From: Utz-Uwe Haus Date: Fri, 23 Oct 2009 21:06:41 +0000 (+0200) Subject: emergency commit X-Git-Url: https://repo.or.cz/w/cl-cudd.git/commitdiff_plain/8da727899e73ebe082787f305efb2bbea8c365d1 emergency commit --- 8da727899e73ebe082787f305efb2bbea8c365d1 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..07f0bf3 --- /dev/null +++ b/.gitignore @@ -0,0 +1,8 @@ +*~ +*.o +*.a +*.so +*.sw[pqrs] +*.fasl +# autogenerated: +cuddapi.lisp diff --git a/asdf-component-shared-unix-library.asd b/asdf-component-shared-unix-library.asd new file mode 100644 index 0000000..5214a21 --- /dev/null +++ b/asdf-component-shared-unix-library.asd @@ -0,0 +1,47 @@ +;;; ASDF Definition. -*- lisp -*- + +(defpackage :asdf-component-shared-unix-library-system + (:use :cl :asdf) + (:export #:shared-unix-library)) + +(in-package :asdf-component-shared-unix-library-system) + +(defclass shared-unix-library (source-file) + ()) + +(defmethod source-file-type ((component shared-unix-library) system) + "so") + +(defmethod input-files (operation (component shared-unix-library)) + nil) + +(defmethod output-files ((operation compile-op) (component shared-unix-library)) + nil) + +(defmethod perform ((operation compile-op) (component shared-unix-library)) + nil) +(defmethod operation-done-p ((o compile-op) (c shared-unix-library)) + t) +(defmethod operation-done-p ((o load-op) (c shared-unix-library)) + nil) + +(defmethod perform ((operation load-op) (component shared-unix-library)) + (flet ((load-lib (lib) + #+cffi + (cffi:load-foreign-library lib) + #+(and (not cffi) sbcl) + (sb-alien:load-shared-object lib) + #+(and (not cffi) allegro) + (load lib :foreign t) + #-(or sbcl allegro cffi) + (error "No foreign library support"))) + (handler-case (load-lib (component-pathname component)) + (error (e) (declare (ignore e)) + nil)))) + +(pushnew :asdf-component-shared-unix-library *features*) + +(asdf:defsystem :asdf-component-shared-unix-library + :name "ASDF component :shared-unix-library" + :components ()) + diff --git a/cudd-cffi.i b/cudd-cffi.i new file mode 100644 index 0000000..c20d27f --- /dev/null +++ b/cudd-cffi.i @@ -0,0 +1,496 @@ +/* swig interface wrapper file for cffi binding generation -*- lisp -*- */ +/* swig -cffi interface for CUDD */ +/* (c) 2009 Utz-Uwe Haus */ + +%module "cuddapi" + +%feature("intern_function","1"); // use swig-lispify +%feature("export"); // export wrapped things + +%insert("lisphead")%{ +;;; Auto-generated -*- lisp -*- file +;;; generated from $Id:$ +(eval-when (:compile-toplevel :load-toplevel) + (declaim (optimize (speed 3) (debug 0) (safety 1)))) + +(cl:defpackage :swig-macros + (:use :cl :cffi) + (:documentation "Package containing utility functions for SWIG cffi interface generation") + (:export #:swig-lispify #:defanonenum)) + +(cl:in-package :swig-macros) + +(cl:defun swig-lispify (name flag cl:&optional (package (find-package :cuddapi))) + (cl:labels ((helper (lst last rest cl:&aux (c (cl:car lst))) + (cl:cond + ((cl:null lst) + rest) + ((cl:upper-case-p c) + (helper (cl:cdr lst) 'upper + (cl:case last + ((lower digit) (cl:list* c #\- rest)) + (cl:t (cl:cons c rest))))) + ((cl:lower-case-p c) + (helper (cl:cdr lst) 'lower (cl:cons (cl:char-upcase c) rest))) + ((cl:digit-char-p c) + (helper (cl:cdr lst) 'digit + (cl:case last + ((upper lower) (cl:list* c #\- rest)) + (cl:t (cl:cons c rest))))) + ((cl:char-equal c #\_) + (helper (cl:cdr lst) '_ (cl:cons #\- rest))) + ((cl:char-equal c #\-) + (helper (cl:cdr lst) '- (cl:cons #\- rest))) + (cl:t + (cl:error "Invalid character: ~A" c))))) + (cl:let ((fix (cl:case flag + ((constant enumvalue) "+") + (variable "*") + (cl:t "")))) + (cl:intern + (cl:concatenate + 'cl:string + fix + (cl:nreverse (helper (cl:concatenate 'cl:list name) cl:nil cl:nil)) + fix) + package)))) + + +%} + +%{ + +/* includes that SWIG needs to see to parse the cudd.h file go here */ + +%} + +%insert ("swiglisp") %{ + +(cl:defpackage #:cuddapi + (:use :cl :cffi :swig-macros) + (:export #:cudd-manager #:cudd-node) + ;; other exports done by swig + ) +(cl:in-package :cuddapi) +%} +%insert ("swiglisp") %{ +;; foreign type definitions to hide pointer values +(defclass wrapped-pointer () + ((ptrval :reader get-ptrval :initarg :ptrval) + (ctype :reader get-ctype :initarg :ctype)) + (:documentation "A wrapped pointer")) + +(defmethod print-object ((p wrapped-pointer) stream) + (print-unreadable-object (p stream :type nil :identity nil) + (format stream "wrapper around `~A' @0x~16R" (get-ctype p) (get-ptrval p)))) + +(define-condition foreign-null-pointer-condition (error) + ((type :initarg :type + :reader foreign-null-pointer-condition-type)) + (:report (lambda (condition stream) + (format stream "The foreign pointer of type ~A was NULL" + (foreign-null-pointer-condition-type condition))))) + +%} + +%define TYPEMAP_WRAPPED_POINTER(PTRTYPE,LISPCLASS) + +%insert ("swiglisp") %{ +(define-foreign-type LISPCLASS () + () + (:actual-type :pointer) + (:documentation "cffi wrapper type around PTRTYPE.")) + +(define-parse-method LISPCLASS () + (make-instance 'LISPCLASS)) + +(defmethod translate-from-foreign (value (type LISPCLASS)) + "Wrap PTRTYPE, signaling a null-pointer-exception if value is NULL." + (if (cffi:null-pointer-p value) + (error 'foreign-null-pointer-condition :type type) + (make-instance 'wrapped-pointer :ptrval value :ctype "PTRTYPE"))) + +(defmethod translate-to-foreign ((g wrapped-pointer) (type LISPCLASS)) + "Unwrap PTRTYPE" + (get-ptrval g)) + +%} +%typemap (cin) PTRTYPE "LISPCLASS" +%typemap (cout) PTRTYPE "LISPCLASS" +%enddef + +TYPEMAP_WRAPPED_POINTER(DdManager *, cudd-manager) +TYPEMAP_WRAPPED_POINTER(DdNode *, cudd-node) + +%typemap (cin) DdManager * "cudd-manager" +%typemap (cout) DdManager * "cudd-manager" +%typemap (cin) DdNode * "cudd-node" +%typemap (cout) DdNode * "cudd-node" + +/* Now parse and wrap the API header */ +%insert ("swiglisp") %{ +(eval-when (:compile-toplevel :load-toplevel) + ;; Muffle compiler-notes globally + #+sbcl (declaim (sb-ext:muffle-conditions sb-ext:defconstant-uneql)) + +%} + +%include "cudd/cudd.h" +%insert ("swiglisp") %{ +) ;; end of eval-when to avoid top-level export +%} + +%insert ("swiglisp") %{ +;; (defmethod translate-from-foreign :around (manager (type cudd-manager)) +;; (let ((cudd-manager (call-next-method))) +;; (when manager +;; (trivial-garbage:finalize cudd-manager #'(lambda () +;; ;; (break "finalize manager #x~x~%" manager) +;; ;; (format T "kill mgmr ~A~%" manager) (force-output) + + + +;; (format T "~D nodes unfreed in manager ~A" (cuddapi:cudd-check-zero-ref manager) manager) +;; ;; (cuddapi:cudd-quit manager) +;; ;; (format T "killed mgmr ~A~%" manager) (force-output) +;; ))) + +;; cudd-manager)) +%} +%insert ("swiglisp") %{ +;; (defmethod translate-from-foreign :around (node (type cudd-node)) +;; (let ((cudd-node (call-next-method))) +;; (when node +;; (trivial-garbage:finalize cudd-node #'(lambda () +;; ;; (format T "finalize node #x~x~%" node) +;; ;; (format T "kill node ~A" node) (force-output) + +;; ;; (format T "~&killed ~A~%" node) +;; ;; (format T "killed node ~A~%" node) (force-output) +;; ))) +;; cudd-node)) +%} + + + + +%insert ("swiglisp") %{ +;;; Higher-level interface similar to de.uuhaus.bdd +(defpackage #:cudd + (:use #:cuddapi #:cl) + (:export #:bdd-environment) + (:export #:with-bdd-environment #:make-bdd-environment) + ; (:export #:make-bdd) + (:export #:bdd-true #:bdd-false) + (:export #:bdd-new-variable) + (:export #:bdd-and #:bdd-or #:bdd-not #:bdd-xor #:bdd-nand #:bdd-nor + #:bdd-and-not #:bdd-or-not #:bdd-implies + #:bdd-iff #:bdd-restrict) + (:export #:bdd-exists #:bdd-forall) + (:export #:bdd-tautologyp #:bdd-satisfiablep) + (:export #:bdd-var-min #:bdd-var-max) + (:export #:bdd-var-fixed0 #:bdd-var-fixed0) + (:export #:deserialize-bdd)) + +(cl:in-package :cudd) + + +;; for garbage collection purposes we wrap a reference to the manager with each +;; variable object +(defvar *bdd-env* nil + "A special variable holding the current BDD Environment.") + +(deftype wrapped-bdd () + `(simple-vector 2)) + +(defmacro wrap-bdd (bdd env) + "Build a lisp object object around the cudd-node v." + `(the wrapped-bdd + (make-array 2 :adjustable NIL :fill-pointer NIL + :initial-contents + (list ,bdd ,env))) + ) + +(defmacro unwrap-bdd (bdd) + "Extract the cudd-node object from bdd." + `(svref (the wrapped-bdd ,bdd) 0) + ) + + +(defun make-cudd-manager (&key + (initial-num-vars 0) + (initial-num-slots 256) ;; #.(cuddapi:CUDD-UNIQUE-SLOTS) + (cache-size 262144) ;; #.(cuddapi:CUDD-CACHE-SLOTS) + (max-memory 0)) + (cuddapi:cudd-init initial-num-vars + 0 ;; num-zvars + initial-num-slots + cache-size + max-memory)) + +(defstruct (bdd-environment (:constructor construct-bdd-environment)) + "A wrapper object describing a CUDD-based BDD environment." + (manager ) + (name "" :type string) + ;; caching of the T and F objects of this manager to save FF overhead + (true) + (false) + ;; mapping VARs to foreign IDs + (var->id (make-hash-table :test #'eq) :type hash-table) + (nextvar 0 :type (integer 0 #.(expt 2 (* 8 (- (cffi:foreign-type-size :int) 1)))))) + +(defmethod print-object ((e bdd-environment) stream) + (print-unreadable-object (e stream :type T) + (format stream "~A (manager @#x~X, ~D vars)" + (bdd-environment-name e) + (cuddapi::get-ptrval (bdd-environment-manager e)) + (bdd-environment-nextvar e)))) + +(defun make-bdd-environment (&key + (manager (make-cudd-manager)) + (name (format nil "BDD Environment ~A" (gensym "BDDE")))) + (let ((res (construct-bdd-environment :manager manager :name name))) + (setf (bdd-environment-true res) + (wrap-bdd (cuddapi:cudd-read-one manager) res)) + (setf (bdd-environment-false res) + (wrap-bdd (cuddapi:cudd-read-logic-zero manager) res)) + ;; these need no finalization: + (trivial-garbage:cancel-finalization (unwrap-bdd (bdd-environment-false res))) + (trivial-garbage:cancel-finalization (unwrap-bdd (bdd-environment-true res))) + + + (let ((vartab (bdd-environment-var->id res))) + (trivial-garbage:finalize res + #'(lambda () + (format T "~&killing ~D vars in ~A~%" + (hash-table-size vartab) + manager) + (maphash #'(lambda (key val) + (declare (ignore val)) + (cuddapi:cudd-recursive-deref + (unwrap-bdd key))) + vartab)))) + res)) + +(eval-when (:load-toplevel) + (setf *bdd-env* (or *bdd-env* + (make-bdd-environment :name "The global BDD Environment.")))) + +(defmacro with-bdd-environment (env &body body) + "Execute BODY within the bdd environment ENV." + `(let ((*bdd-env* ,env)) + ,@body)) + +;;; utility functions for the environment +(defun var->id (var &optional (env *bdd-env*)) + "Return the ID for VAR in ENV (which defaults to *bdd-env*)." + (gethash var (bdd-environment-var->id env))) + +(defsetf var->id (var &optional (env *bdd-env*)) (id) + `(setf (gethash ,var (bdd-environment-var->id ,env)) ,id)) + +(defun id->var (id &optional (env *bdd-env*)) + "Return the VAR for ID in ENV (which defaults to *bdd-env*)." + (wrap-bdd (cuddapi:cudd-bdd-ith-var (bdd-environment-manager env) id) env)) + + +(defun bdd-true () + (bdd-environment-true *bdd-env*)) + +(defun bdd-false () + (bdd-environment-false *bdd-env*)) + +(defun bdd-new-variable () + (handler-case + (let ((v (wrap-bdd + (cuddapi:cudd-bdd-new-var (bdd-environment-manager *bdd-env*)) + *bdd-env*)) + (id (bdd-environment-nextvar *bdd-env*))) + (progn + (incf (bdd-environment-nextvar *bdd-env*)) + (setf (var->id v *bdd-env*) id) + v)) + (cuddapi::foreign-null-pointer-condition (c) + (declare (ignore c)) + ;; FIXME: maybe try a garbage collection here + (error "CUDD failed to allocate a variable ~D:~%BDD environment ~A full." + (bdd-environment-nextvar *bdd-env*) + *bdd-env*)))) + +(defun bdd-restrict (var val bdd) + (wrap-bdd + (cuddapi:cudd-bdd-restrict (bdd-environment-manager *bdd-env*) + (unwrap-bdd bdd) + (unwrap-bdd (if val var (bdd-not var)))) + *bdd-env*)) + +(defun bdd-and (x y) + (wrap-bdd + (cuddapi:cudd-bdd-and (bdd-environment-manager *bdd-env*) + (unwrap-bdd x) (unwrap-bdd y)) + *bdd-env*)) + +(defun bdd-or (x y) + (wrap-bdd + (cuddapi:cudd-bdd-or (bdd-environment-manager *bdd-env*) + (unwrap-bdd x) (unwrap-bdd y)) + *bdd-env*)) + +(defun bdd-not (x) + ;; FIXME: cudd-not is a macro and hence not swig'ed, but would probably + ;; perform be better + (wrap-bdd + (cuddapi:cudd-bdd-nand (bdd-environment-manager *bdd-env*) + (unwrap-bdd x) + (unwrap-bdd x)) + *bdd-env*)) + +(defun bdd-xor (x y) + (wrap-bdd + (cuddapi:cudd-bdd-xor (bdd-environment-manager *bdd-env*) + (unwrap-bdd x) + (unwrap-bdd y)) + *bdd-env*)) + +(defun bdd-nand (x y) + (wrap-bdd + (cuddapi:cudd-bdd-nand (bdd-environment-manager *bdd-env*) + (unwrap-bdd x) + (unwrap-bdd y)) + *bdd-env*)) + +(defun bdd-nor (x y) + (wrap-bdd + (cuddapi:cudd-bdd-nor (bdd-environment-manager *bdd-env*) + (unwrap-bdd x) + (unwrap-bdd y)) + *bdd-env*)) + +(defun bdd-and-not (bdd1 bdd2) + (bdd-and bdd1 (bdd-not bdd2))) + +(defun bdd-or-not (bdd1 bdd2) + (bdd-or bdd1 (bdd-not bdd2))) + +(defun bdd-implies (bdd1 bdd2) + (bdd-or-not bdd1 bdd2)) + +(defun bdd-iff (bdd1 bdd2) + (bdd-and (bdd-implies bdd1 bdd2) + (bdd-implies bdd2 bdd1))) + +(defun bdd-equal (bdd1 bdd2) + "Check whether BDD1 and BDD2 are equal." + (let ((b1 (unwrap-bdd bdd1)) + (b2 (unwrap-bdd bdd2))) + (and (= 1 (cuddapi:cudd-bdd-leq (bdd-environment-manager *bdd-env*) b1 b2)) + (= 1 (cuddapi:cudd-bdd-leq (bdd-environment-manager *bdd-env*) b2 b1))))) + +(defun bdd-tautologyp (bdd &optional (fixings '())) + "Check whether BDD is tautologic, possibly under a given fixing in FIXINGS, a list of pairs (bddvar . value), value being T or NIL. " + (if fixings + (bdd-tautologyp (bdd-restrict (caar fixings) (cadr fixings) bdd) + (cdr fixings)) + (bdd-equal bdd (bdd-true)))) + +(defun bdd-satisfiablep (bdd &optional (fixings '())) + "Check whether BDD is satisfiable, possibly under a given fixing in FIXINGS, a list of pairs (bddvar . value), value being T or NIL. " + (if fixings + (bdd-satisfiablep (bdd-restrict (caar fixings) (cadr fixings) bdd) + (cdr fixings)) + (not (bdd-equal bdd (bdd-false))))) + +(defun bdd-var-fixed0 (bdd var) + (ecase (cuddapi:cudd-bdd-is-var-essential (bdd-environment-manager *bdd-env*) + bdd + (var->id var *bdd-env*) + 0) + (1 T) + (0 NIL))) + +(defun bdd-var-fixed1 (bdd var) + (ecase (cuddapi:cudd-bdd-is-var-essential (bdd-environment-manager *bdd-env*) + bdd + (var->id var) + 1) + (1 T) + (0 NIL))) + +(defgeneric deserialize-bdd (source) + (:documentation "Parse a textual representation of a BDD from SOURCE within the current BDD environment.")) + +(defmethod deserialize-bdd ((s string)) + (with-input-from-string (f s) + (deserialize-bdd f))) + +(defmethod deserialize-bdd ((s pathname)) + (with-open-file (f s :direction :input) + (deserialize-bdd f))) + +(defmethod deserialize-bdd ((l list)) + (with-input-from-string (f (format nil "~W" l)) + (deserialize-bdd f))) + +(defmethod deserialize-bdd ((s stream)) + "Read a textual external representation of a bdd from STREAM. +New variables are allocated in the current bdd environment. +Returns two values: the bdd structure and an alist mapping variable numbers to the +variable names specified in the bdd file." + (labels ((parse-bddfile (s) + (let* ((bddblock (read s)) + (data (member "BDD" bddblock :test #'string-equal) ) + (tree nil) + (nodenames nil)) + (unless data + (error "Could not find BDD block in ~A" data)) + (setf data (cdr data)) + (setf tree (assoc "DAG" data :test #'string-equal)) + (unless tree + (error "Could not find BDD DAG in ~A" data)) + (setf tree (cadr tree)) + (setf nodenames (assoc "VARNAMES" data :test #'string-equal)) + (unless nodenames + (error "Could not find node name mapping in ~A" data)) + (setf nodenames (cadr nodenames)) + (values tree nodenames))) + (max-varnum (tree) + ;; we depend on having consecutive variable numbers in the bdd file + ;; starting above 0 + ;; Deducing maxvarnum from tree instead of varnames is safer because some + ;; variable may be missing a name. In that case we fail softly: the tree will be + ;; fine, but the mapping returned to the caller will be defective in the same way + ;; that the user messed it up when calling serialize-bdd with an incomplete name map. + (if (consp tree) + (max (second tree) + (max-varnum (third tree)) + (max-varnum (fourth tree))) + 0))) + (multiple-value-bind (tree nodenames) + (parse-bddfile s) + (let* ((maxvar (max-varnum tree)) + (mapping (make-hash-table :size maxvar :test #'eql))) + ;; fetch new variables + (loop :for i :from 2 :upto maxvar + :do (setf (gethash i mapping) (bdd-new-variable))) + (labels ((walk (bddtext) + (cond + ((eq bddtext NIL) + (bdd-false)) + ((eq bddtext T) + (bdd-true)) + (T + (let ((thisvar (gethash (second bddtext) mapping)) + (t-child (walk (third bddtext))) + (nil-child (walk (fourth bddtext)))) + (bdd-or (bdd-and thisvar t-child) + (bdd-and (bdd-not thisvar) nil-child))))))) + (values + (walk tree) + (loop :for pair :in nodenames + :as oldnum := (car pair) + :do (setf (car pair) + (gethash oldnum mapping)) + :finally (return nodenames)))))))) + + +%} \ No newline at end of file diff --git a/cudd.asd b/cudd.asd new file mode 100644 index 0000000..da12ad1 --- /dev/null +++ b/cudd.asd @@ -0,0 +1,60 @@ +;;; -*- Mode: Lisp; Syntax: ANSI-Common-Lisp; Base: 10; -*- +;;; +;;; cudd.asd --- cudd wrapper + +;; Copyright (C) 2009 Utz-Uwe Haus +;; +;; $Id:$ +;; +;; This code is free software; you can redistribute it and/or modify +;; it under the terms of the version 3 of the GNU General +;; Public License as published by the Free Software Foundation, as +;; clarified by the prequel found in LICENSE.Lisp-GPL-Preface. +;; +;; This code 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. +;; +;; Version 3 of the GNU General Public License is in the file +;; LICENSE.GPL that was distributed with this file. If it is not +;; present, you can access it from +;; http://www.gnu.org/copyleft/gpl.txt (until superseded by a +;; newer version) or write to the Free Software Foundation, Inc., 59 +;; Temple Place, Suite 330, Boston, MA 02111-1307 USA +;; +;; Commentary: + +;; + +;;; Code: + +#-asdf-component-shared-unix-library +(asdf:operate 'asdf:load-op :asdf-component-shared-unix-library) + +(defpackage #:cudd-system + (:use #:cl #:asdf #:asdf-component-shared-unix-library-system)) +(in-package #:cudd-system) + +(defsystem #:cudd + :description "?" + :version "0" + :author "Utz-Uwe Haus " + :license "ask me" + :depends-on (:cffi :trivial-garbage) + :components ((:module "foreignlib" + :if-component-dep-fails :try-next + :pathname "distr/" + :components + (;; try installed copy + (:shared-unix-library "installed_libcudd" + :pathname "/usr/local/lib/libcudd.so") + ;; try local copy + (:shared-unix-library "temp_libcudd" + :pathname "./cudd/libcudd.so"))) + + ;; (:file "package") + (:file "cuddapi" :depends-on ("foreignlib")) + (:file "cuddsat" :depends-on ("cuddapi")) + )) + diff --git a/cuddsat.lisp b/cuddsat.lisp new file mode 100644 index 0000000..d979b91 --- /dev/null +++ b/cuddsat.lisp @@ -0,0 +1,254 @@ +;;; -*- Mode: Lisp; Syntax: ANSI-Common-Lisp; Base: 10; -*- +;;; +;;; cuddsat.lisp --- SAT solver based on CUDD BDDs + +;; Copyright (C) 2009 Utz-Uwe Haus +;; $Id:$ +;; This code is free software; you can redistribute it and/or modify +;; it under the terms of the version 3 of the GNU General +;; Public License as published by the Free Software Foundation, as +;; clarified by the prequel found in LICENSE.Lisp-GPL-Preface. +;; +;; This code 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. +;; +;; Version 3 of the GNU General Public License is in the file +;; LICENSE.GPL that was distributed with this file. If it is not +;; present, you can access it from +;; http://www.gnu.org/copyleft/gpl.txt (until superseded by a +;; newer version) or write to the Free Software Foundation, Inc., 59 +;; Temple Place, Suite 330, Boston, MA 02111-1307 USA +;; +;; Commentary: + +;; + +;;; Code: + +(eval-when (:compile-toplevel :load-toplevel) + (declaim (optimize (speed 3) (debug 1) (safety 1)))) + + +(in-package #:CUDD) + + +(defstruct sat-env + (name) + (manager) + (cnf) + (true) + (false) + (vars #() :type simple-vector)) + +(defmacro reference (f) + (let ((x (gensym))) + `(let ((,x ,f)) + (cuddapi:cudd-ref ,x) + ,x))) + +(defmacro dereference (f manager) + (let ((x (gensym))) + `(let ((,x ,f)) + (cuddapi:cudd-recursive-deref ,manager ,x) + ,x))) + +(defun make-clause-tree (env c) + (loop :with f := (reference (sat-env-false env)) + :with manager := (sat-env-manager env) + :with vars := (sat-env-vars env) + :for x :of-type fixnum :in c + :as var := (svref vars (the cudd-int (abs x))) + :as phase := (signum x) + :do (let* ((var (if (= 1 phase) + var + (cuddapi:cudd-bdd-nand manager var var))) + (tmp (cuddapi:cudd-bdd-or manager var f))) + (reference tmp) + (dereference f manager) + (setf f tmp)) + :finally (return f))) + +(defun sat-env-add-clause (env c) + (let* ((subtree (make-clause-tree env c)) + (newcnf (cuddapi:cudd-bdd-and (sat-env-manager env) + (sat-env-cnf env) subtree))) + ;; reference new tree + (cuddapi:cudd-ref newcnf) + ;; deref consumed old tree + (cuddapi:cudd-recursive-deref (sat-env-manager env) (sat-env-cnf env)) + (cuddapi:cudd-recursive-deref (sat-env-manager env) subtree) + (setf (sat-env-cnf env) newcnf)) + (values)) + +(deftype cudd-int () + `(integer ,#.(1- (- (expt 2 (* 8 (- (cffi:foreign-type-size :int) 1))))) + ,#.(expt 2 (* 8 (- (cffi:foreign-type-size :int) 1))))) + +(defun destroy-sat-env (env) + (with-slots (name manager cnf vars) + env + (declare (type simple-vector vars)) + (format *debug-io* "~&Cleaning up sat-env ~A, tree has ~D nodes~%" name + (cuddapi:cudd-dag-size cnf)) + ;; goes to stderr, unfortunately: + ;; (cuddapi:cudd-print-debug manager cnf (length (sat-env-vars env)) 4) + ;; (cuddapi:cudd-print-minterm manager cnf) + + ;; (format *debug-io* " ~D refs initially~%" + ;; (cuddapi:cudd-check-zero-ref manager)) + (cuddapi:cudd-recursive-deref manager cnf) + (when (= 0 (the cudd-int (cuddapi:cudd-check-zero-ref manager))) + (break "env ~A empty too early: ~A" name env)) + + ;; (format *debug-io* " destroyed tree, ~D left~%" + ;; (cuddapi:cudd-check-zero-ref manager)) + (when (/= (length vars) (the cudd-int (cuddapi:cudd-check-zero-ref manager))) + (break "env ~A occupation does not match varcount: ~D vs ~D; ~A" + name + (length vars) + (cuddapi:cudd-check-zero-ref manager) + env)) + + (loop :for x :across vars + :do (cuddapi:cudd-deref x)) +;; (format *debug-io* " ~D vars deleted, ~D left~%" +;; (length vars) (cuddapi:cudd-check-zero-ref manager)) + (unless (= 0 (the cudd-int (cuddapi:cudd-check-zero-ref manager))) + (break "env ~A unclean: ~A" name env)) + (unless (= 0 (the cudd-int (cuddapi:cudd-debug-check manager))) + (break "debug check failed ~D~%" (cuddapi:cudd-debug-check manager))) + + (cuddapi:cudd-quit manager) +;; (format *debug-io* " done.~%") + + )) + +(defun make-cnf (numatoms clauses) + (let* ((name (gensym "cnf-sat-env")) + (manager (make-cudd-manager :initial-num-vars (1+ numatoms))) + (truevar (cuddapi:cudd-read-one manager)) + (falsevar (cuddapi:cudd-read-logic-zero manager)) + (vars (coerce (the list + (loop :for i :of-type fixnum :from 0 :upto numatoms + :collecting (reference (cuddapi:cudd-bdd-new-var manager)))) + 'simple-vector)) + (env (make-sat-env :name name + :manager manager + :cnf truevar + :true truevar + :false falsevar + :vars vars))) + (cuddapi:cudd-ref truevar) ;; it is used as inital cnf + (cuddapi:cudd-enable-reordering-reporting manager) + (cuddapi:cudd-autodyn-enable manager :cudd-reorder-symm-sift) + ; (cuddapi:cudd-autodyn-enable manager :cudd-reorder-symm-sift-conv) + ; (cuddapi:cudd-autodyn-enable manager :cudd-reorder-symm-sift) + (loop :for c :in clauses + :do (sat-env-add-clause env c)) + env)) + + + +(defmacro with-sat-bdd ((name numatoms clauses) &body body) + `(let ((,name (make-cnf ,numatoms ,clauses))) + (declare (dynamic-extent ,name)) + (unwind-protect + (progn ,@body) + (destroy-sat-env ,name)))) + +(defun satisfiablep (sat-env f) + (= 0 + (the cudd-int + (cuddapi:cudd-bdd-leq (sat-env-manager sat-env) + f (sat-env-false sat-env))))) + +(defun get-essential-vars (sat-env) + "Return a list of two lists: the indices of vars fixed to FALSE and those +fixed to TRUE in the current cnf of sat-env" + (let ((t-ess '()) + (f-ess '())) + (loop :with bdd := (reference (sat-env-cnf sat-env)) + :with manager := (sat-env-manager sat-env) + :for i :of-type fixnum :from 1 :below (length (sat-env-vars sat-env)) + :as var := (svref (sat-env-vars sat-env) i) + :as negvar := (cuddapi:cudd-bdd-nand manager var var) + :do (let ((tmp1 (reference + (cuddapi:cudd-bdd-and manager var bdd))) + (tmp2 (reference + (cuddapi:cudd-bdd-and manager negvar bdd)))) + (let ((sat-with-T (satisfiablep sat-env tmp1)) + (sat-with-F (satisfiablep sat-env tmp2))) + (cond + ((or (and sat-with-T sat-with-F) + (and (not sat-with-T) (not sat-with-F))) + (dereference tmp1 manager) + (dereference tmp2 manager)) + ((and sat-with-T (not sat-with-F)) + (push i t-ess) + (dereference bdd manager) + (dereference tmp2 manager) + (setf bdd tmp1)) + ((and (not sat-with-T) sat-with-F) + (push i f-ess) + (dereference bdd manager) + (dereference tmp1 manager) + (setf bdd tmp2))))) + :finally (dereference bdd manager)) + (list f-ess t-ess))) + + + + +(defun satcheck (numatoms clauses) + "Check the CNF of CLAUSES or satisfiability. +NUMATOMS is the number of variables occuring in clauses, they are numbered from 1 through NUMATOMS. +CLAUSES is a list of lists, where the sublists are (sparse) disjunctions of atom-indices. Positive/negative sign of index determine phase of literal in the clause. +Return 3 values: T or NIL to answer SAT(clauses), and two lists of fixed-to-1 and fixed-to-0 atoms." + (with-sat-bdd (bdd numatoms clauses) + (apply #'values + (satisfiablep bdd (sat-env-cnf bdd)) + (get-essential-vars bdd)) + + ;; (format T "computing...~%") + )) + +(defmacro with-index-hash ((mapping &key (test 'cl:eq)) objects &body body) + "Execute BODY while binding MAPPING to a hash-table (with predicate +TEST, defaults to #'cl:eq) mapping the OBJECTS to small integers." + `(let ((,mapping (loop :with ht := (make-hash-table :test ,test) + :for x :in ,objects + :for num :from 1 + :do (setf (gethash x ht) num) + :finally (return ht)))) + ,@body)) + +(defun clauses-for-if (lhs rhs) + "Return clauses for LHS -> RHS, both being disjunctions." + (mapcar #'(lambda (lhsatom) + (cons (- lhsatom) rhs)) + lhs)) + +(defun clauses-for-iff (lhs rhs) + "Return clauses for LHS -> RHS, both being disjunctions." + (append (clauses-for-if lhs rhs) + (clauses-for-if rhs lhs))) + +(defun testsat (numvars numclauses &key + (maxlhs (/ numvars 2)) + (maxrhs (/ numvars 2))) + (declare (type fixnum numvars numclauses)) + (setf maxlhs (ceiling maxlhs)) + (setf maxrhs (ceiling maxrhs)) + (let ((clauses '())) + (declare (type fixnum maxlhs maxrhs)) + (loop :repeat numclauses + :as lhs := (loop :repeat (random maxlhs) + :collecting (1+ (random numvars))) + :as rhs := (loop :repeat (random maxrhs) + :collecting (1+ (random numvars))) + :do (dolist (c (clauses-for-iff lhs rhs)) + (push c clauses))) + ; (format T "~D ~A~%" numvars clauses) + (satcheck numvars clauses))) \ No newline at end of file diff --git a/distr/LICENSE b/distr/LICENSE new file mode 100644 index 0000000..99c7fba --- /dev/null +++ b/distr/LICENSE @@ -0,0 +1,31 @@ +Copyright (c) 1995-2004, Regents of the University of Colorado + +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + +Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. + +Neither the name of the University of Colorado nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. diff --git a/distr/Makefile b/distr/Makefile new file mode 100644 index 0000000..d931d8c --- /dev/null +++ b/distr/Makefile @@ -0,0 +1,322 @@ +# $Id$ +# +# Makefile for the CUDD distribution kit +#--------------------------------------------------------------------------- + +# Beginning of the configuration section. These symbol definitions can +# be overridden from the command line. + +# C++ compiler +CPP = g++ +#CPP = icpc +#CPP = ecpc +#CPP = CC +#CPP = /usr/local/opt/SUNWspro/bin/CC +#CPP = cxx + +# Specific options for compilation of C++ files. +CPPFLAGS = +# Stricter standard conformance for g++. +#CPPFLAGS = -std=c++98 +# For Sun CC version 5, this invokes compatibility mode. +#CPPFLAGS = -compat +# On some versions of UP-UX, it is necessary to pass the option +a1 +# to CC for the C++ test program to compile successfully. +#CPPFLAGS = +a1 + +# C compiler used for all targets except optimize_dec, which always uses cc. +#CC = cc +#CC = /usr/local/opt/SUNWspro/bin/cc +CC = gcc +#CC = icc +#CC = ecc +#CC = /usr/ucb/cc +#CC = c89 +#CC = $(CPP) + +# On some machines ranlib is either non-existent or redundant. +# Use the following definition if your machine has ranlib and you think +# it is needed. +RANLIB = ranlib +# Use the following definition if your machine either does not have +# ranlib (e.g., SUN running solaris) or can do without it (e.g., DEC Alpha). +#RANLIB = : + +# Use ICFLAGS to specify machine-independent compilation flags. +# These three are typical settings for cc. +#ICFLAGS = -g +#ICFLAGS = -O +#ICFLAGS = +# These four are typical settings for optimized code with gcc. The +# last two also work with icc/ecc. +#ICFLAGS = -g -O6 -Wall +ICFLAGS = -g -O6 +#ICFLAGS = -g -O3 -Wall +#ICFLAGS = -g -O3 + +# Use XCFLAGS to specify machine-dependent compilation flags. +# For some platforms no special flags are needed. +#XCFLAGS = -DHAVE_IEEE_754 -DBSD +# +#========================== +# Linux +# +# Gcc 3.2.2 or higher on i686. +XCFLAGS = -mtune=pentium4 -malign-double -DHAVE_IEEE_754 -DBSD +# Gcc 2.8.1 on i686. +#XCFLAGS = -mcpu=pentiumpro -malign-double -DHAVE_IEEE_754 -DBSD +# Gcc 4.2.4 or higher on x86_64 (64-bit compilation) +#XCFLAGS = -mtune=native -DHAVE_IEEE_754 -DBSD -DSIZEOF_VOID_P=8 -DSIZEOF_LONG=8 +# Gcc 4.2.4 or higher on x86_64 (32-bit compilation) +#XCFLAGS = -m32 -mtune=native -malign-double -DHAVE_IEEE_754 -DBSD +# Icc on i686 (older versions may not support -xHost). +#XCFLAGS = -ansi -xHost -align -ip -DHAVE_IEEE_754 -DBSD +# Icc on x86_64 (64-bit compilation). +#XCFLAGS = -ansi -xHost -align -ip -DHAVE_IEEE_754 -DBSD -DSIZEOF_VOID_P=8 -DSIZEOF_LONG=8 +# Gcc on ia64. +#XCFLAGS = -DHAVE_IEEE_754 -DBSD -DSIZEOF_VOID_P=8 -DSIZEOF_LONG=8 +# Icc/ecc on ia64. +#XCFLAGS = -ansi -DBSD -DHAVE_IEEE_754 -DSIZEOF_VOID_P=8 -DSIZEOF_LONG=8 +# +#========================== +# Solaris +# +# For Solaris, BSD should not be replaced by UNIX100. +#XCFLAGS = -DHAVE_IEEE_754 -DUNIX100 -DEPD_BIG_ENDIAN +# Gcc 2.8.1 or higher on Ultrasparc. +#XCFLAGS = -mcpu=ultrasparc -DHAVE_IEEE_754 -DUNIX100 -DEPD_BIG_ENDIAN +# For Solaris 2.5 and higher, optimized code with /usr/bin/cc or CC. +#XCFLAGS = -DHAVE_IEEE_754 -DUNIX100 -xO5 -native -dalign -DEPD_BIG_ENDIAN +# On IA platforms, -dalign is not supported and causes warnings. +#XCFLAGS = -DHAVE_IEEE_754 -DUNIX100 -xO5 -native +# Recent Sun compilers won't let you use -native on old Ultras. +#XCFLAGS = -DHAVE_IEEE_754 -DUNIX100 -xO5 -dalign -xlibmil -DEPD_BIG_ENDIAN +# For Solaris 2.4, optimized code with /usr/bin/cc. +#XCFLAGS = -DHAVE_IEEE_754 -DUNIX100 -xO4 -dalign -DEPD_BIG_ENDIAN +# For Solaris 2.5 and higher, optimized code with /usr/ucb/cc. +#XCFLAGS = -DHAVE_IEEE_754 -DBSD -xO5 -native -dalign -DEPD_BIG_ENDIAN +#XCFLAGS = -DHAVE_IEEE_754 -DBSD -xO5 -dalign -xlibmil -DEPD_BIG_ENDIAN +# For Solaris 2.4, optimized code with /usr/ucb/cc. +#XCFLAGS = -DHAVE_IEEE_754 -DBSD -xO4 -dalign -DEPD_BIG_ENDIAN +# +#========================== +# DEC Alphas running Digital Unix +# +# For DEC Alphas either -ieee_with_inexact or -ieee_with_no_inexact is +# needed. If you use only BDDs, -ieee_with_no_inexact is enough. +# In the following, we consider three different compilers: +# - the old native compiler (the one of MIPS ancestry that produces u-code); +# - the new native compiler; +# - gcc +# On the Alphas, gcc (as of release 2.7.2) does not support 32-bit pointers +# and IEEE 754 floating point arithmetic. Therefore, for this architecture +# only, the native compilers provide a substatial advantage. +# With the native compilers, specify -xtaso for 32-bit pointers. +# Do not use -xtaso_short because explicit reference to stdout and stderr +# does not work with this option. (Among other things.) +# Notice that -taso must be included in LDFLAGS for -xtaso to work. +# Given the number of possible choices, only some typical configurations +# are proposed here. +# +# Old native compiler for the Alphas; 64-bit pointers. +#XCFLAGS = -DBSD -DHAVE_IEEE_754 -ieee_with_no_inexact -tune host -DSIZEOF_VOID_P=8 -DSIZEOF_LONG=8 +# Old native compiler for the Alphas; 32-bit pointers. +#XCFLAGS = -DBSD -DHAVE_IEEE_754 -ieee_with_no_inexact -tune host -xtaso -DSIZEOF_LONG=8 +# New native compiler for the Alphas; 64-bit pointers. +#XCFLAGS = -g3 -O4 -std -DBSD -DHAVE_IEEE_754 -ieee_with_no_inexact -tune host -DSIZEOF_VOID_P=8 -DSIZEOF_LONG=8 +# New native compiler for the Alphas; 32-bit pointers. +#XCFLAGS = -g3 -O4 -std -DBSD -DHAVE_IEEE_754 -ieee_with_no_inexact -tune host -xtaso -DSIZEOF_LONG=8 +# gcc for the Alphas: compile without HAVE_IEEE_754. +#XCFLAGS = -DBSD -DSIZEOF_VOID_P=8 -DSIZEOF_LONG=8 +# +#========================== +# +# IBM RS6000 +# +# For the IBM RS6000 -qstrict is necessary when specifying -O3 with cc. +#XCFLAGS = -DBSD -DHAVE_IEEE_754 -DEPD_BIG_ENDIAN -O3 -qstrict +# +#========================== +# +# HP-UX +# +# I haven't figured out how to enable IEEE 754 on the HPs I've tried... +# For HP-UX using gcc. +#XCFLAGS = -DUNIX100 -DEPD_BIG_ENDIAN +# For HP-UX using c89. +#XCFLAGS = +O3 -DUNIX100 -DEPD_BIG_ENDIAN +# +#========================== +# +# Windows 95/98/NT/XP/Vista with Cygwin tools +# +# The value of RLIMIT_DATA_DEFAULT should reflect the amount of +# available memory (expressed in bytes). +# Recent versions of cygwin have getrlimit, but the datasize limit +# cannot be set. +#XCFLAGS = -mtune=pentium4 -malign-double -DHAVE_IEEE_754 -DHAVE_GETRLIMIT=0 -DRLIMIT_DATA_DEFAULT=268435456 + + +# Define the level of self-checking and verbosity of the CUDD package. +#DDDEBUG = -DDD_DEBUG -DDD_VERBOSE -DDD_STATS -DDD_CACHE_PROFILE -DDD_UNIQUE_PROFILE -DDD_COUNT +DDDEBUG = + +# Define the level of self-checking and verbosity of the MTR package. +#MTRDEBUG = -DMTR_DEBUG +MTRDEBUG = + +# Loader options. +LDFLAGS = +# This may produce faster code on the DECstations. +#LDFLAGS = -jmpopt -Olimit 1000 +# This may be necessary under some old versions of Linux. +#LDFLAGS = -static +# This normally makes the program faster on the DEC Alphas. +#LDFLAGS = -non_shared -om +# This is for 32-bit pointers on the DEC Alphas. +#LDFLAGS = -non_shared -om -taso +#LDFLAGS = -non_shared -taso + +# Define PURE as purify to link with purify. +# Define PURE as quantify to link with quantify. +# Remember to compile with -g if you want line-by-line info with quantify. +PURE = +#PURE = purify +#PURE = quantify + +# Define EXE as .exe for MS-DOS and derivatives. Not required by recent +# versions of cygwin. +EXE = +#EXE = .exe + +# End of the configuration section. +#--------------------------------------------------------------------------- + +MFLAG = -DMNEMOSYNE +MNEMLIB = ../mnemosyne/libmnem.a + +DDWDIR = . +IDIR = $(DDWDIR)/include +INCLUDE = -I$(IDIR) + +BDIRS = cudd dddmp mtr st util epd +DIRS = $(BDIRS) nanotrav + +#------------------------------------------------------------------------ + +.PHONY : build +.PHONY : nanotrav +.PHONY : check_leaks +.PHONY : optimize_dec +.PHONY : testcudd +.PHONY : libobj +.PHONY : testobj +.PHONY : testdddmp +.PHONY : testmtr +.PHONY : lint +.PHONY : all +.PHONY : clean +.PHONY : distclean + + +build: + sh ./setup.sh + @for dir in $(DIRS); do \ + (cd $$dir; \ + echo Making $$dir ...; \ + make CC=$(CC) RANLIB=$(RANLIB) MFLAG= MNEMLIB= ICFLAGS="$(ICFLAGS)" XCFLAGS="$(XCFLAGS)" DDDEBUG="$(DDDEBUG)" MTRDEBUG="$(MTRDEBUG)" LDFLAGS="$(LDFLAGS)" PURE="$(PURE)" EXE="$(EXE)" )\ + done + +nanotrav: build + +check_leaks: + sh ./setup.sh + @for dir in mnemosyne $(DIRS); do \ + (cd $$dir; \ + echo Making $$dir ...; \ + make CC=$(CC) RANLIB=$(RANLIB) MFLAG=$(MFLAG) MNEMLIB=$(MNEMLIB) ICFLAGS="$(ICFLAGS)" XCFLAGS="$(XCFLAGS)" DDDEBUG="$(DDDEBUG)" MTRDEBUG="$(MTRDEBUG)" LDFLAGS="$(LDFLAGS)" EXE="$(EXE)" )\ + done + +optimize_dec: + sh ./setup.sh + @for dir in $(DIRS); do \ + (cd $$dir; \ + echo Making $$dir ...; \ + make CC=$(CC) RANLIB=$(RANLIB) XCFLAGS="$(XCFLAGS)" LDFLAGS="$(LDFLAGS)" optimize_dec )\ + done + +lint: + sh ./setup.sh + @for dir in $(DIRS) obj; do \ + (cd $$dir; \ + echo Making lint in $$dir ...; \ + make CC=$(CC) lint )\ + done + +tags: + sh ./setup.sh + @for dir in $(DIRS) obj; do \ + (cd $$dir; \ + echo Making tags in $$dir ...; \ + make CC=$(CC) tags )\ + done + +all: + sh ./setup.sh + @for dir in $(DIRS); do \ + (cd $$dir; \ + echo Making all in $$dir ...; \ + make CC=$(CC) RANLIB=$(RANLIB) MFLAG= MNEMLIB= ICFLAGS="$(ICFLAGS)" XCFLAGS="$(XCFLAGS)" DDDEBUG="$(DDDEBUG)" MTRDEBUG="$(MTRDEBUG)" LDFLAGS="$(LDFLAGS)" PURE="$(PURE)" EXE="$(EXE)" all )\ + done + +testcudd: + sh ./setup.sh + @for dir in util st mtr epd; do \ + (cd $$dir; \ + echo Making $$dir ...; \ + make CC=$(CC) RANLIB=$(RANLIB) MFLAG= MNEMLIB= ICFLAGS="$(ICFLAGS)" XCFLAGS="$(XCFLAGS)" DDDEBUG="$(DDDEBUG)" MTRDEBUG="$(MTRDEBUG)" LDFLAGS="$(LDFLAGS)" PURE="$(PURE)" EXE="$(EXE)" )\ + done + @(cd cudd; \ + echo Making testcudd ...; \ + make CC=$(CC) RANLIB=$(RANLIB) MFLAG= MNEMLIB= ICFLAGS="$(ICFLAGS)" XCFLAGS="$(XCFLAGS)" DDDEBUG="$(DDDEBUG)" MTRDEBUG="$(MTRDEBUG)" LDFLAGS="$(LDFLAGS)" PURE="$(PURE)" EXE="$(EXE)" testcudd$(EXE) ) + +objlib: + sh ./setup.sh + @for dir in $(BDIRS); do \ + (cd $$dir; \ + echo Making $$dir ...; \ + make CC=$(CC) RANLIB=$(RANLIB) MFLAG= MNEMLIB= ICFLAGS="$(ICFLAGS)" XCFLAGS="$(XCFLAGS)" DDDEBUG="$(DDDEBUG)" MTRDEBUG="$(MTRDEBUG)" LDFLAGS="$(LDFLAGS)" PURE="$(PURE)" EXE="$(EXE)" )\ + done + @(cd obj; \ + echo Making obj ...; \ + make CPP=$(CPP) CPPFLAGS=$(CPPFLAGS) RANLIB=$(RANLIB) MFLAG= MNEMLIB= ICFLAGS="$(ICFLAGS)" XCFLAGS="$(XCFLAGS)" DDDEBUG="$(DDDEBUG)" MTRDEBUG="$(MTRDEBUG)" LDFLAGS="$(LDFLAGS)" PURE="$(PURE)" EXE="$(EXE)" ) + +testobj: objlib + @(cd obj; \ + echo Making testobj ...; \ + make CPP=$(CPP) CPPFLAGS=$(CPPFLAGS) RANLIB=$(RANLIB) MFLAG= MNEMLIB= ICFLAGS="$(ICFLAGS)" XCFLAGS="$(XCFLAGS)" DDDEBUG="$(DDDEBUG)" MTRDEBUG="$(MTRDEBUG)" LDFLAGS="$(LDFLAGS)" PURE="$(PURE)" EXE="$(EXE)" testobj$(EXE) ) + +testdddmp: build + @(cd dddmp; \ + echo Making testdddmp ...; \ + make CC=$(CC) RANLIB=$(RANLIB) MFLAG= MNEMLIB= ICFLAGS="$(ICFLAGS)" XCFLAGS="$(XCFLAGS)" DDDEBUG="$(DDDEBUG)" MTRDEBUG="$(MTRDEBUG)" LDFLAGS="$(LDFLAGS)" PURE="$(PURE)" EXE="$(EXE)" testdddmp$(EXE) ) + +testmtr: build + @(cd mtr; \ + echo Making testmtr ...; \ + make CC=$(CC) RANLIB=$(RANLIB) MFLAG= MNEMLIB= ICFLAGS="$(ICFLAGS)" XCFLAGS="$(XCFLAGS)" DDDEBUG="$(DDDEBUG)" MTRDEBUG="$(MTRDEBUG)" LDFLAGS="$(LDFLAGS)" PURE="$(PURE)" EXE="$(EXE)" testmtr$(EXE) ) + +clean: + @for dir in mnemosyne $(DIRS) obj; do \ + (cd $$dir; \ + echo Cleaning $$dir ...; \ + make -s clean ) \ + done + +distclean: + @for dir in mnemosyne $(DIRS) obj; do \ + (cd $$dir; \ + echo Cleaning $$dir ...; \ + make -s EXE="$(EXE)" distclean ) \ + done + sh ./shutdown.sh diff --git a/distr/README b/distr/README new file mode 100644 index 0000000..c53383f --- /dev/null +++ b/distr/README @@ -0,0 +1,181 @@ +$Id$ + +This directory contains a set of packages that allow you to build a toy +application based on the CUDD package. + +The CUDD package is a package written in C for the manipulation of +decision diagrams. It supports binary decision diagrams (BDDs), +algebraic decision diagrams (ADDs), and Zero-Suppressed BDDs (ZDDs). + +The toy application provided in this kit is called nanotrav and is a +simple-minded FSM traversal program. (See the README file and the man +page nanotrav.1 in the nanotrav directory for the details.) It is +included so that you can run a sanity check on your installation. + +INSTALLATION + +Before you build the libraries and programs, you need to check the +Makefile in the top directory. Go through the definitions contained in the +configuration section, and select the desired compiler and compilation +flags. Instructions are provided in the comments of the Makefile. + +You can always specify the options on the command line. For instance, +on some machines you can build a "fast" version of the program by typing: + + make DDDEBUG= MTRDEBUG= ICFLAGS=-O2 + +The Makefile supports several targets: + + make: + Creates a "plain" version of the program. + + make testdddmp: + Builds a test program (testdddmp) for BDD loading from and + storing to disk. See file README.test in the dddmp directory for + how to run the program. + + make testobj: + Builds a test program for the C++ interface. Requires a C++ + compiler. To run the program, run obj/testobj. + + make testcudd: + Builds a test program for CUDD. To run the program, go to the + cudd directory and type "./testcudd -p 2 r7x8.1.mat". The result + can be compared to r7x7.1.out. + + make testmtr: + Builds a test program for the mtr package. To run the program, + go to the mtr directory and type "./testmtr -p 1 test.groups". + + make clean: + Cleans directories, but leaves libraries and programs. + + make distclean: + Cleans thoroughly, returning the directories to their pristine + state. + +The following targets are more or less obsolete and may disappear or +change in the future. + + make check_leaks: + Creates a version of the program with the mnemosyne library + linked to it. It also builds the mnemalyse program, which + helps in finding memory leaks. This target does not work on the + IBM RS6000. The makefile also supports purify. To use purify, + set the PURE variable in the Makefile, and use the standard + target. + + make optimize_dec: + Builds a version of the program using the u-code compiler + available on DEC machines (DECstations and Alphas). The newer + native compiler on the Alphas does not use u-code, though. + Therefore the standard target should be used with it. + + make lint: + Runs lint on all subdirectories except mnemosyne. Creates lint + libraries for all object libraries. + + make tags: + Builds ctags-style tag files for all subdirectories except + mnemosyne. + + make all: + Makes all of the above, except check_leaks, which is + incompatible with a plain "make." + +All targets, except clean and distclean, will create the include +directory if it does not already exist. + +The Makefile does not compile the SIS interface (cuddBddPort.c and +cuddPwPt.c found in subdirectory sis). To compile the interface, you +also need array.h and var_set.h, which are not part of this +distribution, but come with SIS. Detailed instructions on how to +integrate the CUDD package in SIS can be found in the documentation +(cudd/doc). + +PLATFORMS + +This kit has been successfully built on the following configurations: + PC (ia32 and ia64) running Linux RedHat with gcc + PC (ia32 and ia64) running Linux RedHat with g++ + PC (ia32) running Linux RedHat with icc + PC (ia32) running Linux RedHat with icpc + PC (ia64) running Linux RedHat with ecc + PC (ia64) running Linux RedHat with ecpc + SUN running Solaris 2.8 with cc + SUN running Solaris 2.8 with CC + SUN running Solaris 2.8 with gcc + SUN running Solaris 2.8 with g++ + +Platforms to which I have no longer access and therefore are no longer +supported. + + DECstation running Ultrix with cc + DECstation running Ultrix with gcc + IBM RS6000 running AIX 3.2.4 with cc (**) + IBM RS6000 running AIX 3.2.4 with gcc + IBM RS6000 running AIX 3.2.4 with g++ + SUN running SunOS with gcc + DEC Alpha running Digital Unix with cc + DEC Alpha running Digital Unix with cxx + DEC Alpha running Digital Unix with gcc + HP 9000/770 running HP-UX with c89 + HP 9000/770 running HP-UX with CC + HP 9000/770 running HP-UX with gcc + HP 9000/770 running HP-UX with g++ (*) + SUN running Solaris 2.8 with /usr/ucb/cc + PC running Solaris 2.8 with /usr/bin/cc + PC running Solaris 2.8 with /usr/ucb/cc + PC running Solaris 2.8 with CC + PC running Solaris 2.8 with gcc + PC running Solaris 2.8 with g++ + +NOTES + (*) C programs were compiled with g++, but linked with gcc. + + (**) Some old versions of the AIX cc compiler have buggy optimizers: + Try compiling with -O2 instead of -O3 if the program crashes. + +Running lint and compiling with gcc -Wall still produces warnings. +Running `purify' under Solaris 2.8 generates no messages. + +CUDD AND WIN32 + +This kit has also been built on a PC running Windows98, Windows NT, +and Windows XP using the Cygnus port of the GNU tools +(http://www.cygwin.com/.) This release of CUDD was tested under Windows +XP with versions 1.5.5-1 of the Cygwin DLL. Both gcc and g++ were used. +The time measurement functions do not work under Windows98. You must have +bash set up properly for make to work. See also the instructions in Makefile. + +SANITY CHECK + +The directory `nanotrav' contains a very simple application based on the +CUDD package. The `nanotrav' directory contains a man page that +describes the options nanotrav supports. The files *.blif are sample +input files for nanotrav. + +If you have built the mnemosyne library (make check_leaks), you can do + cd mnemosyne + make runmtest +This does not work on machines running SunOS, but the version of +nanotrav that uses mnemosyne may work. + +DOCUMENTATION + +Directory cudd-2.4.1/cudd/doc contains HTML documentation for the CUDD +package. The recommended starting point is cuddIntro.html. Documentation +in both postscript(tm) format and plain text format is also provided. +Documentation for the auxiliary libraries (except for the util library) +is in the doc subdirectories. + +FEEDBACK: + +Send feedback to: + +Fabio Somenzi +University of Colorado at Boulder +ECE Dept. +Boulder, CO 80309-0425 +Fabio@Colorado.EDU +http://vlsi.colorado.edu/~fabio diff --git a/distr/RELEASE.NOTES b/distr/RELEASE.NOTES new file mode 100644 index 0000000..6eba803 --- /dev/null +++ b/distr/RELEASE.NOTES @@ -0,0 +1,38 @@ +Release 2.4.2 of Cudd features several bug fixes. The most important +are those that prevented Cudd from making full use of up to 4 GB of +memory when using 32-bit pointers. A handful of bugs were discovered by +Coverity. (Thanks to Christian Stangier!) + +This release can be compiled with either 64-bit pointers or 32-bit +pointers on x86_64 platforms if sizeof(long) = sizeof(void *) = 8 and +sizeof(int) = 4. This is known as the LP64 model. For 32-bit pointers, +one usually needs supplementary libraries. On Ubuntu and Debian Linux, +one needs g++-multilib, which can be installed with +"apt-get install g++-multilib." + +Added functions + +DdNode *Cudd_Inequality (DdManager * dd, int N, int c, DdNode ** x, +DdNode ** y); + +DdNode * Cudd_Disequality (DdManager * dd, int N, int c, DdNode ** x, +DdNode ** y); + +DdNode * Cudd_bddInterval (DdManager * dd, int N, DdNode ** x, +unsigned int lowerB, unsigned int upperB); + +Changed prototypes: + +int Cudd_DumpBlif (DdManager *dd, int n, DdNode **f, char +**inames, char **onames, char *mname, FILE *fp, int mv); + +int Cudd_DumpBlifBody (DdManager *dd, int n, DdNode **f, char +**inames, char **onames, FILE *fp, int mv); + +The additional parameter allows the caller to choose between plain blif +and blif-MV. + +---------------------------------------------------------------------- + +Release 2.4.1 of Cudd features one major change with respect to previous +releases. The licensing terms are now explicitly stated. diff --git a/distr/cudd/Makefile b/distr/cudd/Makefile new file mode 100644 index 0000000..bf8ab71 --- /dev/null +++ b/distr/cudd/Makefile @@ -0,0 +1,127 @@ +# $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).so: $(POBJ) + gcc --shared -o $@ $? $(LIBS) +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).so 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/distr/cudd/cudd.h b/distr/cudd/cudd.h new file mode 100644 index 0000000..7b005ae --- /dev/null +++ b/distr/cudd/cudd.h @@ -0,0 +1,1053 @@ +/**CHeaderFile***************************************************************** + + FileName [cudd.h] + + PackageName [cudd] + + Synopsis [The University of Colorado decision diagram package.] + + Description [External functions and data strucures of the CUDD package. +
    +
  • To turn on the gathering of statistics, define DD_STATS. +
  • To link with mis, define DD_MIS. +
+ 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 _CUDD +#define _CUDD + +/*---------------------------------------------------------------------------*/ +/* Nested includes */ +/*---------------------------------------------------------------------------*/ + +#include "mtr.h" +#include "epd.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/*---------------------------------------------------------------------------*/ +/* 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; +}; + +#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 *)((long)(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 *)((long)(node) ^ (c))) + + +/**Macro*********************************************************************** + + Synopsis [Returns the regular version of a pointer.] + + Description [] + + SideEffects [none] + + SeeAlso [Cudd_Complement Cudd_IsComplement] + +******************************************************************************/ +#define Cudd_Regular(node) ((DdNode *)((unsigned long)(node) & ~01)) + + +/**Macro*********************************************************************** + + Synopsis [Returns the complemented version of a pointer.] + + Description [] + + SideEffects [none] + + SeeAlso [Cudd_Regular Cudd_IsComplement] + +******************************************************************************/ +#define Cudd_Complement(node) ((DdNode *)((unsigned long)(node) | 01)) + + +/**Macro*********************************************************************** + + Synopsis [Returns 1 if a pointer is complemented.] + + Description [] + + SideEffects [none] + + SeeAlso [Cudd_Regular Cudd_Complement] + +******************************************************************************/ +#define Cudd_IsComplement(node) ((int) ((long) (node) & 01)) + + +/**Macro*********************************************************************** + + Synopsis [Returns the then child of an internal node.] + + Description [Returns the then child of an internal node. If + node 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 + node 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 + node 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. +
    +
  • DdManager *manager; +
  • DdNode *f; +
  • DdGen *gen; +
  • int *cube; +
  • CUDD_VALUE_TYPE value; +
+ 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.

+ 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. +

    +
  • DdManager *manager; +
  • DdNode *l; +
  • DdNode *u; +
  • DdGen *gen; +
  • int *cube; +
+ 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.

+ 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. +

    +
  • DdManager *manager; +
  • DdNode *f; +
  • DdGen *gen; +
  • DdNode *node; +
+ 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.

+ 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. +

    +
  • DdManager *manager; +
  • DdNode *f; +
  • DdGen *gen; +
  • int *path; +
+ 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.

+ 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 *Pii, 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***************************************************************/ + +#ifdef __cplusplus +} /* end of extern "C" */ +#endif + +#endif /* _CUDD */ diff --git a/distr/cudd/cuddAPI.c b/distr/cudd/cuddAPI.c new file mode 100644 index 0000000..0d931e9 --- /dev/null +++ b/distr/cudd/cuddAPI.c @@ -0,0 +1,4437 @@ +/**CFile*********************************************************************** + + FileName [cuddAPI.c] + + PackageName [cudd] + + Synopsis [Application interface functions.] + + Description [External procedures included in this module: +

    +
  • Cudd_addNewVar() +
  • Cudd_addNewVarAtLevel() +
  • Cudd_bddNewVar() +
  • Cudd_bddNewVarAtLevel() +
  • Cudd_addIthVar() +
  • Cudd_bddIthVar() +
  • Cudd_zddIthVar() +
  • Cudd_zddVarsFromBddVars() +
  • Cudd_addConst() +
  • Cudd_IsNonConstant() +
  • Cudd_AutodynEnable() +
  • Cudd_AutodynDisable() +
  • Cudd_ReorderingStatus() +
  • Cudd_AutodynEnableZdd() +
  • Cudd_AutodynDisableZdd() +
  • Cudd_ReorderingStatusZdd() +
  • Cudd_zddRealignmentEnabled() +
  • Cudd_zddRealignEnable() +
  • Cudd_zddRealignDisable() +
  • Cudd_bddRealignmentEnabled() +
  • Cudd_bddRealignEnable() +
  • Cudd_bddRealignDisable() +
  • Cudd_ReadOne() +
  • Cudd_ReadZddOne() +
  • Cudd_ReadZero() +
  • Cudd_ReadLogicZero() +
  • Cudd_ReadPlusInfinity() +
  • Cudd_ReadMinusInfinity() +
  • Cudd_ReadBackground() +
  • Cudd_SetBackground() +
  • Cudd_ReadCacheSlots() +
  • Cudd_ReadCacheUsedSlots() +
  • Cudd_ReadCacheLookUps() +
  • Cudd_ReadCacheHits() +
  • Cudd_ReadMinHit() +
  • Cudd_SetMinHit() +
  • Cudd_ReadLooseUpTo() +
  • Cudd_SetLooseUpTo() +
  • Cudd_ReadMaxCache() +
  • Cudd_ReadMaxCacheHard() +
  • Cudd_SetMaxCacheHard() +
  • Cudd_ReadSize() +
  • Cudd_ReadSlots() +
  • Cudd_ReadUsedSlots() +
  • Cudd_ExpectedUsedSlots() +
  • Cudd_ReadKeys() +
  • Cudd_ReadDead() +
  • Cudd_ReadMinDead() +
  • Cudd_ReadReorderings() +
  • Cudd_ReadReorderingTime() +
  • Cudd_ReadGarbageCollections() +
  • Cudd_ReadGarbageCollectionTime() +
  • Cudd_ReadNodesFreed() +
  • Cudd_ReadNodesDropped() +
  • Cudd_ReadUniqueLookUps() +
  • Cudd_ReadUniqueLinks() +
  • Cudd_ReadSiftMaxVar() +
  • Cudd_SetSiftMaxVar() +
  • Cudd_ReadMaxGrowth() +
  • Cudd_SetMaxGrowth() +
  • Cudd_ReadMaxGrowthAlternate() +
  • Cudd_SetMaxGrowthAlternate() +
  • Cudd_ReadReorderingCycle() +
  • Cudd_SetReorderingCycle() +
  • Cudd_ReadTree() +
  • Cudd_SetTree() +
  • Cudd_FreeTree() +
  • Cudd_ReadZddTree() +
  • Cudd_SetZddTree() +
  • Cudd_FreeZddTree() +
  • Cudd_NodeReadIndex() +
  • Cudd_ReadPerm() +
  • Cudd_ReadInvPerm() +
  • Cudd_ReadVars() +
  • Cudd_ReadEpsilon() +
  • Cudd_SetEpsilon() +
  • Cudd_ReadGroupCheck() +
  • Cudd_SetGroupcheck() +
  • Cudd_GarbageCollectionEnabled() +
  • Cudd_EnableGarbageCollection() +
  • Cudd_DisableGarbageCollection() +
  • Cudd_DeadAreCounted() +
  • Cudd_TurnOnCountDead() +
  • Cudd_TurnOffCountDead() +
  • Cudd_ReadRecomb() +
  • Cudd_SetRecomb() +
  • Cudd_ReadSymmviolation() +
  • Cudd_SetSymmviolation() +
  • Cudd_ReadArcviolation() +
  • Cudd_SetArcviolation() +
  • Cudd_ReadPopulationSize() +
  • Cudd_SetPopulationSize() +
  • Cudd_ReadNumberXovers() +
  • Cudd_SetNumberXovers() +
  • Cudd_ReadMemoryInUse() +
  • Cudd_PrintInfo() +
  • Cudd_ReadPeakNodeCount() +
  • Cudd_ReadPeakLiveNodeCount() +
  • Cudd_ReadNodeCount() +
  • Cudd_zddReadNodeCount() +
  • Cudd_AddHook() +
  • Cudd_RemoveHook() +
  • Cudd_IsInHook() +
  • Cudd_StdPreReordHook() +
  • Cudd_StdPostReordHook() +
  • Cudd_EnableReorderingReporting() +
  • Cudd_DisableReorderingReporting() +
  • Cudd_ReorderingReporting() +
  • Cudd_ReadErrorCode() +
  • Cudd_ClearErrorCode() +
  • Cudd_ReadStdout() +
  • Cudd_SetStdout() +
  • Cudd_ReadStderr() +
  • Cudd_SetStderr() +
  • Cudd_ReadNextReordering() +
  • Cudd_SetNextReordering() +
  • Cudd_ReadSwapSteps() +
  • Cudd_ReadMaxLive() +
  • Cudd_SetMaxLive() +
  • Cudd_ReadMaxMemory() +
  • Cudd_SetMaxMemory() +
  • Cudd_bddBindVar() +
  • Cudd_bddUnbindVar() +
  • Cudd_bddVarIsBound() +
  • Cudd_bddSetPiVar() +
  • Cudd_bddSetPsVar() +
  • Cudd_bddSetNsVar() +
  • Cudd_bddIsPiVar() +
  • Cudd_bddIsPsVar() +
  • Cudd_bddIsNsVar() +
  • Cudd_bddSetPairIndex() +
  • Cudd_bddReadPairIndex() +
  • Cudd_bddSetVarToBeGrouped() +
  • Cudd_bddSetVarHardGroup() +
  • Cudd_bddResetVarToBeGrouped() +
  • Cudd_bddIsVarToBeGrouped() +
  • Cudd_bddSetVarToBeUngrouped() +
  • Cudd_bddIsVarToBeUngrouped() +
  • Cudd_bddIsVarHardGroup() +
+ Static procedures included in this module: +
    +
  • fixVarTree() +
] + + 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 */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* 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 = 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); + 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 = ALLOC(char, dd->size); + if (vmask == NULL) { + dd->errorCode = CUDD_MEMORY_OUT; + return(0); + } + lmask = 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); + FREE(vmask); + 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 = 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 M be the + ratio of the two numbers. For the purpose of realignment, the ZDD + variables from M*i to (M+1)*i-1 are + reagarded as corresponding to BDD variable i. 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 M be the + ratio of the two numbers. For the purpose of realignment, the ZDD + variables from M*i to (M+1)*i-1 are + reagarded as corresponding to BDD variable i. 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 i.] + + 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 f10 = f01 or + f11 = f00 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 f10 = f01 or + f11 = f00 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 y not coming from x 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 y not coming from x 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: %.0f\n", + 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 = 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; + 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 */ diff --git a/distr/cudd/cuddAddAbs.c b/distr/cudd/cuddAddAbs.c new file mode 100644 index 0000000..4e9012e --- /dev/null +++ b/distr/cudd/cuddAddAbs.c @@ -0,0 +1,579 @@ +/**CFile*********************************************************************** + + FileName [cuddAddAbs.c] + + PackageName [cudd] + + Synopsis [Quantification functions for ADDs.] + + Description [External procedures included in this module: +
    +
  • Cudd_addExistAbstract() +
  • Cudd_addUnivAbstract() +
  • Cudd_addOrAbstract() +
+ Internal procedures included in this module: +
    +
  • cuddAddExistAbstractRecur() +
  • cuddAddUnivAbstractRecur() +
  • cuddAddOrAbstractRecur() +
+ Static procedures included in this module: +
    +
  • addCheckPositiveCube() +
] + + 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 */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* 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 */ + diff --git a/distr/cudd/cuddAddApply.c b/distr/cudd/cuddAddApply.c new file mode 100644 index 0000000..944d7a4 --- /dev/null +++ b/distr/cudd/cuddAddApply.c @@ -0,0 +1,941 @@ +/**CFile*********************************************************************** + + FileName [cuddAddApply.c] + + PackageName [cudd] + + Synopsis [Apply functions for ADDs and their operators.] + + Description [External procedures included in this module: +
    +
  • Cudd_addApply() +
  • 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() +
+ Internal procedures included in this module: +
    +
  • cuddAddApplyRecur() +
  • cuddAddMonadicApplyRecur() +
] + + 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 */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* 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>=g; 0 if f<g.] + + Description [Threshold operator for Apply (f if f >=g; 0 if f<g). + Returns NULL if not a terminal case; f op g otherwise.] + + SideEffects [None] + + SeeAlso [Cudd_addApply] + +******************************************************************************/ +DdNode * +Cudd_addThreshold( + DdManager * dd, + DdNode ** f, + DdNode ** g) +{ + DdNode *F, *G; + + F = *f; G = *g; + if (F == G || F == DD_PLUS_INFINITY(dd)) return(F); + if (cuddIsConstant(F) && cuddIsConstant(G)) { + if (cuddV(F) >= cuddV(G)) { + return(F); + } else { + return(DD_ZERO(dd)); + } + } + return(NULL); + +} /* end of Cudd_addThreshold */ + + +/**Function******************************************************************** + + Synopsis [This operator sets f to the value of g wherever g != 0.] + + Description [This operator sets f to the value of g wherever g != 0. + Returns NULL if not a terminal case; f op g otherwise.] + + SideEffects [None] + + SeeAlso [Cudd_addApply] + +******************************************************************************/ +DdNode * +Cudd_addSetNZ( + DdManager * dd, + DdNode ** f, + DdNode ** g) +{ + DdNode *F, *G; + + F = *f; G = *g; + if (F == G) return(F); + if (F == DD_ZERO(dd)) return(G); + if (G == DD_ZERO(dd)) return(F); + if (cuddIsConstant(G)) return(G); + return(NULL); + +} /* end of Cudd_addSetNZ */ + + +/**Function******************************************************************** + + Synopsis [Integer and floating point division.] + + Description [Integer and floating point division. Returns NULL if not + a terminal case; f / g otherwise.] + + SideEffects [None] + + SeeAlso [Cudd_addApply] + +******************************************************************************/ +DdNode * +Cudd_addDivide( + DdManager * dd, + DdNode ** f, + DdNode ** g) +{ + DdNode *res; + DdNode *F, *G; + CUDD_VALUE_TYPE value; + + F = *f; G = *g; + /* We would like to use F == G -> F/G == 1, but F and G may + ** contain zeroes. */ + if (F == DD_ZERO(dd)) return(DD_ZERO(dd)); + if (G == DD_ONE(dd)) return(F); + if (cuddIsConstant(F) && cuddIsConstant(G)) { + value = cuddV(F)/cuddV(G); + res = cuddUniqueConst(dd,value); + return(res); + } + return(NULL); + +} /* end of Cudd_addDivide */ + + +/**Function******************************************************************** + + Synopsis [Integer and floating point subtraction.] + + Description [Integer and floating point subtraction. Returns NULL if + not a terminal case; f - g otherwise.] + + SideEffects [None] + + SeeAlso [Cudd_addApply] + +******************************************************************************/ +DdNode * +Cudd_addMinus( + DdManager * dd, + DdNode ** f, + DdNode ** g) +{ + DdNode *res; + DdNode *F, *G; + CUDD_VALUE_TYPE value; + + F = *f; G = *g; + if (F == G) return(DD_ZERO(dd)); + if (F == DD_ZERO(dd)) return(cuddAddNegateRecur(dd,G)); + if (G == DD_ZERO(dd)) return(F); + if (cuddIsConstant(F) && cuddIsConstant(G)) { + value = cuddV(F)-cuddV(G); + res = cuddUniqueConst(dd,value); + return(res); + } + return(NULL); + +} /* end of Cudd_addMinus */ + + +/**Function******************************************************************** + + Synopsis [Integer and floating point min.] + + Description [Integer and floating point min for Cudd_addApply. + Returns NULL if not a terminal case; min(f,g) otherwise.] + + SideEffects [None] + + SeeAlso [Cudd_addApply] + +******************************************************************************/ +DdNode * +Cudd_addMinimum( + DdManager * dd, + DdNode ** f, + DdNode ** g) +{ + DdNode *F, *G; + + F = *f; G = *g; + if (F == DD_PLUS_INFINITY(dd)) return(G); + if (G == DD_PLUS_INFINITY(dd)) return(F); + if (F == G) return(F); +#if 0 + /* These special cases probably do not pay off. */ + if (F == DD_MINUS_INFINITY(dd)) return(F); + if (G == DD_MINUS_INFINITY(dd)) return(G); +#endif + if (cuddIsConstant(F) && cuddIsConstant(G)) { + if (cuddV(F) <= cuddV(G)) { + return(F); + } else { + return(G); + } + } + if (F > G) { /* swap f and g */ + *f = G; + *g = F; + } + return(NULL); + +} /* end of Cudd_addMinimum */ + + +/**Function******************************************************************** + + Synopsis [Integer and floating point max.] + + Description [Integer and floating point max for Cudd_addApply. + Returns NULL if not a terminal case; max(f,g) otherwise.] + + SideEffects [None] + + SeeAlso [Cudd_addApply] + +******************************************************************************/ +DdNode * +Cudd_addMaximum( + DdManager * dd, + DdNode ** f, + DdNode ** g) +{ + DdNode *F, *G; + + F = *f; G = *g; + if (F == G) return(F); + if (F == DD_MINUS_INFINITY(dd)) return(G); + if (G == DD_MINUS_INFINITY(dd)) return(F); +#if 0 + /* These special cases probably do not pay off. */ + if (F == DD_PLUS_INFINITY(dd)) return(F); + if (G == DD_PLUS_INFINITY(dd)) return(G); +#endif + if (cuddIsConstant(F) && cuddIsConstant(G)) { + if (cuddV(F) >= cuddV(G)) { + return(F); + } else { + return(G); + } + } + if (F > G) { /* swap f and g */ + *f = G; + *g = F; + } + return(NULL); + +} /* end of Cudd_addMaximum */ + + +/**Function******************************************************************** + + Synopsis [Returns 1 if f > g and 0 otherwise.] + + Description [Returns 1 if f > g and 0 otherwise. Used in + conjunction with Cudd_addApply. Returns NULL if not a terminal + case.] + + SideEffects [None] + + SeeAlso [Cudd_addApply] + +******************************************************************************/ +DdNode * +Cudd_addOneZeroMaximum( + DdManager * dd, + DdNode ** f, + DdNode ** g) +{ + + if (*f == *g) return(DD_ZERO(dd)); + if (*g == DD_PLUS_INFINITY(dd)) + return DD_ZERO(dd); + if (cuddIsConstant(*f) && cuddIsConstant(*g)) { + if (cuddV(*f) > cuddV(*g)) { + return(DD_ONE(dd)); + } else { + return(DD_ZERO(dd)); + } + } + + return(NULL); + +} /* end of Cudd_addOneZeroMaximum */ + + +/**Function******************************************************************** + + Synopsis [Returns plusinfinity if f=g; returns min(f,g) if f!=g.] + + Description [Returns NULL if not a terminal case; f op g otherwise, + where f op g is plusinfinity if f=g; min(f,g) if f!=g.] + + SideEffects [None] + + SeeAlso [Cudd_addApply] + +******************************************************************************/ +DdNode * +Cudd_addDiff( + DdManager * dd, + DdNode ** f, + DdNode ** g) +{ + DdNode *F, *G; + + F = *f; G = *g; + if (F == G) return(DD_PLUS_INFINITY(dd)); + if (F == DD_PLUS_INFINITY(dd)) return(G); + if (G == DD_PLUS_INFINITY(dd)) return(F); + if (cuddIsConstant(F) && cuddIsConstant(G)) { + if (cuddV(F) != cuddV(G)) { + if (cuddV(F) < cuddV(G)) { + return(F); + } else { + return(G); + } + } else { + return(DD_PLUS_INFINITY(dd)); + } + } + return(NULL); + +} /* end of Cudd_addDiff */ + + +/**Function******************************************************************** + + Synopsis [f if f==g; background if f!=g.] + + Description [Returns NULL if not a terminal case; f op g otherwise, + where f op g is f if f==g; background if f!=g.] + + SideEffects [None] + + SeeAlso [Cudd_addApply] + +******************************************************************************/ +DdNode * +Cudd_addAgreement( + DdManager * dd, + DdNode ** f, + DdNode ** g) +{ + DdNode *F, *G; + + F = *f; G = *g; + if (F == G) return(F); + if (F == dd->background) return(F); + if (G == dd->background) return(G); + if (cuddIsConstant(F) && cuddIsConstant(G)) return(dd->background); + return(NULL); + +} /* end of Cudd_addAgreement */ + + +/**Function******************************************************************** + + Synopsis [Disjunction of two 0-1 ADDs.] + + Description [Disjunction of two 0-1 ADDs. Returns NULL + if not a terminal case; f OR g otherwise.] + + SideEffects [None] + + SeeAlso [Cudd_addApply] + +******************************************************************************/ +DdNode * +Cudd_addOr( + DdManager * dd, + DdNode ** f, + DdNode ** g) +{ + DdNode *F, *G; + + F = *f; G = *g; + if (F == DD_ONE(dd) || G == DD_ONE(dd)) return(DD_ONE(dd)); + if (cuddIsConstant(F)) return(G); + if (cuddIsConstant(G)) return(F); + if (F == G) return(F); + if (F > G) { /* swap f and g */ + *f = G; + *g = F; + } + return(NULL); + +} /* end of Cudd_addOr */ + + +/**Function******************************************************************** + + Synopsis [NAND of two 0-1 ADDs.] + + Description [NAND of two 0-1 ADDs. Returns NULL + if not a terminal case; f NAND g otherwise.] + + SideEffects [None] + + SeeAlso [Cudd_addApply] + +******************************************************************************/ +DdNode * +Cudd_addNand( + DdManager * dd, + DdNode ** f, + DdNode ** g) +{ + DdNode *F, *G; + + F = *f; G = *g; + if (F == DD_ZERO(dd) || G == DD_ZERO(dd)) return(DD_ONE(dd)); + if (cuddIsConstant(F) && cuddIsConstant(G)) return(DD_ZERO(dd)); + if (F > G) { /* swap f and g */ + *f = G; + *g = F; + } + return(NULL); + +} /* end of Cudd_addNand */ + + +/**Function******************************************************************** + + Synopsis [NOR of two 0-1 ADDs.] + + Description [NOR of two 0-1 ADDs. Returns NULL + if not a terminal case; f NOR g otherwise.] + + SideEffects [None] + + SeeAlso [Cudd_addApply] + +******************************************************************************/ +DdNode * +Cudd_addNor( + DdManager * dd, + DdNode ** f, + DdNode ** g) +{ + DdNode *F, *G; + + F = *f; G = *g; + if (F == DD_ONE(dd) || G == DD_ONE(dd)) return(DD_ZERO(dd)); + if (cuddIsConstant(F) && cuddIsConstant(G)) return(DD_ONE(dd)); + if (F > G) { /* swap f and g */ + *f = G; + *g = F; + } + return(NULL); + +} /* end of Cudd_addNor */ + + +/**Function******************************************************************** + + Synopsis [XOR of two 0-1 ADDs.] + + Description [XOR of two 0-1 ADDs. Returns NULL + if not a terminal case; f XOR g otherwise.] + + SideEffects [None] + + SeeAlso [Cudd_addApply] + +******************************************************************************/ +DdNode * +Cudd_addXor( + DdManager * dd, + DdNode ** f, + DdNode ** g) +{ + DdNode *F, *G; + + F = *f; G = *g; + if (F == G) return(DD_ZERO(dd)); + if (F == DD_ONE(dd) && G == DD_ZERO(dd)) return(DD_ONE(dd)); + if (G == DD_ONE(dd) && F == DD_ZERO(dd)) return(DD_ONE(dd)); + if (cuddIsConstant(F) && cuddIsConstant(G)) return(DD_ZERO(dd)); + if (F > G) { /* swap f and g */ + *f = G; + *g = F; + } + return(NULL); + +} /* end of Cudd_addXor */ + + +/**Function******************************************************************** + + Synopsis [XNOR of two 0-1 ADDs.] + + Description [XNOR of two 0-1 ADDs. Returns NULL + if not a terminal case; f XNOR g otherwise.] + + SideEffects [None] + + SeeAlso [Cudd_addApply] + +******************************************************************************/ +DdNode * +Cudd_addXnor( + DdManager * dd, + DdNode ** f, + DdNode ** g) +{ + DdNode *F, *G; + + F = *f; G = *g; + if (F == G) return(DD_ONE(dd)); + if (F == DD_ONE(dd) && G == DD_ONE(dd)) return(DD_ONE(dd)); + if (G == DD_ZERO(dd) && F == DD_ZERO(dd)) return(DD_ONE(dd)); + if (cuddIsConstant(F) && cuddIsConstant(G)) return(DD_ZERO(dd)); + if (F > G) { /* swap f and g */ + *f = G; + *g = F; + } + return(NULL); + +} /* end of Cudd_addXnor */ + + +/**Function******************************************************************** + + Synopsis [Applies op to the discriminants of f.] + + Description [Applies op to the discriminants of f. + Returns a pointer to the result if succssful; NULL otherwise.] + + SideEffects [None] + + SeeAlso [Cudd_addApply Cudd_addLog] + +******************************************************************************/ +DdNode * +Cudd_addMonadicApply( + DdManager * dd, + DD_MAOP op, + DdNode * f) +{ + DdNode *res; + + do { + dd->reordered = 0; + res = cuddAddMonadicApplyRecur(dd,op,f); + } while (dd->reordered == 1); + return(res); + +} /* end of Cudd_addMonadicApply */ + + +/**Function******************************************************************** + + Synopsis [Natural logarithm of an ADD.] + + Description [Natural logarithm of an ADDs. Returns NULL + if not a terminal case; log(f) otherwise. The discriminants of f must + be positive double's.] + + SideEffects [None] + + SeeAlso [Cudd_addMonadicApply] + +******************************************************************************/ +DdNode * +Cudd_addLog( + DdManager * dd, + DdNode * f) +{ + if (cuddIsConstant(f)) { + CUDD_VALUE_TYPE value = log(cuddV(f)); + DdNode *res = cuddUniqueConst(dd,value); + return(res); + } + return(NULL); + +} /* end of Cudd_addLog */ + + +/*---------------------------------------------------------------------------*/ +/* Definition of internal functions */ +/*---------------------------------------------------------------------------*/ + + +/**Function******************************************************************** + + Synopsis [Performs the recursive step of Cudd_addApply.] + + Description [Performs the recursive step of Cudd_addApply. Returns a + pointer to the result if successful; NULL otherwise.] + + SideEffects [None] + + SeeAlso [cuddAddMonadicApplyRecur] + +******************************************************************************/ +DdNode * +cuddAddApplyRecur( + DdManager * dd, + DD_AOP op, + DdNode * f, + DdNode * g) +{ + DdNode *res, + *fv, *fvn, *gv, *gvn, + *T, *E; + unsigned int ford, gord; + unsigned int index; + DD_CTFP cacheOp; + + /* Check terminal cases. Op may swap f and g to increase the + * cache hit rate. + */ + statLine(dd); + res = (*op)(dd,&f,&g); + if (res != NULL) return(res); + + /* Check cache. */ + cacheOp = (DD_CTFP) op; + res = cuddCacheLookup2(dd,cacheOp,f,g); + if (res != NULL) return(res); + + /* Recursive step. */ + ford = cuddI(dd,f->index); + gord = cuddI(dd,g->index); + if (ford <= gord) { + index = f->index; + fv = cuddT(f); + fvn = cuddE(f); + } else { + index = g->index; + fv = fvn = f; + } + if (gord <= ford) { + gv = cuddT(g); + gvn = cuddE(g); + } else { + gv = gvn = g; + } + + T = cuddAddApplyRecur(dd,op,fv,gv); + if (T == NULL) return(NULL); + cuddRef(T); + + E = cuddAddApplyRecur(dd,op,fvn,gvn); + if (E == NULL) { + Cudd_RecursiveDeref(dd,T); + return(NULL); + } + cuddRef(E); + + res = (T == E) ? T : cuddUniqueInter(dd,(int)index,T,E); + if (res == NULL) { + Cudd_RecursiveDeref(dd, T); + Cudd_RecursiveDeref(dd, E); + return(NULL); + } + cuddDeref(T); + cuddDeref(E); + + /* Store result. */ + cuddCacheInsert2(dd,cacheOp,f,g,res); + + return(res); + +} /* end of cuddAddApplyRecur */ + + +/**Function******************************************************************** + + Synopsis [Performs the recursive step of Cudd_addMonadicApply.] + + Description [Performs the recursive step of Cudd_addMonadicApply. Returns a + pointer to the result if successful; NULL otherwise.] + + SideEffects [None] + + SeeAlso [cuddAddApplyRecur] + +******************************************************************************/ +DdNode * +cuddAddMonadicApplyRecur( + DdManager * dd, + DD_MAOP op, + DdNode * f) +{ + DdNode *res, *ft, *fe, *T, *E; + unsigned int index; + + /* Check terminal cases. */ + statLine(dd); + res = (*op)(dd,f); + if (res != NULL) return(res); + + /* Check cache. */ + res = cuddCacheLookup1(dd,op,f); + if (res != NULL) return(res); + + /* Recursive step. */ + index = f->index; + ft = cuddT(f); + fe = cuddE(f); + + T = cuddAddMonadicApplyRecur(dd,op,ft); + if (T == NULL) return(NULL); + cuddRef(T); + + E = cuddAddMonadicApplyRecur(dd,op,fe); + if (E == NULL) { + Cudd_RecursiveDeref(dd,T); + return(NULL); + } + cuddRef(E); + + res = (T == E) ? T : cuddUniqueInter(dd,(int)index,T,E); + if (res == NULL) { + Cudd_RecursiveDeref(dd, T); + Cudd_RecursiveDeref(dd, E); + return(NULL); + } + cuddDeref(T); + cuddDeref(E); + + /* Store result. */ + cuddCacheInsert1(dd,op,f,res); + + return(res); + +} /* end of cuddAddMonadicApplyRecur */ + + +/*---------------------------------------------------------------------------*/ +/* Definition of static functions */ +/*---------------------------------------------------------------------------*/ diff --git a/distr/cudd/cuddAddFind.c b/distr/cudd/cuddAddFind.c new file mode 100644 index 0000000..98ab7e7 --- /dev/null +++ b/distr/cudd/cuddAddFind.c @@ -0,0 +1,316 @@ +/**CFile*********************************************************************** + + FileName [cuddAddFind.c] + + PackageName [cudd] + + Synopsis [Functions to find maximum and minimum in an ADD and to + extract the i-th bit.] + + Description [External procedures included in this module: +
    +
  • Cudd_addFindMax() +
  • Cudd_addFindMin() +
  • Cudd_addIthBit() +
+ Static functions included in this module: +
    +
  • addDoIthBit() +
] + + 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 */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* 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 */ + diff --git a/distr/cudd/cuddAddInv.c b/distr/cudd/cuddAddInv.c new file mode 100644 index 0000000..323d506 --- /dev/null +++ b/distr/cudd/cuddAddInv.c @@ -0,0 +1,201 @@ +/**CFile*********************************************************************** + + FileName [cuddAddInv.c] + + PackageName [cudd] + + Synopsis [Function to compute the scalar inverse of an ADD.] + + Description [External procedures included in this module: +
    +
  • Cudd_addScalarInverse() +
+ Internal procedures included in this module: +
    +
  • cuddAddScalarInverseRecur() +
] + + 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 */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* 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 */ +/*---------------------------------------------------------------------------*/ + diff --git a/distr/cudd/cuddAddIte.c b/distr/cudd/cuddAddIte.c new file mode 100644 index 0000000..19a829b --- /dev/null +++ b/distr/cudd/cuddAddIte.c @@ -0,0 +1,639 @@ +/**CFile*********************************************************************** + + FileName [cuddAddIte.c] + + PackageName [cudd] + + Synopsis [ADD ITE function and satellites.] + + Description [External procedures included in this module: +
    +
  • Cudd_addIte() +
  • Cudd_addIteConstant() +
  • Cudd_addEvalConst() +
  • Cudd_addCmpl() +
  • Cudd_addLeq() +
+ Internal procedures included in this module: +
    +
  • cuddAddIteRecur() +
  • cuddAddCmplRecur() +
+ Static procedures included in this module: +
    +
  • addVarToConst() +
] + + 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 */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* 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; + + 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 */ diff --git a/distr/cudd/cuddAddNeg.c b/distr/cudd/cuddAddNeg.c new file mode 100644 index 0000000..e0a9b4c --- /dev/null +++ b/distr/cudd/cuddAddNeg.c @@ -0,0 +1,288 @@ +/**CFile*********************************************************************** + + FileName [cuddAddNeg.c] + + PackageName [cudd] + + Synopsis [Function to compute the negation of an ADD.] + + Description [External procedures included in this module: +
    +
  • Cudd_addNegate() +
  • Cudd_addRoundOff() +
+ Internal procedures included in this module: +
    +
  • cuddAddNegateRecur() +
  • cuddAddRoundOffRecur() +
] + + 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 "util.h" +#include "cuddInt.h" + + +/*---------------------------------------------------------------------------*/ +/* Constant declarations */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Stucture declarations */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Type declarations */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Variable declarations */ +/*---------------------------------------------------------------------------*/ + +#ifndef lint +static char rcsid[] DD_UNUSED = "$Id: cuddAddNeg.c,v 1.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 */ +/*---------------------------------------------------------------------------*/ diff --git a/distr/cudd/cuddAddWalsh.c b/distr/cudd/cuddAddWalsh.c new file mode 100644 index 0000000..9c45bc8 --- /dev/null +++ b/distr/cudd/cuddAddWalsh.c @@ -0,0 +1,391 @@ +/**CFile*********************************************************************** + + FileName [cuddAddWalsh.c] + + PackageName [cudd] + + Synopsis [Functions that generate Walsh matrices and residue + functions in ADD form.] + + Description [External procedures included in this module: +
    +
  • Cudd_addWalsh() +
  • Cudd_addResidue() +
+ Static procedures included in this module: +
    +
  • addWalshInt() +
] + + 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 */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* 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] = ALLOC(DdNode *,m); + if (array[0] == NULL) { + dd->errorCode = CUDD_MEMORY_OUT; + return(NULL); + } + array[1] = ALLOC(DdNode *,m); + if (array[1] == NULL) { + FREE(array[0]); + dd->errorCode = CUDD_MEMORY_OUT; + return(NULL); + } + for (i = 0; i < m; i++) { + array[0][i] = array[1][i] = NULL; + } + + /* Initialize residues. */ + for (i = 0; i < m; i++) { + tmp = cuddUniqueConst(dd,(CUDD_VALUE_TYPE) i); + if (tmp == NULL) { + for (j = 0; j < i; j++) { + Cudd_RecursiveDeref(dd,array[1][j]); + } + FREE(array[0]); + FREE(array[1]); + return(NULL); + } + cuddRef(tmp); + array[1][i] = tmp; + } + + /* Main iteration. */ + residue = 1; /* residue of 2**0 */ + for (k = 0; k < n; k++) { + /* Choose current and previous arrays. */ + thisOne = k & 1; + previous = thisOne ^ 1; + /* Build an ADD projection function. */ + if (msbLsb) { + index = top+n-k-1; + } else { + index = top+k; + } + var = cuddUniqueInter(dd,index,DD_ONE(dd),DD_ZERO(dd)); + if (var == NULL) { + for (j = 0; j < m; j++) { + Cudd_RecursiveDeref(dd,array[previous][j]); + } + FREE(array[0]); + FREE(array[1]); + return(NULL); + } + cuddRef(var); + for (i = 0; i < m; i ++) { + t = (i + residue) % m; + tmp = Cudd_addIte(dd,var,array[previous][t],array[previous][i]); + if (tmp == NULL) { + for (j = 0; j < i; j++) { + Cudd_RecursiveDeref(dd,array[thisOne][j]); + } + for (j = 0; j < m; j++) { + Cudd_RecursiveDeref(dd,array[previous][j]); + } + FREE(array[0]); + FREE(array[1]); + return(NULL); + } + cuddRef(tmp); + array[thisOne][i] = tmp; + } + /* One layer completed. Free the other array for the next iteration. */ + for (i = 0; i < m; i++) { + Cudd_RecursiveDeref(dd,array[previous][i]); + } + Cudd_RecursiveDeref(dd,var); + /* Update residue of 2**k. */ + residue = (2 * residue) % m; + /* Adjust residue for MSB, if this is a two's complement number. */ + if (tc && (k == n - 1)) { + residue = (m - residue) % m; + } + } + + /* We are only interested in the 0-residue node of the top layer. */ + for (i = 1; i < m; i++) { + Cudd_RecursiveDeref(dd,array[(n - 1) & 1][i]); + } + res = array[(n - 1) & 1][0]; + + FREE(array[0]); + FREE(array[1]); + + cuddDeref(res); + return(res); + +} /* end of Cudd_addResidue */ + + +/*---------------------------------------------------------------------------*/ +/* Definition of internal functions */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Definition of static functions */ +/*---------------------------------------------------------------------------*/ + + +/**Function******************************************************************** + + Synopsis [Implements the recursive step of Cudd_addWalsh.] + + Description [Generates a Walsh matrix in ADD form. Returns a pointer + to the matrixi if successful; NULL otherwise.] + + SideEffects [None] + +******************************************************************************/ +static DdNode * +addWalshInt( + DdManager * dd, + DdNode ** x, + DdNode ** y, + int n) +{ + DdNode *one, *minusone; + DdNode *t, *u, *t1, *u1, *v, *w; + int i; + + one = DD_ONE(dd); + if (n == 0) return(one); + + /* Build bottom part of ADD outside loop */ + minusone = cuddUniqueConst(dd,(CUDD_VALUE_TYPE) -1); + if (minusone == NULL) return(NULL); + cuddRef(minusone); + v = Cudd_addIte(dd, y[n-1], minusone, one); + if (v == NULL) { + Cudd_RecursiveDeref(dd, minusone); + return(NULL); + } + cuddRef(v); + u = Cudd_addIte(dd, x[n-1], v, one); + if (u == NULL) { + Cudd_RecursiveDeref(dd, minusone); + Cudd_RecursiveDeref(dd, v); + return(NULL); + } + cuddRef(u); + Cudd_RecursiveDeref(dd, v); + if (n>1) { + w = Cudd_addIte(dd, y[n-1], one, minusone); + if (w == NULL) { + Cudd_RecursiveDeref(dd, minusone); + Cudd_RecursiveDeref(dd, u); + return(NULL); + } + cuddRef(w); + t = Cudd_addIte(dd, x[n-1], w, minusone); + if (t == NULL) { + Cudd_RecursiveDeref(dd, minusone); + Cudd_RecursiveDeref(dd, u); + Cudd_RecursiveDeref(dd, w); + return(NULL); + } + cuddRef(t); + Cudd_RecursiveDeref(dd, w); + } + cuddDeref(minusone); /* minusone is in the result; it won't die */ + + /* Loop to build the rest of the ADD */ + for (i=n-2; i>=0; i--) { + t1 = t; u1 = u; + v = Cudd_addIte(dd, y[i], t1, u1); + if (v == NULL) { + Cudd_RecursiveDeref(dd, u1); + Cudd_RecursiveDeref(dd, t1); + return(NULL); + } + cuddRef(v); + u = Cudd_addIte(dd, x[i], v, u1); + if (u == NULL) { + Cudd_RecursiveDeref(dd, u1); + Cudd_RecursiveDeref(dd, t1); + Cudd_RecursiveDeref(dd, v); + return(NULL); + } + cuddRef(u); + Cudd_RecursiveDeref(dd, v); + if (i>0) { + w = Cudd_addIte(dd, y[i], u1, t1); + if (w == NULL) { + Cudd_RecursiveDeref(dd, u1); + Cudd_RecursiveDeref(dd, t1); + Cudd_RecursiveDeref(dd, u); + return(NULL); + } + cuddRef(w); + t = Cudd_addIte(dd, x[i], w, t1); + if (u == NULL) { + Cudd_RecursiveDeref(dd, u1); + Cudd_RecursiveDeref(dd, t1); + Cudd_RecursiveDeref(dd, u); + Cudd_RecursiveDeref(dd, w); + return(NULL); + } + cuddRef(t); + Cudd_RecursiveDeref(dd, w); + } + Cudd_RecursiveDeref(dd, u1); + Cudd_RecursiveDeref(dd, t1); + } + + cuddDeref(u); + return(u); + +} /* end of addWalshInt */ diff --git a/distr/cudd/cuddAndAbs.c b/distr/cudd/cuddAndAbs.c new file mode 100644 index 0000000..b1cfe27 --- /dev/null +++ b/distr/cudd/cuddAndAbs.c @@ -0,0 +1,373 @@ +/**CFile*********************************************************************** + + FileName [cuddAndAbs.c] + + PackageName [cudd] + + Synopsis [Combined AND and existential abstraction for BDDs] + + Description [External procedures included in this module: +
    +
  • Cudd_bddAndAbstract() +
  • Cudd_bddAndAbstractLimit() +
+ Internal procedures included in this module: +
    +
  • cuddBddAndAbstractRecur() +
] + + 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 */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* 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 + limit, this function returns NULL.] + + SideEffects [None] + + SeeAlso [Cudd_bddAndAbstract] + +******************************************************************************/ +DdNode * +Cudd_bddAndAbstractLimit( + DdManager * manager, + DdNode * f, + DdNode * g, + DdNode * cube, + unsigned int limit) +{ + DdNode *res; + unsigned int saveLimit = manager->maxLive; + + manager->maxLive = (manager->keys - manager->dead) + + (manager->keysZ - manager->deadZ) + limit; + do { + manager->reordered = 0; + res = cuddBddAndAbstractRecur(manager, f, g, cube); + } while (manager->reordered == 1); + manager->maxLive = saveLimit; + return(res); + +} /* end of Cudd_bddAndAbstractLimit */ + + +/*---------------------------------------------------------------------------*/ +/* Definition of internal functions */ +/*---------------------------------------------------------------------------*/ + + +/**Function******************************************************************** + + Synopsis [Takes the AND of two BDDs and simultaneously abstracts the + variables in cube.] + + Description [Takes the AND of two BDDs and simultaneously abstracts + the variables in cube. The variables are existentially abstracted. + Returns a pointer to the result is successful; NULL otherwise.] + + SideEffects [None] + + SeeAlso [Cudd_bddAndAbstract] + +******************************************************************************/ +DdNode * +cuddBddAndAbstractRecur( + DdManager * manager, + DdNode * f, + DdNode * g, + DdNode * cube) +{ + DdNode *F, *ft, *fe, *G, *gt, *ge; + DdNode *one, *zero, *r, *t, *e; + unsigned int topf, topg, topcube, top, index; + + statLine(manager); + one = DD_ONE(manager); + zero = Cudd_Not(one); + + /* Terminal cases. */ + if (f == zero || g == zero || f == Cudd_Not(g)) return(zero); + if (f == one && g == one) return(one); + + if (cube == one) { + return(cuddBddAndRecur(manager, f, g)); + } + if (f == one || f == g) { + return(cuddBddExistAbstractRecur(manager, g, cube)); + } + if (g == one) { + return(cuddBddExistAbstractRecur(manager, f, cube)); + } + /* At this point f, g, and cube are not constant. */ + + if (f > g) { /* Try to increase cache efficiency. */ + DdNode *tmp = f; + f = g; + g = tmp; + } + + /* Here we can skip the use of cuddI, because the operands are known + ** to be non-constant. + */ + F = Cudd_Regular(f); + G = Cudd_Regular(g); + topf = manager->perm[F->index]; + topg = manager->perm[G->index]; + top = ddMin(topf, topg); + topcube = manager->perm[cube->index]; + + while (topcube < top) { + cube = cuddT(cube); + if (cube == one) { + return(cuddBddAndRecur(manager, f, g)); + } + topcube = manager->perm[cube->index]; + } + /* Now, topcube >= top. */ + + /* Check cache. */ + if (F->ref != 1 || G->ref != 1) { + r = cuddCacheLookup(manager, DD_BDD_AND_ABSTRACT_TAG, f, g, cube); + if (r != NULL) { + return(r); + } + } + + if (topf == top) { + index = F->index; + ft = cuddT(F); + fe = cuddE(F); + if (Cudd_IsComplement(f)) { + ft = Cudd_Not(ft); + fe = Cudd_Not(fe); + } + } else { + index = G->index; + ft = fe = f; + } + + if (topg == top) { + gt = cuddT(G); + ge = cuddE(G); + if (Cudd_IsComplement(g)) { + gt = Cudd_Not(gt); + ge = Cudd_Not(ge); + } + } else { + gt = ge = g; + } + + if (topcube == top) { /* quantify */ + DdNode *Cube = cuddT(cube); + t = cuddBddAndAbstractRecur(manager, ft, gt, Cube); + if (t == NULL) return(NULL); + /* Special case: 1 OR anything = 1. Hence, no need to compute + ** the else branch if t is 1. Likewise t + t * anything == t. + ** Notice that t == fe implies that fe does not depend on the + ** variables in Cube. Likewise for t == ge. + */ + if (t == one || t == fe || t == ge) { + if (F->ref != 1 || G->ref != 1) + cuddCacheInsert(manager, DD_BDD_AND_ABSTRACT_TAG, + f, g, cube, t); + return(t); + } + cuddRef(t); + /* Special case: t + !t * anything == t + anything. */ + if (t == Cudd_Not(fe)) { + e = cuddBddExistAbstractRecur(manager, ge, Cube); + } else if (t == Cudd_Not(ge)) { + e = cuddBddExistAbstractRecur(manager, fe, Cube); + } else { + e = cuddBddAndAbstractRecur(manager, fe, ge, Cube); + } + if (e == NULL) { + Cudd_IterDerefBdd(manager, t); + return(NULL); + } + if (t == e) { + r = t; + cuddDeref(t); + } else { + cuddRef(e); + r = cuddBddAndRecur(manager, Cudd_Not(t), Cudd_Not(e)); + if (r == NULL) { + Cudd_IterDerefBdd(manager, t); + Cudd_IterDerefBdd(manager, e); + return(NULL); + } + r = Cudd_Not(r); + cuddRef(r); + Cudd_DelayedDerefBdd(manager, t); + Cudd_DelayedDerefBdd(manager, e); + cuddDeref(r); + } + } else { + t = cuddBddAndAbstractRecur(manager, ft, gt, cube); + if (t == NULL) return(NULL); + cuddRef(t); + e = cuddBddAndAbstractRecur(manager, fe, ge, cube); + if (e == NULL) { + Cudd_IterDerefBdd(manager, t); + return(NULL); + } + if (t == e) { + r = t; + cuddDeref(t); + } else { + cuddRef(e); + if (Cudd_IsComplement(t)) { + r = cuddUniqueInter(manager, (int) index, + Cudd_Not(t), Cudd_Not(e)); + if (r == NULL) { + Cudd_IterDerefBdd(manager, t); + Cudd_IterDerefBdd(manager, e); + return(NULL); + } + r = Cudd_Not(r); + } else { + r = cuddUniqueInter(manager,(int)index,t,e); + if (r == NULL) { + Cudd_IterDerefBdd(manager, t); + Cudd_IterDerefBdd(manager, e); + return(NULL); + } + } + cuddDeref(e); + cuddDeref(t); + } + } + + if (F->ref != 1 || G->ref != 1) + cuddCacheInsert(manager, DD_BDD_AND_ABSTRACT_TAG, f, g, cube, r); + return (r); + +} /* end of cuddBddAndAbstractRecur */ + + +/*---------------------------------------------------------------------------*/ +/* Definition of static functions */ +/*---------------------------------------------------------------------------*/ + diff --git a/distr/cudd/cuddAnneal.c b/distr/cudd/cuddAnneal.c new file mode 100644 index 0000000..7f1f860 --- /dev/null +++ b/distr/cudd/cuddAnneal.c @@ -0,0 +1,814 @@ +/**CFile*********************************************************************** + + FileName [cuddAnneal.c] + + PackageName [cudd] + + Synopsis [Reordering of DDs based on simulated annealing] + + Description [Internal procedures included in this file: +
    +
  • cuddAnnealing() +
+ Static procedures included in this file: +
    +
  • stopping_criterion() +
  • random_generator() +
  • ddExchange() +
  • ddJumpingAux() +
  • ddJumpingUp() +
  • ddJumpingDown() +
  • siftBackwardProb() +
  • copyOrder() +
  • restoreOrder() +
+ ] + + 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 "util.h" +#include "cuddInt.h" + +/*---------------------------------------------------------------------------*/ +/* Constant declarations */ +/*---------------------------------------------------------------------------*/ + +/* Annealing parameters */ +#define BETA 0.6 +#define ALPHA 0.90 +#define EXC_PROB 0.4 +#define JUMP_UP_PROB 0.36 +#define MAXGEN_RATIO 15.0 +#define STOP_TEMP 1.0 + +/*---------------------------------------------------------------------------*/ +/* Stucture declarations */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Type declarations */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Variable declarations */ +/*---------------------------------------------------------------------------*/ + +#ifndef lint +static char rcsid[] DD_UNUSED = "$Id: cuddAnneal.c,v 1.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 = ALLOC(int,nvars); + if (BestOrder == NULL) { + table->errorCode = CUDD_MEMORY_OUT; + return(0); + } + copyOrder(table,BestOrder,lower,upper); + + temp = BETA * size; + maxGen = (int) (MAXGEN_RATIO * nvars); + + c1 = size + 10; + c2 = c1 + 10; + c3 = size; + c4 = c2 + 10; + ecount = ucount = dcount = 0; + + while (!stopping_criterion(c1, c2, c3, c4, temp)) { +#ifdef DD_STATS + (void) fprintf(table->out,"temp=%f\tsize=%d\tgen=%d\t", + temp,size,maxGen); + tosses = acceptances = 0; +#endif + for (innerloop = 0; innerloop < maxGen; innerloop++) { + /* Choose x, y randomly. */ + x = (int) Cudd_Random() % nvars; + do { + y = (int) Cudd_Random() % nvars; + } while (x == y); + x += lower; + y += lower; + if (x > y) { + int tmp = x; + x = y; + y = tmp; + } + + /* Choose move with roulette wheel. */ + rand1 = random_generator(); + if (rand1 < EXC_PROB) { + result = ddExchange(table,x,y,temp); /* exchange */ + ecount++; +#if 0 + (void) fprintf(table->out, + "Exchange of %d and %d: size = %d\n", + x,y,table->keys - table->isolated); +#endif + } else if (rand1 < EXC_PROB + JUMP_UP_PROB) { + result = ddJumpingAux(table,y,x,y,temp); /* jumping_up */ + ucount++; +#if 0 + (void) fprintf(table->out, + "Jump up of %d to %d: size = %d\n", + y,x,table->keys - table->isolated); +#endif + } else { + result = ddJumpingAux(table,x,x,y,temp); /* jumping_down */ + dcount++; +#if 0 + (void) fprintf(table->out, + "Jump down of %d to %d: size = %d\n", + x,y,table->keys - table->isolated); +#endif + } + + if (!result) { + FREE(BestOrder); + return(0); + } + + size = table->keys - table->isolated; /* keep current size */ + if (size < BestCost) { /* update best order */ + BestCost = size; + copyOrder(table,BestOrder,lower,upper); + } + } + c1 = c2; + c2 = c3; + c3 = c4; + c4 = size; + NewTemp = ALPHA * temp; + if (NewTemp >= 1.0) { + maxGen = (int)(log(NewTemp) / log(temp) * maxGen); + } + temp = NewTemp; /* control variable */ +#ifdef DD_STATS + (void) fprintf(table->out,"uphill = %d\taccepted = %d\n", + tosses,acceptances); + fflush(table->out); +#endif + } + + result = restoreOrder(table,BestOrder,lower,upper); + FREE(BestOrder); + if (!result) return(0); +#ifdef DD_STATS + fprintf(table->out,"#:N_EXCHANGE %8d : total exchanges\n",ecount); + fprintf(table->out,"#:N_JUMPUP %8d : total jumps up\n",ucount); + fprintf(table->out,"#:N_JUMPDOWN %8d : total jumps down",dcount); +#endif + return(1); + +} /* end of cuddAnnealing */ + + +/*---------------------------------------------------------------------------*/ +/* Definition of static functions */ +/*---------------------------------------------------------------------------*/ + +/**Function******************************************************************** + + Synopsis [Checks termination condition.] + + Description [If temperature is STOP_TEMP or there is no improvement + then terminates. Returns 1 if the termination criterion is met; 0 + otherwise.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +static int +stopping_criterion( + int c1, + int c2, + int c3, + int c4, + double temp) +{ + if (STOP_TEMP < temp) { + return(0); + } else if ((c1 == c2) && (c1 == c3) && (c1 == c4)) { + return(1); + } else { + return(0); + } + +} /* end of stopping_criterion */ + + +/**Function******************************************************************** + + Synopsis [Random number generator.] + + Description [Returns a double precision value between 0.0 and 1.0.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +static double +random_generator(void) +{ + return((double)(Cudd_Random() / 2147483561.0)); + +} /* end of random_generator */ + + +/**Function******************************************************************** + + Synopsis [This function is for exchanging two variables, x and y.] + + Description [This is the same funcion as ddSwapping except for + comparison expression. Use probability function, exp(-size_change/temp).] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +static int +ddExchange( + DdManager * table, + int x, + int y, + double temp) +{ + Move *move,*moves; + int tmp; + int x_ref,y_ref; + int x_next,y_next; + int size, result; + int initial_size, limit_size; + + x_ref = x; + y_ref = y; + + x_next = cuddNextHigh(table,x); + y_next = cuddNextLow(table,y); + moves = NULL; + initial_size = limit_size = table->keys - table->isolated; + + for (;;) { + if (x_next == y_next) { + size = cuddSwapInPlace(table,x,x_next); + if (size == 0) goto ddExchangeOutOfMem; + move = (Move *)cuddDynamicAllocNode(table); + if (move == NULL) goto ddExchangeOutOfMem; + move->x = x; + move->y = x_next; + move->size = size; + move->next = moves; + moves = move; + size = cuddSwapInPlace(table,y_next,y); + if (size == 0) goto ddExchangeOutOfMem; + move = (Move *)cuddDynamicAllocNode(table); + if (move == NULL) goto ddExchangeOutOfMem; + move->x = y_next; + move->y = y; + move->size = size; + move->next = moves; + moves = move; + size = cuddSwapInPlace(table,x,x_next); + if (size == 0) goto ddExchangeOutOfMem; + move = (Move *)cuddDynamicAllocNode(table); + if (move == NULL) goto ddExchangeOutOfMem; + move->x = x; + move->y = x_next; + move->size = size; + move->next = moves; + moves = move; + + tmp = x; + x = y; + y = tmp; + } else if (x == y_next) { + size = cuddSwapInPlace(table,x,x_next); + if (size == 0) goto ddExchangeOutOfMem; + move = (Move *)cuddDynamicAllocNode(table); + if (move == NULL) goto ddExchangeOutOfMem; + move->x = x; + move->y = x_next; + move->size = size; + move->next = moves; + moves = move; + tmp = x; + x = y; + y = tmp; + } else { + size = cuddSwapInPlace(table,x,x_next); + if (size == 0) goto ddExchangeOutOfMem; + move = (Move *)cuddDynamicAllocNode(table); + if (move == NULL) goto ddExchangeOutOfMem; + move->x = x; + move->y = x_next; + move->size = size; + move->next = moves; + moves = move; + size = cuddSwapInPlace(table,y_next,y); + if (size == 0) goto ddExchangeOutOfMem; + move = (Move *)cuddDynamicAllocNode(table); + if (move == NULL) goto ddExchangeOutOfMem; + move->x = y_next; + move->y = y; + move->size = size; + move->next = moves; + moves = move; + x = x_next; + y = y_next; + } + + x_next = cuddNextHigh(table,x); + y_next = cuddNextLow(table,y); + if (x_next > y_ref) break; + + if ((double) size > DD_MAX_REORDER_GROWTH * (double) limit_size) { + break; + } else if (size < limit_size) { + limit_size = size; + } + } + + if (y_next>=x_ref) { + size = cuddSwapInPlace(table,y_next,y); + if (size == 0) goto ddExchangeOutOfMem; + move = (Move *)cuddDynamicAllocNode(table); + if (move == NULL) goto ddExchangeOutOfMem; + move->x = y_next; + move->y = y; + move->size = size; + move->next = moves; + moves = move; + } + + /* move backward and stop at best position or accept uphill move */ + result = siftBackwardProb(table,moves,initial_size,temp); + if (!result) goto ddExchangeOutOfMem; + + while (moves != NULL) { + move = moves->next; + cuddDeallocMove(table, moves); + moves = move; + } + return(1); + +ddExchangeOutOfMem: + while (moves != NULL) { + move = moves->next; + cuddDeallocMove(table, moves); + moves = move; + } + return(0); + +} /* end of ddExchange */ + + +/**Function******************************************************************** + + Synopsis [Moves a variable to a specified position.] + + Description [If x==x_low, it executes jumping_down. If x==x_high, it + executes jumping_up. This funcion is similar to ddSiftingAux. Returns + 1 in case of success; 0 otherwise.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +static int +ddJumpingAux( + DdManager * table, + int x, + int x_low, + int x_high, + double temp) +{ + Move *move; + Move *moves; /* list of moves */ + int initial_size; + int result; + + initial_size = table->keys - table->isolated; + +#ifdef DD_DEBUG + assert(table->subtables[x].keys > 0); +#endif + + moves = NULL; + + if (cuddNextLow(table,x) < x_low) { + if (cuddNextHigh(table,x) > x_high) return(1); + moves = ddJumpingDown(table,x,x_high,initial_size); + /* after that point x --> x_high unless early termination */ + if (moves == NULL) goto ddJumpingAuxOutOfMem; + /* move backward and stop at best position or accept uphill move */ + result = siftBackwardProb(table,moves,initial_size,temp); + if (!result) goto ddJumpingAuxOutOfMem; + } else if (cuddNextHigh(table,x) > x_high) { + moves = ddJumpingUp(table,x,x_low,initial_size); + /* after that point x --> x_low unless early termination */ + if (moves == NULL) goto ddJumpingAuxOutOfMem; + /* move backward and stop at best position or accept uphill move */ + result = siftBackwardProb(table,moves,initial_size,temp); + if (!result) goto ddJumpingAuxOutOfMem; + } else { + (void) fprintf(table->err,"Unexpected condition in ddJumping\n"); + goto ddJumpingAuxOutOfMem; + } + while (moves != NULL) { + move = moves->next; + cuddDeallocMove(table, moves); + moves = move; + } + return(1); + +ddJumpingAuxOutOfMem: + while (moves != NULL) { + move = moves->next; + cuddDeallocMove(table, moves); + moves = move; + } + return(0); + +} /* end of ddJumpingAux */ + + +/**Function******************************************************************** + + Synopsis [This function is for jumping up.] + + Description [This is a simplified version of ddSiftingUp. It does not + use lower bounding. Returns the set of moves in case of success; NULL + if memory is full.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +static Move * +ddJumpingUp( + DdManager * table, + int x, + int x_low, + int initial_size) +{ + Move *moves; + Move *move; + int y; + int size; + int limit_size = initial_size; + + moves = NULL; + y = cuddNextLow(table,x); + while (y >= x_low) { + size = cuddSwapInPlace(table,y,x); + if (size == 0) goto ddJumpingUpOutOfMem; + move = (Move *)cuddDynamicAllocNode(table); + if (move == NULL) goto ddJumpingUpOutOfMem; + move->x = y; + move->y = x; + move->size = size; + move->next = moves; + moves = move; + if ((double) size > table->maxGrowth * (double) limit_size) { + break; + } else if (size < limit_size) { + limit_size = size; + } + x = y; + y = cuddNextLow(table,x); + } + return(moves); + +ddJumpingUpOutOfMem: + while (moves != NULL) { + move = moves->next; + cuddDeallocMove(table, moves); + moves = move; + } + return(NULL); + +} /* end of ddJumpingUp */ + + +/**Function******************************************************************** + + Synopsis [This function is for jumping down.] + + Description [This is a simplified version of ddSiftingDown. It does not + use lower bounding. Returns the set of moves in case of success; NULL + if memory is full.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +static Move * +ddJumpingDown( + DdManager * table, + int x, + int x_high, + int initial_size) +{ + Move *moves; + Move *move; + int y; + int size; + int limit_size = initial_size; + + moves = NULL; + y = cuddNextHigh(table,x); + while (y <= x_high) { + size = cuddSwapInPlace(table,x,y); + if (size == 0) goto ddJumpingDownOutOfMem; + move = (Move *)cuddDynamicAllocNode(table); + if (move == NULL) goto ddJumpingDownOutOfMem; + move->x = x; + move->y = y; + move->size = size; + move->next = moves; + moves = move; + if ((double) size > table->maxGrowth * (double) limit_size) { + break; + } else if (size < limit_size) { + limit_size = size; + } + x = y; + y = cuddNextHigh(table,x); + } + return(moves); + +ddJumpingDownOutOfMem: + while (moves != NULL) { + move = moves->next; + cuddDeallocMove(table, moves); + moves = move; + } + return(NULL); + +} /* end of ddJumpingDown */ + + +/**Function******************************************************************** + + Synopsis [Returns the DD to the best position encountered during + sifting if there was improvement.] + + Description [Otherwise, "tosses a coin" to decide whether to keep + the current configuration or return the DD to the original + one. Returns 1 in case of success; 0 otherwise.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +static int +siftBackwardProb( + DdManager * table, + Move * moves, + int size, + double temp) +{ + Move *move; + int res; + int best_size = size; + double coin, threshold; + + /* Look for best size during the last sifting */ + for (move = moves; move != NULL; move = move->next) { + if (move->size < best_size) { + best_size = move->size; + } + } + + /* If best_size equals size, the last sifting did not produce any + ** improvement. We now toss a coin to decide whether to retain + ** this change or not. + */ + if (best_size == size) { + coin = random_generator(); +#ifdef DD_STATS + tosses++; +#endif + threshold = exp(-((double)(table->keys - table->isolated - size))/temp); + if (coin < threshold) { +#ifdef DD_STATS + acceptances++; +#endif + return(1); + } + } + + /* Either there was improvement, or we have decided not to + ** accept the uphill move. Go to best position. + */ + res = table->keys - table->isolated; + for (move = moves; move != NULL; move = move->next) { + if (res == best_size) return(1); + res = cuddSwapInPlace(table,(int)move->x,(int)move->y); + if (!res) return(0); + } + + return(1); + +} /* end of sift_backward_prob */ + + +/**Function******************************************************************** + + Synopsis [Copies the current variable order to array.] + + Description [Copies the current variable order to array. + At the same time inverts the permutation.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +static void +copyOrder( + DdManager * table, + int * array, + int lower, + int upper) +{ + int i; + int nvars; + + nvars = upper - lower + 1; + for (i = 0; i < nvars; i++) { + array[i] = table->invperm[i+lower]; + } + +} /* end of copyOrder */ + + +/**Function******************************************************************** + + Synopsis [Restores the variable order in array by a series of sifts up.] + + Description [Restores the variable order in array by a series of sifts up. + Returns 1 in case of success; 0 otherwise.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +static int +restoreOrder( + DdManager * table, + int * array, + int lower, + int upper) +{ + int i, x, y, size; + int nvars = upper - lower + 1; + + for (i = 0; i < nvars; i++) { + x = table->perm[array[i]]; +#ifdef DD_DEBUG + assert(x >= lower && x <= upper); +#endif + y = cuddNextLow(table,x); + while (y >= i + lower) { + size = cuddSwapInPlace(table,y,x); + if (size == 0) return(0); + x = y; + y = cuddNextLow(table,x); + } + } + + return(1); + +} /* end of restoreOrder */ + diff --git a/distr/cudd/cuddApa.c b/distr/cudd/cuddApa.c new file mode 100644 index 0000000..6903d07 --- /dev/null +++ b/distr/cudd/cuddApa.c @@ -0,0 +1,979 @@ +/**CFile*********************************************************************** + + FileName [cuddApa.c] + + PackageName [cudd] + + Synopsis [Arbitrary precision arithmetic functions.] + + Description [External procedures included in this module: +
    +
  • Cudd_ApaNumberOfDigits() +
  • Cudd_NewApaNumber() +
  • Cudd_ApaCopy() +
  • Cudd_ApaAdd() +
  • Cudd_ApaSubtract() +
  • Cudd_ApaShortDivision() +
  • Cudd_ApaIntDivision() +
  • Cudd_ApaShiftRight() +
  • Cudd_ApaSetToLiteral() +
  • Cudd_ApaPowerOfTwo() +
  • Cudd_ApaCompare() +
  • Cudd_ApaCompareRatios() +
  • Cudd_ApaPrintHex() +
  • Cudd_ApaPrintDecimal() +
  • Cudd_ApaPrintExponential() +
  • Cudd_ApaCountMinterm() +
  • Cudd_ApaPrintMinterm() +
  • Cudd_ApaPrintMintermExp() +
  • Cudd_ApaPrintDensity() +
+ Static procedures included in this module: +
    +
  • cuddApaCountMintermAux() +
  • cuddApaStCountfree() +
] + + 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 */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* 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(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 dest.] + + 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 sum.] + + 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 + diff.] + + 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 quotient.] + + 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 quotient.] + + 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 in.] + + SideEffects [The result is returned in parameter b.] + + 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 number.] + + 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 number.] + + SeeAlso [] + +******************************************************************************/ +void +Cudd_ApaPowerOfTwo( + int digits, + DdApaNumber number, + int power) +{ + int i; + int index; + + for (i = 0; i < digits; i++) + number[i] = 0; + i = digits - 1 - power / DD_APA_BITS; + if (i < 0) return; + index = power & (DD_APA_BITS - 1); + number[i] = 1 << index; + +} /* end of Cudd_ApaPowerOfTwo */ + + +/**Function******************************************************************** + + Synopsis [Compares two arbitrary precision integers.] + + Description [Compares two arbitrary precision integers. Returns 1 if + the first number is larger; 0 if they are equal; -1 if the second + number is larger.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +int +Cudd_ApaCompare( + int digitsFirst, + DdApaNumber first, + int digitsSecond, + DdApaNumber second) +{ + int i; + int firstNZ, secondNZ; + + /* Find first non-zero in both numbers. */ + for (firstNZ = 0; firstNZ < digitsFirst; firstNZ++) + if (first[firstNZ] != 0) break; + for (secondNZ = 0; secondNZ < digitsSecond; secondNZ++) + if (second[secondNZ] != 0) break; + if (digitsFirst - firstNZ > digitsSecond - secondNZ) return(1); + else if (digitsFirst - firstNZ < digitsSecond - secondNZ) return(-1); + for (i = 0; i < digitsFirst - firstNZ; i++) { + if (first[firstNZ + i] > second[secondNZ + i]) return(1); + else if (first[firstNZ + i] < second[secondNZ + i]) return(-1); + } + return(0); + +} /* end of Cudd_ApaCompare */ + + +/**Function******************************************************************** + + Synopsis [Compares the ratios of two arbitrary precision integers to two + unsigned ints.] + + Description [Compares the ratios of two arbitrary precision integers + to two unsigned ints. Returns 1 if the first number is larger; 0 if + they are equal; -1 if the second number is larger.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +int +Cudd_ApaCompareRatios( + int digitsFirst, + DdApaNumber firstNum, + unsigned int firstDen, + int digitsSecond, + DdApaNumber secondNum, + unsigned int secondDen) +{ + int result; + DdApaNumber first, second; + unsigned int firstRem, secondRem; + + first = Cudd_NewApaNumber(digitsFirst); + firstRem = Cudd_ApaIntDivision(digitsFirst,firstNum,firstDen,first); + second = Cudd_NewApaNumber(digitsSecond); + secondRem = Cudd_ApaIntDivision(digitsSecond,secondNum,secondDen,second); + result = Cudd_ApaCompare(digitsFirst,first,digitsSecond,second); + FREE(first); + FREE(second); + if (result == 0) { + if ((double)firstRem/firstDen > (double)secondRem/secondDen) + return(1); + else if ((double)firstRem/firstDen < (double)secondRem/secondDen) + return(-1); + } + return(result); + +} /* end of Cudd_ApaCompareRatios */ + + +/**Function******************************************************************** + + Synopsis [Prints an arbitrary precision integer in hexadecimal format.] + + Description [Prints an arbitrary precision integer in hexadecimal format. + Returns 1 if successful; 0 otherwise.] + + SideEffects [None] + + SeeAlso [Cudd_ApaPrintDecimal Cudd_ApaPrintExponential] + +******************************************************************************/ +int +Cudd_ApaPrintHex( + FILE * fp, + int digits, + DdApaNumber number) +{ + int i, result; + + for (i = 0; i < digits; i++) { + result = fprintf(fp,DD_APA_HEXPRINT,number[i]); + if (result == EOF) + return(0); + } + return(1); + +} /* end of Cudd_ApaPrintHex */ + + +/**Function******************************************************************** + + Synopsis [Prints an arbitrary precision integer in decimal format.] + + Description [Prints an arbitrary precision integer in decimal format. + Returns 1 if successful; 0 otherwise.] + + SideEffects [None] + + SeeAlso [Cudd_ApaPrintHex Cudd_ApaPrintExponential] + +******************************************************************************/ +int +Cudd_ApaPrintDecimal( + FILE * fp, + int digits, + DdApaNumber number) +{ + int i, result; + DdApaDigit remainder; + DdApaNumber work; + unsigned char *decimal; + int leadingzero; + int decimalDigits = (int) (digits * log10((double) DD_APA_BASE)) + 1; + + work = Cudd_NewApaNumber(digits); + if (work == NULL) + return(0); + decimal = ALLOC(unsigned char, decimalDigits); + if (decimal == NULL) { + FREE(work); + return(0); + } + Cudd_ApaCopy(digits,number,work); + for (i = decimalDigits - 1; i >= 0; i--) { + remainder = Cudd_ApaShortDivision(digits,work,(DdApaDigit) 10,work); + decimal[i] = (unsigned char) remainder; + } + FREE(work); + + leadingzero = 1; + for (i = 0; i < decimalDigits; i++) { + leadingzero = leadingzero && (decimal[i] == 0); + if ((!leadingzero) || (i == (decimalDigits - 1))) { + result = fprintf(fp,"%1d",decimal[i]); + if (result == EOF) { + FREE(decimal); + return(0); + } + } + } + FREE(decimal); + return(1); + +} /* end of Cudd_ApaPrintDecimal */ + + +/**Function******************************************************************** + + Synopsis [Prints an arbitrary precision integer in exponential format.] + + Description [Prints an arbitrary precision integer in exponential format. + Returns 1 if successful; 0 otherwise.] + + SideEffects [None] + + SeeAlso [Cudd_ApaPrintHex Cudd_ApaPrintDecimal] + +******************************************************************************/ +int +Cudd_ApaPrintExponential( + FILE * fp, + int digits, + DdApaNumber number, + int precision) +{ + int i, first, last, result; + DdApaDigit remainder; + DdApaNumber work; + unsigned char *decimal; + int decimalDigits = (int) (digits * log10((double) DD_APA_BASE)) + 1; + + work = Cudd_NewApaNumber(digits); + if (work == NULL) + return(0); + decimal = ALLOC(unsigned char, decimalDigits); + if (decimal == NULL) { + FREE(work); + return(0); + } + Cudd_ApaCopy(digits,number,work); + first = decimalDigits - 1; + for (i = decimalDigits - 1; i >= 0; i--) { + remainder = Cudd_ApaShortDivision(digits,work,(DdApaDigit) 10,work); + decimal[i] = (unsigned char) remainder; + if (remainder != 0) first = i; /* keep track of MS non-zero */ + } + FREE(work); + last = ddMin(first + precision, decimalDigits); + + for (i = first; i < last; i++) { + result = fprintf(fp,"%s%1d",i == first+1 ? "." : "", decimal[i]); + if (result == EOF) { + FREE(decimal); + return(0); + } + } + FREE(decimal); + result = fprintf(fp,"e+%d",decimalDigits - first - 1); + if (result == EOF) { + return(0); + } + return(1); + +} /* end of Cudd_ApaPrintExponential */ + + +/**Function******************************************************************** + + Synopsis [Counts the number of minterms of a DD.] + + Description [Counts the number of minterms of a DD. The function is + assumed to depend on nvars variables. The minterm count is + represented as an arbitrary precision unsigned integer, to allow for + any number of variables CUDD supports. Returns a pointer to the + array representing the number of minterms of the function rooted at + node if successful; NULL otherwise.] + + SideEffects [The number of digits of the result is returned in + parameter digits.] + + SeeAlso [Cudd_CountMinterm] + +******************************************************************************/ +DdApaNumber +Cudd_ApaCountMinterm( + DdManager * manager, + DdNode * node, + int nvars, + int * digits) +{ + DdApaNumber max, min; + st_table *table; + DdApaNumber i,count; + + background = manager->background; + zero = Cudd_Not(manager->one); + + *digits = Cudd_ApaNumberOfDigits(nvars+1); + max = Cudd_NewApaNumber(*digits); + if (max == NULL) { + return(NULL); + } + Cudd_ApaPowerOfTwo(*digits,max,nvars); + min = Cudd_NewApaNumber(*digits); + if (min == NULL) { + FREE(max); + return(NULL); + } + Cudd_ApaSetToLiteral(*digits,min,0); + table = st_init_table(st_ptrcmp,st_ptrhash); + if (table == NULL) { + FREE(max); + FREE(min); + return(NULL); + } + i = cuddApaCountMintermAux(Cudd_Regular(node),*digits,max,min,table); + if (i == NULL) { + FREE(max); + FREE(min); + st_foreach(table, cuddApaStCountfree, NULL); + st_free_table(table); + return(NULL); + } + count = Cudd_NewApaNumber(*digits); + if (count == NULL) { + FREE(max); + FREE(min); + st_foreach(table, cuddApaStCountfree, NULL); + st_free_table(table); + if (Cudd_Regular(node)->ref == 1) FREE(i); + return(NULL); + } + if (Cudd_IsComplement(node)) { + (void) Cudd_ApaSubtract(*digits,max,i,count); + } else { + Cudd_ApaCopy(*digits,i,count); + } + FREE(max); + FREE(min); + st_foreach(table, cuddApaStCountfree, NULL); + st_free_table(table); + if (Cudd_Regular(node)->ref == 1) FREE(i); + return(count); + +} /* end of Cudd_ApaCountMinterm */ + + +/**Function******************************************************************** + + Synopsis [Prints the number of minterms of a BDD or ADD using + arbitrary precision arithmetic.] + + Description [Prints the number of minterms of a BDD or ADD using + arbitrary precision arithmetic. Returns 1 if successful; 0 otherwise.] + + SideEffects [None] + + SeeAlso [Cudd_ApaPrintMintermExp] + +******************************************************************************/ +int +Cudd_ApaPrintMinterm( + FILE * fp, + DdManager * dd, + DdNode * node, + int nvars) +{ + int digits; + int result; + DdApaNumber count; + + count = Cudd_ApaCountMinterm(dd,node,nvars,&digits); + if (count == NULL) + return(0); + result = Cudd_ApaPrintDecimal(fp,digits,count); + FREE(count); + if (fprintf(fp,"\n") == EOF) { + return(0); + } + return(result); + +} /* end of Cudd_ApaPrintMinterm */ + + +/**Function******************************************************************** + + Synopsis [Prints the number of minterms of a BDD or ADD in exponential + format using arbitrary precision arithmetic.] + + Description [Prints the number of minterms of a BDD or ADD in + exponential format using arbitrary precision arithmetic. Parameter + precision controls the number of signficant digits printed. Returns + 1 if successful; 0 otherwise.] + + SideEffects [None] + + SeeAlso [Cudd_ApaPrintMinterm] + +******************************************************************************/ +int +Cudd_ApaPrintMintermExp( + FILE * fp, + DdManager * dd, + DdNode * node, + int nvars, + int precision) +{ + int digits; + int result; + DdApaNumber count; + + count = Cudd_ApaCountMinterm(dd,node,nvars,&digits); + if (count == NULL) + return(0); + result = Cudd_ApaPrintExponential(fp,digits,count,precision); + FREE(count); + if (fprintf(fp,"\n") == EOF) { + return(0); + } + return(result); + +} /* end of Cudd_ApaPrintMintermExp */ + + +/**Function******************************************************************** + + Synopsis [Prints the density of a BDD or ADD using + arbitrary precision arithmetic.] + + Description [Prints the density of a BDD or ADD using + arbitrary precision arithmetic. Returns 1 if successful; 0 otherwise.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +int +Cudd_ApaPrintDensity( + FILE * fp, + DdManager * dd, + DdNode * node, + int nvars) +{ + int digits; + int result; + DdApaNumber count,density; + unsigned int size, remainder, fractional; + + count = Cudd_ApaCountMinterm(dd,node,nvars,&digits); + if (count == NULL) + return(0); + size = Cudd_DagSize(node); + density = Cudd_NewApaNumber(digits); + remainder = Cudd_ApaIntDivision(digits,count,size,density); + result = Cudd_ApaPrintDecimal(fp,digits,density); + FREE(count); + FREE(density); + fractional = (unsigned int)((double)remainder / size * 1000000); + if (fprintf(fp,".%u\n", fractional) == EOF) { + return(0); + } + return(result); + +} /* end of Cudd_ApaPrintDensity */ + + +/*---------------------------------------------------------------------------*/ +/* Definition of internal functions */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Definition of static functions */ +/*---------------------------------------------------------------------------*/ + + +/**Function******************************************************************** + + Synopsis [Performs the recursive step of Cudd_ApaCountMinterm.] + + Description [Performs the recursive step of Cudd_ApaCountMinterm. + It is based on the following identity. Let |f| be the + number of minterms of f. Then: + + |f| = (|f0|+|f1|)/2 + + where f0 and f1 are the two cofactors of f. + Uses the identity |f'| = max - |f|. + The procedure expects the argument "node" to be a regular pointer, and + guarantees this condition is met in the recursive calls. + For efficiency, the result of a call is cached only if the node has + a reference count greater than 1. + Returns the number of minterms of the function rooted at node.] + + SideEffects [None] + +******************************************************************************/ +static DdApaNumber +cuddApaCountMintermAux( + DdNode * node, + int digits, + DdApaNumber max, + DdApaNumber min, + st_table * table) +{ + DdNode *Nt, *Ne; + DdApaNumber mint, mint1, mint2; + DdApaDigit carryout; + + if (cuddIsConstant(node)) { + if (node == background || node == zero) { + return(min); + } else { + return(max); + } + } + if (node->ref > 1 && st_lookup(table, node, &mint)) { + return(mint); + } + + Nt = cuddT(node); Ne = cuddE(node); + + mint1 = cuddApaCountMintermAux(Nt, digits, max, min, table); + if (mint1 == NULL) return(NULL); + mint2 = cuddApaCountMintermAux(Cudd_Regular(Ne), digits, max, min, table); + if (mint2 == NULL) { + if (Nt->ref == 1) FREE(mint1); + return(NULL); + } + mint = Cudd_NewApaNumber(digits); + if (mint == NULL) { + if (Nt->ref == 1) FREE(mint1); + if (Cudd_Regular(Ne)->ref == 1) FREE(mint2); + return(NULL); + } + if (Cudd_IsComplement(Ne)) { + (void) Cudd_ApaSubtract(digits,max,mint2,mint); + carryout = Cudd_ApaAdd(digits,mint1,mint,mint); + } else { + carryout = Cudd_ApaAdd(digits,mint1,mint2,mint); + } + Cudd_ApaShiftRight(digits,carryout,mint,mint); + /* If the refernce count of a child is 1, its minterm count + ** hasn't been stored in table. Therefore, it must be explicitly + ** freed here. */ + if (Nt->ref == 1) FREE(mint1); + if (Cudd_Regular(Ne)->ref == 1) FREE(mint2); + + if (node->ref > 1) { + if (st_insert(table, (char *)node, (char *)mint) == ST_OUT_OF_MEM) { + FREE(mint); + return(NULL); + } + } + return(mint); + +} /* end of cuddApaCountMintermAux */ + + +/**Function******************************************************************** + + Synopsis [Frees the memory used to store the minterm counts recorded + in the visited table.] + + Description [Frees the memory used to store the minterm counts + recorded in the visited table. Returns ST_CONTINUE.] + + SideEffects [None] + +******************************************************************************/ +static enum st_retval +cuddApaStCountfree( + char * key, + char * value, + char * arg) +{ + DdApaNumber d; + + d = (DdApaNumber) value; + FREE(d); + return(ST_CONTINUE); + +} /* end of cuddApaStCountfree */ diff --git a/distr/cudd/cuddApprox.c b/distr/cudd/cuddApprox.c new file mode 100644 index 0000000..9155e1d --- /dev/null +++ b/distr/cudd/cuddApprox.c @@ -0,0 +1,2205 @@ +/**CFile*********************************************************************** + + FileName [cuddApprox.c] + + PackageName [cudd] + + Synopsis [Procedures to approximate a given BDD.] + + Description [External procedures provided by this module: +
    +
  • Cudd_UnderApprox() +
  • Cudd_OverApprox() +
  • Cudd_RemapUnderApprox() +
  • Cudd_RemapOverApprox() +
  • Cudd_BiasedUnderApprox() +
  • Cudd_BiasedOverApprox() +
+ Internal procedures included in this module: +
    +
  • cuddUnderApprox() +
  • cuddRemapUnderApprox() +
  • cuddBiasedUnderApprox() +
+ Static procedures included in this module: +
    +
  • gatherInfoAux() +
  • gatherInfo() +
  • computeSavings() +
  • UAmarkNodes() +
  • UAbuildSubset() +
  • updateRefs() +
  • RAmarkNodes() +
  • BAmarkNodes() +
  • RAbuildSubset() +
+ ] + + 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 +#else +#define DBL_MAX_EXP 1024 +#endif +#include "util.h" +#include "cuddInt.h" + +/*---------------------------------------------------------------------------*/ +/* 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: +
    +
  • collect information on each node in the BDD; this is done via DFS. +
  • traverse the BDD in top-down fashion and compute for each node + whether its elimination increases density. +
  • traverse the BDD via DFS and actually perform the elimination. +
+ 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"); + FREE(info->page); + st_free_table(info->table); + 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 + FREE(info->page); + st_free_table(info->table); + 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: +
    +
  • collect information on each node in the BDD; this is done via DFS. +
  • traverse the BDD in top-down fashion and compute for each node + whether remapping increases density. +
  • traverse the BDD via DFS and actually perform the elimination. +
+ 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"); + FREE(info->page); + st_free_table(info->table); + 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 + FREE(info->page); + st_free_table(info->table); + 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: +
    +
  • collect information on each node in the BDD; this is done via DFS. +
  • traverse the BDD in top-down fashion and compute for each node + whether remapping increases density. +
  • traverse the BDD via DFS and actually perform the elimination. +
+ 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); + FREE(info->page); + st_free_table(info->table); + 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"); + FREE(info->page); + st_free_table(info->table); + 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 + FREE(info->page); + st_free_table(info->table); + 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, node, &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, N, &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 = 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 = ALLOC(NodeData,info->size); + if (info->page == NULL) { + dd->errorCode = CUDD_MEMORY_OUT; + 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) { + FREE(info->page); + 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) { + FREE(info->page); + 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) { + FREE(info->page); + st_free_table(info->table); + 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, node, &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, node, &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, node, &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, skip, &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, node, &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, cuddT(node), &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, Cudd_Regular(cuddE(node)), &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, node, &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, N, &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, node, &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, T, &infoT); + (void) st_lookup(info->table, E, &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, T, &infoT); + (void) st_lookup(info->table, Ereg, &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, Cudd_Regular(shared), &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, node, &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, T, &infoT); + (void) st_lookup(info->table, E, &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, T, &infoT); + (void) st_lookup(info->table, Ereg, &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, Cudd_Regular(shared), &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, N, &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, f, &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 */ diff --git a/distr/cudd/cuddBddAbs.c b/distr/cudd/cuddBddAbs.c new file mode 100644 index 0000000..4b3060b --- /dev/null +++ b/distr/cudd/cuddBddAbs.c @@ -0,0 +1,715 @@ +/**CFile*********************************************************************** + + FileName [cuddBddAbs.c] + + PackageName [cudd] + + Synopsis [Quantification functions for BDDs.] + + Description [External procedures included in this module: +
    +
  • Cudd_bddExistAbstract() +
  • Cudd_bddXorExistAbstract() +
  • Cudd_bddUnivAbstract() +
  • Cudd_bddBooleanDiff() +
  • Cudd_bddVarIsDependent() +
+ Internal procedures included in this module: +
    +
  • cuddBddExistAbstractRecur() +
  • cuddBddXorExistAbstractRecur() +
  • cuddBddBooleanDiffRecur() +
+ Static procedures included in this module: +
    +
  • bddCheckPositiveCube() +
+ ] + + 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 */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* 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); + } + cuddDeref(res1); + cuddDeref(res2); + if (F->ref != 1) + cuddCacheInsert2(manager, Cudd_bddExistAbstract, f, cube, res); + return(res); + } + +} /* end of cuddBddExistAbstractRecur */ + + +/**Function******************************************************************** + + Synopsis [Takes the exclusive OR of two BDDs and simultaneously abstracts the + variables in cube.] + + Description [Takes the exclusive OR of two BDDs and simultaneously abstracts + the variables in cube. The variables are existentially abstracted. Returns a + pointer to the result is successful; NULL otherwise.] + + SideEffects [None] + + SeeAlso [Cudd_bddAndAbstract] + +******************************************************************************/ +DdNode * +cuddBddXorExistAbstractRecur( + DdManager * manager, + DdNode * f, + DdNode * g, + DdNode * cube) +{ + DdNode *F, *fv, *fnv, *G, *gv, *gnv; + DdNode *one, *zero, *r, *t, *e, *Cube; + unsigned int topf, topg, topcube, top, index; + + statLine(manager); + one = DD_ONE(manager); + zero = Cudd_Not(one); + + /* Terminal cases. */ + if (f == g) { + return(zero); + } + if (f == Cudd_Not(g)) { + return(one); + } + if (cube == one) { + return(cuddBddXorRecur(manager, f, g)); + } + if (f == one) { + return(cuddBddExistAbstractRecur(manager, Cudd_Not(g), cube)); + } + if (g == one) { + return(cuddBddExistAbstractRecur(manager, Cudd_Not(f), cube)); + } + if (f == zero) { + return(cuddBddExistAbstractRecur(manager, g, cube)); + } + if (g == zero) { + return(cuddBddExistAbstractRecur(manager, f, cube)); + } + + /* At this point f, g, and cube are not constant. */ + + if (f > g) { /* Try to increase cache efficiency. */ + DdNode *tmp = f; + f = g; + g = tmp; + } + + /* Check cache. */ + r = cuddCacheLookup(manager, DD_BDD_XOR_EXIST_ABSTRACT_TAG, f, g, cube); + if (r != NULL) { + return(r); + } + + /* Here we can skip the use of cuddI, because the operands are known + ** to be non-constant. + */ + F = Cudd_Regular(f); + topf = manager->perm[F->index]; + G = Cudd_Regular(g); + topg = manager->perm[G->index]; + top = ddMin(topf, topg); + topcube = manager->perm[cube->index]; + + if (topcube < top) { + return(cuddBddXorExistAbstractRecur(manager, f, g, cuddT(cube))); + } + /* Now, topcube >= top. */ + + if (topf == top) { + index = F->index; + fv = cuddT(F); + fnv = cuddE(F); + if (Cudd_IsComplement(f)) { + fv = Cudd_Not(fv); + fnv = Cudd_Not(fnv); + } + } else { + index = G->index; + fv = fnv = f; + } + + if (topg == top) { + gv = cuddT(G); + gnv = cuddE(G); + if (Cudd_IsComplement(g)) { + gv = Cudd_Not(gv); + gnv = Cudd_Not(gnv); + } + } else { + gv = gnv = g; + } + + if (topcube == top) { + Cube = cuddT(cube); + } else { + Cube = cube; + } + + t = cuddBddXorExistAbstractRecur(manager, fv, gv, Cube); + if (t == NULL) return(NULL); + + /* Special case: 1 OR anything = 1. Hence, no need to compute + ** the else branch if t is 1. + */ + if (t == one && topcube == top) { + cuddCacheInsert(manager, DD_BDD_XOR_EXIST_ABSTRACT_TAG, f, g, cube, one); + return(one); + } + cuddRef(t); + + e = cuddBddXorExistAbstractRecur(manager, fnv, gnv, Cube); + if (e == NULL) { + Cudd_IterDerefBdd(manager, t); + return(NULL); + } + cuddRef(e); + + if (topcube == top) { /* abstract */ + r = cuddBddAndRecur(manager, Cudd_Not(t), Cudd_Not(e)); + if (r == NULL) { + Cudd_IterDerefBdd(manager, t); + Cudd_IterDerefBdd(manager, e); + return(NULL); + } + r = Cudd_Not(r); + cuddRef(r); + Cudd_IterDerefBdd(manager, t); + Cudd_IterDerefBdd(manager, e); + cuddDeref(r); + } else if (t == e) { + r = t; + cuddDeref(t); + cuddDeref(e); + } else { + if (Cudd_IsComplement(t)) { + r = cuddUniqueInter(manager,(int)index,Cudd_Not(t),Cudd_Not(e)); + if (r == NULL) { + Cudd_IterDerefBdd(manager, t); + Cudd_IterDerefBdd(manager, e); + return(NULL); + } + r = Cudd_Not(r); + } else { + r = cuddUniqueInter(manager,(int)index,t,e); + if (r == NULL) { + Cudd_IterDerefBdd(manager, t); + Cudd_IterDerefBdd(manager, e); + return(NULL); + } + } + cuddDeref(e); + cuddDeref(t); + } + cuddCacheInsert(manager, DD_BDD_XOR_EXIST_ABSTRACT_TAG, f, g, cube, r); + return (r); + +} /* end of cuddBddXorExistAbstractRecur */ + + +/**Function******************************************************************** + + Synopsis [Performs the recursive steps of Cudd_bddBoleanDiff.] + + Description [Performs the recursive steps of Cudd_bddBoleanDiff. + Returns the BDD obtained by XORing the cofactors of f with respect to + var if successful; NULL otherwise. Exploits the fact that dF/dx = + dF'/dx.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +DdNode * +cuddBddBooleanDiffRecur( + DdManager * manager, + DdNode * f, + DdNode * var) +{ + DdNode *T, *E, *res, *res1, *res2; + + statLine(manager); + if (cuddI(manager,f->index) > manager->perm[var->index]) { + /* f does not depend on var. */ + return(Cudd_Not(DD_ONE(manager))); + } + + /* From now on, f is non-constant. */ + + /* If the two indices are the same, so are their levels. */ + if (f->index == var->index) { + res = cuddBddXorRecur(manager, cuddT(f), cuddE(f)); + return(res); + } + + /* From now on, cuddI(manager,f->index) < cuddI(manager,cube->index). */ + + /* Check the cache. */ + res = cuddCacheLookup2(manager, cuddBddBooleanDiffRecur, f, var); + if (res != NULL) { + return(res); + } + + /* Compute the cofactors of f. */ + T = cuddT(f); E = cuddE(f); + + res1 = cuddBddBooleanDiffRecur(manager, T, var); + if (res1 == NULL) return(NULL); + cuddRef(res1); + res2 = cuddBddBooleanDiffRecur(manager, Cudd_Regular(E), var); + if (res2 == NULL) { + Cudd_IterDerefBdd(manager, res1); + return(NULL); + } + cuddRef(res2); + /* ITE takes care of possible complementation of res1 and of the + ** case in which res1 == res2. */ + res = cuddBddIteRecur(manager, manager->vars[f->index], res1, res2); + if (res == NULL) { + Cudd_IterDerefBdd(manager, res1); + Cudd_IterDerefBdd(manager, res2); + return(NULL); + } + cuddDeref(res1); + cuddDeref(res2); + cuddCacheInsert2(manager, cuddBddBooleanDiffRecur, f, var, res); + return(res); + +} /* end of cuddBddBooleanDiffRecur */ + + +/*---------------------------------------------------------------------------*/ +/* Definition of static functions */ +/*---------------------------------------------------------------------------*/ + +/**Function******************************************************************** + + Synopsis [Checks whether cube is an BDD representing the product of + positive literals.] + + Description [Returns 1 in case of success; 0 otherwise.] + + SideEffects [None] + +******************************************************************************/ +static int +bddCheckPositiveCube( + DdManager * manager, + DdNode * cube) +{ + if (Cudd_IsComplement(cube)) return(0); + if (cube == DD_ONE(manager)) return(1); + if (cuddIsConstant(cube)) return(0); + if (cuddE(cube) == Cudd_Not(DD_ONE(manager))) { + return(bddCheckPositiveCube(manager, cuddT(cube))); + } + return(0); + +} /* end of bddCheckPositiveCube */ + diff --git a/distr/cudd/cuddBddCorr.c b/distr/cudd/cuddBddCorr.c new file mode 100644 index 0000000..a04b4f1 --- /dev/null +++ b/distr/cudd/cuddBddCorr.c @@ -0,0 +1,515 @@ +/**CFile*********************************************************************** + + FileName [cuddBddCorr.c] + + PackageName [cudd] + + Synopsis [Correlation between BDDs.] + + Description [External procedures included in this module: +
    +
  • Cudd_bddCorrelation() +
  • Cudd_bddCorrelationWeights() +
+ Static procedures included in this module: +
    +
  • bddCorrelationAux() +
  • bddCorrelationWeightsAux() +
  • CorrelCompare() +
  • CorrelHash() +
  • CorrelCleanUp() +
+ ] + + 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 */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* 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 (char *key, int modulus); +static enum st_retval CorrelCleanUp (char *key, char *value, char *arg); + +/**AutomaticEnd***************************************************************/ + +#ifdef __cplusplus +} +#endif + + +/*---------------------------------------------------------------------------*/ +/* Definition of exported functions */ +/*---------------------------------------------------------------------------*/ + + +/**Function******************************************************************** + + Synopsis [Computes the correlation of f and g.] + + Description [Computes the correlation of f and g. If f == g, their + correlation is 1. If f == g', their correlation is 0. Returns the + fraction of minterms in the ON-set of the EXNOR of f and g. If it + runs out of memory, returns (double)CUDD_OUT_OF_MEM.] + + SideEffects [None] + + SeeAlso [Cudd_bddCorrelationWeights] + +******************************************************************************/ +double +Cudd_bddCorrelation( + DdManager * manager, + DdNode * f, + DdNode * g) +{ + + st_table *table; + double correlation; + +#ifdef CORREL_STATS + num_calls = 0; +#endif + + table = st_init_table(CorrelCompare,CorrelHash); + if (table == NULL) return((double)CUDD_OUT_OF_MEM); + correlation = bddCorrelationAux(manager,f,g,table); + st_foreach(table, CorrelCleanUp, NIL(char)); + st_free_table(table); + return(correlation); + +} /* end of Cudd_bddCorrelation */ + + +/**Function******************************************************************** + + Synopsis [Computes the correlation of f and g for given input + probabilities.] + + Description [Computes the correlation of f and g for given input + probabilities. On input, prob\[i\] is supposed to contain the + probability of the i-th input variable to be 1. + If f == g, their correlation is 1. If f == g', their + correlation is 0. Returns the probability that f and g have the same + value. If it runs out of memory, returns (double)CUDD_OUT_OF_MEM. The + correlation of f and the constant one gives the probability of f.] + + SideEffects [None] + + SeeAlso [Cudd_bddCorrelation] + +******************************************************************************/ +double +Cudd_bddCorrelationWeights( + DdManager * manager, + DdNode * f, + DdNode * g, + double * prob) +{ + + st_table *table; + double correlation; + +#ifdef CORREL_STATS + num_calls = 0; +#endif + + table = st_init_table(CorrelCompare,CorrelHash); + if (table == NULL) return((double)CUDD_OUT_OF_MEM); + correlation = bddCorrelationWeightsAux(manager,f,g,prob,table); + st_foreach(table, CorrelCleanUp, NIL(char)); + st_free_table(table); + return(correlation); + +} /* end of Cudd_bddCorrelationWeights */ + + +/*---------------------------------------------------------------------------*/ +/* Definition of internal functions */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Definition of static functions */ +/*---------------------------------------------------------------------------*/ + + +/**Function******************************************************************** + + Synopsis [Performs the recursive step of Cudd_bddCorrelation.] + + Description [Performs the recursive step of Cudd_bddCorrelation. + Returns the fraction of minterms in the ON-set of the EXNOR of f and + g.] + + SideEffects [None] + + SeeAlso [bddCorrelationWeightsAux] + +******************************************************************************/ +static double +bddCorrelationAux( + DdManager * dd, + DdNode * f, + DdNode * g, + st_table * table) +{ + DdNode *Fv, *Fnv, *G, *Gv, *Gnv; + double min, *pmin, min1, min2, *dummy; + HashEntry *entry; + unsigned int topF, topG; + + statLine(dd); +#ifdef CORREL_STATS + num_calls++; +#endif + + /* Terminal cases: only work for BDDs. */ + if (f == g) return(1.0); + if (f == Cudd_Not(g)) return(0.0); + + /* Standardize call using the following properties: + ** (f EXNOR g) = (g EXNOR f) + ** (f' EXNOR g') = (f EXNOR g). + */ + if (f > g) { + DdNode *tmp = f; + f = g; g = tmp; + } + if (Cudd_IsComplement(f)) { + f = Cudd_Not(f); + g = Cudd_Not(g); + } + /* From now on, f is regular. */ + + entry = ALLOC(HashEntry,1); + if (entry == NULL) { + dd->errorCode = CUDD_MEMORY_OUT; + return(CUDD_OUT_OF_MEM); + } + entry->f = f; entry->g = g; + + /* We do not use the fact that + ** correlation(f,g') = 1 - correlation(f,g) + ** to minimize the risk of cancellation. + */ + if (st_lookup(table, entry, &dummy)) { + min = *dummy; + FREE(entry); + return(min); + } + + G = Cudd_Regular(g); + topF = cuddI(dd,f->index); topG = cuddI(dd,G->index); + if (topF <= topG) { Fv = cuddT(f); Fnv = cuddE(f); } else { Fv = Fnv = f; } + if (topG <= topF) { Gv = cuddT(G); Gnv = cuddE(G); } else { Gv = Gnv = G; } + + if (g != G) { + Gv = Cudd_Not(Gv); + Gnv = Cudd_Not(Gnv); + } + + min1 = bddCorrelationAux(dd, Fv, Gv, table) / 2.0; + if (min1 == (double)CUDD_OUT_OF_MEM) { + FREE(entry); + return(CUDD_OUT_OF_MEM); + } + min2 = bddCorrelationAux(dd, Fnv, Gnv, table) / 2.0; + if (min2 == (double)CUDD_OUT_OF_MEM) { + FREE(entry); + return(CUDD_OUT_OF_MEM); + } + min = (min1+min2); + + pmin = ALLOC(double,1); + if (pmin == NULL) { + dd->errorCode = CUDD_MEMORY_OUT; + return((double)CUDD_OUT_OF_MEM); + } + *pmin = min; + + if (st_insert(table,(char *)entry, (char *)pmin) == ST_OUT_OF_MEM) { + FREE(entry); + FREE(pmin); + return((double)CUDD_OUT_OF_MEM); + } + return(min); + +} /* end of bddCorrelationAux */ + + +/**Function******************************************************************** + + Synopsis [Performs the recursive step of Cudd_bddCorrelationWeigths.] + + Description [] + + SideEffects [None] + + SeeAlso [bddCorrelationAux] + +******************************************************************************/ +static double +bddCorrelationWeightsAux( + DdManager * dd, + DdNode * f, + DdNode * g, + double * prob, + st_table * table) +{ + DdNode *Fv, *Fnv, *G, *Gv, *Gnv; + double min, *pmin, min1, min2, *dummy; + HashEntry *entry; + int topF, topG, index; + + statLine(dd); +#ifdef CORREL_STATS + num_calls++; +#endif + + /* Terminal cases: only work for BDDs. */ + if (f == g) return(1.0); + if (f == Cudd_Not(g)) return(0.0); + + /* Standardize call using the following properties: + ** (f EXNOR g) = (g EXNOR f) + ** (f' EXNOR g') = (f EXNOR g). + */ + if (f > g) { + DdNode *tmp = f; + f = g; g = tmp; + } + if (Cudd_IsComplement(f)) { + f = Cudd_Not(f); + g = Cudd_Not(g); + } + /* From now on, f is regular. */ + + entry = ALLOC(HashEntry,1); + if (entry == NULL) { + dd->errorCode = CUDD_MEMORY_OUT; + return((double)CUDD_OUT_OF_MEM); + } + entry->f = f; entry->g = g; + + /* We do not use the fact that + ** correlation(f,g') = 1 - correlation(f,g) + ** to minimize the risk of cancellation. + */ + if (st_lookup(table, entry, &dummy)) { + min = *dummy; + FREE(entry); + return(min); + } + + G = Cudd_Regular(g); + topF = cuddI(dd,f->index); topG = cuddI(dd,G->index); + if (topF <= topG) { + Fv = cuddT(f); Fnv = cuddE(f); + index = f->index; + } else { + Fv = Fnv = f; + index = G->index; + } + if (topG <= topF) { Gv = cuddT(G); Gnv = cuddE(G); } else { Gv = Gnv = G; } + + if (g != G) { + Gv = Cudd_Not(Gv); + Gnv = Cudd_Not(Gnv); + } + + min1 = bddCorrelationWeightsAux(dd, Fv, Gv, prob, table) * prob[index]; + if (min1 == (double)CUDD_OUT_OF_MEM) { + FREE(entry); + return((double)CUDD_OUT_OF_MEM); + } + min2 = bddCorrelationWeightsAux(dd, Fnv, Gnv, prob, table) * (1.0 - prob[index]); + if (min2 == (double)CUDD_OUT_OF_MEM) { + FREE(entry); + return((double)CUDD_OUT_OF_MEM); + } + min = (min1+min2); + + pmin = ALLOC(double,1); + if (pmin == NULL) { + dd->errorCode = CUDD_MEMORY_OUT; + return((double)CUDD_OUT_OF_MEM); + } + *pmin = min; + + if (st_insert(table,(char *)entry, (char *)pmin) == ST_OUT_OF_MEM) { + FREE(entry); + FREE(pmin); + return((double)CUDD_OUT_OF_MEM); + } + return(min); + +} /* end of bddCorrelationWeightsAux */ + + +/**Function******************************************************************** + + Synopsis [Compares two hash table entries.] + + Description [Compares two hash table entries. Returns 0 if they are + identical; 1 otherwise.] + + SideEffects [None] + +******************************************************************************/ +static int +CorrelCompare( + const char * key1, + const char * key2) +{ + HashEntry *entry1; + HashEntry *entry2; + + entry1 = (HashEntry *) key1; + entry2 = (HashEntry *) key2; + if (entry1->f != entry2->f || entry1->g != entry2->g) return(1); + + return(0); + +} /* end of CorrelCompare */ + + +/**Function******************************************************************** + + Synopsis [Hashes a hash table entry.] + + Description [Hashes a hash table entry. It is patterned after + st_strhash. Returns a value between 0 and modulus.] + + SideEffects [None] + +******************************************************************************/ +static int +CorrelHash( + char * key, + int modulus) +{ + HashEntry *entry; + int val = 0; + + entry = (HashEntry *) key; +#if SIZEOF_VOID_P == 8 && SIZEOF_INT == 4 + val = ((int) ((long)entry->f))*997 + ((int) ((long)entry->g)); +#else + val = ((int) entry->f)*997 + ((int) entry->g); +#endif + + return ((val < 0) ? -val : val) % modulus; + +} /* end of CorrelHash */ + + +/**Function******************************************************************** + + Synopsis [Frees memory associated with hash table.] + + Description [Frees memory associated with hash table. Returns + ST_CONTINUE.] + + SideEffects [None] + +******************************************************************************/ +static enum st_retval +CorrelCleanUp( + char * key, + char * value, + char * arg) +{ + double *d; + HashEntry *entry; + + entry = (HashEntry *) key; + FREE(entry); + d = (double *)value; + FREE(d); + return ST_CONTINUE; + +} /* end of CorrelCleanUp */ + diff --git a/distr/cudd/cuddBddIte.c b/distr/cudd/cuddBddIte.c new file mode 100644 index 0000000..127e236 --- /dev/null +++ b/distr/cudd/cuddBddIte.c @@ -0,0 +1,1317 @@ +/**CFile*********************************************************************** + + FileName [cuddBddIte.c] + + PackageName [cudd] + + Synopsis [BDD ITE function and satellites.] + + Description [External procedures included in this module: +
    +
  • Cudd_bddIte() +
  • Cudd_bddIteConstant() +
  • Cudd_bddIntersect() +
  • Cudd_bddAnd() +
  • Cudd_bddAndLimit() +
  • Cudd_bddOr() +
  • Cudd_bddNand() +
  • Cudd_bddNor() +
  • Cudd_bddXor() +
  • Cudd_bddXnor() +
  • Cudd_bddLeq() +
+ Internal procedures included in this module: +
    +
  • cuddBddIteRecur() +
  • cuddBddIntersectRecur() +
  • cuddBddAndRecur() +
  • cuddBddXorRecur() +
+ Static procedures included in this module: +
    +
  • bddVarToConst() +
  • bddVarToCanonical() +
  • bddVarToCanonicalSimple() +
] + + 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 */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* 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 limit 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) && g < 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; + 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 (f > 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 (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); + } + + /* 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 (f > 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 && f > 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 && f > 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 && f > 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 */ + diff --git a/distr/cudd/cuddBridge.c b/distr/cudd/cuddBridge.c new file mode 100644 index 0000000..fbc7064 --- /dev/null +++ b/distr/cudd/cuddBridge.c @@ -0,0 +1,1016 @@ +/**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: +
    +
  • Cudd_addBddThreshold() +
  • Cudd_addBddStrictThreshold() +
  • Cudd_addBddInterval() +
  • Cudd_addBddIthBit() +
  • Cudd_BddToAdd() +
  • Cudd_addBddPattern() +
  • Cudd_bddTransfer() +
+ Internal procedures included in this file: +
    +
  • cuddBddTransfer() +
  • cuddAddBddDoPattern() +
+ Static procedures included in this file: +
    +
  • addBddDoThreshold() +
  • addBddDoStrictThreshold() +
  • addBddDoInterval() +
  • addBddDoIthBit() +
  • ddBddToAddRecur() +
  • cuddBddTransferRecur() +
+ ] + + 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 */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* 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, &key, &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, f, &res)) + return(Cudd_NotCond(res,comple)); + + /* 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 */ + diff --git a/distr/cudd/cuddCache.c b/distr/cudd/cuddCache.c new file mode 100644 index 0000000..739e6da --- /dev/null +++ b/distr/cudd/cuddCache.c @@ -0,0 +1,1050 @@ +/**CFile*********************************************************************** + + FileName [cuddCache.c] + + PackageName [cudd] + + Synopsis [Functions for cache insertion and lookup.] + + Description [Internal procedures included in this module: +
    +
  • cuddInitCache() +
  • cuddCacheInsert() +
  • cuddCacheInsert2() +
  • cuddCacheLookup() +
  • cuddCacheLookupZdd() +
  • cuddCacheLookup2() +
  • cuddCacheLookup2Zdd() +
  • cuddConstantLookup() +
  • cuddCacheProfile() +
  • cuddCacheResize() +
  • cuddCacheFlush() +
  • cuddComputeFloorLog2() +
+ Static procedures included in this module: +
    +
] + + 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 */ +/*---------------------------------------------------------------------------*/ + +#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 = ALLOC(DdCache,cacheSize+1); + 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); + unique->cache = (DdCache *) mem; + assert(((ptruint) unique->cache & (sizeof(DdCache) - 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; + register DdCache *entry; + ptruint uf, ug, uh; + + uf = (ptruint) f | (op & 0xe); + ug = (ptruint) g | (op >> 4); + uh = (ptruint) h; + + posn = ddCHash2(uh,uf,ug,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 + +} /* 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; + register DdCache *entry; + + posn = ddCHash2(op,f,g,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 + +} /* 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; + register DdCache *entry; + + posn = ddCHash2(op,f,f,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 + +} /* 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; + + uf = (ptruint) f | (op & 0xe); + ug = (ptruint) g | (op >> 4); + uh = (ptruint) h; + + cache = table->cache; +#ifdef DD_DEBUG + if (cache == NULL) { + return(NULL); + } +#endif + + posn = ddCHash2(uh,uf,ug,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; + + uf = (ptruint) f | (op & 0xe); + ug = (ptruint) g | (op >> 4); + uh = (ptruint) h; + + cache = table->cache; +#ifdef DD_DEBUG + if (cache == NULL) { + return(NULL); + } +#endif + + posn = ddCHash2(uh,uf,ug,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,f,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,f,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,f,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,f,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; + + uf = (ptruint) f | (op & 0xe); + ug = (ptruint) g | (op >> 4); + uh = (ptruint) h; + + cache = table->cache; +#ifdef DD_DEBUG + if (cache == NULL) { + return(NULL); + } +#endif + posn = ddCHash2(uh,uf,ug,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 = ALLOC(double, nbins); + if (hystogramQ == NULL) { + table->errorCode = CUDD_MEMORY_OUT; + return(0); + } + hystogramR = ALLOC(double, nbins); + if (hystogramR == NULL) { + 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); + } + + FREE(hystogramQ); + 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 = ALLOC(DdCache,slots+1); + 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); +#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); + 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 + moved++; + } + } + + 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 */ +/*---------------------------------------------------------------------------*/ diff --git a/distr/cudd/cuddCheck.c b/distr/cudd/cuddCheck.c new file mode 100644 index 0000000..74eed40 --- /dev/null +++ b/distr/cudd/cuddCheck.c @@ -0,0 +1,879 @@ +/**CFile*********************************************************************** + + FileName [cuddCheck.c] + + PackageName [cudd] + + Synopsis [Functions to check consistency of data structures.] + + Description [External procedures included in this module: +
    +
  • Cudd_DebugCheck() +
  • Cudd_CheckKeys() +
+ Internal procedures included in this module: +
    +
  • cuddHeapProfile() +
  • cuddPrintNode() +
  • cuddPrintVarGroups() +
+ Static procedures included in this module: +
    +
  • debugFindParent() +
+ ] + + 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 */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* 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: +
    +
  • node has illegal index +
  • live node has dead children +
  • node has illegal Then or Else pointers +
  • BDD/ADD node has identical children +
  • ZDD node has zero then child +
  • wrong number of total nodes +
  • wrong number of dead nodes +
  • ref count error at node +
+ 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, &f, &count)) { + if (count > (int)(f->ref) && f->ref != DD_MAXREF) { +#if SIZEOF_VOID_P == 8 + fprintf(table->err,"ref count error at node 0x%lx, count = %d, id = %u, ref = %u, then = 0x%lx, else = 0x%lx\n",(ptruint)f,count,f->index,f->ref,(ptruint)cuddT(f),(ptruint)cuddE(f)); +#else + fprintf(table->err,"ref count error at node 0x%x, count = %d, id = %hu, ref = %hu, then = 0x%x, else = 0x%x\n",(ptruint)f,count,f->index,f->ref,(ptruint)cuddT(f),(ptruint)cuddE(f)); +#endif + debugFindParent(table,f); + flag = 1; + } + } + st_free_gen(gen); + st_free_table(edgeTable); + + return (flag); + +} /* end of Cudd_DebugCheck */ + + +/**Function******************************************************************** + + Synopsis [Checks for several conditions that should not occur.] + + Description [Checks for the following conditions: +
    +
  • Wrong sizes of subtables. +
  • Wrong number of keys found in unique subtable. +
  • Wrong number of dead found in unique subtable. +
  • Wrong number of keys found in the constant table +
  • Wrong number of dead found in the constant table +
  • Wrong number of total slots found +
  • Wrong number of maximum keys found +
  • Wrong number of total dead found +
+ 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: +
    +
  • total number of tables; +
  • number of tables with live nodes; +
  • table with the largest number of live nodes; +
  • number of nodes in that table. +
+ 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; iout,"%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. +
    +
  • F: MTR_FIXED +
  • N: MTR_NEWNODE +
  • S: MTR_SOFT +
+ 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;jout,"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;jref != 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 diff --git a/distr/cudd/cuddClip.c b/distr/cudd/cuddClip.c new file mode 100644 index 0000000..30111b0 --- /dev/null +++ b/distr/cudd/cuddClip.c @@ -0,0 +1,558 @@ +/**CFile*********************************************************************** + + FileName [cuddClip.c] + + PackageName [cudd] + + Synopsis [Clipping functions.] + + Description [External procedures included in this module: +
    +
  • Cudd_bddClippingAnd() +
  • Cudd_bddClippingAndAbstract() +
+ Internal procedures included in this module: +
    +
  • cuddBddClippingAnd() +
  • cuddBddClippingAndAbstract() +
+ Static procedures included in this module: +
    +
  • cuddBddClippingAndRecur() +
  • cuddBddClipAndAbsRecur() +
+ + 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 */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* 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 */ + diff --git a/distr/cudd/cuddCof.c b/distr/cudd/cuddCof.c new file mode 100644 index 0000000..571efcd --- /dev/null +++ b/distr/cudd/cuddCof.c @@ -0,0 +1,327 @@ +/**CFile*********************************************************************** + + FileName [cuddCof.c] + + PackageName [cudd] + + Synopsis [Cofactoring functions.] + + Description [External procedures included in this module: +
    +
  • Cudd_Cofactor() +
+ Internal procedures included in this module: +
    +
  • cuddGetBranches() +
  • cuddCheckCube() +
  • cuddCofactorRecur() +
+ ] + + 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 */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* 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 */ +/*---------------------------------------------------------------------------*/ + diff --git a/distr/cudd/cuddCompose.c b/distr/cudd/cuddCompose.c new file mode 100644 index 0000000..2cd77e8 --- /dev/null +++ b/distr/cudd/cuddCompose.c @@ -0,0 +1,1749 @@ +/**CFile*********************************************************************** + + FileName [cuddCompose.c] + + PackageName [cudd] + + Synopsis [Functional composition and variable permutation of DDs.] + + Description [External procedures included in this module: +
    +
  • Cudd_bddCompose() +
  • Cudd_addCompose() +
  • Cudd_addPermute() +
  • Cudd_addSwapVariables() +
  • Cudd_bddPermute() +
  • Cudd_bddVarMap() +
  • Cudd_SetVarMap() +
  • Cudd_bddSwapVariables() +
  • Cudd_bddAdjPermuteX() +
  • Cudd_addVectorCompose() +
  • Cudd_addGeneralVectorCompose() +
  • Cudd_addNonSimCompose() +
  • Cudd_bddVectorCompose() +
+ Internal procedures included in this module: +
    +
  • cuddBddComposeRecur() +
  • cuddAddComposeRecur() +
+ Static procedures included in this module: +
    +
  • cuddAddPermuteRecur() +
  • cuddBddPermuteRecur() +
  • cuddBddVarMapRecur() +
  • cuddAddVectorComposeRecur() +
  • cuddAddGeneralVectorComposeRecur() +
  • cuddAddNonSimComposeRecur() +
  • cuddBddVectorComposeRecur() +
  • ddIsIthAddVar() +
  • ddIsIthAddVarPair() +
+ 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 "util.h" +#include "cuddInt.h" + + +/*---------------------------------------------------------------------------*/ +/* 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 = 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); + 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 = 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 = 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); + 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 = 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); + 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.

+ 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.

+ 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)); + } + + /* 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 = ALLOC(DdNode *,lastsub); + if (vect1 == NULL) { + dd->errorCode = CUDD_MEMORY_OUT; + Cudd_RecursiveDeref(dd,key1); + return(NULL); + } + vect0 = ALLOC(DdNode *,lastsub); + if (vect0 == NULL) { + dd->errorCode = CUDD_MEMORY_OUT; + Cudd_RecursiveDeref(dd,key1); + 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); + FREE(vect1); + if (T == NULL) { + Cudd_RecursiveDeref(dd,key1); + FREE(vect0); + return(NULL); + } + cuddRef(T); + E = cuddAddNonSimComposeRecur(dd,f0,vect0,key0,cube1,lastsub); + 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 */ diff --git a/distr/cudd/cuddDecomp.c b/distr/cudd/cuddDecomp.c new file mode 100644 index 0000000..2d3c4ea --- /dev/null +++ b/distr/cudd/cuddDecomp.c @@ -0,0 +1,2177 @@ +/**CFile*********************************************************************** + + FileName [cuddDecomp.c] + + PackageName [cudd] + + Synopsis [Functions for BDD decomposition.] + + Description [External procedures included in this file: +

    +
  • Cudd_bddApproxConjDecomp() +
  • Cudd_bddApproxDisjDecomp() +
  • Cudd_bddIterConjDecomp() +
  • Cudd_bddIterDisjDecomp() +
  • Cudd_bddGenConjDecomp() +
  • Cudd_bddGenDisjDecomp() +
  • Cudd_bddVarConjDecomp() +
  • Cudd_bddVarDisjDecomp() +
+ Static procedures included in this module: +
    +
  • cuddConjunctsAux() +
  • CreateBotDist() +
  • BuildConjuncts() +
  • ConjunctsFree() +
] + + 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 "util.h" +#include "cuddInt.h" + +/*---------------------------------------------------------------------------*/ +/* 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 = 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 = 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 = 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 = 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 = 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 = 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 = 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 = 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 = 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 f is the function of the BDD and + x is the variable, the decomposition is + (f+x)(f+x'). 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 = 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 = 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 = 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 = 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 f is the function of the + BDD and x is the variable, the decomposition is + f*x + f*x'. 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, N, &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 = 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, node, &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 = 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); + 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 = 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) { + 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 = 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) { + FREE(factors); + return(NULL); + } + } + } else { + value = 1; + if (st_insert(ghTable, (char *)Cudd_Regular(factors->g), + (char *)(long)value) == ST_OUT_OF_MEM) { + 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) { + FREE(factors); + return(NULL); + } + } + } else { + value = 2; + if (st_insert(ghTable, (char *)Cudd_Regular(factors->h), + (char *)(long)value) == ST_OUT_OF_MEM) { + FREE(factors); + return(NULL); + } + } + } + + /* Store factors in cache table for later use. */ + if (st_insert(cacheTable, (char *)node, (char *)factors) == + ST_OUT_OF_MEM) { + 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 = 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; + 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; + 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; + 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; + 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; + 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; + 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; + 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; + 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; + 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; + 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; + 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; + 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; + 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 = 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); + 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 = 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); + 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, *factorsNnv, *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 = 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, node, &dummy)) { + factors = dummy; + return(factors); + } + + /* check distance and local reference count of this node */ + N = Cudd_Regular(node); + if (!st_lookup(distanceTable, N, &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 = 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; + 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; + 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, Nv, &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, Nnv, &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) 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) 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) 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) FREE(factorsNv); + if (freeNnv) 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) FREE(factorsNv); + if (freeNnv) 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) FREE(factorsNv); + if (freeNnv) 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) FREE(factorsNv); + if (freeNnv) FREE(factorsNnv); + return(NULL); + } + cuddRef(h2); + Cudd_RecursiveDeref(dd, factorsNv->h); + Cudd_RecursiveDeref(dd, factorsNnv->g); + if (freeNv) FREE(factorsNv); + if (freeNnv) 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 = 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, (char **)&key, (char **)&value)) { + 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, (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, (char **)&key, (char **)&value)) { + 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, (char **)&key, (char **)&value)) { + 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) 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, (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, (char **)&key, (char **)&value)) { + 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, (char **)&key, (char **)&value)) { + 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, (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 */ diff --git a/distr/cudd/cuddEssent.c b/distr/cudd/cuddEssent.c new file mode 100644 index 0000000..f053f86 --- /dev/null +++ b/distr/cudd/cuddEssent.c @@ -0,0 +1,1467 @@ +/**CFile*********************************************************************** + + FileName [cuddEssent.c] + + PackageName [cudd] + + Synopsis [Functions for the detection of essential variables.] + + Description [External procedures included in this file: +
    +
  • Cudd_FindEssential() +
  • Cudd_bddIsVarEssential() +
  • Cudd_FindTwoLiteralClauses() +
  • Cudd_ReadIthClause() +
  • Cudd_PrintTwoLiteralClauses() +
  • Cudd_tlcInfoFree() +
+ Static procedures included in this module: +
    +
  • ddFindEssentialRecur() +
  • ddFindTwoLiteralClausesRecur() +
  • computeClauses() +
  • computeClausesWithUniverse() +
  • emptyClauseSet() +
  • sentinelp() +
  • equalp() +
  • beforep() +
  • oneliteralp() +
  • impliedp() +
  • bitVectorAlloc() +
  • bitVectorClear() +
  • bitVectorFree() +
  • bitVectorRead() +
  • bitVectorSet() +
  • tlcInfoAlloc() +
] + + 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 */ +/*---------------------------------------------------------------------------*/ + +/* 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, &node, &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) FREE(t->vars); + if (t->phases != NULL) FREE(t->phases); + 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, f, &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 = ALLOC(DdHalfWord,4); + if (res->vars == NULL) { + FREE(res); + return(NULL); + } + res->phases = bitVectorAlloc(2); + if (res->phases == NULL) { + FREE(res->vars); + 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 = ALLOC(DdHalfWord,4); + if (res->vars == NULL) { + FREE(res); + return(NULL); + } + res->phases = bitVectorAlloc(2); + if (res->phases == NULL) { + FREE(res->vars); + 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) { + 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 = 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 = 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 = 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 = 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 = 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 = 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 = 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 = 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; + } + FREE(tclauses); + tclauses = nextclause; + } else { + TlClause *nextclause = eclauses->next; + TlClause *otherclauses = tclauses; + while (otherclauses != NULL) { + if (eclauses->v1 != otherclauses->v1) { + newclause = 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; + } + FREE(eclauses); + eclauses = nextclause; + } + } + while (tclauses != NULL) { + TlClause *nextclause = tclauses->next; + FREE(tclauses); + tclauses = nextclause; + } + while (eclauses != NULL) { + TlClause *nextclause = eclauses->next; + 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 = 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; + 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; + FREE(nclauses); + nclauses = nextclause; + } + } + assert(cv == 0); + + return(res); + + cleanup: + if (res != NULL) Cudd_tlcInfoFree(res); + while (iclauses != NULL) { + TlClause *nextclause = iclauses->next; + FREE(iclauses); + iclauses = nextclause; + } + while (nclauses != NULL) { + TlClause *nextclause = nclauses->next; + FREE(nclauses); + nclauses = nextclause; + } + while (tclauses != NULL) { + TlClause *nextclause = tclauses->next; + FREE(tclauses); + tclauses = nextclause; + } + while (eclauses != NULL) { + TlClause *nextclause = eclauses->next; + 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 = 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) 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 = ALLOC(DdTlcInfo,1); + if (eset == NULL) return(NULL); + eset->vars = ALLOC(DdHalfWord,2); + if (eset->vars == NULL) { + 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 = 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) +{ + 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 = ALLOC(DdTlcInfo,1); + if (res == NULL) return(NULL); + res->vars = NULL; + res->phases = NULL; + res->cnt = 0; + return(res); + +} /* end of tlcInfoAlloc */ diff --git a/distr/cudd/cuddExact.c b/distr/cudd/cuddExact.c new file mode 100644 index 0000000..716fb41 --- /dev/null +++ b/distr/cudd/cuddExact.c @@ -0,0 +1,1020 @@ +/**CFile*********************************************************************** + + FileName [cuddExact.c] + + PackageName [cudd] + + Synopsis [Functions for exact variable reordering.] + + Description [External procedures included in this file: +
    +
+ Internal procedures included in this module: +
    +
  • cuddExact() +
+ Static procedures included in this module: +
    +
  • getMaxBinomial() +
  • gcd() +
  • getMatrix() +
  • freeMatrix() +
  • getLevelKeys() +
  • ddShuffle() +
  • ddSiftUp() +
  • updateUB() +
  • ddCountRoots() +
  • ddClearGlobal() +
  • computeLB() +
  • updateEntry() +
  • pushDown() +
  • initSymmInfo() +
] + + 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 "util.h" +#include "cuddInt.h" + +/*---------------------------------------------------------------------------*/ +/* 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 = ALLOC(int, maxBinomial); + if (newCost == NULL) goto cuddExactOutOfMem; + + oldOrder = getMatrix(maxBinomial, size); + if (oldOrder == NULL) goto cuddExactOutOfMem; + + oldCost = ALLOC(int, maxBinomial); + if (oldCost == NULL) goto cuddExactOutOfMem; + + bestOrder = ALLOC(DdHalfWord, size); + if (bestOrder == NULL) goto cuddExactOutOfMem; + + mask = 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); + FREE(bestOrder); + FREE(oldCost); + FREE(newCost); + FREE(symmInfo); + FREE(mask); + return(1); + +cuddExactOutOfMem: + + if (newOrder != NULL) freeMatrix(newOrder); + if (oldOrder != NULL) freeMatrix(oldOrder); + if (bestOrder != NULL) FREE(bestOrder); + if (oldCost != NULL) FREE(oldCost); + if (newCost != NULL) FREE(newCost); + if (symmInfo != NULL) FREE(symmInfo); + if (mask != NULL) 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 +
+    binomial(n,k) = n/k * binomial(n-1,k-1).
+  
+ 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 = ALLOC(DdHalfWord *, rows); + if (matrix == NULL) return(NULL); + matrix[0] = ALLOC(DdHalfWord, cols*rows); + if (matrix[0] == NULL) { + 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) +{ + FREE(matrix[0]); + 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: +
    +
  • size of the lower part of it; +
  • size of the part of the upper part not subjected to reordering; +
  • number of roots in the part of the BDD subjected to reordering; +
  • variable in the support of the roots in the upper part of the + BDD subjected to reordering. +
      ] + + 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 = 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 */ diff --git a/distr/cudd/cuddExport.c b/distr/cudd/cuddExport.c new file mode 100644 index 0000000..73d90d2 --- /dev/null +++ b/distr/cudd/cuddExport.c @@ -0,0 +1,1389 @@ +/**CFile*********************************************************************** + + FileName [cuddExport.c] + + PackageName [cudd] + + Synopsis [Export functions.] + + Description [External procedures included in this module: +
        +
      • Cudd_DumpBlif() +
      • Cudd_DumpBlifBody() +
      • Cudd_DumpDot() +
      • Cudd_DumpDaVinci() +
      • Cudd_DumpDDcal() +
      • Cudd_DumpFactoredForm() +
      + Internal procedures included in this module: +
        +
      + Static procedures included in this module: +
        +
      • ddDoDumpBlif() +
      • ddDoDumpDaVinci() +
      • ddDoDumpDDcal() +
      • ddDoDumpFactoredForm() +
      ] + + 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 */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* 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 = 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) { + 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; + } + } + 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) 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: +
        +
      • solid line: THEN arcs; +
      • dotted line: complement arcs; +
      • dashed line: regular ELSE arcs. +
      + 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 = 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, &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,"\"%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; + /* Account for the possible complement on the root. */ + if (Cudd_IsComplement(f[i])) { + retval = fprintf(fp," -> \"%p\" [style = dotted];\n", + (void *) ((mask & (ptrint) f[i]) / sizeof(DdNode))); + } else { + 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->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, + "\"%p\" -> \"%p\";\n", + (void *) ((mask & (ptrint) scan) / + sizeof(DdNode)), + (void *) ((mask & (ptrint) cuddT(scan)) / + sizeof(DdNode))); + if (retval == EOF) goto failure; + if (Cudd_IsComplement(cuddE(scan))) { + retval = fprintf(fp, + "\"%p\" -> \"%p\" [style = dotted];\n", + (void *) ((mask & (ptrint) scan) / + sizeof(DdNode)), + (void *) ((mask & (ptrint) cuddE(scan)) / + sizeof(DdNode))); + } else { + 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); + FREE(sorted); + return(1); + +failure: + if (sorted != NULL) 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, &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, &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); + + /* Build a bit array with the support of f. */ + sorted = 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; + } + 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; + + st_free_table(visited); + return(1); + +failure: + if (sorted != NULL) 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 */ diff --git a/distr/cudd/cuddGenCof.c b/distr/cudd/cuddGenCof.c new file mode 100644 index 0000000..714a007 --- /dev/null +++ b/distr/cudd/cuddGenCof.c @@ -0,0 +1,2175 @@ +/**CFile*********************************************************************** + + FileName [cuddGenCof.c] + + PackageName [cudd] + + Synopsis [Generalized cofactors for BDDs and ADDs.] + + Description [External procedures included in this module: +
        +
      • Cudd_bddConstrain() +
      • Cudd_bddRestrict() +
      • Cudd_bddNPAnd() +
      • Cudd_addConstrain() +
      • Cudd_bddConstrainDecomp() +
      • Cudd_addRestrict() +
      • Cudd_bddCharToVect() +
      • Cudd_bddLICompaction() +
      • Cudd_bddSqueeze() +
      • Cudd_SubsetCompress() +
      • Cudd_SupersetCompress() +
      + Internal procedures included in this module: +
        +
      • cuddBddConstrainRecur() +
      • cuddBddRestrictRecur() +
      • cuddBddNPAndRecur() +
      • cuddAddConstrainRecur() +
      • cuddAddRestrictRecur() +
      • cuddBddLICompaction() +
      + Static procedures included in this module: +
        +
      • cuddBddConstrainDecomp() +
      • cuddBddCharToVect() +
      • cuddBddLICMarkEdges() +
      • cuddBddLICBuildResult() +
      • cuddBddSqueeze() +
      + ] + + 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 */ +/*---------------------------------------------------------------------------*/ + +/* 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 (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: +
        +
      • f @ 0 = 0 +
      • f @ 1 = f +
      • 0 @ c = 0 +
      • 1 @ c = 1 +
      • f @ f = 1 +
      • f @ f'= 0 +
      + 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: +
        +
      • F @ 0 = 0 +
      • F @ 1 = F +
      • 0 @ c = 0 +
      • 1 @ c = 1 +
      • F @ F = 1 +
      + 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 = 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) { + 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 = 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) { + 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 + f of a function to be minimized and a BDD + c representing the care set, Cudd_bddLICompaction + produces the BDD of a function that agrees with f + wherever c is 1. Safe minimization means that the size + of the result is guaranteed not to exceed the size of + f. 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 + l and u, 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 f over + c.] + + Description [Finds a small BDD that agrees with f over + c. 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 f.] + + Description [Finds a dense subset of BDD f. 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 f.] + + Description [Finds a dense superset of BDD f. 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 + f of a function to be minimized and a BDD + c representing the care set, Cudd_bddLICompaction + produces the BDD of a function that agrees with f + wherever c is 1. Safe minimization means that the size + of the result is guaranteed not to exceed the size of + f. 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 f + 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 = 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)) { + 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) { + FREE(key); + return(CUDD_OUT_OF_MEM); + } + resE = cuddBddLICMarkEdges(dd, Fnv, Cnv, table, cache); + if (resE == CUDD_OUT_OF_MEM) { + 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 { + 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) { + 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, f, &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( + 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; + 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 */ diff --git a/distr/cudd/cuddGenetic.c b/distr/cudd/cuddGenetic.c new file mode 100644 index 0000000..4ce3031 --- /dev/null +++ b/distr/cudd/cuddGenetic.c @@ -0,0 +1,957 @@ +/**CFile*********************************************************************** + + FileName [cuddGenetic.c] + + PackageName [cudd] + + Synopsis [Genetic algorithm for variable reordering.] + + Description [Internal procedures included in this file: +
        +
      • cuddGa() +
      + Static procedures included in this module: +
        +
      • make_random() +
      • sift_up() +
      • build_dd() +
      • largest() +
      • rand_int() +
      • array_hash() +
      • array_compare() +
      • find_best() +
      • find_average_fitness() +
      • PMX() +
      • roulette() +
      + + 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 "util.h" +#include "cuddInt.h" + +/*---------------------------------------------------------------------------*/ +/* Constant declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Stucture declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Type declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Variable declarations */ +/*---------------------------------------------------------------------------*/ + +#ifndef lint +static char rcsid[] DD_UNUSED = "$Id: cuddGenetic.c,v 1.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 (char *array, int modulus); +static int array_compare (const char *array1, const char *array2); +static int find_best (void); +#ifdef DD_STATS +static double find_average_fitness (void); +#endif +static int PMX (int maxvar); +static int roulette (int *p1, int *p2); + +/**AutomaticEnd***************************************************************/ + +#ifdef __cplusplus +} +#endif + +/*---------------------------------------------------------------------------*/ +/* Definition of exported functions */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Definition of internal functions */ +/*---------------------------------------------------------------------------*/ + + +/**Function******************************************************************** + + Synopsis [Genetic algorithm for DD reordering.] + + Description [Genetic algorithm for DD reordering. + The two children of a crossover will be stored in + storedd[popsize] and storedd[popsize+1] --- the last two slots in the + storedd array. (This will make comparisons and replacement easy.) + Returns 1 in case of success; 0 otherwise.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +int +cuddGa( + DdManager * table /* manager */, + int lower /* lowest level to be reordered */, + int upper /* highest level to be reorderded */) +{ + int i,n,m; /* dummy/loop vars */ + int index; +#ifdef DD_STATS + double average_fitness; +#endif + int small; /* index of smallest DD in population */ + + /* Do an initial sifting to produce at least one reasonable individual. */ + if (!cuddSifting(table,lower,upper)) return(0); + + /* Get the initial values. */ + numvars = upper - lower + 1; /* number of variables to be reordered */ + if (table->populationSize == 0) { + popsize = 3 * numvars; /* population size is 3 times # of vars */ + if (popsize > 120) { + popsize = 120; /* Maximum population size is 120 */ + } + } else { + popsize = table->populationSize; /* user specified value */ + } + if (popsize < 4) popsize = 4; /* enforce minimum population size */ + + /* Allocate population table. */ + storedd = ALLOC(int,(popsize+2)*(numvars+1)); + if (storedd == NULL) { + table->errorCode = CUDD_MEMORY_OUT; + return(0); + } + + /* Initialize the computed table. This table is made up of two data + ** structures: A hash table with the key given by the order, which says + ** if a given order is present in the population; and the repeat + ** vector, which says how many copies of a given order are stored in + ** the population table. If there are multiple copies of an order, only + ** one has a repeat count greater than 1. This copy is the one pointed + ** by the computed table. + */ + repeat = ALLOC(int,popsize); + if (repeat == NULL) { + table->errorCode = CUDD_MEMORY_OUT; + FREE(storedd); + return(0); + } + for (i = 0; i < popsize; i++) { + repeat[i] = 0; + } + computed = st_init_table(array_compare,array_hash); + if (computed == NULL) { + table->errorCode = CUDD_MEMORY_OUT; + FREE(storedd); + FREE(repeat); + return(0); + } + + /* Copy the current DD and its size to the population table. */ + for (i = 0; i < numvars; i++) { + STOREDD(0,i) = table->invperm[i+lower]; /* order of initial DD */ + } + STOREDD(0,numvars) = table->keys - table->isolated; /* size of initial DD */ + + /* Store the initial order in the computed table. */ + if (st_insert(computed,(char *)storedd,(char *) 0) == ST_OUT_OF_MEM) { + FREE(storedd); + FREE(repeat); + st_free_table(computed); + return(0); + } + repeat[0]++; + + /* Insert the reverse order as second element of the population. */ + for (i = 0; i < numvars; i++) { + STOREDD(1,numvars-1-i) = table->invperm[i+lower]; /* reverse order */ + } + + /* Now create the random orders. make_random fills the population + ** table with random permutations. The successive loop builds and sifts + ** the DDs for the reverse order and each random permutation, and stores + ** the results in the computed table. + */ + if (!make_random(table,lower)) { + table->errorCode = CUDD_MEMORY_OUT; + FREE(storedd); + FREE(repeat); + st_free_table(computed); + return(0); + } + for (i = 1; i < popsize; i++) { + result = build_dd(table,i,lower,upper); /* build and sift order */ + if (!result) { + FREE(storedd); + FREE(repeat); + st_free_table(computed); + return(0); + } + if (st_lookup_int(computed,(char *)&STOREDD(i,0),&index)) { + repeat[index]++; + } else { + if (st_insert(computed,(char *)&STOREDD(i,0),(char *)(long)i) == + ST_OUT_OF_MEM) { + FREE(storedd); + FREE(repeat); + st_free_table(computed); + return(0); + } + repeat[i]++; + } + } + +#if 0 +#ifdef DD_STATS + /* Print the initial population. */ + (void) fprintf(table->out,"Initial population after sifting\n"); + for (m = 0; m < popsize; m++) { + for (i = 0; i < numvars; i++) { + (void) fprintf(table->out," %2d",STOREDD(m,i)); + } + (void) fprintf(table->out," : %3d (%d)\n", + STOREDD(m,numvars),repeat[m]); + } +#endif +#endif + + small = find_best(); +#ifdef DD_STATS + average_fitness = find_average_fitness(); + (void) fprintf(table->out,"\nInitial population: best fitness = %d, average fitness %8.3f",STOREDD(small,numvars),average_fitness); +#endif + + /* Decide how many crossovers should be tried. */ + if (table->numberXovers == 0) { + cross = 3*numvars; + if (cross > 60) { /* do a maximum of 50 crossovers */ + cross = 60; + } + } else { + cross = table->numberXovers; /* use user specified value */ + } + + /* Perform the crossovers to get the best order. */ + for (m = 0; m < cross; m++) { + if (!PMX(table->size)) { /* perform one crossover */ + table->errorCode = CUDD_MEMORY_OUT; + FREE(storedd); + FREE(repeat); + st_free_table(computed); + return(0); + } + /* The offsprings are left in the last two entries of the + ** population table. These are now considered in turn. + */ + for (i = popsize; i <= popsize+1; i++) { + result = build_dd(table,i,lower,upper); /* build and sift child */ + if (!result) { + FREE(storedd); + FREE(repeat); + st_free_table(computed); + return(0); + } + large = largest(); /* find the largest DD in population */ + + /* If the new child is smaller than the largest DD in the current + ** population, enter it into the population in place of the + ** largest DD. + */ + if (STOREDD(i,numvars) < STOREDD(large,numvars)) { + /* Look up the largest DD in the computed table. + ** Decrease its repetition count. If the repetition count + ** goes to 0, remove the largest DD from the computed table. + */ + result = st_lookup_int(computed,(char *)&STOREDD(large,0), + &index); + if (!result) { + FREE(storedd); + FREE(repeat); + st_free_table(computed); + return(0); + } + repeat[index]--; + if (repeat[index] == 0) { + int *pointer = &STOREDD(index,0); + result = st_delete(computed, &pointer, NULL); + if (!result) { + FREE(storedd); + FREE(repeat); + st_free_table(computed); + return(0); + } + } + /* Copy the new individual to the entry of the + ** population table just made available and update the + ** computed table. + */ + for (n = 0; n <= numvars; n++) { + STOREDD(large,n) = STOREDD(i,n); + } + if (st_lookup_int(computed,(char *)&STOREDD(large,0), + &index)) { + repeat[index]++; + } else { + if (st_insert(computed,(char *)&STOREDD(large,0), + (char *)(long)large) == ST_OUT_OF_MEM) { + FREE(storedd); + FREE(repeat); + st_free_table(computed); + return(0); + } + repeat[large]++; + } + } + } + } + + /* Find the smallest DD in the population and build it; + ** that will be the result. + */ + small = find_best(); + + /* Print stats on the final population. */ +#ifdef DD_STATS + average_fitness = find_average_fitness(); + (void) fprintf(table->out,"\nFinal population: best fitness = %d, average fitness %8.3f",STOREDD(small,numvars),average_fitness); +#endif + + /* Clean up, build the result DD, and return. */ + st_free_table(computed); + computed = NULL; + result = build_dd(table,small,lower,upper); + FREE(storedd); + FREE(repeat); + return(result); + +} /* end of cuddGa */ + + +/*---------------------------------------------------------------------------*/ +/* Definition of static functions */ +/*---------------------------------------------------------------------------*/ + +/**Function******************************************************************** + + Synopsis [Generates the random sequences for the initial population.] + + Description [Generates the random sequences for the initial population. + The sequences are permutations of the indices between lower and + upper in the current order.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +static int +make_random( + DdManager * table, + int lower) +{ + int i,j; /* loop variables */ + int *used; /* is a number already in a permutation */ + int next; /* next random number without repetitions */ + + used = ALLOC(int,numvars); + if (used == NULL) { + table->errorCode = CUDD_MEMORY_OUT; + return(0); + } +#if 0 +#ifdef DD_STATS + (void) fprintf(table->out,"Initial population before sifting\n"); + for (i = 0; i < 2; i++) { + for (j = 0; j < numvars; j++) { + (void) fprintf(table->out," %2d",STOREDD(i,j)); + } + (void) fprintf(table->out,"\n"); + } +#endif +#endif + for (i = 2; i < popsize; i++) { + for (j = 0; j < numvars; j++) { + used[j] = 0; + } + /* Generate a permutation of {0...numvars-1} and use it to + ** permute the variables in the layesr from lower to upper. + */ + for (j = 0; j < numvars; j++) { + do { + next = rand_int(numvars-1); + } while (used[next] != 0); + used[next] = 1; + STOREDD(i,j) = table->invperm[next+lower]; + } +#if 0 +#ifdef DD_STATS + /* Print the order just generated. */ + for (j = 0; j < numvars; j++) { + (void) fprintf(table->out," %2d",STOREDD(i,j)); + } + (void) fprintf(table->out,"\n"); +#endif +#endif + } + FREE(used); + return(1); + +} /* end of make_random */ + + +/**Function******************************************************************** + + Synopsis [Moves one variable up.] + + Description [Takes a variable from position x and sifts it up to + position x_low; x_low should be less than x. Returns 1 if successful; + 0 otherwise] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +static int +sift_up( + DdManager * table, + int x, + int x_low) +{ + int y; + int size; + + y = cuddNextLow(table,x); + while (y >= x_low) { + size = cuddSwapInPlace(table,y,x); + if (size == 0) { + return(0); + } + x = y; + y = cuddNextLow(table,x); + } + return(1); + +} /* end of sift_up */ + + +/**Function******************************************************************** + + Synopsis [Builds a DD from a given order.] + + Description [Builds a DD from a given order. This procedure also + sifts the final order and inserts into the array the size in nodes + of the result. Returns 1 if successful; 0 otherwise.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +static int +build_dd( + DdManager * table, + int num /* the index of the individual to be built */, + int lower, + int upper) +{ + int i,j; /* loop vars */ + int position; + int index; + int limit; /* how large the DD for this order can grow */ + int size; + + /* Check the computed table. If the order already exists, it + ** suffices to copy the size from the existing entry. + */ + if (computed && st_lookup_int(computed,(char *)&STOREDD(num,0),&index)) { + STOREDD(num,numvars) = STOREDD(index,numvars); +#ifdef DD_STATS + (void) fprintf(table->out,"\nCache hit for index %d", index); +#endif + return(1); + } + + /* Stop if the DD grows 20 times larges than the reference size. */ + limit = 20 * STOREDD(0,numvars); + + /* Sift up the variables so as to build the desired permutation. + ** First the variable that has to be on top is sifted to the top. + ** Then the variable that has to occupy the secon position is sifted + ** up to the second position, and so on. + */ + for (j = 0; j < numvars; j++) { + i = STOREDD(num,j); + position = table->perm[i]; + result = sift_up(table,position,j+lower); + if (!result) return(0); + size = table->keys - table->isolated; + if (size > limit) break; + } + + /* Sift the DD just built. */ +#ifdef DD_STATS + (void) fprintf(table->out,"\n"); +#endif + result = cuddSifting(table,lower,upper); + if (!result) return(0); + + /* Copy order and size to table. */ + for (j = 0; j < numvars; j++) { + STOREDD(num,j) = table->invperm[lower+j]; + } + STOREDD(num,numvars) = table->keys - table->isolated; /* size of new DD */ + return(1); + +} /* end of build_dd */ + + +/**Function******************************************************************** + + Synopsis [Finds the largest DD in the population.] + + Description [Finds the largest DD in the population. If an order is + repeated, it avoids choosing the copy that is in the computed table + (it has repeat[i] > 1).] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +static int +largest(void) +{ + int i; /* loop var */ + int big; /* temporary holder to return result */ + + big = 0; + while (repeat[big] > 1) big++; + for (i = big + 1; i < popsize; i++) { + if (STOREDD(i,numvars) >= STOREDD(big,numvars) && repeat[i] <= 1) { + big = i; + } + } + return(big); + +} /* end of largest */ + + +/**Function******************************************************************** + + Synopsis [Generates a random number between 0 and the integer a.] + + Description [] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +static int +rand_int( + int a) +{ + return(Cudd_Random() % (a+1)); + +} /* end of rand_int */ + + +/**Function******************************************************************** + + Synopsis [Hash function for the computed table.] + + Description [Hash function for the computed table. Returns the bucket + number.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +static int +array_hash( + char * array, + int modulus) +{ + int val = 0; + int i; + int *intarray; + + intarray = (int *) array; + + for (i = 0; i < numvars; i++) { + val = val * 997 + intarray[i]; + } + + return ((val < 0) ? -val : val) % modulus; + +} /* end of array_hash */ + + +/**Function******************************************************************** + + Synopsis [Comparison function for the computed table.] + + Description [Comparison function for the computed table. Returns 0 if + the two arrays are equal; 1 otherwise.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +static int +array_compare( + const char * array1, + const char * array2) +{ + int i; + int *intarray1, *intarray2; + + intarray1 = (int *) array1; + intarray2 = (int *) array2; + + for (i = 0; i < numvars; i++) { + if (intarray1[i] != intarray2[i]) return(1); + } + return(0); + +} /* end of array_compare */ + + +/**Function******************************************************************** + + Synopsis [Returns the index of the fittest individual.] + + Description [] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +static int +find_best(void) +{ + int i,small; + + small = 0; + for (i = 1; i < popsize; i++) { + if (STOREDD(i,numvars) < STOREDD(small,numvars)) { + small = i; + } + } + return(small); + +} /* end of find_best */ + + +/**Function******************************************************************** + + Synopsis [Returns the average fitness of the population.] + + Description [] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +#ifdef DD_STATS +static double +find_average_fitness(void) +{ + int i; + int total_fitness = 0; + double average_fitness; + + for (i = 0; i < popsize; i++) { + total_fitness += STOREDD(i,numvars); + } + average_fitness = (double) total_fitness / (double) popsize; + return(average_fitness); + +} /* end of find_average_fitness */ +#endif + + +/**Function******************************************************************** + + Synopsis [Performs the crossover between two parents.] + + Description [Performs the crossover between two randomly chosen + parents, and creates two children, x1 and x2. Uses the Partially + Matched Crossover operator.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +static int +PMX( + int maxvar) +{ + int cut1,cut2; /* the two cut positions (random) */ + int mom,dad; /* the two randomly chosen parents */ + int *inv1; /* inverse permutations for repair algo */ + int *inv2; + int i; /* loop vars */ + int u,v; /* aux vars */ + + inv1 = ALLOC(int,maxvar); + if (inv1 == NULL) { + return(0); + } + inv2 = ALLOC(int,maxvar); + if (inv2 == NULL) { + FREE(inv1); + return(0); + } + + /* Choose two orders from the population using roulette wheel. */ + if (!roulette(&mom,&dad)) { + FREE(inv1); + FREE(inv2); + return(0); + } + + /* Choose two random cut positions. A cut in position i means that + ** the cut immediately precedes position i. If cut1 < cut2, we + ** exchange the middle of the two orderings; otherwise, we + ** exchange the beginnings and the ends. + */ + cut1 = rand_int(numvars-1); + do { + cut2 = rand_int(numvars-1); + } while (cut1 == cut2); + +#if 0 + /* Print out the parents. */ + (void) fprintf(table->out, + "Crossover of %d (mom) and %d (dad) between %d and %d\n", + mom,dad,cut1,cut2); + for (i = 0; i < numvars; i++) { + if (i == cut1 || i == cut2) (void) fprintf(table->out,"|"); + (void) fprintf(table->out,"%2d ",STOREDD(mom,i)); + } + (void) fprintf(table->out,"\n"); + for (i = 0; i < numvars; i++) { + if (i == cut1 || i == cut2) (void) fprintf(table->out,"|"); + (void) fprintf(table->out,"%2d ",STOREDD(dad,i)); + } + (void) fprintf(table->out,"\n"); +#endif + + /* Initialize the inverse permutations: -1 means yet undetermined. */ + for (i = 0; i < maxvar; i++) { + inv1[i] = -1; + inv2[i] = -1; + } + + /* Copy the portions whithin the cuts. */ + for (i = cut1; i != cut2; i = (i == numvars-1) ? 0 : i+1) { + STOREDD(popsize,i) = STOREDD(dad,i); + inv1[STOREDD(popsize,i)] = i; + STOREDD(popsize+1,i) = STOREDD(mom,i); + inv2[STOREDD(popsize+1,i)] = i; + } + + /* Now apply the repair algorithm outside the cuts. */ + for (i = cut2; i != cut1; i = (i == numvars-1 ) ? 0 : i+1) { + v = i; + do { + u = STOREDD(mom,v); + v = inv1[u]; + } while (v != -1); + STOREDD(popsize,i) = u; + inv1[u] = i; + v = i; + do { + u = STOREDD(dad,v); + v = inv2[u]; + } while (v != -1); + STOREDD(popsize+1,i) = u; + inv2[u] = i; + } + +#if 0 + /* Print the results of crossover. */ + for (i = 0; i < numvars; i++) { + if (i == cut1 || i == cut2) (void) fprintf(table->out,"|"); + (void) fprintf(table->out,"%2d ",STOREDD(popsize,i)); + } + (void) fprintf(table->out,"\n"); + for (i = 0; i < numvars; i++) { + if (i == cut1 || i == cut2) (void) fprintf(table->out,"|"); + (void) fprintf(table->out,"%2d ",STOREDD(popsize+1,i)); + } + (void) fprintf(table->out,"\n"); +#endif + + FREE(inv1); + FREE(inv2); + return(1); + +} /* end of PMX */ + + +/**Function******************************************************************** + + Synopsis [Selects two parents with the roulette wheel method.] + + Description [Selects two distinct parents with the roulette wheel method.] + + SideEffects [The indices of the selected parents are returned as side + effects.] + + SeeAlso [] + +******************************************************************************/ +static int +roulette( + int * p1, + int * p2) +{ + double *wheel; + double spin; + int i; + + wheel = ALLOC(double,popsize); + if (wheel == NULL) { + return(0); + } + + /* The fitness of an individual is the reciprocal of its size. */ + wheel[0] = 1.0 / (double) STOREDD(0,numvars); + + for (i = 1; i < popsize; i++) { + wheel[i] = wheel[i-1] + 1.0 / (double) STOREDD(i,numvars); + } + + /* Get a random number between 0 and wheel[popsize-1] (that is, + ** the sum of all fitness values. 2147483561 is the largest number + ** returned by Cudd_Random. + */ + spin = wheel[numvars-1] * (double) Cudd_Random() / 2147483561.0; + + /* Find the lucky element by scanning the wheel. */ + for (i = 0; i < popsize; i++) { + if (spin <= wheel[i]) break; + } + *p1 = i; + + /* Repeat the process for the second parent, making sure it is + ** distinct from the first. + */ + do { + spin = wheel[popsize-1] * (double) Cudd_Random() / 2147483561.0; + for (i = 0; i < popsize; i++) { + if (spin <= wheel[i]) break; + } + } while (i == *p1); + *p2 = i; + + FREE(wheel); + return(1); + +} /* end of roulette */ + diff --git a/distr/cudd/cuddGroup.c b/distr/cudd/cuddGroup.c new file mode 100644 index 0000000..2f8e75b --- /dev/null +++ b/distr/cudd/cuddGroup.c @@ -0,0 +1,2179 @@ +/**CFile*********************************************************************** + + FileName [cuddGroup.c] + + PackageName [cudd] + + Synopsis [Functions for group sifting.] + + Description [External procedures included in this file: +
        +
      • Cudd_MakeTreeNode() +
      + Internal procedures included in this file: +
        +
      • cuddTreeSifting() +
      + Static procedures included in this module: +
        +
      • ddTreeSiftingAux() +
      • ddCountInternalMtrNodes() +
      • ddReorderChildren() +
      • ddFindNodeHiLo() +
      • ddUniqueCompareGroup() +
      • ddGroupSifting() +
      • ddCreateGroup() +
      • ddGroupSiftingAux() +
      • ddGroupSiftingUp() +
      • ddGroupSiftingDown() +
      • ddGroupMove() +
      • ddGroupMoveBackward() +
      • ddGroupSiftingBackward() +
      • ddMergeGroups() +
      • ddDissolveGroup() +
      • ddNoCheck() +
      • ddSecDiffCheck() +
      • ddExtSymmCheck() +
      • ddVarGroupCheck() +
      • ddSetVarHandled() +
      • ddResetVarHandled() +
      • ddIsVarHandled() +
      ] + + 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 "util.h" +#include "cuddInt.h" + +/*---------------------------------------------------------------------------*/ +/* 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; + 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 = ALLOC(int,nvars); + if (var == NULL) { + table->errorCode = CUDD_MEMORY_OUT; + goto ddGroupSiftingOutOfMem; + } + entry = ALLOC(int,nvars); + if (entry == NULL) { + table->errorCode = CUDD_MEMORY_OUT; + goto ddGroupSiftingOutOfMem; + } + sifted = 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 */ + + FREE(sifted); + FREE(var); + FREE(entry); + + return(1); + +ddGroupSiftingOutOfMem: + if (entry != NULL) FREE(entry); + if (var != NULL) FREE(var); + if (sifted != NULL) 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,swapy; +#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; + 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 */ diff --git a/distr/cudd/cuddHarwell.c b/distr/cudd/cuddHarwell.c new file mode 100644 index 0000000..57ed757 --- /dev/null +++ b/distr/cudd/cuddHarwell.c @@ -0,0 +1,568 @@ +/**CFile*********************************************************************** + + FileName [cuddHarwell.c] + + PackageName [cudd] + + Synopsis [Function to read a matrix in Harwell format.] + + Description [External procedures included in this module: +
        +
      • Cudd_addHarwell() +
      + ] + + 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 */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* 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: +
      + x\[0\] y\[0\] x\[1\] y\[1\] ... +
      + 0 is the most significant bit. On input, nx and ny hold the numbers + of row and column variables already in existence. On output, they + hold the numbers of row and column variables actually used by the + matrix. m and n are set to the numbers of rows and columns of the + matrix. Their values on input are immaterial. Returns 1 on + success; 0 otherwise. The ADD for the sparse matrix is returned in + E, and its reference count is > 0.] + + SideEffects [None] + + SeeAlso [Cudd_addRead Cudd_bddRead] + +******************************************************************************/ +int +Cudd_addHarwell( + FILE * fp /* pointer to the input file */, + DdManager * dd /* DD manager */, + DdNode ** E /* characteristic function of the graph */, + DdNode *** x /* array of row variables */, + DdNode *** y /* array of column variables */, + DdNode *** xn /* array of complemented row variables */, + DdNode *** yn_ /* array of complemented column variables */, + int * nx /* number or row variables */, + int * ny /* number or column variables */, + int * m /* number of rows */, + int * n /* number of columns */, + int bx /* first index of row variables */, + int sx /* step of row variables */, + int by /* first index of column variables */, + int sy /* step of column variables */, + int pr /* verbosity level */) +{ + DdNode *one, *zero; + DdNode *w; + DdNode *cubex, *cubey, *minterm1; + int u, v, err, i, j, nv; + double val; + DdNode **lx, **ly, **lxn, **lyn; /* local copies of x, y, xn, yn_ */ + int lnx, lny; /* local copies of nx and ny */ + char title[73], key[9], mxtype[4], rhstyp[4]; + int totcrd, ptrcrd, indcrd, valcrd, rhscrd, + nrow, ncol, nnzero, neltvl, + nrhs, nrhsix; + int *colptr, *rowind; +#if 0 + int nguess, nexact; + int *rhsptr, *rhsind; +#endif + + if (*nx < 0 || *ny < 0) return(0); + + one = DD_ONE(dd); + zero = DD_ZERO(dd); + + /* Read the header */ + err = fscanf(fp, "%72c %8c", title, key); + if (err == EOF) { + return(0); + } else if (err != 2) { + return(0); + } + title[72] = (char) 0; + key[8] = (char) 0; + + err = fscanf(fp, "%d %d %d %d %d", &totcrd, &ptrcrd, &indcrd, + &valcrd, &rhscrd); + if (err == EOF) { + return(0); + } else if (err != 5) { + return(0); + } + + err = fscanf(fp, "%3s %d %d %d %d", mxtype, &nrow, &ncol, + &nnzero, &neltvl); + if (err == EOF) { + return(0); + } else if (err != 5) { + return(0); + } + + /* Skip FORTRAN formats */ + if (rhscrd == 0) { + err = fscanf(fp, "%*s %*s %*s \n"); + } else { + err = fscanf(fp, "%*s %*s %*s %*s \n"); + } + if (err == EOF) { + return(0); + } else if (err != 0) { + return(0); + } + + /* Print out some stuff if requested to be verbose */ + if (pr>0) { + (void) fprintf(dd->out,"%s: type %s, %d rows, %d columns, %d entries\n", key, + mxtype, nrow, ncol, nnzero); + if (pr>1) (void) fprintf(dd->out,"%s\n", title); + } + + /* Check matrix type */ + if (mxtype[0] != 'R' || mxtype[1] != 'U' || mxtype[2] != 'A') { + (void) fprintf(dd->err,"%s: Illegal matrix type: %s\n", + key, mxtype); + return(0); + } + if (neltvl != 0) return(0); + + /* Read optional 5-th line */ + if (rhscrd != 0) { + err = fscanf(fp, "%3c %d %d", rhstyp, &nrhs, &nrhsix); + if (err == EOF) { + return(0); + } else if (err != 3) { + return(0); + } + rhstyp[3] = (char) 0; + if (rhstyp[0] != 'F') { + (void) fprintf(dd->err, + "%s: Sparse right-hand side not yet supported\n", key); + return(0); + } + if (pr>0) (void) fprintf(dd->out,"%d right-hand side(s)\n", nrhs); + } else { + nrhs = 0; + } + + /* Compute the number of variables */ + + /* row and column numbers start from 0 */ + u = nrow - 1; + for (i=0; u > 0; i++) { + u >>= 1; + } + lnx = i; + if (nrhs == 0) { + v = ncol - 1; + } else { + v = 2* (ddMax(ncol, nrhs) - 1); + } + for (i=0; v > 0; i++) { + v >>= 1; + } + lny = i; + + /* Allocate or reallocate arrays for variables as needed */ + if (*nx == 0) { + if (lnx > 0) { + *x = lx = ALLOC(DdNode *,lnx); + if (lx == NULL) { + dd->errorCode = CUDD_MEMORY_OUT; + return(0); + } + *xn = lxn = ALLOC(DdNode *,lnx); + if (lxn == NULL) { + dd->errorCode = CUDD_MEMORY_OUT; + return(0); + } + } else { + *x = *xn = NULL; + } + } else if (lnx > *nx) { + *x = lx = REALLOC(DdNode *, *x, lnx); + if (lx == NULL) { + dd->errorCode = CUDD_MEMORY_OUT; + return(0); + } + *xn = lxn = REALLOC(DdNode *, *xn, lnx); + if (lxn == NULL) { + dd->errorCode = CUDD_MEMORY_OUT; + return(0); + } + } else { + lx = *x; + lxn = *xn; + } + if (*ny == 0) { + if (lny >0) { + *y = ly = ALLOC(DdNode *,lny); + if (ly == NULL) { + dd->errorCode = CUDD_MEMORY_OUT; + return(0); + } + *yn_ = lyn = ALLOC(DdNode *,lny); + if (lyn == NULL) { + dd->errorCode = CUDD_MEMORY_OUT; + return(0); + } + } else { + *y = *yn_ = NULL; + } + } else if (lny > *ny) { + *y = ly = REALLOC(DdNode *, *y, lny); + if (ly == NULL) { + dd->errorCode = CUDD_MEMORY_OUT; + return(0); + } + *yn_ = lyn = REALLOC(DdNode *, *yn_, lny); + if (lyn == NULL) { + dd->errorCode = CUDD_MEMORY_OUT; + return(0); + } + } else { + ly = *y; + lyn = *yn_; + } + + /* Create new variables as needed */ + for (i= *nx,nv=bx+(*nx)*sx; i < lnx; i++,nv+=sx) { + do { + dd->reordered = 0; + lx[i] = cuddUniqueInter(dd, nv, one, zero); + } while (dd->reordered == 1); + if (lx[i] == NULL) return(0); + cuddRef(lx[i]); + do { + dd->reordered = 0; + lxn[i] = cuddUniqueInter(dd, nv, zero, one); + } while (dd->reordered == 1); + if (lxn[i] == NULL) return(0); + cuddRef(lxn[i]); + } + for (i= *ny,nv=by+(*ny)*sy; i < lny; i++,nv+=sy) { + do { + dd->reordered = 0; + ly[i] = cuddUniqueInter(dd, nv, one, zero); + } while (dd->reordered == 1); + if (ly[i] == NULL) return(0); + cuddRef(ly[i]); + do { + dd->reordered = 0; + lyn[i] = cuddUniqueInter(dd, nv, zero, one); + } while (dd->reordered == 1); + if (lyn[i] == NULL) return(0); + cuddRef(lyn[i]); + } + + /* Update matrix parameters */ + *nx = lnx; + *ny = lny; + *m = nrow; + if (nrhs == 0) { + *n = ncol; + } else { + *n = (1 << (lny - 1)) + nrhs; + } + + /* Read structure data */ + colptr = ALLOC(int, ncol+1); + if (colptr == NULL) { + dd->errorCode = CUDD_MEMORY_OUT; + return(0); + } + rowind = ALLOC(int, nnzero); + if (rowind == NULL) { + dd->errorCode = CUDD_MEMORY_OUT; + return(0); + } + + for (i=0; ierr,"%s: Unexpected colptr[0] (%d)\n", + key,colptr[0]); + FREE(colptr); + FREE(rowind); + return(0); + } + for (i=0; i=0; nv--) { + if (v & 1) { + w = Cudd_addApply(dd, Cudd_addTimes, cubey, ly[nv]); + } else { + w = Cudd_addApply(dd, Cudd_addTimes, cubey, lyn[nv]); + } + if (w == NULL) { + Cudd_RecursiveDeref(dd, cubey); + FREE(colptr); + FREE(rowind); + return(0); + } + cuddRef(w); + Cudd_RecursiveDeref(dd, cubey); + cubey = w; + v >>= 1; + } + for (i=colptr[j]; i=0; nv--) { + if (u & 1) { + w = Cudd_addApply(dd, Cudd_addTimes, cubex, lx[nv]); + } else { + w = Cudd_addApply(dd, Cudd_addTimes, cubex, lxn[nv]); + } + if (w == NULL) { + Cudd_RecursiveDeref(dd, cubey); + Cudd_RecursiveDeref(dd, cubex); + FREE(colptr); + FREE(rowind); + return(0); + } + cuddRef(w); + Cudd_RecursiveDeref(dd, cubex); + cubex = w; + u >>= 1; + } + minterm1 = Cudd_addApply(dd, Cudd_addTimes, cubey, cubex); + if (minterm1 == NULL) { + Cudd_RecursiveDeref(dd, cubey); + Cudd_RecursiveDeref(dd, cubex); + FREE(colptr); + FREE(rowind); + return(0); + } + cuddRef(minterm1); + Cudd_RecursiveDeref(dd, cubex); + w = Cudd_addApply(dd, Cudd_addPlus, *E, minterm1); + if (w == NULL) { + Cudd_RecursiveDeref(dd, cubey); + FREE(colptr); + FREE(rowind); + return(0); + } + cuddRef(w); + Cudd_RecursiveDeref(dd, minterm1); + Cudd_RecursiveDeref(dd, *E); + *E = w; + } + Cudd_RecursiveDeref(dd, cubey); + } + FREE(colptr); + FREE(rowind); + + /* Read right-hand sides */ + for (j=0; j=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=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 */ +/*---------------------------------------------------------------------------*/ + diff --git a/distr/cudd/cuddInit.c b/distr/cudd/cuddInit.c new file mode 100644 index 0000000..f37a9f7 --- /dev/null +++ b/distr/cudd/cuddInit.c @@ -0,0 +1,308 @@ +/**CFile*********************************************************************** + + FileName [cuddInit.c] + + PackageName [cudd] + + Synopsis [Functions to initialize and shut down the DD manager.] + + Description [External procedures included in this module: +
        +
      • Cudd_Init() +
      • Cudd_Quit() +
      + Internal procedures included in this module: +
        +
      • cuddZddInitUniv() +
      • cuddZddFreeUniv() +
      + ] + + 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 */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* 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 = ALLOC(char,(maxMemory / DD_STASH_FRACTION) + 4); + MMoutOfMemory = saveHandler; + if (unique->stash == NULL) { + (void) fprintf(unique->err,"Unable to set aside memory\n"); + } + + /* Initialize constants. */ + unique->one = cuddUniqueConst(unique,1.0); + if (unique->one == NULL) return(0); + cuddRef(unique->one); + unique->zero = cuddUniqueConst(unique,0.0); + if (unique->zero == NULL) return(0); + cuddRef(unique->zero); +#ifdef HAVE_IEEE_754 + if (DD_PLUS_INF_VAL != DD_PLUS_INF_VAL * 3 || + DD_PLUS_INF_VAL != DD_PLUS_INF_VAL / 3) { + (void) fprintf(unique->err,"Warning: Crippled infinite values\n"); + (void) fprintf(unique->err,"Recompile without -DHAVE_IEEE_754\n"); + } +#endif + unique->plusinfinity = cuddUniqueConst(unique,DD_PLUS_INF_VAL); + if (unique->plusinfinity == NULL) return(0); + cuddRef(unique->plusinfinity); + unique->minusinfinity = cuddUniqueConst(unique,DD_MINUS_INF_VAL); + if (unique->minusinfinity == NULL) return(0); + cuddRef(unique->minusinfinity); + unique->background = unique->zero; + + /* The logical zero is different from the CUDD_VALUE_TYPE zero! */ + one = unique->one; + zero = Cudd_Not(one); + /* Create the projection functions. */ + unique->vars = ALLOC(DdNodePtr,unique->maxSize); + if (unique->vars == NULL) { + unique->errorCode = CUDD_MEMORY_OUT; + return(NULL); + } + for (i = 0; i < unique->size; i++) { + unique->vars[i] = cuddUniqueInter(unique,i,one,zero); + if (unique->vars[i] == NULL) return(0); + cuddRef(unique->vars[i]); + } + + if (unique->sizeZ) + cuddZddInitUniv(unique); + + unique->memused += sizeof(DdNode *) * unique->maxSize; + + return(unique); + +} /* end of Cudd_Init */ + + +/**Function******************************************************************** + + Synopsis [Deletes resources associated with a DD manager.] + + Description [Deletes resources associated with a DD manager and + resets the global statistical counters. (Otherwise, another manaqger + subsequently created would inherit the stats of this one.)] + + SideEffects [None] + + SeeAlso [Cudd_Init] + +******************************************************************************/ +void +Cudd_Quit( + DdManager * unique) +{ + if (unique->stash != NULL) FREE(unique->stash); + cuddFreeTable(unique); + +} /* end of Cudd_Quit */ + + +/*---------------------------------------------------------------------------*/ +/* Definition of internal functions */ +/*---------------------------------------------------------------------------*/ + + +/**Function******************************************************************** + + Synopsis [Initializes the ZDD universe.] + + Description [Initializes the ZDD universe. Returns 1 if successful; 0 + otherwise.] + + SideEffects [None] + + SeeAlso [cuddZddFreeUniv] + +******************************************************************************/ +int +cuddZddInitUniv( + DdManager * zdd) +{ + DdNode *p, *res; + int i; + + zdd->univ = ALLOC(DdNodePtr, zdd->sizeZ); + if (zdd->univ == NULL) { + zdd->errorCode = CUDD_MEMORY_OUT; + return(0); + } + + res = DD_ONE(zdd); + cuddRef(res); + for (i = zdd->sizeZ - 1; i >= 0; i--) { + unsigned int index = zdd->invpermZ[i]; + p = res; + res = cuddUniqueInterZdd(zdd, index, p, p); + if (res == NULL) { + Cudd_RecursiveDerefZdd(zdd,p); + FREE(zdd->univ); + return(0); + } + cuddRef(res); + cuddDeref(p); + zdd->univ[i] = res; + } + +#ifdef DD_VERBOSE + cuddZddP(zdd, zdd->univ[0]); +#endif + + return(1); + +} /* end of cuddZddInitUniv */ + + +/**Function******************************************************************** + + Synopsis [Frees the ZDD universe.] + + Description [Frees the ZDD universe.] + + SideEffects [None] + + SeeAlso [cuddZddInitUniv] + +******************************************************************************/ +void +cuddZddFreeUniv( + DdManager * zdd) +{ + if (zdd->univ) { + Cudd_RecursiveDerefZdd(zdd, zdd->univ[0]); + FREE(zdd->univ); + } + +} /* end of cuddZddFreeUniv */ + + +/*---------------------------------------------------------------------------*/ +/* Definition of static functions */ +/*---------------------------------------------------------------------------*/ + diff --git a/distr/cudd/cuddInt.h b/distr/cudd/cuddInt.h new file mode 100644 index 0000000..96b95d5 --- /dev/null +++ b/distr/cudd/cuddInt.h @@ -0,0 +1,1203 @@ +/**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 _CUDDINT +#define _CUDDINT + + +/*---------------------------------------------------------------------------*/ +/* Nested includes */ +/*---------------------------------------------------------------------------*/ + +#ifdef DD_MIS +#include "array.h" +#include "list.h" +#include "st.h" +#include "espresso.h" +#include "node.h" +#ifdef SIS +#include "graph.h" +#include "astg.h" +#endif +#include "network.h" +#endif + +#include +#include "cudd.h" +#include "st.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#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.2 +#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 + +#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 +} 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 */ + /* (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 +}; + +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 + node 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 + node 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 + node 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 [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)) +#else +#define ddCHash2(o,f,g,s) \ +(((((unsigned)(f) + (unsigned)(o)) * DD_P1 + (unsigned)(g)) * DD_P2) >> (s)) +#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 * (*op)(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***************************************************************/ + +#ifdef __cplusplus +} /* end of extern "C" */ +#endif + +#endif /* _CUDDINT */ diff --git a/distr/cudd/cuddInteract.c b/distr/cudd/cuddInteract.c new file mode 100644 index 0000000..3c089a2 --- /dev/null +++ b/distr/cudd/cuddInteract.c @@ -0,0 +1,429 @@ +/**CFile*********************************************************************** + + FileName [cuddInteract.c] + + PackageName [cudd] + + Synopsis [Functions to manipulate the variable interaction matrix.] + + Description [Internal procedures included in this file: +
        +
      • cuddSetInteract() +
      • cuddTestInteract() +
      • cuddInitInteract() +
      + Static procedures included in this file: +
        +
      • ddSuppInteract() +
      • ddClearLocal() +
      • ddUpdateInteract() +
      • ddClearGlobal() +
      + 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.

      + 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 "util.h" +#include "cuddInt.h" + +/*---------------------------------------------------------------------------*/ +/* Constant declarations */ +/*---------------------------------------------------------------------------*/ + +#if SIZEOF_LONG == 8 +#define BPL 64 +#define LOGBPL 6 +#else +#define BPL 32 +#define LOGBPL 5 +#endif + +/*---------------------------------------------------------------------------*/ +/* Stucture declarations */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Type declarations */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Variable declarations */ +/*---------------------------------------------------------------------------*/ + +#ifndef lint +static char rcsid[] DD_UNUSED = "$Id: cuddInteract.c,v 1.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; + int 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 = ALLOC(long,words); + if (interact == NULL) { + table->errorCode = CUDD_MEMORY_OUT; + return(0); + } + for (i = 0; i < words; i++) { + interact[i] = 0; + } + + support = ALLOC(int,n); + if (support == NULL) { + table->errorCode = CUDD_MEMORY_OUT; + 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); + + 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 */ + diff --git a/distr/cudd/cuddLCache.c b/distr/cudd/cuddLCache.c new file mode 100644 index 0000000..f617d84 --- /dev/null +++ b/distr/cudd/cuddLCache.c @@ -0,0 +1,1457 @@ +/**CFile*********************************************************************** + + FileName [cuddLCache.c] + + PackageName [cudd] + + Synopsis [Functions for local caches.] + + Description [Internal procedures included in this module: +

        +
      • cuddLocalCacheInit() +
      • cuddLocalCacheQuit() +
      • cuddLocalCacheInsert() +
      • cuddLocalCacheLookup() +
      • cuddLocalCacheClearDead() +
      • cuddLocalCacheClearAll() +
      • cuddLocalCacheProfile() +
      • cuddHashTableInit() +
      • cuddHashTableQuit() +
      • cuddHashTableInsert() +
      • cuddHashTableLookup() +
      • cuddHashTableInsert2() +
      • cuddHashTableLookup2() +
      • cuddHashTableInsert3() +
      • cuddHashTableLookup3() +
      + Static procedures included in this module: +
        +
      • cuddLocalCacheResize() +
      • ddLCHash() +
      • cuddLocalCacheAddToList() +
      • cuddLocalCacheRemoveFromList() +
      • cuddHashTableResize() +
      • cuddHashTableAlloc() +
      ] + + 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 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 = 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 *) + ALLOC(char, cacheSize * cache->itemsize); + if (cache->item == NULL) { + manager->errorCode = CUDD_MEMORY_OUT; + 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); + FREE(cache->item); + 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 = 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); + } + + 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 = 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 = ALLOC(DdHashItem *, hash->numBuckets); + if (hash->bucket == NULL) { + manager->errorCode = CUDD_MEMORY_OUT; + 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]; + FREE(memlist); + memlist = nextmem; + } + + FREE(hash->bucket); + 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(f,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(f,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(f,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(f,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(f,g,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(f,g,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 *) 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; + } + } + + 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 = 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(key[0], 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(key[0], 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(key[0], key[1], 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; + } + } + } + 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 **) ALLOC(char,(DD_MEM_CHUNK+1) * itemsize); + MMoutOfMemory = saveHandler; +#ifdef __osf__ +#pragma pointer_size restore +#endif + if (mem == NULL) { + if (hash->manager->stash != NULL) { + 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 **) 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 */ diff --git a/distr/cudd/cuddLevelQ.c b/distr/cudd/cuddLevelQ.c new file mode 100644 index 0000000..214ca3d --- /dev/null +++ b/distr/cudd/cuddLevelQ.c @@ -0,0 +1,561 @@ +/**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: +
        +
      • cuddLevelQueueInit() +
      • cuddLevelQueueQuit() +
      • cuddLevelQueueEnqueue() +
      • cuddLevelQueueDequeue() +
      + Static procedures included in this module: +
        +
      • hashLookup() +
      • hashInsert() +
      • hashDelete() +
      • hashResize() +
      + ] + + 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 */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* 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 = 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 = ALLOC(DdQueueItem *, levels); +#ifdef __osf__ +#pragma pointer_size restore +#endif + if (queue->last == NULL) { + FREE(queue); + return(NULL); + } + /* Use a hash table to test for uniqueness. */ + if (numBuckets < 2) numBuckets = 2; + logSize = cuddComputeFloorLog2(numBuckets); + queue->numBuckets = 1 << logSize; + queue->shift = sizeof(int) * 8 - logSize; +#ifdef __osf__ +#pragma pointer_size save +#pragma pointer_size short +#endif + queue->buckets = ALLOC(DdQueueItem *, queue->numBuckets); +#ifdef __osf__ +#pragma pointer_size restore +#endif + if (queue->buckets == NULL) { + FREE(queue->last); + 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; + FREE(item); + } + while (queue->first != NULL) { + item = (DdQueueItem *) queue->first; + queue->first = item->next; + FREE(item); + } + FREE(queue->buckets); + FREE(queue->last); + FREE(queue); + return; + +} /* end of cuddLevelQueueQuit */ + + +/**Function******************************************************************** + + Synopsis [Inserts a new key in a level queue.] + + Description [Inserts a new key in a level queue. A new entry is + created in the queue only if the node is not already + enqueued. Returns a pointer to the queue item if successful; NULL + otherwise.] + + SideEffects [None] + + SeeAlso [cuddLevelQueueInit cuddLevelQueueDequeue] + +******************************************************************************/ +void * +cuddLevelQueueEnqueue( + DdLevelQueue * queue /* level queue */, + void * key /* key to be enqueued */, + int level /* level at which to insert */) +{ + 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 *) 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 = 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; + } + } + FREE(oldBuckets); + return(1); + +} /* end of hashResize */ diff --git a/distr/cudd/cuddLinear.c b/distr/cudd/cuddLinear.c new file mode 100644 index 0000000..fdae938 --- /dev/null +++ b/distr/cudd/cuddLinear.c @@ -0,0 +1,1365 @@ +/**CFile*********************************************************************** + + FileName [cuddLinear.c] + + PackageName [cudd] + + Synopsis [Functions for DD reduction by linear transformations.] + + Description [ Internal procedures included in this module: +
        +
      • cuddLinearAndSifting() +
      • cuddLinearInPlace() +
      • cuddUpdateInteractionMatrix() +
      • cuddInitLinear() +
      • cuddResizeLinear() +
      + Static procedures included in this module: +
        +
      • ddLinearUniqueCompare() +
      • ddLinearAndSiftingAux() +
      • ddLinearAndSiftingUp() +
      • ddLinearAndSiftingDown() +
      • ddLinearAndSiftingBackward() +
      • ddUndoMoves() +
      • cuddXorLinear() +
      ] + + 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 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. +
        +
      1. Order all the variables according to the number of entries + in each unique table. +
      2. 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. +
      3. Select the best permutation. +
      4. Repeat 3 and 4 for all variables. +
      + 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 = ALLOC(int,size); + if (entry == NULL) { + table->errorCode = CUDD_MEMORY_OUT; + goto cuddLinearAndSiftingOutOfMem; + } + var = 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 + } + + FREE(var); + FREE(entry); + +#ifdef DD_STATS + (void) fprintf(table->out,"\n#:L_LINSIFT %8d: linear trans.", + ddTotalNumberLinearTr); +#endif + + return(1); + +cuddLinearAndSiftingOutOfMem: + + if (entry != NULL) FREE(entry); + if (var != NULL) 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 < + 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; + 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(f11, 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(f01, 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(newf1, 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 = 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 = 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]; + } + } + 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 */ diff --git a/distr/cudd/cuddLiteral.c b/distr/cudd/cuddLiteral.c new file mode 100644 index 0000000..400b060 --- /dev/null +++ b/distr/cudd/cuddLiteral.c @@ -0,0 +1,264 @@ +/**CFile*********************************************************************** + + FileName [cuddLiteral.c] + + PackageName [cudd] + + Synopsis [Functions for manipulation of literal sets represented by + BDDs.] + + Description [External procedures included in this file: +
        +
      • Cudd_bddLiteralSetIntersection() +
      + Internal procedures included in this file: +
        +
      • cuddBddLiteralSetIntersectionRecur() +
      ] + + 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 */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* 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 */ +/*---------------------------------------------------------------------------*/ + diff --git a/distr/cudd/cuddMatMult.c b/distr/cudd/cuddMatMult.c new file mode 100644 index 0000000..29e1f5b --- /dev/null +++ b/distr/cudd/cuddMatMult.c @@ -0,0 +1,707 @@ +/**CFile*********************************************************************** + + FileName [cuddMatMult.c] + + PackageName [cudd] + + Synopsis [Matrix multiplication functions.] + + Description [External procedures included in this module: +
        +
      • Cudd_addMatrixMultiply() +
      • Cudd_addTimesPlus() +
      • Cudd_addTriangle() +
      • Cudd_addOuterSum() +
      + Static procedures included in this module: +
        +
      • addMMRecur() +
      • addTriangleRecur() +
      • cuddAddOuterSumRecur() +
      ] + + 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 */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* 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 = ALLOC(int,nvars); + if (vars == NULL) { + dd->errorCode = CUDD_MEMORY_OUT; + return(NULL); + } + for (i = 0; i < nvars; i++) { + vars[i] = 0; + } + for (i = 0; i < nz; i++) { + vars[z[i]->index] = 1; + } + + do { + dd->reordered = 0; + res = addMMRecur(dd,A,B,-1,vars); + } while (dd->reordered == 1); + FREE(vars); + return(res); + +} /* end of Cudd_addMatrixMultiply */ + + +/**Function******************************************************************** + + Synopsis [Calculates the product of two matrices represented as + ADDs.] + + Description [Calculates the product of two matrices, A and B, + represented as ADDs, using the CMU matrix by matrix multiplication + procedure by Clarke et al.. Matrix A has x's as row variables and z's + as column variables, while matrix B has z's as row variables and y's + as column variables. Returns the pointer to the result if successful; + NULL otherwise. The resulting matrix has x's as row variables and y's + as column variables.] + + SideEffects [None] + + SeeAlso [Cudd_addMatrixMultiply] + +******************************************************************************/ +DdNode * +Cudd_addTimesPlus( + DdManager * dd, + DdNode * A, + DdNode * B, + DdNode ** z, + int nz) +{ + DdNode *w, *cube, *tmp, *res; + int i; + tmp = Cudd_addApply(dd,Cudd_addTimes,A,B); + if (tmp == NULL) return(NULL); + Cudd_Ref(tmp); + Cudd_Ref(cube = DD_ONE(dd)); + for (i = nz-1; i >= 0; i--) { + w = Cudd_addIte(dd,z[i],cube,DD_ZERO(dd)); + if (w == NULL) { + Cudd_RecursiveDeref(dd,tmp); + return(NULL); + } + Cudd_Ref(w); + Cudd_RecursiveDeref(dd,cube); + cube = w; + } + res = Cudd_addExistAbstract(dd,tmp,cube); + if (res == NULL) { + Cudd_RecursiveDeref(dd,tmp); + Cudd_RecursiveDeref(dd,cube); + return(NULL); + } + Cudd_Ref(res); + Cudd_RecursiveDeref(dd,cube); + Cudd_RecursiveDeref(dd,tmp); + Cudd_Deref(res); + return(res); + +} /* end of Cudd_addTimesPlus */ + + +/**Function******************************************************************** + + Synopsis [Performs the triangulation step for the shortest path + computation.] + + Description [Implements the semiring multiplication algorithm used in + the triangulation step for the shortest path computation. f + is assumed to depend on variables x (rows) and z (columns). g is + assumed to depend on variables z (rows) and y (columns). The product + of f and g then depends on x (rows) and y (columns). Only the z + variables have to be explicitly identified; they are the + "abstraction" variables. Returns a pointer to the result if + successful; NULL otherwise. ] + + SideEffects [None] + + SeeAlso [Cudd_addMatrixMultiply Cudd_bddAndAbstract] + +******************************************************************************/ +DdNode * +Cudd_addTriangle( + DdManager * dd, + DdNode * f, + DdNode * g, + DdNode ** z, + int nz) +{ + int i, nvars, *vars; + DdNode *res, *cube; + + nvars = dd->size; + vars = ALLOC(int, nvars); + if (vars == NULL) { + dd->errorCode = CUDD_MEMORY_OUT; + return(NULL); + } + for (i = 0; i < nvars; i++) vars[i] = -1; + for (i = 0; i < nz; i++) vars[z[i]->index] = i; + cube = Cudd_addComputeCube(dd, z, NULL, nz); + if (cube == NULL) { + FREE(vars); + return(NULL); + } + cuddRef(cube); + + do { + dd->reordered = 0; + res = addTriangleRecur(dd, f, g, vars, cube); + } while (dd->reordered == 1); + if (res != NULL) cuddRef(res); + Cudd_RecursiveDeref(dd,cube); + if (res != NULL) cuddDeref(res); + FREE(vars); + return(res); + +} /* end of Cudd_addTriangle */ + + +/**Function******************************************************************** + + Synopsis [Takes the minimum of a matrix and the outer sum of two vectors.] + + Description [Takes the pointwise minimum of a matrix and the outer + sum of two vectors. This procedure is used in the Floyd-Warshall + all-pair shortest path algorithm. Returns a pointer to the result if + successful; NULL otherwise.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +DdNode * +Cudd_addOuterSum( + DdManager *dd, + DdNode *M, + DdNode *r, + DdNode *c) +{ + DdNode *res; + + do { + dd->reordered = 0; + res = cuddAddOuterSumRecur(dd, M, r, c); + } while (dd->reordered == 1); + return(res); + +} /* end of Cudd_addOuterSum */ + + +/*---------------------------------------------------------------------------*/ +/* Definition of internal functions */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Definition of static functions */ +/*---------------------------------------------------------------------------*/ + +/**Function******************************************************************** + + Synopsis [Performs the recursive step of Cudd_addMatrixMultiply.] + + Description [Performs the recursive step of Cudd_addMatrixMultiply. + Returns a pointer to the result if successful; NULL otherwise.] + + SideEffects [None] + +******************************************************************************/ +static DdNode * +addMMRecur( + DdManager * dd, + DdNode * A, + DdNode * B, + int topP, + int * vars) +{ + DdNode *zero, + *At, /* positive cofactor of first operand */ + *Ae, /* negative cofactor of first operand */ + *Bt, /* positive cofactor of second operand */ + *Be, /* negative cofactor of second operand */ + *t, /* positive cofactor of result */ + *e, /* negative cofactor of result */ + *scaled, /* scaled result */ + *add_scale, /* ADD representing the scaling factor */ + *res; + int i; /* loop index */ + double scale; /* scaling factor */ + int index; /* index of the top variable */ + CUDD_VALUE_TYPE value; + unsigned int topA, topB, topV; + DD_CTFP cacheOp; + + statLine(dd); + zero = DD_ZERO(dd); + + if (A == zero || B == zero) { + return(zero); + } + + if (cuddIsConstant(A) && cuddIsConstant(B)) { + /* Compute the scaling factor. It is 2^k, where k is the + ** number of summation variables below the current variable. + ** Indeed, these constants represent blocks of 2^k identical + ** constant values in both A and B. + */ + value = cuddV(A) * cuddV(B); + for (i = 0; i < dd->size; i++) { + if (vars[i]) { + if (dd->perm[i] > topP) { + value *= (CUDD_VALUE_TYPE) 2; + } + } + } + res = cuddUniqueConst(dd, value); + return(res); + } + + /* Standardize to increase cache efficiency. Clearly, A*B != B*A + ** in matrix multiplication. However, which matrix is which is + ** determined by the variables appearing in the ADDs and not by + ** which one is passed as first argument. + */ + if (A > B) { + DdNode *tmp = A; + A = B; + B = tmp; + } + + topA = cuddI(dd,A->index); topB = cuddI(dd,B->index); + topV = ddMin(topA,topB); + + cacheOp = (DD_CTFP) addMMRecur; + res = cuddCacheLookup2(dd,cacheOp,A,B); + if (res != NULL) { + /* If the result is 0, there is no need to normalize. + ** Otherwise we count the number of z variables between + ** the current depth and the top of the ADDs. These are + ** the missing variables that determine the size of the + ** constant blocks. + */ + if (res == zero) return(res); + scale = 1.0; + for (i = 0; i < dd->size; i++) { + if (vars[i]) { + if (dd->perm[i] > topP && (unsigned) dd->perm[i] < topV) { + scale *= 2; + } + } + } + if (scale > 1.0) { + cuddRef(res); + add_scale = cuddUniqueConst(dd,(CUDD_VALUE_TYPE)scale); + if (add_scale == NULL) { + Cudd_RecursiveDeref(dd, res); + return(NULL); + } + cuddRef(add_scale); + scaled = cuddAddApplyRecur(dd,Cudd_addTimes,res,add_scale); + if (scaled == NULL) { + Cudd_RecursiveDeref(dd, add_scale); + Cudd_RecursiveDeref(dd, res); + return(NULL); + } + cuddRef(scaled); + Cudd_RecursiveDeref(dd, add_scale); + Cudd_RecursiveDeref(dd, res); + res = scaled; + cuddDeref(res); + } + return(res); + } + + /* compute the cofactors */ + if (topV == topA) { + At = cuddT(A); + Ae = cuddE(A); + } else { + At = Ae = A; + } + if (topV == topB) { + Bt = cuddT(B); + Be = cuddE(B); + } else { + Bt = Be = B; + } + + t = addMMRecur(dd, At, Bt, (int)topV, vars); + if (t == NULL) return(NULL); + cuddRef(t); + e = addMMRecur(dd, Ae, Be, (int)topV, vars); + if (e == NULL) { + Cudd_RecursiveDeref(dd, t); + return(NULL); + } + cuddRef(e); + + index = dd->invperm[topV]; + if (vars[index] == 0) { + /* We have split on either the rows of A or the columns + ** of B. We just need to connect the two subresults, + ** which correspond to two submatrices of the result. + */ + res = (t == e) ? t : cuddUniqueInter(dd,index,t,e); + if (res == NULL) { + Cudd_RecursiveDeref(dd, t); + Cudd_RecursiveDeref(dd, e); + return(NULL); + } + cuddRef(res); + cuddDeref(t); + cuddDeref(e); + } else { + /* we have simultaneously split on the columns of A and + ** the rows of B. The two subresults must be added. + */ + res = cuddAddApplyRecur(dd,Cudd_addPlus,t,e); + if (res == NULL) { + Cudd_RecursiveDeref(dd, t); + Cudd_RecursiveDeref(dd, e); + return(NULL); + } + cuddRef(res); + Cudd_RecursiveDeref(dd, t); + Cudd_RecursiveDeref(dd, e); + } + + cuddCacheInsert2(dd,cacheOp,A,B,res); + + /* We have computed (and stored in the computed table) a minimal + ** result; that is, a result that assumes no summation variables + ** between the current depth of the recursion and its top + ** variable. We now take into account the z variables by properly + ** scaling the result. + */ + if (res != zero) { + scale = 1.0; + for (i = 0; i < dd->size; i++) { + if (vars[i]) { + if (dd->perm[i] > topP && (unsigned) dd->perm[i] < topV) { + scale *= 2; + } + } + } + if (scale > 1.0) { + add_scale = cuddUniqueConst(dd,(CUDD_VALUE_TYPE)scale); + if (add_scale == NULL) { + Cudd_RecursiveDeref(dd, res); + return(NULL); + } + cuddRef(add_scale); + scaled = cuddAddApplyRecur(dd,Cudd_addTimes,res,add_scale); + if (scaled == NULL) { + Cudd_RecursiveDeref(dd, res); + Cudd_RecursiveDeref(dd, add_scale); + return(NULL); + } + cuddRef(scaled); + Cudd_RecursiveDeref(dd, add_scale); + Cudd_RecursiveDeref(dd, res); + res = scaled; + } + } + cuddDeref(res); + return(res); + +} /* end of addMMRecur */ + + +/**Function******************************************************************** + + Synopsis [Performs the recursive step of Cudd_addTriangle.] + + Description [Performs the recursive step of Cudd_addTriangle. Returns + a pointer to the result if successful; NULL otherwise.] + + SideEffects [None] + +******************************************************************************/ +static DdNode * +addTriangleRecur( + DdManager * dd, + DdNode * f, + DdNode * g, + int * vars, + DdNode *cube) +{ + DdNode *fv, *fvn, *gv, *gvn, *t, *e, *res; + CUDD_VALUE_TYPE value; + int top, topf, topg, index; + + statLine(dd); + if (f == DD_PLUS_INFINITY(dd) || g == DD_PLUS_INFINITY(dd)) { + return(DD_PLUS_INFINITY(dd)); + } + + if (cuddIsConstant(f) && cuddIsConstant(g)) { + value = cuddV(f) + cuddV(g); + res = cuddUniqueConst(dd, value); + return(res); + } + if (f < g) { + DdNode *tmp = f; + f = g; + g = tmp; + } + + if (f->ref != 1 || g->ref != 1) { + res = cuddCacheLookup(dd, DD_ADD_TRIANGLE_TAG, f, g, cube); + if (res != NULL) { + return(res); + } + } + + topf = cuddI(dd,f->index); topg = cuddI(dd,g->index); + top = ddMin(topf,topg); + + if (top == topf) {fv = cuddT(f); fvn = cuddE(f);} else {fv = fvn = f;} + if (top == topg) {gv = cuddT(g); gvn = cuddE(g);} else {gv = gvn = g;} + + t = addTriangleRecur(dd, fv, gv, vars, cube); + if (t == NULL) return(NULL); + cuddRef(t); + e = addTriangleRecur(dd, fvn, gvn, vars, cube); + if (e == NULL) { + Cudd_RecursiveDeref(dd, t); + return(NULL); + } + cuddRef(e); + + index = dd->invperm[top]; + if (vars[index] < 0) { + res = (t == e) ? t : cuddUniqueInter(dd,index,t,e); + if (res == NULL) { + Cudd_RecursiveDeref(dd, t); + Cudd_RecursiveDeref(dd, e); + return(NULL); + } + cuddDeref(t); + cuddDeref(e); + } else { + res = cuddAddApplyRecur(dd,Cudd_addMinimum,t,e); + if (res == NULL) { + Cudd_RecursiveDeref(dd, t); + Cudd_RecursiveDeref(dd, e); + return(NULL); + } + cuddRef(res); + Cudd_RecursiveDeref(dd, t); + Cudd_RecursiveDeref(dd, e); + cuddDeref(res); + } + + if (f->ref != 1 || g->ref != 1) { + cuddCacheInsert(dd, DD_ADD_TRIANGLE_TAG, f, g, cube, res); + } + + return(res); + +} /* end of addTriangleRecur */ + + +/**Function******************************************************************** + + Synopsis [Performs the recursive step of Cudd_addOuterSum.] + + Description [Performs the recursive step of Cudd_addOuterSum. + Returns a pointer to the result if successful; NULL otherwise.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +static DdNode * +cuddAddOuterSumRecur( + DdManager *dd, + DdNode *M, + DdNode *r, + DdNode *c) +{ + DdNode *P, *R, *Mt, *Me, *rt, *re, *ct, *ce, *Rt, *Re; + int topM, topc, topr; + int v, index; + + statLine(dd); + /* Check special cases. */ + if (r == DD_PLUS_INFINITY(dd) || c == DD_PLUS_INFINITY(dd)) return(M); + + if (cuddIsConstant(c) && cuddIsConstant(r)) { + R = cuddUniqueConst(dd,Cudd_V(c)+Cudd_V(r)); + cuddRef(R); + if (cuddIsConstant(M)) { + if (cuddV(R) <= cuddV(M)) { + cuddDeref(R); + return(R); + } else { + Cudd_RecursiveDeref(dd,R); + return(M); + } + } else { + P = Cudd_addApply(dd,Cudd_addMinimum,R,M); + cuddRef(P); + Cudd_RecursiveDeref(dd,R); + cuddDeref(P); + return(P); + } + } + + /* Check the cache. */ + R = cuddCacheLookup(dd,DD_ADD_OUT_SUM_TAG,M,r,c); + if (R != NULL) return(R); + + topM = cuddI(dd,M->index); topr = cuddI(dd,r->index); + topc = cuddI(dd,c->index); + v = ddMin(topM,ddMin(topr,topc)); + + /* Compute cofactors. */ + if (topM == v) { Mt = cuddT(M); Me = cuddE(M); } else { Mt = Me = M; } + if (topr == v) { rt = cuddT(r); re = cuddE(r); } else { rt = re = r; } + if (topc == v) { ct = cuddT(c); ce = cuddE(c); } else { ct = ce = c; } + + /* Recursively solve. */ + Rt = cuddAddOuterSumRecur(dd,Mt,rt,ct); + if (Rt == NULL) return(NULL); + cuddRef(Rt); + Re = cuddAddOuterSumRecur(dd,Me,re,ce); + if (Re == NULL) { + Cudd_RecursiveDeref(dd, Rt); + return(NULL); + } + cuddRef(Re); + index = dd->invperm[v]; + R = (Rt == Re) ? Rt : cuddUniqueInter(dd,index,Rt,Re); + if (R == NULL) { + Cudd_RecursiveDeref(dd, Rt); + Cudd_RecursiveDeref(dd, Re); + return(NULL); + } + cuddDeref(Rt); + cuddDeref(Re); + + /* Store the result in the cache. */ + cuddCacheInsert(dd,DD_ADD_OUT_SUM_TAG,M,r,c,R); + + return(R); + +} /* end of cuddAddOuterSumRecur */ diff --git a/distr/cudd/cuddPriority.c b/distr/cudd/cuddPriority.c new file mode 100644 index 0000000..2ef59ea --- /dev/null +++ b/distr/cudd/cuddPriority.c @@ -0,0 +1,2027 @@ +/**CFile*********************************************************************** + + FileName [cuddPriority.c] + + PackageName [cudd] + + Synopsis [Priority functions.] + + Description [External procedures included in this file: +
        +
      • Cudd_PrioritySelect() +
      • Cudd_Xgty() +
      • Cudd_Xeqy() +
      • Cudd_addXeqy() +
      • Cudd_Dxygtdxz() +
      • Cudd_Dxygtdyz() +
      • Cudd_Inequality() +
      • Cudd_Disequality() +
      • Cudd_bddInterval() +
      • Cudd_CProjection() +
      • Cudd_addHamming() +
      • Cudd_MinHammingDist() +
      • Cudd_bddClosestCube() +
      + Internal procedures included in this module: +
        +
      • cuddCProjectionRecur() +
      • cuddBddClosestCube() +
      + Static procedures included in this module: +
        +
      • cuddMinHammingDistRecur() +
      • separateCube() +
      • createResult() +
      + ] + + 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 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: +
        +
      • When extracting representatives from an equivalence relation, + Cudd_CProjection has the advantage of nor requiring the auxiliary + variables. +
      • 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). +
      + ] + + 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 = 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) { + 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 > 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\]. + 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) > d(x,z).] + + Description [This function generates a BDD for the function d(x,y) + > 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) > d(y,z).] + + Description [This function generates a BDD for the function d(x,y) + > 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 ≥ 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_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]; + 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]; + 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]; + 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]; + 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 ≤ x ≤ upperB.] + + Description [This function generates a BDD for the function + lowerB ≤ x ≤ 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 ≤ x and x ≤ 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; + 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 + f and g according to the following formula. +
      +    H(f,g) = min(H(ft,gt), H(fe,ge), H(ft,ge)+1, H(fe,gt)+1)
      +  
      + Bounding is based on the following observations. +
        +
      • If we already found two points at distance 0, there is no point in + continuing. Furthermore, +
      • 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.) +
      + The variable bound is set at the largest value of the distance + that we are still interested in. Therefore, we desist when +
      +    (bound == -1) and (F != not(G)) or (bound == 0) and (F == not(G)).
      +  
      + 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 +
      +    bound < minD,
      +  
      + except at the very beginning, when we have no value for + minD.

      + + However, we do not use bound < minD 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.

      + + When we compute H(ft,ge) and H(fe,gt) 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.

      + + Another important observation concerns the need of examining all + four pairs of cofators only when both f and + g depend on the top variable.

      + + Suppose gt == ge == g. (That is, g does + not depend on the top variable.) Then +

      +    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)) .
      +  
      + Therefore, under these circumstances, we skip the two "cross" cases.

      + + 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 < (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: +

      + H(f) = min(H(f0)+h0,H(f1)+h1) + + 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 */ diff --git a/distr/cudd/cuddRead.c b/distr/cudd/cuddRead.c new file mode 100644 index 0000000..a51527d --- /dev/null +++ b/distr/cudd/cuddRead.c @@ -0,0 +1,517 @@ +/**CFile*********************************************************************** + + FileName [cuddRead.c] + + PackageName [cudd] + + Synopsis [Functions to read in a matrix] + + Description [External procedures included in this module: +
        +
      • Cudd_addRead() +
      • Cudd_bddRead() +
      ] + + 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 "util.h" +#include "cuddInt.h" + + +/*---------------------------------------------------------------------------*/ +/* Constant declarations */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Stucture declarations */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Type declarations */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Variable declarations */ +/*---------------------------------------------------------------------------*/ + +#ifndef lint +static char rcsid[] DD_UNUSED = "$Id: cuddRead.c,v 1.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.

      + 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.

      + 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.

      + m and n are set to the numbers of rows and columns of the + matrix. Their values on input are immaterial. + The ADD for the + sparse matrix is returned in E, and its reference count is > 0. + Cudd_addRead returns 1 in case of success; 0 otherwise.] + + SideEffects [nx and ny are set to the numbers of row and column + variables. m and n are set to the numbers of rows and columns. x and y + are possibly extended to represent the array of row and column + variables. Similarly for xn and yn_, which hold on return from + Cudd_addRead the complements of the row and column variables.] + + SeeAlso [Cudd_addHarwell Cudd_bddRead] + +******************************************************************************/ +int +Cudd_addRead( + FILE * fp /* input file pointer */, + DdManager * dd /* DD manager */, + DdNode ** E /* characteristic function of the graph */, + DdNode *** x /* array of row variables */, + DdNode *** y /* array of column variables */, + DdNode *** xn /* array of complemented row variables */, + DdNode *** yn_ /* array of complemented column variables */, + int * nx /* number or row variables */, + int * ny /* number or column variables */, + int * m /* number of rows */, + int * n /* number of columns */, + int bx /* first index of row variables */, + int sx /* step of row variables */, + int by /* first index of column variables */, + int sy /* step of column variables */) +{ + DdNode *one, *zero; + DdNode *w, *neW; + DdNode *minterm1; + int u, v, err, i, nv; + int lnx, lny; + CUDD_VALUE_TYPE val; + DdNode **lx, **ly, **lxn, **lyn; + + one = DD_ONE(dd); + zero = DD_ZERO(dd); + + err = fscanf(fp, "%d %d", &u, &v); + if (err == EOF) { + return(0); + } else if (err != 2) { + return(0); + } + + *m = u; + /* Compute the number of x variables. */ + lx = *x; lxn = *xn; + u--; /* row and column numbers start from 0 */ + for (lnx=0; u > 0; lnx++) { + u >>= 1; + } + /* Here we rely on the fact that REALLOC of a null pointer is + ** translates to an ALLOC. + */ + if (lnx > *nx) { + *x = lx = REALLOC(DdNode *, *x, lnx); + if (lx == NULL) { + dd->errorCode = CUDD_MEMORY_OUT; + return(0); + } + *xn = lxn = REALLOC(DdNode *, *xn, lnx); + if (lxn == NULL) { + dd->errorCode = CUDD_MEMORY_OUT; + return(0); + } + } + + *n = v; + /* Compute the number of y variables. */ + ly = *y; lyn = *yn_; + v--; /* row and column numbers start from 0 */ + for (lny=0; v > 0; lny++) { + v >>= 1; + } + /* Here we rely on the fact that REALLOC of a null pointer is + ** translates to an ALLOC. + */ + if (lny > *ny) { + *y = ly = REALLOC(DdNode *, *y, lny); + if (ly == NULL) { + dd->errorCode = CUDD_MEMORY_OUT; + return(0); + } + *yn_ = lyn = REALLOC(DdNode *, *yn_, lny); + if (lyn == NULL) { + dd->errorCode = CUDD_MEMORY_OUT; + return(0); + } + } + + /* Create all new variables. */ + for (i = *nx, nv = bx + (*nx) * sx; i < lnx; i++, nv += sx) { + do { + dd->reordered = 0; + lx[i] = cuddUniqueInter(dd, nv, one, zero); + } while (dd->reordered == 1); + if (lx[i] == NULL) return(0); + cuddRef(lx[i]); + do { + dd->reordered = 0; + lxn[i] = cuddUniqueInter(dd, nv, zero, one); + } while (dd->reordered == 1); + if (lxn[i] == NULL) return(0); + cuddRef(lxn[i]); + } + for (i = *ny, nv = by + (*ny) * sy; i < lny; i++, nv += sy) { + do { + dd->reordered = 0; + ly[i] = cuddUniqueInter(dd, nv, one, zero); + } while (dd->reordered == 1); + if (ly[i] == NULL) return(0); + cuddRef(ly[i]); + do { + dd->reordered = 0; + lyn[i] = cuddUniqueInter(dd, nv, zero, one); + } while (dd->reordered == 1); + if (lyn[i] == NULL) return(0); + cuddRef(lyn[i]); + } + *nx = lnx; + *ny = lny; + + *E = dd->background; /* this call will never cause reordering */ + cuddRef(*E); + + while (! feof(fp)) { + err = fscanf(fp, "%d %d %lf", &u, &v, &val); + if (err == EOF) { + break; + } else if (err != 3) { + return(0); + } else if (u >= *m || v >= *n || u < 0 || v < 0) { + return(0); + } + + minterm1 = one; cuddRef(minterm1); + + /* Build minterm1 corresponding to this arc */ + for (i = lnx - 1; i>=0; i--) { + if (u & 1) { + w = Cudd_addApply(dd, Cudd_addTimes, minterm1, lx[i]); + } else { + w = Cudd_addApply(dd, Cudd_addTimes, minterm1, lxn[i]); + } + if (w == NULL) { + Cudd_RecursiveDeref(dd, minterm1); + return(0); + } + cuddRef(w); + Cudd_RecursiveDeref(dd, minterm1); + minterm1 = w; + u >>= 1; + } + for (i = lny - 1; i>=0; i--) { + if (v & 1) { + w = Cudd_addApply(dd, Cudd_addTimes, minterm1, ly[i]); + } else { + w = Cudd_addApply(dd, Cudd_addTimes, minterm1, lyn[i]); + } + if (w == NULL) { + Cudd_RecursiveDeref(dd, minterm1); + return(0); + } + cuddRef(w); + Cudd_RecursiveDeref(dd, minterm1); + minterm1 = w; + v >>= 1; + } + /* Create new constant node if necessary. + ** This call will never cause reordering. + */ + neW = cuddUniqueConst(dd, val); + if (neW == NULL) { + Cudd_RecursiveDeref(dd, minterm1); + return(0); + } + cuddRef(neW); + + w = Cudd_addIte(dd, minterm1, neW, *E); + if (w == NULL) { + Cudd_RecursiveDeref(dd, minterm1); + Cudd_RecursiveDeref(dd, neW); + return(0); + } + cuddRef(w); + Cudd_RecursiveDeref(dd, minterm1); + Cudd_RecursiveDeref(dd, neW); + Cudd_RecursiveDeref(dd, *E); + *E = w; + } + return(1); + +} /* end of Cudd_addRead */ + + +/**Function******************************************************************** + + Synopsis [Reads in a graph (without labels) given as a list of arcs.] + + Description [Reads in a graph (without labels) given as an adjacency + matrix. The first line of the input contains the numbers of rows and + columns of the adjacency matrix. The remaining lines contain the arcs + of the graph, one per line. Each arc is described by two integers, + i.e., the row and column number, or the indices of the two endpoints. + Cudd_bddRead produces a BDD that depends on two sets of variables: x + and y. The x variables (x\[0\] ... x\[nx-1\]) encode + the row index and the y variables (y\[0\] ... y\[ny-1\]) encode the + column index. x\[0\] and y\[0\] are the most significant bits in the + indices. + The variables may already exist or may be created by the function. + The index of x\[i\] is bx+i*sx, and the index of y\[i\] is by+i*sy.

      + 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.

      + m and n are set to the numbers of rows and columns of the + matrix. Their values on input are immaterial. The BDD for the graph + is returned in E, and its reference count is > 0. Cudd_bddRead returns + 1 in case of success; 0 otherwise.] + + SideEffects [nx and ny are set to the numbers of row and column + variables. m and n are set to the numbers of rows and columns. x and y + are possibly extended to represent the array of row and column + variables.] + + SeeAlso [Cudd_addHarwell Cudd_addRead] + +******************************************************************************/ +int +Cudd_bddRead( + FILE * fp /* input file pointer */, + DdManager * dd /* DD manager */, + DdNode ** E /* characteristic function of the graph */, + DdNode *** x /* array of row variables */, + DdNode *** y /* array of column variables */, + int * nx /* number or row variables */, + int * ny /* number or column variables */, + int * m /* number of rows */, + int * n /* number of columns */, + int bx /* first index of row variables */, + int sx /* step of row variables */, + int by /* first index of column variables */, + int sy /* step of column variables */) +{ + DdNode *one, *zero; + DdNode *w; + DdNode *minterm1; + int u, v, err, i, nv; + int lnx, lny; + DdNode **lx, **ly; + + one = DD_ONE(dd); + zero = Cudd_Not(one); + + err = fscanf(fp, "%d %d", &u, &v); + if (err == EOF) { + return(0); + } else if (err != 2) { + return(0); + } + + *m = u; + /* Compute the number of x variables. */ + lx = *x; + u--; /* row and column numbers start from 0 */ + for (lnx=0; u > 0; lnx++) { + u >>= 1; + } + if (lnx > *nx) { + *x = lx = REALLOC(DdNode *, *x, lnx); + if (lx == NULL) { + dd->errorCode = CUDD_MEMORY_OUT; + return(0); + } + } + + *n = v; + /* Compute the number of y variables. */ + ly = *y; + v--; /* row and column numbers start from 0 */ + for (lny=0; v > 0; lny++) { + v >>= 1; + } + if (lny > *ny) { + *y = ly = REALLOC(DdNode *, *y, lny); + if (ly == NULL) { + dd->errorCode = CUDD_MEMORY_OUT; + return(0); + } + } + + /* Create all new variables. */ + for (i = *nx, nv = bx + (*nx) * sx; i < lnx; i++, nv += sx) { + do { + dd->reordered = 0; + lx[i] = cuddUniqueInter(dd, nv, one, zero); + } while (dd->reordered == 1); + if (lx[i] == NULL) return(0); + cuddRef(lx[i]); + } + for (i = *ny, nv = by + (*ny) * sy; i < lny; i++, nv += sy) { + do { + dd->reordered = 0; + ly[i] = cuddUniqueInter(dd, nv, one, zero); + } while (dd->reordered == 1); + if (ly[i] == NULL) return(0); + cuddRef(ly[i]); + } + *nx = lnx; + *ny = lny; + + *E = zero; /* this call will never cause reordering */ + cuddRef(*E); + + while (! feof(fp)) { + err = fscanf(fp, "%d %d", &u, &v); + if (err == EOF) { + break; + } else if (err != 2) { + return(0); + } else if (u >= *m || v >= *n || u < 0 || v < 0) { + return(0); + } + + minterm1 = one; cuddRef(minterm1); + + /* Build minterm1 corresponding to this arc. */ + for (i = lnx - 1; i>=0; i--) { + if (u & 1) { + w = Cudd_bddAnd(dd, minterm1, lx[i]); + } else { + w = Cudd_bddAnd(dd, minterm1, Cudd_Not(lx[i])); + } + if (w == NULL) { + Cudd_RecursiveDeref(dd, minterm1); + return(0); + } + cuddRef(w); + Cudd_RecursiveDeref(dd,minterm1); + minterm1 = w; + u >>= 1; + } + for (i = lny - 1; i>=0; i--) { + if (v & 1) { + w = Cudd_bddAnd(dd, minterm1, ly[i]); + } else { + w = Cudd_bddAnd(dd, minterm1, Cudd_Not(ly[i])); + } + if (w == NULL) { + Cudd_RecursiveDeref(dd, minterm1); + return(0); + } + cuddRef(w); + Cudd_RecursiveDeref(dd, minterm1); + minterm1 = w; + v >>= 1; + } + + w = Cudd_bddAnd(dd, Cudd_Not(minterm1), Cudd_Not(*E)); + if (w == NULL) { + Cudd_RecursiveDeref(dd, minterm1); + return(0); + } + w = Cudd_Not(w); + cuddRef(w); + Cudd_RecursiveDeref(dd, minterm1); + Cudd_RecursiveDeref(dd, *E); + *E = w; + } + return(1); + +} /* end of Cudd_bddRead */ + +/*---------------------------------------------------------------------------*/ +/* Definition of internal functions */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Definition of static functions */ +/*---------------------------------------------------------------------------*/ + diff --git a/distr/cudd/cuddRef.c b/distr/cudd/cuddRef.c new file mode 100644 index 0000000..5e2f8b9 --- /dev/null +++ b/distr/cudd/cuddRef.c @@ -0,0 +1,808 @@ +/**CFile*********************************************************************** + + FileName [cuddRef.c] + + PackageName [cudd] + + Synopsis [Functions that manipulate the reference counts.] + + Description [External procedures included in this module: +

        +
      • Cudd_Ref() +
      • Cudd_RecursiveDeref() +
      • Cudd_IterDerefBdd() +
      • Cudd_DelayedDerefBdd() +
      • Cudd_RecursiveDerefZdd() +
      • Cudd_Deref() +
      • Cudd_CheckZeroRef() +
      + Internal procedures included in this module: +
        +
      • cuddReclaim() +
      • cuddReclaimZdd() +
      • cuddClearDeathRow() +
      • cuddShrinkDeathRow() +
      • cuddIsInDeathRow() +
      • cuddTimesInDeathRow() +
      + ] + + 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 */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* 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 = REALLOC(DdNodePtr,table->deathRow,2*table->deathRowDepth); + MMoutOfMemory = saveHandler; + if (newRow == NULL) { + table->nextDead = 0; + } else { + int i; + table->memused += table->deathRowDepth; + i = table->deathRowDepth; + table->deathRowDepth <<= 1; + for (; i < table->deathRowDepth; i++) { + newRow[i] = NULL; + } + table->deadMask = table->deathRowDepth - 1; + table->deathRow = newRow; + } + } else { + table->nextDead = 0; + } + } +#endif +#endif + +} /* end of Cudd_DelayedDerefBdd */ + + +/**Function******************************************************************** + + Synopsis [Decreases the reference count of ZDD node n.] + + Description [Decreases the reference count of ZDD node n. If n dies, + recursively decreases the reference counts of its children. It is + used to dispose of a ZDD that is no longer needed.] + + SideEffects [None] + + SeeAlso [Cudd_Deref Cudd_Ref Cudd_RecursiveDeref] + +******************************************************************************/ +void +Cudd_RecursiveDerefZdd( + DdManager * table, + DdNode * n) +{ + DdNode *N; + int ord; + DdNodePtr *stack = table->stack; + int SP = 1; + + N = n; + + do { +#ifdef DD_DEBUG + assert(N->ref != 0); +#endif + + cuddSatDec(N->ref); + + if (N->ref == 0) { + table->deadZ++; +#ifdef DD_STATS + table->nodesDropped++; +#endif +#ifdef DD_DEBUG + assert(!cuddIsConstant(N)); +#endif + ord = table->permZ[N->index]; + stack[SP++] = cuddE(N); + table->subtableZ[ord].dead++; + N = cuddT(N); + } else { + N = stack[--SP]; + } + } while (SP != 0); + +} /* end of Cudd_RecursiveDerefZdd */ + + +/**Function******************************************************************** + + Synopsis [Decreases the reference count of node.] + + Description [Decreases the reference count of node. It is primarily + used in recursive procedures to decrease the ref count of a result + node before returning it. This accomplishes the goal of removing the + protection applied by a previous Cudd_Ref.] + + SideEffects [None] + + SeeAlso [Cudd_RecursiveDeref Cudd_RecursiveDerefZdd Cudd_Ref] + +******************************************************************************/ +void +Cudd_Deref( + DdNode * node) +{ + node = Cudd_Regular(node); + cuddSatDec(node->ref); + +} /* end of Cudd_Deref */ + + +/**Function******************************************************************** + + Synopsis [Checks the unique table for nodes with non-zero reference + counts.] + + Description [Checks the unique table for nodes with non-zero + reference counts. It is normally called before Cudd_Quit to make sure + that there are no memory leaks due to missing Cudd_RecursiveDeref's. + Takes into account that reference counts may saturate and that the + basic constants and the projection functions are referenced by the + manager. Returns the number of nodes with non-zero reference count. + (Except for the cases mentioned above.)] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +int +Cudd_CheckZeroRef( + DdManager * manager) +{ + int size; + int i, j; + int remain; /* the expected number of remaining references to one */ + DdNodePtr *nodelist; + DdNode *node; + DdNode *sentinel = &(manager->sentinel); + DdSubtable *subtable; + int count = 0; + int index; + +#ifndef DD_NO_DEATH_ROW + cuddClearDeathRow(manager); +#endif + + /* First look at the BDD/ADD subtables. */ + remain = 1; /* reference from the manager */ + size = manager->size; + remain += 2 * size; /* reference from the BDD projection functions */ + + for (i = 0; i < size; i++) { + subtable = &(manager->subtables[i]); + nodelist = subtable->nodelist; + for (j = 0; (unsigned) j < subtable->slots; j++) { + node = nodelist[j]; + while (node != sentinel) { + if (node->ref != 0 && node->ref != DD_MAXREF) { + index = (int) node->index; + if (node != manager->vars[index]) { + count++; + } else { + if (node->ref != 1) { + count++; + } + } + } + node = node->next; + } + } + } + + /* Then look at the ZDD subtables. */ + size = manager->sizeZ; + if (size) /* references from ZDD universe */ + remain += 2; + + for (i = 0; i < size; i++) { + subtable = &(manager->subtableZ[i]); + nodelist = subtable->nodelist; + for (j = 0; (unsigned) j < subtable->slots; j++) { + node = nodelist[j]; + while (node != NULL) { + if (node->ref != 0 && node->ref != DD_MAXREF) { + index = (int) node->index; + if (node == manager->univ[manager->permZ[index]]) { + if (node->ref > 2) { + count++; + } + } else { + count++; + } + } + node = node->next; + } + } + } + + /* Now examine the constant table. Plusinfinity, minusinfinity, and + ** zero are referenced by the manager. One is referenced by the + ** manager, by the ZDD universe, and by all projection functions. + ** All other nodes should have no references. + */ + nodelist = manager->constants.nodelist; + for (j = 0; (unsigned) j < manager->constants.slots; j++) { + node = nodelist[j]; + while (node != NULL) { + if (node->ref != 0 && node->ref != DD_MAXREF) { + if (node == manager->one) { + if ((int) node->ref != remain) { + count++; + } + } else if (node == manager->zero || + node == manager->plusinfinity || + node == manager->minusinfinity) { + if (node->ref != 1) { + count++; + } + } else { + count++; + } + } + node = node->next; + } + } + return(count); + +} /* end of Cudd_CheckZeroRef */ + + +/*---------------------------------------------------------------------------*/ +/* Definition of internal functions */ +/*---------------------------------------------------------------------------*/ + + +/**Function******************************************************************** + + Synopsis [Brings children of a dead node back.] + + Description [] + + SideEffects [None] + + SeeAlso [cuddReclaimZdd] + +******************************************************************************/ +void +cuddReclaim( + DdManager * table, + DdNode * n) +{ + DdNode *N; + int ord; + DdNodePtr *stack = table->stack; + int SP = 1; + double initialDead = table->dead; + + N = Cudd_Regular(n); + +#ifdef DD_DEBUG + assert(N->ref == 0); +#endif + + do { + if (N->ref == 0) { + N->ref = 1; + table->dead--; + if (cuddIsConstant(N)) { + table->constants.dead--; + N = stack[--SP]; + } else { + ord = table->perm[N->index]; + stack[SP++] = Cudd_Regular(cuddE(N)); + table->subtables[ord].dead--; + N = cuddT(N); + } + } else { + cuddSatInc(N->ref); + N = stack[--SP]; + } + } while (SP != 0); + + N = Cudd_Regular(n); + cuddSatDec(N->ref); + table->reclaimed += initialDead - table->dead; + +} /* end of cuddReclaim */ + + +/**Function******************************************************************** + + Synopsis [Brings children of a dead ZDD node back.] + + Description [] + + SideEffects [None] + + SeeAlso [cuddReclaim] + +******************************************************************************/ +void +cuddReclaimZdd( + DdManager * table, + DdNode * n) +{ + DdNode *N; + int ord; + DdNodePtr *stack = table->stack; + int SP = 1; + + N = n; + +#ifdef DD_DEBUG + assert(N->ref == 0); +#endif + + do { + cuddSatInc(N->ref); + + if (N->ref == 1) { + table->deadZ--; + table->reclaimed++; +#ifdef DD_DEBUG + assert(!cuddIsConstant(N)); +#endif + ord = table->permZ[N->index]; + stack[SP++] = cuddE(N); + table->subtableZ[ord].dead--; + N = cuddT(N); + } else { + N = stack[--SP]; + } + } while (SP != 0); + + cuddSatDec(n->ref); + +} /* end of cuddReclaimZdd */ + + +/**Function******************************************************************** + + Synopsis [Shrinks the death row.] + + Description [Shrinks the death row by a factor of four.] + + SideEffects [None] + + SeeAlso [cuddClearDeathRow] + +******************************************************************************/ +void +cuddShrinkDeathRow( + DdManager *table) +{ +#ifndef DD_NO_DEATH_ROW + int i; + + if (table->deathRowDepth > 3) { + for (i = table->deathRowDepth/4; i < table->deathRowDepth; i++) { + if (table->deathRow[i] == NULL) break; + Cudd_IterDerefBdd(table,table->deathRow[i]); + table->deathRow[i] = NULL; + } + table->deathRowDepth /= 4; + table->deadMask = table->deathRowDepth - 1; + if ((unsigned) table->nextDead > table->deadMask) { + table->nextDead = 0; + } + table->deathRow = REALLOC(DdNodePtr, table->deathRow, + table->deathRowDepth); + } +#endif + +} /* end of cuddShrinkDeathRow */ + + +/**Function******************************************************************** + + Synopsis [Clears the death row.] + + Description [] + + SideEffects [None] + + SeeAlso [Cudd_DelayedDerefBdd Cudd_IterDerefBdd Cudd_CheckZeroRef + cuddGarbageCollect] + +******************************************************************************/ +void +cuddClearDeathRow( + DdManager *table) +{ +#ifndef DD_NO_DEATH_ROW + int i; + + for (i = 0; i < table->deathRowDepth; i++) { + if (table->deathRow[i] == NULL) break; + Cudd_IterDerefBdd(table,table->deathRow[i]); + table->deathRow[i] = NULL; + } +#ifdef DD_DEBUG + for (; i < table->deathRowDepth; i++) { + assert(table->deathRow[i] == NULL); + } +#endif + table->nextDead = 0; +#endif + +} /* end of cuddClearDeathRow */ + + +/**Function******************************************************************** + + Synopsis [Checks whether a node is in the death row.] + + Description [Checks whether a node is in the death row. Returns the + position of the first occurrence if the node is present; -1 + otherwise.] + + SideEffects [None] + + SeeAlso [Cudd_DelayedDerefBdd cuddClearDeathRow] + +******************************************************************************/ +int +cuddIsInDeathRow( + DdManager *dd, + DdNode *f) +{ +#ifndef DD_NO_DEATH_ROW + int i; + + for (i = 0; i < dd->deathRowDepth; i++) { + if (f == dd->deathRow[i]) { + return(i); + } + } +#endif + + return(-1); + +} /* end of cuddIsInDeathRow */ + + +/**Function******************************************************************** + + Synopsis [Counts how many times a node is in the death row.] + + Description [] + + SideEffects [None] + + SeeAlso [Cudd_DelayedDerefBdd cuddClearDeathRow cuddIsInDeathRow] + +******************************************************************************/ +int +cuddTimesInDeathRow( + DdManager *dd, + DdNode *f) +{ + int count = 0; +#ifndef DD_NO_DEATH_ROW + int i; + + for (i = 0; i < dd->deathRowDepth; i++) { + count += f == dd->deathRow[i]; + } +#endif + + return(count); + +} /* end of cuddTimesInDeathRow */ + +/*---------------------------------------------------------------------------*/ +/* Definition of static functions */ +/*---------------------------------------------------------------------------*/ diff --git a/distr/cudd/cuddReorder.c b/distr/cudd/cuddReorder.c new file mode 100644 index 0000000..61f1c88 --- /dev/null +++ b/distr/cudd/cuddReorder.c @@ -0,0 +1,2129 @@ +/**CFile*********************************************************************** + + FileName [cuddReorder.c] + + PackageName [cudd] + + Synopsis [Functions for dynamic variable reordering.] + + Description [External procedures included in this file: +
        +
      • Cudd_ReduceHeap() +
      • Cudd_ShuffleHeap() +
      + Internal procedures included in this module: +
        +
      • cuddDynamicAllocNode() +
      • cuddSifting() +
      • cuddSwapping() +
      • cuddNextHigh() +
      • cuddNextLow() +
      • cuddSwapInPlace() +
      • cuddBddAlignToZdd() +
      + Static procedures included in this module: +
        +
      • ddUniqueCompare() +
      • ddSwapAny() +
      • ddSiftingAux() +
      • ddSiftingUp() +
      • ddSiftingDown() +
      • ddSiftingBackward() +
      • ddReorderPreprocess() +
      • ddReorderPostprocess() +
      • ddShuffle() +
      • ddSiftUp() +
      • bddFixTree() +
      ] + + 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 "util.h" +#include "cuddInt.h" + +/*---------------------------------------------------------------------------*/ +/* 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: +
        +
      • Swapping +
      • Sifting +
      • Symmetric Sifting +
      • Group Sifting +
      • Window Permutation +
      • Simulated Annealing +
      • Genetic Algorithm +
      • Dynamic Programming (exact) +
      + + For sifting, symmetric sifting, group sifting, and window + permutation it is possible to request reordering to convergence.

      + + 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 = ALLOC(int, table->size); + for (i = 0; i < table->size; i++) + perm[permutation[i]] = i; + if (!ddCheckPermuation(table,table->tree,perm,permutation)) { + FREE(perm); + return(0); + } + if (!ddUpdateMtrTree(table,table->tree,perm,permutation)) { + FREE(perm); + return(0); + } + 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 *) ALLOC(DdNode, DD_MEM_CHUNK + 1); + MMoutOfMemory = saveHandler; + if (mem == NULL && table->stash != NULL) { + 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 *) ALLOC(DdNode,DD_MEM_CHUNK + 1); + } + 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); +#ifdef DD_DEBUG + assert(((unsigned long) mem & (sizeof(DdNode) - 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. +

        +
      1. Order all the variables according to the number of entries + in each unique table. +
      2. Sift the variable up and down, remembering each time the + total size of the DD heap. +
      3. Select the best permutation. +
      4. Repeat 3 and 4 for all variables. +
      + 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 = ALLOC(int,size); + if (entry == NULL) { + table->errorCode = CUDD_MEMORY_OUT; + goto cuddSiftingOutOfMem; + } + var = 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 + } + + FREE(var); + FREE(entry); + + return(1); + +cuddSiftingOutOfMem: + + if (entry != NULL) FREE(entry); + if (var != NULL) 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. +
        +
      1. Select two variables (RANDOM or HEURISTIC). +
      2. Permute these variables. +
      3. If the nodes have decreased accept the permutation. +
      4. Otherwise reconstruct the original heap. +
      5. Loop. +
      + 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; + 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 < 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 = 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); + 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(f1, 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(f11, 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(f10, 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(newf1, 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 + M be the ratio of the two numbers. cuddBddAlignToZdd + then considers the ZDD variables from M*i to + (M+1)*i-1 as corresponding to BDD variable + i. 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 = 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); + FREE(invperm); + /* Free interaction matrix. */ + 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. */ + 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) +{ + unsigned 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) +{ + unsigned 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); +} diff --git a/distr/cudd/cuddSat.c b/distr/cudd/cuddSat.c new file mode 100644 index 0000000..ce5d59a --- /dev/null +++ b/distr/cudd/cuddSat.c @@ -0,0 +1,1338 @@ +/**CFile*********************************************************************** + + FileName [cuddSat.c] + + PackageName [cudd] + + Synopsis [Functions for the solution of satisfiability related + problems.] + + Description [External procedures included in this file: +
        +
      • Cudd_Eval() +
      • Cudd_ShortestPath() +
      • Cudd_LargestCube() +
      • Cudd_ShortestLength() +
      • Cudd_Decreasing() +
      • Cudd_Increasing() +
      • Cudd_EquivDC() +
      • Cudd_bddLeqUnless() +
      • Cudd_EqualSupNorm() +
      • Cudd_bddMakePrime() +
      + Internal procedures included in this module: +
        +
      • cuddBddMakePrime() +
      + Static procedures included in this module: +
        +
      • freePathPair() +
      • getShortest() +
      • getPath() +
      • getLargest() +
      • getCube() +
      ] + + 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 "util.h" +#include "cuddInt.h" + +/*---------------------------------------------------------------------------*/ +/* 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, F, &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, F, &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, F, &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 pr 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; + 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, my_root, &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 = 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, Cudd_Regular(T), &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, Cudd_Regular(E), &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, my_root, &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 = 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, Cudd_Regular(T), &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, Cudd_Regular(E), &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 */ diff --git a/distr/cudd/cuddSign.c b/distr/cudd/cuddSign.c new file mode 100644 index 0000000..a6b209c --- /dev/null +++ b/distr/cudd/cuddSign.c @@ -0,0 +1,318 @@ +/**CFile*********************************************************************** + + FileName [cuddSign.c] + + PackageName [cudd] + + Synopsis [Computation of signatures.] + + Description [External procedures included in this module: +
        +
      • Cudd_CofMinterm(); +
      + Static procedures included in this module: +
        +
      • ddCofMintermAux() +
      + ] + + 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 */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* 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 = ALLOC(double,size + 1); + if (result != NULL) { +#ifdef DD_STATS + table_mem += (size + 1) * sizeof(double); +#endif + if (Cudd_IsConstant(node)) + firstLevel = 1; + else + firstLevel = cuddI(dd,Cudd_Regular(node)->index); + for (i = 0; i < size; i++) { + if (i >= cuddI(dd,Cudd_Regular(node)->index)) { + result[dd->invperm[i]] = values[i - firstLevel]; + } else { + result[dd->invperm[i]] = values[size - firstLevel]; + } + } + result[size] = values[size - firstLevel]; + } else { + dd->errorCode = CUDD_MEMORY_OUT; + } + } + +#ifdef DD_STATS + table_mem += table->num_bins * sizeof(st_table_entry *); +#endif + if (Cudd_Regular(node)->ref == 1) FREE(values); + st_foreach(table, cuddStCountfree, NULL); + st_free_table(table); +#ifdef DD_STATS + (void) fprintf(dd->out,"Number of calls: %d\tTable memory: %d bytes\n", + num_calls, table_mem); + (void) fprintf(dd->out,"Time to compute measures: %s\n", + util_print_time(util_cpu_time() - startTime)); +#endif + if (result == NULL) { + (void) fprintf(dd->out, + "out-of-memory, couldn't measure DD cofactors.\n"); + dd->errorCode = CUDD_MEMORY_OUT; + } + return(result); + +} /* end of Cudd_CofMinterm */ + + +/*---------------------------------------------------------------------------*/ +/* Definition of internal functions */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Definition of static functions */ +/*---------------------------------------------------------------------------*/ + + +/**Function******************************************************************** + + Synopsis [Recursive Step for Cudd_CofMinterm function.] + + Description [Traverses the DD node and computes the fraction of + minterms in the on-set of all positive cofactors simultaneously. + It allocates an array with two more entries than there are + variables below the one labeling the node. One extra entry (the + first in the array) is for the variable labeling the node. The other + entry (the last one in the array) holds the fraction of minterms of + the function rooted at node. Each other entry holds the value for + one cofactor. The array is put in a symbol table, to avoid repeated + computation, and its address is returned by the procedure, for use + by the caller. Returns a pointer to the array of cofactor measures.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +static double * +ddCofMintermAux( + DdManager * dd, + DdNode * node, + st_table * table) +{ + DdNode *N; /* regular version of node */ + DdNode *Nv, *Nnv; + double *values; + double *valuesT, *valuesE; + int i; + int localSize, localSizeT, localSizeE; + double vT, vE; + + statLine(dd); +#ifdef DD_STATS + num_calls++; +#endif + + if (st_lookup(table, node, &values)) { + return(values); + } + + N = Cudd_Regular(node); + if (cuddIsConstant(N)) { + localSize = 1; + } else { + localSize = size - cuddI(dd,N->index) + 1; + } + values = ALLOC(double, localSize); + if (values == NULL) { + dd->errorCode = CUDD_MEMORY_OUT; + return(NULL); + } + + if (cuddIsConstant(N)) { + if (node == DD_ZERO(dd) || node == Cudd_Not(DD_ONE(dd))) { + values[0] = 0.0; + } else { + values[0] = 1.0; + } + } else { + Nv = Cudd_NotCond(cuddT(N),N!=node); + Nnv = Cudd_NotCond(cuddE(N),N!=node); + + valuesT = ddCofMintermAux(dd, Nv, table); + if (valuesT == NULL) return(NULL); + valuesE = ddCofMintermAux(dd, Nnv, table); + if (valuesE == NULL) return(NULL); + + if (Cudd_IsConstant(Nv)) { + localSizeT = 1; + } else { + localSizeT = size - cuddI(dd,Cudd_Regular(Nv)->index) + 1; + } + if (Cudd_IsConstant(Nnv)) { + localSizeE = 1; + } else { + localSizeE = size - cuddI(dd,Cudd_Regular(Nnv)->index) + 1; + } + values[0] = valuesT[localSizeT - 1]; + for (i = 1; i < localSize; i++) { + if (i >= cuddI(dd,Cudd_Regular(Nv)->index) - cuddI(dd,N->index)) { + vT = valuesT[i - cuddI(dd,Cudd_Regular(Nv)->index) + + cuddI(dd,N->index)]; + } else { + vT = valuesT[localSizeT - 1]; + } + if (i >= cuddI(dd,Cudd_Regular(Nnv)->index) - cuddI(dd,N->index)) { + vE = valuesE[i - cuddI(dd,Cudd_Regular(Nnv)->index) + + cuddI(dd,N->index)]; + } else { + vE = valuesE[localSizeE - 1]; + } + values[i] = (vT + vE) / 2.0; + } + if (Cudd_Regular(Nv)->ref == 1) FREE(valuesT); + if (Cudd_Regular(Nnv)->ref == 1) FREE(valuesE); + } + + if (N->ref > 1) { + if (st_add_direct(table, (char *) node, (char *) values) == ST_OUT_OF_MEM) { + FREE(values); + return(NULL); + } +#ifdef DD_STATS + table_mem += localSize * sizeof(double) + sizeof(st_table_entry); +#endif + } + return(values); + +} /* end of ddCofMintermAux */ diff --git a/distr/cudd/cuddSolve.c b/distr/cudd/cuddSolve.c new file mode 100644 index 0000000..217d49e --- /dev/null +++ b/distr/cudd/cuddSolve.c @@ -0,0 +1,366 @@ +/**CFile*********************************************************************** + + FileName [cuddSolve.c] + + PackageName [cudd] + + Synopsis [Boolean equation solver and related functions.] + + Description [External functions included in this modoule: +
        +
      • Cudd_SolveEqn() +
      • Cudd_VerifySol() +
      + Internal functions included in this module: +
        +
      • cuddSolveEqnRecur() +
      • cuddVerifySol() +
      ] + + 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 "util.h" +#include "cuddInt.h" + +/*---------------------------------------------------------------------------*/ +/* Constant declarations */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Type declarations */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Structure declarations */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Variable declarations */ +/*---------------------------------------------------------------------------*/ + +#ifndef lint +static char rcsid[] DD_UNUSED = "$Id: cuddSolve.c,v 1.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 = ALLOC(int, n); + if (temp == NULL) { + bdd->errorCode = CUDD_MEMORY_OUT; + (void) fprintf(bdd->out, + "Cudd_SolveEqn: Out of memory for yIndex\n"); + return(NULL); + } + + do { + bdd->reordered = 0; + res = cuddSolveEqnRecur(bdd, F, Y, G, n, temp, 0); + } while (bdd->reordered == 1); + + return(res); + +} /* end of Cudd_SolveEqn */ + + +/**Function******************************************************************** + + Synopsis [Checks the solution of F(x,y) = 0.] + + Description [Checks the solution of F(x,y) = 0. This procedure + substitutes the solution components for the unknowns of F and returns + the resulting BDD for F.] + + SideEffects [Frees the memory pointed by yIndex.] + + SeeAlso [Cudd_SolveEqn] + +******************************************************************************/ +DdNode * +Cudd_VerifySol( + DdManager * bdd, + DdNode * F /* the left-hand side of the equation */, + DdNode ** G /* the array of solutions */, + int * yIndex /* index of y variables */, + int n /* numbers of unknowns */) +{ + DdNode *res; + + do { + bdd->reordered = 0; + res = cuddVerifySol(bdd, F, G, yIndex, n); + } while (bdd->reordered == 1); + + FREE(yIndex); + + return(res); + +} /* end of Cudd_VerifySol */ + + +/*---------------------------------------------------------------------------*/ +/* Definition of internal functions */ +/*---------------------------------------------------------------------------*/ + + +/**Function******************************************************************** + + Synopsis [Implements the recursive step of Cudd_SolveEqn.] + + Description [Implements the recursive step of Cudd_SolveEqn. + Returns NULL if the intermediate solution blows up + or reordering occurs. The parametric solutions are + stored in the array G.] + + SideEffects [none] + + SeeAlso [Cudd_SolveEqn, Cudd_VerifySol] + +******************************************************************************/ +DdNode * +cuddSolveEqnRecur( + DdManager * bdd, + DdNode * F /* the left-hand side of the equation */, + DdNode * Y /* the cube of remaining y variables */, + DdNode ** G /* the array of solutions */, + int n /* number of unknowns */, + int * yIndex /* array holding the y variable indices */, + int i /* level of recursion */) +{ + DdNode *Fn, *Fm1, *Fv, *Fvbar, *T, *w, *nextY, *one; + DdNodePtr *variables; + + int j; + + statLine(bdd); + variables = bdd->vars; + one = DD_ONE(bdd); + + /* Base condition. */ + if (Y == one) { + return F; + } + + /* Cofactor of Y. */ + yIndex[i] = Y->index; + nextY = Cudd_T(Y); + + /* Universal abstraction of F with respect to the top variable index. */ + Fm1 = cuddBddExistAbstractRecur(bdd, Cudd_Not(F), variables[yIndex[i]]); + if (Fm1) { + Fm1 = Cudd_Not(Fm1); + cuddRef(Fm1); + } else { + return(NULL); + } + + Fn = cuddSolveEqnRecur(bdd, Fm1, nextY, G, n, yIndex, i+1); + if (Fn) { + cuddRef(Fn); + } else { + Cudd_RecursiveDeref(bdd, Fm1); + return(NULL); + } + + Fv = cuddCofactorRecur(bdd, F, variables[yIndex[i]]); + if (Fv) { + cuddRef(Fv); + } else { + Cudd_RecursiveDeref(bdd, Fm1); + Cudd_RecursiveDeref(bdd, Fn); + return(NULL); + } + + Fvbar = cuddCofactorRecur(bdd, F, Cudd_Not(variables[yIndex[i]])); + if (Fvbar) { + cuddRef(Fvbar); + } else { + Cudd_RecursiveDeref(bdd, Fm1); + Cudd_RecursiveDeref(bdd, Fn); + Cudd_RecursiveDeref(bdd, Fv); + return(NULL); + } + + /* Build i-th component of the solution. */ + w = cuddBddIteRecur(bdd, variables[yIndex[i]], Cudd_Not(Fv), Fvbar); + if (w) { + cuddRef(w); + } else { + Cudd_RecursiveDeref(bdd, Fm1); + Cudd_RecursiveDeref(bdd, Fn); + Cudd_RecursiveDeref(bdd, Fv); + Cudd_RecursiveDeref(bdd, Fvbar); + return(NULL); + } + + T = cuddBddRestrictRecur(bdd, w, Cudd_Not(Fm1)); + if(T) { + cuddRef(T); + } else { + Cudd_RecursiveDeref(bdd, Fm1); + Cudd_RecursiveDeref(bdd, Fn); + Cudd_RecursiveDeref(bdd, Fv); + Cudd_RecursiveDeref(bdd, Fvbar); + Cudd_RecursiveDeref(bdd, w); + return(NULL); + } + + Cudd_RecursiveDeref(bdd,Fm1); + Cudd_RecursiveDeref(bdd,w); + Cudd_RecursiveDeref(bdd,Fv); + Cudd_RecursiveDeref(bdd,Fvbar); + + /* Substitute components of solution already found into solution. */ + for (j = n-1; j > i; j--) { + w = cuddBddComposeRecur(bdd,T, G[j], variables[yIndex[j]]); + if(w) { + cuddRef(w); + } else { + Cudd_RecursiveDeref(bdd, Fn); + Cudd_RecursiveDeref(bdd, T); + return(NULL); + } + Cudd_RecursiveDeref(bdd,T); + T = w; + } + G[i] = T; + + Cudd_Deref(Fn); + + return(Fn); + +} /* end of cuddSolveEqnRecur */ + + +/**Function******************************************************************** + + Synopsis [Implements the recursive step of Cudd_VerifySol. ] + + Description [] + + SideEffects [none] + + SeeAlso [Cudd_VerifySol] + +******************************************************************************/ +DdNode * +cuddVerifySol( + DdManager * bdd, + DdNode * F /* the left-hand side of the equation */, + DdNode ** G /* the array of solutions */, + int * yIndex /* array holding the y variable indices */, + int n /* number of unknowns */) +{ + DdNode *w, *R; + + int j; + + R = F; + cuddRef(R); + for(j = n - 1; j >= 0; j--) { + w = Cudd_bddCompose(bdd, R, G[j], yIndex[j]); + if (w) { + cuddRef(w); + } else { + return(NULL); + } + Cudd_RecursiveDeref(bdd,R); + R = w; + } + + cuddDeref(R); + + return(R); + +} /* end of cuddVerifySol */ + + +/*---------------------------------------------------------------------------*/ +/* Definition of static functions */ +/*---------------------------------------------------------------------------*/ + diff --git a/distr/cudd/cuddSplit.c b/distr/cudd/cuddSplit.c new file mode 100644 index 0000000..89aed06 --- /dev/null +++ b/distr/cudd/cuddSplit.c @@ -0,0 +1,686 @@ +/**CFile*********************************************************************** + + FileName [cuddSplit.c] + + PackageName [cudd] + + Synopsis [Returns a subset of minterms from a boolean function.] + + Description [External functions included in this modoule: +
        +
      • Cudd_SplitSet() +
      + Internal functions included in this module: +
        +
      • cuddSplitSetRecur() + + Static functions included in this module: +
          +
        • selectMintermsFromUniverse() +
        • mintermsFromUniverse() +
        • bddAnnotateMintermCount() +
        ] + + 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 "util.h" +#include "cuddInt.h" + +/*---------------------------------------------------------------------------*/ +/* Constant declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Type declarations */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Structure declarations */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Variable declarations */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Macro declarations */ +/*---------------------------------------------------------------------------*/ + + +/**AutomaticStart*************************************************************/ + +/*---------------------------------------------------------------------------*/ +/* Static function prototypes */ +/*---------------------------------------------------------------------------*/ + +static DdNode * selectMintermsFromUniverse (DdManager *manager, int *varSeen, double n); +static DdNode * mintermsFromUniverse (DdManager *manager, DdNode **vars, int numVars, double n, int index); +static double bddAnnotateMintermCount (DdManager *manager, DdNode *node, double max, st_table *table); + +/**AutomaticEnd***************************************************************/ + + +/*---------------------------------------------------------------------------*/ +/* Definition of exported functions */ +/*---------------------------------------------------------------------------*/ + + +/**Function******************************************************************** + + Synopsis [Returns m minterms from a BDD.] + + Description [Returns m minterms from a BDD whose + support has n variables at most. The procedure tries + to create as few extra nodes as possible. The function represented + by S depends on at most n of the variables + in xVars. Returns a BDD with m minterms + of the on-set of S if successful; NULL otherwise.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +DdNode * +Cudd_SplitSet( + DdManager * manager, + DdNode * S, + DdNode ** xVars, + int n, + double m) +{ + DdNode *result; + DdNode *zero, *one; + double max, num; + st_table *mtable; + int *varSeen; + int i,index, size; + + size = manager->size; + one = DD_ONE(manager); + zero = Cudd_Not(one); + + /* Trivial cases. */ + if (m == 0.0) { + return(zero); + } + if (S == zero) { + return(NULL); + } + + max = pow(2.0,(double)n); + if (m > max) + return(NULL); + + do { + manager->reordered = 0; + /* varSeen is used to mark the variables that are encountered + ** while traversing the BDD S. + */ + varSeen = ALLOC(int, size); + if (varSeen == NULL) { + manager->errorCode = CUDD_MEMORY_OUT; + return(NULL); + } + for (i = 0; i < size; i++) { + varSeen[i] = -1; + } + for (i = 0; i < n; i++) { + index = (xVars[i])->index; + varSeen[manager->invperm[index]] = 0; + } + + if (S == one) { + if (m == max) { + FREE(varSeen); + return(S); + } + result = selectMintermsFromUniverse(manager,varSeen,m); + if (result) + cuddRef(result); + FREE(varSeen); + } else { + mtable = st_init_table(st_ptrcmp,st_ptrhash); + if (mtable == NULL) { + (void) fprintf(manager->out, + "Cudd_SplitSet: out-of-memory.\n"); + FREE(varSeen); + manager->errorCode = CUDD_MEMORY_OUT; + return(NULL); + } + /* The nodes of BDD S are annotated by the number of minterms + ** in their onset. The node and the number of minterms in its + ** onset are stored in mtable. + */ + num = bddAnnotateMintermCount(manager,S,max,mtable); + if (m == num) { + st_foreach(mtable,cuddStCountfree,NIL(char)); + st_free_table(mtable); + FREE(varSeen); + return(S); + } + + result = cuddSplitSetRecur(manager,mtable,varSeen,S,m,max,0); + if (result) + cuddRef(result); + st_foreach(mtable,cuddStCountfree,NULL); + st_free_table(mtable); + FREE(varSeen); + } + } while (manager->reordered == 1); + + cuddDeref(result); + return(result); + +} /* end of Cudd_SplitSet */ + + +/*---------------------------------------------------------------------------*/ +/* Definition of internal functions */ +/*---------------------------------------------------------------------------*/ + +/**Function******************************************************************** + + Synopsis [Implements the recursive step of Cudd_SplitSet.] + + Description [Implements the recursive step of Cudd_SplitSet. The + procedure recursively traverses the BDD and checks to see if any + node satisfies the minterm requirements as specified by 'n'. At any + node X, n is compared to the number of minterms in the onset of X's + children. If either of the child nodes have exactly n minterms, then + that node is returned; else, if n is greater than the onset of one + of the child nodes, that node is retained and the difference in the + number of minterms is extracted from the other child. In case n + minterms can be extracted from constant 1, the algorithm returns the + result with at most log(n) nodes.] + + SideEffects [The array 'varSeen' is updated at every recursive call + to set the variables traversed by the procedure.] + + SeeAlso [] + +******************************************************************************/ +DdNode* +cuddSplitSetRecur( + DdManager * manager, + st_table * mtable, + int * varSeen, + DdNode * p, + double n, + double max, + int index) +{ + DdNode *one, *zero, *N, *Nv; + DdNode *Nnv, *q, *r, *v; + DdNode *result; + double *dummy, numT, numE; + int variable, positive; + + statLine(manager); + one = DD_ONE(manager); + zero = Cudd_Not(one); + + /* If p is constant, extract n minterms from constant 1. The procedure by + ** construction guarantees that minterms will not be extracted from + ** constant 0. + */ + if (Cudd_IsConstant(p)) { + q = selectMintermsFromUniverse(manager,varSeen,n); + return(q); + } + + N = Cudd_Regular(p); + + /* Set variable as seen. */ + variable = N->index; + varSeen[manager->invperm[variable]] = -1; + + Nv = cuddT(N); + Nnv = cuddE(N); + if (Cudd_IsComplement(p)) { + Nv = Cudd_Not(Nv); + Nnv = Cudd_Not(Nnv); + } + + /* If both the children of 'p' are constants, extract n minterms from a + ** constant node. + */ + if (Cudd_IsConstant(Nv) && Cudd_IsConstant(Nnv)) { + q = selectMintermsFromUniverse(manager,varSeen,n); + if (q == NULL) { + return(NULL); + } + cuddRef(q); + r = cuddBddAndRecur(manager,p,q); + if (r == NULL) { + Cudd_RecursiveDeref(manager,q); + return(NULL); + } + cuddRef(r); + Cudd_RecursiveDeref(manager,q); + cuddDeref(r); + return(r); + } + + /* Lookup the # of minterms in the onset of the node from the table. */ + if (!Cudd_IsConstant(Nv)) { + if (!st_lookup(mtable, Nv, &dummy)) return(NULL); + numT = *dummy/(2*(1<size; + one = DD_ONE(manager); + zero = Cudd_Not(one); + + /* Count the number of variables not encountered so far in procedure + ** cuddSplitSetRecur. + */ + for (i = size-1; i >= 0; i--) { + if(varSeen[i] == 0) + numVars++; + } + vars = ALLOC(DdNode *, numVars); + if (!vars) { + manager->errorCode = CUDD_MEMORY_OUT; + return(NULL); + } + + j = 0; + for (i = size-1; i >= 0; i--) { + if(varSeen[i] == 0) { + vars[j] = cuddUniqueInter(manager,manager->perm[i],one,zero); + cuddRef(vars[j]); + j++; + } + } + + /* Compute a function which has n minterms and depends on at most + ** numVars variables. + */ + result = mintermsFromUniverse(manager,vars,numVars,n, 0); + if (result) + cuddRef(result); + + for (i = 0; i < numVars; i++) + Cudd_RecursiveDeref(manager,vars[i]); + FREE(vars); + + return(result); + +} /* end of selectMintermsFromUniverse */ + + +/**Function******************************************************************** + + Synopsis [Recursive procedure to extract n mintems from constant 1.] + + Description [Recursive procedure to extract n mintems from constant 1.] + + SideEffects [None] + +******************************************************************************/ +static DdNode * +mintermsFromUniverse( + DdManager * manager, + DdNode ** vars, + int numVars, + double n, + int index) +{ + DdNode *one, *zero; + DdNode *q, *result; + double max, max2; + + statLine(manager); + one = DD_ONE(manager); + zero = Cudd_Not(one); + + max = pow(2.0, (double)numVars); + max2 = max / 2.0; + + if (n == max) + return(one); + if (n == 0.0) + return(zero); + /* if n == 2^(numVars-1), return a single variable */ + if (n == max2) + return vars[index]; + else if (n > max2) { + /* When n > 2^(numVars-1), a single variable vars[index] + ** contains 2^(numVars-1) minterms. The rest are extracted + ** from a constant with 1 less variable. + */ + q = mintermsFromUniverse(manager,vars,numVars-1,(n-max2),index+1); + if (q == NULL) + return(NULL); + cuddRef(q); + result = cuddBddIteRecur(manager,vars[index],one,q); + } else { + /* When n < 2^(numVars-1), a literal of variable vars[index] + ** is selected. The required n minterms are extracted from a + ** constant with 1 less variable. + */ + q = mintermsFromUniverse(manager,vars,numVars-1,n,index+1); + if (q == NULL) + return(NULL); + cuddRef(q); + result = cuddBddAndRecur(manager,vars[index],q); + } + + if (result == NULL) { + Cudd_RecursiveDeref(manager,q); + return(NULL); + } + cuddRef(result); + Cudd_RecursiveDeref(manager,q); + cuddDeref(result); + return(result); + +} /* end of mintermsFromUniverse */ + + +/**Function******************************************************************** + + Synopsis [Annotates every node in the BDD node with its minterm count.] + + Description [Annotates every node in the BDD node with its minterm count. + In this function, every node and the minterm count represented by it are + stored in a hash table.] + + SideEffects [Fills up 'table' with the pair .] + +******************************************************************************/ +static double +bddAnnotateMintermCount( + DdManager * manager, + DdNode * node, + double max, + st_table * table) +{ + + DdNode *N,*Nv,*Nnv; + register double min_v,min_nv; + register double min_N; + double *pmin; + double *dummy; + + statLine(manager); + N = Cudd_Regular(node); + if (cuddIsConstant(N)) { + if (node == DD_ONE(manager)) { + return(max); + } else { + return(0.0); + } + } + + if (st_lookup(table, node, &dummy)) { + return(*dummy); + } + + Nv = cuddT(N); + Nnv = cuddE(N); + if (N != node) { + Nv = Cudd_Not(Nv); + Nnv = Cudd_Not(Nnv); + } + + /* Recur on the two branches. */ + min_v = bddAnnotateMintermCount(manager,Nv,max,table) / 2.0; + if (min_v == (double)CUDD_OUT_OF_MEM) + return ((double)CUDD_OUT_OF_MEM); + min_nv = bddAnnotateMintermCount(manager,Nnv,max,table) / 2.0; + if (min_nv == (double)CUDD_OUT_OF_MEM) + return ((double)CUDD_OUT_OF_MEM); + min_N = min_v + min_nv; + + pmin = ALLOC(double,1); + if (pmin == NULL) { + manager->errorCode = CUDD_MEMORY_OUT; + return((double)CUDD_OUT_OF_MEM); + } + *pmin = min_N; + + if (st_insert(table,(char *)node, (char *)pmin) == ST_OUT_OF_MEM) { + FREE(pmin); + return((double)CUDD_OUT_OF_MEM); + } + + return(min_N); + +} /* end of bddAnnotateMintermCount */ diff --git a/distr/cudd/cuddSubsetHB.c b/distr/cudd/cuddSubsetHB.c new file mode 100644 index 0000000..43713fe --- /dev/null +++ b/distr/cudd/cuddSubsetHB.c @@ -0,0 +1,1329 @@ +/**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: +
          +
        • Cudd_SubsetHeavyBranch() +
        • Cudd_SupersetHeavyBranch() +
        + Internal procedures included in this module: +
          +
        • cuddSubsetHeavyBranch() +
        + Static procedures included in this module: +
          +
        • ResizeCountMintermPages(); +
        • ResizeNodeDataPages() +
        • ResizeCountNodePages() +
        • SubsetCountMintermAux() +
        • SubsetCountMinterm() +
        • SubsetCountNodesAux() +
        • SubsetCountNodes() +
        • BuildSubsetBdd() +
        + ] + + 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 +#else +#define DBL_MAX_EXP 1024 +#endif +#include "util.h" +#include "cuddInt.h" + +/*---------------------------------------------------------------------------*/ +/* 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, f, &currNodeQual) == 0) { + fprintf(dd->err, + "Something is wrong, ought to be node quality table\n"); + dd->errorCode = CUDD_INTERNAL_ERROR; + } + + size = 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, (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, (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++) { + FREE(mintermPages[i]); + } + FREE(mintermPages); + for (i = 0; i <= page; i++) { + FREE(nodePages[i]); + } + FREE(nodePages); + for (i = 0; i <= page; i++) { + FREE(lightNodePages[i]); + } + FREE(lightNodePages); + for (i = 0; i <= nodeDataPage; i++) { + FREE(nodeDataPages[i]); + } + FREE(nodeDataPages); + st_free_table(visitedTable); + 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 = ALLOC(NodeData_t *,maxNodeDataPages + INITIAL_PAGES); + if (newNodeDataPages == NULL) { + for (i = 0; i < nodeDataPage; i++) FREE(nodeDataPages[i]); + FREE(nodeDataPages); + memOut = 1; + return; + } else { + for (i = 0; i < maxNodeDataPages; i++) { + newNodeDataPages[i] = nodeDataPages[i]; + } + /* Increase total page count */ + maxNodeDataPages += INITIAL_PAGES; + FREE(nodeDataPages); + nodeDataPages = newNodeDataPages; + } + } + /* Allocate a new page */ + currentNodeDataPage = nodeDataPages[nodeDataPage] = + ALLOC(NodeData_t ,nodeDataPageSize); + if (currentNodeDataPage == NULL) { + for (i = 0; i < nodeDataPage; i++) FREE(nodeDataPages[i]); + 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 = ALLOC(double *,maxPages + INITIAL_PAGES); + if (newMintermPages == NULL) { + for (i = 0; i < page; i++) FREE(mintermPages[i]); + FREE(mintermPages); + memOut = 1; + return; + } else { + for (i = 0; i < maxPages; i++) { + newMintermPages[i] = mintermPages[i]; + } + /* Increase total page count */ + maxPages += INITIAL_PAGES; + FREE(mintermPages); + mintermPages = newMintermPages; + } + } + /* Allocate a new page */ + currentMintermPage = mintermPages[page] = ALLOC(double,pageSize); + if (currentMintermPage == NULL) { + for (i = 0; i < page; i++) FREE(mintermPages[i]); + 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 = ALLOC(int *,maxPages + INITIAL_PAGES); + if (newNodePages == NULL) { + for (i = 0; i < page; i++) FREE(nodePages[i]); + FREE(nodePages); + for (i = 0; i < page; i++) FREE(lightNodePages[i]); + FREE(lightNodePages); + memOut = 1; + return; + } else { + for (i = 0; i < maxPages; i++) { + newNodePages[i] = nodePages[i]; + } + FREE(nodePages); + nodePages = newNodePages; + } + + newNodePages = ALLOC(int *,maxPages + INITIAL_PAGES); + if (newNodePages == NULL) { + for (i = 0; i < page; i++) FREE(nodePages[i]); + FREE(nodePages); + for (i = 0; i < page; i++) FREE(lightNodePages[i]); + FREE(lightNodePages); + memOut = 1; + return; + } else { + for (i = 0; i < maxPages; i++) { + newNodePages[i] = lightNodePages[i]; + } + FREE(lightNodePages); + lightNodePages = newNodePages; + } + /* Increase total page count */ + maxPages += INITIAL_PAGES; + } + /* Allocate a new page */ + currentNodePage = nodePages[page] = ALLOC(int,pageSize); + if (currentNodePage == NULL) { + for (i = 0; i < page; i++) FREE(nodePages[i]); + FREE(nodePages); + for (i = 0; i < page; i++) FREE(lightNodePages[i]); + FREE(lightNodePages); + memOut = 1; + return; + } + /* Allocate a new page */ + currentLightNodePage = lightNodePages[page] = ALLOC(int,pageSize); + if (currentLightNodePage == NULL) { + for (i = 0; i <= page; i++) FREE(nodePages[i]); + FREE(nodePages); + for (i = 0; i < page; i++) FREE(lightNodePages[i]); + 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, node, &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++) FREE(nodeDataPages[i]); + 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++) FREE(mintermPages[i]); + 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++) FREE(mintermPages[i]); + FREE(mintermPages); + for (i = 0; i <= nodeDataPage; i++) FREE(nodeDataPages[i]); + 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 = ALLOC(double *,maxPages); + if (mintermPages == NULL) { + st_free_table(table); + goto OUT_OF_MEM; + } + page = 0; + currentMintermPage = ALLOC(double,pageSize); + mintermPages[page] = currentMintermPage; + if (currentMintermPage == NULL) { + FREE(mintermPages); + st_free_table(table); + goto OUT_OF_MEM; + } + pageIndex = 0; + maxNodeDataPages = INITIAL_PAGES; + nodeDataPages = ALLOC(NodeData_t *, maxNodeDataPages); + if (nodeDataPages == NULL) { + for (i = 0; i <= page ; i++) FREE(mintermPages[i]); + FREE(mintermPages); + st_free_table(table); + goto OUT_OF_MEM; + } + nodeDataPage = 0; + currentNodeDataPage = ALLOC(NodeData_t ,nodeDataPageSize); + nodeDataPages[nodeDataPage] = currentNodeDataPage; + if (currentNodeDataPage == NULL) { + for (i = 0; i <= page ; i++) FREE(mintermPages[i]); + FREE(mintermPages); + 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, node, &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, Nv, &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, Nnv, &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++) FREE(mintermPages[i]); + FREE(mintermPages); + for (i = 0; i <= nodeDataPage; i++) FREE(nodeDataPages[i]); + 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++) FREE(mintermPages[i]); + FREE(mintermPages); + for (i = 0; i <= nodeDataPage; i++) FREE(nodeDataPages[i]); + 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, Cudd_Not(node), &dummyNBar) == 1) { + if (pageIndex == pageSize) ResizeCountNodePages(); + if (memOut) { + for (i = 0; i < page; i++) FREE(mintermPages[i]); + FREE(mintermPages); + for (i = 0; i < nodeDataPage; i++) FREE(nodeDataPages[i]); + 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++) FREE(mintermPages[i]); + FREE(mintermPages); + for (i = 0; i < nodeDataPage; i++) FREE(nodeDataPages[i]); + 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 = ALLOC(int *,maxPages); + if (nodePages == NULL) { + goto OUT_OF_MEM; + } + + lightNodePages = ALLOC(int *,maxPages); + if (lightNodePages == NULL) { + for (i = 0; i <= page; i++) FREE(mintermPages[i]); + FREE(mintermPages); + for (i = 0; i <= nodeDataPage; i++) FREE(nodeDataPages[i]); + FREE(nodeDataPages); + FREE(nodePages); + goto OUT_OF_MEM; + } + + page = 0; + currentNodePage = nodePages[page] = ALLOC(int,pageSize); + if (currentNodePage == NULL) { + for (i = 0; i <= page; i++) FREE(mintermPages[i]); + FREE(mintermPages); + for (i = 0; i <= nodeDataPage; i++) FREE(nodeDataPages[i]); + FREE(nodeDataPages); + FREE(lightNodePages); + FREE(nodePages); + goto OUT_OF_MEM; + } + + currentLightNodePage = lightNodePages[page] = ALLOC(int,pageSize); + if (currentLightNodePage == NULL) { + for (i = 0; i <= page; i++) FREE(mintermPages[i]); + FREE(mintermPages); + for (i = 0; i <= nodeDataPage; i++) FREE(nodeDataPages[i]); + FREE(nodeDataPages); + FREE(currentNodePage); + FREE(lightNodePages); + 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, node, &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, Nv, &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, Nnv, &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 */ diff --git a/distr/cudd/cuddSubsetSP.c b/distr/cudd/cuddSubsetSP.c new file mode 100644 index 0000000..23d3a0d --- /dev/null +++ b/distr/cudd/cuddSubsetSP.c @@ -0,0 +1,1657 @@ +/**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: +
          +
        • Cudd_SubsetShortPaths() +
        • Cudd_SupersetShortPaths() +
        + Internal procedures included in this module: +
          +
        • cuddSubsetShortPaths() +
        + Static procedures included in this module: +
          +
        • BuildSubsetBdd() +
        • CreatePathTable() +
        • AssessPathLength() +
        • CreateTopDist() +
        • CreateBotDist() +
        • ResizeNodeDistPages() +
        • ResizeQueuePages() +
        • stPathTableDdFree() +
        + ] + + 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 "util.h" +#include "cuddInt.h" + +/*---------------------------------------------------------------------------*/ +/* 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 = 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); + FREE(pathLengthArray); + return (NIL(DdNode)); + } + + excess = ALLOC(unsigned int, 1); + *excess = 0; + maxpath = AssessPathLength(pathLengthArray, threshold, numVars, excess, + dd->err); + + if (maxpath != (unsigned) (numVars + 1)) { + + info = 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, N, &nodeStat)) { + fprintf(dd->err, "Something wrong, root node must be in table\n"); + dd->errorCode = CUDD_INTERNAL_ERROR; + FREE(excess); + 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); + + FREE(info); + + } else {/* if threshold larger than size of dd */ + subset = f; + cuddRef(subset); + } + FREE(excess); + st_free_table(pathTable); + FREE(pathLengthArray); + for (i = 0; i <= nodeDistPage; i++) FREE(nodeDistPages[i]); + 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 = ALLOC(NodeDist_t *,maxNodeDistPages + INITIAL_PAGES); + if (newNodeDistPages == NULL) { + for (i = 0; i < nodeDistPage; i++) FREE(nodeDistPages[i]); + FREE(nodeDistPages); + memOut = 1; + return; + } else { + for (i = 0; i < maxNodeDistPages; i++) { + newNodeDistPages[i] = nodeDistPages[i]; + } + /* Increase total page count */ + maxNodeDistPages += INITIAL_PAGES; + FREE(nodeDistPages); + nodeDistPages = newNodeDistPages; + } + } + /* Allocate a new page */ + currentNodeDistPage = nodeDistPages[nodeDistPage] = ALLOC(NodeDist_t, + nodeDistPageSize); + if (currentNodeDistPage == NULL) { + for (i = 0; i < nodeDistPage; i++) FREE(nodeDistPages[i]); + 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 = ALLOC(DdNode **,maxQueuePages + INITIAL_PAGES); + if (newQueuePages == NULL) { + for (i = 0; i < queuePage; i++) FREE(queuePages[i]); + FREE(queuePages); + memOut = 1; + return; + } else { + for (i = 0; i < maxQueuePages; i++) { + newQueuePages[i] = queuePages[i]; + } + /* Increase total page count */ + maxQueuePages += INITIAL_PAGES; + FREE(queuePages); + queuePages = newQueuePages; + } + } + /* Allocate a new page */ + currentQueuePage = queuePages[queuePage] = ALLOC(DdNode *,queuePageSize); + if (currentQueuePage == NULL) { + for (i = 0; i < queuePage; i++) FREE(queuePages[i]); + 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, regChild, &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++) FREE(queuePages[i]); + 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++) + FREE(nodeDistPages[i]); + FREE(nodeDistPages); + for (i = 0; i <= queuePage; i++) FREE(queuePages[i]); + 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++) + FREE(nodeDistPages[i]); + 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++) + FREE(nodeDistPages[i]); + 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, N, &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, regChild, &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 = ALLOC(NodeDist_t *, maxNodeDistPages); + if (nodeDistPages == NULL) { + goto OUT_OF_MEM; + } + nodeDistPage = 0; + currentNodeDistPage = nodeDistPages[nodeDistPage] = + ALLOC(NodeDist_t, nodeDistPageSize); + if (currentNodeDistPage == NULL) { + for (i = 0; i <= nodeDistPage; i++) FREE(nodeDistPages[i]); + FREE(nodeDistPages); + goto OUT_OF_MEM; + } + nodeDistPageIndex = 0; + + /* Initializing pages for the BFS search queue, implemented as an array. */ + maxQueuePages = INITIAL_PAGES; + queuePages = ALLOC(DdNode **, maxQueuePages); + if (queuePages == NULL) { + goto OUT_OF_MEM; + } + queuePage = 0; + currentQueuePage = queuePages[queuePage] = ALLOC(DdNode *, queuePageSize); + if (currentQueuePage == NULL) { + for (i = 0; i <= queuePage; i++) FREE(queuePages[i]); + 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++) FREE(nodeDistPages[i]); + FREE(nodeDistPages); + for (i = 0; i <= queuePage; i++) FREE(queuePages[i]); + 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++) FREE(nodeDistPages[i]); + FREE(nodeDistPages); + for (i = 0; i <= queuePage; i++) FREE(queuePages[i]); + 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++) FREE(queuePages[i]); + 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, *regNv; + NodeDist_t *nodeStatNv, *nodeStat, *nodeStatNnv; + DdNode *neW, *topv, *regNew; + char *entry; + unsigned int topid; + unsigned int childPathLength, oddLen, evenLen, NnvPathLength, NvPathLength; + 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, N, &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, regNv, &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, regNnv, &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 */ diff --git a/distr/cudd/cuddSymmetry.c b/distr/cudd/cuddSymmetry.c new file mode 100644 index 0000000..cd7bcc8 --- /dev/null +++ b/distr/cudd/cuddSymmetry.c @@ -0,0 +1,1695 @@ +/**CFile*********************************************************************** + + FileName [cuddSymmetry.c] + + PackageName [cudd] + + Synopsis [Functions for symmetry-based variable reordering.] + + Description [External procedures included in this file: +
          +
        • Cudd_SymmProfile() +
        + Internal procedures included in this module: +
          +
        • cuddSymmCheck() +
        • cuddSymmSifting() +
        • cuddSymmSiftingConv() +
        + Static procedures included in this module: +
          +
        • ddSymmUniqueCompare() +
        • ddSymmSiftingAux() +
        • ddSymmSiftingConvAux() +
        • ddSymmSiftingUp() +
        • ddSymmSiftingDown() +
        • ddSymmGroupMove() +
        • ddSymmGroupMoveBackward() +
        • ddSymmSiftingBackward() +
        • ddSymmSummary() +
        ] + + 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 "util.h" +#include "cuddInt.h" + +/*---------------------------------------------------------------------------*/ +/* 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. +
          +
        1. Order all the variables according to the number of entries in + each unique subtable. +
        2. Sift the variable up and down, remembering each time the total + size of the DD heap and grouping variables that are symmetric. +
        3. Select the best permutation. +
        4. Repeat 3 and 4 for all variables. +
        + 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 = ALLOC(int,size); + if (entry == NULL) { + table->errorCode = CUDD_MEMORY_OUT; + goto ddSymmSiftingOutOfMem; + } + var = 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; + 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 + } + } + + FREE(var); + 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) FREE(entry); + if (var != NULL) 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. +
          +
        1. Order all the variables according to the number of entries in + each unique subtable. +
        2. Sift the variable up and down, remembering each time the total + size of the DD heap and grouping variables that are symmetric. +
        3. Select the best permutation. +
        4. Repeat 3 and 4 for all variables. +
        5. Repeat 1-4 until no further improvement. +
        + 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 = ALLOC(int,size); + if (entry == NULL) { + table->errorCode = CUDD_MEMORY_OUT; + goto ddSymmSiftingConvOutOfMem; + } + var = 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 + + FREE(var); + FREE(entry); + + return(1+symvars); + +ddSymmSiftingConvOutOfMem: + + if (entry != NULL) FREE(entry); + if (var != NULL) 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; + int i,j; + int xtop,xbot,xsize,ytop,ybot,ysize,newxtop; + int swapx,swapy; + +#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; + 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; + + 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 */ diff --git a/distr/cudd/cuddTable.c b/distr/cudd/cuddTable.c new file mode 100644 index 0000000..b6b5436 --- /dev/null +++ b/distr/cudd/cuddTable.c @@ -0,0 +1,3160 @@ +/**CFile*********************************************************************** + + FileName [cuddTable.c] + + PackageName [cudd] + + Synopsis [Unique table management functions.] + + Description [External procedures included in this module: +
          +
        • Cudd_Prime() +
        + Internal procedures included in this module: +
          +
        • cuddAllocNode() +
        • cuddInitTable() +
        • cuddFreeTable() +
        • cuddGarbageCollect() +
        • cuddZddGetNode() +
        • cuddZddGetNodeIVO() +
        • cuddUniqueInter() +
        • cuddUniqueInterIVO() +
        • cuddUniqueInterZdd() +
        • cuddUniqueConst() +
        • cuddRehash() +
        • cuddShrinkSubtable() +
        • cuddInsertSubtables() +
        • cuddDestroySubtables() +
        • cuddResizeTableZdd() +
        • cuddSlowTableGrowth() +
        + Static procedures included in this module: +
          +
        • ddRehashZdd() +
        • ddResizeTable() +
        • cuddFindParent() +
        • cuddOrderedInsert() +
        • cuddOrderedThread() +
        • cuddRotateLeft() +
        • cuddRotateRight() +
        • cuddDoRebalance() +
        • cuddCheckCollisionOrdering() +
        ] + + 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 */ +/*---------------------------------------------------------------------------*/ + +#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 >= 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 *) ALLOC(DdNode,DD_MEM_CHUNK + 1); + 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) { + FREE(unique->stash); + unique->stash = NULL; + /* Inhibit resizing of tables. */ + cuddSlowTableGrowth(unique); + /* Now try again. */ + mem = (DdNodePtr *) ALLOC(DdNode,DD_MEM_CHUNK + 1); + } + 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; + + 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; + 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 = 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 = ALLOC(DdSubtable,unique->maxSize); + if (unique->subtables == NULL) { + FREE(unique); + return(NULL); + } + unique->subtableZ = ALLOC(DdSubtable,unique->maxSizeZ); + if (unique->subtableZ == NULL) { + FREE(unique->subtables); + FREE(unique); + return(NULL); + } + unique->perm = ALLOC(int,unique->maxSize); + if (unique->perm == NULL) { + FREE(unique->subtables); + FREE(unique->subtableZ); + FREE(unique); + return(NULL); + } + unique->invperm = ALLOC(int,unique->maxSize); + if (unique->invperm == NULL) { + FREE(unique->subtables); + FREE(unique->subtableZ); + FREE(unique->perm); + FREE(unique); + return(NULL); + } + unique->permZ = ALLOC(int,unique->maxSizeZ); + if (unique->permZ == NULL) { + FREE(unique->subtables); + FREE(unique->subtableZ); + FREE(unique->perm); + FREE(unique->invperm); + FREE(unique); + return(NULL); + } + unique->invpermZ = ALLOC(int,unique->maxSizeZ); + if (unique->invpermZ == NULL) { + FREE(unique->subtables); + FREE(unique->subtableZ); + FREE(unique->perm); + FREE(unique->invperm); + FREE(unique->permZ); + FREE(unique); + return(NULL); + } + unique->map = NULL; + unique->stack = ALLOC(DdNodePtr,ddMax(unique->maxSize,unique->maxSizeZ)+1); + if (unique->stack == NULL) { + FREE(unique->subtables); + FREE(unique->subtableZ); + FREE(unique->perm); + FREE(unique->invperm); + FREE(unique->permZ); + FREE(unique->invpermZ); + 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 = ALLOC(DdNodePtr,unique->deathRowDepth); + if (unique->deathRow == NULL) { + FREE(unique->subtables); + FREE(unique->subtableZ); + FREE(unique->perm); + FREE(unique->invperm); + FREE(unique->permZ); + FREE(unique->invpermZ); + FREE(unique->stack); + 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 = ALLOC(DdNodePtr,slots); + if (nodelist == NULL) { + for (j = 0; j < i; j++) { + FREE(unique->subtables[j].nodelist); + } + FREE(unique->subtables); + FREE(unique->subtableZ); + FREE(unique->perm); + FREE(unique->invperm); + FREE(unique->permZ); + FREE(unique->invpermZ); + FREE(unique->stack); + 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 = ALLOC(DdNodePtr,slots); + if (nodelist == NULL) { + for (j = 0; (unsigned) j < numVars; j++) { + FREE(unique->subtables[j].nodelist); + } + FREE(unique->subtables); + for (j = 0; j < i; j++) { + FREE(unique->subtableZ[j].nodelist); + } + FREE(unique->subtableZ); + FREE(unique->perm); + FREE(unique->invperm); + FREE(unique->permZ); + FREE(unique->invpermZ); + FREE(unique->stack); + 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 = ALLOC(DdNodePtr,slots); + if (nodelist == NULL) { + for (j = 0; (unsigned) j < numVars; j++) { + FREE(unique->subtables[j].nodelist); + } + FREE(unique->subtables); + for (j = 0; (unsigned) j < numVarsZ; j++) { + FREE(unique->subtableZ[j].nodelist); + } + FREE(unique->subtableZ); + FREE(unique->perm); + FREE(unique->invperm); + FREE(unique->permZ); + FREE(unique->invpermZ); + FREE(unique->stack); + 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 */ + FREE(memlist); + memlist = next; + } + unique->nextFree = NULL; + unique->memoryList = NULL; + + for (i = 0; i < unique->size; i++) { + FREE(unique->subtables[i].nodelist); + } + for (i = 0; i < unique->sizeZ; i++) { + FREE(unique->subtableZ[i].nodelist); + } + FREE(unique->constants.nodelist); + FREE(unique->subtables); + FREE(unique->subtableZ); + FREE(unique->acache); + FREE(unique->perm); + FREE(unique->permZ); + FREE(unique->invperm); + FREE(unique->invpermZ); + FREE(unique->vars); + if (unique->map != NULL) FREE(unique->map); + FREE(unique->stack); +#ifndef DD_NO_DEATH_ROW + FREE(unique->deathRow); +#endif + if (unique->tree != NULL) Mtr_FreeTree(unique->tree); + if (unique->treeZ != NULL) Mtr_FreeTree(unique->treeZ); + if (unique->linear != NULL) 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); + 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); + 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(T, 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(T, 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(T, 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 + + 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(T, 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 = 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) { + 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(cuddT(node), cuddE(node), shift); + if (pos & 1) { + *oddP = node; + oddP = &(node->next); + } else { + *evenP = node; + evenP = &(node->next); + } + node = next; + } + *evenP = *oddP = sentinel; + } + 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 = 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; + } + } + 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 = 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(cuddT(node), 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; + } + } + 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; + 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 = + 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 = ALLOC(DdSubtable,newsize); + if (newsubtables == NULL) { + unique->errorCode = CUDD_MEMORY_OUT; + return(0); + } + newvars = ALLOC(DdNodePtr,newsize); + if (newvars == NULL) { + unique->errorCode = CUDD_MEMORY_OUT; + FREE(newsubtables); + return(0); + } + newperm = ALLOC(int,newsize); + if (newperm == NULL) { + unique->errorCode = CUDD_MEMORY_OUT; + FREE(newsubtables); + FREE(newvars); + return(0); + } + newinvperm = ALLOC(int,newsize); + if (newinvperm == NULL) { + unique->errorCode = CUDD_MEMORY_OUT; + FREE(newsubtables); + FREE(newvars); + FREE(newperm); + return(0); + } + if (unique->map != NULL) { + newmap = ALLOC(int,newsize); + if (newmap == NULL) { + unique->errorCode = CUDD_MEMORY_OUT; + FREE(newsubtables); + FREE(newvars); + FREE(newperm); + 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 = 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; + } + FREE(unique->map); + unique->map = newmap; + } + /* Install the new tables and free the old ones. */ + FREE(unique->subtables); + unique->subtables = newsubtables; + unique->maxSize = newsize; + FREE(unique->vars); + unique->vars = newvars; + FREE(unique->perm); + unique->perm = newperm; + FREE(unique->invperm); + unique->invperm = newinvperm; + /* Update the stack for iterative procedures. */ + if (newsize > unique->maxSizeZ) { + FREE(unique->stack); + unique->stack = 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; + 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 + 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); + 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 = + 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 = ALLOC(DdSubtable,newsize); + if (newsubtables == NULL) { + unique->errorCode = CUDD_MEMORY_OUT; + return(0); + } + newperm = ALLOC(int,newsize); + if (newperm == NULL) { + unique->errorCode = CUDD_MEMORY_OUT; + return(0); + } + newinvperm = 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) { + FREE(unique->stack); + unique->stack = 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 = ALLOC(DdNodePtr, numSlots); + if (newnodelist == NULL) { + unique->errorCode = CUDD_MEMORY_OUT; + return(0); + } + for (j = 0; (unsigned) j < numSlots; j++) { + newnodelist[j] = NULL; + } + } + FREE(unique->subtableZ); + unique->subtableZ = newsubtables; + unique->maxSizeZ = newsize; + FREE(unique->permZ); + unique->permZ = newperm; + 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 = 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(cuddT(node), cuddE(node), shift); + node->next = nodelist[pos]; + nodelist[pos] = node; + node = next; + } + } + 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; + 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 = + ALLOC(DdNodePtr, numSlots); + if (newnodelist == NULL) { + for (j = oldsize; j < i; j++) { + 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 = ALLOC(DdSubtable,newsize); + if (newsubtables == NULL) { + unique->errorCode = CUDD_MEMORY_OUT; + return(0); + } + newvars = ALLOC(DdNodePtr,newsize); + if (newvars == NULL) { + FREE(newsubtables); + unique->errorCode = CUDD_MEMORY_OUT; + return(0); + } + newperm = ALLOC(int,newsize); + if (newperm == NULL) { + FREE(newsubtables); + FREE(newvars); + unique->errorCode = CUDD_MEMORY_OUT; + return(0); + } + newinvperm = ALLOC(int,newsize); + if (newinvperm == NULL) { + FREE(newsubtables); + FREE(newvars); + FREE(newperm); + unique->errorCode = CUDD_MEMORY_OUT; + return(0); + } + if (unique->map != NULL) { + newmap = ALLOC(int,newsize); + if (newmap == NULL) { + FREE(newsubtables); + FREE(newvars); + FREE(newperm); + 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) { + FREE(unique->stack); + unique->stack = ALLOC(DdNodePtr,newsize + 1); + if (unique->stack == NULL) { + FREE(newsubtables); + FREE(newvars); + FREE(newperm); + FREE(newinvperm); + if (unique->map != NULL) { + 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 = 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; + } + FREE(unique->map); + unique->map = newmap; + } + FREE(unique->subtables); + unique->subtables = newsubtables; + unique->maxSize = newsize; + FREE(unique->vars); + unique->vars = newvars; + FREE(unique->perm); + unique->perm = newperm; + 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++) { + 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 */ diff --git a/distr/cudd/cuddUtil.c b/distr/cudd/cuddUtil.c new file mode 100644 index 0000000..f662f48 --- /dev/null +++ b/distr/cudd/cuddUtil.c @@ -0,0 +1,3929 @@ +/**CFile*********************************************************************** + + FileName [cuddUtil.c] + + PackageName [cudd] + + Synopsis [Utility functions.] + + Description [External procedures included in this module: +
          +
        • Cudd_PrintMinterm() +
        • Cudd_bddPrintCover() +
        • Cudd_PrintDebug() +
        • Cudd_DagSize() +
        • Cudd_EstimateCofactor() +
        • Cudd_EstimateCofactorSimple() +
        • Cudd_SharingSize() +
        • Cudd_CountMinterm() +
        • Cudd_EpdCountMinterm() +
        • Cudd_CountPath() +
        • Cudd_CountPathsToNonZero() +
        • Cudd_Support() +
        • Cudd_SupportIndex() +
        • Cudd_SupportSize() +
        • Cudd_VectorSupport() +
        • Cudd_VectorSupportIndex() +
        • Cudd_VectorSupportSize() +
        • Cudd_ClassifySupport() +
        • Cudd_CountLeaves() +
        • Cudd_bddPickOneCube() +
        • Cudd_bddPickOneMinterm() +
        • Cudd_bddPickArbitraryMinterms() +
        • Cudd_SubsetWithMaskVars() +
        • Cudd_FirstCube() +
        • Cudd_NextCube() +
        • Cudd_bddComputeCube() +
        • Cudd_addComputeCube() +
        • Cudd_FirstNode() +
        • Cudd_NextNode() +
        • Cudd_GenFree() +
        • Cudd_IsGenEmpty() +
        • Cudd_IndicesToCube() +
        • Cudd_PrintVersion() +
        • Cudd_AverageDistance() +
        • Cudd_Random() +
        • Cudd_Srandom() +
        • Cudd_Density() +
        + Internal procedures included in this module: +
          +
        • cuddP() +
        • cuddStCountfree() +
        • cuddCollectNodes() +
        • cuddNodeArray() +
        + Static procedures included in this module: +
          +
        • dp2() +
        • ddPrintMintermAux() +
        • ddDagInt() +
        • ddCountMintermAux() +
        • ddEpdCountMintermAux() +
        • ddCountPathAux() +
        • ddSupportStep() +
        • ddClearFlag() +
        • ddLeavesInt() +
        • ddPickArbitraryMinterms() +
        • ddPickRepresentativeCube() +
        • ddEpdFree() +
        ] + + 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 */ +/*---------------------------------------------------------------------------*/ + +/* 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 = 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); + 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 = 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); + FREE(array); + return(0); + } + cuddRef(implicant); + prime = Cudd_bddMakePrime(dd,implicant,u); + if (prime == NULL) { + Cudd_RecursiveDeref(dd,lb); + Cudd_RecursiveDeref(dd,implicant); + 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); + 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); + 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); + 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); + 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 > 0. Specifically: +
          +
        • pr = 0 : prints nothing +
        • pr = 1 : prints counts of nodes and minterms +
        • pr = 2 : prints counts + disjoint sum of product +
        • pr = 3 : prints counts + list of nodes +
        • pr > 3 : prints counts + disjoint sum of product + list of nodes +
        + 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 = 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); + + 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 = 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 = 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++; + } + + 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 = 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); + FREE(support); + return(NULL); + } + cuddRef(tmp); + Cudd_RecursiveDeref(dd,res); + Cudd_RecursiveDeref(dd,var); + res = tmp; + } + } + + 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 = 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 = 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++; + } + + 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 + f and g, depending on whther they appear + in both DDs, only in f, or only in g. + 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 = ALLOC(int,size); + if (supportF == NULL) { + dd->errorCode = CUDD_MEMORY_OUT; + return(0); + } + supportG = ALLOC(int,size); + if (supportG == NULL) { + dd->errorCode = CUDD_MEMORY_OUT; + 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); + FREE(supportF); 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); + FREE(supportF); 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); + FREE(supportF); FREE(supportG); + return(0); + } + cuddRef(tmp); + Cudd_RecursiveDeref(dd,*common); + *common = tmp; + } + Cudd_RecursiveDeref(dd,var); + } + + FREE(supportF); 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 vars. The array + vars should contain at least all variables in the + support of f; if this condition is not met the minterm + built by this procedure may not be contained in + f. 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: +
          +
        • It may run out of memory; +
        • the function f may be the constant 0; +
        • the minterm may not be contained in f. +
        ] + + 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 vars */) +{ + char *string; + int i, size; + int *indices; + int result; + DdNode *old, *neW; + + size = dd->size; + string = ALLOC(char, size); + if (string == NULL) { + dd->errorCode = CUDD_MEMORY_OUT; + return(NULL); + } + indices = ALLOC(int,n); + if (indices == NULL) { + dd->errorCode = CUDD_MEMORY_OUT; + FREE(string); + return(NULL); + } + + for (i = 0; i < n; i++) { + indices[i] = vars[i]->index; + } + + result = Cudd_bddPickOneCube(dd,f,string); + if (result == 0) { + FREE(string); + 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) { + FREE(string); + 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 + + FREE(string); + 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 vars. The array + vars should contain at least all variables in the + support of f; if this condition is not met the minterms + built by this procedure may not be contained in + f. 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: +
          +
        • It may run out of memory; +
        • the function f may be the constant 0; +
        • the minterms may not be contained in f. +
        ] + + 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 vars */, + 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, isSame; + + minterms = Cudd_CountMinterm(dd,f,n); + if ((double)k > minterms) { + return(NULL); + } + + size = dd->size; + string = ALLOC(char *, k); + if (string == NULL) { + dd->errorCode = CUDD_MEMORY_OUT; + return(NULL); + } + for (i = 0; i < k; i++) { + string[i] = ALLOC(char, size + 1); + if (string[i] == NULL) { + for (j = 0; j < i; j++) + FREE(string[i]); + FREE(string); + dd->errorCode = CUDD_MEMORY_OUT; + return(NULL); + } + for (j = 0; j < size; j++) string[i][j] = '2'; + string[i][size] = '\0'; + } + indices = ALLOC(int,n); + if (indices == NULL) { + dd->errorCode = CUDD_MEMORY_OUT; + for (i = 0; i < k; i++) + FREE(string[i]); + 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++) + FREE(string[i]); + FREE(string); + FREE(indices); + return(NULL); + } + + old = ALLOC(DdNode *, k); + if (old == NULL) { + dd->errorCode = CUDD_MEMORY_OUT; + for (i = 0; i < k; i++) + FREE(string[i]); + FREE(string); + FREE(indices); + return(NULL); + } + saveString = ALLOC(char, size + 1); + if (saveString == NULL) { + dd->errorCode = CUDD_MEMORY_OUT; + for (i = 0; i < k; i++) + FREE(string[i]); + FREE(string); + FREE(indices); + 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) { + FREE(saveString); + for (l = 0; l < k; l++) + FREE(string[l]); + FREE(string); + FREE(indices); + for (l = 0; l <= i; l++) + Cudd_RecursiveDeref(dd,old[l]); + FREE(old); + return(NULL); + } + cuddRef(neW); + Cudd_RecursiveDeref(dd,old[i]); + old[i] = neW; + } + + /* Test. */ + if (!Cudd_bddLeq(dd,old[i],f)) { + FREE(saveString); + for (l = 0; l < k; l++) + FREE(string[l]); + FREE(string); + FREE(indices); + for (l = 0; l <= i; l++) + Cudd_RecursiveDeref(dd,old[l]); + FREE(old); + return(NULL); + } + } + + FREE(saveString); + for (i = 0; i < k; i++) { + cuddDeref(old[i]); + FREE(string[i]); + } + FREE(string); + 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 vars */, + DdNode ** maskVars /* array of variables */, + int mvars /* size of maskVars */) +{ + 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 = 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 = ALLOC(char, size + 1); + if (string == NULL) { + dd->errorCode = CUDD_MEMORY_OUT; + FREE(weight); + return(NULL); + } + mask = ALLOC(int, size); + if (mask == NULL) { + dd->errorCode = CUDD_MEMORY_OUT; + FREE(weight); + FREE(string); + return(NULL); + } + for (i = 0; i < size; i++) { + string[i] = '2'; + mask[i] = 0; + } + string[size] = '\0'; + indices = ALLOC(int,nvars); + if (indices == NULL) { + dd->errorCode = CUDD_MEMORY_OUT; + FREE(weight); + FREE(string); + FREE(mask); + return(NULL); + } + for (i = 0; i < nvars; i++) { + indices[i] = vars[i]->index; + } + + result = ddPickRepresentativeCube(dd,f,weight,string); + if (result == 0) { + FREE(weight); + FREE(string); + FREE(mask); + 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) { + FREE(weight); + FREE(string); + FREE(mask); + 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) { + FREE(weight); + FREE(string); + FREE(mask); + 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; + } + + FREE(weight); + FREE(string); + FREE(mask); + 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.

        + 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.

        + 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 = 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 = ALLOC(int,nvars); + if (gen->gen.cubes.cube == NULL) { + dd->errorCode = CUDD_MEMORY_OUT; + 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 = ALLOC(DdNodePtr, nvars+1); + if (gen->stack.stack == NULL) { + dd->errorCode = CUDD_MEMORY_OUT; + FREE(gen->gen.cubes.cube); + 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.

        + + 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.

        + + 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.

        + + 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 = 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 = ALLOC(int,dd->size); + if (gen->gen.primes.cube == NULL) { + dd->errorCode = CUDD_MEMORY_OUT; + 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); + FREE(gen->gen.primes.cube); + 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); + FREE(gen->gen.primes.cube); + 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); + FREE(gen->gen.primes.cube); + 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); + FREE(gen->gen.primes.cube); + 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 = 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) { + 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: + FREE(gen->gen.cubes.cube); + FREE(gen->stack.stack); + break; + case CUDD_GEN_PRIMES: + FREE(gen->gen.primes.cube); + Cudd_RecursiveDeref(gen->manager,gen->node); + break; + case CUDD_GEN_NODES: + FREE(gen->stack.stack); + break; + default: + return(0); + } + 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; + 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 = 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(T, 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: +

        + |f| = (|f0|+|f1|)/2 + + 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: + + |f| = |f0|+|f1| + + 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, node, &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 = 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) { + 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: + + |f| = (|f0|+|f1|)/2 + + 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, node, &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: + + |f| = |f0|+|f1| + + 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, N, &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 = 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) { + 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 */ diff --git a/distr/cudd/cuddWindow.c b/distr/cudd/cuddWindow.c new file mode 100644 index 0000000..f2abf1f --- /dev/null +++ b/distr/cudd/cuddWindow.c @@ -0,0 +1,1023 @@ +/**CFile*********************************************************************** + + FileName [cuddWindow.c] + + PackageName [cudd] + + Synopsis [Functions for variable reordering by window permutation.] + + Description [Internal procedures included in this module: +
          +
        • cuddWindowReorder() +
        + Static procedures included in this module: +
          +
        • ddWindow2() +
        • ddWindowConv2() +
        • ddPermuteWindow3() +
        • ddWindow3() +
        • ddWindowConv3() +
        • ddPermuteWindow4() +
        • ddWindow4() +
        • ddWindowConv4() +
        ] + + 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 */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* 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 = ALLOC(int,nwin); + if (events == NULL) { + table->errorCode = CUDD_MEMORY_OUT; + return(0); + } + for (x=0; xkeys - table->isolated; + do { + newevent = 0; + for (x=0; x= size) { /* no improvement: undo permutation */ + res = cuddSwapInPlace(table,x+low,x+low+1); + if (res == 0) { + 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); + + 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 = ALLOC(int,nwin); + if (events == NULL) { + table->errorCode = CUDD_MEMORY_OUT; + return(0); + } + for (x=0; 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: + 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); + + 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 = ALLOC(int,nwin); + if (events == NULL) { + table->errorCode = CUDD_MEMORY_OUT; + return(0); + } + for (x=0; 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: + 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); + + FREE(events); + + return(1); + +} /* end of ddWindowConv4 */ diff --git a/distr/cudd/cuddZddCount.c b/distr/cudd/cuddZddCount.c new file mode 100644 index 0000000..1351468 --- /dev/null +++ b/distr/cudd/cuddZddCount.c @@ -0,0 +1,357 @@ +/**CFile*********************************************************************** + + FileName [cuddZddCount.c] + + PackageName [cudd] + + Synopsis [Procedures to count the number of minterms of a ZDD.] + + Description [External procedures included in this module: +
          +
        • Cudd_zddCount(); +
        • Cudd_zddCountDouble(); +
        + Internal procedures included in this module: +
          +
        + Static procedures included in this module: +
          +
        • cuddZddCountStep(); +
        • cuddZddCountDoubleStep(); +
        • st_zdd_count_dbl_free() +
        • st_zdd_countfree() +
        + ] + + 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 "util.h" +#include "cuddInt.h" + +/*---------------------------------------------------------------------------*/ +/* Constant declarations */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Stucture declarations */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Type declarations */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Variable declarations */ +/*---------------------------------------------------------------------------*/ + +#ifndef lint +static char rcsid[] DD_UNUSED = "$Id: cuddZddCount.c,v 1.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, P, &dummy)) { + res = *dummy; + return(res); + } + + res = cuddZddCountStep(cuddE(P), table, base, empty) + + cuddZddCountStep(cuddT(P), table, base, empty); + + dummy = ALLOC(int, 1); + if (dummy == NULL) { + return(CUDD_OUT_OF_MEM); + } + *dummy = res; + if (st_insert(table, (char *)P, (char *)dummy) == ST_OUT_OF_MEM) { + FREE(dummy); + return(CUDD_OUT_OF_MEM); + } + + return(res); + +} /* end of cuddZddCountStep */ + + +/**Function******************************************************************** + + Synopsis [Performs the recursive step of Cudd_zddCountDouble.] + + Description [] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +static double +cuddZddCountDoubleStep( + DdNode * P, + st_table * table, + DdNode * base, + DdNode * empty) +{ + double res; + double *dummy; + + if (P == empty) + return((double)0.0); + if (P == base) + return((double)1.0); + + /* Check cache */ + if (st_lookup(table, P, &dummy)) { + res = *dummy; + return(res); + } + + res = cuddZddCountDoubleStep(cuddE(P), table, base, empty) + + cuddZddCountDoubleStep(cuddT(P), table, base, empty); + + dummy = ALLOC(double, 1); + if (dummy == NULL) { + return((double)CUDD_OUT_OF_MEM); + } + *dummy = res; + if (st_insert(table, (char *)P, (char *)dummy) == ST_OUT_OF_MEM) { + FREE(dummy); + return((double)CUDD_OUT_OF_MEM); + } + + return(res); + +} /* end of cuddZddCountDoubleStep */ + + +/**Function******************************************************************** + + Synopsis [Frees the memory associated with the computed table of + Cudd_zddCount.] + + Description [] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +static enum st_retval +st_zdd_countfree( + char * key, + char * value, + char * arg) +{ + int *d; + + d = (int *)value; + FREE(d); + return(ST_CONTINUE); + +} /* end of st_zdd_countfree */ + + +/**Function******************************************************************** + + Synopsis [Frees the memory associated with the computed table of + Cudd_zddCountDouble.] + + Description [] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +static enum st_retval +st_zdd_count_dbl_free( + char * key, + char * value, + char * arg) +{ + double *d; + + d = (double *)value; + FREE(d); + return(ST_CONTINUE); + +} /* end of st_zdd_count_dbl_free */ diff --git a/distr/cudd/cuddZddFuncs.c b/distr/cudd/cuddZddFuncs.c new file mode 100644 index 0000000..2681992 --- /dev/null +++ b/distr/cudd/cuddZddFuncs.c @@ -0,0 +1,1630 @@ +/**CFile*********************************************************************** + + FileName [cuddZddFuncs.c] + + PackageName [cudd] + + Synopsis [Functions to manipulate covers represented as ZDDs.] + + Description [External procedures included in this module: +
          +
        • Cudd_zddProduct(); +
        • Cudd_zddUnateProduct(); +
        • Cudd_zddWeakDiv(); +
        • Cudd_zddWeakDivF(); +
        • Cudd_zddDivide(); +
        • Cudd_zddDivideF(); +
        • Cudd_zddComplement(); +
        + Internal procedures included in this module: +
          +
        • cuddZddProduct(); +
        • cuddZddUnateProduct(); +
        • cuddZddWeakDiv(); +
        • cuddZddWeakDivF(); +
        • cuddZddDivide(); +
        • cuddZddDivideF(); +
        • cuddZddGetCofactors3() +
        • cuddZddGetCofactors2() +
        • cuddZddComplement(); +
        • cuddZddGetPosVarIndex(); +
        • cuddZddGetNegVarIndex(); +
        • cuddZddGetPosVarLevel(); +
        • cuddZddGetNegVarLevel(); +
        + Static procedures included in this module: +
          +
        + ] + + 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 "util.h" +#include "cuddInt.h" + +/*---------------------------------------------------------------------------*/ +/* 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 */ diff --git a/distr/cudd/cuddZddGroup.c b/distr/cudd/cuddZddGroup.c new file mode 100644 index 0000000..f59d826 --- /dev/null +++ b/distr/cudd/cuddZddGroup.c @@ -0,0 +1,1336 @@ +/**CFile*********************************************************************** + + FileName [cuddZddGroup.c] + + PackageName [cudd] + + Synopsis [Functions for ZDD group sifting.] + + Description [External procedures included in this file: +
          +
        • Cudd_MakeZddTreeNode() +
        + Internal procedures included in this file: +
          +
        • cuddZddTreeSifting() +
        + Static procedures included in this module: +
          +
        • zddTreeSiftingAux() +
        • zddCountInternalMtrNodes() +
        • zddReorderChildren() +
        • zddFindNodeHiLo() +
        • zddUniqueCompareGroup() +
        • zddGroupSifting() +
        • zddGroupSiftingAux() +
        • zddGroupSiftingUp() +
        • zddGroupSiftingDown() +
        • zddGroupMove() +
        • zddGroupMoveBackward() +
        • zddGroupSiftingBackward() +
        • zddMergeGroups() +
        ] + + 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 */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* 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; + 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 = ALLOC(int,nvars); + if (var == NULL) { + table->errorCode = CUDD_MEMORY_OUT; + goto zddGroupSiftingOutOfMem; + } + entry = ALLOC(int,nvars); + if (entry == NULL) { + table->errorCode = CUDD_MEMORY_OUT; + goto zddGroupSiftingOutOfMem; + } + sifted = 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 */ + + FREE(sifted); + FREE(var); + FREE(entry); + + return(1); + +zddGroupSiftingOutOfMem: + if (entry != NULL) FREE(entry); + if (var != NULL) FREE(var); + if (sifted != NULL) 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,swapy; +#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 */ diff --git a/distr/cudd/cuddZddIsop.c b/distr/cudd/cuddZddIsop.c new file mode 100644 index 0000000..fa03b61 --- /dev/null +++ b/distr/cudd/cuddZddIsop.c @@ -0,0 +1,911 @@ +/**CFile*********************************************************************** + + FileName [cuddZddIsop.c] + + PackageName [cudd] + + Synopsis [Functions to find irredundant SOP covers as ZDDs from BDDs.] + + Description [External procedures included in this module: +
          +
        • Cudd_bddIsop() +
        • Cudd_zddIsop() +
        • Cudd_MakeBddFromZddCover() +
        + Internal procedures included in this module: +
          +
        • cuddBddIsop() +
        • cuddZddIsop() +
        • cuddMakeBddFromZddCover() +
        + Static procedures included in this module: +
          +
        + ] + + 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 "util.h" +#include "cuddInt.h" + +/*---------------------------------------------------------------------------*/ +/* Constant declarations */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Stucture declarations */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Type declarations */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Variable declarations */ +/*---------------------------------------------------------------------------*/ + +#ifndef lint +static char rcsid[] DD_UNUSED = "$Id: cuddZddIsop.c,v 1.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 i should have indices 2i and + 2i+1. 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 */ +/*---------------------------------------------------------------------------*/ diff --git a/distr/cudd/cuddZddLin.c b/distr/cudd/cuddZddLin.c new file mode 100644 index 0000000..8f58e52 --- /dev/null +++ b/distr/cudd/cuddZddLin.c @@ -0,0 +1,967 @@ +/**CFile*********************************************************************** + + FileName [cuddZddLin.c] + + PackageName [cudd] + + Synopsis [Procedures for dynamic variable ordering of ZDDs.] + + Description [Internal procedures included in this module: +
          +
        • cuddZddLinearSifting() +
        + Static procedures included in this module: +
          +
        • cuddZddLinearInPlace() +
        • cuddZddLinerAux() +
        • cuddZddLinearUp() +
        • cuddZddLinearDown() +
        • cuddZddLinearBackward() +
        • cuddZddUndoMoves() +
        + ] + + 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 "util.h" +#include "cuddInt.h" + +/*---------------------------------------------------------------------------*/ +/* Constant declarations */ +/*---------------------------------------------------------------------------*/ + +#define CUDD_SWAP_MOVE 0 +#define CUDD_LINEAR_TRANSFORM_MOVE 1 +#define CUDD_INVERSE_TRANSFORM_MOVE 2 + +/*---------------------------------------------------------------------------*/ +/* Stucture declarations */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Type declarations */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Variable declarations */ +/*---------------------------------------------------------------------------*/ + +#ifndef lint +static char rcsid[] DD_UNUSED = "$Id: cuddZddLin.c,v 1.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. +
          +
        1. Order all the variables according to the number of entries + in each unique table. +
        2. Sift the variable up and down and applies the XOR transformation, + remembering each time the total size of the DD heap. +
        3. Select the best permutation. +
        4. Repeat 3 and 4 for all variables. +
        + Returns 1 if successful; 0 otherwise.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +int +cuddZddLinearSifting( + DdManager * table, + int lower, + int upper) +{ + int i; + int *var; + int size; + int x; + int result; +#ifdef DD_STATS + int previousSize; +#endif + + size = table->sizeZ; + empty = table->zero; + + /* Find order in which to sift variables. */ + var = NULL; + zdd_entry = ALLOC(int, size); + if (zdd_entry == NULL) { + table->errorCode = CUDD_MEMORY_OUT; + goto cuddZddSiftingOutOfMem; + } + var = ALLOC(int, size); + if (var == NULL) { + table->errorCode = CUDD_MEMORY_OUT; + goto cuddZddSiftingOutOfMem; + } + + for (i = 0; i < size; i++) { + x = table->permZ[i]; + zdd_entry[i] = table->subtableZ[x].keys; + var[i] = i; + } + + qsort((void *)var, size, sizeof(int), (DD_QSFP)cuddZddUniqueCompare); + + /* Now sift. */ + for (i = 0; i < ddMin(table->siftMaxVar, size); i++) { + if (zddTotalNumberSwapping >= table->siftMaxSwap) + break; + x = table->permZ[var[i]]; + if (x < lower || x > upper) continue; +#ifdef DD_STATS + previousSize = table->keysZ; +#endif + result = cuddZddLinearAux(table, x, lower, upper); + if (!result) + goto cuddZddSiftingOutOfMem; +#ifdef DD_STATS + if (table->keysZ < (unsigned) previousSize) { + (void) fprintf(table->out,"-"); + } else if (table->keysZ > (unsigned) previousSize) { + (void) fprintf(table->out,"+"); /* should never happen */ + (void) fprintf(table->out,"\nSize increased from %d to %d while sifting variable %d\n", previousSize, table->keysZ , var[i]); + } else { + (void) fprintf(table->out,"="); + } + fflush(table->out); +#endif + } + + FREE(var); + FREE(zdd_entry); + + return(1); + +cuddZddSiftingOutOfMem: + + if (zdd_entry != NULL) FREE(zdd_entry); + if (var != NULL) FREE(var); + + return(0); + +} /* end of cuddZddLinearSifting */ + + +/*---------------------------------------------------------------------------*/ +/* Definition of static functions */ +/*---------------------------------------------------------------------------*/ + + +/**Function******************************************************************** + + Synopsis [Linearly combines two adjacent variables.] + + Description [Linearly combines two adjacent variables. It assumes + that no dead nodes are present on entry to this procedure. The + procedure then guarantees that no dead nodes will be present when it + terminates. cuddZddLinearInPlace assumes that x < y. Returns the + number of keys in the table if successful; 0 otherwise.] + + SideEffects [None] + + SeeAlso [cuddZddSwapInPlace cuddLinearInPlace] + +******************************************************************************/ +static int +cuddZddLinearInPlace( + DdManager * table, + int x, + int y) +{ + DdNodePtr *xlist, *ylist; + int xindex, yindex; + int xslots, yslots; + int xshift, yshift; + int oldxkeys, oldykeys; + int newxkeys, newykeys; + int i; + int posn; + DdNode *f, *f1, *f0, *f11, *f10, *f01, *f00; + DdNode *newf1, *newf0, *g, *next, *previous; + DdNode *special; + +#ifdef DD_DEBUG + assert(x < y); + assert(cuddZddNextHigh(table,x) == y); + assert(table->subtableZ[x].keys != 0); + assert(table->subtableZ[y].keys != 0); + assert(table->subtableZ[x].dead == 0); + assert(table->subtableZ[y].dead == 0); +#endif + + zddTotalNumberLinearTr++; + + /* Get parameters of x subtable. */ + xindex = table->invpermZ[x]; + xlist = table->subtableZ[x].nodelist; + oldxkeys = table->subtableZ[x].keys; + xslots = table->subtableZ[x].slots; + xshift = table->subtableZ[x].shift; + newxkeys = 0; + + /* Get parameters of y subtable. */ + yindex = table->invpermZ[y]; + ylist = table->subtableZ[y].nodelist; + oldykeys = table->subtableZ[y].keys; + yslots = table->subtableZ[y].slots; + yshift = table->subtableZ[y].shift; + newykeys = oldykeys; + + /* The nodes in the x layer are put in two chains. The chain + ** pointed by g holds the normal nodes. When re-expressed they stay + ** in the x list. The chain pointed by special holds the elements + ** that will move to the y list. + */ + g = special = NULL; + for (i = 0; i < xslots; i++) { + f = xlist[i]; + if (f == NULL) continue; + xlist[i] = NULL; + while (f != NULL) { + next = f->next; + f1 = cuddT(f); + /* if (f1->index == yindex) */ cuddSatDec(f1->ref); + f0 = cuddE(f); + /* if (f0->index == yindex) */ cuddSatDec(f0->ref); + if ((int) f1->index == yindex && cuddE(f1) == empty && + (int) f0->index != yindex) { + f->next = special; + special = f; + } else { + f->next = g; + g = f; + } + f = next; + } /* while there are elements in the collision chain */ + } /* for each slot of the x subtable */ + + /* Mark y nodes with pointers from above x. We mark them by + ** changing their index to x. + */ + for (i = 0; i < yslots; i++) { + f = ylist[i]; + while (f != NULL) { + if (f->ref != 0) { + f->index = xindex; + } + f = f->next; + } /* while there are elements in the collision chain */ + } /* for each slot of the y subtable */ + + /* Move special nodes to the y list. */ + f = special; + while (f != NULL) { + next = f->next; + f1 = cuddT(f); + f11 = cuddT(f1); + cuddT(f) = f11; + cuddSatInc(f11->ref); + f0 = cuddE(f); + cuddSatInc(f0->ref); + f->index = yindex; + /* Insert at the beginning of the list so that it will be + ** found first if there is a duplicate. The duplicate will + ** eventually be moved or garbage collected. No node + ** re-expression will add a pointer to it. + */ + posn = ddHash(f11, f0, yshift); + f->next = ylist[posn]; + ylist[posn] = f; + newykeys++; + f = next; + } + + /* Take care of the remaining x nodes that must be re-expressed. + ** They form a linked list pointed by g. + */ + f = g; + while (f != NULL) { +#ifdef DD_COUNT + table->swapSteps++; +#endif + next = f->next; + /* Find f1, f0, f11, f10, f01, f00. */ + f1 = cuddT(f); + if ((int) f1->index == yindex || (int) f1->index == xindex) { + f11 = cuddT(f1); f10 = cuddE(f1); + } else { + f11 = empty; f10 = f1; + } + f0 = cuddE(f); + if ((int) f0->index == yindex || (int) f0->index == xindex) { + f01 = cuddT(f0); f00 = cuddE(f0); + } else { + f01 = empty; f00 = f0; + } + /* Create the new T child. */ + if (f01 == empty) { + newf1 = f10; + cuddSatInc(newf1->ref); + } else { + /* Check ylist for triple (yindex, f01, f10). */ + posn = ddHash(f01, f10, yshift); + /* For each element newf1 in collision list ylist[posn]. */ + newf1 = ylist[posn]; + /* Search the collision chain skipping the marked nodes. */ + while (newf1 != NULL) { + if (cuddT(newf1) == f01 && cuddE(newf1) == f10 && + (int) newf1->index == yindex) { + cuddSatInc(newf1->ref); + break; /* match */ + } + newf1 = newf1->next; + } /* while newf1 */ + if (newf1 == NULL) { /* no match */ + newf1 = cuddDynamicAllocNode(table); + if (newf1 == NULL) + goto zddSwapOutOfMem; + newf1->index = yindex; newf1->ref = 1; + cuddT(newf1) = f01; + cuddE(newf1) = f10; + /* Insert newf1 in the collision list ylist[pos]; + ** increase the ref counts of f01 and f10 + */ + newykeys++; + newf1->next = ylist[posn]; + ylist[posn] = newf1; + cuddSatInc(f01->ref); + cuddSatInc(f10->ref); + } + } + cuddT(f) = newf1; + + /* Do the same for f0. */ + /* Create the new E child. */ + if (f11 == empty) { + newf0 = f00; + cuddSatInc(newf0->ref); + } else { + /* Check ylist for triple (yindex, f11, f00). */ + posn = ddHash(f11, f00, yshift); + /* For each element newf0 in collision list ylist[posn]. */ + newf0 = ylist[posn]; + while (newf0 != NULL) { + if (cuddT(newf0) == f11 && cuddE(newf0) == f00 && + (int) newf0->index == yindex) { + cuddSatInc(newf0->ref); + break; /* match */ + } + newf0 = newf0->next; + } /* while newf0 */ + if (newf0 == NULL) { /* no match */ + newf0 = cuddDynamicAllocNode(table); + if (newf0 == NULL) + goto zddSwapOutOfMem; + newf0->index = yindex; newf0->ref = 1; + cuddT(newf0) = f11; cuddE(newf0) = f00; + /* Insert newf0 in the collision list ylist[posn]; + ** increase the ref counts of f11 and f00. + */ + newykeys++; + newf0->next = ylist[posn]; + ylist[posn] = newf0; + cuddSatInc(f11->ref); + cuddSatInc(f00->ref); + } + } + cuddE(f) = newf0; + + /* Re-insert the modified f in xlist. + ** The modified f does not already exists in xlist. + ** (Because of the uniqueness of the cofactors.) + */ + posn = ddHash(newf1, newf0, xshift); + newxkeys++; + f->next = xlist[posn]; + xlist[posn] = f; + f = next; + } /* while f != NULL */ + + /* GC the y layer and move the marked nodes to the x list. */ + + /* For each node f in ylist. */ + for (i = 0; i < yslots; i++) { + previous = NULL; + f = ylist[i]; + while (f != NULL) { + next = f->next; + if (f->ref == 0) { + cuddSatDec(cuddT(f)->ref); + cuddSatDec(cuddE(f)->ref); + cuddDeallocNode(table, f); + newykeys--; + if (previous == NULL) + ylist[i] = next; + else + previous->next = next; + } else if ((int) f->index == xindex) { /* move marked node */ + if (previous == NULL) + ylist[i] = next; + else + previous->next = next; + f1 = cuddT(f); + cuddSatDec(f1->ref); + /* Check ylist for triple (yindex, f1, empty). */ + posn = ddHash(f1, empty, yshift); + /* For each element newf1 in collision list ylist[posn]. */ + newf1 = ylist[posn]; + while (newf1 != NULL) { + if (cuddT(newf1) == f1 && cuddE(newf1) == empty && + (int) newf1->index == yindex) { + cuddSatInc(newf1->ref); + break; /* match */ + } + newf1 = newf1->next; + } /* while newf1 */ + if (newf1 == NULL) { /* no match */ + newf1 = cuddDynamicAllocNode(table); + if (newf1 == NULL) + goto zddSwapOutOfMem; + newf1->index = yindex; newf1->ref = 1; + cuddT(newf1) = f1; cuddE(newf1) = empty; + /* Insert newf1 in the collision list ylist[posn]; + ** increase the ref counts of f1 and empty. + */ + newykeys++; + newf1->next = ylist[posn]; + ylist[posn] = newf1; + if (posn == i && previous == NULL) + previous = newf1; + cuddSatInc(f1->ref); + cuddSatInc(empty->ref); + } + cuddT(f) = newf1; + f0 = cuddE(f); + /* Insert f in x list. */ + posn = ddHash(newf1, f0, xshift); + newxkeys++; + newykeys--; + f->next = xlist[posn]; + xlist[posn] = f; + } else { + previous = f; + } + f = next; + } /* while f */ + } /* for i */ + + /* Set the appropriate fields in table. */ + table->subtableZ[x].keys = newxkeys; + table->subtableZ[y].keys = newykeys; + + table->keysZ += newxkeys + newykeys - oldxkeys - oldykeys; + + /* Update univ section; univ[x] remains the same. */ + table->univ[y] = cuddT(table->univ[x]); + +#if 0 + (void) fprintf(table->out,"x = %d y = %d\n", x, y); + (void) Cudd_DebugCheck(table); + (void) Cudd_CheckKeys(table); +#endif + + return (table->keysZ); + +zddSwapOutOfMem: + (void) fprintf(table->err, "Error: cuddZddSwapInPlace out of memory\n"); + + return (0); + +} /* end of cuddZddLinearInPlace */ + + +/**Function******************************************************************** + + Synopsis [Given xLow <= x <= xHigh moves x up and down between the + boundaries.] + + Description [Given xLow <= x <= xHigh moves x up and down between the + boundaries. Finds the best position and does the required changes. + Returns 1 if successful; 0 otherwise.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +static int +cuddZddLinearAux( + DdManager * table, + int x, + int xLow, + int xHigh) +{ + Move *move; + Move *moveUp; /* list of up move */ + Move *moveDown; /* list of down move */ + + int initial_size; + int result; + + initial_size = table->keysZ; + +#ifdef DD_DEBUG + assert(table->subtableZ[x].keys > 0); +#endif + + moveDown = NULL; + moveUp = NULL; + + if (x == xLow) { + moveDown = cuddZddLinearDown(table, x, xHigh, NULL); + /* At this point x --> xHigh. */ + if (moveDown == (Move *) CUDD_OUT_OF_MEM) + goto cuddZddLinearAuxOutOfMem; + /* Move backward and stop at best position. */ + result = cuddZddLinearBackward(table, initial_size, moveDown); + if (!result) + goto cuddZddLinearAuxOutOfMem; + + } else if (x == xHigh) { + moveUp = cuddZddLinearUp(table, x, xLow, NULL); + /* At this point x --> xLow. */ + if (moveUp == (Move *) CUDD_OUT_OF_MEM) + goto cuddZddLinearAuxOutOfMem; + /* Move backward and stop at best position. */ + result = cuddZddLinearBackward(table, initial_size, moveUp); + if (!result) + goto cuddZddLinearAuxOutOfMem; + + } else if ((x - xLow) > (xHigh - x)) { /* must go down first: shorter */ + moveDown = cuddZddLinearDown(table, x, xHigh, NULL); + /* At this point x --> xHigh. */ + if (moveDown == (Move *) CUDD_OUT_OF_MEM) + goto cuddZddLinearAuxOutOfMem; + moveUp = cuddZddUndoMoves(table,moveDown); +#ifdef DD_DEBUG + assert(moveUp == NULL || moveUp->x == x); +#endif + moveUp = cuddZddLinearUp(table, x, xLow, moveUp); + if (moveUp == (Move *) CUDD_OUT_OF_MEM) + goto cuddZddLinearAuxOutOfMem; + /* Move backward and stop at best position. */ + result = cuddZddLinearBackward(table, initial_size, moveUp); + if (!result) + goto cuddZddLinearAuxOutOfMem; + + } else { + moveUp = cuddZddLinearUp(table, x, xLow, NULL); + /* At this point x --> xHigh. */ + if (moveUp == (Move *) CUDD_OUT_OF_MEM) + goto cuddZddLinearAuxOutOfMem; + /* Then move up. */ + moveDown = cuddZddUndoMoves(table,moveUp); +#ifdef DD_DEBUG + assert(moveDown == NULL || moveDown->y == x); +#endif + moveDown = cuddZddLinearDown(table, x, xHigh, moveDown); + if (moveDown == (Move *) CUDD_OUT_OF_MEM) + goto cuddZddLinearAuxOutOfMem; + /* Move backward and stop at best position. */ + result = cuddZddLinearBackward(table, initial_size, moveDown); + if (!result) + goto cuddZddLinearAuxOutOfMem; + } + + while (moveDown != NULL) { + move = moveDown->next; + cuddDeallocMove(table, moveDown); + moveDown = move; + } + while (moveUp != NULL) { + move = moveUp->next; + cuddDeallocMove(table, moveUp); + moveUp = move; + } + + return(1); + +cuddZddLinearAuxOutOfMem: + if (moveDown != (Move *) CUDD_OUT_OF_MEM) { + while (moveDown != NULL) { + move = moveDown->next; + cuddDeallocMove(table, moveDown); + moveDown = move; + } + } + if (moveUp != (Move *) CUDD_OUT_OF_MEM) { + while (moveUp != NULL) { + move = moveUp->next; + cuddDeallocMove(table, moveUp); + moveUp = move; + } + } + + return(0); + +} /* end of cuddZddLinearAux */ + + +/**Function******************************************************************** + + Synopsis [Sifts a variable up applying the XOR transformation.] + + Description [Sifts a variable up applying the XOR + transformation. Moves y up until either it reaches the bound (xLow) + or the size of the ZDD heap increases too much. Returns the set of + moves in case of success; NULL if memory is full.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +static Move * +cuddZddLinearUp( + DdManager * table, + int y, + int xLow, + Move * prevMoves) +{ + Move *moves; + Move *move; + int x; + int size, newsize; + int limitSize; + + moves = prevMoves; + limitSize = table->keysZ; + + x = cuddZddNextLow(table, y); + while (x >= xLow) { + size = cuddZddSwapInPlace(table, x, y); + if (size == 0) + goto cuddZddLinearUpOutOfMem; + newsize = cuddZddLinearInPlace(table, x, y); + if (newsize == 0) + goto cuddZddLinearUpOutOfMem; + move = (Move *) cuddDynamicAllocNode(table); + if (move == NULL) + goto cuddZddLinearUpOutOfMem; + move->x = x; + move->y = y; + move->next = moves; + moves = move; + move->flags = CUDD_SWAP_MOVE; + if (newsize > size) { + /* Undo transformation. The transformation we apply is + ** its own inverse. Hence, we just apply the transformation + ** again. + */ + newsize = cuddZddLinearInPlace(table,x,y); + if (newsize == 0) goto cuddZddLinearUpOutOfMem; +#ifdef DD_DEBUG + if (newsize != size) { + (void) fprintf(table->err,"Change in size after identity transformation! From %d to %d\n",size,newsize); + } +#endif + } else { + size = newsize; + move->flags = CUDD_LINEAR_TRANSFORM_MOVE; + } + move->size = size; + + if ((double)size > (double)limitSize * table->maxGrowth) + break; + if (size < limitSize) + limitSize = size; + + y = x; + x = cuddZddNextLow(table, y); + } + return(moves); + +cuddZddLinearUpOutOfMem: + while (moves != NULL) { + move = moves->next; + cuddDeallocMove(table, moves); + moves = move; + } + return((Move *) CUDD_OUT_OF_MEM); + +} /* end of cuddZddLinearUp */ + + +/**Function******************************************************************** + + Synopsis [Sifts a variable down and applies the XOR transformation.] + + Description [Sifts a variable down. Moves x down until either it + reaches the bound (xHigh) or the size of the ZDD heap increases too + much. Returns the set of moves in case of success; NULL if memory is + full.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +static Move * +cuddZddLinearDown( + DdManager * table, + int x, + int xHigh, + Move * prevMoves) +{ + Move *moves; + Move *move; + int y; + int size, newsize; + int limitSize; + + moves = prevMoves; + limitSize = table->keysZ; + + y = cuddZddNextHigh(table, x); + while (y <= xHigh) { + size = cuddZddSwapInPlace(table, x, y); + if (size == 0) + goto cuddZddLinearDownOutOfMem; + newsize = cuddZddLinearInPlace(table, x, y); + if (newsize == 0) + goto cuddZddLinearDownOutOfMem; + move = (Move *) cuddDynamicAllocNode(table); + if (move == NULL) + goto cuddZddLinearDownOutOfMem; + move->x = x; + move->y = y; + move->next = moves; + moves = move; + move->flags = CUDD_SWAP_MOVE; + if (newsize > size) { + /* Undo transformation. The transformation we apply is + ** its own inverse. Hence, we just apply the transformation + ** again. + */ + newsize = cuddZddLinearInPlace(table,x,y); + if (newsize == 0) goto cuddZddLinearDownOutOfMem; + if (newsize != size) { + (void) fprintf(table->err,"Change in size after identity transformation! From %d to %d\n",size,newsize); + } + } else { + size = newsize; + move->flags = CUDD_LINEAR_TRANSFORM_MOVE; + } + move->size = size; + + if ((double)size > (double)limitSize * table->maxGrowth) + break; + if (size < limitSize) + limitSize = size; + + x = y; + y = cuddZddNextHigh(table, x); + } + return(moves); + +cuddZddLinearDownOutOfMem: + while (moves != NULL) { + move = moves->next; + cuddDeallocMove(table, moves); + moves = move; + } + return((Move *) CUDD_OUT_OF_MEM); + +} /* end of cuddZddLinearDown */ + + +/**Function******************************************************************** + + Synopsis [Given a set of moves, returns the ZDD heap to the position + giving the minimum size.] + + Description [Given a set of moves, returns the ZDD heap to the + position giving the minimum size. In case of ties, returns to the + closest position giving the minimum size. Returns 1 in case of + success; 0 otherwise.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +static int +cuddZddLinearBackward( + DdManager * table, + int size, + Move * moves) +{ + Move *move; + int res; + + /* Find the minimum size among moves. */ + for (move = moves; move != NULL; move = move->next) { + if (move->size < size) { + size = move->size; + } + } + + for (move = moves; move != NULL; move = move->next) { + if (move->size == size) return(1); + if (move->flags == CUDD_LINEAR_TRANSFORM_MOVE) { + res = cuddZddLinearInPlace(table,(int)move->x,(int)move->y); + if (!res) return(0); + } + res = cuddZddSwapInPlace(table, move->x, move->y); + if (!res) + return(0); + if (move->flags == CUDD_INVERSE_TRANSFORM_MOVE) { + res = cuddZddLinearInPlace(table,(int)move->x,(int)move->y); + if (!res) return(0); + } + } + + return(1); + +} /* end of cuddZddLinearBackward */ + + +/**Function******************************************************************** + + Synopsis [Given a set of moves, returns the ZDD heap to the order + in effect before the moves.] + + Description [Given a set of moves, returns the ZDD heap to the + order in effect before the moves. Returns 1 in case of success; + 0 otherwise.] + + SideEffects [None] + +******************************************************************************/ +static Move* +cuddZddUndoMoves( + DdManager * table, + Move * moves) +{ + Move *invmoves = NULL; + Move *move; + Move *invmove; + int size; + + for (move = moves; move != NULL; move = move->next) { + invmove = (Move *) cuddDynamicAllocNode(table); + if (invmove == NULL) goto cuddZddUndoMovesOutOfMem; + invmove->x = move->x; + invmove->y = move->y; + invmove->next = invmoves; + invmoves = invmove; + if (move->flags == CUDD_SWAP_MOVE) { + invmove->flags = CUDD_SWAP_MOVE; + size = cuddZddSwapInPlace(table,(int)move->x,(int)move->y); + if (!size) goto cuddZddUndoMovesOutOfMem; + } else if (move->flags == CUDD_LINEAR_TRANSFORM_MOVE) { + invmove->flags = CUDD_INVERSE_TRANSFORM_MOVE; + size = cuddZddLinearInPlace(table,(int)move->x,(int)move->y); + if (!size) goto cuddZddUndoMovesOutOfMem; + size = cuddZddSwapInPlace(table,(int)move->x,(int)move->y); + if (!size) goto cuddZddUndoMovesOutOfMem; + } else { /* must be CUDD_INVERSE_TRANSFORM_MOVE */ +#ifdef DD_DEBUG + (void) fprintf(table->err,"Unforseen event in ddUndoMoves!\n"); +#endif + invmove->flags = CUDD_LINEAR_TRANSFORM_MOVE; + size = cuddZddSwapInPlace(table,(int)move->x,(int)move->y); + if (!size) goto cuddZddUndoMovesOutOfMem; + size = cuddZddLinearInPlace(table,(int)move->x,(int)move->y); + if (!size) goto cuddZddUndoMovesOutOfMem; + } + invmove->size = size; + } + + return(invmoves); + +cuddZddUndoMovesOutOfMem: + while (invmoves != NULL) { + move = invmoves->next; + cuddDeallocMove(table, invmoves); + invmoves = move; + } + return((Move *) CUDD_OUT_OF_MEM); + +} /* end of cuddZddUndoMoves */ + diff --git a/distr/cudd/cuddZddMisc.c b/distr/cudd/cuddZddMisc.c new file mode 100644 index 0000000..ac22665 --- /dev/null +++ b/distr/cudd/cuddZddMisc.c @@ -0,0 +1,278 @@ +/**CFile*********************************************************************** + + FileName [cuddZddMisc.c] + + PackageName [cudd] + + Synopsis [Miscellaneous utility functions for ZDDs.] + + Description [External procedures included in this module: +
          +
        • Cudd_zddDagSize() +
        • Cudd_zddCountMinterm() +
        • Cudd_zddPrintSubtable() +
        + Internal procedures included in this module: +
          +
        + Static procedures included in this module: +
          +
        • cuddZddDagInt() +
        + ] + + 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 +#include "util.h" +#include "cuddInt.h" + +/*---------------------------------------------------------------------------*/ +/* Constant declarations */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Stucture declarations */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Type declarations */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Variable declarations */ +/*---------------------------------------------------------------------------*/ + +#ifndef lint +static char rcsid[] DD_UNUSED = "$Id: cuddZddMisc.c,v 1.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 + node. This procedure takes a parameter + path 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 */ diff --git a/distr/cudd/cuddZddPort.c b/distr/cudd/cuddZddPort.c new file mode 100644 index 0000000..c4f9046 --- /dev/null +++ b/distr/cudd/cuddZddPort.c @@ -0,0 +1,381 @@ +/**CFile*********************************************************************** + + FileName [cuddZddPort.c] + + PackageName [cudd] + + Synopsis [Functions that translate BDDs to ZDDs.] + + Description [External procedures included in this module: +
          +
        • Cudd_zddPortFromBdd() +
        • Cudd_zddPortToBdd() +
        + Internal procedures included in this module: +
          +
        + Static procedures included in this module: +
          +
        • zddPortFromBddStep() +
        • zddPortToBddStep() +
        + ] + + 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 "util.h" +#include "cuddInt.h" + +/*---------------------------------------------------------------------------*/ +/* Constant declarations */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Stucture declarations */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Type declarations */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Variable declarations */ +/*---------------------------------------------------------------------------*/ + +#ifndef lint +static char rcsid[] DD_UNUSED = "$Id: cuddZddPort.c,v 1.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 */ + diff --git a/distr/cudd/cuddZddReord.c b/distr/cudd/cuddZddReord.c new file mode 100644 index 0000000..410a2db --- /dev/null +++ b/distr/cudd/cuddZddReord.c @@ -0,0 +1,1660 @@ +/**CFile*********************************************************************** + + FileName [cuddZddReord.c] + + PackageName [cudd] + + Synopsis [Procedures for dynamic variable ordering of ZDDs.] + + Description [External procedures included in this module: +
          +
        • Cudd_zddReduceHeap() +
        • Cudd_zddShuffleHeap() +
        + Internal procedures included in this module: +
          +
        • cuddZddAlignToBdd() +
        • cuddZddNextHigh() +
        • cuddZddNextLow() +
        • cuddZddUniqueCompare() +
        • cuddZddSwapInPlace() +
        • cuddZddSwapping() +
        • cuddZddSifting() +
        + Static procedures included in this module: +
          +
        • zddSwapAny() +
        • cuddZddSiftingAux() +
        • cuddZddSiftingUp() +
        • cuddZddSiftingDown() +
        • cuddZddSiftingBackward() +
        • zddReorderPreprocess() +
        • zddReorderPostprocess() +
        • zddShuffle() +
        • zddSiftUp() +
        + ] + + 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 "util.h" +#include "cuddInt.h" + +/*---------------------------------------------------------------------------*/ +/* 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: +
          +
        • Swapping +
        • Sifting +
        • Symmetric Sifting +
        + + For sifting and symmetric sifting it is possible to request reordering + to convergence.

        + + 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 + M be the ratio of the two numbers. cuddZddAlignToBdd + then considers the ZDD variables from M*i to + (M+1)*i-1 as corresponding to BDD variable + i. 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 = 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); + 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 < 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, *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(f11, 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(f10, 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(newf1, 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. +

          +
        1. Select two variables (RANDOM or HEURISTIC). +
        2. Permute these variables. +
        3. If the nodes have decreased accept the permutation. +
        4. Otherwise reconstruct the original heap. +
        5. Loop. +
        + 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; + 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. +
          +
        1. Order all the variables according to the number of entries + in each unique table. +
        2. Sift the variable up and down, remembering each time the + total size of the DD heap. +
        3. Select the best permutation. +
        4. Repeat 3 and 4 for all variables. +
        + 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 = ALLOC(int, size); + if (zdd_entry == NULL) { + table->errorCode = CUDD_MEMORY_OUT; + goto cuddZddSiftingOutOfMem; + } + var = ALLOC(int, size); + if (var == NULL) { + table->errorCode = CUDD_MEMORY_OUT; + goto cuddZddSiftingOutOfMem; + } + + for (i = 0; i < size; i++) { + x = table->permZ[i]; + zdd_entry[i] = table->subtableZ[x].keys; + var[i] = i; + } + + qsort((void *)var, size, sizeof(int), (DD_QSFP)cuddZddUniqueCompare); + + /* Now sift. */ + for (i = 0; i < ddMin(table->siftMaxVar, size); i++) { + if (zddTotalNumberSwapping >= table->siftMaxSwap) + break; + 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 + } + + FREE(var); + FREE(zdd_entry); + + return(1); + +cuddZddSiftingOutOfMem: + + if (zdd_entry != NULL) FREE(zdd_entry); + if (var != NULL) 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 * 0.5) 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 = 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(cuddT(node), cuddE(node), shift); + node->next = nodelist[posn]; + nodelist[posn] = node; + node = next; + } + } + 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 */ + diff --git a/distr/cudd/cuddZddSetop.c b/distr/cudd/cuddZddSetop.c new file mode 100644 index 0000000..9025204 --- /dev/null +++ b/distr/cudd/cuddZddSetop.c @@ -0,0 +1,1166 @@ +/**CFile*********************************************************************** + + FileName [cuddZddSetop.c] + + PackageName [cudd] + + Synopsis [Set operations on ZDDs.] + + Description [External procedures included in this module: +
          +
        • Cudd_zddIte() +
        • Cudd_zddUnion() +
        • Cudd_zddIntersect() +
        • Cudd_zddDiff() +
        • Cudd_zddDiffConst() +
        • Cudd_zddSubset1() +
        • Cudd_zddSubset0() +
        • Cudd_zddChange() +
        + Internal procedures included in this module: +
          +
        • cuddZddIte() +
        • cuddZddUnion() +
        • cuddZddIntersect() +
        • cuddZddDiff() +
        • cuddZddChangeAux() +
        • cuddZddSubset1() +
        • cuddZddSubset0() +
        + Static procedures included in this module: +
          +
        • zdd_subset1_aux() +
        • zdd_subset0_aux() +
        • zddVarToConst() +
        + ] + + 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 "util.h" +#include "cuddInt.h" + +/*---------------------------------------------------------------------------*/ +/* 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 */ + diff --git a/distr/cudd/cuddZddSymm.c b/distr/cudd/cuddZddSymm.c new file mode 100644 index 0000000..1fba52f --- /dev/null +++ b/distr/cudd/cuddZddSymm.c @@ -0,0 +1,1699 @@ +/**CFile*********************************************************************** + + FileName [cuddZddSymm.c] + + PackageName [cudd] + + Synopsis [Functions for symmetry-based ZDD variable reordering.] + + Description [External procedures included in this module: +
          +
        • Cudd_zddSymmProfile() +
        + Internal procedures included in this module: +
          +
        • cuddZddSymmCheck() +
        • cuddZddSymmSifting() +
        • cuddZddSymmSiftingConv() +
        + Static procedures included in this module: +
          +
        • cuddZddUniqueCompare() +
        • cuddZddSymmSiftingAux() +
        • cuddZddSymmSiftingConvAux() +
        • cuddZddSymmSifting_up() +
        • cuddZddSymmSifting_down() +
        • zdd_group_move() +
        • cuddZddSymmSiftingBackward() +
        • zdd_group_move_backward() +
        + ] + + 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 "util.h" +#include "cuddInt.h" + +/*---------------------------------------------------------------------------*/ +/* 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. +
          +
        1. Order all the variables according to the number of entries in + each unique subtable. +
        2. Sift the variable up and down, remembering each time the total + size of the ZDD heap and grouping variables that are symmetric. +
        3. Select the best permutation. +
        4. Repeat 3 and 4 for all variables. +
        + 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 = ALLOC(int, nvars); + if (zdd_entry == NULL) { + table->errorCode = CUDD_MEMORY_OUT; + goto cuddZddSymmSiftingOutOfMem; + } + var = 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 + } + } + + FREE(var); + 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) + FREE(zdd_entry); + if (var != NULL) + 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. +
          +
        1. Order all the variables according to the number of entries in + each unique subtable. +
        2. Sift the variable up and down, remembering each time the total + size of the ZDD heap and grouping variables that are symmetric. +
        3. Select the best permutation. +
        4. Repeat 3 and 4 for all variables. +
        5. Repeat 1-4 until no further improvement. +
        + 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 = ALLOC(int, nvars); + if (zdd_entry == NULL) { + table->errorCode = CUDD_MEMORY_OUT; + goto cuddZddSymmSiftingConvOutOfMem; + } + var = 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 + + FREE(var); + FREE(zdd_entry); + + return(1+symvars); + +cuddZddSymmSiftingConvOutOfMem: + + if (zdd_entry != NULL) + FREE(zdd_entry); + if (var != NULL) + 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; + + 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, swapy; + +#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; + 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 */ + diff --git a/distr/cudd/cuddZddUtil.c b/distr/cudd/cuddZddUtil.c new file mode 100644 index 0000000..9dd45ff --- /dev/null +++ b/distr/cudd/cuddZddUtil.c @@ -0,0 +1,1063 @@ +/**CFile*********************************************************************** + + FileName [cuddZddUtil.c] + + PackageName [cudd] + + Synopsis [Utility functions for ZDDs.] + + Description [External procedures included in this module: +
          +
        • Cudd_zddPrintMinterm() +
        • Cudd_zddPrintCover() +
        • Cudd_zddPrintDebug() +
        • Cudd_zddFirstPath() +
        • Cudd_zddNextPath() +
        • Cudd_zddCoverPathToString() +
        • Cudd_zddDumpDot() +
        + Internal procedures included in this module: +
          +
        • cuddZddP() +
        + Static procedures included in this module: +
          +
        • zp2() +
        • zdd_print_minterm_aux() +
        • zddPrintCoverAux() +
        + ] + + 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 "util.h" +#include "cuddInt.h" + +/*---------------------------------------------------------------------------*/ +/* 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 = 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); + 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 = 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); + 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 > 0. Specifically: +
          +
        • pr = 0 : prints nothing +
        • pr = 1 : prints counts of nodes and minterms +
        • pr = 2 : prints counts + disjoint sum of products +
        • pr = 3 : prints counts + list of nodes +
        • pr > 3 : prints counts + disjoint sum of products + list of nodes +
        + 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.

        + 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.

        + 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 = 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 = ALLOC(int,nvars); + if (gen->gen.cubes.cube == NULL) { + zdd->errorCode = CUDD_MEMORY_OUT; + 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 = ALLOC(DdNodePtr, nvars+1); + if (gen->stack.stack == NULL) { + zdd->errorCode = CUDD_MEMORY_OUT; + FREE(gen->gen.cubes.cube); + 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 = 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: +

          +
        • solid line: THEN arcs; +
        • dashed line: ELSE arcs. +
        + 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 = 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, &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); + FREE(sorted); + return(1); + +failure: + if (sorted != NULL) 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 */ diff --git a/distr/cudd/doc/cudd.doc b/distr/cudd/doc/cudd.doc new file mode 100644 index 0000000..340d660 --- /dev/null +++ b/distr/cudd/doc/cudd.doc @@ -0,0 +1,6399 @@ +The cudd package + +The University of Colorado decision diagram package. + +Fabio Somenzi + +********************************************************************** + +Cudd_AddHook() Adds a function to a hook. + +Cudd_ApaAdd() Adds two arbitrary precision integers. + +Cudd_ApaCompareRatios() Compares the ratios of two arbitrary precision + integers to two unsigned ints. + +Cudd_ApaCompare() Compares two arbitrary precision integers. + +Cudd_ApaCopy() Makes a copy of an arbitrary precision integer. + +Cudd_ApaCountMinterm() Counts the number of minterms of a DD. + +Cudd_ApaIntDivision() Divides an arbitrary precision integer by an + integer. + +Cudd_ApaNumberOfDigits() Finds the number of digits for an arbitrary + precision integer. + +Cudd_ApaPowerOfTwo() Sets an arbitrary precision integer to a power + of two. + +Cudd_ApaPrintDecimal() Prints an arbitrary precision integer in + decimal format. + +Cudd_ApaPrintDensity() Prints the density of a BDD or ADD using + arbitrary precision arithmetic. + +Cudd_ApaPrintExponential() Prints an arbitrary precision integer in + exponential format. + +Cudd_ApaPrintHex() Prints an arbitrary precision integer in + hexadecimal format. + +Cudd_ApaPrintMintermExp() Prints the number of minterms of a BDD or ADD + in exponential format using arbitrary + precision arithmetic. + +Cudd_ApaPrintMinterm() Prints the number of minterms of a BDD or ADD + using arbitrary precision arithmetic. + +Cudd_ApaSetToLiteral() Sets an arbitrary precision integer to a one- + digit literal. + +Cudd_ApaShiftRight() Shifts right an arbitrary precision integer by + one binary place. + +Cudd_ApaShortDivision() Divides an arbitrary precision integer by a + digit. + +Cudd_ApaSubtract() Subtracts two arbitrary precision integers. + +Cudd_AutodynDisableZdd() Disables automatic dynamic reordering of ZDDs. + +Cudd_AutodynDisable() Disables automatic dynamic reordering. + +Cudd_AutodynEnableZdd() Enables automatic dynamic reordering of ZDDs. + +Cudd_AutodynEnable() Enables automatic dynamic reordering of BDDs + and ADDs. + +Cudd_AverageDistance() Computes the average distance between adjacent + nodes. + +Cudd_BddToAdd() Converts a BDD to a 0-1 ADD. + +Cudd_BddToCubeArray() Builds a positional array from the BDD of a + cube. + +Cudd_BiasedOverApprox() Extracts a dense superset from a BDD with the + biased underapproximation method. + +Cudd_BiasedUnderApprox() Extracts a dense subset from a BDD with the + biased underapproximation method. + +Cudd_CProjection() Computes the compatible projection of R w.r.t. + cube Y. + +Cudd_CheckKeys() Checks for several conditions that should not + occur. + +Cudd_CheckZeroRef() Checks the unique table for nodes with non-zero + reference counts. + +Cudd_ClassifySupport() Classifies the variables in the support of two + DDs. + +Cudd_ClearErrorCode() Clear the error code of a manager. + +Cudd_CofMinterm() Computes the fraction of minterms in the on-set + of all the positive cofactors of a BDD or + ADD. + +Cudd_Cofactor() Computes the cofactor of f with respect to g. + +Cudd_CountLeaves() Counts the number of leaves in a DD. + +Cudd_CountMinterm() Counts the number of minterms of a DD. + +Cudd_CountPathsToNonZero() Counts the number of paths to a non-zero + terminal of a DD. + +Cudd_CountPath() Counts the number of paths of a DD. + +Cudd_CubeArrayToBdd() Builds the BDD of a cube from a positional + array. + +Cudd_DagSize() Counts the number of nodes in a DD. + +Cudd_DeadAreCounted() Tells whether dead nodes are counted towards + triggering reordering. + +Cudd_DebugCheck() Checks for inconsistencies in the DD heap. + +Cudd_Decreasing() Determines whether a BDD is negative unate in a + variable. + +Cudd_DelayedDerefBdd() Decreases the reference count of BDD node n. + +Cudd_Density() Computes the density of a BDD or ADD. + +Cudd_Deref() Decreases the reference count of node. + +Cudd_DisableGarbageCollection() + Disables garbage collection. + +Cudd_DisableReorderingReporting() + Disables reporting of reordering stats. + +Cudd_Disequality() Generates a BDD for the function x - y != c. + +Cudd_DumpBlifBody() Writes a blif body representing the argument + BDDs. + +Cudd_DumpBlif() Writes a blif file representing the argument + BDDs. + +Cudd_DumpDDcal() Writes a DDcal file representing the argument + BDDs. + +Cudd_DumpDaVinci() Writes a daVinci file representing the argument + BDDs. + +Cudd_DumpDot() Writes a dot file representing the argument + DDs. + +Cudd_DumpFactoredForm() Writes factored forms representing the argument + BDDs. + +Cudd_Dxygtdxz() Generates a BDD for the function d(x,y) > + d(x,z). + +Cudd_Dxygtdyz() Generates a BDD for the function d(x,y) > + d(y,z). + +Cudd_EnableGarbageCollection() Enables garbage collection. + +Cudd_EnableReorderingReporting() + Enables reporting of reordering stats. + +Cudd_EpdCountMinterm() Counts the number of minterms of a DD with + extended precision. + +Cudd_EqualSupNorm() Compares two ADDs for equality within + tolerance. + +Cudd_EquivDC() Tells whether F and G are identical wherever D + is 0. + +Cudd_EstimateCofactorSimple() Estimates the number of nodes in a cofactor of + a DD. + +Cudd_EstimateCofactor() Estimates the number of nodes in a cofactor of + a DD. + +Cudd_Eval() Returns the value of a DD for a given variable + assignment. + +Cudd_ExpectedUsedSlots() Computes the expected fraction of used slots in + the unique table. + +Cudd_FindEssential() Finds the essential variables of a DD. + +Cudd_FindTwoLiteralClauses() Finds the two literal clauses of a DD. + +Cudd_FirstCube() Finds the first cube of a decision diagram. + +Cudd_FirstNode() Finds the first node of a decision diagram. + +Cudd_FirstPrime() Finds the first prime of a Boolean function. + +Cudd_FreeTree() Frees the variable group tree of the manager. + +Cudd_FreeZddTree() Frees the variable group tree of the manager. + +Cudd_GarbageCollectionEnabled() + Tells whether garbage collection is enabled. + +Cudd_GenFree() Frees a CUDD generator. + +Cudd_Increasing() Determines whether a BDD is positive unate in a + variable. + +Cudd_IndicesToCube() Builds a cube of BDD variables from an array of + indices. + +Cudd_Inequality() Generates a BDD for the function x - y ≥ c. + +Cudd_Init() Creates a new DD manager. + +Cudd_IsGenEmpty() Queries the status of a generator. + +Cudd_IsInHook() Checks whether a function is in a hook. + +Cudd_IsNonConstant() Returns 1 if a DD node is not constant. + +Cudd_IterDerefBdd() Decreases the reference count of BDD node n. + +Cudd_LargestCube() Finds a largest cube in a DD. + +Cudd_MakeBddFromZddCover() Converts a ZDD cover to a BDD graph. + +Cudd_MakeTreeNode() Creates a new variable group. + +Cudd_MakeZddTreeNode() Creates a new ZDD variable group. + +Cudd_MinHammingDist() Returns the minimum Hamming distance between f + and minterm. + +Cudd_NewApaNumber() Allocates memory for an arbitrary precision + integer. + +Cudd_NextCube() Generates the next cube of a decision diagram + onset. + +Cudd_NextNode() Finds the next node of a decision diagram. + +Cudd_NextPrime() Generates the next prime of a Boolean function. + +Cudd_NodeReadIndex() Returns the index of the node. + +Cudd_OutOfMem() Warns that a memory allocation failed. + +Cudd_OverApprox() Extracts a dense superset from a BDD with + Shiple's underapproximation method. + +Cudd_Prime() Returns the next prime >= p. + +Cudd_PrintDebug() Prints to the standard output a DD and its + statistics. + +Cudd_PrintInfo() Prints out statistics and settings for a CUDD + manager. + +Cudd_PrintLinear() Prints the linear transform matrix. + +Cudd_PrintMinterm() Prints a disjoint sum of products. + +Cudd_PrintTwoLiteralClauses() Prints the two literal clauses of a DD. + +Cudd_PrintVersion() Prints the package version number. + +Cudd_PrioritySelect() Selects pairs from R using a priority function. + +Cudd_Quit() Deletes resources associated with a DD manager. + +Cudd_Random() Portable random number generator. + +Cudd_ReadArcviolation() Returns the current value of the arcviolation + parameter used in group sifting. + +Cudd_ReadBackground() Reads the background constant of the manager. + +Cudd_ReadCacheHits() Returns the number of cache hits. + +Cudd_ReadCacheLookUps() Returns the number of cache look-ups. + +Cudd_ReadCacheSlots() Reads the number of slots in the cache. + +Cudd_ReadCacheUsedSlots() Reads the fraction of used slots in the cache. + +Cudd_ReadDead() Returns the number of dead nodes in the unique + table. + +Cudd_ReadEpsilon() Reads the epsilon parameter of the manager. + +Cudd_ReadErrorCode() Returns the code of the last error. + +Cudd_ReadGarbageCollectionTime() + Returns the time spent in garbage collection. + +Cudd_ReadGarbageCollections() Returns the number of times garbage collection + has occurred. + +Cudd_ReadGroupcheck() Reads the groupcheck parameter of the manager. + +Cudd_ReadInvPermZdd() Returns the index of the ZDD variable currently + in the i-th position of the order. + +Cudd_ReadInvPerm() Returns the index of the variable currently in + the i-th position of the order. + +Cudd_ReadIthClause() Accesses the i-th clause of a DD. + +Cudd_ReadKeys() Returns the number of nodes in the unique + table. + +Cudd_ReadLinear() Reads an entry of the linear transform matrix. + +Cudd_ReadLogicZero() Returns the logic zero constant of the manager. + +Cudd_ReadLooseUpTo() Reads the looseUpTo parameter of the manager. + +Cudd_ReadMaxCacheHard() Reads the maxCacheHard parameter of the + manager. + +Cudd_ReadMaxCache() Returns the soft limit for the cache size. + +Cudd_ReadMaxGrowthAlternate() Reads the maxGrowthAlt parameter of the + manager. + +Cudd_ReadMaxGrowth() Reads the maxGrowth parameter of the manager. + +Cudd_ReadMaxLive() Reads the maximum allowed number of live nodes. + +Cudd_ReadMaxMemory() Reads the maximum allowed memory. + +Cudd_ReadMemoryInUse() Returns the memory in use by the manager + measured in bytes. + +Cudd_ReadMinDead() Reads the minDead parameter of the manager. + +Cudd_ReadMinHit() Reads the hit rate that causes resizinig of the + computed table. + +Cudd_ReadMinusInfinity() Reads the minus-infinity constant from the + manager. + +Cudd_ReadNextReordering() Returns the threshold for the next dynamic + reordering. + +Cudd_ReadNodeCount() Reports the number of nodes in BDDs and ADDs. + +Cudd_ReadNodesDropped() Returns the number of nodes dropped. + +Cudd_ReadNodesFreed() Returns the number of nodes freed. + +Cudd_ReadNumberXovers() Reads the current number of crossovers used by + the genetic algorithm for reordering. + +Cudd_ReadOne() Returns the one constant of the manager. + +Cudd_ReadPeakLiveNodeCount() Reports the peak number of live nodes. + +Cudd_ReadPeakNodeCount() Reports the peak number of nodes. + +Cudd_ReadPermZdd() Returns the current position of the i-th ZDD + variable in the order. + +Cudd_ReadPerm() Returns the current position of the i-th + variable in the order. + +Cudd_ReadPlusInfinity() Reads the plus-infinity constant from the + manager. + +Cudd_ReadPopulationSize() Reads the current size of the population used + by the genetic algorithm for reordering. + +Cudd_ReadRecomb() Returns the current value of the recombination + parameter used in group sifting. + +Cudd_ReadRecursiveCalls() Returns the number of recursive calls. + +Cudd_ReadReorderingCycle() Reads the reordCycle parameter of the manager. + +Cudd_ReadReorderingTime() Returns the time spent in reordering. + +Cudd_ReadReorderings() Returns the number of times reordering has + occurred. + +Cudd_ReadSiftMaxSwap() Reads the siftMaxSwap parameter of the manager. + +Cudd_ReadSiftMaxVar() Reads the siftMaxVar parameter of the manager. + +Cudd_ReadSize() Returns the number of BDD variables in + existance. + +Cudd_ReadSlots() Returns the total number of slots of the unique + table. + +Cudd_ReadStderr() Reads the stderr of a manager. + +Cudd_ReadStdout() Reads the stdout of a manager. + +Cudd_ReadSwapSteps() Reads the number of elementary reordering + steps. + +Cudd_ReadSymmviolation() Returns the current value of the symmviolation + parameter used in group sifting. + +Cudd_ReadTree() Returns the variable group tree of the manager. + +Cudd_ReadUniqueLinks() Returns the number of links followed in the + unique table. + +Cudd_ReadUniqueLookUps() Returns the number of look-ups in the unique + table. + +Cudd_ReadUsedSlots() Reads the fraction of used slots in the unique + table. + +Cudd_ReadVars() Returns the i-th element of the vars array. + +Cudd_ReadZddOne() Returns the ZDD for the constant 1 function. + +Cudd_ReadZddSize() Returns the number of ZDD variables in + existance. + +Cudd_ReadZddTree() Returns the variable group tree of the manager. + +Cudd_ReadZero() Returns the zero constant of the manager. + +Cudd_RecursiveDerefZdd() Decreases the reference count of ZDD node n. + +Cudd_RecursiveDeref() Decreases the reference count of node n. + +Cudd_ReduceHeap() Main dynamic reordering routine. + +Cudd_Ref() Increases the reference count of a node, if it + is not saturated. + +Cudd_RemapOverApprox() Extracts a dense superset from a BDD with the + remapping underapproximation method. + +Cudd_RemapUnderApprox() Extracts a dense subset from a BDD with the + remapping underapproximation method. + +Cudd_RemoveHook() Removes a function from a hook. + +Cudd_ReorderingReporting() Returns 1 if reporting of reordering stats is + enabled. + +Cudd_ReorderingStatusZdd() Reports the status of automatic dynamic + reordering of ZDDs. + +Cudd_ReorderingStatus() Reports the status of automatic dynamic + reordering of BDDs and ADDs. + +Cudd_SetArcviolation() Sets the value of the arcviolation parameter + used in group sifting. + +Cudd_SetBackground() Sets the background constant of the manager. + +Cudd_SetEpsilon() Sets the epsilon parameter of the manager to + ep. + +Cudd_SetGroupcheck() Sets the parameter groupcheck of the manager to + gc. + +Cudd_SetLooseUpTo() Sets the looseUpTo parameter of the manager. + +Cudd_SetMaxCacheHard() Sets the maxCacheHard parameter of the manager. + +Cudd_SetMaxGrowthAlternate() Sets the maxGrowthAlt parameter of the manager. + +Cudd_SetMaxGrowth() Sets the maxGrowth parameter of the manager. + +Cudd_SetMaxLive() Sets the maximum allowed number of live nodes. + +Cudd_SetMaxMemory() Sets the maximum allowed memory. + +Cudd_SetMinHit() Sets the hit rate that causes resizinig of the + computed table. + +Cudd_SetNextReordering() Sets the threshold for the next dynamic + reordering. + +Cudd_SetNumberXovers() Sets the number of crossovers used by the + genetic algorithm for reordering. + +Cudd_SetPopulationSize() Sets the size of the population used by the + genetic algorithm for reordering. + +Cudd_SetRecomb() Sets the value of the recombination parameter + used in group sifting. + +Cudd_SetReorderingCycle() Sets the reordCycle parameter of the manager. + +Cudd_SetSiftMaxSwap() Sets the siftMaxSwap parameter of the manager. + +Cudd_SetSiftMaxVar() Sets the siftMaxVar parameter of the manager. + +Cudd_SetStderr() Sets the stderr of a manager. + +Cudd_SetStdout() Sets the stdout of a manager. + +Cudd_SetSymmviolation() Sets the value of the symmviolation parameter + used in group sifting. + +Cudd_SetTree() Sets the variable group tree of the manager. + +Cudd_SetVarMap() Registers a variable mapping with the manager. + +Cudd_SetZddTree() Sets the ZDD variable group tree of the + manager. + +Cudd_SharingSize() Counts the number of nodes in an array of DDs. + +Cudd_ShortestLength() Find the length of the shortest path(s) in a + DD. + +Cudd_ShortestPath() Finds a shortest path in a DD. + +Cudd_ShuffleHeap() Reorders variables according to given + permutation. + +Cudd_SolveEqn() Implements the solution of F(x,y) = 0. + +Cudd_SplitSet() Returns m minterms from a BDD. + +Cudd_Srandom() Initializer for the portable random number + generator. + +Cudd_StdPostReordHook() Sample hook function to call after reordering. + +Cudd_StdPreReordHook() Sample hook function to call before reordering. + +Cudd_SubsetCompress() Find a dense subset of BDD f. + +Cudd_SubsetHeavyBranch() Extracts a dense subset from a BDD with the + heavy branch heuristic. + +Cudd_SubsetShortPaths() Extracts a dense subset from a BDD with the + shortest paths heuristic. + +Cudd_SubsetWithMaskVars() Extracts a subset from a BDD. + +Cudd_SupersetCompress() Find a dense superset of BDD f. + +Cudd_SupersetHeavyBranch() Extracts a dense superset from a BDD with the + heavy branch heuristic. + +Cudd_SupersetShortPaths() Extracts a dense superset from a BDD with the + shortest paths heuristic. + +Cudd_SupportIndex() Finds the variables on which a DD depends. + +Cudd_SupportSize() Counts the variables on which a DD depends. + +Cudd_Support() Finds the variables on which a DD depends. + +Cudd_SymmProfile() Prints statistics on symmetric variables. + +Cudd_TurnOffCountDead() Causes the dead nodes not to be counted towards + triggering reordering. + +Cudd_TurnOnCountDead() Causes the dead nodes to be counted towards + triggering reordering. + +Cudd_UnderApprox() Extracts a dense subset from a BDD with + Shiple's underapproximation method. + +Cudd_VectorSupportIndex() Finds the variables on which a set of DDs + depends. + +Cudd_VectorSupportSize() Counts the variables on which a set of DDs + depends. + +Cudd_VectorSupport() Finds the variables on which a set of DDs + depends. + +Cudd_VerifySol() Checks the solution of F(x,y) = 0. + +Cudd_Xeqy() Generates a BDD for the function x==y. + +Cudd_Xgty() Generates a BDD for the function x > y. + +Cudd_addAgreement() f if f==g; background if f!=g. + +Cudd_addApply() Applies op to the corresponding discriminants + of f and g. + +Cudd_addBddInterval() Converts an ADD to a BDD. + +Cudd_addBddIthBit() Converts an ADD to a BDD by extracting the i-th + bit from the leaves. + +Cudd_addBddPattern() Converts an ADD to a BDD. + +Cudd_addBddStrictThreshold() Converts an ADD to a BDD. + +Cudd_addBddThreshold() Converts an ADD to a BDD. + +Cudd_addCmpl() Computes the complement of an ADD a la C + language. + +Cudd_addCompose() Substitutes g for x_v in the ADD for f. + +Cudd_addComputeCube() Computes the cube of an array of ADD variables. + +Cudd_addConstrain() Computes f constrain c for ADDs. + +Cudd_addConst() Returns the ADD for constant c. + +Cudd_addDiff() Returns plusinfinity if f=g; returns min(f,g) + if f!=g. + +Cudd_addDivide() Integer and floating point division. + +Cudd_addEvalConst() Checks whether ADD g is constant whenever ADD f + is 1. + +Cudd_addExistAbstract() Existentially Abstracts all the variables in + cube from f. + +Cudd_addFindMax() Finds the maximum discriminant of f. + +Cudd_addFindMin() Finds the minimum discriminant of f. + +Cudd_addGeneralVectorCompose() Composes an ADD with a vector of ADDs. + +Cudd_addHamming() Computes the Hamming distance ADD. + +Cudd_addHarwell() Reads in a matrix in the format of the Harwell- + Boeing benchmark suite. + +Cudd_addIteConstant() Implements ITEconstant for ADDs. + +Cudd_addIte() Implements ITE(f,g,h). + +Cudd_addIthBit() Extracts the i-th bit from an ADD. + +Cudd_addIthVar() Returns the ADD variable with index i. + +Cudd_addLeq() Determines whether f is less than or equal to + g. + +Cudd_addLog() Natural logarithm of an ADD. + +Cudd_addMatrixMultiply() Calculates the product of two matrices + represented as ADDs. + +Cudd_addMaximum() Integer and floating point max. + +Cudd_addMinimum() Integer and floating point min. + +Cudd_addMinus() Integer and floating point subtraction. + +Cudd_addMonadicApply() Applies op to the discriminants of f. + +Cudd_addNand() NAND of two 0-1 ADDs. + +Cudd_addNegate() Computes the additive inverse of an ADD. + +Cudd_addNewVarAtLevel() Returns a new ADD variable at a specified + level. + +Cudd_addNewVar() Returns a new ADD variable. + +Cudd_addNonSimCompose() Composes an ADD with a vector of 0-1 ADDs. + +Cudd_addNor() NOR of two 0-1 ADDs. + +Cudd_addOneZeroMaximum() Returns 1 if f > g and 0 otherwise. + +Cudd_addOrAbstract() Disjunctively abstracts all the variables in + cube from the 0-1 ADD f. + +Cudd_addOr() Disjunction of two 0-1 ADDs. + +Cudd_addOuterSum() Takes the minimum of a matrix and the outer sum + of two vectors. + +Cudd_addPermute() Permutes the variables of an ADD. + +Cudd_addPlus() Integer and floating point addition. + +Cudd_addRead() Reads in a sparse matrix. + +Cudd_addResidue() Builds an ADD for the residue modulo m of an n- + bit number. + +Cudd_addRestrict() ADD restrict according to Coudert and Madre's + algorithm (ICCAD90). + +Cudd_addRoundOff() Rounds off the discriminants of an ADD. + +Cudd_addScalarInverse() Computes the scalar inverse of an ADD. + +Cudd_addSetNZ() This operator sets f to the value of g wherever + g != 0. + +Cudd_addSwapVariables() Swaps two sets of variables of the same size (x + and y) in the ADD f. + +Cudd_addThreshold() f if f>=g; 0 if f 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]. + + Side Effects: None + +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 +) + This function generates a BDD for the function d(x,y) > 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]. + + Side Effects: None + +void +Cudd_EnableGarbageCollection( + DdManager * dd +) + Enables garbage collection. Garbage collection is initially enabled. + Therefore it is necessary to call this function only if garbage collection + has been explicitly disabled. + + Side Effects: None + +int +Cudd_EnableReorderingReporting( + DdManager * dd +) + Enables reporting of reordering stats. Returns 1 if successful; 0 otherwise. + + Side Effects: Installs functions in the pre-reordering and post-reordering + hooks. + +int +Cudd_EpdCountMinterm( + DdManager * manager, + DdNode * node, + int nvars, + EpDouble * epd +) + 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. + + Side Effects: None + +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 +) + 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 + pr is positive the first failure is reported to the standard + output. + + Side Effects: None + +int +Cudd_EquivDC( + DdManager * dd, + DdNode * F, + DdNode * G, + DdNode * D +) + 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. + + Side Effects: None + +int +Cudd_EstimateCofactorSimple( + DdNode * node, + int i +) + 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. + + Side Effects: None + +int +Cudd_EstimateCofactor( + DdManager * dd, manager + DdNode * f, function + int i, index of variable + int phase 1: positive; 0: negative +) + 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. + + Side Effects: None + +DdNode * +Cudd_Eval( + DdManager * dd, + DdNode * f, + int * inputs +) + 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. + + Side Effects: None + +double +Cudd_ExpectedUsedSlots( + DdManager * dd +) + 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. + + Side Effects: None + +DdNode * +Cudd_FindEssential( + DdManager * dd, + DdNode * f +) + 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. + + Side Effects: None + +DdTlcInfo * +Cudd_FindTwoLiteralClauses( + DdManager * dd, + DdNode * f +) + 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. + + Side Effects: None + +DdGen * +Cudd_FirstCube( + DdManager * dd, + DdNode * f, + int ** cube, + CUDD_VALUE_TYPE * value +) + 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. 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. + 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. + + Side Effects: The first cube and its value are returned as side effects. + +DdGen * +Cudd_FirstNode( + DdManager * dd, + DdNode * f, + DdNode ** node +) + 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. + + Side Effects: The first node is returned as a side effect. + +DdGen * +Cudd_FirstPrime( + DdManager * dd, + DdNode * l, + DdNode * u, + int ** cube +) + 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. 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. 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. This iterator can only be + used on BDDs. + + Side Effects: The first cube is returned as side effect. + +void +Cudd_FreeTree( + DdManager * dd +) + Frees the variable group tree of the manager. + + Side Effects: None + +void +Cudd_FreeZddTree( + DdManager * dd +) + Frees the variable group tree of the manager. + + Side Effects: None + +int +Cudd_GarbageCollectionEnabled( + DdManager * dd +) + Returns 1 if garbage collection is enabled; 0 otherwise. + + Side Effects: None + +int +Cudd_GenFree( + DdGen * gen +) + Frees a CUDD generator. Always returns 0, so that it can be used in mis-like + foreach constructs. + + Side Effects: None + +DdNode * +Cudd_Increasing( + DdManager * dd, + DdNode * f, + int i +) + 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. + + Side Effects: None + +DdNode * +Cudd_IndicesToCube( + DdManager * dd, + int * array, + int n +) + Builds a cube of BDD variables from an array of indices. Returns a pointer + to the result if successful; NULL otherwise. + + Side Effects: None + +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 +) + 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]. + + Side Effects: None + +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 +) + 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. + + Side Effects: None + +int +Cudd_IsGenEmpty( + DdGen * gen +) + Queries the status of a generator. Returns 1 if the generator is empty or + NULL; 0 otherswise. + + Side Effects: None + +int +Cudd_IsInHook( + DdManager * dd, + DD_HFP f, + Cudd_HookType where +) + 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. + + Side Effects: None + +int +Cudd_IsNonConstant( + DdNode * f +) + 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. + + Side Effects: None + +void +Cudd_IterDerefBdd( + DdManager * table, + DdNode * n +) + 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. + + Side Effects: None + +DdNode * +Cudd_LargestCube( + DdManager * manager, + DdNode * f, + int * length +) + 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. + + Side Effects: The number of literals of the cube is returned in length. + +DdNode * +Cudd_MakeBddFromZddCover( + DdManager * dd, + DdNode * node +) + Converts a ZDD cover to a BDD graph. If successful, it returns a BDD node, + otherwise it returns NULL. + + +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 +) + 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. + + Side Effects: The variable tree is changed. + +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 +) + 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. + + Side Effects: The ZDD variable tree is changed. + +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 +) + 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. + + Side Effects: None + +DdApaNumber +Cudd_NewApaNumber( + int digits +) + Allocates memory for an arbitrary precision integer. Returns a pointer to + the allocated memory if successful; NULL otherwise. + + Side Effects: None + +int +Cudd_NextCube( + DdGen * gen, + int ** cube, + CUDD_VALUE_TYPE * value +) + Generates the next cube of a decision diagram onset, using generator gen. + Returns 0 if the enumeration is completed; 1 otherwise. + + Side Effects: The cube and its value are returned as side effects. The + generator is modified. + +int +Cudd_NextNode( + DdGen * gen, + DdNode ** node +) + Finds the node of a decision diagram, using generator gen. Returns 0 if the + enumeration is completed; 1 otherwise. + + Side Effects: The next node is returned as a side effect. + +int +Cudd_NextPrime( + DdGen * gen, + int ** cube +) + Generates the next cube of a Boolean function, using generator gen. Returns + 0 if the enumeration is completed; 1 otherwise. + + Side Effects: The cube and is returned as side effects. The generator is + modified. + +unsigned int +Cudd_NodeReadIndex( + DdNode * node +) + Returns the index of the node. The node pointer can be either regular or + complemented. + + Side Effects: None + +void +Cudd_OutOfMem( + long size size of the allocation that failed +) + 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. + + Side Effects: None + +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 +) + 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. + + Side Effects: None + +unsigned int +Cudd_Prime( + unsigned int p +) + Returns the next prime >= p. + + Side Effects: None + +int +Cudd_PrintDebug( + DdManager * dd, + DdNode * f, + int n, + int pr +) + 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 > 0. Specifically: pr = 0 : prints nothing pr = 1 : + prints counts of nodes and minterms pr = 2 : prints counts + disjoint + sum of product pr = 3 : prints counts + list of nodes pr > 3 : + prints counts + disjoint sum of product + list of nodes For the + purpose of counting the number of minterms, the function is supposed to + depend on n variables. Returns 1 if successful; 0 otherwise. + + Side Effects: None + +int +Cudd_PrintInfo( + DdManager * dd, + FILE * fp +) + Prints out statistics and settings for a CUDD manager. Returns 1 if + successful; 0 otherwise. + + Side Effects: None + +int +Cudd_PrintLinear( + DdManager * table +) + Prints the linear transform matrix. Returns 1 in case of success; 0 + otherwise. + + Side Effects: none + +int +Cudd_PrintMinterm( + DdManager * manager, + DdNode * node +) + 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. + + Side Effects: None + +int +Cudd_PrintTwoLiteralClauses( + DdManager * dd, + DdNode * f, + char ** names, + FILE * fp +) + 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. + + Side Effects: None + +void +Cudd_PrintVersion( + FILE * fp +) + Prints the package version number. + + Side Effects: None + +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 +) + 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: When extracting representatives from an equivalence + relation, Cudd_CProjection has the advantage of nor requiring the auxiliary + variables. 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). + + Side Effects: If called with z == NULL, will create new variables in the + manager. + +void +Cudd_Quit( + DdManager * unique +) + 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.) + + Side Effects: None + +long +Cudd_Random( + +) + 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. + + Side Effects: None + +int +Cudd_ReadArcviolation( + DdManager * dd +) + Returns the current value of the arcviolation parameter. This parameter is + used in group sifting to decide how many arcs into y not coming + from x 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. + + Side Effects: None + +DdNode * +Cudd_ReadBackground( + DdManager * dd +) + Reads the background constant of the manager. + + Side Effects: None + +double +Cudd_ReadCacheHits( + DdManager * dd +) + Returns the number of cache hits. + + Side Effects: None + +double +Cudd_ReadCacheLookUps( + DdManager * dd +) + Returns the number of cache look-ups. + + Side Effects: None + +unsigned int +Cudd_ReadCacheSlots( + DdManager * dd +) + Reads the number of slots in the cache. + + Side Effects: None + +double +Cudd_ReadCacheUsedSlots( + DdManager * dd +) + 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. + + Side Effects: None + +unsigned int +Cudd_ReadDead( + DdManager * dd +) + Returns the number of dead nodes in the unique table. + + Side Effects: None + +CUDD_VALUE_TYPE +Cudd_ReadEpsilon( + DdManager * dd +) + Reads the epsilon parameter of the manager. The epsilon parameter control + the comparison between floating point numbers. + + Side Effects: None + +Cudd_ErrorType +Cudd_ReadErrorCode( + DdManager * dd +) + Returns the code of the last error. The error codes are defined in cudd.h. + + Side Effects: None + +long +Cudd_ReadGarbageCollectionTime( + DdManager * dd +) + Returns the number of milliseconds spent doing garbage collection since the + manager was initialized. + + Side Effects: None + +int +Cudd_ReadGarbageCollections( + DdManager * dd +) + 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. + + Side Effects: None + +Cudd_AggregationType +Cudd_ReadGroupcheck( + DdManager * dd +) + Reads the groupcheck parameter of the manager. The groupcheck parameter + determines the aggregation criterion in group sifting. + + Side Effects: None + +int +Cudd_ReadInvPermZdd( + DdManager * dd, + int i +) + 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. + + Side Effects: None + +int +Cudd_ReadInvPerm( + DdManager * dd, + int i +) + 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. + + Side Effects: None + +int +Cudd_ReadIthClause( + DdTlcInfo * tlc, + int i, + DdHalfWord * var1, + DdHalfWord * var2, + int * phase1, + int * phase2 +) + 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. + + Side Effects: the four components of a clause are returned as side effects. + +unsigned int +Cudd_ReadKeys( + DdManager * dd +) + Returns the total number of nodes currently in the unique table, including + the dead nodes. + + Side Effects: None + +int +Cudd_ReadLinear( + DdManager * table, CUDD manager + int x, row index + int y column index +) + Reads an entry of the linear transform matrix. + + Side Effects: none + +DdNode * +Cudd_ReadLogicZero( + DdManager * dd +) + 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. + + Side Effects: None + +unsigned int +Cudd_ReadLooseUpTo( + DdManager * dd +) + Reads the looseUpTo parameter of the manager. + + Side Effects: None + +unsigned int +Cudd_ReadMaxCacheHard( + DdManager * dd +) + Reads the maxCacheHard parameter of the manager. + + Side Effects: None + +unsigned int +Cudd_ReadMaxCache( + DdManager * dd +) + Returns the soft limit for the cache size. The soft limit + + Side Effects: None + +double +Cudd_ReadMaxGrowthAlternate( + DdManager * dd +) + 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. + + Side Effects: None + +double +Cudd_ReadMaxGrowth( + DdManager * dd +) + 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. + + Side Effects: None + +unsigned int +Cudd_ReadMaxLive( + DdManager * dd +) + Reads the maximum allowed number of live nodes. When this number is + exceeded, the package returns NULL. + + Side Effects: none + +unsigned long +Cudd_ReadMaxMemory( + DdManager * dd +) + Reads the maximum allowed memory. When this number is exceeded, the package + returns NULL. + + Side Effects: none + +unsigned long +Cudd_ReadMemoryInUse( + DdManager * dd +) + Returns the memory in use by the manager measured in bytes. + + Side Effects: None + +unsigned int +Cudd_ReadMinDead( + DdManager * dd +) + 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. + + Side Effects: None + +unsigned int +Cudd_ReadMinHit( + DdManager * dd +) + Reads the hit rate that causes resizinig of the computed table. + + Side Effects: None + +DdNode * +Cudd_ReadMinusInfinity( + DdManager * dd +) + Reads the minus-infinity constant from the manager. + + Side Effects: None + +unsigned int +Cudd_ReadNextReordering( + DdManager * dd +) + 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. + + Side Effects: None + +long +Cudd_ReadNodeCount( + DdManager * dd +) + 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. + + Side Effects: None + +double +Cudd_ReadNodesDropped( + DdManager * dd +) + 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. + + Side Effects: None + +double +Cudd_ReadNodesFreed( + DdManager * dd +) + 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. + + Side Effects: None + +int +Cudd_ReadNumberXovers( + DdManager * dd +) + 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. + + Side Effects: None + +DdNode * +Cudd_ReadOne( + DdManager * dd +) + Returns the one constant of the manager. The one constant is common to ADDs + and BDDs. + + Side Effects: None + +int +Cudd_ReadPeakLiveNodeCount( + DdManager * dd +) + 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. + + Side Effects: None + +long +Cudd_ReadPeakNodeCount( + DdManager * dd +) + 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. + + Side Effects: None + +int +Cudd_ReadPermZdd( + DdManager * dd, + int i +) + 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. + + Side Effects: None + +int +Cudd_ReadPerm( + DdManager * dd, + int i +) + 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. + + Side Effects: None + +DdNode * +Cudd_ReadPlusInfinity( + DdManager * dd +) + Reads the plus-infinity constant from the manager. + + Side Effects: None + +int +Cudd_ReadPopulationSize( + DdManager * dd +) + 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. + + Side Effects: None + +int +Cudd_ReadRecomb( + DdManager * dd +) + 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. + + Side Effects: None + +double +Cudd_ReadRecursiveCalls( + DdManager * dd +) + Returns the number of recursive calls if the package is compiled with + DD_COUNT defined. + + Side Effects: None + +int +Cudd_ReadReorderingCycle( + DdManager * dd +) + Reads the reordCycle parameter of the manager. This parameter determines how + often the alternate threshold on maximum growth is used in reordering. + + Side Effects: None + +long +Cudd_ReadReorderingTime( + DdManager * dd +) + Returns the number of milliseconds spent reordering variables since the + manager was initialized. The time spent in collecting garbage before + reordering is included. + + Side Effects: None + +int +Cudd_ReadReorderings( + DdManager * dd +) + 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. + + Side Effects: None + +int +Cudd_ReadSiftMaxSwap( + DdManager * dd +) + 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. + + Side Effects: None + +int +Cudd_ReadSiftMaxVar( + DdManager * dd +) + Reads the siftMaxVar parameter of the manager. This parameter gives the + maximum number of variables that will be sifted for each invocation of + sifting. + + Side Effects: None + +int +Cudd_ReadSize( + DdManager * dd +) + Returns the number of BDD variables in existance. + + Side Effects: None + +unsigned int +Cudd_ReadSlots( + DdManager * dd +) + Returns the total number of slots of the unique table. This number ismainly + for diagnostic purposes. + + Side Effects: None + +FILE * +Cudd_ReadStderr( + DdManager * dd +) + 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. + + Side Effects: None + +FILE * +Cudd_ReadStdout( + DdManager * dd +) + 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. + + Side Effects: None + +double +Cudd_ReadSwapSteps( + DdManager * dd +) + Reads the number of elementary reordering steps. + + Side Effects: none + +int +Cudd_ReadSymmviolation( + DdManager * dd +) + Returns the current value of the symmviolation parameter. This parameter is + used in group sifting to decide how many violations to the symmetry + conditions f10 = f01 or f11 = f00 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. + + Side Effects: None + +MtrNode * +Cudd_ReadTree( + DdManager * dd +) + Returns the variable group tree of the manager. + + Side Effects: None + +double +Cudd_ReadUniqueLinks( + DdManager * dd +) + 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. + + Side Effects: None + +double +Cudd_ReadUniqueLookUps( + DdManager * dd +) + 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. + + Side Effects: None + +double +Cudd_ReadUsedSlots( + DdManager * dd +) + 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. + + Side Effects: None + +DdNode * +Cudd_ReadVars( + DdManager * dd, + int i +) + 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. + + Side Effects: None + +DdNode * +Cudd_ReadZddOne( + DdManager * dd, + int i +) + 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 i. + + Side Effects: None + +int +Cudd_ReadZddSize( + DdManager * dd +) + Returns the number of ZDD variables in existance. + + Side Effects: None + +MtrNode * +Cudd_ReadZddTree( + DdManager * dd +) + Returns the variable group tree of the manager. + + Side Effects: None + +DdNode * +Cudd_ReadZero( + DdManager * dd +) + 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. + + Side Effects: None + +void +Cudd_RecursiveDerefZdd( + DdManager * table, + DdNode * n +) + 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. + + Side Effects: None + +void +Cudd_RecursiveDeref( + DdManager * table, + DdNode * n +) + 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. + + Side Effects: None + +int +Cudd_ReduceHeap( + DdManager * table, DD manager + Cudd_ReorderingTy heuristic, method used for reordering + int minsize bound below which no reordering occurs +) + Main dynamic reordering routine. Calls one of the possible reordering + procedures: Swapping Sifting Symmetric Sifting Group + Sifting Window Permutation Simulated Annealing Genetic Algorithm + Dynamic Programming (exact) For sifting, symmetric sifting, group + sifting, and window permutation it is possible to request reordering to + convergence. 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. + + Side Effects: Changes the variable order for all diagrams and clears the + cache. + +void +Cudd_Ref( + DdNode * n +) + Increases the reference count of a node, if it is not saturated. + + Side Effects: None + +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 +) + 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. + + Side Effects: None + +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 +) + 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. + + Side Effects: None + +int +Cudd_RemoveHook( + DdManager * dd, + DD_HFP f, + Cudd_HookType where +) + 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. + + Side Effects: None + +int +Cudd_ReorderingReporting( + DdManager * dd +) + Returns 1 if reporting of reordering stats is enabled; 0 otherwise. + + Side Effects: none + +int +Cudd_ReorderingStatusZdd( + DdManager * unique, + Cudd_ReorderingTy method +) + 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. + + Side Effects: Parameter method is set to the ZDD reordering method currently + selected. + +int +Cudd_ReorderingStatus( + DdManager * unique, + Cudd_ReorderingTy method +) + 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. + + Side Effects: Parameter method is set to the reordering method currently + selected. + +void +Cudd_SetArcviolation( + DdManager * dd, + int arcviolation +) + Sets the value of the arcviolation parameter. This parameter is used in + group sifting to decide how many arcs into y not coming from + x 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. + + Side Effects: None + +void +Cudd_SetBackground( + DdManager * dd, + DdNode * bck +) + Sets the background constant of the manager. It assumes that the DdNode + pointer bck is already referenced. + + Side Effects: None + +void +Cudd_SetEpsilon( + DdManager * dd, + CUDD_VALUE_TYPE ep +) + Sets the epsilon parameter of the manager to ep. The epsilon parameter + control the comparison between floating point numbers. + + Side Effects: None + +void +Cudd_SetGroupcheck( + DdManager * dd, + Cudd_AggregationT gc +) + Sets the parameter groupcheck of the manager to gc. The groupcheck parameter + determines the aggregation criterion in group sifting. + + Side Effects: None + +void +Cudd_SetLooseUpTo( + DdManager * dd, + unsigned int lut +) + 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. + + Side Effects: None + +void +Cudd_SetMaxCacheHard( + DdManager * dd, + unsigned int mc +) + 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. + + Side Effects: None + +void +Cudd_SetMaxGrowthAlternate( + DdManager * dd, + double mg +) + 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. + + Side Effects: None + +void +Cudd_SetMaxGrowth( + DdManager * dd, + double mg +) + 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. + + Side Effects: None + +void +Cudd_SetMaxLive( + DdManager * dd, + unsigned int maxLive +) + Sets the maximum allowed number of live nodes. When this number is exceeded, + the package returns NULL. + + Side Effects: none + +void +Cudd_SetMaxMemory( + DdManager * dd, + unsigned long maxMemory +) + Sets the maximum allowed memory. When this number is exceeded, the package + returns NULL. + + Side Effects: none + +void +Cudd_SetMinHit( + DdManager * dd, + unsigned int hr +) + 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. + + Side Effects: None + +void +Cudd_SetNextReordering( + DdManager * dd, + unsigned int next +) + 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. + + Side Effects: None + +void +Cudd_SetNumberXovers( + DdManager * dd, + int numberXovers +) + 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. + + Side Effects: None + +void +Cudd_SetPopulationSize( + DdManager * dd, + int populationSize +) + 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. + + Side Effects: Changes the manager. + +void +Cudd_SetRecomb( + DdManager * dd, + int recomb +) + 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. + + Side Effects: Changes the manager. + +void +Cudd_SetReorderingCycle( + DdManager * dd, + int cycle +) + Sets the reordCycle parameter of the manager. This parameter determines how + often the alternate threshold on maximum growth is used in reordering. + + Side Effects: None + +void +Cudd_SetSiftMaxSwap( + DdManager * dd, + int sms +) + 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. + + Side Effects: None + +void +Cudd_SetSiftMaxVar( + DdManager * dd, + int smv +) + Sets the siftMaxVar parameter of the manager. This parameter gives the + maximum number of variables that will be sifted for each invocation of + sifting. + + Side Effects: None + +void +Cudd_SetStderr( + DdManager * dd, + FILE * fp +) + Sets the stderr of a manager. + + Side Effects: None + +void +Cudd_SetStdout( + DdManager * dd, + FILE * fp +) + Sets the stdout of a manager. + + Side Effects: None + +void +Cudd_SetSymmviolation( + DdManager * dd, + int symmviolation +) + Sets the value of the symmviolation parameter. This parameter is used in + group sifting to decide how many violations to the symmetry conditions + f10 = f01 or f11 = f00 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. + + Side Effects: Changes the manager. + +void +Cudd_SetTree( + DdManager * dd, + MtrNode * tree +) + Sets the variable group tree of the manager. + + Side Effects: None + +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 +) + 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. + + Side Effects: Modifies the manager. May clear the cache. + +void +Cudd_SetZddTree( + DdManager * dd, + MtrNode * tree +) + Sets the ZDD variable group tree of the manager. + + Side Effects: None + +int +Cudd_SharingSize( + DdNode ** nodeArray, + int n +) + Counts the number of nodes in an array of DDs. Shared nodes are counted only + once. Returns the total number of nodes. + + Side Effects: None + +int +Cudd_ShortestLength( + DdManager * manager, + DdNode * f, + int * weight +) + 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. + + Side Effects: None + +DdNode * +Cudd_ShortestPath( + DdManager * manager, + DdNode * f, + int * weight, + int * support, + int * length +) + 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. + + Side Effects: 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. + +int +Cudd_ShuffleHeap( + DdManager * table, DD manager + int * permutation required variable permutation +) + 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. + + Side Effects: Changes the variable order for all diagrams and clears the + cache. + +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 +) + 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. + + Side Effects: The solution is returned in G; the indices of the y variables + are returned in yIndex. + +DdNode * +Cudd_SplitSet( + DdManager * manager, + DdNode * S, + DdNode ** xVars, + int n, + double m +) + Returns m minterms from a BDD whose support has n + variables at most. The procedure tries to create as few extra nodes as + possible. The function represented by S depends on at most + n of the variables in xVars. Returns a BDD with + m minterms of the on-set of S if successful; NULL otherwise. + + Side Effects: None + +void +Cudd_Srandom( + long seed +) + 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. + + Side Effects: None + +int +Cudd_StdPostReordHook( + DdManager * dd, + const char * str, + void * data +) + Sample hook function to call after reordering. Prints on the manager's + stdout final size and reordering time. Returns 1 if successful; 0 otherwise. + + Side Effects: None + +int +Cudd_StdPreReordHook( + DdManager * dd, + const char * str, + void * data +) + Sample hook function to call before reordering. Prints on the manager's + stdout reordering method and initial size. Returns 1 if successful; 0 + otherwise. + + Side Effects: None + +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 +) + Finds a dense subset of BDD f. 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. + + Side Effects: None + +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 +) + 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. + + Side Effects: None + +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 +) + 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. + + Side Effects: None + +DdNode * +Cudd_SubsetWithMaskVars( + DdManager * dd, manager + DdNode * f, function from which to pick a cube + DdNode ** vars, array of variables + int nvars, size of vars + DdNode ** maskVars, array of variables + int mvars size of maskVars +) + 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. + + Side Effects: None + +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 +) + Finds a dense superset of BDD f. 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. + + Side Effects: None + +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 +) + 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. + + Side Effects: None + +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 +) + 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. + + Side Effects: None + +int * +Cudd_SupportIndex( + DdManager * dd, manager + DdNode * f DD whose support is sought +) + 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. + + Side Effects: None + +int +Cudd_SupportSize( + DdManager * dd, manager + DdNode * f DD whose support size is sought +) + Counts the variables on which a DD depends. Returns the number of the + variables if successful; CUDD_OUT_OF_MEM otherwise. + + Side Effects: None + +DdNode * +Cudd_Support( + DdManager * dd, manager + DdNode * f DD whose support is sought +) + Finds the variables on which a DD depends. Returns a BDD consisting of the + product of the variables if successful; NULL otherwise. + + Side Effects: None + +void +Cudd_SymmProfile( + DdManager * table, + int lower, + int upper +) + Prints statistics on symmetric variables. + + Side Effects: None + +void +Cudd_TurnOffCountDead( + DdManager * dd +) + 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. + + Side Effects: Changes the manager. + +void +Cudd_TurnOnCountDead( + DdManager * dd +) + Causes the dead nodes to be counted towards triggering reordering. This + causes more frequent reorderings. By default dead nodes are not counted. + + Side Effects: Changes the manager. + +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 +) + 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. + + Side Effects: None + +int * +Cudd_VectorSupportIndex( + DdManager * dd, manager + DdNode ** F, array of DDs whose support is sought + int n size of the array +) + 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. + + Side Effects: None + +int +Cudd_VectorSupportSize( + DdManager * dd, manager + DdNode ** F, array of DDs whose support is sought + int n size of the array +) + 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. + + Side Effects: None + +DdNode * +Cudd_VectorSupport( + DdManager * dd, manager + DdNode ** F, array of DDs whose support is sought + int n size of the array +) + 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. + + Side Effects: None + +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 +) + 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. + + Side Effects: Frees the memory pointed by yIndex. + +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 +) + 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]. + + Side Effects: None + +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 +) + 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]. + Argument z is not used by Cudd_Xgty: it is included to make it call- + compatible to Cudd_Dxygtdxz and Cudd_Dxygtdyz. + + Side Effects: None + +DdNode * +Cudd_addAgreement( + DdManager * dd, + DdNode ** f, + DdNode ** g +) + Returns NULL if not a terminal case; f op g otherwise, where f op g is f if + f==g; background if f!=g. + + Side Effects: None + +DdNode * +Cudd_addApply( + DdManager * dd, + DD_AOP op, + DdNode * f, + DdNode * g +) + Applies op to the corresponding discriminants of f and g. Returns a pointer + to the result if succssful; NULL otherwise. + + Side Effects: None + +DdNode * +Cudd_addBddInterval( + DdManager * dd, + DdNode * f, + CUDD_VALUE_TYPE lower, + CUDD_VALUE_TYPE upper +) + 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. + + Side Effects: None + +DdNode * +Cudd_addBddIthBit( + DdManager * dd, + DdNode * f, + int bit +) + 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. + + Side Effects: None + +DdNode * +Cudd_addBddPattern( + DdManager * dd, + DdNode * f +) + 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. + + Side Effects: None + +DdNode * +Cudd_addBddStrictThreshold( + DdManager * dd, + DdNode * f, + CUDD_VALUE_TYPE value +) + 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. + + Side Effects: None + +DdNode * +Cudd_addBddThreshold( + DdManager * dd, + DdNode * f, + CUDD_VALUE_TYPE value +) + 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. + + Side Effects: None + +DdNode * +Cudd_addCmpl( + DdManager * dd, + DdNode * f +) + 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. + + Side Effects: None + +DdNode * +Cudd_addCompose( + DdManager * dd, + DdNode * f, + DdNode * g, + int v +) + 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. + + Side Effects: None + +DdNode * +Cudd_addComputeCube( + DdManager * dd, + DdNode ** vars, + int * phase, + int n +) + 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. + + Side Effects: none + +DdNode * +Cudd_addConstrain( + DdManager * dd, + DdNode * f, + DdNode * c +) + Computes f constrain c (f @ c), for f an ADD and c a 0-1 ADD. List of + special cases: F @ 0 = 0 F @ 1 = F 0 @ c = 0 1 @ c + = 1 F @ F = 1 Returns a pointer to the result if successful; NULL + otherwise. + + Side Effects: None + +DdNode * +Cudd_addConst( + DdManager * dd, + CUDD_VALUE_TYPE c +) + 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. + + Side Effects: None + +DdNode * +Cudd_addDiff( + DdManager * dd, + DdNode ** f, + DdNode ** g +) + 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. + + Side Effects: None + +DdNode * +Cudd_addDivide( + DdManager * dd, + DdNode ** f, + DdNode ** g +) + Integer and floating point division. Returns NULL if not a terminal case; f + / g otherwise. + + Side Effects: None + +DdNode * +Cudd_addEvalConst( + DdManager * dd, + DdNode * f, + DdNode * g +) + 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. + + Side Effects: None + +DdNode * +Cudd_addExistAbstract( + DdManager * manager, + DdNode * f, + DdNode * cube +) + Abstracts all the variables in cube from f by summing over all possible + values taken by the variables. Returns the abstracted ADD. + + Side Effects: None + +DdNode * +Cudd_addFindMax( + DdManager * dd, + DdNode * f +) + Returns a pointer to a constant ADD. + + Side Effects: None + +DdNode * +Cudd_addFindMin( + DdManager * dd, + DdNode * f +) + Returns a pointer to a constant ADD. + + Side Effects: None + +DdNode * +Cudd_addGeneralVectorCompose( + DdManager * dd, + DdNode * f, + DdNode ** vectorOn, + DdNode ** vectorOff +) + 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. + + Side Effects: None + +DdNode * +Cudd_addHamming( + DdManager * dd, + DdNode ** xVars, + DdNode ** yVars, + int nVars +) + 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. + + Side Effects: None + +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 +) + Reads in a matrix in the format of the Harwell-Boeing benchmark suite. The + variables are ordered as follows: x[0] y[0] x[1] y[1] ... + 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. + + Side Effects: None + +DdNode * +Cudd_addIteConstant( + DdManager * dd, + DdNode * f, + DdNode * g, + DdNode * h +) + 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. + + Side Effects: None + +DdNode * +Cudd_addIte( + DdManager * dd, + DdNode * f, + DdNode * g, + DdNode * h +) + 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. + + Side Effects: None + +DdNode * +Cudd_addIthBit( + DdManager * dd, + DdNode * f, + int bit +) + 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. + + Side Effects: None + +DdNode * +Cudd_addIthVar( + DdManager * dd, + int i +) + 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. + + Side Effects: None + +int +Cudd_addLeq( + DdManager * dd, + DdNode * f, + DdNode * g +) + 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. + + Side Effects: None + +DdNode * +Cudd_addLog( + DdManager * dd, + DdNode * f +) + Natural logarithm of an ADDs. Returns NULL if not a terminal case; log(f) + otherwise. The discriminants of f must be positive double's. + + Side Effects: None + +DdNode * +Cudd_addMatrixMultiply( + DdManager * dd, + DdNode * A, + DdNode * B, + DdNode ** z, + int nz +) + 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. + + Side Effects: None + +DdNode * +Cudd_addMaximum( + DdManager * dd, + DdNode ** f, + DdNode ** g +) + Integer and floating point max for Cudd_addApply. Returns NULL if not a + terminal case; max(f,g) otherwise. + + Side Effects: None + +DdNode * +Cudd_addMinimum( + DdManager * dd, + DdNode ** f, + DdNode ** g +) + Integer and floating point min for Cudd_addApply. Returns NULL if not a + terminal case; min(f,g) otherwise. + + Side Effects: None + +DdNode * +Cudd_addMinus( + DdManager * dd, + DdNode ** f, + DdNode ** g +) + Integer and floating point subtraction. Returns NULL if not a terminal case; + f - g otherwise. + + Side Effects: None + +DdNode * +Cudd_addMonadicApply( + DdManager * dd, + DD_MAOP op, + DdNode * f +) + Applies op to the discriminants of f. Returns a pointer to the result if + succssful; NULL otherwise. + + Side Effects: None + +DdNode * +Cudd_addNand( + DdManager * dd, + DdNode ** f, + DdNode ** g +) + NAND of two 0-1 ADDs. Returns NULL if not a terminal case; f NAND g + otherwise. + + Side Effects: None + +DdNode * +Cudd_addNegate( + DdManager * dd, + DdNode * f +) + Computes the additive inverse of an ADD. Returns a pointer to the result if + successful; NULL otherwise. + + Side Effects: None + +DdNode * +Cudd_addNewVarAtLevel( + DdManager * dd, + int level +) + 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. + + Side Effects: None + +DdNode * +Cudd_addNewVar( + DdManager * dd +) + 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. + + Side Effects: None + +DdNode * +Cudd_addNonSimCompose( + DdManager * dd, + DdNode * f, + DdNode ** vector +) + 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. + + Side Effects: None + +DdNode * +Cudd_addNor( + DdManager * dd, + DdNode ** f, + DdNode ** g +) + NOR of two 0-1 ADDs. Returns NULL if not a terminal case; f NOR g otherwise. + + Side Effects: None + +DdNode * +Cudd_addOneZeroMaximum( + DdManager * dd, + DdNode ** f, + DdNode ** g +) + Returns 1 if f > g and 0 otherwise. Used in conjunction with + Cudd_addApply. Returns NULL if not a terminal case. + + Side Effects: None + +DdNode * +Cudd_addOrAbstract( + DdManager * manager, + DdNode * f, + DdNode * cube +) + 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. + + Side Effects: None + +DdNode * +Cudd_addOr( + DdManager * dd, + DdNode ** f, + DdNode ** g +) + Disjunction of two 0-1 ADDs. Returns NULL if not a terminal case; f OR g + otherwise. + + Side Effects: None + +DdNode * +Cudd_addOuterSum( + DdManager * dd, + DdNode * M, + DdNode * r, + DdNode * c +) + 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. + + Side Effects: None + +DdNode * +Cudd_addPermute( + DdManager * manager, + DdNode * node, + int * permut +) + 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. + + Side Effects: None + +DdNode * +Cudd_addPlus( + DdManager * dd, + DdNode ** f, + DdNode ** g +) + Integer and floating point addition. Returns NULL if not a terminal case; + f+g otherwise. + + Side Effects: None + +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 +) + 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. 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. 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. 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. + + Side Effects: 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. + +DdNode * +Cudd_addResidue( + DdManager * dd, manager + int n, number of bits + int m, modulus + int options, options + int top index of top variable +) + 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. + + Side Effects: None + +DdNode * +Cudd_addRestrict( + DdManager * dd, + DdNode * f, + DdNode * c +) + 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. + + Side Effects: None + +DdNode * +Cudd_addRoundOff( + DdManager * dd, + DdNode * f, + int N +) + 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. + + Side Effects: None + +DdNode * +Cudd_addScalarInverse( + DdManager * dd, + DdNode * f, + DdNode * epsilon +) + 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. + + Side Effects: None + +DdNode * +Cudd_addSetNZ( + DdManager * dd, + DdNode ** f, + DdNode ** g +) + This operator sets f to the value of g wherever g != 0. Returns NULL if not + a terminal case; f op g otherwise. + + Side Effects: None + +DdNode * +Cudd_addSwapVariables( + DdManager * dd, + DdNode * f, + DdNode ** x, + DdNode ** y, + int n +) + 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. + + Side Effects: None + +DdNode * +Cudd_addThreshold( + DdManager * dd, + DdNode ** f, + DdNode ** g +) + Threshold operator for Apply (f if f >=g; 0 if fx_id, or if + phase == 0 and f-->x_id'. + + Side Effects: None + +int +Cudd_bddIsVarHardGroup( + DdManager * dd, + int index +) + 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. + + Side Effects: none + +int +Cudd_bddIsVarToBeGrouped( + DdManager * dd, + int index +) + Checks whether a variable is set to be grouped. This function is used for + lazy sifting. + + Side Effects: none + +int +Cudd_bddIsVarToBeUngrouped( + DdManager * dd, + int index +) + 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. + + Side Effects: none + +DdNode * +Cudd_bddIsop( + DdManager * dd, + DdNode * L, + DdNode * U +) + 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. + + Side Effects: None + +DdNode * +Cudd_bddIteConstant( + DdManager * dd, + DdNode * f, + DdNode * g, + DdNode * h +) + 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. + + Side Effects: None + +int +Cudd_bddIterConjDecomp( + DdManager * dd, manager + DdNode * f, function to be decomposed + DdNode *** conjuncts address of the array of conjuncts +) + 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. + + Side Effects: 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. + +int +Cudd_bddIterDisjDecomp( + DdManager * dd, manager + DdNode * f, function to be decomposed + DdNode *** disjuncts address of the array of the disjuncts +) + 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. + + Side Effects: 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. + +DdNode * +Cudd_bddIte( + DdManager * dd, + DdNode * f, + DdNode * g, + DdNode * h +) + Implements ITE(f,g,h). Returns a pointer to the resulting BDD if successful; + NULL if the intermediate result blows up. + + Side Effects: None + +DdNode * +Cudd_bddIthVar( + DdManager * dd, + int i +) + 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. + + Side Effects: None + +DdNode * +Cudd_bddLICompaction( + DdManager * dd, manager + DdNode * f, function to be minimized + DdNode * c constraint (care set) +) + Performs safe minimization of a BDD. Given the BDD f of a + function to be minimized and a BDD c representing the care set, + Cudd_bddLICompaction produces the BDD of a function that agrees with + f wherever c is 1. Safe minimization means that + the size of the result is guaranteed not to exceed the size of + f. This function is based on the DAC97 paper by Hong et al.. + Returns a pointer to the result if successful; NULL otherwise. + + Side Effects: None + +int +Cudd_bddLeqUnless( + DdManager * dd, + DdNode * f, + DdNode * g, + DdNode * D +) + 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. + + Side Effects: None + +int +Cudd_bddLeq( + DdManager * dd, + DdNode * f, + DdNode * g +) + Returns 1 if f is less than or equal to g; 0 otherwise. No new nodes are + created. + + Side Effects: None + +DdNode * +Cudd_bddLiteralSetIntersection( + DdManager * dd, + DdNode * f, + DdNode * g +) + 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. + + Side Effects: None + +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 +) + 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. + + Side Effects: None + +DdNode * +Cudd_bddMinimize( + DdManager * dd, + DdNode * f, + DdNode * c +) + Finds a small BDD that agrees with f over c. + Returns a pointer to the result if successful; NULL otherwise. + + Side Effects: None + +DdNode * +Cudd_bddNPAnd( + DdManager * dd, + DdNode * f, + DdNode * g +) + 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. + + Side Effects: None + +DdNode * +Cudd_bddNand( + DdManager * dd, + DdNode * f, + DdNode * g +) + 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. + + Side Effects: None + +DdNode * +Cudd_bddNewVarAtLevel( + DdManager * dd, + int level +) + 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. + + Side Effects: None + +DdNode * +Cudd_bddNewVar( + DdManager * dd +) + 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. + + Side Effects: None + +DdNode * +Cudd_bddNor( + DdManager * dd, + DdNode * f, + DdNode * g +) + 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. + + Side Effects: None + +DdNode * +Cudd_bddOr( + DdManager * dd, + DdNode * f, + DdNode * g +) + 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. + + Side Effects: None + +DdNode * +Cudd_bddPermute( + DdManager * manager, + DdNode * node, + int * permut +) + 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. + + Side Effects: None + +DdNode ** +Cudd_bddPickArbitraryMinterms( + DdManager * dd, manager + DdNode * f, function from which to pick k minterms + DdNode ** vars, array of variables + int n, size of vars + int k number of minterms to find +) + Picks k on-set minterms evenly distributed from given DD. The minterms are + in terms of vars. The array vars should contain at + least all variables in the support of f; if this condition is + not met the minterms built by this procedure may not be contained in + f. 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: It may run out of memory; the function + f may be the constant 0; the minterms may not be contained + in f. + + Side Effects: None + +int +Cudd_bddPickOneCube( + DdManager * ddm, + DdNode * node, + char * string +) + 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. + + Side Effects: None + +DdNode * +Cudd_bddPickOneMinterm( + DdManager * dd, manager + DdNode * f, function from which to pick one minterm + DdNode ** vars, array of variables + int n size of vars +) + Picks one on-set minterm randomly from the given DD. The minterm is in terms + of vars. The array vars should contain at least + all variables in the support of f; if this condition is not met + the minterm built by this procedure may not be contained in f. + 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: It + may run out of memory; the function f may be the constant + 0; the minterm may not be contained in f. + + Side Effects: None + +int +Cudd_bddPrintCover( + DdManager * dd, + DdNode * l, + DdNode * u +) + 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. + + Side Effects: None + +int +Cudd_bddReadPairIndex( + DdManager * dd, + int index +) + 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. + + Side Effects: modifies the manager + +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 +) + 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. 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. 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. + + Side Effects: 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. + +void +Cudd_bddRealignDisable( + DdManager * unique +) + Disables realignment of ZDD order to BDD order. + + Side Effects: None + +void +Cudd_bddRealignEnable( + DdManager * unique +) + 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 + M be the ratio of the two numbers. For the purpose of + realignment, the ZDD variables from M*i to (M+1)*i- + 1 are reagarded as corresponding to BDD variable i. + Realignment is initially disabled. + + Side Effects: None + +int +Cudd_bddRealignmentEnabled( + DdManager * unique +) + Returns 1 if the realignment of BDD order to ZDD order is enabled; 0 + otherwise. + + Side Effects: None + +int +Cudd_bddResetVarToBeGrouped( + DdManager * dd, + int index +) + Resets a variable not to be grouped. This function is used for lazy sifting. + Returns 1 if successful; 0 otherwise. + + Side Effects: modifies the manager + +DdNode * +Cudd_bddRestrict( + DdManager * dd, + DdNode * f, + DdNode * c +) + 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. + + Side Effects: None + +int +Cudd_bddSetNsVar( + DdManager * dd, manager + int index variable index +) + Sets a variable type to next state. The variable type is used by lazy + sifting. Returns 1 if successful; 0 otherwise. + + Side Effects: modifies the manager + +int +Cudd_bddSetPairIndex( + DdManager * dd, manager + int index, variable index + int pairIndex corresponding variable index +) + Sets a corresponding pair index for a given index. These pair indices are + present and next state variable. Returns 1 if successful; 0 otherwise. + + Side Effects: modifies the manager + +int +Cudd_bddSetPiVar( + DdManager * dd, manager + int index variable index +) + Sets a variable type to primary input. The variable type is used by lazy + sifting. Returns 1 if successful; 0 otherwise. + + Side Effects: modifies the manager + +int +Cudd_bddSetPsVar( + DdManager * dd, manager + int index variable index +) + Sets a variable type to present state. The variable type is used by lazy + sifting. Returns 1 if successful; 0 otherwise. + + Side Effects: modifies the manager + +int +Cudd_bddSetVarHardGroup( + DdManager * dd, + int index +) + Sets a variable to be a hard group. This function is used for lazy sifting. + Returns 1 if successful; 0 otherwise. + + Side Effects: modifies the manager + +int +Cudd_bddSetVarToBeGrouped( + DdManager * dd, + int index +) + Sets a variable to be grouped. This function is used for lazy sifting. + Returns 1 if successful; 0 otherwise. + + Side Effects: modifies the manager + +int +Cudd_bddSetVarToBeUngrouped( + DdManager * dd, + int index +) + Sets a variable to be ungrouped. This function is used for lazy sifting. + Returns 1 if successful; 0 otherwise. + + Side Effects: modifies the manager + +DdNode * +Cudd_bddSqueeze( + DdManager * dd, manager + DdNode * l, lower bound + DdNode * u upper bound +) + Finds a small BDD in a function interval. Given BDDs l and + u, 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. + + Side Effects: None + +DdNode * +Cudd_bddSwapVariables( + DdManager * dd, + DdNode * f, + DdNode ** x, + DdNode ** y, + int n +) + 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. + + Side Effects: None + +DdNode * +Cudd_bddTransfer( + DdManager * ddSource, + DdManager * ddDestination, + DdNode * f +) + 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. + + Side Effects: None + +int +Cudd_bddUnbindVar( + DdManager * dd, manager + int index variable index +) + 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). + + Side Effects: Changes the "bindVar" flag in DdSubtable. + +DdNode * +Cudd_bddUnivAbstract( + DdManager * manager, + DdNode * f, + DdNode * cube +) + Universally abstracts all the variables in cube from f. Returns the + abstracted BDD if successful; NULL otherwise. + + Side Effects: None + +int +Cudd_bddVarConjDecomp( + DdManager * dd, manager + DdNode * f, function to be decomposed + DdNode *** conjuncts address of the array of conjuncts +) + Conjunctively decomposes one BDD according to a variable. If f + is the function of the BDD and x is the variable, the + decomposition is (f+x)(f+x'). 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. + + Side Effects: 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. + +int +Cudd_bddVarDisjDecomp( + DdManager * dd, manager + DdNode * f, function to be decomposed + DdNode *** disjuncts address of the array of the disjuncts +) + Performs two-way disjunctive decomposition of a BDD according to a variable. + If f is the function of the BDD and x is the + variable, the decomposition is f*x + f*x'. 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. + + Side Effects: 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. + +int +Cudd_bddVarIsBound( + DdManager * dd, manager + int index variable index +) + 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. + + Side Effects: none + +int +Cudd_bddVarIsDependent( + DdManager * dd, + DdNode * f, + DdNode * var variable +) + 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. + + Side Effects: None + +DdNode * +Cudd_bddVarMap( + DdManager * manager, DD manager + DdNode * f function in which to remap variables +) + 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. + + Side Effects: None + +DdNode * +Cudd_bddVectorCompose( + DdManager * dd, + DdNode * f, + DdNode ** vector +) + 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. + + Side Effects: None + +DdNode * +Cudd_bddXnor( + DdManager * dd, + DdNode * f, + DdNode * g +) + 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. + + Side Effects: None + +DdNode * +Cudd_bddXorExistAbstract( + DdManager * manager, + DdNode * f, + DdNode * g, + DdNode * cube +) + 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. + + Side Effects: None + +DdNode * +Cudd_bddXor( + DdManager * dd, + DdNode * f, + DdNode * g +) + 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. + + Side Effects: None + +void +Cudd_tlcInfoFree( + DdTlcInfo * t +) + Frees a DdTlcInfo Structure as well as the memory pointed by it. + + Side Effects: None + +DdNode * +Cudd_zddChange( + DdManager * dd, + DdNode * P, + int var +) + Substitutes a variable with its complement in a ZDD. returns a pointer to + the result if successful; NULL otherwise. + + Side Effects: None + +DdNode * +Cudd_zddComplement( + DdManager * dd, + DdNode * node +) + 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. + + Side Effects: The result depends on current variable order. + +double +Cudd_zddCountDouble( + DdManager * zdd, + DdNode * P +) + 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. + + Side Effects: None + +double +Cudd_zddCountMinterm( + DdManager * zdd, + DdNode * node, + int path +) + Counts the number of minterms of the ZDD rooted at node. This + procedure takes a parameter path 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. + + Side Effects: None + +int +Cudd_zddCount( + DdManager * zdd, + DdNode * P +) + Returns an integer representing the number of minterms in a ZDD. + + Side Effects: None + +char * +Cudd_zddCoverPathToString( + DdManager * zdd, DD manager + int * path, path of ZDD representing a cover + char * str pointer to string to use if != NULL +) + 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. + + Side Effects: None + +int +Cudd_zddDagSize( + DdNode * p_node +) + Counts the number of nodes in a ZDD. This function duplicates Cudd_DagSize + and is only retained for compatibility. + + Side Effects: None + +DdNode * +Cudd_zddDiffConst( + DdManager * zdd, + DdNode * P, + DdNode * Q +) + 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. + + Side Effects: None + +DdNode * +Cudd_zddDiff( + DdManager * dd, + DdNode * P, + DdNode * Q +) + Computes the difference of two ZDDs. Returns a pointer to the result if + successful; NULL otherwise. + + Side Effects: None + +DdNode * +Cudd_zddDivideF( + DdManager * dd, + DdNode * f, + DdNode * g +) + Modified version of Cudd_zddDivide. This function may disappear in future + releases. + + Side Effects: None + +DdNode * +Cudd_zddDivide( + DdManager * dd, + DdNode * f, + DdNode * g +) + 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. + + Side Effects: None + +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 +) + 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: solid line: THEN arcs; dashed line: + ELSE arcs. The dot options are chosen so that the drawing fits on a + letter-size sheet. + + Side Effects: None + +DdGen * +Cudd_zddFirstPath( + DdManager * zdd, + DdNode * f, + int ** path +) + 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. 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. The paths that end + in the empty terminal are not enumerated. + + Side Effects: The first path is returned as a side effect. + +DdNode * +Cudd_zddIntersect( + DdManager * dd, + DdNode * P, + DdNode * Q +) + Computes the intersection of two ZDDs. Returns a pointer to the result if + successful; NULL otherwise. + + Side Effects: None + +DdNode * +Cudd_zddIsop( + DdManager * dd, + DdNode * L, + DdNode * U, + DdNode ** zdd_I +) + 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 i should have indices + 2i and 2i+1. 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. + + Side Effects: zdd_I holds the pointer to the ZDD for the ISOP on successful + return. + +DdNode * +Cudd_zddIte( + DdManager * dd, + DdNode * f, + DdNode * g, + DdNode * h +) + Computes the ITE of three ZDDs. Returns a pointer to the result if + successful; NULL otherwise. + + Side Effects: None + +DdNode * +Cudd_zddIthVar( + DdManager * dd, + int i +) + 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. + + Side Effects: None + +int +Cudd_zddNextPath( + DdGen * gen, + int ** path +) + Generates the next path of a ZDD onset, using generator gen. Returns 0 if + the enumeration is completed; 1 otherwise. + + Side Effects: The path is returned as a side effect. The generator is + modified. + +DdNode * +Cudd_zddPortFromBdd( + DdManager * dd, + DdNode * B +) + 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. + + Side Effects: None + +DdNode * +Cudd_zddPortToBdd( + DdManager * dd, + DdNode * f +) + Converts a ZDD into a BDD. Returns a pointer to the resulting ZDD if + successful; NULL otherwise. + + Side Effects: None + +int +Cudd_zddPrintCover( + DdManager * zdd, + DdNode * node +) + Prints a sum of products from a ZDD representing a cover. Returns 1 if + successful; 0 otherwise. + + Side Effects: None + +int +Cudd_zddPrintDebug( + DdManager * zdd, + DdNode * f, + int n, + int pr +) + 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 > 0. Specifically: pr = 0 : prints nothing + pr = 1 : prints counts of nodes and minterms pr = 2 : prints counts + + disjoint sum of products pr = 3 : prints counts + list of nodes pr + > 3 : prints counts + disjoint sum of products + list of nodes + Returns 1 if successful; 0 otherwise. + + Side Effects: None + +int +Cudd_zddPrintMinterm( + DdManager * zdd, + DdNode * node +) + Prints a disjoint sum of product form for a ZDD. Returns 1 if successful; 0 + otherwise. + + Side Effects: None + +void +Cudd_zddPrintSubtable( + DdManager * table +) + Prints the ZDD table for debugging purposes. + + Side Effects: None + +DdNode * +Cudd_zddProduct( + DdManager * dd, + DdNode * f, + DdNode * g +) + 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. + + Side Effects: None + +long +Cudd_zddReadNodeCount( + DdManager * dd +) + Reports the number of nodes in ZDDs. This number always includes the two + constants 1 and 0. + + Side Effects: None + +void +Cudd_zddRealignDisable( + DdManager * unique +) + Disables realignment of ZDD order to BDD order. + + Side Effects: None + +void +Cudd_zddRealignEnable( + DdManager * unique +) + 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 + M be the ratio of the two numbers. For the purpose of + realignment, the ZDD variables from M*i to (M+1)*i- + 1 are reagarded as corresponding to BDD variable i. + Realignment is initially disabled. + + Side Effects: None + +int +Cudd_zddRealignmentEnabled( + DdManager * unique +) + Returns 1 if the realignment of ZDD order to BDD order is enabled; 0 + otherwise. + + Side Effects: None + +int +Cudd_zddReduceHeap( + DdManager * table, DD manager + Cudd_ReorderingTy heuristic, method used for reordering + int minsize bound below which no reordering occurs +) + Main dynamic reordering routine for ZDDs. Calls one of the possible + reordering procedures: Swapping Sifting Symmetric Sifting + For sifting and symmetric sifting it is possible to request reordering + to convergence. 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. + + Side Effects: Changes the variable order for all ZDDs and clears the cache. + +int +Cudd_zddShuffleHeap( + DdManager * table, DD manager + int * permutation required variable permutation +) + 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. + + Side Effects: Changes the ZDD variable order for all diagrams and clears the + cache. + +DdNode * +Cudd_zddSubset0( + DdManager * dd, + DdNode * P, + int var +) + 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. + + Side Effects: None + +DdNode * +Cudd_zddSubset1( + DdManager * dd, + DdNode * P, + int var +) + 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. + + Side Effects: None + +void +Cudd_zddSymmProfile( + DdManager * table, + int lower, + int upper +) + Prints statistics on symmetric ZDD variables. + + Side Effects: None + +DdNode * +Cudd_zddUnateProduct( + DdManager * dd, + DdNode * f, + DdNode * g +) + 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. + + Side Effects: None + +DdNode * +Cudd_zddUnion( + DdManager * dd, + DdNode * P, + DdNode * Q +) + Computes the union of two ZDDs. Returns a pointer to the result if + successful; NULL otherwise. + + Side Effects: None + +int +Cudd_zddVarsFromBddVars( + DdManager * dd, DD manager + int multiplicity how many ZDD variables are created for + each BDD variable +) + 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. + + Side Effects: None + +DdNode * +Cudd_zddWeakDivF( + DdManager * dd, + DdNode * f, + DdNode * g +) + Modified version of Cudd_zddWeakDiv. This function may disappear in future + releases. + + Side Effects: None + +DdNode * +Cudd_zddWeakDiv( + DdManager * dd, + DdNode * f, + DdNode * g +) + 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. + + Side Effects: None + diff --git a/distr/cudd/doc/cudd.ps b/distr/cudd/doc/cudd.ps new file mode 100644 index 0000000..739fe48 --- /dev/null +++ b/distr/cudd/doc/cudd.ps @@ -0,0 +1,5549 @@ +%!PS-Adobe-2.0 +%%Creator: dvips(k) 5.92b Copyright 2002 Radical Eye Software +%%Title: cudd.dvi +%%Pages: 47 +%%PageOrder: Ascend +%%BoundingBox: 0 0 596 842 +%%DocumentFonts: Times-Roman CMMI12 Times-Bold Times-Italic CMSY10 CMR10 +%%+ CMMI10 CMMI8 Courier CMSY8 CMR8 Times-BoldItalic +%%EndComments +%DVIPSWebPage: (www.radicaleye.com) +%DVIPSCommandLine: dvips -Ppdf -o cudd.ps cudd +%DVIPSParameters: dpi=8000, compressed +%DVIPSSource: TeX output 2009.02.20:2323 +%%BeginProcSet: tex.pro +%! +/TeXDict 300 dict def TeXDict begin/N{def}def/B{bind def}N/S{exch}N/X{S +N}B/A{dup}B/TR{translate}N/isls false N/vsize 11 72 mul N/hsize 8.5 72 +mul N/landplus90{false}def/@rigin{isls{[0 landplus90{1 -1}{-1 1}ifelse 0 +0 0]concat}if 72 Resolution div 72 VResolution div neg scale isls{ +landplus90{VResolution 72 div vsize mul 0 exch}{Resolution -72 div hsize +mul 0}ifelse TR}if Resolution VResolution vsize -72 div 1 add mul TR[ +matrix currentmatrix{A A round sub abs 0.00001 lt{round}if}forall round +exch round exch]setmatrix}N/@landscape{/isls true N}B/@manualfeed{ +statusdict/manualfeed true put}B/@copies{/#copies X}B/FMat[1 0 0 -1 0 0] +N/FBB[0 0 0 0]N/nn 0 N/IEn 0 N/ctr 0 N/df-tail{/nn 8 dict N nn begin +/FontType 3 N/FontMatrix fntrx N/FontBBox FBB N string/base X array +/BitMaps X/BuildChar{CharBuilder}N/Encoding IEn N end A{/foo setfont}2 +array copy cvx N load 0 nn put/ctr 0 N[}B/sf 0 N/df{/sf 1 N/fntrx FMat N +df-tail}B/dfs{div/sf X/fntrx[sf 0 0 sf neg 0 0]N df-tail}B/E{pop nn A +definefont setfont}B/Cw{Cd A length 5 sub get}B/Ch{Cd A length 4 sub get +}B/Cx{128 Cd A length 3 sub get sub}B/Cy{Cd A length 2 sub get 127 sub} +B/Cdx{Cd A length 1 sub get}B/Ci{Cd A type/stringtype ne{ctr get/ctr ctr +1 add N}if}B/CharBuilder{save 3 1 roll S A/base get 2 index get S +/BitMaps get S get/Cd X pop/ctr 0 N Cdx 0 Cx Cy Ch sub Cx Cw add Cy +setcachedevice Cw Ch true[1 0 0 -1 -.1 Cx sub Cy .1 sub]{Ci}imagemask +restore}B/D{/cc X A type/stringtype ne{]}if nn/base get cc ctr put nn +/BitMaps get S ctr S sf 1 ne{A A length 1 sub A 2 index S get sf div put +}if put/ctr ctr 1 add N}B/I{cc 1 add D}B/bop{userdict/bop-hook known{ +bop-hook}if/SI save N @rigin 0 0 moveto/V matrix currentmatrix A 1 get A +mul exch 0 get A mul add .99 lt{/QV}{/RV}ifelse load def pop pop}N/eop{ +SI restore userdict/eop-hook known{eop-hook}if showpage}N/@start{ +userdict/start-hook known{start-hook}if pop/VResolution X/Resolution X +1000 div/DVImag X/IEn 256 array N 2 string 0 1 255{IEn S A 360 add 36 4 +index cvrs cvn put}for pop 65781.76 div/vsize X 65781.76 div/hsize X}N +/p{show}N/RMat[1 0 0 -1 0 0]N/BDot 260 string N/Rx 0 N/Ry 0 N/V{}B/RV/v{ +/Ry X/Rx X V}B statusdict begin/product where{pop false[(Display)(NeXT) +(LaserWriter 16/600)]{A length product length le{A length product exch 0 +exch getinterval eq{pop true exit}if}{pop}ifelse}forall}{false}ifelse +end{{gsave TR -.1 .1 TR 1 1 scale Rx Ry false RMat{BDot}imagemask +grestore}}{{gsave TR -.1 .1 TR Rx Ry scale 1 1 false RMat{BDot} +imagemask grestore}}ifelse B/QV{gsave newpath transform round exch round +exch itransform moveto Rx 0 rlineto 0 Ry neg rlineto Rx neg 0 rlineto +fill grestore}B/a{moveto}B/delta 0 N/tail{A/delta X 0 rmoveto}B/M{S p +delta add tail}B/b{S p tail}B/c{-4 M}B/d{-3 M}B/e{-2 M}B/f{-1 M}B/g{0 M} +B/h{1 M}B/i{2 M}B/j{3 M}B/k{4 M}B/w{0 rmoveto}B/l{p -4 w}B/m{p -3 w}B/n{ +p -2 w}B/o{p -1 w}B/q{p 1 w}B/r{p 2 w}B/s{p 3 w}B/t{p 4 w}B/x{0 S +rmoveto}B/y{3 2 roll p a}B/bos{/SS save N}B/eos{SS restore}B end + +%%EndProcSet +%%BeginProcSet: alt-rule.pro +%! +% Patch by TVZ +% Makes dvips files draw rules with stroke rather than fill. +% Makes narrow rules more predictable at low resolutions +% after distilling to PDF. +% May have unknown consequences for very thick rules. +% Tested only with dvips 5.85(k). +TeXDict begin +/QV { + gsave newpath /ruleY X /ruleX X + Rx Ry gt + { ruleX ruleY Ry 2 div sub moveto Rx 0 rlineto Ry } + { ruleX Rx 2 div add ruleY moveto 0 Ry neg rlineto Rx } + ifelse + setlinewidth 0 setlinecap stroke grestore +} bind def +end + +%%EndProcSet +%%BeginProcSet: texc.pro +%! +/TeXDict 300 dict def TeXDict begin/N{def}def/B{bind def}N/S{exch}N/X{S +N}B/A{dup}B/TR{translate}N/isls false N/vsize 11 72 mul N/hsize 8.5 72 +mul N/landplus90{false}def/@rigin{isls{[0 landplus90{1 -1}{-1 1}ifelse 0 +0 0]concat}if 72 Resolution div 72 VResolution div neg scale isls{ +landplus90{VResolution 72 div vsize mul 0 exch}{Resolution -72 div hsize +mul 0}ifelse TR}if Resolution VResolution vsize -72 div 1 add mul TR[ +matrix currentmatrix{A A round sub abs 0.00001 lt{round}if}forall round +exch round exch]setmatrix}N/@landscape{/isls true N}B/@manualfeed{ +statusdict/manualfeed true put}B/@copies{/#copies X}B/FMat[1 0 0 -1 0 0] +N/FBB[0 0 0 0]N/nn 0 N/IEn 0 N/ctr 0 N/df-tail{/nn 8 dict N nn begin +/FontType 3 N/FontMatrix fntrx N/FontBBox FBB N string/base X array +/BitMaps X/BuildChar{CharBuilder}N/Encoding IEn N end A{/foo setfont}2 +array copy cvx N load 0 nn put/ctr 0 N[}B/sf 0 N/df{/sf 1 N/fntrx FMat N +df-tail}B/dfs{div/sf X/fntrx[sf 0 0 sf neg 0 0]N df-tail}B/E{pop nn A +definefont setfont}B/Cw{Cd A length 5 sub get}B/Ch{Cd A length 4 sub get +}B/Cx{128 Cd A length 3 sub get sub}B/Cy{Cd A length 2 sub get 127 sub} +B/Cdx{Cd A length 1 sub get}B/Ci{Cd A type/stringtype ne{ctr get/ctr ctr +1 add N}if}B/id 0 N/rw 0 N/rc 0 N/gp 0 N/cp 0 N/G 0 N/CharBuilder{save 3 +1 roll S A/base get 2 index get S/BitMaps get S get/Cd X pop/ctr 0 N Cdx +0 Cx Cy Ch sub Cx Cw add Cy setcachedevice Cw Ch true[1 0 0 -1 -.1 Cx +sub Cy .1 sub]/id Ci N/rw Cw 7 add 8 idiv string N/rc 0 N/gp 0 N/cp 0 N{ +rc 0 ne{rc 1 sub/rc X rw}{G}ifelse}imagemask restore}B/G{{id gp get/gp +gp 1 add N A 18 mod S 18 idiv pl S get exec}loop}B/adv{cp add/cp X}B +/chg{rw cp id gp 4 index getinterval putinterval A gp add/gp X adv}B/nd{ +/cp 0 N rw exit}B/lsh{rw cp 2 copy get A 0 eq{pop 1}{A 255 eq{pop 254}{ +A A add 255 and S 1 and or}ifelse}ifelse put 1 adv}B/rsh{rw cp 2 copy +get A 0 eq{pop 128}{A 255 eq{pop 127}{A 2 idiv S 128 and or}ifelse} +ifelse put 1 adv}B/clr{rw cp 2 index string putinterval adv}B/set{rw cp +fillstr 0 4 index getinterval putinterval adv}B/fillstr 18 string 0 1 17 +{2 copy 255 put pop}for N/pl[{adv 1 chg}{adv 1 chg nd}{1 add chg}{1 add +chg nd}{adv lsh}{adv lsh nd}{adv rsh}{adv rsh nd}{1 add adv}{/rc X nd}{ +1 add set}{1 add clr}{adv 2 chg}{adv 2 chg nd}{pop nd}]A{bind pop} +forall N/D{/cc X A type/stringtype ne{]}if nn/base get cc ctr put nn +/BitMaps get S ctr S sf 1 ne{A A length 1 sub A 2 index S get sf div put +}if put/ctr ctr 1 add N}B/I{cc 1 add D}B/bop{userdict/bop-hook known{ +bop-hook}if/SI save N @rigin 0 0 moveto/V matrix currentmatrix A 1 get A +mul exch 0 get A mul add .99 lt{/QV}{/RV}ifelse load def pop pop}N/eop{ +SI restore userdict/eop-hook known{eop-hook}if showpage}N/@start{ +userdict/start-hook known{start-hook}if pop/VResolution X/Resolution X +1000 div/DVImag X/IEn 256 array N 2 string 0 1 255{IEn S A 360 add 36 4 +index cvrs cvn put}for pop 65781.76 div/vsize X 65781.76 div/hsize X}N +/p{show}N/RMat[1 0 0 -1 0 0]N/BDot 260 string N/Rx 0 N/Ry 0 N/V{}B/RV/v{ +/Ry X/Rx X V}B statusdict begin/product where{pop false[(Display)(NeXT) +(LaserWriter 16/600)]{A length product length le{A length product exch 0 +exch getinterval eq{pop true exit}if}{pop}ifelse}forall}{false}ifelse +end{{gsave TR -.1 .1 TR 1 1 scale Rx Ry false RMat{BDot}imagemask +grestore}}{{gsave TR -.1 .1 TR Rx Ry scale 1 1 false RMat{BDot} +imagemask grestore}}ifelse B/QV{gsave newpath transform round exch round +exch itransform moveto Rx 0 rlineto 0 Ry neg rlineto Rx neg 0 rlineto +fill grestore}B/a{moveto}B/delta 0 N/tail{A/delta X 0 rmoveto}B/M{S p +delta add tail}B/b{S p tail}B/c{-4 M}B/d{-3 M}B/e{-2 M}B/f{-1 M}B/g{0 M} +B/h{1 M}B/i{2 M}B/j{3 M}B/k{4 M}B/w{0 rmoveto}B/l{p -4 w}B/m{p -3 w}B/n{ +p -2 w}B/o{p -1 w}B/q{p 1 w}B/r{p 2 w}B/s{p 3 w}B/t{p 4 w}B/x{0 S +rmoveto}B/y{3 2 roll p a}B/bos{/SS save N}B/eos{SS restore}B end + +%%EndProcSet +%%BeginProcSet: 8r.enc +% File 8r.enc as of 2002-03-12 for PSNFSS 9 +% +% This is the encoding vector for Type1 and TrueType fonts to be used +% with TeX. This file is part of the PSNFSS bundle, version 9 +% +% Authors: S. Rahtz, P. MacKay, Alan Jeffrey, B. Horn, K. Berry, W. Schmidt +% +% Idea is to have all the characters normally included in Type 1 fonts +% available for typesetting. This is effectively the characters in Adobe +% Standard Encoding + ISO Latin 1 + extra characters from Lucida + Euro. +% +% Character code assignments were made as follows: +% +% (1) the Windows ANSI characters are almost all in their Windows ANSI +% positions, because some Windows users cannot easily reencode the +% fonts, and it makes no difference on other systems. The only Windows +% ANSI characters not available are those that make no sense for +% typesetting -- rubout (127 decimal), nobreakspace (160), softhyphen +% (173). quotesingle and grave are moved just because it's such an +% irritation not having them in TeX positions. +% +% (2) Remaining characters are assigned arbitrarily to the lower part +% of the range, avoiding 0, 10 and 13 in case we meet dumb software. +% +% (3) Y&Y Lucida Bright includes some extra text characters; in the +% hopes that other PostScript fonts, perhaps created for public +% consumption, will include them, they are included starting at 0x12. +% +% (4) Remaining positions left undefined are for use in (hopefully) +% upward-compatible revisions, if someday more characters are generally +% available. +% +% (5) hyphen appears twice for compatibility with both ASCII and Windows. +% +% (6) /Euro is assigned to 128, as in Windows ANSI +% +/TeXBase1Encoding [ +% 0x00 (encoded characters from Adobe Standard not in Windows 3.1) + /.notdef /dotaccent /fi /fl + /fraction /hungarumlaut /Lslash /lslash + /ogonek /ring /.notdef + /breve /minus /.notdef +% These are the only two remaining unencoded characters, so may as +% well include them. + /Zcaron /zcaron +% 0x10 + /caron /dotlessi +% (unusual TeX characters available in, e.g., Lucida Bright) + /dotlessj /ff /ffi /ffl + /.notdef /.notdef /.notdef /.notdef + /.notdef /.notdef /.notdef /.notdef + % very contentious; it's so painful not having quoteleft and quoteright + % at 96 and 145 that we move the things normally found there down to here. + /grave /quotesingle +% 0x20 (ASCII begins) + /space /exclam /quotedbl /numbersign + /dollar /percent /ampersand /quoteright + /parenleft /parenright /asterisk /plus /comma /hyphen /period /slash +% 0x30 + /zero /one /two /three /four /five /six /seven + /eight /nine /colon /semicolon /less /equal /greater /question +% 0x40 + /at /A /B /C /D /E /F /G /H /I /J /K /L /M /N /O +% 0x50 + /P /Q /R /S /T /U /V /W + /X /Y /Z /bracketleft /backslash /bracketright /asciicircum /underscore +% 0x60 + /quoteleft /a /b /c /d /e /f /g /h /i /j /k /l /m /n /o +% 0x70 + /p /q /r /s /t /u /v /w + /x /y /z /braceleft /bar /braceright /asciitilde + /.notdef % rubout; ASCII ends +% 0x80 + /Euro /.notdef /quotesinglbase /florin + /quotedblbase /ellipsis /dagger /daggerdbl + /circumflex /perthousand /Scaron /guilsinglleft + /OE /.notdef /.notdef /.notdef +% 0x90 + /.notdef /.notdef /.notdef /quotedblleft + /quotedblright /bullet /endash /emdash + /tilde /trademark /scaron /guilsinglright + /oe /.notdef /.notdef /Ydieresis +% 0xA0 + /.notdef % nobreakspace + /exclamdown /cent /sterling + /currency /yen /brokenbar /section + /dieresis /copyright /ordfeminine /guillemotleft + /logicalnot + /hyphen % Y&Y (also at 45); Windows' softhyphen + /registered + /macron +% 0xD0 + /degree /plusminus /twosuperior /threesuperior + /acute /mu /paragraph /periodcentered + /cedilla /onesuperior /ordmasculine /guillemotright + /onequarter /onehalf /threequarters /questiondown +% 0xC0 + /Agrave /Aacute /Acircumflex /Atilde /Adieresis /Aring /AE /Ccedilla + /Egrave /Eacute /Ecircumflex /Edieresis + /Igrave /Iacute /Icircumflex /Idieresis +% 0xD0 + /Eth /Ntilde /Ograve /Oacute + /Ocircumflex /Otilde /Odieresis /multiply + /Oslash /Ugrave /Uacute /Ucircumflex + /Udieresis /Yacute /Thorn /germandbls +% 0xE0 + /agrave /aacute /acircumflex /atilde + /adieresis /aring /ae /ccedilla + /egrave /eacute /ecircumflex /edieresis + /igrave /iacute /icircumflex /idieresis +% 0xF0 + /eth /ntilde /ograve /oacute + /ocircumflex /otilde /odieresis /divide + /oslash /ugrave /uacute /ucircumflex + /udieresis /yacute /thorn /ydieresis +] def + +%%EndProcSet +%%BeginProcSet: texps.pro +%! +TeXDict begin/rf{findfont dup length 1 add dict begin{1 index/FID ne 2 +index/UniqueID ne and{def}{pop pop}ifelse}forall[1 index 0 6 -1 roll +exec 0 exch 5 -1 roll VResolution Resolution div mul neg 0 0]FontType 0 +ne{/Metrics exch def dict begin Encoding{exch dup type/integertype ne{ +pop pop 1 sub dup 0 le{pop}{[}ifelse}{FontMatrix 0 get div Metrics 0 get +div def}ifelse}forall Metrics/Metrics currentdict end def}{{1 index type +/nametype eq{exit}if exch pop}loop}ifelse[2 index currentdict end +definefont 3 -1 roll makefont/setfont cvx]cvx def}def/ObliqueSlant{dup +sin S cos div neg}B/SlantFont{4 index mul add}def/ExtendFont{3 -1 roll +mul exch}def/ReEncodeFont{CharStrings rcheck{/Encoding false def dup[ +exch{dup CharStrings exch known not{pop/.notdef/Encoding true def}if} +forall Encoding{]exch pop}{cleartomark}ifelse}if/Encoding exch def}def +end + +%%EndProcSet +%%BeginProcSet: special.pro +%! +TeXDict begin/SDict 200 dict N SDict begin/@SpecialDefaults{/hs 612 N +/vs 792 N/ho 0 N/vo 0 N/hsc 1 N/vsc 1 N/ang 0 N/CLIP 0 N/rwiSeen false N +/rhiSeen false N/letter{}N/note{}N/a4{}N/legal{}N}B/@scaleunit 100 N +/@hscale{@scaleunit div/hsc X}B/@vscale{@scaleunit div/vsc X}B/@hsize{ +/hs X/CLIP 1 N}B/@vsize{/vs X/CLIP 1 N}B/@clip{/CLIP 2 N}B/@hoffset{/ho +X}B/@voffset{/vo X}B/@angle{/ang X}B/@rwi{10 div/rwi X/rwiSeen true N}B +/@rhi{10 div/rhi X/rhiSeen true N}B/@llx{/llx X}B/@lly{/lly X}B/@urx{ +/urx X}B/@ury{/ury X}B/magscale true def end/@MacSetUp{userdict/md known +{userdict/md get type/dicttype eq{userdict begin md length 10 add md +maxlength ge{/md md dup length 20 add dict copy def}if end md begin +/letter{}N/note{}N/legal{}N/od{txpose 1 0 mtx defaultmatrix dtransform S +atan/pa X newpath clippath mark{transform{itransform moveto}}{transform{ +itransform lineto}}{6 -2 roll transform 6 -2 roll transform 6 -2 roll +transform{itransform 6 2 roll itransform 6 2 roll itransform 6 2 roll +curveto}}{{closepath}}pathforall newpath counttomark array astore/gc xdf +pop ct 39 0 put 10 fz 0 fs 2 F/|______Courier fnt invertflag{PaintBlack} +if}N/txpose{pxs pys scale ppr aload pop por{noflips{pop S neg S TR pop 1 +-1 scale}if xflip yflip and{pop S neg S TR 180 rotate 1 -1 scale ppr 3 +get ppr 1 get neg sub neg ppr 2 get ppr 0 get neg sub neg TR}if xflip +yflip not and{pop S neg S TR pop 180 rotate ppr 3 get ppr 1 get neg sub +neg 0 TR}if yflip xflip not and{ppr 1 get neg ppr 0 get neg TR}if}{ +noflips{TR pop pop 270 rotate 1 -1 scale}if xflip yflip and{TR pop pop +90 rotate 1 -1 scale ppr 3 get ppr 1 get neg sub neg ppr 2 get ppr 0 get +neg sub neg TR}if xflip yflip not and{TR pop pop 90 rotate ppr 3 get ppr +1 get neg sub neg 0 TR}if yflip xflip not and{TR pop pop 270 rotate ppr +2 get ppr 0 get neg sub neg 0 S TR}if}ifelse scaleby96{ppr aload pop 4 +-1 roll add 2 div 3 1 roll add 2 div 2 copy TR .96 dup scale neg S neg S +TR}if}N/cp{pop pop showpage pm restore}N end}if}if}N/normalscale{ +Resolution 72 div VResolution 72 div neg scale magscale{DVImag dup scale +}if 0 setgray}N/psfts{S 65781.76 div N}N/startTexFig{/psf$SavedState +save N userdict maxlength dict begin/magscale true def normalscale +currentpoint TR/psf$ury psfts/psf$urx psfts/psf$lly psfts/psf$llx psfts +/psf$y psfts/psf$x psfts currentpoint/psf$cy X/psf$cx X/psf$sx psf$x +psf$urx psf$llx sub div N/psf$sy psf$y psf$ury psf$lly sub div N psf$sx +psf$sy scale psf$cx psf$sx div psf$llx sub psf$cy psf$sy div psf$ury sub +TR/showpage{}N/erasepage{}N/setpagedevice{pop}N/copypage{}N/p 3 def +@MacSetUp}N/doclip{psf$llx psf$lly psf$urx psf$ury currentpoint 6 2 roll +newpath 4 copy 4 2 roll moveto 6 -1 roll S lineto S lineto S lineto +closepath clip newpath moveto}N/endTexFig{end psf$SavedState restore}N +/@beginspecial{SDict begin/SpecialSave save N gsave normalscale +currentpoint TR @SpecialDefaults count/ocount X/dcount countdictstack N} +N/@setspecial{CLIP 1 eq{newpath 0 0 moveto hs 0 rlineto 0 vs rlineto hs +neg 0 rlineto closepath clip}if ho vo TR hsc vsc scale ang rotate +rwiSeen{rwi urx llx sub div rhiSeen{rhi ury lly sub div}{dup}ifelse +scale llx neg lly neg TR}{rhiSeen{rhi ury lly sub div dup scale llx neg +lly neg TR}if}ifelse CLIP 2 eq{newpath llx lly moveto urx lly lineto urx +ury lineto llx ury lineto closepath clip}if/showpage{}N/erasepage{}N +/setpagedevice{pop}N/copypage{}N newpath}N/@endspecial{count ocount sub{ +pop}repeat countdictstack dcount sub{end}repeat grestore SpecialSave +restore end}N/@defspecial{SDict begin}N/@fedspecial{end}B/li{lineto}B +/rl{rlineto}B/rc{rcurveto}B/np{/SaveX currentpoint/SaveY X N 1 +setlinecap newpath}N/st{stroke SaveX SaveY moveto}N/fil{fill SaveX SaveY +moveto}N/ellipse{/endangle X/startangle X/yrad X/xrad X/savematrix +matrix currentmatrix N TR xrad yrad scale 0 0 1 startangle endangle arc +savematrix setmatrix}N end + +%%EndProcSet +%%BeginProcSet: color.pro +%! +TeXDict begin/setcmykcolor where{pop}{/setcmykcolor{dup 10 eq{pop +setrgbcolor}{1 sub 4 1 roll 3{3 index add neg dup 0 lt{pop 0}if 3 1 roll +}repeat setrgbcolor pop}ifelse}B}ifelse/TeXcolorcmyk{setcmykcolor}def +/TeXcolorrgb{setrgbcolor}def/TeXcolorgrey{setgray}def/TeXcolorgray{ +setgray}def/TeXcolorhsb{sethsbcolor}def/currentcmykcolor where{pop}{ +/currentcmykcolor{currentrgbcolor 10}B}ifelse/DC{exch dup userdict exch +known{pop pop}{X}ifelse}B/GreenYellow{0.15 0 0.69 0 setcmykcolor}DC +/Yellow{0 0 1 0 setcmykcolor}DC/Goldenrod{0 0.10 0.84 0 setcmykcolor}DC +/Dandelion{0 0.29 0.84 0 setcmykcolor}DC/Apricot{0 0.32 0.52 0 +setcmykcolor}DC/Peach{0 0.50 0.70 0 setcmykcolor}DC/Melon{0 0.46 0.50 0 +setcmykcolor}DC/YellowOrange{0 0.42 1 0 setcmykcolor}DC/Orange{0 0.61 +0.87 0 setcmykcolor}DC/BurntOrange{0 0.51 1 0 setcmykcolor}DC +/Bittersweet{0 0.75 1 0.24 setcmykcolor}DC/RedOrange{0 0.77 0.87 0 +setcmykcolor}DC/Mahogany{0 0.85 0.87 0.35 setcmykcolor}DC/Maroon{0 0.87 +0.68 0.32 setcmykcolor}DC/BrickRed{0 0.89 0.94 0.28 setcmykcolor}DC/Red{ +0 1 1 0 setcmykcolor}DC/OrangeRed{0 1 0.50 0 setcmykcolor}DC/RubineRed{ +0 1 0.13 0 setcmykcolor}DC/WildStrawberry{0 0.96 0.39 0 setcmykcolor}DC +/Salmon{0 0.53 0.38 0 setcmykcolor}DC/CarnationPink{0 0.63 0 0 +setcmykcolor}DC/Magenta{0 1 0 0 setcmykcolor}DC/VioletRed{0 0.81 0 0 +setcmykcolor}DC/Rhodamine{0 0.82 0 0 setcmykcolor}DC/Mulberry{0.34 0.90 +0 0.02 setcmykcolor}DC/RedViolet{0.07 0.90 0 0.34 setcmykcolor}DC +/Fuchsia{0.47 0.91 0 0.08 setcmykcolor}DC/Lavender{0 0.48 0 0 +setcmykcolor}DC/Thistle{0.12 0.59 0 0 setcmykcolor}DC/Orchid{0.32 0.64 0 +0 setcmykcolor}DC/DarkOrchid{0.40 0.80 0.20 0 setcmykcolor}DC/Purple{ +0.45 0.86 0 0 setcmykcolor}DC/Plum{0.50 1 0 0 setcmykcolor}DC/Violet{ +0.79 0.88 0 0 setcmykcolor}DC/RoyalPurple{0.75 0.90 0 0 setcmykcolor}DC +/BlueViolet{0.86 0.91 0 0.04 setcmykcolor}DC/Periwinkle{0.57 0.55 0 0 +setcmykcolor}DC/CadetBlue{0.62 0.57 0.23 0 setcmykcolor}DC +/CornflowerBlue{0.65 0.13 0 0 setcmykcolor}DC/MidnightBlue{0.98 0.13 0 +0.43 setcmykcolor}DC/NavyBlue{0.94 0.54 0 0 setcmykcolor}DC/RoyalBlue{1 +0.50 0 0 setcmykcolor}DC/Blue{1 1 0 0 setcmykcolor}DC/Cerulean{0.94 0.11 +0 0 setcmykcolor}DC/Cyan{1 0 0 0 setcmykcolor}DC/ProcessBlue{0.96 0 0 0 +setcmykcolor}DC/SkyBlue{0.62 0 0.12 0 setcmykcolor}DC/Turquoise{0.85 0 +0.20 0 setcmykcolor}DC/TealBlue{0.86 0 0.34 0.02 setcmykcolor}DC +/Aquamarine{0.82 0 0.30 0 setcmykcolor}DC/BlueGreen{0.85 0 0.33 0 +setcmykcolor}DC/Emerald{1 0 0.50 0 setcmykcolor}DC/JungleGreen{0.99 0 +0.52 0 setcmykcolor}DC/SeaGreen{0.69 0 0.50 0 setcmykcolor}DC/Green{1 0 +1 0 setcmykcolor}DC/ForestGreen{0.91 0 0.88 0.12 setcmykcolor}DC +/PineGreen{0.92 0 0.59 0.25 setcmykcolor}DC/LimeGreen{0.50 0 1 0 +setcmykcolor}DC/YellowGreen{0.44 0 0.74 0 setcmykcolor}DC/SpringGreen{ +0.26 0 0.76 0 setcmykcolor}DC/OliveGreen{0.64 0 0.95 0.40 setcmykcolor} +DC/RawSienna{0 0.72 1 0.45 setcmykcolor}DC/Sepia{0 0.83 1 0.70 +setcmykcolor}DC/Brown{0 0.81 1 0.60 setcmykcolor}DC/Tan{0.14 0.42 0.56 0 +setcmykcolor}DC/Gray{0 0 0 0.50 setcmykcolor}DC/Black{0 0 0 1 +setcmykcolor}DC/White{0 0 0 0 setcmykcolor}DC end + +%%EndProcSet +%%BeginFont: CMR8 +%!PS-AdobeFont-1.1: CMR8 1.0 +%%CreationDate: 1991 Aug 20 16:39:40 +% Copyright (C) 1997 American Mathematical Society. All Rights Reserved. +11 dict begin +/FontInfo 7 dict dup begin +/version (1.0) readonly def +/Notice (Copyright (C) 1997 American Mathematical Society. All Rights Reserved) readonly def +/FullName (CMR8) readonly def +/FamilyName (Computer Modern) readonly def +/Weight (Medium) readonly def +/ItalicAngle 0 def +/isFixedPitch false def +end readonly def +/FontName /CMR8 def +/PaintType 0 def +/FontType 1 def +/FontMatrix [0.001 0 0 0.001 0 0] readonly def +/Encoding 256 array +0 1 255 {1 index exch /.notdef put} for +dup 48 /zero put +dup 49 /one put +dup 50 /two put +dup 51 /three put +readonly def +/FontBBox{-36 -250 1070 750}readonly def +/UniqueID 5000791 def +currentdict end +currentfile eexec +D9D66F633B846A97B686A97E45A3D0AA052A014267B7904EB3C0D3BD0B83D891 +016CA6CA4B712ADEB258FAAB9A130EE605E61F77FC1B738ABC7C51CD46EF8171 +9098D5FEE67660E69A7AB91B58F29A4D79E57022F783EB0FBBB6D4F4EC35014F +D2DECBA99459A4C59DF0C6EBA150284454E707DC2100C15B76B4C19B84363758 +469A6C558785B226332152109871A9883487DD7710949204DDCF837E6A8708B8 +2BDBF16FBC7512FAA308A093FE5CF4E9D2405B169CD5365D6ECED5D768D66D6C +68618B8C482B341F8CA38E9BB9BAFCFAAD9C2F3FD033B62690986ED43D9C9361 +3645B82392D5CAE11A7CB49D7E2E82DCD485CBA1772CE422BB1D7283AD675B65 +48A7EA0069A883EC1DAA3E1F9ECE7586D6CF0A128CD557C7E5D7AA3EA97EBAD3 +9619D1BFCF4A6D64768741EDEA0A5B0EFBBF347CDCBE2E03D756967A16B613DB +0FC45FA2A3312E0C46A5FD0466AB097C58FFEEC40601B8395E52775D0AFCD7DB +8AB317333110531E5C44A4CB4B5ACD571A1A60960B15E450948A5EEA14DD330F +EA209265DB8E1A1FC80DCD3860323FD26C113B041A88C88A21655878680A4466 +FA10403D24BB97152A49B842C180E4D258C9D48F21D057782D90623116830BA3 +9902B3C5F2F2DD01433B0D7099C07DBDE268D0FFED5169BCD03D48B2F058AD62 +D8678C626DC7A3F352152C99BA963EF95F8AD11DB8B0D351210A17E4C2C55AD8 +9EB64172935D3C20A398F3EEEEC31551966A7438EF3FEE422C6D4E05337620D5 +ACC7B52BED984BFAAD36EF9D20748B05D07BE4414A63975125D272FAD83F76E6 +10FFF8363014BE526D580873C5A42B70FA911EC7B86905F13AFE55EB0273F582 +83158793B8CC296B8DE1DCCF1250FD57CB0E035C7EDA3B0092ED940D37A05493 +2EC54E09B984FCA4AB7D2EA182BCF1263AA244B07EC0EA901C077A059F709F30 +4384CB5FA748F2054FAD9A7A43D4EA427918BD414F766531136B60C3477C6632 +BEFE3897B58C19276A301926C2AEF2756B367319772C9B201C49B4D935A8267B +041D6F1783B6AEA4DAC4F5B3507D7032AA640AAB12E343A4E9BDCF419C04A721 +3888B25AF4E293AACED9A6BDC78E61DA1C424C6503CC1885F762BE0618B16C14 +7386EB4C4B9B3142B9662F48CF5B55DC44261F9F0F975611120F7B9846423136 +B3A568B97F5822B76CF10ECD4CD0C64DC55413CC2E843FB37053EAFE985A98CF +9E408707AB2BBD2F036B622F74397BE4BEFA06A0CC51A30C326C3654B5E548B5 +FD5BE6BFFD05A02E81F12A94892139862012A6776D80F0B7C3E90F8E34918601 +8A6B25676CDD71F0DBD7CF514F0363B15B6C7E62EF9BE227EB164481CC0EF812 +8B8B5FDD0FA1815E629760FDEAA026094F96B05BE963194E99D2E5444F62C26B +1BBAD76672EEC98948B7D9C81CAEBBB7C9CBA16CBDFC595D7AD3F92651B63D50 +CC7E92F4E96C4DE2721AFEE94FBFE5843979D30068BC1F11E5374F6F6EF4586C +AB699727770D97A8681D2E75E907027302832D0834FD7BB48EE89D7F0A39E263 +C34F09602BDEF782A7BCF182CB6D8603E31EF82E669B294BBE9B5AD29CD12FA9 +DD1CAAC8AB4DBB663F8C50472C9D7CF3CFB9AE712D83B306991B89F75A87A6C8 +CF7901236E9EE16204F26C79404A6EB87AC532A29C47C9455D0F3DCCA48E2B26 +1240EB3CD115047EC6C4E3F5B3680127DF7509CD26BEF7C542D0332B2A2F680F +ECAC3A2C958DC3F17576DEBDB9478343EE622DF8C8F7C488ED049690697A6B1D +BAFF45A781099100DD7B0A0598A4A93E088E8B44198EB0DE3761F141AEF45C92 +1A71F32189FEFCC7978570BEBD53305BFB9B68829998196345770721ABAE7410 +50A99976446ABBBF31130CE1A85B4F37B85BBCCD2E31C072B96F005E7506BA7B +6AF46E32CEAB608411DACC4D93ECE77BC4C4282DE8FC4189C8661A93F0A3C0CC +B09077804522B3675B87F45E9E0AB99AFC3F6A979FB2030642DB80CBB4A92BA9 +8FEADF534577FE567839008FEB0F6CD811ACB7CEDCEFC98807636A24B6EDAD43 +83CE013C9E660F3F3DB842554D04B5D8277640A931ED4CC700F8BCFF901775C6 +DBE1A76EE8ADC5601FF1DC4EC663E3E960064875BBCA81F5B82118A055D48C9D +C2DC4C00BB1B42B6C3D00354040080ACAD10EE6A464E5F62E5AC4236FF2D2A6A +BBFE55CD6E55990D15C6A13229F0AB706D61C746EF99E2AF9365 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +cleartomark +%%EndFont +%%BeginFont: CMSY8 +%!PS-AdobeFont-1.1: CMSY8 1.0 +%%CreationDate: 1991 Aug 15 07:22:10 +% Copyright (C) 1997 American Mathematical Society. All Rights Reserved. +11 dict begin +/FontInfo 7 dict dup begin +/version (1.0) readonly def +/Notice (Copyright (C) 1997 American Mathematical Society. All Rights Reserved) readonly def +/FullName (CMSY8) readonly def +/FamilyName (Computer Modern) readonly def +/Weight (Medium) readonly def +/ItalicAngle -14.035 def +/isFixedPitch false def +end readonly def +/FontName /CMSY8 def +/PaintType 0 def +/FontType 1 def +/FontMatrix [0.001 0 0 0.001 0 0] readonly def +/Encoding 256 array +0 1 255 {1 index exch /.notdef put} for +dup 161 /minus put +dup 48 /prime put +readonly def +/FontBBox{-30 -955 1185 779}readonly def +/UniqueID 5000818 def +currentdict end +currentfile eexec +D9D66F633B846A97B686A97E45A3D0AA052F09F9C8ADE9D907C058B87E9B6964 +7D53359E51216774A4EAA1E2B58EC3176BD1184A633B951372B4198D4E8C5EF4 +A213ACB58AA0A658908035BF2ED8531779838A960DFE2B27EA49C37156989C85 +E21B3ABF72E39A89232CD9F4237FC80C9E64E8425AA3BEF7DED60B122A52922A +221A37D9A807DD01161779DDE7D5FC1B2109839E5B52DFBB2A7C1B5D8E7E8AA0 +5B10EA43D6A8ED61AF5B23D49920D8F79DAB6A59062134D84AC0100187A6CD1F +80F5DDD9D222ACB1C23326A7656A635C4A241CCD32CBFDF8363206B8AA36E107 +1477F5496111E055C7491002AFF272E46ECC46422F0380D093284870022523FB +DA1716CC4F2E2CCAD5F173FCBE6EDDB874AD255CD5E5C0F86214393FCB5F5C20 +9C3C2BB5886E36FC3CCC21483C3AC193485A46E9D22BD7201894E4D45ADD9BF1 +CC5CF6A5010B5654AC0BE0DA903DB563B13840BA3015F72E51E3BC80156388BA +F83C7D393392BCBC227771CDCB976E93302530FA3F4BEF341997D4302A48384A +CEFFC1559462EA5F60DC05245E8499D8E61397B2C094CEED1AF26EE15A837209 +ECE64FEF41ABE8DDA7BE1F351CF14E07BA8FD40CEFBFC3CE7B9D4912D6FE752D +9CF163084E688DDCC4B5AAEDEB6E94DDDE34330BA35394A8B485E767F0F94A71 +4532F3B89C51AC3FD1C082EF41EA489B9595B4120FDCA2F599C88F5058126CD1 +4C7F96B4FE22BAB1A5E16F215DECBCE4186C68B6263BD5331CDC1FF9F30332A7 +7B831255A41A642C5719272C6B5993171CA395A0D11B6376457EC30E1CDE47A4 +9B9EE95D112C64084901B6357E881C0DEB6836B80F21E57B660388BA4F7B89EB +9AF7DE8AEA702FC5B765552F78058A20E424277F667A4E9955A797593CE44E19 +A98F149CA17D6379040A1C836CA18234278DFDA205EFD55D527C7F38766D4C97 + +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +cleartomark +%%EndFont +%%BeginFont: CMMI8 +%!PS-AdobeFont-1.1: CMMI8 1.100 +%%CreationDate: 1996 Jul 23 07:53:54 +% Copyright (C) 1997 American Mathematical Society. All Rights Reserved. +11 dict begin +/FontInfo 7 dict dup begin +/version (1.100) readonly def +/Notice (Copyright (C) 1997 American Mathematical Society. All Rights Reserved) readonly def +/FullName (CMMI8) readonly def +/FamilyName (Computer Modern) readonly def +/Weight (Medium) readonly def +/ItalicAngle -14.04 def +/isFixedPitch false def +end readonly def +/FontName /CMMI8 def +/PaintType 0 def +/FontType 1 def +/FontMatrix [0.001 0 0 0.001 0 0] readonly def +/Encoding 256 array +0 1 255 {1 index exch /.notdef put} for +dup 110 /n put +readonly def +/FontBBox{-24 -250 1110 750}readonly def +/UniqueID 5087383 def +currentdict end +currentfile eexec +D9D66F633B846A97B686A97E45A3D0AA0529731C99A784CCBE85B4993B2EEBDE +3B12D472B7CF54651EF21185116A69AB1096ED4BAD2F646635E019B6417CC77B +532F85D811C70D1429A19A5307EF63EB5C5E02C89FC6C20F6D9D89E7D91FE470 +B72BEFDA23F5DF76BE05AF4CE93137A219ED8A04A9D7D6FDF37E6B7FCDE0D90B +986423E5960A5D9FBB4C956556E8DF90CBFAEC476FA36FD9A5C8175C9AF513FE +D919C2DDD26BDC0D99398B9F4D03D6A8F05B47AF95EF28A9C561DBDC98C47CF5 +5250011D19E9366EB6FD153D3A100CAA6212E3D5D93990737F8D326D347B7EDC +4391C9DF440285B8FC159D0E98D4258FC57892DDF753642CD526A96ACEDA4120 +788F22B1D09F149794E66DD1AC2C2B3BC6FEC59D626F427CD5AE9C54C7F78F62 +C36F49B3C2E5E62AFB56DCEE87445A12A942C14AE618D1FE1B11A9CF9FAA1F32 +617B598CE5058715EF3051E228F72F651040AD99A741F247C68007E68C84E9D1 +D0BF99AA5D777D88A7D3CED2EA67F4AE61E8BC0495E7DA382E82DDB2B009DD63 +532C74E3BE5EC555A014BCBB6AB31B8286D7712E0E926F8696830672B8214E9B +5D0740C16ADF0AFD47C4938F373575C6CA91E46D88DE24E682DEC44B57EA8AF8 +4E57D45646073250D82C4B50CBBB0B369932618301F3D4186277103B53B3C9E6 +DB42D6B30115F67B9D078220D5752644930643BDF9FACF684EBE13E39B65055E +B1BD054C324962025EC79E1D155936FE32D9F2224353F2A46C3558EF216F6BB2 +A304BAF752BEEC36C4440B556AEFECF454BA7CBBA7537BCB10EBC21047333A89 +8936419D857CD9F59EBA20B0A3D9BA4A0D3395336B4CDA4BA6451B6E4D1370FA +D9BDABB7F271BC1C6C48D9DF1E5A6FAE788F5609DE3C48D47A67097C547D9817 +AD3A7CCE2B771843D69F860DA4059A71494281C0AD8D4BAB3F67BB6739723C04 +AE05F9E35B2B2CB9C7874C114F57A185C8563C0DCCA93F8096384D71A2994748 +A3C7C8B8AF54961A8838AD279441D9A5EB6C1FE26C98BD025F353124DA68A827 +AE2AF8D25CA48031C242AA433EEEBB8ABA4B96821786C38BACB5F58C3D5DA011 +85B385124C2B6534F3CD1866AF92009D93B97F763AA3CF46C60636D7FC1564CF +1DDFBC12CA37D27A79B11F2AFF2D70DBEE03CF1DFA5B864A2DC22266E4FA43DC +3F2CC229231F1F72874E6A74A90E8003B9AF1BFAA55C071FDDE5C94E4AE3C5BF +936EDFD4164624881410AB9EF0593F823D40BA7D059992104D08E41EBAD8F276 +A84EE2C9AEBC7CCB72AA6B6E6FE52293DC7BC34C2D1B69418392608FC5920291 +733654FA401E05F3E647B1C6AF4BECC3E802F9963344B05EC3DE8C774293CDB4 +3F057D6F258BD341848FA7FDCFD4D1923FCAB51FA8ADAE6D9F19C1FFA6EB5E9F +ECF844CEC6C1320D3F00C7259EF5812526F58248C61F89A42D9C9288CA8076FA +77E1C950940D8D6A7D852A0D0ABEBF2EDEDCDF6DDE0C8CCAC8DA9B28207D9CF8 +46446E1153D8D8795EE914B12349137D4BE461BCF5A6A3CF15FA5B9E91EB9B90 +0483916D0CD40EDC29EB0B996B16462A64F3B19B57802D9AFE3F1D91D9A8553C +531EB8B4E975037ED620EED3020388BFE705958B1E3AD4638B9CC8644C2F4024 +5DACD97151C3DF7A448CC3 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +cleartomark +%%EndFont +%%BeginFont: CMMI10 +%!PS-AdobeFont-1.1: CMMI10 1.100 +%%CreationDate: 1996 Jul 23 07:53:57 +% Copyright (C) 1997 American Mathematical Society. All Rights Reserved. +11 dict begin +/FontInfo 7 dict dup begin +/version (1.100) readonly def +/Notice (Copyright (C) 1997 American Mathematical Society. All Rights Reserved) readonly def +/FullName (CMMI10) readonly def +/FamilyName (Computer Modern) readonly def +/Weight (Medium) readonly def +/ItalicAngle -14.04 def +/isFixedPitch false def +end readonly def +/FontName /CMMI10 def +/PaintType 0 def +/FontType 1 def +/FontMatrix [0.001 0 0 0.001 0 0] readonly def +/Encoding 256 array +0 1 255 {1 index exch /.notdef put} for +dup 59 /comma put +dup 76 /L put +dup 85 /U put +dup 102 /f put +dup 103 /g put +dup 104 /h put +dup 105 /i put +dup 110 /n put +dup 120 /x put +readonly def +/FontBBox{-32 -250 1048 750}readonly def +/UniqueID 5087385 def +currentdict end +currentfile eexec +D9D66F633B846A97B686A97E45A3D0AA0529731C99A784CCBE85B4993B2EEBDE +3B12D472B7CF54651EF21185116A69AB1096ED4BAD2F646635E019B6417CC77B +532F85D811C70D1429A19A5307EF63EB5C5E02C89FC6C20F6D9D89E7D91FE470 +B72BEFDA23F5DF76BE05AF4CE93137A219ED8A04A9D7D6FDF37E6B7FCDE0D90B +986423E5960A5D9FBB4C956556E8DF90CBFAEC476FA36FD9A5C8175C9AF513FE +D919C2DDD26BDC0D99398B9F4D03D5993DFC0930297866E1CD0A319B6B1FD958 +9E394A533A081C36D456A09920001A3D2199583EB9B84B4DEE08E3D12939E321 +990CD249827D9648574955F61BAAA11263A91B6C3D47A5190165B0C25ABF6D3E +6EC187E4B05182126BB0D0323D943170B795255260F9FD25F2248D04F45DFBFB +DEF7FF8B19BFEF637B210018AE02572B389B3F76282BEB29CC301905D388C721 +59616893E774413F48DE0B408BC66DCE3FE17CB9F84D205839D58014D6A88823 +D9320AE93AF96D97A02C4D5A2BB2B8C7925C4578003959C46E3CE1A2F0EAC4BF +8B9B325E46435BDE60BC54D72BC8ACB5C0A34413AC87045DC7B84646A324B808 +6FD8E34217213E131C3B1510415CE45420688ED9C1D27890EC68BD7C1235FAF9 +1DAB3A369DD2FC3BE5CF9655C7B7EDA7361D7E05E5831B6B8E2EEC542A7B38EE +03BE4BAC6079D038ACB3C7C916279764547C2D51976BABA94BA9866D79F13909 +95AA39B0F03103A07CBDF441B8C5669F729020AF284B7FF52A29C6255FCAACF1 +74109050FBA2602E72593FBCBFC26E726EE4AEF97B7632BC4F5F353B5C67FED2 +3EA752A4A57B8F7FEFF1D7341D895F0A3A0BE1D8E3391970457A967EFF84F6D8 +47750B1145B8CC5BD96EE7AA99DDC9E06939E383BDA41175233D58AD263EBF19 +AFC0E2F840512D321166547B306C592B8A01E1FA2564B9A26DAC14256414E4C8 +42616728D918C74D13C349F4186EC7B9708B86467425A6FDB3A396562F7EE4D8 +40B43621744CF8A23A6E532649B66C2A0002DD04F8F39618E4F572819DD34837 +B5A08E643FDCA1505AF6A1FA3DDFD1FA758013CAED8ACDDBBB334D664DFF5B53 +95601766758C197F327101A9C9BF396ED625E27A7791ADF7474135C50F2F927A +5B5E332A003F858399565E4C02931D19AC2866CEFAB2288ACA215F2B7BE37156 +89009B14D623E0A872AC17AA52D29EA6E8D725A05A300AAD937745F61803544E +978846734C4C8FEA576A5D77903920CF4531C051776BBDF99ABD8C09849E586C +ED0E1D51A0047D2FF9097EA10DE0E397D69BC302D7A949CC435EE46C508FB6D6 +DAA66F2EDD3A6881D50A440A702018A99102DE5039F7CA1EF9F4C36D5C66AA4C +97C81079C961F48C6EC9E1C26E3740945443C9A262373410B96043CF52CA074A +D18DAFCE0ADE27C2C4A109C21C1B2A8E2F9DF1F14ED57195984F76A5B4213F69 +53C017777402DB63066D528BD2C690959CFE72FAE34C98CA3E797C3CE2B8544E +143B2BB6D7ED137528BC8BB4AB4BB49A295C43C96E92D2D4AA0157DD37CFE2DA +921259A6876045871A994E1316BD39142279BEED0AFCAE7F8D847650D409C934 +D8D16486AC153C8C6F5849270F71DBB5A744A258D5EF64F8819025F49B5A3D29 +889F9CE6CAFB1A44F503559B63B9BEB727C9FD6F99F1E618DEC55C349E1D24BA +3E4599AC645E89E2852D0E152DC94465071B3835EDC93C2924778DFAC1664734 +98F5583DDF83315203AAF78897CE1768F22083276F6D29D07C72CE4B3FF6F293 +28DC673F80626F8654E4FCF6A0263C1DB7AC8F63790729256F9B969908F3A176 +05D7AD6ED5F8E8AF79890282AE7B4C55AEE6526920983A72C5876DE620CF4E3A +7D1376FEF0B296F62C5C29D8D9BEE6B622AAFB66335001F92DAA1E119CFD5101 +08FCB0F238A64FCF56A62C7C08C0871C8D15DB0374C53D39CCD8B1058BAA3FAF +F9785E2D17FCE278B5179EB8AE77B6F1ADBDA6284B0658A07D91B044ABD82EE8 +C9F1763A966496728615DD1EBAB159D7CF6168DBB2582815DA6733785828DF75 +D6848392D3E479E5527DFC967F36D3D66CA6FE01FC6FA9BF6AD401051013DE6A +C69971B1271DFE6ED6A8B53B394CE11FEE75CB1F9AB278A74FD2765FFA3773F9 +F61B5B11C462CE38287536B946E7BD1F8AE0C8F5804B04AFDBB624A2489DAE07 +903F90656C96D1E1C2101FBB9B48C66BFED1B572CEEA04A16AAFE734E754251F +EC12CAF4D56AA5A936D40CBB44E76FF4780B8594967138A1E3092254DB2D4C2C +CDECE9AF76FAF9B3DED9847C79C1723CDD328E4B0B15566C6CD8490ADFEB9169 +418B34C36EF4FB43EF7FB5F1BFE7F795E85FEBA443DCABD076418BA94DAE6505 +D4E6075D792C0C1A6BDFF56326FBA965DFB9519F072BBB8CA486D4C9AA6FCF62 +3CDACB91B41C69837DB4E6DACD0AC582A044D526E340343720AED1742DC4E52F +67579B3A625C4B5E508BCFF3DA667DAE69B25F9D50996033797C42D7CBD85F99 +AB2CDCF739E3B2C6AEA3C315AC2D0F0D48B293B1397A9C1E304260CD8D0C3497 +27385284419D6B3BFCD701C367149332FA1A58EAA22A193C24375D40482129C0 +55BD4147CF597B64FD1F3F3545A03235B6918790D39B7473FE8AE5ED218500D2 +1F6B8EE7632762D06578544C16D9D3866B4A8295904C95CE224E15044770C7B8 +F7408C215A0FA286CAE554D3C51D6BF20B33F4890784816A1AD1B202C381DA82 +01CBEFC0B043181DCD849BCCF035C87708B6E3A9CE4D68B61E35B9CF54123A30 +0939400BA136E6CD4D30F42259ADDAAC17D613E6998BBE4F37C414F397D802AF +83EB5B4247C648B834C3F59C566F252EACE08706E410299F72BEAB9A49274E5E +74F834B4A5983F4C00932124B5D9DFA54E5EF7C1CB9A97C29B49BBCE6F00AE13 +E9CB172D2033E719841728DAB47C858BA8C0687B844B7FC5C2513F5A88A9E5DF +436A28193F1C9A42F840634CCB6681EFC5249080769728E330520A5D6D50164C +0C9A8456535BC89E45BDA70C62CC42C5E750470EFAE512202D95E5BAF604352E +8001E29161B7D6FB6CAD331E42E636021B2854923894715B496038F4AEDBD1E9 +12CC6F15B440C87B8633C43B5D696AFE0C8ACDDC98503A6B3F8685987D178FD6 +E3E8DC9763CCB10ED3D8E065CF3354496D648053B2F0B7B5596528AA91EB6F7D +F7E856ECB8DDB8523CAB5CB6349827450C58A3B007CB9928AF1E98DF77D84B4A +A97B85CEC023289C82A2189AB947C56BAA64911653C2FFFB4D546F3A08821136 +14E904163C9F1CBC64BCC368CBE5764423BB308364B8CA907F38687A153BB01F +6BAE773B21DB3FFE55F9523A52C6286FA2C090F4B8EA11A7C793AC55AAEDDF0C +5E9219B11A940F1ACDE2E124F42F040C9B29D8A56099B0592E1FC33C42B5BAF5 +5CD5E0997B66D81132C4DEE5A9B34AB0761164E23B1418D9AF2EF466EE648BF7 +B550A0559B37AA4EEFE096D5B7B65A891FBB0364CDB8FAC49A7011152CA04B0C +4A91E982CF0E718DBDCAE97F90BC2D22EEA14CDE4003702563D5E02D758A3839 +4A4DDC3DF05069E1F23CB5B5ED68DBFDD1E26FF41967D5158056D86DE8BFAE94 +407645A693988C796417224C91661505FA3983863E2563E4228A5E76BA5E72B9 +10C08AF95D0C4C29E812EF8B3E2CD401562C1C7A35E49054D492DE9712D89C49 +FCB524E3D479A05DABA3D774E30F247A9287407468809AB93E53C3F9B5F5A6D7 +74F447C46BDA6AC95BBFF5A39268259C1E4A4C16FBE30C2DAD58C1D3F9DF5887 +CFE667D2E29DDBA05CE796355F0E1EC3A10FA0421074651E0B584FBD4A04D4C1 +3B4E8E729EB0F7676958F4A3677504132AEAF0DF00F781E4CC4E055917D0F363 +327C3C8E48E75675D425B02D4387269FC8487A325155B0335D +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +cleartomark +%%EndFont +%%BeginFont: CMR10 +%!PS-AdobeFont-1.1: CMR10 1.00B +%%CreationDate: 1992 Feb 19 19:54:52 +% Copyright (C) 1997 American Mathematical Society. All Rights Reserved. +11 dict begin +/FontInfo 7 dict dup begin +/version (1.00B) readonly def +/Notice (Copyright (C) 1997 American Mathematical Society. All Rights Reserved) readonly def +/FullName (CMR10) readonly def +/FamilyName (Computer Modern) readonly def +/Weight (Medium) readonly def +/ItalicAngle 0 def +/isFixedPitch false def +end readonly def +/FontName /CMR10 def +/PaintType 0 def +/FontType 1 def +/FontMatrix [0.001 0 0 0.001 0 0] readonly def +/Encoding 256 array +0 1 255 {1 index exch /.notdef put} for +dup 40 /parenleft put +dup 41 /parenright put +dup 43 /plus put +dup 48 /zero put +dup 49 /one put +dup 50 /two put +dup 53 /five put +dup 61 /equal put +readonly def +/FontBBox{-251 -250 1009 969}readonly def +/UniqueID 5000793 def +currentdict end +currentfile eexec +D9D66F633B846A97B686A97E45A3D0AA052A014267B7904EB3C0D3BD0B83D891 +016CA6CA4B712ADEB258FAAB9A130EE605E61F77FC1B738ABC7C51CD46EF8171 +9098D5FEE67660E69A7AB91B58F29A4D79E57022F783EB0FBBB6D4F4EC35014F +D2DECBA99459A4C59DF0C6EBA150284454E707DC2100C15B76B4C19B84363758 +469A6C558785B226332152109871A9883487DD7710949204DDCF837E6A8708B8 +2BDBF16FBC7512FAA308A093FE5CF7158F1163BC1F3352E22A1452E73FECA8A4 +87100FB1FFC4C8AF409B2067537220E605DA0852CA49839E1386AF9D7A1A455F +D1F017CE45884D76EF2CB9BC5821FD25365DDEA6E45F332B5F68A44AD8A530F0 +92A36FAC8D27F9087AFEEA2096F839A2BC4B937F24E080EF7C0F9374A18D565C +295A05210DB96A23175AC59A9BD0147A310EF49C551A417E0A22703F94FF7B75 +409A5D417DA6730A69E310FA6A4229FC7E4F620B0FC4C63C50E99E179EB51E4C +4BC45217722F1E8E40F1E1428E792EAFE05C5A50D38C52114DFCD24D54027CBF +2512DD116F0463DE4052A7AD53B641A27E81E481947884CE35661B49153FA19E +0A2A860C7B61558671303DE6AE06A80E4E450E17067676E6BBB42A9A24ACBC3E +B0CA7B7A3BFEA84FED39CCFB6D545BB2BCC49E5E16976407AB9D94556CD4F008 +24EF579B6800B6DC3AAF840B3FC6822872368E3B4274DD06CA36AF8F6346C11B +43C772CC242F3B212C4BD7018D71A1A74C9A94ED0093A5FB6557F4E0751047AF +D72098ECA301B8AE68110F983796E581F106144951DF5B750432A230FDA3B575 +5A38B5E7972AABC12306A01A99FCF8189D71B8DBF49550BAEA9CF1B97CBFC7CC +96498ECC938B1A1710B670657DE923A659DB8757147B140A48067328E7E3F9C3 +7D1888B284904301450CE0BC15EEEA00E48CCD6388F3FC390E75D51F36C3E61E +E84B5AD036ADADEBD4F8D399AA559B34270D370DEDF077D1D49253F313C333CB +F22FD740EDE076FE3383503F159888E77132A06528CEBA5BB0E57C07D36B73D7 +C81B71200D95D73A1AD33BBA5CA3E34B94447EAB8D27625CBFF13B56F87A9B74 +4B52A09BAB0AABD5E398B1E5E9868BC080EFC7ECBDA4D6817C3255A51A814A04 +0839172E2CCECB4F6E7B5B6B3B61D5858256AD27D93969EBB34C7EE68BF805D0 +39CA6AC7DECCD1A395E7BA297AB0E97B3290EDAED775EAB0D7D553F222A3B014 +FFA358EE448BBB24E1B44CE0BB474DFA01B0F4C4964248444FCA4DDEA8FDA9B8 +82F96DCBEF94CAC9C8F48922899CB1E7D70F650E6471E5408C44554E72599D97 +BC1D32360ECFB378192605E726A3DDA7E5B02736CEB7BE8A5C27AE952F4946D0 +1DD1D65C1D50D0317984B781D64B6075D35EC1E3507FD4FE2E7097A0EE116EEC +3497D2D84B19F68EBF7125FB02920466AE4FE25A3C3068A83A513556D05359A3 +93B6C6929BA47044787EEBA3A38E8266CF1D13DB69779644DF8AFE2C2C5C81F9 +75CBC9CA07E6CB70211CA62FD7CF596132333970E5233AAFBF984EC110664810 +AEFBADCE663CADF91D36D1587C5D7E7F63E3A674856AD7CDB99CD276D3659ED0 +CA0FDC17251E69BA7F2F3AC57257831C31AFBB0DADF44F7E6EF84D63C03E75FF +886FFDAF8153EA8E0779E46935AB0AEFC84AC2061291D39E5F67FB75BEA48EDA +030512CDB14B16D466CFBC58D3764B83AF5C00D05A3F052F53BBE4E1417773CA +BDBEAC50BB7BFF981255BDA6650870E4D67BCB80A63BA050F2650934CB6E742B +B2B2A115C1F9827C979E8F2E92C0A1F428288643C8A27B7105587366E1BFF1FB +056DE92CAD4A7F391A483DE4E9930E8C5BA9B215F1E3FA4798A1740A9B72810A +44CD1D1ECAC8ED7BA3655C4EEF6BF28A2B0B23B0BF783A4FBDDB1246B5EEA601 +6440F98C0A3B6ED360561479EA83990A78A0F4608698B30FE6476AED9349D11F +FB467D3C19D7A3539B8A2DA0C54454A231B87FB441A1BE6893E0F67081E8FF09 +FC20412C452D8227D4BA7665EA8F14A1987845CF8570EDD926F4EF5F2D85DB99 +736D7A939D4313F589033FA135D6366EB8B63C026357360A9E8717656ADABA76 +11B9D672B7D57F1422CAEA295A774CB1F6BEAE51A7A9F7EACF6F22CC6412F1D6 +9DDF884EB94F91B5F301039EE962C51F7FCEF8319CE80F46A7E3187EE60342DB +4057C2374CF68AAD30B5979B24D41ED8A803A1E6EA845D7E7675031A2D4257D8 +4BE91A75006673CE3C24AA4C4138EED6DE5147FD16049BC523D54F26BF951AAC +85157DB39E8B38798267AE2E5266331CFAA0E4D18D2F5C50277BE056498E569E +90AB0A7127F94F0EEC3FC2DC7BF421A2A855318646BACC78EC03D14CC41AB9CA +61649659F81614F8FA9E052F37445DBAF2B0873A06015E16A268544FB047AD0A +E9EF324844E8CA272D00944D54B691CA137E1CF59B69F59D5F9A40EEA081C9EC +6AD88DB832E588F5AACA900198105A8D59C215DCD387B32FE34E9B8476AB5C7A +B739EEE6840ACBFDC79501A04FFB2A57D3A4D3D181D68F074DFB0E828C41FBE3 +E7D0F2A7CE0AC1C7ED09FD9C6E085C89E8BC46BA83A8CED54EDB6EDE1B55B349 +84C37F33BB71994A8EF29050A902448E21CA0B2B5E9DDCF43ACBB79CC841E7EA +5D8BA0D8C18DDFB3B72559BF6251A5F026FAEB035509D20058FEC5FDB1B7E329 +3E299B4FBDF2BD3A5D27035BB8732C3688C3C203D1664522CEBC8BCAC7D4E643 +6490E8CAE79FB51F9285A64099719EA841CD4710392D94660920608397214CEA +588A9CFC233DA75C7C8F381ECEA4065F431122D472D333B2E260DB32F5CCCB15 +56BB953DEC3B6E451B212ABBE079888B73C48744CF5A9C1DCB47C423C647A94F +2B4358B020B2C5FDF1D4B7BE081BC0F4EA86359DFE9BDCC1CBDA475618A71ED4 +F61834FCC9DAA616C7C8D2407333ECE57AD5F5F43FD077EB12C2310BF7EB1EFC +1EAEE06F0891DEFD32AF69082D203207524CA6DC8005C22C1C1CE2C6CBED42B3 +122148A0A6BAFC0DEEEC37594B68494BB5EF16E510C1CD4BF3F6597F98E5362C +544F51DC368425AD6A867D1E6E9AB208C77982536D56581A539597DC172F1D09 +BF027427518C4CCD96BD4321DD8FF54C8D034F66F32F3A2DDFA05E33E5C5408B +8C8511FE0E8F52F38475B84E2A2F5F7B09F8F92D8E1DE2754E683A39EE71BD78 +EFFA9E0804386F6B98CB37112C4A8844C8E2F26C8920CD18089BE16D20922DD4 +AF2EFCE40BCFFB79A001E1DFF89AC67B02FFB09FD38354B57A5FAD9BA3640064 +E4CB7CFC355B5384699A57E86513CA2F89B938688A3F42A6FDBC6E92D50C050E +B96AFCE7691A96AEC83213FC00BD81EA3895 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +cleartomark +%%EndFont +%%BeginFont: CMSY10 +%!PS-AdobeFont-1.1: CMSY10 1.0 +%%CreationDate: 1991 Aug 15 07:20:57 +% Copyright (C) 1997 American Mathematical Society. All Rights Reserved. +11 dict begin +/FontInfo 7 dict dup begin +/version (1.0) readonly def +/Notice (Copyright (C) 1997 American Mathematical Society. All Rights Reserved) readonly def +/FullName (CMSY10) readonly def +/FamilyName (Computer Modern) readonly def +/Weight (Medium) readonly def +/ItalicAngle -14.035 def +/isFixedPitch false def +end readonly def +/FontName /CMSY10 def +/PaintType 0 def +/FontType 1 def +/FontMatrix [0.001 0 0 0.001 0 0] readonly def +/Encoding 256 array +0 1 255 {1 index exch /.notdef put} for +dup 162 /periodcentered put +dup 178 /bullet put +dup 102 /braceleft put +dup 103 /braceright put +readonly def +/FontBBox{-29 -960 1116 775}readonly def +/UniqueID 5000820 def +currentdict end +currentfile eexec +D9D66F633B846A97B686A97E45A3D0AA052F09F9C8ADE9D907C058B87E9B6964 +7D53359E51216774A4EAA1E2B58EC3176BD1184A633B951372B4198D4E8C5EF4 +A213ACB58AA0A658908035BF2ED8531779838A960DFE2B27EA49C37156989C85 +E21B3ABF72E39A89232CD9F4237FC80C9E64E8425AA3BEF7DED60B122A52922A +221A37D9A807DD01161779DDE7D31FF2B87F97C73D63EECDDA4C49501773468A +27D1663E0B62F461F6E40A5D6676D1D12B51E641C1D4E8E2771864FC104F8CBF +5B78EC1D88228725F1C453A678F58A7E1B7BD7CA700717D288EB8DA1F57C4F09 +0ABF1D42C5DDD0C384C7E22F8F8047BE1D4C1CC8E33368FB1AC82B4E96146730 +DE3302B2E6B819CB6AE455B1AF3187FFE8071AA57EF8A6616B9CB7941D44EC7A +71A7BB3DF755178D7D2E4BB69859EFA4BBC30BD6BB1531133FD4D9438FF99F09 +4ECC068A324D75B5F696B8688EEB2F17E5ED34CCD6D047A4E3806D000C199D7C +515DB70A8D4F6146FE068DC1E5DE8BC57030ACE57A0A31C99BEDB251A0ECAD78 +253AB3339E847FBB1AF693606A973F6ECD887C325CA59C6A4A9AC48AF5551D10 +EE26B8C4DA13F670D3F0C09187B9AB37F2BA6A32F8D363393D22215650EEE7F8 +DFB1378390C44F36098EA2DA6CB943DACFB8AECD62E46F120BE7A15C19200094 +7975CA278BAF5E155531F90FCBFE67D2AC15BA6E3B15FEF09F697956F198D111 +16292151DECACDAF2B2CF42B82DE6D4515735744887745770F8D8656BAEEFC04 +2F6A832F466D4244F1F9998BF49A413F094108FC90F586AEB324888BD885F2A1 +C749504E6DCB10F6A2B797826939AFA46BD208A268FB4C6635264B2B39F6E11E +34ED5B3D02E6C9178BFE61AE0A0B6B789E394F8A33730EC5E4484F2D962268F5 +8FD36EAD6CF68C7120E82FD8B2EA91095227CFF985054557361FD9B1E8FACB8C +A17AD35513D4D69B5D52470A6B4796299442430E66AAB39A574CF4C4D0838C52 +B675FB04C646FE52C599EA039302B200CEA102986E6549225D22F30455B7947B +5DCF0190B5296E12FA026272B1D2076B630CABB8F71589ECB69B95486A650A09 +05D11C00F0909A7228A107C7D27074FC6B5380FB3534816E122D65369D70C68E +98E1951DA9756B3CD665F378B661506661175A89D37889CDB07D1692988875EE +878DC0771EF29DDB382287584FE12E47FD7CEE6C130E2D2B3028C8C54B83C977 +26845C0960D62A50B290605368BE2568340524244ABCEE470B683E92456DEE76 +228DCCBDBC688458DF63F2C1E4D8BA46657CB79B9E28179AD2459603874FC200 +CAB2ABDBD725DB89EB7E7C5DFE03826FC7EA65F57CF87E382A976D70F44596B5 +53C6DC34FE7F2B295D67AA8A550F1DF1D040237352D42F14D1D0E7A23318E53B +BA0958CC11E47508EE8D9DCAB8116452978F0963222D14739F8E890A39AB41BC +B66B92570A18 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +cleartomark +%%EndFont +%%BeginFont: CMMI12 +%!PS-AdobeFont-1.1: CMMI12 1.100 +%%CreationDate: 1996 Jul 27 08:57:55 +% Copyright (C) 1997 American Mathematical Society. All Rights Reserved. +11 dict begin +/FontInfo 7 dict dup begin +/version (1.100) readonly def +/Notice (Copyright (C) 1997 American Mathematical Society. All Rights Reserved) readonly def +/FullName (CMMI12) readonly def +/FamilyName (Computer Modern) readonly def +/Weight (Medium) readonly def +/ItalicAngle -14.04 def +/isFixedPitch false def +end readonly def +/FontName /CMMI12 def +/PaintType 0 def +/FontType 1 def +/FontMatrix [0.001 0 0 0.001 0 0] readonly def +/Encoding 256 array +0 1 255 {1 index exch /.notdef put} for +dup 60 /less put +dup 62 /greater put +readonly def +/FontBBox{-30 -250 1026 750}readonly def +/UniqueID 5087386 def +currentdict end +currentfile eexec +D9D66F633B846A97B686A97E45A3D0AA0529731C99A784CCBE85B4993B2EEBDE +3B12D472B7CF54651EF21185116A69AB1096ED4BAD2F646635E019B6417CC77B +532F85D811C70D1429A19A5307EF63EB5C5E02C89FC6C20F6D9D89E7D91FE470 +B72BEFDA23F5DF76BE05AF4CE93137A219ED8A04A9D7D6FDF37E6B7FCDE0D90B +986423E5960A5D9FBB4C956556E8DF90CBFAEC476FA36FD9A5C8175C9AF513FE +D919C2DDD26BDC0D99398B9F4D03D6A8F05B47AF95EF28A9C561DBDC98C47CF5 +5250011D19E9366EB6FD153D3A100CAA6212E3D5D93990737F8D326D347B7EDC +4391C9DF440285B8FC159D0E98D4258FC57892DCC57F7903449E07914FBE9E67 +3C15C2153C061EB541F66C11E7EE77D5D77C0B11E1AC55101DA976CCACAB6993 +EED1406FBB7FF30EAC9E90B90B2AF4EC7C273CA32F11A5C1426FF641B4A2FB2F +4E68635C93DB835737567FAF8471CBC05078DCD4E40E25A2F4E5AF46C234CF59 +2A1CE8F39E1BA1B2A594355637E474167EAD4D97D51AF0A899B44387E1FD933A +323AFDA6BA740534A510B4705C0A15647AFBF3E53A82BF320DD96753639BE49C +2F79A1988863EF977B800C9DB5B42039C23EB86953713F730E03EA22FF7BB2C1 +D97D33FD77B1BDCC2A60B12CF7805CFC90C5B914C0F30A673DF9587F93E47CEA +5932DD1930560C4F0D97547BCD805D6D854455B13A4D7382A22F562D7C55041F +0FD294BDAA1834820F894265A667E5C97D95FF152531EF97258F56374502865D +A1E7C0C5FB7C6FB7D3C43FEB3431095A59FBF6F61CEC6D6DEE09F4EB0FD70D77 +2A8B0A4984C6120293F6B947944BE23259F6EB64303D627353163B6505FC8A60 +00681F7A3968B6CBB49E0420A691258F5E7B07B417157803FCBE9B9FB1F80FD8 +CA0DA1186446DD565542BCCC7D339A1EB34C7F49246E8D72E987EB477C6DB757 +99AF86CEBCD7605C487A00CD2CD093098182DC57B20D78ECE0BECF3A0BF88EBA +C866DB19F34BBBED6634AFC0F08D2AFB2A92578A6F8B4ADCD6594737FF6EED7D +5B536DA9E3E2CADB40DB7C600EA4D100D33C3B92B1CF857E012C4EB370BA8295 +55B50047CD58E912E67E22C1B92F41D0BEE742201DF198F3766AE35EA71D8195 +A8C94D661C40D718CB09497485FAA34204229AECFE644C93FFDA54C789E4F751 +3D2519F7CB9E79B2ABE3101DF2EBFAD375469CDC687FB3DC2833EDC0F946B41F +F28D72FFF2A9B8B0D76DC542537612E2BE0F3FB9601C897386359C55E867A547 +F872005F5C56C6EC5E9685E03D7A82653BE8B69741C4DF332AEEB2AA450B23F3 +EABD5ED060606CC7DB1762632EC3C6C4A66ADAF61A97D949DEA5156B4CF34765 +67AC3F10AE17199A710A882D47979F9D41AA2CB794648BE47479F0B00E18BF04 +923F54CEC1214BAFA39BB65ECB013875899E9901B7882D16D2E2C97AD3353668 +A6070081E4DC627AF9192599F5876369908FBDFA11E8D6CB2E83896E9C897CEC +FD1D25651D66A333AF531FF74E1B0DEB1E3D1B5B7D3FB9D1C8BF60517B31C8D2 +1C264F44BC9AF3D9BA5280D1618EED96C11ED24F789FAA263394C658DFCA8DE9 +D47D9E188E212F9EC1DCF449DFDAB8437FAB9EA9AF01AE1714E8F932855182 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +cleartomark +%%EndFont +TeXDict begin 39158280 55380996 1000 8000 8000 (cudd.dvi) +@start /Fa 137[538 674 1[472 472 8[337 2[404 538 606 +538 16[808 13[875 808 67[{ TeXBase1Encoding ReEncodeFont }12 +1212.12 /Times-BoldItalic rf /Fb 136[665 7[498 2[277 +108[{ TeXBase1Encoding ReEncodeFont }3 996.264 /Times-Italic +rf /Fc 204[470 470 470 470 48[{}4 885.568 /CMR8 rf /Fd +207[255 47[732{}2 885.568 /CMSY8 rf /Fe 133[442 498 498 +719 498 498 277 388 332 1[498 498 498 775 277 498 1[277 +498 498 332 442 498 442 498 442 9[940 719 719 609 11[719 +2[609 719 665 7[277 277 10[277 249 332 249 41[554 2[{ + TeXBase1Encoding ReEncodeFont }39 996.264 /Times-Roman +rf /Ff 201[332 332 332 332 332 332 49[{ TeXBase1Encoding ReEncodeFont } +6 664.176 /Times-Roman rf /Fg 201[443 443 443 443 443 +443 49[{ TeXBase1Encoding ReEncodeFont }6 885.568 /Times-Roman +rf /Fh 130[727 727 727 727 727 727 727 727 727 727 727 +727 727 727 727 727 727 727 727 727 727 727 727 727 727 +727 727 727 727 1[727 1[727 727 727 727 1[727 1[727 727 +727 727 727 727 727 727 727 727 727 2[727 727 727 727 +727 727 727 727 727 727 727 727 727 727 727 727 727 727 +727 727 727 727 727 727 727 727 727 727 727 727 727 727 +727 727 2[727 1[727 727 727 33[{ TeXBase1Encoding ReEncodeFont }84 +1212.12 /Courier rf /Fi 133[590 664 1[959 664 739 442 +517 590 739 739 664 739 1107 369 739 1[369 739 664 442 +590 739 590 739 664 6[886 2[1328 959 959 886 739 959 +1[812 1033 1[1254 886 1033 1[517 1033 1033 812 1[959 +959 886 959 7[664 664 664 664 664 664 664 664 664 664 +369 332 46[{ TeXBase1Encoding ReEncodeFont }56 1328.35 +/Times-Bold rf /Fj 145[571 110[{}1 885.568 /CMMI8 rf +/Fk 135[693 9[728 4[418 698 578 593 16[828 8[825 16[337 +59[{}9 1212.12 /CMMI10 rf /Fl 194[943 7[606 2[606 606 +606 4[943 1[471 471 40[{}8 1212.12 /CMR10 rf /Fm 152[606 +606 86[606 13[337 1[{}4 1212.12 /CMSY10 rf /Fn 133[472 +538 538 808 538 606 337 472 472 606 606 606 606 875 337 +538 337 337 606 606 337 538 606 538 606 606 6[674 1[741 +1010 741 875 674 606 741 875 741 875 808 1010 674 808 +538 404 875 875 741 741 875 808 741 741 7[606 1[606 3[606 +606 606 2[303 404 3[404 404 404 35[606 606 2[{ + TeXBase1Encoding ReEncodeFont }63 1212.12 /Times-Italic +rf /Fo 87[404 16[1212 606 1[538 538 24[538 606 606 875 +606 606 337 472 404 606 606 606 606 943 337 606 337 337 +606 606 404 538 606 538 606 538 3[404 1[404 741 875 875 +1144 875 875 741 674 808 875 674 875 875 1078 741 875 +472 404 875 875 674 741 875 808 808 875 5[337 337 606 +606 606 606 606 606 606 606 606 606 337 303 404 303 684 +1[404 404 404 1[1010 33[674 674 2[{ TeXBase1Encoding ReEncodeFont }82 +1212.12 /Times-Roman rf /Fp 105[606 27[538 606 606 875 +606 674 404 472 538 1[674 606 674 1010 337 674 1[337 +674 606 404 538 674 538 674 606 6[808 875 875 1212 875 +875 808 674 875 1[741 943 875 1144 808 2[472 943 943 +741 808 875 875 808 875 5[404 404 1[606 606 606 606 606 +606 606 606 606 1[303 1[303 691 3[404 36[674 2[{ + TeXBase1Encoding ReEncodeFont }64 1212.12 /Times-Bold +rf /Fq 135[797 1151 1[886 531 620 708 2[797 886 1328 +443 886 1[443 886 797 531 708 886 708 1[797 11[1151 1063 +1[1151 1[974 2[1505 3[620 1240 1240 2[1151 1151 1[1151 +10[797 797 797 797 797 797 5[909 3[531 39[{ + TeXBase1Encoding ReEncodeFont }38 1594.02 /Times-Bold +rf /Fr 193[1012 1[1012 60[{}2 1328.35 /CMMI12 rf /Fs +133[590 664 2[664 664 369 517 442 1[664 664 664 1033 +369 2[369 1[664 442 590 664 590 664 590 11[959 1[739 +12[739 812 959 886 886 1[1223 6[664 6[664 1[664 1[332 +1[332 44[{ TeXBase1Encoding ReEncodeFont }33 1328.35 +/Times-Roman rf /Ft 140[744 637 2[956 956 1488 532 956 +1[532 1[956 1[849 1[849 1[849 11[1381 2[1276 1[1064 11[1381 +1276 8[532 5[956 1[956 3[478 46[{ TeXBase1Encoding ReEncodeFont }21 +1912.83 /Times-Roman rf end +%%EndProlog +%%BeginSetup +%%Feature: *Resolution 8000dpi +TeXDict begin +%%PaperSize: A4 + end +%%EndSetup +%%Page: 1 1 +TeXDict begin 1 0 bop Black Black Black Black 10724 12498 +a Ft(CUDD:)478 b(CU)g(Decision)h(Diagram)g(P)-29 b(ackage)20777 +14933 y(Release)479 b(2.4.2)21909 18301 y Fs(F)-20 b(abio)332 +b(Somenzi)9599 19851 y(Department)h(of)g(Electrical,)f(Computer)-53 +b(,)333 b(and)g(Ener)-24 b(gy)332 b(Engineering)16816 +21400 y(Uni)-33 b(v)-20 b(ersity)334 b(of)e(Colorado)h(at)f(Boulder) +18774 22950 y Fr(<)p Fs(F)-20 b(abio@Colorado.EDU)p Fr(>)21015 +25644 y Fs(February)332 b(20,)g(2009)5978 30874 y Fq(Contents)5978 +33634 y Fp(1)1212 b(Intr)-22 b(oduction)30847 b(4)5978 +36351 y(2)1212 b(Ho)-12 b(w)303 b(to)g(Get)f(CUDD)27711 +b(5)7796 37857 y Fo(2.1)1273 b(The)303 b(CUDD)g(P)-18 +b(ackage)1207 b(.)606 b(.)g(.)g(.)g(.)g(.)g(.)g(.)h(.)f(.)g(.)g(.)g(.)g +(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)h(.)f(.)g(.)p Black 2275 +w(5)p Black 7796 39362 a(2.2)1273 b(CUDD)304 b(Friends)1050 +b(.)606 b(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)h(.)f(.)g(.)g(.)g(.)g +(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)h(.)f(.)g(.)p Black 2275 +w(5)p Black 5978 42080 a Fp(3)1212 b(User')-45 b(s)302 +b(Manual)29829 b(5)7796 43585 y Fo(3.1)1273 b(Compiling)303 +b(and)h(Linking)678 b(.)606 b(.)g(.)g(.)g(.)g(.)g(.)h(.)f(.)g(.)g(.)g +(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)h(.)f(.)g(.)p Black +2275 w(6)p Black 7796 45091 a(3.2)1273 b(Basic)303 b(Data)g(Structures) +648 b(.)606 b(.)g(.)g(.)g(.)g(.)g(.)g(.)h(.)f(.)g(.)g(.)g(.)g(.)g(.)g +(.)g(.)g(.)g(.)g(.)g(.)h(.)f(.)g(.)p Black 2275 w(6)p +Black 10584 46596 a(3.2.1)1454 b(Nodes)540 b(.)606 b(.)g(.)g(.)g(.)g(.) +g(.)g(.)g(.)g(.)g(.)g(.)h(.)f(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g +(.)g(.)h(.)f(.)g(.)p Black 2275 w(6)p Black 10584 48102 +a(3.2.2)1454 b(The)303 b(Manager)777 b(.)606 b(.)g(.)g(.)g(.)g(.)g(.)g +(.)h(.)f(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)h(.)f(.)g(.)p +Black 2275 w(7)p Black 10584 49607 a(3.2.3)1454 b(Cache)609 +b(.)d(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)h(.)f(.)g(.)g(.)g(.)g +(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)h(.)f(.)g(.)p Black 2275 +w(8)p Black 7796 51113 a(3.3)1273 b(Initializing)303 +b(and)g(Shutting)g(Do)-30 b(wn)303 b(a)g(DdManager)1016 +b(.)606 b(.)g(.)g(.)g(.)g(.)g(.)g(.)h(.)f(.)g(.)p Black +2275 w(8)p Black 7796 52618 a(3.4)1273 b(Setting)303 +b(P)-18 b(arameters)1136 b(.)606 b(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)h(.)f +(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)h(.)f(.)g(.)p +Black 2275 w(9)p Black 7796 54124 a(3.5)1273 b(Constant)303 +b(Functions)847 b(.)606 b(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)h(.)f(.)g(.)g +(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)h(.)f(.)g(.)p +Black 2275 w(9)p Black 10584 55629 a(3.5.1)1454 b(One,)304 +b(Logic)f(Zero,)f(and)i(Arithmetic)f(Zero)542 b(.)606 +b(.)g(.)g(.)g(.)g(.)g(.)g(.)h(.)f(.)g(.)p Black 2275 +w(9)p Black 10584 57134 a(3.5.2)1454 b(Prede\002ned)304 +b(Constants)639 b(.)606 b(.)g(.)g(.)h(.)f(.)g(.)g(.)g(.)g(.)g(.)g(.)g +(.)g(.)g(.)g(.)g(.)h(.)f(.)g(.)p Black 1669 w(10)p Black +10584 58640 a(3.5.3)1454 b(Background)440 b(.)606 b(.)g(.)g(.)g(.)g(.)g +(.)g(.)g(.)h(.)f(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)h(.)f(.) +g(.)p Black 1669 w(10)p Black 10584 60145 a(3.5.4)1454 +b(Ne)-30 b(w)304 b(Constants)838 b(.)606 b(.)g(.)g(.)g(.)g(.)g(.)h(.)f +(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)h(.)f(.)g(.)p +Black 1669 w(11)p Black 7796 61651 a(3.6)1273 b(Creating)303 +b(V)-135 b(ariables)346 b(.)606 b(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)h +(.)f(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)h(.)f(.)g(.)p +Black 1669 w(11)p Black 10584 63156 a(3.6.1)1454 b(Ne)-30 +b(w)304 b(BDD)f(and)h(ADD)f(V)-135 b(ariables)540 b(.)606 +b(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)h(.)f(.)g(.)p +Black 1669 w(11)p Black 10584 64662 a(3.6.2)1454 b(Ne)-30 +b(w)304 b(ZDD)f(V)-135 b(ariables)1043 b(.)606 b(.)g(.)g(.)h(.)f(.)g(.) +g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)h(.)f(.)g(.)p +Black 1669 w(12)p Black 7796 66167 a(3.7)1273 b(Basic)303 +b(BDD)h(Manipulation)579 b(.)606 b(.)g(.)g(.)g(.)g(.)h(.)f(.)g(.)g(.)g +(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)h(.)f(.)g(.)p Black +1669 w(12)p Black Black 25600 69672 a(1)p Black eop end +%%Page: 2 2 +TeXDict begin 2 1 bop Black Black 7796 7638 a Fo(3.8)1273 +b(Basic)303 b(ADD)g(Manipulation)513 b(.)606 b(.)g(.)g(.)g(.)g(.)h(.)f +(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)h(.)f(.)g(.)p +Black 1669 w(13)p Black 7796 9143 a(3.9)1273 b(Basic)303 +b(ZDD)g(Manipulation)647 b(.)606 b(.)g(.)g(.)g(.)g(.)h(.)f(.)g(.)g(.)g +(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)h(.)f(.)g(.)p Black +1669 w(14)p Black 7796 10649 a(3.10)667 b(Con)-48 b(v)-18 +b(erting)303 b(ADDs)f(to)i(BDDs)f(and)g(V)-73 b(ice)304 +b(V)-135 b(ersa)1126 b(.)606 b(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)h(.)f(.)g +(.)p Black 1669 w(15)p Black 7796 12154 a(3.11)667 b(Con)-48 +b(v)-18 b(erting)303 b(BDDs)g(to)g(ZDDs)f(and)i(V)-73 +b(ice)303 b(V)-135 b(ersa)352 b(.)606 b(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g +(.)h(.)f(.)g(.)p Black 1669 w(15)p Black 7796 13660 a(3.12)667 +b(V)-135 b(ariable)303 b(Reordering)h(for)e(BDDs)h(and)h(ADDs)853 +b(.)606 b(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)h(.)f(.)g(.)p +Black 1669 w(16)p Black 7796 15165 a(3.13)667 b(Grouping)303 +b(V)-135 b(ariables)783 b(.)606 b(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)h(.)f +(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)h(.)f(.)g(.)p +Black 1669 w(19)p Black 7796 16671 a(3.14)667 b(V)-135 +b(ariable)303 b(Reordering)h(for)e(ZDDs)919 b(.)606 b(.)g(.)h(.)f(.)g +(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)h(.)f(.)g(.)p +Black 1669 w(20)p Black 7796 18176 a(3.15)667 b(K)-30 +b(eeping)303 b(Consistent)g(V)-135 b(ariable)303 b(Orders)g(for)f(BDDs) +h(and)h(ZDDs)613 b(.)606 b(.)h(.)f(.)g(.)p Black 1669 +w(21)p Black 7796 19682 a(3.16)667 b(Hooks)713 b(.)606 +b(.)g(.)h(.)f(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)h(.)f(.)g +(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)h(.)f(.)g(.)p +Black 1669 w(21)p Black 7796 21187 a(3.17)667 b(The)303 +b(SIS/VIS)f(Interf)-12 b(ace)324 b(.)606 b(.)g(.)g(.)g(.)g(.)g(.)g(.)h +(.)f(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)h(.)f(.)g(.)p +Black 1669 w(22)p Black 10584 22693 a(3.17.1)848 b(Using)303 +b(the)g(CUDD)h(P)-18 b(ackage)304 b(in)f(SIS)322 b(.)606 +b(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)h(.)f(.)g(.)p +Black 1669 w(22)p Black 7796 24198 a(3.18)667 b(Writing)303 +b(Decision)g(Diagrams)f(to)h(a)h(File)749 b(.)606 b(.)g(.)g(.)g(.)g(.)g +(.)g(.)g(.)g(.)g(.)g(.)g(.)h(.)f(.)g(.)p Black 1669 w(23)p +Black 7796 25704 a(3.19)667 b(Sa)-24 b(ving)303 b(and)g(Restoring)g +(BDDs)1041 b(.)606 b(.)g(.)g(.)h(.)f(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.) +g(.)g(.)g(.)h(.)f(.)g(.)p Black 1669 w(25)p Black 5978 +28421 a Fp(4)1212 b(Pr)-22 b(ogrammer')-45 b(s)302 b(Manual)24937 +b(25)7796 29927 y Fo(4.1)1273 b(Compiling)303 b(and)h(Linking)678 +b(.)606 b(.)g(.)g(.)g(.)g(.)g(.)h(.)f(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g +(.)g(.)g(.)g(.)h(.)f(.)g(.)p Black 1669 w(25)p Black +7796 31432 a(4.2)1273 b(Reference)303 b(Counts)683 b(.)606 +b(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)h(.)f(.)g(.)g(.)g(.)g(.)g(.)g(.)g +(.)g(.)g(.)g(.)g(.)h(.)f(.)g(.)p Black 1669 w(25)p Black +10584 32938 a(4.2.1)1454 b(NULL)303 b(Return)g(V)-135 +b(alues)541 b(.)606 b(.)g(.)g(.)h(.)f(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g +(.)g(.)g(.)g(.)h(.)f(.)g(.)p Black 1669 w(26)p Black +10584 34443 a(4.2.2)1454 b Fn(Cudd)p 17161 34443 364 +45 v 437 w(Recur)-12 b(siveDer)-45 b(ef)480 b Fo(vs.)302 +b Fn(Cudd)p 29870 34443 V 437 w(Der)-45 b(ef)604 b Fo(.)i(.)g(.)g(.)g +(.)g(.)g(.)g(.)h(.)f(.)g(.)p Black 1669 w(27)p Black +10584 35949 a(4.2.3)1454 b(When)304 b(Increasing)e(the)i(Reference)f +(Count)h(is)e(Unnecessary)1153 b(.)606 b(.)p Black 1669 +w(27)p Black 10584 37454 a(4.2.4)1454 b(Saturating)303 +b(Increments)g(and)g(Decrements)1183 b(.)606 b(.)g(.)g(.)g(.)g(.)g(.)h +(.)f(.)g(.)p Black 1669 w(27)p Black 7796 38959 a(4.3)1273 +b(Complement)304 b(Arcs)478 b(.)606 b(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g +(.)h(.)f(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)h(.)f(.)g(.)p +Black 1669 w(28)p Black 7796 40465 a(4.4)1273 b(The)303 +b(Cache)480 b(.)607 b(.)f(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g +(.)h(.)f(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)h(.)f(.)g(.)p +Black 1669 w(28)p Black 10584 41970 a(4.4.1)1454 b(Cache)305 +b(Sizing)842 b(.)606 b(.)g(.)g(.)g(.)g(.)g(.)g(.)h(.)f(.)g(.)g(.)g(.)g +(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)h(.)f(.)g(.)p Black 1669 +w(29)p Black 10584 43476 a(4.4.2)1454 b(Local)303 b(Caches)710 +b(.)606 b(.)g(.)g(.)g(.)g(.)g(.)g(.)h(.)f(.)g(.)g(.)g(.)g(.)g(.)g(.)g +(.)g(.)g(.)g(.)g(.)h(.)f(.)g(.)p Black 1669 w(30)p Black +7796 44981 a(4.5)1273 b(The)303 b(Unique)g(T)-97 b(able)611 +b(.)606 b(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)h(.)f(.)g(.)g(.)g(.)g(.)g +(.)g(.)g(.)g(.)g(.)g(.)g(.)h(.)f(.)g(.)p Black 1669 w(30)p +Black 7796 46487 a(4.6)1273 b(Allo)-30 b(wing)303 b(Asynchronous)f +(Reordering)814 b(.)606 b(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g +(.)h(.)f(.)g(.)p Black 1669 w(32)p Black 7796 47992 a(4.7)1273 +b(Deb)-24 b(ugging)334 b(.)607 b(.)f(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.) +g(.)g(.)g(.)h(.)f(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)h(.)f +(.)g(.)p Black 1669 w(33)p Black 7796 49498 a(4.8)1273 +b(Gathering)303 b(and)g(Interpreting)g(Statistics)816 +b(.)606 b(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)h(.)f(.)g(.)p +Black 1669 w(33)p Black 10584 51003 a(4.8.1)1454 b(Non)304 +b(Modi\002able)f(P)-18 b(arameters)1164 b(.)606 b(.)g(.)g(.)g(.)g(.)g +(.)g(.)g(.)g(.)g(.)g(.)g(.)h(.)f(.)g(.)p Black 1669 w(34)p +Black 10584 52509 a(4.8.2)1454 b(Modi\002able)303 b(P)-18 +b(arameters)827 b(.)606 b(.)g(.)h(.)f(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g +(.)g(.)g(.)g(.)h(.)f(.)g(.)p Black 1669 w(37)p Black +10584 54014 a(4.8.3)1454 b(Extended)304 b(Statistics)e(and)h(Reporting) +809 b(.)606 b(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)h(.)f(.)g(.)p +Black 1669 w(39)p Black 7796 55520 a(4.9)1273 b(Guidelines)303 +b(for)f(Documentation)952 b(.)606 b(.)g(.)h(.)f(.)g(.)g(.)g(.)g(.)g(.)g +(.)g(.)g(.)g(.)g(.)g(.)h(.)f(.)g(.)p Black 1669 w(39)p +Black 5978 58237 a Fp(5)1212 b(The)303 b(C++)g(Interface)27225 +b(40)7796 59743 y Fo(5.1)1273 b(Compiling)303 b(and)h(Linking)678 +b(.)606 b(.)g(.)g(.)g(.)g(.)g(.)h(.)f(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g +(.)g(.)g(.)g(.)h(.)f(.)g(.)p Black 1669 w(40)p Black +7796 61248 a(5.2)1273 b(Basic)303 b(Manipulation)714 +b(.)606 b(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)h(.)f(.)g(.)g(.)g(.)g(.)g(.)g +(.)g(.)g(.)g(.)g(.)g(.)h(.)f(.)g(.)p Black 1669 w(40)p +Black 5978 63966 a Fp(6)1212 b(Ackno)-12 b(wledgments)27337 +b(41)p Black 25600 69672 a Fo(2)p Black eop end +%%Page: 3 3 +TeXDict begin 3 2 bop Black Black 7796 7638 a Fp(Refer)-22 +b(ences)31189 b(41)7796 10356 y(Index)33856 b(43)p Black +25600 69672 a Fo(3)p Black eop end +%%Page: 4 4 +TeXDict begin 4 3 bop Black Black 5978 7638 a Fq(1)1594 +b(Intr)-29 b(oduction)5978 10398 y Fo(The)360 b(CUDD)h(package)g(pro) +-18 b(vides)360 b(functions)f(to)i(manipulate)g(Binary)f(Decision)g +(Diagrams)5978 11904 y(\(BDDs\))458 b([5)o(,)h(3],)497 +b(Algebraic)459 b(Decision)g(Diagrams)f(\(ADDs\))g([1)o(],)497 +b(and)459 b(Zero-suppressed)5978 13409 y(Binary)428 b(Decision)h +(Diagrams)f(\(ZDDs\))e([12].)751 b(BDDs)429 b(are)f(used)g(to)h +(represent)e(switching)5978 14914 y(functions;)456 b(ADDs)406 +b(are)g(used)g(to)g(represent)f(function)h(from)f Fm(f)p +Fl(0)p Fk(;)202 b Fl(1)p Fm(g)35668 14475 y Fj(n)36700 +14914 y Fo(to)406 b(an)g(arbitrary)f(set.)5978 16420 +y(ZDDs)268 b(represent)g(switching)h(functions)f(lik)-12 +b(e)269 b(BDDs;)281 b(ho)-30 b(we)g(v)-18 b(er)-48 b(,)274 +b(the)-18 b(y)269 b(are)g(much)g(more)g(ef)-30 b(\002-)5978 +17925 y(cient)330 b(than)g(BDDs)h(when)f(the)h(functions)e(to)i(be)f +(represented)g(are)g(characteristic)g(functions)5978 +19431 y(of)395 b(cube)i(sets,)418 b(or)396 b(in)g(general,)420 +b(when)396 b(the)h(ON-set)e(of)h(the)h(function)f(to)g(be)g +(represented)g(is)5978 20936 y(v)-18 b(ery)302 b(sparse.)375 +b(The)-18 b(y)303 b(are)g(inferior)f(to)h(BDDs)g(in)g(other)g(cases.) +7859 22442 y(The)384 b(package)h(pro)-18 b(vides)384 +b(a)g(lar)-22 b(ge)385 b(set)e(of)h(operations)g(on)g(BDDs,)405 +b(ADDs,)f(and)385 b(ZDDs,)5978 23947 y(functions)307 +b(to)g(con)-48 b(v)-18 b(ert)308 b(BDDs)g(into)f(ADDs)h(or)f(ZDDs)h +(and)g(vice)g(v)-18 b(ersa,)308 b(and)g(a)g(lar)-22 b(ge)308 +b(assort-)5978 25453 y(ment)303 b(of)g(v)-30 b(ariable)302 +b(reordering)h(methods.)7859 26958 y(The)g(CUDD)h(package)g(can)g(be)f +(used)g(in)g(three)g(w)-12 b(ays:)p Black 7796 29202 +a Fm(\262)p Black 606 w Fo(As)232 b(a)h(black)g(box.)352 +b(In)232 b(this)g(case,)247 b(the)233 b(application)g(program)f(that)h +(needs)f(to)h(manipulate)9008 30707 y(decision)297 b(diagrams)g(only)g +(uses)f(the)h(e)-18 b(xported)297 b(functions)g(of)g(the)g(package.)374 +b(The)297 b(rich)9008 32213 y(set)303 b(of)g(functions)g(included)h(in) +g(the)f(CUDD)i(package)f(allo)-30 b(ws)303 b(man)-18 +b(y)304 b(applications)f(to)9008 33718 y(be)280 b(written)h(in)f(this)g +(w)-12 b(ay)-79 b(.)369 b(Section)280 b(3)h(describes)e(ho)-30 +b(w)280 b(to)h(use)f(the)g(e)-18 b(xported)281 b(functions)9008 +35223 y(of)315 b(the)h(package.)413 b(An)316 b(application)g(written)f +(in)h(terms)e(of)i(the)f(e)-18 b(xported)316 b(functions)e(of)9008 +36729 y(the)342 b(package)h(needs)f(not)g(concern)h(itself)e(with)h +(the)g(details)g(of)g(v)-30 b(ariable)342 b(reordering,)9008 +38234 y(which)303 b(may)h(tak)-12 b(e)303 b(place)g(behind)h(the)f +(scenes.)p Black 7796 40633 a Fm(\262)p Black 606 w Fo(As)333 +b(a)g(clear)g(box.)466 b(When)334 b(writing)e(a)i(sophisticated)e +(application)i(based)f(on)g(decision)9008 42138 y(diagrams,)444 +b(ef)-30 b(\002cienc)-18 b(y)417 b(often)f(dictates)h(that)f(some)h +(functions)f(be)g(implemented)h(as)9008 43644 y(direct)448 +b(recursi)-30 b(v)-18 b(e)447 b(manipulation)i(of)e(the)i(diagrams,)484 +b(instead)448 b(of)g(being)g(written)g(in)9008 45149 +y(terms)431 b(of)h(e)-18 b(xisting)431 b(primiti)-30 +b(v)-18 b(e)432 b(functions.)762 b(Section)432 b(4)g(e)-18 +b(xplains)432 b(ho)-30 b(w)432 b(to)g(add)g(ne)-30 b(w)9008 +46655 y(functions)459 b(to)g(the)g(CUDD)h(package.)846 +b(It)458 b(also)h(details)g(ho)-30 b(w)459 b(to)h(write)f(a)g(recursi) +-30 b(v)-18 b(e)9008 48160 y(function)303 b(that)g(can)g(be)h +(interrupted)f(by)g(dynamic)g(v)-30 b(ariable)303 b(reordering.)p +Black 7796 50559 a Fm(\262)p Black 606 w Fo(Through)255 +b(an)h(interf)-12 b(ace.)359 b(Object-oriented)256 b(languages)g(lik) +-12 b(e)255 b(C++)h(and)f(Perl5)h(can)g(free)9008 52064 +y(the)323 b(programmer)g(from)f(the)h(b)-24 b(urden)323 +b(of)g(memory)g(management.)436 b(A)324 b(C++)e(interf)-12 +b(ace)9008 53570 y(is)365 b(included)h(in)f(the)h(distrib)-24 +b(ution)364 b(of)h(CUDD.)i(It)e(automatically)h(frees)e(decision)h(di-) +9008 55075 y(agrams)379 b(that)g(are)g(no)g(longer)h(used)e(by)i(the)f +(application)h(and)f(o)-18 b(v)g(erloads)379 b(operators.)9008 +56580 y(Almost)440 b(all)g(the)g(functionality)g(pro)-18 +b(vided)440 b(by)h(the)f(CUDD)h(e)-18 b(xported)440 b(functions)g(is) +9008 58086 y(a)-24 b(v)-30 b(ailable)402 b(through)g(the)g(C++)g +(interf)-12 b(ace,)426 b(which)403 b(is)e(especially)h(recommended)h +(for)9008 59591 y(f)-12 b(ast)406 b(prototyping.)689 +b(Section)407 b(5)h(e)-18 b(xplains)407 b(ho)-30 b(w)407 +b(to)g(use)g(the)h(interf)-12 b(ace.)688 b(A)407 b(Perl5)g(in-)9008 +61097 y(terf)-12 b(ace)482 b(also)f(e)-18 b(xists)481 +b(and)h(is)g(ditrib)-24 b(uted)481 b(separately)-79 b(.)913 +b(\(See)482 b(Section)g(2.2.\))912 b(Some)9008 62602 +y(applications)303 b(de\002ne)g(their)g(o)-30 b(wn)303 +b(interf)-12 b(aces.)375 b(See)304 b(for)e(e)-18 b(xample)303 +b(Section)h(3.17.)5978 64846 y(In)378 b(the)h(follo)-30 +b(wing,)397 b(the)379 b(reader)f(is)g(supposed)h(to)f(be)h(f)-12 +b(amiliar)378 b(with)h(the)g(basic)f(ideas)h(about)5978 +66351 y(decision)303 b(diagrams,)f(as)h(found,)g(for)f(instance,)h(in)g +([3].)p Black 25600 69672 a(4)p Black eop end +%%Page: 5 5 +TeXDict begin 5 4 bop Black Black 5978 7638 a Fq(2)1594 +b(Ho)-16 b(w)398 b(to)h(Get)f(CUDD)5978 10442 y Fi(2.1)1328 +b(The)332 b(CUDD)g(P)-13 b(ackage)5978 12766 y Fo(The)474 +b(CUDD)h(package)h(is)e(a)-24 b(v)-30 b(ailable)475 b(via)g(anon)-18 +b(ymous)474 b(FTP)g(from)g(vlsi.Colorado.EDU.)5978 14271 +y(A)385 b(compressed)g(tar)h(\002le)g(named)g Fh(cudd-2.4.2.tar.gz)k +Fo(can)c(be)g(found)g(in)f(directory)5978 15777 y Fh(pub)p +Fo(.)376 b(Once)304 b(you)f(ha)-24 b(v)-18 b(e)303 b(this)g(\002le,)p +Black Black 9008 18279 a Fh(gzip)728 b(-dc)g(cudd-2.4.2.tar.gz)k(|)c +(tar)g(xvf)g(-)5978 20780 y Fo(will)344 b(create)h(directory)g +Fh(cudd-2.4.2)j Fo(and)d(its)f(subdirectories.)500 b(These)344 +b(directories)g(con-)5978 22286 y(tain)397 b(the)h(decision)f(diagram)h +(package,)422 b(a)398 b(fe)-30 b(w)397 b(support)f(libraries,)421 +b(and)397 b(a)h(to)-12 b(y)398 b(application)5978 23791 +y(based)281 b(on)g(the)g(decision)g(diagram)g(package.)369 +b(There)281 b(is)f(a)i(README)e(\002le)h(with)g(instructions)5978 +25297 y(on)426 b(con\002guration)g(and)g(installation)g(in)g +Fh(cudd-2.4.2)p Fo(.)747 b(Y)-133 b(ou)426 b(can)h(use)f(a)g(compiler)g +(for)5978 26802 y(either)303 b(ANSI)f(C)i(or)f(C++.)7859 +28308 y(Once)h(you)f(ha)-24 b(v)-18 b(e)303 b(made)h(the)f(libraries)f +(and)h(program,)g(you)g(can)h(type:)p Black Black 9008 +30809 a Fh(cd)728 b(nanotrav)9008 32315 y(nanotrav)h(-p)f(1)g(-autodyn) +h(-reordering)h(sifting)g(-trav)9008 33820 y(mult32a.blif)5978 +36322 y Fo(This)337 b(will)i(run)f(a)g(simple-minded)g(FSM)g(tra)-24 +b(v)-18 b(ersal)338 b(program.)481 b(\(On)338 b(a)h(2.4)g(GHz)f +(Pentium)h(4)5978 37828 y(\(TM\),)363 b(it)i(tak)-12 +b(es)364 b(about)h(0.5)g(s.\))561 b(The)364 b(output)h(produced)h(by)f +(the)g(program)f(can)h(be)g(check)-12 b(ed)5978 39333 +y(ag)-6 b(ainst)437 b Fh(cudd-2.4.2/nanotrav/mult32a.out)p +Fo(.)789 b(More)437 b(information)h(on)g(the)5978 40838 +y Fh(nanotrav)305 b Fo(program)d(can)i(be)f(found)g(in)g +Fh(cudd-2.4.2/nanotrav/README)p Fo(.)7859 42344 y(If)336 +b(you)h(w)-12 b(ant)337 b(to)g(be)f(noti\002ed)h(of)g(ne)-30 +b(w)336 b(releases)g(of)g(the)h(CUDD)h(package,)346 b(send)336 +b(a)h(mes-)5978 43849 y(sage)303 b(to)g Fh(Fabio@Colorado.EDU)p +Fo(.)5978 47172 y Fi(2.2)1328 b(CUDD)333 b(Friends)5978 +49496 y Fo(T)-97 b(w)-12 b(o)249 b(CUDD)h(e)-18 b(xtensions)248 +b(are)i(a)-24 b(v)-30 b(ailable)249 b(via)h(anon)-18 +b(ymous)249 b(FTP)g(from)f(vlsi.Colorado.EDU.)p Black +7796 51997 a Fm(\262)p Black 606 w Fn(P)-97 b(erlDD)372 +b Fo(is)h(an)g(object-oriented)g(Perl5)f(interf)-12 b(ace)373 +b(to)g(CUDD.)g(It)g(is)f(or)-22 b(g)-6 b(anized)373 b(as)g(a)9008 +53503 y(standard)342 b(Perl)h(e)-18 b(xtension)343 b(module.)496 +b(The)342 b(Perl)h(interf)-12 b(ace)343 b(is)f(at)h(a)g(some)-30 +b(what)343 b(higher)9008 55008 y(le)-30 b(v)-18 b(el)303 +b(than)g(the)g(C++)g(interf)-12 b(ace,)303 b(b)-24 b(ut)303 +b(it)g(is)f(not)h(as)g(complete.)p Black 7796 57510 a +Fm(\262)p Black 606 w Fn(DDcal)311 b Fo(is)d(a)i(graphic)f(BDD)h +(calculator)f(based)g(on)h(CUDD,)g(Perl-Tk,)g(and)f(dot.)394 +b(\(See)9008 59015 y(Section)303 b(3.18)g(for)g(information)f(on)i +Fn(dot)p Fo(.\))5978 62917 y Fq(3)1594 b(User')-59 b(s)397 +b(Manual)5978 65677 y Fo(This)302 b(section)h(describes)f(the)h(use)g +(of)g(the)g(CUDD)h(package)g(as)e(a)i(black)f(box.)p +Black 25600 69672 a(5)p Black eop end +%%Page: 6 6 +TeXDict begin 6 5 bop Black Black 5978 7638 a Fi(3.1)1328 +b(Compiling)332 b(and)g(Linking)5978 9962 y Fo(T)-97 +b(o)302 b(b)-24 b(uild)303 b(an)g(application)h(that)f(uses)g(the)g +(CUDD)h(package,)g(you)f(should)g(add)p Black Black 5978 +12463 a Fh(#include)729 b("util.h")5978 13969 y(#include)g("cudd.h") +5978 16471 y Fo(to)410 b(your)h(source)f(\002les,)438 +b(and)411 b(should)f(link)h Fh(libcudd.a)p Fo(,)440 b +Fh(libmtr.a)p Fo(,)g Fh(libst.a)p Fo(,)g(and)5978 17976 +y Fh(libutil.a)362 b Fo(to)e(your)g(e)-18 b(x)g(ecutable.)547 +b(\(All)360 b(these)g(libraries)f(are)h(part)g(of)f(the)i(distrib)-24 +b(ution.\))5978 19482 y(Some)254 b(platforms)g(require)g(speci\002c)h +(compiler)f(and)h(link)-12 b(er)255 b(\003ags.)359 b(Refer)255 +b(to)f(the)h Fh(Makefile)5978 20987 y Fo(in)303 b(the)g(top)g(le)-30 +b(v)-18 b(el)303 b(directory)g(of)f(the)i(distrib)-24 +b(ution.)7859 22492 y(K)-30 b(eep)257 b(in)f(mind)g(that)g(whate)-30 +b(v)-18 b(er)255 b(\003ags)h(af)-30 b(fect)255 b(the)h(size)g(of)g +(data)g(structures\227for)e(instance)5978 23998 y(the)i(\003ags)g(used) +g(to)h(use)f(64-bit)g(pointers)g(where)g(a)-24 b(v)-30 +b(ailable\227must)256 b(be)h(speci\002ed)f(when)h(com-)5978 +25503 y(piling)303 b(both)g(CUDD)h(and)f(the)g(\002les)g(that)g +(include)h(its)e(header)h(\002les.)5978 28826 y Fi(3.2)1328 +b(Basic)332 b(Data)h(Structur)-24 b(es)5978 31150 y Fp(3.2.1)1212 +b(Nodes)5978 33473 y Fo(BDDs,)335 b(ADDs,)h(and)329 b(ZDDs)f(are)h +(made)g(of)g(DdNode')-67 b(s.)453 b(A)329 b(DdNode)h(\(node)f(for)f +(short\))g(is)g(a)5978 34979 y(structure)340 b(with)h(se)-30 +b(v)-18 b(eral)341 b(\002elds.)490 b(Those)341 b(that)g(are)g(of)g +(interest)g(to)g(the)h(application)f(that)h(uses)5978 +36484 y(the)315 b(CUDD)i(package)f(as)g(a)f(black)h(box)g(are)g(the)f +(v)-30 b(ariable)316 b(inde)-18 b(x,)319 b(the)c(reference)h(count,)j +(and)5978 37990 y(the)d(v)-30 b(alue.)415 b(The)316 b(remaining)g +(\002elds)g(are)g(pointers)f(that)i(connect)f(nodes)g(among)h(themselv) +-18 b(es)5978 39495 y(and)303 b(that)g(are)g(used)g(to)g(implement)g +(the)h(unique)f(table.)376 b(\(See)303 b(Section)g(3.2.2.\))7859 +41000 y(The)339 b Fn(inde)-24 b(x)342 b Fo(\002eld)c(holds)g(the)h +(name)f(of)g(the)h(v)-30 b(ariable)338 b(that)g(labels)g(the)h(node.) +482 b(The)338 b(inde)-18 b(x)5978 42506 y(of)477 b(a)h(v)-30 +b(ariable)478 b(is)f(a)h(permanent)g(attrib)-24 b(ute)478 +b(that)g(re\003ects)f(the)h(order)f(of)h(creation.)900 +b(Inde)-18 b(x)5978 44011 y(0)337 b(corresponds)f(to)h(the)h(v)-30 +b(ariable)337 b(created)h(\002rst.)477 b(On)338 b(a)f(machine)h(with)g +(32-bit)f(pointers,)345 b(the)5978 45517 y(maximum)265 +b(number)g(of)g(v)-30 b(ariables)264 b(is)h(the)g(lar)-22 +b(gest)264 b(v)-30 b(alue)266 b(that)f(can)g(be)g(stored)g(in)g(an)g +(unsigned)5978 47022 y(short)331 b(inte)-18 b(ger)332 +b(minus)g(1.)463 b(The)332 b(lar)-22 b(gest)332 b(inde)-18 +b(x)332 b(is)g(reserv)-18 b(ed)331 b(for)h(the)g(constant)g(nodes.)464 +b(When)5978 48528 y(64-bit)282 b(pointers)g(are)g(used,)287 +b(the)282 b(maximum)h(number)g(of)f(v)-30 b(ariables)282 +b(is)g(the)g(lar)-22 b(gest)282 b(v)-30 b(alue)283 b(that)5978 +50033 y(can)303 b(be)g(stored)g(in)g(an)g(unsigned)g(inte)-18 +b(ger)303 b(minus)f(1.)7859 51539 y(When)359 b(v)-30 +b(ariables)357 b(are)h(reordered)f(to)h(reduce)g(the)g(size)g(of)f(the) +h(decision)g(diagrams,)371 b(the)5978 53044 y(v)-30 b(ariables)374 +b(may)h(shift)f(in)i(the)f(order)-48 b(,)392 b(b)-24 +b(ut)375 b(the)-18 b(y)375 b(retain)g(their)g(indices.)591 +b(The)375 b(package)h(k)-12 b(eeps)5978 54550 y(track)342 +b(of)g(the)h(v)-30 b(ariable)343 b(permutation)f(\(and)h(its)f(in)-48 +b(v)-18 b(erse\).)493 b(The)343 b(application)g(is)f(not)g(af)-30 +b(fected)5978 56055 y(by)303 b(v)-30 b(ariable)303 b(reordering,)f(e) +-18 b(xcept)304 b(in)f(the)g(follo)-30 b(wing)302 b(cases.)p +Black 7796 58557 a Fm(\262)p Black 606 w Fo(If)229 b(the)i(application) +g(uses)e(generators)h(\()p Fn(Cudd)p 28073 58557 364 +45 v 437 w(F)-127 b(or)-45 b(eac)-18 b(hCube)230 b Fo(and)h +Fn(Cudd)p 39822 58557 V 437 w(F)-127 b(or)-45 b(eac)-18 +b(hNode)p Fo(\))9008 60062 y(and)259 b(reordering)e(is)h(enabled,)268 +b(then)259 b(it)f(must)g(tak)-12 b(e)258 b(care)h(not)f(to)g(call)h(an) +-18 b(y)259 b(operation)f(that)9008 61568 y(may)388 b(create)f(ne)-30 +b(w)388 b(nodes)f(\(and)g(hence)h(possibly)f(trigger)g(reordering\).) +628 b(This)386 b(is)h(be-)9008 63073 y(cause)423 b(the)h(cubes)f +(\(i.e.,)453 b(paths\))423 b(and)g(nodes)g(of)g(a)g(diagram)h(change)g +(as)f(a)g(result)f(of)9008 64579 y(reordering.)p Black +25600 69672 a(6)p Black eop end +%%Page: 7 7 +TeXDict begin 7 6 bop Black Black Black 7796 7638 a Fm(\262)p +Black 606 w Fo(If)345 b(the)g(application)h(uses)f Fn(Cudd)p +22851 7638 364 45 v 437 w(bddConstr)-18 b(ain)345 b Fo(and)h +(reordering)f(tak)-12 b(es)345 b(place,)357 b(then)9008 +9143 y(the)303 b(property)g(of)f Fn(Cudd)p 19213 9143 +V 438 w(bddConstr)-18 b(ain)302 b Fo(of)h(being)g(an)g(image)h +(restrictor)e(is)g(lost.)7859 11645 y(The)356 b(CUDD)g(package)g +(relies)f(on)h(g)-6 b(arbage)355 b(collection)h(to)g(reclaim)f(the)h +(memory)f(used)5978 13151 y(by)456 b(diagrams)g(that)g(are)g(no)g +(longer)g(in)h(use.)835 b(The)456 b(scheme)g(emplo)-12 +b(yed)456 b(for)g(g)-6 b(arbage)456 b(col-)5978 14656 +y(lection)384 b(is)g(based)g(on)g(k)-12 b(eeping)385 +b(a)g(reference)f(count)g(for)g(each)h(node.)619 b(The)384 +b(references)g(that)5978 16162 y(are)332 b(counted)i(are)e(both)h(the)g +(internal)g(references)f(\(references)g(from)g(other)g(nodes\))g(and)h +(e)-18 b(x-)5978 17667 y(ternal)459 b(references)h(\(typically)f +(references)h(from)f(the)h(calling)g(en)-48 b(vironment\).)846 +b(When)460 b(an)5978 19173 y(application)279 b(creates)g(a)h(ne)-30 +b(w)279 b(BDD,)h(ADD,)f(or)g(ZDD,)g(it)h(must)e(increase)h(its)g +(reference)g(count)5978 20678 y(e)-18 b(xplicitly)-79 +b(,)493 b(through)455 b(a)g(call)h(to)f Fn(Cudd)p 22778 +20678 V 437 w(Ref)177 b Fo(.)831 b(Similarly)-79 b(,)493 +b(when)456 b(a)f(diagram)g(is)g(no)g(longer)5978 22183 +y(needed,)337 b(the)331 b(application)g(must)e(call)i +Fn(Cudd)p 25046 22183 V 437 w(Recur)-12 b(siveDer)-45 +b(ef)506 b Fo(\(for)330 b(BDDs)g(and)h(ADDs\))e(or)5978 +23689 y Fn(Cudd)p 8677 23689 V 437 w(Recur)-12 b(siveDer)-45 +b(efZdd)335 b Fo(\(for)302 b(ZDDs\))g(to)h(\223rec)-18 +b(ycle\224)303 b(the)h(nodes)e(of)h(the)g(diagram.)7859 +25194 y(T)-85 b(erminal)478 b(nodes)g(carry)g(a)g(v)-30 +b(alue.)901 b(This)477 b(is)g(especially)i(important)f(for)f(ADDs.)901 +b(By)5978 26700 y(def)-12 b(ault,)357 b(the)348 b(v)-30 +b(alue)347 b(is)f(a)h(double.)508 b(T)-97 b(o)347 b(change)h(to)f +(something)g(dif)-30 b(ferent)346 b(\(e.g.,)357 b(an)348 +b(inte)-18 b(ger\),)5978 28205 y(the)263 b(package)h(must)f(be)g +(modi\002ed)g(and)h(recompiled.)363 b(Support)262 b(for)h(this)g +(process)f(is)g(currently)5978 29711 y(v)-18 b(ery)302 +b(rudimentary)-79 b(.)5978 32989 y Fp(3.2.2)1212 b(The)304 +b(Manager)5978 35313 y Fo(All)359 b(nodes)g(used)f(in)h(BDDs,)374 +b(ADDs,)f(and)359 b(ZDDs)g(are)g(k)-12 b(ept)359 b(in)g(special)g(hash) +g(tables)g(called)5978 36818 y(the)465 b Fn(unique)h(tables)p +Fo(.)863 b(Speci\002cally)-79 b(,)506 b(BDDs)466 b(and)g(ADDs)f(share)g +(the)h(same)f(unique)h(table,)5978 38324 y(whereas)292 +b(ZDDs)f(ha)-24 b(v)-18 b(e)293 b(their)f(o)-30 b(wn)292 +b(table.)372 b(As)292 b(the)h(name)f(implies,)i(the)f(main)f(purpose)g +(of)g(the)5978 39829 y(unique)g(table)f(is)h(to)f(guarantee)h(that)g +(each)g(node)g(is)f(unique;)296 b(that)c(is,)h(there)f(is)f(no)g(other) +h(node)5978 41335 y(labeled)284 b(by)g(the)g(same)f(v)-30 +b(ariable)284 b(and)g(with)g(the)g(same)g(children.)369 +b(This)283 b(uniqueness)h(property)5978 42840 y(mak)-12 +b(es)434 b(decision)h(diagrams)f(canonical.)773 b(The)434 +b(unique)h(tables)g(and)g(some)g(auxiliary)g(data)5978 +44345 y(structures)400 b(mak)-12 b(e)401 b(up)h(the)f(DdManager)g +(\(manager)h(for)e(short\).)670 b(Though)401 b(the)h(application)5978 +45851 y(that)342 b(uses)g(only)h(the)g(e)-18 b(xported)342 +b(functions)g(needs)h(not)f(be)h(concerned)g(with)g(most)f(details)g +(of)5978 47356 y(the)246 b(manager)-48 b(,)258 b(it)246 +b(has)g(to)h(deal)g(with)f(the)h(manager)g(in)f(the)h(follo)-30 +b(wing)246 b(sense.)356 b(The)247 b(application)5978 +48862 y(must)353 b(initialize)h(the)g(manager)g(by)g(calling)g(an)g +(appropriate)g(function.)528 b(\(See)353 b(Section)h(3.3.\))5978 +50367 y(Subsequently)-79 b(,)281 b(it)c(must)e(pass)h(a)g(pointer)h(to) +f(the)g(manager)h(to)f(all)g(the)h(functions)f(that)g(operate)5978 +51873 y(on)303 b(decision)g(diagrams.)7859 53378 y(W)-48 +b(ith)382 b(the)g(e)-18 b(xception)383 b(of)e(a)h(fe)-30 +b(w)382 b(statistical)f(counters,)402 b(there)382 b(are)f(no)i(global)f +(v)-30 b(ariables)5978 54884 y(in)385 b(the)h(CUDD)g(package.)623 +b(Therefore,)406 b(it)385 b(is)g(quite)g(possible)g(to)g(ha)-24 +b(v)-18 b(e)386 b(multiple)f(managers)5978 56389 y(simultaneously)363 +b(acti)-30 b(v)-18 b(e)363 b(in)h(the)g(same)f(application.)28586 +55949 y Fg(1)29642 56389 y Fo(It)g(is)g(the)h(pointers)f(to)h(the)f +(managers)5978 57895 y(that)303 b(tell)g(the)g(functions)g(on)g(what)g +(data)g(the)-18 b(y)304 b(should)e(operate.)p Black 5978 +58976 15940 45 v 7383 59717 a Ff(1)7771 60140 y Fe(The)240 +b(global)g(statistical)f(counters)h(are)g(used)g(locally;)j(hence)e +(the)-15 b(y)240 b(are)g(compatible)h(with)f(the)g(use)g(of)f(multi-) +5978 61358 y(ple)249 b(managers.)p Black Black 25600 +69672 a Fo(7)p Black eop end +%%Page: 8 8 +TeXDict begin 8 7 bop Black Black 5978 7638 a Fp(3.2.3)1212 +b(Cache)5978 9962 y Fo(Ef)-30 b(\002cient)297 b(recursi)-30 +b(v)-18 b(e)296 b(manipulation)j(of)e(decision)h(diagrams)f(requires)g +(the)h(use)g(of)f(a)h(table)g(to)5978 11467 y(store)317 +b(computed)h(results.)419 b(This)317 b(table)h(is)f(called)h(here)g +(the)g Fn(cac)-18 b(he)318 b Fo(because)g(it)g(is)f(ef)-30 +b(fecti)g(v)-18 b(ely)5978 12973 y(handled)281 b(lik)-12 +b(e)282 b(a)f(cache)h(of)f(v)-30 b(ariable)281 b(b)-24 +b(ut)281 b(limited)g(capacity)-79 b(.)370 b(The)281 b(CUDD)h(package)g +(starts)e(by)5978 14478 y(def)-12 b(ault)376 b(with)h(a)g(small)f +(cache,)396 b(and)377 b(increases)f(its)g(size)g(until)h(either)f(no)h +(further)f(bene\002t)h(is)5978 15984 y(achie)-30 b(v)-18 +b(ed,)302 b(or)g(a)g(limit)g(size)g(is)f(reached.)376 +b(The)302 b(user)f(can)i(in\003uence)f(this)g(polic)-18 +b(y)302 b(by)g(choosing)5978 17489 y(initial)h(and)g(limit)g(v)-30 +b(alues)302 b(for)h(the)g(cache)h(size.)7859 18994 y(T)-97 +b(oo)279 b(small)g(a)h(cache)g(will)f(cause)g(frequent)g(o)-18 +b(v)g(erwriting)279 b(of)f(useful)h(results.)367 b(T)-97 +b(oo)279 b(lar)-22 b(ge)279 b(a)5978 20500 y(cache)285 +b(will)g(cause)h(o)-18 b(v)g(erhead,)288 b(because)e(the)f(whole)g +(cache)h(is)f(scanned)g(e)-30 b(v)-18 b(ery)285 b(time)g(g)-6 +b(arbage)5978 22005 y(collection)314 b(tak)-12 b(es)314 +b(place.)410 b(The)314 b(optimal)h(parameters)f(depend)g(on)h(the)f +(speci\002c)h(application.)5978 23511 y(The)302 b(def)-12 +b(ault)303 b(parameters)g(w)-12 b(ork)303 b(reasonably)g(well)g(for)f +(a)h(lar)-22 b(ge)304 b(spectrum)e(of)h(applications.)7859 +25016 y(The)418 b(cache)h(of)f(the)g(CUDD)g(package)h(is)f(used)f(by)i +(most)e(recursi)-30 b(v)-18 b(e)417 b(functions)g(of)h(the)5978 +26522 y(package,)304 b(and)f(can)g(be)h(used)e(by)i(user)-24 +b(-supplied)301 b(functions)i(as)f(well.)376 b(\(See)303 +b(Section)h(4.4.\))5978 29820 y Fi(3.3)1328 b(Initializing)333 +b(and)e(Shutting)h(Do)-13 b(wn)332 b(a)g(DdManager)5978 +32143 y Fo(T)-97 b(o)353 b(use)h(the)h(functions)e(in)h(the)h(CUDD)g +(package,)368 b(one)354 b(has)g(\002rst)f(to)h(initialize)h(the)f +(package)5978 33649 y(itself)302 b(by)h(calling)g Fn(Cudd)p +16521 33649 364 45 v 437 w(Init)22 b Fo(.)376 b(This)302 +b(function)h(tak)-12 b(es)302 b(four)h(parameters:)p +Black 7796 36026 a Fm(\262)p Black 606 w Fo(numV)-135 +b(ars:)362 b(It)274 b(is)h(the)g(initial)g(number)g(of)f(v)-30 +b(ariables)275 b(for)f(BDDs)h(and)h(ADDs.)366 b(If)274 +b(the)h(to-)9008 37531 y(tal)265 b(number)g(of)f(v)-30 +b(ariables)264 b(needed)i(by)f(the)g(application)g(is)f(kno)-30 +b(wn,)273 b(then)265 b(it)f(is)h(slightly)9008 39037 +y(more)274 b(ef)-30 b(\002cient)274 b(to)h(create)f(a)h(manager)f(with) +h(that)f(number)h(of)f(v)-30 b(ariables.)365 b(If)274 +b(the)g(num-)9008 40542 y(ber)e(is)h(unkno)-30 b(wn,)279 +b(it)272 b(can)h(be)g(set)g(to)g(0,)278 b(or)273 b(to)g(an)-18 +b(y)272 b(other)h(lo)-30 b(wer)272 b(bound)h(on)g(the)g(number)9008 +42048 y(of)374 b(v)-30 b(ariables.)588 b(Requesting)375 +b(more)f(v)-30 b(ariables)373 b(than)h(are)g(actually)h(needed)g(is)e +(not)h(in-)9008 43553 y(correct,)303 b(b)-24 b(ut)303 +b(is)f(not)h(ef)-30 b(\002cient.)p Black 7796 46005 a +Fm(\262)p Black 606 w Fo(numV)-135 b(arsZ:)356 b(It)h(is)f(the)i +(initial)f(number)g(of)f(v)-30 b(ariables)357 b(for)f(ZDDs.)537 +b(See)357 b(Sections)g(3.9)9008 47511 y(and)303 b(3.11)g(for)g(a)g +(discussion)f(of)h(the)g(v)-30 b(alue)303 b(of)g(this)f(ar)-22 +b(gument.)p Black 7796 49963 a Fm(\262)p Black 606 w +Fo(numSlots:)541 b(Determines)385 b(the)i(initial)e(size)h(of)g(each)g +(subtable)g(of)f(the)i(unique)f(table.)9008 51468 y(There)362 +b(is)g(a)h(subtable)g(for)f(each)i(v)-30 b(ariable.)554 +b(The)363 b(size)g(of)f(each)h(subtable)g(is)f(dynami-)9008 +52974 y(cally)334 b(adjusted)f(to)h(re\003ect)g(the)g(number)f(of)h +(nodes.)467 b(It)333 b(is)g(normally)h(O.K.)g(to)g(use)f(the)9008 +54479 y(def)-12 b(ault)303 b(v)-30 b(alue)303 b(for)f(this)h(parameter) +-48 b(,)302 b(which)i(is)e(CUDD)p 32620 54479 V 438 w(UNIQ)-12 +b(UE)p 37691 54479 V 436 w(SLO)-48 b(TS.)p Black 7796 +56931 a Fm(\262)p Black 606 w Fo(cacheSize:)494 b(It)361 +b(is)g(the)h(initial)g(size)f(\(number)h(of)f(entries\))g(of)g(the)h +(cache.)552 b(Its)361 b(def)-12 b(ault)9008 58436 y(v)-30 +b(alue)303 b(is)g(CUDD)p 16524 58436 V 437 w(CA)-48 b(CHE)p +21020 58436 V 437 w(SLO)g(TS.)p Black 7796 60888 a Fm(\262)p +Black 606 w Fo(maxMemory:)372 b(It)297 b(is)f(the)h(tar)-22 +b(get)297 b(v)-30 b(alue)297 b(for)g(the)g(maximum)g(memory)g +(occupation)g(\(in)9008 62394 y(bytes\).)375 b(The)303 +b(package)h(uses)e(this)h(v)-30 b(alue)303 b(to)g(decide)g(tw)-12 +b(o)303 b(parameters.)p Black 10462 64846 a Fp(\226)p +Black 607 w Fo(the)373 b(maximum)g(size)g(to)g(which)h(the)f(cache)h +(will)f(gro)-30 b(w)-79 b(,)390 b(re)-18 b(g)-6 b(ardless)372 +b(of)h(the)g(hit)11675 66351 y(rate)303 b(or)f(the)h(size)g(of)g(the)g +(unique)h(table.)p Black 25600 69672 a(8)p Black eop +end +%%Page: 9 9 +TeXDict begin 9 8 bop Black Black Black 10462 7638 a +Fp(\226)p Black 607 w Fo(the)245 b(maximum)h(size)f(to)g(which)h(gro) +-30 b(wth)245 b(of)g(the)h(unique)f(table)h(will)f(be)h(preferred)11675 +9143 y(to)303 b(g)-6 b(arbage)303 b(collection.)9008 +11645 y(If)370 b(maxMemory)g(is)g(set)g(to)h(0,)388 b(CUDD)371 +b(tries)f(to)g(guess)g(a)h(good)g(v)-30 b(alue)371 b(based)f(on)h(the) +9008 13151 y(a)-24 b(v)-30 b(ailable)303 b(memory)-79 +b(.)5978 15652 y(A)303 b(typical)g(call)g(to)g Fn(Cudd)p +16756 15652 364 45 v 437 w(Init)325 b Fo(may)303 b(look)g(lik)-12 +b(e)303 b(this:)p Black Black 7432 18154 a Fh(manager)729 +b(=)f(Cudd_Init\(0,0,CUDD_UNIQUE_SLOTS,CUDD_CACHE_SLOTS,0\);)5978 +20656 y Fo(T)-97 b(o)454 b(reclaim)g(all)h(the)f(memory)h(associated)f +(with)g(a)h(manager)-48 b(,)492 b(an)455 b(application)g(must)f(call) +5978 22161 y Fn(Cudd)p 8677 22161 V 437 w(Quit)22 b Fo(.)375 +b(This)302 b(is)h(normally)g(done)g(before)g(e)-18 b(xiting.)5978 +25484 y Fi(3.4)1328 b(Setting)332 b(P)-13 b(arameters)5978 +27807 y Fo(The)369 b(package)h(pro)-18 b(vides)369 b(se)-30 +b(v)-18 b(eral)369 b(functions)g(to)g(set)g(the)h(parameters)f(that)h +(control)f(v)-30 b(arious)5978 29313 y(functions.)372 +b(F)-18 b(or)294 b(instance,)j(the)e(package)h(has)f(an)g(automatic)g +(w)-12 b(ay)295 b(of)g(determining)g(whether)5978 30818 +y(a)310 b(lar)-22 b(ger)310 b(unique)g(table)h(w)-12 +b(ould)310 b(mak)-12 b(e)310 b(the)h(application)f(run)g(f)-12 +b(aster)-67 b(.)397 b(In)310 b(that)g(case,)i(the)e(pack-)5978 +32324 y(age)238 b(enters)f(a)h(\223f)-12 b(ast)237 b(gro)-30 +b(wth\224)238 b(mode)g(in)g(which)g(resizing)g(of)f(the)h(unique)g +(subtables)g(is)f(f)-12 b(a)-24 b(v)g(ored)5978 33829 +y(o)-18 b(v)g(er)319 b(g)-6 b(arbage)320 b(collection.)427 +b(When)320 b(the)g(unique)g(table)h(reaches)e(a)h(gi)-30 +b(v)-18 b(en)320 b(size,)k(ho)-30 b(we)g(v)-18 b(er)-48 +b(,)323 b(the)5978 35335 y(package)246 b(returns)f(to)h(the)g(normal)g +(\223slo)-30 b(w)246 b(gro)-30 b(wth\224)245 b(mode,)258 +b(e)-30 b(v)-18 b(en)246 b(though)g(the)g(conditions)g(that)5978 +36840 y(caused)326 b(the)g(transition)f(to)h(f)-12 b(ast)325 +b(gro)-30 b(wth)326 b(still)f(pre)-30 b(v)g(ail.)444 +b(The)325 b(limit)h(size)g(for)f(f)-12 b(ast)325 b(gro)-30 +b(wth)326 b(can)5978 38346 y(be)388 b(read)g(by)g Fn(Cudd)p +14283 38346 V 437 w(ReadLooseUpT)-112 b(o)388 b Fo(and)g(changed)h(by)f +Fn(Cudd)p 33935 38346 V 437 w(SetLooseUpT)-112 b(o)p +Fo(.)631 b(Similar)5978 39851 y(pairs)302 b(of)h(functions)f(e)-18 +b(xist)303 b(for)f(se)-30 b(v)-18 b(eral)302 b(other)h(parameters.)375 +b(See)304 b(also)e(Section)i(4.8.)5978 43174 y Fi(3.5)1328 +b(Constant)332 b(Functions)5978 45497 y Fo(The)233 b(CUDD)h(P)-18 +b(ackage)234 b(de\002nes)f(se)-30 b(v)-18 b(eral)233 +b(constant)g(functions.)353 b(These)232 b(functions)h(are)h(created) +5978 47003 y(when)303 b(the)g(manager)h(is)e(initialized,)i(and)f(are)g +(accessible)g(through)g(the)g(manager)g(itself.)5978 +50281 y Fp(3.5.1)1212 b(One,)303 b(Logic)h(Zer)-22 b(o,)304 +b(and)f(Arithmetic)f(Zer)-22 b(o)5978 52605 y Fo(The)466 +b(constant)g(1)g(\(returned)g(by)g Fn(Cudd)p 23193 52605 +V 437 w(ReadOne)p Fo(\))h(is)e(common)i(to)f(BDDs,)508 +b(ADDs,)f(and)5978 54110 y(ZDDs.)566 b(Ho)-30 b(we)g(v)-18 +b(er)-48 b(,)382 b(its)366 b(meaning)h(is)f(dif)-30 b(ferent)366 +b(for)g(ADDs)g(and)h(BDDs,)383 b(on)367 b(the)g(one)g(hand,)5978 +55616 y(and)319 b(ZDDs,)j(on)c(the)h(other)g(hand.)423 +b(The)319 b(diagram)f(consisting)g(of)h(the)g(constant)f(1)h(node)g +(only)5978 57121 y(represents)387 b(the)h(constant)h(1)f(function)g +(for)g(ADDs)g(and)h(BDDs.)632 b(F)-18 b(or)388 b(ZDDs,)409 +b(its)388 b(meaning)5978 58626 y(depends)378 b(on)h(the)g(number)g(of)f +(v)-30 b(ariables:)527 b(It)378 b(is)g(the)h(conjunction)g(of)g(the)g +(complements)f(of)5978 60132 y(all)442 b(v)-30 b(ariables.)795 +b(Con)-48 b(v)-18 b(ersely)-79 b(,)477 b(the)443 b(representation)f(of) +h(the)g(constant)g(1)f(function)h(depends)5978 61637 +y(on)351 b(the)g(number)g(of)g(v)-30 b(ariables.)519 +b(The)351 b(constant)g(1)g(function)g(of)g Fk(n)f Fo(v)-30 +b(ariables)351 b(is)f(returned)h(by)5978 63143 y Fn(Cudd)p +8677 63143 V 437 w(ReadZddOne)p Fo(.)p Black 25600 69672 +a(9)p Black eop end +%%Page: 10 10 +TeXDict begin 10 9 bop Black Black 7859 7638 a Fo(The)379 +b(constant)f(0)g(is)g(common)g(to)h(ADDs)f(and)g(ZDDs,)397 +b(b)-24 b(ut)378 b(not)g(to)h(BDDs.)601 b(The)378 b(BDD)5978 +9143 y(logic)257 b(0)g(is)f Fp(not)g Fo(associated)h(with)g(the)g +(constant)g(0)g(function:)353 b(It)256 b(is)g(obtained)i(by)f +(complemen-)5978 10649 y(tation)318 b(\()p Fn(Cudd)p +12160 10649 364 45 v 437 w(Not)22 b Fo(\))318 b(of)g(the)h(constant)f +(1.)422 b(\(It)317 b(is)h(also)g(returned)g(by)g Fn(Cudd)p +37282 10649 V 437 w(ReadLo)-12 b(gicZer)-55 b(o)p Fo(.\))5978 +12154 y(All)303 b(other)g(constants)f(are)h(speci\002c)g(to)g(ADDs.) +5978 15433 y Fp(3.5.2)1212 b(Pr)-22 b(ede\002ned)303 +b(Constants)5978 17756 y Fo(Besides)422 b(0)g(\(returned)f(by)h +Fn(Cudd)p 20396 17756 V 437 w(ReadZer)-55 b(o)p Fo(\))422 +b(and)h(1,)452 b(the)422 b(follo)-30 b(wing)422 b(constant)g(functions) +5978 19262 y(are)303 b(created)g(at)g(initialization)h(time.)p +Black 7493 21763 a(1.)p Black 606 w(PlusIn\002nity)322 +b(and)i(MinusIn\002nity:)415 b(On)323 b(computers)g(implementing)h(the) +f(IEEE)f(stan-)9008 23269 y(dard)501 b(754)f(for)h(\003oating-point)f +(arithmetic,)550 b(these)501 b(tw)-12 b(o)501 b(constants)f(are)h(set)f +(to)h(the)9008 24774 y(signed)230 b(in\002nities.)351 +b(On)231 b(the)f(DEC)h(Alphas,)244 b(the)231 b(option)f +Fh(-ieee_with_no_inexact)9008 26280 y Fo(or)440 b Fh +(-ieee_with_inexact)445 b Fo(must)440 b(be)h(passed)f(to)h(the)f(DEC)h +(compiler)f(to)h(get)9008 27785 y(support)313 b(of)h(the)g(IEEE)f +(standard.)408 b(\(The)313 b(compiler)h(still)g(produces)f(a)i(w)-12 +b(arning,)316 b(b)-24 b(ut)314 b(it)9008 29291 y(can)397 +b(be)f(ignored.\))655 b(Compiling)397 b(with)f(those)g(options)g(may)h +(cause)f(substantial)g(per)-24 b(-)9008 30796 y(formance)499 +b(de)-18 b(gradation)499 b(on)g(the)g(Ev)-24 b(olution)499 +b(IV)f(CPUs.)964 b(\(Especially)498 b(if)h(the)g(ap-)9008 +32302 y(plication)428 b(does)f(use)g(the)h(in\002nities.\))748 +b(The)427 b(problem)g(is)g(reportedly)g(solv)-18 b(ed)428 +b(in)f(the)9008 33807 y(Ev)-24 b(olution)422 b(V)i(CPUs.)736 +b(If)422 b Fh(gcc)i Fo(is)e(used)h(to)g(compile)h(CUDD)g(on)f(the)g +(Alphas,)453 b(the)9008 35313 y(symbol)329 b Fh(HAVE)p +15888 35313 V 437 w(IEEE)p 19233 35313 V 438 w(754)h +Fo(must)f(be)g(unde\002ned.)455 b(\(See)330 b(the)f(Mak)-12 +b(e\002le)329 b(for)g(the)g(de-)9008 36818 y(tails.\))499 +b(The)344 b(v)-30 b(alues)345 b(of)f(these)g(constants)g(are)g +(returned)h(by)f Fn(Cudd)p 37384 36818 V 437 w(ReadPlusIn\002nity)9008 +38324 y Fo(and)303 b Fn(Cudd)p 13760 38324 V 437 w(ReadMinusIn\002nity) +p Fo(.)p Black 7493 40825 a(2.)p Black 606 w(Epsilon:)488 +b(This)359 b(constant,)374 b(initially)360 b(set)f(to)h +Fl(10)29123 40385 y Fd(\241)p Fc(12)30851 40825 y Fo(,)374 +b(is)359 b(used)g(in)h(comparing)g(\003oating)9008 42331 +y(point)338 b(v)-30 b(alues)337 b(for)g(equality)-79 +b(.)481 b(Its)337 b(v)-30 b(alue)338 b(is)f(returned)h(by)g +Fn(Cudd)p 35858 42331 V 437 w(ReadEpsilon)p Fo(,)345 +b(and)338 b(it)9008 43836 y(can)366 b(be)g(modi\002ed)g(by)g(calling)h +Fn(Cudd)p 25185 43836 V 437 w(SetEpsilon)p Fo(.)563 b(Unlik)-12 +b(e)366 b(the)g(other)g(constants,)381 b(it)9008 45342 +y(does)303 b(not)g(correspond)f(to)h(a)h(node.)5978 48620 +y Fp(3.5.3)1212 b(Backgr)-22 b(ound)5978 50944 y Fo(The)289 +b(background)h(v)-30 b(alue)290 b(is)f(a)h(constant)f(typically)h(used) +f(to)h(represent)f(non-e)-18 b(xisting)289 b(arcs)g(in)5978 +52449 y(graphs.)385 b(Consider)306 b(a)h(shortest)e(path)i(problem.)385 +b(T)-97 b(w)-12 b(o)307 b(nodes)f(that)g(are)h(not)f(connected)h(by)g +(an)5978 53954 y(arc)391 b(can)g(be)g(re)-18 b(g)-6 b(arded)391 +b(as)f(being)i(joined)f(by)g(an)g(arc)g(of)g(in\002nite)g(length.)639 +b(In)391 b(shortest)f(path)5978 55460 y(problems,)321 +b(it)d(is)g(therefore)f(con)-48 b(v)-18 b(enient)319 +b(to)f(set)g(the)g(background)h(v)-30 b(alue)318 b(to)g +(PlusIn\002nity.)420 b(In)5978 56965 y(netw)-12 b(ork)320 +b(\003o)-30 b(w)320 b(problems,)k(on)c(the)h(other)f(hand,)325 +b(tw)-12 b(o)320 b(nodes)g(not)h(connected)g(by)f(an)h(arc)f(can)5978 +58471 y(be)359 b(re)-18 b(g)-6 b(arded)359 b(as)g(joined)h(by)g(an)f +(arc)h(of)f(0)g(capacity)-79 b(.)546 b(F)-18 b(or)359 +b(these)g(problems,)373 b(therefore,)g(it)360 b(is)5978 +59976 y(more)370 b(con)-48 b(v)-18 b(enient)371 b(to)f(set)g(the)h +(background)g(v)-30 b(alue)370 b(to)h(0.)578 b(In)370 +b(general,)388 b(when)371 b(representing)5978 61482 y(sparse)302 +b(matrices,)g(the)i(background)f(v)-30 b(alue)303 b(is)g(the)g(v)-30 +b(alue)303 b(that)g(is)g(assumed)f(implicitly)-79 b(.)7859 +62987 y(At)231 b(initialization,)245 b(the)231 b(background)f(v)-30 +b(alue)231 b(is)e(set)h(to)h(0.)351 b(It)230 b(can)h(be)f(read)h(with)f +Fn(Cudd)p 43176 62987 V 437 w(ReadBac)-24 b(kgr)-55 b(ound)33 +b Fo(,)5978 64493 y(and)265 b(modi\002ed)h(with)g Fn(Cudd)p +17689 64493 V 437 w(SetBac)-24 b(kgr)-55 b(ound)p Fo(.)363 +b(The)266 b(background)g(v)-30 b(alue)265 b(af)-30 b(fects)265 +b(procedures)p Black 25297 69672 a(10)p Black eop end +%%Page: 11 11 +TeXDict begin 11 10 bop Black Black 5978 7638 a Fo(that)427 +b(read)h(sparse)f(matrices/graphs)g(\()p Fn(Cudd)p 25400 +7638 364 45 v 437 w(addRead)460 b Fo(and)428 b Fn(Cudd)p +35410 7638 V 437 w(addHarwell)q Fo(\),)459 b(proce-)5978 +9143 y(dures)379 b(that)h(print)g(out)g(sum-of-product)e(e)-18 +b(xpressions)379 b(for)g(ADDs)h(\()p Fn(Cudd)p 38091 +9143 V 437 w(PrintMinterm)p Fo(\),)5978 10649 y(generators)520 +b(of)h(cubes)h(\()p Fn(Cudd)p 19463 10649 V 436 w(F)-127 +b(or)-45 b(eac)-18 b(hCube)p Fo(\),)576 b(and)522 b(procedures)f(that)g +(count)h(minterms)5978 12154 y(\()p Fn(Cudd)p 9081 12154 +V 436 w(CountMinterm)p Fo(\).)5978 15433 y Fp(3.5.4)1212 +b(New)303 b(Constants)5978 17756 y Fo(Ne)-30 b(w)258 +b(constant)h(can)f(be)h(created)g(by)g(calling)f Fn(Cudd)p +27621 17756 V 437 w(addConst)22 b Fo(.)361 b(This)258 +b(function)g(will)h(retrie)-30 b(v)-18 b(e)5978 19262 +y(the)397 b(ADD)h(for)f(the)g(desired)g(constant,)421 +b(if)397 b(it)h(already)f(e)-18 b(xist,)421 b(or)397 +b(it)h(will)f(create)h(a)f(ne)-30 b(w)398 b(one.)5978 +20767 y(Ob)-18 b(viously)-79 b(,)303 b(ne)-30 b(w)303 +b(constants)f(should)h(only)g(be)g(used)g(when)h(manipulating)f(ADDs.) +5978 24090 y Fi(3.6)1328 b(Cr)-24 b(eating)333 b(V)-122 +b(ariables)5978 26413 y Fo(Decision)339 b(diagrams)g(are)h(typically)g +(created)g(by)f(combining)h(simpler)f(decision)h(diagrams.)5978 +27919 y(The)282 b(simplest)f(decision)i(diagrams,)j(of)c(course,)k +(cannot)d(be)g(created)f(in)h(that)g(w)-12 b(ay)-79 b(.)369 +b(Constant)5978 29424 y(functions)296 b(ha)-24 b(v)-18 +b(e)297 b(been)g(discussed)f(in)h(Section)h(3.5.)373 +b(In)297 b(this)g(section)f(we)i(discuss)d(the)i(simple)5978 +30930 y(v)-30 b(ariable)302 b(functions,)h(also)g(kno)-30 +b(wn)303 b(as)g Fn(pr)-55 b(ojection)303 b(functions)p +Fo(.)5978 34208 y Fp(3.6.1)1212 b(New)303 b(BDD)h(and)f(ADD)h(V)-112 +b(ariables)5978 36532 y Fo(The)353 b(projection)h(functions)f(are)h +(distinct)f(for)g(BDDs)h(and)h(ADDs.)527 b(A)354 b(projection)g +(function)5978 38037 y(for)296 b(BDDs)i(consists)e(of)h(an)h(internal)f +(node)h(with)g(both)f(outgoing)h(arcs)f(pointing)g(to)h(the)f(con-)5978 +39542 y(stant)302 b(1.)376 b(The)303 b Fn(else)g Fo(arc)g(is)f +(complemented.)7859 41048 y(An)269 b(ADD)f(projection)g(function,)275 +b(on)268 b(the)g(other)g(hand,)275 b(has)268 b(the)g +Fn(else)g Fo(pointer)g(directed)g(to)5978 42553 y(the)448 +b(arithmetic)g(zero)g(function.)811 b(One)448 b(should)g(ne)-30 +b(v)-18 b(er)448 b(mix)g(the)g(tw)-12 b(o)448 b(types)g(of)g(v)-30 +b(ariables.)5978 44059 y(BDD)522 b(v)-30 b(ariables)521 +b(should)g(be)h(used)f(when)h(manipulating)g(BDDs,)577 +b(and)522 b(ADD)g(v)-30 b(ariables)5978 45564 y(should)417 +b(be)g(used)h(when)f(manipulating)h(ADDs.)719 b(Three)417 +b(functions)g(are)h(pro)-18 b(vided)417 b(to)h(cre-)5978 +47070 y(ate)303 b(BDD)h(v)-30 b(ariables:)p Black 7796 +49572 a Fm(\262)p Black 606 w Fn(Cudd)p 11707 49572 V +437 w(bddIthV)-135 b(ar)28 b Fo(:)493 b(Returns)361 b(the)h(projection) +g(function)g(with)g(inde)-18 b(x)362 b Fk(i)p Fo(.)552 +b(If)361 b(the)h(func-)9008 51077 y(tion)303 b(does)g(not)g(e)-18 +b(xist,)302 b(it)h(is)g(created.)p Black 7796 53579 a +Fm(\262)p Black 606 w Fn(Cudd)p 11707 53579 V 437 w(bddNe)-18 +b(wV)-135 b(ar)28 b Fo(:)637 b(Returns)433 b(a)h(ne)-30 +b(w)433 b(projection)g(function,)466 b(whose)434 b(inde)-18 +b(x)433 b(is)g(the)9008 55084 y(lar)-22 b(gest)303 b(inde)-18 +b(x)303 b(in)g(use)g(at)g(the)g(time)g(of)g(the)g(call,)g(plus)g(1.)p +Black 7796 57586 a Fm(\262)p Black 606 w Fn(Cudd)p 11707 +57586 V 437 w(bddNe)-18 b(wV)-135 b(arAtLe)-18 b(vel)q +Fo(:)646 b(Similar)437 b(to)h Fn(Cudd)p 30465 57586 V +437 w(bddNe)-18 b(wV)-135 b(ar)28 b Fo(.)781 b(In)438 +b(addition)g(it)f(al-)9008 59091 y(lo)-30 b(ws)360 b(to)h(specify)g +(the)g(position)f(in)h(the)g(v)-30 b(ariable)361 b(order)g(at)g(which)g +(the)g(ne)-30 b(w)361 b(v)-30 b(ariable)9008 60597 y(should)374 +b(be)h(inserted.)591 b(In)374 b(contrast,)393 b Fn(Cudd)p +27483 60597 V 437 w(bddNe)-18 b(wV)-135 b(ar)403 b Fo(adds)375 +b(the)g(ne)-30 b(w)374 b(v)-30 b(ariable)375 b(at)9008 +62102 y(the)303 b(end)g(of)g(the)g(order)-67 b(.)5978 +64604 y(The)432 b(analogous)g(functions)g(for)g(ADDs)g(are)g +Fn(Cudd)p 28572 64604 V 437 w(addIthV)-135 b(ar)28 b +Fo(,)464 b Fn(Cudd)p 37279 64604 V 437 w(addNe)-18 b(wV)-135 +b(ar)28 b Fo(,)466 b(and)5978 66110 y Fn(Cudd)p 8677 +66110 V 437 w(addNe)-18 b(wV)-135 b(arAtLe)-18 b(vel)q +Fo(.)p Black 25297 69672 a(11)p Black eop end +%%Page: 12 12 +TeXDict begin 12 11 bop Black Black 5978 7638 a Fp(3.6.2)1212 +b(New)303 b(ZDD)h(V)-112 b(ariables)5978 9962 y Fo(Unlik)-12 +b(e)411 b(the)g(projection)g(functions)g(of)f(BDDs)h(and)h(ADDs,)438 +b(the)411 b(projection)g(functions)f(of)5978 11467 y(ZDDs)277 +b(ha)-24 b(v)-18 b(e)279 b(diagrams)e(with)i Fk(n)178 +b Fl(+)g(1)276 b Fo(nodes,)283 b(where)c Fk(n)f Fo(is)f(the)i(number)f +(of)g(v)-30 b(ariables.)367 b(There-)5978 12973 y(fore)k(the)i(ZDDs)f +(of)g(the)g(projection)h(functions)e(change)i(when)g(ne)-30 +b(w)373 b(v)-30 b(ariables)371 b(are)i(added.)5978 14478 +y(This)273 b(will)h(be)g(discussed)f(in)h(Section)g(3.9.)366 +b(Here)274 b(we)h(assume)e(that)h(the)g(number)g(of)g(v)-30 +b(ariables)5978 15984 y(is)302 b(\002x)-18 b(ed.)376 +b(The)303 b(ZDD)g(of)f(the)i Fk(i)p Fo(-th)e(projection)h(function)g +(is)g(returned)f(by)h Fn(Cudd)p 39548 15984 364 45 v +437 w(zddIthV)-135 b(ar)28 b Fo(.)5978 19306 y Fi(3.7)1328 +b(Basic)332 b(BDD)h(Manipulation)5978 21630 y Fo(Common)441 +b(manipulations)f(of)g(BDDs)g(can)h(be)g(accomplished)f(by)h(calling)f +Fn(Cudd)p 42064 21630 V 437 w(bddIte)p Fo(.)5978 23135 +y(This)236 b(function)h(tak)-12 b(es)237 b(three)g(BDDs,)250 +b Fk(f)130 b Fo(,)252 b Fk(g)43 b Fo(,)251 b(and)237 +b Fk(h)p Fo(,)251 b(as)236 b(ar)-22 b(guments)237 b(and)h(computes)f +Fk(f)156 b Fm(\242)25 b Fk(g)69 b Fl(+)25 b Fk(f)44129 +22695 y Fd(0)44465 23135 y Fm(\242)g Fk(h)p Fo(.)5978 +24641 y(Lik)-12 b(e)374 b(all)g(the)h(functions)f(that)h(create)f(ne) +-30 b(w)375 b(BDDs)g(or)f(ADDs,)392 b Fn(Cudd)p 35994 +24641 V 437 w(bddIte)375 b Fo(returns)e(a)i(re-)5978 +26146 y(sult)390 b(that)h(must)g(be)g(e)-18 b(xplicitly)391 +b(referenced)g(by)g(the)g(caller)-67 b(.)640 b Fn(Cudd)p +34812 26146 V 437 w(bddIte)391 b Fo(can)g(be)g(used)g(to)5978 +27652 y(implement)409 b(all)g(tw)-12 b(o-ar)-22 b(gument)409 +b(boolean)h(functions.)693 b(Ho)-30 b(we)g(v)-18 b(er)-48 +b(,)435 b(the)409 b(package)h(also)f(pro-)5978 29157 +y(vides)284 b Fn(Cudd)p 11520 29157 V 437 w(bddAnd)318 +b Fo(as)285 b(well)g(as)f(the)i(other)e(tw)-12 b(o-operand)285 +b(boolean)h(functions,)i(which)d(are)5978 30662 y(slightly)389 +b(more)i(ef)-30 b(\002cient)390 b(when)h(a)f(tw)-12 b(o-operand)391 +b(function)f(is)g(called)h(for)-67 b(.)637 b(The)391 +b(follo)-30 b(wing)5978 32168 y(fragment)291 b(of)h(code)g(illustrates) +f(ho)-30 b(w)292 b(to)g(b)-24 b(uild)292 b(the)g(BDD)g(for)g(the)g +(function)g Fk(f)467 b Fl(=)337 b Fk(x)41344 31728 y +Fd(0)41344 32476 y Fc(0)41869 32168 y Fk(x)42562 31728 +y Fd(0)42562 32476 y Fc(1)43088 32168 y Fk(x)43781 31728 +y Fd(0)43781 32476 y Fc(2)44307 32168 y Fk(x)45000 31728 +y Fd(0)45000 32476 y Fc(3)45525 32168 y Fo(.)p Black +Black 5978 34670 a Fh(DdManager)729 b(*manager;)5978 +36175 y(DdNode)f(*f,)h(*var,)f(*tmp;)5978 37681 y(int)g(i;)5978 +40692 y(...)5978 43702 y(f)f(=)h(Cudd_ReadOne\(manager\);)5978 +45208 y(Cudd_Ref\(f\);)5978 46713 y(for)g(\(i)f(=)h(3;)g(i)f(>=)h(0;)g +(i--\))g({)8887 48219 y(var)g(=)f(Cudd_bddIthVar\(manager,i\);)8887 +49724 y(tmp)h(=)f(Cudd_bddAnd\(manager,Cudd_Not\(var\),f\);)8887 +51230 y(Cudd_Ref\(tmp\);)8887 52735 y +(Cudd_RecursiveDeref\(manager,f\);)8887 54241 y(f)g(=)h(tmp;)5978 +55746 y(})5978 58248 y Fo(This)302 b(e)-18 b(xample)303 +b(illustrates)f(the)h(follo)-30 b(wing)303 b(points:)p +Black 7796 60750 a Fm(\262)p Black 606 w Fo(Intermediate)494 +b(results)f(must)h(be)h(\223referenced\224)g(and)f(\223dereferenced.) +-85 b(\224)951 b(Ho)-30 b(we)g(v)-18 b(er)-48 b(,)9008 +62255 y Fh(var)361 b Fo(is)e(a)h(projection)h(function,)374 +b(and)360 b(its)g(reference)f(count)i(is)e(al)-12 b(w)g(ays)360 +b(greater)g(than)9008 63761 y(0.)376 b(Therefore,)302 +b(there)h(is)f(no)i(call)f(to)g Fn(Cudd)p 27028 63761 +V 437 w(Ref)177 b Fo(.)p Black 25297 69672 a(12)p Black +eop end +%%Page: 13 13 +TeXDict begin 13 12 bop Black Black Black 7796 7638 a +Fm(\262)p Black 606 w Fo(The)317 b(ne)-30 b(w)318 b Fh(f)g +Fo(must)g(be)g(assigned)f(to)h(a)g(temporary)f(v)-30 +b(ariable)318 b(\()p Fh(tmp)g Fo(in)g(this)f(e)-18 b(xample\).)9008 +9143 y(If)273 b(the)h(result)e(of)i Fn(Cudd)p 18793 9143 +364 45 v 437 w(bddAnd)306 b Fo(were)274 b(assigned)f(directly)g(to)h +Fh(f)p Fo(,)280 b(the)274 b(old)f Fh(f)h Fo(w)-12 b(ould)274 +b(be)9008 10649 y(lost,)302 b(and)i(there)f(w)-12 b(ould)303 +b(be)g(no)g(w)-12 b(ay)304 b(to)f(free)f(its)h(nodes.)p +Black 7796 13103 a Fm(\262)p Black 606 w Fo(The)g(statement)g +Fh(f)727 b(=)h(tmp)304 b Fo(has)e(the)i(same)f(ef)-30 +b(fect)302 b(as:)p Black Black 11917 15958 a Fh(f)728 +b(=)f(tmp;)11917 17464 y(Cudd_Ref\(f\);)11917 18969 y +(Cudd_RecursiveDeref\(manager,tmp\);)9008 21825 y Fo(b)-24 +b(ut)344 b(is)g(more)h(ef)-30 b(\002cient.)500 b(The)344 +b(reference)h(is)f(\223passed\224)g(from)g Fh(tmp)i Fo(to)e +Fh(f)p Fo(,)355 b(and)345 b Fh(tmp)h Fo(is)9008 23330 +y(no)-30 b(w)303 b(ready)g(to)g(be)g(reutilized.)p Black +7796 25784 a Fm(\262)p Black 606 w Fo(It)405 b(is)h(normally)g(more)f +(ef)-30 b(\002cient)406 b(to)g(b)-24 b(uild)406 b(BDDs)g +(\223bottom-up.)-85 b(\224)684 b(This)406 b(is)f(wh)-6 +b(y)406 b(the)9008 27290 y(loop)273 b(goes)f(from)g(3)h(to)g(0.)366 +b(Notice,)279 b(ho)-30 b(we)g(v)-18 b(er)-48 b(,)278 +b(that)273 b(after)f(v)-30 b(ariable)273 b(reordering,)278 +b(higher)9008 28795 y(inde)-18 b(x)385 b(does)g(not)f(necessarily)h +(mean)g(\223closer)g(to)f(the)h(bottom.)-85 b(\224)622 +b(Of)385 b(course,)405 b(in)385 b(this)9008 30301 y(simple)303 +b(e)-18 b(xample,)303 b(ef)-30 b(\002cienc)-18 b(y)303 +b(is)f(not)i(a)f(concern.)p Black 7796 32754 a Fm(\262)p +Black 606 w Fo(Had)412 b(we)h(w)-12 b(anted)412 b(to)g(conjoin)g(the)h +(v)-30 b(ariables)411 b(in)h(a)g(bottom-up)g(f)-12 b(ashion)412 +b(e)-30 b(v)-18 b(en)412 b(after)9008 34260 y(reordering,)300 +b(we)h(should)f(ha)-24 b(v)-18 b(e)301 b(used)f Fn(Cudd)p +27675 34260 V 437 w(ReadIn)-48 b(vP)-97 b(erm)p Fo(.)374 +b(One)301 b(has)f(to)h(be)f(careful,)9008 35765 y(though,)346 +b(to)338 b(\002x)f(the)h(order)f(of)g(conjunction)h(before)g(entering)f +(the)h(loop.)479 b(Otherwise,)9008 37271 y(if)432 b(reordering)g(tak) +-12 b(es)433 b(place,)465 b(it)433 b(is)f(possible)g(to)h(use)f(one)h +(v)-30 b(ariable)433 b(twice)g(and)g(skip)9008 38776 +y(another)303 b(v)-30 b(ariable.)5978 42075 y Fi(3.8)1328 +b(Basic)332 b(ADD)h(Manipulation)5978 44399 y Fo(The)305 +b(most)f(common)i(w)-12 b(ay)306 b(to)f(manipulate)h(ADDs)f(is)g(via)g +Fn(Cudd)p 33632 44399 V 437 w(addApply)p Fo(.)383 b(This)304 +b(function)5978 45904 y(can)440 b(apply)h(a)f(wide)h(v)-30 +b(ariety)440 b(of)g(operators)f(to)h(a)h(pair)f(of)g(ADDs.)787 +b(Among)441 b(the)f(a)-24 b(v)-30 b(ailable)5978 47409 +y(operators)307 b(are)i(addition,)h(multiplication,)g(di)-30 +b(vision,)309 b(minimum,)h(maximum,)g(and)f(boolean)5978 +48915 y(operators)302 b(that)h(w)-12 b(ork)303 b(on)g(ADDs)g(whose)g +(lea)-24 b(v)-18 b(es)303 b(are)g(restricted)f(to)h(0)g(and)g(1)g +(\(0-1)g(ADDs\).)7859 50420 y(The)k(follo)-30 b(wing)306 +b(fragment)g(of)h(code)g(illustrates)e(ho)-30 b(w)307 +b(to)f(b)-24 b(uild)307 b(the)g(ADD)g(for)f(the)h(func-)5978 +51926 y(tion)c Fk(f)467 b Fl(=)337 b(5)p Fk(x)11806 52108 +y Fc(0)12331 51926 y Fk(x)13024 52108 y Fc(1)13550 51926 +y Fk(x)14243 52108 y Fc(2)14768 51926 y Fk(x)15461 52108 +y Fc(3)15987 51926 y Fo(.)p Black Black 5978 54307 a +Fh(DdManager)729 b(*manager;)5978 55813 y(DdNode)f(*f,)h(*var,)f(*tmp;) +5978 57318 y(int)g(i;)5978 60329 y(...)5978 63340 y(f)f(=)h +(Cudd_addConst\(manager,5\);)5978 64846 y(Cudd_Ref\(f\);)5978 +66351 y(for)g(\(i)f(=)h(3;)g(i)f(>=)h(0;)g(i--\))g({)p +Black 25297 69672 a Fo(13)p Black eop end +%%Page: 14 14 +TeXDict begin 14 13 bop Black Black 8887 7638 a Fh(var)728 +b(=)f(Cudd_addIthVar\(manager,i\);)8887 9143 y(Cudd_Ref\(var\);)8887 +10649 y(tmp)h(=)f(Cudd_addApply\(manager,Cudd_addTimes,var,f\);)8887 +12154 y(Cudd_Ref\(tmp\);)8887 13660 y +(Cudd_RecursiveDeref\(manager,f\);)8887 15165 y +(Cudd_RecursiveDeref\(manager,var\);)8887 16671 y(f)g(=)h(tmp;)5978 +18176 y(})5978 20512 y Fo(This)325 b(e)-18 b(xample,)331 +b(contrasted)326 b(to)g(the)g(e)-18 b(xample)326 b(of)g(BDD)g +(manipulation,)332 b(illustrates)325 b(the)h(fol-)5978 +22017 y(lo)-30 b(wing)303 b(points:)p Black 7796 24353 +a Fm(\262)p Black 606 w Fo(The)281 b(ADD)g(projection)h(function)f(are) +g(not)g(maintained)h(by)f(the)g(manager)-67 b(.)369 b(It)281 +b(is)g(there-)9008 25858 y(fore)302 b(necessary)h(to)g(reference)g(and) +g(dereference)g(them.)p Black 7796 28293 a Fm(\262)p +Black 606 w Fo(The)230 b(product)g(of)g(tw)-12 b(o)231 +b(ADDs)f(is)g(computed)h(by)f(calling)h Fn(Cudd)p 35381 +28293 364 45 v 437 w(addApply)f Fo(with)g Fn(Cudd)p 45705 +28293 V 437 w(addT)-67 b(imes)9008 29799 y Fo(as)250 +b(parameter)-67 b(.)358 b(There)250 b(is)g(no)h(\223apply\224)g +(function)f(for)g(BDDs,)261 b(because)251 b Fn(Cudd)p +41661 29799 V 437 w(bddAnd)9008 31304 y Fo(and)266 b +Fn(Cudd)p 13723 31304 V 437 w(bddXor)293 b Fo(plus)266 +b(complementation)h(are)f(suf)-30 b(\002cient)265 b(to)h(implement)g +(all)g(tw)-12 b(o-)9008 32810 y(ar)-22 b(gument)303 b(boolean)h +(functions.)5978 36099 y Fi(3.9)1328 b(Basic)332 b(ZDD)h(Manipulation) +5978 38423 y Fo(ZDDs)291 b(are)h(often)h(generated)f(by)h(con)-48 +b(v)-18 b(erting)291 b(e)-18 b(xisting)292 b(BDDs.)373 +b(\(See)292 b(Section)g(3.11.\))372 b(Ho)-30 b(w-)5978 +39928 y(e)g(v)-18 b(er)-48 b(,)246 b(it)233 b(is)f(also)h(possible)f +(to)h(b)-24 b(uild)233 b(ZDDs)f(by)h(applying)g(boolean)h(operators)e +(to)h(other)g(ZDDs,)5978 41434 y(starting)345 b(from)h(constants)g(and) +h(projection)f(functions.)506 b(The)346 b(follo)-30 b(wing)346 +b(fragment)h(of)f(code)5978 42939 y(illustrates)406 b(ho)-30 +b(w)408 b(to)g(b)-24 b(uild)408 b(the)g(ZDD)f(for)h(the)g(function)f +Fk(f)662 b Fl(=)531 b Fk(x)34158 42499 y Fd(0)34158 43247 +y Fc(0)35030 42939 y Fl(+)347 b Fk(x)37013 42499 y Fd(0)37013 +43247 y Fc(1)37886 42939 y Fl(+)f Fk(x)39868 42499 y +Fd(0)39868 43247 y Fc(2)40741 42939 y Fl(+)h Fk(x)42724 +42499 y Fd(0)42724 43247 y Fc(3)43249 42939 y Fo(.)691 +b(W)-97 b(e)5978 44445 y(assume)308 b(that)i(the)f(four)g(v)-30 +b(ariables)308 b(already)i(e)-18 b(xist)309 b(in)g(the)g(manager)h +(when)f(the)h(ZDD)f(for)g Fk(f)440 b Fo(is)5978 45950 +y(b)-24 b(uilt.)375 b(Note)303 b(the)h(use)e(of)h(De)h(Mor)-22 +b(g)-6 b(an')-67 b(s)302 b(la)-18 b(w)-79 b(.)p Black +Black 5978 48286 a Fh(DdManager)729 b(*manager;)5978 +49791 y(DdNode)f(*f,)h(*var,)f(*tmp;)5978 51297 y(int)g(i;)5978 +54307 y(manager)h(=)e(Cudd_Init\(0,4,CUDD_UNIQUE_SLOTS,)8887 +55813 y(CUDD_CACHE_SLOTS,0\);)5978 57318 y(...)5978 60329 +y(tmp)h(=)f(Cudd_ReadZddOne\(manager,0\);)5978 61835 +y(Cudd_Ref\(tmp\);)5978 63340 y(for)h(\(i)f(=)h(3;)g(i)f(>=)h(0;)g +(i--\))g({)8887 64846 y(var)g(=)f(Cudd_zddIthVar\(manager,i\);)8887 +66351 y(Cudd_Ref\(var\);)p Black 25297 69672 a Fo(14)p +Black eop end +%%Page: 15 15 +TeXDict begin 15 14 bop Black Black 8887 7638 a Fh(f)727 +b(=)h(Cudd_zddIntersect\(manager,var,tmp\);)8887 9143 +y(Cudd_Ref\(f\);)8887 10649 y(Cudd_RecursiveDerefZdd\(manager,tmp\);) +8887 12154 y(Cudd_RecursiveDerefZdd\(manager,var\);)8887 +13660 y(tmp)g(=)f(f;)5978 15165 y(})5978 16671 y(f)g(=)h +(Cudd_zddDiff\(manager,Cudd_ReadZddOne\(manager,0\),tmp\);)5978 +18176 y(Cudd_Ref\(f\);)5978 19682 y +(Cudd_RecursiveDerefZdd\(manager,tmp\);)5978 22183 y +Fo(This)302 b(e)-18 b(xample)303 b(illustrates)f(the)h(follo)-30 +b(wing)303 b(points:)p Black 7796 24685 a Fm(\262)p Black +606 w Fo(The)k(projection)h(functions)g(are)f(referenced,)i(because)f +(the)-18 b(y)308 b(are)g(not)g(maintained)g(by)9008 26191 +y(the)303 b(manager)-67 b(.)p Black 7796 28692 a Fm(\262)p +Black 606 w Fo(Complementation)304 b(is)f(obtained)g(by)g(subtracting)g +(from)f(the)h(constant)g(1)h(function.)p Black 7796 31194 +a Fm(\262)p Black 606 w Fo(The)f(result)f(of)h Fn(Cudd)p +18204 31194 364 45 v 437 w(ReadZddOne)g Fo(does)g(not)g(require)g +(referencing.)5978 33696 y(CUDD)426 b(pro)-18 b(vides)425 +b(functions)g(for)g(the)h(manipulation)g(of)f(co)-18 +b(v)g(ers)425 b(represented)g(by)h(ZDDs.)5978 35201 y(F)-18 +b(or)529 b(instance,)586 b Fn(Cudd)p 15733 35201 V 437 +w(zddIsop)529 b Fo(b)-24 b(uilds)529 b(a)h(ZDD)f(representing)h(an)g +(irredundant)f(sum)g(of)5978 36707 y(products)368 b(for)h(the)g +(incompletely)h(speci\002ed)f(function)g(de\002ned)h(by)f(the)g(tw)-12 +b(o)369 b(BDDs)h Fk(L)f Fo(and)5978 38212 y Fk(U)132 +b Fo(.)594 b Fn(Cudd)p 10534 38212 V 437 w(zddW)-112 +b(eakDiv)377 b Fo(performs)e(the)h(weak)h(di)-30 b(vision)375 +b(of)h(tw)-12 b(o)377 b(co)-18 b(v)g(ers)375 b(gi)-30 +b(v)-18 b(en)376 b(as)g(ZDDs.)5978 39718 y(These)308 +b(functions)g(e)-18 b(xpect)308 b(the)h(tw)-12 b(o)309 +b(ZDD)f(v)-30 b(ariables)308 b(corresponding)g(to)g(the)h(tw)-12 +b(o)309 b(literals)e(of)5978 41223 y(the)387 b(function)g(v)-30 +b(ariable)388 b(to)f(be)g(adjacent.)630 b(One)388 b(has)f(to)g(create)h +(v)-30 b(ariable)387 b(groups)f(\(see)h(Sec-)5978 42729 +y(tion)288 b(3.14\))f(for)h(reordering)f(of)h(the)g(ZDD)g(v)-30 +b(ariables)287 b(to)h(w)-12 b(ork.)371 b(BDD)288 b(automatic)h +(reordering)5978 44234 y(is)400 b(safe)h(e)-30 b(v)-18 +b(en)401 b(without)h(groups:)572 b(If)400 b(realignment)i(of)f(ZDD)g +(and)h(ADD/BDD)g(v)-30 b(ariables)401 b(is)5978 45740 +y(requested)302 b(\(see)h(Section)g(3.15\))g(groups)g(will)g(be)g(k)-12 +b(ept)303 b(adjacent.)5978 49062 y Fi(3.10)1329 b(Con)-53 +b(v)-13 b(erting)331 b(ADDs)h(to)h(BDDs)f(and)f(V)-49 +b(ice)332 b(V)-133 b(ersa)5978 51386 y Fo(Se)-30 b(v)-18 +b(eral)310 b(procedures)h(are)g(pro)-18 b(vided)311 b(to)h(con)-48 +b(v)-18 b(ert)310 b(ADDs)i(to)f(BDDs,)i(according)f(to)f(dif)-30 +b(ferent)5978 52891 y(criteria.)351 b(\()p Fn(Cudd)p +13168 52891 V 436 w(addBddP)-97 b(attern)p Fo(,)245 b +Fn(Cudd)p 24089 52891 V 437 w(addBddInterval)q Fo(,)f(and)231 +b Fn(Cudd)p 37290 52891 V 437 w(addBddThr)-45 b(eshold)33 +b Fo(.\))5978 54397 y(The)437 b(con)-48 b(v)-18 b(ersion)437 +b(from)g(BDDs)h(to)g(ADDs)g(\()p Fn(Cudd)p 28271 54397 +V 436 w(BddT)-112 b(oAdd)33 b Fo(\))438 b(is)f(based)h(on)f(the)h +(simple)5978 55902 y(principle)305 b(of)h(mapping)g(the)g(logical)g(0)g +(and)g(1)f(on)h(the)g(arithmetic)g(0)g(and)g(1.)384 b(It)305 +b(is)g(also)g(possi-)5978 57408 y(ble)f(to)h(con)-48 +b(v)-18 b(ert)304 b(an)g(ADD)h(with)g(inte)-18 b(ger)304 +b(v)-30 b(alues)304 b(\(more)g(precisely)-79 b(,)305 +b(\003oating)f(point)h(numbers)5978 58913 y(with)e(0)g(fractional)g +(part\))f(to)h(an)g(array)g(of)g(BDDs)g(by)g(repeatedly)h(calling)f +Fn(Cudd)p 40184 58913 V 437 w(addIthBit)22 b Fo(.)5978 +62236 y Fi(3.11)1329 b(Con)-53 b(v)-13 b(erting)331 b(BDDs)h(to)h(ZDDs) +f(and)f(V)-49 b(ice)332 b(V)-133 b(ersa)5978 64559 y +Fo(Man)-18 b(y)282 b(applications)g(\002rst)f(b)-24 b(uild)283 +b(a)f(set)g(of)g(BDDs)h(and)f(then)h(deri)-30 b(v)-18 +b(e)282 b(ZDDs)g(from)f(the)i(BDDs.)5978 66065 y(These)299 +b(applications)g(should)h(create)g(the)f(manager)h(with)g(0)g(ZDD)f(v) +-30 b(ariables)299 b(and)h(create)g(the)p Black 25297 +69672 a(15)p Black eop end +%%Page: 16 16 +TeXDict begin 16 15 bop Black Black 5978 7638 a Fo(BDDs.)536 +b(Then)356 b(the)-18 b(y)357 b(should)f(call)h Fn(Cudd)p +23515 7638 364 45 v 437 w(zddV)-135 b(ar)-12 b(sF)-67 +b(r)-55 b(omBddV)-135 b(ar)-12 b(s)354 b Fo(to)i(create)h(the)g +(necessary)5978 9143 y(ZDD)425 b(v)-30 b(ariables\227whose)424 +b(number)i(is)e(lik)-12 b(ely)426 b(to)f(be)g(kno)-30 +b(wn)426 b(once)f(the)h(BDDs)f(are)h(a)-24 b(v)-30 b(ail-)5978 +10649 y(able.)416 b(This)315 b(approach)i(eliminates)f(the)g(dif)-30 +b(\002culties)316 b(that)g(arise)g(when)h(the)f(number)g(of)g(ZDD)5978 +12154 y(v)-30 b(ariables)302 b(changes)h(while)h(ZDDs)e(are)h(being)g +(b)-24 b(uilt.)7859 13660 y(The)331 b(simplest)f(con)-48 +b(v)-18 b(ersion)329 b(from)h(BDDs)h(to)g(ZDDs)f(is)g(a)h(simple)f +(change)i(of)e(represen-)5978 15165 y(tation,)493 b(which)455 +b(preserv)-18 b(es)453 b(the)j(functions.)830 b(Simply)455 +b(put,)493 b(gi)-30 b(v)-18 b(en)455 b(a)g(BDD)g(for)f +Fk(f)130 b Fo(,)494 b(a)455 b(ZDD)5978 16671 y(for)437 +b Fk(f)569 b Fo(is)437 b(requested.)781 b(In)437 b(this)h(case)g(the)g +(correspondence)g(between)h(the)f(BDD)h(v)-30 b(ariables)5978 +18176 y(and)407 b(ZDD)h(v)-30 b(ariables)407 b(is)g(one-to-one.)689 +b(Hence,)435 b Fn(Cudd)p 29778 18176 V 437 w(zddV)-135 +b(ar)-12 b(sF)-67 b(r)-55 b(omBddV)-135 b(ar)-12 b(s)405 +b Fo(should)i(be)5978 19682 y(called)353 b(with)f(the)h +Fn(multiplicity)g Fo(parameter)g(equal)g(to)g(1.)524 +b(The)353 b(con)-48 b(v)-18 b(ersion)352 b(proper)g(can)h(then)5978 +21187 y(be)475 b(performed)f(by)h(calling)h Fn(Cudd)p +21281 21187 V 437 w(zddP)-97 b(ortF)-67 b(r)-55 b(omBdd)33 +b Fo(.)890 b(The)475 b(in)-48 b(v)-18 b(erse)474 b(transformation)g(is) +5978 22693 y(performed)302 b(by)h Fn(Cudd)p 15543 22693 +V 437 w(zddP)-97 b(ortT)-112 b(oBdd)33 b Fo(.)7859 24198 +y(ZDDs)383 b(are)h(quite)g(often)f(used)g(for)g(the)h(representation)f +(of)g Fn(co)-12 b(ver)g(s)p Fo(.)617 b(This)382 b(is)h(normally)5978 +25704 y(done)459 b(by)g(associating)f(tw)-12 b(o)459 +b(ZDD)g(v)-30 b(ariables)458 b(to)h(each)h(v)-30 b(ariable)458 +b(of)h(the)g(function.)843 b(\(And)5978 27209 y(hence,)340 +b(typically)-79 b(,)341 b(to)333 b(each)h(BDD)f(v)-30 +b(ariable.\))465 b(One)333 b(ZDD)g(v)-30 b(ariable)332 +b(is)g(associated)h(with)g(the)5978 28715 y(positi)-30 +b(v)-18 b(e)428 b(literal)i(of)f(the)h(BDD)g(v)-30 b(ariable,)461 +b(while)430 b(the)f(other)h(ZDD)f(v)-30 b(ariable)429 +b(is)g(associated)5978 30220 y(with)434 b(the)h(ne)-18 +b(g)-6 b(ati)-30 b(v)-18 b(e)434 b(literal.)770 b(A)435 +b(call)g(to)f Fn(Cudd)p 26423 30220 V 437 w(zddV)-135 +b(ar)-12 b(sF)-67 b(r)-55 b(omBddV)-135 b(ar)-12 b(s)432 +b Fo(with)j Fn(multiplicity)5978 31725 y Fo(equal)303 +b(to)g(2)g(will)g(associate)g(to)g(BDD)h(v)-30 b(ariable)303 +b Fk(i)f Fo(the)i(tw)-12 b(o)303 b(ZDD)g(v)-30 b(ariables)302 +b Fl(2)p Fk(i)h Fo(and)g Fl(2)p Fk(i)269 b Fl(+)g(1)p +Fo(.)7859 33231 y(If)291 b(a)h(BDD)h(v)-30 b(ariable)291 +b(group)h(tree)f(e)-18 b(xists)291 b(when)h Fn(Cudd)p +30683 33231 V 437 w(zddV)-135 b(ar)-12 b(sF)-67 b(r)-55 +b(omBddV)-135 b(ar)-12 b(s)289 b Fo(is)j(called)5978 +34736 y(\(see)357 b(Section)i(3.13\))f(the)h(function)f(generates)h(a)f +(ZDD)g(v)-30 b(ariable)359 b(group)f(tree)g(consistent)g(to)5978 +36242 y(it.)758 b(In)430 b(an)-18 b(y)430 b(case,)463 +b(all)430 b(the)h(ZDD)f(v)-30 b(ariables)430 b(deri)-30 +b(v)-18 b(ed)430 b(from)g(the)g(same)h(BDD)g(v)-30 b(ariable)430 +b(are)5978 37747 y(clustered)302 b(into)h(a)h(group.)7859 +39253 y(If)313 b(the)h(ZDD)f(for)g Fk(f)445 b Fo(is)313 +b(created)h(and)f(later)h(a)f(ne)-30 b(w)314 b(ZDD)g(v)-30 +b(ariable)313 b(is)g(added)h(to)g(the)f(man-)5978 40758 +y(ager)-48 b(,)277 b(the)271 b(function)h(represented)f(by)g(the)g(e) +-18 b(xisting)271 b(ZDD)g(changes.)366 b(Suppose,)277 +b(for)271 b(instance,)5978 42264 y(that)323 b(tw)-12 +b(o)322 b(v)-30 b(ariables)323 b(are)f(initially)h(created,)328 +b(and)323 b(that)g(the)g(ZDD)g(for)f Fk(f)504 b Fl(=)373 +b Fk(x)38617 42446 y Fc(0)39427 42264 y Fl(+)284 b Fk(x)41347 +42446 y Fc(1)42195 42264 y Fo(is)322 b(b)-24 b(uilt.)5978 +43769 y(If)430 b(a)i(third)f(v)-30 b(ariable)431 b(is)g(added,)464 +b(say)432 b Fk(x)22854 43951 y Fc(2)23379 43769 y Fo(,)464 +b(then)431 b(the)h(ZDD)f(represents)g Fk(g)618 b Fl(=)574 +b(\()p Fk(x)40722 43951 y Fc(0)41612 43769 y Fl(+)365 +b Fk(x)43613 43951 y Fc(1)44138 43769 y Fl(\))p Fk(x)45302 +43329 y Fd(0)45302 44077 y Fc(2)5978 45275 y Fo(instead.)446 +b(This)326 b(change)h(in)g(function)g(ob)-18 b(viously)326 +b(applies)g(re)-18 b(g)-6 b(ardless)326 b(of)g(what)h(use)g(is)f(made) +5978 46780 y(of)358 b(the)h(ZDD.)543 b(Ho)-30 b(we)g(v)-18 +b(er)-48 b(,)372 b(if)358 b(the)h(ZDD)g(is)f(used)h(to)g(represent)f(a) +h(co)-18 b(v)g(er,)372 b(the)359 b(co)-18 b(v)g(er)359 +b(itself)f(is)5978 48286 y(not)376 b(changed)h(by)g(the)f(addition)h +(of)f(ne)-30 b(w)376 b(v)-30 b(ariable.)596 b(\(What)376 +b(changes)h(is)f(the)g(characteristic)5978 49791 y(function)303 +b(of)f(the)i(co)-18 b(v)g(er)-67 b(.\))5978 53114 y Fi(3.12)1329 +b(V)-122 b(ariable)332 b(Reordering)f(f)-33 b(or)332 +b(BDDs)g(and)f(ADDs)5978 55437 y Fo(The)253 b(CUDD)g(package)h(pro)-18 +b(vides)253 b(a)g(rich)g(set)g(of)g(dynamic)g(reordering)g(algorithms.) +358 b(Some)253 b(of)5978 56943 y(them)303 b(are)g(slight)g(v)-30 +b(ariations)303 b(of)g(e)-18 b(xisting)302 b(techniques)i([16,)f(6,)g +(2,)h(10,)f(15,)h(11];)f(some)g(others)5978 58448 y(ha)-24 +b(v)-18 b(e)303 b(been)g(de)-30 b(v)-18 b(eloped)303 +b(speci\002cally)h(for)e(this)g(package)i([14,)f(13].)7859 +59954 y(Reordering)394 b(af)-30 b(fects)393 b(a)g(unique)h(table.)648 +b(This)393 b(means)g(that)h(BDDs)g(and)g(ADDs,)416 b(which)5978 +61459 y(share)456 b(the)i(same)f(unique)g(table)h(are)f(simultaneously) +g(reordered.)837 b(ZDDs,)496 b(on)457 b(the)g(other)5978 +62965 y(hand,)271 b(are)264 b(reordered)f(separately)-79 +b(.)363 b(In)263 b(the)h(follo)-30 b(wing)263 b(we)h(discuss)f(the)h +(reordering)f(of)g(BDDs)5978 64470 y(and)303 b(ADDs.)376 +b(Reordering)303 b(for)f(ZDDs)h(is)f(the)h(subject)g(of)g(Section)g +(3.14.)p Black 25297 69672 a(16)p Black eop end +%%Page: 17 17 +TeXDict begin 17 16 bop Black Black 7859 7638 a Fo(Reordering)324 +b(of)g(the)f(v)-30 b(ariables)323 b(can)h(be)g(in)-48 +b(v)-24 b(ok)-12 b(ed)323 b(directly)h(by)g(the)f(application)i(by)e +(call-)5978 9143 y(ing)i Fn(Cudd)p 10551 9143 364 45 +v 437 w(ReduceHeap)p Fo(.)444 b(Or)326 b(it)f(can)h(be)g(automatically) +g(triggered)g(by)f(the)h(package)h(when)5978 10649 y(the)394 +b(number)h(of)f(nodes)h(has)f(reached)h(a)g(gi)-30 b(v)-18 +b(en)394 b(threshold.)650 b(\(The)394 b(threshold)g(is)g(initialized) +5978 12154 y(and)k(automatically)g(adjusted)g(after)g(each)g +(reordering)g(by)g(the)g(package.\))661 b(T)-97 b(o)398 +b(enable)g(au-)5978 13660 y(tomatic)351 b(dynamic)h(reordering)f +(\(also)g(called)h Fn(async)-18 b(hr)-55 b(onous)351 +b Fo(dynamic)g(reordering)g(in)h(this)5978 15165 y(document\))457 +b(the)h(application)g(must)f(call)g Fn(Cudd)p 27123 15165 +V 437 w(A)-24 b(utodynEnable)p Fo(.)839 b(Automatic)458 +b(dynamic)5978 16671 y(reordering)302 b(can)h(subsequently)g(be)g +(disabled)g(by)h(calling)f Fn(Cudd)p 33554 16671 V 437 +w(A)-24 b(utodynDisable)p Fo(.)7859 18176 y(All)231 b(reordering)f +(methods)g(are)g(a)-24 b(v)-30 b(ailable)230 b(in)h(both)f(the)h(case)f +(of)g(direct)g(call)h(to)f Fn(Cudd)p 43187 18176 V 437 +w(ReduceHeap)5978 19682 y Fo(and)289 b(the)h(case)f(of)g(automatic)h +(in)-48 b(v)-24 b(ocation.)371 b(F)-18 b(or)289 b(man)-18 +b(y)290 b(methods,)i(the)d(reordering)g(procedure)5978 +21187 y(is)433 b(iterated)h(until)g(no)h(further)e(impro)-18 +b(v)g(ement)434 b(is)g(obtained.)769 b(W)-97 b(e)435 +b(call)f(these)g(methods)g(the)5978 22693 y Fn(con)-48 +b(ver)j(ging)473 b Fo(methods.)887 b(When)474 b(constraints)f(are)g +(imposed)h(on)f(the)h(relati)-30 b(v)-18 b(e)473 b(position)g(of)5978 +24198 y(v)-30 b(ariables)363 b(\(see)g(Section)i(3.13\))e(the)h +(reordering)g(methods)g(apply)g(inside)f(the)h(groups.)558 +b(The)5978 25704 y(groups)401 b(themselv)-18 b(es)401 +b(are)h(reordered)g(by)g(sifting.)672 b(Each)402 b(method)g(is)g +(identi\002ed)g(by)g(a)g(con-)5978 27209 y(stant)297 +b(of)g(the)g(enumerated)h(type)g Fn(Cudd)p 22686 27209 +V 437 w(Reor)-45 b(deringT)-90 b(ype)298 b Fo(de\002ned)f(in)h +Fn(cudd.h)g Fo(\(the)f(e)-18 b(xternal)5978 28715 y(header)303 +b(\002le)g(of)g(the)g(CUDD)h(package\):)p Black 5978 +31548 a Fp(CUDD)p 9551 31548 V 437 w(REORDER)p 16047 +31548 V 437 w(NONE:)p Black 607 w Fo(This)e(method)h(causes)g(no)g +(reordering.)p Black 5978 34050 a Fp(CUDD)p 9551 34050 +V 437 w(REORDER)p 16047 34050 V 437 w(SAME:)p Black 607 +w Fo(If)229 b(passed)h(to)h Fn(Cudd)p 29295 34050 V 437 +w(A)-24 b(utodynEnable)p Fo(,)244 b(this)230 b(method)h(lea)-24 +b(v)-18 b(es)9008 35556 y(the)230 b(current)g(method)h(for)f(automatic) +g(reordering)g(unchanged.)353 b(If)229 b(passed)h(to)g +Fn(Cudd)p 44459 35556 V 437 w(ReduceHeap)p Fo(,)9008 +37061 y(this)302 b(method)i(causes)e(the)i(current)e(method)i(for)e +(automatic)i(reordering)e(to)h(be)g(used.)p Black 5978 +39563 a Fp(CUDD)p 9551 39563 V 437 w(REORDER)p 16047 +39563 V 437 w(RANDOM:)p Black 607 w Fo(P)-18 b(airs)229 +b(of)h(v)-30 b(ariables)230 b(are)g(randomly)h(chosen,)244 +b(and)231 b(sw)-12 b(apped)9008 41068 y(in)384 b(the)f(order)-67 +b(.)618 b(The)383 b(sw)-12 b(ap)384 b(is)f(performed)g(by)h(a)f(series) +g(of)g(sw)-12 b(aps)383 b(of)h(adjacent)g(v)-30 b(ari-)9008 +42574 y(ables.)353 b(The)234 b(best)h(order)f(among)h(those)g(obtained) +g(by)g(the)g(series)e(of)i(sw)-12 b(aps)234 b(is)g(retained.)9008 +44079 y(The)323 b(number)f(of)h(pairs)f(chosen)h(for)f(sw)-12 +b(apping)323 b(equals)g(the)g(number)f(of)h(v)-30 b(ariables)322 +b(in)9008 45585 y(the)303 b(diagram.)p Black 5978 48086 +a Fp(CUDD)p 9551 48086 V 437 w(REORDER)p 16047 48086 +V 437 w(RANDOM)p 22071 48086 V 438 w(PIV)-55 b(O)-48 +b(T:)p Black 605 w Fo(Same)231 b(as)f(CUDD)p 34851 48086 +V 437 w(REORDER)p 40944 48086 V 437 w(RANDOM,)9008 49592 +y(b)-24 b(ut)384 b(the)g(tw)-12 b(o)384 b(v)-30 b(ariables)384 +b(are)g(chosen)g(so)f(that)i(the)f(\002rst)f(is)h(abo)-18 +b(v)g(e)384 b(the)g(v)-30 b(ariable)384 b(with)9008 51097 +y(the)359 b(lar)-22 b(gest)358 b(number)g(of)g(nodes,)372 +b(and)359 b(the)g(second)f(is)g(belo)-30 b(w)359 b(that)f(v)-30 +b(ariable.)542 b(In)358 b(case)9008 52603 y(there)372 +b(are)g(se)-30 b(v)-18 b(eral)372 b(v)-30 b(ariables)371 +b(tied)i(for)e(the)h(maximum)h(number)f(of)g(nodes,)389 +b(the)373 b(one)9008 54108 y(closest)302 b(to)h(the)h(root)e(is)h +(used.)p Black 5978 56610 a Fp(CUDD)p 9551 56610 V 437 +w(REORDER)p 16047 56610 V 437 w(SIFT:)p Black 606 w Fo(This)314 +b(method)i(is)g(an)g(implementation)g(of)f(Rudell')-67 +b(s)316 b(sifting)9008 58115 y(algorithm)349 b([16].)513 +b(A)349 b(simpli\002ed)g(description)f(of)h(sifting)f(is)h(as)f(follo) +-30 b(ws:)467 b(Each)349 b(v)-30 b(ari-)9008 59621 y(able)416 +b(is)f(considered)g(in)h(turn.)713 b(A)415 b(v)-30 b(ariable)416 +b(is)f(mo)-18 b(v)g(ed)415 b(up)h(and)g(do)-30 b(wn)415 +b(in)h(the)g(order)9008 61126 y(so)338 b(that)g(it)h(tak)-12 +b(es)338 b(all)g(possible)g(positions.)481 b(The)338 +b(best)g(position)g(is)g(identi\002ed)g(and)h(the)9008 +62632 y(v)-30 b(ariable)303 b(is)f(returned)h(to)g(that)g(position.) +9008 64635 y(In)399 b(reality)-79 b(,)424 b(things)399 +b(are)h(a)f(bit)h(more)f(complicated.)666 b(F)-18 b(or)399 +b(instance,)424 b(there)400 b(is)f(a)g(limit)9008 66141 +y(on)390 b(the)h(number)f(of)g(v)-30 b(ariables)389 b(that)i(will)f(be) +h(sifted.)636 b(This)390 b(limit)g(can)g(be)h(read)f(with)p +Black 25297 69672 a(17)p Black eop end +%%Page: 18 18 +TeXDict begin 18 17 bop Black Black 9008 7638 a Fn(Cudd)p +11707 7638 364 45 v 437 w(ReadSiftMaxV)-135 b(ar)349 +b Fo(and)323 b(set)f(with)g Fn(Cudd)p 29284 7638 V 437 +w(SetSiftMaxV)-135 b(ar)28 b Fo(.)434 b(In)322 b(addition,)327 +b(if)322 b(the)9008 9143 y(diagram)399 b(gro)-30 b(ws)399 +b(too)g(much)h(while)f(mo)-18 b(ving)400 b(a)f(v)-30 +b(ariable)399 b(up)h(or)f(do)-30 b(wn,)423 b(that)400 +b(mo)-18 b(v)g(e-)9008 10649 y(ment)482 b(is)f(terminated)h(before)g +(the)g(v)-30 b(ariable)482 b(has)g(reached)g(one)g(end)g(of)g(the)g +(order)-67 b(.)9008 12154 y(The)358 b(maximum)h(ratio)f(by)h(which)g +(the)g(diagram)f(is)g(allo)-30 b(wed)359 b(to)f(gro)-30 +b(w)359 b(while)f(a)h(v)-30 b(ari-)9008 13660 y(able)448 +b(is)g(being)g(sifted)f(can)i(be)f(read)g(with)g Fn(Cudd)p +30573 13660 V 437 w(ReadMaxGr)-55 b(owth)449 b Fo(and)f(set)g(with)9008 +15165 y Fn(Cudd)p 11707 15165 V 437 w(SetMaxGr)-55 b(owth)p +Fo(.)p Black 5978 17574 a Fp(CUDD)p 9551 17574 V 437 +w(REORDER)p 16047 17574 V 437 w(SIFT)p 19179 17574 V +436 w(CONVERGE:)p Black 608 w Fo(This)229 b(is)h(the)g(con)-48 +b(v)-18 b(er)c(ging)230 b(v)-30 b(ariant)230 b(of)g(CUDD-)p +9008 19080 V 9372 19080 a(REORDER)p 15101 19080 V 437 +w(SIFT)-90 b(.)p Black 5978 21488 a Fp(CUDD)p 9551 21488 +V 437 w(REORDER)p 16047 21488 V 437 w(SYMM)p 20321 21488 +V 437 w(SIFT:)p Black 606 w Fo(This)441 b(method)h(is)f(an)h +(implementation)g(of)g(sym-)9008 22994 y(metric)350 b(sifting)f([14].) +516 b(It)350 b(is)f(similar)g(to)h(sifting,)361 b(with)350 +b(one)h(addition:)470 b(V)-135 b(ariables)350 b(that)9008 +24499 y(become)291 b(adjacent)g(during)g(sifting)f(are)g(tested)h(for)f +(symmetry.)371 b(If)290 b(the)-18 b(y)290 b(are)h(symmet-)9008 +26005 y(ric,)450 b(the)-18 b(y)421 b(are)g(link)-12 b(ed)421 +b(in)g(a)g(group.)730 b(Sifting)421 b(then)g(continues)g(with)g(a)g +(group)g(being)9008 27510 y(mo)-18 b(v)g(ed,)416 b(instead)393 +b(of)g(a)h(single)f(v)-30 b(ariable.)647 b(After)393 +b(symmetric)g(sifting)f(has)h(been)h(run,)9008 29016 +y Fn(Cudd)p 11707 29016 V 437 w(SymmPr)-55 b(o\002le)409 +b Fo(can)g(be)g(called)g(to)g(report)f(on)h(the)g(symmetry)f(groups)g +(found.)9008 30521 y(\(Both)303 b(positi)-30 b(v)-18 +b(e)302 b(and)i(ne)-18 b(g)-6 b(ati)-30 b(v)-18 b(e)303 +b(symmetries)f(are)h(reported.\))p Black 5978 32930 a +Fp(CUDD)p 9551 32930 V 437 w(REORDER)p 16047 32930 V +437 w(SYMM)p 20321 32930 V 437 w(SIFT)p 23453 32930 V +436 w(CONV:)p Black 606 w Fo(This)230 b(is)g(the)g(con)-48 +b(v)-18 b(er)c(ging)230 b(v)-30 b(ariant)230 b(of)g(CUDD-)p +9008 34435 V 9372 34435 a(REORDER)p 15101 34435 V 437 +w(SYMM)p 19243 34435 V 435 w(SIFT)-90 b(.)p Black 5978 +36844 a Fp(CUDD)p 9551 36844 V 437 w(REORDER)p 16047 +36844 V 437 w(GR)-36 b(OUP)p 20825 36844 V 436 w(SIFT:)p +Black 606 w Fo(This)289 b(method)i(is)g(an)g(implementation)g(of)f +(group)9008 38350 y(sifting)232 b([13].)352 b(It)233 +b(is)f(similar)h(to)g(symmetric)g(sifting,)246 b(b)-24 +b(ut)233 b(aggre)-18 b(g)-6 b(ation)233 b(is)g(not)g(restricted)9008 +39855 y(to)303 b(symmetric)f(v)-30 b(ariables.)p Black +5978 42264 a Fp(CUDD)p 9551 42264 V 437 w(REORDER)p 16047 +42264 V 437 w(GR)-36 b(OUP)p 20825 42264 V 436 w(SIFT)p +23956 42264 V 436 w(CONV:)p Black 606 w Fo(This)468 b(method)g(repeats) +g(until)g(con)-48 b(v)-18 b(er)-24 b(-)9008 43769 y(gence)484 +b(the)g(combination)h(of)e(CUDD)p 25827 43769 V 438 w(REORDER)p +31921 43769 V 437 w(GR)-48 b(OUP)p 36417 43769 V 437 +w(SIFT)482 b(and)j(CUDD-)p 9008 45275 V 9372 45275 a(REORDER)p +15101 45275 V 437 w(WINDO)-42 b(W4.)p Black 5978 47683 +a Fp(CUDD)p 9551 47683 V 437 w(REORDER)p 16047 47683 +V 437 w(WINDO)-61 b(W2:)p Black 607 w Fo(This)392 b(method)i +(implements)f(the)h(windo)-30 b(w)394 b(permu-)9008 49189 +y(tation)434 b(approach)h(of)f(Fujita)h([8)o(])f(and)h(Ishiura)e([10].) +769 b(The)434 b(size)h(of)f(the)g(windo)-30 b(w)435 b(is)9008 +50694 y(2.)p Black 5978 53103 a Fp(CUDD)p 9551 53103 +V 437 w(REORDER)p 16047 53103 V 437 w(WINDO)-61 b(W3:)p +Black 607 w Fo(Similar)230 b(to)g(CUDD)p 32035 53103 +V 437 w(REORDER)p 38128 53103 V 437 w(WINDO)-42 b(W2,)246 +b(b)-24 b(ut)9008 54609 y(with)303 b(a)g(windo)-30 b(w)303 +b(of)g(size)g(3.)p Black 5978 57017 a Fp(CUDD)p 9551 +57017 V 437 w(REORDER)p 16047 57017 V 437 w(WINDO)-61 +b(W4:)p Black 607 w Fo(Similar)230 b(to)g(CUDD)p 32035 +57017 V 437 w(REORDER)p 38128 57017 V 437 w(WINDO)-42 +b(W2,)246 b(b)-24 b(ut)9008 58523 y(with)303 b(a)g(windo)-30 +b(w)303 b(of)g(size)g(4.)p Black 5978 60932 a Fp(CUDD)p +9551 60932 V 437 w(REORDER)p 16047 60932 V 437 w(WINDO)-61 +b(W2)p 22618 60932 V 437 w(CONV:)p Black 606 w Fo(This)230 +b(is)g(the)g(con)-48 b(v)-18 b(er)c(ging)230 b(v)-30 +b(ariant)230 b(of)g(CUDD-)p 9008 62437 V 9372 62437 a(REORDER)p +15101 62437 V 437 w(WINDO)-42 b(W2.)p Black 5978 64846 +a Fp(CUDD)p 9551 64846 V 437 w(REORDER)p 16047 64846 +V 437 w(WINDO)-61 b(W3)p 22618 64846 V 437 w(CONV:)p +Black 606 w Fo(This)230 b(is)g(the)g(con)-48 b(v)-18 +b(er)c(ging)230 b(v)-30 b(ariant)230 b(of)g(CUDD-)p 9008 +66351 V 9372 66351 a(REORDER)p 15101 66351 V 437 w(WINDO)-42 +b(W3.)p Black 25297 69672 a(18)p Black eop end +%%Page: 19 19 +TeXDict begin 19 18 bop Black Black Black 5978 7638 a +Fp(CUDD)p 9551 7638 364 45 v 437 w(REORDER)p 16047 7638 +V 437 w(WINDO)-61 b(W4)p 22618 7638 V 437 w(CONV:)p Black +606 w Fo(This)230 b(is)g(the)g(con)-48 b(v)-18 b(er)c(ging)230 +b(v)-30 b(ariant)230 b(of)g(CUDD-)p 9008 9143 V 9372 +9143 a(REORDER)p 15101 9143 V 437 w(WINDO)-42 b(W4.)p +Black 5978 11566 a Fp(CUDD)p 9551 11566 V 437 w(REORDER)p +16047 11566 V 437 w(ANNEALING:)p Black 607 w Fo(This)312 +b(method)h(is)f(an)h(implementation)g(of)f(simu-)9008 +13071 y(lated)271 b(annealing)g(for)f(v)-30 b(ariable)271 +b(ordering,)277 b(v)-30 b(aguely)271 b(resemblant)f(of)h(the)g +(algorithm)f(of)9008 14577 y([2].)375 b(This)302 b(method)i(is)e +(potentially)h(v)-18 b(ery)303 b(slo)-30 b(w)-79 b(.)p +Black 5978 16999 a Fp(CUDD)p 9551 16999 V 437 w(REORDER)p +16047 16999 V 437 w(GENETIC:)p Black 607 w Fo(This)344 +b(method)i(is)e(an)h(implementation)h(of)e(a)i(genetic)9008 +18504 y(algorithm)328 b(for)f(v)-30 b(ariable)329 b(ordering,)334 +b(inspired)327 b(by)i(the)f(w)-12 b(ork)328 b(of)g(Drechsler)f([6].)451 +b(This)9008 20010 y(method)303 b(is)g(potentially)g(v)-18 +b(ery)303 b(slo)-30 b(w)-79 b(.)p Black 5978 22432 a +Fp(CUDD)p 9551 22432 V 437 w(REORDER)p 16047 22432 V +437 w(EXA)-67 b(CT:)p Black 608 w Fo(This)293 b(method)i(implements)f +(a)h(dynamic)f(programming)9008 23937 y(approach)249 +b(to)f(e)-18 b(xact)248 b(reordering)g([9,)g(7,)g(10)q(],)258 +b(with)249 b(impro)-18 b(v)g(ements)247 b(described)h(in)h([11)o(].) +9008 25443 y(It)433 b(only)g(stores)f(one)h(BDD)h(at)f(the)g(time.)766 +b(Therefore,)465 b(it)433 b(is)g(relati)-30 b(v)-18 b(ely)432 +b(ef)-30 b(\002cient)433 b(in)9008 26948 y(terms)374 +b(of)g(memory)-79 b(.)592 b(Compared)375 b(to)g(other)f(reordering)h +(strate)-18 b(gies,)391 b(it)375 b(is)f(v)-18 b(ery)375 +b(slo)-30 b(w)-79 b(,)9008 28454 y(and)303 b(is)g(not)g(recommended)g +(for)g(more)g(than)g(16)g(v)-30 b(ariables.)5978 31049 +y(So)301 b(f)-12 b(ar)301 b(we)h(ha)-24 b(v)-18 b(e)302 +b(described)g(methods)f(whereby)h(the)g(package)h(selects)e(an)h(order) +f(automati-)5978 32555 y(cally)-79 b(.)352 b(A)230 b(gi)-30 +b(v)-18 b(en)230 b(order)g(of)g(the)h(v)-30 b(ariables)229 +b(can)i(also)f(be)g(imposed)h(by)f(calling)h Fn(Cudd)p +40685 32555 V 437 w(Shuf)-22 b(\003eHeap)p Fo(.)5978 +35838 y Fi(3.13)1329 b(Gr)-24 b(ouping)331 b(V)-122 b(ariables)5978 +38162 y Fo(CUDD)400 b(allo)-30 b(ws)400 b(the)g(application)h(to)f +(specify)f(constraints)g(on)i(the)f(positions)f(of)h(group)f(of)5978 +39667 y(v)-30 b(ariables.)804 b(It)446 b(is)f(possible)g(to)h(request)g +(that)g(a)h(group)e(of)h(contiguous)g(v)-30 b(ariables)446 +b(be)g(k)-12 b(ept)5978 41173 y(contiguous)463 b(by)g(the)g(reordering) +g(procedures.)855 b(It)463 b(is)g(also)f(possible)h(to)g(request)g +(that)g(the)5978 42678 y(relati)-30 b(v)-18 b(e)382 b(order)g(of)g +(some)g(groups)g(of)g(v)-30 b(ariables)382 b(be)g(left)g(unchanged.)615 +b(The)383 b(constraints)e(on)5978 44183 y(the)303 b(order)f(are)h +(speci\002ed)g(by)h(means)f(of)f(a)h(tree,)g(which)h(is)e(created)i(in) +f(one)g(of)g(tw)-12 b(o)303 b(w)-12 b(ays:)p Black 7796 +46486 a Fm(\262)p Black 606 w Fo(By)303 b(calling)h Fn(Cudd)p +17027 46486 V 437 w(Mak)-12 b(eT)-67 b(r)-45 b(eeNode)p +Fo(.)p Black 7796 48909 a Fm(\262)p Black 606 w Fo(By)289 +b(calling)f(the)h(functions)e(of)h(the)h(MTR)f(library)f(\(part)h(of)g +(the)h(distrib)-24 b(ution\),)289 b(and)g(by)9008 50414 +y(re)-18 b(gistering)286 b(the)h(result)f(with)h(the)g(manager)g(using) +f Fn(Cudd)p 33491 50414 V 437 w(SetT)-67 b(r)-45 b(ee)p +Fo(.)371 b(The)287 b(current)f(tree)9008 51920 y(re)-18 +b(gistered)302 b(with)h(the)g(manager)h(can)f(be)g(read)h(with)f +Fn(Cudd)p 33770 51920 V 437 w(ReadT)-67 b(r)-45 b(ee)p +Fo(.)7859 54223 y(Each)469 b(node)f(in)h(the)f(tree)h(represents)e(a)h +(range)h(of)f(v)-30 b(ariables.)871 b(The)468 b(lo)-30 +b(wer)468 b(bound)g(of)5978 55728 y(the)365 b(range)g(is)f(gi)-30 +b(v)-18 b(en)365 b(by)g(the)g Fn(low)h Fo(\002eld)f(of)g(the)g(node,) +381 b(and)365 b(the)g(size)g(of)g(the)g(group)g(is)f(gi)-30 +b(v)-18 b(en)5978 57233 y(by)425 b(the)h Fn(size)e Fo(\002eld)h(of)g +(the)h(node.)20346 56794 y Fg(2)21587 57233 y Fo(The)f(v)-30 +b(ariables)425 b(in)g(each)h(range)f(are)h(k)-12 b(ept)425 +b(contiguous.)5978 58739 y(Furthermore,)263 b(if)253 +b(a)h(node)g(is)g(mark)-12 b(ed)254 b(with)g(the)g(MTR)p +28784 58739 V 436 w(FIXED)f(\003ag,)264 b(then)254 b(the)g(relati)-30 +b(v)-18 b(e)254 b(order)5978 60244 y(of)415 b(the)g(v)-30 +b(ariable)416 b(ranges)f(associated)g(to)g(its)g(children)h(is)f(not)g +(changed.)714 b(As)415 b(an)h(e)-18 b(xample,)5978 61750 +y(suppose)302 b(the)h(initial)g(v)-30 b(ariable)303 b(order)g(is:)p +Black 5978 62752 15940 45 v 7383 63493 a Ff(2)7771 63916 +y Fe(When)239 b(the)g(v)-25 b(ariables)239 b(in)g(a)g(group)g(are)f +(reordered,)k(the)d(association)g(between)h(the)e Fb(low)h +Fe(\002eld)f(and)h(the)g(inde)-15 b(x)5978 65134 y(of)291 +b(the)h(\002rst)f(v)-25 b(ariable)293 b(in)f(the)g(group)g(is)g(lost.) +436 b(The)292 b(package)i(updates)e(the)g(tree)g(to)g(k)-10 +b(eep)293 b(track)f(of)g(the)g(changes.)5978 66351 y(Ho)-25 +b(we)g(v)-15 b(er)-40 b(,)250 b(the)g(application)g(cannot)g(rely)g(on) +f Fb(low)g Fe(to)g(determine)h(the)f(position)g(of)g(v)-25 +b(ariables.)p Black Black 25297 69672 a Fo(19)p Black +eop end +%%Page: 20 20 +TeXDict begin 20 19 bop Black Black Black Black 5978 +7638 a Fh(x0,)728 b(y0,)g(z0,)g(x1,)g(y1,)g(z1,)g(...)g(,)g(x9,)g(y9,)g +(z9.)5978 9977 y Fo(Suppose)334 b(we)g(w)-12 b(ant)335 +b(to)f(k)-12 b(eep)335 b(each)g(group)f(of)g(three)g(v)-30 +b(ariables)334 b(with)g(the)h(same)f(inde)-18 b(x)334 +b(\(e.g.,)5978 11483 y Fh(x3,)728 b(y3,)g(z3)p Fo(\))299 +b(contiguous,)g(while)h(allo)-30 b(wing)299 b(the)g(package)g(to)g +(change)h(the)f(order)f(of)h(the)5978 12988 y(groups.)375 +b(W)-97 b(e)303 b(can)h(accomplish)f(this)f(with)h(the)h(follo)-30 +b(wing)302 b(code:)p Black Black 5978 15328 a Fh(for)728 +b(\(i)f(=)h(0;)g(i)f(<)h(10;)g(i++\))g({)8887 16833 y(\(void\))h +(Cudd_MakeTreeNode\(manager,i*3,3,MTR_DEFAULT\);)5978 +18339 y(})5978 20678 y Fo(If)335 b(we)h(w)-12 b(ant)336 +b(to)g(k)-12 b(eep)336 b(the)g(order)f(within)h(each)h(group)f(of)f(v) +-30 b(ariables)335 b(\002x)-18 b(ed)336 b(\(i.e.,)344 +b Fh(x)336 b Fo(before)g Fh(y)5978 22184 y Fo(before)302 +b Fh(z)p Fo(\))h(we)h(need)f(to)g(change)h(MTR)p 22800 +22184 364 45 v 436 w(DEF)-90 b(A)-67 b(UL)-112 b(T)303 +b(into)g(MTR)p 33608 22184 V 436 w(FIXED.)7859 23689 +y(The)411 b Fn(low)f Fo(parameter)h(passed)e(to)i Fn(Cudd)p +25267 23689 V 437 w(Mak)-12 b(eT)-67 b(r)-45 b(eeNode)411 +b Fo(is)f(the)g(inde)-18 b(x)411 b(of)f(a)g(v)-30 b(ariable)5978 +25195 y(\(as)343 b(opposed)i(to)f(its)g(le)-30 b(v)-18 +b(el)344 b(or)g(position)g(in)h(the)f(order\).)499 b(The)344 +b(group)h(tree)f(can)h(be)f(created)h(at)5978 26700 y(an)-18 +b(y)353 b(time.)528 b(The)353 b(result)g(ob)-18 b(viously)354 +b(depends)f(on)h(the)g(v)-30 b(ariable)353 b(order)h(in)f(ef)-30 +b(fect)353 b(at)h(creation)5978 28206 y(time.)7859 29711 +y(It)255 b(is)f(possible)g(to)g(create)h(a)g(v)-30 b(ariable)254 +b(group)h(tree)f(also)h(before)f(the)h(v)-30 b(ariables)254 +b(themselv)-18 b(es)5978 31216 y(are)263 b(created.)363 +b(The)263 b(package)i(assumes)d(in)h(this)g(case)h(that)g(the)f(inde) +-18 b(x)264 b(of)f(the)h(v)-30 b(ariables)262 b(not)i(yet)5978 +32722 y(in)280 b(e)-18 b(xistence)281 b(will)g(equal)g(their)f +(position)g(in)h(the)g(order)f(when)h(the)-18 b(y)281 +b(are)f(created.)369 b(Therefore,)5978 34227 y(applications)335 +b(that)h(rely)f(on)h Fn(Cudd)p 20792 34227 V 437 w(bddNe)-18 +b(wV)-135 b(arAtLe)-18 b(vel)337 b Fo(or)f Fn(Cudd)p +34861 34227 V 437 w(addNe)-18 b(wV)-135 b(arAtLe)-18 +b(vel)337 b Fo(to)5978 35733 y(create)303 b(ne)-30 b(w)303 +b(v)-30 b(ariables)302 b(ha)-24 b(v)-18 b(e)304 b(to)f(create)g(the)g +(v)-30 b(ariables)302 b(before)h(the)-18 b(y)303 b(group)g(them.)7859 +37238 y(The)407 b(reordering)e(procedure)i(will)f(skip)g(all)g(groups)g +(whose)g(v)-30 b(ariables)406 b(are)g(not)h(yet)f(in)5978 +38744 y(e)-18 b(xistence.)393 b(F)-18 b(or)308 b(groups)h(that)g(are)g +(only)g(partially)f(in)h(e)-18 b(xistence,)311 b(the)e(reordering)f +(procedure)5978 40249 y(will)232 b(try)f(to)h(reorder)g(the)g(v)-30 +b(ariables)231 b(already)h(instantiated,)247 b(without)232 +b(violating)g(the)g(adjacenc)-18 b(y)5978 41755 y(constraints.)5978 +45045 y Fi(3.14)1329 b(V)-122 b(ariable)332 b(Reordering)f(f)-33 +b(or)332 b(ZDDs)5978 47369 y Fo(Reordering)288 b(of)f(ZDDs)g(is)g(done) +h(in)g(much)g(the)g(same)f(w)-12 b(ay)288 b(as)g(the)f(reordering)h(of) +f(BDDs)h(and)5978 48874 y(ADDs.)379 b(The)304 b(functions)g +(corresponding)f(to)i Fn(Cudd)p 27947 48874 V 437 w(ReduceHeap)g +Fo(and)f Fn(Cudd)p 39561 48874 V 437 w(Shuf)-22 b(\003eHeap)5978 +50380 y Fo(are)310 b Fn(Cudd)p 10467 50380 V 437 w(zddReduceHeap)h +Fo(and)g Fn(Cudd)p 23778 50380 V 437 w(zddShuf)-22 b(\003eHeap)p +Fo(.)399 b(T)-97 b(o)310 b(enable)h(dynamic)g(reorder)-24 +b(-)5978 51885 y(ing,)468 b(the)436 b(application)g(must)g(call)f +Fn(Cudd)p 23715 51885 V 437 w(A)-24 b(utodynEnableZdd)33 +b Fo(,)469 b(and)436 b(to)f(disable)h(dynamic)5978 53391 +y(reordering,)340 b(it)334 b(must)f(call)h Fn(Cudd)p +20152 53391 V 437 w(A)-24 b(utodynDisableZdd)33 b Fo(.)466 +b(In)334 b(the)f(current)h(implementation,)5978 54896 +y(ho)-30 b(we)g(v)-18 b(er)-48 b(,)296 b(the)f(choice)h(of)g +(reordering)f(methods)g(for)g(ZDDs)g(is)g(more)g(limited.)373 +b(Speci\002cally)-79 b(,)5978 56402 y(these)302 b(methods)h(are)g(a)-24 +b(v)-30 b(ailable:)p Black 5978 59041 a Fp(CUDD)p 9551 +59041 V 437 w(REORDER)p 16047 59041 V 437 w(NONE;)p Black +Black 5978 61478 a(CUDD)p 9551 61478 V 437 w(REORDER)p +16047 61478 V 437 w(SAME;)p Black Black 5978 63914 a(CUDD)p +9551 63914 V 437 w(REORDER)p 16047 63914 V 437 w(RANDOM;)p +Black Black 5978 66351 a(CUDD)p 9551 66351 V 437 w(REORDER)p +16047 66351 V 437 w(RANDOM)p 22071 66351 V 438 w(PIV)-55 +b(O)-48 b(T;)p Black Black 25297 69672 a Fo(20)p Black +eop end +%%Page: 21 21 +TeXDict begin 21 20 bop Black Black Black 5978 7638 a +Fp(CUDD)p 9551 7638 364 45 v 437 w(REORDER)p 16047 7638 +V 437 w(SIFT;)p Black Black 5978 10140 a(CUDD)p 9551 +10140 V 437 w(REORDER)p 16047 10140 V 437 w(SIFT)p 19179 +10140 V 436 w(CONVERGE;)p Black Black 5978 12641 a(CUDD)p +9551 12641 V 437 w(REORDER)p 16047 12641 V 437 w(SYMM)p +20321 12641 V 437 w(SIFT;)p Black Black 5978 15143 a(CUDD)p +9551 15143 V 437 w(REORDER)p 16047 15143 V 437 w(SYMM)p +20321 15143 V 437 w(SIFT)p 23453 15143 V 436 w(CONV.)p +Black 7859 17977 a Fo(T)-97 b(o)270 b(create)h(ZDD)f(v)-30 +b(ariable)270 b(groups,)276 b(the)270 b(application)h(calls)f +Fn(Cudd)p 35926 17977 V 437 w(Mak)-12 b(eZddT)-67 b(r)-45 +b(eeNode)p Fo(.)5978 21300 y Fi(3.15)1329 b(K)-33 b(eeping)331 +b(Consistent)h(V)-122 b(ariable)332 b(Orders)f(f)-33 +b(or)332 b(BDDs)g(and)f(ZDDs)5978 23623 y Fo(Se)-30 b(v)-18 +b(eral)298 b(applications)g(that)h(manipulate)g(both)g(BDDs)g(and)f +(ZDDs)g(bene\002t)h(from)f(k)-12 b(eeping)299 b(a)5978 +25129 y(\002x)-18 b(ed)314 b(correspondence)g(between)h(the)g(order)f +(of)g(the)g(BDD)h(v)-30 b(ariables)314 b(and)h(the)f(order)g(of)g(the) +5978 26634 y(ZDD)390 b(v)-30 b(ariables.)638 b(If)390 +b(each)h(BDD)h(v)-30 b(ariable)390 b(corresponds)g(to)h(a)f(group)h(of) +f(ZDD)h(v)-30 b(ariables,)5978 28140 y(then)423 b(it)h(is)f(often)g +(desirable)g(that)h(the)g(groups)f(of)g(ZDD)g(v)-30 b(ariables)423 +b(be)h(in)f(the)h(same)g(order)5978 29645 y(as)414 b(the)h +(corresponding)f(BDD)i(v)-30 b(ariables.)710 b(CUDD)415 +b(allo)-30 b(ws)415 b(the)g(ZDD)f(order)g(to)h(track)g(the)5978 +31150 y(BDD)371 b(order)g(and)h(vice)f(v)-18 b(ersa.)579 +b(T)-97 b(o)371 b(ha)-24 b(v)-18 b(e)371 b(the)h(ZDD)f(order)f(track)i +(the)f(BDD)h(order)-48 b(,)387 b(the)371 b(ap-)5978 32656 +y(plication)342 b(calls)g Fn(Cudd)p 15825 32656 V 437 +w(zddRealignEnable)p Fo(.)491 b(The)342 b(ef)-30 b(fect)342 +b(of)f(this)h(call)g(can)g(be)g(re)-30 b(v)-18 b(ersed)341 +b(by)5978 34161 y(calling)374 b Fn(Cudd)p 12350 34161 +V 437 w(zddRealignDisable)p Fo(.)587 b(When)374 b(ZDD)f(realignment)h +(is)f(in)h(ef)-30 b(fect,)391 b(automatic)5978 35667 +y(reordering)302 b(of)h(ZDDs)f(should)h(be)g(disabled.)5978 +38989 y Fi(3.16)1329 b(Hooks)5978 41313 y Fo(Hooks)268 +b(in)h(CUDD)g(are)g(lists)f(of)g(application-speci\002ed)h(functions)f +(to)h(be)g(run)g(on)f(certain)h(oc-)5978 42818 y(casions.)351 +b(Each)230 b(hook)g(is)g(identi\002ed)h(by)f(a)h(constant)f(of)g(the)g +(enumerated)h(type)g Fn(Cudd)p 41691 42818 V 437 w(HookT)-90 +b(ype)p Fo(.)5978 44324 y(In)302 b(V)-135 b(ersion)303 +b(2.4.2)h(hooks)e(are)h(de\002ned)h(for)e(these)h(occasions:)p +Black 7796 46826 a Fm(\262)p Black 606 w Fo(before)g(g)-6 +b(arbage)303 b(collection)h(\(CUDD)p 25534 46826 V 436 +w(PRE)p 28193 46826 V 437 w(GC)p 30313 46826 V 437 w(HOOK\);)p +Black 7796 49327 a Fm(\262)p Black 606 w Fo(after)e(g)-6 +b(arbage)304 b(collection)f(\(CUDD)p 24658 49327 V 437 +w(POST)p 28059 49327 V 436 w(GC)p 30178 49327 V 437 w(HOOK\);)p +Black 7796 51829 a Fm(\262)p Black 606 w Fo(before)g(v)-30 +b(ariable)303 b(reordering)f(\(CUDD)p 25845 51829 V 437 +w(PRE)p 28505 51829 V 436 w(REORDERING)p 36751 51829 +V 438 w(HOOK\);)p Black 7796 54331 a Fm(\262)p Black +606 w Fo(after)g(v)-30 b(ariable)303 b(reordering)g(\(CUDD)p +24970 54331 V 437 w(POST)p 28371 54331 V 436 w(REORDERING)p +36617 54331 V 437 w(HOOK\).)5978 56833 y(The)315 b(current)g +(implementation)h(of)f(hooks)g(is)g(e)-18 b(xperimental.)412 +b(A)316 b(function)f(added)h(to)f(a)h(hook)5978 58338 +y(recei)-30 b(v)-18 b(es)232 b(a)g(pointer)h(to)g(the)f(manager)-48 +b(,)247 b(a)233 b(pointer)f(to)h(a)g(constant)f(string,)246 +b(and)233 b(a)g(pointer)g(to)f(v)-24 b(oid)5978 59844 +y(as)342 b(ar)-22 b(guments;)362 b(it)343 b(must)f(return)h(1)f(if)h +(successful;)361 b(0)343 b(otherwise.)494 b(The)343 b(second)g(ar)-22 +b(gument)343 b(is)5978 61349 y(one)259 b(of)f(\223DD,)-85 +b(\224)259 b(\223BDD,)-85 b(\224)260 b(and)f(\223ZDD.)-85 +b(\224)259 b(This)f(allo)-30 b(ws)258 b(the)h(hook)g(functions)f(to)h +(tell)g(the)g(type)f(of)5978 62854 y(diagram)241 b(for)f(which)h +(reordering)f(or)h(g)-6 b(arbage)241 b(collection)g(tak)-12 +b(es)241 b(place.)356 b(The)240 b(third)h(ar)-22 b(gument)5978 +64360 y(v)-30 b(aries)369 b(depending)h(on)g(the)g(hook.)577 +b(The)369 b(hook)i(functions)e(called)h(before)g(or)f(after)h(g)-6 +b(arbage)5978 65865 y(collection)294 b(do)g(not)g(use)f(it.)373 +b(The)293 b(hook)h(functions)f(called)i(before)e(reordering)g(are)h +(passed,)h(in)p Black 25297 69672 a(21)p Black eop end +%%Page: 22 22 +TeXDict begin 22 21 bop Black Black 5978 7638 a Fo(addition)382 +b(to)h(the)g(pointer)f(to)h(the)g(manager)-48 b(,)402 +b(also)382 b(the)h(method)g(used)f(for)g(reordering.)614 +b(The)5978 9143 y(hook)331 b(functions)g(called)g(after)g(reordering)g +(are)g(passed)g(the)g(start)g(time.)460 b(T)-97 b(o)331 +b(add)h(a)f(function)5978 10649 y(to)294 b(a)h(hook,)i(one)e(uses)e +Fn(Cudd)p 18197 10649 364 45 v 437 w(AddHook)21 b Fo(.)373 +b(The)295 b(function)f(of)g(a)h(gi)-30 b(v)-18 b(en)295 +b(hook)g(are)f(called)h(in)g(the)5978 12154 y(order)328 +b(in)i(which)f(the)-18 b(y)330 b(were)f(added)h(to)f(the)h(hook.)455 +b(F)-18 b(or)328 b(sample)h(hook)h(functions,)335 b(one)330 +b(may)5978 13660 y(look)303 b(at)g Fn(Cudd)p 12313 13660 +V 437 w(StdPr)-45 b(eReor)g(dHook)323 b Fo(and)303 b +Fn(Cudd)p 26550 13660 V 437 w(StdP)-97 b(ostReor)-45 +b(dHook)21 b Fo(.)5978 16942 y Fi(3.17)1329 b(The)331 +b(SIS/VIS)f(Interface)5978 19266 y Fo(The)357 b(CUDD)i(package)g +(contains)f(interf)-12 b(ace)358 b(functions)f(that)h(emulate)g(the)g +(beha)-24 b(vior)358 b(of)g(the)5978 20772 y(original)j(BDD)g(package)h +(used)f(in)g(SIS)g([17])f(and)i(in)f(the)g(ne)-30 b(wer)361 +b(VIS)36244 20332 y Fg(3)37103 20772 y Fo([4)o(].)550 +b(Ho)-30 b(w)361 b(to)g(b)-24 b(uild)5978 22277 y(VIS)408 +b(with)h(CUDD)g(is)f(described)h(in)g(the)g(installation)f(documents)h +(of)f(VIS.)h(\(V)-135 b(ersion)408 b(1.1)5978 23783 y(and)303 +b(later)-67 b(.\))5978 27021 y Fp(3.17.1)1212 b(Using)303 +b(the)f(CUDD)i(P)-12 b(ackage)303 b(in)g(SIS)5978 29344 +y Fo(This)409 b(section)h(describes)f(ho)-30 b(w)410 +b(to)h(b)-24 b(uild)410 b(SIS)f(with)h(the)h(CUDD)g(package.)698 +b(Let)410 b Fh(SISDIR)5978 30850 y Fo(designate)496 b(the)h(root)g(of)f +(the)h(directory)g(hierarch)-6 b(y)497 b(where)g(the)g(sources)e(for)i +(SIS)f(reside.)5978 32355 y(Let)355 b Fh(CUDDDIR)j Fo(be)f(the)f(root)g +(of)g(the)g(directory)g(hierarch)-6 b(y)356 b(where)g(the)g(distrib)-24 +b(ution)355 b(of)h(the)5978 33861 y(CUDD)295 b(package)g(resides.)372 +b(T)-97 b(o)294 b(b)-24 b(uild)294 b(SIS)f(with)i(the)f(CUDD)h +(package,)i(follo)-30 b(w)294 b(these)g(steps.)p Black +7493 36160 a(1.)p Black 606 w(Create)304 b(directories)e +Fh(SISDIR/sis/cudd)307 b Fo(and)c Fh(SISDIR/sis/mtr)p +Fo(.)p Black 7493 38581 a(2.)p Black 606 w(Cop)-12 b(y)231 +b(all)f(\002les)g(from)g Fh(CUDDDIR/cudd)j Fo(and)e Fh(CUDDDIR/sis)i +Fo(to)d Fh(SISDIR/sis/cudd)9008 40086 y Fo(and)303 b(all)g(\002les)g +(from)f Fh(CUDDDIR/mtr)k Fo(to)d Fh(SISDIR/sis/mtr)p +Fo(.)p Black 7493 42507 a(3.)p Black 606 w(Cop)-12 b(y)452 +b Fh(CUDDDIR/cudd/doc/cudd.doc)459 b Fo(to)452 b Fh(SISDIR/sis/cudd)p +Fo(;)530 b(also)9008 44013 y(cop)-12 b(y)303 b Fh +(CUDDDIR/mtr/doc/mtr.doc)309 b Fo(to)303 b Fh(SISDIR/sis/mtr)p +Fo(.)p Black 7493 46433 a(4.)p Black 606 w(In)499 b Fh(SISDIR/sis/cudd) +j Fo(mak)-12 b(e)500 b Fh(bdd.h)g Fo(a)f(symbolic)g(link)g(to)g +Fh(cuddBdd.h)p Fo(.)9008 47939 y(\(That)302 b(is:)376 +b Fh(ln)727 b(-s)h(cuddBdd.h)i(bdd.h)p Fo(.\))p Black +7493 50360 a(5.)p Black 606 w(In)357 b Fh(SISDIR/sis/cudd)k +Fo(delete)d Fh(Makefile)i Fo(and)d(rename)h Fh(Makefile.sis)9008 +51865 y Fo(as)303 b Fh(Makefile)p Fo(.)378 b(Do)303 b(the)g(same)g(in)g +Fh(SISDIR/sis/mtr)p Fo(.)p Black 7493 54286 a(6.)p Black +606 w(Cop)-12 b(y)231 b Fh(CUDDDIR/sis/st.[ch])k Fo(and)c +Fh(CUDDDIR/st/doc/st.doc)236 b Fo(to)230 b Fh(SISDIR/sis/st)p +Fo(.)9008 55791 y(\(This)385 b(will)i(o)-18 b(v)g(erwrite)386 +b(the)g(original)h(\002les:)542 b(Y)-133 b(ou)386 b(may)h(w)-12 +b(ant)387 b(to)f(sa)-24 b(v)-18 b(e)386 b(them)h(before-)9008 +57297 y(hand.\))p Black 7493 59718 a(7.)p Black 606 w(From)230 +b Fh(CUDDDIR/util)j Fo(cop)-12 b(y)231 b Fh(datalimit.c)i +Fo(to)e Fh(SISDIR/sis/util)p Fo(.)355 b(Up-)9008 61223 +y(date)392 b Fh(util.h)i Fo(and)e Fh(Makefile)i Fo(in)e +Fh(SISDIR/sis/util)p Fo(.)646 b(Speci\002cally)-79 b(,)415 +b(add)9008 62728 y(the)501 b(declaration)g Fh(EXTERN)729 +b(long)f(getSoftDataLimit\(\);)605 b Fo(to)501 b Fh(util.h)9008 +64234 y Fo(and)303 b(add)h Fh(datalimit.c)i Fo(to)d(the)g(list)f(of)h +(source)g(\002les)f(\(PSRC\))h(in)g Fh(Makefile)p Fo(.)p +Black 5978 65187 15940 45 v 7383 65928 a Ff(3)7771 66351 +y Fe(http://vlsi.Colorado.EDU/)249 b(vis/)p Black Black +25297 69672 a Fo(22)p Black eop end +%%Page: 23 23 +TeXDict begin 23 22 bop Black Black Black 7493 7638 a +Fo(8.)p Black 606 w(In)296 b Fh(SISDIR/sis)j Fo(remo)-18 +b(v)g(e)296 b(the)g(link)h(from)e Fh(bdd)j Fo(to)e Fh(bdd)p +34362 7638 364 45 v 437 w(cmu)h Fo(or)f Fh(bdd)p 40764 +7638 V 437 w(ucb)h Fo(\(that)9008 9143 y(is,)481 b Fh(rm)728 +b(bdd)p Fo(\))447 b(and)f(mak)-12 b(e)447 b Fh(bdd)g +Fo(a)f(symbolic)g(link)g(to)g Fh(cudd)p Fo(.)807 b(\(That)445 +b(is:)662 b Fh(ln)728 b(-s)9008 10649 y(cudd)g(bdd)p +Fo(.\))p Black 7493 13111 a(9.)p Black 606 w(Still)230 +b(in)g Fh(SISDIR/sis)p Fo(,)248 b(edit)230 b Fh(Makefile)p +Fo(,)247 b Fh(Makefile.oct)p Fo(,)i(and)230 b Fh(Makefile.nooct)p +Fo(.)9008 14617 y(In)303 b(all)g(three)g(\002les)f(add)i(mtr)e(to)h +(the)h(list)e(of)h(directories)f(to)h(be)g(made)h(\(DIRS\).)p +Black 6887 17079 a(10.)p Black 606 w(In)230 b Fh(SISDIR/sis/include)235 +b Fo(mak)-12 b(e)231 b Fh(mtr.h)g Fo(a)g(symbolic)f(link)g(to)h +Fh(../mtr/mtr.h)p Fo(.)p Black 6887 19541 a(11.)p Black +606 w(In)f Fh(SISDIR/sis/doc)k Fo(mak)-12 b(e)231 b Fh(cudd.doc)h +Fo(a)f(symbolic)f(link)g(to)g Fh(../cudd/cudd.doc)9008 +21046 y Fo(and)420 b Fh(mtr.doc)i Fo(a)e(symbolic)g(link)g(to)f +Fh(../mtr/mtr.doc)p Fo(.)731 b(\(That)419 b(is:)609 b +Fh(ln)728 b(-s)9008 22552 y(../cudd/cudd.doc)k(.;)727 +b(ln)h(-s)g(../mtr/mtr.doc)j(.)p Fo(.\))p Black 6887 +25014 a(12.)p Black 606 w(From)338 b Fh(SISDIR)i Fo(do)e +Fh(make)729 b(clean)340 b Fo(follo)-30 b(wed)338 b(by)g +Fh(make)729 b(-i)p Fo(.)482 b(This)337 b(should)i(cre-)9008 +26519 y(ate)303 b(a)g(w)-12 b(orking)303 b(cop)-12 b(y)304 +b(of)e(SIS)h(that)g(uses)f(the)h(CUDD)h(package.)7859 +28922 y(The)458 b(replacement)h(for)e(the)h Fh(st)h Fo(library)f(is)f +(because)h(the)h(v)-18 b(ersion)457 b(shipped)h(with)g(the)5978 +30427 y(CUDD)314 b(package)h(tests)e(for)g(out-of-memory)g(conditions.) +407 b(Notice)315 b(that)f(the)f(v)-18 b(ersion)314 b(of)f(the)5978 +31933 y Fh(st)441 b Fo(library)f(to)g(be)h(used)f(for)g(replacement)h +(is)g(not)f(the)h(one)g(used)f(for)g(the)h(normal)f(b)-24 +b(uild,)5978 33438 y(because)304 b(the)g(latter)g(has)g(been)g +(modi\002ed)g(for)g(C++)f(compatibility)-79 b(.)379 b(The)304 +b(abo)-18 b(v)g(e)304 b(installation)5978 34944 y(procedure)408 +b(has)h(been)g(tested)g(on)f(SIS)h(1.3.)693 b(SIS)408 +b(can)h(be)g(obtained)g(via)g(anon)-18 b(ymous)409 b(FTP)5978 +36449 y(from)229 b Fh(ic.eecs.berkeley.edu)p Fo(.)357 +b(T)-97 b(o)230 b(b)-24 b(uild)230 b(SIS)g(1.3,)245 b(you)231 +b(need)f Fh(sis-1.2.tar.Z)5978 37955 y Fo(and)238 b Fh +(sis-1.2.patch1.Z)p Fo(.)k(When)c(compiling)g(on)g(a)g(DEC)f(Alpha,)252 +b(you)238 b(should)f(add)h(the)5978 39460 y Fh(-ieee)p +9686 39460 V 437 w(with)p 13031 39460 V 438 w(no)p 14923 +39460 V 437 w(inexact)260 b Fo(\003ag.)361 b(\(See)258 +b(Section)h(3.5.2.\))361 b(Refer)258 b(to)h(the)g Fh(Makefile)h +Fo(in)5978 40966 y(the)303 b(top)g(le)-30 b(v)-18 b(el)303 +b(directory)g(of)f(the)h(distrib)-24 b(ution)302 b(for)h(ho)-30 +b(w)303 b(to)g(compile)g(with)g(32-bit)g(pointers.)5978 +44269 y Fi(3.18)1329 b(Writing)332 b(Decision)g(Diagrams)g(to)h(a)f +(File)5978 46592 y Fo(The)271 b(CUDD)h(package)h(pro)-18 +b(vides)271 b(se)-30 b(v)-18 b(eral)270 b(functions)h(to)h(write)f +(decision)h(diagrams)f(to)g(a)h(\002le.)5978 48098 y +Fn(Cudd)p 8677 48098 V 437 w(DumpBlif)465 b Fo(writes)287 +b(a)i(\002le)f(in)g Fn(blif)465 b Fo(format.)370 b(It)288 +b(is)g(restricted)f(to)h(BDDs.)372 b(The)288 b(diagrams)5978 +49603 y(are)314 b(written)g(as)f(a)i(netw)-12 b(ork)314 +b(of)g(multiple)-18 b(x)g(ers,)316 b(one)e(multiple)-18 +b(x)g(er)314 b(for)f(each)i(internal)f(node)g(of)5978 +51109 y(the)303 b(BDD.)7859 52614 y Fn(Cudd)p 10558 52614 +V 437 w(DumpDot)491 b Fo(produces)468 b(input)h(suitable)f(to)h(the)f +(graph-dra)-18 b(wing)468 b(program)g Fn(dot)45330 52174 +y Fg(4)5978 54119 y Fo(written)367 b(by)h(Eleftherios)e(K)-42 +b(outso\002os)366 b(and)i(Stephen)g(C.)g(North.)569 b(An)367 +b(e)-18 b(xample)368 b(of)f(dra)-18 b(wing)5978 55625 +y(produced)320 b(by)h(dot)f(from)g(the)h(output)f(of)g +Fn(Cudd)p 26136 55625 V 437 w(DumpDot)343 b Fo(is)320 +b(sho)-30 b(wn)320 b(in)h(Figure)f(1.)428 b(It)320 b(is)g(re-)5978 +57130 y(stricted)313 b(to)h(BDDs)g(and)h(ADDs.)409 b +Fn(Cudd)p 23034 57130 V 437 w(zddDumpDot)336 b Fo(is)313 +b(the)h(analog)h(of)f Fn(Cudd)p 40684 57130 V 437 w(DumpDot)5978 +58636 y Fo(for)302 b(ZDDs.)7859 60141 y Fn(Cudd)p 10558 +60141 V 437 w(DumpDaV)-90 b(inci)531 b Fo(produces)e(input)g(suitable)g +(to)h(the)g(graph-dra)-18 b(wing)529 b(program)5978 61647 +y Fn(daV)-90 b(inci)9659 61207 y Fg(5)10651 61647 y Fo(de)-30 +b(v)-18 b(eloped)494 b(at)g(the)g(Uni)-30 b(v)-18 b(ersity)492 +b(of)i(Bremen.)948 b(It)494 b(is)f(restricted)g(to)h(BDDs)g(and)5978 +63152 y(ADDs.)p Black 5978 63946 15940 45 v 7383 64687 +a Ff(4)7771 65110 y Fe(http://www)-65 b +(.research.att.com/sw/tools/graphviz)7383 65928 y Ff(5)7771 +66351 y Fe(ftp://ftp.uni-bremen.de/pub/graphics/daV)-60 +b(inci)p Black Black 25297 69672 a Fo(23)p Black eop +end +%%Page: 24 24 +TeXDict begin 24 23 bop Black Black Black 9619 56347 +a @beginspecial 66 @llx 36 @lly 547 @urx 757 @ury 4393 +@rhi @setspecial +%%BeginDocument: phase.ps +%!PS-Adobe-2.0 +%%Creator: dot version 95 (4-10-95) +%%For: (fabio) Fabio Somenzi,OT4-11,2-3466,ECE faculty +%%Title: DD +%%Pages: (atend) +%%BoundingBox: 66 36 547 757 +%%EndComments +%%BeginProlog +save +/DotDict 200 dict def +DotDict begin + +%%BeginResource: procset +/coord-font-family /Times-Roman def +/default-font-family /Times-Roman def +/coordfont coord-font-family findfont 8 scalefont def + +/InvScaleFactor 1.0 def +/set_scale { + dup 1 exch div /InvScaleFactor exch def + dup scale +} bind def + +% styles +/solid { } bind def +/dashed { [9 InvScaleFactor mul dup ] 0 setdash } bind def +/dotted { [1 InvScaleFactor mul 6 InvScaleFactor mul] 0 setdash } bind def +/invis {/fill {newpath} def /stroke {newpath} def /show {pop newpath} def} bind def +/bold { 2 setlinewidth } bind def +/filled { } bind def +/unfilled { } bind def +/rounded { } bind def +/diagonals { } bind def + +% hooks for setting color +/nodecolor { sethsbcolor } bind def +/edgecolor { sethsbcolor } bind def +/graphcolor { sethsbcolor } bind def +/nopcolor {pop pop pop} bind def + +/beginpage { % i j npages + /npages exch def + /j exch def + /i exch def + /str 10 string def + npages 1 gt { + gsave + coordfont setfont + 0 0 moveto + (() show i str cvs show (,) show j str cvs show ()) show + grestore + } if +} bind def + +/set_font { + findfont exch + scalefont setfont +} def + +/arrowhead { + /arrowwidth exch def + /arrowlength exch def + gsave + 3 1 roll + translate + rotate + newpath + arrowlength arrowwidth 2 div moveto + 0 0 lineto + arrowlength arrowwidth -2 div lineto + closepath fill + stroke + grestore +} def + +% draw aligned label in bounding box aligned to current point +% alignfactor tells what fraction to place on the left. +% -.5 is centered. +/alignedtext { % text labelwidth fontsz alignfactor + /alignfactor exch def + /fontsz exch def + /width exch def + /text exch def + gsave + % even if node or edge is dashed, don't paint text with dashes + [] 0 setdash + currentpoint newpath moveto + text stringwidth pop + alignfactor mul fontsz -.3 mul rmoveto + text show + grestore +} def + +/boxprim { % xcorner ycorner xsize ysize + 4 2 roll + moveto + 2 copy + exch 0 rlineto + 0 exch rlineto + pop neg 0 rlineto + closepath +} bind def + +/ellipse_path { + /ry exch def + /rx exch def + /y exch def + /x exch def + matrix currentmatrix + newpath + x y translate + rx ry scale + 0 0 1 0 360 arc + setmatrix +} bind def + +/endpage { showpage } bind def + +/layercolorseq + [ % layer color sequence - darkest to lightest + [0 0 0] + [.2 .8 .8] + [.4 .8 .8] + [.6 .8 .8] + [.8 .8 .8] + ] +def + +/setlayer {/maxlayer exch def /curlayer exch def + layercolorseq curlayer get + aload pop sethsbcolor + /nodecolor {nopcolor} def + /edgecolor {nopcolor} def + /graphcolor {nopcolor} def +} bind def + +/onlayer { curlayer ne {invis} if } def + +/onlayers { + /myupper exch def + /mylower exch def + curlayer mylower lt + curlayer myupper gt + or + {invis} if +} def + +/curlayer 0 def + +%%EndResource +%%EndProlog +%%BeginSetup +14 default-font-family set_font +% /arrowlength 10 def +% /arrowwidth 5 def +%%EndSetup +%%Page: 1 (atend) +%%PageBoundingBox: 66 36 547 757 +gsave +65 35 482 722 boxprim clip newpath +66 36 translate +0 0 1 beginpage +0.7407 set_scale +0 0 translate 0 rotate +0.000 0.000 0.000 graphcolor +14.00 /Times-Roman set_font + +% CONST NODES +gsave 10 dict begin +invis +gsave 10 dict begin +55 19 moveto (CONST NODES) 96 14.00 -0.50 alignedtext +end grestore +end grestore + +% a110 +gsave 10 dict begin +gsave 10 dict begin +55 883 moveto (a110) 27 14.00 -0.50 alignedtext +end grestore +end grestore + +% a111 +gsave 10 dict begin +gsave 10 dict begin +55 811 moveto (a111) 27 14.00 -0.50 alignedtext +end grestore +end grestore + +% a110 -> a111 +gsave 10 dict begin +invis +newpath 55 864 moveto +55 853 55 839 55 828 curveto +stroke +end grestore + +% a210 +gsave 10 dict begin +gsave 10 dict begin +55 739 moveto (a210) 27 14.00 -0.50 alignedtext +end grestore +end grestore + +% a111 -> a210 +gsave 10 dict begin +invis +newpath 55 792 moveto +55 781 55 767 55 756 curveto +stroke +end grestore + +% a211 +gsave 10 dict begin +gsave 10 dict begin +55 667 moveto (a211) 27 14.00 -0.50 alignedtext +end grestore +end grestore + +% a210 -> a211 +gsave 10 dict begin +invis +newpath 55 720 moveto +55 709 55 695 55 684 curveto +stroke +end grestore + +% a310 +gsave 10 dict begin +gsave 10 dict begin +55 595 moveto (a310) 27 14.00 -0.50 alignedtext +end grestore +end grestore + +% a211 -> a310 +gsave 10 dict begin +invis +newpath 55 648 moveto +55 637 55 623 55 612 curveto +stroke +end grestore + +% a311 +gsave 10 dict begin +gsave 10 dict begin +55 523 moveto (a311) 27 14.00 -0.50 alignedtext +end grestore +end grestore + +% a310 -> a311 +gsave 10 dict begin +invis +newpath 55 576 moveto +55 565 55 551 55 540 curveto +stroke +end grestore + +% a410 +gsave 10 dict begin +gsave 10 dict begin +55 451 moveto (a410) 27 14.00 -0.50 alignedtext +end grestore +end grestore + +% a311 -> a410 +gsave 10 dict begin +invis +newpath 55 504 moveto +55 493 55 479 55 468 curveto +stroke +end grestore + +% a411 +gsave 10 dict begin +gsave 10 dict begin +55 379 moveto (a411) 27 14.00 -0.50 alignedtext +end grestore +end grestore + +% a410 -> a411 +gsave 10 dict begin +invis +newpath 55 432 moveto +55 421 55 407 55 396 curveto +stroke +end grestore + +% a510 +gsave 10 dict begin +gsave 10 dict begin +55 307 moveto (a510) 27 14.00 -0.50 alignedtext +end grestore +end grestore + +% a411 -> a510 +gsave 10 dict begin +invis +newpath 55 360 moveto +55 349 55 335 55 324 curveto +stroke +end grestore + +% a511 +gsave 10 dict begin +gsave 10 dict begin +55 235 moveto (a511) 27 14.00 -0.50 alignedtext +end grestore +end grestore + +% a510 -> a511 +gsave 10 dict begin +invis +newpath 55 288 moveto +55 277 55 263 55 252 curveto +stroke +end grestore + +% a610 +gsave 10 dict begin +gsave 10 dict begin +55 163 moveto (a610) 27 14.00 -0.50 alignedtext +end grestore +end grestore + +% a511 -> a610 +gsave 10 dict begin +invis +newpath 55 216 moveto +55 205 55 191 55 180 curveto +stroke +end grestore + +% a611 +gsave 10 dict begin +gsave 10 dict begin +55 91 moveto (a611) 27 14.00 -0.50 alignedtext +end grestore +end grestore + +% a610 -> a611 +gsave 10 dict begin +invis +newpath 55 144 moveto +55 133 55 119 55 108 curveto +stroke +end grestore + +% a611 -> CONST NODES +gsave 10 dict begin +invis +newpath 55 72 moveto +55 61 55 47 55 36 curveto +stroke +end grestore + +% o +gsave 10 dict begin +newpath 511 972 moveto +457 972 lineto +457 936 lineto +511 936 lineto +closepath +stroke +gsave 10 dict begin +484 955 moveto (o) 7 14.00 -0.50 alignedtext +end grestore +end grestore + +% a00 +gsave 10 dict begin +484 882 27 18 ellipse_path +stroke +gsave 10 dict begin +484 883 moveto (a00) 20 14.00 -0.50 alignedtext +end grestore +end grestore + +% o -> a00 +gsave 10 dict begin +solid +newpath 484 936 moveto +484 925 484 911 484 900 curveto +stroke +end grestore + +% 9fc +gsave 10 dict begin +448 810 27 18 ellipse_path +stroke +gsave 10 dict begin +448 811 moveto (9fc) 17 14.00 -0.50 alignedtext +end grestore +end grestore + +% a00 -> 9fc +newpath 475 865 moveto +470 853 462 839 457 827 curveto +stroke + +% 9ff +gsave 10 dict begin +520 810 27 18 ellipse_path +stroke +gsave 10 dict begin +520 811 moveto (9ff) 16 14.00 -0.50 alignedtext +end grestore +end grestore + +% a00 -> 9ff +gsave 10 dict begin +dashed +newpath 493 865 moveto +498 853 506 839 511 827 curveto +stroke +end grestore + +% 995 +gsave 10 dict begin +453 738 27 18 ellipse_path +stroke +gsave 10 dict begin +453 739 moveto (995) 21 14.00 -0.50 alignedtext +end grestore +end grestore + +% 9fc -> 995 +gsave 10 dict begin +dashed +newpath 449 792 moveto +450 781 451 767 452 756 curveto +stroke +end grestore + +% 9fb +gsave 10 dict begin +381 738 27 18 ellipse_path +stroke +gsave 10 dict begin +381 739 moveto (9fb) 18 14.00 -0.50 alignedtext +end grestore +end grestore + +% 9fc -> 9fb +newpath 433 794 moveto +422 782 407 765 396 753 curveto +stroke + +% 9fe +gsave 10 dict begin +584 738 27 18 ellipse_path +stroke +gsave 10 dict begin +584 739 moveto (9fe) 17 14.00 -0.50 alignedtext +end grestore +end grestore + +% 9ff -> 9fe +gsave 10 dict begin +dashed +newpath 534 794 moveto +545 782 560 765 570 753 curveto +stroke +end grestore + +% 95f +gsave 10 dict begin +512 666 27 18 ellipse_path +stroke +gsave 10 dict begin +512 667 moveto (95f) 18 14.00 -0.50 alignedtext +end grestore +end grestore + +% 9ff -> 95f +newpath 519 792 moveto +518 764 515 712 513 684 curveto +stroke + +% 994 +gsave 10 dict begin +347 594 27 18 ellipse_path +stroke +gsave 10 dict begin +347 595 moveto (994) 21 14.00 -0.50 alignedtext +end grestore +end grestore + +% 995 -> 994 +newpath 432 727 moveto +407 714 370 693 363 684 curveto +356 675 351 636 349 612 curveto +stroke + +% 946 +gsave 10 dict begin +newpath 401 36 moveto +347 36 lineto +347 0 lineto +401 0 lineto +closepath +stroke +gsave 10 dict begin +374 19 moveto (1) 7 14.00 -0.50 alignedtext +end grestore +end grestore + +% 995 -> 946 +gsave 10 dict begin +dotted +newpath 584 594 moveto +589 570 587 545 584 522 curveto +stroke +newpath 453 720 moveto +454 698 458 662 473 648 curveto +498 621 544 628 577 612 curveto +582 609 582 600 584 594 curveto +stroke +end grestore + +% 9f7 +gsave 10 dict begin +292 666 27 18 ellipse_path +stroke +gsave 10 dict begin +292 667 moveto (9f7) 18 14.00 -0.50 alignedtext +end grestore +end grestore + +% 9fb -> 9f7 +newpath 363 724 moveto +347 711 325 693 309 680 curveto +stroke + +% 9fa +gsave 10 dict begin +402 666 27 18 ellipse_path +stroke +gsave 10 dict begin +402 667 moveto (9fa) 17 14.00 -0.50 alignedtext +end grestore +end grestore + +% 9fb -> 9fa +gsave 10 dict begin +dashed +newpath 386 720 moveto +389 709 393 695 397 684 curveto +stroke +end grestore + +% 9fd +gsave 10 dict begin +584 666 27 18 ellipse_path +stroke +gsave 10 dict begin +584 667 moveto (9fd) 18 14.00 -0.50 alignedtext +end grestore +end grestore + +% 9fe -> 9fd +newpath 584 720 moveto +584 709 584 695 584 684 curveto +stroke + +% 9fe -> 946 +gsave 10 dict begin +dotted +newpath 600 723 moveto +611 711 625 696 632 684 curveto +637 673 637 658 632 648 curveto +632 648 584 594 584 594 curveto +stroke +end grestore + +% 9f7 -> 994 +gsave 10 dict begin +dashed +newpath 304 650 moveto +313 638 326 622 335 610 curveto +stroke +end grestore + +% 9f6 +gsave 10 dict begin +275 594 27 18 ellipse_path +stroke +gsave 10 dict begin +275 595 moveto (9f6) 18 14.00 -0.50 alignedtext +end grestore +end grestore + +% 9f7 -> 9f6 +newpath 288 648 moveto +285 637 282 623 279 612 curveto +stroke + +% 9f9 +gsave 10 dict begin +529 594 27 18 ellipse_path +stroke +gsave 10 dict begin +529 595 moveto (9f9) 18 14.00 -0.50 alignedtext +end grestore +end grestore + +% 9fa -> 9f9 +gsave 10 dict begin +dashed +newpath 423 654 moveto +447 641 485 619 508 606 curveto +stroke +end grestore + +% 95e +gsave 10 dict begin +457 522 27 18 ellipse_path +stroke +gsave 10 dict begin +457 523 moveto (95e) 20 14.00 -0.50 alignedtext +end grestore +end grestore + +% 9fa -> 95e +newpath 465 594 moveto +464 579 462 556 460 540 curveto +stroke +newpath 420 652 moveto +439 638 464 614 465 594 curveto +stroke + +% 95f -> 95e +newpath 497 651 moveto +483 636 464 612 465 594 curveto +stroke + +% 95f -> 946 +gsave 10 dict begin +dotted +newpath 531 653 moveto +551 639 579 615 584 594 curveto +stroke +end grestore + +% 9fd -> 9f9 +newpath 572 650 moveto +563 638 550 622 541 610 curveto +stroke + +% 9fd -> 946 +gsave 10 dict begin +dotted +newpath 582 648 moveto +581 631 580 608 584 594 curveto +stroke +end grestore + +% 993 +gsave 10 dict begin +292 450 27 18 ellipse_path +stroke +gsave 10 dict begin +292 451 moveto (993) 21 14.00 -0.50 alignedtext +end grestore +end grestore + +% 994 -> 993 +newpath 333 578 moveto +323 566 312 551 308 540 curveto +301 521 296 489 294 468 curveto +stroke + +% 994 -> 946 +gsave 10 dict begin +dotted +newpath 357 577 moveto +371 556 396 519 418 504 curveto +447 482 489 484 522 468 curveto +527 465 527 456 529 450 curveto +stroke +newpath 529 450 moveto +534 426 532 401 529 378 curveto +stroke +end grestore + +% 9f5 +gsave 10 dict begin +347 522 27 18 ellipse_path +stroke +gsave 10 dict begin +347 523 moveto (9f5) 18 14.00 -0.50 alignedtext +end grestore +end grestore + +% 9f6 -> 9f5 +gsave 10 dict begin +dashed +newpath 290 579 moveto +302 567 319 550 332 537 curveto +stroke +end grestore + +% 9f2 +gsave 10 dict begin +237 522 27 18 ellipse_path +stroke +gsave 10 dict begin +237 523 moveto (9f2) 18 14.00 -0.50 alignedtext +end grestore +end grestore + +% 9f6 -> 9f2 +newpath 266 577 moveto +260 566 252 551 246 539 curveto +stroke + +% 9f8 +gsave 10 dict begin +529 522 27 18 ellipse_path +stroke +gsave 10 dict begin +529 523 moveto (9f8) 18 14.00 -0.50 alignedtext +end grestore +end grestore + +% 9f9 -> 9f8 +newpath 529 576 moveto +529 565 529 551 529 540 curveto +stroke + +% 9f9 -> 946 +gsave 10 dict begin +dotted +newpath 546 580 moveto +563 565 587 541 584 522 curveto +stroke +newpath 584 522 moveto +579 492 522 479 529 450 curveto +stroke +end grestore + +% 9f4 +gsave 10 dict begin +474 450 27 18 ellipse_path +stroke +gsave 10 dict begin +474 451 moveto (9f4) 18 14.00 -0.50 alignedtext +end grestore +end grestore + +% 9f5 -> 9f4 +gsave 10 dict begin +dashed +newpath 368 510 moveto +392 497 430 475 453 462 curveto +stroke +end grestore + +% 95d +gsave 10 dict begin +402 378 27 18 ellipse_path +stroke +gsave 10 dict begin +402 379 moveto (95d) 21 14.00 -0.50 alignedtext +end grestore +end grestore + +% 9f5 -> 95d +newpath 365 508 moveto +384 494 409 470 410 450 curveto +stroke +newpath 410 450 moveto +409 435 407 412 405 396 curveto +stroke + +% 9f2 -> 993 +gsave 10 dict begin +dashed +newpath 249 506 moveto +258 494 271 478 280 466 curveto +stroke +end grestore + +% 9f1 +gsave 10 dict begin +220 450 27 18 ellipse_path +stroke +gsave 10 dict begin +220 451 moveto (9f1) 18 14.00 -0.50 alignedtext +end grestore +end grestore + +% 9f2 -> 9f1 +newpath 233 504 moveto +230 493 227 479 224 468 curveto +stroke + +% 95e -> 95d +newpath 442 507 moveto +428 492 409 468 410 450 curveto +stroke + +% 95e -> 946 +gsave 10 dict begin +dotted +newpath 476 509 moveto +496 495 524 471 529 450 curveto +stroke +end grestore + +% 9f8 -> 9f4 +newpath 517 506 moveto +508 494 495 478 486 466 curveto +stroke + +% 9f8 -> 946 +gsave 10 dict begin +dotted +newpath 527 504 moveto +526 487 525 464 529 450 curveto +stroke +end grestore + +% 992 +gsave 10 dict begin +237 306 27 18 ellipse_path +stroke +gsave 10 dict begin +237 307 moveto (992) 21 14.00 -0.50 alignedtext +end grestore +end grestore + +% 993 -> 992 +newpath 278 434 moveto +268 422 257 407 253 396 curveto +246 377 241 345 239 324 curveto +stroke + +% 993 -> 946 +gsave 10 dict begin +dotted +newpath 474 306 moveto +474 306 474 234 474 234 curveto +stroke +newpath 302 433 moveto +316 412 341 375 363 360 curveto +392 338 434 340 467 324 curveto +472 321 472 312 474 306 curveto +stroke +end grestore + +% 9ed +gsave 10 dict begin +182 378 27 18 ellipse_path +stroke +gsave 10 dict begin +182 379 moveto (9ed) 20 14.00 -0.50 alignedtext +end grestore +end grestore + +% 9f1 -> 9ed +newpath 211 433 moveto +205 422 197 407 191 395 curveto +stroke + +% 9f0 +gsave 10 dict begin +292 378 27 18 ellipse_path +stroke +gsave 10 dict begin +292 379 moveto (9f0) 18 14.00 -0.50 alignedtext +end grestore +end grestore + +% 9f1 -> 9f0 +gsave 10 dict begin +dashed +newpath 235 435 moveto +247 423 264 406 277 393 curveto +stroke +end grestore + +% 9f3 +gsave 10 dict begin +474 378 27 18 ellipse_path +stroke +gsave 10 dict begin +474 379 moveto (9f3) 18 14.00 -0.50 alignedtext +end grestore +end grestore + +% 9f4 -> 9f3 +newpath 474 432 moveto +474 421 474 407 474 396 curveto +stroke + +% 9f4 -> 946 +gsave 10 dict begin +dotted +newpath 491 436 moveto +508 421 532 397 529 378 curveto +stroke +newpath 529 378 moveto +528 371 525 365 522 360 curveto +522 360 474 306 474 306 curveto +stroke +end grestore + +% 9ed -> 992 +gsave 10 dict begin +dashed +newpath 194 362 moveto +203 350 216 334 225 322 curveto +stroke +end grestore + +% 9ec +gsave 10 dict begin +165 306 27 18 ellipse_path +stroke +gsave 10 dict begin +165 307 moveto (9ec) 19 14.00 -0.50 alignedtext +end grestore +end grestore + +% 9ed -> 9ec +newpath 178 360 moveto +175 349 172 335 169 324 curveto +stroke + +% 9ef +gsave 10 dict begin +419 306 27 18 ellipse_path +stroke +gsave 10 dict begin +419 307 moveto (9ef) 17 14.00 -0.50 alignedtext +end grestore +end grestore + +% 9f0 -> 9ef +gsave 10 dict begin +dashed +newpath 313 366 moveto +337 353 375 331 398 318 curveto +stroke +end grestore + +% 95c +gsave 10 dict begin +347 234 27 18 ellipse_path +stroke +gsave 10 dict begin +347 235 moveto (95c) 20 14.00 -0.50 alignedtext +end grestore +end grestore + +% 9f0 -> 95c +newpath 310 364 moveto +329 350 354 326 355 306 curveto +stroke +newpath 355 306 moveto +354 291 352 268 350 252 curveto +stroke + +% 95d -> 95c +newpath 387 363 moveto +373 348 354 324 355 306 curveto +stroke + +% 95d -> 946 +gsave 10 dict begin +dotted +newpath 421 365 moveto +441 351 469 327 474 306 curveto +stroke +end grestore + +% 9f3 -> 9ef +newpath 462 362 moveto +453 350 440 334 431 322 curveto +stroke + +% 9f3 -> 946 +gsave 10 dict begin +dotted +newpath 472 360 moveto +471 343 470 320 474 306 curveto +stroke +end grestore + +% 954 +gsave 10 dict begin +165 162 27 18 ellipse_path +stroke +gsave 10 dict begin +165 163 moveto (954) 21 14.00 -0.50 alignedtext +end grestore +end grestore + +% 992 -> 954 +newpath 220 234 moveto +214 216 194 192 180 177 curveto +stroke +newpath 233 288 moveto +230 272 224 248 220 234 curveto +stroke + +% 992 -> 946 +gsave 10 dict begin +dotted +newpath 220 234 moveto +220 234 213 144 213 144 curveto +213 144 193 90 193 90 curveto +stroke +end grestore + +% 987 +gsave 10 dict begin +165 234 27 18 ellipse_path +stroke +gsave 10 dict begin +165 235 moveto (987) 21 14.00 -0.50 alignedtext +end grestore +end grestore + +% 9ec -> 987 +newpath 165 288 moveto +165 277 165 263 165 252 curveto +stroke + +% 9eb +gsave 10 dict begin +275 234 27 18 ellipse_path +stroke +gsave 10 dict begin +275 235 moveto (9eb) 20 14.00 -0.50 alignedtext +end grestore +end grestore + +% 9ec -> 9eb +gsave 10 dict begin +dashed +newpath 184 293 moveto +204 280 236 260 256 247 curveto +stroke +end grestore + +% 9ee +gsave 10 dict begin +419 234 27 18 ellipse_path +stroke +gsave 10 dict begin +419 235 moveto (9ee) 19 14.00 -0.50 alignedtext +end grestore +end grestore + +% 9ef -> 9ee +newpath 419 288 moveto +419 277 419 263 419 252 curveto +stroke + +% 9ef -> 946 +gsave 10 dict begin +dotted +newpath 474 234 moveto +477 210 461 184 469 162 curveto +stroke +newpath 435 291 moveto +450 276 471 252 474 234 curveto +stroke +end grestore + +% 987 -> 954 +gsave 10 dict begin +dashed +newpath 165 216 moveto +165 205 165 191 165 180 curveto +stroke +end grestore + +% 987 -> 946 +newpath 193 90 moveto +225 56 305 34 347 24 curveto +stroke +newpath 152 218 moveto +136 197 113 162 126 144 curveto +144 120 173 110 193 90 curveto +stroke + +% 9ea +gsave 10 dict begin +410 162 27 18 ellipse_path +stroke +gsave 10 dict begin +410 163 moveto (9ea) 19 14.00 -0.50 alignedtext +end grestore +end grestore + +% 9eb -> 9ea +gsave 10 dict begin +dashed +newpath 296 223 moveto +321 210 363 187 389 174 curveto +stroke +end grestore + +% 955 +gsave 10 dict begin +374 90 27 18 ellipse_path +stroke +gsave 10 dict begin +374 91 moveto (955) 21 14.00 -0.50 alignedtext +end grestore +end grestore + +% 9eb -> 955 +newpath 293 220 moveto +311 206 338 182 347 162 curveto +stroke +newpath 347 162 moveto +353 147 362 124 368 108 curveto +stroke + +% 95c -> 955 +newpath 344 216 moveto +342 199 341 175 347 162 curveto +stroke + +% 95c -> 946 +gsave 10 dict begin +dotted +newpath 368 222 moveto +372 220 376 217 380 216 curveto +407 203 436 195 462 180 curveto +467 176 466 168 469 162 curveto +stroke +newpath 469 162 moveto +476 139 475 113 469 90 curveto +stroke +end grestore + +% 9ee -> 9ea +newpath 417 216 moveto +415 205 414 191 412 180 curveto +stroke + +% 9ee -> 946 +gsave 10 dict begin +dotted +newpath 432 218 moveto +442 206 454 190 462 180 curveto +465 174 466 168 469 162 curveto +stroke +end grestore + +% 954 -> 946 +newpath 169 144 moveto +174 127 182 101 193 90 curveto +stroke + +% 954 -> 946 +gsave 10 dict begin +dotted +end grestore + +% 9ea -> 955 +newpath 401 145 moveto +396 133 388 119 383 107 curveto +stroke + +% 9ea -> 946 +gsave 10 dict begin +dotted +newpath 429 149 moveto +448 133 474 109 469 90 curveto +stroke +newpath 469 90 moveto +462 66 427 44 401 30 curveto +stroke +end grestore + +% 955 -> 946 +newpath 374 72 moveto +374 61 374 47 374 36 curveto +stroke + +% 955 -> 946 +gsave 10 dict begin +dotted +end grestore +endpage +grestore +%%PageTrailer +%%Trailer +%%Pages: 1 +end +restore +%%EOF + +%%EndDocument + @endspecial 5978 58959 a Fo(Figure)432 b(1:)636 b(A)433 +b(BDD)g(representing)f(a)h(phase)g(constraint)f(for)h(the)g +(optimization)g(of)f(\002x)-18 b(ed-)5978 60465 y(polarity)321 +b(Reed-Muller)g(forms.)429 b(The)321 b(label)h(of)e(each)i(node)g(is)e +(the)i(unique)f(part)g(of)g(the)h(node)5978 61970 y(address.)370 +b(All)289 b(nodes)g(on)g(the)h(same)f(le)-30 b(v)-18 +b(el)289 b(correspond)f(to)h(the)h(same)f(v)-30 b(ariable,)292 +b(whose)d(name)5978 63476 y(is)283 b(sho)-30 b(wn)283 +b(at)h(the)g(left)g(of)f(the)h(diagram.)370 b(Dotted)284 +b(lines)f(indicate)i(complement)f(arcs.)369 b(Dashed)5978 +64981 y(lines)302 b(indicate)i(re)-18 b(gular)302 b(\223else\224)i +(arcs.)p Black Black 25297 69672 a(24)p Black eop end +%%Page: 25 25 +TeXDict begin 25 24 bop Black Black 7859 7638 a Fo(Functions)420 +b(are)f(also)g(a)-24 b(v)-30 b(ailable)420 b(to)f(produce)h(the)g +(input)f(format)g(of)g Fn(DDcal)i Fo(\(see)e(Sec-)5978 +9143 y(tion)303 b(2.2\))f(and)i(f)-12 b(actored)303 b(forms.)5978 +12466 y Fi(3.19)1329 b(Sa)-33 b(ving)331 b(and)h(Restoring)g(BDDs)5978 +14790 y Fo(The)298 b Fn(dddmp)11460 14350 y Fg(6)12256 +14790 y Fo(library)g(by)g(Gianpiero)g(Cabodi)h(and)f(Stef)-12 +b(ano)298 b(Quer)g(allo)-30 b(ws)298 b(a)g(CUDD)h(appli-)5978 +16295 y(cation)365 b(to)h(sa)-24 b(v)-18 b(e)365 b(BDDs)h(to)f(disk)g +(in)h(compact)g(form)e(for)h(later)h(retrie)-30 b(v)g(al.)562 +b(See)366 b(the)f(library')-67 b(s)5978 17801 y(o)-30 +b(wn)303 b(documentation)g(for)g(the)g(details.)5978 +21702 y Fq(4)1594 b(Pr)-29 b(ogrammer')-59 b(s)397 b(Manual)5978 +24462 y Fo(This)348 b(section)i(pro)-18 b(vides)349 b(additional)h +(detail)g(on)g(the)g(w)-12 b(orking)349 b(of)h(the)g(CUDD)g(package)h +(and)5978 25968 y(on)475 b(the)g(programming)g(con)-48 +b(v)-18 b(entions)475 b(follo)-30 b(wed)475 b(in)g(its)f(writing.)892 +b(The)475 b(additional)h(detail)5978 27473 y(should)246 +b(help)i(those)f(who)g(w)-12 b(ant)248 b(to)f(write)g(procedures)g +(that)g(directly)g(manipulate)h(the)f(CUDD)5978 28979 +y(data)303 b(structures.)5978 32301 y Fi(4.1)1328 b(Compiling)332 +b(and)g(Linking)5978 34625 y Fo(If)420 b(you)i(plan)g(to)g(use)f(the)h +(CUDD)g(package)g(as)g(a)f(clear)h(box)g(\(for)e(instance,)452 +b(you)421 b(w)-12 b(ant)422 b(to)5978 36130 y(write)302 +b(a)i(procedure)f(that)g(tra)-24 b(v)-18 b(erses)301 +b(a)j(decision)f(diagram\))f(you)h(need)h(to)f(add)p +Black Black 5978 38632 a Fh(#include)729 b("cuddInt.h")5978 +41134 y Fo(to)310 b(your)g(source)h(\002les.)397 b(In)311 +b(addition,)h(you)f(should)f(link)h Fh(libcudd.a)i Fo(to)d(your)g(e)-18 +b(x)g(ecutable.)5978 42639 y(Some)254 b(platforms)g(require)g +(speci\002c)h(compiler)f(and)h(link)-12 b(er)255 b(\003ags.)359 +b(Refer)255 b(to)f(the)h Fh(Makefile)5978 44145 y Fo(in)303 +b(the)g(top)g(le)-30 b(v)-18 b(el)303 b(directory)g(of)f(the)i(distrib) +-24 b(ution.)5978 47467 y Fi(4.2)1328 b(Refer)-24 b(ence)331 +b(Counts)5978 49791 y Fo(Garbage)293 b(collection)h(in)g(the)f(CUDD)i +(package)f(is)f(based)g(on)h(reference)f(counts.)372 +b(Each)294 b(node)5978 51296 y(stores)299 b(the)j(sum)e(of)h(the)g(e) +-18 b(xternal)301 b(references)f(and)i(internal)f(references.)374 +b(An)301 b(internal)g(BDD)5978 52802 y(or)425 b(ADD)h(node)h(is)e +(created)h(by)g(a)g(call)g(to)g Fn(cuddUniqueInter)28 +b Fo(,)457 b(an)426 b(internal)g(ZDD)f(node)i(is)5978 +54307 y(created)350 b(by)g(a)g(call)g(to)g Fn(cuddUniqueInterZdd)33 +b Fo(,)362 b(and)350 b(a)h(terminal)e(node)i(is)e(created)i(by)f(a)g +(call)5978 55813 y(to)341 b Fn(cuddUniqueConst)22 b Fo(.)492 +b(If)340 b(the)i(node)g(returned)f(by)g(these)g(functions)g(is)g(ne)-30 +b(w)-79 b(,)352 b(its)340 b(reference)5978 57318 y(count)396 +b(is)g(zero.)655 b(The)396 b(function)g(that)g(calls)g +Fn(cuddUniqueInter)28 b Fo(,)419 b Fn(cuddUniqueInterZdd)33 +b Fo(,)419 b(or)5978 58823 y Fn(cuddUniqueConst)474 b +Fo(is)451 b(responsible)g(for)g(increasing)h(the)g(reference)f(count)h +(of)g(the)g(node.)5978 60329 y(This)302 b(is)g(accomplished)i(by)f +(calling)g Fn(Cudd)p 24332 60329 364 45 v 437 w(Ref)177 +b Fo(.)7859 61834 y(When)272 b(a)f(function)g(is)f(no)h(longer)g +(needed)h(by)f(an)g(application,)278 b(the)271 b(memory)g(used)g(by)g +(its)5978 63340 y(diagram)403 b(can)h(be)g(rec)-18 b(ycled)404 +b(by)g(calling)g Fn(Cudd)p 26496 63340 V 437 w(Recur)-12 +b(siveDer)-45 b(ef)580 b Fo(\(BDDs)403 b(and)h(ADDs\))f(or)p +Black 5978 64421 15940 45 v 7383 65162 a Ff(6)7771 65585 +y Fe(ftp://ftp.polito.it/pub/research/dddmp/)p Black +Black 25297 69672 a Fo(25)p Black eop end +%%Page: 26 26 +TeXDict begin 26 25 bop Black Black 5978 7638 a Fn(Cudd)p +8677 7638 364 45 v 437 w(Recur)-12 b(siveDer)-45 b(efZdd)430 +b Fo(\(ZDDs\).)661 b(These)398 b(functions)g(decrease)h(the)f +(reference)h(count)5978 9143 y(of)443 b(the)h(node)h(passed)e(to)h +(them.)799 b(If)443 b(the)h(reference)g(count)g(becomes)g(0,)479 +b(then)445 b(tw)-12 b(o)444 b(things)5978 10649 y(happen:)p +Black 7493 13151 a(1.)p Black 606 w(The)308 b(node)g(is)f(declared)i +(\223dead;\224)i(this)d(entails)f(increasing)h(the)g(counters)g(of)g +(the)g(dead)9008 14656 y(nodes.)727 b(\(One)420 b(counter)h(for)e(the)i +(subtable)f(to)g(which)h(the)f(node)h(belongs,)449 b(and)421 +b(one)9008 16162 y(global)406 b(counter)f(for)g(the)h(unique)f(table)h +(to)g(which)g(the)f(node)h(belongs.\))683 b(The)405 b(node)9008 +17667 y(itself)302 b(is)h(not)g(af)-30 b(fected.)p Black +7493 20169 a(2.)p Black 606 w(The)303 b(function)g(is)f(recursi)-30 +b(v)-18 b(ely)302 b(called)i(on)f(the)g(tw)-12 b(o)303 +b(children)g(of)g(the)g(node.)5978 22671 y(F)-18 b(or)467 +b(instance,)509 b(if)468 b(the)g(diagram)g(of)g(a)g(function)g(does)g +(not)g(share)g(an)-18 b(y)468 b(nodes)g(with)g(other)5978 +24176 y(diagrams,)482 b(then)447 b(calling)g Fn(Cudd)p +20186 24176 V 437 w(Recur)-12 b(siveDer)-45 b(ef)623 +b Fo(or)447 b Fn(Cudd)p 32812 24176 V 437 w(Recur)-12 +b(siveDer)-45 b(efZdd)479 b Fo(on)447 b(its)5978 25681 +y(root)302 b(will)h(cause)g(all)h(the)f(nodes)g(of)f(the)i(diagram)f +(to)g(become)g(dead.)7859 27187 y(When)255 b(the)e(number)h(of)f(dead)h +(nodes)g(reaches)f(a)h(gi)-30 b(v)-18 b(en)254 b(le)-30 +b(v)-18 b(el)253 b(\(dynamically)h(determined)5978 28692 +y(by)419 b(the)h(package\))g(g)-6 b(arbage)419 b(collection)h(tak)-12 +b(es)419 b(place.)726 b(During)419 b(g)-6 b(arbage)420 +b(collection)g(dead)5978 30198 y(nodes)302 b(are)h(returned)g(to)g(the) +h(node)f(free)g(list.)7859 31703 y(When)469 b(a)f(ne)-30 +b(w)468 b(node)g(is)f(created,)510 b(it)467 b(is)h(important)f(to)h +(increase)g(its)f(reference)h(count)5978 33209 y(before)302 +b(one)i(of)e(the)i(tw)-12 b(o)303 b(follo)-30 b(wing)302 +b(e)-30 b(v)-18 b(ents)303 b(occurs:)p Black 7493 35711 +a(1.)p Black 606 w(A)268 b(call)g(to)f Fn(cuddUniqueInter)28 +b Fo(,)275 b(to)268 b Fn(cuddUniqueInterZdd)33 b Fo(,)274 +b(to)268 b Fn(cuddUniqueConst)22 b Fo(,)275 b(or)9008 +37216 y(to)303 b(a)g(function)g(that)g(may)h(e)-30 b(v)-18 +b(entually)303 b(cause)g(a)g(call)g(to)g(them.)p Black +7493 39718 a(2.)p Black 606 w(A)381 b(call)g(to)g Fn(Cudd)p +16418 39718 V 437 w(Recur)-12 b(siveDer)-45 b(ef)177 +b Fo(,)400 b(to)381 b Fn(Cudd)p 29168 39718 V 437 w(Recur)-12 +b(siveDer)-45 b(efZdd)33 b Fo(,)400 b(or)380 b(to)h(a)h(func-)9008 +41223 y(tion)303 b(that)g(may)g(e)-30 b(v)-18 b(entually)304 +b(cause)f(a)g(call)g(to)g(them.)5978 43725 y(In)399 b(practice,)424 +b(it)400 b(is)f(recommended)i(to)e(increase)h(the)g(reference)f(count)h +(as)g(soon)f(as)h(the)g(re-)5978 45230 y(turned)303 b(pointer)f(has)h +(been)h(tested)f(for)f(not)h(being)g(NULL.)5978 48509 +y Fp(4.2.1)1212 b(NULL)304 b(Retur)-18 b(n)303 b(V)-112 +b(alues)5978 50832 y Fo(The)321 b(interf)-12 b(ace)321 +b(to)h(the)f(memory)h(management)g(functions)f(\(e.g.,)326 +b(malloc\))321 b(used)h(by)f(CUDD)5978 52338 y(intercepts)342 +b(NULL)g(return)g(v)-30 b(alues)342 b(and)h(calls)g(a)f(handler)-67 +b(.)495 b(The)343 b(def)-12 b(ault)342 b(handler)h(e)-18 +b(xits)342 b(with)5978 53843 y(an)378 b(error)e(message.)600 +b(If)377 b(the)h(application)g(does)f(not)h(install)f(another)h +(handler)-48 b(,)396 b(therefore,)g(a)5978 55349 y(NULL)302 +b(return)h(v)-30 b(alue)303 b(from)f(an)h(e)-18 b(xported)303 +b(function)g(of)g(CUDD)h(signals)e(an)i(internal)f(error)-67 +b(.)7859 56854 y(If)288 b(the)g(aplication,)k(ho)-30 +b(we)g(v)-18 b(er)-48 b(,)290 b(installs)d(another)h(handler)g(that)h +(lets)e(e)-18 b(x)g(ecution)289 b(continue,)5978 58360 +y(a)343 b(NULL)g(pointer)g(returned)g(by)g(an)h(e)-18 +b(xported)343 b(function)g(typically)h(indicates)f(that)g(the)h(pro-) +5978 59865 y(cess)407 b(has)g(run)h(out)g(of)g(memory)-79 +b(.)690 b Fn(Cudd)p 23480 59865 V 437 w(ReadErr)-55 b(orCode)407 +b Fo(can)i(be)f(used)f(to)h(ascertain)g(the)5978 61371 +y(nature)303 b(of)f(the)i(problem.)7859 62876 y(An)483 +b(application)g(that)f(tests)f(for)h(the)g(result)g(being)g(NULL)g(can) +g(try)g(some)g(remedial)5978 64381 y(action,)302 b(if)f(it)h(runs)f +(out)g(of)h(memory)-79 b(.)375 b(F)-18 b(or)301 b(instance,)h(it)g(may) +g(free)f(some)h(memory)f(that)h(is)f(not)5978 65887 y(strictly)350 +b(necessary)-79 b(,)363 b(or)351 b(try)f(a)i(slo)-30 +b(wer)350 b(algorithm)h(that)g(tak)-12 b(es)351 b(less)f(space.)521 +b(As)350 b(an)i(e)-18 b(xample,)p Black 25297 69672 a(26)p +Black eop end +%%Page: 27 27 +TeXDict begin 27 26 bop Black Black 5978 7638 a Fo(CUDD)354 +b(o)-18 b(v)g(errides)352 b(the)i(def)-12 b(ault)354 +b(handler)f(when)h(trying)g(to)f(enlar)-22 b(ge)354 b(the)g(cache)g(or) +f(increase)5978 9143 y(the)365 b(number)g(of)g(slots)f(of)h(the)g +(unique)g(table.)563 b(If)364 b(the)h(allocation)h(f)-12 +b(ails,)380 b(the)365 b(package)h(prints)5978 10649 y(out)303 +b(a)g(message)g(and)g(continues)g(without)g(resizing)g(the)g(cache.) +5978 13927 y Fp(4.2.2)1212 b Fa(Cudd)p 12381 13927 364 +45 v 437 w(Recursiv)-18 b(eDeref)439 b Fp(vs.)303 b Fa(Cudd)p +25359 13927 V 437 w(Deref)5978 16251 y Fo(It)465 b(is)g(often)g(the)h +(case)g(that)g(a)f(recursi)-30 b(v)-18 b(e)465 b(procedure)g(has)h(to)f +(protect)h(the)g(result)f(it)g(is)g(go-)5978 17756 y(ing)502 +b(to)h(return,)552 b(while)502 b(it)h(disposes)e(of)h(intermediate)h +(results.)973 b(\(See)503 b(the)f(pre)-30 b(vious)502 +b(dis-)5978 19262 y(cussion)528 b(on)i(when)g(to)f(increase)h +(reference)f(counts.\))1055 b(Once)530 b(the)g(intermediate)f(results) +5978 20767 y(ha)-24 b(v)-18 b(e)463 b(been)g(properly)g(disposed)f(of,) +503 b(the)463 b(\002nal)g(result)g(must)f(be)i(returned)e(to)h(its)g +(pristine)5978 22273 y(state,)458 b(in)428 b(which)h(the)f(root)f(node) +i(may)f(ha)-24 b(v)-18 b(e)428 b(a)g(reference)g(count)g(of)f(0.)751 +b(One)428 b(cannot)g(use)5978 23778 y Fn(Cudd)p 8677 +23778 V 437 w(Recur)-12 b(siveDer)-45 b(ef)604 b Fo(\(or)428 +b Fn(Cudd)p 21669 23778 V 437 w(Recur)-12 b(siveDer)-45 +b(efZdd)33 b Fo(\))428 b(for)g(this)g(purpose,)459 b(because)429 +b(it)5978 25284 y(may)281 b(erroneously)f(mak)-12 b(e)281 +b(some)f(nodes)h(dead.)369 b(Therefore,)284 b(the)d(package)h(pro)-18 +b(vides)280 b(a)h(dif)-30 b(fer)-24 b(-)5978 26789 y(ent)320 +b(function:)411 b Fn(Cudd)p 15266 26789 V 437 w(Der)-45 +b(ef)177 b Fo(.)429 b(This)319 b(function)i(is)f(not)h(recursi)-30 +b(v)-18 b(e,)324 b(and)d(does)f(not)h(change)g(the)5978 +28295 y(dead)c(node)h(counts.)419 b(Its)317 b(use)g(is)g(almost)g(e)-18 +b(xclusi)-30 b(v)-18 b(ely)317 b(the)g(one)h(just)f(described:)404 +b(Decreasing)5978 29800 y(the)325 b(reference)h(count)g(of)f(the)h +(root)f(of)g(the)h(\002nal)f(result)g(before)h(returning)f(from)g(a)g +(recursi)-30 b(v)-18 b(e)5978 31305 y(procedure.)5978 +34584 y Fp(4.2.3)1212 b(When)303 b(Incr)-22 b(easing)303 +b(the)g(Refer)-22 b(ence)304 b(Count)e(is)h(Unnecessary)5978 +36907 y Fo(When)366 b(a)h(cop)-12 b(y)366 b(of)g(a)g(prede\002ned)h +(constant)f(or)g(of)f(a)i(simple)e(BDD)i(v)-30 b(ariable)366 +b(is)g(needed)h(for)5978 38413 y(comparison)353 b(purposes,)366 +b(then)354 b(calling)g Fn(Cudd)p 25759 38413 V 437 w(Ref)531 +b Fo(is)354 b(not)g(necessary)-79 b(,)366 b(because)354 +b(these)g(sim-)5978 39918 y(ple)394 b(functions)g(are)g(guaranteed)g +(to)g(ha)-24 b(v)-18 b(e)395 b(reference)f(counts)g(greater)f(than)i(0) +f(at)g(all)h(times.)5978 41424 y(If)451 b(no)h(call)g(to)h +Fn(Cudd)p 15198 41424 V 437 w(Ref)628 b Fo(is)452 b(made,)490 +b(then)452 b(no)g(attempt)g(to)h(free)e(the)h(diagram)h(by)f(calling) +5978 42929 y Fn(Cudd)p 8677 42929 V 437 w(Recur)-12 b(siveDer)-45 +b(ef)479 b Fo(or)303 b Fn(Cudd)p 21015 42929 V 437 w(Recur)-12 +b(siveDer)-45 b(efZdd)335 b Fo(should)302 b(be)i(made.)5978 +46207 y Fp(4.2.4)1212 b(Saturating)302 b(Incr)-22 b(ements)302 +b(and)h(Decr)-22 b(ements)5978 48531 y Fo(On)398 b(32-bit)g(machines,) +422 b(the)399 b(CUDD)g(package)g(stores)e(the)i(reference)f(counts)g +(in)g(unsigned)5978 50036 y(short)475 b(int')-67 b(s.)894 +b(F)-18 b(or)475 b(lar)-22 b(ge)476 b(diagrams,)519 b(it)476 +b(is)f(possible)g(for)g(some)h(reference)g(counts)g(to)f(e)-18 +b(x-)5978 51542 y(ceed)341 b(the)f(capacity)h(of)g(an)f(unsigned)h +(short)e(int.)488 b(Therefore,)349 b(increments)340 b(and)h(decrements) +5978 53047 y(of)445 b(reference)g(counts)h(are)f Fn(satur)-18 +b(ating)p Fo(.)803 b(This)445 b(means)g(that)h(once)g(a)g(reference)f +(count)h(has)5978 54553 y(reached)278 b(the)h(maximum)g(possible)e(v) +-30 b(alue,)284 b(it)278 b(is)g(no)h(longer)f(changed)h(by)g(calls)f +(to)g Fn(Cudd)p 43545 54553 V 437 w(Ref)p Fo(,)5978 56058 +y Fn(Cudd)p 8677 56058 V 437 w(Recur)-12 b(siveDer)-45 +b(ef)177 b Fo(,)574 b Fn(Cudd)p 20277 56058 V 437 w(Recur)-12 +b(siveDer)-45 b(efZdd)33 b Fo(,)574 b(or)521 b Fn(Cudd)p +35150 56058 V 437 w(Der)-45 b(ef)177 b Fo(.)1029 b(As)521 +b(a)g(conse-)5978 57564 y(quence,)364 b(some)351 b(nodes)h(that)g(ha) +-24 b(v)-18 b(e)351 b(no)h(references)f(may)h(not)f(be)h(declared)g +(dead.)522 b(This)351 b(may)5978 59069 y(result)367 b(in)h(a)g(small)f +(w)-12 b(aste)368 b(of)f(memory)-79 b(,)384 b(which)369 +b(is)e(normally)h(more)f(than)h(of)-30 b(fset)367 b(by)h(the)g(re-)5978 +60575 y(duction)303 b(in)g(size)g(of)g(the)g(node)g(structure.)7859 +62080 y(When)342 b(using)f(64-bit)g(pointers,)350 b(there)341 +b(is)f(normally)h(no)h(memory)f(adv)-30 b(antage)341 +b(from)g(us-)5978 63586 y(ing)302 b(short)f(int')-67 +b(s)301 b(instead)h(of)f(int')-67 b(s)301 b(in)h(a)g(DdNode.)376 +b(Therefore,)302 b(increments)f(and)h(decrements)5978 +65091 y(are)401 b(not)h(saturating)f(in)h(that)g(case.)671 +b(What)403 b(option)e(is)g(in)h(ef)-30 b(fect)401 b(depends)h(on)g(tw) +-12 b(o)402 b(macros,)p Black 25297 69672 a(27)p Black +eop end +%%Page: 28 28 +TeXDict begin 28 27 bop Black Black 5978 7638 a Fo(SIZEOF)p +10160 7638 364 45 v 435 w(V)-48 b(OID)p 13576 7638 V +436 w(P)396 b(and)g(SIZEOF)p 21337 7638 V 435 w(INT,)g(de\002ned)g(in)g +(the)h(e)-18 b(xternal)396 b(header)g(\002le)g(\()p Fn(cudd.h)p +Fo(\).)5978 9143 y(The)386 b(increments)g(and)h(decrements)g(of)f(the)h +(reference)f(counts)g(are)h(performed)f(using)g(tw)-12 +b(o)5978 10649 y(macros:)338 b Fn(cuddSatInc)231 b Fo(and)g +Fn(cuddSatDec)p Fo(,)245 b(whose)231 b(de\002nitions)f(depend)h(on)f +(SIZEOF)p 42255 10649 V 435 w(V)-48 b(OID)p 45671 10649 +V 436 w(P)5978 12154 y(and)303 b(SIZEOF)p 12213 12154 +V 435 w(INT.)5978 15477 y Fi(4.3)1328 b(Complement)331 +b(Ar)-24 b(cs)5978 17801 y Fo(If)377 b(ADDs)h(are)g(restricted)f(to)h +(use)g(only)g(the)g(constants)f(0)h(and)h(1,)397 b(the)-18 +b(y)378 b(beha)-24 b(v)-18 b(e)378 b(lik)-12 b(e)378 +b(BDDs)5978 19306 y(without)333 b(complement)h(arcs.)466 +b(It)333 b(is)f(normally)i(easier)f(to)g(write)g(code)h(that)f +(manipulates)g(0-1)5978 20811 y(ADDs,)453 b(than)424 +b(to)f(write)g(code)h(for)f(BDDs.)737 b(Ho)-30 b(we)g(v)-18 +b(er)-48 b(,)452 b(complementation)424 b(is)f(tri)-30 +b(vial)423 b(with)5978 22317 y(complement)354 b(arcs,)367 +b(and)354 b(is)f(not)i(tri)-30 b(vial)353 b(without.)529 +b(As)354 b(a)g(consequence,)367 b(with)354 b(complement)5978 +23822 y(arcs)369 b(it)h(is)f(possible)g(to)h(check)g(for)f(more)h +(terminal)g(cases)f(and)h(it)g(is)f(possible)g(to)h(apply)g(De)5978 +25328 y(Mor)-22 b(g)-6 b(an')-67 b(s)291 b(la)-18 b(ws)292 +b(to)g(reduce)h(problems)e(that)i(are)f(essentially)g(identical)g(to)h +(a)f(standard)g(form.)5978 26833 y(This)302 b(in)h(turn)g(increases)f +(the)h(utilization)g(of)g(the)g(cache.)7859 28339 y(The)490 +b(complement)g(attrib)-24 b(ute)490 b(is)f(stored)g(in)g(the)h(least)g +(signi\002cant)f(bit)h(of)f(the)h(\223else\224)5978 29844 +y(pointer)300 b(of)h(each)g(node.)376 b(An)301 b(e)-18 +b(xternal)301 b(pointer)g(to)f(a)h(function)g(can)h(also)e(be)h +(complemented.)5978 31350 y(The)263 b(\223then\224)i(pointer)e(to)h(a)g +(node,)272 b(on)264 b(the)g(other)g(hand,)272 b(is)263 +b(al)-12 b(w)g(ays)263 b Fn(r)-45 b(e)d(gular)p Fo(.)362 +b(It)263 b(is)h(a)g(mistak)-12 b(e)263 b(to)5978 32855 +y(use)248 b(a)g(complement)h(pointer)f(as)g(it)h(is)e(to)i(address)e +(memory)-79 b(.)358 b(Instead,)259 b(it)248 b(is)g(al)-12 +b(w)g(ays)248 b(necessary)5978 34361 y(to)364 b(obtain)g(a)g(re)-18 +b(gular)364 b(v)-18 b(ersion)363 b(of)h(it.)559 b(This)363 +b(is)h(normally)g(done)h(by)f(calling)g Fn(Cudd)p 41276 +34361 V 437 w(Re)-48 b(gular)28 b Fo(.)5978 35866 y(It)355 +b(is)g(also)g(a)h(mistak)-12 b(e)355 b(to)g(call)h Fn(cuddUniqueInter) +384 b Fo(with)355 b(a)h(complemented)h(\223then\224)f(child)f(as)5978 +37372 y(ar)-22 b(gument.)369 b(The)284 b(calling)f(procedure)h(must)f +(apply)h(De)g(Mor)-22 b(g)-6 b(an')-67 b(s)283 b(la)-18 +b(ws)283 b(by)g(complementing)5978 38877 y(both)406 b(pointers)h +(passed)f(to)h Fn(cuddUniqueInter)434 b Fo(and)407 b(then)g(taking)g +(the)g(complement)h(of)e(the)5978 40383 y(result.)5978 +43705 y Fi(4.4)1328 b(The)332 b(Cache)5978 46029 y Fo(Each)488 +b(entry)h(of)f(the)h(cache)g(consists)e(of)h(\002)-30 +b(v)-18 b(e)489 b(\002elds:)746 b(The)488 b(operator)-48 +b(,)535 b(three)488 b(pointers)g(to)5978 47534 y(operands)434 +b(and)h(a)g(pointer)g(to)g(the)g(result.)771 b(The)434 +b(operator)h(and)g(the)g(three)g(pointers)f(to)h(the)5978 +49040 y(operands)302 b(are)h(combined)h(to)f(form)f(three)h(w)-12 +b(ords.)375 b(The)303 b(combination)h(relies)e(on)h(tw)-12 +b(o)304 b(f)-12 b(acts:)p Black 7796 51541 a Fm(\262)p +Black 606 w Fo(Most)345 b(operations)g(ha)-24 b(v)-18 +b(e)346 b(one)g(or)f(tw)-12 b(o)346 b(operands.)503 b(A)346 +b(fe)-30 b(w)346 b(bits)f(are)g(suf)-30 b(\002cient)345 +b(to)h(dis-)9008 53047 y(criminate)303 b(all)g(three-operands)g +(operations.)p Black 7796 55549 a Fm(\262)p Black 606 +w Fo(All)383 b(nodes)g(are)g(aligned)h(to)f(16-byte)h(boundaries.)616 +b(\(32-byte)383 b(boundaries)g(if)f(64-bit)9008 57054 +y(pointers)397 b(are)h(used.\))660 b(Hence,)423 b(there)398 +b(are)g(a)g(fe)-30 b(w)397 b(bits)h(a)-24 b(v)-30 b(ailable)398 +b(to)g(distinguish)f(the)9008 58559 y(three-operand)303 +b(operations)f(from)h(te)g(others)f(and)i(to)f(assign)f(unique)h(codes) +g(to)g(them.)7859 61061 y(The)386 b(cache)h(does)e(not)h(contrib)-24 +b(ute)386 b(to)g(the)g(reference)g(counts)g(of)f(the)h(nodes.)625 +b(The)385 b(f)-12 b(act)5978 62567 y(that)391 b(the)h(cache)h(contains) +f(a)g(pointer)f(to)h(a)g(node)g(does)g(not)f(imply)h(that)g(the)g(node) +g(is)f(ali)-30 b(v)-18 b(e.)5978 64072 y(Instead,)418 +b(when)396 b(g)-6 b(arbage)396 b(collection)g(tak)-12 +b(es)396 b(place,)419 b(all)396 b(entries)f(of)g(the)h(cache)g +(pointing)g(to)5978 65578 y(dead)303 b(nodes)g(are)g(cleared.)p +Black 25297 69672 a(28)p Black eop end +%%Page: 29 29 +TeXDict begin 29 28 bop Black Black 7859 7638 a Fo(The)302 +b(cache)g(is)f(also)g(cleared)g(\(of)g(all)h(entries\))e(when)i +(dynamic)g(reordering)e(tak)-12 b(es)302 b(place.)5978 +9143 y(In)g(both)h(cases,)g(the)g(entries)g(remo)-18 +b(v)g(ed)303 b(from)f(the)h(cache)h(are)f(about)g(to)g(become)h(in)-48 +b(v)-30 b(alid.)7859 10649 y(All)398 b(operands)f(and)g(results)f(in)h +(a)g(cache)h(entry)f(must)g(be)g(pointers)g(to)g(DdNodes.)659 +b(If)396 b(a)5978 12154 y(function)352 b(produces)h(more)f(than)i(one)f +(result,)364 b(or)353 b(uses)f(more)g(than)h(three)g(ar)-22 +b(guments,)365 b(there)5978 13660 y(are)303 b(currently)f(tw)-12 +b(o)303 b(solutions:)p Black 7796 16162 a Fm(\262)p Black +606 w Fo(Build)g(a)h(separate,)f(local,)g(cache.)376 +b(\(Using,)303 b(for)f(instance,)h(the)h Fn(st)324 b +Fo(library.\))p Black 7796 18663 a Fm(\262)p Black 606 +w Fo(Combine)425 b(multiple)f(results,)453 b(or)423 b(multiple)h +(operands,)454 b(into)424 b(a)g(single)g(diagram,)454 +b(by)9008 20169 y(b)-24 b(uilding)303 b(a)g(\223multiple)-18 +b(xing)303 b(structure\224)g(with)g(reserv)-18 b(ed)302 +b(v)-30 b(ariables.)5978 22671 y(Support)442 b(of)h(the)g(former)g +(solution)f(is)h(under)g(de)-30 b(v)-18 b(elopment.)796 +b(\(See)443 b Fh(cuddLCache.c)p Fo(..\))5978 24176 y(Support)302 +b(for)h(the)g(latter)g(solution)f(may)i(be)f(pro)-18 +b(vided)303 b(in)g(future)g(v)-18 b(ersions)301 b(of)i(the)g(package.) +7859 25681 y(There)280 b(are)g(three)g(sets)f(of)h(interf)-12 +b(ace)280 b(functions)g(to)g(the)g(cache.)369 b(The)280 +b(\002rst)f(set)h(is)f(for)h(func-)5978 27187 y(tions)391 +b(with)g(three)g(operands:)553 b Fn(cuddCac)-18 b(heInsert)413 +b Fo(and)391 b Fn(cuddCac)-18 b(heLookup)p Fo(.)643 b(The)391 +b(second)5978 28692 y(set)267 b(is)f(for)h(functions)g(with)g(tw)-12 +b(o)268 b(operands:)358 b Fn(cuddCac)-18 b(heInsert2)267 +b Fo(and)h Fn(cuddCac)-18 b(heLookup2)p Fo(.)5978 30198 +y(The)435 b(second)g(set)g(is)g(for)g(functions)f(with)i(one)g +(operand:)640 b Fn(cuddCac)-18 b(heInsert1)436 b Fo(and)f +Fn(cudd-)5978 31703 y(Cac)-18 b(heLookup1)p Fo(.)516 +b(The)349 b(second)g(set)h(is)e(slightly)h(f)-12 b(aster)349 +b(than)g(the)h(\002rst,)360 b(and)350 b(the)g(third)f(set)g(is)5978 +33209 y(slightly)302 b(f)-12 b(aster)302 b(than)h(the)h(second.)5978 +36487 y Fp(4.4.1)1212 b(Cache)303 b(Sizing)5978 38811 +y Fo(The)277 b(size)g(of)g(the)h(cache)g(can)g(increase)f(during)g(the) +h(e)-18 b(x)g(ecution)277 b(of)h(an)f(application.)368 +b(\(There)277 b(is)5978 40316 y(currently)310 b(no)h(w)-12 +b(ay)310 b(to)h(decrease)g(the)f(size)h(of)f(the)h(cache,)i(though)e +(it)f(w)-12 b(ould)311 b(not)g(be)g(dif)-30 b(\002cult)5978 +41822 y(to)428 b(do)h(it.\))751 b(When)429 b(a)g(cache)g(miss)f +(occurs,)459 b(the)429 b(package)g(uses)f(the)h(follo)-30 +b(wing)428 b(criteria)g(to)5978 43327 y(decide)303 b(whether)g(to)g +(resize)g(the)g(cache:)p Black 7493 45829 a(1.)p Black +606 w(If)369 b(the)i(cache)g(already)f(e)-18 b(xceeds)371 +b(the)f(limit)g(gi)-30 b(v)-18 b(en)370 b(by)h(the)f +Fh(maxCache)j Fo(\002eld)d(of)g(the)9008 47334 y(manager)-48 +b(,)381 b(no)366 b(resizing)g(tak)-12 b(es)365 b(place.)565 +b(The)365 b(limit)h(is)f(the)h(minimum)g(of)g(tw)-12 +b(o)366 b(v)-30 b(alues:)9008 48840 y(a)427 b(v)-30 b(alue)427 +b(set)g(at)g(initialization)g(time)g(and)h(possibly)e(modi\002ed)h(by)g +(the)h(application,)9008 50345 y(which)d(constitutes)e(the)i(hard)f +(limit)g(be)-18 b(yond)424 b(which)h(the)f(cache)h(will)g(ne)-30 +b(v)-18 b(er)424 b(gro)-30 b(w;)9008 51851 y(and)293 +b(a)g(number)g(that)f(depends)h(on)g(the)g(current)f(total)h(number)g +(of)f(slots)g(in)h(the)g(unique)9008 53356 y(table.)p +Black 7493 55858 a(2.)p Black 606 w(If)g(the)g(cache)i(is)e(not)g(too)h +(lar)-22 b(ge)294 b(already)-79 b(,)296 b(resizing)d(is)g(decided)h +(based)f(on)h(the)g(hit)f(rate.)9008 57363 y(The)375 +b(polic)-18 b(y)376 b(adopted)h(by)f(the)f(CUDD)i(package)g(is)e +(\223re)-30 b(w)-12 b(ard-based.)-85 b(\224)593 b(If)375 +b(the)h(cache)9008 58869 y(hit)303 b(rate)g(is)f(high,)i(then)f(it)g +(is)f(w)-12 b(orthwhile)303 b(to)g(increase)g(the)g(size)g(of)g(the)g +(cache.)5978 61371 y(When)324 b(resizing)f(tak)-12 b(es)324 +b(place,)329 b(the)324 b(statistical)f(counters)h(used)f(to)h(compute)h +(the)f(hit)f(rate)h(are)5978 62876 y(reinitialized)270 +b(so)g(as)g(to)h(pre)-30 b(v)-18 b(ent)270 b(immediate)h(resizing.)364 +b(The)270 b(number)h(of)f(entries)g(is)g(doubled.)7859 +64381 y(The)306 b(rationale)g(for)f(the)h(\223re)-30 +b(w)-12 b(ard-based\224)305 b(polic)-18 b(y)305 b(is)h(as)f(follo)-30 +b(ws.)383 b(In)305 b(man)-18 b(y)306 b(BDD/ADD)5978 65887 +y(applications)293 b(the)h(hit)f(rate)g(is)g(not)g(v)-18 +b(ery)293 b(sensiti)-30 b(v)-18 b(e)293 b(to)g(the)h(size)f(of)g(the)g +(cache:)372 b(It)293 b(is)g(primarily)p Black 25297 69672 +a(29)p Black eop end +%%Page: 30 30 +TeXDict begin 30 29 bop Black Black 5978 7638 a Fo(a)330 +b(function)g(of)g(the)g(problem)g(instance)h(at)f(hand.)457 +b(If)330 b(a)g(lar)-22 b(ge)330 b(hit)h(rate)f(is)f(observ)-18 +b(ed,)337 b(chances)5978 9143 y(are)289 b(that)g(by)g(using)g(a)g(lar) +-22 b(ge)289 b(cache,)k(the)c(results)f(of)g(lar)-22 +b(ge)290 b(problems)e(\(those)h(that)g(w)-12 b(ould)289 +b(tak)-12 b(e)5978 10649 y(longer)383 b(to)h(solv)-18 +b(e\))383 b(will)h(survi)-30 b(v)-18 b(e)382 b(in)i(the)g(cache)h +(without)f(being)g(o)-18 b(v)g(erwritten)383 b(long)h(enough)5978 +12154 y(to)418 b(cause)g(a)h(v)-30 b(aluable)418 b(cache)h(hit.)722 +b(Notice)418 b(that)h(when)g(a)f(lar)-22 b(ge)418 b(problem)h(is)e +(solv)-18 b(ed)418 b(more)5978 13660 y(than)359 b(once,)373 +b(so)358 b(are)h(its)f(recursi)-30 b(v)-18 b(ely)358 +b(generated)h(subproblems.)542 b(If)358 b(the)h(hit)g(rate)g(is)f(lo) +-30 b(w)-79 b(,)373 b(the)5978 15165 y(probability)303 +b(of)f(lar)-22 b(ge)303 b(problems)g(being)g(solv)-18 +b(ed)303 b(more)g(than)g(once)h(is)e(lo)-30 b(w)-79 b(.)7859 +16671 y(The)258 b(other)g(observ)-30 b(ation)257 b(about)h(the)g(cache) +h(sizing)f(polic)-18 b(y)258 b(is)f(that)h(there)g(is)f(little)h(point) +g(in)5978 18176 y(k)-12 b(eeping)288 b(a)h(cache)g(which)g(is)f(much)g +(lar)-22 b(ger)289 b(than)f(the)h(unique)g(table.)371 +b(Ev)-18 b(ery)288 b(time)g(the)h(unique)5978 19682 y(table)365 +b(\223\002lls)f(up,)-85 b(\224)380 b(g)-6 b(arbage)365 +b(collection)g(is)f(in)-48 b(v)-24 b(ok)-12 b(ed)365 +b(and)f(the)h(cache)h(is)e(cleared)h(of)f(all)h(dead)5978 +21187 y(entries.)359 b(A)257 b(cache)h(that)f(is)f(much)h(lar)-22 +b(ger)257 b(than)g(the)g(unique)g(table)g(is)f(therefore)h(less)e(than) +i(fully)5978 22693 y(utilized.)5978 25971 y Fp(4.4.2)1212 +b(Local)304 b(Caches)5978 28295 y Fo(Sometimes)350 b(it)h(may)g(be)g +(necessary)f(or)h(con)-48 b(v)-18 b(enient)350 b(to)h(use)g(a)g(local)g +(cache.)519 b(A)351 b(local)g(cache)5978 29800 y(can)344 +b(be)g(lossless)e(\(no)i(results)f(are)h(e)-30 b(v)-18 +b(er)344 b(o)-18 b(v)g(erwritten\),)353 b(or)344 b(it)g(may)g(store)f +(objects)h(for)g(which)5978 31305 y(canonical)428 b(representations)e +(are)h(not)h(a)-24 b(v)-30 b(ailable.)749 b(One)427 b(important)h(f)-12 +b(act)427 b(to)g(k)-12 b(eep)428 b(in)f(mind)5978 32811 +y(when)380 b(using)g(a)h(local)f(cache)h(is)f(that)g(local)h(caches)f +(are)h(not)f(cleared)h(during)f(g)-6 b(arbage)380 b(col-)5978 +34316 y(lection)351 b(or)f(before)h(reordering.)519 b(Therefore,)362 +b(it)351 b(is)f(necessary)g(to)h(increment)g(the)g(reference)5978 +35822 y(count)256 b(of)g(all)h(nodes)f(pointed)g(by)h(a)f(local)h +(cache.)361 b(\(Unless)255 b(their)h(reference)g(counts)h(are)f(guar) +-24 b(-)5978 37327 y(anteed)305 b(positi)-30 b(v)-18 +b(e)305 b(in)g(some)g(other)g(w)-12 b(ay)-79 b(.)383 +b(One)306 b(such)f(w)-12 b(ay)305 b(is)g(by)g(including)h(all)f +(partial)g(results)5978 38833 y(in)347 b(the)h(global)g(result.\))509 +b(Before)348 b(disposing)f(of)g(the)h(local)g(cache,)360 +b(all)348 b(elements)f(stored)g(in)h(it)5978 40338 y(must)250 +b(be)h(passed)g(to)g Fn(Cudd)p 17357 40338 364 45 v 437 +w(Recur)-12 b(siveDer)-45 b(ef)177 b Fo(.)357 b(As)251 +b(consequence)h(of)e(the)h(f)-12 b(act)251 b(that)g(all)g(results)5978 +41844 y(in)284 b(a)h(local)g(cache)h(are)e(referenced,)289 +b(it)284 b(is)g(generally)h(con)-48 b(v)-18 b(enient)285 +b(to)g(store)f(in)g(the)h(local)g(cache)5978 43349 y(also)k(the)h +(result)g(of)f(tri)-30 b(vial)290 b(problems,)i(which)e(are)g(not)g +(usually)g(stored)f(in)h(the)g(global)g(cache.)5978 44855 +y(Otherwise,)441 b(after)414 b(a)g(recursi)-30 b(v)-18 +b(e)413 b(call,)442 b(it)414 b(is)f(dif)-30 b(\002cult)414 +b(to)g(tell)g(whether)g(the)g(result)f(is)h(in)g(the)5978 +46360 y(cache,)303 b(and)h(therefore)e(referenced,)h(or)g(not)g(in)g +(the)g(cache,)h(and)f(therefore)g(not)g(referenced.)7859 +47866 y(An)242 b(alternati)-30 b(v)-18 b(e)242 b(approach)g(to)g +(referencing)g(the)g(results)e(in)i(the)g(local)g(caches)g(is)g(to)g +(install)5978 49371 y(hook)303 b(functions)f(\(see)h(Section)g(3.16\))g +(to)g(be)g(e)-18 b(x)g(ecuted)304 b(before)f(g)-6 b(arbage)303 +b(collection.)5978 52694 y Fi(4.5)1328 b(The)332 b(Unique)f(T)-122 +b(able)5978 55017 y Fo(A)391 b(recursi)-30 b(v)-18 b(e)390 +b(procedure)h(typically)g(splits)f(the)i(operands)e(by)i(e)-18 +b(xpanding)391 b(with)g(respect)g(to)5978 56523 y(the)358 +b(topmost)h(v)-30 b(ariable.)542 b(T)-97 b(opmost)358 +b(in)g(this)g(conte)-18 b(xt)359 b(refers)e(to)i(the)g(v)-30 +b(ariable)358 b(that)h(is)f(closest)5978 58028 y(to)381 +b(the)g(roots)f(in)h(the)g(current)g(v)-30 b(ariable)380 +b(order)-67 b(.)610 b(The)381 b(nodes,)400 b(on)381 b(the)g(other)g +(hand,)401 b(hold)381 b(the)5978 59534 y(inde)-18 b(x,)326 +b(which)321 b(is)g(in)-48 b(v)-30 b(ariant)321 b(with)g(reordering.)430 +b(Therefore,)325 b(when)d(splitting,)j(one)d(must)e(use)5978 +61039 y(the)355 b(permutation)g(array)f(maintained)h(by)g(the)g +(package)h(to)f(get)g(the)g(right)g(le)-30 b(v)-18 b(el.)531 +b(Access)354 b(to)5978 62544 y(the)272 b(permutation)h(array)f(is)g +(pro)-18 b(vided)273 b(by)f(the)h(macro)g Fn(cuddI)334 +b Fo(for)272 b(BDDs)h(and)g(ADDs,)278 b(and)273 b(by)5978 +64050 y(the)303 b(macro)g Fn(cuddIZ)363 b Fo(for)303 +b(ZDDs.)7859 65555 y(The)338 b(unique)g(table)g(consists)e(of)h(as)g +(man)-18 b(y)338 b(hash)f(tables)h(as)f(there)g(are)h(v)-30 +b(ariables)337 b(in)g(use.)p Black 25297 69672 a(30)p +Black eop end +%%Page: 31 31 +TeXDict begin 31 30 bop Black Black 5978 7638 a Fo(These)296 +b(has)g(tables)h(are)f(called)h Fn(unique)g(subtables)p +Fo(.)373 b(The)297 b(sizes)f(of)g(the)h(unique)g(subtables)f(are)5978 +9143 y(determined)303 b(by)g(tw)-12 b(o)303 b(criteria:)p +Black 7493 11645 a(1.)p Black 606 w(The)g(collision)f(lists)g(should)h +(be)g(short)g(to)g(k)-12 b(eep)303 b(access)g(time)g(do)-30 +b(wn.)p Black 7493 14147 a(2.)p Black 606 w(There)230 +b(should)g(be)g(enough)h(room)f(for)g(dead)h(nodes,)244 +b(to)231 b(pre)-30 b(v)-18 b(ent)230 b(too)g(frequent)g(g)-6 +b(arbage)9008 15652 y(collections.)5978 18154 y(While)386 +b(the)g(\002rst)f(criterion)h(is)f(f)-12 b(airly)386 +b(straightforw)-12 b(ard)384 b(to)i(implement,)407 b(the)386 +b(second)h(lea)-24 b(v)-18 b(es)5978 19660 y(more)278 +b(room)g(to)g(creati)-30 b(vity)-79 b(.)367 b(The)278 +b(CUDD)h(package)g(tries)f(to)g(\002gure)g(out)g(whether)h(more)f(dead) +5978 21165 y(node)295 b(should)g(be)g(allo)-30 b(wed)295 +b(to)h(increase)e(performance.)373 b(\(See)295 b(also)g(Section)h +(3.4.\))372 b(There)295 b(are)5978 22671 y(tw)-12 b(o)344 +b(reasons)f(for)h(not)g(doing)h(g)-6 b(arbage)345 b(collection)f(too)h +(often.)499 b(The)344 b(ob)-18 b(vious)344 b(one)h(is)f(that)g(it)5978 +24176 y(is)272 b(e)-18 b(xpensi)-30 b(v)-18 b(e.)365 +b(The)272 b(second)h(is)f(that)g(dead)h(nodes)g(may)f(be)h(reclaimed,) +279 b(if)272 b(the)-18 b(y)273 b(are)f(the)h(result)5978 +25681 y(of)325 b(a)g(successful)f(cache)i(lookup.)443 +b(Hence)326 b(dead)g(nodes)f(may)g(pro)-18 b(vide)325 +b(a)h(substantial)f(speed-)5978 27187 y(up)445 b(if)g(the)-18 +b(y)446 b(are)f(k)-12 b(ept)446 b(around)f(long)h(enough.)803 +b(The)445 b(usefulness)f(of)h(k)-12 b(eeping)446 b(man)-18 +b(y)446 b(dead)5978 28692 y(nodes)426 b(around)h(v)-30 +b(aries)426 b(from)g(application)h(to)g(application,)458 +b(and)427 b(from)f(problem)h(instance)5978 30198 y(to)393 +b(problem)g(instance.)648 b(As)393 b(in)g(the)h(sizing)f(of)g(the)h +(cache,)416 b(the)394 b(CUDD)g(package)h(adopts)e(a)5978 +31703 y(\223re)-30 b(w)-12 b(ard-based\224)421 b(polic)-18 +b(y)423 b(to)f(decide)h(ho)-30 b(w)422 b(much)h(room)f(should)g(be)h +(used)f(for)f(the)i(unique)5978 33209 y(table.)809 b(If)447 +b(the)g(number)h(of)f(dead)h(nodes)f(reclaimed)h(is)f(lar)-22 +b(ge)447 b(compared)h(to)g(the)f(number)5978 34714 y(of)396 +b(nodes)g(directly)h(requested)g(from)f(the)g(memory)h(manager)-48 +b(,)420 b(then)397 b(the)g(CUDD)g(package)5978 36220 +y(assumes)425 b(that)i(it)f(will)h(be)g(bene\002cial)g(to)f(allo)-30 +b(w)427 b(more)f(room)h(for)e(the)i(subtables,)457 b(thereby)5978 +37725 y(reducing)371 b(the)h(frequenc)-18 b(y)371 b(of)g(g)-6 +b(arbage)372 b(collection.)582 b(The)371 b(package)h(does)g(so)f(by)g +(switching)5978 39231 y(between)303 b(tw)-12 b(o)303 +b(modes)g(of)g(operation:)p Black 7493 41732 a(1.)p Black +606 w(F)-18 b(ast)287 b(gro)-30 b(wth:)368 b(In)287 b(this)h(mode,)j +(the)d(ratio)f(of)h(dead)g(nodes)g(to)g(total)g(nodes)f(required)h(for) +9008 43238 y(g)-6 b(arbage)347 b(collection)g(is)f(higher)g(than)h(in)g +(the)g(slo)-30 b(w)345 b(gro)-30 b(wth)347 b(mode)g(to)f(f)-12 +b(a)-24 b(v)g(or)346 b(resizing)9008 44743 y(of)303 b(the)g(subtables.) +p Black 7493 47245 a(2.)p Black 606 w(Slo)-30 b(w)383 +b(gro)-30 b(wth:)535 b(In)382 b(this)g(mode)i(k)-12 b(eeping)383 +b(man)-18 b(y)383 b(dead)g(nodes)g(around)g(is)f(not)h(as)g(im-)9008 +48751 y(portant)303 b(as)g(k)-12 b(eeping)303 b(memory)g(requirements)f +(lo)-30 b(w)-79 b(.)5978 51252 y(Switching)303 b(from)f(one)i(mode)f +(to)g(the)g(other)g(is)g(based)g(on)g(the)g(follo)-30 +b(wing)303 b(criteria:)p Black 7493 53754 a(1.)p Black +606 w(If)f(the)h(unique)h(table)f(is)g(already)g(lar)-22 +b(ge,)303 b(only)g(slo)-30 b(w)303 b(gro)-30 b(wth)302 +b(is)h(possible.)p Black 7493 56256 a(2.)p Black 606 +w(If)467 b(the)g(table)h(is)f(small)g(and)h(man)-18 b(y)467 +b(dead)h(nodes)f(are)h(being)f(reclaimed,)509 b(then)468 +b(f)-12 b(ast)9008 57761 y(gro)-30 b(wth)303 b(is)f(selected.)5978 +60263 y(This)329 b(polic)-18 b(y)330 b(is)g(especially)g(ef)-30 +b(fecti)g(v)-18 b(e)330 b(when)h(the)f(diagrams)g(being)g(manipulated)h +(ha)-24 b(v)-18 b(e)331 b(lots)5978 61768 y(of)322 b(recombination.)437 +b(Notice)324 b(the)f(interplay)g(of)g(the)g(cache)h(sizing)f(and)h +(unique)f(sizing:)416 b(F)-18 b(ast)5978 63274 y(gro)-30 +b(wth)298 b(normally)g(occurs)h(when)g(the)g(cache)g(hit)g(rate)f(is)h +(lar)-22 b(ge.)374 b(The)299 b(cache)g(and)g(the)g(unique)5978 +64779 y(table)k(then)g(gro)-30 b(w)303 b(in)g(concert,)g(preserving)g +(a)g(health)-6 b(y)303 b(balance)h(between)g(their)f(sizes.)p +Black 25297 69672 a(31)p Black eop end +%%Page: 32 32 +TeXDict begin 32 31 bop Black Black 5978 7638 a Fi(4.6)1328 +b(Allo)-13 b(wing)333 b(Asynchr)-24 b(onous)330 b(Reordering)5978 +9962 y Fo(Asynchronous)416 b(reordering)g(is)g(the)h(reordering)f(that) +h(is)f(triggered)h(automatically)g(by)g(the)5978 11467 +y(increase)448 b(of)g(the)g(number)h(of)e(nodes.)812 +b(Asynchronous)448 b(reordering)f(tak)-12 b(es)448 b(place)h(when)g(a) +5978 12973 y(ne)-30 b(w)367 b(internal)g(node)h(must)f(be)g(created,) +384 b(and)368 b(the)f(number)h(of)f(nodes)g(has)g(reached)h(a)f(gi)-30 +b(v)-18 b(en)5978 14478 y(threshold.)604 b(\(The)378 +b(threshold)h(is)g(adjusted)g(by)h(the)f(package)h(e)-30 +b(v)-18 b(ery)379 b(time)h(reordering)e(tak)-12 b(es)5978 +15984 y(place.\))7859 17489 y(Those)302 b(procedures)h(that)f(do)h(not) +g(create)g(ne)-30 b(w)303 b(nodes)f(\(e.g.,)h(procedures)f(that)h +(count)g(the)5978 18994 y(number)c(of)h(nodes)g(or)f(minterms\))g(need) +h(not)g(w)-12 b(orry)299 b(about)h(asynchronous)f(reordering:)374 +b(No)5978 20500 y(special)303 b(precaution)g(is)f(necessary)h(in)g +(writing)g(them.)7859 22005 y(Procedures)e(that)g(only)g(manipulate)g +(decision)g(diagrams)f(through)h(the)g(e)-18 b(xported)301 +b(func-)5978 23511 y(tions)343 b(of)g(the)h(CUDD)h(package)g(also)e +(need)i(not)e(concern)i(themselv)-18 b(es)343 b(with)h(asynchronous) +5978 25016 y(reordering.)375 b(\(See)303 b(Section)g(3.2.1)g(for)g(the) +g(e)-18 b(xceptions.\))7859 26522 y(The)331 b(remaining)g(class)f(of)g +(procedures)g(is)g(composed)h(of)f(functions)h(that)f(visit)g(the)h +(dia-)5978 28027 y(grams)344 b(and)h(may)g(create)g(ne)-30 +b(w)345 b(nodes.)502 b(All)345 b(such)f(procedures)h(in)g(the)g(CUDD)g +(package)h(are)5978 29533 y(written)435 b(so)h(that)g(the)-18 +b(y)436 b(can)g(be)g(interrupted)g(by)g(dynamic)g(reordering.)774 +b(The)435 b(general)h(ap-)5978 31038 y(proach)313 b(follo)-30 +b(wed)314 b(goes)f(under)h(the)g(name)g(of)f(\223abort)h(and)g(retry.) +-85 b(\224)407 b(As)313 b(the)h(name)g(implies,)i(a)5978 +32544 y(computation)303 b(that)g(is)g(interrupted)g(by)g(dynamic)g +(reordering)g(is)f(aborted)h(and)h(tried)e(ag)-6 b(ain.)7859 +34049 y(A)301 b(recursi)-30 b(v)-18 b(e)300 b(procedure)g(that)h(can)g +(be)g(interrupted)f(by)h(dynamic)g(reordering)f(\(an)g(inter)-24 +b(-)5978 35555 y(ruptible)284 b(procedure)h(from)f(no)-30 +b(w)285 b(on\))f(is)g(composed)h(of)g(tw)-12 b(o)285 +b(functions.)369 b(One)285 b(is)f(responsible)5978 37060 +y(for)378 b(the)i(real)g(computation.)606 b(The)379 b(other)h(is)f(a)g +(simple)h(wrapper,)398 b(which)380 b(tests)f(whether)h(re-)5978 +38566 y(ordering)302 b(occurred)h(and)h(restarts)d(the)i(computation)h +(if)f(it)f(did.)7859 40071 y(Asynchronous)238 b(reordering)g(of)g(BDDs) +h(and)g(ADDs)f(can)h(only)g(be)g(triggered)f(inside)g +Fn(cud-)5978 41576 y(dUniqueInter)28 b Fo(,)424 b(when)401 +b(a)f(ne)-30 b(w)400 b(node)h(is)f(about)g(to)h(be)f(created.)668 +b(Lik)-12 b(e)-30 b(wise,)424 b(asynchronous)5978 43082 +y(reordering)363 b(of)h(ZDDs)f(can)h(only)g(be)h(triggered)e(inside)h +Fn(cuddUniqueInterZdd)33 b Fo(.)558 b(When)365 b(re-)5978 +44587 y(ordering)302 b(is)h(triggered,)f(three)i(things)e(happen:)p +Black 7493 46987 a(1.)p Black 606 w Fn(cuddUniqueInter)331 +b Fo(returns)302 b(a)h(NULL)g(v)-30 b(alue;)p Black 7493 +49447 a(2.)p Black 606 w(The)304 b(\003ag)h Fn(r)-45 +b(eor)g(der)g(ed)336 b Fo(of)304 b(the)h(manager)g(is)f(set)g(to)g(1.) +380 b(\(0)304 b(means)g(no)h(reordering,)f(while)9008 +50953 y(2)f(indicates)g(an)g(error)f(occurred)h(during)g(reordering.\)) +p Black 7493 53414 a(3.)p Black 606 w(The)340 b(counter)g +Fn(r)-45 b(eor)g(derings)339 b Fo(of)h(the)g(manager)g(is)g +(incremented.)487 b(The)340 b(counter)g(is)g(ini-)9008 +54919 y(tialized)466 b(to)g(0)g(when)g(the)g(manager)g(is)f(started)g +(and)h(can)g(be)g(accessed)g(by)g(calling)9008 56425 +y Fn(Cudd)p 11707 56425 364 45 v 437 w(ReadReor)-45 b(derings)p +Fo(.)489 b(By)342 b(taking)f(tw)-12 b(o)341 b(readings)g(of)g(the)g +(counter)-48 b(,)351 b(an)341 b(applica-)9008 57930 y(tion)413 +b(can)h(determine)g(if)f(v)-30 b(ariable)414 b(reordering)f(has)g(tak) +-12 b(en)414 b(place)g(between)g(the)g(\002rst)9008 59436 +y(and)347 b(the)g(second)g(reading.)507 b(The)346 b(package)i(itself,) +357 b(ho)-30 b(we)g(v)-18 b(er)-48 b(,)357 b(does)346 +b(not)h(mak)-12 b(e)347 b(use)f(of)9008 60941 y(the)303 +b(counter:)376 b(It)303 b(is)f(mentioned)i(here)f(for)f(completeness.) +7859 63340 y(The)453 b(recursi)-30 b(v)-18 b(e)451 b(procedure)i(that)g +(recei)-30 b(v)-18 b(es)452 b(a)h(NULL)e(v)-30 b(alue)453 +b(from)f Fn(cuddUniqueInter)5978 64846 y Fo(must)k(free)h(all)g +(intermediate)h(results)d(that)j(it)f(may)g(ha)-24 b(v)-18 +b(e)457 b(computed)h(before,)495 b(and)458 b(return)5978 +66351 y(NULL)302 b(in)h(its)g(turn.)p Black 25297 69672 +a(32)p Black eop end +%%Page: 33 33 +TeXDict begin 33 32 bop Black Black 7859 7638 a Fo(The)398 +b(wrapper)f(function)g(does)g(not)h(decide)g(whether)f(reordering)g +(occurred)h(based)f(on)5978 9143 y(the)479 b(NULL)g(return)g(v)-30 +b(alue,)524 b(because)480 b(the)f(NULL)g(v)-30 b(alue)480 +b(may)f(be)h(the)g(result)e(of)i(lack)f(of)5978 10649 +y(memory)-79 b(.)376 b(Instead,)302 b(it)h(checks)g(the)g +Fn(r)-45 b(eor)g(der)g(ed)336 b Fo(\003ag.)7859 12154 +y(When)361 b(a)f(recursi)-30 b(v)-18 b(e)360 b(procedure)g(calls)g +(another)g(recursi)-30 b(v)-18 b(e)359 b(procedure)h(that)h(may)f +(cause)5978 13660 y(reordering,)342 b(it)335 b(should)f(bypass)h(the)g +(wrapper)g(and)g(call)g(the)g(recursi)-30 b(v)-18 b(e)334 +b(procedure)h(directly)-79 b(.)5978 15165 y(Otherwise,)370 +b(the)357 b(calling)g(procedure)g(will)g(not)f(kno)-30 +b(w)357 b(whether)g(reordering)g(occurred,)370 b(and)5978 +16671 y(will)333 b(not)g(be)g(able)g(to)g(restart.)465 +b(This)332 b(is)g(the)h(main)h(reason)e(wh)-6 b(y)333 +b(most)g(recursi)-30 b(v)-18 b(e)332 b(procedures)5978 +18176 y(are)391 b(internal,)413 b(rather)391 b(than)g(static.)641 +b(\(The)390 b(wrappers,)413 b(on)391 b(the)h(other)f(hand,)413 +b(are)392 b(mostly)e(e)-18 b(x-)5978 19682 y(ported.\))5978 +23004 y Fi(4.7)1328 b(Deb)-27 b(ugging)5978 25328 y Fo(By)467 +b(de\002ning)h(the)f(symbol)g(DD)p 20108 25328 364 45 +v 436 w(DEB)-12 b(UG)468 b(during)f(compilation,)508 +b(numerous)467 b(checks)g(are)5978 26833 y(added)230 +b(to)h(the)f(code.)352 b(In)230 b(addition,)245 b(the)231 +b(procedures)f Fn(Cudd)p 30650 26833 V 437 w(Deb)-24 +b(ugChec)g(k)21 b Fo(,)245 b Fn(Cudd)p 40493 26833 V +437 w(Chec)-24 b(kK)-42 b(e)-36 b(ys)p Fo(,)5978 28339 +y(and)257 b Fn(cuddHeapPr)-55 b(o\002le)258 b Fo(can)g(be)g(called)g +(at)g(an)-18 b(y)257 b(point)h(to)f(v)-18 b(erify)257 +b(the)h(consistenc)-18 b(y)257 b(of)g(the)h(data)5978 +29844 y(structure.)542 b(\()p Fn(cuddHeapPr)-55 b(o\002le)358 +b Fo(is)h(an)g(internal)f(procedure.)543 b(It)358 b(is)h(declared)g(in) +f Fn(cuddInt.h)p Fo(.\))5978 31350 y(Procedures)450 b +Fn(Cudd)p 14513 31350 V 437 w(Deb)-24 b(ugChec)g(k)473 +b Fo(and)452 b Fn(Cudd)p 26462 31350 V 437 w(Chec)-24 +b(kK)-42 b(e)-36 b(ys)451 b Fo(are)h(especially)f(useful)g(when)5978 +32855 y(CUDD)282 b(reports)f(that)g(during)h(g)-6 b(arbage)282 +b(collection)g(the)f(number)h(of)f(nodes)h(actually)g(deleted)5978 +34361 y(from)365 b(the)h(unique)g(table)h(is)e(dif)-30 +b(ferent)365 b(from)g(the)i(count)f(of)g(dead)g(nodes)g(k)-12 +b(ept)366 b(by)g(the)g(man-)5978 35866 y(ager)-67 b(.)454 +b(The)328 b(error)g(causing)h(the)h(discrepanc)-18 b(y)328 +b(may)i(ha)-24 b(v)-18 b(e)329 b(occurred)g(much)g(earlier)g(than)g(it) +g(is)5978 37372 y(disco)-18 b(v)g(ered.)522 b(A)353 b(fe)-30 +b(w)351 b(strate)-18 b(gicaly)352 b(placed)h(calls)f(to)g(the)g(deb)-24 +b(ugging)353 b(procedures)f(can)g(con-)5978 38877 y(siderably)366 +b(narro)-30 b(w)367 b(do)-30 b(wn)367 b(the)g(search)g(for)g(the)g +(source)g(of)g(the)g(problem.)568 b(\(F)-18 b(or)367 +b(instance,)383 b(a)5978 40383 y(call)290 b(to)g Fn(Cudd)p +11950 40383 V 437 w(Recur)-12 b(siveDer)-45 b(ef)467 +b Fo(where)290 b(one)g(to)h Fn(Cudd)p 29488 40383 V 437 +w(Der)-45 b(ef)467 b Fo(w)-12 b(as)290 b(required)f(may)i(be)f(iden-) +5978 41888 y(ti\002ed)303 b(in)g(this)f(w)-12 b(ay)-79 +b(.\))7859 43393 y(One)376 b(of)f(the)g(most)g(common)g(problems)g +(encountered)h(in)f(deb)-24 b(ugging)375 b(code)h(based)f(on)5978 +44899 y(the)427 b(CUDD)h(package)g(is)e(a)i(missing)e(call)h(to)h +Fn(Cudd)p 28792 44899 V 437 w(Recur)-12 b(siveDer)-45 +b(ef)177 b Fo(.)747 b(T)-97 b(o)427 b(help)g(identify)5978 +46404 y(this)269 b(type)i(of)e(problems,)277 b(the)270 +b(package)h(pro)-18 b(vides)269 b(a)i(function)f(called)g +Fn(Cudd)p 38128 46404 V 437 w(Chec)-24 b(kZer)-55 b(oRef)177 +b Fo(.)5978 47910 y(This)475 b(function)i(should)g(be)g(called)g +(immediately)g(before)f(shutting)h(do)-30 b(wn)477 b(the)f(manager)-67 +b(.)5978 49415 y Fn(Cudd)p 8677 49415 V 437 w(Chec)-24 +b(kZer)-55 b(oRef)420 b Fo(checks)242 b(that)g(the)h(only)f(nodes)h +(left)f(with)g(non-zero)g(reference)g(counts)5978 50921 +y(are)340 b(the)h(prede\002ned)g(constants,)349 b(the)341 +b(BDD)g(projection)g(functions,)349 b(and)341 b(nodes)g(whose)f(ref-) +5978 52426 y(erence)303 b(counts)g(are)g(saturated.)7859 +53932 y(F)-18 b(or)385 b(this)f(function)h(to)g(be)g(ef)-30 +b(fecti)g(v)-18 b(e)384 b(the)h(application)h(must)e(e)-18 +b(xplicitly)385 b(dispose)f(of)h(all)5978 55437 y(diagrams)302 +b(to)h(which)h(it)f(has)f(pointers)h(before)g(calling)g(it.)5978 +58760 y Fi(4.8)1328 b(Gathering)333 b(and)e(Inter)-13 +b(pr)-24 b(eting)330 b(Statistics)5978 61083 y Fo(Function)409 +b Fn(Cudd)p 13396 61083 V 437 w(PrintInfo)e Fo(can)i(be)g(called)g(to)g +(print)f(out)h(the)g(v)-30 b(alues)408 b(of)h(parameters)f(and)5978 +62589 y(statistics)354 b(for)g(a)i(manager)-67 b(.)533 +b(The)355 b(output)h(of)f Fn(Cudd)p 27871 62589 V 437 +w(PrintInfo)f Fo(is)h(di)-30 b(vided)355 b(in)g(tw)-12 +b(o)356 b(sections.)5978 64094 y(The)244 b(\002rst)g(reports)f(the)i(v) +-30 b(alues)244 b(of)g(parameters)g(that)h(are)g(under)f(the)h +(application)g(control.)356 b(The)5978 65600 y(second)325 +b(reports)g(the)h(v)-30 b(alues)325 b(of)g(statistical)g(counters)g +(and)h(other)f(non-modi\002able)h(parame-)p Black 25297 +69672 a(33)p Black eop end +%%Page: 34 34 +TeXDict begin 34 33 bop Black Black 5978 7638 a Fo(ters.)391 +b(A)308 b(quick)h(guide)f(to)h(the)f(interpretation)h(of)f(all)g(these) +g(quantities)g(follo)-30 b(ws.)391 b(F)-18 b(or)308 b(ease)g(of)5978 +9143 y(e)-18 b(xposition,)351 b(we)342 b(re)-30 b(v)-18 +b(erse)341 b(the)h(order)f(and)h(describe)g(the)g(non-modi\002able)g +(parameters)f(\002rst.)5978 10649 y(W)-97 b(e')-12 b(ll)302 +b(use)h(a)g(sample)g(run)g(as)g(e)-18 b(xample.)376 b(There)303 +b(is)f(nothing)h(special)h(about)f(this)f(run.)5978 13927 +y Fp(4.8.1)1212 b(Non)303 b(Modi\002able)g(P)-12 b(arameters)5978 +16251 y Fo(The)302 b(list)h(of)g(non-modi\002able)g(parameters)f +(starts)g(with:)p Black Black 8887 18753 a Fh(****)728 +b(CUDD)g(non-modifiable)j(parameters)f(****)8887 20258 +y(Memory)f(in)e(use:)i(32544220)5978 22760 y Fo(This)317 +b(is)i(the)f(memory)h(used)g(by)f(CUDD)i(for)e(three)h(things)f +(mainly:)407 b(Unique)320 b(table)f(\(includ-)5978 24265 +y(ing)341 b(all)f(DD)i(nodes)e(in)h(use\),)350 b(node)341 +b(free)g(list,)349 b(and)342 b(computed)f(table.)490 +b(This)340 b(number)g(almost)5978 25771 y(ne)-30 b(v)-18 +b(er)350 b(decreases)g(in)h(the)g(lifetime)g(of)f(a)h(CUDD)h(manager) +-48 b(,)362 b(because)352 b(CUDD)f(does)g(not)g(re-)5978 +27276 y(lease)384 b(memory)h(when)g(it)g(frees)f(nodes.)621 +b(Rather)-48 b(,)405 b(it)385 b(puts)g(the)g(nodes)f(on)h(its)g(o)-30 +b(wn)384 b(free)h(list.)5978 28782 y(This)396 b(number)h(is)f(in)h +(bytes.)658 b(It)397 b(does)g(not)g(represent)f(the)h(peak)h(memory)f +(occupation,)421 b(be-)5978 30287 y(cause)393 b(it)g(does)g(not)g +(include)h(the)f(size)g(of)g(data)h(structures)e(created)h(temporarily) +g(by)g(some)5978 31793 y(functions)302 b(\(e.g.,)h(local)g(look-up)g +(tables\).)p Black Black 8887 34626 a Fh(Peak)728 b(number)h(of)f +(nodes:)h(837018)5978 37460 y Fo(This)400 b(number)h(is)f(the)h(number) +g(of)g(nodes)g(that)g(the)g(manager)g(has)g(allocated.)671 +b(This)400 b(is)g(not)5978 38966 y(the)353 b(lar)-22 +b(gest)353 b(size)g(of)g(the)g(BDDs,)366 b(because)353 +b(the)h(manager)f(will)g(normally)h(ha)-24 b(v)-18 b(e)353 +b(some)g(dead)5978 40471 y(nodes)302 b(and)i(some)f(nodes)f(on)i(the)f +(free)f(list.)p Black Black 8887 43305 a Fh(Peak)728 +b(number)h(of)f(live)g(nodes:)h(836894)5978 46139 y Fo(This)256 +b(is)i(the)g(lar)-22 b(gest)257 b(number)h(of)f(li)-30 +b(v)-18 b(e)258 b(nodes)g(that)f(the)h(manager)h(has)e(held)h(since)g +(its)f(creation.)p Black Black 8887 48973 a Fh(Number)729 +b(of)e(BDD)h(variables:)i(198)8887 50478 y(Number)f(of)e(ZDD)h +(variables:)i(0)5978 53312 y Fo(These)302 b(numbers)h(tell)g(us)f(this) +h(run)g(w)-12 b(as)302 b(not)h(using)g(ZDDs.)p Black +Black 8887 56146 a Fh(Number)729 b(of)e(cache)i(entries:)g(1048576)5978 +58979 y Fo(Current)309 b(number)g(of)f(slots)g(of)h(the)g(computed)h +(table.)394 b(If)308 b(one)h(has)g(a)g(performance)g(problem,)5978 +60485 y(this)302 b(is)h(one)g(of)g(the)g(numbers)f(to)h(look)h(at.)375 +b(The)303 b(cache)h(size)f(is)f(al)-12 b(w)g(ays)303 +b(a)g(po)-30 b(wer)303 b(of)g(2.)p Black Black 8887 63319 +a Fh(Number)729 b(of)e(cache)i(look-ups:)h(2996536)8887 +64824 y(Number)f(of)e(cache)i(hits:)g(1187087)p Black +25297 69672 a Fo(34)p Black eop end +%%Page: 35 35 +TeXDict begin 35 34 bop Black Black 5978 7638 a Fo(These)280 +b(numbers)h(gi)-30 b(v)-18 b(e)281 b(an)g(indication)g(of)g(the)g(hit)g +(rate)g(in)g(the)h(computed)f(table.)369 b(It)281 b(is)f(not)h(un-)5978 +9143 y(lik)-12 b(ely)303 b(for)f(model)h(checking)h(runs)e(to)h(get)h +(hit)f(rates)f(e)-30 b(v)-18 b(en)303 b(higher)g(than)g(this)g(one)g +(\(39.62\045\).)p Black Black 8887 11874 a Fh(Number)729 +b(of)e(cache)i(insertions:)h(1809473)8887 13380 y(Number)f(of)e(cache)i +(collisions:)h(961208)8887 14885 y(Number)f(of)e(cache)i(deletions:)h +(0)5978 17616 y Fo(A)399 b(collision)f(occurs)h(when)h(a)f(cache)h +(entry)e(is)h(o)-18 b(v)g(erwritten.)663 b(A)399 b(deletion)h(occurs)e +(when)i(a)5978 19122 y(cache)332 b(entry)g(is)g(in)-48 +b(v)-30 b(alidated)331 b(\(e.g.,)339 b(during)332 b(g)-6 +b(arbage)332 b(collection\).)463 b(If)331 b(the)i(number)f(of)f(dele-) +5978 20627 y(tions)265 b(is)g(high)h(compared)g(to)g(the)g(number)g(of) +g(collisions,)272 b(it)266 b(means)g(that)g(g)-6 b(arbage)266 +b(collection)5978 22133 y(occurs)385 b(too)i(often.)625 +b(In)386 b(this)g(case)g(there)g(were)g(no)h(g)-6 b(arbage)386 +b(collections;)428 b(hence,)408 b(no)386 b(dele-)5978 +23638 y(tions.)p Black Black 8887 26369 a Fh(Cache)728 +b(used)h(slots)f(=)g(80.90\045)h(\(expected)g(82.19\045\))5978 +29100 y Fo(Percentage)311 b(of)f(cache)h(slots)e(that)i(contain)g(a)g +(v)-30 b(alid)310 b(entry)-79 b(.)398 b(If)310 b(this)g(number)h(is)f +(small,)h(it)g(may)5978 30606 y(signal)302 b(one)i(of)e(three)h +(conditions:)p Black 7493 33022 a(1.)p Black 606 w(The)g(cache)h(may)f +(ha)-24 b(v)-18 b(e)303 b(been)g(recently)h(resized)e(and)i(it)f(is)f +(still)g(\002lling)h(up.)p Black 7493 35489 a(2.)p Black +606 w(The)363 b(cache)g(is)g(too)g(lar)-22 b(ge)363 b(for)f(the)h +(BDDs.)556 b(This)362 b(should)h(not)g(happen)g(if)g(the)g(size)f(of) +9008 36995 y(the)303 b(cache)h(is)e(determined)i(by)f(CUDD.)p +Black 7493 39462 a(3.)p Black 606 w(The)k(hash)g(function)h(is)f(not)g +(w)-12 b(orking)308 b(properly)-79 b(.)388 b(This)307 +b(is)g(accompanied)h(by)g(a)g(de)-18 b(gra-)9008 40968 +y(dation)428 b(in)f(performance.)748 b(Con)-48 b(v)-18 +b(ersely)-79 b(,)459 b(a)427 b(de)-18 b(gradation)428 +b(in)f(performance)g(may)h(be)9008 42473 y(due)303 b(to)g(bad)h(hash)e +(function)h(beha)-24 b(vior)-67 b(.)5978 44889 y(The)342 +b(e)-18 b(xpected)343 b(v)-30 b(alue)342 b(is)g(computed)h(assuming)f +(a)g(uniformly)g(random)h(distrib)-24 b(ution)341 b(of)h(the)5978 +46394 y(accesses.)563 b(If)365 b(the)h(dif)-30 b(ference)365 +b(between)h(the)g(measured)g(v)-30 b(alue)366 b(and)g(the)f(e)-18 +b(xpected)367 b(v)-30 b(alue)366 b(is)5978 47900 y(lar)-22 +b(ge)303 b(\(unlik)-12 b(e)303 b(this)f(case\),)h(the)g(cache)h(is)e +(not)h(w)-12 b(orking)303 b(properly)-79 b(.)p Black +Black 8887 50631 a Fh(Soft)728 b(limit)h(for)f(cache)g(size:)h(1318912) +5978 53362 y Fo(This)319 b(number)i(says)f(ho)-30 b(w)320 +b(lar)-22 b(ge)321 b(the)g(cache)g(can)g(gro)-30 b(w)-79 +b(.)429 b(This)319 b(limit)i(is)f(based)h(on)f(the)h(size)f(of)5978 +54867 y(the)362 b(unique)h(table.)555 b(CUDD)363 b(uses)f(a)g(re)-30 +b(w)-12 b(ard-based)362 b(polic)-18 b(y)363 b(for)e(gro)-30 +b(wing)363 b(the)f(cache.)555 b(\(See)5978 56373 y(Section)394 +b(4.4.1.\))647 b(The)394 b(def)-12 b(ault)394 b(hit)f(rate)h(for)f +(resizing)g(is)g(30\045)h(and)g(the)g(v)-30 b(alue)394 +b(in)g(ef)-30 b(fect)393 b(is)5978 57878 y(reported)302 +b(among)i(the)f(modi\002able)g(parameters.)p Black Black +8887 60609 a Fh(Number)729 b(of)e(buckets)j(in)d(unique)i(table:)g +(329728)5978 63340 y Fo(This)357 b(number)i(is)f(e)-18 +b(xactly)359 b(one)g(quarter)g(of)f(the)h(one)g(abo)-18 +b(v)g(e.)543 b(This)358 b(is)g(indeed)h(ho)-30 b(w)359 +b(the)g(soft)5978 64846 y(limit)482 b(is)g(determined)h(currently)-79 +b(,)528 b(unless)482 b(the)g(computed)i(table)f(hits)f(the)h +(speci\002ed)f(hard)5978 66351 y(limit.)375 b(\(See)303 +b(belo)-30 b(w)-79 b(.\))p Black 25297 69672 a(35)p Black +eop end +%%Page: 36 36 +TeXDict begin 36 35 bop Black Black Black Black 8887 +7638 a Fh(Used)728 b(buckets)h(in)f(unique)h(table:)g(87.96\045)g +(\(expected)g(87.93\045\))5978 10302 y Fo(Percentage)322 +b(of)f(unique)h(table)g(b)-24 b(uck)-12 b(ets)321 b(that)h(contain)g +(at)g(least)f(one)h(node.)432 b(Remarks)322 b(analo-)5978 +11807 y(gous)302 b(to)h(those)g(made)h(about)f(the)g(used)g(cache)h +(slots)e(apply)-79 b(.)p Black Black 8887 14471 a Fh(Number)729 +b(of)e(BDD)h(and)h(ADD)f(nodes:)h(836894)8887 15976 y(Number)g(of)e +(ZDD)h(nodes:)h(0)5978 18640 y Fo(Ho)-30 b(w)303 b(man)-18 +b(y)303 b(nodes)g(are)g(currently)f(in)h(the)h(unique)f(table,)g +(either)g(ali)-30 b(v)-18 b(e)303 b(or)g(dead.)p Black +Black 8887 21303 a Fh(Number)729 b(of)e(dead)i(BDD)f(and)g(ADD)g +(nodes:)h(0)8887 22808 y(Number)g(of)e(dead)i(ZDD)f(nodes:)h(0)5978 +25472 y Fo(Subtract)351 b(these)h(numbers)f(from)g(those)g(abo)-18 +b(v)g(e)352 b(to)f(get)h(the)g(number)g(of)f(li)-30 b(v)-18 +b(e)351 b(nodes.)521 b(In)352 b(this)5978 26977 y(case)391 +b(there)h(are)g(no)g(dead)g(nodes)f(because)i(the)e(application)i(uses) +e(delayed)h(dereferencing)5978 28483 y Fn(Cudd)p 8677 +28483 364 45 v 437 w(DelayedDer)-45 b(efBdd)33 b Fo(.)p +Black Black 8887 31146 a Fh(Total)728 b(number)h(of)f(nodes)h +(allocated:)h(836894)5978 33810 y Fo(This)373 b(is)i(the)g(total)f +(number)h(of)g(nodes)f(that)h(were)g(requested)f(and)h(obtained)h(from) +e(the)h(free)5978 35315 y(list.)680 b(It)404 b(ne)-30 +b(v)-18 b(er)405 b(decreases,)430 b(and)405 b(is)f(not)h(an)g +(indication)g(of)f(memory)h(occupation)h(after)e(the)5978 +36821 y(\002rst)302 b(g)-6 b(arbage)303 b(collection.)376 +b(Rather)-48 b(,)303 b(it)g(is)g(a)g(measure)g(of)f(the)i(package)g +(acti)-30 b(vity)-79 b(.)p Black Black 8887 39484 a Fh(Total)728 +b(number)h(of)f(nodes)h(reclaimed:)h(0)5978 42148 y Fo(These)365 +b(are)h(the)g(nodes)f(that)h(were)g(resuscitated)g(from)f(the)h(dead.) +564 b(If)366 b(the)-18 b(y)365 b(are)h(man)-18 b(y)366 +b(more)5978 43653 y(than)276 b(the)g(allocated)g(nodes,)281 +b(and)c(the)f(total)g(number)f(of)h(slots)f(is)g(lo)-30 +b(w)276 b(relati)-30 b(v)-18 b(e)275 b(to)h(the)g(number)5978 +45159 y(of)338 b(nodes,)347 b(then)339 b(one)g(may)g(w)-12 +b(ant)339 b(to)f(increase)h(the)f(limit)h(for)f(f)-12 +b(ast)338 b(unique)g(table)h(gro)-30 b(wth.)482 b(In)5978 +46664 y(this)302 b(case,)h(the)g(number)g(is)g(0)g(because)g(of)g +(delayed)h(dereferencing.)p Black Black 8887 49328 a +Fh(Garbage)729 b(collections)h(so)e(far:)g(0)8887 50833 +y(Time)g(for)g(garbage)h(collections:)i(0.00)d(sec)8887 +52339 y(Reorderings)i(so)e(far:)g(0)8887 53844 y(Time)g(for)g +(reordering:)i(0.00)f(sec)5978 56508 y Fo(There)327 b(is)h(a)g(GC)h +(for)f(each)g(reordering.)451 b(Hence)329 b(the)f(\002rst)f(count)i +(will)f(al)-12 b(w)g(ays)328 b(be)g(at)h(least)e(as)5978 +58013 y(lar)-22 b(ge)303 b(as)g(the)g(second.)p Black +Black 8887 60677 a Fh(Node)728 b(swaps)h(in)e(reordering:)k(0)5978 +63340 y Fo(This)400 b(is)g(the)h(number)g(of)g(elementary)g(reordering) +g(steps.)669 b(Each)401 b(step)f(consists)g(of)h(the)g(re-)5978 +64846 y(e)-18 b(xpression)361 b(of)h(one)h(node)g(while)g(sw)-12 +b(apping)363 b(tw)-12 b(o)362 b(adjacent)i(v)-30 b(ariables.)554 +b(This)361 b(number)i(is)f(a)5978 66351 y(good)303 b(measure)g(of)f +(the)i(amount)f(of)g(w)-12 b(ork)302 b(done)i(in)f(reordering.)p +Black 25297 69672 a(36)p Black eop end +%%Page: 37 37 +TeXDict begin 37 36 bop Black Black 5978 7638 a Fp(4.8.2)1212 +b(Modi\002able)303 b(P)-12 b(arameters)5978 9962 y Fo(Let)296 +b(us)g(no)-30 b(w)297 b(consider)f(the)h(modi\002able)g(parameters,)g +(that)g(is,)g(those)f(settings)g(on)h(which)g(the)5978 +11467 y(application)303 b(or)g(the)g(user)g(has)f(control.)p +Black Black 8887 14301 a Fh(****)728 b(CUDD)g(modifiable)i(parameters)g +(****)8887 15806 y(Hard)e(limit)h(for)f(cache)g(size:)h(8388608)5978 +18640 y Fo(This)391 b(number)i(counts)f(entries.)644 +b(Each)392 b(entry)h(is)f(16)g(bytes)h(if)f(CUDD)h(is)f(compiled)h(to)f +(use)5978 20146 y(32-bit)302 b(pointers.)376 b(T)-97 +b(w)-12 b(o)302 b(important)h(observ)-30 b(ations)302 +b(are)h(in)g(order:)p Black 7493 22647 a(1.)p Black 606 +w(If)389 b(the)h(datasize)f(limit)h(is)f(set,)411 b(CUDD)390 +b(will)g(use)f(it)h(to)g(determine)g(this)f(number)g(au-)9008 +24153 y(tomatically)-79 b(.)492 b(On)341 b(a)h(Unix)f(system,)351 +b(one)341 b(can)h(type)g(\223limit\224)g(or)f(\223ulimit\224)g(to)h(v) +-18 b(erify)341 b(if)9008 25658 y(this)333 b(v)-30 b(alue)334 +b(is)f(set.)468 b(If)333 b(the)h(datasize)g(limit)g(is)f(not)h(set,)341 +b(CUDD)335 b(uses)e(a)h(def)-12 b(ault)334 b(which)9008 +27164 y(is)277 b(rather)h(small.)367 b(If)277 b(you)h(ha)-24 +b(v)-18 b(e)278 b(enough)h(memory)f(\(say)f(64MB)h(or)g(more\))f(you)h +(should)9008 28669 y(seriously)344 b(consider)h Fn(not)367 +b Fo(using)345 b(the)h(def)-12 b(ault.)502 b(So,)356 +b(either)346 b(set)f(the)g(datasize)h(limit,)355 b(or)9008 +30175 y(o)-18 b(v)g(erride)302 b(the)i(def)-12 b(ault)302 +b(with)i Fn(Cudd)p 23912 30175 364 45 v 437 w(SetMaxCac)-18 +b(heHar)-45 b(d)33 b Fo(.)p Black 7493 32676 a(2.)p Black +606 w(If)265 b(a)g(process)g(seems)g(to)g(be)h(going)g(no)-30 +b(where,)273 b(a)266 b(small)f(v)-30 b(alue)266 b(for)e(this)h +(parameter)h(may)9008 34182 y(be)381 b(the)g(culprit.)609 +b(One)381 b(cannot)g(o)-18 b(v)g(eremphasize)381 b(the)g(importance)g +(of)g(the)g(computed)9008 35687 y(table)303 b(in)g(BDD)h(algorithms.) +5978 38189 y(In)e(this)g(case)g(the)h(limit)f(w)-12 b(as)302 +b(automatically)h(set)f(for)g(a)g(tar)-22 b(get)303 b(maximum)f(memory) +h(occupa-)5978 39695 y(tion)g(of)f(104)i(MB.)p Black +Black 8887 42528 a Fh(Cache)728 b(hit)g(threshold)i(for)e(resizing:)i +(15\045)5978 45362 y Fo(This)314 b(number)i(can)g(be)f(changed)i(if)e +(one)h(suspects)e(performance)h(is)g(hindered)h(by)g(the)g(small)5978 +46868 y(size)373 b(of)g(the)h(cache,)392 b(and)373 b(the)h(cache)g(is)f +(not)h(gro)-30 b(wing)373 b(to)-30 b(w)-12 b(ards)372 +b(the)i(soft)f(limit)g(suf)-30 b(\002ciently)5978 48373 +y(f)-12 b(ast.)365 b(In)273 b(such)h(a)g(case)f(one)h(can)h(change)f +(the)g(def)-12 b(ault)274 b(30\045)f(to)h(15\045)f(\(as)g(in)h(this)f +(case\))h(or)f(e)-30 b(v)-18 b(en)5978 49879 y(1\045.)p +Black Black 8887 52712 a Fh(Garbage)729 b(collection)h(enabled:)f(yes) +5978 55546 y Fo(One)440 b(can)h(disable)f(it,)474 b(b)-24 +b(ut)440 b(there)g(are)g(fe)-30 b(w)440 b(good)g(reasons)g(for)f(doing) +h(so.)787 b(It)440 b(is)f(normally)5978 57052 y(preferable)302 +b(to)h(raise)g(the)g(limit)g(for)f(f)-12 b(ast)302 b(unique)i(table)f +(gro)-30 b(wth.)376 b(\(See)302 b(belo)-30 b(w)-79 b(.\))p +Black Black 8887 59886 a Fh(Limit)728 b(for)g(fast)h(unique)g(table)f +(growth:)h(1363148)5978 62719 y Fo(See)305 b(Section)h(4.5)f(and)g(the) +h(comments)f(abo)-18 b(v)g(e)305 b(about)h(reclaimed)f(nodes)g(and)h +(hard)f(limit)g(for)5978 64225 y(the)g(cache)h(size.)381 +b(This)305 b(v)-30 b(alue)305 b(w)-12 b(as)304 b(chosen)i +(automatically)f(by)g(CUDD)h(for)f(a)g(datasize)g(limit)5978 +65730 y(of)d(1)h(GB.)p Black 25297 69672 a(37)p Black +eop end +%%Page: 38 38 +TeXDict begin 38 37 bop Black Black Black Black 8887 +7638 a Fh(Maximum)729 b(number)g(of)f(variables)h(sifted)g(per)f +(reordering:)j(1000)8887 9143 y(Maximum)e(number)g(of)f(variable)h +(swaps)g(per)f(reordering:)i(2000000)8887 10649 y(Maximum)f(growth)g +(while)f(sifting)i(a)d(variable:)j(1.2)5978 13445 y Fo(Lo)-30 +b(wering)360 b(these)g(numbers)g(will)h(cause)g(reordering)f(to)h(be)g +(less)f(accurate)h(and)g(f)-12 b(aster)-67 b(.)548 b(Re-)5978 +14950 y(sults)262 b(are)i(some)-30 b(what)264 b(unpredictable,)272 +b(because)264 b(lar)-22 b(ger)264 b(BDDs)g(after)g(one)g(reordering)f +(do)h(not)5978 16456 y(necessarily)302 b(mean)h(the)h(process)e(will)h +(go)g(f)-12 b(aster)302 b(or)h(slo)-30 b(wer)-67 b(.)p +Black Black 8887 19252 a Fh(Dynamic)729 b(reordering)h(of)e(BDDs)g +(enabled:)h(yes)8887 20757 y(Default)g(BDD)f(reordering)i(method:)f(4) +8887 22263 y(Dynamic)g(reordering)h(of)e(ZDDs)g(enabled:)h(no)8887 +23768 y(Default)g(ZDD)f(reordering)i(method:)f(4)5978 +26564 y Fo(These)489 b(lines)h(tell)h(whether)f(automatic)h(reordering) +f(can)h(tak)-12 b(e)491 b(place)f(and)h(what)g(method)5978 +28069 y(w)-12 b(ould)352 b(be)h(used.)525 b(The)353 b(mapping)g(from)f +(numbers)g(to)h(methods)f(is)h(in)f Fh(cudd.h)p Fo(.)527 +b(One)353 b(may)5978 29575 y(w)-12 b(ant)366 b(to)g(try)g(dif)-30 +b(ferent)365 b(BDD)i(reordering)f(methods.)565 b(If)366 +b(v)-30 b(ariable)366 b(groups)f(are)i(used,)382 b(ho)-30 +b(w-)5978 31080 y(e)g(v)-18 b(er)-48 b(,)262 b(one)253 +b(should)f(not)h(e)-18 b(xpect)253 b(to)g(see)g(big)g(dif)-30 +b(ferences,)262 b(because)253 b(CUDD)g(uses)f(the)h(reported)5978 +32586 y(method)380 b(only)f(to)h(reorder)f(each)h(leaf)g(v)-30 +b(ariable)379 b(group)h(\(typically)f(corresponding)h(present)5978 +34091 y(and)394 b(ne)-18 b(xt)393 b(state)h(v)-30 b(ariables\).)647 +b(F)-18 b(or)393 b(the)h(relati)-30 b(v)-18 b(e)393 b(order)h(of)f(the) +h(groups,)416 b(it)393 b(al)-12 b(w)g(ays)394 b(uses)f(the)5978 +35597 y(same)302 b(algorithm,)h(which)h(is)e(ef)-30 b(fecti)g(v)-18 +b(ely)303 b(sifting.)7859 37102 y(As)369 b(for)e(enabling)i(dynamic)g +(reordering)f(or)g(not,)385 b(a)369 b(sensible)f(recommendation)h(is)f +(the)5978 38608 y(follo)-30 b(wing:)440 b(Unless)335 +b(the)h(circuit)f(is)g(rather)h(small)f(or)g(one)h(has)f(a)h(pretty)g +(good)g(idea)g(of)f(what)5978 40113 y(the)303 b(order)f(should)h(be,)g +(reordering)g(should)g(be)g(enabled.)p Black Black 8887 +42909 a Fh(Realignment)730 b(of)e(ZDDs)g(to)g(BDDs)g(enabled:)i(no)8887 +44414 y(Realignment)g(of)e(BDDs)g(to)g(ZDDs)g(enabled:)i(no)8887 +45920 y(Dead)e(nodes)h(counted)g(in)f(triggering)i(reordering:)g(no) +8887 47425 y(Group)e(checking)i(criterion:)g(7)8887 48931 +y(Recombination)g(threshold:)g(0)8887 50436 y(Symmetry)f(violation)h +(threshold:)g(0)8887 51942 y(Arc)e(violation)h(threshold:)h(0)8887 +53447 y(GA)d(population)j(size:)f(0)8887 54953 y(Number)g(of)e +(crossovers)j(for)e(GA:)h(0)5978 57749 y Fo(P)-18 b(arameters)323 +b(for)h(reordering.)438 b(See)325 b(the)f(documentation)h(of)f(the)g +(functions)g(used)g(to)g(control)5978 59254 y(these)302 +b(parameters)h(for)f(the)i(details.)p Black Black 8887 +62050 a Fh(Next)728 b(reordering)i(threshold:)g(100000)5978 +64846 y Fo(When)317 b(the)f(number)g(of)h(nodes)f(crosses)f(this)h +(threshold,)j(reordering)d(will)g(be)h(triggered.)415 +b(\(If)5978 66351 y(enabled;)300 b(in)e(this)g(case)g(it)g(is)f(not.\)) +374 b(This)297 b(parameter)h(is)g(updated)h(by)f(the)g(package)h(whene) +-30 b(v)-18 b(er)p Black 25297 69672 a(38)p Black eop +end +%%Page: 39 39 +TeXDict begin 39 38 bop Black Black 5978 7638 a Fo(reordering)312 +b(tak)-12 b(es)313 b(place.)407 b(The)313 b(application)h(can)g(change) +g(it,)i(for)c(instance)h(at)h(start-up.)405 b(An-)5978 +9143 y(other)288 b(possibility)g(is)h(to)g(use)f(a)h(hook)h(function)e +(\(see)h(Section)g(3.16\))g(to)g(o)-18 b(v)g(erride)288 +b(the)h(def)-12 b(ault)5978 10649 y(updating)303 b(polic)-18 +b(y)-79 b(.)5978 13927 y Fp(4.8.3)1212 b(Extended)303 +b(Statistics)e(and)i(Reporting)5978 16251 y Fo(The)350 +b(follo)-30 b(wing)351 b(symbols)e(can)j(be)f(de\002ned)g(during)f +(compilation)i(to)e(increase)h(the)g(amount)5978 17756 +y(of)302 b(statistics)g(g)-6 b(athered)303 b(and)h(the)f(number)g(of)g +(messages)f(produced)h(by)g(the)g(package:)p Black 7796 +20258 a Fm(\262)p Black 606 w Fo(DD)p 10831 20258 364 +45 v 437 w(ST)-113 b(A)-135 b(TS;)p Black 7796 22760 +a Fm(\262)p Black 606 w Fo(DD)p 10831 22760 V 437 w(CA)-48 +b(CHE)p 15327 22760 V 436 w(PR)g(OFILE;)p Black 7796 +25261 a Fm(\262)p Black 606 w Fo(DD)p 10831 25261 V 437 +w(UNIQ)-12 b(UE)p 15901 25261 V 436 w(PR)-48 b(OFILE.)p +Black 7796 27763 a Fm(\262)p Black 606 w Fo(DD)p 10831 +27763 V 437 w(VERBOSE;)5978 30265 y(De\002ning)345 b(DD)p +12388 30265 V 437 w(CA)-48 b(CHE)p 16884 30265 V 437 +w(PR)g(OFILE)344 b(causes)g(each)i(entry)f(of)g(the)h(cache)g(to)f +(include)h(an)f(ac-)5978 31770 y(cess)357 b(counter)-48 +b(,)372 b(which)359 b(is)f(used)g(to)g(compute)h(simple)f(statistics)f +(on)i(the)g(distrib)-24 b(ution)357 b(of)h(the)5978 33276 +y(k)-12 b(e)-18 b(ys.)5978 36598 y Fi(4.9)1328 b(Guidelines)332 +b(f)-33 b(or)332 b(Documentation)5978 38922 y Fo(The)465 +b(documentation)h(of)g(the)f(CUDD)i(functions)e(is)g(e)-18 +b(xtracted)466 b(automatically)g(from)f(the)5978 40427 +y(sources)265 b(by)h(Stephen)g(Edw)-12 b(ards')-67 b(s)265 +b(e)-18 b(xtdoc.)363 b(\(The)266 b(Ext)f(system)h(is)f(a)-24 +b(v)-30 b(ailable)266 b(via)g(anon)-18 b(ymous)5978 41933 +y(FTP)374 b(from)h Fh(ic.eecs.berkeley.edu)p Fo(.\))597 +b(The)375 b(follo)-30 b(wing)375 b(guidelines)g(are)g(follo)-30 +b(wed)5978 43438 y(in)358 b(CUDD)h(to)f(insure)f(consistent)h(and)g(ef) +-30 b(fecti)g(v)-18 b(e)357 b(use)h(of)g(automatic)g(e)-18 +b(xtraction.)541 b(It)358 b(is)g(rec-)5978 44944 y(ommended)303 +b(that)g(e)-18 b(xtensions)303 b(to)g(CUDD)h(follo)-30 +b(w)302 b(the)i(same)e(documentation)i(guidelines.)p +Black 7796 47446 a Fm(\262)p Black 606 w Fo(The)404 b(documentation)h +(of)f(an)h(e)-18 b(xported)404 b(procedure)h(should)f(be)g(suf)-30 +b(\002cient)404 b(to)g(allo)-30 b(w)9008 48951 y(one)301 +b(to)g(use)f(it)h(without)f(reading)h(the)g(code.)375 +b(It)301 b(is)f(not)h(necessary)f(to)g(e)-18 b(xplain)301 +b(ho)-30 b(w)301 b(the)9008 50456 y(procedure)i(w)-12 +b(orks;)302 b(only)h(what)h(it)f(does.)p Black 7796 52958 +a Fm(\262)p Black 606 w Fo(The)389 b Fn(SeeAlso)f Fo(\002elds)h(should) +f(be)h(space-separated)g(lists)f(of)g(function)h(names.)633 +b(The)9008 54464 y Fn(SeeAlso)299 b Fo(\002eld)h(of)f(an)h(e)-18 +b(xported)299 b(procedure)h(should)f(only)g(reference)h(other)f(e)-18 +b(xported)9008 55969 y(procedures.)483 b(The)339 b Fn(SeeAlso)f +Fo(\002eld)h(of)g(an)g(internal)g(procedure)f(may)i(reference)e(other) +9008 57475 y(internal)293 b(procedures)g(as)f(well)i(as)f(e)-18 +b(xported)293 b(procedures,)h(b)-24 b(ut)293 b(no)h(static)f +(procedures.)p Black 7796 59976 a Fm(\262)p Black 606 +w Fo(The)401 b(return)f(v)-30 b(alues)401 b(are)f(detailed)i(in)f(the)g +Fn(Description)f Fo(\002eld,)426 b(not)401 b(in)g(the)g +Fn(Synopsis)9008 61482 y Fo(\002eld.)p Black 7796 63984 +a Fm(\262)p Black 606 w Fo(The)366 b(parameters)f(are)h(documented)h +(alongside)f(their)f(declarations.)565 b(Further)365 +b(com-)9008 65489 y(ments)303 b(may)g(appear)g(in)g(the)g +Fn(Description)g Fo(\002eld.)p Black 25297 69672 a(39)p +Black eop end +%%Page: 40 40 +TeXDict begin 40 39 bop Black Black Black 7796 7638 a +Fm(\262)p Black 606 w Fo(If)376 b(the)h Fn(Description)f +Fo(\002eld)h(is)f(non-empty\227which)i(is)e(the)h(normal)g(case)f(for)g +(an)h(e)-18 b(x-)9008 9143 y(ported)230 b(procedure\227then)h(the)f +(synopsis)f(is)h(repeated\227possibly)g(slightly)g(changed\227)9008 +10649 y(at)331 b(the)h(be)-18 b(ginning)331 b(of)g(the)h +Fn(Description)e Fo(\002eld.)461 b(This)330 b(is)h(so)g(because)g(e)-18 +b(xtdoc)332 b(will)f(not)9008 12154 y(put)303 b(the)g(synopsis)f(in)h +(the)g(same)g(HTML)f(\002le)h(as)g(the)g(description.)p +Black 7796 14656 a Fm(\262)p Black 606 w Fo(The)g Fn(Synopsis)f +Fo(\002eld)h(should)g(be)g(about)h(one)f(line)g(long.)5978 +18558 y Fq(5)1594 b(The)398 b(C++)g(Interface)5978 21362 +y Fi(5.1)1328 b(Compiling)332 b(and)g(Linking)5978 23686 +y Fo(T)-97 b(o)302 b(b)-24 b(uild)303 b(an)g(application)h(that)f(uses) +g(the)g(CUDD)h(C++)e(interf)-12 b(ace,)303 b(you)h(should)e(add)p +Black Black 5978 26187 a Fh(#include)729 b("cuddObj.hh")5978 +28689 y Fo(to)398 b(your)h(source)f(\002les.)662 b(In)398 +b(addition)h(to)f(the)h(normal)f(CUDD)i(libraries)d(\(see)h(Section)h +(3.1\))5978 30195 y(you)267 b(should)g(link)h Fh(libobj.a)h +Fo(to)f(your)f(e)-18 b(x)g(ecutable.)365 b(Refer)267 +b(to)h(the)f Fh(Makefile)j Fo(in)d(the)h(top)5978 31700 +y(le)-30 b(v)-18 b(el)302 b(directory)h(of)g(the)g(distrib)-24 +b(ution)302 b(for)g(further)h(details.)5978 35023 y Fi(5.2)1328 +b(Basic)332 b(Manipulation)5978 37346 y Fo(The)289 b(follo)-30 +b(wing)289 b(fragment)g(of)g(code)h(illustrates)f(some)g(simple)g +(operations)g(on)h(BDDs)g(using)5978 38852 y(the)303 +b(C++)g(interf)-12 b(ace.)p Black Black 5978 41353 a +Fh(Cudd)728 b(mgr\(0,0\);)5978 42859 y(BDD)g(x)f(=)h(mgr.bddVar\(\);) +5978 44364 y(BDD)g(y)f(=)h(mgr.bddVar\(\);)5978 45870 +y(BDD)g(f)f(=)h(x)f(*)h(y;)5978 47375 y(BDD)g(g)f(=)h(y)f(+)h(!x;)5978 +48881 y(cout)g(<<)g("f)g(is")g(<<)f(\(f)h(<=)g(g)g(?)f("")h(:)g(")f +(not"\))9614 50386 y(<<)h(")f(less)i(than)f(or)g(equal)g(to)g(g\\n";) +5978 52888 y Fo(This)284 b(code)i(creates)f(a)h(manager)f(called)h +Fh(mgr)g Fo(and)g(tw)-12 b(o)285 b(v)-30 b(ariables)285 +b(in)g(it.)370 b(It)285 b(then)h(de\002nes)f(tw)-12 b(o)5978 +54393 y(functions)362 b Fh(f)h Fo(and)g Fh(g)g Fo(in)f(terms)g(of)h +(the)g(v)-30 b(ariables.)554 b(Finally)-79 b(,)378 b(it)362 +b(prints)g(a)h(message)f(based)h(on)5978 55899 y(the)387 +b(comparison)g(of)g(the)h(tw)-12 b(o)387 b(functions.)629 +b(No)388 b(e)-18 b(xplicit)387 b(referencing)g(or)g(dereferencing)h(is) +5978 57404 y(required.)418 b(The)317 b(operators)g(are)g(o)-18 +b(v)g(erloaded)318 b(in)f(the)h(intuiti)-30 b(v)-18 b(e)317 +b(w)-12 b(ay)-79 b(.)419 b(BDDs)317 b(are)h(freed)f(when)5978 +58910 y(e)-18 b(x)g(ecution)248 b(lea)-24 b(v)-18 b(es)247 +b(the)h(scope)g(in)g(which)g(the)-18 b(y)248 b(are)g(de\002ned)g(or)g +(when)g(the)g(v)-30 b(ariables)247 b(referring)5978 60415 +y(to)303 b(them)g(are)g(o)-18 b(v)g(erwritten.)p Black +25297 69672 a(40)p Black eop end +%%Page: 41 41 +TeXDict begin 41 40 bop Black Black 5978 7638 a Fq(6)1594 +b(Ackno)-16 b(wledgments)5978 10398 y Fo(The)348 b(contrib)-24 +b(utors:)464 b(Iris)347 b(Bahar)-48 b(,)360 b(Hyunw)-12 +b(oo)349 b(Cho,)360 b(Erica)347 b(Frohm,)360 b(Charlie)348 +b(Gaona,)360 b(Cheng)5978 11904 y(Hua,)413 b(Jae-Y)-133 +b(oung)391 b(Jang,)414 b(Seh-W)-97 b(oong)391 b(Jeong,)414 +b(Balakrishna)391 b(K)-18 b(umthekar)-48 b(,)413 b(Enrico)391 +b(Macii,)5978 13409 y(Bobbie)231 b(Manne,)245 b(In-Ho)229 +b(Moon,)245 b(Curt)230 b(Musfeldt,)244 b(Shipra)230 b(P)-18 +b(anda,)245 b(Abelardo)231 b(P)-18 b(ardo,)245 b(Bernard)5978 +14914 y(Plessier)-48 b(,)346 b(Ka)-24 b(vita)339 b(Ra)-24 +b(vi,)349 b(Hyongk)-18 b(yoon)340 b(Shin,)348 b(Alan)339 +b(Shuler)-48 b(,)348 b(Arun)339 b(Si)-30 b(v)g(akumaran,)347 +b(Jor)-22 b(gen)5978 16420 y(Si)-30 b(v)-18 b(esind.)5978 +17925 y(The)419 b(early)g(adopters:)607 b(Gianpiero)420 +b(Cabodi,)449 b(Jordi)418 b(Cortadella,)449 b(Mario)419 +b(Escobar)-48 b(,)447 b(Gayani)5978 19431 y(Gamage,)364 +b(Gary)352 b(Hachtel,)365 b(Mariano)352 b(Hermida,)364 +b(W)-97 b(ooh)-6 b(yuk)352 b(Lee,)364 b(Enric)352 b(P)-18 +b(astor)-48 b(,)362 b(Massimo)5978 20936 y(Poncino,)303 +b(Ellen)g(Sento)-18 b(vich,)303 b(the)g(students)g(of)f(ECEN5139.)7859 +22442 y(I)278 b(am)f(also)h(particularly)f(indebted)h(to)g(the)g(follo) +-30 b(wing)277 b(people)h(for)f(in-depth)h(discussions)5978 +23947 y(on)321 b(BDDs:)413 b(Armin)322 b(Biere,)k(Oli)-30 +b(vier)322 b(Coudert,)k(Geert)c(Janssen,)j(Don)d(Knuth,)327 +b(Da)-24 b(vid)321 b(Long,)5978 25453 y(Jean)394 b(Christophe)g(Madre,) +416 b(K)-30 b(en)395 b(McMillan,)416 b(Shin-Ichi)394 +b(Minato,)417 b(Jaehong)394 b(P)-18 b(ark,)416 b(Rajee)-30 +b(v)5978 26958 y(Ranjan,)279 b(Rick)273 b(Rudell,)279 +b(Ellen)272 b(Sento)-18 b(vich,)279 b(T)-97 b(om)272 +b(Shiple,)279 b(Christian)272 b(Stangier)-48 b(,)278 +b(and)272 b(Bw)-12 b(olen)5978 28464 y(Y)-121 b(ang.)7859 +29969 y(Special)352 b(thanks)g(to)f(Norris)g(Ip)g(for)f(guiding)i(my)g +(f)-12 b(altering)351 b(steps)f(in)i(the)f(design)h(of)f(the)5978 +31475 y(C++)367 b(interf)-12 b(ace.)571 b(Gianpiero)368 +b(Cabodi)g(and)h(Stef)-12 b(ano)367 b(Quer)h(ha)-24 b(v)-18 +b(e)368 b(graciously)g(agreed)g(to)g(let)5978 32980 y(me)303 +b(distrib)-24 b(ute)302 b(their)h(dddmp)g(library)g(with)g(CUDD.)7859 +34485 y(Masahiro)321 b(Fujita,)326 b(Gary)c(Hachtel,)327 +b(and)322 b(Carl)g(Pixle)-18 b(y)321 b(ha)-24 b(v)-18 +b(e)322 b(pro)-18 b(vided)321 b(encouragement)5978 35991 +y(and)303 b(advice.)7859 37496 y(The)406 b(National)g(Science)h(F)-18 +b(oundation)406 b(and)g(the)g(Semiconductor)g(Research)g(Corpora-)5978 +39002 y(tion)303 b(ha)-24 b(v)-18 b(e)303 b(supported)f(in)h(part)g +(the)g(de)-30 b(v)-18 b(elopment)304 b(of)e(this)h(package.)5978 +42852 y Fq(Refer)-29 b(ences)p Black 6584 45612 a Fo([1])p +Black 605 w(R.)371 b(I.)g(Bahar)-48 b(,)388 b(E.)370 +b(A.)h(Frohm,)388 b(C.)371 b(M.)f(Gaona,)389 b(G.)371 +b(D.)g(Hachtel,)388 b(E.)371 b(Macii,)387 b(A.)371 b(P)-18 +b(ardo,)8603 47117 y(and)316 b(F)-97 b(.)315 b(Somenzi.)477 +b(Algebraic)316 b(decision)f(diagrams)g(and)h(their)f(applications.)477 +b(In)315 b Fn(Pr)-55 b(o-)8603 48623 y(ceedings)355 b(of)h(the)f +(International)g(Confer)-45 b(ence)356 b(on)f(Computer)-24 +b(-Aided)355 b(Design)p Fo(,)368 b(pages)8603 50128 y(188\226191,)304 +b(Santa)f(Clara,)g(CA,)h(No)-18 b(v)g(ember)303 b(1993.)p +Black 6584 52525 a([2])p Black 605 w(B.)484 b(Bollig,)530 +b(M.)483 b(L)16768 52519 y(\250)16667 52525 y(obbing,)529 +b(and)484 b(I.)g(W)-97 b(e)-18 b(gener)-67 b(.)1015 b(Simulated)484 +b(annealing)h(to)f(impro)-18 b(v)g(e)8603 54030 y(v)-30 +b(ariable)380 b(orderings)f(for)h(OBDDs.)683 b(Presented)380 +b(at)g(the)g(International)g(W)-97 b(orkshop)380 b(on)8603 +55536 y(Logic)303 b(Synthesis,)f(Granlibakk)-12 b(en,)304 +b(CA,)f(May)g(1995.)p Black 6584 57933 a([3])p Black +605 w(K.)390 b(S.)g(Brace,)413 b(R.)391 b(L.)e(Rudell,)413 +b(and)390 b(R.)h(E.)f(Bryant.)715 b(Ef)-30 b(\002cient)389 +b(implementation)i(of)f(a)8603 59438 y(BDD)395 b(package.)731 +b(In)394 b Fn(Pr)-55 b(oceedings)394 b(of)h(the)g(27th)f(Design)h(A)-24 +b(utomation)394 b(Confer)-45 b(ence)p Fo(,)8603 60944 +y(pages)303 b(40\22645,)g(Orlando,)h(FL,)e(June)h(1990.)p +Black 6584 63340 a([4])p Black 605 w(R.)330 b(K.)g(Brayton)f(et)h(al.) +521 b(VIS:)329 b(A)h(system)e(for)h(v)-18 b(eri\002cation)329 +b(and)h(synthesis.)520 b(T)-85 b(echnical)8603 64846 +y(Report)386 b(UCB/ERL)h(M95/104,)407 b(Electronics)385 +b(Research)h(Lab,)407 b(Uni)-30 b(v)-79 b(.)386 b(of)g(California,)8603 +66351 y(December)304 b(1995.)p Black 25297 69672 a(41)p +Black eop end +%%Page: 42 42 +TeXDict begin 42 41 bop Black Black Black 6584 7638 a +Fo([5])p Black 605 w(R.)435 b(E.)f(Bryant.)856 b(Graph-based)434 +b(algorithms)g(for)f(Boolean)i(function)g(manipulation.)8603 +9143 y Fn(IEEE)301 b(T)-67 b(r)-18 b(ansactions)303 b(on)g(Computer)-12 +b(s)p Fo(,)303 b(C-35\(8\):677\226691,)g(August)f(1986.)p +Black 6584 11552 a([6])p Black 605 w(R.)435 b(Drechsler)-48 +b(,)466 b(B.)435 b(Beck)-12 b(er)-48 b(,)467 b(and)434 +b(N.)h(G)26043 11546 y(\250)25942 11552 y(ock)-12 b(el.)856 +b(A)435 b(genetic)g(algorithm)f(for)f(v)-30 b(ariable)8603 +13058 y(ordering)318 b(of)h(OBDDs.)487 b(Presented)318 +b(at)h(the)g(International)g(W)-97 b(orkshop)318 b(on)h(Logic)f(Syn-) +8603 14563 y(thesis,)302 b(Granlibakk)-12 b(en,)304 b(CA,)f(May)g +(1995.)p Black 6584 16972 a([7])p Black 605 w(S.)352 +b(J.)f(Friedman)g(and)h(K.)g(J.)f(Supo)-30 b(wit.)592 +b(Finding)352 b(the)f(optimal)h(v)-30 b(ariable)352 b(ordering)f(for) +8603 18477 y(binary)289 b(decision)f(diagrams.)405 b +Fn(IEEE)287 b(T)-67 b(r)-18 b(ansactions)287 b(on)i(Computer)-12 +b(s)p Fo(,)291 b(39\(5\):710\226713,)8603 19983 y(May)303 +b(1990.)p Black 6584 22392 a([8])p Black 605 w(M.)468 +b(Fujita,)509 b(Y)-156 b(.)468 b(Matsunag)-6 b(a,)510 +b(and)468 b(T)-90 b(.)468 b(Kakuda.)966 b(On)468 b(v)-30 +b(ariable)468 b(ordering)g(of)g(binary)8603 23897 y(decision)358 +b(diagrams)f(for)g(the)h(application)g(of)f(multi-le)-30 +b(v)-18 b(el)358 b(logic)f(synthesis.)611 b(In)357 b +Fn(Pr)-55 b(o-)8603 25403 y(ceedings)399 b(of)g(the)h(Eur)-55 +b(opean)399 b(Confer)-45 b(ence)400 b(on)f(Design)g(A)-24 +b(utomation)p Fo(,)423 b(pages)399 b(50\22654,)8603 26908 +y(Amsterdam,)303 b(February)g(1991.)p Black 6584 29317 +a([9])p Black 605 w(M.)346 b(Held)g(and)g(R.)g(M.)g(Karp.)574 +b(A)346 b(dynamic)g(programming)g(approach)g(to)g(sequencing)8603 +30822 y(problems.)436 b Fn(J)-30 b(.)303 b(SIAM)p Fo(,)f +(10\(1\):196\226210,)h(1962.)p Black 5978 33231 a([10])p +Black 605 w(N.)346 b(Ishiura,)355 b(H.)346 b(Sa)-18 b(w)-12 +b(ada,)356 b(and)346 b(S.)f(Y)-121 b(ajima.)573 b(Minimization)345 +b(of)g(binary)h(decision)f(dia-)8603 34736 y(grams)352 +b(based)g(on)h(e)-18 b(xchanges)352 b(of)h(v)-30 b(ariables.)593 +b(In)352 b Fn(Pr)-55 b(oceedings)353 b(of)f(the)h(International)8603 +36242 y(Confer)-45 b(ence)457 b(on)f(Computer)-24 b(-Aided)456 +b(Design)p Fo(,)494 b(pages)456 b(472\226475,)495 b(Santa)457 +b(Clara,)494 b(CA,)8603 37747 y(No)-18 b(v)g(ember)303 +b(1991.)p Black 5978 40156 a([11])p Black 605 w(S.-W)-112 +b(.)432 b(Jeong,)464 b(T)-90 b(.-S.)432 b(Kim,)464 b(and)432 +b(F)-97 b(.)432 b(Somenzi.)850 b(An)432 b(ef)-30 b(\002cient)431 +b(method)i(for)e(optimal)8603 41662 y(BDD)349 b(ordering)f +(computation.)582 b(In)348 b Fn(International)f(Confer)-45 +b(ence)350 b(on)e(VLSI)f(and)i(CAD)8603 43167 y(\(ICVC'93\))p +Fo(,)302 b(T)-97 b(aejon,)303 b(K)-42 b(orea,)303 b(No)-18 +b(v)g(ember)303 b(1993.)p Black 5978 45576 a([12])p Black +605 w(S.-I.)391 b(Minato.)718 b(Zero-suppressed)390 b(BDDs)h(for)g(set) +g(manipulation)h(in)f(combinatorial)8603 47081 y(problems.)440 +b(In)304 b Fn(Pr)-55 b(oceedings)304 b(of)g(the)h(Design)f(A)-24 +b(utomation)304 b(Confer)-45 b(ence)p Fo(,)306 b(pages)e(272\226)8603 +48587 y(277,)f(Dallas,)g(TX,)g(June)g(1993.)p Black 5978 +50995 a([13])p Black 605 w(S.)515 b(P)-18 b(anda)515 +b(and)g(F)-97 b(.)515 b(Somenzi.)1115 b(Who)516 b(are)f(the)g(v)-30 +b(ariables)514 b(in)h(your)g(neighborhood.)8603 52501 +y(In)355 b Fn(Pr)-55 b(oceedings)355 b(of)g(the)g(International)g +(Confer)-45 b(ence)356 b(on)f(Computer)-24 b(-Aided)355 +b(Design)p Fo(,)8603 54006 y(pages)303 b(74\22677,)g(San)h(Jose,)e(CA,) +i(No)-18 b(v)g(ember)303 b(1995.)p Black 5978 56415 a([14])p +Black 605 w(S.)558 b(P)-18 b(anda,)623 b(F)-97 b(.)558 +b(Somenzi,)623 b(and)559 b(B.)g(F)-97 b(.)558 b(Plessier)-67 +b(.)1253 b(Symmetry)559 b(detection)g(and)f(dy-)8603 +57921 y(namic)398 b(v)-30 b(ariable)397 b(ordering)f(of)h(decision)g +(diagrams.)737 b(In)397 b Fn(Pr)-55 b(oceedings)397 b(of)g(the)g(Inter) +-24 b(-)8603 59426 y(national)385 b(Confer)-45 b(ence)386 +b(on)g(Computer)-24 b(-Aided)385 b(Design)p Fo(,)405 +b(pages)385 b(628\226631,)407 b(San)385 b(Jose,)8603 +60932 y(CA,)304 b(No)-18 b(v)g(ember)303 b(1994.)p Black +5978 63340 a([15])p Black 605 w(B.)352 b(F)-97 b(.)351 +b(Plessier)-67 b(.)589 b Fn(A)351 b(Gener)-18 b(al)351 +b(F)-67 b(r)-18 b(ame)g(work)351 b(for)f(V)-135 b(eri\002cation)352 +b(of)f(Sequential)g(Cir)-45 b(cuits)p Fo(.)8603 64846 +y(PhD)322 b(thesis,)327 b(Uni)-30 b(v)-18 b(ersity)321 +b(of)h(Colorado)h(at)f(Boulder)-48 b(,)328 b(Dept.)322 +b(of)g(Electrical)g(and)h(Com-)8603 66351 y(puter)303 +b(Engineering,)g(1993.)p Black 25297 69672 a(42)p Black +eop end +%%Page: 43 43 +TeXDict begin 43 42 bop Black Black Black 5978 7638 a +Fo([16])p Black 605 w(R.)330 b(Rudell.)521 b(Dynamic)330 +b(v)-30 b(ariable)329 b(ordering)g(for)g(ordered)g(binary)g(decision)h +(diagrams.)8603 9143 y(In)355 b Fn(Pr)-55 b(oceedings)355 +b(of)g(the)g(International)g(Confer)-45 b(ence)356 b(on)f(Computer)-24 +b(-Aided)355 b(Design)p Fo(,)8603 10649 y(pages)303 b(42\22647,)g +(Santa)h(Clara,)f(CA,)h(No)-18 b(v)g(ember)303 b(1993.)p +Black 5978 13151 a([17])p Black 605 w(E.)576 b(M.)f(Sento)-18 +b(vich,)645 b(K.)576 b(J.)g(Singh,)644 b(C.)577 b(Moon,)644 +b(H.)576 b(Sa)-24 b(v)g(oj,)644 b(R.)577 b(K.)f(Brayton,)645 +b(and)8603 14656 y(A.)473 b(Sangio)-18 b(v)-30 b(anni-V)-73 +b(incentelli.)979 b(Sequential)473 b(circuit)f(design)g(using)h +(synthesis)e(and)8603 16162 y(optimization.)687 b(In)380 +b Fn(Pr)-55 b(oceedings)381 b(of)h(the)f(International)f(Confer)-45 +b(ence)382 b(on)g(Computer)8603 17667 y(Design)p Fo(,)303 +b(pages)g(328\226333,)g(Cambridge,)h(MA,)f(October)g(1992.)p +Black 25297 69672 a(43)p Black eop end +%%Page: 44 44 +TeXDict begin 44 43 bop Black Black Black 5978 9401 a +Fq(Index)p Black 5978 11896 a Fo(ADD,)303 b(4,)g(7,)g(11,)g(13)5978 +13401 y(aggre)-18 b(g)-6 b(ation,)303 b(18)5978 14907 +y(Algebraic)g(Decision)g(Diagram,)g Fn(see)g Fo(ADD)5978 +16412 y(arc)8192 17918 y(complement,)g(11,)g(24,)h(28)8192 +19423 y(re)-18 b(gular)-48 b(,)302 b(24,)h(28)5978 22036 +y(background)g(v)-30 b(alue,)303 b(10)5978 23541 y(BDD,)g(4,)h(7,)f +(10,)g(12)5978 25047 y(Binary)g(Decision)g(Diagram,)g +Fn(see)g Fo(BDD)5978 26552 y(box)8192 28058 y(black,)g(4)8192 +29563 y(clear)-48 b(,)302 b(4,)h(25)5978 32175 y(cache,)g(8,)h(28)8192 +33681 y(collision,)e(35)8192 35186 y(collision)g(list,)h(31)8192 +36692 y(deletion,)g(35)8192 38197 y(local,)g(29,)g(30)8192 +39703 y(lossless,)e(30)8192 41208 y(re)-30 b(w)-12 b(ard-based)302 +b(resizing,)g(29)8192 42714 y(sizing,)g(29)5978 44219 +y(cacheSize,)i(8)5978 45725 y(canonical,)f(7,)h(30)5978 +47230 y(compiling,)f(6,)g(10,)g(25)5978 48736 y(con\002guration,)g(5) +5978 50241 y(con)-48 b(v)-18 b(ersion)8192 51747 y(of)302 +b(ADDs)h(to)g(BDDs,)h(15)8192 53252 y(of)e(BDDs)i(to)f(ADDs,)g(15)8192 +54757 y(of)f(BDDs)i(to)f(ZDDs,)f(14,)h(15)8192 56263 +y(of)f(ZDDs)h(to)g(BDDs,)g(15)5978 57768 y(cube)g(sets,)f(4)5978 +59274 y(cudd.h,)h(6,)g(17,)g(28)5978 60779 y Fn(Cudd)p +8677 60779 364 45 v 437 w(addApply)p Fo(,)g(13,)g(14)5978 +62285 y Fn(Cudd)p 8677 62285 V 437 w(addBddInterval)p +Fo(,)f(15)5978 63790 y Fn(Cudd)p 8677 63790 V 437 w(addBddP)-97 +b(attern)p Fo(,)302 b(15)5978 65296 y Fn(Cudd)p 8677 +65296 V 437 w(addBddThr)-45 b(eshold)p Fo(,)302 b(15)p +Black Black 26456 11896 a Fn(Cudd)p 29155 11896 V 437 +w(addConst)p Fo(,)i(11)26456 13401 y Fn(Cudd)p 29155 +13401 V 437 w(addHarwell)p Fo(,)g(11)26456 14907 y Fn(Cudd)p +29155 14907 V 437 w(AddHook)p Fo(,)g(22)26456 16412 y +Fn(Cudd)p 29155 16412 V 437 w(addIthBit)p Fo(,)f(15)26456 +17918 y Fn(Cudd)p 29155 17918 V 437 w(addIthV)-135 b(ar)p +Fo(,)303 b(11)26456 19423 y Fn(Cudd)p 29155 19423 V 437 +w(addNe)-18 b(wV)-135 b(ar)p Fo(,)304 b(11)26456 20929 +y Fn(Cudd)p 29155 20929 V 437 w(addNe)-18 b(wV)-135 b(arAtLe)-18 +b(vel)p Fo(,)304 b(11,)f(20)26456 22434 y Fn(Cudd)p 29155 +22434 V 437 w(addRead)p Fo(,)g(11)26456 23940 y Fn(Cudd)p +29155 23940 V 437 w(addT)-67 b(imes)p Fo(,)304 b(14)26456 +25445 y Fn(Cudd)p 29155 25445 V 437 w(A)-24 b(utodynDisable)p +Fo(,)303 b(17)26456 26951 y Fn(Cudd)p 29155 26951 V 437 +w(A)-24 b(utodynDisableZdd)p Fo(,)303 b(20)26456 28456 +y Fn(Cudd)p 29155 28456 V 437 w(A)-24 b(utodynEnable)p +Fo(,)303 b(17)26456 29962 y Fn(Cudd)p 29155 29962 V 437 +w(A)-24 b(utodynEnableZdd)p Fo(,)303 b(20)26456 31467 +y Fn(Cudd)p 29155 31467 V 437 w(bddAnd)p Fo(,)g(12\22614)26456 +32972 y Fn(Cudd)p 29155 32972 V 437 w(bddConstr)-18 b(ain)p +Fo(,)303 b(7)26456 34478 y Fn(Cudd)p 29155 34478 V 437 +w(bddIte)p Fo(,)g(12)26456 35983 y Fn(Cudd)p 29155 35983 +V 437 w(bddIthV)-135 b(ar)p Fo(,)303 b(11)26456 37489 +y Fn(Cudd)p 29155 37489 V 437 w(bddNe)-18 b(wV)-135 b(ar)p +Fo(,)304 b(11)26456 38994 y Fn(Cudd)p 29155 38994 V 437 +w(bddNe)-18 b(wV)-135 b(arAtLe)-18 b(vel)p Fo(,)304 b(11,)f(20)26456 +40500 y Fn(Cudd)p 29155 40500 V 437 w(BddT)-112 b(oAdd)p +Fo(,)303 b(15)26456 42005 y Fn(Cudd)p 29155 42005 V 437 +w(bddXor)p Fo(,)g(14)26456 43511 y(CUDD)p 29962 43511 +V 438 w(CA)-48 b(CHE)p 34459 43511 V 436 w(SLO)g(TS,)302 +b(8)26456 45016 y Fn(Cudd)p 29155 45016 V 437 w(Chec)-24 +b(kK)-42 b(e)-36 b(ys)p Fo(,)304 b(33)26456 46522 y Fn(Cudd)p +29155 46522 V 437 w(Chec)-24 b(kZer)-55 b(oRef)p Fo(,)304 +b(33)26456 48027 y Fn(Cudd)p 29155 48027 V 437 w(CountMinterm)p +Fo(,)g(11)26456 49533 y Fn(Cudd)p 29155 49533 V 437 w(Deb)-24 +b(ugChec)g(k)p Fo(,)304 b(33)26456 51038 y Fn(Cudd)p +29155 51038 V 437 w(DelayedDer)-45 b(efBdd)p Fo(,)304 +b(36)26456 52544 y Fn(Cudd)p 29155 52544 V 437 w(Der)-45 +b(ef)p Fo(,)304 b(27)26456 54049 y Fn(Cudd)p 29155 54049 +V 437 w(DumpBlif)p Fo(,)f(23)26456 55554 y Fn(Cudd)p +29155 55554 V 437 w(DumpDaV)-90 b(inci)p Fo(,)304 b(23)26456 +57060 y Fn(Cudd)p 29155 57060 V 437 w(DumpDot)p Fo(,)g(23)26456 +58565 y Fn(Cudd)p 29155 58565 V 437 w(F)-127 b(or)-45 +b(eac)-18 b(hCube)p Fo(,)304 b(6,)f(11)26456 60071 y +Fn(Cudd)p 29155 60071 V 437 w(F)-127 b(or)-45 b(eac)-18 +b(hNode)p Fo(,)304 b(6)26456 61576 y Fn(Cudd)p 29155 +61576 V 437 w(HookT)-90 b(ype)p Fo(,)304 b(21)26456 63082 +y Fn(Cudd)p 29155 63082 V 437 w(Init)p Fo(,)f(8,)g(9)26456 +64587 y Fn(Cudd)p 29155 64587 V 437 w(Mak)-12 b(eT)-67 +b(r)-45 b(eeNode)p Fo(,)304 b(19,)g(20)26456 66093 y +Fn(Cudd)p 29155 66093 V 437 w(Mak)-12 b(eZddT)-67 b(r)-45 +b(eeNode)p Fo(,)304 b(21)p Black 25297 69672 a(44)p Black +eop end +%%Page: 45 45 +TeXDict begin 45 44 bop Black Black 5978 7638 a Fn(Cudd)p +8677 7638 364 45 v 437 w(Not)p Fo(,)303 b(10)5978 9143 +y Fn(Cudd)p 8677 9143 V 437 w(PrintInfo)p Fo(,)e(33)5978 +10649 y Fn(Cudd)p 8677 10649 V 437 w(PrintMinterm)p Fo(,)g(11)5978 +12154 y Fn(Cudd)p 8677 12154 V 437 w(Quit)p Fo(,)i(9)5978 +13660 y Fn(Cudd)p 8677 13660 V 437 w(ReadBac)-24 b(kgr)-55 +b(ound)p Fo(,)303 b(10)5978 15165 y Fn(Cudd)p 8677 15165 +V 437 w(ReadEpsilon)p Fo(,)f(10)5978 16671 y Fn(Cudd)p +8677 16671 V 437 w(ReadErr)-55 b(orCode)p Fo(,)302 b(26)5978 +18176 y Fn(Cudd)p 8677 18176 V 437 w(ReadIn)-48 b(vP)-97 +b(erm)p Fo(,)301 b(13)5978 19682 y Fn(Cudd)p 8677 19682 +V 437 w(ReadLo)-12 b(gicZer)-55 b(o)p Fo(,)303 b(10)5978 +21187 y Fn(Cudd)p 8677 21187 V 437 w(ReadLooseUpto)p +Fo(,)g(9)5978 22693 y Fn(Cudd)p 8677 22693 V 437 w(ReadMaxGr)-55 +b(owth)p Fo(,)303 b(18)5978 24198 y Fn(Cudd)p 8677 24198 +V 437 w(ReadMinusIn\002nity)p Fo(,)f(10)5978 25704 y +Fn(Cudd)p 8677 25704 V 437 w(ReadOne)p Fo(,)h(9)5978 +27209 y Fn(Cudd)p 8677 27209 V 437 w(ReadPlusIn\002nity)p +Fo(,)f(10)5978 28715 y Fn(Cudd)p 8677 28715 V 437 w(ReadReor)-45 +b(derings)p Fo(,)301 b(32)5978 30220 y Fn(Cudd)p 8677 +30220 V 437 w(ReadSiftMaxV)-135 b(ar)p Fo(,)302 b(18)5978 +31725 y Fn(Cudd)p 8677 31725 V 437 w(ReadT)-67 b(r)-45 +b(ee)p Fo(,)303 b(19)5978 33231 y Fn(Cudd)p 8677 33231 +V 437 w(ReadZddOne)p Fo(,)g(9,)g(15)5978 34736 y Fn(Cudd)p +8677 34736 V 437 w(ReadZer)-55 b(o)p Fo(,)303 b(10)5978 +36242 y Fn(Cudd)p 8677 36242 V 437 w(Recur)-12 b(siveDer)-45 +b(ef)p Fo(,)302 b(7,)h(25\22627,)g(30,)h(33)5978 37747 +y Fn(Cudd)p 8677 37747 V 437 w(Recur)-12 b(siveDer)-45 +b(efZdd)p Fo(,)302 b(7,)h(26,)g(27)5978 39253 y Fn(Cudd)p +8677 39253 V 437 w(ReduceHeap)p Fo(,)g(17)5978 40758 +y Fn(Cudd)p 8677 40758 V 437 w(Ref)p Fo(,)f(7,)i(12,)f(25,)g(27)5978 +42264 y Fn(Cudd)p 8677 42264 V 437 w(Re)-48 b(gular)p +Fo(,)302 b(28)5978 43769 y(CUDD)p 9484 43769 V 437 w(REORDER)p +15577 43769 V 437 w(ANNEALING,)h(19)5978 45275 y(CUDD)p +9484 45275 V 437 w(REORDER)p 15577 45275 V 437 w(EXA)-48 +b(CT)-90 b(,)303 b(19)5978 46780 y(CUDD)p 9484 46780 +V 437 w(REORDER)p 15577 46780 V 437 w(GENETIC,)f(19)5978 +48286 y(CUDD)p 9484 48286 V 437 w(REORDER)p 15577 48286 +V 437 w(GR)-48 b(OUP)p 20073 48286 V 437 w(SIFT)-90 b(,)302 +b(18)5978 49791 y(CUDD)p 9484 49791 V 437 w(REORDER)p +15577 49791 V 437 w(GR)-48 b(OUP)p 20073 49791 V 437 +w(SIFT)p 23003 49791 V 435 w(CONV)-156 b(,)10405 51297 +y(18)5978 52802 y(CUDD)p 9484 52802 V 437 w(REORDER)p +15577 52802 V 437 w(NONE,)303 b(17,)g(20)5978 54307 y(CUDD)p +9484 54307 V 437 w(REORDER)p 15577 54307 V 437 w(RANDOM,)h(17,)f(20) +5978 55813 y(CUDD)p 9484 55813 V 437 w(REORDER)p 15577 +55813 V 437 w(RANDOM)p 21400 55813 V 437 w(PIV)-48 b(O)g(T)-90 +b(,)10405 57318 y(17,)304 b(20)5978 58824 y(CUDD)p 9484 +58824 V 437 w(REORDER)p 15577 58824 V 437 w(SAME,)e(17,)i(20)5978 +60329 y(CUDD)p 9484 60329 V 437 w(REORDER)p 15577 60329 +V 437 w(SIFT)-90 b(,)303 b(17,)g(21)5978 61835 y(CUDD)p +9484 61835 V 437 w(REORDER)p 15577 61835 V 437 w(SIFT)p +18507 61835 V 436 w(CONVERGE,)10405 63340 y(18,)h(21)5978 +64846 y(CUDD)p 9484 64846 V 437 w(REORDER)p 15577 64846 +V 437 w(SYMM)p 19719 64846 V 436 w(SIFT)-90 b(,)229 b(18,)245 +b(21)p Black Black 26456 7638 a(CUDD)p 29962 7638 V 438 +w(REORDER)p 36056 7638 V 437 w(SYMM)p 40198 7638 V 435 +w(SIFT)p 43126 7638 V 436 w(CONV)-156 b(,)30884 9143 +y(18,)303 b(21)26456 10649 y(CUDD)p 29962 10649 V 438 +w(REORDER)p 36056 10649 V 437 w(WINDO)-42 b(W2,)303 b(18)26456 +12154 y(CUDD)p 29962 12154 V 438 w(REORDER)p 36056 12154 +V 437 w(WINDO)-42 b(W2)p 42374 12154 V 436 w(CONV)-156 +b(,)30884 13660 y(18)26456 15165 y(CUDD)p 29962 15165 +V 438 w(REORDER)p 36056 15165 V 437 w(WINDO)-42 b(W3,)303 +b(18)26456 16671 y(CUDD)p 29962 16671 V 438 w(REORDER)p +36056 16671 V 437 w(WINDO)-42 b(W3)p 42374 16671 V 436 +w(CONV)-156 b(,)30884 18176 y(18)26456 19682 y(CUDD)p +29962 19682 V 438 w(REORDER)p 36056 19682 V 437 w(WINDO)-42 +b(W4,)303 b(18)26456 21187 y(CUDD)p 29962 21187 V 438 +w(REORDER)p 36056 21187 V 437 w(WINDO)-42 b(W4)p 42374 +21187 V 436 w(CONV)-156 b(,)30884 22693 y(19)26456 24198 +y Fn(Cudd)p 29155 24198 V 437 w(SetEpsilon)p Fo(,)303 +b(10)26456 25704 y Fn(Cudd)p 29155 25704 V 437 w(SetLooseUpT)-112 +b(o)p Fo(,)304 b(9)26456 27209 y Fn(Cudd)p 29155 27209 +V 437 w(SetMaxCac)-18 b(heHar)-45 b(d)p Fo(,)304 b(37)26456 +28715 y Fn(Cudd)p 29155 28715 V 437 w(SetMaxGr)-55 b(owth)p +Fo(,)304 b(18)26456 30220 y Fn(Cudd)p 29155 30220 V 437 +w(SetSiftMaxV)-135 b(ar)p Fo(,)303 b(18)26456 31725 y +Fn(Cudd)p 29155 31725 V 437 w(SetT)-67 b(r)-45 b(ee)p +Fo(,)304 b(19)26456 33231 y Fn(Cudd)p 29155 33231 V 437 +w(Shuf)-22 b(\003eHeap)p Fo(,)304 b(19)26456 34736 y +Fn(Cudd)p 29155 34736 V 437 w(StdP)-97 b(ostReor)-45 +b(dHook)p Fo(,)303 b(22)26456 36242 y Fn(Cudd)p 29155 +36242 V 437 w(StdPr)-45 b(eReor)g(dHook)p Fo(,)303 b(22)26456 +37747 y Fn(Cudd)p 29155 37747 V 437 w(SymmPr)-55 b(o\002le)p +Fo(,)304 b(18)26456 39253 y(CUDD)p 29962 39253 V 438 +w(UNIQ)-12 b(UE)p 35033 39253 V 436 w(SLO)-48 b(TS,)301 +b(8)26456 40758 y Fn(Cudd)p 29155 40758 V 437 w(zddDumpDot)p +Fo(,)j(23)26456 42264 y Fn(Cudd)p 29155 42264 V 437 w(zddIsop)p +Fo(,)e(15)26456 43769 y Fn(Cudd)p 29155 43769 V 437 w(zddIthV)-135 +b(ar)p Fo(,)302 b(12)26456 45275 y Fn(Cudd)p 29155 45275 +V 437 w(zddP)-97 b(ortF)-67 b(r)-55 b(omBdd)p Fo(,)302 +b(16)26456 46780 y Fn(Cudd)p 29155 46780 V 437 w(zddP)-97 +b(ortT)-112 b(oBdd)p Fo(,)302 b(16)26456 48286 y Fn(Cudd)p +29155 48286 V 437 w(zddRealignDisable)p Fo(,)h(21)26456 +49791 y Fn(Cudd)p 29155 49791 V 437 w(zddRealignEnable)p +Fo(,)g(21)26456 51297 y Fn(Cudd)p 29155 51297 V 437 w(zddReduceHeap)p +Fo(,)h(20)26456 52802 y Fn(Cudd)p 29155 52802 V 437 w(zddShuf)-22 +b(\003eHeap)p Fo(,)304 b(20)26456 54307 y Fn(Cudd)p 29155 +54307 V 437 w(zddV)-135 b(ar)-12 b(sF)-67 b(r)-55 b(omBddV)-135 +b(ar)-12 b(s)p Fo(,)301 b(16)26456 55813 y Fn(Cudd)p +29155 55813 V 437 w(zddW)-112 b(eakDiv)p Fo(,)304 b(15)26456 +57318 y Fn(cuddCac)-18 b(heInsert)p Fo(,)303 b(29)26456 +58824 y Fn(cuddCac)-18 b(heInsert1)p Fo(,)303 b(29)26456 +60329 y Fn(cuddCac)-18 b(heInsert2)p Fo(,)303 b(29)26456 +61835 y Fn(cuddCac)-18 b(heLookup)p Fo(,)305 b(29)26456 +63340 y Fn(cuddCac)-18 b(heLookup1)p Fo(,)305 b(29)26456 +64846 y Fn(cuddCac)-18 b(heLookup2)p Fo(,)305 b(29)26456 +66351 y(CUDDDIR,)g(22)p Black 25297 69672 a(45)p Black +eop end +%%Page: 46 46 +TeXDict begin 46 45 bop Black Black 5978 7638 a Fn(cuddHeapPr)-55 +b(o\002le)p Fo(,)303 b(33)5978 9143 y Fn(cuddI)p Fo(,)g(30)5978 +10649 y(cuddInt.h,)g(33)5978 12154 y Fn(cuddIZ)p Fo(,)g(30)5978 +13660 y Fn(cuddSatDec)p Fo(,)h(28)5978 15165 y Fn(cuddSatInc)p +Fo(,)f(28)5978 16671 y Fn(cuddUniqueConst)p Fo(,)h(25,)f(26)5978 +18176 y Fn(cuddUniqueInter)p Fo(,)g(25,)g(26,)g(28,)g(32)5978 +19682 y Fn(cuddUniqueInterZdd)p Fo(,)g(25,)g(26,)g(32)5978 +22191 y(DD)p 7801 22191 364 45 v 436 w(CA)-48 b(CHE)p +12296 22191 V 437 w(PR)g(OFILE,)302 b(39)5978 23696 y(DD)p +7801 23696 V 436 w(DEB)-12 b(UG,)304 b(33)5978 25202 +y(DD)p 7801 25202 V 436 w(ST)-113 b(A)-135 b(TS,)303 +b(39)5978 26707 y(DD)p 7801 26707 V 436 w(UNIQ)-12 b(UE)p +12870 26707 V 436 w(PR)-48 b(OFILE,)302 b(39)5978 28213 +y(DD)p 7801 28213 V 436 w(VERBOSE,)i(39)5978 29718 y(DdManager)-48 +b(,)302 b(7,)h(8)5978 31224 y(DdNode,)g(6,)g(29)5978 +32729 y(deb)-24 b(ugging,)303 b(33)5978 34235 y(DEC)g(Alpha,)g(23)5978 +35740 y(DEC)g(Alpha,)g(10)5978 37246 y(documentation,)g(39)8192 +38751 y Fn(Description)p Fo(,)f(39)8192 40256 y(HTML)f(\002les,)i(40) +8192 41762 y Fn(SeeAlso)p Fo(,)f(39)8192 43267 y Fn(Synopsis)p +Fo(,)g(39)5978 44773 y(dot,)h Fn(see)g Fo(graph,)g(dra)-18 +b(wing)5978 47282 y(Epsilon,)302 b(10)5978 48787 y(e)-18 +b(xtdoc,)303 b Fn(see)g Fo(documentation)5978 51297 y(\003oating)g +(point,)g(10)8192 52802 y(double)g(\(C)g(type\),)g(7)8192 +54307 y(IEEE)e(Standard)i(754,)g(10)5978 55813 y(free)f(list,)h(26)5978 +57318 y(FTP)-135 b(,)303 b(5,)g(23,)g(39)5978 58824 y(function)8192 +60329 y(characteristic,)f(4,)h(16)8192 61835 y(co)-18 +b(v)g(er)-48 b(,)302 b(15,)h(16)9298 63340 y(irredundant,)g(15)8192 +64846 y(minterms,)f(11,)h(32)8192 66351 y(ON-set,)f(4)p +Black Black 28670 7638 a(sum)h(of)g(products,)f(11)28670 +9143 y(switching,)h(4)26456 11756 y(g)-6 b(arbage)367 +b(collection,)382 b(7\2269,)h(25,)f(26,)g(28,)g(30,)30884 +13261 y(31)28670 14767 y(hooks,)303 b(21)26456 16272 +y(gcc,)h(10)26456 17778 y(generator)-48 b(,)303 b(6)26456 +19283 y(global)h(v)-30 b(ariables,)302 b(7)26456 20789 +y(graph)28670 22294 y(arc)h(capacity)-79 b(,)304 b(10)28670 +23800 y(arc)f(length,)h(10)28670 25305 y(dra)-18 b(wing,)303 +b(23)26456 26811 y(gro)-30 b(wth,)303 b(9)26456 28316 +y(gzip,)h(5)26456 30928 y(HA)-164 b(VE)p 29731 30928 +V 437 w(IEEE)p 32795 30928 V 435 w(754,)303 b(10)26456 +32434 y(header)h(\002les,)e(17,)h(28)26456 33939 y(hook,)h(21)26456 +36552 y(in\002nities,)f(10)26456 38057 y(installation,)g(5)26456 +39563 y(Intel)g(Pentium)g(4,)g(5)26456 41068 y(interf)-12 +b(ace)28670 42574 y(cache,)304 b(29)28670 44079 y(SIS,)f(22)28670 +45585 y(VIS,)g(22)26456 48197 y(libraries,)f(5)28670 +49703 y(cudd,)i(6)28670 51208 y(dddmp,)g(25)28670 52713 +y(mtr)-48 b(,)302 b(6,)i(19)28670 54219 y(obj,)f(40)28670 +55724 y(st,)g(6,)g(29)28670 57230 y(util,)g(6)26456 59842 +y(Mak)-12 b(e\002le,)303 b(6,)g(10,)h(40)26456 61348 +y(manager)-48 b(,)303 b(7,)g(9)26456 62853 y(matrix)28670 +64359 y(sparse,)f(10)26456 65864 y(maxCache,)j(29)p Black +25297 69672 a(46)p Black eop end +%%Page: 47 47 +TeXDict begin 47 46 bop Black Black 5978 7638 a Fo(maxMemory)-79 +b(,)303 b(8)5978 9143 y(MinusIn\002nity)-79 b(,)302 b(10)5978 +10649 y(MTR)p 8678 10649 364 45 v 436 w(DEF)-90 b(A)-67 +b(UL)-112 b(T)-90 b(,)303 b(20)5978 12154 y(MTR)p 8678 +12154 V 436 w(FIXED,)f(19)5978 14664 y(nanotra)-24 b(v)-79 +b(,)303 b(5)5978 16169 y(node,)g(6)8192 17674 y(constant,)g(6,)g +(9\22611,)g(25,)g(27)9298 19180 y(v)-30 b(alue,)304 b(7)8192 +20685 y(dead,)f(26,)g(28,)g(31)8192 22191 y(dereference,)g(14)8192 +23696 y(reclaimed,)g(31)8192 25202 y(rec)-18 b(ycling,)303 +b(7)8192 26707 y(reference,)f(14)8192 28213 y(reference)g(count,)i(26) +8192 29718 y(reference)233 b(count,)248 b(6,)g(7,)g(12,)f(13,)h +(25\22628,)10405 31224 y(30,)304 b(33)9298 32729 y(saturated,)f(33)8192 +34235 y(terminal,)f Fn(see)h Fo(node,)h(constant)8192 +35740 y(v)-30 b(ariable)302 b(inde)-18 b(x,)304 b(6)5978 +37246 y(numSlots,)e(8)5978 38751 y(numV)-135 b(ars,)303 +b(8)5978 40256 y(numV)-135 b(arsZ,)302 b(8)5978 42766 +y(PlusIn\002nity)-79 b(,)302 b(10)5978 44271 y(projection)h(functions,) +f(11,)h(12,)h(14,)f(15,)g(33)5978 46780 y(README)f(\002le,)h(5)5978 +48286 y(reordering,)f(4,)h(6,)g(29)8192 49791 y(abort)f(and)i(retry)-79 +b(,)302 b(32)8192 51297 y(asynchronous,)g(17,)h(32)8192 +52802 y(con)-48 b(v)-18 b(er)c(ging,)302 b(17,)i(18)8192 +54307 y(Cudd)p 10891 54307 V 437 w(ReorderingT)-97 b(ype,)303 +b(17)8192 55813 y(dynamic,)g(4,)g(16,)g(20)8192 57318 +y(e)-18 b(xact,)303 b(19)8192 58824 y(function)f(wrapper)-48 +b(,)303 b(32,)g(33)8192 60329 y(genetic,)g(19)8192 61835 +y(group,)f(17,)i(18)8192 63340 y(hooks,)e(21)8192 64846 +y(interruptible)g(procedure,)h(32)8192 66351 y(of)f(BDDs)i(and)f(ADDs,) +g(16)p Black Black 28670 7638 a(of)g(ZDDs,)f(15,)i(20)28670 +9143 y(random,)f(17)28670 10649 y(sifting,)f(17)28670 +12154 y(simulated)h(annealing,)h(19)28670 13660 y(symmetric,)f(18)28670 +15165 y(threshold,)g(17,)g(32)28670 16671 y(windo)-30 +b(w)-79 b(,)304 b(18)26456 19283 y(saturating)28670 20789 +y(decrements,)f(27)28670 22294 y(increments,)g(27)26456 +23800 y(SISDIR,)g(22)26456 25305 y(SIZEOF)p 30638 25305 +V 436 w(INT)-90 b(,)302 b(28)26456 26811 y(SIZEOF)p 30638 +26811 V 436 w(V)-48 b(OID)p 34055 26811 V 436 w(P)-135 +b(,)303 b(28)26456 28316 y(statistical)g(counters,)f(7,)h(29)26456 +29822 y(statistical)g(counters,)f(26)26456 31327 y(statistics,)g(33) +26456 32832 y(subtable,)h(8,)g(26)26456 34338 y(symmetry)-79 +b(,)303 b(18)26456 36950 y(table)28670 38456 y(computed,)h(8)28670 +39961 y(gro)-30 b(wth,)303 b(9)28670 41467 y(hash,)g(7,)g(30)28670 +42972 y(unique,)h(6\2269,)f(16,)g(26,)g(29,)g(30)29777 +44478 y(f)-12 b(ast)302 b(gro)-30 b(wth,)303 b(31)29777 +45983 y(re)-30 b(w)-12 b(ard-based)302 b(resizing,)h(31)29777 +47489 y(slo)-30 b(w)303 b(gro)-30 b(wth,)302 b(31)26456 +50101 y(v)-30 b(ariable)28670 51606 y(groups,)303 b(19)28670 +53112 y(order)-48 b(,)302 b(6,)i(11)28670 54617 y(permutation,)f(6,)h +(30)28670 56123 y(tree,)f(19,)g(20)26456 58735 y(ZDD,)g(4,)g(7,)h(12,)f +(14,)g(15)26456 60241 y(zero)28670 61746 y(arithmetic,)g(9,)g(11,)h(15) +28670 63252 y(logical,)g(9,)f(15)26456 64757 y(Zero-suppressed)228 +b(Binary)j(Decision)f(Diagram,)30884 66263 y Fn(see)303 +b Fo(ZDD)p Black 25297 69672 a(47)p Black eop end +%%Trailer + +userdict /end-hook known{end-hook}if +%%EOF diff --git a/distr/cudd/doc/cuddAllAbs.html b/distr/cudd/doc/cuddAllAbs.html new file mode 100644 index 0000000..17ef1be --- /dev/null +++ b/distr/cudd/doc/cuddAllAbs.html @@ -0,0 +1,2986 @@ + +cudd package abstract + + + + + +
        +
        AssessPathLength() +
        Chooses the maximum allowable path length of nodes under the + threshold. + +
        BAapplyBias() +
        Finds don't care nodes. + +
        BAmarkNodes() +
        Marks nodes for remapping. + +
        BuildConjuncts() +
        Builds the conjuncts recursively, bottom up. + +
        BuildSubsetBdd() +
        Builds the BDD with nodes labeled with path length less than or equal to maxpath + +
        BuildSubsetBdd() +
        Builds the subset BDD using the heavy branch method. + +
        CheckInTables() +
        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. + +
        CheckTablesCacheAndReturn() +
        Check the tables for the existence of pair and return one + combination, cache the result. + +
        ConjunctsFree() +
        Free factors structure + +
        CorrelCleanUp() +
        Frees memory associated with hash table. + +
        CorrelCompare() +
        Compares two hash table entries. + +
        CorrelHash() +
        Hashes a hash table entry. + +
        CountMinterms() +
        Count the number of minterms of each node ina a BDD and + store it in a hash table. + +
        CreateBotDist() +
        Get longest distance of node from constant. + +
        CreateBotDist() +
        Labels each node with the shortest distance from the constant. + +
        CreatePathTable() +
        The outer procedure to label each node with its shortest + distance from the root and constant + +
        CreateTopDist() +
        Labels each node with its shortest distance from the root + +
        Cudd_AddHook() +
        Adds a function to a hook. + +
        Cudd_ApaAdd() +
        Adds two arbitrary precision integers. + +
        Cudd_ApaCompareRatios() +
        Compares the ratios of two arbitrary precision integers to two + unsigned ints. + +
        Cudd_ApaCompare() +
        Compares two arbitrary precision integers. + +
        Cudd_ApaCopy() +
        Makes a copy of an arbitrary precision integer. + +
        Cudd_ApaCountMinterm() +
        Counts the number of minterms of a DD. + +
        Cudd_ApaIntDivision() +
        Divides an arbitrary precision integer by an integer. + +
        Cudd_ApaNumberOfDigits() +
        Finds the number of digits for an arbitrary precision + integer. + +
        Cudd_ApaPowerOfTwo() +
        Sets an arbitrary precision integer to a power of two. + +
        Cudd_ApaPrintDecimal() +
        Prints an arbitrary precision integer in decimal format. + +
        Cudd_ApaPrintDensity() +
        Prints the density of a BDD or ADD using + arbitrary precision arithmetic. + +
        Cudd_ApaPrintExponential() +
        Prints an arbitrary precision integer in exponential format. + +
        Cudd_ApaPrintHex() +
        Prints an arbitrary precision integer in hexadecimal format. + +
        Cudd_ApaPrintMintermExp() +
        Prints the number of minterms of a BDD or ADD in exponential + format using arbitrary precision arithmetic. + +
        Cudd_ApaPrintMinterm() +
        Prints the number of minterms of a BDD or ADD using + arbitrary precision arithmetic. + +
        Cudd_ApaSetToLiteral() +
        Sets an arbitrary precision integer to a one-digit literal. + +
        Cudd_ApaShiftRight() +
        Shifts right an arbitrary precision integer by one binary + place. + +
        Cudd_ApaShortDivision() +
        Divides an arbitrary precision integer by a digit. + +
        Cudd_ApaSubtract() +
        Subtracts two arbitrary precision integers. + +
        Cudd_AutodynDisableZdd() +
        Disables automatic dynamic reordering of ZDDs. + +
        Cudd_AutodynDisable() +
        Disables automatic dynamic reordering. + +
        Cudd_AutodynEnableZdd() +
        Enables automatic dynamic reordering of ZDDs. + +
        Cudd_AutodynEnable() +
        Enables automatic dynamic reordering of BDDs and ADDs. + +
        Cudd_AverageDistance() +
        Computes the average distance between adjacent nodes. + +
        Cudd_BddToAdd() +
        Converts a BDD to a 0-1 ADD. + +
        Cudd_BddToCubeArray() +
        Builds a positional array from the BDD of a cube. + +
        Cudd_BiasedOverApprox() +
        Extracts a dense superset from a BDD with the biased + underapproximation method. + +
        Cudd_BiasedUnderApprox() +
        Extracts a dense subset from a BDD with the biased + underapproximation method. + +
        Cudd_CProjection() +
        Computes the compatible projection of R w.r.t. cube Y. + +
        Cudd_CheckKeys() +
        Checks for several conditions that should not occur. + +
        Cudd_CheckZeroRef() +
        Checks the unique table for nodes with non-zero reference + counts. + +
        Cudd_ClassifySupport() +
        Classifies the variables in the support of two DDs. + +
        Cudd_ClearErrorCode() +
        Clear the error code of a manager. + +
        Cudd_CofMinterm() +
        Computes the fraction of minterms in the on-set of all the + positive cofactors of a BDD or ADD. + +
        Cudd_Cofactor() +
        Computes the cofactor of f with respect to g. + +
        Cudd_CountLeaves() +
        Counts the number of leaves in a DD. + +
        Cudd_CountMinterm() +
        Counts the number of minterms of a DD. + +
        Cudd_CountPathsToNonZero() +
        Counts the number of paths to a non-zero terminal of a DD. + +
        Cudd_CountPath() +
        Counts the number of paths of a DD. + +
        Cudd_CubeArrayToBdd() +
        Builds the BDD of a cube from a positional array. + +
        Cudd_DagSize() +
        Counts the number of nodes in a DD. + +
        Cudd_DeadAreCounted() +
        Tells whether dead nodes are counted towards triggering + reordering. + +
        Cudd_DebugCheck() +
        Checks for inconsistencies in the DD heap. + +
        Cudd_Decreasing() +
        Determines whether a BDD is negative unate in a + variable. + +
        Cudd_DelayedDerefBdd() +
        Decreases the reference count of BDD node n. + +
        Cudd_Density() +
        Computes the density of a BDD or ADD. + +
        Cudd_Deref() +
        Decreases the reference count of node. + +
        Cudd_DisableGarbageCollection() +
        Disables garbage collection. + +
        Cudd_DisableReorderingReporting() +
        Disables reporting of reordering stats. + +
        Cudd_Disequality() +
        Generates a BDD for the function x - y != c. + +
        Cudd_DumpBlifBody() +
        Writes a blif body representing the argument BDDs. + +
        Cudd_DumpBlif() +
        Writes a blif file representing the argument BDDs. + +
        Cudd_DumpDDcal() +
        Writes a DDcal file representing the argument BDDs. + +
        Cudd_DumpDaVinci() +
        Writes a daVinci file representing the argument BDDs. + +
        Cudd_DumpDot() +
        Writes a dot file representing the argument DDs. + +
        Cudd_DumpFactoredForm() +
        Writes factored forms representing the argument BDDs. + +
        Cudd_Dxygtdxz() +
        Generates a BDD for the function d(x,y) > d(x,z). + +
        Cudd_Dxygtdyz() +
        Generates a BDD for the function d(x,y) > d(y,z). + +
        Cudd_EnableGarbageCollection() +
        Enables garbage collection. + +
        Cudd_EnableReorderingReporting() +
        Enables reporting of reordering stats. + +
        Cudd_EpdCountMinterm() +
        Counts the number of minterms of a DD with extended precision. + +
        Cudd_EqualSupNorm() +
        Compares two ADDs for equality within tolerance. + +
        Cudd_EquivDC() +
        Tells whether F and G are identical wherever D is 0. + +
        Cudd_EstimateCofactorSimple() +
        Estimates the number of nodes in a cofactor of a DD. + +
        Cudd_EstimateCofactor() +
        Estimates the number of nodes in a cofactor of a DD. + +
        Cudd_Eval() +
        Returns the value of a DD for a given variable assignment. + +
        Cudd_ExpectedUsedSlots() +
        Computes the expected fraction of used slots in the unique + table. + +
        Cudd_FindEssential() +
        Finds the essential variables of a DD. + +
        Cudd_FindTwoLiteralClauses() +
        Finds the two literal clauses of a DD. + +
        Cudd_FirstCube() +
        Finds the first cube of a decision diagram. + +
        Cudd_FirstNode() +
        Finds the first node of a decision diagram. + +
        Cudd_FirstPrime() +
        Finds the first prime of a Boolean function. + +
        Cudd_FreeTree() +
        Frees the variable group tree of the manager. + +
        Cudd_FreeZddTree() +
        Frees the variable group tree of the manager. + +
        Cudd_GarbageCollectionEnabled() +
        Tells whether garbage collection is enabled. + +
        Cudd_GenFree() +
        Frees a CUDD generator. + +
        Cudd_Increasing() +
        Determines whether a BDD is positive unate in a + variable. + +
        Cudd_IndicesToCube() +
        Builds a cube of BDD variables from an array of indices. + +
        Cudd_Inequality() +
        Generates a BDD for the function x - y ≥ c. + +
        Cudd_Init() +
        Creates a new DD manager. + +
        Cudd_IsGenEmpty() +
        Queries the status of a generator. + +
        Cudd_IsInHook() +
        Checks whether a function is in a hook. + +
        Cudd_IsNonConstant() +
        Returns 1 if a DD node is not constant. + +
        Cudd_IterDerefBdd() +
        Decreases the reference count of BDD node n. + +
        Cudd_LargestCube() +
        Finds a largest cube in a DD. + +
        Cudd_MakeBddFromZddCover() +
        Converts a ZDD cover to a BDD graph. + +
        Cudd_MakeTreeNode() +
        Creates a new variable group. + +
        Cudd_MakeZddTreeNode() +
        Creates a new ZDD variable group. + +
        Cudd_MinHammingDist() +
        Returns the minimum Hamming distance between f and minterm. + +
        Cudd_NewApaNumber() +
        Allocates memory for an arbitrary precision integer. + +
        Cudd_NextCube() +
        Generates the next cube of a decision diagram onset. + +
        Cudd_NextNode() +
        Finds the next node of a decision diagram. + +
        Cudd_NextPrime() +
        Generates the next prime of a Boolean function. + +
        Cudd_NodeReadIndex() +
        Returns the index of the node. + +
        Cudd_OutOfMem() +
        Warns that a memory allocation failed. + +
        Cudd_OverApprox() +
        Extracts a dense superset from a BDD with Shiple's + underapproximation method. + +
        Cudd_Prime() +
        Returns the next prime >= p. + +
        Cudd_PrintDebug() +
        Prints to the standard output a DD and its statistics. + +
        Cudd_PrintInfo() +
        Prints out statistics and settings for a CUDD manager. + +
        Cudd_PrintLinear() +
        Prints the linear transform matrix. + +
        Cudd_PrintMinterm() +
        Prints a disjoint sum of products. + +
        Cudd_PrintTwoLiteralClauses() +
        Prints the two literal clauses of a DD. + +
        Cudd_PrintVersion() +
        Prints the package version number. + +
        Cudd_PrioritySelect() +
        Selects pairs from R using a priority function. + +
        Cudd_Quit() +
        Deletes resources associated with a DD manager. + +
        Cudd_Random() +
        Portable random number generator. + +
        Cudd_ReadArcviolation() +
        Returns the current value of the arcviolation parameter used + in group sifting. + +
        Cudd_ReadBackground() +
        Reads the background constant of the manager. + +
        Cudd_ReadCacheHits() +
        Returns the number of cache hits. + +
        Cudd_ReadCacheLookUps() +
        Returns the number of cache look-ups. + +
        Cudd_ReadCacheSlots() +
        Reads the number of slots in the cache. + +
        Cudd_ReadCacheUsedSlots() +
        Reads the fraction of used slots in the cache. + +
        Cudd_ReadDead() +
        Returns the number of dead nodes in the unique table. + +
        Cudd_ReadEpsilon() +
        Reads the epsilon parameter of the manager. + +
        Cudd_ReadErrorCode() +
        Returns the code of the last error. + +
        Cudd_ReadGarbageCollectionTime() +
        Returns the time spent in garbage collection. + +
        Cudd_ReadGarbageCollections() +
        Returns the number of times garbage collection has occurred. + +
        Cudd_ReadGroupcheck() +
        Reads the groupcheck parameter of the manager. + +
        Cudd_ReadInvPermZdd() +
        Returns the index of the ZDD variable currently in the i-th + position of the order. + +
        Cudd_ReadInvPerm() +
        Returns the index of the variable currently in the i-th + position of the order. + +
        Cudd_ReadIthClause() +
        Accesses the i-th clause of a DD. + +
        Cudd_ReadKeys() +
        Returns the number of nodes in the unique table. + +
        Cudd_ReadLinear() +
        Reads an entry of the linear transform matrix. + +
        Cudd_ReadLogicZero() +
        Returns the logic zero constant of the manager. + +
        Cudd_ReadLooseUpTo() +
        Reads the looseUpTo parameter of the manager. + +
        Cudd_ReadMaxCacheHard() +
        Reads the maxCacheHard parameter of the manager. + +
        Cudd_ReadMaxCache() +
        Returns the soft limit for the cache size. + +
        Cudd_ReadMaxGrowthAlternate() +
        Reads the maxGrowthAlt parameter of the manager. + +
        Cudd_ReadMaxGrowth() +
        Reads the maxGrowth parameter of the manager. + +
        Cudd_ReadMaxLive() +
        Reads the maximum allowed number of live nodes. + +
        Cudd_ReadMaxMemory() +
        Reads the maximum allowed memory. + +
        Cudd_ReadMemoryInUse() +
        Returns the memory in use by the manager measured in bytes. + +
        Cudd_ReadMinDead() +
        Reads the minDead parameter of the manager. + +
        Cudd_ReadMinHit() +
        Reads the hit rate that causes resizinig of the computed + table. + +
        Cudd_ReadMinusInfinity() +
        Reads the minus-infinity constant from the manager. + +
        Cudd_ReadNextReordering() +
        Returns the threshold for the next dynamic reordering. + +
        Cudd_ReadNodeCount() +
        Reports the number of nodes in BDDs and ADDs. + +
        Cudd_ReadNodesDropped() +
        Returns the number of nodes dropped. + +
        Cudd_ReadNodesFreed() +
        Returns the number of nodes freed. + +
        Cudd_ReadNumberXovers() +
        Reads the current number of crossovers used by the + genetic algorithm for reordering. + +
        Cudd_ReadOne() +
        Returns the one constant of the manager. + +
        Cudd_ReadPeakLiveNodeCount() +
        Reports the peak number of live nodes. + +
        Cudd_ReadPeakNodeCount() +
        Reports the peak number of nodes. + +
        Cudd_ReadPermZdd() +
        Returns the current position of the i-th ZDD variable in the + order. + +
        Cudd_ReadPerm() +
        Returns the current position of the i-th variable in the + order. + +
        Cudd_ReadPlusInfinity() +
        Reads the plus-infinity constant from the manager. + +
        Cudd_ReadPopulationSize() +
        Reads the current size of the population used by the + genetic algorithm for reordering. + +
        Cudd_ReadRecomb() +
        Returns the current value of the recombination parameter used + in group sifting. + +
        Cudd_ReadRecursiveCalls() +
        Returns the number of recursive calls. + +
        Cudd_ReadReorderingCycle() +
        Reads the reordCycle parameter of the manager. + +
        Cudd_ReadReorderingTime() +
        Returns the time spent in reordering. + +
        Cudd_ReadReorderings() +
        Returns the number of times reordering has occurred. + +
        Cudd_ReadSiftMaxSwap() +
        Reads the siftMaxSwap parameter of the manager. + +
        Cudd_ReadSiftMaxVar() +
        Reads the siftMaxVar parameter of the manager. + +
        Cudd_ReadSize() +
        Returns the number of BDD variables in existance. + +
        Cudd_ReadSlots() +
        Returns the total number of slots of the unique table. + +
        Cudd_ReadStderr() +
        Reads the stderr of a manager. + +
        Cudd_ReadStdout() +
        Reads the stdout of a manager. + +
        Cudd_ReadSwapSteps() +
        Reads the number of elementary reordering steps. + +
        Cudd_ReadSymmviolation() +
        Returns the current value of the symmviolation parameter used + in group sifting. + +
        Cudd_ReadTree() +
        Returns the variable group tree of the manager. + +
        Cudd_ReadUniqueLinks() +
        Returns the number of links followed in the unique table. + +
        Cudd_ReadUniqueLookUps() +
        Returns the number of look-ups in the unique table. + +
        Cudd_ReadUsedSlots() +
        Reads the fraction of used slots in the unique table. + +
        Cudd_ReadVars() +
        Returns the i-th element of the vars array. + +
        Cudd_ReadZddOne() +
        Returns the ZDD for the constant 1 function. + +
        Cudd_ReadZddSize() +
        Returns the number of ZDD variables in existance. + +
        Cudd_ReadZddTree() +
        Returns the variable group tree of the manager. + +
        Cudd_ReadZero() +
        Returns the zero constant of the manager. + +
        Cudd_RecursiveDerefZdd() +
        Decreases the reference count of ZDD node n. + +
        Cudd_RecursiveDeref() +
        Decreases the reference count of node n. + +
        Cudd_ReduceHeap() +
        Main dynamic reordering routine. + +
        Cudd_Ref() +
        Increases the reference count of a node, if it is not + saturated. + +
        Cudd_RemapOverApprox() +
        Extracts a dense superset from a BDD with the remapping + underapproximation method. + +
        Cudd_RemapUnderApprox() +
        Extracts a dense subset from a BDD with the remapping + underapproximation method. + +
        Cudd_RemoveHook() +
        Removes a function from a hook. + +
        Cudd_ReorderingReporting() +
        Returns 1 if reporting of reordering stats is enabled. + +
        Cudd_ReorderingStatusZdd() +
        Reports the status of automatic dynamic reordering of ZDDs. + +
        Cudd_ReorderingStatus() +
        Reports the status of automatic dynamic reordering of BDDs + and ADDs. + +
        Cudd_SetArcviolation() +
        Sets the value of the arcviolation parameter used + in group sifting. + +
        Cudd_SetBackground() +
        Sets the background constant of the manager. + +
        Cudd_SetEpsilon() +
        Sets the epsilon parameter of the manager to ep. + +
        Cudd_SetGroupcheck() +
        Sets the parameter groupcheck of the manager to gc. + +
        Cudd_SetLooseUpTo() +
        Sets the looseUpTo parameter of the manager. + +
        Cudd_SetMaxCacheHard() +
        Sets the maxCacheHard parameter of the manager. + +
        Cudd_SetMaxGrowthAlternate() +
        Sets the maxGrowthAlt parameter of the manager. + +
        Cudd_SetMaxGrowth() +
        Sets the maxGrowth parameter of the manager. + +
        Cudd_SetMaxLive() +
        Sets the maximum allowed number of live nodes. + +
        Cudd_SetMaxMemory() +
        Sets the maximum allowed memory. + +
        Cudd_SetMinHit() +
        Sets the hit rate that causes resizinig of the computed + table. + +
        Cudd_SetNextReordering() +
        Sets the threshold for the next dynamic reordering. + +
        Cudd_SetNumberXovers() +
        Sets the number of crossovers used by the + genetic algorithm for reordering. + +
        Cudd_SetPopulationSize() +
        Sets the size of the population used by the + genetic algorithm for reordering. + +
        Cudd_SetRecomb() +
        Sets the value of the recombination parameter used in group + sifting. + +
        Cudd_SetReorderingCycle() +
        Sets the reordCycle parameter of the manager. + +
        Cudd_SetSiftMaxSwap() +
        Sets the siftMaxSwap parameter of the manager. + +
        Cudd_SetSiftMaxVar() +
        Sets the siftMaxVar parameter of the manager. + +
        Cudd_SetStderr() +
        Sets the stderr of a manager. + +
        Cudd_SetStdout() +
        Sets the stdout of a manager. + +
        Cudd_SetSymmviolation() +
        Sets the value of the symmviolation parameter used + in group sifting. + +
        Cudd_SetTree() +
        Sets the variable group tree of the manager. + +
        Cudd_SetVarMap() +
        Registers a variable mapping with the manager. + +
        Cudd_SetZddTree() +
        Sets the ZDD variable group tree of the manager. + +
        Cudd_SharingSize() +
        Counts the number of nodes in an array of DDs. + +
        Cudd_ShortestLength() +
        Find the length of the shortest path(s) in a DD. + +
        Cudd_ShortestPath() +
        Finds a shortest path in a DD. + +
        Cudd_ShuffleHeap() +
        Reorders variables according to given permutation. + +
        Cudd_SolveEqn() +
        Implements the solution of F(x,y) = 0. + +
        Cudd_SplitSet() +
        Returns m minterms from a BDD. + +
        Cudd_Srandom() +
        Initializer for the portable random number generator. + +
        Cudd_StdPostReordHook() +
        Sample hook function to call after reordering. + +
        Cudd_StdPreReordHook() +
        Sample hook function to call before reordering. + +
        Cudd_SubsetCompress() +
        Find a dense subset of BDD f. + +
        Cudd_SubsetHeavyBranch() +
        Extracts a dense subset from a BDD with the heavy branch + heuristic. + +
        Cudd_SubsetShortPaths() +
        Extracts a dense subset from a BDD with the shortest paths + heuristic. + +
        Cudd_SubsetWithMaskVars() +
        Extracts a subset from a BDD. + +
        Cudd_SupersetCompress() +
        Find a dense superset of BDD f. + +
        Cudd_SupersetHeavyBranch() +
        Extracts a dense superset from a BDD with the heavy branch + heuristic. + +
        Cudd_SupersetShortPaths() +
        Extracts a dense superset from a BDD with the shortest paths + heuristic. + +
        Cudd_SupportIndex() +
        Finds the variables on which a DD depends. + +
        Cudd_SupportSize() +
        Counts the variables on which a DD depends. + +
        Cudd_Support() +
        Finds the variables on which a DD depends. + +
        Cudd_SymmProfile() +
        Prints statistics on symmetric variables. + +
        Cudd_TurnOffCountDead() +
        Causes the dead nodes not to be counted towards triggering + reordering. + +
        Cudd_TurnOnCountDead() +
        Causes the dead nodes to be counted towards triggering + reordering. + +
        Cudd_UnderApprox() +
        Extracts a dense subset from a BDD with Shiple's + underapproximation method. + +
        Cudd_VectorSupportIndex() +
        Finds the variables on which a set of DDs depends. + +
        Cudd_VectorSupportSize() +
        Counts the variables on which a set of DDs depends. + +
        Cudd_VectorSupport() +
        Finds the variables on which a set of DDs depends. + +
        Cudd_VerifySol() +
        Checks the solution of F(x,y) = 0. + +
        Cudd_Xeqy() +
        Generates a BDD for the function x==y. + +
        Cudd_Xgty() +
        Generates a BDD for the function x > y. + +
        Cudd_addAgreement() +
        f if f==g; background if f!=g. + +
        Cudd_addApply() +
        Applies op to the corresponding discriminants of f and g. + +
        Cudd_addBddInterval() +
        Converts an ADD to a BDD. + +
        Cudd_addBddIthBit() +
        Converts an ADD to a BDD by extracting the i-th bit from + the leaves. + +
        Cudd_addBddPattern() +
        Converts an ADD to a BDD. + +
        Cudd_addBddStrictThreshold() +
        Converts an ADD to a BDD. + +
        Cudd_addBddThreshold() +
        Converts an ADD to a BDD. + +
        Cudd_addCmpl() +
        Computes the complement of an ADD a la C language. + +
        Cudd_addCompose() +
        Substitutes g for x_v in the ADD for f. + +
        Cudd_addComputeCube() +
        Computes the cube of an array of ADD variables. + +
        Cudd_addConstrain() +
        Computes f constrain c for ADDs. + +
        Cudd_addConst() +
        Returns the ADD for constant c. + +
        Cudd_addDiff() +
        Returns plusinfinity if f=g; returns min(f,g) if f!=g. + +
        Cudd_addDivide() +
        Integer and floating point division. + +
        Cudd_addEvalConst() +
        Checks whether ADD g is constant whenever ADD f is 1. + +
        Cudd_addExistAbstract() +
        Existentially Abstracts all the variables in cube from f. + +
        Cudd_addFindMax() +
        Finds the maximum discriminant of f. + +
        Cudd_addFindMin() +
        Finds the minimum discriminant of f. + +
        Cudd_addGeneralVectorCompose() +
        Composes an ADD with a vector of ADDs. + +
        Cudd_addHamming() +
        Computes the Hamming distance ADD. + +
        Cudd_addHarwell() +
        Reads in a matrix in the format of the Harwell-Boeing + benchmark suite. + +
        Cudd_addIteConstant() +
        Implements ITEconstant for ADDs. + +
        Cudd_addIte() +
        Implements ITE(f,g,h). + +
        Cudd_addIthBit() +
        Extracts the i-th bit from an ADD. + +
        Cudd_addIthVar() +
        Returns the ADD variable with index i. + +
        Cudd_addLeq() +
        Determines whether f is less than or equal to g. + +
        Cudd_addLog() +
        Natural logarithm of an ADD. + +
        Cudd_addMatrixMultiply() +
        Calculates the product of two matrices represented as + ADDs. + +
        Cudd_addMaximum() +
        Integer and floating point max. + +
        Cudd_addMinimum() +
        Integer and floating point min. + +
        Cudd_addMinus() +
        Integer and floating point subtraction. + +
        Cudd_addMonadicApply() +
        Applies op to the discriminants of f. + +
        Cudd_addNand() +
        NAND of two 0-1 ADDs. + +
        Cudd_addNegate() +
        Computes the additive inverse of an ADD. + +
        Cudd_addNewVarAtLevel() +
        Returns a new ADD variable at a specified level. + +
        Cudd_addNewVar() +
        Returns a new ADD variable. + +
        Cudd_addNonSimCompose() +
        Composes an ADD with a vector of 0-1 ADDs. + +
        Cudd_addNor() +
        NOR of two 0-1 ADDs. + +
        Cudd_addOneZeroMaximum() +
        Returns 1 if f > g and 0 otherwise. + +
        Cudd_addOrAbstract() +
        Disjunctively abstracts all the variables in cube from the + 0-1 ADD f. + +
        Cudd_addOr() +
        Disjunction of two 0-1 ADDs. + +
        Cudd_addOuterSum() +
        Takes the minimum of a matrix and the outer sum of two vectors. + +
        Cudd_addPermute() +
        Permutes the variables of an ADD. + +
        Cudd_addPlus() +
        Integer and floating point addition. + +
        Cudd_addRead() +
        Reads in a sparse matrix. + +
        Cudd_addResidue() +
        Builds an ADD for the residue modulo m of an n-bit + number. + +
        Cudd_addRestrict() +
        ADD restrict according to Coudert and Madre's algorithm + (ICCAD90). + +
        Cudd_addRoundOff() +
        Rounds off the discriminants of an ADD. + +
        Cudd_addScalarInverse() +
        Computes the scalar inverse of an ADD. + +
        Cudd_addSetNZ() +
        This operator sets f to the value of g wherever g != 0. + +
        Cudd_addSwapVariables() +
        Swaps two sets of variables of the same size (x and y) in + the ADD f. + +
        Cudd_addThreshold() +
        f if f>=g; 0 if f<g. + +
        Cudd_addTimesPlus() +
        Calculates the product of two matrices represented as + ADDs. + +
        Cudd_addTimes() +
        Integer and floating point multiplication. + +
        Cudd_addTriangle() +
        Performs the triangulation step for the shortest path + computation. + +
        Cudd_addUnivAbstract() +
        Universally Abstracts all the variables in cube from f. + +
        Cudd_addVectorCompose() +
        Composes an ADD with a vector of 0-1 ADDs. + +
        Cudd_addWalsh() +
        Generates a Walsh matrix in ADD form. + +
        Cudd_addXeqy() +
        Generates an ADD for the function x==y. + +
        Cudd_addXnor() +
        XNOR of two 0-1 ADDs. + +
        Cudd_addXor() +
        XOR of two 0-1 ADDs. + +
        Cudd_bddAdjPermuteX() +
        Rearranges a set of variables in the BDD B. + +
        Cudd_bddAndAbstractLimit() +
        Takes the AND of two BDDs and simultaneously abstracts the + variables in cube. Returns NULL if too many nodes are required. + +
        Cudd_bddAndAbstract() +
        Takes the AND of two BDDs and simultaneously abstracts the + variables in cube. + +
        Cudd_bddAndLimit() +
        Computes the conjunction of two BDDs f and g. Returns + NULL if too many nodes are required. + +
        Cudd_bddAnd() +
        Computes the conjunction of two BDDs f and g. + +
        Cudd_bddApproxConjDecomp() +
        Performs two-way conjunctive decomposition of a BDD. + +
        Cudd_bddApproxDisjDecomp() +
        Performs two-way disjunctive decomposition of a BDD. + +
        Cudd_bddBindVar() +
        Prevents sifting of a variable. + +
        Cudd_bddBooleanDiff() +
        Computes the boolean difference of f with respect to x. + +
        Cudd_bddCharToVect() +
        Computes a vector whose image equals a non-zero function. + +
        Cudd_bddClippingAndAbstract() +
        Approximates the conjunction of two BDDs f and g and + simultaneously abstracts the variables in cube. + +
        Cudd_bddClippingAnd() +
        Approximates the conjunction of two BDDs f and g. + +
        Cudd_bddClosestCube() +
        Finds a cube of f at minimum Hamming distance from g. + +
        Cudd_bddCompose() +
        Substitutes g for x_v in the BDD for f. + +
        Cudd_bddComputeCube() +
        Computes the cube of an array of BDD variables. + +
        Cudd_bddConstrainDecomp() +
        BDD conjunctive decomposition as in McMillan's CAV96 paper. + +
        Cudd_bddConstrain() +
        Computes f constrain c. + +
        Cudd_bddCorrelationWeights() +
        Computes the correlation of f and g for given input + probabilities. + +
        Cudd_bddCorrelation() +
        Computes the correlation of f and g. + +
        Cudd_bddExistAbstract() +
        Existentially abstracts all the variables in cube from f. + +
        Cudd_bddGenConjDecomp() +
        Performs two-way conjunctive decomposition of a BDD. + +
        Cudd_bddGenDisjDecomp() +
        Performs two-way disjunctive decomposition of a BDD. + +
        Cudd_bddIntersect() +
        Returns a function included in the intersection of f and g. + +
        Cudd_bddInterval() +
        Generates a BDD for the function lowerB ≤ x ≤ upperB. + +
        Cudd_bddIsNsVar() +
        Checks whether a variable is next state. + +
        Cudd_bddIsPiVar() +
        Checks whether a variable is primary input. + +
        Cudd_bddIsPsVar() +
        Checks whether a variable is present state. + +
        Cudd_bddIsVarEssential() +
        Determines whether a given variable is essential with a + given phase in a BDD. + +
        Cudd_bddIsVarHardGroup() +
        Checks whether a variable is set to be in a hard group. + +
        Cudd_bddIsVarToBeGrouped() +
        Checks whether a variable is set to be grouped. + +
        Cudd_bddIsVarToBeUngrouped() +
        Checks whether a variable is set to be ungrouped. + +
        Cudd_bddIsop() +
        Computes a BDD in the interval between L and U with a + simple sum-of-produuct cover. + +
        Cudd_bddIteConstant() +
        Implements ITEconstant(f,g,h). + +
        Cudd_bddIterConjDecomp() +
        Performs two-way conjunctive decomposition of a BDD. + +
        Cudd_bddIterDisjDecomp() +
        Performs two-way disjunctive decomposition of a BDD. + +
        Cudd_bddIte() +
        Implements ITE(f,g,h). + +
        Cudd_bddIthVar() +
        Returns the BDD variable with index i. + +
        Cudd_bddLICompaction() +
        Performs safe minimization of a BDD. + +
        Cudd_bddLeqUnless() +
        Tells whether f is less than of equal to G unless D is 1. + +
        Cudd_bddLeq() +
        Determines whether f is less than or equal to g. + +
        Cudd_bddLiteralSetIntersection() +
        Computes the intesection of two sets of literals + represented as BDDs. + +
        Cudd_bddMakePrime() +
        Expands cube to a prime implicant of f. + +
        Cudd_bddMinimize() +
        Finds a small BDD that agrees with f over + c. + +
        Cudd_bddNPAnd() +
        Computes f non-polluting-and g. + +
        Cudd_bddNand() +
        Computes the NAND of two BDDs f and g. + +
        Cudd_bddNewVarAtLevel() +
        Returns a new BDD variable at a specified level. + +
        Cudd_bddNewVar() +
        Returns a new BDD variable. + +
        Cudd_bddNor() +
        Computes the NOR of two BDDs f and g. + +
        Cudd_bddOr() +
        Computes the disjunction of two BDDs f and g. + +
        Cudd_bddPermute() +
        Permutes the variables of a BDD. + +
        Cudd_bddPickArbitraryMinterms() +
        Picks k on-set minterms evenly distributed from given DD. + +
        Cudd_bddPickOneCube() +
        Picks one on-set cube randomly from the given DD. + +
        Cudd_bddPickOneMinterm() +
        Picks one on-set minterm randomly from the given DD. + +
        Cudd_bddPrintCover() +
        Prints a sum of prime implicants of a BDD. + +
        Cudd_bddReadPairIndex() +
        Reads a corresponding pair index for a given index. + +
        Cudd_bddRead() +
        Reads in a graph (without labels) given as a list of arcs. + +
        Cudd_bddRealignDisable() +
        Disables realignment of ZDD order to BDD order. + +
        Cudd_bddRealignEnable() +
        Enables realignment of BDD order to ZDD order. + +
        Cudd_bddRealignmentEnabled() +
        Tells whether the realignment of BDD order to ZDD order is + enabled. + +
        Cudd_bddResetVarToBeGrouped() +
        Resets a variable not to be grouped. + +
        Cudd_bddRestrict() +
        BDD restrict according to Coudert and Madre's algorithm + (ICCAD90). + +
        Cudd_bddSetNsVar() +
        Sets a variable type to next state. + +
        Cudd_bddSetPairIndex() +
        Sets a corresponding pair index for a given index. + +
        Cudd_bddSetPiVar() +
        Sets a variable type to primary input. + +
        Cudd_bddSetPsVar() +
        Sets a variable type to present state. + +
        Cudd_bddSetVarHardGroup() +
        Sets a variable to be a hard group. + +
        Cudd_bddSetVarToBeGrouped() +
        Sets a variable to be grouped. + +
        Cudd_bddSetVarToBeUngrouped() +
        Sets a variable to be ungrouped. + +
        Cudd_bddSqueeze() +
        Finds a small BDD in a function interval. + +
        Cudd_bddSwapVariables() +
        Swaps two sets of variables of the same size (x and y) in + the BDD f. + +
        Cudd_bddTransfer() +
        Convert a BDD from a manager to another one. + +
        Cudd_bddUnbindVar() +
        Allows the sifting of a variable. + +
        Cudd_bddUnivAbstract() +
        Universally abstracts all the variables in cube from f. + +
        Cudd_bddVarConjDecomp() +
        Performs two-way conjunctive decomposition of a BDD. + +
        Cudd_bddVarDisjDecomp() +
        Performs two-way disjunctive decomposition of a BDD. + +
        Cudd_bddVarIsBound() +
        Tells whether a variable can be sifted. + +
        Cudd_bddVarIsDependent() +
        Checks whether a variable is dependent on others in a + function. + +
        Cudd_bddVarMap() +
        Remaps the variables of a BDD using the default variable map. + +
        Cudd_bddVectorCompose() +
        Composes a BDD with a vector of BDDs. + +
        Cudd_bddXnor() +
        Computes the exclusive NOR of two BDDs f and g. + +
        Cudd_bddXorExistAbstract() +
        Takes the exclusive OR of two BDDs and simultaneously abstracts the + variables in cube. + +
        Cudd_bddXor() +
        Computes the exclusive OR of two BDDs f and g. + +
        Cudd_tlcInfoFree() +
        Frees a DdTlcInfo Structure. + +
        Cudd_zddChange() +
        Substitutes a variable with its complement in a ZDD. + +
        Cudd_zddComplement() +
        Computes a complement cover for a ZDD node. + +
        Cudd_zddCountDouble() +
        Counts the number of minterms of a ZDD. + +
        Cudd_zddCountMinterm() +
        Counts the number of minterms of a ZDD. + +
        Cudd_zddCount() +
        Counts the number of minterms in a ZDD. + +
        Cudd_zddCoverPathToString() +
        Converts a path of a ZDD representing a cover to a string. + +
        Cudd_zddDagSize() +
        Counts the number of nodes in a ZDD. + +
        Cudd_zddDiffConst() +
        Performs the inclusion test for ZDDs (P implies Q). + +
        Cudd_zddDiff() +
        Computes the difference of two ZDDs. + +
        Cudd_zddDivideF() +
        Modified version of Cudd_zddDivide. + +
        Cudd_zddDivide() +
        Computes the quotient of two unate covers. + +
        Cudd_zddDumpDot() +
        Writes a dot file representing the argument ZDDs. + +
        Cudd_zddFirstPath() +
        Finds the first path of a ZDD. + +
        Cudd_zddIntersect() +
        Computes the intersection of two ZDDs. + +
        Cudd_zddIsop() +
        Computes an ISOP in ZDD form from BDDs. + +
        Cudd_zddIte() +
        Computes the ITE of three ZDDs. + +
        Cudd_zddIthVar() +
        Returns the ZDD variable with index i. + +
        Cudd_zddNextPath() +
        Generates the next path of a ZDD. + +
        Cudd_zddPortFromBdd() +
        Converts a BDD into a ZDD. + +
        Cudd_zddPortToBdd() +
        Converts a ZDD into a BDD. + +
        Cudd_zddPrintCover() +
        Prints a sum of products from a ZDD representing a cover. + +
        Cudd_zddPrintDebug() +
        Prints to the standard output a ZDD and its statistics. + +
        Cudd_zddPrintMinterm() +
        Prints a disjoint sum of product form for a ZDD. + +
        Cudd_zddPrintSubtable() +
        Prints the ZDD table. + +
        Cudd_zddProduct() +
        Computes the product of two covers represented by ZDDs. + +
        Cudd_zddReadNodeCount() +
        Reports the number of nodes in ZDDs. + +
        Cudd_zddRealignDisable() +
        Disables realignment of ZDD order to BDD order. + +
        Cudd_zddRealignEnable() +
        Enables realignment of ZDD order to BDD order. + +
        Cudd_zddRealignmentEnabled() +
        Tells whether the realignment of ZDD order to BDD order is + enabled. + +
        Cudd_zddReduceHeap() +
        Main dynamic reordering routine for ZDDs. + +
        Cudd_zddShuffleHeap() +
        Reorders ZDD variables according to given permutation. + +
        Cudd_zddSubset0() +
        Computes the negative cofactor of a ZDD w.r.t. a variable. + +
        Cudd_zddSubset1() +
        Computes the positive cofactor of a ZDD w.r.t. a variable. + +
        Cudd_zddSymmProfile() +
        Prints statistics on symmetric ZDD variables. + +
        Cudd_zddUnateProduct() +
        Computes the product of two unate covers. + +
        Cudd_zddUnion() +
        Computes the union of two ZDDs. + +
        Cudd_zddVarsFromBddVars() +
        Creates one or more ZDD variables for each BDD variable. + +
        Cudd_zddWeakDivF() +
        Modified version of Cudd_zddWeakDiv. + +
        Cudd_zddWeakDiv() +
        Applies weak division to two covers. + +
        MarkCacheCleanUp() +
        Frees memory associated with computed table of + cuddBddLICMarkEdges. + +
        MarkCacheCompare() +
        Comparison function for the computed table of + cuddBddLICMarkEdges. + +
        MarkCacheHash() +
        Hash function for the computed table of cuddBddLICMarkEdges. + +
        PMX() +
        Performs the crossover between two parents. + +
        PairInTables() +
        Check whether the given pair is in the tables. + +
        PickOnePair() +
        Check the tables for the existence of pair and return one + combination, store in cache. + +
        RAbuildSubset() +
        Builds the subset BDD for cuddRemapUnderApprox. + +
        RAmarkNodes() +
        Marks nodes for remapping. + +
        ResizeCountMintermPages() +
        Resize the number of pages allocated to store the minterm + counts. + +
        ResizeCountNodePages() +
        Resize the number of pages allocated to store the node counts. + +
        ResizeNodeDataPages() +
        Resize the number of pages allocated to store the node data. + +
        ResizeNodeDistPages() +
        Resize the number of pages allocated to store the distances + related to each node. + +
        ResizeQueuePages() +
        Resize the number of pages allocated to store nodes in the BFS + traversal of the Bdd . + +
        StoreNodes() +
        Procedure to recursively store nodes that are retained in the subset. + +
        SubsetCountMintermAux() +
        Recursively counts minterms of each node in the DAG. + +
        SubsetCountMinterm() +
        Counts minterms of each node in the DAG + +
        SubsetCountNodesAux() +
        Recursively counts the number of nodes under the dag. + Also counts the number of nodes under the lighter child of + this node. + +
        SubsetCountNodes() +
        Counts the nodes under the current node and its lighter child + +
        UAbuildSubset() +
        Builds the subset BDD. + +
        UAmarkNodes() +
        Marks nodes for replacement by zero. + +
        ZeroCase() +
        If one child is zero, do explicitly what Restrict does or better + +
        addBddDoInterval() +
        Performs the recursive step for Cudd_addBddInterval. + +
        addBddDoIthBit() +
        Performs the recursive step for Cudd_addBddIthBit. + +
        addBddDoStrictThreshold() +
        Performs the recursive step for Cudd_addBddStrictThreshold. + +
        addBddDoThreshold() +
        Performs the recursive step for Cudd_addBddThreshold. + +
        addCheckPositiveCube() +
        Checks whether cube is an ADD representing the product + of positive literals. + +
        addDoIthBit() +
        Performs the recursive step for Cudd_addIthBit. + +
        addMMRecur() +
        Performs the recursive step of Cudd_addMatrixMultiply. + +
        addMultiplicityGroups() +
        Adds multiplicity groups to a ZDD variable group tree. + +
        addTriangleRecur() +
        Performs the recursive step of Cudd_addTriangle. + +
        addVarToConst() +
        Replaces variables with constants if possible (part of + canonical form). + +
        addWalshInt() +
        Implements the recursive step of Cudd_addWalsh. + +
        array_compare() +
        Comparison function for the computed table. + +
        array_hash() +
        Hash function for the computed table. + +
        bddAnnotateMintermCount() +
        Annotates every node in the BDD node with its minterm count. + +
        bddCheckPositiveCube() +
        Checks whether cube is an BDD representing the product of + positive literals. + +
        bddCorrelationAux() +
        Performs the recursive step of Cudd_bddCorrelation. + +
        bddCorrelationWeightsAux() +
        Performs the recursive step of Cudd_bddCorrelationWeigths. + +
        bddFixTree() +
        Fixes the BDD variable group tree after a shuffle. + +
        bddVarToCanonicalSimple() +
        Picks unique member from equiv expressions. + +
        bddVarToCanonical() +
        Picks unique member from equiv expressions. + +
        bddVarToConst() +
        Replaces variables with constants if possible. + +
        beforep() +
        Returns true iff the first argument precedes the second in + the clause order. + +
        bitVectorAlloc() +
        Allocates a bit vector. + +
        bitVectorClear() +
        Clears a bit vector. + +
        bitVectorFree() +
        Frees a bit vector. + +
        bitVectorRead() +
        Returns the i-th entry of a bit vector. + +
        bitVectorSet() +
        Sets the i-th entry of a bit vector to a value. + +
        build_dd() +
        Builds a DD from a given order. + +
        checkSymmInfo() +
        Check symmetry condition. + +
        computeClausesWithUniverse() +
        Computes the two-literal clauses for a node. + +
        computeClauses() +
        Computes the two-literal clauses for a node. + +
        computeLB() +
        Computes a lower bound on the size of a BDD. + +
        computeSavings() +
        Counts the nodes that would be eliminated if a given node + were replaced by zero. + +
        copyOrder() +
        Copies the current variable order to array. + +
        createResult() +
        Builds a result for cache storage. + +
        cuddAddApplyRecur() +
        Performs the recursive step of Cudd_addApply. + +
        cuddAddBddDoPattern() +
        Performs the recursive step for Cudd_addBddPattern. + +
        cuddAddCmplRecur() +
        Performs the recursive step of Cudd_addCmpl. + +
        cuddAddComposeRecur() +
        Performs the recursive step of Cudd_addCompose. + +
        cuddAddConstrainRecur() +
        Performs the recursive step of Cudd_addConstrain. + +
        cuddAddExistAbstractRecur() +
        Performs the recursive step of Cudd_addExistAbstract. + +
        cuddAddGeneralVectorComposeRecur() +
        Performs the recursive step of Cudd_addGeneralVectorCompose. + +
        cuddAddIteRecur() +
        Implements the recursive step of Cudd_addIte(f,g,h). + +
        cuddAddMonadicApplyRecur() +
        Performs the recursive step of Cudd_addMonadicApply. + +
        cuddAddNegateRecur() +
        Implements the recursive step of Cudd_addNegate. + +
        cuddAddNonSimComposeRecur() +
        Performs the recursive step of Cudd_addNonSimCompose. + +
        cuddAddOrAbstractRecur() +
        Performs the recursive step of Cudd_addOrAbstract. + +
        cuddAddOuterSumRecur() +
        Performs the recursive step of Cudd_addOuterSum. + +
        cuddAddPermuteRecur() +
        Implements the recursive step of Cudd_addPermute. + +
        cuddAddRestrictRecur() +
        Performs the recursive step of Cudd_addRestrict. + +
        cuddAddRoundOffRecur() +
        Implements the recursive step of Cudd_addRoundOff. + +
        cuddAddScalarInverseRecur() +
        Performs the recursive step of addScalarInverse. + +
        cuddAddUnivAbstractRecur() +
        Performs the recursive step of Cudd_addUnivAbstract. + +
        cuddAddVectorComposeRecur() +
        Performs the recursive step of Cudd_addVectorCompose. + +
        cuddAllocNode() +
        Fast storage allocation for DdNodes in the table. + +
        cuddAnnealing() +
        Get new variable-order by simulated annealing algorithm. + +
        cuddApaCountMintermAux() +
        Performs the recursive step of Cudd_ApaCountMinterm. + +
        cuddApaStCountfree() +
        Frees the memory used to store the minterm counts recorded + in the visited table. + +
        cuddBddAlignToZdd() +
        Reorders BDD variables according to the order of the ZDD + variables. + +
        cuddBddAndAbstractRecur() +
        Takes the AND of two BDDs and simultaneously abstracts the + variables in cube. + +
        cuddBddAndRecur() +
        Implements the recursive step of Cudd_bddAnd. + +
        cuddBddBooleanDiffRecur() +
        Performs the recursive steps of Cudd_bddBoleanDiff. + +
        cuddBddCharToVect() +
        Performs the recursive step of Cudd_bddCharToVect. + +
        cuddBddClipAndAbsRecur() +
        Approximates the AND of two BDDs and simultaneously abstracts the + variables in cube. + +
        cuddBddClippingAndAbstract() +
        Approximates the conjunction of two BDDs f and g and + simultaneously abstracts the variables in cube. + +
        cuddBddClippingAndRecur() +
        Implements the recursive step of Cudd_bddClippingAnd. + +
        cuddBddClippingAnd() +
        Approximates the conjunction of two BDDs f and g. + +
        cuddBddClosestCube() +
        Performs the recursive step of Cudd_bddClosestCube. + +
        cuddBddComposeRecur() +
        Performs the recursive step of Cudd_bddCompose. + +
        cuddBddConstrainDecomp() +
        Performs the recursive step of Cudd_bddConstrainDecomp. + +
        cuddBddConstrainRecur() +
        Performs the recursive step of Cudd_bddConstrain. + +
        cuddBddExistAbstractRecur() +
        Performs the recursive steps of Cudd_bddExistAbstract. + +
        cuddBddIntersectRecur() +
        Implements the recursive step of Cudd_bddIntersect. + +
        cuddBddIsop() +
        Performs the recursive step of Cudd_bddIsop. + +
        cuddBddIteRecur() +
        Implements the recursive step of Cudd_bddIte. + +
        cuddBddLICBuildResult() +
        Builds the result of Cudd_bddLICompaction. + +
        cuddBddLICMarkEdges() +
        Performs the edge marking step of Cudd_bddLICompaction. + +
        cuddBddLICompaction() +
        Performs safe minimization of a BDD. + +
        cuddBddLiteralSetIntersectionRecur() +
        Performs the recursive step of + Cudd_bddLiteralSetIntersection. + +
        cuddBddMakePrime() +
        Performs the recursive step of Cudd_bddMakePrime. + +
        cuddBddNPAndRecur() +
        Implements the recursive step of Cudd_bddAnd. + +
        cuddBddPermuteRecur() +
        Implements the recursive step of Cudd_bddPermute. + +
        cuddBddRestrictRecur() +
        Performs the recursive step of Cudd_bddRestrict. + +
        cuddBddSqueeze() +
        Performs the recursive step of Cudd_bddSqueeze. + +
        cuddBddTransferRecur() +
        Performs the recursive step of Cudd_bddTransfer. + +
        cuddBddTransfer() +
        Convert a BDD from a manager to another one. + +
        cuddBddVarMapRecur() +
        Implements the recursive step of Cudd_bddVarMap. + +
        cuddBddVectorComposeRecur() +
        Performs the recursive step of Cudd_bddVectorCompose. + +
        cuddBddXorExistAbstractRecur() +
        Takes the exclusive OR of two BDDs and simultaneously abstracts the + variables in cube. + +
        cuddBddXorRecur() +
        Implements the recursive step of Cudd_bddXor. + +
        cuddBiasedUnderApprox() +
        Applies the biased remapping underappoximation algorithm. + +
        cuddCProjectionRecur() +
        Performs the recursive step of Cudd_CProjection. + +
        cuddCacheFlush() +
        Flushes the cache. + +
        cuddCacheInsert1() +
        Inserts a result in the cache for a function with two + operands. + +
        cuddCacheInsert2() +
        Inserts a result in the cache for a function with two + operands. + +
        cuddCacheInsert() +
        Inserts a result in the cache. + +
        cuddCacheLookup1Zdd() +
        Looks up in the cache for the result of op applied to f. + +
        cuddCacheLookup1() +
        Looks up in the cache for the result of op applied to f. + +
        cuddCacheLookup2Zdd() +
        Looks up in the cache for the result of op applied to f + and g. + +
        cuddCacheLookup2() +
        Looks up in the cache for the result of op applied to f + and g. + +
        cuddCacheLookupZdd() +
        Looks up in the cache for the result of op applied to f, + g, and h. + +
        cuddCacheLookup() +
        Looks up in the cache for the result of op applied to f, + g, and h. + +
        cuddCacheProfile() +
        Computes and prints a profile of the cache usage. + +
        cuddCacheResize() +
        Resizes the cache. + +
        cuddCheckCollisionOrdering() +
        Checks whether a collision list is ordered. + +
        cuddCheckCube() +
        Checks whether g is the BDD of a cube. + +
        cuddClearDeathRow() +
        Clears the death row. + +
        cuddCofactorRecur() +
        Performs the recursive step of Cudd_Cofactor. + +
        cuddCollectNodes() +
        Recursively collects all the nodes of a DD in a symbol + table. + +
        cuddComputeFloorLog2() +
        Returns the floor of the logarithm to the base 2. + +
        cuddConjunctsAux() +
        Procedure to compute two conjunctive factors of f and place in *c1 and *c2. + +
        cuddConstantLookup() +
        Looks up in the cache for the result of op applied to f, + g, and h. + +
        cuddDestroySubtables() +
        Destroys the n most recently created subtables in a unique table. + +
        cuddDoRebalance() +
        Rebalances a red/black tree. + +
        cuddDynamicAllocNode() +
        Dynamically allocates a Node. + +
        cuddEstimateCofactorSimple() +
        Performs the recursive step of Cudd_CofactorEstimateSimple. + +
        cuddEstimateCofactor() +
        Performs the recursive step of Cudd_CofactorEstimate. + +
        cuddExact() +
        Exact variable ordering algorithm. + +
        cuddFindParent() +
        Searches the subtables above node for a parent. + +
        cuddFreeTable() +
        Frees the resources associated to a unique table. + +
        cuddGarbageCollect() +
        Performs garbage collection on the unique tables. + +
        cuddGa() +
        Genetic algorithm for DD reordering. + +
        cuddGetBranches() +
        Computes the children of g. + +
        cuddHashTableAlloc() +
        Fast storage allocation for items in a hash table. + +
        cuddHashTableInit() +
        Initializes a hash table. + +
        cuddHashTableInsert1() +
        Inserts an item in a hash table. + +
        cuddHashTableInsert2() +
        Inserts an item in a hash table. + +
        cuddHashTableInsert3() +
        Inserts an item in a hash table. + +
        cuddHashTableInsert() +
        Inserts an item in a hash table. + +
        cuddHashTableLookup1() +
        Looks up a key consisting of one pointer in a hash table. + +
        cuddHashTableLookup2() +
        Looks up a key consisting of two pointers in a hash table. + +
        cuddHashTableLookup3() +
        Looks up a key consisting of three pointers in a hash table. + +
        cuddHashTableLookup() +
        Looks up a key in a hash table. + +
        cuddHashTableQuit() +
        Shuts down a hash table. + +
        cuddHashTableResize() +
        Resizes a hash table. + +
        cuddHeapProfile() +
        Prints information about the heap. + +
        cuddInitCache() +
        Initializes the computed table. + +
        cuddInitInteract() +
        Initializes the interaction matrix. + +
        cuddInitLinear() +
        Initializes the linear transform matrix. + +
        cuddInitTable() +
        Creates and initializes the unique table. + +
        cuddInsertSubtables() +
        Inserts n new subtables in a unique table at level. + +
        cuddIsInDeathRow() +
        Checks whether a node is in the death row. + +
        cuddLevelQueueDequeue() +
        Remove an item from the front of a level queue. + +
        cuddLevelQueueEnqueue() +
        Inserts a new key in a level queue. + +
        cuddLevelQueueInit() +
        Initializes a level queue. + +
        cuddLevelQueueQuit() +
        Shuts down a level queue. + +
        cuddLinearAndSifting() +
        BDD reduction based on combination of sifting and linear + transformations. + +
        cuddLinearInPlace() +
        Linearly combines two adjacent variables. + +
        cuddLocalCacheAddToList() +
        Inserts a local cache in the manager list. + +
        cuddLocalCacheClearAll() +
        Clears the local caches of a manager. + +
        cuddLocalCacheClearDead() +
        Clears the dead entries of the local caches of a manager. + +
        cuddLocalCacheInit() +
        Initializes a local computed table. + +
        cuddLocalCacheInsert() +
        Inserts a result in a local cache. + +
        cuddLocalCacheLookup() +
        Looks up in a local cache. + +
        cuddLocalCacheProfile() +
        Computes and prints a profile of a local cache usage. + +
        cuddLocalCacheQuit() +
        Shuts down a local computed table. + +
        cuddLocalCacheRemoveFromList() +
        Removes a local cache from the manager list. + +
        cuddLocalCacheResize() +
        Resizes a local cache. + +
        cuddMakeBddFromZddCover() +
        Converts a ZDD cover to a BDD graph. + +
        cuddMinHammingDistRecur() +
        Performs the recursive step of Cudd_MinHammingDist. + +
        cuddNextHigh() +
        Finds the next subtable with a larger index. + +
        cuddNextLow() +
        Finds the next subtable with a smaller index. + +
        cuddNodeArrayRecur() +
        Performs the recursive step of cuddNodeArray. + +
        cuddNodeArray() +
        Recursively collects all the nodes of a DD in an array. + +
        cuddOrderedInsert() +
        Inserts a DdNode in a red/black search tree. + +
        cuddOrderedThread() +
        Threads all the nodes of a search tree into a linear list. + +
        cuddPrintNode() +
        Prints out information on a node. + +
        cuddPrintVarGroups() +
        Prints the variable groups as a parenthesized list. + +
        cuddP() +
        Prints a DD to the standard output. One line per node is + printed. + +
        cuddReclaimZdd() +
        Brings children of a dead ZDD node back. + +
        cuddReclaim() +
        Brings children of a dead node back. + +
        cuddRehash() +
        Rehashes a unique subtable. + +
        cuddRemapUnderApprox() +
        Applies the remapping underappoximation algorithm. + +
        cuddResizeLinear() +
        Resizes the linear transform matrix. + +
        cuddResizeTableZdd() +
        Increases the number of ZDD subtables in a unique table so + that it meets or exceeds index. + +
        cuddRotateLeft() +
        Performs the left rotation for red/black trees. + +
        cuddRotateRight() +
        Performs the right rotation for red/black trees. + +
        cuddSetInteract() +
        Set interaction matrix entries. + +
        cuddShrinkDeathRow() +
        Shrinks the death row. + +
        cuddShrinkSubtable() +
        Shrinks a subtable. + +
        cuddSifting() +
        Implementation of Rudell's sifting algorithm. + +
        cuddSlowTableGrowth() +
        Adjusts parameters of a table to slow down its growth. + +
        cuddSolveEqnRecur() +
        Implements the recursive step of Cudd_SolveEqn. + +
        cuddSplitSetRecur() +
        Implements the recursive step of Cudd_SplitSet. + +
        cuddStCountfree() +
        Frees the memory used to store the minterm counts recorded + in the visited table. + +
        cuddSubsetHeavyBranch() +
        The main procedure that returns a subset by choosing the heavier + branch in the BDD. + +
        cuddSubsetShortPaths() +
        The outermost procedure to return a subset of the given BDD + with the shortest path lengths. + +
        cuddSwapInPlace() +
        Swaps two adjacent variables. + +
        cuddSwapping() +
        Reorders variables by a sequence of (non-adjacent) swaps. + +
        cuddSymmCheck() +
        Checks for symmetry of x and y. + +
        cuddSymmSiftingConv() +
        Symmetric sifting to convergence algorithm. + +
        cuddSymmSifting() +
        Symmetric sifting algorithm. + +
        cuddTestInteract() +
        Test interaction matrix entries. + +
        cuddTimesInDeathRow() +
        Counts how many times a node is in the death row. + +
        cuddTreeSifting() +
        Tree sifting algorithm. + +
        cuddUnderApprox() +
        Applies Tom Shiple's underappoximation algorithm. + +
        cuddUniqueConst() +
        Checks the unique table for the existence of a constant node. + +
        cuddUniqueInterIVO() +
        Wrapper for cuddUniqueInter that is independent of variable + ordering. + +
        cuddUniqueInterZdd() +
        Checks the unique table for the existence of an internal + ZDD node. + +
        cuddUniqueInter() +
        Checks the unique table for the existence of an internal node. + +
        cuddUniqueLookup() +
        Checks the unique table for the existence of an internal node. + +
        cuddUpdateInteractionMatrix() +
        Updates the interaction matrix. + +
        cuddVerifySol() +
        Implements the recursive step of Cudd_VerifySol. + +
        cuddWindowReorder() +
        Reorders by applying the method of the sliding window. + +
        cuddXorLinear() +
        XORs two rows of the linear transform matrix. + +
        cuddZddAlignToBdd() +
        Reorders ZDD variables according to the order of the BDD + variables. + +
        cuddZddChangeAux() +
        Performs the recursive step of Cudd_zddChange. + +
        cuddZddChange() +
        Substitutes a variable with its complement in a ZDD. + +
        cuddZddComplement() +
        Computes a complement of a ZDD node. + +
        cuddZddCountDoubleStep() +
        Performs the recursive step of Cudd_zddCountDouble. + +
        cuddZddCountStep() +
        Performs the recursive step of Cudd_zddCount. + +
        cuddZddDagInt() +
        Performs the recursive step of Cudd_zddDagSize. + +
        cuddZddDiff() +
        Performs the recursive step of Cudd_zddDiff. + +
        cuddZddDivideF() +
        Performs the recursive step of Cudd_zddDivideF. + +
        cuddZddDivide() +
        Performs the recursive step of Cudd_zddDivide. + +
        cuddZddFreeUniv() +
        Frees the ZDD universe. + +
        cuddZddGetCofactors2() +
        Computes the two-way decomposition of f w.r.t. v. + +
        cuddZddGetCofactors3() +
        Computes the three-way decomposition of f w.r.t. v. + +
        cuddZddGetNegVarIndex() +
        Returns the index of negative ZDD variable. + +
        cuddZddGetNegVarLevel() +
        Returns the level of negative ZDD variable. + +
        cuddZddGetNodeIVO() +
        Wrapper for cuddUniqueInterZdd that is independent of variable + ordering. + +
        cuddZddGetNode() +
        Wrapper for cuddUniqueInterZdd. + +
        cuddZddGetPosVarIndex() +
        Returns the index of positive ZDD variable. + +
        cuddZddGetPosVarLevel() +
        Returns the level of positive ZDD variable. + +
        cuddZddInitUniv() +
        Initializes the ZDD universe. + +
        cuddZddIntersect() +
        Performs the recursive step of Cudd_zddIntersect. + +
        cuddZddIsop() +
        Performs the recursive step of Cudd_zddIsop. + +
        cuddZddIte() +
        Performs the recursive step of Cudd_zddIte. + +
        cuddZddLinearAux() +
        Given xLow <= x <= xHigh moves x up and down between the + boundaries. + +
        cuddZddLinearBackward() +
        Given a set of moves, returns the ZDD heap to the position + giving the minimum size. + +
        cuddZddLinearDown() +
        Sifts a variable down and applies the XOR transformation. + +
        cuddZddLinearInPlace() +
        Linearly combines two adjacent variables. + +
        cuddZddLinearSifting() +
        Implementation of the linear sifting algorithm for ZDDs. + +
        cuddZddLinearUp() +
        Sifts a variable up applying the XOR transformation. + +
        cuddZddNextHigh() +
        Finds the next subtable with a larger index. + +
        cuddZddNextLow() +
        Finds the next subtable with a smaller index. + +
        cuddZddProduct() +
        Performs the recursive step of Cudd_zddProduct. + +
        cuddZddP() +
        Prints a ZDD to the standard output. One line per node is + printed. + +
        cuddZddSiftingAux() +
        Given xLow <= x <= xHigh moves x up and down between the + boundaries. + +
        cuddZddSiftingBackward() +
        Given a set of moves, returns the ZDD heap to the position + giving the minimum size. + +
        cuddZddSiftingDown() +
        Sifts a variable down. + +
        cuddZddSiftingUp() +
        Sifts a variable up. + +
        cuddZddSifting() +
        Implementation of Rudell's sifting algorithm. + +
        cuddZddSubset0() +
        Computes the negative cofactor of a ZDD w.r.t. a variable. + +
        cuddZddSubset1() +
        Computes the positive cofactor of a ZDD w.r.t. a variable. + +
        cuddZddSwapInPlace() +
        Swaps two adjacent variables. + +
        cuddZddSwapping() +
        Reorders variables by a sequence of (non-adjacent) swaps. + +
        cuddZddSymmCheck() +
        Checks for symmetry of x and y. + +
        cuddZddSymmSiftingAux() +
        Given x_low <= x <= x_high moves x up and down between the + boundaries. + +
        cuddZddSymmSiftingBackward() +
        Given a set of moves, returns the ZDD heap to the position + giving the minimum size. + +
        cuddZddSymmSiftingConvAux() +
        Given x_low <= x <= x_high moves x up and down between the + boundaries. + +
        cuddZddSymmSiftingConv() +
        Symmetric sifting to convergence algorithm for ZDDs. + +
        cuddZddSymmSifting_down() +
        Moves x down until either it reaches the bound (x_high) or + the size of the ZDD heap increases too much. + +
        cuddZddSymmSifting_up() +
        Moves x up until either it reaches the bound (x_low) or + the size of the ZDD heap increases too much. + +
        cuddZddSymmSifting() +
        Symmetric sifting algorithm for ZDDs. + +
        cuddZddSymmSummary() +
        Counts numbers of symmetric variables and symmetry + groups. + +
        cuddZddTreeSifting() +
        Tree sifting algorithm for ZDDs. + +
        cuddZddUnateProduct() +
        Performs the recursive step of Cudd_zddUnateProduct. + +
        cuddZddUndoMoves() +
        Given a set of moves, returns the ZDD heap to the order + in effect before the moves. + +
        cuddZddUnion() +
        Performs the recursive step of Cudd_zddUnion. + +
        cuddZddUniqueCompare() +
        Comparison function used by qsort. + +
        cuddZddWeakDivF() +
        Performs the recursive step of Cudd_zddWeakDivF. + +
        cuddZddWeakDiv() +
        Performs the recursive step of Cudd_zddWeakDiv. + +
        ddBddToAddRecur() +
        Performs the recursive step for Cudd_BddToAdd. + +
        ddCheckPermuation() +
        Checks the BDD variable group tree before a shuffle. + +
        ddClearFlag() +
        Performs a DFS from f, clearing the LSB of the next + pointers. + +
        ddClearGlobal() +
        Scans the DD and clears the LSB of the next pointers. + +
        ddClearGlobal() +
        Scans the DD and clears the LSB of the next pointers. + +
        ddClearLocal() +
        Performs a DFS from f, clearing the LSB of the then pointers. + +
        ddCofMintermAux() +
        Recursive Step for Cudd_CofMinterm function. + +
        ddCountInternalMtrNodes() +
        Counts the number of internal nodes of the group tree. + +
        ddCountMintermAux() +
        Performs the recursive step of Cudd_CountMinterm. + +
        ddCountPathAux() +
        Performs the recursive step of Cudd_CountPath. + +
        ddCountPathsToNonZero() +
        Performs the recursive step of Cudd_CountPathsToNonZero. + +
        ddCountRoots() +
        Counts the number of roots. + +
        ddCreateGroup() +
        Creates a group encompassing variables from x to y in the + DD table. + +
        ddDagInt() +
        Performs the recursive step of Cudd_DagSize. + +
        ddDissolveGroup() +
        Dissolves a group in the DD table. + +
        ddDoDumpBlif() +
        Performs the recursive step of Cudd_DumpBlif. + +
        ddDoDumpDDcal() +
        Performs the recursive step of Cudd_DumpDDcal. + +
        ddDoDumpDaVinci() +
        Performs the recursive step of Cudd_DumpDaVinci. + +
        ddDoDumpFactoredForm() +
        Performs the recursive step of Cudd_DumpFactoredForm. + +
        ddEpdCountMintermAux() +
        Performs the recursive step of Cudd_EpdCountMinterm. + +
        ddEpdFree() +
        Frees the memory used to store the minterm counts recorded + in the visited table. + +
        ddExchange() +
        This function is for exchanging two variables, x and y. + +
        ddExtSymmCheck() +
        Checks for extended symmetry of x and y. + +
        ddFindEssentialRecur() +
        Implements the recursive step of Cudd_FindEssential. + +
        ddFindNodeHiLo() +
        Finds the lower and upper bounds of the group represented + by treenode. + +
        ddFindTwoLiteralClausesRecur() +
        Implements the recursive step of Cudd_FindTwoLiteralClauses. + +
        ddFixLimits() +
        Adjusts the values of table limits. + +
        ddGroupMoveBackward() +
        Undoes the swap two groups. + +
        ddGroupMove() +
        Swaps two groups and records the move. + +
        ddGroupSiftingAux() +
        Sifts one variable up and down until it has taken all + positions. Checks for aggregation. + +
        ddGroupSiftingBackward() +
        Determines the best position for a variables and returns + it there. + +
        ddGroupSiftingDown() +
        Sifts down a variable until it reaches position xHigh. + +
        ddGroupSiftingUp() +
        Sifts up a variable until either it reaches position xLow + or the size of the DD heap increases too much. + +
        ddGroupSifting() +
        Sifts from treenode->low to treenode->high. + +
        ddIsIthAddVarPair() +
        Comparison of a pair of functions to the i-th ADD variable. + +
        ddIsIthAddVar() +
        Comparison of a function to the i-th ADD variable. + +
        ddIsVarHandled() +
        Checks whether a variables is already handled. + +
        ddJumpingAux() +
        Moves a variable to a specified position. + +
        ddJumpingDown() +
        This function is for jumping down. + +
        ddJumpingUp() +
        This function is for jumping up. + +
        ddLCHash() +
        Computes the hash value for a local cache. + +
        ddLeavesInt() +
        Performs the recursive step of Cudd_CountLeaves. + +
        ddLinearAndSiftingAux() +
        Given xLow <= x <= xHigh moves x up and down between the + boundaries. + +
        ddLinearAndSiftingBackward() +
        Given a set of moves, returns the DD heap to the order + giving the minimum size. + +
        ddLinearAndSiftingDown() +
        Sifts a variable down and applies linear transformations. + +
        ddLinearAndSiftingUp() +
        Sifts a variable up and applies linear transformations. + +
        ddLinearUniqueCompare() +
        Comparison function used by qsort. + +
        ddMergeGroups() +
        Merges groups in the DD table. + +
        ddNoCheck() +
        Pretends to check two variables for aggregation. + +
        ddPatchTree() +
        Fixes a variable tree after the insertion of new subtables. + +
        ddPermuteWindow3() +
        Tries all the permutations of the three variables between + x and x+2 and retains the best. + +
        ddPermuteWindow4() +
        Tries all the permutations of the four variables between w + and w+3 and retains the best. + +
        ddPickArbitraryMinterms() +
        Performs the recursive step of Cudd_bddPickArbitraryMinterms. + +
        ddPickRepresentativeCube() +
        Finds a representative cube of a BDD. + +
        ddPrintMintermAux() +
        Performs the recursive step of Cudd_PrintMinterm. + +
        ddRehashZdd() +
        Rehashes a ZDD unique subtable. + +
        ddReorderChildren() +
        Reorders the children of a group tree node according to + the options. + +
        ddReorderPostprocess() +
        Cleans up at the end of reordering. + +
        ddReorderPreprocess() +
        Prepares the DD heap for dynamic reordering. + +
        ddReportRefMess() +
        Reports problem in garbage collection. + +
        ddResetVarHandled() +
        Resets a variable to be processed. + +
        ddResizeTable() +
        Increases the number of subtables in a unique table so + that it meets or exceeds index. + +
        ddSecDiffCheck() +
        Checks two variables for aggregation. + +
        ddSetVarHandled() +
        Sets a variable to already handled. + +
        ddShuffle() +
        Reorders variables according to a given permutation. + +
        ddShuffle() +
        Reorders variables according to a given permutation. + +
        ddSiftUp() +
        Moves one variable up. + +
        ddSiftUp() +
        Moves one variable up. + +
        ddSiftingAux() +
        Given xLow <= x <= xHigh moves x up and down between the + boundaries. + +
        ddSiftingBackward() +
        Given a set of moves, returns the DD heap to the position + giving the minimum size. + +
        ddSiftingDown() +
        Sifts a variable down. + +
        ddSiftingUp() +
        Sifts a variable up. + +
        ddSuppInteract() +
        Find the support of f. + +
        ddSupportStep() +
        Performs the recursive step of Cudd_Support. + +
        ddSwapAny() +
        Swaps any two variables. + +
        ddSymmGroupMoveBackward() +
        Undoes the swap of two groups. + +
        ddSymmGroupMove() +
        Swaps two groups. + +
        ddSymmSiftingAux() +
        Given xLow <= x <= xHigh moves x up and down between the + boundaries. + +
        ddSymmSiftingBackward() +
        Given a set of moves, returns the DD heap to the position + giving the minimum size. + +
        ddSymmSiftingConvAux() +
        Given xLow <= x <= xHigh moves x up and down between the + boundaries. + +
        ddSymmSiftingDown() +
        Moves x down until either it reaches the bound (xHigh) or + the size of the DD heap increases too much. + +
        ddSymmSiftingUp() +
        Moves x up until either it reaches the bound (xLow) or + the size of the DD heap increases too much. + +
        ddSymmSummary() +
        Counts numbers of symmetric variables and symmetry + groups. + +
        ddSymmUniqueCompare() +
        Comparison function used by qsort. + +
        ddTreeSiftingAux() +
        Visits the group tree and reorders each group. + +
        ddUndoMoves() +
        Given a set of moves, returns the DD heap to the order + in effect before the moves. + +
        ddUniqueCompareGroup() +
        Comparison function used by qsort. + +
        ddUniqueCompare() +
        Comparison function used by qsort. + +
        ddUpdateInteract() +
        Marks as interacting all pairs of variables that appear in + support. + +
        ddUpdateMtrTree() +
        Updates the BDD variable group tree before a shuffle. + +
        ddVarGroupCheck() +
        Checks for grouping of x and y. + +
        ddWindow2() +
        Reorders by applying a sliding window of width 2. + +
        ddWindow3() +
        Reorders by applying a sliding window of width 3. + +
        ddWindow4() +
        Reorders by applying a sliding window of width 4. + +
        ddWindowConv2() +
        Reorders by repeatedly applying a sliding window of width 2. + +
        ddWindowConv3() +
        Reorders by repeatedly applying a sliding window of width 3. + +
        ddWindowConv4() +
        Reorders by repeatedly applying a sliding window of width 4. + +
        debugCheckParent() +
        Reports an error if a (dead) node has a non-dead parent. + +
        debugFindParent() +
        Searches the subtables above node for its parents. + +
        dp2() +
        Performs the recursive step of cuddP. + +
        emptyClauseSet() +
        Returns an enpty set of clauses. + +
        equalp() +
        Returns true iff the two arguments are identical clauses. + +
        find_average_fitness() +
        Returns the average fitness of the population. + +
        find_best() +
        Returns the index of the fittest individual. + +
        fixVarTree() +
        Fixes a variable group tree. + +
        freeMatrix() +
        Frees a two-dimensional matrix allocated by getMatrix. + +
        freePathPair() +
        Frees the entries of the visited symbol table. + +
        gatherInfoAux() +
        Recursively counts minterms and computes reference counts + of each node in the BDD. + +
        gatherInfo() +
        Gathers information about each node. + +
        gcd() +
        Returns the gcd of two integers. + +
        getCube() +
        Build a BDD for a largest cube of f. + +
        getLargest() +
        Finds the size of the largest cube(s) in a DD. + +
        getLevelKeys() +
        Returns the number of nodes at one level of a unique table. + +
        getMatrix() +
        Allocates a two-dimensional matrix of ints. + +
        getMaxBinomial() +
        Returns the maximum value of (n choose k) for a given n. + +
        getPath() +
        Build a BDD for a shortest path of f. + +
        getShortest() +
        Finds the length of the shortest path(s) in a DD. + +
        hashDelete() +
        Removes an item from the hash table of a level queue. + +
        hashInsert() +
        Inserts an item in the hash table of a level queue. + +
        hashLookup() +
        Looks up a key in the hash table of a level queue. + +
        hashResize() +
        Resizes the hash table of a level queue. + +
        impliedp() +
        Returns true iff either literal of a clause is in a set of + literals. + +
        initSymmInfo() +
        Gathers symmetry information. + +
        largest() +
        Finds the largest DD in the population. + +
        make_random() +
        Generates the random sequences for the initial population. + +
        mintermsFromUniverse() +
        Recursive procedure to extract n mintems from constant 1. + +
        oneliteralp() +
        Returns true iff the argument is a one-literal clause. + +
        pushDown() +
        Pushes a variable in the order down to position "level." + +
        rand_int() +
        Generates a random number between 0 and the integer a. + +
        random_generator() +
        Random number generator. + +
        restoreOrder() +
        Restores the variable order in array by a series of sifts up. + +
        roulette() +
        Selects two parents with the roulette wheel method. + +
        selectMintermsFromUniverse() +
        This function prepares an array of variables which have not been + encountered so far when traversing the procedure cuddSplitSetRecur. + +
        sentinelp() +
        Returns true iff the argument is the sentinel clause. + +
        separateCube() +
        Separates cube from distance. + +
        siftBackwardProb() +
        Returns the DD to the best position encountered during + sifting if there was improvement. + +
        sift_up() +
        Moves one variable up. + +
        stPathTableDdFree() +
        Procedure to free te result dds stored in the NodeDist pages. + +
        st_zdd_count_dbl_free() +
        Frees the memory associated with the computed table of + Cudd_zddCountDouble. + +
        st_zdd_countfree() +
        Frees the memory associated with the computed table of + Cudd_zddCount. + +
        stopping_criterion() +
        Checks termination condition. + +
        tlcInfoAlloc() +
        Allocates a DdTlcInfo Structure. + +
        updateEntry() +
        Updates entry for a subset. + +
        updateParity() +
        Recursively update the parity of the paths reaching a node. + +
        updateRefs() +
        Update function reference counts. + +
        updateUB() +
        Updates the upper bound and saves the best order seen so far. + +
        zddCountInternalMtrNodes() +
        Counts the number of internal nodes of the group tree. + +
        zddFindNodeHiLo() +
        Finds the lower and upper bounds of the group represented + by treenode. + +
        zddFixTree() +
        Fixes the ZDD variable group tree after a shuffle. + +
        zddGroupMoveBackward() +
        Undoes the swap two groups. + +
        zddGroupMove() +
        Swaps two groups and records the move. + +
        zddGroupSiftingAux() +
        Sifts one variable up and down until it has taken all + positions. Checks for aggregation. + +
        zddGroupSiftingBackward() +
        Determines the best position for a variables and returns + it there. + +
        zddGroupSiftingDown() +
        Sifts down a variable until it reaches position xHigh. + +
        zddGroupSiftingUp() +
        Sifts up a variable until either it reaches position xLow + or the size of the DD heap increases too much. + +
        zddGroupSifting() +
        Sifts from treenode->low to treenode->high. + +
        zddMergeGroups() +
        Merges groups in the DD table. + +
        zddPortFromBddStep() +
        Performs the recursive step of Cudd_zddPortFromBdd. + +
        zddPortToBddStep() +
        Performs the recursive step of Cudd_zddPortToBdd. + +
        zddPrintCoverAux() +
        Performs the recursive step of Cudd_zddPrintCover. + +
        zddReorderChildren() +
        Reorders the children of a group tree node according to + the options. + +
        zddReorderPostprocess() +
        Shrinks almost empty ZDD subtables at the end of reordering + to guarantee that they have a reasonable load factor. + +
        zddReorderPreprocess() +
        Prepares the ZDD heap for dynamic reordering. + +
        zddShuffle() +
        Reorders ZDD variables according to a given permutation. + +
        zddSiftUp() +
        Moves one ZDD variable up. + +
        zddSwapAny() +
        Swaps any two variables. + +
        zddTreeSiftingAux() +
        Visits the group tree and reorders each group. + +
        zddUniqueCompareGroup() +
        Comparison function used by qsort. + +
        zddVarToConst() +
        Replaces variables with constants if possible (part of + canonical form). + +
        zdd_group_move_backward() +
        Undoes the swap of two groups. + +
        zdd_group_move() +
        Swaps two groups. + +
        zdd_print_minterm_aux() +
        Performs the recursive step of Cudd_zddPrintMinterm. + +
        zdd_subset0_aux() +
        Performs the recursive step of Cudd_zddSubset0. + +
        zdd_subset1_aux() +
        Performs the recursive step of Cudd_zddSubset1. + +
        zp2() +
        Performs the recursive step of cuddZddP. + +
        () +
        Adds node to the head of the free list. + +
        () +
        Adds node to the head of the free list. + +
        () +
        Clears the 4 least significant bits of a pointer. + +
        () +
        Complements a DD if a condition is true. + +
        () +
        Complements a DD. + +
        () +
        Computes hash function for keys of three operands. + +
        () +
        Computes hash function for keys of two operands. + +
        () +
        Computes the absolute value of a number. + +
        () +
        Computes the maximum of two numbers. + +
        () +
        Computes the minimum of two numbers. + +
        () +
        Decreases the reference count of a node, if it is not + saturated. + +
        () +
        Enforces DD_MINUS_INF_VAL <= x <= DD_PLUS_INF_VAL. + +
        () +
        Extract the least significant digit of a double digit. + +
        () +
        Extract the most significant digit of a double digit. + +
        () +
        Finds the current position of ZDD variable index in the + order. + +
        () +
        Finds the current position of variable index in the + order. + +
        () +
        Hash function for the cache for functions with two + operands. + +
        () +
        Hash function for the cache. + +
        () +
        Hash function for the table of a level queue. + +
        () +
        Hash function for the unique table. + +
        () +
        Increases the reference count of a node, if it is not + saturated. + +
        () +
        Iterates over the cubes of a decision diagram. + +
        () +
        Iterates over the nodes of a decision diagram. + +
        () +
        Iterates over the paths of a ZDD. + +
        () +
        Iterates over the primes of a Boolean function. + +
        () +
        Outputs a line of stats. + +
        () +
        Returns 1 if a pointer is complemented. + +
        () +
        Returns 1 if the absolute value of the difference of the two + arguments x and y is less than e. + +
        () +
        Returns 1 if the node is a constant node. + +
        () +
        Returns 1 if the node is a constant node. + +
        () +
        Returns the arithmetic 0 constant node. + +
        () +
        Returns the complemented version of a pointer. + +
        () +
        Returns the constant 1 node. + +
        () +
        Returns the current position in the order of variable + index. + +
        () +
        Returns the else child of an internal node. + +
        () +
        Returns the else child of an internal node. + +
        () +
        Returns the minus infinity constant node. + +
        () +
        Returns the plus infinity constant node. + +
        () +
        Returns the regular version of a pointer. + +
        () +
        Returns the then child of an internal node. + +
        () +
        Returns the then child of an internal node. + +
        () +
        Returns the value of a constant node. + +
        () +
        Returns the value of a constant node. + +
        () +
        Saturating decrement operator. + +
        () +
        Saturating increment operator. + +
        + +
        + +Last updated on 20090220 23h06 + diff --git a/distr/cudd/doc/cuddAllByFile.html b/distr/cudd/doc/cuddAllByFile.html new file mode 100644 index 0000000..4076dde --- /dev/null +++ b/distr/cudd/doc/cuddAllByFile.html @@ -0,0 +1,13 @@ + +The cudd package for maintainers + + + + + + + + + + + diff --git a/distr/cudd/doc/cuddAllByFunc.html b/distr/cudd/doc/cuddAllByFunc.html new file mode 100644 index 0000000..76ec3ae --- /dev/null +++ b/distr/cudd/doc/cuddAllByFunc.html @@ -0,0 +1,13 @@ + +The cudd package for maintainers + + + + + + + + + + + diff --git a/distr/cudd/doc/cuddAllDet.html b/distr/cudd/doc/cuddAllDet.html new file mode 100644 index 0000000..9553951 --- /dev/null +++ b/distr/cudd/doc/cuddAllDet.html @@ -0,0 +1,21165 @@ + +The cudd package: all functions + + + +
        +
        +
        +
        +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
        +)
        +
        +
        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; +

        + +

        Side Effects None +

        + +

        Defined in cuddSubsetSP.c + +
        +
        +static int 
        +BAapplyBias(
        +  DdManager * dd, 
        +  DdNode * f, 
        +  DdNode * b, 
        +  ApproxInfo * info, 
        +  DdHashTable * cache 
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        See Also cuddBiasedUnderApprox + + +
        Defined in cuddApprox.c + +
        +
        +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
        +)
        +
        +
        Marks nodes for remapping. Returns 1 if successful; 0 + otherwise. +

        + +

        Side Effects None +

        + +

        See Also cuddRemapUnderApprox + + +
        Defined in cuddApprox.c + +
        +
        +static Conjuncts * 
        +BuildConjuncts(
        +  DdManager * dd, 
        +  DdNode * node, 
        +  st_table * distanceTable, 
        +  st_table * cacheTable, 
        +  int  approxDistance, 
        +  int  maxLocalRef, 
        +  st_table * ghTable, 
        +  st_table * mintermTable 
        +)
        +
        +
        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. +

        + +

        See Also cuddConjunctsAux + + +
        Defined in cuddDecomp.c + +
        +
        +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
        +)
        +
        +
        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. +

        + +

        Side Effects SubsetNodeTable is changed if it is not NIL. +

        + +

        Defined in cuddSubsetSP.c + +
        +
        +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 
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        Defined in cuddSubsetHB.c + +
        +
        +static Conjuncts * 
        +CheckInTables(
        +  DdNode * node, 
        +  DdNode * g1, 
        +  DdNode * h1, 
        +  DdNode * g2, 
        +  DdNode * h2, 
        +  st_table * ghTable, 
        +  st_table * cacheTable, 
        +  int * outOfMem 
        +)
        +
        +
        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. +

        + +

        See Also ZeroCase +BuildConjuncts + + +
        Defined in cuddDecomp.c + +
        +
        +static Conjuncts * 
        +CheckTablesCacheAndReturn(
        +  DdNode * node, 
        +  DdNode * g, 
        +  DdNode * h, 
        +  st_table * ghTable, 
        +  st_table * cacheTable 
        +)
        +
        +
        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. +

        + +

        Side Effects g and h referenced for the cache +

        + +

        See Also ZeroCase + + +
        Defined in cuddDecomp.c + +
        +
        +static void 
        +ConjunctsFree(
        +  DdManager * dd, 
        +  Conjuncts * factors 
        +)
        +
        +
        Free factors structure +

        + +

        Side Effects None +

        + +

        Defined in cuddDecomp.c + +
        +
        +static enum st_retval 
        +CorrelCleanUp(
        +  char * key, 
        +  char * value, 
        +  char * arg 
        +)
        +
        +
        Frees memory associated with hash table. Returns + ST_CONTINUE. +

        + +

        Side Effects None +

        + +

        Defined in cuddBddCorr.c + +
        +
        +static int 
        +CorrelCompare(
        +  const char * key1, 
        +  const char * key2 
        +)
        +
        +
        Compares two hash table entries. Returns 0 if they are + identical; 1 otherwise. +

        + +

        Side Effects None +

        + +

        Defined in cuddBddCorr.c + +
        +
        +static int 
        +CorrelHash(
        +  char * key, 
        +  int  modulus 
        +)
        +
        +
        Hashes a hash table entry. It is patterned after + st_strhash. Returns a value between 0 and modulus. +

        + +

        Side Effects None +

        + +

        Defined in cuddBddCorr.c + +
        +
        +static double 
        +CountMinterms(
        +  DdNode * node, 
        +  double  max, 
        +  st_table * mintermTable, 
        +  FILE * fp 
        +)
        +
        +
        Count the number of minterms of each node ina a BDD and + store it in a hash table. +

        + +

        Side Effects None +

        + +

        Defined in cuddDecomp.c + +
        +
        +static NodeStat * 
        +CreateBotDist(
        +  DdNode * node, 
        +  st_table * distanceTable 
        +)
        +
        +
        Get longest distance of node from constant. Returns the + distance of the root from the constant if successful; CUDD_OUT_OF_MEM + otherwise. +

        + +

        Side Effects None +

        + +

        Defined in cuddDecomp.c + +
        +
        +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
        +)
        +
        +
        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 +

        + +

        Side Effects Updates Path Table and path length array +

        + +

        See Also CreatePathTable +CreateTopDist +AssessPathLength + + +
        Defined in cuddSubsetSP.c + +
        +
        +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
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        See Also CreateTopDist +CreateBotDist + + +
        Defined in cuddSubsetSP.c + +
        +
        +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
        +)
        +
        +
        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. +

        + +

        Side Effects Creates entries in the pathTable +

        + +

        See Also CreatePathTable +CreateBotDist + + +
        Defined in cuddSubsetSP.c + +
        +
        +int 
        +Cudd_AddHook(
        +  DdManager * dd, 
        +  DD_HFP  f, 
        +  Cudd_HookType  where 
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        See Also Cudd_RemoveHook + + +
        Defined in cuddAPI.c + +
        +
        +DdApaDigit 
        +Cudd_ApaAdd(
        +  int  digits, 
        +  DdApaNumber  a, 
        +  DdApaNumber  b, 
        +  DdApaNumber  sum 
        +)
        +
        +
        Adds two arbitrary precision integers. Returns the + carry out of the most significant digit. +

        + +

        Side Effects The result of the sum is stored in parameter sum. +

        + +

        Defined in cuddApa.c + +
        +
        +int 
        +Cudd_ApaCompareRatios(
        +  int  digitsFirst, 
        +  DdApaNumber  firstNum, 
        +  unsigned int  firstDen, 
        +  int  digitsSecond, 
        +  DdApaNumber  secondNum, 
        +  unsigned int  secondDen 
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        Defined in cuddApa.c + +
        +
        +int 
        +Cudd_ApaCompare(
        +  int  digitsFirst, 
        +  DdApaNumber  first, 
        +  int  digitsSecond, 
        +  DdApaNumber  second 
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        Defined in cuddApa.c + +
        +
        +void 
        +Cudd_ApaCopy(
        +  int  digits, 
        +  DdApaNumber  source, 
        +  DdApaNumber  dest 
        +)
        +
        +
        Makes a copy of an arbitrary precision integer. +

        + +

        Side Effects Changes parameter dest. +

        + +

        Defined in cuddApa.c + +
        +
        +DdApaNumber 
        +Cudd_ApaCountMinterm(
        +  DdManager * manager, 
        +  DdNode * node, 
        +  int  nvars, 
        +  int * digits 
        +)
        +
        +
        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. +

        + +

        Side Effects The number of digits of the result is returned in + parameter digits. +

        + +

        See Also Cudd_CountMinterm + + +
        Defined in cuddApa.c + +
        +
        +unsigned int 
        +Cudd_ApaIntDivision(
        +  int  digits, 
        +  DdApaNumber  dividend, 
        +  unsigned int  divisor, 
        +  DdApaNumber  quotient 
        +)
        +
        +
        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. +

        + +

        Side Effects The quotient is returned in parameter quotient. +

        + +

        See Also Cudd_ApaShortDivision + + +
        Defined in cuddApa.c + +
        +
        +int 
        +Cudd_ApaNumberOfDigits(
        +  int  binaryDigits 
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        Defined in cuddApa.c + +
        +
        +void 
        +Cudd_ApaPowerOfTwo(
        +  int  digits, 
        +  DdApaNumber  number, 
        +  int  power 
        +)
        +
        +
        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. +

        + +

        Side Effects The result is returned in parameter number. +

        + +

        Defined in cuddApa.c + +
        +
        +int 
        +Cudd_ApaPrintDecimal(
        +  FILE * fp, 
        +  int  digits, 
        +  DdApaNumber  number 
        +)
        +
        +
        Prints an arbitrary precision integer in decimal format. + Returns 1 if successful; 0 otherwise. +

        + +

        Side Effects None +

        + +

        See Also Cudd_ApaPrintHex +Cudd_ApaPrintExponential + + +
        Defined in cuddApa.c + +
        +
        +int 
        +Cudd_ApaPrintDensity(
        +  FILE * fp, 
        +  DdManager * dd, 
        +  DdNode * node, 
        +  int  nvars 
        +)
        +
        +
        Prints the density of a BDD or ADD using + arbitrary precision arithmetic. Returns 1 if successful; 0 otherwise. +

        + +

        Side Effects None +

        + +

        Defined in cuddApa.c + +
        +
        +int 
        +Cudd_ApaPrintExponential(
        +  FILE * fp, 
        +  int  digits, 
        +  DdApaNumber  number, 
        +  int  precision 
        +)
        +
        +
        Prints an arbitrary precision integer in exponential format. + Returns 1 if successful; 0 otherwise. +

        + +

        Side Effects None +

        + +

        See Also Cudd_ApaPrintHex +Cudd_ApaPrintDecimal + + +
        Defined in cuddApa.c + +
        +
        +int 
        +Cudd_ApaPrintHex(
        +  FILE * fp, 
        +  int  digits, 
        +  DdApaNumber  number 
        +)
        +
        +
        Prints an arbitrary precision integer in hexadecimal format. + Returns 1 if successful; 0 otherwise. +

        + +

        Side Effects None +

        + +

        See Also Cudd_ApaPrintDecimal +Cudd_ApaPrintExponential + + +
        Defined in cuddApa.c + +
        +
        +int 
        +Cudd_ApaPrintMintermExp(
        +  FILE * fp, 
        +  DdManager * dd, 
        +  DdNode * node, 
        +  int  nvars, 
        +  int  precision 
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        See Also Cudd_ApaPrintMinterm + + +
        Defined in cuddApa.c + +
        +
        +int 
        +Cudd_ApaPrintMinterm(
        +  FILE * fp, 
        +  DdManager * dd, 
        +  DdNode * node, 
        +  int  nvars 
        +)
        +
        +
        Prints the number of minterms of a BDD or ADD using + arbitrary precision arithmetic. Returns 1 if successful; 0 otherwise. +

        + +

        Side Effects None +

        + +

        See Also Cudd_ApaPrintMintermExp + + +
        Defined in cuddApa.c + +
        +
        +void 
        +Cudd_ApaSetToLiteral(
        +  int  digits, 
        +  DdApaNumber  number, 
        +  DdApaDigit  literal 
        +)
        +
        +
        Sets an arbitrary precision integer to a one-digit literal. +

        + +

        Side Effects The result is returned in parameter number. +

        + +

        Defined in cuddApa.c + +
        +
        +void 
        +Cudd_ApaShiftRight(
        +  int  digits, 
        +  DdApaDigit  in, 
        +  DdApaNumber  a, 
        +  DdApaNumber  b 
        +)
        +
        +
        Shifts right an arbitrary precision integer by one + binary place. The most significant binary digit of the result is + taken from parameter in. +

        + +

        Side Effects The result is returned in parameter b. +

        + +

        Defined in cuddApa.c + +
        +
        +DdApaDigit 
        +Cudd_ApaShortDivision(
        +  int  digits, 
        +  DdApaNumber  dividend, 
        +  DdApaDigit  divisor, 
        +  DdApaNumber  quotient 
        +)
        +
        +
        Divides an arbitrary precision integer by a digit. +

        + +

        Side Effects The quotient is returned in parameter quotient. +

        + +

        Defined in cuddApa.c + +
        +
        +DdApaDigit 
        +Cudd_ApaSubtract(
        +  int  digits, 
        +  DdApaNumber  a, 
        +  DdApaNumber  b, 
        +  DdApaNumber  diff 
        +)
        +
        +
        Subtracts two arbitrary precision integers. Returns the + borrow out of the most significant digit. +

        + +

        Side Effects The result of the subtraction is stored in parameter + diff. +

        + +

        Defined in cuddApa.c + +
        +
        +void 
        +Cudd_AutodynDisableZdd(
        +  DdManager * unique 
        +)
        +
        +
        Disables automatic dynamic reordering of ZDDs. +

        + +

        Side Effects None +

        + +

        See Also Cudd_AutodynEnableZdd +Cudd_ReorderingStatusZdd +Cudd_AutodynDisable + + +
        Defined in cuddAPI.c + +
        +
        +void 
        +Cudd_AutodynDisable(
        +  DdManager * unique 
        +)
        +
        +
        Disables automatic dynamic reordering. +

        + +

        Side Effects None +

        + +

        See Also Cudd_AutodynEnable +Cudd_ReorderingStatus +Cudd_AutodynDisableZdd + + +
        Defined in cuddAPI.c + +
        +
        +void 
        +Cudd_AutodynEnableZdd(
        +  DdManager * unique, 
        +  Cudd_ReorderingType  method 
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        See Also Cudd_AutodynDisableZdd +Cudd_ReorderingStatusZdd +Cudd_AutodynEnable + + +
        Defined in cuddAPI.c + +
        +
        +void 
        +Cudd_AutodynEnable(
        +  DdManager * unique, 
        +  Cudd_ReorderingType  method 
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        See Also Cudd_AutodynDisable +Cudd_ReorderingStatus +Cudd_AutodynEnableZdd + + +
        Defined in cuddAPI.c + +
        +
        +double 
        +Cudd_AverageDistance(
        +  DdManager * dd 
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        Defined in cuddUtil.c + +
        +
        +DdNode * 
        +Cudd_BddToAdd(
        +  DdManager * dd, 
        +  DdNode * B 
        +)
        +
        +
        Converts a BDD to a 0-1 ADD. Returns a pointer to the + resulting ADD if successful; NULL otherwise. +

        + +

        Side Effects None +

        + +

        See Also Cudd_addBddPattern +Cudd_addBddThreshold +Cudd_addBddInterval +Cudd_addBddStrictThreshold + + +
        Defined in cuddBridge.c + +
        +
        +int 
        +Cudd_BddToCubeArray(
        +  DdManager * dd, 
        +  DdNode * cube, 
        +  int * array 
        +)
        +
        +
        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. +

        + +

        Side Effects The result is in the array passed by reference. +

        + +

        See Also Cudd_CubeArrayToBdd + + +
        Defined in cuddUtil.c + +
        +
        +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
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        See Also Cudd_SupersetHeavyBranch +Cudd_SupersetShortPaths +Cudd_RemapOverApprox +Cudd_BiasedUnderApprox +Cudd_ReadSize + + +
        Defined in cuddApprox.c + +
        +
        +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
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        See Also Cudd_SubsetShortPaths +Cudd_SubsetHeavyBranch +Cudd_UnderApprox +Cudd_RemapUnderApprox +Cudd_ReadSize + + +
        Defined in cuddApprox.c + +
        +
        +DdNode * 
        +Cudd_CProjection(
        +  DdManager * dd, 
        +  DdNode * R, 
        +  DdNode * Y 
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        See Also Cudd_PrioritySelect + + +
        Defined in cuddPriority.c + +
        +
        +int 
        +Cudd_CheckKeys(
        +  DdManager * table 
        +)
        +
        +
        Checks for the following conditions: +
          +
        • Wrong sizes of subtables. +
        • Wrong number of keys found in unique subtable. +
        • Wrong number of dead found in unique subtable. +
        • Wrong number of keys found in the constant table +
        • Wrong number of dead found in the constant table +
        • Wrong number of total slots found +
        • Wrong number of maximum keys found +
        • Wrong number of total dead found +
        + Reports the average length of non-empty lists. Returns the number of + subtables for which the number of keys is wrong. +

        + +

        Side Effects None +

        + +

        See Also Cudd_DebugCheck + + +
        Defined in cuddCheck.c + +
        +
        +int 
        +Cudd_CheckZeroRef(
        +  DdManager * manager 
        +)
        +
        +
        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.) +

        + +

        Side Effects None +

        + +

        Defined in cuddRef.c + +
        +
        +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
        +)
        +
        +
        Classifies the variables in the support of two DDs + f and g, depending on whther they appear + in both DDs, only in f, or only in g. + Returns 1 if successful; 0 otherwise. +

        + +

        Side Effects The cubes of the three classes of variables are + returned as side effects. +

        + +

        See Also Cudd_Support +Cudd_VectorSupport + + +
        Defined in cuddUtil.c + +
        +
        +void 
        +Cudd_ClearErrorCode(
        +  DdManager * dd 
        +)
        +
        +
        Clear the error code of a manager. +

        + +

        Side Effects None +

        + +

        See Also Cudd_ReadErrorCode + + +
        Defined in cuddAPI.c + +
        +
        +double * 
        +Cudd_CofMinterm(
        +  DdManager * dd, 
        +  DdNode * node 
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        Defined in cuddSign.c + +
        +
        +DdNode * 
        +Cudd_Cofactor(
        +  DdManager * dd, 
        +  DdNode * f, 
        +  DdNode * g 
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        See Also Cudd_bddConstrain +Cudd_bddRestrict + + +
        Defined in cuddCof.c + +
        +
        +int 
        +Cudd_CountLeaves(
        +  DdNode * node 
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        See Also Cudd_PrintDebug + + +
        Defined in cuddUtil.c + +
        +
        +double 
        +Cudd_CountMinterm(
        +  DdManager * manager, 
        +  DdNode * node, 
        +  int  nvars 
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        See Also Cudd_PrintDebug +Cudd_CountPath + + +
        Defined in cuddUtil.c + +
        +
        +double 
        +Cudd_CountPathsToNonZero(
        +  DdNode * node 
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        See Also Cudd_CountMinterm +Cudd_CountPath + + +
        Defined in cuddUtil.c + +
        +
        +double 
        +Cudd_CountPath(
        +  DdNode * node 
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        See Also Cudd_CountMinterm + + +
        Defined in cuddUtil.c + +
        +
        +DdNode * 
        +Cudd_CubeArrayToBdd(
        +  DdManager * dd, 
        +  int * array 
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        See Also Cudd_bddComputeCube +Cudd_IndicesToCube +Cudd_BddToCubeArray + + +
        Defined in cuddUtil.c + +
        +
        +int 
        +Cudd_DagSize(
        +  DdNode * node 
        +)
        +
        +
        Counts the number of nodes in a DD. Returns the number + of nodes in the graph rooted at node. +

        + +

        Side Effects None +

        + +

        See Also Cudd_SharingSize +Cudd_PrintDebug + + +
        Defined in cuddUtil.c + +
        +
        +int 
        +Cudd_DeadAreCounted(
        +  DdManager * dd 
        +)
        +
        +
        Tells whether dead nodes are counted towards triggering + reordering. Returns 1 if dead nodes are counted; 0 otherwise. +

        + +

        Side Effects None +

        + +

        See Also Cudd_TurnOnCountDead +Cudd_TurnOffCountDead + + +
        Defined in cuddAPI.c + +
        +
        +int 
        +Cudd_DebugCheck(
        +  DdManager * table 
        +)
        +
        +
        Checks for inconsistencies in the DD heap: +
          +
        • node has illegal index +
        • live node has dead children +
        • node has illegal Then or Else pointers +
        • BDD/ADD node has identical children +
        • ZDD node has zero then child +
        • wrong number of total nodes +
        • wrong number of dead nodes +
        • ref count error at node +
        + Returns 0 if no inconsistencies are found; DD_OUT_OF_MEM if there is + not enough memory; 1 otherwise. +

        + +

        Side Effects None +

        + +

        See Also Cudd_CheckKeys + + +
        Defined in cuddCheck.c + +
        +
        +DdNode * 
        +Cudd_Decreasing(
        +  DdManager * dd, 
        +  DdNode * f, 
        +  int  i 
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        See Also Cudd_Increasing + + +
        Defined in cuddSat.c + +
        +
        +void 
        +Cudd_DelayedDerefBdd(
        +  DdManager * table, 
        +  DdNode * n 
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        See Also Cudd_RecursiveDeref +Cudd_IterDerefBdd + + +
        Defined in cuddRef.c + +
        +
        +double 
        +Cudd_Density(
        +  DdManager * dd, manager
        +  DdNode * f, function whose density is sought
        +  int  nvars size of the support of f
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        See Also Cudd_CountMinterm +Cudd_DagSize + + +
        Defined in cuddUtil.c + +
        +
        +void 
        +Cudd_Deref(
        +  DdNode * node 
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        See Also Cudd_RecursiveDeref +Cudd_RecursiveDerefZdd +Cudd_Ref + + +
        Defined in cuddRef.c + +
        +
        +void 
        +Cudd_DisableGarbageCollection(
        +  DdManager * dd 
        +)
        +
        +
        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.) +

        + +

        Side Effects None +

        + +

        See Also Cudd_EnableGarbageCollection +Cudd_GarbageCollectionEnabled + + +
        Defined in cuddAPI.c + +
        +
        +int 
        +Cudd_DisableReorderingReporting(
        +  DdManager * dd 
        +)
        +
        +
        Disables reporting of reordering stats. + Returns 1 if successful; 0 otherwise. +

        + +

        Side Effects Removes functions from the pre-reordering and post-reordering + hooks. +

        + +

        See Also Cudd_EnableReorderingReporting +Cudd_ReorderingReporting + + +
        Defined in cuddAPI.c + +
        +
        +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
        +)
        +
        +
        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]. +

        + +

        Side Effects None +

        + +

        See Also Cudd_Xgty + + +
        Defined in cuddPriority.c + +
        +
        +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
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        See Also Cudd_DumpBlif +Cudd_DumpDot +Cudd_PrintDebug +Cudd_DumpDDcal +Cudd_DumpDaVinci +Cudd_DumpFactoredForm + + +
        Defined in cuddExport.c + +
        +
        +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
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        See Also Cudd_DumpBlifBody +Cudd_DumpDot +Cudd_PrintDebug +Cudd_DumpDDcal +Cudd_DumpDaVinci +Cudd_DumpFactoredForm + + +
        Defined in cuddExport.c + +
        +
        +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
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        See Also Cudd_DumpDot +Cudd_PrintDebug +Cudd_DumpBlif +Cudd_DumpDaVinci +Cudd_DumpFactoredForm + + +
        Defined in cuddExport.c + +
        +
        +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
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        See Also Cudd_DumpDot +Cudd_PrintDebug +Cudd_DumpBlif +Cudd_DumpDDcal +Cudd_DumpFactoredForm + + +
        Defined in cuddExport.c + +
        +
        +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
        +)
        +
        +
        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: +
          +
        • solid line: THEN arcs; +
        • dotted line: complement arcs; +
        • dashed line: regular ELSE arcs. +
        + The dot options are chosen so that the drawing fits on a letter-size + sheet. +

        + +

        Side Effects None +

        + +

        See Also Cudd_DumpBlif +Cudd_PrintDebug +Cudd_DumpDDcal +Cudd_DumpDaVinci +Cudd_DumpFactoredForm + + +
        Defined in cuddExport.c + +
        +
        +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
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        See Also Cudd_DumpDot +Cudd_PrintDebug +Cudd_DumpBlif +Cudd_DumpDaVinci +Cudd_DumpDDcal + + +
        Defined in cuddExport.c + +
        +
        +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
        +)
        +
        +
        This function generates a BDD for the function d(x,y) + > 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]. +

        + +

        Side Effects None +

        + +

        See Also Cudd_PrioritySelect +Cudd_Dxygtdyz +Cudd_Xgty +Cudd_bddAdjPermuteX + + +
        Defined in cuddPriority.c + +
        +
        +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
        +)
        +
        +
        This function generates a BDD for the function d(x,y) + > 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]. +

        + +

        Side Effects None +

        + +

        See Also Cudd_PrioritySelect +Cudd_Dxygtdxz +Cudd_Xgty +Cudd_bddAdjPermuteX + + +
        Defined in cuddPriority.c + +
        +
        +void 
        +Cudd_EnableGarbageCollection(
        +  DdManager * dd 
        +)
        +
        +
        Enables garbage collection. Garbage collection is + initially enabled. Therefore it is necessary to call this function + only if garbage collection has been explicitly disabled. +

        + +

        Side Effects None +

        + +

        See Also Cudd_DisableGarbageCollection +Cudd_GarbageCollectionEnabled + + +
        Defined in cuddAPI.c + +
        +
        +int 
        +Cudd_EnableReorderingReporting(
        +  DdManager * dd 
        +)
        +
        +
        Enables reporting of reordering stats. + Returns 1 if successful; 0 otherwise. +

        + +

        Side Effects Installs functions in the pre-reordering and post-reordering + hooks. +

        + +

        See Also Cudd_DisableReorderingReporting +Cudd_ReorderingReporting + + +
        Defined in cuddAPI.c + +
        +
        +int 
        +Cudd_EpdCountMinterm(
        +  DdManager * manager, 
        +  DdNode * node, 
        +  int  nvars, 
        +  EpDouble * epd 
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        See Also Cudd_PrintDebug +Cudd_CountPath + + +
        Defined in cuddUtil.c + +
        +
        +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
        +)
        +
        +
        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 pr is positive + the first failure is reported to the standard output. +

        + +

        Side Effects None +

        + +

        Defined in cuddSat.c + +
        +
        +int 
        +Cudd_EquivDC(
        +  DdManager * dd, 
        +  DdNode * F, 
        +  DdNode * G, 
        +  DdNode * D 
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        See Also Cudd_bddLeqUnless + + +
        Defined in cuddSat.c + +
        +
        +int 
        +Cudd_EstimateCofactorSimple(
        +  DdNode * node, 
        +  int  i 
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        See Also Cudd_DagSize + + +
        Defined in cuddUtil.c + +
        +
        +int 
        +Cudd_EstimateCofactor(
        +  DdManager * dd, manager
        +  DdNode * f, function
        +  int  i, index of variable
        +  int  phase 1: positive; 0: negative
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        See Also Cudd_DagSize +Cudd_EstimateCofactorSimple + + +
        Defined in cuddUtil.c + +
        +
        +DdNode * 
        +Cudd_Eval(
        +  DdManager * dd, 
        +  DdNode * f, 
        +  int * inputs 
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        See Also Cudd_bddLeq +Cudd_addEvalConst + + +
        Defined in cuddSat.c + +
        +
        +double 
        +Cudd_ExpectedUsedSlots(
        +  DdManager * dd 
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        See Also Cudd_ReadSlots +Cudd_ReadUsedSlots + + +
        Defined in cuddAPI.c + +
        +
        +DdNode * 
        +Cudd_FindEssential(
        +  DdManager * dd, 
        +  DdNode * f 
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        See Also Cudd_bddIsVarEssential + + +
        Defined in cuddEssent.c + +
        +
        +DdTlcInfo * 
        +Cudd_FindTwoLiteralClauses(
        +  DdManager * dd, 
        +  DdNode * f 
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        See Also Cudd_FindEssential + + +
        Defined in cuddEssent.c + +
        +
        +DdGen * 
        +Cudd_FirstCube(
        +  DdManager * dd, 
        +  DdNode * f, 
        +  int ** cube, 
        +  CUDD_VALUE_TYPE * value 
        +)
        +
        +
        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.

        + 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.

        + 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. +

        + +

        Side Effects The first cube and its value are returned as side effects. +

        + +

        See Also Cudd_ForeachCube +Cudd_NextCube +Cudd_GenFree +Cudd_IsGenEmpty +Cudd_FirstNode + + +
        Defined in cuddUtil.c + +
        +
        +DdGen * 
        +Cudd_FirstNode(
        +  DdManager * dd, 
        +  DdNode * f, 
        +  DdNode ** node 
        +)
        +
        +
        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. +

        + +

        Side Effects The first node is returned as a side effect. +

        + +

        See Also Cudd_ForeachNode +Cudd_NextNode +Cudd_GenFree +Cudd_IsGenEmpty +Cudd_FirstCube + + +
        Defined in cuddUtil.c + +
        +
        +DdGen * 
        +Cudd_FirstPrime(
        +  DdManager * dd, 
        +  DdNode * l, 
        +  DdNode * u, 
        +  int ** cube 
        +)
        +
        +
        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.

        + + 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.

        + + 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.

        + + This iterator can only be used on BDDs. +

        + +

        Side Effects The first cube is returned as side effect. +

        + +

        See Also Cudd_ForeachPrime +Cudd_NextPrime +Cudd_GenFree +Cudd_IsGenEmpty +Cudd_FirstCube +Cudd_FirstNode + + +
        Defined in cuddUtil.c + +
        +
        +void 
        +Cudd_FreeTree(
        +  DdManager * dd 
        +)
        +
        +
        Frees the variable group tree of the manager. +

        + +

        Side Effects None +

        + +

        See Also Cudd_SetTree +Cudd_ReadTree +Cudd_FreeZddTree + + +
        Defined in cuddAPI.c + +
        +
        +void 
        +Cudd_FreeZddTree(
        +  DdManager * dd 
        +)
        +
        +
        Frees the variable group tree of the manager. +

        + +

        Side Effects None +

        + +

        See Also Cudd_SetZddTree +Cudd_ReadZddTree +Cudd_FreeTree + + +
        Defined in cuddAPI.c + +
        +
        +int 
        +Cudd_GarbageCollectionEnabled(
        +  DdManager * dd 
        +)
        +
        +
        Returns 1 if garbage collection is enabled; 0 otherwise. +

        + +

        Side Effects None +

        + +

        See Also Cudd_EnableGarbageCollection +Cudd_DisableGarbageCollection + + +
        Defined in cuddAPI.c + +
        +
        +int 
        +Cudd_GenFree(
        +  DdGen * gen 
        +)
        +
        +
        Frees a CUDD generator. Always returns 0, so that it can + be used in mis-like foreach constructs. +

        + +

        Side Effects None +

        + +

        See Also Cudd_ForeachCube +Cudd_ForeachNode +Cudd_FirstCube +Cudd_NextCube +Cudd_FirstNode +Cudd_NextNode +Cudd_IsGenEmpty + + +
        Defined in cuddUtil.c + +
        +
        +DdNode * 
        +Cudd_Increasing(
        +  DdManager * dd, 
        +  DdNode * f, 
        +  int  i 
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        See Also Cudd_Decreasing + + +
        Defined in cuddSat.c + +
        +
        +DdNode * 
        +Cudd_IndicesToCube(
        +  DdManager * dd, 
        +  int * array, 
        +  int  n 
        +)
        +
        +
        Builds a cube of BDD variables from an array of indices. + Returns a pointer to the result if successful; NULL otherwise. +

        + +

        Side Effects None +

        + +

        See Also Cudd_bddComputeCube +Cudd_CubeArrayToBdd + + +
        Defined in cuddUtil.c + +
        +
        +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
        +)
        +
        +
        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]. +

        + +

        Side Effects None +

        + +

        See Also Cudd_Xgty + + +
        Defined in cuddPriority.c + +
        +
        +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
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        See Also Cudd_Quit + + +
        Defined in cuddInit.c + +
        +
        +int 
        +Cudd_IsGenEmpty(
        +  DdGen * gen 
        +)
        +
        +
        Queries the status of a generator. Returns 1 if the + generator is empty or NULL; 0 otherswise. +

        + +

        Side Effects None +

        + +

        See Also Cudd_ForeachCube +Cudd_ForeachNode +Cudd_FirstCube +Cudd_NextCube +Cudd_FirstNode +Cudd_NextNode +Cudd_GenFree + + +
        Defined in cuddUtil.c + +
        +
        +int 
        +Cudd_IsInHook(
        +  DdManager * dd, 
        +  DD_HFP  f, 
        +  Cudd_HookType  where 
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        See Also Cudd_AddHook +Cudd_RemoveHook + + +
        Defined in cuddAPI.c + +
        +
        +int 
        +Cudd_IsNonConstant(
        +  DdNode * f 
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        See Also Cudd_IsConstant +Cudd_bddIteConstant +Cudd_addIteConstant +Cudd_addEvalConst + + +
        Defined in cuddAPI.c + +
        +
        +void 
        +Cudd_IterDerefBdd(
        +  DdManager * table, 
        +  DdNode * n 
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        See Also Cudd_RecursiveDeref +Cudd_DelayedDerefBdd + + +
        Defined in cuddRef.c + +
        +
        +DdNode * 
        +Cudd_LargestCube(
        +  DdManager * manager, 
        +  DdNode * f, 
        +  int * length 
        +)
        +
        +
        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. +

        + +

        Side Effects The number of literals of the cube is returned in length. +

        + +

        See Also Cudd_ShortestPath + + +
        Defined in cuddSat.c + +
        +
        +DdNode	* 
        +Cudd_MakeBddFromZddCover(
        +  DdManager * dd, 
        +  DdNode * node 
        +)
        +
        +
        Converts a ZDD cover to a BDD graph. If successful, it + returns a BDD node, otherwise it returns NULL. +

        + +

        See Also cuddMakeBddFromZddCover + + +
        Defined in cuddZddIsop.c + +
        +
        +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
        +)
        +
        +
        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. +

        + +

        Side Effects The variable tree is changed. +

        + +

        See Also Cudd_MakeZddTreeNode + + +
        Defined in cuddGroup.c + +
        +
        +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
        +)
        +
        +
        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. +

        + +

        Side Effects The ZDD variable tree is changed. +

        + +

        See Also Cudd_MakeTreeNode + + +
        Defined in cuddZddGroup.c + +
        +
        +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
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        See Also Cudd_addHamming +Cudd_bddClosestCube + + +
        Defined in cuddPriority.c + +
        +
        +DdApaNumber 
        +Cudd_NewApaNumber(
        +  int  digits 
        +)
        +
        +
        Allocates memory for an arbitrary precision + integer. Returns a pointer to the allocated memory if successful; + NULL otherwise. +

        + +

        Side Effects None +

        + +

        Defined in cuddApa.c + +
        +
        +int 
        +Cudd_NextCube(
        +  DdGen * gen, 
        +  int ** cube, 
        +  CUDD_VALUE_TYPE * value 
        +)
        +
        +
        Generates the next cube of a decision diagram onset, + using generator gen. Returns 0 if the enumeration is completed; 1 + otherwise. +

        + +

        Side Effects The cube and its value are returned as side effects. The + generator is modified. +

        + +

        See Also Cudd_ForeachCube +Cudd_FirstCube +Cudd_GenFree +Cudd_IsGenEmpty +Cudd_NextNode + + +
        Defined in cuddUtil.c + +
        +
        +int 
        +Cudd_NextNode(
        +  DdGen * gen, 
        +  DdNode ** node 
        +)
        +
        +
        Finds the node of a decision diagram, using generator + gen. Returns 0 if the enumeration is completed; 1 otherwise. +

        + +

        Side Effects The next node is returned as a side effect. +

        + +

        See Also Cudd_ForeachNode +Cudd_FirstNode +Cudd_GenFree +Cudd_IsGenEmpty +Cudd_NextCube + + +
        Defined in cuddUtil.c + +
        +
        +int 
        +Cudd_NextPrime(
        +  DdGen * gen, 
        +  int ** cube 
        +)
        +
        +
        Generates the next cube of a Boolean function, + using generator gen. Returns 0 if the enumeration is completed; 1 + otherwise. +

        + +

        Side Effects The cube and is returned as side effects. The + generator is modified. +

        + +

        See Also Cudd_ForeachPrime +Cudd_FirstPrime +Cudd_GenFree +Cudd_IsGenEmpty +Cudd_NextCube +Cudd_NextNode + + +
        Defined in cuddUtil.c + +
        +
        +unsigned int 
        +Cudd_NodeReadIndex(
        +  DdNode * node 
        +)
        +
        +
        Returns the index of the node. The node pointer can be + either regular or complemented. +

        + +

        Side Effects None +

        + +

        See Also Cudd_ReadIndex + + +
        Defined in cuddAPI.c + +
        +
        +void 
        +Cudd_OutOfMem(
        +  long  size size of the allocation that failed
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        Defined in cuddUtil.c + +
        +
        +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
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        See Also Cudd_SupersetHeavyBranch +Cudd_SupersetShortPaths +Cudd_ReadSize + + +
        Defined in cuddApprox.c + +
        +
        +unsigned int 
        +Cudd_Prime(
        +  unsigned int  p 
        +)
        +
        +
        Returns the next prime >= p. +

        + +

        Side Effects None +

        + +

        Defined in cuddTable.c + +
        +
        +int 
        +Cudd_PrintDebug(
        +  DdManager * dd, 
        +  DdNode * f, 
        +  int  n, 
        +  int  pr 
        +)
        +
        +
        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 > 0. Specifically: +
          +
        • pr = 0 : prints nothing +
        • pr = 1 : prints counts of nodes and minterms +
        • pr = 2 : prints counts + disjoint sum of product +
        • pr = 3 : prints counts + list of nodes +
        • pr > 3 : prints counts + disjoint sum of product + list of nodes +
        + For the purpose of counting the number of minterms, the function is + supposed to depend on n variables. Returns 1 if successful; 0 otherwise. +

        + +

        Side Effects None +

        + +

        See Also Cudd_DagSize +Cudd_CountLeaves +Cudd_CountMinterm +Cudd_PrintMinterm + + +
        Defined in cuddUtil.c + +
        +
        +int 
        +Cudd_PrintInfo(
        +  DdManager * dd, 
        +  FILE * fp 
        +)
        +
        +
        Prints out statistics and settings for a CUDD manager. + Returns 1 if successful; 0 otherwise. +

        + +

        Side Effects None +

        + +

        Defined in cuddAPI.c + +
        +
        +int 
        +Cudd_PrintLinear(
        +  DdManager * table 
        +)
        +
        +
        Prints the linear transform matrix. Returns 1 in case of + success; 0 otherwise. +

        + +

        Side Effects none +

        + +

        Defined in cuddLinear.c + +
        +
        +int 
        +Cudd_PrintMinterm(
        +  DdManager * manager, 
        +  DdNode * node 
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        See Also Cudd_PrintDebug +Cudd_bddPrintCover + + +
        Defined in cuddUtil.c + +
        +
        +int 
        +Cudd_PrintTwoLiteralClauses(
        +  DdManager * dd, 
        +  DdNode * f, 
        +  char ** names, 
        +  FILE * fp 
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        See Also Cudd_FindTwoLiteralClauses + + +
        Defined in cuddEssent.c + +
        +
        +void 
        +Cudd_PrintVersion(
        +  FILE * fp 
        +)
        +
        +
        Prints the package version number. +

        + +

        Side Effects None +

        + +

        Defined in cuddUtil.c + +
        +
        +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
        +)
        +
        +
        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: +
          +
        • When extracting representatives from an equivalence relation, + Cudd_CProjection has the advantage of nor requiring the auxiliary + variables. +
        • 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). +
        +

        + +

        Side Effects If called with z == NULL, will create new variables in + the manager. +

        + +

        See Also Cudd_Dxygtdxz +Cudd_Dxygtdyz +Cudd_Xgty +Cudd_bddAdjPermuteX +Cudd_CProjection + + +
        Defined in cuddPriority.c + +
        +
        +void 
        +Cudd_Quit(
        +  DdManager * unique 
        +)
        +
        +
        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.) +

        + +

        Side Effects None +

        + +

        See Also Cudd_Init + + +
        Defined in cuddInit.c + +
        +
        +long 
        +Cudd_Random(
        +    
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        See Also Cudd_Srandom + + +
        Defined in cuddUtil.c + +
        +
        +int 
        +Cudd_ReadArcviolation(
        +  DdManager * dd 
        +)
        +
        +
        Returns the current value of the arcviolation + parameter. This parameter is used in group sifting to decide how + many arcs into y not coming from x 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. +

        + +

        Side Effects None +

        + +

        See Also Cudd_SetArcviolation + + +
        Defined in cuddAPI.c + +
        +
        +DdNode * 
        +Cudd_ReadBackground(
        +  DdManager * dd 
        +)
        +
        +
        Reads the background constant of the manager. +

        + +

        Side Effects None +

        + +

        Defined in cuddAPI.c + +
        +
        +double 
        +Cudd_ReadCacheHits(
        +  DdManager * dd 
        +)
        +
        +
        Returns the number of cache hits. +

        + +

        Side Effects None +

        + +

        See Also Cudd_ReadCacheLookUps + + +
        Defined in cuddAPI.c + +
        +
        +double 
        +Cudd_ReadCacheLookUps(
        +  DdManager * dd 
        +)
        +
        +
        Returns the number of cache look-ups. +

        + +

        Side Effects None +

        + +

        See Also Cudd_ReadCacheHits + + +
        Defined in cuddAPI.c + +
        +
        +unsigned int 
        +Cudd_ReadCacheSlots(
        +  DdManager * dd 
        +)
        +
        +
        Reads the number of slots in the cache. +

        + +

        Side Effects None +

        + +

        See Also Cudd_ReadCacheUsedSlots + + +
        Defined in cuddAPI.c + +
        +
        +double 
        +Cudd_ReadCacheUsedSlots(
        +  DdManager * dd 
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        See Also Cudd_ReadCacheSlots + + +
        Defined in cuddAPI.c + +
        +
        +unsigned int 
        +Cudd_ReadDead(
        +  DdManager * dd 
        +)
        +
        +
        Returns the number of dead nodes in the unique table. +

        + +

        Side Effects None +

        + +

        See Also Cudd_ReadKeys + + +
        Defined in cuddAPI.c + +
        +
        +CUDD_VALUE_TYPE 
        +Cudd_ReadEpsilon(
        +  DdManager * dd 
        +)
        +
        +
        Reads the epsilon parameter of the manager. The epsilon + parameter control the comparison between floating point numbers. +

        + +

        Side Effects None +

        + +

        See Also Cudd_SetEpsilon + + +
        Defined in cuddAPI.c + +
        +
        +Cudd_ErrorType 
        +Cudd_ReadErrorCode(
        +  DdManager * dd 
        +)
        +
        +
        Returns the code of the last error. The error codes are + defined in cudd.h. +

        + +

        Side Effects None +

        + +

        See Also Cudd_ClearErrorCode + + +
        Defined in cuddAPI.c + +
        +
        +long 
        +Cudd_ReadGarbageCollectionTime(
        +  DdManager * dd 
        +)
        +
        +
        Returns the number of milliseconds spent doing garbage + collection since the manager was initialized. +

        + +

        Side Effects None +

        + +

        See Also Cudd_ReadGarbageCollections + + +
        Defined in cuddAPI.c + +
        +
        +int 
        +Cudd_ReadGarbageCollections(
        +  DdManager * dd 
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        See Also Cudd_ReadGarbageCollectionTime + + +
        Defined in cuddAPI.c + +
        +
        +Cudd_AggregationType 
        +Cudd_ReadGroupcheck(
        +  DdManager * dd 
        +)
        +
        +
        Reads the groupcheck parameter of the manager. The + groupcheck parameter determines the aggregation criterion in group + sifting. +

        + +

        Side Effects None +

        + +

        See Also Cudd_SetGroupcheck + + +
        Defined in cuddAPI.c + +
        +
        +int 
        +Cudd_ReadInvPermZdd(
        +  DdManager * dd, 
        +  int  i 
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        See Also Cudd_ReadPerm +Cudd_ReadInvPermZdd + + +
        Defined in cuddAPI.c + +
        +
        +int 
        +Cudd_ReadInvPerm(
        +  DdManager * dd, 
        +  int  i 
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        See Also Cudd_ReadPerm +Cudd_ReadInvPermZdd + + +
        Defined in cuddAPI.c + +
        +
        +int 
        +Cudd_ReadIthClause(
        +  DdTlcInfo * tlc, 
        +  int  i, 
        +  DdHalfWord * var1, 
        +  DdHalfWord * var2, 
        +  int * phase1, 
        +  int * phase2 
        +)
        +
        +
        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. +

        + +

        Side Effects the four components of a clause are returned as side effects. +

        + +

        See Also Cudd_FindTwoLiteralClauses + + +
        Defined in cuddEssent.c + +
        +
        +unsigned int 
        +Cudd_ReadKeys(
        +  DdManager * dd 
        +)
        +
        +
        Returns the total number of nodes currently in the unique + table, including the dead nodes. +

        + +

        Side Effects None +

        + +

        See Also Cudd_ReadDead + + +
        Defined in cuddAPI.c + +
        +
        +int 
        +Cudd_ReadLinear(
        +  DdManager * table, CUDD manager
        +  int  x, row index
        +  int  y column index
        +)
        +
        +
        Reads an entry of the linear transform matrix. +

        + +

        Side Effects none +

        + +

        Defined in cuddLinear.c + +
        +
        +DdNode * 
        +Cudd_ReadLogicZero(
        +  DdManager * dd 
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        See Also Cudd_ReadOne +Cudd_ReadZero + + +
        Defined in cuddAPI.c + +
        +
        +unsigned int 
        +Cudd_ReadLooseUpTo(
        +  DdManager * dd 
        +)
        +
        +
        Reads the looseUpTo parameter of the manager. +

        + +

        Side Effects None +

        + +

        See Also Cudd_SetLooseUpTo +Cudd_ReadMinHit +Cudd_ReadMinDead + + +
        Defined in cuddAPI.c + +
        +
        +unsigned int 
        +Cudd_ReadMaxCacheHard(
        +  DdManager * dd 
        +)
        +
        +
        Reads the maxCacheHard parameter of the manager. +

        + +

        Side Effects None +

        + +

        See Also Cudd_SetMaxCacheHard +Cudd_ReadMaxCache + + +
        Defined in cuddAPI.c + +
        +
        +unsigned int 
        +Cudd_ReadMaxCache(
        +  DdManager * dd 
        +)
        +
        +
        Returns the soft limit for the cache size. The soft limit +

        + +

        Side Effects None +

        + +

        See Also Cudd_ReadMaxCache + + +
        Defined in cuddAPI.c + +
        +
        +double 
        +Cudd_ReadMaxGrowthAlternate(
        +  DdManager * dd 
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        See Also Cudd_ReadMaxGrowth +Cudd_SetMaxGrowthAlternate +Cudd_SetReorderingCycle +Cudd_ReadReorderingCycle + + +
        Defined in cuddAPI.c + +
        +
        +double 
        +Cudd_ReadMaxGrowth(
        +  DdManager * dd 
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        See Also Cudd_SetMaxGrowth +Cudd_ReadMaxGrowthAlternate + + +
        Defined in cuddAPI.c + +
        +
        +unsigned int 
        +Cudd_ReadMaxLive(
        +  DdManager * dd 
        +)
        +
        +
        Reads the maximum allowed number of live nodes. When this + number is exceeded, the package returns NULL. +

        + +

        Side Effects none +

        + +

        See Also Cudd_SetMaxLive + + +
        Defined in cuddAPI.c + +
        +
        +unsigned long 
        +Cudd_ReadMaxMemory(
        +  DdManager * dd 
        +)
        +
        +
        Reads the maximum allowed memory. When this + number is exceeded, the package returns NULL. +

        + +

        Side Effects none +

        + +

        See Also Cudd_SetMaxMemory + + +
        Defined in cuddAPI.c + +
        +
        +unsigned long 
        +Cudd_ReadMemoryInUse(
        +  DdManager * dd 
        +)
        +
        +
        Returns the memory in use by the manager measured in bytes. +

        + +

        Side Effects None +

        + +

        Defined in cuddAPI.c + +
        +
        +unsigned int 
        +Cudd_ReadMinDead(
        +  DdManager * dd 
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        See Also Cudd_ReadDead +Cudd_ReadLooseUpTo +Cudd_SetLooseUpTo + + +
        Defined in cuddAPI.c + +
        +
        +unsigned int 
        +Cudd_ReadMinHit(
        +  DdManager * dd 
        +)
        +
        +
        Reads the hit rate that causes resizinig of the computed + table. +

        + +

        Side Effects None +

        + +

        See Also Cudd_SetMinHit + + +
        Defined in cuddAPI.c + +
        +
        +DdNode * 
        +Cudd_ReadMinusInfinity(
        +  DdManager * dd 
        +)
        +
        +
        Reads the minus-infinity constant from the manager. +

        + +

        Side Effects None +

        + +

        Defined in cuddAPI.c + +
        +
        +unsigned int 
        +Cudd_ReadNextReordering(
        +  DdManager * dd 
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        See Also Cudd_SetNextReordering + + +
        Defined in cuddAPI.c + +
        +
        +long 
        +Cudd_ReadNodeCount(
        +  DdManager * dd 
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        See Also Cudd_ReadPeakNodeCount +Cudd_zddReadNodeCount + + +
        Defined in cuddAPI.c + +
        +
        +double 
        +Cudd_ReadNodesDropped(
        +  DdManager * dd 
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        See Also Cudd_ReadNodesFreed + + +
        Defined in cuddAPI.c + +
        +
        +double 
        +Cudd_ReadNodesFreed(
        +  DdManager * dd 
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        See Also Cudd_ReadNodesDropped + + +
        Defined in cuddAPI.c + +
        +
        +int 
        +Cudd_ReadNumberXovers(
        +  DdManager * dd 
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        See Also Cudd_SetNumberXovers + + +
        Defined in cuddAPI.c + +
        +
        +DdNode * 
        +Cudd_ReadOne(
        +  DdManager * dd 
        +)
        +
        +
        Returns the one constant of the manager. The one + constant is common to ADDs and BDDs. +

        + +

        Side Effects None +

        + +

        See Also Cudd_ReadZero +Cudd_ReadLogicZero +Cudd_ReadZddOne + + +
        Defined in cuddAPI.c + +
        +
        +int 
        +Cudd_ReadPeakLiveNodeCount(
        +  DdManager * dd 
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        See Also Cudd_ReadNodeCount +Cudd_PrintInfo +Cudd_ReadPeakNodeCount + + +
        Defined in cuddAPI.c + +
        +
        +long 
        +Cudd_ReadPeakNodeCount(
        +  DdManager * dd 
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        See Also Cudd_ReadNodeCount +Cudd_PrintInfo + + +
        Defined in cuddAPI.c + +
        +
        +int 
        +Cudd_ReadPermZdd(
        +  DdManager * dd, 
        +  int  i 
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        See Also Cudd_ReadInvPermZdd +Cudd_ReadPerm + + +
        Defined in cuddAPI.c + +
        +
        +int 
        +Cudd_ReadPerm(
        +  DdManager * dd, 
        +  int  i 
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        See Also Cudd_ReadInvPerm +Cudd_ReadPermZdd + + +
        Defined in cuddAPI.c + +
        +
        +DdNode * 
        +Cudd_ReadPlusInfinity(
        +  DdManager * dd 
        +)
        +
        +
        Reads the plus-infinity constant from the manager. +

        + +

        Side Effects None +

        + +

        Defined in cuddAPI.c + +
        +
        +int 
        +Cudd_ReadPopulationSize(
        +  DdManager * dd 
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        See Also Cudd_SetPopulationSize + + +
        Defined in cuddAPI.c + +
        +
        +int 
        +Cudd_ReadRecomb(
        +  DdManager * dd 
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        See Also Cudd_SetRecomb + + +
        Defined in cuddAPI.c + +
        +
        +double 
        +Cudd_ReadRecursiveCalls(
        +  DdManager * dd 
        +)
        +
        +
        Returns the number of recursive calls if the package is + compiled with DD_COUNT defined. +

        + +

        Side Effects None +

        + +

        Defined in cuddAPI.c + +
        +
        +int 
        +Cudd_ReadReorderingCycle(
        +  DdManager * dd 
        +)
        +
        +
        Reads the reordCycle parameter of the manager. This + parameter determines how often the alternate threshold on maximum + growth is used in reordering. +

        + +

        Side Effects None +

        + +

        See Also Cudd_ReadMaxGrowthAlternate +Cudd_SetMaxGrowthAlternate +Cudd_SetReorderingCycle + + +
        Defined in cuddAPI.c + +
        +
        +long 
        +Cudd_ReadReorderingTime(
        +  DdManager * dd 
        +)
        +
        +
        Returns the number of milliseconds spent reordering + variables since the manager was initialized. The time spent in collecting + garbage before reordering is included. +

        + +

        Side Effects None +

        + +

        See Also Cudd_ReadReorderings + + +
        Defined in cuddAPI.c + +
        +
        +int 
        +Cudd_ReadReorderings(
        +  DdManager * dd 
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        See Also Cudd_ReduceHeap +Cudd_ReadReorderingTime + + +
        Defined in cuddAPI.c + +
        +
        +int 
        +Cudd_ReadSiftMaxSwap(
        +  DdManager * dd 
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        See Also Cudd_ReadSiftMaxVar +Cudd_SetSiftMaxSwap + + +
        Defined in cuddAPI.c + +
        +
        +int 
        +Cudd_ReadSiftMaxVar(
        +  DdManager * dd 
        +)
        +
        +
        Reads the siftMaxVar parameter of the manager. This + parameter gives the maximum number of variables that will be sifted + for each invocation of sifting. +

        + +

        Side Effects None +

        + +

        See Also Cudd_ReadSiftMaxSwap +Cudd_SetSiftMaxVar + + +
        Defined in cuddAPI.c + +
        +
        +int 
        +Cudd_ReadSize(
        +  DdManager * dd 
        +)
        +
        +
        Returns the number of BDD variables in existance. +

        + +

        Side Effects None +

        + +

        See Also Cudd_ReadZddSize + + +
        Defined in cuddAPI.c + +
        +
        +unsigned int 
        +Cudd_ReadSlots(
        +  DdManager * dd 
        +)
        +
        +
        Returns the total number of slots of the unique table. + This number ismainly for diagnostic purposes. +

        + +

        Side Effects None +

        + +

        Defined in cuddAPI.c + +
        +
        +FILE * 
        +Cudd_ReadStderr(
        +  DdManager * dd 
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        See Also Cudd_SetStderr +Cudd_ReadStdout + + +
        Defined in cuddAPI.c + +
        +
        +FILE * 
        +Cudd_ReadStdout(
        +  DdManager * dd 
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        See Also Cudd_SetStdout +Cudd_ReadStderr + + +
        Defined in cuddAPI.c + +
        +
        +double 
        +Cudd_ReadSwapSteps(
        +  DdManager * dd 
        +)
        +
        +
        Reads the number of elementary reordering steps. +

        + +

        Side Effects none +

        + +

        Defined in cuddAPI.c + +
        +
        +int 
        +Cudd_ReadSymmviolation(
        +  DdManager * dd 
        +)
        +
        +
        Returns the current value of the symmviolation + parameter. This parameter is used in group sifting to decide how + many violations to the symmetry conditions f10 = f01 or + f11 = f00 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. +

        + +

        Side Effects None +

        + +

        See Also Cudd_SetSymmviolation + + +
        Defined in cuddAPI.c + +
        +
        +MtrNode * 
        +Cudd_ReadTree(
        +  DdManager * dd 
        +)
        +
        +
        Returns the variable group tree of the manager. +

        + +

        Side Effects None +

        + +

        See Also Cudd_SetTree +Cudd_FreeTree +Cudd_ReadZddTree + + +
        Defined in cuddAPI.c + +
        +
        +double 
        +Cudd_ReadUniqueLinks(
        +  DdManager * dd 
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        See Also Cudd_ReadUniqueLookUps + + +
        Defined in cuddAPI.c + +
        +
        +double 
        +Cudd_ReadUniqueLookUps(
        +  DdManager * dd 
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        See Also Cudd_ReadUniqueLinks + + +
        Defined in cuddAPI.c + +
        +
        +double 
        +Cudd_ReadUsedSlots(
        +  DdManager * dd 
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        See Also Cudd_ReadSlots + + +
        Defined in cuddAPI.c + +
        +
        +DdNode * 
        +Cudd_ReadVars(
        +  DdManager * dd, 
        +  int  i 
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        See Also Cudd_bddIthVar + + +
        Defined in cuddAPI.c + +
        +
        +DdNode * 
        +Cudd_ReadZddOne(
        +  DdManager * dd, 
        +  int  i 
        +)
        +
        +
        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 i. +

        + +

        Side Effects None +

        + +

        See Also Cudd_ReadOne + + +
        Defined in cuddAPI.c + +
        +
        +int 
        +Cudd_ReadZddSize(
        +  DdManager * dd 
        +)
        +
        +
        Returns the number of ZDD variables in existance. +

        + +

        Side Effects None +

        + +

        See Also Cudd_ReadSize + + +
        Defined in cuddAPI.c + +
        +
        +MtrNode * 
        +Cudd_ReadZddTree(
        +  DdManager * dd 
        +)
        +
        +
        Returns the variable group tree of the manager. +

        + +

        Side Effects None +

        + +

        See Also Cudd_SetZddTree +Cudd_FreeZddTree +Cudd_ReadTree + + +
        Defined in cuddAPI.c + +
        +
        +DdNode * 
        +Cudd_ReadZero(
        +  DdManager * dd 
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        See Also Cudd_ReadOne +Cudd_ReadLogicZero + + +
        Defined in cuddAPI.c + +
        +
        +void 
        +Cudd_RecursiveDerefZdd(
        +  DdManager * table, 
        +  DdNode * n 
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        See Also Cudd_Deref +Cudd_Ref +Cudd_RecursiveDeref + + +
        Defined in cuddRef.c + +
        +
        +void 
        +Cudd_RecursiveDeref(
        +  DdManager * table, 
        +  DdNode * n 
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        See Also Cudd_Deref +Cudd_Ref +Cudd_RecursiveDerefZdd + + +
        Defined in cuddRef.c + +
        +
        +int 
        +Cudd_ReduceHeap(
        +  DdManager * table, DD manager
        +  Cudd_ReorderingType  heuristic, method used for reordering
        +  int  minsize bound below which no reordering occurs
        +)
        +
        +
        Main dynamic reordering routine. + Calls one of the possible reordering procedures: +
          +
        • Swapping +
        • Sifting +
        • Symmetric Sifting +
        • Group Sifting +
        • Window Permutation +
        • Simulated Annealing +
        • Genetic Algorithm +
        • Dynamic Programming (exact) +
        + + For sifting, symmetric sifting, group sifting, and window + permutation it is possible to request reordering to convergence.

        + + 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. +

        + +

        Side Effects Changes the variable order for all diagrams and clears + the cache. +

        + +

        Defined in cuddReorder.c + +
        +
        +void 
        +Cudd_Ref(
        +  DdNode * n 
        +)
        +
        +
        Increases the reference count of a node, if it is not + saturated. +

        + +

        Side Effects None +

        + +

        See Also Cudd_RecursiveDeref +Cudd_Deref + + +
        Defined in cuddRef.c + +
        +
        +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
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        See Also Cudd_SupersetHeavyBranch +Cudd_SupersetShortPaths +Cudd_ReadSize + + +
        Defined in cuddApprox.c + +
        +
        +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
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        See Also Cudd_SubsetShortPaths +Cudd_SubsetHeavyBranch +Cudd_UnderApprox +Cudd_ReadSize + + +
        Defined in cuddApprox.c + +
        +
        +int 
        +Cudd_RemoveHook(
        +  DdManager * dd, 
        +  DD_HFP  f, 
        +  Cudd_HookType  where 
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        See Also Cudd_AddHook + + +
        Defined in cuddAPI.c + +
        +
        +int 
        +Cudd_ReorderingReporting(
        +  DdManager * dd 
        +)
        +
        +
        Returns 1 if reporting of reordering stats is enabled; + 0 otherwise. +

        + +

        Side Effects none +

        + +

        See Also Cudd_EnableReorderingReporting +Cudd_DisableReorderingReporting + + +
        Defined in cuddAPI.c + +
        +
        +int 
        +Cudd_ReorderingStatusZdd(
        +  DdManager * unique, 
        +  Cudd_ReorderingType * method 
        +)
        +
        +
        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. +

        + +

        Side Effects Parameter method is set to the ZDD reordering method currently + selected. +

        + +

        See Also Cudd_AutodynEnableZdd +Cudd_AutodynDisableZdd +Cudd_ReorderingStatus + + +
        Defined in cuddAPI.c + +
        +
        +int 
        +Cudd_ReorderingStatus(
        +  DdManager * unique, 
        +  Cudd_ReorderingType * method 
        +)
        +
        +
        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. +

        + +

        Side Effects Parameter method is set to the reordering method currently + selected. +

        + +

        See Also Cudd_AutodynEnable +Cudd_AutodynDisable +Cudd_ReorderingStatusZdd + + +
        Defined in cuddAPI.c + +
        +
        +void 
        +Cudd_SetArcviolation(
        +  DdManager * dd, 
        +  int  arcviolation 
        +)
        +
        +
        Sets the value of the arcviolation + parameter. This parameter is used in group sifting to decide how + many arcs into y not coming from x 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. +

        + +

        Side Effects None +

        + +

        See Also Cudd_ReadArcviolation + + +
        Defined in cuddAPI.c + +
        +
        +void 
        +Cudd_SetBackground(
        +  DdManager * dd, 
        +  DdNode * bck 
        +)
        +
        +
        Sets the background constant of the manager. It assumes + that the DdNode pointer bck is already referenced. +

        + +

        Side Effects None +

        + +

        Defined in cuddAPI.c + +
        +
        +void 
        +Cudd_SetEpsilon(
        +  DdManager * dd, 
        +  CUDD_VALUE_TYPE  ep 
        +)
        +
        +
        Sets the epsilon parameter of the manager to ep. The epsilon + parameter control the comparison between floating point numbers. +

        + +

        Side Effects None +

        + +

        See Also Cudd_ReadEpsilon + + +
        Defined in cuddAPI.c + +
        +
        +void 
        +Cudd_SetGroupcheck(
        +  DdManager * dd, 
        +  Cudd_AggregationType  gc 
        +)
        +
        +
        Sets the parameter groupcheck of the manager to gc. The + groupcheck parameter determines the aggregation criterion in group + sifting. +

        + +

        Side Effects None +

        + +

        See Also Cudd_ReadGroupCheck + + +
        Defined in cuddAPI.c + +
        +
        +void 
        +Cudd_SetLooseUpTo(
        +  DdManager * dd, 
        +  unsigned int  lut 
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        See Also Cudd_ReadLooseUpTo +Cudd_SetMinHit + + +
        Defined in cuddAPI.c + +
        +
        +void 
        +Cudd_SetMaxCacheHard(
        +  DdManager * dd, 
        +  unsigned int  mc 
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        See Also Cudd_ReadMaxCacheHard +Cudd_SetMaxCache + + +
        Defined in cuddAPI.c + +
        +
        +void 
        +Cudd_SetMaxGrowthAlternate(
        +  DdManager * dd, 
        +  double  mg 
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        See Also Cudd_ReadMaxGrowthAlternate +Cudd_SetMaxGrowth +Cudd_SetReorderingCycle +Cudd_ReadReorderingCycle + + +
        Defined in cuddAPI.c + +
        +
        +void 
        +Cudd_SetMaxGrowth(
        +  DdManager * dd, 
        +  double  mg 
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        See Also Cudd_ReadMaxGrowth +Cudd_SetMaxGrowthAlternate + + +
        Defined in cuddAPI.c + +
        +
        +void 
        +Cudd_SetMaxLive(
        +  DdManager * dd, 
        +  unsigned int  maxLive 
        +)
        +
        +
        Sets the maximum allowed number of live nodes. When this + number is exceeded, the package returns NULL. +

        + +

        Side Effects none +

        + +

        See Also Cudd_ReadMaxLive + + +
        Defined in cuddAPI.c + +
        +
        +void 
        +Cudd_SetMaxMemory(
        +  DdManager * dd, 
        +  unsigned long  maxMemory 
        +)
        +
        +
        Sets the maximum allowed memory. When this + number is exceeded, the package returns NULL. +

        + +

        Side Effects none +

        + +

        See Also Cudd_ReadMaxMemory + + +
        Defined in cuddAPI.c + +
        +
        +void 
        +Cudd_SetMinHit(
        +  DdManager * dd, 
        +  unsigned int  hr 
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        See Also Cudd_ReadMinHit + + +
        Defined in cuddAPI.c + +
        +
        +void 
        +Cudd_SetNextReordering(
        +  DdManager * dd, 
        +  unsigned int  next 
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        See Also Cudd_ReadNextReordering + + +
        Defined in cuddAPI.c + +
        +
        +void 
        +Cudd_SetNumberXovers(
        +  DdManager * dd, 
        +  int  numberXovers 
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        See Also Cudd_ReadNumberXovers + + +
        Defined in cuddAPI.c + +
        +
        +void 
        +Cudd_SetPopulationSize(
        +  DdManager * dd, 
        +  int  populationSize 
        +)
        +
        +
        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. +

        + +

        Side Effects Changes the manager. +

        + +

        See Also Cudd_ReadPopulationSize + + +
        Defined in cuddAPI.c + +
        +
        +void 
        +Cudd_SetRecomb(
        +  DdManager * dd, 
        +  int  recomb 
        +)
        +
        +
        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. +

        + +

        Side Effects Changes the manager. +

        + +

        See Also Cudd_ReadRecomb + + +
        Defined in cuddAPI.c + +
        +
        +void 
        +Cudd_SetReorderingCycle(
        +  DdManager * dd, 
        +  int  cycle 
        +)
        +
        +
        Sets the reordCycle parameter of the manager. This + parameter determines how often the alternate threshold on maximum + growth is used in reordering. +

        + +

        Side Effects None +

        + +

        See Also Cudd_ReadMaxGrowthAlternate +Cudd_SetMaxGrowthAlternate +Cudd_ReadReorderingCycle + + +
        Defined in cuddAPI.c + +
        +
        +void 
        +Cudd_SetSiftMaxSwap(
        +  DdManager * dd, 
        +  int  sms 
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        See Also Cudd_SetSiftMaxVar +Cudd_ReadSiftMaxSwap + + +
        Defined in cuddAPI.c + +
        +
        +void 
        +Cudd_SetSiftMaxVar(
        +  DdManager * dd, 
        +  int  smv 
        +)
        +
        +
        Sets the siftMaxVar parameter of the manager. This + parameter gives the maximum number of variables that will be sifted + for each invocation of sifting. +

        + +

        Side Effects None +

        + +

        See Also Cudd_SetSiftMaxSwap +Cudd_ReadSiftMaxVar + + +
        Defined in cuddAPI.c + +
        +
        +void 
        +Cudd_SetStderr(
        +  DdManager * dd, 
        +  FILE * fp 
        +)
        +
        +
        Sets the stderr of a manager. +

        + +

        Side Effects None +

        + +

        See Also Cudd_ReadStderr +Cudd_SetStdout + + +
        Defined in cuddAPI.c + +
        +
        +void 
        +Cudd_SetStdout(
        +  DdManager * dd, 
        +  FILE * fp 
        +)
        +
        +
        Sets the stdout of a manager. +

        + +

        Side Effects None +

        + +

        See Also Cudd_ReadStdout +Cudd_SetStderr + + +
        Defined in cuddAPI.c + +
        +
        +void 
        +Cudd_SetSymmviolation(
        +  DdManager * dd, 
        +  int  symmviolation 
        +)
        +
        +
        Sets the value of the symmviolation + parameter. This parameter is used in group sifting to decide how + many violations to the symmetry conditions f10 = f01 or + f11 = f00 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. +

        + +

        Side Effects Changes the manager. +

        + +

        See Also Cudd_ReadSymmviolation + + +
        Defined in cuddAPI.c + +
        +
        +void 
        +Cudd_SetTree(
        +  DdManager * dd, 
        +  MtrNode * tree 
        +)
        +
        +
        Sets the variable group tree of the manager. +

        + +

        Side Effects None +

        + +

        See Also Cudd_FreeTree +Cudd_ReadTree +Cudd_SetZddTree + + +
        Defined in cuddAPI.c + +
        +
        +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
        +)
        +
        +
        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. +

        + +

        Side Effects Modifies the manager. May clear the cache. +

        + +

        See Also Cudd_bddVarMap +Cudd_bddPermute +Cudd_bddSwapVariables + + +
        Defined in cuddCompose.c + +
        +
        +void 
        +Cudd_SetZddTree(
        +  DdManager * dd, 
        +  MtrNode * tree 
        +)
        +
        +
        Sets the ZDD variable group tree of the manager. +

        + +

        Side Effects None +

        + +

        See Also Cudd_FreeZddTree +Cudd_ReadZddTree +Cudd_SetTree + + +
        Defined in cuddAPI.c + +
        +
        +int 
        +Cudd_SharingSize(
        +  DdNode ** nodeArray, 
        +  int  n 
        +)
        +
        +
        Counts the number of nodes in an array of DDs. Shared + nodes are counted only once. Returns the total number of nodes. +

        + +

        Side Effects None +

        + +

        See Also Cudd_DagSize + + +
        Defined in cuddUtil.c + +
        +
        +int 
        +Cudd_ShortestLength(
        +  DdManager * manager, 
        +  DdNode * f, 
        +  int * weight 
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        See Also Cudd_ShortestPath + + +
        Defined in cuddSat.c + +
        +
        +DdNode * 
        +Cudd_ShortestPath(
        +  DdManager * manager, 
        +  DdNode * f, 
        +  int * weight, 
        +  int * support, 
        +  int * length 
        +)
        +
        +
        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. +

        + +

        Side Effects 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. +

        + +

        See Also Cudd_ShortestLength +Cudd_LargestCube + + +
        Defined in cuddSat.c + +
        +
        +int 
        +Cudd_ShuffleHeap(
        +  DdManager * table, DD manager
        +  int * permutation required variable permutation
        +)
        +
        +
        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. +

        + +

        Side Effects Changes the variable order for all diagrams and clears + the cache. +

        + +

        See Also Cudd_ReduceHeap + + +
        Defined in cuddReorder.c + +
        +
        +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
        +)
        +
        +
        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. +

        + +

        Side Effects The solution is returned in G; the indices of the y + variables are returned in yIndex. +

        + +

        See Also Cudd_VerifySol + + +
        Defined in cuddSolve.c + +
        +
        +DdNode * 
        +Cudd_SplitSet(
        +  DdManager * manager, 
        +  DdNode * S, 
        +  DdNode ** xVars, 
        +  int  n, 
        +  double  m 
        +)
        +
        +
        Returns m minterms from a BDD whose + support has n variables at most. The procedure tries + to create as few extra nodes as possible. The function represented + by S depends on at most n of the variables + in xVars. Returns a BDD with m minterms + of the on-set of S if successful; NULL otherwise. +

        + +

        Side Effects None +

        + +

        Defined in cuddSplit.c + +
        +
        +void 
        +Cudd_Srandom(
        +  long  seed 
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        See Also Cudd_Random + + +
        Defined in cuddUtil.c + +
        +
        +int 
        +Cudd_StdPostReordHook(
        +  DdManager * dd, 
        +  const char * str, 
        +  void * data 
        +)
        +
        +
        Sample hook function to call after reordering. + Prints on the manager's stdout final size and reordering time. + Returns 1 if successful; 0 otherwise. +

        + +

        Side Effects None +

        + +

        See Also Cudd_StdPreReordHook + + +
        Defined in cuddAPI.c + +
        +
        +int 
        +Cudd_StdPreReordHook(
        +  DdManager * dd, 
        +  const char * str, 
        +  void * data 
        +)
        +
        +
        Sample hook function to call before reordering. + Prints on the manager's stdout reordering method and initial size. + Returns 1 if successful; 0 otherwise. +

        + +

        Side Effects None +

        + +

        See Also Cudd_StdPostReordHook + + +
        Defined in cuddAPI.c + +
        +
        +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
        +)
        +
        +
        Finds a dense subset of BDD f. 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. +

        + +

        Side Effects None +

        + +

        See Also Cudd_SubsetRemap +Cudd_SubsetShortPaths +Cudd_SubsetHeavyBranch +Cudd_bddSqueeze + + +
        Defined in cuddGenCof.c + +
        +
        +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
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        See Also Cudd_SubsetShortPaths +Cudd_SupersetHeavyBranch +Cudd_ReadSize + + +
        Defined in cuddSubsetHB.c + +
        +
        +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
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        See Also Cudd_SupersetShortPaths +Cudd_SubsetHeavyBranch +Cudd_ReadSize + + +
        Defined in cuddSubsetSP.c + +
        +
        +DdNode * 
        +Cudd_SubsetWithMaskVars(
        +  DdManager * dd, manager
        +  DdNode * f, function from which to pick a cube
        +  DdNode ** vars, array of variables
        +  int  nvars, size of vars
        +  DdNode ** maskVars, array of variables
        +  int  mvars size of maskVars
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        Defined in cuddUtil.c + +
        +
        +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
        +)
        +
        +
        Finds a dense superset of BDD f. 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. +

        + +

        Side Effects None +

        + +

        See Also Cudd_SubsetCompress +Cudd_SupersetRemap +Cudd_SupersetShortPaths +Cudd_SupersetHeavyBranch +Cudd_bddSqueeze + + +
        Defined in cuddGenCof.c + +
        +
        +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
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        See Also Cudd_SubsetHeavyBranch +Cudd_SupersetShortPaths +Cudd_ReadSize + + +
        Defined in cuddSubsetHB.c + +
        +
        +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
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        See Also Cudd_SubsetShortPaths +Cudd_SupersetHeavyBranch +Cudd_ReadSize + + +
        Defined in cuddSubsetSP.c + +
        +
        +int * 
        +Cudd_SupportIndex(
        +  DdManager * dd, manager
        +  DdNode * f DD whose support is sought
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        See Also Cudd_Support +Cudd_VectorSupport +Cudd_ClassifySupport + + +
        Defined in cuddUtil.c + +
        +
        +int 
        +Cudd_SupportSize(
        +  DdManager * dd, manager
        +  DdNode * f DD whose support size is sought
        +)
        +
        +
        Counts the variables on which a DD depends. + Returns the number of the variables if successful; CUDD_OUT_OF_MEM + otherwise. +

        + +

        Side Effects None +

        + +

        See Also Cudd_Support + + +
        Defined in cuddUtil.c + +
        +
        +DdNode * 
        +Cudd_Support(
        +  DdManager * dd, manager
        +  DdNode * f DD whose support is sought
        +)
        +
        +
        Finds the variables on which a DD depends. + Returns a BDD consisting of the product of the variables if + successful; NULL otherwise. +

        + +

        Side Effects None +

        + +

        See Also Cudd_VectorSupport +Cudd_ClassifySupport + + +
        Defined in cuddUtil.c + +
        +
        +void 
        +Cudd_SymmProfile(
        +  DdManager * table, 
        +  int  lower, 
        +  int  upper 
        +)
        +
        +
        Prints statistics on symmetric variables. +

        + +

        Side Effects None +

        + +

        Defined in cuddSymmetry.c + +
        +
        +void 
        +Cudd_TurnOffCountDead(
        +  DdManager * dd 
        +)
        +
        +
        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. +

        + +

        Side Effects Changes the manager. +

        + +

        See Also Cudd_TurnOnCountDead +Cudd_DeadAreCounted + + +
        Defined in cuddAPI.c + +
        +
        +void 
        +Cudd_TurnOnCountDead(
        +  DdManager * dd 
        +)
        +
        +
        Causes the dead nodes to be counted towards triggering + reordering. This causes more frequent reorderings. By default dead + nodes are not counted. +

        + +

        Side Effects Changes the manager. +

        + +

        See Also Cudd_TurnOffCountDead +Cudd_DeadAreCounted + + +
        Defined in cuddAPI.c + +
        +
        +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
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        See Also Cudd_SubsetShortPaths +Cudd_SubsetHeavyBranch +Cudd_ReadSize + + +
        Defined in cuddApprox.c + +
        +
        +int * 
        +Cudd_VectorSupportIndex(
        +  DdManager * dd, manager
        +  DdNode ** F, array of DDs whose support is sought
        +  int  n size of the array
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        See Also Cudd_SupportIndex +Cudd_VectorSupport +Cudd_ClassifySupport + + +
        Defined in cuddUtil.c + +
        +
        +int 
        +Cudd_VectorSupportSize(
        +  DdManager * dd, manager
        +  DdNode ** F, array of DDs whose support is sought
        +  int  n size of the array
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        See Also Cudd_VectorSupport +Cudd_SupportSize + + +
        Defined in cuddUtil.c + +
        +
        +DdNode * 
        +Cudd_VectorSupport(
        +  DdManager * dd, manager
        +  DdNode ** F, array of DDs whose support is sought
        +  int  n size of the array
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        See Also Cudd_Support +Cudd_ClassifySupport + + +
        Defined in cuddUtil.c + +
        +
        +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
        +)
        +
        +
        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. +

        + +

        Side Effects Frees the memory pointed by yIndex. +

        + +

        See Also Cudd_SolveEqn + + +
        Defined in cuddSolve.c + +
        +
        +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
        +)
        +
        +
        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]. +

        + +

        Side Effects None +

        + +

        See Also Cudd_addXeqy + + +
        Defined in cuddPriority.c + +
        +
        +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
        +)
        +
        +
        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]. + Argument z is not used by Cudd_Xgty: it is included to make it + call-compatible to Cudd_Dxygtdxz and Cudd_Dxygtdyz. +

        + +

        Side Effects None +

        + +

        See Also Cudd_PrioritySelect +Cudd_Dxygtdxz +Cudd_Dxygtdyz + + +
        Defined in cuddPriority.c + +
        +
        +DdNode * 
        +Cudd_addAgreement(
        +  DdManager * dd, 
        +  DdNode ** f, 
        +  DdNode ** g 
        +)
        +
        +
        Returns NULL if not a terminal case; f op g otherwise, + where f op g is f if f==g; background if f!=g. +

        + +

        Side Effects None +

        + +

        See Also Cudd_addApply + + +
        Defined in cuddAddApply.c + +
        +
        +DdNode * 
        +Cudd_addApply(
        +  DdManager * dd, 
        +  DD_AOP  op, 
        +  DdNode * f, 
        +  DdNode * g 
        +)
        +
        +
        Applies op to the corresponding discriminants of f and g. + Returns a pointer to the result if succssful; NULL otherwise. +

        + +

        Side Effects None +

        + +

        See Also 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 + + +
        Defined in cuddAddApply.c + +
        +
        +DdNode * 
        +Cudd_addBddInterval(
        +  DdManager * dd, 
        +  DdNode * f, 
        +  CUDD_VALUE_TYPE  lower, 
        +  CUDD_VALUE_TYPE  upper 
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        See Also Cudd_addBddThreshold +Cudd_addBddStrictThreshold +Cudd_addBddPattern +Cudd_BddToAdd + + +
        Defined in cuddBridge.c + +
        +
        +DdNode * 
        +Cudd_addBddIthBit(
        +  DdManager * dd, 
        +  DdNode * f, 
        +  int  bit 
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        See Also Cudd_addBddInterval +Cudd_addBddPattern +Cudd_BddToAdd + + +
        Defined in cuddBridge.c + +
        +
        +DdNode * 
        +Cudd_addBddPattern(
        +  DdManager * dd, 
        +  DdNode * f 
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        See Also Cudd_BddToAdd +Cudd_addBddThreshold +Cudd_addBddInterval +Cudd_addBddStrictThreshold + + +
        Defined in cuddBridge.c + +
        +
        +DdNode * 
        +Cudd_addBddStrictThreshold(
        +  DdManager * dd, 
        +  DdNode * f, 
        +  CUDD_VALUE_TYPE  value 
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        See Also Cudd_addBddInterval +Cudd_addBddPattern +Cudd_BddToAdd +Cudd_addBddThreshold + + +
        Defined in cuddBridge.c + +
        +
        +DdNode * 
        +Cudd_addBddThreshold(
        +  DdManager * dd, 
        +  DdNode * f, 
        +  CUDD_VALUE_TYPE  value 
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        See Also Cudd_addBddInterval +Cudd_addBddPattern +Cudd_BddToAdd +Cudd_addBddStrictThreshold + + +
        Defined in cuddBridge.c + +
        +
        +DdNode * 
        +Cudd_addCmpl(
        +  DdManager * dd, 
        +  DdNode * f 
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        See Also Cudd_addNegate + + +
        Defined in cuddAddIte.c + +
        +
        +DdNode * 
        +Cudd_addCompose(
        +  DdManager * dd, 
        +  DdNode * f, 
        +  DdNode * g, 
        +  int  v 
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        See Also Cudd_bddCompose + + +
        Defined in cuddCompose.c + +
        +
        +DdNode * 
        +Cudd_addComputeCube(
        +  DdManager * dd, 
        +  DdNode ** vars, 
        +  int * phase, 
        +  int  n 
        +)
        +
        +
        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. +

        + +

        Side Effects none +

        + +

        See Also Cudd_bddComputeCube + + +
        Defined in cuddUtil.c + +
        +
        +DdNode * 
        +Cudd_addConstrain(
        +  DdManager * dd, 
        +  DdNode * f, 
        +  DdNode * c 
        +)
        +
        +
        Computes f constrain c (f @ c), for f an ADD and c a 0-1 + ADD. List of special cases: +
          +
        • F @ 0 = 0 +
        • F @ 1 = F +
        • 0 @ c = 0 +
        • 1 @ c = 1 +
        • F @ F = 1 +
        + Returns a pointer to the result if successful; NULL otherwise. +

        + +

        Side Effects None +

        + +

        See Also Cudd_bddConstrain + + +
        Defined in cuddGenCof.c + +
        +
        +DdNode * 
        +Cudd_addConst(
        +  DdManager * dd, 
        +  CUDD_VALUE_TYPE  c 
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        See Also Cudd_addNewVar +Cudd_addIthVar + + +
        Defined in cuddAPI.c + +
        +
        +DdNode * 
        +Cudd_addDiff(
        +  DdManager * dd, 
        +  DdNode ** f, 
        +  DdNode ** g 
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        See Also Cudd_addApply + + +
        Defined in cuddAddApply.c + +
        +
        +DdNode * 
        +Cudd_addDivide(
        +  DdManager * dd, 
        +  DdNode ** f, 
        +  DdNode ** g 
        +)
        +
        +
        Integer and floating point division. Returns NULL if not + a terminal case; f / g otherwise. +

        + +

        Side Effects None +

        + +

        See Also Cudd_addApply + + +
        Defined in cuddAddApply.c + +
        +
        +DdNode * 
        +Cudd_addEvalConst(
        +  DdManager * dd, 
        +  DdNode * f, 
        +  DdNode * g 
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        See Also Cudd_addIteConstant +Cudd_addLeq + + +
        Defined in cuddAddIte.c + +
        +
        +DdNode * 
        +Cudd_addExistAbstract(
        +  DdManager * manager, 
        +  DdNode * f, 
        +  DdNode * cube 
        +)
        +
        +
        Abstracts all the variables in cube from f by summing + over all possible values taken by the variables. Returns the + abstracted ADD. +

        + +

        Side Effects None +

        + +

        See Also Cudd_addUnivAbstract +Cudd_bddExistAbstract +Cudd_addOrAbstract + + +
        Defined in cuddAddAbs.c + +
        +
        +DdNode * 
        +Cudd_addFindMax(
        +  DdManager * dd, 
        +  DdNode * f 
        +)
        +
        +
        Returns a pointer to a constant ADD. +

        + +

        Side Effects None +

        + +

        Defined in cuddAddFind.c + +
        +
        +DdNode * 
        +Cudd_addFindMin(
        +  DdManager * dd, 
        +  DdNode * f 
        +)
        +
        +
        Returns a pointer to a constant ADD. +

        + +

        Side Effects None +

        + +

        Defined in cuddAddFind.c + +
        +
        +DdNode * 
        +Cudd_addGeneralVectorCompose(
        +  DdManager * dd, 
        +  DdNode * f, 
        +  DdNode ** vectorOn, 
        +  DdNode ** vectorOff 
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        See Also Cudd_addVectorCompose +Cudd_addNonSimCompose +Cudd_addPermute +Cudd_addCompose +Cudd_bddVectorCompose + + +
        Defined in cuddCompose.c + +
        +
        +DdNode * 
        +Cudd_addHamming(
        +  DdManager * dd, 
        +  DdNode ** xVars, 
        +  DdNode ** yVars, 
        +  int  nVars 
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        Defined in cuddPriority.c + +
        +
        +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
        +)
        +
        +
        Reads in a matrix in the format of the Harwell-Boeing + benchmark suite. The variables are ordered as follows: +
        + x[0] y[0] x[1] y[1] ... +
        + 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. +

        + +

        Side Effects None +

        + +

        See Also Cudd_addRead +Cudd_bddRead + + +
        Defined in cuddHarwell.c + +
        +
        +DdNode * 
        +Cudd_addIteConstant(
        +  DdManager * dd, 
        +  DdNode * f, 
        +  DdNode * g, 
        +  DdNode * h 
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        See Also Cudd_addIte +Cudd_addEvalConst +Cudd_bddIteConstant + + +
        Defined in cuddAddIte.c + +
        +
        +DdNode * 
        +Cudd_addIte(
        +  DdManager * dd, 
        +  DdNode * f, 
        +  DdNode * g, 
        +  DdNode * h 
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        See Also Cudd_bddIte +Cudd_addIteConstant +Cudd_addApply + + +
        Defined in cuddAddIte.c + +
        +
        +DdNode * 
        +Cudd_addIthBit(
        +  DdManager * dd, 
        +  DdNode * f, 
        +  int  bit 
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        See Also Cudd_addBddIthBit + + +
        Defined in cuddAddFind.c + +
        +
        +DdNode * 
        +Cudd_addIthVar(
        +  DdManager * dd, 
        +  int  i 
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        See Also Cudd_addNewVar +Cudd_bddIthVar +Cudd_addConst +Cudd_addNewVarAtLevel + + +
        Defined in cuddAPI.c + +
        +
        +int 
        +Cudd_addLeq(
        +  DdManager * dd, 
        +  DdNode * f, 
        +  DdNode * g 
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        See Also Cudd_addIteConstant +Cudd_addEvalConst +Cudd_bddLeq + + +
        Defined in cuddAddIte.c + +
        +
        +DdNode * 
        +Cudd_addLog(
        +  DdManager * dd, 
        +  DdNode * f 
        +)
        +
        +
        Natural logarithm of an ADDs. Returns NULL + if not a terminal case; log(f) otherwise. The discriminants of f must + be positive double's. +

        + +

        Side Effects None +

        + +

        See Also Cudd_addMonadicApply + + +
        Defined in cuddAddApply.c + +
        +
        +DdNode * 
        +Cudd_addMatrixMultiply(
        +  DdManager * dd, 
        +  DdNode * A, 
        +  DdNode * B, 
        +  DdNode ** z, 
        +  int  nz 
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        See Also Cudd_addTimesPlus +Cudd_addTriangle +Cudd_bddAndAbstract + + +
        Defined in cuddMatMult.c + +
        +
        +DdNode * 
        +Cudd_addMaximum(
        +  DdManager * dd, 
        +  DdNode ** f, 
        +  DdNode ** g 
        +)
        +
        +
        Integer and floating point max for Cudd_addApply. + Returns NULL if not a terminal case; max(f,g) otherwise. +

        + +

        Side Effects None +

        + +

        See Also Cudd_addApply + + +
        Defined in cuddAddApply.c + +
        +
        +DdNode * 
        +Cudd_addMinimum(
        +  DdManager * dd, 
        +  DdNode ** f, 
        +  DdNode ** g 
        +)
        +
        +
        Integer and floating point min for Cudd_addApply. + Returns NULL if not a terminal case; min(f,g) otherwise. +

        + +

        Side Effects None +

        + +

        See Also Cudd_addApply + + +
        Defined in cuddAddApply.c + +
        +
        +DdNode * 
        +Cudd_addMinus(
        +  DdManager * dd, 
        +  DdNode ** f, 
        +  DdNode ** g 
        +)
        +
        +
        Integer and floating point subtraction. Returns NULL if + not a terminal case; f - g otherwise. +

        + +

        Side Effects None +

        + +

        See Also Cudd_addApply + + +
        Defined in cuddAddApply.c + +
        +
        +DdNode * 
        +Cudd_addMonadicApply(
        +  DdManager * dd, 
        +  DD_MAOP  op, 
        +  DdNode * f 
        +)
        +
        +
        Applies op to the discriminants of f. + Returns a pointer to the result if succssful; NULL otherwise. +

        + +

        Side Effects None +

        + +

        See Also Cudd_addApply +Cudd_addLog + + +
        Defined in cuddAddApply.c + +
        +
        +DdNode * 
        +Cudd_addNand(
        +  DdManager * dd, 
        +  DdNode ** f, 
        +  DdNode ** g 
        +)
        +
        +
        NAND of two 0-1 ADDs. Returns NULL + if not a terminal case; f NAND g otherwise. +

        + +

        Side Effects None +

        + +

        See Also Cudd_addApply + + +
        Defined in cuddAddApply.c + +
        +
        +DdNode * 
        +Cudd_addNegate(
        +  DdManager * dd, 
        +  DdNode * f 
        +)
        +
        +
        Computes the additive inverse of an ADD. Returns a pointer + to the result if successful; NULL otherwise. +

        + +

        Side Effects None +

        + +

        See Also Cudd_addCmpl + + +
        Defined in cuddAddNeg.c + +
        +
        +DdNode * 
        +Cudd_addNewVarAtLevel(
        +  DdManager * dd, 
        +  int  level 
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        See Also Cudd_addNewVar +Cudd_addIthVar +Cudd_bddNewVarAtLevel + + +
        Defined in cuddAPI.c + +
        +
        +DdNode * 
        +Cudd_addNewVar(
        +  DdManager * dd 
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        See Also Cudd_bddNewVar +Cudd_addIthVar +Cudd_addConst +Cudd_addNewVarAtLevel + + +
        Defined in cuddAPI.c + +
        +
        +DdNode * 
        +Cudd_addNonSimCompose(
        +  DdManager * dd, 
        +  DdNode * f, 
        +  DdNode ** vector 
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        See Also Cudd_addVectorCompose +Cudd_addPermute +Cudd_addCompose + + +
        Defined in cuddCompose.c + +
        +
        +DdNode * 
        +Cudd_addNor(
        +  DdManager * dd, 
        +  DdNode ** f, 
        +  DdNode ** g 
        +)
        +
        +
        NOR of two 0-1 ADDs. Returns NULL + if not a terminal case; f NOR g otherwise. +

        + +

        Side Effects None +

        + +

        See Also Cudd_addApply + + +
        Defined in cuddAddApply.c + +
        +
        +DdNode * 
        +Cudd_addOneZeroMaximum(
        +  DdManager * dd, 
        +  DdNode ** f, 
        +  DdNode ** g 
        +)
        +
        +
        Returns 1 if f > g and 0 otherwise. Used in + conjunction with Cudd_addApply. Returns NULL if not a terminal + case. +

        + +

        Side Effects None +

        + +

        See Also Cudd_addApply + + +
        Defined in cuddAddApply.c + +
        +
        +DdNode * 
        +Cudd_addOrAbstract(
        +  DdManager * manager, 
        +  DdNode * f, 
        +  DdNode * cube 
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        See Also Cudd_addUnivAbstract +Cudd_addExistAbstract + + +
        Defined in cuddAddAbs.c + +
        +
        +DdNode * 
        +Cudd_addOr(
        +  DdManager * dd, 
        +  DdNode ** f, 
        +  DdNode ** g 
        +)
        +
        +
        Disjunction of two 0-1 ADDs. Returns NULL + if not a terminal case; f OR g otherwise. +

        + +

        Side Effects None +

        + +

        See Also Cudd_addApply + + +
        Defined in cuddAddApply.c + +
        +
        +DdNode * 
        +Cudd_addOuterSum(
        +  DdManager * dd, 
        +  DdNode * M, 
        +  DdNode * r, 
        +  DdNode * c 
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        Defined in cuddMatMult.c + +
        +
        +DdNode * 
        +Cudd_addPermute(
        +  DdManager * manager, 
        +  DdNode * node, 
        +  int * permut 
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        See Also Cudd_bddPermute +Cudd_addSwapVariables + + +
        Defined in cuddCompose.c + +
        +
        +DdNode * 
        +Cudd_addPlus(
        +  DdManager * dd, 
        +  DdNode ** f, 
        +  DdNode ** g 
        +)
        +
        +
        Integer and floating point addition. Returns NULL if not + a terminal case; f+g otherwise. +

        + +

        Side Effects None +

        + +

        See Also Cudd_addApply + + +
        Defined in cuddAddApply.c + +
        +
        +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
        +)
        +
        +
        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.

        + 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.

        + 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.

        + 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. +

        + +

        Side Effects 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. +

        + +

        See Also Cudd_addHarwell +Cudd_bddRead + + +
        Defined in cuddRead.c + +
        +
        +DdNode * 
        +Cudd_addResidue(
        +  DdManager * dd, manager
        +  int  n, number of bits
        +  int  m, modulus
        +  int  options, options
        +  int  top index of top variable
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        Defined in cuddAddWalsh.c + +
        +
        +DdNode * 
        +Cudd_addRestrict(
        +  DdManager * dd, 
        +  DdNode * f, 
        +  DdNode * c 
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        See Also Cudd_addConstrain +Cudd_bddRestrict + + +
        Defined in cuddGenCof.c + +
        +
        +DdNode * 
        +Cudd_addRoundOff(
        +  DdManager * dd, 
        +  DdNode * f, 
        +  int  N 
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        Defined in cuddAddNeg.c + +
        +
        +DdNode * 
        +Cudd_addScalarInverse(
        +  DdManager * dd, 
        +  DdNode * f, 
        +  DdNode * epsilon 
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        Defined in cuddAddInv.c + +
        +
        +DdNode * 
        +Cudd_addSetNZ(
        +  DdManager * dd, 
        +  DdNode ** f, 
        +  DdNode ** g 
        +)
        +
        +
        This operator sets f to the value of g wherever g != 0. + Returns NULL if not a terminal case; f op g otherwise. +

        + +

        Side Effects None +

        + +

        See Also Cudd_addApply + + +
        Defined in cuddAddApply.c + +
        +
        +DdNode * 
        +Cudd_addSwapVariables(
        +  DdManager * dd, 
        +  DdNode * f, 
        +  DdNode ** x, 
        +  DdNode ** y, 
        +  int  n 
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        See Also Cudd_addPermute +Cudd_bddSwapVariables + + +
        Defined in cuddCompose.c + +
        +
        +DdNode * 
        +Cudd_addThreshold(
        +  DdManager * dd, 
        +  DdNode ** f, 
        +  DdNode ** g 
        +)
        +
        +
        Threshold operator for Apply (f if f >=g; 0 if f<g). + Returns NULL if not a terminal case; f op g otherwise. +

        + +

        Side Effects None +

        + +

        See Also Cudd_addApply + + +
        Defined in cuddAddApply.c + +
        +
        +DdNode * 
        +Cudd_addTimesPlus(
        +  DdManager * dd, 
        +  DdNode * A, 
        +  DdNode * B, 
        +  DdNode ** z, 
        +  int  nz 
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        See Also Cudd_addMatrixMultiply + + +
        Defined in cuddMatMult.c + +
        +
        +DdNode * 
        +Cudd_addTimes(
        +  DdManager * dd, 
        +  DdNode ** f, 
        +  DdNode ** g 
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        See Also Cudd_addApply + + +
        Defined in cuddAddApply.c + +
        +
        +DdNode * 
        +Cudd_addTriangle(
        +  DdManager * dd, 
        +  DdNode * f, 
        +  DdNode * g, 
        +  DdNode ** z, 
        +  int  nz 
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        See Also Cudd_addMatrixMultiply +Cudd_bddAndAbstract + + +
        Defined in cuddMatMult.c + +
        +
        +DdNode * 
        +Cudd_addUnivAbstract(
        +  DdManager * manager, 
        +  DdNode * f, 
        +  DdNode * cube 
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        See Also Cudd_addExistAbstract +Cudd_bddUnivAbstract +Cudd_addOrAbstract + + +
        Defined in cuddAddAbs.c + +
        +
        +DdNode * 
        +Cudd_addVectorCompose(
        +  DdManager * dd, 
        +  DdNode * f, 
        +  DdNode ** vector 
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        See Also Cudd_addNonSimCompose +Cudd_addPermute +Cudd_addCompose +Cudd_bddVectorCompose + + +
        Defined in cuddCompose.c + +
        +
        +DdNode * 
        +Cudd_addWalsh(
        +  DdManager * dd, 
        +  DdNode ** x, 
        +  DdNode ** y, 
        +  int  n 
        +)
        +
        +
        Generates a Walsh matrix in ADD form. Returns a pointer + to the matrixi if successful; NULL otherwise. +

        + +

        Side Effects None +

        + +

        Defined in cuddAddWalsh.c + +
        +
        +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
        +)
        +
        +
        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]. +

        + +

        Side Effects None +

        + +

        See Also Cudd_Xeqy + + +
        Defined in cuddPriority.c + +
        +
        +DdNode * 
        +Cudd_addXnor(
        +  DdManager * dd, 
        +  DdNode ** f, 
        +  DdNode ** g 
        +)
        +
        +
        XNOR of two 0-1 ADDs. Returns NULL + if not a terminal case; f XNOR g otherwise. +

        + +

        Side Effects None +

        + +

        See Also Cudd_addApply + + +
        Defined in cuddAddApply.c + +
        +
        +DdNode * 
        +Cudd_addXor(
        +  DdManager * dd, 
        +  DdNode ** f, 
        +  DdNode ** g 
        +)
        +
        +
        XOR of two 0-1 ADDs. Returns NULL + if not a terminal case; f XOR g otherwise. +

        + +

        Side Effects None +

        + +

        See Also Cudd_addApply + + +
        Defined in cuddAddApply.c + +
        +
        +DdNode * 
        +Cudd_bddAdjPermuteX(
        +  DdManager * dd, 
        +  DdNode * B, 
        +  DdNode ** x, 
        +  int  n 
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        See Also Cudd_bddPermute +Cudd_bddSwapVariables +Cudd_Dxygtdxz +Cudd_Dxygtdyz +Cudd_PrioritySelect + + +
        Defined in cuddCompose.c + +
        +
        +DdNode * 
        +Cudd_bddAndAbstractLimit(
        +  DdManager * manager, 
        +  DdNode * f, 
        +  DdNode * g, 
        +  DdNode * cube, 
        +  unsigned int  limit 
        +)
        +
        +
        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 + limit, this function returns NULL. +

        + +

        Side Effects None +

        + +

        See Also Cudd_bddAndAbstract + + +
        Defined in cuddAndAbs.c + +
        +
        +DdNode * 
        +Cudd_bddAndAbstract(
        +  DdManager * manager, 
        +  DdNode * f, 
        +  DdNode * g, 
        +  DdNode * cube 
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        See Also Cudd_addMatrixMultiply +Cudd_addTriangle +Cudd_bddAnd + + +
        Defined in cuddAndAbs.c + +
        +
        +DdNode * 
        +Cudd_bddAndLimit(
        +  DdManager * dd, 
        +  DdNode * f, 
        +  DdNode * g, 
        +  unsigned int  limit 
        +)
        +
        +
        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 limit are + required. +

        + +

        Side Effects None +

        + +

        See Also Cudd_bddAnd + + +
        Defined in cuddBddIte.c + +
        +
        +DdNode * 
        +Cudd_bddAnd(
        +  DdManager * dd, 
        +  DdNode * f, 
        +  DdNode * g 
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        See Also Cudd_bddIte +Cudd_addApply +Cudd_bddAndAbstract +Cudd_bddIntersect +Cudd_bddOr +Cudd_bddNand +Cudd_bddNor +Cudd_bddXor +Cudd_bddXnor + + +
        Defined in cuddBddIte.c + +
        +
        +int 
        +Cudd_bddApproxConjDecomp(
        +  DdManager * dd, manager
        +  DdNode * f, function to be decomposed
        +  DdNode *** conjuncts address of the first factor
        +)
        +
        +
        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. +

        + +

        Side Effects 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. +

        + +

        See Also Cudd_bddApproxDisjDecomp +Cudd_bddIterConjDecomp +Cudd_bddGenConjDecomp +Cudd_bddVarConjDecomp +Cudd_RemapOverApprox +Cudd_bddSqueeze +Cudd_bddLICompaction + + +
        Defined in cuddDecomp.c + +
        +
        +int 
        +Cudd_bddApproxDisjDecomp(
        +  DdManager * dd, manager
        +  DdNode * f, function to be decomposed
        +  DdNode *** disjuncts address of the array of the disjuncts
        +)
        +
        +
        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. +

        + +

        Side Effects 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. +

        + +

        See Also Cudd_bddApproxConjDecomp +Cudd_bddIterDisjDecomp +Cudd_bddGenDisjDecomp +Cudd_bddVarDisjDecomp + + +
        Defined in cuddDecomp.c + +
        +
        +int 
        +Cudd_bddBindVar(
        +  DdManager * dd, manager
        +  int  index variable index
        +)
        +
        +
        This function sets a flag to prevent sifting of a + variable. Returns 1 if successful; 0 otherwise (i.e., invalid + variable index). +

        + +

        Side Effects Changes the "bindVar" flag in DdSubtable. +

        + +

        See Also Cudd_bddUnbindVar + + +
        Defined in cuddAPI.c + +
        +
        +DdNode * 
        +Cudd_bddBooleanDiff(
        +  DdManager * manager, 
        +  DdNode * f, 
        +  int  x 
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        Defined in cuddBddAbs.c + +
        +
        +DdNode ** 
        +Cudd_bddCharToVect(
        +  DdManager * dd, 
        +  DdNode * f 
        +)
        +
        +
        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). +

        + +

        Side Effects None +

        + +

        See Also Cudd_bddConstrain + + +
        Defined in cuddGenCof.c + +
        +
        +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
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        See Also Cudd_bddAndAbstract +Cudd_bddClippingAnd + + +
        Defined in cuddClip.c + +
        +
        +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
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        See Also Cudd_bddAnd + + +
        Defined in cuddClip.c + +
        +
        +DdNode * 
        +Cudd_bddClosestCube(
        +  DdManager * dd, 
        +  DdNode * f, 
        +  DdNode * g, 
        +  int * distance 
        +)
        +
        +
        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. +

        + +

        Side Effects The distance is returned as a side effect. +

        + +

        See Also Cudd_MinHammingDist + + +
        Defined in cuddPriority.c + +
        +
        +DdNode * 
        +Cudd_bddCompose(
        +  DdManager * dd, 
        +  DdNode * f, 
        +  DdNode * g, 
        +  int  v 
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        See Also Cudd_addCompose + + +
        Defined in cuddCompose.c + +
        +
        +DdNode * 
        +Cudd_bddComputeCube(
        +  DdManager * dd, 
        +  DdNode ** vars, 
        +  int * phase, 
        +  int  n 
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        See Also Cudd_addComputeCube +Cudd_IndicesToCube +Cudd_CubeArrayToBdd + + +
        Defined in cuddUtil.c + +
        +
        +DdNode ** 
        +Cudd_bddConstrainDecomp(
        +  DdManager * dd, 
        +  DdNode * f 
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        See Also Cudd_bddConstrain +Cudd_bddExistAbstract + + +
        Defined in cuddGenCof.c + +
        +
        +DdNode * 
        +Cudd_bddConstrain(
        +  DdManager * dd, 
        +  DdNode * f, 
        +  DdNode * c 
        +)
        +
        +
        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: +
          +
        • f @ 0 = 0 +
        • f @ 1 = f +
        • 0 @ c = 0 +
        • 1 @ c = 1 +
        • f @ f = 1 +
        • f @ f'= 0 +
        + 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. +

        + +

        Side Effects None +

        + +

        See Also Cudd_bddRestrict +Cudd_addConstrain + + +
        Defined in cuddGenCof.c + +
        +
        +double 
        +Cudd_bddCorrelationWeights(
        +  DdManager * manager, 
        +  DdNode * f, 
        +  DdNode * g, 
        +  double * prob 
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        See Also Cudd_bddCorrelation + + +
        Defined in cuddBddCorr.c + +
        +
        +double 
        +Cudd_bddCorrelation(
        +  DdManager * manager, 
        +  DdNode * f, 
        +  DdNode * g 
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        See Also Cudd_bddCorrelationWeights + + +
        Defined in cuddBddCorr.c + +
        +
        +DdNode * 
        +Cudd_bddExistAbstract(
        +  DdManager * manager, 
        +  DdNode * f, 
        +  DdNode * cube 
        +)
        +
        +
        Existentially abstracts all the variables in cube from f. + Returns the abstracted BDD if successful; NULL otherwise. +

        + +

        Side Effects None +

        + +

        See Also Cudd_bddUnivAbstract +Cudd_addExistAbstract + + +
        Defined in cuddBddAbs.c + +
        +
        +int 
        +Cudd_bddGenConjDecomp(
        +  DdManager * dd, manager
        +  DdNode * f, function to be decomposed
        +  DdNode *** conjuncts address of the array of conjuncts
        +)
        +
        +
        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. +

        + +

        Side Effects 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. +

        + +

        See Also Cudd_bddGenDisjDecomp +Cudd_bddApproxConjDecomp +Cudd_bddIterConjDecomp +Cudd_bddVarConjDecomp + + +
        Defined in cuddDecomp.c + +
        +
        +int 
        +Cudd_bddGenDisjDecomp(
        +  DdManager * dd, manager
        +  DdNode * f, function to be decomposed
        +  DdNode *** disjuncts address of the array of the disjuncts
        +)
        +
        +
        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. +

        + +

        Side Effects 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. +

        + +

        See Also Cudd_bddGenConjDecomp +Cudd_bddApproxDisjDecomp +Cudd_bddIterDisjDecomp +Cudd_bddVarDisjDecomp + + +
        Defined in cuddDecomp.c + +
        +
        +DdNode * 
        +Cudd_bddIntersect(
        +  DdManager * dd, manager
        +  DdNode * f, first operand
        +  DdNode * g second operand
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        See Also Cudd_bddLeq +Cudd_bddIteConstant + + +
        Defined in cuddBddIte.c + +
        +
        +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
        +)
        +
        +
        This function generates a BDD for the function + lowerB ≤ x ≤ 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 ≤ x and x ≤ upperB, and they + are finally conjoined. +

        + +

        Side Effects None +

        + +

        See Also Cudd_Xgty + + +
        Defined in cuddPriority.c + +
        +
        +int 
        +Cudd_bddIsNsVar(
        +  DdManager * dd, 
        +  int  index 
        +)
        +
        +
        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. +

        + +

        Side Effects none +

        + +

        See Also Cudd_bddSetNsVar +Cudd_bddIsPiVar +Cudd_bddIsPsVar + + +
        Defined in cuddAPI.c + +
        +
        +int 
        +Cudd_bddIsPiVar(
        +  DdManager * dd, manager
        +  int  index variable index
        +)
        +
        +
        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. +

        + +

        Side Effects none +

        + +

        See Also Cudd_bddSetPiVar +Cudd_bddIsPsVar +Cudd_bddIsNsVar + + +
        Defined in cuddAPI.c + +
        +
        +int 
        +Cudd_bddIsPsVar(
        +  DdManager * dd, 
        +  int  index 
        +)
        +
        +
        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. +

        + +

        Side Effects none +

        + +

        See Also Cudd_bddSetPsVar +Cudd_bddIsPiVar +Cudd_bddIsNsVar + + +
        Defined in cuddAPI.c + +
        +
        +int 
        +Cudd_bddIsVarEssential(
        +  DdManager * manager, 
        +  DdNode * f, 
        +  int  id, 
        +  int  phase 
        +)
        +
        +
        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'. +

        + +

        Side Effects None +

        + +

        See Also Cudd_FindEssential + + +
        Defined in cuddEssent.c + +
        +
        +int 
        +Cudd_bddIsVarHardGroup(
        +  DdManager * dd, 
        +  int  index 
        +)
        +
        +
        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. +

        + +

        Side Effects none +

        + +

        See Also Cudd_bddSetVarHardGroup + + +
        Defined in cuddAPI.c + +
        +
        +int 
        +Cudd_bddIsVarToBeGrouped(
        +  DdManager * dd, 
        +  int  index 
        +)
        +
        +
        Checks whether a variable is set to be grouped. This + function is used for lazy sifting. +

        + +

        Side Effects none +

        + +

        Defined in cuddAPI.c + +
        +
        +int 
        +Cudd_bddIsVarToBeUngrouped(
        +  DdManager * dd, 
        +  int  index 
        +)
        +
        +
        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. +

        + +

        Side Effects none +

        + +

        See Also Cudd_bddSetVarToBeUngrouped + + +
        Defined in cuddAPI.c + +
        +
        +DdNode	* 
        +Cudd_bddIsop(
        +  DdManager * dd, 
        +  DdNode * L, 
        +  DdNode * U 
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        See Also Cudd_zddIsop + + +
        Defined in cuddZddIsop.c + +
        +
        +DdNode * 
        +Cudd_bddIteConstant(
        +  DdManager * dd, 
        +  DdNode * f, 
        +  DdNode * g, 
        +  DdNode * h 
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        See Also Cudd_bddIte +Cudd_bddIntersect +Cudd_bddLeq +Cudd_addIteConstant + + +
        Defined in cuddBddIte.c + +
        +
        +int 
        +Cudd_bddIterConjDecomp(
        +  DdManager * dd, manager
        +  DdNode * f, function to be decomposed
        +  DdNode *** conjuncts address of the array of conjuncts
        +)
        +
        +
        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. +

        + +

        Side Effects 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. +

        + +

        See Also Cudd_bddIterDisjDecomp +Cudd_bddApproxConjDecomp +Cudd_bddGenConjDecomp +Cudd_bddVarConjDecomp +Cudd_RemapOverApprox +Cudd_bddSqueeze +Cudd_bddLICompaction + + +
        Defined in cuddDecomp.c + +
        +
        +int 
        +Cudd_bddIterDisjDecomp(
        +  DdManager * dd, manager
        +  DdNode * f, function to be decomposed
        +  DdNode *** disjuncts address of the array of the disjuncts
        +)
        +
        +
        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. +

        + +

        Side Effects 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. +

        + +

        See Also Cudd_bddIterConjDecomp +Cudd_bddApproxDisjDecomp +Cudd_bddGenDisjDecomp +Cudd_bddVarDisjDecomp + + +
        Defined in cuddDecomp.c + +
        +
        +DdNode * 
        +Cudd_bddIte(
        +  DdManager * dd, 
        +  DdNode * f, 
        +  DdNode * g, 
        +  DdNode * h 
        +)
        +
        +
        Implements ITE(f,g,h). Returns a pointer to the + resulting BDD if successful; NULL if the intermediate result blows + up. +

        + +

        Side Effects None +

        + +

        See Also Cudd_addIte +Cudd_bddIteConstant +Cudd_bddIntersect + + +
        Defined in cuddBddIte.c + +
        +
        +DdNode * 
        +Cudd_bddIthVar(
        +  DdManager * dd, 
        +  int  i 
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        See Also Cudd_bddNewVar +Cudd_addIthVar +Cudd_bddNewVarAtLevel +Cudd_ReadVars + + +
        Defined in cuddAPI.c + +
        +
        +DdNode * 
        +Cudd_bddLICompaction(
        +  DdManager * dd, manager
        +  DdNode * f, function to be minimized
        +  DdNode * c constraint (care set)
        +)
        +
        +
        Performs safe minimization of a BDD. Given the BDD + f of a function to be minimized and a BDD + c representing the care set, Cudd_bddLICompaction + produces the BDD of a function that agrees with f + wherever c is 1. Safe minimization means that the size + of the result is guaranteed not to exceed the size of + f. This function is based on the DAC97 paper by Hong et + al.. Returns a pointer to the result if successful; NULL + otherwise. +

        + +

        Side Effects None +

        + +

        See Also Cudd_bddRestrict + + +
        Defined in cuddGenCof.c + +
        +
        +int 
        +Cudd_bddLeqUnless(
        +  DdManager * dd, 
        +  DdNode * f, 
        +  DdNode * g, 
        +  DdNode * D 
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        See Also Cudd_EquivDC +Cudd_bddLeq +Cudd_bddIteConstant + + +
        Defined in cuddSat.c + +
        +
        +int 
        +Cudd_bddLeq(
        +  DdManager * dd, 
        +  DdNode * f, 
        +  DdNode * g 
        +)
        +
        +
        Returns 1 if f is less than or equal to g; 0 otherwise. + No new nodes are created. +

        + +

        Side Effects None +

        + +

        See Also Cudd_bddIteConstant +Cudd_addEvalConst + + +
        Defined in cuddBddIte.c + +
        +
        +DdNode * 
        +Cudd_bddLiteralSetIntersection(
        +  DdManager * dd, 
        +  DdNode * f, 
        +  DdNode * g 
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        Defined in cuddLiteral.c + +
        +
        +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
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        Defined in cuddSat.c + +
        +
        +DdNode * 
        +Cudd_bddMinimize(
        +  DdManager * dd, 
        +  DdNode * f, 
        +  DdNode * c 
        +)
        +
        +
        Finds a small BDD that agrees with f over + c. Returns a pointer to the result if successful; NULL + otherwise. +

        + +

        Side Effects None +

        + +

        See Also Cudd_bddRestrict +Cudd_bddLICompaction +Cudd_bddSqueeze + + +
        Defined in cuddGenCof.c + +
        +
        +DdNode * 
        +Cudd_bddNPAnd(
        +  DdManager * dd, 
        +  DdNode * f, 
        +  DdNode * g 
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        See Also Cudd_bddConstrain +Cudd_bddRestrict + + +
        Defined in cuddGenCof.c + +
        +
        +DdNode * 
        +Cudd_bddNand(
        +  DdManager * dd, 
        +  DdNode * f, 
        +  DdNode * g 
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        See Also Cudd_bddIte +Cudd_addApply +Cudd_bddAnd +Cudd_bddOr +Cudd_bddNor +Cudd_bddXor +Cudd_bddXnor + + +
        Defined in cuddBddIte.c + +
        +
        +DdNode * 
        +Cudd_bddNewVarAtLevel(
        +  DdManager * dd, 
        +  int  level 
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        See Also Cudd_bddNewVar +Cudd_bddIthVar +Cudd_addNewVarAtLevel + + +
        Defined in cuddAPI.c + +
        +
        +DdNode * 
        +Cudd_bddNewVar(
        +  DdManager * dd 
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        See Also Cudd_addNewVar +Cudd_bddIthVar +Cudd_bddNewVarAtLevel + + +
        Defined in cuddAPI.c + +
        +
        +DdNode * 
        +Cudd_bddNor(
        +  DdManager * dd, 
        +  DdNode * f, 
        +  DdNode * g 
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        See Also Cudd_bddIte +Cudd_addApply +Cudd_bddAnd +Cudd_bddOr +Cudd_bddNand +Cudd_bddXor +Cudd_bddXnor + + +
        Defined in cuddBddIte.c + +
        +
        +DdNode * 
        +Cudd_bddOr(
        +  DdManager * dd, 
        +  DdNode * f, 
        +  DdNode * g 
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        See Also Cudd_bddIte +Cudd_addApply +Cudd_bddAnd +Cudd_bddNand +Cudd_bddNor +Cudd_bddXor +Cudd_bddXnor + + +
        Defined in cuddBddIte.c + +
        +
        +DdNode * 
        +Cudd_bddPermute(
        +  DdManager * manager, 
        +  DdNode * node, 
        +  int * permut 
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        See Also Cudd_addPermute +Cudd_bddSwapVariables + + +
        Defined in cuddCompose.c + +
        +
        +DdNode ** 
        +Cudd_bddPickArbitraryMinterms(
        +  DdManager * dd, manager
        +  DdNode * f, function from which to pick k minterms
        +  DdNode ** vars, array of variables
        +  int  n, size of vars
        +  int  k number of minterms to find
        +)
        +
        +
        Picks k on-set minterms evenly distributed from given DD. + The minterms are in terms of vars. The array + vars should contain at least all variables in the + support of f; if this condition is not met the minterms + built by this procedure may not be contained in + f. 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: +
          +
        • It may run out of memory; +
        • the function f may be the constant 0; +
        • the minterms may not be contained in f. +
        +

        + +

        Side Effects None +

        + +

        See Also Cudd_bddPickOneMinterm +Cudd_bddPickOneCube + + +
        Defined in cuddUtil.c + +
        +
        +int 
        +Cudd_bddPickOneCube(
        +  DdManager * ddm, 
        +  DdNode * node, 
        +  char * string 
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        See Also Cudd_bddPickOneMinterm + + +
        Defined in cuddUtil.c + +
        +
        +DdNode * 
        +Cudd_bddPickOneMinterm(
        +  DdManager * dd, manager
        +  DdNode * f, function from which to pick one minterm
        +  DdNode ** vars, array of variables
        +  int  n size of vars
        +)
        +
        +
        Picks one on-set minterm randomly from the given + DD. The minterm is in terms of vars. The array + vars should contain at least all variables in the + support of f; if this condition is not met the minterm + built by this procedure may not be contained in + f. 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: +
          +
        • It may run out of memory; +
        • the function f may be the constant 0; +
        • the minterm may not be contained in f. +
        +

        + +

        Side Effects None +

        + +

        See Also Cudd_bddPickOneCube + + +
        Defined in cuddUtil.c + +
        +
        +int 
        +Cudd_bddPrintCover(
        +  DdManager * dd, 
        +  DdNode * l, 
        +  DdNode * u 
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        See Also Cudd_PrintMinterm + + +
        Defined in cuddUtil.c + +
        +
        +int 
        +Cudd_bddReadPairIndex(
        +  DdManager * dd, 
        +  int  index 
        +)
        +
        +
        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. +

        + +

        Side Effects modifies the manager +

        + +

        See Also Cudd_bddSetPairIndex + + +
        Defined in cuddAPI.c + +
        +
        +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
        +)
        +
        +
        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.

        + 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.

        + 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. +

        + +

        Side Effects 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. +

        + +

        See Also Cudd_addHarwell +Cudd_addRead + + +
        Defined in cuddRead.c + +
        +
        +void 
        +Cudd_bddRealignDisable(
        +  DdManager * unique 
        +)
        +
        +
        Disables realignment of ZDD order to BDD order. +

        + +

        Side Effects None +

        + +

        See Also Cudd_bddRealignEnable +Cudd_bddRealignmentEnabled +Cudd_zddRealignEnable +Cudd_zddRealignmentEnabled + + +
        Defined in cuddAPI.c + +
        +
        +void 
        +Cudd_bddRealignEnable(
        +  DdManager * unique 
        +)
        +
        +
        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 M be the + ratio of the two numbers. For the purpose of realignment, the ZDD + variables from M*i to (M+1)*i-1 are + reagarded as corresponding to BDD variable i. Realignment + is initially disabled. +

        + +

        Side Effects None +

        + +

        See Also Cudd_zddReduceHeap +Cudd_bddRealignDisable +Cudd_bddRealignmentEnabled +Cudd_zddRealignDisable +Cudd_zddRealignmentEnabled + + +
        Defined in cuddAPI.c + +
        +
        +int 
        +Cudd_bddRealignmentEnabled(
        +  DdManager * unique 
        +)
        +
        +
        Returns 1 if the realignment of BDD order to ZDD order is + enabled; 0 otherwise. +

        + +

        Side Effects None +

        + +

        See Also Cudd_bddRealignEnable +Cudd_bddRealignDisable +Cudd_zddRealignEnable +Cudd_zddRealignDisable + + +
        Defined in cuddAPI.c + +
        +
        +int 
        +Cudd_bddResetVarToBeGrouped(
        +  DdManager * dd, 
        +  int  index 
        +)
        +
        +
        Resets a variable not to be grouped. This function is + used for lazy sifting. Returns 1 if successful; 0 otherwise. +

        + +

        Side Effects modifies the manager +

        + +

        See Also Cudd_bddSetVarToBeGrouped +Cudd_bddSetVarHardGroup + + +
        Defined in cuddAPI.c + +
        +
        +DdNode * 
        +Cudd_bddRestrict(
        +  DdManager * dd, 
        +  DdNode * f, 
        +  DdNode * c 
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        See Also Cudd_bddConstrain +Cudd_addRestrict + + +
        Defined in cuddGenCof.c + +
        +
        +int 
        +Cudd_bddSetNsVar(
        +  DdManager * dd, manager
        +  int  index variable index
        +)
        +
        +
        Sets a variable type to next state. The variable type is + used by lazy sifting. Returns 1 if successful; 0 otherwise. +

        + +

        Side Effects modifies the manager +

        + +

        See Also Cudd_bddSetPiVar +Cudd_bddSetPsVar +Cudd_bddIsNsVar + + +
        Defined in cuddAPI.c + +
        +
        +int 
        +Cudd_bddSetPairIndex(
        +  DdManager * dd, manager
        +  int  index, variable index
        +  int  pairIndex corresponding variable index
        +)
        +
        +
        Sets a corresponding pair index for a given index. + These pair indices are present and next state variable. Returns 1 if + successful; 0 otherwise. +

        + +

        Side Effects modifies the manager +

        + +

        See Also Cudd_bddReadPairIndex + + +
        Defined in cuddAPI.c + +
        +
        +int 
        +Cudd_bddSetPiVar(
        +  DdManager * dd, manager
        +  int  index variable index
        +)
        +
        +
        Sets a variable type to primary input. The variable type is + used by lazy sifting. Returns 1 if successful; 0 otherwise. +

        + +

        Side Effects modifies the manager +

        + +

        See Also Cudd_bddSetPsVar +Cudd_bddSetNsVar +Cudd_bddIsPiVar + + +
        Defined in cuddAPI.c + +
        +
        +int 
        +Cudd_bddSetPsVar(
        +  DdManager * dd, manager
        +  int  index variable index
        +)
        +
        +
        Sets a variable type to present state. The variable type is + used by lazy sifting. Returns 1 if successful; 0 otherwise. +

        + +

        Side Effects modifies the manager +

        + +

        See Also Cudd_bddSetPiVar +Cudd_bddSetNsVar +Cudd_bddIsPsVar + + +
        Defined in cuddAPI.c + +
        +
        +int 
        +Cudd_bddSetVarHardGroup(
        +  DdManager * dd, 
        +  int  index 
        +)
        +
        +
        Sets a variable to be a hard group. This function is used + for lazy sifting. Returns 1 if successful; 0 otherwise. +

        + +

        Side Effects modifies the manager +

        + +

        See Also Cudd_bddSetVarToBeGrouped +Cudd_bddResetVarToBeGrouped +Cudd_bddIsVarHardGroup + + +
        Defined in cuddAPI.c + +
        +
        +int 
        +Cudd_bddSetVarToBeGrouped(
        +  DdManager * dd, 
        +  int  index 
        +)
        +
        +
        Sets a variable to be grouped. This function is used for + lazy sifting. Returns 1 if successful; 0 otherwise. +

        + +

        Side Effects modifies the manager +

        + +

        See Also Cudd_bddSetVarHardGroup +Cudd_bddResetVarToBeGrouped + + +
        Defined in cuddAPI.c + +
        +
        +int 
        +Cudd_bddSetVarToBeUngrouped(
        +  DdManager * dd, 
        +  int  index 
        +)
        +
        +
        Sets a variable to be ungrouped. This function is used + for lazy sifting. Returns 1 if successful; 0 otherwise. +

        + +

        Side Effects modifies the manager +

        + +

        See Also Cudd_bddIsVarToBeUngrouped + + +
        Defined in cuddAPI.c + +
        +
        +DdNode * 
        +Cudd_bddSqueeze(
        +  DdManager * dd, manager
        +  DdNode * l, lower bound
        +  DdNode * u upper bound
        +)
        +
        +
        Finds a small BDD in a function interval. Given BDDs + l and u, 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. +

        + +

        Side Effects None +

        + +

        See Also Cudd_bddRestrict +Cudd_bddLICompaction + + +
        Defined in cuddGenCof.c + +
        +
        +DdNode * 
        +Cudd_bddSwapVariables(
        +  DdManager * dd, 
        +  DdNode * f, 
        +  DdNode ** x, 
        +  DdNode ** y, 
        +  int  n 
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        See Also Cudd_bddPermute +Cudd_addSwapVariables + + +
        Defined in cuddCompose.c + +
        +
        +DdNode * 
        +Cudd_bddTransfer(
        +  DdManager * ddSource, 
        +  DdManager * ddDestination, 
        +  DdNode * f 
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        Defined in cuddBridge.c + +
        +
        +int 
        +Cudd_bddUnbindVar(
        +  DdManager * dd, manager
        +  int  index variable index
        +)
        +
        +
        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). +

        + +

        Side Effects Changes the "bindVar" flag in DdSubtable. +

        + +

        See Also Cudd_bddBindVar + + +
        Defined in cuddAPI.c + +
        +
        +DdNode * 
        +Cudd_bddUnivAbstract(
        +  DdManager * manager, 
        +  DdNode * f, 
        +  DdNode * cube 
        +)
        +
        +
        Universally abstracts all the variables in cube from f. + Returns the abstracted BDD if successful; NULL otherwise. +

        + +

        Side Effects None +

        + +

        See Also Cudd_bddExistAbstract +Cudd_addUnivAbstract + + +
        Defined in cuddBddAbs.c + +
        +
        +int 
        +Cudd_bddVarConjDecomp(
        +  DdManager * dd, manager
        +  DdNode * f, function to be decomposed
        +  DdNode *** conjuncts address of the array of conjuncts
        +)
        +
        +
        Conjunctively decomposes one BDD according to a + variable. If f is the function of the BDD and + x is the variable, the decomposition is + (f+x)(f+x'). 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. +

        + +

        Side Effects 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. +

        + +

        See Also Cudd_bddVarDisjDecomp +Cudd_bddGenConjDecomp +Cudd_bddApproxConjDecomp +Cudd_bddIterConjDecomp + + +
        Defined in cuddDecomp.c + +
        +
        +int 
        +Cudd_bddVarDisjDecomp(
        +  DdManager * dd, manager
        +  DdNode * f, function to be decomposed
        +  DdNode *** disjuncts address of the array of the disjuncts
        +)
        +
        +
        Performs two-way disjunctive decomposition of a BDD + according to a variable. If f is the function of the + BDD and x is the variable, the decomposition is + f*x + f*x'. 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. +

        + +

        Side Effects 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. +

        + +

        See Also Cudd_bddVarConjDecomp +Cudd_bddApproxDisjDecomp +Cudd_bddIterDisjDecomp +Cudd_bddGenDisjDecomp + + +
        Defined in cuddDecomp.c + +
        +
        +int 
        +Cudd_bddVarIsBound(
        +  DdManager * dd, manager
        +  int  index variable index
        +)
        +
        +
        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. +

        + +

        Side Effects none +

        + +

        See Also Cudd_bddBindVar +Cudd_bddUnbindVar + + +
        Defined in cuddAPI.c + +
        +
        +int 
        +Cudd_bddVarIsDependent(
        +  DdManager * dd, 
        +  DdNode * f, 
        +  DdNode * var variable
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        Defined in cuddBddAbs.c + +
        +
        +DdNode * 
        +Cudd_bddVarMap(
        +  DdManager * manager, DD manager
        +  DdNode * f function in which to remap variables
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        See Also Cudd_bddPermute +Cudd_bddSwapVariables +Cudd_SetVarMap + + +
        Defined in cuddCompose.c + +
        +
        +DdNode * 
        +Cudd_bddVectorCompose(
        +  DdManager * dd, 
        +  DdNode * f, 
        +  DdNode ** vector 
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        See Also Cudd_bddPermute +Cudd_bddCompose +Cudd_addVectorCompose + + +
        Defined in cuddCompose.c + +
        +
        +DdNode * 
        +Cudd_bddXnor(
        +  DdManager * dd, 
        +  DdNode * f, 
        +  DdNode * g 
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        See Also Cudd_bddIte +Cudd_addApply +Cudd_bddAnd +Cudd_bddOr +Cudd_bddNand +Cudd_bddNor +Cudd_bddXor + + +
        Defined in cuddBddIte.c + +
        +
        +DdNode * 
        +Cudd_bddXorExistAbstract(
        +  DdManager * manager, 
        +  DdNode * f, 
        +  DdNode * g, 
        +  DdNode * cube 
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        See Also Cudd_bddUnivAbstract +Cudd_bddExistAbstract +Cudd_bddAndAbstract + + +
        Defined in cuddBddAbs.c + +
        +
        +DdNode * 
        +Cudd_bddXor(
        +  DdManager * dd, 
        +  DdNode * f, 
        +  DdNode * g 
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        See Also Cudd_bddIte +Cudd_addApply +Cudd_bddAnd +Cudd_bddOr +Cudd_bddNand +Cudd_bddNor +Cudd_bddXnor + + +
        Defined in cuddBddIte.c + +
        +
        +void 
        +Cudd_tlcInfoFree(
        +  DdTlcInfo * t 
        +)
        +
        +
        Frees a DdTlcInfo Structure as well as the memory pointed + by it. +

        + +

        Side Effects None +

        + +

        Defined in cuddEssent.c + +
        +
        +DdNode * 
        +Cudd_zddChange(
        +  DdManager * dd, 
        +  DdNode * P, 
        +  int  var 
        +)
        +
        +
        Substitutes a variable with its complement in a ZDD. + returns a pointer to the result if successful; NULL otherwise. +

        + +

        Side Effects None +

        + +

        Defined in cuddZddSetop.c + +
        +
        +DdNode	* 
        +Cudd_zddComplement(
        +  DdManager * dd, 
        +  DdNode * node 
        +)
        +
        +
        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. +

        + +

        Side Effects The result depends on current variable order. +

        + +

        Defined in cuddZddFuncs.c + +
        +
        +double 
        +Cudd_zddCountDouble(
        +  DdManager * zdd, 
        +  DdNode * P 
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        See Also Cudd_zddCountMinterm +Cudd_zddCount + + +
        Defined in cuddZddCount.c + +
        +
        +double 
        +Cudd_zddCountMinterm(
        +  DdManager * zdd, 
        +  DdNode * node, 
        +  int  path 
        +)
        +
        +
        Counts the number of minterms of the ZDD rooted at + node. This procedure takes a parameter + path 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. +

        + +

        Side Effects None +

        + +

        See Also Cudd_zddCountDouble + + +
        Defined in cuddZddMisc.c + +
        +
        +int 
        +Cudd_zddCount(
        +  DdManager * zdd, 
        +  DdNode * P 
        +)
        +
        +
        Returns an integer representing the number of minterms + in a ZDD. +

        + +

        Side Effects None +

        + +

        See Also Cudd_zddCountDouble + + +
        Defined in cuddZddCount.c + +
        +
        +char * 
        +Cudd_zddCoverPathToString(
        +  DdManager * zdd, DD manager
        +  int * path, path of ZDD representing a cover
        +  char * str pointer to string to use if != NULL
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        See Also Cudd_zddForeachPath + + +
        Defined in cuddZddUtil.c + +
        +
        +int 
        +Cudd_zddDagSize(
        +  DdNode * p_node 
        +)
        +
        +
        Counts the number of nodes in a ZDD. This function + duplicates Cudd_DagSize and is only retained for compatibility. +

        + +

        Side Effects None +

        + +

        See Also Cudd_DagSize + + +
        Defined in cuddZddMisc.c + +
        +
        +DdNode * 
        +Cudd_zddDiffConst(
        +  DdManager * zdd, 
        +  DdNode * P, 
        +  DdNode * Q 
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        See Also Cudd_zddDiff + + +
        Defined in cuddZddSetop.c + +
        +
        +DdNode * 
        +Cudd_zddDiff(
        +  DdManager * dd, 
        +  DdNode * P, 
        +  DdNode * Q 
        +)
        +
        +
        Computes the difference of two ZDDs. Returns a pointer to the + result if successful; NULL otherwise. +

        + +

        Side Effects None +

        + +

        See Also Cudd_zddDiffConst + + +
        Defined in cuddZddSetop.c + +
        +
        +DdNode	* 
        +Cudd_zddDivideF(
        +  DdManager * dd, 
        +  DdNode * f, 
        +  DdNode * g 
        +)
        +
        +
        Modified version of Cudd_zddDivide. This function may + disappear in future releases. +

        + +

        Side Effects None +

        + +

        Defined in cuddZddFuncs.c + +
        +
        +DdNode	* 
        +Cudd_zddDivide(
        +  DdManager * dd, 
        +  DdNode * f, 
        +  DdNode * g 
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        See Also Cudd_zddWeakDiv + + +
        Defined in cuddZddFuncs.c + +
        +
        +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
        +)
        +
        +
        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: +
          +
        • solid line: THEN arcs; +
        • dashed line: ELSE arcs. +
        + The dot options are chosen so that the drawing fits on a letter-size + sheet. +

        + +

        Side Effects None +

        + +

        See Also Cudd_DumpDot +Cudd_zddPrintDebug + + +
        Defined in cuddZddUtil.c + +
        +
        +DdGen * 
        +Cudd_zddFirstPath(
        +  DdManager * zdd, 
        +  DdNode * f, 
        +  int ** path 
        +)
        +
        +
        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.

        + 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.

        + The paths that end in the empty terminal are not enumerated. +

        + +

        Side Effects The first path is returned as a side effect. +

        + +

        See Also Cudd_zddForeachPath +Cudd_zddNextPath +Cudd_GenFree +Cudd_IsGenEmpty + + +
        Defined in cuddZddUtil.c + +
        +
        +DdNode * 
        +Cudd_zddIntersect(
        +  DdManager * dd, 
        +  DdNode * P, 
        +  DdNode * Q 
        +)
        +
        +
        Computes the intersection of two ZDDs. Returns a pointer to + the result if successful; NULL otherwise. +

        + +

        Side Effects None +

        + +

        Defined in cuddZddSetop.c + +
        +
        +DdNode	* 
        +Cudd_zddIsop(
        +  DdManager * dd, 
        +  DdNode * L, 
        +  DdNode * U, 
        +  DdNode ** zdd_I 
        +)
        +
        +
        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 i should have indices 2i and + 2i+1. 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. +

        + +

        Side Effects zdd_I holds the pointer to the ZDD for the ISOP on + successful return. +

        + +

        See Also Cudd_bddIsop +Cudd_zddVarsFromBddVars + + +
        Defined in cuddZddIsop.c + +
        +
        +DdNode * 
        +Cudd_zddIte(
        +  DdManager * dd, 
        +  DdNode * f, 
        +  DdNode * g, 
        +  DdNode * h 
        +)
        +
        +
        Computes the ITE of three ZDDs. Returns a pointer to the + result if successful; NULL otherwise. +

        + +

        Side Effects None +

        + +

        Defined in cuddZddSetop.c + +
        +
        +DdNode * 
        +Cudd_zddIthVar(
        +  DdManager * dd, 
        +  int  i 
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        See Also Cudd_bddIthVar +Cudd_addIthVar + + +
        Defined in cuddAPI.c + +
        +
        +int 
        +Cudd_zddNextPath(
        +  DdGen * gen, 
        +  int ** path 
        +)
        +
        +
        Generates the next path of a ZDD onset, + using generator gen. Returns 0 if the enumeration is completed; 1 + otherwise. +

        + +

        Side Effects The path is returned as a side effect. The + generator is modified. +

        + +

        See Also Cudd_zddForeachPath +Cudd_zddFirstPath +Cudd_GenFree +Cudd_IsGenEmpty + + +
        Defined in cuddZddUtil.c + +
        +
        +DdNode * 
        +Cudd_zddPortFromBdd(
        +  DdManager * dd, 
        +  DdNode * B 
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        See Also Cudd_zddVarsFromBddVars + + +
        Defined in cuddZddPort.c + +
        +
        +DdNode * 
        +Cudd_zddPortToBdd(
        +  DdManager * dd, 
        +  DdNode * f 
        +)
        +
        +
        Converts a ZDD into a BDD. Returns a pointer to the resulting + ZDD if successful; NULL otherwise. +

        + +

        Side Effects None +

        + +

        See Also Cudd_zddPortFromBdd + + +
        Defined in cuddZddPort.c + +
        +
        +int 
        +Cudd_zddPrintCover(
        +  DdManager * zdd, 
        +  DdNode * node 
        +)
        +
        +
        Prints a sum of products from a ZDD representing a cover. + Returns 1 if successful; 0 otherwise. +

        + +

        Side Effects None +

        + +

        See Also Cudd_zddPrintMinterm + + +
        Defined in cuddZddUtil.c + +
        +
        +int 
        +Cudd_zddPrintDebug(
        +  DdManager * zdd, 
        +  DdNode * f, 
        +  int  n, 
        +  int  pr 
        +)
        +
        +
        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 > 0. Specifically: +
          +
        • pr = 0 : prints nothing +
        • pr = 1 : prints counts of nodes and minterms +
        • pr = 2 : prints counts + disjoint sum of products +
        • pr = 3 : prints counts + list of nodes +
        • pr > 3 : prints counts + disjoint sum of products + list of nodes +
        + Returns 1 if successful; 0 otherwise. +

        + +

        Side Effects None +

        + +

        Defined in cuddZddUtil.c + +
        +
        +int 
        +Cudd_zddPrintMinterm(
        +  DdManager * zdd, 
        +  DdNode * node 
        +)
        +
        +
        Prints a disjoint sum of product form for a ZDD. Returns 1 + if successful; 0 otherwise. +

        + +

        Side Effects None +

        + +

        See Also Cudd_zddPrintDebug +Cudd_zddPrintCover + + +
        Defined in cuddZddUtil.c + +
        +
        +void 
        +Cudd_zddPrintSubtable(
        +  DdManager * table 
        +)
        +
        +
        Prints the ZDD table for debugging purposes. +

        + +

        Side Effects None +

        + +

        Defined in cuddZddMisc.c + +
        +
        +DdNode	* 
        +Cudd_zddProduct(
        +  DdManager * dd, 
        +  DdNode * f, 
        +  DdNode * g 
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        See Also Cudd_zddUnateProduct + + +
        Defined in cuddZddFuncs.c + +
        +
        +long 
        +Cudd_zddReadNodeCount(
        +  DdManager * dd 
        +)
        +
        +
        Reports the number of nodes in ZDDs. This + number always includes the two constants 1 and 0. +

        + +

        Side Effects None +

        + +

        See Also Cudd_ReadPeakNodeCount +Cudd_ReadNodeCount + + +
        Defined in cuddAPI.c + +
        +
        +void 
        +Cudd_zddRealignDisable(
        +  DdManager * unique 
        +)
        +
        +
        Disables realignment of ZDD order to BDD order. +

        + +

        Side Effects None +

        + +

        See Also Cudd_zddRealignEnable +Cudd_zddRealignmentEnabled +Cudd_bddRealignEnable +Cudd_bddRealignmentEnabled + + +
        Defined in cuddAPI.c + +
        +
        +void 
        +Cudd_zddRealignEnable(
        +  DdManager * unique 
        +)
        +
        +
        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 M be the + ratio of the two numbers. For the purpose of realignment, the ZDD + variables from M*i to (M+1)*i-1 are + reagarded as corresponding to BDD variable i. Realignment + is initially disabled. +

        + +

        Side Effects None +

        + +

        See Also Cudd_ReduceHeap +Cudd_zddRealignDisable +Cudd_zddRealignmentEnabled +Cudd_bddRealignDisable +Cudd_bddRealignmentEnabled + + +
        Defined in cuddAPI.c + +
        +
        +int 
        +Cudd_zddRealignmentEnabled(
        +  DdManager * unique 
        +)
        +
        +
        Returns 1 if the realignment of ZDD order to BDD order is + enabled; 0 otherwise. +

        + +

        Side Effects None +

        + +

        See Also Cudd_zddRealignEnable +Cudd_zddRealignDisable +Cudd_bddRealignEnable +Cudd_bddRealignDisable + + +
        Defined in cuddAPI.c + +
        +
        +int 
        +Cudd_zddReduceHeap(
        +  DdManager * table, DD manager
        +  Cudd_ReorderingType  heuristic, method used for reordering
        +  int  minsize bound below which no reordering occurs
        +)
        +
        +
        Main dynamic reordering routine for ZDDs. + Calls one of the possible reordering procedures: +
          +
        • Swapping +
        • Sifting +
        • Symmetric Sifting +
        + + For sifting and symmetric sifting it is possible to request reordering + to convergence.

        + + 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. +

        + +

        Side Effects Changes the variable order for all ZDDs and clears + the cache. +

        + +

        Defined in cuddZddReord.c + +
        +
        +int 
        +Cudd_zddShuffleHeap(
        +  DdManager * table, DD manager
        +  int * permutation required variable permutation
        +)
        +
        +
        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. +

        + +

        Side Effects Changes the ZDD variable order for all diagrams and clears + the cache. +

        + +

        See Also Cudd_zddReduceHeap + + +
        Defined in cuddZddReord.c + +
        +
        +DdNode * 
        +Cudd_zddSubset0(
        +  DdManager * dd, 
        +  DdNode * P, 
        +  int  var 
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        See Also Cudd_zddSubset1 + + +
        Defined in cuddZddSetop.c + +
        +
        +DdNode * 
        +Cudd_zddSubset1(
        +  DdManager * dd, 
        +  DdNode * P, 
        +  int  var 
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        See Also Cudd_zddSubset0 + + +
        Defined in cuddZddSetop.c + +
        +
        +void 
        +Cudd_zddSymmProfile(
        +  DdManager * table, 
        +  int  lower, 
        +  int  upper 
        +)
        +
        +
        Prints statistics on symmetric ZDD variables. +

        + +

        Side Effects None +

        + +

        Defined in cuddZddSymm.c + +
        +
        +DdNode	* 
        +Cudd_zddUnateProduct(
        +  DdManager * dd, 
        +  DdNode * f, 
        +  DdNode * g 
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        See Also Cudd_zddProduct + + +
        Defined in cuddZddFuncs.c + +
        +
        +DdNode * 
        +Cudd_zddUnion(
        +  DdManager * dd, 
        +  DdNode * P, 
        +  DdNode * Q 
        +)
        +
        +
        Computes the union of two ZDDs. Returns a pointer to the + result if successful; NULL otherwise. +

        + +

        Side Effects None +

        + +

        Defined in cuddZddSetop.c + +
        +
        +int 
        +Cudd_zddVarsFromBddVars(
        +  DdManager * dd, DD manager
        +  int  multiplicity how many ZDD variables are created for each BDD variable
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        See Also Cudd_bddNewVar +Cudd_bddIthVar +Cudd_bddNewVarAtLevel + + +
        Defined in cuddAPI.c + +
        +
        +DdNode	* 
        +Cudd_zddWeakDivF(
        +  DdManager * dd, 
        +  DdNode * f, 
        +  DdNode * g 
        +)
        +
        +
        Modified version of Cudd_zddWeakDiv. This function may + disappear in future releases. +

        + +

        Side Effects None +

        + +

        See Also Cudd_zddWeakDiv + + +
        Defined in cuddZddFuncs.c + +
        +
        +DdNode	* 
        +Cudd_zddWeakDiv(
        +  DdManager * dd, 
        +  DdNode * f, 
        +  DdNode * g 
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        See Also Cudd_zddDivide + + +
        Defined in cuddZddFuncs.c + +
        +
        +static enum st_retval 
        +MarkCacheCleanUp(
        +  char * key, 
        +  char * value, 
        +  char * arg 
        +)
        +
        +
        Frees memory associated with computed table of + cuddBddLICMarkEdges. Returns ST_CONTINUE. +

        + +

        Side Effects None +

        + +

        See Also Cudd_bddLICompaction + + +
        Defined in cuddGenCof.c + +
        +
        +static int 
        +MarkCacheCompare(
        +  const char * ptr1, 
        +  const char * ptr2 
        +)
        +
        +
        Comparison function for the computed table of + cuddBddLICMarkEdges. Returns 0 if the two nodes of the key are equal; 1 + otherwise. +

        + +

        Side Effects None +

        + +

        See Also Cudd_bddLICompaction + + +
        Defined in cuddGenCof.c + +
        +
        +static int 
        +MarkCacheHash(
        +  char * ptr, 
        +  int  modulus 
        +)
        +
        +
        Hash function for the computed table of + cuddBddLICMarkEdges. Returns the bucket number. +

        + +

        Side Effects None +

        + +

        See Also Cudd_bddLICompaction + + +
        Defined in cuddGenCof.c + +
        +
        +static int 
        +PMX(
        +  int  maxvar 
        +)
        +
        +
        Performs the crossover between two randomly chosen + parents, and creates two children, x1 and x2. Uses the Partially + Matched Crossover operator. +

        + +

        Side Effects None +

        + +

        Defined in cuddGenetic.c + +
        +
        +static int 
        +PairInTables(
        +  DdNode * g, 
        +  DdNode * h, 
        +  st_table * ghTable 
        +)
        +
        +
        .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; +

        + +

        See Also CheckTablesCacheAndReturn +CheckInTables + + +
        Defined in cuddDecomp.c + +
        +
        +static Conjuncts * 
        +PickOnePair(
        +  DdNode * node, 
        +  DdNode * g1, 
        +  DdNode * h1, 
        +  DdNode * g2, 
        +  DdNode * h2, 
        +  st_table * ghTable, 
        +  st_table * cacheTable 
        +)
        +
        +
        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. +

        + +

        See Also ZeroCase +BuildConjuncts + + +
        Defined in cuddDecomp.c + +
        +
        +static DdNode * 
        +RAbuildSubset(
        +  DdManager * dd, DD manager
        +  DdNode * node, current node
        +  ApproxInfo * info node info
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        See Also cuddRemapUnderApprox + + +
        Defined in cuddApprox.c + +
        +
        +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
        +)
        +
        +
        Marks nodes for remapping. Returns 1 if successful; 0 + otherwise. +

        + +

        Side Effects None +

        + +

        See Also cuddRemapUnderApprox + + +
        Defined in cuddApprox.c + +
        +
        +static void 
        +ResizeCountMintermPages(
        +    
        +)
        +
        +
        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. +

        + +

        Side Effects Changes the size of minterm pages, page, page index, maximum + number of pages freeing stuff in case of memory out. +

        + +

        Defined in cuddSubsetHB.c + +
        +
        +static void 
        +ResizeCountNodePages(
        +    
        +)
        +
        +
        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. +

        + +

        Side Effects Changes the size of pages, page, page index, maximum + number of pages freeing stuff in case of memory out. +

        + +

        Defined in cuddSubsetHB.c + +
        +
        +static void 
        +ResizeNodeDataPages(
        +    
        +)
        +
        +
        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. +

        + +

        Side Effects Changes the size of pages, page, page index, maximum + number of pages freeing stuff in case of memory out. +

        + +

        Defined in cuddSubsetHB.c + +
        +
        +static void 
        +ResizeNodeDistPages(
        +    
        +)
        +
        +
        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. +

        + +

        Side Effects Changes the size of pages, page, page index, maximum + number of pages freeing stuff in case of memory out. +

        + +

        Defined in cuddSubsetSP.c + +
        +
        +static void 
        +ResizeQueuePages(
        +    
        +)
        +
        +
        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. +

        + +

        Side Effects Changes the size of pages, page, page index, maximum + number of pages freeing stuff in case of memory out. +

        + +

        Defined in cuddSubsetSP.c + +
        +
        +static void 
        +StoreNodes(
        +  st_table * storeTable, 
        +  DdManager * dd, 
        +  DdNode * node 
        +)
        +
        +
        rocedure to recursively store nodes that are retained in the subset. +

        + +

        Side Effects None +

        + +

        See Also StoreNodes + + +
        Defined in cuddSubsetHB.c + +
        +
        +static double 
        +SubsetCountMintermAux(
        +  DdNode * node, function to analyze
        +  double  max, number of minterms of constant 1
        +  st_table * table visitedTable table
        +)
        +
        +
        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. +

        + +

        Side Effects Creates structures of type node quality and fills the st_table +

        + +

        See Also SubsetCountMinterm + + +
        Defined in cuddSubsetHB.c + +
        +
        +static st_table * 
        +SubsetCountMinterm(
        +  DdNode * node, function to be analyzed
        +  int  nvars number of variables node depends on
        +)
        +
        +
        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. +

        + +

        Side Effects none +

        + +

        See Also SubsetCountMintermAux + + +
        Defined in cuddSubsetHB.c + +
        +
        +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
        +)
        +
        +
        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. +

        + +

        Side Effects Updates the node data table with node counts +

        + +

        See Also SubsetCountNodes + + +
        Defined in cuddSubsetHB.c + +
        +
        +static int 
        +SubsetCountNodes(
        +  DdNode * node, function to be analyzed
        +  st_table * table, node quality table
        +  int  nvars number of variables node depends on
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        See Also SubsetCountNodesAux + + +
        Defined in cuddSubsetHB.c + +
        +
        +static DdNode * 
        +UAbuildSubset(
        +  DdManager * dd, DD manager
        +  DdNode * node, current node
        +  ApproxInfo * info node info
        +)
        +
        +
        Builds the subset BDD. Based on the info table, + replaces selected nodes by zero. Returns a pointer to the result if + successful; NULL otherwise. +

        + +

        Side Effects None +

        + +

        See Also cuddUnderApprox + + +
        Defined in cuddApprox.c + +
        +
        +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
        +)
        +
        +
        Marks nodes for replacement by zero. Returns 1 if successful; + 0 otherwise. +

        + +

        Side Effects None +

        + +

        See Also cuddUnderApprox + + +
        Defined in cuddApprox.c + +
        +
        +static Conjuncts * 
        +ZeroCase(
        +  DdManager * dd, 
        +  DdNode * node, 
        +  Conjuncts * factorsNv, 
        +  st_table * ghTable, 
        +  st_table * cacheTable, 
        +  int  switched 
        +)
        +
        +
        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. +

        + +

        Side Effects Frees the BDDs in factorsNv. factorsNv itself is not freed + because it is freed above. +

        + +

        See Also BuildConjuncts + + +
        Defined in cuddDecomp.c + +
        +
        +static DdNode * 
        +addBddDoInterval(
        +  DdManager * dd, 
        +  DdNode * f, 
        +  DdNode * l, 
        +  DdNode * u 
        +)
        +
        +
        Performs the recursive step for Cudd_addBddInterval. + Returns a pointer to the BDD if successful; NULL otherwise. +

        + +

        Side Effects None +

        + +

        See Also addBddDoThreshold +addBddDoStrictThreshold + + +
        Defined in cuddBridge.c + +
        +
        +static DdNode * 
        +addBddDoIthBit(
        +  DdManager * dd, 
        +  DdNode * f, 
        +  DdNode * index 
        +)
        +
        +
        Performs the recursive step for Cudd_addBddIthBit. + Returns a pointer to the BDD if successful; NULL otherwise. +

        + +

        Side Effects None +

        + +

        Defined in cuddBridge.c + +
        +
        +static DdNode * 
        +addBddDoStrictThreshold(
        +  DdManager * dd, 
        +  DdNode * f, 
        +  DdNode * val 
        +)
        +
        +
        Performs the recursive step for Cudd_addBddStrictThreshold. + Returns a pointer to the BDD if successful; NULL otherwise. +

        + +

        Side Effects None +

        + +

        See Also addBddDoThreshold + + +
        Defined in cuddBridge.c + +
        +
        +static DdNode * 
        +addBddDoThreshold(
        +  DdManager * dd, 
        +  DdNode * f, 
        +  DdNode * val 
        +)
        +
        +
        Performs the recursive step for Cudd_addBddThreshold. + Returns a pointer to the BDD if successful; NULL otherwise. +

        + +

        Side Effects None +

        + +

        See Also addBddDoStrictThreshold + + +
        Defined in cuddBridge.c + +
        +
        +static int 
        +addCheckPositiveCube(
        +  DdManager * manager, 
        +  DdNode * cube 
        +)
        +
        +
        Checks whether cube is an ADD representing the product of + positive literals. Returns 1 in case of success; 0 otherwise. +

        + +

        Side Effects None +

        + +

        Defined in cuddAddAbs.c + +
        +
        +static DdNode * 
        +addDoIthBit(
        +  DdManager * dd, 
        +  DdNode * f, 
        +  DdNode * index 
        +)
        +
        +
        Performs the recursive step for Cudd_addIthBit. + Returns a pointer to the BDD if successful; NULL otherwise. +

        + +

        Side Effects None +

        + +

        Defined in cuddAddFind.c + +
        +
        +static DdNode * 
        +addMMRecur(
        +  DdManager * dd, 
        +  DdNode * A, 
        +  DdNode * B, 
        +  int  topP, 
        +  int * vars 
        +)
        +
        +
        Performs the recursive step of Cudd_addMatrixMultiply. + Returns a pointer to the result if successful; NULL otherwise. +

        + +

        Side Effects None +

        + +

        Defined in cuddMatMult.c + +
        +
        +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
        +)
        +
        +
        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. +

        + +

        Side Effects Changes the variable group tree. +

        + +

        See Also Cudd_zddVarsFromBddVars + + +
        Defined in cuddAPI.c + +
        +
        +static DdNode * 
        +addTriangleRecur(
        +  DdManager * dd, 
        +  DdNode * f, 
        +  DdNode * g, 
        +  int * vars, 
        +  DdNode * cube 
        +)
        +
        +
        Performs the recursive step of Cudd_addTriangle. Returns + a pointer to the result if successful; NULL otherwise. +

        + +

        Side Effects None +

        + +

        Defined in cuddMatMult.c + +
        +
        +static void 
        +addVarToConst(
        +  DdNode * f, 
        +  DdNode ** gp, 
        +  DdNode ** hp, 
        +  DdNode * one, 
        +  DdNode * zero 
        +)
        +
        +
        Replaces variables with constants if possible (part of + canonical form). +

        + +

        Side Effects None +

        + +

        Defined in cuddAddIte.c + +
        +
        +static DdNode * 
        +addWalshInt(
        +  DdManager * dd, 
        +  DdNode ** x, 
        +  DdNode ** y, 
        +  int  n 
        +)
        +
        +
        Generates a Walsh matrix in ADD form. Returns a pointer + to the matrixi if successful; NULL otherwise. +

        + +

        Side Effects None +

        + +

        Defined in cuddAddWalsh.c + +
        +
        +static int 
        +array_compare(
        +  const char * array1, 
        +  const char * array2 
        +)
        +
        +
        Comparison function for the computed table. Returns 0 if + the two arrays are equal; 1 otherwise. +

        + +

        Side Effects None +

        + +

        Defined in cuddGenetic.c + +
        +
        +static int 
        +array_hash(
        +  char * array, 
        +  int  modulus 
        +)
        +
        +
        Hash function for the computed table. Returns the bucket + number. +

        + +

        Side Effects None +

        + +

        Defined in cuddGenetic.c + +
        +
        +static double 
        +bddAnnotateMintermCount(
        +  DdManager * manager, 
        +  DdNode * node, 
        +  double  max, 
        +  st_table * table 
        +)
        +
        +
        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. +

        + +

        Side Effects Fills up 'table' with the pair . +

        + +

        Defined in cuddSplit.c + +
        +
        +static int 
        +bddCheckPositiveCube(
        +  DdManager * manager, 
        +  DdNode * cube 
        +)
        +
        +
        Returns 1 in case of success; 0 otherwise. +

        + +

        Side Effects None +

        + +

        Defined in cuddBddAbs.c + +
        +
        +static double 
        +bddCorrelationAux(
        +  DdManager * dd, 
        +  DdNode * f, 
        +  DdNode * g, 
        +  st_table * table 
        +)
        +
        +
        Performs the recursive step of Cudd_bddCorrelation. + Returns the fraction of minterms in the ON-set of the EXNOR of f and + g. +

        + +

        Side Effects None +

        + +

        See Also bddCorrelationWeightsAux + + +
        Defined in cuddBddCorr.c + +
        +
        +static double 
        +bddCorrelationWeightsAux(
        +  DdManager * dd, 
        +  DdNode * f, 
        +  DdNode * g, 
        +  double * prob, 
        +  st_table * table 
        +)
        +
        +
        Performs the recursive step of Cudd_bddCorrelationWeigths. +

        + +

        Side Effects None +

        + +

        See Also bddCorrelationAux + + +
        Defined in cuddBddCorr.c + +
        +
        +static void 
        +bddFixTree(
        +  DdManager * table, 
        +  MtrNode * treenode 
        +)
        +
        +
        Fixes the BDD variable group tree after a + shuffle. Assumes that the order of the variables in a terminal node + has not been changed. +

        + +

        Side Effects Changes the BDD variable group tree. +

        + +

        Defined in cuddReorder.c + +
        +
        +static int 
        +bddVarToCanonicalSimple(
        +  DdManager * dd, 
        +  DdNode ** fp, 
        +  DdNode ** gp, 
        +  DdNode ** hp, 
        +  unsigned int * topfp, 
        +  unsigned int * topgp, 
        +  unsigned int * tophp 
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        See Also bddVarToConst +bddVarToCanonical + + +
        Defined in cuddBddIte.c + +
        +
        +static int 
        +bddVarToCanonical(
        +  DdManager * dd, 
        +  DdNode ** fp, 
        +  DdNode ** gp, 
        +  DdNode ** hp, 
        +  unsigned int * topfp, 
        +  unsigned int * topgp, 
        +  unsigned int * tophp 
        +)
        +
        +
        Reduces 2 variable expressions to canonical form. +

        + +

        Side Effects None +

        + +

        See Also bddVarToConst +bddVarToCanonicalSimple + + +
        Defined in cuddBddIte.c + +
        +
        +static void 
        +bddVarToConst(
        +  DdNode * f, 
        +  DdNode ** gp, 
        +  DdNode ** hp, 
        +  DdNode * one 
        +)
        +
        +
        This function performs part of the transformation to + standard form by replacing variables with constants if possible. +

        + +

        Side Effects None +

        + +

        See Also bddVarToCanonical +bddVarToCanonicalSimple + + +
        Defined in cuddBddIte.c + +
        +
        +static int 
        +beforep(
        +  DdHalfWord  var1a, 
        +  short  phase1a, 
        +  DdHalfWord  var1b, 
        +  short  phase1b, 
        +  DdHalfWord  var2a, 
        +  short  phase2a, 
        +  DdHalfWord  var2b, 
        +  short  phase2b 
        +)
        +
        +
        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). +

        + +

        Side Effects None +

        + +

        See Also equalp + + +
        Defined in cuddEssent.c + +
        +
        +static BitVector * 
        +bitVectorAlloc(
        +  int  size 
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        See Also bitVectorClear +bitVectorFree + + +
        Defined in cuddEssent.c + +
        +
        +static void 
        +bitVectorClear(
        +  BitVector * vector, 
        +  int  size 
        +)
        +
        +
        Clears a bit vector. The parameter size gives the + number of bits. +

        + +

        Side Effects None +

        + +

        See Also bitVectorAlloc + + +
        Defined in cuddEssent.c + +
        +
        +static void 
        +bitVectorFree(
        +  BitVector * vector 
        +)
        +
        +
        Frees a bit vector. +

        + +

        Side Effects None +

        + +

        See Also bitVectorAlloc + + +
        Defined in cuddEssent.c + +
        +
        +static short 
        +bitVectorRead(
        +  BitVector * vector, 
        +  int  i 
        +)
        +
        +
        Returns the i-th entry of a bit vector. +

        + +

        Side Effects None +

        + +

        See Also bitVectorSet + + +
        Defined in cuddEssent.c + +
        +
        +static void 
        +bitVectorSet(
        +  BitVector * vector, 
        +  int  i, 
        +  short  val 
        +)
        +
        +
        Sets the i-th entry of a bit vector to a value. +

        + +

        Side Effects None +

        + +

        See Also bitVectorRead + + +
        Defined in cuddEssent.c + +
        +
        +static int 
        +build_dd(
        +  DdManager * table, 
        +  int  num, the index of the individual to be built
        +  int  lower, 
        +  int  upper 
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        Defined in cuddGenetic.c + +
        +
        +static int 
        +checkSymmInfo(
        +  DdManager * table, 
        +  DdHalfWord * symmInfo, 
        +  int  index, 
        +  int  level 
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        See Also initSymmInfo + + +
        Defined in cuddExact.c + +
        +
        +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
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        See Also computeClauses + + +
        Defined in cuddEssent.c + +
        +
        +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
        +)
        +
        +
        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. +

        + +

        Side Effects None +

        + +

        See Also computeClausesWithUniverse + + +
        Defined in cuddEssent.c + +
        +
        +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
        +)
        +
        +
        Computes a lower bound on the size of a BDD from the + following factors: +
          +
        • size of the lower part of it; +
        • size of the part of the upper part not subjected to reordering; +
        • number of roots in the part of the BDD subjected to reordering; +
        • variable in the support of the roots in the upper part of the + BDD subjected to reordering. +
            +

            + +

            Side Effects None +

            + +

            Defined in cuddExact.c + +
            +
            +static int 
            +computeSavings(
            +  DdManager * dd, 
            +  DdNode * f, 
            +  DdNode * skip, 
            +  ApproxInfo * info, 
            +  DdLevelQueue * queue 
            +)
            +
            +
            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. +

            + +

            Side Effects None +

            + +

            See Also cuddUnderApprox + + +
            Defined in cuddApprox.c + +
            +
            +static void 
            +copyOrder(
            +  DdManager * table, 
            +  int * array, 
            +  int  lower, 
            +  int  upper 
            +)
            +
            +
            Copies the current variable order to array. + At the same time inverts the permutation. +

            + +

            Side Effects None +

            + +

            Defined in cuddAnneal.c + +
            +
            +static DdNode * 
            +createResult(
            +  DdManager * dd, 
            +  unsigned int  index, 
            +  unsigned int  phase, 
            +  DdNode * cube, 
            +  CUDD_VALUE_TYPE  distance 
            +)
            +
            +
            Builds a result for cache storage. Returns a pointer + to the resulting ADD if successful; NULL otherwise. +

            + +

            Side Effects None +

            + +

            See Also cuddBddClosestCube +separateCube + + +
            Defined in cuddPriority.c + +
            +
            +DdNode * 
            +cuddAddApplyRecur(
            +  DdManager * dd, 
            +  DD_AOP  op, 
            +  DdNode * f, 
            +  DdNode * g 
            +)
            +
            +
            Performs the recursive step of Cudd_addApply. Returns a + pointer to the result if successful; NULL otherwise. +

            + +

            Side Effects None +

            + +

            See Also cuddAddMonadicApplyRecur + + +
            Defined in cuddAddApply.c + +
            +
            +DdNode * 
            +cuddAddBddDoPattern(
            +  DdManager * dd, 
            +  DdNode * f 
            +)
            +
            +
            Performs the recursive step for Cudd_addBddPattern. Returns a + pointer to the resulting BDD if successful; NULL otherwise. +

            + +

            Side Effects None +

            + +

            Defined in cuddBridge.c + +
            +
            +DdNode * 
            +cuddAddCmplRecur(
            +  DdManager * dd, 
            +  DdNode * f 
            +)
            +
            +
            Performs the recursive step of Cudd_addCmpl. Returns a + pointer to the resulting ADD if successful; NULL otherwise. +

            + +

            Side Effects None +

            + +

            See Also Cudd_addCmpl + + +
            Defined in cuddAddIte.c + +
            +
            +DdNode * 
            +cuddAddComposeRecur(
            +  DdManager * dd, 
            +  DdNode * f, 
            +  DdNode * g, 
            +  DdNode * proj 
            +)
            +
            +
            Performs the recursive step of Cudd_addCompose. + Returns the composed BDD if successful; NULL otherwise. +

            + +

            Side Effects None +

            + +

            See Also Cudd_addCompose + + +
            Defined in cuddCompose.c + +
            +
            +DdNode * 
            +cuddAddConstrainRecur(
            +  DdManager * dd, 
            +  DdNode * f, 
            +  DdNode * c 
            +)
            +
            +
            Performs the recursive step of Cudd_addConstrain. + Returns a pointer to the result if successful; NULL otherwise. +

            + +

            Side Effects None +

            + +

            See Also Cudd_addConstrain + + +
            Defined in cuddGenCof.c + +
            +
            +DdNode * 
            +cuddAddExistAbstractRecur(
            +  DdManager * manager, 
            +  DdNode * f, 
            +  DdNode * cube 
            +)
            +
            +
            Performs the recursive step of Cudd_addExistAbstract. + Returns the ADD obtained by abstracting the variables of cube from f, + if successful; NULL otherwise. +

            + +

            Side Effects None +

            + +

            Defined in cuddAddAbs.c + +
            +
            +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
            +)
            +
            +
            Performs the recursive step of Cudd_addGeneralVectorCompose. +

            + +

            Side Effects None +

            + +

            Defined in cuddCompose.c + +
            +
            +DdNode * 
            +cuddAddIteRecur(
            +  DdManager * dd, 
            +  DdNode * f, 
            +  DdNode * g, 
            +  DdNode * h 
            +)
            +
            +
            Implements the recursive step of Cudd_addIte(f,g,h). + Returns a pointer to the resulting ADD if successful; NULL + otherwise. +

            + +

            Side Effects None +

            + +

            See Also Cudd_addIte + + +
            Defined in cuddAddIte.c + +
            +
            +DdNode * 
            +cuddAddMonadicApplyRecur(
            +  DdManager * dd, 
            +  DD_MAOP  op, 
            +  DdNode * f 
            +)
            +
            +
            Performs the recursive step of Cudd_addMonadicApply. Returns a + pointer to the result if successful; NULL otherwise. +

            + +

            Side Effects None +

            + +

            See Also cuddAddApplyRecur + + +
            Defined in cuddAddApply.c + +
            +
            +DdNode * 
            +cuddAddNegateRecur(
            +  DdManager * dd, 
            +  DdNode * f 
            +)
            +
            +
            Implements the recursive step of Cudd_addNegate. + Returns a pointer to the result. +

            + +

            Side Effects None +

            + +

            Defined in cuddAddNeg.c + +
            +
            +static DdNode * 
            +cuddAddNonSimComposeRecur(
            +  DdManager * dd, 
            +  DdNode * f, 
            +  DdNode ** vector, 
            +  DdNode * key, 
            +  DdNode * cube, 
            +  int  lastsub 
            +)
            +
            +
            Performs the recursive step of Cudd_addNonSimCompose. +

            + +

            Side Effects None +

            + +

            Defined in cuddCompose.c + +
            +
            +DdNode * 
            +cuddAddOrAbstractRecur(
            +  DdManager * manager, 
            +  DdNode * f, 
            +  DdNode * cube 
            +)
            +
            +
            Performs the recursive step of Cudd_addOrAbstract. + Returns the ADD obtained by abstracting the variables of cube from f, + if successful; NULL otherwise. +

            + +

            Side Effects None +

            + +

            Defined in cuddAddAbs.c + +
            +
            +static DdNode * 
            +cuddAddOuterSumRecur(
            +  DdManager * dd, 
            +  DdNode * M, 
            +  DdNode * r, 
            +  DdNode * c 
            +)
            +
            +
            Performs the recursive step of Cudd_addOuterSum. + Returns a pointer to the result if successful; NULL otherwise. +

            + +

            Side Effects None +

            + +

            Defined in cuddMatMult.c + +
            +
            +static DdNode * 
            +cuddAddPermuteRecur(
            +  DdManager * manager, DD manager
            +  DdHashTable * table, computed table
            +  DdNode * node, ADD to be reordered
            +  int * permut permutation array
            +)
            +
            +
            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.

            + The DdNode * that is returned is the same ADD as passed in as node, + but in the new order. +

            + +

            Side Effects None +

            + +

            See Also Cudd_addPermute +cuddBddPermuteRecur + + +
            Defined in cuddCompose.c + +
            +
            +DdNode * 
            +cuddAddRestrictRecur(
            +  DdManager * dd, 
            +  DdNode * f, 
            +  DdNode * c 
            +)
            +
            +
            Performs the recursive step of Cudd_addRestrict. + Returns the restricted ADD if successful; otherwise NULL. +

            + +

            Side Effects None +

            + +

            See Also Cudd_addRestrict + + +
            Defined in cuddGenCof.c + +
            +
            +DdNode * 
            +cuddAddRoundOffRecur(
            +  DdManager * dd, 
            +  DdNode * f, 
            +  double  trunc 
            +)
            +
            +
            Implements the recursive step of Cudd_addRoundOff. + Returns a pointer to the result. +

            + +

            Side Effects None +

            + +

            Defined in cuddAddNeg.c + +
            +
            +DdNode * 
            +cuddAddScalarInverseRecur(
            +  DdManager * dd, 
            +  DdNode * f, 
            +  DdNode * epsilon 
            +)
            +
            +
            Returns a pointer to the resulting ADD in case of + success. Returns NULL if any discriminants smaller than epsilon is + encountered. +

            + +

            Side Effects None +

            + +

            Defined in cuddAddInv.c + +
            +
            +DdNode * 
            +cuddAddUnivAbstractRecur(
            +  DdManager * manager, 
            +  DdNode * f, 
            +  DdNode * cube 
            +)
            +
            +
            Performs the recursive step of Cudd_addUnivAbstract. + Returns the ADD obtained by abstracting the variables of cube from f, + if successful; NULL otherwise. +

            + +

            Side Effects None +

            + +

            Defined in cuddAddAbs.c + +
            +
            +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
            +)
            +
            +
            Performs the recursive step of Cudd_addVectorCompose. +

            + +

            Side Effects None +

            + +

            Defined in cuddCompose.c + +
            +
            +DdNode * 
            +cuddAllocNode(
            +  DdManager * unique 
            +)
            +
            +
            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. +

            + +

            Side Effects None +

            + +

            See Also cuddDynamicAllocNode + + +
            Defined in cuddTable.c + +
            +
            +int 
            +cuddAnnealing(
            +  DdManager * table, 
            +  int  lower, 
            +  int  upper 
            +)
            +
            +
            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. +

            + +

            Side Effects None +

            + +

            Defined in cuddAnneal.c + +
            +
            +static DdApaNumber 
            +cuddApaCountMintermAux(
            +  DdNode * node, 
            +  int  digits, 
            +  DdApaNumber  max, 
            +  DdApaNumber  min, 
            +  st_table * table 
            +)
            +
            +
            Performs the recursive step of Cudd_ApaCountMinterm. + It is based on the following identity. Let |f| be the + number of minterms of f. Then: + + |f| = (|f0|+|f1|)/2 + + where f0 and f1 are the two cofactors of f. + Uses the identity |f'| = max - |f|. + 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. +

            + +

            Side Effects None +

            + +

            Defined in cuddApa.c + +
            +
            +static enum st_retval 
            +cuddApaStCountfree(
            +  char * key, 
            +  char * value, 
            +  char * arg 
            +)
            +
            +
            Frees the memory used to store the minterm counts + recorded in the visited table. Returns ST_CONTINUE. +

            + +

            Side Effects None +

            + +

            Defined in cuddApa.c + +
            +
            +int 
            +cuddBddAlignToZdd(
            +  DdManager * table DD manager
            +)
            +
            +
            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 + M be the ratio of the two numbers. cuddBddAlignToZdd + then considers the ZDD variables from M*i to + (M+1)*i-1 as corresponding to BDD variable + i. This function should be normally called from + Cudd_zddReduceHeap, which clears the cache. Returns 1 in case of + success; 0 otherwise. +

            + +

            Side Effects Changes the BDD variable order for all diagrams and performs + garbage collection of the BDD unique table. +

            + +

            See Also Cudd_ShuffleHeap +Cudd_zddReduceHeap + + +
            Defined in cuddReorder.c + +
            +
            +DdNode * 
            +cuddBddAndAbstractRecur(
            +  DdManager * manager, 
            +  DdNode * f, 
            +  DdNode * g, 
            +  DdNode * cube 
            +)
            +
            +
            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. +

            + +

            Side Effects None +

            + +

            See Also Cudd_bddAndAbstract + + +
            Defined in cuddAndAbs.c + +
            +
            +DdNode * 
            +cuddBddAndRecur(
            +  DdManager * manager, 
            +  DdNode * f, 
            +  DdNode * g 
            +)
            +
            +
            Implements the recursive step of Cudd_bddAnd by taking + the conjunction of two BDDs. Returns a pointer to the result is + successful; NULL otherwise. +

            + +

            Side Effects None +

            + +

            See Also Cudd_bddAnd + + +
            Defined in cuddBddIte.c + +
            +
            +DdNode * 
            +cuddBddBooleanDiffRecur(
            +  DdManager * manager, 
            +  DdNode * f, 
            +  DdNode * var 
            +)
            +
            +
            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. +

            + +

            Side Effects None +

            + +

            Defined in cuddBddAbs.c + +
            +
            +static DdNode * 
            +cuddBddCharToVect(
            +  DdManager * dd, 
            +  DdNode * f, 
            +  DdNode * x 
            +)
            +
            +
            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. +

            + +

            Side Effects None +

            + +

            See Also Cudd_bddCharToVect + + +
            Defined in cuddGenCof.c + +
            +
            +static DdNode * 
            +cuddBddClipAndAbsRecur(
            +  DdManager * manager, 
            +  DdNode * f, 
            +  DdNode * g, 
            +  DdNode * cube, 
            +  int  distance, 
            +  int  direction 
            +)
            +
            +
            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. +

            + +

            Side Effects None +

            + +

            See Also Cudd_bddClippingAndAbstract + + +
            Defined in cuddClip.c + +
            +
            +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
            +)
            +
            +
            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. +

            + +

            Side Effects None +

            + +

            See Also Cudd_bddClippingAndAbstract + + +
            Defined in cuddClip.c + +
            +
            +static DdNode * 
            +cuddBddClippingAndRecur(
            +  DdManager * manager, 
            +  DdNode * f, 
            +  DdNode * g, 
            +  int  distance, 
            +  int  direction 
            +)
            +
            +
            Implements the recursive step of Cudd_bddClippingAnd by taking + the conjunction of two BDDs. Returns a pointer to the result is + successful; NULL otherwise. +

            + +

            Side Effects None +

            + +

            See Also cuddBddClippingAnd + + +
            Defined in cuddClip.c + +
            +
            +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
            +)
            +
            +
            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. +

            + +

            Side Effects None +

            + +

            See Also Cudd_bddClippingAnd + + +
            Defined in cuddClip.c + +
            +
            +DdNode * 
            +cuddBddClosestCube(
            +  DdManager * dd, 
            +  DdNode * f, 
            +  DdNode * g, 
            +  CUDD_VALUE_TYPE  bound 
            +)
            +
            +
            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 + f and g according to the following formula. +
            +    H(f,g) = min(H(ft,gt), H(fe,ge), H(ft,ge)+1, H(fe,gt)+1)
            +  
            + Bounding is based on the following observations. +
              +
            • If we already found two points at distance 0, there is no point in + continuing. Furthermore, +
            • 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.) +
            + The variable bound is set at the largest value of the distance + that we are still interested in. Therefore, we desist when +
            +    (bound == -1) and (F != not(G)) or (bound == 0) and (F == not(G)).
            +  
            + 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 +
            +    bound < minD,
            +  
            + except at the very beginning, when we have no value for + minD.

            + + However, we do not use bound < minD 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.

            + + When we compute H(ft,ge) and H(fe,gt) 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.

            + + Another important observation concerns the need of examining all + four pairs of cofators only when both f and + g depend on the top variable.

            + + Suppose gt == ge == g. (That is, g does + not depend on the top variable.) Then +

            +    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)) .
            +  
            + Therefore, under these circumstances, we skip the two "cross" cases.

            + + 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). +

            + +

            Side Effects None +

            + +

            See Also Cudd_bddClosestCube + + +
            Defined in cuddPriority.c + +
            +
            +DdNode * 
            +cuddBddComposeRecur(
            +  DdManager * dd, 
            +  DdNode * f, 
            +  DdNode * g, 
            +  DdNode * proj 
            +)
            +
            +
            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. +

            + +

            Side Effects None +

            + +

            See Also Cudd_bddCompose + + +
            Defined in cuddCompose.c + +
            +
            +static int 
            +cuddBddConstrainDecomp(
            +  DdManager * dd, 
            +  DdNode * f, 
            +  DdNode ** decomp 
            +)
            +
            +
            Performs the recursive step of Cudd_bddConstrainDecomp. + Returns f super (i) if successful; otherwise NULL. +

            + +

            Side Effects None +

            + +

            See Also Cudd_bddConstrainDecomp + + +
            Defined in cuddGenCof.c + +
            +
            +DdNode * 
            +cuddBddConstrainRecur(
            +  DdManager * dd, 
            +  DdNode * f, 
            +  DdNode * c 
            +)
            +
            +
            Performs the recursive step of Cudd_bddConstrain. + Returns a pointer to the result if successful; NULL otherwise. +

            + +

            Side Effects None +

            + +

            See Also Cudd_bddConstrain + + +
            Defined in cuddGenCof.c + +
            +
            +DdNode * 
            +cuddBddExistAbstractRecur(
            +  DdManager * manager, 
            +  DdNode * f, 
            +  DdNode * cube 
            +)
            +
            +
            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. +

            + +

            Side Effects None +

            + +

            See Also Cudd_bddExistAbstract +Cudd_bddUnivAbstract + + +
            Defined in cuddBddAbs.c + +
            +
            +DdNode * 
            +cuddBddIntersectRecur(
            +  DdManager * dd, 
            +  DdNode * f, 
            +  DdNode * g 
            +)
            +
            +
            Implements the recursive step of Cudd_bddIntersect. +

            + +

            Side Effects None +

            + +

            See Also Cudd_bddIntersect + + +
            Defined in cuddBddIte.c + +
            +
            +DdNode	* 
            +cuddBddIsop(
            +  DdManager * dd, 
            +  DdNode * L, 
            +  DdNode * U 
            +)
            +
            +
            Performs the recursive step of Cudd_bddIsop. +

            + +

            Side Effects None +

            + +

            See Also Cudd_bddIsop + + +
            Defined in cuddZddIsop.c + +
            +
            +DdNode * 
            +cuddBddIteRecur(
            +  DdManager * dd, 
            +  DdNode * f, 
            +  DdNode * g, 
            +  DdNode * h 
            +)
            +
            +
            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. +

            + +

            Side Effects None +

            + +

            Defined in cuddBddIte.c + +
            +
            +static DdNode * 
            +cuddBddLICBuildResult(
            +  DdManager * dd, 
            +  DdNode * f, 
            +  st_table * cache, 
            +  st_table * table 
            +)
            +
            +
            Builds the results of Cudd_bddLICompaction. + Returns a pointer to the minimized BDD if successful; otherwise NULL. +

            + +

            Side Effects None +

            + +

            See Also Cudd_bddLICompaction +cuddBddLICMarkEdges + + +
            Defined in cuddGenCof.c + +
            +
            +static int 
            +cuddBddLICMarkEdges(
            +  DdManager * dd, 
            +  DdNode * f, 
            +  DdNode * c, 
            +  st_table * table, 
            +  st_table * cache 
            +)
            +
            +
            Performs the edge marking step of Cudd_bddLICompaction. + Returns the LUB of the markings of the two outgoing edges of f + if successful; otherwise CUDD_OUT_OF_MEM. +

            + +

            Side Effects None +

            + +

            See Also Cudd_bddLICompaction +cuddBddLICBuildResult + + +
            Defined in cuddGenCof.c + +
            +
            +DdNode * 
            +cuddBddLICompaction(
            +  DdManager * dd, manager
            +  DdNode * f, function to be minimized
            +  DdNode * c constraint (care set)
            +)
            +
            +
            Performs safe minimization of a BDD. Given the BDD + f of a function to be minimized and a BDD + c representing the care set, Cudd_bddLICompaction + produces the BDD of a function that agrees with f + wherever c is 1. Safe minimization means that the size + of the result is guaranteed not to exceed the size of + f. This function is based on the DAC97 paper by Hong et + al.. Returns a pointer to the result if successful; NULL + otherwise. +

            + +

            Side Effects None +

            + +

            See Also Cudd_bddLICompaction + + +
            Defined in cuddGenCof.c + +
            +
            +DdNode * 
            +cuddBddLiteralSetIntersectionRecur(
            +  DdManager * dd, 
            +  DdNode * f, 
            +  DdNode * g 
            +)
            +
            +
            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. +

            + +

            Side Effects None +

            + +

            Defined in cuddLiteral.c + +
            +
            +DdNode * 
            +cuddBddMakePrime(
            +  DdManager * dd, manager
            +  DdNode * cube, cube to be expanded
            +  DdNode * f function of which the cube is to be made a prime
            +)
            +
            +
            Performs the recursive step of Cudd_bddMakePrime. + Returns the prime if successful; NULL otherwise. +

            + +

            Side Effects None +

            + +

            Defined in cuddSat.c + +
            +
            +DdNode * 
            +cuddBddNPAndRecur(
            +  DdManager * manager, 
            +  DdNode * f, 
            +  DdNode * g 
            +)
            +
            +
            Implements the recursive step of Cudd_bddNPAnd. + Returns a pointer to the result is successful; NULL otherwise. +

            + +

            Side Effects None +

            + +

            See Also Cudd_bddNPAnd + + +
            Defined in cuddGenCof.c + +
            +
            +static DdNode * 
            +cuddBddPermuteRecur(
            +  DdManager * manager, DD manager
            +  DdHashTable * table, computed table
            +  DdNode * node, BDD to be reordered
            +  int * permut permutation array
            +)
            +
            +
            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.

            + The DdNode * that is returned is the same BDD as passed in as node, + but in the new order. +

            + +

            Side Effects None +

            + +

            See Also Cudd_bddPermute +cuddAddPermuteRecur + + +
            Defined in cuddCompose.c + +
            +
            +DdNode * 
            +cuddBddRestrictRecur(
            +  DdManager * dd, 
            +  DdNode * f, 
            +  DdNode * c 
            +)
            +
            +
            Performs the recursive step of Cudd_bddRestrict. + Returns the restricted BDD if successful; otherwise NULL. +

            + +

            Side Effects None +

            + +

            See Also Cudd_bddRestrict + + +
            Defined in cuddGenCof.c + +
            +
            +static DdNode * 
            +cuddBddSqueeze(
            +  DdManager * dd, 
            +  DdNode * l, 
            +  DdNode * u 
            +)
            +
            +
            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. +

            + +

            Side Effects None +

            + +

            See Also Cudd_bddSqueeze + + +
            Defined in cuddGenCof.c + +
            +
            +static DdNode * 
            +cuddBddTransferRecur(
            +  DdManager * ddS, 
            +  DdManager * ddD, 
            +  DdNode * f, 
            +  st_table * table 
            +)
            +
            +
            Performs the recursive step of Cudd_bddTransfer. + Returns a pointer to the result if successful; NULL otherwise. +

            + +

            Side Effects None +

            + +

            See Also cuddBddTransfer + + +
            Defined in cuddBridge.c + +
            +
            +DdNode * 
            +cuddBddTransfer(
            +  DdManager * ddS, 
            +  DdManager * ddD, 
            +  DdNode * f 
            +)
            +
            +
            Convert a BDD from a manager to another one. Returns a + pointer to the BDD in the destination manager if successful; NULL + otherwise. +

            + +

            Side Effects None +

            + +

            See Also Cudd_bddTransfer + + +
            Defined in cuddBridge.c + +
            +
            +static DdNode * 
            +cuddBddVarMapRecur(
            +  DdManager * manager, DD manager
            +  DdNode * f BDD to be remapped
            +)
            +
            +
            Implements the recursive step of Cudd_bddVarMap. + Returns a pointer to the result if successful; NULL otherwise. +

            + +

            Side Effects None +

            + +

            See Also Cudd_bddVarMap + + +
            Defined in cuddCompose.c + +
            +
            +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
            +)
            +
            +
            Performs the recursive step of Cudd_bddVectorCompose. +

            + +

            Side Effects None +

            + +

            Defined in cuddCompose.c + +
            +
            +DdNode * 
            +cuddBddXorExistAbstractRecur(
            +  DdManager * manager, 
            +  DdNode * f, 
            +  DdNode * g, 
            +  DdNode * cube 
            +)
            +
            +
            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. +

            + +

            Side Effects None +

            + +

            See Also Cudd_bddAndAbstract + + +
            Defined in cuddBddAbs.c + +
            +
            +DdNode * 
            +cuddBddXorRecur(
            +  DdManager * manager, 
            +  DdNode * f, 
            +  DdNode * g 
            +)
            +
            +
            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. +

            + +

            Side Effects None +

            + +

            See Also Cudd_bddXor + + +
            Defined in cuddBddIte.c + +
            +
            +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
            +)
            +
            +
            Applies the biased remapping underappoximation algorithm. + Proceeds in three phases: +
              +
            • collect information on each node in the BDD; this is done via DFS. +
            • traverse the BDD in top-down fashion and compute for each node + whether remapping increases density. +
            • traverse the BDD via DFS and actually perform the elimination. +
            + Returns the approximated BDD if successful; NULL otherwise. +

            + +

            Side Effects None +

            + +

            See Also Cudd_BiasedUnderApprox + + +
            Defined in cuddApprox.c + +
            +
            +DdNode * 
            +cuddCProjectionRecur(
            +  DdManager * dd, 
            +  DdNode * R, 
            +  DdNode * Y, 
            +  DdNode * Ysupp 
            +)
            +
            +
            Performs the recursive step of Cudd_CProjection. Returns + the projection if successful; NULL otherwise. +

            + +

            Side Effects None +

            + +

            See Also Cudd_CProjection + + +
            Defined in cuddPriority.c + +
            +
            +void 
            +cuddCacheFlush(
            +  DdManager * table 
            +)
            +
            +
            Flushes the cache. +

            + +

            Side Effects None +

            + +

            Defined in cuddCache.c + +
            +
            +void 
            +cuddCacheInsert1(
            +  DdManager * table, 
            +  DD_CTFP1  op, 
            +  DdNode * f, 
            +  DdNode * data 
            +)
            +
            +
            Inserts a result in the cache for a function with two + operands. +

            + +

            Side Effects None +

            + +

            See Also cuddCacheInsert +cuddCacheInsert2 + + +
            Defined in cuddCache.c + +
            +
            +void 
            +cuddCacheInsert2(
            +  DdManager * table, 
            +  DD_CTFP  op, 
            +  DdNode * f, 
            +  DdNode * g, 
            +  DdNode * data 
            +)
            +
            +
            Inserts a result in the cache for a function with two + operands. +

            + +

            Side Effects None +

            + +

            See Also cuddCacheInsert +cuddCacheInsert1 + + +
            Defined in cuddCache.c + +
            +
            +void 
            +cuddCacheInsert(
            +  DdManager * table, 
            +  ptruint  op, 
            +  DdNode * f, 
            +  DdNode * g, 
            +  DdNode * h, 
            +  DdNode * data 
            +)
            +
            +
            Inserts a result in the cache. +

            + +

            Side Effects None +

            + +

            See Also cuddCacheInsert2 +cuddCacheInsert1 + + +
            Defined in cuddCache.c + +
            +
            +DdNode * 
            +cuddCacheLookup1Zdd(
            +  DdManager * table, 
            +  DD_CTFP1  op, 
            +  DdNode * f 
            +)
            +
            +
            Returns the result if found; it returns NULL if no + result is found. +

            + +

            Side Effects None +

            + +

            See Also cuddCacheLookupZdd +cuddCacheLookup2Zdd + + +
            Defined in cuddCache.c + +
            +
            +DdNode * 
            +cuddCacheLookup1(
            +  DdManager * table, 
            +  DD_CTFP1  op, 
            +  DdNode * f 
            +)
            +
            +
            Returns the result if found; it returns NULL if no + result is found. +

            + +

            Side Effects None +

            + +

            See Also cuddCacheLookup +cuddCacheLookup2 + + +
            Defined in cuddCache.c + +
            +
            +DdNode * 
            +cuddCacheLookup2Zdd(
            +  DdManager * table, 
            +  DD_CTFP  op, 
            +  DdNode * f, 
            +  DdNode * g 
            +)
            +
            +
            Returns the result if found; it returns NULL if no + result is found. +

            + +

            Side Effects None +

            + +

            See Also cuddCacheLookupZdd +cuddCacheLookup1Zdd + + +
            Defined in cuddCache.c + +
            +
            +DdNode * 
            +cuddCacheLookup2(
            +  DdManager * table, 
            +  DD_CTFP  op, 
            +  DdNode * f, 
            +  DdNode * g 
            +)
            +
            +
            Returns the result if found; it returns NULL if no + result is found. +

            + +

            Side Effects None +

            + +

            See Also cuddCacheLookup +cuddCacheLookup1 + + +
            Defined in cuddCache.c + +
            +
            +DdNode * 
            +cuddCacheLookupZdd(
            +  DdManager * table, 
            +  ptruint  op, 
            +  DdNode * f, 
            +  DdNode * g, 
            +  DdNode * h 
            +)
            +
            +
            Returns the result if found; it returns NULL if no + result is found. +

            + +

            Side Effects None +

            + +

            See Also cuddCacheLookup2Zdd +cuddCacheLookup1Zdd + + +
            Defined in cuddCache.c + +
            +
            +DdNode * 
            +cuddCacheLookup(
            +  DdManager * table, 
            +  ptruint  op, 
            +  DdNode * f, 
            +  DdNode * g, 
            +  DdNode * h 
            +)
            +
            +
            Returns the result if found; it returns NULL if no + result is found. +

            + +

            Side Effects None +

            + +

            See Also cuddCacheLookup2 +cuddCacheLookup1 + + +
            Defined in cuddCache.c + +
            +
            +int 
            +cuddCacheProfile(
            +  DdManager * table, 
            +  FILE * fp 
            +)
            +
            +
            Computes and prints a profile of the cache usage. + Returns 1 if successful; 0 otherwise. +

            + +

            Side Effects None +

            + +

            Defined in cuddCache.c + +
            +
            +void 
            +cuddCacheResize(
            +  DdManager * table 
            +)
            +
            +
            Resizes the cache. +

            + +

            Side Effects None +

            + +

            Defined in cuddCache.c + +
            +
            +static int 
            +cuddCheckCollisionOrdering(
            +  DdManager * unique, 
            +  int  i, 
            +  int  j 
            +)
            +
            +
            Checks whether a collision list is ordered. +

            + +

            Side Effects None +

            + +

            Defined in cuddTable.c + +
            +
            +int 
            +cuddCheckCube(
            +  DdManager * dd, 
            +  DdNode * g 
            +)
            +
            +
            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. +

            + +

            Side Effects None +

            + +

            Defined in cuddCof.c + +
            +
            +void 
            +cuddClearDeathRow(
            +  DdManager * table 
            +)
            +
            +
            Clears the death row. +

            + +

            Side Effects None +

            + +

            See Also Cudd_DelayedDerefBdd +Cudd_IterDerefBdd +Cudd_CheckZeroRef +cuddGarbageCollect + + +
            Defined in cuddRef.c + +
            +
            +DdNode * 
            +cuddCofactorRecur(
            +  DdManager * dd, 
            +  DdNode * f, 
            +  DdNode * g 
            +)
            +
            +
            Performs the recursive step of Cudd_Cofactor. Returns a + pointer to the cofactor if successful; NULL otherwise. +

            + +

            Side Effects None +

            + +

            See Also Cudd_Cofactor + + +
            Defined in cuddCof.c + +
            +
            +int 
            +cuddCollectNodes(
            +  DdNode * f, 
            +  st_table * visited 
            +)
            +
            +
            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. +

            + +

            Side Effects None +

            + +

            Defined in cuddUtil.c + +
            +
            +int 
            +cuddComputeFloorLog2(
            +  unsigned int  value 
            +)
            +
            +
            Returns the floor of the logarithm to the base 2. + The input value is assumed to be greater than 0. +

            + +

            Side Effects None +

            + +

            Defined in cuddCache.c + +
            +
            +static int 
            +cuddConjunctsAux(
            +  DdManager * dd, 
            +  DdNode * f, 
            +  DdNode ** c1, 
            +  DdNode ** c2 
            +)
            +
            +
            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. +

            + +

            Defined in cuddDecomp.c + +
            +
            +DdNode * 
            +cuddConstantLookup(
            +  DdManager * table, 
            +  ptruint  op, 
            +  DdNode * f, 
            +  DdNode * g, 
            +  DdNode * h 
            +)
            +
            +
            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. +

            + +

            Side Effects None +

            + +

            See Also cuddCacheLookup + + +
            Defined in cuddCache.c + +
            +
            +int 
            +cuddDestroySubtables(
            +  DdManager * unique, 
            +  int  n 
            +)
            +
            +
            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. +

            + +

            Side Effects The variable map used for fast variable substitution is + destroyed if it exists. In this case the cache is also cleared. +

            + +

            See Also cuddInsertSubtables +Cudd_SetVarMap + + +
            Defined in cuddTable.c + +
            +
            +static void 
            +cuddDoRebalance(
            +  DdNodePtr ** stack, 
            +  int  stackN 
            +)
            +
            +
            Rebalances a red/black tree. +

            + +

            Side Effects None +

            + +

            Defined in cuddTable.c + +
            +
            +DdNode * 
            +cuddDynamicAllocNode(
            +  DdManager * table 
            +)
            +
            +
            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. +

            + +

            Side Effects None +

            + +

            See Also cuddAllocNode + + +
            Defined in cuddReorder.c + +
            +
            +static int 
            +cuddEstimateCofactorSimple(
            +  DdNode * node, 
            +  int  i 
            +)
            +
            +
            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. +

            + +

            Side Effects None +

            + +

            Defined in cuddUtil.c + +
            +
            +static int 
            +cuddEstimateCofactor(
            +  DdManager * dd, 
            +  st_table * table, 
            +  DdNode * node, 
            +  int  i, 
            +  int  phase, 
            +  DdNode ** ptr 
            +)
            +
            +
            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. +

            + +

            Side Effects None +

            + +

            Defined in cuddUtil.c + +
            +
            +int 
            +cuddExact(
            +  DdManager * table, 
            +  int  lower, 
            +  int  upper 
            +)
            +
            +
            Exact variable ordering algorithm. Finds an optimum + order for the variables between lower and upper. Returns 1 if + successful; 0 otherwise. +

            + +

            Side Effects None +

            + +

            Defined in cuddExact.c + +
            +
            +static int 
            +cuddFindParent(
            +  DdManager * table, 
            +  DdNode * node 
            +)
            +
            +
            Searches the subtables above node for a parent. Returns 1 + as soon as one parent is found. Returns 0 is the search is fruitless. +

            + +

            Side Effects None +

            + +

            Defined in cuddTable.c + +
            +
            +void 
            +cuddFreeTable(
            +  DdManager * unique 
            +)
            +
            +
            Frees the resources associated to a unique table. +

            + +

            Side Effects None +

            + +

            See Also cuddInitTable + + +
            Defined in cuddTable.c + +
            +
            +int 
            +cuddGarbageCollect(
            +  DdManager * unique, 
            +  int  clearCache 
            +)
            +
            +
            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. +

            + +

            Side Effects None +

            + +

            Defined in cuddTable.c + +
            +
            +int 
            +cuddGa(
            +  DdManager * table, manager
            +  int  lower, lowest level to be reordered
            +  int  upper highest level to be reorderded
            +)
            +
            +
            Genetic algorithm for DD reordering. + The two children of a crossover will be stored in + storedd[popsize +

            + +

            Side Effects None +

            + +

            Defined in cuddGenetic.c + +
            +
            +void 
            +cuddGetBranches(
            +  DdNode * g, 
            +  DdNode ** g1, 
            +  DdNode ** g0 
            +)
            +
            +
            Computes the children of g. +

            + +

            Side Effects None +

            + +

            Defined in cuddCof.c + +
            +
            +static DdHashItem * 
            +cuddHashTableAlloc(
            +  DdHashTable * hash 
            +)
            +
            +
            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. +

            + +

            Side Effects None +

            + +

            See Also cuddAllocNode +cuddDynamicAllocNode + + +
            Defined in cuddLCache.c + +
            +
            +DdHashTable * 
            +cuddHashTableInit(
            +  DdManager * manager, 
            +  unsigned int  keySize, 
            +  unsigned int  initSize 
            +)
            +
            +
            Initializes a hash table. Returns a pointer to the new + table if successful; NULL otherwise. +

            + +

            Side Effects None +

            + +

            See Also cuddHashTableQuit + + +
            Defined in cuddLCache.c + +
            +
            +int 
            +cuddHashTableInsert1(
            +  DdHashTable * hash, 
            +  DdNode * f, 
            +  DdNode * value, 
            +  ptrint  count 
            +)
            +
            +
            Inserts an item in a hash table when the key is one pointer. + Returns 1 if successful; 0 otherwise. +

            + +

            Side Effects None +

            + +

            See Also cuddHashTableInsert +cuddHashTableInsert2 +cuddHashTableInsert3 +cuddHashTableLookup1 + + +
            Defined in cuddLCache.c + +
            +
            +int 
            +cuddHashTableInsert2(
            +  DdHashTable * hash, 
            +  DdNode * f, 
            +  DdNode * g, 
            +  DdNode * value, 
            +  ptrint  count 
            +)
            +
            +
            Inserts an item in a hash table when the key is + composed of two pointers. Returns 1 if successful; 0 otherwise. +

            + +

            Side Effects None +

            + +

            See Also cuddHashTableInsert +cuddHashTableInsert1 +cuddHashTableInsert3 +cuddHashTableLookup2 + + +
            Defined in cuddLCache.c + +
            +
            +int 
            +cuddHashTableInsert3(
            +  DdHashTable * hash, 
            +  DdNode * f, 
            +  DdNode * g, 
            +  DdNode * h, 
            +  DdNode * value, 
            +  ptrint  count 
            +)
            +
            +
            Inserts an item in a hash table when the key is + composed of three pointers. Returns 1 if successful; 0 otherwise. +

            + +

            Side Effects None +

            + +

            See Also cuddHashTableInsert +cuddHashTableInsert1 +cuddHashTableInsert2 +cuddHashTableLookup3 + + +
            Defined in cuddLCache.c + +
            +
            +int 
            +cuddHashTableInsert(
            +  DdHashTable * hash, 
            +  DdNodePtr * key, 
            +  DdNode * value, 
            +  ptrint  count 
            +)
            +
            +
            Inserts an item in a hash table when the key has more than + three pointers. Returns 1 if successful; 0 otherwise. +

            + +

            Side Effects None +

            + +

            See Also [cuddHashTableInsert1 +cuddHashTableInsert2 +cuddHashTableInsert3 +cuddHashTableLookup + + +
            Defined in cuddLCache.c + +
            +
            +DdNode * 
            +cuddHashTableLookup1(
            +  DdHashTable * hash, 
            +  DdNode * f 
            +)
            +
            +
            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. +

            + +

            Side Effects None +

            + +

            See Also cuddHashTableLookup +cuddHashTableLookup2 +cuddHashTableLookup3 +cuddHashTableInsert1 + + +
            Defined in cuddLCache.c + +
            +
            +DdNode * 
            +cuddHashTableLookup2(
            +  DdHashTable * hash, 
            +  DdNode * f, 
            +  DdNode * g 
            +)
            +
            +
            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. +

            + +

            Side Effects None +

            + +

            See Also cuddHashTableLookup +cuddHashTableLookup1 +cuddHashTableLookup3 +cuddHashTableInsert2 + + +
            Defined in cuddLCache.c + +
            +
            +DdNode * 
            +cuddHashTableLookup3(
            +  DdHashTable * hash, 
            +  DdNode * f, 
            +  DdNode * g, 
            +  DdNode * h 
            +)
            +
            +
            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. +

            + +

            Side Effects None +

            + +

            See Also cuddHashTableLookup +cuddHashTableLookup1 +cuddHashTableLookup2 +cuddHashTableInsert3 + + +
            Defined in cuddLCache.c + +
            +
            +DdNode * 
            +cuddHashTableLookup(
            +  DdHashTable * hash, 
            +  DdNodePtr * key 
            +)
            +
            +
            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. +

            + +

            Side Effects None +

            + +

            See Also cuddHashTableLookup1 +cuddHashTableLookup2 +cuddHashTableLookup3 +cuddHashTableInsert + + +
            Defined in cuddLCache.c + +
            +
            +void 
            +cuddHashTableQuit(
            +  DdHashTable * hash 
            +)
            +
            +
            Shuts down a hash table, dereferencing all the values. +

            + +

            Side Effects None +

            + +

            See Also cuddHashTableInit + + +
            Defined in cuddLCache.c + +
            +
            +static int 
            +cuddHashTableResize(
            +  DdHashTable * hash 
            +)
            +
            +
            Resizes a hash table. Returns 1 if successful; 0 + otherwise. +

            + +

            Side Effects None +

            + +

            See Also cuddHashTableInsert + + +
            Defined in cuddLCache.c + +
            +
            +int 
            +cuddHeapProfile(
            +  DdManager * dd 
            +)
            +
            +
            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: +
              +
            • total number of tables; +
            • number of tables with live nodes; +
            • table with the largest number of live nodes; +
            • number of nodes in that table. +
            + 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. +

            + +

            Side Effects None +

            + +

            Defined in cuddCheck.c + +
            +
            +int 
            +cuddInitCache(
            +  DdManager * unique, unique table
            +  unsigned int  cacheSize, initial size of the cache
            +  unsigned int  maxCacheSize cache size beyond which no resizing occurs
            +)
            +
            +
            Initializes the computed table. It is called by + Cudd_Init. Returns 1 in case of success; 0 otherwise. +

            + +

            Side Effects None +

            + +

            See Also Cudd_Init + + +
            Defined in cuddCache.c + +
            +
            +int 
            +cuddInitInteract(
            +  DdManager * table 
            +)
            +
            +
            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. +

            + +

            Side Effects None +

            + +

            Defined in cuddInteract.c + +
            +
            +int 
            +cuddInitLinear(
            +  DdManager * table 
            +)
            +
            +
            Initializes the linear transform matrix. Returns 1 if + successful; 0 otherwise. +

            + +

            Side Effects none +

            + +

            Defined in cuddLinear.c + +
            +
            +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
            +)
            +
            +
            Creates and initializes the unique table. Returns a pointer + to the table if successful; NULL otherwise. +

            + +

            Side Effects None +

            + +

            See Also Cudd_Init +cuddFreeTable + + +
            Defined in cuddTable.c + +
            +
            +int 
            +cuddInsertSubtables(
            +  DdManager * unique, 
            +  int  n, 
            +  int  level 
            +)
            +
            +
            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. +

            + +

            Side Effects None +

            + +

            See Also cuddDestroySubtables + + +
            Defined in cuddTable.c + +
            +
            +int 
            +cuddIsInDeathRow(
            +  DdManager * dd, 
            +  DdNode * f 
            +)
            +
            +
            Checks whether a node is in the death row. Returns the + position of the first occurrence if the node is present; -1 + otherwise. +

            + +

            Side Effects None +

            + +

            See Also Cudd_DelayedDerefBdd +cuddClearDeathRow + + +
            Defined in cuddRef.c + +
            +
            +void 
            +cuddLevelQueueDequeue(
            +  DdLevelQueue * queue, 
            +  int  level 
            +)
            +
            +
            Remove an item from the front of a level queue. +

            + +

            Side Effects None +

            + +

            See Also cuddLevelQueueEnqueue + + +
            Defined in cuddLevelQ.c + +
            +
            +void * 
            +cuddLevelQueueEnqueue(
            +  DdLevelQueue * queue, level queue
            +  void * key, key to be enqueued
            +  int  level level at which to insert
            +)
            +
            +
            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. +

            + +

            Side Effects None +

            + +

            See Also cuddLevelQueueInit +cuddLevelQueueDequeue + + +
            Defined in cuddLevelQ.c + +
            +
            +DdLevelQueue * 
            +cuddLevelQueueInit(
            +  int  levels, number of levels
            +  int  itemSize, size of the item
            +  int  numBuckets initial number of hash buckets
            +)
            +
            +
            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. +

            + +

            Side Effects None +

            + +

            See Also cuddLevelQueueQuit +cuddLevelQueueEnqueue +cuddLevelQueueDequeue + + +
            Defined in cuddLevelQ.c + +
            +
            +void 
            +cuddLevelQueueQuit(
            +  DdLevelQueue * queue 
            +)
            +
            +
            Shuts down a level queue and releases all the + associated memory. +

            + +

            Side Effects None +

            + +

            See Also cuddLevelQueueInit + + +
            Defined in cuddLevelQ.c + +
            +
            +int 
            +cuddLinearAndSifting(
            +  DdManager * table, 
            +  int  lower, 
            +  int  upper 
            +)
            +
            +
            BDD reduction based on combination of sifting and linear + transformations. Assumes that no dead nodes are present. +
              +
            1. Order all the variables according to the number of entries + in each unique table. +
            2. 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. +
            3. Select the best permutation. +
            4. Repeat 3 and 4 for all variables. +
            + Returns 1 if successful; 0 otherwise. +

            + +

            Side Effects None +

            + +

            Defined in cuddLinear.c + +
            +
            +int 
            +cuddLinearInPlace(
            +  DdManager * table, 
            +  int  x, 
            +  int  y 
            +)
            +
            +
            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 < + y. Returns the number of keys in the table if successful; 0 + otherwise. +

            + +

            Side Effects The two subtables corrresponding to variables x and y are + modified. The global counters of the unique table are also affected. +

            + +

            See Also cuddSwapInPlace + + +
            Defined in cuddLinear.c + +
            +
            +static void 
            +cuddLocalCacheAddToList(
            +  DdLocalCache * cache 
            +)
            +
            +
            Inserts a local cache in the manager list. +

            + +

            Side Effects None +

            + +

            Defined in cuddLCache.c + +
            +
            +void 
            +cuddLocalCacheClearAll(
            +  DdManager * manager 
            +)
            +
            +
            Clears the local caches of a manager. + Used before reordering. +

            + +

            Side Effects None +

            + +

            Defined in cuddLCache.c + +
            +
            +void 
            +cuddLocalCacheClearDead(
            +  DdManager * manager 
            +)
            +
            +
            Clears the dead entries of the local caches of a manager. + Used during garbage collection. +

            + +

            Side Effects None +

            + +

            Defined in cuddLCache.c + +
            +
            +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
            +)
            +
            +
            Initializes a computed table. Returns a pointer the + the new local cache in case of success; NULL otherwise. +

            + +

            Side Effects None +

            + +

            See Also cuddInitCache + + +
            Defined in cuddLCache.c + +
            +
            +void 
            +cuddLocalCacheInsert(
            +  DdLocalCache * cache, 
            +  DdNodePtr * key, 
            +  DdNode * value 
            +)
            +
            +
            Inserts a result in a local cache. +

            + +

            Side Effects None +

            + +

            Defined in cuddLCache.c + +
            +
            +DdNode * 
            +cuddLocalCacheLookup(
            +  DdLocalCache * cache, 
            +  DdNodePtr * key 
            +)
            +
            +
            Looks up in a local cache. Returns the result if found; + it returns NULL if no result is found. +

            + +

            Side Effects None +

            + +

            Defined in cuddLCache.c + +
            +
            +int 
            +cuddLocalCacheProfile(
            +  DdLocalCache * cache 
            +)
            +
            +
            Computes and prints a profile of a local cache usage. + Returns 1 if successful; 0 otherwise. +

            + +

            Side Effects None +

            + +

            Defined in cuddLCache.c + +
            +
            +void 
            +cuddLocalCacheQuit(
            +  DdLocalCache * cache cache to be shut down
            +)
            +
            +
            Initializes the computed table. It is called by + Cudd_Init. Returns a pointer the the new local cache in case of + success; NULL otherwise. +

            + +

            Side Effects None +

            + +

            See Also cuddLocalCacheInit + + +
            Defined in cuddLCache.c + +
            +
            +static void 
            +cuddLocalCacheRemoveFromList(
            +  DdLocalCache * cache 
            +)
            +
            +
            Removes a local cache from the manager list. +

            + +

            Side Effects None +

            + +

            Defined in cuddLCache.c + +
            +
            +static void 
            +cuddLocalCacheResize(
            +  DdLocalCache * cache 
            +)
            +
            +
            Resizes a local cache. +

            + +

            Side Effects None +

            + +

            Defined in cuddLCache.c + +
            +
            +DdNode	* 
            +cuddMakeBddFromZddCover(
            +  DdManager * dd, 
            +  DdNode * node 
            +)
            +
            +
            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. +

            + +

            See Also Cudd_MakeBddFromZddCover + + +
            Defined in cuddZddIsop.c + +
            +
            +static int 
            +cuddMinHammingDistRecur(
            +  DdNode * f, 
            +  int * minterm, 
            +  DdHashTable * table, 
            +  int  upperBound 
            +)
            +
            +
            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: + + H(f) = min(H(f0)+h0,H(f1)+h1) + + 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. +

            + +

            Side Effects None +

            + +

            See Also Cudd_MinHammingDist + + +
            Defined in cuddPriority.c + +
            +
            +int 
            +cuddNextHigh(
            +  DdManager * table, 
            +  int  x 
            +)
            +
            +
            Finds the next subtable with a larger index. Returns the + index. +

            + +

            Side Effects None +

            + +

            See Also cuddNextLow + + +
            Defined in cuddReorder.c + +
            +
            +int 
            +cuddNextLow(
            +  DdManager * table, 
            +  int  x 
            +)
            +
            +
            Finds the next subtable with a smaller index. Returns the + index. +

            + +

            Side Effects None +

            + +

            See Also cuddNextHigh + + +
            Defined in cuddReorder.c + +
            +
            +static int 
            +cuddNodeArrayRecur(
            +  DdNode * f, 
            +  DdNodePtr * table, 
            +  int  index 
            +)
            +
            +
            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. +

            + +

            Side Effects None +

            + +

            Defined in cuddUtil.c + +
            +
            +DdNodePtr * 
            +cuddNodeArray(
            +  DdNode * f, 
            +  int * n 
            +)
            +
            +
            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. +

            + +

            Side Effects The number of nodes is returned as a side effect. +

            + +

            See Also Cudd_FirstNode + + +
            Defined in cuddUtil.c + +
            +
            +static void 
            +cuddOrderedInsert(
            +  DdNodePtr * root, 
            +  DdNodePtr  node 
            +)
            +
            +
            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. +

            + +

            Side Effects None +

            + +

            See Also cuddOrderedThread + + +
            Defined in cuddTable.c + +
            +
            +static DdNode * 
            +cuddOrderedThread(
            +  DdNode * root, 
            +  DdNode * list 
            +)
            +
            +
            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. +

            + +

            Side Effects The search tree is destroyed as a result of this operation. +

            + +

            See Also cuddOrderedInsert + + +
            Defined in cuddTable.c + +
            +
            +void 
            +cuddPrintNode(
            +  DdNode * f, 
            +  FILE * fp 
            +)
            +
            +
            Prints out information on a node. +

            + +

            Side Effects None +

            + +

            Defined in cuddCheck.c + +
            +
            +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
            +)
            +
            +
            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. +
              +
            • F: MTR_FIXED +
            • N: MTR_NEWNODE +
            • S: MTR_SOFT +
            + The second argument, silent, if different from 0, causes + Cudd_PrintVarGroups to only check the syntax of the group tree. +

            + +

            Side Effects None +

            + +

            Defined in cuddCheck.c + +
            +
            +int 
            +cuddP(
            +  DdManager * dd, 
            +  DdNode * f 
            +)
            +
            +
            Prints a DD to the standard output. One line per node is + printed. Returns 1 if successful; 0 otherwise. +

            + +

            Side Effects None +

            + +

            See Also Cudd_PrintDebug + + +
            Defined in cuddUtil.c + +
            +
            +void 
            +cuddReclaimZdd(
            +  DdManager * table, 
            +  DdNode * n 
            +)
            +
            +
            Brings children of a dead ZDD node back. +

            + +

            Side Effects None +

            + +

            See Also cuddReclaim + + +
            Defined in cuddRef.c + +
            +
            +void 
            +cuddReclaim(
            +  DdManager * table, 
            +  DdNode * n 
            +)
            +
            +
            Brings children of a dead node back. +

            + +

            Side Effects None +

            + +

            See Also cuddReclaimZdd + + +
            Defined in cuddRef.c + +
            +
            +void 
            +cuddRehash(
            +  DdManager * unique, 
            +  int  i 
            +)
            +
            +
            Doubles the size of a unique subtable and rehashes its + contents. +

            + +

            Side Effects None +

            + +

            Defined in cuddTable.c + +
            +
            +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
            +)
            +
            +
            Applies the remapping underappoximation algorithm. + Proceeds in three phases: +
              +
            • collect information on each node in the BDD; this is done via DFS. +
            • traverse the BDD in top-down fashion and compute for each node + whether remapping increases density. +
            • traverse the BDD via DFS and actually perform the elimination. +
            + Returns the approximated BDD if successful; NULL otherwise. +

            + +

            Side Effects None +

            + +

            See Also Cudd_RemapUnderApprox + + +
            Defined in cuddApprox.c + +
            +
            +int 
            +cuddResizeLinear(
            +  DdManager * table 
            +)
            +
            +
            Resizes the linear transform matrix. Returns 1 if + successful; 0 otherwise. +

            + +

            Side Effects none +

            + +

            Defined in cuddLinear.c + +
            +
            +int 
            +cuddResizeTableZdd(
            +  DdManager * unique, 
            +  int  index 
            +)
            +
            +
            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. +

            + +

            Side Effects None +

            + +

            See Also ddResizeTable + + +
            Defined in cuddTable.c + +
            +
            +static void 
            +cuddRotateLeft(
            +  DdNodePtr * nodeP 
            +)
            +
            +
            Performs the left rotation for red/black trees. +

            + +

            Side Effects None +

            + +

            See Also cuddRotateRight + + +
            Defined in cuddTable.c + +
            +
            +static void 
            +cuddRotateRight(
            +  DdNodePtr * nodeP 
            +)
            +
            +
            Performs the right rotation for red/black trees. +

            + +

            Side Effects None +

            + +

            See Also cuddRotateLeft + + +
            Defined in cuddTable.c + +
            +
            +void 
            +cuddSetInteract(
            +  DdManager * table, 
            +  int  x, 
            +  int  y 
            +)
            +
            +
            Given a pair of variables 0 <= x < y < table->size, + sets the corresponding bit of the interaction matrix to 1. +

            + +

            Side Effects None +

            + +

            Defined in cuddInteract.c + +
            +
            +void 
            +cuddShrinkDeathRow(
            +  DdManager * table 
            +)
            +
            +
            Shrinks the death row by a factor of four. +

            + +

            Side Effects None +

            + +

            See Also cuddClearDeathRow + + +
            Defined in cuddRef.c + +
            +
            +void 
            +cuddShrinkSubtable(
            +  DdManager * unique, 
            +  int  i 
            +)
            +
            +
            Shrinks a subtable. +

            + +

            Side Effects None +

            + +

            See Also cuddRehash + + +
            Defined in cuddTable.c + +
            +
            +int 
            +cuddSifting(
            +  DdManager * table, 
            +  int  lower, 
            +  int  upper 
            +)
            +
            +
            Implementation of Rudell's sifting algorithm. + Assumes that no dead nodes are present. +
              +
            1. Order all the variables according to the number of entries + in each unique table. +
            2. Sift the variable up and down, remembering each time the + total size of the DD heap. +
            3. Select the best permutation. +
            4. Repeat 3 and 4 for all variables. +
            + Returns 1 if successful; 0 otherwise. +

            + +

            Side Effects None +

            + +

            Defined in cuddReorder.c + +
            +
            +void 
            +cuddSlowTableGrowth(
            +  DdManager * unique 
            +)
            +
            +
            Adjusts parameters of a table to slow down its growth. +

            + +

            Side Effects None +

            + +

            Defined in cuddTable.c + +
            +
            +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
            +)
            +
            +
            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. +

            + +

            Side Effects none +

            + +

            See Also Cudd_SolveEqn +Cudd_VerifySol + + +
            Defined in cuddSolve.c + +
            +
            +DdNode* 
            +cuddSplitSetRecur(
            +  DdManager * manager, 
            +  st_table * mtable, 
            +  int * varSeen, 
            +  DdNode * p, 
            +  double  n, 
            +  double  max, 
            +  int  index 
            +)
            +
            +
            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. +

            + +

            Side Effects The array 'varSeen' is updated at every recursive call + to set the variables traversed by the procedure. +

            + +

            Defined in cuddSplit.c + +
            +
            +enum st_retval 
            +cuddStCountfree(
            +  char * key, 
            +  char * value, 
            +  char * arg 
            +)
            +
            +
            Frees the memory used to store the minterm counts + recorded in the visited table. Returns ST_CONTINUE. +

            + +

            Side Effects None +

            + +

            Defined in cuddUtil.c + +
            +
            +DdNode * 
            +cuddSubsetHeavyBranch(
            +  DdManager * dd, DD manager
            +  DdNode * f, current DD
            +  int  numVars, maximum number of variables
            +  int  threshold threshold size for the subset
            +)
            +
            +
            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. +

            + +

            Side Effects None +

            + +

            See Also Cudd_SubsetHeavyBranch + + +
            Defined in cuddSubsetHB.c + +
            +
            +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
            +)
            +
            +
            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. +

            + +

            Side Effects None +

            + +

            See Also Cudd_SubsetShortPaths + + +
            Defined in cuddSubsetSP.c + +
            +
            +int 
            +cuddSwapInPlace(
            +  DdManager * table, 
            +  int  x, 
            +  int  y 
            +)
            +
            +
            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 < y. Returns the number of keys in + the table if successful; 0 otherwise. +

            + +

            Side Effects None +

            + +

            Defined in cuddReorder.c + +
            +
            +int 
            +cuddSwapping(
            +  DdManager * table, 
            +  int  lower, 
            +  int  upper, 
            +  Cudd_ReorderingType  heuristic 
            +)
            +
            +
            Implementation of Plessier's algorithm that reorders + variables by a sequence of (non-adjacent) swaps. +
              +
            1. Select two variables (RANDOM or HEURISTIC). +
            2. Permute these variables. +
            3. If the nodes have decreased accept the permutation. +
            4. Otherwise reconstruct the original heap. +
            5. Loop. +
            + Returns 1 in case of success; 0 otherwise. +

            + +

            Side Effects None +

            + +

            Defined in cuddReorder.c + +
            +
            +int 
            +cuddSymmCheck(
            +  DdManager * table, 
            +  int  x, 
            +  int  y 
            +)
            +
            +
            Checks for symmetry of x and y. Ignores projection + functions, unless they are isolated. Returns 1 in case of symmetry; 0 + otherwise. +

            + +

            Side Effects None +

            + +

            Defined in cuddSymmetry.c + +
            +
            +int 
            +cuddSymmSiftingConv(
            +  DdManager * table, 
            +  int  lower, 
            +  int  upper 
            +)
            +
            +
            Symmetric sifting to convergence algorithm. + Assumes that no dead nodes are present. +
              +
            1. Order all the variables according to the number of entries in + each unique subtable. +
            2. Sift the variable up and down, remembering each time the total + size of the DD heap and grouping variables that are symmetric. +
            3. Select the best permutation. +
            4. Repeat 3 and 4 for all variables. +
            5. Repeat 1-4 until no further improvement. +
            + Returns 1 plus the number of symmetric variables if successful; 0 + otherwise. +

            + +

            Side Effects None +

            + +

            See Also cuddSymmSifting + + +
            Defined in cuddSymmetry.c + +
            +
            +int 
            +cuddSymmSifting(
            +  DdManager * table, 
            +  int  lower, 
            +  int  upper 
            +)
            +
            +
            Symmetric sifting algorithm. + Assumes that no dead nodes are present. +
              +
            1. Order all the variables according to the number of entries in + each unique subtable. +
            2. Sift the variable up and down, remembering each time the total + size of the DD heap and grouping variables that are symmetric. +
            3. Select the best permutation. +
            4. Repeat 3 and 4 for all variables. +
            + Returns 1 plus the number of symmetric variables if successful; 0 + otherwise. +

            + +

            Side Effects None +

            + +

            See Also cuddSymmSiftingConv + + +
            Defined in cuddSymmetry.c + +
            +
            +int 
            +cuddTestInteract(
            +  DdManager * table, 
            +  int  x, 
            +  int  y 
            +)
            +
            +
            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. +

            + +

            Side Effects None +

            + +

            Defined in cuddInteract.c + +
            +
            +int 
            +cuddTimesInDeathRow(
            +  DdManager * dd, 
            +  DdNode * f 
            +)
            +
            +
            Counts how many times a node is in the death row. +

            + +

            Side Effects None +

            + +

            See Also Cudd_DelayedDerefBdd +cuddClearDeathRow +cuddIsInDeathRow + + +
            Defined in cuddRef.c + +
            +
            +int 
            +cuddTreeSifting(
            +  DdManager * table, DD table
            +  Cudd_ReorderingType  method reordering method for the groups of leaves
            +)
            +
            +
            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. +

            + +

            Side Effects None +

            + +

            Defined in cuddGroup.c + +
            +
            +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
            +)
            +
            +
            Applies Tom Shiple's underappoximation algorithm. Proceeds + in three phases: +
              +
            • collect information on each node in the BDD; this is done via DFS. +
            • traverse the BDD in top-down fashion and compute for each node + whether its elimination increases density. +
            • traverse the BDD via DFS and actually perform the elimination. +
            + Returns the approximated BDD if successful; NULL otherwise. +

            + +

            Side Effects None +

            + +

            See Also Cudd_UnderApprox + + +
            Defined in cuddApprox.c + +
            +
            +DdNode * 
            +cuddUniqueConst(
            +  DdManager * unique, 
            +  CUDD_VALUE_TYPE  value 
            +)
            +
            +
            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. +

            + +

            Side Effects None +

            + +

            Defined in cuddTable.c + +
            +
            +DdNode * 
            +cuddUniqueInterIVO(
            +  DdManager * unique, 
            +  int  index, 
            +  DdNode * T, 
            +  DdNode * E 
            +)
            +
            +
            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. +

            + +

            Side Effects None +

            + +

            See Also cuddUniqueInter +Cudd_MakeBddFromZddCover + + +
            Defined in cuddTable.c + +
            +
            +DdNode * 
            +cuddUniqueInterZdd(
            +  DdManager * unique, 
            +  int  index, 
            +  DdNode * T, 
            +  DdNode * E 
            +)
            +
            +
            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. +

            + +

            Side Effects None +

            + +

            See Also cuddUniqueInter + + +
            Defined in cuddTable.c + +
            +
            +DdNode * 
            +cuddUniqueInter(
            +  DdManager * unique, 
            +  int  index, 
            +  DdNode * T, 
            +  DdNode * E 
            +)
            +
            +
            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. +

            + +

            Side Effects None +

            + +

            See Also cuddUniqueInterZdd + + +
            Defined in cuddTable.c + +
            +
            +static DdNode * 
            +cuddUniqueLookup(
            +  DdManager * unique, 
            +  int  index, 
            +  DdNode * T, 
            +  DdNode * E 
            +)
            +
            +
            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. +

            + +

            Side Effects None +

            + +

            See Also cuddUniqueInter + + +
            Defined in cuddUtil.c + +
            +
            +void 
            +cuddUpdateInteractionMatrix(
            +  DdManager * table, 
            +  int  xindex, 
            +  int  yindex 
            +)
            +
            +
            Updates the interaction matrix. +

            + +

            Side Effects none +

            + +

            Defined in cuddLinear.c + +
            +
            +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
            +)
            +
            +
            Implements the recursive step of Cudd_VerifySol. +

            + +

            Side Effects none +

            + +

            See Also Cudd_VerifySol + + +
            Defined in cuddSolve.c + +
            +
            +int 
            +cuddWindowReorder(
            +  DdManager * table, DD table
            +  int  low, lowest index to reorder
            +  int  high, highest index to reorder
            +  Cudd_ReorderingType  submethod window reordering option
            +)
            +
            +
            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. +

            + +

            Side Effects None +

            + +

            Defined in cuddWindow.c + +
            +
            +static void 
            +cuddXorLinear(
            +  DdManager * table, 
            +  int  x, 
            +  int  y 
            +)
            +
            +
            XORs two rows of the linear transform matrix and replaces + the first row with the result. +

            + +

            Side Effects none +

            + +

            Defined in cuddLinear.c + +
            +
            +int 
            +cuddZddAlignToBdd(
            +  DdManager * table DD manager
            +)
            +
            +
            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 + M be the ratio of the two numbers. cuddZddAlignToBdd + then considers the ZDD variables from M*i to + (M+1)*i-1 as corresponding to BDD variable + i. This function should be normally called from + Cudd_ReduceHeap, which clears the cache. Returns 1 in case of + success; 0 otherwise. +

            + +

            Side Effects Changes the ZDD variable order for all diagrams and performs + garbage collection of the ZDD unique table. +

            + +

            See Also Cudd_zddShuffleHeap +Cudd_ReduceHeap + + +
            Defined in cuddZddReord.c + +
            +
            +DdNode * 
            +cuddZddChangeAux(
            +  DdManager * zdd, 
            +  DdNode * P, 
            +  DdNode * zvar 
            +)
            +
            +
            Performs the recursive step of Cudd_zddChange. +

            + +

            Side Effects None +

            + +

            Defined in cuddZddSetop.c + +
            +
            +DdNode * 
            +cuddZddChange(
            +  DdManager * dd, 
            +  DdNode * P, 
            +  int  var 
            +)
            +
            +
            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. +

            + +

            Side Effects None +

            + +

            See Also Cudd_zddChange + + +
            Defined in cuddZddSetop.c + +
            +
            +DdNode	* 
            +cuddZddComplement(
            +  DdManager * dd, 
            +  DdNode * node 
            +)
            +
            +
            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. +

            + +

            Side Effects The result depends on current variable order. +

            + +

            Defined in cuddZddFuncs.c + +
            +
            +static double 
            +cuddZddCountDoubleStep(
            +  DdNode * P, 
            +  st_table * table, 
            +  DdNode * base, 
            +  DdNode * empty 
            +)
            +
            +
            Performs the recursive step of Cudd_zddCountDouble. +

            + +

            Side Effects None +

            + +

            Defined in cuddZddCount.c + +
            +
            +static int 
            +cuddZddCountStep(
            +  DdNode * P, 
            +  st_table * table, 
            +  DdNode * base, 
            +  DdNode * empty 
            +)
            +
            +
            Performs the recursive step of Cudd_zddCount. +

            + +

            Side Effects None +

            + +

            Defined in cuddZddCount.c + +
            +
            +static int 
            +cuddZddDagInt(
            +  DdNode * n, 
            +  st_table * tab 
            +)
            +
            +
            Performs the recursive step of Cudd_zddDagSize. Does + not check for out-of-memory conditions. +

            + +

            Side Effects None +

            + +

            Defined in cuddZddMisc.c + +
            +
            +DdNode * 
            +cuddZddDiff(
            +  DdManager * zdd, 
            +  DdNode * P, 
            +  DdNode * Q 
            +)
            +
            +
            Performs the recursive step of Cudd_zddDiff. +

            + +

            Side Effects None +

            + +

            Defined in cuddZddSetop.c + +
            +
            +DdNode	* 
            +cuddZddDivideF(
            +  DdManager * dd, 
            +  DdNode * f, 
            +  DdNode * g 
            +)
            +
            +
            Performs the recursive step of Cudd_zddDivideF. +

            + +

            Side Effects None +

            + +

            See Also Cudd_zddDivideF + + +
            Defined in cuddZddFuncs.c + +
            +
            +DdNode	* 
            +cuddZddDivide(
            +  DdManager * dd, 
            +  DdNode * f, 
            +  DdNode * g 
            +)
            +
            +
            Performs the recursive step of Cudd_zddDivide. +

            + +

            Side Effects None +

            + +

            See Also Cudd_zddDivide + + +
            Defined in cuddZddFuncs.c + +
            +
            +void 
            +cuddZddFreeUniv(
            +  DdManager * zdd 
            +)
            +
            +
            Frees the ZDD universe. +

            + +

            Side Effects None +

            + +

            See Also cuddZddInitUniv + + +
            Defined in cuddInit.c + +
            +
            +int 
            +cuddZddGetCofactors2(
            +  DdManager * dd, 
            +  DdNode * f, 
            +  int  v, 
            +  DdNode ** f1, 
            +  DdNode ** f0 
            +)
            +
            +
            Computes the two-way decomposition of f w.r.t. v. +

            + +

            Side Effects The results are returned in f1 and f0. +

            + +

            See Also cuddZddGetCofactors3 + + +
            Defined in cuddZddFuncs.c + +
            +
            +int 
            +cuddZddGetCofactors3(
            +  DdManager * dd, 
            +  DdNode * f, 
            +  int  v, 
            +  DdNode ** f1, 
            +  DdNode ** f0, 
            +  DdNode ** fd 
            +)
            +
            +
            Computes the three-way decomposition of function f (represented + by a ZDD) wit respect to variable v. Returns 0 if successful; 1 otherwise. +

            + +

            Side Effects The results are returned in f1, f0, and fd. +

            + +

            See Also cuddZddGetCofactors2 + + +
            Defined in cuddZddFuncs.c + +
            +
            +int 
            +cuddZddGetNegVarIndex(
            +  DdManager * dd, 
            +  int  index 
            +)
            +
            +
            Returns the index of negative ZDD variable. +

            + +

            Defined in cuddZddFuncs.c + +
            +
            +int 
            +cuddZddGetNegVarLevel(
            +  DdManager * dd, 
            +  int  index 
            +)
            +
            +
            Returns the level of negative ZDD variable. +

            + +

            Defined in cuddZddFuncs.c + +
            +
            +DdNode * 
            +cuddZddGetNodeIVO(
            +  DdManager * dd, 
            +  int  index, 
            +  DdNode * g, 
            +  DdNode * h 
            +)
            +
            +
            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. +

            + +

            Side Effects None +

            + +

            See Also cuddZddGetNode +cuddZddIsop + + +
            Defined in cuddTable.c + +
            +
            +DdNode * 
            +cuddZddGetNode(
            +  DdManager * zdd, 
            +  int  id, 
            +  DdNode * T, 
            +  DdNode * E 
            +)
            +
            +
            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. +

            + +

            Side Effects None +

            + +

            See Also cuddUniqueInterZdd + + +
            Defined in cuddTable.c + +
            +
            +int 
            +cuddZddGetPosVarIndex(
            +  DdManager * dd, 
            +  int  index 
            +)
            +
            +
            Returns the index of positive ZDD variable. +

            + +

            Defined in cuddZddFuncs.c + +
            +
            +int 
            +cuddZddGetPosVarLevel(
            +  DdManager * dd, 
            +  int  index 
            +)
            +
            +
            Returns the level of positive ZDD variable. +

            + +

            Defined in cuddZddFuncs.c + +
            +
            +int 
            +cuddZddInitUniv(
            +  DdManager * zdd 
            +)
            +
            +
            Initializes the ZDD universe. Returns 1 if successful; 0 + otherwise. +

            + +

            Side Effects None +

            + +

            See Also cuddZddFreeUniv + + +
            Defined in cuddInit.c + +
            +
            +DdNode * 
            +cuddZddIntersect(
            +  DdManager * zdd, 
            +  DdNode * P, 
            +  DdNode * Q 
            +)
            +
            +
            Performs the recursive step of Cudd_zddIntersect. +

            + +

            Side Effects None +

            + +

            Defined in cuddZddSetop.c + +
            +
            +DdNode	* 
            +cuddZddIsop(
            +  DdManager * dd, 
            +  DdNode * L, 
            +  DdNode * U, 
            +  DdNode ** zdd_I 
            +)
            +
            +
            Performs the recursive step of Cudd_zddIsop. +

            + +

            Side Effects None +

            + +

            See Also Cudd_zddIsop + + +
            Defined in cuddZddIsop.c + +
            +
            +DdNode * 
            +cuddZddIte(
            +  DdManager * dd, 
            +  DdNode * f, 
            +  DdNode * g, 
            +  DdNode * h 
            +)
            +
            +
            Performs the recursive step of Cudd_zddIte. +

            + +

            Side Effects None +

            + +

            Defined in cuddZddSetop.c + +
            +
            +static int 
            +cuddZddLinearAux(
            +  DdManager * table, 
            +  int  x, 
            +  int  xLow, 
            +  int  xHigh 
            +)
            +
            +
            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. +

            + +

            Side Effects None +

            + +

            Defined in cuddZddLin.c + +
            +
            +static int 
            +cuddZddLinearBackward(
            +  DdManager * table, 
            +  int  size, 
            +  Move * moves 
            +)
            +
            +
            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. +

            + +

            Side Effects None +

            + +

            Defined in cuddZddLin.c + +
            +
            +static Move * 
            +cuddZddLinearDown(
            +  DdManager * table, 
            +  int  x, 
            +  int  xHigh, 
            +  Move * prevMoves 
            +)
            +
            +
            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. +

            + +

            Side Effects None +

            + +

            Defined in cuddZddLin.c + +
            +
            +static int 
            +cuddZddLinearInPlace(
            +  DdManager * table, 
            +  int  x, 
            +  int  y 
            +)
            +
            +
            Linearly combines two adjacent variables. It assumes + that no dead nodes are present on entry to this procedure. The + procedure then guarantees that no dead nodes will be present when it + terminates. cuddZddLinearInPlace assumes that x < y. Returns the + number of keys in the table if successful; 0 otherwise. +

            + +

            Side Effects None +

            + +

            See Also cuddZddSwapInPlace +cuddLinearInPlace + + +
            Defined in cuddZddLin.c + +
            +
            +int 
            +cuddZddLinearSifting(
            +  DdManager * table, 
            +  int  lower, 
            +  int  upper 
            +)
            +
            +
            Implementation of the linear sifting algorithm for ZDDs. + Assumes that no dead nodes are present. +
              +
            1. Order all the variables according to the number of entries + in each unique table. +
            2. Sift the variable up and down and applies the XOR transformation, + remembering each time the total size of the DD heap. +
            3. Select the best permutation. +
            4. Repeat 3 and 4 for all variables. +
            + Returns 1 if successful; 0 otherwise. +

            + +

            Side Effects None +

            + +

            Defined in cuddZddLin.c + +
            +
            +static Move * 
            +cuddZddLinearUp(
            +  DdManager * table, 
            +  int  y, 
            +  int  xLow, 
            +  Move * prevMoves 
            +)
            +
            +
            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. +

            + +

            Side Effects None +

            + +

            Defined in cuddZddLin.c + +
            +
            +int 
            +cuddZddNextHigh(
            +  DdManager * table, 
            +  int  x 
            +)
            +
            +
            Finds the next subtable with a larger index. Returns the + index. +

            + +

            Side Effects None +

            + +

            Defined in cuddZddReord.c + +
            +
            +int 
            +cuddZddNextLow(
            +  DdManager * table, 
            +  int  x 
            +)
            +
            +
            Finds the next subtable with a smaller index. Returns the + index. +

            + +

            Side Effects None +

            + +

            Defined in cuddZddReord.c + +
            +
            +DdNode	* 
            +cuddZddProduct(
            +  DdManager * dd, 
            +  DdNode * f, 
            +  DdNode * g 
            +)
            +
            +
            Performs the recursive step of Cudd_zddProduct. +

            + +

            Side Effects None +

            + +

            See Also Cudd_zddProduct + + +
            Defined in cuddZddFuncs.c + +
            +
            +int 
            +cuddZddP(
            +  DdManager * zdd, 
            +  DdNode * f 
            +)
            +
            +
            Prints a ZDD to the standard output. One line per node is + printed. Returns 1 if successful; 0 otherwise. +

            + +

            Side Effects None +

            + +

            See Also Cudd_zddPrintDebug + + +
            Defined in cuddZddUtil.c + +
            +
            +static int 
            +cuddZddSiftingAux(
            +  DdManager * table, 
            +  int  x, 
            +  int  x_low, 
            +  int  x_high 
            +)
            +
            +
            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. +

            + +

            Side Effects None +

            + +

            Defined in cuddZddReord.c + +
            +
            +static int 
            +cuddZddSiftingBackward(
            +  DdManager * table, 
            +  Move * moves, 
            +  int  size 
            +)
            +
            +
            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. +

            + +

            Side Effects None +

            + +

            Defined in cuddZddReord.c + +
            +
            +static Move * 
            +cuddZddSiftingDown(
            +  DdManager * table, 
            +  int  x, 
            +  int  x_high, 
            +  int  initial_size 
            +)
            +
            +
            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. +

            + +

            Side Effects None +

            + +

            Defined in cuddZddReord.c + +
            +
            +static Move * 
            +cuddZddSiftingUp(
            +  DdManager * table, 
            +  int  x, 
            +  int  x_low, 
            +  int  initial_size 
            +)
            +
            +
            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. +

            + +

            Side Effects None +

            + +

            Defined in cuddZddReord.c + +
            +
            +int 
            +cuddZddSifting(
            +  DdManager * table, 
            +  int  lower, 
            +  int  upper 
            +)
            +
            +
            Implementation of Rudell's sifting algorithm. + Assumes that no dead nodes are present. +
              +
            1. Order all the variables according to the number of entries + in each unique table. +
            2. Sift the variable up and down, remembering each time the + total size of the DD heap. +
            3. Select the best permutation. +
            4. Repeat 3 and 4 for all variables. +
            + Returns 1 if successful; 0 otherwise. +

            + +

            Side Effects None +

            + +

            Defined in cuddZddReord.c + +
            +
            +DdNode * 
            +cuddZddSubset0(
            +  DdManager * dd, 
            +  DdNode * P, 
            +  int  var 
            +)
            +
            +
            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. +

            + +

            Side Effects None +

            + +

            See Also cuddZddSubset1 +Cudd_zddSubset0 + + +
            Defined in cuddZddSetop.c + +
            +
            +DdNode * 
            +cuddZddSubset1(
            +  DdManager * dd, 
            +  DdNode * P, 
            +  int  var 
            +)
            +
            +
            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. +

            + +

            Side Effects None +

            + +

            See Also cuddZddSubset0 +Cudd_zddSubset1 + + +
            Defined in cuddZddSetop.c + +
            +
            +int 
            +cuddZddSwapInPlace(
            +  DdManager * table, 
            +  int  x, 
            +  int  y 
            +)
            +
            +
            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 < y. Returns the number of keys in + the table if successful; 0 otherwise. +

            + +

            Side Effects None +

            + +

            Defined in cuddZddReord.c + +
            +
            +int 
            +cuddZddSwapping(
            +  DdManager * table, 
            +  int  lower, 
            +  int  upper, 
            +  Cudd_ReorderingType  heuristic 
            +)
            +
            +
            Implementation of Plessier's algorithm that reorders + variables by a sequence of (non-adjacent) swaps. +
              +
            1. Select two variables (RANDOM or HEURISTIC). +
            2. Permute these variables. +
            3. If the nodes have decreased accept the permutation. +
            4. Otherwise reconstruct the original heap. +
            5. Loop. +
            + Returns 1 in case of success; 0 otherwise. +

            + +

            Side Effects None +

            + +

            Defined in cuddZddReord.c + +
            +
            +int 
            +cuddZddSymmCheck(
            +  DdManager * table, 
            +  int  x, 
            +  int  y 
            +)
            +
            +
            Checks for symmetry of x and y. Ignores projection + functions, unless they are isolated. Returns 1 in case of + symmetry; 0 otherwise. +

            + +

            Side Effects None +

            + +

            Defined in cuddZddSymm.c + +
            +
            +static int 
            +cuddZddSymmSiftingAux(
            +  DdManager * table, 
            +  int  x, 
            +  int  x_low, 
            +  int  x_high 
            +)
            +
            +
            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. +

            + +

            Side Effects None +

            + +

            Defined in cuddZddSymm.c + +
            +
            +static int 
            +cuddZddSymmSiftingBackward(
            +  DdManager * table, 
            +  Move * moves, 
            +  int  size 
            +)
            +
            +
            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. +

            + +

            Side Effects None +

            + +

            Defined in cuddZddSymm.c + +
            +
            +static int 
            +cuddZddSymmSiftingConvAux(
            +  DdManager * table, 
            +  int  x, 
            +  int  x_low, 
            +  int  x_high 
            +)
            +
            +
            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. +

            + +

            Side Effects None +

            + +

            Defined in cuddZddSymm.c + +
            +
            +int 
            +cuddZddSymmSiftingConv(
            +  DdManager * table, 
            +  int  lower, 
            +  int  upper 
            +)
            +
            +
            Symmetric sifting to convergence algorithm for ZDDs. + Assumes that no dead nodes are present. +
              +
            1. Order all the variables according to the number of entries in + each unique subtable. +
            2. Sift the variable up and down, remembering each time the total + size of the ZDD heap and grouping variables that are symmetric. +
            3. Select the best permutation. +
            4. Repeat 3 and 4 for all variables. +
            5. Repeat 1-4 until no further improvement. +
            + Returns 1 plus the number of symmetric variables if successful; 0 + otherwise. +

            + +

            Side Effects None +

            + +

            See Also cuddZddSymmSifting + + +
            Defined in cuddZddSymm.c + +
            +
            +static Move * 
            +cuddZddSymmSifting_down(
            +  DdManager * table, 
            +  int  x, 
            +  int  x_high, 
            +  int  initial_size 
            +)
            +
            +
            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. +

            + +

            Side Effects None +

            + +

            Defined in cuddZddSymm.c + +
            +
            +static Move * 
            +cuddZddSymmSifting_up(
            +  DdManager * table, 
            +  int  x, 
            +  int  x_low, 
            +  int  initial_size 
            +)
            +
            +
            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. +

            + +

            Side Effects None +

            + +

            Defined in cuddZddSymm.c + +
            +
            +int 
            +cuddZddSymmSifting(
            +  DdManager * table, 
            +  int  lower, 
            +  int  upper 
            +)
            +
            +
            Symmetric sifting algorithm. + Assumes that no dead nodes are present. +
              +
            1. Order all the variables according to the number of entries in + each unique subtable. +
            2. Sift the variable up and down, remembering each time the total + size of the ZDD heap and grouping variables that are symmetric. +
            3. Select the best permutation. +
            4. Repeat 3 and 4 for all variables. +
            + Returns 1 plus the number of symmetric variables if successful; 0 + otherwise. +

            + +

            Side Effects None +

            + +

            See Also cuddZddSymmSiftingConv + + +
            Defined in cuddZddSymm.c + +
            +
            +static void 
            +cuddZddSymmSummary(
            +  DdManager * table, 
            +  int  lower, 
            +  int  upper, 
            +  int * symvars, 
            +  int * symgroups 
            +)
            +
            +
            Counts numbers of symmetric variables and symmetry + groups. +

            + +

            Side Effects None +

            + +

            Defined in cuddZddSymm.c + +
            +
            +int 
            +cuddZddTreeSifting(
            +  DdManager * table, DD table
            +  Cudd_ReorderingType  method reordering method for the groups of leaves
            +)
            +
            +
            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. +

            + +

            Side Effects None +

            + +

            Defined in cuddZddGroup.c + +
            +
            +DdNode	* 
            +cuddZddUnateProduct(
            +  DdManager * dd, 
            +  DdNode * f, 
            +  DdNode * g 
            +)
            +
            +
            Performs the recursive step of Cudd_zddUnateProduct. +

            + +

            Side Effects None +

            + +

            See Also Cudd_zddUnateProduct + + +
            Defined in cuddZddFuncs.c + +
            +
            +static Move* 
            +cuddZddUndoMoves(
            +  DdManager * table, 
            +  Move * moves 
            +)
            +
            +
            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. +

            + +

            Side Effects None +

            + +

            Defined in cuddZddLin.c + +
            +
            +DdNode * 
            +cuddZddUnion(
            +  DdManager * zdd, 
            +  DdNode * P, 
            +  DdNode * Q 
            +)
            +
            +
            Performs the recursive step of Cudd_zddUnion. +

            + +

            Side Effects None +

            + +

            Defined in cuddZddSetop.c + +
            +
            +int 
            +cuddZddUniqueCompare(
            +  int * ptr_x, 
            +  int * ptr_y 
            +)
            +
            +
            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. +

            + +

            Side Effects None +

            + +

            Defined in cuddZddReord.c + +
            +
            +DdNode	* 
            +cuddZddWeakDivF(
            +  DdManager * dd, 
            +  DdNode * f, 
            +  DdNode * g 
            +)
            +
            +
            Performs the recursive step of Cudd_zddWeakDivF. +

            + +

            Side Effects None +

            + +

            See Also Cudd_zddWeakDivF + + +
            Defined in cuddZddFuncs.c + +
            +
            +DdNode	* 
            +cuddZddWeakDiv(
            +  DdManager * dd, 
            +  DdNode * f, 
            +  DdNode * g 
            +)
            +
            +
            Performs the recursive step of Cudd_zddWeakDiv. +

            + +

            Side Effects None +

            + +

            See Also Cudd_zddWeakDiv + + +
            Defined in cuddZddFuncs.c + +
            +
            +static DdNode * 
            +ddBddToAddRecur(
            +  DdManager * dd, 
            +  DdNode * B 
            +)
            +
            +
            Performs the recursive step for Cudd_BddToAdd. Returns a + pointer to the resulting ADD if successful; NULL otherwise. +

            + +

            Side Effects None +

            + +

            Defined in cuddBridge.c + +
            +
            +static int 
            +ddCheckPermuation(
            +  DdManager * table, 
            +  MtrNode * treenode, 
            +  int * perm, 
            +  int * invperm 
            +)
            +
            +
            Checks the BDD variable group tree before a shuffle. + Returns 1 if successful; 0 otherwise. +

            + +

            Side Effects Changes the BDD variable group tree. +

            + +

            Defined in cuddReorder.c + +
            +
            +static void 
            +ddClearFlag(
            +  DdNode * f 
            +)
            +
            +
            Performs a DFS from f, clearing the LSB of the next + pointers. +

            + +

            Side Effects None +

            + +

            See Also ddSupportStep +ddDagInt + + +
            Defined in cuddUtil.c + +
            +
            +static void 
            +ddClearGlobal(
            +  DdManager * table, 
            +  int  lower, 
            +  int  maxlevel 
            +)
            +
            +
            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. +

            + +

            Side Effects None +

            + +

            See Also ddCountRoots + + +
            Defined in cuddExact.c + +
            +
            +static void 
            +ddClearGlobal(
            +  DdManager * table 
            +)
            +
            +
            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. +

            + +

            Side Effects None +

            + +

            Defined in cuddInteract.c + +
            +
            +static void 
            +ddClearLocal(
            +  DdNode * f 
            +)
            +
            +
            Performs a DFS from f, clearing the LSB of the then pointers. +

            + +

            Side Effects None +

            + +

            Defined in cuddInteract.c + +
            +
            +static double * 
            +ddCofMintermAux(
            +  DdManager * dd, 
            +  DdNode * node, 
            +  st_table * table 
            +)
            +
            +
            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. +

            + +

            Side Effects None +

            + +

            Defined in cuddSign.c + +
            +
            +static int 
            +ddCountInternalMtrNodes(
            +  DdManager * table, 
            +  MtrNode * treenode 
            +)
            +
            +
            Counts the number of internal nodes of the group tree. + Returns the count. +

            + +

            Side Effects None +

            + +

            Defined in cuddGroup.c + +
            +
            +static double 
            +ddCountMintermAux(
            +  DdNode * node, 
            +  double  max, 
            +  DdHashTable * table 
            +)
            +
            +
            Performs the recursive step of Cudd_CountMinterm. + It is based on the following identity. Let |f| be the + number of minterms of f. Then: + + |f| = (|f0|+|f1|)/2 + + 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. +

            + +

            Side Effects None +

            + +

            Defined in cuddUtil.c + +
            +
            +static double 
            +ddCountPathAux(
            +  DdNode * node, 
            +  st_table * table 
            +)
            +
            +
            Performs the recursive step of Cudd_CountPath. + It is based on the following identity. Let |f| be the + number of paths of f. Then: + + |f| = |f0|+|f1| + + 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. +

            + +

            Side Effects None +

            + +

            Defined in cuddUtil.c + +
            +
            +static double 
            +ddCountPathsToNonZero(
            +  DdNode * N, 
            +  st_table * table 
            +)
            +
            +
            Performs the recursive step of Cudd_CountPathsToNonZero. + It is based on the following identity. Let |f| be the + number of paths of f. Then: + + |f| = |f0|+|f1| + + where f0 and f1 are the two cofactors of f. Returns the number of + paths of the function rooted at node. +

            + +

            Side Effects None +

            + +

            Defined in cuddUtil.c + +
            +
            +static int 
            +ddCountRoots(
            +  DdManager * table, 
            +  int  lower, 
            +  int  upper 
            +)
            +
            +
            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. +

            + +

            Side Effects None +

            + +

            See Also ddClearGlobal + + +
            Defined in cuddExact.c + +
            +
            +static void 
            +ddCreateGroup(
            +  DdManager * table, 
            +  int  x, 
            +  int  y 
            +)
            +
            +
            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. +

            + +

            Side Effects None +

            + +

            Defined in cuddGroup.c + +
            +
            +static int 
            +ddDagInt(
            +  DdNode * n 
            +)
            +
            +
            Performs the recursive step of Cudd_DagSize. Returns the + number of nodes in the graph rooted at n. +

            + +

            Side Effects None +

            + +

            Defined in cuddUtil.c + +
            +
            +static void 
            +ddDissolveGroup(
            +  DdManager * table, 
            +  int  x, 
            +  int  y 
            +)
            +
            +
            x and y are variables in a group to be cut in two. The cut + is to pass between x and y. +

            + +

            Side Effects None +

            + +

            Defined in cuddGroup.c + +
            +
            +static int 
            +ddDoDumpBlif(
            +  DdManager * dd, 
            +  DdNode * f, 
            +  FILE * fp, 
            +  st_table * visited, 
            +  char ** names, 
            +  int  mv 
            +)
            +
            +
            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. +

            + +

            Side Effects None +

            + +

            Defined in cuddExport.c + +
            +
            +static int 
            +ddDoDumpDDcal(
            +  DdManager * dd, 
            +  DdNode * f, 
            +  FILE * fp, 
            +  st_table * visited, 
            +  char ** names, 
            +  unsigned long  mask 
            +)
            +
            +
            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. +

            + +

            Side Effects None +

            + +

            Defined in cuddExport.c + +
            +
            +static int 
            +ddDoDumpDaVinci(
            +  DdManager * dd, 
            +  DdNode * f, 
            +  FILE * fp, 
            +  st_table * visited, 
            +  char ** names, 
            +  unsigned long  mask 
            +)
            +
            +
            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. +

            + +

            Side Effects None +

            + +

            Defined in cuddExport.c + +
            +
            +static int 
            +ddDoDumpFactoredForm(
            +  DdManager * dd, 
            +  DdNode * f, 
            +  FILE * fp, 
            +  char ** names 
            +)
            +
            +
            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. +

            + +

            Side Effects None +

            + +

            See Also Cudd_DumpFactoredForm + + +
            Defined in cuddExport.c + +
            +
            +static int 
            +ddEpdCountMintermAux(
            +  DdNode * node, 
            +  EpDouble * max, 
            +  EpDouble * epd, 
            +  st_table * table 
            +)
            +
            +
            Performs the recursive step of Cudd_EpdCountMinterm. + It is based on the following identity. Let |f| be the + number of minterms of f. Then: + + |f| = (|f0|+|f1|)/2 + + 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. +

            + +

            Side Effects None +

            + +

            Defined in cuddUtil.c + +
            +
            +static enum st_retval 
            +ddEpdFree(
            +  char * key, 
            +  char * value, 
            +  char * arg 
            +)
            +
            +
            Frees the memory used to store the minterm counts + recorded in the visited table. Returns ST_CONTINUE. +

            + +

            Side Effects None +

            + +

            Defined in cuddUtil.c + +
            +
            +static int 
            +ddExchange(
            +  DdManager * table, 
            +  int  x, 
            +  int  y, 
            +  double  temp 
            +)
            +
            +
            This is the same funcion as ddSwapping except for + comparison expression. Use probability function, exp(-size_change/temp). +

            + +

            Side Effects None +

            + +

            Defined in cuddAnneal.c + +
            +
            +static int 
            +ddExtSymmCheck(
            +  DdManager * table, 
            +  int  x, 
            +  int  y 
            +)
            +
            +
            Checks for extended symmetry of x and y. Returns 1 in + case of extended symmetry; 0 otherwise. +

            + +

            Side Effects None +

            + +

            Defined in cuddGroup.c + +
            +
            +static DdNode * 
            +ddFindEssentialRecur(
            +  DdManager * dd, 
            +  DdNode * f 
            +)
            +
            +
            Implements the recursive step of Cudd_FindEssential. + Returns a pointer to the cube BDD if successful; NULL otherwise. +

            + +

            Side Effects None +

            + +

            Defined in cuddEssent.c + +
            +
            +static void 
            +ddFindNodeHiLo(
            +  DdManager * table, 
            +  MtrNode * treenode, 
            +  int * lower, 
            +  int * upper 
            +)
            +
            +
            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. +

            + +

            Side Effects The bounds are returned as side effects. +

            + +

            Defined in cuddGroup.c + +
            +
            +static DdTlcInfo * 
            +ddFindTwoLiteralClausesRecur(
            +  DdManager * dd, 
            +  DdNode * f, 
            +  st_table * table 
            +)
            +
            +
            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. +

            + +

            Side Effects None +

            + +

            See Also Cudd_FindTwoLiteralClauses + + +
            Defined in cuddEssent.c + +
            +
            +static void 
            +ddFixLimits(
            +  DdManager * unique 
            +)
            +
            +
            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. +

            + +

            Side Effects Modifies manager fields. May resize computed table. +

            + +

            Defined in cuddTable.c + +
            +
            +static int 
            +ddGroupMoveBackward(
            +  DdManager * table, 
            +  int  x, 
            +  int  y 
            +)
            +
            +
            Undoes the swap two groups. Returns 1 in case of + success; 0 otherwise. +

            + +

            Side Effects None +

            + +

            Defined in cuddGroup.c + +
            +
            +static int 
            +ddGroupMove(
            +  DdManager * table, 
            +  int  x, 
            +  int  y, 
            +  Move ** moves 
            +)
            +
            +
            Swaps two groups and records the move. Returns the + number of keys in the DD table in case of success; 0 otherwise. +

            + +

            Side Effects None +

            + +

            Defined in cuddGroup.c + +
            +
            +static int 
            +ddGroupSiftingAux(
            +  DdManager * table, 
            +  int  x, 
            +  int  xLow, 
            +  int  xHigh, 
            +  DD_CHKFP  checkFunction, 
            +  int  lazyFlag 
            +)
            +
            +
            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. +

            + +

            Side Effects None +

            + +

            Defined in cuddGroup.c + +
            +
            +static int 
            +ddGroupSiftingBackward(
            +  DdManager * table, 
            +  Move * moves, 
            +  int  size, 
            +  int  upFlag, 
            +  int  lazyFlag 
            +)
            +
            +
            Determines the best position for a variables and returns + it there. Returns 1 in case of success; 0 otherwise. +

            + +

            Side Effects None +

            + +

            Defined in cuddGroup.c + +
            +
            +static int 
            +ddGroupSiftingDown(
            +  DdManager * table, 
            +  int  x, 
            +  int  xHigh, 
            +  DD_CHKFP  checkFunction, 
            +  Move ** moves 
            +)
            +
            +
            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. +

            + +

            Side Effects None +

            + +

            Defined in cuddGroup.c + +
            +
            +static int 
            +ddGroupSiftingUp(
            +  DdManager * table, 
            +  int  y, 
            +  int  xLow, 
            +  DD_CHKFP  checkFunction, 
            +  Move ** moves 
            +)
            +
            +
            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. +

            + +

            Side Effects None +

            + +

            Defined in cuddGroup.c + +
            +
            +static int 
            +ddGroupSifting(
            +  DdManager * table, 
            +  int  lower, 
            +  int  upper, 
            +  DD_CHKFP  checkFunction, 
            +  int  lazyFlag 
            +)
            +
            +
            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. +

            + +

            Side Effects None +

            + +

            Defined in cuddGroup.c + +
            +
            +static int 
            +ddIsIthAddVarPair(
            +  DdManager * dd, 
            +  DdNode * f, 
            +  DdNode * g, 
            +  unsigned int  i 
            +)
            +
            +
            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. +

            + +

            Side Effects None +

            + +

            Defined in cuddCompose.c + +
            +
            +static int 
            +ddIsIthAddVar(
            +  DdManager * dd, 
            +  DdNode * f, 
            +  unsigned int  i 
            +)
            +
            +
            Comparison of a function to the i-th ADD variable. Returns 1 if + the function is the i-th ADD variable; 0 otherwise. +

            + +

            Side Effects None +

            + +

            Defined in cuddCompose.c + +
            +
            +static int 
            +ddIsVarHandled(
            +  DdManager * dd, 
            +  int  index 
            +)
            +
            +
            Checks whether a variables is already handled. This + function is used for lazy sifting. +

            + +

            Side Effects none +

            + +

            Defined in cuddGroup.c + +
            +
            +static int 
            +ddJumpingAux(
            +  DdManager * table, 
            +  int  x, 
            +  int  x_low, 
            +  int  x_high, 
            +  double  temp 
            +)
            +
            +
            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. +

            + +

            Side Effects None +

            + +

            Defined in cuddAnneal.c + +
            +
            +static Move * 
            +ddJumpingDown(
            +  DdManager * table, 
            +  int  x, 
            +  int  x_high, 
            +  int  initial_size 
            +)
            +
            +
            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. +

            + +

            Side Effects None +

            + +

            Defined in cuddAnneal.c + +
            +
            +static Move * 
            +ddJumpingUp(
            +  DdManager * table, 
            +  int  x, 
            +  int  x_low, 
            +  int  initial_size 
            +)
            +
            +
            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. +

            + +

            Side Effects None +

            + +

            Defined in cuddAnneal.c + +
            +
            +static unsigned int 
            +ddLCHash(
            +  DdNodePtr * key, 
            +  unsigned int  keysize, 
            +  int  shift 
            +)
            +
            +
            Computes the hash value for a local cache. Returns the + bucket index. +

            + +

            Side Effects None +

            + +

            Defined in cuddLCache.c + +
            +
            +static int 
            +ddLeavesInt(
            +  DdNode * n 
            +)
            +
            +
            Performs the recursive step of Cudd_CountLeaves. Returns + the number of leaves in the DD rooted at n. +

            + +

            Side Effects None +

            + +

            See Also Cudd_CountLeaves + + +
            Defined in cuddUtil.c + +
            +
            +static int 
            +ddLinearAndSiftingAux(
            +  DdManager * table, 
            +  int  x, 
            +  int  xLow, 
            +  int  xHigh 
            +)
            +
            +
            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. +

            + +

            Side Effects None +

            + +

            Defined in cuddLinear.c + +
            +
            +static int 
            +ddLinearAndSiftingBackward(
            +  DdManager * table, 
            +  int  size, 
            +  Move * moves 
            +)
            +
            +
            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. +

            + +

            Side Effects None +

            + +

            Defined in cuddLinear.c + +
            +
            +static Move * 
            +ddLinearAndSiftingDown(
            +  DdManager * table, 
            +  int  x, 
            +  int  xHigh, 
            +  Move * prevMoves 
            +)
            +
            +
            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. +

            + +

            Side Effects None +

            + +

            Defined in cuddLinear.c + +
            +
            +static Move * 
            +ddLinearAndSiftingUp(
            +  DdManager * table, 
            +  int  y, 
            +  int  xLow, 
            +  Move * prevMoves 
            +)
            +
            +
            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. +

            + +

            Side Effects None +

            + +

            Defined in cuddLinear.c + +
            +
            +static int 
            +ddLinearUniqueCompare(
            +  int * ptrX, 
            +  int * ptrY 
            +)
            +
            +
            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. +

            + +

            Side Effects None +

            + +

            Defined in cuddLinear.c + +
            +
            +static void 
            +ddMergeGroups(
            +  DdManager * table, 
            +  MtrNode * treenode, 
            +  int  low, 
            +  int  high 
            +)
            +
            +
            Creates a single group from low to high and adjusts the + index field of the tree node. +

            + +

            Side Effects None +

            + +

            Defined in cuddGroup.c + +
            +
            +static int 
            +ddNoCheck(
            +  DdManager * table, 
            +  int  x, 
            +  int  y 
            +)
            +
            +
            Pretends to check two variables for aggregation. Always + returns 0. +

            + +

            Side Effects None +

            + +

            Defined in cuddGroup.c + +
            +
            +static void 
            +ddPatchTree(
            +  DdManager * dd, 
            +  MtrNode * treenode 
            +)
            +
            +
            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. +

            + +

            Side Effects None +

            + +

            Defined in cuddTable.c + +
            +
            +static int 
            +ddPermuteWindow3(
            +  DdManager * table, 
            +  int  x 
            +)
            +
            +
            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. +

            + +

            Side Effects None +

            + +

            Defined in cuddWindow.c + +
            +
            +static int 
            +ddPermuteWindow4(
            +  DdManager * table, 
            +  int  w 
            +)
            +
            +
            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. +

            + +

            Side Effects None +

            + +

            Defined in cuddWindow.c + +
            +
            +static int 
            +ddPickArbitraryMinterms(
            +  DdManager * dd, 
            +  DdNode * node, 
            +  int  nvars, 
            +  int  nminterms, 
            +  char ** string 
            +)
            +
            +
            Performs the recursive step of Cudd_bddPickArbitraryMinterms. + Returns 1 if successful; 0 otherwise. +

            + +

            Side Effects none +

            + +

            See Also Cudd_bddPickArbitraryMinterms + + +
            Defined in cuddUtil.c + +
            +
            +static int 
            +ddPickRepresentativeCube(
            +  DdManager * dd, 
            +  DdNode * node, 
            +  double * weight, 
            +  char * string 
            +)
            +
            +
            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. +

            + +

            Side Effects Cudd_SubsetWithMaskVars Cudd_bddPickOneCube +

            + +

            Defined in cuddUtil.c + +
            +
            +static void 
            +ddPrintMintermAux(
            +  DdManager * dd, manager
            +  DdNode * node, current node
            +  int * list current recursion path
            +)
            +
            +
            Performs the recursive step of Cudd_PrintMinterm. +

            + +

            Side Effects None +

            + +

            Defined in cuddUtil.c + +
            +
            +static void 
            +ddRehashZdd(
            +  DdManager * unique, 
            +  int  i 
            +)
            +
            +
            Rehashes a ZDD unique subtable. +

            + +

            Side Effects None +

            + +

            See Also cuddRehash + + +
            Defined in cuddTable.c + +
            +
            +static int 
            +ddReorderChildren(
            +  DdManager * table, 
            +  MtrNode * treenode, 
            +  Cudd_ReorderingType  method 
            +)
            +
            +
            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. +

            + +

            Side Effects None +

            + +

            Defined in cuddGroup.c + +
            +
            +static int 
            +ddReorderPostprocess(
            +  DdManager * table 
            +)
            +
            +
            Cleans up at the end of reordering. +

            + +

            Side Effects None +

            + +

            Defined in cuddReorder.c + +
            +
            +static int 
            +ddReorderPreprocess(
            +  DdManager * table 
            +)
            +
            +
            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. +

            + +

            Side Effects None +

            + +

            Defined in cuddReorder.c + +
            +
            +static void 
            +ddReportRefMess(
            +  DdManager * unique, manager
            +  int  i, table in which the problem occurred
            +  const char * caller procedure that detected the problem
            +)
            +
            +
            Reports problem in garbage collection. +

            + +

            Side Effects None +

            + +

            See Also cuddGarbageCollect +cuddGarbageCollectZdd + + +
            Defined in cuddTable.c + +
            +
            +static int 
            +ddResetVarHandled(
            +  DdManager * dd, 
            +  int  index 
            +)
            +
            +
            Resets a variable to be processed. This function is used + for lazy sifting. +

            + +

            Side Effects none +

            + +

            Defined in cuddGroup.c + +
            +
            +static int 
            +ddResizeTable(
            +  DdManager * unique, 
            +  int  index 
            +)
            +
            +
            Increases the number of subtables in a unique table so + that it meets or exceeds index. Returns 1 if successful; 0 otherwise. +

            + +

            Side Effects None +

            + +

            See Also cuddResizeTableZdd + + +
            Defined in cuddTable.c + +
            +
            +static int 
            +ddSecDiffCheck(
            +  DdManager * table, 
            +  int  x, 
            +  int  y 
            +)
            +
            +
            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. +

            + +

            Side Effects None +

            + +

            Defined in cuddGroup.c + +
            +
            +static int 
            +ddSetVarHandled(
            +  DdManager * dd, 
            +  int  index 
            +)
            +
            +
            Sets a variable to already handled. This function is used + for lazy sifting. +

            + +

            Side Effects none +

            + +

            Defined in cuddGroup.c + +
            +
            +static int 
            +ddShuffle(
            +  DdManager * table, 
            +  DdHalfWord * permutation, 
            +  int  lower, 
            +  int  upper 
            +)
            +
            +
            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. +

            + +

            Side Effects None +

            + +

            Defined in cuddExact.c + +
            +
            +static int 
            +ddShuffle(
            +  DdManager * table, 
            +  int * permutation 
            +)
            +
            +
            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. +

            + +

            Side Effects None +

            + +

            Defined in cuddReorder.c + +
            +
            +static int 
            +ddSiftUp(
            +  DdManager * table, 
            +  int  x, 
            +  int  xLow 
            +)
            +
            +
            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 +

            + +

            Side Effects None +

            + +

            Defined in cuddExact.c + +
            +
            +static int 
            +ddSiftUp(
            +  DdManager * table, 
            +  int  x, 
            +  int  xLow 
            +)
            +
            +
            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 +

            + +

            Side Effects None +

            + +

            Defined in cuddReorder.c + +
            +
            +static int 
            +ddSiftingAux(
            +  DdManager * table, 
            +  int  x, 
            +  int  xLow, 
            +  int  xHigh 
            +)
            +
            +
            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. +

            + +

            Side Effects None +

            + +

            Defined in cuddReorder.c + +
            +
            +static int 
            +ddSiftingBackward(
            +  DdManager * table, 
            +  int  size, 
            +  Move * moves 
            +)
            +
            +
            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. +

            + +

            Side Effects None +

            + +

            Defined in cuddReorder.c + +
            +
            +static Move * 
            +ddSiftingDown(
            +  DdManager * table, 
            +  int  x, 
            +  int  xHigh 
            +)
            +
            +
            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. +

            + +

            Side Effects None +

            + +

            Defined in cuddReorder.c + +
            +
            +static Move * 
            +ddSiftingUp(
            +  DdManager * table, 
            +  int  y, 
            +  int  xLow 
            +)
            +
            +
            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. +

            + +

            Side Effects None +

            + +

            Defined in cuddReorder.c + +
            +
            +static void 
            +ddSuppInteract(
            +  DdNode * f, 
            +  int * support 
            +)
            +
            +
            Performs a DFS from f. Uses the LSB of the then pointer + as visited flag. +

            + +

            Side Effects Accumulates in support the variables on which f depends. +

            + +

            Defined in cuddInteract.c + +
            +
            +static void 
            +ddSupportStep(
            +  DdNode * f, 
            +  int * support 
            +)
            +
            +
            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. +

            + +

            Side Effects None +

            + +

            See Also ddClearFlag + + +
            Defined in cuddUtil.c + +
            +
            +static Move * 
            +ddSwapAny(
            +  DdManager * table, 
            +  int  x, 
            +  int  y 
            +)
            +
            +
            Swaps any two variables. Returns the set of moves. +

            + +

            Side Effects None +

            + +

            Defined in cuddReorder.c + +
            +
            +static int 
            +ddSymmGroupMoveBackward(
            +  DdManager * table, 
            +  int  x, 
            +  int  y 
            +)
            +
            +
            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. +

            + +

            Side Effects None +

            + +

            Defined in cuddSymmetry.c + +
            +
            +static int 
            +ddSymmGroupMove(
            +  DdManager * table, 
            +  int  x, 
            +  int  y, 
            +  Move ** moves 
            +)
            +
            +
            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. +

            + +

            Side Effects None +

            + +

            Defined in cuddSymmetry.c + +
            +
            +static int 
            +ddSymmSiftingAux(
            +  DdManager * table, 
            +  int  x, 
            +  int  xLow, 
            +  int  xHigh 
            +)
            +
            +
            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. +

            + +

            Side Effects None +

            + +

            Defined in cuddSymmetry.c + +
            +
            +static int 
            +ddSymmSiftingBackward(
            +  DdManager * table, 
            +  Move * moves, 
            +  int  size 
            +)
            +
            +
            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. +

            + +

            Side Effects None +

            + +

            Defined in cuddSymmetry.c + +
            +
            +static int 
            +ddSymmSiftingConvAux(
            +  DdManager * table, 
            +  int  x, 
            +  int  xLow, 
            +  int  xHigh 
            +)
            +
            +
            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. +

            + +

            Side Effects None +

            + +

            Defined in cuddSymmetry.c + +
            +
            +static Move * 
            +ddSymmSiftingDown(
            +  DdManager * table, 
            +  int  x, 
            +  int  xHigh 
            +)
            +
            +
            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. +

            + +

            Side Effects None +

            + +

            Defined in cuddSymmetry.c + +
            +
            +static Move * 
            +ddSymmSiftingUp(
            +  DdManager * table, 
            +  int  y, 
            +  int  xLow 
            +)
            +
            +
            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. +

            + +

            Side Effects None +

            + +

            Defined in cuddSymmetry.c + +
            +
            +static void 
            +ddSymmSummary(
            +  DdManager * table, 
            +  int  lower, 
            +  int  upper, 
            +  int * symvars, 
            +  int * symgroups 
            +)
            +
            +
            Counts numbers of symmetric variables and symmetry + groups. +

            + +

            Side Effects None +

            + +

            Defined in cuddSymmetry.c + +
            +
            +static int 
            +ddSymmUniqueCompare(
            +  int * ptrX, 
            +  int * ptrY 
            +)
            +
            +
            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. +

            + +

            Side Effects None +

            + +

            Defined in cuddSymmetry.c + +
            +
            +static int 
            +ddTreeSiftingAux(
            +  DdManager * table, 
            +  MtrNode * treenode, 
            +  Cudd_ReorderingType  method 
            +)
            +
            +
            Recursively visits the group tree and reorders each + group in postorder fashion. Returns 1 if successful; 0 otherwise. +

            + +

            Side Effects None +

            + +

            Defined in cuddGroup.c + +
            +
            +static Move* 
            +ddUndoMoves(
            +  DdManager * table, 
            +  Move * moves 
            +)
            +
            +
            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. +

            + +

            Side Effects None +

            + +

            Defined in cuddLinear.c + +
            +
            +static int 
            +ddUniqueCompareGroup(
            +  int * ptrX, 
            +  int * ptrY 
            +)
            +
            +
            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. +

            + +

            Side Effects None +

            + +

            Defined in cuddGroup.c + +
            +
            +static int 
            +ddUniqueCompare(
            +  int * ptrX, 
            +  int * ptrY 
            +)
            +
            +
            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. +

            + +

            Side Effects None +

            + +

            Defined in cuddReorder.c + +
            +
            +static void 
            +ddUpdateInteract(
            +  DdManager * table, 
            +  int * support 
            +)
            +
            +
            If support[i +

            + +

            Side Effects None +

            + +

            Defined in cuddInteract.c + +
            +
            +static int 
            +ddUpdateMtrTree(
            +  DdManager * table, 
            +  MtrNode * treenode, 
            +  int * perm, 
            +  int * invperm 
            +)
            +
            +
            Updates the BDD variable group tree before a shuffle. + Returns 1 if successful; 0 otherwise. +

            + +

            Side Effects Changes the BDD variable group tree. +

            + +

            Defined in cuddReorder.c + +
            +
            +static int 
            +ddVarGroupCheck(
            +  DdManager * table, 
            +  int  x, 
            +  int  y 
            +)
            +
            +
            Checks for grouping of x and y. Returns 1 in + case of grouping; 0 otherwise. This function is used for lazy sifting. +

            + +

            Side Effects None +

            + +

            Defined in cuddGroup.c + +
            +
            +static int 
            +ddWindow2(
            +  DdManager * table, 
            +  int  low, 
            +  int  high 
            +)
            +
            +
            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. +

            + +

            Side Effects None +

            + +

            Defined in cuddWindow.c + +
            +
            +static int 
            +ddWindow3(
            +  DdManager * table, 
            +  int  low, 
            +  int  high 
            +)
            +
            +
            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. +

            + +

            Side Effects None +

            + +

            Defined in cuddWindow.c + +
            +
            +static int 
            +ddWindow4(
            +  DdManager * table, 
            +  int  low, 
            +  int  high 
            +)
            +
            +
            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. +

            + +

            Side Effects None +

            + +

            Defined in cuddWindow.c + +
            +
            +static int 
            +ddWindowConv2(
            +  DdManager * table, 
            +  int  low, 
            +  int  high 
            +)
            +
            +
            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. +

            + +

            Side Effects None +

            + +

            Defined in cuddWindow.c + +
            +
            +static int 
            +ddWindowConv3(
            +  DdManager * table, 
            +  int  low, 
            +  int  high 
            +)
            +
            +
            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. +

            + +

            Side Effects None +

            + +

            Defined in cuddWindow.c + +
            +
            +static int 
            +ddWindowConv4(
            +  DdManager * table, 
            +  int  low, 
            +  int  high 
            +)
            +
            +
            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. +

            + +

            Side Effects None +

            + +

            Defined in cuddWindow.c + +
            +
            +static void 
            +debugCheckParent(
            +  DdManager * table, 
            +  DdNode * node 
            +)
            +
            +
            Searches all the subtables above node. Very expensive. + The same check is now implemented more efficiently in ddDebugCheck. +

            + +

            Side Effects None +

            + +

            See Also debugFindParent + + +
            Defined in cuddCheck.c + +
            +
            +static void 
            +debugFindParent(
            +  DdManager * table, 
            +  DdNode * node 
            +)
            +
            +
            Searches the subtables above node for its parents. +

            + +

            Side Effects None +

            + +

            Defined in cuddCheck.c + +
            +
            +static int 
            +dp2(
            +  DdManager * dd, 
            +  DdNode * f, 
            +  st_table * t 
            +)
            +
            +
            Performs the recursive step of cuddP. Returns 1 in case + of success; 0 otherwise. +

            + +

            Side Effects None +

            + +

            Defined in cuddUtil.c + +
            +
            +static DdTlcInfo * 
            +emptyClauseSet(
            +    
            +)
            +
            +
            Returns a pointer to an empty set of clauses if + successful; NULL otherwise. No bit vector for the phases is + allocated. +

            + +

            Side Effects None +

            + +

            Defined in cuddEssent.c + +
            +
            +static int 
            +equalp(
            +  DdHalfWord  var1a, 
            +  short  phase1a, 
            +  DdHalfWord  var1b, 
            +  short  phase1b, 
            +  DdHalfWord  var2a, 
            +  short  phase2a, 
            +  DdHalfWord  var2b, 
            +  short  phase2b 
            +)
            +
            +
            Returns true iff the two arguments are identical + clauses. Since literals are sorted, we only need to compare + literals in the same position. +

            + +

            Side Effects None +

            + +

            See Also beforep + + +
            Defined in cuddEssent.c + +
            +
            +static double 
            +find_average_fitness(
            +    
            +)
            +
            +
            Returns the average fitness of the population. +

            + +

            Side Effects None +

            + +

            Defined in cuddGenetic.c + +
            +
            +static int 
            +find_best(
            +    
            +)
            +
            +
            Returns the index of the fittest individual. +

            + +

            Side Effects None +

            + +

            Defined in cuddGenetic.c + +
            +
            +static void 
            +fixVarTree(
            +  MtrNode * treenode, 
            +  int * perm, 
            +  int  size 
            +)
            +
            +
            Fixes a variable group tree. +

            + +

            Side Effects Changes the variable group tree. +

            + +

            Defined in cuddAPI.c + +
            +
            +static void 
            +freeMatrix(
            +  DdHalfWord ** matrix 
            +)
            +
            +
            Frees a two-dimensional matrix allocated by getMatrix. +

            + +

            Side Effects None +

            + +

            See Also getMatrix + + +
            Defined in cuddExact.c + +
            +
            +static enum st_retval 
            +freePathPair(
            +  char * key, 
            +  char * value, 
            +  char * arg 
            +)
            +
            +
            Frees the entries of the visited symbol table. Returns + ST_CONTINUE. +

            + +

            Side Effects None +

            + +

            Defined in cuddSat.c + +
            +
            +static NodeData * 
            +gatherInfoAux(
            +  DdNode * node, function to analyze
            +  ApproxInfo * info, info on BDD
            +  int  parity gather parity information
            +)
            +
            +
            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. +

            + +

            Side Effects None +

            + +

            See Also gatherInfo + + +
            Defined in cuddApprox.c + +
            +
            +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
            +)
            +
            +
            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. +

            + +

            Side Effects None +

            + +

            See Also cuddUnderApprox +gatherInfoAux + + +
            Defined in cuddApprox.c + +
            +
            +static int 
            +gcd(
            +  int  x, 
            +  int  y 
            +)
            +
            +
            Returns the gcd of two integers. Uses the binary GCD + algorithm described in Cormen, Leiserson, and Rivest. +

            + +

            Side Effects None +

            + +

            Defined in cuddExact.c + +
            +
            +static DdNode * 
            +getCube(
            +  DdManager * manager, 
            +  st_table * visited, 
            +  DdNode * f, 
            +  int  cost 
            +)
            +
            +
            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. +

            + +

            Side Effects None +

            + +

            Defined in cuddSat.c + +
            +
            +static cuddPathPair 
            +getLargest(
            +  DdNode * root, 
            +  st_table * visited 
            +)
            +
            +
            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. +

            + +

            Side Effects none +

            + +

            Defined in cuddSat.c + +
            +
            +static int 
            +getLevelKeys(
            +  DdManager * table, 
            +  int  l 
            +)
            +
            +
            Returns the number of nodes at one level of a unique table. + The projection function, if isolated, is not counted. +

            + +

            Side Effects None +

            + +

            Defined in cuddExact.c + +
            +
            +static DdHalfWord ** 
            +getMatrix(
            +  int  rows, number of rows
            +  int  cols number of columns
            +)
            +
            +
            Allocates a two-dimensional matrix of ints. + Returns the pointer to the matrix if successful; NULL otherwise. +

            + +

            Side Effects None +

            + +

            See Also freeMatrix + + +
            Defined in cuddExact.c + +
            +
            +static int 
            +getMaxBinomial(
            +  int  n 
            +)
            +
            +
            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 +
            +    binomial(n,k) = n/k * binomial(n-1,k-1).
            +  
            + Returns the computed value if successful; -1 if out of range. +

            + +

            Side Effects None +

            + +

            Defined in cuddExact.c + +
            +
            +static DdNode * 
            +getPath(
            +  DdManager * manager, 
            +  st_table * visited, 
            +  DdNode * f, 
            +  int * weight, 
            +  int  cost 
            +)
            +
            +
            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. +

            + +

            Side Effects None +

            + +

            Defined in cuddSat.c + +
            +
            +static cuddPathPair 
            +getShortest(
            +  DdNode * root, 
            +  int * cost, 
            +  int * support, 
            +  st_table * visited 
            +)
            +
            +
            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. +

            + +

            Side Effects Accumulates the support of the DD in support. +

            + +

            Defined in cuddSat.c + +
            +
            +static void 
            +hashDelete(
            +  DdLevelQueue * queue, 
            +  DdQueueItem * item 
            +)
            +
            +
            Removes an item from the hash table of a level queue. + Nothing is done if the item is not in the table. +

            + +

            Side Effects None +

            + +

            See Also cuddLevelQueueDequeue +hashInsert + + +
            Defined in cuddLevelQ.c + +
            +
            +static int 
            +hashInsert(
            +  DdLevelQueue * queue, 
            +  DdQueueItem * item 
            +)
            +
            +
            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. +

            + +

            Side Effects None +

            + +

            See Also cuddLevelQueueEnqueue + + +
            Defined in cuddLevelQ.c + +
            +
            +static DdQueueItem * 
            +hashLookup(
            +  DdLevelQueue * queue, 
            +  void * key 
            +)
            +
            +
            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. +

            + +

            Side Effects None +

            + +

            See Also cuddLevelQueueEnqueue +hashInsert + + +
            Defined in cuddLevelQ.c + +
            +
            +static int 
            +hashResize(
            +  DdLevelQueue * queue 
            +)
            +
            +
            Resizes the hash table of a level queue. Returns 1 if + successful; 0 otherwise. +

            + +

            Side Effects None +

            + +

            See Also hashInsert + + +
            Defined in cuddLevelQ.c + +
            +
            +static int 
            +impliedp(
            +  DdHalfWord  var1, 
            +  short  phase1, 
            +  DdHalfWord  var2, 
            +  short  phase2, 
            +  BitVector * olv, 
            +  BitVector * olp 
            +)
            +
            +
            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. +

            + +

            Side Effects None +

            + +

            Defined in cuddEssent.c + +
            +
            +static DdHalfWord * 
            +initSymmInfo(
            +  DdManager * table, 
            +  int  lower, 
            +  int  upper 
            +)
            +
            +
            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. +

            + +

            Side Effects None +

            + +

            See Also checkSymmInfo + + +
            Defined in cuddExact.c + +
            +
            +static int 
            +largest(
            +    
            +)
            +
            +
            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 +

            + +

            Side Effects None +

            + +

            Defined in cuddGenetic.c + +
            +
            +static int 
            +make_random(
            +  DdManager * table, 
            +  int  lower 
            +)
            +
            +
            Generates the random sequences for the initial population. + The sequences are permutations of the indices between lower and + upper in the current order. +

            + +

            Side Effects None +

            + +

            Defined in cuddGenetic.c + +
            +
            +static DdNode * 
            +mintermsFromUniverse(
            +  DdManager * manager, 
            +  DdNode ** vars, 
            +  int  numVars, 
            +  double  n, 
            +  int  index 
            +)
            +
            +
            Recursive procedure to extract n mintems from constant 1. +

            + +

            Side Effects None +

            + +

            Defined in cuddSplit.c + +
            +
            +static int 
            +oneliteralp(
            +  DdHalfWord  var 
            +)
            +
            +
            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. +

            + +

            Side Effects None +

            + +

            Defined in cuddEssent.c + +
            +
            +static void 
            +pushDown(
            +  DdHalfWord * order, 
            +  int  j, 
            +  int  level 
            +)
            +
            +
            Pushes a variable in the order down to position "level." +

            + +

            Side Effects None +

            + +

            Defined in cuddExact.c + +
            +
            +static int 
            +rand_int(
            +  int  a 
            +)
            +
            +
            Generates a random number between 0 and the integer a. +

            + +

            Side Effects None +

            + +

            Defined in cuddGenetic.c + +
            +
            +static double 
            +random_generator(
            +    
            +)
            +
            +
            Returns a double precision value between 0.0 and 1.0. +

            + +

            Side Effects None +

            + +

            Defined in cuddAnneal.c + +
            +
            +static int 
            +restoreOrder(
            +  DdManager * table, 
            +  int * array, 
            +  int  lower, 
            +  int  upper 
            +)
            +
            +
            Restores the variable order in array by a series of sifts up. + Returns 1 in case of success; 0 otherwise. +

            + +

            Side Effects None +

            + +

            Defined in cuddAnneal.c + +
            +
            +static int 
            +roulette(
            +  int * p1, 
            +  int * p2 
            +)
            +
            +
            Selects two distinct parents with the roulette wheel method. +

            + +

            Side Effects The indices of the selected parents are returned as side + effects. +

            + +

            Defined in cuddGenetic.c + +
            +
            +static DdNode * 
            +selectMintermsFromUniverse(
            +  DdManager * manager, 
            +  int * varSeen, 
            +  double  n 
            +)
            +
            +
            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). +

            + +

            Side Effects None +

            + +

            Defined in cuddSplit.c + +
            +
            +static int 
            +sentinelp(
            +  DdHalfWord  var1, 
            +  DdHalfWord  var2 
            +)
            +
            +
            Returns true iff the argument is the sentinel clause. + A sentinel clause has both variables equal to 0. +

            + +

            Side Effects None +

            + +

            Defined in cuddEssent.c + +
            +
            +static DdNode * 
            +separateCube(
            +  DdManager * dd, 
            +  DdNode * f, 
            +  CUDD_VALUE_TYPE * distance 
            +)
            +
            +
            Separates cube from distance. Returns the cube if + successful; NULL otherwise. +

            + +

            Side Effects The distance is returned as a side effect. +

            + +

            See Also cuddBddClosestCube +createResult + + +
            Defined in cuddPriority.c + +
            +
            +static int 
            +siftBackwardProb(
            +  DdManager * table, 
            +  Move * moves, 
            +  int  size, 
            +  double  temp 
            +)
            +
            +
            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. +

            + +

            Side Effects None +

            + +

            Defined in cuddAnneal.c + +
            +
            +static int 
            +sift_up(
            +  DdManager * table, 
            +  int  x, 
            +  int  x_low 
            +)
            +
            +
            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 +

            + +

            Side Effects None +

            + +

            Defined in cuddGenetic.c + +
            +
            +static enum st_retval 
            +stPathTableDdFree(
            +  char * key, 
            +  char * value, 
            +  char * arg 
            +)
            +
            +
            None +

            + +

            Side Effects None +

            + +

            Defined in cuddSubsetSP.c + +
            +
            +static enum st_retval 
            +st_zdd_count_dbl_free(
            +  char * key, 
            +  char * value, 
            +  char * arg 
            +)
            +
            +
            Frees the memory associated with the computed table of + Cudd_zddCountDouble. +

            + +

            Side Effects None +

            + +

            Defined in cuddZddCount.c + +
            +
            +static enum st_retval 
            +st_zdd_countfree(
            +  char * key, 
            +  char * value, 
            +  char * arg 
            +)
            +
            +
            Frees the memory associated with the computed table of + Cudd_zddCount. +

            + +

            Side Effects None +

            + +

            Defined in cuddZddCount.c + +
            +
            +static int 
            +stopping_criterion(
            +  int  c1, 
            +  int  c2, 
            +  int  c3, 
            +  int  c4, 
            +  double  temp 
            +)
            +
            +
            If temperature is STOP_TEMP or there is no improvement + then terminates. Returns 1 if the termination criterion is met; 0 + otherwise. +

            + +

            Side Effects None +

            + +

            Defined in cuddAnneal.c + +
            +
            +static DdTlcInfo * 
            +tlcInfoAlloc(
            +    
            +)
            +
            +
            Returns a pointer to a DdTlcInfo Structure if successful; + NULL otherwise. +

            + +

            Side Effects None +

            + +

            See Also Cudd_tlcInfoFree + + +
            Defined in cuddEssent.c + +
            +
            +static int 
            +updateEntry(
            +  DdManager * table, 
            +  DdHalfWord * order, 
            +  int  level, 
            +  int  cost, 
            +  DdHalfWord ** orders, 
            +  int * costs, 
            +  int  subsets, 
            +  char * mask, 
            +  int  lower, 
            +  int  upper 
            +)
            +
            +
            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. +

            + +

            Side Effects None +

            + +

            Defined in cuddExact.c + +
            +
            +static void 
            +updateParity(
            +  DdNode * node, function to analyze
            +  ApproxInfo * info, info on BDD
            +  int  newparity new parity for node
            +)
            +
            +
            Recursively update the parity of the paths reaching a node. + Assumes that node is regular and propagates the invariant. +

            + +

            Side Effects None +

            + +

            See Also gatherInfoAux + + +
            Defined in cuddApprox.c + +
            +
            +static int 
            +updateRefs(
            +  DdManager * dd, 
            +  DdNode * f, 
            +  DdNode * skip, 
            +  ApproxInfo * info, 
            +  DdLevelQueue * queue 
            +)
            +
            +
            Update function reference counts to account for replacement. + Returns the number of nodes saved if successful; 0 otherwise. +

            + +

            Side Effects None +

            + +

            See Also UAmarkNodes +RAmarkNodes + + +
            Defined in cuddApprox.c + +
            +
            +static int 
            +updateUB(
            +  DdManager * table, 
            +  int  oldBound, 
            +  DdHalfWord * bestOrder, 
            +  int  lower, 
            +  int  upper 
            +)
            +
            +
            Updates the upper bound and saves the best order seen so far. + Returns the current value of the upper bound. +

            + +

            Side Effects None +

            + +

            Defined in cuddExact.c + +
            +
            +static int 
            +zddCountInternalMtrNodes(
            +  DdManager * table, 
            +  MtrNode * treenode 
            +)
            +
            +
            Counts the number of internal nodes of the group tree. + Returns the count. +

            + +

            Side Effects None +

            + +

            Defined in cuddZddGroup.c + +
            +
            +static void 
            +zddFindNodeHiLo(
            +  DdManager * table, 
            +  MtrNode * treenode, 
            +  int * lower, 
            +  int * upper 
            +)
            +
            +
            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. +

            + +

            Side Effects The bounds are returned as side effects. +

            + +

            Defined in cuddZddGroup.c + +
            +
            +static void 
            +zddFixTree(
            +  DdManager * table, 
            +  MtrNode * treenode 
            +)
            +
            +
            Fixes the ZDD variable group tree after a + shuffle. Assumes that the order of the variables in a terminal node + has not been changed. +

            + +

            Side Effects Changes the ZDD variable group tree. +

            + +

            Defined in cuddZddReord.c + +
            +
            +static int 
            +zddGroupMoveBackward(
            +  DdManager * table, 
            +  int  x, 
            +  int  y 
            +)
            +
            +
            Undoes the swap two groups. Returns 1 in case of + success; 0 otherwise. +

            + +

            Side Effects None +

            + +

            Defined in cuddZddGroup.c + +
            +
            +static int 
            +zddGroupMove(
            +  DdManager * table, 
            +  int  x, 
            +  int  y, 
            +  Move ** moves 
            +)
            +
            +
            Swaps two groups and records the move. Returns the + number of keys in the DD table in case of success; 0 otherwise. +

            + +

            Side Effects None +

            + +

            Defined in cuddZddGroup.c + +
            +
            +static int 
            +zddGroupSiftingAux(
            +  DdManager * table, 
            +  int  x, 
            +  int  xLow, 
            +  int  xHigh 
            +)
            +
            +
            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. +

            + +

            Side Effects None +

            + +

            Defined in cuddZddGroup.c + +
            +
            +static int 
            +zddGroupSiftingBackward(
            +  DdManager * table, 
            +  Move * moves, 
            +  int  size 
            +)
            +
            +
            Determines the best position for a variables and returns + it there. Returns 1 in case of success; 0 otherwise. +

            + +

            Side Effects None +

            + +

            Defined in cuddZddGroup.c + +
            +
            +static int 
            +zddGroupSiftingDown(
            +  DdManager * table, 
            +  int  x, 
            +  int  xHigh, 
            +  Move ** moves 
            +)
            +
            +
            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. +

            + +

            Side Effects None +

            + +

            Defined in cuddZddGroup.c + +
            +
            +static int 
            +zddGroupSiftingUp(
            +  DdManager * table, 
            +  int  y, 
            +  int  xLow, 
            +  Move ** moves 
            +)
            +
            +
            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. +

            + +

            Side Effects None +

            + +

            Defined in cuddZddGroup.c + +
            +
            +static int 
            +zddGroupSifting(
            +  DdManager * table, 
            +  int  lower, 
            +  int  upper 
            +)
            +
            +
            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. +

            + +

            Side Effects None +

            + +

            Defined in cuddZddGroup.c + +
            +
            +static void 
            +zddMergeGroups(
            +  DdManager * table, 
            +  MtrNode * treenode, 
            +  int  low, 
            +  int  high 
            +)
            +
            +
            Creates a single group from low to high and adjusts the + idex field of the tree node. +

            + +

            Side Effects None +

            + +

            Defined in cuddZddGroup.c + +
            +
            +static DdNode * 
            +zddPortFromBddStep(
            +  DdManager * dd, 
            +  DdNode * B, 
            +  int  expected 
            +)
            +
            +
            Performs the recursive step of Cudd_zddPortFromBdd. +

            + +

            Side Effects None +

            + +

            Defined in cuddZddPort.c + +
            +
            +static DdNode * 
            +zddPortToBddStep(
            +  DdManager * dd, manager
            +  DdNode * f, ZDD to be converted
            +  int  depth recursion depth
            +)
            +
            +
            Performs the recursive step of Cudd_zddPortToBdd. +

            + +

            Side Effects None +

            + +

            Defined in cuddZddPort.c + +
            +
            +static void 
            +zddPrintCoverAux(
            +  DdManager * zdd, manager
            +  DdNode * node, current node
            +  int  level, depth in the recursion
            +  int * list current recursion path
            +)
            +
            +
            Performs the recursive step of Cudd_zddPrintCover. +

            + +

            Side Effects None +

            + +

            Defined in cuddZddUtil.c + +
            +
            +static int 
            +zddReorderChildren(
            +  DdManager * table, 
            +  MtrNode * treenode, 
            +  Cudd_ReorderingType  method 
            +)
            +
            +
            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. +

            + +

            Side Effects None +

            + +

            Defined in cuddZddGroup.c + +
            +
            +static int 
            +zddReorderPostprocess(
            +  DdManager * table 
            +)
            +
            +
            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. +

            + +

            Side Effects None +

            + +

            Defined in cuddZddReord.c + +
            +
            +static void 
            +zddReorderPreprocess(
            +  DdManager * table 
            +)
            +
            +
            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. +

            + +

            Side Effects None +

            + +

            Defined in cuddZddReord.c + +
            +
            +static int 
            +zddShuffle(
            +  DdManager * table, 
            +  int * permutation 
            +)
            +
            +
            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. +

            + +

            Side Effects None +

            + +

            Defined in cuddZddReord.c + +
            +
            +static int 
            +zddSiftUp(
            +  DdManager * table, 
            +  int  x, 
            +  int  xLow 
            +)
            +
            +
            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 +

            + +

            Side Effects None +

            + +

            Defined in cuddZddReord.c + +
            +
            +static Move * 
            +zddSwapAny(
            +  DdManager * table, 
            +  int  x, 
            +  int  y 
            +)
            +
            +
            Swaps any two variables. Returns the set of moves. +

            + +

            Side Effects None +

            + +

            Defined in cuddZddReord.c + +
            +
            +static int 
            +zddTreeSiftingAux(
            +  DdManager * table, 
            +  MtrNode * treenode, 
            +  Cudd_ReorderingType  method 
            +)
            +
            +
            Recursively visits the group tree and reorders each + group in postorder fashion. Returns 1 if successful; 0 otherwise. +

            + +

            Side Effects None +

            + +

            Defined in cuddZddGroup.c + +
            +
            +static int 
            +zddUniqueCompareGroup(
            +  int * ptrX, 
            +  int * ptrY 
            +)
            +
            +
            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. +

            + +

            Side Effects None +

            + +

            Defined in cuddZddGroup.c + +
            +
            +static void 
            +zddVarToConst(
            +  DdNode * f, 
            +  DdNode ** gp, 
            +  DdNode ** hp, 
            +  DdNode * base, 
            +  DdNode * empty 
            +)
            +
            +
            Replaces variables with constants if possible (part of + canonical form). +

            + +

            Side Effects None +

            + +

            Defined in cuddZddSetop.c + +
            +
            +static int 
            +zdd_group_move_backward(
            +  DdManager * table, 
            +  int  x, 
            +  int  y 
            +)
            +
            +
            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. +

            + +

            Side Effects None +

            + +

            Defined in cuddZddSymm.c + +
            +
            +static int 
            +zdd_group_move(
            +  DdManager * table, 
            +  int  x, 
            +  int  y, 
            +  Move ** moves 
            +)
            +
            +
            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. +

            + +

            Side Effects None +

            + +

            Defined in cuddZddSymm.c + +
            +
            +static void 
            +zdd_print_minterm_aux(
            +  DdManager * zdd, manager
            +  DdNode * node, current node
            +  int  level, depth in the recursion
            +  int * list current recursion path
            +)
            +
            +
            Performs the recursive step of Cudd_zddPrintMinterm. +

            + +

            Side Effects None +

            + +

            Defined in cuddZddUtil.c + +
            +
            +static DdNode * 
            +zdd_subset0_aux(
            +  DdManager * zdd, 
            +  DdNode * P, 
            +  DdNode * zvar 
            +)
            +
            +
            Performs the recursive step of Cudd_zddSubset0. +

            + +

            Side Effects None +

            + +

            Defined in cuddZddSetop.c + +
            +
            +static DdNode * 
            +zdd_subset1_aux(
            +  DdManager * zdd, 
            +  DdNode * P, 
            +  DdNode * zvar 
            +)
            +
            +
            Performs the recursive step of Cudd_zddSubset1. +

            + +

            Side Effects None +

            + +

            Defined in cuddZddSetop.c + +
            +
            +static int 
            +zp2(
            +  DdManager * zdd, 
            +  DdNode * f, 
            +  st_table * t 
            +)
            +
            +
            Performs the recursive step of cuddZddP. Returns 1 in + case of success; 0 otherwise. +

            + +

            Side Effects None +

            + +

            Defined in cuddZddUtil.c + +
            +
            + 
            +(
            +    
            +)
            +
            +
            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. +

            + +

            Side Effects None +

            + +

            See Also cuddAllocNode +cuddDynamicAllocNode +cuddDeallocMove + + +
            Defined in cuddInt.h + +
            +
            + 
            +(
            +    
            +)
            +
            +
            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. +

            + +

            Side Effects None +

            + +

            See Also cuddDeallocNode +cuddDynamicAllocNode + + +
            Defined in cuddInt.h + +
            +
            + 
            +(
            +    
            +)
            +
            +
            Clears the 4 least significant bits of a pointer. +

            + +

            Side Effects none +

            + +

            Defined in cuddInt.h + +
            +
            + 
            +(
            +    
            +)
            +
            +
            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". +

            + +

            Side Effects none +

            + +

            See Also Cudd_Not + + +
            Defined in cudd.h + +
            +
            + 
            +(
            +    
            +)
            +
            +
            Complements a DD by flipping the complement attribute of + the pointer (the least significant bit). +

            + +

            Side Effects none +

            + +

            See Also Cudd_NotCond + + +
            Defined in cudd.h + +
            +
            + 
            +(
            +    
            +)
            +
            +
            Computes hash function for keys of three operands. +

            + +

            Side Effects None +

            + +

            See Also ddLCHash2 +ddLCHash + + +
            Defined in cuddLCache.c + +
            +
            + 
            +(
            +    
            +)
            +
            +
            Computes hash function for keys of two operands. +

            + +

            Side Effects None +

            + +

            See Also ddLCHash3 +ddLCHash + + +
            Defined in cuddLCache.c + +
            +
            + 
            +(
            +    
            +)
            +
            +
            Computes the absolute value of a number. +

            + +

            Side Effects none +

            + +

            Defined in cuddInt.h + +
            +
            + 
            +(
            +    
            +)
            +
            +
            Computes the maximum of two numbers. +

            + +

            Side Effects none +

            + +

            See Also ddMin + + +
            Defined in cuddInt.h + +
            +
            + 
            +(
            +    
            +)
            +
            +
            Computes the minimum of two numbers. +

            + +

            Side Effects none +

            + +

            See Also ddMax + + +
            Defined in cuddInt.h + +
            +
            + 
            +(
            +    
            +)
            +
            +
            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()). +

            + +

            Side Effects none +

            + +

            See Also Cudd_Deref + + +
            Defined in cuddInt.h + +
            +
            + 
            +(
            +    
            +)
            +
            +
            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. +

            + +

            Side Effects none +

            + +

            Defined in cuddInt.h + +
            +
            + 
            +(
            +    
            +)
            +
            +
            Extract the least significant digit of a double digit. Used + in the manipulation of arbitrary precision integers. +

            + +

            Side Effects None +

            + +

            See Also DD_MSDIGIT + + +
            Defined in cuddInt.h + +
            +
            + 
            +(
            +    
            +)
            +
            +
            Extract the most significant digit of a double digit. Used + in the manipulation of arbitrary precision integers. +

            + +

            Side Effects None +

            + +

            See Also DD_LSDIGIT + + +
            Defined in cuddInt.h + +
            +
            + 
            +(
            +    
            +)
            +
            +
            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. +

            + +

            Side Effects none +

            + +

            See Also Cudd_ReadPermZdd + + +
            Defined in cuddInt.h + +
            +
            + 
            +(
            +    
            +)
            +
            +
            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. +

            + +

            Side Effects none +

            + +

            See Also Cudd_ReadPerm + + +
            Defined in cuddInt.h + +
            +
            + 
            +(
            +    
            +)
            +
            +
            Hash function for the cache for functions with two + operands. +

            + +

            Side Effects none +

            + +

            See Also ddHash +ddCHash + + +
            Defined in cuddInt.h + +
            +
            + 
            +(
            +    
            +)
            +
            +
            Hash function for the cache. +

            + +

            Side Effects none +

            + +

            See Also ddHash +ddCHash2 + + +
            Defined in cuddInt.h + +
            +
            + 
            +(
            +    
            +)
            +
            +
            Hash function for the table of a level queue. +

            + +

            Side Effects None +

            + +

            See Also hashInsert +hashLookup +hashDelete + + +
            Defined in cuddLevelQ.c + +
            +
            + 
            +(
            +    
            +)
            +
            +
            Hash function for the unique table. +

            + +

            Side Effects none +

            + +

            See Also ddCHash +ddCHash2 + + +
            Defined in cuddInt.h + +
            +
            + 
            +(
            +    
            +)
            +
            +
            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()). +

            + +

            Side Effects none +

            + +

            See Also Cudd_Ref + + +
            Defined in cuddInt.h + +
            +
            + 
            +(
            +    
            +)
            +
            +
            Iterates over the cubes of a decision diagram f. +
              +
            • DdManager *manager; +
            • DdNode *f; +
            • DdGen *gen; +
            • int *cube; +
            • CUDD_VALUE_TYPE value; +
            + 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.

            + 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. +

            + +

            Side Effects none +

            + +

            See Also Cudd_ForeachNode +Cudd_FirstCube +Cudd_NextCube +Cudd_GenFree +Cudd_IsGenEmpty +Cudd_AutodynDisable + + +
            Defined in cudd.h + +
            +
            + 
            +(
            +    
            +)
            +
            +
            Iterates over the nodes of a decision diagram f. +
              +
            • DdManager *manager; +
            • DdNode *f; +
            • DdGen *gen; +
            • DdNode *node; +
            + 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.

            + 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. +

            + +

            Side Effects none +

            + +

            See Also Cudd_ForeachCube +Cudd_FirstNode +Cudd_NextNode +Cudd_GenFree +Cudd_IsGenEmpty +Cudd_AutodynDisable + + +
            Defined in cudd.h + +
            +
            + 
            +(
            +    
            +)
            +
            +
            Iterates over the paths of a ZDD f. +
              +
            • DdManager *manager; +
            • DdNode *f; +
            • DdGen *gen; +
            • int *path; +
            + 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.

            + 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. +

            + +

            Side Effects none +

            + +

            See Also Cudd_zddFirstPath +Cudd_zddNextPath +Cudd_GenFree +Cudd_IsGenEmpty +Cudd_AutodynDisable + + +
            Defined in cudd.h + +
            +
            + 
            +(
            +    
            +)
            +
            +
            Iterates over the primes of a Boolean function producing + a prime and irredundant cover. +
              +
            • DdManager *manager; +
            • DdNode *l; +
            • DdNode *u; +
            • DdGen *gen; +
            • int *cube; +
            + 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.

            + CAUTION: It is a mistake to change a diagram on which generation is ongoing. +

            + +

            Side Effects none +

            + +

            See Also Cudd_ForeachCube +Cudd_FirstPrime +Cudd_NextPrime +Cudd_GenFree +Cudd_IsGenEmpty + + +
            Defined in cudd.h + +
            +
            + 
            +(
            +    
            +)
            +
            +
            Outputs a line of stats if DD_COUNT and DD_STATS are + defined. Increments the number of recursive calls if DD_COUNT is + defined. +

            + +

            Side Effects None +

            + +

            Defined in cuddInt.h + +
            +
            + 
            +(
            +    
            +)
            +
            +
            Returns 1 if a pointer is complemented. +

            + +

            Side Effects none +

            + +

            See Also Cudd_Regular +Cudd_Complement + + +
            Defined in cudd.h + +
            +
            + 
            +(
            +    
            +)
            +
            +
            Returns 1 if the absolute value of the difference of the two + arguments x and y is less than e. +

            + +

            Side Effects none +

            + +

            Defined in cuddInt.h + +
            +
            + 
            +(
            +    
            +)
            +
            +
            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. +

            + +

            Side Effects none +

            + +

            Defined in cudd.h + +
            +
            + 
            +(
            +    
            +)
            +
            +
            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. +

            + +

            Side Effects none +

            + +

            See Also Cudd_IsConstant + + +
            Defined in cuddInt.h + +
            +
            + 
            +(
            +    
            +)
            +
            +
            Returns the arithmetic 0 constant node. This is different + from the logical zero. The latter is obtained by + Cudd_Not(DD_ONE(dd)). +

            + +

            Side Effects none +

            + +

            See Also DD_ONE +Cudd_Not +DD_PLUS_INFINITY +DD_MINUS_INFINITY + + +
            Defined in cuddInt.h + +
            +
            + 
            +(
            +    
            +)
            +
            +
            Returns the complemented version of a pointer. +

            + +

            Side Effects none +

            + +

            See Also Cudd_Regular +Cudd_IsComplement + + +
            Defined in cudd.h + +
            +
            + 
            +(
            +    
            +)
            +
            +
            Returns the constant 1 node. +

            + +

            Side Effects none +

            + +

            See Also DD_ZERO +DD_PLUS_INFINITY +DD_MINUS_INFINITY + + +
            Defined in cuddInt.h + +
            +
            + 
            +(
            +    
            +)
            +
            +
            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. +

            + +

            Side Effects none +

            + +

            See Also Cudd_ReadPerm + + +
            Defined in cudd.h + +
            +
            + 
            +(
            +    
            +)
            +
            +
            Returns the else child of an internal node. If + node is a constant node, the result is unpredictable. + The pointer passed to cuddE must be regular. +

            + +

            Side Effects none +

            + +

            See Also Cudd_E + + +
            Defined in cuddInt.h + +
            +
            + 
            +(
            +    
            +)
            +
            +
            Returns the else child of an internal node. If + node is a constant node, the result is unpredictable. +

            + +

            Side Effects none +

            + +

            See Also Cudd_T +Cudd_V + + +
            Defined in cudd.h + +
            +
            + 
            +(
            +    
            +)
            +
            +
            Returns the minus infinity constant node. +

            + +

            Side Effects none +

            + +

            See Also DD_ONE +DD_ZERO +DD_PLUS_INFINITY + + +
            Defined in cuddInt.h + +
            +
            + 
            +(
            +    
            +)
            +
            +
            Returns the plus infinity constant node. +

            + +

            Side Effects none +

            + +

            See Also DD_ONE +DD_ZERO +DD_MINUS_INFINITY + + +
            Defined in cuddInt.h + +
            +
            + 
            +(
            +    
            +)
            +
            +
            Returns the regular version of a pointer. +

            + +

            Side Effects none +

            + +

            See Also Cudd_Complement +Cudd_IsComplement + + +
            Defined in cudd.h + +
            +
            + 
            +(
            +    
            +)
            +
            +
            Returns the then child of an internal node. If + node is a constant node, the result is unpredictable. + The pointer passed to cuddT must be regular. +

            + +

            Side Effects none +

            + +

            See Also Cudd_T + + +
            Defined in cuddInt.h + +
            +
            + 
            +(
            +    
            +)
            +
            +
            Returns the then child of an internal node. If + node is a constant node, the result is unpredictable. +

            + +

            Side Effects none +

            + +

            See Also Cudd_E +Cudd_V + + +
            Defined in cudd.h + +
            +
            + 
            +(
            +    
            +)
            +
            +
            Returns the value of a constant node. If + node is an internal node, the result is unpredictable. + The pointer passed to cuddV must be regular. +

            + +

            Side Effects none +

            + +

            See Also Cudd_V + + +
            Defined in cuddInt.h + +
            +
            + 
            +(
            +    
            +)
            +
            +
            Returns the value of a constant node. If + node is an internal node, the result is unpredictable. +

            + +

            Side Effects none +

            + +

            See Also Cudd_T +Cudd_E + + +
            Defined in cudd.h + +
            +
            + 
            +(
            +    
            +)
            +
            +
            Saturating decrement operator. +

            + +

            Side Effects none +

            + +

            See Also cuddSatInc + + +
            Defined in cuddInt.h + +
            +
            + 
            +(
            +    
            +)
            +
            +
            Saturating increment operator. +

            + +

            Side Effects none +

            + +

            See Also cuddSatDec + + +
            Defined in cuddInt.h + + +
        +
        +Last updated on 20090220 23h06 + diff --git a/distr/cudd/doc/cuddAllFile.html b/distr/cudd/doc/cuddAllFile.html new file mode 100644 index 0000000..89073dd --- /dev/null +++ b/distr/cudd/doc/cuddAllFile.html @@ -0,0 +1,4707 @@ + +The cudd package: files + + +
        +
        cuddAddAbs.c +
        Quantification functions for ADDs. +
        cuddAddApply.c +
        Apply functions for ADDs and their operators. +
        cuddAddFind.c +
        Functions to find maximum and minimum in an ADD and to + extract the i-th bit. +
        cuddAddInv.c +
        Function to compute the scalar inverse of an ADD. +
        cuddAddIte.c +
        ADD ITE function and satellites. +
        cuddAddNeg.c +
        Function to compute the negation of an ADD. +
        cuddAddWalsh.c +
        Functions that generate Walsh matrices and residue + functions in ADD form. +
        cuddAndAbs.c +
        Combined AND and existential abstraction for BDDs +
        cuddAnneal.c +
        Reordering of DDs based on simulated annealing +
        cuddApa.c +
        Arbitrary precision arithmetic functions. +
        cuddAPI.c +
        Application interface functions. +
        cuddApprox.c +
        Procedures to approximate a given BDD. +
        cuddBddAbs.c +
        Quantification functions for BDDs. +
        cuddBddCorr.c +
        Correlation between BDDs. +
        cuddBddIte.c +
        BDD ITE function and satellites. +
        cuddBridge.c +
        Translation from BDD to ADD and vice versa and transfer between + different managers. +
        cuddCache.c +
        Functions for cache insertion and lookup. +
        cuddCheck.c +
        Functions to check consistency of data structures. +
        cuddClip.c +
        Clipping functions. +
        cuddCof.c +
        Cofactoring functions. +
        cuddCompose.c +
        Functional composition and variable permutation of DDs. +
        cuddDecomp.c +
        Functions for BDD decomposition. +
        cuddEssent.c +
        Functions for the detection of essential variables. +
        cuddExact.c +
        Functions for exact variable reordering. +
        cuddExport.c +
        Export functions. +
        cuddGenCof.c +
        Generalized cofactors for BDDs and ADDs. +
        cuddGenetic.c +
        Genetic algorithm for variable reordering. +
        cuddGroup.c +
        Functions for group sifting. +
        cuddHarwell.c +
        Function to read a matrix in Harwell format. +
        cuddInit.c +
        Functions to initialize and shut down the DD manager. +
        cuddInteract.c +
        Functions to manipulate the variable interaction matrix. +
        cuddLCache.c +
        Functions for local caches. +
        cuddLevelQ.c +
        Procedure to manage level queues. +
        cuddLinear.c +
        Functions for DD reduction by linear transformations. +
        cuddLiteral.c +
        Functions for manipulation of literal sets represented by + BDDs. +
        cuddMatMult.c +
        Matrix multiplication functions. +
        cuddPriority.c +
        Priority functions. +
        cuddRead.c +
        Functions to read in a matrix +
        cuddRef.c +
        Functions that manipulate the reference counts. +
        cuddReorder.c +
        Functions for dynamic variable reordering. +
        cuddSat.c +
        Functions for the solution of satisfiability related + problems. +
        cuddSign.c +
        Computation of signatures. +
        cuddSolve.c +
        Boolean equation solver and related functions. +
        cuddSplit.c +
        Returns a subset of minterms from a boolean function. +
        cuddSubsetHB.c +
        Procedure to subset the given BDD by choosing the heavier + branches. +
        cuddSubsetSP.c +
        Procedure to subset the given BDD choosing the shortest paths + (largest cubes) in the BDD. +
        cuddSymmetry.c +
        Functions for symmetry-based variable reordering. +
        cuddTable.c +
        Unique table management functions. +
        cuddUtil.c +
        Utility functions. +
        cuddWindow.c +
        Functions for variable reordering by window permutation. +
        cuddZddCount.c +
        Procedures to count the number of minterms of a ZDD. +
        cuddZddFuncs.c +
        Functions to manipulate covers represented as ZDDs. +
        cuddZddGroup.c +
        Functions for ZDD group sifting. +
        cuddZddIsop.c +
        Functions to find irredundant SOP covers as ZDDs from BDDs. +
        cuddZddLin.c +
        Procedures for dynamic variable ordering of ZDDs. +
        cuddZddMisc.c +
        Miscellaneous utility functions for ZDDs. +
        cuddZddPort.c +
        Functions that translate BDDs to ZDDs. +
        cuddZddReord.c +
        Procedures for dynamic variable ordering of ZDDs. +
        cuddZddSetop.c +
        Set operations on ZDDs. +
        cuddZddSymm.c +
        Functions for symmetry-based ZDD variable reordering. +
        cuddZddUtil.c +
        Utility functions for ZDDs. +

        +

        cuddAddAbs.c

        +Quantification functions for ADDs.

        +By: Fabio Somenzi

        +External procedures included in this module: +

          +
        • Cudd_addExistAbstract() +
        • Cudd_addUnivAbstract() +
        • Cudd_addOrAbstract() +
        + Internal procedures included in this module: +
          +
        • cuddAddExistAbstractRecur() +
        • cuddAddUnivAbstractRecur() +
        • cuddAddOrAbstractRecur() +
        + Static procedures included in this module: +
          +
        • addCheckPositiveCube() +

        +

        +
        Cudd_addExistAbstract() +
        Existentially Abstracts all the variables in cube from f. + +
        Cudd_addUnivAbstract() +
        Universally Abstracts all the variables in cube from f. + +
        Cudd_addOrAbstract() +
        Disjunctively abstracts all the variables in cube from the + 0-1 ADD f. + +
        cuddAddExistAbstractRecur() +
        Performs the recursive step of Cudd_addExistAbstract. + +
        cuddAddUnivAbstractRecur() +
        Performs the recursive step of Cudd_addUnivAbstract. + +
        cuddAddOrAbstractRecur() +
        Performs the recursive step of Cudd_addOrAbstract. + +
        addCheckPositiveCube() +
        Checks whether cube is an ADD representing the product + of positive literals. + +
        +
        +

        cuddAddApply.c

        +Apply functions for ADDs and their operators.

        +By: Fabio Somenzi

        +External procedures included in this module: +

          +
        • Cudd_addApply() +
        • 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() +
        + Internal procedures included in this module: +
          +
        • cuddAddApplyRecur() +
        • cuddAddMonadicApplyRecur() +

        +

        +
        Cudd_addApply() +
        Applies op to the corresponding discriminants of f and g. + +
        Cudd_addPlus() +
        Integer and floating point addition. + +
        Cudd_addTimes() +
        Integer and floating point multiplication. + +
        Cudd_addThreshold() +
        f if f>=g; 0 if f<g. + +
        Cudd_addSetNZ() +
        This operator sets f to the value of g wherever g != 0. + +
        Cudd_addDivide() +
        Integer and floating point division. + +
        Cudd_addMinus() +
        Integer and floating point subtraction. + +
        Cudd_addMinimum() +
        Integer and floating point min. + +
        Cudd_addMaximum() +
        Integer and floating point max. + +
        Cudd_addOneZeroMaximum() +
        Returns 1 if f > g and 0 otherwise. + +
        Cudd_addDiff() +
        Returns plusinfinity if f=g; returns min(f,g) if f!=g. + +
        Cudd_addAgreement() +
        f if f==g; background if f!=g. + +
        Cudd_addOr() +
        Disjunction of two 0-1 ADDs. + +
        Cudd_addNand() +
        NAND of two 0-1 ADDs. + +
        Cudd_addNor() +
        NOR of two 0-1 ADDs. + +
        Cudd_addXor() +
        XOR of two 0-1 ADDs. + +
        Cudd_addXnor() +
        XNOR of two 0-1 ADDs. + +
        Cudd_addMonadicApply() +
        Applies op to the discriminants of f. + +
        Cudd_addLog() +
        Natural logarithm of an ADD. + +
        cuddAddApplyRecur() +
        Performs the recursive step of Cudd_addApply. + +
        cuddAddMonadicApplyRecur() +
        Performs the recursive step of Cudd_addMonadicApply. + +
        +
        +

        cuddAddFind.c

        +Functions to find maximum and minimum in an ADD and to + extract the i-th bit.

        +By: Fabio Somenzi

        +External procedures included in this module: +

          +
        • Cudd_addFindMax() +
        • Cudd_addFindMin() +
        • Cudd_addIthBit() +
        + Static functions included in this module: +
          +
        • addDoIthBit() +

        +

        +
        Cudd_addFindMax() +
        Finds the maximum discriminant of f. + +
        Cudd_addFindMin() +
        Finds the minimum discriminant of f. + +
        Cudd_addIthBit() +
        Extracts the i-th bit from an ADD. + +
        addDoIthBit() +
        Performs the recursive step for Cudd_addIthBit. + +
        +
        +

        cuddAddInv.c

        +Function to compute the scalar inverse of an ADD.

        +By: Fabio Somenzi

        +External procedures included in this module: +

          +
        • Cudd_addScalarInverse() +
        + Internal procedures included in this module: +
          +
        • cuddAddScalarInverseRecur() +

        +

        +
        Cudd_addScalarInverse() +
        Computes the scalar inverse of an ADD. + +
        cuddAddScalarInverseRecur() +
        Performs the recursive step of addScalarInverse. + +
        +
        +

        cuddAddIte.c

        +ADD ITE function and satellites.

        +By: Fabio Somenzi

        +External procedures included in this module: +

          +
        • Cudd_addIte() +
        • Cudd_addIteConstant() +
        • Cudd_addEvalConst() +
        • Cudd_addCmpl() +
        • Cudd_addLeq() +
        + Internal procedures included in this module: +
          +
        • cuddAddIteRecur() +
        • cuddAddCmplRecur() +
        + Static procedures included in this module: +
          +
        • addVarToConst() +

        +

        +
        Cudd_addIte() +
        Implements ITE(f,g,h). + +
        Cudd_addIteConstant() +
        Implements ITEconstant for ADDs. + +
        Cudd_addEvalConst() +
        Checks whether ADD g is constant whenever ADD f is 1. + +
        Cudd_addCmpl() +
        Computes the complement of an ADD a la C language. + +
        Cudd_addLeq() +
        Determines whether f is less than or equal to g. + +
        cuddAddIteRecur() +
        Implements the recursive step of Cudd_addIte(f,g,h). + +
        cuddAddCmplRecur() +
        Performs the recursive step of Cudd_addCmpl. + +
        addVarToConst() +
        Replaces variables with constants if possible (part of + canonical form). + +
        +
        +

        cuddAddNeg.c

        +Function to compute the negation of an ADD.

        +By: Fabio Somenzi, Balakrishna Kumthekar

        +External procedures included in this module: +

          +
        • Cudd_addNegate() +
        • Cudd_addRoundOff() +
        + Internal procedures included in this module: +
          +
        • cuddAddNegateRecur() +
        • cuddAddRoundOffRecur() +

        +

        +
        Cudd_addNegate() +
        Computes the additive inverse of an ADD. + +
        Cudd_addRoundOff() +
        Rounds off the discriminants of an ADD. + +
        cuddAddNegateRecur() +
        Implements the recursive step of Cudd_addNegate. + +
        cuddAddRoundOffRecur() +
        Implements the recursive step of Cudd_addRoundOff. + +
        +
        +

        cuddAddWalsh.c

        +Functions that generate Walsh matrices and residue + functions in ADD form.

        +By: Fabio Somenzi

        +External procedures included in this module: +

          +
        • Cudd_addWalsh() +
        • Cudd_addResidue() +
        + Static procedures included in this module: +
          +
        • addWalshInt() +

        +

        +
        Cudd_addWalsh() +
        Generates a Walsh matrix in ADD form. + +
        Cudd_addResidue() +
        Builds an ADD for the residue modulo m of an n-bit + number. + +
        addWalshInt() +
        Implements the recursive step of Cudd_addWalsh. + +
        +
        +

        cuddAndAbs.c

        +Combined AND and existential abstraction for BDDs

        +By: Fabio Somenzi

        +External procedures included in this module: +

          +
        • Cudd_bddAndAbstract() +
        • Cudd_bddAndAbstractLimit() +
        + Internal procedures included in this module: +
          +
        • cuddBddAndAbstractRecur() +

        +

        +
        Cudd_bddAndAbstract() +
        Takes the AND of two BDDs and simultaneously abstracts the + variables in cube. + +
        Cudd_bddAndAbstractLimit() +
        Takes the AND of two BDDs and simultaneously abstracts the + variables in cube. Returns NULL if too many nodes are required. + +
        cuddBddAndAbstractRecur() +
        Takes the AND of two BDDs and simultaneously abstracts the + variables in cube. + +
        +
        +

        cuddAnneal.c

        +Reordering of DDs based on simulated annealing

        +By: Jae-Young Jang, Jorgen Sivesind

        +Internal procedures included in this file: +

          +
        • cuddAnnealing() +
        + Static procedures included in this file: +
          +
        • stopping_criterion() +
        • random_generator() +
        • ddExchange() +
        • ddJumpingAux() +
        • ddJumpingUp() +
        • ddJumpingDown() +
        • siftBackwardProb() +
        • copyOrder() +
        • restoreOrder() +

        +

        +
        cuddAnnealing() +
        Get new variable-order by simulated annealing algorithm. + +
        stopping_criterion() +
        Checks termination condition. + +
        random_generator() +
        Random number generator. + +
        ddExchange() +
        This function is for exchanging two variables, x and y. + +
        ddJumpingAux() +
        Moves a variable to a specified position. + +
        ddJumpingUp() +
        This function is for jumping up. + +
        ddJumpingDown() +
        This function is for jumping down. + +
        siftBackwardProb() +
        Returns the DD to the best position encountered during + sifting if there was improvement. + +
        copyOrder() +
        Copies the current variable order to array. + +
        restoreOrder() +
        Restores the variable order in array by a series of sifts up. + +
        +
        +

        cuddApa.c

        +Arbitrary precision arithmetic functions.

        +By: Fabio Somenzi

        +External procedures included in this module: +

          +
        • Cudd_ApaNumberOfDigits() +
        • Cudd_NewApaNumber() +
        • Cudd_ApaCopy() +
        • Cudd_ApaAdd() +
        • Cudd_ApaSubtract() +
        • Cudd_ApaShortDivision() +
        • Cudd_ApaIntDivision() +
        • Cudd_ApaShiftRight() +
        • Cudd_ApaSetToLiteral() +
        • Cudd_ApaPowerOfTwo() +
        • Cudd_ApaCompare() +
        • Cudd_ApaCompareRatios() +
        • Cudd_ApaPrintHex() +
        • Cudd_ApaPrintDecimal() +
        • Cudd_ApaPrintExponential() +
        • Cudd_ApaCountMinterm() +
        • Cudd_ApaPrintMinterm() +
        • Cudd_ApaPrintMintermExp() +
        • Cudd_ApaPrintDensity() +
        + Static procedures included in this module: +
          +
        • cuddApaCountMintermAux() +
        • cuddApaStCountfree() +

        +

        +
        Cudd_ApaNumberOfDigits() +
        Finds the number of digits for an arbitrary precision + integer. + +
        Cudd_NewApaNumber() +
        Allocates memory for an arbitrary precision integer. + +
        Cudd_ApaCopy() +
        Makes a copy of an arbitrary precision integer. + +
        Cudd_ApaAdd() +
        Adds two arbitrary precision integers. + +
        Cudd_ApaSubtract() +
        Subtracts two arbitrary precision integers. + +
        Cudd_ApaShortDivision() +
        Divides an arbitrary precision integer by a digit. + +
        Cudd_ApaIntDivision() +
        Divides an arbitrary precision integer by an integer. + +
        Cudd_ApaShiftRight() +
        Shifts right an arbitrary precision integer by one binary + place. + +
        Cudd_ApaSetToLiteral() +
        Sets an arbitrary precision integer to a one-digit literal. + +
        Cudd_ApaPowerOfTwo() +
        Sets an arbitrary precision integer to a power of two. + +
        Cudd_ApaCompare() +
        Compares two arbitrary precision integers. + +
        Cudd_ApaCompareRatios() +
        Compares the ratios of two arbitrary precision integers to two + unsigned ints. + +
        Cudd_ApaPrintHex() +
        Prints an arbitrary precision integer in hexadecimal format. + +
        Cudd_ApaPrintDecimal() +
        Prints an arbitrary precision integer in decimal format. + +
        Cudd_ApaPrintExponential() +
        Prints an arbitrary precision integer in exponential format. + +
        Cudd_ApaCountMinterm() +
        Counts the number of minterms of a DD. + +
        Cudd_ApaPrintMinterm() +
        Prints the number of minterms of a BDD or ADD using + arbitrary precision arithmetic. + +
        Cudd_ApaPrintMintermExp() +
        Prints the number of minterms of a BDD or ADD in exponential + format using arbitrary precision arithmetic. + +
        Cudd_ApaPrintDensity() +
        Prints the density of a BDD or ADD using + arbitrary precision arithmetic. + +
        cuddApaCountMintermAux() +
        Performs the recursive step of Cudd_ApaCountMinterm. + +
        cuddApaStCountfree() +
        Frees the memory used to store the minterm counts recorded + in the visited table. + +
        +
        +

        cuddAPI.c

        +Application interface functions.

        +By: Fabio Somenzi

        +External procedures included in this module: +

          +
        • Cudd_addNewVar() +
        • Cudd_addNewVarAtLevel() +
        • Cudd_bddNewVar() +
        • Cudd_bddNewVarAtLevel() +
        • Cudd_addIthVar() +
        • Cudd_bddIthVar() +
        • Cudd_zddIthVar() +
        • Cudd_zddVarsFromBddVars() +
        • Cudd_addConst() +
        • Cudd_IsNonConstant() +
        • Cudd_AutodynEnable() +
        • Cudd_AutodynDisable() +
        • Cudd_ReorderingStatus() +
        • Cudd_AutodynEnableZdd() +
        • Cudd_AutodynDisableZdd() +
        • Cudd_ReorderingStatusZdd() +
        • Cudd_zddRealignmentEnabled() +
        • Cudd_zddRealignEnable() +
        • Cudd_zddRealignDisable() +
        • Cudd_bddRealignmentEnabled() +
        • Cudd_bddRealignEnable() +
        • Cudd_bddRealignDisable() +
        • Cudd_ReadOne() +
        • Cudd_ReadZddOne() +
        • Cudd_ReadZero() +
        • Cudd_ReadLogicZero() +
        • Cudd_ReadPlusInfinity() +
        • Cudd_ReadMinusInfinity() +
        • Cudd_ReadBackground() +
        • Cudd_SetBackground() +
        • Cudd_ReadCacheSlots() +
        • Cudd_ReadCacheUsedSlots() +
        • Cudd_ReadCacheLookUps() +
        • Cudd_ReadCacheHits() +
        • Cudd_ReadMinHit() +
        • Cudd_SetMinHit() +
        • Cudd_ReadLooseUpTo() +
        • Cudd_SetLooseUpTo() +
        • Cudd_ReadMaxCache() +
        • Cudd_ReadMaxCacheHard() +
        • Cudd_SetMaxCacheHard() +
        • Cudd_ReadSize() +
        • Cudd_ReadSlots() +
        • Cudd_ReadUsedSlots() +
        • Cudd_ExpectedUsedSlots() +
        • Cudd_ReadKeys() +
        • Cudd_ReadDead() +
        • Cudd_ReadMinDead() +
        • Cudd_ReadReorderings() +
        • Cudd_ReadReorderingTime() +
        • Cudd_ReadGarbageCollections() +
        • Cudd_ReadGarbageCollectionTime() +
        • Cudd_ReadNodesFreed() +
        • Cudd_ReadNodesDropped() +
        • Cudd_ReadUniqueLookUps() +
        • Cudd_ReadUniqueLinks() +
        • Cudd_ReadSiftMaxVar() +
        • Cudd_SetSiftMaxVar() +
        • Cudd_ReadMaxGrowth() +
        • Cudd_SetMaxGrowth() +
        • Cudd_ReadMaxGrowthAlternate() +
        • Cudd_SetMaxGrowthAlternate() +
        • Cudd_ReadReorderingCycle() +
        • Cudd_SetReorderingCycle() +
        • Cudd_ReadTree() +
        • Cudd_SetTree() +
        • Cudd_FreeTree() +
        • Cudd_ReadZddTree() +
        • Cudd_SetZddTree() +
        • Cudd_FreeZddTree() +
        • Cudd_NodeReadIndex() +
        • Cudd_ReadPerm() +
        • Cudd_ReadInvPerm() +
        • Cudd_ReadVars() +
        • Cudd_ReadEpsilon() +
        • Cudd_SetEpsilon() +
        • Cudd_ReadGroupCheck() +
        • Cudd_SetGroupcheck() +
        • Cudd_GarbageCollectionEnabled() +
        • Cudd_EnableGarbageCollection() +
        • Cudd_DisableGarbageCollection() +
        • Cudd_DeadAreCounted() +
        • Cudd_TurnOnCountDead() +
        • Cudd_TurnOffCountDead() +
        • Cudd_ReadRecomb() +
        • Cudd_SetRecomb() +
        • Cudd_ReadSymmviolation() +
        • Cudd_SetSymmviolation() +
        • Cudd_ReadArcviolation() +
        • Cudd_SetArcviolation() +
        • Cudd_ReadPopulationSize() +
        • Cudd_SetPopulationSize() +
        • Cudd_ReadNumberXovers() +
        • Cudd_SetNumberXovers() +
        • Cudd_ReadMemoryInUse() +
        • Cudd_PrintInfo() +
        • Cudd_ReadPeakNodeCount() +
        • Cudd_ReadPeakLiveNodeCount() +
        • Cudd_ReadNodeCount() +
        • Cudd_zddReadNodeCount() +
        • Cudd_AddHook() +
        • Cudd_RemoveHook() +
        • Cudd_IsInHook() +
        • Cudd_StdPreReordHook() +
        • Cudd_StdPostReordHook() +
        • Cudd_EnableReorderingReporting() +
        • Cudd_DisableReorderingReporting() +
        • Cudd_ReorderingReporting() +
        • Cudd_ReadErrorCode() +
        • Cudd_ClearErrorCode() +
        • Cudd_ReadStdout() +
        • Cudd_SetStdout() +
        • Cudd_ReadStderr() +
        • Cudd_SetStderr() +
        • Cudd_ReadNextReordering() +
        • Cudd_SetNextReordering() +
        • Cudd_ReadSwapSteps() +
        • Cudd_ReadMaxLive() +
        • Cudd_SetMaxLive() +
        • Cudd_ReadMaxMemory() +
        • Cudd_SetMaxMemory() +
        • Cudd_bddBindVar() +
        • Cudd_bddUnbindVar() +
        • Cudd_bddVarIsBound() +
        • Cudd_bddSetPiVar() +
        • Cudd_bddSetPsVar() +
        • Cudd_bddSetNsVar() +
        • Cudd_bddIsPiVar() +
        • Cudd_bddIsPsVar() +
        • Cudd_bddIsNsVar() +
        • Cudd_bddSetPairIndex() +
        • Cudd_bddReadPairIndex() +
        • Cudd_bddSetVarToBeGrouped() +
        • Cudd_bddSetVarHardGroup() +
        • Cudd_bddResetVarToBeGrouped() +
        • Cudd_bddIsVarToBeGrouped() +
        • Cudd_bddSetVarToBeUngrouped() +
        • Cudd_bddIsVarToBeUngrouped() +
        • Cudd_bddIsVarHardGroup() +
        + Static procedures included in this module: +
          +
        • fixVarTree() +

        +

        +
        Cudd_addNewVar() +
        Returns a new ADD variable. + +
        Cudd_addNewVarAtLevel() +
        Returns a new ADD variable at a specified level. + +
        Cudd_bddNewVar() +
        Returns a new BDD variable. + +
        Cudd_bddNewVarAtLevel() +
        Returns a new BDD variable at a specified level. + +
        Cudd_addIthVar() +
        Returns the ADD variable with index i. + +
        Cudd_bddIthVar() +
        Returns the BDD variable with index i. + +
        Cudd_zddIthVar() +
        Returns the ZDD variable with index i. + +
        Cudd_zddVarsFromBddVars() +
        Creates one or more ZDD variables for each BDD variable. + +
        Cudd_addConst() +
        Returns the ADD for constant c. + +
        Cudd_IsNonConstant() +
        Returns 1 if a DD node is not constant. + +
        Cudd_AutodynEnable() +
        Enables automatic dynamic reordering of BDDs and ADDs. + +
        Cudd_AutodynDisable() +
        Disables automatic dynamic reordering. + +
        Cudd_ReorderingStatus() +
        Reports the status of automatic dynamic reordering of BDDs + and ADDs. + +
        Cudd_AutodynEnableZdd() +
        Enables automatic dynamic reordering of ZDDs. + +
        Cudd_AutodynDisableZdd() +
        Disables automatic dynamic reordering of ZDDs. + +
        Cudd_ReorderingStatusZdd() +
        Reports the status of automatic dynamic reordering of ZDDs. + +
        Cudd_zddRealignmentEnabled() +
        Tells whether the realignment of ZDD order to BDD order is + enabled. + +
        Cudd_zddRealignEnable() +
        Enables realignment of ZDD order to BDD order. + +
        Cudd_zddRealignDisable() +
        Disables realignment of ZDD order to BDD order. + +
        Cudd_bddRealignmentEnabled() +
        Tells whether the realignment of BDD order to ZDD order is + enabled. + +
        Cudd_bddRealignEnable() +
        Enables realignment of BDD order to ZDD order. + +
        Cudd_bddRealignDisable() +
        Disables realignment of ZDD order to BDD order. + +
        Cudd_ReadOne() +
        Returns the one constant of the manager. + +
        Cudd_ReadZddOne() +
        Returns the ZDD for the constant 1 function. + +
        Cudd_ReadZero() +
        Returns the zero constant of the manager. + +
        Cudd_ReadLogicZero() +
        Returns the logic zero constant of the manager. + +
        Cudd_ReadPlusInfinity() +
        Reads the plus-infinity constant from the manager. + +
        Cudd_ReadMinusInfinity() +
        Reads the minus-infinity constant from the manager. + +
        Cudd_ReadBackground() +
        Reads the background constant of the manager. + +
        Cudd_SetBackground() +
        Sets the background constant of the manager. + +
        Cudd_ReadCacheSlots() +
        Reads the number of slots in the cache. + +
        Cudd_ReadCacheUsedSlots() +
        Reads the fraction of used slots in the cache. + +
        Cudd_ReadCacheLookUps() +
        Returns the number of cache look-ups. + +
        Cudd_ReadCacheHits() +
        Returns the number of cache hits. + +
        Cudd_ReadRecursiveCalls() +
        Returns the number of recursive calls. + +
        Cudd_ReadMinHit() +
        Reads the hit rate that causes resizinig of the computed + table. + +
        Cudd_SetMinHit() +
        Sets the hit rate that causes resizinig of the computed + table. + +
        Cudd_ReadLooseUpTo() +
        Reads the looseUpTo parameter of the manager. + +
        Cudd_SetLooseUpTo() +
        Sets the looseUpTo parameter of the manager. + +
        Cudd_ReadMaxCache() +
        Returns the soft limit for the cache size. + +
        Cudd_ReadMaxCacheHard() +
        Reads the maxCacheHard parameter of the manager. + +
        Cudd_SetMaxCacheHard() +
        Sets the maxCacheHard parameter of the manager. + +
        Cudd_ReadSize() +
        Returns the number of BDD variables in existance. + +
        Cudd_ReadZddSize() +
        Returns the number of ZDD variables in existance. + +
        Cudd_ReadSlots() +
        Returns the total number of slots of the unique table. + +
        Cudd_ReadUsedSlots() +
        Reads the fraction of used slots in the unique table. + +
        Cudd_ExpectedUsedSlots() +
        Computes the expected fraction of used slots in the unique + table. + +
        Cudd_ReadKeys() +
        Returns the number of nodes in the unique table. + +
        Cudd_ReadDead() +
        Returns the number of dead nodes in the unique table. + +
        Cudd_ReadMinDead() +
        Reads the minDead parameter of the manager. + +
        Cudd_ReadReorderings() +
        Returns the number of times reordering has occurred. + +
        Cudd_ReadReorderingTime() +
        Returns the time spent in reordering. + +
        Cudd_ReadGarbageCollections() +
        Returns the number of times garbage collection has occurred. + +
        Cudd_ReadGarbageCollectionTime() +
        Returns the time spent in garbage collection. + +
        Cudd_ReadNodesFreed() +
        Returns the number of nodes freed. + +
        Cudd_ReadNodesDropped() +
        Returns the number of nodes dropped. + +
        Cudd_ReadUniqueLookUps() +
        Returns the number of look-ups in the unique table. + +
        Cudd_ReadUniqueLinks() +
        Returns the number of links followed in the unique table. + +
        Cudd_ReadSiftMaxVar() +
        Reads the siftMaxVar parameter of the manager. + +
        Cudd_SetSiftMaxVar() +
        Sets the siftMaxVar parameter of the manager. + +
        Cudd_ReadSiftMaxSwap() +
        Reads the siftMaxSwap parameter of the manager. + +
        Cudd_SetSiftMaxSwap() +
        Sets the siftMaxSwap parameter of the manager. + +
        Cudd_ReadMaxGrowth() +
        Reads the maxGrowth parameter of the manager. + +
        Cudd_SetMaxGrowth() +
        Sets the maxGrowth parameter of the manager. + +
        Cudd_ReadMaxGrowthAlternate() +
        Reads the maxGrowthAlt parameter of the manager. + +
        Cudd_SetMaxGrowthAlternate() +
        Sets the maxGrowthAlt parameter of the manager. + +
        Cudd_ReadReorderingCycle() +
        Reads the reordCycle parameter of the manager. + +
        Cudd_SetReorderingCycle() +
        Sets the reordCycle parameter of the manager. + +
        Cudd_ReadTree() +
        Returns the variable group tree of the manager. + +
        Cudd_SetTree() +
        Sets the variable group tree of the manager. + +
        Cudd_FreeTree() +
        Frees the variable group tree of the manager. + +
        Cudd_ReadZddTree() +
        Returns the variable group tree of the manager. + +
        Cudd_SetZddTree() +
        Sets the ZDD variable group tree of the manager. + +
        Cudd_FreeZddTree() +
        Frees the variable group tree of the manager. + +
        Cudd_NodeReadIndex() +
        Returns the index of the node. + +
        Cudd_ReadPerm() +
        Returns the current position of the i-th variable in the + order. + +
        Cudd_ReadPermZdd() +
        Returns the current position of the i-th ZDD variable in the + order. + +
        Cudd_ReadInvPerm() +
        Returns the index of the variable currently in the i-th + position of the order. + +
        Cudd_ReadInvPermZdd() +
        Returns the index of the ZDD variable currently in the i-th + position of the order. + +
        Cudd_ReadVars() +
        Returns the i-th element of the vars array. + +
        Cudd_ReadEpsilon() +
        Reads the epsilon parameter of the manager. + +
        Cudd_SetEpsilon() +
        Sets the epsilon parameter of the manager to ep. + +
        Cudd_ReadGroupcheck() +
        Reads the groupcheck parameter of the manager. + +
        Cudd_SetGroupcheck() +
        Sets the parameter groupcheck of the manager to gc. + +
        Cudd_GarbageCollectionEnabled() +
        Tells whether garbage collection is enabled. + +
        Cudd_EnableGarbageCollection() +
        Enables garbage collection. + +
        Cudd_DisableGarbageCollection() +
        Disables garbage collection. + +
        Cudd_DeadAreCounted() +
        Tells whether dead nodes are counted towards triggering + reordering. + +
        Cudd_TurnOnCountDead() +
        Causes the dead nodes to be counted towards triggering + reordering. + +
        Cudd_TurnOffCountDead() +
        Causes the dead nodes not to be counted towards triggering + reordering. + +
        Cudd_ReadRecomb() +
        Returns the current value of the recombination parameter used + in group sifting. + +
        Cudd_SetRecomb() +
        Sets the value of the recombination parameter used in group + sifting. + +
        Cudd_ReadSymmviolation() +
        Returns the current value of the symmviolation parameter used + in group sifting. + +
        Cudd_SetSymmviolation() +
        Sets the value of the symmviolation parameter used + in group sifting. + +
        Cudd_ReadArcviolation() +
        Returns the current value of the arcviolation parameter used + in group sifting. + +
        Cudd_SetArcviolation() +
        Sets the value of the arcviolation parameter used + in group sifting. + +
        Cudd_ReadPopulationSize() +
        Reads the current size of the population used by the + genetic algorithm for reordering. + +
        Cudd_SetPopulationSize() +
        Sets the size of the population used by the + genetic algorithm for reordering. + +
        Cudd_ReadNumberXovers() +
        Reads the current number of crossovers used by the + genetic algorithm for reordering. + +
        Cudd_SetNumberXovers() +
        Sets the number of crossovers used by the + genetic algorithm for reordering. + +
        Cudd_ReadMemoryInUse() +
        Returns the memory in use by the manager measured in bytes. + +
        Cudd_PrintInfo() +
        Prints out statistics and settings for a CUDD manager. + +
        Cudd_ReadPeakNodeCount() +
        Reports the peak number of nodes. + +
        Cudd_ReadPeakLiveNodeCount() +
        Reports the peak number of live nodes. + +
        Cudd_ReadNodeCount() +
        Reports the number of nodes in BDDs and ADDs. + +
        Cudd_zddReadNodeCount() +
        Reports the number of nodes in ZDDs. + +
        Cudd_AddHook() +
        Adds a function to a hook. + +
        Cudd_RemoveHook() +
        Removes a function from a hook. + +
        Cudd_IsInHook() +
        Checks whether a function is in a hook. + +
        Cudd_StdPreReordHook() +
        Sample hook function to call before reordering. + +
        Cudd_StdPostReordHook() +
        Sample hook function to call after reordering. + +
        Cudd_EnableReorderingReporting() +
        Enables reporting of reordering stats. + +
        Cudd_DisableReorderingReporting() +
        Disables reporting of reordering stats. + +
        Cudd_ReorderingReporting() +
        Returns 1 if reporting of reordering stats is enabled. + +
        Cudd_ReadErrorCode() +
        Returns the code of the last error. + +
        Cudd_ClearErrorCode() +
        Clear the error code of a manager. + +
        Cudd_ReadStdout() +
        Reads the stdout of a manager. + +
        Cudd_SetStdout() +
        Sets the stdout of a manager. + +
        Cudd_ReadStderr() +
        Reads the stderr of a manager. + +
        Cudd_SetStderr() +
        Sets the stderr of a manager. + +
        Cudd_ReadNextReordering() +
        Returns the threshold for the next dynamic reordering. + +
        Cudd_SetNextReordering() +
        Sets the threshold for the next dynamic reordering. + +
        Cudd_ReadSwapSteps() +
        Reads the number of elementary reordering steps. + +
        Cudd_ReadMaxLive() +
        Reads the maximum allowed number of live nodes. + +
        Cudd_SetMaxLive() +
        Sets the maximum allowed number of live nodes. + +
        Cudd_ReadMaxMemory() +
        Reads the maximum allowed memory. + +
        Cudd_SetMaxMemory() +
        Sets the maximum allowed memory. + +
        Cudd_bddBindVar() +
        Prevents sifting of a variable. + +
        Cudd_bddUnbindVar() +
        Allows the sifting of a variable. + +
        Cudd_bddVarIsBound() +
        Tells whether a variable can be sifted. + +
        Cudd_bddSetPiVar() +
        Sets a variable type to primary input. + +
        Cudd_bddSetPsVar() +
        Sets a variable type to present state. + +
        Cudd_bddSetNsVar() +
        Sets a variable type to next state. + +
        Cudd_bddIsPiVar() +
        Checks whether a variable is primary input. + +
        Cudd_bddIsPsVar() +
        Checks whether a variable is present state. + +
        Cudd_bddIsNsVar() +
        Checks whether a variable is next state. + +
        Cudd_bddSetPairIndex() +
        Sets a corresponding pair index for a given index. + +
        Cudd_bddReadPairIndex() +
        Reads a corresponding pair index for a given index. + +
        Cudd_bddSetVarToBeGrouped() +
        Sets a variable to be grouped. + +
        Cudd_bddSetVarHardGroup() +
        Sets a variable to be a hard group. + +
        Cudd_bddResetVarToBeGrouped() +
        Resets a variable not to be grouped. + +
        Cudd_bddIsVarToBeGrouped() +
        Checks whether a variable is set to be grouped. + +
        Cudd_bddSetVarToBeUngrouped() +
        Sets a variable to be ungrouped. + +
        Cudd_bddIsVarToBeUngrouped() +
        Checks whether a variable is set to be ungrouped. + +
        Cudd_bddIsVarHardGroup() +
        Checks whether a variable is set to be in a hard group. + +
        fixVarTree() +
        Fixes a variable group tree. + +
        addMultiplicityGroups() +
        Adds multiplicity groups to a ZDD variable group tree. + +
        +
        +

        cuddApprox.c

        +Procedures to approximate a given BDD.

        +By: Fabio Somenzi

        +External procedures provided by this module: +

          +
        • Cudd_UnderApprox() +
        • Cudd_OverApprox() +
        • Cudd_RemapUnderApprox() +
        • Cudd_RemapOverApprox() +
        • Cudd_BiasedUnderApprox() +
        • Cudd_BiasedOverApprox() +
        + Internal procedures included in this module: +
          +
        • cuddUnderApprox() +
        • cuddRemapUnderApprox() +
        • cuddBiasedUnderApprox() +
        + Static procedures included in this module: +
          +
        • gatherInfoAux() +
        • gatherInfo() +
        • computeSavings() +
        • UAmarkNodes() +
        • UAbuildSubset() +
        • updateRefs() +
        • RAmarkNodes() +
        • BAmarkNodes() +
        • RAbuildSubset() +

        +

        See AlsocuddSubsetHB.c +cuddSubsetSP.c +cuddGenCof.c +

        +
        Cudd_UnderApprox() +
        Extracts a dense subset from a BDD with Shiple's + underapproximation method. + +
        Cudd_OverApprox() +
        Extracts a dense superset from a BDD with Shiple's + underapproximation method. + +
        Cudd_RemapUnderApprox() +
        Extracts a dense subset from a BDD with the remapping + underapproximation method. + +
        Cudd_RemapOverApprox() +
        Extracts a dense superset from a BDD with the remapping + underapproximation method. + +
        Cudd_BiasedUnderApprox() +
        Extracts a dense subset from a BDD with the biased + underapproximation method. + +
        Cudd_BiasedOverApprox() +
        Extracts a dense superset from a BDD with the biased + underapproximation method. + +
        cuddUnderApprox() +
        Applies Tom Shiple's underappoximation algorithm. + +
        cuddRemapUnderApprox() +
        Applies the remapping underappoximation algorithm. + +
        cuddBiasedUnderApprox() +
        Applies the biased remapping underappoximation algorithm. + +
        updateParity() +
        Recursively update the parity of the paths reaching a node. + +
        gatherInfoAux() +
        Recursively counts minterms and computes reference counts + of each node in the BDD. + +
        gatherInfo() +
        Gathers information about each node. + +
        computeSavings() +
        Counts the nodes that would be eliminated if a given node + were replaced by zero. + +
        updateRefs() +
        Update function reference counts. + +
        UAmarkNodes() +
        Marks nodes for replacement by zero. + +
        UAbuildSubset() +
        Builds the subset BDD. + +
        RAmarkNodes() +
        Marks nodes for remapping. + +
        BAmarkNodes() +
        Marks nodes for remapping. + +
        RAbuildSubset() +
        Builds the subset BDD for cuddRemapUnderApprox. + +
        BAapplyBias() +
        Finds don't care nodes. + +
        +
        +

        cuddBddAbs.c

        +Quantification functions for BDDs.

        +By: Fabio Somenzi

        +External procedures included in this module: +

          +
        • Cudd_bddExistAbstract() +
        • Cudd_bddXorExistAbstract() +
        • Cudd_bddUnivAbstract() +
        • Cudd_bddBooleanDiff() +
        • Cudd_bddVarIsDependent() +
        + Internal procedures included in this module: +
          +
        • cuddBddExistAbstractRecur() +
        • cuddBddXorExistAbstractRecur() +
        • cuddBddBooleanDiffRecur() +
        + Static procedures included in this module: +
          +
        • bddCheckPositiveCube() +

        +

        +
        Cudd_bddExistAbstract() +
        Existentially abstracts all the variables in cube from f. + +
        Cudd_bddXorExistAbstract() +
        Takes the exclusive OR of two BDDs and simultaneously abstracts the + variables in cube. + +
        Cudd_bddUnivAbstract() +
        Universally abstracts all the variables in cube from f. + +
        Cudd_bddBooleanDiff() +
        Computes the boolean difference of f with respect to x. + +
        Cudd_bddVarIsDependent() +
        Checks whether a variable is dependent on others in a + function. + +
        cuddBddExistAbstractRecur() +
        Performs the recursive steps of Cudd_bddExistAbstract. + +
        cuddBddXorExistAbstractRecur() +
        Takes the exclusive OR of two BDDs and simultaneously abstracts the + variables in cube. + +
        cuddBddBooleanDiffRecur() +
        Performs the recursive steps of Cudd_bddBoleanDiff. + +
        bddCheckPositiveCube() +
        Checks whether cube is an BDD representing the product of + positive literals. + +
        +
        +

        cuddBddCorr.c

        +Correlation between BDDs.

        +By: Fabio Somenzi

        +External procedures included in this module: +

          +
        • Cudd_bddCorrelation() +
        • Cudd_bddCorrelationWeights() +
        + Static procedures included in this module: +
          +
        • bddCorrelationAux() +
        • bddCorrelationWeightsAux() +
        • CorrelCompare() +
        • CorrelHash() +
        • CorrelCleanUp() +

        +

        +
        Cudd_bddCorrelation() +
        Computes the correlation of f and g. + +
        Cudd_bddCorrelationWeights() +
        Computes the correlation of f and g for given input + probabilities. + +
        bddCorrelationAux() +
        Performs the recursive step of Cudd_bddCorrelation. + +
        bddCorrelationWeightsAux() +
        Performs the recursive step of Cudd_bddCorrelationWeigths. + +
        CorrelCompare() +
        Compares two hash table entries. + +
        CorrelHash() +
        Hashes a hash table entry. + +
        CorrelCleanUp() +
        Frees memory associated with hash table. + +
        +
        +

        cuddBddIte.c

        +BDD ITE function and satellites.

        +By: Fabio Somenzi

        +External procedures included in this module: +

          +
        • Cudd_bddIte() +
        • Cudd_bddIteConstant() +
        • Cudd_bddIntersect() +
        • Cudd_bddAnd() +
        • Cudd_bddAndLimit() +
        • Cudd_bddOr() +
        • Cudd_bddNand() +
        • Cudd_bddNor() +
        • Cudd_bddXor() +
        • Cudd_bddXnor() +
        • Cudd_bddLeq() +
        + Internal procedures included in this module: +
          +
        • cuddBddIteRecur() +
        • cuddBddIntersectRecur() +
        • cuddBddAndRecur() +
        • cuddBddXorRecur() +
        + Static procedures included in this module: +
          +
        • bddVarToConst() +
        • bddVarToCanonical() +
        • bddVarToCanonicalSimple() +

        +

        +
        Cudd_bddIte() +
        Implements ITE(f,g,h). + +
        Cudd_bddIteConstant() +
        Implements ITEconstant(f,g,h). + +
        Cudd_bddIntersect() +
        Returns a function included in the intersection of f and g. + +
        Cudd_bddAnd() +
        Computes the conjunction of two BDDs f and g. + +
        Cudd_bddAndLimit() +
        Computes the conjunction of two BDDs f and g. Returns + NULL if too many nodes are required. + +
        Cudd_bddOr() +
        Computes the disjunction of two BDDs f and g. + +
        Cudd_bddNand() +
        Computes the NAND of two BDDs f and g. + +
        Cudd_bddNor() +
        Computes the NOR of two BDDs f and g. + +
        Cudd_bddXor() +
        Computes the exclusive OR of two BDDs f and g. + +
        Cudd_bddXnor() +
        Computes the exclusive NOR of two BDDs f and g. + +
        Cudd_bddLeq() +
        Determines whether f is less than or equal to g. + +
        cuddBddIteRecur() +
        Implements the recursive step of Cudd_bddIte. + +
        cuddBddIntersectRecur() +
        Implements the recursive step of Cudd_bddIntersect. + +
        cuddBddAndRecur() +
        Implements the recursive step of Cudd_bddAnd. + +
        cuddBddXorRecur() +
        Implements the recursive step of Cudd_bddXor. + +
        bddVarToConst() +
        Replaces variables with constants if possible. + +
        bddVarToCanonical() +
        Picks unique member from equiv expressions. + +
        bddVarToCanonicalSimple() +
        Picks unique member from equiv expressions. + +
        +
        +

        cuddBridge.c

        +Translation from BDD to ADD and vice versa and transfer between + different managers.

        +By: Fabio Somenzi

        +External procedures included in this file: +

          +
        • Cudd_addBddThreshold() +
        • Cudd_addBddStrictThreshold() +
        • Cudd_addBddInterval() +
        • Cudd_addBddIthBit() +
        • Cudd_BddToAdd() +
        • Cudd_addBddPattern() +
        • Cudd_bddTransfer() +
        + Internal procedures included in this file: +
          +
        • cuddBddTransfer() +
        • cuddAddBddDoPattern() +
        + Static procedures included in this file: +
          +
        • addBddDoThreshold() +
        • addBddDoStrictThreshold() +
        • addBddDoInterval() +
        • addBddDoIthBit() +
        • ddBddToAddRecur() +
        • cuddBddTransferRecur() +

        +

        +
        Cudd_addBddThreshold() +
        Converts an ADD to a BDD. + +
        Cudd_addBddStrictThreshold() +
        Converts an ADD to a BDD. + +
        Cudd_addBddInterval() +
        Converts an ADD to a BDD. + +
        Cudd_addBddIthBit() +
        Converts an ADD to a BDD by extracting the i-th bit from + the leaves. + +
        Cudd_BddToAdd() +
        Converts a BDD to a 0-1 ADD. + +
        Cudd_addBddPattern() +
        Converts an ADD to a BDD. + +
        Cudd_bddTransfer() +
        Convert a BDD from a manager to another one. + +
        cuddBddTransfer() +
        Convert a BDD from a manager to another one. + +
        cuddAddBddDoPattern() +
        Performs the recursive step for Cudd_addBddPattern. + +
        addBddDoThreshold() +
        Performs the recursive step for Cudd_addBddThreshold. + +
        addBddDoStrictThreshold() +
        Performs the recursive step for Cudd_addBddStrictThreshold. + +
        addBddDoInterval() +
        Performs the recursive step for Cudd_addBddInterval. + +
        addBddDoIthBit() +
        Performs the recursive step for Cudd_addBddIthBit. + +
        ddBddToAddRecur() +
        Performs the recursive step for Cudd_BddToAdd. + +
        cuddBddTransferRecur() +
        Performs the recursive step of Cudd_bddTransfer. + +
        +
        +

        cuddCache.c

        +Functions for cache insertion and lookup.

        +By: Fabio Somenzi

        +Internal procedures included in this module: +

          +
        • cuddInitCache() +
        • cuddCacheInsert() +
        • cuddCacheInsert2() +
        • cuddCacheLookup() +
        • cuddCacheLookupZdd() +
        • cuddCacheLookup2() +
        • cuddCacheLookup2Zdd() +
        • cuddConstantLookup() +
        • cuddCacheProfile() +
        • cuddCacheResize() +
        • cuddCacheFlush() +
        • cuddComputeFloorLog2() +
        + Static procedures included in this module: +
          +

        +

        +
        cuddInitCache() +
        Initializes the computed table. + +
        cuddCacheInsert() +
        Inserts a result in the cache. + +
        cuddCacheInsert2() +
        Inserts a result in the cache for a function with two + operands. + +
        cuddCacheInsert1() +
        Inserts a result in the cache for a function with two + operands. + +
        cuddCacheLookup() +
        Looks up in the cache for the result of op applied to f, + g, and h. + +
        cuddCacheLookupZdd() +
        Looks up in the cache for the result of op applied to f, + g, and h. + +
        cuddCacheLookup2() +
        Looks up in the cache for the result of op applied to f + and g. + +
        cuddCacheLookup1() +
        Looks up in the cache for the result of op applied to f. + +
        cuddCacheLookup2Zdd() +
        Looks up in the cache for the result of op applied to f + and g. + +
        cuddCacheLookup1Zdd() +
        Looks up in the cache for the result of op applied to f. + +
        cuddConstantLookup() +
        Looks up in the cache for the result of op applied to f, + g, and h. + +
        cuddCacheProfile() +
        Computes and prints a profile of the cache usage. + +
        cuddCacheResize() +
        Resizes the cache. + +
        cuddCacheFlush() +
        Flushes the cache. + +
        cuddComputeFloorLog2() +
        Returns the floor of the logarithm to the base 2. + +
        +
        +

        cuddCheck.c

        +Functions to check consistency of data structures.

        +By: Fabio Somenzi

        +External procedures included in this module: +

          +
        • Cudd_DebugCheck() +
        • Cudd_CheckKeys() +
        + Internal procedures included in this module: +
          +
        • cuddHeapProfile() +
        • cuddPrintNode() +
        • cuddPrintVarGroups() +
        + Static procedures included in this module: +
          +
        • debugFindParent() +

        +

        +
        Cudd_DebugCheck() +
        Checks for inconsistencies in the DD heap. + +
        Cudd_CheckKeys() +
        Checks for several conditions that should not occur. + +
        cuddHeapProfile() +
        Prints information about the heap. + +
        cuddPrintNode() +
        Prints out information on a node. + +
        cuddPrintVarGroups() +
        Prints the variable groups as a parenthesized list. + +
        debugFindParent() +
        Searches the subtables above node for its parents. + +
        debugCheckParent() +
        Reports an error if a (dead) node has a non-dead parent. + +
        +
        +

        cuddClip.c

        +Clipping functions.

        +By: Fabio Somenzi

        +External procedures included in this module: +

          +
        • Cudd_bddClippingAnd() +
        • Cudd_bddClippingAndAbstract() +
        + Internal procedures included in this module: +
          +
        • cuddBddClippingAnd() +
        • cuddBddClippingAndAbstract() +
        + Static procedures included in this module: +
          +
        • cuddBddClippingAndRecur() +
        • cuddBddClipAndAbsRecur() +
        + + SeeAlso [

        +

        +
        Cudd_bddClippingAnd() +
        Approximates the conjunction of two BDDs f and g. + +
        Cudd_bddClippingAndAbstract() +
        Approximates the conjunction of two BDDs f and g and + simultaneously abstracts the variables in cube. + +
        cuddBddClippingAnd() +
        Approximates the conjunction of two BDDs f and g. + +
        cuddBddClippingAndAbstract() +
        Approximates the conjunction of two BDDs f and g and + simultaneously abstracts the variables in cube. + +
        cuddBddClippingAndRecur() +
        Implements the recursive step of Cudd_bddClippingAnd. + +
        cuddBddClipAndAbsRecur() +
        Approximates the AND of two BDDs and simultaneously abstracts the + variables in cube. + +
        +
        +

        cuddCof.c

        +Cofactoring functions.

        +By: Fabio Somenzi

        +External procedures included in this module: +

          +
        • Cudd_Cofactor() +
        + Internal procedures included in this module: +
          +
        • cuddGetBranches() +
        • cuddCheckCube() +
        • cuddCofactorRecur() +

        +

        +
        Cudd_Cofactor() +
        Computes the cofactor of f with respect to g. + +
        cuddGetBranches() +
        Computes the children of g. + +
        cuddCheckCube() +
        Checks whether g is the BDD of a cube. + +
        cuddCofactorRecur() +
        Performs the recursive step of Cudd_Cofactor. + +
        +
        +

        cuddCompose.c

        +Functional composition and variable permutation of DDs.

        +By: Fabio Somenzi and Kavita Ravi

        +External procedures included in this module: +

          +
        • Cudd_bddCompose() +
        • Cudd_addCompose() +
        • Cudd_addPermute() +
        • Cudd_addSwapVariables() +
        • Cudd_bddPermute() +
        • Cudd_bddVarMap() +
        • Cudd_SetVarMap() +
        • Cudd_bddSwapVariables() +
        • Cudd_bddAdjPermuteX() +
        • Cudd_addVectorCompose() +
        • Cudd_addGeneralVectorCompose() +
        • Cudd_addNonSimCompose() +
        • Cudd_bddVectorCompose() +
        + Internal procedures included in this module: +
          +
        • cuddBddComposeRecur() +
        • cuddAddComposeRecur() +
        + Static procedures included in this module: +
          +
        • cuddAddPermuteRecur() +
        • cuddBddPermuteRecur() +
        • cuddBddVarMapRecur() +
        • cuddAddVectorComposeRecur() +
        • cuddAddGeneralVectorComposeRecur() +
        • cuddAddNonSimComposeRecur() +
        • cuddBddVectorComposeRecur() +
        • ddIsIthAddVar() +
        • ddIsIthAddVarPair() +
        + 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.

        +

        +
        Cudd_bddCompose() +
        Substitutes g for x_v in the BDD for f. + +
        Cudd_addCompose() +
        Substitutes g for x_v in the ADD for f. + +
        Cudd_addPermute() +
        Permutes the variables of an ADD. + +
        Cudd_addSwapVariables() +
        Swaps two sets of variables of the same size (x and y) in + the ADD f. + +
        Cudd_bddPermute() +
        Permutes the variables of a BDD. + +
        Cudd_bddVarMap() +
        Remaps the variables of a BDD using the default variable map. + +
        Cudd_SetVarMap() +
        Registers a variable mapping with the manager. + +
        Cudd_bddSwapVariables() +
        Swaps two sets of variables of the same size (x and y) in + the BDD f. + +
        Cudd_bddAdjPermuteX() +
        Rearranges a set of variables in the BDD B. + +
        Cudd_addVectorCompose() +
        Composes an ADD with a vector of 0-1 ADDs. + +
        Cudd_addGeneralVectorCompose() +
        Composes an ADD with a vector of ADDs. + +
        Cudd_addNonSimCompose() +
        Composes an ADD with a vector of 0-1 ADDs. + +
        Cudd_bddVectorCompose() +
        Composes a BDD with a vector of BDDs. + +
        cuddBddComposeRecur() +
        Performs the recursive step of Cudd_bddCompose. + +
        cuddAddComposeRecur() +
        Performs the recursive step of Cudd_addCompose. + +
        cuddAddPermuteRecur() +
        Implements the recursive step of Cudd_addPermute. + +
        cuddBddPermuteRecur() +
        Implements the recursive step of Cudd_bddPermute. + +
        cuddBddVarMapRecur() +
        Implements the recursive step of Cudd_bddVarMap. + +
        cuddAddVectorComposeRecur() +
        Performs the recursive step of Cudd_addVectorCompose. + +
        cuddAddGeneralVectorComposeRecur() +
        Performs the recursive step of Cudd_addGeneralVectorCompose. + +
        cuddAddNonSimComposeRecur() +
        Performs the recursive step of Cudd_addNonSimCompose. + +
        cuddBddVectorComposeRecur() +
        Performs the recursive step of Cudd_bddVectorCompose. + +
        ddIsIthAddVar() +
        Comparison of a function to the i-th ADD variable. + +
        ddIsIthAddVarPair() +
        Comparison of a pair of functions to the i-th ADD variable. + +
        +
        +

        cuddDecomp.c

        +Functions for BDD decomposition.

        +By: Kavita Ravi, Fabio Somenzi

        +External procedures included in this file: +

          +
        • Cudd_bddApproxConjDecomp() +
        • Cudd_bddApproxDisjDecomp() +
        • Cudd_bddIterConjDecomp() +
        • Cudd_bddIterDisjDecomp() +
        • Cudd_bddGenConjDecomp() +
        • Cudd_bddGenDisjDecomp() +
        • Cudd_bddVarConjDecomp() +
        • Cudd_bddVarDisjDecomp() +
        + Static procedures included in this module: +
          +
        • cuddConjunctsAux() +
        • CreateBotDist() +
        • BuildConjuncts() +
        • ConjunctsFree() +

        +

        +
        Cudd_bddApproxConjDecomp() +
        Performs two-way conjunctive decomposition of a BDD. + +
        Cudd_bddApproxDisjDecomp() +
        Performs two-way disjunctive decomposition of a BDD. + +
        Cudd_bddIterConjDecomp() +
        Performs two-way conjunctive decomposition of a BDD. + +
        Cudd_bddIterDisjDecomp() +
        Performs two-way disjunctive decomposition of a BDD. + +
        Cudd_bddGenConjDecomp() +
        Performs two-way conjunctive decomposition of a BDD. + +
        Cudd_bddGenDisjDecomp() +
        Performs two-way disjunctive decomposition of a BDD. + +
        Cudd_bddVarConjDecomp() +
        Performs two-way conjunctive decomposition of a BDD. + +
        Cudd_bddVarDisjDecomp() +
        Performs two-way disjunctive decomposition of a BDD. + +
        CreateBotDist() +
        Get longest distance of node from constant. + +
        CountMinterms() +
        Count the number of minterms of each node ina a BDD and + store it in a hash table. + +
        ConjunctsFree() +
        Free factors structure + +
        PairInTables() +
        Check whether the given pair is in the tables. + +
        CheckTablesCacheAndReturn() +
        Check the tables for the existence of pair and return one + combination, cache the result. + +
        PickOnePair() +
        Check the tables for the existence of pair and return one + combination, store in cache. + +
        CheckInTables() +
        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. + +
        ZeroCase() +
        If one child is zero, do explicitly what Restrict does or better + +
        BuildConjuncts() +
        Builds the conjuncts recursively, bottom up. + +
        cuddConjunctsAux() +
        Procedure to compute two conjunctive factors of f and place in *c1 and *c2. + +
        +
        +

        cuddEssent.c

        +Functions for the detection of essential variables.

        +By: Fabio Somenzi

        +External procedures included in this file: +

          +
        • Cudd_FindEssential() +
        • Cudd_bddIsVarEssential() +
        • Cudd_FindTwoLiteralClauses() +
        • Cudd_ReadIthClause() +
        • Cudd_PrintTwoLiteralClauses() +
        • Cudd_tlcInfoFree() +
        + Static procedures included in this module: +
          +
        • ddFindEssentialRecur() +
        • ddFindTwoLiteralClausesRecur() +
        • computeClauses() +
        • computeClausesWithUniverse() +
        • emptyClauseSet() +
        • sentinelp() +
        • equalp() +
        • beforep() +
        • oneliteralp() +
        • impliedp() +
        • bitVectorAlloc() +
        • bitVectorClear() +
        • bitVectorFree() +
        • bitVectorRead() +
        • bitVectorSet() +
        • tlcInfoAlloc() +

        +

        +
        Cudd_FindEssential() +
        Finds the essential variables of a DD. + +
        Cudd_bddIsVarEssential() +
        Determines whether a given variable is essential with a + given phase in a BDD. + +
        Cudd_FindTwoLiteralClauses() +
        Finds the two literal clauses of a DD. + +
        Cudd_ReadIthClause() +
        Accesses the i-th clause of a DD. + +
        Cudd_PrintTwoLiteralClauses() +
        Prints the two literal clauses of a DD. + +
        Cudd_tlcInfoFree() +
        Frees a DdTlcInfo Structure. + +
        ddFindEssentialRecur() +
        Implements the recursive step of Cudd_FindEssential. + +
        ddFindTwoLiteralClausesRecur() +
        Implements the recursive step of Cudd_FindTwoLiteralClauses. + +
        computeClauses() +
        Computes the two-literal clauses for a node. + +
        computeClausesWithUniverse() +
        Computes the two-literal clauses for a node. + +
        emptyClauseSet() +
        Returns an enpty set of clauses. + +
        sentinelp() +
        Returns true iff the argument is the sentinel clause. + +
        equalp() +
        Returns true iff the two arguments are identical clauses. + +
        beforep() +
        Returns true iff the first argument precedes the second in + the clause order. + +
        oneliteralp() +
        Returns true iff the argument is a one-literal clause. + +
        impliedp() +
        Returns true iff either literal of a clause is in a set of + literals. + +
        bitVectorAlloc() +
        Allocates a bit vector. + +
        bitVectorClear() +
        Clears a bit vector. + +
        bitVectorFree() +
        Frees a bit vector. + +
        bitVectorRead() +
        Returns the i-th entry of a bit vector. + +
        bitVectorSet() +
        Sets the i-th entry of a bit vector to a value. + +
        tlcInfoAlloc() +
        Allocates a DdTlcInfo Structure. + +
        +
        +

        cuddExact.c

        +Functions for exact variable reordering.

        +By: Cheng Hua, Fabio Somenzi

        +External procedures included in this file: +

          +
        + Internal procedures included in this module: +
          +
        • cuddExact() +
        + Static procedures included in this module: +
          +
        • getMaxBinomial() +
        • gcd() +
        • getMatrix() +
        • freeMatrix() +
        • getLevelKeys() +
        • ddShuffle() +
        • ddSiftUp() +
        • updateUB() +
        • ddCountRoots() +
        • ddClearGlobal() +
        • computeLB() +
        • updateEntry() +
        • pushDown() +
        • initSymmInfo() +

        +

        +
        cuddExact() +
        Exact variable ordering algorithm. + +
        getMaxBinomial() +
        Returns the maximum value of (n choose k) for a given n. + +
        gcd() +
        Returns the gcd of two integers. + +
        getMatrix() +
        Allocates a two-dimensional matrix of ints. + +
        freeMatrix() +
        Frees a two-dimensional matrix allocated by getMatrix. + +
        getLevelKeys() +
        Returns the number of nodes at one level of a unique table. + +
        ddShuffle() +
        Reorders variables according to a given permutation. + +
        ddSiftUp() +
        Moves one variable up. + +
        updateUB() +
        Updates the upper bound and saves the best order seen so far. + +
        ddCountRoots() +
        Counts the number of roots. + +
        ddClearGlobal() +
        Scans the DD and clears the LSB of the next pointers. + +
        computeLB() +
        Computes a lower bound on the size of a BDD. + +
        updateEntry() +
        Updates entry for a subset. + +
        pushDown() +
        Pushes a variable in the order down to position "level." + +
        initSymmInfo() +
        Gathers symmetry information. + +
        checkSymmInfo() +
        Check symmetry condition. + +
        +
        +

        cuddExport.c

        +Export functions.

        +By: Fabio Somenzi

        +External procedures included in this module: +

          +
        • Cudd_DumpBlif() +
        • Cudd_DumpBlifBody() +
        • Cudd_DumpDot() +
        • Cudd_DumpDaVinci() +
        • Cudd_DumpDDcal() +
        • Cudd_DumpFactoredForm() +
        + Internal procedures included in this module: +
          +
        + Static procedures included in this module: +
          +
        • ddDoDumpBlif() +
        • ddDoDumpDaVinci() +
        • ddDoDumpDDcal() +
        • ddDoDumpFactoredForm() +

        +

        +
        Cudd_DumpBlif() +
        Writes a blif file representing the argument BDDs. + +
        Cudd_DumpBlifBody() +
        Writes a blif body representing the argument BDDs. + +
        Cudd_DumpDot() +
        Writes a dot file representing the argument DDs. + +
        Cudd_DumpDaVinci() +
        Writes a daVinci file representing the argument BDDs. + +
        Cudd_DumpDDcal() +
        Writes a DDcal file representing the argument BDDs. + +
        Cudd_DumpFactoredForm() +
        Writes factored forms representing the argument BDDs. + +
        ddDoDumpBlif() +
        Performs the recursive step of Cudd_DumpBlif. + +
        ddDoDumpDaVinci() +
        Performs the recursive step of Cudd_DumpDaVinci. + +
        ddDoDumpDDcal() +
        Performs the recursive step of Cudd_DumpDDcal. + +
        ddDoDumpFactoredForm() +
        Performs the recursive step of Cudd_DumpFactoredForm. + +
        +
        +

        cuddGenCof.c

        +Generalized cofactors for BDDs and ADDs.

        +By: Fabio Somenzi

        +External procedures included in this module: +

          +
        • Cudd_bddConstrain() +
        • Cudd_bddRestrict() +
        • Cudd_bddNPAnd() +
        • Cudd_addConstrain() +
        • Cudd_bddConstrainDecomp() +
        • Cudd_addRestrict() +
        • Cudd_bddCharToVect() +
        • Cudd_bddLICompaction() +
        • Cudd_bddSqueeze() +
        • Cudd_SubsetCompress() +
        • Cudd_SupersetCompress() +
        + Internal procedures included in this module: +
          +
        • cuddBddConstrainRecur() +
        • cuddBddRestrictRecur() +
        • cuddBddNPAndRecur() +
        • cuddAddConstrainRecur() +
        • cuddAddRestrictRecur() +
        • cuddBddLICompaction() +
        + Static procedures included in this module: +
          +
        • cuddBddConstrainDecomp() +
        • cuddBddCharToVect() +
        • cuddBddLICMarkEdges() +
        • cuddBddLICBuildResult() +
        • cuddBddSqueeze() +

        +

        +
        Cudd_bddConstrain() +
        Computes f constrain c. + +
        Cudd_bddRestrict() +
        BDD restrict according to Coudert and Madre's algorithm + (ICCAD90). + +
        Cudd_bddNPAnd() +
        Computes f non-polluting-and g. + +
        Cudd_addConstrain() +
        Computes f constrain c for ADDs. + +
        Cudd_bddConstrainDecomp() +
        BDD conjunctive decomposition as in McMillan's CAV96 paper. + +
        Cudd_addRestrict() +
        ADD restrict according to Coudert and Madre's algorithm + (ICCAD90). + +
        Cudd_bddCharToVect() +
        Computes a vector whose image equals a non-zero function. + +
        Cudd_bddLICompaction() +
        Performs safe minimization of a BDD. + +
        Cudd_bddSqueeze() +
        Finds a small BDD in a function interval. + +
        Cudd_bddMinimize() +
        Finds a small BDD that agrees with f over + c. + +
        Cudd_SubsetCompress() +
        Find a dense subset of BDD f. + +
        Cudd_SupersetCompress() +
        Find a dense superset of BDD f. + +
        cuddBddConstrainRecur() +
        Performs the recursive step of Cudd_bddConstrain. + +
        cuddBddRestrictRecur() +
        Performs the recursive step of Cudd_bddRestrict. + +
        cuddBddNPAndRecur() +
        Implements the recursive step of Cudd_bddAnd. + +
        cuddAddConstrainRecur() +
        Performs the recursive step of Cudd_addConstrain. + +
        cuddAddRestrictRecur() +
        Performs the recursive step of Cudd_addRestrict. + +
        cuddBddLICompaction() +
        Performs safe minimization of a BDD. + +
        cuddBddConstrainDecomp() +
        Performs the recursive step of Cudd_bddConstrainDecomp. + +
        cuddBddCharToVect() +
        Performs the recursive step of Cudd_bddCharToVect. + +
        cuddBddLICMarkEdges() +
        Performs the edge marking step of Cudd_bddLICompaction. + +
        cuddBddLICBuildResult() +
        Builds the result of Cudd_bddLICompaction. + +
        MarkCacheHash() +
        Hash function for the computed table of cuddBddLICMarkEdges. + +
        MarkCacheCompare() +
        Comparison function for the computed table of + cuddBddLICMarkEdges. + +
        MarkCacheCleanUp() +
        Frees memory associated with computed table of + cuddBddLICMarkEdges. + +
        cuddBddSqueeze() +
        Performs the recursive step of Cudd_bddSqueeze. + +
        +
        +

        cuddGenetic.c

        +Genetic algorithm for variable reordering.

        +By: Curt Musfeldt, Alan Shuler, Fabio Somenzi

        +Internal procedures included in this file: +

          +
        • cuddGa() +
        + Static procedures included in this module: +
          +
        • make_random() +
        • sift_up() +
        • build_dd() +
        • largest() +
        • rand_int() +
        • array_hash() +
        • array_compare() +
        • find_best() +
        • find_average_fitness() +
        • PMX() +
        • roulette() +
        + + 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.

        +

        +
        cuddGa() +
        Genetic algorithm for DD reordering. + +
        make_random() +
        Generates the random sequences for the initial population. + +
        sift_up() +
        Moves one variable up. + +
        build_dd() +
        Builds a DD from a given order. + +
        largest() +
        Finds the largest DD in the population. + +
        rand_int() +
        Generates a random number between 0 and the integer a. + +
        array_hash() +
        Hash function for the computed table. + +
        array_compare() +
        Comparison function for the computed table. + +
        find_best() +
        Returns the index of the fittest individual. + +
        find_average_fitness() +
        Returns the average fitness of the population. + +
        PMX() +
        Performs the crossover between two parents. + +
        roulette() +
        Selects two parents with the roulette wheel method. + +
        +
        +

        cuddGroup.c

        +Functions for group sifting.

        +By: Shipra Panda, Fabio Somenzi

        +External procedures included in this file: +

          +
        • Cudd_MakeTreeNode() +
        + Internal procedures included in this file: +
          +
        • cuddTreeSifting() +
        + Static procedures included in this module: +
          +
        • ddTreeSiftingAux() +
        • ddCountInternalMtrNodes() +
        • ddReorderChildren() +
        • ddFindNodeHiLo() +
        • ddUniqueCompareGroup() +
        • ddGroupSifting() +
        • ddCreateGroup() +
        • ddGroupSiftingAux() +
        • ddGroupSiftingUp() +
        • ddGroupSiftingDown() +
        • ddGroupMove() +
        • ddGroupMoveBackward() +
        • ddGroupSiftingBackward() +
        • ddMergeGroups() +
        • ddDissolveGroup() +
        • ddNoCheck() +
        • ddSecDiffCheck() +
        • ddExtSymmCheck() +
        • ddVarGroupCheck() +
        • ddSetVarHandled() +
        • ddResetVarHandled() +
        • ddIsVarHandled() +

        +

        +
        Cudd_MakeTreeNode() +
        Creates a new variable group. + +
        cuddTreeSifting() +
        Tree sifting algorithm. + +
        ddTreeSiftingAux() +
        Visits the group tree and reorders each group. + +
        ddCountInternalMtrNodes() +
        Counts the number of internal nodes of the group tree. + +
        ddReorderChildren() +
        Reorders the children of a group tree node according to + the options. + +
        ddFindNodeHiLo() +
        Finds the lower and upper bounds of the group represented + by treenode. + +
        ddUniqueCompareGroup() +
        Comparison function used by qsort. + +
        ddGroupSifting() +
        Sifts from treenode->low to treenode->high. + +
        ddCreateGroup() +
        Creates a group encompassing variables from x to y in the + DD table. + +
        ddGroupSiftingAux() +
        Sifts one variable up and down until it has taken all + positions. Checks for aggregation. + +
        ddGroupSiftingUp() +
        Sifts up a variable until either it reaches position xLow + or the size of the DD heap increases too much. + +
        ddGroupSiftingDown() +
        Sifts down a variable until it reaches position xHigh. + +
        ddGroupMove() +
        Swaps two groups and records the move. + +
        ddGroupMoveBackward() +
        Undoes the swap two groups. + +
        ddGroupSiftingBackward() +
        Determines the best position for a variables and returns + it there. + +
        ddMergeGroups() +
        Merges groups in the DD table. + +
        ddDissolveGroup() +
        Dissolves a group in the DD table. + +
        ddNoCheck() +
        Pretends to check two variables for aggregation. + +
        ddSecDiffCheck() +
        Checks two variables for aggregation. + +
        ddExtSymmCheck() +
        Checks for extended symmetry of x and y. + +
        ddVarGroupCheck() +
        Checks for grouping of x and y. + +
        ddSetVarHandled() +
        Sets a variable to already handled. + +
        ddResetVarHandled() +
        Resets a variable to be processed. + +
        ddIsVarHandled() +
        Checks whether a variables is already handled. + +
        +
        +

        cuddHarwell.c

        +Function to read a matrix in Harwell format.

        +By: Fabio Somenzi

        +External procedures included in this module: +

          +
        • Cudd_addHarwell() +

        +

        +
        Cudd_addHarwell() +
        Reads in a matrix in the format of the Harwell-Boeing + benchmark suite. + +
        +
        +

        cuddInit.c

        +Functions to initialize and shut down the DD manager.

        +By: Fabio Somenzi

        +External procedures included in this module: +

          +
        • Cudd_Init() +
        • Cudd_Quit() +
        + Internal procedures included in this module: +
          +
        • cuddZddInitUniv() +
        • cuddZddFreeUniv() +

        +

        +
        Cudd_Init() +
        Creates a new DD manager. + +
        Cudd_Quit() +
        Deletes resources associated with a DD manager. + +
        cuddZddInitUniv() +
        Initializes the ZDD universe. + +
        cuddZddFreeUniv() +
        Frees the ZDD universe. + +
        +
        +

        cuddInteract.c

        +Functions to manipulate the variable interaction matrix.

        +By: Fabio Somenzi

        +Internal procedures included in this file: +

          +
        • cuddSetInteract() +
        • cuddTestInteract() +
        • cuddInitInteract() +
        + Static procedures included in this file: +
          +
        • ddSuppInteract() +
        • ddClearLocal() +
        • ddUpdateInteract() +
        • ddClearGlobal() +
        + 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.

        + 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.

        +

        +
        cuddSetInteract() +
        Set interaction matrix entries. + +
        cuddTestInteract() +
        Test interaction matrix entries. + +
        cuddInitInteract() +
        Initializes the interaction matrix. + +
        ddSuppInteract() +
        Find the support of f. + +
        ddClearLocal() +
        Performs a DFS from f, clearing the LSB of the then pointers. + +
        ddUpdateInteract() +
        Marks as interacting all pairs of variables that appear in + support. + +
        ddClearGlobal() +
        Scans the DD and clears the LSB of the next pointers. + +
        +
        +

        cuddLCache.c

        +Functions for local caches.

        +By: Fabio Somenzi

        +Internal procedures included in this module: +

          +
        • cuddLocalCacheInit() +
        • cuddLocalCacheQuit() +
        • cuddLocalCacheInsert() +
        • cuddLocalCacheLookup() +
        • cuddLocalCacheClearDead() +
        • cuddLocalCacheClearAll() +
        • cuddLocalCacheProfile() +
        • cuddHashTableInit() +
        • cuddHashTableQuit() +
        • cuddHashTableInsert() +
        • cuddHashTableLookup() +
        • cuddHashTableInsert2() +
        • cuddHashTableLookup2() +
        • cuddHashTableInsert3() +
        • cuddHashTableLookup3() +
        + Static procedures included in this module: +
          +
        • cuddLocalCacheResize() +
        • ddLCHash() +
        • cuddLocalCacheAddToList() +
        • cuddLocalCacheRemoveFromList() +
        • cuddHashTableResize() +
        • cuddHashTableAlloc() +

        +

        +
        cuddLocalCacheInit() +
        Initializes a local computed table. + +
        cuddLocalCacheQuit() +
        Shuts down a local computed table. + +
        cuddLocalCacheInsert() +
        Inserts a result in a local cache. + +
        cuddLocalCacheLookup() +
        Looks up in a local cache. + +
        cuddLocalCacheClearDead() +
        Clears the dead entries of the local caches of a manager. + +
        cuddLocalCacheClearAll() +
        Clears the local caches of a manager. + +
        cuddLocalCacheProfile() +
        Computes and prints a profile of a local cache usage. + +
        cuddHashTableInit() +
        Initializes a hash table. + +
        cuddHashTableQuit() +
        Shuts down a hash table. + +
        cuddHashTableInsert() +
        Inserts an item in a hash table. + +
        cuddHashTableLookup() +
        Looks up a key in a hash table. + +
        cuddHashTableInsert1() +
        Inserts an item in a hash table. + +
        cuddHashTableLookup1() +
        Looks up a key consisting of one pointer in a hash table. + +
        cuddHashTableInsert2() +
        Inserts an item in a hash table. + +
        cuddHashTableLookup2() +
        Looks up a key consisting of two pointers in a hash table. + +
        cuddHashTableInsert3() +
        Inserts an item in a hash table. + +
        cuddHashTableLookup3() +
        Looks up a key consisting of three pointers in a hash table. + +
        cuddLocalCacheResize() +
        Resizes a local cache. + +
        ddLCHash() +
        Computes the hash value for a local cache. + +
        cuddLocalCacheAddToList() +
        Inserts a local cache in the manager list. + +
        cuddLocalCacheRemoveFromList() +
        Removes a local cache from the manager list. + +
        cuddHashTableResize() +
        Resizes a hash table. + +
        cuddHashTableAlloc() +
        Fast storage allocation for items in a hash table. + +
        +
        +

        cuddLevelQ.c

        +Procedure to manage level queues.

        +By: Fabio Somenzi

        +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: +

          +
        • cuddLevelQueueInit() +
        • cuddLevelQueueQuit() +
        • cuddLevelQueueEnqueue() +
        • cuddLevelQueueDequeue() +
        + Static procedures included in this module: +
          +
        • hashLookup() +
        • hashInsert() +
        • hashDelete() +
        • hashResize() +

        +

        +
        cuddLevelQueueInit() +
        Initializes a level queue. + +
        cuddLevelQueueQuit() +
        Shuts down a level queue. + +
        cuddLevelQueueEnqueue() +
        Inserts a new key in a level queue. + +
        cuddLevelQueueDequeue() +
        Remove an item from the front of a level queue. + +
        hashLookup() +
        Looks up a key in the hash table of a level queue. + +
        hashInsert() +
        Inserts an item in the hash table of a level queue. + +
        hashDelete() +
        Removes an item from the hash table of a level queue. + +
        hashResize() +
        Resizes the hash table of a level queue. + +
        +
        +

        cuddLinear.c

        +Functions for DD reduction by linear transformations.

        +By: Fabio Somenzi

        +Internal procedures included in this module: +

          +
        • cuddLinearAndSifting() +
        • cuddLinearInPlace() +
        • cuddUpdateInteractionMatrix() +
        • cuddInitLinear() +
        • cuddResizeLinear() +
        + Static procedures included in this module: +
          +
        • ddLinearUniqueCompare() +
        • ddLinearAndSiftingAux() +
        • ddLinearAndSiftingUp() +
        • ddLinearAndSiftingDown() +
        • ddLinearAndSiftingBackward() +
        • ddUndoMoves() +
        • cuddXorLinear() +

        +

        +
        Cudd_PrintLinear() +
        Prints the linear transform matrix. + +
        Cudd_ReadLinear() +
        Reads an entry of the linear transform matrix. + +
        cuddLinearAndSifting() +
        BDD reduction based on combination of sifting and linear + transformations. + +
        cuddLinearInPlace() +
        Linearly combines two adjacent variables. + +
        cuddUpdateInteractionMatrix() +
        Updates the interaction matrix. + +
        cuddInitLinear() +
        Initializes the linear transform matrix. + +
        cuddResizeLinear() +
        Resizes the linear transform matrix. + +
        ddLinearUniqueCompare() +
        Comparison function used by qsort. + +
        ddLinearAndSiftingAux() +
        Given xLow <= x <= xHigh moves x up and down between the + boundaries. + +
        ddLinearAndSiftingUp() +
        Sifts a variable up and applies linear transformations. + +
        ddLinearAndSiftingDown() +
        Sifts a variable down and applies linear transformations. + +
        ddLinearAndSiftingBackward() +
        Given a set of moves, returns the DD heap to the order + giving the minimum size. + +
        ddUndoMoves() +
        Given a set of moves, returns the DD heap to the order + in effect before the moves. + +
        cuddXorLinear() +
        XORs two rows of the linear transform matrix. + +
        +
        +

        cuddLiteral.c

        +Functions for manipulation of literal sets represented by + BDDs.

        +By: Fabio Somenzi

        +External procedures included in this file: +

          +
        • Cudd_bddLiteralSetIntersection() +
        + Internal procedures included in this file: +
          +
        • cuddBddLiteralSetIntersectionRecur() +

        +

        +
        Cudd_bddLiteralSetIntersection() +
        Computes the intesection of two sets of literals + represented as BDDs. + +
        cuddBddLiteralSetIntersectionRecur() +
        Performs the recursive step of + Cudd_bddLiteralSetIntersection. + +
        +
        +

        cuddMatMult.c

        +Matrix multiplication functions.

        +By: Fabio Somenzi

        +External procedures included in this module: +

          +
        • Cudd_addMatrixMultiply() +
        • Cudd_addTimesPlus() +
        • Cudd_addTriangle() +
        • Cudd_addOuterSum() +
        + Static procedures included in this module: +
          +
        • addMMRecur() +
        • addTriangleRecur() +
        • cuddAddOuterSumRecur() +

        +

        +
        Cudd_addMatrixMultiply() +
        Calculates the product of two matrices represented as + ADDs. + +
        Cudd_addTimesPlus() +
        Calculates the product of two matrices represented as + ADDs. + +
        Cudd_addTriangle() +
        Performs the triangulation step for the shortest path + computation. + +
        Cudd_addOuterSum() +
        Takes the minimum of a matrix and the outer sum of two vectors. + +
        addMMRecur() +
        Performs the recursive step of Cudd_addMatrixMultiply. + +
        addTriangleRecur() +
        Performs the recursive step of Cudd_addTriangle. + +
        cuddAddOuterSumRecur() +
        Performs the recursive step of Cudd_addOuterSum. + +
        +
        +

        cuddPriority.c

        +Priority functions.

        +By: Fabio Somenzi

        +External procedures included in this file: +

          +
        • Cudd_PrioritySelect() +
        • Cudd_Xgty() +
        • Cudd_Xeqy() +
        • Cudd_addXeqy() +
        • Cudd_Dxygtdxz() +
        • Cudd_Dxygtdyz() +
        • Cudd_Inequality() +
        • Cudd_Disequality() +
        • Cudd_bddInterval() +
        • Cudd_CProjection() +
        • Cudd_addHamming() +
        • Cudd_MinHammingDist() +
        • Cudd_bddClosestCube() +
        + Internal procedures included in this module: +
          +
        • cuddCProjectionRecur() +
        • cuddBddClosestCube() +
        + Static procedures included in this module: +
          +
        • cuddMinHammingDistRecur() +
        • separateCube() +
        • createResult() +

        +

        +
        Cudd_PrioritySelect() +
        Selects pairs from R using a priority function. + +
        Cudd_Xgty() +
        Generates a BDD for the function x > y. + +
        Cudd_Xeqy() +
        Generates a BDD for the function x==y. + +
        Cudd_addXeqy() +
        Generates an ADD for the function x==y. + +
        Cudd_Dxygtdxz() +
        Generates a BDD for the function d(x,y) > d(x,z). + +
        Cudd_Dxygtdyz() +
        Generates a BDD for the function d(x,y) > d(y,z). + +
        Cudd_Inequality() +
        Generates a BDD for the function x - y ≥ c. + +
        Cudd_Disequality() +
        Generates a BDD for the function x - y != c. + +
        Cudd_bddInterval() +
        Generates a BDD for the function lowerB ≤ x ≤ upperB. + +
        Cudd_CProjection() +
        Computes the compatible projection of R w.r.t. cube Y. + +
        Cudd_addHamming() +
        Computes the Hamming distance ADD. + +
        Cudd_MinHammingDist() +
        Returns the minimum Hamming distance between f and minterm. + +
        Cudd_bddClosestCube() +
        Finds a cube of f at minimum Hamming distance from g. + +
        cuddCProjectionRecur() +
        Performs the recursive step of Cudd_CProjection. + +
        cuddBddClosestCube() +
        Performs the recursive step of Cudd_bddClosestCube. + +
        cuddMinHammingDistRecur() +
        Performs the recursive step of Cudd_MinHammingDist. + +
        separateCube() +
        Separates cube from distance. + +
        createResult() +
        Builds a result for cache storage. + +
        +
        +

        cuddRead.c

        +Functions to read in a matrix

        +By: Fabio Somenzi

        +External procedures included in this module: +

          +
        • Cudd_addRead() +
        • Cudd_bddRead() +

        +

        See Alsocudd_addHarwell.c +

        +
        Cudd_addRead() +
        Reads in a sparse matrix. + +
        Cudd_bddRead() +
        Reads in a graph (without labels) given as a list of arcs. + +
        +
        +

        cuddRef.c

        +Functions that manipulate the reference counts.

        +By: Fabio Somenzi

        +External procedures included in this module: +

          +
        • Cudd_Ref() +
        • Cudd_RecursiveDeref() +
        • Cudd_IterDerefBdd() +
        • Cudd_DelayedDerefBdd() +
        • Cudd_RecursiveDerefZdd() +
        • Cudd_Deref() +
        • Cudd_CheckZeroRef() +
        + Internal procedures included in this module: +
          +
        • cuddReclaim() +
        • cuddReclaimZdd() +
        • cuddClearDeathRow() +
        • cuddShrinkDeathRow() +
        • cuddIsInDeathRow() +
        • cuddTimesInDeathRow() +

        +

        +
        Cudd_Ref() +
        Increases the reference count of a node, if it is not + saturated. + +
        Cudd_RecursiveDeref() +
        Decreases the reference count of node n. + +
        Cudd_IterDerefBdd() +
        Decreases the reference count of BDD node n. + +
        Cudd_DelayedDerefBdd() +
        Decreases the reference count of BDD node n. + +
        Cudd_RecursiveDerefZdd() +
        Decreases the reference count of ZDD node n. + +
        Cudd_Deref() +
        Decreases the reference count of node. + +
        Cudd_CheckZeroRef() +
        Checks the unique table for nodes with non-zero reference + counts. + +
        cuddReclaim() +
        Brings children of a dead node back. + +
        cuddReclaimZdd() +
        Brings children of a dead ZDD node back. + +
        cuddShrinkDeathRow() +
        Shrinks the death row. + +
        cuddClearDeathRow() +
        Clears the death row. + +
        cuddIsInDeathRow() +
        Checks whether a node is in the death row. + +
        cuddTimesInDeathRow() +
        Counts how many times a node is in the death row. + +
        +
        +

        cuddReorder.c

        +Functions for dynamic variable reordering.

        +By: Shipra Panda, Bernard Plessier, Fabio Somenzi

        +External procedures included in this file: +

          +
        • Cudd_ReduceHeap() +
        • Cudd_ShuffleHeap() +
        + Internal procedures included in this module: +
          +
        • cuddDynamicAllocNode() +
        • cuddSifting() +
        • cuddSwapping() +
        • cuddNextHigh() +
        • cuddNextLow() +
        • cuddSwapInPlace() +
        • cuddBddAlignToZdd() +
        + Static procedures included in this module: +
          +
        • ddUniqueCompare() +
        • ddSwapAny() +
        • ddSiftingAux() +
        • ddSiftingUp() +
        • ddSiftingDown() +
        • ddSiftingBackward() +
        • ddReorderPreprocess() +
        • ddReorderPostprocess() +
        • ddShuffle() +
        • ddSiftUp() +
        • bddFixTree() +

        +

        +
        Cudd_ReduceHeap() +
        Main dynamic reordering routine. + +
        Cudd_ShuffleHeap() +
        Reorders variables according to given permutation. + +
        cuddDynamicAllocNode() +
        Dynamically allocates a Node. + +
        cuddSifting() +
        Implementation of Rudell's sifting algorithm. + +
        cuddSwapping() +
        Reorders variables by a sequence of (non-adjacent) swaps. + +
        cuddNextHigh() +
        Finds the next subtable with a larger index. + +
        cuddNextLow() +
        Finds the next subtable with a smaller index. + +
        cuddSwapInPlace() +
        Swaps two adjacent variables. + +
        cuddBddAlignToZdd() +
        Reorders BDD variables according to the order of the ZDD + variables. + +
        ddUniqueCompare() +
        Comparison function used by qsort. + +
        ddSwapAny() +
        Swaps any two variables. + +
        ddSiftingAux() +
        Given xLow <= x <= xHigh moves x up and down between the + boundaries. + +
        ddSiftingUp() +
        Sifts a variable up. + +
        ddSiftingDown() +
        Sifts a variable down. + +
        ddSiftingBackward() +
        Given a set of moves, returns the DD heap to the position + giving the minimum size. + +
        ddReorderPreprocess() +
        Prepares the DD heap for dynamic reordering. + +
        ddReorderPostprocess() +
        Cleans up at the end of reordering. + +
        ddShuffle() +
        Reorders variables according to a given permutation. + +
        ddSiftUp() +
        Moves one variable up. + +
        bddFixTree() +
        Fixes the BDD variable group tree after a shuffle. + +
        ddUpdateMtrTree() +
        Updates the BDD variable group tree before a shuffle. + +
        ddCheckPermuation() +
        Checks the BDD variable group tree before a shuffle. + +
        +
        +

        cuddSat.c

        +Functions for the solution of satisfiability related + problems.

        +By: Seh-Woong Jeong, Fabio Somenzi

        +External procedures included in this file: +

          +
        • Cudd_Eval() +
        • Cudd_ShortestPath() +
        • Cudd_LargestCube() +
        • Cudd_ShortestLength() +
        • Cudd_Decreasing() +
        • Cudd_Increasing() +
        • Cudd_EquivDC() +
        • Cudd_bddLeqUnless() +
        • Cudd_EqualSupNorm() +
        • Cudd_bddMakePrime() +
        + Internal procedures included in this module: +
          +
        • cuddBddMakePrime() +
        + Static procedures included in this module: +
          +
        • freePathPair() +
        • getShortest() +
        • getPath() +
        • getLargest() +
        • getCube() +

        +

        +
        Cudd_Eval() +
        Returns the value of a DD for a given variable assignment. + +
        Cudd_ShortestPath() +
        Finds a shortest path in a DD. + +
        Cudd_LargestCube() +
        Finds a largest cube in a DD. + +
        Cudd_ShortestLength() +
        Find the length of the shortest path(s) in a DD. + +
        Cudd_Decreasing() +
        Determines whether a BDD is negative unate in a + variable. + +
        Cudd_Increasing() +
        Determines whether a BDD is positive unate in a + variable. + +
        Cudd_EquivDC() +
        Tells whether F and G are identical wherever D is 0. + +
        Cudd_bddLeqUnless() +
        Tells whether f is less than of equal to G unless D is 1. + +
        Cudd_EqualSupNorm() +
        Compares two ADDs for equality within tolerance. + +
        Cudd_bddMakePrime() +
        Expands cube to a prime implicant of f. + +
        cuddBddMakePrime() +
        Performs the recursive step of Cudd_bddMakePrime. + +
        freePathPair() +
        Frees the entries of the visited symbol table. + +
        getShortest() +
        Finds the length of the shortest path(s) in a DD. + +
        getPath() +
        Build a BDD for a shortest path of f. + +
        getLargest() +
        Finds the size of the largest cube(s) in a DD. + +
        getCube() +
        Build a BDD for a largest cube of f. + +
        +
        +

        cuddSign.c

        +Computation of signatures.

        +By: Fabio Somenzi

        +External procedures included in this module: +

          +
        • Cudd_CofMinterm(); +
        + Static procedures included in this module: +
          +
        • ddCofMintermAux() +

        +

        +
        Cudd_CofMinterm() +
        Computes the fraction of minterms in the on-set of all the + positive cofactors of a BDD or ADD. + +
        ddCofMintermAux() +
        Recursive Step for Cudd_CofMinterm function. + +
        +
        +

        cuddSolve.c

        +Boolean equation solver and related functions.

        +By: Balakrishna Kumthekar

        +External functions included in this modoule: +

          +
        • Cudd_SolveEqn() +
        • Cudd_VerifySol() +
        + Internal functions included in this module: +
          +
        • cuddSolveEqnRecur() +
        • cuddVerifySol() +

        +

        +
        Cudd_SolveEqn() +
        Implements the solution of F(x,y) = 0. + +
        Cudd_VerifySol() +
        Checks the solution of F(x,y) = 0. + +
        cuddSolveEqnRecur() +
        Implements the recursive step of Cudd_SolveEqn. + +
        cuddVerifySol() +
        Implements the recursive step of Cudd_VerifySol. + +
        +
        +

        cuddSplit.c

        +Returns a subset of minterms from a boolean function.

        +By: Balakrishna Kumthekar

        +External functions included in this modoule: +

          +
        • Cudd_SplitSet() +
        + Internal functions included in this module: +
          +
        • cuddSplitSetRecur() + + Static functions included in this module: +
            +
          • selectMintermsFromUniverse() +
          • mintermsFromUniverse() +
          • bddAnnotateMintermCount() +

          +

          +
          Cudd_SplitSet() +
          Returns m minterms from a BDD. + +
          cuddSplitSetRecur() +
          Implements the recursive step of Cudd_SplitSet. + +
          selectMintermsFromUniverse() +
          This function prepares an array of variables which have not been + encountered so far when traversing the procedure cuddSplitSetRecur. + +
          mintermsFromUniverse() +
          Recursive procedure to extract n mintems from constant 1. + +
          bddAnnotateMintermCount() +
          Annotates every node in the BDD node with its minterm count. + +
          +
          +

          cuddSubsetHB.c

          +Procedure to subset the given BDD by choosing the heavier + branches.

          +By: Kavita Ravi

          +External procedures provided by this module: +

            +
          • Cudd_SubsetHeavyBranch() +
          • Cudd_SupersetHeavyBranch() +
          + Internal procedures included in this module: +
            +
          • cuddSubsetHeavyBranch() +
          + Static procedures included in this module: +
            +
          • ResizeCountMintermPages(); +
          • ResizeNodeDataPages() +
          • ResizeCountNodePages() +
          • SubsetCountMintermAux() +
          • SubsetCountMinterm() +
          • SubsetCountNodesAux() +
          • SubsetCountNodes() +
          • BuildSubsetBdd() +

          +

          See AlsocuddSubsetSP.c +

          +
          Cudd_SubsetHeavyBranch() +
          Extracts a dense subset from a BDD with the heavy branch + heuristic. + +
          Cudd_SupersetHeavyBranch() +
          Extracts a dense superset from a BDD with the heavy branch + heuristic. + +
          cuddSubsetHeavyBranch() +
          The main procedure that returns a subset by choosing the heavier + branch in the BDD. + +
          ResizeNodeDataPages() +
          Resize the number of pages allocated to store the node data. + +
          ResizeCountMintermPages() +
          Resize the number of pages allocated to store the minterm + counts. + +
          ResizeCountNodePages() +
          Resize the number of pages allocated to store the node counts. + +
          SubsetCountMintermAux() +
          Recursively counts minterms of each node in the DAG. + +
          SubsetCountMinterm() +
          Counts minterms of each node in the DAG + +
          SubsetCountNodesAux() +
          Recursively counts the number of nodes under the dag. + Also counts the number of nodes under the lighter child of + this node. + +
          SubsetCountNodes() +
          Counts the nodes under the current node and its lighter child + +
          StoreNodes() +
          Procedure to recursively store nodes that are retained in the subset. + +
          BuildSubsetBdd() +
          Builds the subset BDD using the heavy branch method. + +
          +
          +

          cuddSubsetSP.c

          +Procedure to subset the given BDD choosing the shortest paths + (largest cubes) in the BDD.

          +By: Kavita Ravi

          +External procedures included in this module: +

            +
          • Cudd_SubsetShortPaths() +
          • Cudd_SupersetShortPaths() +
          + Internal procedures included in this module: +
            +
          • cuddSubsetShortPaths() +
          + Static procedures included in this module: +
            +
          • BuildSubsetBdd() +
          • CreatePathTable() +
          • AssessPathLength() +
          • CreateTopDist() +
          • CreateBotDist() +
          • ResizeNodeDistPages() +
          • ResizeQueuePages() +
          • stPathTableDdFree() +

          +

          See AlsocuddSubsetHB.c +

          +
          Cudd_SubsetShortPaths() +
          Extracts a dense subset from a BDD with the shortest paths + heuristic. + +
          Cudd_SupersetShortPaths() +
          Extracts a dense superset from a BDD with the shortest paths + heuristic. + +
          cuddSubsetShortPaths() +
          The outermost procedure to return a subset of the given BDD + with the shortest path lengths. + +
          ResizeNodeDistPages() +
          Resize the number of pages allocated to store the distances + related to each node. + +
          ResizeQueuePages() +
          Resize the number of pages allocated to store nodes in the BFS + traversal of the Bdd . + +
          CreateTopDist() +
          Labels each node with its shortest distance from the root + +
          CreateBotDist() +
          Labels each node with the shortest distance from the constant. + +
          CreatePathTable() +
          The outer procedure to label each node with its shortest + distance from the root and constant + +
          AssessPathLength() +
          Chooses the maximum allowable path length of nodes under the + threshold. + +
          BuildSubsetBdd() +
          Builds the BDD with nodes labeled with path length less than or equal to maxpath + +
          stPathTableDdFree() +
          Procedure to free te result dds stored in the NodeDist pages. + +
          +
          +

          cuddSymmetry.c

          +Functions for symmetry-based variable reordering.

          +By: Shipra Panda, Fabio Somenzi

          +External procedures included in this file: +

            +
          • Cudd_SymmProfile() +
          + Internal procedures included in this module: +
            +
          • cuddSymmCheck() +
          • cuddSymmSifting() +
          • cuddSymmSiftingConv() +
          + Static procedures included in this module: +
            +
          • ddSymmUniqueCompare() +
          • ddSymmSiftingAux() +
          • ddSymmSiftingConvAux() +
          • ddSymmSiftingUp() +
          • ddSymmSiftingDown() +
          • ddSymmGroupMove() +
          • ddSymmGroupMoveBackward() +
          • ddSymmSiftingBackward() +
          • ddSymmSummary() +

          +

          +
          Cudd_SymmProfile() +
          Prints statistics on symmetric variables. + +
          cuddSymmCheck() +
          Checks for symmetry of x and y. + +
          cuddSymmSifting() +
          Symmetric sifting algorithm. + +
          cuddSymmSiftingConv() +
          Symmetric sifting to convergence algorithm. + +
          ddSymmUniqueCompare() +
          Comparison function used by qsort. + +
          ddSymmSiftingAux() +
          Given xLow <= x <= xHigh moves x up and down between the + boundaries. + +
          ddSymmSiftingConvAux() +
          Given xLow <= x <= xHigh moves x up and down between the + boundaries. + +
          ddSymmSiftingUp() +
          Moves x up until either it reaches the bound (xLow) or + the size of the DD heap increases too much. + +
          ddSymmSiftingDown() +
          Moves x down until either it reaches the bound (xHigh) or + the size of the DD heap increases too much. + +
          ddSymmGroupMove() +
          Swaps two groups. + +
          ddSymmGroupMoveBackward() +
          Undoes the swap of two groups. + +
          ddSymmSiftingBackward() +
          Given a set of moves, returns the DD heap to the position + giving the minimum size. + +
          ddSymmSummary() +
          Counts numbers of symmetric variables and symmetry + groups. + +
          +
          +

          cuddTable.c

          +Unique table management functions.

          +By: Fabio Somenzi

          +External procedures included in this module: +

            +
          • Cudd_Prime() +
          + Internal procedures included in this module: +
            +
          • cuddAllocNode() +
          • cuddInitTable() +
          • cuddFreeTable() +
          • cuddGarbageCollect() +
          • cuddZddGetNode() +
          • cuddZddGetNodeIVO() +
          • cuddUniqueInter() +
          • cuddUniqueInterIVO() +
          • cuddUniqueInterZdd() +
          • cuddUniqueConst() +
          • cuddRehash() +
          • cuddShrinkSubtable() +
          • cuddInsertSubtables() +
          • cuddDestroySubtables() +
          • cuddResizeTableZdd() +
          • cuddSlowTableGrowth() +
          + Static procedures included in this module: +
            +
          • ddRehashZdd() +
          • ddResizeTable() +
          • cuddFindParent() +
          • cuddOrderedInsert() +
          • cuddOrderedThread() +
          • cuddRotateLeft() +
          • cuddRotateRight() +
          • cuddDoRebalance() +
          • cuddCheckCollisionOrdering() +

          +

          +
          Cudd_Prime() +
          Returns the next prime >= p. + +
          cuddAllocNode() +
          Fast storage allocation for DdNodes in the table. + +
          cuddInitTable() +
          Creates and initializes the unique table. + +
          cuddFreeTable() +
          Frees the resources associated to a unique table. + +
          cuddGarbageCollect() +
          Performs garbage collection on the unique tables. + +
          cuddZddGetNode() +
          Wrapper for cuddUniqueInterZdd. + +
          cuddZddGetNodeIVO() +
          Wrapper for cuddUniqueInterZdd that is independent of variable + ordering. + +
          cuddUniqueInter() +
          Checks the unique table for the existence of an internal node. + +
          cuddUniqueInterIVO() +
          Wrapper for cuddUniqueInter that is independent of variable + ordering. + +
          cuddUniqueInterZdd() +
          Checks the unique table for the existence of an internal + ZDD node. + +
          cuddUniqueConst() +
          Checks the unique table for the existence of a constant node. + +
          cuddRehash() +
          Rehashes a unique subtable. + +
          cuddShrinkSubtable() +
          Shrinks a subtable. + +
          cuddInsertSubtables() +
          Inserts n new subtables in a unique table at level. + +
          cuddDestroySubtables() +
          Destroys the n most recently created subtables in a unique table. + +
          cuddResizeTableZdd() +
          Increases the number of ZDD subtables in a unique table so + that it meets or exceeds index. + +
          cuddSlowTableGrowth() +
          Adjusts parameters of a table to slow down its growth. + +
          ddRehashZdd() +
          Rehashes a ZDD unique subtable. + +
          ddResizeTable() +
          Increases the number of subtables in a unique table so + that it meets or exceeds index. + +
          cuddFindParent() +
          Searches the subtables above node for a parent. + +
          ddFixLimits() +
          Adjusts the values of table limits. + +
          cuddOrderedInsert() +
          Inserts a DdNode in a red/black search tree. + +
          cuddOrderedThread() +
          Threads all the nodes of a search tree into a linear list. + +
          cuddRotateLeft() +
          Performs the left rotation for red/black trees. + +
          cuddRotateRight() +
          Performs the right rotation for red/black trees. + +
          cuddDoRebalance() +
          Rebalances a red/black tree. + +
          ddPatchTree() +
          Fixes a variable tree after the insertion of new subtables. + +
          cuddCheckCollisionOrdering() +
          Checks whether a collision list is ordered. + +
          ddReportRefMess() +
          Reports problem in garbage collection. + +
          +
          +

          cuddUtil.c

          +Utility functions.

          +By: Fabio Somenzi

          +External procedures included in this module: +

            +
          • Cudd_PrintMinterm() +
          • Cudd_bddPrintCover() +
          • Cudd_PrintDebug() +
          • Cudd_DagSize() +
          • Cudd_EstimateCofactor() +
          • Cudd_EstimateCofactorSimple() +
          • Cudd_SharingSize() +
          • Cudd_CountMinterm() +
          • Cudd_EpdCountMinterm() +
          • Cudd_CountPath() +
          • Cudd_CountPathsToNonZero() +
          • Cudd_Support() +
          • Cudd_SupportIndex() +
          • Cudd_SupportSize() +
          • Cudd_VectorSupport() +
          • Cudd_VectorSupportIndex() +
          • Cudd_VectorSupportSize() +
          • Cudd_ClassifySupport() +
          • Cudd_CountLeaves() +
          • Cudd_bddPickOneCube() +
          • Cudd_bddPickOneMinterm() +
          • Cudd_bddPickArbitraryMinterms() +
          • Cudd_SubsetWithMaskVars() +
          • Cudd_FirstCube() +
          • Cudd_NextCube() +
          • Cudd_bddComputeCube() +
          • Cudd_addComputeCube() +
          • Cudd_FirstNode() +
          • Cudd_NextNode() +
          • Cudd_GenFree() +
          • Cudd_IsGenEmpty() +
          • Cudd_IndicesToCube() +
          • Cudd_PrintVersion() +
          • Cudd_AverageDistance() +
          • Cudd_Random() +
          • Cudd_Srandom() +
          • Cudd_Density() +
          + Internal procedures included in this module: +
            +
          • cuddP() +
          • cuddStCountfree() +
          • cuddCollectNodes() +
          • cuddNodeArray() +
          + Static procedures included in this module: +
            +
          • dp2() +
          • ddPrintMintermAux() +
          • ddDagInt() +
          • ddCountMintermAux() +
          • ddEpdCountMintermAux() +
          • ddCountPathAux() +
          • ddSupportStep() +
          • ddClearFlag() +
          • ddLeavesInt() +
          • ddPickArbitraryMinterms() +
          • ddPickRepresentativeCube() +
          • ddEpdFree() +

          +

          +
          Cudd_PrintMinterm() +
          Prints a disjoint sum of products. + +
          Cudd_bddPrintCover() +
          Prints a sum of prime implicants of a BDD. + +
          Cudd_PrintDebug() +
          Prints to the standard output a DD and its statistics. + +
          Cudd_DagSize() +
          Counts the number of nodes in a DD. + +
          Cudd_EstimateCofactor() +
          Estimates the number of nodes in a cofactor of a DD. + +
          Cudd_EstimateCofactorSimple() +
          Estimates the number of nodes in a cofactor of a DD. + +
          Cudd_SharingSize() +
          Counts the number of nodes in an array of DDs. + +
          Cudd_CountMinterm() +
          Counts the number of minterms of a DD. + +
          Cudd_CountPath() +
          Counts the number of paths of a DD. + +
          Cudd_EpdCountMinterm() +
          Counts the number of minterms of a DD with extended precision. + +
          Cudd_CountPathsToNonZero() +
          Counts the number of paths to a non-zero terminal of a DD. + +
          Cudd_Support() +
          Finds the variables on which a DD depends. + +
          Cudd_SupportIndex() +
          Finds the variables on which a DD depends. + +
          Cudd_SupportSize() +
          Counts the variables on which a DD depends. + +
          Cudd_VectorSupport() +
          Finds the variables on which a set of DDs depends. + +
          Cudd_VectorSupportIndex() +
          Finds the variables on which a set of DDs depends. + +
          Cudd_VectorSupportSize() +
          Counts the variables on which a set of DDs depends. + +
          Cudd_ClassifySupport() +
          Classifies the variables in the support of two DDs. + +
          Cudd_CountLeaves() +
          Counts the number of leaves in a DD. + +
          Cudd_bddPickOneCube() +
          Picks one on-set cube randomly from the given DD. + +
          Cudd_bddPickOneMinterm() +
          Picks one on-set minterm randomly from the given DD. + +
          Cudd_bddPickArbitraryMinterms() +
          Picks k on-set minterms evenly distributed from given DD. + +
          Cudd_SubsetWithMaskVars() +
          Extracts a subset from a BDD. + +
          Cudd_FirstCube() +
          Finds the first cube of a decision diagram. + +
          Cudd_NextCube() +
          Generates the next cube of a decision diagram onset. + +
          Cudd_FirstPrime() +
          Finds the first prime of a Boolean function. + +
          Cudd_NextPrime() +
          Generates the next prime of a Boolean function. + +
          Cudd_bddComputeCube() +
          Computes the cube of an array of BDD variables. + +
          Cudd_addComputeCube() +
          Computes the cube of an array of ADD variables. + +
          Cudd_CubeArrayToBdd() +
          Builds the BDD of a cube from a positional array. + +
          Cudd_BddToCubeArray() +
          Builds a positional array from the BDD of a cube. + +
          Cudd_FirstNode() +
          Finds the first node of a decision diagram. + +
          Cudd_NextNode() +
          Finds the next node of a decision diagram. + +
          Cudd_GenFree() +
          Frees a CUDD generator. + +
          Cudd_IsGenEmpty() +
          Queries the status of a generator. + +
          Cudd_IndicesToCube() +
          Builds a cube of BDD variables from an array of indices. + +
          Cudd_PrintVersion() +
          Prints the package version number. + +
          Cudd_AverageDistance() +
          Computes the average distance between adjacent nodes. + +
          Cudd_Random() +
          Portable random number generator. + +
          Cudd_Srandom() +
          Initializer for the portable random number generator. + +
          Cudd_Density() +
          Computes the density of a BDD or ADD. + +
          Cudd_OutOfMem() +
          Warns that a memory allocation failed. + +
          cuddP() +
          Prints a DD to the standard output. One line per node is + printed. + +
          cuddStCountfree() +
          Frees the memory used to store the minterm counts recorded + in the visited table. + +
          cuddCollectNodes() +
          Recursively collects all the nodes of a DD in a symbol + table. + +
          cuddNodeArray() +
          Recursively collects all the nodes of a DD in an array. + +
          dp2() +
          Performs the recursive step of cuddP. + +
          ddPrintMintermAux() +
          Performs the recursive step of Cudd_PrintMinterm. + +
          ddDagInt() +
          Performs the recursive step of Cudd_DagSize. + +
          cuddNodeArrayRecur() +
          Performs the recursive step of cuddNodeArray. + +
          cuddEstimateCofactor() +
          Performs the recursive step of Cudd_CofactorEstimate. + +
          cuddUniqueLookup() +
          Checks the unique table for the existence of an internal node. + +
          cuddEstimateCofactorSimple() +
          Performs the recursive step of Cudd_CofactorEstimateSimple. + +
          ddCountMintermAux() +
          Performs the recursive step of Cudd_CountMinterm. + +
          ddCountPathAux() +
          Performs the recursive step of Cudd_CountPath. + +
          ddEpdCountMintermAux() +
          Performs the recursive step of Cudd_EpdCountMinterm. + +
          ddCountPathsToNonZero() +
          Performs the recursive step of Cudd_CountPathsToNonZero. + +
          ddSupportStep() +
          Performs the recursive step of Cudd_Support. + +
          ddClearFlag() +
          Performs a DFS from f, clearing the LSB of the next + pointers. + +
          ddLeavesInt() +
          Performs the recursive step of Cudd_CountLeaves. + +
          ddPickArbitraryMinterms() +
          Performs the recursive step of Cudd_bddPickArbitraryMinterms. + +
          ddPickRepresentativeCube() +
          Finds a representative cube of a BDD. + +
          ddEpdFree() +
          Frees the memory used to store the minterm counts recorded + in the visited table. + +
          +
          +

          cuddWindow.c

          +Functions for variable reordering by window permutation.

          +By: Fabio Somenzi

          +Internal procedures included in this module: +

            +
          • cuddWindowReorder() +
          + Static procedures included in this module: +
            +
          • ddWindow2() +
          • ddWindowConv2() +
          • ddPermuteWindow3() +
          • ddWindow3() +
          • ddWindowConv3() +
          • ddPermuteWindow4() +
          • ddWindow4() +
          • ddWindowConv4() +

          +

          +
          cuddWindowReorder() +
          Reorders by applying the method of the sliding window. + +
          ddWindow2() +
          Reorders by applying a sliding window of width 2. + +
          ddWindowConv2() +
          Reorders by repeatedly applying a sliding window of width 2. + +
          ddPermuteWindow3() +
          Tries all the permutations of the three variables between + x and x+2 and retains the best. + +
          ddWindow3() +
          Reorders by applying a sliding window of width 3. + +
          ddWindowConv3() +
          Reorders by repeatedly applying a sliding window of width 3. + +
          ddPermuteWindow4() +
          Tries all the permutations of the four variables between w + and w+3 and retains the best. + +
          ddWindow4() +
          Reorders by applying a sliding window of width 4. + +
          ddWindowConv4() +
          Reorders by repeatedly applying a sliding window of width 4. + +
          +
          +

          cuddZddCount.c

          +Procedures to count the number of minterms of a ZDD.

          +By: Hyong-Kyoon Shin, In-Ho Moon

          +External procedures included in this module: +

            +
          • Cudd_zddCount(); +
          • Cudd_zddCountDouble(); +
          + Internal procedures included in this module: +
            +
          + Static procedures included in this module: +
            +
          • cuddZddCountStep(); +
          • cuddZddCountDoubleStep(); +
          • st_zdd_count_dbl_free() +
          • st_zdd_countfree() +

          +

          +
          Cudd_zddCount() +
          Counts the number of minterms in a ZDD. + +
          Cudd_zddCountDouble() +
          Counts the number of minterms of a ZDD. + +
          cuddZddCountStep() +
          Performs the recursive step of Cudd_zddCount. + +
          cuddZddCountDoubleStep() +
          Performs the recursive step of Cudd_zddCountDouble. + +
          st_zdd_countfree() +
          Frees the memory associated with the computed table of + Cudd_zddCount. + +
          st_zdd_count_dbl_free() +
          Frees the memory associated with the computed table of + Cudd_zddCountDouble. + +
          +
          +

          cuddZddFuncs.c

          +Functions to manipulate covers represented as ZDDs.

          +By: In-Ho Moon

          +External procedures included in this module: +

            +
          • Cudd_zddProduct(); +
          • Cudd_zddUnateProduct(); +
          • Cudd_zddWeakDiv(); +
          • Cudd_zddWeakDivF(); +
          • Cudd_zddDivide(); +
          • Cudd_zddDivideF(); +
          • Cudd_zddComplement(); +
          + Internal procedures included in this module: +
            +
          • cuddZddProduct(); +
          • cuddZddUnateProduct(); +
          • cuddZddWeakDiv(); +
          • cuddZddWeakDivF(); +
          • cuddZddDivide(); +
          • cuddZddDivideF(); +
          • cuddZddGetCofactors3() +
          • cuddZddGetCofactors2() +
          • cuddZddComplement(); +
          • cuddZddGetPosVarIndex(); +
          • cuddZddGetNegVarIndex(); +
          • cuddZddGetPosVarLevel(); +
          • cuddZddGetNegVarLevel(); +
          + Static procedures included in this module: +
            +

          +

          +
          Cudd_zddProduct() +
          Computes the product of two covers represented by ZDDs. + +
          Cudd_zddUnateProduct() +
          Computes the product of two unate covers. + +
          Cudd_zddWeakDiv() +
          Applies weak division to two covers. + +
          Cudd_zddDivide() +
          Computes the quotient of two unate covers. + +
          Cudd_zddWeakDivF() +
          Modified version of Cudd_zddWeakDiv. + +
          Cudd_zddDivideF() +
          Modified version of Cudd_zddDivide. + +
          Cudd_zddComplement() +
          Computes a complement cover for a ZDD node. + +
          cuddZddProduct() +
          Performs the recursive step of Cudd_zddProduct. + +
          cuddZddUnateProduct() +
          Performs the recursive step of Cudd_zddUnateProduct. + +
          cuddZddWeakDiv() +
          Performs the recursive step of Cudd_zddWeakDiv. + +
          cuddZddWeakDivF() +
          Performs the recursive step of Cudd_zddWeakDivF. + +
          cuddZddDivide() +
          Performs the recursive step of Cudd_zddDivide. + +
          cuddZddDivideF() +
          Performs the recursive step of Cudd_zddDivideF. + +
          cuddZddGetCofactors3() +
          Computes the three-way decomposition of f w.r.t. v. + +
          cuddZddGetCofactors2() +
          Computes the two-way decomposition of f w.r.t. v. + +
          cuddZddComplement() +
          Computes a complement of a ZDD node. + +
          cuddZddGetPosVarIndex() +
          Returns the index of positive ZDD variable. + +
          cuddZddGetNegVarIndex() +
          Returns the index of negative ZDD variable. + +
          cuddZddGetPosVarLevel() +
          Returns the level of positive ZDD variable. + +
          cuddZddGetNegVarLevel() +
          Returns the level of negative ZDD variable. + +
          +
          +

          cuddZddGroup.c

          +Functions for ZDD group sifting.

          +By: Fabio Somenzi

          +External procedures included in this file: +

            +
          • Cudd_MakeZddTreeNode() +
          + Internal procedures included in this file: +
            +
          • cuddZddTreeSifting() +
          + Static procedures included in this module: +
            +
          • zddTreeSiftingAux() +
          • zddCountInternalMtrNodes() +
          • zddReorderChildren() +
          • zddFindNodeHiLo() +
          • zddUniqueCompareGroup() +
          • zddGroupSifting() +
          • zddGroupSiftingAux() +
          • zddGroupSiftingUp() +
          • zddGroupSiftingDown() +
          • zddGroupMove() +
          • zddGroupMoveBackward() +
          • zddGroupSiftingBackward() +
          • zddMergeGroups() +

          +

          +
          Cudd_MakeZddTreeNode() +
          Creates a new ZDD variable group. + +
          cuddZddTreeSifting() +
          Tree sifting algorithm for ZDDs. + +
          zddTreeSiftingAux() +
          Visits the group tree and reorders each group. + +
          zddCountInternalMtrNodes() +
          Counts the number of internal nodes of the group tree. + +
          zddReorderChildren() +
          Reorders the children of a group tree node according to + the options. + +
          zddFindNodeHiLo() +
          Finds the lower and upper bounds of the group represented + by treenode. + +
          zddUniqueCompareGroup() +
          Comparison function used by qsort. + +
          zddGroupSifting() +
          Sifts from treenode->low to treenode->high. + +
          zddGroupSiftingAux() +
          Sifts one variable up and down until it has taken all + positions. Checks for aggregation. + +
          zddGroupSiftingUp() +
          Sifts up a variable until either it reaches position xLow + or the size of the DD heap increases too much. + +
          zddGroupSiftingDown() +
          Sifts down a variable until it reaches position xHigh. + +
          zddGroupMove() +
          Swaps two groups and records the move. + +
          zddGroupMoveBackward() +
          Undoes the swap two groups. + +
          zddGroupSiftingBackward() +
          Determines the best position for a variables and returns + it there. + +
          zddMergeGroups() +
          Merges groups in the DD table. + +
          +
          +

          cuddZddIsop.c

          +Functions to find irredundant SOP covers as ZDDs from BDDs.

          +By: In-Ho Moon

          +External procedures included in this module: +

            +
          • Cudd_bddIsop() +
          • Cudd_zddIsop() +
          • Cudd_MakeBddFromZddCover() +
          + Internal procedures included in this module: +
            +
          • cuddBddIsop() +
          • cuddZddIsop() +
          • cuddMakeBddFromZddCover() +
          + Static procedures included in this module: +
            +

          +

          +
          Cudd_zddIsop() +
          Computes an ISOP in ZDD form from BDDs. + +
          Cudd_bddIsop() +
          Computes a BDD in the interval between L and U with a + simple sum-of-produuct cover. + +
          Cudd_MakeBddFromZddCover() +
          Converts a ZDD cover to a BDD graph. + +
          cuddZddIsop() +
          Performs the recursive step of Cudd_zddIsop. + +
          cuddBddIsop() +
          Performs the recursive step of Cudd_bddIsop. + +
          cuddMakeBddFromZddCover() +
          Converts a ZDD cover to a BDD graph. + +
          +
          +

          cuddZddLin.c

          +Procedures for dynamic variable ordering of ZDDs.

          +By: Fabio Somenzi

          +Internal procedures included in this module: +

            +
          • cuddZddLinearSifting() +
          + Static procedures included in this module: +
            +
          • cuddZddLinearInPlace() +
          • cuddZddLinerAux() +
          • cuddZddLinearUp() +
          • cuddZddLinearDown() +
          • cuddZddLinearBackward() +
          • cuddZddUndoMoves() +

          +

          See AlsocuddLinear.c +cuddZddReord.c +

          +
          cuddZddLinearSifting() +
          Implementation of the linear sifting algorithm for ZDDs. + +
          cuddZddLinearInPlace() +
          Linearly combines two adjacent variables. + +
          cuddZddLinearAux() +
          Given xLow <= x <= xHigh moves x up and down between the + boundaries. + +
          cuddZddLinearUp() +
          Sifts a variable up applying the XOR transformation. + +
          cuddZddLinearDown() +
          Sifts a variable down and applies the XOR transformation. + +
          cuddZddLinearBackward() +
          Given a set of moves, returns the ZDD heap to the position + giving the minimum size. + +
          cuddZddUndoMoves() +
          Given a set of moves, returns the ZDD heap to the order + in effect before the moves. + +
          +
          +

          cuddZddMisc.c

          +Miscellaneous utility functions for ZDDs.

          +By: Hyong-Kyoon Shin, In-Ho Moon

          +External procedures included in this module: +

            +
          • Cudd_zddDagSize() +
          • Cudd_zddCountMinterm() +
          • Cudd_zddPrintSubtable() +
          + Internal procedures included in this module: +
            +
          + Static procedures included in this module: +
            +
          • cuddZddDagInt() +

          +

          +
          Cudd_zddDagSize() +
          Counts the number of nodes in a ZDD. + +
          Cudd_zddCountMinterm() +
          Counts the number of minterms of a ZDD. + +
          Cudd_zddPrintSubtable() +
          Prints the ZDD table. + +
          cuddZddDagInt() +
          Performs the recursive step of Cudd_zddDagSize. + +
          +
          +

          cuddZddPort.c

          +Functions that translate BDDs to ZDDs.

          +By: Hyong-kyoon Shin, In-Ho Moon

          +External procedures included in this module: +

            +
          • Cudd_zddPortFromBdd() +
          • Cudd_zddPortToBdd() +
          + Internal procedures included in this module: +
            +
          + Static procedures included in this module: +
            +
          • zddPortFromBddStep() +
          • zddPortToBddStep() +

          +

          +
          Cudd_zddPortFromBdd() +
          Converts a BDD into a ZDD. + +
          Cudd_zddPortToBdd() +
          Converts a ZDD into a BDD. + +
          zddPortFromBddStep() +
          Performs the recursive step of Cudd_zddPortFromBdd. + +
          zddPortToBddStep() +
          Performs the recursive step of Cudd_zddPortToBdd. + +
          +
          +

          cuddZddReord.c

          +Procedures for dynamic variable ordering of ZDDs.

          +By: Hyong-Kyoon Shin, In-Ho Moon

          +External procedures included in this module: +

            +
          • Cudd_zddReduceHeap() +
          • Cudd_zddShuffleHeap() +
          + Internal procedures included in this module: +
            +
          • cuddZddAlignToBdd() +
          • cuddZddNextHigh() +
          • cuddZddNextLow() +
          • cuddZddUniqueCompare() +
          • cuddZddSwapInPlace() +
          • cuddZddSwapping() +
          • cuddZddSifting() +
          + Static procedures included in this module: +
            +
          • zddSwapAny() +
          • cuddZddSiftingAux() +
          • cuddZddSiftingUp() +
          • cuddZddSiftingDown() +
          • cuddZddSiftingBackward() +
          • zddReorderPreprocess() +
          • zddReorderPostprocess() +
          • zddShuffle() +
          • zddSiftUp() +

          +

          +
          Cudd_zddReduceHeap() +
          Main dynamic reordering routine for ZDDs. + +
          Cudd_zddShuffleHeap() +
          Reorders ZDD variables according to given permutation. + +
          cuddZddAlignToBdd() +
          Reorders ZDD variables according to the order of the BDD + variables. + +
          cuddZddNextHigh() +
          Finds the next subtable with a larger index. + +
          cuddZddNextLow() +
          Finds the next subtable with a smaller index. + +
          cuddZddUniqueCompare() +
          Comparison function used by qsort. + +
          cuddZddSwapInPlace() +
          Swaps two adjacent variables. + +
          cuddZddSwapping() +
          Reorders variables by a sequence of (non-adjacent) swaps. + +
          cuddZddSifting() +
          Implementation of Rudell's sifting algorithm. + +
          zddSwapAny() +
          Swaps any two variables. + +
          cuddZddSiftingAux() +
          Given xLow <= x <= xHigh moves x up and down between the + boundaries. + +
          cuddZddSiftingUp() +
          Sifts a variable up. + +
          cuddZddSiftingDown() +
          Sifts a variable down. + +
          cuddZddSiftingBackward() +
          Given a set of moves, returns the ZDD heap to the position + giving the minimum size. + +
          zddReorderPreprocess() +
          Prepares the ZDD heap for dynamic reordering. + +
          zddReorderPostprocess() +
          Shrinks almost empty ZDD subtables at the end of reordering + to guarantee that they have a reasonable load factor. + +
          zddShuffle() +
          Reorders ZDD variables according to a given permutation. + +
          zddSiftUp() +
          Moves one ZDD variable up. + +
          zddFixTree() +
          Fixes the ZDD variable group tree after a shuffle. + +
          +
          +

          cuddZddSetop.c

          +Set operations on ZDDs.

          +By: Hyong-Kyoon Shin, In-Ho Moon

          +External procedures included in this module: +

            +
          • Cudd_zddIte() +
          • Cudd_zddUnion() +
          • Cudd_zddIntersect() +
          • Cudd_zddDiff() +
          • Cudd_zddDiffConst() +
          • Cudd_zddSubset1() +
          • Cudd_zddSubset0() +
          • Cudd_zddChange() +
          + Internal procedures included in this module: +
            +
          • cuddZddIte() +
          • cuddZddUnion() +
          • cuddZddIntersect() +
          • cuddZddDiff() +
          • cuddZddChangeAux() +
          • cuddZddSubset1() +
          • cuddZddSubset0() +
          + Static procedures included in this module: +
            +
          • zdd_subset1_aux() +
          • zdd_subset0_aux() +
          • zddVarToConst() +

          +

          +
          Cudd_zddIte() +
          Computes the ITE of three ZDDs. + +
          Cudd_zddUnion() +
          Computes the union of two ZDDs. + +
          Cudd_zddIntersect() +
          Computes the intersection of two ZDDs. + +
          Cudd_zddDiff() +
          Computes the difference of two ZDDs. + +
          Cudd_zddDiffConst() +
          Performs the inclusion test for ZDDs (P implies Q). + +
          Cudd_zddSubset1() +
          Computes the positive cofactor of a ZDD w.r.t. a variable. + +
          Cudd_zddSubset0() +
          Computes the negative cofactor of a ZDD w.r.t. a variable. + +
          Cudd_zddChange() +
          Substitutes a variable with its complement in a ZDD. + +
          cuddZddIte() +
          Performs the recursive step of Cudd_zddIte. + +
          cuddZddUnion() +
          Performs the recursive step of Cudd_zddUnion. + +
          cuddZddIntersect() +
          Performs the recursive step of Cudd_zddIntersect. + +
          cuddZddDiff() +
          Performs the recursive step of Cudd_zddDiff. + +
          cuddZddChangeAux() +
          Performs the recursive step of Cudd_zddChange. + +
          cuddZddSubset1() +
          Computes the positive cofactor of a ZDD w.r.t. a variable. + +
          cuddZddSubset0() +
          Computes the negative cofactor of a ZDD w.r.t. a variable. + +
          cuddZddChange() +
          Substitutes a variable with its complement in a ZDD. + +
          zdd_subset1_aux() +
          Performs the recursive step of Cudd_zddSubset1. + +
          zdd_subset0_aux() +
          Performs the recursive step of Cudd_zddSubset0. + +
          zddVarToConst() +
          Replaces variables with constants if possible (part of + canonical form). + +
          +
          +

          cuddZddSymm.c

          +Functions for symmetry-based ZDD variable reordering.

          +By: Hyong-Kyoon Shin, In-Ho Moon

          +External procedures included in this module: +

            +
          • Cudd_zddSymmProfile() +
          + Internal procedures included in this module: +
            +
          • cuddZddSymmCheck() +
          • cuddZddSymmSifting() +
          • cuddZddSymmSiftingConv() +
          + Static procedures included in this module: +
            +
          • cuddZddUniqueCompare() +
          • cuddZddSymmSiftingAux() +
          • cuddZddSymmSiftingConvAux() +
          • cuddZddSymmSifting_up() +
          • cuddZddSymmSifting_down() +
          • zdd_group_move() +
          • cuddZddSymmSiftingBackward() +
          • zdd_group_move_backward() +

          +

          See AlsocuddSymmetry.c +

          +
          Cudd_zddSymmProfile() +
          Prints statistics on symmetric ZDD variables. + +
          cuddZddSymmCheck() +
          Checks for symmetry of x and y. + +
          cuddZddSymmSifting() +
          Symmetric sifting algorithm for ZDDs. + +
          cuddZddSymmSiftingConv() +
          Symmetric sifting to convergence algorithm for ZDDs. + +
          cuddZddSymmSiftingAux() +
          Given x_low <= x <= x_high moves x up and down between the + boundaries. + +
          cuddZddSymmSiftingConvAux() +
          Given x_low <= x <= x_high moves x up and down between the + boundaries. + +
          cuddZddSymmSifting_up() +
          Moves x up until either it reaches the bound (x_low) or + the size of the ZDD heap increases too much. + +
          cuddZddSymmSifting_down() +
          Moves x down until either it reaches the bound (x_high) or + the size of the ZDD heap increases too much. + +
          cuddZddSymmSiftingBackward() +
          Given a set of moves, returns the ZDD heap to the position + giving the minimum size. + +
          zdd_group_move() +
          Swaps two groups. + +
          zdd_group_move_backward() +
          Undoes the swap of two groups. + +
          cuddZddSymmSummary() +
          Counts numbers of symmetric variables and symmetry + groups. + +
          +
          +

          cuddZddUtil.c

          +Utility functions for ZDDs.

          +By: Hyong-Kyoon Shin, In-Ho Moon, Fabio Somenzi

          +External procedures included in this module: +

            +
          • Cudd_zddPrintMinterm() +
          • Cudd_zddPrintCover() +
          • Cudd_zddPrintDebug() +
          • Cudd_zddFirstPath() +
          • Cudd_zddNextPath() +
          • Cudd_zddCoverPathToString() +
          • Cudd_zddDumpDot() +
          + Internal procedures included in this module: +
            +
          • cuddZddP() +
          + Static procedures included in this module: +
            +
          • zp2() +
          • zdd_print_minterm_aux() +
          • zddPrintCoverAux() +

          +

          +
          Cudd_zddPrintMinterm() +
          Prints a disjoint sum of product form for a ZDD. + +
          Cudd_zddPrintCover() +
          Prints a sum of products from a ZDD representing a cover. + +
          Cudd_zddPrintDebug() +
          Prints to the standard output a ZDD and its statistics. + +
          Cudd_zddFirstPath() +
          Finds the first path of a ZDD. + +
          Cudd_zddNextPath() +
          Generates the next path of a ZDD. + +
          Cudd_zddCoverPathToString() +
          Converts a path of a ZDD representing a cover to a string. + +
          Cudd_zddDumpDot() +
          Writes a dot file representing the argument ZDDs. + +
          cuddZddP() +
          Prints a ZDD to the standard output. One line per node is + printed. + +
          zp2() +
          Performs the recursive step of cuddZddP. + +
          zdd_print_minterm_aux() +
          Performs the recursive step of Cudd_zddPrintMinterm. + +
          zddPrintCoverAux() +
          Performs the recursive step of Cudd_zddPrintCover. + +
          +
          +Last updated on 20090220 23h06 + diff --git a/distr/cudd/doc/cuddDesc.html b/distr/cudd/doc/cuddDesc.html new file mode 100644 index 0000000..bfdf695 --- /dev/null +++ b/distr/cudd/doc/cuddDesc.html @@ -0,0 +1,32 @@ + +The cudd package: Overview + + +

          The cudd package

          +

          The University of Colorado decision diagram package.

          +

          By Fabio Somenzi

          + + + +
          + +External functions and data strucures of the CUDD package. +
            +
          • To turn on the gathering of statistics, define DD_STATS. +
          • To link with mis, define DD_MIS. +
          + Modified by Abelardo Pardo to interface it to VIS. + +
          + +Last updated on 20090220 23h06 + + + diff --git a/distr/cudd/doc/cuddExt.html b/distr/cudd/doc/cuddExt.html new file mode 100644 index 0000000..6dd3d20 --- /dev/null +++ b/distr/cudd/doc/cuddExt.html @@ -0,0 +1,13 @@ + +The cudd Package for Programmers + + + + + + + + + + + diff --git a/distr/cudd/doc/cuddExtAbs.html b/distr/cudd/doc/cuddExtAbs.html new file mode 100644 index 0000000..de6372b --- /dev/null +++ b/distr/cudd/doc/cuddExtAbs.html @@ -0,0 +1,1325 @@ + +cudd package abstract + + + + + +
          +
          Cudd_AddHook() +
          Adds a function to a hook. + +
          Cudd_ApaAdd() +
          Adds two arbitrary precision integers. + +
          Cudd_ApaCompareRatios() +
          Compares the ratios of two arbitrary precision integers to two + unsigned ints. + +
          Cudd_ApaCompare() +
          Compares two arbitrary precision integers. + +
          Cudd_ApaCopy() +
          Makes a copy of an arbitrary precision integer. + +
          Cudd_ApaCountMinterm() +
          Counts the number of minterms of a DD. + +
          Cudd_ApaIntDivision() +
          Divides an arbitrary precision integer by an integer. + +
          Cudd_ApaNumberOfDigits() +
          Finds the number of digits for an arbitrary precision + integer. + +
          Cudd_ApaPowerOfTwo() +
          Sets an arbitrary precision integer to a power of two. + +
          Cudd_ApaPrintDecimal() +
          Prints an arbitrary precision integer in decimal format. + +
          Cudd_ApaPrintDensity() +
          Prints the density of a BDD or ADD using + arbitrary precision arithmetic. + +
          Cudd_ApaPrintExponential() +
          Prints an arbitrary precision integer in exponential format. + +
          Cudd_ApaPrintHex() +
          Prints an arbitrary precision integer in hexadecimal format. + +
          Cudd_ApaPrintMintermExp() +
          Prints the number of minterms of a BDD or ADD in exponential + format using arbitrary precision arithmetic. + +
          Cudd_ApaPrintMinterm() +
          Prints the number of minterms of a BDD or ADD using + arbitrary precision arithmetic. + +
          Cudd_ApaSetToLiteral() +
          Sets an arbitrary precision integer to a one-digit literal. + +
          Cudd_ApaShiftRight() +
          Shifts right an arbitrary precision integer by one binary + place. + +
          Cudd_ApaShortDivision() +
          Divides an arbitrary precision integer by a digit. + +
          Cudd_ApaSubtract() +
          Subtracts two arbitrary precision integers. + +
          Cudd_AutodynDisableZdd() +
          Disables automatic dynamic reordering of ZDDs. + +
          Cudd_AutodynDisable() +
          Disables automatic dynamic reordering. + +
          Cudd_AutodynEnableZdd() +
          Enables automatic dynamic reordering of ZDDs. + +
          Cudd_AutodynEnable() +
          Enables automatic dynamic reordering of BDDs and ADDs. + +
          Cudd_AverageDistance() +
          Computes the average distance between adjacent nodes. + +
          Cudd_BddToAdd() +
          Converts a BDD to a 0-1 ADD. + +
          Cudd_BddToCubeArray() +
          Builds a positional array from the BDD of a cube. + +
          Cudd_BiasedOverApprox() +
          Extracts a dense superset from a BDD with the biased + underapproximation method. + +
          Cudd_BiasedUnderApprox() +
          Extracts a dense subset from a BDD with the biased + underapproximation method. + +
          Cudd_CProjection() +
          Computes the compatible projection of R w.r.t. cube Y. + +
          Cudd_CheckKeys() +
          Checks for several conditions that should not occur. + +
          Cudd_CheckZeroRef() +
          Checks the unique table for nodes with non-zero reference + counts. + +
          Cudd_ClassifySupport() +
          Classifies the variables in the support of two DDs. + +
          Cudd_ClearErrorCode() +
          Clear the error code of a manager. + +
          Cudd_CofMinterm() +
          Computes the fraction of minterms in the on-set of all the + positive cofactors of a BDD or ADD. + +
          Cudd_Cofactor() +
          Computes the cofactor of f with respect to g. + +
          Cudd_CountLeaves() +
          Counts the number of leaves in a DD. + +
          Cudd_CountMinterm() +
          Counts the number of minterms of a DD. + +
          Cudd_CountPathsToNonZero() +
          Counts the number of paths to a non-zero terminal of a DD. + +
          Cudd_CountPath() +
          Counts the number of paths of a DD. + +
          Cudd_CubeArrayToBdd() +
          Builds the BDD of a cube from a positional array. + +
          Cudd_DagSize() +
          Counts the number of nodes in a DD. + +
          Cudd_DeadAreCounted() +
          Tells whether dead nodes are counted towards triggering + reordering. + +
          Cudd_DebugCheck() +
          Checks for inconsistencies in the DD heap. + +
          Cudd_Decreasing() +
          Determines whether a BDD is negative unate in a + variable. + +
          Cudd_DelayedDerefBdd() +
          Decreases the reference count of BDD node n. + +
          Cudd_Density() +
          Computes the density of a BDD or ADD. + +
          Cudd_Deref() +
          Decreases the reference count of node. + +
          Cudd_DisableGarbageCollection() +
          Disables garbage collection. + +
          Cudd_DisableReorderingReporting() +
          Disables reporting of reordering stats. + +
          Cudd_Disequality() +
          Generates a BDD for the function x - y != c. + +
          Cudd_DumpBlifBody() +
          Writes a blif body representing the argument BDDs. + +
          Cudd_DumpBlif() +
          Writes a blif file representing the argument BDDs. + +
          Cudd_DumpDDcal() +
          Writes a DDcal file representing the argument BDDs. + +
          Cudd_DumpDaVinci() +
          Writes a daVinci file representing the argument BDDs. + +
          Cudd_DumpDot() +
          Writes a dot file representing the argument DDs. + +
          Cudd_DumpFactoredForm() +
          Writes factored forms representing the argument BDDs. + +
          Cudd_Dxygtdxz() +
          Generates a BDD for the function d(x,y) > d(x,z). + +
          Cudd_Dxygtdyz() +
          Generates a BDD for the function d(x,y) > d(y,z). + +
          Cudd_EnableGarbageCollection() +
          Enables garbage collection. + +
          Cudd_EnableReorderingReporting() +
          Enables reporting of reordering stats. + +
          Cudd_EpdCountMinterm() +
          Counts the number of minterms of a DD with extended precision. + +
          Cudd_EqualSupNorm() +
          Compares two ADDs for equality within tolerance. + +
          Cudd_EquivDC() +
          Tells whether F and G are identical wherever D is 0. + +
          Cudd_EstimateCofactorSimple() +
          Estimates the number of nodes in a cofactor of a DD. + +
          Cudd_EstimateCofactor() +
          Estimates the number of nodes in a cofactor of a DD. + +
          Cudd_Eval() +
          Returns the value of a DD for a given variable assignment. + +
          Cudd_ExpectedUsedSlots() +
          Computes the expected fraction of used slots in the unique + table. + +
          Cudd_FindEssential() +
          Finds the essential variables of a DD. + +
          Cudd_FindTwoLiteralClauses() +
          Finds the two literal clauses of a DD. + +
          Cudd_FirstCube() +
          Finds the first cube of a decision diagram. + +
          Cudd_FirstNode() +
          Finds the first node of a decision diagram. + +
          Cudd_FirstPrime() +
          Finds the first prime of a Boolean function. + +
          Cudd_FreeTree() +
          Frees the variable group tree of the manager. + +
          Cudd_FreeZddTree() +
          Frees the variable group tree of the manager. + +
          Cudd_GarbageCollectionEnabled() +
          Tells whether garbage collection is enabled. + +
          Cudd_GenFree() +
          Frees a CUDD generator. + +
          Cudd_Increasing() +
          Determines whether a BDD is positive unate in a + variable. + +
          Cudd_IndicesToCube() +
          Builds a cube of BDD variables from an array of indices. + +
          Cudd_Inequality() +
          Generates a BDD for the function x - y ≥ c. + +
          Cudd_Init() +
          Creates a new DD manager. + +
          Cudd_IsGenEmpty() +
          Queries the status of a generator. + +
          Cudd_IsInHook() +
          Checks whether a function is in a hook. + +
          Cudd_IsNonConstant() +
          Returns 1 if a DD node is not constant. + +
          Cudd_IterDerefBdd() +
          Decreases the reference count of BDD node n. + +
          Cudd_LargestCube() +
          Finds a largest cube in a DD. + +
          Cudd_MakeBddFromZddCover() +
          Converts a ZDD cover to a BDD graph. + +
          Cudd_MakeTreeNode() +
          Creates a new variable group. + +
          Cudd_MakeZddTreeNode() +
          Creates a new ZDD variable group. + +
          Cudd_MinHammingDist() +
          Returns the minimum Hamming distance between f and minterm. + +
          Cudd_NewApaNumber() +
          Allocates memory for an arbitrary precision integer. + +
          Cudd_NextCube() +
          Generates the next cube of a decision diagram onset. + +
          Cudd_NextNode() +
          Finds the next node of a decision diagram. + +
          Cudd_NextPrime() +
          Generates the next prime of a Boolean function. + +
          Cudd_NodeReadIndex() +
          Returns the index of the node. + +
          Cudd_OutOfMem() +
          Warns that a memory allocation failed. + +
          Cudd_OverApprox() +
          Extracts a dense superset from a BDD with Shiple's + underapproximation method. + +
          Cudd_Prime() +
          Returns the next prime >= p. + +
          Cudd_PrintDebug() +
          Prints to the standard output a DD and its statistics. + +
          Cudd_PrintInfo() +
          Prints out statistics and settings for a CUDD manager. + +
          Cudd_PrintLinear() +
          Prints the linear transform matrix. + +
          Cudd_PrintMinterm() +
          Prints a disjoint sum of products. + +
          Cudd_PrintTwoLiteralClauses() +
          Prints the two literal clauses of a DD. + +
          Cudd_PrintVersion() +
          Prints the package version number. + +
          Cudd_PrioritySelect() +
          Selects pairs from R using a priority function. + +
          Cudd_Quit() +
          Deletes resources associated with a DD manager. + +
          Cudd_Random() +
          Portable random number generator. + +
          Cudd_ReadArcviolation() +
          Returns the current value of the arcviolation parameter used + in group sifting. + +
          Cudd_ReadBackground() +
          Reads the background constant of the manager. + +
          Cudd_ReadCacheHits() +
          Returns the number of cache hits. + +
          Cudd_ReadCacheLookUps() +
          Returns the number of cache look-ups. + +
          Cudd_ReadCacheSlots() +
          Reads the number of slots in the cache. + +
          Cudd_ReadCacheUsedSlots() +
          Reads the fraction of used slots in the cache. + +
          Cudd_ReadDead() +
          Returns the number of dead nodes in the unique table. + +
          Cudd_ReadEpsilon() +
          Reads the epsilon parameter of the manager. + +
          Cudd_ReadErrorCode() +
          Returns the code of the last error. + +
          Cudd_ReadGarbageCollectionTime() +
          Returns the time spent in garbage collection. + +
          Cudd_ReadGarbageCollections() +
          Returns the number of times garbage collection has occurred. + +
          Cudd_ReadGroupcheck() +
          Reads the groupcheck parameter of the manager. + +
          Cudd_ReadInvPermZdd() +
          Returns the index of the ZDD variable currently in the i-th + position of the order. + +
          Cudd_ReadInvPerm() +
          Returns the index of the variable currently in the i-th + position of the order. + +
          Cudd_ReadIthClause() +
          Accesses the i-th clause of a DD. + +
          Cudd_ReadKeys() +
          Returns the number of nodes in the unique table. + +
          Cudd_ReadLinear() +
          Reads an entry of the linear transform matrix. + +
          Cudd_ReadLogicZero() +
          Returns the logic zero constant of the manager. + +
          Cudd_ReadLooseUpTo() +
          Reads the looseUpTo parameter of the manager. + +
          Cudd_ReadMaxCacheHard() +
          Reads the maxCacheHard parameter of the manager. + +
          Cudd_ReadMaxCache() +
          Returns the soft limit for the cache size. + +
          Cudd_ReadMaxGrowthAlternate() +
          Reads the maxGrowthAlt parameter of the manager. + +
          Cudd_ReadMaxGrowth() +
          Reads the maxGrowth parameter of the manager. + +
          Cudd_ReadMaxLive() +
          Reads the maximum allowed number of live nodes. + +
          Cudd_ReadMaxMemory() +
          Reads the maximum allowed memory. + +
          Cudd_ReadMemoryInUse() +
          Returns the memory in use by the manager measured in bytes. + +
          Cudd_ReadMinDead() +
          Reads the minDead parameter of the manager. + +
          Cudd_ReadMinHit() +
          Reads the hit rate that causes resizinig of the computed + table. + +
          Cudd_ReadMinusInfinity() +
          Reads the minus-infinity constant from the manager. + +
          Cudd_ReadNextReordering() +
          Returns the threshold for the next dynamic reordering. + +
          Cudd_ReadNodeCount() +
          Reports the number of nodes in BDDs and ADDs. + +
          Cudd_ReadNodesDropped() +
          Returns the number of nodes dropped. + +
          Cudd_ReadNodesFreed() +
          Returns the number of nodes freed. + +
          Cudd_ReadNumberXovers() +
          Reads the current number of crossovers used by the + genetic algorithm for reordering. + +
          Cudd_ReadOne() +
          Returns the one constant of the manager. + +
          Cudd_ReadPeakLiveNodeCount() +
          Reports the peak number of live nodes. + +
          Cudd_ReadPeakNodeCount() +
          Reports the peak number of nodes. + +
          Cudd_ReadPermZdd() +
          Returns the current position of the i-th ZDD variable in the + order. + +
          Cudd_ReadPerm() +
          Returns the current position of the i-th variable in the + order. + +
          Cudd_ReadPlusInfinity() +
          Reads the plus-infinity constant from the manager. + +
          Cudd_ReadPopulationSize() +
          Reads the current size of the population used by the + genetic algorithm for reordering. + +
          Cudd_ReadRecomb() +
          Returns the current value of the recombination parameter used + in group sifting. + +
          Cudd_ReadRecursiveCalls() +
          Returns the number of recursive calls. + +
          Cudd_ReadReorderingCycle() +
          Reads the reordCycle parameter of the manager. + +
          Cudd_ReadReorderingTime() +
          Returns the time spent in reordering. + +
          Cudd_ReadReorderings() +
          Returns the number of times reordering has occurred. + +
          Cudd_ReadSiftMaxSwap() +
          Reads the siftMaxSwap parameter of the manager. + +
          Cudd_ReadSiftMaxVar() +
          Reads the siftMaxVar parameter of the manager. + +
          Cudd_ReadSize() +
          Returns the number of BDD variables in existance. + +
          Cudd_ReadSlots() +
          Returns the total number of slots of the unique table. + +
          Cudd_ReadStderr() +
          Reads the stderr of a manager. + +
          Cudd_ReadStdout() +
          Reads the stdout of a manager. + +
          Cudd_ReadSwapSteps() +
          Reads the number of elementary reordering steps. + +
          Cudd_ReadSymmviolation() +
          Returns the current value of the symmviolation parameter used + in group sifting. + +
          Cudd_ReadTree() +
          Returns the variable group tree of the manager. + +
          Cudd_ReadUniqueLinks() +
          Returns the number of links followed in the unique table. + +
          Cudd_ReadUniqueLookUps() +
          Returns the number of look-ups in the unique table. + +
          Cudd_ReadUsedSlots() +
          Reads the fraction of used slots in the unique table. + +
          Cudd_ReadVars() +
          Returns the i-th element of the vars array. + +
          Cudd_ReadZddOne() +
          Returns the ZDD for the constant 1 function. + +
          Cudd_ReadZddSize() +
          Returns the number of ZDD variables in existance. + +
          Cudd_ReadZddTree() +
          Returns the variable group tree of the manager. + +
          Cudd_ReadZero() +
          Returns the zero constant of the manager. + +
          Cudd_RecursiveDerefZdd() +
          Decreases the reference count of ZDD node n. + +
          Cudd_RecursiveDeref() +
          Decreases the reference count of node n. + +
          Cudd_ReduceHeap() +
          Main dynamic reordering routine. + +
          Cudd_Ref() +
          Increases the reference count of a node, if it is not + saturated. + +
          Cudd_RemapOverApprox() +
          Extracts a dense superset from a BDD with the remapping + underapproximation method. + +
          Cudd_RemapUnderApprox() +
          Extracts a dense subset from a BDD with the remapping + underapproximation method. + +
          Cudd_RemoveHook() +
          Removes a function from a hook. + +
          Cudd_ReorderingReporting() +
          Returns 1 if reporting of reordering stats is enabled. + +
          Cudd_ReorderingStatusZdd() +
          Reports the status of automatic dynamic reordering of ZDDs. + +
          Cudd_ReorderingStatus() +
          Reports the status of automatic dynamic reordering of BDDs + and ADDs. + +
          Cudd_SetArcviolation() +
          Sets the value of the arcviolation parameter used + in group sifting. + +
          Cudd_SetBackground() +
          Sets the background constant of the manager. + +
          Cudd_SetEpsilon() +
          Sets the epsilon parameter of the manager to ep. + +
          Cudd_SetGroupcheck() +
          Sets the parameter groupcheck of the manager to gc. + +
          Cudd_SetLooseUpTo() +
          Sets the looseUpTo parameter of the manager. + +
          Cudd_SetMaxCacheHard() +
          Sets the maxCacheHard parameter of the manager. + +
          Cudd_SetMaxGrowthAlternate() +
          Sets the maxGrowthAlt parameter of the manager. + +
          Cudd_SetMaxGrowth() +
          Sets the maxGrowth parameter of the manager. + +
          Cudd_SetMaxLive() +
          Sets the maximum allowed number of live nodes. + +
          Cudd_SetMaxMemory() +
          Sets the maximum allowed memory. + +
          Cudd_SetMinHit() +
          Sets the hit rate that causes resizinig of the computed + table. + +
          Cudd_SetNextReordering() +
          Sets the threshold for the next dynamic reordering. + +
          Cudd_SetNumberXovers() +
          Sets the number of crossovers used by the + genetic algorithm for reordering. + +
          Cudd_SetPopulationSize() +
          Sets the size of the population used by the + genetic algorithm for reordering. + +
          Cudd_SetRecomb() +
          Sets the value of the recombination parameter used in group + sifting. + +
          Cudd_SetReorderingCycle() +
          Sets the reordCycle parameter of the manager. + +
          Cudd_SetSiftMaxSwap() +
          Sets the siftMaxSwap parameter of the manager. + +
          Cudd_SetSiftMaxVar() +
          Sets the siftMaxVar parameter of the manager. + +
          Cudd_SetStderr() +
          Sets the stderr of a manager. + +
          Cudd_SetStdout() +
          Sets the stdout of a manager. + +
          Cudd_SetSymmviolation() +
          Sets the value of the symmviolation parameter used + in group sifting. + +
          Cudd_SetTree() +
          Sets the variable group tree of the manager. + +
          Cudd_SetVarMap() +
          Registers a variable mapping with the manager. + +
          Cudd_SetZddTree() +
          Sets the ZDD variable group tree of the manager. + +
          Cudd_SharingSize() +
          Counts the number of nodes in an array of DDs. + +
          Cudd_ShortestLength() +
          Find the length of the shortest path(s) in a DD. + +
          Cudd_ShortestPath() +
          Finds a shortest path in a DD. + +
          Cudd_ShuffleHeap() +
          Reorders variables according to given permutation. + +
          Cudd_SolveEqn() +
          Implements the solution of F(x,y) = 0. + +
          Cudd_SplitSet() +
          Returns m minterms from a BDD. + +
          Cudd_Srandom() +
          Initializer for the portable random number generator. + +
          Cudd_StdPostReordHook() +
          Sample hook function to call after reordering. + +
          Cudd_StdPreReordHook() +
          Sample hook function to call before reordering. + +
          Cudd_SubsetCompress() +
          Find a dense subset of BDD f. + +
          Cudd_SubsetHeavyBranch() +
          Extracts a dense subset from a BDD with the heavy branch + heuristic. + +
          Cudd_SubsetShortPaths() +
          Extracts a dense subset from a BDD with the shortest paths + heuristic. + +
          Cudd_SubsetWithMaskVars() +
          Extracts a subset from a BDD. + +
          Cudd_SupersetCompress() +
          Find a dense superset of BDD f. + +
          Cudd_SupersetHeavyBranch() +
          Extracts a dense superset from a BDD with the heavy branch + heuristic. + +
          Cudd_SupersetShortPaths() +
          Extracts a dense superset from a BDD with the shortest paths + heuristic. + +
          Cudd_SupportIndex() +
          Finds the variables on which a DD depends. + +
          Cudd_SupportSize() +
          Counts the variables on which a DD depends. + +
          Cudd_Support() +
          Finds the variables on which a DD depends. + +
          Cudd_SymmProfile() +
          Prints statistics on symmetric variables. + +
          Cudd_TurnOffCountDead() +
          Causes the dead nodes not to be counted towards triggering + reordering. + +
          Cudd_TurnOnCountDead() +
          Causes the dead nodes to be counted towards triggering + reordering. + +
          Cudd_UnderApprox() +
          Extracts a dense subset from a BDD with Shiple's + underapproximation method. + +
          Cudd_VectorSupportIndex() +
          Finds the variables on which a set of DDs depends. + +
          Cudd_VectorSupportSize() +
          Counts the variables on which a set of DDs depends. + +
          Cudd_VectorSupport() +
          Finds the variables on which a set of DDs depends. + +
          Cudd_VerifySol() +
          Checks the solution of F(x,y) = 0. + +
          Cudd_Xeqy() +
          Generates a BDD for the function x==y. + +
          Cudd_Xgty() +
          Generates a BDD for the function x > y. + +
          Cudd_addAgreement() +
          f if f==g; background if f!=g. + +
          Cudd_addApply() +
          Applies op to the corresponding discriminants of f and g. + +
          Cudd_addBddInterval() +
          Converts an ADD to a BDD. + +
          Cudd_addBddIthBit() +
          Converts an ADD to a BDD by extracting the i-th bit from + the leaves. + +
          Cudd_addBddPattern() +
          Converts an ADD to a BDD. + +
          Cudd_addBddStrictThreshold() +
          Converts an ADD to a BDD. + +
          Cudd_addBddThreshold() +
          Converts an ADD to a BDD. + +
          Cudd_addCmpl() +
          Computes the complement of an ADD a la C language. + +
          Cudd_addCompose() +
          Substitutes g for x_v in the ADD for f. + +
          Cudd_addComputeCube() +
          Computes the cube of an array of ADD variables. + +
          Cudd_addConstrain() +
          Computes f constrain c for ADDs. + +
          Cudd_addConst() +
          Returns the ADD for constant c. + +
          Cudd_addDiff() +
          Returns plusinfinity if f=g; returns min(f,g) if f!=g. + +
          Cudd_addDivide() +
          Integer and floating point division. + +
          Cudd_addEvalConst() +
          Checks whether ADD g is constant whenever ADD f is 1. + +
          Cudd_addExistAbstract() +
          Existentially Abstracts all the variables in cube from f. + +
          Cudd_addFindMax() +
          Finds the maximum discriminant of f. + +
          Cudd_addFindMin() +
          Finds the minimum discriminant of f. + +
          Cudd_addGeneralVectorCompose() +
          Composes an ADD with a vector of ADDs. + +
          Cudd_addHamming() +
          Computes the Hamming distance ADD. + +
          Cudd_addHarwell() +
          Reads in a matrix in the format of the Harwell-Boeing + benchmark suite. + +
          Cudd_addIteConstant() +
          Implements ITEconstant for ADDs. + +
          Cudd_addIte() +
          Implements ITE(f,g,h). + +
          Cudd_addIthBit() +
          Extracts the i-th bit from an ADD. + +
          Cudd_addIthVar() +
          Returns the ADD variable with index i. + +
          Cudd_addLeq() +
          Determines whether f is less than or equal to g. + +
          Cudd_addLog() +
          Natural logarithm of an ADD. + +
          Cudd_addMatrixMultiply() +
          Calculates the product of two matrices represented as + ADDs. + +
          Cudd_addMaximum() +
          Integer and floating point max. + +
          Cudd_addMinimum() +
          Integer and floating point min. + +
          Cudd_addMinus() +
          Integer and floating point subtraction. + +
          Cudd_addMonadicApply() +
          Applies op to the discriminants of f. + +
          Cudd_addNand() +
          NAND of two 0-1 ADDs. + +
          Cudd_addNegate() +
          Computes the additive inverse of an ADD. + +
          Cudd_addNewVarAtLevel() +
          Returns a new ADD variable at a specified level. + +
          Cudd_addNewVar() +
          Returns a new ADD variable. + +
          Cudd_addNonSimCompose() +
          Composes an ADD with a vector of 0-1 ADDs. + +
          Cudd_addNor() +
          NOR of two 0-1 ADDs. + +
          Cudd_addOneZeroMaximum() +
          Returns 1 if f > g and 0 otherwise. + +
          Cudd_addOrAbstract() +
          Disjunctively abstracts all the variables in cube from the + 0-1 ADD f. + +
          Cudd_addOr() +
          Disjunction of two 0-1 ADDs. + +
          Cudd_addOuterSum() +
          Takes the minimum of a matrix and the outer sum of two vectors. + +
          Cudd_addPermute() +
          Permutes the variables of an ADD. + +
          Cudd_addPlus() +
          Integer and floating point addition. + +
          Cudd_addRead() +
          Reads in a sparse matrix. + +
          Cudd_addResidue() +
          Builds an ADD for the residue modulo m of an n-bit + number. + +
          Cudd_addRestrict() +
          ADD restrict according to Coudert and Madre's algorithm + (ICCAD90). + +
          Cudd_addRoundOff() +
          Rounds off the discriminants of an ADD. + +
          Cudd_addScalarInverse() +
          Computes the scalar inverse of an ADD. + +
          Cudd_addSetNZ() +
          This operator sets f to the value of g wherever g != 0. + +
          Cudd_addSwapVariables() +
          Swaps two sets of variables of the same size (x and y) in + the ADD f. + +
          Cudd_addThreshold() +
          f if f>=g; 0 if f<g. + +
          Cudd_addTimesPlus() +
          Calculates the product of two matrices represented as + ADDs. + +
          Cudd_addTimes() +
          Integer and floating point multiplication. + +
          Cudd_addTriangle() +
          Performs the triangulation step for the shortest path + computation. + +
          Cudd_addUnivAbstract() +
          Universally Abstracts all the variables in cube from f. + +
          Cudd_addVectorCompose() +
          Composes an ADD with a vector of 0-1 ADDs. + +
          Cudd_addWalsh() +
          Generates a Walsh matrix in ADD form. + +
          Cudd_addXeqy() +
          Generates an ADD for the function x==y. + +
          Cudd_addXnor() +
          XNOR of two 0-1 ADDs. + +
          Cudd_addXor() +
          XOR of two 0-1 ADDs. + +
          Cudd_bddAdjPermuteX() +
          Rearranges a set of variables in the BDD B. + +
          Cudd_bddAndAbstractLimit() +
          Takes the AND of two BDDs and simultaneously abstracts the + variables in cube. Returns NULL if too many nodes are required. + +
          Cudd_bddAndAbstract() +
          Takes the AND of two BDDs and simultaneously abstracts the + variables in cube. + +
          Cudd_bddAndLimit() +
          Computes the conjunction of two BDDs f and g. Returns + NULL if too many nodes are required. + +
          Cudd_bddAnd() +
          Computes the conjunction of two BDDs f and g. + +
          Cudd_bddApproxConjDecomp() +
          Performs two-way conjunctive decomposition of a BDD. + +
          Cudd_bddApproxDisjDecomp() +
          Performs two-way disjunctive decomposition of a BDD. + +
          Cudd_bddBindVar() +
          Prevents sifting of a variable. + +
          Cudd_bddBooleanDiff() +
          Computes the boolean difference of f with respect to x. + +
          Cudd_bddCharToVect() +
          Computes a vector whose image equals a non-zero function. + +
          Cudd_bddClippingAndAbstract() +
          Approximates the conjunction of two BDDs f and g and + simultaneously abstracts the variables in cube. + +
          Cudd_bddClippingAnd() +
          Approximates the conjunction of two BDDs f and g. + +
          Cudd_bddClosestCube() +
          Finds a cube of f at minimum Hamming distance from g. + +
          Cudd_bddCompose() +
          Substitutes g for x_v in the BDD for f. + +
          Cudd_bddComputeCube() +
          Computes the cube of an array of BDD variables. + +
          Cudd_bddConstrainDecomp() +
          BDD conjunctive decomposition as in McMillan's CAV96 paper. + +
          Cudd_bddConstrain() +
          Computes f constrain c. + +
          Cudd_bddCorrelationWeights() +
          Computes the correlation of f and g for given input + probabilities. + +
          Cudd_bddCorrelation() +
          Computes the correlation of f and g. + +
          Cudd_bddExistAbstract() +
          Existentially abstracts all the variables in cube from f. + +
          Cudd_bddGenConjDecomp() +
          Performs two-way conjunctive decomposition of a BDD. + +
          Cudd_bddGenDisjDecomp() +
          Performs two-way disjunctive decomposition of a BDD. + +
          Cudd_bddIntersect() +
          Returns a function included in the intersection of f and g. + +
          Cudd_bddInterval() +
          Generates a BDD for the function lowerB ≤ x ≤ upperB. + +
          Cudd_bddIsNsVar() +
          Checks whether a variable is next state. + +
          Cudd_bddIsPiVar() +
          Checks whether a variable is primary input. + +
          Cudd_bddIsPsVar() +
          Checks whether a variable is present state. + +
          Cudd_bddIsVarEssential() +
          Determines whether a given variable is essential with a + given phase in a BDD. + +
          Cudd_bddIsVarHardGroup() +
          Checks whether a variable is set to be in a hard group. + +
          Cudd_bddIsVarToBeGrouped() +
          Checks whether a variable is set to be grouped. + +
          Cudd_bddIsVarToBeUngrouped() +
          Checks whether a variable is set to be ungrouped. + +
          Cudd_bddIsop() +
          Computes a BDD in the interval between L and U with a + simple sum-of-produuct cover. + +
          Cudd_bddIteConstant() +
          Implements ITEconstant(f,g,h). + +
          Cudd_bddIterConjDecomp() +
          Performs two-way conjunctive decomposition of a BDD. + +
          Cudd_bddIterDisjDecomp() +
          Performs two-way disjunctive decomposition of a BDD. + +
          Cudd_bddIte() +
          Implements ITE(f,g,h). + +
          Cudd_bddIthVar() +
          Returns the BDD variable with index i. + +
          Cudd_bddLICompaction() +
          Performs safe minimization of a BDD. + +
          Cudd_bddLeqUnless() +
          Tells whether f is less than of equal to G unless D is 1. + +
          Cudd_bddLeq() +
          Determines whether f is less than or equal to g. + +
          Cudd_bddLiteralSetIntersection() +
          Computes the intesection of two sets of literals + represented as BDDs. + +
          Cudd_bddMakePrime() +
          Expands cube to a prime implicant of f. + +
          Cudd_bddMinimize() +
          Finds a small BDD that agrees with f over + c. + +
          Cudd_bddNPAnd() +
          Computes f non-polluting-and g. + +
          Cudd_bddNand() +
          Computes the NAND of two BDDs f and g. + +
          Cudd_bddNewVarAtLevel() +
          Returns a new BDD variable at a specified level. + +
          Cudd_bddNewVar() +
          Returns a new BDD variable. + +
          Cudd_bddNor() +
          Computes the NOR of two BDDs f and g. + +
          Cudd_bddOr() +
          Computes the disjunction of two BDDs f and g. + +
          Cudd_bddPermute() +
          Permutes the variables of a BDD. + +
          Cudd_bddPickArbitraryMinterms() +
          Picks k on-set minterms evenly distributed from given DD. + +
          Cudd_bddPickOneCube() +
          Picks one on-set cube randomly from the given DD. + +
          Cudd_bddPickOneMinterm() +
          Picks one on-set minterm randomly from the given DD. + +
          Cudd_bddPrintCover() +
          Prints a sum of prime implicants of a BDD. + +
          Cudd_bddReadPairIndex() +
          Reads a corresponding pair index for a given index. + +
          Cudd_bddRead() +
          Reads in a graph (without labels) given as a list of arcs. + +
          Cudd_bddRealignDisable() +
          Disables realignment of ZDD order to BDD order. + +
          Cudd_bddRealignEnable() +
          Enables realignment of BDD order to ZDD order. + +
          Cudd_bddRealignmentEnabled() +
          Tells whether the realignment of BDD order to ZDD order is + enabled. + +
          Cudd_bddResetVarToBeGrouped() +
          Resets a variable not to be grouped. + +
          Cudd_bddRestrict() +
          BDD restrict according to Coudert and Madre's algorithm + (ICCAD90). + +
          Cudd_bddSetNsVar() +
          Sets a variable type to next state. + +
          Cudd_bddSetPairIndex() +
          Sets a corresponding pair index for a given index. + +
          Cudd_bddSetPiVar() +
          Sets a variable type to primary input. + +
          Cudd_bddSetPsVar() +
          Sets a variable type to present state. + +
          Cudd_bddSetVarHardGroup() +
          Sets a variable to be a hard group. + +
          Cudd_bddSetVarToBeGrouped() +
          Sets a variable to be grouped. + +
          Cudd_bddSetVarToBeUngrouped() +
          Sets a variable to be ungrouped. + +
          Cudd_bddSqueeze() +
          Finds a small BDD in a function interval. + +
          Cudd_bddSwapVariables() +
          Swaps two sets of variables of the same size (x and y) in + the BDD f. + +
          Cudd_bddTransfer() +
          Convert a BDD from a manager to another one. + +
          Cudd_bddUnbindVar() +
          Allows the sifting of a variable. + +
          Cudd_bddUnivAbstract() +
          Universally abstracts all the variables in cube from f. + +
          Cudd_bddVarConjDecomp() +
          Performs two-way conjunctive decomposition of a BDD. + +
          Cudd_bddVarDisjDecomp() +
          Performs two-way disjunctive decomposition of a BDD. + +
          Cudd_bddVarIsBound() +
          Tells whether a variable can be sifted. + +
          Cudd_bddVarIsDependent() +
          Checks whether a variable is dependent on others in a + function. + +
          Cudd_bddVarMap() +
          Remaps the variables of a BDD using the default variable map. + +
          Cudd_bddVectorCompose() +
          Composes a BDD with a vector of BDDs. + +
          Cudd_bddXnor() +
          Computes the exclusive NOR of two BDDs f and g. + +
          Cudd_bddXorExistAbstract() +
          Takes the exclusive OR of two BDDs and simultaneously abstracts the + variables in cube. + +
          Cudd_bddXor() +
          Computes the exclusive OR of two BDDs f and g. + +
          Cudd_tlcInfoFree() +
          Frees a DdTlcInfo Structure. + +
          Cudd_zddChange() +
          Substitutes a variable with its complement in a ZDD. + +
          Cudd_zddComplement() +
          Computes a complement cover for a ZDD node. + +
          Cudd_zddCountDouble() +
          Counts the number of minterms of a ZDD. + +
          Cudd_zddCountMinterm() +
          Counts the number of minterms of a ZDD. + +
          Cudd_zddCount() +
          Counts the number of minterms in a ZDD. + +
          Cudd_zddCoverPathToString() +
          Converts a path of a ZDD representing a cover to a string. + +
          Cudd_zddDagSize() +
          Counts the number of nodes in a ZDD. + +
          Cudd_zddDiffConst() +
          Performs the inclusion test for ZDDs (P implies Q). + +
          Cudd_zddDiff() +
          Computes the difference of two ZDDs. + +
          Cudd_zddDivideF() +
          Modified version of Cudd_zddDivide. + +
          Cudd_zddDivide() +
          Computes the quotient of two unate covers. + +
          Cudd_zddDumpDot() +
          Writes a dot file representing the argument ZDDs. + +
          Cudd_zddFirstPath() +
          Finds the first path of a ZDD. + +
          Cudd_zddIntersect() +
          Computes the intersection of two ZDDs. + +
          Cudd_zddIsop() +
          Computes an ISOP in ZDD form from BDDs. + +
          Cudd_zddIte() +
          Computes the ITE of three ZDDs. + +
          Cudd_zddIthVar() +
          Returns the ZDD variable with index i. + +
          Cudd_zddNextPath() +
          Generates the next path of a ZDD. + +
          Cudd_zddPortFromBdd() +
          Converts a BDD into a ZDD. + +
          Cudd_zddPortToBdd() +
          Converts a ZDD into a BDD. + +
          Cudd_zddPrintCover() +
          Prints a sum of products from a ZDD representing a cover. + +
          Cudd_zddPrintDebug() +
          Prints to the standard output a ZDD and its statistics. + +
          Cudd_zddPrintMinterm() +
          Prints a disjoint sum of product form for a ZDD. + +
          Cudd_zddPrintSubtable() +
          Prints the ZDD table. + +
          Cudd_zddProduct() +
          Computes the product of two covers represented by ZDDs. + +
          Cudd_zddReadNodeCount() +
          Reports the number of nodes in ZDDs. + +
          Cudd_zddRealignDisable() +
          Disables realignment of ZDD order to BDD order. + +
          Cudd_zddRealignEnable() +
          Enables realignment of ZDD order to BDD order. + +
          Cudd_zddRealignmentEnabled() +
          Tells whether the realignment of ZDD order to BDD order is + enabled. + +
          Cudd_zddReduceHeap() +
          Main dynamic reordering routine for ZDDs. + +
          Cudd_zddShuffleHeap() +
          Reorders ZDD variables according to given permutation. + +
          Cudd_zddSubset0() +
          Computes the negative cofactor of a ZDD w.r.t. a variable. + +
          Cudd_zddSubset1() +
          Computes the positive cofactor of a ZDD w.r.t. a variable. + +
          Cudd_zddSymmProfile() +
          Prints statistics on symmetric ZDD variables. + +
          Cudd_zddUnateProduct() +
          Computes the product of two unate covers. + +
          Cudd_zddUnion() +
          Computes the union of two ZDDs. + +
          Cudd_zddVarsFromBddVars() +
          Creates one or more ZDD variables for each BDD variable. + +
          Cudd_zddWeakDivF() +
          Modified version of Cudd_zddWeakDiv. + +
          Cudd_zddWeakDiv() +
          Applies weak division to two covers. + +
          + +
          + +Last updated on 20090220 23h06 + diff --git a/distr/cudd/doc/cuddExtDet.html b/distr/cudd/doc/cuddExtDet.html new file mode 100644 index 0000000..ed2567e --- /dev/null +++ b/distr/cudd/doc/cuddExtDet.html @@ -0,0 +1,9289 @@ + +The cudd package + + +
          +
          +
          +int 
          +Cudd_AddHook(
          +  DdManager * dd, 
          +  DD_HFP  f, 
          +  Cudd_HookType  where 
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          See Also Cudd_RemoveHook + + +
          +
          +DdApaDigit 
          +Cudd_ApaAdd(
          +  int  digits, 
          +  DdApaNumber  a, 
          +  DdApaNumber  b, 
          +  DdApaNumber  sum 
          +)
          +
          +
          Adds two arbitrary precision integers. Returns the + carry out of the most significant digit. +

          + +

          Side Effects The result of the sum is stored in parameter sum. +

          + +

          +
          +int 
          +Cudd_ApaCompareRatios(
          +  int  digitsFirst, 
          +  DdApaNumber  firstNum, 
          +  unsigned int  firstDen, 
          +  int  digitsSecond, 
          +  DdApaNumber  secondNum, 
          +  unsigned int  secondDen 
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          +
          +int 
          +Cudd_ApaCompare(
          +  int  digitsFirst, 
          +  DdApaNumber  first, 
          +  int  digitsSecond, 
          +  DdApaNumber  second 
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          +
          +void 
          +Cudd_ApaCopy(
          +  int  digits, 
          +  DdApaNumber  source, 
          +  DdApaNumber  dest 
          +)
          +
          +
          Makes a copy of an arbitrary precision integer. +

          + +

          Side Effects Changes parameter dest. +

          + +

          +
          +DdApaNumber 
          +Cudd_ApaCountMinterm(
          +  DdManager * manager, 
          +  DdNode * node, 
          +  int  nvars, 
          +  int * digits 
          +)
          +
          +
          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. +

          + +

          Side Effects The number of digits of the result is returned in + parameter digits. +

          + +

          See Also Cudd_CountMinterm + + +
          +
          +unsigned int 
          +Cudd_ApaIntDivision(
          +  int  digits, 
          +  DdApaNumber  dividend, 
          +  unsigned int  divisor, 
          +  DdApaNumber  quotient 
          +)
          +
          +
          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. +

          + +

          Side Effects The quotient is returned in parameter quotient. +

          + +

          See Also Cudd_ApaShortDivision + + +
          +
          +int 
          +Cudd_ApaNumberOfDigits(
          +  int  binaryDigits 
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          +
          +void 
          +Cudd_ApaPowerOfTwo(
          +  int  digits, 
          +  DdApaNumber  number, 
          +  int  power 
          +)
          +
          +
          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. +

          + +

          Side Effects The result is returned in parameter number. +

          + +

          +
          +int 
          +Cudd_ApaPrintDecimal(
          +  FILE * fp, 
          +  int  digits, 
          +  DdApaNumber  number 
          +)
          +
          +
          Prints an arbitrary precision integer in decimal format. + Returns 1 if successful; 0 otherwise. +

          + +

          Side Effects None +

          + +

          See Also Cudd_ApaPrintHex +Cudd_ApaPrintExponential + + +
          +
          +int 
          +Cudd_ApaPrintDensity(
          +  FILE * fp, 
          +  DdManager * dd, 
          +  DdNode * node, 
          +  int  nvars 
          +)
          +
          +
          Prints the density of a BDD or ADD using + arbitrary precision arithmetic. Returns 1 if successful; 0 otherwise. +

          + +

          Side Effects None +

          + +

          +
          +int 
          +Cudd_ApaPrintExponential(
          +  FILE * fp, 
          +  int  digits, 
          +  DdApaNumber  number, 
          +  int  precision 
          +)
          +
          +
          Prints an arbitrary precision integer in exponential format. + Returns 1 if successful; 0 otherwise. +

          + +

          Side Effects None +

          + +

          See Also Cudd_ApaPrintHex +Cudd_ApaPrintDecimal + + +
          +
          +int 
          +Cudd_ApaPrintHex(
          +  FILE * fp, 
          +  int  digits, 
          +  DdApaNumber  number 
          +)
          +
          +
          Prints an arbitrary precision integer in hexadecimal format. + Returns 1 if successful; 0 otherwise. +

          + +

          Side Effects None +

          + +

          See Also Cudd_ApaPrintDecimal +Cudd_ApaPrintExponential + + +
          +
          +int 
          +Cudd_ApaPrintMintermExp(
          +  FILE * fp, 
          +  DdManager * dd, 
          +  DdNode * node, 
          +  int  nvars, 
          +  int  precision 
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          See Also Cudd_ApaPrintMinterm + + +
          +
          +int 
          +Cudd_ApaPrintMinterm(
          +  FILE * fp, 
          +  DdManager * dd, 
          +  DdNode * node, 
          +  int  nvars 
          +)
          +
          +
          Prints the number of minterms of a BDD or ADD using + arbitrary precision arithmetic. Returns 1 if successful; 0 otherwise. +

          + +

          Side Effects None +

          + +

          See Also Cudd_ApaPrintMintermExp + + +
          +
          +void 
          +Cudd_ApaSetToLiteral(
          +  int  digits, 
          +  DdApaNumber  number, 
          +  DdApaDigit  literal 
          +)
          +
          +
          Sets an arbitrary precision integer to a one-digit literal. +

          + +

          Side Effects The result is returned in parameter number. +

          + +

          +
          +void 
          +Cudd_ApaShiftRight(
          +  int  digits, 
          +  DdApaDigit  in, 
          +  DdApaNumber  a, 
          +  DdApaNumber  b 
          +)
          +
          +
          Shifts right an arbitrary precision integer by one + binary place. The most significant binary digit of the result is + taken from parameter in. +

          + +

          Side Effects The result is returned in parameter b. +

          + +

          +
          +DdApaDigit 
          +Cudd_ApaShortDivision(
          +  int  digits, 
          +  DdApaNumber  dividend, 
          +  DdApaDigit  divisor, 
          +  DdApaNumber  quotient 
          +)
          +
          +
          Divides an arbitrary precision integer by a digit. +

          + +

          Side Effects The quotient is returned in parameter quotient. +

          + +

          +
          +DdApaDigit 
          +Cudd_ApaSubtract(
          +  int  digits, 
          +  DdApaNumber  a, 
          +  DdApaNumber  b, 
          +  DdApaNumber  diff 
          +)
          +
          +
          Subtracts two arbitrary precision integers. Returns the + borrow out of the most significant digit. +

          + +

          Side Effects The result of the subtraction is stored in parameter + diff. +

          + +

          +
          +void 
          +Cudd_AutodynDisableZdd(
          +  DdManager * unique 
          +)
          +
          +
          Disables automatic dynamic reordering of ZDDs. +

          + +

          Side Effects None +

          + +

          See Also Cudd_AutodynEnableZdd +Cudd_ReorderingStatusZdd +Cudd_AutodynDisable + + +
          +
          +void 
          +Cudd_AutodynDisable(
          +  DdManager * unique 
          +)
          +
          +
          Disables automatic dynamic reordering. +

          + +

          Side Effects None +

          + +

          See Also Cudd_AutodynEnable +Cudd_ReorderingStatus +Cudd_AutodynDisableZdd + + +
          +
          +void 
          +Cudd_AutodynEnableZdd(
          +  DdManager * unique, 
          +  Cudd_ReorderingType  method 
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          See Also Cudd_AutodynDisableZdd +Cudd_ReorderingStatusZdd +Cudd_AutodynEnable + + +
          +
          +void 
          +Cudd_AutodynEnable(
          +  DdManager * unique, 
          +  Cudd_ReorderingType  method 
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          See Also Cudd_AutodynDisable +Cudd_ReorderingStatus +Cudd_AutodynEnableZdd + + +
          +
          +double 
          +Cudd_AverageDistance(
          +  DdManager * dd 
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          +
          +DdNode * 
          +Cudd_BddToAdd(
          +  DdManager * dd, 
          +  DdNode * B 
          +)
          +
          +
          Converts a BDD to a 0-1 ADD. Returns a pointer to the + resulting ADD if successful; NULL otherwise. +

          + +

          Side Effects None +

          + +

          See Also Cudd_addBddPattern +Cudd_addBddThreshold +Cudd_addBddInterval +Cudd_addBddStrictThreshold + + +
          +
          +int 
          +Cudd_BddToCubeArray(
          +  DdManager * dd, 
          +  DdNode * cube, 
          +  int * array 
          +)
          +
          +
          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. +

          + +

          Side Effects The result is in the array passed by reference. +

          + +

          See Also Cudd_CubeArrayToBdd + + +
          +
          +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
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          See Also Cudd_SupersetHeavyBranch +Cudd_SupersetShortPaths +Cudd_RemapOverApprox +Cudd_BiasedUnderApprox +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
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          See Also Cudd_SubsetShortPaths +Cudd_SubsetHeavyBranch +Cudd_UnderApprox +Cudd_RemapUnderApprox +Cudd_ReadSize + + +
          +
          +DdNode * 
          +Cudd_CProjection(
          +  DdManager * dd, 
          +  DdNode * R, 
          +  DdNode * Y 
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          See Also Cudd_PrioritySelect + + +
          +
          +int 
          +Cudd_CheckKeys(
          +  DdManager * table 
          +)
          +
          +
          Checks for the following conditions: +
            +
          • Wrong sizes of subtables. +
          • Wrong number of keys found in unique subtable. +
          • Wrong number of dead found in unique subtable. +
          • Wrong number of keys found in the constant table +
          • Wrong number of dead found in the constant table +
          • Wrong number of total slots found +
          • Wrong number of maximum keys found +
          • Wrong number of total dead found +
          + Reports the average length of non-empty lists. Returns the number of + subtables for which the number of keys is wrong. +

          + +

          Side Effects None +

          + +

          See Also Cudd_DebugCheck + + +
          +
          +int 
          +Cudd_CheckZeroRef(
          +  DdManager * manager 
          +)
          +
          +
          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.) +

          + +

          Side Effects None +

          + +

          +
          +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
          +)
          +
          +
          Classifies the variables in the support of two DDs + f and g, depending on whther they appear + in both DDs, only in f, or only in g. + Returns 1 if successful; 0 otherwise. +

          + +

          Side Effects The cubes of the three classes of variables are + returned as side effects. +

          + +

          See Also Cudd_Support +Cudd_VectorSupport + + +
          +
          +void 
          +Cudd_ClearErrorCode(
          +  DdManager * dd 
          +)
          +
          +
          Clear the error code of a manager. +

          + +

          Side Effects None +

          + +

          See Also Cudd_ReadErrorCode + + +
          +
          +double * 
          +Cudd_CofMinterm(
          +  DdManager * dd, 
          +  DdNode * node 
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          +
          +DdNode * 
          +Cudd_Cofactor(
          +  DdManager * dd, 
          +  DdNode * f, 
          +  DdNode * g 
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          See Also Cudd_bddConstrain +Cudd_bddRestrict + + +
          +
          +int 
          +Cudd_CountLeaves(
          +  DdNode * node 
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          See Also Cudd_PrintDebug + + +
          +
          +double 
          +Cudd_CountMinterm(
          +  DdManager * manager, 
          +  DdNode * node, 
          +  int  nvars 
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          See Also Cudd_PrintDebug +Cudd_CountPath + + +
          +
          +double 
          +Cudd_CountPathsToNonZero(
          +  DdNode * node 
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          See Also Cudd_CountMinterm +Cudd_CountPath + + +
          +
          +double 
          +Cudd_CountPath(
          +  DdNode * node 
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          See Also Cudd_CountMinterm + + +
          +
          +DdNode * 
          +Cudd_CubeArrayToBdd(
          +  DdManager * dd, 
          +  int * array 
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          See Also Cudd_bddComputeCube +Cudd_IndicesToCube +Cudd_BddToCubeArray + + +
          +
          +int 
          +Cudd_DagSize(
          +  DdNode * node 
          +)
          +
          +
          Counts the number of nodes in a DD. Returns the number + of nodes in the graph rooted at node. +

          + +

          Side Effects None +

          + +

          See Also Cudd_SharingSize +Cudd_PrintDebug + + +
          +
          +int 
          +Cudd_DeadAreCounted(
          +  DdManager * dd 
          +)
          +
          +
          Tells whether dead nodes are counted towards triggering + reordering. Returns 1 if dead nodes are counted; 0 otherwise. +

          + +

          Side Effects None +

          + +

          See Also Cudd_TurnOnCountDead +Cudd_TurnOffCountDead + + +
          +
          +int 
          +Cudd_DebugCheck(
          +  DdManager * table 
          +)
          +
          +
          Checks for inconsistencies in the DD heap: +
            +
          • node has illegal index +
          • live node has dead children +
          • node has illegal Then or Else pointers +
          • BDD/ADD node has identical children +
          • ZDD node has zero then child +
          • wrong number of total nodes +
          • wrong number of dead nodes +
          • ref count error at node +
          + Returns 0 if no inconsistencies are found; DD_OUT_OF_MEM if there is + not enough memory; 1 otherwise. +

          + +

          Side Effects None +

          + +

          See Also Cudd_CheckKeys + + +
          +
          +DdNode * 
          +Cudd_Decreasing(
          +  DdManager * dd, 
          +  DdNode * f, 
          +  int  i 
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          See Also Cudd_Increasing + + +
          +
          +void 
          +Cudd_DelayedDerefBdd(
          +  DdManager * table, 
          +  DdNode * n 
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          See Also Cudd_RecursiveDeref +Cudd_IterDerefBdd + + +
          +
          +double 
          +Cudd_Density(
          +  DdManager * dd, manager
          +  DdNode * f, function whose density is sought
          +  int  nvars size of the support of f
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          See Also Cudd_CountMinterm +Cudd_DagSize + + +
          +
          +void 
          +Cudd_Deref(
          +  DdNode * node 
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          See Also Cudd_RecursiveDeref +Cudd_RecursiveDerefZdd +Cudd_Ref + + +
          +
          +void 
          +Cudd_DisableGarbageCollection(
          +  DdManager * dd 
          +)
          +
          +
          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.) +

          + +

          Side Effects None +

          + +

          See Also Cudd_EnableGarbageCollection +Cudd_GarbageCollectionEnabled + + +
          +
          +int 
          +Cudd_DisableReorderingReporting(
          +  DdManager * dd 
          +)
          +
          +
          Disables reporting of reordering stats. + Returns 1 if successful; 0 otherwise. +

          + +

          Side Effects Removes functions from the pre-reordering and post-reordering + hooks. +

          + +

          See Also Cudd_EnableReorderingReporting +Cudd_ReorderingReporting + + +
          +
          +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
          +)
          +
          +
          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]. +

          + +

          Side Effects None +

          + +

          See Also Cudd_Xgty + + +
          +
          +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
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          See Also Cudd_DumpBlif +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
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          See Also Cudd_DumpBlifBody +Cudd_DumpDot +Cudd_PrintDebug +Cudd_DumpDDcal +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
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          See Also Cudd_DumpDot +Cudd_PrintDebug +Cudd_DumpBlif +Cudd_DumpDaVinci +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
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          See Also Cudd_DumpDot +Cudd_PrintDebug +Cudd_DumpBlif +Cudd_DumpDDcal +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
          +)
          +
          +
          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: +
            +
          • solid line: THEN arcs; +
          • dotted line: complement arcs; +
          • dashed line: regular ELSE arcs. +
          + The dot options are chosen so that the drawing fits on a letter-size + sheet. +

          + +

          Side Effects None +

          + +

          See Also Cudd_DumpBlif +Cudd_PrintDebug +Cudd_DumpDDcal +Cudd_DumpDaVinci +Cudd_DumpFactoredForm + + +
          +
          +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
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          See Also Cudd_DumpDot +Cudd_PrintDebug +Cudd_DumpBlif +Cudd_DumpDaVinci +Cudd_DumpDDcal + + +
          +
          +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
          +)
          +
          +
          This function generates a BDD for the function d(x,y) + > 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]. +

          + +

          Side Effects None +

          + +

          See Also Cudd_PrioritySelect +Cudd_Dxygtdyz +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
          +)
          +
          +
          This function generates a BDD for the function d(x,y) + > 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]. +

          + +

          Side Effects None +

          + +

          See Also Cudd_PrioritySelect +Cudd_Dxygtdxz +Cudd_Xgty +Cudd_bddAdjPermuteX + + +
          +
          +void 
          +Cudd_EnableGarbageCollection(
          +  DdManager * dd 
          +)
          +
          +
          Enables garbage collection. Garbage collection is + initially enabled. Therefore it is necessary to call this function + only if garbage collection has been explicitly disabled. +

          + +

          Side Effects None +

          + +

          See Also Cudd_DisableGarbageCollection +Cudd_GarbageCollectionEnabled + + +
          +
          +int 
          +Cudd_EnableReorderingReporting(
          +  DdManager * dd 
          +)
          +
          +
          Enables reporting of reordering stats. + Returns 1 if successful; 0 otherwise. +

          + +

          Side Effects Installs functions in the pre-reordering and post-reordering + hooks. +

          + +

          See Also Cudd_DisableReorderingReporting +Cudd_ReorderingReporting + + +
          +
          +int 
          +Cudd_EpdCountMinterm(
          +  DdManager * manager, 
          +  DdNode * node, 
          +  int  nvars, 
          +  EpDouble * epd 
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          See Also Cudd_PrintDebug +Cudd_CountPath + + +
          +
          +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
          +)
          +
          +
          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 pr is positive + the first failure is reported to the standard output. +

          + +

          Side Effects None +

          + +

          +
          +int 
          +Cudd_EquivDC(
          +  DdManager * dd, 
          +  DdNode * F, 
          +  DdNode * G, 
          +  DdNode * D 
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          See Also Cudd_bddLeqUnless + + +
          +
          +int 
          +Cudd_EstimateCofactorSimple(
          +  DdNode * node, 
          +  int  i 
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          See Also Cudd_DagSize + + +
          +
          +int 
          +Cudd_EstimateCofactor(
          +  DdManager * dd, manager
          +  DdNode * f, function
          +  int  i, index of variable
          +  int  phase 1: positive; 0: negative
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          See Also Cudd_DagSize +Cudd_EstimateCofactorSimple + + +
          +
          +DdNode * 
          +Cudd_Eval(
          +  DdManager * dd, 
          +  DdNode * f, 
          +  int * inputs 
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          See Also Cudd_bddLeq +Cudd_addEvalConst + + +
          +
          +double 
          +Cudd_ExpectedUsedSlots(
          +  DdManager * dd 
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          See Also Cudd_ReadSlots +Cudd_ReadUsedSlots + + +
          +
          +DdNode * 
          +Cudd_FindEssential(
          +  DdManager * dd, 
          +  DdNode * f 
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          See Also Cudd_bddIsVarEssential + + +
          +
          +DdTlcInfo * 
          +Cudd_FindTwoLiteralClauses(
          +  DdManager * dd, 
          +  DdNode * f 
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          See Also Cudd_FindEssential + + +
          +
          +DdGen * 
          +Cudd_FirstCube(
          +  DdManager * dd, 
          +  DdNode * f, 
          +  int ** cube, 
          +  CUDD_VALUE_TYPE * value 
          +)
          +
          +
          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.

          + 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.

          + 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. +

          + +

          Side Effects The first cube and its value are returned as side effects. +

          + +

          See Also Cudd_ForeachCube +Cudd_NextCube +Cudd_GenFree +Cudd_IsGenEmpty +Cudd_FirstNode + + +
          +
          +DdGen * 
          +Cudd_FirstNode(
          +  DdManager * dd, 
          +  DdNode * f, 
          +  DdNode ** node 
          +)
          +
          +
          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. +

          + +

          Side Effects The first node is returned as a side effect. +

          + +

          See Also Cudd_ForeachNode +Cudd_NextNode +Cudd_GenFree +Cudd_IsGenEmpty +Cudd_FirstCube + + +
          +
          +DdGen * 
          +Cudd_FirstPrime(
          +  DdManager * dd, 
          +  DdNode * l, 
          +  DdNode * u, 
          +  int ** cube 
          +)
          +
          +
          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.

          + + 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.

          + + 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.

          + + This iterator can only be used on BDDs. +

          + +

          Side Effects The first cube is returned as side effect. +

          + +

          See Also Cudd_ForeachPrime +Cudd_NextPrime +Cudd_GenFree +Cudd_IsGenEmpty +Cudd_FirstCube +Cudd_FirstNode + + +
          +
          +void 
          +Cudd_FreeTree(
          +  DdManager * dd 
          +)
          +
          +
          Frees the variable group tree of the manager. +

          + +

          Side Effects None +

          + +

          See Also Cudd_SetTree +Cudd_ReadTree +Cudd_FreeZddTree + + +
          +
          +void 
          +Cudd_FreeZddTree(
          +  DdManager * dd 
          +)
          +
          +
          Frees the variable group tree of the manager. +

          + +

          Side Effects None +

          + +

          See Also Cudd_SetZddTree +Cudd_ReadZddTree +Cudd_FreeTree + + +
          +
          +int 
          +Cudd_GarbageCollectionEnabled(
          +  DdManager * dd 
          +)
          +
          +
          Returns 1 if garbage collection is enabled; 0 otherwise. +

          + +

          Side Effects None +

          + +

          See Also Cudd_EnableGarbageCollection +Cudd_DisableGarbageCollection + + +
          +
          +int 
          +Cudd_GenFree(
          +  DdGen * gen 
          +)
          +
          +
          Frees a CUDD generator. Always returns 0, so that it can + be used in mis-like foreach constructs. +

          + +

          Side Effects None +

          + +

          See Also Cudd_ForeachCube +Cudd_ForeachNode +Cudd_FirstCube +Cudd_NextCube +Cudd_FirstNode +Cudd_NextNode +Cudd_IsGenEmpty + + +
          +
          +DdNode * 
          +Cudd_Increasing(
          +  DdManager * dd, 
          +  DdNode * f, 
          +  int  i 
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          See Also Cudd_Decreasing + + +
          +
          +DdNode * 
          +Cudd_IndicesToCube(
          +  DdManager * dd, 
          +  int * array, 
          +  int  n 
          +)
          +
          +
          Builds a cube of BDD variables from an array of indices. + Returns a pointer to the result if successful; NULL otherwise. +

          + +

          Side Effects None +

          + +

          See Also Cudd_bddComputeCube +Cudd_CubeArrayToBdd + + +
          +
          +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
          +)
          +
          +
          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]. +

          + +

          Side Effects None +

          + +

          See Also Cudd_Xgty + + +
          +
          +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
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          See Also Cudd_Quit + + +
          +
          +int 
          +Cudd_IsGenEmpty(
          +  DdGen * gen 
          +)
          +
          +
          Queries the status of a generator. Returns 1 if the + generator is empty or NULL; 0 otherswise. +

          + +

          Side Effects None +

          + +

          See Also Cudd_ForeachCube +Cudd_ForeachNode +Cudd_FirstCube +Cudd_NextCube +Cudd_FirstNode +Cudd_NextNode +Cudd_GenFree + + +
          +
          +int 
          +Cudd_IsInHook(
          +  DdManager * dd, 
          +  DD_HFP  f, 
          +  Cudd_HookType  where 
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          See Also Cudd_AddHook +Cudd_RemoveHook + + +
          +
          +int 
          +Cudd_IsNonConstant(
          +  DdNode * f 
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          See Also Cudd_IsConstant +Cudd_bddIteConstant +Cudd_addIteConstant +Cudd_addEvalConst + + +
          +
          +void 
          +Cudd_IterDerefBdd(
          +  DdManager * table, 
          +  DdNode * n 
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          See Also Cudd_RecursiveDeref +Cudd_DelayedDerefBdd + + +
          +
          +DdNode * 
          +Cudd_LargestCube(
          +  DdManager * manager, 
          +  DdNode * f, 
          +  int * length 
          +)
          +
          +
          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. +

          + +

          Side Effects The number of literals of the cube is returned in length. +

          + +

          See Also Cudd_ShortestPath + + +
          +
          +DdNode	* 
          +Cudd_MakeBddFromZddCover(
          +  DdManager * dd, 
          +  DdNode * node 
          +)
          +
          +
          Converts a ZDD cover to a BDD graph. If successful, it + returns a BDD node, otherwise it returns NULL. +

          + +

          See Also cuddMakeBddFromZddCover + + +
          +
          +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
          +)
          +
          +
          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. +

          + +

          Side Effects The variable tree is changed. +

          + +

          See Also Cudd_MakeZddTreeNode + + +
          +
          +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
          +)
          +
          +
          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. +

          + +

          Side Effects The ZDD variable tree is changed. +

          + +

          See Also Cudd_MakeTreeNode + + +
          +
          +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
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          See Also Cudd_addHamming +Cudd_bddClosestCube + + +
          +
          +DdApaNumber 
          +Cudd_NewApaNumber(
          +  int  digits 
          +)
          +
          +
          Allocates memory for an arbitrary precision + integer. Returns a pointer to the allocated memory if successful; + NULL otherwise. +

          + +

          Side Effects None +

          + +

          +
          +int 
          +Cudd_NextCube(
          +  DdGen * gen, 
          +  int ** cube, 
          +  CUDD_VALUE_TYPE * value 
          +)
          +
          +
          Generates the next cube of a decision diagram onset, + using generator gen. Returns 0 if the enumeration is completed; 1 + otherwise. +

          + +

          Side Effects The cube and its value are returned as side effects. The + generator is modified. +

          + +

          See Also Cudd_ForeachCube +Cudd_FirstCube +Cudd_GenFree +Cudd_IsGenEmpty +Cudd_NextNode + + +
          +
          +int 
          +Cudd_NextNode(
          +  DdGen * gen, 
          +  DdNode ** node 
          +)
          +
          +
          Finds the node of a decision diagram, using generator + gen. Returns 0 if the enumeration is completed; 1 otherwise. +

          + +

          Side Effects The next node is returned as a side effect. +

          + +

          See Also Cudd_ForeachNode +Cudd_FirstNode +Cudd_GenFree +Cudd_IsGenEmpty +Cudd_NextCube + + +
          +
          +int 
          +Cudd_NextPrime(
          +  DdGen * gen, 
          +  int ** cube 
          +)
          +
          +
          Generates the next cube of a Boolean function, + using generator gen. Returns 0 if the enumeration is completed; 1 + otherwise. +

          + +

          Side Effects The cube and is returned as side effects. The + generator is modified. +

          + +

          See Also Cudd_ForeachPrime +Cudd_FirstPrime +Cudd_GenFree +Cudd_IsGenEmpty +Cudd_NextCube +Cudd_NextNode + + +
          +
          +unsigned int 
          +Cudd_NodeReadIndex(
          +  DdNode * node 
          +)
          +
          +
          Returns the index of the node. The node pointer can be + either regular or complemented. +

          + +

          Side Effects None +

          + +

          See Also Cudd_ReadIndex + + +
          +
          +void 
          +Cudd_OutOfMem(
          +  long  size size of the allocation that failed
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          +
          +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
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          See Also Cudd_SupersetHeavyBranch +Cudd_SupersetShortPaths +Cudd_ReadSize + + +
          +
          +unsigned int 
          +Cudd_Prime(
          +  unsigned int  p 
          +)
          +
          +
          Returns the next prime >= p. +

          + +

          Side Effects None +

          + +

          +
          +int 
          +Cudd_PrintDebug(
          +  DdManager * dd, 
          +  DdNode * f, 
          +  int  n, 
          +  int  pr 
          +)
          +
          +
          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 > 0. Specifically: +
            +
          • pr = 0 : prints nothing +
          • pr = 1 : prints counts of nodes and minterms +
          • pr = 2 : prints counts + disjoint sum of product +
          • pr = 3 : prints counts + list of nodes +
          • pr > 3 : prints counts + disjoint sum of product + list of nodes +
          + For the purpose of counting the number of minterms, the function is + supposed to depend on n variables. Returns 1 if successful; 0 otherwise. +

          + +

          Side Effects None +

          + +

          See Also Cudd_DagSize +Cudd_CountLeaves +Cudd_CountMinterm +Cudd_PrintMinterm + + +
          +
          +int 
          +Cudd_PrintInfo(
          +  DdManager * dd, 
          +  FILE * fp 
          +)
          +
          +
          Prints out statistics and settings for a CUDD manager. + Returns 1 if successful; 0 otherwise. +

          + +

          Side Effects None +

          + +

          +
          +int 
          +Cudd_PrintLinear(
          +  DdManager * table 
          +)
          +
          +
          Prints the linear transform matrix. Returns 1 in case of + success; 0 otherwise. +

          + +

          Side Effects none +

          + +

          +
          +int 
          +Cudd_PrintMinterm(
          +  DdManager * manager, 
          +  DdNode * node 
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          See Also Cudd_PrintDebug +Cudd_bddPrintCover + + +
          +
          +int 
          +Cudd_PrintTwoLiteralClauses(
          +  DdManager * dd, 
          +  DdNode * f, 
          +  char ** names, 
          +  FILE * fp 
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          See Also Cudd_FindTwoLiteralClauses + + +
          +
          +void 
          +Cudd_PrintVersion(
          +  FILE * fp 
          +)
          +
          +
          Prints the package version number. +

          + +

          Side Effects None +

          + +

          +
          +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
          +)
          +
          +
          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: +
            +
          • When extracting representatives from an equivalence relation, + Cudd_CProjection has the advantage of nor requiring the auxiliary + variables. +
          • 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). +
          +

          + +

          Side Effects If called with z == NULL, will create new variables in + the manager. +

          + +

          See Also Cudd_Dxygtdxz +Cudd_Dxygtdyz +Cudd_Xgty +Cudd_bddAdjPermuteX +Cudd_CProjection + + +
          +
          +void 
          +Cudd_Quit(
          +  DdManager * unique 
          +)
          +
          +
          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.) +

          + +

          Side Effects None +

          + +

          See Also Cudd_Init + + +
          +
          +long 
          +Cudd_Random(
          +    
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          See Also Cudd_Srandom + + +
          +
          +int 
          +Cudd_ReadArcviolation(
          +  DdManager * dd 
          +)
          +
          +
          Returns the current value of the arcviolation + parameter. This parameter is used in group sifting to decide how + many arcs into y not coming from x 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. +

          + +

          Side Effects None +

          + +

          See Also Cudd_SetArcviolation + + +
          +
          +DdNode * 
          +Cudd_ReadBackground(
          +  DdManager * dd 
          +)
          +
          +
          Reads the background constant of the manager. +

          + +

          Side Effects None +

          + +

          +
          +double 
          +Cudd_ReadCacheHits(
          +  DdManager * dd 
          +)
          +
          +
          Returns the number of cache hits. +

          + +

          Side Effects None +

          + +

          See Also Cudd_ReadCacheLookUps + + +
          +
          +double 
          +Cudd_ReadCacheLookUps(
          +  DdManager * dd 
          +)
          +
          +
          Returns the number of cache look-ups. +

          + +

          Side Effects None +

          + +

          See Also Cudd_ReadCacheHits + + +
          +
          +unsigned int 
          +Cudd_ReadCacheSlots(
          +  DdManager * dd 
          +)
          +
          +
          Reads the number of slots in the cache. +

          + +

          Side Effects None +

          + +

          See Also Cudd_ReadCacheUsedSlots + + +
          +
          +double 
          +Cudd_ReadCacheUsedSlots(
          +  DdManager * dd 
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          See Also Cudd_ReadCacheSlots + + +
          +
          +unsigned int 
          +Cudd_ReadDead(
          +  DdManager * dd 
          +)
          +
          +
          Returns the number of dead nodes in the unique table. +

          + +

          Side Effects None +

          + +

          See Also Cudd_ReadKeys + + +
          +
          +CUDD_VALUE_TYPE 
          +Cudd_ReadEpsilon(
          +  DdManager * dd 
          +)
          +
          +
          Reads the epsilon parameter of the manager. The epsilon + parameter control the comparison between floating point numbers. +

          + +

          Side Effects None +

          + +

          See Also Cudd_SetEpsilon + + +
          +
          +Cudd_ErrorType 
          +Cudd_ReadErrorCode(
          +  DdManager * dd 
          +)
          +
          +
          Returns the code of the last error. The error codes are + defined in cudd.h. +

          + +

          Side Effects None +

          + +

          See Also Cudd_ClearErrorCode + + +
          +
          +long 
          +Cudd_ReadGarbageCollectionTime(
          +  DdManager * dd 
          +)
          +
          +
          Returns the number of milliseconds spent doing garbage + collection since the manager was initialized. +

          + +

          Side Effects None +

          + +

          See Also Cudd_ReadGarbageCollections + + +
          +
          +int 
          +Cudd_ReadGarbageCollections(
          +  DdManager * dd 
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          See Also Cudd_ReadGarbageCollectionTime + + +
          +
          +Cudd_AggregationType 
          +Cudd_ReadGroupcheck(
          +  DdManager * dd 
          +)
          +
          +
          Reads the groupcheck parameter of the manager. The + groupcheck parameter determines the aggregation criterion in group + sifting. +

          + +

          Side Effects None +

          + +

          See Also Cudd_SetGroupcheck + + +
          +
          +int 
          +Cudd_ReadInvPermZdd(
          +  DdManager * dd, 
          +  int  i 
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          See Also Cudd_ReadPerm +Cudd_ReadInvPermZdd + + +
          +
          +int 
          +Cudd_ReadInvPerm(
          +  DdManager * dd, 
          +  int  i 
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          See Also Cudd_ReadPerm +Cudd_ReadInvPermZdd + + +
          +
          +int 
          +Cudd_ReadIthClause(
          +  DdTlcInfo * tlc, 
          +  int  i, 
          +  DdHalfWord * var1, 
          +  DdHalfWord * var2, 
          +  int * phase1, 
          +  int * phase2 
          +)
          +
          +
          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. +

          + +

          Side Effects the four components of a clause are returned as side effects. +

          + +

          See Also Cudd_FindTwoLiteralClauses + + +
          +
          +unsigned int 
          +Cudd_ReadKeys(
          +  DdManager * dd 
          +)
          +
          +
          Returns the total number of nodes currently in the unique + table, including the dead nodes. +

          + +

          Side Effects None +

          + +

          See Also Cudd_ReadDead + + +
          +
          +int 
          +Cudd_ReadLinear(
          +  DdManager * table, CUDD manager
          +  int  x, row index
          +  int  y column index
          +)
          +
          +
          Reads an entry of the linear transform matrix. +

          + +

          Side Effects none +

          + +

          +
          +DdNode * 
          +Cudd_ReadLogicZero(
          +  DdManager * dd 
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          See Also Cudd_ReadOne +Cudd_ReadZero + + +
          +
          +unsigned int 
          +Cudd_ReadLooseUpTo(
          +  DdManager * dd 
          +)
          +
          +
          Reads the looseUpTo parameter of the manager. +

          + +

          Side Effects None +

          + +

          See Also Cudd_SetLooseUpTo +Cudd_ReadMinHit +Cudd_ReadMinDead + + +
          +
          +unsigned int 
          +Cudd_ReadMaxCacheHard(
          +  DdManager * dd 
          +)
          +
          +
          Reads the maxCacheHard parameter of the manager. +

          + +

          Side Effects None +

          + +

          See Also Cudd_SetMaxCacheHard +Cudd_ReadMaxCache + + +
          +
          +unsigned int 
          +Cudd_ReadMaxCache(
          +  DdManager * dd 
          +)
          +
          +
          Returns the soft limit for the cache size. The soft limit +

          + +

          Side Effects None +

          + +

          See Also Cudd_ReadMaxCache + + +
          +
          +double 
          +Cudd_ReadMaxGrowthAlternate(
          +  DdManager * dd 
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          See Also Cudd_ReadMaxGrowth +Cudd_SetMaxGrowthAlternate +Cudd_SetReorderingCycle +Cudd_ReadReorderingCycle + + +
          +
          +double 
          +Cudd_ReadMaxGrowth(
          +  DdManager * dd 
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          See Also Cudd_SetMaxGrowth +Cudd_ReadMaxGrowthAlternate + + +
          +
          +unsigned int 
          +Cudd_ReadMaxLive(
          +  DdManager * dd 
          +)
          +
          +
          Reads the maximum allowed number of live nodes. When this + number is exceeded, the package returns NULL. +

          + +

          Side Effects none +

          + +

          See Also Cudd_SetMaxLive + + +
          +
          +unsigned long 
          +Cudd_ReadMaxMemory(
          +  DdManager * dd 
          +)
          +
          +
          Reads the maximum allowed memory. When this + number is exceeded, the package returns NULL. +

          + +

          Side Effects none +

          + +

          See Also Cudd_SetMaxMemory + + +
          +
          +unsigned long 
          +Cudd_ReadMemoryInUse(
          +  DdManager * dd 
          +)
          +
          +
          Returns the memory in use by the manager measured in bytes. +

          + +

          Side Effects None +

          + +

          +
          +unsigned int 
          +Cudd_ReadMinDead(
          +  DdManager * dd 
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          See Also Cudd_ReadDead +Cudd_ReadLooseUpTo +Cudd_SetLooseUpTo + + +
          +
          +unsigned int 
          +Cudd_ReadMinHit(
          +  DdManager * dd 
          +)
          +
          +
          Reads the hit rate that causes resizinig of the computed + table. +

          + +

          Side Effects None +

          + +

          See Also Cudd_SetMinHit + + +
          +
          +DdNode * 
          +Cudd_ReadMinusInfinity(
          +  DdManager * dd 
          +)
          +
          +
          Reads the minus-infinity constant from the manager. +

          + +

          Side Effects None +

          + +

          +
          +unsigned int 
          +Cudd_ReadNextReordering(
          +  DdManager * dd 
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          See Also Cudd_SetNextReordering + + +
          +
          +long 
          +Cudd_ReadNodeCount(
          +  DdManager * dd 
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          See Also Cudd_ReadPeakNodeCount +Cudd_zddReadNodeCount + + +
          +
          +double 
          +Cudd_ReadNodesDropped(
          +  DdManager * dd 
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          See Also Cudd_ReadNodesFreed + + +
          +
          +double 
          +Cudd_ReadNodesFreed(
          +  DdManager * dd 
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          See Also Cudd_ReadNodesDropped + + +
          +
          +int 
          +Cudd_ReadNumberXovers(
          +  DdManager * dd 
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          See Also Cudd_SetNumberXovers + + +
          +
          +DdNode * 
          +Cudd_ReadOne(
          +  DdManager * dd 
          +)
          +
          +
          Returns the one constant of the manager. The one + constant is common to ADDs and BDDs. +

          + +

          Side Effects None +

          + +

          See Also Cudd_ReadZero +Cudd_ReadLogicZero +Cudd_ReadZddOne + + +
          +
          +int 
          +Cudd_ReadPeakLiveNodeCount(
          +  DdManager * dd 
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          See Also Cudd_ReadNodeCount +Cudd_PrintInfo +Cudd_ReadPeakNodeCount + + +
          +
          +long 
          +Cudd_ReadPeakNodeCount(
          +  DdManager * dd 
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          See Also Cudd_ReadNodeCount +Cudd_PrintInfo + + +
          +
          +int 
          +Cudd_ReadPermZdd(
          +  DdManager * dd, 
          +  int  i 
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          See Also Cudd_ReadInvPermZdd +Cudd_ReadPerm + + +
          +
          +int 
          +Cudd_ReadPerm(
          +  DdManager * dd, 
          +  int  i 
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          See Also Cudd_ReadInvPerm +Cudd_ReadPermZdd + + +
          +
          +DdNode * 
          +Cudd_ReadPlusInfinity(
          +  DdManager * dd 
          +)
          +
          +
          Reads the plus-infinity constant from the manager. +

          + +

          Side Effects None +

          + +

          +
          +int 
          +Cudd_ReadPopulationSize(
          +  DdManager * dd 
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          See Also Cudd_SetPopulationSize + + +
          +
          +int 
          +Cudd_ReadRecomb(
          +  DdManager * dd 
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          See Also Cudd_SetRecomb + + +
          +
          +double 
          +Cudd_ReadRecursiveCalls(
          +  DdManager * dd 
          +)
          +
          +
          Returns the number of recursive calls if the package is + compiled with DD_COUNT defined. +

          + +

          Side Effects None +

          + +

          +
          +int 
          +Cudd_ReadReorderingCycle(
          +  DdManager * dd 
          +)
          +
          +
          Reads the reordCycle parameter of the manager. This + parameter determines how often the alternate threshold on maximum + growth is used in reordering. +

          + +

          Side Effects None +

          + +

          See Also Cudd_ReadMaxGrowthAlternate +Cudd_SetMaxGrowthAlternate +Cudd_SetReorderingCycle + + +
          +
          +long 
          +Cudd_ReadReorderingTime(
          +  DdManager * dd 
          +)
          +
          +
          Returns the number of milliseconds spent reordering + variables since the manager was initialized. The time spent in collecting + garbage before reordering is included. +

          + +

          Side Effects None +

          + +

          See Also Cudd_ReadReorderings + + +
          +
          +int 
          +Cudd_ReadReorderings(
          +  DdManager * dd 
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          See Also Cudd_ReduceHeap +Cudd_ReadReorderingTime + + +
          +
          +int 
          +Cudd_ReadSiftMaxSwap(
          +  DdManager * dd 
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          See Also Cudd_ReadSiftMaxVar +Cudd_SetSiftMaxSwap + + +
          +
          +int 
          +Cudd_ReadSiftMaxVar(
          +  DdManager * dd 
          +)
          +
          +
          Reads the siftMaxVar parameter of the manager. This + parameter gives the maximum number of variables that will be sifted + for each invocation of sifting. +

          + +

          Side Effects None +

          + +

          See Also Cudd_ReadSiftMaxSwap +Cudd_SetSiftMaxVar + + +
          +
          +int 
          +Cudd_ReadSize(
          +  DdManager * dd 
          +)
          +
          +
          Returns the number of BDD variables in existance. +

          + +

          Side Effects None +

          + +

          See Also Cudd_ReadZddSize + + +
          +
          +unsigned int 
          +Cudd_ReadSlots(
          +  DdManager * dd 
          +)
          +
          +
          Returns the total number of slots of the unique table. + This number ismainly for diagnostic purposes. +

          + +

          Side Effects None +

          + +

          +
          +FILE * 
          +Cudd_ReadStderr(
          +  DdManager * dd 
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          See Also Cudd_SetStderr +Cudd_ReadStdout + + +
          +
          +FILE * 
          +Cudd_ReadStdout(
          +  DdManager * dd 
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          See Also Cudd_SetStdout +Cudd_ReadStderr + + +
          +
          +double 
          +Cudd_ReadSwapSteps(
          +  DdManager * dd 
          +)
          +
          +
          Reads the number of elementary reordering steps. +

          + +

          Side Effects none +

          + +

          +
          +int 
          +Cudd_ReadSymmviolation(
          +  DdManager * dd 
          +)
          +
          +
          Returns the current value of the symmviolation + parameter. This parameter is used in group sifting to decide how + many violations to the symmetry conditions f10 = f01 or + f11 = f00 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. +

          + +

          Side Effects None +

          + +

          See Also Cudd_SetSymmviolation + + +
          +
          +MtrNode * 
          +Cudd_ReadTree(
          +  DdManager * dd 
          +)
          +
          +
          Returns the variable group tree of the manager. +

          + +

          Side Effects None +

          + +

          See Also Cudd_SetTree +Cudd_FreeTree +Cudd_ReadZddTree + + +
          +
          +double 
          +Cudd_ReadUniqueLinks(
          +  DdManager * dd 
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          See Also Cudd_ReadUniqueLookUps + + +
          +
          +double 
          +Cudd_ReadUniqueLookUps(
          +  DdManager * dd 
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          See Also Cudd_ReadUniqueLinks + + +
          +
          +double 
          +Cudd_ReadUsedSlots(
          +  DdManager * dd 
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          See Also Cudd_ReadSlots + + +
          +
          +DdNode * 
          +Cudd_ReadVars(
          +  DdManager * dd, 
          +  int  i 
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          See Also Cudd_bddIthVar + + +
          +
          +DdNode * 
          +Cudd_ReadZddOne(
          +  DdManager * dd, 
          +  int  i 
          +)
          +
          +
          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 i. +

          + +

          Side Effects None +

          + +

          See Also Cudd_ReadOne + + +
          +
          +int 
          +Cudd_ReadZddSize(
          +  DdManager * dd 
          +)
          +
          +
          Returns the number of ZDD variables in existance. +

          + +

          Side Effects None +

          + +

          See Also Cudd_ReadSize + + +
          +
          +MtrNode * 
          +Cudd_ReadZddTree(
          +  DdManager * dd 
          +)
          +
          +
          Returns the variable group tree of the manager. +

          + +

          Side Effects None +

          + +

          See Also Cudd_SetZddTree +Cudd_FreeZddTree +Cudd_ReadTree + + +
          +
          +DdNode * 
          +Cudd_ReadZero(
          +  DdManager * dd 
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          See Also Cudd_ReadOne +Cudd_ReadLogicZero + + +
          +
          +void 
          +Cudd_RecursiveDerefZdd(
          +  DdManager * table, 
          +  DdNode * n 
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          See Also Cudd_Deref +Cudd_Ref +Cudd_RecursiveDeref + + +
          +
          +void 
          +Cudd_RecursiveDeref(
          +  DdManager * table, 
          +  DdNode * n 
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          See Also Cudd_Deref +Cudd_Ref +Cudd_RecursiveDerefZdd + + +
          +
          +int 
          +Cudd_ReduceHeap(
          +  DdManager * table, DD manager
          +  Cudd_ReorderingType  heuristic, method used for reordering
          +  int  minsize bound below which no reordering occurs
          +)
          +
          +
          Main dynamic reordering routine. + Calls one of the possible reordering procedures: +
            +
          • Swapping +
          • Sifting +
          • Symmetric Sifting +
          • Group Sifting +
          • Window Permutation +
          • Simulated Annealing +
          • Genetic Algorithm +
          • Dynamic Programming (exact) +
          + + For sifting, symmetric sifting, group sifting, and window + permutation it is possible to request reordering to convergence.

          + + 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. +

          + +

          Side Effects Changes the variable order for all diagrams and clears + the cache. +

          + +

          +
          +void 
          +Cudd_Ref(
          +  DdNode * n 
          +)
          +
          +
          Increases the reference count of a node, if it is not + saturated. +

          + +

          Side Effects None +

          + +

          See Also Cudd_RecursiveDeref +Cudd_Deref + + +
          +
          +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
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          See Also Cudd_SupersetHeavyBranch +Cudd_SupersetShortPaths +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
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          See Also Cudd_SubsetShortPaths +Cudd_SubsetHeavyBranch +Cudd_UnderApprox +Cudd_ReadSize + + +
          +
          +int 
          +Cudd_RemoveHook(
          +  DdManager * dd, 
          +  DD_HFP  f, 
          +  Cudd_HookType  where 
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          See Also Cudd_AddHook + + +
          +
          +int 
          +Cudd_ReorderingReporting(
          +  DdManager * dd 
          +)
          +
          +
          Returns 1 if reporting of reordering stats is enabled; + 0 otherwise. +

          + +

          Side Effects none +

          + +

          See Also Cudd_EnableReorderingReporting +Cudd_DisableReorderingReporting + + +
          +
          +int 
          +Cudd_ReorderingStatusZdd(
          +  DdManager * unique, 
          +  Cudd_ReorderingType * method 
          +)
          +
          +
          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. +

          + +

          Side Effects Parameter method is set to the ZDD reordering method currently + selected. +

          + +

          See Also Cudd_AutodynEnableZdd +Cudd_AutodynDisableZdd +Cudd_ReorderingStatus + + +
          +
          +int 
          +Cudd_ReorderingStatus(
          +  DdManager * unique, 
          +  Cudd_ReorderingType * method 
          +)
          +
          +
          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. +

          + +

          Side Effects Parameter method is set to the reordering method currently + selected. +

          + +

          See Also Cudd_AutodynEnable +Cudd_AutodynDisable +Cudd_ReorderingStatusZdd + + +
          +
          +void 
          +Cudd_SetArcviolation(
          +  DdManager * dd, 
          +  int  arcviolation 
          +)
          +
          +
          Sets the value of the arcviolation + parameter. This parameter is used in group sifting to decide how + many arcs into y not coming from x 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. +

          + +

          Side Effects None +

          + +

          See Also Cudd_ReadArcviolation + + +
          +
          +void 
          +Cudd_SetBackground(
          +  DdManager * dd, 
          +  DdNode * bck 
          +)
          +
          +
          Sets the background constant of the manager. It assumes + that the DdNode pointer bck is already referenced. +

          + +

          Side Effects None +

          + +

          +
          +void 
          +Cudd_SetEpsilon(
          +  DdManager * dd, 
          +  CUDD_VALUE_TYPE  ep 
          +)
          +
          +
          Sets the epsilon parameter of the manager to ep. The epsilon + parameter control the comparison between floating point numbers. +

          + +

          Side Effects None +

          + +

          See Also Cudd_ReadEpsilon + + +
          +
          +void 
          +Cudd_SetGroupcheck(
          +  DdManager * dd, 
          +  Cudd_AggregationType  gc 
          +)
          +
          +
          Sets the parameter groupcheck of the manager to gc. The + groupcheck parameter determines the aggregation criterion in group + sifting. +

          + +

          Side Effects None +

          + +

          See Also Cudd_ReadGroupCheck + + +
          +
          +void 
          +Cudd_SetLooseUpTo(
          +  DdManager * dd, 
          +  unsigned int  lut 
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          See Also Cudd_ReadLooseUpTo +Cudd_SetMinHit + + +
          +
          +void 
          +Cudd_SetMaxCacheHard(
          +  DdManager * dd, 
          +  unsigned int  mc 
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          See Also Cudd_ReadMaxCacheHard +Cudd_SetMaxCache + + +
          +
          +void 
          +Cudd_SetMaxGrowthAlternate(
          +  DdManager * dd, 
          +  double  mg 
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          See Also Cudd_ReadMaxGrowthAlternate +Cudd_SetMaxGrowth +Cudd_SetReorderingCycle +Cudd_ReadReorderingCycle + + +
          +
          +void 
          +Cudd_SetMaxGrowth(
          +  DdManager * dd, 
          +  double  mg 
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          See Also Cudd_ReadMaxGrowth +Cudd_SetMaxGrowthAlternate + + +
          +
          +void 
          +Cudd_SetMaxLive(
          +  DdManager * dd, 
          +  unsigned int  maxLive 
          +)
          +
          +
          Sets the maximum allowed number of live nodes. When this + number is exceeded, the package returns NULL. +

          + +

          Side Effects none +

          + +

          See Also Cudd_ReadMaxLive + + +
          +
          +void 
          +Cudd_SetMaxMemory(
          +  DdManager * dd, 
          +  unsigned long  maxMemory 
          +)
          +
          +
          Sets the maximum allowed memory. When this + number is exceeded, the package returns NULL. +

          + +

          Side Effects none +

          + +

          See Also Cudd_ReadMaxMemory + + +
          +
          +void 
          +Cudd_SetMinHit(
          +  DdManager * dd, 
          +  unsigned int  hr 
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          See Also Cudd_ReadMinHit + + +
          +
          +void 
          +Cudd_SetNextReordering(
          +  DdManager * dd, 
          +  unsigned int  next 
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          See Also Cudd_ReadNextReordering + + +
          +
          +void 
          +Cudd_SetNumberXovers(
          +  DdManager * dd, 
          +  int  numberXovers 
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          See Also Cudd_ReadNumberXovers + + +
          +
          +void 
          +Cudd_SetPopulationSize(
          +  DdManager * dd, 
          +  int  populationSize 
          +)
          +
          +
          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. +

          + +

          Side Effects Changes the manager. +

          + +

          See Also Cudd_ReadPopulationSize + + +
          +
          +void 
          +Cudd_SetRecomb(
          +  DdManager * dd, 
          +  int  recomb 
          +)
          +
          +
          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. +

          + +

          Side Effects Changes the manager. +

          + +

          See Also Cudd_ReadRecomb + + +
          +
          +void 
          +Cudd_SetReorderingCycle(
          +  DdManager * dd, 
          +  int  cycle 
          +)
          +
          +
          Sets the reordCycle parameter of the manager. This + parameter determines how often the alternate threshold on maximum + growth is used in reordering. +

          + +

          Side Effects None +

          + +

          See Also Cudd_ReadMaxGrowthAlternate +Cudd_SetMaxGrowthAlternate +Cudd_ReadReorderingCycle + + +
          +
          +void 
          +Cudd_SetSiftMaxSwap(
          +  DdManager * dd, 
          +  int  sms 
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          See Also Cudd_SetSiftMaxVar +Cudd_ReadSiftMaxSwap + + +
          +
          +void 
          +Cudd_SetSiftMaxVar(
          +  DdManager * dd, 
          +  int  smv 
          +)
          +
          +
          Sets the siftMaxVar parameter of the manager. This + parameter gives the maximum number of variables that will be sifted + for each invocation of sifting. +

          + +

          Side Effects None +

          + +

          See Also Cudd_SetSiftMaxSwap +Cudd_ReadSiftMaxVar + + +
          +
          +void 
          +Cudd_SetStderr(
          +  DdManager * dd, 
          +  FILE * fp 
          +)
          +
          +
          Sets the stderr of a manager. +

          + +

          Side Effects None +

          + +

          See Also Cudd_ReadStderr +Cudd_SetStdout + + +
          +
          +void 
          +Cudd_SetStdout(
          +  DdManager * dd, 
          +  FILE * fp 
          +)
          +
          +
          Sets the stdout of a manager. +

          + +

          Side Effects None +

          + +

          See Also Cudd_ReadStdout +Cudd_SetStderr + + +
          +
          +void 
          +Cudd_SetSymmviolation(
          +  DdManager * dd, 
          +  int  symmviolation 
          +)
          +
          +
          Sets the value of the symmviolation + parameter. This parameter is used in group sifting to decide how + many violations to the symmetry conditions f10 = f01 or + f11 = f00 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. +

          + +

          Side Effects Changes the manager. +

          + +

          See Also Cudd_ReadSymmviolation + + +
          +
          +void 
          +Cudd_SetTree(
          +  DdManager * dd, 
          +  MtrNode * tree 
          +)
          +
          +
          Sets the variable group tree of the manager. +

          + +

          Side Effects None +

          + +

          See Also Cudd_FreeTree +Cudd_ReadTree +Cudd_SetZddTree + + +
          +
          +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
          +)
          +
          +
          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. +

          + +

          Side Effects Modifies the manager. May clear the cache. +

          + +

          See Also Cudd_bddVarMap +Cudd_bddPermute +Cudd_bddSwapVariables + + +
          +
          +void 
          +Cudd_SetZddTree(
          +  DdManager * dd, 
          +  MtrNode * tree 
          +)
          +
          +
          Sets the ZDD variable group tree of the manager. +

          + +

          Side Effects None +

          + +

          See Also Cudd_FreeZddTree +Cudd_ReadZddTree +Cudd_SetTree + + +
          +
          +int 
          +Cudd_SharingSize(
          +  DdNode ** nodeArray, 
          +  int  n 
          +)
          +
          +
          Counts the number of nodes in an array of DDs. Shared + nodes are counted only once. Returns the total number of nodes. +

          + +

          Side Effects None +

          + +

          See Also Cudd_DagSize + + +
          +
          +int 
          +Cudd_ShortestLength(
          +  DdManager * manager, 
          +  DdNode * f, 
          +  int * weight 
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          See Also Cudd_ShortestPath + + +
          +
          +DdNode * 
          +Cudd_ShortestPath(
          +  DdManager * manager, 
          +  DdNode * f, 
          +  int * weight, 
          +  int * support, 
          +  int * length 
          +)
          +
          +
          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. +

          + +

          Side Effects 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. +

          + +

          See Also Cudd_ShortestLength +Cudd_LargestCube + + +
          +
          +int 
          +Cudd_ShuffleHeap(
          +  DdManager * table, DD manager
          +  int * permutation required variable permutation
          +)
          +
          +
          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. +

          + +

          Side Effects Changes the variable order for all diagrams and clears + the cache. +

          + +

          See Also Cudd_ReduceHeap + + +
          +
          +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
          +)
          +
          +
          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. +

          + +

          Side Effects The solution is returned in G; the indices of the y + variables are returned in yIndex. +

          + +

          See Also Cudd_VerifySol + + +
          +
          +DdNode * 
          +Cudd_SplitSet(
          +  DdManager * manager, 
          +  DdNode * S, 
          +  DdNode ** xVars, 
          +  int  n, 
          +  double  m 
          +)
          +
          +
          Returns m minterms from a BDD whose + support has n variables at most. The procedure tries + to create as few extra nodes as possible. The function represented + by S depends on at most n of the variables + in xVars. Returns a BDD with m minterms + of the on-set of S if successful; NULL otherwise. +

          + +

          Side Effects None +

          + +

          +
          +void 
          +Cudd_Srandom(
          +  long  seed 
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          See Also Cudd_Random + + +
          +
          +int 
          +Cudd_StdPostReordHook(
          +  DdManager * dd, 
          +  const char * str, 
          +  void * data 
          +)
          +
          +
          Sample hook function to call after reordering. + Prints on the manager's stdout final size and reordering time. + Returns 1 if successful; 0 otherwise. +

          + +

          Side Effects None +

          + +

          See Also Cudd_StdPreReordHook + + +
          +
          +int 
          +Cudd_StdPreReordHook(
          +  DdManager * dd, 
          +  const char * str, 
          +  void * data 
          +)
          +
          +
          Sample hook function to call before reordering. + Prints on the manager's stdout reordering method and initial size. + Returns 1 if successful; 0 otherwise. +

          + +

          Side Effects None +

          + +

          See Also Cudd_StdPostReordHook + + +
          +
          +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
          +)
          +
          +
          Finds a dense subset of BDD f. 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. +

          + +

          Side Effects None +

          + +

          See Also Cudd_SubsetRemap +Cudd_SubsetShortPaths +Cudd_SubsetHeavyBranch +Cudd_bddSqueeze + + +
          +
          +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
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          See Also Cudd_SubsetShortPaths +Cudd_SupersetHeavyBranch +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
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          See Also Cudd_SupersetShortPaths +Cudd_SubsetHeavyBranch +Cudd_ReadSize + + +
          +
          +DdNode * 
          +Cudd_SubsetWithMaskVars(
          +  DdManager * dd, manager
          +  DdNode * f, function from which to pick a cube
          +  DdNode ** vars, array of variables
          +  int  nvars, size of vars
          +  DdNode ** maskVars, array of variables
          +  int  mvars size of maskVars
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          +
          +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
          +)
          +
          +
          Finds a dense superset of BDD f. 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. +

          + +

          Side Effects None +

          + +

          See Also Cudd_SubsetCompress +Cudd_SupersetRemap +Cudd_SupersetShortPaths +Cudd_SupersetHeavyBranch +Cudd_bddSqueeze + + +
          +
          +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
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          See Also Cudd_SubsetHeavyBranch +Cudd_SupersetShortPaths +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
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          See Also Cudd_SubsetShortPaths +Cudd_SupersetHeavyBranch +Cudd_ReadSize + + +
          +
          +int * 
          +Cudd_SupportIndex(
          +  DdManager * dd, manager
          +  DdNode * f DD whose support is sought
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          See Also Cudd_Support +Cudd_VectorSupport +Cudd_ClassifySupport + + +
          +
          +int 
          +Cudd_SupportSize(
          +  DdManager * dd, manager
          +  DdNode * f DD whose support size is sought
          +)
          +
          +
          Counts the variables on which a DD depends. + Returns the number of the variables if successful; CUDD_OUT_OF_MEM + otherwise. +

          + +

          Side Effects None +

          + +

          See Also Cudd_Support + + +
          +
          +DdNode * 
          +Cudd_Support(
          +  DdManager * dd, manager
          +  DdNode * f DD whose support is sought
          +)
          +
          +
          Finds the variables on which a DD depends. + Returns a BDD consisting of the product of the variables if + successful; NULL otherwise. +

          + +

          Side Effects None +

          + +

          See Also Cudd_VectorSupport +Cudd_ClassifySupport + + +
          +
          +void 
          +Cudd_SymmProfile(
          +  DdManager * table, 
          +  int  lower, 
          +  int  upper 
          +)
          +
          +
          Prints statistics on symmetric variables. +

          + +

          Side Effects None +

          + +

          +
          +void 
          +Cudd_TurnOffCountDead(
          +  DdManager * dd 
          +)
          +
          +
          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. +

          + +

          Side Effects Changes the manager. +

          + +

          See Also Cudd_TurnOnCountDead +Cudd_DeadAreCounted + + +
          +
          +void 
          +Cudd_TurnOnCountDead(
          +  DdManager * dd 
          +)
          +
          +
          Causes the dead nodes to be counted towards triggering + reordering. This causes more frequent reorderings. By default dead + nodes are not counted. +

          + +

          Side Effects Changes the manager. +

          + +

          See Also Cudd_TurnOffCountDead +Cudd_DeadAreCounted + + +
          +
          +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
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          See Also Cudd_SubsetShortPaths +Cudd_SubsetHeavyBranch +Cudd_ReadSize + + +
          +
          +int * 
          +Cudd_VectorSupportIndex(
          +  DdManager * dd, manager
          +  DdNode ** F, array of DDs whose support is sought
          +  int  n size of the array
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          See Also Cudd_SupportIndex +Cudd_VectorSupport +Cudd_ClassifySupport + + +
          +
          +int 
          +Cudd_VectorSupportSize(
          +  DdManager * dd, manager
          +  DdNode ** F, array of DDs whose support is sought
          +  int  n size of the array
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          See Also Cudd_VectorSupport +Cudd_SupportSize + + +
          +
          +DdNode * 
          +Cudd_VectorSupport(
          +  DdManager * dd, manager
          +  DdNode ** F, array of DDs whose support is sought
          +  int  n size of the array
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          See Also Cudd_Support +Cudd_ClassifySupport + + +
          +
          +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
          +)
          +
          +
          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. +

          + +

          Side Effects Frees the memory pointed by yIndex. +

          + +

          See Also Cudd_SolveEqn + + +
          +
          +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
          +)
          +
          +
          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]. +

          + +

          Side Effects None +

          + +

          See Also Cudd_addXeqy + + +
          +
          +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
          +)
          +
          +
          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]. + Argument z is not used by Cudd_Xgty: it is included to make it + call-compatible to Cudd_Dxygtdxz and Cudd_Dxygtdyz. +

          + +

          Side Effects None +

          + +

          See Also Cudd_PrioritySelect +Cudd_Dxygtdxz +Cudd_Dxygtdyz + + +
          +
          +DdNode * 
          +Cudd_addAgreement(
          +  DdManager * dd, 
          +  DdNode ** f, 
          +  DdNode ** g 
          +)
          +
          +
          Returns NULL if not a terminal case; f op g otherwise, + where f op g is f if f==g; background if f!=g. +

          + +

          Side Effects None +

          + +

          See Also Cudd_addApply + + +
          +
          +DdNode * 
          +Cudd_addApply(
          +  DdManager * dd, 
          +  DD_AOP  op, 
          +  DdNode * f, 
          +  DdNode * g 
          +)
          +
          +
          Applies op to the corresponding discriminants of f and g. + Returns a pointer to the result if succssful; NULL otherwise. +

          + +

          Side Effects None +

          + +

          See Also 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_addBddInterval(
          +  DdManager * dd, 
          +  DdNode * f, 
          +  CUDD_VALUE_TYPE  lower, 
          +  CUDD_VALUE_TYPE  upper 
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          See Also Cudd_addBddThreshold +Cudd_addBddStrictThreshold +Cudd_addBddPattern +Cudd_BddToAdd + + +
          +
          +DdNode * 
          +Cudd_addBddIthBit(
          +  DdManager * dd, 
          +  DdNode * f, 
          +  int  bit 
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          See Also Cudd_addBddInterval +Cudd_addBddPattern +Cudd_BddToAdd + + +
          +
          +DdNode * 
          +Cudd_addBddPattern(
          +  DdManager * dd, 
          +  DdNode * f 
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          See Also Cudd_BddToAdd +Cudd_addBddThreshold +Cudd_addBddInterval +Cudd_addBddStrictThreshold + + +
          +
          +DdNode * 
          +Cudd_addBddStrictThreshold(
          +  DdManager * dd, 
          +  DdNode * f, 
          +  CUDD_VALUE_TYPE  value 
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          See Also Cudd_addBddInterval +Cudd_addBddPattern +Cudd_BddToAdd +Cudd_addBddThreshold + + +
          +
          +DdNode * 
          +Cudd_addBddThreshold(
          +  DdManager * dd, 
          +  DdNode * f, 
          +  CUDD_VALUE_TYPE  value 
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          See Also Cudd_addBddInterval +Cudd_addBddPattern +Cudd_BddToAdd +Cudd_addBddStrictThreshold + + +
          +
          +DdNode * 
          +Cudd_addCmpl(
          +  DdManager * dd, 
          +  DdNode * f 
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          See Also Cudd_addNegate + + +
          +
          +DdNode * 
          +Cudd_addCompose(
          +  DdManager * dd, 
          +  DdNode * f, 
          +  DdNode * g, 
          +  int  v 
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          See Also Cudd_bddCompose + + +
          +
          +DdNode * 
          +Cudd_addComputeCube(
          +  DdManager * dd, 
          +  DdNode ** vars, 
          +  int * phase, 
          +  int  n 
          +)
          +
          +
          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. +

          + +

          Side Effects none +

          + +

          See Also Cudd_bddComputeCube + + +
          +
          +DdNode * 
          +Cudd_addConstrain(
          +  DdManager * dd, 
          +  DdNode * f, 
          +  DdNode * c 
          +)
          +
          +
          Computes f constrain c (f @ c), for f an ADD and c a 0-1 + ADD. List of special cases: +
            +
          • F @ 0 = 0 +
          • F @ 1 = F +
          • 0 @ c = 0 +
          • 1 @ c = 1 +
          • F @ F = 1 +
          + Returns a pointer to the result if successful; NULL otherwise. +

          + +

          Side Effects None +

          + +

          See Also Cudd_bddConstrain + + +
          +
          +DdNode * 
          +Cudd_addConst(
          +  DdManager * dd, 
          +  CUDD_VALUE_TYPE  c 
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          See Also Cudd_addNewVar +Cudd_addIthVar + + +
          +
          +DdNode * 
          +Cudd_addDiff(
          +  DdManager * dd, 
          +  DdNode ** f, 
          +  DdNode ** g 
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          See Also Cudd_addApply + + +
          +
          +DdNode * 
          +Cudd_addDivide(
          +  DdManager * dd, 
          +  DdNode ** f, 
          +  DdNode ** g 
          +)
          +
          +
          Integer and floating point division. Returns NULL if not + a terminal case; f / g otherwise. +

          + +

          Side Effects None +

          + +

          See Also Cudd_addApply + + +
          +
          +DdNode * 
          +Cudd_addEvalConst(
          +  DdManager * dd, 
          +  DdNode * f, 
          +  DdNode * g 
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          See Also Cudd_addIteConstant +Cudd_addLeq + + +
          +
          +DdNode * 
          +Cudd_addExistAbstract(
          +  DdManager * manager, 
          +  DdNode * f, 
          +  DdNode * cube 
          +)
          +
          +
          Abstracts all the variables in cube from f by summing + over all possible values taken by the variables. Returns the + abstracted ADD. +

          + +

          Side Effects None +

          + +

          See Also Cudd_addUnivAbstract +Cudd_bddExistAbstract +Cudd_addOrAbstract + + +
          +
          +DdNode * 
          +Cudd_addFindMax(
          +  DdManager * dd, 
          +  DdNode * f 
          +)
          +
          +
          Returns a pointer to a constant ADD. +

          + +

          Side Effects None +

          + +

          +
          +DdNode * 
          +Cudd_addFindMin(
          +  DdManager * dd, 
          +  DdNode * f 
          +)
          +
          +
          Returns a pointer to a constant ADD. +

          + +

          Side Effects None +

          + +

          +
          +DdNode * 
          +Cudd_addGeneralVectorCompose(
          +  DdManager * dd, 
          +  DdNode * f, 
          +  DdNode ** vectorOn, 
          +  DdNode ** vectorOff 
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          See Also Cudd_addVectorCompose +Cudd_addNonSimCompose +Cudd_addPermute +Cudd_addCompose +Cudd_bddVectorCompose + + +
          +
          +DdNode * 
          +Cudd_addHamming(
          +  DdManager * dd, 
          +  DdNode ** xVars, 
          +  DdNode ** yVars, 
          +  int  nVars 
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          +
          +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
          +)
          +
          +
          Reads in a matrix in the format of the Harwell-Boeing + benchmark suite. The variables are ordered as follows: +
          + x[0] y[0] x[1] y[1] ... +
          + 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. +

          + +

          Side Effects None +

          + +

          See Also Cudd_addRead +Cudd_bddRead + + +
          +
          +DdNode * 
          +Cudd_addIteConstant(
          +  DdManager * dd, 
          +  DdNode * f, 
          +  DdNode * g, 
          +  DdNode * h 
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          See Also Cudd_addIte +Cudd_addEvalConst +Cudd_bddIteConstant + + +
          +
          +DdNode * 
          +Cudd_addIte(
          +  DdManager * dd, 
          +  DdNode * f, 
          +  DdNode * g, 
          +  DdNode * h 
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          See Also Cudd_bddIte +Cudd_addIteConstant +Cudd_addApply + + +
          +
          +DdNode * 
          +Cudd_addIthBit(
          +  DdManager * dd, 
          +  DdNode * f, 
          +  int  bit 
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          See Also Cudd_addBddIthBit + + +
          +
          +DdNode * 
          +Cudd_addIthVar(
          +  DdManager * dd, 
          +  int  i 
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          See Also Cudd_addNewVar +Cudd_bddIthVar +Cudd_addConst +Cudd_addNewVarAtLevel + + +
          +
          +int 
          +Cudd_addLeq(
          +  DdManager * dd, 
          +  DdNode * f, 
          +  DdNode * g 
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          See Also Cudd_addIteConstant +Cudd_addEvalConst +Cudd_bddLeq + + +
          +
          +DdNode * 
          +Cudd_addLog(
          +  DdManager * dd, 
          +  DdNode * f 
          +)
          +
          +
          Natural logarithm of an ADDs. Returns NULL + if not a terminal case; log(f) otherwise. The discriminants of f must + be positive double's. +

          + +

          Side Effects None +

          + +

          See Also Cudd_addMonadicApply + + +
          +
          +DdNode * 
          +Cudd_addMatrixMultiply(
          +  DdManager * dd, 
          +  DdNode * A, 
          +  DdNode * B, 
          +  DdNode ** z, 
          +  int  nz 
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          See Also Cudd_addTimesPlus +Cudd_addTriangle +Cudd_bddAndAbstract + + +
          +
          +DdNode * 
          +Cudd_addMaximum(
          +  DdManager * dd, 
          +  DdNode ** f, 
          +  DdNode ** g 
          +)
          +
          +
          Integer and floating point max for Cudd_addApply. + Returns NULL if not a terminal case; max(f,g) otherwise. +

          + +

          Side Effects None +

          + +

          See Also Cudd_addApply + + +
          +
          +DdNode * 
          +Cudd_addMinimum(
          +  DdManager * dd, 
          +  DdNode ** f, 
          +  DdNode ** g 
          +)
          +
          +
          Integer and floating point min for Cudd_addApply. + Returns NULL if not a terminal case; min(f,g) otherwise. +

          + +

          Side Effects None +

          + +

          See Also Cudd_addApply + + +
          +
          +DdNode * 
          +Cudd_addMinus(
          +  DdManager * dd, 
          +  DdNode ** f, 
          +  DdNode ** g 
          +)
          +
          +
          Integer and floating point subtraction. Returns NULL if + not a terminal case; f - g otherwise. +

          + +

          Side Effects None +

          + +

          See Also Cudd_addApply + + +
          +
          +DdNode * 
          +Cudd_addMonadicApply(
          +  DdManager * dd, 
          +  DD_MAOP  op, 
          +  DdNode * f 
          +)
          +
          +
          Applies op to the discriminants of f. + Returns a pointer to the result if succssful; NULL otherwise. +

          + +

          Side Effects None +

          + +

          See Also Cudd_addApply +Cudd_addLog + + +
          +
          +DdNode * 
          +Cudd_addNand(
          +  DdManager * dd, 
          +  DdNode ** f, 
          +  DdNode ** g 
          +)
          +
          +
          NAND of two 0-1 ADDs. Returns NULL + if not a terminal case; f NAND g otherwise. +

          + +

          Side Effects None +

          + +

          See Also Cudd_addApply + + +
          +
          +DdNode * 
          +Cudd_addNegate(
          +  DdManager * dd, 
          +  DdNode * f 
          +)
          +
          +
          Computes the additive inverse of an ADD. Returns a pointer + to the result if successful; NULL otherwise. +

          + +

          Side Effects None +

          + +

          See Also Cudd_addCmpl + + +
          +
          +DdNode * 
          +Cudd_addNewVarAtLevel(
          +  DdManager * dd, 
          +  int  level 
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          See Also Cudd_addNewVar +Cudd_addIthVar +Cudd_bddNewVarAtLevel + + +
          +
          +DdNode * 
          +Cudd_addNewVar(
          +  DdManager * dd 
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          See Also Cudd_bddNewVar +Cudd_addIthVar +Cudd_addConst +Cudd_addNewVarAtLevel + + +
          +
          +DdNode * 
          +Cudd_addNonSimCompose(
          +  DdManager * dd, 
          +  DdNode * f, 
          +  DdNode ** vector 
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          See Also Cudd_addVectorCompose +Cudd_addPermute +Cudd_addCompose + + +
          +
          +DdNode * 
          +Cudd_addNor(
          +  DdManager * dd, 
          +  DdNode ** f, 
          +  DdNode ** g 
          +)
          +
          +
          NOR of two 0-1 ADDs. Returns NULL + if not a terminal case; f NOR g otherwise. +

          + +

          Side Effects None +

          + +

          See Also Cudd_addApply + + +
          +
          +DdNode * 
          +Cudd_addOneZeroMaximum(
          +  DdManager * dd, 
          +  DdNode ** f, 
          +  DdNode ** g 
          +)
          +
          +
          Returns 1 if f > g and 0 otherwise. Used in + conjunction with Cudd_addApply. Returns NULL if not a terminal + case. +

          + +

          Side Effects None +

          + +

          See Also Cudd_addApply + + +
          +
          +DdNode * 
          +Cudd_addOrAbstract(
          +  DdManager * manager, 
          +  DdNode * f, 
          +  DdNode * cube 
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          See Also Cudd_addUnivAbstract +Cudd_addExistAbstract + + +
          +
          +DdNode * 
          +Cudd_addOr(
          +  DdManager * dd, 
          +  DdNode ** f, 
          +  DdNode ** g 
          +)
          +
          +
          Disjunction of two 0-1 ADDs. Returns NULL + if not a terminal case; f OR g otherwise. +

          + +

          Side Effects None +

          + +

          See Also Cudd_addApply + + +
          +
          +DdNode * 
          +Cudd_addOuterSum(
          +  DdManager * dd, 
          +  DdNode * M, 
          +  DdNode * r, 
          +  DdNode * c 
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          +
          +DdNode * 
          +Cudd_addPermute(
          +  DdManager * manager, 
          +  DdNode * node, 
          +  int * permut 
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          See Also Cudd_bddPermute +Cudd_addSwapVariables + + +
          +
          +DdNode * 
          +Cudd_addPlus(
          +  DdManager * dd, 
          +  DdNode ** f, 
          +  DdNode ** g 
          +)
          +
          +
          Integer and floating point addition. Returns NULL if not + a terminal case; f+g otherwise. +

          + +

          Side Effects None +

          + +

          See Also Cudd_addApply + + +
          +
          +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
          +)
          +
          +
          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.

          + 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.

          + 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.

          + 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. +

          + +

          Side Effects 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. +

          + +

          See Also Cudd_addHarwell +Cudd_bddRead + + +
          +
          +DdNode * 
          +Cudd_addResidue(
          +  DdManager * dd, manager
          +  int  n, number of bits
          +  int  m, modulus
          +  int  options, options
          +  int  top index of top variable
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          +
          +DdNode * 
          +Cudd_addRestrict(
          +  DdManager * dd, 
          +  DdNode * f, 
          +  DdNode * c 
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          See Also Cudd_addConstrain +Cudd_bddRestrict + + +
          +
          +DdNode * 
          +Cudd_addRoundOff(
          +  DdManager * dd, 
          +  DdNode * f, 
          +  int  N 
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          +
          +DdNode * 
          +Cudd_addScalarInverse(
          +  DdManager * dd, 
          +  DdNode * f, 
          +  DdNode * epsilon 
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          +
          +DdNode * 
          +Cudd_addSetNZ(
          +  DdManager * dd, 
          +  DdNode ** f, 
          +  DdNode ** g 
          +)
          +
          +
          This operator sets f to the value of g wherever g != 0. + Returns NULL if not a terminal case; f op g otherwise. +

          + +

          Side Effects None +

          + +

          See Also Cudd_addApply + + +
          +
          +DdNode * 
          +Cudd_addSwapVariables(
          +  DdManager * dd, 
          +  DdNode * f, 
          +  DdNode ** x, 
          +  DdNode ** y, 
          +  int  n 
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          See Also Cudd_addPermute +Cudd_bddSwapVariables + + +
          +
          +DdNode * 
          +Cudd_addThreshold(
          +  DdManager * dd, 
          +  DdNode ** f, 
          +  DdNode ** g 
          +)
          +
          +
          Threshold operator for Apply (f if f >=g; 0 if f<g). + Returns NULL if not a terminal case; f op g otherwise. +

          + +

          Side Effects None +

          + +

          See Also Cudd_addApply + + +
          +
          +DdNode * 
          +Cudd_addTimesPlus(
          +  DdManager * dd, 
          +  DdNode * A, 
          +  DdNode * B, 
          +  DdNode ** z, 
          +  int  nz 
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          See Also Cudd_addMatrixMultiply + + +
          +
          +DdNode * 
          +Cudd_addTimes(
          +  DdManager * dd, 
          +  DdNode ** f, 
          +  DdNode ** g 
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          See Also Cudd_addApply + + +
          +
          +DdNode * 
          +Cudd_addTriangle(
          +  DdManager * dd, 
          +  DdNode * f, 
          +  DdNode * g, 
          +  DdNode ** z, 
          +  int  nz 
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          See Also Cudd_addMatrixMultiply +Cudd_bddAndAbstract + + +
          +
          +DdNode * 
          +Cudd_addUnivAbstract(
          +  DdManager * manager, 
          +  DdNode * f, 
          +  DdNode * cube 
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          See Also Cudd_addExistAbstract +Cudd_bddUnivAbstract +Cudd_addOrAbstract + + +
          +
          +DdNode * 
          +Cudd_addVectorCompose(
          +  DdManager * dd, 
          +  DdNode * f, 
          +  DdNode ** vector 
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          See Also Cudd_addNonSimCompose +Cudd_addPermute +Cudd_addCompose +Cudd_bddVectorCompose + + +
          +
          +DdNode * 
          +Cudd_addWalsh(
          +  DdManager * dd, 
          +  DdNode ** x, 
          +  DdNode ** y, 
          +  int  n 
          +)
          +
          +
          Generates a Walsh matrix in ADD form. Returns a pointer + to the matrixi if successful; NULL otherwise. +

          + +

          Side Effects None +

          + +

          +
          +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
          +)
          +
          +
          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]. +

          + +

          Side Effects None +

          + +

          See Also Cudd_Xeqy + + +
          +
          +DdNode * 
          +Cudd_addXnor(
          +  DdManager * dd, 
          +  DdNode ** f, 
          +  DdNode ** g 
          +)
          +
          +
          XNOR of two 0-1 ADDs. Returns NULL + if not a terminal case; f XNOR g otherwise. +

          + +

          Side Effects None +

          + +

          See Also Cudd_addApply + + +
          +
          +DdNode * 
          +Cudd_addXor(
          +  DdManager * dd, 
          +  DdNode ** f, 
          +  DdNode ** g 
          +)
          +
          +
          XOR of two 0-1 ADDs. Returns NULL + if not a terminal case; f XOR g otherwise. +

          + +

          Side Effects None +

          + +

          See Also Cudd_addApply + + +
          +
          +DdNode * 
          +Cudd_bddAdjPermuteX(
          +  DdManager * dd, 
          +  DdNode * B, 
          +  DdNode ** x, 
          +  int  n 
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          See Also Cudd_bddPermute +Cudd_bddSwapVariables +Cudd_Dxygtdxz +Cudd_Dxygtdyz +Cudd_PrioritySelect + + +
          +
          +DdNode * 
          +Cudd_bddAndAbstractLimit(
          +  DdManager * manager, 
          +  DdNode * f, 
          +  DdNode * g, 
          +  DdNode * cube, 
          +  unsigned int  limit 
          +)
          +
          +
          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 + limit, this function returns NULL. +

          + +

          Side Effects None +

          + +

          See Also Cudd_bddAndAbstract + + +
          +
          +DdNode * 
          +Cudd_bddAndAbstract(
          +  DdManager * manager, 
          +  DdNode * f, 
          +  DdNode * g, 
          +  DdNode * cube 
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          See Also Cudd_addMatrixMultiply +Cudd_addTriangle +Cudd_bddAnd + + +
          +
          +DdNode * 
          +Cudd_bddAndLimit(
          +  DdManager * dd, 
          +  DdNode * f, 
          +  DdNode * g, 
          +  unsigned int  limit 
          +)
          +
          +
          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 limit are + required. +

          + +

          Side Effects None +

          + +

          See Also Cudd_bddAnd + + +
          +
          +DdNode * 
          +Cudd_bddAnd(
          +  DdManager * dd, 
          +  DdNode * f, 
          +  DdNode * g 
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          See Also Cudd_bddIte +Cudd_addApply +Cudd_bddAndAbstract +Cudd_bddIntersect +Cudd_bddOr +Cudd_bddNand +Cudd_bddNor +Cudd_bddXor +Cudd_bddXnor + + +
          +
          +int 
          +Cudd_bddApproxConjDecomp(
          +  DdManager * dd, manager
          +  DdNode * f, function to be decomposed
          +  DdNode *** conjuncts address of the first factor
          +)
          +
          +
          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. +

          + +

          Side Effects 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. +

          + +

          See Also Cudd_bddApproxDisjDecomp +Cudd_bddIterConjDecomp +Cudd_bddGenConjDecomp +Cudd_bddVarConjDecomp +Cudd_RemapOverApprox +Cudd_bddSqueeze +Cudd_bddLICompaction + + +
          +
          +int 
          +Cudd_bddApproxDisjDecomp(
          +  DdManager * dd, manager
          +  DdNode * f, function to be decomposed
          +  DdNode *** disjuncts address of the array of the disjuncts
          +)
          +
          +
          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. +

          + +

          Side Effects 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. +

          + +

          See Also Cudd_bddApproxConjDecomp +Cudd_bddIterDisjDecomp +Cudd_bddGenDisjDecomp +Cudd_bddVarDisjDecomp + + +
          +
          +int 
          +Cudd_bddBindVar(
          +  DdManager * dd, manager
          +  int  index variable index
          +)
          +
          +
          This function sets a flag to prevent sifting of a + variable. Returns 1 if successful; 0 otherwise (i.e., invalid + variable index). +

          + +

          Side Effects Changes the "bindVar" flag in DdSubtable. +

          + +

          See Also Cudd_bddUnbindVar + + +
          +
          +DdNode * 
          +Cudd_bddBooleanDiff(
          +  DdManager * manager, 
          +  DdNode * f, 
          +  int  x 
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          +
          +DdNode ** 
          +Cudd_bddCharToVect(
          +  DdManager * dd, 
          +  DdNode * f 
          +)
          +
          +
          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). +

          + +

          Side Effects None +

          + +

          See Also Cudd_bddConstrain + + +
          +
          +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
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          See Also Cudd_bddAndAbstract +Cudd_bddClippingAnd + + +
          +
          +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
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          See Also Cudd_bddAnd + + +
          +
          +DdNode * 
          +Cudd_bddClosestCube(
          +  DdManager * dd, 
          +  DdNode * f, 
          +  DdNode * g, 
          +  int * distance 
          +)
          +
          +
          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. +

          + +

          Side Effects The distance is returned as a side effect. +

          + +

          See Also Cudd_MinHammingDist + + +
          +
          +DdNode * 
          +Cudd_bddCompose(
          +  DdManager * dd, 
          +  DdNode * f, 
          +  DdNode * g, 
          +  int  v 
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          See Also Cudd_addCompose + + +
          +
          +DdNode * 
          +Cudd_bddComputeCube(
          +  DdManager * dd, 
          +  DdNode ** vars, 
          +  int * phase, 
          +  int  n 
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          See Also Cudd_addComputeCube +Cudd_IndicesToCube +Cudd_CubeArrayToBdd + + +
          +
          +DdNode ** 
          +Cudd_bddConstrainDecomp(
          +  DdManager * dd, 
          +  DdNode * f 
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          See Also Cudd_bddConstrain +Cudd_bddExistAbstract + + +
          +
          +DdNode * 
          +Cudd_bddConstrain(
          +  DdManager * dd, 
          +  DdNode * f, 
          +  DdNode * c 
          +)
          +
          +
          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: +
            +
          • f @ 0 = 0 +
          • f @ 1 = f +
          • 0 @ c = 0 +
          • 1 @ c = 1 +
          • f @ f = 1 +
          • f @ f'= 0 +
          + 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. +

          + +

          Side Effects None +

          + +

          See Also Cudd_bddRestrict +Cudd_addConstrain + + +
          +
          +double 
          +Cudd_bddCorrelationWeights(
          +  DdManager * manager, 
          +  DdNode * f, 
          +  DdNode * g, 
          +  double * prob 
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          See Also Cudd_bddCorrelation + + +
          +
          +double 
          +Cudd_bddCorrelation(
          +  DdManager * manager, 
          +  DdNode * f, 
          +  DdNode * g 
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          See Also Cudd_bddCorrelationWeights + + +
          +
          +DdNode * 
          +Cudd_bddExistAbstract(
          +  DdManager * manager, 
          +  DdNode * f, 
          +  DdNode * cube 
          +)
          +
          +
          Existentially abstracts all the variables in cube from f. + Returns the abstracted BDD if successful; NULL otherwise. +

          + +

          Side Effects None +

          + +

          See Also Cudd_bddUnivAbstract +Cudd_addExistAbstract + + +
          +
          +int 
          +Cudd_bddGenConjDecomp(
          +  DdManager * dd, manager
          +  DdNode * f, function to be decomposed
          +  DdNode *** conjuncts address of the array of conjuncts
          +)
          +
          +
          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. +

          + +

          Side Effects 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. +

          + +

          See Also Cudd_bddGenDisjDecomp +Cudd_bddApproxConjDecomp +Cudd_bddIterConjDecomp +Cudd_bddVarConjDecomp + + +
          +
          +int 
          +Cudd_bddGenDisjDecomp(
          +  DdManager * dd, manager
          +  DdNode * f, function to be decomposed
          +  DdNode *** disjuncts address of the array of the disjuncts
          +)
          +
          +
          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. +

          + +

          Side Effects 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. +

          + +

          See Also Cudd_bddGenConjDecomp +Cudd_bddApproxDisjDecomp +Cudd_bddIterDisjDecomp +Cudd_bddVarDisjDecomp + + +
          +
          +DdNode * 
          +Cudd_bddIntersect(
          +  DdManager * dd, manager
          +  DdNode * f, first operand
          +  DdNode * g second operand
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          See Also Cudd_bddLeq +Cudd_bddIteConstant + + +
          +
          +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
          +)
          +
          +
          This function generates a BDD for the function + lowerB ≤ x ≤ 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 ≤ x and x ≤ upperB, and they + are finally conjoined. +

          + +

          Side Effects None +

          + +

          See Also Cudd_Xgty + + +
          +
          +int 
          +Cudd_bddIsNsVar(
          +  DdManager * dd, 
          +  int  index 
          +)
          +
          +
          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. +

          + +

          Side Effects none +

          + +

          See Also Cudd_bddSetNsVar +Cudd_bddIsPiVar +Cudd_bddIsPsVar + + +
          +
          +int 
          +Cudd_bddIsPiVar(
          +  DdManager * dd, manager
          +  int  index variable index
          +)
          +
          +
          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. +

          + +

          Side Effects none +

          + +

          See Also Cudd_bddSetPiVar +Cudd_bddIsPsVar +Cudd_bddIsNsVar + + +
          +
          +int 
          +Cudd_bddIsPsVar(
          +  DdManager * dd, 
          +  int  index 
          +)
          +
          +
          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. +

          + +

          Side Effects none +

          + +

          See Also Cudd_bddSetPsVar +Cudd_bddIsPiVar +Cudd_bddIsNsVar + + +
          +
          +int 
          +Cudd_bddIsVarEssential(
          +  DdManager * manager, 
          +  DdNode * f, 
          +  int  id, 
          +  int  phase 
          +)
          +
          +
          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'. +

          + +

          Side Effects None +

          + +

          See Also Cudd_FindEssential + + +
          +
          +int 
          +Cudd_bddIsVarHardGroup(
          +  DdManager * dd, 
          +  int  index 
          +)
          +
          +
          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. +

          + +

          Side Effects none +

          + +

          See Also Cudd_bddSetVarHardGroup + + +
          +
          +int 
          +Cudd_bddIsVarToBeGrouped(
          +  DdManager * dd, 
          +  int  index 
          +)
          +
          +
          Checks whether a variable is set to be grouped. This + function is used for lazy sifting. +

          + +

          Side Effects none +

          + +

          +
          +int 
          +Cudd_bddIsVarToBeUngrouped(
          +  DdManager * dd, 
          +  int  index 
          +)
          +
          +
          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. +

          + +

          Side Effects none +

          + +

          See Also Cudd_bddSetVarToBeUngrouped + + +
          +
          +DdNode	* 
          +Cudd_bddIsop(
          +  DdManager * dd, 
          +  DdNode * L, 
          +  DdNode * U 
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          See Also Cudd_zddIsop + + +
          +
          +DdNode * 
          +Cudd_bddIteConstant(
          +  DdManager * dd, 
          +  DdNode * f, 
          +  DdNode * g, 
          +  DdNode * h 
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          See Also Cudd_bddIte +Cudd_bddIntersect +Cudd_bddLeq +Cudd_addIteConstant + + +
          +
          +int 
          +Cudd_bddIterConjDecomp(
          +  DdManager * dd, manager
          +  DdNode * f, function to be decomposed
          +  DdNode *** conjuncts address of the array of conjuncts
          +)
          +
          +
          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. +

          + +

          Side Effects 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. +

          + +

          See Also Cudd_bddIterDisjDecomp +Cudd_bddApproxConjDecomp +Cudd_bddGenConjDecomp +Cudd_bddVarConjDecomp +Cudd_RemapOverApprox +Cudd_bddSqueeze +Cudd_bddLICompaction + + +
          +
          +int 
          +Cudd_bddIterDisjDecomp(
          +  DdManager * dd, manager
          +  DdNode * f, function to be decomposed
          +  DdNode *** disjuncts address of the array of the disjuncts
          +)
          +
          +
          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. +

          + +

          Side Effects 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. +

          + +

          See Also Cudd_bddIterConjDecomp +Cudd_bddApproxDisjDecomp +Cudd_bddGenDisjDecomp +Cudd_bddVarDisjDecomp + + +
          +
          +DdNode * 
          +Cudd_bddIte(
          +  DdManager * dd, 
          +  DdNode * f, 
          +  DdNode * g, 
          +  DdNode * h 
          +)
          +
          +
          Implements ITE(f,g,h). Returns a pointer to the + resulting BDD if successful; NULL if the intermediate result blows + up. +

          + +

          Side Effects None +

          + +

          See Also Cudd_addIte +Cudd_bddIteConstant +Cudd_bddIntersect + + +
          +
          +DdNode * 
          +Cudd_bddIthVar(
          +  DdManager * dd, 
          +  int  i 
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          See Also Cudd_bddNewVar +Cudd_addIthVar +Cudd_bddNewVarAtLevel +Cudd_ReadVars + + +
          +
          +DdNode * 
          +Cudd_bddLICompaction(
          +  DdManager * dd, manager
          +  DdNode * f, function to be minimized
          +  DdNode * c constraint (care set)
          +)
          +
          +
          Performs safe minimization of a BDD. Given the BDD + f of a function to be minimized and a BDD + c representing the care set, Cudd_bddLICompaction + produces the BDD of a function that agrees with f + wherever c is 1. Safe minimization means that the size + of the result is guaranteed not to exceed the size of + f. This function is based on the DAC97 paper by Hong et + al.. Returns a pointer to the result if successful; NULL + otherwise. +

          + +

          Side Effects None +

          + +

          See Also Cudd_bddRestrict + + +
          +
          +int 
          +Cudd_bddLeqUnless(
          +  DdManager * dd, 
          +  DdNode * f, 
          +  DdNode * g, 
          +  DdNode * D 
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          See Also Cudd_EquivDC +Cudd_bddLeq +Cudd_bddIteConstant + + +
          +
          +int 
          +Cudd_bddLeq(
          +  DdManager * dd, 
          +  DdNode * f, 
          +  DdNode * g 
          +)
          +
          +
          Returns 1 if f is less than or equal to g; 0 otherwise. + No new nodes are created. +

          + +

          Side Effects None +

          + +

          See Also Cudd_bddIteConstant +Cudd_addEvalConst + + +
          +
          +DdNode * 
          +Cudd_bddLiteralSetIntersection(
          +  DdManager * dd, 
          +  DdNode * f, 
          +  DdNode * g 
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          +
          +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
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          +
          +DdNode * 
          +Cudd_bddMinimize(
          +  DdManager * dd, 
          +  DdNode * f, 
          +  DdNode * c 
          +)
          +
          +
          Finds a small BDD that agrees with f over + c. Returns a pointer to the result if successful; NULL + otherwise. +

          + +

          Side Effects None +

          + +

          See Also Cudd_bddRestrict +Cudd_bddLICompaction +Cudd_bddSqueeze + + +
          +
          +DdNode * 
          +Cudd_bddNPAnd(
          +  DdManager * dd, 
          +  DdNode * f, 
          +  DdNode * g 
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          See Also Cudd_bddConstrain +Cudd_bddRestrict + + +
          +
          +DdNode * 
          +Cudd_bddNand(
          +  DdManager * dd, 
          +  DdNode * f, 
          +  DdNode * g 
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          See Also Cudd_bddIte +Cudd_addApply +Cudd_bddAnd +Cudd_bddOr +Cudd_bddNor +Cudd_bddXor +Cudd_bddXnor + + +
          +
          +DdNode * 
          +Cudd_bddNewVarAtLevel(
          +  DdManager * dd, 
          +  int  level 
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          See Also Cudd_bddNewVar +Cudd_bddIthVar +Cudd_addNewVarAtLevel + + +
          +
          +DdNode * 
          +Cudd_bddNewVar(
          +  DdManager * dd 
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          See Also Cudd_addNewVar +Cudd_bddIthVar +Cudd_bddNewVarAtLevel + + +
          +
          +DdNode * 
          +Cudd_bddNor(
          +  DdManager * dd, 
          +  DdNode * f, 
          +  DdNode * g 
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          See Also Cudd_bddIte +Cudd_addApply +Cudd_bddAnd +Cudd_bddOr +Cudd_bddNand +Cudd_bddXor +Cudd_bddXnor + + +
          +
          +DdNode * 
          +Cudd_bddOr(
          +  DdManager * dd, 
          +  DdNode * f, 
          +  DdNode * g 
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          See Also Cudd_bddIte +Cudd_addApply +Cudd_bddAnd +Cudd_bddNand +Cudd_bddNor +Cudd_bddXor +Cudd_bddXnor + + +
          +
          +DdNode * 
          +Cudd_bddPermute(
          +  DdManager * manager, 
          +  DdNode * node, 
          +  int * permut 
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          See Also Cudd_addPermute +Cudd_bddSwapVariables + + +
          +
          +DdNode ** 
          +Cudd_bddPickArbitraryMinterms(
          +  DdManager * dd, manager
          +  DdNode * f, function from which to pick k minterms
          +  DdNode ** vars, array of variables
          +  int  n, size of vars
          +  int  k number of minterms to find
          +)
          +
          +
          Picks k on-set minterms evenly distributed from given DD. + The minterms are in terms of vars. The array + vars should contain at least all variables in the + support of f; if this condition is not met the minterms + built by this procedure may not be contained in + f. 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: +
            +
          • It may run out of memory; +
          • the function f may be the constant 0; +
          • the minterms may not be contained in f. +
          +

          + +

          Side Effects None +

          + +

          See Also Cudd_bddPickOneMinterm +Cudd_bddPickOneCube + + +
          +
          +int 
          +Cudd_bddPickOneCube(
          +  DdManager * ddm, 
          +  DdNode * node, 
          +  char * string 
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          See Also Cudd_bddPickOneMinterm + + +
          +
          +DdNode * 
          +Cudd_bddPickOneMinterm(
          +  DdManager * dd, manager
          +  DdNode * f, function from which to pick one minterm
          +  DdNode ** vars, array of variables
          +  int  n size of vars
          +)
          +
          +
          Picks one on-set minterm randomly from the given + DD. The minterm is in terms of vars. The array + vars should contain at least all variables in the + support of f; if this condition is not met the minterm + built by this procedure may not be contained in + f. 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: +
            +
          • It may run out of memory; +
          • the function f may be the constant 0; +
          • the minterm may not be contained in f. +
          +

          + +

          Side Effects None +

          + +

          See Also Cudd_bddPickOneCube + + +
          +
          +int 
          +Cudd_bddPrintCover(
          +  DdManager * dd, 
          +  DdNode * l, 
          +  DdNode * u 
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          See Also Cudd_PrintMinterm + + +
          +
          +int 
          +Cudd_bddReadPairIndex(
          +  DdManager * dd, 
          +  int  index 
          +)
          +
          +
          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. +

          + +

          Side Effects modifies the manager +

          + +

          See Also Cudd_bddSetPairIndex + + +
          +
          +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
          +)
          +
          +
          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.

          + 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.

          + 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. +

          + +

          Side Effects 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. +

          + +

          See Also Cudd_addHarwell +Cudd_addRead + + +
          +
          +void 
          +Cudd_bddRealignDisable(
          +  DdManager * unique 
          +)
          +
          +
          Disables realignment of ZDD order to BDD order. +

          + +

          Side Effects None +

          + +

          See Also Cudd_bddRealignEnable +Cudd_bddRealignmentEnabled +Cudd_zddRealignEnable +Cudd_zddRealignmentEnabled + + +
          +
          +void 
          +Cudd_bddRealignEnable(
          +  DdManager * unique 
          +)
          +
          +
          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 M be the + ratio of the two numbers. For the purpose of realignment, the ZDD + variables from M*i to (M+1)*i-1 are + reagarded as corresponding to BDD variable i. Realignment + is initially disabled. +

          + +

          Side Effects None +

          + +

          See Also Cudd_zddReduceHeap +Cudd_bddRealignDisable +Cudd_bddRealignmentEnabled +Cudd_zddRealignDisable +Cudd_zddRealignmentEnabled + + +
          +
          +int 
          +Cudd_bddRealignmentEnabled(
          +  DdManager * unique 
          +)
          +
          +
          Returns 1 if the realignment of BDD order to ZDD order is + enabled; 0 otherwise. +

          + +

          Side Effects None +

          + +

          See Also Cudd_bddRealignEnable +Cudd_bddRealignDisable +Cudd_zddRealignEnable +Cudd_zddRealignDisable + + +
          +
          +int 
          +Cudd_bddResetVarToBeGrouped(
          +  DdManager * dd, 
          +  int  index 
          +)
          +
          +
          Resets a variable not to be grouped. This function is + used for lazy sifting. Returns 1 if successful; 0 otherwise. +

          + +

          Side Effects modifies the manager +

          + +

          See Also Cudd_bddSetVarToBeGrouped +Cudd_bddSetVarHardGroup + + +
          +
          +DdNode * 
          +Cudd_bddRestrict(
          +  DdManager * dd, 
          +  DdNode * f, 
          +  DdNode * c 
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          See Also Cudd_bddConstrain +Cudd_addRestrict + + +
          +
          +int 
          +Cudd_bddSetNsVar(
          +  DdManager * dd, manager
          +  int  index variable index
          +)
          +
          +
          Sets a variable type to next state. The variable type is + used by lazy sifting. Returns 1 if successful; 0 otherwise. +

          + +

          Side Effects modifies the manager +

          + +

          See Also Cudd_bddSetPiVar +Cudd_bddSetPsVar +Cudd_bddIsNsVar + + +
          +
          +int 
          +Cudd_bddSetPairIndex(
          +  DdManager * dd, manager
          +  int  index, variable index
          +  int  pairIndex corresponding variable index
          +)
          +
          +
          Sets a corresponding pair index for a given index. + These pair indices are present and next state variable. Returns 1 if + successful; 0 otherwise. +

          + +

          Side Effects modifies the manager +

          + +

          See Also Cudd_bddReadPairIndex + + +
          +
          +int 
          +Cudd_bddSetPiVar(
          +  DdManager * dd, manager
          +  int  index variable index
          +)
          +
          +
          Sets a variable type to primary input. The variable type is + used by lazy sifting. Returns 1 if successful; 0 otherwise. +

          + +

          Side Effects modifies the manager +

          + +

          See Also Cudd_bddSetPsVar +Cudd_bddSetNsVar +Cudd_bddIsPiVar + + +
          +
          +int 
          +Cudd_bddSetPsVar(
          +  DdManager * dd, manager
          +  int  index variable index
          +)
          +
          +
          Sets a variable type to present state. The variable type is + used by lazy sifting. Returns 1 if successful; 0 otherwise. +

          + +

          Side Effects modifies the manager +

          + +

          See Also Cudd_bddSetPiVar +Cudd_bddSetNsVar +Cudd_bddIsPsVar + + +
          +
          +int 
          +Cudd_bddSetVarHardGroup(
          +  DdManager * dd, 
          +  int  index 
          +)
          +
          +
          Sets a variable to be a hard group. This function is used + for lazy sifting. Returns 1 if successful; 0 otherwise. +

          + +

          Side Effects modifies the manager +

          + +

          See Also Cudd_bddSetVarToBeGrouped +Cudd_bddResetVarToBeGrouped +Cudd_bddIsVarHardGroup + + +
          +
          +int 
          +Cudd_bddSetVarToBeGrouped(
          +  DdManager * dd, 
          +  int  index 
          +)
          +
          +
          Sets a variable to be grouped. This function is used for + lazy sifting. Returns 1 if successful; 0 otherwise. +

          + +

          Side Effects modifies the manager +

          + +

          See Also Cudd_bddSetVarHardGroup +Cudd_bddResetVarToBeGrouped + + +
          +
          +int 
          +Cudd_bddSetVarToBeUngrouped(
          +  DdManager * dd, 
          +  int  index 
          +)
          +
          +
          Sets a variable to be ungrouped. This function is used + for lazy sifting. Returns 1 if successful; 0 otherwise. +

          + +

          Side Effects modifies the manager +

          + +

          See Also Cudd_bddIsVarToBeUngrouped + + +
          +
          +DdNode * 
          +Cudd_bddSqueeze(
          +  DdManager * dd, manager
          +  DdNode * l, lower bound
          +  DdNode * u upper bound
          +)
          +
          +
          Finds a small BDD in a function interval. Given BDDs + l and u, 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. +

          + +

          Side Effects None +

          + +

          See Also Cudd_bddRestrict +Cudd_bddLICompaction + + +
          +
          +DdNode * 
          +Cudd_bddSwapVariables(
          +  DdManager * dd, 
          +  DdNode * f, 
          +  DdNode ** x, 
          +  DdNode ** y, 
          +  int  n 
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          See Also Cudd_bddPermute +Cudd_addSwapVariables + + +
          +
          +DdNode * 
          +Cudd_bddTransfer(
          +  DdManager * ddSource, 
          +  DdManager * ddDestination, 
          +  DdNode * f 
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          +
          +int 
          +Cudd_bddUnbindVar(
          +  DdManager * dd, manager
          +  int  index variable index
          +)
          +
          +
          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). +

          + +

          Side Effects Changes the "bindVar" flag in DdSubtable. +

          + +

          See Also Cudd_bddBindVar + + +
          +
          +DdNode * 
          +Cudd_bddUnivAbstract(
          +  DdManager * manager, 
          +  DdNode * f, 
          +  DdNode * cube 
          +)
          +
          +
          Universally abstracts all the variables in cube from f. + Returns the abstracted BDD if successful; NULL otherwise. +

          + +

          Side Effects None +

          + +

          See Also Cudd_bddExistAbstract +Cudd_addUnivAbstract + + +
          +
          +int 
          +Cudd_bddVarConjDecomp(
          +  DdManager * dd, manager
          +  DdNode * f, function to be decomposed
          +  DdNode *** conjuncts address of the array of conjuncts
          +)
          +
          +
          Conjunctively decomposes one BDD according to a + variable. If f is the function of the BDD and + x is the variable, the decomposition is + (f+x)(f+x'). 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. +

          + +

          Side Effects 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. +

          + +

          See Also Cudd_bddVarDisjDecomp +Cudd_bddGenConjDecomp +Cudd_bddApproxConjDecomp +Cudd_bddIterConjDecomp + + +
          +
          +int 
          +Cudd_bddVarDisjDecomp(
          +  DdManager * dd, manager
          +  DdNode * f, function to be decomposed
          +  DdNode *** disjuncts address of the array of the disjuncts
          +)
          +
          +
          Performs two-way disjunctive decomposition of a BDD + according to a variable. If f is the function of the + BDD and x is the variable, the decomposition is + f*x + f*x'. 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. +

          + +

          Side Effects 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. +

          + +

          See Also Cudd_bddVarConjDecomp +Cudd_bddApproxDisjDecomp +Cudd_bddIterDisjDecomp +Cudd_bddGenDisjDecomp + + +
          +
          +int 
          +Cudd_bddVarIsBound(
          +  DdManager * dd, manager
          +  int  index variable index
          +)
          +
          +
          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. +

          + +

          Side Effects none +

          + +

          See Also Cudd_bddBindVar +Cudd_bddUnbindVar + + +
          +
          +int 
          +Cudd_bddVarIsDependent(
          +  DdManager * dd, 
          +  DdNode * f, 
          +  DdNode * var variable
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          +
          +DdNode * 
          +Cudd_bddVarMap(
          +  DdManager * manager, DD manager
          +  DdNode * f function in which to remap variables
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          See Also Cudd_bddPermute +Cudd_bddSwapVariables +Cudd_SetVarMap + + +
          +
          +DdNode * 
          +Cudd_bddVectorCompose(
          +  DdManager * dd, 
          +  DdNode * f, 
          +  DdNode ** vector 
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          See Also Cudd_bddPermute +Cudd_bddCompose +Cudd_addVectorCompose + + +
          +
          +DdNode * 
          +Cudd_bddXnor(
          +  DdManager * dd, 
          +  DdNode * f, 
          +  DdNode * g 
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          See Also Cudd_bddIte +Cudd_addApply +Cudd_bddAnd +Cudd_bddOr +Cudd_bddNand +Cudd_bddNor +Cudd_bddXor + + +
          +
          +DdNode * 
          +Cudd_bddXorExistAbstract(
          +  DdManager * manager, 
          +  DdNode * f, 
          +  DdNode * g, 
          +  DdNode * cube 
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          See Also Cudd_bddUnivAbstract +Cudd_bddExistAbstract +Cudd_bddAndAbstract + + +
          +
          +DdNode * 
          +Cudd_bddXor(
          +  DdManager * dd, 
          +  DdNode * f, 
          +  DdNode * g 
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          See Also Cudd_bddIte +Cudd_addApply +Cudd_bddAnd +Cudd_bddOr +Cudd_bddNand +Cudd_bddNor +Cudd_bddXnor + + +
          +
          +void 
          +Cudd_tlcInfoFree(
          +  DdTlcInfo * t 
          +)
          +
          +
          Frees a DdTlcInfo Structure as well as the memory pointed + by it. +

          + +

          Side Effects None +

          + +

          +
          +DdNode * 
          +Cudd_zddChange(
          +  DdManager * dd, 
          +  DdNode * P, 
          +  int  var 
          +)
          +
          +
          Substitutes a variable with its complement in a ZDD. + returns a pointer to the result if successful; NULL otherwise. +

          + +

          Side Effects None +

          + +

          +
          +DdNode	* 
          +Cudd_zddComplement(
          +  DdManager * dd, 
          +  DdNode * node 
          +)
          +
          +
          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. +

          + +

          Side Effects The result depends on current variable order. +

          + +

          +
          +double 
          +Cudd_zddCountDouble(
          +  DdManager * zdd, 
          +  DdNode * P 
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          See Also Cudd_zddCountMinterm +Cudd_zddCount + + +
          +
          +double 
          +Cudd_zddCountMinterm(
          +  DdManager * zdd, 
          +  DdNode * node, 
          +  int  path 
          +)
          +
          +
          Counts the number of minterms of the ZDD rooted at + node. This procedure takes a parameter + path 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. +

          + +

          Side Effects None +

          + +

          See Also Cudd_zddCountDouble + + +
          +
          +int 
          +Cudd_zddCount(
          +  DdManager * zdd, 
          +  DdNode * P 
          +)
          +
          +
          Returns an integer representing the number of minterms + in a ZDD. +

          + +

          Side Effects None +

          + +

          See Also Cudd_zddCountDouble + + +
          +
          +char * 
          +Cudd_zddCoverPathToString(
          +  DdManager * zdd, DD manager
          +  int * path, path of ZDD representing a cover
          +  char * str pointer to string to use if != NULL
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          See Also Cudd_zddForeachPath + + +
          +
          +int 
          +Cudd_zddDagSize(
          +  DdNode * p_node 
          +)
          +
          +
          Counts the number of nodes in a ZDD. This function + duplicates Cudd_DagSize and is only retained for compatibility. +

          + +

          Side Effects None +

          + +

          See Also Cudd_DagSize + + +
          +
          +DdNode * 
          +Cudd_zddDiffConst(
          +  DdManager * zdd, 
          +  DdNode * P, 
          +  DdNode * Q 
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          See Also Cudd_zddDiff + + +
          +
          +DdNode * 
          +Cudd_zddDiff(
          +  DdManager * dd, 
          +  DdNode * P, 
          +  DdNode * Q 
          +)
          +
          +
          Computes the difference of two ZDDs. Returns a pointer to the + result if successful; NULL otherwise. +

          + +

          Side Effects None +

          + +

          See Also Cudd_zddDiffConst + + +
          +
          +DdNode	* 
          +Cudd_zddDivideF(
          +  DdManager * dd, 
          +  DdNode * f, 
          +  DdNode * g 
          +)
          +
          +
          Modified version of Cudd_zddDivide. This function may + disappear in future releases. +

          + +

          Side Effects None +

          + +

          +
          +DdNode	* 
          +Cudd_zddDivide(
          +  DdManager * dd, 
          +  DdNode * f, 
          +  DdNode * g 
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          See Also Cudd_zddWeakDiv + + +
          +
          +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
          +)
          +
          +
          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: +
            +
          • solid line: THEN arcs; +
          • dashed line: ELSE arcs. +
          + The dot options are chosen so that the drawing fits on a letter-size + sheet. +

          + +

          Side Effects None +

          + +

          See Also Cudd_DumpDot +Cudd_zddPrintDebug + + +
          +
          +DdGen * 
          +Cudd_zddFirstPath(
          +  DdManager * zdd, 
          +  DdNode * f, 
          +  int ** path 
          +)
          +
          +
          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.

          + 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.

          + The paths that end in the empty terminal are not enumerated. +

          + +

          Side Effects The first path is returned as a side effect. +

          + +

          See Also Cudd_zddForeachPath +Cudd_zddNextPath +Cudd_GenFree +Cudd_IsGenEmpty + + +
          +
          +DdNode * 
          +Cudd_zddIntersect(
          +  DdManager * dd, 
          +  DdNode * P, 
          +  DdNode * Q 
          +)
          +
          +
          Computes the intersection of two ZDDs. Returns a pointer to + the result if successful; NULL otherwise. +

          + +

          Side Effects None +

          + +

          +
          +DdNode	* 
          +Cudd_zddIsop(
          +  DdManager * dd, 
          +  DdNode * L, 
          +  DdNode * U, 
          +  DdNode ** zdd_I 
          +)
          +
          +
          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 i should have indices 2i and + 2i+1. 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. +

          + +

          Side Effects zdd_I holds the pointer to the ZDD for the ISOP on + successful return. +

          + +

          See Also Cudd_bddIsop +Cudd_zddVarsFromBddVars + + +
          +
          +DdNode * 
          +Cudd_zddIte(
          +  DdManager * dd, 
          +  DdNode * f, 
          +  DdNode * g, 
          +  DdNode * h 
          +)
          +
          +
          Computes the ITE of three ZDDs. Returns a pointer to the + result if successful; NULL otherwise. +

          + +

          Side Effects None +

          + +

          +
          +DdNode * 
          +Cudd_zddIthVar(
          +  DdManager * dd, 
          +  int  i 
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          See Also Cudd_bddIthVar +Cudd_addIthVar + + +
          +
          +int 
          +Cudd_zddNextPath(
          +  DdGen * gen, 
          +  int ** path 
          +)
          +
          +
          Generates the next path of a ZDD onset, + using generator gen. Returns 0 if the enumeration is completed; 1 + otherwise. +

          + +

          Side Effects The path is returned as a side effect. The + generator is modified. +

          + +

          See Also Cudd_zddForeachPath +Cudd_zddFirstPath +Cudd_GenFree +Cudd_IsGenEmpty + + +
          +
          +DdNode * 
          +Cudd_zddPortFromBdd(
          +  DdManager * dd, 
          +  DdNode * B 
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          See Also Cudd_zddVarsFromBddVars + + +
          +
          +DdNode * 
          +Cudd_zddPortToBdd(
          +  DdManager * dd, 
          +  DdNode * f 
          +)
          +
          +
          Converts a ZDD into a BDD. Returns a pointer to the resulting + ZDD if successful; NULL otherwise. +

          + +

          Side Effects None +

          + +

          See Also Cudd_zddPortFromBdd + + +
          +
          +int 
          +Cudd_zddPrintCover(
          +  DdManager * zdd, 
          +  DdNode * node 
          +)
          +
          +
          Prints a sum of products from a ZDD representing a cover. + Returns 1 if successful; 0 otherwise. +

          + +

          Side Effects None +

          + +

          See Also Cudd_zddPrintMinterm + + +
          +
          +int 
          +Cudd_zddPrintDebug(
          +  DdManager * zdd, 
          +  DdNode * f, 
          +  int  n, 
          +  int  pr 
          +)
          +
          +
          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 > 0. Specifically: +
            +
          • pr = 0 : prints nothing +
          • pr = 1 : prints counts of nodes and minterms +
          • pr = 2 : prints counts + disjoint sum of products +
          • pr = 3 : prints counts + list of nodes +
          • pr > 3 : prints counts + disjoint sum of products + list of nodes +
          + Returns 1 if successful; 0 otherwise. +

          + +

          Side Effects None +

          + +

          +
          +int 
          +Cudd_zddPrintMinterm(
          +  DdManager * zdd, 
          +  DdNode * node 
          +)
          +
          +
          Prints a disjoint sum of product form for a ZDD. Returns 1 + if successful; 0 otherwise. +

          + +

          Side Effects None +

          + +

          See Also Cudd_zddPrintDebug +Cudd_zddPrintCover + + +
          +
          +void 
          +Cudd_zddPrintSubtable(
          +  DdManager * table 
          +)
          +
          +
          Prints the ZDD table for debugging purposes. +

          + +

          Side Effects None +

          + +

          +
          +DdNode	* 
          +Cudd_zddProduct(
          +  DdManager * dd, 
          +  DdNode * f, 
          +  DdNode * g 
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          See Also Cudd_zddUnateProduct + + +
          +
          +long 
          +Cudd_zddReadNodeCount(
          +  DdManager * dd 
          +)
          +
          +
          Reports the number of nodes in ZDDs. This + number always includes the two constants 1 and 0. +

          + +

          Side Effects None +

          + +

          See Also Cudd_ReadPeakNodeCount +Cudd_ReadNodeCount + + +
          +
          +void 
          +Cudd_zddRealignDisable(
          +  DdManager * unique 
          +)
          +
          +
          Disables realignment of ZDD order to BDD order. +

          + +

          Side Effects None +

          + +

          See Also Cudd_zddRealignEnable +Cudd_zddRealignmentEnabled +Cudd_bddRealignEnable +Cudd_bddRealignmentEnabled + + +
          +
          +void 
          +Cudd_zddRealignEnable(
          +  DdManager * unique 
          +)
          +
          +
          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 M be the + ratio of the two numbers. For the purpose of realignment, the ZDD + variables from M*i to (M+1)*i-1 are + reagarded as corresponding to BDD variable i. Realignment + is initially disabled. +

          + +

          Side Effects None +

          + +

          See Also Cudd_ReduceHeap +Cudd_zddRealignDisable +Cudd_zddRealignmentEnabled +Cudd_bddRealignDisable +Cudd_bddRealignmentEnabled + + +
          +
          +int 
          +Cudd_zddRealignmentEnabled(
          +  DdManager * unique 
          +)
          +
          +
          Returns 1 if the realignment of ZDD order to BDD order is + enabled; 0 otherwise. +

          + +

          Side Effects None +

          + +

          See Also Cudd_zddRealignEnable +Cudd_zddRealignDisable +Cudd_bddRealignEnable +Cudd_bddRealignDisable + + +
          +
          +int 
          +Cudd_zddReduceHeap(
          +  DdManager * table, DD manager
          +  Cudd_ReorderingType  heuristic, method used for reordering
          +  int  minsize bound below which no reordering occurs
          +)
          +
          +
          Main dynamic reordering routine for ZDDs. + Calls one of the possible reordering procedures: +
            +
          • Swapping +
          • Sifting +
          • Symmetric Sifting +
          + + For sifting and symmetric sifting it is possible to request reordering + to convergence.

          + + 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. +

          + +

          Side Effects Changes the variable order for all ZDDs and clears + the cache. +

          + +

          +
          +int 
          +Cudd_zddShuffleHeap(
          +  DdManager * table, DD manager
          +  int * permutation required variable permutation
          +)
          +
          +
          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. +

          + +

          Side Effects Changes the ZDD variable order for all diagrams and clears + the cache. +

          + +

          See Also Cudd_zddReduceHeap + + +
          +
          +DdNode * 
          +Cudd_zddSubset0(
          +  DdManager * dd, 
          +  DdNode * P, 
          +  int  var 
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          See Also Cudd_zddSubset1 + + +
          +
          +DdNode * 
          +Cudd_zddSubset1(
          +  DdManager * dd, 
          +  DdNode * P, 
          +  int  var 
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          See Also Cudd_zddSubset0 + + +
          +
          +void 
          +Cudd_zddSymmProfile(
          +  DdManager * table, 
          +  int  lower, 
          +  int  upper 
          +)
          +
          +
          Prints statistics on symmetric ZDD variables. +

          + +

          Side Effects None +

          + +

          +
          +DdNode	* 
          +Cudd_zddUnateProduct(
          +  DdManager * dd, 
          +  DdNode * f, 
          +  DdNode * g 
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          See Also Cudd_zddProduct + + +
          +
          +DdNode * 
          +Cudd_zddUnion(
          +  DdManager * dd, 
          +  DdNode * P, 
          +  DdNode * Q 
          +)
          +
          +
          Computes the union of two ZDDs. Returns a pointer to the + result if successful; NULL otherwise. +

          + +

          Side Effects None +

          + +

          +
          +int 
          +Cudd_zddVarsFromBddVars(
          +  DdManager * dd, DD manager
          +  int  multiplicity how many ZDD variables are created for each BDD variable
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          See Also Cudd_bddNewVar +Cudd_bddIthVar +Cudd_bddNewVarAtLevel + + +
          +
          +DdNode	* 
          +Cudd_zddWeakDivF(
          +  DdManager * dd, 
          +  DdNode * f, 
          +  DdNode * g 
          +)
          +
          +
          Modified version of Cudd_zddWeakDiv. This function may + disappear in future releases. +

          + +

          Side Effects None +

          + +

          See Also Cudd_zddWeakDiv + + +
          +
          +DdNode	* 
          +Cudd_zddWeakDiv(
          +  DdManager * dd, 
          +  DdNode * f, 
          +  DdNode * g 
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          See Also Cudd_zddDivide + + + +
          +
          +Last updated on 20090220 23h06 + diff --git a/distr/cudd/doc/cuddIntro.css b/distr/cudd/doc/cuddIntro.css new file mode 100644 index 0000000..d1824af --- /dev/null +++ b/distr/cudd/doc/cuddIntro.css @@ -0,0 +1,30 @@ +/* Century Schoolbook font is very similar to Computer Modern Math: cmmi */ +.MATH { font-family: "Century Schoolbook", serif; } +.MATH I { font-family: "Century Schoolbook", serif; font-style: italic } +.BOLDMATH { font-family: "Century Schoolbook", serif; font-weight: bold } + +/* implement both fixed-size and relative sizes */ +SMALL.XTINY { font-size : xx-small } +SMALL.TINY { font-size : x-small } +SMALL.SCRIPTSIZE { font-size : smaller } +SMALL.FOOTNOTESIZE { font-size : small } +SMALL.SMALL { } +BIG.LARGE { } +BIG.XLARGE { font-size : large } +BIG.XXLARGE { font-size : x-large } +BIG.HUGE { font-size : larger } +BIG.XHUGE { font-size : xx-large } + +/* heading styles */ +H1 { } +H2 { } +H3 { } +H4 { } +H5 { } + +/* mathematics styles */ +DIV.displaymath { } /* math displays */ +TD.eqno { } /* equation-number cells */ + + +/* document-specific styles come next */ diff --git a/distr/cudd/doc/cuddIntro.html b/distr/cudd/doc/cuddIntro.html new file mode 100644 index 0000000..88285ad --- /dev/null +++ b/distr/cudd/doc/cuddIntro.html @@ -0,0 +1,220 @@ + + + + + +CUDD: CU Decision Diagram Package +Release 2.4.2 + + + + + + + + + + + + + + + + +next +up +previous + +index +
          + Next: Introduction +   Index +
          +
          + + +

          CUDD: CU Decision Diagram Package +
          +Release 2.4.2

          +
          + +

          Fabio Somenzi

          +

          Department of Electrical, Computer, and Energy Engineering

          +

          University of Colorado at Boulder

          +
          + +

          +


          + + + + + +

          +
          +Fabio Somenzi +2009-02-20 +
          + + diff --git a/distr/cudd/doc/cuddTitle.html b/distr/cudd/doc/cuddTitle.html new file mode 100644 index 0000000..2530e55 --- /dev/null +++ b/distr/cudd/doc/cuddTitle.html @@ -0,0 +1,17 @@ + +The cudd package: Title + + + + + + + + +
          + Programmer view + Maintainer by function + Maintainer by file
          + + + diff --git a/distr/cudd/doc/footnode.html b/distr/cudd/doc/footnode.html new file mode 100644 index 0000000..c5bca24 --- /dev/null +++ b/distr/cudd/doc/footnode.html @@ -0,0 +1,112 @@ + + + + + +Footnotes + + + + + + + + + + + + + + + + +
          +
          ... application.1
          +
          The + global statistical counters are used locally; hence they are + compatible with the use of multiple managers. + +
          .
          +.
          +.
          +.
          +.
          +.
          +.
          +.
          +.
          +.
          +.
          +.
          +.
          +.
          +.
          +.
          +.
          +.
          +.
          +.
          +.
          +.
          +.
          +.
          +.
          +.
          +.
          +.
          +.
          +.
          +
          +
          +
          ... +node.2
          +
          When the variables in a group are reordered, the + association between the low field and the index of the first + variable in the group is lost. The package updates the tree to keep + track of the changes. However, the application cannot rely on + low to determine the position of variables. + +
          .
          +.
          +.
          +.
          +.
          +.
          +.
          +.
          +.
          +.
          +.
          +.
          +.
          +.
          +.
          +.
          +.
          +.
          +.
          +.
          +.
          +.
          +.
          +.
          +.
          +.
          +.
          +.
          +.
          +.
          +
          +
          +
          + + diff --git a/distr/cudd/doc/icons/blueball.png b/distr/cudd/doc/icons/blueball.png new file mode 100644 index 0000000..9720c29 Binary files /dev/null and b/distr/cudd/doc/icons/blueball.png differ diff --git a/distr/cudd/doc/icons/ch_beg_r.png b/distr/cudd/doc/icons/ch_beg_r.png new file mode 100644 index 0000000..807941a Binary files /dev/null and b/distr/cudd/doc/icons/ch_beg_r.png differ diff --git a/distr/cudd/doc/icons/ch_begin.png b/distr/cudd/doc/icons/ch_begin.png new file mode 100644 index 0000000..0b3a6e2 Binary files /dev/null and b/distr/cudd/doc/icons/ch_begin.png differ diff --git a/distr/cudd/doc/icons/ch_del_r.png b/distr/cudd/doc/icons/ch_del_r.png new file mode 100644 index 0000000..d5ae8e5 Binary files /dev/null and b/distr/cudd/doc/icons/ch_del_r.png differ diff --git a/distr/cudd/doc/icons/ch_delet.png b/distr/cudd/doc/icons/ch_delet.png new file mode 100644 index 0000000..d5ae8e5 Binary files /dev/null and b/distr/cudd/doc/icons/ch_delet.png differ diff --git a/distr/cudd/doc/icons/ch_end.png b/distr/cudd/doc/icons/ch_end.png new file mode 100644 index 0000000..1f8f91c Binary files /dev/null and b/distr/cudd/doc/icons/ch_end.png differ diff --git a/distr/cudd/doc/icons/ch_end_r.png b/distr/cudd/doc/icons/ch_end_r.png new file mode 100644 index 0000000..3059c93 Binary files /dev/null and b/distr/cudd/doc/icons/ch_end_r.png differ diff --git a/distr/cudd/doc/icons/contents.png b/distr/cudd/doc/icons/contents.png new file mode 100644 index 0000000..0c752c6 Binary files /dev/null and b/distr/cudd/doc/icons/contents.png differ diff --git a/distr/cudd/doc/icons/crossref.png b/distr/cudd/doc/icons/crossref.png new file mode 100644 index 0000000..7dd2ddd Binary files /dev/null and b/distr/cudd/doc/icons/crossref.png differ diff --git a/distr/cudd/doc/icons/footnote.png b/distr/cudd/doc/icons/footnote.png new file mode 100644 index 0000000..4591c0e Binary files /dev/null and b/distr/cudd/doc/icons/footnote.png differ diff --git a/distr/cudd/doc/icons/greenball.png b/distr/cudd/doc/icons/greenball.png new file mode 100644 index 0000000..a4d7145 Binary files /dev/null and b/distr/cudd/doc/icons/greenball.png differ diff --git a/distr/cudd/doc/icons/image.png b/distr/cudd/doc/icons/image.png new file mode 100644 index 0000000..05ffff5 Binary files /dev/null and b/distr/cudd/doc/icons/image.png differ diff --git a/distr/cudd/doc/icons/index.png b/distr/cudd/doc/icons/index.png new file mode 100644 index 0000000..698f09c Binary files /dev/null and b/distr/cudd/doc/icons/index.png differ diff --git a/distr/cudd/doc/icons/next.png b/distr/cudd/doc/icons/next.png new file mode 100644 index 0000000..1628652 Binary files /dev/null and b/distr/cudd/doc/icons/next.png differ diff --git a/distr/cudd/doc/icons/next_g.png b/distr/cudd/doc/icons/next_g.png new file mode 100644 index 0000000..9d3f591 Binary files /dev/null and b/distr/cudd/doc/icons/next_g.png differ diff --git a/distr/cudd/doc/icons/nx_grp.png b/distr/cudd/doc/icons/nx_grp.png new file mode 100644 index 0000000..4ec914a Binary files /dev/null and b/distr/cudd/doc/icons/nx_grp.png differ diff --git a/distr/cudd/doc/icons/nx_grp_g.png b/distr/cudd/doc/icons/nx_grp_g.png new file mode 100644 index 0000000..b2277a1 Binary files /dev/null and b/distr/cudd/doc/icons/nx_grp_g.png differ diff --git a/distr/cudd/doc/icons/orangeball.png b/distr/cudd/doc/icons/orangeball.png new file mode 100644 index 0000000..10249c6 Binary files /dev/null and b/distr/cudd/doc/icons/orangeball.png differ diff --git a/distr/cudd/doc/icons/pinkball.png b/distr/cudd/doc/icons/pinkball.png new file mode 100644 index 0000000..5b92325 Binary files /dev/null and b/distr/cudd/doc/icons/pinkball.png differ diff --git a/distr/cudd/doc/icons/prev.png b/distr/cudd/doc/icons/prev.png new file mode 100644 index 0000000..e60b8b4 Binary files /dev/null and b/distr/cudd/doc/icons/prev.png differ diff --git a/distr/cudd/doc/icons/prev_g.png b/distr/cudd/doc/icons/prev_g.png new file mode 100644 index 0000000..476d956 Binary files /dev/null and b/distr/cudd/doc/icons/prev_g.png differ diff --git a/distr/cudd/doc/icons/purpleball.png b/distr/cudd/doc/icons/purpleball.png new file mode 100644 index 0000000..d6d63fb Binary files /dev/null and b/distr/cudd/doc/icons/purpleball.png differ diff --git a/distr/cudd/doc/icons/pv_grp.png b/distr/cudd/doc/icons/pv_grp.png new file mode 100644 index 0000000..b9dec59 Binary files /dev/null and b/distr/cudd/doc/icons/pv_grp.png differ diff --git a/distr/cudd/doc/icons/pv_grp_g.png b/distr/cudd/doc/icons/pv_grp_g.png new file mode 100644 index 0000000..ab9893b Binary files /dev/null and b/distr/cudd/doc/icons/pv_grp_g.png differ diff --git a/distr/cudd/doc/icons/redball.png b/distr/cudd/doc/icons/redball.png new file mode 100644 index 0000000..2e442ba Binary files /dev/null and b/distr/cudd/doc/icons/redball.png differ diff --git a/distr/cudd/doc/icons/up.png b/distr/cudd/doc/icons/up.png new file mode 100644 index 0000000..3937e16 Binary files /dev/null and b/distr/cudd/doc/icons/up.png differ diff --git a/distr/cudd/doc/icons/up_g.png b/distr/cudd/doc/icons/up_g.png new file mode 100644 index 0000000..54ceb68 Binary files /dev/null and b/distr/cudd/doc/icons/up_g.png differ diff --git a/distr/cudd/doc/icons/whiteball.png b/distr/cudd/doc/icons/whiteball.png new file mode 100644 index 0000000..9d30562 Binary files /dev/null and b/distr/cudd/doc/icons/whiteball.png differ diff --git a/distr/cudd/doc/icons/yellowball.png b/distr/cudd/doc/icons/yellowball.png new file mode 100644 index 0000000..ede8fc9 Binary files /dev/null and b/distr/cudd/doc/icons/yellowball.png differ diff --git a/distr/cudd/doc/img1.png b/distr/cudd/doc/img1.png new file mode 100644 index 0000000..3a81412 Binary files /dev/null and b/distr/cudd/doc/img1.png differ diff --git a/distr/cudd/doc/img10.png b/distr/cudd/doc/img10.png new file mode 100644 index 0000000..dbfd674 Binary files /dev/null and b/distr/cudd/doc/img10.png differ diff --git a/distr/cudd/doc/img11.png b/distr/cudd/doc/img11.png new file mode 100644 index 0000000..675a0e7 Binary files /dev/null and b/distr/cudd/doc/img11.png differ diff --git a/distr/cudd/doc/img12.png b/distr/cudd/doc/img12.png new file mode 100644 index 0000000..f657bc6 Binary files /dev/null and b/distr/cudd/doc/img12.png differ diff --git a/distr/cudd/doc/img13.png b/distr/cudd/doc/img13.png new file mode 100644 index 0000000..a6c4fdc Binary files /dev/null and b/distr/cudd/doc/img13.png differ diff --git a/distr/cudd/doc/img14.png b/distr/cudd/doc/img14.png new file mode 100644 index 0000000..4b52d82 Binary files /dev/null and b/distr/cudd/doc/img14.png differ diff --git a/distr/cudd/doc/img15.png b/distr/cudd/doc/img15.png new file mode 100644 index 0000000..3d8c215 Binary files /dev/null and b/distr/cudd/doc/img15.png differ diff --git a/distr/cudd/doc/img16.png b/distr/cudd/doc/img16.png new file mode 100644 index 0000000..c16200a Binary files /dev/null and b/distr/cudd/doc/img16.png differ diff --git a/distr/cudd/doc/img17.png b/distr/cudd/doc/img17.png new file mode 100644 index 0000000..f9c476a Binary files /dev/null and b/distr/cudd/doc/img17.png differ diff --git a/distr/cudd/doc/img18.png b/distr/cudd/doc/img18.png new file mode 100644 index 0000000..b7abbd2 Binary files /dev/null and b/distr/cudd/doc/img18.png differ diff --git a/distr/cudd/doc/img19.png b/distr/cudd/doc/img19.png new file mode 100644 index 0000000..fa21c22 Binary files /dev/null and b/distr/cudd/doc/img19.png differ diff --git a/distr/cudd/doc/img2.png b/distr/cudd/doc/img2.png new file mode 100644 index 0000000..9fff4e7 Binary files /dev/null and b/distr/cudd/doc/img2.png differ diff --git a/distr/cudd/doc/img20.png b/distr/cudd/doc/img20.png new file mode 100644 index 0000000..2f6f8a9 Binary files /dev/null and b/distr/cudd/doc/img20.png differ diff --git a/distr/cudd/doc/img21.png b/distr/cudd/doc/img21.png new file mode 100644 index 0000000..c2c358a Binary files /dev/null and b/distr/cudd/doc/img21.png differ diff --git a/distr/cudd/doc/img22.png b/distr/cudd/doc/img22.png new file mode 100644 index 0000000..1c26248 Binary files /dev/null and b/distr/cudd/doc/img22.png differ diff --git a/distr/cudd/doc/img3.png b/distr/cudd/doc/img3.png new file mode 100644 index 0000000..0f956de Binary files /dev/null and b/distr/cudd/doc/img3.png differ diff --git a/distr/cudd/doc/img4.png b/distr/cudd/doc/img4.png new file mode 100644 index 0000000..b254cdc Binary files /dev/null and b/distr/cudd/doc/img4.png differ diff --git a/distr/cudd/doc/img5.png b/distr/cudd/doc/img5.png new file mode 100644 index 0000000..3913c9b Binary files /dev/null and b/distr/cudd/doc/img5.png differ diff --git a/distr/cudd/doc/img6.png b/distr/cudd/doc/img6.png new file mode 100644 index 0000000..533297f Binary files /dev/null and b/distr/cudd/doc/img6.png differ diff --git a/distr/cudd/doc/img7.png b/distr/cudd/doc/img7.png new file mode 100644 index 0000000..14f32e8 Binary files /dev/null and b/distr/cudd/doc/img7.png differ diff --git a/distr/cudd/doc/img8.png b/distr/cudd/doc/img8.png new file mode 100644 index 0000000..a7619d6 Binary files /dev/null and b/distr/cudd/doc/img8.png differ diff --git a/distr/cudd/doc/img9.png b/distr/cudd/doc/img9.png new file mode 100644 index 0000000..f6aa2d5 Binary files /dev/null and b/distr/cudd/doc/img9.png differ diff --git a/distr/cudd/doc/index.html b/distr/cudd/doc/index.html new file mode 100644 index 0000000..88285ad --- /dev/null +++ b/distr/cudd/doc/index.html @@ -0,0 +1,220 @@ + + + + + +CUDD: CU Decision Diagram Package +Release 2.4.2 + + + + + + + + + + + + + + + + +next +up +previous + +index +
          + Next: Introduction +   Index +
          +
          + + +

          CUDD: CU Decision Diagram Package +
          +Release 2.4.2

          +
          + +

          Fabio Somenzi

          +

          Department of Electrical, Computer, and Energy Engineering

          +

          University of Colorado at Boulder

          +
          + +

          +


          + + + + + +

          +
          +Fabio Somenzi +2009-02-20 +
          + + diff --git a/distr/cudd/doc/node1.html b/distr/cudd/doc/node1.html new file mode 100644 index 0000000..845374a --- /dev/null +++ b/distr/cudd/doc/node1.html @@ -0,0 +1,177 @@ + + + + + +Introduction + + + + + + + + + + + + + + + + + + + +next + +up + +previous + +index +
          + Next: How to Get CUDD + Up: CUDD: CU Decision Diagram + Previous: CUDD: CU Decision Diagram +   Index +
          +
          + + +

          + +
          +Introduction +

          + +

          +The CUDD package provides functions to manipulate Binary Decision +Diagrams (BDDs) [5,3], +Algebraic Decision Diagrams (ADDs) +[1], and Zero-suppressed Binary Decision +Diagrams (ZDDs) +[12]. BDDs are used to represent +switching functions; ADDs are used to +represent function from $\{0,1\}^n$ to an arbitrary set. ZDDs +represent switching functions like BDDs; +however, they are much more efficient than BDDs when the functions to +be represented are characteristic +functions of cube sets, or in general, when the +ON-set of the function to be represented is +very sparse. They are inferior to BDDs in other cases. + +

          +The package provides a large set of operations on BDDs, ADDs, and +ZDDs, functions to convert BDDs into ADDs or ZDDs and vice versa, and +a large assortment of variable reordering methods. + +

          +The CUDD package can be used in three ways: + +

            +
          • As a black box. In this case, the application + program that needs to manipulate decision diagrams only uses the + exported functions of the package. The rich set of functions + included in the CUDD package allows many applications to be written + in this way. Section 3 describes how to use the + exported functions of the package. An application written in terms + of the exported functions of the package needs not concern itself + with the details of variable reordering, which may + take place behind the scenes. +Click here +for a list of the + exported functions. +
          • +
          • As a clear box. When writing a sophisticated + application based on decision diagrams, efficiency often dictates + that some functions be implemented as direct recursive manipulation + of the diagrams, instead of being written in terms of existing + primitive functions. Section 4 explains how to add new + functions to the CUDD package. It also details how to write a + recursive function that can be interrupted by + dynamic variable reordering. +Click here +for a list of the + exported and internal functions. +
          • +
          • Through an interface. Object-oriented languages like C++ and + Perl5 can free the programmer from the burden of memory management. + A C++ interface is included in the distribution of CUDD. It + automatically frees decision diagrams that are no longer used by the + application and overloads operators. Almost all the functionality + provided by the CUDD exported functions is available through the C++ + interface, which is especially recommended for fast prototyping. + Section 5 explains how to use the interface. A Perl5 + interface also exists and is ditributed separately. (See + Section 2.2.) Some applications define their own + interfaces. See for example Section 3.17. +
          • +
          +In the following, the reader is supposed to be familiar with the basic +ideas about decision diagrams, as found, for instance, in [3]. + +

          +


          + + +next + +up + +previous + +index +
          + Next: How to Get CUDD + Up: CUDD: CU Decision Diagram + Previous: CUDD: CU Decision Diagram +   Index + +
          +Fabio Somenzi +2009-02-20 +
          + + diff --git a/distr/cudd/doc/node2.html b/distr/cudd/doc/node2.html new file mode 100644 index 0000000..9bf5814 --- /dev/null +++ b/distr/cudd/doc/node2.html @@ -0,0 +1,178 @@ + + + + + +How to Get CUDD + + + + + + + + + + + + + + + + + + + +next + +up + +previous + +index +
          + Next: User's Manual + Up: CUDD: CU Decision Diagram + Previous: Introduction +   Index +
          +
          + + +Subsections + + + +
          + +

          + +
          +How to Get CUDD +

          + +

          + +

          + +
          +The CUDD Package +

          + +

          +The CUDD package is available via anonymous FTP from +vlsi.Colorado.EDU. A compressed tar file named +cudd-2.4.2.tar.gz can be found in directory pub. +Once you have this file, +

          +gzip -dc cudd-2.4.2.tar.gz | tar xvf - + +
          +will create directory cudd-2.4.2 and its subdirectories. +These directories contain the decision diagram package, a few support +libraries, and a toy application based on the +decision diagram package. There is a README file +with instructions on configuration and +installation in cudd-2.4.2. You can use +a compiler for either ANSI C or C++. + +

          +Once you have made the libraries and program, you can type: +

          +cd nanotrav +
          +nanotrav -p 1 -autodyn -reordering sifting -trav mult32a.blif + +
          +This will run a simple-minded FSM traversal program. (On a 2.4 GHz +Pentium 4 (TM), it takes about 0.5 s.) The +output produced by the program can be checked against +cudd-2.4.2/nanotrav/mult32a.out. More information on the +nanotrav program can be found in +cudd-2.4.2/nanotrav/README. + +

          +If you want to be notified of new releases of the CUDD package, send a +message to Fabio@Colorado.EDU. + +

          + +

          + +
          +CUDD Friends +

          + +

          +Two CUDD extensions are available via anonymous FTP from +vlsi.Colorado.EDU. + +

            +
          • PerlDD is an object-oriented Perl5 interface to CUDD. It + is organized as a standard Perl extension module. The Perl interface + is at a somewhat higher level than the C++ interface, but it is not + as complete. +
          • +
          • DDcal is a graphic BDD calculator based on CUDD, Perl-Tk, + and dot. (See Section 3.18 for information on dot.) + +

            +

          • +

          + + +next + +up + +previous + +index +
          + Next: User's Manual + Up: CUDD: CU Decision Diagram + Previous: Introduction +   Index + +
          +Fabio Somenzi +2009-02-20 +
          + + diff --git a/distr/cudd/doc/node3.html b/distr/cudd/doc/node3.html new file mode 100644 index 0000000..bb0e9ae --- /dev/null +++ b/distr/cudd/doc/node3.html @@ -0,0 +1,1612 @@ + + + + + +User's Manual + + + + + + + + + + + + + + + + + + + +next + +up + +previous + +index +
          + Next: Programmer's Manual + Up: CUDD: CU Decision Diagram + Previous: How to Get CUDD +   Index +
          +
          + + +Subsections + + + +
          + +

          + +
          +User's Manual +

          + +

          +This section describes the use of the CUDD package as a black box. + +

          + +

          + +
          +Compiling and Linking +

          + +

          +To build an application that uses the CUDD package, you should add +

          +#include "util.h"
          +#include "cudd.h"
          +
          + +to your source files, and should link +libcudd.a, +libmtr.a, +libst.a, and +libutil.a to your executable. (All these +libraries are part of the distribution.) Some +platforms require specific compiler and linker flags. Refer to the +Makefile in the top level directory of the +distribution. + +

          +Keep in mind that whatever flags affect the size of data +structures--for instance the flags used to use 64-bit pointers where +available--must be specified when compiling both CUDD and the files +that include its header files. + +

          + +

          + +
          +Basic Data Structures +

          + +

          + +

          + +
          +Nodes +

          + +

          +BDDs, ADDs, and ZDDs are made of DdNode's. A DdNode +(node for short) is a structure with several fields. Those +that are of interest to the application that uses the CUDD package as +a black box are the variable index, the +reference count, and the value. The +remaining fields are pointers that connect nodes among themselves and +that are used to implement the unique table. (See +Section 3.2.2.) + +

          +The index field holds the name of the variable that labels the +node. The index of a variable is a permanent attribute that reflects +the order of creation. Index 0 corresponds to +the variable created first. On a machine with 32-bit pointers, the +maximum number of variables is the largest value that can be stored in +an unsigned short integer minus 1. The largest index is reserved for +the constant nodes. When 64-bit pointers are +used, the maximum number of variables is the largest value that can be +stored in an unsigned integer minus 1. + +

          +When variables are reordered to reduce the size of the decision +diagrams, the variables may shift in the order, but they retain their +indices. The package keeps track of the variable +permutation (and its inverse). The +application is not affected by variable reordering, +except in the following cases. + +

            +
          • If the application uses generators + (Cudd_ForeachCube and + Cudd_ForeachNode) and reordering is + enabled, then it must take care not to call any operation that may + create new nodes (and hence possibly trigger reordering). This is + because the cubes (i.e., paths) and nodes of a diagram change as a + result of reordering. +
          • +
          • If the application uses + Cudd_bddConstrain and reordering + takes place, then the property of Cudd_bddConstrain of + being an image restrictor is lost. +
          • +
          + +

          +The CUDD package relies on garbage +collection to reclaim the memory used by diagrams that are no longer +in use. The scheme employed for garbage collection is based on keeping +a reference count for each node. The +references that are counted are both the internal references +(references from other nodes) and external references (typically +references from the calling environment). When an application creates +a new BDD, ADD, or ZDD, it must +increase its reference count explicitly, through a call to +Cudd_Ref. Similarly, when a diagram is no +longer needed, the application must call +Cudd_RecursiveDeref (for BDDs and +ADDs) or Cudd_RecursiveDerefZdd +(for ZDDs) to ``recycle'' the nodes of the +diagram. + +

          +Terminal nodes carry a value. This is especially +important for ADDs. By default, the value is a double. +To change to something different (e.g., an integer), the +package must be modified and recompiled. Support for this process is +currently very rudimentary. + +

          + +

          + +
          +The Manager +

          + +

          +All nodes used in BDDs, ADDs, and ZDDs are kept in special +hash tables called the +unique tables. Specifically, BDDs and ADDs +share the same unique table, whereas ZDDs have their own table. As +the name implies, the main purpose of the unique table is to guarantee +that each node is unique; that is, there is no other node labeled by +the same variable and with the same children. This uniqueness +property makes decision diagrams canonical. The +unique tables and some auxiliary data structures +make up the DdManager (manager for +short). Though the application that uses only the exported functions +needs not be concerned with most details of the manager, it has to +deal with the manager in the following sense. The application must +initialize the manager by calling an appropriate function. (See +Section 3.3.) Subsequently, it must pass a pointer to the +manager to all the functions that operate on decision diagrams. + +

          +With the exception of a few statistical counters, there are no global variables in +the CUDD package. Therefore, it is quite possible to have multiple +managers simultaneously active in the same application.1 It is the pointers to +the managers that tell the functions on what data they should operate. + +

          + +

          + +
          +Cache +

          + +

          +Efficient recursive manipulation of decision diagrams requires the use +of a table to store computed results. This table +is called here the cache because it is +effectively handled like a cache of variable but limited capacity. The +CUDD package starts by default with a small cache, and increases its +size until either no further benefit is achieved, or a limit size is +reached. The user can influence this policy by choosing initial and +limit values for the cache size. + +

          +Too small a cache will cause frequent overwriting of useful results. +Too large a cache will cause overhead, because the whole cache is +scanned every time garbage collection takes +place. The optimal parameters depend on the specific application. The +default parameters work reasonably well for a large spectrum of +applications. + +

          +The cache of the CUDD package is used by most recursive +functions of the package, and can be used by user-supplied functions +as well. (See Section 4.4.) + +

          + +

          + +
          +Initializing and Shutting Down a DdManager +

          + +

          +To use the functions in the CUDD package, one has first to initialize +the package itself by calling Cudd_Init. +This function takes four parameters: + +

            +
          • numVars: It is the initial number of variables + for BDDs and ADDs. If the total number of variables needed by the + application is known, then it is slightly more efficient to create a + manager with that number of variables. If the number is unknown, it + can be set to 0, or to any other lower bound on the number of + variables. Requesting more variables than are actually needed is + not incorrect, but is not efficient. +
          • +
          • numVarsZ: It is the initial number of variables + for ZDDs. See Sections 3.9 and 3.11 for + a discussion of the value of this argument. +
          • +
          • numSlots: Determines the initial size of each + subtable of the unique table. + There is a subtable for each variable. The size of each subtable is + dynamically adjusted to reflect the number of nodes. It is normally + O.K. to use the default value for this parameter, which is + CUDD_UNIQUE_SLOTS. +
          • +
          • cacheSize: It is the initial size (number of + entries) of the cache. Its default value is + CUDD_CACHE_SLOTS. +
          • +
          • maxMemory: It is the target value for the + maximum memory occupation (in bytes). The package uses this value to + decide two parameters. + +
              +
            • the maximum size to which the cache will grow, regardless of + the hit rate or the size of the unique table. +
            • +
            • the maximum size to which growth of the unique table will be + preferred to garbage collection. + +
            • +
            + If maxMemory is set to 0, CUDD tries to guess a good value based on + the available memory. +
          • +
          +A typical call to Cudd_Init may look +like this: +
          +  manager = Cudd_Init(0,0,CUDD_UNIQUE_SLOTS,CUDD_CACHE_SLOTS,0);
          +
          +To reclaim all the memory associated with a manager, an application +must call Cudd_Quit. This is normally +done before exiting. + +

          + +

          + +
          +Setting Parameters +

          + +

          +The package provides several functions to set the parameters that +control various functions. For instance, the package has an automatic +way of determining whether a larger unique table +would make the application run faster. In that case, the package +enters a ``fast growth'' mode in which resizing of +the unique subtables is favored over garbage +collection. When the unique table reaches a given size, however, the +package returns to the normal ``slow growth'' mode, even though the +conditions that caused the transition to fast growth still prevail. +The limit size for fast growth can be read by +Cudd_ReadLooseUpTo and changed by +Cudd_SetLooseUpTo. Similar pairs of +functions exist for several other parameters. See also +Section 4.8. + +

          + +

          + +
          +Constant Functions +

          + +

          +The CUDD Package defines several constant functions. These functions +are created when the manager is initialized, and are accessible +through the manager itself. + +

          + +

          + +
          +One, Logic Zero, and Arithmetic Zero +

          + +

          +The constant 1 (returned by +Cudd_ReadOne) is common to BDDs, ADDs, and +ZDDs. However, its meaning is different for ADDs and BDDs, on the one +hand, and ZDDs, on the other hand. The diagram consisting of the +constant 1 node only represents the constant 1 function for ADDs and +BDDs. For ZDDs, its meaning depends on the number of variables: It is +the conjunction of the complements of all variables. Conversely, the +representation of the constant 1 function depends on the number of +variables. The constant 1 function of $n$ variables is returned by +Cudd_ReadZddOne. + +

          +The constant 0 is common to ADDs and ZDDs, but not to BDDs. The +BDD logic 0 is not associated with the constant 0 +function: It is obtained by complementation +(Cudd_Not) of the constant 1. (It is also +returned by Cudd_ReadLogicZero.) +All other constants are specific to ADDs. + +

          + +

          + +
          +Predefined Constants +

          + +

          +Besides 0 (returned by Cudd_ReadZero) +and 1, the following constant functions are +created at initialization time. + +

            +
          1. PlusInfinity and + MinusInfinity: On computers implementing the + IEEE standard 754 for + floating-point arithmetic, these two constants + are set to the signed infinities. On the DEC + Alphas, the option -ieee_with_no_inexact or + -ieee_with_inexact must be passed to the DEC compiler to get + support of the IEEE standard. (The compiler still produces a + warning, but it can be ignored.) Compiling with + those options may cause substantial performance degradation on the + Evolution IV CPUs. (Especially if the application does use the + infinities.) The problem is reportedly solved in the Evolution V + CPUs. If gcc is used to compile CUDD on the + Alphas, the symbol HAVE_IEEE_754 + must be undefined. (See the Makefile for the + details.) The values of these constants are returned by + Cudd_ReadPlusInfinity and + Cudd_ReadMinusInfinity. +
          2. +
          3. Epsilon: This constant, initially set to + $10^{-12}$, is used in comparing floating point values for equality. + Its value is returned by + Cudd_ReadEpsilon, and it can be + modified by calling Cudd_SetEpsilon. + Unlike the other constants, it does not correspond to a node. +
          4. +
          + +

          + +

          + +
          +Background +

          + +

          +The background value is a constant typically used +to represent non-existing arcs in graphs. Consider a shortest path +problem. Two nodes that are not connected by an arc can be regarded as +being joined by an arc of infinite length. In +shortest path problems, it is therefore convenient to set the +background value to PlusInfinity. In network flow +problems, on the other hand, two nodes not connected by an arc can be +regarded as joined by an arc of 0 capacity. +For these problems, therefore, it is more convenient to set the +background value to 0. In general, when representing +sparse matrices, the background value is the value that +is assumed implicitly. + +

          +At initialization, the background value is set to 0. It can be read +with Cudd_ReadBackground, and +modified with Cudd_SetBackground. The background value +affects procedures that read sparse matrices/graphs +(Cudd_addRead and +Cudd_addHarwell), procedures that print +out sum-of-product expressions for +ADDs (Cudd_PrintMinterm), generators +of cubes (Cudd_ForeachCube), and +procedures that count minterms +(Cudd_CountMinterm). + +

          + +

          + +
          +New Constants +

          + +

          +New constant can be created by calling +Cudd_addConst. This function will +retrieve the ADD for the desired constant, if it already +exist, or it will create a new one. Obviously, new constants should +only be used when manipulating ADDs. + +

          + +

          + +
          +Creating Variables +

          + +

          +Decision diagrams are typically created by combining simpler decision +diagrams. The simplest decision diagrams, of course, cannot be +created in that way. Constant functions have been discussed in +Section 3.5. In this section we discuss the simple +variable functions, also known as projection functions. + +

          + +

          + +
          +New BDD and ADD Variables +

          + +

          +The projection functions are distinct for +BDDs and ADDs. A projection function for BDDs consists of an internal +node with both outgoing arcs pointing to the constant 1. The +else arc is complemented. + +

          +An ADD projection function, on the other hand, has the else +pointer directed to the arithmetic zero +function. One should never mix the two types of variables. BDD +variables should be used when manipulating BDDs, and ADD variables +should be used when manipulating ADDs. Three functions are provided +to create BDD variables: + +

            +
          • Cudd_bddIthVar: Returns + the projection function with index $i$. + If the function does not exist, it is created. +
          • +
          • Cudd_bddNewVar: Returns a + new projection function, whose index is + the largest index in use at the time of the call, plus 1. +
          • +
          • Cudd_bddNewVarAtLevel: + Similar to Cudd_bddNewVar. In + addition it allows to specify the position in the variable + order at which the new variable should be + inserted. In contrast, Cudd_bddNewVar + adds the new variable at the end of the order. +
          • +
          +The analogous functions for ADDs are +Cudd_addIthVar, +Cudd_addNewVar, and +Cudd_addNewVarAtLevel. + +

          + +

          + +
          +New ZDD Variables +

          + +

          +Unlike the projection functions of BDDs and ADDs, the +projection functions of ZDDs have diagrams +with $n+1$ nodes, where $n$ is the number of variables. Therefore the +ZDDs of the projection functions change when new variables are added. +This will be discussed in Section 3.9. Here we assume +that the number of variables is fixed. The ZDD of the $i$-th +projection function is returned by +Cudd_zddIthVar. + +

          + +

          + +
          +Basic BDD Manipulation +

          + +

          +Common manipulations of BDDs can be accomplished by calling +Cudd_bddIte. This function takes three BDDs, $f$, $g$, and +$h$, as arguments and computes +$f\cdot g + f'\cdot h$. Like all the +functions that create new BDDs or ADDs, Cudd_bddIte returns a result that must be +explicitly referenced by the caller. Cudd_bddIte can be used +to implement all two-argument boolean functions. However, the package +also provides Cudd_bddAnd as well as the +other two-operand boolean functions, which are slightly more efficient +when a two-operand function is called for. The following fragment of +code illustrates how to build the BDD for the function +$f =
+x_0'x_1'x_2'x_3'$. +

          +	DdManager *manager;
          +	DdNode *f, *var, *tmp;
          +	int i;
          +
          +	...
          +
          +	f = Cudd_ReadOne(manager);
          +	Cudd_Ref(f);
          +	for (i = 3; i >= 0; i--) {
          +	    var = Cudd_bddIthVar(manager,i);
          +	    tmp = Cudd_bddAnd(manager,Cudd_Not(var),f);
          +	    Cudd_Ref(tmp);
          +	    Cudd_RecursiveDeref(manager,f);
          +	    f = tmp;
          +	}
          +
          +This example illustrates the following points: + +
            +
          • Intermediate results must be ``referenced'' and + ``dereferenced.'' However, var is a + projection function, and its + reference count is always greater than + 0. Therefore, there is no call to Cudd_Ref. +
          • +
          • The new f must be assigned to a temporary variable + (tmp in this example). If the result of + Cudd_bddAnd were assigned directly to + f, the old f would be lost, and there would be no + way to free its nodes. +
          • +
          • The statement f = tmp has the same effect as: +
            +	    f = tmp;
            +	    Cudd_Ref(f);
            +	    Cudd_RecursiveDeref(manager,tmp);
            +
            + but is more efficient. The reference is + ``passed'' from tmp to f, and tmp is now + ready to be reutilized. +
          • +
          • It is normally more efficient to build BDDs ``bottom-up.'' This + is why the loop goes from 3 to 0. Notice, however, that after + variable reordering, higher index does not necessarily mean ``closer + to the bottom.'' Of course, in this simple example, efficiency is + not a concern. +
          • +
          • Had we wanted to conjoin the variables in a bottom-up fashion + even after reordering, we should have used + Cudd_ReadInvPerm. One has to be + careful, though, to fix the order of conjunction before entering the + loop. Otherwise, if reordering takes place, it is possible to use + one variable twice and skip another variable. +
          • +
          + +

          + +

          + +
          +Basic ADD Manipulation +

          + +

          +The most common way to manipulate ADDs is via +Cudd_addApply. This function can apply a +wide variety of operators to a pair of ADDs. Among the available +operators are addition, multiplication, division, minimum, maximum, +and boolean operators that work on ADDs whose leaves are restricted to +0 and 1 (0-1 ADDs). + +

          +The following fragment of code illustrates how to build the ADD for +the function +$f = 5x_0x_1x_2x_3$. +

          +	DdManager *manager;
          +	DdNode *f, *var, *tmp;
          +	int i;
          +
          +	...
          +
          +	f = Cudd_addConst(manager,5);
          +	Cudd_Ref(f);
          +	for (i = 3; i >= 0; i--) {
          +	    var = Cudd_addIthVar(manager,i);
          +	    Cudd_Ref(var);
          +	    tmp = Cudd_addApply(manager,Cudd_addTimes,var,f);
          +	    Cudd_Ref(tmp);
          +	    Cudd_RecursiveDeref(manager,f);
          +	    Cudd_RecursiveDeref(manager,var);
          +	    f = tmp;
          +	}
          +
          +This example, contrasted to the example of BDD manipulation, +illustrates the following points: + +
            +
          • The ADD projection function are not + maintained by the manager. It is therefore necessary to + reference and + dereference them. +
          • +
          • The product of two ADDs is computed by calling + Cudd_addApply with + Cudd_addTimes as parameter. There is + no ``apply'' function for BDDs, because + Cudd_bddAnd and + Cudd_bddXor plus complementation are + sufficient to implement all two-argument boolean functions. +
          • +
          + +

          + +

          + +
          +Basic ZDD Manipulation +

          + +

          +ZDDs are often generated by converting +existing BDDs. (See Section 3.11.) However, it is also +possible to build ZDDs by applying boolean operators to other ZDDs, +starting from constants and projection +functions. The following fragment of code illustrates how to build +the ZDD for the function +$f = x_0'+x_1'+x_2'+x_3'$. We assume that the +four variables already exist in the manager when the ZDD for $f$ is +built. Note the use of De Morgan's law. +

          +	DdManager *manager;
          +	DdNode *f, *var, *tmp;
          +	int i;
          +
          +	manager = Cudd_Init(0,4,CUDD_UNIQUE_SLOTS,
          +			    CUDD_CACHE_SLOTS,0);
          +	...
          +
          +	tmp = Cudd_ReadZddOne(manager,0);
          +	Cudd_Ref(tmp);
          +	for (i = 3; i >= 0; i--) {
          +	    var = Cudd_zddIthVar(manager,i);
          +	    Cudd_Ref(var);
          +	    f = Cudd_zddIntersect(manager,var,tmp);
          +	    Cudd_Ref(f);
          +	    Cudd_RecursiveDerefZdd(manager,tmp);
          +	    Cudd_RecursiveDerefZdd(manager,var);
          +	    tmp = f;
          +	}
          +	f = Cudd_zddDiff(manager,Cudd_ReadZddOne(manager,0),tmp);
          +	Cudd_Ref(f);
          +	Cudd_RecursiveDerefZdd(manager,tmp);
          +
          +This example illustrates the following points: + +
            +
          • The projection functions are + referenced, because they are not maintained by the manager. +
          • +
          • Complementation is obtained by subtracting from the constant 1 + function. +
          • +
          • The result of Cudd_ReadZddOne + does not require referencing. +
          • +
          +CUDD provides functions for the manipulation of +covers represented by ZDDs. For instance, +Cudd_zddIsop builds a ZDD representing an +irredundant sum of products for the +incompletely specified function defined by the two BDDs $L$ and $U$. +Cudd_zddWeakDiv performs the weak +division of two covers given as ZDDs. These functions expect the two +ZDD variables corresponding to the two literals of the function +variable to be adjacent. One has to create variable groups (see +Section 3.14) for reordering of +the ZDD variables to work. BDD automatic reordering is safe even +without groups: If realignment of ZDD and ADD/BDD variables is +requested (see Section 3.15) groups will be kept +adjacent. + +

          + +

          + + +
          +Converting ADDs to BDDs and Vice Versa +

          + +

          +Several procedures are provided to convert ADDs to BDDs, according to +different criteria. +(Cudd_addBddPattern, +Cudd_addBddInterval, and +Cudd_addBddThreshold.) The +conversion from BDDs to ADDs +(Cudd_BddToAdd) is based on the simple +principle of mapping the logical 0 and 1 on the +arithmetic 0 and 1. It is also possible to +convert an ADD with integer values (more precisely, floating point +numbers with 0 fractional part) to an array of BDDs by repeatedly +calling Cudd_addIthBit. + +

          + +

          + + +
          +Converting BDDs to ZDDs and Vice Versa +

          + +

          +Many applications first build a set of BDDs and then derive ZDDs from +the BDDs. These applications should create the manager with 0 +ZDD variables and create the BDDs. Then they should call +Cudd_zddVarsFromBddVars to +create the necessary ZDD variables--whose number is likely to be +known once the BDDs are available. This approach eliminates the +difficulties that arise when the number of ZDD variables changes while +ZDDs are being built. + +

          +The simplest conversion from BDDs to ZDDs is a simple change of +representation, which preserves the functions. Simply put, given a BDD +for $f$, a ZDD for $f$ is requested. In this case the correspondence +between the BDD variables and ZDD variables is one-to-one. Hence, +Cudd_zddVarsFromBddVars should be called with the +multiplicity parameter equal to 1. The conversion proper can +then be performed by calling +Cudd_zddPortFromBdd. The inverse +transformation is performed by +Cudd_zddPortToBdd. + +

          +ZDDs are quite often used for the representation of +covers. This is normally done by +associating two ZDD variables to each variable of the function. (And +hence, typically, to each BDD variable.) One ZDD variable is +associated with the positive literal of the BDD variable, while the +other ZDD variable is associated with the negative literal. A call to +Cudd_zddVarsFromBddVars with +multiplicity equal to 2 will associate to BDD variable $i$ the +two ZDD variables $2i$ and $2i+1$. + +

          +If a BDD variable group tree exists when +Cudd_zddVarsFromBddVars is called (see +Section 3.13) the function generates a ZDD variable group +tree consistent to it. In any case, all the ZDD variables derived +from the same BDD variable are clustered into a group. + +

          +If the ZDD for $f$ is created and later a new ZDD variable is added to +the manager, the function represented by the existing ZDD changes. +Suppose, for instance, that two variables are initially created, and +that the ZDD for $f = x_0 + x_1$ is built. If a third variable is +added, say $x_2$, then the ZDD represents +$g = (x_0 + x_1) x_2'$ +instead. This change in function obviously applies regardless of what +use is made of the ZDD. However, if the ZDD is used to represent a +cover, the cover itself is not changed by the +addition of new variable. (What changes is the +characteristic function of the cover.) + +

          + +

          + +
          +Variable Reordering for BDDs and ADDs +

          + +

          +The CUDD package provides a rich set of +dynamic reordering algorithms. Some of them +are slight variations of existing techniques +[16,6,2,10,15,11]; some +others have been developed specifically for this package +[14,13]. + +

          +Reordering affects a unique table. This means that +BDDs and ADDs, which share the same unique table are simultaneously +reordered. ZDDs, on the other hand, are reordered separately. In the +following we discuss the reordering of BDDs and ADDs. Reordering for +ZDDs is the subject of Section 3.14. + +

          +Reordering of the variables can be invoked directly by the application +by calling Cudd_ReduceHeap. Or it can +be automatically triggered by the package when the number of nodes has +reached a given threshold. (The threshold +is initialized and automatically adjusted after each reordering by the +package.) To enable automatic dynamic reordering (also called +asynchronous dynamic reordering +in this document) the application must call +Cudd_AutodynEnable. Automatic +dynamic reordering can subsequently be disabled by calling +Cudd_AutodynDisable. + +

          +All reordering methods are available in both the case of direct call +to Cudd_ReduceHeap and the case of +automatic invocation. For many methods, the reordering procedure is +iterated until no further improvement is obtained. We call these +methods the converging methods. +When constraints are imposed on the relative position of variables +(see Section 3.13) the reordering methods apply inside the +groups. The groups themselves are reordered +by sifting. Each method is identified by a +constant of the enumerated type +Cudd_ReorderingType +defined in cudd.h (the external +header file of the CUDD package): + +

          +

          +
          CUDD_REORDER_NONE:
          +
          This method + causes no reordering. +
          +
          CUDD_REORDER_SAME:
          +
          If passed to + Cudd_AutodynEnable, this + method leaves the current method for automatic reordering unchanged. + If passed to Cudd_ReduceHeap, + this method causes the current method for automatic reordering to be + used. +
          +
          CUDD_REORDER_RANDOM:
          +
          Pairs of + variables are randomly chosen, and swapped in the order. The swap is + performed by a series of swaps of adjacent variables. The best order + among those obtained by the series of swaps is retained. The number + of pairs chosen for swapping equals the + number of variables in the diagram. +
          +
          CUDD_REORDER_RANDOM_PIVOT:
          +
          Same as CUDD_REORDER_RANDOM, but the two variables are chosen so + that the first is above the variable with the largest number of + nodes, and the second is below that variable. In case there are + several variables tied for the maximum number of nodes, the one + closest to the root is used. +
          +
          CUDD_REORDER_SIFT:
          +
          This method is + an implementation of Rudell's sifting + algorithm [16]. A simplified description of sifting is as + follows: Each variable is considered in turn. A variable is moved up + and down in the order so that it takes all possible positions. The + best position is identified and the variable is returned to that + position. + +

          +In reality, things are a bit more complicated. For instance, there + is a limit on the number of variables that will be sifted. This + limit can be read with + Cudd_ReadSiftMaxVar and set with + Cudd_SetSiftMaxVar. In addition, + if the diagram grows too much while moving a variable up or down, + that movement is terminated before the variable has reached one end + of the order. The maximum ratio by which the diagram is allowed to + grow while a variable is being sifted can be read with + Cudd_ReadMaxGrowth and set with + Cudd_SetMaxGrowth. +

          +
          CUDD_REORDER_SIFT_CONVERGE:
          +
          This is the converging variant of + CUDD_REORDER_SIFT. +
          +
          CUDD_REORDER_SYMM_SIFT:
          +
          This method is an implementation of + symmetric sifting [14]. It is + similar to sifting, with one addition: Variables that become + adjacent during sifting are tested for symmetry. If + they are symmetric, they are linked in a group. Sifting then + continues with a group being moved, instead of a single variable. + After symmetric sifting has been run, + Cudd_SymmProfile can be called to + report on the symmetry groups found. (Both positive and negative + symmetries are reported.) +
          +
          CUDD_REORDER_SYMM_SIFT_CONV:
          +
          This is the converging variant of + CUDD_REORDER_SYMM_SIFT. +
          +
          CUDD_REORDER_GROUP_SIFT:
          +
          This method is an implementation of group + sifting [13]. It is similar to symmetric sifting, but + aggregation is not restricted to symmetric + variables. +
          +
          CUDD_REORDER_GROUP_SIFT_CONV:
          +
          This method repeats until convergence the combination of + CUDD_REORDER_GROUP_SIFT and CUDD_REORDER_WINDOW4. +
          +
          CUDD_REORDER_WINDOW2:
          +
          This + method implements the window permutation + approach of Fujita [8] and Ishiura [10]. + The size of the window is 2. +
          +
          CUDD_REORDER_WINDOW3:
          +
          Similar + to CUDD_REORDER_WINDOW2, but with a window of size 3. +
          +
          CUDD_REORDER_WINDOW4:
          +
          Similar + to CUDD_REORDER_WINDOW2, but with a window of size 4. +
          +
          CUDD_REORDER_WINDOW2_CONV:
          +
          This is the converging variant of + CUDD_REORDER_WINDOW2. +
          +
          CUDD_REORDER_WINDOW3_CONV:
          +
          This is the converging variant of CUDD_REORDER_WINDOW3. +
          +
          CUDD_REORDER_WINDOW4_CONV:
          +
          This is the converging variant of CUDD_REORDER_WINDOW4. +
          +
          CUDD_REORDER_ANNEALING:
          +
          This + method is an implementation of simulated + annealing for variable + ordering, vaguely resemblant of the algorithm of [2]. + This method is potentially very slow. +
          +
          CUDD_REORDER_GENETIC:
          +
          This + method is an implementation of a genetic + algorithm for variable ordering, inspired by the work of Drechsler + [6]. This method is potentially very slow. +
          +
          CUDD_REORDER_EXACT:
          +
          This method + implements a dynamic programming approach to + exact reordering + [9,7,10], with improvements described in + [11]. It only stores one BDD at the time. Therefore, it is + relatively efficient in terms of memory. Compared to other + reordering strategies, it is very slow, and is not recommended for + more than 16 variables. +
          +
          +So far we have described methods whereby the package selects an order +automatically. A given order of the variables can also be imposed by +calling Cudd_ShuffleHeap. + +

          + +

          + +
          +Grouping Variables +

          + +

          +CUDD allows the application to specify constraints on the positions of +group of variables. It is possible to request that a group of +contiguous variables be kept contiguous by the reordering procedures. +It is also possible to request that the relative order of some groups +of variables be left unchanged. The constraints on the order are +specified by means of a tree, which is created in +one of two ways: + +

            +
          • By calling Cudd_MakeTreeNode. +
          • +
          • By calling the functions of the MTR library + (part of the distribution), and by registering the result with the + manager using Cudd_SetTree. The current + tree registered with the manager can be read with + Cudd_ReadTree. +
          • +
          + +

          +Each node in the tree represents a range of variables. The lower bound +of the range is given by the low field of the node, and the +size of the group is given by the size field of the +node.2 The variables +in each range are kept contiguous. Furthermore, if a node is marked +with the MTR_FIXED flag, then the relative order of +the variable ranges associated to its children is not changed. As an +example, suppose the initial variable order is: +

          +	x0, y0, z0, x1, y1, z1, ... , x9, y9, z9.
          +
          +Suppose we want to keep each group of three variables with the same +index (e.g., x3, y3, z3) contiguous, while allowing the package +to change the order of the groups. We can accomplish this with the +following code: +
          +	for (i = 0; i < 10; i++) {
          +	    (void) Cudd_MakeTreeNode(manager,i*3,3,MTR_DEFAULT);
          +	}
          +
          +If we want to keep the order within each group of variables +fixed (i.e., x before y before z) we need to +change MTR_DEFAULT into MTR_FIXED. + +

          +The low parameter passed to +Cudd_MakeTreeNode is the index of a +variable (as opposed to its level or position in the order). The +group tree can be created at any time. The +result obviously depends on the variable order in effect at creation +time. + +

          +It is possible to create a variable group tree also before the +variables themselves are created. The package assumes in this case +that the index of the variables not yet in existence will equal their +position in the order when they are created. Therefore, applications +that rely on +Cudd_bddNewVarAtLevel or +Cudd_addNewVarAtLevel to create +new variables have to create the variables before they group them. + +

          +The reordering procedure will skip all groups whose variables are not +yet in existence. For groups that are only partially in existence, the +reordering procedure will try to reorder the variables already +instantiated, without violating the adjacency constraints. + +

          + +

          + +
          +Variable Reordering for ZDDs +

          + +

          +Reordering of ZDDs is done in much the same way as the reordering of +BDDs and ADDs. The functions corresponding to Cudd_ReduceHeap +and Cudd_ShuffleHeap are +Cudd_zddReduceHeap and +Cudd_zddShuffleHeap. To enable +dynamic reordering, the application must +call Cudd_AutodynEnableZdd, and +to disable dynamic reordering, it must call +Cudd_AutodynDisableZdd. In the +current implementation, however, the choice of reordering methods for +ZDDs is more limited. Specifically, these methods are available: + +

          +

          +
          CUDD_REORDER_NONE;
          +
          +
          +
          CUDD_REORDER_SAME;
          +
          +
          +
          CUDD_REORDER_RANDOM;
          +
          +
          +
          CUDD_REORDER_RANDOM_PIVOT;
          +
          +
          +
          CUDD_REORDER_SIFT;
          +
          +
          +
          CUDD_REORDER_SIFT_CONVERGE;
          +
          +
          +
          CUDD_REORDER_SYMM_SIFT;
          +
          +
          +
          CUDD_REORDER_SYMM_SIFT_CONV.
          +
          +
          +
          + +

          +To create ZDD variable groups, the application calls +Cudd_MakeZddTreeNode. + +

          + +

          + +
          +Keeping Consistent Variable Orders for BDDs and ZDDs +

          + +

          +Several applications that manipulate both BDDs and ZDDs benefit from +keeping a fixed correspondence between the order of the BDD variables +and the order of the ZDD variables. If each BDD variable corresponds +to a group of ZDD variables, then it is often desirable that the +groups of ZDD variables be in the same order as the corresponding BDD +variables. CUDD allows the ZDD order to track the BDD order and vice +versa. To have the ZDD order track the BDD order, the application +calls Cudd_zddRealignEnable. The +effect of this call can be reversed by calling +Cudd_zddRealignDisable. When +ZDD realignment is in effect, automatic reordering of ZDDs should be +disabled. + +

          + +

          + +
          +Hooks +

          + +

          +Hooks in CUDD are lists of application-specified functions to be run on +certain occasions. Each hook is identified by a constant of the +enumerated type Cudd_HookType. In Version +2.4.2 hooks are defined for these occasions: + +

            +
          • before garbage collection (CUDD_PRE_GC_HOOK); +
          • +
          • after garbage collection (CUDD_POST_GC_HOOK); +
          • +
          • before variable reordering (CUDD_PRE_REORDERING_HOOK); +
          • +
          • after variable reordering (CUDD_POST_REORDERING_HOOK). +
          • +
          +The current implementation of hooks is experimental. A function added +to a hook receives a pointer to the manager, a pointer to a constant +string, and a pointer to void as arguments; it must return 1 if +successful; 0 otherwise. The second argument is one of ``DD,'' +``BDD,'' and ``ZDD.'' This allows the hook functions to tell the type +of diagram for which reordering or garbage collection takes place. The +third argument varies depending on the hook. The hook functions called +before or after garbage collection do +not use it. The hook functions called before +reordering are passed, in addition to the +pointer to the manager, also the method used for reordering. The hook +functions called after reordering are passed the start time. To add a +function to a hook, one uses Cudd_AddHook. +The function of a given hook +are called in the order in which they were added to the hook. For +sample hook functions, one may look at +Cudd_StdPreReordHook and +Cudd_StdPostReordHook. + +

          + +

          + +
          +The SIS/VIS Interface +

          + +

          +The CUDD package contains interface functions that emulate the +behavior of the original BDD package used in SIS [17] and +in the newer +VIS +[4]. How to build VIS with CUDD is described +in the installation documents of VIS. (Version 1.1 and later.) + +

          + +

          + +
          +Using the CUDD Package in SIS +

          + +

          +This section describes how to build SIS with the CUDD package. Let +SISDIR designate the root of the directory +hierarchy where the sources for SIS reside. Let +CUDDDIR be the root of the directory hierarchy +where the distribution of the CUDD package resides. To build SIS with +the CUDD package, follow these steps. + +

            +
          1. Create directories SISDIR/sis/cudd and + SISDIR/sis/mtr. +
          2. +
          3. Copy all files from CUDDDIR/cudd and + CUDDDIR/sis to SISDIR/sis/cudd and all files from + CUDDDIR/mtr to SISDIR/sis/mtr. +
          4. +
          5. Copy CUDDDIR/cudd/doc/cudd.doc to + SISDIR/sis/cudd; also copy CUDDDIR/mtr/doc/mtr.doc + to SISDIR/sis/mtr. +
          6. +
          7. In SISDIR/sis/cudd make bdd.h a symbolic link + to cuddBdd.h. (That is: ln -s cuddBdd.h bdd.h.) +
          8. +
          9. In SISDIR/sis/cudd delete Makefile and rename + Makefile.sis as Makefile. Do the same in + SISDIR/sis/mtr. +
          10. +
          11. Copy CUDDDIR/sis/st.[ch] and CUDDDIR/st/doc/st.doc + to SISDIR/sis/st. (This will overwrite the original files: You + may want to save them beforehand.) +
          12. +
          13. From CUDDDIR/util copy datalimit.c to + SISDIR/sis/util. Update util.h and + Makefile in SISDIR/sis/util. Specifically, add the + declaration EXTERN long getSoftDataLimit(); to + util.h and add datalimit.c to the list of source + files (PSRC) in Makefile. +
          14. +
          15. In SISDIR/sis remove the link from bdd to + bdd_cmu or bdd_ucb (that is, rm bdd) + and make bdd a symbolic link to cudd. (That is: + ln -s cudd bdd.) +
          16. +
          17. Still in SISDIR/sis, edit Makefile, Makefile.oct, and Makefile.nooct. In all three files add + mtr to the list of directories to be made (DIRS). +
          18. +
          19. In SISDIR/sis/include make mtr.h a symbolic + link to ../mtr/mtr.h. +
          20. +
          21. In SISDIR/sis/doc make cudd.doc a symbolic + link to ../cudd/cudd.doc and mtr.doc a symbolic + link to ../mtr/mtr.doc. (That is: ln -s + ../cudd/cudd.doc .; ln -s ../mtr/mtr.doc ..) +
          22. +
          23. From SISDIR do make clean followed by + make -i. This should create a working copy of SIS that + uses the CUDD package. +
          24. +
          + +

          +The replacement for the st library is because the version +shipped with the CUDD package tests for out-of-memory conditions. +Notice that the version of the st library to be used for +replacement is not the one used for the normal build, because the +latter has been modified for C++ compatibility. The above installation +procedure has been tested on SIS 1.3. SIS can be obtained via +anonymous FTP from +ic.eecs.berkeley.edu. +To build SIS 1.3, you need sis-1.2.tar.Z and +sis-1.2.patch1.Z. When compiling on a DEC Alpha, you should add the -ieee_with_no_inexact flag. +(See Section 3.5.2.) Refer to the Makefile +in the top level directory of the distribution for how to compile with +32-bit pointers. + +

          + +

          + +
          +Writing Decision Diagrams to a File +

          + +

          +The CUDD package provides several functions to write decision diagrams +to a file. Cudd_DumpBlif writes a +file in blif format. It is restricted to BDDs. The diagrams +are written as a network of multiplexers, one multiplexer for each +internal node of the BDD. + +

          +Cudd_DumpDot produces input suitable to +the graph-drawing program +dot +written by Eleftherios Koutsofios and Stephen C. North. An example of +drawing produced by dot from the output of Cudd_DumpDot is +shown in Figure 1. It is restricted to BDDs and ADDs. + +

          + + + +
          Figure 1: +A BDD representing a phase constraint for the optimization of + fixed-polarity Reed-Muller forms. The label of each node is the + unique part of the node address. All nodes on the same level + correspond to the same variable, whose name is shown at the left of + the diagram. Dotted lines indicate complement + arcs. Dashed lines indicate regular ``else'' + arcs.
          +
          +\includegraphics[height=15.5cm]{phase.ps}
          +
          + +Cudd_zddDumpDot is the analog of +Cudd_DumpDot for ZDDs. + +

          +Cudd_DumpDaVinci produces input +suitable to the graph-drawing program +daVinci +developed at the University of Bremen. It is restricted to BDDs and +ADDs. + +

          +Functions are also available to produce the input format of +DDcal (see Section 2.2) and factored forms. + +

          + +

          + +
          +Saving and Restoring BDDs +

          + +

          +The +dddmp +library by Gianpiero Cabodi and Stefano Quer +allows a CUDD application to save BDDs to disk in compact form for +later retrieval. See the library's own documentation for the details. + +

          +


          + + +next + +up + +previous + +index +
          + Next: Programmer's Manual + Up: CUDD: CU Decision Diagram + Previous: How to Get CUDD +   Index + +
          +Fabio Somenzi +2009-02-20 +
          + + diff --git a/distr/cudd/doc/node4.html b/distr/cudd/doc/node4.html new file mode 100644 index 0000000..d7a60ba --- /dev/null +++ b/distr/cudd/doc/node4.html @@ -0,0 +1,1168 @@ + + + + + +Programmer's Manual + + + + + + + + + + + + + + + + + + + +next + +up + +previous + +index +
          + Next: The C++ Interface + Up: CUDD: CU Decision Diagram + Previous: User's Manual +   Index +
          +
          + + +Subsections + + + +
          + +

          + +
          +Programmer's Manual +

          + +

          +This section provides additional detail on the working of the CUDD +package and on the programming conventions followed in its writing. +The additional detail should help those who want to write procedures +that directly manipulate the CUDD data structures. + +

          + +

          + +
          +Compiling and Linking +

          + +

          +If you plan to use the CUDD package as a clear box +(for instance, you want to write a procedure that traverses a decision +diagram) you need to add +

          +#include "cuddInt.h"
          +
          +to your source files. In addition, you should link libcudd.a to +your executable. Some platforms require specific compiler and linker +flags. Refer to the Makefile in the top level directory of +the distribution. + +

          + +

          + +
          +Reference Counts +

          + +

          +Garbage collection in the CUDD package is +based on reference counts. Each node stores the sum of the external +references and internal references. An internal BDD or ADD node is +created by a call to cuddUniqueInter, an +internal ZDD node is created by a call to +cuddUniqueInterZdd, and a +terminal node is created by a call to +cuddUniqueConst. If the node returned by +these functions is new, its reference count is zero. The function +that calls cuddUniqueInter, +cuddUniqueInterZdd, or +cuddUniqueConst is responsible for +increasing the reference count of the node. This is accomplished by +calling Cudd_Ref. + +

          +When a function is no longer needed by an application, the memory used +by its diagram can be recycled by calling +Cudd_RecursiveDeref (BDDs and ADDs) +or Cudd_RecursiveDerefZdd +(ZDDs). These functions decrease the reference count of the node passed to them. If the reference count +becomes 0, then two things happen: + +

            +
          1. The node is declared ``dead;'' this entails + increasing the counters of the dead + nodes. (One counter for the subtable to which the + node belongs, and one global counter for the + unique table to which the node belongs.) The + node itself is not affected. +
          2. +
          3. The function is recursively called on the two children of the + node. +
          4. +
          +For instance, if the diagram of a function does not share any nodes +with other diagrams, then calling +Cudd_RecursiveDeref or +Cudd_RecursiveDerefZdd on its +root will cause all the nodes of the diagram to become dead. + +

          +When the number of dead nodes reaches a given level (dynamically +determined by the package) garbage collection takes place. During +garbage collection dead nodes are returned +to the node free list. + +

          +When a new node is created, it is important to increase its +reference count before one of the two +following events occurs: + +

            +
          1. A call to cuddUniqueInter, + to cuddUniqueInterZdd, to + cuddUniqueConst, or to a + function that may eventually cause a call to them. +
          2. +
          3. A call to + Cudd_RecursiveDeref, to + Cudd_RecursiveDerefZdd, or to + a function that may eventually cause a call to them. +
          4. +
          +In practice, it is recommended to increase the reference count as soon +as the returned pointer has been tested for not being NULL. + +

          + +

          + +
          +NULL Return Values +

          + +

          +The interface to the memory management functions (e.g., malloc) used +by CUDD intercepts NULL return values and calls a handler. The +default handler exits with an error message. If the application does +not install another handler, therefore, a NULL return value from an +exported function of CUDD signals an internal error. + +

          +If the aplication, however, installs another handler that lets +execution continue, a NULL pointer returned by an exported function +typically indicates that the process has run out of memory. +Cudd_ReadErrorCode can be used to +ascertain the nature of the problem. + +

          +An application that tests for the result being NULL can try some +remedial action, if it runs out of memory. For instance, it may free +some memory that is not strictly necessary, or try a slower algorithm +that takes less space. As an example, CUDD overrides the default +handler when trying to enlarge the cache or increase the number of +slots of the unique table. If the allocation fails, the package prints +out a message and continues without resizing the cache. + +

          + +

          + +
          +Cudd_RecursiveDeref vs. Cudd_Deref +

          + +

          +It is often the case that a recursive procedure has to protect the +result it is going to return, while it disposes of intermediate +results. (See the previous discussion on when to increase reference +counts.) Once the intermediate results have been properly disposed +of, the final result must be returned to its pristine state, in which +the root node may have a reference count of 0. One cannot use +Cudd_RecursiveDeref (or +Cudd_RecursiveDerefZdd) for this purpose, because it may +erroneously make some nodes dead. Therefore, the package provides a +different function: Cudd_Deref. This +function is not recursive, and does not change the dead node counts. +Its use is almost exclusively the one just described: Decreasing the +reference count of the root of the final result before returning from +a recursive procedure. + +

          + +

          + +
          +When Increasing the Reference Count is Unnecessary +

          + +

          +When a copy of a predefined constant or of a +simple BDD variable is needed for comparison purposes, then calling +Cudd_Ref is not necessary, because these +simple functions are guaranteed to have reference counts greater than +0 at all times. If no call to Cudd_Ref is made, then no +attempt to free the diagram by calling +Cudd_RecursiveDeref or +Cudd_RecursiveDerefZdd should be +made. + +

          + +

          + +
          +Saturating Increments and Decrements +

          + +

          +On 32-bit machines, the CUDD package stores the +reference counts in unsigned short int's. +For large diagrams, it is possible for some reference counts to exceed +the capacity of an unsigned short int. Therefore, increments and +decrements of reference counts are saturating. This means that +once a reference count has reached the maximum possible value, it is +no longer changed by calls to Cudd_Ref, +Cudd_RecursiveDeref, +Cudd_RecursiveDerefZdd, or +Cudd_Deref. As a consequence, some nodes +that have no references may not be declared dead. This may result in a +small waste of memory, which is normally more than offset by the +reduction in size of the node structure. + +

          +When using 64-bit pointers, there is normally no memory advantage from +using short int's instead of int's in a DdNode. Therefore, increments +and decrements are not saturating in that case. What option is in +effect depends on two macros, SIZEOF_VOID_P +and SIZEOF_INT, defined in the external +header file (cudd.h). The +increments and decrements of the reference counts are performed using +two macros: cuddSatInc and +cuddSatDec, whose definitions depend on +SIZEOF_VOID_P and +SIZEOF_INT. + +

          + +

          + +
          +Complement Arcs +

          + +

          +If ADDs are restricted to use only the constants 0 and 1, they behave +like BDDs without complement arcs. It is normally easier to write code +that manipulates 0-1 ADDs, than to write code for BDDs. However, +complementation is trivial with complement arcs, and is not trivial +without. As a consequence, with complement arcs it is possible to +check for more terminal cases and it is possible to apply De Morgan's +laws to reduce problems that are essentially identical to a standard +form. This in turn increases the utilization of the cache. + +

          +The complement attribute is stored in the least significant bit of the +``else'' pointer of each node. An external pointer to a function can +also be complemented. The ``then'' pointer to a node, on the other +hand, is always regular. It is a mistake to +use a complement pointer as it is to address +memory. Instead, it is always necessary to obtain a regular version +of it. This is normally done by calling +Cudd_Regular. It is also a mistake to +call cuddUniqueInter with a complemented +``then'' child as argument. The calling procedure must apply De +Morgan's laws by complementing both pointers passed to +cuddUniqueInter and then taking the +complement of the result. + +

          + +

          + +
          +The Cache +

          + +

          +Each entry of the cache consists of five fields: The operator, three +pointers to operands and a pointer to the result. The operator and the +three pointers to the operands are combined to form three words. The +combination relies on two facts: + +

            +
          • Most operations have one or two operands. A few bits are + sufficient to discriminate all three-operands operations. +
          • +
          • All nodes are aligned to 16-byte boundaries. (32-byte boundaries + if 64-bit pointers are used.) Hence, there are a few bits available + to distinguish the three-operand operations from te others and to + assign unique codes to them. +
          • +
          + +

          +The cache does not contribute to the reference + +counts of the nodes. The fact that the cache contains a +pointer to a node does not imply that the node is alive. Instead, when +garbage collection takes place, all entries +of the cache pointing to dead nodes are cleared. + +

          +The cache is also cleared (of all entries) when dynamic +reordering takes place. In both cases, the entries +removed from the cache are about to become invalid. + +

          +All operands and results in a cache entry must be pointers to +DdNodes. If a function produces more than one result, +or uses more than three arguments, there are currently two solutions: + +

            +
          • Build a separate, local, cache. (Using, for + instance, the st library.) +
          • +
          • Combine multiple results, or multiple operands, into a single + diagram, by building a ``multiplexing structure'' with reserved + variables. +
          • +
          +Support of the former solution is under development. (See +cuddLCache.c..) Support for the latter solution may be +provided in future versions of the package. + +

          +There are three sets of interface functions to +the cache. The first set is for functions with three operands: +cuddCacheInsert and +cuddCacheLookup. The second set is for +functions with two operands: +cuddCacheInsert2 and +cuddCacheLookup2. The second set is for +functions with one operand: +cuddCacheInsert1 and +cuddCacheLookup1. The second set is +slightly faster than the first, and the third set is slightly faster +than the second. + +

          + +

          + +
          +Cache Sizing +

          + +

          +The size of the cache can increase during the execution of an +application. (There is currently no way to decrease the size of the +cache, though it would not be difficult to do it.) When a cache miss +occurs, the package uses the following criteria to decide whether to +resize the cache: + +

            +
          1. If the cache already exceeds the limit given by the + maxCache field of the manager, no resizing + takes place. The limit is the minimum of two values: a value set at + initialization time and possibly modified by the application, which + constitutes the hard limit beyond which the cache will never grow; + and a number that depends on the current total number of slots in + the unique table. +
          2. +
          3. If the cache is not too large already, resizing is decided based + on the hit rate. The policy adopted by the CUDD package is + ``reward-based.'' If the cache hit + rate is high, then it is worthwhile to increase the size of the + cache. +
          4. +
          +When resizing takes place, the statistical counters used to compute the hit rate are reinitialized so as to +prevent immediate resizing. The number of entries is doubled. + +

          +The rationale for the ``reward-based'' +policy is as follows. In many BDD/ADD applications the hit rate is +not very sensitive to the size of the cache: It is primarily a +function of the problem instance at hand. If a large hit rate is +observed, chances are that by using a large cache, the results of +large problems (those that would take longer to solve) will survive in +the cache without being overwritten long enough to cause a valuable +cache hit. Notice that when a large problem is solved more than once, +so are its recursively generated subproblems. If the hit rate is +low, the probability of large problems being solved more than once is +low. + +

          +The other observation about the cache sizing policy is that there is +little point in keeping a cache which is much larger than the unique +table. Every time the unique table ``fills up,'' garbage collection is +invoked and the cache is cleared of all dead entries. A cache that is +much larger than the unique table is therefore +less than fully utilized. + +

          + +

          + +
          +Local Caches +

          + +

          +Sometimes it may be necessary or convenient to use a local cache. A +local cache can be lossless (no results are ever +overwritten), or it may store objects for which +canonical representations are not available. One +important fact to keep in mind when using a local cache is that local +caches are not cleared during garbage +collection or before reordering. Therefore, it is necessary to +increment the reference count of all nodes +pointed by a local cache. (Unless their reference counts are +guaranteed positive in some other way. One such way is by including +all partial results in the global result.) Before disposing of the +local cache, all elements stored in it must be passed to +Cudd_RecursiveDeref. As consequence +of the fact that all results in a local cache are referenced, it is +generally convenient to store in the local cache also the result of +trivial problems, which are not usually stored in the global cache. +Otherwise, after a recursive call, it is difficult to tell whether the +result is in the cache, and therefore referenced, or not in the cache, +and therefore not referenced. + +

          +An alternative approach to referencing the results in the local caches +is to install hook functions (see Section 3.16) to be +executed before garbage collection. + +

          + +

          + +
          +The Unique Table +

          + +

          +A recursive procedure typically splits the operands by expanding with +respect to the topmost variable. Topmost in this context refers to the +variable that is closest to the roots in the current variable order. +The nodes, on the other hand, hold the index, which is invariant with +reordering. Therefore, when splitting, one must use the +permutation array maintained by the +package to get the right level. Access to the permutation array is +provided by the macro cuddI for BDDs and ADDs, +and by the macro cuddIZ for ZDDs. + +

          +The unique table consists of as many hash tables as +there are variables in use. These has tables are called unique + subtables. The sizes of the unique subtables are determined by two +criteria: + +

            +
          1. The collision lists should be short + to keep access time down. +
          2. +
          3. There should be enough room for dead nodes, to + prevent too frequent garbage collections. +
          4. +
          +While the first criterion is fairly straightforward to implement, the +second leaves more room to creativity. The CUDD package tries to +figure out whether more dead node should be allowed to increase +performance. (See also Section 3.4.) There are two +reasons for not doing garbage collection too often. The obvious one is +that it is expensive. The second is that dead nodes may be +reclaimed, if they are the result of a +successful cache lookup. Hence dead nodes may provide a substantial +speed-up if they are kept around long enough. The usefulness of +keeping many dead nodes around varies from application to application, +and from problem instance to problem instance. As in the sizing of the +cache, the CUDD package adopts a +``reward-based'' policy to +decide how much room should be used for the unique table. If the +number of dead nodes reclaimed is large compared to the number of +nodes directly requested from the memory manager, then the CUDD +package assumes that it will be beneficial to allow more room for the +subtables, thereby reducing the frequency of garbage collection. The +package does so by switching between two modes of operation: + +
            +
          1. Fast growth: In this mode, the + ratio of dead nodes to total nodes required for garbage collection + is higher than in the slow growth mode to favor resizing + of the subtables. +
          2. +
          3. Slow growth: In this + mode keeping many dead nodes around is not as important as + keeping memory requirements low. +
          4. +
          +Switching from one mode to the other is based on the following +criteria: + +
            +
          1. If the unique table is already large, only slow growth is + possible. +
          2. +
          3. If the table is small and many dead nodes are being reclaimed, + then fast growth is selected. +
          4. +
          +This policy is especially effective when the diagrams being +manipulated have lots of recombination. Notice the interplay of the +cache sizing and unique sizing: Fast growth normally occurs when the +cache hit rate is large. The cache and the unique table then grow in +concert, preserving a healthy balance between their sizes. + +

          + +

          + +
          +Allowing Asynchronous Reordering +

          + +

          +Asynchronous reordering is the reordering that is triggered +automatically by the increase of the number of nodes. Asynchronous +reordering takes place when a new internal node must be created, and +the number of nodes has reached a given +threshold. (The threshold is adjusted by +the package every time reordering takes place.) + +

          +Those procedures that do not create new nodes (e.g., procedures that +count the number of nodes or minterms) need +not worry about asynchronous reordering: No special precaution is +necessary in writing them. + +

          +Procedures that only manipulate decision diagrams through the exported +functions of the CUDD package also need not concern themselves with +asynchronous reordering. (See Section 3.2.1 for the +exceptions.) + +

          +The remaining class of procedures is composed of functions that visit +the diagrams and may create new nodes. All such procedures in the CUDD +package are written so that they can be interrupted by dynamic +reordering. The general approach followed goes under the name of +``abort and retry.'' As the name +implies, a computation that is interrupted by dynamic reordering is +aborted and tried again. + +

          +A recursive procedure that can be interrupted by dynamic reordering +(an interruptible procedure +from now on) is composed of two functions. One is responsible for the +real computation. The other is a simple +wrapper, which tests whether +reordering occurred and restarts the computation if it did. + +

          +Asynchronous reordering of BDDs and ADDs can only be triggered inside +cuddUniqueInter, when a new node is about +to be created. Likewise, asynchronous reordering of ZDDs can only be +triggered inside cuddUniqueInterZdd. +When reordering is triggered, three things happen: + +

            +
          1. cuddUniqueInter returns a NULL + value; +
          2. +
          3. The flag reordered of the manager is set to 1. (0 means + no reordering, while 2 indicates an error occurred during + reordering.) +
          4. +
          5. The counter reorderings of the manager is incremented. + The counter is initialized to 0 when the manager is started and can + be accessed by calling + Cudd_ReadReorderings. By taking + two readings of the counter, an application can determine if + variable reordering has taken place between the first and the second + reading. The package itself, however, does not make use of the + counter: It is mentioned here for completeness. +
          6. +
          + +

          +The recursive procedure that receives a NULL value from +cuddUniqueInter must free all +intermediate results that it may have computed before, and return NULL +in its turn. + +

          +The wrapper function does not +decide whether reordering occurred based on the NULL return value, +because the NULL value may be the result of lack of memory. Instead, +it checks the reordered flag. + +

          +When a recursive procedure calls another recursive procedure that may +cause reordering, it should bypass the wrapper and call the recursive +procedure directly. Otherwise, the calling procedure will not know +whether reordering occurred, and will not be able to restart. This is +the main reason why most recursive procedures are internal, rather +than static. (The wrappers, on the other hand, are mostly exported.) + +

          + +

          + +
          +Debugging +

          + +

          +By defining the symbol DD_DEBUG during compilation, +numerous checks are added to the code. In addition, the procedures +Cudd_DebugCheck, +Cudd_CheckKeys, and +cuddHeapProfile can be called at any +point to verify the consistency of the data structure. +(cuddHeapProfile is an internal procedure. It is declared in +cuddInt.h.) Procedures +Cudd_DebugCheck and Cudd_CheckKeys are especially +useful when CUDD reports that during garbage collection the number of +nodes actually deleted from the unique table is different from the +count of dead nodes kept by the manager. The error causing the +discrepancy may have occurred much earlier than it is discovered. A +few strategicaly placed calls to the debugging procedures can +considerably narrow down the search for the source of the problem. +(For instance, a call to Cudd_RecursiveDeref where one to +Cudd_Deref was required may be identified in this way.) + +

          +One of the most common problems encountered in debugging code based on +the CUDD package is a missing call to +Cudd_RecursiveDeref. To help +identify this type of problems, the package provides a function called +Cudd_CheckZeroRef. This function +should be called immediately before shutting down the manager. +Cudd_CheckZeroRef checks that the only nodes left with +non-zero reference counts are the +predefined constants, the BDD projection +functions, and nodes whose reference counts are +saturated. + +

          +For this function to be effective the application must explicitly +dispose of all diagrams to which it has pointers before calling it. + +

          + +

          + +
          +Gathering and Interpreting Statistics +

          + +

          +Function Cudd_PrintInfo can be called to +print out the values of parameters and statistics for a manager. The +output of Cudd_PrintInfo is divided in two sections. The +first reports the values of parameters that are under the application +control. The second reports the values of statistical counters and +other non-modifiable parameters. A quick guide to the interpretation +of all these quantities follows. For ease of exposition, we reverse +the order and describe the non-modifiable parameters first. We'll use +a sample run as example. There is nothing special about this run. + +

          + +

          + +
          +Non Modifiable Parameters +

          + +

          +The list of non-modifiable parameters starts with: +

          +    **** CUDD non-modifiable parameters ****
          +    Memory in use: 32544220
          +
          +This is the memory used by CUDD for three things mainly: Unique table +(including all DD nodes in use), node free list, and computed table. +This number almost never decreases in the lifetime of a CUDD manager, +because CUDD does not release memory when it frees nodes. Rather, it +puts the nodes on its own free list. This number is in bytes. It does +not represent the peak memory occupation, because it does not include +the size of data structures created temporarily by some functions (e.g., +local look-up tables). + +

          +

          +    Peak number of nodes: 837018
          +
          +This number is the number of nodes that the manager has allocated. +This is not the largest size of the BDDs, because the manager will +normally have some dead nodes and some nodes on the free list. + +

          +

          +    Peak number of live nodes: 836894
          +
          +This is the largest number of live nodes that the manager has held +since its creation. + +

          +

          +    Number of BDD variables: 198
          +    Number of ZDD variables: 0
          +
          +These numbers tell us this run was not using ZDDs. + +

          +

          +    Number of cache entries: 1048576
          +
          +Current number of slots of the computed table. If one has a +performance problem, this is one of the numbers to look at. The cache +size is always a power of 2. + +

          +

          +    Number of cache look-ups: 2996536
          +    Number of cache hits: 1187087
          +
          +These numbers give an indication of the hit rate in the computed +table. It is not unlikely for model checking runs to get +hit rates even higher than this one (39.62%). + +

          +

          +    Number of cache insertions: 1809473
          +    Number of cache collisions: 961208
          +    Number of cache deletions: 0
          +
          +A collision occurs when a cache entry is +overwritten. A deletion +occurs when a cache entry is invalidated (e.g., during garbage +collection). If the number of deletions is high compared to the +number of collisions, it means that garbage collection occurs too +often. In this case there were no garbage collections; hence, no +deletions. + +

          +

          +    Cache used slots = 80.90% (expected 82.19%)
          +
          +Percentage of cache slots that contain a valid entry. If this +number is small, it may signal one of three conditions: + +
            +
          1. The cache may have been recently resized and it is still filling + up. +
          2. +
          3. The cache is too large for the BDDs. This should not happen if + the size of the cache is determined by CUDD. +
          4. +
          5. The hash function is not working properly. This is accompanied + by a degradation in performance. Conversely, a degradation in + performance may be due to bad hash function behavior. +
          6. +
          +The expected value is computed assuming a uniformly random +distribution of the accesses. If the difference between the measured +value and the expected value is large (unlike this case), the cache is +not working properly. + +

          +

          +    Soft limit for cache size: 1318912
          +
          +This number says how large the cache can grow. This limit is based on +the size of the unique table. CUDD uses a reward-based policy for +growing the cache. (See Section 4.4.1.) The default +hit rate for resizing is 30% and the value in effect is reported +among the modifiable parameters. + +

          +

          +    Number of buckets in unique table: 329728
          +
          +This number is exactly one quarter of the one above. This is indeed +how the soft limit is determined currently, unless the computed table +hits the specified hard limit. (See below.) + +

          +

          +    Used buckets in unique table: 87.96% (expected 87.93%)
          +
          +Percentage of unique table buckets that contain at least one +node. Remarks analogous to those made about the used cache slots apply. + +

          +

          +    Number of BDD and ADD nodes: 836894
          +    Number of ZDD nodes: 0
          +
          +How many nodes are currently in the unique table, either alive or dead. + +

          +

          +    Number of dead BDD and ADD nodes: 0
          +    Number of dead ZDD nodes: 0
          +
          +Subtract these numbers from those above to get the number of live +nodes. In this case there are no dead nodes because the application +uses delayed dereferencing +Cudd_DelayedDerefBdd. + +

          +

          +    Total number of nodes allocated: 836894
          +
          +This is the total number of nodes that were requested and obtained +from the free list. It never decreases, and is not an indication of +memory occupation after the first garbage collection. Rather, it is a +measure of the package activity. + +

          +

          +    Total number of nodes reclaimed: 0
          +
          +These are the nodes that were resuscitated from the dead. If they are +many more than the allocated nodes, and the total +number of slots is low relative to the number of nodes, then one may +want to increase the limit for fast unique table growth. In this case, +the number is 0 because of delayed dereferencing. + +

          +

          +    Garbage collections so far: 0
          +    Time for garbage collections: 0.00 sec
          +    Reorderings so far: 0
          +    Time for reordering: 0.00 sec
          +
          +There is a GC for each reordering. Hence the first count will always be +at least as large as the second. + +

          +

          +    Node swaps in reordering: 0
          +
          +This is the number of elementary reordering steps. Each step consists +of the re-expression of one node while swapping two adjacent +variables. This number is a good measure of the amount of work done in +reordering. + +

          + +

          + +
          +Modifiable Parameters +

          + +

          +Let us now consider the modifiable parameters, that is, those settings on +which the application or the user has control. + +

          +

          +    **** CUDD modifiable parameters ****
          +    Hard limit for cache size: 8388608
          +
          +This number counts entries. Each entry is 16 bytes if CUDD is compiled +to use 32-bit pointers. Two important observations are in order: + +
            +
          1. If the datasize limit is set, CUDD will use it to determine this + number automatically. On a Unix system, one can type ``limit'' or + ``ulimit'' to verify if this value is set. If the datasize limit is + not set, CUDD uses a default which is rather small. If you have + enough memory (say 64MB or more) you should seriously consider + not using the default. So, either set the datasize limit, or + override the default with + Cudd_SetMaxCacheHard. +
          2. +
          3. If a process seems to be going nowhere, a small value for + this parameter may be the culprit. One cannot overemphasize the + importance of the computed table in BDD algorithms. +
          4. +
          +In this case the limit was automatically set for a target maximum +memory occupation of 104 MB. + +

          +

          +    Cache hit threshold for resizing: 15%
          +
          +This number can be changed if one suspects performance is hindered by +the small size of the cache, and the cache is not growing towards the +soft limit sufficiently fast. In such a case one can change the +default 30% to 15% (as in this case) or even 1%. + +

          +

          +    Garbage collection enabled: yes
          +
          +One can disable it, but there are few good reasons for doing +so. It is normally preferable to raise the limit for fast unique table +growth. (See below.) + +

          +

          +    Limit for fast unique table growth: 1363148
          +
          +See Section 4.5 and the comments above about reclaimed +nodes and hard limit for the cache size. This value was chosen +automatically by CUDD for a datasize limit of 1 GB. + +

          +

          +    Maximum number of variables sifted per reordering: 1000
          +    Maximum number of variable swaps per reordering: 2000000
          +    Maximum growth while sifting a variable: 1.2
          +
          +Lowering these numbers will cause reordering to be less accurate and +faster. Results are somewhat unpredictable, because larger BDDs after one +reordering do not necessarily mean the process will go faster or slower. + +

          +

          +    Dynamic reordering of BDDs enabled: yes
          +    Default BDD reordering method: 4
          +    Dynamic reordering of ZDDs enabled: no
          +    Default ZDD reordering method: 4
          +
          +These lines tell whether automatic reordering can take place and what +method would be used. The mapping from numbers to methods is in +cudd.h. One may want to try different BDD reordering +methods. If variable groups are used, however, one should not expect +to see big differences, because CUDD uses the reported method only to +reorder each leaf variable group (typically corresponding present and +next state variables). For the relative order of the groups, it +always uses the same algorithm, which is effectively sifting. + +

          +As for enabling dynamic reordering or not, a sensible recommendation is the +following: Unless the circuit is rather small or one has a pretty good +idea of what the order should be, reordering should be enabled. + +

          +

          +    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
          +
          +Parameters for reordering. See the documentation of the functions used +to control these parameters for the details. + +

          +

          +    Next reordering threshold: 100000
          +
          +When the number of nodes crosses this threshold, reordering will be +triggered. (If enabled; in this case it is not.) This parameter is +updated by the package whenever reordering takes place. The +application can change it, for instance at start-up. Another +possibility is to use a hook function (see Section 3.16) to +override the default updating policy. + +

          + +

          + +
          +Extended Statistics and Reporting +

          + +

          +The following symbols can be defined during compilation to increase +the amount of statistics gathered and the number of messages produced +by the package: + +

            +
          • DD_STATS; +
          • +
          • DD_CACHE_PROFILE; +
          • +
          • DD_UNIQUE_PROFILE. +
          • +
          • DD_VERBOSE; +
          • +
          +Defining DD_CACHE_PROFILE causes each entry of the cache to include +an access counter, which is used to compute simple statistics on the +distribution of the keys. + +

          + +

          + +
          +Guidelines for Documentation +

          + +

          +The documentation of the CUDD functions is extracted automatically +from the sources by Stephen Edwards's extdoc. (The Ext system is +available via anonymous FTP from +ic.eecs.berkeley.edu.) +The following guidelines are followed in CUDD to insure consistent and +effective use of automatic extraction. It is recommended that +extensions to CUDD follow the same documentation guidelines. + +

            +
          • The documentation of an exported procedure should be sufficient + to allow one to use it without reading the code. It is not necessary + to explain how the procedure works; only what it does. +
          • +
          • The SeeAlso + fields should be space-separated lists of function names. The + SeeAlso field of an exported procedure should only reference + other exported procedures. The SeeAlso field of an internal + procedure may reference other internal procedures as well as + exported procedures, but no static procedures. +
          • +
          • The return values are detailed in the + Description + field, not in the + Synopsis field. +
          • +
          • The parameters are documented alongside their declarations. + Further comments may appear in the Description field. +
          • +
          • If the Description field is non-empty--which is the + normal case for an exported procedure--then the synopsis is + repeated--possibly slightly changed--at the beginning of the + Description field. This is so because extdoc will not put the + synopsis in the same HTML file as + the description. +
          • +
          • The Synopsis field should be about one line long. +
          • +
          + +

          +


          + + +next + +up + +previous + +index +
          + Next: The C++ Interface + Up: CUDD: CU Decision Diagram + Previous: User's Manual +   Index + +
          +Fabio Somenzi +2009-02-20 +
          + + diff --git a/distr/cudd/doc/node5.html b/distr/cudd/doc/node5.html new file mode 100644 index 0000000..6912b76 --- /dev/null +++ b/distr/cudd/doc/node5.html @@ -0,0 +1,160 @@ + + + + + +The C++ Interface + + + + + + + + + + + + + + + + + + + +next + +up + +previous + +index +
          + Next: Acknowledgments + Up: CUDD: CU Decision Diagram + Previous: Programmer's Manual +   Index +
          +
          + + +Subsections + + + +
          + +

          + +
          +The C++ Interface +

          + +

          + +

          + +
          +Compiling and Linking +

          + +

          +To build an application that uses the CUDD C++ interface, you should +add +

          +#include "cuddObj.hh"
          +
          +to your source files. In addition to the normal CUDD libraries (see +Section 3.1) you should link +libobj.a to your executable. Refer to the +Makefile in the top level directory of the +distribution for further details. + +

          + +

          + +
          +Basic Manipulation +

          + +

          +The following fragment of code illustrates some simple operations on +BDDs using the C++ interface. +

          +	Cudd mgr(0,0);
          +	BDD x = mgr.bddVar();
          +	BDD y = mgr.bddVar();
          +	BDD f = x * y;
          +	BDD g = y + !x;
          +	cout << "f is" << (f <= g ? "" : " not")
          +	     << " less than or equal to g\n";
          +
          +This code creates a manager called mgr and two variables in it. +It then defines two functions f and g in terms of the +variables. Finally, it prints a message based on the comparison of the +two functions. No explicit referencing or dereferencing is required. +The operators are overloaded in the intuitive way. BDDs are freed when +execution leaves the scope in which they are defined or when the +variables referring to them are overwritten. + +

          +


          + + +next + +up + +previous + +index +
          + Next: Acknowledgments + Up: CUDD: CU Decision Diagram + Previous: Programmer's Manual +   Index + +
          +Fabio Somenzi +2009-02-20 +
          + + diff --git a/distr/cudd/doc/node6.html b/distr/cudd/doc/node6.html new file mode 100644 index 0000000..10b0d54 --- /dev/null +++ b/distr/cudd/doc/node6.html @@ -0,0 +1,135 @@ + + + + + +Acknowledgments + + + + + + + + + + + + + + + + + + + +next + +up + +previous + +index +
          + Next: Bibliography + Up: CUDD: CU Decision Diagram + Previous: The C++ Interface +   Index +
          +
          + + +

          + +
          +Acknowledgments +

          + +

          +The contributors: Iris Bahar, Hyunwoo Cho, Erica Frohm, Charlie Gaona, +Cheng Hua, Jae-Young Jang, Seh-Woong Jeong, Balakrishna Kumthekar, +Enrico Macii, Bobbie Manne, In-Ho Moon, Curt Musfeldt, Shipra Panda, +Abelardo Pardo, Bernard Plessier, Kavita Ravi, Hyongkyoon Shin, Alan +Shuler, Arun Sivakumaran, Jorgen Sivesind. + +

          +The early adopters: Gianpiero Cabodi, Jordi Cortadella, Mario Escobar, +Gayani Gamage, Gary Hachtel, Mariano Hermida, Woohyuk Lee, Enric +Pastor, Massimo Poncino, Ellen Sentovich, the students of ECEN5139. + +

          +I am also particularly indebted to the following people for in-depth +discussions on BDDs: Armin Biere, Olivier Coudert, Geert Janssen, Don +Knuth, David Long, Jean Christophe Madre, Ken McMillan, Shin-Ichi +Minato, Jaehong Park, Rajeev Ranjan, Rick Rudell, Ellen Sentovich, Tom +Shiple, Christian Stangier, and Bwolen Yang. + +

          +Special thanks to Norris Ip for guiding my faltering steps +in the design of the C++ interface. +Gianpiero Cabodi and Stefano Quer have graciously agreed to let me +distribute their dddmp library with CUDD. + +

          +Masahiro Fujita, Gary Hachtel, and Carl Pixley have provided +encouragement and advice. + +

          +The National Science Foundation and the Semiconductor Research +Corporation have supported in part the development of this package. + +

          + +


          + + +next + +up + +previous + +index +
          + Next: Bibliography + Up: CUDD: CU Decision Diagram + Previous: The C++ Interface +   Index + +
          +Fabio Somenzi +2009-02-20 +
          + + diff --git a/distr/cudd/doc/node7.html b/distr/cudd/doc/node7.html new file mode 100644 index 0000000..d85d7bb --- /dev/null +++ b/distr/cudd/doc/node7.html @@ -0,0 +1,198 @@ + + + + + +Bibliography + + + + + + + + + + + + + + + + + + + +next + +up + +previous + +index +
          + Next: Index + Up: CUDD: CU Decision Diagram + Previous: Acknowledgments +   Index +

          + + +

          +Bibliography +

          1 +
          +R. I. Bahar, E. A. Frohm, C. M. Gaona, G. D. Hachtel, E. Macii, A. Pardo, and + F. Somenzi. +
          Algebraic decision diagrams and their applications. +
          In Proceedings of the International Conference on Computer-Aided + Design, pages 188-191, Santa Clara, CA, November 1993. + +

          2 +
          +B. Bollig, M. Löbbing, and I. Wegener. +
          Simulated annealing to improve variable orderings for OBDDs. +
          Presented at the International Workshop on Logic Synthesis, + Granlibakken, CA, May 1995. + +

          3 +
          +K. S. Brace, R. L. Rudell, and R. E. Bryant. +
          Efficient implementation of a BDD package. +
          In Proceedings of the 27th Design Automation Conference, pages + 40-45, Orlando, FL, June 1990. + +

          4 +
          +R. K. Brayton et al. +
          VIS: A system for verification and synthesis. +
          Technical Report UCB/ERL M95/104, Electronics Research Lab, Univ. of + California, December 1995. + +

          5 +
          +R. E. Bryant. +
          Graph-based algorithms for Boolean function manipulation. +
          IEEE Transactions on Computers, C-35(8):677-691, August 1986. + +

          6 +
          +R. Drechsler, B. Becker, and N. Göckel. +
          A genetic algorithm for variable ordering of OBDDs. +
          Presented at the International Workshop on Logic Synthesis, + Granlibakken, CA, May 1995. + +

          7 +
          +S. J. Friedman and K. J. Supowit. +
          Finding the optimal variable ordering for binary decision diagrams. +
          IEEE Transactions on Computers, 39(5):710-713, May 1990. + +

          8 +
          +M. Fujita, Y. Matsunaga, and T. Kakuda. +
          On variable ordering of binary decision diagrams for the application + of multi-level logic synthesis. +
          In Proceedings of the European Conference on Design Automation, + pages 50-54, Amsterdam, February 1991. + +

          9 +
          +M. Held and R. M. Karp. +
          A dynamic programming approach to sequencing problems. +
          J. SIAM, 10(1):196-210, 1962. + +

          10 +
          +N. Ishiura, H. Sawada, and S. Yajima. +
          Minimization of binary decision diagrams based on exchanges of + variables. +
          In Proceedings of the International Conference on Computer-Aided + Design, pages 472-475, Santa Clara, CA, November 1991. + +

          11 +
          +S.-W. Jeong, T.-S. Kim, and F. Somenzi. +
          An efficient method for optimal BDD ordering computation. +
          In International Conference on VLSI and CAD (ICVC'93), Taejon, + Korea, November 1993. + +

          12 +
          +S.-I. Minato. +
          Zero-suppressed BDDs for set manipulation in combinatorial + problems. +
          In Proceedings of the Design Automation Conference, pages + 272-277, Dallas, TX, June 1993. + +

          13 +
          +S. Panda and F. Somenzi. +
          Who are the variables in your neighborhood. +
          In Proceedings of the International Conference on Computer-Aided + Design, pages 74-77, San Jose, CA, November 1995. + +

          14 +
          +S. Panda, F. Somenzi, and B. F. Plessier. +
          Symmetry detection and dynamic variable ordering of decision + diagrams. +
          In Proceedings of the International Conference on Computer-Aided + Design, pages 628-631, San Jose, CA, November 1994. + +

          15 +
          +B. F. Plessier. +
          A General Framework for Verification of Sequential Circuits. +
          PhD thesis, University of Colorado at Boulder, Dept. of Electrical + and Computer Engineering, 1993. + +

          16 +
          +R. Rudell. +
          Dynamic variable ordering for ordered binary decision diagrams. +
          In Proceedings of the International Conference on Computer-Aided + Design, pages 42-47, Santa Clara, CA, November 1993. + +

          17 +
          +E. M. Sentovich, K. J. Singh, C. Moon, H. Savoj, R. K. Brayton, and + A. Sangiovanni-Vincentelli. +
          Sequential circuit design using synthesis and optimization. +
          In Proceedings of the International Conference on Computer + Design, pages 328-333, Cambridge, MA, October 1992. +
          + + + + + + + +

          +


          +
          +Fabio Somenzi +2009-02-20 +
          + + diff --git a/distr/cudd/doc/node8.html b/distr/cudd/doc/node8.html new file mode 100644 index 0000000..8140ab1 --- /dev/null +++ b/distr/cudd/doc/node8.html @@ -0,0 +1,845 @@ + + + + + +Index + + + + + + + + + + + + + + + + +next + +up + +previous +
          + Up: CUDD: CU Decision Diagram + Previous: Bibliography +
          +
          + +
          + +

          +Index +

          +
          ADD +
          Introduction + | Nodes + | New Constants + | Basic ADD Manipulation +
          aggregation +
          Variable Reordering for BDDs +
          Algebraic Decision Diagram +
          see ADD +
          arc +
          +
          complement +
          New BDD and ADD + | Writing Decision Diagrams to + | Writing Decision Diagrams to + | Complement Arcs + | Complement Arcs +
          regular +
          Writing Decision Diagrams to + | Writing Decision Diagrams to + | Complement Arcs +
          +
          background value +
          Background +
          BDD +
          Introduction + | Nodes + | One, Logic Zero, and + | Basic BDD Manipulation +
          Binary Decision Diagram +
          see BDD +
          box +
          +
          black +
          Introduction +
          clear +
          Introduction + | Compiling and Linking +
          +
          cache +
          Cache + | Cache + | Cache + | Initializing and Shutting Down + | Complement Arcs + | The Cache +
          +
          collision +
          Non Modifiable Parameters +
          collision list +
          The Unique Table +
          deletion +
          Non Modifiable Parameters +
          local +
          The Cache + | Local Caches +
          lossless +
          Local Caches +
          reward-based resizing +
          Cache Sizing + | Cache Sizing +
          sizing +
          Cache Sizing +
          +
          cacheSize +
          Initializing and Shutting Down +
          canonical +
          The Manager + | Local Caches +
          compiling +
          Compiling and Linking + | Predefined Constants + | Compiling and Linking +
          configuration +
          The CUDD Package +
          conversion +
          +
          of ADDs to BDDs +
          Converting ADDs to BDDs +
          of BDDs to ADDs +
          Converting ADDs to BDDs +
          of BDDs to ZDDs +
          Basic ZDD Manipulation + | Converting BDDs to ZDDs +
          of ZDDs to BDDs +
          Converting BDDs to ZDDs +
          +
          cube sets +
          Introduction +
          cudd.h +
          Compiling and Linking + | Variable Reordering for BDDs + | Saturating Increments and Decrements +
          Cudd_addApply +
          Basic ADD Manipulation + | Basic ADD Manipulation +
          Cudd_addBddInterval +
          Converting ADDs to BDDs +
          Cudd_addBddPattern +
          Converting ADDs to BDDs +
          Cudd_addBddThreshold +
          Converting ADDs to BDDs +
          Cudd_addConst +
          New Constants +
          Cudd_addHarwell +
          Background +
          Cudd_AddHook +
          Hooks +
          Cudd_addIthBit +
          Converting ADDs to BDDs +
          Cudd_addIthVar +
          New BDD and ADD +
          Cudd_addNewVar +
          New BDD and ADD +
          Cudd_addNewVarAtLevel +
          New BDD and ADD + | Grouping Variables +
          Cudd_addRead +
          Background +
          Cudd_addTimes +
          Basic ADD Manipulation +
          Cudd_AutodynDisable +
          Variable Reordering for BDDs +
          Cudd_AutodynDisableZdd +
          Variable Reordering for ZDDs +
          Cudd_AutodynEnable +
          Variable Reordering for BDDs + | Variable Reordering for BDDs +
          Cudd_AutodynEnableZdd +
          Variable Reordering for ZDDs +
          Cudd_bddAnd +
          Basic BDD Manipulation + | Basic BDD Manipulation + | Basic ADD Manipulation +
          Cudd_bddConstrain +
          Nodes +
          Cudd_bddIte +
          Basic BDD Manipulation +
          Cudd_bddIthVar +
          New BDD and ADD +
          Cudd_bddNewVar +
          New BDD and ADD + | New BDD and ADD + | New BDD and ADD +
          Cudd_bddNewVarAtLevel +
          New BDD and ADD + | Grouping Variables +
          Cudd_BddToAdd +
          Converting ADDs to BDDs +
          Cudd_bddXor +
          Basic ADD Manipulation +
          CUDD_CACHE_SLOTS +
          Initializing and Shutting Down +
          Cudd_CheckKeys +
          Debugging +
          Cudd_CheckZeroRef +
          Debugging +
          Cudd_CountMinterm +
          Background +
          Cudd_DebugCheck +
          Debugging +
          Cudd_DelayedDerefBdd +
          Non Modifiable Parameters +
          Cudd_Deref +
          Cudd_RecursiveDeref vs. Cudd_Deref + | Saturating Increments and Decrements +
          Cudd_DumpBlif +
          Writing Decision Diagrams to +
          Cudd_DumpDaVinci +
          Writing Decision Diagrams to +
          Cudd_DumpDot +
          Writing Decision Diagrams to +
          Cudd_ForeachCube +
          Nodes + | Background +
          Cudd_ForeachNode +
          Nodes +
          Cudd_HookType +
          Hooks +
          Cudd_Init +
          Initializing and Shutting Down + | Initializing and Shutting Down +
          Cudd_MakeTreeNode +
          Grouping Variables + | Grouping Variables +
          Cudd_MakeZddTreeNode +
          Variable Reordering for ZDDs +
          Cudd_Not +
          One, Logic Zero, and +
          Cudd_PrintInfo +
          Gathering and Interpreting Statistics +
          Cudd_PrintMinterm +
          Background +
          Cudd_Quit +
          Initializing and Shutting Down +
          Cudd_ReadBackground +
          Background +
          Cudd_ReadEpsilon +
          Predefined Constants +
          Cudd_ReadErrorCode +
          NULL Return Values +
          Cudd_ReadInvPerm +
          Basic BDD Manipulation +
          Cudd_ReadLogicZero +
          One, Logic Zero, and +
          Cudd_ReadLooseUpto +
          Setting Parameters +
          Cudd_ReadMaxGrowth +
          Variable Reordering for BDDs +
          Cudd_ReadMinusInfinity +
          Predefined Constants +
          Cudd_ReadOne +
          One, Logic Zero, and +
          Cudd_ReadPlusInfinity +
          Predefined Constants +
          Cudd_ReadReorderings +
          Allowing Asynchronous Reordering +
          Cudd_ReadSiftMaxVar +
          Variable Reordering for BDDs +
          Cudd_ReadTree +
          Grouping Variables +
          Cudd_ReadZddOne +
          One, Logic Zero, and + | Basic ZDD Manipulation +
          Cudd_ReadZero +
          Predefined Constants +
          Cudd_RecursiveDeref +
          Nodes + | Reference Counts + | Reference Counts + | Reference Counts + | Cudd_RecursiveDeref vs. Cudd_Deref + | When Increasing the Reference + | Saturating Increments and Decrements + | Local Caches + | Debugging +
          Cudd_RecursiveDerefZdd +
          Nodes + | Reference Counts + | Reference Counts + | Reference Counts + | When Increasing the Reference + | Saturating Increments and Decrements +
          Cudd_ReduceHeap +
          Variable Reordering for BDDs + | Variable Reordering for BDDs + | Variable Reordering for BDDs +
          Cudd_Ref +
          Nodes + | Basic BDD Manipulation + | Reference Counts + | When Increasing the Reference +
          Cudd_Regular +
          Complement Arcs +
          CUDD_REORDER_ANNEALING +
          Variable Reordering for BDDs +
          CUDD_REORDER_EXACT +
          Variable Reordering for BDDs +
          CUDD_REORDER_GENETIC +
          Variable Reordering for BDDs +
          CUDD_REORDER_GROUP_SIFT +
          Variable Reordering for BDDs +
          CUDD_REORDER_GROUP_SIFT_CONV +
          Variable Reordering for BDDs +
          CUDD_REORDER_NONE +
          Variable Reordering for BDDs + | Variable Reordering for ZDDs +
          CUDD_REORDER_RANDOM +
          Variable Reordering for BDDs + | Variable Reordering for ZDDs +
          CUDD_REORDER_RANDOM_PIVOT +
          Variable Reordering for BDDs + | Variable Reordering for ZDDs +
          CUDD_REORDER_SAME +
          Variable Reordering for BDDs + | Variable Reordering for ZDDs +
          CUDD_REORDER_SIFT +
          Variable Reordering for BDDs + | Variable Reordering for ZDDs +
          CUDD_REORDER_SIFT_CONVERGE +
          Variable Reordering for BDDs + | Variable Reordering for ZDDs +
          CUDD_REORDER_SYMM_SIFT +
          Variable Reordering for BDDs + | Variable Reordering for ZDDs +
          CUDD_REORDER_SYMM_SIFT_CONV +
          Variable Reordering for BDDs + | Variable Reordering for ZDDs +
          CUDD_REORDER_WINDOW2 +
          Variable Reordering for BDDs +
          CUDD_REORDER_WINDOW2_CONV +
          Variable Reordering for BDDs +
          CUDD_REORDER_WINDOW3 +
          Variable Reordering for BDDs +
          CUDD_REORDER_WINDOW3_CONV +
          Variable Reordering for BDDs +
          CUDD_REORDER_WINDOW4 +
          Variable Reordering for BDDs +
          CUDD_REORDER_WINDOW4_CONV +
          Variable Reordering for BDDs +
          Cudd_SetEpsilon +
          Predefined Constants +
          Cudd_SetLooseUpTo +
          Setting Parameters +
          Cudd_SetMaxCacheHard +
          Modifiable Parameters +
          Cudd_SetMaxGrowth +
          Variable Reordering for BDDs +
          Cudd_SetSiftMaxVar +
          Variable Reordering for BDDs +
          Cudd_SetTree +
          Grouping Variables +
          Cudd_ShuffleHeap +
          Variable Reordering for BDDs +
          Cudd_StdPostReordHook +
          Hooks +
          Cudd_StdPreReordHook +
          Hooks +
          Cudd_SymmProfile +
          Variable Reordering for BDDs +
          CUDD_UNIQUE_SLOTS +
          Initializing and Shutting Down +
          Cudd_zddDumpDot +
          Writing Decision Diagrams to +
          Cudd_zddIsop +
          Basic ZDD Manipulation +
          Cudd_zddIthVar +
          New ZDD Variables +
          Cudd_zddPortFromBdd +
          Converting BDDs to ZDDs +
          Cudd_zddPortToBdd +
          Converting BDDs to ZDDs +
          Cudd_zddRealignDisable +
          Keeping Consistent Variable Orders +
          Cudd_zddRealignEnable +
          Keeping Consistent Variable Orders +
          Cudd_zddReduceHeap +
          Variable Reordering for ZDDs +
          Cudd_zddShuffleHeap +
          Variable Reordering for ZDDs +
          Cudd_zddVarsFromBddVars +
          Converting BDDs to ZDDs + | Converting BDDs to ZDDs +
          Cudd_zddWeakDiv +
          Basic ZDD Manipulation +
          cuddCacheInsert +
          The Cache +
          cuddCacheInsert1 +
          The Cache +
          cuddCacheInsert2 +
          The Cache +
          cuddCacheLookup +
          The Cache +
          cuddCacheLookup1 +
          The Cache +
          cuddCacheLookup2 +
          The Cache +
          CUDDDIR +
          Using the CUDD Package +
          cuddHeapProfile +
          Debugging +
          cuddI +
          The Unique Table +
          cuddInt.h +
          Debugging +
          cuddIZ +
          The Unique Table +
          cuddSatDec +
          Saturating Increments and Decrements +
          cuddSatInc +
          Saturating Increments and Decrements +
          cuddUniqueConst +
          Reference Counts + | Reference Counts + | Reference Counts +
          cuddUniqueInter +
          Reference Counts + | Reference Counts + | Reference Counts + | Complement Arcs + | Complement Arcs + | Allowing Asynchronous Reordering + | Allowing Asynchronous Reordering + | Allowing Asynchronous Reordering +
          cuddUniqueInterZdd +
          Reference Counts + | Reference Counts + | Reference Counts + | Allowing Asynchronous Reordering +
          DD_CACHE_PROFILE +
          Extended Statistics and Reporting +
          DD_DEBUG +
          Debugging +
          DD_STATS +
          Extended Statistics and Reporting +
          DD_UNIQUE_PROFILE +
          Extended Statistics and Reporting +
          DD_VERBOSE +
          Extended Statistics and Reporting +
          DdManager +
          The Manager + | Initializing and Shutting Down +
          DdNode +
          Nodes + | The Cache +
          debugging +
          Debugging +
          DEC Alpha +
          Predefined Constants + | Using the CUDD Package +
          documentation +
          Guidelines for Documentation +
          +
          Description +
          Guidelines for Documentation +
          HTML files +
          Guidelines for Documentation +
          SeeAlso +
          Guidelines for Documentation +
          Synopsis +
          Guidelines for Documentation +
          +
          dot +
          see graph, drawing +
          Epsilon +
          Predefined Constants +
          extdoc +
          see documentation +
          floating point +
          Predefined Constants +
          +
          double (C type) +
          Nodes +
          IEEE Standard 754 +
          Predefined Constants +
          +
          free list +
          Reference Counts +
          FTP +
          The CUDD Package + | CUDD Friends + | Using the CUDD Package + | Guidelines for Documentation +
          function +
          +
          characteristic +
          Introduction + | Converting BDDs to ZDDs +
          cover +
          Basic ZDD Manipulation + | Converting BDDs to ZDDs + | Converting BDDs to ZDDs +
          +
          irredundant +
          Basic ZDD Manipulation +
          +
          minterms +
          Background + | Allowing Asynchronous Reordering +
          ON-set +
          Introduction +
          sum of products +
          Background +
          switching +
          Introduction + | Introduction +
          +
          garbage collection +
          Nodes + | Cache + | Setting Parameters + | Reference Counts + | Reference Counts + | The Cache + | Local Caches + | The Unique Table +
          +
          hooks +
          Hooks +
          +
          gcc +
          Predefined Constants +
          generator +
          Nodes +
          global variables +
          The Manager +
          graph +
          +
          arc capacity +
          Background +
          arc length +
          Background +
          drawing +
          Writing Decision Diagrams to + | Writing Decision Diagrams to +
          +
          growth +
          Setting Parameters +
          gzip +
          The CUDD Package +
          HAVE_IEEE_754 +
          Predefined Constants +
          header files +
          Variable Reordering for BDDs + | Saturating Increments and Decrements +
          hook +
          Hooks +
          infinities +
          Predefined Constants +
          installation +
          The CUDD Package +
          Intel Pentium 4 +
          The CUDD Package +
          interface +
          +
          cache +
          The Cache +
          SIS +
          The SIS/VIS Interface + | Using the CUDD Package +
          VIS +
          The SIS/VIS Interface +
          +
          libraries +
          The CUDD Package +
          +
          cudd +
          Compiling and Linking +
          dddmp +
          Saving and Restoring BDDs +
          mtr +
          Compiling and Linking + | Grouping Variables +
          obj +
          Compiling and Linking +
          st +
          Compiling and Linking + | The Cache +
          util +
          Compiling and Linking +
          +
          Makefile +
          Compiling and Linking + | Predefined Constants + | Compiling and Linking +
          manager +
          The Manager + | The Manager + | Constant Functions +
          matrix +
          +
          sparse +
          Background +
          +
          maxCache +
          Cache Sizing +
          maxMemory +
          Initializing and Shutting Down +
          MinusInfinity +
          Predefined Constants +
          MTR_DEFAULT +
          Grouping Variables +
          MTR_FIXED +
          Grouping Variables +
          nanotrav +
          The CUDD Package + | The CUDD Package +
          node +
          Nodes +
          +
          constant +
          Nodes + | Constant Functions + | One, Logic Zero, and + | Predefined Constants + | Background + | New Constants + | Reference Counts + | When Increasing the Reference +
          +
          value +
          Nodes +
          +
          dead +
          Reference Counts + | The Cache + | The Unique Table +
          dereference +
          Basic ADD Manipulation +
          reclaimed +
          The Unique Table +
          recycling +
          Nodes +
          reference +
          Basic ADD Manipulation +
          reference count +
          Nodes + | Nodes + | Basic BDD Manipulation + | Basic BDD Manipulation + | Reference Counts + | Reference Counts + | Reference Counts + | When Increasing the Reference + | Saturating Increments and Decrements + | The Cache + | Local Caches + | Debugging +
          +
          saturated +
          Debugging +
          +
          terminal +
          see node, constant +
          variable index +
          Nodes +
          +
          numSlots +
          Initializing and Shutting Down +
          numVars +
          Initializing and Shutting Down +
          numVarsZ +
          Initializing and Shutting Down +
          PlusInfinity +
          Predefined Constants + | Background +
          projection functions +
          Creating Variables + | New BDD and ADD + | New BDD and ADD + | New BDD and ADD + | New ZDD Variables + | Basic BDD Manipulation + | Basic ADD Manipulation + | Basic ZDD Manipulation + | Basic ZDD Manipulation + | Debugging +
          README file +
          The CUDD Package + | The CUDD Package +
          reordering +
          Introduction + | Introduction + | Nodes + | The Cache +
          +
          abort and retry +
          Allowing Asynchronous Reordering +
          asynchronous +
          Variable Reordering for BDDs + | Allowing Asynchronous Reordering +
          converging +
          Variable Reordering for BDDs + | Variable Reordering for BDDs + | Variable Reordering for BDDs + | Variable Reordering for BDDs +
          Cudd_ReorderingType +
          Variable Reordering for BDDs +
          dynamic +
          Introduction + | Variable Reordering for BDDs + | Variable Reordering for ZDDs +
          exact +
          Variable Reordering for BDDs +
          function wrapper +
          Allowing Asynchronous Reordering + | Allowing Asynchronous Reordering +
          genetic +
          Variable Reordering for BDDs +
          group +
          Variable Reordering for BDDs + | Variable Reordering for BDDs +
          hooks +
          Hooks +
          interruptible procedure +
          Allowing Asynchronous Reordering +
          of BDDs and ADDs +
          Variable Reordering for BDDs +
          of ZDDs +
          Basic ZDD Manipulation + | Variable Reordering for ZDDs +
          random +
          Variable Reordering for BDDs +
          sifting +
          Variable Reordering for BDDs + | Variable Reordering for BDDs +
          simulated annealing +
          Variable Reordering for BDDs +
          symmetric +
          Variable Reordering for BDDs +
          threshold +
          Variable Reordering for BDDs + | Allowing Asynchronous Reordering +
          window +
          Variable Reordering for BDDs +
          +
          saturating +
          +
          decrements +
          Saturating Increments and Decrements +
          increments +
          Saturating Increments and Decrements +
          +
          SISDIR +
          Using the CUDD Package +
          SIZEOF_INT +
          Saturating Increments and Decrements + | Saturating Increments and Decrements +
          SIZEOF_VOID_P +
          Saturating Increments and Decrements + | Saturating Increments and Decrements +
          statistical counters +
          The Manager + | Reference Counts + | Cache Sizing +
          statistics +
          Gathering and Interpreting Statistics +
          subtable +
          Initializing and Shutting Down + | Reference Counts +
          symmetry +
          Variable Reordering for BDDs +
          table +
          +
          computed +
          Cache +
          growth +
          Setting Parameters +
          hash +
          The Manager + | The Unique Table +
          unique +
          Nodes + | The Manager + | The Manager + | Initializing and Shutting Down + | Initializing and Shutting Down + | Setting Parameters + | Variable Reordering for BDDs + | Reference Counts + | Cache Sizing + | Cache Sizing + | The Unique Table +
          +
          fast growth +
          The Unique Table +
          reward-based resizing +
          The Unique Table +
          slow growth +
          The Unique Table +
          +
          +
          variable +
          +
          groups +
          Grouping Variables +
          order +
          Nodes + | New BDD and ADD +
          permutation +
          Nodes + | The Unique Table +
          tree +
          Grouping Variables + | Grouping Variables +
          +
          ZDD +
          Introduction + | Nodes + | New ZDD Variables + | Basic ZDD Manipulation + | Converting BDDs to ZDDs +
          zero +
          +
          arithmetic +
          One, Logic Zero, and + | New BDD and ADD + | Converting ADDs to BDDs +
          logical +
          One, Logic Zero, and + | Converting ADDs to BDDs +
          +
          Zero-suppressed Binary Decision Diagram +
          see ZDD + +
          +

          +
          +Fabio Somenzi +2009-02-20 +
          + + diff --git a/distr/cudd/r7x8.1.mat b/distr/cudd/r7x8.1.mat new file mode 100644 index 0000000..b0dd0a0 --- /dev/null +++ b/distr/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/distr/cudd/r7x8.1.out b/distr/cudd/r7x8.1.out new file mode 100644 index 0000000..8ca6188 --- /dev/null +++ b/distr/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/distr/cudd/testcudd.c b/distr/cudd/testcudd.c new file mode 100644 index 0000000..0b5adf9 --- /dev/null +++ b/distr/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; iinvperm[i]); + } + (void) printf("\n"); + (void) printf("Inverse Permutation:"); + for (i=0; iperm[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/distr/dddmp/Makefile b/distr/dddmp/Makefile new file mode 100644 index 0000000..3f06cc2 --- /dev/null +++ b/distr/dddmp/Makefile @@ -0,0 +1,243 @@ +#----------------------------------------------------------------------------# +# Makefile for the dddmp distribution kit # +# dddmp: Decision Diagram DuMP # +# (storage and retrieval of BDDs, ADDs and CNF formulas) # +# Revision: Version 2.0.2, February 01, 2004 # +#----------------------------------------------------------------------------# + +# Commands Available: +# make +# it makes the library libdddmp.a +# make testdddmp +# it makes the testdddmp program, which allows to test the dddmp +# package +# make clean +# it cleans dddmp +# make distclean +# it cleans dddmp (as clean) with libraries and executable +# files + +#----------------------------------------------------------------------------# +# Configuration Section # +# uncomment the desired options/sections # +#----------------------------------------------------------------------------# + +#--------------------# +# Define Directories # +#--------------------# + +# Cudd directory +WHERE = .. +#WHERE = ../cudd-2.4.0 + +# Include directory (Cudd include files) +INCLUDE = $(WHERE)/include + +#------------------------# +# Define C Compiler Used # +#------------------------# + +CC = gcc +#CC = g++ +#CC = cc +#CC = icc +#CC = ecc +#CC = /usr/ucb/cc +#CC = c89 + +.SUFFIXES: .o .c .u + +#---------------# +# Define ranlib # +#---------------# + +# For machines with ranlib and you think it is needed +RANLIB = ranlib +# For machines which either do not have ranlib or can do without it +#RANLIB = : + +#----------------------------------# +# Define Machine Independent Flags # +#----------------------------------# + +# Settings for cc +#ICFLAGS = +#ICFLAGS = -g +#ICFLAGS = -O +# Settings for optimized code with gcc +#ICFLAGS = -g -Wall +#ICFLAGS = -g -O3 -Wall +ICFLAGS = -g -O6 -Wall + +#--------------------------------# +# Define Machine Dependent Flags # +#--------------------------------# + +# When no special flags are needed +#XCFLAGS = -DHAVE_IEEE_754 -DBSD +# Linux with Gcc 2.8.1 or higher on i686. +XCFLAGS = -mcpu=pentiumpro -malign-double -DHAVE_IEEE_754 -DBSD +# Gcc 3.3.2 or higher on i686. +#XCFLAGS = -mcpu=pentium4 -malign-double -DHAVE_IEEE_754 -DBSD +# For Solaris, BSD should not be replaced by UNIX100. +#XCFLAGS = -DHAVE_IEEE_754 -DUNIX100 -DEPD_BIG_ENDIAN +# New native compiler for the Alphas; 64-bit pointers. +#XCFLAGS = -g3 -O4 -std -DBSD -DHAVE_IEEE_754 -ieee_with_no_inexact -tune host -DSIZEOF_VOID_P=8 -DSIZEOF_LONG=8 +# New native compiler for the Alphas; 32-bit pointers. +#XCFLAGS = -g3 -O4 -std -DBSD -DHAVE_IEEE_754 -ieee_with_no_inexact -tune host -xtaso -DSIZEOF_LONG=8 +# Windows95/98/NT/XP with Cygwin tools +#XCFLAGS = -mcpu=pentiumpro -malign-double -DHAVE_IEEE_754 -DHAVE_GETRLIMIT=0 -DRLIMIT_DATA_DEFAULT=67108864 + +#---------------------------------------------# +# Define Level of Self-Checking and Verbosity # +#---------------------------------------------# + +# ... for the CUDD package +#DDDEBUG = -DDD_DEBUG -DDD_VERBOSE -DDD_STATS -DDD_CACHE_PROFILE -DDD_UNIQUE_PROFILE -DDD_COUNT +DDDEBUG = + +# ... for the MTR package +#MTRDEBUG = -DMTR_DEBUG +MTRDEBUG = + +# ... for the DDDMP package +#DDDMPDEBUG = -DDDDMP_DEBUG +DDDMPDEBUG = + +#-----------------------# +# Define Loader Options # +#-----------------------# + +LDFLAGS = +# This may produce faster code on the DECstations. +#LDFLAGS = -jmpopt -Olimit 1000 +# This may be necessary under some old versions of Linux. +#LDFLAGS = -static +# This normally makes the program faster on the DEC Alphas. +#LDFLAGS = -non_shared -om +# This is for 32-bit pointers on the DEC Alphas. +#LDFLAGS = -non_shared -om -taso +#LDFLAGS = -non_shared -taso + +#-------------# +# Define PURE # +#-------------# + +PURE = +# ... as purify to link with purify. +#PURE = purify +# ... as quantify to link with quantify. +#PURE = quantify + +#------------# +# Define EXE # +#------------# + +EXE = +# ... as .exe for MS-DOS and derivatives. +#EXE = .exe + +#----------------------------------------------------------------------------# +# Files for the Package # +#----------------------------------------------------------------------------# + +P = dddmp +PSRC = dddmpStoreBdd.c dddmpStoreAdd.c dddmpStoreCnf.c \ + dddmpLoad.c dddmpLoadCnf.c \ + dddmpNodeBdd.c dddmpNodeAdd.c dddmpNodeCnf.c \ + dddmpStoreMisc.c dddmpUtil.c dddmpBinary.c dddmpConvert.c \ + dddmpDbg.c +PHDR = dddmp.h dddmpInt.h $(INCLUDE)/cudd.h $(INCLUDE)/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) + +#----------------------------------------------------------------------------# +# Rules to compile and build libraries and executables # +#----------------------------------------------------------------------------# + +#MFLAG = +MFLAG = -DMNEMOSYNE +MNEMLIB = ../mnemosyne/libmnem.a + +# This is to create the lint library +LINTFLAGS = -u -n +LINTSWITCH = -o + +LIBS = ./libdddmp.a $(WHERE)/cudd/libcudd.a $(WHERE)/mtr/libmtr.a \ + $(WHERE)/st/libst.a $(WHERE)/util/libutil.a $(WHERE)/epd/libepd.a + +MNEMLIB = + +BLIBS = -kL. -kldddmp -kL$(WHERE)/cudd -klcudd -kL$(WHERE)/mtr -klmtr \ + -kL$(WHERE)/st -klst -kL$(WHERE)/util -klutil + +LINTLIBS = ./llib-ldddmp.ln $(WHERE)/cudd/llib-lcudd.ln \ + $(WHERE)/mtr/llib-lmtr.ln $(WHERE)/st/llib-lst.ln \ + $(WHERE)/util/llib-lutil.ln + +lib$(P).a: $(POBJ) + ar rv $@ $? + $(RANLIB) $@ + +.c.o: $(PHDR) + $(CC) -c $< -I$(INCLUDE) $(ICFLAGS) $(XCFLAGS) $(DDDEBUG) $(MTRDEBUG) $(DDDMPDEBUG) $(LDFLAGS) + +optimize_dec: lib$(P).b + +lib$(P).b: $(PUBJ) + ar rv $@ $? + $(RANLIB) $@ + +.c.u: $(PHDR) + cc -c $< -I$(INCLUDE) $(CFLAGS) + +# if the header files change, recompile +$(POBJ): $(PHDR) +$(PUBJ): $(PHDR) +$(OBJ): $(PHDR) +$(UBJ): $(PHDR) + +$(TARGET): $(SRC) $(OBJ) $(PHDR) $(LIBS) $(MNEMLIB) + $(PURE) $(CC) $(ICFLAGS) $(XCFLAGS) $(DDDEBUG) $(MTRDEBUG) $(DDDMPDEBUG) $(LDFLAGS) -o $@ $(OBJ) $(LIBS) $(MNEMLIB) -lm + +# optimize (DECstations and Alphas only: uses u-code) +$(TARGETu): $(SRC) $(UBJ) $(PHDR) $(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 the Package # +#----------------------------------------------------------------------------# + +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/distr/dddmp/README.dddmp b/distr/dddmp/README.dddmp new file mode 100644 index 0000000..704bd19 --- /dev/null +++ b/distr/dddmp/README.dddmp @@ -0,0 +1,64 @@ +README file for the DDDMP-2.0 package +Revision: Version 2.0.2, February 01, 2004 + + + +WHAT IS DDDMP +============= + +The DDDMP package defines formats for DD storage on file, and it contains a +set of functions to dump DDs and DD forests on file. + +In the version 1.0, only BDDs (ROBDDs) of the CUDD package (version 2.2.0 +or higher) were supported. +The version 2.0 includes supports for ADDs and CNF formulas. +The version 2.0.2 is for bug fixes. + + + +MAKE DDDMP +========== + +Before you build the libraries and programs, you need to check the +Makefile in the top directory. +Go through the definitions contained in the configuration section, and +select the desired compiler and compilation flags. +Instructions are provided in the comments of the Makefile. + +Then run "make". +This should produce the dddmplib.a library. + + + +DOCUMENTATION +============= + +Directory dddmp/doc contains HTML documentation for the package. +The recommended starting point is package.html. +Documentation in both postscript format and plain text format is also +provided. + + + +FTP SITE +======== + +The package is singularly available from the author home page: +http://staff.polito.it/{gianpiero.cabodi,stefano.quer} + + + + +FEEDBACK +======== + +Send feedback to: + +Stefano Quer & Gianpiero Cabodi +Politecnico di Torino +Dip. Automatica e Informatica +C.so Duca degli Abruzzi 24 +I-10129 Torino +Italy +E-mail: {gianpiero.cabodi,stefano.quer}@polito.it +WEB page: http://staff.polito.it/{gianpiero.cabodi,stefano.quer} diff --git a/distr/dddmp/README.testdddmp b/distr/dddmp/README.testdddmp new file mode 100644 index 0000000..e1e1acf --- /dev/null +++ b/distr/dddmp/README.testdddmp @@ -0,0 +1,79 @@ +README file for the test program of the DDDMP-2.0 package +Revision: Version 2.0.2, February 01, 2004 + + + +WHAT IS TESTDDDMP +================= + +testdddmp is a test program for the dddmp package. +Practically, it is a naive user interface to load, store and execute +operations with BDDs. +It is included to provide a sanity check for the installation of the +package and an easy tool to play with BDDs and BDD on files. + + + +MAKE TESTDDDMP +============== + +Run "make testdddmp". +This should produce the testdddmp executable file. + + + +TEST DDDMP +========== + +Run the runAllTest.script file in the exp directory. +This should run all the test?.script files in the same directory. +Each of them is specifically written to check a particular feature of +the package (e.g., store and load of BDDs, store of CNF formulas and +retrieval, etc.). +Each test?.script should terminate with a comparison with a previously +generated set of files, then with the following set of messages: + +Files 0or1.bdd and 0or1.bdd2 are identical +Files 2and3.bdd and 2and3.bdd2 are identical +... + +If so everything is OK. + +Notice that mismatches may be caused by the presence of CR - LF characters at +the end of each BDD file line. + + + +WORK WITH DDDMPTEST +=================== + +To work with dddmptest (once the executable file has been built) it is enough +to run it (no parameter is necessary). +The help command print out the main commands available. +For each command further inputs are eventually required on an interactive +basis. +BDDs and ADDs can be loaded from files by choosing the file name or they +can be directly created (randomly for example). +They can be maintained into the main memory trough an array of BDD pointers. +Operations (logical and re-ordering) can be performed on any BDD into this +array. +Eventually any of them can be stored in a file giving the file name. +BDDs can also be stored in a CNF format using three different possible +solution to store them. + + + +FEEDBACK +======== + +Send feedback to: + +Gianpiero Cabodi and Stefano Quer +Politecnico di Torino +Dip. Automatica e Informatica +C.so Duca degli Abruzzi 24 +I-10129 Torino +Italy +E-mail: {gianpiero.cabodi,stefano.quer}@polito.it +WEB page: http://staff.polito.it/{gianpiero.cabodi,stefano.quer} + diff --git a/distr/dddmp/RELEASE_NOTES b/distr/dddmp/RELEASE_NOTES new file mode 100644 index 0000000..c8f4b9a --- /dev/null +++ b/distr/dddmp/RELEASE_NOTES @@ -0,0 +1,60 @@ +RELEASE NOTES FOR DDDMP +Revision: Version 2.0.2 +Turin, Italy, February 01, 2004 + +dddmp-2.0.2 is now available at +WEB page: http://staff.polito.it/{gianpiero.cabodi,stefano.quer} +dddmp-2.0.2 has a few bug fixes with respect to dddmp-2.0 + +Release 2.0.2 of DDDMP improves DDDMP-1.2 in the following areas: + + 1. Support to store and load ADD has been inserted in the dddmp tool + + 2. Support to store BDDs as CNF formulas has been inserted in the + dddmp tool. + As far as the storing process is concerned three possible formats + are available: + + DDDMP_CNF_MODE_NODE + store a BDD by introducing an auxiliary variable for each BDD node + + DDDMP_CNF_MODE_MAXTERM + store a BDD by following the maxterm of the represented function + + DDDMP_CNF_MODE_BEST + trade-of between the two previous solution, trying to optimize + the number of literals stored. + + As far as the loading process is concerned three possible formats + are available: + + DDDMP_CNF_MODE_NO_CONJ + Return the Clauses without Conjunction + + DDDMP_CNF_MODE_NO_QUANT + Return the sets of BDDs without Quantification + + DDDMP_CNF_MODE_CONJ_QUANT + Return the sets of BDDs AFTER Existential Quantification + + 3. Functions to load the header of a BDD/ADD/CNF file, so collecting + information regarding variables, variable ordering, etc. + This can be seen as a pre-processing step prior a possible BDD/ADD/CNF + load of the entire structure. + Moreover it can be used in a manager initialization phase. + + 4. More precise information are stored in each BDD/ADD header during + the storing phase. + In particular this information may be used to make up the exact + variable ordering present in the manager used during the storing + phase. + Full compatibility with previously versions of the files (from + dddmp-1.0 on) is guaranteed. + + 5. Miscellaneous + Debugging has been performed on different hardware architectures + + 6. The test program, testdddmp has been improved. + Now it allows to perform more operations and to better debug the + different options. + diff --git a/distr/dddmp/dddmp.h b/distr/dddmp/dddmp.h new file mode 100644 index 0000000..7228fe7 --- /dev/null +++ b/distr/dddmp/dddmp.h @@ -0,0 +1,330 @@ +/**CHeaderFile***************************************************************** + + FileName [dddmp.h] + + PackageName [dddmp] + + Synopsis [Functions to read in and write out BDDs, ADDs + and CNF formulas from and to files.] + + Description [] + + Author [Gianpiero Cabodi and Stefano Quer] + + Copyright [ + Copyright (c) 2002 by Politecnico di Torino. + All Rights Reserved. This software is for educational purposes only. + Permission is given to academic institutions to use, copy, and modify + this software and its documentation provided that this introductory + message is not removed, that this software and its documentation is + used for the institutions' internal research and educational purposes, + and that no monies are exchanged. No guarantee is expressed or implied + by the distribution of this code. + Send bug-reports and/or questions to: + {gianpiero.cabodi,stefano.quer}@polito.it. + ] + +******************************************************************************/ + +#ifndef _DDDMP +#define _DDDMP + +#if 0 +#define DDDMP_DEBUG +#endif + +/*---------------------------------------------------------------------------*/ +/* Nested includes */ +/*---------------------------------------------------------------------------*/ + +#include "util.h" +#include "cudd.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/*---------------------------------------------------------------------------*/ +/* Constant declarations */ +/*---------------------------------------------------------------------------*/ + +/* + * Dddmp format version + */ + +#define DDDMP_VERSION "DDDMP-2.0" + +/* + * Returned values (for theorically ALL the function of the package) + */ + +#define DDDMP_FAILURE ((int) 0) +#define DDDMP_SUCCESS ((int) 1) + +/* + * Format modes for DD (BDD and ADD) files + */ + +#define DDDMP_MODE_TEXT ((int)'A') +#define DDDMP_MODE_BINARY ((int)'B') +#define DDDMP_MODE_DEFAULT ((int)'D') + +/*---------------------------------------------------------------------------*/ +/* Structure declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Type declarations */ +/*---------------------------------------------------------------------------*/ + +/**Enum************************************************************************ + + Synopsis [Format modes for storing CNF files] + + Description [Type supported for storing BDDs into CNF + formulas. + Used internally to select the proper storing format: + DDDMP_CNF_MODE_NODE: create a CNF temporary variables for + each BDD node + DDDMP_CNF_MODE_MAXTERM: no temporary variables + DDDMP_CNF_MODE_BEST: trade-off between the two previous methods + ] + +******************************************************************************/ + +typedef enum { + DDDMP_CNF_MODE_NODE, + DDDMP_CNF_MODE_MAXTERM, + DDDMP_CNF_MODE_BEST +} Dddmp_DecompCnfStoreType; + +/**Enum************************************************************************ + + Synopsis [Format modes for loading CNF files.] + + Description [Type supported for loading CNF formulas into BDDs. + Used internally to select the proper returning format: + ] + +******************************************************************************/ + +typedef enum { + DDDMP_CNF_MODE_NO_CONJ, + DDDMP_CNF_MODE_NO_QUANT, + DDDMP_CNF_MODE_CONJ_QUANT +} Dddmp_DecompCnfLoadType; + +/**Enum************************************************************************ + + Synopsis [Type for supported decomposition types.] + + Description [Type for supported decomposition types. + Used internally to select the proper type (bdd, add, ...). + Given externally as information fule content. + ] + +******************************************************************************/ + +typedef enum { + DDDMP_BDD, + DDDMP_ADD, + DDDMP_CNF, + DDDMP_NONE +} Dddmp_DecompType; + + +/**Enum************************************************************************ + + Synopsis [Type for variable extra info.] + + Description [Type for variable extra info. Used to specify info stored + in text mode.] + +******************************************************************************/ + +typedef enum { + DDDMP_VARIDS, + DDDMP_VARPERMIDS, + DDDMP_VARAUXIDS, + DDDMP_VARNAMES, + DDDMP_VARDEFAULT +} Dddmp_VarInfoType; + +/**Enum************************************************************************ + + Synopsis [Type for variable matching in BDD load.] + + Description [] + +******************************************************************************/ + +typedef enum { + DDDMP_VAR_MATCHIDS, + DDDMP_VAR_MATCHPERMIDS, + DDDMP_VAR_MATCHAUXIDS, + DDDMP_VAR_MATCHNAMES, + DDDMP_VAR_COMPOSEIDS +} Dddmp_VarMatchType; + +/**Enum************************************************************************ + + Synopsis [Type for BDD root matching in BDD load.] + + Description [] + +******************************************************************************/ + +typedef enum { + DDDMP_ROOT_MATCHNAMES, + DDDMP_ROOT_MATCHLIST +} Dddmp_RootMatchType; + +typedef struct Dddmp_Hdr_s Dddmp_Hdr_t; + +/*---------------------------------------------------------------------------*/ +/* Variable declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Macro declarations */ +/*---------------------------------------------------------------------------*/ + +/**Macro*********************************************************************** + + Synopsis [Checks for fatal bugs] + + Description [Conditional safety assertion. It prints out the file + name and line number where the fatal error occurred. + Messages are printed out on stderr. + ] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ + +#ifdef DDDMP_DEBUG +# define Dddmp_Assert(expr,errMsg) \ + { \ + if ((expr) == 0) { \ + fprintf (stderr, "FATAL ERROR: %s\n", errMsg); \ + fprintf (stderr, " File %s -> Line %d\n", \ + __FILE__, __LINE__); \ + fflush (stderr); \ + exit (DDDMP_FAILURE); \ + } \ + } +#else +# define Dddmp_Assert(expr,errMsg) \ + {} +#endif + +/**Macro*********************************************************************** + + Synopsis [Checks for Warnings: If expr==1 it prints out the warning + on stderr.] + + Description [] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ + +#define Dddmp_Warning(expr,errMsg) \ + { \ + if ((expr) == 1) { \ + fprintf (stderr, "WARNING: %s\n", errMsg); \ + fprintf (stderr, " File %s -> Line %d\n", \ + __FILE__, __LINE__); \ + fflush (stderr); \ + } \ + } + +/**Macro*********************************************************************** + + Synopsis [Checks for fatal bugs and return the DDDMP_FAILURE flag.] + + Description [] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ + +#define Dddmp_CheckAndReturn(expr,errMsg) \ + { \ + if ((expr) == 1) { \ + fprintf (stderr, "FATAL ERROR: %s\n", errMsg); \ + fprintf (stderr, " File %s -> Line %d\n", \ + __FILE__, __LINE__); \ + fflush (stderr); \ + return (DDDMP_FAILURE); \ + } \ + } + +/**Macro*********************************************************************** + + Synopsis [Checks for fatal bugs and go to the label to deal with + the error. + ] + + Description [] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ + +#define Dddmp_CheckAndGotoLabel(expr,errMsg,label) \ + { \ + if ((expr) == 1) { \ + fprintf (stderr, "FATAL ERROR: %s\n", errMsg); \ + fprintf (stderr, " File %s -> Line %d\n", \ + __FILE__, __LINE__); \ + fflush (stderr); \ + goto label; \ + } \ + } + +/**AutomaticStart*************************************************************/ + +/*---------------------------------------------------------------------------*/ +/* Function prototypes */ +/*---------------------------------------------------------------------------*/ + +extern int Dddmp_Text2Bin(char *filein, char *fileout); +extern int Dddmp_Bin2Text(char *filein, char *fileout); +extern int Dddmp_cuddBddDisplayBinary(char *fileIn, char *fileOut); +extern DdNode * Dddmp_cuddBddLoad(DdManager *ddMgr, Dddmp_VarMatchType varMatchMode, char **varmatchnames, int *varmatchauxids, int *varcomposeids, int mode, char *file, FILE *fp); +extern int Dddmp_cuddBddArrayLoad(DdManager *ddMgr, Dddmp_RootMatchType rootMatchMode, char **rootmatchnames, Dddmp_VarMatchType varMatchMode, char **varmatchnames, int *varmatchauxids, int *varcomposeids, int mode, char *file, FILE *fp, DdNode ***pproots); +extern DdNode * Dddmp_cuddAddLoad(DdManager *ddMgr, Dddmp_VarMatchType varMatchMode, char **varmatchnames, int *varmatchauxids, int *varcomposeids, int mode, char *file, FILE *fp); +extern int Dddmp_cuddAddArrayLoad(DdManager *ddMgr, Dddmp_RootMatchType rootMatchMode, char **rootmatchnames, Dddmp_VarMatchType varMatchMode, char **varmatchnames, int *varmatchauxids, int *varcomposeids, int mode, char *file, FILE *fp, DdNode ***pproots); +extern int Dddmp_cuddHeaderLoad (Dddmp_DecompType *ddType, int *nVars, int *nsuppvars, char ***suppVarNames, char ***orderedVarNames, int **varIds, int **composeIds, int **auxIds, int *nRoots, char *file, FILE *fp); +extern int Dddmp_cuddBddLoadCnf(DdManager *ddMgr, Dddmp_VarMatchType varmatchmode, char **varmatchnames, int *varmatchauxids, int *varcomposeids, int mode, char *file, FILE *fp, DdNode ***rootsPtrPtr, int *nRoots); +extern int Dddmp_cuddBddArrayLoadCnf(DdManager *ddMgr, Dddmp_RootMatchType rootmatchmode, char **rootmatchnames, Dddmp_VarMatchType varmatchmode, char **varmatchnames, int *varmatchauxids, int *varcomposeids, int mode, char *file, FILE *fp, DdNode ***rootsPtrPtr, int *nRoots); +extern int Dddmp_cuddHeaderLoadCnf (int *nVars, int *nsuppvars, char ***suppVarNames, char ***orderedVarNames, int **varIds, int **composeIds, int **auxIds, int *nRoots, char *file, FILE *fp); +extern int Dddmp_cuddAddStore(DdManager *ddMgr, char *ddname, DdNode *f, char **varnames, int *auxids, int mode, Dddmp_VarInfoType varinfo, char *fname, FILE *fp); +extern int Dddmp_cuddAddArrayStore(DdManager *ddMgr, char *ddname, int nRoots, DdNode **f, char **rootnames, char **varnames, int *auxids, int mode, Dddmp_VarInfoType varinfo, char *fname, FILE *fp); +extern int Dddmp_cuddBddStore(DdManager *ddMgr, char *ddname, DdNode *f, char **varnames, int *auxids, int mode, Dddmp_VarInfoType varinfo, char *fname, FILE *fp); +extern int Dddmp_cuddBddArrayStore(DdManager *ddMgr, char *ddname, int nRoots, DdNode **f, char **rootnames, char **varnames, int *auxids, int mode, Dddmp_VarInfoType varinfo, char *fname, FILE *fp); +extern int Dddmp_cuddBddStoreCnf(DdManager *ddMgr, DdNode *f, Dddmp_DecompCnfStoreType mode, int noHeader, char **varNames, int *bddIds, int *bddAuxIds, int *cnfIds, int idInitial, int edgeInTh, int pathLengthTh, char *fname, FILE *fp, int *clauseNPtr, int *varNewNPtr); +extern int Dddmp_cuddBddArrayStoreCnf(DdManager *ddMgr, DdNode **f, int rootN, Dddmp_DecompCnfStoreType mode, int noHeader, char **varNames, int *bddIds, int *bddAuxIds, int *cnfIds, int idInitial, int edgeInTh, int pathLengthTh, char *fname, FILE *fp, int *clauseNPtr, int *varNewNPtr); +extern int Dddmp_cuddBddStorePrefix(DdManager *ddMgr, int nRoots, DdNode *f, char **inputNames, char **outputNames, char *modelName, char *fileName, FILE *fp); +extern int Dddmp_cuddBddArrayStorePrefix(DdManager *ddMgr, int nroots, DdNode **f, char **inputNames, char **outputNames, char *modelName, char *fname, FILE *fp); +extern int Dddmp_cuddBddStoreBlif(DdManager *ddMgr, int nRoots, DdNode *f, char **inputNames, char **outputNames, char *modelName, char *fileName, FILE *fp); +extern int Dddmp_cuddBddArrayStoreBlif(DdManager *ddMgr, int nroots, DdNode **f, char **inputNames, char **outputNames, char *modelName, char *fname, FILE *fp); +extern int Dddmp_cuddBddStoreSmv(DdManager *ddMgr, int nRoots, DdNode *f, char **inputNames, char **outputNames, char *modelName, char *fileName, FILE *fp); +extern int Dddmp_cuddBddArrayStoreSmv(DdManager *ddMgr, int nroots, DdNode **f, char **inputNames, char **outputNames, char *modelName, char *fname, FILE *fp); + +/**AutomaticEnd***************************************************************/ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/distr/dddmp/dddmpBinary.c b/distr/dddmp/dddmpBinary.c new file mode 100644 index 0000000..a7cd674 --- /dev/null +++ b/distr/dddmp/dddmpBinary.c @@ -0,0 +1,343 @@ +/**CFile********************************************************************** + + FileName [dddmpBinary.c] + + PackageName [dddmp] + + Synopsis [Input and output BDD codes and integers from/to file] + + Description [Input and output BDD codes and integers from/to file + in binary mode. + DD node codes are written as one byte. + Integers of any length are written as sequences of "linked" bytes. + For each byte 7 bits are used for data and one (MSBit) as link with + a further byte (MSB = 1 means one more byte). + Low level read/write of bytes filter , and + with escape sequences. + ] + + Author [Gianpiero Cabodi and Stefano Quer] + + Copyright [ + Copyright (c) 2004 by Politecnico di Torino. + All Rights Reserved. This software is for educational purposes only. + Permission is given to academic institutions to use, copy, and modify + this software and its documentation provided that this introductory + message is not removed, that this software and its documentation is + used for the institutions' internal research and educational purposes, + and that no monies are exchanged. No guarantee is expressed or implied + by the distribution of this code. + Send bug-reports and/or questions to: + {gianpiero.cabodi,stefano.quer}@polito.it. + ] + +******************************************************************************/ + +#include "dddmpInt.h" + +/*---------------------------------------------------------------------------*/ +/* Stucture declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Type declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Variable declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Macro declarations */ +/*---------------------------------------------------------------------------*/ + +/**AutomaticStart*************************************************************/ + +/*---------------------------------------------------------------------------*/ +/* Static function prototypes */ +/*---------------------------------------------------------------------------*/ + +static int WriteByteBinary(FILE *fp, unsigned char c); +static int ReadByteBinary(FILE *fp, unsigned char *cp); + +/**AutomaticEnd***************************************************************/ + + +/*---------------------------------------------------------------------------*/ +/* Definition of exported functions */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Definition of internal functions */ +/*---------------------------------------------------------------------------*/ + +/**Function******************************************************************** + + Synopsis [Writes 1 byte node code] + + Description [outputs a 1 byte node code using the following format: +
          +     Unused      : 1 bit;
          +     V           : 2 bits;     (variable code)
          +     T           : 2 bits;     (Then code)
          +     Ecompl      : 1 bit;      (Else complemented)
          +     E           : 2 bits;     (Else code)
          +    
          + Ecompl is set with complemented edges. + ] + + SideEffects [None] + + SeeAlso [DddmpReadCode()] + +******************************************************************************/ + +int +DddmpWriteCode ( + FILE *fp /* IN: file where to write the code */, + struct binary_dd_code code /* IN: the code to be written */ + ) +{ + unsigned char c; + int retValue; + + c = (code.Unused<<7)|(code.V<<5)|(code.T<<3)| + (code.Ecompl<<2)|(code.E); + + retValue = WriteByteBinary (fp, c); + + return (retValue); +} + +/**Function******************************************************************** + + Synopsis [Reads a 1 byte node code] + + Description [Reads a 1 byte node code. See DddmpWriteCode() + for code description.] + + SideEffects [None] + + SeeAlso [DddmpWriteCode()] + +******************************************************************************/ + +int +DddmpReadCode ( + FILE *fp /* IN: file where to read the code */, + struct binary_dd_code *pcode /* OUT: the read code */ + ) +{ + unsigned char c; + + if (ReadByteBinary (fp, &c) == EOF) { + return (0); + } + + pcode->Unused = c>>7; + pcode->V = (c>>5) & 3; + pcode->T = (c>>3) & 3; + pcode->Ecompl = (c>>2) & 1; + pcode->E = c & 3; + + return (1); +} + +/**Function******************************************************************** + + Synopsis [Writes a "packed integer"] + + Description [Writes an integer as a sequence of bytes (MSByte first). + For each byte 7 bits are used for data and one (LSBit) as link + with a further byte (LSB = 1 means one more byte). + ] + + SideEffects [None] + + SeeAlso [DddmpReadInt()] + +******************************************************************************/ + +int +DddmpWriteInt ( + FILE *fp /* IN: file where to write the integer */, + int id /* IN: integer to be written */ + ) +{ + char cvet[4]; + int i; + + for (i=0; i<4; i++) { + cvet[i] = (char)((id & 0x0000007f) << 1); + id >>= 7; + } + + for (i=3; (i>0) && (cvet[i] == 0); i--); + + for (; i>0; i--) { + cvet[i] |= (char)1; + if (WriteByteBinary (fp, cvet[i]) == EOF) + return (0); + } + + if (WriteByteBinary (fp, cvet[0]) == EOF) { + return (0); + } + + return (1); +} + + +/**Function******************************************************************** + + Synopsis [Reads a "packed integer"] + + Description [Reads an integer coded on a sequence of bytes. See + DddmpWriteInt() for format.] + + SideEffects [None] + + SeeAlso [DddmpWriteInt()] + +******************************************************************************/ + +int +DddmpReadInt ( + FILE *fp /* IN: file where to read the integer */, + int *pid /* OUT: the read integer */ + ) +{ + unsigned char c; + int i; + unsigned int id; + + id = 0; + for (i=0; i<4; i++) { + if (ReadByteBinary (fp, &c) == EOF) + return (0); + id = (id<<7) | (c>>1); + if ((c & 1) == 0) + break; + } + + /* Check for correct format: last char should + be found before i = 4 */ + assert(i<4); + + *pid = id; + + return (i+1); +} + +/*---------------------------------------------------------------------------*/ +/* Definition of static functions */ +/*---------------------------------------------------------------------------*/ + +/**Function******************************************************************** + + Synopsis [Writes a byte to file filtering , and ] + + Description [outputs a byte to file fp. Uses 0x00 as escape character + to filter , and . + This is done for compatibility between unix and dos/windows systems. + ] + + SideEffects [None] + + SeeAlso [ReadByteBinary()] + +******************************************************************************/ + +static int +WriteByteBinary ( + FILE *fp /* IN: file where to write the byte */, + unsigned char c /* IN: the byte to be written */ + ) +{ + unsigned char BinaryEscape; + + switch (c) { + + case 0x00: /* Escape */ + BinaryEscape = 0x00; + if (fwrite (&BinaryEscape, sizeof(char), 1, fp) != sizeof(char)) + return (0); + c = 0x00; + break; + case 0x0a: /* */ + BinaryEscape = 0x00; + if (fwrite (&BinaryEscape, sizeof(char), 1, fp) != sizeof(char)) + return (0); + c = 0x01; + break; + case 0x0d: /* */ + BinaryEscape = 0x00; + if (fwrite (&BinaryEscape, sizeof(char), 1, fp) != sizeof(char)) + return (0); + c = 0x02; + break; + case 0x1a: /* */ + BinaryEscape = 0x00; + if (fwrite (&BinaryEscape, sizeof(char), 1, fp) != sizeof(char)) + return (0); + c = 0x03; + break; + } + if (fwrite (&c, sizeof(char), 1, fp) != sizeof(char)) + return (0); + + return (1); +} + +/**Function******************************************************************** + + Synopsis [Reads a byte from file with escaped , and ] + + Description [inputs a byte to file fp. 0x00 has been used as escape character + to filter , and . This is done for + compatibility between unix and dos/windows systems. + ] + + SideEffects [None] + + SeeAlso [WriteByteBinary()] + +******************************************************************************/ + +static int +ReadByteBinary ( + FILE *fp /* IN: file where to read the byte */, + unsigned char *cp /* OUT: the read byte */ + ) +{ + + if (fread (cp, sizeof(char), 1, fp) != sizeof(char)) { + return (0); + } + + if (*cp == 0x00) { /* Escape */ + if (fread (cp, sizeof(char), 1, fp) != sizeof(char)) { + return (0); + } + + switch (*cp) { + + case 0x00: /* Escape */ + break; + case 0x01: /* */ + *cp = 0x0a; + break; + case 0x02: /* */ + *cp = 0x0d; + break; + case 0x03: /* */ + *cp = 0x1a; + break; + } + } + + return (1); +} + + diff --git a/distr/dddmp/dddmpConvert.c b/distr/dddmp/dddmpConvert.c new file mode 100644 index 0000000..c24292e --- /dev/null +++ b/distr/dddmp/dddmpConvert.c @@ -0,0 +1,180 @@ +/**CFile********************************************************************** + + FileName [dddmpConvert.c] + + PackageName [dddmp] + + Synopsis [Conversion between ASCII and binary formats] + + Description [Conversion between ASCII and binary formats is presently + supported by loading a BDD in the source format and storing it + in the target one. We plan to introduce ad hoc procedures + avoiding explicit BDD node generation. + ] + + Author [Gianpiero Cabodi and Stefano Quer] + + Copyright [ + Copyright (c) 2004 by Politecnico di Torino. + All Rights Reserved. This software is for educational purposes only. + Permission is given to academic institutions to use, copy, and modify + this software and its documentation provided that this introductory + message is not removed, that this software and its documentation is + used for the institutions' internal research and educational purposes, + and that no monies are exchanged. No guarantee is expressed or implied + by the distribution of this code. + Send bug-reports and/or questions to: + {gianpiero.cabodi,stefano.quer}@polito.it. + ] + +******************************************************************************/ + +#include "dddmpInt.h" + +/*---------------------------------------------------------------------------*/ +/* Stucture declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Type declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Variable declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Macro declarations */ +/*---------------------------------------------------------------------------*/ + +/**AutomaticStart*************************************************************/ + +/*---------------------------------------------------------------------------*/ +/* Static function prototypes */ +/*---------------------------------------------------------------------------*/ + + +/**AutomaticEnd***************************************************************/ + + +/*---------------------------------------------------------------------------*/ +/* Definition of exported functions */ +/*---------------------------------------------------------------------------*/ + +/**Function******************************************************************** + + Synopsis [Converts from ASCII to binary format] + + Description [Converts from ASCII to binary format. A BDD array is loaded and + and stored to the target file.] + + SideEffects [None] + + SeeAlso [Dddmp_Bin2Text()] + +******************************************************************************/ + +int +Dddmp_Text2Bin ( + char *filein /* IN: name of ASCII file */, + char *fileout /* IN: name of binary file */ + ) +{ + DdManager *ddMgr; /* pointer to DD manager */ + DdNode **roots; /* array of BDD roots to be loaded */ + int nRoots; /* number of BDD roots */ + int retValue; + + ddMgr = Cudd_Init(0,0,CUDD_UNIQUE_SLOTS,CUDD_CACHE_SLOTS,0); + if (ddMgr == NULL) { + return (0); + } + + nRoots = Dddmp_cuddBddArrayLoad(ddMgr,DDDMP_ROOT_MATCHLIST,NULL, + DDDMP_VAR_MATCHIDS,NULL,NULL,NULL, + DDDMP_MODE_TEXT,filein,NULL,&roots); + + Dddmp_CheckAndGotoLabel (nRoots<=0, + "Negative Number of Roots.", failure); + + retValue = Dddmp_cuddBddArrayStore (ddMgr,NULL,nRoots,roots,NULL, + NULL,NULL,DDDMP_MODE_BINARY,DDDMP_VARIDS,fileout,NULL); + + Dddmp_CheckAndGotoLabel (retValue<=0, + "Error code returned.", failure); + + Cudd_Quit(ddMgr); + return (1); + + failure: + printf("error converting BDD format\n"); + Cudd_Quit(ddMgr); + return (0); +} + +/**Function******************************************************************** + + Synopsis [Converts from binary to ASCII format] + + Description [Converts from binary to ASCII format. A BDD array is loaded and + and stored to the target file.] + + SideEffects [None] + + SeeAlso [Dddmp_Text2Bin()] + +******************************************************************************/ + +int +Dddmp_Bin2Text ( + char *filein /* IN: name of binary file */, + char *fileout /* IN: name of ASCII file */ + ) +{ + DdManager *ddMgr; /* pointer to DD manager */ + DdNode **roots; /* array of BDD roots to be loaded */ + int nRoots; /* number of BDD roots */ + int retValue; + + ddMgr = Cudd_Init(0,0,CUDD_UNIQUE_SLOTS,CUDD_CACHE_SLOTS,0); + if (ddMgr == NULL) { + return (0); + } + + nRoots = Dddmp_cuddBddArrayLoad(ddMgr,DDDMP_ROOT_MATCHLIST,NULL, + DDDMP_VAR_MATCHIDS,NULL,NULL,NULL, + DDDMP_MODE_BINARY,filein,NULL,&roots); + + Dddmp_CheckAndGotoLabel (nRoots<=0, + "Negative Number of Roots.", failure); + + retValue = Dddmp_cuddBddArrayStore (ddMgr,NULL,nRoots,roots,NULL, + NULL,NULL,DDDMP_MODE_TEXT,DDDMP_VARIDS,fileout,NULL); + + Dddmp_CheckAndGotoLabel (retValue<=0, + "Error code returned.", failure); + + Cudd_Quit(ddMgr); + return (1); + + failure: + printf("error converting BDD format\n"); + Cudd_Quit(ddMgr); + return (0); +} + +/*---------------------------------------------------------------------------*/ +/* Definition of internal functions */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Definition of static functions */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Static function prototypes */ +/*---------------------------------------------------------------------------*/ + + diff --git a/distr/dddmp/dddmpDbg.c b/distr/dddmp/dddmpDbg.c new file mode 100644 index 0000000..88304f5 --- /dev/null +++ b/distr/dddmp/dddmpDbg.c @@ -0,0 +1,166 @@ +/**CFile********************************************************************** + + FileName [dddmpDbg.c] + + PackageName [dddmp] + + Synopsis [Functions to display BDD files] + + Description [Functions to display BDD files in binary format + ] + + Author [Gianpiero Cabodi and Stefano Quer] + + Copyright [ + Copyright (c) 2004 by Politecnico di Torino. + All Rights Reserved. This software is for educational purposes only. + Permission is given to academic institutions to use, copy, and modify + this software and its documentation provided that this introductory + message is not removed, that this software and its documentation is + used for the institutions' internal research and educational purposes, + and that no monies are exchanged. No guarantee is expressed or implied + by the distribution of this code. + Send bug-reports and/or questions to: + {gianpiero.cabodi,stefano.quer}@polito.it. + ] + +******************************************************************************/ + +#include "dddmpInt.h" + +/*---------------------------------------------------------------------------*/ +/* Stucture declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Type declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Variable declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Macro declarations */ +/*---------------------------------------------------------------------------*/ + + +/**AutomaticStart*************************************************************/ + +/*---------------------------------------------------------------------------*/ +/* Static function prototypes */ +/*---------------------------------------------------------------------------*/ + + +/**AutomaticEnd***************************************************************/ + + +/*---------------------------------------------------------------------------*/ +/* Definition of exported functions */ +/*---------------------------------------------------------------------------*/ + + +/**Function******************************************************************** + + Synopsis [Display a binary dump file in a text file] + + Description [Display a binary dump file in a text file] + + SideEffects [None] + + SeeAlso [Dddmp_cuddBddStore , Dddmp_cuddBddLoad ] + +******************************************************************************/ + +int +Dddmp_cuddBddDisplayBinary( + char *fileIn /* IN: name of binary file */, + char *fileOut /* IN: name of text file */ + ) +{ + FILE *fp, *fpo; + int id, size; + struct binary_dd_code code; + char buf[1000]; + int nnodes, i; + + fp = fopen (fileIn, "rb"); + if (fp == 0) { + return (0); + } + + fpo = fopen (fileOut, "w"); + if (fpo == 0) { + return (0); + } + + while (fgets(buf, 999,fp)!=NULL) { + fprintf (fpo, "%s", buf); + if (strncmp(buf, ".nnodes", 7) == 0) { + sscanf (buf, "%*s %d", &nnodes); + } + if (strncmp(buf, ".rootids", 8) == 0) { + break; + } + } + + for (i=1; i<=nnodes; i++) { + if (feof(fp)) { + return (0); + } + if (DddmpReadCode(fp,&code) == 0) { + return (0); + } + fprintf (fpo, "c : v %d | T %d | E %d\n", + (int)code.V, (int)code.T, + (code.Ecompl ? -(int)(code.E) : (int)(code.E))); + if (code.V == DDDMP_TERMINAL) { + continue; + } + if (code.V <= DDDMP_RELATIVE_ID) { + size = DddmpReadInt(fp,&id); + if (size == 0) { + return (0); + } + fprintf(fpo, "v(%d): %d\n", size, id); + } + if (code.T <= DDDMP_RELATIVE_ID) { + size = DddmpReadInt(fp,&id); + if (size == 0) { + return (0); + } + fprintf(fpo, "T(%d): %d\n", size, id); + } + if (code.E <= DDDMP_RELATIVE_ID) { + size = DddmpReadInt(fp,&id); + if (size == 0) { + return (0); + } + fprintf(fpo, "E(%d): %d\n", size, id); + } + + } + + fgets(buf, 999,fp); + if (strncmp(buf, ".end", 4) != 0) { + return (0); + } + + fprintf(fpo, ".end"); + + fclose(fp); + fclose(fpo); + + return (1); +} + + +/*---------------------------------------------------------------------------*/ +/* Definition of internal functions */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Definition of static functions */ +/*---------------------------------------------------------------------------*/ + + diff --git a/distr/dddmp/dddmpDdNodeBdd.c b/distr/dddmp/dddmpDdNodeBdd.c new file mode 100644 index 0000000..443ef5d --- /dev/null +++ b/distr/dddmp/dddmpDdNodeBdd.c @@ -0,0 +1,455 @@ +/**CFile********************************************************************** + + FileName [dddmpDdNodeBdd.c] + + PackageName [dddmp] + + Synopsis [Functions to handle BDD node infos and numbering] + + Description [Functions to handle BDD node infos and numbering. + ] + + Author [Gianpiero Cabodi and Stefano Quer] + + Copyright [ + Copyright (c) 2004 by Politecnico di Torino. + All Rights Reserved. This software is for educational purposes only. + Permission is given to academic institutions to use, copy, and modify + this software and its documentation provided that this introductory + message is not removed, that this software and its documentation is + used for the institutions' internal research and educational purposes, + and that no monies are exchanged. No guarantee is expressed or implied + by the distribution of this code. + Send bug-reports and/or questions to: + {gianpiero.cabodi,stefano.quer}@polito.it. + ] + +******************************************************************************/ + +#include "dddmpInt.h" + +/*---------------------------------------------------------------------------*/ +/* Stucture declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Type declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Variable declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Macro declarations */ +/*---------------------------------------------------------------------------*/ + +/**AutomaticStart*************************************************************/ + +/*---------------------------------------------------------------------------*/ +/* Static function prototypes */ +/*---------------------------------------------------------------------------*/ + +static int NumberNodeRecur(DdNode *f, int id); +static void RemoveFromUniqueRecur(DdManager *ddMgr, DdNode *f); +static void RestoreInUniqueRecur(DdManager *ddMgr, DdNode *f); + +/**AutomaticEnd***************************************************************/ + +/*---------------------------------------------------------------------------*/ +/* Definition of exported functions */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Definition of internal functions */ +/*---------------------------------------------------------------------------*/ + +/**Function******************************************************************** + + Synopsis [Removes nodes from unique table and number them] + + Description [Node numbering is required to convert pointers to integers. + Since nodes are removed from unique table, no new nodes should + be generated before re-inserting nodes in the unique table + (DddmpUnnumberDdNodes()). + ] + + SideEffects [Nodes are temporarily removed from unique table] + + SeeAlso [RemoveFromUniqueRecur(), NumberNodeRecur(), + DddmpUnnumberDdNodes()] + +******************************************************************************/ + +int +DddmpNumberDdNodes ( + DdManager *ddMgr /* IN: DD Manager */, + DdNode **f /* IN: array of BDDs */, + int n /* IN: number of BDD roots in the array of BDDs */ + ) +{ + int id=0, i; + + for (i=0; inext = (struct DdNode *)((ptruint)((id)<<1)); + } + + return; +} + +/**Function******************************************************************** + + Synopsis [Reads the index of a node] + + Description [Reads the index of a node. LSB is skipped (used as visited + flag). + ] + + SideEffects [None] + + SeeAlso [DddmpWriteNodeIndex(), DddmpSetVisited (), DddmpVisited ()] + +******************************************************************************/ + +int +DddmpReadNodeIndex ( + DdNode *f /* IN: BDD node */ + ) +{ + +#if 0 + if (1 || !Cudd_IsConstant (f)) { +#else + if (!Cudd_IsConstant (f)) { +#endif + return ((int)(((ptruint)(f->next))>>1)); + } else { + return (1); + } +} + +/**Function******************************************************************** + + Synopsis [Returns true if node is visited] + + Description [Returns true if node is visited] + + SideEffects [None] + + SeeAlso [DddmpSetVisited (), DddmpClearVisited ()] + +******************************************************************************/ + +int +DddmpVisited ( + DdNode *f /* IN: BDD node to be tested */ + ) +{ + f = Cudd_Regular(f); + return ((int)((ptruint)(f->next)) & (01)); +} + +/**Function******************************************************************** + + Synopsis [Marks a node as visited] + + Description [Marks a node as visited] + + SideEffects [None] + + SeeAlso [DddmpVisited (), DddmpClearVisited ()] + +******************************************************************************/ + +void +DddmpSetVisited ( + DdNode *f /* IN: BDD node to be marked (as visited) */ + ) +{ + f = Cudd_Regular(f); + + f->next = (DdNode *)(ptruint)((int)((ptruint)(f->next))|01); + + return; +} + +/**Function******************************************************************** + + Synopsis [Marks a node as not visited] + + Description [Marks a node as not visited] + + SideEffects [None] + + SeeAlso [DddmpVisited (), DddmpSetVisited ()] + +******************************************************************************/ + +void +DddmpClearVisited ( + DdNode *f /* IN: BDD node to be marked (as not visited) */ + ) +{ + f = Cudd_Regular (f); + + f->next = (DdNode *)(ptruint)((int)((ptruint)(f->next)) & (~01)); + + return; +} + +/*---------------------------------------------------------------------------*/ +/* Definition of static functions */ +/*---------------------------------------------------------------------------*/ + +/**Function******************************************************************** + + Synopsis [Number nodes recursively in post-order] + + Description [Number nodes recursively in post-order. + The "visited" flag is used with inverse polarity, because all nodes + were set "visited" when removing them from unique. + ] + + SideEffects ["visited" flags are reset.] + + SeeAlso [] + +******************************************************************************/ + +static int +NumberNodeRecur( + DdNode *f /* IN: root of the BDD to be numbered */, + int id /* IN/OUT: index to be assigned to the node */ + ) +{ + f = Cudd_Regular(f); + + if (!DddmpVisited (f)) { + return (id); + } + + if (!cuddIsConstant (f)) { + id = NumberNodeRecur (cuddT (f), id); + id = NumberNodeRecur (cuddE (f), id); + } + + DddmpWriteNodeIndex (f, ++id); + DddmpClearVisited (f); + + return (id); +} + +/**Function******************************************************************** + + Synopsis [Removes a node from unique table] + + Description [Removes a node from the unique table by locating the proper + subtable and unlinking the node from it. It recurs on the + children of the node. + ] + + SideEffects [Nodes are left with the "visited" flag true.] + + SeeAlso [RestoreInUniqueRecur()] + +******************************************************************************/ + +static void +RemoveFromUniqueRecur ( + DdManager *ddMgr /* IN: DD Manager */, + DdNode *f /* IN: root of the BDD to be extracted */ + ) +{ + DdNode *node, *last, *next; + DdNode *sentinel = &(ddMgr->sentinel); + DdNodePtr *nodelist; + DdSubtable *subtable; + int pos, level; + + f = Cudd_Regular (f); + + if (DddmpVisited (f)) { + return; + } + + if (!cuddIsConstant (f)) { + + RemoveFromUniqueRecur (ddMgr, cuddT (f)); + RemoveFromUniqueRecur (ddMgr, cuddE (f)); + + level = ddMgr->perm[f->index]; + subtable = &(ddMgr->subtables[level]); + + nodelist = subtable->nodelist; + + pos = ddHash (cuddT (f), cuddE (f), subtable->shift); + node = nodelist[pos]; + last = NULL; + while (node != sentinel) { + next = node->next; + if (node == f) { + if (last != NULL) + last->next = next; + else + nodelist[pos] = next; + break; + } else { + last = node; + node = next; + } + } + + f->next = NULL; + + } + + DddmpSetVisited (f); + + return; +} + +/**Function******************************************************************** + + Synopsis [Restores a node in unique table] + + Description [Restores a node in unique table (recursively)] + + SideEffects [Nodes are not restored in the same order as before removal] + + SeeAlso [RemoveFromUnique()] + +******************************************************************************/ + +static void +RestoreInUniqueRecur ( + DdManager *ddMgr /* IN: DD Manager */, + DdNode *f /* IN: root of the BDD to be restored */ + ) +{ + DdNodePtr *nodelist; + DdNode *T, *E, *looking; + DdNodePtr *previousP; + DdSubtable *subtable; + int pos, level; +#ifdef DDDMP_DEBUG + DdNode *node; + DdNode *sentinel = &(ddMgr->sentinel); +#endif + + f = Cudd_Regular(f); + + if (!Cudd_IsComplement (f->next)) { + return; + } + + if (cuddIsConstant (f)) { + DddmpClearVisited (f); + /*f->next = NULL;*/ + return; + } + + RestoreInUniqueRecur (ddMgr, cuddT (f)); + RestoreInUniqueRecur (ddMgr, cuddE (f)); + + level = ddMgr->perm[f->index]; + subtable = &(ddMgr->subtables[level]); + + nodelist = subtable->nodelist; + + pos = ddHash (cuddT (f), cuddE (f), subtable->shift); + +#ifdef DDDMP_DEBUG + /* verify uniqueness to avoid duplicate nodes in unique table */ + for (node=nodelist[pos]; node != sentinel; node=node->next) + assert(node!=f); +#endif + + T = cuddT (f); + E = cuddE (f); + previousP = &(nodelist[pos]); + looking = *previousP; + + while (T < cuddT (looking)) { + previousP = &(looking->next); + looking = *previousP; + } + + while (T == cuddT (looking) && E < cuddE (looking)) { + previousP = &(looking->next); + looking = *previousP; + } + + f->next = *previousP; + *previousP = f; + + return; +} + + diff --git a/distr/dddmp/dddmpDdNodeCnf.c b/distr/dddmp/dddmpDdNodeCnf.c new file mode 100644 index 0000000..421d920 --- /dev/null +++ b/distr/dddmp/dddmpDdNodeCnf.c @@ -0,0 +1,944 @@ +/**CFile********************************************************************** + + FileName [dddmpDdNodeCnf.c] + + PackageName [dddmp] + + Synopsis [Functions to handle BDD node infos and numbering + while storing a CNF formula from a BDD or an array of BDDs] + + Description [Functions to handle BDD node infos and numbering + while storing a CNF formula from a BDD or an array of BDDs. + ] + + Author [Gianpiero Cabodi and Stefano Quer] + + Copyright [ + Copyright (c) 2004 by Politecnico di Torino. + All Rights Reserved. This software is for educational purposes only. + Permission is given to academic institutions to use, copy, and modify + this software and its documentation provided that this introductory + message is not removed, that this software and its documentation is + used for the institutions' internal research and educational purposes, + and that no monies are exchanged. No guarantee is expressed or implied + by the distribution of this code. + Send bug-reports and/or questions to: + {gianpiero.cabodi,stefano.quer}@polito.it. + ] + +******************************************************************************/ + +#include "dddmpInt.h" + +/*---------------------------------------------------------------------------*/ +/* Stucture declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Type declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Variable declarations */ +/*---------------------------------------------------------------------------*/ + +#define DDDMP_DEBUG_CNF 0 + +/*---------------------------------------------------------------------------*/ +/* Macro declarations */ +/*---------------------------------------------------------------------------*/ + +/**AutomaticStart*************************************************************/ + +/*---------------------------------------------------------------------------*/ +/* Static function prototypes */ +/*---------------------------------------------------------------------------*/ + +static int DddmpWriteNodeIndexCnf(DdNode *f, int *cnfIds, int id); +static int DddmpReadNodeIndexCnf(DdNode *f); +static int DddmpClearVisitedCnfRecur(DdNode *f); +static int DddmpVisitedCnf(DdNode *f); +static void DddmpSetVisitedCnf(DdNode *f); +static void DddmpClearVisitedCnf(DdNode *f); +static int NumberNodeRecurCnf(DdNode *f, int *cnfIds, int id); +static void DddmpDdNodesCheckIncomingAndScanPath(DdNode *f, int pathLengthCurrent, int edgeInTh, int pathLengthTh); +static int DddmpDdNodesNumberEdgesRecur(DdNode *f, int *cnfIds, int id); +static int DddmpDdNodesResetCountRecur(DdNode *f); +static int DddmpDdNodesCountEdgesRecur(DdNode *f); +static void RemoveFromUniqueRecurCnf(DdManager *ddMgr, DdNode *f); +static void RestoreInUniqueRecurCnf(DdManager *ddMgr, DdNode *f); +static int DddmpPrintBddAndNextRecur(DdManager *ddMgr, DdNode *f); + +/**AutomaticEnd***************************************************************/ + +/*---------------------------------------------------------------------------*/ +/* Definition of exported functions */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Definition of internal functions */ +/*---------------------------------------------------------------------------*/ + +/**Function******************************************************************** + + Synopsis [Removes nodes from unique table and numbers them] + + Description [Node numbering is required to convert pointers to integers. + Since nodes are removed from unique table, no new nodes should + be generated before re-inserting nodes in the unique table + (DddmpUnnumberDdNodesCnf()). + ] + + SideEffects [Nodes are temporarily removed from unique table] + + SeeAlso [RemoveFromUniqueRecurCnf(), NumberNodeRecurCnf(), + DddmpUnnumberDdNodesCnf()] + +******************************************************************************/ + +int +DddmpNumberDdNodesCnf ( + DdManager *ddMgr /* IN: DD Manager */, + DdNode **f /* IN: array of BDDs */, + int rootN /* IN: number of BDD roots in the array of BDDs */, + int *cnfIds /* OUT: CNF identifiers for variables */, + int id /* OUT: number of Temporary Variables Introduced */ + ) +{ + int i; + + for (i=0; i BDDs After Count Reset:\n"); + DddmpPrintBddAndNext (ddMgr, f, rootN); +#endif + + /*----------------------- Count Incoming Edges ----------------------------*/ + + for (i=0; i BDDs After Count Recur:\n"); + DddmpPrintBddAndNext (ddMgr, f, rootN); +#endif + + /*------------------------- Count Path Length ----------------------------*/ + + for (i=0; i BDDs After Check Incoming And Scan Path:\n"); + DddmpPrintBddAndNext (ddMgr, f, rootN); +#endif + + /*-------------------- Number Nodes and Set Visited -----------------------*/ + + for (i=0; i BDDs After Count Edges Recur:\n"); + DddmpPrintBddAndNext (ddMgr, f, rootN); +#endif + + /*---------------------------- Clear Visited ------------------------------*/ + +#if DDDMP_DEBUG_CNF + for (i=0; i BDDs After All Numbering Process:\n"); + DddmpPrintBddAndNext (ddMgr, f, rootN); +#endif +#endif + + return (id); +} + +/**Function******************************************************************** + + Synopsis [Restores nodes in unique table, loosing numbering] + + Description [Node indexes are no more needed. Nodes are re-linked in the + unique table. + ] + + SideEffects [None] + + SeeAlso [DddmpNumberDdNode()] + +******************************************************************************/ + +void +DddmpUnnumberDdNodesCnf( + DdManager *ddMgr /* IN: DD Manager */, + DdNode **f /* IN: array of BDDs */, + int rootN /* IN: number of BDD roots in the array of BDDs */ + ) +{ + int i; + + for (i=0; i Bdd %d:\n", i); + fflush (stdout); + DddmpPrintBddAndNextRecur (ddMgr, f[i]); + } + + return (DDDMP_SUCCESS); +} + +/**Function******************************************************************** + + Synopsis [Write index to node] + + Description [The index of the node is written in the "next" field of + a DdNode struct. LSB is not used (set to 0). It is used as + "visited" flag in DD traversals. + ] + + SideEffects [None] + + SeeAlso [DddmpReadNodeIndexCnf(), DddmpSetVisitedCnf (), + DddmpVisitedCnf () + ] + +******************************************************************************/ + +int +DddmpWriteNodeIndexCnfBis ( + DdNode *f /* IN: BDD node */, + int id /* IN: index to be written */ + ) +{ + if (!Cudd_IsConstant (f)) { + f->next = (struct DdNode *)((ptruint)((id)<<1)); + } + + return (DDDMP_SUCCESS); +} + +/*---------------------------------------------------------------------------*/ +/* Definition of static functions */ +/*---------------------------------------------------------------------------*/ + +/**Function******************************************************************** + + Synopsis [Write index to node] + + Description [The index of the node is written in the "next" field of + a DdNode struct. LSB is not used (set to 0). It is used as + "visited" flag in DD traversals. The index corresponds to + the BDD node variable if both the node's children are a + constant node, otherwise a new CNF variable is used. + ] + + SideEffects [None] + + SeeAlso [DddmpReadNodeIndexCnf(), DddmpSetVisitedCnf (), + DddmpVisitedCnf ()] + +*****************************************************************************/ + +static int +DddmpWriteNodeIndexCnf ( + DdNode *f /* IN: BDD node */, + int *cnfIds /* IN: possible source for the index to be written */, + int id /* IN: possible source for the index to be written */ + ) +{ + if (!Cudd_IsConstant (f)) { + if (Cudd_IsConstant (cuddT (f)) && Cudd_IsConstant (cuddE (f))) { + /* If Variable SET ID as Variable ID */ + f->next = (struct DdNode *)((ptruint)((cnfIds[f->index])<<1)); + } else { + f->next = (struct DdNode *)((ptruint)((id)<<1)); + id++; + } + } + + return(id); +} + +/**Function******************************************************************** + + Synopsis [Reads the index of a node] + + Description [Reads the index of a node. LSB is skipped (used as visited + flag). + ] + + SideEffects [None] + + SeeAlso [DddmpWriteNodeIndexCnf(), DddmpSetVisitedCnf (), + DddmpVisitedCnf ()] + +******************************************************************************/ + +static int +DddmpReadNodeIndexCnf ( + DdNode *f /* IN: BDD node */ + ) +{ + if (!Cudd_IsConstant (f)) { + return ((int)(((ptruint)(f->next))>>1)); + } else { + return (1); + } +} + +/**Function******************************************************************** + + Synopsis [Mark ALL nodes as not visited] + + Description [Mark ALL nodes as not visited (it recurs on the node children)] + + SideEffects [None] + + SeeAlso [DddmpVisitedCnf (), DddmpSetVisitedCnf ()] + +******************************************************************************/ + +static int +DddmpClearVisitedCnfRecur ( + DdNode *f /* IN: root of the BDD to be marked */ + ) +{ + int retValue; + + f = Cudd_Regular(f); + + if (cuddIsConstant (f)) { + return (DDDMP_SUCCESS); + } + + if (!DddmpVisitedCnf (f)) { + return (DDDMP_SUCCESS); + } + + retValue = DddmpClearVisitedCnfRecur (cuddT (f)); + retValue = DddmpClearVisitedCnfRecur (cuddE (f)); + + DddmpClearVisitedCnf (f); + + return (DDDMP_SUCCESS); +} + +/**Function******************************************************************** + + Synopsis [Returns true if node is visited] + + Description [Returns true if node is visited] + + SideEffects [None] + + SeeAlso [DddmpSetVisitedCnf (), DddmpClearVisitedCnf ()] + +******************************************************************************/ + +static int +DddmpVisitedCnf ( + DdNode *f /* IN: BDD node to be tested */ + ) +{ + f = Cudd_Regular(f); + + return ((int)((ptruint)(f->next)) & (01)); +} + +/**Function******************************************************************** + + Synopsis [Marks a node as visited] + + Description [Marks a node as visited] + + SideEffects [None] + + SeeAlso [DddmpVisitedCnf (), DddmpClearVisitedCnf ()] + +******************************************************************************/ + +static void +DddmpSetVisitedCnf ( + DdNode *f /* IN: BDD node to be marked (as visited) */ + ) +{ + f = Cudd_Regular(f); + + f->next = (DdNode *)(ptruint)((int)((ptruint)(f->next))|01); + + return; +} + +/**Function******************************************************************** + + Synopsis [Marks a node as not visited] + + Description [Marks a node as not visited] + + SideEffects [None] + + SeeAlso [DddmpVisitedCnf (), DddmpSetVisitedCnf ()] + +******************************************************************************/ + +static void +DddmpClearVisitedCnf ( + DdNode *f /* IN: BDD node to be marked (as not visited) */ + ) +{ + f = Cudd_Regular (f); + + f->next = (DdNode *)(ptruint)((int)((ptruint)(f->next)) & (~01)); + + return; +} + +/**Function******************************************************************** + + Synopsis [Number nodes recursively in post-order] + + Description [Number nodes recursively in post-order. + The "visited" flag is used with inverse polarity, because all nodes + were set "visited" when removing them from unique. + ] + + SideEffects ["visited" flags are reset.] + + SeeAlso [] + +******************************************************************************/ + +static int +NumberNodeRecurCnf( + DdNode *f /* IN: root of the BDD to be numbered */, + int *cnfIds /* IN: possible source for numbering */, + int id /* IN/OUT: possible source for numbering */ + ) +{ + f = Cudd_Regular(f); + + if (!DddmpVisitedCnf (f)) { + return (id); + } + + if (!cuddIsConstant (f)) { + id = NumberNodeRecurCnf (cuddT (f), cnfIds, id); + id = NumberNodeRecurCnf (cuddE (f), cnfIds, id); + } + + id = DddmpWriteNodeIndexCnf (f, cnfIds, id); + DddmpClearVisitedCnf (f); + + return (id); +} + +/**Function******************************************************************** + + Synopsis [Number nodes recursively in post-order] + + Description [Number nodes recursively in post-order. + The "visited" flag is used with the right polarity. + The node is assigned to a new CNF variable only if it is a "shared" + node (i.e. the number of its incoming edges is greater than 1). + ] + + SideEffects ["visited" flags are set.] + + SeeAlso [] + +******************************************************************************/ + +static void +DddmpDdNodesCheckIncomingAndScanPath ( + DdNode *f /* IN: BDD node to be numbered */, + int pathLengthCurrent /* IN: Current Path Length */, + int edgeInTh /* IN: Max # In-Edges, after a Insert Cut Point */, + int pathLengthTh /* IN: Max Path Length (after, Insert a Cut Point) */ + ) +{ + int retValue; + + f = Cudd_Regular(f); + + if (DddmpVisitedCnf (f)) { + return; + } + + if (cuddIsConstant (f)) { + return; + } + + pathLengthCurrent++; + retValue = DddmpReadNodeIndexCnf (f); + + if ( ((edgeInTh >= 0) && (retValue > edgeInTh)) || + ((pathLengthTh >= 0) && (pathLengthCurrent > pathLengthTh)) + ) { + DddmpWriteNodeIndexCnfBis (f, 1); + pathLengthCurrent = 0; + } else { + DddmpWriteNodeIndexCnfBis (f, 0); + } + + DddmpDdNodesCheckIncomingAndScanPath (cuddT (f), pathLengthCurrent, + edgeInTh, pathLengthTh); + DddmpDdNodesCheckIncomingAndScanPath (cuddE (f), pathLengthCurrent, + edgeInTh, pathLengthTh); + + DddmpSetVisitedCnf (f); + + return; +} + +/**Function******************************************************************** + + Synopsis [Number nodes recursively in post-order] + + Description [Number nodes recursively in post-order. + The "visited" flag is used with the inverse polarity. + Numbering follows the subsequent strategy: + * if the index = 0 it remains so + * if the index >= 1 it gets enumerated. + This implies that the node is assigned to a new CNF variable only if + it is not a terminal node otherwise it is assigned the index of + the BDD variable. + ] + + SideEffects ["visited" flags are reset.] + + SeeAlso [] + +******************************************************************************/ + +static int +DddmpDdNodesNumberEdgesRecur ( + DdNode *f /* IN: BDD node to be numbered */, + int *cnfIds /* IN: possible source for numbering */, + int id /* IN/OUT: possible source for numbering */ + ) +{ + int retValue; + + f = Cudd_Regular(f); + + if (!DddmpVisitedCnf (f)) { + return (id); + } + + if (cuddIsConstant (f)) { + return (id); + } + + id = DddmpDdNodesNumberEdgesRecur (cuddT (f), cnfIds, id); + id = DddmpDdNodesNumberEdgesRecur (cuddE (f), cnfIds, id); + + retValue = DddmpReadNodeIndexCnf (f); + if (retValue >= 1) { + id = DddmpWriteNodeIndexCnf (f, cnfIds, id); + } else { + DddmpWriteNodeIndexCnfBis (f, 0); + } + + DddmpClearVisitedCnf (f); + + return (id); +} + +/**Function******************************************************************** + + Synopsis [Resets counter and visited flag for ALL nodes of a BDD] + + Description [Resets counter and visited flag for ALL nodes of a BDD (it + recurs on the node children). The index field of the node is + used as counter. + ] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ + +static int +DddmpDdNodesResetCountRecur ( + DdNode *f /* IN: root of the BDD whose counters are reset */ + ) +{ + int retValue; + + f = Cudd_Regular (f); + + if (!DddmpVisitedCnf (f)) { + return (DDDMP_SUCCESS); + } + + if (!cuddIsConstant (f)) { + retValue = DddmpDdNodesResetCountRecur (cuddT (f)); + retValue = DddmpDdNodesResetCountRecur (cuddE (f)); + } + + DddmpWriteNodeIndexCnfBis (f, 0); + DddmpClearVisitedCnf (f); + + return (DDDMP_SUCCESS); +} + +/**Function******************************************************************** + + Synopsis [Counts the number of incoming edges for each node of a BDD] + + Description [Counts (recursively) the number of incoming edges for each + node of a BDD. This number is stored in the index field. + ] + + SideEffects ["visited" flags remain untouched.] + + SeeAlso [] + +******************************************************************************/ + +static int +DddmpDdNodesCountEdgesRecur ( + DdNode *f /* IN: root of the BDD */ + ) +{ + int indexValue, retValue; + + f = Cudd_Regular (f); + + if (cuddIsConstant (f)) { + return (DDDMP_SUCCESS); + } + + if (Cudd_IsConstant (cuddT (f)) && Cudd_IsConstant (cuddE (f))) { + return (DDDMP_SUCCESS); + } + + indexValue = DddmpReadNodeIndexCnf (f); + + /* IF (first time) THEN recur */ + if (indexValue == 0) { + retValue = DddmpDdNodesCountEdgesRecur (cuddT (f)); + retValue = DddmpDdNodesCountEdgesRecur (cuddE (f)); + } + + /* Increment Incoming-Edge Count Flag */ + indexValue++; + DddmpWriteNodeIndexCnfBis (f, indexValue); + + return (DDDMP_SUCCESS); +} + +/**Function******************************************************************** + + Synopsis [Removes a node from unique table] + + Description [Removes a node from the unique table by locating the proper + subtable and unlinking the node from it. It recurs on son nodes. + ] + + SideEffects [Nodes are left with the "visited" flag true.] + + SeeAlso [RestoreInUniqueRecurCnf()] + +******************************************************************************/ + +static void +RemoveFromUniqueRecurCnf ( + DdManager *ddMgr /* IN: DD Manager */, + DdNode *f /* IN: root of the BDD to be extracted */ + ) +{ + DdNode *node, *last, *next; + DdNode *sentinel = &(ddMgr->sentinel); + DdNodePtr *nodelist; + DdSubtable *subtable; + int pos, level; + + f = Cudd_Regular (f); + + if (DddmpVisitedCnf (f)) { + return; + } + + if (!cuddIsConstant (f)) { + + RemoveFromUniqueRecurCnf (ddMgr, cuddT (f)); + RemoveFromUniqueRecurCnf (ddMgr, cuddE (f)); + + level = ddMgr->perm[f->index]; + subtable = &(ddMgr->subtables[level]); + + nodelist = subtable->nodelist; + + pos = ddHash (cuddT (f), cuddE (f), subtable->shift); + node = nodelist[pos]; + last = NULL; + while (node != sentinel) { + next = node->next; + if (node == f) { + if (last != NULL) + last->next = next; + else + nodelist[pos] = next; + break; + } else { + last = node; + node = next; + } + } + + f->next = NULL; + + } + + DddmpSetVisitedCnf (f); + + return; +} + +/**Function******************************************************************** + + Synopsis [Restores a node in unique table] + + Description [Restores a node in unique table (recursive)] + + SideEffects [Nodes are not restored in the same order as before removal] + + SeeAlso [RemoveFromUnique()] + +******************************************************************************/ + +static void +RestoreInUniqueRecurCnf ( + DdManager *ddMgr /* IN: DD Manager */, + DdNode *f /* IN: root of the BDD to be restored */ + ) +{ + DdNodePtr *nodelist; + DdNode *T, *E, *looking; + DdNodePtr *previousP; + DdSubtable *subtable; + int pos, level; +#ifdef DDDMP_DEBUG + DdNode *node; + DdNode *sentinel = &(ddMgr->sentinel); +#endif + + f = Cudd_Regular(f); + + if (!Cudd_IsComplement (f->next)) { + return; + } + + if (cuddIsConstant (f)) { + DddmpClearVisitedCnf (f); + /*f->next = NULL;*/ + return; + } + + RestoreInUniqueRecurCnf (ddMgr, cuddT (f)); + RestoreInUniqueRecurCnf (ddMgr, cuddE (f)); + + level = ddMgr->perm[f->index]; + subtable = &(ddMgr->subtables[level]); + + nodelist = subtable->nodelist; + + pos = ddHash (cuddT (f), cuddE (f), subtable->shift); + +#ifdef DDDMP_DEBUG + /* verify uniqueness to avoid duplicate nodes in unique table */ + for (node=nodelist[pos]; node != sentinel; node=node->next) + assert(node!=f); +#endif + + T = cuddT (f); + E = cuddE (f); + previousP = &(nodelist[pos]); + looking = *previousP; + + while (T < cuddT (looking)) { + previousP = &(looking->next); + looking = *previousP; + } + + while (T == cuddT (looking) && E < cuddE (looking)) { + previousP = &(looking->next); + looking = *previousP; + } + f->next = *previousP; + *previousP = f; + + return; +} + +/**Function******************************************************************** + + Synopsis [Prints debug info] + + Description [Prints debug info for a BDD on the screen. It recurs on + node's children. + ] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ + +static int +DddmpPrintBddAndNextRecur ( + DdManager *ddMgr /* IN: DD Manager */, + DdNode *f /* IN: root of the BDD to be displayed */ + ) +{ + int retValue; + DdNode *fPtr, *tPtr, *ePtr; + + fPtr = Cudd_Regular (f); + + if (Cudd_IsComplement (f)) { + fprintf (stdout, "sign=- ptr=%ld ", ((long int) fPtr)); + } else { + fprintf (stdout, "sign=+ ptr=%ld ", ((long int) fPtr)); + } + + if (cuddIsConstant (fPtr)) { + fprintf (stdout, "one\n"); + fflush (stdout); + return (DDDMP_SUCCESS); + } + + fprintf (stdout, + "thenPtr=%ld elsePtr=%ld BddId=%d CnfId=%d Visited=%d\n", + ((long int) cuddT (fPtr)), ((long int) cuddE (fPtr)), + fPtr->index, DddmpReadNodeIndexCnf (fPtr), + DddmpVisitedCnf (fPtr)); + + tPtr = cuddT (fPtr); + ePtr = cuddE (fPtr); + if (Cudd_IsComplement (f)) { + tPtr = Cudd_Not (tPtr); + ePtr = Cudd_Not (ePtr); + } + + retValue = DddmpPrintBddAndNextRecur (ddMgr, tPtr); + retValue = DddmpPrintBddAndNextRecur (ddMgr, ePtr); + + return (DDDMP_SUCCESS); +} + + diff --git a/distr/dddmp/dddmpInt.h b/distr/dddmp/dddmpInt.h new file mode 100644 index 0000000..7d0f54d --- /dev/null +++ b/distr/dddmp/dddmpInt.h @@ -0,0 +1,216 @@ +/**CHeaderFile***************************************************************** + + FileName [dddmpInt.h] + + PackageName [dddmp] + + Synopsis [Low level functions to read in and write out bdds to file] + + Description [A set of internal low-level routines of the dddmp package + doing: +
            +
          • read and write of node codes in binary mode, +
          • read and write of integers in binary mode, +
          • marking/unmarking nodes as visited, +
          • numbering nodes. +
          + ] + + Author [Gianpiero Cabodi and Stefano Quer] + + Copyright [ + Copyright (c) 2002 by Politecnico di Torino. + All Rights Reserved. This software is for educational purposes only. + Permission is given to academic institutions to use, copy, and modify + this software and its documentation provided that this introductory + message is not removed, that this software and its documentation is + used for the institutions' internal research and educational purposes, + and that no monies are exchanged. No guarantee is expressed or implied + by the distribution of this code. + Send bug-reports and/or questions to: + {gianpiero.cabodi,stefano.quer}@polito.it. + ] + +******************************************************************************/ + +#ifndef _DDDMPINT +#define _DDDMPINT + +#include "dddmp.h" +#include "cuddInt.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/*---------------------------------------------------------------------------*/ +/* Constant declarations */ +/*---------------------------------------------------------------------------*/ + +/* constants for code fields */ +#define DDDMP_TERMINAL 0 +#define DDDMP_ABSOLUTE_ID 1 +#define DDDMP_RELATIVE_ID 2 +#define DDDMP_RELATIVE_1 3 + +#define DDDMP_MAXSTRLEN 500 + +/*---------------------------------------------------------------------------*/ +/* Type declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Structure declarations */ +/*---------------------------------------------------------------------------*/ + +/**Struct********************************************************************** + Synopsis [used in binary mode to store code info of a dd node] + Description [V , T , E store the mode used to represent variable, Then + and Else indexes. An index is either an absolute + ( DDDMP_ABSOLUTE_ID ), + a relative numbers ( DDDMP_RELATIVE_ID , DDDMP_RELATIVE_1 ) or + a terminal node ( DDDMP_TERMINAL ) . + Ecomp is used for the complemented edge attribute. + ] + SideEffect [none] + SeeAlso [DddmpWriteCode DddmpReadCode] +******************************************************************************/ + +struct binary_dd_code { + unsigned Unused : 1; + unsigned V : 2; + unsigned T : 2; + unsigned Ecompl : 1; + unsigned E : 2; +}; + +/**Struct********************************************************************* + + Synopsis [BDD file header] + + Description [Structure containing the BDD header file infos] + +******************************************************************************/ + +struct Dddmp_Hdr_s { + char *ver; + char mode; + Dddmp_DecompType ddType; + Dddmp_VarInfoType varinfo; + char *dd; + int nnodes; + int nVars; + int nsuppvars; + char **orderedVarNames; + char **suppVarNames; + int *ids; + int *permids; + int *auxids; + int *cnfids; + int nRoots; + int *rootids; + char **rootnames; + int nAddedCnfVar; + int nVarsCnf; + int nClausesCnf; +}; + +/*---------------------------------------------------------------------------*/ +/* Variable declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Macro declarations */ +/*---------------------------------------------------------------------------*/ + +/**Macro*********************************************************************** + + Synopsis [Memory Allocation Macro for DDDMP] + + Description [] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ + +#ifdef ALLOC +# define DDDMP_ALLOC(type, num) ALLOC(type,num) +#else +# define DDDMP_ALLOC(type, num) \ + ((type *) malloc(sizeof(type) * (num))) +#endif + +/**Macro*********************************************************************** + + Synopsis [Memory Free Macro for DDDMP] + + Description [] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ + +#ifdef FREE +#define DDDMP_FREE(p) (FREE(p)) +#else +#define DDDMP_FREE(p) \ + ((p)!=NULL)?(free(p)):0) +#endif + + +/**AutomaticStart*************************************************************/ + +/*---------------------------------------------------------------------------*/ +/* Function prototypes */ +/*---------------------------------------------------------------------------*/ + +extern int DddmpWriteCode(FILE *fp, struct binary_dd_code code); +extern int DddmpReadCode(FILE *fp, struct binary_dd_code *pcode); +extern int DddmpWriteInt(FILE *fp, int id); +extern int DddmpReadInt(FILE *fp, int *pid); +extern int DddmpNumberAddNodes(DdManager *ddMgr, DdNode **f, int n); +extern void DddmpUnnumberAddNodes(DdManager *ddMgr, DdNode **f, int n); +extern void DddmpWriteNodeIndexAdd(DdNode *f, int id); +extern int DddmpReadNodeIndexAdd(DdNode *f); +extern int DddmpVisitedAdd(DdNode *f); +extern void DddmpSetVisitedAdd(DdNode *f); +extern void DddmpClearVisitedAdd(DdNode *f); +extern int DddmpNumberBddNodes(DdManager *ddMgr, DdNode **f, int n); +extern void DddmpUnnumberBddNodes(DdManager *ddMgr, DdNode **f, int n); +extern void DddmpWriteNodeIndexBdd(DdNode *f, int id); +extern int DddmpReadNodeIndexBdd(DdNode *f); +extern int DddmpVisitedBdd(DdNode *f); +extern void DddmpSetVisitedBdd(DdNode *f); +extern void DddmpClearVisitedBdd(DdNode *f); +extern int DddmpNumberDdNodesCnf(DdManager *ddMgr, DdNode **f, int rootN, int *cnfIds, int id); +extern int DddmpDdNodesCountEdgesAndNumber(DdManager *ddMgr, DdNode **f, int rootN, int edgeInTh, int pathLengthTh, int *cnfIds, int id); +extern void DddmpUnnumberDdNodesCnf(DdManager *ddMgr, DdNode **f, int rootN); +extern int DddmpPrintBddAndNext(DdManager *ddMgr, DdNode **f, int rootN); +extern int DddmpWriteNodeIndexCnf(DdNode *f, int id); +extern int DddmpVisitedCnf(DdNode *f); +extern void DddmpSetVisitedCnf(DdNode *f); +extern int DddmpReadNodeIndexCnf(DdNode *f); +extern int DddmpCuddDdArrayStoreBdd(Dddmp_DecompType ddType, DdManager *ddMgr, char *ddname, int nRoots, DdNode **f, char **rootnames, char **varnames, int *auxids, int mode, Dddmp_VarInfoType varinfo, char *fname, FILE *fp); +extern int DddmpCuddBddArrayStore(Dddmp_DecompType ddType, DdManager *ddMgr, char *ddname, int nRoots, DdNode **f, char **rootnames, char **varnames, int *auxids, int mode, Dddmp_VarInfoType varinfo, char *fname, FILE *fp); +extern int QsortStrcmp(const void *ps1, const void *ps2); +extern int FindVarname(char *name, char **array, int n); +extern char * DddmpStrDup(char *str); +extern char ** DddmpStrArrayDup(char **array, int n); +extern char ** DddmpStrArrayRead(FILE *fp, int n); +extern int DddmpStrArrayWrite(FILE *fp, char **array, int n); +extern void DddmpStrArrayFree(char **array, int n); +extern int * DddmpIntArrayDup(int *array, int n); +extern int * DddmpIntArrayRead(FILE *fp, int n); +extern int DddmpIntArrayWrite(FILE *fp, int *array, int n); + +/**AutomaticEnd***************************************************************/ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/distr/dddmp/dddmpLoad.c b/distr/dddmp/dddmpLoad.c new file mode 100644 index 0000000..27d9f09 --- /dev/null +++ b/distr/dddmp/dddmpLoad.c @@ -0,0 +1,1486 @@ +/**CFile********************************************************************** + + FileName [dddmpLoad.c] + + PackageName [dddmp] + + Synopsis [Functions to read in bdds to file] + + Description [Functions to read in bdds to file. BDDs + are represended on file either in text or binary format under the + following rules. A file contains a forest of BDDs (a vector of + Boolean functions). BDD nodes are numbered with contiguous numbers, + from 1 to NNodes (total number of nodes on a file). 0 is not used to + allow negative node indexes for complemented edges. A file contains + a header, including information about variables and roots to BDD + functions, followed by the list of nodes. BDD nodes are listed + according to their numbering, and in the present implementation + numbering follows a post-order strategy, in such a way that a node + is never listed before its Then/Else children. + ] + + Author [Gianpiero Cabodi and Stefano Quer] + + Copyright [ + Copyright (c) 2004 by Politecnico di Torino. + All Rights Reserved. This software is for educational purposes only. + Permission is given to academic institutions to use, copy, and modify + this software and its documentation provided that this introductory + message is not removed, that this software and its documentation is + used for the institutions' internal research and educational purposes, + and that no monies are exchanged. No guarantee is expressed or implied + by the distribution of this code. + Send bug-reports and/or questions to: + {gianpiero.cabodi,stefano.quer}@polito.it. + ] + +******************************************************************************/ + +#include "dddmpInt.h" + +/*---------------------------------------------------------------------------*/ +/* Stucture declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Type declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Variable declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Macro declarations */ +/*---------------------------------------------------------------------------*/ + +#define matchkeywd(str,key) (strncmp(str,key,strlen(key))==0) + +/**AutomaticStart*************************************************************/ + +/*---------------------------------------------------------------------------*/ +/* Static function prototypes */ +/*---------------------------------------------------------------------------*/ + +static int DddmpCuddDdArrayLoad(Dddmp_DecompType ddType, DdManager *ddMgr, Dddmp_RootMatchType rootMatchMode, char **rootmatchnames, Dddmp_VarMatchType varMatchMode, char **varmatchnames, int *varmatchauxids, int *varcomposeids, int mode, char *file, FILE *fp, DdNode ***pproots); +static Dddmp_Hdr_t * DddmpBddReadHeader(char *file, FILE *fp); +static void DddmpFreeHeader(Dddmp_Hdr_t *Hdr); + +/**AutomaticEnd***************************************************************/ + +/*---------------------------------------------------------------------------*/ +/* Definition of exported functions */ +/*---------------------------------------------------------------------------*/ + +/**Function******************************************************************** + + Synopsis [Reads a dump file representing the argument BDD.] + + Description [Reads a dump file representing the argument BDD. + Dddmp_cuddBddArrayLoad is used through a dummy array (see this + function's description for more details). + Mode, the requested input file format, is checked against + the file format. + The loaded BDDs is referenced before returning it. + ] + + SideEffects [A vector of pointers to DD nodes is allocated and freed.] + + SeeAlso [Dddmp_cuddBddStore, Dddmp_cuddBddArrayLoad] + +******************************************************************************/ + +DdNode * +Dddmp_cuddBddLoad ( + DdManager *ddMgr /* IN: DD Manager */, + Dddmp_VarMatchType varMatchMode /* IN: storing mode selector */, + char **varmatchnames /* IN: array of variable names - by IDs */, + int *varmatchauxids /* IN: array of variable auxids - by IDs */, + int *varcomposeids /* IN: array of new ids accessed - by IDs */, + int mode /* IN: requested input file format */, + char *file /* IN: file name */, + FILE *fp /* IN: file pointer */ + ) +{ + DdNode *f , **tmpArray; + int i, nRoots; + + nRoots = Dddmp_cuddBddArrayLoad(ddMgr,DDDMP_ROOT_MATCHLIST,NULL, + varMatchMode,varmatchnames,varmatchauxids,varcomposeids, + mode,file,fp,&tmpArray); + + if (nRoots == 0) { + return (NULL); + } else { + f = tmpArray[0]; + if (nRoots > 1) { + fprintf (stderr, + "Warning: %d BDD roots found in file. Only first retrieved.\n", + nRoots); + for (i=1; i +
        • varMatchMode=DDDMP_VAR_MATCHIDS

          + allows the loading of a DD keeping variable IDs unchanged + (regardless of the variable ordering of the reading manager); this + is useful, for example, when swapping DDs to file and restoring them + later from file, after possible variable reordering activations. + +

        • varMatchMode=DDDMP_VAR_MATCHPERMIDS

          + is used to allow variable match according to the position in the + ordering. + +

        • varMatchMode=DDDMP_VAR_MATCHNAMES

          + requires a non NULL varmatchnames parameter; this is a vector of + strings in one-to-one correspondence with variable IDs of the + reading manager. Variables in the DD file read are matched with + manager variables according to their name (a non NULL varnames + parameter was required while storing the DD file). + +

        • varMatchMode=DDDMP_VAR_MATCHIDS

          + has a meaning similar to DDDMP_VAR_MATCHNAMES, but integer auxiliary + IDs are used instead of strings; the additional non NULL + varmatchauxids parameter is needed. + +

        • varMatchMode=DDDMP_VAR_COMPOSEIDS

          + uses the additional varcomposeids parameter is used as array of + variable ids to be composed with ids stored in file. + + + In the present implementation, the array varnames (3), varauxids (4) + and composeids (5) need to have one entry for each variable in the + DD manager (NULL pointers are allowed for unused variables + in varnames). Hence variables need to be already present in the + manager. All arrays are sorted according to IDs. + + All the loaded BDDs are referenced before returning them. + ] + + SideEffects [A vector of pointers to DD nodes is allocated and freed.] + + SeeAlso [Dddmp_cuddBddArrayStore] + +******************************************************************************/ + +int +Dddmp_cuddBddArrayLoad ( + DdManager *ddMgr /* IN: DD Manager */, + Dddmp_RootMatchType rootMatchMode /* IN: storing mode selector */, + char **rootmatchnames /* IN: sorted names for loaded roots */, + Dddmp_VarMatchType varMatchMode /* IN: storing mode selector */, + char **varmatchnames /* IN: array of variable names, by ids */, + int *varmatchauxids /* IN: array of variable auxids, by ids */, + int *varcomposeids /* IN: array of new ids, by ids */, + int mode /* IN: requested input file format */, + char *file /* IN: file name */, + FILE *fp /* IN: file pointer */, + DdNode ***pproots /* OUT: array of returned BDD roots */ + ) +{ + int retValue; + +#ifdef DDDMP_DEBUG +#ifndef __alpha__ + int retValueBis; + + retValueBis = Cudd_DebugCheck (ddMgr); + if (retValueBis == 1) { + fprintf (stderr, "Inconsistency Found During BDD Load.\n"); + fflush (stderr); + } else { + if (retValueBis == CUDD_OUT_OF_MEM) { + fprintf (stderr, "Out of Memory During BDD Load.\n"); + fflush (stderr); + } + } +#endif +#endif + + retValue = DddmpCuddDdArrayLoad (DDDMP_BDD, ddMgr, rootMatchMode, + rootmatchnames, varMatchMode, varmatchnames, varmatchauxids, + varcomposeids, mode, file, fp, pproots); + +#ifdef DDDMP_DEBUG +#ifndef __alpha__ + retValueBis = Cudd_DebugCheck (ddMgr); + if (retValueBis == 1) { + fprintf (stderr, "Inconsistency Found During BDD Load.\n"); + fflush (stderr); + } else { + if (retValueBis == CUDD_OUT_OF_MEM) { + fprintf (stderr, "Out of Memory During BDD Load.\n"); + fflush (stderr); + } + } +#endif +#endif + + return (retValue); +} + +/**Function******************************************************************** + + Synopsis [Reads a dump file representing the argument ADD.] + + Description [Reads a dump file representing the argument ADD. + Dddmp_cuddAddArrayLoad is used through a dummy array. + ] + + SideEffects [A vector of pointers to DD nodes is allocated and freed.] + + SeeAlso [Dddmp_cuddAddStore, Dddmp_cuddAddArrayLoad] + +******************************************************************************/ + +DdNode * +Dddmp_cuddAddLoad ( + DdManager *ddMgr /* IN: Manager */, + Dddmp_VarMatchType varMatchMode /* IN: storing mode selector */, + char **varmatchnames /* IN: array of variable names by IDs */, + int *varmatchauxids /* IN: array of variable auxids by IDs */, + int *varcomposeids /* IN: array of new ids by IDs */, + int mode /* IN: requested input file format */, + char *file /* IN: file name */, + FILE *fp /* IN: file pointer */ + ) +{ + DdNode *f , **tmpArray; + int i, nRoots; + + nRoots = Dddmp_cuddAddArrayLoad (ddMgr, DDDMP_ROOT_MATCHLIST,NULL, + varMatchMode, varmatchnames, varmatchauxids, varcomposeids, + mode, file, fp, &tmpArray); + + if (nRoots == 0) { + return (NULL); + } else { + f = tmpArray[0]; + if (nRoots > 1) { + fprintf (stderr, + "Warning: %d BDD roots found in file. Only first retrieved.\n", + nRoots); + for (i=1; innodes==0, "Zero number of nodes.", + failure); + + /* + * Type, number of variables (tot and support) + */ + + *ddType = Hdr->ddType; + *nVars = Hdr->nVars; + *nsuppvars = Hdr->nsuppvars; + + /* + * Support Varnames + */ + + if (Hdr->suppVarNames != NULL) { + *suppVarNames = DDDMP_ALLOC (char *, *nsuppvars); + Dddmp_CheckAndGotoLabel (*suppVarNames==NULL, + "Error allocating memory.", failure); + + for (i=0; i<*nsuppvars; i++) { + (*suppVarNames)[i] = DDDMP_ALLOC (char, + (strlen (Hdr->suppVarNames[i]) + 1)); + Dddmp_CheckAndGotoLabel (Hdr->suppVarNames[i]==NULL, + "Support Variable Name Missing in File.", failure); + strcpy ((*suppVarNames)[i], Hdr->suppVarNames[i]); + } + } else { + *suppVarNames = NULL; + } + + /* + * Ordered Varnames + */ + + if (Hdr->orderedVarNames != NULL) { + *orderedVarNames = DDDMP_ALLOC (char *, *nVars); + Dddmp_CheckAndGotoLabel (*orderedVarNames==NULL, + "Error allocating memory.", failure); + + for (i=0; i<*nVars; i++) { + (*orderedVarNames)[i] = DDDMP_ALLOC (char, + (strlen (Hdr->orderedVarNames[i]) + 1)); + Dddmp_CheckAndGotoLabel (Hdr->orderedVarNames[i]==NULL, + "Support Variable Name Missing in File.", failure); + strcpy ((*orderedVarNames)[i], Hdr->orderedVarNames[i]); + } + } else { + *orderedVarNames = NULL; + } + + /* + * Variable Ids + */ + + if (Hdr->ids != NULL) { + tmpVarIds = DDDMP_ALLOC (int, *nsuppvars); + Dddmp_CheckAndGotoLabel (tmpVarIds==NULL, "Error allocating memory.", + failure); + for (i=0; i<*nsuppvars; i++) { + tmpVarIds[i] = Hdr->ids[i]; + } + + *varIds = tmpVarIds; + } else { + *varIds = NULL; + } + + /* + * Variable Compose Ids + */ + + if (Hdr->permids != NULL) { + tmpVarComposeIds = DDDMP_ALLOC (int, *nsuppvars); + Dddmp_CheckAndGotoLabel (tmpVarComposeIds==NULL, + "Error allocating memory.", failure); + for (i=0; i<*nsuppvars; i++) { + tmpVarComposeIds[i] = Hdr->permids[i]; + } + + *varComposeIds = tmpVarComposeIds; + } else { + *varComposeIds = NULL; + } + + /* + * Variable Auxiliary Ids + */ + + if (Hdr->auxids != NULL) { + tmpVarAuxIds = DDDMP_ALLOC (int, *nsuppvars); + Dddmp_CheckAndGotoLabel (tmpVarAuxIds==NULL, + "Error allocating memory.", failure); + for (i=0; i<*nsuppvars; i++) { + tmpVarAuxIds[i] = Hdr->auxids[i]; + } + + *varAuxIds = tmpVarAuxIds; + } else { + *varAuxIds = NULL; + } + + /* + * Number of roots + */ + + *nRoots = Hdr->nRoots; + + /* + * Free and Return + */ + + if (fileToClose == 1) { + fclose (fp); + } + + DddmpFreeHeader(Hdr); + + return (DDDMP_SUCCESS); + + failure: + return (DDDMP_FAILURE); +} + + +/*---------------------------------------------------------------------------*/ +/* Definition of internal functions */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Definition of static functions */ +/*---------------------------------------------------------------------------*/ + +/**Function******************************************************************** + + Synopsis [Reads a dump file representing the argument BDDs.] + + Description [Reads a dump file representing the argument BDDs. The header is + common to both text and binary mode. The node list is either + in text or binary format. A dynamic vector of DD pointers + is allocated to support conversion from DD indexes to pointers. + Several criteria are supported for variable match between file + and dd manager. Several changes/permutations/compositions are allowed + for variables while loading DDs. Variable of the dd manager are allowed + to match with variables on file on ids, permids, varnames, + varauxids; also direct composition between ids and + composeids is supported. More in detail: +

            +
          1. varMatchMode=DDDMP_VAR_MATCHIDS

            + allows the loading of a DD keeping variable IDs unchanged + (regardless of the variable ordering of the reading manager); this + is useful, for example, when swapping DDs to file and restoring them + later from file, after possible variable reordering activations. + +

          2. varMatchMode=DDDMP_VAR_MATCHPERMIDS

            + is used to allow variable match according to the position in the ordering. + +

          3. varMatchMode=DDDMP_VAR_MATCHNAMES

            + requires a non NULL varmatchnames parameter; this is a vector of + strings in one-to-one correspondence with variable IDs of the + reading manager. Variables in the DD file read are matched with + manager variables according to their name (a non NULL varnames + parameter was required while storing the DD file). + +

          4. varMatchMode=DDDMP_VAR_MATCHIDS

            + has a meaning similar to DDDMP_VAR_MATCHNAMES, but integer auxiliary + IDs are used instead of strings; the additional non NULL + varmatchauxids parameter is needed. + +

          5. varMatchMode=DDDMP_VAR_COMPOSEIDS

            + uses the additional varcomposeids parameter is used as array of + variable ids to be composed with ids stored in file. +

          + + In the present implementation, the array varnames (3), varauxids (4) + and composeids (5) need to have one entry for each variable in the + DD manager (NULL pointers are allowed for unused variables + in varnames). Hence variables need to be already present in the + manager. All arrays are sorted according to IDs. + ] + + SideEffects [A vector of pointers to DD nodes is allocated and freed.] + + SeeAlso [Dddmp_cuddBddArrayStore] + +******************************************************************************/ + +static int +DddmpCuddDdArrayLoad ( + Dddmp_DecompType ddType /* IN: Selects decomp type */, + DdManager *ddMgr /* IN: DD Manager */, + Dddmp_RootMatchType rootMatchMode /* IN: storing mode selector */, + char **rootmatchnames /* IN: sorted names for loaded roots */, + Dddmp_VarMatchType varMatchMode /* IN: storing mode selector */, + char **varmatchnames /* IN: array of variable names, by ids */, + int *varmatchauxids /* IN: array of variable auxids, by ids */, + int *varcomposeids /* IN: array of new ids, by ids */, + int mode /* IN: requested input file format */, + char *file /* IN: file name */, + FILE *fp /* IN: file pointer */, + DdNode ***pproots /* OUT: array BDD roots (by reference) */ + ) +{ + Dddmp_Hdr_t *Hdr = NULL; + DdNode *f = NULL; + DdNode *T = NULL; + DdNode *E = NULL; + struct binary_dd_code code; + char buf[DDDMP_MAXSTRLEN]; + int retValue, id, size, maxv; + int i, j, k, maxaux, var, vT, vE, idT, idE; + double addConstant; + int *permsupport = NULL; + int *convertids = NULL; + int *invconvertids = NULL; + int *invauxids = NULL; + char **sortedvarnames = NULL; + int nddvars, nRoots; + DdNode **pnodes = NULL; + unsigned char *pvars1byte = NULL; + unsigned short *pvars2byte = NULL; + DdNode **proots = NULL; + int fileToClose = 0; + + *pproots = NULL; + + if (fp == NULL) { + fp = fopen (file, "r"); + Dddmp_CheckAndGotoLabel (fp==NULL, "Error opening file.", + failure); + fileToClose = 1; + } + + nddvars = ddMgr->size; + + Hdr = DddmpBddReadHeader (NULL, fp); + + Dddmp_CheckAndGotoLabel (Hdr->nnodes==0, "Zero number of nodes.", + failure); + + nRoots = Hdr->nRoots; + + if (Hdr->ddType != ddType) { + (void) fprintf (stderr, "DdLoad Error: ddType mismatch\n"); + + if (Hdr->ddType == DDDMP_BDD) + (void) fprintf (stderr, "BDD found\n"); + if (Hdr->ddType == DDDMP_ADD) + (void) fprintf (stderr, "ADD found\n"); + if (ddType == DDDMP_BDD) + (void) fprintf (stderr, "when loading a BDD\n"); + if (ddType == DDDMP_ADD) + (void) fprintf (stderr, "when loading an ADD\n"); + + fflush (stderr); + goto failure; + } + + if (Hdr->mode != mode) { + Dddmp_CheckAndGotoLabel (mode!=DDDMP_MODE_DEFAULT, + "Mode Mismatch.", failure); + mode = Hdr->mode; + } + + /* + * For each variable in the support + * compute the relative position in the ordering + * (within the support only) + */ + + permsupport = DDDMP_ALLOC (int, Hdr->nsuppvars); + Dddmp_CheckAndGotoLabel (permsupport==NULL, "Error allocating memory.", + failure); + for (i=0,k=0; i < Hdr->nVars; i++) { + for (j=0; j < Hdr->nsuppvars; j++) { + if (Hdr->permids[j] == i) { + permsupport[j] = k++; + } + } + } + Dddmp_Assert (k==Hdr->nsuppvars, "k==Hdr->nsuppvars"); + + if (Hdr->suppVarNames != NULL) { + /* + * Varnames are sorted for binary search + */ + + sortedvarnames = DDDMP_ALLOC(char *, Hdr->nsuppvars); + Dddmp_CheckAndGotoLabel (sortedvarnames==NULL, "Error allocating memory.", + failure); + for (i=0; insuppvars; i++) { + Dddmp_CheckAndGotoLabel (Hdr->suppVarNames[i]==NULL, + "Support Variable Name Missing in File.", failure); + sortedvarnames[i] = Hdr->suppVarNames[i]; + } + + qsort ((void *) sortedvarnames, Hdr->nsuppvars, + sizeof(char *), QsortStrcmp); + + } + + /* + * Convertids is the array used to convert variable ids from positional + * (shrinked) ids used within the DD file. + * Positions in the file are from 0 to nsuppvars-1. + */ + + convertids = DDDMP_ALLOC (int, Hdr->nsuppvars); + Dddmp_CheckAndGotoLabel (convertids==NULL, "Error allocating memory.", + failure); + + again_matchmode: + switch (varMatchMode) { + case DDDMP_VAR_MATCHIDS: + for (i=0; insuppvars; i++) { + convertids[permsupport[i]] = Hdr->ids[i]; + } + break; + case DDDMP_VAR_MATCHPERMIDS: + for (i=0; insuppvars; i++) { + convertids[permsupport[i]] = Cudd_ReadInvPerm (ddMgr, + Hdr->permids[i]); + } + break; + case DDDMP_VAR_MATCHAUXIDS: + if (Hdr->auxids == NULL) { + (void) fprintf (stderr, + "DdLoad Error: variable auxids matching requested\n"); + (void) fprintf (stderr, "but .auxids not found in BDD file\n"); + (void) fprintf (stderr, "Matching IDs forced.\n"); + fflush (stderr); + varMatchMode = DDDMP_VAR_MATCHIDS; + goto again_matchmode; + } + /* find max auxid value to alloc invaux array */ + for (i=0,maxaux= -1; imaxaux) { + maxaux = varmatchauxids[i]; + } + } + /* generate invaux array */ + invauxids = DDDMP_ALLOC (int, maxaux+1); + Dddmp_CheckAndGotoLabel (invauxids==NULL, "Error allocating memory.", + failure); + + for (i=0; i<=maxaux; i++) { + invauxids[i] = -1; + } + + for (i=0; insuppvars; i++) { + invauxids[varmatchauxids[Hdr->ids[i]]] = Hdr->ids[i]; + } + + /* generate convertids array */ + for (i=0; insuppvars; i++) { + if ((Hdr->auxids[i]>maxaux) || (invauxids[Hdr->auxids[i]]<0)) { + (void) fprintf (stderr, + "DdLoad Error: auxid %d not found in DD manager.\n", + Hdr->auxids[i]); + (void) fprintf (stderr, "ID matching forced (%d).\n", i); + (void) fprintf (stderr, + "Beware of possible overlappings with other variables\n"); + fflush (stderr); + convertids[permsupport[i]] = i; + } else { + convertids[permsupport[i]] = invauxids[Hdr->auxids[i]]; + } + } + break; + case DDDMP_VAR_MATCHNAMES: + if (Hdr->suppVarNames == NULL) { + (void) fprintf (stderr, + "DdLoad Error: variable names matching requested\n"); + (void) fprintf (stderr, "but .suppvarnames not found in BDD file\n"); + (void) fprintf (stderr, "Matching IDs forced.\n"); + fflush (stderr); + varMatchMode = DDDMP_VAR_MATCHIDS; + goto again_matchmode; + } + + /* generate invaux array */ + invauxids = DDDMP_ALLOC (int, Hdr->nsuppvars); + Dddmp_CheckAndGotoLabel (invauxids==NULL, "Error allocating memory.", + failure); + + for (i=0; insuppvars; i++) { + invauxids[i] = -1; + } + + for (i=0; insuppvars)) + >=0) { + Dddmp_Assert (jnsuppvars, "jnsuppvars"); + invauxids[j] = i; + } + } + /* generate convertids array */ + for (i=0; insuppvars; i++) { + Dddmp_Assert (Hdr->suppVarNames[i]!=NULL, + "Hdr->suppVarNames[i] != NULL"); + j=FindVarname(Hdr->suppVarNames[i],sortedvarnames,Hdr->nsuppvars); + Dddmp_Assert ((j>=0) && (jnsuppvars), + "(j>=0) && (jnsuppvars)"); + if (invauxids[j]<0) { + fprintf (stderr, + "DdLoad Error: varname %s not found in DD manager.", + Hdr->suppVarNames[i]); + fprintf (stderr, "ID matching forced (%d)\n", i); + fflush (stderr); + convertids[permsupport[i]]=i; + } else { + convertids[permsupport[i]] = invauxids[j]; + } + } + break; + case DDDMP_VAR_COMPOSEIDS: + for (i=0; insuppvars; i++) { + convertids[permsupport[i]] = varcomposeids[Hdr->ids[i]]; + } + break; + } + + maxv = (-1); + for (i=0; insuppvars; i++) { + if (convertids[i] > maxv) { + maxv = convertids[i]; + } + } + + invconvertids = DDDMP_ALLOC (int, maxv+1); + Dddmp_CheckAndGotoLabel (invconvertids==NULL, "Error allocating memory.", + failure); + + for (i=0; i<=maxv; i++) { + invconvertids[i]= -1; + } + + for (i=0; insuppvars; i++) { + invconvertids[convertids[i]] = i; + } + + pnodes = DDDMP_ALLOC(DdNode *,(Hdr->nnodes+1)); + Dddmp_CheckAndGotoLabel (pnodes==NULL, "Error allocating memory.", + failure); + + if (Hdr->nsuppvars < 256) { + pvars1byte = DDDMP_ALLOC(unsigned char,(Hdr->nnodes+1)); + Dddmp_CheckAndGotoLabel (pvars1byte==NULL, "Error allocating memory.", + failure); + } + else if (Hdr->nsuppvars < 0xffff) { + pvars2byte = DDDMP_ALLOC(unsigned short,(Hdr->nnodes+1)); + Dddmp_CheckAndGotoLabel (pvars2byte==NULL, "Error allocating memory.", + failure); + } else { + (void) fprintf (stderr, + "DdLoad Error: more than %d variables. Not supported.\n", 0xffff); + fflush (stderr); + goto failure; + } + + /*-------------- Deal With Nodes ... One Row File at a Time --------------*/ + + for (i=1; i<=Hdr->nnodes; i++) { + + Dddmp_CheckAndGotoLabel (feof(fp), + "Unexpected EOF While Reading DD Nodes.", failure); + + switch (mode) { + + /* + * Text FORMAT + */ + + case DDDMP_MODE_TEXT: + + switch (Hdr->varinfo) { + case DDDMP_VARIDS: + case DDDMP_VARPERMIDS: + case DDDMP_VARAUXIDS: + case DDDMP_VARNAMES: + retValue = fscanf(fp, "%d %*s %s %d %d\n", &id, buf, &idT, &idE); + Dddmp_CheckAndGotoLabel (retValue<4, + "Error Reading Nodes in Text Mode.", failure); + break; + case DDDMP_VARDEFAULT: + retValue = fscanf(fp, "%d %s %d %d\n", &id, buf, &idT, &idE); + Dddmp_CheckAndGotoLabel (retValue<4, + "Error Reading Nodes in Text Mode.", failure); + break; + } +#ifdef DDDMP_DEBUG + Dddmp_Assert (id==i, "id == i"); +#endif + if (idT==0 && idE==0) { + /* leaf node: a constant */ + if (strcmp(buf, "1") == 0) { + pnodes[i] = Cudd_ReadOne (ddMgr); + } else { + /* this is an ADD constant ! */ + if (strcmp(buf, "0") == 0) { + pnodes[i] = Cudd_ReadZero (ddMgr); + } else { + addConstant = atof(buf); + pnodes[i] = Cudd_addConst (ddMgr, + (CUDD_VALUE_TYPE) addConstant); + } + } + + /* StQ 11.02.2004: + Bug fixed --> Reference All Nodes for ADD */ + Cudd_Ref (pnodes[i]); + Dddmp_CheckAndGotoLabel (pnodes[i]==NULL, "NULL pnodes.", + failure); + continue; + } else { +#ifdef DDDMP_DEBUG + Dddmp_Assert (idT>0, "id > 0"); +#endif + var = atoi(buf); + T = pnodes[idT]; + if(idE<0) { + idE = -idE; + E = pnodes[idE]; + E = Cudd_Not(E); + } else { + E = pnodes[idE]; + } + } + + break; + + /* + * Binary FORMAT + */ + + case DDDMP_MODE_BINARY: + + Dddmp_CheckAndGotoLabel (DddmpReadCode(fp,&code) == 0, + "Error Reading witn ReadCode.", failure); + + switch (code.V) { + case DDDMP_TERMINAL: + /* only 1 terminal presently supported */ + pnodes[i] = Cudd_ReadOne (ddMgr); + continue; + break; + case DDDMP_RELATIVE_1: + break; + case DDDMP_RELATIVE_ID: + case DDDMP_ABSOLUTE_ID: + size = DddmpReadInt (fp, &var); + Dddmp_CheckAndGotoLabel (size==0, "Error reading size.", + failure); + break; + } + + switch (code.T) { + case DDDMP_TERMINAL: + idT = 1; + break; + case DDDMP_RELATIVE_1: + idT = i-1; + break; + case DDDMP_RELATIVE_ID: + size = DddmpReadInt (fp, &id); + Dddmp_CheckAndGotoLabel (size==0, "Error reading size.", + failure); + idT = i-id; + break; + case DDDMP_ABSOLUTE_ID: + size = DddmpReadInt (fp, &idT); + Dddmp_CheckAndGotoLabel (size==0, "Error reading size.", + failure); + break; + } + + switch (code.E) { + case DDDMP_TERMINAL: + idE = 1; + break; + case DDDMP_RELATIVE_1: + idE = i-1; + break; + case DDDMP_RELATIVE_ID: + size = DddmpReadInt (fp, &id); + Dddmp_CheckAndGotoLabel (size==0, "Error reading size.", + failure); + idE = i-id; + break; + case DDDMP_ABSOLUTE_ID: + size = DddmpReadInt (fp, &idE); + Dddmp_CheckAndGotoLabel (size==0, "Error reading size.", + failure); + break; + } + +#ifdef DDDMP_DEBUG + Dddmp_Assert (idTnsuppvars; + else { + if (pvars1byte != NULL) + vT = pvars1byte[idT]; + else if (pvars2byte != NULL) + vT = pvars2byte[idT]; + else + vT = invconvertids[T->index]; + } +#ifdef DDDMP_DEBUG + Dddmp_Assert (vT>0, "vT > 0"); + Dddmp_Assert (vT<=Hdr->nsuppvars, "vT <= Hdr->nsuppvars"); +#endif + +#ifdef DDDMP_DEBUG + Dddmp_Assert (idEnsuppvars; + else { + if (pvars1byte != NULL) + vE = pvars1byte[idE]; + else if (pvars2byte != NULL) + vE = pvars2byte[idE]; + else + vE = invconvertids[E->index]; + } +#ifdef DDDMP_DEBUG + Dddmp_Assert (vE>0, "vE > 0"); + Dddmp_Assert (vE<=Hdr->nsuppvars, "vE <= Hdr->nsuppvars"); +#endif + + switch (code.V) { + case DDDMP_TERMINAL: + case DDDMP_ABSOLUTE_ID: + break; + case DDDMP_RELATIVE_1: + var = (vTnsuppvars, "var < Hdr->nsuppvars"); +#endif + + break; + } + + if (pvars1byte != NULL) { + pvars1byte[i] = (unsigned char) var; + } else { + if (pvars2byte != NULL) { + pvars2byte[i] = (unsigned short) var; + } + } + + var = convertids[var]; + switch (ddType) { + case DDDMP_BDD: + pnodes[i] = Cudd_bddIte (ddMgr, Cudd_bddIthVar (ddMgr, var), + T, E); + break; + case DDDMP_ADD: + { + DdNode *tmp = Cudd_addIthVar (ddMgr, var); + Cudd_Ref (tmp); + pnodes[i] = Cudd_addIte (ddMgr, tmp, T, E); + Cudd_RecursiveDeref (ddMgr, tmp); + break; + } + case DDDMP_CNF: + case DDDMP_NONE: + Dddmp_Warning (1, "Wrong DD Type."); + break; + } + + cuddRef (pnodes[i]); + } + + /*------------------------ Deal With the File Tail -----------------------*/ + + fgets (buf, DDDMP_MAXSTRLEN-1,fp); + Dddmp_CheckAndGotoLabel (!matchkeywd(buf, ".end"), + "Error .end not found.", failure); + + /* Close File IFF Necessary */ + if (fileToClose) { + fclose (fp); + } + + /* BDD Roots */ + proots = DDDMP_ALLOC(DdNode *,nRoots); + Dddmp_CheckAndGotoLabel (proots==NULL, "Error allocating memory.", + failure); + + for(i=0; irootnames[j]) == 0) + break; + } + if (j>=nRoots) { + /* rootname not found */ + fprintf (stderr, "Warning: unable to match root name <%s>\n", + rootmatchnames[i]); + } + break; + case DDDMP_ROOT_MATCHLIST: + j = i; + break; + } + + id = Hdr->rootids[i]; + if (id==0) { + (void) fprintf (stderr, "DdLoad Warning: NULL root found in file\n"); + fflush (stderr); + f = NULL; + } else { + if (id<0) { + f = Cudd_Not(pnodes[-id]); + } else { + f = pnodes[id]; + } + } + proots[i] = f; + + cuddRef (f); + } /* end for i = 0..nRoots */ + + /* + * Decrease Reference for all Nodes + */ + + /* StQ 11.02.2004: + Bug fixed --> De-Reference All Nodes for ADD */ + for (i=1; i<=Hdr->nnodes; i++) { + f = pnodes[i]; + Cudd_RecursiveDeref (ddMgr, f); + } + + /* + * Free Memory: load_end label + */ + +load_end: + + DddmpFreeHeader(Hdr); + + DDDMP_FREE (pnodes); + DDDMP_FREE (pvars1byte); + DDDMP_FREE (pvars2byte); + + /* variable names are not freed because they were shared with varnames */ + DDDMP_FREE (sortedvarnames); + + DDDMP_FREE (permsupport); + DDDMP_FREE (convertids); + DDDMP_FREE (invconvertids); + DDDMP_FREE (invauxids); + + *pproots = proots; + return (nRoots); + + /* + * Failure Condition + */ + +failure: + + if (fileToClose) { + fclose (fp); + } + + nRoots = 0; /* return 0 on error ! */ + + DDDMP_FREE (proots); + + goto load_end; /* this is done to free memory */ +} + +/**Function******************************************************************** + + Synopsis [Reads a the header of a dump file representing the + argument BDDs. + ] + + Description [Reads the header of a dump file. Builds a Dddmp_Hdr_t struct + containing all infos in the header, for next manipulations. + ] + + SideEffects [none] + + SeeAlso [] + +******************************************************************************/ + +static Dddmp_Hdr_t * +DddmpBddReadHeader ( + char *file /* IN: file name */, + FILE *fp /* IN: file pointer */ + ) +{ + Dddmp_Hdr_t *Hdr = NULL; + char buf[DDDMP_MAXSTRLEN]; + int retValue, fileToClose = 0; + + if (fp == NULL) { + fp = fopen (file, "r"); + Dddmp_CheckAndGotoLabel (fp==NULL, "Error opening file.", + failure); + fileToClose = 1; + } + + /* START HEADER */ + + Hdr = DDDMP_ALLOC (Dddmp_Hdr_t,1); + if (Hdr == NULL) { + return NULL; + } + Hdr->ver = NULL; + Hdr->mode = 0; + Hdr->ddType = DDDMP_BDD; + Hdr->varinfo = DDDMP_VARIDS; + Hdr->dd = NULL; + Hdr->nnodes = 0; + Hdr->nVars = 0; + Hdr->nsuppvars = 0; + Hdr->suppVarNames = NULL; + Hdr->orderedVarNames = NULL; + Hdr->ids = NULL; + Hdr->permids = NULL; + Hdr->auxids = NULL; + Hdr->cnfids = NULL; + Hdr->nRoots = 0; + Hdr->rootids = NULL; + Hdr->rootnames = NULL; + Hdr->nAddedCnfVar = 0; + Hdr->nVarsCnf = 0; + Hdr->nClausesCnf = 0; + + while (fscanf(fp, "%s", buf)!=EOF) { + + /* comment */ + if (buf[0] == '#') { + fgets(buf,DDDMP_MAXSTRLEN,fp); + continue; + } + + Dddmp_CheckAndGotoLabel (buf[0] != '.', + "Error; line must begin with '.' or '#'.", + failure); + + if (matchkeywd(buf, ".ver")) { + /* this not checked so far: only read */ + retValue = fscanf (fp, "%s", buf); + Dddmp_CheckAndGotoLabel (retValue==EOF, "Error reading from file.", + failure); + + Hdr->ver=DddmpStrDup(buf); + Dddmp_CheckAndGotoLabel (Hdr->ver==NULL, + "Error allocating memory.", failure); + + continue; + } + + if (matchkeywd(buf, ".add")) { + Hdr->ddType = DDDMP_ADD; + continue; + } + + if (matchkeywd(buf, ".bdd")) { + Hdr->ddType = DDDMP_BDD; + continue; + } + + if (matchkeywd(buf, ".mode")) { + retValue = fscanf (fp, "%s", buf); + Dddmp_CheckAndGotoLabel (retValue==EOF, "Error reading to file.", + failure); + + Hdr->mode = buf[0]; + continue; + } + + if (matchkeywd(buf, ".varinfo")) { + int readMe; + retValue = fscanf (fp, "%d", &readMe); + Dddmp_CheckAndGotoLabel (retValue==EOF, "Error reading file.", + failure); + Hdr->varinfo = (Dddmp_VarInfoType) readMe; + + continue; + } + + if (matchkeywd(buf, ".dd")) { + retValue = fscanf (fp, "%s", buf); + Dddmp_CheckAndGotoLabel (retValue==EOF, "Error reading file.", + failure); + + Hdr->dd = DddmpStrDup (buf); + Dddmp_CheckAndGotoLabel (Hdr->dd==NULL, "Error allocating memory.", + failure); + + continue; + } + + if (matchkeywd(buf, ".nnodes")) { + retValue = fscanf (fp, "%d", &(Hdr->nnodes)); + Dddmp_CheckAndGotoLabel (retValue==EOF, "Error reading file.", + failure); + + continue; + } + + if (matchkeywd(buf, ".nvars")) { + retValue = fscanf (fp, "%d", &(Hdr->nVars)); + Dddmp_CheckAndGotoLabel (retValue==EOF, "Error reading file.", + failure); + + continue; + } + + if (matchkeywd(buf, ".nsuppvars")) { + retValue = fscanf (fp, "%d", &(Hdr->nsuppvars)); + Dddmp_CheckAndGotoLabel (retValue==EOF, "Error reading file.", + failure); + + continue; + } + + if (matchkeywd(buf, ".orderedvarnames")) { + Hdr->orderedVarNames = DddmpStrArrayRead (fp, Hdr->nVars); + Dddmp_CheckAndGotoLabel (Hdr->orderedVarNames==NULL, + "Error allocating memory.", failure); + + continue; + } + + if (matchkeywd(buf, ".suppvarnames") || + ((strcmp (Hdr->ver, "DDDMP-1.0") == 0) && + matchkeywd (buf, ".varnames"))) { + Hdr->suppVarNames = DddmpStrArrayRead (fp, Hdr->nsuppvars); + Dddmp_CheckAndGotoLabel (Hdr->suppVarNames==NULL, + "Error allocating memory.", failure); + + continue; + } + + if matchkeywd(buf, ".ids") { + Hdr->ids = DddmpIntArrayRead(fp,Hdr->nsuppvars); + Dddmp_CheckAndGotoLabel (Hdr->ids==NULL, + "Error allocating memory.", failure); + + continue; + } + + if (matchkeywd(buf, ".permids")) { + Hdr->permids = DddmpIntArrayRead(fp,Hdr->nsuppvars); + Dddmp_CheckAndGotoLabel (Hdr->permids==NULL, + "Error allocating memory.", failure); + + continue; + } + + if (matchkeywd(buf, ".auxids")) { + Hdr->auxids = DddmpIntArrayRead(fp,Hdr->nsuppvars); + Dddmp_CheckAndGotoLabel (Hdr->auxids==NULL, + "Error allocating memory.", failure); + + continue; + } + + if (matchkeywd(buf, ".nroots")) { + retValue = fscanf (fp, "%d", &(Hdr->nRoots)); + Dddmp_CheckAndGotoLabel (retValue==EOF, "Error reading file.", + failure); + + continue; + } + + if (matchkeywd(buf, ".rootids")) { + Hdr->rootids = DddmpIntArrayRead(fp,Hdr->nRoots); + Dddmp_CheckAndGotoLabel (Hdr->rootids==NULL, + "Error allocating memory.", failure); + + continue; + } + + if (matchkeywd(buf, ".rootnames")) { + Hdr->rootnames = DddmpStrArrayRead(fp,Hdr->nRoots); + Dddmp_CheckAndGotoLabel (Hdr->rootnames==NULL, + "Error allocating memory.", failure); + + continue; + } + + if (matchkeywd(buf, ".nodes")) { + fgets(buf,DDDMP_MAXSTRLEN,fp); + break; + } + + } + + /* END HEADER */ + + return (Hdr); + +failure: + + if (fileToClose == 1) { + fclose (fp); + } + + DddmpFreeHeader(Hdr); + + return (NULL); +} + + +/**Function******************************************************************** + + Synopsis [Frees the internal header structure.] + + Description [Frees the internal header structureby freeing all internal + fields first. + ] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ + +static void +DddmpFreeHeader ( + Dddmp_Hdr_t *Hdr /* IN: pointer to header */ + ) +{ + DDDMP_FREE (Hdr->ver); + DDDMP_FREE (Hdr->dd); + DddmpStrArrayFree (Hdr->orderedVarNames, Hdr->nVars); + DddmpStrArrayFree (Hdr->suppVarNames, Hdr->nsuppvars); + DDDMP_FREE (Hdr->ids); + DDDMP_FREE (Hdr->permids); + DDDMP_FREE (Hdr->auxids); + DDDMP_FREE (Hdr->rootids); + DddmpStrArrayFree (Hdr->rootnames, Hdr->nRoots); + + DDDMP_FREE (Hdr); + + return; +} + + + diff --git a/distr/dddmp/dddmpLoadCnf.c b/distr/dddmp/dddmpLoadCnf.c new file mode 100644 index 0000000..35bec27 --- /dev/null +++ b/distr/dddmp/dddmpLoadCnf.c @@ -0,0 +1,1072 @@ +/**CFile********************************************************************** + + FileName [dddmpLoadCnf.c] + + PackageName [dddmp] + + Synopsis [Functions to read in CNF from file as BDDs.] + + Description [Functions to read in CNF from file as BDDs. + ] + + Author [Gianpiero Cabodi and Stefano Quer] + + Copyright [ + Copyright (c) 2004 by Politecnico di Torino. + All Rights Reserved. This software is for educational purposes only. + Permission is given to academic institutions to use, copy, and modify + this software and its documentation provided that this introductory + message is not removed, that this software and its documentation is + used for the institutions' internal research and educational purposes, + and that no monies are exchanged. No guarantee is expressed or implied + by the distribution of this code. + Send bug-reports and/or questions to: + {gianpiero.cabodi,stefano.quer}@polito.it. + ] + +******************************************************************************/ + +#include "dddmpInt.h" + +/*---------------------------------------------------------------------------*/ +/* Constant declarations */ +/*---------------------------------------------------------------------------*/ + +#define DDDMP_MAX_CNF_ROW_LENGTH 1000 +#define DDDMP_DEBUG_CNF 0 + +/*---------------------------------------------------------------------------*/ +/* Stucture declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Type declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Variable declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Macro declarations */ +/*---------------------------------------------------------------------------*/ + +#define matchkeywd(str,key) (strncmp(str,key,strlen(key))==0) + +/**AutomaticStart*************************************************************/ + +/*---------------------------------------------------------------------------*/ +/* Static function prototypes */ +/*---------------------------------------------------------------------------*/ + +static int DddmpCuddDdArrayLoadCnf(DdManager *ddMgr, Dddmp_RootMatchType rootmatchmode, char **rootmatchnames, Dddmp_VarMatchType varmatchmode, char **varmatchnames, int *varmatchauxids, int *varcomposeids, int mode, char *file, FILE *fp, DdNode ***rootsPtrPtr, int *nRoots); +static Dddmp_Hdr_t * DddmpBddReadHeaderCnf(char *file, FILE *fp); +static void DddmpFreeHeaderCnf(Dddmp_Hdr_t *Hdr); +static int DddmpReadCnfClauses(Dddmp_Hdr_t *Hdr, int ***cnfTable, FILE *fp); +static int DddmpCnfClauses2Bdd(Dddmp_Hdr_t *Hdr, DdManager *ddMgr, int **cnfTable, int mode, DdNode ***rootsPtrPtr); + +/**AutomaticEnd***************************************************************/ + +/*---------------------------------------------------------------------------*/ +/* Definition of exported functions */ +/*---------------------------------------------------------------------------*/ + +/**Function******************************************************************** + + Synopsis [Reads a dump file in a CNF format.] + + Description [Reads a dump file representing the argument BDD in a + CNF formula. + Dddmp_cuddBddArrayLoadCnf is used through a dummy array. + The results is returned in different formats depending on the + mode selection: + IFF mode == 0 Return the Clauses without Conjunction + IFF mode == 1 Return the sets of BDDs without Quantification + IFF mode == 2 Return the sets of BDDs AFTER Existential Quantification + ] + + SideEffects [A vector of pointers to DD nodes is allocated and freed.] + + SeeAlso [Dddmp_cuddBddLoad, Dddmp_cuddBddArrayLoad] + +******************************************************************************/ + +int +Dddmp_cuddBddLoadCnf ( + DdManager *ddMgr /* IN: DD Manager */, + Dddmp_VarMatchType varmatchmode /* IN: storing mode selector */, + char **varmatchnames /* IN: array of variable names, by IDs */, + int *varmatchauxids /* IN: array of variable auxids, by IDs */, + int *varcomposeids /* IN: array of new ids accessed, by IDs */, + int mode /* IN: computation mode */, + char *file /* IN: file name */, + FILE *fp /* IN: file pointer */, + DdNode ***rootsPtrPtr /* OUT: array of returned BDD roots */, + int *nRoots /* OUT: number of BDDs returned */ + ) +{ + int i, retValue; + + retValue = Dddmp_cuddBddArrayLoadCnf (ddMgr, DDDMP_ROOT_MATCHLIST, NULL, + varmatchmode, varmatchnames, varmatchauxids, varcomposeids, mode, + file, fp, rootsPtrPtr, nRoots); + + if (retValue == DDDMP_FAILURE) { + return (DDDMP_FAILURE); + } + + if (*nRoots > 1) { + fprintf (stderr, + "Warning: %d BDD roots found in file. Only first retrieved.\n", + *nRoots); + for (i=1; i<*nRoots; i++) { + Cudd_RecursiveDeref (ddMgr, *rootsPtrPtr[i]); + } + } + + return (DDDMP_SUCCESS); +} + +/**Function******************************************************************** + + Synopsis [Reads a dump file in a CNF format.] + + Description [Reads a dump file representing the argument BDD in a + CNF formula. + ] + + SideEffects [A vector of pointers to DD nodes is allocated and freed.] + + SeeAlso [Dddmp_cuddBddArrayLoad] + +******************************************************************************/ + +int +Dddmp_cuddBddArrayLoadCnf ( + DdManager *ddMgr /* IN: DD Manager */, + Dddmp_RootMatchType rootmatchmode/* IN: storing mode selector */, + char **rootmatchnames /* IN: sorted names for loaded roots */, + Dddmp_VarMatchType varmatchmode /* IN: storing mode selector */, + char **varmatchnames /* IN: array of variable names, by IDs */, + int *varmatchauxids /* IN: array of variable auxids, by IDs */, + int *varcomposeids /* IN: array of new ids, by IDs */, + int mode /* IN: computation Mode */, + char *file /* IN: file name */, + FILE *fp /* IN: file pointer */, + DdNode ***rootsPtrPtr /* OUT: array of returned BDD roots */, + int *nRoots /* OUT: number of BDDs returned */ + ) +{ + int retValue; + +#ifdef DDDMP_DEBUG +#ifndef __alpha__ + int retValueBis; + + retValueBis = Cudd_DebugCheck (ddMgr); + if (retValueBis == 1) { + fprintf (stderr, "Inconsistency Found During CNF Load.\n"); + fflush (stderr); + } else { + if (retValueBis == CUDD_OUT_OF_MEM) { + fprintf (stderr, "Out of Memory During CNF Load.\n"); + fflush (stderr); + } + } +#endif +#endif + + retValue = DddmpCuddDdArrayLoadCnf (ddMgr, rootmatchmode, + rootmatchnames, varmatchmode, varmatchnames, varmatchauxids, + varcomposeids, mode, file, fp, rootsPtrPtr, nRoots); + +#ifdef DDDMP_DEBUG +#ifndef __alpha__ + retValueBis = Cudd_DebugCheck (ddMgr); + if (retValueBis == 1) { + fprintf (stderr, "Inconsistency Found During CNF Load.\n"); + fflush (stderr); + } else { + if (retValueBis == CUDD_OUT_OF_MEM) { + fprintf (stderr, "Out of Memory During CNF Load.\n"); + fflush (stderr); + } + } +#endif +#endif + + return (retValue); +} + +/**Function******************************************************************** + + Synopsis [Reads the header of a dump file representing the argument BDDs] + + Description [Reads the header of a dump file representing the argument BDDs. + Returns main information regarding DD type stored in the file, + the variable ordering used, the number of variables, etc. + It reads only the header of the file NOT the BDD/ADD section. + ] + + SideEffects [] + + SeeAlso [Dddmp_cuddBddArrayLoad] + +******************************************************************************/ + +int +Dddmp_cuddHeaderLoadCnf ( + int *nVars /* OUT: number of DD variables */, + int *nsuppvars /* OUT: number of support variables */, + char ***suppVarNames /* OUT: array of support variable names */, + char ***orderedVarNames /* OUT: array of variable names */, + int **varIds /* OUT: array of variable ids */, + int **varComposeIds /* OUT: array of permids ids */, + int **varAuxIds /* OUT: array of variable aux ids */, + int *nRoots /* OUT: number of root in the file */, + char *file /* IN: file name */, + FILE *fp /* IN: file pointer */ + ) +{ + Dddmp_Hdr_t *Hdr; + int i, fileToClose; + char **tmpOrderedVarNames = NULL; + char **tmpSuppVarNames = NULL; + int *tmpVarIds = NULL; + int *tmpVarComposeIds = NULL; + int *tmpVarAuxIds = NULL; + + fileToClose = 0; + if (fp == NULL) { + fp = fopen (file, "r"); + Dddmp_CheckAndGotoLabel (fp==NULL, "Error opening file.", + failure); + fileToClose = 1; + } + + Hdr = DddmpBddReadHeaderCnf (NULL, fp); + + Dddmp_CheckAndGotoLabel (Hdr->nnodes==0, "Zero number of nodes.", + failure); + + /* + * Number of variables (tot and support) + */ + + *nVars = Hdr->nVars; + *nsuppvars = Hdr->nsuppvars; + + /* + * Support Varnames + */ + + if (Hdr->suppVarNames != NULL) { + tmpSuppVarNames = DDDMP_ALLOC (char *, *nsuppvars); + Dddmp_CheckAndGotoLabel (tmpSuppVarNames==NULL, "Error allocating memory.", + failure); + + for (i=0; i<*nsuppvars; i++) { + tmpSuppVarNames[i] = DDDMP_ALLOC (char, + (strlen (Hdr->suppVarNames[i]) + 1)); + Dddmp_CheckAndGotoLabel (Hdr->suppVarNames[i]==NULL, + "Support Variable Name Missing in File.", failure); + strcpy (tmpSuppVarNames[i], Hdr->suppVarNames[i]); + } + + *suppVarNames = tmpSuppVarNames; + } else { + *suppVarNames = NULL; + } + + /* + * Ordered Varnames + */ + + if (Hdr->orderedVarNames != NULL) { + tmpOrderedVarNames = DDDMP_ALLOC (char *, *nVars); + Dddmp_CheckAndGotoLabel (tmpOrderedVarNames==NULL, + "Error allocating memory.", failure); + + for (i=0; i<*nVars; i++) { + tmpOrderedVarNames[i] = DDDMP_ALLOC (char, + (strlen (Hdr->orderedVarNames[i]) + 1)); + Dddmp_CheckAndGotoLabel (Hdr->orderedVarNames[i]==NULL, + "Support Variable Name Missing in File.", failure); + strcpy (tmpOrderedVarNames[i], Hdr->orderedVarNames[i]); + } + + *orderedVarNames = tmpOrderedVarNames; + } else { + *orderedVarNames = NULL; + } + + /* + * Variable Ids + */ + + if (Hdr->ids != NULL) { + tmpVarIds = DDDMP_ALLOC (int, *nsuppvars); + Dddmp_CheckAndGotoLabel (tmpVarIds==NULL, "Error allocating memory.", + failure); + for (i=0; i<*nsuppvars; i++) { + tmpVarIds[i] = Hdr->ids[i]; + } + + *varIds = tmpVarIds; + } else { + *varIds = NULL; + } + + /* + * Variable Compose Ids + */ + + if (Hdr->permids != NULL) { + tmpVarComposeIds = DDDMP_ALLOC (int, *nsuppvars); + Dddmp_CheckAndGotoLabel (tmpVarComposeIds==NULL, + "Error allocating memory.", failure); + for (i=0; i<*nsuppvars; i++) { + tmpVarComposeIds[i] = Hdr->permids[i]; + } + + *varComposeIds = tmpVarComposeIds; + } else { + *varComposeIds = NULL; + } + + /* + * Variable Auxiliary Ids + */ + + if (Hdr->auxids != NULL) { + tmpVarAuxIds = DDDMP_ALLOC (int, *nsuppvars); + Dddmp_CheckAndGotoLabel (tmpVarAuxIds==NULL, + "Error allocating memory.", failure); + for (i=0; i<*nsuppvars; i++) { + tmpVarAuxIds[i] = Hdr->auxids[i]; + } + + *varAuxIds = tmpVarAuxIds; + } else { + *varAuxIds = NULL; + } + + /* + * Number of roots + */ + + *nRoots = Hdr->nRoots; + + /* + * Free and Return + */ + + if (fileToClose == 1) { + fclose (fp); + } + + DddmpFreeHeaderCnf (Hdr); + + return (DDDMP_SUCCESS); + + failure: + return (DDDMP_FAILURE); +} + +/*---------------------------------------------------------------------------*/ +/* Definition of internal functions */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Definition of static functions */ +/*---------------------------------------------------------------------------*/ + +/**Function******************************************************************** + + Synopsis [Reads a dump file representing the argument BDDs in CNF + format. + ] + + Description [Reads a dump file representing the argument BDDs in CNF + format. + IFF mode == 0 Return the Clauses without Conjunction + IFF mode == 1 Return the sets of BDDs without Quantification + IFF mode == 2 Return the sets of BDDs AFTER Existential Quantification + ] + + SideEffects [A vector of pointers to DD nodes is allocated and freed.] + + SeeAlso [Dddmp_cuddBddArrayLoad] + +******************************************************************************/ + +static int +DddmpCuddDdArrayLoadCnf ( + DdManager *ddMgr /* IN: DD Manager */, + Dddmp_RootMatchType rootmatchmode/* IN: storing mode selector */, + char **rootmatchnames /* IN: sorted names for loaded roots */, + Dddmp_VarMatchType varmatchmode /* IN: storing mode selector */, + char **varmatchnames /* IN: array of variable names, by ids */, + int *varmatchauxids /* IN: array of variable auxids, by ids */, + int *varcomposeids /* IN: array of new ids, by ids */, + int mode /* IN: computation mode */, + char *file /* IN: file name */, + FILE *fp /* IN: file pointer */, + DdNode ***rootsPtrPtr /* OUT: array of BDD roots */, + int *nRoots /* OUT: number of BDDs returned */ + ) +{ + Dddmp_Hdr_t *Hdr = NULL; + int **cnfTable = NULL; + int fileToClose = 0; + int retValue, i; + + fileToClose = 0; + *rootsPtrPtr = NULL; + + if (fp == NULL) { + fp = fopen (file, "r"); + Dddmp_CheckAndGotoLabel (fp==NULL, "Error opening file.", + failure); + fileToClose = 1; + } + + /*--------------------------- Read the Header -----------------------------*/ + + Hdr = DddmpBddReadHeaderCnf (NULL, fp); + + Dddmp_CheckAndGotoLabel (Hdr->nnodes==0, "Zero number of nodes.", + failure); + + /*------------------------ Read the CNF Clauses ---------------------------*/ + + retValue = DddmpReadCnfClauses (Hdr, &cnfTable, fp); + + Dddmp_CheckAndGotoLabel (retValue==DDDMP_FAILURE, + "Read CNF Clauses Failure.", failure); + + /*------------------------- From Clauses to BDDs --------------------------*/ + + retValue = DddmpCnfClauses2Bdd (Hdr, ddMgr, cnfTable, mode, rootsPtrPtr); + + Dddmp_CheckAndGotoLabel (retValue==DDDMP_FAILURE, + "CNF Clauses To BDDs Failure.", failure); + + *nRoots = Hdr->nRoots; + + if (fileToClose) { + fclose (fp); + } + + for (i=0; inClausesCnf; i++) { + DDDMP_FREE (cnfTable[i]); + } + DDDMP_FREE (cnfTable); + + DddmpFreeHeaderCnf (Hdr); + + return (DDDMP_SUCCESS); + + /* + * Failure Condition + */ + +failure: + + if (fileToClose) { + fclose (fp); + } + + for (i=0; inClausesCnf; i++) { + DDDMP_FREE (cnfTable[i]); + } + DDDMP_FREE (cnfTable); + + DddmpFreeHeaderCnf (Hdr); + + /* return 0 on error ! */ + nRoots = 0; + + return (DDDMP_FAILURE); +} + +/**Function******************************************************************** + + Synopsis [Reads a the header of a dump file representing the argument + BDDs. + ] + + Description [Reads the header of a dump file. Builds a Dddmp_Hdr_t struct + containing all infos in the header, for next manipulations. + ] + + SideEffects [none] + + SeeAlso [] + +******************************************************************************/ + +static Dddmp_Hdr_t * +DddmpBddReadHeaderCnf ( + char *file /* IN: file name */, + FILE *fp /* IN: file pointer */ + ) +{ + Dddmp_Hdr_t *Hdr = NULL; + char buf[DDDMP_MAXSTRLEN]; + int nv, nc, retValue, fileToClose = 0; + + if (fp == NULL) { + fp = fopen (file, "r"); + Dddmp_CheckAndGotoLabel (fp==NULL, "Error opening file.", + failure); + fileToClose = 1; + } + + /* Start Header */ + Hdr = DDDMP_ALLOC (Dddmp_Hdr_t, 1); + if (Hdr == NULL) { + return NULL; + } + + Hdr->ver = NULL; + Hdr->mode = 0; + Hdr->ddType = DDDMP_CNF; + Hdr->varinfo = DDDMP_VARIDS; + Hdr->dd = NULL; + Hdr->nnodes = 0; + Hdr->nVars = 0; + Hdr->nsuppvars = 0; + Hdr->orderedVarNames = NULL; + Hdr->suppVarNames = NULL; + Hdr->ids = NULL; + Hdr->permids = NULL; + Hdr->auxids = NULL; + Hdr->cnfids = NULL; + Hdr->nRoots = 0; + Hdr->rootids = NULL; + Hdr->rootnames = NULL; + Hdr->nAddedCnfVar = 0; + Hdr->nVarsCnf = 0; + Hdr->nClausesCnf = 0; + + while (fscanf (fp, "%s", buf) != EOF) { + + /* Init Problem Line */ + if (buf[0] == 'p') { + fscanf (fp, "%*s %d %d", &nv, &nc); + Hdr->nVarsCnf = nv; + Hdr->nClausesCnf = nc; + break; + } + + /* CNF Comment Line */ + if (buf[0] == 'c') { + if (fscanf (fp, "%s", buf) == EOF) { + break; + } + } + + /* Skip Comment? */ + if (buf[0] != '.') { + fgets (buf, DDDMP_MAXSTRLEN, fp); + continue; + } + + if (matchkeywd (buf, ".ver")) { + /* this not checked so far: only read */ + retValue = fscanf (fp, "%s", buf); + Dddmp_CheckAndGotoLabel (retValue==EOF, "Error reading from file.", + failure); + + Hdr->ver=DddmpStrDup(buf); + Dddmp_CheckAndGotoLabel (Hdr->ver==NULL, + "Error allocating memory.", failure); + + continue; + } + + if (matchkeywd (buf, ".dd")) { + retValue = fscanf (fp, "%s", buf); + Dddmp_CheckAndGotoLabel (retValue==EOF, "Error reading file.", + failure); + + Hdr->dd = DddmpStrDup (buf); + Dddmp_CheckAndGotoLabel (Hdr->dd==NULL, "Error allocating memory.", + failure); + + continue; + } + + if (matchkeywd (buf, ".nnodes")) { + retValue = fscanf (fp, "%d", &(Hdr->nnodes)); + Dddmp_CheckAndGotoLabel (retValue==EOF, "Error reading file.", + failure); + + continue; + } + + if (matchkeywd (buf, ".nvars")) { + retValue = fscanf (fp, "%d", &(Hdr->nVars)); + Dddmp_CheckAndGotoLabel (retValue==EOF, "Error reading file.", + failure); + + continue; + } + + if (matchkeywd (buf, ".nsuppvars")) { + retValue = fscanf (fp, "%d", &(Hdr->nsuppvars)); + Dddmp_CheckAndGotoLabel (retValue==EOF, "Error reading file.", + failure); + + continue; + } + + if (matchkeywd (buf, ".orderedvarnames")) { + Hdr->orderedVarNames = DddmpStrArrayRead (fp, Hdr->nVars); + Dddmp_CheckAndGotoLabel (Hdr->orderedVarNames==NULL, + "Error allocating memory.", failure); + + continue; + } + + if (matchkeywd (buf, ".suppvarnames")) { + Hdr->suppVarNames = DddmpStrArrayRead (fp, Hdr->nsuppvars); + Dddmp_CheckAndGotoLabel (Hdr->suppVarNames==NULL, + "Error allocating memory.", failure); + + continue; + } + + if matchkeywd (buf, ".ids") { + Hdr->ids = DddmpIntArrayRead(fp,Hdr->nsuppvars); + Dddmp_CheckAndGotoLabel (Hdr->ids==NULL, + "Error allocating memory.", failure); + + continue; + } + + if (matchkeywd (buf, ".permids")) { + Hdr->permids = DddmpIntArrayRead(fp,Hdr->nsuppvars); + Dddmp_CheckAndGotoLabel (Hdr->permids==NULL, + "Error allocating memory.", failure); + + continue; + } + + if (matchkeywd (buf, ".auxids")) { + Hdr->auxids = DddmpIntArrayRead(fp,Hdr->nsuppvars); + Dddmp_CheckAndGotoLabel (Hdr->auxids==NULL, + "Error allocating memory.", failure); + + continue; + } + + if (matchkeywd (buf, ".cnfids")) { + Hdr->cnfids = DddmpIntArrayRead (fp, Hdr->nsuppvars); + Dddmp_CheckAndGotoLabel (Hdr->cnfids==NULL, + "Error allocating memory.", failure); + + continue; + } + + if (matchkeywd (buf, ".nroots")) { + retValue = fscanf (fp, "%d", &(Hdr->nRoots)); + Dddmp_CheckAndGotoLabel (retValue==EOF, "Error reading file.", + failure); + + continue; + } + + if (matchkeywd (buf, ".rootids")) { + Hdr->rootids = DddmpIntArrayRead(fp,Hdr->nRoots); + Dddmp_CheckAndGotoLabel (Hdr->rootids==NULL, + "Error allocating memory.", failure); + + continue; + } + + if (matchkeywd (buf, ".rootnames")) { + Hdr->rootnames = DddmpStrArrayRead(fp,Hdr->nRoots); + Dddmp_CheckAndGotoLabel (Hdr->rootnames==NULL, + "Error allocating memory.", failure); + + continue; + } + + + if (matchkeywd (buf, ".nAddedCnfVar")) { + retValue = fscanf (fp, "%d", &(Hdr->nAddedCnfVar)); + Dddmp_CheckAndGotoLabel (retValue==EOF, "Error reading file.", + failure); + + continue; + } + } + + /* END HEADER */ + return (Hdr); + +failure: + + if (fileToClose == 1) { + fclose (fp); + } + + DddmpFreeHeaderCnf (Hdr); + + return (NULL); +} + + +/**Function******************************************************************** + + Synopsis [Frees the internal header structure.] + + Description [Frees the internal header structure by freeing all internal + fields first. + ] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ + +static void +DddmpFreeHeaderCnf ( + Dddmp_Hdr_t *Hdr /* IN: pointer to header */ + ) +{ + if (Hdr==NULL) { + return; + } + + DDDMP_FREE (Hdr->ver); + DDDMP_FREE (Hdr->dd); + DddmpStrArrayFree (Hdr->orderedVarNames, Hdr->nVars); + DddmpStrArrayFree (Hdr->suppVarNames, Hdr->nsuppvars); + DDDMP_FREE (Hdr->ids); + DDDMP_FREE (Hdr->permids); + DDDMP_FREE (Hdr->auxids); + DDDMP_FREE (Hdr->cnfids); + DDDMP_FREE (Hdr->rootids); + DddmpStrArrayFree (Hdr->rootnames, Hdr->nRoots); + + DDDMP_FREE (Hdr); + + return; +} + +/**Function******************************************************************** + + Synopsis [Read the CNF clauses from the file in the standard DIMACS + format. + ] + + Description [Read the CNF clauses from the file in the standard DIMACS + format. Store all the clauses in an internal structure for + future transformation into BDDs. + ] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ + +static int +DddmpReadCnfClauses ( + Dddmp_Hdr_t *Hdr /* IN: file header */, + int ***cnfTable /* OUT: CNF table for clauses */, + FILE *fp /* IN: source file */ + ) +{ + char word[DDDMP_MAX_CNF_ROW_LENGTH]; + int i, j, var; + int **cnfTableLocal = NULL; + int *clause = NULL; + + cnfTableLocal = DDDMP_ALLOC (int *, Hdr->nClausesCnf); + clause = DDDMP_ALLOC (int, 2*Hdr->nVarsCnf+1); + + for (i=0; inClausesCnf; i++) { + cnfTableLocal[i] = NULL; + } + + for (i=0; i<=2*Hdr->nVarsCnf; i++) { + clause[i] = 0; + } + + i = j = 0; + do { + if (fscanf(fp, "%s", word)==EOF) { + if (j>0) { + /* force last zero */ + strcpy(word,"0"); + } + else break; + } + + /* Check for Comment */ + if (word[0] == 'c') { + /* Comment Found: Skip line */ + fgets (word, DDDMP_MAX_CNF_ROW_LENGTH-1, fp); + break; + } + + var = atoi (word); + Dddmp_Assert ((var>=(-Hdr->nVarsCnf))&&(var<=Hdr->nVarsCnf), + "Wrong num found"); + clause[j++] = var; + if (var == 0) { + cnfTableLocal[i] = DDDMP_ALLOC (int, j); + while (--j >=0) { + cnfTableLocal[i][j] = clause[j]; + } + i++; + j=0; + } + + } while (!feof(fp)); + + Dddmp_Assert (i==Hdr->nClausesCnf, + "Wrong number of clauses in file"); + +#if DDDMP_DEBUG_CNF + for (i=0; inClausesCnf; i++) { + fprintf (stdout, "[%4d] ", i); + j=0; + while ((var = cnfTableLocal[i][j++]) != 0) { + fprintf (stdout, "%d ", var); + } + fprintf (stdout, "0\n"); + } +#endif + + DDDMP_FREE (clause); + + *cnfTable = cnfTableLocal; + + return (DDDMP_SUCCESS); +} + +/**Function******************************************************************** + + Synopsis [Transforms CNF clauses into BDDs.] + + Description [Transforms CNF clauses into BDDs. Clauses are stored in an + internal structure previously read. The results can be given in + different format according to the mode selection: + IFF mode == 0 Return the Clauses without Conjunction + IFF mode == 1 Return the sets of BDDs without Quantification + IFF mode == 2 Return the sets of BDDs AFTER Existential Quantification + ] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ + +static int +DddmpCnfClauses2Bdd ( + Dddmp_Hdr_t *Hdr /* IN: file header */, + DdManager *ddMgr /* IN: DD Manager */, + int **cnfTable /* IN: CNF table for clauses */, + int mode /* IN: computation mode */, + DdNode ***rootsPtrPtr /* OUT: array of returned BDD roots (by reference) */ + ) +{ + DdNode **rel = NULL; + DdNode *lit = NULL; + DdNode *tmp1 = NULL; + DdNode *tmp2 = NULL; + DdNode **rootsPtr = NULL; + DdNode *cubeAllVar = NULL; + DdNode *cubeBddVar = NULL; + DdNode *cubeCnfVar = NULL; + int i, j, k, n, var1, var2, fromLine, toLine; + + rootsPtr = NULL; + *rootsPtrPtr = NULL; + + /*-------------------------- Read The Clauses -----------------------------*/ + + rel = DDDMP_ALLOC (DdNode *, Hdr->nClausesCnf); + + cubeBddVar = Cudd_ReadOne (ddMgr); + cubeCnfVar = Cudd_ReadOne (ddMgr); + cubeAllVar = Cudd_ReadOne (ddMgr); + Cudd_Ref (cubeBddVar); + Cudd_Ref (cubeCnfVar); + Cudd_Ref (cubeAllVar); + + for (i=0; inClausesCnf; i++) { + rel[i] = Cudd_Not (Cudd_ReadOne (ddMgr)); + Cudd_Ref (rel[i]); + j=0; + while ((var1 = cnfTable[i][j++]) != 0) { + + /* Deal with the Literal */ + var2 = abs (var1); + n = (-1); + for (k=0; knsuppvars; k++) { + if (Hdr->cnfids[k] == var2) { + n = k; + break; + } + } + + if (n == (-1)) { + lit = Cudd_bddIthVar (ddMgr, var2); + + /* Create the cubes of CNF Variables */ + tmp1 = Cudd_bddAnd (ddMgr, cubeCnfVar, lit); + Cudd_Ref (tmp1); + Cudd_RecursiveDeref (ddMgr, cubeCnfVar); + cubeCnfVar = tmp1; + + } else { + lit = Cudd_bddIthVar (ddMgr, Hdr->ids[n]); + + /* Create the cubes of BDD Variables */ + tmp1 = Cudd_bddAnd (ddMgr, cubeBddVar, lit); + Cudd_Ref (tmp1); + Cudd_RecursiveDeref (ddMgr, cubeBddVar); + cubeBddVar = tmp1; + } + + /* Create the cubes of ALL Variables */ + tmp1 = Cudd_bddAnd (ddMgr, cubeAllVar, lit); + Cudd_Ref (tmp1); + Cudd_RecursiveDeref (ddMgr, cubeAllVar); + cubeAllVar = tmp1; + + /* Deal with Relations */ + if (var1<0) { + lit = Cudd_Not (lit); + } + tmp1 = Cudd_bddOr (ddMgr, rel[i], lit); + Cudd_Ref (tmp1); + Cudd_RecursiveDeref (ddMgr, rel[i]); + rel[i] = tmp1; + } + } + + /* + * Mode == 0 Return the Clauses without Conjunction + */ + + if (mode == 0) { + return (DDDMP_SUCCESS); + } + + rootsPtr = DDDMP_ALLOC (DdNode *, Hdr->nRoots); + Dddmp_CheckAndGotoLabel (rootsPtr==NULL, "Error allocating memory.", + failure); + + for (i=0; inRoots; i++) { + if (i == (Hdr->nRoots-1)) { + fromLine = Hdr->rootids[i] - 1; + toLine = Hdr->nClausesCnf; + } else { + fromLine = Hdr->rootids[i] - 1; + toLine = Hdr->rootids[i+1]; + } + + tmp1 = Cudd_ReadOne (ddMgr); + Cudd_Ref (tmp1); + for (j=fromLine; jnsuppvars; i++) { + lit = Cudd_bddIthVar (ddMgr, Hdr->ids[i]); + tmp1 = Cudd_bddAnd (ddMgr, cubeBddVar, lit); + Cudd_Ref (tmp1); + Cudd_RecursiveDeref (ddMgr, cubeBddVar); + cubeBddVar = tmp1; + } + + cubeCnfVar = Cudd_bddExistAbstract (ddMgr, cubeAllVar, cubeBddVar); +#endif + + for (i=0; inRoots; i++) { +#if DDDMP_DEBUG_CNF + fprintf (stdout, "rootsPtr Before Exist:\n"); + Cudd_PrintDebug (ddMgr, rootsPtr[i], 0, 3); +#endif + + tmp1 = Cudd_bddExistAbstract (ddMgr, rootsPtr[i], cubeCnfVar); + Cudd_RecursiveDeref (ddMgr, rootsPtr[i]); + rootsPtr[i] = tmp1; + +#if DDDMP_DEBUG_CNF + fprintf (stdout, "rootsPtr After Exist:\n"); + Cudd_PrintDebug (ddMgr, rootsPtr[i], 0, 3); +#endif + } + +#if DDDMP_DEBUG_CNF + fprintf (stdout, "cubeAllVar:\n"); + Cudd_PrintDebug (ddMgr, cubeAllVar, 0, 3); + fprintf (stdout, "cubeBddVar:\n"); + Cudd_PrintDebug (ddMgr, cubeBddVar, 0, 3); + fprintf (stdout, "cubeCnfVar:\n"); + Cudd_PrintDebug (ddMgr, cubeCnfVar, 0, 3); +#endif + + Cudd_RecursiveDeref (ddMgr, cubeAllVar); + Cudd_RecursiveDeref (ddMgr, cubeBddVar); + Cudd_RecursiveDeref (ddMgr, cubeCnfVar); + *rootsPtrPtr = rootsPtr; + + return (DDDMP_SUCCESS); + + /* + * Failure Condition + */ + +failure: + + DDDMP_FREE (rel); + DDDMP_FREE (rootsPtrPtr); + + return (DDDMP_FAILURE); +} + + + + + + + + + + + diff --git a/distr/dddmp/dddmpNodeAdd.c b/distr/dddmp/dddmpNodeAdd.c new file mode 100644 index 0000000..6fca772 --- /dev/null +++ b/distr/dddmp/dddmpNodeAdd.c @@ -0,0 +1,451 @@ +/**CFile********************************************************************** + + FileName [dddmpNodeAdd.c] + + PackageName [dddmp] + + Synopsis [Functions to handle ADD node infos and numbering] + + Description [Functions to handle ADD node infos and numbering. + ] + + Author [Gianpiero Cabodi and Stefano Quer] + + Copyright [ + Copyright (c) 2004 by Politecnico di Torino. + All Rights Reserved. This software is for educational purposes only. + Permission is given to academic institutions to use, copy, and modify + this software and its documentation provided that this introductory + message is not removed, that this software and its documentation is + used for the institutions' internal research and educational purposes, + and that no monies are exchanged. No guarantee is expressed or implied + by the distribution of this code. + Send bug-reports and/or questions to: + {gianpiero.cabodi,stefano.quer}@polito.it. + ] + +******************************************************************************/ + +#include "dddmpInt.h" + +/*---------------------------------------------------------------------------*/ +/* Stucture declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Type declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Variable declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Macro declarations */ +/*---------------------------------------------------------------------------*/ + +/**AutomaticStart*************************************************************/ + +/*---------------------------------------------------------------------------*/ +/* Static function prototypes */ +/*---------------------------------------------------------------------------*/ + +static int NumberNodeRecurAdd(DdNode *f, int id); +static void RemoveFromUniqueRecurAdd(DdManager *ddMgr, DdNode *f); +static void RestoreInUniqueRecurAdd(DdManager *ddMgr, DdNode *f); + +/**AutomaticEnd***************************************************************/ + +/*---------------------------------------------------------------------------*/ +/* Definition of exported functions */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Definition of internal functions */ +/*---------------------------------------------------------------------------*/ + +/**Function******************************************************************** + + Synopsis [Removes nodes from unique table and number them] + + Description [Node numbering is required to convert pointers to integers. + Since nodes are removed from unique table, no new nodes should + be generated before re-inserting nodes in the unique table + (DddmpUnnumberDdNodes()). + ] + + SideEffects [Nodes are temporarily removed from unique table] + + SeeAlso [RemoveFromUniqueRecurAdd (), NumberNodeRecurAdd (), + DddmpUnnumberDdNodesAdd ()] + +******************************************************************************/ + +int +DddmpNumberAddNodes ( + DdManager *ddMgr /* IN: DD Manager */, + DdNode **f /* IN: array of BDDs */, + int n /* IN: number of BDD roots in the array of BDDs */ + ) +{ + int id=0, i; + + for (i=0; inext = (struct DdNode *)((ptruint)((id)<<1)); + } + + return; +} + +/**Function******************************************************************** + + Synopsis [Reads the index of a node] + + Description [Reads the index of a node. LSB is skipped (used as visited + flag). + ] + + SideEffects [None] + + SeeAlso [DddmpWriteNodeIndexAdd (), DddmpSetVisitedAdd (), + DddmpVisitedAdd ()] + +******************************************************************************/ + +int +DddmpReadNodeIndexAdd ( + DdNode *f /* IN: BDD node */ + ) +{ + if (1 || !Cudd_IsConstant (f)) { + return ((int)(((ptruint)(f->next))>>1)); + } else { + return (1); + } +} + +/**Function******************************************************************** + + Synopsis [Returns true if node is visited] + + Description [Returns true if node is visited] + + SideEffects [None] + + SeeAlso [DddmpSetVisitedAdd (), DddmpClearVisitedAdd ()] + +******************************************************************************/ + +int +DddmpVisitedAdd ( + DdNode *f /* IN: BDD node to be tested */ + ) +{ + f = Cudd_Regular(f); + return ((int)((ptruint)(f->next)) & (01)); +} + +/**Function******************************************************************** + + Synopsis [Marks a node as visited] + + Description [Marks a node as visited] + + SideEffects [None] + + SeeAlso [DddmpVisitedAdd (), DddmpClearVisitedAdd ()] + +******************************************************************************/ + +void +DddmpSetVisitedAdd ( + DdNode *f /* IN: BDD node to be marked (as visited) */ + ) +{ + f = Cudd_Regular(f); + + f->next = (DdNode *)(ptruint)((int)((ptruint)(f->next))|01); + + return; +} + +/**Function******************************************************************** + + Synopsis [Marks a node as not visited] + + Description [Marks a node as not visited] + + SideEffects [None] + + SeeAlso [DddmpVisitedAdd (), DddmpSetVisitedAdd ()] + +******************************************************************************/ + +void +DddmpClearVisitedAdd ( + DdNode *f /* IN: BDD node to be marked (as not visited) */ + ) +{ + f = Cudd_Regular (f); + + f->next = (DdNode *)(ptruint)((int)((ptruint)(f->next)) & (~01)); + + return; +} + +/*---------------------------------------------------------------------------*/ +/* Definition of static functions */ +/*---------------------------------------------------------------------------*/ + +/**Function******************************************************************** + + Synopsis [Number nodes recursively in post-order] + + Description [Number nodes recursively in post-order. + The "visited" flag is used with inverse polarity, because all nodes + were set "visited" when removing them from unique. + ] + + SideEffects ["visited" flags are reset.] + + SeeAlso [] + +******************************************************************************/ + +static int +NumberNodeRecurAdd ( + DdNode *f /* IN: root of the BDD to be numbered */, + int id /* IN/OUT: index to be assigned to the node */ + ) +{ + f = Cudd_Regular(f); + + if (!DddmpVisitedAdd (f)) { + return (id); + } + + if (!cuddIsConstant (f)) { + id = NumberNodeRecurAdd (cuddT (f), id); + id = NumberNodeRecurAdd (cuddE (f), id); + } + + DddmpWriteNodeIndexAdd (f, ++id); + DddmpClearVisitedAdd (f); + + return (id); +} + +/**Function******************************************************************** + + Synopsis [Removes a node from unique table] + + Description [Removes a node from the unique table by locating the proper + subtable and unlinking the node from it. It recurs on the + children of the node. Constants remain untouched. + ] + + SideEffects [Nodes are left with the "visited" flag true.] + + SeeAlso [RestoreInUniqueRecurAdd ()] + +******************************************************************************/ + +static void +RemoveFromUniqueRecurAdd ( + DdManager *ddMgr /* IN: DD Manager */, + DdNode *f /* IN: root of the BDD to be extracted */ + ) +{ + DdNode *node, *last, *next; + DdNode *sentinel = &(ddMgr->sentinel); + DdNodePtr *nodelist; + DdSubtable *subtable; + int pos, level; + + f = Cudd_Regular (f); + + if (DddmpVisitedAdd (f)) { + return; + } + + if (!cuddIsConstant (f)) { + + RemoveFromUniqueRecurAdd (ddMgr, cuddT (f)); + RemoveFromUniqueRecurAdd (ddMgr, cuddE (f)); + + level = ddMgr->perm[f->index]; + subtable = &(ddMgr->subtables[level]); + + nodelist = subtable->nodelist; + + pos = ddHash (cuddT (f), cuddE (f), subtable->shift); + node = nodelist[pos]; + last = NULL; + while (node != sentinel) { + next = node->next; + if (node == f) { + if (last != NULL) + last->next = next; + else + nodelist[pos] = next; + break; + } else { + last = node; + node = next; + } + } + + f->next = NULL; + + } + + DddmpSetVisitedAdd (f); + + return; +} + +/**Function******************************************************************** + + Synopsis [Restores a node in unique table] + + Description [Restores a node in unique table (recursively)] + + SideEffects [Nodes are not restored in the same order as before removal] + + SeeAlso [RemoveFromUniqueAdd ()] + +******************************************************************************/ + +static void +RestoreInUniqueRecurAdd ( + DdManager *ddMgr /* IN: DD Manager */, + DdNode *f /* IN: root of the BDD to be restored */ + ) +{ + DdNodePtr *nodelist; + DdNode *T, *E, *looking; + DdNodePtr *previousP; + DdSubtable *subtable; + int pos, level; +#ifdef DDDMP_DEBUG + DdNode *node; + DdNode *sentinel = &(ddMgr->sentinel); +#endif + + f = Cudd_Regular(f); + + if (!Cudd_IsComplement (f->next)) { + return; + } + + if (cuddIsConstant (f)) { + /* StQ 11.02.2004: + Bug fixed --> restore NULL within the next field */ + /*DddmpClearVisitedAdd (f);*/ + f->next = NULL; + + return; + } + + RestoreInUniqueRecurAdd (ddMgr, cuddT (f)); + RestoreInUniqueRecurAdd (ddMgr, cuddE (f)); + + level = ddMgr->perm[f->index]; + subtable = &(ddMgr->subtables[level]); + + nodelist = subtable->nodelist; + + pos = ddHash (cuddT (f), cuddE (f), subtable->shift); + +#ifdef DDDMP_DEBUG + /* verify uniqueness to avoid duplicate nodes in unique table */ + for (node=nodelist[pos]; node != sentinel; node=node->next) + assert(node!=f); +#endif + + T = cuddT (f); + E = cuddE (f); + previousP = &(nodelist[pos]); + looking = *previousP; + + while (T < cuddT (looking)) { + previousP = &(looking->next); + looking = *previousP; + } + + while (T == cuddT (looking) && E < cuddE (looking)) { + previousP = &(looking->next); + looking = *previousP; + } + + f->next = *previousP; + *previousP = f; + + return; +} + + diff --git a/distr/dddmp/dddmpNodeBdd.c b/distr/dddmp/dddmpNodeBdd.c new file mode 100644 index 0000000..17f7fe3 --- /dev/null +++ b/distr/dddmp/dddmpNodeBdd.c @@ -0,0 +1,452 @@ +/**CFile********************************************************************** + + FileName [dddmpNodeBdd.c] + + PackageName [dddmp] + + Synopsis [Functions to handle BDD node infos and numbering] + + Description [Functions to handle BDD node infos and numbering. + ] + + Author [Gianpiero Cabodi and Stefano Quer] + + Copyright [ + Copyright (c) 2004 by Politecnico di Torino. + All Rights Reserved. This software is for educational purposes only. + Permission is given to academic institutions to use, copy, and modify + this software and its documentation provided that this introductory + message is not removed, that this software and its documentation is + used for the institutions' internal research and educational purposes, + and that no monies are exchanged. No guarantee is expressed or implied + by the distribution of this code. + Send bug-reports and/or questions to: + {gianpiero.cabodi,stefano.quer}@polito.it. + ] + +******************************************************************************/ + +#include "dddmpInt.h" + +/*---------------------------------------------------------------------------*/ +/* Stucture declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Type declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Variable declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Macro declarations */ +/*---------------------------------------------------------------------------*/ + +/**AutomaticStart*************************************************************/ + +/*---------------------------------------------------------------------------*/ +/* Static function prototypes */ +/*---------------------------------------------------------------------------*/ + +static int NumberNodeRecurBdd(DdNode *f, int id); +static void RemoveFromUniqueRecurBdd(DdManager *ddMgr, DdNode *f); +static void RestoreInUniqueRecurBdd(DdManager *ddMgr, DdNode *f); + +/**AutomaticEnd***************************************************************/ + +/*---------------------------------------------------------------------------*/ +/* Definition of exported functions */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Definition of internal functions */ +/*---------------------------------------------------------------------------*/ + +/**Function******************************************************************** + + Synopsis [Removes nodes from unique table and number them] + + Description [Node numbering is required to convert pointers to integers. + Since nodes are removed from unique table, no new nodes should + be generated before re-inserting nodes in the unique table + (DddmpUnnumberBddNodes ()). + ] + + SideEffects [Nodes are temporarily removed from unique table] + + SeeAlso [RemoveFromUniqueRecur(), NumberNodeRecur(), + DddmpUnnumberBddNodes ()] + +******************************************************************************/ + +int +DddmpNumberBddNodes ( + DdManager *ddMgr /* IN: DD Manager */, + DdNode **f /* IN: array of BDDs */, + int n /* IN: number of BDD roots in the array of BDDs */ + ) +{ + int id=0, i; + + for (i=0; inext = (struct DdNode *)((ptruint)((id)<<1)); + } + + return; +} + +/**Function******************************************************************** + + Synopsis [Reads the index of a node] + + Description [Reads the index of a node. LSB is skipped (used as visited + flag). + ] + + SideEffects [None] + + SeeAlso [DddmpWriteNodeIndexBdd (), DddmpSetVisitedBdd (), + DddmpVisitedBdd ()] + +******************************************************************************/ + +int +DddmpReadNodeIndexBdd ( + DdNode *f /* IN: BDD node */ + ) +{ + if (!Cudd_IsConstant (f)) { + return ((int)(((ptruint)(f->next))>>1)); + } else { + return (1); + } +} + +/**Function******************************************************************** + + Synopsis [Returns true if node is visited] + + Description [Returns true if node is visited] + + SideEffects [None] + + SeeAlso [DddmpSetVisitedBdd (), DddmpClearVisitedBdd ()] + +******************************************************************************/ + +int +DddmpVisitedBdd ( + DdNode *f /* IN: BDD node to be tested */ + ) +{ + f = Cudd_Regular(f); + + return ((int)((ptruint)(f->next)) & (01)); +} + +/**Function******************************************************************** + + Synopsis [Marks a node as visited] + + Description [Marks a node as visited] + + SideEffects [None] + + SeeAlso [DddmpVisitedBdd (), DddmpClearVisitedBdd ()] + +******************************************************************************/ + +void +DddmpSetVisitedBdd ( + DdNode *f /* IN: BDD node to be marked (as visited) */ + ) +{ + f = Cudd_Regular(f); + + f->next = (DdNode *)(ptruint)((int)((ptruint)(f->next))|01); + + return; +} + +/**Function******************************************************************** + + Synopsis [Marks a node as not visited] + + Description [Marks a node as not visited] + + SideEffects [None] + + SeeAlso [DddmpVisited (), DddmpSetVisited ()] + +******************************************************************************/ + +void +DddmpClearVisitedBdd ( + DdNode *f /* IN: BDD node to be marked (as not visited) */ + ) +{ + f = Cudd_Regular (f); + + f->next = (DdNode *)(ptruint)((int)((ptruint)(f->next)) & (~01)); + + return; +} + +/*---------------------------------------------------------------------------*/ +/* Definition of static functions */ +/*---------------------------------------------------------------------------*/ + +/**Function******************************************************************** + + Synopsis [Number nodes recursively in post-order] + + Description [Number nodes recursively in post-order. + The "visited" flag is used with inverse polarity, because all nodes + were set "visited" when removing them from unique. + ] + + SideEffects ["visited" flags are reset.] + + SeeAlso [] + +******************************************************************************/ + +static int +NumberNodeRecurBdd ( + DdNode *f /* IN: root of the BDD to be numbered */, + int id /* IN/OUT: index to be assigned to the node */ + ) +{ + f = Cudd_Regular (f); + + if (!DddmpVisitedBdd (f)) { + return (id); + } + + if (!cuddIsConstant (f)) { + id = NumberNodeRecurBdd (cuddT (f), id); + id = NumberNodeRecurBdd (cuddE (f), id); + } + + DddmpWriteNodeIndexBdd (f, ++id); + DddmpClearVisitedBdd (f); + + return (id); +} + +/**Function******************************************************************** + + Synopsis [Removes a node from unique table] + + Description [Removes a node from the unique table by locating the proper + subtable and unlinking the node from it. It recurs on the + children of the node. Constants remain untouched. + ] + + SideEffects [Nodes are left with the "visited" flag true.] + + SeeAlso [RestoreInUniqueRecurBdd ()] + +******************************************************************************/ + +static void +RemoveFromUniqueRecurBdd ( + DdManager *ddMgr /* IN: DD Manager */, + DdNode *f /* IN: root of the BDD to be extracted */ + ) +{ + DdNode *node, *last, *next; + DdNode *sentinel = &(ddMgr->sentinel); + DdNodePtr *nodelist; + DdSubtable *subtable; + int pos, level; + + f = Cudd_Regular (f); + + if (DddmpVisitedBdd (f)) { + return; + } + + if (!cuddIsConstant (f)) { + + RemoveFromUniqueRecurBdd (ddMgr, cuddT (f)); + RemoveFromUniqueRecurBdd (ddMgr, cuddE (f)); + + level = ddMgr->perm[f->index]; + subtable = &(ddMgr->subtables[level]); + + nodelist = subtable->nodelist; + + pos = ddHash (cuddT (f), cuddE (f), subtable->shift); + node = nodelist[pos]; + last = NULL; + while (node != sentinel) { + next = node->next; + if (node == f) { + if (last != NULL) + last->next = next; + else + nodelist[pos] = next; + break; + } else { + last = node; + node = next; + } + } + + f->next = NULL; + + } + + DddmpSetVisitedBdd (f); + + return; +} + +/**Function******************************************************************** + + Synopsis [Restores a node in unique table] + + Description [Restores a node in unique table (recursively)] + + SideEffects [Nodes are not restored in the same order as before removal] + + SeeAlso [RemoveFromUnique()] + +******************************************************************************/ + +static void +RestoreInUniqueRecurBdd ( + DdManager *ddMgr /* IN: DD Manager */, + DdNode *f /* IN: root of the BDD to be restored */ + ) +{ + DdNodePtr *nodelist; + DdNode *T, *E, *looking; + DdNodePtr *previousP; + DdSubtable *subtable; + int pos, level; +#ifdef DDDMP_DEBUG + DdNode *node; + DdNode *sentinel = &(ddMgr->sentinel); +#endif + + f = Cudd_Regular(f); + + if (!Cudd_IsComplement (f->next)) { + return; + } + + if (cuddIsConstant (f)) { + /* StQ 11.02.2004: + Bug fixed --> restore NULL within the next field */ + /*DddmpClearVisitedBdd (f);*/ + f->next = NULL; + + return; + } + + RestoreInUniqueRecurBdd (ddMgr, cuddT (f)); + RestoreInUniqueRecurBdd (ddMgr, cuddE (f)); + + level = ddMgr->perm[f->index]; + subtable = &(ddMgr->subtables[level]); + + nodelist = subtable->nodelist; + + pos = ddHash (cuddT (f), cuddE (f), subtable->shift); + +#ifdef DDDMP_DEBUG + /* verify uniqueness to avoid duplicate nodes in unique table */ + for (node=nodelist[pos]; node != sentinel; node=node->next) + assert(node!=f); +#endif + + T = cuddT (f); + E = cuddE (f); + previousP = &(nodelist[pos]); + looking = *previousP; + + while (T < cuddT (looking)) { + previousP = &(looking->next); + looking = *previousP; + } + + while (T == cuddT (looking) && E < cuddE (looking)) { + previousP = &(looking->next); + looking = *previousP; + } + + f->next = *previousP; + *previousP = f; + + return; +} + + diff --git a/distr/dddmp/dddmpNodeCnf.c b/distr/dddmp/dddmpNodeCnf.c new file mode 100644 index 0000000..fa61ace --- /dev/null +++ b/distr/dddmp/dddmpNodeCnf.c @@ -0,0 +1,932 @@ +/**CFile********************************************************************** + + FileName [dddmpNodeCnf.c] + + PackageName [dddmp] + + Synopsis [Functions to handle BDD node infos and numbering + while storing a CNF formula from a BDD or an array of BDDs] + + Description [Functions to handle BDD node infos and numbering + while storing a CNF formula from a BDD or an array of BDDs. + ] + + Author [Gianpiero Cabodi and Stefano Quer] + + Copyright [ + Copyright (c) 2004 by Politecnico di Torino. + All Rights Reserved. This software is for educational purposes only. + Permission is given to academic institutions to use, copy, and modify + this software and its documentation provided that this introductory + message is not removed, that this software and its documentation is + used for the institutions' internal research and educational purposes, + and that no monies are exchanged. No guarantee is expressed or implied + by the distribution of this code. + Send bug-reports and/or questions to: + {gianpiero.cabodi,stefano.quer}@polito.it. + ] + +******************************************************************************/ + +#include "dddmpInt.h" + +/*---------------------------------------------------------------------------*/ +/* Stucture declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Type declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Variable declarations */ +/*---------------------------------------------------------------------------*/ + +#define DDDMP_DEBUG_CNF 0 + +/*---------------------------------------------------------------------------*/ +/* Macro declarations */ +/*---------------------------------------------------------------------------*/ + +/**AutomaticStart*************************************************************/ + +/*---------------------------------------------------------------------------*/ +/* Static function prototypes */ +/*---------------------------------------------------------------------------*/ + +static int DddmpWriteNodeIndexCnfWithTerminalCheck(DdNode *f, int *cnfIds, int id); +static int DddmpClearVisitedCnfRecur(DdNode *f); +static void DddmpClearVisitedCnf(DdNode *f); +static int NumberNodeRecurCnf(DdNode *f, int *cnfIds, int id); +static void DddmpDdNodesCheckIncomingAndScanPath(DdNode *f, int pathLengthCurrent, int edgeInTh, int pathLengthTh); +static int DddmpDdNodesNumberEdgesRecur(DdNode *f, int *cnfIds, int id); +static int DddmpDdNodesResetCountRecur(DdNode *f); +static int DddmpDdNodesCountEdgesRecur(DdNode *f); +static void RemoveFromUniqueRecurCnf(DdManager *ddMgr, DdNode *f); +static void RestoreInUniqueRecurCnf(DdManager *ddMgr, DdNode *f); +static int DddmpPrintBddAndNextRecur(DdManager *ddMgr, DdNode *f); + +/**AutomaticEnd***************************************************************/ + +/*---------------------------------------------------------------------------*/ +/* Definition of exported functions */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Definition of internal functions */ +/*---------------------------------------------------------------------------*/ + +/**Function******************************************************************** + + Synopsis [Removes nodes from unique table and numbers them] + + Description [Node numbering is required to convert pointers to integers. + Since nodes are removed from unique table, no new nodes should + be generated before re-inserting nodes in the unique table + (DddmpUnnumberDdNodesCnf()). + ] + + SideEffects [Nodes are temporarily removed from unique table] + + SeeAlso [RemoveFromUniqueRecurCnf(), NumberNodeRecurCnf(), + DddmpUnnumberDdNodesCnf()] + +******************************************************************************/ + +int +DddmpNumberDdNodesCnf ( + DdManager *ddMgr /* IN: DD Manager */, + DdNode **f /* IN: array of BDDs */, + int rootN /* IN: number of BDD roots in the array of BDDs */, + int *cnfIds /* OUT: CNF identifiers for variables */, + int id /* OUT: number of Temporary Variables Introduced */ + ) +{ + int i; + + for (i=0; i BDDs After Count Reset:\n"); + DddmpPrintBddAndNext (ddMgr, f, rootN); +#endif + + /*----------------------- Count Incoming Edges ----------------------------*/ + + for (i=0; i BDDs After Count Recur:\n"); + DddmpPrintBddAndNext (ddMgr, f, rootN); +#endif + + /*------------------------- Count Path Length ----------------------------*/ + + for (i=0; i BDDs After Check Incoming And Scan Path:\n"); + DddmpPrintBddAndNext (ddMgr, f, rootN); +#endif + + /*-------------------- Number Nodes and Set Visited -----------------------*/ + + for (i=0; i BDDs After Count Edges Recur:\n"); + DddmpPrintBddAndNext (ddMgr, f, rootN); +#endif + + return (id); +} + +/**Function******************************************************************** + + Synopsis [Restores nodes in unique table, loosing numbering] + + Description [Node indexes are no more needed. Nodes are re-linked in the + unique table. + ] + + SideEffects [None] + + SeeAlso [DddmpNumberDdNode()] + +******************************************************************************/ + +void +DddmpUnnumberDdNodesCnf( + DdManager *ddMgr /* IN: DD Manager */, + DdNode **f /* IN: array of BDDs */, + int rootN /* IN: number of BDD roots in the array of BDDs */ + ) +{ + int i; + + for (i=0; i Bdd %d:\n", i); + fflush (stdout); + DddmpPrintBddAndNextRecur (ddMgr, f[i]); + } + + return (DDDMP_SUCCESS); +} + +/**Function******************************************************************** + + Synopsis [Write index to node] + + Description [The index of the node is written in the "next" field of + a DdNode struct. LSB is not used (set to 0). It is used as + "visited" flag in DD traversals. + ] + + SideEffects [None] + + SeeAlso [DddmpReadNodeIndexCnf(), DddmpSetVisitedCnf (), + DddmpVisitedCnf () + ] + +******************************************************************************/ + +int +DddmpWriteNodeIndexCnf ( + DdNode *f /* IN: BDD node */, + int id /* IN: index to be written */ + ) +{ + if (!Cudd_IsConstant (f)) { + f->next = (struct DdNode *)((ptruint)((id)<<1)); + } + + return (DDDMP_SUCCESS); +} + +/**Function******************************************************************** + + Synopsis [Returns true if node is visited] + + Description [Returns true if node is visited] + + SideEffects [None] + + SeeAlso [DddmpSetVisitedCnf (), DddmpClearVisitedCnf ()] + +******************************************************************************/ + +int +DddmpVisitedCnf ( + DdNode *f /* IN: BDD node to be tested */ + ) +{ + f = Cudd_Regular(f); + + return ((int)((ptruint)(f->next)) & (01)); +} + +/**Function******************************************************************** + + Synopsis [Marks a node as visited] + + Description [Marks a node as visited] + + SideEffects [None] + + SeeAlso [DddmpVisitedCnf (), DddmpClearVisitedCnf ()] + +******************************************************************************/ + +void +DddmpSetVisitedCnf ( + DdNode *f /* IN: BDD node to be marked (as visited) */ + ) +{ + f = Cudd_Regular(f); + + f->next = (DdNode *)(ptruint)((int)((ptruint)(f->next))|01); + + return; +} + +/**Function******************************************************************** + + Synopsis [Reads the index of a node] + + Description [Reads the index of a node. LSB is skipped (used as visited + flag). + ] + + SideEffects [None] + + SeeAlso [DddmpWriteNodeIndexCnf(), DddmpSetVisitedCnf (), + DddmpVisitedCnf ()] + +******************************************************************************/ + +int +DddmpReadNodeIndexCnf ( + DdNode *f /* IN: BDD node */ + ) +{ + if (!Cudd_IsConstant (f)) { + return ((int)(((ptruint)(f->next))>>1)); + } else { + return (1); + } +} + +/*---------------------------------------------------------------------------*/ +/* Definition of static functions */ +/*---------------------------------------------------------------------------*/ + +/**Function******************************************************************** + + Synopsis [Write index to node] + + Description [The index of the node is written in the "next" field of + a DdNode struct. LSB is not used (set to 0). It is used as + "visited" flag in DD traversals. The index corresponds to + the BDD node variable if both the node's children are a + constant node, otherwise a new CNF variable is used. + ] + + SideEffects [None] + + SeeAlso [DddmpReadNodeIndexCnf(), DddmpSetVisitedCnf (), + DddmpVisitedCnf ()] + +*****************************************************************************/ + +static int +DddmpWriteNodeIndexCnfWithTerminalCheck ( + DdNode *f /* IN: BDD node */, + int *cnfIds /* IN: possible source for the index to be written */, + int id /* IN: possible source for the index to be written */ + ) +{ + if (!Cudd_IsConstant (f)) { + if (Cudd_IsConstant (cuddT (f)) && Cudd_IsConstant (cuddE (f))) { + /* If Variable SET ID as Variable ID */ + f->next = (struct DdNode *)((ptruint)((cnfIds[f->index])<<1)); + } else { + f->next = (struct DdNode *)((ptruint)((id)<<1)); + id++; + } + } + + return(id); +} + +/**Function******************************************************************** + + Synopsis [Mark ALL nodes as not visited] + + Description [Mark ALL nodes as not visited (it recurs on the node children)] + + SideEffects [None] + + SeeAlso [DddmpVisitedCnf (), DddmpSetVisitedCnf ()] + +******************************************************************************/ + +static int +DddmpClearVisitedCnfRecur ( + DdNode *f /* IN: root of the BDD to be marked */ + ) +{ + int retValue; + + f = Cudd_Regular(f); + + if (cuddIsConstant (f)) { + return (DDDMP_SUCCESS); + } + + if (!DddmpVisitedCnf (f)) { + return (DDDMP_SUCCESS); + } + + retValue = DddmpClearVisitedCnfRecur (cuddT (f)); + retValue = DddmpClearVisitedCnfRecur (cuddE (f)); + + DddmpClearVisitedCnf (f); + + return (DDDMP_SUCCESS); +} + +/**Function******************************************************************** + + Synopsis [Marks a node as not visited] + + Description [Marks a node as not visited] + + SideEffects [None] + + SeeAlso [DddmpVisitedCnf (), DddmpSetVisitedCnf ()] + +******************************************************************************/ + +static void +DddmpClearVisitedCnf ( + DdNode *f /* IN: BDD node to be marked (as not visited) */ + ) +{ + f = Cudd_Regular (f); + + f->next = (DdNode *)(ptruint)((int)((ptruint)(f->next)) & (~01)); + + return; +} + +/**Function******************************************************************** + + Synopsis [Number nodes recursively in post-order] + + Description [Number nodes recursively in post-order. + The "visited" flag is used with inverse polarity, because all nodes + were set "visited" when removing them from unique. + ] + + SideEffects ["visited" flags are reset.] + + SeeAlso [] + +******************************************************************************/ + +static int +NumberNodeRecurCnf( + DdNode *f /* IN: root of the BDD to be numbered */, + int *cnfIds /* IN: possible source for numbering */, + int id /* IN/OUT: possible source for numbering */ + ) +{ + f = Cudd_Regular(f); + + if (!DddmpVisitedCnf (f)) { + return (id); + } + + if (!cuddIsConstant (f)) { + id = NumberNodeRecurCnf (cuddT (f), cnfIds, id); + id = NumberNodeRecurCnf (cuddE (f), cnfIds, id); + } + + id = DddmpWriteNodeIndexCnfWithTerminalCheck (f, cnfIds, id); + DddmpClearVisitedCnf (f); + + return (id); +} + +/**Function******************************************************************** + + Synopsis [Number nodes recursively in post-order] + + Description [Number nodes recursively in post-order. + The "visited" flag is used with the right polarity. + The node is assigned to a new CNF variable only if it is a "shared" + node (i.e. the number of its incoming edges is greater than 1). + ] + + SideEffects ["visited" flags are set.] + + SeeAlso [] + +******************************************************************************/ + +static void +DddmpDdNodesCheckIncomingAndScanPath ( + DdNode *f /* IN: BDD node to be numbered */, + int pathLengthCurrent /* IN: Current Path Length */, + int edgeInTh /* IN: Max # In-Edges, after a Insert Cut Point */, + int pathLengthTh /* IN: Max Path Length (after, Insert a Cut Point) */ + ) +{ + int retValue; + + f = Cudd_Regular(f); + + if (DddmpVisitedCnf (f)) { + return; + } + + if (cuddIsConstant (f)) { + return; + } + + pathLengthCurrent++; + retValue = DddmpReadNodeIndexCnf (f); + + if ( ((edgeInTh >= 0) && (retValue > edgeInTh)) || + ((pathLengthTh >= 0) && (pathLengthCurrent > pathLengthTh)) + ) { + DddmpWriteNodeIndexCnf (f, 1); + pathLengthCurrent = 0; + } else { + DddmpWriteNodeIndexCnf (f, 0); + } + + DddmpDdNodesCheckIncomingAndScanPath (cuddT (f), pathLengthCurrent, + edgeInTh, pathLengthTh); + DddmpDdNodesCheckIncomingAndScanPath (cuddE (f), pathLengthCurrent, + edgeInTh, pathLengthTh); + + DddmpSetVisitedCnf (f); + + return; +} + +/**Function******************************************************************** + + Synopsis [Number nodes recursively in post-order] + + Description [Number nodes recursively in post-order. + The "visited" flag is used with the inverse polarity. + Numbering follows the subsequent strategy: + * if the index = 0 it remains so + * if the index >= 1 it gets enumerated. + This implies that the node is assigned to a new CNF variable only if + it is not a terminal node otherwise it is assigned the index of + the BDD variable. + ] + + SideEffects ["visited" flags are reset.] + + SeeAlso [] + +******************************************************************************/ + +static int +DddmpDdNodesNumberEdgesRecur ( + DdNode *f /* IN: BDD node to be numbered */, + int *cnfIds /* IN: possible source for numbering */, + int id /* IN/OUT: possible source for numbering */ + ) +{ + int retValue; + + f = Cudd_Regular(f); + + if (!DddmpVisitedCnf (f)) { + return (id); + } + + if (cuddIsConstant (f)) { + return (id); + } + + id = DddmpDdNodesNumberEdgesRecur (cuddT (f), cnfIds, id); + id = DddmpDdNodesNumberEdgesRecur (cuddE (f), cnfIds, id); + + retValue = DddmpReadNodeIndexCnf (f); + if (retValue >= 1) { + id = DddmpWriteNodeIndexCnfWithTerminalCheck (f, cnfIds, id); + } else { + DddmpWriteNodeIndexCnf (f, 0); + } + + DddmpClearVisitedCnf (f); + + return (id); +} + +/**Function******************************************************************** + + Synopsis [Resets counter and visited flag for ALL nodes of a BDD] + + Description [Resets counter and visited flag for ALL nodes of a BDD (it + recurs on the node children). The index field of the node is + used as counter. + ] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ + +static int +DddmpDdNodesResetCountRecur ( + DdNode *f /* IN: root of the BDD whose counters are reset */ + ) +{ + int retValue; + + f = Cudd_Regular (f); + + if (!DddmpVisitedCnf (f)) { + return (DDDMP_SUCCESS); + } + + if (!cuddIsConstant (f)) { + retValue = DddmpDdNodesResetCountRecur (cuddT (f)); + retValue = DddmpDdNodesResetCountRecur (cuddE (f)); + } + + DddmpWriteNodeIndexCnf (f, 0); + DddmpClearVisitedCnf (f); + + return (DDDMP_SUCCESS); +} + +/**Function******************************************************************** + + Synopsis [Counts the number of incoming edges for each node of a BDD] + + Description [Counts (recursively) the number of incoming edges for each + node of a BDD. This number is stored in the index field. + ] + + SideEffects ["visited" flags remain untouched.] + + SeeAlso [] + +******************************************************************************/ + +static int +DddmpDdNodesCountEdgesRecur ( + DdNode *f /* IN: root of the BDD */ + ) +{ + int indexValue, retValue; + + f = Cudd_Regular (f); + + if (cuddIsConstant (f)) { + return (DDDMP_SUCCESS); + } + + if (Cudd_IsConstant (cuddT (f)) && Cudd_IsConstant (cuddE (f))) { + return (DDDMP_SUCCESS); + } + + indexValue = DddmpReadNodeIndexCnf (f); + + /* IF (first time) THEN recur */ + if (indexValue == 0) { + retValue = DddmpDdNodesCountEdgesRecur (cuddT (f)); + retValue = DddmpDdNodesCountEdgesRecur (cuddE (f)); + } + + /* Increment Incoming-Edge Count Flag */ + indexValue++; + DddmpWriteNodeIndexCnf (f, indexValue); + + return (DDDMP_SUCCESS); +} + +/**Function******************************************************************** + + Synopsis [Removes a node from unique table] + + Description [Removes a node from the unique table by locating the proper + subtable and unlinking the node from it. It recurs on on the + children of the node. Constants remain untouched. + ] + + SideEffects [Nodes are left with the "visited" flag true.] + + SeeAlso [RestoreInUniqueRecurCnf()] + +******************************************************************************/ + +static void +RemoveFromUniqueRecurCnf ( + DdManager *ddMgr /* IN: DD Manager */, + DdNode *f /* IN: root of the BDD to be extracted */ + ) +{ + DdNode *node, *last, *next; + DdNode *sentinel = &(ddMgr->sentinel); + DdNodePtr *nodelist; + DdSubtable *subtable; + int pos, level; + + f = Cudd_Regular (f); + + if (DddmpVisitedCnf (f)) { + return; + } + + if (!cuddIsConstant (f)) { + + RemoveFromUniqueRecurCnf (ddMgr, cuddT (f)); + RemoveFromUniqueRecurCnf (ddMgr, cuddE (f)); + + level = ddMgr->perm[f->index]; + subtable = &(ddMgr->subtables[level]); + + nodelist = subtable->nodelist; + + pos = ddHash (cuddT (f), cuddE (f), subtable->shift); + node = nodelist[pos]; + last = NULL; + while (node != sentinel) { + next = node->next; + if (node == f) { + if (last != NULL) + last->next = next; + else + nodelist[pos] = next; + break; + } else { + last = node; + node = next; + } + } + + f->next = NULL; + + } + + DddmpSetVisitedCnf (f); + + return; +} + +/**Function******************************************************************** + + Synopsis [Restores a node in unique table] + + Description [Restores a node in unique table (recursive)] + + SideEffects [Nodes are not restored in the same order as before removal] + + SeeAlso [RemoveFromUnique()] + +******************************************************************************/ + +static void +RestoreInUniqueRecurCnf ( + DdManager *ddMgr /* IN: DD Manager */, + DdNode *f /* IN: root of the BDD to be restored */ + ) +{ + DdNodePtr *nodelist; + DdNode *T, *E, *looking; + DdNodePtr *previousP; + DdSubtable *subtable; + int pos, level; +#ifdef DDDMP_DEBUG + DdNode *node; + DdNode *sentinel = &(ddMgr->sentinel); +#endif + + f = Cudd_Regular(f); + + if (!Cudd_IsComplement (f->next)) { + return; + } + + if (cuddIsConstant (f)) { + /* StQ 11.02.2004: + Bug fixed --> restore NULL within the next field */ + /*DddmpClearVisitedCnf (f);*/ + f->next = NULL; + + return; + } + + RestoreInUniqueRecurCnf (ddMgr, cuddT (f)); + RestoreInUniqueRecurCnf (ddMgr, cuddE (f)); + + level = ddMgr->perm[f->index]; + subtable = &(ddMgr->subtables[level]); + + nodelist = subtable->nodelist; + + pos = ddHash (cuddT (f), cuddE (f), subtable->shift); + +#ifdef DDDMP_DEBUG + /* verify uniqueness to avoid duplicate nodes in unique table */ + for (node=nodelist[pos]; node != sentinel; node=node->next) + assert(node!=f); +#endif + + T = cuddT (f); + E = cuddE (f); + previousP = &(nodelist[pos]); + looking = *previousP; + + while (T < cuddT (looking)) { + previousP = &(looking->next); + looking = *previousP; + } + + while (T == cuddT (looking) && E < cuddE (looking)) { + previousP = &(looking->next); + looking = *previousP; + } + f->next = *previousP; + *previousP = f; + + return; +} + +/**Function******************************************************************** + + Synopsis [Prints debug info] + + Description [Prints debug info for a BDD on the screen. It recurs on + node's children. + ] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ + +static int +DddmpPrintBddAndNextRecur ( + DdManager *ddMgr /* IN: DD Manager */, + DdNode *f /* IN: root of the BDD to be displayed */ + ) +{ + int retValue; + DdNode *fPtr, *tPtr, *ePtr; + + fPtr = Cudd_Regular (f); + + if (Cudd_IsComplement (f)) { + fprintf (stdout, "sign=- ptr=%ld ", ((long int) fPtr)); + } else { + fprintf (stdout, "sign=+ ptr=%ld ", ((long int) fPtr)); + } + + if (cuddIsConstant (fPtr)) { + fprintf (stdout, "one\n"); + fflush (stdout); + return (DDDMP_SUCCESS); + } + + fprintf (stdout, + "thenPtr=%ld elsePtr=%ld BddId=%d CnfId=%d Visited=%d\n", + ((long int) cuddT (fPtr)), ((long int) cuddE (fPtr)), + fPtr->index, DddmpReadNodeIndexCnf (fPtr), + DddmpVisitedCnf (fPtr)); + + tPtr = cuddT (fPtr); + ePtr = cuddE (fPtr); + if (Cudd_IsComplement (f)) { + tPtr = Cudd_Not (tPtr); + ePtr = Cudd_Not (ePtr); + } + + retValue = DddmpPrintBddAndNextRecur (ddMgr, tPtr); + retValue = DddmpPrintBddAndNextRecur (ddMgr, ePtr); + + return (DDDMP_SUCCESS); +} + + diff --git a/distr/dddmp/dddmpStoreAdd.c b/distr/dddmp/dddmpStoreAdd.c new file mode 100644 index 0000000..a86e39a --- /dev/null +++ b/distr/dddmp/dddmpStoreAdd.c @@ -0,0 +1,957 @@ +/**CFile********************************************************************** + FileName [dddmpStoreAdd.c] + + PackageName [dddmp] + + Synopsis [Functions to write ADDs to file.] + + Description [Functions to write ADDs to file. + ADDs are represended on file either in text or binary format under the + following rules. A file contains a forest of ADDs (a vector of + Boolean functions). ADD nodes are numbered with contiguous numbers, + from 1 to NNodes (total number of nodes on a file). 0 is not used to + allow negative node indexes for complemented edges. A file contains + a header, including information about variables and roots to ADD + functions, followed by the list of nodes. + ADD nodes are listed according to their numbering, and in the present + implementation numbering follows a post-order strategy, in such a way + that a node is never listed before its Then/Else children. + ] + + Author [Gianpiero Cabodi and Stefano Quer] + + Copyright [ + Copyright (c) 2004 by Politecnico di Torino. + All Rights Reserved. This software is for educational purposes only. + Permission is given to academic institutions to use, copy, and modify + this software and its documentation provided that this introductory + message is not removed, that this software and its documentation is + used for the institutions' internal research and educational purposes, + and that no monies are exchanged. No guarantee is expressed or implied + by the distribution of this code. + Send bug-reports and/or questions to: + {gianpiero.cabodi,stefano.quer}@polito.it. + ] + +******************************************************************************/ + +#include "dddmpInt.h" + +/*---------------------------------------------------------------------------*/ +/* Stucture declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Type declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Variable declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Macro declarations */ +/*---------------------------------------------------------------------------*/ + +/**AutomaticStart*************************************************************/ + +/*---------------------------------------------------------------------------*/ +/* Static function prototypes */ +/*---------------------------------------------------------------------------*/ + +static int NodeStoreRecurAdd(DdManager *ddMgr, DdNode *f, int mode, int *supportids, char **varnames, int *outids, FILE *fp); +static int NodeTextStoreAdd(DdManager *ddMgr, DdNode *f, int mode, int *supportids, char **varnames, int *outids, FILE *fp, int idf, int vf, int idT, int idE); + +/**AutomaticEnd***************************************************************/ + +/*---------------------------------------------------------------------------*/ +/* Definition of exported functions */ +/*---------------------------------------------------------------------------*/ + +/**Function******************************************************************** + + Synopsis [Writes a dump file representing the argument ADD.] + + Description [Dumps the argument ADD to file. Dumping is done through + Dddmp_cuddAddArrayStore, And a dummy array of 1 ADD root is + used for this purpose. + ] + + SideEffects [Nodes are temporarily removed from unique hash. They are + re-linked after the store operation in a modified order.] + + SeeAlso [Dddmp_cuddAddLoad Dddmp_cuddAddArrayLoad] + +******************************************************************************/ + +int +Dddmp_cuddAddStore ( + DdManager *ddMgr /* IN: DD Manager */, + char *ddname /* IN: DD name (or NULL) */, + DdNode *f /* IN: ADD root to be stored */, + char **varnames /* IN: array of variable names (or NULL) */, + int *auxids /* IN: array of converted var ids */, + int mode /* IN: storing mode selector */, + Dddmp_VarInfoType varinfo /* IN: extra info for variables in text mode */, + char *fname /* IN: File name */, + FILE *fp /* IN: File pointer to the store file */ + ) +{ + int retValue; + DdNode *tmpArray[1]; + + tmpArray[0] = f; + retValue = Dddmp_cuddAddArrayStore (ddMgr, ddname, 1, tmpArray, NULL, + varnames, auxids, mode, varinfo, fname, fp); + + return (retValue); +} + +/**Function******************************************************************** + + Synopsis [Writes a dump file representing the argument Array of ADDs.] + + Description [Dumps the argument array of ADDs to file. Dumping is + either in text or binary form. see the corresponding BDD dump + function for further details. + ] + + SideEffects [Nodes are temporarily removed from the unique hash + table. They are re-linked after the store operation in a + modified order. + ] + + SeeAlso [Dddmp_cuddAddStore, Dddmp_cuddAddLoad, + Dddmp_cuddAddArrayLoad] + +******************************************************************************/ + +int +Dddmp_cuddAddArrayStore ( + DdManager *ddMgr /* IN: DD Manager */, + char *ddname /* IN: DD name (or NULL) */, + int nRoots /* IN: number of output BDD roots to be stored */, + DdNode **f /* IN: array of ADD roots to be stored */, + char **rootnames /* IN: array of root names (or NULL) */, + char **varnames /* IN: array of variable names (or NULL) */, + int *auxids /* IN: array of converted var IDs */, + int mode /* IN: storing mode selector */, + Dddmp_VarInfoType varinfo /* IN: extra info for variables in text mode */, + char *fname /* IN: File name */, + FILE *fp /* IN: File pointer to the store file */ + ) +{ + int retValue; + +#if 0 +#ifdef DDDMP_DEBUG +#ifndef __alpha__ + int retValueBis; + + retValueBis = Cudd_DebugCheck (ddMgr); + if (retValueBis == 1) { + fprintf (stderr, "Inconsistency Found During ADD Store.\n"); + fflush (stderr); + } else { + if (retValueBis == CUDD_OUT_OF_MEM) { + fprintf (stderr, "Out of Memory During ADD Store.\n"); + fflush (stderr); + } + } +#endif +#endif +#endif + + retValue = DddmpCuddDdArrayStoreBdd (DDDMP_ADD, ddMgr, ddname, nRoots, f, + rootnames, varnames, auxids, mode, varinfo, fname, fp); + +#if 0 +#ifdef DDDMP_DEBUG +#ifndef __alpha__ + retValueBis = Cudd_DebugCheck (ddMgr); + if (retValueBis == 1) { + fprintf (stderr, "Inconsistency Found During ADD Store.\n"); + fflush (stderr); + } else { + if (retValueBis == CUDD_OUT_OF_MEM) { + fprintf (stderr, "Out of Memory During ADD Store.\n"); + fflush (stderr); + } + } +#endif +#endif +#endif + + return (retValue); +} + +/*---------------------------------------------------------------------------*/ +/* Definition of internal functions */ +/*---------------------------------------------------------------------------*/ + +/**Function******************************************************************** + + Synopsis [Writes a dump file representing the argument Array of + BDDs/ADDs. + ] + + Description [Dumps the argument array of BDDs/ADDs to file. Internal + function doing inner steps of store for BDDs and ADDs. + ADD store is presently supported only with the text format. + ] + + SideEffects [Nodes are temporarily removed from the unique hash + table. They are re-linked after the store operation in a + modified order. + ] + + SeeAlso [Dddmp_cuddBddStore, Dddmp_cuddBddLoad, + Dddmp_cuddBddArrayLoad + ] + +******************************************************************************/ + +int +DddmpCuddDdArrayStoreBdd ( + Dddmp_DecompType ddType /* IN: Selects the decomp type: BDD or ADD */, + DdManager *ddMgr /* IN: DD Manager */, + char *ddname /* IN: DD name (or NULL) */, + int nRoots /* IN: number of output BDD roots to be stored */, + DdNode **f /* IN: array of DD roots to be stored */, + char **rootnames /* IN: array of root names (or NULL) */, + char **varnames /* IN: array of variable names (or NULL) */, + int *auxids /* IN: array of converted var IDs */, + int mode /* IN: storing mode selector */, + Dddmp_VarInfoType varinfo /* IN: extra info for variables in text mode */, + char *fname /* IN: File name */, + FILE *fp /* IN: File pointer to the store file */ + ) +{ + DdNode *support = NULL; + DdNode *scan; + int *ids = NULL; + int *permids = NULL; + int *invpermids = NULL; + int *supportids = NULL; + int *outids = NULL; + char **outvarnames = NULL; + int nVars = ddMgr->size; + int nnodes; + int retValue; + int i, var; + int fileToClose = 0; + + /* + * Check DD Type and Mode + */ + + Dddmp_CheckAndGotoLabel (ddType==DDDMP_BDD, + "Error writing to file: BDD Type.", failure); + Dddmp_CheckAndGotoLabel (mode==DDDMP_MODE_BINARY, + "Error writing to file: ADD Type with Binary Mode.", failure); + + /* + * Check if File needs to be opened in the proper mode. + */ + + if (fp == NULL) { + fp = fopen (fname, "w"); + Dddmp_CheckAndGotoLabel (fp==NULL, "Error opening file.", + failure); + fileToClose = 1; + } + + /* + * Force binary mode if automatic. + */ + + switch (mode) { + case DDDMP_MODE_TEXT: + case DDDMP_MODE_BINARY: + break; + case DDDMP_MODE_DEFAULT: + mode = DDDMP_MODE_BINARY; + break; + default: + mode = DDDMP_MODE_BINARY; + break; + } + + /* + * Alloc vectors for variable IDs, perm IDs and support IDs. + * +1 to include a slot for terminals. + */ + + ids = DDDMP_ALLOC (int, nVars); + Dddmp_CheckAndGotoLabel (ids==NULL, "Error allocating memory.", failure); + permids = DDDMP_ALLOC (int, nVars); + Dddmp_CheckAndGotoLabel (permids==NULL, "Error allocating memory.", failure); + invpermids = DDDMP_ALLOC (int, nVars); + Dddmp_CheckAndGotoLabel (invpermids==NULL, "Error allocating memory.", + failure); + supportids = DDDMP_ALLOC (int, nVars+1); + Dddmp_CheckAndGotoLabel (supportids==NULL, "Error allocating memory.", + failure); + + for (i=0; iindex] = scan->index; + permids[scan->index] = ddMgr->perm[scan->index]; + invpermids[ddMgr->perm[scan->index]] = scan->index; + scan = cuddT (scan); + } + Cudd_RecursiveDeref (ddMgr, support); + } + /* so that we do not try to free it in case of failure */ + support = NULL; + + /* + * Set supportids to incremental (shrinked) values following the ordering. + */ + + for (i=0, var=0; i= 0) { + supportids[invpermids[i]] = var++; + } + } + /* set a dummy id for terminal nodes */ + supportids[nVars] = var; + + /* + * Select conversion array for extra var info + */ + + switch (mode) { + case DDDMP_MODE_TEXT: + switch (varinfo) { + case DDDMP_VARIDS: + outids = ids; + break; + case DDDMP_VARPERMIDS: + outids = permids; + break; + case DDDMP_VARAUXIDS: + outids = auxids; + break; + case DDDMP_VARNAMES: + outvarnames = varnames; + break; + case DDDMP_VARDEFAULT: + break; + } + break; + case DDDMP_MODE_BINARY: + outids = NULL; + break; + } + + /* + * Number dd nodes and count them (numbering is from 1 to nnodes) + */ + + nnodes = DddmpNumberAddNodes (ddMgr, f, nRoots); + + /* + * Start Header + */ + +#ifdef DDDMP_VERSION + retValue = fprintf (fp, ".ver %s\n", DDDMP_VERSION); + Dddmp_CheckAndGotoLabel (retValue==EOF, "Error writing to file.", + failure); +#endif + + retValue = fprintf (fp, ".add\n"); + Dddmp_CheckAndGotoLabel (retValue==EOF, "Error writing to file.", + failure); + + retValue = fprintf (fp, ".mode %c\n", mode); + Dddmp_CheckAndGotoLabel (retValue==EOF, "Error writing to file.", + failure); + + if (mode == DDDMP_MODE_TEXT) { + retValue = fprintf (fp, ".varinfo %d\n", varinfo); + Dddmp_CheckAndGotoLabel (retValue==EOF, "Error writing to file.", + failure); + } + + if (ddname != NULL) { + retValue = fprintf (fp, ".dd %s\n",ddname); + Dddmp_CheckAndGotoLabel (retValue==EOF, "Error writing to file.", + failure); + } + + retValue = fprintf (fp, ".nnodes %d\n", nnodes); + Dddmp_CheckAndGotoLabel (retValue==EOF, "Error writing to file.", + failure); + + retValue = fprintf (fp, ".nvars %d\n", nVars); + Dddmp_CheckAndGotoLabel (retValue==EOF, "Error writing to file.", + failure); + + retValue = fprintf (fp, ".nsuppvars %d\n", var); + Dddmp_CheckAndGotoLabel (retValue==EOF, "Error writing to file.", + failure); + + /*------------ Write the Var Names by scanning the ids array -------------*/ + + if (varnames != NULL) { + + retValue = fprintf (fp, ".suppvarnames"); + Dddmp_CheckAndGotoLabel (retValue==EOF, "Error writing to file.", + failure); + + for (i=0; i= 0) { + if (varnames[ids[i]] == NULL) { + (void) fprintf (stderr, + "DdStore Warning: null variable name. DUMMY%d generated\n", i); + fflush (stderr); + varnames[ids[i]] = DDDMP_ALLOC (char, 10); + Dddmp_CheckAndGotoLabel (varnames[ids[i]] == NULL, + "Error allocating memory.", failure); + sprintf (varnames[ids[i]], "DUMMY%d", i); + } + retValue = fprintf (fp, " %s", varnames[ids[i]]); + Dddmp_CheckAndGotoLabel (retValue==EOF, "Error writing to file.", + failure); + } + } + + retValue = fprintf (fp, "\n"); + Dddmp_CheckAndGotoLabel (retValue==EOF, "Error writing to file.", + failure); + } + + /*--------- Write the Var SUPPORT Names by scanning the ids array ---------*/ + + if (varnames != NULL) { + retValue = fprintf (fp, ".orderedvarnames"); + Dddmp_CheckAndGotoLabel (retValue==EOF, "Error writing to file.", + failure); + + for (i=0; iinvperm[i]] == NULL) { + (void) fprintf (stderr, + "DdStore Warning: null variable name. DUMMY%d generated\n", i); + fflush (stderr); + varnames[ddMgr->invperm[i]] = DDDMP_ALLOC (char, 10); + Dddmp_CheckAndGotoLabel (varnames[ddMgr->invperm[i]] == NULL, + "Error allocating memory.", failure); + sprintf (varnames[ddMgr->invperm[i]], "DUMMY%d", i); + } + + retValue = fprintf (fp, " %s", varnames[ddMgr->invperm[i]]); + Dddmp_CheckAndGotoLabel (retValue==EOF, "Error writing to file.", + failure); + } + + retValue = fprintf (fp, "\n"); + Dddmp_CheckAndGotoLabel (retValue==EOF, "Error writing to file.", + failure); + } + + /*------------ Write the var ids by scanning the ids array ---------------*/ + + retValue = fprintf (fp, ".ids"); + Dddmp_CheckAndGotoLabel (retValue==EOF, "Error writing to file.", + failure); + + for (i=0; i= 0) { + retValue = fprintf (fp, " %d", i); + Dddmp_CheckAndGotoLabel (retValue==EOF, "Error writing to file.", + failure); + } + } + retValue = fprintf (fp, "\n"); + Dddmp_CheckAndGotoLabel (retValue==EOF, "Error writing to file.", + failure); + + /* + * Write the var permids by scanning the permids array. + */ + + retValue = fprintf (fp, ".permids"); + Dddmp_CheckAndGotoLabel (retValue==EOF, "Error writing to file.", + failure); + for (i = 0; i < nVars; i++) { + if (permids[i] >= 0) { + retValue = fprintf (fp, " %d", permids[i]); + Dddmp_CheckAndGotoLabel (retValue==EOF, "Error writing to file.", + failure); + } + } + + retValue = fprintf (fp, "\n"); + Dddmp_CheckAndGotoLabel (retValue==EOF, "Error writing to file.", + failure); + + if (auxids != NULL) { + + /* + * Write the var auxids by scanning the ids array. + */ + + retValue = fprintf (fp, ".auxids"); + Dddmp_CheckAndGotoLabel (retValue==EOF, "Error writing to file.", + failure); + for (i = 0; i < nVars; i++) { + if (ids[i] >= 0) { + retValue = fprintf (fp, " %d", auxids[i]); + Dddmp_CheckAndGotoLabel (retValue==EOF, "Error writing to file.", + failure); + } + } + retValue = fprintf (fp, "\n"); + Dddmp_CheckAndGotoLabel (retValue==EOF, "Error writing to file.", + failure); + } + + /* + * Write the roots info. + */ + + retValue = fprintf (fp, ".nroots %d\n", nRoots); + Dddmp_CheckAndGotoLabel (retValue==EOF, "Error writing to file.", + failure); + + if (rootnames != NULL) { + + /* + * Write the root names. + */ + + retValue = fprintf (fp, ".rootnames"); + Dddmp_CheckAndGotoLabel (retValue==EOF, "Error writing to file.", + failure); + + for (i = 0; i < nRoots; i++) { + if (rootnames[i] == NULL) { + (void) fprintf (stderr, + "DdStore Warning: null variable name. ROOT%d generated\n",i); + fflush (stderr); + rootnames[i] = DDDMP_ALLOC(char,10); + Dddmp_CheckAndGotoLabel (rootnames[i]==NULL, + "Error writing to file.", failure); + sprintf(rootnames[ids[i]], "ROOT%d",i); + } + retValue = fprintf (fp, " %s", rootnames[i]); + Dddmp_CheckAndGotoLabel (retValue==EOF, "Error writing to file.", + failure); + } + + retValue = fprintf (fp, "\n"); + Dddmp_CheckAndGotoLabel (retValue==EOF, "Error writing to file.", + failure); + } + + retValue = fprintf (fp, ".rootids"); + Dddmp_CheckAndGotoLabel (retValue==EOF, "Error writing to file.", + failure); + + /* + * Write BDD indexes of function roots. + * Use negative integers for complemented edges. + */ + + for (i = 0; i < nRoots; i++) { + if (f[i] == NULL) { + (void) fprintf (stderr, "DdStore Warning: %d-th root is NULL\n",i); + fflush (stderr); + retValue = fprintf (fp, " 0"); + } + if (Cudd_IsComplement(f[i])) { + retValue = fprintf (fp, " -%d", + DddmpReadNodeIndexAdd (Cudd_Regular (f[i]))); + } else { + retValue = fprintf (fp, " %d", + DddmpReadNodeIndexAdd (Cudd_Regular (f[i]))); + } + Dddmp_CheckAndGotoLabel (retValue==EOF, "Error writing to file.", + failure); + } + + retValue = fprintf (fp, "\n"); + Dddmp_CheckAndGotoLabel (retValue==EOF, "Error writing to file.", + failure); + + retValue = fprintf (fp, ".nodes\n"); + Dddmp_CheckAndGotoLabel (retValue==EOF, "Error writing to file.", + failure); + + /* + * END HEADER + */ + + /* + * Call the function that really gets the job done. + */ + + for (i = 0; i < nRoots; i++) { + if (f[i] != NULL) { + retValue = NodeStoreRecurAdd (ddMgr, Cudd_Regular(f[i]), + mode, supportids, outvarnames, outids, fp); + Dddmp_CheckAndGotoLabel (retValue==DDDMP_FAILURE, + "Error writing to file.", failure); + } + } + + /* + * Write trailer and return. + */ + + retValue = fprintf (fp, ".end\n"); + Dddmp_CheckAndGotoLabel (retValue==EOF, "Error writing to file.", + failure); + + if (fileToClose) { + fclose (fp); + } + + DddmpUnnumberAddNodes (ddMgr, f, nRoots); + DDDMP_FREE (ids); + DDDMP_FREE (permids); + DDDMP_FREE (invpermids); + DDDMP_FREE (supportids); + + return (DDDMP_SUCCESS); + + failure: + + if (ids != NULL) { + DDDMP_FREE (ids); + } + if (permids != NULL) { + DDDMP_FREE (permids); + } + if (invpermids != NULL) { + DDDMP_FREE (invpermids); + } + if (supportids != NULL) { + DDDMP_FREE (supportids); + } + if (support != NULL) { + Cudd_RecursiveDeref (ddMgr, support); + } + + return (DDDMP_FAILURE); +} + +/*---------------------------------------------------------------------------*/ +/* Definition of static functions */ +/*---------------------------------------------------------------------------*/ + +/**Function******************************************************************** + + Synopsis [Performs the recursive step of Dddmp_bddStore.] + + Description [Stores a node to file in either test or binary mode. + In text mode a node is represented (on a text line basis) as +
            +
          • node-index \[var-extrainfo\] var-index Then-index Else-index +
          + + where all indexes are integer numbers and var-extrainfo + (optional redundant field) is either an integer or a string + (variable name). Node-index is redundant (due to the node + ordering) but we keep it for readability.

          + + In binary mode nodes are represented as a sequence of bytes, + representing var-index, Then-index, and Else-index in an + optimized way. Only the first byte (code) is mandatory. + Integer indexes are represented in absolute or relative mode, + where relative means offset wrt. a Then/Else node info. + Suppose Var(NodeId), Then(NodeId) and Else(NodeId) represent + infos about a given node.

          + + The generic "NodeId" node is stored as + +

            +
          • code-byte +
          • \[var-info\] +
          • \[Then-info\] +
          • \[Else-info\] +
          + + where code-byte contains bit fields + +
            +
          • Unused : 1 bit +
          • Variable: 2 bits, one of the following codes +
              +
            • DDDMP_ABSOLUTE_ID var-info = Var(NodeId) follows +
            • DDDMP_RELATIVE_ID Var(NodeId) is represented in relative form as + var-info = Min(Var(Then(NodeId)),Var(Else(NodeId))) -Var(NodeId) +
            • DDDMP_RELATIVE_1 No var-info follows, because + Var(NodeId) = Min(Var(Then(NodeId)),Var(Else(NodeId)))-1 +
            • DDDMP_TERMINAL Node is a terminal, no var info required +
            +
          • T : 2 bits, with codes similar to V +
              +
            • DDDMP_ABSOLUTE_ID Then-info = Then(NodeId) follows +
            • DDDMP_RELATIVE_ID Then(NodeId) is represented in relative form as + Then-info = Nodeid-Then(NodeId) +
            • DDDMP_RELATIVE_1 No info on Then(NodeId) follows, because + Then(NodeId) = NodeId-1 +
            • DDDMP_TERMINAL Then Node is a terminal, no info required (for BDDs) +
            +
          • Ecompl : 1 bit, if 1 means complemented edge +
          • E : 2 bits, with codes and meanings as for the Then edge +
          + var-info, Then-info, Else-info (if required) are represented as unsigned + integer values on a sufficient set of bytes (MSByte first). + ] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ + +static int +NodeStoreRecurAdd ( + DdManager *ddMgr /* IN: DD Manager */, + DdNode *f /* IN: DD node to be stored */, + int mode /* IN: store mode */, + int *supportids /* IN: internal ids for variables */, + char **varnames /* IN: names of variables: to be stored with nodes */, + int *outids /* IN: output ids for variables */, + FILE *fp /* IN: store file */ + ) +{ + DdNode *T = NULL; + DdNode *E = NULL; + int idf = (-1); + int idT = (-1); + int idE = (-1); + int vf = (-1); + int vT = (-1); + int vE = (-1); + int retValue; + int nVars; + + nVars = ddMgr->size; + T = E = NULL; + idf = idT = idE = (-1); + +#ifdef DDDMP_DEBUG + assert(!Cudd_IsComplement(f)); + assert(f!=NULL); + assert(supportids!=NULL); +#endif + + /* If already visited, nothing to do. */ + if (DddmpVisitedAdd (f)) { + return (DDDMP_SUCCESS); + } + + /* Mark node as visited. */ + DddmpSetVisitedAdd (f); + + if (Cudd_IsConstant(f)) { + /* Check for special case: don't recur */ + idf = DddmpReadNodeIndexAdd (f); + } else { + +#ifdef DDDMP_DEBUG + /* BDDs! Only one constant supported */ + assert (!cuddIsConstant(f)); +#endif + + /* + * Recursive call for Then edge + */ + + T = cuddT(f); +#ifdef DDDMP_DEBUG + /* ROBDDs! No complemented Then edge */ + assert (!Cudd_IsComplement(T)); +#endif + /* recur */ + retValue = NodeStoreRecurAdd (ddMgr, T, mode, supportids, varnames, outids, + fp); + if (retValue != DDDMP_SUCCESS) { + return (retValue); + } + + /* + * Recursive call for Else edge + */ + + E = Cudd_Regular (cuddE (f)); + retValue = NodeStoreRecurAdd (ddMgr, E, mode, supportids, varnames, outids, + fp); + if (retValue != DDDMP_SUCCESS) { + return (retValue); + } + + /* + * Obtain nodeids and variable ids of f, T, E + */ + + idf = DddmpReadNodeIndexAdd (f); + vf = f->index; + + idT = DddmpReadNodeIndexAdd (T); + if (Cudd_IsConstant(T)) { + vT = nVars; + } else { + vT = T->index; + } + + idE = DddmpReadNodeIndexAdd (E); + if (Cudd_IsConstant(E)) { + vE = nVars; + } else { + vE = E->index; + } + } + + retValue = NodeTextStoreAdd (ddMgr, f, mode, supportids, varnames, + outids, fp, idf, vf, idT, idE); + + return (retValue); +} + +/**Function******************************************************************** + + Synopsis [Store One Single Node in Text Format.] + + Description [Store 1 0 0 for the terminal node. + Store id, left child pointer, right pointer for all the other nodes. + ] + + SideEffects [None] + + SeeAlso [NodeBinaryStore] + +******************************************************************************/ + +static int +NodeTextStoreAdd ( + DdManager *ddMgr /* IN: DD Manager */, + DdNode *f /* IN: DD node to be stored */, + int mode /* IN: store mode */, + int *supportids /* IN: internal ids for variables */, + char **varnames /* IN: names of variables: to be stored with nodes */, + int *outids /* IN: output ids for variables */, + FILE *fp /* IN: Store file */, + int idf /* IN: index of the current node */, + int vf /* IN: variable of the current node */, + int idT /* IN: index of the Then node */, + int idE /* IN: index of the Else node */ + ) +{ + int retValue; + + /* + * Check for Constant + */ + + if (Cudd_IsConstant(f)) { + + if (f == Cudd_ReadOne(ddMgr)) { + if ((varnames != NULL) || (outids != NULL)) { + retValue = fprintf (fp, "%d T 1 0 0\n", idf); + } else { + retValue = fprintf (fp, "%d 1 0 0\n", idf); + } + + if (retValue == EOF) { + return (DDDMP_FAILURE); + } else { + return (DDDMP_SUCCESS); + } + } + + if (f == Cudd_ReadZero(ddMgr)) { + if ((varnames != NULL) || (outids != NULL)) { + retValue = fprintf (fp, "%d T 0 0 0\n", idf); + } else { + retValue = fprintf (fp, "%d 0 0 0\n", idf); + } + + if (retValue == EOF) { + return (DDDMP_FAILURE); + } else { + return (DDDMP_SUCCESS); + } + } + + /* + * A constant node different from 1: an ADD constant + */ + + if ((varnames != NULL) || (outids != NULL)) { + retValue = fprintf (fp, "%d T %g 0 0\n",idf,Cudd_V(f)); + } else { + retValue = fprintf (fp, "%d %g 0 0\n",idf, Cudd_V(f)); + } + + if (retValue == EOF) { + return (DDDMP_FAILURE); + } else { + return (DDDMP_SUCCESS); + } + } + + /* + * ... Not A Constant + */ + + if (Cudd_IsComplement (cuddE(f))) { + idE = -idE; + } + + if (varnames != NULL) { + retValue = fprintf (fp, "%d %s %d %d %d\n", + idf, varnames[vf], supportids[vf], idT, idE); + + if (retValue == EOF) { + return (DDDMP_FAILURE); + } else { + return (DDDMP_SUCCESS); + } + } + + if (outids != NULL) { + retValue = fprintf (fp, "%d %d %d %d %d\n", + idf, outids[vf], supportids[vf], idT, idE); + + if (retValue == EOF) { + return (DDDMP_FAILURE); + } else { + return (DDDMP_SUCCESS); + } + } + + retValue = fprintf (fp, "%d %d %d %d\n", + idf, supportids[vf], idT, idE); + + if (retValue == EOF) { + return (DDDMP_FAILURE); + } else { + return (DDDMP_SUCCESS); + } +} diff --git a/distr/dddmp/dddmpStoreBdd.c b/distr/dddmp/dddmpStoreBdd.c new file mode 100644 index 0000000..cdc7968 --- /dev/null +++ b/distr/dddmp/dddmpStoreBdd.c @@ -0,0 +1,1114 @@ +/**CFile********************************************************************** + + FileName [dddmpStoreBdd.c] + + PackageName [dddmp] + + Synopsis [Functions to write BDDs to file.] + + Description [Functions to write BDDs to file. + BDDs are represended on file either in text or binary format under the + following rules. A file contains a forest of BDDs (a vector of + Boolean functions). BDD nodes are numbered with contiguous numbers, + from 1 to NNodes (total number of nodes on a file). 0 is not used to + allow negative node indexes for complemented edges. A file contains + a header, including information about variables and roots to BDD + functions, followed by the list of nodes. BDD nodes are listed + according to their numbering, and in the present implementation + numbering follows a post-order strategy, in such a way that a node + is never listed before its Then/Else children. + ] + + Author [Gianpiero Cabodi and Stefano Quer] + + Copyright [ + Copyright (c) 2004 by Politecnico di Torino. + All Rights Reserved. This software is for educational purposes only. + Permission is given to academic institutions to use, copy, and modify + this software and its documentation provided that this introductory + message is not removed, that this software and its documentation is + used for the institutions' internal research and educational purposes, + and that no monies are exchanged. No guarantee is expressed or implied + by the distribution of this code. + Send bug-reports and/or questions to: + {gianpiero.cabodi,stefano.quer}@polito.it. + ] + +******************************************************************************/ + +#include "dddmpInt.h" + +/*---------------------------------------------------------------------------*/ +/* Stucture declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Type declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Variable declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Macro declarations */ +/*---------------------------------------------------------------------------*/ + +/**AutomaticStart*************************************************************/ + +/*---------------------------------------------------------------------------*/ +/* Static function prototypes */ +/*---------------------------------------------------------------------------*/ + +static int NodeStoreRecurBdd(DdManager *ddMgr, DdNode *f, int mode, int *supportids, char **varnames, int *outids, FILE *fp); +static int NodeTextStoreBdd(DdManager *ddMgr, DdNode *f, int mode, int *supportids, char **varnames, int *outids, FILE *fp, int idf, int vf, int idT, int idE); +static int NodeBinaryStoreBdd(DdManager *ddMgr, DdNode *f, int mode, int *supportids, char **varnames, int *outids, FILE *fp, int idf, int vf, int idT, int idE, int vT, int vE, DdNode *T, DdNode *E); + +/**AutomaticEnd***************************************************************/ + +/*---------------------------------------------------------------------------*/ +/* Definition of exported functions */ +/*---------------------------------------------------------------------------*/ + +/**Function******************************************************************** + + Synopsis [Writes a dump file representing the argument BDD.] + + Description [Dumps the argument BDD to file. Dumping is done through + Dddmp_cuddBddArrayStore. A dummy array of 1 BDD root is + used for this purpose. + ] + + SideEffects [Nodes are temporarily removed from unique hash. They are + re-linked after the store operation in a modified order. + ] + + SeeAlso [Dddmp_cuddBddLoad Dddmp_cuddBddArrayLoad] + +******************************************************************************/ + +int +Dddmp_cuddBddStore ( + DdManager *ddMgr /* IN: DD Manager */, + char *ddname /* IN: DD name (or NULL) */, + DdNode *f /* IN: BDD root to be stored */, + char **varnames /* IN: array of variable names (or NULL) */, + int *auxids /* IN: array of converted var ids */, + int mode /* IN: storing mode selector */, + Dddmp_VarInfoType varinfo /* IN: extra info for variables in text mode */, + char *fname /* IN: File name */, + FILE *fp /* IN: File pointer to the store file */ + ) +{ + int retValue; + DdNode *tmpArray[1]; + + tmpArray[0] = f; + + retValue = Dddmp_cuddBddArrayStore (ddMgr,ddname,1,tmpArray,NULL, + varnames, auxids, mode, varinfo, fname, fp); + + return (retValue); +} + +/**Function******************************************************************** + + Synopsis [Writes a dump file representing the argument Array of BDDs.] + + Description [Dumps the argument array of BDDs to file. Dumping is either + in text or binary form. BDDs are stored to the fp (already + open) file if not NULL. Otherwise the file whose name is + fname is opened in write mode. The header has the same format + for both textual and binary dump. Names are allowed for input + variables (vnames) and for represented functions (rnames). + For sake of generality and because of dynamic variable + ordering both variable IDs and permuted IDs are included. + New IDs are also supported (auxids). Variables are identified + with incremental numbers. according with their positiom in + the support set. In text mode, an extra info may be added, + chosen among the following options: name, ID, PermID, or an + auxiliary id. Since conversion from DD pointers to integers + is required, DD nodes are temporarily removed from the unique + hash table. This allows the use of the next field to store + node IDs. + ] + + SideEffects [Nodes are temporarily removed from the unique hash + table. They are re-linked after the store operation in a + modified order. + ] + + SeeAlso [Dddmp_cuddBddStore, Dddmp_cuddBddLoad, + Dddmp_cuddBddArrayLoad + ] + +******************************************************************************/ + +int +Dddmp_cuddBddArrayStore ( + DdManager *ddMgr /* IN: DD Manager */, + char *ddname /* IN: dd name (or NULL) */, + int nRoots /* IN: number of output BDD roots to be stored */, + DdNode **f /* IN: array of BDD roots to be stored */, + char **rootnames /* IN: array of root names (or NULL) */, + char **varnames /* IN: array of variable names (or NULL) */, + int *auxids /* IN: array of converted var IDs */, + int mode /* IN: storing mode selector */, + Dddmp_VarInfoType varinfo /* IN: extra info for variables in text mode */, + char *fname /* IN: File name */, + FILE *fp /* IN: File pointer to the store file */ + ) +{ + int retValue; + +#ifdef DDDMP_DEBUG +#ifndef __alpha__ + int retValueBis; + + retValueBis = Cudd_DebugCheck (ddMgr); + if (retValueBis == 1) { + fprintf (stderr, "Inconsistency Found During BDD Store.\n"); + fflush (stderr); + } else { + if (retValueBis == CUDD_OUT_OF_MEM) { + fprintf (stderr, "Out of Memory During BDD Store.\n"); + fflush (stderr); + } + } +#endif +#endif + + retValue = DddmpCuddBddArrayStore (DDDMP_BDD, ddMgr, ddname, nRoots, f, + rootnames, varnames, auxids, mode, varinfo, fname, fp); + +#ifdef DDDMP_DEBUG +#ifndef __alpha__ + retValueBis = Cudd_DebugCheck (ddMgr); + if (retValueBis == 1) { + fprintf (stderr, "Inconsistency Found During BDD Store.\n"); + fflush (stderr); + } else { + if (retValueBis == CUDD_OUT_OF_MEM) { + fprintf (stderr, "Out of Memory During BDD Store.\n"); + fflush (stderr); + } + } +#endif +#endif + + return (retValue); +} + +/*---------------------------------------------------------------------------*/ +/* Definition of internal functions */ +/*---------------------------------------------------------------------------*/ + +/**Function******************************************************************** + + Synopsis [Writes a dump file representing the argument Array of + BDDs. + ] + + Description [Dumps the argument array of BDDs to file. + Internal function doing inner steps of store for BDDs. + ] + + SideEffects [Nodes are temporarily removed from the unique hash + table. They are re-linked after the store operation in a + modified order. + ] + + SeeAlso [Dddmp_cuddBddStore, Dddmp_cuddBddLoad, + Dddmp_cuddBddArrayLoad + ] + +******************************************************************************/ + +int +DddmpCuddBddArrayStore ( + Dddmp_DecompType ddType /* IN: Selects the decomp type BDD */, + DdManager *ddMgr /* IN: DD Manager */, + char *ddname /* IN: DD name (or NULL) */, + int nRoots /* IN: number of output BDD roots to be stored */, + DdNode **f /* IN: array of DD roots to be stored */, + char **rootnames /* IN: array of root names (or NULL) */, + char **varnames /* IN: array of variable names (or NULL) */, + int *auxids /* IN: array of converted var IDs */, + int mode /* IN: storing mode selector */, + Dddmp_VarInfoType varinfo /* IN: extra info for variables in text mode */, + char *fname /* IN: File name */, + FILE *fp /* IN: File pointer to the store file */ + ) +{ + DdNode *support = NULL; + DdNode *scan; + int *ids = NULL; + int *permids = NULL; + int *invpermids = NULL; + int *supportids = NULL; + int *outids = NULL; + char **outvarnames = NULL; + int nVars = ddMgr->size; + int nnodes; + int retValue; + int i, var; + int fileToClose = 0; + + /* + * Check DD Type + */ + + Dddmp_CheckAndGotoLabel (ddType==DDDMP_ADD, + "Error writing to file: ADD Type.", failure); + + /* + * Check if File needs to be opened in the proper mode. + */ + + if (fp == NULL) { + fp = fopen (fname, "w"); + Dddmp_CheckAndGotoLabel (fp==NULL, "Error opening file.", + failure); + fileToClose = 1; + } + + /* + * Force binary mode if automatic. + */ + + switch (mode) { + case DDDMP_MODE_TEXT: + case DDDMP_MODE_BINARY: + break; + case DDDMP_MODE_DEFAULT: + mode = DDDMP_MODE_BINARY; + break; + default: + mode = DDDMP_MODE_BINARY; + break; + } + + /* + * Alloc vectors for variable IDs, perm IDs and support IDs. + * +1 to include a slot for terminals. + */ + + ids = DDDMP_ALLOC (int, nVars); + Dddmp_CheckAndGotoLabel (ids==NULL, "Error allocating memory.", failure); + permids = DDDMP_ALLOC (int, nVars); + Dddmp_CheckAndGotoLabel (permids==NULL, "Error allocating memory.", failure); + invpermids = DDDMP_ALLOC (int, nVars); + Dddmp_CheckAndGotoLabel (invpermids==NULL, "Error allocating memory.", + failure); + supportids = DDDMP_ALLOC (int, nVars+1); + Dddmp_CheckAndGotoLabel (supportids==NULL, "Error allocating memory.", + failure); + + for (i=0; iindex] = scan->index; + permids[scan->index] = ddMgr->perm[scan->index]; + invpermids[ddMgr->perm[scan->index]] = scan->index; + scan = cuddT (scan); + } + Cudd_RecursiveDeref (ddMgr, support); + } + /* so that we do not try to free it in case of failure */ + support = NULL; + + /* + * Set supportids to incremental (shrinked) values following the ordering. + */ + + for (i=0, var=0; i= 0) { + supportids[invpermids[i]] = var++; + } + } + /* set a dummy id for terminal nodes */ + supportids[nVars] = var; + + /* + * Select conversion array for extra var info + */ + + switch (mode) { + case DDDMP_MODE_TEXT: + switch (varinfo) { + case DDDMP_VARIDS: + outids = ids; + break; + case DDDMP_VARPERMIDS: + outids = permids; + break; + case DDDMP_VARAUXIDS: + outids = auxids; + break; + case DDDMP_VARNAMES: + outvarnames = varnames; + break; + case DDDMP_VARDEFAULT: + break; + } + break; + case DDDMP_MODE_BINARY: + outids = NULL; + break; + } + + /* + * Number dd nodes and count them (numbering is from 1 to nnodes) + */ + + nnodes = DddmpNumberBddNodes (ddMgr, f, nRoots); + + /* + * Start Header + */ + +#ifdef DDDMP_VERSION + retValue = fprintf (fp, ".ver %s\n", DDDMP_VERSION); + Dddmp_CheckAndGotoLabel (retValue==EOF, "Error writing to file.", + failure); +#endif + + retValue = fprintf (fp, ".mode %c\n", mode); + Dddmp_CheckAndGotoLabel (retValue==EOF, "Error writing to file.", + failure); + + if (mode == DDDMP_MODE_TEXT) { + retValue = fprintf (fp, ".varinfo %d\n", varinfo); + Dddmp_CheckAndGotoLabel (retValue==EOF, "Error writing to file.", + failure); + } + + if (ddname != NULL) { + retValue = fprintf (fp, ".dd %s\n",ddname); + Dddmp_CheckAndGotoLabel (retValue==EOF, "Error writing to file.", + failure); + } + + retValue = fprintf (fp, ".nnodes %d\n", nnodes); + Dddmp_CheckAndGotoLabel (retValue==EOF, "Error writing to file.", + failure); + + retValue = fprintf (fp, ".nvars %d\n", nVars); + Dddmp_CheckAndGotoLabel (retValue==EOF, "Error writing to file.", + failure); + + retValue = fprintf (fp, ".nsuppvars %d\n", var); + Dddmp_CheckAndGotoLabel (retValue==EOF, "Error writing to file.", + failure); + + /*------------ Write the Var Names by scanning the ids array -------------*/ + + if (varnames != NULL) { + + retValue = fprintf (fp, ".suppvarnames"); + Dddmp_CheckAndGotoLabel (retValue==EOF, "Error writing to file.", + failure); + + for (i=0; i= 0) { + if (varnames[ids[i]] == NULL) { + (void) fprintf (stderr, + "DdStore Warning: null variable name. DUMMY%d generated\n", i); + fflush (stderr); + varnames[ids[i]] = DDDMP_ALLOC (char, 10); + Dddmp_CheckAndGotoLabel (varnames[ids[i]] == NULL, + "Error allocating memory.", failure); + sprintf (varnames[ids[i]], "DUMMY%d", i); + } + retValue = fprintf (fp, " %s", varnames[ids[i]]); + Dddmp_CheckAndGotoLabel (retValue==EOF, "Error writing to file.", + failure); + } + } + + retValue = fprintf (fp, "\n"); + Dddmp_CheckAndGotoLabel (retValue==EOF, "Error writing to file.", + failure); + } + + /*--------- Write the Var SUPPORT Names by scanning the ids array ---------*/ + + if (varnames != NULL) { + retValue = fprintf (fp, ".orderedvarnames"); + Dddmp_CheckAndGotoLabel (retValue==EOF, "Error writing to file.", + failure); + + for (i=0; iinvperm[i]] == NULL) { + (void) fprintf (stderr, + "DdStore Warning: null variable name. DUMMY%d generated\n", i); + fflush (stderr); + varnames[ddMgr->invperm[i]] = DDDMP_ALLOC (char, 10); + Dddmp_CheckAndGotoLabel (varnames[ddMgr->invperm[i]] == NULL, + "Error allocating memory.", failure); + sprintf (varnames[ddMgr->invperm[i]], "DUMMY%d", i); + } + + retValue = fprintf (fp, " %s", varnames[ddMgr->invperm[i]]); + Dddmp_CheckAndGotoLabel (retValue==EOF, "Error writing to file.", + failure); + } + + retValue = fprintf (fp, "\n"); + Dddmp_CheckAndGotoLabel (retValue==EOF, "Error writing to file.", + failure); + } + + /*------------ Write the var ids by scanning the ids array ---------------*/ + + retValue = fprintf (fp, ".ids"); + Dddmp_CheckAndGotoLabel (retValue==EOF, "Error writing to file.", + failure); + + for (i=0; i= 0) { + retValue = fprintf (fp, " %d", i); + Dddmp_CheckAndGotoLabel (retValue==EOF, "Error writing to file.", + failure); + } + } + retValue = fprintf (fp, "\n"); + Dddmp_CheckAndGotoLabel (retValue==EOF, "Error writing to file.", + failure); + + /* + * Write the var permids by scanning the permids array. + */ + + retValue = fprintf (fp, ".permids"); + Dddmp_CheckAndGotoLabel (retValue==EOF, "Error writing to file.", + failure); + for (i = 0; i < nVars; i++) { + if (permids[i] >= 0) { + retValue = fprintf (fp, " %d", permids[i]); + Dddmp_CheckAndGotoLabel (retValue==EOF, "Error writing to file.", + failure); + } + } + + retValue = fprintf (fp, "\n"); + Dddmp_CheckAndGotoLabel (retValue==EOF, "Error writing to file.", + failure); + + if (auxids != NULL) { + + /* + * Write the var auxids by scanning the ids array. + */ + + retValue = fprintf (fp, ".auxids"); + Dddmp_CheckAndGotoLabel (retValue==EOF, "Error writing to file.", + failure); + for (i = 0; i < nVars; i++) { + if (ids[i] >= 0) { + retValue = fprintf (fp, " %d", auxids[i]); + Dddmp_CheckAndGotoLabel (retValue==EOF, "Error writing to file.", + failure); + } + } + retValue = fprintf (fp, "\n"); + Dddmp_CheckAndGotoLabel (retValue==EOF, "Error writing to file.", + failure); + } + + /* + * Write the roots info. + */ + + retValue = fprintf (fp, ".nroots %d\n", nRoots); + Dddmp_CheckAndGotoLabel (retValue==EOF, "Error writing to file.", + failure); + + if (rootnames != NULL) { + + /* + * Write the root names. + */ + + retValue = fprintf (fp, ".rootnames"); + Dddmp_CheckAndGotoLabel (retValue==EOF, "Error writing to file.", + failure); + + for (i = 0; i < nRoots; i++) { + if (rootnames[i] == NULL) { + (void) fprintf (stderr, + "DdStore Warning: null variable name. ROOT%d generated\n",i); + fflush (stderr); + rootnames[i] = DDDMP_ALLOC(char,10); + Dddmp_CheckAndGotoLabel (rootnames[i]==NULL, + "Error writing to file.", failure); + sprintf(rootnames[ids[i]], "ROOT%d",i); + } + retValue = fprintf (fp, " %s", rootnames[i]); + Dddmp_CheckAndGotoLabel (retValue==EOF, "Error writing to file.", + failure); + } + + retValue = fprintf (fp, "\n"); + Dddmp_CheckAndGotoLabel (retValue==EOF, "Error writing to file.", + failure); + } + + retValue = fprintf (fp, ".rootids"); + Dddmp_CheckAndGotoLabel (retValue==EOF, "Error writing to file.", + failure); + + /* + * Write BDD indexes of function roots. + * Use negative integers for complemented edges. + */ + + for (i = 0; i < nRoots; i++) { + if (f[i] == NULL) { + (void) fprintf (stderr, "DdStore Warning: %d-th root is NULL\n",i); + fflush (stderr); + retValue = fprintf (fp, " 0"); + } + if (Cudd_IsComplement(f[i])) { + retValue = fprintf (fp, " -%d", + DddmpReadNodeIndexBdd (Cudd_Regular (f[i]))); + } else { + retValue = fprintf (fp, " %d", + DddmpReadNodeIndexBdd (Cudd_Regular (f[i]))); + } + Dddmp_CheckAndGotoLabel (retValue==EOF, "Error writing to file.", + failure); + } + + retValue = fprintf (fp, "\n"); + Dddmp_CheckAndGotoLabel (retValue==EOF, "Error writing to file.", + failure); + + retValue = fprintf (fp, ".nodes\n"); + Dddmp_CheckAndGotoLabel (retValue==EOF, "Error writing to file.", + failure); + + /* + * END HEADER + */ + + /* + * Call the function that really gets the job done. + */ + + for (i = 0; i < nRoots; i++) { + if (f[i] != NULL) { + retValue = NodeStoreRecurBdd (ddMgr, Cudd_Regular(f[i]), + mode, supportids, outvarnames, outids, fp); + Dddmp_CheckAndGotoLabel (retValue==DDDMP_FAILURE, + "Error writing to file.", failure); + } + } + + /* + * Write trailer and return. + */ + + retValue = fprintf (fp, ".end\n"); + Dddmp_CheckAndGotoLabel (retValue==EOF, "Error writing to file.", + failure); + + if (fileToClose) { + fclose (fp); + } + + DddmpUnnumberBddNodes (ddMgr, f, nRoots); + DDDMP_FREE (ids); + DDDMP_FREE (permids); + DDDMP_FREE (invpermids); + DDDMP_FREE (supportids); + + return (DDDMP_SUCCESS); + + failure: + + if (ids != NULL) { + DDDMP_FREE (ids); + } + if (permids != NULL) { + DDDMP_FREE (permids); + } + if (invpermids != NULL) { + DDDMP_FREE (invpermids); + } + if (supportids != NULL) { + DDDMP_FREE (supportids); + } + if (support != NULL) { + Cudd_RecursiveDeref (ddMgr, support); + } + + return (DDDMP_FAILURE); +} + +/*---------------------------------------------------------------------------*/ +/* Definition of static functions */ +/*---------------------------------------------------------------------------*/ + +/**Function******************************************************************** + + Synopsis [Performs the recursive step of Dddmp_bddStore.] + + Description [Stores a node to file in either test or binary mode. + In text mode a node is represented (on a text line basis) as +
            +
          • node-index \[var-extrainfo\] var-index Then-index Else-index +
          + + where all indexes are integer numbers and var-extrainfo + (optional redundant field) is either an integer or a string + (variable name). Node-index is redundant (due to the node + ordering) but we keep it for readability.

          + + In binary mode nodes are represented as a sequence of bytes, + representing var-index, Then-index, and Else-index in an + optimized way. Only the first byte (code) is mandatory. + Integer indexes are represented in absolute or relative mode, + where relative means offset wrt. a Then/Else node info. + Suppose Var(NodeId), Then(NodeId) and Else(NodeId) represent + infos about a given node.

          + + The generic "NodeId" node is stored as + +

            +
          • code-byte +
          • \[var-info\] +
          • \[Then-info\] +
          • \[Else-info\] +
          + + where code-byte contains bit fields + +
            +
          • Unused : 1 bit +
          • Variable: 2 bits, one of the following codes +
              +
            • DDDMP_ABSOLUTE_ID var-info = Var(NodeId) follows +
            • DDDMP_RELATIVE_ID Var(NodeId) is represented in relative form as + var-info = Min(Var(Then(NodeId)),Var(Else(NodeId))) -Var(NodeId) +
            • DDDMP_RELATIVE_1 No var-info follows, because + Var(NodeId) = Min(Var(Then(NodeId)),Var(Else(NodeId)))-1 +
            • DDDMP_TERMINAL Node is a terminal, no var info required +
            +
          • T : 2 bits, with codes similar to V +
              +
            • DDDMP_ABSOLUTE_ID Then-info = Then(NodeId) follows +
            • DDDMP_RELATIVE_ID Then(NodeId) is represented in relative form as + Then-info = Nodeid-Then(NodeId) +
            • DDDMP_RELATIVE_1 No info on Then(NodeId) follows, because + Then(NodeId) = NodeId-1 +
            • DDDMP_TERMINAL Then Node is a terminal, no info required (for BDDs) +
            +
          • Ecompl : 1 bit, if 1 means complemented edge +
          • E : 2 bits, with codes and meanings as for the Then edge +
          + var-info, Then-info, Else-info (if required) are represented as unsigned + integer values on a sufficient set of bytes (MSByte first). + ] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ + +static int +NodeStoreRecurBdd ( + DdManager *ddMgr /* IN: DD Manager */, + DdNode *f /* IN: DD node to be stored */, + int mode /* IN: store mode */, + int *supportids /* IN: internal ids for variables */, + char **varnames /* IN: names of variables: to be stored with nodes */, + int *outids /* IN: output ids for variables */, + FILE *fp /* IN: store file */ + ) +{ + DdNode *T = NULL; + DdNode *E = NULL; + int idf = (-1); + int idT = (-1); + int idE = (-1); + int vf = (-1); + int vT = (-1); + int vE = (-1); + int retValue; + int nVars; + + nVars = ddMgr->size; + T = E = NULL; + idf = idT = idE = (-1); + +#ifdef DDDMP_DEBUG + assert(!Cudd_IsComplement(f)); + assert(f!=NULL); + assert(supportids!=NULL); +#endif + + /* If already visited, nothing to do. */ + if (DddmpVisitedBdd (f)) { + return (DDDMP_SUCCESS); + } + + /* Mark node as visited. */ + DddmpSetVisitedBdd (f); + + if (Cudd_IsConstant(f)) { + /* Check for special case: don't recur */ + idf = DddmpReadNodeIndexBdd (f); + } else { + +#ifdef DDDMP_DEBUG + /* BDDs! Only one constant supported */ + assert (!cuddIsConstant(f)); +#endif + + /* + * Recursive call for Then edge + */ + + T = cuddT(f); +#ifdef DDDMP_DEBUG + /* ROBDDs! No complemented Then edge */ + assert (!Cudd_IsComplement(T)); +#endif + /* recur */ + retValue = NodeStoreRecurBdd (ddMgr, T, mode, supportids, varnames, outids, + fp); + if (retValue != DDDMP_SUCCESS) { + return (retValue); + } + + /* + * Recursive call for Else edge + */ + + E = Cudd_Regular (cuddE (f)); + retValue = NodeStoreRecurBdd (ddMgr, E, mode, supportids, varnames, outids, + fp); + if (retValue != DDDMP_SUCCESS) { + return (retValue); + } + + /* + * Obtain nodeids and variable ids of f, T, E + */ + + idf = DddmpReadNodeIndexBdd (f); + vf = f->index; + + idT = DddmpReadNodeIndexBdd (T); + if (Cudd_IsConstant(T)) { + vT = nVars; + } else { + vT = T->index; + } + + idE = DddmpReadNodeIndexBdd (E); + if (Cudd_IsConstant(E)) { + vE = nVars; + } else { + vE = E->index; + } + } + + switch (mode) { + case DDDMP_MODE_TEXT: + retValue = NodeTextStoreBdd (ddMgr, f, mode, supportids, varnames, + outids, fp, idf, vf, idT, idE); + break; + case DDDMP_MODE_BINARY: + retValue = NodeBinaryStoreBdd (ddMgr, f, mode, supportids, varnames, + outids, fp, idf, vf, idT, idE, vT, vE, T, E); + break; + default: + return (DDDMP_FAILURE); + } + + return (retValue); +} + +/**Function******************************************************************** + + Synopsis [Store One Single Node in Text Format.] + + Description [Store 1 0 0 for the terminal node. + Store id, left child pointer, right pointer for all the other nodes. + ] + + SideEffects [None] + + SeeAlso [NodeBinaryStoreBdd] + +******************************************************************************/ + +static int +NodeTextStoreBdd ( + DdManager *ddMgr /* IN: DD Manager */, + DdNode *f /* IN: DD node to be stored */, + int mode /* IN: store mode */, + int *supportids /* IN: internal ids for variables */, + char **varnames /* IN: names of variables: to be stored with nodes */, + int *outids /* IN: output ids for variables */, + FILE *fp /* IN: Store file */, + int idf /* IN: index of the current node */, + int vf /* IN: variable of the current node */, + int idT /* IN: index of the Then node */, + int idE /* IN: index of the Else node */ + ) +{ + int retValue = EOF; + + /* + * Check for Constant + */ + + if (Cudd_IsConstant(f)) { + + if (f == Cudd_ReadOne(ddMgr)) { + if ((varnames != NULL) || (outids != NULL)) { + retValue = fprintf (fp, "%d T 1 0 0\n", idf); + } else { + retValue = fprintf (fp, "%d 1 0 0\n", idf); + } + + if (retValue == EOF) { + return (DDDMP_FAILURE); + } else { + return (DDDMP_SUCCESS); + } + } + + if (f == Cudd_ReadZero(ddMgr)) { + if ((varnames != NULL) || (outids != NULL)) { + retValue = fprintf (fp, "%d T 0 0 0\n", idf); + } else { + retValue = fprintf (fp, "%d 0 0 0\n", idf); + } + + if (retValue == EOF) { + return (DDDMP_FAILURE); + } else { + return (DDDMP_SUCCESS); + } + } + + /* + * A constant node different from 1: an ADD constant + */ + + Dddmp_CheckAndReturn (((varnames!=NULL)||(outids!=NULL)), + "Error writing to file: ADD Type."); + + if (retValue == EOF) { + return (DDDMP_FAILURE); + } else { + return (DDDMP_SUCCESS); + } + } + + /* + * ... Not A Constant + */ + + if (Cudd_IsComplement (cuddE(f))) { + idE = -idE; + } + + if (varnames != NULL) { + retValue = fprintf (fp, "%d %s %d %d %d\n", + idf, varnames[vf], supportids[vf], idT, idE); + + if (retValue == EOF) { + return (DDDMP_FAILURE); + } else { + return (DDDMP_SUCCESS); + } + } + + if (outids != NULL) { + retValue = fprintf (fp, "%d %d %d %d %d\n", + idf, outids[vf], supportids[vf], idT, idE); + + if (retValue == EOF) { + return (DDDMP_FAILURE); + } else { + return (DDDMP_SUCCESS); + } + } + + retValue = fprintf (fp, "%d %d %d %d\n", + idf, supportids[vf], idT, idE); + + if (retValue == EOF) { + return (DDDMP_FAILURE); + } else { + return (DDDMP_SUCCESS); + } +} + +/**Function******************************************************************** + + Synopsis [Store One Single Node in Binary Format.] + + Description [Store 1 0 0 for the terminal node. + Store id, left child pointer, right pointer for all the other nodes. + Store every information as coded binary values.] + + SideEffects [None] + + SeeAlso [NodeTextStoreBdd] + +******************************************************************************/ + +static int +NodeBinaryStoreBdd ( + DdManager *ddMgr /* IN: DD Manager */, + DdNode *f /* IN: DD node to be stored */, + int mode /* IN: store mode */, + int *supportids /* IN: internal ids for variables */, + char **varnames /* IN: names of variables: to be stored with nodes */, + int *outids /* IN: output ids for variables */, + FILE *fp /* IN: store file */, + int idf /* IN: index of the node */, + int vf /* IN: variable of the node */, + int idT /* IN: index of the Then node */, + int idE /* IN: index of the Else node */, + int vT /* IN: variable of the Then node */, + int vE /* IN: variable of the Else node */, + DdNode *T /* IN: Then node */, + DdNode *E /* IN: Else node */ + ) +{ + int retValue, diff, var; + struct binary_dd_code code; + + /* + * Check for Constant + */ + + /* only integer ids used, varnames ignored */ + /* Terminal one is coded as DDDMP_TERMINAL, all other fields are 0 */ + if (Cudd_IsConstant(f)) { + code.Unused = 0; + code.V = DDDMP_TERMINAL; + code.T = 0; + code.E = 0; + code.Ecompl = 0; + retValue = DddmpWriteCode (fp,code); + if (retValue == EOF) { + return (DDDMP_FAILURE); + } else { + return (DDDMP_SUCCESS); + } + } + + /* + * Non terminal: output variable id + */ + + var = supportids[vf]; + diff = (supportids[vT] +#include "dddmpInt.h" + +/*-------------------------------1--------------------------------------------*/ +/* Stucture declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Type declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Variable declarations */ +/*---------------------------------------------------------------------------*/ + +#define DDDMP_DEBUG_CNF 0 + +/*---------------------------------------------------------------------------*/ +/* Macro declarations */ +/*---------------------------------------------------------------------------*/ + +#define GET_MAX(x,y) (x>y?x:y) + +/**AutomaticStart*************************************************************/ + +/*---------------------------------------------------------------------------*/ +/* Static function prototypes */ +/*---------------------------------------------------------------------------*/ + +static int DddmpCuddBddArrayStoreCnf(DdManager *ddMgr, DdNode **f, int rootN, Dddmp_DecompCnfStoreType mode, int noHeader, char **varNames, int *bddIds, int *bddAuxIds, int *cnfIds, int idInitial, int edgeInTh, int pathLengthTh, char *fname, FILE *fp, int *clauseNPtr, int *varNewNPtr); +static int StoreCnfNodeByNode(DdManager *ddMgr, DdNode **f, int rootN, int *bddIds, int *cnfIds, FILE *fp, int *clauseN, int *varMax, int *rootStartLine); +static int StoreCnfNodeByNodeRecur(DdManager *ddMgr, DdNode *f, int *bddIds, int *cnfIds, FILE *fp, int *clauseN, int *varMax); +static int StoreCnfOneNode(DdNode *f, int idf, int vf, int idT, int idE, FILE *fp, int *clauseN, int *varMax); +static int StoreCnfMaxtermByMaxterm(DdManager *ddMgr, DdNode **f, int rootN, int *bddIds, int *cnfIds, int idInitial, FILE *fp, int *varMax, int *clauseN, int *rootStartLine); +static int StoreCnfBest(DdManager *ddMgr, DdNode **f, int rootN, int *bddIds, int *cnfIds, int idInitial, FILE *fp, int *varMax, int *clauseN, int *rootStartLine); +static void StoreCnfMaxtermByMaxtermRecur(DdManager *ddMgr, DdNode *node, int *bddIds, int *cnfIds, FILE *fp, int *list, int *clauseN, int *varMax); +static int StoreCnfBestNotSharedRecur(DdManager *ddMgr, DdNode *node, int idf, int *bddIds, int *cnfIds, FILE *fp, int *list, int *clauseN, int *varMax); +static int StoreCnfBestSharedRecur(DdManager *ddMgr, DdNode *node, int *bddIds, int *cnfIds, FILE *fp, int *list, int *clauseN, int *varMax); +static int printCubeCnf(DdManager *ddMgr, DdNode *node, int *cnfIds, FILE *fp, int *list, int *varMax); + +/**AutomaticEnd***************************************************************/ + +/*---------------------------------------------------------------------------*/ +/* Definition of exported functions */ +/*---------------------------------------------------------------------------*/ + +/**Function******************************************************************** + + Synopsis [Writes a dump file representing the argument BDD in + a CNF format. + ] + + Description [Dumps the argument BDD to file. + This task is performed by calling the function + Dddmp_cuddBddArrayStoreCnf. + ] + + SideEffects [Nodes are temporarily removed from unique hash. They are + re-linked after the store operation in a modified order. + ] + + SeeAlso [Dddmp_cuddBddArrayStoreCnf] + +******************************************************************************/ + +int +Dddmp_cuddBddStoreCnf ( + DdManager *ddMgr /* IN: DD Manager */, + DdNode *f /* IN: BDD root to be stored */, + Dddmp_DecompCnfStoreType mode /* IN: format selection */, + int noHeader /* IN: do not store header iff 1 */, + char **varNames /* IN: array of variable names (or NULL) */, + int *bddIds /* IN: array of var ids */, + int *bddAuxIds /* IN: array of BDD node Auxiliary Ids */, + int *cnfIds /* IN: array of CNF var ids */, + int idInitial /* IN: starting id for cutting variables */, + int edgeInTh /* IN: Max # Incoming Edges */, + int pathLengthTh /* IN: Max Path Length */, + char *fname /* IN: file name */, + FILE *fp /* IN: pointer to the store file */, + int *clauseNPtr /* OUT: number of clause stored */, + int *varNewNPtr /* OUT: number of new variable created */ + ) +{ + int retValue; + DdNode *tmpArray[1]; + + tmpArray[0] = f; + + retValue = Dddmp_cuddBddArrayStoreCnf (ddMgr, tmpArray, 1, mode, + noHeader, varNames, bddIds, bddAuxIds, cnfIds, idInitial, edgeInTh, + pathLengthTh, fname, fp, clauseNPtr, varNewNPtr); + + Dddmp_CheckAndReturn (retValue==DDDMP_FAILURE, "Failure."); + + return (DDDMP_SUCCESS); +} + +/**Function******************************************************************** + + Synopsis [Writes a dump file representing the argument array of BDDs + in CNF format. + ] + + Description [Dumps the argument array of BDDs to file.] + + SideEffects [Nodes are temporarily removed from the unique hash + table. They are re-linked after the store operation in a + modified order. + Three methods are allowed: + * NodeByNode method: Insert a cut-point for each BDD node (but the + terminal nodes) + * MaxtermByMaxterm method: Insert no cut-points, i.e. the off-set of + trhe function is stored + * Best method: Tradeoff between the previous two methods. + Auxiliary variables, i.e., cut points are inserted following these + criterias: + * edgeInTh + indicates the maximum number of incoming edges up to which + no cut point (auxiliary variable) is inserted. + If edgeInTh: + * is equal to -1 no cut point due to incoming edges are inserted + (MaxtermByMaxterm method.) + * is equal to 0 a cut point is inserted for each node with a single + incoming edge, i.e., each node, (NodeByNode method). + * is equal to n a cut point is inserted for each node with (n+1) + incoming edges. + * pathLengthTh + indicates the maximum length path up to which no cut points + (auxiliary variable) is inserted. + If the path length between two nodes exceeds this value, a cut point + is inserted. + If pathLengthTh: + * is equal to -1 no cut point due path length are inserted + (MaxtermByMaxterm method.) + * is equal to 0 a cut point is inserted for each node (NodeByNode + method). + * is equal to n a cut point is inserted on path whose length is + equal to (n+1). + Notice that the maximum number of literals in a clause is equal + to (pathLengthTh + 2), i.e., for each path we have to keep into + account a CNF variable for each node plus 2 added variables for + the bottom and top-path cut points. + The stored file can contain a file header or not depending on the + noHeader parameter (IFF 0, usual setting, the header is usually stored. + This option can be useful in storing multiple BDDs, as separate BDDs, + on the same file leaving the opening of the file to the caller. + ] + + SeeAlso [] + +******************************************************************************/ + +int +Dddmp_cuddBddArrayStoreCnf ( + DdManager *ddMgr /* IN: DD Manager */, + DdNode **f /* IN: array of BDD roots to be stored */, + int rootN /* IN: # output BDD roots to be stored */, + Dddmp_DecompCnfStoreType mode /* IN: format selection */, + int noHeader /* IN: do not store header iff 1 */, + char **varNames /* IN: array of variable names (or NULL) */, + int *bddIds /* IN: array of converted var IDs */, + int *bddAuxIds /* IN: array of BDD node Auxiliary Ids */, + int *cnfIds /* IN: array of converted var IDs */, + int idInitial /* IN: starting id for cutting variables */, + int edgeInTh /* IN: Max # Incoming Edges */, + int pathLengthTh /* IN: Max Path Length */, + char *fname /* IN: file name */, + FILE *fp /* IN: pointer to the store file */, + int *clauseNPtr /* OUT: number of clause stored */, + int *varNewNPtr /* OUT: number of new variable created */ + ) +{ + int retValue2; + +#if 0 +#ifdef DDDMP_DEBUG +#ifndef __alpha__ + int retValue1; + + retValue1 = Cudd_DebugCheck (ddMgr); + Dddmp_CheckAndReturn (retValue1==1, + "Inconsistency Found During CNF Store."); + Dddmp_CheckAndReturn (retValue1==CUDD_OUT_OF_MEM, + "Out of Memory During CNF Store."); +#endif +#endif +#endif + + retValue2 = DddmpCuddBddArrayStoreCnf (ddMgr, f, rootN, mode, noHeader, + varNames, bddIds, bddAuxIds, cnfIds, idInitial, edgeInTh, pathLengthTh, + fname, fp, clauseNPtr, varNewNPtr); + +#if 0 +#ifdef DDDMP_DEBUG +#ifndef __alpha__ + retValue1 = Cudd_DebugCheck (ddMgr); + Dddmp_CheckAndReturn (retValue1==1, + "Inconsistency Found During CNF Store."); + Dddmp_CheckAndReturn (retValue1==CUDD_OUT_OF_MEM, + "Out of Memory During CNF Store."); +#endif +#endif +#endif + + return (retValue2); +} + +/*---------------------------------------------------------------------------*/ +/* Definition of internal functions */ +/*---------------------------------------------------------------------------*/ + +/**Function******************************************************************** + + Synopsis [Writes a dump file representing the argument Array of + BDDs in the CNF standard format. + ] + + Description [Dumps the argument array of BDDs/ADDs to file in CNF format. + The following arrays: varNames, bddIds, bddAuxIds, and cnfIds + fix the correspondence among variable names, BDD ids, BDD + auxiliary ids and the ids used to store the CNF problem. + All these arrays are automatically created iff NULL. + Auxiliary variable, iff necessary, are created starting from value + idInitial. + Iff idInitial is <= 0 its value is selected as the number of internal + CUDD variable + 2. + Auxiliary variables, i.e., cut points are inserted following these + criterias: + * edgeInTh + indicates the maximum number of incoming edges up to which + no cut point (auxiliary variable) is inserted. + If edgeInTh: + * is equal to -1 no cut point due to incoming edges are inserted + (MaxtermByMaxterm method.) + * is equal to 0 a cut point is inserted for each node with a single + incoming edge, i.e., each node, (NodeByNode method). + * is equal to n a cut point is inserted for each node with (n+1) + incoming edges. + * pathLengthTh + indicates the maximum length path up to which no cut points + (auxiliary variable) is inserted. + If the path length between two nodes exceeds this value, a cut point + is inserted. + If pathLengthTh: + * is equal to -1 no cut point due path length are inserted + (MaxtermByMaxterm method.) + * is equal to 0 a cut point is inserted for each node (NodeByNode + method). + * is equal to n a cut point is inserted on path whose length is + equal to (n+1). + Notice that the maximum number of literals in a clause is equal + to (pathLengthTh + 2), i.e., for each path we have to keep into + account a CNF variable for each node plus 2 added variables for + the bottom and top-path cut points. + ] + + SideEffects [Nodes are temporarily removed from the unique hash table. + They are re-linked after the store operation in a modified + order. + ] + + SeeAlso [Dddmp_cuddBddStore] + +******************************************************************************/ + +static int +DddmpCuddBddArrayStoreCnf ( + DdManager *ddMgr /* IN: DD Manager */, + DdNode **f /* IN: array of BDD roots to be stored */, + int rootN /* IN: # of output BDD roots to be stored */, + Dddmp_DecompCnfStoreType mode /* IN: format selection */, + int noHeader /* IN: do not store header iff 1 */, + char **varNames /* IN: array of variable names (or NULL) */, + int *bddIds /* IN: array of BDD node Ids (or NULL) */, + int *bddAuxIds /* IN: array of BDD Aux Ids (or NULL) */, + int *cnfIds /* IN: array of CNF ids (or NULL) */, + int idInitial /* IN: starting id for cutting variables */, + int edgeInTh /* IN: Max # Incoming Edges */, + int pathLengthTh /* IN: Max Path Length */, + char *fname /* IN: file name */, + FILE *fp /* IN: pointer to the store file */, + int *clauseNPtr /* OUT: number of clause stored */, + int *varNewNPtr /* OUT: number of new variable created */ + ) +{ + DdNode *support = NULL; + DdNode *scan = NULL; + int *bddIdsInSupport = NULL; + int *permIdsInSupport = NULL; + int *rootStartLine = NULL; + int nVar, nVarInSupport, retValue, i, j, fileToClose; + int varMax, clauseN, flagVar, intStringLength; + int bddIdsToFree = 0; + int bddAuxIdsToFree = 0; + int cnfIdsToFree = 0; + int varNamesToFree = 0; + char intString[DDDMP_MAXSTRLEN]; + char tmpString[DDDMP_MAXSTRLEN]; + fpos_t posFile1, posFile2; + + /*---------------------------- Set Initial Values -------------------------*/ + + support = scan = NULL; + bddIdsInSupport = permIdsInSupport = rootStartLine = NULL; + nVar = ddMgr->size; + fileToClose = 0; + sprintf (intString, "%d", INT_MAX); + intStringLength = strlen (intString); + + /*---------- Check if File needs to be opened in the proper mode ----------*/ + + if (fp == NULL) { + fp = fopen (fname, "w"); + Dddmp_CheckAndGotoLabel (fp==NULL, "Error opening file.", + failure); + fileToClose = 1; + } + + /*--------- Generate Bdd LOCAL IDs and Perm IDs and count them ------------*/ + + /* BDD Ids */ + bddIdsInSupport = DDDMP_ALLOC (int, nVar); + Dddmp_CheckAndGotoLabel (bddIdsInSupport==NULL, "Error allocating memory.", + failure); + /* BDD PermIds */ + permIdsInSupport = DDDMP_ALLOC (int, nVar); + Dddmp_CheckAndGotoLabel (permIdsInSupport==NULL, "Error allocating memory.", + failure); + /* Support Size (Number of BDD Ids-PermIds */ + nVarInSupport = 0; + + for (i=0; iindex] = scan->index; + permIdsInSupport[scan->index] = ddMgr->perm[scan->index]; + scan = cuddT (scan); + } + Cudd_RecursiveDeref (ddMgr, support); + } + /* so that we do not try to free it in case of failure */ + support = NULL; + + /*---------------------------- Start HEADER -------------------------------*/ + + if (noHeader==0) { + + retValue = fprintf (fp, + "c # BDD stored by the DDDMP tool in CNF format\n"); + Dddmp_CheckAndGotoLabel (retValue==EOF, "Error writing on file.", + failure); + fprintf (fp, "c #\n"); + } + + /*-------------------- Generate Bdd IDs IFF necessary ---------------------*/ + + if (bddIds == NULL) { + if (noHeader==0) { + fprintf (fp, "c # Warning: BDD IDs missing ... evaluating them.\n"); + fprintf (fp, "c # \n"); + fflush (fp); + } + + bddIdsToFree = 1; + bddIds = DDDMP_ALLOC (int, nVar); + Dddmp_CheckAndGotoLabel (bddIds==NULL, "Error allocating memory.", + failure); + + /* Get BDD-IDs Directly from Cudd Manager */ + for (i=0; i= 0) { + fprintf (fp, " %s", varNames[i]); + } + } + fprintf (fp, "\n"); + } + + /* Ordered Variable Names */ + if (varNames != NULL) { + fprintf (fp, "c .orderedvarnames"); + for (i=0; i= 0) { + fprintf (fp, " %d", bddIdsInSupport[i]); + } + } + fprintf (fp, "\n"); + + /* BDD Variable Permutation Ids */ + fprintf (fp, "c .permids "); + for (i=0; i= 0) { + fprintf (fp, " %d", permIdsInSupport[i]); + } + } + fprintf (fp, "\n"); + + /* BDD Variable Auxiliary Ids */ + fprintf (fp, "c .auxids "); + for (i=0; i= 0) { + fprintf (fp, " %d", bddAuxIds[i]); + } + } + fprintf (fp, "\n"); + + /* CNF Ids */ + fprintf (fp, "c .cnfids "); + for (i=0; i= 0) { + fprintf (fp, " %d", cnfIds[i]); + } + } + fprintf (fp, "\n"); + + /* Number of Roots */ + fprintf (fp, "c .nroots %d", rootN); + fprintf (fp, "\n"); + + /* Root Starting Line */ + fgetpos (fp, &posFile1); + fprintf (fp, "c .rootids"); + for (i=0; i \n", i); +#endif + if (Cudd_IsComplement (f[i])) { + retValue = fprintf (fp, "-%d 0\n", idf); + } else { + retValue = fprintf (fp, "%d 0\n", idf); + } + *varMax = GET_MAX (*varMax, idf); + *clauseN = *clauseN + 1; + + if (retValue == EOF) { + (void) fprintf (stderr, + "DdStoreCnf: Error in recursive node store\n"); + fflush (stderr); + } + } + } + } + + return (retValue); +} + +/**Function******************************************************************** + + Synopsis [Performs the recursive step of Dddmp_bddStore.] + + Description [Performs the recursive step of Dddmp_bddStore. + Traverse the BDD and store a CNF formula for each "terminal" node. + ] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ + +static int +StoreCnfNodeByNodeRecur ( + DdManager *ddMgr /* IN: DD Manager */, + DdNode *f /* IN: BDD node to be stored */, + int *bddIds /* IN: BDD ids for variables */, + int *cnfIds /* IN: CNF ids for variables */, + FILE *fp /* IN: store file */, + int *clauseN /* OUT: number of clauses written in the CNF file */, + int *varMax /* OUT: maximum value of id written in the CNF file */ + ) +{ + DdNode *T, *E; + int idf, idT, idE, vf; + int retValue; + +#ifdef DDDMP_DEBUG + assert(!Cudd_IsComplement(f)); + assert(f!=NULL); +#endif + + /* If constant, nothing to do. */ + if (Cudd_IsConstant(f)) { + return (1); + } + + /* If already visited, nothing to do. */ + if (DddmpVisitedCnf (f)) { + return (1); + } + + /* Mark node as visited. */ + DddmpSetVisitedCnf (f); + + /*------------------ Non Terminal Node -------------------------------*/ + +#ifdef DDDMP_DEBUG + /* BDDs! Only one constant supported */ + assert (!cuddIsConstant(f)); +#endif + + /* + * Recursive call for Then edge + */ + + T = cuddT (f); +#ifdef DDDMP_DEBUG + /* ROBDDs! No complemented Then edge */ + assert (!Cudd_IsComplement(T)); +#endif + /* recur */ + retValue = StoreCnfNodeByNodeRecur (ddMgr, T, bddIds, cnfIds, fp, + clauseN, varMax); + if (retValue != 1) { + return(retValue); + } + + /* + * Recursive call for Else edge + */ + + E = Cudd_Regular (cuddE (f)); + retValue = StoreCnfNodeByNodeRecur (ddMgr, E, bddIds, cnfIds, fp, + clauseN, varMax); + if (retValue != 1) { + return (retValue); + } + + /* + * Obtain nodeids and variable ids of f, T, E + */ + + idf = DddmpReadNodeIndexCnf (f); + vf = f->index; + + if (bddIds[vf] != vf) { + (void) fprintf (stderr, "DdStoreCnf: Error writing to file\n"); + fflush (stderr); + return (0); + } + + idT = DddmpReadNodeIndexCnf (T); + + idE = DddmpReadNodeIndexCnf (E); + if (Cudd_IsComplement (cuddE (f))) { + idE = -idE; + } + + retValue = StoreCnfOneNode (f, idf, cnfIds[vf], idT, idE, fp, + clauseN, varMax); + + if (retValue == EOF) { + return (0); + } else { + return (1); + } +} + +/**Function******************************************************************** + + Synopsis [Store One Single BDD Node.] + + Description [Store One Single BDD Node translating it as a multiplexer.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ + +static int +StoreCnfOneNode ( + DdNode *f /* IN: node to be stored */, + int idf /* IN: node CNF Index */, + int vf /* IN: node BDD Index */, + int idT /* IN: Then CNF Index with sign = inverted edge */, + int idE /* IN: Else CNF Index with sign = inverted edge */, + FILE *fp /* IN: store file */, + int *clauseN /* OUT: number of clauses */, + int *varMax /* OUT: maximun Index of variable stored */ + ) +{ + int retValue = 0; + int idfAbs, idTAbs, idEAbs; + + idfAbs = abs (idf); + idTAbs = abs (idT); + idEAbs = abs (idE); + + /*----------------------------- Check for Constant ------------------------*/ + + assert(!Cudd_IsConstant(f)); + + /*------------------------- Check for terminal nodes ----------------------*/ + + if ((idTAbs==1) && (idEAbs==1)) { + return (1); + } + + /*------------------------------ Internal Node ----------------------------*/ + +#if DDDMP_DEBUG_CNF + retValue = fprintf (fp, "id=%d var=%d idT=%d idE=%d\n", + idf, vf, idT, idE); +#endif + + /* + * Then to terminal + */ + + if ((idTAbs==1) && (idEAbs!=1)) { +#if DDDMP_DEBUG_CNF + retValue = fprintf (fp, "CASE 1 -->\n"); +#endif + retValue = fprintf (fp, "%d %d 0\n", + idf, -vf); + retValue = fprintf (fp, "%d %d 0\n", + idf, -idE); + retValue = fprintf (fp, "%d %d %d 0\n", + -idf, vf, idE); + *clauseN = *clauseN + 3; + + *varMax = GET_MAX (*varMax, idfAbs); + *varMax = GET_MAX (*varMax, vf); + *varMax = GET_MAX (*varMax, idEAbs); + } + + /* + * Else to terminal + */ + + if ((idTAbs!=1) && (idEAbs==1)) { + if (idE == 1) { +#if DDDMP_DEBUG_CNF + retValue = fprintf (fp, "CASE 2 -->\n"); +#endif + retValue = fprintf (fp, "%d %d 0\n", + idf, vf); + retValue = fprintf (fp, "%d %d 0\n", + idf, -idT); + retValue = fprintf (fp, "%d %d %d 0\n", + -idf, -vf, idT); + } else { +#if DDDMP_DEBUG_CNF + retValue = fprintf (fp, "CASE 3 -->\n"); +#endif + retValue = fprintf (fp, "%d %d 0\n", + -idf, vf); + retValue = fprintf (fp, "%d %d 0\n", + -idf, idT); + retValue = fprintf (fp, "%d %d %d 0\n", + idf, -vf, -idT); + } + + *varMax = GET_MAX (*varMax, idfAbs); + *varMax = GET_MAX (*varMax, vf); + *varMax = GET_MAX (*varMax, idTAbs); + + *clauseN = *clauseN + 3; + } + + /* + * Nor Then or Else to terminal + */ + + if ((idTAbs!=1) && (idEAbs!=1)) { +#if DDDMP_DEBUG_CNF + retValue = fprintf (fp, "CASE 4 -->\n"); +#endif + retValue = fprintf (fp, "%d %d %d 0\n", + idf, vf, -idE); + retValue = fprintf (fp, "%d %d %d 0\n", + -idf, vf, idE); + retValue = fprintf (fp, "%d %d %d 0\n", + idf, -vf, -idT); + retValue = fprintf (fp, "%d %d %d 0\n", + -idf, -vf, idT); + + *varMax = GET_MAX (*varMax, idfAbs); + *varMax = GET_MAX (*varMax, vf); + *varMax = GET_MAX (*varMax, idTAbs); + *varMax = GET_MAX (*varMax, idEAbs); + + *clauseN = *clauseN + 4; + } + + return (retValue); +} + +/**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 a + leaf node different from the logical zero, and different from + the background value. Uses the standard output. Returns 1 if + successful, 0 otherwise. + ] + + SideEffects [None] + + SeeAlso [StoreCnfBest] + +******************************************************************************/ + +static int +StoreCnfMaxtermByMaxterm ( + DdManager *ddMgr /* IN: DD Manager */, + DdNode **f /* IN: array of BDDs to store */, + int rootN /* IN: number of BDDs in the array */, + int *bddIds /* IN: BDD Identifiers */, + int *cnfIds /* IN: corresponding CNF Identifiers */, + int idInitial /* IN: initial value for numbering new CNF variables */, + FILE *fp /* IN: file pointer */, + int *varMax /* OUT: maximum identifier of the variables created */, + int *clauseN /* OUT: number of stored clauses */, + int *rootStartLine /* OUT: line where root starts */ + ) +{ + int i, j, *list; + + list = DDDMP_ALLOC (int, ddMgr->size); + if (list == NULL) { + ddMgr->errorCode = CUDD_MEMORY_OUT; + return (DDDMP_FAILURE); + } + + for (i=0; isize; j++) { + list[j] = 2; + } + + /* + * Set Starting Line for this Root + */ + + rootStartLine[i] = *clauseN + 1; + + StoreCnfMaxtermByMaxtermRecur (ddMgr, f[i], bddIds, cnfIds, fp, + list, clauseN, varMax); + } + } + } + + FREE (list); + + return (1); +} + +/**Function******************************************************************** + + Synopsis [Prints a disjoint sum of products with intermediate + cutting points.] + + Description [Prints a disjoint sum of product cover for the function + rooted at node intorducing cutting points whenever necessary. + Each product corresponds to a path from node a leaf + node different from the logical zero, and different from the + background value. Uses the standard output. Returns 1 if + successful, 0 otherwise. + ] + + SideEffects [None] + + SeeAlso [StoreCnfMaxtermByMaxterm] + +******************************************************************************/ + +static int +StoreCnfBest ( + DdManager *ddMgr /* IN: DD Manager */, + DdNode **f /* IN: array of BDDs to store */, + int rootN /* IN: number of BDD in the array */, + int *bddIds /* IN: BDD identifiers */, + int *cnfIds /* IN: corresponding CNF identifiers */, + int idInitial /* IN: initial value for numbering new CNF variables */, + FILE *fp /* IN: file pointer */, + int *varMax /* OUT: maximum identifier of the variables created */, + int *clauseN /* OUT: number of stored clauses */, + int *rootStartLine /* OUT: line where root starts */ + ) +{ + int i, j, *list; + + list = DDDMP_ALLOC (int, ddMgr->size); + if (list == NULL) { + ddMgr->errorCode = CUDD_MEMORY_OUT; + return (DDDMP_FAILURE); + } + + for (i=0; isize; j++) { + list[j] = 2; + } + + /* + * Set Starting Line for this Root + */ + + rootStartLine[i] = *clauseN + 1; + +#if DDDMP_DEBUG_CNF + fprintf (fp, "root NOT shared BDDs %d --> \n", i); +#endif + StoreCnfBestNotSharedRecur (ddMgr, f[i], 0, bddIds, cnfIds, fp, list, + clauseN, varMax); + +#if DDDMP_DEBUG_CNF + fprintf (fp, "root SHARED BDDs %d --> \n", i); +#endif + StoreCnfBestSharedRecur (ddMgr, Cudd_Regular (f[i]), bddIds, cnfIds, + fp, list, clauseN, varMax); + } + } + } + +#if DDDMP_DEBUG_CNF + fprintf (stdout, "###---> BDDs After the Storing Process:\n"); + DddmpPrintBddAndNext (ddMgr, f, rootN); +#endif + + FREE (list); + + return (DDDMP_SUCCESS); +} + +/**Function******************************************************************** + + Synopsis [Performs the recursive step of Print Maxterm.] + + Description [Performs the recursive step of Print Maxterm. + Traverse a BDD a print out a cube in CNF format each time a terminal + node is reached. + ] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ + +static void +StoreCnfMaxtermByMaxtermRecur ( + DdManager *ddMgr /* IN: DD Manager */, + DdNode *node /* IN: BDD to store */, + int *bddIds /* IN: BDD identifiers */, + int *cnfIds /* IN: corresponding CNF identifiers */, + FILE *fp /* IN: file pointer */, + int *list /* IN: temporary array to store cubes */, + int *clauseN /* OUT: number of stored clauses */, + int *varMax /* OUT: maximum identifier of the variables created */ + ) +{ + DdNode *N, *Nv, *Nnv; + int retValue, index; + + N = Cudd_Regular (node); + + /* + * Terminal case: Print one cube based on the current recursion + */ + + if (cuddIsConstant (N)) { + retValue = printCubeCnf (ddMgr, node, cnfIds, fp, list, varMax); + if (retValue == DDDMP_SUCCESS) { + fprintf (fp, "0\n"); + *clauseN = *clauseN + 1; + } + return; + } + + /* + * NON Terminal case: Recur + */ + + Nv = cuddT (N); + Nnv = cuddE (N); + if (Cudd_IsComplement (node)) { + Nv = Cudd_Not (Nv); + Nnv = Cudd_Not (Nnv); + } + index = N->index; + + /* + * StQ 06.05.2003 + * Perform the optimization: + * f = (a + b)' = (a') ^ (a + b') = (a') ^ (b') + * i.e., if the THEN node is the constant ZERO then that variable + * can be forgotten (list[index] = 2) for subsequent ELSE cubes + */ + if (cuddIsConstant (Cudd_Regular (Nv)) && Nv != ddMgr->one) { + list[index] = 2; + } else { + list[index] = 0; + } + StoreCnfMaxtermByMaxtermRecur (ddMgr, Nnv, bddIds, cnfIds, fp, list, + clauseN, varMax); + + /* + * StQ 06.05.2003 + * Perform the optimization: + * f = a ^ b = (a) ^ (a' + b) = (a) ^ (b) + * i.e., if the ELSE node is the constant ZERO then that variable + * can be forgotten (list[index] = 2) for subsequent THEN cubes + */ + if (cuddIsConstant (Cudd_Regular (Nnv)) && Nnv != ddMgr->one) { + list[index] = 2; + } else { + list[index] = 1; + } + StoreCnfMaxtermByMaxtermRecur (ddMgr, Nv, bddIds, cnfIds, fp, list, + clauseN, varMax); + list[index] = 2; + + return; +} + +/**Function******************************************************************** + + Synopsis [Performs the recursive step of Print Best on Not Shared + sub-BDDs.] + + Description [Performs the recursive step of Print Best on Not Shared + sub-BDDs, i.e., print out information for the nodes belonging to + BDDs not shared (whose root has just one incoming edge). + ] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ + +static int +StoreCnfBestNotSharedRecur ( + DdManager *ddMgr /* IN: DD Manager */, + DdNode *node /* IN: BDD to store */, + int idf /* IN: Id to store */, + int *bddIds /* IN: BDD identifiers */, + int *cnfIds /* IN: corresponding CNF identifiers */, + FILE *fp /* IN: file pointer */, + int *list /* IN: temporary array to store cubes */, + int *clauseN /* OUT: number of stored clauses */, + int *varMax /* OUT: maximum identifier of the variables created */ + ) +{ + DdNode *N, *Nv, *Nnv; + int index, retValue; + DdNode *one; + + one = ddMgr->one; + + N = Cudd_Regular (node); + + /* + * Terminal case or Already Visited: + * Print one cube based on the current recursion + */ + + if (cuddIsConstant (N)) { + retValue = printCubeCnf (ddMgr, node, cnfIds, fp, list, varMax); + if (retValue == DDDMP_SUCCESS) { + if (idf != 0) { + fprintf (fp, "%d ", idf); + } + fprintf (fp, "0\n"); + *varMax = GET_MAX (*varMax, abs(idf)); + *clauseN = *clauseN + 1; + } + return (DDDMP_SUCCESS); + } + + /* + * Shared Sub-Tree: Print Cube + */ + + index = DddmpReadNodeIndexCnf (N); + if (index > 0) { + if (idf != 0) { + fprintf (fp, "%d ", idf); + } + if (Cudd_IsComplement (node)) { + retValue = fprintf (fp, "-%d ", index); + } else { + retValue = fprintf (fp, "%d ", index); + } + retValue = printCubeCnf (ddMgr, node, cnfIds, fp, list, varMax); + fprintf (fp, "0\n"); + *varMax = GET_MAX (*varMax, abs(index)); + *clauseN = *clauseN + 1; + return (DDDMP_SUCCESS); + } + + /* + * NON Terminal case: Recur + */ + + Nv = cuddT (N); + Nnv = cuddE (N); + if (Cudd_IsComplement (node)) { + Nv = Cudd_Not (Nv); + Nnv = Cudd_Not (Nnv); + } + index = N->index; + + /* + * StQ 06.05.2003 + * Perform the optimization: + * f = (a + b)' = (a') ^ (a + b') = (a') ^ (b') + * i.e., if the THEN node is the constant ZERO then that variable + * can be forgotten (list[index] = 2) for subsequent ELSE cubes + */ + if (cuddIsConstant (Cudd_Regular (Nv)) && Nv != ddMgr->one) { + list[index] = 2; + } else { + list[index] = 0; + } + StoreCnfBestNotSharedRecur (ddMgr, Nnv, idf, bddIds, cnfIds, fp, list, + clauseN, varMax); + + /* + * StQ 06.05.2003 + * Perform the optimization: + * f = a ^ b = (a) ^ (a' + b) = (a) ^ (b) + * i.e., if the ELSE node is the constant ZERO then that variable + * can be forgotten (list[index] = 2) for subsequent THEN cubes + */ + if (cuddIsConstant (Cudd_Regular (Nnv)) && Nnv != ddMgr->one) { + list[index] = 2; + } else { + list[index] = 1; + } + StoreCnfBestNotSharedRecur (ddMgr, Nv, idf, bddIds, cnfIds, fp, list, + clauseN, varMax); + list[index] = 2; + + return (DDDMP_SUCCESS); +} + +/**Function******************************************************************** + + Synopsis [Performs the recursive step of Print Best on Shared + sub-BDDs. + ] + + Description [Performs the recursive step of Print Best on Not Shared + sub-BDDs, i.e., print out information for the nodes belonging to + BDDs not shared (whose root has just one incoming edge). + ] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ + +static int +StoreCnfBestSharedRecur ( + DdManager *ddMgr /* IN: DD Manager */, + DdNode *node /* IN: BDD to store */, + int *bddIds /* IN: BDD identifiers */, + int *cnfIds /* IN: corresponding CNF identifiers */, + FILE *fp /* IN: file pointer */, + int *list /* IN: temporary array to store cubes */, + int *clauseN /* OUT: number of stored clauses */, + int *varMax /* OUT: maximum identifier of the variables created */ + ) +{ + DdNode *nodeThen, *nodeElse; + int i, idf, index; + DdNode *one; + + one = ddMgr->one; + + Dddmp_Assert (node==Cudd_Regular(node), + "Inverted Edge during Shared Printing."); + + /* If constant, nothing to do. */ + if (cuddIsConstant (node)) { + return (DDDMP_SUCCESS); + } + + /* If already visited, nothing to do. */ + if (DddmpVisitedCnf (node)) { + return (DDDMP_SUCCESS); + } + + /* + * Shared Sub-Tree: Print Cube + */ + + idf = DddmpReadNodeIndexCnf (node); + if (idf > 0) { + /* Cheat the Recur Function about the Index of the Current Node */ + DddmpWriteNodeIndexCnf (node, 0); + +#if DDDMP_DEBUG_CNF + fprintf (fp, "Else of XNOR\n"); +#endif + for (i=0; isize; i++) { + list[i] = 2; + } + StoreCnfBestNotSharedRecur (ddMgr, Cudd_Not (node), idf, bddIds, cnfIds, + fp, list, clauseN, varMax); + +#if DDDMP_DEBUG_CNF + fprintf (fp, "Then of XNOR\n"); +#endif + for (i=0; isize; i++) { + list[i] = 2; + } + StoreCnfBestNotSharedRecur (ddMgr, node, -idf, bddIds, cnfIds, + fp, list, clauseN, varMax); + + /* Set Back Index of Current Node */ + DddmpWriteNodeIndexCnf (node, idf); + } + + /* Mark node as visited. */ + DddmpSetVisitedCnf (node); + + /* + * Recur + */ + + nodeThen = cuddT (node); + nodeElse = cuddE (node); + index = node->index; + + StoreCnfBestSharedRecur (ddMgr, Cudd_Regular (nodeThen), bddIds, cnfIds, + fp, list, clauseN, varMax); + StoreCnfBestSharedRecur (ddMgr, Cudd_Regular (nodeElse), bddIds, cnfIds, + fp, list, clauseN, varMax); + + return (DDDMP_SUCCESS); +} + +/**Function******************************************************************** + + Synopsis [Print One Cube in CNF Format.] + + Description [Print One Cube in CNF Format. + Return DDDMP_SUCCESS if something is printed out, DDDMP_FAILURE + is nothing is printed out. + ] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ + +static int +printCubeCnf ( + DdManager *ddMgr /* IN: DD Manager */, + DdNode *node /* IN: BDD to store */, + int *cnfIds /* IN: CNF identifiers */, + FILE *fp /* IN: file pointer */, + int *list /* IN: temporary array to store cubes */, + int *varMax /* OUT: maximum identifier of the variables created */ + ) +{ + int i, retValue; + DdNode *one; + + retValue = DDDMP_FAILURE; + one = ddMgr->one; + + if (node != one) { + for (i=0; isize; i++) { + if (list[i] == 0) { + retValue = DDDMP_SUCCESS; + (void) fprintf (fp, "%d ", cnfIds[i]); + *varMax = GET_MAX(*varMax, cnfIds[i]); + } else { + if (list[i] == 1) { + retValue = DDDMP_SUCCESS; + (void) fprintf (fp, "-%d ", cnfIds[i]); + *varMax = GET_MAX(*varMax, cnfIds[i]); + } + } + } + } + + return (retValue); +} + + + + + diff --git a/distr/dddmp/dddmpStoreMisc.c b/distr/dddmp/dddmpStoreMisc.c new file mode 100644 index 0000000..2dc18f0 --- /dev/null +++ b/distr/dddmp/dddmpStoreMisc.c @@ -0,0 +1,1641 @@ +/**CFile********************************************************************** + + FileName [dddmpStoreMisc.c] + + PackageName [dddmp] + + Synopsis [Functions to write out bdds to file in prefixed + and in Blif form.] + + Description [Functions to write out bdds to file. + BDDs are represended on file in text format. + Each node is stored as a multiplexer in a prefix notation format for + the prefix notation file or in PLA format for the blif file. + ] + + Author [Gianpiero Cabodi and Stefano Quer] + + Copyright [ + Copyright (c) 2004 by Politecnico di Torino. + All Rights Reserved. This software is for educational purposes only. + Permission is given to academic institutions to use, copy, and modify + this software and its documentation provided that this introductory + message is not removed, that this software and its documentation is + used for the institutions' internal research and educational purposes, + and that no monies are exchanged. No guarantee is expressed or implied + by the distribution of this code. + Send bug-reports and/or questions to: + {gianpiero.cabodi,stefano.quer}@polito.it. + ] + +******************************************************************************/ + +#include "dddmpInt.h" + +/*---------------------------------------------------------------------------*/ +/* Stucture declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Type declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Variable declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Macro declarations */ +/*---------------------------------------------------------------------------*/ + +/**AutomaticStart*************************************************************/ + +/*---------------------------------------------------------------------------*/ +/* Static function prototypes */ +/*---------------------------------------------------------------------------*/ + +static int DddmpCuddDdArrayStorePrefix(DdManager *ddMgr, int n, DdNode **f, char **inputNames, char **outputNames, char *modelName, FILE *fp); +static int DddmpCuddDdArrayStorePrefixBody(DdManager *ddMgr, int n, DdNode **f, char **inputNames, char **outputNames, FILE *fp); +static int DddmpCuddDdArrayStorePrefixStep(DdManager * ddMgr, DdNode * f, FILE * fp, st_table * visited, char ** names); +static int DddmpCuddDdArrayStoreBlif(DdManager *ddMgr, int n, DdNode **f, char **inputNames, char **outputNames, char *modelName, FILE *fp); +static int DddmpCuddDdArrayStoreBlifBody(DdManager *ddMgr, int n, DdNode **f, char **inputNames, char **outputNames, FILE *fp); +static int DddmpCuddDdArrayStoreBlifStep(DdManager *ddMgr, DdNode *f, FILE *fp, st_table *visited, char **names); +static int DddmpCuddDdArrayStoreSmv(DdManager *ddMgr, int n, DdNode **f, char **inputNames, char **outputNames, char *modelName, FILE *fp); +static int DddmpCuddDdArrayStoreSmvBody(DdManager *ddMgr, int n, DdNode **f, char **inputNames, char **outputNames, FILE *fp); +static int DddmpCuddDdArrayStoreSmvStep(DdManager * ddMgr, DdNode * f, FILE * fp, st_table * visited, char ** names); + +/**AutomaticEnd***************************************************************/ + +/*---------------------------------------------------------------------------*/ +/* Definition of exported functions */ +/*---------------------------------------------------------------------------*/ + +/**Function******************************************************************** + + Synopsis [Writes a dump file representing the argument BDD in + a prefix notation.] + + Description [Dumps the argument BDD to file. + Dumping is done through Dddmp_cuddBddArrayStorePrefix. + A dummy array of 1 BDD root is used for this purpose. + ] + + SideEffects [] + + SeeAlso [Dddmp_cuddBddStore] + +******************************************************************************/ + +int +Dddmp_cuddBddStorePrefix ( + DdManager *ddMgr /* IN: DD Manager */, + int nRoots /* IN: Number of BDD roots */, + DdNode *f /* IN: BDD root to be stored */, + char **inputNames /* IN: Array of variable names */, + char **outputNames /* IN: Array of root names */, + char *modelName /* IN: Model Name */, + char *fileName /* IN: File name */, + FILE *fp /* IN: File pointer to the store file */ + ) +{ + int retValue; + DdNode *tmpArray[1]; + + tmpArray[0] = f; + + retValue = Dddmp_cuddBddArrayStorePrefix (ddMgr, 1, tmpArray, + inputNames, outputNames, modelName, fileName, fp); + + return (retValue); +} + +/**Function******************************************************************** + + Synopsis [Writes a dump file representing the argument BDD in + a prefix notation.] + + Description [Dumps the argument BDD to file. + Dumping is done through Dddmp_cuddBddArrayStorePrefix. + A dummy array of 1 BDD root is used for this purpose. + ] + + SideEffects [] + + SeeAlso [Dddmp_cuddBddArrayStore] + +******************************************************************************/ + +int +Dddmp_cuddBddArrayStorePrefix ( + DdManager *ddMgr /* IN: DD Manager */, + int nroots /* IN: number of output BDD roots to be stored */, + DdNode **f /* IN: array of BDD roots to be stored */, + char **inputNames /* IN: array of variable names (or NULL) */, + char **outputNames /* IN: array of root names (or NULL) */, + char *modelName /* IN: Model Name */, + char *fname /* IN: File name */, + FILE *fp /* IN: File pointer to the store file */ + ) +{ + int retValue; + int fileToClose = 0; + +#ifdef DDDMP_DEBUG +#ifndef __alpha__ + int retValueBis; + + retValueBis = Cudd_DebugCheck (ddMgr); + if (retValueBis == 1) { + fprintf (stderr, "Inconsistency Found During BDD Store.\n"); + fflush (stderr); + } else { + if (retValueBis == CUDD_OUT_OF_MEM) { + fprintf (stderr, "Out of Memory During BDD Store.\n"); + fflush (stderr); + } + } +#endif +#endif + + /* + * Check if File needs to be opened in the proper mode. + */ + + if (fp == NULL) { + fp = fopen (fname, "w"); + Dddmp_CheckAndGotoLabel (fp==NULL, "Error opening file.", + failure); + fileToClose = 1; + } + + retValue = DddmpCuddDdArrayStorePrefix (ddMgr, nroots, f, + inputNames, outputNames, modelName, fp); + + if (fileToClose) { + fclose (fp); + } + +#ifdef DDDMP_DEBUG +#ifndef __alpha__ + retValueBis = Cudd_DebugCheck (ddMgr); + if (retValueBis == 1) { + fprintf (stderr, "Inconsistency Found During BDD Store.\n"); + fflush (stderr); + } else { + if (retValueBis == CUDD_OUT_OF_MEM) { + fprintf (stderr, "Out of Memory During BDD Store.\n"); + fflush (stderr); + } + } +#endif +#endif + + return (retValue); + + failure: + return (DDDMP_FAILURE); +} + +/**Function******************************************************************** + + Synopsis [Writes a dump file representing the argument BDD in + a Blif/Exlif notation.] + + Description [Dumps the argument BDD to file. + Dumping is done through Dddmp_cuddBddArrayStoreBlif. + A dummy array of 1 BDD root is used for this purpose. + ] + + SideEffects [] + + SeeAlso [Dddmp_cuddBddStorePrefix] + +******************************************************************************/ + +int +Dddmp_cuddBddStoreBlif ( + DdManager *ddMgr /* IN: DD Manager */, + int nRoots /* IN: Number of BDD roots */, + DdNode *f /* IN: BDD root to be stored */, + char **inputNames /* IN: Array of variable names */, + char **outputNames /* IN: Array of root names */, + char *modelName /* IN: Model Name */, + char *fileName /* IN: File name */, + FILE *fp /* IN: File pointer to the store file */ + ) +{ + int retValue; + DdNode *tmpArray[1]; + + tmpArray[0] = f; + + retValue = Dddmp_cuddBddArrayStoreBlif (ddMgr, 1, tmpArray, + inputNames, outputNames, modelName, fileName, fp); + + return (retValue); +} + +/**Function******************************************************************** + + Synopsis [Writes a dump file representing the argument BDD in + a Blif/Exlif notation.] + + Description [Dumps the argument BDD to file. + Dumping is done through Dddmp_cuddBddArrayStoreBLif. + A dummy array of 1 BDD root is used for this purpose. + ] + + SideEffects [] + + SeeAlso [Dddmp_cuddBddArrayStorePrefix] + +******************************************************************************/ + +int +Dddmp_cuddBddArrayStoreBlif ( + DdManager *ddMgr /* IN: DD Manager */, + int nroots /* IN: number of output BDD roots to be stored */, + DdNode **f /* IN: array of BDD roots to be stored */, + char **inputNames /* IN: array of variable names (or NULL) */, + char **outputNames /* IN: array of root names (or NULL) */, + char *modelName /* IN: Model Name */, + char *fname /* IN: File name */, + FILE *fp /* IN: File pointer to the store file */ + ) +{ + int retValue; + int fileToClose = 0; + +#ifdef DDDMP_DEBUG +#ifndef __alpha__ + int retValueBis; + + retValueBis = Cudd_DebugCheck (ddMgr); + if (retValueBis == 1) { + fprintf (stderr, "Inconsistency Found During BDD Store.\n"); + fflush (stderr); + } else { + if (retValueBis == CUDD_OUT_OF_MEM) { + fprintf (stderr, "Out of Memory During BDD Store.\n"); + fflush (stderr); + } + } +#endif +#endif + + /* + * Check if File needs to be opened in the proper mode. + */ + + if (fp == NULL) { + fp = fopen (fname, "w"); + Dddmp_CheckAndGotoLabel (fp==NULL, "Error opening file.", + failure); + fileToClose = 1; + } + + retValue = DddmpCuddDdArrayStoreBlif (ddMgr, nroots, f, + inputNames, outputNames, modelName, fp); + + if (fileToClose) { + fclose (fp); + } + +#ifdef DDDMP_DEBUG +#ifndef __alpha__ + retValueBis = Cudd_DebugCheck (ddMgr); + if (retValueBis == 1) { + fprintf (stderr, "Inconsistency Found During BDD Store.\n"); + fflush (stderr); + } else { + if (retValueBis == CUDD_OUT_OF_MEM) { + fprintf (stderr, "Out of Memory During BDD Store.\n"); + fflush (stderr); + } + } +#endif +#endif + + return (retValue); + + failure: + return (DDDMP_FAILURE); +} + +/**Function******************************************************************** + + Synopsis [Writes a dump file representing the argument BDD in + a prefix notation.] + + Description [Dumps the argument BDD to file. + Dumping is done through Dddmp_cuddBddArrayStorePrefix. + A dummy array of 1 BDD root is used for this purpose. + ] + + SideEffects [] + + SeeAlso [Dddmp_cuddBddStore] + +******************************************************************************/ + +int +Dddmp_cuddBddStoreSmv ( + DdManager *ddMgr /* IN: DD Manager */, + int nRoots /* IN: Number of BDD roots */, + DdNode *f /* IN: BDD root to be stored */, + char **inputNames /* IN: Array of variable names */, + char **outputNames /* IN: Array of root names */, + char *modelName /* IN: Model Name */, + char *fileName /* IN: File name */, + FILE *fp /* IN: File pointer to the store file */ + ) +{ + int retValue; + DdNode *tmpArray[1]; + + tmpArray[0] = f; + + retValue = Dddmp_cuddBddArrayStoreSmv (ddMgr, 1, tmpArray, + inputNames, outputNames, modelName, fileName, fp); + + return (retValue); +} + +/**Function******************************************************************** + + Synopsis [Writes a dump file representing the argument BDD in + a prefix notation.] + + Description [Dumps the argument BDD to file. + Dumping is done through Dddmp_cuddBddArrayStorePrefix. + A dummy array of 1 BDD root is used for this purpose. + ] + + SideEffects [] + + SeeAlso [Dddmp_cuddBddArrayStore] + +******************************************************************************/ + +int +Dddmp_cuddBddArrayStoreSmv ( + DdManager *ddMgr /* IN: DD Manager */, + int nroots /* IN: number of output BDD roots to be stored */, + DdNode **f /* IN: array of BDD roots to be stored */, + char **inputNames /* IN: array of variable names (or NULL) */, + char **outputNames /* IN: array of root names (or NULL) */, + char *modelName /* IN: Model Name */, + char *fname /* IN: File name */, + FILE *fp /* IN: File pointer to the store file */ + ) +{ + int retValue; + int fileToClose = 0; + +#ifdef DDDMP_DEBUG +#ifndef __alpha__ + int retValueBis; + + retValueBis = Cudd_DebugCheck (ddMgr); + if (retValueBis == 1) { + fprintf (stderr, "Inconsistency Found During BDD Store.\n"); + fflush (stderr); + } else { + if (retValueBis == CUDD_OUT_OF_MEM) { + fprintf (stderr, "Out of Memory During BDD Store.\n"); + fflush (stderr); + } + } +#endif +#endif + + /* + * Check if File needs to be opened in the proper mode. + */ + + if (fp == NULL) { + fp = fopen (fname, "w"); + Dddmp_CheckAndGotoLabel (fp==NULL, "Error opening file.", + failure); + fileToClose = 1; + } + + retValue = DddmpCuddDdArrayStoreSmv (ddMgr, nroots, f, + inputNames, outputNames, modelName, fp); + + if (fileToClose) { + fclose (fp); + } + +#ifdef DDDMP_DEBUG +#ifndef __alpha__ + retValueBis = Cudd_DebugCheck (ddMgr); + if (retValueBis == 1) { + fprintf (stderr, "Inconsistency Found During BDD Store.\n"); + fflush (stderr); + } else { + if (retValueBis == CUDD_OUT_OF_MEM) { + fprintf (stderr, "Out of Memory During BDD Store.\n"); + fflush (stderr); + } + } +#endif +#endif + + return (retValue); + + failure: + return (DDDMP_FAILURE); +} + +/*---------------------------------------------------------------------------*/ +/* Definition of static functions */ +/*---------------------------------------------------------------------------*/ + +/**Function******************************************************************** + + Synopsis [Internal function to writes a dump file representing the + argument BDD in a prefix notation.] + + Description [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). + It does not close the file: This is the caller responsibility. + It uses a minimal unique subset of the hexadecimal address of a node as + name for it. + If the argument inputNames is non-null, it is assumed to hold the + pointers to the names of the inputs. Similarly for outputNames. + For each BDD node of function f, variable v, then child T, and else + child E it stores: + f = v * T + v' * E + that is + (OR f (AND v T) (AND (NOT v) E)) + If E is a complemented child this results in the following + (OR f (AND v T) (AND (NOT v) (NOT E))) + Comments (COMMENT) are added at the beginning of the description to + describe inputs and outputs of the design. + A buffer (BUF) is add on the output to cope with complemented functions. + ] + + SideEffects [None] + + SeeAlso [DddmpCuddDdArrayStoreBlif] + +******************************************************************************/ + +static int +DddmpCuddDdArrayStorePrefix ( + DdManager *ddMgr /* IN: Manager */, + int n /* IN: Number of output nodes to be dumped */, + DdNode **f /* IN: Array of output nodes to be dumped */, + char **inputNames /* IN: Array of input names (or NULL) */, + char **outputNames /* IN: Array of output names (or NULL) */, + char *modelName /* IN: Model name (or NULL) */, + FILE *fp /* IN: Pointer to the dump file */ + ) +{ + DdNode *support = NULL; + DdNode *scan; + int *sorted = NULL; + int nVars = ddMgr->size; + int retValue; + int i; + + /* Build a bit array with the support of f. */ + sorted = ALLOC(int, nVars); + if (sorted == NULL) { + ddMgr->errorCode = CUDD_MEMORY_OUT; + Dddmp_CheckAndGotoLabel (1, "Allocation Error.", failure); + } + for (i = 0; i < nVars; i++) { + sorted[i] = 0; + } + + /* Take the union of the supports of each output function. */ + support = Cudd_VectorSupport(ddMgr,f,n); + Dddmp_CheckAndGotoLabel (support==NULL, + "Error in function Cudd_VectorSupport.", failure); + cuddRef(support); + scan = support; + while (!cuddIsConstant(scan)) { + sorted[scan->index] = 1; + scan = cuddT(scan); + } + Cudd_RecursiveDeref(ddMgr,support); + /* so that we do not try to free it in case of failure */ + support = NULL; + + /* Write the header (.model .inputs .outputs). */ + if (modelName == NULL) { + retValue = fprintf (fp, "(COMMENT - model name: Unknown )\n"); + } else { + retValue = fprintf (fp, "(COMMENT - model name: %s )\n", modelName); + } + if (retValue == EOF) { + return(0); + } + + retValue = fprintf(fp, "(COMMENT - input names: "); + if (retValue == EOF) { + return(0); + } + /* Write the input list by scanning the support array. */ + for (i = 0; i < nVars; i++) { + if (sorted[i]) { + if (inputNames == NULL) { + retValue = fprintf(fp," inNode%d", i); + } else { + retValue = fprintf(fp," %s", inputNames[i]); + } + Dddmp_CheckAndGotoLabel (retValue==EOF, + "Error during file store.", failure); + } + } + FREE(sorted); + sorted = NULL; + retValue = fprintf(fp, " )\n"); + if (retValue == EOF) { + return(0); + } + + /* Write the .output line. */ + retValue = fprintf(fp,"(COMMENT - output names: "); + if (retValue == EOF) { + return(0); + } + for (i = 0; i < n; i++) { + if (outputNames == NULL) { + retValue = fprintf (fp," outNode%d", i); + } else { + retValue = fprintf (fp," %s", outputNames[i]); + } + Dddmp_CheckAndGotoLabel (retValue==EOF, + "Error during file store.", failure); + } + retValue = fprintf(fp, " )\n"); + Dddmp_CheckAndGotoLabel (retValue==EOF, + "Error during file store.", failure); + + retValue = DddmpCuddDdArrayStorePrefixBody (ddMgr, n, f, inputNames, + outputNames, fp); + Dddmp_CheckAndGotoLabel (retValue==0, + "Error in function DddmpCuddDdArrayStorePrefixBody.", failure); + + return(1); + +failure: + if (sorted != NULL) { + FREE(sorted); + } + if (support != NULL) { + Cudd_RecursiveDeref(ddMgr,support); + } + return(0); +} + +/**Function******************************************************************** + + Synopsis [Internal function to writes a dump file representing the + argument BDD in a prefix notation. Writes the body of the file.] + + Description [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). + It does not close the file: This is the caller responsibility. + It uses a minimal unique subset of the hexadecimal address of a node as + name for it. + If the argument inputNames is non-null, it is assumed to hold the + pointers to the names of the inputs. Similarly for outputNames. + For each BDD node of function f, variable v, then child T, and else + child E it stores: + f = v * T + v' * E + that is + (OR f (AND v T) (AND (NOT v) E)) + If E is a complemented child this results in the following + (OR f (AND v T) (AND (NOT v) (NOT E))) + ] + + SideEffects [None] + + SeeAlso [DddmpCuddDdArrayStoreBlif] + +******************************************************************************/ + +static int +DddmpCuddDdArrayStorePrefixBody ( + DdManager *ddMgr /* IN: Manager */, + int n /* IN: Number of output nodes to be dumped */, + DdNode **f /* IN: Array of output nodes to be dumped */, + char **inputNames /* IN: Array of input names (or NULL) */, + char **outputNames /* IN: Array of output names (or NULL) */, + FILE *fp /* IN: Pointer to the dump file */ + ) +{ + st_table *visited = NULL; + int retValue; + int i; + + /* Initialize symbol table for visited nodes. */ + visited = st_init_table(st_ptrcmp, st_ptrhash); + Dddmp_CheckAndGotoLabel (visited==NULL, + "Error if function st_init_table.", failure); + + /* Call the function that really gets the job done. */ + for (i = 0; i < n; i++) { + retValue = DddmpCuddDdArrayStorePrefixStep (ddMgr, Cudd_Regular(f[i]), + fp, visited, inputNames); + Dddmp_CheckAndGotoLabel (retValue==0, + "Error if function DddmpCuddDdArrayStorePrefixStep.", 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; iindex]); + } else { + retValue = fprintf(fp, "inNode%d ", f->index); + } + if (retValue == EOF) { + return(0); + } + +#if SIZEOF_VOID_P == 8 + retValue = fprintf (fp, "node%lx) (AND (NOT ", + (unsigned long) T / (unsigned long) sizeof(DdNode)); +#else + retValue = fprintf (fp, "node%x) (AND (NOT ", + (unsigned) T / (unsigned) sizeof(DdNode)); +#endif + if (retValue == EOF) { + return(0); + } + + if (names != NULL) { + retValue = fprintf (fp, "%s", names[f->index]); + } else { + retValue = fprintf (fp, "inNode%d", f->index); + } + if (retValue == EOF) { + return(0); + } + +#if SIZEOF_VOID_P == 8 + if (Cudd_IsComplement(cuddE(f))) { + retValue = fprintf (fp, ") (NOT node%lx)))\n", + (unsigned long) E / (unsigned long) sizeof(DdNode)); + } else { + retValue = fprintf (fp, ") node%lx))\n", + (unsigned long) E / (unsigned long) sizeof(DdNode)); + } +#else + if (Cudd_IsComplement(cuddE(f))) { + retValue = fprintf (fp, ") (NOT node%x)))\n", + (unsigned) E / (unsigned) sizeof(DdNode)); + } else { + retValue = fprintf (fp, ") node%x))\n", + (unsigned) E / (unsigned) sizeof(DdNode)); + } +#endif + + if (retValue == EOF) { + return(0); + } else { + return(1); + } +} + +/**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). + DddmpCuddDdArrayStoreBlif does not close the file: This is the + caller responsibility. + DddmpCuddDdArrayStoreBlif 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 outputNames. + It prefixes the string "NODE" to each nome to have "regular" names + for each elements. + ] + + SideEffects [None] + + SeeAlso [DddmpCuddDdArrayStoreBlifBody,Cudd_DumpBlif] + +******************************************************************************/ + +static int +DddmpCuddDdArrayStoreBlif ( + DdManager *ddMgr /* IN: Manager */, + int n /* IN: Number of output nodes to be dumped */, + DdNode **f /* IN: Array of output nodes to be dumped */, + char **inputNames /* IN: Array of input names (or NULL) */, + char **outputNames /* IN: Array of output names (or NULL) */, + char *modelName /* IN: Model name (or NULL) */, + FILE *fp /* IN: Pointer to the dump file */ + ) +{ + DdNode *support = NULL; + DdNode *scan; + int *sorted = NULL; + int nVars = ddMgr->size; + int retValue; + int i; + + /* Build a bit array with the support of f. */ + sorted = ALLOC (int, nVars); + if (sorted == NULL) { + ddMgr->errorCode = CUDD_MEMORY_OUT; + Dddmp_CheckAndGotoLabel (1, "Allocation Error.", failure); + } + for (i = 0; i < nVars; i++) { + sorted[i] = 0; + } + + /* Take the union of the supports of each output function. */ + support = Cudd_VectorSupport(ddMgr,f,n); + Dddmp_CheckAndGotoLabel (support==NULL, + "Error in function Cudd_VectorSupport.", failure); + cuddRef(support); + scan = support; + while (!cuddIsConstant(scan)) { + sorted[scan->index] = 1; + scan = cuddT(scan); + } + Cudd_RecursiveDeref(ddMgr,support); + support = NULL; + /* so that we do not try to free it in case of failure */ + + /* Write the header (.model .inputs .outputs). */ + if (modelName == NULL) { + retValue = fprintf(fp,".model DD\n.inputs"); + } else { + retValue = fprintf(fp,".model %s\n.inputs", modelName); + } + if (retValue == EOF) { + return(0); + } + + /* Write the input list by scanning the support array. */ + for (i = 0; i < nVars; i++) { + if (sorted[i]) { + if (inputNames == NULL || (inputNames[i] == NULL)) { + retValue = fprintf(fp," inNode%d", i); + } else { + retValue = fprintf(fp," %s", inputNames[i]); + } + Dddmp_CheckAndGotoLabel (retValue==EOF, + "Error during file store.", failure); + } + } + FREE(sorted); + sorted = NULL; + + /* Write the .output line. */ + retValue = fprintf(fp,"\n.outputs"); + Dddmp_CheckAndGotoLabel (retValue==EOF, + "Error during file store.", failure); + for (i = 0; i < n; i++) { + if (outputNames == NULL || (outputNames[i] == NULL)) { + retValue = fprintf(fp," outNode%d", i); + } else { + retValue = fprintf(fp," %s", outputNames[i]); + } + Dddmp_CheckAndGotoLabel (retValue==EOF, + "Error during file store.", failure); + } + retValue = fprintf(fp,"\n"); + Dddmp_CheckAndGotoLabel (retValue==EOF, + "Error during file store.", failure); + + retValue = DddmpCuddDdArrayStoreBlifBody(ddMgr, n, f, inputNames, + outputNames, fp); + Dddmp_CheckAndGotoLabel (retValue==0, + "Error if function DddmpCuddDdArrayStoreBlifBody.", failure); + + /* Write trailer and return. */ + retValue = fprintf (fp, ".end\n"); + Dddmp_CheckAndGotoLabel (retValue==EOF, + "Error during file store.", failure); + + return(1); + +failure: + if (sorted != NULL) { + FREE(sorted); + } + if (support != NULL) { + Cudd_RecursiveDeref(ddMgr,support); + } + + return(0); +} + + +/**Function******************************************************************** + + Synopsis [Writes a blif body representing the argument BDDs.] + + Description [Writes a blif body 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). + DddmpCuddDdArrayStoreBlif does not close the file: This is the + caller responsibility. + DddmpCuddDdArrayStoreBlif uses a minimal unique subset of + the hexadecimal address of a node as name for it. If the argument + inputNames is non-null, it is assumed to hold the pointers to the names + of the inputs. Similarly for outputNames. This function prints out only + .names part. + ] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ + +static int +DddmpCuddDdArrayStoreBlifBody ( + DdManager *ddMgr /* IN: Manager */, + int n /* IN: Number of output nodes to be dumped */, + DdNode **f /* IN: Array of output nodes to be dumped */, + char **inputNames /* IN: Array of input names (or NULL) */, + char **outputNames /* IN: Array of output names (or NULL) */, + FILE *fp /* IN: Pointer to the dump file */ + ) +{ + st_table *visited = NULL; + int retValue; + int i; + + /* Initialize symbol table for visited nodes. */ + visited = st_init_table(st_ptrcmp, st_ptrhash); + Dddmp_CheckAndGotoLabel (visited==NULL, + "Error if function st_init_table.", failure); + + /* Call the function that really gets the job done. */ + for (i = 0; i < n; i++) { + retValue = DddmpCuddDdArrayStoreBlifStep (ddMgr, Cudd_Regular(f[i]), + fp, visited, inputNames); + Dddmp_CheckAndGotoLabel (retValue==0, + "Error if function DddmpCuddDdArrayStoreBlifStep.", 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 (outputNames == NULL) { + retValue = fprintf(fp, +#if SIZEOF_VOID_P == 8 + ".names node%lx outNode%d\n", + (unsigned long) f[i] / (unsigned long) sizeof(DdNode), i); +#else + ".names node%x outNode%d\n", + (unsigned) f[i] / (unsigned) sizeof(DdNode), i); +#endif + } else { + retValue = fprintf(fp, +#if SIZEOF_VOID_P == 8 + ".names node%lx %s\n", + (unsigned long) f[i] / (unsigned long) sizeof(DdNode), outputNames[i]); +#else + ".names node%x %s\n", + (unsigned) f[i] / (unsigned) sizeof(DdNode), outputNames[i]); +#endif + } + Dddmp_CheckAndGotoLabel (retValue==EOF, + "Error during file store.", failure); + if (Cudd_IsComplement(f[i])) { + retValue = fprintf(fp,"0 1\n"); + } else { + retValue = fprintf(fp,"1 1\n"); + } + Dddmp_CheckAndGotoLabel (retValue==EOF, + "Error during file store.", failure); + } + + st_free_table(visited); + return(1); + +failure: + if (visited != NULL) { + st_free_table(visited); + } + return(0); +} + +/**Function******************************************************************** + + Synopsis [Performs the recursive step of DddmpCuddDdArrayStoreBlif.] + + Description [Performs the recursive step of DddmpCuddDdArrayStoreBlif. + 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 DddmpCuddDdArrayStoreBlifStep + guarantees this assumption in the recursive calls. + ] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ + +static int +DddmpCuddDdArrayStoreBlifStep ( + DdManager *ddMgr, + DdNode *f, + FILE *fp, + st_table *visited, + char **names + ) +{ + DdNode *T, *E; + int retValue; + +#ifdef DDDMP_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(ddMgr)) { +#if SIZEOF_VOID_P == 8 + retValue = fprintf(fp, ".names node%lx\n1\n", + (unsigned long) f / (unsigned long) sizeof(DdNode)); +#else + retValue = fprintf(fp, ".names node%x\n1\n", + (unsigned) f / (unsigned) sizeof(DdNode)); +#endif + if (retValue == 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(ddMgr)) { +#if SIZEOF_VOID_P == 8 + retValue = fprintf(fp, ".names node%lx\n", + (unsigned long) f / (unsigned long) sizeof(DdNode)); +#else + retValue = fprintf(fp, ".names node%x\n", + (unsigned) f / (unsigned) sizeof(DdNode)); +#endif + if (retValue == EOF) { + return(0); + } else { + return(1); + } + } + if (cuddIsConstant(f)) { + return(0); + } + + /* Recursive calls. */ + T = cuddT(f); + retValue = DddmpCuddDdArrayStoreBlifStep(ddMgr,T,fp,visited,names); + if (retValue != 1) return(retValue); + E = Cudd_Regular(cuddE(f)); + retValue = DddmpCuddDdArrayStoreBlifStep(ddMgr,E,fp,visited,names); + if (retValue != 1) return(retValue); + + /* Write multiplexer taking complement arc into account. */ + if (names != NULL) { + retValue = fprintf(fp,".names %s", names[f->index]); + } else { + retValue = fprintf(fp,".names inNode%d", f->index); + } + if (retValue == EOF) { + return(0); + } + +#if SIZEOF_VOID_P == 8 + if (Cudd_IsComplement(cuddE(f))) { + retValue = fprintf(fp," node%lx node%lx node%lx\n11- 1\n0-0 1\n", + (unsigned long) T / (unsigned long) sizeof(DdNode), + (unsigned long) E / (unsigned long) sizeof(DdNode), + (unsigned long) f / (unsigned long) sizeof(DdNode)); + } else { + retValue = fprintf(fp," node%lx node%lx node%lx\n11- 1\n0-1 1\n", + (unsigned long) T / (unsigned long) sizeof(DdNode), + (unsigned long) E / (unsigned long) sizeof(DdNode), + (unsigned long) f / (unsigned long) sizeof(DdNode)); + } +#else + if (Cudd_IsComplement(cuddE(f))) { + retValue = fprintf(fp," node%x node%x node%x\n11- 1\n0-0 1\n", + (unsigned) T / (unsigned) sizeof(DdNode), + (unsigned) E / (unsigned) sizeof(DdNode), + (unsigned) f / (unsigned) sizeof(DdNode)); + } else { + retValue = fprintf(fp," node%x node%x node%x\n11- 1\n0-1 1\n", + (unsigned) T / (unsigned) sizeof(DdNode), + (unsigned) E / (unsigned) sizeof(DdNode), + (unsigned) f / (unsigned) sizeof(DdNode)); + } +#endif + if (retValue == EOF) { + return(0); + } else { + return(1); + } +} + +/**Function******************************************************************** + + Synopsis [Internal function to writes a dump file representing the + argument BDD in a SMV notation.] + + Description [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). + It does not close the file: This is the caller responsibility. + It uses a minimal unique subset of the hexadecimal address of a node as + name for it. + If the argument inputNames is non-null, it is assumed to hold the + pointers to the names of the inputs. Similarly for outputNames. + For each BDD node of function f, variable v, then child T, and else + child E it stores: + f = v * T + v' * E + that is + (OR f (AND v T) (AND (NOT v) E)) + If E is a complemented child this results in the following + (OR f (AND v T) (AND (NOT v) (NOT E))) + Comments (COMMENT) are added at the beginning of the description to + describe inputs and outputs of the design. + A buffer (BUF) is add on the output to cope with complemented functions. + ] + + SideEffects [None] + + SeeAlso [DddmpCuddDdArrayStoreBlif] + +******************************************************************************/ + +static int +DddmpCuddDdArrayStoreSmv ( + DdManager *ddMgr /* IN: Manager */, + int n /* IN: Number of output nodes to be dumped */, + DdNode **f /* IN: Array of output nodes to be dumped */, + char **inputNames /* IN: Array of input names (or NULL) */, + char **outputNames /* IN: Array of output names (or NULL) */, + char *modelName /* IN: Model name (or NULL) */, + FILE *fp /* IN: Pointer to the dump file */ + ) +{ + DdNode *support = NULL; + DdNode *scan; + int *sorted = NULL; + int nVars = ddMgr->size; + int retValue; + int i; + + /* Build a bit array with the support of f. */ + sorted = ALLOC(int, nVars); + if (sorted == NULL) { + ddMgr->errorCode = CUDD_MEMORY_OUT; + Dddmp_CheckAndGotoLabel (1, "Allocation Error.", failure); + } + for (i = 0; i < nVars; i++) { + sorted[i] = 0; + } + + /* Take the union of the supports of each output function. */ + support = Cudd_VectorSupport(ddMgr,f,n); + Dddmp_CheckAndGotoLabel (support==NULL, + "Error in function Cudd_VectorSupport.", failure); + cuddRef(support); + scan = support; + while (!cuddIsConstant(scan)) { + sorted[scan->index] = 1; + scan = cuddT(scan); + } + Cudd_RecursiveDeref(ddMgr,support); + /* so that we do not try to free it in case of failure */ + support = NULL; + + /* Write the header */ + if (modelName == NULL) { + retValue = fprintf (fp, "MODULE main -- Unknown\n"); + } else { + retValue = fprintf (fp, "MODULE main -- %s\n", modelName); + } + if (retValue == EOF) { + return(0); + } + + retValue = fprintf(fp, "IVAR\n"); + if (retValue == EOF) { + return(0); + } + + /* Write the input list by scanning the support array. */ + for (i=0; iindex]); + } else { + retValue = fprintf(fp, "inNode%d ", f->index); + } + if (retValue == EOF) { + return(0); + } + +#if SIZEOF_VOID_P == 8 + retValue = fprintf (fp, "& node%lx | ", + (unsigned long) T / (unsigned long) sizeof(DdNode)); +#else + retValue = fprintf (fp, "& node%x | ", + (unsigned) T / (unsigned) sizeof(DdNode)); +#endif + if (retValue == EOF) { + return(0); + } + + if (names != NULL) { + retValue = fprintf (fp, "!%s ", names[f->index]); + } else { + retValue = fprintf (fp, "!inNode%d ", f->index); + } + if (retValue == EOF) { + return(0); + } + +#if SIZEOF_VOID_P == 8 + if (Cudd_IsComplement(cuddE(f))) { + retValue = fprintf (fp, "& !node%lx\n", + (unsigned long) E / (unsigned long) sizeof(DdNode)); + } else { + retValue = fprintf (fp, "& node%lx\n", + (unsigned long) E / (unsigned long) sizeof(DdNode)); + } +#else + if (Cudd_IsComplement(cuddE(f))) { + retValue = fprintf (fp, "& !node%x\n", + (unsigned) E / (unsigned) sizeof(DdNode)); + } else { + retValue = fprintf (fp, "& node%x\n", + (unsigned) E / (unsigned) sizeof(DdNode)); + } +#endif + + if (retValue == EOF) { + return(0); + } else { + return(1); + } +} + diff --git a/distr/dddmp/dddmpUtil.c b/distr/dddmp/dddmpUtil.c new file mode 100644 index 0000000..feff439 --- /dev/null +++ b/distr/dddmp/dddmpUtil.c @@ -0,0 +1,436 @@ +/**CFile********************************************************************** + + FileName [dddmpUtil.c] + + PackageName [dddmp] + + Synopsis [Util Functions for the dddmp package] + + Description [Functions to manipulate arrays.] + + Author [Gianpiero Cabodi and Stefano Quer] + + Copyright [ + Copyright (c) 2004 by Politecnico di Torino. + All Rights Reserved. This software is for educational purposes only. + Permission is given to academic institutions to use, copy, and modify + this software and its documentation provided that this introductory + message is not removed, that this software and its documentation is + used for the institutions' internal research and educational purposes, + and that no monies are exchanged. No guarantee is expressed or implied + by the distribution of this code. + Send bug-reports and/or questions to: + {gianpiero.cabodi,stefano.quer}@polito.it. + ] + +******************************************************************************/ + +#include "dddmpInt.h" + +/*---------------------------------------------------------------------------*/ +/* Stucture declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Type declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Variable declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Macro declarations */ +/*---------------------------------------------------------------------------*/ + +/**AutomaticStart*************************************************************/ + +/*---------------------------------------------------------------------------*/ +/* Static function prototypes */ +/*---------------------------------------------------------------------------*/ + + +/**AutomaticEnd***************************************************************/ + +/*---------------------------------------------------------------------------*/ +/* Definition of exported functions */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Definition of internal functions */ +/*---------------------------------------------------------------------------*/ + +/**Function******************************************************************** + + Synopsis [String compare for qsort] + + Description [String compare for qsort] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ + +int +QsortStrcmp( + const void *ps1 /* IN: pointer to the first string */, + const void *ps2 /* IN: pointer to the second string */ + ) +{ + return (strcmp (*((char**)ps1),*((char **)ps2))); +} + +/**Function******************************************************************** + + Synopsis [Performs binary search of a name within a sorted array] + + Description [Binary search of a name within a sorted array of strings. + Used when matching names of variables. + ] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ + +int +FindVarname ( + char *name /* IN: name to look for */, + char **array /* IN: search array */, + int n /* IN: size of the array */ + ) +{ + int d, m, u, t; + + d = 0; u = n-1; + + while (u>=d) { + m = (u+d)/2; + t=strcmp(name,array[m]); + if (t==0) + return m; + if (t<0) + u=m-1; + else + d=m+1; + } + + return (-1); +} + + +/**Function******************************************************************** + + Synopsis [Duplicates a string] + + Description [Allocates memory and copies source string] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ + +char * +DddmpStrDup ( + char *str /* IN: string to be duplicated */ + ) +{ + char *str2; + + str2 = DDDMP_ALLOC(char,strlen(str)+1); + if (str2 != NULL) { + strcpy (str2,str); + } + + return (str2); +} + +/**Function******************************************************************** + + Synopsis [Duplicates an array of strings] + + Description [Allocates memory and copies source array] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ + +char ** +DddmpStrArrayDup ( + char **array /* IN: array of strings to be duplicated */, + int n /* IN: size of the array */ + ) +{ + char **array2; + int i; + + array2 = DDDMP_ALLOC(char *, n); + if (array2 == NULL) { + (void) fprintf (stderr, "DddmpStrArrayDup: Error allocating memory\n"); + fflush (stderr); + return NULL; + } + + /* + * initialize all slots to NULL for fair FREEing in case of failure + */ + + for (i=0; i +Command Documentation + + +

          Command Documentation


          +
          +
          +Last updated on 1040218 17h15 + diff --git a/distr/dddmp/doc/commands.html b/distr/dddmp/doc/commands.html new file mode 100644 index 0000000..2609aaf --- /dev/null +++ b/distr/dddmp/doc/commands.html @@ -0,0 +1,12 @@ + +Command Documentation + + + + + + + + + + diff --git a/distr/dddmp/doc/credit.html b/distr/dddmp/doc/credit.html new file mode 100644 index 0000000..868097b --- /dev/null +++ b/distr/dddmp/doc/credit.html @@ -0,0 +1,15 @@ + +Credit + + + + + + + +
          + Command Documentation + Package Documentation Generated by + the Ext system
          + + diff --git a/distr/dddmp/doc/dddmp-2.0-A4.ps b/distr/dddmp/doc/dddmp-2.0-A4.ps new file mode 100644 index 0000000..7c1010a --- /dev/null +++ b/distr/dddmp/doc/dddmp-2.0-A4.ps @@ -0,0 +1,1261 @@ +%!PS-Adobe-2.0 +%%Creator: dvips(k) 5.86 Copyright 1999 Radical Eye Software +%%Title: dddmp-2.0.dvi +%%Pages: 10 +%%PageOrder: Ascend +%%BoundingBox: 0 0 596 842 +%%DocumentFonts: Times-Bold Times-Roman Courier Times-Italic Helvetica +%%DocumentPaperSizes: a4 +%%EndComments +%DVIPSWebPage: (www.radicaleye.com) +%DVIPSCommandLine: dvips -t a4 -f dddmp-2.0 +%DVIPSParameters: dpi=600, compressed +%DVIPSSource: TeX output 2002.12.11:0557 +%%BeginProcSet: texc.pro +%! +/TeXDict 300 dict def TeXDict begin/N{def}def/B{bind def}N/S{exch}N/X{S +N}B/A{dup}B/TR{translate}N/isls false N/vsize 11 72 mul N/hsize 8.5 72 +mul N/landplus90{false}def/@rigin{isls{[0 landplus90{1 -1}{-1 1}ifelse 0 +0 0]concat}if 72 Resolution div 72 VResolution div neg scale isls{ +landplus90{VResolution 72 div vsize mul 0 exch}{Resolution -72 div hsize +mul 0}ifelse TR}if Resolution VResolution vsize -72 div 1 add mul TR[ +matrix currentmatrix{A A round sub abs 0.00001 lt{round}if}forall round +exch round exch]setmatrix}N/@landscape{/isls true N}B/@manualfeed{ +statusdict/manualfeed true put}B/@copies{/#copies X}B/FMat[1 0 0 -1 0 0] +N/FBB[0 0 0 0]N/nn 0 N/IEn 0 N/ctr 0 N/df-tail{/nn 8 dict N nn begin +/FontType 3 N/FontMatrix fntrx N/FontBBox FBB N string/base X array +/BitMaps X/BuildChar{CharBuilder}N/Encoding IEn N end A{/foo setfont}2 +array copy cvx N load 0 nn put/ctr 0 N[}B/sf 0 N/df{/sf 1 N/fntrx FMat N +df-tail}B/dfs{div/sf X/fntrx[sf 0 0 sf neg 0 0]N df-tail}B/E{pop nn A +definefont setfont}B/Cw{Cd A length 5 sub get}B/Ch{Cd A length 4 sub get +}B/Cx{128 Cd A length 3 sub get sub}B/Cy{Cd A length 2 sub get 127 sub} +B/Cdx{Cd A length 1 sub get}B/Ci{Cd A type/stringtype ne{ctr get/ctr ctr +1 add N}if}B/id 0 N/rw 0 N/rc 0 N/gp 0 N/cp 0 N/G 0 N/CharBuilder{save 3 +1 roll S A/base get 2 index get S/BitMaps get S get/Cd X pop/ctr 0 N Cdx +0 Cx Cy Ch sub Cx Cw add Cy setcachedevice Cw Ch true[1 0 0 -1 -.1 Cx +sub Cy .1 sub]/id Ci N/rw Cw 7 add 8 idiv string N/rc 0 N/gp 0 N/cp 0 N{ +rc 0 ne{rc 1 sub/rc X rw}{G}ifelse}imagemask restore}B/G{{id gp get/gp +gp 1 add N A 18 mod S 18 idiv pl S get exec}loop}B/adv{cp add/cp X}B +/chg{rw cp id gp 4 index getinterval putinterval A gp add/gp X adv}B/nd{ +/cp 0 N rw exit}B/lsh{rw cp 2 copy get A 0 eq{pop 1}{A 255 eq{pop 254}{ +A A add 255 and S 1 and or}ifelse}ifelse put 1 adv}B/rsh{rw cp 2 copy +get A 0 eq{pop 128}{A 255 eq{pop 127}{A 2 idiv S 128 and or}ifelse} +ifelse put 1 adv}B/clr{rw cp 2 index string putinterval adv}B/set{rw cp +fillstr 0 4 index getinterval putinterval adv}B/fillstr 18 string 0 1 17 +{2 copy 255 put pop}for N/pl[{adv 1 chg}{adv 1 chg nd}{1 add chg}{1 add +chg nd}{adv lsh}{adv lsh nd}{adv rsh}{adv rsh nd}{1 add adv}{/rc X nd}{ +1 add set}{1 add clr}{adv 2 chg}{adv 2 chg nd}{pop nd}]A{bind pop} +forall N/D{/cc X A type/stringtype ne{]}if nn/base get cc ctr put nn +/BitMaps get S ctr S sf 1 ne{A A length 1 sub A 2 index S get sf div put +}if put/ctr ctr 1 add N}B/I{cc 1 add D}B/bop{userdict/bop-hook known{ +bop-hook}if/SI save N @rigin 0 0 moveto/V matrix currentmatrix A 1 get A +mul exch 0 get A mul add .99 lt{/QV}{/RV}ifelse load def pop pop}N/eop{ +SI restore userdict/eop-hook known{eop-hook}if showpage}N/@start{ +userdict/start-hook known{start-hook}if pop/VResolution X/Resolution X +1000 div/DVImag X/IEn 256 array N 2 string 0 1 255{IEn S A 360 add 36 4 +index cvrs cvn put}for pop 65781.76 div/vsize X 65781.76 div/hsize X}N +/p{show}N/RMat[1 0 0 -1 0 0]N/BDot 260 string N/Rx 0 N/Ry 0 N/V{}B/RV/v{ +/Ry X/Rx X V}B statusdict begin/product where{pop false[(Display)(NeXT) +(LaserWriter 16/600)]{A length product length le{A length product exch 0 +exch getinterval eq{pop true exit}if}{pop}ifelse}forall}{false}ifelse +end{{gsave TR -.1 .1 TR 1 1 scale Rx Ry false RMat{BDot}imagemask +grestore}}{{gsave TR -.1 .1 TR Rx Ry scale 1 1 false RMat{BDot} +imagemask grestore}}ifelse B/QV{gsave newpath transform round exch round +exch itransform moveto Rx 0 rlineto 0 Ry neg rlineto Rx neg 0 rlineto +fill grestore}B/a{moveto}B/delta 0 N/tail{A/delta X 0 rmoveto}B/M{S p +delta add tail}B/b{S p tail}B/c{-4 M}B/d{-3 M}B/e{-2 M}B/f{-1 M}B/g{0 M} +B/h{1 M}B/i{2 M}B/j{3 M}B/k{4 M}B/w{0 rmoveto}B/l{p -4 w}B/m{p -3 w}B/n{ +p -2 w}B/o{p -1 w}B/q{p 1 w}B/r{p 2 w}B/s{p 3 w}B/t{p 4 w}B/x{0 S +rmoveto}B/y{3 2 roll p a}B/bos{/SS save N}B/eos{SS restore}B end + +%%EndProcSet +%%BeginProcSet: 8r.enc +% @@psencodingfile@{ +% author = "S. Rahtz, P. MacKay, Alan Jeffrey, B. Horn, K. Berry", +% version = "0.6", +% date = "22 June 1996", +% filename = "8r.enc", +% email = "kb@@mail.tug.org", +% address = "135 Center Hill Rd. // Plymouth, MA 02360", +% codetable = "ISO/ASCII", +% checksum = "119 662 4424", +% docstring = "Encoding for TrueType or Type 1 fonts to be used with TeX." +% @} +% +% Idea is to have all the characters normally included in Type 1 fonts +% available for typesetting. This is effectively the characters in Adobe +% Standard Encoding + ISO Latin 1 + extra characters from Lucida. +% +% Character code assignments were made as follows: +% +% (1) the Windows ANSI characters are almost all in their Windows ANSI +% positions, because some Windows users cannot easily reencode the +% fonts, and it makes no difference on other systems. The only Windows +% ANSI characters not available are those that make no sense for +% typesetting -- rubout (127 decimal), nobreakspace (160), softhyphen +% (173). quotesingle and grave are moved just because it's such an +% irritation not having them in TeX positions. +% +% (2) Remaining characters are assigned arbitrarily to the lower part +% of the range, avoiding 0, 10 and 13 in case we meet dumb software. +% +% (3) Y&Y Lucida Bright includes some extra text characters; in the +% hopes that other PostScript fonts, perhaps created for public +% consumption, will include them, they are included starting at 0x12. +% +% (4) Remaining positions left undefined are for use in (hopefully) +% upward-compatible revisions, if someday more characters are generally +% available. +% +% (5) hyphen appears twice for compatibility with both ASCII and Windows. +% +/TeXBase1Encoding [ +% 0x00 (encoded characters from Adobe Standard not in Windows 3.1) + /.notdef /dotaccent /fi /fl + /fraction /hungarumlaut /Lslash /lslash + /ogonek /ring /.notdef + /breve /minus /.notdef +% These are the only two remaining unencoded characters, so may as +% well include them. + /Zcaron /zcaron +% 0x10 + /caron /dotlessi +% (unusual TeX characters available in, e.g., Lucida Bright) + /dotlessj /ff /ffi /ffl + /.notdef /.notdef /.notdef /.notdef + /.notdef /.notdef /.notdef /.notdef + % very contentious; it's so painful not having quoteleft and quoteright + % at 96 and 145 that we move the things normally found there down to here. + /grave /quotesingle +% 0x20 (ASCII begins) + /space /exclam /quotedbl /numbersign + /dollar /percent /ampersand /quoteright + /parenleft /parenright /asterisk /plus /comma /hyphen /period /slash +% 0x30 + /zero /one /two /three /four /five /six /seven + /eight /nine /colon /semicolon /less /equal /greater /question +% 0x40 + /at /A /B /C /D /E /F /G /H /I /J /K /L /M /N /O +% 0x50 + /P /Q /R /S /T /U /V /W + /X /Y /Z /bracketleft /backslash /bracketright /asciicircum /underscore +% 0x60 + /quoteleft /a /b /c /d /e /f /g /h /i /j /k /l /m /n /o +% 0x70 + /p /q /r /s /t /u /v /w + /x /y /z /braceleft /bar /braceright /asciitilde + /.notdef % rubout; ASCII ends +% 0x80 + /.notdef /.notdef /quotesinglbase /florin + /quotedblbase /ellipsis /dagger /daggerdbl + /circumflex /perthousand /Scaron /guilsinglleft + /OE /.notdef /.notdef /.notdef +% 0x90 + /.notdef /.notdef /.notdef /quotedblleft + /quotedblright /bullet /endash /emdash + /tilde /trademark /scaron /guilsinglright + /oe /.notdef /.notdef /Ydieresis +% 0xA0 + /.notdef % nobreakspace + /exclamdown /cent /sterling + /currency /yen /brokenbar /section + /dieresis /copyright /ordfeminine /guillemotleft + /logicalnot + /hyphen % Y&Y (also at 45); Windows' softhyphen + /registered + /macron +% 0xD0 + /degree /plusminus /twosuperior /threesuperior + /acute /mu /paragraph /periodcentered + /cedilla /onesuperior /ordmasculine /guillemotright + /onequarter /onehalf /threequarters /questiondown +% 0xC0 + /Agrave /Aacute /Acircumflex /Atilde /Adieresis /Aring /AE /Ccedilla + /Egrave /Eacute /Ecircumflex /Edieresis + /Igrave /Iacute /Icircumflex /Idieresis +% 0xD0 + /Eth /Ntilde /Ograve /Oacute + /Ocircumflex /Otilde /Odieresis /multiply + /Oslash /Ugrave /Uacute /Ucircumflex + /Udieresis /Yacute /Thorn /germandbls +% 0xE0 + /agrave /aacute /acircumflex /atilde + /adieresis /aring /ae /ccedilla + /egrave /eacute /ecircumflex /edieresis + /igrave /iacute /icircumflex /idieresis +% 0xF0 + /eth /ntilde /ograve /oacute + /ocircumflex /otilde /odieresis /divide + /oslash /ugrave /uacute /ucircumflex + /udieresis /yacute /thorn /ydieresis +] def + +%%EndProcSet +%%BeginProcSet: texps.pro +%! +TeXDict begin/rf{findfont dup length 1 add dict begin{1 index/FID ne 2 +index/UniqueID ne and{def}{pop pop}ifelse}forall[1 index 0 6 -1 roll +exec 0 exch 5 -1 roll VResolution Resolution div mul neg 0 0]/Metrics +exch def dict begin Encoding{exch dup type/integertype ne{pop pop 1 sub +dup 0 le{pop}{[}ifelse}{FontMatrix 0 get div Metrics 0 get div def} +ifelse}forall Metrics/Metrics currentdict end def[2 index currentdict +end definefont 3 -1 roll makefont/setfont cvx]cvx def}def/ObliqueSlant{ +dup sin S cos div neg}B/SlantFont{4 index mul add}def/ExtendFont{3 -1 +roll mul exch}def/ReEncodeFont{CharStrings rcheck{/Encoding false def +dup[exch{dup CharStrings exch known not{pop/.notdef/Encoding true def} +if}forall Encoding{]exch pop}{cleartomark}ifelse}if/Encoding exch def} +def end + +%%EndProcSet +%%BeginProcSet: special.pro +%! +TeXDict begin/SDict 200 dict N SDict begin/@SpecialDefaults{/hs 612 N +/vs 792 N/ho 0 N/vo 0 N/hsc 1 N/vsc 1 N/ang 0 N/CLIP 0 N/rwiSeen false N +/rhiSeen false N/letter{}N/note{}N/a4{}N/legal{}N}B/@scaleunit 100 N +/@hscale{@scaleunit div/hsc X}B/@vscale{@scaleunit div/vsc X}B/@hsize{ +/hs X/CLIP 1 N}B/@vsize{/vs X/CLIP 1 N}B/@clip{/CLIP 2 N}B/@hoffset{/ho +X}B/@voffset{/vo X}B/@angle{/ang X}B/@rwi{10 div/rwi X/rwiSeen true N}B +/@rhi{10 div/rhi X/rhiSeen true N}B/@llx{/llx X}B/@lly{/lly X}B/@urx{ +/urx X}B/@ury{/ury X}B/magscale true def end/@MacSetUp{userdict/md known +{userdict/md get type/dicttype eq{userdict begin md length 10 add md +maxlength ge{/md md dup length 20 add dict copy def}if end md begin +/letter{}N/note{}N/legal{}N/od{txpose 1 0 mtx defaultmatrix dtransform S +atan/pa X newpath clippath mark{transform{itransform moveto}}{transform{ +itransform lineto}}{6 -2 roll transform 6 -2 roll transform 6 -2 roll +transform{itransform 6 2 roll itransform 6 2 roll itransform 6 2 roll +curveto}}{{closepath}}pathforall newpath counttomark array astore/gc xdf +pop ct 39 0 put 10 fz 0 fs 2 F/|______Courier fnt invertflag{PaintBlack} +if}N/txpose{pxs pys scale ppr aload pop por{noflips{pop S neg S TR pop 1 +-1 scale}if xflip yflip and{pop S neg S TR 180 rotate 1 -1 scale ppr 3 +get ppr 1 get neg sub neg ppr 2 get ppr 0 get neg sub neg TR}if xflip +yflip not and{pop S neg S TR pop 180 rotate ppr 3 get ppr 1 get neg sub +neg 0 TR}if yflip xflip not and{ppr 1 get neg ppr 0 get neg TR}if}{ +noflips{TR pop pop 270 rotate 1 -1 scale}if xflip yflip and{TR pop pop +90 rotate 1 -1 scale ppr 3 get ppr 1 get neg sub neg ppr 2 get ppr 0 get +neg sub neg TR}if xflip yflip not and{TR pop pop 90 rotate ppr 3 get ppr +1 get neg sub neg 0 TR}if yflip xflip not and{TR pop pop 270 rotate ppr +2 get ppr 0 get neg sub neg 0 S TR}if}ifelse scaleby96{ppr aload pop 4 +-1 roll add 2 div 3 1 roll add 2 div 2 copy TR .96 dup scale neg S neg S +TR}if}N/cp{pop pop showpage pm restore}N end}if}if}N/normalscale{ +Resolution 72 div VResolution 72 div neg scale magscale{DVImag dup scale +}if 0 setgray}N/psfts{S 65781.76 div N}N/startTexFig{/psf$SavedState +save N userdict maxlength dict begin/magscale true def normalscale +currentpoint TR/psf$ury psfts/psf$urx psfts/psf$lly psfts/psf$llx psfts +/psf$y psfts/psf$x psfts currentpoint/psf$cy X/psf$cx X/psf$sx psf$x +psf$urx psf$llx sub div N/psf$sy psf$y psf$ury psf$lly sub div N psf$sx +psf$sy scale psf$cx psf$sx div psf$llx sub psf$cy psf$sy div psf$ury sub +TR/showpage{}N/erasepage{}N/copypage{}N/p 3 def @MacSetUp}N/doclip{ +psf$llx psf$lly psf$urx psf$ury currentpoint 6 2 roll newpath 4 copy 4 2 +roll moveto 6 -1 roll S lineto S lineto S lineto closepath clip newpath +moveto}N/endTexFig{end psf$SavedState restore}N/@beginspecial{SDict +begin/SpecialSave save N gsave normalscale currentpoint TR +@SpecialDefaults count/ocount X/dcount countdictstack N}N/@setspecial{ +CLIP 1 eq{newpath 0 0 moveto hs 0 rlineto 0 vs rlineto hs neg 0 rlineto +closepath clip}if ho vo TR hsc vsc scale ang rotate rwiSeen{rwi urx llx +sub div rhiSeen{rhi ury lly sub div}{dup}ifelse scale llx neg lly neg TR +}{rhiSeen{rhi ury lly sub div dup scale llx neg lly neg TR}if}ifelse +CLIP 2 eq{newpath llx lly moveto urx lly lineto urx ury lineto llx ury +lineto closepath clip}if/showpage{}N/erasepage{}N/copypage{}N newpath}N +/@endspecial{count ocount sub{pop}repeat countdictstack dcount sub{end} +repeat grestore SpecialSave restore end}N/@defspecial{SDict begin}N +/@fedspecial{end}B/li{lineto}B/rl{rlineto}B/rc{rcurveto}B/np{/SaveX +currentpoint/SaveY X N 1 setlinecap newpath}N/st{stroke SaveX SaveY +moveto}N/fil{fill SaveX SaveY moveto}N/ellipse{/endangle X/startangle X +/yrad X/xrad X/savematrix matrix currentmatrix N TR xrad yrad scale 0 0 +1 startangle endangle arc savematrix setmatrix}N end + +%%EndProcSet +TeXDict begin 39158280 55380996 1000 600 600 (dddmp-2.0.dvi) +@start /Fa 143[55 1[55 7[28 2[50 99[{TeXBase1Encoding ReEncodeFont}4 +99.6264 /Helvetica rf +%DVIPSBitmapFont: Fb cmr12 12 3 +/Fb 3 53 df<14FF010713E090381F81F890383E007C01FC133F4848EB1F8049130F4848 +EB07C04848EB03E0A2000F15F0491301001F15F8A2003F15FCA390C8FC4815FEA54815FF +B3A46C15FEA56D1301003F15FCA3001F15F8A26C6CEB03F0A36C6CEB07E0000315C06D13 +0F6C6CEB1F806C6CEB3F00013E137C90381F81F8903807FFE0010090C7FC28447CC131> +48 D<143014F013011303131F13FFB5FC13E713071200B3B3B0497E497E007FB6FCA320 +4278C131>I52 D E +%EndDVIPSBitmapFont +/Fc 64[50 29[39 12[55 55 25[44 44 66 44 50 28 39 39 1[50 +50 50 72 28 44 1[28 50 50 28 44 50 44 50 50 10[61 2[50 +4[66 83 55 2[33 2[61 1[72 66 61 61 15[50 2[25 33 25 2[33 +33 37[50 2[{TeXBase1Encoding ReEncodeFont}45 99.6264 +/Times-Italic rf +%DVIPSBitmapFont: Fd cmmi12 12 3 +/Fd 3 103 df60 D<127012FCB4FCEA7FC0EA1FF0EA +07FCEA01FF38007FC0EB1FF0EB07FE903801FF809038007FE0EC1FF8EC03FE913800FF80 +ED3FE0ED0FF8ED03FF030013C0EE3FF0EE0FFCEE01FF9338007FC0EF1FF0EF07FCEF01FF +9438007FC0F01FE0A2F07FC0943801FF00EF07FCEF1FF0EF7FC04C48C7FCEE0FFCEE3FF0 +EEFFC0030390C8FCED0FF8ED3FE0EDFF80DA03FEC9FCEC1FF8EC7FE0903801FF80D907FE +CAFCEB1FF0EB7FC04848CBFCEA07FCEA1FF0EA7FC048CCFC12FC12703B3878B44C>62 +D102 +D E +%EndDVIPSBitmapFont +/Fe 134[42 2[42 42 23 32 28 1[42 42 42 65 23 2[23 42 +42 28 37 42 1[42 37 12[51 10[28 4[60 1[55 19[21 28 21 +44[{TeXBase1Encoding ReEncodeFont}26 83.022 /Times-Roman +rf +%DVIPSBitmapFont: Ff cmr7 7 2 +/Ff 2 51 df<13381378EA01F8121F12FE12E01200B3AB487EB512F8A215267BA521>49 +D<13FF000313E0380E03F0381800F848137C48137E00787F12FC6CEB1F80A4127CC7FC15 +005C143E147E147C5C495A495A5C495A010EC7FC5B5B903870018013E0EA018039030003 +0012065A001FB5FC5A485BB5FCA219267DA521>I E +%EndDVIPSBitmapFont +/Fg 103[60 26[60 1[60 60 60 60 60 60 60 60 60 60 60 60 +60 60 60 60 2[60 60 60 60 60 60 60 60 60 3[60 1[60 3[60 +60 1[60 60 1[60 60 1[60 60 3[60 1[60 1[60 60 60 1[60 +60 1[60 1[60 1[60 60 60 60 60 60 60 60 60 60 60 60 60 +60 60 5[60 38[{TeXBase1Encoding ReEncodeFont}62 99.6264 +/Courier rf +%DVIPSBitmapFont: Fh cmr8 8 2 +/Fh 2 51 df<130C133C137CEA03FC12FFEAFC7C1200B3B113FE387FFFFEA2172C7AAB23 +>49 DI E +%EndDVIPSBitmapFont +/Fi 105[50 28[50 50 2[55 33 39 44 1[55 50 55 83 28 2[28 +1[50 33 44 55 44 55 50 10[72 1[66 55 3[78 72 94 66 3[78 +1[61 66 72 72 66 72 13[50 50 50 1[28 25 33 45[{ +TeXBase1Encoding ReEncodeFont}40 99.6264 /Times-Bold +rf /Fj 139[40 1[53 1[66 60 66 100 33 2[33 3[53 3[60 23[47 +2[73 18[60 60 60 2[30 46[{TeXBase1Encoding ReEncodeFont}16 +119.552 /Times-Bold rf +%DVIPSBitmapFont: Fk cmsy10 12 1 +/Fk 1 16 df<49B4FC010F13E0013F13F8497F48B6FC4815804815C04815E04815F0A248 +15F8A24815FCA3B712FEA96C15FCA36C15F8A26C15F0A26C15E06C15C06C15806C15006C +6C13FC6D5B010F13E0010190C7FC27277BAB32>15 D E +%EndDVIPSBitmapFont +/Fl 64[44 42[44 44 24[44 50 50 72 50 50 28 39 33 50 50 +50 50 78 28 50 28 28 50 50 33 44 50 44 50 44 6[61 1[72 +94 72 72 61 55 66 72 55 72 72 89 61 1[39 33 72 72 55 +61 72 66 66 72 3[56 1[28 28 50 50 50 50 50 50 50 50 50 +50 28 25 33 25 2[33 33 36[55 55 2[{TeXBase1Encoding ReEncodeFont}74 +99.6264 /Times-Roman rf +%DVIPSBitmapFont: Fm cmsy10 14.4 2 +/Fm 2 104 df102 +DI E +%EndDVIPSBitmapFont +/Fn 105[60 27[53 4[60 33 47 40 60 60 60 60 93 33 2[33 +1[60 40 53 60 53 60 53 7[86 4[73 66 1[86 66 3[73 2[40 +1[86 1[73 86 80 1[86 110 5[33 60 4[60 1[60 60 60 1[30 +40 30 44[{TeXBase1Encoding ReEncodeFont}42 119.552 /Times-Roman +rf /Fo 136[104 1[80 48 56 64 1[80 72 80 120 40 80 1[40 +1[72 1[64 80 64 80 72 12[96 80 104 1[88 1[104 135 3[56 +2[88 1[104 104 96 104 6[48 1[72 72 72 72 72 72 72 72 +72 1[36 46[{TeXBase1Encoding ReEncodeFont}41 143.462 +/Times-Bold rf end +%%EndProlog +%%BeginSetup +%%Feature: *Resolution 600dpi +TeXDict begin +%%BeginPaperSize: a4 +a4 +%%EndPaperSize + +%%EndSetup +%%Page: 1 1 +1 0 bop 472 600 a Fo(DDDMP:)35 b(Decision)f(Diagram)f(DuMP)j(package) +1480 830 y(Release)e(2.0)462 1230 y Fn(Gianpiero)c(Cabodi)2402 +1232 y(Stef)o(ano)g(Quer)1316 1506 y(Politecnico)g(di)g(T)-10 +b(orino)1024 1656 y(Dip.)30 b(di)g(Automatica)g(e)g(Informatica)1119 +1805 y(Corso)f(Duca)h(de)n(gli)g(Abruzzi)g(24)1277 1955 +y(I\22610129)e(T)-5 b(urin,)29 b(IT)-11 b(AL)f(Y)1038 +2104 y(E-mail:)38 b Fm(f)p Fn(cabodi,quer)p Fm(g)p Fn(@polito.it)-189 +2614 y Fo(1)143 b(Intr)m(oduction)-189 2837 y Fl(The)27 +b(DDDMP)h(package)f(de\002nes)h(formats)f(and)g(rules)g(to)g(store)g +(DD)g(on)g(\002le.)39 b(More)27 b(in)g(particular)g(it)g(contains)g(a) +-189 2958 y(set)e(of)g(functions)e(to)i(dump)e(\(store)i(and)g(load\))g +(DDs)f(and)h(DD)g(forests)f(on)h(\002le)g(in)f(dif)n(ferent)h(formats.) +47 3078 y(In)30 b(the)g(present)g(implementation,)f(BDDs)h(\(R)l +(OBDDs\))h(and)f(ADD)g(\(Algebraic)g(Decision)g(Diagram\))g(of)-189 +3199 y(the)g(CUDD)g(package)g(\(v)o(ersion)f(2.3.0)g(or)h(higher\))g +(are)g(supported.)45 b(These)30 b(structures)f(can)h(be)g(represented)g +(on)-189 3319 y(\002les)25 b(either)g(in)f(te)o(xt,)g(binary)-6 +b(,)24 b(or)h(CNF)g(\(DIMA)l(CS\))h(formats.)47 3439 +y(The)f(main)f(rules)h(used)f(are)i(follo)n(wing)d(rules:)-44 +3643 y Fk(\017)49 b Fl(A)30 b(\002le)h(contains)e(a)i(single)e(BDD/ADD) +h(or)g(a)h(forest)f(of)g(BDDs/ADD,)g(i.e.,)i(a)e(v)o(ector)g(of)g +(Boolean)h(func-)55 3763 y(tions.)-44 3966 y Fk(\017)49 +b Fl(Inte)o(ger)21 b(inde)o(x)o(es)f(are)i(used)f(instead)g(of)g +(pointers)g(to)g(reference)i(nodes.)29 b(BDD/ADD)21 b(nodes)g(are)h +(numbered)55 4087 y(with)j(contiguous)g(numbers,)g(from)h(1)g(to)f +(NNodes)h(\(total)f(number)h(of)g(nodes)g(on)f(a)i(\002le\).)35 +b(0)26 b(is)f(not)h(used)f(to)55 4207 y(allo)n(w)f(ne)o(gati)n(v)o(e)e +(inde)o(x)o(es)h(for)i(complemented)f(edges.)-44 4411 +y Fk(\017)49 b Fl(A)23 b(\002le)g(contains)f(a)h(header)l(,)h +(including)d(se)n(v)o(eral)h(informations)f(about)h(v)n(ariables)h(and) +f(roots)g(of)h(BDD)h(func-)55 4531 y(tions,)32 b(then)e(the)h(list)g +(of)g(nodes.)49 b(The)32 b(header)f(is)g(al)o(w)o(ays)g(represented)h +(in)f(te)o(xt)f(format)h(\(also)g(for)g(binary)55 4651 +y(\002les\).)g(BDDs,)25 b(ADDs,)f(and)h(CNF)h(\002les)f(share)g(a)g +(similar)f(format)g(header)-5 b(.)-44 4855 y Fk(\017)49 +b Fl(BDD/ADD)40 b(nodes)g(are)h(listed)f(follo)n(wing)e(their)i +(numbering,)j(which)d(is)g(produced)g(by)h(a)f(post-order)55 +4975 y(tra)n(v)o(ersal,)24 b(in)h(such)f(a)h(w)o(ay)g(that)g(a)g(node)f +(is)h(al)o(w)o(ays)f(listed)g(after)h(its)f(Then/Else)g(children.)47 +5179 y(In)32 b(the)f(sequel)g(we)g(describe)h(more)f(in)g(detail)f(the) +h(dif)n(ferent)g(formats)g(and)g(procedures)h(a)n(v)n(ailable.)49 +b(First)-189 5299 y(of)26 b(all,)f(we)h(describe)f(BDDs)h(and)g(ADDs)f +(formats)g(and)g(procedure.)33 b(Secondly)-6 b(,)26 b(we)f(concentrate) +h(on)f(CNF)i(\002les,)-189 5419 y(i.e.,)e(ho)n(w)f(to)g(translate)g(a)i +(BDD)f(or)g(a)g(forest)g(of)f(BDDs)h(into)f(a)h(CNF)h(formula)e(and)h +(vice-v)o(ersa.)1794 5800 y(1)p eop +%%Page: 2 2 +2 1 bop -189 218 a Fo(2)143 b(BDD)35 b(and)g(ADD)g(Support)-189 +441 y Fl(In)23 b(this)f(section)g(we)g(describe)h(format)g(and)f +(procedure)h(re)o(garding)f(BDDs)h(and)f(ADDs.)30 b(W)-8 +b(e)23 b(speci\002cally)g(refer)g(to)-189 562 y(BDDs)h(in)g(the)g +(description)e(as)j(ADD)e(may)h(be)g(seen)g(as)h(an)f(e)o(xtension)e +(and)i(will)f(be)h(described)g(later)-5 b(.)30 b(First)24 +b(of)g(all,)-189 682 y(we)29 b(concentrate)f(on)g(the)g(format)g(used)g +(to)g(store)g(these)g(structure,)h(then)f(we)g(describe)h(the)f +(procedure)h(a)n(v)n(ailable)-189 802 y(to)24 b(store)h(and)g(load)f +(them.)-189 1094 y Fj(2.1)119 b(F)m(ormat)-189 1281 y +Fl(BDD)30 b(dump)f(\002les)g(are)i(composed)e(of)g(tw)o(o)g(sections:) +40 b(The)29 b(header)h(and)g(the)f(list)g(of)h(nodes.)44 +b(The)30 b(header)g(has)g(a)-189 1402 y(common)c(\(te)o(xt\))h(format,) +h(while)e(the)i(list)e(of)h(nodes)g(is)g(either)g(in)g(te)o(xt)g(or)g +(binary)g(format.)38 b(In)28 b(te)o(xt)e(format)h(nodes)-189 +1522 y(are)33 b(represented)f(with)f(redundant)g(informations,)h(where) +h(the)f(main)f(goal)g(is)h(readability)-6 b(,)32 b(while)g(the)f +(purpose)-189 1642 y(of)i(binary)f(format)g(is)g(minimizing)e(the)i(o)o +(v)o(erall)f(storage)h(size)h(for)g(BDD)f(nodes.)54 b(The)32 +b(header)h(format)f(is)g(k)o(ept)-189 1763 y(common)h(to)h(te)o(xt)g +(and)g(binary)g(formats)g(for)h(sak)o(e)f(of)h(simplicity:)47 +b(No)34 b(particular)g(optimization)f(is)h(presently)-189 +1883 y(done)29 b(on)f(binary)h(\002le)g(headers,)h(whose)f(size)g(is)f +(by)h(f)o(ar)g(dominated)f(by)h(node)f(lists)g(in)g(the)h(case)g(of)g +(lar)n(ge)h(BDDs)-189 2003 y(\(se)n(v)o(eral)24 b(thousands)g(of)h(DD)f +(nodes\).)-189 2266 y Fi(2.1.1)99 b(Header)-189 2453 +y Fl(The)23 b(header)h(has)f(the)g(same)g(format)g(both)g(for)g(te)o +(xtual)f(and)i(binary)e(dump.)30 b(F)o(or)23 b(sak)o(e)g(of)h +(generality)e(and)h(because)-189 2574 y(of)f(dynamic)g(v)n(ariable)g +(ordering)g(both)f(v)n(ariable)h(IDs)g(and)g(permutations)2377 +2537 y Fh(1)2438 2574 y Fl(are)h(included.)29 b(Names)22 +b(are)h(optionally)-189 2694 y(listed)35 b(for)h(input)f(v)n(ariables)g +(and)h(for)h(the)e(stored)h(functions.)63 b(Ne)n(w)36 +b(auxiliary)f(IDs)h(are)h(also)e(allo)n(wed.)64 b(Only)-189 +2814 y(the)34 b(v)n(ariables)f(in)g(the)h(true)g(support)f(of)h(the)f +(stored)h(BDDs)g(are)h(listed.)56 b(All)34 b(information)e(on)i(v)n +(ariables)f(\(IDs,)-189 2935 y(permutations,)c(names,)i(auxiliary)e +(IDs\))h(sorted)g(by)g(IDs,)h(and)e(the)o(y)h(are)g(restricted)g(to)f +(the)h(true)g(support)f(of)h(the)-189 3055 y(dumped)22 +b(BDD,)h(while)g(IDs)g(and)f(permutations)g(are)h(referred)i(to)d(the)h +(writing)f(BDD)h(manager)-5 b(.)30 b(Names)22 b(can)i(thus)-189 +3175 y(be)h(sorted)f(by)h(v)n(ariable)f(ordering)h(by)f(permuting)g +(them)g(according)h(to)f(the)h(permutations)e(stored)h(in)h(the)f +(\002le.)47 3296 y(As)h(an)g(e)o(xample,)f(the)g(header)i(\(in)e(te)o +(xt)g(mode\))h(of)f(the)h(ne)o(xt)f(state)h(functions)e(of)i(circuit)g +(s27)f(follo)n(ws:)-189 3494 y Fg(.ver)59 b(DDDMP-2.0)-189 +3615 y(.mode)g(A)-189 3735 y(.varinfo)f(3)-189 3855 y(.dd)h(s27-delta) +-189 3976 y(.nnodes)f(16)-189 4096 y(.nvars)g(10)-189 +4216 y(.nsuppvars)g(7)-189 4337 y(.varnames)g(G0)h(G1)g(G2)h(G3)f(G5)g +(G6)h(G7)-189 4457 y(.orderedvarnames)c(G0)k(G1)f(G2)g(G3)h(G5)f(G6)g +(G7)-189 4578 y(.ids)g(0)g(1)h(2)g(3)f(4)h(5)f(6)-189 +4698 y(.permids)f(0)i(1)f(2)h(3)f(5)h(7)f(9)-189 4818 +y(.auxids)f(1)i(2)f(3)h(4)f(5)h(6)g(7)-189 4939 y(.nroots)e(3)-189 +5059 y(.rootids)g(6)i(-13)f(-16)-189 5179 y(.rootnames)f(G10)h(G11)g +(G13)47 5378 y Fl(The)25 b(lines)f(contain)g(the)h(follo)n(wing)e +(informations:)p -189 5460 1607 4 v -77 5521 a Ff(1)-40 +5551 y Fe(The)d(permutation)e(of)i(the)g(i-th)h(v)n(ariable)e(ID)h(is)h +(the)f(relati)n(v)o(e)g(position)f(of)h(the)g(v)n(ariable)f(in)i(the)f +(ordering.)1794 5800 y Fl(2)p eop +%%Page: 3 3 +3 2 bop -44 218 a Fk(\017)49 b Fl(Dddmp)24 b(v)o(ersion)f(information.) +-44 411 y Fk(\017)49 b Fl(File)25 b(mode)f(\(A)h(for)g(ASCII)h(te)o +(xt,)e(B)h(for)g(binary)g(mode\).)-44 604 y Fk(\017)49 +b Fl(V)-11 b(ar)n(-e)o(xtra-info)25 b(\(0:)30 b(v)n(ariable)24 +b(ID,)h(1:)31 b(permID,)24 b(2:)31 b(aux)25 b(ID,)g(3:)30 +b(v)n(ariable)24 b(name,)h(4)g(no)f(e)o(xtra)h(info\).)-44 +797 y Fk(\017)49 b Fl(Name)25 b(of)g(dd)f(\(optional\).)-44 +990 y Fk(\017)49 b Fl(T)-8 b(otal)24 b(number)g(of)h(nodes)g(in)f(the)h +(\002le.)-44 1183 y Fk(\017)49 b Fl(Number)24 b(of)h(v)n(ariables)f(of) +h(the)g(writing)f(DD)g(manager)-5 b(.)-44 1375 y Fk(\017)49 +b Fl(Number)24 b(of)h(v)n(ariables)f(in)h(the)f(true)h(support)f(of)h +(the)f(stored)h(DDs.)-44 1568 y Fk(\017)49 b Fl(V)-11 +b(ariable)25 b(names)f(\(optional\))g(for)h(all)g(the)f(v)n(ariables)g +(in)h(the)f(BDD/ADD)h(support.)-44 1761 y Fk(\017)49 +b Fl(V)-11 b(ariable)20 b(names)g(for)h(all)f(the)g(v)n(ariables)f(in)h +(the)g(DD)h(manager)f(during)g(the)g(storing)f(phase.)29 +b(Notice)20 b(that)g(this)55 1882 y(information)k(w)o(as)h(not)g +(stored)g(by)g(pre)n(vious)f(v)o(ersions)g(of)i(the)f(same)g(tool.)32 +b(Full)25 b(backw)o(ard)g(compatibility)55 2002 y(is)f(guaranteed)h(by) +g(the)f(present)h(implementation)d(of)j(the)g(tool.)-44 +2195 y Fk(\017)49 b Fl(V)-11 b(ariable)25 b(IDs.)-44 +2388 y Fk(\017)49 b Fl(V)-11 b(ariable)25 b(permuted)f(IDs.)-44 +2581 y Fk(\017)49 b Fl(V)-11 b(ariable)25 b(auxiliary)f(IDs)h +(\(optional\).)-44 2774 y Fk(\017)49 b Fl(Number)24 b(of)h(BDD)g +(roots.)-44 2967 y Fk(\017)49 b Fl(Inde)o(x)o(es)24 b(of)h(BDD)g(roots) +f(\(complemented)g(edges)g(allo)n(wed\).)-44 3160 y Fk(\017)49 +b Fl(Names)24 b(of)h(BDD)h(roots)e(\(optional\).)-189 +3332 y(Notice)h(that)f(a)h(\002eld)-189 3504 y Fg(.add)-189 +3676 y Fl(is)f(present)h(after)g(the)g(dddmp)f(v)o(ersion)f(for)j +(\002les)e(containing)g(ADDs.)-189 3936 y Fi(2.1.2)99 +b(T)-9 b(ext)25 b(F)n(ormat)-189 4124 y Fl(In)g(te)o(xt)f(mode)g(nodes) +g(are)i(listed)e(on)g(a)h(te)o(xt)f(line)h(basis.)30 +b(Each)25 b(a)g(node)f(is)h(represented)g(as)-189 4296 +y Fg()57 b([])f()588 +4416 y()h()-189 4588 y Fl(where)25 +b(all)g(inde)o(x)o(es)e(are)j(inte)o(ger)e(numbers.)47 +4709 y(This)h(format)g(is)g(redundant)f(\(due)i(to)f(the)g(node)g +(ordering,)g Fd(<)p Fl(Node-inde)o(x)p Fd(>)f Fl(is)g(and)i +(incremental)e(inte)o(ger\))-189 4829 y(b)n(ut)g(we)h(k)o(eep)g(it)g +(for)g(readability)-6 b(.)47 4949 y Fd(<)p Fl(V)-11 b(ar)n(-e)o +(xtra-info)p Fd(>)34 b Fl(\(optional)e(redundant)i(\002eld\))g(is)f +(either)h(an)g(inte)o(ger)f(\(ID,)h(PermID,)g(or)g(auxID\))g(or)g(a) +-189 5070 y(string)k(\(v)n(ariable)h(name\).)75 b Fd(<)p +Fl(V)-11 b(ar)n(-internal-inde)o(x)p Fd(>)38 b Fl(is)h(an)g(internal)g +(v)n(ariable)g(inde)o(x:)59 b(V)-11 b(ariables)39 b(in)g(the)g(true) +-189 5190 y(support)25 b(of)h(the)g(stored)g(BDDs)g(are)h(numbered)e +(with)g(ascending)h(inte)o(gers)f(starting)g(from)h(0,)g(and)g(follo)n +(wing)e(the)-189 5311 y(v)n(ariable)g(ordering.)31 b +Fd(<)p Fl(Then-inde)o(x)p Fd(>)23 b Fl(and)i Fd(<)p Fl(Else-inde)o(x)p +Fd(>)e Fl(are)j(signed)e(inde)o(x)o(es)f(of)i(children)f(nodes.)47 +5431 y(In)h(the)f(follo)n(wing,)f(we)i(report)f(the)g(list)g(of)h +(nodes)f(of)g(the)h(s27)f(ne)o(xt)f(state)i(functions)e(\(see)i(pre)n +(vious)e(header)-189 5551 y(e)o(xample\):)1794 5800 y(3)p +eop +%%Page: 4 4 +4 3 bop -189 218 a Fg(.nodes)-189 338 y(1)60 b(T)f(1)h(0)f(0)-189 +459 y(2)h(G7)f(6)g(1)h(-1)-189 579 y(3)g(G5)f(4)g(1)h(2)-189 +699 y(4)g(G3)f(3)g(3)h(1)-189 820 y(5)g(G1)f(1)g(1)h(4)-189 +940 y(6)g(G0)f(0)g(5)h(-1)-189 1061 y(7)g(G6)f(5)g(1)h(-1)-189 +1181 y(8)g(G5)f(4)g(1)h(-7)-189 1301 y(9)g(G6)f(5)g(1)h(-2)-189 +1422 y(10)f(G5)h(4)f(1)h(-9)-189 1542 y(11)f(G3)h(3)f(10)h(8)-189 +1662 y(12)f(G1)h(1)f(8)h(11)-189 1783 y(13)f(G0)h(0)f(5)h(12)-189 +1903 y(14)f(G2)h(2)f(1)h(-1)-189 2024 y(15)f(G2)h(2)f(1)h(-2)-189 +2144 y(16)f(G1)h(1)f(14)h(15)-189 2264 y(.end)-189 2468 +y Fl(The)27 b(list)f(is)h(enclosed)g(between)g(the)g +Fg(.nodes)f Fl(and)h Fg(.end)f Fl(lines.)37 b(First)27 +b(node)g(is)g(the)g(one)g(constant,)f(each)i(node)-189 +2588 y(contains)c(the)h(optional)e(v)n(ariable)h(name.)47 +2708 y(F)o(or)29 b(ADDs)f(more)h(than)f(one)h(constant)e(is)i(stored)f +(in)g(the)g(\002le.)43 b(Each)29 b(constant)f(has)g(the)h(same)f +(format)h(we)-189 2829 y(ha)n(v)o(e)c(just)e(analyzed)i(for)g(the)g +(BDD)g(b)n(ut)g(the)f(represented)h(v)n(alue)f(is)h(stored)f(as)h(a)g +(\003oat)g(number)-5 b(.)-189 3095 y Fi(2.1.3)99 b(Binary)25 +b(F)n(ormat)-189 3283 y Fl(The)h(binary)g(format)f(is)h(not)f(allo)n +(wed)g(for)i(ADDs.)33 b(As)26 b(a)h(consequence)f(we)g(concentrate)g +(only)f(on)h(BDDs)g(in)g(this)-189 3403 y(section.)k(In)25 +b(binary)f(mode)h(nodes)f(are)i(represented)f(as)g(a)g(sequence)g(of)g +(bytes,)f(encoding)g(tuples)-189 3606 y Fg()-189 +3727 y([])-189 3847 y([])-189 +3968 y([])-189 4171 y Fl(in)30 b(an)g(optimized)f(w)o(ay)-6 +b(.)46 b(Only)29 b(the)h(\002rst)g(byte)g(\(code\))h(is)e(mandatory)-6 +b(,)30 b(while)g(inte)o(ger)f(inde)o(x)o(es)g(are)i(represented)-189 +4291 y(in)c(absolute)f(or)h(relati)n(v)o(e)f(mode,)h(where)h(relati)n +(v)o(e)e(means)g(of)n(fset)h(with)f(respect)i(to)e(a)i(Then/Else)e +(node)h(info.)37 b(The)-189 4412 y(best)23 b(between)g(absolute)f(and)h +(relati)n(v)o(e)e(representation)i(is)f(chosen)h(and)g(relati)n(v)o(e)f +(1)h(is)f(directly)g(coded)h(in)g Fd(<)p Fl(Node-)-189 +4532 y(code)p Fd(>)e Fl(without)f(an)o(y)g(e)o(xtra)h(info.)29 +b(Suppose)21 b(V)-11 b(ar\(NodeId\),)22 b(Then\(NodeId\))f(and)g +(Else\(NodeId\))f(represent)i(infos)-189 4652 y(about)i(a)h(gi)n(v)o +(en)f(node.)30 b Fd(<)p Fl(Node-code)p Fd(>)25 b Fl(is)f(a)h(byte)g +(which)f(contains)g(the)h(follo)n(wing)e(bit)h(\002elds)h(\(MSB)g(to)g +(LSB\))-44 4856 y Fk(\017)49 b Fl(Unused)24 b(:)31 b(1)24 +b(bit)-44 5059 y Fk(\017)49 b Fl(V)-11 b(ariable:)30 +b(2)25 b(bits,)f(one)h(of)g(the)f(follo)n(wing)f(codes)171 +5288 y Fi(\226)49 b Fl(DDDMP)p 636 5288 30 4 v 35 w(ABSOLUTE)p +1191 5288 V 36 w(ID:)22 b(V)-11 b(ar\(NodeId\))22 b(is)f(represented)h +(in)g(absolute)f(form)g(as)h Fd(<)p Fl(V)-11 b(ar)n(-internal-)270 +5408 y(info)p Fd(>)24 b Fl(=)h(V)-11 b(ar\(NodeId\))25 +b(follo)n(ws)e(\(absolute)i(info\))1794 5800 y(4)p eop +%%Page: 5 5 +5 4 bop 171 218 a Fi(\226)49 b Fl(DDDMP)p 636 218 30 +4 v 35 w(RELA)-11 b(TIVE)p 1147 218 V 36 w(ID:)32 b(V)-11 +b(ar\(NodeId\))32 b(is)g(represented)g(in)f(relati)n(v)o(e)g(form)h(as) +g Fd(<)p Fl(V)-11 b(ar)n(-internal-)270 338 y(info\277)24 +b(=)h(Min\(V)-11 b(ar\(Then\(NodeId\)\),V)g(ar\(Else\(NodeId\)\)\)-V)g +(ar\(NodeId\))171 500 y Fi(\226)49 b Fl(DDDMP)p 636 500 +V 35 w(RELA)-11 b(TIVE)p 1147 500 V 36 w(1:)27 b(the)19 +b(\002eld)g Fd(<)p Fl(V)-11 b(ar)n(-internal-info)p Fd(>)18 +b Fl(does)h(not)f(follo)n(w)-6 b(,)18 b(because)h(V)-11 +b(ar\(NodeId\))270 620 y(=)25 b(Min\(V)-11 b(ar\(Then\(NodeId\)\),V)g +(ar\(Else\(NodeId\)\)\)-1)171 782 y Fi(\226)49 b Fl(DDDMP)p +636 782 V 35 w(TERMIN)m(AL:)24 b(Node)h(is)f(a)h(terminal,)f(no)g(v)n +(ar)h(info)g(required)-44 1011 y Fk(\017)49 b Fl(T)25 +b(:)f(2)h(bits,)f(with)g(codes)h(similar)e(to)i(V)171 +1214 y Fi(\226)49 b Fl(DDDMP)p 636 1214 V 35 w(ABSOLUTE)p +1191 1214 V 36 w(ID:)20 b Fd(<)p Fl(Then-info)p Fd(>)f +Fl(is)h(represented)g(in)g(absolute)f(form)h(as)g Fd(<)p +Fl(Then-info)p Fd(>)270 1334 y Fl(=)25 b(Then\(NodeId\))171 +1496 y Fi(\226)49 b Fl(DDDMP)p 636 1496 V 35 w(RELA)-11 +b(TIVE)p 1147 1496 V 36 w(ID:)28 b(Then\(NodeId\))f(is)g(represented)h +(in)g(relati)n(v)o(e)e(form)i(as)g Fd(<)p Fl(Then-info)p +Fd(>)270 1617 y Fl(=)d(Nodeid-Then\(NodeId\))171 1779 +y Fi(\226)49 b Fl(DDDMP)p 636 1779 V 35 w(RELA)-11 b(TIVE)p +1147 1779 V 36 w(1:)30 b(no)25 b Fd(<)p Fl(Then-info)p +Fd(>)f Fl(follo)n(ws,)f(because)i(Then\(NodeId\))g(=)g(NodeId-1)171 +1941 y Fi(\226)49 b Fl(DDDMP)p 636 1941 V 35 w(TERMIN)m(AL:)24 +b(Then)h(Node)f(is)h(a)g(terminal,)f(no)g(info)h(required)f(\(for)i(R)l +(OBDDs\))-44 2144 y Fk(\017)49 b Fl(Ecompl)24 b(:)30 +b(1)25 b(bit,)f(if)h(1)g(means)f(that)g(the)h(else)g(edge)g(is)f +(complemented)-44 2347 y Fk(\017)49 b Fl(E)25 b(:)f(2)h(bits,)f(with)g +(codes)h(and)f(meanings)g(as)h(for)g(the)g(Then)f(edge)-189 +2551 y(DD)35 b(node)f(codes)h(are)h(written)e(as)h(one)g(byte.)60 +b Fd(<)p Fl(V)-11 b(ar)n(-internal-inde)o(x)p Fd(>)p +Fl(,)36 b Fd(<)p Fl(Then-inde)o(x)p Fd(>)p Fl(,)g Fd(<)p +Fl(Else-inde)o(x)p Fd(>)e Fl(\(if)-189 2671 y(required\))25 +b(are)h(represented)f(as)g(unsigned)e(inte)o(ger)h(v)n(alues)g(on)h(a)g +(suf)n(\002cient)f(set)h(of)g(bytes)f(\(MSByte)h(\002rst\).)47 +2792 y(Inte)o(gers)h(of)f(an)o(y)h(length)e(are)j(written)e(as)h +(sequences)g(of)g(\224link)o(ed\224)f(bytes)g(\(MSByte)h(\002rst\).)34 +b(F)o(or)26 b(each)g(byte)-189 2912 y(7)f(bits)f(are)h(used)g(for)g +(data)g(and)f(one)h(\(MSBit\))g(as)g(link)f(with)g(a)h(further)g(byte)g +(\(MSB)g(=)g(1)g(means)f(one)h(more)g(byte\).)47 3032 +y(Lo)n(w)f(le)n(v)o(el)g(read/write)h(of)g(bytes)f(\002lters)h +Fd(<)p Fl(CR)p Fd(>)p Fl(,)g Fd(<)p Fl(LF)p Fd(>)g Fl(and)g +Fd(<)p Fl(ctrl-Z)p Fd(>)f Fl(through)g(escape)h(sequences.)-189 +3327 y Fj(2.2)119 b(Implementation)-189 3515 y Fl(Store)24 +b(and)g(load)g(for)g(single)g(Boolean)g(functions)f(and)h(arrays)g(of)g +(Boolean)g(functions)f(are)i(implemented.)k(More-)-189 +3635 y(o)o(v)o(er)l(,)37 b(the)e(current)h(presentation)f(includes)f +(functions)h(to)g(retrie)n(v)o(e)g(v)n(ariables)f(names,)k(auxiliary)d +(identi\002erss,)-189 3756 y(and)c(all)g(the)g(information)f(contained) +h(in)f(the)h(header)h(of)f(the)h(\002les.)50 b(This)30 +b(information)g(can)h(be)h(used)f(as)g(a)g(pre-)-189 +3876 y(processing)19 b(step)g(for)i(load)e(operations.)28 +b(These)20 b(functions)f(allo)n(w)f(to)i(o)o(v)o(ercome)f(fe)n(w)g +(limitations)f(of)h(the)h(pre)n(vious)-189 3997 y(implementations.)-189 +4263 y Fi(2.2.1)99 b(Storing)25 b(Decision)g(Diagrams)-189 +4450 y Fc(Dddmp)p 111 4450 V 35 w(cuddBddStor)l(e)f Fl(and)h +Fc(Dddmp)p 1195 4450 V 35 w(cuddBddArr)o(ayStor)l(e)e +Fl(are)j(the)f(tw)o(o)f(store)h(functions,)f(used)h(to)g(store)f(sin-) +-189 4571 y(gle)f(BDD)h(or)g(a)f(forest)h(of)f(BDDs,)h(respecti)n(v)o +(ely)-6 b(.)28 b(Internally)-6 b(,)23 b Fc(Dddmp)p 2275 +4571 V 35 w(cuddBddStor)l(e)f Fl(b)n(uilds)g(a)i(dummy)e(1)h(entry)-189 +4691 y(array)j(of)e(BDDs,)h(and)g(calls)g Fc(dddmp)p +1102 4691 V 35 w(cuddBddArr)o(ayStor)l(e)p Fl(.)47 4811 +y(Since)30 b(con)l(v)o(ersion)e(from)h(DD)h(pointers)e(to)h(inte)o(ger) +f(is)h(required,)i(DD)e(nodes)g(are)h(temporarily)e(remo)o(v)o(ed)-189 +4932 y(from)23 b(the)f(unique)h(hash.)29 b(This)23 b(mak)o(es)f(room)g +(in)h(their)f Fc(ne)n(xt)h Fl(\002eld)h(to)e(store)h(node)f(IDs.)30 +b(Nodes)23 b(are)h(re-link)o(ed)e(after)-189 5052 y(the)i(store)g +(operation,)g(possible)f(in)g(a)i(modi\002ed)e(order)-5 +b(.)31 b(Dumping)22 b(is)i(either)g(in)g(te)o(xt)f(or)i(binary)f(form.) +30 b(Both)24 b(a)g(\002le)-189 5173 y(pointer)31 b(\()p +Fc(fp)p Fl(\))g(and)g(a)h(\002le)g(name)f(\()p Fc(fname)p +Fl(\))h(are)g(pro)o(vided)e(as)h(inputs)f(parameters)i(to)f(store)g +(routines.)50 b(BDDs)31 b(are)-189 5293 y(stored)c(to)g(the)g(already)g +(open)h(\002le)f Fc(fp)p Fl(,)h(if)f(not)g(NULL.)g(Otherwise)f(\002le)i +(whose)f(name)g(is)g Fc(fname)g Fl(is)g(opened.)38 b(This)-189 +5413 y(is)24 b(intended)g(to)h(allo)n(w)f(either)g(DD)h(storage)g +(within)e(\002les)i(containing)f(other)g(data,)h(or)g(to)g(speci\002c)g +(\002les.)1794 5800 y(5)p eop +%%Page: 6 6 +6 5 bop -189 218 a Fi(2.2.2)99 b(Loading)25 b(Decision)g(Diagrams)-189 +405 y Fc(Dddmp)p 111 405 30 4 v 35 w(cuddBddLoad)37 b +Fl(and)h Fc(Dddmp)p 1219 405 V 35 w(cuddBddArr)o(ayLoad)f +Fl(are)h(the)g(load)g(functions,)i(which)e(read)g(a)g(BDD)-189 +526 y(dump)24 b(\002le.)47 646 y(F)o(ollo)n(wing)34 b(the)h(store)h +(function,)h(the)f(main)f(BDD)h(load)f(function,)j Fc(Dddmp)p +2813 646 V 35 w(cuddBddLoad)p Fl(,)f(is)f(imple-)-189 +767 y(mented)g(by)g(calling)f(the)h(main)g(BDD-array)h(loading)f +(function)f Fc(Dddmp)p 2466 767 V 35 w(cuddBddArr)o(ayLoad)p +Fl(.)63 b(A)37 b(dynamic)-189 887 y(v)o(ector)24 b(of)h(DD)g(pointers)f +(is)g(temporarily)g(allocated)h(to)f(support)g(con)l(v)o(ersion)f(from) +i(DD)g(inde)o(x)o(es)e(to)h(pointers.)47 1007 y(Se)n(v)o(eral)40 +b(criteria)f(are)i(supported)d(for)i(v)n(ariable)f(match)g(between)g +(\002le)h(and)g(DD)f(manager)l(,)k(practically)-189 1128 +y(allo)n(wing)37 b(v)n(ariable)h(permutations)f(or)i(compositions)d +(while)i(loading)g(DDs.)71 b(V)-11 b(ariable)39 b(match)f(between)h +(the)-189 1248 y(DD)32 b(manager)g(and)g(the)g(BDD)g(\002le)g(is)g +(optionally)e(based)i(in)f Fc(IDs)p Fl(,)j Fc(perids)p +Fl(,)f Fc(varnames)p Fl(,)g Fc(var)o(auxids)p Fl(;)g(also)f(direct)-189 +1369 y(composition)j(between)j Fc(IDs)g Fl(and)f Fc(composeids)g +Fl(is)g(supported.)68 b(The)38 b Fc(varmatc)o(hmode)e +Fl(parameter)i(is)f(used)g(to)-189 1489 y(select)27 b(mathing)e(mode.) +37 b(More)27 b(in)f(detail,)h(tw)o(o)f(match)h(modes)f(use)h(the)f +(information)g(within)f(the)i(DD)g(manager)l(,)-189 1609 +y(the)e(other)f(ones)h(use)g(e)o(xtra)f(information,)f(which)i(support) +f(an)o(y)g(v)n(ariable)g(remap)h(or)g(change)g(in)f(the)h(ordering.)-44 +1813 y Fk(\017)49 b Fl(v)n(armatchnode=DDDMP)p 1040 1813 +V 35 w(V)-13 b(AR)p 1272 1813 V 35 w(MA)i(TCHIDS)19 b(allo)n(ws)f +(loading)g(a)h(DD)g(k)o(eeping)f(v)n(ariable)g(IDs)h(unchanged)55 +1933 y(\(re)o(gardless)24 b(of)h(the)f(v)n(ariable)h(ordering)f(of)h +(the)g(reading)f(manager)-5 b(.)55 2095 y(This)24 b(is)g(useful,)g(for) +h(e)o(xample,)f(when)g(sw)o(apping)g(DDs)g(to)h(\002le)g(and)f +(restoring)g(them)g(later)h(from)f(\002le,)h(after)55 +2215 y(possible)e(v)n(ariable)i(reordering)g(acti)n(v)n(ations.)-44 +2419 y Fk(\017)49 b Fl(v)n(armatchnode=DDDMP)p 1040 2419 +V 35 w(V)-13 b(AR)p 1272 2419 V 35 w(MA)i(TCHPERMIDS)36 +b(is)e(used)h(to)f(allo)n(w)g(v)n(ariable)g(match)h(according)55 +2539 y(to)h(the)h(position)e(in)i(the)g(ordering)f(\(retrie)n(v)o(ed)g +(by)h(array)h(of)f(permutations)e(stored)h(on)h(\002le)g(and)g(within) +55 2660 y(the)h(reading)g(DD)h(manager\).)72 b(A)38 b(possible)f +(application)h(is)g(retrie)n(ving)f(BDDs)i(stored)f(after)h(dynamic)55 +2780 y(reordering,)28 b(from)g(a)g(DD)g(manager)g(where)h(all)e(v)n +(ariable)h(IDs)f(map)h(their)f(position)g(in)g(the)h(ordering,)g(and)55 +2900 y(the)d(loaded)f(BDD)h(k)o(eeps)g(the)g(ordering)f(as)h(stored)f +(on)h(\002le.)-44 3104 y Fk(\017)49 b Fl(v)n(armatchnode=DDDMP)p +1040 3104 V 35 w(V)-13 b(AR)p 1272 3104 V 35 w(MA)i(TCHN)m(AMES)26 +b(requires)h(a)h(not)e(NULL)h(v)n(armatchmodes)f(param-)55 +3224 y(eter;)34 b(this)c(is)g(a)h(v)o(ector)g(of)g(strings)e(in)i +(one-to-one)f(correspondence)h(with)f(v)n(ariable)h(IDs)f(of)h(the)g +(reading)55 3344 y(manager)-5 b(.)40 b(V)-11 b(ariables)28 +b(in)g(the)g(DD)g(\002le)g(read)h(are)g(matched)f(with)f(manager)h(v)n +(ariables)f(according)h(to)g(their)55 3465 y(name)35 +b(\(a)h(not)f(NULL)g(v)n(arnames)g(parameter)h(w)o(as)f(required)h +(while)f(storing)f(the)h(DD)g(\002le\).)64 b(The)35 b(most)55 +3585 y(common)c(usage)h(of)g(this)f(feature)i(is)e(in)h(combination)e +(with)i(a)g(v)n(ariable)g(ordering)g(stored)f(on)h(a)g(\002le)h(and)55 +3706 y(based)28 b(on)h(v)n(ariables)f(names.)41 b(Names)29 +b(must)e(be)i(loaded)f(in)g(an)h(array)g(of)g(strings)e(and)i(passed)f +(to)g(the)h(DD)55 3826 y(load)24 b(procedure.)-44 4029 +y Fk(\017)49 b Fl(v)n(armatchnode=DDDMP)p 1040 4029 V +35 w(V)-13 b(AR)p 1272 4029 V 35 w(MA)i(TCHIDS)25 b(has)g(a)g(meaning)f +(similar)g(to)55 4150 y(DDDMP)p 421 4150 V 36 w(V)-13 +b(AR)p 654 4150 V 35 w(MA)i(TCHN)m(AMES)26 b(b)n(ut)h(inte)o(ger)f +(auxiliary)g(IDs)h(are)h(used)f(instead)f(of)h(strings.)36 +b(The)28 b(ad-)55 4270 y(ditional)23 b(not)h(NULL)h(v)n(armathauxids)e +(parameter)i(is)g(needed.)-44 4474 y Fk(\017)49 b Fl(v)n +(armatchnode=DDDMP)p 1040 4474 V 35 w(V)-13 b(AR)p 1272 +4474 V 35 w(COMPOSEIDS,)38 b(uses)f(the)f(additional)f(v)n +(arcomposeids)g(parameter)55 4594 y(as)25 b(an)g(array)g(of)g(v)n +(ariable)f(IDs)h(to)g(be)g(composed)f(with)g(IDs)g(stored)h(in)f +(\002le.)-189 4860 y Fi(2.2.3)99 b(DD)25 b(Load/Stor)n(e)h(and)f(V)-9 +b(ariable)25 b(Ordering)-189 5048 y Fl(Loading)31 b(of)i(Decision)e +(Diagrams)h(from)g(\002le)g(supports)f(dif)n(ferent)h(v)n(ariables)g +(ordering)f(strate)o(gies,)i(as)g(already)-189 5168 y(pointed)23 +b(out)h(in)g(the)h(pre)n(vious)e(section.)30 b(This)24 +b(allo)n(ws)f(or)h(e)o(xample)g(storing)f(dif)n(ferent)i(BDDs)f(each)h +(with)f(its)g(o)n(wn)-189 5288 y(v)n(ariable)29 b(ordering,)h(and)g(to) +f(mer)n(ge)h(them)f(within)f(the)i(same)f(DD)h(manager)f(by)h(means)f +(of)g(proper)h(load)f(opera-)-189 5409 y(tions.)44 b(W)-8 +b(e)30 b(suggest)f(using)f(DDDMP)p 1175 5409 V 36 w(V)-13 +b(AR)p 1408 5409 V 36 w(MA)i(TCHIDS)30 b(whene)n(v)o(er)f(IDs)g(k)o +(eeps)h(on)f(representing)h(the)f(same)-189 5529 y(entities)24 +b(while)h(changing)f(v)n(ariable)h(ordering.)31 b(If)25 +b(this)f(is)h(not)f(true,)h(v)n(ariable)g(names)g(\(if)g(a)n(v)n +(ailable\))f(or)i(auxiliary)1794 5800 y(6)p eop +%%Page: 7 7 +7 6 bop -189 218 a Fl(IDs)34 b(are)h(a)g(good)e(w)o(ay)i(to)f +(represent)g(in)l(v)n(ariant)f(attrib)n(uted)g(of)i(v)n(ariables)e +(across)h(se)n(v)o(eral)g(runs)g(with)f(dif)n(ferent)-189 +338 y(orderings.)50 b(DDDMP)p 629 338 30 4 v 35 w(V)-13 +b(AR)p 861 338 V 36 w(COMPOSEIDS)32 b(is)f(an)h(alternati)n(v)o(e)e +(solution,)h(that)g(practically)f(corresponds)h(to)-189 +459 y(cascading)23 b(DDDMP)p 593 459 V 36 w(V)-13 b(AR)p +826 459 V 36 w(MA)i(TCHIDS)23 b(and)h(v)n(ariable)f(composition)e(with) +h(a)i(gi)n(v)o(en)e(array)i(of)g(ne)n(w)f(v)n(ariables.)-189 +797 y Fo(3)143 b(CNF)35 b(Support)-189 1050 y Fj(3.1)119 +b(F)m(ormat)-189 1237 y Fl(Gi)n(v)o(en)30 b(a)h(BDD)g(representing)g(a) +g(function)f Fd(f)11 b Fl(,)32 b(we)f(de)n(v)o(elop)f(three)h(basic)g +(possible)e(w)o(ays)i(to)g(store)f(it)h(as)g(a)g(CNF)-189 +1358 y(formula.)54 b(In)33 b(each)h(method)d(the)i(set)g(of)f(clauses)h +(is)f(written)h(after)g(an)g(header)g(part.)55 b(Only)32 +b(the)h(te)o(xt)f(format)g(is)-189 1478 y(allo)n(wed.)-189 +1743 y Fi(3.1.1)99 b(Header)-189 1931 y Fl(The)23 b(header)h(part)f(of) +g(each)h(CNF)g(\002le)f(has)g(basically)g(the)f(same)h(format)g +(analyzed)g(for)h(the)f(BDD/ADD)g(\002les.)30 b(F)o(or)-189 +2051 y(e)o(xample)h(the)g Fg(.rootids)f Fl(line)h(indicates)f(the)i(be) +o(ginning)d(of)j(each)g(CNF)g(formula)f(represented)h(by)f(a)h(single) +-189 2172 y(BDD.)j(T)-8 b(o)34 b(be)g(compatible)f(with)h(the)g(DIMA)l +(CS)h(format)f(each)h(header)f(line)g(start)g(with)g(the)g(character)h +(\223c\224)g(to)-189 2292 y(indicate)24 b(a)h(comment.)-189 +2557 y Fi(3.1.2)99 b(T)-9 b(ext)25 b(F)n(ormat)-189 2745 +y Fl(The)j(\002rst)g(method,)g(which)f(we)h(call)g Fi(Single-Node-Cut)p +Fl(,)j(models)26 b(each)j(BDD)f(nodes,)h(b)n(ut)e(the)h(ones)f(with)h +(both)-189 2865 y(the)c(children)g(equal)h(to)f(the)g(constant)g(node)g +Fb(1)p Fl(,)g(as)h(a)g(multiple)o(x)o(er)-5 b(.)27 b(Each)e(multiple)o +(x)o(er)d(has)i(tw)o(o)g(data)h(inputs)e(\(i.e.,)-189 +2985 y(the)k(node)h(children\),)f(a)h(selection)f(input)f(\(i.e.,)i +(the)g(node)f(v)n(ariable\))g(and)h(one)f(output)f(\(i.e.,)i(the)g +(function)e(v)n(alue\))-189 3106 y(whose)h(v)n(alue)f(is)h(assigned)f +(to)h(an)g(additional)f(CNF)i(v)n(ariable.)37 b(The)27 +b(\002nal)h(number)e(of)h(v)n(ariables)g(is)f(equal)h(to)g(the)-189 +3226 y(number)d(of)h(original)f(BDD)h(v)n(ariables)f(plus)g(the)h +(number)f(of)h(\223internal\224)g(nodes)f(of)h(the)g(BDD.)47 +3346 y(The)k(second)f(method,)g(which)h(we)f(call)h Fi(Maxterm-Cut)p +Fl(,)h(create)g(clauses)e(starting)g(from)g Fd(f)39 b +Fl(corresponds)-189 3467 y(to)25 b(the)h(of)n(f-set)g(\(i.e.,)f(all)h +(the)g(paths-cubes)f(from)g(the)h(root)g(node)f(to)h(the)f(terminal)g +Fg(0)p Fl(\))h(of)g(the)g(function)e Fd(f)11 b Fl(.)34 +b(W)l(ithin)-189 3587 y(the)29 b(BDD)g(for)g Fd(f)11 +b Fl(,)30 b(such)f(clauses)f(are)i(found)e(by)h(follo)n(wing)e(all)i +(the)f(paths)h(from)f(the)h(root)g(node)f(of)h(the)g(BDD)g(to)-189 +3708 y(the)c(constant)f(node)g Fb(0)p Fl(.)31 b(The)25 +b(\002nal)g(number)f(of)h(v)n(ariables)f(is)g(equal)h(to)f(the)h +(number)f(of)h(original)f(BDD)h(v)n(ariables.)47 3828 +y(The)k(third)g(method,)g(which)g(we)g(call)g Fi(A)-5 +b(uxiliary-V)c(ariable-Cut)p Fl(,)30 b(is)f(a)h(trade-of)n(f)f(between) +g(the)g(\002rst)g(tw)o(o)-189 3948 y(strate)o(gies.)69 +b(Internal)37 b(v)n(ariables,)j(i.e.,)h(cutting)c(points,)j(are)e +(added)g(in)f(order)h(to)g(decompose)f(the)h(BDD)g(into)-189 +4069 y(multiple)27 b(sub-trees)i(each)h(of)f(which)f(is)h(stored)g +(follo)n(wing)e(the)h(second)h(strate)o(gy)-6 b(.)42 +b(The)29 b(trade-of)n(f)g(is)g(guided)f(by)-189 4189 +y(the)23 b(cutting)f(point)g(selection)g(strate)o(gy)-6 +b(,)22 b(and)h(we)g(e)o(xperiment)f(with)g(tw)o(o)g(methodologies.)28 +b(In)23 b(the)g(\002rst)g(method,)g(a)-189 4310 y(ne)n(w)f(CNF)h(v)n +(ariable)f(is)f(inserted)h(in)g(correspondence)g(to)g(the)g(shared)g +(nodes)g(of)g(the)h(BDD,)f(i.e.,)h(the)f(nodes)f(which)-189 +4430 y(ha)n(v)o(e)29 b(more)g(than)h(one)f(incoming)f(edge.)45 +b(This)29 b(technique,)h(albeit)e(optimizing)g(the)h(number)g(of)h +(literals)e(stored,)-189 4550 y(can)35 b(produce)g(clauses)f(with)g(a)h +(high)f(number)h(of)f(literals)1894 4514 y Fh(2)1933 +4550 y Fl(.)60 b(T)-8 b(o)35 b(a)n(v)n(oid)f(this)g(dra)o(wback,)j(the) +e(second)f(method,)-189 4671 y(introduces)28 b(all)g(the)g(pre)n +(viously)e(indicated)i(cutting)f(points)g(more)h(the)h(ones)f +(necessary)g(to)g(break)h(the)f(length)g(of)-189 4791 +y(the)d(path)f(to)h(a)g(maximum)e(\(user\))i(selected)g(v)n(alue.)47 +4911 y(Actually)-6 b(,)37 b(all)f(the)f(methods)g(described)h(abo)o(v)o +(e)e(can)j(be)e(re-conducted)h(to)g(the)f(basic)h(idea)g(of)g(possibly) +-189 5032 y(breaking)24 b(the)h(BDD)g(through)f(the)g(use)h(of)f +(additional)g(cutting)f(v)n(ariables)h(and)h(dumping)e(the)h(paths)g +(between)h(the)-189 5152 y(root)34 b(of)h(the)f(BDD,)h(the)g(cutting)e +(v)n(ariables)h(and)g(the)h(terminal)e(nodes.)60 b(Such)35 +b(internal)f(cutting)f(v)n(ariables)h(are)-189 5273 y(added)25 +b(al)o(w)o(ays)f(\(for)i(each)f(node\),)g(ne)n(v)o(er)f(or)h(sometimes) +e(respecti)n(v)o(ely)-6 b(.)p -189 5360 1607 4 v -77 +5422 a Ff(2)-40 5452 y Fe(This)27 b(v)n(alue)f(is)i(superiorly)d +(limited)h(by)g(the)h(number)e(of)h(v)n(ariables)g(of)g(the)h(BDD,)g +(i.e.,)h(the)f(longest)f(path)g(from)g(the)h(root)f(to)g(the)-189 +5551 y(terminal)19 b(node.)1794 5800 y Fl(7)p eop +%%Page: 8 8 +8 7 bop 47 218 a Fl(While)33 b(the)f Fc(Single-Node-Cut)h +Fl(method)f(minimizes)f(the)i(length)f(of)h(the)f(clauses)h(produced,)i +(b)n(ut)d(it)g(also)-189 338 y(requires)d(the)h(higher)f(number)g(of)g +(CNF)i(v)n(ariables,)e(the)h Fc(Maxterm-Cut)f Fl(technique)g(minimizes) +f(the)h(number)g(of)-189 459 y(CNF)36 b(v)n(ariables)d(required.)61 +b(This)34 b(adv)n(antage)g(is)g(counter)n(-balanced)h(by)f(the)h(f)o +(act)g(that)f(in)g(the)h(w)o(orst)f(case)h(the)-189 579 +y(number)23 b(of)g(clauses,)g(as)h(well)e(as)i(the)f(total)f(number)h +(of)g(literals,)g(produced)g(is)g(e)o(xponential)e(in)i(the)g(BDD)h +(size)f(\(in)-189 699 y(terms)28 b(of)i(number)e(of)h(nodes\).)43 +b(The)29 b(application)f(of)h(this)f(method)g(is)g(then)h(limited)e(to) +i(the)g(cases)g(in)f(which)h(the)-189 820 y(\223of)n(f-set\224)c(of)f +(the)g(represented)h(function)f Fd(f)35 b Fl(has)24 b(a)h(small)f +(cardinality)-6 b(.)29 b(The)c Fc(A)n(uxiliary-V)-11 +b(ariable-Cut)22 b Fl(strate)o(gy)h(is)-189 940 y(a)k(trade-of)n(f)h +(between)f(the)g(\002rst)g(tw)o(o)g(methods)f(and)h(the)g(ones)f(which) +h(gi)n(v)o(es)f(more)h(compact)f(results.)37 b(As)27 +b(a)h(\002nal)-189 1061 y(remark)f(notice)e(that)h(the)g(method)g(is)f +(able)i(to)f(store)g(both)f(monolithic)f(BDDs)j(and)f(conjuncti)n(v)o +(e)e(forms.)35 b(In)26 b(each)-189 1181 y(case)f(we)g(generate)h(CNF)f +(\002les)g(using)f(the)h(standard)f(DIMA)l(CS)i(format.)-189 +1365 y Fi(Example)f(1)49 b Fc(F)l(igur)l(e)20 b(1)h(shows)f(an)h(e)n +(xample)g(of)f(how)h(our)f(pr)l(ocedur)l(e)h(works)f(to)h(stor)l(e)f(a) +h(small)f(monolithic)f(BDD.)-189 1486 y(F)l(igur)l(e)j(1\(a\))h(r)l +(epr)l(esents)g(a)g(BDD)g(with)g Fb(4)g Fc(nodes.)30 +b(BDD)23 b(variables)f(ar)l(e)h(named)g(after)f(inte)l(g)o(er)g(number) +o(s)h(r)o(anging)-189 1606 y(fr)l(om)k Fb(1)h Fc(to)g +Fb(4)p Fc(,)h(to)f(have)g(an)g(easy-to-follow)f(corr)l(espondence)h +(with)g(the)g(CNF)h(variables.)40 b(F)l(igur)l(e)27 b(1\(b\),)i(\(c\))g +(and)-189 1727 y(\(d\))c(show)g(the)f(corr)l(esponding)f(CNF)j(r)l(epr) +l(esentations)d(g)o(ener)o(ated)h(by)h(our)f(thr)l(ee)h(methods.)30 +b(As)24 b(in)h(the)f(standar)l(d)-189 1847 y(format)i +Fa(p)i Fc(indicates)e(the)h(total)f(number)g(of)h(variables)f(used)h +(\()p Fb(4)g Fc(is)g(the)g(minimum)f(value)h(as)g(the)g(BDD)g(itself)f +(has)-189 1967 y Fb(4)f Fc(variables\),)e(and)i Fa(cnf)g +Fc(the)f(total)g(number)g(of)h(clauses.)47 2088 y(As)i(a)g(\002nal)f(r) +l(emark)h(notice)f(that)g(for)g(this)g(speci\002c)h(e)n(xample)g(the)f +(\223Maxterm-Cut\224)i(appr)l(oac)o(h)d(is)h(the)h(one)-189 +2208 y(whic)o(h)36 b(gives)g(the)g(most)f(compact)h(CNF)h(r)l(epr)l +(esentation)e(b)n(ut)h(also)f(the)h(clause)g(with)g(the)g(lar)l(g)o +(est)g(number)f(of)-189 2328 y(liter)o(als)23 b(\()p +Fb(4)p Fc(\).)188 2471 y + 6339814 10777681 0 0 11709153 19997655 startTexFig + 188 2471 a +%%BeginDocument: bdd.eps +%!PS-Adobe-2.0 EPSF-2.0 +%%Title: bdd.eps +%%Creator: fig2dev Version 3.2 Patchlevel 3c +%%CreationDate: Mon Sep 9 14:21:26 2002 +%%For: quer@pcsq (Stefano Quer) +%%BoundingBox: 0 0 178 304 +%%Magnification: 1.0000 +%%EndComments +/$F2psDict 200 dict def +$F2psDict begin +$F2psDict /mtrx matrix put +/col-1 {0 setgray} bind def +/col0 {0.000 0.000 0.000 srgb} bind def +/col1 {0.000 0.000 1.000 srgb} bind def +/col2 {0.000 1.000 0.000 srgb} bind def +/col3 {0.000 1.000 1.000 srgb} bind def +/col4 {1.000 0.000 0.000 srgb} bind def +/col5 {1.000 0.000 1.000 srgb} bind def +/col6 {1.000 1.000 0.000 srgb} bind def +/col7 {1.000 1.000 1.000 srgb} bind def +/col8 {0.000 0.000 0.560 srgb} bind def +/col9 {0.000 0.000 0.690 srgb} bind def +/col10 {0.000 0.000 0.820 srgb} bind def +/col11 {0.530 0.810 1.000 srgb} bind def +/col12 {0.000 0.560 0.000 srgb} bind def +/col13 {0.000 0.690 0.000 srgb} bind def +/col14 {0.000 0.820 0.000 srgb} bind def +/col15 {0.000 0.560 0.560 srgb} bind def +/col16 {0.000 0.690 0.690 srgb} bind def +/col17 {0.000 0.820 0.820 srgb} bind def +/col18 {0.560 0.000 0.000 srgb} bind def +/col19 {0.690 0.000 0.000 srgb} bind def +/col20 {0.820 0.000 0.000 srgb} bind def +/col21 {0.560 0.000 0.560 srgb} bind def +/col22 {0.690 0.000 0.690 srgb} bind def +/col23 {0.820 0.000 0.820 srgb} bind def +/col24 {0.500 0.190 0.000 srgb} bind def +/col25 {0.630 0.250 0.000 srgb} bind def +/col26 {0.750 0.380 0.000 srgb} bind def +/col27 {1.000 0.500 0.500 srgb} bind def +/col28 {1.000 0.630 0.630 srgb} bind def +/col29 {1.000 0.750 0.750 srgb} bind def +/col30 {1.000 0.880 0.880 srgb} bind def +/col31 {1.000 0.840 0.000 srgb} bind def + +end +save +newpath 0 304 moveto 0 0 lineto 178 0 lineto 178 304 lineto closepath clip newpath +-51.0 319.0 translate +1 -1 scale + +/cp {closepath} bind def +/ef {eofill} bind def +/gr {grestore} bind def +/gs {gsave} bind def +/sa {save} bind def +/rs {restore} bind def +/l {lineto} bind def +/m {moveto} bind def +/rm {rmoveto} bind def +/n {newpath} bind def +/s {stroke} bind def +/sh {show} bind def +/slc {setlinecap} bind def +/slj {setlinejoin} bind def +/slw {setlinewidth} bind def +/srgb {setrgbcolor} bind def +/rot {rotate} bind def +/sc {scale} bind def +/sd {setdash} bind def +/ff {findfont} bind def +/sf {setfont} bind def +/scf {scalefont} bind def +/sw {stringwidth} bind def +/tr {translate} bind def +/tnt {dup dup currentrgbcolor + 4 -2 roll dup 1 exch sub 3 -1 roll mul add + 4 -2 roll dup 1 exch sub 3 -1 roll mul add + 4 -2 roll dup 1 exch sub 3 -1 roll mul add srgb} + bind def +/shd {dup dup currentrgbcolor 4 -2 roll mul 4 -2 roll mul + 4 -2 roll mul srgb} bind def + /DrawEllipse { + /endangle exch def + /startangle exch def + /yrad exch def + /xrad exch def + /y exch def + /x exch def + /savematrix mtrx currentmatrix def + x y tr xrad yrad sc 0 0 1 startangle endangle arc + closepath + savematrix setmatrix + } def + +/$F2psBegin {$F2psDict begin /$F2psEnteredState save def} def +/$F2psEnd {$F2psEnteredState restore end} def + +$F2psBegin +%%Page: 1 1 +10 setmiterlimit + 0.06299 0.06299 sc +% +% Fig objects follow +% +% Polyline +15.000 slw +n 2010 4515 m 2550 4515 l 2550 5040 l 2010 5040 l + cp gs col0 s gr +/Times-Roman ff 300.00 scf sf +2205 4875 m +gs 1 -1 sc (1) col0 sh gr +% Ellipse +n 1515 1800 270 270 0 360 DrawEllipse gs col0 s gr + +% Ellipse +n 2250 900 270 270 0 360 DrawEllipse gs col0 s gr + +% Ellipse +n 2970 2715 270 270 0 360 DrawEllipse gs col0 s gr + +% Ellipse +n 2280 3705 270 270 0 360 DrawEllipse gs col0 s gr + +7.500 slw +% Ellipse +n 3555 3555 64 64 0 360 DrawEllipse gs 0.00 setgray ef gr gs col0 s gr + +% Ellipse +n 2712 1726 64 64 0 360 DrawEllipse gs 0.00 setgray ef gr gs col0 s gr + +% Ellipse +n 2430 4230 64 64 0 360 DrawEllipse gs 0.00 setgray ef gr gs col0 s gr + +% Polyline +15.000 slw +n 2805 2910 m + 2250 3450 l gs col0 s gr +% Polyline + [90] 0 sd +gs clippath +2940 2472 m 3010 2445 l 2931 2239 l 2957 2411 l 2861 2266 l cp +eoclip +n 2460 1110 m + 2970 2445 l gs col0 s gr gr + [] 0 sd +% arrowhead +n 2861 2266 m 2957 2411 l 2931 2239 l 2908 2284 l 2861 2266 l + cp gs 0.00 setgray ef gr col0 s +% Polyline +gs clippath +1478 1511 m 1528 1568 l 1693 1422 l 1542 1506 l 1643 1366 l cp +eoclip +n 2025 1080 m + 1515 1530 l gs col0 s gr gr + +% arrowhead +n 1643 1366 m 1542 1506 l 1693 1422 l 1643 1416 l 1643 1366 l + cp gs 0.00 setgray ef gr col0 s +% Polyline +gs clippath +2212 645 m 2287 645 l 2287 425 l 2250 594 l 2212 425 l cp +eoclip +n 2250 270 m + 2250 630 l gs col0 s gr gr + +% arrowhead +n 2212 425 m 2250 594 l 2287 425 l 2250 459 l 2212 425 l + cp gs 0.00 setgray ef gr col0 s +% Polyline + [90] 0 sd +gs clippath +2692 2664 m 2732 2601 l 2546 2485 l 2670 2606 l 2506 2548 l cp +eoclip +n 1710 2010 m + 2700 2625 l gs col0 s gr gr + [] 0 sd +% arrowhead +n 2506 2548 m 2670 2606 l 2546 2485 l 2555 2534 l 2506 2548 l + cp gs 0.00 setgray ef gr col0 s +% Polyline +2 slj + [90] 0 sd +gs clippath +2504 4653 m 2539 4720 l 2733 4616 l 2567 4663 l 2698 4550 l cp +eoclip +n 3180 2910 m 3181 2911 l 3183 2913 l 3186 2916 l 3192 2921 l 3200 2929 l + 3210 2939 l 3223 2951 l 3238 2966 l 3255 2984 l 3274 3003 l + 3295 3025 l 3317 3049 l 3339 3075 l 3362 3103 l 3385 3131 l + 3407 3161 l 3429 3192 l 3450 3225 l 3470 3258 l 3488 3293 l + 3504 3329 l 3519 3367 l 3531 3406 l 3541 3447 l 3548 3490 l + 3552 3536 l 3552 3583 l 3548 3634 l 3540 3686 l 3528 3740 l + 3510 3795 l 3490 3844 l 3467 3892 l 3441 3939 l 3413 3985 l + 3382 4028 l 3350 4070 l 3317 4110 l 3283 4148 l 3248 4184 l + 3211 4219 l 3174 4253 l 3136 4285 l 3098 4316 l 3059 4347 l + 3020 4376 l 2980 4405 l 2941 4432 l 2901 4459 l 2862 4484 l + 2824 4509 l 2787 4532 l 2751 4554 l 2717 4575 l 2686 4593 l + 2657 4610 l 2631 4626 l 2608 4639 l 2589 4650 l 2572 4659 l + 2559 4666 l 2550 4672 l + 2535 4680 l gs col0 s gr gr + [] 0 sd +% arrowhead +0 slj +n 2698 4550 m 2567 4663 l 2733 4616 l 2686 4599 l 2698 4550 l + cp gs 0.00 setgray ef gr col0 s +% Polyline +2 slj +gs clippath +1985 4734 m 2028 4672 l 1847 4548 l 1965 4675 l 1804 4609 l cp +eoclip +n 1350 2025 m 1349 2026 l 1348 2027 l 1345 2030 l 1340 2035 l 1334 2042 l + 1325 2051 l 1314 2063 l 1301 2078 l 1286 2095 l 1268 2114 l + 1249 2137 l 1227 2161 l 1205 2188 l 1181 2218 l 1156 2249 l + 1131 2282 l 1105 2316 l 1080 2352 l 1054 2390 l 1029 2428 l + 1005 2468 l 981 2509 l 959 2552 l 938 2595 l 918 2640 l + 900 2687 l 884 2736 l 870 2786 l 858 2839 l 848 2894 l + 841 2951 l 837 3011 l 836 3074 l 838 3139 l 845 3206 l + 855 3275 l 870 3345 l 888 3412 l 910 3477 l 934 3542 l + 961 3604 l 990 3665 l 1022 3723 l 1054 3779 l 1088 3833 l + 1124 3885 l 1160 3935 l 1198 3983 l 1236 4029 l 1275 4074 l + 1315 4118 l 1356 4160 l 1397 4201 l 1438 4241 l 1480 4280 l + 1522 4318 l 1563 4355 l 1605 4390 l 1645 4424 l 1685 4457 l + 1723 4488 l 1760 4517 l 1795 4545 l 1827 4570 l 1857 4593 l + 1884 4613 l 1909 4632 l 1930 4647 l 1947 4660 l 1962 4671 l + 1973 4679 l 1982 4686 l + 1995 4695 l gs col0 s gr gr + +% arrowhead +0 slj +n 1804 4609 m 1965 4675 l 1847 4548 l 1854 4598 l 1804 4609 l + cp gs 0.00 setgray ef gr col0 s +% Polyline +2 slj + [90] 0 sd +gs clippath +2300 4492 m 2363 4532 l 2481 4347 l 2359 4470 l 2417 4307 l cp +eoclip +n 2340 3960 m 2341 3962 l 2344 3966 l 2348 3973 l 2354 3982 l 2362 3995 l + 2370 4010 l 2379 4028 l 2389 4046 l 2397 4066 l 2406 4088 l + 2413 4111 l 2420 4137 l 2425 4165 l 2429 4197 l 2430 4230 l + 2429 4263 l 2425 4295 l 2420 4323 l 2413 4349 l 2406 4372 l + 2397 4394 l 2389 4414 l 2379 4433 l 2370 4450 l 2362 4465 l + 2354 4478 l + 2340 4500 l gs col0 s gr gr + [] 0 sd +% arrowhead +0 slj +n 2417 4307 m 2359 4470 l 2481 4347 l 2431 4356 l 2417 4307 l + cp gs 0.00 setgray ef gr col0 s +% Polyline +2 slj +gs clippath +2136 4532 m 2199 4492 l 2082 4307 l 2141 4470 l 2018 4347 l cp +eoclip +n 2160 3960 m 2159 3962 l 2156 3966 l 2152 3973 l 2146 3982 l 2138 3995 l + 2130 4010 l 2121 4028 l 2111 4046 l 2103 4066 l 2094 4088 l + 2087 4111 l 2080 4137 l 2075 4165 l 2071 4197 l 2070 4230 l + 2071 4263 l 2075 4295 l 2080 4323 l 2087 4349 l 2094 4372 l + 2103 4394 l 2111 4414 l 2121 4433 l 2130 4450 l 2138 4465 l + 2146 4478 l + 2160 4500 l gs col0 s gr gr + +% arrowhead +0 slj +n 2018 4347 m 2141 4470 l 2082 4307 l 2068 4356 l 2018 4347 l + cp gs 0.00 setgray ef gr col0 s +/Times-Roman ff 300.00 scf sf +2175 990 m +gs 1 -1 sc (1) col0 sh gr +/Times-Roman ff 300.00 scf sf +1440 1890 m +gs 1 -1 sc (2) col0 sh gr +/Times-Roman ff 300.00 scf sf +2895 2805 m +gs 1 -1 sc (3) col0 sh gr +/Times-Roman ff 300.00 scf sf +2205 3795 m +gs 1 -1 sc (4) col0 sh gr +$F2psEnd +rs + +%%EndDocument + + endTexFig + 531 3990 a Fc(\(a\))1512 2504 y Fg(p)60 b(cnf)f(7)g(11)1512 +2624 y(-5)g(3)h(0)1512 2745 y(-5)f(4)h(0)1512 2865 y(5)g(-3)f(-4)g(0) +1512 2985 y(6)h(-2)f(0)1512 3106 y(6)h(-5)f(0)1512 3226 +y(-6)g(2)h(5)f(0)1512 3347 y(7)h(1)f(5)h(0)1512 3467 +y(-7)f(1)h(-5)f(0)1512 3587 y(7)h(-1)f(-6)g(0)1512 3708 +y(-7)g(-1)h(6)f(0)1512 3828 y(7)h(0)1836 3990 y Fc(\(b\))2541 +2525 y Fg(p)f(cnf)g(4)h(3)2541 2645 y(1)f(-3)h(-4)f(0)2541 +2766 y(-1)g(2)h(3)f(0)2541 2886 y(-1)g(2)h(-3)f(4)h(0)2868 +3048 y Fc(\(c\))2541 3251 y Fg(p)f(cnf)g(5)h(5)2541 3371 +y(-5)f(1)h(0)2541 3492 y(5)f(-1)h(2)f(0)2541 3612 y(-3)g(-4)g(5)h(0) +2541 3733 y(3)f(-5)h(0)2541 3853 y(-3)f(4)h(-5)f(0)2865 +3990 y Fc(\(d\))-189 4138 y Fl(Figure)46 b(1:)71 b(\(a\))47 +b(BDD;)e(\(b\))h(\223Single-Node-Cut\224)g(format;)55 +b(\(c\))46 b(\223Maxterm-Cut\224)g(format;)55 b(\(d\))45 +b(\223)-8 b(Auxiliary-)-189 4258 y(V)d(ariable-Cut\224)25 +b(F)o(ormat.)-189 4625 y Fj(3.2)119 b(Implementation)-189 +4813 y Fl(Store)25 b(and)g(Load)g(for)g(a)g(single)f(BDD)h(or)g(a)g +(forest)g(of)g(BDDs)g(is)f(currently)h(implemented.)-189 +5073 y Fi(3.2.1)99 b(Storing)25 b(Decision)g(Diagrams)f(as)g(CNF)h(F)n +(ormulas)-189 5260 y Fl(As)g(f)o(ar)g(as)g(the)g(storing)e(process)i +(is)f(concerned)i(three)f(possible)e(formats)h(are)i(a)n(v)n(ailable:) +-44 5431 y Fk(\017)49 b Fl(DDDMP)p 421 5431 30 4 v 36 +w(CNF)p 650 5431 V 36 w(MODE)p 980 5431 V 35 w(NODE:)21 +b(store)f(a)h(BDD)h(by)e(introducing)f(an)i(auxiliary)g(v)n(ariable)f +(for)h(each)g(BDD)55 5551 y(node)1794 5800 y(8)p eop +%%Page: 9 9 +9 8 bop -44 218 a Fk(\017)49 b Fl(DDDMP)p 421 218 30 +4 v 36 w(CNF)p 650 218 V 36 w(MODE)p 980 218 V 35 w(MAXTERM:)20 +b(store)g(a)h(BDD)h(by)e(follo)n(wing)f(the)h(maxterm)g(of)h(the)g +(represented)55 338 y(function)-44 542 y Fk(\017)49 b +Fl(DDDMP)p 421 542 V 36 w(CNF)p 650 542 V 36 w(MODE)p +980 542 V 35 w(BEST)-5 b(:)32 b(trade-of)f(between)h(the)f(tw)o(o)f +(pre)n(vious)g(solution,)h(trying)f(to)h(optimize)55 +662 y(the)25 b(number)f(of)h(literals)f(stored.)-189 +865 y(See)c(procedures)f(Dddmp)p 736 865 V 35 w(cuddBddStoreCnf)g(\(to) +g(store)f(a)h(single)f(BDD)i(as)e(a)i(CNF)f(formula\))g(and)g(Dddmp)p +3609 865 V 34 w(cuddBddArrayStoreCnf)-189 986 y(\(to)25 +b(store)f(an)h(array)h(of)f(BDDs)g(as)f(a)i(CNF)f(formula\).)-189 +1252 y Fi(3.2.2)99 b(Loadinf)26 b(CNF)e(F)n(ormulas)g(as)h(BDDs)-189 +1439 y Fl(As)g(f)o(ar)g(as)g(the)g(loading)e(process)i(is)f(concerned)i +(three)f(possible)e(formats)i(are)g(a)n(v)n(ailable:)-44 +1643 y Fk(\017)49 b Fl(DDDMP)p 421 1643 V 36 w(CNF)p +650 1643 V 36 w(MODE)p 980 1643 V 35 w(NO)p 1159 1643 +V 36 w(CONJ:)25 b(Return)g(the)f(Clauses)h(without)f(Conjunction)-44 +1846 y Fk(\017)49 b Fl(DDDMP)p 421 1846 V 36 w(CNF)p +650 1846 V 36 w(MODE)p 980 1846 V 35 w(NO)p 1159 1846 +V 36 w(Q)o(U)l(ANT)-5 b(:)24 b(Return)h(the)g(sets)f(of)h(BDDs)g +(without)f(Quanti\002cation)-44 2050 y Fk(\017)49 b Fl(DDDMP)p +421 2050 V 36 w(CNF)p 650 2050 V 36 w(MODE)p 980 2050 +V 35 w(CONJ)p 1264 2050 V 36 w(Q)o(U)l(ANT)-5 b(:)23 +b(Return)h(the)g(sets)f(of)h(BDDs)g(AFTER)g(Existential)e(Quanti\002-) +55 2170 y(cation)-189 2373 y(See)e(procedures)f(Dddmp)p +736 2373 V 35 w(cuddBddLoadCnf)f(\(to)h(load)f(a)i(CNF)f(formula)g(as)g +(a)g(single)f(BDD\))h(and)g(Dddmp)p 3581 2373 V 35 w +(cuddBddArrayLoadCnf)-189 2494 y(\(to)35 b(load)h(a)g(CNF)g(formula)f +(as)h(an)g(array)g(of)g(BDDs\).)63 b(See)36 b(also)g(Dddmp)p +2485 2494 V 34 w(cuddHeaderLoadCnf)h(to)e(load)g(the)-189 +2614 y(header)25 b(of)g(a)g(CNF)h(\002le)f(to)g(gather)f(information)f +(on)i(the)g(sa)n(v)o(ed)f(structure.)-189 2954 y Fo(4)143 +b(T)-13 b(est)35 b(Pr)m(ogram)f(and)h(Regr)m(ession)f(T)-13 +b(ests)-189 3177 y Fl(The)20 b Fc(testddmp.c)e Fl(\002le,)j(pro)o +(vided)d(with)h(this)f(distrib)n(ution,)g(e)o(x)o(empli\002es)g(some)h +(of)h(the)f(abo)o(v)o(e)g(features.)29 b(Moreo)o(v)o(er)l(,)-189 +3298 y(in)d(the)h Fc(e)n(xp)g Fl(e)o(xperiments)e(a)j(fe)n(w)e +(scripts,)h(named)f Fc(test\241n\277.script)f Fl(are)i(a)n(v)n(ailable) +f(for)h(a)g(sanity)f(check)h(of)g(the)g(tool)-189 3418 +y(and)e(to)f(tak)o(e)h(a)g(look)f(at)h(some)f(runs)h(e)o(x)o +(empli\002cation.)-189 3758 y Fo(5)143 b(Documentation)-189 +3981 y Fl(F)o(or)27 b(further)f(documentation)f(on)i(the)f(package)h +(see)g(the)g(on-line)f(documentation)f(automatically)g(created)i(from) +-189 4102 y(the)e(source)g(code)g(\002les.)-189 4441 +y Fo(6)143 b(Ackno)o(wledgments)-189 4665 y Fl(W)-8 b(e)19 +b(are)h(particular)f(indebted)f(with)g(F)o(abio)g(Somenzi,)i(for)f +(discussions,)f(advice,)i(and)f(for)g(including)e(the)i(DDDMP)-189 +4785 y(package)28 b(into)f(the)h(CUDD)g(distrib)n(ution.)37 +b(W)-8 b(e)29 b(also)e(thank)g(all)h(the)g(user)g(of)g(the)f(package)i +(for)f(their)f(useful)h(indi-)-189 4905 y(cation)c(and)h(comments)f(on) +g(the)h(it.)1794 5800 y(9)p eop +%%Page: 10 10 +10 9 bop -189 218 a Fo(7)143 b(FTP)35 b(Site)-189 441 +y Fl(The)25 b(package)g(is)f(singularly)g(a)n(v)n(ailable)g(from:)-189 +645 y Fg(site:)59 b(ftp.polito.it)-189 765 y(user:)g(anonymous)-189 +885 y(directory:)f(/pub/research/dddmp)-189 1089 y Fl(or)25 +b(directly)f(from)h(the)f(author)h(WEB)g(pages:)-189 +1292 y Fg(WWW:)59 b(http://www.polito.it/\230{cabodi)o(,quer)o(})-189 +1632 y Fo(8)143 b(F)l(eedback)-189 1855 y Fl(Send)25 +b(feedback)h(to:)-189 2059 y Fg(Gianpiero)58 b(Cabodi)g(&)i(Stefano)e +(Quer)-189 2179 y(Politecnico)f(di)j(Torino)-189 2300 +y(Dipartimento)d(di)i(Automatica)f(e)i(Informatica)-189 +2420 y(Corso)f(Duca)g(degli)f(Abruzzi,)g(24)-189 2540 +y(I-10129)g(Torino)-189 2661 y(Italy)-189 2781 y(E-mail:)g +({cabodi,quer}@polito.it)-189 2901 y(WWW:)h +(http://www.polito.it/\230{cabodi)o(,quer)o(})1769 5800 +y Fl(10)p eop +%%Trailer +end +userdict /end-hook known{end-hook}if +%%EOF diff --git a/distr/dddmp/doc/dddmp-2.0-Letter.ps b/distr/dddmp/doc/dddmp-2.0-Letter.ps new file mode 100644 index 0000000..ad51df7 --- /dev/null +++ b/distr/dddmp/doc/dddmp-2.0-Letter.ps @@ -0,0 +1,1260 @@ +%!PS-Adobe-2.0 +%%Creator: dvips(k) 5.86 Copyright 1999 Radical Eye Software +%%Title: dddmp-2.0.dvi +%%Pages: 10 +%%PageOrder: Ascend +%%BoundingBox: 0 0 612 792 +%%DocumentFonts: Times-Bold Times-Roman Courier Times-Italic Helvetica +%%EndComments +%DVIPSWebPage: (www.radicaleye.com) +%DVIPSCommandLine: dvips -t letter -f dddmp-2.0 +%DVIPSParameters: dpi=600, compressed +%DVIPSSource: TeX output 2002.12.11:0557 +%%BeginProcSet: texc.pro +%! +/TeXDict 300 dict def TeXDict begin/N{def}def/B{bind def}N/S{exch}N/X{S +N}B/A{dup}B/TR{translate}N/isls false N/vsize 11 72 mul N/hsize 8.5 72 +mul N/landplus90{false}def/@rigin{isls{[0 landplus90{1 -1}{-1 1}ifelse 0 +0 0]concat}if 72 Resolution div 72 VResolution div neg scale isls{ +landplus90{VResolution 72 div vsize mul 0 exch}{Resolution -72 div hsize +mul 0}ifelse TR}if Resolution VResolution vsize -72 div 1 add mul TR[ +matrix currentmatrix{A A round sub abs 0.00001 lt{round}if}forall round +exch round exch]setmatrix}N/@landscape{/isls true N}B/@manualfeed{ +statusdict/manualfeed true put}B/@copies{/#copies X}B/FMat[1 0 0 -1 0 0] +N/FBB[0 0 0 0]N/nn 0 N/IEn 0 N/ctr 0 N/df-tail{/nn 8 dict N nn begin +/FontType 3 N/FontMatrix fntrx N/FontBBox FBB N string/base X array +/BitMaps X/BuildChar{CharBuilder}N/Encoding IEn N end A{/foo setfont}2 +array copy cvx N load 0 nn put/ctr 0 N[}B/sf 0 N/df{/sf 1 N/fntrx FMat N +df-tail}B/dfs{div/sf X/fntrx[sf 0 0 sf neg 0 0]N df-tail}B/E{pop nn A +definefont setfont}B/Cw{Cd A length 5 sub get}B/Ch{Cd A length 4 sub get +}B/Cx{128 Cd A length 3 sub get sub}B/Cy{Cd A length 2 sub get 127 sub} +B/Cdx{Cd A length 1 sub get}B/Ci{Cd A type/stringtype ne{ctr get/ctr ctr +1 add N}if}B/id 0 N/rw 0 N/rc 0 N/gp 0 N/cp 0 N/G 0 N/CharBuilder{save 3 +1 roll S A/base get 2 index get S/BitMaps get S get/Cd X pop/ctr 0 N Cdx +0 Cx Cy Ch sub Cx Cw add Cy setcachedevice Cw Ch true[1 0 0 -1 -.1 Cx +sub Cy .1 sub]/id Ci N/rw Cw 7 add 8 idiv string N/rc 0 N/gp 0 N/cp 0 N{ +rc 0 ne{rc 1 sub/rc X rw}{G}ifelse}imagemask restore}B/G{{id gp get/gp +gp 1 add N A 18 mod S 18 idiv pl S get exec}loop}B/adv{cp add/cp X}B +/chg{rw cp id gp 4 index getinterval putinterval A gp add/gp X adv}B/nd{ +/cp 0 N rw exit}B/lsh{rw cp 2 copy get A 0 eq{pop 1}{A 255 eq{pop 254}{ +A A add 255 and S 1 and or}ifelse}ifelse put 1 adv}B/rsh{rw cp 2 copy +get A 0 eq{pop 128}{A 255 eq{pop 127}{A 2 idiv S 128 and or}ifelse} +ifelse put 1 adv}B/clr{rw cp 2 index string putinterval adv}B/set{rw cp +fillstr 0 4 index getinterval putinterval adv}B/fillstr 18 string 0 1 17 +{2 copy 255 put pop}for N/pl[{adv 1 chg}{adv 1 chg nd}{1 add chg}{1 add +chg nd}{adv lsh}{adv lsh nd}{adv rsh}{adv rsh nd}{1 add adv}{/rc X nd}{ +1 add set}{1 add clr}{adv 2 chg}{adv 2 chg nd}{pop nd}]A{bind pop} +forall N/D{/cc X A type/stringtype ne{]}if nn/base get cc ctr put nn +/BitMaps get S ctr S sf 1 ne{A A length 1 sub A 2 index S get sf div put +}if put/ctr ctr 1 add N}B/I{cc 1 add D}B/bop{userdict/bop-hook known{ +bop-hook}if/SI save N @rigin 0 0 moveto/V matrix currentmatrix A 1 get A +mul exch 0 get A mul add .99 lt{/QV}{/RV}ifelse load def pop pop}N/eop{ +SI restore userdict/eop-hook known{eop-hook}if showpage}N/@start{ +userdict/start-hook known{start-hook}if pop/VResolution X/Resolution X +1000 div/DVImag X/IEn 256 array N 2 string 0 1 255{IEn S A 360 add 36 4 +index cvrs cvn put}for pop 65781.76 div/vsize X 65781.76 div/hsize X}N +/p{show}N/RMat[1 0 0 -1 0 0]N/BDot 260 string N/Rx 0 N/Ry 0 N/V{}B/RV/v{ +/Ry X/Rx X V}B statusdict begin/product where{pop false[(Display)(NeXT) +(LaserWriter 16/600)]{A length product length le{A length product exch 0 +exch getinterval eq{pop true exit}if}{pop}ifelse}forall}{false}ifelse +end{{gsave TR -.1 .1 TR 1 1 scale Rx Ry false RMat{BDot}imagemask +grestore}}{{gsave TR -.1 .1 TR Rx Ry scale 1 1 false RMat{BDot} +imagemask grestore}}ifelse B/QV{gsave newpath transform round exch round +exch itransform moveto Rx 0 rlineto 0 Ry neg rlineto Rx neg 0 rlineto +fill grestore}B/a{moveto}B/delta 0 N/tail{A/delta X 0 rmoveto}B/M{S p +delta add tail}B/b{S p tail}B/c{-4 M}B/d{-3 M}B/e{-2 M}B/f{-1 M}B/g{0 M} +B/h{1 M}B/i{2 M}B/j{3 M}B/k{4 M}B/w{0 rmoveto}B/l{p -4 w}B/m{p -3 w}B/n{ +p -2 w}B/o{p -1 w}B/q{p 1 w}B/r{p 2 w}B/s{p 3 w}B/t{p 4 w}B/x{0 S +rmoveto}B/y{3 2 roll p a}B/bos{/SS save N}B/eos{SS restore}B end + +%%EndProcSet +%%BeginProcSet: 8r.enc +% @@psencodingfile@{ +% author = "S. Rahtz, P. MacKay, Alan Jeffrey, B. Horn, K. Berry", +% version = "0.6", +% date = "22 June 1996", +% filename = "8r.enc", +% email = "kb@@mail.tug.org", +% address = "135 Center Hill Rd. // Plymouth, MA 02360", +% codetable = "ISO/ASCII", +% checksum = "119 662 4424", +% docstring = "Encoding for TrueType or Type 1 fonts to be used with TeX." +% @} +% +% Idea is to have all the characters normally included in Type 1 fonts +% available for typesetting. This is effectively the characters in Adobe +% Standard Encoding + ISO Latin 1 + extra characters from Lucida. +% +% Character code assignments were made as follows: +% +% (1) the Windows ANSI characters are almost all in their Windows ANSI +% positions, because some Windows users cannot easily reencode the +% fonts, and it makes no difference on other systems. The only Windows +% ANSI characters not available are those that make no sense for +% typesetting -- rubout (127 decimal), nobreakspace (160), softhyphen +% (173). quotesingle and grave are moved just because it's such an +% irritation not having them in TeX positions. +% +% (2) Remaining characters are assigned arbitrarily to the lower part +% of the range, avoiding 0, 10 and 13 in case we meet dumb software. +% +% (3) Y&Y Lucida Bright includes some extra text characters; in the +% hopes that other PostScript fonts, perhaps created for public +% consumption, will include them, they are included starting at 0x12. +% +% (4) Remaining positions left undefined are for use in (hopefully) +% upward-compatible revisions, if someday more characters are generally +% available. +% +% (5) hyphen appears twice for compatibility with both ASCII and Windows. +% +/TeXBase1Encoding [ +% 0x00 (encoded characters from Adobe Standard not in Windows 3.1) + /.notdef /dotaccent /fi /fl + /fraction /hungarumlaut /Lslash /lslash + /ogonek /ring /.notdef + /breve /minus /.notdef +% These are the only two remaining unencoded characters, so may as +% well include them. + /Zcaron /zcaron +% 0x10 + /caron /dotlessi +% (unusual TeX characters available in, e.g., Lucida Bright) + /dotlessj /ff /ffi /ffl + /.notdef /.notdef /.notdef /.notdef + /.notdef /.notdef /.notdef /.notdef + % very contentious; it's so painful not having quoteleft and quoteright + % at 96 and 145 that we move the things normally found there down to here. + /grave /quotesingle +% 0x20 (ASCII begins) + /space /exclam /quotedbl /numbersign + /dollar /percent /ampersand /quoteright + /parenleft /parenright /asterisk /plus /comma /hyphen /period /slash +% 0x30 + /zero /one /two /three /four /five /six /seven + /eight /nine /colon /semicolon /less /equal /greater /question +% 0x40 + /at /A /B /C /D /E /F /G /H /I /J /K /L /M /N /O +% 0x50 + /P /Q /R /S /T /U /V /W + /X /Y /Z /bracketleft /backslash /bracketright /asciicircum /underscore +% 0x60 + /quoteleft /a /b /c /d /e /f /g /h /i /j /k /l /m /n /o +% 0x70 + /p /q /r /s /t /u /v /w + /x /y /z /braceleft /bar /braceright /asciitilde + /.notdef % rubout; ASCII ends +% 0x80 + /.notdef /.notdef /quotesinglbase /florin + /quotedblbase /ellipsis /dagger /daggerdbl + /circumflex /perthousand /Scaron /guilsinglleft + /OE /.notdef /.notdef /.notdef +% 0x90 + /.notdef /.notdef /.notdef /quotedblleft + /quotedblright /bullet /endash /emdash + /tilde /trademark /scaron /guilsinglright + /oe /.notdef /.notdef /Ydieresis +% 0xA0 + /.notdef % nobreakspace + /exclamdown /cent /sterling + /currency /yen /brokenbar /section + /dieresis /copyright /ordfeminine /guillemotleft + /logicalnot + /hyphen % Y&Y (also at 45); Windows' softhyphen + /registered + /macron +% 0xD0 + /degree /plusminus /twosuperior /threesuperior + /acute /mu /paragraph /periodcentered + /cedilla /onesuperior /ordmasculine /guillemotright + /onequarter /onehalf /threequarters /questiondown +% 0xC0 + /Agrave /Aacute /Acircumflex /Atilde /Adieresis /Aring /AE /Ccedilla + /Egrave /Eacute /Ecircumflex /Edieresis + /Igrave /Iacute /Icircumflex /Idieresis +% 0xD0 + /Eth /Ntilde /Ograve /Oacute + /Ocircumflex /Otilde /Odieresis /multiply + /Oslash /Ugrave /Uacute /Ucircumflex + /Udieresis /Yacute /Thorn /germandbls +% 0xE0 + /agrave /aacute /acircumflex /atilde + /adieresis /aring /ae /ccedilla + /egrave /eacute /ecircumflex /edieresis + /igrave /iacute /icircumflex /idieresis +% 0xF0 + /eth /ntilde /ograve /oacute + /ocircumflex /otilde /odieresis /divide + /oslash /ugrave /uacute /ucircumflex + /udieresis /yacute /thorn /ydieresis +] def + +%%EndProcSet +%%BeginProcSet: texps.pro +%! +TeXDict begin/rf{findfont dup length 1 add dict begin{1 index/FID ne 2 +index/UniqueID ne and{def}{pop pop}ifelse}forall[1 index 0 6 -1 roll +exec 0 exch 5 -1 roll VResolution Resolution div mul neg 0 0]/Metrics +exch def dict begin Encoding{exch dup type/integertype ne{pop pop 1 sub +dup 0 le{pop}{[}ifelse}{FontMatrix 0 get div Metrics 0 get div def} +ifelse}forall Metrics/Metrics currentdict end def[2 index currentdict +end definefont 3 -1 roll makefont/setfont cvx]cvx def}def/ObliqueSlant{ +dup sin S cos div neg}B/SlantFont{4 index mul add}def/ExtendFont{3 -1 +roll mul exch}def/ReEncodeFont{CharStrings rcheck{/Encoding false def +dup[exch{dup CharStrings exch known not{pop/.notdef/Encoding true def} +if}forall Encoding{]exch pop}{cleartomark}ifelse}if/Encoding exch def} +def end + +%%EndProcSet +%%BeginProcSet: special.pro +%! +TeXDict begin/SDict 200 dict N SDict begin/@SpecialDefaults{/hs 612 N +/vs 792 N/ho 0 N/vo 0 N/hsc 1 N/vsc 1 N/ang 0 N/CLIP 0 N/rwiSeen false N +/rhiSeen false N/letter{}N/note{}N/a4{}N/legal{}N}B/@scaleunit 100 N +/@hscale{@scaleunit div/hsc X}B/@vscale{@scaleunit div/vsc X}B/@hsize{ +/hs X/CLIP 1 N}B/@vsize{/vs X/CLIP 1 N}B/@clip{/CLIP 2 N}B/@hoffset{/ho +X}B/@voffset{/vo X}B/@angle{/ang X}B/@rwi{10 div/rwi X/rwiSeen true N}B +/@rhi{10 div/rhi X/rhiSeen true N}B/@llx{/llx X}B/@lly{/lly X}B/@urx{ +/urx X}B/@ury{/ury X}B/magscale true def end/@MacSetUp{userdict/md known +{userdict/md get type/dicttype eq{userdict begin md length 10 add md +maxlength ge{/md md dup length 20 add dict copy def}if end md begin +/letter{}N/note{}N/legal{}N/od{txpose 1 0 mtx defaultmatrix dtransform S +atan/pa X newpath clippath mark{transform{itransform moveto}}{transform{ +itransform lineto}}{6 -2 roll transform 6 -2 roll transform 6 -2 roll +transform{itransform 6 2 roll itransform 6 2 roll itransform 6 2 roll +curveto}}{{closepath}}pathforall newpath counttomark array astore/gc xdf +pop ct 39 0 put 10 fz 0 fs 2 F/|______Courier fnt invertflag{PaintBlack} +if}N/txpose{pxs pys scale ppr aload pop por{noflips{pop S neg S TR pop 1 +-1 scale}if xflip yflip and{pop S neg S TR 180 rotate 1 -1 scale ppr 3 +get ppr 1 get neg sub neg ppr 2 get ppr 0 get neg sub neg TR}if xflip +yflip not and{pop S neg S TR pop 180 rotate ppr 3 get ppr 1 get neg sub +neg 0 TR}if yflip xflip not and{ppr 1 get neg ppr 0 get neg TR}if}{ +noflips{TR pop pop 270 rotate 1 -1 scale}if xflip yflip and{TR pop pop +90 rotate 1 -1 scale ppr 3 get ppr 1 get neg sub neg ppr 2 get ppr 0 get +neg sub neg TR}if xflip yflip not and{TR pop pop 90 rotate ppr 3 get ppr +1 get neg sub neg 0 TR}if yflip xflip not and{TR pop pop 270 rotate ppr +2 get ppr 0 get neg sub neg 0 S TR}if}ifelse scaleby96{ppr aload pop 4 +-1 roll add 2 div 3 1 roll add 2 div 2 copy TR .96 dup scale neg S neg S +TR}if}N/cp{pop pop showpage pm restore}N end}if}if}N/normalscale{ +Resolution 72 div VResolution 72 div neg scale magscale{DVImag dup scale +}if 0 setgray}N/psfts{S 65781.76 div N}N/startTexFig{/psf$SavedState +save N userdict maxlength dict begin/magscale true def normalscale +currentpoint TR/psf$ury psfts/psf$urx psfts/psf$lly psfts/psf$llx psfts +/psf$y psfts/psf$x psfts currentpoint/psf$cy X/psf$cx X/psf$sx psf$x +psf$urx psf$llx sub div N/psf$sy psf$y psf$ury psf$lly sub div N psf$sx +psf$sy scale psf$cx psf$sx div psf$llx sub psf$cy psf$sy div psf$ury sub +TR/showpage{}N/erasepage{}N/copypage{}N/p 3 def @MacSetUp}N/doclip{ +psf$llx psf$lly psf$urx psf$ury currentpoint 6 2 roll newpath 4 copy 4 2 +roll moveto 6 -1 roll S lineto S lineto S lineto closepath clip newpath +moveto}N/endTexFig{end psf$SavedState restore}N/@beginspecial{SDict +begin/SpecialSave save N gsave normalscale currentpoint TR +@SpecialDefaults count/ocount X/dcount countdictstack N}N/@setspecial{ +CLIP 1 eq{newpath 0 0 moveto hs 0 rlineto 0 vs rlineto hs neg 0 rlineto +closepath clip}if ho vo TR hsc vsc scale ang rotate rwiSeen{rwi urx llx +sub div rhiSeen{rhi ury lly sub div}{dup}ifelse scale llx neg lly neg TR +}{rhiSeen{rhi ury lly sub div dup scale llx neg lly neg TR}if}ifelse +CLIP 2 eq{newpath llx lly moveto urx lly lineto urx ury lineto llx ury +lineto closepath clip}if/showpage{}N/erasepage{}N/copypage{}N newpath}N +/@endspecial{count ocount sub{pop}repeat countdictstack dcount sub{end} +repeat grestore SpecialSave restore end}N/@defspecial{SDict begin}N +/@fedspecial{end}B/li{lineto}B/rl{rlineto}B/rc{rcurveto}B/np{/SaveX +currentpoint/SaveY X N 1 setlinecap newpath}N/st{stroke SaveX SaveY +moveto}N/fil{fill SaveX SaveY moveto}N/ellipse{/endangle X/startangle X +/yrad X/xrad X/savematrix matrix currentmatrix N TR xrad yrad scale 0 0 +1 startangle endangle arc savematrix setmatrix}N end + +%%EndProcSet +TeXDict begin 40258431 52099146 1000 600 600 (dddmp-2.0.dvi) +@start /Fa 143[55 1[55 7[28 2[50 99[{TeXBase1Encoding ReEncodeFont}4 +99.6264 /Helvetica rf +%DVIPSBitmapFont: Fb cmr12 12 3 +/Fb 3 53 df<14FF010713E090381F81F890383E007C01FC133F4848EB1F8049130F4848 +EB07C04848EB03E0A2000F15F0491301001F15F8A2003F15FCA390C8FC4815FEA54815FF +B3A46C15FEA56D1301003F15FCA3001F15F8A26C6CEB03F0A36C6CEB07E0000315C06D13 +0F6C6CEB1F806C6CEB3F00013E137C90381F81F8903807FFE0010090C7FC28447CC131> +48 D<143014F013011303131F13FFB5FC13E713071200B3B3B0497E497E007FB6FCA320 +4278C131>I52 D E +%EndDVIPSBitmapFont +/Fc 64[50 29[39 12[55 55 25[44 44 66 44 50 28 39 39 1[50 +50 50 72 28 44 1[28 50 50 28 44 50 44 50 50 10[61 2[50 +4[66 83 55 2[33 2[61 1[72 66 61 61 15[50 2[25 33 25 2[33 +33 37[50 2[{TeXBase1Encoding ReEncodeFont}45 99.6264 +/Times-Italic rf +%DVIPSBitmapFont: Fd cmmi12 12 3 +/Fd 3 103 df60 D<127012FCB4FCEA7FC0EA1FF0EA +07FCEA01FF38007FC0EB1FF0EB07FE903801FF809038007FE0EC1FF8EC03FE913800FF80 +ED3FE0ED0FF8ED03FF030013C0EE3FF0EE0FFCEE01FF9338007FC0EF1FF0EF07FCEF01FF +9438007FC0F01FE0A2F07FC0943801FF00EF07FCEF1FF0EF7FC04C48C7FCEE0FFCEE3FF0 +EEFFC0030390C8FCED0FF8ED3FE0EDFF80DA03FEC9FCEC1FF8EC7FE0903801FF80D907FE +CAFCEB1FF0EB7FC04848CBFCEA07FCEA1FF0EA7FC048CCFC12FC12703B3878B44C>62 +D102 +D E +%EndDVIPSBitmapFont +/Fe 134[42 2[42 42 23 32 28 1[42 42 42 65 23 2[23 42 +42 28 37 42 1[42 37 12[51 10[28 4[60 1[55 19[21 28 21 +44[{TeXBase1Encoding ReEncodeFont}26 83.022 /Times-Roman +rf +%DVIPSBitmapFont: Ff cmr7 7 2 +/Ff 2 51 df<13381378EA01F8121F12FE12E01200B3AB487EB512F8A215267BA521>49 +D<13FF000313E0380E03F0381800F848137C48137E00787F12FC6CEB1F80A4127CC7FC15 +005C143E147E147C5C495A495A5C495A010EC7FC5B5B903870018013E0EA018039030003 +0012065A001FB5FC5A485BB5FCA219267DA521>I E +%EndDVIPSBitmapFont +/Fg 103[60 26[60 1[60 60 60 60 60 60 60 60 60 60 60 60 +60 60 60 60 2[60 60 60 60 60 60 60 60 60 3[60 1[60 3[60 +60 1[60 60 1[60 60 1[60 60 3[60 1[60 1[60 60 60 1[60 +60 1[60 1[60 1[60 60 60 60 60 60 60 60 60 60 60 60 60 +60 60 5[60 38[{TeXBase1Encoding ReEncodeFont}62 99.6264 +/Courier rf +%DVIPSBitmapFont: Fh cmr8 8 2 +/Fh 2 51 df<130C133C137CEA03FC12FFEAFC7C1200B3B113FE387FFFFEA2172C7AAB23 +>49 DI E +%EndDVIPSBitmapFont +/Fi 105[50 28[50 50 2[55 33 39 44 1[55 50 55 83 28 2[28 +1[50 33 44 55 44 55 50 10[72 1[66 55 3[78 72 94 66 3[78 +1[61 66 72 72 66 72 13[50 50 50 1[28 25 33 45[{ +TeXBase1Encoding ReEncodeFont}40 99.6264 /Times-Bold +rf /Fj 139[40 1[53 1[66 60 66 100 33 2[33 3[53 3[60 23[47 +2[73 18[60 60 60 2[30 46[{TeXBase1Encoding ReEncodeFont}16 +119.552 /Times-Bold rf +%DVIPSBitmapFont: Fk cmsy10 12 1 +/Fk 1 16 df<49B4FC010F13E0013F13F8497F48B6FC4815804815C04815E04815F0A248 +15F8A24815FCA3B712FEA96C15FCA36C15F8A26C15F0A26C15E06C15C06C15806C15006C +6C13FC6D5B010F13E0010190C7FC27277BAB32>15 D E +%EndDVIPSBitmapFont +/Fl 64[44 42[44 44 24[44 50 50 72 50 50 28 39 33 50 50 +50 50 78 28 50 28 28 50 50 33 44 50 44 50 44 6[61 1[72 +94 72 72 61 55 66 72 55 72 72 89 61 1[39 33 72 72 55 +61 72 66 66 72 3[56 1[28 28 50 50 50 50 50 50 50 50 50 +50 28 25 33 25 2[33 33 36[55 55 2[{TeXBase1Encoding ReEncodeFont}74 +99.6264 /Times-Roman rf +%DVIPSBitmapFont: Fm cmsy10 14.4 2 +/Fm 2 104 df102 +DI E +%EndDVIPSBitmapFont +/Fn 105[60 27[53 4[60 33 47 40 60 60 60 60 93 33 2[33 +1[60 40 53 60 53 60 53 7[86 4[73 66 1[86 66 3[73 2[40 +1[86 1[73 86 80 1[86 110 5[33 60 4[60 1[60 60 60 1[30 +40 30 44[{TeXBase1Encoding ReEncodeFont}42 119.552 /Times-Roman +rf /Fo 136[104 1[80 48 56 64 1[80 72 80 120 40 80 1[40 +1[72 1[64 80 64 80 72 12[96 80 104 1[88 1[104 135 3[56 +2[88 1[104 104 96 104 6[48 1[72 72 72 72 72 72 72 72 +72 1[36 46[{TeXBase1Encoding ReEncodeFont}41 143.462 +/Times-Bold rf end +%%EndProlog +%%BeginSetup +%%Feature: *Resolution 600dpi +TeXDict begin +%%BeginPaperSize: Letter +letter +%%EndPaperSize + +%%EndSetup +%%Page: 1 1 +1 0 bop 472 600 a Fo(DDDMP:)35 b(Decision)f(Diagram)f(DuMP)j(package) +1480 830 y(Release)e(2.0)462 1230 y Fn(Gianpiero)c(Cabodi)2402 +1232 y(Stef)o(ano)g(Quer)1316 1506 y(Politecnico)g(di)g(T)-10 +b(orino)1024 1656 y(Dip.)30 b(di)g(Automatica)g(e)g(Informatica)1119 +1805 y(Corso)f(Duca)h(de)n(gli)g(Abruzzi)g(24)1277 1955 +y(I\22610129)e(T)-5 b(urin,)29 b(IT)-11 b(AL)f(Y)1038 +2104 y(E-mail:)38 b Fm(f)p Fn(cabodi,quer)p Fm(g)p Fn(@polito.it)-189 +2614 y Fo(1)143 b(Intr)m(oduction)-189 2837 y Fl(The)27 +b(DDDMP)h(package)f(de\002nes)h(formats)f(and)g(rules)g(to)g(store)g +(DD)g(on)g(\002le.)39 b(More)27 b(in)g(particular)g(it)g(contains)g(a) +-189 2958 y(set)e(of)g(functions)e(to)i(dump)e(\(store)i(and)g(load\))g +(DDs)f(and)h(DD)g(forests)f(on)h(\002le)g(in)f(dif)n(ferent)h(formats.) +47 3078 y(In)30 b(the)g(present)g(implementation,)f(BDDs)h(\(R)l +(OBDDs\))h(and)f(ADD)g(\(Algebraic)g(Decision)g(Diagram\))g(of)-189 +3199 y(the)g(CUDD)g(package)g(\(v)o(ersion)f(2.3.0)g(or)h(higher\))g +(are)g(supported.)45 b(These)30 b(structures)f(can)h(be)g(represented)g +(on)-189 3319 y(\002les)25 b(either)g(in)f(te)o(xt,)g(binary)-6 +b(,)24 b(or)h(CNF)g(\(DIMA)l(CS\))h(formats.)47 3439 +y(The)f(main)f(rules)h(used)f(are)i(follo)n(wing)d(rules:)-44 +3643 y Fk(\017)49 b Fl(A)30 b(\002le)h(contains)e(a)i(single)e(BDD/ADD) +h(or)g(a)h(forest)f(of)g(BDDs/ADD,)g(i.e.,)i(a)e(v)o(ector)g(of)g +(Boolean)h(func-)55 3763 y(tions.)-44 3966 y Fk(\017)49 +b Fl(Inte)o(ger)21 b(inde)o(x)o(es)f(are)i(used)f(instead)g(of)g +(pointers)g(to)g(reference)i(nodes.)29 b(BDD/ADD)21 b(nodes)g(are)h +(numbered)55 4087 y(with)j(contiguous)g(numbers,)g(from)h(1)g(to)f +(NNodes)h(\(total)f(number)h(of)g(nodes)g(on)f(a)i(\002le\).)35 +b(0)26 b(is)f(not)h(used)f(to)55 4207 y(allo)n(w)f(ne)o(gati)n(v)o(e)e +(inde)o(x)o(es)h(for)i(complemented)f(edges.)-44 4411 +y Fk(\017)49 b Fl(A)23 b(\002le)g(contains)f(a)h(header)l(,)h +(including)d(se)n(v)o(eral)h(informations)f(about)h(v)n(ariables)h(and) +f(roots)g(of)h(BDD)h(func-)55 4531 y(tions,)32 b(then)e(the)h(list)g +(of)g(nodes.)49 b(The)32 b(header)f(is)g(al)o(w)o(ays)g(represented)h +(in)f(te)o(xt)f(format)h(\(also)g(for)g(binary)55 4651 +y(\002les\).)g(BDDs,)25 b(ADDs,)f(and)h(CNF)h(\002les)f(share)g(a)g +(similar)f(format)g(header)-5 b(.)-44 4855 y Fk(\017)49 +b Fl(BDD/ADD)40 b(nodes)g(are)h(listed)f(follo)n(wing)e(their)i +(numbering,)j(which)d(is)g(produced)g(by)h(a)f(post-order)55 +4975 y(tra)n(v)o(ersal,)24 b(in)h(such)f(a)h(w)o(ay)g(that)g(a)g(node)f +(is)h(al)o(w)o(ays)f(listed)g(after)h(its)f(Then/Else)g(children.)47 +5179 y(In)32 b(the)f(sequel)g(we)g(describe)h(more)f(in)g(detail)f(the) +h(dif)n(ferent)g(formats)g(and)g(procedures)h(a)n(v)n(ailable.)49 +b(First)-189 5299 y(of)26 b(all,)f(we)h(describe)f(BDDs)h(and)g(ADDs)f +(formats)g(and)g(procedure.)33 b(Secondly)-6 b(,)26 b(we)f(concentrate) +h(on)f(CNF)i(\002les,)-189 5419 y(i.e.,)e(ho)n(w)f(to)g(translate)g(a)i +(BDD)f(or)g(a)g(forest)g(of)f(BDDs)h(into)f(a)h(CNF)h(formula)e(and)h +(vice-v)o(ersa.)1794 5800 y(1)p eop +%%Page: 2 2 +2 1 bop -189 218 a Fo(2)143 b(BDD)35 b(and)g(ADD)g(Support)-189 +441 y Fl(In)23 b(this)f(section)g(we)g(describe)h(format)g(and)f +(procedure)h(re)o(garding)f(BDDs)h(and)f(ADDs.)30 b(W)-8 +b(e)23 b(speci\002cally)g(refer)g(to)-189 562 y(BDDs)h(in)g(the)g +(description)e(as)j(ADD)e(may)h(be)g(seen)g(as)h(an)f(e)o(xtension)e +(and)i(will)f(be)h(described)g(later)-5 b(.)30 b(First)24 +b(of)g(all,)-189 682 y(we)29 b(concentrate)f(on)g(the)g(format)g(used)g +(to)g(store)g(these)g(structure,)h(then)f(we)g(describe)h(the)f +(procedure)h(a)n(v)n(ailable)-189 802 y(to)24 b(store)h(and)g(load)f +(them.)-189 1094 y Fj(2.1)119 b(F)m(ormat)-189 1281 y +Fl(BDD)30 b(dump)f(\002les)g(are)i(composed)e(of)g(tw)o(o)g(sections:) +40 b(The)29 b(header)h(and)g(the)f(list)g(of)h(nodes.)44 +b(The)30 b(header)g(has)g(a)-189 1402 y(common)c(\(te)o(xt\))h(format,) +h(while)e(the)i(list)e(of)h(nodes)g(is)g(either)g(in)g(te)o(xt)g(or)g +(binary)g(format.)38 b(In)28 b(te)o(xt)e(format)h(nodes)-189 +1522 y(are)33 b(represented)f(with)f(redundant)g(informations,)h(where) +h(the)f(main)f(goal)g(is)h(readability)-6 b(,)32 b(while)g(the)f +(purpose)-189 1642 y(of)i(binary)f(format)g(is)g(minimizing)e(the)i(o)o +(v)o(erall)f(storage)h(size)h(for)g(BDD)f(nodes.)54 b(The)32 +b(header)h(format)f(is)g(k)o(ept)-189 1763 y(common)h(to)h(te)o(xt)g +(and)g(binary)g(formats)g(for)h(sak)o(e)f(of)h(simplicity:)47 +b(No)34 b(particular)g(optimization)f(is)h(presently)-189 +1883 y(done)29 b(on)f(binary)h(\002le)g(headers,)h(whose)f(size)g(is)f +(by)h(f)o(ar)g(dominated)f(by)h(node)f(lists)g(in)g(the)h(case)g(of)g +(lar)n(ge)h(BDDs)-189 2003 y(\(se)n(v)o(eral)24 b(thousands)g(of)h(DD)f +(nodes\).)-189 2266 y Fi(2.1.1)99 b(Header)-189 2453 +y Fl(The)23 b(header)h(has)f(the)g(same)g(format)g(both)g(for)g(te)o +(xtual)f(and)i(binary)e(dump.)30 b(F)o(or)23 b(sak)o(e)g(of)h +(generality)e(and)h(because)-189 2574 y(of)f(dynamic)g(v)n(ariable)g +(ordering)g(both)f(v)n(ariable)h(IDs)g(and)g(permutations)2377 +2537 y Fh(1)2438 2574 y Fl(are)h(included.)29 b(Names)22 +b(are)h(optionally)-189 2694 y(listed)35 b(for)h(input)f(v)n(ariables)g +(and)h(for)h(the)e(stored)h(functions.)63 b(Ne)n(w)36 +b(auxiliary)f(IDs)h(are)h(also)e(allo)n(wed.)64 b(Only)-189 +2814 y(the)34 b(v)n(ariables)f(in)g(the)h(true)g(support)f(of)h(the)f +(stored)h(BDDs)g(are)h(listed.)56 b(All)34 b(information)e(on)i(v)n +(ariables)f(\(IDs,)-189 2935 y(permutations,)c(names,)i(auxiliary)e +(IDs\))h(sorted)g(by)g(IDs,)h(and)e(the)o(y)h(are)g(restricted)g(to)f +(the)h(true)g(support)f(of)h(the)-189 3055 y(dumped)22 +b(BDD,)h(while)g(IDs)g(and)f(permutations)g(are)h(referred)i(to)d(the)h +(writing)f(BDD)h(manager)-5 b(.)30 b(Names)22 b(can)i(thus)-189 +3175 y(be)h(sorted)f(by)h(v)n(ariable)f(ordering)h(by)f(permuting)g +(them)g(according)h(to)f(the)h(permutations)e(stored)h(in)h(the)f +(\002le.)47 3296 y(As)h(an)g(e)o(xample,)f(the)g(header)i(\(in)e(te)o +(xt)g(mode\))h(of)f(the)h(ne)o(xt)f(state)h(functions)e(of)i(circuit)g +(s27)f(follo)n(ws:)-189 3494 y Fg(.ver)59 b(DDDMP-2.0)-189 +3615 y(.mode)g(A)-189 3735 y(.varinfo)f(3)-189 3855 y(.dd)h(s27-delta) +-189 3976 y(.nnodes)f(16)-189 4096 y(.nvars)g(10)-189 +4216 y(.nsuppvars)g(7)-189 4337 y(.varnames)g(G0)h(G1)g(G2)h(G3)f(G5)g +(G6)h(G7)-189 4457 y(.orderedvarnames)c(G0)k(G1)f(G2)g(G3)h(G5)f(G6)g +(G7)-189 4578 y(.ids)g(0)g(1)h(2)g(3)f(4)h(5)f(6)-189 +4698 y(.permids)f(0)i(1)f(2)h(3)f(5)h(7)f(9)-189 4818 +y(.auxids)f(1)i(2)f(3)h(4)f(5)h(6)g(7)-189 4939 y(.nroots)e(3)-189 +5059 y(.rootids)g(6)i(-13)f(-16)-189 5179 y(.rootnames)f(G10)h(G11)g +(G13)47 5378 y Fl(The)25 b(lines)f(contain)g(the)h(follo)n(wing)e +(informations:)p -189 5460 1607 4 v -77 5521 a Ff(1)-40 +5551 y Fe(The)d(permutation)e(of)i(the)g(i-th)h(v)n(ariable)e(ID)h(is)h +(the)f(relati)n(v)o(e)g(position)f(of)h(the)g(v)n(ariable)f(in)i(the)f +(ordering.)1794 5800 y Fl(2)p eop +%%Page: 3 3 +3 2 bop -44 218 a Fk(\017)49 b Fl(Dddmp)24 b(v)o(ersion)f(information.) +-44 411 y Fk(\017)49 b Fl(File)25 b(mode)f(\(A)h(for)g(ASCII)h(te)o +(xt,)e(B)h(for)g(binary)g(mode\).)-44 604 y Fk(\017)49 +b Fl(V)-11 b(ar)n(-e)o(xtra-info)25 b(\(0:)30 b(v)n(ariable)24 +b(ID,)h(1:)31 b(permID,)24 b(2:)31 b(aux)25 b(ID,)g(3:)30 +b(v)n(ariable)24 b(name,)h(4)g(no)f(e)o(xtra)h(info\).)-44 +797 y Fk(\017)49 b Fl(Name)25 b(of)g(dd)f(\(optional\).)-44 +990 y Fk(\017)49 b Fl(T)-8 b(otal)24 b(number)g(of)h(nodes)g(in)f(the)h +(\002le.)-44 1183 y Fk(\017)49 b Fl(Number)24 b(of)h(v)n(ariables)f(of) +h(the)g(writing)f(DD)g(manager)-5 b(.)-44 1375 y Fk(\017)49 +b Fl(Number)24 b(of)h(v)n(ariables)f(in)h(the)f(true)h(support)f(of)h +(the)f(stored)h(DDs.)-44 1568 y Fk(\017)49 b Fl(V)-11 +b(ariable)25 b(names)f(\(optional\))g(for)h(all)g(the)f(v)n(ariables)g +(in)h(the)f(BDD/ADD)h(support.)-44 1761 y Fk(\017)49 +b Fl(V)-11 b(ariable)20 b(names)g(for)h(all)f(the)g(v)n(ariables)f(in)h +(the)g(DD)h(manager)f(during)g(the)g(storing)f(phase.)29 +b(Notice)20 b(that)g(this)55 1882 y(information)k(w)o(as)h(not)g +(stored)g(by)g(pre)n(vious)f(v)o(ersions)g(of)i(the)f(same)g(tool.)32 +b(Full)25 b(backw)o(ard)g(compatibility)55 2002 y(is)f(guaranteed)h(by) +g(the)f(present)h(implementation)d(of)j(the)g(tool.)-44 +2195 y Fk(\017)49 b Fl(V)-11 b(ariable)25 b(IDs.)-44 +2388 y Fk(\017)49 b Fl(V)-11 b(ariable)25 b(permuted)f(IDs.)-44 +2581 y Fk(\017)49 b Fl(V)-11 b(ariable)25 b(auxiliary)f(IDs)h +(\(optional\).)-44 2774 y Fk(\017)49 b Fl(Number)24 b(of)h(BDD)g +(roots.)-44 2967 y Fk(\017)49 b Fl(Inde)o(x)o(es)24 b(of)h(BDD)g(roots) +f(\(complemented)g(edges)g(allo)n(wed\).)-44 3160 y Fk(\017)49 +b Fl(Names)24 b(of)h(BDD)h(roots)e(\(optional\).)-189 +3332 y(Notice)h(that)f(a)h(\002eld)-189 3504 y Fg(.add)-189 +3676 y Fl(is)f(present)h(after)g(the)g(dddmp)f(v)o(ersion)f(for)j +(\002les)e(containing)g(ADDs.)-189 3936 y Fi(2.1.2)99 +b(T)-9 b(ext)25 b(F)n(ormat)-189 4124 y Fl(In)g(te)o(xt)f(mode)g(nodes) +g(are)i(listed)e(on)g(a)h(te)o(xt)f(line)h(basis.)30 +b(Each)25 b(a)g(node)f(is)h(represented)g(as)-189 4296 +y Fg()57 b([])f()588 +4416 y()h()-189 4588 y Fl(where)25 +b(all)g(inde)o(x)o(es)e(are)j(inte)o(ger)e(numbers.)47 +4709 y(This)h(format)g(is)g(redundant)f(\(due)i(to)f(the)g(node)g +(ordering,)g Fd(<)p Fl(Node-inde)o(x)p Fd(>)f Fl(is)g(and)i +(incremental)e(inte)o(ger\))-189 4829 y(b)n(ut)g(we)h(k)o(eep)g(it)g +(for)g(readability)-6 b(.)47 4949 y Fd(<)p Fl(V)-11 b(ar)n(-e)o +(xtra-info)p Fd(>)34 b Fl(\(optional)e(redundant)i(\002eld\))g(is)f +(either)h(an)g(inte)o(ger)f(\(ID,)h(PermID,)g(or)g(auxID\))g(or)g(a) +-189 5070 y(string)k(\(v)n(ariable)h(name\).)75 b Fd(<)p +Fl(V)-11 b(ar)n(-internal-inde)o(x)p Fd(>)38 b Fl(is)h(an)g(internal)g +(v)n(ariable)g(inde)o(x:)59 b(V)-11 b(ariables)39 b(in)g(the)g(true) +-189 5190 y(support)25 b(of)h(the)g(stored)g(BDDs)g(are)h(numbered)e +(with)g(ascending)h(inte)o(gers)f(starting)g(from)h(0,)g(and)g(follo)n +(wing)e(the)-189 5311 y(v)n(ariable)g(ordering.)31 b +Fd(<)p Fl(Then-inde)o(x)p Fd(>)23 b Fl(and)i Fd(<)p Fl(Else-inde)o(x)p +Fd(>)e Fl(are)j(signed)e(inde)o(x)o(es)f(of)i(children)f(nodes.)47 +5431 y(In)h(the)f(follo)n(wing,)f(we)i(report)f(the)g(list)g(of)h +(nodes)f(of)g(the)h(s27)f(ne)o(xt)f(state)i(functions)e(\(see)i(pre)n +(vious)e(header)-189 5551 y(e)o(xample\):)1794 5800 y(3)p +eop +%%Page: 4 4 +4 3 bop -189 218 a Fg(.nodes)-189 338 y(1)60 b(T)f(1)h(0)f(0)-189 +459 y(2)h(G7)f(6)g(1)h(-1)-189 579 y(3)g(G5)f(4)g(1)h(2)-189 +699 y(4)g(G3)f(3)g(3)h(1)-189 820 y(5)g(G1)f(1)g(1)h(4)-189 +940 y(6)g(G0)f(0)g(5)h(-1)-189 1061 y(7)g(G6)f(5)g(1)h(-1)-189 +1181 y(8)g(G5)f(4)g(1)h(-7)-189 1301 y(9)g(G6)f(5)g(1)h(-2)-189 +1422 y(10)f(G5)h(4)f(1)h(-9)-189 1542 y(11)f(G3)h(3)f(10)h(8)-189 +1662 y(12)f(G1)h(1)f(8)h(11)-189 1783 y(13)f(G0)h(0)f(5)h(12)-189 +1903 y(14)f(G2)h(2)f(1)h(-1)-189 2024 y(15)f(G2)h(2)f(1)h(-2)-189 +2144 y(16)f(G1)h(1)f(14)h(15)-189 2264 y(.end)-189 2468 +y Fl(The)27 b(list)f(is)h(enclosed)g(between)g(the)g +Fg(.nodes)f Fl(and)h Fg(.end)f Fl(lines.)37 b(First)27 +b(node)g(is)g(the)g(one)g(constant,)f(each)i(node)-189 +2588 y(contains)c(the)h(optional)e(v)n(ariable)h(name.)47 +2708 y(F)o(or)29 b(ADDs)f(more)h(than)f(one)h(constant)e(is)i(stored)f +(in)g(the)g(\002le.)43 b(Each)29 b(constant)f(has)g(the)h(same)f +(format)h(we)-189 2829 y(ha)n(v)o(e)c(just)e(analyzed)i(for)g(the)g +(BDD)g(b)n(ut)g(the)f(represented)h(v)n(alue)f(is)h(stored)f(as)h(a)g +(\003oat)g(number)-5 b(.)-189 3095 y Fi(2.1.3)99 b(Binary)25 +b(F)n(ormat)-189 3283 y Fl(The)h(binary)g(format)f(is)h(not)f(allo)n +(wed)g(for)i(ADDs.)33 b(As)26 b(a)h(consequence)f(we)g(concentrate)g +(only)f(on)h(BDDs)g(in)g(this)-189 3403 y(section.)k(In)25 +b(binary)f(mode)h(nodes)f(are)i(represented)f(as)g(a)g(sequence)g(of)g +(bytes,)f(encoding)g(tuples)-189 3606 y Fg()-189 +3727 y([])-189 3847 y([])-189 +3968 y([])-189 4171 y Fl(in)30 b(an)g(optimized)f(w)o(ay)-6 +b(.)46 b(Only)29 b(the)h(\002rst)g(byte)g(\(code\))h(is)e(mandatory)-6 +b(,)30 b(while)g(inte)o(ger)f(inde)o(x)o(es)g(are)i(represented)-189 +4291 y(in)c(absolute)f(or)h(relati)n(v)o(e)f(mode,)h(where)h(relati)n +(v)o(e)e(means)g(of)n(fset)h(with)f(respect)i(to)e(a)i(Then/Else)e +(node)h(info.)37 b(The)-189 4412 y(best)23 b(between)g(absolute)f(and)h +(relati)n(v)o(e)e(representation)i(is)f(chosen)h(and)g(relati)n(v)o(e)f +(1)h(is)f(directly)g(coded)h(in)g Fd(<)p Fl(Node-)-189 +4532 y(code)p Fd(>)e Fl(without)f(an)o(y)g(e)o(xtra)h(info.)29 +b(Suppose)21 b(V)-11 b(ar\(NodeId\),)22 b(Then\(NodeId\))f(and)g +(Else\(NodeId\))f(represent)i(infos)-189 4652 y(about)i(a)h(gi)n(v)o +(en)f(node.)30 b Fd(<)p Fl(Node-code)p Fd(>)25 b Fl(is)f(a)h(byte)g +(which)f(contains)g(the)h(follo)n(wing)e(bit)h(\002elds)h(\(MSB)g(to)g +(LSB\))-44 4856 y Fk(\017)49 b Fl(Unused)24 b(:)31 b(1)24 +b(bit)-44 5059 y Fk(\017)49 b Fl(V)-11 b(ariable:)30 +b(2)25 b(bits,)f(one)h(of)g(the)f(follo)n(wing)f(codes)171 +5288 y Fi(\226)49 b Fl(DDDMP)p 636 5288 30 4 v 35 w(ABSOLUTE)p +1191 5288 V 36 w(ID:)22 b(V)-11 b(ar\(NodeId\))22 b(is)f(represented)h +(in)g(absolute)f(form)g(as)h Fd(<)p Fl(V)-11 b(ar)n(-internal-)270 +5408 y(info)p Fd(>)24 b Fl(=)h(V)-11 b(ar\(NodeId\))25 +b(follo)n(ws)e(\(absolute)i(info\))1794 5800 y(4)p eop +%%Page: 5 5 +5 4 bop 171 218 a Fi(\226)49 b Fl(DDDMP)p 636 218 30 +4 v 35 w(RELA)-11 b(TIVE)p 1147 218 V 36 w(ID:)32 b(V)-11 +b(ar\(NodeId\))32 b(is)g(represented)g(in)f(relati)n(v)o(e)g(form)h(as) +g Fd(<)p Fl(V)-11 b(ar)n(-internal-)270 338 y(info\277)24 +b(=)h(Min\(V)-11 b(ar\(Then\(NodeId\)\),V)g(ar\(Else\(NodeId\)\)\)-V)g +(ar\(NodeId\))171 500 y Fi(\226)49 b Fl(DDDMP)p 636 500 +V 35 w(RELA)-11 b(TIVE)p 1147 500 V 36 w(1:)27 b(the)19 +b(\002eld)g Fd(<)p Fl(V)-11 b(ar)n(-internal-info)p Fd(>)18 +b Fl(does)h(not)f(follo)n(w)-6 b(,)18 b(because)h(V)-11 +b(ar\(NodeId\))270 620 y(=)25 b(Min\(V)-11 b(ar\(Then\(NodeId\)\),V)g +(ar\(Else\(NodeId\)\)\)-1)171 782 y Fi(\226)49 b Fl(DDDMP)p +636 782 V 35 w(TERMIN)m(AL:)24 b(Node)h(is)f(a)h(terminal,)f(no)g(v)n +(ar)h(info)g(required)-44 1011 y Fk(\017)49 b Fl(T)25 +b(:)f(2)h(bits,)f(with)g(codes)h(similar)e(to)i(V)171 +1214 y Fi(\226)49 b Fl(DDDMP)p 636 1214 V 35 w(ABSOLUTE)p +1191 1214 V 36 w(ID:)20 b Fd(<)p Fl(Then-info)p Fd(>)f +Fl(is)h(represented)g(in)g(absolute)f(form)h(as)g Fd(<)p +Fl(Then-info)p Fd(>)270 1334 y Fl(=)25 b(Then\(NodeId\))171 +1496 y Fi(\226)49 b Fl(DDDMP)p 636 1496 V 35 w(RELA)-11 +b(TIVE)p 1147 1496 V 36 w(ID:)28 b(Then\(NodeId\))f(is)g(represented)h +(in)g(relati)n(v)o(e)e(form)i(as)g Fd(<)p Fl(Then-info)p +Fd(>)270 1617 y Fl(=)d(Nodeid-Then\(NodeId\))171 1779 +y Fi(\226)49 b Fl(DDDMP)p 636 1779 V 35 w(RELA)-11 b(TIVE)p +1147 1779 V 36 w(1:)30 b(no)25 b Fd(<)p Fl(Then-info)p +Fd(>)f Fl(follo)n(ws,)f(because)i(Then\(NodeId\))g(=)g(NodeId-1)171 +1941 y Fi(\226)49 b Fl(DDDMP)p 636 1941 V 35 w(TERMIN)m(AL:)24 +b(Then)h(Node)f(is)h(a)g(terminal,)f(no)g(info)h(required)f(\(for)i(R)l +(OBDDs\))-44 2144 y Fk(\017)49 b Fl(Ecompl)24 b(:)30 +b(1)25 b(bit,)f(if)h(1)g(means)f(that)g(the)h(else)g(edge)g(is)f +(complemented)-44 2347 y Fk(\017)49 b Fl(E)25 b(:)f(2)h(bits,)f(with)g +(codes)h(and)f(meanings)g(as)h(for)g(the)g(Then)f(edge)-189 +2551 y(DD)35 b(node)f(codes)h(are)h(written)e(as)h(one)g(byte.)60 +b Fd(<)p Fl(V)-11 b(ar)n(-internal-inde)o(x)p Fd(>)p +Fl(,)36 b Fd(<)p Fl(Then-inde)o(x)p Fd(>)p Fl(,)g Fd(<)p +Fl(Else-inde)o(x)p Fd(>)e Fl(\(if)-189 2671 y(required\))25 +b(are)h(represented)f(as)g(unsigned)e(inte)o(ger)h(v)n(alues)g(on)h(a)g +(suf)n(\002cient)f(set)h(of)g(bytes)f(\(MSByte)h(\002rst\).)47 +2792 y(Inte)o(gers)h(of)f(an)o(y)h(length)e(are)j(written)e(as)h +(sequences)g(of)g(\224link)o(ed\224)f(bytes)g(\(MSByte)h(\002rst\).)34 +b(F)o(or)26 b(each)g(byte)-189 2912 y(7)f(bits)f(are)h(used)g(for)g +(data)g(and)f(one)h(\(MSBit\))g(as)g(link)f(with)g(a)h(further)g(byte)g +(\(MSB)g(=)g(1)g(means)f(one)h(more)g(byte\).)47 3032 +y(Lo)n(w)f(le)n(v)o(el)g(read/write)h(of)g(bytes)f(\002lters)h +Fd(<)p Fl(CR)p Fd(>)p Fl(,)g Fd(<)p Fl(LF)p Fd(>)g Fl(and)g +Fd(<)p Fl(ctrl-Z)p Fd(>)f Fl(through)g(escape)h(sequences.)-189 +3327 y Fj(2.2)119 b(Implementation)-189 3515 y Fl(Store)24 +b(and)g(load)g(for)g(single)g(Boolean)g(functions)f(and)h(arrays)g(of)g +(Boolean)g(functions)f(are)i(implemented.)k(More-)-189 +3635 y(o)o(v)o(er)l(,)37 b(the)e(current)h(presentation)f(includes)f +(functions)h(to)g(retrie)n(v)o(e)g(v)n(ariables)f(names,)k(auxiliary)d +(identi\002erss,)-189 3756 y(and)c(all)g(the)g(information)f(contained) +h(in)f(the)h(header)h(of)f(the)h(\002les.)50 b(This)30 +b(information)g(can)h(be)h(used)f(as)g(a)g(pre-)-189 +3876 y(processing)19 b(step)g(for)i(load)e(operations.)28 +b(These)20 b(functions)f(allo)n(w)f(to)i(o)o(v)o(ercome)f(fe)n(w)g +(limitations)f(of)h(the)h(pre)n(vious)-189 3997 y(implementations.)-189 +4263 y Fi(2.2.1)99 b(Storing)25 b(Decision)g(Diagrams)-189 +4450 y Fc(Dddmp)p 111 4450 V 35 w(cuddBddStor)l(e)f Fl(and)h +Fc(Dddmp)p 1195 4450 V 35 w(cuddBddArr)o(ayStor)l(e)e +Fl(are)j(the)f(tw)o(o)f(store)h(functions,)f(used)h(to)g(store)f(sin-) +-189 4571 y(gle)f(BDD)h(or)g(a)f(forest)h(of)f(BDDs,)h(respecti)n(v)o +(ely)-6 b(.)28 b(Internally)-6 b(,)23 b Fc(Dddmp)p 2275 +4571 V 35 w(cuddBddStor)l(e)f Fl(b)n(uilds)g(a)i(dummy)e(1)h(entry)-189 +4691 y(array)j(of)e(BDDs,)h(and)g(calls)g Fc(dddmp)p +1102 4691 V 35 w(cuddBddArr)o(ayStor)l(e)p Fl(.)47 4811 +y(Since)30 b(con)l(v)o(ersion)e(from)h(DD)h(pointers)e(to)h(inte)o(ger) +f(is)h(required,)i(DD)e(nodes)g(are)h(temporarily)e(remo)o(v)o(ed)-189 +4932 y(from)23 b(the)f(unique)h(hash.)29 b(This)23 b(mak)o(es)f(room)g +(in)h(their)f Fc(ne)n(xt)h Fl(\002eld)h(to)e(store)h(node)f(IDs.)30 +b(Nodes)23 b(are)h(re-link)o(ed)e(after)-189 5052 y(the)i(store)g +(operation,)g(possible)f(in)g(a)i(modi\002ed)e(order)-5 +b(.)31 b(Dumping)22 b(is)i(either)g(in)g(te)o(xt)f(or)i(binary)f(form.) +30 b(Both)24 b(a)g(\002le)-189 5173 y(pointer)31 b(\()p +Fc(fp)p Fl(\))g(and)g(a)h(\002le)g(name)f(\()p Fc(fname)p +Fl(\))h(are)g(pro)o(vided)e(as)h(inputs)f(parameters)i(to)f(store)g +(routines.)50 b(BDDs)31 b(are)-189 5293 y(stored)c(to)g(the)g(already)g +(open)h(\002le)f Fc(fp)p Fl(,)h(if)f(not)g(NULL.)g(Otherwise)f(\002le)i +(whose)f(name)g(is)g Fc(fname)g Fl(is)g(opened.)38 b(This)-189 +5413 y(is)24 b(intended)g(to)h(allo)n(w)f(either)g(DD)h(storage)g +(within)e(\002les)i(containing)f(other)g(data,)h(or)g(to)g(speci\002c)g +(\002les.)1794 5800 y(5)p eop +%%Page: 6 6 +6 5 bop -189 218 a Fi(2.2.2)99 b(Loading)25 b(Decision)g(Diagrams)-189 +405 y Fc(Dddmp)p 111 405 30 4 v 35 w(cuddBddLoad)37 b +Fl(and)h Fc(Dddmp)p 1219 405 V 35 w(cuddBddArr)o(ayLoad)f +Fl(are)h(the)g(load)g(functions,)i(which)e(read)g(a)g(BDD)-189 +526 y(dump)24 b(\002le.)47 646 y(F)o(ollo)n(wing)34 b(the)h(store)h +(function,)h(the)f(main)f(BDD)h(load)f(function,)j Fc(Dddmp)p +2813 646 V 35 w(cuddBddLoad)p Fl(,)f(is)f(imple-)-189 +767 y(mented)g(by)g(calling)f(the)h(main)g(BDD-array)h(loading)f +(function)f Fc(Dddmp)p 2466 767 V 35 w(cuddBddArr)o(ayLoad)p +Fl(.)63 b(A)37 b(dynamic)-189 887 y(v)o(ector)24 b(of)h(DD)g(pointers)f +(is)g(temporarily)g(allocated)h(to)f(support)g(con)l(v)o(ersion)f(from) +i(DD)g(inde)o(x)o(es)e(to)h(pointers.)47 1007 y(Se)n(v)o(eral)40 +b(criteria)f(are)i(supported)d(for)i(v)n(ariable)f(match)g(between)g +(\002le)h(and)g(DD)f(manager)l(,)k(practically)-189 1128 +y(allo)n(wing)37 b(v)n(ariable)h(permutations)f(or)i(compositions)d +(while)i(loading)g(DDs.)71 b(V)-11 b(ariable)39 b(match)f(between)h +(the)-189 1248 y(DD)32 b(manager)g(and)g(the)g(BDD)g(\002le)g(is)g +(optionally)e(based)i(in)f Fc(IDs)p Fl(,)j Fc(perids)p +Fl(,)f Fc(varnames)p Fl(,)g Fc(var)o(auxids)p Fl(;)g(also)f(direct)-189 +1369 y(composition)j(between)j Fc(IDs)g Fl(and)f Fc(composeids)g +Fl(is)g(supported.)68 b(The)38 b Fc(varmatc)o(hmode)e +Fl(parameter)i(is)f(used)g(to)-189 1489 y(select)27 b(mathing)e(mode.) +37 b(More)27 b(in)f(detail,)h(tw)o(o)f(match)h(modes)f(use)h(the)f +(information)g(within)f(the)i(DD)g(manager)l(,)-189 1609 +y(the)e(other)f(ones)h(use)g(e)o(xtra)f(information,)f(which)i(support) +f(an)o(y)g(v)n(ariable)g(remap)h(or)g(change)g(in)f(the)h(ordering.)-44 +1813 y Fk(\017)49 b Fl(v)n(armatchnode=DDDMP)p 1040 1813 +V 35 w(V)-13 b(AR)p 1272 1813 V 35 w(MA)i(TCHIDS)19 b(allo)n(ws)f +(loading)g(a)h(DD)g(k)o(eeping)f(v)n(ariable)g(IDs)h(unchanged)55 +1933 y(\(re)o(gardless)24 b(of)h(the)f(v)n(ariable)h(ordering)f(of)h +(the)g(reading)f(manager)-5 b(.)55 2095 y(This)24 b(is)g(useful,)g(for) +h(e)o(xample,)f(when)g(sw)o(apping)g(DDs)g(to)h(\002le)g(and)f +(restoring)g(them)g(later)h(from)f(\002le,)h(after)55 +2215 y(possible)e(v)n(ariable)i(reordering)g(acti)n(v)n(ations.)-44 +2419 y Fk(\017)49 b Fl(v)n(armatchnode=DDDMP)p 1040 2419 +V 35 w(V)-13 b(AR)p 1272 2419 V 35 w(MA)i(TCHPERMIDS)36 +b(is)e(used)h(to)f(allo)n(w)g(v)n(ariable)g(match)h(according)55 +2539 y(to)h(the)h(position)e(in)i(the)g(ordering)f(\(retrie)n(v)o(ed)g +(by)h(array)h(of)f(permutations)e(stored)h(on)h(\002le)g(and)g(within) +55 2660 y(the)h(reading)g(DD)h(manager\).)72 b(A)38 b(possible)f +(application)h(is)g(retrie)n(ving)f(BDDs)i(stored)f(after)h(dynamic)55 +2780 y(reordering,)28 b(from)g(a)g(DD)g(manager)g(where)h(all)e(v)n +(ariable)h(IDs)f(map)h(their)f(position)g(in)g(the)h(ordering,)g(and)55 +2900 y(the)d(loaded)f(BDD)h(k)o(eeps)g(the)g(ordering)f(as)h(stored)f +(on)h(\002le.)-44 3104 y Fk(\017)49 b Fl(v)n(armatchnode=DDDMP)p +1040 3104 V 35 w(V)-13 b(AR)p 1272 3104 V 35 w(MA)i(TCHN)m(AMES)26 +b(requires)h(a)h(not)e(NULL)h(v)n(armatchmodes)f(param-)55 +3224 y(eter;)34 b(this)c(is)g(a)h(v)o(ector)g(of)g(strings)e(in)i +(one-to-one)f(correspondence)h(with)f(v)n(ariable)h(IDs)f(of)h(the)g +(reading)55 3344 y(manager)-5 b(.)40 b(V)-11 b(ariables)28 +b(in)g(the)g(DD)g(\002le)g(read)h(are)g(matched)f(with)f(manager)h(v)n +(ariables)f(according)h(to)g(their)55 3465 y(name)35 +b(\(a)h(not)f(NULL)g(v)n(arnames)g(parameter)h(w)o(as)f(required)h +(while)f(storing)f(the)h(DD)g(\002le\).)64 b(The)35 b(most)55 +3585 y(common)c(usage)h(of)g(this)f(feature)i(is)e(in)h(combination)e +(with)i(a)g(v)n(ariable)g(ordering)g(stored)f(on)h(a)g(\002le)h(and)55 +3706 y(based)28 b(on)h(v)n(ariables)f(names.)41 b(Names)29 +b(must)e(be)i(loaded)f(in)g(an)h(array)g(of)g(strings)e(and)i(passed)f +(to)g(the)h(DD)55 3826 y(load)24 b(procedure.)-44 4029 +y Fk(\017)49 b Fl(v)n(armatchnode=DDDMP)p 1040 4029 V +35 w(V)-13 b(AR)p 1272 4029 V 35 w(MA)i(TCHIDS)25 b(has)g(a)g(meaning)f +(similar)g(to)55 4150 y(DDDMP)p 421 4150 V 36 w(V)-13 +b(AR)p 654 4150 V 35 w(MA)i(TCHN)m(AMES)26 b(b)n(ut)h(inte)o(ger)f +(auxiliary)g(IDs)h(are)h(used)f(instead)f(of)h(strings.)36 +b(The)28 b(ad-)55 4270 y(ditional)23 b(not)h(NULL)h(v)n(armathauxids)e +(parameter)i(is)g(needed.)-44 4474 y Fk(\017)49 b Fl(v)n +(armatchnode=DDDMP)p 1040 4474 V 35 w(V)-13 b(AR)p 1272 +4474 V 35 w(COMPOSEIDS,)38 b(uses)f(the)f(additional)f(v)n +(arcomposeids)g(parameter)55 4594 y(as)25 b(an)g(array)g(of)g(v)n +(ariable)f(IDs)h(to)g(be)g(composed)f(with)g(IDs)g(stored)h(in)f +(\002le.)-189 4860 y Fi(2.2.3)99 b(DD)25 b(Load/Stor)n(e)h(and)f(V)-9 +b(ariable)25 b(Ordering)-189 5048 y Fl(Loading)31 b(of)i(Decision)e +(Diagrams)h(from)g(\002le)g(supports)f(dif)n(ferent)h(v)n(ariables)g +(ordering)f(strate)o(gies,)i(as)g(already)-189 5168 y(pointed)23 +b(out)h(in)g(the)h(pre)n(vious)e(section.)30 b(This)24 +b(allo)n(ws)f(or)h(e)o(xample)g(storing)f(dif)n(ferent)i(BDDs)f(each)h +(with)f(its)g(o)n(wn)-189 5288 y(v)n(ariable)29 b(ordering,)h(and)g(to) +f(mer)n(ge)h(them)f(within)f(the)i(same)f(DD)h(manager)f(by)h(means)f +(of)g(proper)h(load)f(opera-)-189 5409 y(tions.)44 b(W)-8 +b(e)30 b(suggest)f(using)f(DDDMP)p 1175 5409 V 36 w(V)-13 +b(AR)p 1408 5409 V 36 w(MA)i(TCHIDS)30 b(whene)n(v)o(er)f(IDs)g(k)o +(eeps)h(on)f(representing)h(the)f(same)-189 5529 y(entities)24 +b(while)h(changing)f(v)n(ariable)h(ordering.)31 b(If)25 +b(this)f(is)h(not)f(true,)h(v)n(ariable)g(names)g(\(if)g(a)n(v)n +(ailable\))f(or)i(auxiliary)1794 5800 y(6)p eop +%%Page: 7 7 +7 6 bop -189 218 a Fl(IDs)34 b(are)h(a)g(good)e(w)o(ay)i(to)f +(represent)g(in)l(v)n(ariant)f(attrib)n(uted)g(of)i(v)n(ariables)e +(across)h(se)n(v)o(eral)g(runs)g(with)f(dif)n(ferent)-189 +338 y(orderings.)50 b(DDDMP)p 629 338 30 4 v 35 w(V)-13 +b(AR)p 861 338 V 36 w(COMPOSEIDS)32 b(is)f(an)h(alternati)n(v)o(e)e +(solution,)h(that)g(practically)f(corresponds)h(to)-189 +459 y(cascading)23 b(DDDMP)p 593 459 V 36 w(V)-13 b(AR)p +826 459 V 36 w(MA)i(TCHIDS)23 b(and)h(v)n(ariable)f(composition)e(with) +h(a)i(gi)n(v)o(en)e(array)i(of)g(ne)n(w)f(v)n(ariables.)-189 +797 y Fo(3)143 b(CNF)35 b(Support)-189 1050 y Fj(3.1)119 +b(F)m(ormat)-189 1237 y Fl(Gi)n(v)o(en)30 b(a)h(BDD)g(representing)g(a) +g(function)f Fd(f)11 b Fl(,)32 b(we)f(de)n(v)o(elop)f(three)h(basic)g +(possible)e(w)o(ays)i(to)g(store)f(it)h(as)g(a)g(CNF)-189 +1358 y(formula.)54 b(In)33 b(each)h(method)d(the)i(set)g(of)f(clauses)h +(is)f(written)h(after)g(an)g(header)g(part.)55 b(Only)32 +b(the)h(te)o(xt)f(format)g(is)-189 1478 y(allo)n(wed.)-189 +1743 y Fi(3.1.1)99 b(Header)-189 1931 y Fl(The)23 b(header)h(part)f(of) +g(each)h(CNF)g(\002le)f(has)g(basically)g(the)f(same)h(format)g +(analyzed)g(for)h(the)f(BDD/ADD)g(\002les.)30 b(F)o(or)-189 +2051 y(e)o(xample)h(the)g Fg(.rootids)f Fl(line)h(indicates)f(the)i(be) +o(ginning)d(of)j(each)g(CNF)g(formula)f(represented)h(by)f(a)h(single) +-189 2172 y(BDD.)j(T)-8 b(o)34 b(be)g(compatible)f(with)h(the)g(DIMA)l +(CS)h(format)f(each)h(header)f(line)g(start)g(with)g(the)g(character)h +(\223c\224)g(to)-189 2292 y(indicate)24 b(a)h(comment.)-189 +2557 y Fi(3.1.2)99 b(T)-9 b(ext)25 b(F)n(ormat)-189 2745 +y Fl(The)j(\002rst)g(method,)g(which)f(we)h(call)g Fi(Single-Node-Cut)p +Fl(,)j(models)26 b(each)j(BDD)f(nodes,)h(b)n(ut)e(the)h(ones)f(with)h +(both)-189 2865 y(the)c(children)g(equal)h(to)f(the)g(constant)g(node)g +Fb(1)p Fl(,)g(as)h(a)g(multiple)o(x)o(er)-5 b(.)27 b(Each)e(multiple)o +(x)o(er)d(has)i(tw)o(o)g(data)h(inputs)e(\(i.e.,)-189 +2985 y(the)k(node)h(children\),)f(a)h(selection)f(input)f(\(i.e.,)i +(the)g(node)f(v)n(ariable\))g(and)h(one)f(output)f(\(i.e.,)i(the)g +(function)e(v)n(alue\))-189 3106 y(whose)h(v)n(alue)f(is)h(assigned)f +(to)h(an)g(additional)f(CNF)i(v)n(ariable.)37 b(The)27 +b(\002nal)h(number)e(of)h(v)n(ariables)g(is)f(equal)h(to)g(the)-189 +3226 y(number)d(of)h(original)f(BDD)h(v)n(ariables)f(plus)g(the)h +(number)f(of)h(\223internal\224)g(nodes)f(of)h(the)g(BDD.)47 +3346 y(The)k(second)f(method,)g(which)h(we)f(call)h Fi(Maxterm-Cut)p +Fl(,)h(create)g(clauses)e(starting)g(from)g Fd(f)39 b +Fl(corresponds)-189 3467 y(to)25 b(the)h(of)n(f-set)g(\(i.e.,)f(all)h +(the)g(paths-cubes)f(from)g(the)h(root)g(node)f(to)h(the)f(terminal)g +Fg(0)p Fl(\))h(of)g(the)g(function)e Fd(f)11 b Fl(.)34 +b(W)l(ithin)-189 3587 y(the)29 b(BDD)g(for)g Fd(f)11 +b Fl(,)30 b(such)f(clauses)f(are)i(found)e(by)h(follo)n(wing)e(all)i +(the)f(paths)h(from)f(the)h(root)g(node)f(of)h(the)g(BDD)g(to)-189 +3708 y(the)c(constant)f(node)g Fb(0)p Fl(.)31 b(The)25 +b(\002nal)g(number)f(of)h(v)n(ariables)f(is)g(equal)h(to)f(the)h +(number)f(of)h(original)f(BDD)h(v)n(ariables.)47 3828 +y(The)k(third)g(method,)g(which)g(we)g(call)g Fi(A)-5 +b(uxiliary-V)c(ariable-Cut)p Fl(,)30 b(is)f(a)h(trade-of)n(f)f(between) +g(the)g(\002rst)g(tw)o(o)-189 3948 y(strate)o(gies.)69 +b(Internal)37 b(v)n(ariables,)j(i.e.,)h(cutting)c(points,)j(are)e +(added)g(in)f(order)h(to)g(decompose)f(the)h(BDD)g(into)-189 +4069 y(multiple)27 b(sub-trees)i(each)h(of)f(which)f(is)h(stored)g +(follo)n(wing)e(the)h(second)h(strate)o(gy)-6 b(.)42 +b(The)29 b(trade-of)n(f)g(is)g(guided)f(by)-189 4189 +y(the)23 b(cutting)f(point)g(selection)g(strate)o(gy)-6 +b(,)22 b(and)h(we)g(e)o(xperiment)f(with)g(tw)o(o)g(methodologies.)28 +b(In)23 b(the)g(\002rst)g(method,)g(a)-189 4310 y(ne)n(w)f(CNF)h(v)n +(ariable)f(is)f(inserted)h(in)g(correspondence)g(to)g(the)g(shared)g +(nodes)g(of)g(the)h(BDD,)f(i.e.,)h(the)f(nodes)f(which)-189 +4430 y(ha)n(v)o(e)29 b(more)g(than)h(one)f(incoming)f(edge.)45 +b(This)29 b(technique,)h(albeit)e(optimizing)g(the)h(number)g(of)h +(literals)e(stored,)-189 4550 y(can)35 b(produce)g(clauses)f(with)g(a)h +(high)f(number)h(of)f(literals)1894 4514 y Fh(2)1933 +4550 y Fl(.)60 b(T)-8 b(o)35 b(a)n(v)n(oid)f(this)g(dra)o(wback,)j(the) +e(second)f(method,)-189 4671 y(introduces)28 b(all)g(the)g(pre)n +(viously)e(indicated)i(cutting)f(points)g(more)h(the)h(ones)f +(necessary)g(to)g(break)h(the)f(length)g(of)-189 4791 +y(the)d(path)f(to)h(a)g(maximum)e(\(user\))i(selected)g(v)n(alue.)47 +4911 y(Actually)-6 b(,)37 b(all)f(the)f(methods)g(described)h(abo)o(v)o +(e)e(can)j(be)e(re-conducted)h(to)g(the)f(basic)h(idea)g(of)g(possibly) +-189 5032 y(breaking)24 b(the)h(BDD)g(through)f(the)g(use)h(of)f +(additional)g(cutting)f(v)n(ariables)h(and)h(dumping)e(the)h(paths)g +(between)h(the)-189 5152 y(root)34 b(of)h(the)f(BDD,)h(the)g(cutting)e +(v)n(ariables)h(and)g(the)h(terminal)e(nodes.)60 b(Such)35 +b(internal)f(cutting)f(v)n(ariables)h(are)-189 5273 y(added)25 +b(al)o(w)o(ays)f(\(for)i(each)f(node\),)g(ne)n(v)o(er)f(or)h(sometimes) +e(respecti)n(v)o(ely)-6 b(.)p -189 5360 1607 4 v -77 +5422 a Ff(2)-40 5452 y Fe(This)27 b(v)n(alue)f(is)i(superiorly)d +(limited)h(by)g(the)h(number)e(of)h(v)n(ariables)g(of)g(the)h(BDD,)g +(i.e.,)h(the)f(longest)f(path)g(from)g(the)h(root)f(to)g(the)-189 +5551 y(terminal)19 b(node.)1794 5800 y Fl(7)p eop +%%Page: 8 8 +8 7 bop 47 218 a Fl(While)33 b(the)f Fc(Single-Node-Cut)h +Fl(method)f(minimizes)f(the)i(length)f(of)h(the)f(clauses)h(produced,)i +(b)n(ut)d(it)g(also)-189 338 y(requires)d(the)h(higher)f(number)g(of)g +(CNF)i(v)n(ariables,)e(the)h Fc(Maxterm-Cut)f Fl(technique)g(minimizes) +f(the)h(number)g(of)-189 459 y(CNF)36 b(v)n(ariables)d(required.)61 +b(This)34 b(adv)n(antage)g(is)g(counter)n(-balanced)h(by)f(the)h(f)o +(act)g(that)f(in)g(the)h(w)o(orst)f(case)h(the)-189 579 +y(number)23 b(of)g(clauses,)g(as)h(well)e(as)i(the)f(total)f(number)h +(of)g(literals,)g(produced)g(is)g(e)o(xponential)e(in)i(the)g(BDD)h +(size)f(\(in)-189 699 y(terms)28 b(of)i(number)e(of)h(nodes\).)43 +b(The)29 b(application)f(of)h(this)f(method)g(is)g(then)h(limited)e(to) +i(the)g(cases)g(in)f(which)h(the)-189 820 y(\223of)n(f-set\224)c(of)f +(the)g(represented)h(function)f Fd(f)35 b Fl(has)24 b(a)h(small)f +(cardinality)-6 b(.)29 b(The)c Fc(A)n(uxiliary-V)-11 +b(ariable-Cut)22 b Fl(strate)o(gy)h(is)-189 940 y(a)k(trade-of)n(f)h +(between)f(the)g(\002rst)g(tw)o(o)g(methods)f(and)h(the)g(ones)f(which) +h(gi)n(v)o(es)f(more)h(compact)f(results.)37 b(As)27 +b(a)h(\002nal)-189 1061 y(remark)f(notice)e(that)h(the)g(method)g(is)f +(able)i(to)f(store)g(both)f(monolithic)f(BDDs)j(and)f(conjuncti)n(v)o +(e)e(forms.)35 b(In)26 b(each)-189 1181 y(case)f(we)g(generate)h(CNF)f +(\002les)g(using)f(the)h(standard)f(DIMA)l(CS)i(format.)-189 +1365 y Fi(Example)f(1)49 b Fc(F)l(igur)l(e)20 b(1)h(shows)f(an)h(e)n +(xample)g(of)f(how)h(our)f(pr)l(ocedur)l(e)h(works)f(to)h(stor)l(e)f(a) +h(small)f(monolithic)f(BDD.)-189 1486 y(F)l(igur)l(e)j(1\(a\))h(r)l +(epr)l(esents)g(a)g(BDD)g(with)g Fb(4)g Fc(nodes.)30 +b(BDD)23 b(variables)f(ar)l(e)h(named)g(after)f(inte)l(g)o(er)g(number) +o(s)h(r)o(anging)-189 1606 y(fr)l(om)k Fb(1)h Fc(to)g +Fb(4)p Fc(,)h(to)f(have)g(an)g(easy-to-follow)f(corr)l(espondence)h +(with)g(the)g(CNF)h(variables.)40 b(F)l(igur)l(e)27 b(1\(b\),)i(\(c\))g +(and)-189 1727 y(\(d\))c(show)g(the)f(corr)l(esponding)f(CNF)j(r)l(epr) +l(esentations)d(g)o(ener)o(ated)h(by)h(our)f(thr)l(ee)h(methods.)30 +b(As)24 b(in)h(the)f(standar)l(d)-189 1847 y(format)i +Fa(p)i Fc(indicates)e(the)h(total)f(number)g(of)h(variables)f(used)h +(\()p Fb(4)g Fc(is)g(the)g(minimum)f(value)h(as)g(the)g(BDD)g(itself)f +(has)-189 1967 y Fb(4)f Fc(variables\),)e(and)i Fa(cnf)g +Fc(the)f(total)g(number)g(of)h(clauses.)47 2088 y(As)i(a)g(\002nal)f(r) +l(emark)h(notice)f(that)g(for)g(this)g(speci\002c)h(e)n(xample)g(the)f +(\223Maxterm-Cut\224)i(appr)l(oac)o(h)d(is)h(the)h(one)-189 +2208 y(whic)o(h)36 b(gives)g(the)g(most)f(compact)h(CNF)h(r)l(epr)l +(esentation)e(b)n(ut)h(also)f(the)h(clause)g(with)g(the)g(lar)l(g)o +(est)g(number)f(of)-189 2328 y(liter)o(als)23 b(\()p +Fb(4)p Fc(\).)188 2471 y + 6339814 10777681 0 0 11709153 19997655 startTexFig + 188 2471 a +%%BeginDocument: bdd.eps +%!PS-Adobe-2.0 EPSF-2.0 +%%Title: bdd.eps +%%Creator: fig2dev Version 3.2 Patchlevel 3c +%%CreationDate: Mon Sep 9 14:21:26 2002 +%%For: quer@pcsq (Stefano Quer) +%%BoundingBox: 0 0 178 304 +%%Magnification: 1.0000 +%%EndComments +/$F2psDict 200 dict def +$F2psDict begin +$F2psDict /mtrx matrix put +/col-1 {0 setgray} bind def +/col0 {0.000 0.000 0.000 srgb} bind def +/col1 {0.000 0.000 1.000 srgb} bind def +/col2 {0.000 1.000 0.000 srgb} bind def +/col3 {0.000 1.000 1.000 srgb} bind def +/col4 {1.000 0.000 0.000 srgb} bind def +/col5 {1.000 0.000 1.000 srgb} bind def +/col6 {1.000 1.000 0.000 srgb} bind def +/col7 {1.000 1.000 1.000 srgb} bind def +/col8 {0.000 0.000 0.560 srgb} bind def +/col9 {0.000 0.000 0.690 srgb} bind def +/col10 {0.000 0.000 0.820 srgb} bind def +/col11 {0.530 0.810 1.000 srgb} bind def +/col12 {0.000 0.560 0.000 srgb} bind def +/col13 {0.000 0.690 0.000 srgb} bind def +/col14 {0.000 0.820 0.000 srgb} bind def +/col15 {0.000 0.560 0.560 srgb} bind def +/col16 {0.000 0.690 0.690 srgb} bind def +/col17 {0.000 0.820 0.820 srgb} bind def +/col18 {0.560 0.000 0.000 srgb} bind def +/col19 {0.690 0.000 0.000 srgb} bind def +/col20 {0.820 0.000 0.000 srgb} bind def +/col21 {0.560 0.000 0.560 srgb} bind def +/col22 {0.690 0.000 0.690 srgb} bind def +/col23 {0.820 0.000 0.820 srgb} bind def +/col24 {0.500 0.190 0.000 srgb} bind def +/col25 {0.630 0.250 0.000 srgb} bind def +/col26 {0.750 0.380 0.000 srgb} bind def +/col27 {1.000 0.500 0.500 srgb} bind def +/col28 {1.000 0.630 0.630 srgb} bind def +/col29 {1.000 0.750 0.750 srgb} bind def +/col30 {1.000 0.880 0.880 srgb} bind def +/col31 {1.000 0.840 0.000 srgb} bind def + +end +save +newpath 0 304 moveto 0 0 lineto 178 0 lineto 178 304 lineto closepath clip newpath +-51.0 319.0 translate +1 -1 scale + +/cp {closepath} bind def +/ef {eofill} bind def +/gr {grestore} bind def +/gs {gsave} bind def +/sa {save} bind def +/rs {restore} bind def +/l {lineto} bind def +/m {moveto} bind def +/rm {rmoveto} bind def +/n {newpath} bind def +/s {stroke} bind def +/sh {show} bind def +/slc {setlinecap} bind def +/slj {setlinejoin} bind def +/slw {setlinewidth} bind def +/srgb {setrgbcolor} bind def +/rot {rotate} bind def +/sc {scale} bind def +/sd {setdash} bind def +/ff {findfont} bind def +/sf {setfont} bind def +/scf {scalefont} bind def +/sw {stringwidth} bind def +/tr {translate} bind def +/tnt {dup dup currentrgbcolor + 4 -2 roll dup 1 exch sub 3 -1 roll mul add + 4 -2 roll dup 1 exch sub 3 -1 roll mul add + 4 -2 roll dup 1 exch sub 3 -1 roll mul add srgb} + bind def +/shd {dup dup currentrgbcolor 4 -2 roll mul 4 -2 roll mul + 4 -2 roll mul srgb} bind def + /DrawEllipse { + /endangle exch def + /startangle exch def + /yrad exch def + /xrad exch def + /y exch def + /x exch def + /savematrix mtrx currentmatrix def + x y tr xrad yrad sc 0 0 1 startangle endangle arc + closepath + savematrix setmatrix + } def + +/$F2psBegin {$F2psDict begin /$F2psEnteredState save def} def +/$F2psEnd {$F2psEnteredState restore end} def + +$F2psBegin +%%Page: 1 1 +10 setmiterlimit + 0.06299 0.06299 sc +% +% Fig objects follow +% +% Polyline +15.000 slw +n 2010 4515 m 2550 4515 l 2550 5040 l 2010 5040 l + cp gs col0 s gr +/Times-Roman ff 300.00 scf sf +2205 4875 m +gs 1 -1 sc (1) col0 sh gr +% Ellipse +n 1515 1800 270 270 0 360 DrawEllipse gs col0 s gr + +% Ellipse +n 2250 900 270 270 0 360 DrawEllipse gs col0 s gr + +% Ellipse +n 2970 2715 270 270 0 360 DrawEllipse gs col0 s gr + +% Ellipse +n 2280 3705 270 270 0 360 DrawEllipse gs col0 s gr + +7.500 slw +% Ellipse +n 3555 3555 64 64 0 360 DrawEllipse gs 0.00 setgray ef gr gs col0 s gr + +% Ellipse +n 2712 1726 64 64 0 360 DrawEllipse gs 0.00 setgray ef gr gs col0 s gr + +% Ellipse +n 2430 4230 64 64 0 360 DrawEllipse gs 0.00 setgray ef gr gs col0 s gr + +% Polyline +15.000 slw +n 2805 2910 m + 2250 3450 l gs col0 s gr +% Polyline + [90] 0 sd +gs clippath +2940 2472 m 3010 2445 l 2931 2239 l 2957 2411 l 2861 2266 l cp +eoclip +n 2460 1110 m + 2970 2445 l gs col0 s gr gr + [] 0 sd +% arrowhead +n 2861 2266 m 2957 2411 l 2931 2239 l 2908 2284 l 2861 2266 l + cp gs 0.00 setgray ef gr col0 s +% Polyline +gs clippath +1478 1511 m 1528 1568 l 1693 1422 l 1542 1506 l 1643 1366 l cp +eoclip +n 2025 1080 m + 1515 1530 l gs col0 s gr gr + +% arrowhead +n 1643 1366 m 1542 1506 l 1693 1422 l 1643 1416 l 1643 1366 l + cp gs 0.00 setgray ef gr col0 s +% Polyline +gs clippath +2212 645 m 2287 645 l 2287 425 l 2250 594 l 2212 425 l cp +eoclip +n 2250 270 m + 2250 630 l gs col0 s gr gr + +% arrowhead +n 2212 425 m 2250 594 l 2287 425 l 2250 459 l 2212 425 l + cp gs 0.00 setgray ef gr col0 s +% Polyline + [90] 0 sd +gs clippath +2692 2664 m 2732 2601 l 2546 2485 l 2670 2606 l 2506 2548 l cp +eoclip +n 1710 2010 m + 2700 2625 l gs col0 s gr gr + [] 0 sd +% arrowhead +n 2506 2548 m 2670 2606 l 2546 2485 l 2555 2534 l 2506 2548 l + cp gs 0.00 setgray ef gr col0 s +% Polyline +2 slj + [90] 0 sd +gs clippath +2504 4653 m 2539 4720 l 2733 4616 l 2567 4663 l 2698 4550 l cp +eoclip +n 3180 2910 m 3181 2911 l 3183 2913 l 3186 2916 l 3192 2921 l 3200 2929 l + 3210 2939 l 3223 2951 l 3238 2966 l 3255 2984 l 3274 3003 l + 3295 3025 l 3317 3049 l 3339 3075 l 3362 3103 l 3385 3131 l + 3407 3161 l 3429 3192 l 3450 3225 l 3470 3258 l 3488 3293 l + 3504 3329 l 3519 3367 l 3531 3406 l 3541 3447 l 3548 3490 l + 3552 3536 l 3552 3583 l 3548 3634 l 3540 3686 l 3528 3740 l + 3510 3795 l 3490 3844 l 3467 3892 l 3441 3939 l 3413 3985 l + 3382 4028 l 3350 4070 l 3317 4110 l 3283 4148 l 3248 4184 l + 3211 4219 l 3174 4253 l 3136 4285 l 3098 4316 l 3059 4347 l + 3020 4376 l 2980 4405 l 2941 4432 l 2901 4459 l 2862 4484 l + 2824 4509 l 2787 4532 l 2751 4554 l 2717 4575 l 2686 4593 l + 2657 4610 l 2631 4626 l 2608 4639 l 2589 4650 l 2572 4659 l + 2559 4666 l 2550 4672 l + 2535 4680 l gs col0 s gr gr + [] 0 sd +% arrowhead +0 slj +n 2698 4550 m 2567 4663 l 2733 4616 l 2686 4599 l 2698 4550 l + cp gs 0.00 setgray ef gr col0 s +% Polyline +2 slj +gs clippath +1985 4734 m 2028 4672 l 1847 4548 l 1965 4675 l 1804 4609 l cp +eoclip +n 1350 2025 m 1349 2026 l 1348 2027 l 1345 2030 l 1340 2035 l 1334 2042 l + 1325 2051 l 1314 2063 l 1301 2078 l 1286 2095 l 1268 2114 l + 1249 2137 l 1227 2161 l 1205 2188 l 1181 2218 l 1156 2249 l + 1131 2282 l 1105 2316 l 1080 2352 l 1054 2390 l 1029 2428 l + 1005 2468 l 981 2509 l 959 2552 l 938 2595 l 918 2640 l + 900 2687 l 884 2736 l 870 2786 l 858 2839 l 848 2894 l + 841 2951 l 837 3011 l 836 3074 l 838 3139 l 845 3206 l + 855 3275 l 870 3345 l 888 3412 l 910 3477 l 934 3542 l + 961 3604 l 990 3665 l 1022 3723 l 1054 3779 l 1088 3833 l + 1124 3885 l 1160 3935 l 1198 3983 l 1236 4029 l 1275 4074 l + 1315 4118 l 1356 4160 l 1397 4201 l 1438 4241 l 1480 4280 l + 1522 4318 l 1563 4355 l 1605 4390 l 1645 4424 l 1685 4457 l + 1723 4488 l 1760 4517 l 1795 4545 l 1827 4570 l 1857 4593 l + 1884 4613 l 1909 4632 l 1930 4647 l 1947 4660 l 1962 4671 l + 1973 4679 l 1982 4686 l + 1995 4695 l gs col0 s gr gr + +% arrowhead +0 slj +n 1804 4609 m 1965 4675 l 1847 4548 l 1854 4598 l 1804 4609 l + cp gs 0.00 setgray ef gr col0 s +% Polyline +2 slj + [90] 0 sd +gs clippath +2300 4492 m 2363 4532 l 2481 4347 l 2359 4470 l 2417 4307 l cp +eoclip +n 2340 3960 m 2341 3962 l 2344 3966 l 2348 3973 l 2354 3982 l 2362 3995 l + 2370 4010 l 2379 4028 l 2389 4046 l 2397 4066 l 2406 4088 l + 2413 4111 l 2420 4137 l 2425 4165 l 2429 4197 l 2430 4230 l + 2429 4263 l 2425 4295 l 2420 4323 l 2413 4349 l 2406 4372 l + 2397 4394 l 2389 4414 l 2379 4433 l 2370 4450 l 2362 4465 l + 2354 4478 l + 2340 4500 l gs col0 s gr gr + [] 0 sd +% arrowhead +0 slj +n 2417 4307 m 2359 4470 l 2481 4347 l 2431 4356 l 2417 4307 l + cp gs 0.00 setgray ef gr col0 s +% Polyline +2 slj +gs clippath +2136 4532 m 2199 4492 l 2082 4307 l 2141 4470 l 2018 4347 l cp +eoclip +n 2160 3960 m 2159 3962 l 2156 3966 l 2152 3973 l 2146 3982 l 2138 3995 l + 2130 4010 l 2121 4028 l 2111 4046 l 2103 4066 l 2094 4088 l + 2087 4111 l 2080 4137 l 2075 4165 l 2071 4197 l 2070 4230 l + 2071 4263 l 2075 4295 l 2080 4323 l 2087 4349 l 2094 4372 l + 2103 4394 l 2111 4414 l 2121 4433 l 2130 4450 l 2138 4465 l + 2146 4478 l + 2160 4500 l gs col0 s gr gr + +% arrowhead +0 slj +n 2018 4347 m 2141 4470 l 2082 4307 l 2068 4356 l 2018 4347 l + cp gs 0.00 setgray ef gr col0 s +/Times-Roman ff 300.00 scf sf +2175 990 m +gs 1 -1 sc (1) col0 sh gr +/Times-Roman ff 300.00 scf sf +1440 1890 m +gs 1 -1 sc (2) col0 sh gr +/Times-Roman ff 300.00 scf sf +2895 2805 m +gs 1 -1 sc (3) col0 sh gr +/Times-Roman ff 300.00 scf sf +2205 3795 m +gs 1 -1 sc (4) col0 sh gr +$F2psEnd +rs + +%%EndDocument + + endTexFig + 531 3990 a Fc(\(a\))1512 2504 y Fg(p)60 b(cnf)f(7)g(11)1512 +2624 y(-5)g(3)h(0)1512 2745 y(-5)f(4)h(0)1512 2865 y(5)g(-3)f(-4)g(0) +1512 2985 y(6)h(-2)f(0)1512 3106 y(6)h(-5)f(0)1512 3226 +y(-6)g(2)h(5)f(0)1512 3347 y(7)h(1)f(5)h(0)1512 3467 +y(-7)f(1)h(-5)f(0)1512 3587 y(7)h(-1)f(-6)g(0)1512 3708 +y(-7)g(-1)h(6)f(0)1512 3828 y(7)h(0)1836 3990 y Fc(\(b\))2541 +2525 y Fg(p)f(cnf)g(4)h(3)2541 2645 y(1)f(-3)h(-4)f(0)2541 +2766 y(-1)g(2)h(3)f(0)2541 2886 y(-1)g(2)h(-3)f(4)h(0)2868 +3048 y Fc(\(c\))2541 3251 y Fg(p)f(cnf)g(5)h(5)2541 3371 +y(-5)f(1)h(0)2541 3492 y(5)f(-1)h(2)f(0)2541 3612 y(-3)g(-4)g(5)h(0) +2541 3733 y(3)f(-5)h(0)2541 3853 y(-3)f(4)h(-5)f(0)2865 +3990 y Fc(\(d\))-189 4138 y Fl(Figure)46 b(1:)71 b(\(a\))47 +b(BDD;)e(\(b\))h(\223Single-Node-Cut\224)g(format;)55 +b(\(c\))46 b(\223Maxterm-Cut\224)g(format;)55 b(\(d\))45 +b(\223)-8 b(Auxiliary-)-189 4258 y(V)d(ariable-Cut\224)25 +b(F)o(ormat.)-189 4625 y Fj(3.2)119 b(Implementation)-189 +4813 y Fl(Store)25 b(and)g(Load)g(for)g(a)g(single)f(BDD)h(or)g(a)g +(forest)g(of)g(BDDs)g(is)f(currently)h(implemented.)-189 +5073 y Fi(3.2.1)99 b(Storing)25 b(Decision)g(Diagrams)f(as)g(CNF)h(F)n +(ormulas)-189 5260 y Fl(As)g(f)o(ar)g(as)g(the)g(storing)e(process)i +(is)f(concerned)i(three)f(possible)e(formats)h(are)i(a)n(v)n(ailable:) +-44 5431 y Fk(\017)49 b Fl(DDDMP)p 421 5431 30 4 v 36 +w(CNF)p 650 5431 V 36 w(MODE)p 980 5431 V 35 w(NODE:)21 +b(store)f(a)h(BDD)h(by)e(introducing)f(an)i(auxiliary)g(v)n(ariable)f +(for)h(each)g(BDD)55 5551 y(node)1794 5800 y(8)p eop +%%Page: 9 9 +9 8 bop -44 218 a Fk(\017)49 b Fl(DDDMP)p 421 218 30 +4 v 36 w(CNF)p 650 218 V 36 w(MODE)p 980 218 V 35 w(MAXTERM:)20 +b(store)g(a)h(BDD)h(by)e(follo)n(wing)f(the)h(maxterm)g(of)h(the)g +(represented)55 338 y(function)-44 542 y Fk(\017)49 b +Fl(DDDMP)p 421 542 V 36 w(CNF)p 650 542 V 36 w(MODE)p +980 542 V 35 w(BEST)-5 b(:)32 b(trade-of)f(between)h(the)f(tw)o(o)f +(pre)n(vious)g(solution,)h(trying)f(to)h(optimize)55 +662 y(the)25 b(number)f(of)h(literals)f(stored.)-189 +865 y(See)c(procedures)f(Dddmp)p 736 865 V 35 w(cuddBddStoreCnf)g(\(to) +g(store)f(a)h(single)f(BDD)i(as)e(a)i(CNF)f(formula\))g(and)g(Dddmp)p +3609 865 V 34 w(cuddBddArrayStoreCnf)-189 986 y(\(to)25 +b(store)f(an)h(array)h(of)f(BDDs)g(as)f(a)i(CNF)f(formula\).)-189 +1252 y Fi(3.2.2)99 b(Loadinf)26 b(CNF)e(F)n(ormulas)g(as)h(BDDs)-189 +1439 y Fl(As)g(f)o(ar)g(as)g(the)g(loading)e(process)i(is)f(concerned)i +(three)f(possible)e(formats)i(are)g(a)n(v)n(ailable:)-44 +1643 y Fk(\017)49 b Fl(DDDMP)p 421 1643 V 36 w(CNF)p +650 1643 V 36 w(MODE)p 980 1643 V 35 w(NO)p 1159 1643 +V 36 w(CONJ:)25 b(Return)g(the)f(Clauses)h(without)f(Conjunction)-44 +1846 y Fk(\017)49 b Fl(DDDMP)p 421 1846 V 36 w(CNF)p +650 1846 V 36 w(MODE)p 980 1846 V 35 w(NO)p 1159 1846 +V 36 w(Q)o(U)l(ANT)-5 b(:)24 b(Return)h(the)g(sets)f(of)h(BDDs)g +(without)f(Quanti\002cation)-44 2050 y Fk(\017)49 b Fl(DDDMP)p +421 2050 V 36 w(CNF)p 650 2050 V 36 w(MODE)p 980 2050 +V 35 w(CONJ)p 1264 2050 V 36 w(Q)o(U)l(ANT)-5 b(:)23 +b(Return)h(the)g(sets)f(of)h(BDDs)g(AFTER)g(Existential)e(Quanti\002-) +55 2170 y(cation)-189 2373 y(See)e(procedures)f(Dddmp)p +736 2373 V 35 w(cuddBddLoadCnf)f(\(to)h(load)f(a)i(CNF)f(formula)g(as)g +(a)g(single)f(BDD\))h(and)g(Dddmp)p 3581 2373 V 35 w +(cuddBddArrayLoadCnf)-189 2494 y(\(to)35 b(load)h(a)g(CNF)g(formula)f +(as)h(an)g(array)g(of)g(BDDs\).)63 b(See)36 b(also)g(Dddmp)p +2485 2494 V 34 w(cuddHeaderLoadCnf)h(to)e(load)g(the)-189 +2614 y(header)25 b(of)g(a)g(CNF)h(\002le)f(to)g(gather)f(information)f +(on)i(the)g(sa)n(v)o(ed)f(structure.)-189 2954 y Fo(4)143 +b(T)-13 b(est)35 b(Pr)m(ogram)f(and)h(Regr)m(ession)f(T)-13 +b(ests)-189 3177 y Fl(The)20 b Fc(testddmp.c)e Fl(\002le,)j(pro)o +(vided)d(with)h(this)f(distrib)n(ution,)g(e)o(x)o(empli\002es)g(some)h +(of)h(the)f(abo)o(v)o(e)g(features.)29 b(Moreo)o(v)o(er)l(,)-189 +3298 y(in)d(the)h Fc(e)n(xp)g Fl(e)o(xperiments)e(a)j(fe)n(w)e +(scripts,)h(named)f Fc(test\241n\277.script)f Fl(are)i(a)n(v)n(ailable) +f(for)h(a)g(sanity)f(check)h(of)g(the)g(tool)-189 3418 +y(and)e(to)f(tak)o(e)h(a)g(look)f(at)h(some)f(runs)h(e)o(x)o +(empli\002cation.)-189 3758 y Fo(5)143 b(Documentation)-189 +3981 y Fl(F)o(or)27 b(further)f(documentation)f(on)i(the)f(package)h +(see)g(the)g(on-line)f(documentation)f(automatically)g(created)i(from) +-189 4102 y(the)e(source)g(code)g(\002les.)-189 4441 +y Fo(6)143 b(Ackno)o(wledgments)-189 4665 y Fl(W)-8 b(e)19 +b(are)h(particular)f(indebted)f(with)g(F)o(abio)g(Somenzi,)i(for)f +(discussions,)f(advice,)i(and)f(for)g(including)e(the)i(DDDMP)-189 +4785 y(package)28 b(into)f(the)h(CUDD)g(distrib)n(ution.)37 +b(W)-8 b(e)29 b(also)e(thank)g(all)h(the)g(user)g(of)g(the)f(package)i +(for)f(their)f(useful)h(indi-)-189 4905 y(cation)c(and)h(comments)f(on) +g(the)h(it.)1794 5800 y(9)p eop +%%Page: 10 10 +10 9 bop -189 218 a Fo(7)143 b(FTP)35 b(Site)-189 441 +y Fl(The)25 b(package)g(is)f(singularly)g(a)n(v)n(ailable)g(from:)-189 +645 y Fg(site:)59 b(ftp.polito.it)-189 765 y(user:)g(anonymous)-189 +885 y(directory:)f(/pub/research/dddmp)-189 1089 y Fl(or)25 +b(directly)f(from)h(the)f(author)h(WEB)g(pages:)-189 +1292 y Fg(WWW:)59 b(http://www.polito.it/\230{cabodi)o(,quer)o(})-189 +1632 y Fo(8)143 b(F)l(eedback)-189 1855 y Fl(Send)25 +b(feedback)h(to:)-189 2059 y Fg(Gianpiero)58 b(Cabodi)g(&)i(Stefano)e +(Quer)-189 2179 y(Politecnico)f(di)j(Torino)-189 2300 +y(Dipartimento)d(di)i(Automatica)f(e)i(Informatica)-189 +2420 y(Corso)f(Duca)g(degli)f(Abruzzi,)g(24)-189 2540 +y(I-10129)g(Torino)-189 2661 y(Italy)-189 2781 y(E-mail:)g +({cabodi,quer}@polito.it)-189 2901 y(WWW:)h +(http://www.polito.it/\230{cabodi)o(,quer)o(})1769 5800 +y Fl(10)p eop +%%Trailer +end +userdict /end-hook known{end-hook}if +%%EOF diff --git a/distr/dddmp/doc/dddmpAllAbs.html b/distr/dddmp/doc/dddmpAllAbs.html new file mode 100644 index 0000000..5cd6c2a --- /dev/null +++ b/distr/dddmp/doc/dddmpAllAbs.html @@ -0,0 +1,483 @@ + +dddmp package abstract + + + + + +
          +
          DddmpBddReadHeaderCnf() +
          Reads a the header of a dump file representing the argument + BDDs. + +
          DddmpBddReadHeader() +
          Reads a the header of a dump file representing the + argument BDDs. + +
          DddmpClearVisitedAdd() +
          Marks a node as not visited + +
          DddmpClearVisitedBdd() +
          Marks a node as not visited + +
          DddmpClearVisitedCnfRecur() +
          Mark ALL nodes as not visited + +
          DddmpClearVisitedCnfRecur() +
          Mark ALL nodes as not visited + +
          DddmpClearVisitedCnf() +
          Marks a node as not visited + +
          DddmpClearVisitedCnf() +
          Marks a node as not visited + +
          DddmpClearVisited() +
          Marks a node as not visited + +
          DddmpCnfClauses2Bdd() +
          Transforms CNF clauses into BDDs. + +
          DddmpCuddBddArrayStoreCnf() +
          Writes a dump file representing the argument Array of + BDDs in the CNF standard format. + +
          DddmpCuddBddArrayStore() +
          Writes a dump file representing the argument Array of + BDDs. + +
          DddmpCuddDdArrayLoadCnf() +
          Reads a dump file representing the argument BDDs in CNF + format. + +
          DddmpCuddDdArrayLoad() +
          Reads a dump file representing the argument BDDs. + +
          DddmpCuddDdArrayStoreBdd() +
          Writes a dump file representing the argument Array of + BDDs/ADDs. + +
          DddmpCuddDdArrayStoreBlifBody() +
          Writes a blif body representing the argument BDDs. + +
          DddmpCuddDdArrayStoreBlifStep() +
          Performs the recursive step of DddmpCuddDdArrayStoreBlif. + +
          DddmpCuddDdArrayStoreBlif() +
          Writes a blif file representing the argument BDDs. + +
          DddmpCuddDdArrayStorePrefixBody() +
          Internal function to writes a dump file representing the + argument BDD in a prefix notation. Writes the body of the file. + +
          DddmpCuddDdArrayStorePrefixStep() +
          Performs the recursive step of + DddmpCuddDdArrayStorePrefixBody. + +
          DddmpCuddDdArrayStorePrefix() +
          Internal function to writes a dump file representing the + argument BDD in a prefix notation. + +
          DddmpCuddDdArrayStoreSmvBody() +
          Internal function to writes a dump file representing the + argument BDD in a SMV notation. Writes the body of the file. + +
          DddmpCuddDdArrayStoreSmvStep() +
          Performs the recursive step of + DddmpCuddDdArrayStoreSmvBody. + +
          DddmpCuddDdArrayStoreSmv() +
          Internal function to writes a dump file representing the + argument BDD in a SMV notation. + +
          DddmpDdNodesCheckIncomingAndScanPath() +
          Number nodes recursively in post-order + +
          DddmpDdNodesCheckIncomingAndScanPath() +
          Number nodes recursively in post-order + +
          DddmpDdNodesCountEdgesAndNumber() +
          Removes nodes from unique table and numbers each node according + to the number of its incoming BDD edges. + +
          DddmpDdNodesCountEdgesAndNumber() +
          Removes nodes from unique table and numbers each node according + to the number of its incoming BDD edges. + +
          DddmpDdNodesCountEdgesRecur() +
          Counts the number of incoming edges for each node of a BDD + +
          DddmpDdNodesCountEdgesRecur() +
          Counts the number of incoming edges for each node of a BDD + +
          DddmpDdNodesNumberEdgesRecur() +
          Number nodes recursively in post-order + +
          DddmpDdNodesNumberEdgesRecur() +
          Number nodes recursively in post-order + +
          DddmpDdNodesResetCountRecur() +
          Resets counter and visited flag for ALL nodes of a BDD + +
          DddmpDdNodesResetCountRecur() +
          Resets counter and visited flag for ALL nodes of a BDD + +
          DddmpFreeHeaderCnf() +
          Frees the internal header structure. + +
          DddmpFreeHeader() +
          Frees the internal header structure. + +
          DddmpIntArrayDup() +
          Duplicates an array of ints + +
          DddmpIntArrayRead() +
          Inputs an array of ints + +
          DddmpIntArrayWrite() +
          Outputs an array of ints + +
          DddmpNumberAddNodes() +
          Removes nodes from unique table and number them + +
          DddmpNumberBddNodes() +
          Removes nodes from unique table and number them + +
          DddmpNumberDdNodesCnf() +
          Removes nodes from unique table and numbers them + +
          DddmpNumberDdNodesCnf() +
          Removes nodes from unique table and numbers them + +
          DddmpNumberDdNodes() +
          Removes nodes from unique table and number them + +
          DddmpPrintBddAndNextRecur() +
          Prints debug info + +
          DddmpPrintBddAndNextRecur() +
          Prints debug info + +
          DddmpPrintBddAndNext() +
          Prints debug information + +
          DddmpPrintBddAndNext() +
          Prints debug information + +
          DddmpReadCnfClauses() +
          Read the CNF clauses from the file in the standard DIMACS + format. + +
          DddmpReadCode() +
          Reads a 1 byte node code + +
          DddmpReadInt() +
          Reads a "packed integer" + +
          DddmpReadNodeIndexAdd() +
          Reads the index of a node + +
          DddmpReadNodeIndexBdd() +
          Reads the index of a node + +
          DddmpReadNodeIndexCnf() +
          Reads the index of a node + +
          DddmpReadNodeIndexCnf() +
          Reads the index of a node + +
          DddmpReadNodeIndex() +
          Reads the index of a node + +
          DddmpSetVisitedAdd() +
          Marks a node as visited + +
          DddmpSetVisitedBdd() +
          Marks a node as visited + +
          DddmpSetVisitedCnf() +
          Marks a node as visited + +
          DddmpSetVisitedCnf() +
          Marks a node as visited + +
          DddmpSetVisited() +
          Marks a node as visited + +
          DddmpStrArrayDup() +
          Duplicates an array of strings + +
          DddmpStrArrayFree() +
          Frees an array of strings + +
          DddmpStrArrayRead() +
          Inputs an array of strings + +
          DddmpStrArrayWrite() +
          Outputs an array of strings + +
          DddmpStrDup() +
          Duplicates a string + +
          DddmpUnnumberAddNodes() +
          Restores nodes in unique table, loosing numbering + +
          DddmpUnnumberBddNodes() +
          Restores nodes in unique table, loosing numbering + +
          DddmpUnnumberDdNodesCnf() +
          Restores nodes in unique table, loosing numbering + +
          DddmpUnnumberDdNodesCnf() +
          Restores nodes in unique table, loosing numbering + +
          DddmpUnnumberDdNodes() +
          Restores nodes in unique table, loosing numbering + +
          DddmpVisitedAdd() +
          Returns true if node is visited + +
          DddmpVisitedBdd() +
          Returns true if node is visited + +
          DddmpVisitedCnf() +
          Returns true if node is visited + +
          DddmpVisitedCnf() +
          Returns true if node is visited + +
          DddmpVisited() +
          Returns true if node is visited + +
          DddmpWriteCode() +
          Writes 1 byte node code + +
          DddmpWriteInt() +
          Writes a "packed integer" + +
          DddmpWriteNodeIndexAdd() +
          Write index to node + +
          DddmpWriteNodeIndexBdd() +
          Write index to node + +
          DddmpWriteNodeIndexCnfBis() +
          Write index to node + +
          DddmpWriteNodeIndexCnfWithTerminalCheck() +
          Write index to node + +
          DddmpWriteNodeIndexCnf() +
          Write index to node + +
          DddmpWriteNodeIndexCnf() +
          Write index to node + +
          DddmpWriteNodeIndex() +
          Write index to node + +
          Dddmp_Bin2Text() +
          Converts from binary to ASCII format + +
          Dddmp_Text2Bin() +
          Converts from ASCII to binary format + +
          Dddmp_cuddAddArrayLoad() +
          Reads a dump file representing the argument ADDs. + +
          Dddmp_cuddAddArrayStore() +
          Writes a dump file representing the argument Array of ADDs. + +
          Dddmp_cuddAddLoad() +
          Reads a dump file representing the argument ADD. + +
          Dddmp_cuddAddStore() +
          Writes a dump file representing the argument ADD. + +
          Dddmp_cuddBddArrayLoadCnf() +
          Reads a dump file in a CNF format. + +
          Dddmp_cuddBddArrayLoad() +
          Reads a dump file representing the argument BDDs. + +
          Dddmp_cuddBddArrayStoreBlif() +
          Writes a dump file representing the argument BDD in + a Blif/Exlif notation. + +
          Dddmp_cuddBddArrayStoreCnf() +
          Writes a dump file representing the argument array of BDDs + in CNF format. + +
          Dddmp_cuddBddArrayStorePrefix() +
          Writes a dump file representing the argument BDD in + a prefix notation. + +
          Dddmp_cuddBddArrayStoreSmv() +
          Writes a dump file representing the argument BDD in + a prefix notation. + +
          Dddmp_cuddBddArrayStore() +
          Writes a dump file representing the argument Array of BDDs. + +
          Dddmp_cuddBddDisplayBinary() +
          Display a binary dump file in a text file + +
          Dddmp_cuddBddLoadCnf() +
          Reads a dump file in a CNF format. + +
          Dddmp_cuddBddLoad() +
          Reads a dump file representing the argument BDD. + +
          Dddmp_cuddBddStoreBlif() +
          Writes a dump file representing the argument BDD in + a Blif/Exlif notation. + +
          Dddmp_cuddBddStoreCnf() +
          Writes a dump file representing the argument BDD in + a CNF format. + +
          Dddmp_cuddBddStorePrefix() +
          Writes a dump file representing the argument BDD in + a prefix notation. + +
          Dddmp_cuddBddStoreSmv() +
          Writes a dump file representing the argument BDD in + a prefix notation. + +
          Dddmp_cuddBddStore() +
          Writes a dump file representing the argument BDD. + +
          Dddmp_cuddHeaderLoadCnf() +
          Reads the header of a dump file representing the argument BDDs + +
          Dddmp_cuddHeaderLoad() +
          Reads the header of a dump file representing the argument BDDs + +
          FindVarname() +
          Performs binary search of a name within a sorted array + +
          NodeBinaryStoreBdd() +
          Store One Single Node in Binary Format. + +
          NodeStoreRecurAdd() +
          Performs the recursive step of Dddmp_bddStore. + +
          NodeStoreRecurBdd() +
          Performs the recursive step of Dddmp_bddStore. + +
          NodeTextStoreAdd() +
          Store One Single Node in Text Format. + +
          NodeTextStoreBdd() +
          Store One Single Node in Text Format. + +
          NumberNodeRecurAdd() +
          Number nodes recursively in post-order + +
          NumberNodeRecurBdd() +
          Number nodes recursively in post-order + +
          NumberNodeRecurCnf() +
          Number nodes recursively in post-order + +
          NumberNodeRecurCnf() +
          Number nodes recursively in post-order + +
          NumberNodeRecur() +
          Number nodes recursively in post-order + +
          QsortStrcmp() +
          String compare for qsort + +
          ReadByteBinary() +
          Reads a byte from file with escaped , and + +
          RemoveFromUniqueRecurAdd() +
          Removes a node from unique table + +
          RemoveFromUniqueRecurBdd() +
          Removes a node from unique table + +
          RemoveFromUniqueRecurCnf() +
          Removes a node from unique table + +
          RemoveFromUniqueRecurCnf() +
          Removes a node from unique table + +
          RemoveFromUniqueRecur() +
          Removes a node from unique table + +
          RestoreInUniqueRecurAdd() +
          Restores a node in unique table + +
          RestoreInUniqueRecurBdd() +
          Restores a node in unique table + +
          RestoreInUniqueRecurCnf() +
          Restores a node in unique table + +
          RestoreInUniqueRecurCnf() +
          Restores a node in unique table + +
          RestoreInUniqueRecur() +
          Restores a node in unique table + +
          StoreCnfBestNotSharedRecur() +
          Performs the recursive step of Print Best on Not Shared + sub-BDDs. + +
          StoreCnfBestSharedRecur() +
          Performs the recursive step of Print Best on Shared + sub-BDDs. + +
          StoreCnfBest() +
          Prints a disjoint sum of products with intermediate + cutting points. + +
          StoreCnfMaxtermByMaxtermRecur() +
          Performs the recursive step of Print Maxterm. + +
          StoreCnfMaxtermByMaxterm() +
          Prints a disjoint sum of products. + +
          StoreCnfNodeByNodeRecur() +
          Performs the recursive step of Dddmp_bddStore. + +
          StoreCnfNodeByNode() +
          Store the BDD as CNF clauses. + +
          StoreCnfOneNode() +
          Store One Single BDD Node. + +
          WriteByteBinary() +
          Writes a byte to file filtering , and + +
          printCubeCnf() +
          Print One Cube in CNF Format. + +
          () +
          Checks for Warnings: If expr==1 it prints out the warning + on stderr. + +
          () +
          Checks for fatal bugs + +
          () +
          Checks for fatal bugs and go to the label to deal with + the error. + +
          () +
          Checks for fatal bugs and return the DDDMP_FAILURE flag. + +
          () +
          Memory Allocation Macro for DDDMP + +
          () +
          Memory Free Macro for DDDMP + +
          + +
          + +Last updated on 1040218 17h14 + diff --git a/distr/dddmp/doc/dddmpAllByFile.html b/distr/dddmp/doc/dddmpAllByFile.html new file mode 100644 index 0000000..f414ee6 --- /dev/null +++ b/distr/dddmp/doc/dddmpAllByFile.html @@ -0,0 +1,13 @@ + +The dddmp package for maintainers + + + + + + + + + + + diff --git a/distr/dddmp/doc/dddmpAllByFunc.html b/distr/dddmp/doc/dddmpAllByFunc.html new file mode 100644 index 0000000..76671da --- /dev/null +++ b/distr/dddmp/doc/dddmpAllByFunc.html @@ -0,0 +1,13 @@ + +The dddmp package for maintainers + + + + + + + + + + + diff --git a/distr/dddmp/doc/dddmpAllDet.html b/distr/dddmp/doc/dddmpAllDet.html new file mode 100644 index 0000000..9d8e7ba --- /dev/null +++ b/distr/dddmp/doc/dddmpAllDet.html @@ -0,0 +1,3704 @@ + +The dddmp package: all functions + + +A set of internal low-level routines of the dddmp package + doing: +
            +
          • read and write of node codes in binary mode, +
          • read and write of integers in binary mode, +
          • marking/unmarking nodes as visited, +
          • numbering nodes. +
          +
          +
          +
          +
          +static Dddmp_Hdr_t * 
          +DddmpBddReadHeaderCnf(
          +  char * file, IN: file name
          +  FILE * fp IN: file pointer
          +)
          +
          +
          Reads the header of a dump file. Builds a Dddmp_Hdr_t struct + containing all infos in the header, for next manipulations. +

          + +

          Side Effects none +

          + +

          Defined in dddmpLoadCnf.c + +
          +
          +static Dddmp_Hdr_t * 
          +DddmpBddReadHeader(
          +  char * file, IN: file name
          +  FILE * fp IN: file pointer
          +)
          +
          +
          Reads the header of a dump file. Builds a Dddmp_Hdr_t struct + containing all infos in the header, for next manipulations. +

          + +

          Side Effects none +

          + +

          Defined in dddmpLoad.c + +
          +
          +void 
          +DddmpClearVisitedAdd(
          +  DdNode * f IN: BDD node to be marked (as not visited)
          +)
          +
          +
          Marks a node as not visited +

          + +

          Side Effects None +

          + +

          See Also DddmpVisitedAdd +() +DddmpSetVisitedAdd +() + + +
          Defined in dddmpNodeAdd.c + +
          +
          +void 
          +DddmpClearVisitedBdd(
          +  DdNode * f IN: BDD node to be marked (as not visited)
          +)
          +
          +
          Marks a node as not visited +

          + +

          Side Effects None +

          + +

          See Also DddmpVisited +() +DddmpSetVisited +() + + +
          Defined in dddmpNodeBdd.c + +
          +
          +static int 
          +DddmpClearVisitedCnfRecur(
          +  DdNode * f IN: root of the BDD to be marked
          +)
          +
          +
          Mark ALL nodes as not visited (it recurs on the node children) +

          + +

          Side Effects None +

          + +

          See Also DddmpVisitedCnf +() +DddmpSetVisitedCnf +() + + +
          Defined in dddmpDdNodeCnf.c + +
          +
          +static int 
          +DddmpClearVisitedCnfRecur(
          +  DdNode * f IN: root of the BDD to be marked
          +)
          +
          +
          Mark ALL nodes as not visited (it recurs on the node children) +

          + +

          Side Effects None +

          + +

          See Also DddmpVisitedCnf +() +DddmpSetVisitedCnf +() + + +
          Defined in dddmpNodeCnf.c + +
          +
          +static void 
          +DddmpClearVisitedCnf(
          +  DdNode * f IN: BDD node to be marked (as not visited)
          +)
          +
          +
          Marks a node as not visited +

          + +

          Side Effects None +

          + +

          See Also DddmpVisitedCnf +() +DddmpSetVisitedCnf +() + + +
          Defined in dddmpDdNodeCnf.c + +
          +
          +static void 
          +DddmpClearVisitedCnf(
          +  DdNode * f IN: BDD node to be marked (as not visited)
          +)
          +
          +
          Marks a node as not visited +

          + +

          Side Effects None +

          + +

          See Also DddmpVisitedCnf +() +DddmpSetVisitedCnf +() + + +
          Defined in dddmpNodeCnf.c + +
          +
          +void 
          +DddmpClearVisited(
          +  DdNode * f IN: BDD node to be marked (as not visited)
          +)
          +
          +
          Marks a node as not visited +

          + +

          Side Effects None +

          + +

          See Also DddmpVisited +() +DddmpSetVisited +() + + +
          Defined in dddmpDdNodeBdd.c + +
          +
          +static int 
          +DddmpCnfClauses2Bdd(
          +  Dddmp_Hdr_t * Hdr, IN: file header
          +  DdManager * ddMgr, IN: DD Manager
          +  int ** cnfTable, IN: CNF table for clauses
          +  int  mode, IN: computation mode
          +  DdNode *** rootsPtrPtr OUT: array of returned BDD roots (by reference)
          +)
          +
          +
          Transforms CNF clauses into BDDs. Clauses are stored in an + internal structure previously read. The results can be given in + different format according to the mode selection: + IFF mode == 0 Return the Clauses without Conjunction + IFF mode == 1 Return the sets of BDDs without Quantification + IFF mode == 2 Return the sets of BDDs AFTER Existential Quantification +

          + +

          Defined in dddmpLoadCnf.c + +
          +
          +static int 
          +DddmpCuddBddArrayStoreCnf(
          +  DdManager * ddMgr, IN: DD Manager
          +  DdNode ** f, IN: array of BDD roots to be stored
          +  int  rootN, IN: # of output BDD roots to be stored
          +  Dddmp_DecompCnfStoreType  mode, IN: format selection
          +  int  noHeader, IN: do not store header iff 1
          +  char ** varNames, IN: array of variable names (or NULL)
          +  int * bddIds, IN: array of BDD node Ids (or NULL)
          +  int * bddAuxIds, IN: array of BDD Aux Ids (or NULL)
          +  int * cnfIds, IN: array of CNF ids (or NULL)
          +  int  idInitial, IN: starting id for cutting variables
          +  int  edgeInTh, IN: Max # Incoming Edges
          +  int  pathLengthTh, IN: Max Path Length
          +  char * fname, IN: file name
          +  FILE * fp, IN: pointer to the store file
          +  int * clauseNPtr, OUT: number of clause stored
          +  int * varNewNPtr OUT: number of new variable created
          +)
          +
          +
          Dumps the argument array of BDDs/ADDs to file in CNF format. + The following arrays: varNames, bddIds, bddAuxIds, and cnfIds + fix the correspondence among variable names, BDD ids, BDD + auxiliary ids and the ids used to store the CNF problem. + All these arrays are automatically created iff NULL. + Auxiliary variable, iff necessary, are created starting from value + idInitial. + Iff idInitial is <= 0 its value is selected as the number of internal + CUDD variable + 2. + Auxiliary variables, i.e., cut points are inserted following these + criterias: + * edgeInTh + indicates the maximum number of incoming edges up to which + no cut point (auxiliary variable) is inserted. + If edgeInTh: + * is equal to -1 no cut point due to incoming edges are inserted + (MaxtermByMaxterm method.) + * is equal to 0 a cut point is inserted for each node with a single + incoming edge, i.e., each node, (NodeByNode method). + * is equal to n a cut point is inserted for each node with (n+1) + incoming edges. + * pathLengthTh + indicates the maximum length path up to which no cut points + (auxiliary variable) is inserted. + If the path length between two nodes exceeds this value, a cut point + is inserted. + If pathLengthTh: + * is equal to -1 no cut point due path length are inserted + (MaxtermByMaxterm method.) + * is equal to 0 a cut point is inserted for each node (NodeByNode + method). + * is equal to n a cut point is inserted on path whose length is + equal to (n+1). + Notice that the maximum number of literals in a clause is equal + to (pathLengthTh + 2), i.e., for each path we have to keep into + account a CNF variable for each node plus 2 added variables for + the bottom and top-path cut points. +

          + +

          Side Effects Nodes are temporarily removed from the unique hash table. + They are re-linked after the store operation in a modified + order. +

          + +

          See Also Dddmp_cuddBddStore + + +
          Defined in dddmpStoreCnf.c + +
          +
          +int 
          +DddmpCuddBddArrayStore(
          +  Dddmp_DecompType  ddType, IN: Selects the decomp type BDD
          +  DdManager * ddMgr, IN: DD Manager
          +  char * ddname, IN: DD name (or NULL)
          +  int  nRoots, IN: number of output BDD roots to be stored
          +  DdNode ** f, IN: array of DD roots to be stored
          +  char ** rootnames, IN: array of root names (or NULL)
          +  char ** varnames, IN: array of variable names (or NULL)
          +  int * auxids, IN: array of converted var IDs
          +  int  mode, IN: storing mode selector
          +  Dddmp_VarInfoType  varinfo, IN: extra info for variables in text mode
          +  char * fname, IN: File name
          +  FILE * fp IN: File pointer to the store file
          +)
          +
          +
          Dumps the argument array of BDDs to file. + Internal function doing inner steps of store for BDDs. +

          + +

          Side Effects Nodes are temporarily removed from the unique hash + table. They are re-linked after the store operation in a + modified order. +

          + +

          See Also Dddmp_cuddBddStore +Dddmp_cuddBddLoad +Dddmp_cuddBddArrayLoad + + +
          Defined in dddmpStoreBdd.c + +
          +
          +static int 
          +DddmpCuddDdArrayLoadCnf(
          +  DdManager * ddMgr, IN: DD Manager
          +  Dddmp_RootMatchType  rootmatchmode, IN: storing mode selector
          +  char ** rootmatchnames, IN: sorted names for loaded roots
          +  Dddmp_VarMatchType  varmatchmode, IN: storing mode selector
          +  char ** varmatchnames, IN: array of variable names, by ids
          +  int * varmatchauxids, IN: array of variable auxids, by ids
          +  int * varcomposeids, IN: array of new ids, by ids
          +  int  mode, IN: computation mode
          +  char * file, IN: file name
          +  FILE * fp, IN: file pointer
          +  DdNode *** rootsPtrPtr, OUT: array of BDD roots
          +  int * nRoots OUT: number of BDDs returned
          +)
          +
          +
          Reads a dump file representing the argument BDDs in CNF + format. + IFF mode == 0 Return the Clauses without Conjunction + IFF mode == 1 Return the sets of BDDs without Quantification + IFF mode == 2 Return the sets of BDDs AFTER Existential Quantification +

          + +

          Side Effects A vector of pointers to DD nodes is allocated and freed. +

          + +

          See Also Dddmp_cuddBddArrayLoad + + +
          Defined in dddmpLoadCnf.c + +
          +
          +static int 
          +DddmpCuddDdArrayLoad(
          +  Dddmp_DecompType  ddType, IN: Selects decomp type
          +  DdManager * ddMgr, IN: DD Manager
          +  Dddmp_RootMatchType  rootMatchMode, IN: storing mode selector
          +  char ** rootmatchnames, IN: sorted names for loaded roots
          +  Dddmp_VarMatchType  varMatchMode, IN: storing mode selector
          +  char ** varmatchnames, IN: array of variable names, by ids
          +  int * varmatchauxids, IN: array of variable auxids, by ids
          +  int * varcomposeids, IN: array of new ids, by ids
          +  int  mode, IN: requested input file format
          +  char * file, IN: file name
          +  FILE * fp, IN: file pointer
          +  DdNode *** pproots OUT: array BDD roots (by reference)
          +)
          +
          +
          Reads a dump file representing the argument BDDs. The header is + common to both text and binary mode. The node list is either + in text or binary format. A dynamic vector of DD pointers + is allocated to support conversion from DD indexes to pointers. + Several criteria are supported for variable match between file + and dd manager. Several changes/permutations/compositions are allowed + for variables while loading DDs. Variable of the dd manager are allowed + to match with variables on file on ids, permids, varnames, + varauxids; also direct composition between ids and + composeids is supported. More in detail: +
            +
          1. varMatchMode=DDDMP_VAR_MATCHIDS

            + allows the loading of a DD keeping variable IDs unchanged + (regardless of the variable ordering of the reading manager); this + is useful, for example, when swapping DDs to file and restoring them + later from file, after possible variable reordering activations. + +

          2. varMatchMode=DDDMP_VAR_MATCHPERMIDS

            + is used to allow variable match according to the position in the ordering. + +

          3. varMatchMode=DDDMP_VAR_MATCHNAMES

            + requires a non NULL varmatchnames parameter; this is a vector of + strings in one-to-one correspondence with variable IDs of the + reading manager. Variables in the DD file read are matched with + manager variables according to their name (a non NULL varnames + parameter was required while storing the DD file). + +

          4. varMatchMode=DDDMP_VAR_MATCHIDS

            + has a meaning similar to DDDMP_VAR_MATCHNAMES, but integer auxiliary + IDs are used instead of strings; the additional non NULL + varmatchauxids parameter is needed. + +

          5. varMatchMode=DDDMP_VAR_COMPOSEIDS

            + uses the additional varcomposeids parameter is used as array of + variable ids to be composed with ids stored in file. +

          + + In the present implementation, the array varnames (3), varauxids (4) + and composeids (5) need to have one entry for each variable in the + DD manager (NULL pointers are allowed for unused variables + in varnames). Hence variables need to be already present in the + manager. All arrays are sorted according to IDs. +

          + +

          Side Effects A vector of pointers to DD nodes is allocated and freed. +

          + +

          See Also Dddmp_cuddBddArrayStore + + +
          Defined in dddmpLoad.c + +
          +
          +int 
          +DddmpCuddDdArrayStoreBdd(
          +  Dddmp_DecompType  ddType, IN: Selects the decomp type: BDD or ADD
          +  DdManager * ddMgr, IN: DD Manager
          +  char * ddname, IN: DD name (or NULL)
          +  int  nRoots, IN: number of output BDD roots to be stored
          +  DdNode ** f, IN: array of DD roots to be stored
          +  char ** rootnames, IN: array of root names (or NULL)
          +  char ** varnames, IN: array of variable names (or NULL)
          +  int * auxids, IN: array of converted var IDs
          +  int  mode, IN: storing mode selector
          +  Dddmp_VarInfoType  varinfo, IN: extra info for variables in text mode
          +  char * fname, IN: File name
          +  FILE * fp IN: File pointer to the store file
          +)
          +
          +
          Dumps the argument array of BDDs/ADDs to file. Internal + function doing inner steps of store for BDDs and ADDs. + ADD store is presently supported only with the text format. +

          + +

          Side Effects Nodes are temporarily removed from the unique hash + table. They are re-linked after the store operation in a + modified order. +

          + +

          See Also Dddmp_cuddBddStore +Dddmp_cuddBddLoad +Dddmp_cuddBddArrayLoad + + +
          Defined in dddmpStoreAdd.c + +
          +
          +static int 
          +DddmpCuddDdArrayStoreBlifBody(
          +  DdManager * ddMgr, IN: Manager
          +  int  n, IN: Number of output nodes to be dumped
          +  DdNode ** f, IN: Array of output nodes to be dumped
          +  char ** inputNames, IN: Array of input names (or NULL)
          +  char ** outputNames, IN: Array of output names (or NULL)
          +  FILE * fp IN: Pointer to the dump file
          +)
          +
          +
          Writes a blif body 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). + DddmpCuddDdArrayStoreBlif does not close the file: This is the + caller responsibility. + DddmpCuddDdArrayStoreBlif uses a minimal unique subset of + the hexadecimal address of a node as name for it. If the argument + inputNames is non-null, it is assumed to hold the pointers to the names + of the inputs. Similarly for outputNames. This function prints out only + .names part. +

          + +

          Side Effects None +

          + +

          Defined in dddmpStoreMisc.c + +
          +
          +static int 
          +DddmpCuddDdArrayStoreBlifStep(
          +  DdManager * ddMgr, 
          +  DdNode * f, 
          +  FILE * fp, 
          +  st_table * visited, 
          +  char ** names 
          +)
          +
          +
          Performs the recursive step of DddmpCuddDdArrayStoreBlif. + 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 DddmpCuddDdArrayStoreBlifStep + guarantees this assumption in the recursive calls. +

          + +

          Side Effects None +

          + +

          Defined in dddmpStoreMisc.c + +
          +
          +static int 
          +DddmpCuddDdArrayStoreBlif(
          +  DdManager * ddMgr, IN: Manager
          +  int  n, IN: Number of output nodes to be dumped
          +  DdNode ** f, IN: Array of output nodes to be dumped
          +  char ** inputNames, IN: Array of input names (or NULL)
          +  char ** outputNames, IN: Array of output names (or NULL)
          +  char * modelName, IN: Model name (or NULL)
          +  FILE * fp IN: Pointer to the dump file
          +)
          +
          +
          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). + DddmpCuddDdArrayStoreBlif does not close the file: This is the + caller responsibility. + DddmpCuddDdArrayStoreBlif 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 outputNames. + It prefixes the string "NODE" to each nome to have "regular" names + for each elements. +

          + +

          Side Effects None +

          + +

          See Also DddmpCuddDdArrayStoreBlifBody +Cudd_DumpBlif + + +
          Defined in dddmpStoreMisc.c + +
          +
          +static int 
          +DddmpCuddDdArrayStorePrefixBody(
          +  DdManager * ddMgr, IN: Manager
          +  int  n, IN: Number of output nodes to be dumped
          +  DdNode ** f, IN: Array of output nodes to be dumped
          +  char ** inputNames, IN: Array of input names (or NULL)
          +  char ** outputNames, IN: Array of output names (or NULL)
          +  FILE * fp IN: Pointer to the dump file
          +)
          +
          +
          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). + It does not close the file: This is the caller responsibility. + It uses a minimal unique subset of the hexadecimal address of a node as + name for it. + If the argument inputNames is non-null, it is assumed to hold the + pointers to the names of the inputs. Similarly for outputNames. + For each BDD node of function f, variable v, then child T, and else + child E it stores: + f = v * T + v' * E + that is + (OR f (AND v T) (AND (NOT v) E)) + If E is a complemented child this results in the following + (OR f (AND v T) (AND (NOT v) (NOT E))) +

          + +

          Side Effects None +

          + +

          See Also DddmpCuddDdArrayStoreBlif + + +
          Defined in dddmpStoreMisc.c + +
          +
          +static int 
          +DddmpCuddDdArrayStorePrefixStep(
          +  DdManager * ddMgr, 
          +  DdNode * f, 
          +  FILE * fp, 
          +  st_table * visited, 
          +  char ** names 
          +)
          +
          +
          Performs the recursive step of + DddmpCuddDdArrayStorePrefixBody. + Traverses the BDD f and writes a multiplexer-network description to the + file pointed by fp. + For each BDD node of function f, variable v, then child T, and else + child E it stores: + f = v * T + v' * E + that is + (OR f (AND v T) (AND (NOT v) E)) + If E is a complemented child this results in the following + (OR f (AND v T) (AND (NOT v) (NOT E))) + f is assumed to be a regular pointer and the function guarantees this + assumption in the recursive calls. +

          + +

          Side Effects None +

          + +

          Defined in dddmpStoreMisc.c + +
          +
          +static int 
          +DddmpCuddDdArrayStorePrefix(
          +  DdManager * ddMgr, IN: Manager
          +  int  n, IN: Number of output nodes to be dumped
          +  DdNode ** f, IN: Array of output nodes to be dumped
          +  char ** inputNames, IN: Array of input names (or NULL)
          +  char ** outputNames, IN: Array of output names (or NULL)
          +  char * modelName, IN: Model name (or NULL)
          +  FILE * fp IN: Pointer to the dump file
          +)
          +
          +
          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). + It does not close the file: This is the caller responsibility. + It uses a minimal unique subset of the hexadecimal address of a node as + name for it. + If the argument inputNames is non-null, it is assumed to hold the + pointers to the names of the inputs. Similarly for outputNames. + For each BDD node of function f, variable v, then child T, and else + child E it stores: + f = v * T + v' * E + that is + (OR f (AND v T) (AND (NOT v) E)) + If E is a complemented child this results in the following + (OR f (AND v T) (AND (NOT v) (NOT E))) + Comments (COMMENT) are added at the beginning of the description to + describe inputs and outputs of the design. + A buffer (BUF) is add on the output to cope with complemented functions. +

          + +

          Side Effects None +

          + +

          See Also DddmpCuddDdArrayStoreBlif + + +
          Defined in dddmpStoreMisc.c + +
          +
          +static int 
          +DddmpCuddDdArrayStoreSmvBody(
          +  DdManager * ddMgr, IN: Manager
          +  int  n, IN: Number of output nodes to be dumped
          +  DdNode ** f, IN: Array of output nodes to be dumped
          +  char ** inputNames, IN: Array of input names (or NULL)
          +  char ** outputNames, IN: Array of output names (or NULL)
          +  FILE * fp IN: Pointer to the dump file
          +)
          +
          +
          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). + It does not close the file: This is the caller responsibility. + It uses a minimal unique subset of the hexadecimal address of a node as + name for it. + If the argument inputNames is non-null, it is assumed to hold the + pointers to the names of the inputs. Similarly for outputNames. + For each BDD node of function f, variable v, then child T, and else + child E it stores: + f = v * T + v' * E + that is + (OR f (AND v T) (AND (NOT v) E)) + If E is a complemented child this results in the following + (OR f (AND v T) (AND (NOT v) (NOT E))) +

          + +

          Side Effects None +

          + +

          See Also DddmpCuddDdArrayStoreBlif + + +
          Defined in dddmpStoreMisc.c + +
          +
          +static int 
          +DddmpCuddDdArrayStoreSmvStep(
          +  DdManager * ddMgr, 
          +  DdNode * f, 
          +  FILE * fp, 
          +  st_table * visited, 
          +  char ** names 
          +)
          +
          +
          Performs the recursive step of + DddmpCuddDdArrayStoreSmvBody. + Traverses the BDD f and writes a multiplexer-network description to the + file pointed by fp. + For each BDD node of function f, variable v, then child T, and else + child E it stores: + f = v * T + v' * E + that is + (OR f (AND v T) (AND (NOT v) E)) + If E is a complemented child this results in the following + (OR f (AND v T) (AND (NOT v) (NOT E))) + f is assumed to be a regular pointer and the function guarantees this + assumption in the recursive calls. +

          + +

          Side Effects None +

          + +

          Defined in dddmpStoreMisc.c + +
          +
          +static int 
          +DddmpCuddDdArrayStoreSmv(
          +  DdManager * ddMgr, IN: Manager
          +  int  n, IN: Number of output nodes to be dumped
          +  DdNode ** f, IN: Array of output nodes to be dumped
          +  char ** inputNames, IN: Array of input names (or NULL)
          +  char ** outputNames, IN: Array of output names (or NULL)
          +  char * modelName, IN: Model name (or NULL)
          +  FILE * fp IN: Pointer to the dump file
          +)
          +
          +
          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). + It does not close the file: This is the caller responsibility. + It uses a minimal unique subset of the hexadecimal address of a node as + name for it. + If the argument inputNames is non-null, it is assumed to hold the + pointers to the names of the inputs. Similarly for outputNames. + For each BDD node of function f, variable v, then child T, and else + child E it stores: + f = v * T + v' * E + that is + (OR f (AND v T) (AND (NOT v) E)) + If E is a complemented child this results in the following + (OR f (AND v T) (AND (NOT v) (NOT E))) + Comments (COMMENT) are added at the beginning of the description to + describe inputs and outputs of the design. + A buffer (BUF) is add on the output to cope with complemented functions. +

          + +

          Side Effects None +

          + +

          See Also DddmpCuddDdArrayStoreBlif + + +
          Defined in dddmpStoreMisc.c + +
          +
          +static void 
          +DddmpDdNodesCheckIncomingAndScanPath(
          +  DdNode * f, IN: BDD node to be numbered
          +  int  pathLengthCurrent, IN: Current Path Length
          +  int  edgeInTh, IN: Max # In-Edges, after a Insert Cut Point
          +  int  pathLengthTh IN: Max Path Length (after, Insert a Cut Point)
          +)
          +
          +
          Number nodes recursively in post-order. + The "visited" flag is used with the right polarity. + The node is assigned to a new CNF variable only if it is a "shared" + node (i.e. the number of its incoming edges is greater than 1). +

          + +

          Side Effects "visited" flags are set. +

          + +

          Defined in dddmpDdNodeCnf.c + +
          +
          +static void 
          +DddmpDdNodesCheckIncomingAndScanPath(
          +  DdNode * f, IN: BDD node to be numbered
          +  int  pathLengthCurrent, IN: Current Path Length
          +  int  edgeInTh, IN: Max # In-Edges, after a Insert Cut Point
          +  int  pathLengthTh IN: Max Path Length (after, Insert a Cut Point)
          +)
          +
          +
          Number nodes recursively in post-order. + The "visited" flag is used with the right polarity. + The node is assigned to a new CNF variable only if it is a "shared" + node (i.e. the number of its incoming edges is greater than 1). +

          + +

          Side Effects "visited" flags are set. +

          + +

          Defined in dddmpNodeCnf.c + +
          +
          +int 
          +DddmpDdNodesCountEdgesAndNumber(
          +  DdManager * ddMgr, IN: DD Manager
          +  DdNode ** f, IN: Array of BDDs
          +  int  rootN, IN: Number of BDD roots in the array of BDDs
          +  int  edgeInTh, IN: Max # In-Edges, after a Insert Cut Point
          +  int  pathLengthTh, IN: Max Path Length (after, Insert a Cut Point)
          +  int * cnfIds, OUT: CNF identifiers for variables
          +  int  id OUT: Number of Temporary Variables Introduced
          +)
          +
          +
          Removes nodes from unique table and numbers each node according + to the number of its incoming BDD edges. +

          + +

          Side Effects Nodes are temporarily removed from unique table +

          + +

          See Also RemoveFromUniqueRecurCnf() + + +
          Defined in dddmpDdNodeCnf.c + +
          +
          +int 
          +DddmpDdNodesCountEdgesAndNumber(
          +  DdManager * ddMgr, IN: DD Manager
          +  DdNode ** f, IN: Array of BDDs
          +  int  rootN, IN: Number of BDD roots in the array of BDDs
          +  int  edgeInTh, IN: Max # In-Edges, after a Insert Cut Point
          +  int  pathLengthTh, IN: Max Path Length (after, Insert a Cut Point)
          +  int * cnfIds, OUT: CNF identifiers for variables
          +  int  id OUT: Number of Temporary Variables Introduced
          +)
          +
          +
          Removes nodes from unique table and numbers each node according + to the number of its incoming BDD edges. +

          + +

          Side Effects Nodes are temporarily removed from unique table +

          + +

          See Also RemoveFromUniqueRecurCnf() + + +
          Defined in dddmpNodeCnf.c + +
          +
          +static int 
          +DddmpDdNodesCountEdgesRecur(
          +  DdNode * f IN: root of the BDD
          +)
          +
          +
          Counts (recursively) the number of incoming edges for each + node of a BDD. This number is stored in the index field. +

          + +

          Side Effects "visited" flags remain untouched. +

          + +

          Defined in dddmpDdNodeCnf.c + +
          +
          +static int 
          +DddmpDdNodesCountEdgesRecur(
          +  DdNode * f IN: root of the BDD
          +)
          +
          +
          Counts (recursively) the number of incoming edges for each + node of a BDD. This number is stored in the index field. +

          + +

          Side Effects "visited" flags remain untouched. +

          + +

          Defined in dddmpNodeCnf.c + +
          +
          +static int 
          +DddmpDdNodesNumberEdgesRecur(
          +  DdNode * f, IN: BDD node to be numbered
          +  int * cnfIds, IN: possible source for numbering
          +  int  id IN/OUT: possible source for numbering
          +)
          +
          +
          Number nodes recursively in post-order. + The "visited" flag is used with the inverse polarity. + Numbering follows the subsequent strategy: + * if the index = 0 it remains so + * if the index >= 1 it gets enumerated. + This implies that the node is assigned to a new CNF variable only if + it is not a terminal node otherwise it is assigned the index of + the BDD variable. +

          + +

          Side Effects "visited" flags are reset. +

          + +

          Defined in dddmpDdNodeCnf.c + +
          +
          +static int 
          +DddmpDdNodesNumberEdgesRecur(
          +  DdNode * f, IN: BDD node to be numbered
          +  int * cnfIds, IN: possible source for numbering
          +  int  id IN/OUT: possible source for numbering
          +)
          +
          +
          Number nodes recursively in post-order. + The "visited" flag is used with the inverse polarity. + Numbering follows the subsequent strategy: + * if the index = 0 it remains so + * if the index >= 1 it gets enumerated. + This implies that the node is assigned to a new CNF variable only if + it is not a terminal node otherwise it is assigned the index of + the BDD variable. +

          + +

          Side Effects "visited" flags are reset. +

          + +

          Defined in dddmpNodeCnf.c + +
          +
          +static int 
          +DddmpDdNodesResetCountRecur(
          +  DdNode * f IN: root of the BDD whose counters are reset
          +)
          +
          +
          Resets counter and visited flag for ALL nodes of a BDD (it + recurs on the node children). The index field of the node is + used as counter. +

          + +

          Defined in dddmpDdNodeCnf.c + +
          +
          +static int 
          +DddmpDdNodesResetCountRecur(
          +  DdNode * f IN: root of the BDD whose counters are reset
          +)
          +
          +
          Resets counter and visited flag for ALL nodes of a BDD (it + recurs on the node children). The index field of the node is + used as counter. +

          + +

          Defined in dddmpNodeCnf.c + +
          +
          +static void 
          +DddmpFreeHeaderCnf(
          +  Dddmp_Hdr_t * Hdr IN: pointer to header
          +)
          +
          +
          Frees the internal header structure by freeing all internal + fields first. +

          + +

          Defined in dddmpLoadCnf.c + +
          +
          +static void 
          +DddmpFreeHeader(
          +  Dddmp_Hdr_t * Hdr IN: pointer to header
          +)
          +
          +
          Frees the internal header structureby freeing all internal + fields first. +

          + +

          Defined in dddmpLoad.c + +
          +
          +int * 
          +DddmpIntArrayDup(
          +  int * array, IN: array of ints to be duplicated
          +  int  n IN: size of the array
          +)
          +
          +
          Allocates memory and copies source array +

          + +

          Side Effects None +

          + +

          Defined in dddmpUtil.c + +
          +
          +int * 
          +DddmpIntArrayRead(
          +  FILE * fp, IN: input file
          +  int  n IN: size of the array
          +)
          +
          +
          Allocates memory and inputs source array +

          + +

          Side Effects None +

          + +

          Defined in dddmpUtil.c + +
          +
          +int 
          +DddmpIntArrayWrite(
          +  FILE * fp, IN: output file
          +  int * array, IN: array of ints
          +  int  n IN: size of the array
          +)
          +
          +
          Outputs an array of ints to a specified file +

          + +

          Side Effects None +

          + +

          Defined in dddmpUtil.c + +
          +
          +int 
          +DddmpNumberAddNodes(
          +  DdManager * ddMgr, IN: DD Manager
          +  DdNode ** f, IN: array of BDDs
          +  int  n IN: number of BDD roots in the array of BDDs
          +)
          +
          +
          Node numbering is required to convert pointers to integers. + Since nodes are removed from unique table, no new nodes should + be generated before re-inserting nodes in the unique table + (DddmpUnnumberDdNodes()). +

          + +

          Side Effects Nodes are temporarily removed from unique table +

          + +

          See Also RemoveFromUniqueRecurAdd +() +NumberNodeRecurAdd +() +DddmpUnnumberDdNodesAdd +() + + +
          Defined in dddmpNodeAdd.c + +
          +
          +int 
          +DddmpNumberBddNodes(
          +  DdManager * ddMgr, IN: DD Manager
          +  DdNode ** f, IN: array of BDDs
          +  int  n IN: number of BDD roots in the array of BDDs
          +)
          +
          +
          Node numbering is required to convert pointers to integers. + Since nodes are removed from unique table, no new nodes should + be generated before re-inserting nodes in the unique table + (DddmpUnnumberBddNodes ()). +

          + +

          Side Effects Nodes are temporarily removed from unique table +

          + +

          See Also RemoveFromUniqueRecur() +NumberNodeRecur() +DddmpUnnumberBddNodes +() + + +
          Defined in dddmpNodeBdd.c + +
          +
          +int 
          +DddmpNumberDdNodesCnf(
          +  DdManager * ddMgr, IN: DD Manager
          +  DdNode ** f, IN: array of BDDs
          +  int  rootN, IN: number of BDD roots in the array of BDDs
          +  int * cnfIds, OUT: CNF identifiers for variables
          +  int  id OUT: number of Temporary Variables Introduced
          +)
          +
          +
          Node numbering is required to convert pointers to integers. + Since nodes are removed from unique table, no new nodes should + be generated before re-inserting nodes in the unique table + (DddmpUnnumberDdNodesCnf()). +

          + +

          Side Effects Nodes are temporarily removed from unique table +

          + +

          See Also RemoveFromUniqueRecurCnf() +NumberNodeRecurCnf() +DddmpUnnumberDdNodesCnf() + + +
          Defined in dddmpDdNodeCnf.c + +
          +
          +int 
          +DddmpNumberDdNodesCnf(
          +  DdManager * ddMgr, IN: DD Manager
          +  DdNode ** f, IN: array of BDDs
          +  int  rootN, IN: number of BDD roots in the array of BDDs
          +  int * cnfIds, OUT: CNF identifiers for variables
          +  int  id OUT: number of Temporary Variables Introduced
          +)
          +
          +
          Node numbering is required to convert pointers to integers. + Since nodes are removed from unique table, no new nodes should + be generated before re-inserting nodes in the unique table + (DddmpUnnumberDdNodesCnf()). +

          + +

          Side Effects Nodes are temporarily removed from unique table +

          + +

          See Also RemoveFromUniqueRecurCnf() +NumberNodeRecurCnf() +DddmpUnnumberDdNodesCnf() + + +
          Defined in dddmpNodeCnf.c + +
          +
          +int 
          +DddmpNumberDdNodes(
          +  DdManager * ddMgr, IN: DD Manager
          +  DdNode ** f, IN: array of BDDs
          +  int  n IN: number of BDD roots in the array of BDDs
          +)
          +
          +
          Node numbering is required to convert pointers to integers. + Since nodes are removed from unique table, no new nodes should + be generated before re-inserting nodes in the unique table + (DddmpUnnumberDdNodes()). +

          + +

          Side Effects Nodes are temporarily removed from unique table +

          + +

          See Also RemoveFromUniqueRecur() +NumberNodeRecur() +DddmpUnnumberDdNodes() + + +
          Defined in dddmpDdNodeBdd.c + +
          +
          +static int 
          +DddmpPrintBddAndNextRecur(
          +  DdManager * ddMgr, IN: DD Manager
          +  DdNode * f IN: root of the BDD to be displayed
          +)
          +
          +
          Prints debug info for a BDD on the screen. It recurs on + node's children. +

          + +

          Defined in dddmpDdNodeCnf.c + +
          +
          +static int 
          +DddmpPrintBddAndNextRecur(
          +  DdManager * ddMgr, IN: DD Manager
          +  DdNode * f IN: root of the BDD to be displayed
          +)
          +
          +
          Prints debug info for a BDD on the screen. It recurs on + node's children. +

          + +

          Defined in dddmpNodeCnf.c + +
          +
          +int 
          +DddmpPrintBddAndNext(
          +  DdManager * ddMgr, IN: DD Manager
          +  DdNode ** f, IN: Array of BDDs to be displayed
          +  int  rootN IN: Number of BDD roots in the array of BDDs
          +)
          +
          +
          Prints debug information for an array of BDDs on the screen +

          + +

          Side Effects None +

          + +

          Defined in dddmpDdNodeCnf.c + +
          +
          +int 
          +DddmpPrintBddAndNext(
          +  DdManager * ddMgr, IN: DD Manager
          +  DdNode ** f, IN: Array of BDDs to be displayed
          +  int  rootN IN: Number of BDD roots in the array of BDDs
          +)
          +
          +
          Prints debug information for an array of BDDs on the screen +

          + +

          Side Effects None +

          + +

          Defined in dddmpNodeCnf.c + +
          +
          +static int 
          +DddmpReadCnfClauses(
          +  Dddmp_Hdr_t * Hdr, IN: file header
          +  int *** cnfTable, OUT: CNF table for clauses
          +  FILE * fp IN: source file
          +)
          +
          +
          Read the CNF clauses from the file in the standard DIMACS + format. Store all the clauses in an internal structure for + future transformation into BDDs. +

          + +

          Defined in dddmpLoadCnf.c + +
          +
          +int 
          +DddmpReadCode(
          +  FILE * fp, IN: file where to read the code
          +  struct binary_dd_code * pcode OUT: the read code
          +)
          +
          +
          Reads a 1 byte node code. See DddmpWriteCode() + for code description. +

          + +

          Side Effects None +

          + +

          See Also DddmpWriteCode() + + +
          Defined in dddmpBinary.c + +
          +
          +int 
          +DddmpReadInt(
          +  FILE * fp, IN: file where to read the integer
          +  int * pid OUT: the read integer
          +)
          +
          +
          Reads an integer coded on a sequence of bytes. See + DddmpWriteInt() for format. +

          + +

          Side Effects None +

          + +

          See Also DddmpWriteInt() + + +
          Defined in dddmpBinary.c + +
          +
          +int 
          +DddmpReadNodeIndexAdd(
          +  DdNode * f IN: BDD node
          +)
          +
          +
          Reads the index of a node. LSB is skipped (used as visited + flag). +

          + +

          Side Effects None +

          + +

          See Also DddmpWriteNodeIndexAdd +() +DddmpSetVisitedAdd +() +DddmpVisitedAdd +() + + +
          Defined in dddmpNodeAdd.c + +
          +
          +int 
          +DddmpReadNodeIndexBdd(
          +  DdNode * f IN: BDD node
          +)
          +
          +
          Reads the index of a node. LSB is skipped (used as visited + flag). +

          + +

          Side Effects None +

          + +

          See Also DddmpWriteNodeIndexBdd +() +DddmpSetVisitedBdd +() +DddmpVisitedBdd +() + + +
          Defined in dddmpNodeBdd.c + +
          +
          +int 
          +DddmpReadNodeIndexCnf(
          +  DdNode * f IN: BDD node
          +)
          +
          +
          Reads the index of a node. LSB is skipped (used as visited + flag). +

          + +

          Side Effects None +

          + +

          See Also DddmpWriteNodeIndexCnf() +DddmpSetVisitedCnf +() +DddmpVisitedCnf +() + + +
          Defined in dddmpNodeCnf.c + +
          +
          +static int 
          +DddmpReadNodeIndexCnf(
          +  DdNode * f IN: BDD node
          +)
          +
          +
          Reads the index of a node. LSB is skipped (used as visited + flag). +

          + +

          Side Effects None +

          + +

          See Also DddmpWriteNodeIndexCnf() +DddmpSetVisitedCnf +() +DddmpVisitedCnf +() + + +
          Defined in dddmpDdNodeCnf.c + +
          +
          +int 
          +DddmpReadNodeIndex(
          +  DdNode * f IN: BDD node
          +)
          +
          +
          Reads the index of a node. LSB is skipped (used as visited + flag). +

          + +

          Side Effects None +

          + +

          See Also DddmpWriteNodeIndex() +DddmpSetVisited +() +DddmpVisited +() + + +
          Defined in dddmpDdNodeBdd.c + +
          +
          +void 
          +DddmpSetVisitedAdd(
          +  DdNode * f IN: BDD node to be marked (as visited)
          +)
          +
          +
          Marks a node as visited +

          + +

          Side Effects None +

          + +

          See Also DddmpVisitedAdd +() +DddmpClearVisitedAdd +() + + +
          Defined in dddmpNodeAdd.c + +
          +
          +void 
          +DddmpSetVisitedBdd(
          +  DdNode * f IN: BDD node to be marked (as visited)
          +)
          +
          +
          Marks a node as visited +

          + +

          Side Effects None +

          + +

          See Also DddmpVisitedBdd +() +DddmpClearVisitedBdd +() + + +
          Defined in dddmpNodeBdd.c + +
          +
          +static void 
          +DddmpSetVisitedCnf(
          +  DdNode * f IN: BDD node to be marked (as visited)
          +)
          +
          +
          Marks a node as visited +

          + +

          Side Effects None +

          + +

          See Also DddmpVisitedCnf +() +DddmpClearVisitedCnf +() + + +
          Defined in dddmpDdNodeCnf.c + +
          +
          +void 
          +DddmpSetVisitedCnf(
          +  DdNode * f IN: BDD node to be marked (as visited)
          +)
          +
          +
          Marks a node as visited +

          + +

          Side Effects None +

          + +

          See Also DddmpVisitedCnf +() +DddmpClearVisitedCnf +() + + +
          Defined in dddmpNodeCnf.c + +
          +
          +void 
          +DddmpSetVisited(
          +  DdNode * f IN: BDD node to be marked (as visited)
          +)
          +
          +
          Marks a node as visited +

          + +

          Side Effects None +

          + +

          See Also DddmpVisited +() +DddmpClearVisited +() + + +
          Defined in dddmpDdNodeBdd.c + +
          +
          +char ** 
          +DddmpStrArrayDup(
          +  char ** array, IN: array of strings to be duplicated
          +  int  n IN: size of the array
          +)
          +
          +
          Allocates memory and copies source array +

          + +

          Side Effects None +

          + +

          Defined in dddmpUtil.c + +
          +
          +void 
          +DddmpStrArrayFree(
          +  char ** array, IN: array of strings
          +  int  n IN: size of the array
          +)
          +
          +
          Frees memory for strings and the array of pointers +

          + +

          Side Effects None +

          + +

          Defined in dddmpUtil.c + +
          +
          +char ** 
          +DddmpStrArrayRead(
          +  FILE * fp, IN: input file
          +  int  n IN: size of the array
          +)
          +
          +
          Allocates memory and inputs source array +

          + +

          Side Effects None +

          + +

          Defined in dddmpUtil.c + +
          +
          +int 
          +DddmpStrArrayWrite(
          +  FILE * fp, IN: output file
          +  char ** array, IN: array of strings
          +  int  n IN: size of the array
          +)
          +
          +
          Outputs an array of strings to a specified file +

          + +

          Side Effects None +

          + +

          Defined in dddmpUtil.c + +
          +
          +char * 
          +DddmpStrDup(
          +  char * str IN: string to be duplicated
          +)
          +
          +
          Allocates memory and copies source string +

          + +

          Side Effects None +

          + +

          Defined in dddmpUtil.c + +
          +
          +void 
          +DddmpUnnumberAddNodes(
          +  DdManager * ddMgr, IN: DD Manager
          +  DdNode ** f, IN: array of BDDs
          +  int  n IN: number of BDD roots in the array of BDDs
          +)
          +
          +
          Node indexes are no more needed. Nodes are re-linked in the + unique table. +

          + +

          Side Effects None +

          + +

          See Also DddmpNumberDdNodeAdd +() + + +
          Defined in dddmpNodeAdd.c + +
          +
          +void 
          +DddmpUnnumberBddNodes(
          +  DdManager * ddMgr, IN: DD Manager
          +  DdNode ** f, IN: array of BDDs
          +  int  n IN: number of BDD roots in the array of BDDs
          +)
          +
          +
          Node indexes are no more needed. Nodes are re-linked in the + unique table. +

          + +

          Side Effects None +

          + +

          See Also DddmpNumberBddNode +() + + +
          Defined in dddmpNodeBdd.c + +
          +
          +void 
          +DddmpUnnumberDdNodesCnf(
          +  DdManager * ddMgr, IN: DD Manager
          +  DdNode ** f, IN: array of BDDs
          +  int  rootN IN: number of BDD roots in the array of BDDs
          +)
          +
          +
          Node indexes are no more needed. Nodes are re-linked in the + unique table. +

          + +

          Side Effects None +

          + +

          See Also DddmpNumberDdNode() + + +
          Defined in dddmpDdNodeCnf.c + +
          +
          +void 
          +DddmpUnnumberDdNodesCnf(
          +  DdManager * ddMgr, IN: DD Manager
          +  DdNode ** f, IN: array of BDDs
          +  int  rootN IN: number of BDD roots in the array of BDDs
          +)
          +
          +
          Node indexes are no more needed. Nodes are re-linked in the + unique table. +

          + +

          Side Effects None +

          + +

          See Also DddmpNumberDdNode() + + +
          Defined in dddmpNodeCnf.c + +
          +
          +void 
          +DddmpUnnumberDdNodes(
          +  DdManager * ddMgr, IN: DD Manager
          +  DdNode ** f, IN: array of BDDs
          +  int  n IN: number of BDD roots in the array of BDDs
          +)
          +
          +
          Node indexes are no more needed. Nodes are re-linked in the + unique table. +

          + +

          Side Effects None +

          + +

          See Also DddmpNumberDdNode() + + +
          Defined in dddmpDdNodeBdd.c + +
          +
          +int 
          +DddmpVisitedAdd(
          +  DdNode * f IN: BDD node to be tested
          +)
          +
          +
          Returns true if node is visited +

          + +

          Side Effects None +

          + +

          See Also DddmpSetVisitedAdd +() +DddmpClearVisitedAdd +() + + +
          Defined in dddmpNodeAdd.c + +
          +
          +int 
          +DddmpVisitedBdd(
          +  DdNode * f IN: BDD node to be tested
          +)
          +
          +
          Returns true if node is visited +

          + +

          Side Effects None +

          + +

          See Also DddmpSetVisitedBdd +() +DddmpClearVisitedBdd +() + + +
          Defined in dddmpNodeBdd.c + +
          +
          +int 
          +DddmpVisitedCnf(
          +  DdNode * f IN: BDD node to be tested
          +)
          +
          +
          Returns true if node is visited +

          + +

          Side Effects None +

          + +

          See Also DddmpSetVisitedCnf +() +DddmpClearVisitedCnf +() + + +
          Defined in dddmpNodeCnf.c + +
          +
          +static int 
          +DddmpVisitedCnf(
          +  DdNode * f IN: BDD node to be tested
          +)
          +
          +
          Returns true if node is visited +

          + +

          Side Effects None +

          + +

          See Also DddmpSetVisitedCnf +() +DddmpClearVisitedCnf +() + + +
          Defined in dddmpDdNodeCnf.c + +
          +
          +int 
          +DddmpVisited(
          +  DdNode * f IN: BDD node to be tested
          +)
          +
          +
          Returns true if node is visited +

          + +

          Side Effects None +

          + +

          See Also DddmpSetVisited +() +DddmpClearVisited +() + + +
          Defined in dddmpDdNodeBdd.c + +
          +
          +int 
          +DddmpWriteCode(
          +  FILE * fp, IN: file where to write the code
          +  struct binary_dd_code  code IN: the code to be written
          +)
          +
          +
          outputs a 1 byte node code using the following format: +
          +     Unused      : 1 bit;
          +     V           : 2 bits;     (variable code)
          +     T           : 2 bits;     (Then code)
          +     Ecompl      : 1 bit;      (Else complemented)
          +     E           : 2 bits;     (Else code)
          +    
          + Ecompl is set with complemented edges. +

          + +

          Side Effects None +

          + +

          See Also DddmpReadCode() + + +
          Defined in dddmpBinary.c + +
          +
          +int 
          +DddmpWriteInt(
          +  FILE * fp, IN: file where to write the integer
          +  int  id IN: integer to be written
          +)
          +
          +
          Writes an integer as a sequence of bytes (MSByte first). + For each byte 7 bits are used for data and one (LSBit) as link + with a further byte (LSB = 1 means one more byte). +

          + +

          Side Effects None +

          + +

          See Also DddmpReadInt() + + +
          Defined in dddmpBinary.c + +
          +
          +void 
          +DddmpWriteNodeIndexAdd(
          +  DdNode * f, IN: BDD node
          +  int  id IN: index to be written
          +)
          +
          +
          The index of the node is written in the "next" field of + a DdNode struct. LSB is not used (set to 0). It is used as + "visited" flag in DD traversals. +

          + +

          Side Effects None +

          + +

          See Also DddmpReadNodeIndexAdd +() +DddmpSetVisitedAdd +() +DddmpVisitedAdd +() + + +
          Defined in dddmpNodeAdd.c + +
          +
          +void 
          +DddmpWriteNodeIndexBdd(
          +  DdNode * f, IN: BDD node
          +  int  id IN: index to be written
          +)
          +
          +
          The index of the node is written in the "next" field of + a DdNode struct. LSB is not used (set to 0). It is used as + "visited" flag in DD traversals. +

          + +

          Side Effects None +

          + +

          See Also DddmpReadNodeIndexBdd() +DddmpSetVisitedBdd +() +DddmpVisitedBdd +() + + +
          Defined in dddmpNodeBdd.c + +
          +
          +int 
          +DddmpWriteNodeIndexCnfBis(
          +  DdNode * f, IN: BDD node
          +  int  id IN: index to be written
          +)
          +
          +
          The index of the node is written in the "next" field of + a DdNode struct. LSB is not used (set to 0). It is used as + "visited" flag in DD traversals. +

          + +

          Side Effects None +

          + +

          See Also DddmpReadNodeIndexCnf() +DddmpSetVisitedCnf +() +DddmpVisitedCnf +() + + +
          Defined in dddmpDdNodeCnf.c + +
          +
          +static int 
          +DddmpWriteNodeIndexCnfWithTerminalCheck(
          +  DdNode * f, IN: BDD node
          +  int * cnfIds, IN: possible source for the index to be written
          +  int  id IN: possible source for the index to be written
          +)
          +
          +
          The index of the node is written in the "next" field of + a DdNode struct. LSB is not used (set to 0). It is used as + "visited" flag in DD traversals. The index corresponds to + the BDD node variable if both the node's children are a + constant node, otherwise a new CNF variable is used. +

          + +

          Side Effects None +

          + +

          See Also DddmpReadNodeIndexCnf() +DddmpSetVisitedCnf +() +DddmpVisitedCnf +() + + +
          Defined in dddmpNodeCnf.c + +
          +
          +int 
          +DddmpWriteNodeIndexCnf(
          +  DdNode * f, IN: BDD node
          +  int  id IN: index to be written
          +)
          +
          +
          The index of the node is written in the "next" field of + a DdNode struct. LSB is not used (set to 0). It is used as + "visited" flag in DD traversals. +

          + +

          Side Effects None +

          + +

          See Also DddmpReadNodeIndexCnf() +DddmpSetVisitedCnf +() +DddmpVisitedCnf +() + + +
          Defined in dddmpNodeCnf.c + +
          +
          +static int 
          +DddmpWriteNodeIndexCnf(
          +  DdNode * f, IN: BDD node
          +  int * cnfIds, IN: possible source for the index to be written
          +  int  id IN: possible source for the index to be written
          +)
          +
          +
          The index of the node is written in the "next" field of + a DdNode struct. LSB is not used (set to 0). It is used as + "visited" flag in DD traversals. The index corresponds to + the BDD node variable if both the node's children are a + constant node, otherwise a new CNF variable is used. +

          + +

          Side Effects None +

          + +

          See Also DddmpReadNodeIndexCnf() +DddmpSetVisitedCnf +() +DddmpVisitedCnf +() + + +
          Defined in dddmpDdNodeCnf.c + +
          +
          +void 
          +DddmpWriteNodeIndex(
          +  DdNode * f, IN: BDD node
          +  int  id IN: index to be written
          +)
          +
          +
          The index of the node is written in the "next" field of + a DdNode struct. LSB is not used (set to 0). It is used as + "visited" flag in DD traversals. +

          + +

          Side Effects None +

          + +

          See Also DddmpReadNodeIndex() +DddmpSetVisited +() +DddmpVisited +() + + +
          Defined in dddmpDdNodeBdd.c + +
          +
          +int 
          +Dddmp_Bin2Text(
          +  char * filein, IN: name of binary file
          +  char * fileout IN: name of ASCII file
          +)
          +
          +
          Converts from binary to ASCII format. A BDD array is loaded and + and stored to the target file. +

          + +

          Side Effects None +

          + +

          See Also Dddmp_Text2Bin() + + +
          Defined in dddmpConvert.c + +
          +
          +int 
          +Dddmp_Text2Bin(
          +  char * filein, IN: name of ASCII file
          +  char * fileout IN: name of binary file
          +)
          +
          +
          Converts from ASCII to binary format. A BDD array is loaded and + and stored to the target file. +

          + +

          Side Effects None +

          + +

          See Also Dddmp_Bin2Text() + + +
          Defined in dddmpConvert.c + +
          +
          +int 
          +Dddmp_cuddAddArrayLoad(
          +  DdManager * ddMgr, IN: DD Manager
          +  Dddmp_RootMatchType  rootMatchMode, IN: storing mode selector
          +  char ** rootmatchnames, IN: sorted names for loaded roots
          +  Dddmp_VarMatchType  varMatchMode, IN: storing mode selector
          +  char ** varmatchnames, IN: array of variable names, by ids
          +  int * varmatchauxids, IN: array of variable auxids, by ids
          +  int * varcomposeids, IN: array of new ids, by ids
          +  int  mode, IN: requested input file format
          +  char * file, IN: file name
          +  FILE * fp, IN: file pointer
          +  DdNode *** pproots OUT: array of returned BDD roots
          +)
          +
          +
          Reads a dump file representing the argument ADDs. See + BDD load functions for detailed explanation. +

          + +

          Side Effects A vector of pointers to DD nodes is allocated and freed. +

          + +

          See Also Dddmp_cuddBddArrayStore + + +
          Defined in dddmpLoad.c + +
          +
          +int 
          +Dddmp_cuddAddArrayStore(
          +  DdManager * ddMgr, IN: DD Manager
          +  char * ddname, IN: DD name (or NULL)
          +  int  nRoots, IN: number of output BDD roots to be stored
          +  DdNode ** f, IN: array of ADD roots to be stored
          +  char ** rootnames, IN: array of root names (or NULL)
          +  char ** varnames, IN: array of variable names (or NULL)
          +  int * auxids, IN: array of converted var IDs
          +  int  mode, IN: storing mode selector
          +  Dddmp_VarInfoType  varinfo, IN: extra info for variables in text mode
          +  char * fname, IN: File name
          +  FILE * fp IN: File pointer to the store file
          +)
          +
          +
          Dumps the argument array of ADDs to file. Dumping is + either in text or binary form. see the corresponding BDD dump + function for further details. +

          + +

          Side Effects Nodes are temporarily removed from the unique hash + table. They are re-linked after the store operation in a + modified order. +

          + +

          See Also Dddmp_cuddAddStore +Dddmp_cuddAddLoad +Dddmp_cuddAddArrayLoad + + +
          Defined in dddmpStoreAdd.c + +
          +
          +DdNode * 
          +Dddmp_cuddAddLoad(
          +  DdManager * ddMgr, IN: Manager
          +  Dddmp_VarMatchType  varMatchMode, IN: storing mode selector
          +  char ** varmatchnames, IN: array of variable names by IDs
          +  int * varmatchauxids, IN: array of variable auxids by IDs
          +  int * varcomposeids, IN: array of new ids by IDs
          +  int  mode, IN: requested input file format
          +  char * file, IN: file name
          +  FILE * fp IN: file pointer
          +)
          +
          +
          Reads a dump file representing the argument ADD. + Dddmp_cuddAddArrayLoad is used through a dummy array. +

          + +

          Side Effects A vector of pointers to DD nodes is allocated and freed. +

          + +

          See Also Dddmp_cuddAddStore +Dddmp_cuddAddArrayLoad + + +
          Defined in dddmpLoad.c + +
          +
          +int 
          +Dddmp_cuddAddStore(
          +  DdManager * ddMgr, IN: DD Manager
          +  char * ddname, IN: DD name (or NULL)
          +  DdNode * f, IN: ADD root to be stored
          +  char ** varnames, IN: array of variable names (or NULL)
          +  int * auxids, IN: array of converted var ids
          +  int  mode, IN: storing mode selector
          +  Dddmp_VarInfoType  varinfo, IN: extra info for variables in text mode
          +  char * fname, IN: File name
          +  FILE * fp IN: File pointer to the store file
          +)
          +
          +
          Dumps the argument ADD to file. Dumping is done through + Dddmp_cuddAddArrayStore, And a dummy array of 1 ADD root is + used for this purpose. +

          + +

          Side Effects Nodes are temporarily removed from unique hash. They are + re-linked after the store operation in a modified order. +

          + +

          See Also Dddmp_cuddAddLoad +Dddmp_cuddAddArrayLoad + + +
          Defined in dddmpStoreAdd.c + +
          +
          +int 
          +Dddmp_cuddBddArrayLoadCnf(
          +  DdManager * ddMgr, IN: DD Manager
          +  Dddmp_RootMatchType  rootmatchmode, IN: storing mode selector
          +  char ** rootmatchnames, IN: sorted names for loaded roots
          +  Dddmp_VarMatchType  varmatchmode, IN: storing mode selector
          +  char ** varmatchnames, IN: array of variable names, by IDs
          +  int * varmatchauxids, IN: array of variable auxids, by IDs
          +  int * varcomposeids, IN: array of new ids, by IDs
          +  int  mode, IN: computation Mode
          +  char * file, IN: file name
          +  FILE * fp, IN: file pointer
          +  DdNode *** rootsPtrPtr, OUT: array of returned BDD roots
          +  int * nRoots OUT: number of BDDs returned
          +)
          +
          +
          Reads a dump file representing the argument BDD in a + CNF formula. +

          + +

          Side Effects A vector of pointers to DD nodes is allocated and freed. +

          + +

          See Also Dddmp_cuddBddArrayLoad + + +
          Defined in dddmpLoadCnf.c + +
          +
          +int 
          +Dddmp_cuddBddArrayLoad(
          +  DdManager * ddMgr, IN: DD Manager
          +  Dddmp_RootMatchType  rootMatchMode, IN: storing mode selector
          +  char ** rootmatchnames, IN: sorted names for loaded roots
          +  Dddmp_VarMatchType  varMatchMode, IN: storing mode selector
          +  char ** varmatchnames, IN: array of variable names, by ids
          +  int * varmatchauxids, IN: array of variable auxids, by ids
          +  int * varcomposeids, IN: array of new ids, by ids
          +  int  mode, IN: requested input file format
          +  char * file, IN: file name
          +  FILE * fp, IN: file pointer
          +  DdNode *** pproots OUT: array of returned BDD roots
          +)
          +
          +
          Reads a dump file representing the argument BDDs. The header is + common to both text and binary mode. The node list is either + in text or binary format. A dynamic vector of DD pointers + is allocated to support conversion from DD indexes to pointers. + Several criteria are supported for variable match between file + and dd manager. Several changes/permutations/compositions are allowed + for variables while loading DDs. Variable of the dd manager are allowed + to match with variables on file on ids, permids, varnames, + varauxids; also direct composition between ids and + composeids is supported. More in detail: +
            +
          1. varMatchMode=DDDMP_VAR_MATCHIDS

            + allows the loading of a DD keeping variable IDs unchanged + (regardless of the variable ordering of the reading manager); this + is useful, for example, when swapping DDs to file and restoring them + later from file, after possible variable reordering activations. + +

          2. varMatchMode=DDDMP_VAR_MATCHPERMIDS

            + is used to allow variable match according to the position in the + ordering. + +

          3. varMatchMode=DDDMP_VAR_MATCHNAMES

            + requires a non NULL varmatchnames parameter; this is a vector of + strings in one-to-one correspondence with variable IDs of the + reading manager. Variables in the DD file read are matched with + manager variables according to their name (a non NULL varnames + parameter was required while storing the DD file). + +

          4. varMatchMode=DDDMP_VAR_MATCHIDS

            + has a meaning similar to DDDMP_VAR_MATCHNAMES, but integer auxiliary + IDs are used instead of strings; the additional non NULL + varmatchauxids parameter is needed. + +

          5. varMatchMode=DDDMP_VAR_COMPOSEIDS

            + uses the additional varcomposeids parameter is used as array of + variable ids to be composed with ids stored in file. +

          + + In the present implementation, the array varnames (3), varauxids (4) + and composeids (5) need to have one entry for each variable in the + DD manager (NULL pointers are allowed for unused variables + in varnames). Hence variables need to be already present in the + manager. All arrays are sorted according to IDs. + + All the loaded BDDs are referenced before returning them. +

          + +

          Side Effects A vector of pointers to DD nodes is allocated and freed. +

          + +

          See Also Dddmp_cuddBddArrayStore + + +
          Defined in dddmpLoad.c + +
          +
          +int 
          +Dddmp_cuddBddArrayStoreBlif(
          +  DdManager * ddMgr, IN: DD Manager
          +  int  nroots, IN: number of output BDD roots to be stored
          +  DdNode ** f, IN: array of BDD roots to be stored
          +  char ** inputNames, IN: array of variable names (or NULL)
          +  char ** outputNames, IN: array of root names (or NULL)
          +  char * modelName, IN: Model Name
          +  char * fname, IN: File name
          +  FILE * fp IN: File pointer to the store file
          +)
          +
          +
          Dumps the argument BDD to file. + Dumping is done through Dddmp_cuddBddArrayStoreBLif. + A dummy array of 1 BDD root is used for this purpose. +

          + +

          See Also Dddmp_cuddBddArrayStorePrefix + + +
          Defined in dddmpStoreMisc.c + +
          +
          +int 
          +Dddmp_cuddBddArrayStoreCnf(
          +  DdManager * ddMgr, IN: DD Manager
          +  DdNode ** f, IN: array of BDD roots to be stored
          +  int  rootN, IN: # output BDD roots to be stored
          +  Dddmp_DecompCnfStoreType  mode, IN: format selection
          +  int  noHeader, IN: do not store header iff 1
          +  char ** varNames, IN: array of variable names (or NULL)
          +  int * bddIds, IN: array of converted var IDs
          +  int * bddAuxIds, IN: array of BDD node Auxiliary Ids
          +  int * cnfIds, IN: array of converted var IDs
          +  int  idInitial, IN: starting id for cutting variables
          +  int  edgeInTh, IN: Max # Incoming Edges
          +  int  pathLengthTh, IN: Max Path Length
          +  char * fname, IN: file name
          +  FILE * fp, IN: pointer to the store file
          +  int * clauseNPtr, OUT: number of clause stored
          +  int * varNewNPtr OUT: number of new variable created
          +)
          +
          +
          Dumps the argument array of BDDs to file. +

          + +

          Side Effects Nodes are temporarily removed from the unique hash + table. They are re-linked after the store operation in a + modified order. + Three methods are allowed: + * NodeByNode method: Insert a cut-point for each BDD node (but the + terminal nodes) + * MaxtermByMaxterm method: Insert no cut-points, i.e. the off-set of + trhe function is stored + * Best method: Tradeoff between the previous two methods. + Auxiliary variables, i.e., cut points are inserted following these + criterias: + * edgeInTh + indicates the maximum number of incoming edges up to which + no cut point (auxiliary variable) is inserted. + If edgeInTh: + * is equal to -1 no cut point due to incoming edges are inserted + (MaxtermByMaxterm method.) + * is equal to 0 a cut point is inserted for each node with a single + incoming edge, i.e., each node, (NodeByNode method). + * is equal to n a cut point is inserted for each node with (n+1) + incoming edges. + * pathLengthTh + indicates the maximum length path up to which no cut points + (auxiliary variable) is inserted. + If the path length between two nodes exceeds this value, a cut point + is inserted. + If pathLengthTh: + * is equal to -1 no cut point due path length are inserted + (MaxtermByMaxterm method.) + * is equal to 0 a cut point is inserted for each node (NodeByNode + method). + * is equal to n a cut point is inserted on path whose length is + equal to (n+1). + Notice that the maximum number of literals in a clause is equal + to (pathLengthTh + 2), i.e., for each path we have to keep into + account a CNF variable for each node plus 2 added variables for + the bottom and top-path cut points. + The stored file can contain a file header or not depending on the + noHeader parameter (IFF 0, usual setting, the header is usually stored. + This option can be useful in storing multiple BDDs, as separate BDDs, + on the same file leaving the opening of the file to the caller. +

          + +

          Defined in dddmpStoreCnf.c + +
          +
          +int 
          +Dddmp_cuddBddArrayStorePrefix(
          +  DdManager * ddMgr, IN: DD Manager
          +  int  nroots, IN: number of output BDD roots to be stored
          +  DdNode ** f, IN: array of BDD roots to be stored
          +  char ** inputNames, IN: array of variable names (or NULL)
          +  char ** outputNames, IN: array of root names (or NULL)
          +  char * modelName, IN: Model Name
          +  char * fname, IN: File name
          +  FILE * fp IN: File pointer to the store file
          +)
          +
          +
          Dumps the argument BDD to file. + Dumping is done through Dddmp_cuddBddArrayStorePrefix. + A dummy array of 1 BDD root is used for this purpose. +

          + +

          See Also Dddmp_cuddBddArrayStore + + +
          Defined in dddmpStoreMisc.c + +
          +
          +int 
          +Dddmp_cuddBddArrayStoreSmv(
          +  DdManager * ddMgr, IN: DD Manager
          +  int  nroots, IN: number of output BDD roots to be stored
          +  DdNode ** f, IN: array of BDD roots to be stored
          +  char ** inputNames, IN: array of variable names (or NULL)
          +  char ** outputNames, IN: array of root names (or NULL)
          +  char * modelName, IN: Model Name
          +  char * fname, IN: File name
          +  FILE * fp IN: File pointer to the store file
          +)
          +
          +
          Dumps the argument BDD to file. + Dumping is done through Dddmp_cuddBddArrayStorePrefix. + A dummy array of 1 BDD root is used for this purpose. +

          + +

          See Also Dddmp_cuddBddArrayStore + + +
          Defined in dddmpStoreMisc.c + +
          +
          +int 
          +Dddmp_cuddBddArrayStore(
          +  DdManager * ddMgr, IN: DD Manager
          +  char * ddname, IN: dd name (or NULL)
          +  int  nRoots, IN: number of output BDD roots to be stored
          +  DdNode ** f, IN: array of BDD roots to be stored
          +  char ** rootnames, IN: array of root names (or NULL)
          +  char ** varnames, IN: array of variable names (or NULL)
          +  int * auxids, IN: array of converted var IDs
          +  int  mode, IN: storing mode selector
          +  Dddmp_VarInfoType  varinfo, IN: extra info for variables in text mode
          +  char * fname, IN: File name
          +  FILE * fp IN: File pointer to the store file
          +)
          +
          +
          Dumps the argument array of BDDs to file. Dumping is either + in text or binary form. BDDs are stored to the fp (already + open) file if not NULL. Otherwise the file whose name is + fname is opened in write mode. The header has the same format + for both textual and binary dump. Names are allowed for input + variables (vnames) and for represented functions (rnames). + For sake of generality and because of dynamic variable + ordering both variable IDs and permuted IDs are included. + New IDs are also supported (auxids). Variables are identified + with incremental numbers. according with their positiom in + the support set. In text mode, an extra info may be added, + chosen among the following options: name, ID, PermID, or an + auxiliary id. Since conversion from DD pointers to integers + is required, DD nodes are temporarily removed from the unique + hash table. This allows the use of the next field to store + node IDs. +

          + +

          Side Effects Nodes are temporarily removed from the unique hash + table. They are re-linked after the store operation in a + modified order. +

          + +

          See Also Dddmp_cuddBddStore +Dddmp_cuddBddLoad +Dddmp_cuddBddArrayLoad + + +
          Defined in dddmpStoreBdd.c + +
          +
          +int 
          +Dddmp_cuddBddDisplayBinary(
          +  char * fileIn, IN: name of binary file
          +  char * fileOut IN: name of text file
          +)
          +
          +
          Display a binary dump file in a text file +

          + +

          Side Effects None +

          + +

          See Also Dddmp_cuddBddStore +Dddmp_cuddBddLoad + + +
          Defined in dddmpDbg.c + +
          +
          +int 
          +Dddmp_cuddBddLoadCnf(
          +  DdManager * ddMgr, IN: DD Manager
          +  Dddmp_VarMatchType  varmatchmode, IN: storing mode selector
          +  char ** varmatchnames, IN: array of variable names, by IDs
          +  int * varmatchauxids, IN: array of variable auxids, by IDs
          +  int * varcomposeids, IN: array of new ids accessed, by IDs
          +  int  mode, IN: computation mode
          +  char * file, IN: file name
          +  FILE * fp, IN: file pointer
          +  DdNode *** rootsPtrPtr, OUT: array of returned BDD roots
          +  int * nRoots OUT: number of BDDs returned
          +)
          +
          +
          Reads a dump file representing the argument BDD in a + CNF formula. + Dddmp_cuddBddArrayLoadCnf is used through a dummy array. + The results is returned in different formats depending on the + mode selection: + IFF mode == 0 Return the Clauses without Conjunction + IFF mode == 1 Return the sets of BDDs without Quantification + IFF mode == 2 Return the sets of BDDs AFTER Existential Quantification +

          + +

          Side Effects A vector of pointers to DD nodes is allocated and freed. +

          + +

          See Also Dddmp_cuddBddLoad +Dddmp_cuddBddArrayLoad + + +
          Defined in dddmpLoadCnf.c + +
          +
          +DdNode * 
          +Dddmp_cuddBddLoad(
          +  DdManager * ddMgr, IN: DD Manager
          +  Dddmp_VarMatchType  varMatchMode, IN: storing mode selector
          +  char ** varmatchnames, IN: array of variable names - by IDs
          +  int * varmatchauxids, IN: array of variable auxids - by IDs
          +  int * varcomposeids, IN: array of new ids accessed - by IDs
          +  int  mode, IN: requested input file format
          +  char * file, IN: file name
          +  FILE * fp IN: file pointer
          +)
          +
          +
          Reads a dump file representing the argument BDD. + Dddmp_cuddBddArrayLoad is used through a dummy array (see this + function's description for more details). + Mode, the requested input file format, is checked against + the file format. + The loaded BDDs is referenced before returning it. +

          + +

          Side Effects A vector of pointers to DD nodes is allocated and freed. +

          + +

          See Also Dddmp_cuddBddStore +Dddmp_cuddBddArrayLoad + + +
          Defined in dddmpLoad.c + +
          +
          +int 
          +Dddmp_cuddBddStoreBlif(
          +  DdManager * ddMgr, IN: DD Manager
          +  int  nRoots, IN: Number of BDD roots
          +  DdNode * f, IN: BDD root to be stored
          +  char ** inputNames, IN: Array of variable names
          +  char ** outputNames, IN: Array of root names
          +  char * modelName, IN: Model Name
          +  char * fileName, IN: File name
          +  FILE * fp IN: File pointer to the store file
          +)
          +
          +
          Dumps the argument BDD to file. + Dumping is done through Dddmp_cuddBddArrayStoreBlif. + A dummy array of 1 BDD root is used for this purpose. +

          + +

          See Also Dddmp_cuddBddStorePrefix + + +
          Defined in dddmpStoreMisc.c + +
          +
          +int 
          +Dddmp_cuddBddStoreCnf(
          +  DdManager * ddMgr, IN: DD Manager
          +  DdNode * f, IN: BDD root to be stored
          +  Dddmp_DecompCnfStoreType  mode, IN: format selection
          +  int  noHeader, IN: do not store header iff 1
          +  char ** varNames, IN: array of variable names (or NULL)
          +  int * bddIds, IN: array of var ids
          +  int * bddAuxIds, IN: array of BDD node Auxiliary Ids
          +  int * cnfIds, IN: array of CNF var ids
          +  int  idInitial, IN: starting id for cutting variables
          +  int  edgeInTh, IN: Max # Incoming Edges
          +  int  pathLengthTh, IN: Max Path Length
          +  char * fname, IN: file name
          +  FILE * fp, IN: pointer to the store file
          +  int * clauseNPtr, OUT: number of clause stored
          +  int * varNewNPtr OUT: number of new variable created
          +)
          +
          +
          Dumps the argument BDD to file. + This task is performed by calling the function + Dddmp_cuddBddArrayStoreCnf. +

          + +

          Side Effects Nodes are temporarily removed from unique hash. They are + re-linked after the store operation in a modified order. +

          + +

          See Also Dddmp_cuddBddArrayStoreCnf + + +
          Defined in dddmpStoreCnf.c + +
          +
          +int 
          +Dddmp_cuddBddStorePrefix(
          +  DdManager * ddMgr, IN: DD Manager
          +  int  nRoots, IN: Number of BDD roots
          +  DdNode * f, IN: BDD root to be stored
          +  char ** inputNames, IN: Array of variable names
          +  char ** outputNames, IN: Array of root names
          +  char * modelName, IN: Model Name
          +  char * fileName, IN: File name
          +  FILE * fp IN: File pointer to the store file
          +)
          +
          +
          Dumps the argument BDD to file. + Dumping is done through Dddmp_cuddBddArrayStorePrefix. + A dummy array of 1 BDD root is used for this purpose. +

          + +

          See Also Dddmp_cuddBddStore + + +
          Defined in dddmpStoreMisc.c + +
          +
          +int 
          +Dddmp_cuddBddStoreSmv(
          +  DdManager * ddMgr, IN: DD Manager
          +  int  nRoots, IN: Number of BDD roots
          +  DdNode * f, IN: BDD root to be stored
          +  char ** inputNames, IN: Array of variable names
          +  char ** outputNames, IN: Array of root names
          +  char * modelName, IN: Model Name
          +  char * fileName, IN: File name
          +  FILE * fp IN: File pointer to the store file
          +)
          +
          +
          Dumps the argument BDD to file. + Dumping is done through Dddmp_cuddBddArrayStorePrefix. + A dummy array of 1 BDD root is used for this purpose. +

          + +

          See Also Dddmp_cuddBddStore + + +
          Defined in dddmpStoreMisc.c + +
          +
          +int 
          +Dddmp_cuddBddStore(
          +  DdManager * ddMgr, IN: DD Manager
          +  char * ddname, IN: DD name (or NULL)
          +  DdNode * f, IN: BDD root to be stored
          +  char ** varnames, IN: array of variable names (or NULL)
          +  int * auxids, IN: array of converted var ids
          +  int  mode, IN: storing mode selector
          +  Dddmp_VarInfoType  varinfo, IN: extra info for variables in text mode
          +  char * fname, IN: File name
          +  FILE * fp IN: File pointer to the store file
          +)
          +
          +
          Dumps the argument BDD to file. Dumping is done through + Dddmp_cuddBddArrayStore. A dummy array of 1 BDD root is + used for this purpose. +

          + +

          Side Effects Nodes are temporarily removed from unique hash. They are + re-linked after the store operation in a modified order. +

          + +

          See Also Dddmp_cuddBddLoad +Dddmp_cuddBddArrayLoad + + +
          Defined in dddmpStoreBdd.c + +
          +
          +int 
          +Dddmp_cuddHeaderLoadCnf(
          +  int * nVars, OUT: number of DD variables
          +  int * nsuppvars, OUT: number of support variables
          +  char *** suppVarNames, OUT: array of support variable names
          +  char *** orderedVarNames, OUT: array of variable names
          +  int ** varIds, OUT: array of variable ids
          +  int ** varComposeIds, OUT: array of permids ids
          +  int ** varAuxIds, OUT: array of variable aux ids
          +  int * nRoots, OUT: number of root in the file
          +  char * file, IN: file name
          +  FILE * fp IN: file pointer
          +)
          +
          +
          Reads the header of a dump file representing the argument BDDs. + Returns main information regarding DD type stored in the file, + the variable ordering used, the number of variables, etc. + It reads only the header of the file NOT the BDD/ADD section. +

          + +

          See Also Dddmp_cuddBddArrayLoad + + +
          Defined in dddmpLoadCnf.c + +
          +
          +int 
          +Dddmp_cuddHeaderLoad(
          +  Dddmp_DecompType * ddType, OUT: selects the proper decomp type
          +  int * nVars, OUT: number of DD variables
          +  int * nsuppvars, OUT: number of support variables
          +  char *** suppVarNames, OUT: array of support variable names
          +  char *** orderedVarNames, OUT: array of variable names
          +  int ** varIds, OUT: array of variable ids
          +  int ** varComposeIds, OUT: array of permids ids
          +  int ** varAuxIds, OUT: array of variable aux ids
          +  int * nRoots, OUT: number of root in the file
          +  char * file, IN: file name
          +  FILE * fp IN: file pointer
          +)
          +
          +
          Reads the header of a dump file representing the argument BDDs. + Returns main information regarding DD type stored in the file, + the variable ordering used, the number of variables, etc. + It reads only the header of the file NOT the BDD/ADD section. +

          + +

          See Also Dddmp_cuddBddArrayLoad + + +
          Defined in dddmpLoad.c + +
          +
          +int 
          +FindVarname(
          +  char * name, IN: name to look for
          +  char ** array, IN: search array
          +  int  n IN: size of the array
          +)
          +
          +
          Binary search of a name within a sorted array of strings. + Used when matching names of variables. +

          + +

          Side Effects None +

          + +

          Defined in dddmpUtil.c + +
          +
          +static int 
          +NodeBinaryStoreBdd(
          +  DdManager * ddMgr, IN: DD Manager
          +  DdNode * f, IN: DD node to be stored
          +  int  mode, IN: store mode
          +  int * supportids, IN: internal ids for variables
          +  char ** varnames, IN: names of variables: to be stored with nodes
          +  int * outids, IN: output ids for variables
          +  FILE * fp, IN: store file
          +  int  idf, IN: index of the node
          +  int  vf, IN: variable of the node
          +  int  idT, IN: index of the Then node
          +  int  idE, IN: index of the Else node
          +  int  vT, IN: variable of the Then node
          +  int  vE, IN: variable of the Else node
          +  DdNode * T, IN: Then node
          +  DdNode * E IN: Else node
          +)
          +
          +
          Store 1 0 0 for the terminal node. + Store id, left child pointer, right pointer for all the other nodes. + Store every information as coded binary values. +

          + +

          Side Effects None +

          + +

          See Also NodeTextStoreBdd + + +
          Defined in dddmpStoreBdd.c + +
          +
          +static int 
          +NodeStoreRecurAdd(
          +  DdManager * ddMgr, IN: DD Manager
          +  DdNode * f, IN: DD node to be stored
          +  int  mode, IN: store mode
          +  int * supportids, IN: internal ids for variables
          +  char ** varnames, IN: names of variables: to be stored with nodes
          +  int * outids, IN: output ids for variables
          +  FILE * fp IN: store file
          +)
          +
          +
          Stores a node to file in either test or binary mode. + In text mode a node is represented (on a text line basis) as +
            +
          • node-index [var-extrainfo] var-index Then-index Else-index +
          + + where all indexes are integer numbers and var-extrainfo + (optional redundant field) is either an integer or a string + (variable name). Node-index is redundant (due to the node + ordering) but we keep it for readability.

          + + In binary mode nodes are represented as a sequence of bytes, + representing var-index, Then-index, and Else-index in an + optimized way. Only the first byte (code) is mandatory. + Integer indexes are represented in absolute or relative mode, + where relative means offset wrt. a Then/Else node info. + Suppose Var(NodeId), Then(NodeId) and Else(NodeId) represent + infos about a given node.

          + + The generic "NodeId" node is stored as + +

            +
          • code-byte +
          • [var-info] +
          • [Then-info] +
          • [Else-info] +
          + + where code-byte contains bit fields + +
            +
          • Unused : 1 bit +
          • Variable: 2 bits, one of the following codes +
              +
            • DDDMP_ABSOLUTE_ID var-info = Var(NodeId) follows +
            • DDDMP_RELATIVE_ID Var(NodeId) is represented in relative form as + var-info = Min(Var(Then(NodeId)),Var(Else(NodeId))) -Var(NodeId) +
            • DDDMP_RELATIVE_1 No var-info follows, because + Var(NodeId) = Min(Var(Then(NodeId)),Var(Else(NodeId)))-1 +
            • DDDMP_TERMINAL Node is a terminal, no var info required +
            +
          • T : 2 bits, with codes similar to V +
              +
            • DDDMP_ABSOLUTE_ID Then-info = Then(NodeId) follows +
            • DDDMP_RELATIVE_ID Then(NodeId) is represented in relative form as + Then-info = Nodeid-Then(NodeId) +
            • DDDMP_RELATIVE_1 No info on Then(NodeId) follows, because + Then(NodeId) = NodeId-1 +
            • DDDMP_TERMINAL Then Node is a terminal, no info required (for BDDs) +
            +
          • Ecompl : 1 bit, if 1 means complemented edge +
          • E : 2 bits, with codes and meanings as for the Then edge +
          + var-info, Then-info, Else-info (if required) are represented as unsigned + integer values on a sufficient set of bytes (MSByte first). +

          + +

          Side Effects None +

          + +

          Defined in dddmpStoreAdd.c + +
          +
          +static int 
          +NodeStoreRecurBdd(
          +  DdManager * ddMgr, IN: DD Manager
          +  DdNode * f, IN: DD node to be stored
          +  int  mode, IN: store mode
          +  int * supportids, IN: internal ids for variables
          +  char ** varnames, IN: names of variables: to be stored with nodes
          +  int * outids, IN: output ids for variables
          +  FILE * fp IN: store file
          +)
          +
          +
          Stores a node to file in either test or binary mode. + In text mode a node is represented (on a text line basis) as +
            +
          • node-index [var-extrainfo] var-index Then-index Else-index +
          + + where all indexes are integer numbers and var-extrainfo + (optional redundant field) is either an integer or a string + (variable name). Node-index is redundant (due to the node + ordering) but we keep it for readability.

          + + In binary mode nodes are represented as a sequence of bytes, + representing var-index, Then-index, and Else-index in an + optimized way. Only the first byte (code) is mandatory. + Integer indexes are represented in absolute or relative mode, + where relative means offset wrt. a Then/Else node info. + Suppose Var(NodeId), Then(NodeId) and Else(NodeId) represent + infos about a given node.

          + + The generic "NodeId" node is stored as + +

            +
          • code-byte +
          • [var-info] +
          • [Then-info] +
          • [Else-info] +
          + + where code-byte contains bit fields + +
            +
          • Unused : 1 bit +
          • Variable: 2 bits, one of the following codes +
              +
            • DDDMP_ABSOLUTE_ID var-info = Var(NodeId) follows +
            • DDDMP_RELATIVE_ID Var(NodeId) is represented in relative form as + var-info = Min(Var(Then(NodeId)),Var(Else(NodeId))) -Var(NodeId) +
            • DDDMP_RELATIVE_1 No var-info follows, because + Var(NodeId) = Min(Var(Then(NodeId)),Var(Else(NodeId)))-1 +
            • DDDMP_TERMINAL Node is a terminal, no var info required +
            +
          • T : 2 bits, with codes similar to V +
              +
            • DDDMP_ABSOLUTE_ID Then-info = Then(NodeId) follows +
            • DDDMP_RELATIVE_ID Then(NodeId) is represented in relative form as + Then-info = Nodeid-Then(NodeId) +
            • DDDMP_RELATIVE_1 No info on Then(NodeId) follows, because + Then(NodeId) = NodeId-1 +
            • DDDMP_TERMINAL Then Node is a terminal, no info required (for BDDs) +
            +
          • Ecompl : 1 bit, if 1 means complemented edge +
          • E : 2 bits, with codes and meanings as for the Then edge +
          + var-info, Then-info, Else-info (if required) are represented as unsigned + integer values on a sufficient set of bytes (MSByte first). +

          + +

          Side Effects None +

          + +

          Defined in dddmpStoreBdd.c + +
          +
          +static int 
          +NodeTextStoreAdd(
          +  DdManager * ddMgr, IN: DD Manager
          +  DdNode * f, IN: DD node to be stored
          +  int  mode, IN: store mode
          +  int * supportids, IN: internal ids for variables
          +  char ** varnames, IN: names of variables: to be stored with nodes
          +  int * outids, IN: output ids for variables
          +  FILE * fp, IN: Store file
          +  int  idf, IN: index of the current node
          +  int  vf, IN: variable of the current node
          +  int  idT, IN: index of the Then node
          +  int  idE IN: index of the Else node
          +)
          +
          +
          Store 1 0 0 for the terminal node. + Store id, left child pointer, right pointer for all the other nodes. +

          + +

          Side Effects None +

          + +

          See Also NodeBinaryStore + + +
          Defined in dddmpStoreAdd.c + +
          +
          +static int 
          +NodeTextStoreBdd(
          +  DdManager * ddMgr, IN: DD Manager
          +  DdNode * f, IN: DD node to be stored
          +  int  mode, IN: store mode
          +  int * supportids, IN: internal ids for variables
          +  char ** varnames, IN: names of variables: to be stored with nodes
          +  int * outids, IN: output ids for variables
          +  FILE * fp, IN: Store file
          +  int  idf, IN: index of the current node
          +  int  vf, IN: variable of the current node
          +  int  idT, IN: index of the Then node
          +  int  idE IN: index of the Else node
          +)
          +
          +
          Store 1 0 0 for the terminal node. + Store id, left child pointer, right pointer for all the other nodes. +

          + +

          Side Effects None +

          + +

          See Also NodeBinaryStoreBdd + + +
          Defined in dddmpStoreBdd.c + +
          +
          +static int 
          +NumberNodeRecurAdd(
          +  DdNode * f, IN: root of the BDD to be numbered
          +  int  id IN/OUT: index to be assigned to the node
          +)
          +
          +
          Number nodes recursively in post-order. + The "visited" flag is used with inverse polarity, because all nodes + were set "visited" when removing them from unique. +

          + +

          Side Effects "visited" flags are reset. +

          + +

          Defined in dddmpNodeAdd.c + +
          +
          +static int 
          +NumberNodeRecurBdd(
          +  DdNode * f, IN: root of the BDD to be numbered
          +  int  id IN/OUT: index to be assigned to the node
          +)
          +
          +
          Number nodes recursively in post-order. + The "visited" flag is used with inverse polarity, because all nodes + were set "visited" when removing them from unique. +

          + +

          Side Effects "visited" flags are reset. +

          + +

          Defined in dddmpNodeBdd.c + +
          +
          +static int 
          +NumberNodeRecurCnf(
          +  DdNode * f, IN: root of the BDD to be numbered
          +  int * cnfIds, IN: possible source for numbering
          +  int  id IN/OUT: possible source for numbering
          +)
          +
          +
          Number nodes recursively in post-order. + The "visited" flag is used with inverse polarity, because all nodes + were set "visited" when removing them from unique. +

          + +

          Side Effects "visited" flags are reset. +

          + +

          Defined in dddmpDdNodeCnf.c + +
          +
          +static int 
          +NumberNodeRecurCnf(
          +  DdNode * f, IN: root of the BDD to be numbered
          +  int * cnfIds, IN: possible source for numbering
          +  int  id IN/OUT: possible source for numbering
          +)
          +
          +
          Number nodes recursively in post-order. + The "visited" flag is used with inverse polarity, because all nodes + were set "visited" when removing them from unique. +

          + +

          Side Effects "visited" flags are reset. +

          + +

          Defined in dddmpNodeCnf.c + +
          +
          +static int 
          +NumberNodeRecur(
          +  DdNode * f, IN: root of the BDD to be numbered
          +  int  id IN/OUT: index to be assigned to the node
          +)
          +
          +
          Number nodes recursively in post-order. + The "visited" flag is used with inverse polarity, because all nodes + were set "visited" when removing them from unique. +

          + +

          Side Effects "visited" flags are reset. +

          + +

          Defined in dddmpDdNodeBdd.c + +
          +
          +int 
          +QsortStrcmp(
          +  const void * ps1, IN: pointer to the first string
          +  const void * ps2 IN: pointer to the second string
          +)
          +
          +
          String compare for qsort +

          + +

          Side Effects None +

          + +

          Defined in dddmpUtil.c + +
          +
          +static int 
          +ReadByteBinary(
          +  FILE * fp, IN: file where to read the byte
          +  unsigned char * cp OUT: the read byte
          +)
          +
          +
          inputs a byte to file fp. 0x00 has been used as escape character + to filter , and . This is done for + compatibility between unix and dos/windows systems. +

          + +

          Side Effects None +

          + +

          See Also WriteByteBinary() + + +
          Defined in dddmpBinary.c + +
          +
          +static void 
          +RemoveFromUniqueRecurAdd(
          +  DdManager * ddMgr, IN: DD Manager
          +  DdNode * f IN: root of the BDD to be extracted
          +)
          +
          +
          Removes a node from the unique table by locating the proper + subtable and unlinking the node from it. It recurs on the + children of the node. Constants remain untouched. +

          + +

          Side Effects Nodes are left with the "visited" flag true. +

          + +

          See Also RestoreInUniqueRecurAdd +() + + +
          Defined in dddmpNodeAdd.c + +
          +
          +static void 
          +RemoveFromUniqueRecurBdd(
          +  DdManager * ddMgr, IN: DD Manager
          +  DdNode * f IN: root of the BDD to be extracted
          +)
          +
          +
          Removes a node from the unique table by locating the proper + subtable and unlinking the node from it. It recurs on the + children of the node. Constants remain untouched. +

          + +

          Side Effects Nodes are left with the "visited" flag true. +

          + +

          See Also RestoreInUniqueRecurBdd +() + + +
          Defined in dddmpNodeBdd.c + +
          +
          +static void 
          +RemoveFromUniqueRecurCnf(
          +  DdManager * ddMgr, IN: DD Manager
          +  DdNode * f IN: root of the BDD to be extracted
          +)
          +
          +
          Removes a node from the unique table by locating the proper + subtable and unlinking the node from it. It recurs on on the + children of the node. Constants remain untouched. +

          + +

          Side Effects Nodes are left with the "visited" flag true. +

          + +

          See Also RestoreInUniqueRecurCnf() + + +
          Defined in dddmpNodeCnf.c + +
          +
          +static void 
          +RemoveFromUniqueRecurCnf(
          +  DdManager * ddMgr, IN: DD Manager
          +  DdNode * f IN: root of the BDD to be extracted
          +)
          +
          +
          Removes a node from the unique table by locating the proper + subtable and unlinking the node from it. It recurs on son nodes. +

          + +

          Side Effects Nodes are left with the "visited" flag true. +

          + +

          See Also RestoreInUniqueRecurCnf() + + +
          Defined in dddmpDdNodeCnf.c + +
          +
          +static void 
          +RemoveFromUniqueRecur(
          +  DdManager * ddMgr, IN: DD Manager
          +  DdNode * f IN: root of the BDD to be extracted
          +)
          +
          +
          Removes a node from the unique table by locating the proper + subtable and unlinking the node from it. It recurs on the + children of the node. +

          + +

          Side Effects Nodes are left with the "visited" flag true. +

          + +

          See Also RestoreInUniqueRecur() + + +
          Defined in dddmpDdNodeBdd.c + +
          +
          +static void 
          +RestoreInUniqueRecurAdd(
          +  DdManager * ddMgr, IN: DD Manager
          +  DdNode * f IN: root of the BDD to be restored
          +)
          +
          +
          Restores a node in unique table (recursively) +

          + +

          Side Effects Nodes are not restored in the same order as before removal +

          + +

          See Also RemoveFromUniqueAdd +() + + +
          Defined in dddmpNodeAdd.c + +
          +
          +static void 
          +RestoreInUniqueRecurBdd(
          +  DdManager * ddMgr, IN: DD Manager
          +  DdNode * f IN: root of the BDD to be restored
          +)
          +
          +
          Restores a node in unique table (recursively) +

          + +

          Side Effects Nodes are not restored in the same order as before removal +

          + +

          See Also RemoveFromUnique() + + +
          Defined in dddmpNodeBdd.c + +
          +
          +static void 
          +RestoreInUniqueRecurCnf(
          +  DdManager * ddMgr, IN: DD Manager
          +  DdNode * f IN: root of the BDD to be restored
          +)
          +
          +
          Restores a node in unique table (recursive) +

          + +

          Side Effects Nodes are not restored in the same order as before removal +

          + +

          See Also RemoveFromUnique() + + +
          Defined in dddmpDdNodeCnf.c + +
          +
          +static void 
          +RestoreInUniqueRecurCnf(
          +  DdManager * ddMgr, IN: DD Manager
          +  DdNode * f IN: root of the BDD to be restored
          +)
          +
          +
          Restores a node in unique table (recursive) +

          + +

          Side Effects Nodes are not restored in the same order as before removal +

          + +

          See Also RemoveFromUnique() + + +
          Defined in dddmpNodeCnf.c + +
          +
          +static void 
          +RestoreInUniqueRecur(
          +  DdManager * ddMgr, IN: DD Manager
          +  DdNode * f IN: root of the BDD to be restored
          +)
          +
          +
          Restores a node in unique table (recursively) +

          + +

          Side Effects Nodes are not restored in the same order as before removal +

          + +

          See Also RemoveFromUnique() + + +
          Defined in dddmpDdNodeBdd.c + +
          +
          +static int 
          +StoreCnfBestNotSharedRecur(
          +  DdManager * ddMgr, IN: DD Manager
          +  DdNode * node, IN: BDD to store
          +  int  idf, IN: Id to store
          +  int * bddIds, IN: BDD identifiers
          +  int * cnfIds, IN: corresponding CNF identifiers
          +  FILE * fp, IN: file pointer
          +  int * list, IN: temporary array to store cubes
          +  int * clauseN, OUT: number of stored clauses
          +  int * varMax OUT: maximum identifier of the variables created
          +)
          +
          +
          Performs the recursive step of Print Best on Not Shared + sub-BDDs, i.e., print out information for the nodes belonging to + BDDs not shared (whose root has just one incoming edge). +

          + +

          Side Effects None +

          + +

          Defined in dddmpStoreCnf.c + +
          +
          +static int 
          +StoreCnfBestSharedRecur(
          +  DdManager * ddMgr, IN: DD Manager
          +  DdNode * node, IN: BDD to store
          +  int * bddIds, IN: BDD identifiers
          +  int * cnfIds, IN: corresponding CNF identifiers
          +  FILE * fp, IN: file pointer
          +  int * list, IN: temporary array to store cubes
          +  int * clauseN, OUT: number of stored clauses
          +  int * varMax OUT: maximum identifier of the variables created
          +)
          +
          +
          Performs the recursive step of Print Best on Not Shared + sub-BDDs, i.e., print out information for the nodes belonging to + BDDs not shared (whose root has just one incoming edge). +

          + +

          Side Effects None +

          + +

          Defined in dddmpStoreCnf.c + +
          +
          +static int 
          +StoreCnfBest(
          +  DdManager * ddMgr, IN: DD Manager
          +  DdNode ** f, IN: array of BDDs to store
          +  int  rootN, IN: number of BDD in the array
          +  int * bddIds, IN: BDD identifiers
          +  int * cnfIds, IN: corresponding CNF identifiers
          +  int  idInitial, IN: initial value for numbering new CNF variables
          +  FILE * fp, IN: file pointer
          +  int * varMax, OUT: maximum identifier of the variables created
          +  int * clauseN, OUT: number of stored clauses
          +  int * rootStartLine OUT: line where root starts
          +)
          +
          +
          Prints a disjoint sum of product cover for the function + rooted at node intorducing cutting points whenever necessary. + Each product corresponds to a path from node a leaf + node different from the logical zero, and different from the + background value. Uses the standard output. Returns 1 if + successful, 0 otherwise. +

          + +

          Side Effects None +

          + +

          See Also StoreCnfMaxtermByMaxterm + + +
          Defined in dddmpStoreCnf.c + +
          +
          +static void 
          +StoreCnfMaxtermByMaxtermRecur(
          +  DdManager * ddMgr, IN: DD Manager
          +  DdNode * node, IN: BDD to store
          +  int * bddIds, IN: BDD identifiers
          +  int * cnfIds, IN: corresponding CNF identifiers
          +  FILE * fp, IN: file pointer
          +  int * list, IN: temporary array to store cubes
          +  int * clauseN, OUT: number of stored clauses
          +  int * varMax OUT: maximum identifier of the variables created
          +)
          +
          +
          Performs the recursive step of Print Maxterm. + Traverse a BDD a print out a cube in CNF format each time a terminal + node is reached. +

          + +

          Side Effects None +

          + +

          Defined in dddmpStoreCnf.c + +
          +
          +static int 
          +StoreCnfMaxtermByMaxterm(
          +  DdManager * ddMgr, IN: DD Manager
          +  DdNode ** f, IN: array of BDDs to store
          +  int  rootN, IN: number of BDDs in the array
          +  int * bddIds, IN: BDD Identifiers
          +  int * cnfIds, IN: corresponding CNF Identifiers
          +  int  idInitial, IN: initial value for numbering new CNF variables
          +  FILE * fp, IN: file pointer
          +  int * varMax, OUT: maximum identifier of the variables created
          +  int * clauseN, OUT: number of stored clauses
          +  int * rootStartLine OUT: line where root starts
          +)
          +
          +
          Prints a disjoint sum of product cover for the function + rooted at node. Each product corresponds to a path from node a + leaf node different from the logical zero, and different from + the background value. Uses the standard output. Returns 1 if + successful, 0 otherwise. +

          + +

          Side Effects None +

          + +

          See Also StoreCnfBest + + +
          Defined in dddmpStoreCnf.c + +
          +
          +static int 
          +StoreCnfNodeByNodeRecur(
          +  DdManager * ddMgr, IN: DD Manager
          +  DdNode * f, IN: BDD node to be stored
          +  int * bddIds, IN: BDD ids for variables
          +  int * cnfIds, IN: CNF ids for variables
          +  FILE * fp, IN: store file
          +  int * clauseN, OUT: number of clauses written in the CNF file
          +  int * varMax OUT: maximum value of id written in the CNF file
          +)
          +
          +
          Performs the recursive step of Dddmp_bddStore. + Traverse the BDD and store a CNF formula for each "terminal" node. +

          + +

          Side Effects None +

          + +

          Defined in dddmpStoreCnf.c + +
          +
          +static int 
          +StoreCnfNodeByNode(
          +  DdManager * ddMgr, IN: DD Manager
          +  DdNode ** f, IN: BDD array to be stored
          +  int  rootN, IN: number of BDDs in the array
          +  int * bddIds, IN: BDD ids for variables
          +  int * cnfIds, IN: CNF ids for variables
          +  FILE * fp, IN: store file
          +  int * clauseN, IN/OUT: number of clauses written in the CNF file
          +  int * varMax, IN/OUT: maximum value of id written in the CNF file
          +  int * rootStartLine OUT: CNF line where root starts
          +)
          +
          +
          Store the BDD as CNF clauses. + Use a multiplexer description for each BDD node. +

          + +

          Side Effects None +

          + +

          Defined in dddmpStoreCnf.c + +
          +
          +static int 
          +StoreCnfOneNode(
          +  DdNode * f, IN: node to be stored
          +  int  idf, IN: node CNF Index
          +  int  vf, IN: node BDD Index
          +  int  idT, IN: Then CNF Index with sign = inverted edge
          +  int  idE, IN: Else CNF Index with sign = inverted edge
          +  FILE * fp, IN: store file
          +  int * clauseN, OUT: number of clauses
          +  int * varMax OUT: maximun Index of variable stored
          +)
          +
          +
          Store One Single BDD Node translating it as a multiplexer. +

          + +

          Side Effects None +

          + +

          Defined in dddmpStoreCnf.c + +
          +
          +static int 
          +WriteByteBinary(
          +  FILE * fp, IN: file where to write the byte
          +  unsigned char  c IN: the byte to be written
          +)
          +
          +
          outputs a byte to file fp. Uses 0x00 as escape character + to filter , and . + This is done for compatibility between unix and dos/windows systems. +

          + +

          Side Effects None +

          + +

          See Also ReadByteBinary() + + +
          Defined in dddmpBinary.c + +
          +
          +static int 
          +printCubeCnf(
          +  DdManager * ddMgr, IN: DD Manager
          +  DdNode * node, IN: BDD to store
          +  int * cnfIds, IN: CNF identifiers
          +  FILE * fp, IN: file pointer
          +  int * list, IN: temporary array to store cubes
          +  int * varMax OUT: maximum identifier of the variables created
          +)
          +
          +
          Print One Cube in CNF Format. + Return DDDMP_SUCCESS if something is printed out, DDDMP_FAILURE + is nothing is printed out. +

          + +

          Side Effects None +

          + +

          Defined in dddmpStoreCnf.c + +
          +
          + 
          +(
          +    
          +)
          +
          +
          Checks for Warnings: If expr==1 it prints out the warning + on stderr. +

          + +

          Side Effects None +

          + +

          Defined in dddmp.h + +
          +
          + 
          +(
          +    
          +)
          +
          +
          Checks for fatal bugs and go to the label to deal with + the error. +

          + +

          Side Effects None +

          + +

          Defined in dddmp.h + +
          +
          + 
          +(
          +    
          +)
          +
          +
          Checks for fatal bugs and return the DDDMP_FAILURE flag. +

          + +

          Side Effects None +

          + +

          Defined in dddmp.h + +
          +
          + 
          +(
          +    
          +)
          +
          +
          Conditional safety assertion. It prints out the file + name and line number where the fatal error occurred. + Messages are printed out on stderr. +

          + +

          Side Effects None +

          + +

          Defined in dddmp.h + +
          +
          + 
          +(
          +    
          +)
          +
          +
          Memory Allocation Macro for DDDMP +

          + +

          Side Effects None +

          + +

          Defined in dddmpInt.h + +
          +
          + 
          +(
          +    
          +)
          +
          +
          Memory Free Macro for DDDMP +

          + +

          Side Effects None +

          + +

          Defined in dddmpInt.h + + +
          +
          +Last updated on 1040218 17h14 + diff --git a/distr/dddmp/doc/dddmpAllFile.html b/distr/dddmp/doc/dddmpAllFile.html new file mode 100644 index 0000000..2664d07 --- /dev/null +++ b/distr/dddmp/doc/dddmpAllFile.html @@ -0,0 +1,679 @@ + +The dddmp package: files + + +
          +
          dddmp.h +
          External header file +
          dddmpInt.h +
          Internal header file +
          dddmpBinary.c +
          Input and output BDD codes and integers from/to file +
          dddmpConvert.c +
          Conversion between ASCII and binary formats +
          dddmpDbg.c +
          Functions to display BDD files +
          dddmpDdNodeBdd.c +
          Functions to handle BDD node infos and numbering +
          dddmpDdNodeCnf.c +
          Functions to handle BDD node infos and numbering + while storing a CNF formula from a BDD or an array of BDDs +
          dddmpLoad.c +
          Functions to read in bdds to file +
          dddmpLoadCnf.c +
          Functions to read in CNF from file as BDDs. +
          dddmpNodeAdd.c +
          Functions to handle ADD node infos and numbering +
          dddmpNodeBdd.c +
          Functions to handle BDD node infos and numbering +
          dddmpNodeCnf.c +
          Functions to handle BDD node infos and numbering + while storing a CNF formula from a BDD or an array of BDDs +
          dddmpStoreAdd.c +
          Functions to write ADDs to file. +
          dddmpStoreBdd.c +
          Functions to write BDDs to file. +
          dddmpStoreCnf.c +
          Functions to write out BDDs to file in a CNF format +
          dddmpStoreMisc.c +
          Functions to write out bdds to file in prefixed + and in Blif form. +
          dddmpUtil.c +
          Util Functions for the dddmp package +

          +

          dddmp.h

          +External header file

          +By: Gianpiero Cabodi and Stefano Quer

          +

          +
          () +
          Checks for fatal bugs + +
          () +
          Checks for Warnings: If expr==1 it prints out the warning + on stderr. + +
          () +
          Checks for fatal bugs and return the DDDMP_FAILURE flag. + +
          () +
          Checks for fatal bugs and go to the label to deal with + the error. + +
          +
          +

          dddmpInt.h

          +Internal header file

          +By: Gianpiero Cabodi and Stefano Quer

          +

          +
          () +
          Memory Allocation Macro for DDDMP + +
          () +
          Memory Free Macro for DDDMP + +
          +
          +

          dddmpBinary.c

          +Input and output BDD codes and integers from/to file

          +By: Gianpiero Cabodi and Stefano Quer

          +Input and output BDD codes and integers from/to file + in binary mode. + DD node codes are written as one byte. + Integers of any length are written as sequences of "linked" bytes. + For each byte 7 bits are used for data and one (MSBit) as link with + a further byte (MSB = 1 means one more byte). + Low level read/write of bytes filter , and + with escape sequences.

          +

          +
          DddmpWriteCode() +
          Writes 1 byte node code + +
          DddmpReadCode() +
          Reads a 1 byte node code + +
          DddmpWriteInt() +
          Writes a "packed integer" + +
          DddmpReadInt() +
          Reads a "packed integer" + +
          WriteByteBinary() +
          Writes a byte to file filtering , and + +
          ReadByteBinary() +
          Reads a byte from file with escaped , and + +
          +
          +

          dddmpConvert.c

          +Conversion between ASCII and binary formats

          +By: Gianpiero Cabodi and Stefano Quer

          +Conversion between ASCII and binary formats is presently + supported by loading a BDD in the source format and storing it + in the target one. We plan to introduce ad hoc procedures + avoiding explicit BDD node generation.

          +

          +
          Dddmp_Text2Bin() +
          Converts from ASCII to binary format + +
          Dddmp_Bin2Text() +
          Converts from binary to ASCII format + +
          +
          +

          dddmpDbg.c

          +Functions to display BDD files

          +By: Gianpiero Cabodi and Stefano Quer

          +Functions to display BDD files in binary format

          +

          +
          Dddmp_cuddBddDisplayBinary() +
          Display a binary dump file in a text file + +
          +
          +

          dddmpDdNodeBdd.c

          +Functions to handle BDD node infos and numbering

          +By: Gianpiero Cabodi and Stefano Quer

          +Functions to handle BDD node infos and numbering.

          +

          +
          DddmpNumberDdNodes() +
          Removes nodes from unique table and number them + +
          DddmpUnnumberDdNodes() +
          Restores nodes in unique table, loosing numbering + +
          DddmpWriteNodeIndex() +
          Write index to node + +
          DddmpReadNodeIndex() +
          Reads the index of a node + +
          DddmpVisited() +
          Returns true if node is visited + +
          DddmpSetVisited() +
          Marks a node as visited + +
          DddmpClearVisited() +
          Marks a node as not visited + +
          NumberNodeRecur() +
          Number nodes recursively in post-order + +
          RemoveFromUniqueRecur() +
          Removes a node from unique table + +
          RestoreInUniqueRecur() +
          Restores a node in unique table + +
          +
          +

          dddmpDdNodeCnf.c

          +Functions to handle BDD node infos and numbering + while storing a CNF formula from a BDD or an array of BDDs

          +By: Gianpiero Cabodi and Stefano Quer

          +Functions to handle BDD node infos and numbering + while storing a CNF formula from a BDD or an array of BDDs.

          +

          +
          DddmpNumberDdNodesCnf() +
          Removes nodes from unique table and numbers them + +
          DddmpDdNodesCountEdgesAndNumber() +
          Removes nodes from unique table and numbers each node according + to the number of its incoming BDD edges. + +
          DddmpUnnumberDdNodesCnf() +
          Restores nodes in unique table, loosing numbering + +
          DddmpPrintBddAndNext() +
          Prints debug information + +
          DddmpWriteNodeIndexCnfBis() +
          Write index to node + +
          DddmpWriteNodeIndexCnf() +
          Write index to node + +
          DddmpReadNodeIndexCnf() +
          Reads the index of a node + +
          DddmpClearVisitedCnfRecur() +
          Mark ALL nodes as not visited + +
          DddmpVisitedCnf() +
          Returns true if node is visited + +
          DddmpSetVisitedCnf() +
          Marks a node as visited + +
          DddmpClearVisitedCnf() +
          Marks a node as not visited + +
          NumberNodeRecurCnf() +
          Number nodes recursively in post-order + +
          DddmpDdNodesCheckIncomingAndScanPath() +
          Number nodes recursively in post-order + +
          DddmpDdNodesNumberEdgesRecur() +
          Number nodes recursively in post-order + +
          DddmpDdNodesResetCountRecur() +
          Resets counter and visited flag for ALL nodes of a BDD + +
          DddmpDdNodesCountEdgesRecur() +
          Counts the number of incoming edges for each node of a BDD + +
          RemoveFromUniqueRecurCnf() +
          Removes a node from unique table + +
          RestoreInUniqueRecurCnf() +
          Restores a node in unique table + +
          DddmpPrintBddAndNextRecur() +
          Prints debug info + +
          +
          +

          dddmpLoad.c

          +Functions to read in bdds to file

          +By: Gianpiero Cabodi and Stefano Quer

          +Functions to read in bdds to file. BDDs + are represended on file either in text or binary format under the + following rules. A file contains a forest of BDDs (a vector of + Boolean functions). BDD nodes are numbered with contiguous numbers, + from 1 to NNodes (total number of nodes on a file). 0 is not used to + allow negative node indexes for complemented edges. A file contains + a header, including information about variables and roots to BDD + functions, followed by the list of nodes. BDD nodes are listed + according to their numbering, and in the present implementation + numbering follows a post-order strategy, in such a way that a node + is never listed before its Then/Else children.

          +

          +
          Dddmp_cuddBddLoad() +
          Reads a dump file representing the argument BDD. + +
          Dddmp_cuddBddArrayLoad() +
          Reads a dump file representing the argument BDDs. + +
          Dddmp_cuddAddLoad() +
          Reads a dump file representing the argument ADD. + +
          Dddmp_cuddAddArrayLoad() +
          Reads a dump file representing the argument ADDs. + +
          Dddmp_cuddHeaderLoad() +
          Reads the header of a dump file representing the argument BDDs + +
          DddmpCuddDdArrayLoad() +
          Reads a dump file representing the argument BDDs. + +
          DddmpBddReadHeader() +
          Reads a the header of a dump file representing the + argument BDDs. + +
          DddmpFreeHeader() +
          Frees the internal header structure. + +
          +
          +

          dddmpLoadCnf.c

          +Functions to read in CNF from file as BDDs.

          +By: Gianpiero Cabodi and Stefano Quer

          +Functions to read in CNF from file as BDDs.

          +

          +
          Dddmp_cuddBddLoadCnf() +
          Reads a dump file in a CNF format. + +
          Dddmp_cuddBddArrayLoadCnf() +
          Reads a dump file in a CNF format. + +
          Dddmp_cuddHeaderLoadCnf() +
          Reads the header of a dump file representing the argument BDDs + +
          DddmpCuddDdArrayLoadCnf() +
          Reads a dump file representing the argument BDDs in CNF + format. + +
          DddmpBddReadHeaderCnf() +
          Reads a the header of a dump file representing the argument + BDDs. + +
          DddmpFreeHeaderCnf() +
          Frees the internal header structure. + +
          DddmpReadCnfClauses() +
          Read the CNF clauses from the file in the standard DIMACS + format. + +
          DddmpCnfClauses2Bdd() +
          Transforms CNF clauses into BDDs. + +
          +
          +

          dddmpNodeAdd.c

          +Functions to handle ADD node infos and numbering

          +By: Gianpiero Cabodi and Stefano Quer

          +Functions to handle ADD node infos and numbering.

          +

          +
          DddmpNumberAddNodes() +
          Removes nodes from unique table and number them + +
          DddmpUnnumberAddNodes() +
          Restores nodes in unique table, loosing numbering + +
          DddmpWriteNodeIndexAdd() +
          Write index to node + +
          DddmpReadNodeIndexAdd() +
          Reads the index of a node + +
          DddmpVisitedAdd() +
          Returns true if node is visited + +
          DddmpSetVisitedAdd() +
          Marks a node as visited + +
          DddmpClearVisitedAdd() +
          Marks a node as not visited + +
          NumberNodeRecurAdd() +
          Number nodes recursively in post-order + +
          RemoveFromUniqueRecurAdd() +
          Removes a node from unique table + +
          RestoreInUniqueRecurAdd() +
          Restores a node in unique table + +
          +
          +

          dddmpNodeBdd.c

          +Functions to handle BDD node infos and numbering

          +By: Gianpiero Cabodi and Stefano Quer

          +Functions to handle BDD node infos and numbering.

          +

          +
          DddmpNumberBddNodes() +
          Removes nodes from unique table and number them + +
          DddmpUnnumberBddNodes() +
          Restores nodes in unique table, loosing numbering + +
          DddmpWriteNodeIndexBdd() +
          Write index to node + +
          DddmpReadNodeIndexBdd() +
          Reads the index of a node + +
          DddmpVisitedBdd() +
          Returns true if node is visited + +
          DddmpSetVisitedBdd() +
          Marks a node as visited + +
          DddmpClearVisitedBdd() +
          Marks a node as not visited + +
          NumberNodeRecurBdd() +
          Number nodes recursively in post-order + +
          RemoveFromUniqueRecurBdd() +
          Removes a node from unique table + +
          RestoreInUniqueRecurBdd() +
          Restores a node in unique table + +
          +
          +

          dddmpNodeCnf.c

          +Functions to handle BDD node infos and numbering + while storing a CNF formula from a BDD or an array of BDDs

          +By: Gianpiero Cabodi and Stefano Quer

          +Functions to handle BDD node infos and numbering + while storing a CNF formula from a BDD or an array of BDDs.

          +

          +
          DddmpNumberDdNodesCnf() +
          Removes nodes from unique table and numbers them + +
          DddmpDdNodesCountEdgesAndNumber() +
          Removes nodes from unique table and numbers each node according + to the number of its incoming BDD edges. + +
          DddmpUnnumberDdNodesCnf() +
          Restores nodes in unique table, loosing numbering + +
          DddmpPrintBddAndNext() +
          Prints debug information + +
          DddmpWriteNodeIndexCnf() +
          Write index to node + +
          DddmpVisitedCnf() +
          Returns true if node is visited + +
          DddmpSetVisitedCnf() +
          Marks a node as visited + +
          DddmpReadNodeIndexCnf() +
          Reads the index of a node + +
          DddmpWriteNodeIndexCnfWithTerminalCheck() +
          Write index to node + +
          DddmpClearVisitedCnfRecur() +
          Mark ALL nodes as not visited + +
          DddmpClearVisitedCnf() +
          Marks a node as not visited + +
          NumberNodeRecurCnf() +
          Number nodes recursively in post-order + +
          DddmpDdNodesCheckIncomingAndScanPath() +
          Number nodes recursively in post-order + +
          DddmpDdNodesNumberEdgesRecur() +
          Number nodes recursively in post-order + +
          DddmpDdNodesResetCountRecur() +
          Resets counter and visited flag for ALL nodes of a BDD + +
          DddmpDdNodesCountEdgesRecur() +
          Counts the number of incoming edges for each node of a BDD + +
          RemoveFromUniqueRecurCnf() +
          Removes a node from unique table + +
          RestoreInUniqueRecurCnf() +
          Restores a node in unique table + +
          DddmpPrintBddAndNextRecur() +
          Prints debug info + +
          +
          +

          dddmpStoreAdd.c

          +Functions to write ADDs to file.

          +By: Gianpiero Cabodi and Stefano Quer

          +Functions to write ADDs to file. + ADDs are represended on file either in text or binary format under the + following rules. A file contains a forest of ADDs (a vector of + Boolean functions). ADD nodes are numbered with contiguous numbers, + from 1 to NNodes (total number of nodes on a file). 0 is not used to + allow negative node indexes for complemented edges. A file contains + a header, including information about variables and roots to ADD + functions, followed by the list of nodes. + ADD nodes are listed according to their numbering, and in the present + implementation numbering follows a post-order strategy, in such a way + that a node is never listed before its Then/Else children.

          +

          +
          Dddmp_cuddAddStore() +
          Writes a dump file representing the argument ADD. + +
          Dddmp_cuddAddArrayStore() +
          Writes a dump file representing the argument Array of ADDs. + +
          DddmpCuddDdArrayStoreBdd() +
          Writes a dump file representing the argument Array of + BDDs/ADDs. + +
          NodeStoreRecurAdd() +
          Performs the recursive step of Dddmp_bddStore. + +
          NodeTextStoreAdd() +
          Store One Single Node in Text Format. + +
          +
          +

          dddmpStoreBdd.c

          +Functions to write BDDs to file.

          +By: Gianpiero Cabodi and Stefano Quer

          +Functions to write BDDs to file. + BDDs are represended on file either in text or binary format under the + following rules. A file contains a forest of BDDs (a vector of + Boolean functions). BDD nodes are numbered with contiguous numbers, + from 1 to NNodes (total number of nodes on a file). 0 is not used to + allow negative node indexes for complemented edges. A file contains + a header, including information about variables and roots to BDD + functions, followed by the list of nodes. BDD nodes are listed + according to their numbering, and in the present implementation + numbering follows a post-order strategy, in such a way that a node + is never listed before its Then/Else children.

          +

          +
          Dddmp_cuddBddStore() +
          Writes a dump file representing the argument BDD. + +
          Dddmp_cuddBddArrayStore() +
          Writes a dump file representing the argument Array of BDDs. + +
          DddmpCuddBddArrayStore() +
          Writes a dump file representing the argument Array of + BDDs. + +
          NodeStoreRecurBdd() +
          Performs the recursive step of Dddmp_bddStore. + +
          NodeTextStoreBdd() +
          Store One Single Node in Text Format. + +
          NodeBinaryStoreBdd() +
          Store One Single Node in Binary Format. + +
          +
          +

          dddmpStoreCnf.c

          +Functions to write out BDDs to file in a CNF format

          +By: Gianpiero Cabodi and Stefano Quer

          +Functions to write out BDDs to file in a CNF format.

          +

          +
          Dddmp_cuddBddStoreCnf() +
          Writes a dump file representing the argument BDD in + a CNF format. + +
          Dddmp_cuddBddArrayStoreCnf() +
          Writes a dump file representing the argument array of BDDs + in CNF format. + +
          DddmpCuddBddArrayStoreCnf() +
          Writes a dump file representing the argument Array of + BDDs in the CNF standard format. + +
          StoreCnfNodeByNode() +
          Store the BDD as CNF clauses. + +
          StoreCnfNodeByNodeRecur() +
          Performs the recursive step of Dddmp_bddStore. + +
          StoreCnfOneNode() +
          Store One Single BDD Node. + +
          StoreCnfMaxtermByMaxterm() +
          Prints a disjoint sum of products. + +
          StoreCnfBest() +
          Prints a disjoint sum of products with intermediate + cutting points. + +
          StoreCnfMaxtermByMaxtermRecur() +
          Performs the recursive step of Print Maxterm. + +
          StoreCnfBestNotSharedRecur() +
          Performs the recursive step of Print Best on Not Shared + sub-BDDs. + +
          StoreCnfBestSharedRecur() +
          Performs the recursive step of Print Best on Shared + sub-BDDs. + +
          printCubeCnf() +
          Print One Cube in CNF Format. + +
          +
          +

          dddmpStoreMisc.c

          +Functions to write out bdds to file in prefixed + and in Blif form.

          +By: Gianpiero Cabodi and Stefano Quer

          +Functions to write out bdds to file. + BDDs are represended on file in text format. + Each node is stored as a multiplexer in a prefix notation format for + the prefix notation file or in PLA format for the blif file.

          +

          +
          Dddmp_cuddBddStorePrefix() +
          Writes a dump file representing the argument BDD in + a prefix notation. + +
          Dddmp_cuddBddArrayStorePrefix() +
          Writes a dump file representing the argument BDD in + a prefix notation. + +
          Dddmp_cuddBddStoreBlif() +
          Writes a dump file representing the argument BDD in + a Blif/Exlif notation. + +
          Dddmp_cuddBddArrayStoreBlif() +
          Writes a dump file representing the argument BDD in + a Blif/Exlif notation. + +
          Dddmp_cuddBddStoreSmv() +
          Writes a dump file representing the argument BDD in + a prefix notation. + +
          Dddmp_cuddBddArrayStoreSmv() +
          Writes a dump file representing the argument BDD in + a prefix notation. + +
          DddmpCuddDdArrayStorePrefix() +
          Internal function to writes a dump file representing the + argument BDD in a prefix notation. + +
          DddmpCuddDdArrayStorePrefixBody() +
          Internal function to writes a dump file representing the + argument BDD in a prefix notation. Writes the body of the file. + +
          DddmpCuddDdArrayStorePrefixStep() +
          Performs the recursive step of + DddmpCuddDdArrayStorePrefixBody. + +
          DddmpCuddDdArrayStoreBlif() +
          Writes a blif file representing the argument BDDs. + +
          DddmpCuddDdArrayStoreBlifBody() +
          Writes a blif body representing the argument BDDs. + +
          DddmpCuddDdArrayStoreBlifStep() +
          Performs the recursive step of DddmpCuddDdArrayStoreBlif. + +
          DddmpCuddDdArrayStoreSmv() +
          Internal function to writes a dump file representing the + argument BDD in a SMV notation. + +
          DddmpCuddDdArrayStoreSmvBody() +
          Internal function to writes a dump file representing the + argument BDD in a SMV notation. Writes the body of the file. + +
          DddmpCuddDdArrayStoreSmvStep() +
          Performs the recursive step of + DddmpCuddDdArrayStoreSmvBody. + +
          +
          +

          dddmpUtil.c

          +Util Functions for the dddmp package

          +By: Gianpiero Cabodi and Stefano Quer

          +Functions to manipulate arrays.

          +

          +
          QsortStrcmp() +
          String compare for qsort + +
          FindVarname() +
          Performs binary search of a name within a sorted array + +
          DddmpStrDup() +
          Duplicates a string + +
          DddmpStrArrayDup() +
          Duplicates an array of strings + +
          DddmpStrArrayRead() +
          Inputs an array of strings + +
          DddmpStrArrayWrite() +
          Outputs an array of strings + +
          DddmpStrArrayFree() +
          Frees an array of strings + +
          DddmpIntArrayDup() +
          Duplicates an array of ints + +
          DddmpIntArrayRead() +
          Inputs an array of ints + +
          DddmpIntArrayWrite() +
          Outputs an array of ints + +
          +
          +Last updated on 1040218 17h14 + diff --git a/distr/dddmp/doc/dddmpDesc.html b/distr/dddmp/doc/dddmpDesc.html new file mode 100644 index 0000000..a27b184 --- /dev/null +++ b/distr/dddmp/doc/dddmpDesc.html @@ -0,0 +1,28 @@ + +The dddmp package: Overview + + +

          The dddmp package

          +

          Functions to read in and write out BDDs, ADDs + and CNF formulas from and to files.

          +

          By Gianpiero Cabodi and Stefano Quer

          + + + +
          + + + +
          + +Last updated on 1040218 17h14 + + + diff --git a/distr/dddmp/doc/dddmpDoc.txt b/distr/dddmp/doc/dddmpDoc.txt new file mode 100644 index 0000000..5912f35 Binary files /dev/null and b/distr/dddmp/doc/dddmpDoc.txt differ diff --git a/distr/dddmp/doc/dddmpExt.html b/distr/dddmp/doc/dddmpExt.html new file mode 100644 index 0000000..fe026ec --- /dev/null +++ b/distr/dddmp/doc/dddmpExt.html @@ -0,0 +1,13 @@ + +The dddmp Package for Programmers + + + + + + + + + + + diff --git a/distr/dddmp/doc/dddmpExtAbs.html b/distr/dddmp/doc/dddmpExtAbs.html new file mode 100644 index 0000000..612554f --- /dev/null +++ b/distr/dddmp/doc/dddmpExtAbs.html @@ -0,0 +1,91 @@ + +dddmp package abstract + + + + + +
          +
          Dddmp_Bin2Text() +
          Converts from binary to ASCII format + +
          Dddmp_Text2Bin() +
          Converts from ASCII to binary format + +
          Dddmp_cuddAddArrayLoad() +
          Reads a dump file representing the argument ADDs. + +
          Dddmp_cuddAddArrayStore() +
          Writes a dump file representing the argument Array of ADDs. + +
          Dddmp_cuddAddLoad() +
          Reads a dump file representing the argument ADD. + +
          Dddmp_cuddAddStore() +
          Writes a dump file representing the argument ADD. + +
          Dddmp_cuddBddArrayLoadCnf() +
          Reads a dump file in a CNF format. + +
          Dddmp_cuddBddArrayLoad() +
          Reads a dump file representing the argument BDDs. + +
          Dddmp_cuddBddArrayStoreBlif() +
          Writes a dump file representing the argument BDD in + a Blif/Exlif notation. + +
          Dddmp_cuddBddArrayStoreCnf() +
          Writes a dump file representing the argument array of BDDs + in CNF format. + +
          Dddmp_cuddBddArrayStorePrefix() +
          Writes a dump file representing the argument BDD in + a prefix notation. + +
          Dddmp_cuddBddArrayStoreSmv() +
          Writes a dump file representing the argument BDD in + a prefix notation. + +
          Dddmp_cuddBddArrayStore() +
          Writes a dump file representing the argument Array of BDDs. + +
          Dddmp_cuddBddDisplayBinary() +
          Display a binary dump file in a text file + +
          Dddmp_cuddBddLoadCnf() +
          Reads a dump file in a CNF format. + +
          Dddmp_cuddBddLoad() +
          Reads a dump file representing the argument BDD. + +
          Dddmp_cuddBddStoreBlif() +
          Writes a dump file representing the argument BDD in + a Blif/Exlif notation. + +
          Dddmp_cuddBddStoreCnf() +
          Writes a dump file representing the argument BDD in + a CNF format. + +
          Dddmp_cuddBddStorePrefix() +
          Writes a dump file representing the argument BDD in + a prefix notation. + +
          Dddmp_cuddBddStoreSmv() +
          Writes a dump file representing the argument BDD in + a prefix notation. + +
          Dddmp_cuddBddStore() +
          Writes a dump file representing the argument BDD. + +
          Dddmp_cuddHeaderLoadCnf() +
          Reads the header of a dump file representing the argument BDDs + +
          Dddmp_cuddHeaderLoad() +
          Reads the header of a dump file representing the argument BDDs + +
          + +
          + +Last updated on 1040218 17h14 + diff --git a/distr/dddmp/doc/dddmpExtDet.html b/distr/dddmp/doc/dddmpExtDet.html new file mode 100644 index 0000000..38fb590 --- /dev/null +++ b/distr/dddmp/doc/dddmpExtDet.html @@ -0,0 +1,693 @@ + +The dddmp package + + +
          +
          +
          +int 
          +Dddmp_Bin2Text(
          +  char * filein, IN: name of binary file
          +  char * fileout IN: name of ASCII file
          +)
          +
          +
          Converts from binary to ASCII format. A BDD array is loaded and + and stored to the target file. +

          + +

          Side Effects None +

          + +

          See Also Dddmp_Text2Bin() + + +
          +
          +int 
          +Dddmp_Text2Bin(
          +  char * filein, IN: name of ASCII file
          +  char * fileout IN: name of binary file
          +)
          +
          +
          Converts from ASCII to binary format. A BDD array is loaded and + and stored to the target file. +

          + +

          Side Effects None +

          + +

          See Also Dddmp_Bin2Text() + + +
          +
          +int 
          +Dddmp_cuddAddArrayLoad(
          +  DdManager * ddMgr, IN: DD Manager
          +  Dddmp_RootMatchType  rootMatchMode, IN: storing mode selector
          +  char ** rootmatchnames, IN: sorted names for loaded roots
          +  Dddmp_VarMatchType  varMatchMode, IN: storing mode selector
          +  char ** varmatchnames, IN: array of variable names, by ids
          +  int * varmatchauxids, IN: array of variable auxids, by ids
          +  int * varcomposeids, IN: array of new ids, by ids
          +  int  mode, IN: requested input file format
          +  char * file, IN: file name
          +  FILE * fp, IN: file pointer
          +  DdNode *** pproots OUT: array of returned BDD roots
          +)
          +
          +
          Reads a dump file representing the argument ADDs. See + BDD load functions for detailed explanation. +

          + +

          Side Effects A vector of pointers to DD nodes is allocated and freed. +

          + +

          See Also Dddmp_cuddBddArrayStore + + +
          +
          +int 
          +Dddmp_cuddAddArrayStore(
          +  DdManager * ddMgr, IN: DD Manager
          +  char * ddname, IN: DD name (or NULL)
          +  int  nRoots, IN: number of output BDD roots to be stored
          +  DdNode ** f, IN: array of ADD roots to be stored
          +  char ** rootnames, IN: array of root names (or NULL)
          +  char ** varnames, IN: array of variable names (or NULL)
          +  int * auxids, IN: array of converted var IDs
          +  int  mode, IN: storing mode selector
          +  Dddmp_VarInfoType  varinfo, IN: extra info for variables in text mode
          +  char * fname, IN: File name
          +  FILE * fp IN: File pointer to the store file
          +)
          +
          +
          Dumps the argument array of ADDs to file. Dumping is + either in text or binary form. see the corresponding BDD dump + function for further details. +

          + +

          Side Effects Nodes are temporarily removed from the unique hash + table. They are re-linked after the store operation in a + modified order. +

          + +

          See Also Dddmp_cuddAddStore +Dddmp_cuddAddLoad +Dddmp_cuddAddArrayLoad + + +
          +
          +DdNode * 
          +Dddmp_cuddAddLoad(
          +  DdManager * ddMgr, IN: Manager
          +  Dddmp_VarMatchType  varMatchMode, IN: storing mode selector
          +  char ** varmatchnames, IN: array of variable names by IDs
          +  int * varmatchauxids, IN: array of variable auxids by IDs
          +  int * varcomposeids, IN: array of new ids by IDs
          +  int  mode, IN: requested input file format
          +  char * file, IN: file name
          +  FILE * fp IN: file pointer
          +)
          +
          +
          Reads a dump file representing the argument ADD. + Dddmp_cuddAddArrayLoad is used through a dummy array. +

          + +

          Side Effects A vector of pointers to DD nodes is allocated and freed. +

          + +

          See Also Dddmp_cuddAddStore +Dddmp_cuddAddArrayLoad + + +
          +
          +int 
          +Dddmp_cuddAddStore(
          +  DdManager * ddMgr, IN: DD Manager
          +  char * ddname, IN: DD name (or NULL)
          +  DdNode * f, IN: ADD root to be stored
          +  char ** varnames, IN: array of variable names (or NULL)
          +  int * auxids, IN: array of converted var ids
          +  int  mode, IN: storing mode selector
          +  Dddmp_VarInfoType  varinfo, IN: extra info for variables in text mode
          +  char * fname, IN: File name
          +  FILE * fp IN: File pointer to the store file
          +)
          +
          +
          Dumps the argument ADD to file. Dumping is done through + Dddmp_cuddAddArrayStore, And a dummy array of 1 ADD root is + used for this purpose. +

          + +

          Side Effects Nodes are temporarily removed from unique hash. They are + re-linked after the store operation in a modified order. +

          + +

          See Also Dddmp_cuddAddLoad +Dddmp_cuddAddArrayLoad + + +
          +
          +int 
          +Dddmp_cuddBddArrayLoadCnf(
          +  DdManager * ddMgr, IN: DD Manager
          +  Dddmp_RootMatchType  rootmatchmode, IN: storing mode selector
          +  char ** rootmatchnames, IN: sorted names for loaded roots
          +  Dddmp_VarMatchType  varmatchmode, IN: storing mode selector
          +  char ** varmatchnames, IN: array of variable names, by IDs
          +  int * varmatchauxids, IN: array of variable auxids, by IDs
          +  int * varcomposeids, IN: array of new ids, by IDs
          +  int  mode, IN: computation Mode
          +  char * file, IN: file name
          +  FILE * fp, IN: file pointer
          +  DdNode *** rootsPtrPtr, OUT: array of returned BDD roots
          +  int * nRoots OUT: number of BDDs returned
          +)
          +
          +
          Reads a dump file representing the argument BDD in a + CNF formula. +

          + +

          Side Effects A vector of pointers to DD nodes is allocated and freed. +

          + +

          See Also Dddmp_cuddBddArrayLoad + + +
          +
          +int 
          +Dddmp_cuddBddArrayLoad(
          +  DdManager * ddMgr, IN: DD Manager
          +  Dddmp_RootMatchType  rootMatchMode, IN: storing mode selector
          +  char ** rootmatchnames, IN: sorted names for loaded roots
          +  Dddmp_VarMatchType  varMatchMode, IN: storing mode selector
          +  char ** varmatchnames, IN: array of variable names, by ids
          +  int * varmatchauxids, IN: array of variable auxids, by ids
          +  int * varcomposeids, IN: array of new ids, by ids
          +  int  mode, IN: requested input file format
          +  char * file, IN: file name
          +  FILE * fp, IN: file pointer
          +  DdNode *** pproots OUT: array of returned BDD roots
          +)
          +
          +
          Reads a dump file representing the argument BDDs. The header is + common to both text and binary mode. The node list is either + in text or binary format. A dynamic vector of DD pointers + is allocated to support conversion from DD indexes to pointers. + Several criteria are supported for variable match between file + and dd manager. Several changes/permutations/compositions are allowed + for variables while loading DDs. Variable of the dd manager are allowed + to match with variables on file on ids, permids, varnames, + varauxids; also direct composition between ids and + composeids is supported. More in detail: +
            +
          1. varMatchMode=DDDMP_VAR_MATCHIDS

            + allows the loading of a DD keeping variable IDs unchanged + (regardless of the variable ordering of the reading manager); this + is useful, for example, when swapping DDs to file and restoring them + later from file, after possible variable reordering activations. + +

          2. varMatchMode=DDDMP_VAR_MATCHPERMIDS

            + is used to allow variable match according to the position in the + ordering. + +

          3. varMatchMode=DDDMP_VAR_MATCHNAMES

            + requires a non NULL varmatchnames parameter; this is a vector of + strings in one-to-one correspondence with variable IDs of the + reading manager. Variables in the DD file read are matched with + manager variables according to their name (a non NULL varnames + parameter was required while storing the DD file). + +

          4. varMatchMode=DDDMP_VAR_MATCHIDS

            + has a meaning similar to DDDMP_VAR_MATCHNAMES, but integer auxiliary + IDs are used instead of strings; the additional non NULL + varmatchauxids parameter is needed. + +

          5. varMatchMode=DDDMP_VAR_COMPOSEIDS

            + uses the additional varcomposeids parameter is used as array of + variable ids to be composed with ids stored in file. +

          + + In the present implementation, the array varnames (3), varauxids (4) + and composeids (5) need to have one entry for each variable in the + DD manager (NULL pointers are allowed for unused variables + in varnames). Hence variables need to be already present in the + manager. All arrays are sorted according to IDs. + + All the loaded BDDs are referenced before returning them. +

          + +

          Side Effects A vector of pointers to DD nodes is allocated and freed. +

          + +

          See Also Dddmp_cuddBddArrayStore + + +
          +
          +int 
          +Dddmp_cuddBddArrayStoreBlif(
          +  DdManager * ddMgr, IN: DD Manager
          +  int  nroots, IN: number of output BDD roots to be stored
          +  DdNode ** f, IN: array of BDD roots to be stored
          +  char ** inputNames, IN: array of variable names (or NULL)
          +  char ** outputNames, IN: array of root names (or NULL)
          +  char * modelName, IN: Model Name
          +  char * fname, IN: File name
          +  FILE * fp IN: File pointer to the store file
          +)
          +
          +
          Dumps the argument BDD to file. + Dumping is done through Dddmp_cuddBddArrayStoreBLif. + A dummy array of 1 BDD root is used for this purpose. +

          + +

          See Also Dddmp_cuddBddArrayStorePrefix + + +
          +
          +int 
          +Dddmp_cuddBddArrayStoreCnf(
          +  DdManager * ddMgr, IN: DD Manager
          +  DdNode ** f, IN: array of BDD roots to be stored
          +  int  rootN, IN: # output BDD roots to be stored
          +  Dddmp_DecompCnfStoreType  mode, IN: format selection
          +  int  noHeader, IN: do not store header iff 1
          +  char ** varNames, IN: array of variable names (or NULL)
          +  int * bddIds, IN: array of converted var IDs
          +  int * bddAuxIds, IN: array of BDD node Auxiliary Ids
          +  int * cnfIds, IN: array of converted var IDs
          +  int  idInitial, IN: starting id for cutting variables
          +  int  edgeInTh, IN: Max # Incoming Edges
          +  int  pathLengthTh, IN: Max Path Length
          +  char * fname, IN: file name
          +  FILE * fp, IN: pointer to the store file
          +  int * clauseNPtr, OUT: number of clause stored
          +  int * varNewNPtr OUT: number of new variable created
          +)
          +
          +
          Dumps the argument array of BDDs to file. +

          + +

          Side Effects Nodes are temporarily removed from the unique hash + table. They are re-linked after the store operation in a + modified order. + Three methods are allowed: + * NodeByNode method: Insert a cut-point for each BDD node (but the + terminal nodes) + * MaxtermByMaxterm method: Insert no cut-points, i.e. the off-set of + trhe function is stored + * Best method: Tradeoff between the previous two methods. + Auxiliary variables, i.e., cut points are inserted following these + criterias: + * edgeInTh + indicates the maximum number of incoming edges up to which + no cut point (auxiliary variable) is inserted. + If edgeInTh: + * is equal to -1 no cut point due to incoming edges are inserted + (MaxtermByMaxterm method.) + * is equal to 0 a cut point is inserted for each node with a single + incoming edge, i.e., each node, (NodeByNode method). + * is equal to n a cut point is inserted for each node with (n+1) + incoming edges. + * pathLengthTh + indicates the maximum length path up to which no cut points + (auxiliary variable) is inserted. + If the path length between two nodes exceeds this value, a cut point + is inserted. + If pathLengthTh: + * is equal to -1 no cut point due path length are inserted + (MaxtermByMaxterm method.) + * is equal to 0 a cut point is inserted for each node (NodeByNode + method). + * is equal to n a cut point is inserted on path whose length is + equal to (n+1). + Notice that the maximum number of literals in a clause is equal + to (pathLengthTh + 2), i.e., for each path we have to keep into + account a CNF variable for each node plus 2 added variables for + the bottom and top-path cut points. + The stored file can contain a file header or not depending on the + noHeader parameter (IFF 0, usual setting, the header is usually stored. + This option can be useful in storing multiple BDDs, as separate BDDs, + on the same file leaving the opening of the file to the caller. +

          + +

          +
          +int 
          +Dddmp_cuddBddArrayStorePrefix(
          +  DdManager * ddMgr, IN: DD Manager
          +  int  nroots, IN: number of output BDD roots to be stored
          +  DdNode ** f, IN: array of BDD roots to be stored
          +  char ** inputNames, IN: array of variable names (or NULL)
          +  char ** outputNames, IN: array of root names (or NULL)
          +  char * modelName, IN: Model Name
          +  char * fname, IN: File name
          +  FILE * fp IN: File pointer to the store file
          +)
          +
          +
          Dumps the argument BDD to file. + Dumping is done through Dddmp_cuddBddArrayStorePrefix. + A dummy array of 1 BDD root is used for this purpose. +

          + +

          See Also Dddmp_cuddBddArrayStore + + +
          +
          +int 
          +Dddmp_cuddBddArrayStoreSmv(
          +  DdManager * ddMgr, IN: DD Manager
          +  int  nroots, IN: number of output BDD roots to be stored
          +  DdNode ** f, IN: array of BDD roots to be stored
          +  char ** inputNames, IN: array of variable names (or NULL)
          +  char ** outputNames, IN: array of root names (or NULL)
          +  char * modelName, IN: Model Name
          +  char * fname, IN: File name
          +  FILE * fp IN: File pointer to the store file
          +)
          +
          +
          Dumps the argument BDD to file. + Dumping is done through Dddmp_cuddBddArrayStorePrefix. + A dummy array of 1 BDD root is used for this purpose. +

          + +

          See Also Dddmp_cuddBddArrayStore + + +
          +
          +int 
          +Dddmp_cuddBddArrayStore(
          +  DdManager * ddMgr, IN: DD Manager
          +  char * ddname, IN: dd name (or NULL)
          +  int  nRoots, IN: number of output BDD roots to be stored
          +  DdNode ** f, IN: array of BDD roots to be stored
          +  char ** rootnames, IN: array of root names (or NULL)
          +  char ** varnames, IN: array of variable names (or NULL)
          +  int * auxids, IN: array of converted var IDs
          +  int  mode, IN: storing mode selector
          +  Dddmp_VarInfoType  varinfo, IN: extra info for variables in text mode
          +  char * fname, IN: File name
          +  FILE * fp IN: File pointer to the store file
          +)
          +
          +
          Dumps the argument array of BDDs to file. Dumping is either + in text or binary form. BDDs are stored to the fp (already + open) file if not NULL. Otherwise the file whose name is + fname is opened in write mode. The header has the same format + for both textual and binary dump. Names are allowed for input + variables (vnames) and for represented functions (rnames). + For sake of generality and because of dynamic variable + ordering both variable IDs and permuted IDs are included. + New IDs are also supported (auxids). Variables are identified + with incremental numbers. according with their positiom in + the support set. In text mode, an extra info may be added, + chosen among the following options: name, ID, PermID, or an + auxiliary id. Since conversion from DD pointers to integers + is required, DD nodes are temporarily removed from the unique + hash table. This allows the use of the next field to store + node IDs. +

          + +

          Side Effects Nodes are temporarily removed from the unique hash + table. They are re-linked after the store operation in a + modified order. +

          + +

          See Also Dddmp_cuddBddStore +Dddmp_cuddBddLoad +Dddmp_cuddBddArrayLoad + + +
          +
          +int 
          +Dddmp_cuddBddDisplayBinary(
          +  char * fileIn, IN: name of binary file
          +  char * fileOut IN: name of text file
          +)
          +
          +
          Display a binary dump file in a text file +

          + +

          Side Effects None +

          + +

          See Also Dddmp_cuddBddStore +Dddmp_cuddBddLoad + + +
          +
          +int 
          +Dddmp_cuddBddLoadCnf(
          +  DdManager * ddMgr, IN: DD Manager
          +  Dddmp_VarMatchType  varmatchmode, IN: storing mode selector
          +  char ** varmatchnames, IN: array of variable names, by IDs
          +  int * varmatchauxids, IN: array of variable auxids, by IDs
          +  int * varcomposeids, IN: array of new ids accessed, by IDs
          +  int  mode, IN: computation mode
          +  char * file, IN: file name
          +  FILE * fp, IN: file pointer
          +  DdNode *** rootsPtrPtr, OUT: array of returned BDD roots
          +  int * nRoots OUT: number of BDDs returned
          +)
          +
          +
          Reads a dump file representing the argument BDD in a + CNF formula. + Dddmp_cuddBddArrayLoadCnf is used through a dummy array. + The results is returned in different formats depending on the + mode selection: + IFF mode == 0 Return the Clauses without Conjunction + IFF mode == 1 Return the sets of BDDs without Quantification + IFF mode == 2 Return the sets of BDDs AFTER Existential Quantification +

          + +

          Side Effects A vector of pointers to DD nodes is allocated and freed. +

          + +

          See Also Dddmp_cuddBddLoad +Dddmp_cuddBddArrayLoad + + +
          +
          +DdNode * 
          +Dddmp_cuddBddLoad(
          +  DdManager * ddMgr, IN: DD Manager
          +  Dddmp_VarMatchType  varMatchMode, IN: storing mode selector
          +  char ** varmatchnames, IN: array of variable names - by IDs
          +  int * varmatchauxids, IN: array of variable auxids - by IDs
          +  int * varcomposeids, IN: array of new ids accessed - by IDs
          +  int  mode, IN: requested input file format
          +  char * file, IN: file name
          +  FILE * fp IN: file pointer
          +)
          +
          +
          Reads a dump file representing the argument BDD. + Dddmp_cuddBddArrayLoad is used through a dummy array (see this + function's description for more details). + Mode, the requested input file format, is checked against + the file format. + The loaded BDDs is referenced before returning it. +

          + +

          Side Effects A vector of pointers to DD nodes is allocated and freed. +

          + +

          See Also Dddmp_cuddBddStore +Dddmp_cuddBddArrayLoad + + +
          +
          +int 
          +Dddmp_cuddBddStoreBlif(
          +  DdManager * ddMgr, IN: DD Manager
          +  int  nRoots, IN: Number of BDD roots
          +  DdNode * f, IN: BDD root to be stored
          +  char ** inputNames, IN: Array of variable names
          +  char ** outputNames, IN: Array of root names
          +  char * modelName, IN: Model Name
          +  char * fileName, IN: File name
          +  FILE * fp IN: File pointer to the store file
          +)
          +
          +
          Dumps the argument BDD to file. + Dumping is done through Dddmp_cuddBddArrayStoreBlif. + A dummy array of 1 BDD root is used for this purpose. +

          + +

          See Also Dddmp_cuddBddStorePrefix + + +
          +
          +int 
          +Dddmp_cuddBddStoreCnf(
          +  DdManager * ddMgr, IN: DD Manager
          +  DdNode * f, IN: BDD root to be stored
          +  Dddmp_DecompCnfStoreType  mode, IN: format selection
          +  int  noHeader, IN: do not store header iff 1
          +  char ** varNames, IN: array of variable names (or NULL)
          +  int * bddIds, IN: array of var ids
          +  int * bddAuxIds, IN: array of BDD node Auxiliary Ids
          +  int * cnfIds, IN: array of CNF var ids
          +  int  idInitial, IN: starting id for cutting variables
          +  int  edgeInTh, IN: Max # Incoming Edges
          +  int  pathLengthTh, IN: Max Path Length
          +  char * fname, IN: file name
          +  FILE * fp, IN: pointer to the store file
          +  int * clauseNPtr, OUT: number of clause stored
          +  int * varNewNPtr OUT: number of new variable created
          +)
          +
          +
          Dumps the argument BDD to file. + This task is performed by calling the function + Dddmp_cuddBddArrayStoreCnf. +

          + +

          Side Effects Nodes are temporarily removed from unique hash. They are + re-linked after the store operation in a modified order. +

          + +

          See Also Dddmp_cuddBddArrayStoreCnf + + +
          +
          +int 
          +Dddmp_cuddBddStorePrefix(
          +  DdManager * ddMgr, IN: DD Manager
          +  int  nRoots, IN: Number of BDD roots
          +  DdNode * f, IN: BDD root to be stored
          +  char ** inputNames, IN: Array of variable names
          +  char ** outputNames, IN: Array of root names
          +  char * modelName, IN: Model Name
          +  char * fileName, IN: File name
          +  FILE * fp IN: File pointer to the store file
          +)
          +
          +
          Dumps the argument BDD to file. + Dumping is done through Dddmp_cuddBddArrayStorePrefix. + A dummy array of 1 BDD root is used for this purpose. +

          + +

          See Also Dddmp_cuddBddStore + + +
          +
          +int 
          +Dddmp_cuddBddStoreSmv(
          +  DdManager * ddMgr, IN: DD Manager
          +  int  nRoots, IN: Number of BDD roots
          +  DdNode * f, IN: BDD root to be stored
          +  char ** inputNames, IN: Array of variable names
          +  char ** outputNames, IN: Array of root names
          +  char * modelName, IN: Model Name
          +  char * fileName, IN: File name
          +  FILE * fp IN: File pointer to the store file
          +)
          +
          +
          Dumps the argument BDD to file. + Dumping is done through Dddmp_cuddBddArrayStorePrefix. + A dummy array of 1 BDD root is used for this purpose. +

          + +

          See Also Dddmp_cuddBddStore + + +
          +
          +int 
          +Dddmp_cuddBddStore(
          +  DdManager * ddMgr, IN: DD Manager
          +  char * ddname, IN: DD name (or NULL)
          +  DdNode * f, IN: BDD root to be stored
          +  char ** varnames, IN: array of variable names (or NULL)
          +  int * auxids, IN: array of converted var ids
          +  int  mode, IN: storing mode selector
          +  Dddmp_VarInfoType  varinfo, IN: extra info for variables in text mode
          +  char * fname, IN: File name
          +  FILE * fp IN: File pointer to the store file
          +)
          +
          +
          Dumps the argument BDD to file. Dumping is done through + Dddmp_cuddBddArrayStore. A dummy array of 1 BDD root is + used for this purpose. +

          + +

          Side Effects Nodes are temporarily removed from unique hash. They are + re-linked after the store operation in a modified order. +

          + +

          See Also Dddmp_cuddBddLoad +Dddmp_cuddBddArrayLoad + + +
          +
          +int 
          +Dddmp_cuddHeaderLoadCnf(
          +  int * nVars, OUT: number of DD variables
          +  int * nsuppvars, OUT: number of support variables
          +  char *** suppVarNames, OUT: array of support variable names
          +  char *** orderedVarNames, OUT: array of variable names
          +  int ** varIds, OUT: array of variable ids
          +  int ** varComposeIds, OUT: array of permids ids
          +  int ** varAuxIds, OUT: array of variable aux ids
          +  int * nRoots, OUT: number of root in the file
          +  char * file, IN: file name
          +  FILE * fp IN: file pointer
          +)
          +
          +
          Reads the header of a dump file representing the argument BDDs. + Returns main information regarding DD type stored in the file, + the variable ordering used, the number of variables, etc. + It reads only the header of the file NOT the BDD/ADD section. +

          + +

          See Also Dddmp_cuddBddArrayLoad + + +
          +
          +int 
          +Dddmp_cuddHeaderLoad(
          +  Dddmp_DecompType * ddType, OUT: selects the proper decomp type
          +  int * nVars, OUT: number of DD variables
          +  int * nsuppvars, OUT: number of support variables
          +  char *** suppVarNames, OUT: array of support variable names
          +  char *** orderedVarNames, OUT: array of variable names
          +  int ** varIds, OUT: array of variable ids
          +  int ** varComposeIds, OUT: array of permids ids
          +  int ** varAuxIds, OUT: array of variable aux ids
          +  int * nRoots, OUT: number of root in the file
          +  char * file, IN: file name
          +  FILE * fp IN: file pointer
          +)
          +
          +
          Reads the header of a dump file representing the argument BDDs. + Returns main information regarding DD type stored in the file, + the variable ordering used, the number of variables, etc. + It reads only the header of the file NOT the BDD/ADD section. +

          + +

          See Also Dddmp_cuddBddArrayLoad + + + +
          +
          +Last updated on 1040218 17h14 + diff --git a/distr/dddmp/doc/dddmpTitle.html b/distr/dddmp/doc/dddmpTitle.html new file mode 100644 index 0000000..25a3694 --- /dev/null +++ b/distr/dddmp/doc/dddmpTitle.html @@ -0,0 +1,17 @@ + +The dddmp package: Title + + + + + + + + +
          + Programmer view + Maintainer by function + Maintainer by file
          + + + diff --git a/distr/dddmp/doc/packages.html b/distr/dddmp/doc/packages.html new file mode 100644 index 0000000..27e4ace --- /dev/null +++ b/distr/dddmp/doc/packages.html @@ -0,0 +1,12 @@ + +Package Documentation + + + + + + + + + + diff --git a/distr/dddmp/doc/pkgIndex.html b/distr/dddmp/doc/pkgIndex.html new file mode 100644 index 0000000..f2efd6b --- /dev/null +++ b/distr/dddmp/doc/pkgIndex.html @@ -0,0 +1,13 @@ + +Package Documentation + +

          Package Documentation


          + + + + +
          dddmpFunctions to read in and write out BDDs, ADDs +
          +
          +Last updated on 1040218 17h15 + diff --git a/distr/dddmp/exp/0.add b/distr/dddmp/exp/0.add new file mode 100644 index 0000000..ba6bb3d --- /dev/null +++ b/distr/dddmp/exp/0.add @@ -0,0 +1,21 @@ +.ver DDDMP-2.0 +.add +.mode A +.varinfo 0 +.nnodes 5 +.nvars 3 +.nsuppvars 2 +.suppvarnames DUMMY1 DUMMY2 +.orderedvarnames DUMMY0 DUMMY1 DUMMY2 +.ids 1 2 +.permids 1 2 +.auxids 1 2 +.nroots 1 +.rootids 5 +.nodes +1 T 1 0 0 +2 T 2 0 0 +3 T 0 0 0 +4 2 1 2 3 +5 1 0 1 4 +.end diff --git a/distr/dddmp/exp/0.bdd b/distr/dddmp/exp/0.bdd new file mode 100644 index 0000000..5092978 --- /dev/null +++ b/distr/dddmp/exp/0.bdd @@ -0,0 +1,19 @@ +.ver DDDMP-2.0 +.mode A +.varinfo 0 +.nnodes 5 +.nvars 50 +.nsuppvars 3 +.suppvarnames DUMMY1 DUMMY2 DUMMY3 +.ids 1 2 3 +.permids 1 2 3 +.auxids 1 2 3 +.nroots 1 +.rootids -5 +.nodes +1 T 1 0 0 +2 3 2 1 -1 +3 2 1 1 2 +4 2 1 1 -2 +5 1 0 3 4 +.end diff --git a/distr/dddmp/exp/0or1.bdd b/distr/dddmp/exp/0or1.bdd new file mode 100644 index 0000000..4fda5f2 --- /dev/null +++ b/distr/dddmp/exp/0or1.bdd @@ -0,0 +1,119 @@ +.ver DDDMP-2.0 +.mode A +.varinfo 0 +.nnodes 104 +.nvars 50 +.nsuppvars 16 +.suppvarnames DUMMY0 DUMMY1 DUMMY2 DUMMY3 DUMMY4 DUMMY10 DUMMY11 DUMMY12 DUMMY15 DUMMY16 DUMMY17 DUMMY18 DUMMY19 DUMMY20 DUMMY21 DUMMY22 +.orderedvarnames DUMMY0 DUMMY1 DUMMY2 DUMMY3 DUMMY4 DUMMY5 DUMMY6 DUMMY7 DUMMY8 DUMMY9 DUMMY10 DUMMY11 DUMMY12 DUMMY13 DUMMY14 DUMMY15 DUMMY16 DUMMY17 DUMMY18 DUMMY19 DUMMY20 DUMMY21 DUMMY22 DUMMY23 DUMMY24 DUMMY25 DUMMY26 DUMMY27 DUMMY28 DUMMY29 DUMMY30 DUMMY31 DUMMY32 DUMMY33 DUMMY34 DUMMY35 DUMMY36 DUMMY37 DUMMY38 DUMMY39 DUMMY40 DUMMY41 DUMMY42 DUMMY43 DUMMY44 DUMMY45 DUMMY46 DUMMY47 DUMMY48 DUMMY49 +.ids 0 1 2 3 4 10 11 12 15 16 17 18 19 20 21 22 +.permids 0 1 2 3 4 10 11 12 15 16 17 18 19 20 21 22 +.auxids 0 1 2 3 4 10 11 12 15 16 17 18 19 20 21 22 +.nroots 1 +.rootids -104 +.nodes +1 T 1 0 0 +2 22 15 1 -1 +3 21 14 1 -2 +4 20 13 1 3 +5 19 12 1 4 +6 20 13 3 1 +7 21 14 1 2 +8 20 13 1 7 +9 19 12 6 8 +10 18 11 5 9 +11 17 10 1 10 +12 18 11 1 9 +13 17 10 1 12 +14 16 9 11 13 +15 20 13 7 -1 +16 21 14 2 -1 +17 20 13 16 -3 +18 19 12 15 -17 +19 21 14 2 1 +20 20 13 19 7 +21 19 12 6 20 +22 18 11 18 21 +23 17 10 1 22 +24 16 9 23 13 +25 18 11 18 9 +26 17 10 1 25 +27 16 9 26 13 +28 15 8 24 27 +29 12 7 28 27 +30 11 6 28 29 +31 11 6 28 27 +32 10 5 30 31 +33 4 4 14 32 +34 3 3 33 -1 +35 2 2 33 34 +36 19 12 1 8 +37 18 11 5 36 +38 17 10 1 37 +39 16 9 38 1 +40 19 12 1 20 +41 18 11 18 40 +42 17 10 1 41 +43 16 9 42 1 +44 18 11 18 36 +45 17 10 1 44 +46 16 9 45 1 +47 15 8 43 46 +48 12 7 47 46 +49 11 6 47 48 +50 11 6 47 46 +51 10 5 49 50 +52 4 4 39 51 +53 3 3 1 -52 +54 2 2 52 -53 +55 1 1 35 54 +56 20 13 16 -1 +57 21 14 1 -1 +58 20 13 1 57 +59 19 12 56 -58 +60 18 11 59 -9 +61 17 10 1 -60 +62 19 12 56 -8 +63 18 11 62 -9 +64 17 10 1 -63 +65 16 9 61 64 +66 21 14 2 -2 +67 20 13 66 1 +68 20 13 16 -57 +69 19 12 67 68 +70 18 11 69 -21 +71 17 10 1 -70 +72 16 9 71 64 +73 18 11 69 -9 +74 17 10 1 -73 +75 16 9 74 64 +76 15 8 72 75 +77 12 7 76 75 +78 11 6 76 77 +79 11 6 76 75 +80 10 5 78 79 +81 4 4 65 80 +82 3 3 81 -1 +83 2 2 81 82 +84 18 11 59 -36 +85 17 10 1 -84 +86 18 11 62 -1 +87 17 10 1 -86 +88 16 9 85 87 +89 18 11 69 -40 +90 17 10 1 -89 +91 16 9 90 87 +92 18 11 69 -36 +93 17 10 1 -92 +94 16 9 93 87 +95 15 8 91 94 +96 12 7 95 94 +97 11 6 95 96 +98 11 6 95 94 +99 10 5 97 98 +100 4 4 88 99 +101 3 3 1 -100 +102 2 2 100 -101 +103 1 1 83 102 +104 0 0 55 103 +.end diff --git a/distr/dddmp/exp/1.add b/distr/dddmp/exp/1.add new file mode 100644 index 0000000..ab6ab4d --- /dev/null +++ b/distr/dddmp/exp/1.add @@ -0,0 +1,28 @@ +.ver DDDMP-2.0 +.add +.mode A +.varinfo 0 +.nnodes 12 +.nvars 50 +.nsuppvars 4 +.suppvarnames DUMMY1 DUMMY2 DUMMY3 DUMMY4 +.orderedvarnames DUMMY0 DUMMY1 DUMMY2 DUMMY3 DUMMY4 DUMMY5 DUMMY6 DUMMY7 DUMMY8 DUMMY9 DUMMY10 DUMMY11 DUMMY12 DUMMY13 DUMMY14 DUMMY15 DUMMY16 DUMMY17 DUMMY18 DUMMY19 DUMMY20 DUMMY21 DUMMY22 DUMMY23 DUMMY24 DUMMY25 DUMMY26 DUMMY27 DUMMY28 DUMMY29 DUMMY30 DUMMY31 DUMMY32 DUMMY33 DUMMY34 DUMMY35 DUMMY36 DUMMY37 DUMMY38 DUMMY39 DUMMY40 DUMMY41 DUMMY42 DUMMY43 DUMMY44 DUMMY45 DUMMY46 DUMMY47 DUMMY48 DUMMY49 +.ids 1 2 3 4 +.permids 1 2 3 4 +.auxids 2 3 4 0 +.nroots 1 +.rootids 12 +.nodes +1 T 0 0 0 +2 T 2 0 0 +3 4 3 1 2 +4 T 1 0 0 +5 4 3 4 1 +6 3 2 3 5 +7 4 3 2 4 +8 3 2 7 3 +9 2 1 6 8 +10 3 2 5 7 +11 2 1 10 6 +12 1 0 9 11 +.end diff --git a/distr/dddmp/exp/1.bdd b/distr/dddmp/exp/1.bdd new file mode 100644 index 0000000..b7139aa --- /dev/null +++ b/distr/dddmp/exp/1.bdd @@ -0,0 +1,110 @@ +.ver DDDMP-2.0 +.mode A +.varinfo 0 +.nnodes 96 +.nvars 50 +.nsuppvars 14 +.suppvarnames DUMMY0 DUMMY1 DUMMY4 DUMMY10 DUMMY11 DUMMY12 DUMMY15 DUMMY16 DUMMY17 DUMMY18 DUMMY19 DUMMY20 DUMMY21 DUMMY22 +.ids 0 1 4 10 11 12 15 16 17 18 19 20 21 22 +.permids 0 1 4 10 11 12 15 16 17 18 19 20 21 22 +.auxids 0 1 4 10 11 12 15 16 17 18 19 20 21 22 +.nroots 1 +.rootids -96 +.nodes +1 T 1 0 0 +2 22 13 1 -1 +3 21 12 1 -2 +4 20 11 1 3 +5 19 10 1 4 +6 20 11 3 1 +7 21 12 1 2 +8 20 11 1 7 +9 19 10 6 8 +10 18 9 5 9 +11 17 8 1 10 +12 18 9 1 9 +13 17 8 1 12 +14 16 7 11 13 +15 20 11 7 -1 +16 21 12 2 -1 +17 20 11 16 -3 +18 19 10 15 -17 +19 21 12 2 1 +20 20 11 19 7 +21 19 10 6 20 +22 18 9 18 21 +23 17 8 1 22 +24 16 7 23 13 +25 18 9 18 9 +26 17 8 1 25 +27 16 7 26 13 +28 15 6 24 27 +29 12 5 28 27 +30 11 4 28 29 +31 11 4 28 27 +32 10 3 30 31 +33 4 2 14 32 +34 19 10 1 8 +35 18 9 5 34 +36 17 8 1 35 +37 16 7 36 1 +38 19 10 1 20 +39 18 9 18 38 +40 17 8 1 39 +41 16 7 40 1 +42 18 9 18 34 +43 17 8 1 42 +44 16 7 43 1 +45 15 6 41 44 +46 12 5 45 44 +47 11 4 45 46 +48 11 4 45 44 +49 10 3 47 48 +50 4 2 37 49 +51 1 1 33 50 +52 20 11 16 -1 +53 21 12 1 -1 +54 20 11 1 53 +55 19 10 52 -54 +56 18 9 55 -9 +57 17 8 1 -56 +58 19 10 52 -8 +59 18 9 58 -9 +60 17 8 1 -59 +61 16 7 57 60 +62 21 12 2 -2 +63 20 11 62 1 +64 20 11 16 -53 +65 19 10 63 64 +66 18 9 65 -21 +67 17 8 1 -66 +68 16 7 67 60 +69 18 9 65 -9 +70 17 8 1 -69 +71 16 7 70 60 +72 15 6 68 71 +73 12 5 72 71 +74 11 4 72 73 +75 11 4 72 71 +76 10 3 74 75 +77 4 2 61 76 +78 18 9 55 -34 +79 17 8 1 -78 +80 18 9 58 -1 +81 17 8 1 -80 +82 16 7 79 81 +83 18 9 65 -38 +84 17 8 1 -83 +85 16 7 84 81 +86 18 9 65 -34 +87 17 8 1 -86 +88 16 7 87 81 +89 15 6 85 88 +90 12 5 89 88 +91 11 4 89 90 +92 11 4 89 88 +93 10 3 91 92 +94 4 2 82 93 +95 1 1 77 94 +96 0 0 51 95 +.end diff --git a/distr/dddmp/exp/2.bdd b/distr/dddmp/exp/2.bdd new file mode 100644 index 0000000..c23a160 --- /dev/null +++ b/distr/dddmp/exp/2.bdd @@ -0,0 +1,118 @@ +.ver DDDMP-2.0 +.mode A +.varinfo 0 +.nnodes 104 +.nvars 50 +.nsuppvars 16 +.suppvarnames DUMMY0 DUMMY1 DUMMY2 DUMMY3 DUMMY4 DUMMY10 DUMMY11 DUMMY12 DUMMY15 DUMMY16 DUMMY17 DUMMY18 DUMMY19 DUMMY20 DUMMY21 DUMMY22 +.ids 0 1 2 3 4 10 11 12 15 16 17 18 19 20 21 22 +.permids 0 1 2 3 4 10 11 12 15 16 17 18 19 20 21 22 +.auxids 0 1 2 3 4 10 11 12 15 16 17 18 19 20 21 22 +.nroots 1 +.rootids -104 +.nodes +1 T 1 0 0 +2 22 15 1 -1 +3 21 14 1 -2 +4 20 13 1 3 +5 19 12 1 4 +6 20 13 3 1 +7 21 14 1 2 +8 20 13 1 7 +9 19 12 6 8 +10 18 11 5 9 +11 17 10 1 10 +12 18 11 1 9 +13 17 10 1 12 +14 16 9 11 13 +15 20 13 7 -1 +16 21 14 2 -1 +17 20 13 16 -3 +18 19 12 15 -17 +19 21 14 2 1 +20 20 13 19 7 +21 19 12 6 20 +22 18 11 18 21 +23 17 10 1 22 +24 16 9 23 13 +25 18 11 18 9 +26 17 10 1 25 +27 16 9 26 13 +28 15 8 24 27 +29 12 7 28 27 +30 11 6 28 29 +31 11 6 28 27 +32 10 5 30 31 +33 4 4 14 32 +34 3 3 1 33 +35 2 2 1 34 +36 19 12 1 8 +37 18 11 5 36 +38 17 10 1 37 +39 16 9 38 1 +40 19 12 1 20 +41 18 11 18 40 +42 17 10 1 41 +43 16 9 42 1 +44 18 11 18 36 +45 17 10 1 44 +46 16 9 45 1 +47 15 8 43 46 +48 12 7 47 46 +49 11 6 47 48 +50 11 6 47 46 +51 10 5 49 50 +52 4 4 39 51 +53 3 3 52 1 +54 2 2 1 53 +55 1 1 35 54 +56 20 13 16 -1 +57 21 14 1 -1 +58 20 13 1 57 +59 19 12 56 -58 +60 18 11 59 -9 +61 17 10 1 -60 +62 19 12 56 -8 +63 18 11 62 -9 +64 17 10 1 -63 +65 16 9 61 64 +66 21 14 2 -2 +67 20 13 66 1 +68 20 13 16 -57 +69 19 12 67 68 +70 18 11 69 -21 +71 17 10 1 -70 +72 16 9 71 64 +73 18 11 69 -9 +74 17 10 1 -73 +75 16 9 74 64 +76 15 8 72 75 +77 12 7 76 75 +78 11 6 76 77 +79 11 6 76 75 +80 10 5 78 79 +81 4 4 65 80 +82 3 3 1 81 +83 2 2 1 82 +84 18 11 59 -36 +85 17 10 1 -84 +86 18 11 62 -1 +87 17 10 1 -86 +88 16 9 85 87 +89 18 11 69 -40 +90 17 10 1 -89 +91 16 9 90 87 +92 18 11 69 -36 +93 17 10 1 -92 +94 16 9 93 87 +95 15 8 91 94 +96 12 7 95 94 +97 11 6 95 96 +98 11 6 95 94 +99 10 5 97 98 +100 4 4 88 99 +101 3 3 100 1 +102 2 2 1 101 +103 1 1 83 102 +104 0 0 55 103 +.end diff --git a/distr/dddmp/exp/2and3.bdd b/distr/dddmp/exp/2and3.bdd new file mode 100644 index 0000000..650c454 --- /dev/null +++ b/distr/dddmp/exp/2and3.bdd @@ -0,0 +1,76 @@ +.ver DDDMP-2.0 +.mode A +.varinfo 0 +.nnodes 61 +.nvars 50 +.nsuppvars 16 +.suppvarnames DUMMY0 DUMMY1 DUMMY2 DUMMY3 DUMMY4 DUMMY10 DUMMY11 DUMMY12 DUMMY15 DUMMY16 DUMMY17 DUMMY18 DUMMY19 DUMMY20 DUMMY21 DUMMY22 +.orderedvarnames DUMMY0 DUMMY1 DUMMY2 DUMMY3 DUMMY4 DUMMY5 DUMMY6 DUMMY7 DUMMY8 DUMMY9 DUMMY10 DUMMY11 DUMMY12 DUMMY13 DUMMY14 DUMMY15 DUMMY16 DUMMY17 DUMMY18 DUMMY19 DUMMY20 DUMMY21 DUMMY22 DUMMY23 DUMMY24 DUMMY25 DUMMY26 DUMMY27 DUMMY28 DUMMY29 DUMMY30 DUMMY31 DUMMY32 DUMMY33 DUMMY34 DUMMY35 DUMMY36 DUMMY37 DUMMY38 DUMMY39 DUMMY40 DUMMY41 DUMMY42 DUMMY43 DUMMY44 DUMMY45 DUMMY46 DUMMY47 DUMMY48 DUMMY49 +.ids 0 1 2 3 4 10 11 12 15 16 17 18 19 20 21 22 +.permids 0 1 2 3 4 10 11 12 15 16 17 18 19 20 21 22 +.auxids 0 1 2 3 4 10 11 12 15 16 17 18 19 20 21 22 +.nroots 1 +.rootids -61 +.nodes +1 T 1 0 0 +2 22 15 1 -1 +3 21 14 1 2 +4 20 13 3 -1 +5 21 14 2 -1 +6 20 13 5 -1 +7 19 12 4 -6 +8 21 14 2 1 +9 20 13 8 1 +10 19 12 1 9 +11 18 11 7 10 +12 17 10 1 11 +13 16 9 12 1 +14 19 12 4 1 +15 18 11 14 1 +16 17 10 1 15 +17 16 9 16 1 +18 15 8 13 17 +19 18 11 7 1 +20 17 10 1 19 +21 16 9 20 1 +22 15 8 21 17 +23 12 7 18 22 +24 11 6 18 23 +25 11 6 23 22 +26 10 5 24 25 +27 4 4 1 26 +28 3 3 1 27 +29 2 2 1 28 +30 3 3 27 1 +31 2 2 1 30 +32 1 1 29 31 +33 19 12 6 -1 +34 18 11 33 -1 +35 17 10 1 -34 +36 21 14 2 -2 +37 20 13 36 1 +38 19 12 37 6 +39 18 11 38 -10 +40 17 10 1 -39 +41 16 9 40 35 +42 19 12 37 -1 +43 18 11 42 -1 +44 17 10 1 -43 +45 16 9 44 35 +46 15 8 41 45 +47 18 11 38 -1 +48 17 10 1 -47 +49 16 9 48 35 +50 15 8 49 45 +51 12 7 46 50 +52 11 6 46 51 +53 11 6 51 50 +54 10 5 52 53 +55 4 4 35 54 +56 3 3 1 55 +57 2 2 1 56 +58 3 3 55 1 +59 2 2 1 58 +60 1 1 57 59 +61 0 0 32 60 +.end diff --git a/distr/dddmp/exp/3.bdd b/distr/dddmp/exp/3.bdd new file mode 100644 index 0000000..33d6ddf --- /dev/null +++ b/distr/dddmp/exp/3.bdd @@ -0,0 +1,304 @@ +.ver DDDMP-2.0 +.mode A +.varinfo 0 +.nnodes 290 +.nvars 50 +.nsuppvars 17 +.suppvarnames DUMMY0 DUMMY1 DUMMY2 DUMMY3 DUMMY4 DUMMY5 DUMMY10 DUMMY11 DUMMY12 DUMMY15 DUMMY16 DUMMY17 DUMMY18 DUMMY19 DUMMY20 DUMMY21 DUMMY22 +.ids 0 1 2 3 4 5 10 11 12 15 16 17 18 19 20 21 22 +.permids 0 1 2 3 4 5 10 11 12 15 16 17 18 19 20 21 22 +.auxids 0 1 2 3 4 5 10 11 12 15 16 17 18 19 20 21 22 +.nroots 1 +.rootids -290 +.nodes +1 T 1 0 0 +2 22 16 1 -1 +3 21 15 2 1 +4 20 14 3 1 +5 19 13 4 1 +6 18 12 1 5 +7 17 11 1 6 +8 20 14 2 1 +9 19 13 8 1 +10 18 12 1 9 +11 17 11 1 10 +12 5 5 7 11 +13 21 15 1 2 +14 20 14 13 -1 +15 21 15 2 -1 +16 20 14 15 -1 +17 19 13 14 -16 +18 20 14 3 -1 +19 21 15 1 -1 +20 20 14 19 -1 +21 19 13 18 -20 +22 18 12 17 21 +23 17 11 1 22 +24 20 14 13 -15 +25 19 13 24 1 +26 20 14 3 -15 +27 19 13 26 1 +28 18 12 25 27 +29 17 11 1 28 +30 16 10 23 29 +31 19 13 14 1 +32 19 13 18 1 +33 18 12 31 32 +34 17 11 1 33 +35 16 10 34 29 +36 15 9 30 35 +37 19 13 18 -16 +38 18 12 17 37 +39 17 11 1 38 +40 16 10 39 29 +41 15 9 40 35 +42 12 8 36 41 +43 11 7 36 42 +44 11 7 42 36 +45 10 6 43 44 +46 20 14 2 -1 +47 19 13 46 -20 +48 18 12 17 47 +49 17 11 1 48 +50 20 14 2 -15 +51 19 13 50 1 +52 18 12 25 51 +53 17 11 1 52 +54 16 10 49 53 +55 19 13 46 1 +56 18 12 31 55 +57 17 11 1 56 +58 16 10 57 53 +59 15 9 54 58 +60 19 13 46 -16 +61 18 12 17 60 +62 17 11 1 61 +63 16 10 62 53 +64 15 9 63 58 +65 12 8 59 64 +66 11 7 59 65 +67 11 7 65 59 +68 10 6 66 67 +69 5 5 45 68 +70 4 4 12 69 +71 21 15 2 -2 +72 20 14 71 1 +73 19 13 72 1 +74 18 12 1 73 +75 17 11 1 74 +76 20 14 1 13 +77 19 13 72 76 +78 18 12 1 77 +79 17 11 1 78 +80 16 10 75 79 +81 20 14 15 1 +82 19 13 81 1 +83 18 12 1 82 +84 17 11 1 83 +85 19 13 81 76 +86 18 12 1 85 +87 17 11 1 86 +88 16 10 84 87 +89 5 5 80 88 +90 20 14 71 -1 +91 19 13 90 -20 +92 18 12 17 91 +93 17 11 1 92 +94 20 14 71 -15 +95 19 13 94 76 +96 18 12 25 95 +97 17 11 1 96 +98 16 10 93 97 +99 19 13 90 1 +100 18 12 31 99 +101 17 11 1 100 +102 16 10 101 97 +103 15 9 98 102 +104 19 13 90 -16 +105 18 12 17 104 +106 17 11 1 105 +107 16 10 106 97 +108 15 9 107 102 +109 12 8 103 108 +110 11 7 103 109 +111 11 7 109 103 +112 10 6 110 111 +113 19 13 16 -20 +114 18 12 17 113 +115 17 11 1 114 +116 20 14 15 -15 +117 19 13 116 76 +118 18 12 25 117 +119 17 11 1 118 +120 16 10 115 119 +121 19 13 16 1 +122 18 12 31 121 +123 17 11 1 122 +124 16 10 123 119 +125 15 9 120 124 +126 19 13 16 -16 +127 18 12 17 126 +128 17 11 1 127 +129 16 10 128 119 +130 15 9 129 124 +131 12 8 125 130 +132 11 7 125 131 +133 11 7 131 125 +134 10 6 132 133 +135 5 5 112 134 +136 4 4 89 135 +137 3 3 70 136 +138 5 5 75 84 +139 19 13 94 1 +140 18 12 25 139 +141 17 11 1 140 +142 16 10 93 141 +143 16 10 101 141 +144 15 9 142 143 +145 16 10 106 141 +146 15 9 145 143 +147 12 8 144 146 +148 11 7 144 147 +149 11 7 147 144 +150 10 6 148 149 +151 19 13 116 1 +152 18 12 25 151 +153 17 11 1 152 +154 16 10 115 153 +155 16 10 123 153 +156 15 9 154 155 +157 16 10 128 153 +158 15 9 157 155 +159 12 8 156 158 +160 11 7 156 159 +161 11 7 159 156 +162 10 6 160 161 +163 5 5 150 162 +164 4 4 138 163 +165 3 3 70 164 +166 2 2 137 165 +167 1 1 70 166 +168 19 13 16 -1 +169 18 12 168 -5 +170 17 11 1 -169 +171 18 12 168 -9 +172 17 11 1 -171 +173 5 5 170 172 +174 19 13 72 16 +175 18 12 174 -21 +176 17 11 1 -175 +177 20 14 71 15 +178 19 13 177 -1 +179 18 12 178 -27 +180 17 11 1 -179 +181 16 10 176 180 +182 19 13 72 -1 +183 18 12 182 -32 +184 17 11 1 -183 +185 16 10 184 180 +186 15 9 181 185 +187 18 12 174 -37 +188 17 11 1 -187 +189 16 10 188 180 +190 15 9 189 185 +191 12 8 186 190 +192 11 7 186 191 +193 11 7 191 186 +194 10 6 192 193 +195 18 12 174 -47 +196 17 11 1 -195 +197 18 12 178 -51 +198 17 11 1 -197 +199 16 10 196 198 +200 18 12 182 -55 +201 17 11 1 -200 +202 16 10 201 198 +203 15 9 199 202 +204 18 12 174 -60 +205 17 11 1 -204 +206 16 10 205 198 +207 15 9 206 202 +208 12 8 203 207 +209 11 7 203 208 +210 11 7 208 203 +211 10 6 209 210 +212 5 5 194 211 +213 4 4 173 212 +214 18 12 168 -73 +215 17 11 1 -214 +216 18 12 168 -77 +217 17 11 1 -216 +218 16 10 215 217 +219 18 12 168 -82 +220 17 11 1 -219 +221 18 12 168 -85 +222 17 11 1 -221 +223 16 10 220 222 +224 5 5 218 223 +225 18 12 174 -91 +226 17 11 1 -225 +227 18 12 178 -95 +228 17 11 1 -227 +229 16 10 226 228 +230 18 12 182 -99 +231 17 11 1 -230 +232 16 10 231 228 +233 15 9 229 232 +234 18 12 174 -104 +235 17 11 1 -234 +236 16 10 235 228 +237 15 9 236 232 +238 12 8 233 237 +239 11 7 233 238 +240 11 7 238 233 +241 10 6 239 240 +242 18 12 174 -113 +243 17 11 1 -242 +244 18 12 178 -117 +245 17 11 1 -244 +246 16 10 243 245 +247 18 12 182 -121 +248 17 11 1 -247 +249 16 10 248 245 +250 15 9 246 249 +251 18 12 174 -126 +252 17 11 1 -251 +253 16 10 252 245 +254 15 9 253 249 +255 12 8 250 254 +256 11 7 250 255 +257 11 7 255 250 +258 10 6 256 257 +259 5 5 241 258 +260 4 4 224 259 +261 3 3 213 260 +262 5 5 215 220 +263 18 12 178 -139 +264 17 11 1 -263 +265 16 10 226 264 +266 16 10 231 264 +267 15 9 265 266 +268 16 10 235 264 +269 15 9 268 266 +270 12 8 267 269 +271 11 7 267 270 +272 11 7 270 267 +273 10 6 271 272 +274 18 12 178 -151 +275 17 11 1 -274 +276 16 10 243 275 +277 16 10 248 275 +278 15 9 276 277 +279 16 10 252 275 +280 15 9 279 277 +281 12 8 278 280 +282 11 7 278 281 +283 11 7 281 278 +284 10 6 282 283 +285 5 5 273 284 +286 4 4 262 285 +287 3 3 213 286 +288 2 2 261 287 +289 1 1 213 288 +290 0 0 167 289 +.end diff --git a/distr/dddmp/exp/4.bdd b/distr/dddmp/exp/4.bdd new file mode 100644 index 0000000..fb774ba --- /dev/null +++ b/distr/dddmp/exp/4.bdd @@ -0,0 +1,50 @@ +.ver DDDMP-2.0 +.mode A +.varinfo 3 +.nnodes 35 +.nvars 50 +.nsuppvars 15 +.suppvarnames V2 V3 V8 V9 V10 V12 V22 V23 V24 V37 V38 V39 V48 V49 V50 +.orderedvarnames V1 V2 V3 V4 V5 V6 V7 V8 V9 V10 V11 V12 V13 V14 V15 V16 V17 V18 V19 V20 V21 V22 V23 V24 V25 V26 V27 V28 V29 V30 V31 V32 V33 V34 V35 V36 V37 V38 V39 V40 V41 V42 V43 V44 V45 V46 V47 V48 V49 V50 +.ids 1 2 7 8 9 11 21 22 23 36 37 38 47 48 49 +.permids 1 2 7 8 9 11 21 22 23 36 37 38 47 48 49 +.auxids 3 5 15 17 19 23 43 45 47 73 75 77 95 97 99 +.nroots 1 +.rootids -35 +.nodes +1 T 1 0 0 +2 V50 14 1 -1 +3 V49 13 1 2 +4 V48 12 3 1 +5 V48 12 1 -1 +6 V48 12 2 1 +7 V39 11 5 -6 +8 V49 13 1 -1 +9 V48 12 8 1 +10 V39 11 9 4 +11 V38 10 7 -10 +12 V37 9 1 -11 +13 V38 10 5 -9 +14 V37 9 1 -13 +15 V24 8 12 14 +16 V37 9 1 -7 +17 V37 9 1 -5 +18 V24 8 16 17 +19 V23 7 15 18 +20 V22 6 19 1 +21 V23 7 14 17 +22 V22 6 21 1 +23 V12 5 20 22 +24 V10 4 23 1 +25 V22 6 18 1 +26 V12 5 20 25 +27 V10 4 26 1 +28 V9 3 24 27 +29 V12 5 20 1 +30 V10 4 29 1 +31 V10 4 20 1 +32 V9 3 30 31 +33 V8 2 28 32 +34 V3 1 4 33 +35 V2 0 1 34 +.end diff --git a/distr/dddmp/exp/4.bdd.bis1 b/distr/dddmp/exp/4.bdd.bis1 new file mode 100644 index 0000000..220059d --- /dev/null +++ b/distr/dddmp/exp/4.bdd.bis1 @@ -0,0 +1,50 @@ +.ver DDDMP-2.0 +.mode A +.varinfo 0 +.nnodes 35 +.nvars 150 +.nsuppvars 15 +.suppvarnames V3 V8 V23 V24 V37 V39 DUMMY21 DUMMY22 DUMMY23 DUMMY36 DUMMY37 DUMMY38 DUMMY47 DUMMY48 DUMMY49 +.orderedvarnames V2 V3 V8 V9 V10 V12 V22 V23 V24 V37 V38 V39 V48 V49 V50 DUMMY15 DUMMY16 DUMMY17 DUMMY18 DUMMY19 DUMMY20 DUMMY21 DUMMY22 DUMMY23 DUMMY24 DUMMY25 DUMMY26 DUMMY27 DUMMY28 DUMMY29 DUMMY30 DUMMY31 DUMMY32 DUMMY33 DUMMY34 DUMMY35 DUMMY36 DUMMY37 DUMMY38 DUMMY39 DUMMY40 DUMMY41 DUMMY42 DUMMY43 DUMMY44 DUMMY45 DUMMY46 DUMMY47 DUMMY48 DUMMY49 DUMMY50 DUMMY51 DUMMY52 DUMMY53 DUMMY54 DUMMY55 DUMMY56 DUMMY57 DUMMY58 DUMMY59 DUMMY60 DUMMY61 DUMMY62 DUMMY63 DUMMY64 DUMMY65 DUMMY66 DUMMY67 DUMMY68 DUMMY69 DUMMY70 DUMMY71 DUMMY72 DUMMY73 DUMMY74 DUMMY75 DUMMY76 DUMMY77 DUMMY78 DUMMY79 DUMMY80 DUMMY81 DUMMY82 DUMMY83 DUMMY84 DUMMY85 DUMMY86 DUMMY87 DUMMY88 DUMMY89 DUMMY90 DUMMY91 DUMMY92 DUMMY93 DUMMY94 DUMMY95 DUMMY96 DUMMY97 DUMMY98 DUMMY99 DUMMY100 DUMMY101 DUMMY102 DUMMY103 DUMMY104 DUMMY105 DUMMY106 DUMMY107 DUMMY108 DUMMY109 DUMMY110 DUMMY111 DUMMY112 DUMMY113 DUMMY114 DUMMY115 DUMMY116 DUMMY117 DUMMY118 DUMMY119 DUMMY120 DUMMY121 DUMMY122 DUMMY123 DUMMY124 DUMMY125 DUMMY126 DUMMY127 DUMMY128 DUMMY129 DUMMY130 DUMMY131 DUMMY132 DUMMY133 DUMMY134 DUMMY135 DUMMY136 DUMMY137 DUMMY138 DUMMY139 DUMMY140 DUMMY141 DUMMY142 DUMMY143 DUMMY144 DUMMY145 DUMMY146 DUMMY147 DUMMY148 DUMMY149 +.ids 1 2 7 8 9 11 21 22 23 36 37 38 47 48 49 +.permids 1 2 7 8 9 11 21 22 23 36 37 38 47 48 49 +.auxids 1 2 7 8 9 11 21 22 23 36 37 38 47 48 49 +.nroots 1 +.rootids -35 +.nodes +1 T 1 0 0 +2 49 14 1 -1 +3 48 13 1 2 +4 47 12 3 1 +5 47 12 1 -1 +6 47 12 2 1 +7 38 11 5 -6 +8 48 13 1 -1 +9 47 12 8 1 +10 38 11 9 4 +11 37 10 7 -10 +12 36 9 1 -11 +13 37 10 5 -9 +14 36 9 1 -13 +15 23 8 12 14 +16 36 9 1 -7 +17 36 9 1 -5 +18 23 8 16 17 +19 22 7 15 18 +20 21 6 19 1 +21 22 7 14 17 +22 21 6 21 1 +23 11 5 20 22 +24 9 4 23 1 +25 21 6 18 1 +26 11 5 20 25 +27 9 4 26 1 +28 8 3 24 27 +29 11 5 20 1 +30 9 4 29 1 +31 9 4 20 1 +32 8 3 30 31 +33 7 2 28 32 +34 2 1 4 33 +35 1 0 1 34 +.end diff --git a/distr/dddmp/exp/4.bdd.bis2 b/distr/dddmp/exp/4.bdd.bis2 new file mode 100644 index 0000000..220059d --- /dev/null +++ b/distr/dddmp/exp/4.bdd.bis2 @@ -0,0 +1,50 @@ +.ver DDDMP-2.0 +.mode A +.varinfo 0 +.nnodes 35 +.nvars 150 +.nsuppvars 15 +.suppvarnames V3 V8 V23 V24 V37 V39 DUMMY21 DUMMY22 DUMMY23 DUMMY36 DUMMY37 DUMMY38 DUMMY47 DUMMY48 DUMMY49 +.orderedvarnames V2 V3 V8 V9 V10 V12 V22 V23 V24 V37 V38 V39 V48 V49 V50 DUMMY15 DUMMY16 DUMMY17 DUMMY18 DUMMY19 DUMMY20 DUMMY21 DUMMY22 DUMMY23 DUMMY24 DUMMY25 DUMMY26 DUMMY27 DUMMY28 DUMMY29 DUMMY30 DUMMY31 DUMMY32 DUMMY33 DUMMY34 DUMMY35 DUMMY36 DUMMY37 DUMMY38 DUMMY39 DUMMY40 DUMMY41 DUMMY42 DUMMY43 DUMMY44 DUMMY45 DUMMY46 DUMMY47 DUMMY48 DUMMY49 DUMMY50 DUMMY51 DUMMY52 DUMMY53 DUMMY54 DUMMY55 DUMMY56 DUMMY57 DUMMY58 DUMMY59 DUMMY60 DUMMY61 DUMMY62 DUMMY63 DUMMY64 DUMMY65 DUMMY66 DUMMY67 DUMMY68 DUMMY69 DUMMY70 DUMMY71 DUMMY72 DUMMY73 DUMMY74 DUMMY75 DUMMY76 DUMMY77 DUMMY78 DUMMY79 DUMMY80 DUMMY81 DUMMY82 DUMMY83 DUMMY84 DUMMY85 DUMMY86 DUMMY87 DUMMY88 DUMMY89 DUMMY90 DUMMY91 DUMMY92 DUMMY93 DUMMY94 DUMMY95 DUMMY96 DUMMY97 DUMMY98 DUMMY99 DUMMY100 DUMMY101 DUMMY102 DUMMY103 DUMMY104 DUMMY105 DUMMY106 DUMMY107 DUMMY108 DUMMY109 DUMMY110 DUMMY111 DUMMY112 DUMMY113 DUMMY114 DUMMY115 DUMMY116 DUMMY117 DUMMY118 DUMMY119 DUMMY120 DUMMY121 DUMMY122 DUMMY123 DUMMY124 DUMMY125 DUMMY126 DUMMY127 DUMMY128 DUMMY129 DUMMY130 DUMMY131 DUMMY132 DUMMY133 DUMMY134 DUMMY135 DUMMY136 DUMMY137 DUMMY138 DUMMY139 DUMMY140 DUMMY141 DUMMY142 DUMMY143 DUMMY144 DUMMY145 DUMMY146 DUMMY147 DUMMY148 DUMMY149 +.ids 1 2 7 8 9 11 21 22 23 36 37 38 47 48 49 +.permids 1 2 7 8 9 11 21 22 23 36 37 38 47 48 49 +.auxids 1 2 7 8 9 11 21 22 23 36 37 38 47 48 49 +.nroots 1 +.rootids -35 +.nodes +1 T 1 0 0 +2 49 14 1 -1 +3 48 13 1 2 +4 47 12 3 1 +5 47 12 1 -1 +6 47 12 2 1 +7 38 11 5 -6 +8 48 13 1 -1 +9 47 12 8 1 +10 38 11 9 4 +11 37 10 7 -10 +12 36 9 1 -11 +13 37 10 5 -9 +14 36 9 1 -13 +15 23 8 12 14 +16 36 9 1 -7 +17 36 9 1 -5 +18 23 8 16 17 +19 22 7 15 18 +20 21 6 19 1 +21 22 7 14 17 +22 21 6 21 1 +23 11 5 20 22 +24 9 4 23 1 +25 21 6 18 1 +26 11 5 20 25 +27 9 4 26 1 +28 8 3 24 27 +29 11 5 20 1 +30 9 4 29 1 +31 9 4 20 1 +32 8 3 30 31 +33 7 2 28 32 +34 2 1 4 33 +35 1 0 1 34 +.end diff --git a/distr/dddmp/exp/4.bdd.bis3 b/distr/dddmp/exp/4.bdd.bis3 new file mode 100644 index 0000000..220059d --- /dev/null +++ b/distr/dddmp/exp/4.bdd.bis3 @@ -0,0 +1,50 @@ +.ver DDDMP-2.0 +.mode A +.varinfo 0 +.nnodes 35 +.nvars 150 +.nsuppvars 15 +.suppvarnames V3 V8 V23 V24 V37 V39 DUMMY21 DUMMY22 DUMMY23 DUMMY36 DUMMY37 DUMMY38 DUMMY47 DUMMY48 DUMMY49 +.orderedvarnames V2 V3 V8 V9 V10 V12 V22 V23 V24 V37 V38 V39 V48 V49 V50 DUMMY15 DUMMY16 DUMMY17 DUMMY18 DUMMY19 DUMMY20 DUMMY21 DUMMY22 DUMMY23 DUMMY24 DUMMY25 DUMMY26 DUMMY27 DUMMY28 DUMMY29 DUMMY30 DUMMY31 DUMMY32 DUMMY33 DUMMY34 DUMMY35 DUMMY36 DUMMY37 DUMMY38 DUMMY39 DUMMY40 DUMMY41 DUMMY42 DUMMY43 DUMMY44 DUMMY45 DUMMY46 DUMMY47 DUMMY48 DUMMY49 DUMMY50 DUMMY51 DUMMY52 DUMMY53 DUMMY54 DUMMY55 DUMMY56 DUMMY57 DUMMY58 DUMMY59 DUMMY60 DUMMY61 DUMMY62 DUMMY63 DUMMY64 DUMMY65 DUMMY66 DUMMY67 DUMMY68 DUMMY69 DUMMY70 DUMMY71 DUMMY72 DUMMY73 DUMMY74 DUMMY75 DUMMY76 DUMMY77 DUMMY78 DUMMY79 DUMMY80 DUMMY81 DUMMY82 DUMMY83 DUMMY84 DUMMY85 DUMMY86 DUMMY87 DUMMY88 DUMMY89 DUMMY90 DUMMY91 DUMMY92 DUMMY93 DUMMY94 DUMMY95 DUMMY96 DUMMY97 DUMMY98 DUMMY99 DUMMY100 DUMMY101 DUMMY102 DUMMY103 DUMMY104 DUMMY105 DUMMY106 DUMMY107 DUMMY108 DUMMY109 DUMMY110 DUMMY111 DUMMY112 DUMMY113 DUMMY114 DUMMY115 DUMMY116 DUMMY117 DUMMY118 DUMMY119 DUMMY120 DUMMY121 DUMMY122 DUMMY123 DUMMY124 DUMMY125 DUMMY126 DUMMY127 DUMMY128 DUMMY129 DUMMY130 DUMMY131 DUMMY132 DUMMY133 DUMMY134 DUMMY135 DUMMY136 DUMMY137 DUMMY138 DUMMY139 DUMMY140 DUMMY141 DUMMY142 DUMMY143 DUMMY144 DUMMY145 DUMMY146 DUMMY147 DUMMY148 DUMMY149 +.ids 1 2 7 8 9 11 21 22 23 36 37 38 47 48 49 +.permids 1 2 7 8 9 11 21 22 23 36 37 38 47 48 49 +.auxids 1 2 7 8 9 11 21 22 23 36 37 38 47 48 49 +.nroots 1 +.rootids -35 +.nodes +1 T 1 0 0 +2 49 14 1 -1 +3 48 13 1 2 +4 47 12 3 1 +5 47 12 1 -1 +6 47 12 2 1 +7 38 11 5 -6 +8 48 13 1 -1 +9 47 12 8 1 +10 38 11 9 4 +11 37 10 7 -10 +12 36 9 1 -11 +13 37 10 5 -9 +14 36 9 1 -13 +15 23 8 12 14 +16 36 9 1 -7 +17 36 9 1 -5 +18 23 8 16 17 +19 22 7 15 18 +20 21 6 19 1 +21 22 7 14 17 +22 21 6 21 1 +23 11 5 20 22 +24 9 4 23 1 +25 21 6 18 1 +26 11 5 20 25 +27 9 4 26 1 +28 8 3 24 27 +29 11 5 20 1 +30 9 4 29 1 +31 9 4 20 1 +32 8 3 30 31 +33 7 2 28 32 +34 2 1 4 33 +35 1 0 1 34 +.end diff --git a/distr/dddmp/exp/4.bdd.bis4 b/distr/dddmp/exp/4.bdd.bis4 new file mode 100644 index 0000000..220059d --- /dev/null +++ b/distr/dddmp/exp/4.bdd.bis4 @@ -0,0 +1,50 @@ +.ver DDDMP-2.0 +.mode A +.varinfo 0 +.nnodes 35 +.nvars 150 +.nsuppvars 15 +.suppvarnames V3 V8 V23 V24 V37 V39 DUMMY21 DUMMY22 DUMMY23 DUMMY36 DUMMY37 DUMMY38 DUMMY47 DUMMY48 DUMMY49 +.orderedvarnames V2 V3 V8 V9 V10 V12 V22 V23 V24 V37 V38 V39 V48 V49 V50 DUMMY15 DUMMY16 DUMMY17 DUMMY18 DUMMY19 DUMMY20 DUMMY21 DUMMY22 DUMMY23 DUMMY24 DUMMY25 DUMMY26 DUMMY27 DUMMY28 DUMMY29 DUMMY30 DUMMY31 DUMMY32 DUMMY33 DUMMY34 DUMMY35 DUMMY36 DUMMY37 DUMMY38 DUMMY39 DUMMY40 DUMMY41 DUMMY42 DUMMY43 DUMMY44 DUMMY45 DUMMY46 DUMMY47 DUMMY48 DUMMY49 DUMMY50 DUMMY51 DUMMY52 DUMMY53 DUMMY54 DUMMY55 DUMMY56 DUMMY57 DUMMY58 DUMMY59 DUMMY60 DUMMY61 DUMMY62 DUMMY63 DUMMY64 DUMMY65 DUMMY66 DUMMY67 DUMMY68 DUMMY69 DUMMY70 DUMMY71 DUMMY72 DUMMY73 DUMMY74 DUMMY75 DUMMY76 DUMMY77 DUMMY78 DUMMY79 DUMMY80 DUMMY81 DUMMY82 DUMMY83 DUMMY84 DUMMY85 DUMMY86 DUMMY87 DUMMY88 DUMMY89 DUMMY90 DUMMY91 DUMMY92 DUMMY93 DUMMY94 DUMMY95 DUMMY96 DUMMY97 DUMMY98 DUMMY99 DUMMY100 DUMMY101 DUMMY102 DUMMY103 DUMMY104 DUMMY105 DUMMY106 DUMMY107 DUMMY108 DUMMY109 DUMMY110 DUMMY111 DUMMY112 DUMMY113 DUMMY114 DUMMY115 DUMMY116 DUMMY117 DUMMY118 DUMMY119 DUMMY120 DUMMY121 DUMMY122 DUMMY123 DUMMY124 DUMMY125 DUMMY126 DUMMY127 DUMMY128 DUMMY129 DUMMY130 DUMMY131 DUMMY132 DUMMY133 DUMMY134 DUMMY135 DUMMY136 DUMMY137 DUMMY138 DUMMY139 DUMMY140 DUMMY141 DUMMY142 DUMMY143 DUMMY144 DUMMY145 DUMMY146 DUMMY147 DUMMY148 DUMMY149 +.ids 1 2 7 8 9 11 21 22 23 36 37 38 47 48 49 +.permids 1 2 7 8 9 11 21 22 23 36 37 38 47 48 49 +.auxids 1 2 7 8 9 11 21 22 23 36 37 38 47 48 49 +.nroots 1 +.rootids -35 +.nodes +1 T 1 0 0 +2 49 14 1 -1 +3 48 13 1 2 +4 47 12 3 1 +5 47 12 1 -1 +6 47 12 2 1 +7 38 11 5 -6 +8 48 13 1 -1 +9 47 12 8 1 +10 38 11 9 4 +11 37 10 7 -10 +12 36 9 1 -11 +13 37 10 5 -9 +14 36 9 1 -13 +15 23 8 12 14 +16 36 9 1 -7 +17 36 9 1 -5 +18 23 8 16 17 +19 22 7 15 18 +20 21 6 19 1 +21 22 7 14 17 +22 21 6 21 1 +23 11 5 20 22 +24 9 4 23 1 +25 21 6 18 1 +26 11 5 20 25 +27 9 4 26 1 +28 8 3 24 27 +29 11 5 20 1 +30 9 4 29 1 +31 9 4 20 1 +32 8 3 30 31 +33 7 2 28 32 +34 2 1 4 33 +35 1 0 1 34 +.end diff --git a/distr/dddmp/exp/4.cnf b/distr/dddmp/exp/4.cnf new file mode 100644 index 0000000..d1a946c --- /dev/null +++ b/distr/dddmp/exp/4.cnf @@ -0,0 +1,130 @@ +c # BDD stored by the DDDMP tool in CNF format +c # +c # Warning: AUX IDs missing ... equal to BDD IDs. +c # +c .ver DDDMP-2.0 +c .nnodes 35 +c .nvars 50 +c .nsuppvars 15 +c .suppvarnames V2 V3 V8 V9 V10 V12 V22 V23 V24 V37 V38 V39 V48 V49 V50 +c .orderedvarnames V1 V2 V3 V4 V5 V6 V7 V8 V9 V10 V11 V12 V13 V14 V15 V16 V17 V18 V19 V20 V21 V22 V23 V24 V25 V26 V27 V28 V29 V30 V31 V32 V33 V34 V35 V36 V37 V38 V39 V40 V41 V42 V43 V44 V45 V46 V47 V48 V49 V50 +c .ids 1 2 7 8 9 11 21 22 23 36 37 38 47 48 49 +c .permids 1 2 7 8 9 11 21 22 23 36 37 38 47 48 49 +c .auxids 1 2 7 8 9 11 21 22 23 36 37 38 47 48 49 +c .cnfids 2 3 8 9 10 12 22 23 24 37 38 39 48 49 50 +c .nroots 1 +c .rootids 1 +c .nAddedCnfVar 31 +c # +c # Init CNF Clauses +c # +p cnf 130 108 +100 -49 0 +100 -50 0 +-100 49 50 0 +101 48 0 +101 -100 0 +-101 -48 100 0 +102 48 0 +102 -50 0 +-102 -48 50 0 +103 39 102 0 +-103 39 -102 0 +103 -39 -48 0 +-103 -39 48 0 +104 48 0 +104 -49 0 +-104 -48 49 0 +105 39 -101 0 +-105 39 101 0 +105 -39 -104 0 +-105 -39 104 0 +106 38 105 0 +-106 38 -105 0 +106 -38 -103 0 +-106 -38 103 0 +107 -37 0 +107 106 0 +-107 37 -106 0 +108 38 104 0 +-108 38 -104 0 +108 -38 -48 0 +-108 -38 48 0 +109 -37 0 +109 108 0 +-109 37 -108 0 +110 24 -109 0 +-110 24 109 0 +110 -24 -107 0 +-110 -24 107 0 +111 -37 0 +111 103 0 +-111 37 -103 0 +112 -37 0 +112 48 0 +-112 37 -48 0 +113 24 -112 0 +-113 24 112 0 +113 -24 -111 0 +-113 -24 111 0 +114 23 -113 0 +-114 23 113 0 +114 -23 -110 0 +-114 -23 110 0 +115 22 0 +115 -114 0 +-115 -22 114 0 +116 23 -112 0 +-116 23 112 0 +116 -23 -109 0 +-116 -23 109 0 +117 22 0 +117 -116 0 +-117 -22 116 0 +118 12 -117 0 +-118 12 117 0 +118 -12 -115 0 +-118 -12 115 0 +119 10 0 +119 -118 0 +-119 -10 118 0 +120 22 0 +120 -113 0 +-120 -22 113 0 +121 12 -120 0 +-121 12 120 0 +121 -12 -115 0 +-121 -12 115 0 +122 10 0 +122 -121 0 +-122 -10 121 0 +123 9 -122 0 +-123 9 122 0 +123 -9 -119 0 +-123 -9 119 0 +124 12 0 +124 -115 0 +-124 -12 115 0 +125 10 0 +125 -124 0 +-125 -10 124 0 +126 10 0 +126 -115 0 +-126 -10 115 0 +127 9 -126 0 +-127 9 126 0 +127 -9 -125 0 +-127 -9 125 0 +128 8 -127 0 +-128 8 127 0 +128 -8 -123 0 +-128 -8 123 0 +129 3 -128 0 +-129 3 128 0 +129 -3 -101 0 +-129 -3 101 0 +130 -2 0 +130 -129 0 +-130 2 129 0 +-130 0 +c # End of Cnf From dddmp-2.0 diff --git a/distr/dddmp/exp/4.cnf.bis b/distr/dddmp/exp/4.cnf.bis new file mode 100644 index 0000000..d4faf78 --- /dev/null +++ b/distr/dddmp/exp/4.cnf.bis @@ -0,0 +1,130 @@ +c # BDD stored by the DDDMP tool in CNF format +c # +c # Warning: AUX IDs missing ... equal to BDD IDs. +c # +c .ver DDDMP-2.0 +c .nnodes 35 +c .nvars 150 +c .nsuppvars 15 +c .suppvarnames V3 V8 V23 V24 V37 V39 DUMMY21 DUMMY22 DUMMY23 DUMMY36 DUMMY37 DUMMY38 DUMMY47 DUMMY48 DUMMY49 +c .orderedvarnames V2 V3 V8 V9 V10 V12 V22 V23 V24 V37 V38 V39 V48 V49 V50 DUMMY15 DUMMY16 DUMMY17 DUMMY18 DUMMY19 DUMMY20 DUMMY21 DUMMY22 DUMMY23 DUMMY24 DUMMY25 DUMMY26 DUMMY27 DUMMY28 DUMMY29 DUMMY30 DUMMY31 DUMMY32 DUMMY33 DUMMY34 DUMMY35 DUMMY36 DUMMY37 DUMMY38 DUMMY39 DUMMY40 DUMMY41 DUMMY42 DUMMY43 DUMMY44 DUMMY45 DUMMY46 DUMMY47 DUMMY48 DUMMY49 DUMMY50 DUMMY51 DUMMY52 DUMMY53 DUMMY54 DUMMY55 DUMMY56 DUMMY57 DUMMY58 DUMMY59 DUMMY60 DUMMY61 DUMMY62 DUMMY63 DUMMY64 DUMMY65 DUMMY66 DUMMY67 DUMMY68 DUMMY69 DUMMY70 DUMMY71 DUMMY72 DUMMY73 DUMMY74 DUMMY75 DUMMY76 DUMMY77 DUMMY78 DUMMY79 DUMMY80 DUMMY81 DUMMY82 DUMMY83 DUMMY84 DUMMY85 DUMMY86 DUMMY87 DUMMY88 DUMMY89 DUMMY90 DUMMY91 DUMMY92 DUMMY93 DUMMY94 DUMMY95 DUMMY96 DUMMY97 DUMMY98 DUMMY99 DUMMY100 DUMMY101 DUMMY102 DUMMY103 DUMMY104 DUMMY105 DUMMY106 DUMMY107 DUMMY108 DUMMY109 DUMMY110 DUMMY111 DUMMY112 DUMMY113 DUMMY114 DUMMY115 DUMMY116 DUMMY117 DUMMY118 DUMMY119 DUMMY120 DUMMY121 DUMMY122 DUMMY123 DUMMY124 DUMMY125 DUMMY126 DUMMY127 DUMMY128 DUMMY129 DUMMY130 DUMMY131 DUMMY132 DUMMY133 DUMMY134 DUMMY135 DUMMY136 DUMMY137 DUMMY138 DUMMY139 DUMMY140 DUMMY141 DUMMY142 DUMMY143 DUMMY144 DUMMY145 DUMMY146 DUMMY147 DUMMY148 DUMMY149 +c .ids 1 2 7 8 9 11 21 22 23 36 37 38 47 48 49 +c .permids 1 2 7 8 9 11 21 22 23 36 37 38 47 48 49 +c .auxids 1 2 7 8 9 11 21 22 23 36 37 38 47 48 49 +c .cnfids 2 3 8 9 10 12 22 23 24 37 38 39 48 49 50 +c .nroots 1 +c .rootids 1 +c .nAddedCnfVar 31 +c # +c # Init CNF Clauses +c # +p cnf 130 108 +100 -49 0 +100 -50 0 +-100 49 50 0 +101 48 0 +101 -100 0 +-101 -48 100 0 +102 48 0 +102 -50 0 +-102 -48 50 0 +103 39 102 0 +-103 39 -102 0 +103 -39 -48 0 +-103 -39 48 0 +104 48 0 +104 -49 0 +-104 -48 49 0 +105 39 -101 0 +-105 39 101 0 +105 -39 -104 0 +-105 -39 104 0 +106 38 105 0 +-106 38 -105 0 +106 -38 -103 0 +-106 -38 103 0 +107 -37 0 +107 106 0 +-107 37 -106 0 +108 38 104 0 +-108 38 -104 0 +108 -38 -48 0 +-108 -38 48 0 +109 -37 0 +109 108 0 +-109 37 -108 0 +110 24 -109 0 +-110 24 109 0 +110 -24 -107 0 +-110 -24 107 0 +111 -37 0 +111 103 0 +-111 37 -103 0 +112 -37 0 +112 48 0 +-112 37 -48 0 +113 24 -112 0 +-113 24 112 0 +113 -24 -111 0 +-113 -24 111 0 +114 23 -113 0 +-114 23 113 0 +114 -23 -110 0 +-114 -23 110 0 +115 22 0 +115 -114 0 +-115 -22 114 0 +116 23 -112 0 +-116 23 112 0 +116 -23 -109 0 +-116 -23 109 0 +117 22 0 +117 -116 0 +-117 -22 116 0 +118 12 -117 0 +-118 12 117 0 +118 -12 -115 0 +-118 -12 115 0 +119 10 0 +119 -118 0 +-119 -10 118 0 +120 22 0 +120 -113 0 +-120 -22 113 0 +121 12 -120 0 +-121 12 120 0 +121 -12 -115 0 +-121 -12 115 0 +122 10 0 +122 -121 0 +-122 -10 121 0 +123 9 -122 0 +-123 9 122 0 +123 -9 -119 0 +-123 -9 119 0 +124 12 0 +124 -115 0 +-124 -12 115 0 +125 10 0 +125 -124 0 +-125 -10 124 0 +126 10 0 +126 -115 0 +-126 -10 115 0 +127 9 -126 0 +-127 9 126 0 +127 -9 -125 0 +-127 -9 125 0 +128 8 -127 0 +-128 8 127 0 +128 -8 -123 0 +-128 -8 123 0 +129 3 -128 0 +-129 3 128 0 +129 -3 -101 0 +-129 -3 101 0 +130 -2 0 +130 -129 0 +-130 2 129 0 +-130 0 +c # End of Cnf From dddmp-2.0 diff --git a/distr/dddmp/exp/4.max1 b/distr/dddmp/exp/4.max1 new file mode 100644 index 0000000..d9a4984 --- /dev/null +++ b/distr/dddmp/exp/4.max1 @@ -0,0 +1,125 @@ +c # BDD stored by the DDDMP tool in CNF format +c # +c # Warning: AUX IDs missing ... equal to BDD IDs. +c # +c .ver DDDMP-2.0 +c .nnodes 35 +c .nvars 150 +c .nsuppvars 15 +c .suppvarnames V3 V8 V23 V24 V37 V39 DUMMY21 DUMMY22 DUMMY23 DUMMY36 DUMMY37 DUMMY38 DUMMY47 DUMMY48 DUMMY49 +c .orderedvarnames V2 V3 V8 V9 V10 V12 V22 V23 V24 V37 V38 V39 V48 V49 V50 DUMMY15 DUMMY16 DUMMY17 DUMMY18 DUMMY19 DUMMY20 DUMMY21 DUMMY22 DUMMY23 DUMMY24 DUMMY25 DUMMY26 DUMMY27 DUMMY28 DUMMY29 DUMMY30 DUMMY31 DUMMY32 DUMMY33 DUMMY34 DUMMY35 DUMMY36 DUMMY37 DUMMY38 DUMMY39 DUMMY40 DUMMY41 DUMMY42 DUMMY43 DUMMY44 DUMMY45 DUMMY46 DUMMY47 DUMMY48 DUMMY49 DUMMY50 DUMMY51 DUMMY52 DUMMY53 DUMMY54 DUMMY55 DUMMY56 DUMMY57 DUMMY58 DUMMY59 DUMMY60 DUMMY61 DUMMY62 DUMMY63 DUMMY64 DUMMY65 DUMMY66 DUMMY67 DUMMY68 DUMMY69 DUMMY70 DUMMY71 DUMMY72 DUMMY73 DUMMY74 DUMMY75 DUMMY76 DUMMY77 DUMMY78 DUMMY79 DUMMY80 DUMMY81 DUMMY82 DUMMY83 DUMMY84 DUMMY85 DUMMY86 DUMMY87 DUMMY88 DUMMY89 DUMMY90 DUMMY91 DUMMY92 DUMMY93 DUMMY94 DUMMY95 DUMMY96 DUMMY97 DUMMY98 DUMMY99 DUMMY100 DUMMY101 DUMMY102 DUMMY103 DUMMY104 DUMMY105 DUMMY106 DUMMY107 DUMMY108 DUMMY109 DUMMY110 DUMMY111 DUMMY112 DUMMY113 DUMMY114 DUMMY115 DUMMY116 DUMMY117 DUMMY118 DUMMY119 DUMMY120 DUMMY121 DUMMY122 DUMMY123 DUMMY124 DUMMY125 DUMMY126 DUMMY127 DUMMY128 DUMMY129 DUMMY130 DUMMY131 DUMMY132 DUMMY133 DUMMY134 DUMMY135 DUMMY136 DUMMY137 DUMMY138 DUMMY139 DUMMY140 DUMMY141 DUMMY142 DUMMY143 DUMMY144 DUMMY145 DUMMY146 DUMMY147 DUMMY148 DUMMY149 +c .ids 1 2 7 8 9 11 21 22 23 36 37 38 47 48 49 +c .permids 1 2 7 8 9 11 21 22 23 36 37 38 47 48 49 +c .auxids 1 2 7 8 9 11 21 22 23 36 37 38 47 48 49 +c .cnfids 2 3 8 9 10 12 22 23 24 37 38 39 48 49 50 +c .nroots 1 +c .rootids 1 +c .nAddedCnfVar 0 +c # +c # Init CNF Clauses +c # +p cnf 50 103 +3 8 9 10 0 +3 8 9 22 0 +3 8 9 23 24 48 0 +3 8 9 23 24 -37 0 +3 8 9 23 -24 39 48 0 +3 8 9 23 -24 39 -50 0 +3 8 9 23 -24 -39 48 0 +3 8 9 23 -24 -37 0 +3 8 9 -23 24 38 48 0 +3 8 9 -23 24 38 -49 0 +3 8 9 -23 24 -38 48 0 +3 8 9 -23 24 -37 0 +3 8 9 -23 -24 38 39 48 0 +3 8 9 -23 -24 38 39 -50 0 +3 8 9 -23 -24 38 39 -49 0 +3 8 9 -23 -24 38 -39 48 0 +3 8 9 -23 -24 38 -39 -49 0 +3 8 9 -23 -24 -38 39 48 0 +3 8 9 -23 -24 -38 39 -50 0 +3 8 9 -23 -24 -38 -39 48 0 +3 8 9 -23 -24 -37 0 +3 8 -9 10 0 +3 8 -9 12 0 +3 8 -9 22 0 +3 8 -9 23 24 48 0 +3 8 -9 23 24 -37 0 +3 8 -9 23 -24 39 48 0 +3 8 -9 23 -24 39 -50 0 +3 8 -9 23 -24 -39 48 0 +3 8 -9 23 -24 -37 0 +3 8 -9 -23 24 38 48 0 +3 8 -9 -23 24 38 -49 0 +3 8 -9 -23 24 -38 48 0 +3 8 -9 -23 24 -37 0 +3 8 -9 -23 -24 38 39 48 0 +3 8 -9 -23 -24 38 39 -50 0 +3 8 -9 -23 -24 38 39 -49 0 +3 8 -9 -23 -24 38 -39 48 0 +3 8 -9 -23 -24 38 -39 -49 0 +3 8 -9 -23 -24 -38 39 48 0 +3 8 -9 -23 -24 -38 39 -50 0 +3 8 -9 -23 -24 -38 -39 48 0 +3 8 -9 -23 -24 -37 0 +3 -8 9 10 0 +3 -8 9 12 22 0 +3 -8 9 12 24 48 0 +3 -8 9 12 24 -37 0 +3 -8 9 12 -24 39 48 0 +3 -8 9 12 -24 39 -50 0 +3 -8 9 12 -24 -39 48 0 +3 -8 9 12 -24 -37 0 +3 -8 9 -12 22 0 +3 -8 9 -12 23 24 48 0 +3 -8 9 -12 23 24 -37 0 +3 -8 9 -12 23 -24 39 48 0 +3 -8 9 -12 23 -24 39 -50 0 +3 -8 9 -12 23 -24 -39 48 0 +3 -8 9 -12 23 -24 -37 0 +3 -8 9 -12 -23 24 38 48 0 +3 -8 9 -12 -23 24 38 -49 0 +3 -8 9 -12 -23 24 -38 48 0 +3 -8 9 -12 -23 24 -37 0 +3 -8 9 -12 -23 -24 38 39 48 0 +3 -8 9 -12 -23 -24 38 39 -50 0 +3 -8 9 -12 -23 -24 38 39 -49 0 +3 -8 9 -12 -23 -24 38 -39 48 0 +3 -8 9 -12 -23 -24 38 -39 -49 0 +3 -8 9 -12 -23 -24 -38 39 48 0 +3 -8 9 -12 -23 -24 -38 39 -50 0 +3 -8 9 -12 -23 -24 -38 -39 48 0 +3 -8 9 -12 -23 -24 -37 0 +3 -8 -9 10 0 +3 -8 -9 12 22 0 +3 -8 -9 12 23 48 0 +3 -8 -9 12 23 -37 0 +3 -8 -9 12 -23 38 48 0 +3 -8 -9 12 -23 38 -49 0 +3 -8 -9 12 -23 -38 48 0 +3 -8 -9 12 -23 -37 0 +3 -8 -9 -12 22 0 +3 -8 -9 -12 23 24 48 0 +3 -8 -9 -12 23 24 -37 0 +3 -8 -9 -12 23 -24 39 48 0 +3 -8 -9 -12 23 -24 39 -50 0 +3 -8 -9 -12 23 -24 -39 48 0 +3 -8 -9 -12 23 -24 -37 0 +3 -8 -9 -12 -23 24 38 48 0 +3 -8 -9 -12 -23 24 38 -49 0 +3 -8 -9 -12 -23 24 -38 48 0 +3 -8 -9 -12 -23 24 -37 0 +3 -8 -9 -12 -23 -24 38 39 48 0 +3 -8 -9 -12 -23 -24 38 39 -50 0 +3 -8 -9 -12 -23 -24 38 39 -49 0 +3 -8 -9 -12 -23 -24 38 -39 48 0 +3 -8 -9 -12 -23 -24 38 -39 -49 0 +3 -8 -9 -12 -23 -24 -38 39 48 0 +3 -8 -9 -12 -23 -24 -38 39 -50 0 +3 -8 -9 -12 -23 -24 -38 -39 48 0 +3 -8 -9 -12 -23 -24 -37 0 +-3 48 0 +-3 -50 0 +-3 -49 0 +-2 0 +c # End of Cnf From dddmp-2.0 diff --git a/distr/dddmp/exp/4.max2 b/distr/dddmp/exp/4.max2 new file mode 100644 index 0000000..d9a4984 --- /dev/null +++ b/distr/dddmp/exp/4.max2 @@ -0,0 +1,125 @@ +c # BDD stored by the DDDMP tool in CNF format +c # +c # Warning: AUX IDs missing ... equal to BDD IDs. +c # +c .ver DDDMP-2.0 +c .nnodes 35 +c .nvars 150 +c .nsuppvars 15 +c .suppvarnames V3 V8 V23 V24 V37 V39 DUMMY21 DUMMY22 DUMMY23 DUMMY36 DUMMY37 DUMMY38 DUMMY47 DUMMY48 DUMMY49 +c .orderedvarnames V2 V3 V8 V9 V10 V12 V22 V23 V24 V37 V38 V39 V48 V49 V50 DUMMY15 DUMMY16 DUMMY17 DUMMY18 DUMMY19 DUMMY20 DUMMY21 DUMMY22 DUMMY23 DUMMY24 DUMMY25 DUMMY26 DUMMY27 DUMMY28 DUMMY29 DUMMY30 DUMMY31 DUMMY32 DUMMY33 DUMMY34 DUMMY35 DUMMY36 DUMMY37 DUMMY38 DUMMY39 DUMMY40 DUMMY41 DUMMY42 DUMMY43 DUMMY44 DUMMY45 DUMMY46 DUMMY47 DUMMY48 DUMMY49 DUMMY50 DUMMY51 DUMMY52 DUMMY53 DUMMY54 DUMMY55 DUMMY56 DUMMY57 DUMMY58 DUMMY59 DUMMY60 DUMMY61 DUMMY62 DUMMY63 DUMMY64 DUMMY65 DUMMY66 DUMMY67 DUMMY68 DUMMY69 DUMMY70 DUMMY71 DUMMY72 DUMMY73 DUMMY74 DUMMY75 DUMMY76 DUMMY77 DUMMY78 DUMMY79 DUMMY80 DUMMY81 DUMMY82 DUMMY83 DUMMY84 DUMMY85 DUMMY86 DUMMY87 DUMMY88 DUMMY89 DUMMY90 DUMMY91 DUMMY92 DUMMY93 DUMMY94 DUMMY95 DUMMY96 DUMMY97 DUMMY98 DUMMY99 DUMMY100 DUMMY101 DUMMY102 DUMMY103 DUMMY104 DUMMY105 DUMMY106 DUMMY107 DUMMY108 DUMMY109 DUMMY110 DUMMY111 DUMMY112 DUMMY113 DUMMY114 DUMMY115 DUMMY116 DUMMY117 DUMMY118 DUMMY119 DUMMY120 DUMMY121 DUMMY122 DUMMY123 DUMMY124 DUMMY125 DUMMY126 DUMMY127 DUMMY128 DUMMY129 DUMMY130 DUMMY131 DUMMY132 DUMMY133 DUMMY134 DUMMY135 DUMMY136 DUMMY137 DUMMY138 DUMMY139 DUMMY140 DUMMY141 DUMMY142 DUMMY143 DUMMY144 DUMMY145 DUMMY146 DUMMY147 DUMMY148 DUMMY149 +c .ids 1 2 7 8 9 11 21 22 23 36 37 38 47 48 49 +c .permids 1 2 7 8 9 11 21 22 23 36 37 38 47 48 49 +c .auxids 1 2 7 8 9 11 21 22 23 36 37 38 47 48 49 +c .cnfids 2 3 8 9 10 12 22 23 24 37 38 39 48 49 50 +c .nroots 1 +c .rootids 1 +c .nAddedCnfVar 0 +c # +c # Init CNF Clauses +c # +p cnf 50 103 +3 8 9 10 0 +3 8 9 22 0 +3 8 9 23 24 48 0 +3 8 9 23 24 -37 0 +3 8 9 23 -24 39 48 0 +3 8 9 23 -24 39 -50 0 +3 8 9 23 -24 -39 48 0 +3 8 9 23 -24 -37 0 +3 8 9 -23 24 38 48 0 +3 8 9 -23 24 38 -49 0 +3 8 9 -23 24 -38 48 0 +3 8 9 -23 24 -37 0 +3 8 9 -23 -24 38 39 48 0 +3 8 9 -23 -24 38 39 -50 0 +3 8 9 -23 -24 38 39 -49 0 +3 8 9 -23 -24 38 -39 48 0 +3 8 9 -23 -24 38 -39 -49 0 +3 8 9 -23 -24 -38 39 48 0 +3 8 9 -23 -24 -38 39 -50 0 +3 8 9 -23 -24 -38 -39 48 0 +3 8 9 -23 -24 -37 0 +3 8 -9 10 0 +3 8 -9 12 0 +3 8 -9 22 0 +3 8 -9 23 24 48 0 +3 8 -9 23 24 -37 0 +3 8 -9 23 -24 39 48 0 +3 8 -9 23 -24 39 -50 0 +3 8 -9 23 -24 -39 48 0 +3 8 -9 23 -24 -37 0 +3 8 -9 -23 24 38 48 0 +3 8 -9 -23 24 38 -49 0 +3 8 -9 -23 24 -38 48 0 +3 8 -9 -23 24 -37 0 +3 8 -9 -23 -24 38 39 48 0 +3 8 -9 -23 -24 38 39 -50 0 +3 8 -9 -23 -24 38 39 -49 0 +3 8 -9 -23 -24 38 -39 48 0 +3 8 -9 -23 -24 38 -39 -49 0 +3 8 -9 -23 -24 -38 39 48 0 +3 8 -9 -23 -24 -38 39 -50 0 +3 8 -9 -23 -24 -38 -39 48 0 +3 8 -9 -23 -24 -37 0 +3 -8 9 10 0 +3 -8 9 12 22 0 +3 -8 9 12 24 48 0 +3 -8 9 12 24 -37 0 +3 -8 9 12 -24 39 48 0 +3 -8 9 12 -24 39 -50 0 +3 -8 9 12 -24 -39 48 0 +3 -8 9 12 -24 -37 0 +3 -8 9 -12 22 0 +3 -8 9 -12 23 24 48 0 +3 -8 9 -12 23 24 -37 0 +3 -8 9 -12 23 -24 39 48 0 +3 -8 9 -12 23 -24 39 -50 0 +3 -8 9 -12 23 -24 -39 48 0 +3 -8 9 -12 23 -24 -37 0 +3 -8 9 -12 -23 24 38 48 0 +3 -8 9 -12 -23 24 38 -49 0 +3 -8 9 -12 -23 24 -38 48 0 +3 -8 9 -12 -23 24 -37 0 +3 -8 9 -12 -23 -24 38 39 48 0 +3 -8 9 -12 -23 -24 38 39 -50 0 +3 -8 9 -12 -23 -24 38 39 -49 0 +3 -8 9 -12 -23 -24 38 -39 48 0 +3 -8 9 -12 -23 -24 38 -39 -49 0 +3 -8 9 -12 -23 -24 -38 39 48 0 +3 -8 9 -12 -23 -24 -38 39 -50 0 +3 -8 9 -12 -23 -24 -38 -39 48 0 +3 -8 9 -12 -23 -24 -37 0 +3 -8 -9 10 0 +3 -8 -9 12 22 0 +3 -8 -9 12 23 48 0 +3 -8 -9 12 23 -37 0 +3 -8 -9 12 -23 38 48 0 +3 -8 -9 12 -23 38 -49 0 +3 -8 -9 12 -23 -38 48 0 +3 -8 -9 12 -23 -37 0 +3 -8 -9 -12 22 0 +3 -8 -9 -12 23 24 48 0 +3 -8 -9 -12 23 24 -37 0 +3 -8 -9 -12 23 -24 39 48 0 +3 -8 -9 -12 23 -24 39 -50 0 +3 -8 -9 -12 23 -24 -39 48 0 +3 -8 -9 -12 23 -24 -37 0 +3 -8 -9 -12 -23 24 38 48 0 +3 -8 -9 -12 -23 24 38 -49 0 +3 -8 -9 -12 -23 24 -38 48 0 +3 -8 -9 -12 -23 24 -37 0 +3 -8 -9 -12 -23 -24 38 39 48 0 +3 -8 -9 -12 -23 -24 38 39 -50 0 +3 -8 -9 -12 -23 -24 38 39 -49 0 +3 -8 -9 -12 -23 -24 38 -39 48 0 +3 -8 -9 -12 -23 -24 38 -39 -49 0 +3 -8 -9 -12 -23 -24 -38 39 48 0 +3 -8 -9 -12 -23 -24 -38 39 -50 0 +3 -8 -9 -12 -23 -24 -38 -39 48 0 +3 -8 -9 -12 -23 -24 -37 0 +-3 48 0 +-3 -50 0 +-3 -49 0 +-2 0 +c # End of Cnf From dddmp-2.0 diff --git a/distr/dddmp/exp/4bis.bdd b/distr/dddmp/exp/4bis.bdd new file mode 100644 index 0000000..fc242f3 --- /dev/null +++ b/distr/dddmp/exp/4bis.bdd @@ -0,0 +1,47 @@ +.ver DDDMP-2.0 +.mode A +.varinfo 3 +.nnodes 35 +.nvars 50 +.nsuppvars 15 +.ids 1 2 7 8 9 11 21 22 23 36 37 38 47 48 49 +.permids 1 2 7 8 9 11 21 22 23 36 37 38 47 48 49 +.nroots 1 +.rootids -35 +.nodes +1 1 0 0 +2 14 1 -1 +3 13 1 2 +4 12 3 1 +5 12 1 -1 +6 12 2 1 +7 11 5 -6 +8 13 1 -1 +9 12 8 1 +10 11 9 4 +11 10 7 -10 +12 9 1 -11 +13 10 5 -9 +14 9 1 -13 +15 8 12 14 +16 9 1 -7 +17 9 1 -5 +18 8 16 17 +19 7 15 18 +20 6 19 1 +21 7 14 17 +22 6 21 1 +23 5 20 22 +24 4 23 1 +25 6 18 1 +26 5 20 25 +27 4 26 1 +28 3 24 27 +29 5 20 1 +30 4 29 1 +31 4 20 1 +32 3 30 31 +33 2 28 32 +34 1 4 33 +35 0 1 34 +.end diff --git a/distr/dddmp/exp/4xor5.bdd b/distr/dddmp/exp/4xor5.bdd new file mode 100644 index 0000000..9967a67 --- /dev/null +++ b/distr/dddmp/exp/4xor5.bdd @@ -0,0 +1,120 @@ +.ver DDDMP-2.0 +.mode A +.varinfo 0 +.nnodes 105 +.nvars 50 +.nsuppvars 18 +.suppvarnames DUMMY1 DUMMY2 DUMMY7 DUMMY8 DUMMY9 DUMMY11 DUMMY19 DUMMY20 DUMMY21 DUMMY22 DUMMY23 DUMMY24 DUMMY36 DUMMY37 DUMMY38 DUMMY47 DUMMY48 DUMMY49 +.orderedvarnames DUMMY0 DUMMY1 DUMMY2 DUMMY3 DUMMY4 DUMMY5 DUMMY6 DUMMY7 DUMMY8 DUMMY9 DUMMY10 DUMMY11 DUMMY12 DUMMY13 DUMMY14 DUMMY15 DUMMY16 DUMMY17 DUMMY18 DUMMY19 DUMMY20 DUMMY21 DUMMY22 DUMMY23 DUMMY24 DUMMY25 DUMMY26 DUMMY27 DUMMY28 DUMMY29 DUMMY30 DUMMY31 DUMMY32 DUMMY33 DUMMY34 DUMMY35 DUMMY36 DUMMY37 DUMMY38 DUMMY39 DUMMY40 DUMMY41 DUMMY42 DUMMY43 DUMMY44 DUMMY45 DUMMY46 DUMMY47 DUMMY48 DUMMY49 +.ids 1 2 7 8 9 11 19 20 21 22 23 24 36 37 38 47 48 49 +.permids 1 2 7 8 9 11 19 20 21 22 23 24 36 37 38 47 48 49 +.auxids 1 2 7 8 9 11 19 20 21 22 23 24 36 37 38 47 48 49 +.nroots 1 +.rootids 105 +.nodes +1 T 1 0 0 +2 24 11 1 -1 +3 23 10 1 -2 +4 22 9 3 -2 +5 21 8 4 -2 +6 23 10 1 -1 +7 22 9 6 -1 +8 21 8 7 -1 +9 20 7 5 8 +10 23 10 2 -1 +11 22 9 2 10 +12 21 8 11 2 +13 23 10 2 -2 +14 22 9 3 -13 +15 21 8 4 14 +16 20 7 12 15 +17 19 6 9 -16 +18 49 17 1 -1 +19 48 16 1 18 +20 47 15 19 1 +21 24 11 20 -20 +22 23 10 20 -21 +23 22 9 22 -21 +24 21 8 23 -21 +25 23 10 20 -20 +26 22 9 25 -20 +27 21 8 26 -20 +28 20 7 24 27 +29 23 10 21 -20 +30 22 9 21 29 +31 21 8 30 21 +32 23 10 21 -21 +33 22 9 22 -32 +34 21 8 23 33 +35 20 7 31 34 +36 19 6 28 -35 +37 47 15 1 -1 +38 47 15 18 1 +39 38 14 37 -38 +40 48 16 1 -1 +41 47 15 40 1 +42 38 14 41 20 +43 37 13 39 -42 +44 36 12 1 -43 +45 37 13 37 -41 +46 36 12 1 -45 +47 24 11 46 -46 +48 23 10 44 -47 +49 36 12 1 -39 +50 24 11 49 -49 +51 36 12 1 -37 +52 24 11 51 -51 +53 23 10 50 52 +54 22 9 48 -53 +55 21 8 54 -2 +56 23 10 44 -46 +57 23 10 49 51 +58 22 9 56 -57 +59 21 8 58 -1 +60 20 7 55 59 +61 24 11 44 -44 +62 23 10 61 47 +63 23 10 50 -51 +64 22 9 62 63 +65 21 8 64 2 +66 21 8 54 14 +67 20 7 65 66 +68 19 6 60 -67 +69 23 10 46 -47 +70 22 9 69 -52 +71 21 8 70 -2 +72 23 10 46 -46 +73 22 9 72 -51 +74 21 8 73 -1 +75 20 7 71 74 +76 23 10 52 -51 +77 22 9 47 76 +78 21 8 77 2 +79 21 8 70 14 +80 20 7 78 79 +81 19 6 75 -80 +82 11 5 68 81 +83 9 4 82 17 +84 23 10 49 -52 +85 22 9 84 -53 +86 21 8 85 -2 +87 23 10 49 -51 +88 22 9 87 -57 +89 21 8 88 -1 +90 20 7 86 89 +91 22 9 53 63 +92 21 8 91 2 +93 21 8 85 14 +94 20 7 92 93 +95 19 6 90 -94 +96 11 5 68 95 +97 9 4 96 17 +98 8 3 83 97 +99 11 5 68 17 +100 9 4 99 17 +101 9 4 68 17 +102 8 3 100 101 +103 7 2 98 102 +104 2 1 36 103 +105 1 0 17 104 +.end diff --git a/distr/dddmp/exp/5.bdd b/distr/dddmp/exp/5.bdd new file mode 100644 index 0000000..198f6bf --- /dev/null +++ b/distr/dddmp/exp/5.bdd @@ -0,0 +1,31 @@ +.ver DDDMP-2.0 +.mode A +.varinfo 0 +.nnodes 17 +.nvars 50 +.nsuppvars 6 +.suppvarnames DUMMY19 DUMMY20 DUMMY21 DUMMY22 DUMMY23 DUMMY24 +.ids 19 20 21 22 23 24 +.permids 19 20 21 22 23 24 +.auxids 19 20 21 22 23 24 +.nroots 1 +.rootids 17 +.nodes +1 T 1 0 0 +2 24 5 1 -1 +3 23 4 1 -2 +4 22 3 3 -2 +5 21 2 4 -2 +6 23 4 1 -1 +7 22 3 6 -1 +8 21 2 7 -1 +9 20 1 5 8 +10 23 4 2 -1 +11 22 3 2 10 +12 21 2 11 2 +13 23 4 2 -2 +14 22 3 3 -13 +15 21 2 4 14 +16 20 1 12 15 +17 19 0 9 -16 +.end diff --git a/distr/dddmp/exp/composeids.txt b/distr/dddmp/exp/composeids.txt new file mode 100644 index 0000000..0e1340f --- /dev/null +++ b/distr/dddmp/exp/composeids.txt @@ -0,0 +1,20 @@ +0 +2 +4 +6 +8 +10 +12 +14 +16 +18 +20 +22 +24 +26 +28 +30 +32 +34 +36 +38 diff --git a/distr/dddmp/exp/one.bdd b/distr/dddmp/exp/one.bdd new file mode 100644 index 0000000..836566f --- /dev/null +++ b/distr/dddmp/exp/one.bdd @@ -0,0 +1,13 @@ +.ver DDDMP-1.0 +.mode A +.varinfo 0 +.nnodes 1 +.nvars 100 +.nsuppvars 0 +.ids +.permids +.nroots 1 +.rootids 1 +.nodes +1 T 1 0 0 +.end diff --git a/distr/dddmp/exp/runAllTest.out b/distr/dddmp/exp/runAllTest.out new file mode 100644 index 0000000..321532e --- /dev/null +++ b/distr/dddmp/exp/runAllTest.out @@ -0,0 +1,269 @@ +--------------------------------------------------------------------------- +--------------------- TESTING Load and Write Header ----------------------- +--------------------------------------------------------------------------- +#./../testdddmp Version 2.0.2 (use command help) +TestDddmp> Number of Variables: TestDddmp> File : TestDddmp> DD TYPE: DDDMP_BDD +Number of variables: 50 +Number of support variables: 15 +suppVarNames: V2 V3 V8 V9 V10 V12 V22 V23 V24 V37 V38 V39 V48 V49 V50 +orderedVarNames: V1 V2 V3 V4 V5 V6 V7 V8 V9 V10 V11 V12 V13 V14 V15 V16 V17 V18 V19 V20 V21 V22 V23 V24 V25 V26 V27 V28 V29 V30 V31 V32 V33 V34 V35 V36 V37 V38 V39 V40 V41 V42 V43 V44 V45 V46 V47 V48 V49 V50 +varIds: 1 2 7 8 9 11 21 22 23 36 37 38 47 48 49 +varIds for ALL Manager Variables: -1 1 2 -1 -1 -1 -1 7 8 9 -1 11 -1 -1 -1 -1 -1 -1 -1 -1 -1 21 22 23 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 36 37 38 -1 -1 -1 -1 -1 -1 -1 -1 47 48 49 +varComposeIds: 1 2 7 8 9 11 21 22 23 36 37 38 47 48 49 +varComposeIds for ALL Manager Variables: -1 1 2 -1 -1 -1 -1 7 8 9 -1 11 -1 -1 -1 -1 -1 -1 -1 -1 -1 21 22 23 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 36 37 38 -1 -1 -1 -1 -1 -1 -1 -1 47 48 49 +varAuxIds: 3 5 15 17 19 23 43 45 47 73 75 77 95 97 99 +varAuxIds for ALL Manager Variables: -1 3 5 -1 -1 -1 -1 15 17 19 -1 23 -1 -1 -1 -1 -1 -1 -1 -1 -1 43 45 47 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 73 75 77 -1 -1 -1 -1 -1 -1 -1 -1 95 97 99 +Number of roots: 1 +TestDddmp> File : TestDddmp> DD TYPE: DDDMP_ADD +Number of variables: 3 +Number of support variables: 2 +suppVarNames: DUMMY1 DUMMY2 +orderedVarNames: DUMMY0 DUMMY1 DUMMY2 +varIds: 1 2 +varIds for ALL Manager Variables: -1 1 2 +varComposeIds: 1 2 +varComposeIds for ALL Manager Variables: -1 1 2 +varAuxIds: 1 2 +varAuxIds for ALL Manager Variables: -1 1 2 +Number of roots: 1 +TestDddmp> File : TestDddmp> DD TYPE: DDDMP_CNF +Number of variables: 50 +Number of support variables: 15 +suppVarNames: V2 V3 V8 V9 V10 V12 V22 V23 V24 V37 V38 V39 V48 V49 V50 +orderedVarNames: V1 V2 V3 V4 V5 V6 V7 V8 V9 V10 V11 V12 V13 V14 V15 V16 V17 V18 V19 V20 V21 V22 V23 V24 V25 V26 V27 V28 V29 V30 V31 V32 V33 V34 V35 V36 V37 V38 V39 V40 V41 V42 V43 V44 V45 V46 V47 V48 V49 V50 +varIds: 1 2 7 8 9 11 21 22 23 36 37 38 47 48 49 +varIds for ALL Manager Variables: -1 1 2 -1 -1 -1 -1 7 8 9 -1 11 -1 -1 -1 -1 -1 -1 -1 -1 -1 21 22 23 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 36 37 38 -1 -1 -1 -1 -1 -1 -1 -1 47 48 49 +varComposeIds: 1 2 7 8 9 11 21 22 23 36 37 38 47 48 49 +varComposeIds for ALL Manager Variables: -1 1 2 -1 -1 -1 -1 7 8 9 -1 11 -1 -1 -1 -1 -1 -1 -1 -1 -1 21 22 23 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 36 37 38 -1 -1 -1 -1 -1 -1 -1 -1 47 48 49 +varAuxIds: 1 2 7 8 9 11 21 22 23 36 37 38 47 48 49 +varAuxIds for ALL Manager Variables: -1 1 2 -1 -1 -1 -1 7 8 9 -1 11 -1 -1 -1 -1 -1 -1 -1 -1 -1 21 22 23 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 36 37 38 -1 -1 -1 -1 -1 -1 -1 -1 47 48 49 +Number of roots: 1 +TestDddmp> Quitting CUDD Manager. +TestDddmp> End of test. +-------------------------------- ... END ---------------------------------- +rm: No match. +--------------------------------------------------------------------------- +-------------------- TESTING Load BDD from DDDMP-1.0 ---------------------- +--------------------------------------------------------------------------- +#./../testdddmp Version 2.0.2 (use command help) +TestDddmp> Number of Variables: TestDddmp> File : TestDddmp> DD TYPE: DDDMP_BDD +Number of variables: 10 +Number of support variables: 7 +suppVarNames: G0 G1 G2 G3 G5 G6 G7 +orderedVarNames: G0 G1 G2 G3 G5 G6 G7 DUMMY7 DUMMY8 DUMMY9 +varIds: 0 1 2 3 4 5 6 +varIds for ALL Manager Variables: 0 1 2 3 4 5 6 -1 -1 -1 +varComposeIds: 0 1 2 3 4 6 8 +varComposeIds for ALL Manager Variables: 0 1 2 3 4 6 8 -1 -1 -1 +varAuxIds: 0 1 2 3 4 5 6 +varAuxIds for ALL Manager Variables: 0 1 2 3 4 5 6 -1 -1 -1 +Number of roots: 3 +TestDddmp> File : Which Array of BDDs [0..19]: TestDddmp> File : Which Array of BDDs [0..19]: Storing Array of BDDs in file s27deltaDddmp1.bdd.tmp ... +done. +TestDddmp> Quitting CUDD Manager. +TestDddmp> End of test. +----------------------------- ... RESULTS ... ----------------------------- +-------------------------------- ... END ---------------------------------- +rm: No match. +--------------------------------------------------------------------------- +----------------------- TESTING basic Load/Store ... ---------------------- +--------------------------------------------------------------------------- +#./../testdddmp Version 2.0.2 (use command help) +TestDddmp> Number of Variables: TestDddmp> File : TestDddmp> File : Which BDDs [0..19]: Loading 0.bdd ... +TestDddmp> File : Which BDDs [0..19]: Loading 1.bdd ... +TestDddmp> Operation [or,and,xor,!,buf(=)] : Source1 [0..19]: Source2 [0..19]: Destination [0..19]: TestDddmp> File : Which BDDs [0..19]: Storing 0or1.bdd.tmp ... +TestDddmp> File : Which BDDs [0..19]: Loading 2.bdd ... +TestDddmp> File : Which BDDs [0..19]: Loading 3.bdd ... +TestDddmp> Operation [or,and,xor,!,buf(=)] : Source1 [0..19]: Source2 [0..19]: Destination [0..19]: TestDddmp> File : Which BDDs [0..19]: Storing 2and3.bdd.tmp ... +TestDddmp> File : TestDddmp> File : Which BDDs [0..19]: Loading 4.bdd ... +TestDddmp> File : Which BDDs [0..19]: Loading 5.bdd ... +TestDddmp> Operation [or,and,xor,!,buf(=)] : Source1 [0..19]: Source2 [0..19]: Destination [0..19]: TestDddmp> File : Which BDDs [0..19]: Storing 4xor5.bdd.tmp ... +TestDddmp> Quitting CUDD Manager. +TestDddmp> End of test. +----------------------------- ... RESULTS ... ----------------------------- +-------------------------------- ... END ---------------------------------- +rm: No match. +--------------------------------------------------------------------------- +---------- TESTING Load/Store with sifting, varnames & varauxids ---------- +--------------------------------------------------------------------------- +#./../testdddmp Version 2.0.2 (use command help) +TestDddmp> Number of Variables: TestDddmp> File : TestDddmp> File : Which BDDs [0..19]: Loading 4.bdd ... +TestDddmp> File : TestDddmp> File : Which BDDs [0..19]: Storing 4a.bdd.tmp ... +TestDddmp> Reordering Approach (1..17): TestDddmp> File : Which BDDs [0..19]: Storing 4b.bdd.tmp ... +TestDddmp> Quitting CUDD Manager. +TestDddmp> End of test. +------------------------- ... END PHASE 1 ... ----------------------------- +#./../testdddmp Version 2.0.2 (use command help) +TestDddmp> Number of Variables: TestDddmp> File : TestDddmp> Variable matchmode: +Match IDs (1) +Match permIDs (2) +Match names (must have been loaded) (3) +Match auxids (must have been loaded) (4) +Match composeids (must have been loaded) (5) +Your choice: TestDddmp> File : Which BDDs [0..19]: Loading 4b.bdd.tmp ... +TestDddmp> File : TestDddmp> File : Which BDDs [0..19]: Storing 4c.bdd.tmp ... +TestDddmp> Quitting CUDD Manager. +TestDddmp> End of test. +----------------------------- ... RESULTS ... ----------------------------- +-------------------------------- ... END ---------------------------------- +rm: No match. +--------------------------------------------------------------------------- +--------------------- TESTING Load ADD and Store ADD ---------------------- +--------------------------------------------------------------------------- +#./../testdddmp Version 2.0.2 (use command help) +TestDddmp> Number of Variables: TestDddmp> File : TestDddmp> File : Which BDDs [0..19]: Loading 0.add ... +Load: +-01 2 +-1- 1 +TestDddmp> File : Which BDDs [0..19]: Storing 0.add.tmp ... +TestDddmp> Quitting CUDD Manager. +TestDddmp> Number of Variables: TestDddmp> File : TestDddmp> File : Which BDDs [0..19]: Loading 1.add ... +Load: +-0001--------------------------------------------- 1 +-0010--------------------------------------------- 2 +-0100--------------------------------------------- 1 +-0101--------------------------------------------- 2 +-0111--------------------------------------------- 1 +-1000--------------------------------------------- 2 +-1010--------------------------------------------- 1 +-1011--------------------------------------------- 2 +-1101--------------------------------------------- 1 +-1110--------------------------------------------- 2 +TestDddmp> File : Which BDDs [0..19]: Storing 1.add.tmp ... +TestDddmp> Quitting CUDD Manager. +TestDddmp> End of test. +----------------------------- ... RESULTS ... ----------------------------- +-------------------------------- ... END ---------------------------------- +rm: No match. +--------------------------------------------------------------------------- +--------------------- TESTING Load BDD and Store CNF ---------------------- +--------------------------------------------------------------------------- +#./../testdddmp Version 2.0.2 (use command help) +TestDddmp> Number of Variables: TestDddmp> File : TestDddmp> File : Which BDDs [0..19]: Loading 4.bdd ... +TestDddmp> File : Which BDDs [0..19]: Format (Node=N, Maxterm=M, Best=B) : Initial ID : Storing 4.cnf.tmp ... +Number of Clauses Stored = 108 +Number of New Variable Created Storing = 31 +TestDddmp> Quitting CUDD Manager. +TestDddmp> End of test. +--------------------- TESTING Load CNF and Store BDD ---------------------- +#./../testdddmp Version 2.0.2 (use command help) +TestDddmp> Number of Variables: TestDddmp> File : TestDddmp> File : Which BDDs [0..19]: Loading 4.cnf.tmp ... +TestDddmp> DD TYPE: DDDMP_CNF +Number of variables: 150 +Number of support variables: 15 +suppVarNames: V3 V8 V23 V24 V37 V39 DUMMY21 DUMMY22 DUMMY23 DUMMY36 DUMMY37 DUMMY38 DUMMY47 DUMMY48 DUMMY49 +orderedVarNames: V2 V3 V8 V9 V10 V12 V22 V23 V24 V37 V38 V39 V48 V49 V50 DUMMY15 DUMMY16 DUMMY17 DUMMY18 DUMMY19 DUMMY20 DUMMY21 DUMMY22 DUMMY23 DUMMY24 DUMMY25 DUMMY26 DUMMY27 DUMMY28 DUMMY29 DUMMY30 DUMMY31 DUMMY32 DUMMY33 DUMMY34 DUMMY35 DUMMY36 DUMMY37 DUMMY38 DUMMY39 DUMMY40 DUMMY41 DUMMY42 DUMMY43 DUMMY44 DUMMY45 DUMMY46 DUMMY47 DUMMY48 DUMMY49 DUMMY50 DUMMY51 DUMMY52 DUMMY53 DUMMY54 DUMMY55 DUMMY56 DUMMY57 DUMMY58 DUMMY59 DUMMY60 DUMMY61 DUMMY62 DUMMY63 DUMMY64 DUMMY65 DUMMY66 DUMMY67 DUMMY68 DUMMY69 DUMMY70 DUMMY71 DUMMY72 DUMMY73 DUMMY74 DUMMY75 DUMMY76 DUMMY77 DUMMY78 DUMMY79 DUMMY80 DUMMY81 DUMMY82 DUMMY83 DUMMY84 DUMMY85 DUMMY86 DUMMY87 DUMMY88 DUMMY89 DUMMY90 DUMMY91 DUMMY92 DUMMY93 DUMMY94 DUMMY95 DUMMY96 DUMMY97 DUMMY98 DUMMY99 DUMMY100 DUMMY101 DUMMY102 DUMMY103 DUMMY104 DUMMY105 DUMMY106 DUMMY107 DUMMY108 DUMMY109 DUMMY110 DUMMY111 DUMMY112 DUMMY113 DUMMY114 DUMMY115 DUMMY116 DUMMY117 DUMMY118 DUMMY119 DUMMY120 DUMMY121 DUMMY122 DUMMY123 DUMMY124 DUMMY125 DUMMY126 DUMMY127 DUMMY128 DUMMY129 DUMMY130 DUMMY131 DUMMY132 DUMMY133 DUMMY134 DUMMY135 DUMMY136 DUMMY137 DUMMY138 DUMMY139 DUMMY140 DUMMY141 DUMMY142 DUMMY143 DUMMY144 DUMMY145 DUMMY146 DUMMY147 DUMMY148 DUMMY149 +varIds: 1 2 7 8 9 11 21 22 23 36 37 38 47 48 49 +varIds for ALL Manager Variables: -1 1 2 -1 -1 -1 -1 7 8 9 -1 11 -1 -1 -1 -1 -1 -1 -1 -1 -1 21 22 23 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 36 37 38 -1 -1 -1 -1 -1 -1 -1 -1 47 48 49 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 +varComposeIds: 1 2 7 8 9 11 21 22 23 36 37 38 47 48 49 +varComposeIds for ALL Manager Variables: -1 1 2 -1 -1 -1 -1 7 8 9 -1 11 -1 -1 -1 -1 -1 -1 -1 -1 -1 21 22 23 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 36 37 38 -1 -1 -1 -1 -1 -1 -1 -1 47 48 49 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 +varAuxIds: 1 2 7 8 9 11 21 22 23 36 37 38 47 48 49 +varAuxIds for ALL Manager Variables: -1 1 2 -1 -1 -1 -1 7 8 9 -1 11 -1 -1 -1 -1 -1 -1 -1 -1 -1 21 22 23 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 36 37 38 -1 -1 -1 -1 -1 -1 -1 -1 47 48 49 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 +Number of roots: 1 +TestDddmp> File : Which BDDs [0..19]: Storing 4.bdd.tmp ... +TestDddmp> Quitting CUDD Manager. +TestDddmp> End of test. +----------------------------- ... RESULTS ... ----------------------------- +-------------------------------- ... END ---------------------------------- +rm: No match. +--------------------------------------------------------------------------- +--------------------- TESTING Load BDD and Store CNF ---------------------- +--------------------------------------------------------------------------- +#./../testdddmp Version 2.0.2 (use command help) +TestDddmp> Number of Variables: TestDddmp> File : TestDddmp> File : Which BDDs [0..19]: Loading 4.bdd ... +TestDddmp> File : Which BDDs [0..19]: Format (Node=N, Maxterm=M, Best=B) : Initial ID : Storing 4.node1.tmp ... +Number of Clauses Stored = 108 +Number of New Variable Created Storing = 31 +TestDddmp> File : Which BDDs [0..19]: Format (Node=N, Maxterm=M, Best=B) : Initial ID : Storing 4.max1.tmp ... +Number of Clauses Stored = 103 +Number of New Variable Created Storing = 0 +TestDddmp> File : Which BDDs [0..19]: Format (Node=N, Maxterm=M, Best=B) : Max Number of Edges (Insert cut-point from there on) : Max BDD-Path Length (Insert cut-point from there on) : Initial ID : Storing 4.node2.tmp ... +Number of Clauses Stored = 114 +Number of New Variable Created Storing = 31 +TestDddmp> File : Which BDDs [0..19]: Format (Node=N, Maxterm=M, Best=B) : Max Number of Edges (Insert cut-point from there on) : Max BDD-Path Length (Insert cut-point from there on) : Initial ID : Storing 4.node3.tmp ... +Number of Clauses Stored = 108 +Number of New Variable Created Storing = 31 +TestDddmp> File : Which BDDs [0..19]: Format (Node=N, Maxterm=M, Best=B) : Max Number of Edges (Insert cut-point from there on) : Max BDD-Path Length (Insert cut-point from there on) : Initial ID : Storing 4.max2.tmp ... +Number of Clauses Stored = 103 +Number of New Variable Created Storing = 0 +TestDddmp> File : Which BDDs [0..19]: Format (Node=N, Maxterm=M, Best=B) : Max Number of Edges (Insert cut-point from there on) : Max BDD-Path Length (Insert cut-point from there on) : Initial ID : Storing 4.best1.tmp ... +Number of Clauses Stored = 53 +Number of New Variable Created Storing = 7 +TestDddmp> File : Which BDDs [0..19]: Format (Node=N, Maxterm=M, Best=B) : Max Number of Edges (Insert cut-point from there on) : Max BDD-Path Length (Insert cut-point from there on) : Initial ID : Storing 4.best2.tmp ... +Number of Clauses Stored = 69 +Number of New Variable Created Storing = 12 +TestDddmp> Quitting CUDD Manager. +TestDddmp> End of test. +--------------------------------------------------------------------------- +--------------------- TESTING Load CNF and Store BDD ---------------------- +--------------------------------------------------------------------------- +#./../testdddmp Version 2.0.2 (use command help) +TestDddmp> Number of Variables: TestDddmp> File : TestDddmp> File : Which BDDs [0..19]: Loading 4.node2.tmp ... +TestDddmp> DD TYPE: DDDMP_CNF +Number of variables: 150 +Number of support variables: 15 +suppVarNames: V3 V8 V23 V24 V37 V39 DUMMY21 DUMMY22 DUMMY23 DUMMY36 DUMMY37 DUMMY38 DUMMY47 DUMMY48 DUMMY49 +orderedVarNames: V2 V3 V8 V9 V10 V12 V22 V23 V24 V37 V38 V39 V48 V49 V50 DUMMY15 DUMMY16 DUMMY17 DUMMY18 DUMMY19 DUMMY20 DUMMY21 DUMMY22 DUMMY23 DUMMY24 DUMMY25 DUMMY26 DUMMY27 DUMMY28 DUMMY29 DUMMY30 DUMMY31 DUMMY32 DUMMY33 DUMMY34 DUMMY35 DUMMY36 DUMMY37 DUMMY38 DUMMY39 DUMMY40 DUMMY41 DUMMY42 DUMMY43 DUMMY44 DUMMY45 DUMMY46 DUMMY47 DUMMY48 DUMMY49 DUMMY50 DUMMY51 DUMMY52 DUMMY53 DUMMY54 DUMMY55 DUMMY56 DUMMY57 DUMMY58 DUMMY59 DUMMY60 DUMMY61 DUMMY62 DUMMY63 DUMMY64 DUMMY65 DUMMY66 DUMMY67 DUMMY68 DUMMY69 DUMMY70 DUMMY71 DUMMY72 DUMMY73 DUMMY74 DUMMY75 DUMMY76 DUMMY77 DUMMY78 DUMMY79 DUMMY80 DUMMY81 DUMMY82 DUMMY83 DUMMY84 DUMMY85 DUMMY86 DUMMY87 DUMMY88 DUMMY89 DUMMY90 DUMMY91 DUMMY92 DUMMY93 DUMMY94 DUMMY95 DUMMY96 DUMMY97 DUMMY98 DUMMY99 DUMMY100 DUMMY101 DUMMY102 DUMMY103 DUMMY104 DUMMY105 DUMMY106 DUMMY107 DUMMY108 DUMMY109 DUMMY110 DUMMY111 DUMMY112 DUMMY113 DUMMY114 DUMMY115 DUMMY116 DUMMY117 DUMMY118 DUMMY119 DUMMY120 DUMMY121 DUMMY122 DUMMY123 DUMMY124 DUMMY125 DUMMY126 DUMMY127 DUMMY128 DUMMY129 DUMMY130 DUMMY131 DUMMY132 DUMMY133 DUMMY134 DUMMY135 DUMMY136 DUMMY137 DUMMY138 DUMMY139 DUMMY140 DUMMY141 DUMMY142 DUMMY143 DUMMY144 DUMMY145 DUMMY146 DUMMY147 DUMMY148 DUMMY149 +varIds: 1 2 7 8 9 11 21 22 23 36 37 38 47 48 49 +varIds for ALL Manager Variables: -1 1 2 -1 -1 -1 -1 7 8 9 -1 11 -1 -1 -1 -1 -1 -1 -1 -1 -1 21 22 23 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 36 37 38 -1 -1 -1 -1 -1 -1 -1 -1 47 48 49 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 +varComposeIds: 1 2 7 8 9 11 21 22 23 36 37 38 47 48 49 +varComposeIds for ALL Manager Variables: -1 1 2 -1 -1 -1 -1 7 8 9 -1 11 -1 -1 -1 -1 -1 -1 -1 -1 -1 21 22 23 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 36 37 38 -1 -1 -1 -1 -1 -1 -1 -1 47 48 49 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 +varAuxIds: 1 2 7 8 9 11 21 22 23 36 37 38 47 48 49 +varAuxIds for ALL Manager Variables: -1 1 2 -1 -1 -1 -1 7 8 9 -1 11 -1 -1 -1 -1 -1 -1 -1 -1 -1 21 22 23 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 36 37 38 -1 -1 -1 -1 -1 -1 -1 -1 47 48 49 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 +Number of roots: 1 +TestDddmp> File : Which BDDs [0..19]: Storing 4.node2.bdd.tmp ... +TestDddmp> Quitting CUDD Manager. +TestDddmp> End of test. +#./../testdddmp Version 2.0.2 (use command help) +TestDddmp> Number of Variables: TestDddmp> File : TestDddmp> File : Which BDDs [0..19]: Loading 4.node3.tmp ... +TestDddmp> DD TYPE: DDDMP_CNF +Number of variables: 150 +Number of support variables: 15 +suppVarNames: V3 V8 V23 V24 V37 V39 DUMMY21 DUMMY22 DUMMY23 DUMMY36 DUMMY37 DUMMY38 DUMMY47 DUMMY48 DUMMY49 +orderedVarNames: V2 V3 V8 V9 V10 V12 V22 V23 V24 V37 V38 V39 V48 V49 V50 DUMMY15 DUMMY16 DUMMY17 DUMMY18 DUMMY19 DUMMY20 DUMMY21 DUMMY22 DUMMY23 DUMMY24 DUMMY25 DUMMY26 DUMMY27 DUMMY28 DUMMY29 DUMMY30 DUMMY31 DUMMY32 DUMMY33 DUMMY34 DUMMY35 DUMMY36 DUMMY37 DUMMY38 DUMMY39 DUMMY40 DUMMY41 DUMMY42 DUMMY43 DUMMY44 DUMMY45 DUMMY46 DUMMY47 DUMMY48 DUMMY49 DUMMY50 DUMMY51 DUMMY52 DUMMY53 DUMMY54 DUMMY55 DUMMY56 DUMMY57 DUMMY58 DUMMY59 DUMMY60 DUMMY61 DUMMY62 DUMMY63 DUMMY64 DUMMY65 DUMMY66 DUMMY67 DUMMY68 DUMMY69 DUMMY70 DUMMY71 DUMMY72 DUMMY73 DUMMY74 DUMMY75 DUMMY76 DUMMY77 DUMMY78 DUMMY79 DUMMY80 DUMMY81 DUMMY82 DUMMY83 DUMMY84 DUMMY85 DUMMY86 DUMMY87 DUMMY88 DUMMY89 DUMMY90 DUMMY91 DUMMY92 DUMMY93 DUMMY94 DUMMY95 DUMMY96 DUMMY97 DUMMY98 DUMMY99 DUMMY100 DUMMY101 DUMMY102 DUMMY103 DUMMY104 DUMMY105 DUMMY106 DUMMY107 DUMMY108 DUMMY109 DUMMY110 DUMMY111 DUMMY112 DUMMY113 DUMMY114 DUMMY115 DUMMY116 DUMMY117 DUMMY118 DUMMY119 DUMMY120 DUMMY121 DUMMY122 DUMMY123 DUMMY124 DUMMY125 DUMMY126 DUMMY127 DUMMY128 DUMMY129 DUMMY130 DUMMY131 DUMMY132 DUMMY133 DUMMY134 DUMMY135 DUMMY136 DUMMY137 DUMMY138 DUMMY139 DUMMY140 DUMMY141 DUMMY142 DUMMY143 DUMMY144 DUMMY145 DUMMY146 DUMMY147 DUMMY148 DUMMY149 +varIds: 1 2 7 8 9 11 21 22 23 36 37 38 47 48 49 +varIds for ALL Manager Variables: -1 1 2 -1 -1 -1 -1 7 8 9 -1 11 -1 -1 -1 -1 -1 -1 -1 -1 -1 21 22 23 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 36 37 38 -1 -1 -1 -1 -1 -1 -1 -1 47 48 49 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 +varComposeIds: 1 2 7 8 9 11 21 22 23 36 37 38 47 48 49 +varComposeIds for ALL Manager Variables: -1 1 2 -1 -1 -1 -1 7 8 9 -1 11 -1 -1 -1 -1 -1 -1 -1 -1 -1 21 22 23 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 36 37 38 -1 -1 -1 -1 -1 -1 -1 -1 47 48 49 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 +varAuxIds: 1 2 7 8 9 11 21 22 23 36 37 38 47 48 49 +varAuxIds for ALL Manager Variables: -1 1 2 -1 -1 -1 -1 7 8 9 -1 11 -1 -1 -1 -1 -1 -1 -1 -1 -1 21 22 23 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 36 37 38 -1 -1 -1 -1 -1 -1 -1 -1 47 48 49 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 +Number of roots: 1 +TestDddmp> File : Which BDDs [0..19]: Storing 4.node3.bdd.tmp ... +TestDddmp> Quitting CUDD Manager. +TestDddmp> End of test. +#./../testdddmp Version 2.0.2 (use command help) +TestDddmp> Number of Variables: TestDddmp> File : TestDddmp> File : Which BDDs [0..19]: Loading 4.best1.tmp ... +TestDddmp> DD TYPE: DDDMP_CNF +Number of variables: 150 +Number of support variables: 15 +suppVarNames: V3 V8 V23 V24 V37 V39 DUMMY21 DUMMY22 DUMMY23 DUMMY36 DUMMY37 DUMMY38 DUMMY47 DUMMY48 DUMMY49 +orderedVarNames: V2 V3 V8 V9 V10 V12 V22 V23 V24 V37 V38 V39 V48 V49 V50 DUMMY15 DUMMY16 DUMMY17 DUMMY18 DUMMY19 DUMMY20 DUMMY21 DUMMY22 DUMMY23 DUMMY24 DUMMY25 DUMMY26 DUMMY27 DUMMY28 DUMMY29 DUMMY30 DUMMY31 DUMMY32 DUMMY33 DUMMY34 DUMMY35 DUMMY36 DUMMY37 DUMMY38 DUMMY39 DUMMY40 DUMMY41 DUMMY42 DUMMY43 DUMMY44 DUMMY45 DUMMY46 DUMMY47 DUMMY48 DUMMY49 DUMMY50 DUMMY51 DUMMY52 DUMMY53 DUMMY54 DUMMY55 DUMMY56 DUMMY57 DUMMY58 DUMMY59 DUMMY60 DUMMY61 DUMMY62 DUMMY63 DUMMY64 DUMMY65 DUMMY66 DUMMY67 DUMMY68 DUMMY69 DUMMY70 DUMMY71 DUMMY72 DUMMY73 DUMMY74 DUMMY75 DUMMY76 DUMMY77 DUMMY78 DUMMY79 DUMMY80 DUMMY81 DUMMY82 DUMMY83 DUMMY84 DUMMY85 DUMMY86 DUMMY87 DUMMY88 DUMMY89 DUMMY90 DUMMY91 DUMMY92 DUMMY93 DUMMY94 DUMMY95 DUMMY96 DUMMY97 DUMMY98 DUMMY99 DUMMY100 DUMMY101 DUMMY102 DUMMY103 DUMMY104 DUMMY105 DUMMY106 DUMMY107 DUMMY108 DUMMY109 DUMMY110 DUMMY111 DUMMY112 DUMMY113 DUMMY114 DUMMY115 DUMMY116 DUMMY117 DUMMY118 DUMMY119 DUMMY120 DUMMY121 DUMMY122 DUMMY123 DUMMY124 DUMMY125 DUMMY126 DUMMY127 DUMMY128 DUMMY129 DUMMY130 DUMMY131 DUMMY132 DUMMY133 DUMMY134 DUMMY135 DUMMY136 DUMMY137 DUMMY138 DUMMY139 DUMMY140 DUMMY141 DUMMY142 DUMMY143 DUMMY144 DUMMY145 DUMMY146 DUMMY147 DUMMY148 DUMMY149 +varIds: 1 2 7 8 9 11 21 22 23 36 37 38 47 48 49 +varIds for ALL Manager Variables: -1 1 2 -1 -1 -1 -1 7 8 9 -1 11 -1 -1 -1 -1 -1 -1 -1 -1 -1 21 22 23 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 36 37 38 -1 -1 -1 -1 -1 -1 -1 -1 47 48 49 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 +varComposeIds: 1 2 7 8 9 11 21 22 23 36 37 38 47 48 49 +varComposeIds for ALL Manager Variables: -1 1 2 -1 -1 -1 -1 7 8 9 -1 11 -1 -1 -1 -1 -1 -1 -1 -1 -1 21 22 23 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 36 37 38 -1 -1 -1 -1 -1 -1 -1 -1 47 48 49 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 +varAuxIds: 1 2 7 8 9 11 21 22 23 36 37 38 47 48 49 +varAuxIds for ALL Manager Variables: -1 1 2 -1 -1 -1 -1 7 8 9 -1 11 -1 -1 -1 -1 -1 -1 -1 -1 -1 21 22 23 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 36 37 38 -1 -1 -1 -1 -1 -1 -1 -1 47 48 49 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 +Number of roots: 1 +TestDddmp> File : Which BDDs [0..19]: Storing 4.best1.bdd.tmp ... +TestDddmp> Quitting CUDD Manager. +TestDddmp> End of test. +#./../testdddmp Version 2.0.2 (use command help) +TestDddmp> Number of Variables: TestDddmp> File : TestDddmp> File : Which BDDs [0..19]: Loading 4.best2.tmp ... +TestDddmp> DD TYPE: DDDMP_CNF +Number of variables: 150 +Number of support variables: 15 +suppVarNames: V3 V8 V23 V24 V37 V39 DUMMY21 DUMMY22 DUMMY23 DUMMY36 DUMMY37 DUMMY38 DUMMY47 DUMMY48 DUMMY49 +orderedVarNames: V2 V3 V8 V9 V10 V12 V22 V23 V24 V37 V38 V39 V48 V49 V50 DUMMY15 DUMMY16 DUMMY17 DUMMY18 DUMMY19 DUMMY20 DUMMY21 DUMMY22 DUMMY23 DUMMY24 DUMMY25 DUMMY26 DUMMY27 DUMMY28 DUMMY29 DUMMY30 DUMMY31 DUMMY32 DUMMY33 DUMMY34 DUMMY35 DUMMY36 DUMMY37 DUMMY38 DUMMY39 DUMMY40 DUMMY41 DUMMY42 DUMMY43 DUMMY44 DUMMY45 DUMMY46 DUMMY47 DUMMY48 DUMMY49 DUMMY50 DUMMY51 DUMMY52 DUMMY53 DUMMY54 DUMMY55 DUMMY56 DUMMY57 DUMMY58 DUMMY59 DUMMY60 DUMMY61 DUMMY62 DUMMY63 DUMMY64 DUMMY65 DUMMY66 DUMMY67 DUMMY68 DUMMY69 DUMMY70 DUMMY71 DUMMY72 DUMMY73 DUMMY74 DUMMY75 DUMMY76 DUMMY77 DUMMY78 DUMMY79 DUMMY80 DUMMY81 DUMMY82 DUMMY83 DUMMY84 DUMMY85 DUMMY86 DUMMY87 DUMMY88 DUMMY89 DUMMY90 DUMMY91 DUMMY92 DUMMY93 DUMMY94 DUMMY95 DUMMY96 DUMMY97 DUMMY98 DUMMY99 DUMMY100 DUMMY101 DUMMY102 DUMMY103 DUMMY104 DUMMY105 DUMMY106 DUMMY107 DUMMY108 DUMMY109 DUMMY110 DUMMY111 DUMMY112 DUMMY113 DUMMY114 DUMMY115 DUMMY116 DUMMY117 DUMMY118 DUMMY119 DUMMY120 DUMMY121 DUMMY122 DUMMY123 DUMMY124 DUMMY125 DUMMY126 DUMMY127 DUMMY128 DUMMY129 DUMMY130 DUMMY131 DUMMY132 DUMMY133 DUMMY134 DUMMY135 DUMMY136 DUMMY137 DUMMY138 DUMMY139 DUMMY140 DUMMY141 DUMMY142 DUMMY143 DUMMY144 DUMMY145 DUMMY146 DUMMY147 DUMMY148 DUMMY149 +varIds: 1 2 7 8 9 11 21 22 23 36 37 38 47 48 49 +varIds for ALL Manager Variables: -1 1 2 -1 -1 -1 -1 7 8 9 -1 11 -1 -1 -1 -1 -1 -1 -1 -1 -1 21 22 23 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 36 37 38 -1 -1 -1 -1 -1 -1 -1 -1 47 48 49 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 +varComposeIds: 1 2 7 8 9 11 21 22 23 36 37 38 47 48 49 +varComposeIds for ALL Manager Variables: -1 1 2 -1 -1 -1 -1 7 8 9 -1 11 -1 -1 -1 -1 -1 -1 -1 -1 -1 21 22 23 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 36 37 38 -1 -1 -1 -1 -1 -1 -1 -1 47 48 49 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 +varAuxIds: 1 2 7 8 9 11 21 22 23 36 37 38 47 48 49 +varAuxIds for ALL Manager Variables: -1 1 2 -1 -1 -1 -1 7 8 9 -1 11 -1 -1 -1 -1 -1 -1 -1 -1 -1 21 22 23 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 36 37 38 -1 -1 -1 -1 -1 -1 -1 -1 47 48 49 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 +Number of roots: 1 +TestDddmp> File : Which BDDs [0..19]: Storing 4.best2.bdd.tmp ... +TestDddmp> Quitting CUDD Manager. +TestDddmp> End of test. +----------------------------- ... RESULTS ... ----------------------------- +-------------------------------- ... END ---------------------------------- diff --git a/distr/dddmp/exp/runAllTest.script b/distr/dddmp/exp/runAllTest.script new file mode 100755 index 0000000..8d792ef --- /dev/null +++ b/distr/dddmp/exp/runAllTest.script @@ -0,0 +1,11 @@ +# !/bin/sh +# +# Run All Test Files +# +./test1.script +./test2.script +./test3.script +./test4.script +./test5.script +./test6.script +./test7.script diff --git a/distr/dddmp/exp/s27RP1.bdd b/distr/dddmp/exp/s27RP1.bdd new file mode 100644 index 0000000..5653260 --- /dev/null +++ b/distr/dddmp/exp/s27RP1.bdd @@ -0,0 +1,18 @@ +# MONO +.ver DDDMP-1.0 +.mode A +.varinfo 3 +.nnodes 3 +.nvars 10 +.nsuppvars 2 +.varnames G5 G6 +.ids 4 5 +.permids 4 6 +.auxids 4 5 +.nroots 1 +.rootids -3 +.nodes +1 T 1 0 0 +2 5 1 1 -1 +3 4 0 2 -1 +.end diff --git a/distr/dddmp/exp/s27deltaDddmp1.bdd b/distr/dddmp/exp/s27deltaDddmp1.bdd new file mode 100644 index 0000000..11a5956 --- /dev/null +++ b/distr/dddmp/exp/s27deltaDddmp1.bdd @@ -0,0 +1,31 @@ +.ver DDDMP-1.0 +.mode A +.varinfo 0 +.dd s27adelta.bdd +.nnodes 16 +.nvars 10 +.nsuppvars 7 +.varnames G0 G1 G2 G3 G5 G6 G7 +.ids 0 1 2 3 4 5 6 +.permids 0 1 2 3 4 6 8 +.auxids 0 1 2 3 4 5 6 +.nroots 3 +.rootids 6 -13 -16 +.nodes +1 T 1 0 0 +2 6 6 1 -1 +3 4 4 1 2 +4 3 3 3 1 +5 1 1 1 4 +6 0 0 5 -1 +7 5 5 1 -1 +8 4 4 1 -7 +9 5 5 1 -2 +10 4 4 1 -9 +11 3 3 10 8 +12 1 1 8 11 +13 0 0 5 12 +14 2 2 1 -1 +15 2 2 1 -2 +16 1 1 14 15 +.end diff --git a/distr/dddmp/exp/s27deltaDddmp1.bdd.bis b/distr/dddmp/exp/s27deltaDddmp1.bdd.bis new file mode 100644 index 0000000..b7fb86b --- /dev/null +++ b/distr/dddmp/exp/s27deltaDddmp1.bdd.bis @@ -0,0 +1,31 @@ +.ver DDDMP-2.0 +.mode A +.varinfo 0 +.nnodes 16 +.nvars 10 +.nsuppvars 7 +.suppvarnames G0 G1 G2 G3 G5 G6 G7 +.orderedvarnames G0 G1 G2 G3 G5 G6 G7 DUMMY7 DUMMY8 DUMMY9 +.ids 0 1 2 3 4 5 6 +.permids 0 1 2 3 4 5 6 +.auxids 0 1 2 3 4 5 6 +.nroots 3 +.rootids 6 -13 -16 +.nodes +1 T 1 0 0 +2 6 6 1 -1 +3 4 4 1 2 +4 3 3 3 1 +5 1 1 1 4 +6 0 0 5 -1 +7 5 5 1 -1 +8 4 4 1 -7 +9 5 5 1 -2 +10 4 4 1 -9 +11 3 3 10 8 +12 1 1 8 11 +13 0 0 5 12 +14 2 2 1 -1 +15 2 2 1 -2 +16 1 1 14 15 +.end diff --git a/distr/dddmp/exp/s27deltaDddmp2.bdd b/distr/dddmp/exp/s27deltaDddmp2.bdd new file mode 100644 index 0000000..d247bd1 --- /dev/null +++ b/distr/dddmp/exp/s27deltaDddmp2.bdd @@ -0,0 +1,32 @@ +.ver DDDMP-1.0 +.mode A +.varinfo 0 +.dd s27adelta.bdd +.nnodes 16 +.nvars 10 +.nsuppvars 7 +.orderedvarnames G0 G1 G2 G3 G5 G6 G7 TMP1 TMP2 TMP3 +.suppvarnames G0 G1 G2 G3 G5 G6 G7 +.ids 0 1 2 3 4 5 6 +.permids 0 1 2 3 4 6 8 +.auxids 0 1 2 3 4 5 6 +.nroots 3 +.rootids 6 -13 -16 +.nodes +1 T 1 0 0 +2 6 6 1 -1 +3 4 4 1 2 +4 3 3 3 1 +5 1 1 1 4 +6 0 0 5 -1 +7 5 5 1 -1 +8 4 4 1 -7 +9 5 5 1 -2 +10 4 4 1 -9 +11 3 3 10 8 +12 1 1 8 11 +13 0 0 5 12 +14 2 2 1 -1 +15 2 2 1 -2 +16 1 1 14 15 +.end diff --git a/distr/dddmp/exp/test1.out b/distr/dddmp/exp/test1.out new file mode 100644 index 0000000..96b2a3a --- /dev/null +++ b/distr/dddmp/exp/test1.out @@ -0,0 +1,44 @@ +rm: No match. +--------------------------------------------------------------------------- +--------------------- TESTING Load and Write Header ----------------------- +--------------------------------------------------------------------------- +#./../testdddmp Version 2.0.2 (use command help) +TestDddmp> Number of Variables: TestDddmp> File : TestDddmp> DD TYPE: DDDMP_BDD +Number of variables: 50 +Number of support variables: 15 +suppVarNames: V2 V3 V8 V9 V10 V12 V22 V23 V24 V37 V38 V39 V48 V49 V50 +orderedVarNames: V1 V2 V3 V4 V5 V6 V7 V8 V9 V10 V11 V12 V13 V14 V15 V16 V17 V18 V19 V20 V21 V22 V23 V24 V25 V26 V27 V28 V29 V30 V31 V32 V33 V34 V35 V36 V37 V38 V39 V40 V41 V42 V43 V44 V45 V46 V47 V48 V49 V50 +varIds: 1 2 7 8 9 11 21 22 23 36 37 38 47 48 49 +varIds for ALL Manager Variables: -1 1 2 -1 -1 -1 -1 7 8 9 -1 11 -1 -1 -1 -1 -1 -1 -1 -1 -1 21 22 23 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 36 37 38 -1 -1 -1 -1 -1 -1 -1 -1 47 48 49 +varComposeIds: 1 2 7 8 9 11 21 22 23 36 37 38 47 48 49 +varComposeIds for ALL Manager Variables: -1 1 2 -1 -1 -1 -1 7 8 9 -1 11 -1 -1 -1 -1 -1 -1 -1 -1 -1 21 22 23 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 36 37 38 -1 -1 -1 -1 -1 -1 -1 -1 47 48 49 +varAuxIds: 3 5 15 17 19 23 43 45 47 73 75 77 95 97 99 +varAuxIds for ALL Manager Variables: -1 3 5 -1 -1 -1 -1 15 17 19 -1 23 -1 -1 -1 -1 -1 -1 -1 -1 -1 43 45 47 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 73 75 77 -1 -1 -1 -1 -1 -1 -1 -1 95 97 99 +Number of roots: 1 +TestDddmp> File : TestDddmp> DD TYPE: DDDMP_ADD +Number of variables: 3 +Number of support variables: 2 +suppVarNames: DUMMY1 DUMMY2 +orderedVarNames: DUMMY0 DUMMY1 DUMMY2 +varIds: 1 2 +varIds for ALL Manager Variables: -1 1 2 +varComposeIds: 1 2 +varComposeIds for ALL Manager Variables: -1 1 2 +varAuxIds: 1 2 +varAuxIds for ALL Manager Variables: -1 1 2 +Number of roots: 1 +TestDddmp> File : TestDddmp> DD TYPE: DDDMP_CNF +Number of variables: 50 +Number of support variables: 15 +suppVarNames: V2 V3 V8 V9 V10 V12 V22 V23 V24 V37 V38 V39 V48 V49 V50 +orderedVarNames: V1 V2 V3 V4 V5 V6 V7 V8 V9 V10 V11 V12 V13 V14 V15 V16 V17 V18 V19 V20 V21 V22 V23 V24 V25 V26 V27 V28 V29 V30 V31 V32 V33 V34 V35 V36 V37 V38 V39 V40 V41 V42 V43 V44 V45 V46 V47 V48 V49 V50 +varIds: 1 2 7 8 9 11 21 22 23 36 37 38 47 48 49 +varIds for ALL Manager Variables: -1 1 2 -1 -1 -1 -1 7 8 9 -1 11 -1 -1 -1 -1 -1 -1 -1 -1 -1 21 22 23 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 36 37 38 -1 -1 -1 -1 -1 -1 -1 -1 47 48 49 +varComposeIds: 1 2 7 8 9 11 21 22 23 36 37 38 47 48 49 +varComposeIds for ALL Manager Variables: -1 1 2 -1 -1 -1 -1 7 8 9 -1 11 -1 -1 -1 -1 -1 -1 -1 -1 -1 21 22 23 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 36 37 38 -1 -1 -1 -1 -1 -1 -1 -1 47 48 49 +varAuxIds: 1 2 7 8 9 11 21 22 23 36 37 38 47 48 49 +varAuxIds for ALL Manager Variables: -1 1 2 -1 -1 -1 -1 7 8 9 -1 11 -1 -1 -1 -1 -1 -1 -1 -1 -1 21 22 23 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 36 37 38 -1 -1 -1 -1 -1 -1 -1 -1 47 48 49 +Number of roots: 1 +TestDddmp> Quitting CUDD Manager. +TestDddmp> End of test. +-------------------------------- ... END ---------------------------------- diff --git a/distr/dddmp/exp/test1.script b/distr/dddmp/exp/test1.script new file mode 100755 index 0000000..843e365 --- /dev/null +++ b/distr/dddmp/exp/test1.script @@ -0,0 +1,26 @@ +# !/bin/sh +# +# Check Header Load/Store for BDD/ADD/CNFs: +# Load Header +# Write Information on Standard Output +# +rm -f *.*.tmp +echo "---------------------------------------------------------------------------" +echo "--------------------- TESTING Load and Write Header -----------------------" +echo "---------------------------------------------------------------------------" +./../testdddmp << END +mi +50 +hlb +4.bdd +hw +hlb +0.add +hw +hlc +4.cnf +hw +mq +quit +END +echo "-------------------------------- ... END ----------------------------------" diff --git a/distr/dddmp/exp/test2.out b/distr/dddmp/exp/test2.out new file mode 100644 index 0000000..22d6e39 --- /dev/null +++ b/distr/dddmp/exp/test2.out @@ -0,0 +1,23 @@ +rm: No match. +--------------------------------------------------------------------------- +-------------------- TESTING Load BDD from DDDMP-1.0 ---------------------- +--------------------------------------------------------------------------- +#./../testdddmp Version 2.0.2 (use command help) +TestDddmp> Number of Variables: TestDddmp> File : TestDddmp> DD TYPE: DDDMP_BDD +Number of variables: 10 +Number of support variables: 7 +suppVarNames: G0 G1 G2 G3 G5 G6 G7 +orderedVarNames: G0 G1 G2 G3 G5 G6 G7 DUMMY7 DUMMY8 DUMMY9 +varIds: 0 1 2 3 4 5 6 +varIds for ALL Manager Variables: 0 1 2 3 4 5 6 -1 -1 -1 +varComposeIds: 0 1 2 3 4 6 8 +varComposeIds for ALL Manager Variables: 0 1 2 3 4 6 8 -1 -1 -1 +varAuxIds: 0 1 2 3 4 5 6 +varAuxIds for ALL Manager Variables: 0 1 2 3 4 5 6 -1 -1 -1 +Number of roots: 3 +TestDddmp> File : Which Array of BDDs [0..19]: TestDddmp> File : Which Array of BDDs [0..19]: Storing Array of BDDs in file s27deltaDddmp1.bdd.tmp ... +done. +TestDddmp> Quitting CUDD Manager. +TestDddmp> End of test. +----------------------------- ... RESULTS ... ----------------------------- +-------------------------------- ... END ---------------------------------- diff --git a/distr/dddmp/exp/test2.script b/distr/dddmp/exp/test2.script new file mode 100755 index 0000000..f719ed2 --- /dev/null +++ b/distr/dddmp/exp/test2.script @@ -0,0 +1,30 @@ +# !/bin/sh +# +# Check BDDs from DDDMP-1.0: +# Load an Array of BDDs from DDDMP-1.0 +# Store them +# +rm -f *.*.tmp +echo "---------------------------------------------------------------------------" +echo "-------------------- TESTING Load BDD from DDDMP-1.0 ----------------------" +echo "---------------------------------------------------------------------------" +./../testdddmp << END +mi +10 +hlb +s27deltaDddmp1.bdd +hw +bal +s27deltaDddmp1.bdd +0 +bas +s27deltaDddmp1.bdd.tmp +0 +mq +quit +END +echo "----------------------------- ... RESULTS ... -----------------------------" +diff --brief s27deltaDddmp1.bdd.tmp s27deltaDddmp1.bdd.bis +echo "-------------------------------- ... END ----------------------------------" +rm -f *.*.tmp + diff --git a/distr/dddmp/exp/test3.out b/distr/dddmp/exp/test3.out new file mode 100644 index 0000000..0c296c0 --- /dev/null +++ b/distr/dddmp/exp/test3.out @@ -0,0 +1,18 @@ +rm: No match. +--------------------------------------------------------------------------- +----------------------- TESTING basic Load/Store ... ---------------------- +--------------------------------------------------------------------------- +#./../testdddmp Version 2.0.2 (use command help) +TestDddmp> Number of Variables: TestDddmp> File : TestDddmp> File : Which BDDs [0..19]: Loading 0.bdd ... +TestDddmp> File : Which BDDs [0..19]: Loading 1.bdd ... +TestDddmp> Operation [or,and,xor,!,buf(=)] : Source1 [0..19]: Source2 [0..19]: Destination [0..19]: TestDddmp> File : Which BDDs [0..19]: Storing 0or1.bdd.tmp ... +TestDddmp> File : Which BDDs [0..19]: Loading 2.bdd ... +TestDddmp> File : Which BDDs [0..19]: Loading 3.bdd ... +TestDddmp> Operation [or,and,xor,!,buf(=)] : Source1 [0..19]: Source2 [0..19]: Destination [0..19]: TestDddmp> File : Which BDDs [0..19]: Storing 2and3.bdd.tmp ... +TestDddmp> File : TestDddmp> File : Which BDDs [0..19]: Loading 4.bdd ... +TestDddmp> File : Which BDDs [0..19]: Loading 5.bdd ... +TestDddmp> Operation [or,and,xor,!,buf(=)] : Source1 [0..19]: Source2 [0..19]: Destination [0..19]: TestDddmp> File : Which BDDs [0..19]: Storing 4xor5.bdd.tmp ... +TestDddmp> Quitting CUDD Manager. +TestDddmp> End of test. +----------------------------- ... RESULTS ... ----------------------------- +-------------------------------- ... END ---------------------------------- diff --git a/distr/dddmp/exp/test3.script b/distr/dddmp/exp/test3.script new file mode 100755 index 0000000..408496c --- /dev/null +++ b/distr/dddmp/exp/test3.script @@ -0,0 +1,69 @@ +# !/bin/sh +# +# BDD check: +# Load BDDs +# Make some operations +# Store BDDs +# +rm -f *.*.tmp +echo "---------------------------------------------------------------------------" +echo "----------------------- TESTING basic Load/Store ... ----------------------" +echo "---------------------------------------------------------------------------" +./../testdddmp << END +mi +50 +hlb +0or1.bdd +bl +0.bdd +0 +bl +1.bdd +1 +op +or +0 +1 +2 +bs +0or1.bdd.tmp +2 +bl +2.bdd +2 +bl +3.bdd +3 +op +and +2 +3 +4 +bs +2and3.bdd.tmp +4 +hlb +4xor5.bdd +bl +4.bdd +4 +bl +5.bdd +5 +op +xor +4 +5 +6 +bs +4xor5.bdd.tmp +6 +mq +quit +END +echo "----------------------------- ... RESULTS ... -----------------------------" +diff --brief 0or1.bdd 0or1.bdd.tmp +diff --brief 2and3.bdd 2and3.bdd.tmp +diff --brief 4xor5.bdd 4xor5.bdd.tmp +echo "-------------------------------- ... END ----------------------------------" +rm -f *.*.tmp diff --git a/distr/dddmp/exp/test4.out b/distr/dddmp/exp/test4.out new file mode 100644 index 0000000..367602d --- /dev/null +++ b/distr/dddmp/exp/test4.out @@ -0,0 +1,24 @@ +rm: No match. +--------------------------------------------------------------------------- +---------- TESTING Load/Store with sifting, varnames & varauxids ---------- +--------------------------------------------------------------------------- +#./../testdddmp Version 2.0.2 (use command help) +TestDddmp> Number of Variables: TestDddmp> File : TestDddmp> File : Which BDDs [0..19]: Loading 4.bdd ... +TestDddmp> File : TestDddmp> File : Which BDDs [0..19]: Storing 4a.bdd.tmp ... +TestDddmp> Reordering Approach (1..17): TestDddmp> File : Which BDDs [0..19]: Storing 4b.bdd.tmp ... +TestDddmp> Quitting CUDD Manager. +TestDddmp> End of test. +------------------------- ... END PHASE 1 ... ----------------------------- +#./../testdddmp Version 2.0.2 (use command help) +TestDddmp> Number of Variables: TestDddmp> File : TestDddmp> Variable matchmode: +Match IDs (1) +Match permIDs (2) +Match names (must have been loaded) (3) +Match auxids (must have been loaded) (4) +Match composeids (must have been loaded) (5) +Your choice: TestDddmp> File : Which BDDs [0..19]: Loading 4b.bdd.tmp ... +TestDddmp> File : TestDddmp> File : Which BDDs [0..19]: Storing 4c.bdd.tmp ... +TestDddmp> Quitting CUDD Manager. +TestDddmp> End of test. +----------------------------- ... RESULTS ... ----------------------------- +-------------------------------- ... END ---------------------------------- diff --git a/distr/dddmp/exp/test4.script b/distr/dddmp/exp/test4.script new file mode 100755 index 0000000..2c50992 --- /dev/null +++ b/distr/dddmp/exp/test4.script @@ -0,0 +1,56 @@ +# !/bin/sh +# +# BDD Check: +# Load BDDs +# Make some operations (with reordering) +# Store BDDs +# +rm -f *.*/tmp +echo "---------------------------------------------------------------------------" +echo "---------- TESTING Load/Store with sifting, varnames & varauxids ----------" +echo "---------------------------------------------------------------------------" +./../testdddmp << END1 +mi +50 +onl +varnames.ord +bl +4.bdd +4 +oil +varauxids.ord +bs +4a.bdd.tmp +4 +dr +4 +bs +4b.bdd.tmp +4 +mq +quit +END1 +echo "------------------------- ... END PHASE 1 ... -----------------------------" +./../testdddmp << END2 +mi +50 +onl +varnames.ord +slm +3 +bl +4b.bdd.tmp +4 +oil +varauxids.ord +bs +4c.bdd.tmp +4 +mq +quit +END2 +echo "----------------------------- ... RESULTS ... -----------------------------" +diff --brief 4.bdd 4a.bdd.tmp +diff --brief 4a.bdd.tmp 4c.bdd.tmp +echo "-------------------------------- ... END ----------------------------------" +rm -f *.*.tmp diff --git a/distr/dddmp/exp/test5.out b/distr/dddmp/exp/test5.out new file mode 100644 index 0000000..a883f51 --- /dev/null +++ b/distr/dddmp/exp/test5.out @@ -0,0 +1,28 @@ +rm: No match. +--------------------------------------------------------------------------- +--------------------- TESTING Load ADD and Store ADD ---------------------- +--------------------------------------------------------------------------- +#./../testdddmp Version 2.0.2 (use command help) +TestDddmp> Number of Variables: TestDddmp> File : TestDddmp> File : Which BDDs [0..19]: Loading 0.add ... +Load: +-01 2 +-1- 1 +TestDddmp> File : Which BDDs [0..19]: Storing 0.add.tmp ... +TestDddmp> Quitting CUDD Manager. +TestDddmp> Number of Variables: TestDddmp> File : TestDddmp> File : Which BDDs [0..19]: Loading 1.add ... +Load: +-0001--------------------------------------------- 1 +-0010--------------------------------------------- 2 +-0100--------------------------------------------- 1 +-0101--------------------------------------------- 2 +-0111--------------------------------------------- 1 +-1000--------------------------------------------- 2 +-1010--------------------------------------------- 1 +-1011--------------------------------------------- 2 +-1101--------------------------------------------- 1 +-1110--------------------------------------------- 2 +TestDddmp> File : Which BDDs [0..19]: Storing 1.add.tmp ... +TestDddmp> Quitting CUDD Manager. +TestDddmp> End of test. +----------------------------- ... RESULTS ... ----------------------------- +-------------------------------- ... END ---------------------------------- diff --git a/distr/dddmp/exp/test5.script b/distr/dddmp/exp/test5.script new file mode 100755 index 0000000..9676c94 --- /dev/null +++ b/distr/dddmp/exp/test5.script @@ -0,0 +1,42 @@ +# !/bin/sh +# +# Check ADD: +# Load an ADD +# Store the same ADD +# Compare the two +# (done twice on a small - 0.add - and a medium - 1.add - ADD). +# +rm -f *.tmp* +echo "---------------------------------------------------------------------------" +echo "--------------------- TESTING Load ADD and Store ADD ----------------------" +echo "---------------------------------------------------------------------------" +./../testdddmp << END1 +mi +3 +hlb +0.add +al +0.add +0 +as +0.add.tmp +0 +mq +mi +50 +hlb +1.add +al +1.add +1 +as +1.add.tmp +1 +mq +quit +END1 +echo "----------------------------- ... RESULTS ... -----------------------------" +diff --brief 0.add 0.add.tmp +diff --brief 1.add 1.add.tmp +echo "-------------------------------- ... END ----------------------------------" +rm -f *.*.tmp diff --git a/distr/dddmp/exp/test6.out b/distr/dddmp/exp/test6.out new file mode 100644 index 0000000..f10b484 --- /dev/null +++ b/distr/dddmp/exp/test6.out @@ -0,0 +1,31 @@ +rm: No match. +--------------------------------------------------------------------------- +--------------------- TESTING Load BDD and Store CNF ---------------------- +--------------------------------------------------------------------------- +#./../testdddmp Version 2.0.2 (use command help) +TestDddmp> Number of Variables: TestDddmp> File : TestDddmp> File : Which BDDs [0..19]: Loading 4.bdd ... +TestDddmp> File : Which BDDs [0..19]: Format (Node=N, Maxterm=M, Best=B) : Initial ID : Storing 4.cnf.tmp ... +Number of Clauses Stored = 108 +Number of New Variable Created Storing = 31 +TestDddmp> Quitting CUDD Manager. +TestDddmp> End of test. +--------------------- TESTING Load CNF and Store BDD ---------------------- +#./../testdddmp Version 2.0.2 (use command help) +TestDddmp> Number of Variables: TestDddmp> File : TestDddmp> File : Which BDDs [0..19]: Loading 4.cnf.tmp ... +TestDddmp> DD TYPE: DDDMP_CNF +Number of variables: 150 +Number of support variables: 15 +suppVarNames: V3 V8 V23 V24 V37 V39 DUMMY21 DUMMY22 DUMMY23 DUMMY36 DUMMY37 DUMMY38 DUMMY47 DUMMY48 DUMMY49 +orderedVarNames: V2 V3 V8 V9 V10 V12 V22 V23 V24 V37 V38 V39 V48 V49 V50 DUMMY15 DUMMY16 DUMMY17 DUMMY18 DUMMY19 DUMMY20 DUMMY21 DUMMY22 DUMMY23 DUMMY24 DUMMY25 DUMMY26 DUMMY27 DUMMY28 DUMMY29 DUMMY30 DUMMY31 DUMMY32 DUMMY33 DUMMY34 DUMMY35 DUMMY36 DUMMY37 DUMMY38 DUMMY39 DUMMY40 DUMMY41 DUMMY42 DUMMY43 DUMMY44 DUMMY45 DUMMY46 DUMMY47 DUMMY48 DUMMY49 DUMMY50 DUMMY51 DUMMY52 DUMMY53 DUMMY54 DUMMY55 DUMMY56 DUMMY57 DUMMY58 DUMMY59 DUMMY60 DUMMY61 DUMMY62 DUMMY63 DUMMY64 DUMMY65 DUMMY66 DUMMY67 DUMMY68 DUMMY69 DUMMY70 DUMMY71 DUMMY72 DUMMY73 DUMMY74 DUMMY75 DUMMY76 DUMMY77 DUMMY78 DUMMY79 DUMMY80 DUMMY81 DUMMY82 DUMMY83 DUMMY84 DUMMY85 DUMMY86 DUMMY87 DUMMY88 DUMMY89 DUMMY90 DUMMY91 DUMMY92 DUMMY93 DUMMY94 DUMMY95 DUMMY96 DUMMY97 DUMMY98 DUMMY99 DUMMY100 DUMMY101 DUMMY102 DUMMY103 DUMMY104 DUMMY105 DUMMY106 DUMMY107 DUMMY108 DUMMY109 DUMMY110 DUMMY111 DUMMY112 DUMMY113 DUMMY114 DUMMY115 DUMMY116 DUMMY117 DUMMY118 DUMMY119 DUMMY120 DUMMY121 DUMMY122 DUMMY123 DUMMY124 DUMMY125 DUMMY126 DUMMY127 DUMMY128 DUMMY129 DUMMY130 DUMMY131 DUMMY132 DUMMY133 DUMMY134 DUMMY135 DUMMY136 DUMMY137 DUMMY138 DUMMY139 DUMMY140 DUMMY141 DUMMY142 DUMMY143 DUMMY144 DUMMY145 DUMMY146 DUMMY147 DUMMY148 DUMMY149 +varIds: 1 2 7 8 9 11 21 22 23 36 37 38 47 48 49 +varIds for ALL Manager Variables: -1 1 2 -1 -1 -1 -1 7 8 9 -1 11 -1 -1 -1 -1 -1 -1 -1 -1 -1 21 22 23 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 36 37 38 -1 -1 -1 -1 -1 -1 -1 -1 47 48 49 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 +varComposeIds: 1 2 7 8 9 11 21 22 23 36 37 38 47 48 49 +varComposeIds for ALL Manager Variables: -1 1 2 -1 -1 -1 -1 7 8 9 -1 11 -1 -1 -1 -1 -1 -1 -1 -1 -1 21 22 23 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 36 37 38 -1 -1 -1 -1 -1 -1 -1 -1 47 48 49 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 +varAuxIds: 1 2 7 8 9 11 21 22 23 36 37 38 47 48 49 +varAuxIds for ALL Manager Variables: -1 1 2 -1 -1 -1 -1 7 8 9 -1 11 -1 -1 -1 -1 -1 -1 -1 -1 -1 21 22 23 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 36 37 38 -1 -1 -1 -1 -1 -1 -1 -1 47 48 49 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 +Number of roots: 1 +TestDddmp> File : Which BDDs [0..19]: Storing 4.bdd.tmp ... +TestDddmp> Quitting CUDD Manager. +TestDddmp> End of test. +----------------------------- ... RESULTS ... ----------------------------- +-------------------------------- ... END ---------------------------------- diff --git a/distr/dddmp/exp/test6.script b/distr/dddmp/exp/test6.script new file mode 100755 index 0000000..0b4295e --- /dev/null +++ b/distr/dddmp/exp/test6.script @@ -0,0 +1,50 @@ +# !/bin/sh +# +# Check CNF (short check - only NodeByNode method involved): +# Load BDDs +# Store corresponding CNF +# Read CNF +# Store corresponding BDD +# Compare original and final BDDs +# +rm -f *.tmp* +echo "---------------------------------------------------------------------------" +echo "--------------------- TESTING Load BDD and Store CNF ----------------------" +echo "---------------------------------------------------------------------------" +./../testdddmp << END1 +mi +150 +hlc +4.cnf.bis +bl +4.bdd +0 +cs +4.cnf.tmp +0 +N +100 +mq +quit +END1 +echo "--------------------- TESTING Load CNF and Store BDD ----------------------" +./../testdddmp << END2 +mi +150 +hlc +4.cnf.bis +cl +4.cnf.tmp +0 +hw +bs +4.bdd.tmp +0 +mq +quit +END2 +echo "----------------------------- ... RESULTS ... -----------------------------" +diff --brief 4.cnf.bis 4.cnf.tmp +diff --brief 4.bdd.bis1 4.bdd.tmp +echo "-------------------------------- ... END ----------------------------------" +rm -f *.*.tmp diff --git a/distr/dddmp/exp/test7.out b/distr/dddmp/exp/test7.out new file mode 100644 index 0000000..d5cd7d3 --- /dev/null +++ b/distr/dddmp/exp/test7.out @@ -0,0 +1,102 @@ +rm: No match. +--------------------------------------------------------------------------- +--------------------- TESTING Load BDD and Store CNF ---------------------- +--------------------------------------------------------------------------- +#./../testdddmp Version 2.0.2 (use command help) +TestDddmp> Number of Variables: TestDddmp> File : TestDddmp> File : Which BDDs [0..19]: Loading 4.bdd ... +TestDddmp> File : Which BDDs [0..19]: Format (Node=N, Maxterm=M, Best=B) : Initial ID : Storing 4.node1.tmp ... +Number of Clauses Stored = 108 +Number of New Variable Created Storing = 31 +TestDddmp> File : Which BDDs [0..19]: Format (Node=N, Maxterm=M, Best=B) : Initial ID : Storing 4.max1.tmp ... +Number of Clauses Stored = 103 +Number of New Variable Created Storing = 0 +TestDddmp> File : Which BDDs [0..19]: Format (Node=N, Maxterm=M, Best=B) : Max Number of Edges (Insert cut-point from there on) : Max BDD-Path Length (Insert cut-point from there on) : Initial ID : Storing 4.node2.tmp ... +Number of Clauses Stored = 114 +Number of New Variable Created Storing = 31 +TestDddmp> File : Which BDDs [0..19]: Format (Node=N, Maxterm=M, Best=B) : Max Number of Edges (Insert cut-point from there on) : Max BDD-Path Length (Insert cut-point from there on) : Initial ID : Storing 4.node3.tmp ... +Number of Clauses Stored = 108 +Number of New Variable Created Storing = 31 +TestDddmp> File : Which BDDs [0..19]: Format (Node=N, Maxterm=M, Best=B) : Max Number of Edges (Insert cut-point from there on) : Max BDD-Path Length (Insert cut-point from there on) : Initial ID : Storing 4.max2.tmp ... +Number of Clauses Stored = 103 +Number of New Variable Created Storing = 0 +TestDddmp> File : Which BDDs [0..19]: Format (Node=N, Maxterm=M, Best=B) : Max Number of Edges (Insert cut-point from there on) : Max BDD-Path Length (Insert cut-point from there on) : Initial ID : Storing 4.best1.tmp ... +Number of Clauses Stored = 53 +Number of New Variable Created Storing = 7 +TestDddmp> File : Which BDDs [0..19]: Format (Node=N, Maxterm=M, Best=B) : Max Number of Edges (Insert cut-point from there on) : Max BDD-Path Length (Insert cut-point from there on) : Initial ID : Storing 4.best2.tmp ... +Number of Clauses Stored = 69 +Number of New Variable Created Storing = 12 +TestDddmp> Quitting CUDD Manager. +TestDddmp> End of test. +--------------------------------------------------------------------------- +--------------------- TESTING Load CNF and Store BDD ---------------------- +--------------------------------------------------------------------------- +#./../testdddmp Version 2.0.2 (use command help) +TestDddmp> Number of Variables: TestDddmp> File : TestDddmp> File : Which BDDs [0..19]: Loading 4.node2.tmp ... +TestDddmp> DD TYPE: DDDMP_CNF +Number of variables: 150 +Number of support variables: 15 +suppVarNames: V3 V8 V23 V24 V37 V39 DUMMY21 DUMMY22 DUMMY23 DUMMY36 DUMMY37 DUMMY38 DUMMY47 DUMMY48 DUMMY49 +orderedVarNames: V2 V3 V8 V9 V10 V12 V22 V23 V24 V37 V38 V39 V48 V49 V50 DUMMY15 DUMMY16 DUMMY17 DUMMY18 DUMMY19 DUMMY20 DUMMY21 DUMMY22 DUMMY23 DUMMY24 DUMMY25 DUMMY26 DUMMY27 DUMMY28 DUMMY29 DUMMY30 DUMMY31 DUMMY32 DUMMY33 DUMMY34 DUMMY35 DUMMY36 DUMMY37 DUMMY38 DUMMY39 DUMMY40 DUMMY41 DUMMY42 DUMMY43 DUMMY44 DUMMY45 DUMMY46 DUMMY47 DUMMY48 DUMMY49 DUMMY50 DUMMY51 DUMMY52 DUMMY53 DUMMY54 DUMMY55 DUMMY56 DUMMY57 DUMMY58 DUMMY59 DUMMY60 DUMMY61 DUMMY62 DUMMY63 DUMMY64 DUMMY65 DUMMY66 DUMMY67 DUMMY68 DUMMY69 DUMMY70 DUMMY71 DUMMY72 DUMMY73 DUMMY74 DUMMY75 DUMMY76 DUMMY77 DUMMY78 DUMMY79 DUMMY80 DUMMY81 DUMMY82 DUMMY83 DUMMY84 DUMMY85 DUMMY86 DUMMY87 DUMMY88 DUMMY89 DUMMY90 DUMMY91 DUMMY92 DUMMY93 DUMMY94 DUMMY95 DUMMY96 DUMMY97 DUMMY98 DUMMY99 DUMMY100 DUMMY101 DUMMY102 DUMMY103 DUMMY104 DUMMY105 DUMMY106 DUMMY107 DUMMY108 DUMMY109 DUMMY110 DUMMY111 DUMMY112 DUMMY113 DUMMY114 DUMMY115 DUMMY116 DUMMY117 DUMMY118 DUMMY119 DUMMY120 DUMMY121 DUMMY122 DUMMY123 DUMMY124 DUMMY125 DUMMY126 DUMMY127 DUMMY128 DUMMY129 DUMMY130 DUMMY131 DUMMY132 DUMMY133 DUMMY134 DUMMY135 DUMMY136 DUMMY137 DUMMY138 DUMMY139 DUMMY140 DUMMY141 DUMMY142 DUMMY143 DUMMY144 DUMMY145 DUMMY146 DUMMY147 DUMMY148 DUMMY149 +varIds: 1 2 7 8 9 11 21 22 23 36 37 38 47 48 49 +varIds for ALL Manager Variables: -1 1 2 -1 -1 -1 -1 7 8 9 -1 11 -1 -1 -1 -1 -1 -1 -1 -1 -1 21 22 23 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 36 37 38 -1 -1 -1 -1 -1 -1 -1 -1 47 48 49 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 +varComposeIds: 1 2 7 8 9 11 21 22 23 36 37 38 47 48 49 +varComposeIds for ALL Manager Variables: -1 1 2 -1 -1 -1 -1 7 8 9 -1 11 -1 -1 -1 -1 -1 -1 -1 -1 -1 21 22 23 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 36 37 38 -1 -1 -1 -1 -1 -1 -1 -1 47 48 49 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 +varAuxIds: 1 2 7 8 9 11 21 22 23 36 37 38 47 48 49 +varAuxIds for ALL Manager Variables: -1 1 2 -1 -1 -1 -1 7 8 9 -1 11 -1 -1 -1 -1 -1 -1 -1 -1 -1 21 22 23 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 36 37 38 -1 -1 -1 -1 -1 -1 -1 -1 47 48 49 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 +Number of roots: 1 +TestDddmp> File : Which BDDs [0..19]: Storing 4.node2.bdd.tmp ... +TestDddmp> Quitting CUDD Manager. +TestDddmp> End of test. +#./../testdddmp Version 2.0.2 (use command help) +TestDddmp> Number of Variables: TestDddmp> File : TestDddmp> File : Which BDDs [0..19]: Loading 4.node3.tmp ... +TestDddmp> DD TYPE: DDDMP_CNF +Number of variables: 150 +Number of support variables: 15 +suppVarNames: V3 V8 V23 V24 V37 V39 DUMMY21 DUMMY22 DUMMY23 DUMMY36 DUMMY37 DUMMY38 DUMMY47 DUMMY48 DUMMY49 +orderedVarNames: V2 V3 V8 V9 V10 V12 V22 V23 V24 V37 V38 V39 V48 V49 V50 DUMMY15 DUMMY16 DUMMY17 DUMMY18 DUMMY19 DUMMY20 DUMMY21 DUMMY22 DUMMY23 DUMMY24 DUMMY25 DUMMY26 DUMMY27 DUMMY28 DUMMY29 DUMMY30 DUMMY31 DUMMY32 DUMMY33 DUMMY34 DUMMY35 DUMMY36 DUMMY37 DUMMY38 DUMMY39 DUMMY40 DUMMY41 DUMMY42 DUMMY43 DUMMY44 DUMMY45 DUMMY46 DUMMY47 DUMMY48 DUMMY49 DUMMY50 DUMMY51 DUMMY52 DUMMY53 DUMMY54 DUMMY55 DUMMY56 DUMMY57 DUMMY58 DUMMY59 DUMMY60 DUMMY61 DUMMY62 DUMMY63 DUMMY64 DUMMY65 DUMMY66 DUMMY67 DUMMY68 DUMMY69 DUMMY70 DUMMY71 DUMMY72 DUMMY73 DUMMY74 DUMMY75 DUMMY76 DUMMY77 DUMMY78 DUMMY79 DUMMY80 DUMMY81 DUMMY82 DUMMY83 DUMMY84 DUMMY85 DUMMY86 DUMMY87 DUMMY88 DUMMY89 DUMMY90 DUMMY91 DUMMY92 DUMMY93 DUMMY94 DUMMY95 DUMMY96 DUMMY97 DUMMY98 DUMMY99 DUMMY100 DUMMY101 DUMMY102 DUMMY103 DUMMY104 DUMMY105 DUMMY106 DUMMY107 DUMMY108 DUMMY109 DUMMY110 DUMMY111 DUMMY112 DUMMY113 DUMMY114 DUMMY115 DUMMY116 DUMMY117 DUMMY118 DUMMY119 DUMMY120 DUMMY121 DUMMY122 DUMMY123 DUMMY124 DUMMY125 DUMMY126 DUMMY127 DUMMY128 DUMMY129 DUMMY130 DUMMY131 DUMMY132 DUMMY133 DUMMY134 DUMMY135 DUMMY136 DUMMY137 DUMMY138 DUMMY139 DUMMY140 DUMMY141 DUMMY142 DUMMY143 DUMMY144 DUMMY145 DUMMY146 DUMMY147 DUMMY148 DUMMY149 +varIds: 1 2 7 8 9 11 21 22 23 36 37 38 47 48 49 +varIds for ALL Manager Variables: -1 1 2 -1 -1 -1 -1 7 8 9 -1 11 -1 -1 -1 -1 -1 -1 -1 -1 -1 21 22 23 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 36 37 38 -1 -1 -1 -1 -1 -1 -1 -1 47 48 49 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 +varComposeIds: 1 2 7 8 9 11 21 22 23 36 37 38 47 48 49 +varComposeIds for ALL Manager Variables: -1 1 2 -1 -1 -1 -1 7 8 9 -1 11 -1 -1 -1 -1 -1 -1 -1 -1 -1 21 22 23 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 36 37 38 -1 -1 -1 -1 -1 -1 -1 -1 47 48 49 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 +varAuxIds: 1 2 7 8 9 11 21 22 23 36 37 38 47 48 49 +varAuxIds for ALL Manager Variables: -1 1 2 -1 -1 -1 -1 7 8 9 -1 11 -1 -1 -1 -1 -1 -1 -1 -1 -1 21 22 23 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 36 37 38 -1 -1 -1 -1 -1 -1 -1 -1 47 48 49 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 +Number of roots: 1 +TestDddmp> File : Which BDDs [0..19]: Storing 4.node3.bdd.tmp ... +TestDddmp> Quitting CUDD Manager. +TestDddmp> End of test. +#./../testdddmp Version 2.0.2 (use command help) +TestDddmp> Number of Variables: TestDddmp> File : TestDddmp> File : Which BDDs [0..19]: Loading 4.best1.tmp ... +TestDddmp> DD TYPE: DDDMP_CNF +Number of variables: 150 +Number of support variables: 15 +suppVarNames: V3 V8 V23 V24 V37 V39 DUMMY21 DUMMY22 DUMMY23 DUMMY36 DUMMY37 DUMMY38 DUMMY47 DUMMY48 DUMMY49 +orderedVarNames: V2 V3 V8 V9 V10 V12 V22 V23 V24 V37 V38 V39 V48 V49 V50 DUMMY15 DUMMY16 DUMMY17 DUMMY18 DUMMY19 DUMMY20 DUMMY21 DUMMY22 DUMMY23 DUMMY24 DUMMY25 DUMMY26 DUMMY27 DUMMY28 DUMMY29 DUMMY30 DUMMY31 DUMMY32 DUMMY33 DUMMY34 DUMMY35 DUMMY36 DUMMY37 DUMMY38 DUMMY39 DUMMY40 DUMMY41 DUMMY42 DUMMY43 DUMMY44 DUMMY45 DUMMY46 DUMMY47 DUMMY48 DUMMY49 DUMMY50 DUMMY51 DUMMY52 DUMMY53 DUMMY54 DUMMY55 DUMMY56 DUMMY57 DUMMY58 DUMMY59 DUMMY60 DUMMY61 DUMMY62 DUMMY63 DUMMY64 DUMMY65 DUMMY66 DUMMY67 DUMMY68 DUMMY69 DUMMY70 DUMMY71 DUMMY72 DUMMY73 DUMMY74 DUMMY75 DUMMY76 DUMMY77 DUMMY78 DUMMY79 DUMMY80 DUMMY81 DUMMY82 DUMMY83 DUMMY84 DUMMY85 DUMMY86 DUMMY87 DUMMY88 DUMMY89 DUMMY90 DUMMY91 DUMMY92 DUMMY93 DUMMY94 DUMMY95 DUMMY96 DUMMY97 DUMMY98 DUMMY99 DUMMY100 DUMMY101 DUMMY102 DUMMY103 DUMMY104 DUMMY105 DUMMY106 DUMMY107 DUMMY108 DUMMY109 DUMMY110 DUMMY111 DUMMY112 DUMMY113 DUMMY114 DUMMY115 DUMMY116 DUMMY117 DUMMY118 DUMMY119 DUMMY120 DUMMY121 DUMMY122 DUMMY123 DUMMY124 DUMMY125 DUMMY126 DUMMY127 DUMMY128 DUMMY129 DUMMY130 DUMMY131 DUMMY132 DUMMY133 DUMMY134 DUMMY135 DUMMY136 DUMMY137 DUMMY138 DUMMY139 DUMMY140 DUMMY141 DUMMY142 DUMMY143 DUMMY144 DUMMY145 DUMMY146 DUMMY147 DUMMY148 DUMMY149 +varIds: 1 2 7 8 9 11 21 22 23 36 37 38 47 48 49 +varIds for ALL Manager Variables: -1 1 2 -1 -1 -1 -1 7 8 9 -1 11 -1 -1 -1 -1 -1 -1 -1 -1 -1 21 22 23 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 36 37 38 -1 -1 -1 -1 -1 -1 -1 -1 47 48 49 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 +varComposeIds: 1 2 7 8 9 11 21 22 23 36 37 38 47 48 49 +varComposeIds for ALL Manager Variables: -1 1 2 -1 -1 -1 -1 7 8 9 -1 11 -1 -1 -1 -1 -1 -1 -1 -1 -1 21 22 23 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 36 37 38 -1 -1 -1 -1 -1 -1 -1 -1 47 48 49 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 +varAuxIds: 1 2 7 8 9 11 21 22 23 36 37 38 47 48 49 +varAuxIds for ALL Manager Variables: -1 1 2 -1 -1 -1 -1 7 8 9 -1 11 -1 -1 -1 -1 -1 -1 -1 -1 -1 21 22 23 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 36 37 38 -1 -1 -1 -1 -1 -1 -1 -1 47 48 49 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 +Number of roots: 1 +TestDddmp> File : Which BDDs [0..19]: Storing 4.best1.bdd.tmp ... +TestDddmp> Quitting CUDD Manager. +TestDddmp> End of test. +#./../testdddmp Version 2.0.2 (use command help) +TestDddmp> Number of Variables: TestDddmp> File : TestDddmp> File : Which BDDs [0..19]: Loading 4.best2.tmp ... +TestDddmp> DD TYPE: DDDMP_CNF +Number of variables: 150 +Number of support variables: 15 +suppVarNames: V3 V8 V23 V24 V37 V39 DUMMY21 DUMMY22 DUMMY23 DUMMY36 DUMMY37 DUMMY38 DUMMY47 DUMMY48 DUMMY49 +orderedVarNames: V2 V3 V8 V9 V10 V12 V22 V23 V24 V37 V38 V39 V48 V49 V50 DUMMY15 DUMMY16 DUMMY17 DUMMY18 DUMMY19 DUMMY20 DUMMY21 DUMMY22 DUMMY23 DUMMY24 DUMMY25 DUMMY26 DUMMY27 DUMMY28 DUMMY29 DUMMY30 DUMMY31 DUMMY32 DUMMY33 DUMMY34 DUMMY35 DUMMY36 DUMMY37 DUMMY38 DUMMY39 DUMMY40 DUMMY41 DUMMY42 DUMMY43 DUMMY44 DUMMY45 DUMMY46 DUMMY47 DUMMY48 DUMMY49 DUMMY50 DUMMY51 DUMMY52 DUMMY53 DUMMY54 DUMMY55 DUMMY56 DUMMY57 DUMMY58 DUMMY59 DUMMY60 DUMMY61 DUMMY62 DUMMY63 DUMMY64 DUMMY65 DUMMY66 DUMMY67 DUMMY68 DUMMY69 DUMMY70 DUMMY71 DUMMY72 DUMMY73 DUMMY74 DUMMY75 DUMMY76 DUMMY77 DUMMY78 DUMMY79 DUMMY80 DUMMY81 DUMMY82 DUMMY83 DUMMY84 DUMMY85 DUMMY86 DUMMY87 DUMMY88 DUMMY89 DUMMY90 DUMMY91 DUMMY92 DUMMY93 DUMMY94 DUMMY95 DUMMY96 DUMMY97 DUMMY98 DUMMY99 DUMMY100 DUMMY101 DUMMY102 DUMMY103 DUMMY104 DUMMY105 DUMMY106 DUMMY107 DUMMY108 DUMMY109 DUMMY110 DUMMY111 DUMMY112 DUMMY113 DUMMY114 DUMMY115 DUMMY116 DUMMY117 DUMMY118 DUMMY119 DUMMY120 DUMMY121 DUMMY122 DUMMY123 DUMMY124 DUMMY125 DUMMY126 DUMMY127 DUMMY128 DUMMY129 DUMMY130 DUMMY131 DUMMY132 DUMMY133 DUMMY134 DUMMY135 DUMMY136 DUMMY137 DUMMY138 DUMMY139 DUMMY140 DUMMY141 DUMMY142 DUMMY143 DUMMY144 DUMMY145 DUMMY146 DUMMY147 DUMMY148 DUMMY149 +varIds: 1 2 7 8 9 11 21 22 23 36 37 38 47 48 49 +varIds for ALL Manager Variables: -1 1 2 -1 -1 -1 -1 7 8 9 -1 11 -1 -1 -1 -1 -1 -1 -1 -1 -1 21 22 23 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 36 37 38 -1 -1 -1 -1 -1 -1 -1 -1 47 48 49 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 +varComposeIds: 1 2 7 8 9 11 21 22 23 36 37 38 47 48 49 +varComposeIds for ALL Manager Variables: -1 1 2 -1 -1 -1 -1 7 8 9 -1 11 -1 -1 -1 -1 -1 -1 -1 -1 -1 21 22 23 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 36 37 38 -1 -1 -1 -1 -1 -1 -1 -1 47 48 49 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 +varAuxIds: 1 2 7 8 9 11 21 22 23 36 37 38 47 48 49 +varAuxIds for ALL Manager Variables: -1 1 2 -1 -1 -1 -1 7 8 9 -1 11 -1 -1 -1 -1 -1 -1 -1 -1 -1 21 22 23 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 36 37 38 -1 -1 -1 -1 -1 -1 -1 -1 47 48 49 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 +Number of roots: 1 +TestDddmp> File : Which BDDs [0..19]: Storing 4.best2.bdd.tmp ... +TestDddmp> Quitting CUDD Manager. +TestDddmp> End of test. +----------------------------- ... RESULTS ... ----------------------------- +-------------------------------- ... END ---------------------------------- diff --git a/distr/dddmp/exp/test7.script b/distr/dddmp/exp/test7.script new file mode 100755 index 0000000..dcef83f --- /dev/null +++ b/distr/dddmp/exp/test7.script @@ -0,0 +1,150 @@ +# !/bin/sh +# +# Check CNF (long check - all methods involved): +# Load BDDs +# Store corresponding CNF in different format: +# NodeByNode method -> file 4.node1.tmp +# MaxtermByMaxterm -> file 4.max1.tmp +# Best with different options: +# MaxEdge=-1 MaxPath= 0 -> similar to NodeByNode -> file 4.node2.tmp +# MaxEdge= 0 MaxPath=-1 -> similar to NodeByNode -> file 4.node3.tmp +# MaxEdge=-1 MaxPath=-1 -> = MaxtermByMaxterm -> file 4.max2.tmp +# MaxEdge= 1 MaxPath=-1 -> = Original Best -> file 4.best1.tmp +# MaxEdge= 1 MaxPath= 2 -> = Original Best, With Path Shorter than 3 +# file 4.best2.tmp +# Read CNF +# Store corresponding BDD +# Compare original and final BDDs +# +rm -f *.tmp* +echo "---------------------------------------------------------------------------" +echo "--------------------- TESTING Load BDD and Store CNF ----------------------" +echo "---------------------------------------------------------------------------" +./../testdddmp << END1 +mi +150 +hlc +4.cnf.bis +bl +4.bdd +0 +cs +4.node1.tmp +0 +N +100 +cs +4.max1.tmp +0 +M +100 +cs +4.node2.tmp +0 +B +-1 +0 +100 +cs +4.node3.tmp +0 +B +0 +-1 +100 +cs +4.max2.tmp +0 +B +-1 +-1 +100 +cs +4.best1.tmp +0 +B +1 +-1 +100 +cs +4.best2.tmp +0 +B +1 +2 +100 +mq +quit +END1 +echo "---------------------------------------------------------------------------" +echo "--------------------- TESTING Load CNF and Store BDD ----------------------" +echo "---------------------------------------------------------------------------" +./../testdddmp << END2 +mi +150 +hlc +4.node2.tmp +cl +4.node2.tmp +0 +hw +bs +4.node2.bdd.tmp +0 +mq +quit +END2 +./../testdddmp << END3 +mi +150 +hlc +4.node3.tmp +cl +4.node3.tmp +0 +hw +bs +4.node3.bdd.tmp +0 +mq +quit +END3 +./../testdddmp << END4 +mi +150 +hlc +4.best1.tmp +cl +4.best1.tmp +0 +hw +bs +4.best1.bdd.tmp +0 +mq +quit +END4 +./../testdddmp << END5 +mi +150 +hlc +4.best2.tmp +cl +4.best2.tmp +0 +hw +bs +4.best2.bdd.tmp +0 +mq +quit +END5 +echo "----------------------------- ... RESULTS ... -----------------------------" +diff --brief 4.max1 4.max1.tmp +diff --brief 4.max2 4.max2.tmp +diff --brief 4.bdd.bis1 4.node2.bdd.tmp +diff --brief 4.bdd.bis2 4.node3.bdd.tmp +diff --brief 4.bdd.bis3 4.best1.bdd.tmp +diff --brief 4.bdd.bis4 4.best2.bdd.tmp +echo "-------------------------------- ... END ----------------------------------" +rm -f *.tmp* diff --git a/distr/dddmp/exp/varauxids.ord b/distr/dddmp/exp/varauxids.ord new file mode 100644 index 0000000..9dc8856 --- /dev/null +++ b/distr/dddmp/exp/varauxids.ord @@ -0,0 +1,50 @@ +1 +3 +5 +7 +9 +11 +13 +15 +17 +19 +21 +23 +25 +27 +29 +31 +33 +35 +37 +39 +41 +43 +45 +47 +49 +51 +53 +55 +57 +59 +61 +63 +65 +67 +69 +71 +73 +75 +77 +79 +81 +83 +85 +87 +89 +91 +93 +95 +97 +99 diff --git a/distr/dddmp/exp/varnames.ord b/distr/dddmp/exp/varnames.ord new file mode 100644 index 0000000..541f21e --- /dev/null +++ b/distr/dddmp/exp/varnames.ord @@ -0,0 +1,50 @@ +V1 +V2 +V3 +V4 +V5 +V6 +V7 +V8 +V9 +V10 +V11 +V12 +V13 +V14 +V15 +V16 +V17 +V18 +V19 +V20 +V21 +V22 +V23 +V24 +V25 +V26 +V27 +V28 +V29 +V30 +V31 +V32 +V33 +V34 +V35 +V36 +V37 +V38 +V39 +V40 +V41 +V42 +V43 +V44 +V45 +V46 +V47 +V48 +V49 +V50 diff --git a/distr/dddmp/exp/zero.bdd b/distr/dddmp/exp/zero.bdd new file mode 100644 index 0000000..4c229f7 --- /dev/null +++ b/distr/dddmp/exp/zero.bdd @@ -0,0 +1,13 @@ +.ver DDDMP-1.0 +.mode A +.varinfo 0 +.nnodes 1 +.nvars 100 +.nsuppvars 0 +.ids +.permids +.nroots 1 +.rootids -1 +.nodes +1 T 1 0 0 +.end diff --git a/distr/dddmp/testdddmp.c b/distr/dddmp/testdddmp.c new file mode 100644 index 0000000..6879dcc --- /dev/null +++ b/distr/dddmp/testdddmp.c @@ -0,0 +1,2279 @@ +/**CFile********************************************************************** + + FileName [testdddmp.c] + + PackageName [dddmp] + + Synopsis [A simple test function for Dddmp package] + + Description [This program constitutes a simple test program + for the dddmp library (version 2.0). + A simple interactive command selection allow the users to perform the + main operation on BDDs, ADDs, and CNF, such as loading and storing. + It can work also as a BDD calculators. + ] + + Author [Gianpiero Cabodi and Stefano Quer] + + Copyright [ + Copyright (c) 2004 by Politecnico di Torino. + All Rights Reserved. This software is for educational purposes only. + Permission is given to academic institutions to use, copy, and modify + this software and its documentation provided that this introductory + message is not removed, that this software and its documentation is + used for the institutions' internal research and educational purposes, + and that no monies are exchanged. No guarantee is expressed or implied + by the distribution of this code. + Send bug-reports and/or questions to: + {gianpiero.cabodi,stefano.quer}@polito.it. + ] + +******************************************************************************/ + +#include +#include +#include "dddmpInt.h" + +/*---------------------------------------------------------------------------*/ +/* Constant declarations */ +/*---------------------------------------------------------------------------*/ + +#define DDDMPTEST_MAX_FILENAME_LENGTH 256 +#define DDDMPTEST_MAX_STRING_LENGTH 80 +#define DDDMPTEST_MAX_OPERAND 20 +#define DDDMPTEST_MAX_VARIABLE 50 +#define DDDMP_MAX_BDDARRAY_LEN 1000 + +/**Enum************************************************************************ + + Synopsis [Message type for output messages] + + Description [Type supported by the output function to print-out + the proper message. + ] + +******************************************************************************/ + +typedef enum { + /* Int Messages */ + DDDMP_MESSAGE_MANAGER_VAR, + DDDMP_MESSAGE_BDD, + DDDMP_MESSAGE_BDD_ARRAY, + DDDMP_MESSAGE_SOURCE1, + DDDMP_MESSAGE_SOURCE2, + DDDMP_MESSAGE_DESTINATION, + DDDMP_MESSAGE_CUBE, + DDDMP_MESSAGE_INDEX, + DDDMP_MESSAGE_I_ID, + DDDMP_MESSAGE_EDGE_MAX, + DDDMP_MESSAGE_LENGHT_MAX, + DDDMP_MESSAGE_REORDERING, + /* String Messages */ + DDDMP_MESSAGE_PROMPT, + DDDMP_MESSAGE_FILE, + DDDMP_MESSAGE_OP, + DDDMP_MESSAGE_FORMAT +} Dddmp_MessageType; + +#if !defined(RAND_MAX) && defined(sun) && defined(sparc) +#define RAND_MAX 2147483647 +#endif + +/*---------------------------------------------------------------------------*/ +/* Stucture declarations */ +/*---------------------------------------------------------------------------*/ + +typedef struct dddmpVarInfo { + /* + * Local Information + */ + + int nDdVars; /* Local Manager Number of Variables */ + char **rootNames; /* Root Names */ + + /* + * Header File Information + */ + + Dddmp_DecompType ddType; + + int nVars; /* File Manager Number of Variables */ + int nSuppVars; /* File Structure Number of Variables */ + + int varNamesFlagUpdate; /* 0 to NOT Update */ + char **suppVarNames; + char **orderedVarNames; + + int varIdsFlagUpdate; /* 0 to NOT Update */ + int *varIds; /* File ids - nSuppVars size */ + int *varIdsAll; /* ALL ids - nVars size */ + + int varComposeIdsFlagUpdate; /* 0 to NOT Update */ + int *varComposeIds; /* File permids - nSuppVars size */ + int *varComposeIdsAll; /* ALL permids - nVars size */ + + int varAuxIdsFlagUpdate; /* 0 to NOT Update */ + int *varAuxIds; /* File auxids - nSuppVars size */ + int *varAuxIdsAll; /* ALL auxids - nVars size */ + + int nRoots; +} dddmpVarInfo_t; + +/*---------------------------------------------------------------------------*/ +/* Type declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Variable declarations */ +/*---------------------------------------------------------------------------*/ + +Dddmp_RootMatchType rootmatchmode; +Dddmp_VarMatchType varmatchmode; +Dddmp_VarInfoType varoutinfo; +char varname[DDDMPTEST_MAX_STRING_LENGTH]; + +/*---------------------------------------------------------------------------*/ +/* Macro declarations */ +/*---------------------------------------------------------------------------*/ + +/**AutomaticStart*************************************************************/ + +/*---------------------------------------------------------------------------*/ +/* Static function prototypes */ +/*---------------------------------------------------------------------------*/ + +static DdManager *ManagerInit (dddmpVarInfo_t *varInfo); +static void ManagerQuit (DdManager **ddMgr, dddmpVarInfo_t *varInfo); +static int OneCreate(DdManager *ddMgr, DdNode **operandBdd); +static int BddZeroCreate(DdManager *ddMgr, DdNode **operandBdd); +static int LeafCreate(DdManager *ddMgr, DdNode **operandBdd); +static int BddCreate(DdManager *ddMgr, DdNode **operandBdd); +static int A2B(void); +static int B2A(void); +static int HeaderLoadBdd(dddmpVarInfo_t *varInfo); +static int HeaderLoadCnf(dddmpVarInfo_t *varInfo); +static int HeaderWrite(dddmpVarInfo_t *varInfo); +static int Help(void); +static int OrderNamesLoad(dddmpVarInfo_t *varInfo); +static int IntArrayLoad(dddmpVarInfo_t *varInfo, const char *mode); +static int BddLoad(DdManager *ddMgr, DdNode **operandBdd, dddmpVarInfo_t *varInfo); +static int BddArrayLoad(DdManager *ddMgr, DdNode ***operandBddArray, int *operandBddArraySize, dddmpVarInfo_t *varInfo); +static int AddLoad(DdManager *ddMgr, DdNode **operandBdd, dddmpVarInfo_t *varInfo); +static int AddArrayLoad(DdManager *ddMgr, DdNode ***operandBddArray, int *operandBddArraySize, dddmpVarInfo_t *varInfo); +static int BddLoadCnf(DdManager *ddMgr, DdNode **operandBdd, dddmpVarInfo_t *varInfo); +static int BddArrayLoadCnf(DdManager *ddMgr, DdNode ***operandBddArray, int *operandBddArraySize, dddmpVarInfo_t *varInfo); +static int Operation(DdManager *ddMgr, DdNode **operandBdd); +static int BddStore(DdManager *ddMgr, DdNode **operandBdd, dddmpVarInfo_t *varInfo); +static int BddArrayStore(DdManager *ddMgr, DdNode ***operandBddArray, int *operandBddArraySize, dddmpVarInfo_t *varInfo); +static int AddStore(DdManager *ddMgr, DdNode **operandBdd, dddmpVarInfo_t *varInfo); +static int AddArrayStore(DdManager *ddMgr, DdNode ***operandBddArray, int *operandBddArraySize, dddmpVarInfo_t *varInfo); +static int BddStoreCnf(DdManager *ddMgr, DdNode **operandBdd, dddmpVarInfo_t *varInfo); +static int BddArrayStoreCnf(DdManager *ddMgr, DdNode ***operandBddArray, int *operandBddArraySize, dddmpVarInfo_t *varInfo); +static int DynamicReordering(DdManager *ddMgr); +static int SetLoadMatchmode(); +static int CompleteInfoStruct(Dddmp_DecompType ddType, int nVars, int nSuppVars, char **suppVarNames, char **orderedVarNames, int *varIds, int *varComposeIds, int *varAuxIds, int nRoots, dddmpVarInfo_t *varInfo); +static void ReadInt(Dddmp_MessageType message, int *i); +static void ReadString(Dddmp_MessageType message, char string[]); + +/**AutomaticEnd***************************************************************/ + +int +main( + int argc, + char **argv + ) +{ + DdManager *ddMgr = NULL; + DdNode **operandBdd = NULL; + DdNode ***operandBddArray = NULL; + int *operandBddArraySize = NULL; + char *row = NULL; + dddmpVarInfo_t varInfo; + int i; + + /*--------------------- Echo command line and arguments -------------------*/ + + fprintf (stdout, "#"); + for (i=0; i1) { + Help(); + } + + /*-------------------------- Init Array of BDDs ---------------------------*/ + + rootmatchmode = DDDMP_ROOT_MATCHLIST; +#if 1 + varmatchmode = DDDMP_VAR_MATCHIDS; +#else + varmatchmode = DDDMP_VAR_MATCHNAMES; +#endif + varoutinfo = DDDMP_VARIDS; + + row = DDDMP_ALLOC (char, DDDMPTEST_MAX_STRING_LENGTH); + Dddmp_CheckAndReturn (row==NULL, "Allocation error."); + + operandBdd = DDDMP_ALLOC (DdNode *, DDDMPTEST_MAX_OPERAND); + Dddmp_CheckAndReturn (operandBdd==NULL, "Allocation error."); + + operandBddArray = DDDMP_ALLOC (DdNode **, DDDMPTEST_MAX_OPERAND); + Dddmp_CheckAndReturn (operandBddArray==NULL, "Allocation error."); + + operandBddArraySize = DDDMP_ALLOC (int, DDDMPTEST_MAX_OPERAND); + Dddmp_CheckAndReturn (operandBddArraySize==NULL, "Allocation error."); + + for (i=0; inDdVars = nVars; + + varInfo->rootNames = NULL; + varInfo->ddType = DDDMP_NONE; + varInfo->nVars = (-1); + varInfo->nSuppVars = (-1); + varInfo->varNamesFlagUpdate = 1; + varInfo->suppVarNames = NULL; + varInfo->orderedVarNames = NULL; + varInfo->varIdsFlagUpdate = 1; + varInfo->varIds = NULL; + varInfo->varIdsAll = NULL; + varInfo->varComposeIdsFlagUpdate = 1; + varInfo->varComposeIds = NULL; + varInfo->varComposeIdsAll = NULL; + varInfo->varAuxIdsFlagUpdate = 1; + varInfo->varAuxIds = NULL; + varInfo->varAuxIdsAll = NULL; + varInfo->nRoots = (-1); + + /*------------------------------ Init DD Manager --------------------------*/ + + ddMgr = Cudd_Init (nVars, 0, CUDD_UNIQUE_SLOTS, + CUDD_CACHE_SLOTS, 0); + + Dddmp_CheckAndReturn (ddMgr==NULL, "DdManager NOT inizializated."); + + return (ddMgr); +} + +/**Function******************************************************************** + + Synopsis [Quit a CUDD Manager.] + + Description [Quit a CUDD Manager.] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ + +static void +ManagerQuit ( + DdManager **ddMgrPtr /* IN: CUDD Manager */, + dddmpVarInfo_t *varInfo /* IN: Internal Manager */ + ) +{ + if (*ddMgrPtr == NULL) { + return; + } + + fprintf (stdout, "Quitting CUDD Manager.\n"); + Cudd_Quit (*ddMgrPtr); + *ddMgrPtr = NULL; + + DddmpStrArrayFree (varInfo->rootNames, varInfo->nRoots); + DddmpStrArrayFree (varInfo->suppVarNames, varInfo->nSuppVars); + DddmpStrArrayFree (varInfo->orderedVarNames, varInfo->nVars); + DDDMP_FREE (varInfo->varIds); + DDDMP_FREE (varInfo->varIdsAll); + DDDMP_FREE (varInfo->varComposeIds); + DDDMP_FREE (varInfo->varComposeIdsAll); + DDDMP_FREE (varInfo->varAuxIds); + DDDMP_FREE (varInfo->varAuxIdsAll); + + varInfo->nDdVars = (-1); + varInfo->rootNames = NULL; + varInfo->ddType = DDDMP_NONE; + varInfo->nVars = (-1); + varInfo->nSuppVars = (-1); + varInfo->varNamesFlagUpdate = 1; + varInfo->suppVarNames = NULL; + varInfo->orderedVarNames = NULL; + varInfo->varIdsFlagUpdate = 1; + varInfo->varIds = NULL; + varInfo->varIdsAll = NULL; + varInfo->varComposeIdsFlagUpdate = 1; + varInfo->varComposeIds = NULL; + varInfo->varComposeIdsAll = NULL; + varInfo->varAuxIdsFlagUpdate = 1; + varInfo->varAuxIds = NULL; + varInfo->varAuxIdsAll = NULL; + varInfo->nRoots = (-1); + + return; +} + +/**Function******************************************************************** + + Synopsis [Create a One-BDD Leaf.] + + Description [Create a One-BDD Leaf.] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ + +static int +OneCreate( + DdManager *ddMgr /* IN: CUDD Manager */, + DdNode **operandBdd /* In/OUT: Array of operand */ + ) +{ + int i; + + /*------------------------ Read Operation Operands ------------------------*/ + + ReadInt (DDDMP_MESSAGE_BDD, &i); + + operandBdd[i] = Cudd_ReadOne (ddMgr); + + return (DDDMP_SUCCESS); +} + +/**Function******************************************************************** + + Synopsis [Create a Zero-BDD Leaf.] + + Description [Create a Zero-BDD Leaf.] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ + +static int +BddZeroCreate( + DdManager *ddMgr /* IN: CUDD Manager */, + DdNode **operandBdd /* IN/OUT: array of operand */ + ) +{ + int i; + DdNode *one = NULL; + + /*------------------------ Read Operation Operands ------------------------*/ + + ReadInt (DDDMP_MESSAGE_BDD, &i); + + one = Cudd_ReadOne(ddMgr); + operandBdd[i] = Cudd_Not(one); + + return (DDDMP_SUCCESS); +} + +/**Function******************************************************************** + + Synopsis [Create a One-Node BDD.] + + Description [Create a One-Node BDD.] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ + +static int +LeafCreate( + DdManager *ddMgr /* IN: CUDD Manager */, + DdNode **operandBdd /* IN/OUT: Array of operandBdd */ + ) +{ + int i, j; + DdNode *f = NULL; + + /*------------------------ Read Operation Operands ------------------------*/ + + ReadInt (DDDMP_MESSAGE_BDD, &i); + ReadInt (DDDMP_MESSAGE_INDEX, &j); + + f = Cudd_bddIthVar (ddMgr, j); + Cudd_Ref(f); + operandBdd[i] = f; + + return (DDDMP_SUCCESS); +} + +/**Function******************************************************************** + + Synopsis [Create a BDD.] + + Description [Create a BDD: Variable index and number of cubes selection.] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ + +static int +BddCreate ( + DdManager *ddMgr /* IN: CUDD Manager */, + DdNode **operandBdd /* array of operandBdd */ + ) +{ + DdNode **vet, *f, *g, *h; + int nb, nv, vi0, vi1, nc, i, j; + char row[DDDMPTEST_MAX_FILENAME_LENGTH]; + + /*------------------------ Read Operation Operands ------------------------*/ + + ReadInt (DDDMP_MESSAGE_BDD, &nb); + + fprintf (stdout, "Variables Index [n-m] (m-n = number of variables): "); + fgets (row, DDDMPTEST_MAX_STRING_LENGTH, stdin); + sscanf (row, "%d-%d", &vi0, &vi1); + nv = vi1-vi0+1; + + ReadInt (DDDMP_MESSAGE_CUBE, &nc); + + /* Leaf Creation */ + vet = DDDMP_ALLOC (DdNode *, nv); + for (i=0; i 0.5 ) { + h = Cudd_bddAnd (ddMgr, g, vet[j]); + } else { + h = Cudd_bddAnd (ddMgr, g, Cudd_Not (vet[j])); + } + Cudd_Ref (h); + Cudd_RecursiveDeref (ddMgr, g); + g = h; + } + h = Cudd_bddOr (ddMgr, f, g); + Cudd_Ref (h); + Cudd_RecursiveDeref (ddMgr, f); + Cudd_RecursiveDeref (ddMgr, g); + f = h; + } + + operandBdd[nb] = f; + + return (DDDMP_SUCCESS); +} + +/**Function******************************************************************** + + Synopsis [Transform a BDD from the ASCII to the Binary format].] + + Description [Input and Output file selection.] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ + +static int +A2B( + void +) +{ + fprintf (stderr, "Not yet Implemented!!!\n"); + + return (DDDMP_FAILURE); +} + +/**Function******************************************************************** + + Synopsis [Transform a BDD from the Binary to the ASCII format].] + + Description [Input and Output file selection.] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ + +static int +B2A( + void +) +{ + fprintf (stderr, "Not yet Implemented!!!\n"); + + return (DDDMP_FAILURE); +} + +/**Function******************************************************************** + + Synopsis [Read the Header of a file containing a BDD.] + + Description [File name Selection.] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ + +static int +HeaderLoadBdd ( + dddmpVarInfo_t *varInfo /* IN/OUT: Variable Information */ + ) +{ + Dddmp_DecompType ddType; + int retValue, nRoots, nVars, nSuppVars; + int *tmpVarIds = NULL; + int *tmpVarAuxIds = NULL; + int *tmpVarComposeIds = NULL; + char **tmpOrderedVarNames = NULL; + char **tmpSuppVarNames = NULL; + char fileName[DDDMPTEST_MAX_FILENAME_LENGTH]; + + /*------------------------ Read Operation Operands ------------------------*/ + + ReadString (DDDMP_MESSAGE_FILE, fileName); + + retValue = Dddmp_cuddHeaderLoad (&ddType, &nVars, &nSuppVars, + &tmpSuppVarNames, &tmpOrderedVarNames, &tmpVarIds, &tmpVarComposeIds, + &tmpVarAuxIds, &nRoots, fileName, NULL); + + if (retValue == DDDMP_FAILURE) { + return (DDDMP_FAILURE); + } + + /*---------------------------- Tail Operations ----------------------------*/ + + CompleteInfoStruct (ddType, nVars, nSuppVars, + tmpSuppVarNames, tmpOrderedVarNames, tmpVarIds, tmpVarComposeIds, + tmpVarAuxIds, nRoots, varInfo); + + return (DDDMP_SUCCESS); +} + +/**Function******************************************************************** + + Synopsis [Read the Header of a file containing a CNF formula.] + + Description [File name Selection.] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ + +static int +HeaderLoadCnf ( + dddmpVarInfo_t *varInfo /* IN/OUT: Variable Information */ + ) +{ + int retValue, nRoots, nVars, nSuppVars; + int *tmpVarIds = NULL; + int *tmpVarComposeIds = NULL; + int *tmpVarAuxIds = NULL; + char **tmpOrderedVarNames = NULL; + char **tmpSuppVarNames = NULL; + char fileName[DDDMPTEST_MAX_FILENAME_LENGTH]; + + /*------------------------ Read Operation Operands ------------------------*/ + + ReadString (DDDMP_MESSAGE_FILE, fileName); + + retValue = Dddmp_cuddHeaderLoadCnf (&nVars, &nSuppVars, + &tmpSuppVarNames, &tmpOrderedVarNames, &tmpVarIds, &tmpVarComposeIds, + &tmpVarAuxIds, &nRoots, fileName, NULL); + + if (retValue == DDDMP_FAILURE) { + return (DDDMP_FAILURE); + } + + /*---------------------------- Tail Operations ----------------------------*/ + + CompleteInfoStruct (DDDMP_CNF, nVars, nSuppVars, + tmpSuppVarNames, tmpOrderedVarNames, tmpVarIds, tmpVarComposeIds, + tmpVarAuxIds, nRoots, varInfo); + + return (DDDMP_SUCCESS); +} + +/**Function******************************************************************** + + Synopsis [Read the Header of a filke containing a BDD.] + + Description [File name Selection.] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ + +static int +HeaderWrite( + dddmpVarInfo_t *varInfo /* IN/OUT: Variable Information */ + ) +{ + int i; + + switch (varInfo->ddType) { + case DDDMP_BDD: + fprintf (stdout, "DD TYPE: DDDMP_BDD\n"); + break; + case DDDMP_ADD: + fprintf (stdout, "DD TYPE: DDDMP_ADD\n"); + break; + case DDDMP_CNF: + fprintf (stdout, "DD TYPE: DDDMP_CNF\n"); + break; + case DDDMP_NONE: + fprintf (stdout, "DD TYPE: NONE - Error\n"); + break; + } + + fprintf (stdout, "Number of variables: %d\n", varInfo->nVars); + fprintf (stdout, "Number of support variables: %d\n", varInfo->nSuppVars); + + if (varInfo->suppVarNames != NULL) { + fprintf (stdout, "suppVarNames: "); + for (i=0; inSuppVars; i++) { + if (varInfo->suppVarNames[i] != NULL) { + fprintf (stdout, "%s ", varInfo->suppVarNames[i]); + } + } + fprintf (stdout, "\n"); + } + + if (varInfo->orderedVarNames != NULL) { + fprintf (stdout, "orderedVarNames: "); + for (i=0; inVars; i++) { + if (varInfo->orderedVarNames[i] != NULL) { + fprintf (stdout, "%s ", varInfo->orderedVarNames[i]); + } + } + fprintf (stdout, "\n"); + } + + if (varInfo->varIds != NULL) { + fprintf (stdout, "varIds: "); + for (i=0; inSuppVars; i++) { + fprintf (stdout, "%d ", varInfo->varIds[i]); + } + fprintf (stdout, "\n"); + } + + if (varInfo->varIdsAll != NULL) { + fprintf (stdout, "varIds for ALL Manager Variables: "); + for (i=0; inVars; i++) { + fprintf (stdout, "%d ", varInfo->varIdsAll[i]); + } + fprintf (stdout, "\n"); + } + + if (varInfo->varComposeIds != NULL) { + fprintf (stdout, "varComposeIds: "); + for (i=0; inSuppVars; i++) { + fprintf (stdout, "%d ", varInfo->varComposeIds[i]); + } + fprintf (stdout, "\n"); + } + + if (varInfo->varComposeIdsAll != NULL) { + fprintf (stdout, "varComposeIds for ALL Manager Variables: "); + for (i=0; inVars; i++) { + fprintf (stdout, "%d ", varInfo->varComposeIdsAll[i]); + } + fprintf (stdout, "\n"); + } + + if (varInfo->varAuxIds != NULL) { + fprintf (stdout, "varAuxIds: "); + for (i=0; inSuppVars; i++) { + fprintf (stdout, "%d ", varInfo->varAuxIds[i]); + } + fprintf (stdout, "\n"); + } + + if (varInfo->varAuxIdsAll != NULL) { + fprintf (stdout, "varAuxIds for ALL Manager Variables: "); + for (i=0; inVars; i++) { + fprintf (stdout, "%d ", varInfo->varAuxIdsAll[i]); + } + fprintf (stdout, "\n"); + } + + fprintf (stdout, "Number of roots: %d\n", varInfo->nRoots); + + fflush (stdout); + + return (DDDMP_SUCCESS); +} + +/**Function******************************************************************** + + Synopsis [Print the Help messages.] + + Description [Print the Help messages.] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ + +static int +Help( + void + ) +{ + fprintf (stdout, "Commands:\n"); + fprintf (stdout, "MAIN\n"); + + fprintf (stdout, "\thelp : Print this set of messages.\n"); + fprintf (stdout, "\tquit : Quit the test program.\n"); + + fprintf (stdout, "MANAGER OPERATIONs\n"); + + fprintf (stdout, + "\thmi : Manager Init (To do BEFORE any BDD/ADD operation).\n"); + fprintf (stdout, "\thmq : Manager Quit.\n"); + + fprintf (stdout, "LOAD\n"); + + fprintf (stdout, "\thlb : Load the header from a BDD/ADD file.\n"); + fprintf (stdout, "\thlc : Load the header from a CNF file.\n"); + fprintf (stdout, "\tbl : Load a BDD from a file.\n"); + fprintf (stdout, "\tbal : Load an Array-BDD from a file.\n"); + fprintf (stdout, "\tal : Load an ADD from a file.\n"); + fprintf (stdout, "\taal : Load an Array-ADD from a file.\n"); + fprintf (stdout, "\tcl : Load a CNF Formula from a file.\n"); + fprintf (stdout, "\tcal : Load an Array of CNF Formulas from a file.\n"); + + fprintf (stdout, "STORE\n"); + + fprintf (stdout, + "\thw : (Header) Write variable information on stdout.\n"); + fprintf (stdout, "\tbs : Store a BDD into a file.\n"); + fprintf (stdout, "\tbas : Store an Array-BDD from a file.\n"); + fprintf (stdout, "\tas : Store an ADD into a file.\n"); + fprintf (stdout, "\taas : Store an Array-ADD into a file.\n"); + fprintf (stdout, "\tcs : Store BDD as a CNF formula.\n"); + fprintf (stdout, "\tcas : Store and Array of BDDs as a CNF formula.\n"); + + fprintf (stdout, "MISC\n"); + + fprintf (stdout, "\tdr : Activate Dynamic Reordering.\n"); + fprintf (stdout, "\tonl : Load the order from a file (varNames).\n"); + fprintf (stdout, "\toil : Load the order from a file (varAuxIds).\n"); + fprintf (stdout, "\tcil : Load compose IDs from a file.\n"); + fprintf (stdout, "\tslm : Set Load matchmode for variables.\n"); + fprintf (stdout, + "\top : Operation (or, and, xor, not, =) between BDDs.\n"); + fprintf (stdout, "\toc : Create a terminal-one BDD.\n"); + fprintf (stdout, "\tzc : Create a terminal-zero BDD.\n"); + fprintf (stdout, "\tlc : Create a single variable BDD (1 node).\n"); + fprintf (stdout, "\tbc : Create a random BDD.\n"); + + fprintf (stdout, "NOT YET IMPLEMENTED\n"); + + fprintf (stdout, + "\ta2b : Convert a file from the ASCII format to the binary one.\n"); + fprintf (stdout, + "\tb2a : Convert a file from the binary format to the ASCII one.\n"); + + fprintf (stdout, "HINT\n"); + + fprintf (stdout, + " Command 'mi' has to be the first instruction to build:\n"); + fprintf (stdout, " a) The CUDD manager.\n"); + fprintf (stdout, + " b) The internal manager (containing name and variable IDs).\n"); + fprintf (stdout, + " After that load an header file with 'hlb' or 'hlc' to have proper\n"); + fprintf (stdout, + " names and ids for each subsequent load/store operation.\n"); + + return (DDDMP_SUCCESS); +} + +/**Function******************************************************************** + + Synopsis [Load the BDD order from a file (varNames).] + + Description [Load the BDD order from a file (varNames). + Force the orderedVarNames field of the varInfo structure, + i.e., the local manager, to be stucked to this array of values. + ] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ + +static int +OrderNamesLoad( + dddmpVarInfo_t *varInfo /* IN/OUT: Variable Information */ + ) +{ + FILE *fp = NULL; + int i; + char fileName[DDDMPTEST_MAX_FILENAME_LENGTH]; + char tmpBuf[DDDMPTEST_MAX_STRING_LENGTH]; + char tmpName[DDDMPTEST_MAX_STRING_LENGTH]; + char **tmpOrderedVarNames = NULL; + + /*------------------------- Red New Var Names Array ----------------------*/ + + ReadString (DDDMP_MESSAGE_FILE, fileName); + + fp = fopen (fileName, "r"); + Dddmp_CheckAndReturn (fp==NULL, "Cannot open file."); + + varoutinfo = DDDMP_VARNAMES; + tmpOrderedVarNames = DDDMP_ALLOC (char *, varInfo->nDdVars); + + i=0; + while (fgets (tmpBuf, DDDMPTEST_MAX_STRING_LENGTH, fp)!=NULL) { + if (tmpBuf[0]=='#') { + continue; + } + + if (i>=varInfo->nDdVars) { + fprintf (stdout, + "Number of variables in files higher than DD manager vars (%d)\n", + varInfo->nDdVars); + fprintf (stdout, "Exceeding variables ignored\n"); + fprintf (stdout, + "You might increase the DDDMPTEST_MAX_VARIABLE constant\n"); + break; + } + + sscanf (tmpBuf, "%s", tmpName); + tmpOrderedVarNames[i] = DDDMP_ALLOC (char, (strlen (tmpName) + 1)); + if (tmpOrderedVarNames[i]==NULL) { + fprintf (stdout, "Error allocating memory\n"); + } else { + strcpy (tmpOrderedVarNames[i], tmpName); + } + i++; + } + + for ( ;inDdVars; i++) { + tmpOrderedVarNames[i] = NULL; + } + + fclose(fp); + + /*----------------------- Free and Set Var Names Array --------------------*/ + + DddmpStrArrayFree (varInfo->orderedVarNames, varInfo->nVars); + varInfo->orderedVarNames = tmpOrderedVarNames; + varInfo->nVars = varInfo->nDdVars; + + /* DO NOT ALLOW FURTHER UPDATES */ + varInfo->varNamesFlagUpdate = 0; + + return (DDDMP_SUCCESS); +} + +/**Function******************************************************************** + + Synopsis [Load the BDD order from a file (varauxids).] + + Description [Load the BDD order from a file (varauxids). + Force the + varAuxIds and varAuxIdsAll + or the + varComposeIds and varComposeIdsAll + fields of the varInfo structure, i.e., the local manager, to be + stucked to this array of values. + ] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ + +static int +IntArrayLoad ( + dddmpVarInfo_t *varInfo /* IN/OUT: Variable Information */, + const char *mode + ) +{ + FILE *fp = NULL; + int i; + int *tmpArray1 = NULL; + int *tmpArray2 = NULL; + char fileName[DDDMPTEST_MAX_FILENAME_LENGTH]; + char buf[DDDMPTEST_MAX_STRING_LENGTH]; + + ReadString (DDDMP_MESSAGE_FILE, fileName); + + fp = fopen(fileName, "r"); + Dddmp_CheckAndReturn (fp==NULL, "Cannot open file."); + + tmpArray1 = DDDMP_ALLOC (int, varInfo->nDdVars); + tmpArray2 = DDDMP_ALLOC (int, varInfo->nDdVars); + Dddmp_CheckAndReturn (tmpArray1==NULL, "Error allocating memory."); + Dddmp_CheckAndReturn (tmpArray2==NULL, "Error allocating memory."); + + i=0; + while (fgets(buf, DDDMPTEST_MAX_STRING_LENGTH, fp)!=NULL) { + if (buf[0]=='#') { + continue; + } + if (i>=varInfo->nDdVars) { + fprintf (stdout, + "Number of variables in files higher than DD manager vars (%d)\n", + varInfo->nDdVars); + fprintf (stdout, "Exceeding variables ignored.\n"); + fprintf (stdout, "(Increase the DDDMPTEST_MAX_VARIABLE constant.)\n"); + break; + } + sscanf(buf, "%d", &tmpArray1[i]); + sscanf(buf, "%d", &tmpArray2[i++]); + } + + for (;inDdVars;i++) { + tmpArray1[i]= -1; + tmpArray2[i]= -1; + } + + fclose(fp); + + if (strcmp (mode, "oil") == 0) { + varInfo->varAuxIds = tmpArray1; + varInfo->varAuxIdsAll = tmpArray2; + + /* DO NOT ALLOW FURTHER UPDATES */ + varInfo->varAuxIdsFlagUpdate = 0; + } else { + if (strcmp (mode, "cil") == 0) { + varInfo->varComposeIds = tmpArray1; + varInfo->varComposeIdsAll = tmpArray2; + + /* DO NOT ALLOW FURTHER UPDATES */ + varInfo->varComposeIdsFlagUpdate = 0; + } + } + + varInfo->nVars = varInfo->nDdVars; + varInfo->nSuppVars = varInfo->nDdVars; + + return (DDDMP_SUCCESS); +} + +/**Function******************************************************************** + + Synopsis [Load a BDD from a file.] + + Description [Load a BDD from a file.] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ + +static int +BddLoad ( + DdManager *ddMgr /* IN: CUDD Manager */, + DdNode **operandBdd /* IN: Operand BDD */, + dddmpVarInfo_t *varInfo /* IN/OUT: Variable Information */ + ) +{ + DdNode *f = NULL; + int i; + char fileName[DDDMPTEST_MAX_FILENAME_LENGTH]; + + /*------------------------ Read Operation Operands ------------------------*/ + + ReadString (DDDMP_MESSAGE_FILE, fileName); + ReadInt (DDDMP_MESSAGE_BDD, &i); + + /*-------------------------------- Load BDD -------------------------------*/ + + fprintf (stdout, "Loading %s ...\n", fileName); + + f = Dddmp_cuddBddLoad (ddMgr, varmatchmode, varInfo->orderedVarNames, + varInfo->varIdsAll, varInfo->varComposeIdsAll, DDDMP_MODE_DEFAULT, + fileName, NULL); + + if (f==NULL) { + fprintf (stderr, "Dddmp Test Error : %s is not loaded from file\n", + fileName); + } else { + operandBdd[i] = f; + } + + /*---------------------------- Tail Operations ----------------------------*/ + + return (DDDMP_SUCCESS); +} + +/**Function******************************************************************** + + Synopsis [Load an array of BDDs from a file.] + + Description [Load an array of BDDs from a file.] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ + +static int +BddArrayLoad( + DdManager *ddMgr /* IN: CUDD Manager */, + DdNode ***operandBddArray /* IN: Array of operand BDD */, + int *operandBddArraySize /* IN: Number of ADD in the Array */, + dddmpVarInfo_t *varInfo /* IN/OUT: Variable Information */ + ) +{ + DdNode **bddArray = NULL; + int i, j, nRoots; + char fileName[DDDMPTEST_MAX_FILENAME_LENGTH]; + + /*------------------------ Read Operation Operands ------------------------*/ + + ReadString (DDDMP_MESSAGE_FILE, fileName); + ReadInt (DDDMP_MESSAGE_BDD_ARRAY, &i); + + /*---------------------------- Load BDDs ----------------------------------*/ + + nRoots = Dddmp_cuddBddArrayLoad (ddMgr, rootmatchmode, + varInfo->rootNames, varmatchmode, + varInfo->orderedVarNames, varInfo->varIdsAll, varInfo->varComposeIdsAll, + DDDMP_MODE_DEFAULT, fileName, NULL, &bddArray); + + Dddmp_CheckAndReturn (nRoots>DDDMP_MAX_BDDARRAY_LEN, + "DDDMP_MAX_BDDARRAY_LEN exceeded by BDD array len (increase it)."); + + if (nRoots<=0) { + return (DDDMP_FAILURE); + } + + varInfo->nRoots = nRoots; + operandBddArray[i] = DDDMP_ALLOC (DdNode *, nRoots); + Dddmp_CheckAndReturn (operandBddArray[i]==NULL, "Allocation error."); + + for (j=0; jorderedVarNames, + varInfo->varIdsAll, varInfo->varComposeIdsAll, DDDMP_MODE_DEFAULT, + fileName, NULL); + + if (f==NULL) { + fprintf (stderr, "Dddmp Test Error : %s is not loaded from file\n", + fileName); + } else { + operandBdd[i] = f; + } + + /*---------------------------- Tail Operations ----------------------------*/ + + fprintf (stdout, "Load:\n"); + Cudd_PrintMinterm (ddMgr, f); + + return (DDDMP_SUCCESS); +} + +/**Function******************************************************************** + + Synopsis [Load an array of ADDs from a file.] + + Description [Load an array of ADDs from a file.] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ + +static int +AddArrayLoad( + DdManager *ddMgr /* IN: CUDD Manager */, + DdNode ***operandBddArray /* IN: Array of operand BDD */, + int *operandBddArraySize /* IN: Number of ADD in the Array */, + dddmpVarInfo_t *varInfo /* IN/OUT: Variable Information */ + ) +{ + char fileName[DDDMPTEST_MAX_FILENAME_LENGTH]; + int i, j, nRoots; + DdNode **bddArray = NULL; + + /*------------------------ Read Operation Operands ------------------------*/ + + ReadString (DDDMP_MESSAGE_FILE, fileName); + ReadInt (DDDMP_MESSAGE_BDD_ARRAY, &i); + + /*------------------------------- Load ADDs -------------------------------*/ + + nRoots = Dddmp_cuddAddArrayLoad (ddMgr, rootmatchmode, + varInfo->rootNames, varmatchmode, + varInfo->orderedVarNames, varInfo->varIdsAll, varInfo->varComposeIdsAll, + DDDMP_MODE_DEFAULT, fileName, NULL, &bddArray); + + Dddmp_CheckAndReturn (nRoots>DDDMP_MAX_BDDARRAY_LEN, + "DDDMP_MAX_BDDARRAY_LEN exceeded by BDD array len (increase it)."); + + if (nRoots<=0) { + return (DDDMP_FAILURE); + } + + varInfo->nRoots = nRoots; + operandBddArray[i] = DDDMP_ALLOC (DdNode *, nRoots); + Dddmp_CheckAndReturn (operandBddArray[i]==NULL, "Allocation error."); + + for (j=0; jorderedVarNames, varInfo->varAuxIdsAll, varInfo->varComposeIdsAll, + loadingMode, fileName, NULL, &rootsPtr, &nRoots); + + Dddmp_CheckAndGotoLabel (retValue==DDDMP_FAILURE, + "Dddmp Test: Load From File Error.\n", failure); + + operandBdd[i] = rootsPtr[0]; + + /*---------------------------- Tail Operations ----------------------------*/ + + /* Free array */ + DDDMP_FREE (rootsPtr); + + return (DDDMP_SUCCESS); + + failure: + return(DDDMP_FAILURE); +} + +/**Function******************************************************************** + + Synopsis [Load a CNF formula from a file, and create an array of + BDDs. + ] + + Description [Load a CNF formula from a file, and create an array of + BDDs. + ] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ + +static int +BddArrayLoadCnf ( + DdManager *ddMgr /* IN: CUDD Manager */, + DdNode ***operandBddArray /* IN: Array of operand BDD */, + int *operandBddArraySize /* IN: Number of ADD in the Array */, + dddmpVarInfo_t *varInfo /* IN/OUT: Variable Information */ + ) +{ + DdNode **rootsPtr = NULL; + Dddmp_DecompCnfLoadType loadingMode = DDDMP_CNF_MODE_CONJ_QUANT; + int i, j, nRoots, retValue; + char fileName[DDDMPTEST_MAX_FILENAME_LENGTH]; + + /*------------------------ Read Operation Operands ------------------------*/ + + ReadString (DDDMP_MESSAGE_FILE, fileName); + ReadInt (DDDMP_MESSAGE_BDD_ARRAY, &i); + + /*--------------------------- Loading BDDs --------------------------------*/ + + retValue = Dddmp_cuddBddArrayLoadCnf (ddMgr, rootmatchmode, + varInfo->rootNames, varmatchmode, + varInfo->orderedVarNames, varInfo->varIdsAll, varInfo->varComposeIdsAll, + loadingMode, fileName, NULL, &rootsPtr, &nRoots); + + Dddmp_CheckAndReturn (nRoots>DDDMP_MAX_BDDARRAY_LEN, + "DDDMP_MAX_BDDARRAY_LEN exceeded by BDD array len (increase it)."); + + if (nRoots<=0) { + return (DDDMP_FAILURE); + } + + varInfo->nRoots = nRoots; + operandBddArray[i] = DDDMP_ALLOC (DdNode *, nRoots); + Dddmp_CheckAndReturn (operandBddArray[i]==NULL, "Allocation error."); + + for (j=0; jorderedVarNames, + varInfo->varAuxIdsAll, DDDMP_MODE_TEXT, varoutinfo, fileName, NULL); + + Dddmp_CheckAndGotoLabel (retValue!=DDDMP_SUCCESS, "BDD NOT stored.", + failure); + + return (DDDMP_SUCCESS); + + failure: + return(DDDMP_FAILURE); +} + +/**Function******************************************************************** + + Synopsis [Store an Array of BDD in a file.] + + Description [Store an Array of BDD in a file.] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ + +static int +BddArrayStore ( + DdManager *ddMgr /* IN: CUDD Manager */, + DdNode ***operandBddArray /* IN: Array of operand BDD */, + int *operandBddArraySize /* IN: Number of ADD in the Array */, + dddmpVarInfo_t *varInfo /* IN/OUT: Variable Information */ + ) +{ + int i, retValue, nRoots; + char fileName[DDDMPTEST_MAX_FILENAME_LENGTH]; + + /*------------------------ Read Operation Operands ------------------------*/ + + ReadString (DDDMP_MESSAGE_FILE, fileName); + ReadInt (DDDMP_MESSAGE_BDD_ARRAY, &i); + + nRoots = operandBddArraySize[i]; + + /*----------------------------- Store BDDs -------------------------------*/ + + fprintf (stdout, "Storing Array of BDDs in file %s ...\n", fileName); + fflush (stdout); + + retValue = Dddmp_cuddBddArrayStore (ddMgr, NULL, nRoots, operandBddArray[i], + NULL, varInfo->orderedVarNames, varInfo->varAuxIdsAll, DDDMP_MODE_TEXT, + DDDMP_VARIDS, fileName, NULL); + + Dddmp_CheckAndGotoLabel (retValue!=DDDMP_SUCCESS, "BDD NOT stored.", + failure); + fprintf (stdout, "done.\n"); + + return (DDDMP_SUCCESS); + + failure: + return(DDDMP_FAILURE); +} + +/**Function******************************************************************** + + Synopsis [Store an ADD in a file.] + + Description [Store an ADD in a file.] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ + +static int +AddStore( + DdManager *ddMgr /* IN: CUDD Manager */, + DdNode **operandBdd /* IN: operand Bdd */, + dddmpVarInfo_t *varInfo /* IN/OUT: Variable Information */ + ) +{ + DdNode *f; + int i, retValue; + char fileName[DDDMPTEST_MAX_FILENAME_LENGTH]; + + /*------------------------ Read Operation Operands ------------------------*/ + + ReadString (DDDMP_MESSAGE_FILE, fileName); + ReadInt (DDDMP_MESSAGE_BDD, &i); + + fprintf (stdout, "Storing %s ...\n", fileName); + fflush (stdout); + f = operandBdd[i]; + +#if 0 + /* StQ Patch - CREATE temporary ADD to Store */ + f = Cudd_addResidue (ddMgr, 4, 3, 1, 1); + fprintf (stderr, "Store:\n"); + Cudd_PrintMinterm (ddMgr, f); + /* end ... StQ Patch */ +#endif + + retValue = Dddmp_cuddAddStore (ddMgr, NULL, f, varInfo->orderedVarNames, + varInfo->varAuxIdsAll, DDDMP_MODE_TEXT, varoutinfo, fileName, NULL); + + Dddmp_CheckAndReturn (retValue!=DDDMP_SUCCESS, "BDD NOT stored."); + + return (DDDMP_SUCCESS); +} + +/**Function******************************************************************** + + Synopsis [Store a BDD in a file.] + + Description [Store a BDD in a file.] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ + +static int +AddArrayStore ( + DdManager *ddMgr /* IN: CUDD Manager */, + DdNode ***operandBddArray /* IN: Array of operand ADD */, + int *operandBddArraySize /* IN: Number of ADD in the Array */, + dddmpVarInfo_t *varInfo + ) +{ + int i, retValue, nRoots; + char fileName[DDDMPTEST_MAX_FILENAME_LENGTH]; + + /*------------------------ Read Operation Operands ------------------------*/ + + ReadString (DDDMP_MESSAGE_FILE, fileName); + ReadInt (DDDMP_MESSAGE_BDD_ARRAY, &i); + + nRoots = operandBddArraySize[i]; + + fprintf (stdout, "Storing Array of BDDs in file %s ...\n", fileName); + fflush (stdout); + + retValue = Dddmp_cuddAddArrayStore (ddMgr, NULL, nRoots, operandBddArray[i], + NULL, varInfo->orderedVarNames, varInfo->varAuxIdsAll, DDDMP_MODE_TEXT, + DDDMP_VARIDS, fileName, NULL); + + Dddmp_CheckAndReturn (retValue!=DDDMP_SUCCESS, "BDD NOT stored."); + + fprintf (stdout, "done.\n"); + return (DDDMP_SUCCESS); +} + +/**Function******************************************************************** + + Synopsis [Store a BDD as CNF format in a file.] + + Description [Store a BDD as CNF format in a file.] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ + +static int +BddStoreCnf( + DdManager *ddMgr /* IN: CUDD Manager */, + DdNode **operandBdd /* IN: Array of operand ADD */, + dddmpVarInfo_t *varInfo /* IN/OUT: Variable Information */ + ) +{ + DdNode *f = NULL; + Dddmp_DecompCnfStoreType storingMode = DDDMP_CNF_MODE_BEST; + int noHeader = 0; + int i, nVars, retValue, idInitial, varNewN, clauseNewN; + int edgeInTh = (-1); + int pathLengthTh = (-1); + int *tmpBddIds = NULL; + int *tmpCnfIds = NULL; + char fileName[DDDMPTEST_MAX_FILENAME_LENGTH]; + char row[DDDMPTEST_MAX_FILENAME_LENGTH]; + + /*------------------------ Read Operation Operands ------------------------*/ + + ReadString (DDDMP_MESSAGE_FILE, fileName); + ReadInt (DDDMP_MESSAGE_BDD, &i); + ReadString (DDDMP_MESSAGE_FORMAT, row); + + switch (row[0]) { + case 'N': + storingMode = DDDMP_CNF_MODE_NODE; + break; + case 'M': + storingMode = DDDMP_CNF_MODE_MAXTERM; + break; + case 'B': + storingMode = DDDMP_CNF_MODE_BEST; + ReadInt (DDDMP_MESSAGE_EDGE_MAX, &edgeInTh); + ReadInt (DDDMP_MESSAGE_LENGHT_MAX, &pathLengthTh); + break; + } + ReadInt (DDDMP_MESSAGE_I_ID, &idInitial); + + fprintf (stdout, "Storing %s ...\n", fileName); + fflush (stdout); + + f = operandBdd[i]; + + nVars = varInfo->nDdVars; + + /*------------ From BDD and CNF ids to Proper Array of ids ----------------*/ + + tmpBddIds = DDDMP_ALLOC (int, nVars); + Dddmp_CheckAndGotoLabel (tmpBddIds==NULL, "Error allocating memory.", + failure); + tmpCnfIds = DDDMP_ALLOC (int, nVars); + Dddmp_CheckAndGotoLabel (tmpBddIds==NULL, "Error allocating memory.", + failure); + + for (i=0; iorderedVarNames, tmpBddIds, NULL, tmpCnfIds, idInitial, + edgeInTh, pathLengthTh, fileName, NULL, &clauseNewN, &varNewN); + + Dddmp_CheckAndGotoLabel (retValue!=DDDMP_SUCCESS, "BDD NOT stored.", + failure); + + fprintf (stdout, "Number of Clauses Stored = %d\n", clauseNewN); + fprintf (stdout, "Number of New Variable Created Storing = %d\n", + varNewN); + fflush (stdout); + + DDDMP_FREE (tmpBddIds); + DDDMP_FREE (tmpCnfIds); + + return (DDDMP_SUCCESS); + + failure: + DDDMP_FREE (tmpBddIds); + DDDMP_FREE (tmpCnfIds); + + return(DDDMP_FAILURE); +} + +/**Function******************************************************************** + + Synopsis [Store a BDD as CNF format in a file.] + + Description [Store a BDD as CNF format in a file.] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ + +static int +BddArrayStoreCnf( + DdManager *ddMgr /* IN: CUDD Manager */, + DdNode ***operandBddArray /* IN: Array of operand ADD */, + int *operandBddArraySize /* IN: Number of ADD in the Array */, + dddmpVarInfo_t *varInfo /* IN/OUT: Variable Information */ + ) +{ + Dddmp_DecompCnfStoreType storingMode = DDDMP_CNF_MODE_BEST; + int noHeader = 0; + int i, nVars, bddN, retValue, idInitial, varNewN, clauseNewN; + int edgeInTh = (-1); + int pathLengthTh = (-1); + int *tmpBddIds = NULL; + int *tmpCnfIds = NULL; + char fileName[DDDMPTEST_MAX_FILENAME_LENGTH]; + char row[DDDMPTEST_MAX_FILENAME_LENGTH]; + + /*------------------------ Read Operation Operands ------------------------*/ + + ReadString (DDDMP_MESSAGE_FILE, fileName); + ReadInt (DDDMP_MESSAGE_BDD_ARRAY, &bddN); + ReadString (DDDMP_MESSAGE_FORMAT, row); + switch (row[0]) { + case 'N': + storingMode = DDDMP_CNF_MODE_NODE; + break; + case 'M': + storingMode = DDDMP_CNF_MODE_MAXTERM; + break; + case 'B': + storingMode = DDDMP_CNF_MODE_BEST; + ReadInt (DDDMP_MESSAGE_EDGE_MAX, &edgeInTh); + ReadInt (DDDMP_MESSAGE_LENGHT_MAX, &pathLengthTh); + break; + } + ReadInt (DDDMP_MESSAGE_I_ID, &idInitial); + + nVars = varInfo->nDdVars; + + /*------------ From BDD and CNF ids to Proper Array of ids ----------------*/ + + tmpBddIds = DDDMP_ALLOC (int, nVars); + Dddmp_CheckAndReturn (tmpBddIds==NULL, "Allocation error."); + tmpCnfIds = DDDMP_ALLOC (int, nVars); + Dddmp_CheckAndReturn (tmpCnfIds==NULL, "Allocation error."); + + for (i=0; iorderedVarNames, + tmpBddIds, NULL, tmpCnfIds, idInitial, edgeInTh, pathLengthTh, fileName, + NULL, &varNewN, &clauseNewN); + + Dddmp_CheckAndGotoLabel (retValue!=DDDMP_SUCCESS, "BDD NOT stored.", + failure); + + fprintf (stdout, "Number of Clauses Stored = %d\n", clauseNewN); + fprintf (stdout, "Number of New Variable Created Storing = %d\n", + varNewN); + fflush (stdout); + + DDDMP_FREE (tmpBddIds); + DDDMP_FREE (tmpCnfIds); + + return (DDDMP_SUCCESS); + + failure: + DDDMP_FREE (tmpBddIds); + DDDMP_FREE (tmpCnfIds); + + return(DDDMP_FAILURE); +} + +/**Function******************************************************************** + + Synopsis [Dynamic Reordering BDDs.] + + Description [Dynamic Reordering BDDs using one of the allowed CUDD + methods.] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ + +static int +DynamicReordering ( + DdManager *ddMgr /* IN: CUDD Manager */ + ) +{ + Cudd_ReorderingType approach = CUDD_REORDER_SIFT; + int method; + + /*------------------------ Read Operation Operands ------------------------*/ + + ReadInt (DDDMP_MESSAGE_REORDERING, &method); + approach = (Cudd_ReorderingType) method; + + Cudd_ReduceHeap (ddMgr, approach, 5); + + return (DDDMP_SUCCESS); +} + +/**Function******************************************************************** + + Synopsis [Selects variable matching mode.] + + Description [Selects variable matching mode.] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ + +static int +SetLoadMatchmode ( + ) +{ + int sel; + char row[DDDMPTEST_MAX_FILENAME_LENGTH]; + + fprintf (stdout, "Variable matchmode:\n"); + fprintf (stdout, "Match IDs (1)\n"); + fprintf (stdout, "Match permIDs (2)\n"); + fprintf (stdout, "Match names (must have been loaded) (3)\n"); + fprintf (stdout, "Match auxids (must have been loaded) (4)\n"); + fprintf (stdout, "Match composeids (must have been loaded) (5)\n"); + fprintf (stdout, "Your choice: "); + fflush (stdout); + + fgets (row, DDDMPTEST_MAX_STRING_LENGTH, stdin); + sscanf (row, "%d", &sel); + + switch (sel) { + case 1: + varmatchmode = DDDMP_VAR_MATCHIDS; + break; + case 2: + varmatchmode = DDDMP_VAR_MATCHPERMIDS; + break; + case 3: + varmatchmode = DDDMP_VAR_MATCHNAMES; + break; + case 4: + varmatchmode = DDDMP_VAR_MATCHAUXIDS; + break; + case 5: + varmatchmode = DDDMP_VAR_COMPOSEIDS; + break; + default: + fprintf (stderr, "Wrong choice!\n"); + break; + } + + return (DDDMP_SUCCESS); +} + +/**Function******************************************************************** + + Synopsis [Complete the internal manager structure for subsequent + BDD/ADD/CNF operations. + ] + + Description [Complete the internal manager structure for subsequent + BDD/ADD/CNF operations. + The phylosophy is simple: to have proper names and ids it is necessary + to load an header before each actual load/store operation. + An header load should initialize variable names, variable ids, + variable compose ids, and variable auxiliary ids for all variables + stored in the file. + This information has to be extended for all variables in the + *current* CUDD manager (before any store operation). + CompleteInfoStruct does this job. + Arrays varIds, varComposeIds, and varAuxIds contain information for + all the variable in the BDD/ADD/CNF while arrays varIdsAll, + varComposeIdsAll, and varAuxIdsAll contain information for *all* + variable in the current CUDD manager. + ] + + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ + +static int +CompleteInfoStruct ( + Dddmp_DecompType ddType /* IN: selects the proper decomp type */, + int nVars /* IN: number of DD variables */, + int nSuppVars /* IN: number of support variables */, + char **suppVarNames /* IN: array of support variable names */, + char **orderedVarNames /* IN: array of variable names */, + int *varIds /* IN: array of variable ids */, + int *varComposeIds /* IN: array of permids ids */, + int *varAuxIds /* IN: array of variable aux ids */, + int nRoots /* IN: number of root in the file */, + dddmpVarInfo_t *varInfo /* IN: Variable Information */ + ) +{ + int i; + char tmpString[DDDMPTEST_MAX_STRING_LENGTH]; + + /*------------------------- Updates Variable Names ------------------------*/ + + DddmpStrArrayFree (varInfo->suppVarNames, varInfo->nSuppVars); + varInfo->suppVarNames = suppVarNames; + + if (varInfo->varNamesFlagUpdate == 1) { + + DddmpStrArrayFree (varInfo->orderedVarNames, varInfo->nVars); + + if (orderedVarNames != NULL) { + varInfo->orderedVarNames = orderedVarNames; + } else { + varInfo->orderedVarNames = DDDMP_ALLOC (char *, nVars); + Dddmp_CheckAndReturn (varInfo->orderedVarNames==NULL, + "Allocation error."); + + for (i=0; iorderedVarNames[i] = NULL; + } + + if (varInfo->suppVarNames != NULL) { + for (i=0; iorderedVarNames[i] = DDDMP_ALLOC (char, + (strlen (varInfo->suppVarNames[i]) + 1)); + strcpy (varInfo->orderedVarNames[i], varInfo->suppVarNames[i]); + } + } + + for (i=0; iorderedVarNames[i] == NULL) { + sprintf (tmpString, "DUMMY%d", i); + varInfo->orderedVarNames[i] = DDDMP_ALLOC (char, + (strlen (tmpString) + 1)); + strcpy (varInfo->orderedVarNames[i], tmpString); + } + } + } + } + + /*------------------------------ Updates IDs ------------------------------*/ + + DDDMP_FREE (varInfo->varIds); + varInfo->varIds = varIds; + + if (varInfo->varIdsFlagUpdate == 1) { + + /* Free Previously Allocated Memory */ + DDDMP_FREE (varInfo->varIdsAll); + + /* Allocate New Memory and Check */ + varInfo->varIdsAll = DDDMP_ALLOC (int, nVars); + Dddmp_CheckAndReturn (varInfo->varIdsAll==NULL, "Allocation error."); + + /* Set New Values */ + for (i=0; ivarIdsAll[i] = (-1); + } + + if (varInfo->varIds != NULL) { + for (i=0; ivarIdsAll[varInfo->varIds[i]] = varInfo->varIds[i]; + } + } + } + + + /*-------------------------- Updates Compose IDs --------------------------*/ + + DDDMP_FREE (varInfo->varComposeIds); + varInfo->varComposeIds = varComposeIds; + + if (varInfo->varComposeIdsFlagUpdate == 1) { + + /* Free Previously Allocated Memory */ + DDDMP_FREE (varInfo->varComposeIdsAll); + + /* Allocate New Memory and Check */ + varInfo->varComposeIdsAll = DDDMP_ALLOC (int, nVars); + Dddmp_CheckAndReturn (varInfo->varComposeIdsAll==NULL, + "Allocation error."); + + /* Set New Values */ + for (i=0; ivarComposeIdsAll[i] = (-1); + } + + if (varInfo->varComposeIds != NULL) { + for (i=0; ivarComposeIdsAll[varInfo->varIds[i]] = + varInfo->varComposeIds[i]; + } + } + } + + /*------------------------- Updates Auxiliary IDs -------------------------*/ + + DDDMP_FREE (varInfo->varAuxIds); + varInfo->varAuxIds = varAuxIds; + + if (varInfo->varAuxIdsFlagUpdate == 1) { + + /* Free Previously Allocated Memory */ + DDDMP_FREE (varInfo->varAuxIdsAll); + + /* Allocate New Memory and Check */ + varInfo->varAuxIdsAll = DDDMP_ALLOC (int, nVars); + Dddmp_CheckAndReturn (varInfo->varAuxIdsAll==NULL, "Allocation error."); + + /* Set New Values */ + for (i=0; ivarAuxIdsAll[i] = (-1); + } + + if (varInfo->varAuxIds != NULL) { + for (i=0; ivarAuxIdsAll[varInfo->varIds[i]] = varInfo->varAuxIds[i]; + } + } + } + + /*----------------------------- Updates Sizes -----------------------------*/ + + varInfo->ddType = ddType; + varInfo->nVars = nVars; + varInfo->nSuppVars = nSuppVars; + Dddmp_CheckAndReturn (varInfo->nDdVarsnVars, + "Local Manager with Not Enough Variables."); + varInfo->nRoots = nRoots; + + return (DDDMP_SUCCESS); +} + +/**Function******************************************************************** + + Synopsis [Reads an integer value from standard input.] + + Description [Reads an integer value from standard input.] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ + +static void +ReadInt ( + Dddmp_MessageType message, + int *i + ) +{ + char row[DDDMPTEST_MAX_FILENAME_LENGTH]; + + switch (message) { + case DDDMP_MESSAGE_MANAGER_VAR: + fprintf (stdout, "Number of Variables: "); + break; + case DDDMP_MESSAGE_BDD: + fprintf (stdout, "Which BDDs [0..%d]: ", + DDDMPTEST_MAX_OPERAND-1); + break; + case DDDMP_MESSAGE_BDD_ARRAY: + fprintf (stdout, "Which Array of BDDs [0..%d]: ", + DDDMPTEST_MAX_OPERAND-1); + break; + case DDDMP_MESSAGE_CUBE: + fprintf (stdout, "How many cubes [1..]: "); + break; + case DDDMP_MESSAGE_INDEX: + fprintf (stdout, "Index: "); + break; + case DDDMP_MESSAGE_SOURCE1: + fprintf (stdout, "Source1 [0..%d]: ", DDDMPTEST_MAX_OPERAND-1); + break; + case DDDMP_MESSAGE_SOURCE2: + fprintf (stdout, "Source2 [0..%d]: ", DDDMPTEST_MAX_OPERAND-1); + break; + case DDDMP_MESSAGE_DESTINATION: + fprintf (stdout, "Destination [0..%d]: ", DDDMPTEST_MAX_OPERAND-1); + break; + case DDDMP_MESSAGE_I_ID: + fprintf (stdout, "Initial ID : "); + break; + case DDDMP_MESSAGE_EDGE_MAX: + fprintf (stdout, + "Max Number of Edges (Insert cut-point from there on) : "); + break; + case DDDMP_MESSAGE_LENGHT_MAX: + fprintf (stdout, + "Max BDD-Path Length (Insert cut-point from there on) : "); + break; + case DDDMP_MESSAGE_REORDERING: + fprintf (stdout, "Reordering Approach (1..17): "); + break; + default: + fprintf (stdout, "Input Generic Integer: "); + break; + } + fflush (stdout); + + fgets (row, DDDMPTEST_MAX_STRING_LENGTH, stdin); + sscanf (row, "%d", i); + fflush (stdin); + + return; +} + + +/**Function******************************************************************** + + Synopsis [Reads a string from standard input.] + + Description [Reads a string from standard input.] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ + +static void +ReadString ( + Dddmp_MessageType message, + char string[] + ) +{ + char localString[DDDMPTEST_MAX_STRING_LENGTH]; + + switch (message) { + case DDDMP_MESSAGE_PROMPT: + fprintf (stdout, "TestDddmp> "); + break; + case DDDMP_MESSAGE_FILE: + fprintf (stdout, "File : "); + break; + case DDDMP_MESSAGE_OP: + fprintf (stdout, "Operation [or,and,xor,!,buf(=)] : "); + break; + case DDDMP_MESSAGE_FORMAT: + fprintf (stdout, "Format (Node=N, Maxterm=M, Best=B) : "); + break; + default: + fprintf (stdout, "Input Generic String : "); + break; + } + fflush (stdout); + + fgets (localString, DDDMPTEST_MAX_STRING_LENGTH, stdin); + sscanf (localString, "%s", string); + fflush (stdin); + + return; +} + + + + diff --git a/distr/epd/Makefile b/distr/epd/Makefile new file mode 100644 index 0000000..3b26bc9 --- /dev/null +++ b/distr/epd/Makefile @@ -0,0 +1,64 @@ +# $Id$ +# +# epd -- extended precision +#--------------------------------------------------------------------------- +.SUFFIXES: .c .o .u + +CC = gcc +RANLIB = ranlib + +MFLAG = +ICFLAGS = -g -O6 -Wall +CFLAGS = $(ICFLAGS) $(MFLAG) $(XCFLAGS) + +LINTFLAGS = -u -n + +# this is to create the lint library +LINTSWITCH = -o + +P = epd +PSRC = epd.c +PHDR = epd.h +POBJ = $(PSRC:.c=.o) +PUBJ = $(PSRC:.c=.u) + +WHERE = .. +INCLUDE = $(WHERE)/include + +#--------------------------- + +lib$(P).a: $(POBJ) + ar rv $@ $? + $(RANLIB) $@ + +.c.o: $(PSRC) $(PHDR) + $(CC) -c $< -I$(INCLUDE) $(CFLAGS) + +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) + +lint: llib-l$(P).ln + +llib-l$(P).ln: $(PSRC) $(PHDR) + lint $(LINTFLAGS) $(LINTSWITCH)$(P) -I$(INCLUDE) $(PSRC) + +tags: $(PSRC) $(PHDR) + ctags $(PSRC) $(PHDR) + +all: lib$(P).a lib$(P).b llib-l$(P).ln tags + +clean: + rm -f *.o *.u .pure *.warnings + +distclean: clean + rm -f lib*.a lib$(P).b llib-l$(P).ln tags *~ *.bak *.qv *.qx diff --git a/distr/epd/epd.c b/distr/epd/epd.c new file mode 100644 index 0000000..14f314f --- /dev/null +++ b/distr/epd/epd.c @@ -0,0 +1,1344 @@ +/**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 +#include +#include +#include +#include "util.h" +#include "epd.h" + + +/**Function******************************************************************** + + Synopsis [Allocates an EpDouble struct.] + + Description [Allocates an EpDouble struct.] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +EpDouble * +EpdAlloc(void) +{ + EpDouble *epd; + + epd = 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) +{ + 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); +} diff --git a/distr/epd/epd.h b/distr/epd/epd.h new file mode 100644 index 0000000..4b538c0 --- /dev/null +++ b/distr/epd/epd.h @@ -0,0 +1,200 @@ +/**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 _EPD +#define _EPD + +#ifdef __cplusplus +extern "C" { +#endif + +/*---------------------------------------------------------------------------*/ +/* 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***************************************************************/ + +#ifdef __cplusplus +} +#endif + +#endif /* _EPD */ diff --git a/distr/mnemosyne/Makefile b/distr/mnemosyne/Makefile new file mode 100644 index 0000000..3c593a2 --- /dev/null +++ b/distr/mnemosyne/Makefile @@ -0,0 +1,53 @@ +# $Id$ +# +# Makefile for the Mnemosyne memory allocation tracker. +# +# Marcus J. Ranum, 1990 +# +#Options: +# define MALLOC_IS_VOIDSTAR if your system's malloc is declared as a (void *) +# otherwise, it is assumed to be a (char *). a "mall_t" is typedeffed in +# mnemconf.h and mnemosyne.h to implement this. +OPTNS = -DMALLOC_IS_VOIDSTAR +#OPTNS = + +CC = cc +RANLIB = ranlib + +#compiler flags +CFLAGS = -g $(OPTNS) $(XCFLAGS) + +#loader flags +LDFLGS = + +HDRS = mnemosyne.h mnemconf.h + +all: mnemalyse libmnem.a + +mnemalyse: mnemalyse.o + $(CC) $(LDFLGS) -o $@ mnemalyse.o + +libmnem.a: mnemosyne.o + ar rcv $@ mnemosyne.o + $(RANLIB) $@ + +mtest: mtest.o libmnem.a + $(CC) $(LDFLGS) -o $@ mtest.o libmnem.a + +runmtest: all mtest + @echo "running memory waster" + mtest + @echo "press return for symbol list"; read ff + @cat mnem.syms + @echo "press return for waste analysis"; read ff + mnemalyse + +clean: + rm -f mtest core *.o mnem.dat mnem.syms + +distclean: clean + rm -f *.bak *~ libmnem.a mnemalyse + + +mnemosyne.o: Makefile mnemosyne.c $(HDRS) +mnemalyse.o: Makefile mnemalyse.c $(HDRS) diff --git a/distr/mnemosyne/README b/distr/mnemosyne/README new file mode 100644 index 0000000..182bbd2 --- /dev/null +++ b/distr/mnemosyne/README @@ -0,0 +1,39 @@ + + This is a set of tools designed to help find memory leaks in +programs, and to locate memory-hogging functions. It's implemented as +a wrapper library that goes around malloc/free/etc, and an include file +that "intercepts" calls to malloc/free/etc and makes them call the +wrappers. Thus, you can get extensive memory profiling and leak +detection by just adding one #include directive at the top of your +file and recompiling/linking. + + Unlike some similar tools I've seen in the past, this makes +sure that it keeps its on-disk data current, so that if the program +is crashed or interrupted, the results still have some validity. The +on-disk data is as compacted as I could make it, to give a chance of +this being useable in debugging big memory pigs. It adds some cost +in performance and memory size (since it keeps its own in-memory +symbol tables) but since it's only a debugging tool, I think the +cost is worth the benefit. This library can also be used to track +only allocations in a single module, or set of modules, and doesn't +interfere with calls to the "real" malloc() that are made in other +library routines. + + Every effort has been made to ensure that the code is +portable and won't interfere with running code - it should just +plug in or out. The biggest hindrances are forward declarations of +malloc() [which the preprocessor gleefully turns into syntax errors +for you] and structure elements named "free". The code has been +tested under Ultrix on DEC Risc and VAX systems, and under SunOS +on a Motorola platform. Please send patches, suggestions, etc, +to the author, who will probably not have time to do anything with +them. + +Compiling and building: + You may wish to edit the Makefile and glance at mnemconf.h, +then simply type "make". "make mtest" will build a simple test program +that will give you an idea of how things work. "make runmtest" will +run the test and do analysis on it. + +Marcus J. Ranum +mjr@decuac.dec.com diff --git a/distr/mnemosyne/mnemalyse.c b/distr/mnemosyne/mnemalyse.c new file mode 100644 index 0000000..60d2b91 --- /dev/null +++ b/distr/mnemosyne/mnemalyse.c @@ -0,0 +1,197 @@ +/************************************************************************ + * * + * Copyright (c) 1985 by * + * Digital Equipment Corporation, Maynard, MA * + * All rights reserved. * + * * + * The information in this software is subject to change without * + * notice and should not be construed as a commitment by Digital * + * Equipment Corporation. * + * * + * Digital assumes no responsibility for the use or reliability * + * of its software on equipment which is not supplied by Digital. * + * * + * Redistribution and use in source and binary forms are permitted * + * provided that the above copyright notice and this paragraph are * + * duplicated in all such forms and that any documentation, * + * advertising materials, and other materials related to such * + * distribution and use acknowledge that the software was developed * + * by Digital Equipment Corporation. The name of Digital Equipment * + * Corporation may not be used to endorse or promote products derived * + * from this software without specific prior written permission. * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR * + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.* + * Do not take internally. In case of accidental ingestion, contact * + * your physician immediately. * + * * + ************************************************************************/ + +/* DO NOT INCLUDE "mnemosyne.h" !!! */ +#include +#include +#include +#include + +static char rcsid[] = "/fats/tools/hsv/mnemosyne/mnemalyse.c,v 1.1.1.1 1995/06/06 18:18:28 fabio Exp"; + +#include "mnemconf.h" + +extern char *index(); + +/* +post-processor to interpret memory allocation maps and search for +pointers that were allocated but never freed. + + Marcus J. Ranum, 1990. (mjr@decuac.dec.com) +*/ + + +/* +simple and braindead, read in the ".lines" file, and store it in a +table by number. then read the pointer map, and crossref any unfreed +pointers. simple as dereferencing NULL... + +this could use some cleaning and buffing, but it's damn effective as +it is. again, fancier symbol table routines would make this faster, +but who gives a damn? it only has to be faster than finding memory +leaks by hand... +*/ + +struct xsym { + char *dat; + int lnum; + int map; + struct xsym *nxt; +}; + + + +main() +{ + register struct xsym *sp; + register struct xsym *zp; + struct ptr p; + struct xsym *shash[HASHSIZ]; + char inbuf[BUFSIZ]; + FILE *lp; + int fd; + + /* statistics */ + int ptrcnt = 0; + int ptrbad = 0; + int ptrlos = 0; + + /* to chop up lines */ + char *cpmap; + char *cpcalls; + char *cpave; + char *cplnum; + char *cpfnam; + + for(fd = 0; fd < HASHSIZ; fd++) + shash[fd] = (struct xsym *)0; + + if((lp = fopen(LINESFILE,"r")) == (FILE *)0) { + perror(LINESFILE); + exit(1); + } + + if((fd = open(PTRFILE,O_RDONLY|O_RDWR)) < 0) { + perror(PTRFILE); + exit(1); + } + + /* this is ugly, but I refuse to trust !@(#&U!@#&! sscanf() */ + while((cpmap = fgets(inbuf,sizeof(inbuf),lp)) != (char *)0) { + if(inbuf[0] == '#') + continue; + + sp = (struct xsym *)malloc(sizeof(struct xsym)); + if(sp == (struct xsym *)0) { + perror("malloc"); + exit(1); + } + sp->lnum = sp->map = 0; + + if((cpcalls = index(cpmap,'\t')) != (char *)0) + *cpcalls++ = '\0'; + + if((cpave = index(cpcalls,'\t')) != (char *)0) + *cpave++ = '\0'; + + if((cplnum = index(cpave,'\t')) != (char *)0) + *cplnum++ = '\0'; + + if((cpfnam = index(cplnum,'\t')) != (char *)0) + *cpfnam++ = '\0'; + + /* setup symbol */ + sp->map = atoi(cpmap); + + if(cplnum == (char *)0) + sp->lnum = -1; + else + sp->lnum = atoi(cplnum); + + if(cpfnam != (char *)0) { + char *x; + if((x = index(cpfnam,'\n')) != (char *)0) + *x = '\0'; + + sp->dat = malloc((unsigned)(strlen(cpfnam) + 1)); + if(sp->dat == (char *)0) { + perror("malloc"); + exit(1); + } + (void)strcpy(sp->dat,cpfnam); + } else + sp->dat = "unknown"; + + /* check to make sure it is not already in table */ + zp = shash[sp->map % HASHSIZ]; + while(zp != (struct xsym *)0) { + if(zp->map == sp->map) { + (void)fprintf(stderr, + "mnemalyse: duplicate map entry ignored"); + (void)fprintf(stderr, + " (point at both %s and %s)\n",sp->dat,zp->dat); + (void)free(sp); + + /* can't free dat - may not be malloced! */ + sp = (struct xsym *)0; + break; + } + zp = zp->nxt; + } + + /* shrug, link it in */ + if(sp != (struct xsym *)0) { + sp->nxt = shash[sp->map % HASHSIZ]; + shash[sp->map % HASHSIZ] = sp; + } + } + (void)fclose(lp); + + while(read(fd,(char *)&(p.dsk),sizeof(p.dsk)) == sizeof(p.dsk)) { + + /* if the pointer was not deallocated, note it */ + if(p.dsk.siz != 0) { + zp = shash[p.dsk.smap % HASHSIZ]; + while(zp != (struct xsym *)0) { + if(zp->map == p.dsk.smap) { + printf("%d bytes missing %s line:%d\n", + p.dsk.siz,zp->dat,zp->lnum); + } + zp = zp->nxt; + } + ptrbad++; + ptrlos += p.dsk.siz; + } + ptrcnt++; + } + + printf("%d pointers, %d lost totalling %d bytes\n", + ptrcnt,ptrbad,ptrlos); + exit(0); +} diff --git a/distr/mnemosyne/mnemconf.h b/distr/mnemosyne/mnemconf.h new file mode 100644 index 0000000..9ea8f75 --- /dev/null +++ b/distr/mnemosyne/mnemconf.h @@ -0,0 +1,89 @@ +/************************************************************************ + * * + * Copyright (c) 1985 by * + * Digital Equipment Corporation, Maynard, MA * + * All rights reserved. * + * * + * The information in this software is subject to change without * + * notice and should not be construed as a commitment by Digital * + * Equipment Corporation. * + * * + * Digital assumes no responsibility for the use or reliability * + * of its software on equipment which is not supplied by Digital. * + * * + * Redistribution and use in source and binary forms are permitted * + * provided that the above copyright notice and this paragraph are * + * duplicated in all such forms and that any documentation, * + * advertising materials, and other materials related to such * + * distribution and use acknowledge that the software was developed * + * by Digital Equipment Corporation. The name of Digital Equipment * + * Corporation may not be used to endorse or promote products derived * + * from this software without specific prior written permission. * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR * + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.* + * Do not take internally. In case of accidental ingestion, contact * + * your physician immediately. * + * * + ************************************************************************/ + +#ifndef _INCL_MNEMCONF_H + +/* +/fats/tools/hsv/mnemosyne/mnemconf.h,v 1.1.1.1 1995/06/06 18:18:29 fabio Exp +*/ + +/* +site specific and shared internal data structures used by mnemosyne. +the only data structure that may need to be shared is the struct ptr, +which is defined herein. + + Marcus J. Ranum, 1990. (mjr@decuac.dec.com) +*/ + + + +/* if your machine has malloc and all declared as a (void *) not a (char *) */ +#ifdef MALLOC_IS_VOIDSTAR +typedef void *mall_t; +#else +typedef char *mall_t; +#endif + + +/* size of internal hash tables - don't go wild - this is slow anyhow */ +#define HASHSIZ 2027 + + +/* names of files to write */ +#define LINESFILE "mnem.syms" +#define PTRFILE "mnem.dat" + + +extern mall_t malloc(); +extern mall_t realloc(); +extern mall_t calloc(); +extern void free(); + + +/* +storage for a pointer map entry - the only data structure we share +a whole mess of these get written to mnem.dat as calls to malloc and +whatnot are made. the distinction between an *allocated* pointer and +and unallocated one is that 'siz' is 0 in freed ptrs. this is used +by the post-processor to look for memory leaks. +*/ +struct ptr { + mall_t ptr; /* pointer to allocated memory */ + int map; /* this pointer's map # */ + struct ptr *next; + + /* only part that gets written to the disk */ + struct { + unsigned siz; /* size allocated (or 0) */ + int smap; /* symbol map # */ + } dsk; +}; + +#define _INCL_MNEMCONF_H +#endif diff --git a/distr/mnemosyne/mnemosyne.c b/distr/mnemosyne/mnemosyne.c new file mode 100644 index 0000000..0d759da --- /dev/null +++ b/distr/mnemosyne/mnemosyne.c @@ -0,0 +1,670 @@ +/************************************************************************ + * * + * Copyright (c) 1985 by * + * Digital Equipment Corporation, Maynard, MA * + * All rights reserved. * + * * + * The information in this software is subject to change without * + * notice and should not be construed as a commitment by Digital * + * Equipment Corporation. * + * * + * Digital assumes no responsibility for the use or reliability * + * of its software on equipment which is not supplied by Digital. * + * * + * Redistribution and use in source and binary forms are permitted * + * provided that the above copyright notice and this paragraph are * + * duplicated in all such forms and that any documentation, * + * advertising materials, and other materials related to such * + * distribution and use acknowledge that the software was developed * + * by Digital Equipment Corporation. The name of Digital Equipment * + * Corporation may not be used to endorse or promote products derived * + * from this software without specific prior written permission. * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR * + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.* + * Do not take internally. In case of accidental ingestion, contact * + * your physician immediately. * + * * + ************************************************************************/ + +/* DO NOT INCLUDE "mnemosyne.h" !!! */ +#include +#include +#include + +/* shared stuff - and decl of struct ptr */ +#include "mnemconf.h" + +static char rcsid[] = "/fats/tools/hsv/mnemosyne/mnemosyne.c,v 1.1.1.1 1995/06/06 18:18:28 fabio Exp"; + + +/* +malloc() realloc() and family wrappers - these functions manage a set +of data files that are updated whenever a pointer is allocated or freed, +as well as gathering stats about dynamic memory use and leakage. + + Marcus J. Ranum, 1990. (mjr@decuac.dec.com) +*/ + + +/* +there is some egregious use of globals, void functions, and whatnot +in this code. it is mostly due to the constraint that nothing must +be visible to the outside, and that the code must be structurally +simple. error checking is pitched out the window in spots, since an +error in the mnemosyne code should not affect whatever is being +instrumented if at all possible. this means no errors, no signals, +nothing. (this message brought to you by my ego, in case you think +I don't know how to write better code than this) :) + +mjr, hacking on Christmas, 1990. +*/ + +#define REC_UNINIT 000 +#define REC_INITTED 001 +#define REC_ERR 002 +#define REC_ON 010 +#define REC_ONOFF 020 +static int rec_state = REC_UNINIT; + +/* +this method of storing the symbol maps is not the most efficient, but +then that's not important here, since all we're trying to do is find +memory leaks. if you choose to improve the symbol management to use +bucketed hash tables, please contact the author and the code will be +updated :) - besides, since we do file I/O every time you malloc or +free something, there's no way in hell this is going to set any new +records for speed. +*/ + + +/* storage for code/line # entry */ +struct sym { + char *labl; + int lineno; + int mapno; + int mallcnt; + float avsiz; + struct sym *next; +}; + + + +/* static symbol map */ +static struct { + FILE *fp; + FILE *log; + int fd; + + long nalloc; /* count of allocations */ + long nrlloc; /* count of re-allocations */ + long nfree; /* count of frees */ + long nbfree; /* count of bad frees */ + long ninuse; /* known allocated memory in use */ + float avgsiz; /* average malloc size */ + + /* one entry per pointer returned by malloc */ + int pmap; /* current next ptr map to alloc */ + struct ptr *phash[HASHSIZ]; + + /* one entry per line of code that calls malloc/realloc, etc */ + int lmap; /* current next line map to alloc */ + struct sym *shash[HASHSIZ]; /* hash access */ +} map; + + + + +/* print a locale record with checks for closed log file */ +static void +ploc(lab,lin,siz) +char *lab; +int lin; +int siz; +{ + if(map.log == (FILE *)0) + return; + if(lab != (char *)0) + (void)fprintf(map.log," \"%s\"",lab); + else + (void)fprintf(map.log," unknown"); + if(lin != -1) + (void)fprintf(map.log," line:%d",lin); + if(siz != -1) + (void)fprintf(map.log," size:%d",siz); +} + + + + +/* print a symbol map entry with checks for closed log file */ +static void +psym(s) +struct sym *s; +{ + if(map.log == (FILE *)0) + return; + (void)fprintf(map.log," \"%s\"",s->labl); + if(s->lineno != -1) + (void)fprintf(map.log," line:%d",s->lineno); +} + + + + +/* output a warning message with checks for closed log file */ +static void +pmsg(s) +char *s; +{ + if(map.log == (FILE *)0) + return; + (void)fprintf(map.log,"%s",s); +} + + + + +/* save an entry to the .lines file */ +static void +savesym(s) +struct sym *s; +{ + if(map.fp == (FILE *)0) + return; + + (void)fprintf(map.fp,"%d\t%d\t%.1f\t%d\t%s\n", + s->mapno,s->mallcnt,s->avsiz,s->lineno,s->labl); +} + + + + +/* save an entry in the pointer map file */ +static void +saveptr(p) +register struct ptr *p; +{ + if(lseek(map.fd,(off_t)(p->map * sizeof(p->dsk)),0) != + (off_t)(p->map * sizeof(p->dsk))) { + pmsg("mnemosyne: cannot seek in pointer map file\n"); + rec_state |= REC_ERR; + return; + } + + if(write(map.fd,(char *)&(p->dsk),sizeof(p->dsk)) != sizeof(p->dsk)) { + pmsg("mnemosyne: cannot write in pointer map file\n"); + rec_state |= REC_ERR; + return; + } +} + + + + +/* initialize everything - symbol tables, files, and maps */ +static void +initmap() +{ + register int xp; + + if(rec_state & REC_INITTED) + return; + + if((map.fp = fopen(LINESFILE,"w")) == (FILE *)0) + return; + if((map.fd = open(PTRFILE,O_RDWR|O_CREAT|O_TRUNC,0600)) < 0) { + (void)fclose(map.fp); + return; + } + + map.log = stderr; + map.lmap = map.pmap = 0; + map.nalloc = map.nrlloc = map.nfree = map.nbfree = 0L; + map.ninuse = 0L; + map.avgsiz = 0.0; + + for(xp = 0; xp < HASHSIZ; xp++) { + map.phash[xp] = (struct ptr *)0; + map.shash[xp] = (struct sym *)0; + } + + rec_state = REC_INITTED | REC_ON; +} + + + + +/* set logging to a FILE * */ +void +mnem_setlog(fp) +FILE *fp; +{ + map.log = fp; +} + + + + +/* return state of the recorder */ +int +mnem_recording() +{ + return((rec_state & REC_ON) && !(rec_state & REC_ERR)); +} + + + + +/* turn on or off recording */ +int +mnem_setrecording(val) +int val; +{ + if(!(rec_state & REC_INITTED)) + initmap(); + + if(val) + rec_state |= REC_ON; + else + rec_state &= ~REC_ON; + + if(map.fp != (FILE *)0) + (void)fflush(map.fp); + + rec_state |= REC_ONOFF; + return(0); +} + + + + +/* lookup a pointer record - search pointer hash table */ +static struct ptr * +lookupptr(ptr) +mall_t ptr; +{ + register struct ptr *p; + + /* this probably give simply terrible hash performance */ + p = map.phash[(unsigned long)ptr % HASHSIZ]; + while(p != (struct ptr *)0) { + if(ptr == p->ptr) + return(p); + p = p->next; + } + return((struct ptr *)0); +} + + + + +/* + * polynomial conversion ignoring overflows + * [this seems to work remarkably well, in fact better + * then the ndbm hash function. Replace at your own risk] + * use: 65599 nice. + * 65587 even better. + * author: oz@nexus.yorku.ca + */ +static unsigned int +dbm_hash(str) +register char *str; +{ + register unsigned int n = 0; + + while(*str != '\0') + n = *str++ + 65599 * n; + return(n); +} + + + + +/* lookup a line/source entry by name (search hash table) */ +static struct sym * +lookupsymbyname(nam,lin) +char *nam; +int lin; +{ + register struct sym *s; + char *p = nam; + + if(p == (char *)0) + p = "unknown"; + + s = map.shash[(dbm_hash(p) + lin) % HASHSIZ]; + while(s != (struct sym *)0) { + if(!strcmp(s->labl,nam) && s->lineno == lin) + return(s); + s = s->next; + } + + return((struct sym *)0); +} + + + + +/* lookup a line/source entry by number (exhaustively search hash table) */ +static struct sym * +lookupsymbynum(num) +int num; +{ + register struct sym *s; + register int x; + + for(x = 0; x < HASHSIZ; x++) { + s = map.shash[x]; + while(s != (struct sym *)0) { + if(s->mapno == num) + return(s); + s = s->next; + } + } + return((struct sym *)0); +} + + + +/* stuff a pointer's value in the pointer map table */ +static void +storeptr(ptr,siz,lab,lin) +mall_t ptr; +int siz; +char *lab; +int lin; +{ + register struct ptr *p; + register struct sym *s; + int hv; + + /* + is there is no existing symbol entry for this line of code... + we must needs make one - and painful it is... + */ + if((s = lookupsymbyname(lab,lin)) == (struct sym *)0) { + s = (struct sym *)malloc(sizeof(struct sym)); + if(s == (struct sym *)0) { + pmsg("mnemosyne: cannot allocate sym entry\n"); + rec_state |= REC_ERR; + return; + } + + /* + this is funky - since we know the label is (?) + compiled-in, we can just keep a pointer to it, + rather than copying our own version of it. + */ + if(lab != (char *)0) + s->labl = lab; + else + s->labl = "unknown"; + + s->mapno = map.lmap++; + + /* add sym to hash table */ + s->next = map.shash[hv = ((dbm_hash(s->labl) + lin) % HASHSIZ)]; + map.shash[hv] = s; + + s->lineno = lin; + s->mallcnt = 1; + s->avsiz = siz; + savesym(s); + } else { + /* found an already defined symbol. store some averages */ + s->avsiz = ((s->avsiz * s->mallcnt) + siz) / (s->mallcnt + 1); + (s->mallcnt)++; + } + + p = lookupptr(ptr); + if(p != (struct ptr *)0 && p->dsk.siz != 0) { + struct sym *x; + + pmsg("pointer re-allocated without being freed"); + ploc(lab,lin,(int)siz); + if((x = lookupsymbynum(p->dsk.smap)) != (struct sym *)0) { + pmsg(" last allocated "); + psym(x); + } + pmsg("\n"); + } + + /* heavy sigh. no entry for this pointer. make one. */ + if(p == (struct ptr *)0) { + p = (struct ptr *)malloc(sizeof(struct ptr)); + if(p == (struct ptr *)0) { + pmsg("mnemosyne: cannot expand pointer table\n"); + rec_state |= REC_ERR; + return; + } + + /* link it in */ + p->next = map.phash[(unsigned long)ptr % HASHSIZ]; + map.phash[(unsigned long)ptr % HASHSIZ] = p; + } + + /* if we get to here (hazoo! hazaa!) both 's' and 'p' are OK */ + p->ptr = ptr; + p->dsk.siz = siz; + p->dsk.smap = s->mapno; + p->map = map.pmap++; + + /* store the size */ + map.ninuse += siz; + + saveptr(p); +} + + + + +/* +mark a pointer as now being free. note that a 1 is returned IF +the actual value should NOT be really passed to free() +*/ +static int +freeptr(ptr,lab,lin) +mall_t ptr; +char *lab; +int lin; +{ + register struct ptr *p; + + p = lookupptr(ptr); + if(p == (struct ptr *)0) { + pmsg("pointer freed that was never allocated"); + ploc(lab,lin,-1); + pmsg("\n"); + return(1); + } + + if(p != (struct ptr *)0 && p->dsk.siz == 0) { + struct sym *x; + + pmsg("pointer re-freed when already free"); + ploc(lab,lin,-1); + if((x = lookupsymbynum(p->dsk.smap)) != (struct sym *)0) { + pmsg(" last allocated:"); + psym(x); + } + pmsg("\n"); + return(1); + } + + /* get some free */ + map.ninuse -= p->dsk.siz; + + /* write in the map that it is free */ + p->dsk.siz = 0; + saveptr(p); + + return(0); +} + + + + +/* pretend we are malloc() */ +mall_t +mnem_malloc(siz,lab,lin) +unsigned siz; +char *lab; +int lin; +{ + mall_t ret; + + if(!(rec_state & REC_INITTED)) + initmap(); + + if((ret = malloc(siz)) == (mall_t)0) { + pmsg("malloc returned null pointer at"); + ploc(lab,lin,(int)siz); + pmsg("\n"); + return(ret); + } + + if((rec_state & REC_ON) && !(rec_state & REC_ERR)) + storeptr(ret,(int)siz,lab,lin); + + map.avgsiz = ((map.avgsiz * map.nalloc) + siz) / (map.nalloc + 1); + map.nalloc++; + return(ret); +} + + + + +/* pretend we are calloc() */ +mall_t +mnem_calloc(cnt,siz,lab,lin) +unsigned cnt; +unsigned siz; +char *lab; +int lin; +{ + mall_t ret; + + if(!(rec_state & REC_INITTED)) + initmap(); + + if((ret = calloc(cnt,siz)) == (mall_t)0) { + pmsg("calloc returned null pointer at"); + ploc(lab,lin,(int)(siz * cnt)); + pmsg("\n"); + return(ret); + } + + if((rec_state & REC_ON) && !(rec_state & REC_ERR)) + storeptr(ret,(int)(cnt * siz),lab,lin); + + map.avgsiz = ((map.avgsiz * map.nalloc) + siz) / (map.nalloc + 1); + map.nalloc++; + return(ret); +} + + + + +/* pretend we are realloc() */ +mall_t +mnem_realloc(ptr,siz,lab,lin) +mall_t ptr; +unsigned siz; +char *lab; +int lin; +{ + mall_t ret; + + if(!(rec_state & REC_INITTED)) + initmap(); + + if((ret = realloc(ptr,siz)) == (mall_t)0) { + pmsg("realloc returned null pointer at"); + ploc(lab,lin,(int)siz); + pmsg("\n"); + return(ret); + } + + if((rec_state & REC_ON) && !(rec_state & REC_ERR)) { + if(!freeptr(ptr,lab,lin)) + storeptr(ret,(int)siz,lab,lin); + } + + map.nrlloc++; + return(ret); +} + + + + + +/* pretend we are free() */ +void +mnem_free(ptr,lab,lin) +mall_t ptr; +char *lab; +int lin; +{ + if(!(rec_state & REC_INITTED)) + initmap(); + + if((rec_state & REC_ON) && !(rec_state & REC_ERR)) + if(freeptr(ptr,lab,lin) == 0) { + (void)free(ptr); + map.nfree++; + } else + map.nbfree++; +} + + + + +/* dump everything we know about nothing in particular */ +int +mnem_writestats() +{ + register struct sym *s; + register int x; + + if(map.fp == (FILE *)0) + return(-1); + + (void)fseek(map.fp,0L,0); + + /* dump our life's story */ + (void)fprintf(map.fp,"#total allocations:%ld\n",map.nalloc); + (void)fprintf(map.fp,"#total re-allocations:%ld\n",map.nrlloc); + (void)fprintf(map.fp,"#total frees:%ld\n",map.nfree); + + if(map.nbfree != 0L) + (void)fprintf(map.fp,"#bad/dup frees:%ld\n",map.nbfree); + + (void)fprintf(map.fp,"#total allocated never freed:%ld\n",map.ninuse); + + (void)fprintf(map.fp,"#average size of allocations:%.1f\n",map.avgsiz); + + /* note if we detected an internal error */ + if(rec_state & REC_ERR) + (void)fprintf(map.fp, + "#(figures likely inaccurate due to error)\n"); + + /* note if the system was on all the time ? */ + if(!(rec_state & REC_ON) || (rec_state & REC_ONOFF)) + (void)fprintf(map.fp, + "#(figures likely inaccurate as recording was off)\n"); + + /* write the legend */ + (void)fprintf(map.fp,"#map#\tcalls\tave\tline#\tfile\n"); + + for(x = 0; x < HASHSIZ; x++) { + s = map.shash[x]; + while(s != (struct sym *)0) { + savesym(s); + s = s->next; + } + } + + (void)fflush(map.fp); + return(0); +} diff --git a/distr/mnemosyne/mnemosyne.h b/distr/mnemosyne/mnemosyne.h new file mode 100644 index 0000000..910af91 --- /dev/null +++ b/distr/mnemosyne/mnemosyne.h @@ -0,0 +1,73 @@ +/************************************************************************ + * * + * Copyright (c) 1985 by * + * Digital Equipment Corporation, Maynard, MA * + * All rights reserved. * + * * + * The information in this software is subject to change without * + * notice and should not be construed as a commitment by Digital * + * Equipment Corporation. * + * * + * Digital assumes no responsibility for the use or reliability * + * of its software on equipment which is not supplied by Digital. * + * * + * Redistribution and use in source and binary forms are permitted * + * provided that the above copyright notice and this paragraph are * + * duplicated in all such forms and that any documentation, * + * advertising materials, and other materials related to such * + * distribution and use acknowledge that the software was developed * + * by Digital Equipment Corporation. The name of Digital Equipment * + * Corporation may not be used to endorse or promote products derived * + * from this software without specific prior written permission. * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR * + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.* + * Do not take internally. In case of accidental ingestion, contact * + * your physician immediately. * + * * + ************************************************************************/ + +#ifndef _INCL_MNEMOSYNE_H + +/* +/fats/tools/hsv/mnemosyne/mnemosyne.h,v 1.1.1.1 1995/06/06 18:18:28 fabio Exp +*/ + + +/* +main include file for the mnemosyne memory allocation tracker. this file +provides some pre-processor fakes for malloc(), realloc() and family, +as well as forward declarations for the mnemosyne functions. + + Marcus J. Ranum, 1990. (mjr@decuac.dec.com) +*/ + + +/* these disguise mnemosyne calls as calls to malloc and family */ +#ifndef NOFAKEMALLOC +#define malloc(siz) mnem_malloc(siz,__FILE__,__LINE__) +#define calloc(siz,cnt) mnem_calloc(siz,cnt,__FILE__,__LINE__) +#define realloc(ptr,siz) mnem_realloc(ptr,siz,__FILE__,__LINE__) +#define free(ptr) mnem_free(ptr,__FILE__,__LINE__) +#endif + + +#ifdef MALLOC_IS_VOIDSTAR +typedef void *mall_t; +#else +typedef char *mall_t; +#endif + +extern mall_t mnem_malloc(); +extern mall_t mnem_calloc(); +extern mall_t mnem_realloc(); +extern void mnem_free(); + +/* some internal functions and oddimentia */ +extern int mnem_recording(); +extern int mnem_setrecording(); +extern void mnem_setlog(); +extern int mnem_writestats(); + +#define _INCL_MNEMOSYNE_H +#endif diff --git a/distr/mnemosyne/mtest.c b/distr/mnemosyne/mtest.c new file mode 100644 index 0000000..5a51a0a --- /dev/null +++ b/distr/mnemosyne/mtest.c @@ -0,0 +1,38 @@ +#include "mnemosyne.h" + +static char rcsid[] = "/fats/tools/hsv/mnemosyne/mtest.c,v 1.1.1.1 1995/06/06 18:18:27 fabio Exp"; + +/* +test harness/demo of mnemosyne library. deliberately leaks memory on the +floor, double frees, frees unallocated memory, etc. + + Marcus J. Ranum, 1990. (mjr@decuac.dec.com) +*/ + + +main() +{ + char *d = "foobar"; + char *xx; + int x; + + xx = malloc(922); + xx = malloc(123); + + /* huh ? */ + xx = malloc(-9); + + /* waste some memory */ + for(x = 1; x < 8; x++) + xx = malloc(x); + + /* free something we don't own */ + free(d); + + /* double free something */ + free(xx); + free(xx); + + /* not necessary - this triggers a better printout of statistics */ + mnem_writestats(); +} diff --git a/distr/mtr/Makefile b/distr/mtr/Makefile new file mode 100644 index 0000000..b62b7c5 --- /dev/null +++ b/distr/mtr/Makefile @@ -0,0 +1,96 @@ +# $Id: Makefile,v 1.2 1994/10/03 23:30:34 fabio Exp fabio $ +# +# mtr - multiway-branching tree package +#--------------------------- +.SUFFIXES: .o .c .u + +CC = cc +RANLIB = ranlib +PURE = +# Define EXE as .exe for MS-DOS and derivatives. +EXE = +#EXE = .exe + +MFLAG = +ICFLAGS = -g +CFLAGS = $(ICFLAGS) $(MFLAG) $(XCFLAGS) +MTRDEBUG = -DMTR_STATS -DMTR_VERBOSE -DMTR_DEBUG + +LINTFLAGS = -u -n -DMTR_STATS -DMTR_VERBOSE -DMTR_DEBUG + +# this is to create the lint library +LINTSWITCH = -o + +LDFLAGS = + +WHERE = .. + +INCLUDE = $(WHERE)/include + +P = mtr +PSRC = mtrBasic.c mtrGroup.c +PHDR = mtr.h +POBJ = $(PSRC:.c=.o) +PUBJ = $(PSRC:.c=.u) +SRC = test$(P).c +HDR = +OBJ = $(SRC:.c=.o) +UBJ = $(SRC:.c=.u) +TARGET = test$(P)$(EXE) +TARGETu = test$(P)-u + +LIBS = ./libmtr.a $(WHERE)/util/libutil.a + +BLIBS = -kL. -klmtr -kL$(WHERE)/util -klutil + +MNEMLIB = + +LINTLIBS = llib-l$(P).ln + +#--------------------------- + +lib$(P).a: $(POBJ) + ar rv $@ $? + $(RANLIB) $@ + +.c.o: $(PSRC) $(PHDR) + $(CC) -c $< -I$(INCLUDE) $(CFLAGS) $(MTRDEBUG) + +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) + +lint: llib-l$(P).ln + +llib-l$(P).ln: $(PSRC) $(PHDR) + lint $(LINTFLAGS) $(LINTSWITCH)$(P) -I$(INCLUDE) $(PSRC) + +tags: $(PSRC) $(PHDR) + ctags $(PSRC) $(PHDR) + +all: lib$(P).a lib$(P).b llib-l$(P).ln tags + +$(TARGET): $(POBJ) $(OBJ) $(LIBS) $(MNEMLIB) + $(PURE) $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(OBJ) $(LIBS) $(MNEMLIB) -lm + +$(TARGETu): $(SRC) $(PSRC) $(PHDR) $(UBJ) $(PUBJ) $(LIBS:.a=.b) + cc -O3 $(XCFLAGS) $(LDFLAGS) -o $@ $(UBJ) $(BLIBS) -lm + +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 *.qv *.qx diff --git a/distr/mtr/Makefile.sis b/distr/mtr/Makefile.sis new file mode 100644 index 0000000..d920cab --- /dev/null +++ b/distr/mtr/Makefile.sis @@ -0,0 +1,83 @@ +# $Id$ +# +# Cudd - DD package +#--------------------------- +.SUFFIXES: .o .c .u + +RANLIB = ranlib + +CAD = /projects/octtools/octtools/$(MACHINE) +SIS = .. +LINTCREATEFLAG = -C + +# files for the package +P = mtr +PSRC = mtrBasic.c mtrGroup.c +PHDR = mtr.h +POBJ = $(PSRC:.c=.o) + +# files for the test program +TARGET = test$(P) +SRC = test$(P).c +OBJ = $(SRC:.c=.o) +HDR = + +LIBS = ../util/libutil.a +LINTLIBS= ../util/llib-lutil.ln +INCLUDE = -I$(CAD)/include -I$(SIS)/include + +CFLAGS = -g $(INCLUDE) +LDFLAGS = -g +LINTFLAGS = $(INCLUDE) ${LINTEXTRAS} + +#------------------------------------------------------ + +$(TARGET): $(PHDR) $(OBJ) $(POBJ) $(LIBS) + $(CC) $(LDFLAGS) -o $(TARGET) $(OBJ) $(POBJ) $(LIBS) + +lint: $(PSRC) $(PHDR) $(SRC) $(HDR) + lint $(LINTFLAGS) $(SRC) $(PSRC) $(LINTLIBS) + +install: lib$(P).a llib-l$(P).ln + +lib$(P).a: $(POBJ) + ar cr $@ $? + $(RANLIB) $@ + +unpack: lib$(P).a + @for i in $(POBJ); do \ + ln -s $(SIS)/$(P)/$$i $(SIS)/unpack; \ + done + +llib-l$(P).ln: $(PSRC) $(PHDR) + lint $(LINTFLAGS) ${LINTCREATEFLAG}$(P) -n $(PSRC) + +clean: + rm -f $(TARGET) *.a *.ln *.o \ + [Tt]ags [Mm]ake.out lint malloc.out gmon.out __.SYMDEF + +tags: _force + @for i in $(PSRC) $(PHDR); do \ + cwd=`pwd`; ctags -a $$cwd/$$i; + done; + +strip_depend: + sed '/^#--DO NOT CHANGE ANYTHING AFTER THIS LINE/,$$d' Makefile >mktemp + mv mktemp Makefile + +depend: + sed '/^#--DO NOT CHANGE ANYTHING AFTER THIS LINE/,$$d' Makefile >mktemp + echo '#--DO NOT CHANGE ANYTHING AFTER THIS LINE' >>mktemp + $(CAD)/bin/cc-M $(CFLAGS) $(PSRC) | \ + sed 's|$(CAD)|$$(CAD)|g' | \ + grep -v '/usr/include' >>mktemp + mv mktemp Makefile + +#-------------------------- IBM 3090 support ----------------- +IBMHOST = opua +IBMDIST = /users2/sis +ibmdist: $(PSRC) $(PHDR) + rdist -Richw $(PSRC) $(PHDR) $(IBMHOST):$(IBMDIST) +#------------------------------------------------------------- +_force: + diff --git a/distr/mtr/doc/mtr.doc b/distr/mtr/doc/mtr.doc new file mode 100644 index 0000000..2815d29 --- /dev/null +++ b/distr/mtr/doc/mtr.doc @@ -0,0 +1,252 @@ +The mtr package + +Multiway-branch tree manipulation + +Fabio Somenzi + +********************************************************************** + +Mtr_AllocNode() Allocates new tree node. + +Mtr_CopyTree() Makes a copy of tree. + +Mtr_CreateFirstChild() Creates a new node and makes it the first child + of parent. + +Mtr_CreateLastChild() Creates a new node and makes it the last child + of parent. + +Mtr_DeallocNode() Deallocates tree node. + +Mtr_DissolveGroup() Merges the children of `group' with the + children of its parent. + +Mtr_FindGroup() Finds a group with size leaves starting at low, + if it exists. + +Mtr_FreeTree() Disposes of tree rooted at node. + +Mtr_InitGroupTree() Allocate new tree. + +Mtr_InitTree() Initializes tree with one node. + +Mtr_MakeFirstChild() Makes child the first child of parent. + +Mtr_MakeGroup() Makes a new group with size leaves starting at + low. + +Mtr_MakeLastChild() Makes child the last child of parent. + +Mtr_MakeNextSibling() Makes second the next sibling of first. + +Mtr_PrintGroups() Prints the groups as a parenthesized list. + +Mtr_PrintTree() Prints a tree, one node per line. + +Mtr_ReadGroups() Reads groups from a file and creates a group + tree. + +Mtr_SwapGroups() Swaps two children of a tree node. + +********************************************************************** + +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. 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. + +MtrNode * +Mtr_AllocNode( + +) + Allocates new tree node. Returns pointer to node. + + Side Effects: None + +MtrNode * +Mtr_CopyTree( + MtrNode * node, + int expansion +) + 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. + + Side Effects: None + +MtrNode * +Mtr_CreateFirstChild( + MtrNode * parent +) + Creates a new node and makes it the first child of parent. Returns pointer + to new child. + + Side Effects: None + +MtrNode * +Mtr_CreateLastChild( + MtrNode * parent +) + Creates a new node and makes it the last child of parent. Returns pointer to + new child. + + Side Effects: None + +void +Mtr_DeallocNode( + MtrNode * node node to be deallocated +) + Deallocates tree node. + + Side Effects: None + +MtrNode * +Mtr_DissolveGroup( + MtrNode * group group to be dissolved +) + 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. + + Side Effects: None + +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 +) + 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. + + Side Effects: None + +void +Mtr_FreeTree( + MtrNode * node +) + Disposes of tree rooted at node. + + Side Effects: None + +MtrNode * +Mtr_InitGroupTree( + int lower, + int size +) + Allocate new tree with one node, whose low and size fields are specified by + the lower and size parameters. Returns pointer to tree root. + + Side Effects: None + +MtrNode * +Mtr_InitTree( + +) + Initializes tree with one node. Returns pointer to node. + + Side Effects: None + +void +Mtr_MakeFirstChild( + MtrNode * parent, + MtrNode * child +) + Makes child the first child of parent. + + Side Effects: None + +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 +) + 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. + + Side Effects: None + +void +Mtr_MakeLastChild( + MtrNode * parent, + MtrNode * child +) + Makes child the last child of parent. + + Side Effects: None + +void +Mtr_MakeNextSibling( + MtrNode * first, + MtrNode * second +) + Makes second the next sibling of first. Second becomes a child of the parent + of first. + + Side Effects: None + +void +Mtr_PrintGroups( + MtrNode * root, root of the group tree + int silent flag to check tree syntax only +) + 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. F: MTR_FIXED N: MTR_NEWNODE S: + MTR_SOFT The second argument, silent, if different from 0, causes + Mtr_PrintGroups to only check the syntax of the group tree. + + Side Effects: None + +void +Mtr_PrintTree( + MtrNode * node +) + Prints a tree, one node per line. + + Side Effects: None + +MtrNode * +Mtr_ReadGroups( + FILE * fp, file pointer + int nleaves number of leaves of the new tree +) + Reads groups from a file and creates a group tree. Each group is specified + by three fields: low size flags. Low and size are (short) + integers. Flags is a string composed of the following characters (with + associated translation): D: MTR_DEFAULT F: MTR_FIXED N: + MTR_NEWNODE S: MTR_SOFT T: MTR_TERMINAL 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. + + Side Effects: None + +int +Mtr_SwapGroups( + MtrNode * first, first node to be swapped + MtrNode * second second node to be swapped +) + 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. + + Side Effects: None + diff --git a/distr/mtr/doc/mtrAllAbs.html b/distr/mtr/doc/mtrAllAbs.html new file mode 100644 index 0000000..9a59faa --- /dev/null +++ b/distr/mtr/doc/mtrAllAbs.html @@ -0,0 +1,72 @@ + +mtr package abstract (Internal) + + +

          mtr package abstract (Internal)

          +

          Internal data structures of the mtr package

          +
          + + + +
          +
          Mtr_AllocNode() +
          Allocates new tree node. + +
          Mtr_CopyTree() +
          Makes a copy of tree. + +
          Mtr_CreateFirstChild() +
          Creates a new node and makes it the first child of parent. + +
          Mtr_CreateLastChild() +
          Creates a new node and makes it the last child of parent. + +
          Mtr_DeallocNode() +
          Deallocates tree node. + +
          Mtr_DissolveGroup() +
          Merges the children of `group' with the children of its parent. + +
          Mtr_FindGroup() +
          Finds a group with size leaves starting at low, if it exists. + +
          Mtr_FreeTree() +
          Disposes of tree rooted at node. + +
          Mtr_InitGroupTree() +
          Allocate new tree. + +
          Mtr_InitTree() +
          Initializes tree with one node. + +
          Mtr_MakeFirstChild() +
          Makes child the first child of parent. + +
          Mtr_MakeGroup() +
          Makes a new group with size leaves starting at low. + +
          Mtr_MakeLastChild() +
          Makes child the last child of parent. + +
          Mtr_MakeNextSibling() +
          Makes second the next sibling of first. + +
          Mtr_PrintGroups() +
          Prints the groups as a parenthesized list. + +
          Mtr_PrintTree() +
          Prints a tree, one node per line. + +
          Mtr_ReadGroups() +
          Reads groups from a file and creates a group tree. + +
          Mtr_SwapGroups() +
          Swaps two children of a tree node. + +
          + +
          + +Generated automatically by extdoc on 970123 + + diff --git a/distr/mtr/doc/mtrAllDet.html b/distr/mtr/doc/mtrAllDet.html new file mode 100644 index 0000000..e7b7890 --- /dev/null +++ b/distr/mtr/doc/mtrAllDet.html @@ -0,0 +1,317 @@ + +The mtr package (Internal) + + +

          The mtr package (Internal)

          +

          Internal data structures of the mtr package

          +

          +
          + + +
          + + +In this package all definitions are external. + + +
          + + +
          + +
          +MtrNode * 
          +Mtr_AllocNode(
          +    
          +)
          +
          +
          Allocates new tree node. Returns pointer to node. +

          + +

          Side Effects None +

          + +

          See Also Mtr_DeallocNode + + +
          +MtrNode * 
          +Mtr_CopyTree(
          +  MtrNode * node, 
          +  int  expansion 
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          See Also Mtr_InitTree + + +
          +MtrNode * 
          +Mtr_CreateFirstChild(
          +  MtrNode * parent 
          +)
          +
          +
          Creates a new node and makes it the first child of parent. Returns pointer to new child. +

          + +

          Side Effects None +

          + +

          See Also Mtr_MakeFirstChild +Mtr_CreateLastChild + + +
          +MtrNode * 
          +Mtr_CreateLastChild(
          +  MtrNode * parent 
          +)
          +
          +
          Creates a new node and makes it the last child of parent. Returns pointer to new child. +

          + +

          Side Effects None +

          + +

          See Also Mtr_MakeLastChild +Mtr_CreateFirstChild + + +
          +void 
          +Mtr_DeallocNode(
          +  MtrNode * node node to be deallocated
          +)
          +
          +
          Deallocates tree node. +

          + +

          Side Effects None +

          + +

          See Also Mtr_AllocNode + + +
          +MtrNode * 
          +Mtr_DissolveGroup(
          +  MtrNode * group group to be dissolved
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          See Also Mtr_MakeGroup + + +
          +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
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          +void 
          +Mtr_FreeTree(
          +  MtrNode * node 
          +)
          +
          +
          Disposes of tree rooted at node. +

          + +

          Side Effects None +

          + +

          See Also Mtr_InitTree + + +
          +MtrNode * 
          +Mtr_InitGroupTree(
          +  int  lower, 
          +  int  size 
          +)
          +
          +
          Allocate new tree with one node, whose low and size fields are specified by the lower and size parameters. Returns pointer to tree root. +

          + +

          Side Effects None +

          + +

          See Also Mtr_InitTree +Mtr_FreeTree + + +
          +MtrNode * 
          +Mtr_InitTree(
          +    
          +)
          +
          +
          Initializes tree with one node. Returns pointer to node. +

          + +

          Side Effects None +

          + +

          See Also Mtr_FreeTree +Mtr_InitGroupTree + + +
          +void 
          +Mtr_MakeFirstChild(
          +  MtrNode * parent, 
          +  MtrNode * child 
          +)
          +
          +
          Makes child the first child of parent. +

          + +

          Side Effects None +

          + +

          See Also Mtr_MakeLastChild +Mtr_CreateFirstChild + + +
          +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
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          See Also Mtr_DissolveGroup +Mtr_ReadGroups +Mtr_FindGroup + + +
          +void 
          +Mtr_MakeLastChild(
          +  MtrNode * parent, 
          +  MtrNode * child 
          +)
          +
          +
          Makes child the last child of parent. +

          + +

          Side Effects None +

          + +

          See Also Mtr_MakeFirstChild +Mtr_CreateLastChild + + +
          +void 
          +Mtr_MakeNextSibling(
          +  MtrNode * first, 
          +  MtrNode * second 
          +)
          +
          +
          Makes second the next sibling of first. Second becomes a child of the parent of first. +

          + +

          Side Effects None +

          + +

          +void 
          +Mtr_PrintGroups(
          +  MtrNode * root, root of the group tree
          +  int  silent flag to check tree syntax only
          +)
          +
          +
          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.
          • F: MTR_FIXED
          • N: MTR_NEWNODE
          • S: MTR_SOFT
          The second argument, silent, if different from 0, causes Mtr_PrintGroups to only check the syntax of the group tree. +

          + +

          Side Effects None +

          + +

          See Also Mtr_PrintTree + + +
          +void 
          +Mtr_PrintTree(
          +  MtrNode * node 
          +)
          +
          +
          Prints a tree, one node per line. +

          + +

          Side Effects None +

          + +

          See Also Mtr_PrintGroups + + +
          +MtrNode * 
          +Mtr_ReadGroups(
          +  FILE * fp, file pointer
          +  int  nleaves number of leaves of the new tree
          +)
          +
          +
          Reads groups from a file and creates a group tree. Each group is specified by three fields: low size flags. Low and size are (short) integers. Flags is a string composed of the following characters (with associated translation):
          • D: MTR_DEFAULT
          • F: MTR_FIXED
          • N: MTR_NEWNODE
          • S: MTR_SOFT
          • T: MTR_TERMINAL
          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. +

          + +

          Side Effects None +

          + +

          See Also Mtr_InitGroupTree +Mtr_MakeGroup + + +
          +int 
          +Mtr_SwapGroups(
          +  MtrNode * first, first node to be swapped
          +  MtrNode * second second node to be swapped
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + + +

          + +
          + +Generated automatically by extdoc on 970123 + + diff --git a/distr/mtr/doc/mtrExtAbs.html b/distr/mtr/doc/mtrExtAbs.html new file mode 100644 index 0000000..9f48acb --- /dev/null +++ b/distr/mtr/doc/mtrExtAbs.html @@ -0,0 +1,72 @@ + +mtr package abstract + + +

          mtr package abstract

          +

          Multiway-branch tree manipulation

          +
          + + + +
          +
          Mtr_AllocNode() +
          Allocates new tree node. + +
          Mtr_CopyTree() +
          Makes a copy of tree. + +
          Mtr_CreateFirstChild() +
          Creates a new node and makes it the first child of parent. + +
          Mtr_CreateLastChild() +
          Creates a new node and makes it the last child of parent. + +
          Mtr_DeallocNode() +
          Deallocates tree node. + +
          Mtr_DissolveGroup() +
          Merges the children of `group' with the children of its parent. + +
          Mtr_FindGroup() +
          Finds a group with size leaves starting at low, if it exists. + +
          Mtr_FreeTree() +
          Disposes of tree rooted at node. + +
          Mtr_InitGroupTree() +
          Allocate new tree. + +
          Mtr_InitTree() +
          Initializes tree with one node. + +
          Mtr_MakeFirstChild() +
          Makes child the first child of parent. + +
          Mtr_MakeGroup() +
          Makes a new group with size leaves starting at low. + +
          Mtr_MakeLastChild() +
          Makes child the last child of parent. + +
          Mtr_MakeNextSibling() +
          Makes second the next sibling of first. + +
          Mtr_PrintGroups() +
          Prints the groups as a parenthesized list. + +
          Mtr_PrintTree() +
          Prints a tree, one node per line. + +
          Mtr_ReadGroups() +
          Reads groups from a file and creates a group tree. + +
          Mtr_SwapGroups() +
          Swaps two children of a tree node. + +
          + +
          + +Generated automatically by extdoc on 970123 + + diff --git a/distr/mtr/doc/mtrExtDet.html b/distr/mtr/doc/mtrExtDet.html new file mode 100644 index 0000000..8300c3d --- /dev/null +++ b/distr/mtr/doc/mtrExtDet.html @@ -0,0 +1,324 @@ + +The mtr package + + +

          The mtr package

          +

          Multiway-branch tree manipulation

          +

          +
          + + +
          + + +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.

          + 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. + + +


          + + +
          + +
          +MtrNode * 
          +Mtr_AllocNode(
          +    
          +)
          +
          +
          Allocates new tree node. Returns pointer to node. +

          + +

          Side Effects None +

          + +

          See Also Mtr_DeallocNode + + +
          +MtrNode * 
          +Mtr_CopyTree(
          +  MtrNode * node, 
          +  int  expansion 
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          See Also Mtr_InitTree + + +
          +MtrNode * 
          +Mtr_CreateFirstChild(
          +  MtrNode * parent 
          +)
          +
          +
          Creates a new node and makes it the first child of parent. Returns pointer to new child. +

          + +

          Side Effects None +

          + +

          See Also Mtr_MakeFirstChild +Mtr_CreateLastChild + + +
          +MtrNode * 
          +Mtr_CreateLastChild(
          +  MtrNode * parent 
          +)
          +
          +
          Creates a new node and makes it the last child of parent. Returns pointer to new child. +

          + +

          Side Effects None +

          + +

          See Also Mtr_MakeLastChild +Mtr_CreateFirstChild + + +
          +void 
          +Mtr_DeallocNode(
          +  MtrNode * node node to be deallocated
          +)
          +
          +
          Deallocates tree node. +

          + +

          Side Effects None +

          + +

          See Also Mtr_AllocNode + + +
          +MtrNode * 
          +Mtr_DissolveGroup(
          +  MtrNode * group group to be dissolved
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          See Also Mtr_MakeGroup + + +
          +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
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          +void 
          +Mtr_FreeTree(
          +  MtrNode * node 
          +)
          +
          +
          Disposes of tree rooted at node. +

          + +

          Side Effects None +

          + +

          See Also Mtr_InitTree + + +
          +MtrNode * 
          +Mtr_InitGroupTree(
          +  int  lower, 
          +  int  size 
          +)
          +
          +
          Allocate new tree with one node, whose low and size fields are specified by the lower and size parameters. Returns pointer to tree root. +

          + +

          Side Effects None +

          + +

          See Also Mtr_InitTree +Mtr_FreeTree + + +
          +MtrNode * 
          +Mtr_InitTree(
          +    
          +)
          +
          +
          Initializes tree with one node. Returns pointer to node. +

          + +

          Side Effects None +

          + +

          See Also Mtr_FreeTree +Mtr_InitGroupTree + + +
          +void 
          +Mtr_MakeFirstChild(
          +  MtrNode * parent, 
          +  MtrNode * child 
          +)
          +
          +
          Makes child the first child of parent. +

          + +

          Side Effects None +

          + +

          See Also Mtr_MakeLastChild +Mtr_CreateFirstChild + + +
          +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
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + +

          See Also Mtr_DissolveGroup +Mtr_ReadGroups +Mtr_FindGroup + + +
          +void 
          +Mtr_MakeLastChild(
          +  MtrNode * parent, 
          +  MtrNode * child 
          +)
          +
          +
          Makes child the last child of parent. +

          + +

          Side Effects None +

          + +

          See Also Mtr_MakeFirstChild +Mtr_CreateLastChild + + +
          +void 
          +Mtr_MakeNextSibling(
          +  MtrNode * first, 
          +  MtrNode * second 
          +)
          +
          +
          Makes second the next sibling of first. Second becomes a child of the parent of first. +

          + +

          Side Effects None +

          + +

          +void 
          +Mtr_PrintGroups(
          +  MtrNode * root, root of the group tree
          +  int  silent flag to check tree syntax only
          +)
          +
          +
          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.
          • F: MTR_FIXED
          • N: MTR_NEWNODE
          • S: MTR_SOFT
          The second argument, silent, if different from 0, causes Mtr_PrintGroups to only check the syntax of the group tree. +

          + +

          Side Effects None +

          + +

          See Also Mtr_PrintTree + + +
          +void 
          +Mtr_PrintTree(
          +  MtrNode * node 
          +)
          +
          +
          Prints a tree, one node per line. +

          + +

          Side Effects None +

          + +

          See Also Mtr_PrintGroups + + +
          +MtrNode * 
          +Mtr_ReadGroups(
          +  FILE * fp, file pointer
          +  int  nleaves number of leaves of the new tree
          +)
          +
          +
          Reads groups from a file and creates a group tree. Each group is specified by three fields: low size flags. Low and size are (short) integers. Flags is a string composed of the following characters (with associated translation):
          • D: MTR_DEFAULT
          • F: MTR_FIXED
          • N: MTR_NEWNODE
          • S: MTR_SOFT
          • T: MTR_TERMINAL
          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. +

          + +

          Side Effects None +

          + +

          See Also Mtr_InitGroupTree +Mtr_MakeGroup + + +
          +int 
          +Mtr_SwapGroups(
          +  MtrNode * first, first node to be swapped
          +  MtrNode * second second node to be swapped
          +)
          +
          +
          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. +

          + +

          Side Effects None +

          + + +

          + +
          + +Generated automatically by extdoc on 970123 + + diff --git a/distr/mtr/mtr.h b/distr/mtr/mtr.h new file mode 100644 index 0000000..d8f2f92 --- /dev/null +++ b/distr/mtr/mtr.h @@ -0,0 +1,191 @@ +/**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.

          + 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 __MTR +#define __MTR + +/*---------------------------------------------------------------------------*/ +/* Nested includes */ +/*---------------------------------------------------------------------------*/ + +#ifdef __cplusplus +extern "C" { +#endif + +/*---------------------------------------------------------------------------*/ +/* 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***************************************************************/ + +#ifdef __cplusplus +} +#endif + +#endif /* __MTR */ diff --git a/distr/mtr/mtrBasic.c b/distr/mtr/mtrBasic.c new file mode 100644 index 0000000..7c49025 --- /dev/null +++ b/distr/mtr/mtrBasic.c @@ -0,0 +1,450 @@ +/**CFile*********************************************************************** + + FileName [mtrBasic.c] + + PackageName [mtr] + + Synopsis [Basic manipulation of multiway branching trees.] + + Description [External procedures included in this module: +

            +
          • Mtr_AllocNode() +
          • Mtr_DeallocNode() +
          • Mtr_InitTree() +
          • Mtr_FreeTree() +
          • Mtr_CopyTree() +
          • Mtr_MakeFirstChild() +
          • Mtr_MakeLastChild() +
          • Mtr_CreateFirstChild() +
          • Mtr_CreateLastChild() +
          • Mtr_MakeNextSibling() +
          • Mtr_PrintTree() +
          + ] + + 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 "util.h" +#include "mtrInt.h" + + +/*---------------------------------------------------------------------------*/ +/* 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 = 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 */) +{ + 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 */ +/*---------------------------------------------------------------------------*/ diff --git a/distr/mtr/mtrGroup.c b/distr/mtr/mtrGroup.c new file mode 100644 index 0000000..4393211 --- /dev/null +++ b/distr/mtr/mtrGroup.c @@ -0,0 +1,730 @@ +/**CFile*********************************************************************** + + FileName [mtrGroup.c] + + PackageName [mtr] + + Synopsis [Functions to support group specification for reordering.] + + Description [External procedures included in this module: +
            +
          • Mtr_InitGroupTree() +
          • Mtr_MakeGroup() +
          • Mtr_DissolveGroup() +
          • Mtr_FindGroup() +
          • Mtr_SwapGroups() +
          • Mtr_PrintGroups() +
          • Mtr_ReadGroups() +
          + Static procedures included in this module: +
            +
          • mtrShiftHL +
          + ] + + 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 "util.h" +#include "mtrInt.h" + +/*---------------------------------------------------------------------------*/ +/* 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. +
            +
          • F: MTR_FIXED +
          • N: MTR_NEWNODE +
          • S: MTR_SOFT +
          + 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: + + low size flags. + + Low and size are (short) integers. Flags is a string composed of the + following characters (with associated translation): +
            +
          • D: MTR_DEFAULT +
          • F: MTR_FIXED +
          • N: MTR_NEWNODE +
          • S: MTR_SOFT +
          • T: MTR_TERMINAL +
          + 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 */ diff --git a/distr/mtr/mtrInt.h b/distr/mtr/mtrInt.h new file mode 100644 index 0000000..8d6e800 --- /dev/null +++ b/distr/mtr/mtrInt.h @@ -0,0 +1,92 @@ +/**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 _MTRINT +#define _MTRINT + +#include "mtr.h" + +/*---------------------------------------------------------------------------*/ +/* Nested includes */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Constant declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Stucture declarations */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Type declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Variable declarations */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Macro declarations */ +/*---------------------------------------------------------------------------*/ + +/**AutomaticStart*************************************************************/ + +/*---------------------------------------------------------------------------*/ +/* Function prototypes */ +/*---------------------------------------------------------------------------*/ + + +/**AutomaticEnd***************************************************************/ + +#endif /* _MTRINT */ diff --git a/distr/mtr/test.groups b/distr/mtr/test.groups new file mode 100644 index 0000000..fbedcaf --- /dev/null +++ b/distr/mtr/test.groups @@ -0,0 +1,5 @@ +0 6 D +6 6 F +0 2 D +2 2 D +4 2 D diff --git a/distr/mtr/testmtr.c b/distr/mtr/testmtr.c new file mode 100644 index 0000000..632d76c --- /dev/null +++ b/distr/mtr/testmtr.c @@ -0,0 +1,270 @@ +/**CFile*********************************************************************** + + FileName [testmtr.c] + + PackageName [mtr] + + Synopsis [Test program for the mtr 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.] + +******************************************************************************/ + +#include "util.h" +#include "mtr.h" + +/*---------------------------------------------------------------------------*/ +/* Variable declarations */ +/*---------------------------------------------------------------------------*/ + +#ifndef lint +static char rcsid[] MTR_UNUSED = "$Id: testmtr.c,v 1.3 2004/08/13 18:15:12 fabio Exp $"; +#endif + +/*---------------------------------------------------------------------------*/ +/* Constant declarations */ +/*---------------------------------------------------------------------------*/ + +#define TESTMTR_VERSION\ + "TestMtr Version #0.5, Release date 8/26/99" + +/**AutomaticStart*************************************************************/ + +/*---------------------------------------------------------------------------*/ +/* Static function prototypes */ +/*---------------------------------------------------------------------------*/ + +static void usage (char *prog); +static FILE * open_file (char *filename, char *mode); + +/**AutomaticEnd***************************************************************/ + +/*---------------------------------------------------------------------------*/ +/* Definition of exported functions */ +/*---------------------------------------------------------------------------*/ + +/**Function******************************************************************** + + Synopsis [Main program for testmtr.] + + Description [Main program for testmtr. Performs initialization. + Reads command line options and network(s). Builds some simple trees + and prints them out.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +int +main( + int argc, + char ** argv) +{ + MtrNode *root, + *node; + int i, + c, + pr = 0; + FILE *fp; + char *file = NULL; + + (void) printf("# %s\n", TESTMTR_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); + + while ((c = getopt(argc, argv, "Mhp:")) != EOF) { + switch(c) { + case 'M': +#ifdef MNEMOSYNE + (void) mnem_setrecording(0); +#endif + break; + case 'p': + pr = atoi(optarg); + break; + case 'h': + default: + usage(argv[0]); + break; + } + } + + if (argc - optind == 0) { + file = "-"; + } else if (argc - optind == 1) { + file = argv[optind]; + } else { + usage(argv[0]); + } + + /* Create and print a simple tree. */ + root = Mtr_InitTree(); + root->flags = 0; + node = Mtr_CreateFirstChild(root); + node->flags = 1; + node = Mtr_CreateLastChild(root); + node->flags = 2; + node = Mtr_CreateFirstChild(root); + node->flags = 3; + node = Mtr_AllocNode(); + node->flags = 4; + Mtr_MakeNextSibling(root->child,node); + Mtr_PrintTree(root); + Mtr_FreeTree(root); + (void) printf("#------------------------\n"); + + /* Create an initial tree in which all variables belong to one group. */ + root = Mtr_InitGroupTree(0,12); + Mtr_PrintTree(root); (void) printf("# "); + Mtr_PrintGroups(root,pr == 0); (void) printf("\n"); + node = Mtr_MakeGroup(root,0,6,MTR_DEFAULT); + node = Mtr_MakeGroup(root,6,6,MTR_DEFAULT); + Mtr_PrintTree(root); (void) printf("# "); + Mtr_PrintGroups(root,pr == 0); (void) printf("\n"); + for (i = 0; i < 6; i+=2) { + node = Mtr_MakeGroup(root,(unsigned) i,(unsigned) 2,MTR_DEFAULT); + } + node = Mtr_MakeGroup(root,0,12,MTR_FIXED); + Mtr_PrintTree(root); (void) printf("# "); + Mtr_PrintGroups(root,pr == 0); (void) printf("\n"); + /* Print a partial tree. */ + (void) printf("# "); + Mtr_PrintGroups(root->child,pr == 0); (void) printf("\n"); + node = Mtr_FindGroup(root,0,6); + node = Mtr_DissolveGroup(node); + Mtr_PrintTree(root); (void) printf("# "); + Mtr_PrintGroups(root,pr == 0); (void) printf("\n"); + node = Mtr_FindGroup(root,4,2); + if (!Mtr_SwapGroups(node,node->younger)) { + (void) printf("error in Mtr_SwapGroups\n"); + exit(3); + } + Mtr_PrintTree(root); (void) printf("# "); + Mtr_PrintGroups(root,pr == 0); + Mtr_FreeTree(root); + (void) printf("#------------------------\n"); + + /* Create a group tree with fixed subgroups. */ + root = Mtr_InitGroupTree(0,4); + Mtr_PrintTree(root); (void) printf("# "); + Mtr_PrintGroups(root,pr == 0); (void) printf("\n"); + node = Mtr_MakeGroup(root,0,2,MTR_FIXED); + node = Mtr_MakeGroup(root,2,2,MTR_FIXED); + Mtr_PrintTree(root); (void) printf("# "); + Mtr_PrintGroups(root,pr == 0); (void) printf("\n"); + Mtr_FreeTree(root); + (void) printf("#------------------------\n"); + + /* Open input file. */ + fp = open_file(file, "r"); + root = Mtr_ReadGroups(fp,12); + Mtr_PrintTree(root); (void) printf("# "); + Mtr_PrintGroups(root,pr == 0); (void) printf("\n"); + + Mtr_FreeTree(root); + +#ifdef MNEMOSYNE + mnem_writestats(); +#endif + + exit(0); + /* NOTREACHED */ + +} /* end of main */ + + +/**Function******************************************************************** + + Synopsis [Prints usage message and exits.] + + Description [] + + SideEffects [none] + + SeeAlso [] + +******************************************************************************/ +static void +usage( + char * prog) +{ + (void) fprintf(stderr, "usage: %s [options] [file]\n", prog); + (void) fprintf(stderr, " -M\t\tturns off memory allocation recording\n"); + (void) fprintf(stderr, " -h\t\tprints this message\n"); + (void) fprintf(stderr, " -p n\t\tcontrols verbosity\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, + 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 */ + diff --git a/distr/nanotrav/C17.blif b/distr/nanotrav/C17.blif new file mode 100644 index 0000000..b022c7f --- /dev/null +++ b/distr/nanotrav/C17.blif @@ -0,0 +1,16 @@ +.model C17.iscas +.inputs 1GAT(0) 2GAT(1) 3GAT(2) 6GAT(3) 7GAT(4) +.outputs 22GAT(10) 23GAT(9) +.names 3GAT(2) 6GAT(3) 11GAT(5) +11 0 +.names 1GAT(0) 3GAT(2) 10GAT(6) +11 0 +.names 11GAT(5) 7GAT(4) 19GAT(7) +11 0 +.names 2GAT(1) 11GAT(5) 16GAT(8) +11 0 +.names 16GAT(8) 19GAT(7) 23GAT(9) +11 0 +.names 10GAT(6) 16GAT(8) 22GAT(10) +11 0 +.end diff --git a/distr/nanotrav/C17.out b/distr/nanotrav/C17.out new file mode 100644 index 0000000..dd73027 --- /dev/null +++ b/distr/nanotrav/C17.out @@ -0,0 +1,101 @@ +# Nanotrav Version #0.12, Release date 2003/12/31 +# ./nanotrav -p 1 -cover C17.blif +# CUDD Version 2.4.2 +Order before final reordering +1GAT(0) 2GAT(1) 3GAT(2) 6GAT(3) 7GAT(4) +22GAT(10): 8 nodes 18 minterms +23GAT(9): 8 nodes 18 minterms +22GAT(10): 5 nodes 3 minterms +Testing iterator on ZDD paths: +-1-0- 1 +-10-- 1 +1-1-- 1 + +1-1-- 1 +-10-- 1 +-1-0- 1 +23GAT(9): 6 nodes 4 minterms +Testing iterator on ZDD paths: +---01 1 +--0-1 1 +-1-0- 1 +-10-- 1 + +-10-- 1 +-1-0- 1 +--0-1 1 +---01 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: yes +Realignment of BDDs to ZDDs enabled: no +Dead nodes counted in triggering reordering: no +Group checking criterion: 7 +Recombination threshold: 0 +Symmetry violation threshold: 10 +Arc violation threshold: 10 +GA population size: 0 +Number of crossovers for GA: 0 +Next reordering threshold: 4004 +**** CUDD non-modifiable parameters **** +Memory in use: 4737732 +Peak number of nodes: 1022 +Peak number of live nodes: 19 +Number of BDD variables: 5 +Number of ZDD variables: 10 +Number of cache entries: 32768 +Number of cache look-ups: 125 +Number of cache hits: 21 +Number of cache insertions: 117 +Number of cache collisions: 0 +Number of cache deletions: 35 +Cache used slots = 0.33% (expected 0.25%) +Soft limit for cache size: 16384 +Number of buckets in unique table: 4096 +Used buckets in unique table: 1.22% (expected 1.24%) +Number of BDD and ADD nodes: 24 +Number of ZDD nodes: 27 +Number of dead BDD and ADD nodes: 8 +Number of dead ZDD nodes: 17 +Total number of nodes allocated: 67 +Total number of nodes reclaimed: 8 +Garbage collections so far: 1 +Time for garbage collection: 0.00 sec +Reorderings so far: 0 +Time for reordering: 0.00 sec +Final size: 11 +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 = 131815K +Virtual data size = 297K + data size initialized = 25K + data size uninitialized = 137K + data size sbrk = 135K +Virtual memory limit = 358400K (4194304K) + +Major page faults = 8 +Minor page faults = 1413 +Swaps = 0 +Input blocks = 0 +Output blocks = 0 +Context switch (voluntary) = 12 +Context switch (involuntary) = 0 diff --git a/distr/nanotrav/C880.blif b/distr/nanotrav/C880.blif new file mode 100644 index 0000000..38ee2c9 --- /dev/null +++ b/distr/nanotrav/C880.blif @@ -0,0 +1,770 @@ +.model C880.iscas +.inputs 1GAT(0) 8GAT(1) 13GAT(2) 17GAT(3) 26GAT(4) 29GAT(5) 36GAT(6) 42GAT(7) 51GAT(8) 55GAT(9) 59GAT(10) 68GAT(11) 72GAT(12) 73GAT(13) 74GAT(14) 75GAT(15) 80GAT(16) 85GAT(17) 86GAT(18) 87GAT(19) 88GAT(20) 89GAT(21) 90GAT(22) 91GAT(23) 96GAT(24) 101GAT(25) 106GAT(26) 111GAT(27) 116GAT(28) 121GAT(29) 126GAT(30) 130GAT(31) 135GAT(32) 138GAT(33) 143GAT(34) 146GAT(35) 149GAT(36) 152GAT(37) 153GAT(38) 156GAT(39) 159GAT(40) 165GAT(41) 171GAT(42) 177GAT(43) 183GAT(44) 189GAT(45) 195GAT(46) 201GAT(47) 207GAT(48) 210GAT(49) 219GAT(50) 228GAT(51) 237GAT(52) 246GAT(53) 255GAT(54) 259GAT(55) 260GAT(56) 261GAT(57) 267GAT(58) 268GAT(59) +.outputs 388GAT(133) 389GAT(132) 390GAT(131) 391GAT(124) 418GAT(168) 419GAT(164) 420GAT(158) 421GAT(162) 422GAT(161) 423GAT(155) 446GAT(183) 447GAT(182) 448GAT(179) 449GAT(176) 450GAT(173) 767GAT(349) 768GAT(334) 850GAT(404) 863GAT(424) 864GAT(423) 865GAT(422) 866GAT(426) 874GAT(433) 878GAT(442) 879GAT(441) 880GAT(440) +.names 268GAT(59) 310GAT(60) +1 0 +.names 255GAT(54) 267GAT(58) 341GAT(61) +11 1 +.names 255GAT(54) 260GAT(56) 339GAT(62) +11 1 +.names 255GAT(54) 259GAT(55) 337GAT(63) +11 1 +.names 195GAT(46) 201GAT(47) 331GAT(64) +00 0 +.names 195GAT(46) 201GAT(47) 330GAT(65) +11 0 +.names 183GAT(44) 189GAT(45) 329GAT(66) +00 0 +.names 183GAT(44) 189GAT(45) 328GAT(67) +11 0 +.names 171GAT(42) 177GAT(43) 327GAT(68) +00 0 +.names 171GAT(42) 177GAT(43) 326GAT(69) +11 0 +.names 159GAT(40) 165GAT(41) 325GAT(70) +00 0 +.names 159GAT(40) 165GAT(41) 324GAT(71) +11 0 +.names 152GAT(37) 138GAT(33) 318GAT(72) +11 1 +.names 210GAT(49) 121GAT(29) 340GAT(73) +11 1 +.names 121GAT(29) 126GAT(30) 308GAT(74) +00 0 +.names 121GAT(29) 126GAT(30) 307GAT(75) +11 0 +.names 210GAT(49) 116GAT(28) 338GAT(76) +11 1 +.names 210GAT(49) 111GAT(27) 336GAT(77) +11 1 +.names 111GAT(27) 116GAT(28) 306GAT(78) +00 0 +.names 111GAT(27) 116GAT(28) 305GAT(79) +11 0 +.names 210GAT(49) 106GAT(26) 335GAT(80) +11 1 +.names 210GAT(49) 101GAT(25) 334GAT(81) +11 1 +.names 101GAT(25) 106GAT(26) 304GAT(82) +00 0 +.names 101GAT(25) 106GAT(26) 303GAT(83) +11 0 +.names 210GAT(49) 96GAT(24) 333GAT(84) +11 1 +.names 210GAT(49) 91GAT(23) 332GAT(85) +11 1 +.names 91GAT(23) 96GAT(24) 302GAT(86) +00 0 +.names 91GAT(23) 96GAT(24) 301GAT(87) +11 0 +.names 87GAT(19) 88GAT(20) 298GAT(88) +00 0 +.names 85GAT(17) 86GAT(18) 297GAT(89) +11 1 +.names 59GAT(10) 156GAT(39) 319GAT(90) +11 0 +.names 59GAT(10) 75GAT(15) 80GAT(16) 293GAT(91) +111 1 +.names 59GAT(10) 68GAT(11) 74GAT(14) 286GAT(92) +111 0 +.names 51GAT(8) 138GAT(33) 316GAT(93) +11 1 +.names 59GAT(10) 75GAT(15) 42GAT(7) 294GAT(94) +111 1 +.names 59GAT(10) 42GAT(7) 68GAT(11) 72GAT(12) 284GAT(95) +1111 0 +.names 59GAT(10) 36GAT(6) 42GAT(7) 296GAT(96) +111 1 +.names 59GAT(10) 36GAT(6) 80GAT(16) 295GAT(97) +111 1 +.names 29GAT(5) 36GAT(6) 42GAT(7) 292GAT(98) +111 1 +.names 29GAT(5) 36GAT(6) 80GAT(16) 291GAT(99) +111 1 +.names 29GAT(5) 75GAT(15) 42GAT(7) 290GAT(100) +111 1 +.names 29GAT(5) 75GAT(15) 80GAT(16) 287GAT(101) +111 1 +.names 29GAT(5) 68GAT(11) 285GAT(102) +11 0 +.names 29GAT(5) 36GAT(6) 42GAT(7) 273GAT(103) +111 1 +.names 17GAT(3) 42GAT(7) 323GAT(104) +11 1 +.names 17GAT(3) 42GAT(7) 322GAT(105) +00 1 +.names 17GAT(3) 138GAT(33) 317GAT(106) +11 1 +.names 8GAT(1) 138GAT(33) 309GAT(107) +11 1 +.names 1GAT(0) 8GAT(1) 13GAT(2) 55GAT(9) 280GAT(108) +1111 0 +.names 1GAT(0) 8GAT(1) 51GAT(8) 17GAT(3) 279GAT(109) +1111 0 +.names 1GAT(0) 26GAT(4) 51GAT(8) 276GAT(110) +111 1 +.names 1GAT(0) 26GAT(4) 13GAT(2) 17GAT(3) 270GAT(111) +1111 0 +.names 1GAT(0) 8GAT(1) 13GAT(2) 17GAT(3) 269GAT(112) +1111 0 +.names 310GAT(60) 369GAT(113) +1 0 +.names 330GAT(65) 331GAT(64) 385GAT(114) +11 0 +.names 328GAT(67) 329GAT(66) 382GAT(115) +11 0 +.names 326GAT(69) 327GAT(68) 379GAT(116) +11 0 +.names 324GAT(71) 325GAT(70) 376GAT(117) +11 0 +.names 307GAT(75) 308GAT(74) 366GAT(118) +11 0 +.names 305GAT(79) 306GAT(78) 363GAT(119) +11 0 +.names 303GAT(83) 304GAT(82) 360GAT(120) +11 0 +.names 301GAT(87) 302GAT(86) 357GAT(121) +11 0 +.names 90GAT(22) 298GAT(88) 356GAT(122) +11 1 +.names 89GAT(21) 298GAT(88) 355GAT(123) +11 0 +.names 297GAT(89) 391GAT(124) +1 1 +.names 293GAT(91) 351GAT(125) +1 0 +.names 280GAT(108) 286GAT(92) 350GAT(126) +00 0 +.names 294GAT(94) 352GAT(127) +1 0 +.names 280GAT(108) 284GAT(95) 348GAT(128) +00 1 +.names 296GAT(96) 354GAT(129) +1 0 +.names 295GAT(97) 353GAT(130) +1 0 +.names 292GAT(98) 390GAT(131) +1 1 +.names 291GAT(99) 389GAT(132) +1 1 +.names 290GAT(100) 388GAT(133) +1 1 +.names 280GAT(108) 285GAT(102) 349GAT(134) +00 0 +.names 273GAT(103) 343GAT(135) +1 0 +.names 270GAT(111) 273GAT(103) 344GAT(136) +00 0 +.names 322GAT(105) 323GAT(104) 375GAT(137) +00 1 +.names 279GAT(109) 347GAT(138) +1 0 +.names 276GAT(110) 345GAT(139) +1 0 +.names 276GAT(110) 346GAT(140) +1 0 +.names 269GAT(112) 342GAT(141) +1 0 +.names 210GAT(49) 369GAT(113) 417GAT(142) +11 1 +.names 385GAT(114) 415GAT(143) +1 0 +.names 382GAT(115) 385GAT(114) 416GAT(144) +11 1 +.names 382GAT(115) 414GAT(145) +1 0 +.names 379GAT(116) 412GAT(146) +1 0 +.names 376GAT(117) 379GAT(116) 413GAT(147) +11 1 +.names 376GAT(117) 411GAT(148) +1 0 +.names 366GAT(118) 408GAT(149) +1 0 +.names 363GAT(119) 366GAT(118) 409GAT(150) +11 1 +.names 363GAT(119) 407GAT(151) +1 0 +.names 360GAT(120) 405GAT(152) +1 0 +.names 357GAT(121) 360GAT(120) 406GAT(153) +11 1 +.names 357GAT(121) 404GAT(154) +1 0 +.names 356GAT(122) 423GAT(155) +1 1 +.names 355GAT(123) 403GAT(156) +1 0 +.names 348GAT(128) 73GAT(13) 400GAT(157) +11 1 +.names 351GAT(125) 420GAT(158) +1 1 +.names 350GAT(126) 402GAT(159) +1 0 +.names 347GAT(138) 352GAT(127) 410GAT(160) +11 0 +.names 354GAT(129) 422GAT(161) +1 1 +.names 353GAT(130) 421GAT(162) +1 1 +.names 349GAT(134) 401GAT(163) +1 0 +.names 344GAT(136) 419GAT(164) +1 1 +.names 345GAT(139) 393GAT(165) +1 0 +.names 346GAT(140) 399GAT(166) +1 0 +.names 270GAT(111) 343GAT(135) 392GAT(167) +00 0 +.names 342GAT(141) 418GAT(168) +1 1 +.names 414GAT(145) 415GAT(143) 445GAT(169) +11 1 +.names 411GAT(148) 412GAT(146) 444GAT(170) +11 1 +.names 407GAT(151) 408GAT(149) 426GAT(171) +11 1 +.names 404GAT(154) 405GAT(152) 425GAT(172) +11 1 +.names 403GAT(156) 450GAT(173) +1 1 +.names 400GAT(157) 424GAT(174) +1 0 +.names 375GAT(137) 59GAT(10) 156GAT(39) 393GAT(165) 442GAT(175) +1111 0 +.names 402GAT(159) 449GAT(176) +1 1 +.names 393GAT(165) 287GAT(101) 55GAT(9) 437GAT(177) +111 0 +.names 319GAT(90) 393GAT(165) 55GAT(9) 427GAT(178) +111 1 +.names 401GAT(163) 448GAT(179) +1 1 +.names 393GAT(165) 319GAT(90) 17GAT(3) 443GAT(180) +111 0 +.names 393GAT(165) 17GAT(3) 287GAT(101) 432GAT(181) +111 1 +.names 399GAT(166) 447GAT(182) +1 1 +.names 392GAT(167) 446GAT(183) +1 1 +.names 369GAT(113) 437GAT(177) 488GAT(184) +00 0 +.names 369GAT(113) 437GAT(177) 489GAT(185) +00 0 +.names 369GAT(113) 437GAT(177) 490GAT(186) +00 0 +.names 369GAT(113) 437GAT(177) 491GAT(187) +00 0 +.names 310GAT(60) 432GAT(181) 476GAT(188) +11 1 +.names 310GAT(60) 432GAT(181) 478GAT(189) +11 1 +.names 310GAT(60) 432GAT(181) 480GAT(190) +11 1 +.names 310GAT(60) 432GAT(181) 482GAT(191) +11 1 +.names 416GAT(144) 445GAT(169) 495GAT(192) +00 1 +.names 413GAT(147) 444GAT(170) 492GAT(193) +00 1 +.names 153GAT(38) 427GAT(178) 481GAT(194) +11 1 +.names 149GAT(36) 427GAT(178) 479GAT(195) +11 1 +.names 146GAT(35) 427GAT(178) 477GAT(196) +11 1 +.names 143GAT(34) 427GAT(178) 475GAT(197) +11 1 +.names 409GAT(150) 426GAT(171) 463GAT(198) +00 1 +.names 406GAT(153) 425GAT(172) 460GAT(199) +00 1 +.names 424GAT(174) 451GAT(200) +1 0 +.names 442GAT(175) 410GAT(160) 466GAT(201) +11 0 +.names 443GAT(180) 1GAT(0) 483GAT(202) +11 0 +.names 475GAT(197) 476GAT(188) 503GAT(203) +00 1 +.names 477GAT(196) 478GAT(189) 505GAT(204) +00 1 +.names 479GAT(195) 480GAT(190) 507GAT(205) +00 1 +.names 481GAT(194) 482GAT(191) 509GAT(206) +00 1 +.names 495GAT(192) 207GAT(48) 521GAT(207) +00 0 +.names 495GAT(192) 207GAT(48) 520GAT(208) +11 0 +.names 451GAT(200) 201GAT(47) 529GAT(209) +11 0 +.names 451GAT(200) 195GAT(46) 528GAT(210) +11 0 +.names 451GAT(200) 189GAT(45) 527GAT(211) +11 0 +.names 451GAT(200) 183GAT(44) 526GAT(212) +11 1 +.names 451GAT(200) 177GAT(43) 525GAT(213) +11 1 +.names 451GAT(200) 171GAT(42) 524GAT(214) +11 1 +.names 451GAT(200) 165GAT(41) 523GAT(215) +11 1 +.names 451GAT(200) 159GAT(40) 522GAT(216) +11 1 +.names 153GAT(38) 483GAT(202) 516GAT(217) +11 1 +.names 149GAT(36) 483GAT(202) 514GAT(218) +11 1 +.names 146GAT(35) 483GAT(202) 512GAT(219) +11 1 +.names 143GAT(34) 483GAT(202) 510GAT(220) +11 1 +.names 463GAT(198) 135GAT(32) 501GAT(221) +00 0 +.names 463GAT(198) 135GAT(32) 500GAT(222) +11 0 +.names 130GAT(31) 492GAT(193) 519GAT(223) +00 0 +.names 130GAT(31) 492GAT(193) 518GAT(224) +11 0 +.names 130GAT(31) 460GAT(199) 499GAT(225) +00 0 +.names 130GAT(31) 460GAT(199) 498GAT(226) +11 0 +.names 126GAT(30) 466GAT(201) 517GAT(227) +11 1 +.names 121GAT(29) 466GAT(201) 515GAT(228) +11 1 +.names 116GAT(28) 466GAT(201) 513GAT(229) +11 1 +.names 111GAT(27) 466GAT(201) 511GAT(230) +11 1 +.names 106GAT(26) 466GAT(201) 508GAT(231) +11 1 +.names 101GAT(25) 466GAT(201) 506GAT(232) +11 1 +.names 96GAT(24) 466GAT(201) 504GAT(233) +11 1 +.names 91GAT(23) 466GAT(201) 502GAT(234) +11 1 +.names 520GAT(208) 521GAT(207) 547GAT(235) +11 0 +.names 516GAT(217) 517GAT(227) 543GAT(236) +00 1 +.names 514GAT(218) 515GAT(228) 542GAT(237) +00 1 +.names 512GAT(219) 513GAT(229) 541GAT(238) +00 1 +.names 510GAT(220) 511GAT(230) 540GAT(239) +00 1 +.names 318GAT(72) 508GAT(231) 539GAT(240) +00 1 +.names 500GAT(222) 501GAT(221) 533GAT(241) +11 0 +.names 518GAT(224) 519GAT(223) 544GAT(242) +11 0 +.names 498GAT(226) 499GAT(225) 530GAT(243) +11 0 +.names 316GAT(93) 504GAT(233) 537GAT(244) +00 1 +.names 317GAT(106) 506GAT(232) 538GAT(245) +00 1 +.names 309GAT(107) 502GAT(234) 536GAT(246) +00 1 +.names 488GAT(184) 540GAT(239) 569GAT(247) +11 0 +.names 489GAT(185) 541GAT(238) 573GAT(248) +11 0 +.names 490GAT(186) 542GAT(237) 577GAT(249) +11 0 +.names 491GAT(187) 543GAT(236) 581GAT(250) +11 0 +.names 536GAT(246) 503GAT(203) 553GAT(251) +11 0 +.names 537GAT(244) 505GAT(204) 557GAT(252) +11 0 +.names 538GAT(245) 507GAT(205) 561GAT(253) +11 0 +.names 539GAT(240) 509GAT(206) 565GAT(254) +11 0 +.names 547GAT(235) 586GAT(255) +1 0 +.names 544GAT(242) 547GAT(235) 587GAT(256) +11 1 +.names 533GAT(241) 551GAT(257) +1 0 +.names 530GAT(243) 533GAT(241) 552GAT(258) +11 1 +.names 544GAT(242) 585GAT(259) +1 0 +.names 530GAT(243) 550GAT(260) +1 0 +.names 246GAT(53) 581GAT(250) 659GAT(261) +11 1 +.names 246GAT(53) 577GAT(249) 650GAT(262) +11 1 +.names 246GAT(53) 573GAT(248) 640GAT(263) +11 1 +.names 246GAT(53) 569GAT(247) 631GAT(264) +11 1 +.names 246GAT(53) 565GAT(254) 624GAT(265) +11 1 +.names 246GAT(53) 561GAT(253) 615GAT(266) +11 1 +.names 246GAT(53) 557GAT(252) 605GAT(267) +11 1 +.names 246GAT(53) 553GAT(251) 596GAT(268) +11 1 +.names 585GAT(259) 586GAT(255) 589GAT(269) +11 1 +.names 581GAT(250) 201GAT(47) 654GAT(270) +00 0 +.names 581GAT(250) 201GAT(47) 651GAT(271) +11 0 +.names 577GAT(249) 195GAT(46) 644GAT(272) +00 0 +.names 577GAT(249) 195GAT(46) 641GAT(273) +11 0 +.names 573GAT(248) 189GAT(45) 635GAT(274) +00 0 +.names 573GAT(248) 189GAT(45) 632GAT(275) +11 0 +.names 569GAT(247) 183GAT(44) 628GAT(276) +00 0 +.names 569GAT(247) 183GAT(44) 625GAT(277) +11 0 +.names 565GAT(254) 177GAT(43) 619GAT(278) +00 0 +.names 565GAT(254) 177GAT(43) 616GAT(279) +11 0 +.names 561GAT(253) 171GAT(42) 609GAT(280) +00 0 +.names 561GAT(253) 171GAT(42) 606GAT(281) +11 0 +.names 557GAT(252) 165GAT(41) 600GAT(282) +00 0 +.names 557GAT(252) 165GAT(41) 597GAT(283) +11 0 +.names 553GAT(251) 159GAT(40) 593GAT(284) +00 0 +.names 553GAT(251) 159GAT(40) 590GAT(285) +11 0 +.names 550GAT(260) 551GAT(257) 588GAT(286) +11 1 +.names 635GAT(274) 644GAT(272) 654GAT(270) 261GAT(57) 734GAT(287) +1111 0 +.names 644GAT(272) 654GAT(270) 261GAT(57) 733GAT(288) +111 0 +.names 654GAT(270) 261GAT(57) 732GAT(289) +11 0 +.names 341GAT(61) 659GAT(261) 731GAT(290) +00 1 +.names 339GAT(62) 650GAT(262) 721GAT(291) +00 1 +.names 337GAT(63) 640GAT(263) 712GAT(292) +00 1 +.names 587GAT(256) 589GAT(269) 661GAT(293) +00 1 +.names 654GAT(270) 651GAT(271) 727GAT(294) +11 1 +.names 651GAT(271) 722GAT(295) +1 0 +.names 644GAT(272) 641GAT(273) 717GAT(296) +11 1 +.names 641GAT(273) 713GAT(297) +1 0 +.names 635GAT(274) 632GAT(275) 708GAT(298) +11 1 +.names 632GAT(275) 705GAT(299) +1 0 +.names 628GAT(276) 625GAT(277) 700GAT(300) +11 1 +.names 625GAT(277) 697GAT(301) +1 0 +.names 631GAT(264) 526GAT(212) 704GAT(302) +00 1 +.names 619GAT(278) 616GAT(279) 692GAT(303) +11 1 +.names 616GAT(279) 687GAT(304) +1 0 +.names 624GAT(265) 525GAT(213) 696GAT(305) +00 1 +.names 609GAT(280) 606GAT(281) 682GAT(306) +11 1 +.names 606GAT(281) 678GAT(307) +1 0 +.names 615GAT(266) 524GAT(214) 686GAT(308) +00 1 +.names 600GAT(282) 597GAT(283) 673GAT(309) +11 1 +.names 597GAT(283) 670GAT(310) +1 0 +.names 605GAT(267) 523GAT(215) 677GAT(311) +00 1 +.names 593GAT(284) 590GAT(285) 665GAT(312) +11 1 +.names 590GAT(285) 662GAT(313) +1 0 +.names 596GAT(268) 522GAT(216) 669GAT(314) +00 1 +.names 552GAT(258) 588GAT(286) 660GAT(315) +00 1 +.names 727GAT(294) 261GAT(57) 758GAT(316) +11 1 +.names 727GAT(294) 261GAT(57) 757GAT(317) +00 1 +.names 237GAT(52) 722GAT(295) 760GAT(318) +11 1 +.names 237GAT(52) 713GAT(297) 755GAT(319) +11 1 +.names 237GAT(52) 705GAT(299) 752GAT(320) +11 1 +.names 237GAT(52) 697GAT(301) 749GAT(321) +11 1 +.names 237GAT(52) 687GAT(304) 746GAT(322) +11 1 +.names 237GAT(52) 678GAT(307) 743GAT(323) +11 1 +.names 237GAT(52) 670GAT(310) 740GAT(324) +11 1 +.names 237GAT(52) 662GAT(313) 737GAT(325) +11 1 +.names 228GAT(51) 727GAT(294) 759GAT(326) +11 1 +.names 228GAT(51) 717GAT(296) 754GAT(327) +11 1 +.names 228GAT(51) 708GAT(298) 751GAT(328) +11 1 +.names 228GAT(51) 700GAT(300) 748GAT(329) +11 1 +.names 228GAT(51) 692GAT(303) 745GAT(330) +11 1 +.names 228GAT(51) 682GAT(306) 742GAT(331) +11 1 +.names 228GAT(51) 673GAT(309) 739GAT(332) +11 1 +.names 228GAT(51) 665GAT(312) 736GAT(333) +11 1 +.names 661GAT(293) 768GAT(334) +1 1 +.names 722GAT(295) 756GAT(335) +1 0 +.names 644GAT(272) 722GAT(295) 761GAT(336) +11 0 +.names 635GAT(274) 644GAT(272) 722GAT(295) 763GAT(337) +111 0 +.names 713GAT(297) 753GAT(338) +1 0 +.names 635GAT(274) 713GAT(297) 762GAT(339) +11 0 +.names 705GAT(299) 750GAT(340) +1 0 +.names 697GAT(301) 747GAT(341) +1 0 +.names 687GAT(304) 744GAT(342) +1 0 +.names 609GAT(280) 687GAT(304) 764GAT(343) +11 0 +.names 600GAT(282) 609GAT(280) 687GAT(304) 766GAT(344) +111 0 +.names 678GAT(307) 741GAT(345) +1 0 +.names 600GAT(282) 678GAT(307) 765GAT(346) +11 0 +.names 670GAT(310) 738GAT(347) +1 0 +.names 662GAT(313) 735GAT(348) +1 0 +.names 660GAT(315) 767GAT(349) +1 1 +.names 757GAT(317) 758GAT(316) 786GAT(350) +00 1 +.names 750GAT(340) 762GAT(339) 763GAT(337) 734GAT(287) 773GAT(351) +1111 0 +.names 753GAT(338) 761GAT(336) 733GAT(288) 778GAT(352) +111 0 +.names 756GAT(335) 732GAT(289) 782GAT(353) +11 0 +.names 759GAT(326) 760GAT(318) 787GAT(354) +00 1 +.names 754GAT(327) 755GAT(319) 785GAT(355) +00 1 +.names 751GAT(328) 752GAT(320) 781GAT(356) +00 1 +.names 748GAT(329) 749GAT(321) 777GAT(357) +00 1 +.names 745GAT(330) 746GAT(322) 772GAT(358) +00 1 +.names 742GAT(331) 743GAT(323) 771GAT(359) +00 1 +.names 739GAT(332) 740GAT(324) 770GAT(360) +00 1 +.names 736GAT(333) 737GAT(325) 769GAT(361) +00 1 +.names 219GAT(50) 786GAT(350) 794GAT(362) +11 1 +.names 717GAT(296) 782GAT(353) 792GAT(363) +00 1 +.names 717GAT(296) 782GAT(353) 793GAT(364) +11 1 +.names 708GAT(298) 778GAT(352) 790GAT(365) +00 1 +.names 708GAT(298) 778GAT(352) 791GAT(366) +11 1 +.names 700GAT(300) 773GAT(351) 788GAT(367) +00 1 +.names 700GAT(300) 773GAT(351) 789GAT(368) +11 1 +.names 628GAT(276) 773GAT(351) 795GAT(369) +11 0 +.names 792GAT(363) 793GAT(364) 804GAT(370) +00 1 +.names 790GAT(365) 791GAT(366) 803GAT(371) +00 1 +.names 788GAT(367) 789GAT(368) 802GAT(372) +00 1 +.names 795GAT(369) 747GAT(341) 796GAT(373) +11 0 +.names 340GAT(73) 794GAT(362) 805GAT(374) +00 1 +.names 219GAT(50) 804GAT(370) 810GAT(375) +11 1 +.names 219GAT(50) 803GAT(371) 809GAT(376) +11 1 +.names 219GAT(50) 802GAT(372) 808GAT(377) +11 1 +.names 805GAT(374) 787GAT(354) 731GAT(290) 529GAT(209) 811GAT(378) +1111 0 +.names 692GAT(303) 796GAT(373) 806GAT(379) +00 1 +.names 692GAT(303) 796GAT(373) 807GAT(380) +11 1 +.names 619GAT(278) 796GAT(373) 812GAT(381) +11 0 +.names 609GAT(280) 619GAT(278) 796GAT(373) 813GAT(382) +111 0 +.names 600GAT(282) 609GAT(280) 619GAT(278) 796GAT(373) 814GAT(383) +1111 0 +.names 811GAT(378) 829GAT(384) +1 0 +.names 806GAT(379) 807GAT(380) 825GAT(385) +00 1 +.names 744GAT(342) 812GAT(381) 822GAT(386) +11 0 +.names 741GAT(345) 764GAT(343) 813GAT(382) 819GAT(387) +111 0 +.names 738GAT(347) 765GAT(346) 766GAT(344) 814GAT(383) 815GAT(388) +1111 0 +.names 338GAT(76) 810GAT(375) 828GAT(389) +00 1 +.names 336GAT(77) 809GAT(376) 827GAT(390) +00 1 +.names 335GAT(80) 808GAT(377) 826GAT(391) +00 1 +.names 219GAT(50) 825GAT(385) 836GAT(392) +11 1 +.names 829GAT(384) 840GAT(393) +1 0 +.names 828GAT(389) 785GAT(355) 721GAT(291) 528GAT(210) 839GAT(394) +1111 0 +.names 827GAT(390) 781GAT(356) 712GAT(292) 527GAT(211) 838GAT(395) +1111 0 +.names 826GAT(391) 777GAT(357) 704GAT(302) 837GAT(396) +111 0 +.names 682GAT(306) 822GAT(386) 834GAT(397) +00 1 +.names 682GAT(306) 822GAT(386) 835GAT(398) +11 1 +.names 673GAT(309) 819GAT(387) 832GAT(399) +00 1 +.names 673GAT(309) 819GAT(387) 833GAT(400) +11 1 +.names 665GAT(312) 815GAT(388) 830GAT(401) +00 1 +.names 665GAT(312) 815GAT(388) 831GAT(402) +11 1 +.names 815GAT(388) 593GAT(284) 841GAT(403) +11 0 +.names 840GAT(393) 850GAT(404) +1 1 +.names 839GAT(394) 848GAT(405) +1 0 +.names 838GAT(395) 847GAT(406) +1 0 +.names 837GAT(396) 846GAT(407) +1 0 +.names 834GAT(397) 835GAT(398) 844GAT(408) +00 1 +.names 832GAT(399) 833GAT(400) 843GAT(409) +00 1 +.names 830GAT(401) 831GAT(402) 842GAT(410) +00 1 +.names 735GAT(348) 841GAT(403) 849GAT(411) +11 1 +.names 334GAT(81) 836GAT(392) 845GAT(412) +00 1 +.names 219GAT(50) 844GAT(408) 853GAT(413) +11 1 +.names 219GAT(50) 843GAT(409) 852GAT(414) +11 1 +.names 219GAT(50) 842GAT(410) 851GAT(415) +11 1 +.names 848GAT(405) 857GAT(416) +1 0 +.names 847GAT(406) 856GAT(417) +1 0 +.names 846GAT(407) 855GAT(418) +1 0 +.names 845GAT(412) 772GAT(358) 696GAT(305) 854GAT(419) +111 0 +.names 849GAT(411) 858GAT(420) +1 0 +.names 417GAT(142) 851GAT(415) 859GAT(421) +00 1 +.names 857GAT(416) 865GAT(422) +1 1 +.names 856GAT(417) 864GAT(423) +1 1 +.names 855GAT(418) 863GAT(424) +1 1 +.names 854GAT(419) 862GAT(425) +1 0 +.names 858GAT(420) 866GAT(426) +1 1 +.names 333GAT(84) 853GAT(413) 861GAT(427) +00 1 +.names 332GAT(85) 852GAT(414) 860GAT(428) +00 1 +.names 862GAT(425) 870GAT(429) +1 0 +.names 861GAT(427) 771GAT(359) 686GAT(308) 869GAT(430) +111 0 +.names 860GAT(428) 770GAT(360) 677GAT(311) 868GAT(431) +111 0 +.names 859GAT(421) 769GAT(361) 669GAT(314) 867GAT(432) +111 0 +.names 870GAT(429) 874GAT(433) +1 1 +.names 869GAT(430) 873GAT(434) +1 0 +.names 868GAT(431) 872GAT(435) +1 0 +.names 867GAT(432) 871GAT(436) +1 0 +.names 873GAT(434) 877GAT(437) +1 0 +.names 872GAT(435) 876GAT(438) +1 0 +.names 871GAT(436) 875GAT(439) +1 0 +.names 877GAT(437) 880GAT(440) +1 1 +.names 876GAT(438) 879GAT(441) +1 1 +.names 875GAT(439) 878GAT(442) +1 1 +.end diff --git a/distr/nanotrav/C880.out b/distr/nanotrav/C880.out new file mode 100644 index 0000000..71dcb62 --- /dev/null +++ b/distr/nanotrav/C880.out @@ -0,0 +1,101 @@ +# Nanotrav Version #0.12, Release date 2003/12/31 +# ./nanotrav -p 1 -ordering dfs -autodyn -automethod sifting -reordering sifting -drop C880.blif +# CUDD Version 2.4.2 +BDD reordering with sifting: from 3974 to ... 2432 nodes in 0.039 sec +BDD reordering with sifting: from 4893 to ... 3549 nodes in 0.044 sec +BDD reordering with sifting: from 7133 to ... 6246 nodes in 0.072 sec +BDD reordering with sifting: from 12522 to ... 6465 nodes in 0.113 sec +Order before final reordering +86GAT(18) 85GAT(17) 90GAT(22) 89GAT(21) 88GAT(20) 87GAT(19) 1GAT(0) 51GAT(8) +75GAT(15) 26GAT(4) 268GAT(59) 36GAT(6) 29GAT(5) 80GAT(16) 59GAT(10) 42GAT(7) +156GAT(39) 17GAT(3) 74GAT(14) 55GAT(9) 8GAT(1) 219GAT(50) 210GAT(49) 91GAT(23) +101GAT(25) 138GAT(33) 96GAT(24) 171GAT(42) 152GAT(37) 146GAT(35) 116GAT(28) 189GAT(45) +149GAT(36) 121GAT(29) 195GAT(46) 153GAT(38) 126GAT(30) 261GAT(57) 201GAT(47) 143GAT(34) +111GAT(27) 183GAT(44) 130GAT(31) 135GAT(32) 106GAT(26) 177GAT(43) 165GAT(41) 207GAT(48) +159GAT(40) 228GAT(51) 237GAT(52) 246GAT(53) 73GAT(13) 72GAT(12) 68GAT(11) 13GAT(2) +260GAT(56) 267GAT(58) 259GAT(55) 255GAT(54) +Number of inputs = 60 +BDD reordering with sifting: from 6204 to ... 4623 nodes in 0.07 sec +New order +135GAT(32) 207GAT(48) 130GAT(31) 86GAT(18) 85GAT(17) 89GAT(21) 90GAT(22) 88GAT(20) +87GAT(19) 1GAT(0) 51GAT(8) 26GAT(4) 268GAT(59) 29GAT(5) 80GAT(16) 59GAT(10) +42GAT(7) 75GAT(15) 156GAT(39) 36GAT(6) 17GAT(3) 74GAT(14) 55GAT(9) 8GAT(1) +210GAT(49) 91GAT(23) 138GAT(33) 165GAT(41) 96GAT(24) 159GAT(40) 101GAT(25) 171GAT(42) +152GAT(37) 149GAT(36) 146GAT(35) 116GAT(28) 189GAT(45) 121GAT(29) 195GAT(46) 153GAT(38) +143GAT(34) 126GAT(30) 201GAT(47) 261GAT(57) 111GAT(27) 106GAT(26) 183GAT(44) 177GAT(43) +219GAT(50) 246GAT(53) 237GAT(52) 228GAT(51) 73GAT(13) 72GAT(12) 68GAT(11) 13GAT(2) +260GAT(56) 267GAT(58) 259GAT(55) 255GAT(54) +**** 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: 1000000 +Maximum number of variable swaps per reordering: 1000000000 +Maximum growth while sifting a variable: 1.2 +Dynamic reordering of BDDs enabled: yes +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: 10 +Arc violation threshold: 10 +GA population size: 0 +Number of crossovers for GA: 0 +Next reordering threshold: 9340 +**** CUDD non-modifiable parameters **** +Memory in use: 5611044 +Peak number of nodes: 19418 +Peak number of live nodes: 12568 +Number of BDD variables: 60 +Number of ZDD variables: 0 +Number of cache entries: 65536 +Number of cache look-ups: 59167 +Number of cache hits: 28642 +Number of cache insertions: 30604 +Number of cache collisions: 2547 +Number of cache deletions: 28057 +Cache used slots = 18.04% (expected 0.00%) +Soft limit for cache size: 62464 +Number of buckets in unique table: 15616 +Used buckets in unique table: 20.84% (expected 20.96%) +Number of BDD and ADD nodes: 4671 +Number of ZDD nodes: 0 +Number of dead BDD and ADD nodes: 0 +Number of dead ZDD nodes: 0 +Total number of nodes allocated: 32671 +Total number of nodes reclaimed: 1974 +Garbage collections so far: 5 +Time for garbage collection: 0.00 sec +Reorderings so far: 5 +Time for reordering: 0.34 sec +Final size: 4623 +total time = 0.36 sec +Runtime Statistics +------------------ +Machine name: jobim.colorado.edu +User time 0.4 seconds +System time 0.0 seconds + +Average resident text size = 0K +Average resident data+stack size = 0K +Maximum resident size = 0K + +Virtual text size = 131815K +Virtual data size = 297K + data size initialized = 25K + data size uninitialized = 137K + data size sbrk = 135K +Virtual memory limit = 358400K (4194304K) + +Major page faults = 0 +Minor page faults = 1778 +Swaps = 0 +Input blocks = 0 +Output blocks = 0 +Context switch (voluntary) = 1 +Context switch (involuntary) = 6 diff --git a/distr/nanotrav/Makefile b/distr/nanotrav/Makefile new file mode 100644 index 0000000..b40b547 --- /dev/null +++ b/distr/nanotrav/Makefile @@ -0,0 +1,98 @@ +# $Id: Makefile,v 1.12 1999/08/31 19:10:05 fabio Exp fabio $ +# +# nanotrav: simple FSM traversal program +#--------------------------------------------------------------------------- +.SUFFIXES: .o .c .u + +CC = gcc +#CC = cc +RANLIB = ranlib +#RANLIB = : +PURE = + +EXE = +#EXE = .exe +TARGET = nanotrav$(EXE) +TARGETu = nanotrav-u + +WHERE = .. + +INCLUDE = $(WHERE)/include + +LIBS = $(WHERE)/dddmp/libdddmp.a $(WHERE)/cudd/libcudd.a \ + $(WHERE)/mtr/libmtr.a $(WHERE)/st/libst.a $(WHERE)/util/libutil.a \ + $(WHERE)/epd/libepd.a + +MNEMLIB = +#MNEMLIB = $(WHERE)/mnemosyne/libmnem.a + +BLIBS = -kL$(WHERE)/dddmp -kldddmp -kL$(WHERE)/cudd -klcudd -kL$(WHERE)/mtr \ + -klmtr -kL$(WHERE)/st -klst -kL$(WHERE)/util -klutil \ + -kL$(WHERE)/epd -klepd + +LINTLIBS = $(WHERE)/llib-ldddmp.a $(WHERE)/cudd/llib-lcudd.ln \ + $(WHERE)/mtr/llib-lmtr.ln $(WHERE)/st/llib-lst.ln \ + $(WHERE)/util/llib-lutil.ln $(WHERE)/epd/llib-lepd.ln + +SRC = main.c bnet.c ntr.c ntrHeap.c ntrBddTest.c ntrMflow.c ntrZddTest.c \ + ntrShort.c chkMterm.c ucbqsort.c +HDR = bnet.h ntr.h $(WHERE)/include/dddmp.h $(WHERE)/include/cudd.h \ + $(WHERE)/include/cuddInt.h + +OBJ = $(SRC:.c=.o) +UBJ = $(SRC:.c=.u) + +MFLAG = +#MFLAG = -DMNEMOSYNE +ICFLAGS = -g -O6 -Wall +#ICFLAGS = -g -Wall +XCFLAGS = -DHAVE_IEEE_754 -DBSD +#XCFLAGS = -xtaso -ieee_with_no_inexact -tune host +CFLAGS = $(ICFLAGS) $(MFLAG) $(XCFLAGS) +DDDEBUG = +#DDDEBUG = -DDD_STATS -DDD_VERBOSE -DDD_CACHE_PROFILE -DDD_UNIQUE_PROFILE -DDD_DEBUG + +LDFLAGS = +#LDFLAGS = -jmpopt +#LDFLAGS = -non_shared -om -taso + +LINTFLAGS = -u -n -DDD_STATS -DDD_CACHE_PROFILE -DDD_VERBOSE -DDD_DEBUG -DDD_UNIQUE_PROFILE + +#------------------------------------------------------ + +$(TARGET): $(SRC) $(OBJ) $(HDR) $(LIBS) $(MNEMLIB) + $(PURE) $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(OBJ) $(LIBS) $(MNEMLIB) -lm + +.c.o: $(HDR) + $(CC) -c $< -I$(INCLUDE) $(CFLAGS) $(DDDEBUG) + +# if the header files change, recompile +$(OBJ): $(HDR) +$(UBJ): $(HDR) + +optimize_dec: $(TARGETu) + +# optimize (DECstations only: uses u-code) +$(TARGETu): $(SRC) $(UBJ) $(HDR) $(LIBS:.a=.b) + cc -O3 $(XCFLAGS) $(LDFLAGS) $(UBJ) -o $@ $(BLIBS) -lm + +.c.u: $(SRC) $(HDR) + cc -j -I$(INCLUDE) $(XCFLAGS) $< + +lint: $(SRC) $(HDR) $(LINTLIBS) + lint $(LINTFLAGS) -I$(INCLUDE) $(SRC) $(LINTLIBS) + +tags: $(SRC) $(HDR) + ctags $(SRC) $(HDR) + +all: $(TARGET) $(TARGETu) lint tags + +pixie: $(TARGETu) + pixie $(TARGETu) + +clean: + rm -f *.o *.u mon.out gmon.out *.pixie *.Addrs *.Counts mnem.* \ + .pure core *.warnings + +distclean: clean + rm -f $(TARGET) $(TARGETu) *.bak *~ .gdb_history *.qv *.qx diff --git a/distr/nanotrav/README b/distr/nanotrav/README new file mode 100644 index 0000000..cf09d9c --- /dev/null +++ b/distr/nanotrav/README @@ -0,0 +1,47 @@ +$Id: README,v 1.8 1997/01/23 07:33:22 fabio Exp fabio $ + +WHAT IS NANOTRAV +================ + +This directory contains nanotrav, a simple reachability analysis program +based on the CUDD package. Nanotrav uses a very naive approach and is +only included to provide a sanity check for the installation of the +CUDD package. + +Nanotrav reads a circuit written in a small subset of blif. This +format is described in the comments in bnet.c. Nanotrav then creates +BDDs for the primary outputs and the next state functions (if any) of +the circuit. + +If, passed the -trav option, nanotrav builds a BDD for the +characteristic function of the transition relation of the graph. It then +builds a BDD for the initial state(s), and performs reachability +analysis. Reachability analysys is performed with either the method +known as "monolithic transition relation method," whose main virtue is +simplicity, or with a unsophisticated partitioned transition relation +method. + +Once it has completed reachability analysis, nanotrav prints results and +exits. The amount of information printed, as well as several other +features are controlled by the options. For a complete list of the +options, consult the man page. Here, we only mention that the options allow +the user of nanotrav to select among different reordering options. + +TEST CIRCUITS +============= + +Five test circuits are contained in this directory: C17.blif, +C880.blif, s27.blif, mult32a.blif, and rcn25.blif. The first two are +combinational, while the last three are sequential. The results or +running + + nanotrav -p 1 -cover C17.blif > C17.out + nanotrav -p 1 -ordering dfs -autodyn -automethod sifting -reordering sifting -drop C880.blif > C880.out + nanotrav -p 1 -trav s27.blif > s27.out + nanotrav -p 1 -autodyn -reordering sifting -trav mult32a.blif > mult32a.out + nanotrav -p 1 -envelope rcn25.blif > rcn25.out + +are also included. They have been obtained on a 200 MHz P6-based +machine with 128MB of memory. These tests can be run with the shell +script tst.sh. Notice that rcn25 requires approximately 500 sec. All +other tests run in a few seconds. diff --git a/distr/nanotrav/bnet.c b/distr/nanotrav/bnet.c new file mode 100644 index 0000000..950306f --- /dev/null +++ b/distr/nanotrav/bnet.c @@ -0,0 +1,2252 @@ +/**CFile*********************************************************************** + + FileName [bnet.c] + + PackageName [bnet] + + Synopsis [Functions to read in a boolean network.] + + 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.] + +******************************************************************************/ + +#include "bnet.h" + +/*---------------------------------------------------------------------------*/ +/* Constant declarations */ +/*---------------------------------------------------------------------------*/ + +#define MAXLENGTH 131072 + +/*---------------------------------------------------------------------------*/ +/* Stucture declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Type declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Variable declarations */ +/*---------------------------------------------------------------------------*/ + +#ifndef lint +static char rcsid[] UTIL_UNUSED = "$Id: bnet.c,v 1.25 2009/02/21 06:00:31 fabio Exp fabio $"; +#endif + +static char BuffLine[MAXLENGTH]; +static char *CurPos; +static int newNameNumber = 0; + +/*---------------------------------------------------------------------------*/ +/* Macro declarations */ +/*---------------------------------------------------------------------------*/ + +/**AutomaticStart*************************************************************/ + +/*---------------------------------------------------------------------------*/ +/* Static function prototypes */ +/*---------------------------------------------------------------------------*/ + +static char * readString (FILE *fp); +static char ** readList (FILE *fp, int *n); +static void printList (char **list, int n); +static char ** bnetGenerateNewNames (st_table *hash, int n); +static int bnetDumpReencodingLogic (DdManager *dd, char *mname, int noutputs, DdNode **outputs, char **inames, char **altnames, char **onames, FILE *fp); +#if 0 +static int bnetBlifXnorTable (FILE *fp, int n); +#endif +static int bnetBlifWriteReencode (DdManager *dd, char *mname, char **inames, char **altnames, int *support, FILE *fp); +static int * bnetFindVectorSupport (DdManager *dd, DdNode **list, int n); +static int buildExorBDD (DdManager *dd, BnetNode *nd, st_table *hash, int params, int nodrop); +static int buildMuxBDD (DdManager * dd, BnetNode * nd, st_table * hash, int params, int nodrop); +static int bnetSetLevel (BnetNetwork *net); +static int bnetLevelDFS (BnetNetwork *net, BnetNode *node); +static BnetNode ** bnetOrderRoots (BnetNetwork *net, int *nroots); +static int bnetLevelCompare (BnetNode **x, BnetNode **y); +static int bnetDfsOrder (DdManager *dd, BnetNetwork *net, BnetNode *node); + +/**AutomaticEnd***************************************************************/ + +/*---------------------------------------------------------------------------*/ +/* Definition of exported functions */ +/*---------------------------------------------------------------------------*/ + + +/**Function******************************************************************** + + Synopsis [Reads boolean network from blif file.] + + Description [Reads a boolean network from a blif file. A very restricted + subset of blif is supported. Specifically: +
            +
          • The only directives recognized are: +
              +
            • .model +
            • .inputs +
            • .outputs +
            • .latch +
            • .names +
            • .exdc +
            • .wire_load_slope +
            • .end +
            +
          • Latches must have an initial values and no other parameters + specified. +
          • Lines must not exceed MAXLENGTH-1 characters, and individual names must + not exceed 1023 characters. +
          + Caveat emptor: There may be other limitations as well. One should + check the syntax of the blif file with some other tool before relying + on this parser. Bnet_ReadNetwork returns a pointer to the network if + successful; NULL otherwise. + ] + + SideEffects [None] + + SeeAlso [Bnet_PrintNetwork Bnet_FreeNetwork] + +******************************************************************************/ +BnetNetwork * +Bnet_ReadNetwork( + FILE * fp /* pointer to the blif file */, + int pr /* verbosity level */) +{ + char *savestring; + char **list; + int i, j, n; + BnetNetwork *net; + BnetNode *newnode; + BnetNode *lastnode = NULL; + BnetTabline *newline; + BnetTabline *lastline; + char ***latches = NULL; + int maxlatches = 0; + int exdc = 0; + BnetNode *node; + int count; + + /* Allocate network object and initialize symbol table. */ + net = ALLOC(BnetNetwork,1); + if (net == NULL) goto failure; + memset((char *) net, 0, sizeof(BnetNetwork)); + net->hash = st_init_table(strcmp,st_strhash); + if (net->hash == NULL) goto failure; + + savestring = readString(fp); + if (savestring == NULL) goto failure; + net->nlatches = 0; + while (strcmp(savestring, ".model") == 0 || + strcmp(savestring, ".inputs") == 0 || + strcmp(savestring, ".outputs") == 0 || + strcmp(savestring, ".latch") == 0 || + strcmp(savestring, ".wire_load_slope") == 0 || + strcmp(savestring, ".exdc") == 0 || + strcmp(savestring, ".names") == 0 || strcmp(savestring,".end") == 0) { + if (strcmp(savestring, ".model") == 0) { + /* Read .model directive. */ + FREE(savestring); + /* Read network name. */ + savestring = readString(fp); + if (savestring == NULL) goto failure; + net->name = savestring; + } else if (strcmp(savestring, ".inputs") == 0) { + /* Read .inputs directive. */ + FREE(savestring); + /* Read input names. */ + list = readList(fp,&n); + if (list == NULL) goto failure; + if (pr > 2) printList(list,n); + /* Expect at least one input. */ + if (n < 1) { + (void) fprintf(stdout,"Empty input list.\n"); + goto failure; + } + if (exdc) { + for (i = 0; i < n; i++) + FREE(list[i]); + FREE(list); + savestring = readString(fp); + if (savestring == NULL) goto failure; + continue; + } + if (net->ninputs) { + net->inputs = REALLOC(char *, net->inputs, + (net->ninputs + n) * sizeof(char *)); + for (i = 0; i < n; i++) + net->inputs[net->ninputs + i] = list[i]; + } + else + net->inputs = list; + /* Create a node for each primary input. */ + for (i = 0; i < n; i++) { + newnode = ALLOC(BnetNode,1); + memset((char *) newnode, 0, sizeof(BnetNode)); + if (newnode == NULL) goto failure; + newnode->name = list[i]; + newnode->inputs = NULL; + newnode->type = BNET_INPUT_NODE; + newnode->active = FALSE; + newnode->nfo = 0; + newnode->ninp = 0; + newnode->f = NULL; + newnode->polarity = 0; + newnode->dd = NULL; + newnode->next = NULL; + if (lastnode == NULL) { + net->nodes = newnode; + } else { + lastnode->next = newnode; + } + lastnode = newnode; + } + net->npis += n; + net->ninputs += n; + } else if (strcmp(savestring, ".outputs") == 0) { + /* Read .outputs directive. We do not create nodes for the primary + ** outputs, because the nodes will be created when the same names + ** appear as outputs of some gates. + */ + FREE(savestring); + /* Read output names. */ + list = readList(fp,&n); + if (list == NULL) goto failure; + if (pr > 2) printList(list,n); + if (n < 1) { + (void) fprintf(stdout,"Empty .outputs list.\n"); + goto failure; + } + if (exdc) { + for (i = 0; i < n; i++) + FREE(list[i]); + FREE(list); + savestring = readString(fp); + if (savestring == NULL) goto failure; + continue; + } + if (net->noutputs) { + net->outputs = REALLOC(char *, net->outputs, + (net->noutputs + n) * sizeof(char *)); + for (i = 0; i < n; i++) + net->outputs[net->noutputs + i] = list[i]; + } else { + net->outputs = list; + } + net->npos += n; + net->noutputs += n; + } else if (strcmp(savestring,".wire_load_slope") == 0) { + FREE(savestring); + savestring = readString(fp); + net->slope = savestring; + } else if (strcmp(savestring,".latch") == 0) { + FREE(savestring); + newnode = ALLOC(BnetNode,1); + if (newnode == NULL) goto failure; + memset((char *) newnode, 0, sizeof(BnetNode)); + newnode->type = BNET_PRESENT_STATE_NODE; + list = readList(fp,&n); + if (list == NULL) goto failure; + if (pr > 2) printList(list,n); + /* Expect three names. */ + if (n != 3) { + (void) fprintf(stdout, + ".latch not followed by three tokens.\n"); + goto failure; + } + newnode->name = list[1]; + newnode->inputs = NULL; + newnode->ninp = 0; + newnode->f = NULL; + newnode->active = FALSE; + newnode->nfo = 0; + newnode->polarity = 0; + newnode->dd = NULL; + newnode->next = NULL; + if (lastnode == NULL) { + net->nodes = newnode; + } else { + lastnode->next = newnode; + } + lastnode = newnode; + /* Add next state variable to list. */ + if (maxlatches == 0) { + maxlatches = 20; + latches = ALLOC(char **,maxlatches); + } else if (maxlatches <= net->nlatches) { + maxlatches += 20; + latches = REALLOC(char **,latches,maxlatches); + } + latches[net->nlatches] = list; + net->nlatches++; + savestring = readString(fp); + if (savestring == NULL) goto failure; + } else if (strcmp(savestring,".names") == 0) { + FREE(savestring); + newnode = ALLOC(BnetNode,1); + memset((char *) newnode, 0, sizeof(BnetNode)); + if (newnode == NULL) goto failure; + list = readList(fp,&n); + if (list == NULL) goto failure; + if (pr > 2) printList(list,n); + /* Expect at least one name (the node output). */ + if (n < 1) { + (void) fprintf(stdout,"Missing output name.\n"); + goto failure; + } + newnode->name = list[n-1]; + newnode->inputs = list; + newnode->ninp = n-1; + newnode->active = FALSE; + newnode->nfo = 0; + newnode->polarity = 0; + if (newnode->ninp > 0) { + newnode->type = BNET_INTERNAL_NODE; + for (i = 0; i < net->noutputs; i++) { + if (strcmp(net->outputs[i], newnode->name) == 0) { + newnode->type = BNET_OUTPUT_NODE; + break; + } + } + } else { + newnode->type = BNET_CONSTANT_NODE; + } + newnode->dd = NULL; + newnode->next = NULL; + if (lastnode == NULL) { + net->nodes = newnode; + } else { + lastnode->next = newnode; + } + lastnode = newnode; + /* Read node function. */ + newnode->f = NULL; + if (exdc) { + newnode->exdc_flag = 1; + node = net->nodes; + while (node) { + if (node->type == BNET_OUTPUT_NODE && + strcmp(node->name, newnode->name) == 0) { + node->exdc = newnode; + break; + } + node = node->next; + } + } + savestring = readString(fp); + if (savestring == NULL) goto failure; + lastline = NULL; + while (savestring[0] != '.') { + /* Reading a table line. */ + newline = ALLOC(BnetTabline,1); + if (newline == NULL) goto failure; + newline->next = NULL; + if (lastline == NULL) { + newnode->f = newline; + } else { + lastline->next = newline; + } + lastline = newline; + if (newnode->type == BNET_INTERNAL_NODE || + newnode->type == BNET_OUTPUT_NODE) { + newline->values = savestring; + /* Read output 1 or 0. */ + savestring = readString(fp); + if (savestring == NULL) goto failure; + } else { + newline->values = NULL; + } + if (savestring[0] == '0') newnode->polarity = 1; + FREE(savestring); + savestring = readString(fp); + if (savestring == NULL) goto failure; + } + } else if (strcmp(savestring,".exdc") == 0) { + FREE(savestring); + exdc = 1; + } else if (strcmp(savestring,".end") == 0) { + FREE(savestring); + break; + } + if ((!savestring) || savestring[0] != '.') + savestring = readString(fp); + if (savestring == NULL) goto failure; + } + + /* Put nodes in symbol table. */ + newnode = net->nodes; + while (newnode != NULL) { + int retval = st_insert(net->hash,newnode->name,(char *) newnode); + if (retval == ST_OUT_OF_MEM) { + goto failure; + } else if (retval == 1) { + printf("Error: Multiple drivers for node %s\n", newnode->name); + goto failure; + } else { + if (pr > 2) printf("Inserted %s\n",newnode->name); + } + newnode = newnode->next; + } + + if (latches) { + net->latches = latches; + + count = 0; + net->outputs = REALLOC(char *, net->outputs, + (net->noutputs + net->nlatches) * sizeof(char *)); + for (i = 0; i < net->nlatches; i++) { + for (j = 0; j < net->noutputs; j++) { + if (strcmp(latches[i][0], net->outputs[j]) == 0) + break; + } + if (j < net->noutputs) + continue; + savestring = ALLOC(char, strlen(latches[i][0]) + 1); + strcpy(savestring, latches[i][0]); + net->outputs[net->noutputs + count] = savestring; + count++; + if (st_lookup(net->hash, savestring, &node)) { + if (node->type == BNET_INTERNAL_NODE) { + node->type = BNET_OUTPUT_NODE; + } + } + } + net->noutputs += count; + + net->inputs = REALLOC(char *, net->inputs, + (net->ninputs + net->nlatches) * sizeof(char *)); + for (i = 0; i < net->nlatches; i++) { + savestring = ALLOC(char, strlen(latches[i][1]) + 1); + strcpy(savestring, latches[i][1]); + net->inputs[net->ninputs + i] = savestring; + } + net->ninputs += net->nlatches; + } + + /* Compute fanout counts. For each node in the linked list, fetch + ** all its fanins using the symbol table, and increment the fanout of + ** each fanin. + */ + newnode = net->nodes; + while (newnode != NULL) { + BnetNode *auxnd; + for (i = 0; i < newnode->ninp; i++) { + if (!st_lookup(net->hash,newnode->inputs[i],&auxnd)) { + (void) fprintf(stdout,"%s not driven\n", newnode->inputs[i]); + goto failure; + } + auxnd->nfo++; + } + newnode = newnode->next; + } + + if (!bnetSetLevel(net)) goto failure; + + return(net); + +failure: + /* Here we should clean up the mess. */ + (void) fprintf(stdout,"Error in reading network from file.\n"); + return(NULL); + +} /* end of Bnet_ReadNetwork */ + + +/**Function******************************************************************** + + Synopsis [Prints a boolean network created by readNetwork.] + + Description [Prints to the standard output a boolean network created + by Bnet_ReadNetwork. Uses the blif format; this way, one can verify the + equivalence of the input and the output with, say, sis.] + + SideEffects [None] + + SeeAlso [Bnet_ReadNetwork] + +******************************************************************************/ +void +Bnet_PrintNetwork( + BnetNetwork * net /* boolean network */) +{ + BnetNode *nd; + BnetTabline *tl; + int i; + + if (net == NULL) return; + + (void) fprintf(stdout,".model %s\n", net->name); + (void) fprintf(stdout,".inputs"); + printList(net->inputs,net->npis); + (void) fprintf(stdout,".outputs"); + printList(net->outputs,net->npos); + for (i = 0; i < net->nlatches; i++) { + (void) fprintf(stdout,".latch"); + printList(net->latches[i],3); + } + nd = net->nodes; + while (nd != NULL) { + if (nd->type != BNET_INPUT_NODE && nd->type != BNET_PRESENT_STATE_NODE) { + (void) fprintf(stdout,".names"); + for (i = 0; i < nd->ninp; i++) { + (void) fprintf(stdout," %s",nd->inputs[i]); + } + (void) fprintf(stdout," %s\n",nd->name); + tl = nd->f; + while (tl != NULL) { + if (tl->values != NULL) { + (void) fprintf(stdout,"%s %d\n",tl->values, + 1 - nd->polarity); + } else { + (void) fprintf(stdout,"%d\n", 1 - nd->polarity); + } + tl = tl->next; + } + } + nd = nd->next; + } + (void) fprintf(stdout,".end\n"); + +} /* end of Bnet_PrintNetwork */ + + +/**Function******************************************************************** + + Synopsis [Frees a boolean network created by Bnet_ReadNetwork.] + + Description [] + + SideEffects [None] + + SeeAlso [Bnet_ReadNetwork] + +******************************************************************************/ +void +Bnet_FreeNetwork( + BnetNetwork * net) +{ + BnetNode *node, *nextnode; + BnetTabline *line, *nextline; + int i; + + FREE(net->name); + /* The input name strings are already pointed by the input nodes. + ** Here we only need to free the latch names and the array that + ** points to them. + */ + for (i = 0; i < net->nlatches; i++) { + FREE(net->inputs[net->npis + i]); + } + FREE(net->inputs); + /* Free the output name strings and then the array pointing to them. */ + for (i = 0; i < net->noutputs; i++) { + FREE(net->outputs[i]); + } + FREE(net->outputs); + + for (i = 0; i < net->nlatches; i++) { + FREE(net->latches[i][0]); + FREE(net->latches[i][1]); + FREE(net->latches[i][2]); + FREE(net->latches[i]); + } + if (net->nlatches) FREE(net->latches); + node = net->nodes; + while (node != NULL) { + nextnode = node->next; + if (node->type != BNET_PRESENT_STATE_NODE) + FREE(node->name); + for (i = 0; i < node->ninp; i++) { + FREE(node->inputs[i]); + } + if (node->inputs != NULL) { + FREE(node->inputs); + } + /* Free the function table. */ + line = node->f; + while (line != NULL) { + nextline = line->next; + FREE(line->values); + FREE(line); + line = nextline; + } + FREE(node); + node = nextnode; + } + st_free_table(net->hash); + if (net->slope != NULL) FREE(net->slope); + FREE(net); + +} /* end of Bnet_FreeNetwork */ + + +/**Function******************************************************************** + + Synopsis [Builds the BDD for the function of a node.] + + Description [Builds the BDD for the function of a node and stores a + pointer to it in the dd field of the node itself. The reference count + of the BDD is incremented. If params is BNET_LOCAL_DD, then the BDD is + built in terms of the local inputs to the node; otherwise, if params + is BNET_GLOBAL_DD, the BDD is built in terms of the network primary + inputs. To build the global BDD of a node, the BDDs for its local + inputs must exist. If that is not the case, Bnet_BuildNodeBDD + recursively builds them. Likewise, to create the local BDD for a node, + the local inputs must have variables assigned to them. If that is not + the case, Bnet_BuildNodeBDD recursively assigns variables to nodes. + Bnet_BuildNodeBDD returns 1 in case of success; 0 otherwise.] + + SideEffects [Sets the dd field of the node.] + + SeeAlso [] + +******************************************************************************/ +int +Bnet_BuildNodeBDD( + DdManager * dd /* DD manager */, + BnetNode * nd /* node of the boolean network */, + st_table * hash /* symbol table of the boolean network */, + int params /* type of DD to be built */, + int nodrop /* retain the intermediate node DDs until the end */) +{ + DdNode *func; + BnetNode *auxnd; + DdNode *tmp; + DdNode *prod, *var; + BnetTabline *line; + int i; + + if (nd->dd != NULL) return(1); + + if (nd->type == BNET_CONSTANT_NODE) { + if (nd->f == NULL) { /* constant 0 */ + func = Cudd_ReadLogicZero(dd); + } else { /* either constant depending on the polarity */ + func = Cudd_ReadOne(dd); + } + Cudd_Ref(func); + } else if (nd->type == BNET_INPUT_NODE || + nd->type == BNET_PRESENT_STATE_NODE) { + if (nd->active == TRUE) { /* a variable is already associated: use it */ + func = Cudd_ReadVars(dd,nd->var); + if (func == NULL) goto failure; + } else { /* no variable associated: get a new one */ + func = Cudd_bddNewVar(dd); + if (func == NULL) goto failure; + nd->var = func->index; + nd->active = TRUE; + } + Cudd_Ref(func); + } else if (buildExorBDD(dd,nd,hash,params,nodrop)) { + func = nd->dd; + } else if (buildMuxBDD(dd,nd,hash,params,nodrop)) { + func = nd->dd; + } else { /* type == BNET_INTERNAL_NODE or BNET_OUTPUT_NODE */ + /* Initialize the sum to logical 0. */ + func = Cudd_ReadLogicZero(dd); + Cudd_Ref(func); + + /* Build a term for each line of the table and add it to the + ** accumulator (func). + */ + line = nd->f; + while (line != NULL) { +#ifdef BNET_DEBUG + (void) fprintf(stdout,"line = %s\n", line->values); +#endif + /* Initialize the product to logical 1. */ + prod = Cudd_ReadOne(dd); + Cudd_Ref(prod); + /* Scan the table line. */ + for (i = 0; i < nd->ninp; i++) { + if (line->values[i] == '-') continue; + if (!st_lookup(hash,nd->inputs[i],&auxnd)) { + goto failure; + } + if (params == BNET_LOCAL_DD) { + if (auxnd->active == FALSE) { + if (!Bnet_BuildNodeBDD(dd,auxnd,hash,params,nodrop)) { + goto failure; + } + } + var = Cudd_ReadVars(dd,auxnd->var); + if (var == NULL) goto failure; + Cudd_Ref(var); + if (line->values[i] == '0') { + var = Cudd_Not(var); + } + } else { /* params == BNET_GLOBAL_DD */ + if (auxnd->dd == NULL) { + if (!Bnet_BuildNodeBDD(dd,auxnd,hash,params,nodrop)) { + goto failure; + } + } + if (line->values[i] == '1') { + var = auxnd->dd; + } else { /* line->values[i] == '0' */ + var = Cudd_Not(auxnd->dd); + } + } + tmp = Cudd_bddAnd(dd,prod,var); + if (tmp == NULL) goto failure; + Cudd_Ref(tmp); + Cudd_IterDerefBdd(dd,prod); + if (params == BNET_LOCAL_DD) { + Cudd_IterDerefBdd(dd,var); + } + prod = tmp; + } + tmp = Cudd_bddOr(dd,func,prod); + if (tmp == NULL) goto failure; + Cudd_Ref(tmp); + Cudd_IterDerefBdd(dd,func); + Cudd_IterDerefBdd(dd,prod); + func = tmp; + line = line->next; + } + /* Associate a variable to this node if local BDDs are being + ** built. This is done at the end, so that the primary inputs tend + ** to get lower indices. + */ + if (params == BNET_LOCAL_DD && nd->active == FALSE) { + DdNode *auxfunc = Cudd_bddNewVar(dd); + if (auxfunc == NULL) goto failure; + Cudd_Ref(auxfunc); + nd->var = auxfunc->index; + nd->active = TRUE; + Cudd_IterDerefBdd(dd,auxfunc); + } + } + if (nd->polarity == 1) { + nd->dd = Cudd_Not(func); + } else { + nd->dd = func; + } + + if (params == BNET_GLOBAL_DD && nodrop == FALSE) { + /* Decrease counters for all faninis. + ** When count reaches 0, the DD is freed. + */ + for (i = 0; i < nd->ninp; i++) { + if (!st_lookup(hash,nd->inputs[i],&auxnd)) { + goto failure; + } + auxnd->count--; + if (auxnd->count == 0) { + Cudd_IterDerefBdd(dd,auxnd->dd); + if (auxnd->type == BNET_INTERNAL_NODE || + auxnd->type == BNET_CONSTANT_NODE) auxnd->dd = NULL; + } + } + } + return(1); + +failure: + /* Here we should clean up the mess. */ + return(0); + +} /* end of Bnet_BuildNodeBDD */ + + +/**Function******************************************************************** + + Synopsis [Orders the BDD variables by DFS.] + + Description [Orders the BDD variables by DFS. Returns 1 in case of + success; 0 otherwise.] + + SideEffects [Uses the visited flags of the nodes.] + + SeeAlso [] + +******************************************************************************/ +int +Bnet_DfsVariableOrder( + DdManager * dd, + BnetNetwork * net) +{ + BnetNode **roots; + BnetNode *node; + int nroots; + int i; + + roots = bnetOrderRoots(net,&nroots); + if (roots == NULL) return(0); + for (i = 0; i < nroots; i++) { + if (!bnetDfsOrder(dd,net,roots[i])) { + FREE(roots); + return(0); + } + } + /* Clear visited flags. */ + node = net->nodes; + while (node != NULL) { + node->visited = 0; + node = node->next; + } + FREE(roots); + return(1); + +} /* end of Bnet_DfsVariableOrder */ + + +/**Function******************************************************************** + + Synopsis [Writes the network BDDs to a file in dot, blif, or daVinci + format.] + + Description [Writes the network BDDs to a file in dot, blif, or daVinci + format. If "-" is passed as file name, the BDDs are dumped to the + standard output. Returns 1 in case of success; 0 otherwise.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +int +Bnet_bddDump( + DdManager * dd /* DD manager */, + BnetNetwork * network /* network whose BDDs should be dumped */, + char * dfile /* file name */, + int dumpFmt /* 0 -> dot */, + int reencoded /* whether variables have been reencoded */) +{ + int noutputs; + FILE *dfp = NULL; + DdNode **outputs = NULL; + char **inames = NULL; + char **onames = NULL; + char **altnames = NULL; + BnetNode *node; + int i; + int retval = 0; /* 0 -> failure; 1 -> success */ + + /* Open dump file. */ + if (strcmp(dfile, "-") == 0) { + dfp = stdout; + } else { + dfp = fopen(dfile,"w"); + } + if (dfp == NULL) goto endgame; + + /* Initialize data structures. */ + noutputs = network->noutputs; + outputs = ALLOC(DdNode *,noutputs); + if (outputs == NULL) goto endgame; + onames = ALLOC(char *,noutputs); + if (onames == NULL) goto endgame; + inames = ALLOC(char *,Cudd_ReadSize(dd)); + if (inames == NULL) goto endgame; + + /* Find outputs and their names. */ + for (i = 0; i < network->nlatches; i++) { + onames[i] = network->latches[i][0]; + if (!st_lookup(network->hash,network->latches[i][0],&node)) { + goto endgame; + } + outputs[i] = node->dd; + } + for (i = 0; i < network->npos; i++) { + onames[i + network->nlatches] = network->outputs[i]; + if (!st_lookup(network->hash,network->outputs[i],&node)) { + goto endgame; + } + outputs[i + network->nlatches] = node->dd; + } + + /* Find the input names. */ + for (i = 0; i < network->ninputs; i++) { + if (!st_lookup(network->hash,network->inputs[i],&node)) { + goto endgame; + } + inames[node->var] = network->inputs[i]; + } + for (i = 0; i < network->nlatches; i++) { + if (!st_lookup(network->hash,network->latches[i][1],&node)) { + goto endgame; + } + inames[node->var] = network->latches[i][1]; + } + + if (reencoded == 1 && dumpFmt == 1) { + altnames = bnetGenerateNewNames(network->hash,network->ninputs); + if (altnames == NULL) { + retval = 0; + goto endgame; + } + retval = bnetDumpReencodingLogic(dd,network->name,noutputs,outputs, + inames,altnames,onames,dfp); + for (i = 0; i < network->ninputs; i++) { + FREE(altnames[i]); + } + FREE(altnames); + if (retval == 0) goto endgame; + } + + /* Dump the BDDs. */ + if (dumpFmt == 1) { + retval = Cudd_DumpBlif(dd,noutputs,outputs,inames,onames, + network->name,dfp,0); + } else if (dumpFmt == 2) { + retval = Cudd_DumpDaVinci(dd,noutputs,outputs,inames,onames,dfp); + } else if (dumpFmt == 3) { + retval = Cudd_DumpDDcal(dd,noutputs,outputs,inames,onames,dfp); + } else if (dumpFmt == 4) { + retval = Cudd_DumpFactoredForm(dd,noutputs,outputs,inames,onames,dfp); + } else if (dumpFmt == 5) { + retval = Cudd_DumpBlif(dd,noutputs,outputs,inames,onames, + network->name,dfp,1); + } else { + retval = Cudd_DumpDot(dd,noutputs,outputs,inames,onames,dfp); + } + +endgame: + if (dfp != stdout && dfp != NULL) { + if (fclose(dfp) == EOF) retval = 0; + } + if (outputs != NULL) FREE(outputs); + if (onames != NULL) FREE(onames); + if (inames != NULL) FREE(inames); + + return(retval); + +} /* end of Bnet_bddDump */ + + +/**Function******************************************************************** + + Synopsis [Writes an array of BDDs to a file in dot, blif, DDcal, + factored-form, daVinci, or blif-MV format.] + + Description [Writes an array of BDDs to a file in dot, blif, DDcal, + factored-form, daVinci, or blif-MV format. The BDDs and their names + are passed as arguments. The inputs and their names are taken from + the network. If "-" is passed as file name, the BDDs are dumped to + the standard output. Returns 1 in case of success; 0 otherwise.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +int +Bnet_bddArrayDump( + DdManager * dd /* DD manager */, + BnetNetwork * network /* network whose BDDs should be dumped */, + char * dfile /* file name */, + DdNode ** outputs /* BDDs to be dumped */, + char ** onames /* names of the BDDs to be dumped */, + int noutputs /* number of BDDs to be dumped */, + int dumpFmt /* 0 -> dot */) +{ + FILE *dfp = NULL; + char **inames = NULL; + BnetNode *node; + int i; + int retval = 0; /* 0 -> failure; 1 -> success */ + + /* Open dump file. */ + if (strcmp(dfile, "-") == 0) { + dfp = stdout; + } else { + dfp = fopen(dfile,"w"); + } + if (dfp == NULL) goto endgame; + + /* Initialize data structures. */ + inames = ALLOC(char *,Cudd_ReadSize(dd)); + if (inames == NULL) goto endgame; + for (i = 0; i < Cudd_ReadSize(dd); i++) { + inames[i] = NULL; + } + + /* Find the input names. */ + for (i = 0; i < network->ninputs; i++) { + if (!st_lookup(network->hash,network->inputs[i],&node)) { + goto endgame; + } + inames[node->var] = network->inputs[i]; + } + for (i = 0; i < network->nlatches; i++) { + if (!st_lookup(network->hash,network->latches[i][1],&node)) { + goto endgame; + } + inames[node->var] = network->latches[i][1]; + } + + /* Dump the BDDs. */ + if (dumpFmt == 1) { + retval = Cudd_DumpBlif(dd,noutputs,outputs,inames,onames, + network->name,dfp,0); + } else if (dumpFmt == 2) { + retval = Cudd_DumpDaVinci(dd,noutputs,outputs,inames,onames,dfp); + } else if (dumpFmt == 3) { + retval = Cudd_DumpDDcal(dd,noutputs,outputs,inames,onames,dfp); + } else if (dumpFmt == 4) { + retval = Cudd_DumpFactoredForm(dd,noutputs,outputs,inames,onames,dfp); + } else if (dumpFmt == 5) { + retval = Cudd_DumpBlif(dd,noutputs,outputs,inames,onames, + network->name,dfp,1); + } else { + retval = Cudd_DumpDot(dd,noutputs,outputs,inames,onames,dfp); + } + +endgame: + if (dfp != stdout && dfp != NULL) { + if (fclose(dfp) == EOF) retval = 0; + } + if (inames != NULL) FREE(inames); + + return(retval); + +} /* end of Bnet_bddArrayDump */ + + +/**Function******************************************************************** + + Synopsis [Reads the variable order from a file.] + + Description [Reads the variable order from a file. + Returns 1 if successful; 0 otherwise.] + + SideEffects [The BDDs for the primary inputs and present state variables + are built.] + + SeeAlso [] + +*****************************************************************************/ +int +Bnet_ReadOrder( + DdManager * dd, + char * ordFile, + BnetNetwork * net, + int locGlob, + int nodrop) +{ + FILE *fp; + st_table *dict; + int result; + BnetNode *node; + char name[MAXLENGTH]; + + if (ordFile == NULL) { + return(0); + } + + dict = st_init_table(strcmp,st_strhash); + if (dict == NULL) { + return(0); + } + + if ((fp = fopen(ordFile,"r")) == NULL) { + (void) fprintf(stderr,"Unable to open %s\n",ordFile); + st_free_table(dict); + return(0); + } + + while (!feof(fp)) { + result = fscanf(fp, "%s", name); + if (result == EOF) { + break; + } else if (result != 1) { + st_free_table(dict); + return(0); + } else if (strlen(name) > MAXLENGTH) { + st_free_table(dict); + return(0); + } + /* There should be a node named "name" in the network. */ + if (!st_lookup(net->hash,name,&node)) { + (void) fprintf(stderr,"Unknown name in order file (%s)\n", name); + st_free_table(dict); + return(0); + } + /* A name should not appear more than once in the order. */ + if (st_is_member(dict,name)) { + (void) fprintf(stderr,"Duplicate name in order file (%s)\n", name); + st_free_table(dict); + return(0); + } + /* The name should correspond to a primary input or present state. */ + if (node->type != BNET_INPUT_NODE && + node->type != BNET_PRESENT_STATE_NODE) { + (void) fprintf(stderr,"%s has the wrong type (%d)\n", name, + node->type); + st_free_table(dict); + return(0); + } + /* Insert in table. Use node->name rather than name, because the + ** latter gets overwritten. + */ + if (st_insert(dict,node->name,NULL) == ST_OUT_OF_MEM) { + (void) fprintf(stderr,"Out of memory in Bnet_ReadOrder\n"); + st_free_table(dict); + return(0); + } + result = Bnet_BuildNodeBDD(dd,node,net->hash,locGlob,nodrop); + if (result == 0) { + (void) fprintf(stderr,"Construction of BDD failed\n"); + st_free_table(dict); + return(0); + } + } /* while (!feof(fp)) */ + result = fclose(fp); + if (result == EOF) { + (void) fprintf(stderr,"Error closing order file %s\n", ordFile); + st_free_table(dict); + return(0); + } + + /* The number of names in the order file should match exactly the + ** number of primary inputs and present states. + */ + if (st_count(dict) != net->ninputs) { + (void) fprintf(stderr,"Order incomplete: %d names instead of %d\n", + st_count(dict), net->ninputs); + st_free_table(dict); + return(0); + } + + st_free_table(dict); + return(1); + +} /* end of Bnet_ReadOrder */ + + +/**Function******************************************************************** + + Synopsis [Prints the order of the DD variables of a network.] + + Description [Prints the order of the DD variables of a network. + Only primary inputs and present states are printed. + Returns 1 if successful; 0 otherwise.] + + SideEffects [None] + + SeeAlso [] + +*****************************************************************************/ +int +Bnet_PrintOrder( + BnetNetwork * net, + DdManager *dd) +{ + char **names; /* array used to print variable orders */ + int level; /* position of a variable in current order */ + BnetNode *node; /* auxiliary pointer to network node */ + int i,j; + int retval; + int nvars; + + nvars = Cudd_ReadSize(dd); + names = ALLOC(char *, nvars); + if (names == NULL) return(0); + for (i = 0; i < nvars; i++) { + names[i] = NULL; + } + for (i = 0; i < net->npis; i++) { + if (!st_lookup(net->hash,net->inputs[i],&node)) { + FREE(names); + return(0); + } + if (node->dd == NULL) { + FREE(names); + return(0); + } + level = Cudd_ReadPerm(dd,node->var); + names[level] = node->name; + } + for (i = 0; i < net->nlatches; i++) { + if (!st_lookup(net->hash,net->latches[i][1],&node)) { + FREE(names); + return(0); + } + if (node->dd == NULL) { + FREE(names); + return(0); + } + level = Cudd_ReadPerm(dd,node->var); + names[level] = node->name; + } + for (i = 0, j = 0; i < nvars; i++) { + if (names[i] == NULL) continue; + if ((j%8 == 0)&&j) { + retval = printf("\n"); + if (retval == EOF) { + FREE(names); + return(0); + } + } + retval = printf("%s ",names[i]); + if (retval == EOF) { + FREE(names); + return(0); + } + j++; + } + FREE(names); + retval = printf("\n"); + if (retval == EOF) { + return(0); + } + return(1); + +} /* end of Bnet_PrintOrder */ + + +/*---------------------------------------------------------------------------*/ +/* Definition of internal functions */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Definition of static functions */ +/*---------------------------------------------------------------------------*/ + + +/**Function******************************************************************** + + Synopsis [Reads a string from a file.] + + Description [Reads a string from a file. The string can be MAXLENGTH-1 + characters at most. readString allocates memory to hold the string and + returns a pointer to the result if successful. It returns NULL + otherwise.] + + SideEffects [None] + + SeeAlso [readList] + +******************************************************************************/ +static char * +readString( + FILE * fp /* pointer to the file from which the string is read */) +{ + char *savestring; + int length; + + while (!CurPos) { + if (!fgets(BuffLine, MAXLENGTH, fp)) + return(NULL); + BuffLine[strlen(BuffLine) - 1] = '\0'; + CurPos = strtok(BuffLine, " \t"); + if (CurPos && CurPos[0] == '#') CurPos = (char *)NULL; + } + length = strlen(CurPos); + savestring = ALLOC(char,length+1); + if (savestring == NULL) + return(NULL); + strcpy(savestring,CurPos); + CurPos = strtok(NULL, " \t"); + return(savestring); + +} /* end of readString */ + + +/**Function******************************************************************** + + Synopsis [Reads a list of strings from a file.] + + Description [Reads a list of strings from a line of a file. + The strings are sequences of characters separated by spaces or tabs. + The total length of the list, white space included, must not exceed + MAXLENGTH-1 characters. readList allocates memory for the strings and + creates an array of pointers to the individual lists. Only two pieces + of memory are allocated by readList: One to hold all the strings, + and one to hold the pointers to them. Therefore, when freeing the + memory allocated by readList, only the pointer to the list of + pointers, and the pointer to the beginning of the first string should + be freed. readList returns the pointer to the list of pointers if + successful; NULL otherwise.] + + SideEffects [n is set to the number of strings in the list.] + + SeeAlso [readString printList] + +******************************************************************************/ +static char ** +readList( + FILE * fp /* pointer to the file from which the list is read */, + int * n /* on return, number of strings in the list */) +{ + char *savestring; + int length; + char *stack[8192]; + char **list; + int i, count = 0; + + while (CurPos) { + if (strcmp(CurPos, "\\") == 0) { + CurPos = (char *)NULL; + while (!CurPos) { + if (!fgets(BuffLine, MAXLENGTH, fp)) return(NULL); + BuffLine[strlen(BuffLine) - 1] = '\0'; + CurPos = strtok(BuffLine, " \t"); + } + } + length = strlen(CurPos); + savestring = ALLOC(char,length+1); + if (savestring == NULL) return(NULL); + strcpy(savestring,CurPos); + stack[count] = savestring; + count++; + CurPos = strtok(NULL, " \t"); + } + list = ALLOC(char *, count); + for (i = 0; i < count; i++) + list[i] = stack[i]; + *n = count; + return(list); + +} /* end of readList */ + + +/**Function******************************************************************** + + Synopsis [Prints a list of strings to the standard output.] + + Description [Prints a list of strings to the standard output. The list + is in the format created by readList.] + + SideEffects [None] + + SeeAlso [readList Bnet_PrintNetwork] + +******************************************************************************/ +static void +printList( + char ** list /* list of pointers to strings */, + int n /* length of the list */) +{ + int i; + + for (i = 0; i < n; i++) { + (void) fprintf(stdout," %s",list[i]); + } + (void) fprintf(stdout,"\n"); + +} /* end of printList */ + + +/**Function******************************************************************** + + Synopsis [Generates names not currently in a symbol table.] + + Description [Generates n names not currently in the symbol table hash. + The pointer to the symbol table may be NULL, in which case no test is + made. The names generated by the procedure are unique. So, if there is + no possibility of conflict with pre-existing names, NULL can be passed + for the hash table. Returns an array of names if succesful; NULL + otherwise.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +static char ** +bnetGenerateNewNames( + st_table * hash /* table of existing names (or NULL) */, + int n /* number of names to be generated */) +{ + char **list; + char name[256]; + int i; + + if (n < 1) return(NULL); + + list = ALLOC(char *,n); + if (list == NULL) return(NULL); + for (i = 0; i < n; i++) { + do { + sprintf(name, "var%d", newNameNumber); + newNameNumber++; + } while (hash != NULL && st_is_member(hash,name)); + list[i] = util_strsav(name); + } + + return(list); + +} /* bnetGenerateNewNames */ + + +/**Function******************************************************************** + + Synopsis [Writes blif for the reencoding logic.] + + Description [] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +static int +bnetDumpReencodingLogic( + DdManager * dd /* DD manager */, + char * mname /* model name */, + int noutputs /* number of outputs */, + DdNode ** outputs /* array of network outputs */, + char ** inames /* array of network input names */, + char ** altnames /* array of names of reencoded inputs */, + char ** onames /* array of network output names */, + FILE * fp /* file pointer */) +{ + int i; + int retval; + int nvars = Cudd_ReadSize(dd); + int *support = NULL; + + support = bnetFindVectorSupport(dd,outputs,noutputs); + if (support == NULL) return(0); + + /* Write the header (.model .inputs .outputs). */ + retval = fprintf(fp,".model %s.global\n.inputs",mname); + if (retval == EOF) goto failure; + + for (i = 0; i < nvars; i++) { + if ((i%8 == 0)&&i) { + retval = fprintf(fp," \\\n"); + if (retval == EOF) goto failure; + } + retval = fprintf(fp," %s", inames[i]); + if (retval == EOF) goto failure; + } + + /* Write the .output line. */ + retval = fprintf(fp,"\n.outputs"); + if (retval == EOF) goto failure; + for (i = 0; i < noutputs; i++) { + if ((i%8 == 0)&&i) { + retval = fprintf(fp," \\\n"); + if (retval == EOF) goto failure; + } + retval = fprintf(fp," %s", onames[i]); + if (retval == EOF) goto failure; + } + retval = fprintf(fp,"\n"); + if (retval == EOF) goto failure; + + /* Instantiate main subcircuit. */ + retval = fprintf(fp,"\n.subckt %s", mname); + if (retval == EOF) goto failure; + for (i = 0; i < nvars; i++) { + if ((i%8 == 0)&&i) { + retval = fprintf(fp," \\\n"); + if (retval == EOF) goto failure; + } + if (support[i] == 1) { + retval = fprintf(fp," %s=%s", inames[i], altnames[i]); + if (retval == EOF) goto failure; + } + } + for (i = 0; i < noutputs; i++) { + if ((i%8 == 0)&&i) { + retval = fprintf(fp," \\\n"); + if (retval == EOF) goto failure; + } + retval = fprintf(fp," %s=%s", onames[i], onames[i]); + if (retval == EOF) goto failure; + } + retval = fprintf(fp,"\n"); + if (retval == EOF) goto failure; + + /* Instantiate reencoding subcircuit. */ + retval = fprintf(fp,"\n.subckt %s.reencode",mname); + if (retval == EOF) goto failure; + for (i = 0; i < nvars; i++) { + if ((i%8 == 0)&&i) { + retval = fprintf(fp," \\\n"); + if (retval == EOF) goto failure; + } + retval = fprintf(fp," %s=%s", inames[i], inames[i]); + if (retval == EOF) goto failure; + } + retval = fprintf(fp," \\\n"); + if (retval == EOF) goto failure; + for (i = 0; i < nvars; i++) { + if ((i%8 == 0)&&i) { + retval = fprintf(fp," \\\n"); + if (retval == EOF) goto failure; + } + if (support[i] == 1) { + retval = fprintf(fp," %s=%s", altnames[i],altnames[i]); + if (retval == EOF) goto failure; + } + } + retval = fprintf(fp,"\n"); + if (retval == EOF) goto failure; + + /* Write trailer. */ + retval = fprintf(fp,".end\n\n"); + if (retval == EOF) goto failure; + + /* Write reencoding subcircuit. */ + retval = bnetBlifWriteReencode(dd,mname,inames,altnames,support,fp); + if (retval == EOF) goto failure; + + FREE(support); + return(1); + +failure: + if (support != NULL) FREE(support); + return(0); + +} /* end of bnetDumpReencodingLogic */ + + +/**Function******************************************************************** + + Synopsis [Writes blif for the truth table of an n-input xnor.] + + Description [Writes blif for the truth table of an n-input + xnor. Returns 1 if successful; 0 otherwise.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +#if 0 +static int +bnetBlifXnorTable( + FILE * fp /* file pointer */, + int n /* number of inputs */) +{ + int power; /* 2 to the power n */ + int i,j,k; + int nzeroes; + int retval; + char *line; + + line = ALLOC(char,n+1); + if (line == NULL) return(0); + line[n] = '\0'; + + for (i = 0, power = 1; i < n; i++) { + power *= 2; + } + + for (i = 0; i < power; i++) { + k = i; + nzeroes = 0; + for (j = 0; j < n; j++) { + if (k & 1) { + line[j] = '1'; + } else { + line[j] = '0'; + nzeroes++; + } + k >>= 1; + } + if ((nzeroes & 1) == 0) { + retval = fprintf(fp,"%s 1\n",line); + if (retval == 0) return(0); + } + } + return(1); + +} /* end of bnetBlifXnorTable */ +#endif + + +/**Function******************************************************************** + + Synopsis [Writes blif for the reencoding logic.] + + Description [Writes blif for the reencoding logic. Exclusive NORs + with more than two inputs are decomposed into cascaded two-input + gates. Returns 1 if successful; 0 otherwise.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +static int +bnetBlifWriteReencode( + DdManager * dd, + char * mname, + char ** inames, + char ** altnames, + int * support, + FILE * fp) +{ + int retval; + int nvars = Cudd_ReadSize(dd); + int i,j; + int ninp; + + /* Write the header (.model .inputs .outputs). */ + retval = fprintf(fp,".model %s.reencode\n.inputs",mname); + if (retval == EOF) return(0); + + for (i = 0; i < nvars; i++) { + if ((i%8 == 0)&&i) { + retval = fprintf(fp," \\\n"); + if (retval == EOF) goto failure; + } + retval = fprintf(fp," %s", inames[i]); + if (retval == EOF) goto failure; + } + + /* Write the .output line. */ + retval = fprintf(fp,"\n.outputs"); + if (retval == EOF) goto failure; + for (i = 0; i < nvars; i++) { + if ((i%8 == 0)&&i) { + retval = fprintf(fp," \\\n"); + if (retval == EOF) goto failure; + } + if (support[i] == 1) { + retval = fprintf(fp," %s", altnames[i]); + if (retval == EOF) goto failure; + } + } + retval = fprintf(fp,"\n"); + if (retval == EOF) goto failure; + + /* Instantiate exclusive nors. */ + for (i = 0; i < nvars; i++) { + char *in1 = NULL; + char *in2 = NULL; + char **oname; + if (support[i] == 0) continue; + ninp = 0; + for (j = 0; j < nvars; j++) { + if (Cudd_ReadLinear(dd,i,j)) { + switch (ninp) { + case 0: + in1 = inames[j]; + ninp++; + break; + case 1: + in2 = inames[j]; + ninp++; + break; + case 2: + oname = bnetGenerateNewNames(NULL,1); + retval = fprintf(fp,".names %s %s %s\n11 1\n00 1\n", + in1, in2, oname[0]); + if (retval == EOF) goto failure; + in1 = oname[0]; + in2 = inames[j]; + FREE(oname); + break; + default: + goto failure; + } + } + } + switch (ninp) { + case 1: + retval = fprintf(fp,".names %s %s\n1 1\n", in1, altnames[i]); + if (retval == EOF) goto failure; + break; + case 2: + retval = fprintf(fp,".names %s %s %s\n11 1\n00 1\n", + in1, in2, altnames[i]); + if (retval == EOF) goto failure; + break; + default: + goto failure; + } + } + + /* Write trailer. */ + retval = fprintf(fp,"\n.end\n\n"); + if (retval == EOF) goto failure; + + return(1); + +failure: + return(0); + +} /* end of bnetBlifWriteReencode */ + + +/**Function******************************************************************** + + Synopsis [Finds the support of a list of DDs.] + + Description [] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +static int * +bnetFindVectorSupport( + DdManager * dd, + DdNode ** list, + int n) +{ + DdNode *support = NULL; + DdNode *scan; + int *array = NULL; + int nvars = Cudd_ReadSize(dd); + int i; + + /* Build an array with the support of the functions in list. */ + array = ALLOC(int,nvars); + if (array == NULL) return(NULL); + for (i = 0; i < nvars; i++) { + array[i] = 0; + } + + /* Take the union of the supports of each output function. */ + for (i = 0; i < n; i++) { + support = Cudd_Support(dd,list[i]); + if (support == NULL) { + FREE(array); + return(NULL); + } + Cudd_Ref(support); + scan = support; + while (!Cudd_IsConstant(scan)) { + array[scan->index] = 1; + scan = Cudd_T(scan); + } + Cudd_IterDerefBdd(dd,support); + } + + return(array); + +} /* end of bnetFindVectorSupport */ + + +/**Function******************************************************************** + + Synopsis [Builds BDD for a XOR function.] + + Description [Checks whether a function is a XOR with 2 or 3 inputs. If so, + it builds the BDD. Returns 1 if the BDD has been built; 0 otherwise.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +static int +buildExorBDD( + DdManager * dd, + BnetNode * nd, + st_table * hash, + int params, + int nodrop) +{ + int check[8]; + int i; + int nlines; + BnetTabline *line; + DdNode *func, *var, *tmp; + BnetNode *auxnd; + + if (nd->ninp < 2 || nd->ninp > 3) return(0); + + nlines = 1 << (nd->ninp - 1); + for (i = 0; i < 8; i++) check[i] = 0; + line = nd->f; + while (line != NULL) { + int num = 0; + int count = 0; + nlines--; + for (i = 0; i < nd->ninp; i++) { + num <<= 1; + if (line->values[i] == '-') { + return(0); + } else if (line->values[i] == '1') { + count++; + num++; + } + } + if ((count & 1) == 0) return(0); + if (check[num]) return(0); + line = line->next; + } + if (nlines != 0) return(0); + + /* Initialize the exclusive sum to logical 0. */ + func = Cudd_ReadLogicZero(dd); + Cudd_Ref(func); + + /* Scan the inputs. */ + for (i = 0; i < nd->ninp; i++) { + if (!st_lookup(hash, nd->inputs[i], &auxnd)) { + goto failure; + } + if (params == BNET_LOCAL_DD) { + if (auxnd->active == FALSE) { + if (!Bnet_BuildNodeBDD(dd,auxnd,hash,params,nodrop)) { + goto failure; + } + } + var = Cudd_ReadVars(dd,auxnd->var); + if (var == NULL) goto failure; + Cudd_Ref(var); + } else { /* params == BNET_GLOBAL_DD */ + if (auxnd->dd == NULL) { + if (!Bnet_BuildNodeBDD(dd,auxnd,hash,params,nodrop)) { + goto failure; + } + } + var = auxnd->dd; + } + tmp = Cudd_bddXor(dd,func,var); + if (tmp == NULL) goto failure; + Cudd_Ref(tmp); + Cudd_IterDerefBdd(dd,func); + if (params == BNET_LOCAL_DD) { + Cudd_IterDerefBdd(dd,var); + } + func = tmp; + } + nd->dd = func; + + /* Associate a variable to this node if local BDDs are being + ** built. This is done at the end, so that the primary inputs tend + ** to get lower indices. + */ + if (params == BNET_LOCAL_DD && nd->active == FALSE) { + DdNode *auxfunc = Cudd_bddNewVar(dd); + if (auxfunc == NULL) goto failure; + Cudd_Ref(auxfunc); + nd->var = auxfunc->index; + nd->active = TRUE; + Cudd_IterDerefBdd(dd,auxfunc); + } + + return(1); +failure: + return(0); + +} /* end of buildExorBDD */ + + +/**Function******************************************************************** + + Synopsis [Builds BDD for a multiplexer.] + + Description [Checks whether a function is a 2-to-1 multiplexer. If so, + it builds the BDD. Returns 1 if the BDD has been built; 0 otherwise.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +static int +buildMuxBDD( + DdManager * dd, + BnetNode * nd, + st_table * hash, + int params, + int nodrop) +{ + BnetTabline *line; + char *values[2]; + int mux[2]; + int phase[2]; + int j; + int nlines = 0; + int controlC = -1; + int controlR = -1; + DdNode *func, *f, *g, *h; + BnetNode *auxnd; + + if (nd->ninp != 3) return(0); + + for (line = nd->f; line != NULL; line = line->next) { + int dc = 0; + if (nlines > 1) return(0); + values[nlines] = line->values; + for (j = 0; j < 3; j++) { + if (values[nlines][j] == '-') { + if (dc) return(0); + dc = 1; + } + } + if (!dc) return(0); + nlines++; + } + /* At this point we know we have: + ** 3 inputs + ** 2 lines + ** 1 dash in each line + ** If the two dashes are not in the same column, then there is + ** exaclty one column without dashes: the control column. + */ + for (j = 0; j < 3; j++) { + if (values[0][j] == '-' && values[1][j] == '-') return(0); + if (values[0][j] != '-' && values[1][j] != '-') { + if (values[0][j] == values[1][j]) return(0); + controlC = j; + controlR = values[0][j] == '0'; + } + } + assert(controlC != -1 && controlR != -1); + /* At this point we know that there is indeed no column with two + ** dashes. The control column has been identified, and we know that + ** its two elelments are different. */ + for (j = 0; j < 3; j++) { + if (j == controlC) continue; + if (values[controlR][j] == '1') { + mux[0] = j; + phase[0] = 0; + } else if (values[controlR][j] == '0') { + mux[0] = j; + phase[0] = 1; + } else if (values[1-controlR][j] == '1') { + mux[1] = j; + phase[1] = 0; + } else if (values[1-controlR][j] == '0') { + mux[1] = j; + phase[1] = 1; + } + } + + /* Get the inputs. */ + if (!st_lookup(hash, nd->inputs[controlC], &auxnd)) { + goto failure; + } + if (params == BNET_LOCAL_DD) { + if (auxnd->active == FALSE) { + if (!Bnet_BuildNodeBDD(dd,auxnd,hash,params,nodrop)) { + goto failure; + } + } + f = Cudd_ReadVars(dd,auxnd->var); + if (f == NULL) goto failure; + Cudd_Ref(f); + } else { /* params == BNET_GLOBAL_DD */ + if (auxnd->dd == NULL) { + if (!Bnet_BuildNodeBDD(dd,auxnd,hash,params,nodrop)) { + goto failure; + } + } + f = auxnd->dd; + } + if (!st_lookup(hash, nd->inputs[mux[0]], &auxnd)) { + goto failure; + } + if (params == BNET_LOCAL_DD) { + if (auxnd->active == FALSE) { + if (!Bnet_BuildNodeBDD(dd,auxnd,hash,params,nodrop)) { + goto failure; + } + } + g = Cudd_ReadVars(dd,auxnd->var); + if (g == NULL) goto failure; + Cudd_Ref(g); + } else { /* params == BNET_GLOBAL_DD */ + if (auxnd->dd == NULL) { + if (!Bnet_BuildNodeBDD(dd,auxnd,hash,params,nodrop)) { + goto failure; + } + } + g = auxnd->dd; + } + g = Cudd_NotCond(g,phase[0]); + if (!st_lookup(hash, nd->inputs[mux[1]], &auxnd)) { + goto failure; + } + if (params == BNET_LOCAL_DD) { + if (auxnd->active == FALSE) { + if (!Bnet_BuildNodeBDD(dd,auxnd,hash,params,nodrop)) { + goto failure; + } + } + h = Cudd_ReadVars(dd,auxnd->var); + if (h == NULL) goto failure; + Cudd_Ref(h); + } else { /* params == BNET_GLOBAL_DD */ + if (auxnd->dd == NULL) { + if (!Bnet_BuildNodeBDD(dd,auxnd,hash,params,nodrop)) { + goto failure; + } + } + h = auxnd->dd; + } + h = Cudd_NotCond(h,phase[1]); + func = Cudd_bddIte(dd,f,g,h); + if (func == NULL) goto failure; + Cudd_Ref(func); + if (params == BNET_LOCAL_DD) { + Cudd_IterDerefBdd(dd,f); + Cudd_IterDerefBdd(dd,g); + Cudd_IterDerefBdd(dd,h); + } + nd->dd = func; + + /* Associate a variable to this node if local BDDs are being + ** built. This is done at the end, so that the primary inputs tend + ** to get lower indices. + */ + if (params == BNET_LOCAL_DD && nd->active == FALSE) { + DdNode *auxfunc = Cudd_bddNewVar(dd); + if (auxfunc == NULL) goto failure; + Cudd_Ref(auxfunc); + nd->var = auxfunc->index; + nd->active = TRUE; + Cudd_IterDerefBdd(dd,auxfunc); + } + + return(1); +failure: + return(0); + +} /* end of buildExorBDD */ + + +/**Function******************************************************************** + + Synopsis [Sets the level of each node.] + + Description [Sets the level of each node. Returns 1 if successful; 0 + otherwise.] + + SideEffects [Changes the level and visited fields of the nodes it + visits.] + + SeeAlso [bnetLevelDFS] + +******************************************************************************/ +static int +bnetSetLevel( + BnetNetwork * net) +{ + BnetNode *node; + + /* Recursively visit nodes. This is pretty inefficient, because we + ** visit all nodes in this loop, and most of them in the recursive + ** calls to bnetLevelDFS. However, this approach guarantees that + ** all nodes will be reached ven if there are dangling outputs. */ + node = net->nodes; + while (node != NULL) { + if (!bnetLevelDFS(net,node)) return(0); + node = node->next; + } + + /* Clear visited flags. */ + node = net->nodes; + while (node != NULL) { + node->visited = 0; + node = node->next; + } + return(1); + +} /* end of bnetSetLevel */ + + +/**Function******************************************************************** + + Synopsis [Does a DFS from a node setting the level field.] + + Description [Does a DFS from a node setting the level field. Returns + 1 if successful; 0 otherwise.] + + SideEffects [Changes the level and visited fields of the nodes it + visits.] + + SeeAlso [bnetSetLevel] + +******************************************************************************/ +static int +bnetLevelDFS( + BnetNetwork * net, + BnetNode * node) +{ + int i; + BnetNode *auxnd; + + if (node->visited == 1) { + return(1); + } + + node->visited = 1; + + /* Graphical sources have level 0. This is the final value if the + ** node has no fan-ins. Otherwise the successive loop will + ** increase the level. */ + node->level = 0; + for (i = 0; i < node->ninp; i++) { + if (!st_lookup(net->hash, node->inputs[i], &auxnd)) { + return(0); + } + if (!bnetLevelDFS(net,auxnd)) { + return(0); + } + if (auxnd->level >= node->level) node->level = 1 + auxnd->level; + } + return(1); + +} /* end of bnetLevelDFS */ + + +/**Function******************************************************************** + + Synopsis [Orders network roots for variable ordering.] + + Description [Orders network roots for variable ordering. Returns + an array with the ordered outputs and next state variables if + successful; NULL otherwise.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +static BnetNode ** +bnetOrderRoots( + BnetNetwork * net, + int * nroots) +{ + int i, noutputs; + BnetNode *node; + BnetNode **nodes = NULL; + + /* Initialize data structures. */ + noutputs = net->noutputs; + nodes = ALLOC(BnetNode *, noutputs); + if (nodes == NULL) goto endgame; + + /* Find output names and levels. */ + for (i = 0; i < net->noutputs; i++) { + if (!st_lookup(net->hash,net->outputs[i],&node)) { + goto endgame; + } + nodes[i] = node; + } + + qsort((void *)nodes, noutputs, sizeof(BnetNode *), + (DD_QSFP)bnetLevelCompare); + *nroots = noutputs; + return(nodes); + +endgame: + if (nodes != NULL) FREE(nodes); + return(NULL); + +} /* end of bnetOrderRoots */ + + +/**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 +bnetLevelCompare( + BnetNode ** x, + BnetNode ** y) +{ + return((*y)->level - (*x)->level); + +} /* end of bnetLevelCompare */ + + +/**Function******************************************************************** + + Synopsis [Does a DFS from a node ordering the inputs.] + + Description [Does a DFS from a node ordering the inputs. Returns + 1 if successful; 0 otherwise.] + + SideEffects [Changes visited fields of the nodes it visits.] + + SeeAlso [Bnet_DfsVariableOrder] + +******************************************************************************/ +static int +bnetDfsOrder( + DdManager * dd, + BnetNetwork * net, + BnetNode * node) +{ + int i; + BnetNode *auxnd; + BnetNode **fanins; + + if (node->visited == 1) { + return(1); + } + + node->visited = 1; + if (node->type == BNET_INPUT_NODE || + node->type == BNET_PRESENT_STATE_NODE) { + node->dd = Cudd_bddNewVar(dd); + if (node->dd == NULL) return(0); + Cudd_Ref(node->dd); + node->active = TRUE; + node->var = node->dd->index; + return(1); + } + + fanins = ALLOC(BnetNode *, node->ninp); + if (fanins == NULL) return(0); + + for (i = 0; i < node->ninp; i++) { + if (!st_lookup(net->hash, node->inputs[i], &auxnd)) { + FREE(fanins); + return(0); + } + fanins[i] = auxnd; + } + + qsort((void *)fanins, node->ninp, sizeof(BnetNode *), + (DD_QSFP)bnetLevelCompare); + for (i = 0; i < node->ninp; i++) { + /* for (i = node->ninp - 1; i >= 0; i--) { */ + int res = bnetDfsOrder(dd,net,fanins[i]); + if (res == 0) { + FREE(fanins); + return(0); + } + } + FREE(fanins); + return(1); + +} /* end of bnetLevelDFS */ diff --git a/distr/nanotrav/bnet.h b/distr/nanotrav/bnet.h new file mode 100644 index 0000000..195b8f2 --- /dev/null +++ b/distr/nanotrav/bnet.h @@ -0,0 +1,187 @@ +/**CHeaderFile***************************************************************** + + FileName [bnet.h] + + PackageName [bnet] + + Synopsis [Simple-minded package to read a blif file.] + + 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: bnet.h,v 1.12 2004/08/13 18:28:28 fabio Exp fabio $] + +******************************************************************************/ + +#ifndef _BNET +#define _BNET + +/*---------------------------------------------------------------------------*/ +/* Nested includes */ +/*---------------------------------------------------------------------------*/ + +#include "util.h" +#include "st.h" +#include "cudd.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/*---------------------------------------------------------------------------*/ +/* Constant declarations */ +/*---------------------------------------------------------------------------*/ + +/* Different types of nodes. (Used in the "BnetNode" type.) */ +#define BNET_CONSTANT_NODE 0 +#define BNET_INPUT_NODE 1 +#define BNET_PRESENT_STATE_NODE 2 +#define BNET_INTERNAL_NODE 3 +#define BNET_OUTPUT_NODE 4 +#define BNET_NEXT_STATE_NODE 5 + +/* Type of DD of a node. */ +#define BNET_LOCAL_DD 0 +#define BNET_GLOBAL_DD 1 + + +/*---------------------------------------------------------------------------*/ +/* Stucture declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Type declarations */ +/*---------------------------------------------------------------------------*/ + +/* The following types implement a very simple data structure for a boolean +** network. The intent is to be able to read a minimal subset of the blif +** format in a data structure from which it's easy to build DDs for the +** circuit. +*/ + +/* Type to store a line of the truth table of a node. The entire truth table +** implemented as a linked list of objects of this type. +*/ +typedef struct BnetTabline { + char *values; /* string of 1, 0, and - */ + struct BnetTabline *next; /* pointer to next table line */ +} BnetTabline; + +/* Node of the boolean network. There is one node in the network for each +** primary input and for each .names directive. This structure +** has a field to point to the DD of the node function. The function may +** be either in terms of primary inputs, or it may be in terms of the local +** inputs. The latter implies that each node has a variable index +** associated to it at some point in time. The field "var" stores that +** variable index, and "active" says if the association is currently valid. +** (It is indeed possible for an index to be associated to different nodes +** at different times.) +*/ +typedef struct BnetNode { + char *name; /* name of the output signal */ + int type; /* input, internal, constant, ... */ + int ninp; /* number of inputs to the node */ + int nfo; /* number of fanout nodes for this node */ + char **inputs; /* input names */ + BnetTabline *f; /* truth table for this node */ + int polarity; /* f is the onset (0) or the offset (1) */ + int active; /* node has variable associated to it (1) or not (0) */ + int var; /* DD variable index associated to this node */ + DdNode *dd; /* decision diagram for the function of this node */ + int exdc_flag; /* whether an exdc node or not */ + struct BnetNode *exdc; /* pointer to exdc of dd node */ + int count; /* auxiliary field for DD dropping */ + int level; /* maximum distance from the inputs */ + int visited; /* flag for search */ + struct BnetNode *next; /* pointer to implement the linked list of nodes */ +} BnetNode; + +/* Very simple boolean network data structure. */ +typedef struct BnetNetwork { + char *name; /* network name: from the .model directive */ + int npis; /* number of primary inputs */ + int ninputs; /* number of inputs */ + char **inputs; /* primary input names: from the .inputs directive */ + int npos; /* number of primary outputs */ + int noutputs; /* number of outputs */ + char **outputs; /* primary output names: from the .outputs directive */ + int nlatches; /* number of latches */ + char ***latches; /* next state names: from the .latch directives */ + BnetNode *nodes; /* linked list of the nodes */ + st_table *hash; /* symbol table to access nodes by name */ + char *slope; /* wire_load_slope */ +} BnetNetwork; + +/*---------------------------------------------------------------------------*/ +/* Variable declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Macro declarations */ +/*---------------------------------------------------------------------------*/ + +#ifndef TRUE +# define TRUE 1 +#endif +#ifndef FALSE +# define FALSE 0 +#endif + +/**AutomaticStart*************************************************************/ + +/*---------------------------------------------------------------------------*/ +/* Function prototypes */ +/*---------------------------------------------------------------------------*/ + +extern BnetNetwork * Bnet_ReadNetwork (FILE *fp, int pr); +extern void Bnet_PrintNetwork (BnetNetwork *net); +extern void Bnet_FreeNetwork (BnetNetwork *net); +extern int Bnet_BuildNodeBDD (DdManager *dd, BnetNode *nd, st_table *hash, int params, int nodrop); +extern int Bnet_DfsVariableOrder (DdManager *dd, BnetNetwork *net); +extern int Bnet_bddDump (DdManager *dd, BnetNetwork *network, char *dfile, int dumpFmt, int reencoded); +extern int Bnet_bddArrayDump (DdManager *dd, BnetNetwork *network, char *dfile, DdNode **outputs, char **onames, int noutputs, int dumpFmt); +extern int Bnet_ReadOrder (DdManager *dd, char *ordFile, BnetNetwork *net, int locGlob, int nodrop); +extern int Bnet_PrintOrder (BnetNetwork * net, DdManager *dd); + +/**AutomaticEnd***************************************************************/ + +#ifdef __cplusplus +} /* end of extern "C" */ +#endif + +#endif /* _BNET */ diff --git a/distr/nanotrav/chkMterm.c b/distr/nanotrav/chkMterm.c new file mode 100644 index 0000000..38582f9 --- /dev/null +++ b/distr/nanotrav/chkMterm.c @@ -0,0 +1,235 @@ +/**CFile*********************************************************************** + + FileName [chkMterm.c] + + PackageName [ntr] + + Synopsis [Functions to check that the minterm counts have not + changed.] + + Description [Functions to check that the minterm counts have not + changed during reordering.

          + Internal procedures included in this module: +

            +
          • check_minterms() +
          + Static procedures included in this module: +
            +
          • stFree() +
          ] + + 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 "ntr.h" + +/*---------------------------------------------------------------------------*/ +/* Constant declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Stucture declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Type declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Variable declarations */ +/*---------------------------------------------------------------------------*/ + +#ifndef lint +static char rcsid[] UTIL_UNUSED = "$Id: chkMterm.c,v 1.8 2009/02/20 02:19:02 fabio Exp fabio $"; +#endif + +/*---------------------------------------------------------------------------*/ +/* Macro declarations */ +/*---------------------------------------------------------------------------*/ + +/**AutomaticStart*************************************************************/ + +/*---------------------------------------------------------------------------*/ +/* Static function prototypes */ +/*---------------------------------------------------------------------------*/ + +static enum st_retval stFree (char *key, char *value, char *arg); + +/**AutomaticEnd***************************************************************/ + +/*---------------------------------------------------------------------------*/ +/* Definition of exported functions */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Definition of internal functions */ +/*---------------------------------------------------------------------------*/ + + +/**Function******************************************************************** + + Synopsis [Check that minterm counts have not changed.] + + Description [Counts the minterms in the global functions of the + primary outputs of the network passed as argument. + When it is calld with the second argument set to NULL, it allocates + a symbol table and stores, for each output, the minterm count. If + an output does not have a BDD, it stores a NULL pointer for it. + If it is called with a non-null second argument, it assumes that + the symbol table contains the minterm counts measured previously + and it compares the new counts to the old ones. Finally, it frees + the symbol table. + check_minterms is designed so that it can be called twice: once before + reordering, and once after reordering. + Returns a pointer to the symbol table on the first invocation and NULL + on the second invocation.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +st_table * +checkMinterms( + BnetNetwork * net, + DdManager * dd, + st_table * previous) +{ + BnetNode *po; + int numPi; + char *name; + double *count, newcount, *oldcount; + int flag,err,i; + + numPi = net->ninputs; + + if (previous == NULL) { + previous = st_init_table(strcmp,st_strhash); + if (previous == NULL) { + (void) printf("checkMinterms out-of-memory\n"); + return(NULL); + } + for (i = 0; i < net->noutputs; i++) { + if (!st_lookup(net->hash,net->outputs[i],&po)) { + exit(2); + } + name = net->outputs[i]; + if (po->dd != NULL) { + count = ALLOC(double,1); + *count = Cudd_CountMinterm(dd,po->dd,numPi); + err = st_insert(previous, name, (char *) count); + } else { + err = st_insert(previous, name, NULL); + } + if (err) { + (void) printf("Duplicate input name (%s)\n",name); + return(NULL); + } + } + return(previous); + } else { + flag = 0; + if (st_count(previous) != net->noutputs) { + (void) printf("Number of outputs has changed from %d to %d\n", + st_count(previous), net->noutputs); + flag = 1; + } + for (i = 0; i < net->noutputs; i++) { + if (!st_lookup(net->hash,net->outputs[i],&po)) { + exit(2); + } + name = net->outputs[i]; + if (st_lookup(previous,name,&oldcount)) { + if (po->dd != NULL) { + newcount = Cudd_CountMinterm(dd,po->dd,numPi); + if (newcount != *oldcount) { + (void) printf("Number of minterms of %s has changed from %g to %g\n",name,*oldcount,newcount); + flag = 1; + } + } else { + if (oldcount != NULL) { + (void) printf("Output %s lost its BDD!\n",name); + flag = 1; + } + } + } else { + (void) printf("Output %s is new!\n",name); + flag = 1; + } + } + /*st_foreach(previous,(enum st_retval)stFree,NULL);*/ + st_foreach(previous,(ST_PFSR)stFree,NULL); + st_free_table(previous); + if (flag) { + return((st_table *) 1); + } else { + return(NULL); + } + } + +} /* end of checkMinterms */ + + +/*---------------------------------------------------------------------------*/ +/* Definition of static functions */ +/*---------------------------------------------------------------------------*/ + + +/**Function******************************************************************** + + Synopsis [Frees the data of the symbol table.] + + Description [] + + SideEffects [None] + + SeeAlso [] + +*****************************************************************************/ +static enum st_retval +stFree( + char *key, + char *value, + char *arg) +{ + if (value != NULL) { + FREE(value); + } + return(ST_CONTINUE); + +} /* end of stFree */ diff --git a/distr/nanotrav/doc/bnetAllAbs.html b/distr/nanotrav/doc/bnetAllAbs.html new file mode 100644 index 0000000..22ddf66 --- /dev/null +++ b/distr/nanotrav/doc/bnetAllAbs.html @@ -0,0 +1,45 @@ + +bnet package abstract (Internal) + + +

          bnet package abstract (Internal)

          +

          +
          + + + +
          +
          Bnet_BuildNodeBDD() +
          Builds the BDD for the function of a node. + +
          Bnet_DfsVariableOrder() +
          Orders the BDD variables by DFS. + +
          Bnet_FreeNetwork() +
          Frees a boolean network created by Bnet_ReadNetwork. + +
          Bnet_PrintNetwork() +
          Prints a boolean network created by readNetwork. + +
          Bnet_PrintOrder() +
          Prints the order of the DD variables of a network. + +
          Bnet_ReadNetwork() +
          Reads boolean network from blif file. + +
          Bnet_ReadOrder() +
          Reads the variable order from a file. + +
          Bnet_bddArrayDump() +
          Writes an array of BDDs to a file in dot, blif, DDcal, factored-form, or daVinci format. + +
          Bnet_bddDump() +
          Writes the network BDDs to a file in dot, blif, or daVinci format. + +
          + +
          + +Generated automatically by extdoc on 1010215 + + diff --git a/distr/nanotrav/doc/bnetAllDet.html b/distr/nanotrav/doc/bnetAllDet.html new file mode 100644 index 0000000..352011e --- /dev/null +++ b/distr/nanotrav/doc/bnetAllDet.html @@ -0,0 +1,173 @@ + +The bnet package (Internal) + + +

          The bnet package (Internal)

          +

          +

          +
          + + +
          + + + + + +
          + + +
          + +
          +int 
          +Bnet_BuildNodeBDD(
          +  DdManager * dd, DD manager
          +  BnetNode * nd, node of the boolean network
          +  st_table * hash, symbol table of the boolean network
          +  int  params, type of DD to be built
          +  int  nodrop retain the intermediate node DDs until the end
          +)
          +
          +
          Builds the BDD for the function of a node and stores a pointer to it in the dd field of the node itself. The reference count of the BDD is incremented. If params is BNET_LOCAL_DD, then the BDD is built in terms of the local inputs to the node; otherwise, if params is BNET_GLOBAL_DD, the BDD is built in terms of the network primary inputs. To build the global BDD of a node, the BDDs for its local inputs must exist. If that is not the case, Bnet_BuildNodeBDD recursively builds them. Likewise, to create the local BDD for a node, the local inputs must have variables assigned to them. If that is not the case, Bnet_BuildNodeBDD recursively assigns variables to nodes. Bnet_BuildNodeBDD returns 1 in case of success; 0 otherwise. +

          + +

          Side Effects Sets the dd field of the node. +

          + +

          +int 
          +Bnet_DfsVariableOrder(
          +  DdManager * dd, 
          +  BnetNetwork * net 
          +)
          +
          +
          Orders the BDD variables by DFS. Returns 1 in case of success; 0 otherwise. +

          + +

          Side Effects Uses the visited flags of the nodes. +

          + +

          +void 
          +Bnet_FreeNetwork(
          +  BnetNetwork * net 
          +)
          +
          +
          Frees a boolean network created by Bnet_ReadNetwork. +

          + +

          Side Effects None +

          + +

          See Also Bnet_ReadNetwork + + +
          +void 
          +Bnet_PrintNetwork(
          +  BnetNetwork * net boolean network
          +)
          +
          +
          Prints to the standard output a boolean network created by Bnet_ReadNetwork. Uses the blif format; this way, one can verify the equivalence of the input and the output with, say, sis. +

          + +

          Side Effects None +

          + +

          See Also Bnet_ReadNetwork + + +
          +int 
          +Bnet_PrintOrder(
          +  BnetNetwork * net, 
          +  DdManager * dd 
          +)
          +
          +
          Prints the order of the DD variables of a network. Only primary inputs and present states are printed. Returns 1 if successful; 0 otherwise. +

          + +

          Side Effects None +

          + +

          +BnetNetwork * 
          +Bnet_ReadNetwork(
          +  FILE * fp, pointer to the blif file
          +  int  pr verbosity level
          +)
          +
          +
          Reads a boolean network from a blif file. A very restricted subset of blif is supported. Specifically:
          • The only directives recognized are:
            • .model
            • .inputs
            • .outputs
            • .latch
            • .names
            • .exdc
            • .wire_load_slope
            • .end
          • Latches must have an initial values and no other parameters specified.
          • Lines must not exceed MAXLENGTH-1 characters, and individual names must not exceed 1023 characters.
          Caveat emptor: There may be other limitations as well. One should check the syntax of the blif file with some other tool before relying on this parser. Bnet_ReadNetwork returns a pointer to the network if successful; NULL otherwise. +

          + +

          Side Effects None +

          + +

          See Also Bnet_PrintNetwork +Bnet_FreeNetwork + + +
          +int 
          +Bnet_ReadOrder(
          +  DdManager * dd, 
          +  char * ordFile, 
          +  BnetNetwork * net, 
          +  int  locGlob, 
          +  int  nodrop 
          +)
          +
          +
          Reads the variable order from a file. Returns 1 if successful; 0 otherwise. +

          + +

          Side Effects The BDDs for the primary inputs and present state variables are built. +

          + +

          +int 
          +Bnet_bddArrayDump(
          +  DdManager * dd, DD manager
          +  BnetNetwork * network, network whose BDDs should be dumped
          +  char * dfile, file name
          +  DdNode ** outputs, BDDs to be dumped
          +  char ** onames, names of the BDDs to be dumped
          +  int  noutputs, number of BDDs to be dumped
          +  int  dumpFmt 0 -> dot
          +)
          +
          +
          Writes an array of BDDs to a file in dot, blif, DDcal, factored-form, or daVinci format. The BDDs and their names are passed as arguments. The inputs and their names are taken from the network. If "-" is passed as file name, the BDDs are dumped to the standard output. Returns 1 in case of success; 0 otherwise. +

          + +

          Side Effects None +

          + +

          +int 
          +Bnet_bddDump(
          +  DdManager * dd, DD manager
          +  BnetNetwork * network, network whose BDDs should be dumped
          +  char * dfile, file name
          +  int  dumpFmt, 0 -> dot
          +  int  reencoded whether variables have been reencoded
          +)
          +
          +
          Writes the network BDDs to a file in dot, blif, or daVinci format. If "-" is passed as file name, the BDDs are dumped to the standard output. Returns 1 in case of success; 0 otherwise. +

          + +

          Side Effects None +

          + + +

          + +
          + +Generated automatically by extdoc on 1010215 + + diff --git a/distr/nanotrav/doc/bnetExtAbs.html b/distr/nanotrav/doc/bnetExtAbs.html new file mode 100644 index 0000000..d8f645c --- /dev/null +++ b/distr/nanotrav/doc/bnetExtAbs.html @@ -0,0 +1,45 @@ + +bnet package abstract + + +

          bnet package abstract

          +

          Simple-minded package to read a blif file.

          +
          + + + +
          +
          Bnet_BuildNodeBDD() +
          Builds the BDD for the function of a node. + +
          Bnet_DfsVariableOrder() +
          Orders the BDD variables by DFS. + +
          Bnet_FreeNetwork() +
          Frees a boolean network created by Bnet_ReadNetwork. + +
          Bnet_PrintNetwork() +
          Prints a boolean network created by readNetwork. + +
          Bnet_PrintOrder() +
          Prints the order of the DD variables of a network. + +
          Bnet_ReadNetwork() +
          Reads boolean network from blif file. + +
          Bnet_ReadOrder() +
          Reads the variable order from a file. + +
          Bnet_bddArrayDump() +
          Writes an array of BDDs to a file in dot, blif, DDcal, factored-form, or daVinci format. + +
          Bnet_bddDump() +
          Writes the network BDDs to a file in dot, blif, or daVinci format. + +
          + +
          + +Generated automatically by extdoc on 1010215 + + diff --git a/distr/nanotrav/doc/bnetExtDet.html b/distr/nanotrav/doc/bnetExtDet.html new file mode 100644 index 0000000..aee62c0 --- /dev/null +++ b/distr/nanotrav/doc/bnetExtDet.html @@ -0,0 +1,173 @@ + +The bnet package + + +

          The bnet package

          +

          Simple-minded package to read a blif file.

          +

          +
          + + +
          + + + + + +
          + + +
          + +
          +int 
          +Bnet_BuildNodeBDD(
          +  DdManager * dd, DD manager
          +  BnetNode * nd, node of the boolean network
          +  st_table * hash, symbol table of the boolean network
          +  int  params, type of DD to be built
          +  int  nodrop retain the intermediate node DDs until the end
          +)
          +
          +
          Builds the BDD for the function of a node and stores a pointer to it in the dd field of the node itself. The reference count of the BDD is incremented. If params is BNET_LOCAL_DD, then the BDD is built in terms of the local inputs to the node; otherwise, if params is BNET_GLOBAL_DD, the BDD is built in terms of the network primary inputs. To build the global BDD of a node, the BDDs for its local inputs must exist. If that is not the case, Bnet_BuildNodeBDD recursively builds them. Likewise, to create the local BDD for a node, the local inputs must have variables assigned to them. If that is not the case, Bnet_BuildNodeBDD recursively assigns variables to nodes. Bnet_BuildNodeBDD returns 1 in case of success; 0 otherwise. +

          + +

          Side Effects Sets the dd field of the node. +

          + +

          +int 
          +Bnet_DfsVariableOrder(
          +  DdManager * dd, 
          +  BnetNetwork * net 
          +)
          +
          +
          Orders the BDD variables by DFS. Returns 1 in case of success; 0 otherwise. +

          + +

          Side Effects Uses the visited flags of the nodes. +

          + +

          +void 
          +Bnet_FreeNetwork(
          +  BnetNetwork * net 
          +)
          +
          +
          Frees a boolean network created by Bnet_ReadNetwork. +

          + +

          Side Effects None +

          + +

          See Also Bnet_ReadNetwork + + +
          +void 
          +Bnet_PrintNetwork(
          +  BnetNetwork * net boolean network
          +)
          +
          +
          Prints to the standard output a boolean network created by Bnet_ReadNetwork. Uses the blif format; this way, one can verify the equivalence of the input and the output with, say, sis. +

          + +

          Side Effects None +

          + +

          See Also Bnet_ReadNetwork + + +
          +int 
          +Bnet_PrintOrder(
          +  BnetNetwork * net, 
          +  DdManager * dd 
          +)
          +
          +
          Prints the order of the DD variables of a network. Only primary inputs and present states are printed. Returns 1 if successful; 0 otherwise. +

          + +

          Side Effects None +

          + +

          +BnetNetwork * 
          +Bnet_ReadNetwork(
          +  FILE * fp, pointer to the blif file
          +  int  pr verbosity level
          +)
          +
          +
          Reads a boolean network from a blif file. A very restricted subset of blif is supported. Specifically:
          • The only directives recognized are:
            • .model
            • .inputs
            • .outputs
            • .latch
            • .names
            • .exdc
            • .wire_load_slope
            • .end
          • Latches must have an initial values and no other parameters specified.
          • Lines must not exceed MAXLENGTH-1 characters, and individual names must not exceed 1023 characters.
          Caveat emptor: There may be other limitations as well. One should check the syntax of the blif file with some other tool before relying on this parser. Bnet_ReadNetwork returns a pointer to the network if successful; NULL otherwise. +

          + +

          Side Effects None +

          + +

          See Also Bnet_PrintNetwork +Bnet_FreeNetwork + + +
          +int 
          +Bnet_ReadOrder(
          +  DdManager * dd, 
          +  char * ordFile, 
          +  BnetNetwork * net, 
          +  int  locGlob, 
          +  int  nodrop 
          +)
          +
          +
          Reads the variable order from a file. Returns 1 if successful; 0 otherwise. +

          + +

          Side Effects The BDDs for the primary inputs and present state variables are built. +

          + +

          +int 
          +Bnet_bddArrayDump(
          +  DdManager * dd, DD manager
          +  BnetNetwork * network, network whose BDDs should be dumped
          +  char * dfile, file name
          +  DdNode ** outputs, BDDs to be dumped
          +  char ** onames, names of the BDDs to be dumped
          +  int  noutputs, number of BDDs to be dumped
          +  int  dumpFmt 0 -> dot
          +)
          +
          +
          Writes an array of BDDs to a file in dot, blif, DDcal, factored-form, or daVinci format. The BDDs and their names are passed as arguments. The inputs and their names are taken from the network. If "-" is passed as file name, the BDDs are dumped to the standard output. Returns 1 in case of success; 0 otherwise. +

          + +

          Side Effects None +

          + +

          +int 
          +Bnet_bddDump(
          +  DdManager * dd, DD manager
          +  BnetNetwork * network, network whose BDDs should be dumped
          +  char * dfile, file name
          +  int  dumpFmt, 0 -> dot
          +  int  reencoded whether variables have been reencoded
          +)
          +
          +
          Writes the network BDDs to a file in dot, blif, or daVinci format. If "-" is passed as file name, the BDDs are dumped to the standard output. Returns 1 in case of success; 0 otherwise. +

          + +

          Side Effects None +

          + + +

          + +
          + +Generated automatically by extdoc on 1010215 + + diff --git a/distr/nanotrav/doc/ntrAllAbs.html b/distr/nanotrav/doc/ntrAllAbs.html new file mode 100644 index 0000000..360a4e7 --- /dev/null +++ b/distr/nanotrav/doc/ntrAllAbs.html @@ -0,0 +1,114 @@ + +ntr package abstract (Internal) + + +

          ntr package abstract (Internal)

          +

          +
          + + + +
          +
          Ntr_ClosureTrav() +
          Transitive closure traversal procedure. + +
          Ntr_Envelope() +
          Poor man's outer envelope computation. + +
          Ntr_FreeHeap() +
          Frees a priority queue. + +
          Ntr_HeapClone() +
          Clones a priority queue. + +
          Ntr_HeapCount() +
          Returns the number of items in a priority queue. + +
          Ntr_HeapExtractMin() +
          Extracts the element with the minimum key from a priority queue. + +
          Ntr_HeapInsert() +
          Inserts an item in a priority queue. + +
          Ntr_InitHeap() +
          Initializes a priority queue. + +
          Ntr_SCC() +
          Computes the SCCs of the STG. + +
          Ntr_ShortestPaths() +
          Computes shortest paths in a state graph. + +
          Ntr_TestClipping() +
          Tests BDD clipping functions. + +
          Ntr_TestClosestCube() +
          Tests the Cudd_bddClosestCube function. + +
          Ntr_TestCofactorEstimate() +
          Tests BDD cofactor estimate functions. + +
          Ntr_TestDecomp() +
          Tests BDD decomposition functions. + +
          Ntr_TestDensity() +
          Tests BDD density-related functions. + +
          Ntr_TestEquivAndContain() +
          Tests BDD equivalence and containment with don't cares. + +
          Ntr_TestHeap() +
          Tests the heap property of a priority queue. + +
          Ntr_TestMinimization() +
          Tests BDD minimization functions. + +
          Ntr_TransitiveClosure() +
          Builds the transitive closure of a transition relation. + +
          Ntr_Trav() +
          Poor man's traversal procedure. + +
          Ntr_VerifyEquivalence() +
          Verify equivalence of combinational networks. + +
          Ntr_buildDDs() +
          Builds DDs for a network outputs and next state functions. + +
          Ntr_buildTR() +
          Builds the transition relation for a network. + +
          Ntr_cloneTR() +
          Makes a copy of a transition relation. + +
          Ntr_freeTR() +
          Frees the transition relation for a network. + +
          Ntr_getStateCube() +
          Reads a state cube from a file or creates a random one. + +
          Ntr_initState() +
          Builds the BDD of the initial state(s). + +
          Ntr_maxflow() +
          Maximum 0-1 flow between source and sink states. + +
          Ntr_maximum01Flow() +
          + +
          Ntr_testISOP() +
          Builds ZDD covers. + +
          Ntr_testZDD() +
          Tests ZDDs. + +
          STRING_EQUAL() +
          Returns 1 if the two arguments are identical strings. + +
          + +
          + +Generated automatically by extdoc on 1010215 + + diff --git a/distr/nanotrav/doc/ntrAllDet.html b/distr/nanotrav/doc/ntrAllDet.html new file mode 100644 index 0000000..5daa930 --- /dev/null +++ b/distr/nanotrav/doc/ntrAllDet.html @@ -0,0 +1,513 @@ + +The ntr package (Internal) + + +

          The ntr package (Internal)

          +

          +

          +
          + + +
          + + + + + +
          + + +
          + +
          +int 
          +Ntr_ClosureTrav(
          +  DdManager * dd, DD manager
          +  BnetNetwork * net, network
          +  NtrOptions * option options
          +)
          +
          +
          Traversal procedure. based on the transitive closure of the transition relation. Returns 1 in case of success; 0 otherwise. +

          + +

          Side Effects None +

          + +

          See Also Ntr_Trav + + +
          +int 
          +Ntr_Envelope(
          +  DdManager * dd, DD manager
          +  NtrPartTR * TR, transition relation
          +  FILE * dfp, pointer to file for DD dump
          +  NtrOptions * option program options
          +)
          +
          +
          Poor man's outer envelope computation based on the monolithic transition relation. Returns 1 in case of success; 0 otherwise. +

          + +

          Side Effects None +

          + +

          +void 
          +Ntr_FreeHeap(
          +  NtrHeap * heap 
          +)
          +
          +
          Frees a priority queue. +

          + +

          Side Effects None +

          + +

          See Also Ntr_InitHeap + + +
          +NtrHeap * 
          +Ntr_HeapClone(
          +  NtrHeap * source 
          +)
          +
          +
          Clones a priority queue. +

          + +

          Side Effects None +

          + +

          See Also Ntr_InitHeap + + +
          +int 
          +Ntr_HeapCount(
          +  NtrHeap * heap 
          +)
          +
          +
          Returns the number of items in a priority queue. +

          + +

          Side Effects None +

          + +

          +int 
          +Ntr_HeapExtractMin(
          +  NtrHeap * heap, 
          +  void ** item, 
          +  int * key 
          +)
          +
          +
          Extracts the element with the minimum key from a priority queue. Returns 1 if successful; 0 otherwise. +

          + +

          Side Effects The minimum key and the associated item are returned as side effects. +

          + +

          See Also Ntr_HeapInsert + + +
          +int 
          +Ntr_HeapInsert(
          +  NtrHeap * heap, 
          +  void * item, 
          +  int  key 
          +)
          +
          +
          Inserts an item in a priority queue. Returns 1 if successful; 0 otherwise. +

          + +

          Side Effects None +

          + +

          See Also Ntr_HeapExtractMin + + +
          +NtrHeap * 
          +Ntr_InitHeap(
          +  int  size 
          +)
          +
          +
          Initializes a priority queue. Returns a pointer to the heap if successful; NULL otherwise. +

          + +

          Side Effects None +

          + +

          See Also Ntr_FreeHeap + + +
          +int 
          +Ntr_SCC(
          +  DdManager * dd, DD manager
          +  BnetNetwork * net, network
          +  NtrOptions * option options
          +)
          +
          +
          Computes the strongly connected components of the state transition graph. Only the first 10 SCCs are computed. Returns 1 in case of success; 0 otherwise. +

          + +

          Side Effects None +

          + +

          See Also Ntr_Trav + + +
          +int 
          +Ntr_ShortestPaths(
          +  DdManager * dd, 
          +  BnetNetwork * net, 
          +  NtrOptions * option 
          +)
          +
          +
          Computes shortest paths in the state transition graph of a network. Three methods are availabe:
          • Bellman-Ford algorithm for single-source shortest paths; the algorithm computes the distance (number of transitions) from the initial states to all states.
          • Floyd-Warshall algorithm for all-pair shortest paths.
          • Repeated squaring algorithm for all-pair shortest paths.
          The function returns 1 in case of success; 0 otherwise. +

          + +

          Side Effects ADD variables are created in the manager. +

          + +

          +int 
          +Ntr_TestClipping(
          +  DdManager * dd, 
          +  BnetNetwork * net1, 
          +  BnetNetwork * net2, 
          +  NtrOptions * option 
          +)
          +
          +
          Tests BDD clipping functions. Returns 1 if successful; 0 otherwise. +

          + +

          Side Effects None +

          + +

          +int 
          +Ntr_TestClosestCube(
          +  DdManager * dd, 
          +  BnetNetwork * net, 
          +  NtrOptions * option 
          +)
          +
          +
          Tests the Cudd_bddClosestCube function. Returns 1 if successful; 0 otherwise. +

          + +

          Side Effects None +

          + +

          +int 
          +Ntr_TestCofactorEstimate(
          +  DdManager * dd, 
          +  BnetNetwork * net, 
          +  NtrOptions * option 
          +)
          +
          +
          Tests BDD cofactor estimate functions. Returns 1 if successful; 0 otherwise. +

          + +

          Side Effects None +

          + +

          +int 
          +Ntr_TestDecomp(
          +  DdManager * dd, 
          +  BnetNetwork * net1, 
          +  NtrOptions * option 
          +)
          +
          +
          Tests BDD decomposition functions. Returns 1 if successful; 0 otherwise. +

          + +

          Side Effects None +

          + +

          +int 
          +Ntr_TestDensity(
          +  DdManager * dd, 
          +  BnetNetwork * net1, 
          +  NtrOptions * option 
          +)
          +
          +
          Tests BDD density-related functions. Returns 1 if successful; 0 otherwise. +

          + +

          Side Effects None +

          + +

          +int 
          +Ntr_TestEquivAndContain(
          +  DdManager * dd, 
          +  BnetNetwork * net1, 
          +  BnetNetwork * net2, 
          +  NtrOptions * option 
          +)
          +
          +
          Tests functions for BDD equivalence and containment with don't cares, including Cudd_EquivDC and Cudd_bddLeqUnless. This function uses as care set the first output of net2 and checkes equivalence and containment for of all the output pairs of net1. Returns 1 if successful; 0 otherwise. +

          + +

          Side Effects None +

          + +

          +int 
          +Ntr_TestHeap(
          +  NtrHeap * heap, 
          +  int  i 
          +)
          +
          +
          Tests the heap property of a priority queue. Returns 1 if Successful; 0 otherwise. +

          + +

          Side Effects None +

          + +

          +int 
          +Ntr_TestMinimization(
          +  DdManager * dd, 
          +  BnetNetwork * net1, 
          +  BnetNetwork * net2, 
          +  NtrOptions * option 
          +)
          +
          +
          Tests BDD minimization functions, including leaf-identifying compaction, squeezing, and restrict. This function uses as constraint the first output of net2 and computes positive and negative cofactors of all the outputs of net1. For each cofactor, it checks whether compaction was safe (cofactor not larger than original function) and that the expansion based on each minimization function (used as a generalized cofactor) equals the original function. Returns 1 if successful; 0 otherwise. +

          + +

          Side Effects None +

          + +

          +DdNode * 
          +Ntr_TransitiveClosure(
          +  DdManager * dd, 
          +  NtrPartTR * TR, 
          +  NtrOptions * option 
          +)
          +
          +
          Builds the transitive closure of a transition relation. Returns a BDD if successful; NULL otherwise. Uses a simple squaring algorithm. +

          + +

          Side Effects None +

          + +

          +int 
          +Ntr_Trav(
          +  DdManager * dd, DD manager
          +  BnetNetwork * net, network
          +  NtrOptions * option options
          +)
          +
          +
          Poor man's traversal procedure. based on the monolithic transition relation. Returns 1 in case of success; 0 otherwise. +

          + +

          Side Effects None +

          + +

          See Also Ntr_ClosureTrav + + +
          +int 
          +Ntr_VerifyEquivalence(
          +  DdManager * dd, 
          +  BnetNetwork * net1, 
          +  BnetNetwork * net2, 
          +  NtrOptions * option 
          +)
          +
          +
          Verify equivalence of combinational networks. Returns 1 if successful and if the networks are equivalent; -1 if successful, but the networks are not equivalent; 0 otherwise. The two networks are supposed to have the same names for inputs and outputs. The only exception is that the second network may miss output buffers that are present in the first network. This function tries to match both the output and the input of the buffer. +

          + +

          Side Effects None +

          + +

          +int 
          +Ntr_buildDDs(
          +  BnetNetwork * net, network for which DDs are to be built
          +  DdManager * dd, DD manager
          +  NtrOptions * option, option structure
          +  BnetNetwork * net2 companion network with which inputs may be shared
          +)
          +
          +
          Builds DDs for a network outputs and next state functions. The method is really brain-dead, but it is very simple. Returns 1 in case of success; 0 otherwise. Some inputs to the network may be shared with another network whose DDs have already been built. In this case we want to share the DDs as well. +

          + +

          Side Effects the dd fields of the network nodes are modified. Uses the count fields of the nodes. +

          + +

          +NtrPartTR * 
          +Ntr_buildTR(
          +  DdManager * dd, manager
          +  BnetNetwork * net, network
          +  NtrOptions * option, options
          +  int  image image type: monolithic ...
          +)
          +
          +
          Builds the transition relation for a network. Returns a pointer to the transition relation structure if successful; NULL otherwise. +

          + +

          Side Effects None +

          + +

          +NtrPartTR * 
          +Ntr_cloneTR(
          +  NtrPartTR * TR 
          +)
          +
          +
          Makes a copy of a transition relation. Returns a pointer to the copy if successful; NULL otherwise. +

          + +

          Side Effects None +

          + +

          See Also Ntr_buildTR +Ntr_freeTR + + +
          +void 
          +Ntr_freeTR(
          +  DdManager * dd, 
          +  NtrPartTR * TR 
          +)
          +
          +
          Frees the transition relation for a network. +

          + +

          Side Effects None +

          + +

          +DdNode * 
          +Ntr_getStateCube(
          +  DdManager * dd, 
          +  BnetNetwork * net, 
          +  char * filename, 
          +  int  pr 
          +)
          +
          +
          Reads a state cube from a file or create a random one. Returns a pointer to the BDD of the sink nodes if successful; NULL otherwise. +

          + +

          Side Effects None +

          + +

          +DdNode * 
          +Ntr_initState(
          +  DdManager * dd, 
          +  BnetNetwork * net, 
          +  NtrOptions * option 
          +)
          +
          +
          Builds the BDD of the initial state(s). Returns a BDD if successful; NULL otherwise. +

          + +

          Side Effects None +

          + +

          +int 
          +Ntr_maxflow(
          +  DdManager * dd, 
          +  BnetNetwork * net, 
          +  NtrOptions * option 
          +)
          +
          +
          Maximum 0-1 flow between source and sink states. Returns 1 in case of success; 0 otherwise. +

          + +

          Side Effects Creates two new sets of variables. +

          + +

          +double 
          +Ntr_maximum01Flow(
          +  DdManager * bdd, manager
          +  DdNode * sx, source node
          +  DdNode * ty, sink node
          +  DdNode * E, edge relation
          +  DdNode ** F, flow relation
          +  DdNode ** cut, cutset relation
          +  DdNode ** x, array of row variables
          +  DdNode ** y, array of column variables
          +  DdNode ** z, arrays of auxiliary variables
          +  int  n, number of variables in each array
          +  int  pr verbosity level
          +)
          +
          +
          This function implements Dinits's algorithm for (0-1) max flow, using BDDs and a symbolic technique to trace multiple edge-disjoint augmenting paths to complete a phase. The outer forever loop is over phases, and the inner forever loop is to propagate a (not yet) maximal flow of edge-disjoint augmenting paths from one layer to the previous. The subprocedure call implements a least fixed point iteration to compute a (not yet) maximal flow update between layers. At the end of each phase (except the last one) the flow is actually pushed from the source to the sink. Data items:
          • sx(ty) BDD representations of s(t).
          • x(y) The variables encoding the from(to)-node u(v) of an edge (u,v) in the given digraph.
          • z Another set of variables.
          • E(x,y) The edge relation.
          • F(x,y) BDD representation of the current flow, initialized to 0 for each arc, and updated by +1, -1, or 0 at the end of each phase.
          • Ms Mt The maximum flow, that is, the cardinality of a minimum cut, measured at the source and at the sink, respectively. The two values should be identical.
          • reached The set of nodes already visited in the BFS of the digraph.
          • fos fanout of the source node s.
          • fit fanin of the sink node t.
          +

          + +

          Side Effects The flow realtion F and the cutset relation cut are returned as side effects. +

          + +

          +int 
          +Ntr_testISOP(
          +  DdManager * dd, 
          +  BnetNetwork * net, 
          +  NtrOptions * option 
          +)
          +
          +
          Builds ZDD covers. +

          + +

          Side Effects Creates ZDD variables in the manager. +

          + +

          +int 
          +Ntr_testZDD(
          +  DdManager * dd, 
          +  BnetNetwork * net, 
          +  NtrOptions * option 
          +)
          +
          +
          Tests ZDDs. Returns 1 if successful; 0 otherwise. +

          + +

          Side Effects Creates ZDD variables in the manager. +

          + +

          + 
          +STRING_EQUAL(
          +   s1, 
          +   s2 
          +)
          +
          +
          Returns 1 if the two arguments are identical strings. +

          + +

          Side Effects none +

          + + +

          + +
          + +Generated automatically by extdoc on 1010215 + + diff --git a/distr/nanotrav/doc/ntrExtAbs.html b/distr/nanotrav/doc/ntrExtAbs.html new file mode 100644 index 0000000..485d346 --- /dev/null +++ b/distr/nanotrav/doc/ntrExtAbs.html @@ -0,0 +1,111 @@ + +ntr package abstract + + +

          ntr package abstract

          +

          Simple-minded package to do traversal.

          +
          + + + +
          +
          Ntr_ClosureTrav() +
          Transitive closure traversal procedure. + +
          Ntr_Envelope() +
          Poor man's outer envelope computation. + +
          Ntr_FreeHeap() +
          Frees a priority queue. + +
          Ntr_HeapClone() +
          Clones a priority queue. + +
          Ntr_HeapCount() +
          Returns the number of items in a priority queue. + +
          Ntr_HeapExtractMin() +
          Extracts the element with the minimum key from a priority queue. + +
          Ntr_HeapInsert() +
          Inserts an item in a priority queue. + +
          Ntr_InitHeap() +
          Initializes a priority queue. + +
          Ntr_SCC() +
          Computes the SCCs of the STG. + +
          Ntr_ShortestPaths() +
          Computes shortest paths in a state graph. + +
          Ntr_TestClipping() +
          Tests BDD clipping functions. + +
          Ntr_TestClosestCube() +
          Tests the Cudd_bddClosestCube function. + +
          Ntr_TestCofactorEstimate() +
          Tests BDD cofactor estimate functions. + +
          Ntr_TestDecomp() +
          Tests BDD decomposition functions. + +
          Ntr_TestDensity() +
          Tests BDD density-related functions. + +
          Ntr_TestEquivAndContain() +
          Tests BDD equivalence and containment with don't cares. + +
          Ntr_TestHeap() +
          Tests the heap property of a priority queue. + +
          Ntr_TestMinimization() +
          Tests BDD minimization functions. + +
          Ntr_TransitiveClosure() +
          Builds the transitive closure of a transition relation. + +
          Ntr_Trav() +
          Poor man's traversal procedure. + +
          Ntr_VerifyEquivalence() +
          Verify equivalence of combinational networks. + +
          Ntr_buildDDs() +
          Builds DDs for a network outputs and next state functions. + +
          Ntr_buildTR() +
          Builds the transition relation for a network. + +
          Ntr_cloneTR() +
          Makes a copy of a transition relation. + +
          Ntr_freeTR() +
          Frees the transition relation for a network. + +
          Ntr_getStateCube() +
          Reads a state cube from a file or creates a random one. + +
          Ntr_initState() +
          Builds the BDD of the initial state(s). + +
          Ntr_maxflow() +
          Maximum 0-1 flow between source and sink states. + +
          Ntr_maximum01Flow() +
          + +
          Ntr_testISOP() +
          Builds ZDD covers. + +
          Ntr_testZDD() +
          Tests ZDDs. + +
          + +
          + +Generated automatically by extdoc on 1010215 + + diff --git a/distr/nanotrav/doc/ntrExtDet.html b/distr/nanotrav/doc/ntrExtDet.html new file mode 100644 index 0000000..ae06139 --- /dev/null +++ b/distr/nanotrav/doc/ntrExtDet.html @@ -0,0 +1,500 @@ + +The ntr package + + +

          The ntr package

          +

          Simple-minded package to do traversal.

          +

          +
          + + +
          + + + + + +
          + + +
          + +
          +int 
          +Ntr_ClosureTrav(
          +  DdManager * dd, DD manager
          +  BnetNetwork * net, network
          +  NtrOptions * option options
          +)
          +
          +
          Traversal procedure. based on the transitive closure of the transition relation. Returns 1 in case of success; 0 otherwise. +

          + +

          Side Effects None +

          + +

          See Also Ntr_Trav + + +
          +int 
          +Ntr_Envelope(
          +  DdManager * dd, DD manager
          +  NtrPartTR * TR, transition relation
          +  FILE * dfp, pointer to file for DD dump
          +  NtrOptions * option program options
          +)
          +
          +
          Poor man's outer envelope computation based on the monolithic transition relation. Returns 1 in case of success; 0 otherwise. +

          + +

          Side Effects None +

          + +

          +void 
          +Ntr_FreeHeap(
          +  NtrHeap * heap 
          +)
          +
          +
          Frees a priority queue. +

          + +

          Side Effects None +

          + +

          See Also Ntr_InitHeap + + +
          +NtrHeap * 
          +Ntr_HeapClone(
          +  NtrHeap * source 
          +)
          +
          +
          Clones a priority queue. +

          + +

          Side Effects None +

          + +

          See Also Ntr_InitHeap + + +
          +int 
          +Ntr_HeapCount(
          +  NtrHeap * heap 
          +)
          +
          +
          Returns the number of items in a priority queue. +

          + +

          Side Effects None +

          + +

          +int 
          +Ntr_HeapExtractMin(
          +  NtrHeap * heap, 
          +  void ** item, 
          +  int * key 
          +)
          +
          +
          Extracts the element with the minimum key from a priority queue. Returns 1 if successful; 0 otherwise. +

          + +

          Side Effects The minimum key and the associated item are returned as side effects. +

          + +

          See Also Ntr_HeapInsert + + +
          +int 
          +Ntr_HeapInsert(
          +  NtrHeap * heap, 
          +  void * item, 
          +  int  key 
          +)
          +
          +
          Inserts an item in a priority queue. Returns 1 if successful; 0 otherwise. +

          + +

          Side Effects None +

          + +

          See Also Ntr_HeapExtractMin + + +
          +NtrHeap * 
          +Ntr_InitHeap(
          +  int  size 
          +)
          +
          +
          Initializes a priority queue. Returns a pointer to the heap if successful; NULL otherwise. +

          + +

          Side Effects None +

          + +

          See Also Ntr_FreeHeap + + +
          +int 
          +Ntr_SCC(
          +  DdManager * dd, DD manager
          +  BnetNetwork * net, network
          +  NtrOptions * option options
          +)
          +
          +
          Computes the strongly connected components of the state transition graph. Only the first 10 SCCs are computed. Returns 1 in case of success; 0 otherwise. +

          + +

          Side Effects None +

          + +

          See Also Ntr_Trav + + +
          +int 
          +Ntr_ShortestPaths(
          +  DdManager * dd, 
          +  BnetNetwork * net, 
          +  NtrOptions * option 
          +)
          +
          +
          Computes shortest paths in the state transition graph of a network. Three methods are availabe:
          • Bellman-Ford algorithm for single-source shortest paths; the algorithm computes the distance (number of transitions) from the initial states to all states.
          • Floyd-Warshall algorithm for all-pair shortest paths.
          • Repeated squaring algorithm for all-pair shortest paths.
          The function returns 1 in case of success; 0 otherwise. +

          + +

          Side Effects ADD variables are created in the manager. +

          + +

          +int 
          +Ntr_TestClipping(
          +  DdManager * dd, 
          +  BnetNetwork * net1, 
          +  BnetNetwork * net2, 
          +  NtrOptions * option 
          +)
          +
          +
          Tests BDD clipping functions. Returns 1 if successful; 0 otherwise. +

          + +

          Side Effects None +

          + +

          +int 
          +Ntr_TestClosestCube(
          +  DdManager * dd, 
          +  BnetNetwork * net, 
          +  NtrOptions * option 
          +)
          +
          +
          Tests the Cudd_bddClosestCube function. Returns 1 if successful; 0 otherwise. +

          + +

          Side Effects None +

          + +

          +int 
          +Ntr_TestCofactorEstimate(
          +  DdManager * dd, 
          +  BnetNetwork * net, 
          +  NtrOptions * option 
          +)
          +
          +
          Tests BDD cofactor estimate functions. Returns 1 if successful; 0 otherwise. +

          + +

          Side Effects None +

          + +

          +int 
          +Ntr_TestDecomp(
          +  DdManager * dd, 
          +  BnetNetwork * net1, 
          +  NtrOptions * option 
          +)
          +
          +
          Tests BDD decomposition functions. Returns 1 if successful; 0 otherwise. +

          + +

          Side Effects None +

          + +

          +int 
          +Ntr_TestDensity(
          +  DdManager * dd, 
          +  BnetNetwork * net1, 
          +  NtrOptions * option 
          +)
          +
          +
          Tests BDD density-related functions. Returns 1 if successful; 0 otherwise. +

          + +

          Side Effects None +

          + +

          +int 
          +Ntr_TestEquivAndContain(
          +  DdManager * dd, 
          +  BnetNetwork * net1, 
          +  BnetNetwork * net2, 
          +  NtrOptions * option 
          +)
          +
          +
          Tests functions for BDD equivalence and containment with don't cares, including Cudd_EquivDC and Cudd_bddLeqUnless. This function uses as care set the first output of net2 and checkes equivalence and containment for of all the output pairs of net1. Returns 1 if successful; 0 otherwise. +

          + +

          Side Effects None +

          + +

          +int 
          +Ntr_TestHeap(
          +  NtrHeap * heap, 
          +  int  i 
          +)
          +
          +
          Tests the heap property of a priority queue. Returns 1 if Successful; 0 otherwise. +

          + +

          Side Effects None +

          + +

          +int 
          +Ntr_TestMinimization(
          +  DdManager * dd, 
          +  BnetNetwork * net1, 
          +  BnetNetwork * net2, 
          +  NtrOptions * option 
          +)
          +
          +
          Tests BDD minimization functions, including leaf-identifying compaction, squeezing, and restrict. This function uses as constraint the first output of net2 and computes positive and negative cofactors of all the outputs of net1. For each cofactor, it checks whether compaction was safe (cofactor not larger than original function) and that the expansion based on each minimization function (used as a generalized cofactor) equals the original function. Returns 1 if successful; 0 otherwise. +

          + +

          Side Effects None +

          + +

          +DdNode * 
          +Ntr_TransitiveClosure(
          +  DdManager * dd, 
          +  NtrPartTR * TR, 
          +  NtrOptions * option 
          +)
          +
          +
          Builds the transitive closure of a transition relation. Returns a BDD if successful; NULL otherwise. Uses a simple squaring algorithm. +

          + +

          Side Effects None +

          + +

          +int 
          +Ntr_Trav(
          +  DdManager * dd, DD manager
          +  BnetNetwork * net, network
          +  NtrOptions * option options
          +)
          +
          +
          Poor man's traversal procedure. based on the monolithic transition relation. Returns 1 in case of success; 0 otherwise. +

          + +

          Side Effects None +

          + +

          See Also Ntr_ClosureTrav + + +
          +int 
          +Ntr_VerifyEquivalence(
          +  DdManager * dd, 
          +  BnetNetwork * net1, 
          +  BnetNetwork * net2, 
          +  NtrOptions * option 
          +)
          +
          +
          Verify equivalence of combinational networks. Returns 1 if successful and if the networks are equivalent; -1 if successful, but the networks are not equivalent; 0 otherwise. The two networks are supposed to have the same names for inputs and outputs. The only exception is that the second network may miss output buffers that are present in the first network. This function tries to match both the output and the input of the buffer. +

          + +

          Side Effects None +

          + +

          +int 
          +Ntr_buildDDs(
          +  BnetNetwork * net, network for which DDs are to be built
          +  DdManager * dd, DD manager
          +  NtrOptions * option, option structure
          +  BnetNetwork * net2 companion network with which inputs may be shared
          +)
          +
          +
          Builds DDs for a network outputs and next state functions. The method is really brain-dead, but it is very simple. Returns 1 in case of success; 0 otherwise. Some inputs to the network may be shared with another network whose DDs have already been built. In this case we want to share the DDs as well. +

          + +

          Side Effects the dd fields of the network nodes are modified. Uses the count fields of the nodes. +

          + +

          +NtrPartTR * 
          +Ntr_buildTR(
          +  DdManager * dd, manager
          +  BnetNetwork * net, network
          +  NtrOptions * option, options
          +  int  image image type: monolithic ...
          +)
          +
          +
          Builds the transition relation for a network. Returns a pointer to the transition relation structure if successful; NULL otherwise. +

          + +

          Side Effects None +

          + +

          +NtrPartTR * 
          +Ntr_cloneTR(
          +  NtrPartTR * TR 
          +)
          +
          +
          Makes a copy of a transition relation. Returns a pointer to the copy if successful; NULL otherwise. +

          + +

          Side Effects None +

          + +

          See Also Ntr_buildTR +Ntr_freeTR + + +
          +void 
          +Ntr_freeTR(
          +  DdManager * dd, 
          +  NtrPartTR * TR 
          +)
          +
          +
          Frees the transition relation for a network. +

          + +

          Side Effects None +

          + +

          +DdNode * 
          +Ntr_getStateCube(
          +  DdManager * dd, 
          +  BnetNetwork * net, 
          +  char * filename, 
          +  int  pr 
          +)
          +
          +
          Reads a state cube from a file or create a random one. Returns a pointer to the BDD of the sink nodes if successful; NULL otherwise. +

          + +

          Side Effects None +

          + +

          +DdNode * 
          +Ntr_initState(
          +  DdManager * dd, 
          +  BnetNetwork * net, 
          +  NtrOptions * option 
          +)
          +
          +
          Builds the BDD of the initial state(s). Returns a BDD if successful; NULL otherwise. +

          + +

          Side Effects None +

          + +

          +int 
          +Ntr_maxflow(
          +  DdManager * dd, 
          +  BnetNetwork * net, 
          +  NtrOptions * option 
          +)
          +
          +
          Maximum 0-1 flow between source and sink states. Returns 1 in case of success; 0 otherwise. +

          + +

          Side Effects Creates two new sets of variables. +

          + +

          +double 
          +Ntr_maximum01Flow(
          +  DdManager * bdd, manager
          +  DdNode * sx, source node
          +  DdNode * ty, sink node
          +  DdNode * E, edge relation
          +  DdNode ** F, flow relation
          +  DdNode ** cut, cutset relation
          +  DdNode ** x, array of row variables
          +  DdNode ** y, array of column variables
          +  DdNode ** z, arrays of auxiliary variables
          +  int  n, number of variables in each array
          +  int  pr verbosity level
          +)
          +
          +
          This function implements Dinits's algorithm for (0-1) max flow, using BDDs and a symbolic technique to trace multiple edge-disjoint augmenting paths to complete a phase. The outer forever loop is over phases, and the inner forever loop is to propagate a (not yet) maximal flow of edge-disjoint augmenting paths from one layer to the previous. The subprocedure call implements a least fixed point iteration to compute a (not yet) maximal flow update between layers. At the end of each phase (except the last one) the flow is actually pushed from the source to the sink. Data items:
          • sx(ty) BDD representations of s(t).
          • x(y) The variables encoding the from(to)-node u(v) of an edge (u,v) in the given digraph.
          • z Another set of variables.
          • E(x,y) The edge relation.
          • F(x,y) BDD representation of the current flow, initialized to 0 for each arc, and updated by +1, -1, or 0 at the end of each phase.
          • Ms Mt The maximum flow, that is, the cardinality of a minimum cut, measured at the source and at the sink, respectively. The two values should be identical.
          • reached The set of nodes already visited in the BFS of the digraph.
          • fos fanout of the source node s.
          • fit fanin of the sink node t.
          +

          + +

          Side Effects The flow realtion F and the cutset relation cut are returned as side effects. +

          + +

          +int 
          +Ntr_testISOP(
          +  DdManager * dd, 
          +  BnetNetwork * net, 
          +  NtrOptions * option 
          +)
          +
          +
          Builds ZDD covers. +

          + +

          Side Effects Creates ZDD variables in the manager. +

          + +

          +int 
          +Ntr_testZDD(
          +  DdManager * dd, 
          +  BnetNetwork * net, 
          +  NtrOptions * option 
          +)
          +
          +
          Tests ZDDs. Returns 1 if successful; 0 otherwise. +

          + +

          Side Effects Creates ZDD variables in the manager. +

          + + +

          + +
          + +Generated automatically by extdoc on 1010215 + + diff --git a/distr/nanotrav/main.c b/distr/nanotrav/main.c new file mode 100644 index 0000000..b42d8f8 --- /dev/null +++ b/distr/nanotrav/main.c @@ -0,0 +1,1394 @@ +/**CFile*********************************************************************** + + FileName [main.c] + + PackageName [ntr] + + Synopsis [Main program for the nanotrav program.] + + 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.] + +******************************************************************************/ + +#include "ntr.h" +#include "cuddInt.h" + +/*---------------------------------------------------------------------------*/ +/* Constant declarations */ +/*---------------------------------------------------------------------------*/ + +#define NTR_VERSION\ + "Nanotrav Version #0.12, Release date 2003/12/31" + +#define BUFLENGTH 8192 + +/*---------------------------------------------------------------------------*/ +/* Stucture declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Type declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Variable declarations */ +/*---------------------------------------------------------------------------*/ + +#ifndef lint +static char rcsid[] UTIL_UNUSED = "$Id: main.c,v 1.40 2009/02/21 06:00:31 fabio Exp fabio $"; +#endif + +static char buffer[BUFLENGTH]; +#ifdef DD_DEBUG +extern st_table *checkMinterms (BnetNetwork *net, DdManager *dd, st_table *previous); +#endif + +/*---------------------------------------------------------------------------*/ +/* Macro declarations */ +/*---------------------------------------------------------------------------*/ + +/**AutomaticStart*************************************************************/ + +/*---------------------------------------------------------------------------*/ +/* Static function prototypes */ +/*---------------------------------------------------------------------------*/ + +static NtrOptions * mainInit (); +static void ntrReadOptions (int argc, char **argv, NtrOptions *option); +static void ntrReadOptionsFile (char *name, char ***argv, int *argc); +static char* readLine (FILE *fp); +static FILE * open_file (char *filename, const char *mode); +static int reorder (BnetNetwork *net, DdManager *dd, NtrOptions *option); +static void freeOption (NtrOptions *option); +static DdManager * startCudd (NtrOptions *option, int nvars); +static int ntrReadTree (DdManager *dd, char *treefile, int nvars); + +/**AutomaticEnd***************************************************************/ + +/*---------------------------------------------------------------------------*/ +/* Definition of exported functions */ +/*---------------------------------------------------------------------------*/ + +/**Function******************************************************************** + + Synopsis [Main program for ntr.] + + Description [Main program for ntr. Performs initialization. Reads command + line options and network(s). Builds BDDs with reordering, and optionally + does reachability analysis. Prints stats.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +int +main( + int argc, + char ** argv) +{ + NtrOptions *option; /* options */ + FILE *fp1; /* first network file pointer */ + BnetNetwork *net1 = NULL; /* first network */ + FILE *fp2; /* second network file pointer */ + BnetNetwork *net2 = NULL; /* second network */ + DdManager *dd; /* pointer to DD manager */ + int exitval; /* return value of Cudd_CheckZeroRef */ + int ok; /* overall return value from main() */ + int result; /* stores the return value of functions */ + BnetNode *node; /* auxiliary pointer to network node */ + int i; /* loop index */ + int j; /* loop index */ + double *signatures; /* array of signatures */ + int pr; /* verbosity level */ + int reencoded; /* linear transformations attempted */ + + /* Initialize. */ + option = mainInit(); + ntrReadOptions(argc,argv,option); + pr = option->verb; + reencoded = option->reordering == CUDD_REORDER_LINEAR || + option->reordering == CUDD_REORDER_LINEAR_CONVERGE || + option->autoMethod == CUDD_REORDER_LINEAR || + option->autoMethod == CUDD_REORDER_LINEAR_CONVERGE; + /* Currently traversal requires global BDDs. Override whatever + ** was specified for locGlob. + */ + if (option->traverse == TRUE || option->envelope == TRUE || + option->scc == TRUE) { + option->locGlob = BNET_GLOBAL_DD; + } + + /* Read the first network... */ + fp1 = open_file(option->file1, "r"); + net1 = Bnet_ReadNetwork(fp1,pr); + (void) fclose(fp1); + if (net1 == NULL) { + (void) fprintf(stderr,"Syntax error in %s.\n",option->file1); + exit(2); + } + /* ... and optionally echo it to the standard output. */ + if (pr > 2) { + Bnet_PrintNetwork(net1); + } + + /* Read the second network... */ + if (option->verify == TRUE || option->second == TRUE || + option->clip > 0.0 || option->dontcares) { + fp2 = open_file(option->file2, "r"); + net2 = Bnet_ReadNetwork(fp2,pr); + (void) fclose(fp2); + if (net2 == NULL) { + (void) fprintf(stderr,"Syntax error in %s.\n",option->file2); + exit(2); + } + /* ... and optionally echo it to the standard output. */ + if (pr > 2) { + Bnet_PrintNetwork(net2); + } + } + + /* Initialize manager. We start with 0 variables, because + ** Ntr_buildDDs will create new variables rather than using + ** whatever already exists. + */ + dd = startCudd(option,net1->ninputs); + if (dd == NULL) { exit(2); } + + /* Build the BDDs for the nodes of the first network. */ + result = Ntr_buildDDs(net1,dd,option,NULL); + if (result == 0) { exit(2); } + + /* Build the BDDs for the nodes of the second network if requested. */ + if (option->verify == TRUE || option->second == TRUE || + option->clip > 0.0 || option->dontcares == TRUE) { + char *nodesave = option->node; + option->node = NULL; + result = Ntr_buildDDs(net2,dd,option,net1); + option->node = nodesave; + if (result == 0) { exit(2); } + } + + if (option->noBuild == TRUE) { + Bnet_FreeNetwork(net1); + if (option->verify == TRUE || option->second == TRUE || + option->clip > 0.0) { + Bnet_FreeNetwork(net2); + } + freeOption(option); + exit(0); + } + if (option->locGlob != BNET_LOCAL_DD) { + /* Print the order before the final reordering. */ + (void) printf("Order before final reordering\n"); + result = Bnet_PrintOrder(net1,dd); + if (result == 0) exit(2); + } + + /* Perform final reordering */ + if (option->zddtest == FALSE) { + result = reorder(net1,dd,option); + if (result == 0) exit(2); + + /* Print final order. */ + if ((option->reordering != CUDD_REORDER_NONE || option->gaOnOff) && + option->locGlob != BNET_LOCAL_DD) { + (void) printf("New order\n"); + result = Bnet_PrintOrder(net1,dd); + if (result == 0) exit(2); + } + + /* Print the re-encoded inputs. */ + if (pr >= 1 && reencoded == 1) { + for (i = 0; i < net1->npis; i++) { + if (!st_lookup(net1->hash,net1->inputs[i],&node)) { + exit(2); + } + (void) fprintf(stdout,"%s:",node->name); + Cudd_PrintDebug(dd,node->dd,Cudd_ReadSize(dd),pr); + } + for (i = 0; i < net1->nlatches; i++) { + if (!st_lookup(net1->hash,net1->latches[i][1],&node)) { + exit(2); + } + (void) fprintf(stdout,"%s:",node->name); + Cudd_PrintDebug(dd,node->dd,Cudd_ReadSize(dd),pr); + } + if (pr >= 3) { + result = Cudd_PrintLinear(dd); + if (result == 0) exit(2); + } + } + } + + /* Verify (combinational) equivalence. */ + if (option->verify == TRUE) { + result = Ntr_VerifyEquivalence(dd,net1,net2,option); + if (result == 0) { + (void) printf("Verification abnormally terminated\n"); + exit(2); + } else if (result == -1) { + (void) printf("Combinational verification failed\n"); + } else { + (void) printf("Verification succeeded\n"); + } + } + + /* Traverse if requested and if the circuit is sequential. */ + result = Ntr_Trav(dd,net1,option); + if (result == 0) exit(2); + + /* Traverse with trasitive closure. */ + result = Ntr_ClosureTrav(dd,net1,option); + if (result == 0) exit(2); + + /* Compute outer envelope if requested and if the circuit is sequential. */ + if (option->envelope == TRUE && net1->nlatches > 0) { + NtrPartTR *T; + T = Ntr_buildTR(dd,net1,option,option->image); + result = Ntr_Envelope(dd,T,NULL,option); + Ntr_freeTR(dd,T); + } + + /* Compute SCCs if requested and if the circuit is sequential. */ + result = Ntr_SCC(dd,net1,option); + if (result == 0) exit(2); + + /* Test Constrain Decomposition. */ + if (option->partition == TRUE && net1->nlatches > 0) { + NtrPartTR *T; + DdNode *product; + DdNode **decomp; + int sharingSize; + T = Ntr_buildTR(dd,net1,option,NTR_IMAGE_MONO); + decomp = Cudd_bddConstrainDecomp(dd,T->part[0]); + if (decomp == NULL) exit(2); + sharingSize = Cudd_SharingSize(decomp, Cudd_ReadSize(dd)); + (void) fprintf(stdout, "Decomposition Size: %d components %d nodes\n", + Cudd_ReadSize(dd), sharingSize); + product = Cudd_ReadOne(dd); + Cudd_Ref(product); + for (i = 0; i < Cudd_ReadSize(dd); i++) { + DdNode *intermediate = Cudd_bddAnd(dd, product, decomp[i]); + if (intermediate == NULL) { + exit(2); + } + Cudd_Ref(intermediate); + Cudd_IterDerefBdd(dd, product); + product = intermediate; + } + if (product != T->part[0]) + exit(2); + Cudd_IterDerefBdd(dd, product); + for (i = 0; i < Cudd_ReadSize(dd); i++) { + Cudd_IterDerefBdd(dd, decomp[i]); + } + FREE(decomp); + Ntr_freeTR(dd,T); + } + + /* Test char-to-vect conversion. */ + result = Ntr_TestCharToVect(dd,net1,option); + if (result == 0) exit(2); + + /* Test extraction of two-literal clauses. */ + result = Ntr_TestTwoLiteralClauses(dd,net1,option); + if (result == 0) exit(2); + + /* Test BDD minimization functions. */ + result = Ntr_TestMinimization(dd,net1,net2,option); + if (result == 0) exit(2); + + /* Test density-related functions. */ + result = Ntr_TestDensity(dd,net1,option); + if (result == 0) exit(2); + + /* Test decomposition functions. */ + result = Ntr_TestDecomp(dd,net1,option); + if (result == 0) exit(2); + + /* Test cofactor estimation functions. */ + result = Ntr_TestCofactorEstimate(dd,net1,option); + if (result == 0) exit(2); + + /* Test BDD clipping functions. */ + result = Ntr_TestClipping(dd,net1,net2,option); + if (result == 0) exit(2); + + /* Test BDD equivalence and containment under DC functions. */ + result = Ntr_TestEquivAndContain(dd,net1,net2,option); + if (result == 0) exit(2); + + /* Test BDD Cudd_bddClosestCube. */ + result = Ntr_TestClosestCube(dd,net1,option); + if (result == 0) exit(2); + + /* Test ZDDs if requested. */ + if (option->stateOnly == FALSE && option->zddtest == TRUE) { + result = Ntr_testZDD(dd,net1,option); + if (result == 0) + (void) fprintf(stdout,"ZDD test failed.\n"); + result = Ntr_testISOP(dd,net1,option); + if (result == 0) + (void) fprintf(stdout,"ISOP test failed.\n"); + } + + /* Compute maximum flow if requested and if the circuit is sequential. */ + if (option->maxflow == TRUE && net1->nlatches > 0) { + result = Ntr_maxflow(dd,net1,option); + if (result == 0) + (void) fprintf(stdout,"Maxflow computation failed.\n"); + } + + /* Compute shortest paths if requested and if the circuit is sequential. */ + if (option->shortPath != NTR_SHORT_NONE && net1->nlatches > 0) { + result = Ntr_ShortestPaths(dd,net1,option); + if (result == 0) + (void) fprintf(stdout,"Shortest paths computation failed.\n"); + } + + /* Compute output signatures if so requested. */ + if (option->signatures) { + (void) printf("Positive cofactor measures\n"); + for (i = 0; i < net1->noutputs; i++) { + if (!st_lookup(net1->hash,net1->outputs[i],&node)) { + exit(2); + } + signatures = Cudd_CofMinterm(dd, node->dd); + if (signatures) { + (void) printf("%s:\n", node->name); + for (j = 0; j < Cudd_ReadSize(dd); j++) { + if((j%5 == 0)&&i) (void) printf("\n"); + (void) printf("%5d: %-#8.4g ", j, signatures[j]); + } + (void) printf("\n"); + FREE(signatures); + } else { + (void) printf("Signature computation failed.\n"); + } + } + } + + /* Dump BDDs if so requested. */ + if (option->bdddump && option->second == FALSE && + option->density == FALSE && option->decomp == FALSE && + option->cofest == FALSE && option->clip < 0.0 && + option->scc == FALSE) { + (void) printf("Dumping BDDs to %s\n", option->dumpfile); + if (option->node != NULL) { + if (!st_lookup(net1->hash,option->node,&node)) { + exit(2); + } + result = Bnet_bddArrayDump(dd,net1,option->dumpfile,&(node->dd), + &(node->name),1,option->dumpFmt); + } else { + result = Bnet_bddDump(dd, net1, option->dumpfile, + option->dumpFmt, reencoded); + } + if (result != 1) { + (void) printf("BDD dump failed.\n"); + } + } + + /* Print stats and clean up. */ + if (pr >= 0) { + result = Cudd_PrintInfo(dd,stdout); + if (result != 1) { + (void) printf("Cudd_PrintInfo failed.\n"); + } + } + +#if defined(DD_DEBUG) && !defined(DD_NO_DEATH_ROW) + (void) fprintf(dd->err,"%d empty slots in death row\n", + cuddTimesInDeathRow(dd,NULL)); +#endif + (void) printf("Final size: %ld\n", Cudd_ReadNodeCount(dd)); + + /* Dispose of node BDDs. */ + node = net1->nodes; + while (node != NULL) { + if (node->dd != NULL && + node->type != BNET_INPUT_NODE && + node->type != BNET_PRESENT_STATE_NODE) { + Cudd_IterDerefBdd(dd,node->dd); + } + node = node->next; + } + /* Dispose of network. */ + Bnet_FreeNetwork(net1); + /* Do the same cleanup for the second network if it was created. */ + if (option->verify == TRUE || option->second == TRUE || + option->clip > 0.0 || option->dontcares == TRUE) { + node = net2->nodes; + while (node != NULL) { + if (node->dd != NULL && + node->type != BNET_INPUT_NODE && + node->type != BNET_PRESENT_STATE_NODE) { + Cudd_IterDerefBdd(dd,node->dd); + } + node = node->next; + } + Bnet_FreeNetwork(net2); + } + + /* Check reference counts: At this point we should have dereferenced + ** everything we had, except in the case of re-encoding. + */ + exitval = Cudd_CheckZeroRef(dd); + ok = exitval != 0; /* ok == 0 means O.K. */ + if (exitval != 0) { + (void) fflush(stdout); + (void) fprintf(stderr, + "%d non-zero DD reference counts after dereferencing\n", exitval); + } + +#ifdef DD_DEBUG + Cudd_CheckKeys(dd); +#endif + + Cudd_Quit(dd); + + if (pr >= 0) (void) printf("total time = %s\n", + util_print_time(util_cpu_time() - option->initialTime)); + freeOption(option); + if (pr >= 0) util_print_cpu_stats(stdout); + +#ifdef MNEMOSYNE + mnem_writestats(); +#endif + + exit(ok); + /* NOTREACHED */ + +} /* end of main */ + + +/*---------------------------------------------------------------------------*/ +/* Definition of internal functions */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Definition of static functions */ +/*---------------------------------------------------------------------------*/ + + +/**Function******************************************************************** + + Synopsis [Allocates the option structure and initializes it.] + + Description [] + + SideEffects [none] + + SeeAlso [ntrReadOptions] + +******************************************************************************/ +static NtrOptions * +mainInit( + ) +{ + NtrOptions *option; + + /* Initialize option structure. */ + option = ALLOC(NtrOptions,1); + option->initialTime = util_cpu_time(); + option->verify = FALSE; + option->second = FALSE; + option->file1 = NULL; + option->file2 = NULL; + option->traverse = FALSE; + option->depend = FALSE; + option->image = NTR_IMAGE_MONO; + option->imageClip = 1.0; + option->approx = NTR_UNDER_APPROX; + option->threshold = -1; + option->from = NTR_FROM_NEW; + option->groupnsps = NTR_GROUP_NONE; + option->closure = FALSE; + option->closureClip = 1.0; + option->envelope = FALSE; + option->scc = FALSE; + option->maxflow = FALSE; + option->shortPath = NTR_SHORT_NONE; + option->selectiveTrace = FALSE; + option->zddtest = FALSE; + option->printcover = FALSE; + option->sinkfile = NULL; + option->partition = FALSE; + option->char2vect = FALSE; + option->density = FALSE; + option->quality = 1.0; + option->decomp = FALSE; + option->cofest = FALSE; + option->clip = -1.0; + option->dontcares = FALSE; + option->closestCube = FALSE; + option->clauses = FALSE; + option->noBuild = FALSE; + option->stateOnly = FALSE; + option->node = NULL; + option->locGlob = BNET_GLOBAL_DD; + option->progress = FALSE; + option->cacheSize = 32768; + option->maxMemory = 0; /* set automatically */ + option->maxMemHard = 0; /* don't set */ + option->maxLive = ~0; /* very large number */ + option->slots = CUDD_UNIQUE_SLOTS; + option->ordering = PI_PS_FROM_FILE; + option->orderPiPs = NULL; + option->reordering = CUDD_REORDER_NONE; + option->autoMethod = CUDD_REORDER_SIFT; + option->autoDyn = 0; + option->treefile = NULL; + option->firstReorder = DD_FIRST_REORDER; + option->countDead = FALSE; + option->maxGrowth = 20; + option->groupcheck = CUDD_GROUP_CHECK7; + option->arcviolation = 10; + option->symmviolation = 10; + option->recomb = DD_DEFAULT_RECOMB; + option->nodrop = TRUE; + option->signatures = FALSE; + option->verb = 0; + option->gaOnOff = 0; + option->populationSize = 0; /* use default */ + option->numberXovers = 0; /* use default */ + option->bdddump = FALSE; + option->dumpFmt = 0; /* dot */ + option->dumpfile = NULL; + option->store = -1; /* do not store */ + option->storefile = NULL; + option->load = FALSE; + option->loadfile = NULL; + + return(option); + +} /* end of mainInit */ + + +/**Function******************************************************************** + + Synopsis [Reads the command line options.] + + Description [Reads the command line options. Scans the command line + one argument at a time and performs a switch on each arguement it + hits. Some arguemnts also read in the following arg from the list + (i.e., -f also gets the filename which should folow.) + Gives a usage message and exits if any unrecognized args are found.] + + SideEffects [May initialize the random number generator.] + + SeeAlso [mainInit ntrReadOptionsFile] + +******************************************************************************/ +static void +ntrReadOptions( + int argc, + char ** argv, + NtrOptions * option) +{ + int i = 0; + + if (argc < 2) goto usage; + + if (STRING_EQUAL(argv[1],"-f")) { + ntrReadOptionsFile(argv[2],&argv,&argc); + } + + for (i = 1; i < argc; i++) { + if (argv[i][0] != '-' ) { + if (option->file1 == NULL) { + option->file1 = util_strsav(argv[i]); + } else { + goto usage; + } + } else if (STRING_EQUAL(argv[i],"-second")) { + i++; + option->file2 = util_strsav(argv[i]); + option->second = TRUE; + } else if (STRING_EQUAL(argv[i],"-verify")) { + i++; + option->file2 = util_strsav(argv[i]); + option->verify = TRUE; + } else if (STRING_EQUAL(argv[i],"-trav")) { + option->traverse = TRUE; + } else if (STRING_EQUAL(argv[i],"-depend")) { + option->traverse = TRUE; + option->depend = TRUE; + } else if (STRING_EQUAL(argv[i],"-image")) { + i++; + if (STRING_EQUAL(argv[i],"part")) { + option->image = NTR_IMAGE_PART; + } else if (STRING_EQUAL(argv[i],"clip")) { + option->image = NTR_IMAGE_CLIP; + } else if (STRING_EQUAL(argv[i],"depend")) { + option->image = NTR_IMAGE_DEPEND; + } else if (STRING_EQUAL(argv[i],"mono")) { + option->image = NTR_IMAGE_MONO; + } else { + goto usage; + } + } else if (STRING_EQUAL(argv[i],"-depth")) { + i++; + option->imageClip = (double) atof(argv[i]); + } else if (STRING_EQUAL(argv[i],"-cdepth")) { + i++; + option->closureClip = (double) atof(argv[i]); + } else if (STRING_EQUAL(argv[i],"-approx")) { + i++; + if (STRING_EQUAL(argv[i],"under")) { + option->approx = NTR_UNDER_APPROX; + } else if (STRING_EQUAL(argv[i],"over")) { + option->approx = NTR_OVER_APPROX; + } else { + goto usage; + } + } else if (STRING_EQUAL(argv[i],"-threshold")) { + i++; + option->threshold = (int) atoi(argv[i]); + } else if (STRING_EQUAL(argv[i],"-from")) { + i++; + if (STRING_EQUAL(argv[i],"new")) { + option->from = NTR_FROM_NEW; + } else if (STRING_EQUAL(argv[i],"reached")) { + option->from = NTR_FROM_REACHED; + } else if (STRING_EQUAL(argv[i],"restrict")) { + option->from = NTR_FROM_RESTRICT; + } else if (STRING_EQUAL(argv[i],"compact")) { + option->from = NTR_FROM_COMPACT; + } else if (STRING_EQUAL(argv[i],"squeeze")) { + option->from = NTR_FROM_SQUEEZE; + } else if (STRING_EQUAL(argv[i],"subset")) { + option->from = NTR_FROM_UNDERAPPROX; + } else if (STRING_EQUAL(argv[i],"superset")) { + option->from = NTR_FROM_OVERAPPROX; + } else { + goto usage; + } + } else if (STRING_EQUAL(argv[i],"-groupnsps")) { + i++; + if (STRING_EQUAL(argv[i],"none")) { + option->groupnsps = NTR_GROUP_NONE; + } else if (STRING_EQUAL(argv[i],"default")) { + option->groupnsps = NTR_GROUP_DEFAULT; + } else if (STRING_EQUAL(argv[i],"fixed")) { + option->groupnsps = NTR_GROUP_FIXED; + } else { + goto usage; + } + } else if (STRING_EQUAL(argv[i],"-closure")) { + option->closure = TRUE; + } else if (STRING_EQUAL(argv[i],"-envelope")) { + option->envelope = TRUE; + } else if (STRING_EQUAL(argv[i],"-scc")) { + option->scc = TRUE; + } else if (STRING_EQUAL(argv[i],"-maxflow")) { + option->maxflow = TRUE; + } else if (STRING_EQUAL(argv[i],"-shortpaths")) { + i++; + if (STRING_EQUAL(argv[i],"none")) { + option->shortPath = NTR_SHORT_NONE; + } else if (STRING_EQUAL(argv[i],"bellman")) { + option->shortPath = NTR_SHORT_BELLMAN; + } else if (STRING_EQUAL(argv[i],"floyd")) { + option->shortPath = NTR_SHORT_FLOYD; + } else if (STRING_EQUAL(argv[i],"square")) { + option->shortPath = NTR_SHORT_SQUARE; + } else { + goto usage; + } + } else if (STRING_EQUAL(argv[i],"-selective")) { + option->selectiveTrace = TRUE; + } else if (STRING_EQUAL(argv[i],"-zdd")) { + option->zddtest = TRUE; + } else if (STRING_EQUAL(argv[i],"-cover")) { + option->zddtest = TRUE; + option->printcover = TRUE; + } else if (STRING_EQUAL(argv[i],"-sink")) { + i++; + option->maxflow = TRUE; + option->sinkfile = util_strsav(argv[i]); + } else if (STRING_EQUAL(argv[i],"-part")) { + option->partition = TRUE; + } else if (STRING_EQUAL(argv[i],"-char2vect")) { + option->char2vect = TRUE; + } else if (STRING_EQUAL(argv[i],"-density")) { + option->density = TRUE; + } else if (STRING_EQUAL(argv[i],"-quality")) { + i++; + option->quality = (double) atof(argv[i]); + } else if (STRING_EQUAL(argv[i],"-decomp")) { + option->decomp = TRUE; + } else if (STRING_EQUAL(argv[i],"-cofest")) { + option->cofest = TRUE; + } else if (STRING_EQUAL(argv[i],"-clip")) { + i++; + option->clip = (double) atof(argv[i]); + i++; + option->file2 = util_strsav(argv[i]); + } else if (STRING_EQUAL(argv[i],"-dctest")) { + option->dontcares = TRUE; + i++; + option->file2 = util_strsav(argv[i]); + } else if (STRING_EQUAL(argv[i],"-closest")) { + option->closestCube = TRUE; + } else if (STRING_EQUAL(argv[i],"-clauses")) { + option->clauses = TRUE; + } else if (STRING_EQUAL(argv[i],"-nobuild")) { + option->noBuild = TRUE; + option->reordering = CUDD_REORDER_NONE; + } else if (STRING_EQUAL(argv[i],"-delta")) { + option->stateOnly = TRUE; + } else if (STRING_EQUAL(argv[i],"-node")) { + i++; + option->node = util_strsav(argv[i]); + } else if (STRING_EQUAL(argv[i],"-local")) { + option->locGlob = BNET_LOCAL_DD; + } else if (STRING_EQUAL(argv[i],"-progress")) { + option->progress = TRUE; + } else if (STRING_EQUAL(argv[i],"-cache")) { + i++; + option->cacheSize = (int) atoi(argv[i]); + } else if (STRING_EQUAL(argv[i],"-maxmem")) { + i++; + option->maxMemory = 1048576 * (int) atoi(argv[i]); + } else if (STRING_EQUAL(argv[i],"-memhard")) { + i++; + option->maxMemHard = 1048576 * (int) atoi(argv[i]); + } else if (STRING_EQUAL(argv[i],"-maxlive")) { + i++; + option->maxLive = (unsigned int) atoi(argv[i]); + } else if (STRING_EQUAL(argv[i],"-slots")) { + i++; + option->slots = (int) atoi(argv[i]); + } else if (STRING_EQUAL(argv[i],"-ordering")) { + i++; + if (STRING_EQUAL(argv[i],"dfs")) { + option->ordering = PI_PS_DFS; + } else if (STRING_EQUAL(argv[i],"hw")) { + option->ordering = PI_PS_FROM_FILE; + } else { + goto usage; + } + } else if (STRING_EQUAL(argv[i],"-order")) { + i++; + option->ordering = PI_PS_GIVEN; + option->orderPiPs = util_strsav(argv[i]); + } else if (STRING_EQUAL(argv[i],"-reordering")) { + i++; + if (STRING_EQUAL(argv[i],"none")) { + option->reordering = CUDD_REORDER_NONE; + } else if (STRING_EQUAL(argv[i],"random")) { + option->reordering = CUDD_REORDER_RANDOM; + } else if (STRING_EQUAL(argv[i],"bernard") || + STRING_EQUAL(argv[i],"pivot")) { + option->reordering = CUDD_REORDER_RANDOM_PIVOT; + } else if (STRING_EQUAL(argv[i],"sifting")) { + option->reordering = CUDD_REORDER_SIFT; + } else if (STRING_EQUAL(argv[i],"converge")) { + option->reordering = CUDD_REORDER_SIFT_CONVERGE; + } else if (STRING_EQUAL(argv[i],"symm")) { + option->reordering = CUDD_REORDER_SYMM_SIFT; + } else if (STRING_EQUAL(argv[i],"cosymm")) { + option->reordering = CUDD_REORDER_SYMM_SIFT_CONV; + } else if (STRING_EQUAL(argv[i],"tree") || + STRING_EQUAL(argv[i],"group")) { + option->reordering = CUDD_REORDER_GROUP_SIFT; + } else if (STRING_EQUAL(argv[i],"cotree") || + STRING_EQUAL(argv[i],"cogroup")) { + option->reordering = CUDD_REORDER_GROUP_SIFT_CONV; + } else if (STRING_EQUAL(argv[i],"win2")) { + option->reordering = CUDD_REORDER_WINDOW2; + } else if (STRING_EQUAL(argv[i],"win3")) { + option->reordering = CUDD_REORDER_WINDOW3; + } else if (STRING_EQUAL(argv[i],"win4")) { + option->reordering = CUDD_REORDER_WINDOW4; + } else if (STRING_EQUAL(argv[i],"win2conv")) { + option->reordering = CUDD_REORDER_WINDOW2_CONV; + } else if (STRING_EQUAL(argv[i],"win3conv")) { + option->reordering = CUDD_REORDER_WINDOW3_CONV; + } else if (STRING_EQUAL(argv[i],"win4conv")) { + option->reordering = CUDD_REORDER_WINDOW4_CONV; + } else if (STRING_EQUAL(argv[i],"annealing")) { + option->reordering = CUDD_REORDER_ANNEALING; + } else if (STRING_EQUAL(argv[i],"genetic")) { + option->reordering = CUDD_REORDER_GENETIC; + } else if (STRING_EQUAL(argv[i],"linear")) { + option->reordering = CUDD_REORDER_LINEAR; + } else if (STRING_EQUAL(argv[i],"linconv")) { + option->reordering = CUDD_REORDER_LINEAR_CONVERGE; + } else if (STRING_EQUAL(argv[i],"exact")) { + option->reordering = CUDD_REORDER_EXACT; + } else { + goto usage; + } + } else if (STRING_EQUAL(argv[i],"-autodyn")) { + option->autoDyn = 3; + } else if (STRING_EQUAL(argv[i],"-autodynB")) { + option->autoDyn |= 1; + } else if (STRING_EQUAL(argv[i],"-autodynZ")) { + option->autoDyn |= 2; + } else if (STRING_EQUAL(argv[i],"-automethod")) { + i++; + if (STRING_EQUAL(argv[i],"none")) { + option->autoMethod = CUDD_REORDER_NONE; + } else if (STRING_EQUAL(argv[i],"random")) { + option->autoMethod = CUDD_REORDER_RANDOM; + } else if (STRING_EQUAL(argv[i],"bernard") || + STRING_EQUAL(argv[i],"pivot")) { + option->autoMethod = CUDD_REORDER_RANDOM_PIVOT; + } else if (STRING_EQUAL(argv[i],"sifting")) { + option->autoMethod = CUDD_REORDER_SIFT; + } else if (STRING_EQUAL(argv[i],"converge")) { + option->autoMethod = CUDD_REORDER_SIFT_CONVERGE; + } else if (STRING_EQUAL(argv[i],"symm")) { + option->autoMethod = CUDD_REORDER_SYMM_SIFT; + } else if (STRING_EQUAL(argv[i],"cosymm")) { + option->autoMethod = CUDD_REORDER_SYMM_SIFT_CONV; + } else if (STRING_EQUAL(argv[i],"tree") || + STRING_EQUAL(argv[i],"group")) { + option->autoMethod = CUDD_REORDER_GROUP_SIFT; + } else if (STRING_EQUAL(argv[i],"cotree") || + STRING_EQUAL(argv[i],"cogroup")) { + option->autoMethod = CUDD_REORDER_GROUP_SIFT_CONV; + } else if (STRING_EQUAL(argv[i],"win2")) { + option->autoMethod = CUDD_REORDER_WINDOW2; + } else if (STRING_EQUAL(argv[i],"win3")) { + option->autoMethod = CUDD_REORDER_WINDOW3; + } else if (STRING_EQUAL(argv[i],"win4")) { + option->autoMethod = CUDD_REORDER_WINDOW4; + } else if (STRING_EQUAL(argv[i],"win2conv")) { + option->autoMethod = CUDD_REORDER_WINDOW2_CONV; + } else if (STRING_EQUAL(argv[i],"win3conv")) { + option->autoMethod = CUDD_REORDER_WINDOW3_CONV; + } else if (STRING_EQUAL(argv[i],"win4conv")) { + option->autoMethod = CUDD_REORDER_WINDOW4_CONV; + } else if (STRING_EQUAL(argv[i],"annealing")) { + option->autoMethod = CUDD_REORDER_ANNEALING; + } else if (STRING_EQUAL(argv[i],"genetic")) { + option->autoMethod = CUDD_REORDER_GENETIC; + } else if (STRING_EQUAL(argv[i],"linear")) { + option->autoMethod = CUDD_REORDER_LINEAR; + } else if (STRING_EQUAL(argv[i],"linconv")) { + option->autoMethod = CUDD_REORDER_LINEAR_CONVERGE; + } else if (STRING_EQUAL(argv[i],"exact")) { + option->autoMethod = CUDD_REORDER_EXACT; + } else { + goto usage; + } + } else if (STRING_EQUAL(argv[i],"-tree")) { + i++; + option->treefile = util_strsav(argv[i]); + } else if (STRING_EQUAL(argv[i],"-first")) { + i++; + option->firstReorder = (int)atoi(argv[i]); + } else if (STRING_EQUAL(argv[i],"-countdead")) { + option->countDead = TRUE; + } else if (STRING_EQUAL(argv[i],"-growth")) { + i++; + option->maxGrowth = (int)atoi(argv[i]); + } else if (STRING_EQUAL(argv[i],"-groupcheck")) { + i++; + if (STRING_EQUAL(argv[i],"check")) { + option->groupcheck = CUDD_GROUP_CHECK; + } else if (STRING_EQUAL(argv[i],"nocheck")) { + option->groupcheck = CUDD_NO_CHECK; + } else if (STRING_EQUAL(argv[i],"check2")) { + option->groupcheck = CUDD_GROUP_CHECK2; + } else if (STRING_EQUAL(argv[i],"check3")) { + option->groupcheck = CUDD_GROUP_CHECK3; + } else if (STRING_EQUAL(argv[i],"check4")) { + option->groupcheck = CUDD_GROUP_CHECK4; + } else if (STRING_EQUAL(argv[i],"check5")) { + option->groupcheck = CUDD_GROUP_CHECK5; + } else if (STRING_EQUAL(argv[i],"check6")) { + option->groupcheck = CUDD_GROUP_CHECK6; + } else if (STRING_EQUAL(argv[i],"check7")) { + option->groupcheck = CUDD_GROUP_CHECK7; + } else if (STRING_EQUAL(argv[i],"check8")) { + option->groupcheck = CUDD_GROUP_CHECK8; + } else if (STRING_EQUAL(argv[i],"check9")) { + option->groupcheck = CUDD_GROUP_CHECK9; + } else { + goto usage; + } + } else if (STRING_EQUAL(argv[i],"-arcviolation")) { + i++; + option->arcviolation = (int)atoi(argv[i]); + } else if (STRING_EQUAL(argv[i],"-symmviolation")) { + i++; + option->symmviolation = (int)atoi(argv[i]); + } else if (STRING_EQUAL(argv[i],"-recomb")) { + i++; + option->recomb = (int)atoi(argv[i]); + } else if (STRING_EQUAL(argv[i],"-drop")) { + option->nodrop = FALSE; + } else if (STRING_EQUAL(argv[i],"-sign")) { + option->signatures = TRUE; + } else if (STRING_EQUAL(argv[i],"-genetic")) { + option->gaOnOff = 1; + } else if (STRING_EQUAL(argv[i],"-genepop")) { + option->gaOnOff = 1; + i++; + option->populationSize = (int)atoi(argv[i]); + } else if (STRING_EQUAL(argv[i],"-genexover")) { + option->gaOnOff = 1; + i++; + option->numberXovers = (int) atoi(argv[i]); + } else if (STRING_EQUAL(argv[i],"-seed")) { + i++; + Cudd_Srandom((long)atoi(argv[i])); + } else if (STRING_EQUAL(argv[i],"-dumpfile")) { + i++; + option->bdddump = TRUE; + option->dumpfile = util_strsav(argv[i]); + } else if (STRING_EQUAL(argv[i],"-dumpblif")) { + option->dumpFmt = 1; /* blif */ + } else if (STRING_EQUAL(argv[i],"-dumpdaVinci")) { + option->dumpFmt = 2; /* daVinci */ + } else if (STRING_EQUAL(argv[i],"-dumpddcal")) { + option->dumpFmt = 3; /* DDcal */ + } else if (STRING_EQUAL(argv[i],"-dumpfact")) { + option->dumpFmt = 4; /* factored form */ + } else if (STRING_EQUAL(argv[i],"-dumpmv")) { + option->dumpFmt = 5; /* blif-MV */ + } else if (STRING_EQUAL(argv[i],"-store")) { + i++; + option->store = (int) atoi(argv[i]); + } else if (STRING_EQUAL(argv[i],"-storefile")) { + i++; + option->storefile = util_strsav(argv[i]); + } else if (STRING_EQUAL(argv[i],"-loadfile")) { + i++; + option->load = 1; + option->loadfile = util_strsav(argv[i]); + } else if (STRING_EQUAL(argv[i],"-p")) { + i++; + option->verb = (int) atoi(argv[i]); + } else { + goto usage; + } + } + + if (option->store >= 0 && option->storefile == NULL) { + (void) fprintf(stdout,"-storefile mandatory with -store\n"); + exit(-1); + } + + if (option->verb >= 0) { + (void) printf("# %s\n", NTR_VERSION); + /* echo command line and arguments */ + (void) printf("#"); + for (i = 0; i < argc; i++) { + (void) printf(" %s", argv[i]); + } + (void) printf("\n"); + (void) printf("# CUDD Version "); + Cudd_PrintVersion(stdout); + (void) fflush(stdout); + } + + return; + +usage: /* convenient goto */ + printf("Usage: please read man page\n"); + if (i == 0) { + (void) fprintf(stdout,"too few arguments\n"); + } else { + (void) fprintf(stdout,"option: %s is not defined\n",argv[i]); + } + exit(-1); + +} /* end of ntrReadOptions */ + + +/**Function******************************************************************** + + Synopsis [Reads the program options from a file.] + + Description [Reads the program options from a file. Opens file. Reads + the command line from the otpions file using the read_line func. Scans + the line looking for spaces, each space is a searator and demarks a + new option. When a space is found, it is changed to a \0 to terminate + that string; then the next value of slot points to the next non-space + character. There is a limit of 1024 options. + Should produce an error (presently doesn't) on overrun of options, but + this is very unlikely to happen.] + + SideEffects [none] + + SeeAlso [] + +******************************************************************************/ +static void +ntrReadOptionsFile( + char * name, + char *** argv, + int * argc) +{ + char **slot; + char *line; + char c; + int index,flag; + FILE *fp; + + if ((fp = fopen(name,"r")) == NULL) { + fprintf(stderr,"Error: can not find cmd file %s\n",name); + exit(-1); + } + + slot = ALLOC(char *,1024); + index = 1; + line = readLine(fp); + flag = TRUE; + + do { + c = *line; + if ( c == ' ') { + flag = TRUE; + *line = '\0'; + } else if ( c != ' ' && flag == TRUE) { + flag = FALSE; + slot[index] = line; + index++; + } + line++; + } while ( *line != '\0'); + + + *argv = slot; + *argc = index; + + fclose(fp); + +} /* end of ntrReadOptionsFile */ + + +/**Function******************************************************************** + + Synopsis [Reads a line from the option file.] + + Description [] + + SideEffects [none] + + SeeAlso [] + +******************************************************************************/ +static char* +readLine( + FILE * fp) +{ + int c; + char *pbuffer; + + pbuffer = buffer; + + /* Strip white space from beginning of line. */ + for(;;) { + c = getc(fp); + if ( c == EOF) return(NULL); + if ( c == '\n') { + *pbuffer = '\0'; + return(buffer); /* got a blank line */ + } + if ( c != ' ') break; + } + do { + if ( c == '\\' ) { /* if we have a continuation character.. */ + do { /* scan to end of line */ + c = getc(fp); + if ( c == '\n' ) break; + } while ( c != EOF); + if ( c != EOF) { + *pbuffer = ' '; + pbuffer++; + } else return( buffer); + c = getc(fp); + continue; + } + *pbuffer = (char) c; + pbuffer++; + c = getc(fp); + } while( c != '\n' && c != EOF); + *pbuffer = '\0'; + return(buffer); + +} /* end of readLine */ + + +/**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 [Applies reordering to the DDs.] + + Description [Explicitly applies reordering to the DDs. Returns 1 if + successful; 0 otherwise.] + + SideEffects [None] + + SeeAlso [] + +*****************************************************************************/ +static int +reorder( + BnetNetwork * net, + DdManager * dd /* DD Manager */, + NtrOptions * option) +{ +#ifdef DD_DEBUG + st_table *mintermTable; /* minterm counts for each output */ +#endif + int result; /* return value from functions */ + + (void) printf("Number of inputs = %d\n",net->ninputs); + + /* Perform the final reordering */ + if (option->reordering != CUDD_REORDER_NONE) { +#ifdef DD_DEBUG + result = Cudd_DebugCheck(dd); + if (result != 0) { + (void) fprintf(stderr,"Error reported by Cudd_DebugCheck\n"); + return(0); + } + result = Cudd_CheckKeys(dd); + if (result != 0) { + (void) fprintf(stderr,"Error reported by Cudd_CheckKeys\n"); + return(0); + } + mintermTable = checkMinterms(net,dd,NULL); + if (mintermTable == NULL) exit(2); +#endif + + dd->siftMaxVar = 1000000; + dd->siftMaxSwap = 1000000000; + result = Cudd_ReduceHeap(dd,option->reordering,1); + if (result == 0) return(0); +#ifdef DD_DEBUG + result = Cudd_DebugCheck(dd); + if (result != 0) { + (void) fprintf(stderr,"Error reported by Cudd_DebugCheck\n"); + return(0); + } + result = Cudd_CheckKeys(dd); + if (result != 0) { + (void) fprintf(stderr,"Error reported by Cudd_CheckKeys\n"); + return(0); + } + mintermTable = checkMinterms(net,dd,mintermTable); +#endif + + /* Print symmetry stats if pertinent */ + if (dd->tree == NULL && + (option->reordering == CUDD_REORDER_SYMM_SIFT || + option->reordering == CUDD_REORDER_SYMM_SIFT_CONV)) + Cudd_SymmProfile(dd,0,dd->size - 1); + } + + if (option->gaOnOff) { + result = Cudd_ReduceHeap(dd,CUDD_REORDER_GENETIC,1); + if (result == 0) { + (void) printf("Something went wrong in cuddGa\n"); + return(0); + } + } + + return(1); + +} /* end of reorder */ + + +/**Function******************************************************************** + + Synopsis [Frees the option structure and its appendages.] + + Description [] + + SideEffects [None] + + SeeAlso [] + +*****************************************************************************/ +static void +freeOption( + NtrOptions * option) +{ + if (option->file1 != NULL) FREE(option->file1); + if (option->file2 != NULL) FREE(option->file2); + if (option->orderPiPs != NULL) FREE(option->orderPiPs); + if (option->treefile != NULL) FREE(option->treefile); + if (option->sinkfile != NULL) FREE(option->sinkfile); + if (option->dumpfile != NULL) FREE(option->dumpfile); + if (option->loadfile != NULL) FREE(option->loadfile); + if (option->storefile != NULL) FREE(option->storefile); + if (option->node != NULL) FREE(option->node); + FREE(option); + +} /* end of freeOption */ + + +/**Function******************************************************************** + + Synopsis [Starts the CUDD manager with the desired options.] + + Description [Starts the CUDD manager with the desired options. + We start with 0 variables, because Ntr_buildDDs will create new + variables rather than using whatever already exists.] + + SideEffects [None] + + SeeAlso [] + +*****************************************************************************/ +static DdManager * +startCudd( + NtrOptions * option, + int nvars) +{ + DdManager *dd; + int result; + + dd = Cudd_Init(0, 0, option->slots, option->cacheSize, option->maxMemory); + if (dd == NULL) return(NULL); + + if (option->maxMemHard != 0) { + Cudd_SetMaxMemory(dd,option->maxMemHard); + } + Cudd_SetMaxLive(dd,option->maxLive); + Cudd_SetGroupcheck(dd,option->groupcheck); + if (option->autoDyn & 1) { + Cudd_AutodynEnable(dd,option->autoMethod); + } + dd->nextDyn = option->firstReorder; + dd->countDead = (option->countDead == FALSE) ? ~0 : 0; + dd->maxGrowth = 1.0 + ((float) option->maxGrowth / 100.0); + dd->recomb = option->recomb; + dd->arcviolation = option->arcviolation; + dd->symmviolation = option->symmviolation; + dd->populationSize = option->populationSize; + dd->numberXovers = option->numberXovers; + result = ntrReadTree(dd,option->treefile,nvars); + if (result == 0) { + Cudd_Quit(dd); + return(NULL); + } +#ifndef DD_STATS + result = Cudd_EnableReorderingReporting(dd); + if (result == 0) { + (void) fprintf(stderr, + "Error reported by Cudd_EnableReorderingReporting\n"); + Cudd_Quit(dd); + return(NULL); + } +#endif + + return(dd); + +} /* end of startCudd */ + + +/**Function******************************************************************** + + Synopsis [Reads the variable group tree from a file.] + + Description [Reads the variable group tree from a file. + Returns 1 if successful; 0 otherwise.] + + SideEffects [None] + + SeeAlso [] + +*****************************************************************************/ +static int +ntrReadTree( + DdManager * dd, + char * treefile, + int nvars) +{ + FILE *fp; + MtrNode *root; + + if (treefile == NULL) { + return(1); + } + + if ((fp = fopen(treefile,"r")) == NULL) { + (void) fprintf(stderr,"Unable to open %s\n",treefile); + return(0); + } + + root = Mtr_ReadGroups(fp,ddMax(Cudd_ReadSize(dd),nvars)); + if (root == NULL) { + return(0); + } + + Cudd_SetTree(dd,root); + + return(1); + +} /* end of ntrReadTree */ diff --git a/distr/nanotrav/mult32a.blif b/distr/nanotrav/mult32a.blif new file mode 100644 index 0000000..5fafc00 --- /dev/null +++ b/distr/nanotrav/mult32a.blif @@ -0,0 +1,745 @@ +.model MultiplierA_32 +.inputs 1 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 +.outputs 68 +.latch 67 2 0 +.latch 69 36 0 +.latch 70 37 0 +.latch 71 38 0 +.latch 72 39 0 +.latch 73 40 0 +.latch 74 41 0 +.latch 75 42 0 +.latch 76 43 0 +.latch 77 44 0 +.latch 78 45 0 +.latch 79 46 0 +.latch 80 47 0 +.latch 81 48 0 +.latch 82 49 0 +.latch 83 50 0 +.latch 84 51 0 +.latch 85 52 0 +.latch 86 53 0 +.latch 87 54 0 +.latch 88 55 0 +.latch 89 56 0 +.latch 90 57 0 +.latch 91 58 0 +.latch 92 59 0 +.latch 93 60 0 +.latch 94 61 0 +.latch 95 62 0 +.latch 96 63 0 +.latch 97 64 0 +.latch 98 65 0 +.latch 99 66 0 +.names 101 100 +0 1 +.names 1 204 101 +00 1 +11 1 +.names 3 102 +1 1 +.names 4 103 +1 1 +.names 5 104 +1 1 +.names 6 105 +1 1 +.names 7 106 +1 1 +.names 8 107 +1 1 +.names 9 108 +1 1 +.names 10 109 +1 1 +.names 11 110 +1 1 +.names 12 111 +1 1 +.names 13 112 +1 1 +.names 14 113 +1 1 +.names 15 114 +1 1 +.names 16 115 +1 1 +.names 17 116 +1 1 +.names 18 117 +1 1 +.names 19 118 +1 1 +.names 20 119 +1 1 +.names 21 120 +1 1 +.names 22 121 +1 1 +.names 23 122 +1 1 +.names 24 123 +1 1 +.names 25 124 +1 1 +.names 26 125 +1 1 +.names 27 126 +1 1 +.names 28 127 +1 1 +.names 29 128 +1 1 +.names 30 129 +1 1 +.names 31 130 +1 1 +.names 32 131 +1 1 +.names 33 132 +1 1 +.names 34 133 +1 1 +.names 134 +.names 135 +.names 136 +.names 137 +.names 138 +.names 139 +.names 140 +.names 141 +.names 142 +.names 143 +.names 144 +.names 145 +.names 146 +.names 147 +.names 148 +.names 149 +.names 150 +.names 151 +.names 152 +.names 153 +.names 154 +.names 155 +.names 156 +.names 157 +.names 158 +.names 159 +.names 160 +.names 161 +.names 162 +.names 163 +.names 164 +.names 165 +.names 66 265 266 166 +-11 1 +1-1 1 +11- 1 +.names 36 205 206 167 +010 1 +001 1 +100 1 +111 1 +.names 37 207 208 168 +010 1 +001 1 +100 1 +111 1 +.names 38 209 210 169 +010 1 +001 1 +100 1 +111 1 +.names 39 211 212 170 +010 1 +001 1 +100 1 +111 1 +.names 40 213 214 171 +010 1 +001 1 +100 1 +111 1 +.names 41 215 216 172 +010 1 +001 1 +100 1 +111 1 +.names 42 217 218 173 +010 1 +001 1 +100 1 +111 1 +.names 43 219 220 174 +010 1 +001 1 +100 1 +111 1 +.names 44 221 222 175 +010 1 +001 1 +100 1 +111 1 +.names 45 223 224 176 +010 1 +001 1 +100 1 +111 1 +.names 46 225 226 177 +010 1 +001 1 +100 1 +111 1 +.names 47 227 228 178 +010 1 +001 1 +100 1 +111 1 +.names 48 229 230 179 +010 1 +001 1 +100 1 +111 1 +.names 49 231 232 180 +010 1 +001 1 +100 1 +111 1 +.names 50 233 234 181 +010 1 +001 1 +100 1 +111 1 +.names 51 235 236 182 +010 1 +001 1 +100 1 +111 1 +.names 52 237 238 183 +010 1 +001 1 +100 1 +111 1 +.names 53 239 240 184 +010 1 +001 1 +100 1 +111 1 +.names 54 241 242 185 +010 1 +001 1 +100 1 +111 1 +.names 55 243 244 186 +010 1 +001 1 +100 1 +111 1 +.names 56 245 246 187 +010 1 +001 1 +100 1 +111 1 +.names 57 247 248 188 +010 1 +001 1 +100 1 +111 1 +.names 58 249 250 189 +010 1 +001 1 +100 1 +111 1 +.names 59 251 252 190 +010 1 +001 1 +100 1 +111 1 +.names 60 253 254 191 +010 1 +001 1 +100 1 +111 1 +.names 61 255 256 192 +010 1 +001 1 +100 1 +111 1 +.names 62 257 258 193 +010 1 +001 1 +100 1 +111 1 +.names 63 259 260 194 +010 1 +001 1 +100 1 +111 1 +.names 64 261 262 195 +010 1 +001 1 +100 1 +111 1 +.names 65 263 264 196 +010 1 +001 1 +100 1 +111 1 +.names 66 265 266 197 +010 1 +001 1 +100 1 +111 1 +.names 2 268 198 +10 1 +01 1 +.names 269 270 199 +11 1 +.names 166 272 200 +11 1 +.names 166 274 201 +11 1 +.names 166 275 202 +11 1 +.names 276 277 203 +-1 1 +1- 1 +.names 204 +.names 205 +.names 340 341 206 +-1 1 +1- 1 +.names 36 205 206 207 +-11 1 +1-1 1 +11- 1 +.names 338 339 208 +-1 1 +1- 1 +.names 37 207 208 209 +-11 1 +1-1 1 +11- 1 +.names 336 337 210 +-1 1 +1- 1 +.names 38 209 210 211 +-11 1 +1-1 1 +11- 1 +.names 334 335 212 +-1 1 +1- 1 +.names 39 211 212 213 +-11 1 +1-1 1 +11- 1 +.names 332 333 214 +-1 1 +1- 1 +.names 40 213 214 215 +-11 1 +1-1 1 +11- 1 +.names 330 331 216 +-1 1 +1- 1 +.names 41 215 216 217 +-11 1 +1-1 1 +11- 1 +.names 328 329 218 +-1 1 +1- 1 +.names 42 217 218 219 +-11 1 +1-1 1 +11- 1 +.names 326 327 220 +-1 1 +1- 1 +.names 43 219 220 221 +-11 1 +1-1 1 +11- 1 +.names 324 325 222 +-1 1 +1- 1 +.names 44 221 222 223 +-11 1 +1-1 1 +11- 1 +.names 322 323 224 +-1 1 +1- 1 +.names 45 223 224 225 +-11 1 +1-1 1 +11- 1 +.names 320 321 226 +-1 1 +1- 1 +.names 46 225 226 227 +-11 1 +1-1 1 +11- 1 +.names 318 319 228 +-1 1 +1- 1 +.names 47 227 228 229 +-11 1 +1-1 1 +11- 1 +.names 316 317 230 +-1 1 +1- 1 +.names 48 229 230 231 +-11 1 +1-1 1 +11- 1 +.names 314 315 232 +-1 1 +1- 1 +.names 49 231 232 233 +-11 1 +1-1 1 +11- 1 +.names 312 313 234 +-1 1 +1- 1 +.names 50 233 234 235 +-11 1 +1-1 1 +11- 1 +.names 310 311 236 +-1 1 +1- 1 +.names 51 235 236 237 +-11 1 +1-1 1 +11- 1 +.names 308 309 238 +-1 1 +1- 1 +.names 52 237 238 239 +-11 1 +1-1 1 +11- 1 +.names 306 307 240 +-1 1 +1- 1 +.names 53 239 240 241 +-11 1 +1-1 1 +11- 1 +.names 304 305 242 +-1 1 +1- 1 +.names 54 241 242 243 +-11 1 +1-1 1 +11- 1 +.names 302 303 244 +-1 1 +1- 1 +.names 55 243 244 245 +-11 1 +1-1 1 +11- 1 +.names 300 301 246 +-1 1 +1- 1 +.names 56 245 246 247 +-11 1 +1-1 1 +11- 1 +.names 298 299 248 +-1 1 +1- 1 +.names 57 247 248 249 +-11 1 +1-1 1 +11- 1 +.names 296 297 250 +-1 1 +1- 1 +.names 58 249 250 251 +-11 1 +1-1 1 +11- 1 +.names 294 295 252 +-1 1 +1- 1 +.names 59 251 252 253 +-11 1 +1-1 1 +11- 1 +.names 292 293 254 +-1 1 +1- 1 +.names 60 253 254 255 +-11 1 +1-1 1 +11- 1 +.names 290 291 256 +-1 1 +1- 1 +.names 61 255 256 257 +-11 1 +1-1 1 +11- 1 +.names 288 289 258 +-1 1 +1- 1 +.names 62 257 258 259 +-11 1 +1-1 1 +11- 1 +.names 286 287 260 +-1 1 +1- 1 +.names 63 259 260 261 +-11 1 +1-1 1 +11- 1 +.names 284 285 262 +-1 1 +1- 1 +.names 64 261 262 263 +-11 1 +1-1 1 +11- 1 +.names 282 283 264 +-1 1 +1- 1 +.names 65 263 264 265 +-11 1 +1-1 1 +11- 1 +.names 280 281 266 +-1 1 +1- 1 +.names 278 279 267 +-1 1 +1- 1 +.names 166 267 268 +01 1 +10 1 +.names 2 267 269 +11 1 +.names 166 270 +0 1 +.names 267 271 +0 1 +.names 2 271 272 +11 1 +.names 2 273 +0 1 +.names 267 273 274 +11 1 +.names 2 267 275 +11 1 +.names 199 200 276 +-1 1 +1- 1 +.names 201 202 277 +-1 1 +1- 1 +.names 203 67 +1 1 +.names 167 68 +1 1 +.names 168 69 +1 1 +.names 169 70 +1 1 +.names 170 71 +1 1 +.names 171 72 +1 1 +.names 172 73 +1 1 +.names 173 74 +1 1 +.names 174 75 +1 1 +.names 175 76 +1 1 +.names 176 77 +1 1 +.names 177 78 +1 1 +.names 178 79 +1 1 +.names 179 80 +1 1 +.names 180 81 +1 1 +.names 181 82 +1 1 +.names 182 83 +1 1 +.names 183 84 +1 1 +.names 184 85 +1 1 +.names 185 86 +1 1 +.names 186 87 +1 1 +.names 187 88 +1 1 +.names 188 89 +1 1 +.names 189 90 +1 1 +.names 190 91 +1 1 +.names 191 92 +1 1 +.names 192 93 +1 1 +.names 193 94 +1 1 +.names 194 95 +1 1 +.names 195 96 +1 1 +.names 196 97 +1 1 +.names 197 98 +1 1 +.names 198 99 +1 1 +.names 100 133 278 +11 1 +.names 101 165 279 +11 1 +.names 100 132 280 +11 1 +.names 101 164 281 +11 1 +.names 100 131 282 +11 1 +.names 101 163 283 +11 1 +.names 100 130 284 +11 1 +.names 101 162 285 +11 1 +.names 100 129 286 +11 1 +.names 101 161 287 +11 1 +.names 100 128 288 +11 1 +.names 101 160 289 +11 1 +.names 100 127 290 +11 1 +.names 101 159 291 +11 1 +.names 100 126 292 +11 1 +.names 101 158 293 +11 1 +.names 100 125 294 +11 1 +.names 101 157 295 +11 1 +.names 100 124 296 +11 1 +.names 101 156 297 +11 1 +.names 100 123 298 +11 1 +.names 101 155 299 +11 1 +.names 100 122 300 +11 1 +.names 101 154 301 +11 1 +.names 100 121 302 +11 1 +.names 101 153 303 +11 1 +.names 100 120 304 +11 1 +.names 101 152 305 +11 1 +.names 100 119 306 +11 1 +.names 101 151 307 +11 1 +.names 100 118 308 +11 1 +.names 101 150 309 +11 1 +.names 100 117 310 +11 1 +.names 101 149 311 +11 1 +.names 100 116 312 +11 1 +.names 101 148 313 +11 1 +.names 100 115 314 +11 1 +.names 101 147 315 +11 1 +.names 100 114 316 +11 1 +.names 101 146 317 +11 1 +.names 100 113 318 +11 1 +.names 101 145 319 +11 1 +.names 100 112 320 +11 1 +.names 101 144 321 +11 1 +.names 100 111 322 +11 1 +.names 101 143 323 +11 1 +.names 100 110 324 +11 1 +.names 101 142 325 +11 1 +.names 100 109 326 +11 1 +.names 101 141 327 +11 1 +.names 100 108 328 +11 1 +.names 101 140 329 +11 1 +.names 100 107 330 +11 1 +.names 101 139 331 +11 1 +.names 100 106 332 +11 1 +.names 101 138 333 +11 1 +.names 100 105 334 +11 1 +.names 101 137 335 +11 1 +.names 100 104 336 +11 1 +.names 101 136 337 +11 1 +.names 100 103 338 +11 1 +.names 101 135 339 +11 1 +.names 100 102 340 +11 1 +.names 101 134 341 +11 1 +.end diff --git a/distr/nanotrav/mult32a.out b/distr/nanotrav/mult32a.out new file mode 100644 index 0000000..f093330 --- /dev/null +++ b/distr/nanotrav/mult32a.out @@ -0,0 +1,258 @@ +# Nanotrav Version #0.12, Release date 2003/12/31 +# ./nanotrav -p 1 -autodyn -reordering sifting -trav mult32a.blif +# CUDD Version 2.4.2 +BDD reordering with sifting: from 4001 to ... 268 nodes in 0.005 sec +BDD reordering with sifting: from 537 to ... 246 nodes in 0.006 sec +BDD reordering with sifting: from 493 to ... 250 nodes in 0.009 sec +BDD reordering with sifting: from 501 to ... 280 nodes in 0.012 sec +BDD reordering with sifting: from 561 to ... 296 nodes in 0.015 sec +Order before final reordering +2 34 33 66 32 65 31 64 +63 30 62 29 28 61 27 60 +26 59 25 58 24 57 23 56 +22 55 21 54 20 53 19 52 +51 18 50 17 49 16 48 15 +47 14 46 13 45 12 36 3 +37 4 38 5 39 6 40 7 +41 8 42 9 43 10 44 11 +1 +Number of inputs = 65 +BDD reordering with sifting: from 380 to ... 317 nodes in 0.012 sec +New order +1 2 34 66 33 65 32 64 +31 63 30 62 29 61 28 60 +27 59 26 58 25 57 24 56 +23 55 22 54 21 53 20 52 +19 51 18 50 17 49 16 48 +15 47 14 46 13 45 12 36 +3 4 37 5 38 6 39 7 +40 8 41 9 42 10 43 44 +11 +Building transition relation. Time = 0.06 sec +BDD reordering with sifting: from 670 to ... 453 nodes in 0.029 sec +@@BDD reordering with sifting: from 940 to ... 700 nodes in 0.03 sec +@@BDD reordering with sifting: from 1433 to ... 832 nodes in 0.039 sec +@@BDD reordering with sifting: from 1697 to ... 1063 nodes in 0.045 sec +@@@BDD reordering with sifting: from 2159 to ... 786 nodes in 0.049 sec +@@@@BDD reordering with sifting: from 1605 to ... 893 nodes in 0.043 sec +@@@@BDD reordering with sifting: from 1819 to ... 951 nodes in 0.048 sec +@@@@@BDD reordering with sifting: from 1935 to ... 965 nodes in 0.055 sec +@@@@@BDD reordering with sifting: from 1963 to ... 1055 nodes in 0.059 sec +@@@@@ +Transition relation: 1 parts 32 latches 199 nodes +Traversing. Time = 0.46 sec +S0: 33 nodes 1 leaves 1 minterms +From[1]: 33 nodes 1 leaves 2.14748e+09 minterms +Reached[1]: 2 nodes 1 leaves 2.14748e+09 minterms +2147483648 +2.14748e+9 +From[2]: 3 nodes 1 leaves 1.07374e+09 minterms +Reached[2]: 3 nodes 1 leaves 3.22123e+09 minterms +3221225472 +3.22122e+9 +From[3]: 4 nodes 1 leaves 5.36871e+08 minterms +Reached[3]: 4 nodes 1 leaves 3.7581e+09 minterms +3758096384 +3.75809e+9 +From[4]: 5 nodes 1 leaves 2.68435e+08 minterms +Reached[4]: 5 nodes 1 leaves 4.02653e+09 minterms +4026531840 +4.02653e+9 +From[5]: 6 nodes 1 leaves 1.34218e+08 minterms +Reached[5]: 6 nodes 1 leaves 4.16075e+09 minterms +4160749568 +4.16074e+9 +From[6]: 7 nodes 1 leaves 6.71089e+07 minterms +Reached[6]: 7 nodes 1 leaves 4.22786e+09 minterms +4227858432 +4.22785e+9 +From[7]: 8 nodes 1 leaves 3.35544e+07 minterms +Reached[7]: 8 nodes 1 leaves 4.26141e+09 minterms +4261412864 +4.26141e+9 +From[8]: 9 nodes 1 leaves 1.67772e+07 minterms +Reached[8]: 9 nodes 1 leaves 4.27819e+09 minterms +4278190080 +4.27819e+9 +From[9]: 10 nodes 1 leaves 8.38861e+06 minterms +Reached[9]: 10 nodes 1 leaves 4.28658e+09 minterms +4286578688 +4.28657e+9 +From[10]: 11 nodes 1 leaves 4.1943e+06 minterms +Reached[10]: 11 nodes 1 leaves 4.29077e+09 minterms +4290772992 +4.29077e+9 +From[11]: 12 nodes 1 leaves 2.09715e+06 minterms +Reached[11]: 12 nodes 1 leaves 4.29287e+09 minterms +4292870144 +4.29287e+9 +From[12]: 13 nodes 1 leaves 1.04858e+06 minterms +Reached[12]: 13 nodes 1 leaves 4.29392e+09 minterms +4293918720 +4.29391e+9 +From[13]: 14 nodes 1 leaves 524288 minterms +Reached[13]: 14 nodes 1 leaves 4.29444e+09 minterms +4294443008 +4.29444e+9 +From[14]: 15 nodes 1 leaves 262144 minterms +Reached[14]: 15 nodes 1 leaves 4.29471e+09 minterms +4294705152 +4.29470e+9 +From[15]: 16 nodes 1 leaves 131072 minterms +Reached[15]: 16 nodes 1 leaves 4.29484e+09 minterms +4294836224 +4.29483e+9 +From[16]: 17 nodes 1 leaves 65536 minterms +Reached[16]: 17 nodes 1 leaves 4.2949e+09 minterms +4294901760 +4.29490e+9 +From[17]: 18 nodes 1 leaves 32768 minterms +Reached[17]: 18 nodes 1 leaves 4.29493e+09 minterms +4294934528 +4.29493e+9 +From[18]: 19 nodes 1 leaves 16384 minterms +Reached[18]: 19 nodes 1 leaves 4.29495e+09 minterms +4294950912 +4.29495e+9 +From[19]: 20 nodes 1 leaves 8192 minterms +Reached[19]: 20 nodes 1 leaves 4.29496e+09 minterms +4294959104 +4.29495e+9 +From[20]: 21 nodes 1 leaves 4096 minterms +Reached[20]: 21 nodes 1 leaves 4.29496e+09 minterms +4294963200 +4.29496e+9 +From[21]: 22 nodes 1 leaves 2048 minterms +Reached[21]: 22 nodes 1 leaves 4.29497e+09 minterms +4294965248 +4.29496e+9 +From[22]: 23 nodes 1 leaves 1024 minterms +Reached[22]: 23 nodes 1 leaves 4.29497e+09 minterms +4294966272 +4.29496e+9 +From[23]: 24 nodes 1 leaves 512 minterms +Reached[23]: 24 nodes 1 leaves 4.29497e+09 minterms +4294966784 +4.29496e+9 +From[24]: 25 nodes 1 leaves 256 minterms +Reached[24]: 25 nodes 1 leaves 4.29497e+09 minterms +4294967040 +4.29496e+9 +From[25]: 26 nodes 1 leaves 128 minterms +Reached[25]: 26 nodes 1 leaves 4.29497e+09 minterms +4294967168 +4.29496e+9 +From[26]: 27 nodes 1 leaves 64 minterms +Reached[26]: 27 nodes 1 leaves 4.29497e+09 minterms +4294967232 +4.29496e+9 +From[27]: 28 nodes 1 leaves 32 minterms +Reached[27]: 28 nodes 1 leaves 4.29497e+09 minterms +4294967264 +4.29496e+9 +From[28]: 29 nodes 1 leaves 16 minterms +Reached[28]: 29 nodes 1 leaves 4.29497e+09 minterms +4294967280 +4.29496e+9 +From[29]: 30 nodes 1 leaves 8 minterms +Reached[29]: 30 nodes 1 leaves 4.29497e+09 minterms +4294967288 +4.29496e+9 +From[30]: 31 nodes 1 leaves 4 minterms +Reached[30]: 31 nodes 1 leaves 4.29497e+09 minterms +4294967292 +4.29496e+9 +From[31]: 32 nodes 1 leaves 2 minterms +Reached[31]: 32 nodes 1 leaves 4.29497e+09 minterms +4294967294 +4.29496e+9 +From[32]: 33 nodes 1 leaves 1 minterms +Reached[32]: 33 nodes 1 leaves 4.29497e+09 minterms +4294967295 +4.29496e+9 +depth = 32 +R: 33 nodes 1 leaves 4.29497e+09 minterms +Order at the end of reachability analysis +1 2 34 33 66 32 65 31 +64 63 30 29 62 28 61 60 +27 59 26 58 25 57 24 56 +23 55 22 54 21 20 53 19 +52 18 51 17 50 16 49 15 +48 14 47 13 46 12 45 11 +44 10 43 3 36 4 37 5 +38 6 39 7 40 8 41 42 +9 +**** 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: 1000000 +Maximum number of variable swaps per reordering: 1000000000 +Maximum growth while sifting a variable: 1.2 +Dynamic reordering of BDDs enabled: yes +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: 10 +Arc violation threshold: 10 +GA population size: 0 +Number of crossovers for GA: 0 +Next reordering threshold: 2178 +**** CUDD non-modifiable parameters **** +Memory in use: 5461692 +Peak number of nodes: 7154 +Peak number of live nodes: 4004 +Number of BDD variables: 97 +Number of ZDD variables: 0 +Number of cache entries: 65536 +Number of cache look-ups: 48730 +Number of cache hits: 20857 +Number of cache insertions: 27828 +Number of cache collisions: 997 +Number of cache deletions: 20076 +Cache used slots = 17.56% (expected 10.31%) +Soft limit for cache size: 100352 +Number of buckets in unique table: 25088 +Used buckets in unique table: 12.29% (expected 12.30%) +Number of BDD and ADD nodes: 3533 +Number of ZDD nodes: 0 +Number of dead BDD and ADD nodes: 3186 +Number of dead ZDD nodes: 0 +Total number of nodes allocated: 23948 +Total number of nodes reclaimed: 3937 +Garbage collections so far: 15 +Time for garbage collection: 0.00 sec +Reorderings so far: 15 +Time for reordering: 0.46 sec +Final size: 275 +total time = 0.47 sec +Runtime Statistics +------------------ +Machine name: jobim.colorado.edu +User time 0.5 seconds +System time 0.0 seconds + +Average resident text size = 0K +Average resident data+stack size = 0K +Maximum resident size = 0K + +Virtual text size = 131815K +Virtual data size = 297K + data size initialized = 25K + data size uninitialized = 137K + data size sbrk = 135K +Virtual memory limit = 358400K (4194304K) + +Major page faults = 0 +Minor page faults = 1754 +Swaps = 0 +Input blocks = 0 +Output blocks = 0 +Context switch (voluntary) = 1 +Context switch (involuntary) = 21 diff --git a/distr/nanotrav/nanotrav.1 b/distr/nanotrav/nanotrav.1 new file mode 100644 index 0000000..ba50f46 --- /dev/null +++ b/distr/nanotrav/nanotrav.1 @@ -0,0 +1,379 @@ +.\" $Id: nanotrav.1,v 1.23 2009/02/21 06:00:31 fabio Exp fabio $ +.\" +.TH NANOTRAV 1 "18 June 2002" "Release 0.11" +.SH NAME +nanotrav \- a simple state graph traversal program +.SH SYNOPSIS +.B nanotrav +[option ...] +.SH DESCRIPTION + +nanotrav builds the BDDs of a circuit and applies various reordering +methods to the BDDs. It then traverses the state transition graph of +the circuit if the circuit is sequential, and if the user so requires. +nanotrav is based on the CUDD package. The ordering of the variables +is affected by three sets of options: the options that specify the +initial order (-order -ordering); the options that specify the +reordering while the BDDs are being built (-autodyn -automethod); and +the options to specify the final reordering (-reordering +-genetic). Notice that both -autodyn and -automethod must be specified +to get dynamic reordering. The first enables reordering, while the +second says what method to use. +.SH OPTIONS +.TP 10 +.B \fIfile\fB +read input in blif format from \fIfile\fR. +.TP 10 +.B \-f \fIfile\fB +read options from \fIfile\fR. +.TP 10 +.B \-trav +traverse the state transition graph after building the BDDs. This +option has effect only if the circuit is sequential. The initial +states for traversal are taken from the blif file. +.TP 10 +.B \-depend +perform dependent variable analysis after traversal. +.TP 10 +.B \-from \fImethod\fB +use \fImethod\fR to choose the frontier states for image computation +during traversal. Allowed methods are: \fInew\fR (default), \fIreached\fR, +\fIrestrict\fR, \fIcompact\fR, \fIsqueeze\fR, \fIsubset\fR, \fIsuperset\fR. +.TP 10 +.B \-groupnsps \fImethod\fB +use \fImethod\fR to group the corresponding current and next state +variables. Allowed methods are: \fInone\fR (default), \fIdefault\fR, +\fIfixed\fR. +.TP 10 +.B \-image \fImethod\fB +use \fImethod\fR for image computation during traversal. Allowed +methods are: \fImono\fR (default), \fIpart\fR, \fIdepend\fR, and +\fIclip\fR. +.TP 10 +.B \-depth \fIn\fB +use \fIn\fR to derive the clipping depth for image +computation. It should be a number between 0 and 1. The default value +is 1 (no clipping). +.TP 10 +.B \-verify \fIfile\fB +perform combinational verification checking for equivalence to +the network in \fIfile\fR. The two networks being compared must use +the same names for inputs, outputs, and present and next state +variables. The method used for verification is extremely +simplistic. BDDs are built for all outputs of both networks, and are +then compared. +.TP 10 +.B \-closure +perform reachability analysis using the transitive closure of the +transition relation. +.TP 10 +.B \-cdepth \fIn\fB +use \fIn\fR to derive the clipping depth for transitive closure +computation. It should be a number between 0 and 1. The default value +is 1 (no clipping). +.TP 10 +.B \-envelope +compute the greatest fixed point of the state transition +relation. (This greatest fixed point is also called the outer envelope +of the graph.) +.TP 10 +.B \-scc +compute the strongly connected components of the state transition +graph. The algorithm enumerates the SCCs; therefore it stops after a +small number of them has been computed. +.TP 10 +.B \-maxflow +compute the maximum flow in the network defined by the state graph. +.TP 10 +.B \-sink \fIfile\fB +read the sink for maximum flow computation from \fIfile\fR. The source +is given by the initial states. +.TP 10 +.B \-shortpaths \fImethod\fB +compute the distances between states. Allowed methods are: \fInone\fR +(default), \fIbellman\fR, \fIfloyd\fR, and \fIsquare\fR. +.TP 10 +.B \-selective +use selective tracing variant of the \fIsquare\fR method for shortest +paths. +.TP 10 +.B \-part +compute the conjunctive decomposition of the transition relation. The +network must be sequential for the test to take place. +.TP 10 +.B \-sign +compute signatures. For each output of the circuit, all inputs are +assigned a signature. The signature is the fraction of minterms in the +ON\-set of the positive cofactor of the output with respect to the +input. Signatures are useful in identifying the equivalence of circuits +with unknown input or output correspondence. +.TP 10 +.B \-zdd +perform a simple test of ZDD functions. This test is not executed if +-delta is also specified, because it uses the BDDs of the primary +outputs of the circuit. These are converted to ZDDs and the ZDDs are +then converted back to BDDs and checked against the original ones. A +few more functions are exercised and reordering is applied if it is +enabled. Then irredundant sums of products are produced for the +primary outputs. +.TP 10 +.B \-cover +print irredundant sums of products for the primary outputs. This +option implies \fB\-zdd\fR. +.TP 10 +.B \-second \fIfile\fB +read a second network from \fIfile\fR. Currently, if this option is +specified, a test of BDD minimization algorithms is performed using +the largest output of the second network as constraint. Inputs of the +two networks with the same names are merged. +.TP 10 +.B \-density +test BDD approximation functions. +.TP 10 +.B \-approx \fImethod\fB +if \fImethod\fR is \fIunder\fR (default) perform underapproximation +when BDDs are approximated. If \fImethod\fR is \fIover\fR perform +overapproximation when BDDs are approximated. +.TP 10 +.B \-threshold \fIn\fB +Use \fIn\fR as threshold when approximating BDDs. +.TP 10 +.B \-quality \fIn\fB +Use \fIn\fR (a floating point number) as quality factor when +approximating BDDs. Default value is 1. +.TP 10 +.B \-decomp +test BDD decomposition functions. +.TP 10 +.B \-cofest +test cofactor estimation functions. +.TP 10 +.B \-clip \fIn file\fB +test clipping functions using \fIn\fR to determine the clipping depth +and taking one operand from the network in \fIfile\fR. +.TP 10 +.B \-dctest \fIfile\fB +test functions for equality and containment under don't care +conditions taking the don't care conditions from \fIfile\fR. +.TP 10 +.B \-closest +test function that finds a cube in a BDD at minimum Hamming distance +from another BDD. +.TP 10 +.B \-clauses +test function that extracts two-literal clauses from a DD. +.TP 10 +.B \-char2vect +perform a simple test of the conversion from characteristic function +to functional vector. If the network is sequential, the test is +applied to the monolithic transition relation; otherwise to the primary +outputs. +.TP 10 +.B \-local +build local BDDs for each gate of the circuit. This option is not in +effect if traversal, outer envelope computation, or maximum flow +computation are requested. The local BDD of a gate is in terms of its +local inputs. +.TP 10 +.B \-cache \fIn\fB +set the initial size of the computed table to \fIn\fR. +.TP 10 +.B \-slots \fIn\fB +set the initial size of each unique subtable to \fIn\fR. +.TP 10 +.B \-maxmem \fIn\fB +set the target maximum memory occupation to \fIn\fR MB. If this +parameter is not specified or if \fIn\fR is 0, then a suitable value +is computed automatically. +.TP 10 +.B \-memhard \fIn\fB +set the hard limit to memory occupation to \fIn\fR MB. If this +parameter is not specified or if \fIn\fR is 0, no hard limit is +enforced by the program. +.TP 10 +.B \-maxlive \fIn\fB +set the hard limit to the number of live BDD nodes to \fIn\fR. If +this parameter is not specified, the limit is four billion nodes. +.TP 10 +.B \-dumpfile \fIfile\fB +dump BDDs to \fIfile\fR. The BDDs are dumped just before program +termination. (Hence, after reordering, if reordering is specified.) +.TP 10 +.B \-dumpblif +use blif format for dump of BDDs (default is dot format). If blif is +used, the BDDs are dumped as a network of multiplexers. The dot format +is suitable for input to the dot program, which produces a +drawing of the BDDs. +.TP 10 +.B \-dumpmv +use blif-MV format for dump of BDDs. The BDDs are dumped as a network +of multiplexers. +.TP 10 +.B \-dumpdaVinci +use daVinci format for dump of BDDs. +.TP 10 +.B \-dumpddcal +use DDcal format for dump of BDDs. This option may produce an invalid +output if the variable and output names of the BDDs being dumped do +not comply with the restrictions imposed by the DDcal format. +.TP 10 +.B \-dumpfact +use factored form format for dump of BDDs. This option must be used +with caution because the size of the output is proportional to the +number of paths in the BDD. +.TP 10 +.B \-storefile \fIfile\fB +Save the BDD of the reachable states to \fIfile\fR. The BDD is stored at +the iteration specified by \fB\-store\fR. This option uses the format of +the \fIdddmp\fR library. Together with \fB\-loadfile\fR, it implements a +primitive checkpointing capability. It is primitive because the transition +relation is not saved; because the frontier states are not saved; and +because only one check point can be specified. +.TP 10 +.B \-store \fIn\fB +Save the BDD of the reached states at iteration \fIn\fR. This option +requires \fB\-storefile\fR. +.TP 10 +.B \-loadfile \fIfile\fB +Load the BDD of the initial states from \fIfile\fR. This option uses the +format of the \fIdddmp\fR library. Together with \fB\-storefile\fR, it +implements a primitive checkpointing capability. +.TP 10 +.B \-nobuild +do not build the BDDs. Quit after determining the initial variable +order. +.TP 10 +.B \-drop +drop BDDs for intermediate nodes as soon as possible. If this option is +not specified, the BDDs for the intermediate nodes of the circuit are +dropped just before the final reordering. +.TP 10 +.B \-delta +build BDDs only for the next state functions of a sequential circuit. +.TP 10 +.B \-node +build BDD only for \fInode\fR. +.TP 10 +.B \-order \fIfile\fB +read the variable order from \fIfile\fR. This file must contain the +names of the inputs (and present state variables) in the desired order. +Names must be separated by white space or newlines. +.TP 10 +.B \-ordering \fImethod\fB +use \fImethod\fR to derive an initial variable order. \fImethod\fR can +be one of \fIhw\fR, \fIdfs\fR. Method \fIhw\fR uses the order in which the +inputs are listed in the circuit description. +.TP 10 +.B \-autodyn +enable dynamic reordering. By default, dynamic reordering is disabled. +If enabled, the default method is sifting. +.TP 10 +.B \-first \fIn\fB +do first dynamic reordering when the BDDs reach \fIn\fR nodes. +The default value is 4004. (Don't ask why.) +.TP 10 +.B \-countdead +include dead nodes in node count when deciding whether to reorder +dynamically. By default, only live nodes are counted. +.TP 10 +.B \-growth \fIn\fB +maximum percentage by which the BDDs may grow while sifting one +variable. The default value is 20. +.TP 10 +.B \-automethod \fImethod\fB +use \fImethod\fR for dynamic reordering of the BDDs. \fImethod\fR can +be one of none, random, pivot, sifting, converge, symm, cosymm, group, +cogroup, win2, win3, win4, win2conv, win3conv, win4conv, annealing, +genetic, exact. The default method is sifting. +.TP 10 +.B \-reordering \fImethod\fB +use \fImethod\fR for the final reordering of the BDDs. \fImethod\fR can +be one of none, random, pivot, sifting, converge, symm, cosymm, group, +cogroup, win2, win3, win4, win2conv, win3conv, win4conv, annealing, +genetic, exact. The default method is none. +.TP 10 +.B \-genetic +run the genetic algorithm after the final reordering (which in this case +is no longer final). This allows the genetic algorithm to have one good +solution generated by, say, sifting, in the initial population. +.TP 10 +.B \-groupcheck \fImethod\fB +use \fImethod\fR for the the creation of groups in group sifting. +\fImethod\fR can be one of nocheck, check5, check7. Method check5 uses +extended symmetry as aggregation criterion; group7, in addition, also +uses the second difference criterion. The default value is check7. +.TP 10 +.B \-arcviolation \fIn\fB +percentage of arcs that violate the symmetry condition in the aggregation +check of group sifting. Should be between 0 and 100. The default value is +10. A larger value causes more aggregation. +.TP 10 +.B \-symmviolation \fIn\fB +percentage of nodes that violate the symmetry condition in the aggregation +check of group sifting. Should be between 0 and 100. The default value is +10. A larger value causes more aggregation. +.TP 10 +.B \-recomb \fIn\fB +threshold used in the second difference criterion for aggregation. (Used +by check7.) The default value is 0. A larger value causes more +aggregation. It can be either positive or negative. +.TP 10 +.B \-tree \fIfile\fB +read the variable group tree from \fIfile\fR. The format of this file is +a sequence of triplets: \fIlb ub flag\fR. Each triplet describes a +group: \fIlb\fR is the lowest index of the group; \fIub\fR is the +highest index of the group; \fIflag\fR can be either D (default) or F +(fixed). Fixed groups are not reordered. +.TP 10 +.B \-genepop \fIn\fB +size of the population for genetic algorithm. By default, the size of +the population is 3 times the number of variables, with a maximum of 120. +.TP 10 +.B \-genexover \fIn\fB +number of crossovers at each generation for the genetic algorithm. By +default, the number of crossovers is 3 times the number of variables, +with a maximum of 50. +.TP 10 +.B \-seed \fIn\fB +random number generator seed for the genetic algorithm and the random +and pivot reordering methods. +.TP 10 +.B \-progress +report progress when building the BDDs for a network. This option +causes the name of each primary output or next state function to be +printed after its BDD is built. It does not take effect if local BDDs +are requested. +.TP 10 +.B -p \fIn\fB +verbosity level. If negative, the program is very quiet. Larger values cause +more information to be printed. +.SH SEE ALSO +The documentation for the CUDD package explains the various +reordering methods. + +The documentation for the MTR package provides details on the variable +groups. + +dot(1) +.SH REFERENCES +F. Somenzi, +"Efficient Manipulation of Decision Diagrams," +Software Tools for Technology Transfer, +vol. 3, no. 2, pp. 171-181, 2001. + +S. Panda, F. Somenzi, and B. F. Plessier, +"Symmetry Detection and Dynamic Variable Ordering of Decision Diagrams," +IEEE International Conference on Computer-Aided Design, +pp. 628-631, November 1994. + +S. Panda and F. Somenzi, +"Who Are the Variables in Your Neighborhood," +IEEE International Conference on Computer-Aided Design, +pp. 74-77, November 1995. + +G. D. Hachtel and F. Somenzi, +"A Symbolic Algorithm for Maximum Flow in 0-1 Networks," +IEEE International Conference on Computer-Aided Design, +pp. 403-406, November 1993. +.SH AUTHOR +Fabio Somenzi, University of Colorado at Boulder. diff --git a/distr/nanotrav/ntr.c b/distr/nanotrav/ntr.c new file mode 100644 index 0000000..f6b7ca1 --- /dev/null +++ b/distr/nanotrav/ntr.c @@ -0,0 +1,2988 @@ +/**CFile*********************************************************************** + + FileName [ntr.c] + + PackageName [ntr] + + Synopsis [A very simple reachability analysis program.] + + 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.] + +******************************************************************************/ + +#include "ntr.h" + +/*---------------------------------------------------------------------------*/ +/* Constant declarations */ +/*---------------------------------------------------------------------------*/ + +#define NTR_MAX_DEP_SIZE 20 + +/*---------------------------------------------------------------------------*/ +/* Stucture declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Type declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Variable declarations */ +/*---------------------------------------------------------------------------*/ + +#ifndef lint +static char rcsid[] UTIL_UNUSED = "$Id: ntr.c,v 1.27 2009/02/21 06:00:31 fabio Exp fabio $"; +#endif + +static const char *onames[] = { "T", "R" }; /* names of functions to be dumped */ +static double *signatures; /* signatures for all variables */ +static BnetNetwork *staticNet; /* pointer to network used by qsort + ** comparison function */ +static DdNode **staticPart; /* pointer to parts used by qsort + ** comparison function */ + +/*---------------------------------------------------------------------------*/ +/* Macro declarations */ +/*---------------------------------------------------------------------------*/ + +/**AutomaticStart*************************************************************/ + +/*---------------------------------------------------------------------------*/ +/* Static function prototypes */ +/*---------------------------------------------------------------------------*/ + +static DdNode * makecube (DdManager *dd, DdNode **x, int n); +static void ntrInitializeCount (BnetNetwork *net, NtrOptions *option); +static void ntrCountDFS (BnetNetwork *net, BnetNode *node); +static DdNode * ntrImage (DdManager *dd, NtrPartTR *TR, DdNode *from, NtrOptions *option); +static DdNode * ntrPreimage (DdManager *dd, NtrPartTR *T, DdNode *from); +static DdNode * ntrChooseFrom (DdManager *dd, DdNode *neW, DdNode *reached, NtrOptions *option); +static DdNode * ntrUpdateReached (DdManager *dd, DdNode *oldreached, DdNode *to); +static int ntrLatchDependencies (DdManager *dd, DdNode *reached, BnetNetwork *net, NtrOptions *option); +static NtrPartTR * ntrEliminateDependencies (DdManager *dd, NtrPartTR *TR, DdNode **states, NtrOptions *option); +static int ntrUpdateQuantificationSchedule (DdManager *dd, NtrPartTR *T); +static int ntrSignatureCompare (int * ptrX, int * ptrY); +static int ntrSignatureCompare2 (int * ptrX, int * ptrY); +static int ntrPartCompare (int * ptrX, int * ptrY); +static char ** ntrAllocMatrix (int nrows, int ncols); +static void ntrFreeMatrix (char **matrix); +static void ntrPermuteParts (DdNode **a, DdNode **b, int *comesFrom, int *goesTo, int size); + +/**AutomaticEnd***************************************************************/ + +/*---------------------------------------------------------------------------*/ +/* Definition of exported functions */ +/*---------------------------------------------------------------------------*/ + + +/**Function******************************************************************** + + Synopsis [Builds DDs for a network outputs and next state + functions.] + + Description [Builds DDs for a network outputs and next state + functions. The method is really brain-dead, but it is very simple. + Returns 1 in case of success; 0 otherwise. Some inputs to the network + may be shared with another network whose DDs have already been built. + In this case we want to share the DDs as well.] + + SideEffects [the dd fields of the network nodes are modified. Uses the + count fields of the nodes.] + + SeeAlso [] + +******************************************************************************/ +int +Ntr_buildDDs( + BnetNetwork * net /* network for which DDs are to be built */, + DdManager * dd /* DD manager */, + NtrOptions * option /* option structure */, + BnetNetwork * net2 /* companion network with which inputs may be shared */) +{ + int pr = option->verb; + int result; + int i; + BnetNode *node, *node2; + + /* If some inputs or present state variables are shared with + ** another network, we initialize their BDDs from that network. + */ + if (net2 != NULL) { + for (i = 0; i < net->npis; i++) { + if (!st_lookup(net->hash,net->inputs[i],&node)) { + return(0); + } + if (!st_lookup(net2->hash,net->inputs[i],&node2)) { + /* This input is not shared. */ + result = Bnet_BuildNodeBDD(dd,node,net->hash, + option->locGlob,option->nodrop); + if (result == 0) return(0); + } else { + if (node2->dd == NULL) return(0); + node->dd = node2->dd; + Cudd_Ref(node->dd); + node->var = node2->var; + node->active = node2->active; + } + } + for (i = 0; i < net->nlatches; i++) { + if (!st_lookup(net->hash,net->latches[i][1],&node)) { + return(0); + } + if (!st_lookup(net2->hash,net->latches[i][1],&node2)) { + /* This present state variable is not shared. */ + result = Bnet_BuildNodeBDD(dd,node,net->hash, + option->locGlob,option->nodrop); + if (result == 0) return(0); + } else { + if (node2->dd == NULL) return(0); + node->dd = node2->dd; + Cudd_Ref(node->dd); + node->var = node2->var; + node->active = node2->active; + } + } + } else { + /* First assign variables to inputs if the order is provided. + ** (Either in the .blif file or in an order file.) + */ + if (option->ordering == PI_PS_FROM_FILE) { + /* Follow order given in input file. First primary inputs + ** and then present state variables. + */ + for (i = 0; i < net->npis; i++) { + if (!st_lookup(net->hash,net->inputs[i],&node)) { + return(0); + } + result = Bnet_BuildNodeBDD(dd,node,net->hash, + option->locGlob,option->nodrop); + if (result == 0) return(0); + } + for (i = 0; i < net->nlatches; i++) { + if (!st_lookup(net->hash,net->latches[i][1],&node)) { + return(0); + } + result = Bnet_BuildNodeBDD(dd,node,net->hash, + option->locGlob,option->nodrop); + if (result == 0) return(0); + } + } else if (option->ordering == PI_PS_GIVEN) { + result = Bnet_ReadOrder(dd,option->orderPiPs,net,option->locGlob, + option->nodrop); + if (result == 0) return(0); + } else { + result = Bnet_DfsVariableOrder(dd,net); + if (result == 0) return(0); + } + } + /* At this point the BDDs of all primary inputs and present state + ** variables have been built. */ + + /* Currently noBuild doesn't do much. */ + if (option->noBuild == TRUE) + return(1); + + if (option->locGlob == BNET_LOCAL_DD) { + node = net->nodes; + while (node != NULL) { + result = Bnet_BuildNodeBDD(dd,node,net->hash,BNET_LOCAL_DD,TRUE); + if (result == 0) { + return(0); + } + if (pr > 2) { + (void) fprintf(stdout,"%s",node->name); + Cudd_PrintDebug(dd,node->dd,Cudd_ReadSize(dd),pr); + } + node = node->next; + } + } else { /* option->locGlob == BNET_GLOBAL_DD */ + /* Create BDDs with DFS from the primary outputs and the next + ** state functions. If the inputs had not been ordered yet, + ** this would result in a DFS order for the variables. + */ + + ntrInitializeCount(net,option); + + if (option->node != NULL && + option->closestCube == FALSE && option->dontcares == FALSE) { + if (!st_lookup(net->hash,option->node,&node)) { + return(0); + } + result = Bnet_BuildNodeBDD(dd,node,net->hash,BNET_GLOBAL_DD, + option->nodrop); + if (result == 0) return(0); + } else { + if (option->stateOnly == FALSE) { + for (i = 0; i < net->npos; i++) { + if (!st_lookup(net->hash,net->outputs[i],&node)) { + continue; + } + result = Bnet_BuildNodeBDD(dd,node,net->hash, + BNET_GLOBAL_DD,option->nodrop); + if (result == 0) return(0); + if (option->progress) { + (void) fprintf(stdout,"%s\n",node->name); + } +#if 0 + Cudd_PrintDebug(dd,node->dd,net->ninputs,option->verb); +#endif + } + } + for (i = 0; i < net->nlatches; i++) { + if (!st_lookup(net->hash,net->latches[i][0],&node)) { + continue; + } + result = Bnet_BuildNodeBDD(dd,node,net->hash,BNET_GLOBAL_DD, + option->nodrop); + if (result == 0) return(0); + if (option->progress) { + (void) fprintf(stdout,"%s\n",node->name); + } +#if 0 + Cudd_PrintDebug(dd,node->dd,net->ninputs,option->verb); +#endif + } + } + /* Make sure all inputs have a DD and dereference the DDs of + ** the nodes that are not reachable from the outputs. + */ + for (i = 0; i < net->npis; i++) { + if (!st_lookup(net->hash,net->inputs[i],&node)) { + return(0); + } + result = Bnet_BuildNodeBDD(dd,node,net->hash,BNET_GLOBAL_DD, + option->nodrop); + if (result == 0) return(0); + if (node->count == -1) Cudd_RecursiveDeref(dd,node->dd); + } + for (i = 0; i < net->nlatches; i++) { + if (!st_lookup(net->hash,net->latches[i][1],&node)) { + return(0); + } + result = Bnet_BuildNodeBDD(dd,node,net->hash,BNET_GLOBAL_DD, + option->nodrop); + if (result == 0) return(0); + if (node->count == -1) Cudd_RecursiveDeref(dd,node->dd); + } + + /* Dispose of the BDDs of the internal nodes if they have not + ** been dropped already. + */ + if (option->nodrop == TRUE) { + for (node = net->nodes; node != NULL; node = node->next) { + if (node->dd != NULL && node->count != -1 && + (node->type == BNET_INTERNAL_NODE || + node->type == BNET_INPUT_NODE || + node->type == BNET_PRESENT_STATE_NODE)) { + Cudd_RecursiveDeref(dd,node->dd); + if (node->type == BNET_INTERNAL_NODE) node->dd = NULL; + } + } + } + } + + return(1); + +} /* end of buildDD */ + + +/**Function******************************************************************** + + Synopsis [Builds the transition relation for a network.] + + Description [Builds the transition relation for a network. Returns a + pointer to the transition relation structure if successful; NULL + otherwise.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +NtrPartTR * +Ntr_buildTR( + DdManager * dd /* manager */, + BnetNetwork * net /* network */, + NtrOptions * option /* options */, + int image /* image type: monolithic ... */) +{ + NtrPartTR *TR; + DdNode *T, *delta, *support, *scan, *tmp, *preiabs, *prepabs; + DdNode **part, **absicubes, **abspcubes, **nscube, *mnscube; + DdNode **x, **y; + DdNode **pi; + int i; + int xlevel; + BnetNode *node; + int *schedule; + int depth = 0; + + /* Initialize transition relation structure. */ + TR = ALLOC(NtrPartTR,1); + if (TR == NULL) goto endgame; + TR->nlatches = net->nlatches; + if (image == NTR_IMAGE_MONO) { + TR->nparts = 1; + } else if (image == NTR_IMAGE_PART || image == NTR_IMAGE_CLIP || + image == NTR_IMAGE_DEPEND) { + TR->nparts = net->nlatches; + } else { + (void) fprintf(stderr,"Unrecognized image method (%d). Using part.\n", + image); + TR->nparts = net->nlatches; + } + TR->factors = Ntr_InitHeap(TR->nlatches); + if (TR->factors == NULL) goto endgame; + /* Allocate arrays for present state and next state variables. */ + TR->x = x = ALLOC(DdNode *,TR->nlatches); + if (x == NULL) goto endgame; + TR->y = y = ALLOC(DdNode *,TR->nlatches); + if (y == NULL) goto endgame; + /* Allocate array for primary input variables. */ + pi = ALLOC(DdNode *,net->npis); + if (pi == NULL) goto endgame; + /* Allocate array for partitioned transition relation. */ + part = ALLOC(DdNode *,net->nlatches); + if (part == NULL) goto endgame; + /* Allocate array of next state cubes. */ + nscube = ALLOC(DdNode *,net->nlatches); + if (nscube == NULL) goto endgame; + /* Allocate array for quantification schedule and initialize it. */ + schedule = ALLOC(int,Cudd_ReadSize(dd)); + if (schedule == NULL) goto endgame; + for (i = 0; i < Cudd_ReadSize(dd); i++) { + schedule[i] = -1; + } + + /* Create partitioned transition relation from network. */ + TR->xw = Cudd_ReadOne(dd); + Cudd_Ref(TR->xw); + for (i = 0; i < net->nlatches; i++) { + if (!st_lookup(net->hash,net->latches[i][1],&node)) { + goto endgame; + } + x[i] = node->dd; + Cudd_Ref(x[i]); + /* Add present state variable to cube TR->xw. */ + tmp = Cudd_bddAnd(dd,TR->xw,x[i]); + if (tmp == NULL) return(NULL); Cudd_Ref(tmp); + Cudd_RecursiveDeref(dd,TR->xw); + TR->xw = tmp; + /* Create new y variable immediately above the x variable. */ + xlevel = Cudd_ReadPerm(dd,x[i]->index); + y[i] = Cudd_bddNewVarAtLevel(dd,xlevel); + Cudd_Ref(y[i]); + /* Initialize cube of next state variables for this part. */ + nscube[i] = y[i]; + Cudd_Ref(nscube[i]); + /* Group present and next state variable if so requested. */ + if (option->groupnsps != NTR_GROUP_NONE) { + int method = option->groupnsps == NTR_GROUP_DEFAULT ? + MTR_DEFAULT : MTR_FIXED; + if (Cudd_MakeTreeNode(dd,y[i]->index,2,method) == NULL) + goto endgame; + } + /* Get next state function and create transition relation part. */ + if (!st_lookup(net->hash,net->latches[i][0],&node)) { + goto endgame; + } + delta = node->dd; + if (image != NTR_IMAGE_DEPEND) { + part[i] = Cudd_bddXnor(dd,delta,y[i]); + if (part[i] == NULL) goto endgame; + } else { + part[i] = delta; + } + Cudd_Ref(part[i]); + /* Collect scheduling info for this delta. At the end of this loop + ** schedule[i] == j means that the variable of index i does not + ** appear in any part with index greater than j, unless j == -1, + ** in which case the variable appears in no part. + */ + support = Cudd_Support(dd,delta); + Cudd_Ref(support); + scan = support; + while (!Cudd_IsConstant(scan)) { + schedule[scan->index] = i; + scan = Cudd_T(scan); + } + Cudd_RecursiveDeref(dd,support); + } + + /* Collect primary inputs. */ + for (i = 0; i < net->npis; i++) { + if (!st_lookup(net->hash,net->inputs[i],&node)) { + goto endgame; + } + pi[i] = node->dd; + tmp = Cudd_bddAnd(dd,TR->xw,pi[i]); + if (tmp == NULL) goto endgame; Cudd_Ref(tmp); + Cudd_RecursiveDeref(dd,TR->xw); + TR->xw = tmp; + } + + /* Build abstraction cubes. First primary input variables that go + ** in the abstraction cubes for both monolithic and partitioned + ** transition relations. */ + absicubes = ALLOC(DdNode *, net->nlatches); + if (absicubes == NULL) goto endgame; + abspcubes = ALLOC(DdNode *, net->nlatches); + if (abspcubes == NULL) goto endgame; + + for (i = 0; i < net->nlatches; i++) { + absicubes[i] = Cudd_ReadOne(dd); + Cudd_Ref(absicubes[i]); + } + preiabs = Cudd_ReadOne(dd); + Cudd_Ref(preiabs); + + for (i = 0; i < net->npis; i++) { + int j = pi[i]->index; + int k = schedule[j]; + if (k >= 0) { + tmp = Cudd_bddAnd(dd,absicubes[k],pi[i]); + if (tmp == NULL) return(NULL); Cudd_Ref(tmp); + Cudd_RecursiveDeref(dd,absicubes[k]); + absicubes[k] = tmp; + } else { + tmp = Cudd_bddAnd(dd,preiabs,pi[i]); + if (tmp == NULL) return(NULL); Cudd_Ref(tmp); + Cudd_RecursiveDeref(dd,preiabs); + preiabs = tmp; + } + } + FREE(pi); + + /* Build preimage abstraction cubes from image abstraction cubes. */ + for (i = 0; i < net->nlatches; i++) { + abspcubes[i] = Cudd_bddAnd(dd,absicubes[i],nscube[i]); + if (abspcubes[i] == NULL) return(NULL); + Cudd_Ref(abspcubes[i]); + } + Cudd_Ref(prepabs = preiabs); + + /* For partitioned transition relations we add present state variables + ** to the image abstraction cubes. */ + if (image != NTR_IMAGE_MONO) { + for (i = 0; i < net->nlatches; i++) { + int j = x[i]->index; + int k = schedule[j]; + if (k >= 0) { + tmp = Cudd_bddAnd(dd,absicubes[k],x[i]); + if (tmp == NULL) return(NULL); Cudd_Ref(tmp); + Cudd_RecursiveDeref(dd,absicubes[k]); + absicubes[k] = tmp; + } else { + tmp = Cudd_bddAnd(dd,preiabs,x[i]); + if (tmp == NULL) return(NULL); Cudd_Ref(tmp); + Cudd_RecursiveDeref(dd,preiabs); + preiabs = tmp; + } + } + } + FREE(schedule); + + if (image != NTR_IMAGE_MONO) { + TR->part = part; + TR->icube = absicubes; + TR->pcube = abspcubes; + TR->nscube = nscube; + TR->preiabs = preiabs; + TR->prepabs = prepabs; + return(TR); + } + + /* Here we are building a monolithic TR. */ + + /* Reinitialize the cube of variables to be quantified before + ** image computation. */ + Cudd_RecursiveDeref(dd,preiabs); + preiabs = Cudd_ReadOne(dd); + Cudd_Ref(preiabs); + + if (option->imageClip != 1.0) { + depth = (int) ((double) Cudd_ReadSize(dd) * option->imageClip); + } + + /* Collapse transition relation. */ + T = Cudd_ReadOne(dd); + Cudd_Ref(T); + mnscube = Cudd_ReadOne(dd); + Cudd_Ref(mnscube); + for (i = 0; i < net->nlatches; i++) { + /* Eliminate the primary inputs that do not appear in other parts. */ + if (depth != 0) { + tmp = Cudd_bddClippingAndAbstract(dd,T,part[i],absicubes[i], + depth,option->approx); + } else { + tmp = Cudd_bddAndAbstract(dd,T,part[i],absicubes[i]); + } + Cudd_Ref(tmp); + Cudd_RecursiveDeref(dd,T); + Cudd_RecursiveDeref(dd,part[i]); + Cudd_RecursiveDeref(dd,absicubes[i]); + Cudd_RecursiveDeref(dd,abspcubes[i]); + if (option->threshold >= 0) { + if (option->approx) { + T = Cudd_RemapOverApprox(dd,tmp,2*net->nlatches, + option->threshold,option->quality); + } else { + T = Cudd_RemapUnderApprox(dd,tmp,2*net->nlatches, + option->threshold,option->quality); + } + } else { + T = tmp; + } + if (T == NULL) return(NULL); + Cudd_Ref(T); + Cudd_RecursiveDeref(dd,tmp); + /* Add the next state variables of this part to the cube of all + ** next state variables. */ + tmp = Cudd_bddAnd(dd,mnscube,nscube[i]); + if (tmp == NULL) return(NULL); + Cudd_Ref(tmp); + Cudd_RecursiveDeref(dd,mnscube); + mnscube = tmp; + Cudd_RecursiveDeref(dd,nscube[i]); + (void) printf("@"); fflush(stdout); + } + (void) printf("\n"); +#if 0 + (void) printf("T"); Cudd_PrintDebug(dd,T,2*net->nlatches,2); +#endif + + /* Clean up. */ + FREE(absicubes); + FREE(abspcubes); + FREE(part); + FREE(nscube); + + TR->part = part = ALLOC(DdNode *,1); + if (part == NULL) goto endgame; + part[0] = T; + + /* Build cube of x (present state) variables for abstraction. */ + TR->icube = absicubes = ALLOC(DdNode *,1); + if (absicubes == NULL) goto endgame; + absicubes[0] = makecube(dd,x,TR->nlatches); + if (absicubes[0] == NULL) return(0); + Cudd_Ref(absicubes[0]); + /* Build cube of y (next state) variables for abstraction. */ + TR->pcube = abspcubes = ALLOC(DdNode *,1); + if (abspcubes == NULL) goto endgame; + abspcubes[0] = makecube(dd,y,TR->nlatches); + if (abspcubes[0] == NULL) return(0); + Cudd_Ref(abspcubes[0]); + TR->preiabs = preiabs; + TR->prepabs = prepabs; + + TR->nscube = ALLOC(DdNode *,1); + if (TR->nscube == NULL) return(NULL); + TR->nscube[0] = mnscube; + + return(TR); + +endgame: + + return(NULL); + +} /* end of Ntr_buildTR */ + + +/**Function******************************************************************** + + Synopsis [Frees the transition relation for a network.] + + Description [] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +void +Ntr_freeTR( + DdManager * dd, + NtrPartTR * TR) +{ + int i; + for (i = 0; i < TR->nlatches; i++) { + Cudd_RecursiveDeref(dd,TR->x[i]); + Cudd_RecursiveDeref(dd,TR->y[i]); + } + FREE(TR->x); + FREE(TR->y); + for (i = 0; i < TR->nparts; i++) { + Cudd_RecursiveDeref(dd,TR->part[i]); + Cudd_RecursiveDeref(dd,TR->icube[i]); + Cudd_RecursiveDeref(dd,TR->pcube[i]); + Cudd_RecursiveDeref(dd,TR->nscube[i]); + } + FREE(TR->part); + FREE(TR->icube); + FREE(TR->pcube); + FREE(TR->nscube); + Cudd_RecursiveDeref(dd,TR->preiabs); + Cudd_RecursiveDeref(dd,TR->prepabs); + Cudd_RecursiveDeref(dd,TR->xw); + for (i = 0; i < TR->factors->nslots; i++) { + Cudd_RecursiveDeref(dd, (DdNode *) TR->factors->slots[i].item); + } + Ntr_FreeHeap(TR->factors); + FREE(TR); + + return; + +} /* end of Ntr_freeTR */ + + +/**Function******************************************************************** + + Synopsis [Makes a copy of a transition relation.] + + Description [Makes a copy of a transition relation. Returns a pointer + to the copy if successful; NULL otherwise.] + + SideEffects [None] + + SeeAlso [Ntr_buildTR Ntr_freeTR] + +******************************************************************************/ +NtrPartTR * +Ntr_cloneTR( + NtrPartTR *TR) +{ + NtrPartTR *T; + int nparts, nlatches, i; + + T = ALLOC(NtrPartTR,1); + if (T == NULL) return(NULL); + nparts = T->nparts = TR->nparts; + nlatches = T->nlatches = TR->nlatches; + T->part = ALLOC(DdNode *,nparts); + if (T->part == NULL) { + FREE(T); + return(NULL); + } + T->icube = ALLOC(DdNode *,nparts); + if (T->icube == NULL) { + FREE(T->part); + FREE(T); + return(NULL); + } + T->pcube = ALLOC(DdNode *,nparts); + if (T->pcube == NULL) { + FREE(T->icube); + FREE(T->part); + FREE(T); + return(NULL); + } + T->x = ALLOC(DdNode *,nlatches); + if (T->x == NULL) { + FREE(T->pcube); + FREE(T->icube); + FREE(T->part); + FREE(T); + return(NULL); + } + T->y = ALLOC(DdNode *,nlatches); + if (T->y == NULL) { + FREE(T->x); + FREE(T->pcube); + FREE(T->icube); + FREE(T->part); + FREE(T); + return(NULL); + } + T->nscube = ALLOC(DdNode *,nparts); + if (T->nscube == NULL) { + FREE(T->y); + FREE(T->x); + FREE(T->pcube); + FREE(T->icube); + FREE(T->part); + FREE(T); + return(NULL); + } + T->factors = Ntr_HeapClone(TR->factors); + if (T->factors == NULL) { + FREE(T->nscube); + FREE(T->y); + FREE(T->x); + FREE(T->pcube); + FREE(T->icube); + FREE(T->part); + FREE(T); + return(NULL); + } + for (i = 0; i < T->factors->nslots; i++) { + Cudd_Ref((DdNode *) T->factors->slots[i].item); + } + for (i = 0; i < nparts; i++) { + T->part[i] = TR->part[i]; + Cudd_Ref(T->part[i]); + T->icube[i] = TR->icube[i]; + Cudd_Ref(T->icube[i]); + T->pcube[i] = TR->pcube[i]; + Cudd_Ref(T->pcube[i]); + T->nscube[i] = TR->nscube[i]; + Cudd_Ref(T->nscube[i]); + } + T->preiabs = TR->preiabs; + Cudd_Ref(T->preiabs); + T->prepabs = TR->prepabs; + Cudd_Ref(T->prepabs); + T->xw = TR->xw; + Cudd_Ref(T->xw); + for (i = 0; i < nlatches; i++) { + T->x[i] = TR->x[i]; + Cudd_Ref(T->x[i]); + T->y[i] = TR->y[i]; + Cudd_Ref(T->y[i]); + } + + return(T); + +} /* end of Ntr_cloneTR */ + + +/**Function******************************************************************** + + Synopsis [Poor man's traversal procedure.] + + Description [Poor man's traversal procedure. based on the monolithic + transition relation. Returns 1 in case of success; 0 otherwise.] + + SideEffects [None] + + SeeAlso [Ntr_ClosureTrav] + +******************************************************************************/ +int +Ntr_Trav( + DdManager * dd /* DD manager */, + BnetNetwork * net /* network */, + NtrOptions * option /* options */) +{ + NtrPartTR *TR; /* Transition relation */ + DdNode *init; /* initial state(s) */ + DdNode *from; + DdNode *to; + DdNode *reached; + DdNode *neW; + DdNode *one, *zero; + int depth; + int retval; + int pr = option->verb; + int initReord = Cudd_ReadReorderings(dd); + + if (option->traverse == FALSE || net->nlatches == 0) return(1); + (void) printf("Building transition relation. Time = %s\n", + util_print_time(util_cpu_time() - option->initialTime)); + one = Cudd_ReadOne(dd); + zero = Cudd_Not(one); + + /* Build transition relation and initial states. */ + TR = Ntr_buildTR(dd,net,option,option->image); + if (TR == NULL) return(0); + retval = Cudd_SetVarMap(dd,TR->x,TR->y,TR->nlatches); + (void) printf("Transition relation: %d parts %d latches %d nodes\n", + TR->nparts, TR->nlatches, + Cudd_SharingSize(TR->part, TR->nparts)); + (void) printf("Traversing. Time = %s\n", + util_print_time(util_cpu_time() - option->initialTime)); + init = Ntr_initState(dd,net,option); + if (init == NULL) return(0); + + /* Initialize From. */ + Cudd_Ref(from = init); + (void) printf("S0"); Cudd_PrintDebug(dd,from,TR->nlatches,pr); + + /* Initialize Reached. */ + Cudd_Ref(reached = from); + + /* Start traversal. */ + for (depth = 0; ; depth++) { + /* Image computation. */ + to = ntrImage(dd,TR,from,option); + if (to == NULL) { + Cudd_RecursiveDeref(dd,reached); + Cudd_RecursiveDeref(dd,from); + return(0); + } + Cudd_RecursiveDeref(dd,from); + + /* Find new states. */ + neW = Cudd_bddAnd(dd,to,Cudd_Not(reached)); + if (neW == NULL) { + Cudd_RecursiveDeref(dd,reached); + Cudd_RecursiveDeref(dd,to); + return(0); + } + Cudd_Ref(neW); + Cudd_RecursiveDeref(dd,to); + + /* Check for convergence. */ + if (neW == zero) break; + + /* Dump current reached states if requested. */ + if (option->store == depth) { + int ok = Dddmp_cuddBddStore(dd, NULL, reached, NULL, + NULL, DDDMP_MODE_TEXT, DDDMP_VARIDS, + option->storefile, NULL); + if (ok == 0) return(0); + (void) printf("Storing reached in %s after %i iterations.\n", + option->storefile, depth); + break; + } + + /* Update reached. */ + reached = ntrUpdateReached(dd,reached,neW); + if (reached == NULL) { + Cudd_RecursiveDeref(dd,neW); + return(0); + } + + /* Prepare for new iteration. */ + from = ntrChooseFrom(dd,neW,reached,option); + if (from == NULL) { + Cudd_RecursiveDeref(dd,reached); + Cudd_RecursiveDeref(dd,neW); + return(0); + } + Cudd_RecursiveDeref(dd,neW); + (void) printf("From[%d]",depth+1); + Cudd_PrintDebug(dd,from,TR->nlatches,pr); + (void) printf("Reached[%d]",depth+1); + Cudd_PrintDebug(dd,reached,TR->nlatches,pr); + if (pr > 0) { + if (!Cudd_ApaPrintMinterm(stdout, dd, reached, TR->nlatches)) + return(0); + if (!Cudd_ApaPrintMintermExp(stdout, dd, reached, TR->nlatches, 6)) + return(0); + } else { + (void) printf("\n"); + } + } + + /* Print out result. */ + (void) printf("depth = %d\n", depth); + (void) printf("R"); Cudd_PrintDebug(dd,reached,TR->nlatches,pr); + + /* Dump to file if requested. */ + if (option->bdddump) { + DdNode *dfunc[2]; /* addresses of the functions to be dumped */ + char *onames[2]; /* names of the functions to be dumped */ + dfunc[0] = TR->part[0]; onames[0] = (char *) "T"; + dfunc[1] = reached; onames[1] = (char *) "R"; + retval = Bnet_bddArrayDump(dd, net, option->dumpfile, dfunc, + onames, 2, option->dumpFmt); + if (retval == 0) return(0); + } + + if (option->depend) { + retval = ntrLatchDependencies(dd, reached, net, option); + if (retval == -1) return(0); + (void) printf("%d latches are redundant\n", retval); + } + /* Clean up. */ + Cudd_RecursiveDeref(dd,reached); + Cudd_RecursiveDeref(dd,neW); + Cudd_RecursiveDeref(dd,init); + Ntr_freeTR(dd,TR); + + if (Cudd_ReadReorderings(dd) > initReord) { + (void) printf("Order at the end of reachability analysis\n"); + retval = Bnet_PrintOrder(net,dd); + if (retval == 0) return(0); + } + return(1); + +} /* end of Ntr_Trav */ + + +/**Function******************************************************************** + + Synopsis [Computes the SCCs of the STG.] + + Description [Computes the strongly connected components of the state + transition graph. Only the first 10 SCCs are computed. Returns 1 in + case of success; 0 otherwise.] + + SideEffects [None] + + SeeAlso [Ntr_Trav] + +******************************************************************************/ +int +Ntr_SCC( + DdManager * dd /* DD manager */, + BnetNetwork * net /* network */, + NtrOptions * option /* options */) +{ + NtrPartTR *TR; /* Transition relation */ + DdNode *init; /* initial state(s) */ + DdNode *from; + DdNode *to; + DdNode *reached, *reaching; + DdNode *neW; + DdNode *one, *zero; + DdNode *states, *scc; + DdNode *tmp; + DdNode *SCCs[10]; + int depth; + int nscc = 0; + int retval; + int pr = option->verb; + int i; + + if (option->scc == FALSE || net->nlatches == 0) return(1); + (void) printf("Building transition relation. Time = %s\n", + util_print_time(util_cpu_time() - option->initialTime)); + one = Cudd_ReadOne(dd); + zero = Cudd_Not(one); + + /* Build transition relation and initial states. */ + TR = Ntr_buildTR(dd,net,option,option->image); + if (TR == NULL) return(0); + retval = Cudd_SetVarMap(dd,TR->x,TR->y,TR->nlatches); + (void) printf("Transition relation: %d parts %d latches %d nodes\n", + TR->nparts, TR->nlatches, + Cudd_SharingSize(TR->part, TR->nparts)); + (void) printf("Computing SCCs. Time = %s\n", + util_print_time(util_cpu_time() - option->initialTime)); + + /* Consider all SCCs, including those not reachable. */ + states = one; + Cudd_Ref(states); + + while (states != zero) { + if (nscc == 0) { + tmp = Ntr_initState(dd,net,option); + if (tmp == NULL) return(0); + init = Cudd_bddPickOneMinterm(dd,tmp,TR->x,TR->nlatches); + } else { + init = Cudd_bddPickOneMinterm(dd,states,TR->x,TR->nlatches); + } + if (init == NULL) return(0); + Cudd_Ref(init); + if (nscc == 0) { + Cudd_RecursiveDeref(dd,tmp); + } + /* Initialize From. */ + Cudd_Ref(from = init); + (void) printf("S0"); Cudd_PrintDebug(dd,from,TR->nlatches,pr); + + /* Initialize Reached. */ + Cudd_Ref(reached = from); + + /* Start forward traversal. */ + for (depth = 0; ; depth++) { + /* Image computation. */ + to = ntrImage(dd,TR,from,option); + if (to == NULL) { + return(0); + } + Cudd_RecursiveDeref(dd,from); + + /* Find new states. */ + tmp = Cudd_bddAnd(dd,to,states); + if (tmp == NULL) return(0); Cudd_Ref(tmp); + Cudd_RecursiveDeref(dd,to); + neW = Cudd_bddAnd(dd,tmp,Cudd_Not(reached)); + if (neW == NULL) return(0); Cudd_Ref(neW); + Cudd_RecursiveDeref(dd,tmp); + + /* Check for convergence. */ + if (neW == zero) break; + + /* Update reached. */ + reached = ntrUpdateReached(dd,reached,neW); + if (reached == NULL) { + return(0); + } + + /* Prepare for new iteration. */ + from = ntrChooseFrom(dd,neW,reached,option); + if (from == NULL) { + return(0); + } + Cudd_RecursiveDeref(dd,neW); + (void) printf("From[%d]",depth+1); + Cudd_PrintDebug(dd,from,TR->nlatches,pr); + (void) printf("Reached[%d]",depth+1); + Cudd_PrintDebug(dd,reached,TR->nlatches,pr); + if (pr <= 0) { + (void) printf("\n"); + } + } + Cudd_RecursiveDeref(dd,neW); + + /* Express reached in terms of y variables. This allows us to + ** efficiently test for termination during the backward traversal. */ + tmp = Cudd_bddVarMap(dd,reached); + if (tmp == NULL) return(0); + Cudd_Ref(tmp); + Cudd_RecursiveDeref(dd,reached); + reached = tmp; + + /* Initialize from and reaching. */ + from = Cudd_bddVarMap(dd,init); + Cudd_Ref(from); + (void) printf("S0"); Cudd_PrintDebug(dd,from,TR->nlatches,pr); + Cudd_Ref(reaching = from); + + /* Start backward traversal. */ + for (depth = 0; ; depth++) { + /* Preimage computation. */ + to = ntrPreimage(dd,TR,from); + if (to == NULL) { + return(0); + } + Cudd_RecursiveDeref(dd,from); + + /* Find new states. */ + tmp = Cudd_bddAnd(dd,to,reached); + if (tmp == NULL) return(0); Cudd_Ref(tmp); + Cudd_RecursiveDeref(dd,to); + neW = Cudd_bddAnd(dd,tmp,Cudd_Not(reaching)); + if (neW == NULL) return(0); Cudd_Ref(neW); + Cudd_RecursiveDeref(dd,tmp); + + /* Check for convergence. */ + if (neW == zero) break; + + /* Update reaching. */ + reaching = ntrUpdateReached(dd,reaching,neW); + if (reaching == NULL) { + return(0); + } + + /* Prepare for new iteration. */ + from = ntrChooseFrom(dd,neW,reaching,option); + if (from == NULL) { + return(0); + } + Cudd_RecursiveDeref(dd,neW); + (void) printf("From[%d]",depth+1); + Cudd_PrintDebug(dd,from,TR->nlatches,pr); + (void) printf("Reaching[%d]",depth+1); + Cudd_PrintDebug(dd,reaching,TR->nlatches,pr); + if (pr <= 0) { + (void) printf("\n"); + } + } + + scc = Cudd_bddAnd(dd,reached,reaching); + if (scc == NULL) { + return(0); + } + Cudd_Ref(scc); + SCCs[nscc] = Cudd_bddVarMap(dd,scc); + if (SCCs[nscc] == NULL) return(0); + Cudd_Ref(SCCs[nscc]); + Cudd_RecursiveDeref(dd,scc); + /* Print out result. */ + (void) printf("SCC[%d]",nscc); + Cudd_PrintDebug(dd,SCCs[nscc],TR->nlatches,pr); + tmp = Cudd_bddAnd(dd,states,Cudd_Not(SCCs[nscc])); + if (tmp == NULL) { + return(0); + } + Cudd_Ref(tmp); + Cudd_RecursiveDeref(dd,states); + states = tmp; + Cudd_RecursiveDeref(dd,reached); + Cudd_RecursiveDeref(dd,reaching); + Cudd_RecursiveDeref(dd,neW); + Cudd_RecursiveDeref(dd,init); + nscc++; + if (nscc > 9) break; + } + + if (states != zero) { + (void) fprintf(stdout,"More than 10 SCCs. Only the first 10 are computed.\n"); + } + + /* Dump to file if requested. */ + if (option->bdddump) { + char *sccnames[10]; /* names of the SCCs */ + sccnames[0] = (char *) "SCC0"; + sccnames[1] = (char *) "SCC1"; + sccnames[2] = (char *) "SCC2"; + sccnames[3] = (char *) "SCC3"; + sccnames[4] = (char *) "SCC4"; + sccnames[5] = (char *) "SCC5"; + sccnames[6] = (char *) "SCC6"; + sccnames[7] = (char *) "SCC7"; + sccnames[8] = (char *) "SCC8"; + sccnames[9] = (char *) "SCC9"; + retval = Bnet_bddArrayDump(dd, net, option->dumpfile, SCCs, + sccnames, nscc, option->dumpFmt); + if (retval == 0) return(0); + } + + /* Verify that the SCCs form a partition of the universe. */ + scc = zero; + Cudd_Ref(scc); + for (i = 0; i < nscc; i++) { + assert(Cudd_bddLeq(dd,SCCs[i],Cudd_Not(scc))); + tmp = Cudd_bddOr(dd,SCCs[i],scc); + if (tmp == NULL) return(0); + Cudd_Ref(tmp); + Cudd_RecursiveDeref(dd,scc); + scc = tmp; + Cudd_RecursiveDeref(dd,SCCs[i]); + } + assert(scc == Cudd_Not(states)); + + /* Clean up. */ + Cudd_RecursiveDeref(dd,scc); + Cudd_RecursiveDeref(dd,states); + Ntr_freeTR(dd,TR); + + return(1); + +} /* end of Ntr_SCC */ + + +/**Function******************************************************************** + + Synopsis [Transitive closure traversal procedure.] + + Description [Traversal procedure. based on the transitive closure of the + transition relation. Returns 1 in case of success; 0 otherwise.] + + SideEffects [None] + + SeeAlso [Ntr_Trav] + +******************************************************************************/ +int +Ntr_ClosureTrav( + DdManager * dd /* DD manager */, + BnetNetwork * net /* network */, + NtrOptions * option /* options */) +{ + DdNode *init; + DdNode *T; + NtrPartTR *TR; + int retval; + int pr = option->verb; /* verbosity level */ + DdNode *dfunc[2]; /* addresses of the functions to be dumped */ + char *onames[2]; /* names of the functions to be dumped */ + DdNode *reached, *reachedy, *reachedx; + + /* Traverse if requested and if the circuit is sequential. */ + if (option->closure == FALSE || net->nlatches == 0) return(1); + + TR = Ntr_buildTR(dd,net,option,NTR_IMAGE_MONO); + if (TR == NULL) return(0); + (void) printf("TR"); Cudd_PrintDebug(dd,TR->part[0],2*TR->nlatches,pr); + T = Ntr_TransitiveClosure(dd,TR,option); + if (T == NULL) return(0); + Cudd_Ref(T); + (void) printf("TC"); Cudd_PrintDebug(dd,T,2*TR->nlatches,pr); + + init = Ntr_initState(dd,net,option); + if (init == NULL) return(0); + (void) printf("S0"); Cudd_PrintDebug(dd,init,TR->nlatches,pr); + + /* Image computation. */ + if (option->closureClip != 1.0) { + int depth = (int) ((double) Cudd_ReadSize(dd) * option->closureClip); + reachedy = Cudd_bddClippingAndAbstract(dd,T,init,TR->icube[0], + depth,option->approx); + } else { + reachedy = Cudd_bddAndAbstract(dd,T,init,TR->icube[0]); + } + if (reachedy == NULL) return(0); + Cudd_Ref(reachedy); + + /* Express in terms of present state variables. */ + reachedx = Cudd_bddSwapVariables(dd,reachedy,TR->x,TR->y,TR->nlatches); + if (reachedx == NULL) return(0); + Cudd_Ref(reachedx); + Cudd_RecursiveDeref(dd,reachedy); + + /* Add initial state. */ + reached = Cudd_bddOr(dd,reachedx,init); + if (reached == NULL) return(0); + Cudd_Ref(reached); + Cudd_RecursiveDeref(dd,reachedx); + + /* Print out result. */ + (void) printf("R"); Cudd_PrintDebug(dd,reached,TR->nlatches,pr); + + /* Dump to file if requested. */ + if (option->bdddump) { + dfunc[0] = T; onames[0] = (char *) "TC"; + dfunc[1] = reached; onames[1] = (char *) "R"; + retval = Bnet_bddArrayDump(dd, net, option->dumpfile, dfunc, + onames, 2, option->dumpFmt); + if (retval == 0) return(0); + } + + /* Clean up. */ + Cudd_RecursiveDeref(dd,reached); + Cudd_RecursiveDeref(dd,init); + Cudd_RecursiveDeref(dd,T); + Ntr_freeTR(dd,TR); + + return(1); + +} /* end of Ntr_ClosureTrav */ + + +/**Function******************************************************************** + + Synopsis [Builds the transitive closure of a transition relation.] + + Description [Builds the transitive closure of a transition relation. + Returns a BDD if successful; NULL otherwise. Uses a simple squaring + algorithm.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +DdNode * +Ntr_TransitiveClosure( + DdManager * dd, + NtrPartTR * TR, + NtrOptions * option) +{ + DdNode *T,*oldT,*Txz,*Tzy,*Tred,*square,*zcube; + DdNode **z; + int i; + int depth = 0; + int ylevel; + int done; + + if (option->image != NTR_IMAGE_MONO) return(NULL); + + /* Create array of auxiliary variables. */ + z = ALLOC(DdNode *,TR->nlatches); + if (z == NULL) + return(NULL); + for (i = 0; i < TR->nlatches; i++) { + ylevel = Cudd_ReadIndex(dd,TR->y[i]->index); + z[i] = Cudd_bddNewVarAtLevel(dd,ylevel); + if (z[i] == NULL) + return(NULL); + } + /* Build cube of auxiliary variables. */ + zcube = makecube(dd,z,TR->nlatches); + if (zcube == NULL) return(NULL); + Cudd_Ref(zcube); + + if (option->closureClip != 1.0) { + depth = (int) ((double) Cudd_ReadSize(dd) * option->imageClip); + } + + T = TR->part[0]; + Cudd_Ref(T); + for (i = 0; ; i++) { + if (option->threshold >= 0) { + if (option->approx) { + Tred = Cudd_RemapOverApprox(dd,T,TR->nlatches*2, + option->threshold, + option->quality); + } else { + Tred = Cudd_RemapUnderApprox(dd,T,TR->nlatches*2, + option->threshold, + option->quality); + } + } else { + Tred = T; + } + if (Tred == NULL) return(NULL); + Cudd_Ref(Tred); + /* Express T in terms of z and y variables. */ + Tzy = Cudd_bddSwapVariables(dd,Tred,TR->x,z,TR->nlatches); + if (Tzy == NULL) return(NULL); + Cudd_Ref(Tzy); + /* Express T in terms of x and z variables. */ + Txz = Cudd_bddSwapVariables(dd,Tred,TR->y,z,TR->nlatches); + if (Txz == NULL) return(NULL); + Cudd_Ref(Txz); + Cudd_RecursiveDeref(dd,Tred); + /* Square */ + if (depth == 0) { + square = Cudd_bddAndAbstract(dd,Txz,Tzy,zcube); + } else { + square = Cudd_bddClippingAndAbstract(dd,Txz,Tzy,zcube,depth, + option->approx); + } + if (square == NULL) return(NULL); + Cudd_Ref(square); + Cudd_RecursiveDeref(dd,Tzy); + Cudd_RecursiveDeref(dd,Txz); + oldT = T; + T = Cudd_bddOr(dd,square,TR->part[0]); + if (T == NULL) return(NULL); + Cudd_Ref(T); + Cudd_RecursiveDeref(dd,square); + done = T == oldT; + Cudd_RecursiveDeref(dd,oldT); + if (done) break; + (void) fprintf(stdout,"@"); fflush(stdout); + } + (void) fprintf(stdout, "\n"); + + Cudd_RecursiveDeref(dd,zcube); + Cudd_Deref(T); + FREE(z); + return(T); + +} /* end of Ntr_TransitiveClosure */ + + +/**Function******************************************************************** + + Synopsis [Builds the BDD of the initial state(s).] + + Description [Builds the BDD of the initial state(s). Returns a BDD + if successful; NULL otherwise.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +DdNode * +Ntr_initState( + DdManager * dd, + BnetNetwork * net, + NtrOptions * option) +{ + DdNode *res, *x, *w, *one; + BnetNode *node; + int i; + + if (option->load) { + res = Dddmp_cuddBddLoad(dd, DDDMP_VAR_MATCHIDS, NULL, NULL, NULL, + DDDMP_MODE_DEFAULT, option->loadfile, NULL); + } else { + one = Cudd_ReadOne(dd); + Cudd_Ref(res = one); + + if (net->nlatches == 0) return(res); + + for (i = 0; i < net->nlatches; i++) { + if (!st_lookup(net->hash,net->latches[i][1],&node)) { + goto endgame; + } + x = node->dd; + switch (net->latches[i][2][0]) { + case '0': + w = Cudd_bddAnd(dd,res,Cudd_Not(x)); + break; + case '1': + w = Cudd_bddAnd(dd,res,x); + break; + default: /* don't care */ + w = res; + break; + } + + if (w == NULL) { + Cudd_RecursiveDeref(dd,res); + return(NULL); + } + Cudd_Ref(w); + Cudd_RecursiveDeref(dd,res); + res = w; + } + } + return(res); + +endgame: + + return(NULL); + +} /* end of Ntr_initState */ + + +/**Function******************************************************************** + + Synopsis [Reads a state cube from a file or creates a random one.] + + Description [Reads a state cube from a file or create a random one. + Returns a pointer to the BDD of the sink nodes if successful; NULL + otherwise.] + + SideEffects [None] + + SeeAlso [] + +*****************************************************************************/ +DdNode * +Ntr_getStateCube( + DdManager * dd, + BnetNetwork * net, + char * filename, + int pr) +{ + FILE *fp; + DdNode *cube; + DdNode *w; + char *state; + int i; + int err; + BnetNode *node; + DdNode *x; + char c[2]; + + cube = Cudd_ReadOne(dd); + if (net->nlatches == 0) { + Cudd_Ref(cube); + return(cube); + } + + state = ALLOC(char,net->nlatches+1); + if (state == NULL) + return(NULL); + state[net->nlatches] = 0; + + if (filename == NULL) { + /* Pick one random minterm. */ + for (i = 0; i < net->nlatches; i++) { + state[i] = (char) ((Cudd_Random() & 0x2000) ? '1' : '0'); + } + } else { + if ((fp = fopen(filename,"r")) == NULL) { + (void) fprintf(stderr,"Unable to open %s\n",filename); + return(NULL); + } + + /* Read string from file. Allow arbitrary amount of white space. */ + for (i = 0; !feof(fp); i++) { + err = fscanf(fp, "%1s", c); + state[i] = c[0]; + if (err == EOF || i == net->nlatches - 1) { + break; + } else if (err != 1 || strchr("012xX-", c[0]) == NULL ) { + FREE(state); + return(NULL); + } + } + err = fclose(fp); + if (err == EOF) { + FREE(state); + return(NULL); + } + } + + /* Echo the chosen state(s). */ + if (pr > 0) {(void) fprintf(stdout,"%s\n", state);} + + Cudd_Ref(cube); + for (i = 0; i < net->nlatches; i++) { + if (!st_lookup(net->hash,net->latches[i][1],&node)) { + Cudd_RecursiveDeref(dd,cube); + FREE(state); + return(NULL); + } + x = node->dd; + switch (state[i]) { + case '0': + w = Cudd_bddAnd(dd,cube,Cudd_Not(x)); + break; + case '1': + w = Cudd_bddAnd(dd,cube,x); + break; + default: /* don't care */ + w = cube; + break; + } + + if (w == NULL) { + Cudd_RecursiveDeref(dd,cube); + FREE(state); + return(NULL); + } + Cudd_Ref(w); + Cudd_RecursiveDeref(dd,cube); + cube = w; + } + + FREE(state); + return(cube); + +} /* end of Ntr_getStateCube */ + + +/**Function******************************************************************** + + Synopsis [Poor man's outer envelope computation.] + + Description [ Poor man's outer envelope computation based on the + monolithic transition relation. Returns 1 in case of success; 0 + otherwise.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +int +Ntr_Envelope( + DdManager * dd /* DD manager */, + NtrPartTR * TR /* transition relation */, + FILE * dfp /* pointer to file for DD dump */, + NtrOptions * option /* program options */) +{ + DdNode **x; /* array of x variables */ + DdNode **y; /* array of y variables */ + int ns; /* number of x and y variables */ + DdNode *dfunc[2]; /* addresses of the functions to be dumped */ + DdNode *envelope, *oldEnvelope; + DdNode *one; + int depth; + int retval; + int pr = option->verb; + int dumpFmt = option->dumpFmt; + + x = TR->x; + y = TR->y; + ns = TR->nlatches; + + one = Cudd_ReadOne(dd); + retval = Cudd_SetVarMap(dd,x,y,ns); + + /* Initialize From. */ + envelope = one; + if (envelope == NULL) return(0); + Cudd_Ref(envelope); + (void) printf("S0"); Cudd_PrintDebug(dd,envelope,ns,pr); + + /* Start traversal. */ + for (depth = 0; ; depth++) { + oldEnvelope = envelope; + /* Image computation. */ + envelope = ntrImage(dd,TR,oldEnvelope,option); + if (envelope == NULL) { + Cudd_RecursiveDeref(dd,oldEnvelope); + return(0); + } + + /* Check for convergence. */ + if (envelope == oldEnvelope) break; + + /* Prepare for new iteration. */ + Cudd_RecursiveDeref(dd,oldEnvelope); + (void) fprintf(stdout,"Envelope[%d]%s",depth+1,(pr>0)? "" : "\n"); + Cudd_PrintDebug(dd,envelope,ns,pr); + + } + /* Clean up. */ + Cudd_RecursiveDeref(dd,oldEnvelope); + + /* Print out result. */ + (void) printf("depth = %d\n", depth); + (void) printf("Envelope"); Cudd_PrintDebug(dd,envelope,ns,pr); + + /* Write dump file if requested. */ + if (dfp != NULL) { + dfunc[0] = TR->part[0]; + dfunc[1] = envelope; + if (dumpFmt == 1) { + retval = Cudd_DumpBlif(dd,2,dfunc,NULL,(char **)onames,NULL,dfp,0); + } else if (dumpFmt == 2) { + retval = Cudd_DumpDaVinci(dd,2,dfunc,NULL,(char **)onames,dfp); + } else if (dumpFmt == 3) { + retval = Cudd_DumpDDcal(dd,2,dfunc,NULL,(char **)onames,dfp); + } else if (dumpFmt == 4) { + retval = Cudd_DumpFactoredForm(dd,2,dfunc,NULL, + (char **)onames,dfp); + } else if (dumpFmt == 5) { + retval = Cudd_DumpBlif(dd,2,dfunc,NULL,(char **)onames,NULL,dfp,1); + } else { + retval = Cudd_DumpDot(dd,2,dfunc,NULL,(char **)onames,dfp); + } + if (retval != 1) { + (void) fprintf(stderr,"abnormal termination\n"); + return(0); + } + fclose(dfp); + } + + /* Clean up. */ + Cudd_RecursiveDeref(dd,envelope); + + return(1); + +} /* end of Ntr_Envelope */ + + +/**Function******************************************************************** + + Synopsis [Maximum 0-1 flow between source and sink states.] + + Description [Maximum 0-1 flow between source and sink + states. Returns 1 in case of success; 0 otherwise.] + + SideEffects [Creates two new sets of variables.] + + SeeAlso [] + +******************************************************************************/ +int +Ntr_maxflow( + DdManager * dd, + BnetNetwork * net, + NtrOptions * option) +{ + DdNode **x = NULL; + DdNode **y = NULL; + DdNode **z = NULL; + DdNode *E = NULL; + DdNode *F = NULL; + DdNode *cut = NULL; + DdNode *sx = NULL; + DdNode *ty = NULL; + DdNode *tx = NULL; + int n; + int pr; + int ylevel; + int i; + double flow; + int result = 0; + NtrPartTR *TR; + + n = net->nlatches; + pr = option->verb; + TR = Ntr_buildTR(dd,net,option,NTR_IMAGE_MONO); + if (TR == NULL) + goto endgame; + E = TR->part[0]; + x = TR->x; + y = TR->y; + /* Create array of auxiliary variables. */ + z = ALLOC(DdNode *,n); + if (z == NULL) + goto endgame; + for (i = 0; i < n; i++) { + ylevel = Cudd_ReadIndex(dd,y[i]->index); + z[i] = Cudd_bddNewVarAtLevel(dd,ylevel); + if (z[i] == NULL) + goto endgame; + Cudd_Ref(z[i]); + } + /* Create BDDs for source and sink. */ + sx = Ntr_initState(dd,net,option); + if (sx == NULL) + goto endgame; + if (pr > 0) (void) fprintf(stdout, "Sink(s): "); + tx = Ntr_getStateCube(dd,net,option->sinkfile,pr); + if (tx == NULL) + goto endgame; + ty = Cudd_bddSwapVariables(dd,tx,x,y,n); + if (ty == NULL) + goto endgame; + Cudd_Ref(ty); + Cudd_RecursiveDeref(dd,tx); + tx = NULL; + + flow = Ntr_maximum01Flow(dd, sx, ty, E, &F, &cut, x, y, z, n, pr); + if (flow >= 0.0) + result = 1; + if (pr >= 0) { + (void) fprintf(stdout,"Maximum flow = %g\n", flow); + (void) fprintf(stdout,"E"); Cudd_PrintDebug(dd,E,2*n,pr); + (void) fprintf(stdout,"F"); Cudd_PrintDebug(dd,F,2*n,pr); + (void) fprintf(stdout,"cut"); Cudd_PrintDebug(dd,cut,2*n,pr); + } +endgame: + /* Clean up. */ + if (TR != NULL) Ntr_freeTR(dd,TR); + for (i = 0; i < n; i++) { + if (z != NULL && z[i] != NULL) Cudd_RecursiveDeref(dd,z[i]); + } + if (z != NULL) FREE(z); + if (F != NULL) Cudd_RecursiveDeref(dd,F); + if (cut != NULL) Cudd_RecursiveDeref(dd,cut); + if (sx != NULL) Cudd_RecursiveDeref(dd,sx); + if (ty != NULL) Cudd_RecursiveDeref(dd,ty); + return(result); + +} /* end of Ntr_Maxflow */ + +/*---------------------------------------------------------------------------*/ +/* Definition of internal functions */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Definition of static functions */ +/*---------------------------------------------------------------------------*/ + + +/**Function******************************************************************** + + Synopsis [Builds a positive cube of all the variables in x.] + + Description [Builds a positive cube of all the variables in x. Returns + a BDD for the cube if successful; NULL otherwise.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +static DdNode * +makecube( + DdManager * dd, + DdNode ** x, + int n) +{ + DdNode *res, *w, *one; + int i; + + one = Cudd_ReadOne(dd); + Cudd_Ref(res = one); + + for (i = n-1; i >= 0; i--) { + w = Cudd_bddAnd(dd,res,x[i]); + if (w == NULL) { + Cudd_RecursiveDeref(dd,res); + return(NULL); + } + Cudd_Ref(w); + Cudd_RecursiveDeref(dd,res); + res = w; + } + Cudd_Deref(res); + return(res); + +} /* end of makecube */ + + +/**Function******************************************************************** + + Synopsis [Initializes the count fields used to drop DDs.] + + Description [Initializes the count fields used to drop DDs. + Before actually building the BDDs, we perform a DFS from the outputs + to initialize the count fields of the nodes. The initial value of the + count field will normally coincide with the fanout of the node. + However, if there are nodes with no path to any primary output or next + state variable, then the initial value of count for some nodes will be + less than the fanout. For primary outputs and next state functions we + add 1, so that we will never try to free their DDs. The count fields + of the nodes that are not reachable from the outputs are set to -1.] + + SideEffects [Changes the count fields of the network nodes. Uses the + visited fields.] + + SeeAlso [] + +******************************************************************************/ +static void +ntrInitializeCount( + BnetNetwork * net, + NtrOptions * option) +{ + BnetNode *node; + int i; + + if (option->node != NULL && + option->closestCube == FALSE && option->dontcares == FALSE) { + if (!st_lookup(net->hash,option->node,&node)) { + (void) fprintf(stdout, "Warning: node %s not found!\n", + option->node); + } else { + ntrCountDFS(net,node); + node->count++; + } + } else { + if (option->stateOnly == FALSE) { + for (i = 0; i < net->npos; i++) { + if (!st_lookup(net->hash,net->outputs[i],&node)) { + (void) fprintf(stdout, + "Warning: output %s is not driven!\n", + net->outputs[i]); + continue; + } + ntrCountDFS(net,node); + node->count++; + } + } + for (i = 0; i < net->nlatches; i++) { + if (!st_lookup(net->hash,net->latches[i][0],&node)) { + (void) fprintf(stdout, + "Warning: latch input %s is not driven!\n", + net->outputs[i]); + continue; + } + ntrCountDFS(net,node); + node->count++; + } + } + + /* Clear visited flags. */ + node = net->nodes; + while (node != NULL) { + if (node->visited == 0) { + node->count = -1; + } else { + node->visited = 0; + } + node = node->next; + } + +} /* end of ntrInitializeCount */ + + +/**Function******************************************************************** + + Synopsis [Does a DFS from a node setting the count field.] + + Description [] + + SideEffects [Changes the count and visited fields of the nodes it + visits.] + + SeeAlso [ntrLevelDFS] + +******************************************************************************/ +static void +ntrCountDFS( + BnetNetwork * net, + BnetNode * node) +{ + int i; + BnetNode *auxnd; + + node->count++; + + if (node->visited == 1) { + return; + } + + node->visited = 1; + + for (i = 0; i < node->ninp; i++) { + if (!st_lookup(net->hash, node->inputs[i], &auxnd)) { + exit(2); + } + ntrCountDFS(net,auxnd); + } + +} /* end of ntrCountDFS */ + + +/**Function******************************************************************** + + Synopsis [Computes the image of a set given a transition relation.] + + Description [Computes the image of a set given a transition relation. + Returns a pointer to the result if successful; NULL otherwise. The image is + returned in terms of the present state variables; its reference count is + already increased.] + + SideEffects [None] + + SeeAlso [Ntr_Trav] + +******************************************************************************/ +static DdNode * +ntrImage( + DdManager * dd, + NtrPartTR * TR, + DdNode * from, + NtrOptions * option) +{ + int i; + DdNode *image; + DdNode *to; + NtrPartTR *T; + int depth = 0; + + if (option->image == NTR_IMAGE_CLIP) { + depth = (int) ((double) Cudd_ReadSize(dd) * option->imageClip); + } + + /* Existentially quantify the present state variables that are not + ** in the support of any next state function. */ + image = Cudd_bddExistAbstract(dd,from,TR->preiabs); + if (image == NULL) return(NULL); + Cudd_Ref(image); + if (option->image == NTR_IMAGE_DEPEND) { + /* Simplify the transition relation based on dependencies + ** and build the conjuncts from the deltas. */ + T = ntrEliminateDependencies(dd,TR,&image,option); + } else { + T = TR; + } + if (T == NULL) return(NULL); + for (i = 0; i < T->nparts; i++) { +#if 0 + (void) printf(" Intermediate product[%d]: %d nodes\n", + i,Cudd_DagSize(image)); +#endif + if (option->image == NTR_IMAGE_CLIP) { + to = Cudd_bddClippingAndAbstract(dd,T->part[i],image,T->icube[i], + depth,option->approx); + } else { + to = Cudd_bddAndAbstract(dd,T->part[i],image,T->icube[i]); + } + if (to == NULL) return(NULL); + Cudd_Ref(to); + if (option->image == NTR_IMAGE_DEPEND) { + /* Extract dependencies from intermediate product. */ + DdNode *abs, *positive, *absabs, *phi, *exnor, *tmp; + abs = Cudd_bddExistAbstract(dd,to,T->xw); + if (abs == NULL) return(NULL); Cudd_Ref(abs); + if (Cudd_bddVarIsDependent(dd,abs,T->nscube[i]) && + Cudd_EstimateCofactor(dd,abs,T->nscube[i]->index,1) <= + T->nlatches) { + int retval, sizex; + positive = Cudd_Cofactor(dd,abs,T->nscube[i]); + if (positive == NULL) return(NULL); Cudd_Ref(positive); + absabs = Cudd_bddExistAbstract(dd,abs,T->nscube[i]); + if (absabs == NULL) return(NULL); Cudd_Ref(absabs); + Cudd_RecursiveDeref(dd,abs); + phi = Cudd_bddLICompaction(dd,positive,absabs); + if (phi == NULL) return(NULL); Cudd_Ref(phi); + Cudd_RecursiveDeref(dd,positive); + Cudd_RecursiveDeref(dd,absabs); + exnor = Cudd_bddXnor(dd,T->nscube[i],phi); + if (exnor == NULL) return(NULL); Cudd_Ref(exnor); + Cudd_RecursiveDeref(dd,phi); + sizex = Cudd_DagSize(exnor); + (void) printf("new factor of %d nodes\n", sizex); + retval = Ntr_HeapInsert(T->factors,exnor,sizex); + if (retval == 0) return(NULL); + tmp = Cudd_bddExistAbstract(dd,to,T->nscube[i]); + if (tmp == NULL) return(NULL); Cudd_Ref(tmp); + Cudd_RecursiveDeref(dd,to); + to = tmp; + } else { + Cudd_RecursiveDeref(dd,abs); + } + } + Cudd_RecursiveDeref(dd,image); + image = to; + } + if (option->image == NTR_IMAGE_DEPEND) { + int size1, size2; + DdNode *factor1, *factor2, *tmp; + int retval; + size1 = Cudd_DagSize(image); + retval = Ntr_HeapInsert(T->factors,image,size1); + if (retval == 0) return(NULL); + (void) printf("Merging %d factors. Independent image: %d nodes\n", + Ntr_HeapCount(T->factors), size1); + while (Ntr_HeapCount(T->factors) > 1) { + retval = Ntr_HeapExtractMin(T->factors,&factor1,&size1); + if (retval == 0) return(NULL); + retval = Ntr_HeapExtractMin(T->factors,&factor2,&size2); + if (retval == 0) return(NULL); + tmp = Cudd_bddAnd(dd,factor1,factor2); + if (tmp == NULL) return(NULL); Cudd_Ref(tmp); + size1 = Cudd_DagSize(tmp); + (void) printf("new factor %d nodes\n", size1); + Cudd_RecursiveDeref(dd,factor1); + Cudd_RecursiveDeref(dd,factor2); + retval = Ntr_HeapInsert(T->factors,tmp,size1); + if (retval == 0) return(NULL); + } + retval = Ntr_HeapExtractMin(T->factors,&image,&size1); + if (retval == 0) return(NULL); + Ntr_freeTR(dd,T); + } + + /* Express image in terms of x variables. */ + to = Cudd_bddVarMap(dd,image); + if (to == NULL) { + Cudd_RecursiveDeref(dd,image); + return(NULL); + } + Cudd_Ref(to); + Cudd_RecursiveDeref(dd,image); + return(to); + +} /* end of ntrImage */ + + +/**Function******************************************************************** + + Synopsis [Computes the preimage of a set given a transition relation.] + + Description [Computes the preimage of a set given a transition relation. + Returns a pointer to the result if successful; NULL otherwise. The preimage + is returned in terms of the next state variables; its reference count is + already increased.] + + SideEffects [None] + + SeeAlso [ntrImage Ntr_SCC] + +******************************************************************************/ +static DdNode * +ntrPreimage( + DdManager * dd, + NtrPartTR * T, + DdNode * from) +{ + int i; + DdNode *preimage; + DdNode *to; + + /* Existentially quantify the present state variables that are not + ** in the support of any next state function. */ + preimage = Cudd_bddExistAbstract(dd,from,T->prepabs); + if (preimage == NULL) return(NULL); + Cudd_Ref(preimage); + for (i = 0; i < T->nparts; i++) { +#if 0 + (void) printf(" Intermediate product[%d]: %d nodes\n", + i,Cudd_DagSize(preimage)); +#endif + to = Cudd_bddAndAbstract(dd,T->part[i],preimage,T->pcube[i]); + if (to == NULL) return(NULL); + Cudd_Ref(to); + Cudd_RecursiveDeref(dd,preimage); + preimage = to; + } + + /* Express preimage in terms of x variables. */ + to = Cudd_bddVarMap(dd,preimage); + if (to == NULL) { + Cudd_RecursiveDeref(dd,preimage); + return(NULL); + } + Cudd_Ref(to); + Cudd_RecursiveDeref(dd,preimage); + return(to); + +} /* end of ntrPreimage */ + + +/**Function******************************************************************** + + Synopsis [Chooses the initial states for a BFS step.] + + Description [Chooses the initial states for a BFS step. Returns a + pointer to the chose set if successful; NULL otherwise. The + reference count of the result is already incremented.] + + SideEffects [none] + + SeeAlso [Ntr_Trav] + +******************************************************************************/ +static DdNode * +ntrChooseFrom( + DdManager * dd, + DdNode * neW, + DdNode * reached, + NtrOptions * option) +{ + DdNode *min, *c; + int threshold; + + switch (option->from) { + case NTR_FROM_NEW: + Cudd_Ref(neW); + return(neW); + case NTR_FROM_REACHED: + Cudd_Ref(reached); + return(reached); + case NTR_FROM_RESTRICT: + c = Cudd_bddOr(dd, neW, Cudd_Not(reached)); + if (c == NULL) return(NULL); + Cudd_Ref(c); + min = Cudd_bddRestrict(dd,neW,c); + if (min == NULL) { + Cudd_RecursiveDeref(dd, c); + return(NULL); + } + Cudd_Ref(min); + Cudd_RecursiveDeref(dd, c); + return(min); + case NTR_FROM_COMPACT: + c = Cudd_bddOr(dd, neW, Cudd_Not(reached)); + if (c == NULL) return(NULL); + Cudd_Ref(c); + min = Cudd_bddLICompaction(dd,neW,c); + if (min == NULL) { + Cudd_RecursiveDeref(dd, c); + return(NULL); + } + Cudd_Ref(min); + Cudd_RecursiveDeref(dd, c); + return(min); + case NTR_FROM_SQUEEZE: + min = Cudd_bddSqueeze(dd,neW,reached); + if (min == NULL) return(NULL); + Cudd_Ref(min); + return(min); + case NTR_FROM_UNDERAPPROX: + threshold = (option->threshold < 0) ? 0 : option->threshold; + min = Cudd_RemapUnderApprox(dd,neW,Cudd_SupportSize(dd,neW), + threshold,option->quality); + if (min == NULL) return(NULL); + Cudd_Ref(min); + return(min); + case NTR_FROM_OVERAPPROX: + threshold = (option->threshold < 0) ? 0 : option->threshold; + min = Cudd_RemapOverApprox(dd,neW,Cudd_SupportSize(dd,neW), + threshold,option->quality); + if (min == NULL) return(NULL); + Cudd_Ref(min); + return(min); + default: + return(NULL); + } + +} /* end of ntrChooseFrom */ + + +/**Function******************************************************************** + + Synopsis [Updates the reached states after a traversal step.] + + Description [Updates the reached states after a traversal + step. Returns a pointer to the new reached set if successful; NULL + otherwise. The reference count of the result is already incremented.] + + SideEffects [The old reached set is dereferenced.] + + SeeAlso [Ntr_Trav] + +******************************************************************************/ +static DdNode * +ntrUpdateReached( + DdManager * dd /* manager */, + DdNode * oldreached /* old reached state set */, + DdNode * to /* result of last image computation */) +{ + DdNode *reached; + + reached = Cudd_bddOr(dd,oldreached,to); + if (reached == NULL) { + Cudd_RecursiveDeref(dd,oldreached); + return(NULL); + } + Cudd_Ref(reached); + Cudd_RecursiveDeref(dd,oldreached); + return(reached); + +} /* end of ntrUpdateReached */ + + +/**Function******************************************************************** + + Synopsis [Analyzes the reached states after traversal to find + dependent latches.] + + Description [Analyzes the reached states after traversal to find + dependent latches. Returns the number of latches that can be + eliminated because they are stuck at a constant value or are + dependent on others if successful; -1 otherwise. The algorithm is + greedy and determines a local optimum, not a global one.] + + SideEffects [] + + SeeAlso [Ntr_Trav] + +******************************************************************************/ +static int +ntrLatchDependencies( + DdManager *dd, + DdNode *reached, + BnetNetwork *net, + NtrOptions *option) +{ + int i; + int howMany; /* number of latches that can be eliminated */ + DdNode *var, *newreached, *abs, *positive, *phi; + char *name; + BnetNode *node; + int initVars, finalVars; + double initStates, finalStates; + DdNode **roots; + char **onames; + int howManySmall = 0; + int *candidates; + double minStates; + int totalVars; + + (void) printf("Analyzing latch dependencies\n"); + roots = ALLOC(DdNode *, net->nlatches); + if (roots == NULL) return(-1); + onames = ALLOC(char *, net->nlatches); + if (onames == NULL) return(-1); + + candidates = ALLOC(int,net->nlatches); + if (candidates == NULL) return(-1); + for (i = 0; i < net->nlatches; i++) { + candidates[i] = i; + } + /* The signatures of the variables in a function are the number + ** of minterms of the positive cofactors with respect to the + ** variables themselves. */ + newreached = reached; + Cudd_Ref(newreached); + signatures = Cudd_CofMinterm(dd,newreached); + if (signatures == NULL) return(-1); + /* We now extract a positive quantity which is higher for those + ** variables that are closer to being essential. */ + totalVars = Cudd_ReadSize(dd); + minStates = signatures[totalVars]; +#if 0 + (void) printf("Raw signatures (minStates = %g)\n", minStates); + for (i = 0; i < net->nlatches; i++) { + int j = candidates[i]; + if (!st_lookup(net->hash,net->latches[j][1],(char **) &node)) { + return(-1); + } + (void) printf("%s -> %g\n", node->name, signatures[node->dd->index]); + } +#endif + for (i = 0; i < totalVars; i++) { + double z = signatures[i] / minStates - 1.0; + signatures[i] = (z >= 0.0) ? z : -z; /* make positive */ + } + staticNet = net; + qsort((void *)candidates,net->nlatches,sizeof(int), + (DD_QSFP)ntrSignatureCompare2); +#if 0 + (void) printf("Cooked signatures\n"); + for (i = 0; i < net->nlatches; i++) { + int j = candidates[i]; + if (!st_lookup(net->hash,net->latches[j][1],(char **) &node)) { + return(-1); + } + (void) printf("%s -> %g\n", node->name, signatures[node->dd->index]); + } +#endif + FREE(signatures); + + /* Extract simple dependencies. */ + for (i = 0; i < net->nlatches; i++) { + int j = candidates[i]; + if (!st_lookup(net->hash,net->latches[j][1],&node)) { + return(-1); + } + var = node->dd; + name = node->name; + if (Cudd_bddVarIsDependent(dd,newreached,var)) { + positive = Cudd_Cofactor(dd,newreached,var); + if (positive == NULL) return(-1); Cudd_Ref(positive); + abs = Cudd_bddExistAbstract(dd,newreached,var); + if (abs == NULL) return(-1); Cudd_Ref(abs); + phi = Cudd_bddLICompaction(dd,positive,abs); + if (phi == NULL) return(-1); Cudd_Ref(phi); + Cudd_RecursiveDeref(dd,positive); + if (Cudd_DagSize(phi) < NTR_MAX_DEP_SIZE) { + if (Cudd_bddLeq(dd,newreached,var)) { + (void) printf("%s is stuck at 1\n",name); + } else if (Cudd_bddLeq(dd,newreached,Cudd_Not(var))) { + (void) printf("%s is stuck at 0\n",name); + } else { + (void) printf("%s depends on the other variables\n",name); + } + roots[howManySmall] = phi; + onames[howManySmall] = util_strsav(name); + Cudd_RecursiveDeref(dd,newreached); + newreached = abs; + howManySmall++; + candidates[i] = -1; /* do not reconsider */ + } else { + Cudd_RecursiveDeref(dd,abs); + Cudd_RecursiveDeref(dd,phi); + } + } else { + candidates[i] = -1; /* do not reconsider */ + } + } + /* Now remove remaining dependent variables. */ + howMany = howManySmall; + for (i = 0; i < net->nlatches; i++) { + int j = candidates[i]; + if (j == -1) continue; + if (!st_lookup(net->hash,net->latches[j][1],&node)) { + return(-1); + } + var = node->dd; + name = node->name; + if (Cudd_bddVarIsDependent(dd,newreached,var)) { + if (Cudd_bddLeq(dd,newreached,var)) { + (void) printf("%s is stuck at 1\n",name); + } else if (Cudd_bddLeq(dd,newreached,Cudd_Not(var))) { + (void) printf("%s is stuck at 0\n",name); + } else { + (void) printf("%s depends on the other variables\n",name); + } + abs = Cudd_bddExistAbstract(dd,newreached,var); + if (abs == NULL) return(-1); Cudd_Ref(abs); + Cudd_RecursiveDeref(dd,newreached); + newreached = abs; + howMany++; + } + } + FREE(candidates); + if (howManySmall > 0) { + if (!Bnet_bddArrayDump(dd,net,(char *)"-",roots,onames,howManySmall,1)) + return(-1); + } + for (i = 0; i < howManySmall; i++) { + Cudd_RecursiveDeref(dd,roots[i]); + FREE(onames[i]); + } + FREE(roots); + FREE(onames); + + initVars = net->nlatches; + initStates = Cudd_CountMinterm(dd,reached,initVars); + finalVars = initVars - howMany; + finalStates = Cudd_CountMinterm(dd,newreached,finalVars); + if (initStates != finalStates) { + (void) printf("Error: the number of states changed from %g to %g\n", + initStates, finalStates); + return(-1); + } + (void) printf("new reached"); + Cudd_PrintDebug(dd,newreached,finalVars,option->verb); + Cudd_RecursiveDeref(dd,newreached); + return(howMany); + +} /* end of ntrLatchDependencies */ + + +/**Function******************************************************************** + + Synopsis [Eliminates dependent variables from a transition relation.] + + Description [Eliminates dependent variables from a transition + relation. Returns a simplified copy of the given transition + relation if successful; NULL otherwise.] + + SideEffects [The modified set of states is returned as a side effect.] + + SeeAlso [ntrImage] + +******************************************************************************/ +static NtrPartTR * +ntrEliminateDependencies( + DdManager *dd, + NtrPartTR *TR, + DdNode **states, + NtrOptions *option) +{ + NtrPartTR *T; /* new TR without dependent vars */ + int pr = option->verb; + int i, j; + int howMany = 0; /* number of latches that can be eliminated */ + DdNode *var, *newstates, *abs, *positive, *phi; + DdNode *support, *scan, *tmp; + int finalSize; /* size of the TR after substitutions */ + int nvars; /* vars in the support of the state set */ + int *candidates; /* vars to be considered for elimination */ + int totalVars; + double minStates; + + /* Initialize the new transition relation by copying the old one. */ + T = Ntr_cloneTR(TR); + if (T == NULL) return(NULL); + newstates = *states; + Cudd_Ref(newstates); + + /* Find and rank the candidate variables. */ + support = Cudd_Support(dd,newstates); + if (support == NULL) { + Ntr_freeTR(dd,T); + return(NULL); + } + Cudd_Ref(support); + nvars = Cudd_DagSize(support) - 1; + candidates = ALLOC(int,nvars); + if (candidates == NULL) { + Cudd_RecursiveDeref(dd,support); + Ntr_freeTR(dd,T); + return(NULL); + } + scan = support; + for (i = 0; i < nvars; i++) { + candidates[i] = scan->index; + scan = Cudd_T(scan); + } + Cudd_RecursiveDeref(dd,support); + /* The signatures of the variables in a function are the number + ** of minterms of the positive cofactors with respect to the + ** variables themselves. */ + signatures = Cudd_CofMinterm(dd,newstates); + if (signatures == NULL) { + FREE(candidates); + Ntr_freeTR(dd,T); + return(NULL); + } + /* We now extract a positive quantity which is higher for those + ** variables that are closer to being essential. */ + totalVars = Cudd_ReadSize(dd); + minStates = signatures[totalVars]; + for (i = 0; i < totalVars; i++) { + double z = signatures[i] / minStates - 1.0; + signatures[i] = (z < 0.0) ? -z : z; /* make positive */ + } + /* Sort candidates in decreasing order of signature. */ + qsort((void *)candidates,nvars,sizeof(int), + (DD_QSFP)ntrSignatureCompare); + FREE(signatures); + + /* Now process the candidates in the given order. */ + for (i = 0; i < nvars; i++) { + var = Cudd_bddIthVar(dd,candidates[i]); + if (Cudd_bddVarIsDependent(dd,newstates,var)) { + abs = Cudd_bddExistAbstract(dd,newstates,var); + if (abs == NULL) return(NULL); Cudd_Ref(abs); + positive = Cudd_Cofactor(dd,newstates,var); + if (positive == NULL) return(NULL); Cudd_Ref(positive); + phi = Cudd_bddLICompaction(dd,positive,abs); + if (phi == NULL) return(NULL); Cudd_Ref(phi); + Cudd_RecursiveDeref(dd,positive); +#if 0 + if (pr > 0) { + (void) printf("Phi"); + Cudd_PrintDebug(dd,phi,T->nlatches,pr); + } +#endif + if (Cudd_DagSize(phi) < NTR_MAX_DEP_SIZE) { + howMany++; + for (j = 0; j < T->nparts; j++) { + tmp = Cudd_bddCompose(dd,T->part[j],phi,candidates[i]); + if (tmp == NULL) return(NULL); Cudd_Ref(tmp); + Cudd_RecursiveDeref(dd,T->part[j]); + T->part[j] = tmp; + } + Cudd_RecursiveDeref(dd,newstates); + newstates = abs; + } else { + Cudd_RecursiveDeref(dd,abs); + } + Cudd_RecursiveDeref(dd,phi); + } + } + FREE(candidates); + + if (pr > 0) { + finalSize = Cudd_SharingSize(T->part,T->nparts); + (void) printf("Eliminated %d vars. Transition function %d nodes.\n", + howMany,finalSize); + } + + if (!ntrUpdateQuantificationSchedule(dd,T)) return(NULL); + + /* Quantify out of states variables that no longer appear in any part. */ + Cudd_RecursiveDeref(dd,*states); + *states = Cudd_bddExistAbstract(dd,newstates,T->preiabs); + if (*states == NULL) return(NULL); Cudd_Ref(*states); + Cudd_RecursiveDeref(dd,newstates); + return(T); + +} /* end of ntrEliminateDependencies */ + + +/**Function******************************************************************** + + Synopsis [Updates the quantification schedule of a transition relation.] + + Description [Updates the quantification schedule of a transition relation. + Returns 1 if successful; 0 otherwise.] + + SideEffects [None] + + SeeAlso [ntrEliminateDependencies] + +******************************************************************************/ +static int +ntrUpdateQuantificationSchedule( + DdManager *dd, + NtrPartTR *T) +{ + int i, j, k; + int *schedule; + DdNode *one, *support, *scan, *var, *tmp; + char **matrix; + int *position, *row; + char *flags; + int nparts, nvars; + int extracted; +#if 0 + int schedcost; +#endif + + nparts = T->nparts; + nvars = Cudd_ReadSize(dd); + one = Cudd_ReadOne(dd); + + /* Reinitialize the abstraction cubes. */ + Cudd_RecursiveDeref(dd,T->preiabs); + T->preiabs = one; + Cudd_Ref(one); + for (i = 0; i < nparts; i++) { + Cudd_RecursiveDeref(dd,T->icube[i]); + T->icube[i] = one; + Cudd_Ref(one); + } + + /* Initialize row permutations to the identity. */ + position = ALLOC(int,nparts); + if (position == NULL) return(0); + for (i = 0; i < nparts; i++) { + position[i] = i; + } + /* Sort parts so that parts that differ only + ** in the index of the next state variable are contiguous. */ + staticPart = T->part; + qsort((void *)position,nparts,sizeof(int), (DD_QSFP)ntrPartCompare); + /* Extract repeated parts. */ + extracted = 0; + for (i = 0; i < nparts - 1; i += j) { + int pi, pij; + DdNode *eq; + j = 1; + pi = position[i]; + eq = one; + Cudd_Ref(eq); + pij = position[i+j]; + while (Cudd_Regular(staticPart[pij]) == Cudd_Regular(staticPart[pi])) { + int comple = staticPart[pij] != staticPart[pi]; + DdNode *xnor = Cudd_bddXnor(dd,T->nscube[pi], + Cudd_NotCond(T->nscube[pij],comple)); + if (xnor == NULL) return(0); Cudd_Ref(xnor); + tmp = Cudd_bddAnd(dd,xnor,eq); + if (tmp == NULL) return(0); Cudd_Ref(tmp); + Cudd_RecursiveDeref(dd,xnor); + Cudd_RecursiveDeref(dd,eq); + eq = tmp; + Cudd_RecursiveDeref(dd,T->part[pij]); + Cudd_RecursiveDeref(dd,T->icube[pij]); + Cudd_RecursiveDeref(dd,T->nscube[pij]); + T->part[pij] = NULL; + j++; + if (i+j == nparts) break; + pij = position[i+j]; + } + if (eq != one) { + int retval = Ntr_HeapInsert(T->factors,eq,Cudd_DagSize(eq)); + if (retval == 0) return(0); + extracted += j - 1; + } else { + Cudd_RecursiveDeref(dd,eq); + } + } + /* Compact the part array by removing extracted parts. */ + for (i = 0, j = 0; i < nparts; i++) { + if (T->part[i] != NULL) { + T->part[j] = T->part[i]; + T->icube[j] = T->icube[i]; + T->nscube[j] = T->nscube[i]; + j++; + } + } + nparts = T->nparts -= extracted; + (void) printf("Extracted %d repeated parts in %d factors.\n", + extracted, Ntr_HeapCount(T->factors)); + + /* Build the support matrix. Each row corresponds to a part of the + ** transition relation; each column corresponds to a variable in + ** the manager. A 1 in position (i,j) means that Part i depends + ** on Variable j. */ + matrix = ntrAllocMatrix(nparts,nvars); + if (matrix == NULL) return(0); + + /* Allocate array for quantification schedule and initialize it. */ + schedule = ALLOC(int,nvars); + if (schedule == NULL) return(0); + for (i = 0; i < nvars; i++) { + schedule[i] = -1; + } + /* Collect scheduling info for this part. At the end of this loop + ** schedule[i] == j means that the variable of index i does not + ** appear in any part with index greater than j, unless j == -1, + ** in which case the variable appears in no part. + */ + for (i = 0; i < nparts; i++) { + support = Cudd_Support(dd,T->part[i]); + if (support == NULL) return(0); Cudd_Ref(support); + scan = support; + while (!Cudd_IsConstant(scan)) { + int index = scan->index; + schedule[index] = i; + matrix[i][index] = 1; + scan = Cudd_T(scan); + } + Cudd_RecursiveDeref(dd,support); + } +#if 0 + (void) printf("Initial schedule:"); + schedcost = 0; + for (i = 0; i < nvars; i++) { + (void) printf(" %d", schedule[i]); + if (schedule[i] != -1) schedcost += schedule[i]; + } + (void) printf("\nCost = %d\n", schedcost); +#endif + + /* Initialize direct and inverse row permutations to the identity + ** permutation. */ + row = ALLOC(int,nparts); + if (row == NULL) return(0); + for (i = 0; i < nparts; i++) { + position[i] = row[i] = i; + } + + /* Sift the matrix. */ + flags = ALLOC(char,nvars); + if (flags == NULL) return(0); + for (i = 0; i < nparts; i++) { + int cost = 0; /* cost of moving the row */ + int bestcost = 0; + int posn = position[i]; + int bestposn = posn; + /* Sift up. */ + /* Initialize the flags to one is for the variables that are + ** currently scheduled to be quantified after this part gets + ** multiplied. When we cross a row of a part that depends on + ** a variable whose flag is 1, we know that the row being sifted + ** is no longer responsible for that variable. */ + for (k = 0; k < nvars; k++) { + flags[k] = (char) (schedule[k] == i); + } + for (j = posn - 1; j >= 0; j--) { + for (k = 0; k < nvars; k++) { + if (schedule[k] == row[j]) { + cost++; + } else { + flags[k] &= matrix[row[j]][k] == 0; + cost -= flags[k]; + } + } + if (cost < bestcost) { + bestposn = j; + bestcost = cost; + } + } + /* Sift down. */ + /* Reinitialize the flags. (We are implicitly undoing the sift + ** down step.) */ + for (k = 0; k < nvars; k++) { + flags[k] = (char) (schedule[k] == i); + } + for (j = posn + 1; j < nparts; j++) { + for (k = 0; k < nvars; k++) { + if (schedule[k] == row[j]) { + flags[k] |= matrix[i][k] == 1; + cost -= flags[k] == 0; + } else { + cost += flags[k]; + } + } + if (cost < bestcost) { + bestposn = j; + bestcost = cost; + } + } + /* Move to best position. */ + if (bestposn < posn) { + for (j = posn; j >= bestposn; j--) { + k = row[j]; + if (j > 0) row[j] = row[j-1]; + position[k]++; + } + } else { + for (j = posn; j <= bestposn; j++) { + k = row[j]; + if (j < nparts - 1) row[j] = row[j+1]; + position[k]--; + } + } + position[i] = bestposn; + row[bestposn] = i; + /* Fix the schedule. */ + for (k = 0; k < nvars; k++) { + if (matrix[i][k] == 1) { + if (position[schedule[k]] < bestposn) { + schedule[k] = i; + } else { + for (j = nparts - 1; j >= position[i]; j--) { + if (matrix[row[j]][k] == 1) break; + } + schedule[k] = row[j]; + } + } + } + } + ntrFreeMatrix(matrix); + FREE(flags); + + /* Update schedule to account for the permutation. */ + for (i = 0; i < nvars; i++) { + if (schedule[i] >= 0) { + schedule[i] = position[schedule[i]]; + } + } + /* Sort parts. */ + ntrPermuteParts(T->part,T->nscube,row,position,nparts); + FREE(position); + FREE(row); +#if 0 + (void) printf("New schedule:"); + schedcost = 0; + for (i = 0; i < nvars; i++) { + (void) printf(" %d", schedule[i]); + if (schedule[i] != -1) schedcost += schedule[i]; + } + (void) printf("\nCost = %d\n", schedcost); +#endif + + /* Mark the next state varibles so that they do not go in the + ** abstraction cubes. */ + for (i = 0; i < T->nlatches; i++) { + schedule[T->y[i]->index] = -2; + } + + /* Rebuild the cubes from the schedule. */ + for (i = 0; i < nvars; i++) { + k = schedule[i]; + var = Cudd_bddIthVar(dd,i); + if (k >= 0) { + tmp = Cudd_bddAnd(dd,T->icube[k],var); + if (tmp == NULL) return(0); Cudd_Ref(tmp); + Cudd_RecursiveDeref(dd,T->icube[k]); + T->icube[k] = tmp; + } else if (k != -2) { + tmp = Cudd_bddAnd(dd,T->preiabs,var); + if (tmp == NULL) return(0); Cudd_Ref(tmp); + Cudd_RecursiveDeref(dd,T->preiabs); + T->preiabs = tmp; + } + } + FREE(schedule); + + /* Build the conjuncts. */ + for (i = 0; i < nparts; i++) { + tmp = Cudd_bddXnor(dd,T->nscube[i],T->part[i]); + if (tmp == NULL) return(0); Cudd_Ref(tmp); + Cudd_RecursiveDeref(dd,T->part[i]); + T->part[i] = tmp; + } + + return(1); + +} /* end of ntrUpdateQuantificationSchedule */ + + +/**Function******************************************************************** + + Synopsis [Comparison function used by qsort.] + + Description [Comparison function used by qsort to order the + variables according to their signatures.] + + SideEffects [None] + +******************************************************************************/ +static int +ntrSignatureCompare( + int * ptrX, + int * ptrY) +{ + if (signatures[*ptrY] > signatures[*ptrX]) return(1); + if (signatures[*ptrY] < signatures[*ptrX]) return(-1); + return(0); + +} /* end of ntrSignatureCompare */ + + +/**Function******************************************************************** + + Synopsis [Comparison function used by qsort.] + + Description [Comparison function used by qsort to order the + variables according to their signatures.] + + SideEffects [None] + +******************************************************************************/ +static int +ntrSignatureCompare2( + int * ptrX, + int * ptrY) +{ + BnetNode *node; + int x,y; + if (!st_lookup(staticNet->hash,staticNet->latches[*ptrX][1],&node)) { + return(0); + } + x = node->dd->index; + if (!st_lookup(staticNet->hash,staticNet->latches[*ptrY][1],&node)) { + return(0); + } + y = node->dd->index; + if (signatures[x] < signatures[y]) return(1); + if (signatures[x] > signatures[y]) return(-1); + return(0); + +} /* end of ntrSignatureCompare2 */ + + +/**Function******************************************************************** + + Synopsis [Comparison function used by qsort.] + + Description [Comparison function used by qsort to order the + parts according to the BDD addresses.] + + SideEffects [None] + +******************************************************************************/ +static int +ntrPartCompare( + int * ptrX, + int * ptrY) +{ + if (staticPart[*ptrY] > staticPart[*ptrX]) return(1); + if (staticPart[*ptrY] < staticPart[*ptrX]) return(-1); + return(0); + +} /* end of ntrPartCompare */ + + +/**Function******************************************************************** + + Synopsis [Allocates a matrix.] + + Description [Allocates a matrix of char's. Returns a pointer to the matrix + if successful; NULL otherwise.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +static char ** +ntrAllocMatrix( + int nrows, + int ncols) +{ + int i; + char **matrix; + + matrix = ALLOC(char *,nrows); + if (matrix == NULL) return(NULL); + matrix[0] = ALLOC(char,nrows * ncols); + if (matrix[0] == NULL) { + FREE(matrix); + return(NULL); + } + for (i = 1; i < nrows; i++) { + matrix[i] = matrix[i-1] + ncols; + } + for (i = 0; i < nrows * ncols; i++) { + matrix[0][i] = 0; + } + return(matrix); + +} /* end of ntrAllocMatrix */ + + +/**Function******************************************************************** + + Synopsis [Frees a matrix of char's.] + + Description [] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +static void +ntrFreeMatrix( + char **matrix) +{ + FREE(matrix[0]); + FREE(matrix); + return; + +} /* end of ntrFreeMatrix */ + + +/**Function******************************************************************** + + Synopsis [Sorts parts according to given permutation.] + + Description [] + + SideEffects [The permutation arrays are turned into the identity + permutations.] + + SeeAlso [] + +******************************************************************************/ +static void +ntrPermuteParts( + DdNode **a, + DdNode **b, + int *comesFrom, + int *goesTo, + int size) +{ + int i, j; + DdNode *tmp; + + for (i = 0; i < size; i++) { + if (comesFrom[i] == i) continue; + j = comesFrom[i]; + tmp = a[i]; a[i] = a[j]; a[j] = tmp; + tmp = b[i]; b[i] = b[j]; b[j] = tmp; + comesFrom[goesTo[i]] = j; + comesFrom[i] = i; + goesTo[j] = goesTo[i]; + goesTo[i] = i; + } + return; + +} /* end of ntrPermuteParts */ diff --git a/distr/nanotrav/ntr.h b/distr/nanotrav/ntr.h new file mode 100644 index 0000000..60b467d --- /dev/null +++ b/distr/nanotrav/ntr.h @@ -0,0 +1,283 @@ +/**CHeaderFile***************************************************************** + + FileName [ntr.h] + + PackageName [ntr] + + Synopsis [Simple-minded package to do traversal.] + + 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: ntr.h,v 1.27 2009/02/20 02:19:02 fabio Exp fabio $] + +******************************************************************************/ + +#ifndef _NTR +#define _NTR + +/*---------------------------------------------------------------------------*/ +/* Nested includes */ +/*---------------------------------------------------------------------------*/ + +#include "dddmp.h" +#include "bnet.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/*---------------------------------------------------------------------------*/ +/* Constant declarations */ +/*---------------------------------------------------------------------------*/ + +#define PI_PS_FROM_FILE 0 +#define PI_PS_DFS 1 +#define PI_PS_GIVEN 2 + +#define NTR_IMAGE_MONO 0 +#define NTR_IMAGE_PART 1 +#define NTR_IMAGE_CLIP 2 +#define NTR_IMAGE_DEPEND 3 + +#define NTR_UNDER_APPROX 0 +#define NTR_OVER_APPROX 1 + +#define NTR_FROM_NEW 0 +#define NTR_FROM_REACHED 1 +#define NTR_FROM_RESTRICT 2 +#define NTR_FROM_COMPACT 3 +#define NTR_FROM_SQUEEZE 4 +#define NTR_FROM_UNDERAPPROX 5 +#define NTR_FROM_OVERAPPROX 6 + +#define NTR_GROUP_NONE 0 +#define NTR_GROUP_DEFAULT 1 +#define NTR_GROUP_FIXED 2 + +#define NTR_SHORT_NONE 0 +#define NTR_SHORT_BELLMAN 1 +#define NTR_SHORT_FLOYD 2 +#define NTR_SHORT_SQUARE 3 + +/*---------------------------------------------------------------------------*/ +/* Stucture declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Type declarations */ +/*---------------------------------------------------------------------------*/ + +typedef struct NtrOptions { + long initialTime; /* this is here for convenience */ + int verify; /* read two networks and compare them */ + char *file1; /* first network file name */ + char *file2; /* second network file name */ + int second; /* a second network is given */ + int traverse; /* do reachability analysis */ + int depend; /* do latch dependence analysis */ + int image; /* monolithic, partitioned, or clip */ + double imageClip; /* clipping depth in image computation */ + int approx; /* under or over approximation */ + int threshold; /* approximation threshold */ + int from; /* method to compute from states */ + int groupnsps; /* group present state and next state vars */ + int closure; /* use transitive closure */ + double closureClip; /* clipping depth in closure computation */ + int envelope; /* compute outer envelope */ + int scc; /* compute strongly connected components */ + int zddtest; /* do zdd test */ + int printcover; /* print ISOP covers when testing ZDDs */ + int maxflow; /* compute maximum flow in network */ + int shortPath; /* compute shortest paths in network */ + int selectiveTrace; /* use selective trace in shortest paths */ + char *sinkfile; /* file for externally provided sink node */ + int partition; /* test McMillan conjunctive partitioning */ + int char2vect; /* test char-to-vect decomposition */ + int density; /* test density-related functions */ + double quality; /* quality parameter for density functions */ + int decomp; /* test decomposition functions */ + int cofest; /* test cofactor estimation */ + double clip; /* test clipping functions */ + int dontcares; /* test equivalence and containment with DCs */ + int closestCube; /* test Cudd_bddClosestCube */ + int clauses; /* test extraction of two-literal clauses */ + int noBuild; /* do not build BDDs; just echo order */ + int stateOnly; /* ignore primary outputs */ + char *node; /* only node for which to build BDD */ + int locGlob; /* build global or local BDDs */ + int progress; /* report output names while building BDDs */ + int cacheSize; /* computed table initial size */ + unsigned long maxMemory; /* target maximum memory */ + unsigned long maxMemHard; /* maximum allowed memory */ + unsigned int maxLive; /* maximum number of nodes */ + int slots; /* unique subtable initial slots */ + int ordering; /* FANIN DFS ... */ + char *orderPiPs; /* file for externally provided order */ + Cudd_ReorderingType reordering; /* NONE RANDOM PIVOT SIFTING ... */ + int autoDyn; /* ON OFF */ + Cudd_ReorderingType autoMethod; /* RANDOM PIVOT SIFTING CONVERGE ... */ + char *treefile; /* file name for variable tree */ + int firstReorder; /* when to do first reordering */ + int countDead; /* count dead nodes toward triggering + reordering */ + int maxGrowth; /* maximum growth during reordering (%) */ + Cudd_AggregationType groupcheck; /* grouping function */ + int arcviolation; /* percent violation of arcs in + extended symmetry check */ + int symmviolation; /* percent symm violation in + extended symmetry check */ + int recomb; /* recombination parameter for grouping */ + int nodrop; /* don't drop intermediate BDDs ASAP */ + int signatures; /* computation of signatures */ + int gaOnOff; /* whether to run GA at the end */ + int populationSize; /* population size for GA */ + int numberXovers; /* number of crossovers for GA */ + int bdddump; /* ON OFF */ + int dumpFmt; /* 0 -> dot 1 -> blif 2 ->daVinci 3 -> DDcal + ** 4 -> factored form */ + char *dumpfile; /* filename for dump */ + int store; /* iteration at which to store Reached */ + char *storefile; /* filename for storing Reached */ + int load; /* load initial states from file */ + char *loadfile; /* filename for loading states */ + int verb; /* level of verbosity */ +} NtrOptions; + +typedef struct NtrHeapSlot { + void *item; + int key; +} NtrHeapSlot; + +typedef struct NtrHeap { + int size; + int nslots; + NtrHeapSlot *slots; +} NtrHeap; + +typedef struct NtrPartTR { + int nparts; /* number of parts */ + DdNode **part; /* array of parts */ + DdNode **icube; /* quantification cubes for image */ + DdNode **pcube; /* quantification cubes for preimage */ + DdNode **nscube; /* next state variables in each part */ + DdNode *preiabs; /* present state vars and inputs in no part */ + DdNode *prepabs; /* inputs in no part */ + DdNode *xw; /* cube of all present states and PIs */ + NtrHeap *factors; /* factors extracted from the image */ + int nlatches; /* number of latches */ + DdNode **x; /* array of present state variables */ + DdNode **y; /* array of next state variables */ +} NtrPartTR; + +/*---------------------------------------------------------------------------*/ +/* Variable declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Macro declarations */ +/*---------------------------------------------------------------------------*/ + +#ifndef TRUE +# define TRUE 1 +#endif +#ifndef FALSE +# define FALSE 0 +#endif + +/**Macro*********************************************************************** + + Synopsis [Returns 1 if the two arguments are identical strings.] + + Description [] + + SideEffects [none] + + SeeAlso [] + +******************************************************************************/ +#define STRING_EQUAL(s1,s2) (strcmp((s1),(s2)) == 0) + + +/**AutomaticStart*************************************************************/ + +/*---------------------------------------------------------------------------*/ +/* Function prototypes */ +/*---------------------------------------------------------------------------*/ + +extern int Ntr_buildDDs (BnetNetwork *net, DdManager *dd, NtrOptions *option, BnetNetwork *net2); +extern NtrPartTR * Ntr_buildTR (DdManager *dd, BnetNetwork *net, NtrOptions *option, int image); +extern DdNode * Ntr_TransitiveClosure (DdManager *dd, NtrPartTR *TR, NtrOptions *option); +extern int Ntr_Trav (DdManager *dd, BnetNetwork *net, NtrOptions *option); +extern int Ntr_SCC (DdManager *dd, BnetNetwork *net, NtrOptions *option); +extern int Ntr_ClosureTrav (DdManager *dd, BnetNetwork *net, NtrOptions *option); +extern void Ntr_freeTR (DdManager *dd, NtrPartTR *TR); +extern NtrPartTR * Ntr_cloneTR (NtrPartTR *TR); +extern DdNode * Ntr_initState (DdManager *dd, BnetNetwork *net, NtrOptions *option); +extern DdNode * Ntr_getStateCube (DdManager *dd, BnetNetwork *net, char *filename, int pr); +extern int Ntr_Envelope (DdManager *dd, NtrPartTR *TR, FILE *dfp, NtrOptions *option); +extern int Ntr_TestMinimization (DdManager *dd, BnetNetwork *net1, BnetNetwork *net2, NtrOptions *option); +extern int Ntr_TestDensity (DdManager *dd, BnetNetwork *net1, NtrOptions *option); +extern int Ntr_TestDecomp (DdManager *dd, BnetNetwork *net1, NtrOptions *option); +extern int Ntr_VerifyEquivalence (DdManager *dd, BnetNetwork *net1, BnetNetwork *net2, NtrOptions *option); +extern int Ntr_TestCofactorEstimate (DdManager * dd, BnetNetwork * net, NtrOptions * option); +extern int Ntr_TestClipping (DdManager *dd, BnetNetwork *net1, BnetNetwork *net2, NtrOptions *option); +extern int Ntr_TestEquivAndContain (DdManager *dd, BnetNetwork *net1, BnetNetwork *net2, NtrOptions *option); +extern int Ntr_TestClosestCube (DdManager * dd, BnetNetwork * net, NtrOptions * option); +extern int Ntr_TestTwoLiteralClauses (DdManager * dd, BnetNetwork * net1, NtrOptions * option); +extern int Ntr_TestCharToVect(DdManager * dd, BnetNetwork * net1, NtrOptions * option); +extern int Ntr_maxflow (DdManager *dd, BnetNetwork *net, NtrOptions *option); +extern double Ntr_maximum01Flow (DdManager *bdd, DdNode *sx, DdNode *ty, DdNode *E, DdNode **F, DdNode **cut, DdNode **x, DdNode **y, DdNode **z, int n, int pr); +extern int Ntr_testZDD (DdManager *dd, BnetNetwork *net, NtrOptions *option); +extern int Ntr_testISOP (DdManager *dd, BnetNetwork *net, NtrOptions *option); +extern NtrHeap * Ntr_InitHeap (int size); +extern void Ntr_FreeHeap (NtrHeap *heap); +extern int Ntr_HeapInsert (NtrHeap *heap, void *item, int key); +extern int Ntr_HeapExtractMin (NtrHeap *heap, void *item, int *key); +extern int Ntr_HeapCount (NtrHeap *heap); +extern NtrHeap * Ntr_HeapClone (NtrHeap *source); +extern int Ntr_TestHeap (NtrHeap *heap, int i); +extern int Ntr_ShortestPaths (DdManager *dd, BnetNetwork *net, NtrOptions *option); + +/**AutomaticEnd***************************************************************/ + +#ifdef __cplusplus +} +#endif + +#endif /* _NTR */ diff --git a/distr/nanotrav/ntrBddTest.c b/distr/nanotrav/ntrBddTest.c new file mode 100644 index 0000000..fc87d63 --- /dev/null +++ b/distr/nanotrav/ntrBddTest.c @@ -0,0 +1,2315 @@ +/**CFile*********************************************************************** + + FileName [ntrBddTest.c] + + PackageName [ntr] + + Synopsis [BDD test functions for the nanotrav program.] + + 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.] + +******************************************************************************/ + +#include "ntr.h" +#include "cuddInt.h" + +/*---------------------------------------------------------------------------*/ +/* Constant declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Stucture declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Type declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Variable declarations */ +/*---------------------------------------------------------------------------*/ + +#ifndef lint +static char rcsid[] UTIL_UNUSED = "$Id: ntrBddTest.c,v 1.21 2009/02/20 02:19:02 fabio Exp fabio $"; +#endif + +/*---------------------------------------------------------------------------*/ +/* Macro declarations */ +/*---------------------------------------------------------------------------*/ + +/**AutomaticStart*************************************************************/ + +/*---------------------------------------------------------------------------*/ +/* Static function prototypes */ +/*---------------------------------------------------------------------------*/ + +static int ntrTestMinimizationAux (DdManager *dd, BnetNetwork *net1, DdNode *f, char *name, DdNode *c, char *cname, NtrOptions *option); +static int ntrTestDensityAux (DdManager *dd, BnetNetwork *net, DdNode *f, char *name, NtrOptions *option); +static int ntrTestDecompAux (DdManager *dd, BnetNetwork *net, DdNode *f, char *name, NtrOptions *option); +static int ntrTestCofEstAux (DdManager * dd, BnetNetwork * net, DdNode * f, char * name, NtrOptions * option); +static int ntrTestClippingAux (DdManager *dd, BnetNetwork *net1, DdNode *f, char *name, DdNode *g, char *gname, NtrOptions *option); +static int ntrTestEquivAndContainAux (DdManager *dd, BnetNetwork *net1, DdNode *f, char *fname, DdNode *g, char *gname, DdNode *d, char *dname, NtrOptions *option); +static int ntrTestClosestCubeAux (DdManager *dd, BnetNetwork *net, DdNode *f, char *fname, DdNode *g, char *gname, DdNode **vars, NtrOptions *option); +static int ntrTestCharToVect(DdManager * dd, DdNode * f, NtrOptions *option); +#if 0 +static DdNode * ntrCompress1 (DdManager *dd, DdNode *f, int nvars, int threshold); +#endif +static DdNode * ntrCompress2 (DdManager *dd, DdNode *f, int nvars, int threshold); +static BnetNode * ntrNodeIsBuffer (BnetNode *nd, st_table *hash); + +/**AutomaticEnd***************************************************************/ + +/*---------------------------------------------------------------------------*/ +/* Definition of exported functions */ +/*---------------------------------------------------------------------------*/ + + +/**Function******************************************************************** + + Synopsis [Tests BDD minimization functions.] + + Description [Tests BDD minimization functions, including + leaf-identifying compaction, squeezing, and restrict. This function + uses as constraint the first output of net2 and computes positive + and negative cofactors of all the outputs of net1. For each + cofactor, it checks whether compaction was safe (cofactor not larger + than original function) and that the expansion based on each + minimization function (used as a generalized cofactor) equals the + original function. Returns 1 if successful; 0 otherwise.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +int +Ntr_TestMinimization( + DdManager * dd, + BnetNetwork * net1, + BnetNetwork * net2, + NtrOptions * option) +{ + DdNode *f; + DdNode *c = NULL; + char *cname = NULL; + BnetNode *node; + int i; + int result; + int nsize, csize; + + if (option->second == FALSE) return(1); + + (void) printf("Testing BDD minimization algorithms\n"); + /* Use largest output of second network as constraint. */ + csize = -1; + for (i = 0; i < net2->noutputs; i++) { + if (!st_lookup(net2->hash,net2->outputs[i],&node)) { + return(0); + } + nsize = Cudd_DagSize(node->dd); + if (nsize > csize) { + c = node->dd; + cname = node->name; + csize = nsize; + } + } + if (c == NULL || cname == NULL) return(0); + (void) printf("TEST-MINI: Constrain (%s) %d nodes\n", + cname, Cudd_DagSize(c)); + + if (option->node == NULL) { + for (i = 0; i < net1->noutputs; i++) { + if (!st_lookup(net1->hash,net1->outputs[i],&node)) { + return(0); + } + f = node->dd; + if (f == NULL) return(0); + result = ntrTestMinimizationAux(dd,net1,f,node->name,c,cname, + option); + if (result == 0) return(0); + } + } else { + if (!st_lookup(net1->hash,option->node,&node)) { + return(0); + } + f = node->dd; + if (f == NULL) return(0); + result = ntrTestMinimizationAux(dd,net1,f,option->node,c,cname,option); + if (result == 0) return(0); + } + + return(1); + +} /* end of Ntr_TestMinimization */ + + +/**Function******************************************************************** + + Synopsis [Tests BDD density-related functions.] + + Description [Tests BDD density-related functions. + Returns 1 if successful; 0 otherwise.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +int +Ntr_TestDensity( + DdManager * dd, + BnetNetwork * net1, + NtrOptions * option) +{ + DdNode *f; + BnetNode *node; + int i; + int result; + + if (option->density == FALSE) return(1); + + (void) printf("Testing BDD density-related algorithms\n"); + if (option->node == NULL) { + for (i = 0; i < net1->noutputs; i++) { + if (!st_lookup(net1->hash,net1->outputs[i],&node)) { + return(0); + } + f = node->dd; + if (f == NULL) return(0); + result = ntrTestDensityAux(dd,net1,f,node->name,option); + if (result == 0) return(0); + } + } else { + if (!st_lookup(net1->hash,option->node,&node)) { + return(0); + } + f = node->dd; + if (f == NULL) return(0); + result = ntrTestDensityAux(dd,net1,f,option->node,option); + if (result == 0) return(0); + } + + return(1); + +} /* end of Ntr_TestDensity */ + + +/**Function******************************************************************** + + Synopsis [Tests BDD decomposition functions.] + + Description [Tests BDD decomposition functions. + Returns 1 if successful; 0 otherwise.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +int +Ntr_TestDecomp( + DdManager * dd, + BnetNetwork * net1, + NtrOptions * option) +{ + DdNode *f; + BnetNode *node; + int i; + int result; + + if (option->decomp == FALSE) return(1); + + (void) printf("Testing BDD decomposition algorithms\n"); + if (option->node == NULL) { + for (i = 0; i < net1->noutputs; i++) { + if (!st_lookup(net1->hash,net1->outputs[i],&node)) { + return(0); + } + f = node->dd; + if (f == NULL) return(0); + result = ntrTestDecompAux(dd,net1,f,node->name,option); + if (result == 0) return(0); + } + } else { + if (!st_lookup(net1->hash,option->node,&node)) { + return(0); + } + f = node->dd; + if (f == NULL) return(0); + result = ntrTestDecompAux(dd,net1,f,option->node,option); + if (result == 0) return(0); + } + + return(1); + +} /* end of ntrTestDecomp */ + + +/**Function******************************************************************** + + Synopsis [Verify equivalence of combinational networks.] + + Description [Verify equivalence of combinational networks. + Returns 1 if successful and if the networks are equivalent; -1 if + successful, but the networks are not equivalent; 0 otherwise. + The two networks are supposed to have the same names for inputs and + outputs. The only exception is that the second network may miss + output buffers that are present in the first network. This function tries + to match both the output and the input of the buffer.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +int +Ntr_VerifyEquivalence( + DdManager * dd, + BnetNetwork * net1, + BnetNetwork * net2, + NtrOptions * option) +{ + BnetNode *node; + char *oname; + DdNode *odd1, *odd2; + int i; + int pr; + + (void) printf("Testing equivalence\n"); + if (net2->noutputs != net1->noutputs) { + (void) printf("The two networks have different number of outputs\n"); + (void) printf(" %s has %d outputs\n %s has %d outputs\n", + net1->name, net1->noutputs, net2->name, net2->noutputs); + return(-1); + } + if (net2->nlatches != net1->nlatches) { + (void) printf("The two networks have different number of latches\n"); + (void) printf(" %s has %d latches\n %s has %d latches\n", + net1->name, net1->nlatches, net2->name, net2->nlatches); + return(-1); + } + + pr = option->verb; + for (i = 0; i < net1->noutputs; i++) { + oname = net1->outputs[i]; + if (!st_lookup(net1->hash,oname,&node)) { + return(0); + } + odd1 = node->dd; + (void) printf("%s", oname); + Cudd_PrintDebug(dd, node->dd, Cudd_ReadSize(dd), pr); + if (!st_lookup(net2->hash,oname,&node)) { + BnetNode *inpnd; + if ((inpnd = ntrNodeIsBuffer(node,net1->hash)) == NULL || + !st_lookup(net2->hash,inpnd->name,&node)) { + (void) printf("Output %s missing from network %s\n", + oname, net2->name); + return(-1); + } else { + odd2 = inpnd->dd; + } + } else { + odd2 = node->dd; + } + if (odd1 != odd2) { + (void) printf("Output %s is not equivalent\n", oname); + return(-1); + } + } + return(1); + +} /* end of Ntr_VerifyEquivalence */ + + +/**Function******************************************************************** + + Synopsis [Tests BDD cofactor estimate functions.] + + Description [Tests BDD cofactor estimate functions. + Returns 1 if successful; 0 otherwise.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +int +Ntr_TestCofactorEstimate( + DdManager * dd, + BnetNetwork * net, + NtrOptions * option) +{ + DdNode *f; + BnetNode *node; + int i; + int result; + + if (option->cofest == FALSE) return(1); + + (void) printf("Testing BDD cofactor estimation algorithms\n"); + if (option->node == NULL) { + for (i = 0; i < net->noutputs; i++) { + if (!st_lookup(net->hash,net->outputs[i],&node)) { + return(0); + } + f = node->dd; + if (f == NULL) return(0); + result = ntrTestCofEstAux(dd,net,f,node->name,option); + if (result == 0) return(0); + } + } else { + if (!st_lookup(net->hash,option->node,&node)) { + return(0); + } + f = node->dd; + if (f == NULL) return(0); + result = ntrTestCofEstAux(dd,net,f,option->node,option); + if (result == 0) return(0); + } + + return(1); + +} /* end of Ntr_TestCofactorEstimate */ + + +/**Function******************************************************************** + + Synopsis [Tests BDD clipping functions.] + + Description [Tests BDD clipping functions. + Returns 1 if successful; 0 otherwise.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +int +Ntr_TestClipping( + DdManager * dd, + BnetNetwork * net1, + BnetNetwork * net2, + NtrOptions * option) +{ + DdNode *f; + DdNode *g = NULL; + char *gname = NULL; + BnetNode *node; + int i; + int result; + int nsize, gsize; + + if (option->clip < 0.0) return(1); + + (void) printf("Testing BDD clipping algorithms\n"); + /* Use largest output of second network as second operand. */ + gsize = -1; + for (i = 0; i < net2->noutputs; i++) { + if (!st_lookup(net2->hash,net2->outputs[i],&node)) { + return(0); + } + nsize = Cudd_DagSize(node->dd); + if (nsize > gsize) { + g = node->dd; + gname = node->name; + gsize = nsize; + } + } + if (g == NULL || gname == NULL) return(0); + (void) printf("TEST-CLIP: Second operand (%s) %d nodes\n", + gname, Cudd_DagSize(g)); + + if (option->node == NULL) { + for (i = 0; i < net1->noutputs; i++) { + if (!st_lookup(net1->hash,net1->outputs[i],&node)) { + return(0); + } + f = node->dd; + if (f == NULL) return(0); + result = ntrTestClippingAux(dd,net1,f,node->name,g,gname,option); + if (result == 0) return(0); + } + } else { + if (!st_lookup(net1->hash,option->node,&node)) { + return(0); + } + f = node->dd; + if (f == NULL) return(0); + result = ntrTestClippingAux(dd,net1,f,option->node,g,gname,option); + if (result == 0) return(0); + } + + return(1); + +} /* end of Ntr_TestClipping */ + + +/**Function******************************************************************** + + Synopsis [Tests BDD equivalence and containment with don't cares.] + + Description [Tests functions for BDD equivalence and containment + with don't cares, including Cudd_EquivDC and Cudd_bddLeqUnless. This + function uses as care set the first output of net2 and checkes + equivalence and containment for of all the output pairs of net1. + Returns 1 if successful; 0 otherwise.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +int +Ntr_TestEquivAndContain( + DdManager *dd, + BnetNetwork *net1, + BnetNetwork *net2, + NtrOptions *option) +{ + DdNode *f, *g; + DdNode *d = NULL; + char *dname = NULL; + BnetNode *node1, *node2; + int i, j; + int result; + int nsize, dsize; + + if (option->dontcares == FALSE) return(1); + + (void) printf("Testing BDD equivalence and containment algorithms\n"); + /* Use largest output of second network as constraint. */ + dsize = -1; + for (i = 0; i < net2->noutputs; i++) { + if (!st_lookup(net2->hash,net2->outputs[i],&node1)) { + return(0); + } + nsize = Cudd_DagSize(node1->dd); + if (nsize > dsize) { + d = node1->dd; + dname = node1->name; + dsize = nsize; + } + } + if (d == NULL || dname == NULL) return(0); + (void) printf("TEST-DC: Don't care set (%s) %d nodes\n", + dname, Cudd_DagSize(d)); + + if (option->node == NULL) { + for (i = 0; i < net1->noutputs; i++) { + if (!st_lookup(net1->hash,net1->outputs[i],&node1)) { + return(0); + } + f = node1->dd; + if (f == NULL) return(0); + for (j = 0; j < net1->noutputs; j++) { + if (!st_lookup(net1->hash,net1->outputs[j],&node2)) { + return(0); + } + g = node2->dd; + if (g == NULL) return(0); + result = ntrTestEquivAndContainAux(dd,net1,f,node1->name,g, + node2->name,d,dname,option); + if (result == 0) return(0); + } + } + } else { + if (!st_lookup(net1->hash,option->node,&node1)) { + return(0); + } + f = node1->dd; + if (f == NULL) return(0); + for (j = 0; j < net1->noutputs; j++) { + if (!st_lookup(net1->hash,net1->outputs[j],&node2)) { + return(0); + } + g = node2->dd; + if (g == NULL) return(0); + result = ntrTestEquivAndContainAux(dd,net1,f,option->node, + g,node2->name,d,dname,option); + if (result == 0) return(0); + } + } + + return(1); + +} /* end of Ntr_TestEquivAndContain */ + + +/**Function******************************************************************** + + Synopsis [Tests the Cudd_bddClosestCube function.] + + Description [Tests the Cudd_bddClosestCube function. + Returns 1 if successful; 0 otherwise.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +int +Ntr_TestClosestCube( + DdManager * dd, + BnetNetwork * net, + NtrOptions * option) +{ + DdNode *f, *g; + BnetNode *node1, *node2; + int i, j, nvars; + int result; + DdNode **vars; + double calls; + + if (option->closestCube == FALSE) return(1); + + (void) printf("Testing Cudd_bddClosestCube\n"); + nvars = Cudd_ReadSize(dd); + vars = ALLOC(DdNode *, nvars); + if (vars == NULL) return(0); + for (i = 0; i < nvars; i++) { + vars[i] = Cudd_bddIthVar(dd,i); + } + calls = Cudd_ReadRecursiveCalls(dd); + if (option->node == NULL) { + for (i = 0; i < net->noutputs; i++) { + if (!st_lookup(net->hash,net->outputs[i],&node1)) { + FREE(vars); + return(0); + } + f = node1->dd; + if (f == NULL) { + FREE(vars); + return(0); + } + for (j = 0; j < net->noutputs; j++) { + if (!st_lookup(net->hash,net->outputs[j],&node2)) { + FREE(vars); + return(0); + } + g = node2->dd; + if (g == NULL) { + FREE(vars); + return(0); + } + result = ntrTestClosestCubeAux(dd,net,f,node1->name,g, + node2->name,vars,option); + if (result == 0) { + FREE(vars); + return(0); + } + } + } + } else { + if (!st_lookup(net->hash,option->node,&node1)) { + FREE(vars); + return(0); + } + f = node1->dd; + if (f == NULL) { + FREE(vars); + return(0); + } + for (j = 0; j < net->noutputs; j++) { + if (!st_lookup(net->hash,net->outputs[j],&node2)) { + FREE(vars); + return(0); + } + g = node2->dd; + if (g == NULL) { + FREE(vars); + return(0); + } + result = ntrTestClosestCubeAux(dd,net,f,option->node,g, + node2->name,vars,option); + if (result == 0) { + FREE(vars); + return(0); + } + } + } + (void) printf("End of test. Performed %.0f recursive calls.\n", + Cudd_ReadRecursiveCalls(dd) - calls); + FREE(vars); + return(1); + +} /* end of Ntr_TestClosestCube */ + + +/**Function******************************************************************** + + Synopsis [Tests extraction of two-literal clauses.] + + Description [Tests extraction of two-literal clauses. + Returns 1 if successful; 0 otherwise.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +int +Ntr_TestTwoLiteralClauses( + DdManager * dd, + BnetNetwork * net1, + NtrOptions * option) +{ + DdNode *f; + BnetNode *node; + int result; + char **inames = NULL; + int i; + + if (option->clauses == FALSE) return(1); + + /* Initialize data structures. */ + inames = ALLOC(char *,Cudd_ReadSize(dd)); + if (inames == NULL) return(0); + for (i = 0; i < Cudd_ReadSize(dd); i++) { + inames[i] = NULL; + } + + /* Find the input names. */ + for (i = 0; i < net1->ninputs; i++) { + if (!st_lookup(net1->hash,net1->inputs[i],&node)) { + FREE(inames); + return(0); + } + inames[node->var] = net1->inputs[i]; + } + for (i = 0; i < net1->nlatches; i++) { + if (!st_lookup(net1->hash,net1->latches[i][1],&node)) { + FREE(inames); + return(0); + } + inames[node->var] = net1->latches[i][1]; + } + + (void) printf("Testing extraction of two literal clauses\n"); + if (option->node == NULL) { + for (i = 0; i < net1->noutputs; i++) { + if (!st_lookup(net1->hash,net1->outputs[i],&node)) { + return(0); + } + f = node->dd; + if (f == NULL) { + FREE(inames); + return(0); + } + (void) printf("*** %s ***\n", net1->outputs[i]); + result = Cudd_PrintTwoLiteralClauses(dd, f, inames, NULL); + if (result == 0) { + FREE(inames); + return(0); + } + } + } else { + if (!st_lookup(net1->hash,option->node,&node)) { + return(0); + } + f = node->dd; + if (f == NULL) { + FREE(inames); + return(0); + } + (void) printf("*** %s ***\n", option->node); + result = Cudd_PrintTwoLiteralClauses(dd, f, inames, NULL); + if (result == 0) { + FREE(inames); + return(0); + } + } + + FREE(inames); + return(1); + +} /* end of Ntr_TestTwoLiteralClauses */ + + +/**Function******************************************************************** + + Synopsis [Test char-to-vect conversion.] + + Description [Test char-to-vect conversion. Returns 1 if successful; + 0 otherwise.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +int +Ntr_TestCharToVect( + DdManager * dd, + BnetNetwork * net1, + NtrOptions * option) +{ + DdNode *f; + int result; + BnetNode *node; + int i; + + if (option->char2vect == FALSE) return(1); + + (void) printf("Testing char-to-vect\n"); + if (net1->nlatches > 0) { + NtrPartTR *T; + T = Ntr_buildTR(dd,net1,option,NTR_IMAGE_MONO); + result = ntrTestCharToVect(dd,T->part[0],option); + Ntr_freeTR(dd,T); + } else if (option->node == NULL) { + result = 1; + for (i = 0; i < net1->noutputs; i++) { + if (!st_lookup(net1->hash,net1->outputs[i],&node)) { + return(0); + } + f = node->dd; + if (f == NULL) return(0); + (void) printf("*** %s ***\n", net1->outputs[i]); + result = ntrTestCharToVect(dd,f,option); + if (result == 0) return(0); + } + } else { + if (!st_lookup(net1->hash,option->node,&node)) { + return(0); + } + f = node->dd; + if (f == NULL) return(0); + result = ntrTestCharToVect(dd,f,option); + } + return(result); + +} /* end of Ntr_TestCharToVect */ + + +/*---------------------------------------------------------------------------*/ +/* Definition of internal functions */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Definition of static functions */ +/*---------------------------------------------------------------------------*/ + + +/**Function******************************************************************** + + Synopsis [Processes one BDD for Ntr_TestMinimization.] + + Description [Processes one BDD for Ntr_TestMinimization. + Returns 1 if successful; 0 otherwise.] + + SideEffects [None] + + SeeAlso [Ntr_TestMinimization] + +******************************************************************************/ +static int +ntrTestMinimizationAux( + DdManager * dd, + BnetNetwork * net1, + DdNode * f, + char * name, + DdNode * c, + char * cname, + NtrOptions * option) +{ + DdNode *com1, *com0, *min1, *min0, *sq1, *sq0; + DdNode *rs1, *rs0, *cs1, *cs0, *na1, *na0, *a1, *a0; + DdNode *g, *u1, *l1, *u0, *l0; + int pr, nvars; + int sizeF, sizeMin1, sizeMin0, sizeSq1, sizeSq0, sizeCom1, sizeCom0; + int sizeRs1, sizeRs0, sizeCs1, sizeCs0, sizeNa1, sizeNa0, sizeA1, sizeA0; + static char *onames[11]; + DdNode *outputs[11]; + DdNode *fc[2]; + + pr = option->verb; + fc[0] = f; fc[1] = c; + nvars = Cudd_VectorSupportSize(dd,fc,2); + if (nvars == CUDD_OUT_OF_MEM) return(0); + (void) printf("TEST-MINI:: %s\n", name); + (void) printf("T-M "); + Cudd_PrintDebug(dd, f, nvars, pr); + sizeF = Cudd_DagSize(f); + + /* Compute positive generalized cofactor. */ + com1 = Cudd_bddLICompaction(dd, f, c); + if (com1 == NULL) { + (void) printf("TEST-MINI: LI-compaction failed (1).\n"); + return(0); + } + Cudd_Ref(com1); + (void) printf("T-M L1 "); + Cudd_PrintDebug(dd, com1, nvars, pr); + sizeCom1 = Cudd_DagSize(com1); + if (sizeCom1 > sizeF) { + (void) printf("TEST-MINI: LI-compaction not safe (1).\n"); + return(0); + } + min1 = Cudd_bddMinimize(dd, f, c); + if (min1 == NULL) { + (void) printf("TEST-MINI: minimize failed (1).\n"); + return(0); + } + Cudd_Ref(min1); + (void) printf("T-M M1 "); + Cudd_PrintDebug(dd, min1, nvars, pr); + sizeMin1 = Cudd_DagSize(min1); + if (sizeMin1 > sizeF) { + (void) printf("TEST-MINI: minimize not safe (1).\n"); + return(0); + } + rs1 = Cudd_bddRestrict(dd, f, c); + if (rs1 == NULL) { + (void) printf("TEST-MINI: restrict failed (1).\n"); + return(0); + } + Cudd_Ref(rs1); + (void) printf("T-M R1 "); + Cudd_PrintDebug(dd, rs1, nvars, pr); + sizeRs1 = Cudd_DagSize(rs1); + cs1 = Cudd_bddConstrain(dd, f, c); + if (cs1 == NULL) { + (void) printf("TEST-MINI: constrain failed (1).\n"); + return(0); + } + Cudd_Ref(cs1); + (void) printf("T-M C1 "); + Cudd_PrintDebug(dd, cs1, nvars, pr); + sizeCs1 = Cudd_DagSize(cs1); + l1 = Cudd_bddAnd(dd, f, c); + if (l1 == NULL) { + (void) printf("TEST-MINI: lower bound failed (1).\n"); + return(0); + } + Cudd_Ref(l1); + u1 = Cudd_bddOr(dd, f, Cudd_Not(c)); + if (u1 == NULL) { + (void) printf("TEST-MINI: upper bound failed (1).\n"); + return(0); + } + Cudd_Ref(u1); + (void) printf("TEST-MINI: (lb,ub) : (%d,%d) nodes\n", + Cudd_DagSize(l1), Cudd_DagSize(u1)); + sq1 = Cudd_bddSqueeze(dd, l1, u1); + if (sq1 == NULL) { + (void) printf("TEST-MINI: squeezing failed (1).\n"); + return(0); + } + Cudd_Ref(sq1); + sizeSq1 = Cudd_DagSize(sq1); + if (sizeSq1 > sizeF) { + Cudd_RecursiveDeref(dd,sq1); + sq1 = f; + Cudd_Ref(sq1); + sizeSq1 = sizeF; + } + (void) printf("T-M S1 "); + Cudd_PrintDebug(dd, sq1, nvars, pr); + na1 = Cudd_bddNPAnd(dd, f, c); + if (na1 == NULL) { + (void) printf("TEST-MINI: NPand failed (1).\n"); + return(0); + } + Cudd_Ref(na1); + (void) printf("T-M N1 "); + Cudd_PrintDebug(dd, na1, nvars, pr); + sizeNa1 = Cudd_DagSize(na1); + a1 = Cudd_bddAnd(dd, f, c); + if (a1 == NULL) { + (void) printf("TEST-MINI: and failed (1).\n"); + return(0); + } + Cudd_Ref(a1); + (void) printf("T-M A1 "); + Cudd_PrintDebug(dd, a1, nvars, pr); + sizeA1 = Cudd_DagSize(a1); + (void) printf("TEST-MINI: f %d comp %d mini %d rest %d cons %d sque %d na %d and %d\n", + sizeF, sizeCom1, sizeMin1, sizeRs1, sizeCs1, sizeSq1, sizeNa1, sizeA1); + if (option->bdddump) { + onames[0] = name; outputs[0] = f; + onames[1] = cname; outputs[1] = c; + onames[2] = (char *) "cons"; outputs[2] = cs1; + onames[3] = (char *) "rest"; outputs[3] = rs1; + onames[4] = (char *) "comp"; outputs[4] = com1; + onames[5] = (char *) "mini"; outputs[5] = min1; + onames[6] = (char *) "sqee"; outputs[6] = sq1; + onames[7] = (char *) "lb"; outputs[7] = l1; + onames[8] = (char *) "ub"; outputs[8] = u1; + onames[9] = (char *) "na"; outputs[9] = na1; + onames[10] = (char *) "and"; outputs[10] = a1; + if (!Bnet_bddArrayDump(dd, net1, option->dumpfile, outputs, onames, + 11, option->dumpFmt)) + return(0); + } + Cudd_RecursiveDeref(dd,l1); + Cudd_RecursiveDeref(dd,u1); + + /* Compute negative generalized cofactor. */ + (void) printf("TEST-MINI:: %s\n", name); + (void) printf("T-M "); + Cudd_PrintDebug(dd, f, nvars, pr); + + com0 = Cudd_bddLICompaction(dd, f, Cudd_Not(c)); + if (com0 == NULL) { + (void) printf("TEST-MINI: LI-compaction failed (2).\n"); + return(0); + } + Cudd_Ref(com0); + (void) printf("T-M L0 "); + Cudd_PrintDebug(dd, com0, nvars, pr); + sizeCom0 = Cudd_DagSize(com0); + if (sizeCom0 > sizeF) { + (void) printf("TEST-MINI: LI-compaction not safe (2).\n"); + return(0); + } + min0 = Cudd_bddMinimize(dd, f, Cudd_Not(c)); + if (min0 == NULL) { + (void) printf("TEST-MINI: minimize failed (2).\n"); + return(0); + } + Cudd_Ref(min0); + (void) printf("T-M M0 "); + Cudd_PrintDebug(dd, min0, nvars, pr); + sizeMin0 = Cudd_DagSize(min0); + if (sizeMin0 > sizeF) { + (void) printf("TEST-MINI: minimize not safe (2).\n"); + return(0); + } + rs0 = Cudd_bddRestrict(dd, f, Cudd_Not(c)); + if (rs0 == NULL) { + (void) printf("TEST-MINI: restrict failed (2).\n"); + return(0); + } + Cudd_Ref(rs0); + (void) printf("T-M R0 "); + Cudd_PrintDebug(dd, rs0, nvars, pr); + sizeRs0 = Cudd_DagSize(rs0); + cs0 = Cudd_bddConstrain(dd, f, Cudd_Not(c)); + if (cs0 == NULL) { + (void) printf("TEST-MINI: constrain failed (2).\n"); + return(0); + } + Cudd_Ref(cs0); + (void) printf("T-M C0 "); + Cudd_PrintDebug(dd, cs0, nvars, pr); + sizeCs0 = Cudd_DagSize(cs0); + + l0 = Cudd_bddAnd(dd, f, Cudd_Not(c)); + if (l0 == NULL) { + (void) printf("TEST-MINI: lower bound failed (2).\n"); + return(0); + } + Cudd_Ref(l0); + u0 = Cudd_bddOr(dd, f, c); + if (u0 == NULL) { + (void) printf("TEST-MINI: upper bound failed (2).\n"); + return(0); + } + Cudd_Ref(u0); + (void) printf("TEST-MINI: (lb,ub) : (%d,%d) nodes\n", + Cudd_DagSize(l0), Cudd_DagSize(u0)); + sq0 = Cudd_bddSqueeze(dd, l0, u0); + if (sq0 == NULL) { + (void) printf("TEST-MINI: squeezing failed (2).\n"); + return(0); + } + Cudd_Ref(sq0); + Cudd_RecursiveDeref(dd,l0); + Cudd_RecursiveDeref(dd,u0); + sizeSq0 = Cudd_DagSize(sq0); + if (sizeSq0 > sizeF) { + Cudd_RecursiveDeref(dd,sq0); + sq0 = f; + Cudd_Ref(sq0); + sizeSq0 = sizeF; + } + (void) printf("T-M S0 "); + Cudd_PrintDebug(dd, sq0, nvars, pr); + na0 = Cudd_bddNPAnd(dd, f, Cudd_Not(c)); + if (na0 == NULL) { + (void) printf("TEST-MINI: NPand failed (2).\n"); + return(0); + } + Cudd_Ref(na0); + (void) printf("T-M N0 "); + Cudd_PrintDebug(dd, na0, nvars, pr); + sizeNa0 = Cudd_DagSize(na0); + a0 = Cudd_bddAnd(dd, f, Cudd_Not(c)); + if (a0 == NULL) { + (void) printf("TEST-MINI: and failed (2).\n"); + return(0); + } + Cudd_Ref(a0); + (void) printf("T-M A0 "); + Cudd_PrintDebug(dd, a0, nvars, pr); + sizeA0 = Cudd_DagSize(a0); + (void) printf("TEST-MINI: f %d comp %d mini %d rest %d cons %d sque %d na %d, and %d\n", + sizeF, sizeCom0, sizeMin0, sizeRs0, sizeCs0, sizeSq0, sizeNa0, sizeA0); + + /* Check fundamental identity. */ + g = Cudd_bddIte(dd,c,com1,com0); + if (g == NULL) { + (void) printf("TEST-MINI: LI-compaction failed (3).\n"); + return(0); + } + Cudd_Ref(g); + if (g != f) { + (void) printf("TEST-MINI: LI-compaction failed (4).\n"); + return(0); + } + Cudd_RecursiveDeref(dd,com1); + Cudd_RecursiveDeref(dd,com0); + Cudd_RecursiveDeref(dd,g); + g = Cudd_bddIte(dd,c,min1,min0); + if (g == NULL) { + (void) printf("TEST-MINI: minimize failed (3).\n"); + return(0); + } + Cudd_Ref(g); + if (g != f) { + (void) printf("TEST-MINI: minimize failed (4).\n"); + return(0); + } + Cudd_RecursiveDeref(dd,min1); + Cudd_RecursiveDeref(dd,min0); + Cudd_RecursiveDeref(dd,g); + g = Cudd_bddIte(dd,c,sq1,sq0); + if (g == NULL) { + (void) printf("TEST-MINI: squeezing failed (3).\n"); + return(0); + } + Cudd_Ref(g); + if (g != f) { + (void) printf("TEST-MINI: squeezing failed (4).\n"); + return(0); + } + Cudd_RecursiveDeref(dd,sq1); + Cudd_RecursiveDeref(dd,sq0); + Cudd_RecursiveDeref(dd,g); + g = Cudd_bddIte(dd,c,rs1,rs0); + if (g == NULL) { + (void) printf("TEST-MINI: restrict failed (3).\n"); + return(0); + } + Cudd_Ref(g); + if (g != f) { + (void) printf("TEST-MINI: restrict failed (4).\n"); + return(0); + } + Cudd_RecursiveDeref(dd,rs1); + Cudd_RecursiveDeref(dd,rs0); + Cudd_RecursiveDeref(dd,g); + g = Cudd_bddIte(dd,c,cs1,cs0); + if (g == NULL) { + (void) printf("TEST-MINI: constrain failed (3).\n"); + return(0); + } + Cudd_Ref(g); + if (g != f) { + (void) printf("TEST-MINI: constrain failed (4).\n"); + return(0); + } + Cudd_RecursiveDeref(dd,cs1); + Cudd_RecursiveDeref(dd,cs0); + Cudd_RecursiveDeref(dd,g); + g = Cudd_bddIte(dd,c,na1,na0); + if (g == NULL) { + (void) printf("TEST-MINI: NPand failed (3).\n"); + return(0); + } + Cudd_Ref(g); + if (g != f) { + (void) printf("TEST-MINI: NPand failed (4).\n"); + return(0); + } + Cudd_RecursiveDeref(dd,na1); + Cudd_RecursiveDeref(dd,na0); + Cudd_RecursiveDeref(dd,g); + g = Cudd_bddIte(dd,c,a1,a0); + if (g == NULL) { + (void) printf("TEST-MINI: and failed (3).\n"); + return(0); + } + Cudd_Ref(g); + if (g != f) { + (void) printf("TEST-MINI: and failed (4).\n"); + return(0); + } + Cudd_RecursiveDeref(dd,a1); + Cudd_RecursiveDeref(dd,a0); + Cudd_RecursiveDeref(dd,g); + + return(1); + +} /* end of ntrTestMinimizationAux */ + + +/**Function******************************************************************** + + Synopsis [Processes one BDD for Ntr_TestDensity.] + + Description [Processes one BDD for Ntr_TestDensity. Returns 1 if + successful; 0 otherwise.] + + SideEffects [None] + + SeeAlso [Ntr_TestDensity ntrCompress1] + +******************************************************************************/ +static int +ntrTestDensityAux( + DdManager * dd, + BnetNetwork * net, + DdNode * f, + char * name, + NtrOptions * option) +{ + DdNode *s, *b, *hb, *sp, *ua, *c1, *c2; + int pr; + int result; + int nvars; + int size, sizeS; + double densityF, densityB, densityS, densityHB, densitySP, densityUA; + double densityC1, densityC2; + char *onames[8]; + DdNode *outputs[8]; + + result = 1; + pr = option->verb; + nvars = Cudd_SupportSize(dd,f); + if (nvars == CUDD_OUT_OF_MEM) return(0); + densityF = Cudd_Density(dd,f,nvars); + (void) printf("TEST-DENSITY:: %s (%d variables)\n", name, nvars); + if (pr > 0) { + (void) printf("T-D (%g)", densityF); + Cudd_PrintDebug(dd, f, nvars, pr); + (void) printf("T-D APA "); + if (!Cudd_ApaPrintMinterm(stdout, dd, f, nvars)) + result = 0; + } + /* Test remapping underapproximation. */ + /* s = Cudd_SubsetRemap(dd,f); */ + s = Cudd_RemapUnderApprox(dd,f,nvars,0,option->quality); + if (s == NULL) { + (void) printf("TEST-DENSITY: computation failed\n"); + return(0); + } + Cudd_Ref(s); + sizeS = Cudd_DagSize(s); + densityS = Cudd_Density(dd,s,nvars); + if (pr > 0) { + (void) printf("T-D ID (%g)", densityS); + Cudd_PrintDebug(dd, s, nvars, pr); + } + if (!Cudd_bddLeq(dd,s,f)) { + (void) printf("TEST-DENSITY: result not a subset\n"); + result = 0; + } + if (densityF > densityS) { + (void) printf("TEST-DENSITY: result less dense\n"); + /* result = 0; */ + } + size = sizeS; + /* Test biased underapproximation. */ + b = Cudd_BiasedUnderApprox(dd,f,Cudd_Not(s),nvars,0, + option->quality*1.1,option->quality*0.5); + if (b == NULL) { + (void) printf("TEST-DENSITY: computation failed\n"); + return(0); + } + Cudd_Ref(b); + densityB = Cudd_Density(dd,b,nvars); + if (pr > 0) { + (void) printf("T-D BU (%g)", densityB); + Cudd_PrintDebug(dd, b, nvars, pr); + } + if (!Cudd_bddLeq(dd,b,f)) { + (void) printf("TEST-DENSITY: result not a subset\n"); + result = 0; + } + if (densityF > densityB) { + (void) printf("TEST-DENSITY: result less dense\n"); + /* result = 0; */ + } + /* Test heavy-branch subsetting. */ + hb = Cudd_SubsetHeavyBranch(dd, f, nvars, size); + if (hb == NULL) { + (void) printf("TEST-DENSITY: HB computation failed\n"); + Cudd_RecursiveDeref(dd,s); + return(0); + } + Cudd_Ref(hb); + densityHB = Cudd_Density(dd,hb,nvars); + if (pr > 0) { + (void) printf("T-D HB (%g)", densityHB); + Cudd_PrintDebug(dd, hb, nvars, pr); + } + if (!Cudd_bddLeq(dd,hb,f)) { + (void) printf("TEST-DENSITY: HB not a subset\n"); + result = 0; + } + /* Test short paths subsetting. */ + sp = Cudd_SubsetShortPaths(dd, f, nvars, size, 0); + if (sp == NULL) { + (void) printf("TEST-DENSITY: SP computation failed\n"); + Cudd_RecursiveDeref(dd,s); + Cudd_RecursiveDeref(dd,hb); + return(0); + } + Cudd_Ref(sp); + densitySP = Cudd_Density(dd,sp,nvars); + if (pr > 0) { + (void) printf("T-D SP (%g)", densitySP); + Cudd_PrintDebug(dd, sp, nvars, pr); + } + if (!Cudd_bddLeq(dd,sp,f)) { + (void) printf("TEST-DENSITY: SP not a subset\n"); + result = 0; + } + /* Test underapproximation. */ + ua = Cudd_UnderApprox(dd,f,nvars,0,FALSE,option->quality); + if (ua == NULL) { + (void) printf("TEST-DENSITY: computation failed\n"); + Cudd_RecursiveDeref(dd,s); + Cudd_RecursiveDeref(dd,hb); + Cudd_RecursiveDeref(dd,sp); + return(0); + } + Cudd_Ref(ua); + densityUA = Cudd_Density(dd,ua,nvars); + if (pr > 0) { + (void) printf("T-D UA (%g)", densityUA); + Cudd_PrintDebug(dd, ua, nvars, pr); + } + if (!Cudd_bddLeq(dd,ua,f)) { + (void) printf("TEST-DENSITY: result not a subset\n"); + result = 0; + } + if (densityF > densityUA) { + (void) printf("TEST-DENSITY: result less dense\n"); + } + /* Test compress 2 method. */ + c1 = ntrCompress2(dd, f, nvars, size); + if (c1 == NULL) { + (void) printf("TEST-DENSITY: C1 computation failed\n"); + Cudd_RecursiveDeref(dd,s); + Cudd_RecursiveDeref(dd,hb); + Cudd_RecursiveDeref(dd,sp); + Cudd_RecursiveDeref(dd,ua); + return(0); + } + densityC1 = Cudd_Density(dd,c1,nvars); + if (pr > 0) { + (void) printf("T-D C1 (%g)", densityC1); + Cudd_PrintDebug(dd, c1, nvars, pr); + } + if (!Cudd_bddLeq(dd,c1,f)) { + (void) printf("TEST-DENSITY: C1 not a subset\n"); + result = 0; + } + /* Test compress subsetting. */ + c2 = Cudd_SubsetCompress(dd, f, nvars, size); + if (c2 == NULL) { + (void) printf("TEST-DENSITY: C2 computation failed\n"); + Cudd_RecursiveDeref(dd,s); + Cudd_RecursiveDeref(dd,hb); + Cudd_RecursiveDeref(dd,sp); + Cudd_RecursiveDeref(dd,ua); + Cudd_RecursiveDeref(dd,c1); + return(0); + } + Cudd_Ref(c2); + densityC2 = Cudd_Density(dd,c2,nvars); + if (pr > 0) { + (void) printf("T-D C2 (%g)", densityC2); + Cudd_PrintDebug(dd, c2, nvars, pr); + } + if (!Cudd_bddLeq(dd,c2,f)) { + (void) printf("TEST-DENSITY: C2 not a subset\n"); + result = 0; + } + /* Dump results if so requested. */ + if (option->bdddump) { + onames[0] = name; outputs[0] = f; + onames[1] = (char *) "id"; outputs[1] = s; + onames[2] = (char *) "bu"; outputs[2] = b; + onames[3] = (char *) "hb"; outputs[3] = hb; + onames[4] = (char *) "sp"; outputs[4] = sp; + onames[5] = (char *) "ua"; outputs[5] = ua; + onames[6] = (char *) "c1"; outputs[6] = c1; + onames[7] = (char *) "c2"; outputs[7] = c2; + result &= Bnet_bddArrayDump(dd, net, option->dumpfile, outputs, + onames, 8, option->dumpFmt); + } + + Cudd_RecursiveDeref(dd,s); + Cudd_RecursiveDeref(dd,b); + Cudd_RecursiveDeref(dd,hb); + Cudd_RecursiveDeref(dd,sp); + Cudd_RecursiveDeref(dd,ua); + Cudd_RecursiveDeref(dd,c1); + Cudd_RecursiveDeref(dd,c2); + + return(result); + +} /* end of ntrTestDensityAux */ + + +/**Function******************************************************************** + + Synopsis [Processes one BDD for Ntr_TestDecomp.] + + Description [Processes one BDD for Ntr_TestDecomp. Returns 1 if + successful; 0 otherwise.] + + SideEffects [None] + + SeeAlso [Ntr_TestDecomp] + +******************************************************************************/ +static int +ntrTestDecompAux( + DdManager * dd, + BnetNetwork * net, + DdNode * f, + char * name, + NtrOptions * option) +{ + DdNode *one, *g, *h, *product; + DdNode **A, **I, **G, **V; + int pr; + int i, result; + int nA, nI, nG, nV; + int nvars; + int sizeSa; + int sizeSi, sizeSg, sizeSv; + char *onames[9]; + DdNode *outputs[9]; + + result = 1; + pr = option->verb; + nvars = Cudd_SupportSize(dd,f); + if (nvars == CUDD_OUT_OF_MEM) return(0); + (void) printf("TEST-DECOMP:: %s (%d variables)\n", name, nvars); + if (pr > 0) { + (void) printf("T-d "); + Cudd_PrintDebug(dd, f, nvars, pr); + } + one = Cudd_ReadOne(dd); + + /* Test Cudd_bddApproxConjDecomp */ + nA = Cudd_bddApproxConjDecomp(dd,f,&A); + if (nA == 0) { + (void) printf("TEST-DECOMP: computation failed\n"); + return(0); + } + g = A[0]; + h = (nA == 2) ? A[1] : one; + sizeSa = Cudd_SharingSize(A,nA); + if (pr > 0) { + (void) printf("T-d SS : %d nodes\n", sizeSa); + (void) printf("T-d GS "); + Cudd_PrintDebug(dd, g, nvars, pr); + (void) printf("T-d HS "); + Cudd_PrintDebug(dd, h, nvars, pr); + } + product = Cudd_bddAnd(dd,g,h); + if (product == NULL) { + (void) printf("TEST-DECOMP: computation failed\n"); + return(0); + } + Cudd_Ref(product); + if (product != f) { + (void) printf("TEST-DECOMP: result not a decomposition\n"); + result = 0; + } + Cudd_RecursiveDeref(dd,product); + + /* Test Cudd_bddIterConjDecomp */ + nI = Cudd_bddIterConjDecomp(dd,f,&I); + if (nI == 0) { + (void) printf("TEST-DECOMP: computation failed\n"); + return(0); + } + g = I[0]; + h = (nI == 2) ? I[1] : one; + sizeSi = Cudd_SharingSize(I,nI); + if (pr > 0) { + (void) printf("T-d SI : %d nodes\n", sizeSi); + (void) printf("T-d GI "); + Cudd_PrintDebug(dd, g, nvars, pr); + (void) printf("T-d HI "); + Cudd_PrintDebug(dd, h, nvars, pr); + } + product = Cudd_bddAnd(dd,g,h); + if (product == NULL) { + (void) printf("TEST-DECOMP: computation failed\n"); + return(0); + } + Cudd_Ref(product); + if (product != f) { + (void) printf("TEST-DECOMP: result not a decomposition\n"); + result = 0; + } + Cudd_RecursiveDeref(dd,product); + + /* Test Cudd_bddGenConjDecomp */ + nG = Cudd_bddGenConjDecomp(dd,f,&G); + if (nG == 0) { + (void) printf("TEST-DECOMP: computation failed\n"); + return(0); + } + g = G[0]; + h = (nG == 2) ? G[1] : one; + sizeSg = Cudd_SharingSize(G,nG); + if (pr > 0) { + (void) printf("T-d SD : %d nodes\n", sizeSg); + (void) printf("T-d GD "); + Cudd_PrintDebug(dd, g, nvars, pr); + (void) printf("T-d HD "); + Cudd_PrintDebug(dd, h, nvars, pr); + } + product = Cudd_bddAnd(dd,g,h); + if (product == NULL) { + (void) printf("TEST-DECOMP: computation failed\n"); + return(0); + } + Cudd_Ref(product); + if (product != f) { + (void) printf("TEST-DECOMP: result not a decomposition\n"); + result = 0; + } + Cudd_RecursiveDeref(dd,product); + + /* Test Cudd_bddVarConjDecomp */ + nV = Cudd_bddVarConjDecomp(dd,f,&V); + if (nV == 0) { + (void) printf("TEST-DECOMP: computation failed\n"); + return(0); + } + g = V[0]; + h = (nV == 2) ? V[1] : one; + sizeSv = Cudd_SharingSize(V,nV); + if (pr > 0) { + (void) printf("T-d SQ : %d nodes\n", sizeSv); + (void) printf("T-d GQ "); + Cudd_PrintDebug(dd, g, nvars, pr); + (void) printf("T-d HQ "); + Cudd_PrintDebug(dd, h, nvars, pr); + } + product = Cudd_bddAnd(dd,g,h); + if (product == NULL) { + (void) printf("TEST-DECOMP: computation failed\n"); + return(0); + } + Cudd_Ref(product); + if (product != f) { + (void) printf("TEST-DECOMP: result not a decomposition\n"); + result = 0; + } + Cudd_RecursiveDeref(dd,product); + + /* Dump to file if requested. */ + if (option->bdddump) { + onames[0] = name; outputs[0] = f; + onames[1] = (char *) "ga"; outputs[1] = A[0]; + onames[2] = (char *) "ha"; outputs[2] = (nA == 2) ? A[1] : one; + onames[3] = (char *) "gi"; outputs[3] = I[0]; + onames[4] = (char *) "hi"; outputs[4] = (nI == 2) ? I[1] : one; + onames[5] = (char *) "gg"; outputs[5] = G[0]; + onames[6] = (char *) "hg"; outputs[6] = (nG == 2) ? G[1] : one; + onames[7] = (char *) "gv"; outputs[7] = V[0]; + onames[8] = (char *) "hv"; outputs[8] = (nV == 2) ? V[1] : one; + result &= Bnet_bddArrayDump(dd, net, option->dumpfile, outputs, + onames, 9, option->dumpFmt); + } + + /* Clean up. */ + for (i = 0; i < nA; i++) { + Cudd_RecursiveDeref(dd,A[i]); + } + for (i = 0; i < nI; i++) { + Cudd_RecursiveDeref(dd,I[i]); + } + for (i = 0; i < nG; i++) { + Cudd_RecursiveDeref(dd,G[i]); + } + for (i = 0; i < nV; i++) { + Cudd_RecursiveDeref(dd,V[i]); + } + FREE(A); + FREE(I); + FREE(G); + FREE(V); + + return(result); + +} /* end of ntrTestDecompAux */ + + +/**Function******************************************************************** + + Synopsis [Processes one BDD for Ntr_TestCofactorEstimate.] + + Description [Processes one BDD for Ntr_TestCofactorEstimate. Returns 1 if + successful; 0 otherwise.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +static int +ntrTestCofEstAux( + DdManager * dd, + BnetNetwork * net, + DdNode * f, + char * name, + NtrOptions * option) +{ + DdNode *support, *scan, *cof; + int pr; + int nvars; + int exactSize, estimate, estimateS; + int totalExactSize = 0; + int totalEstimate = 0; + int totalEstimateS = 0; + int largestError = -1; + int largestErrorS = -1; + DdNode *errorVar = NULL; + + pr = option->verb; + support = Cudd_Support(dd,f); + if (support == NULL) return(0); + Cudd_Ref(support); + nvars = Cudd_DagSize(support) - 1; + scan = support; + while (!Cudd_IsConstant(scan)) { + DdNode *var = Cudd_bddIthVar(dd,scan->index); + cof = Cudd_Cofactor(dd,f,var); + if (cof == NULL) return(0); + Cudd_Ref(cof); + exactSize = Cudd_DagSize(cof); + totalExactSize += exactSize; + estimate = Cudd_EstimateCofactor(dd,f,scan->index,1); + totalEstimate += estimate; + if (estimate < exactSize) + (void) printf("Optimistic estimate!\n"); + if (estimate - exactSize > largestError) { + largestError = estimate - exactSize; + errorVar = var; + } + estimateS = Cudd_EstimateCofactorSimple(f,scan->index); + totalEstimateS += estimateS; + if (estimateS < exactSize) + (void) printf("Optimistic estimateS!\n"); + if (estimateS - exactSize > largestErrorS) + largestErrorS = estimateS - exactSize; + Cudd_RecursiveDeref(dd,cof); + scan = cuddT(scan); + } + Cudd_RecursiveDeref(dd,support); + (void) printf("TEST-COF:: %s (%d vars)", name, nvars); + Cudd_PrintDebug(dd, f, nvars, pr); + (void) printf("T-c : %d\n", totalExactSize); + (void) printf("T-c E : %d %d\n", totalEstimate, largestError); + (void) printf("T-c S : %d %d\n", totalEstimateS, largestErrorS); + + /* Dump to file if requested. */ + if (option->bdddump) { + char *onames[3]; + DdNode *outputs[3]; + int result; + cof = Cudd_Cofactor(dd,f,errorVar); + if (cof == NULL) return(0); + Cudd_Ref(cof); + onames[0] = name; outputs[0] = f; + onames[1] = (char *) "var"; outputs[1] = errorVar; + onames[2] = (char *) "cof"; outputs[2] = cof; + result = Bnet_bddArrayDump(dd, net, option->dumpfile, outputs, + onames, 3, option->dumpFmt); + Cudd_RecursiveDeref(dd,cof); + if (result == 0) return(0); + } + + return(1); + +} /* end of ntrTestCofEstAux */ + + +/**Function******************************************************************** + + Synopsis [Processes one BDD for Ntr_TestClipping.] + + Description [Processes one BDD for Ntr_TestClipping. It checks whether + clipping was correct. Returns 1 if successful; 0 otherwise.] + + SideEffects [None] + + SeeAlso [Ntr_TestClipping] + +******************************************************************************/ +static int +ntrTestClippingAux( + DdManager * dd, + BnetNetwork * net1, + DdNode * f, + char * name, + DdNode * g, + char * gname, + NtrOptions * option) +{ + DdNode *prod, *sub, *sup; + DdNode *subF, *subG, *psub; + DdNode *supF, *supG, *psup; + int pr, nvars, depth; + int sizeProd, sizeSub, sizeSup; + static char *onames[7]; + DdNode *outputs[7]; + DdNode *operands[2]; + int retval = 1; + int threshold = (option->threshold < 0) ? 0 : option->threshold; + + pr = option->verb; + operands[0] = f; operands[1] = g; + nvars = Cudd_VectorSupportSize(dd,operands,2); + if (nvars == CUDD_OUT_OF_MEM) return(0); + depth = (int) ((double) nvars * option->clip); + (void) printf("TEST-CLIP:: %s depth = %d\n", name, depth); + (void) printf("T-C "); + Cudd_PrintDebug(dd, f, nvars, pr); + + /* Compute product. */ + prod = Cudd_bddAnd(dd, f, g); + if (prod == NULL) { + (void) printf("TEST-CLIP: product failed.\n"); + return(0); + } + Cudd_Ref(prod); + (void) printf("T-C P= "); + Cudd_PrintDebug(dd, prod, nvars, pr); + sizeProd = Cudd_DagSize(prod); + + /* Compute subset of product. */ + sub = Cudd_bddClippingAnd(dd, f, g, depth, 0); + if (sub == NULL) { + (void) printf("TEST-CLIP: subsetting product failed.\n"); + return(0); + } + Cudd_Ref(sub); + (void) printf("T-C P- "); + Cudd_PrintDebug(dd, sub, nvars, pr); + sizeSub = Cudd_DagSize(sub); + if (sizeSub > sizeProd) { + (void) printf("TEST-CLIP: subsetting product not safe.\n"); + } + + /* Compute product of subsets. */ + subF = Cudd_RemapUnderApprox(dd,f,nvars,threshold,option->quality); + if (subF == NULL) { + (void) printf("TEST-CLIP: subsetting of f failed.\n"); + return(0); + } + Cudd_Ref(subF); + subG = Cudd_RemapUnderApprox(dd,g,nvars,threshold,option->quality); + if (subF == NULL) { + (void) printf("TEST-CLIP: subsetting of g failed.\n"); + return(0); + } + Cudd_Ref(subG); + psub = Cudd_bddAnd(dd,subF,subG); + if (psub == NULL) { + (void) printf("TEST-CLIP: product of subsets failed.\n"); + return(0); + } + Cudd_Ref(psub); + Cudd_RecursiveDeref(dd,subF); + Cudd_RecursiveDeref(dd,subG); + (void) printf("T-C P< "); + Cudd_PrintDebug(dd, psub, nvars, pr); + + /* Compute superset of product. */ + sup = Cudd_bddClippingAnd(dd, f, g, depth, 1); + if (sup == NULL) { + (void) printf("TEST-CLIP: supersetting product failed.\n"); + return(0); + } + Cudd_Ref(sup); + (void) printf("T-C P+ "); + Cudd_PrintDebug(dd, sup, nvars, pr); + sizeSup = Cudd_DagSize(sup); + if (sizeSup > sizeProd) { + (void) printf("TEST-CLIP: supersetting product not safe.\n"); + } + + /* Compute product of supersets. */ + supF = Cudd_RemapOverApprox(dd,f,nvars,threshold,option->quality); + if (supF == NULL) { + (void) printf("TEST-CLIP: supersetting of f failed.\n"); + return(0); + } + Cudd_Ref(supF); + supG = Cudd_RemapOverApprox(dd,g,nvars,threshold,option->quality); + if (supF == NULL) { + (void) printf("TEST-CLIP: supersetting of g failed.\n"); + return(0); + } + Cudd_Ref(supG); + psup = Cudd_bddAnd(dd,supF,supG); + if (psup == NULL) { + (void) printf("TEST-CLIP: product of supersets failed.\n"); + return(0); + } + Cudd_Ref(psup); + Cudd_RecursiveDeref(dd,supF); + Cudd_RecursiveDeref(dd,supG); + (void) printf("T-C P> "); + Cudd_PrintDebug(dd, psup, nvars, pr); + + if (option->bdddump) { + onames[0] = name; outputs[0] = f; + onames[1] = gname; outputs[1] = g; + onames[2] = (char *) "prod"; outputs[2] = prod; + onames[3] = (char *) "sub"; outputs[3] = sub; + onames[4] = (char *) "sup"; outputs[4] = sup; + onames[5] = (char *) "psub"; outputs[5] = psub; + onames[6] = (char *) "psup"; outputs[6] = psup; + retval &= Bnet_bddArrayDump(dd, net1, option->dumpfile, outputs, + onames, 7, option->dumpFmt); + } + + /* Check correctness. */ + if (!Cudd_bddLeq(dd,sub,prod)) { + (void) printf("TEST-CLIP: subsetting product not a subset.\n"); + return(0); + } + if (!Cudd_bddLeq(dd,prod,sup)) { + (void) printf("TEST-CLIP: supersetting product not a superset.\n"); + return(0); + } + if (!Cudd_bddLeq(dd,psub,prod)) { + (void) printf("TEST-CLIP: product of subsets not a subset.\n"); + return(0); + } + if (!Cudd_bddLeq(dd,prod,psup)) { + (void) printf("TEST-CLIP: product of supersets not a superset.\n"); + return(0); + } + + Cudd_RecursiveDeref(dd,prod); + Cudd_RecursiveDeref(dd,sub); + Cudd_RecursiveDeref(dd,sup); + Cudd_RecursiveDeref(dd,psub); + Cudd_RecursiveDeref(dd,psup); + + return(retval); + +} /* end of ntrTestClippingAux */ + + + +/**Function******************************************************************** + + Synopsis [Processes one triplet of BDDs for Ntr_TestEquivAndContain.] + + Description [Processes one triplet of BDDs for Ntr_TestEquivAndContain. + Returns 1 if successful; 0 otherwise.] + + SideEffects [None] + + SeeAlso [Ntr_TestEquivAndContain] + +******************************************************************************/ +static int +ntrTestEquivAndContainAux( + DdManager *dd, + BnetNetwork *net1, + DdNode *f, + char *fname, + DdNode *g, + char *gname, + DdNode *d, + char *dname, + NtrOptions *option) +{ + DdNode *xor_, *diff, *ndiff; + int pr, nvars; + int equiv, implies; + static char *onames[6]; + DdNode *outputs[6]; + DdNode *fgd[3]; + + pr = option->verb; + fgd[0] = f; fgd[1] = g; fgd[2] = d; + nvars = Cudd_VectorSupportSize(dd,fgd,3); + if (nvars == CUDD_OUT_OF_MEM) return(0); + (void) printf("TEST-DC:: %s [=<]= %s unless %s\n", fname, gname, dname); + (void) printf("T-F "); + Cudd_PrintDebug(dd, f, nvars, pr); + (void) printf("T-G "); + Cudd_PrintDebug(dd, g, nvars, pr); + (void) printf("T-D "); + Cudd_PrintDebug(dd, d, nvars, pr); + + /* Check equivalence unless don't cares. */ + xor_ = Cudd_bddXor(dd, f, g); + if (xor_ == NULL) { + (void) printf("TEST-DC: XOR computation failed (1).\n"); + return(0); + } + Cudd_Ref(xor_); + equiv = Cudd_EquivDC(dd, f, g, d); + if (equiv != Cudd_bddLeq(dd,xor_,d)) { + (void) printf("TEST-DC: EquivDC computation incorrect (1).\n"); + (void) printf(" EquivDC states that %s and %s are %s\n", + fname, gname, equiv ? "equivalent" : "not equivalent"); + (void) printf("T-X "); + Cudd_PrintDebug(dd, xor_, nvars, pr); + return(0); + } + equiv = Cudd_EquivDC(dd, f, g, Cudd_Not(d)); + if (equiv != Cudd_bddLeq(dd,xor_,Cudd_Not(d))) { + (void) printf("TEST-DC: EquivDC computation incorrect (2).\n"); + (void) printf(" EquivDC states that %s and %s are %s\n", + fname, gname, equiv ? "equivalent" : "not equivalent"); + (void) printf("T-X "); + Cudd_PrintDebug(dd, xor_, nvars, pr); + return(0); + } + equiv = Cudd_EquivDC(dd, f, Cudd_Not(g), d); + if (equiv != Cudd_bddLeq(dd,Cudd_Not(xor_),d)) { + (void) printf("TEST-DC: EquivDC computation incorrect (3).\n"); + (void) printf(" EquivDC states that %s and not %s are %s\n", + fname, gname, equiv ? "equivalent" : "not equivalent"); + (void) printf("T-X "); + Cudd_PrintDebug(dd, Cudd_Not(xor_), nvars, pr); + return(0); + } + equiv = Cudd_EquivDC(dd, f, Cudd_Not(g), Cudd_Not(d)); + if (equiv != Cudd_bddLeq(dd,d,xor_)) { + (void) printf("TEST-DC: EquivDC computation incorrect (4).\n"); + (void) printf(" EquivDC states that %s and not %s are %s\n", + fname, gname, equiv ? "equivalent" : "not equivalent"); + (void) printf("T-X "); + Cudd_PrintDebug(dd, Cudd_Not(xor_), nvars, pr); + return(0); + } + + /* Check containment unless don't cares. */ + diff = Cudd_bddAnd(dd, f, Cudd_Not(g)); + if (diff == NULL) { + (void) printf("TEST-DC: AND/NOT computation failed (1).\n"); + return(0); + } + Cudd_Ref(diff); + implies = Cudd_bddLeqUnless(dd, f, g, d); + if (implies != Cudd_bddLeq(dd,diff,d)) { + (void) printf("TEST-DC: LeqUnless computation incorrect (1).\n"); + (void) printf(" LeqUnless states that %s %s %s\n", + fname, implies ? "implies" : "does not imply", gname); + (void) printf("T-I "); + Cudd_PrintDebug(dd, diff, nvars, pr); + return(0); + } + implies = Cudd_bddLeqUnless(dd, f, g, Cudd_Not(d)); + if (implies != Cudd_bddLeq(dd,diff,Cudd_Not(d))) { + (void) printf("TEST-DC: LeqUnless computation incorrect (2).\n"); + (void) printf(" LeqUnless states that %s %s %s\n", + fname, implies ? "implies" : "does not imply", gname); + (void) printf("T-I "); + Cudd_PrintDebug(dd, diff, nvars, pr); + return(0); + } + ndiff = Cudd_bddAnd(dd, f, g); + if (ndiff == NULL) { + (void) printf("TEST-DC: AND computation failed (3).\n"); + return(0); + } + Cudd_Ref(ndiff); + implies = Cudd_bddLeqUnless(dd, f, Cudd_Not(g), d); + if (implies != Cudd_bddLeq(dd,ndiff,d)) { + (void) printf("TEST-DC: LeqUnless computation incorrect (3).\n"); + (void) printf(" LeqUnless states that %s %s not(%s)\n", + fname, implies ? "implies" : "does not imply", gname); + (void) printf("T-I "); + Cudd_PrintDebug(dd, ndiff, nvars, pr); + return(0); + } + implies = Cudd_bddLeqUnless(dd, f, Cudd_Not(g), Cudd_Not(d)); + if (implies != Cudd_bddLeq(dd,ndiff,Cudd_Not(d))) { + (void) printf("TEST-DC: LeqUnless computation incorrect (3).\n"); + (void) printf(" LeqUnless states that %s %s not(%s)\n", + fname, implies ? "implies" : "does not imply", gname); + (void) printf("T-I "); + Cudd_PrintDebug(dd, ndiff, nvars, pr); + return(0); + } + if (option->bdddump) { + onames[0] = fname; outputs[0] = f; + onames[1] = gname; outputs[1] = g; + onames[2] = dname; outputs[2] = d; + onames[3] = (char *) "xor"; outputs[3] = xor_; + onames[4] = (char *) "diff"; outputs[4] = diff; + onames[5] = (char *) "ndiff"; outputs[5] = ndiff; + if (!Bnet_bddArrayDump(dd, net1, option->dumpfile, outputs, onames, + 6, option->dumpFmt)) + return(0); + } + Cudd_RecursiveDeref(dd,xor_); + Cudd_RecursiveDeref(dd,diff); + Cudd_RecursiveDeref(dd,ndiff); + + return(1); + +} /* end of ntrTestEquivAndContainAux */ + + +/**Function******************************************************************** + + Synopsis [Processes one pair of BDDs for Ntr_TestClosestCube.] + + Description [Processes one pair of BDDs for Ntr_TestClosestCube. + Returns 1 if successful; 0 otherwise.] + + SideEffects [None] + + SeeAlso [Ntr_TestClosestCube] + +******************************************************************************/ +static int +ntrTestClosestCubeAux( + DdManager *dd, + BnetNetwork *net, + DdNode *f, + char *fname, + DdNode *g, + char *gname, + DdNode **vars, + NtrOptions *option) +{ + DdNode *cube, *cubeN; + int distance, pr, nvars; + DdNode *fg[2]; + static char *onames[4]; + DdNode *outputs[4]; + + pr = option->verb; + fg[0] = f; fg[1] = g; + nvars = Cudd_VectorSupportSize(dd,fg,2); + if (nvars == CUDD_OUT_OF_MEM) return(0); + (void) printf("TEST-CC:: H(%s, %s)\n", fname, gname); + (void) printf("T-F "); + Cudd_PrintDebug(dd, f, nvars, pr); + (void) printf("T-G "); + Cudd_PrintDebug(dd, g, nvars, pr); + + cube = Cudd_bddClosestCube(dd, f, g, &distance); + if (cube == NULL) { + (void) printf("TEST-CC: computation failed (1).\n"); + return(0); + } + Cudd_Ref(cube); + (void) printf("T-C (%d) ", distance); + Cudd_PrintDebug(dd, cube, nvars, pr); + if (distance == 0) { + if (!Cudd_bddLeq(dd,cube,g)) { + (void) printf("TEST-CC: distance-0 cube not in g (2).\n"); + return(0); + } + } + + (void) printf("T-GN "); + Cudd_PrintDebug(dd, Cudd_Not(g), nvars, pr); + cubeN = Cudd_bddClosestCube(dd, f, Cudd_Not(g), &distance); + if (cubeN == NULL) { + (void) printf("TEST-CC: computation failed (3).\n"); + return(0); + } + Cudd_Ref(cubeN); + (void) printf("T-N (%d) ", distance); + Cudd_PrintDebug(dd, cubeN, nvars, pr); + if (distance == 0) { + if (!Cudd_bddLeq(dd,cubeN,Cudd_Not(g))) { + (void) printf("TEST-CC: distance-0 cube not in not(g) (4).\n"); + return(0); + } + } else { + int d, *minterm; + int numvars = Cudd_ReadSize(dd); + DdNode *scan, *zero; + DdNode *minBdd = Cudd_bddPickOneMinterm(dd,cubeN,vars,numvars); + if (minBdd == NULL) { + (void) printf("TEST-CC: minterm selection failed (5).\n"); + return(0); + } + Cudd_Ref(minBdd); + minterm = ALLOC(int,numvars); + if (minterm == NULL) { + (void) printf("TEST-CC: allocation failed (6).\n"); + 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[Cudd_NodeReadIndex(R)] = 0; + scan = E; + } else { + minterm[Cudd_NodeReadIndex(R)] = 1; + scan = T; + } + } + Cudd_RecursiveDeref(dd,minBdd); + d = Cudd_MinHammingDist(dd,Cudd_Not(g),minterm,numvars); + FREE(minterm); + if (d != distance) { + (void) printf("TEST-CC: distance disagreement (7).\n"); + return(0); + } + } + + if (option->bdddump) { + onames[0] = fname; outputs[0] = f; + onames[1] = gname; outputs[1] = g; + onames[2] = (char *) "cube"; outputs[2] = cube; + onames[3] = (char *) "cubeN"; outputs[3] = cubeN; + if (!Bnet_bddArrayDump(dd, net, option->dumpfile, outputs, onames, + 4, option->dumpFmt)) + return(0); + } + Cudd_RecursiveDeref(dd,cube); + Cudd_RecursiveDeref(dd,cubeN); + + return(1); + +} /* end of ntrTestClosestCubeAux */ + + +/**Function******************************************************************** + + Synopsis [Processes one BDDs for Ntr_TestCharToVect.] + + Description [Processes one BDD for Ntr_TestCharToVect. + Returns 1 if successful; 0 otherwise.] + + SideEffects [None] + + SeeAlso [Ntr_TestCharToVect] + +******************************************************************************/ +static int +ntrTestCharToVect( + DdManager * dd, + DdNode * f, + NtrOptions *option) +{ + DdNode **vector; + int sharingSize; + DdNode *verify; + int pr = option->verb; + int i; + + (void) fprintf(stdout,"f"); + Cudd_PrintDebug(dd, f, Cudd_ReadSize(dd), 1); + if (pr > 1) { + Cudd_bddPrintCover(dd, f, f); + } + vector = Cudd_bddCharToVect(dd,f); + if (vector == NULL) return(0); + sharingSize = Cudd_SharingSize(vector, Cudd_ReadSize(dd)); + (void) fprintf(stdout, "Vector Size: %d components %d nodes\n", + Cudd_ReadSize(dd), sharingSize); + for (i = 0; i < Cudd_ReadSize(dd); i++) { + (void) fprintf(stdout,"v[%d]",i); + Cudd_PrintDebug(dd, vector[i], Cudd_ReadSize(dd), 1); + if (pr > 1) { + Cudd_bddPrintCover(dd, vector[i], vector[i]); + } + } + verify = Cudd_bddVectorCompose(dd,f,vector); + if (verify != Cudd_ReadOne(dd)) { + (void) fprintf(stdout, "Verification failed!\n"); + return(0); + } + Cudd_Ref(verify); + Cudd_IterDerefBdd(dd, verify); + for (i = 0; i < Cudd_ReadSize(dd); i++) { + Cudd_IterDerefBdd(dd, vector[i]); + } + FREE(vector); + return(1); + +} /* end of ntrTestCharToVect */ + + +#if 0 +/**Function******************************************************************** + + Synopsis [Try hard to squeeze a BDD.] + + Description [Try hard to squeeze a BDD. + Returns a pointer to the squeezed BDD if successful; NULL otherwise.] + + SideEffects [None] + + SeeAlso [ntrTestDensityAux Cudd_SubsetCompress] + +******************************************************************************/ +static DdNode * +ntrCompress1( + DdManager * dd, + DdNode * f, + int nvars, + int threshold) +{ + DdNode *res, *tmp1, *tmp2; + int sizeI, size; + + tmp1 = Cudd_RemapUnderApprox(dd,f,nvars,0,1.0); + if (tmp1 == NULL) return(NULL); + Cudd_Ref(tmp1); + sizeI = Cudd_DagSize(tmp1); + size = (sizeI < threshold) ? sizeI : threshold; + tmp2 = Cudd_SubsetShortPaths(dd, tmp1, nvars, size, 0); + if (tmp2 == NULL) { + Cudd_RecursiveDeref(dd,tmp1); + return(NULL); + } + Cudd_Ref(tmp2); + Cudd_RecursiveDeref(dd,tmp1); + res = Cudd_bddSqueeze(dd,tmp2,f); + if (res == NULL) { + Cudd_RecursiveDeref(dd,tmp2); + return(NULL); + } + Cudd_Ref(res); + Cudd_RecursiveDeref(dd,tmp2); + return(res); + +} /* end of ntrCompress1 */ +#endif + + +/**Function******************************************************************** + + Synopsis [Try hard to squeeze a BDD.] + + Description [Try hard to squeeze a BDD. + Returns a pointer to the squeezed BDD if successful; NULL otherwise.] + + SideEffects [None] + + SeeAlso [ntrTestDensityAux Cudd_SubsetCompress] + +******************************************************************************/ +static DdNode * +ntrCompress2( + DdManager * dd, + DdNode * f, + int nvars, + int threshold) +{ + DdNode *res, *tmp1, *tmp2; + int sizeI; + + tmp1 = Cudd_RemapUnderApprox(dd,f,nvars,0,1.0); + if (tmp1 == NULL) return(NULL); + Cudd_Ref(tmp1); + sizeI = Cudd_DagSize(tmp1); + if (sizeI > threshold) { + tmp2 = Cudd_SubsetShortPaths(dd, tmp1, nvars, threshold, 0); + if (tmp2 == NULL) { + Cudd_RecursiveDeref(dd,tmp1); + return(NULL); + } + Cudd_Ref(tmp2); + Cudd_RecursiveDeref(dd,tmp1); + } else { + tmp2 = tmp1; + } + res = Cudd_bddSqueeze(dd,tmp2,f); + if (res == NULL) { + Cudd_RecursiveDeref(dd,tmp2); + return(NULL); + } + Cudd_Ref(res); + if (Cudd_Density(dd,res,nvars) < Cudd_Density(dd,tmp2,nvars)) { + Cudd_RecursiveDeref(dd,res); + return(tmp2); + } else { + Cudd_RecursiveDeref(dd,tmp2); + return(res); + } + +} /* end of ntrCompress2 */ + + +/**Function******************************************************************** + + Synopsis [Checks whether node is a buffer.] + + Description [Checks whether node is a buffer. Returns a pointer to the + input node if nd is a buffer; NULL otherwise.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +static BnetNode * +ntrNodeIsBuffer( + BnetNode *nd, + st_table *hash) +{ + BnetNode *inpnd; + + if (nd->ninp != 1) return(0); + if (!st_lookup(hash, nd->inputs[0], &inpnd)) return(0); + + return(nd->dd == inpnd->dd ? inpnd : NULL); + +} /* end of ntrNodeIsBuffer */ diff --git a/distr/nanotrav/ntrHeap.c b/distr/nanotrav/ntrHeap.c new file mode 100644 index 0000000..a9fa875 --- /dev/null +++ b/distr/nanotrav/ntrHeap.c @@ -0,0 +1,390 @@ +/**CFile*********************************************************************** + + FileName [ntrHeap.c] + + PackageName [ntr] + + Synopsis [Functions for heap-based priority queue.] + + Description [The functions in this file manage a priority queue implemented + as a heap. The first element of the heap is the one with the smallest key. + Refer to Chapter 7 of Cormen, Leiserson, and Rivest for the theory.] + + 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 "ntr.h" + +/*---------------------------------------------------------------------------*/ +/* Constant declarations */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Stucture declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Type declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Variable declarations */ +/*---------------------------------------------------------------------------*/ + +#ifndef lint +static char rcsid[] UTIL_UNUSED = "$Id: ntrHeap.c,v 1.5 2004/08/13 18:28:28 fabio Exp fabio $"; +#endif + +/*---------------------------------------------------------------------------*/ +/* Macro declarations */ +/*---------------------------------------------------------------------------*/ + +#define PARENT(i) (((i)-1)>>1) +#define RIGHT(i) (((i)+1)<<1) +#define LEFT(i) (((i)<<1)|1) +#define ITEM(p,i) ((p)[i].item) +#define KEY(p,i) ((p)[i].key) + +/**AutomaticStart*************************************************************/ + +/*---------------------------------------------------------------------------*/ +/* Static function prototypes */ +/*---------------------------------------------------------------------------*/ + +static void ntrHeapify (NtrHeap *heap, int i); +static int ntrHeapResize (NtrHeap *heap); + +/**AutomaticEnd***************************************************************/ + +/*---------------------------------------------------------------------------*/ +/* Definition of exported functions */ +/*---------------------------------------------------------------------------*/ + + +/**Function******************************************************************** + + Synopsis [Initializes a priority queue.] + + Description [Initializes a priority queue. Returns a pointer to the heap + if successful; NULL otherwise.] + + SideEffects [None] + + SeeAlso [Ntr_FreeHeap] + +******************************************************************************/ +NtrHeap * +Ntr_InitHeap( + int size) +{ + NtrHeap *heap; + + heap = ALLOC(NtrHeap,1); + if (heap == NULL) return(NULL); + heap->size = size; + heap->nslots = 0; + heap->slots = ALLOC(NtrHeapSlot,size); + if (heap->slots == NULL) { + FREE(heap); + return(NULL); + } + return(heap); + +} /* end of Ntr_InitHeap */ + + +/**Function******************************************************************** + + Synopsis [Frees a priority queue.] + + Description [] + + SideEffects [None] + + SeeAlso [Ntr_InitHeap] + +******************************************************************************/ +void +Ntr_FreeHeap( + NtrHeap *heap) +{ + FREE(heap->slots); + FREE(heap); + return; + +} /* end of Ntr_FreeHeap */ + + +/**Function******************************************************************** + + Synopsis [Inserts an item in a priority queue.] + + Description [Inserts an item in a priority queue. Returns 1 if successful; + 0 otherwise.] + + SideEffects [None] + + SeeAlso [Ntr_HeapExtractMin] + +******************************************************************************/ +int +Ntr_HeapInsert( + NtrHeap *heap, + void *item, + int key) +{ + NtrHeapSlot *slots; + int i = heap->nslots; + + if (i == heap->size && !ntrHeapResize(heap)) return(0); + slots = heap->slots; + heap->nslots++; + while (i > 0 && KEY(slots,PARENT(i)) > key) { + ITEM(slots,i) = ITEM(slots,PARENT(i)); + KEY(slots,i) = KEY(slots,PARENT(i)); + i = PARENT(i); + } + ITEM(slots,i) = item; + KEY(slots,i) = key; + return(1); + +} /* end of Ntr_HeapInsert */ + + +/**Function******************************************************************** + + Synopsis [Extracts the element with the minimum key from a priority + queue.] + + Description [Extracts the element with the minimum key from a priority + queue. Returns 1 if successful; 0 otherwise.] + + SideEffects [The minimum key and the associated item are returned as + side effects.] + + SeeAlso [Ntr_HeapInsert] + +******************************************************************************/ +int +Ntr_HeapExtractMin( + NtrHeap *heap, + void *item, + int *key) +{ + NtrHeapSlot *slots = heap->slots; + + if (heap->nslots == 0) return(0); + *(void **)item = ITEM(slots,0); + *key = KEY(slots,0); + heap->nslots--; + ITEM(slots,0) = ITEM(slots,heap->nslots); + KEY(slots,0) = KEY(slots,heap->nslots); + ntrHeapify(heap,0); + + return(1); + +} /* end of Ntr_HeapExtractMin */ + + +/**Function******************************************************************** + + Synopsis [Returns the number of items in a priority queue.] + + Description [] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +int +Ntr_HeapCount( + NtrHeap *heap) +{ + return(heap->nslots); + +} /* end of Ntr_HeapCount */ + + +/**Function******************************************************************** + + Synopsis [Clones a priority queue.] + + Description [] + + SideEffects [None] + + SeeAlso [Ntr_InitHeap] + +******************************************************************************/ +NtrHeap * +Ntr_HeapClone( + NtrHeap *source) +{ + NtrHeap *dest; + int i; + int nslots = source->nslots; + NtrHeapSlot *sslots = source->slots; + NtrHeapSlot *dslots; + + dest = Ntr_InitHeap(source->size); + if (dest == NULL) return(NULL); + dest->nslots = nslots; + dslots = dest->slots; + for (i = 0; i < nslots; i++) { + KEY(dslots,i) = KEY(sslots,i); + ITEM(dslots,i) = ITEM(sslots,i); + } + return(dest); + +} /* end of Ntr_HeapClone */ + + +/**Function******************************************************************** + + Synopsis [Tests the heap property of a priority queue.] + + Description [Tests the heap property of a priority queue. Returns 1 if + Successful; 0 otherwise.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +int +Ntr_TestHeap( + NtrHeap *heap, + int i) +{ + NtrHeapSlot *slots = heap->slots; + int nslots = heap->nslots; + + if (i > 0 && KEY(slots,i) < KEY(slots,PARENT(i))) + return(0); + if (LEFT(i) < nslots) { + if (!Ntr_TestHeap(heap,LEFT(i))) + return(0); + } + if (RIGHT(i) < nslots) { + if (!Ntr_TestHeap(heap,RIGHT(i))) + return(0); + } + return(1); + +} /* end of Ntr_TestHeap */ + + +/*---------------------------------------------------------------------------*/ +/* Definition of static functions */ +/*---------------------------------------------------------------------------*/ + + +/**Function******************************************************************** + + Synopsis [Maintains the heap property of a priority queue.] + + Description [] + + SideEffects [None] + + SeeAlso [Ntr_HeapExtractMin] + +******************************************************************************/ +static void +ntrHeapify( + NtrHeap *heap, + int i) +{ + int smallest; + int left = LEFT(i); + int right = RIGHT(i); + int nslots = heap->nslots; + NtrHeapSlot *slots = heap->slots; + int key = KEY(slots,i); + + if (left < nslots && KEY(slots,left) < key) { + smallest = left; + } else { + smallest = i; + } + if (right < nslots && KEY(slots,right) < KEY(slots,smallest)) { + smallest = right; + } + if (smallest != i) { + void *item = ITEM(slots,i); + KEY(slots,i) = KEY(slots,smallest); + ITEM(slots,i) = ITEM(slots,smallest); + KEY(slots,smallest) = key; + ITEM(slots,smallest) = item; + ntrHeapify(heap,smallest); + } + + return; + +} /* end of ntrHeapify */ + + +/**Function******************************************************************** + + Synopsis [Resizes a priority queue.] + + Description [Resizes a priority queue by doubling the number of + available slots. Returns 1 if successful; 0 otherwise.] + + SideEffects [None] + + SeeAlso [Ntr_HeapInsert] + +******************************************************************************/ +static int +ntrHeapResize( + NtrHeap *heap) +{ + int oldlength = heap->size; + int newlength = 2 * oldlength; + NtrHeapSlot *oldslots = heap->slots; + NtrHeapSlot *newslots = REALLOC(NtrHeapSlot, oldslots, newlength); + if (newslots == NULL) return 0; + heap->size = newlength; + heap->slots = newslots; + assert(Ntr_TestHeap(heap, 0)); + return 1; + +} /* end of ntrHeapResize */ diff --git a/distr/nanotrav/ntrMflow.c b/distr/nanotrav/ntrMflow.c new file mode 100644 index 0000000..c80c18d --- /dev/null +++ b/distr/nanotrav/ntrMflow.c @@ -0,0 +1,1581 @@ +/**CFile*********************************************************************** + + FileName [ntrMflow.c] + + PackageName [ntr] + + Synopsis [Symbolic maxflow algorithm.] + + Description [This file contains the functions that implement the + symbolic version of Dinits's maxflow algorithm described in the + ICCAD93 paper. The present implementation differs from the algorithm + described in the paper in that more than one matching techniques is + used. The technique of the paper is the one applied to + hourglass-type bilayers here.] + + Author [Fabio Somenzi, Gary Hachtel] + + 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 "ntr.h" + +/*---------------------------------------------------------------------------*/ +/* Constant declarations */ +/*---------------------------------------------------------------------------*/ + +#define MAXPHASE 1000 +#define MAXLAYER 1000 +#define MAXFPIT 100000 +#define MANY_TIMES 3.0 + +#define PRUNE /* If defined, enables pruning of E */ + +/*---------------------------------------------------------------------------*/ +/* Stucture declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Type declarations */ +/*---------------------------------------------------------------------------*/ + +typedef struct flowStatsStruct { + int pr; /* level of verbosity */ + long start_time; /* cpu time when the covering started */ + int phases; /* number of phases */ + int layers; /* number of layers */ + int fpit; /* number of fixed point iterations */ +} flowStats; + +/*---------------------------------------------------------------------------*/ +/* Variable declarations */ +/*---------------------------------------------------------------------------*/ + +#ifndef lint +static char rcsid[] UTIL_UNUSED = "$Id: ntrMflow.c,v 1.7 2009/02/20 02:19:02 fabio Exp fabio $"; +#endif + +static DdNode *xcube, *ycube, *zcube; + +/*---------------------------------------------------------------------------*/ +/* Macro declarations */ +/*---------------------------------------------------------------------------*/ + +/**AutomaticStart*************************************************************/ + +/*---------------------------------------------------------------------------*/ +/* Static function prototypes */ +/*---------------------------------------------------------------------------*/ + +static void maximal_pull (DdManager *bdd, int l, DdNode *ty, DdNode **neW, DdNode **U, DdNode *E, DdNode **F, DdNode **x, DdNode **y, DdNode **z, int n, DdNode *pryz, DdNode *prxz, flowStats *stats); +static void propagate_maximal_flow (DdManager *bdd, int m, DdNode **neW, DdNode **U, DdNode **x, DdNode **y, DdNode **z, int n, DdNode *pryz, DdNode *prxz, flowStats *stats); +static void trellis (DdManager *bdd, int m, DdNode **neW, DdNode **U, DdNode **x, DdNode **y, DdNode **z, int n, DdNode *pryz, DdNode *prxz, flowStats *stats); +static void rhombus (DdManager *bdd, int m, DdNode **neW, DdNode **U, DdNode **x, DdNode **y, DdNode **z, int n, DdNode *pryz, DdNode *prxz, flowStats *stats); +static void hourglass (DdManager *bdd, int m, DdNode **neW, DdNode **U, DdNode **x, DdNode **y, DdNode **z, int n, DdNode *pryz, DdNode *prxz, flowStats *stats); +static void maximal_push (DdManager *bdd, int l, DdNode **U, DdNode **F, DdNode **x, DdNode **y, DdNode **z, int n, DdNode *pryz, DdNode *prxz, flowStats *stats); +static void trellisPush (DdManager *bdd, int m, DdNode **U, DdNode **x, DdNode **y, DdNode **z, int n, DdNode *pryz, DdNode *prxz, flowStats *stats); +static void rhombusPush (DdManager *bdd, int m, DdNode **U, DdNode **x, DdNode **y, DdNode **z, int n, DdNode *pryz, DdNode *prxz, flowStats *stats); +static void hourglassPush (DdManager *bdd, int m, DdNode **U, DdNode **x, DdNode **y, DdNode **z, int n, DdNode *pryz, DdNode *prxz, flowStats *stats); + +/**AutomaticEnd***************************************************************/ + +/*---------------------------------------------------------------------------*/ +/* Definition of exported functions */ +/*---------------------------------------------------------------------------*/ + + +/**Function******************************************************************** + + Synopsis [] + + Description [This function implements Dinits's algorithm for (0-1) + max flow, using BDDs and a symbolic technique to trace multiple + edge-disjoint augmenting paths to complete a phase. The outer + forever loop is over phases, and the inner forever loop is to + propagate a (not yet) maximal flow of edge-disjoint augmenting paths + from one layer to the previous. The subprocedure call implements a + least fixed point iteration to compute a (not yet) maximal flow + update between layers. At the end of each phase (except the last + one) the flow is actually pushed from the source to the sink. + + Data items: +
            +
          • sx(ty) BDD representations of s(t). +
          • x(y) The variables encoding the from(to)-node u(v) of an + edge (u,v) in the given digraph. +
          • z Another set of variables. +
          • E(x,y) The edge relation. +
          • F(x,y) BDD representation of the current flow, initialized to 0 + for each arc, and updated by +1, -1, or 0 at the + end of each phase. +
          • Ms Mt The maximum flow, that is, the cardinality of a minimum cut, + measured at the source and at the sink, respectively. + The two values should be identical. +
          • reached The set of nodes already visited in the BFS of the digraph. +
          • fos fanout of the source node s. +
          • fit fanin of the sink node t. +
          + ] + + SideEffects [The flow realtion F and the cutset relation cut are returned + as side effects.] + + SeeAlso [] + +******************************************************************************/ +double +Ntr_maximum01Flow( + DdManager * bdd /* manager */, + DdNode * sx /* source node */, + DdNode * ty /* sink node */, + DdNode * E /* edge relation */, + DdNode ** F /* flow relation */, + DdNode ** cut /* cutset relation */, + DdNode ** x /* array of row variables */, + DdNode ** y /* array of column variables */, + DdNode ** z /* arrays of auxiliary variables */, + int n /* number of variables in each array */, + int pr /* verbosity level */) +{ + flowStats stats; + DdNode *one, *zero, +#ifdef PRUNE + *EDC, /* Edge don't care set */ +#endif + *reached, /* states reached through useful edges */ + *fos, *fit, /* fanout of source, fanin of sink */ + *rF, *rB, *tx, + *I, *P, + *w, *p, *q, *r,/* intemediate results */ + *pryz, *prxz, /* priority functions for disjoint path tracing */ + **neW, **U; /* arrays of BDDs for flow propagation */ + int i, j, l; + double Ms, Mt; + + /* Initialize debugging structure. */ + stats.pr = pr; + stats.start_time = util_cpu_time(); + stats.phases = 0; + stats.layers = 0; + stats.fpit = 0; + + /* Allocate arrays for new (just reached vertex sets) + ** and U (useful edge sets). + */ + U = ALLOC(DdNode *, ((unsigned) MAXLAYER)); + neW = ALLOC(DdNode *, ((unsigned) MAXLAYER)); + + one = Cudd_ReadOne(bdd); + zero = Cudd_Not(one); + + /* Initialize xcube, ycube, and zcube (for abstractions). */ + Cudd_Ref(xcube = Cudd_bddComputeCube(bdd,x,NULL,n)); + Cudd_Ref(ycube = Cudd_bddComputeCube(bdd,y,NULL,n)); + Cudd_Ref(zcube = Cudd_bddComputeCube(bdd,z,NULL,n)); + + /* Build the BDD for the priority functions. */ + Cudd_Ref(pryz = Cudd_Dxygtdxz(bdd, n, x, y, z)); + Cudd_Ref(prxz = Cudd_Dxygtdyz(bdd, n, x, y, z)); + /* Now "randomize" by shuffling the x variables in pryz and the y + ** variables in prxz. + */ + Cudd_Ref(p = Cudd_bddAdjPermuteX(bdd,pryz,x,n)); + Cudd_RecursiveDeref(bdd,pryz); + pryz = p; + if(pr>2){(void) fprintf(stdout,"pryz");Cudd_PrintDebug(bdd,pryz,n*3,pr);} + Cudd_Ref(p = Cudd_bddAdjPermuteX(bdd,prxz,y,n)); + Cudd_RecursiveDeref(bdd,prxz); + prxz = p; + if(pr>2){(void) fprintf(stdout,"prxz");Cudd_PrintDebug(bdd,prxz,n*3,pr);} + +#ifdef PRUNE + /* Build the edge don't care set and prune E. The edge don't care + ** set consists of the edges into the source(s), the edges out of the + ** sink(s), and the self-loops. These edges cannot contribute to the + ** maximum flow. + */ + Cudd_Ref(p = Cudd_bddSwapVariables(bdd, sx, x, y, n)); + Cudd_Ref(q = Cudd_bddSwapVariables(bdd, ty, x, y, n)); + Cudd_Ref(r = Cudd_bddOr(bdd, p, q)); + Cudd_RecursiveDeref(bdd,p); + Cudd_RecursiveDeref(bdd,q); + Cudd_Ref(p = Cudd_Xeqy(bdd, n, x, y)); + Cudd_Ref(EDC = Cudd_bddOr(bdd, p, r)); + Cudd_RecursiveDeref(bdd,p); + Cudd_RecursiveDeref(bdd,r); + if(pr>2){(void) fprintf(stdout,"EDC");Cudd_PrintDebug(bdd,EDC,n<<1,pr);} + Cudd_Ref(p = Cudd_bddAnd(bdd, E, Cudd_Not(EDC))); + Cudd_RecursiveDeref(bdd,EDC); + if(pr>0){(void) fprintf(stdout,"Given E");Cudd_PrintDebug(bdd,E,n<<1,pr);} + E = p; + if(pr>0){(void) fprintf(stdout,"Pruned E");Cudd_PrintDebug(bdd,E,n<<1,pr);} +#endif + + /* Compute fanin of sink node t: it is an upper bound for the flow. */ + Cudd_Ref(fit = Cudd_bddAnd(bdd, E, ty)); + if (pr>2) { + /* Compute fanout of source node s. */ + Cudd_Ref(fos = Cudd_bddAnd(bdd, E, sx)); + (void) fprintf(stdout,"fos");Cudd_PrintDebug(bdd,fos,n<<1,pr); + Cudd_RecursiveDeref(bdd,fos); + + (void) fprintf(stdout,"fit");Cudd_PrintDebug(bdd,fit,n<<1,pr); + } + /* t(x) is used to check for termination of forward traversal. */ + Cudd_Ref(tx = Cudd_bddSwapVariables(bdd, ty, x, y, n)); + + /* \KW{Procedure}\ \ \PC{maximum\_flow}$(s,t,E(x,y)) */ + Cudd_Ref(*F = zero); + + for (i = 1; i < MAXPHASE; i++) { + stats.phases++; + if(pr>0){(void) fprintf(stdout,"## Starting Phase %d at time = %s\n",i, + util_print_time(util_cpu_time() - stats.start_time));} + /* new[0](x) = s(x);U^0(x,y)=E(x,y)\cdot s(x) \cdot \overline{F(x,y)}; + ** reached=s; new[1](x)=\exists_xU^0(x,y); + */ + Cudd_Ref(neW[0] = sx); + Cudd_Ref(p = Cudd_bddAnd(bdd, sx, Cudd_Not(*F))); + Cudd_Ref(U[0] = Cudd_bddAnd(bdd, p, E)); + Cudd_RecursiveDeref(bdd,p); + Cudd_Ref(reached = sx); + Cudd_Ref(r = Cudd_bddExistAbstract(bdd, U[0], xcube)); + Cudd_RecursiveDeref(bdd,U[0]); + Cudd_Ref(q = Cudd_bddSwapVariables(bdd, r, x, y, n)); + Cudd_RecursiveDeref(bdd,r); + Cudd_Ref(neW[1] = Cudd_bddAnd(bdd, q, Cudd_Not(reached))); + Cudd_RecursiveDeref(bdd,q); + if(pr>0) { + (void) fprintf(stdout,"neW[1]");Cudd_PrintDebug(bdd,neW[1],n,pr); + } + for (l = 1; l < MAXLAYER; l++) { + if (neW[l] == zero) { /* flow is maximum */ + /* cut=reached(x) \cdot E(x,y) \cdot \overline{reached(y)} */ + Cudd_Ref(p = Cudd_bddAnd(bdd, reached, E)); + Cudd_Ref(q = Cudd_bddSwapVariables(bdd, reached, x, y, n)); + Cudd_Ref(*cut = Cudd_bddAnd(bdd, p, Cudd_Not(q))); + Cudd_RecursiveDeref(bdd,p); + Cudd_RecursiveDeref(bdd,q); + Cudd_RecursiveDeref(bdd,reached); + for (j = 0; j <= l; j++) + Cudd_RecursiveDeref(bdd,neW[j]); + goto endPhases; + } + /* As soon as we touch one sink node we stop traversal. + ** \KW{if} ($t\cdot new^{l} \neq 0$) + */ + if (!Cudd_bddLeq(bdd, tx, Cudd_Not(neW[l]))) { + Cudd_RecursiveDeref(bdd,reached); + maximal_pull(bdd,l-1,ty,neW,U,E,F,x,y,z,n,pryz,prxz,&stats); + goto endLayers; + } + stats.layers++; + if(pr>2){(void) fprintf(stdout,"===== Layer %d =====\n",l);} + /* reached(x) = reached(x) + new^l(x) */ + Cudd_Ref(w = Cudd_bddOr(bdd, reached, neW[l])); + Cudd_RecursiveDeref(bdd,reached); + reached = w; + /* I(y) = \exists_x((E(x,y) \cdot \overline{F(x,y)}) + ** \cdot new^l(x)) + */ + Cudd_Ref(p = Cudd_bddAnd(bdd, E, Cudd_Not(*F))); + Cudd_Ref(I = Cudd_bddAndAbstract(bdd, p, neW[l], xcube)); + if(pr>3){(void) fprintf(stdout,"I");Cudd_PrintDebug(bdd,I,n,pr);} + Cudd_RecursiveDeref(bdd,p); + /* rF(x)= I(x) \cdot \overline{reached(x)}) */ + Cudd_Ref(p = Cudd_bddSwapVariables(bdd, I, x, y, n)); + Cudd_RecursiveDeref(bdd,I); + Cudd_Ref(rF = Cudd_bddAnd(bdd, p, Cudd_Not(reached))); + Cudd_RecursiveDeref(bdd,p); + if(pr>2){(void) fprintf(stdout,"rF");Cudd_PrintDebug(bdd,rF,n,pr);} + /* P(x) = \exists_{y}(F(x,y) \cdot new^l(y)) */ + Cudd_Ref(p = Cudd_bddSwapVariables(bdd, neW[l], x, y, n)); + Cudd_Ref(P = Cudd_bddAndAbstract(bdd, *F, p, ycube)); + Cudd_RecursiveDeref(bdd,p); + /* rB(x) = P(x) \cdot \overline{reached(x)}) */ + Cudd_Ref(rB = Cudd_bddAnd(bdd, P, Cudd_Not(reached))); + Cudd_RecursiveDeref(bdd,P); + if(pr>2){(void) fprintf(stdout,"rB");Cudd_PrintDebug(bdd,rB,n,pr);} + /* new^{l+1}(x) = rF(x) + rB(x) */ + Cudd_Ref(neW[l+1] = Cudd_bddOr(bdd, rF, rB)); + Cudd_RecursiveDeref(bdd,rB); + Cudd_RecursiveDeref(bdd,rF); + if(pr>0) { + (void) fprintf(stdout,"new[%d]",l+1); + Cudd_PrintDebug(bdd,neW[l+1],n,pr); + } + } /* start next layer */ + if (l==MAXLAYER) (void) fprintf(stderr,"ERROR! MAXLAYER exceeded.\n"); + exit(3); +endLayers: + maximal_push(bdd, l-1, U, F, x, y, z, n, pryz, prxz, &stats); + for (j = 0; j < l; j++) { + Cudd_RecursiveDeref(bdd,U[j]); + Cudd_RecursiveDeref(bdd,neW[j]); + } + Cudd_RecursiveDeref(bdd,neW[l]); + if (pr > 0) { + Cudd_Ref(p = Cudd_bddAnd(bdd, sx, *F)); + Ms=Cudd_CountMinterm(bdd, p, n<<1); + (void) fprintf(stdout,"# Flow out of s: %g\n", Ms); + Cudd_RecursiveDeref(bdd,p); + } + if (Cudd_bddLeq(bdd, fit, *F)) { + Cudd_Ref(*cut = fit); + goto endPhases; + } + } /* start next phase */ + if (i == MAXPHASE) (void) fprintf(stderr,"ERROR! MAXPHASE exceeded.\n"); + + /* Last phase is completed --- print flow results. */ +endPhases: + Cudd_RecursiveDeref(bdd,tx); + + Cudd_Ref(q = Cudd_bddAnd(bdd, *F, sx)); + Ms = Cudd_CountMinterm(bdd, q, n<<1); + Cudd_RecursiveDeref(bdd,q); + + Cudd_Ref(q = Cudd_bddAnd(bdd, *F, ty)); + Mt = Cudd_CountMinterm(bdd, q, n<<1); + Cudd_RecursiveDeref(bdd,q); + + if (pr>1) (void) fprintf(stdout,"Mt= %g, Ms= %g \n", Mt, Ms); + + if (pr>3){(void) fprintf(stdout,"pryz");Cudd_PrintDebug(bdd,pryz,n*3,pr);} + if (pr>3){(void) fprintf(stdout,"prxz");Cudd_PrintDebug(bdd,prxz,n*3,pr);} + + if (pr>0) { + (void) fprintf(stdout,"#### Stats for maximum_flow ####\n"); + (void) fprintf(stdout,"%d variables %d of which x[i]\n", Cudd_ReadSize(bdd), n); + (void) fprintf(stdout,"time = %s\n", + util_print_time(util_cpu_time() - stats.start_time)); + (void) fprintf(stdout,"phases = %d\n", stats.phases); + (void) fprintf(stdout,"layers = %d\n", stats.layers); + (void) fprintf(stdout,"FP iter. = %d\n", stats.fpit); + } + + Cudd_RecursiveDeref(bdd,fit); + Cudd_RecursiveDeref(bdd,pryz); + Cudd_RecursiveDeref(bdd,prxz); + Cudd_RecursiveDeref(bdd,xcube); + Cudd_RecursiveDeref(bdd,ycube); + Cudd_RecursiveDeref(bdd,zcube); +#ifdef PRUNE + Cudd_RecursiveDeref(bdd,E); +#endif + + FREE(U); + FREE(neW); + + return(Ms); + +} /* end of Ntr_maximum01Flow */ + + +/*---------------------------------------------------------------------------*/ +/* Definition of internal functions */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Definition of static functions */ +/*---------------------------------------------------------------------------*/ + + +/**Function******************************************************************** + + Synopsis [Selects set of edge-disjoint paths from layered network.] + + Description [Selects set of edge-disjoint paths from layered + network. maximal_pull is called when the BFS constructing the + layered graph reaches a sink. At this point the new sets of the + BFS have been formed, and we know every vertex in these sets is + reachable from the source vertex (or vertices) s. The new sets are + used to compute the set of useful edges exiting each layer to the + right. In each layer, propagate_maximal_flow is called to select a + maximal subset of these useful edges. This subset is then used to + prune new and U.] + + SideEffects [None] + + SeeAlso [maximal_push] + +******************************************************************************/ +static void +maximal_pull( + DdManager * bdd /* manager */, + int l /* depth of layered network for current phase */, + DdNode * ty /* sink node */, + DdNode ** neW /* array of BFS layers */, + DdNode ** U /* array of useful edges */, + DdNode * E /* edge relation */, + DdNode ** F /* flow relation */, + DdNode ** x, + DdNode ** y, + DdNode ** z /* arrays of variables for rows and columns */, + int n /* number of x variables */, + DdNode * pryz, + DdNode * prxz /* priority functions */, + flowStats * stats) +{ + DdNode *p, *q, *r, + *UF, *UB; + int m, + pr; /* Print control */ + + pr = stats->pr; + + /* The useful edges of the last layer are all the empty edges into + ** the sink(s) from new[l]. + ** U^{l}(x,y) = t(y)\cdot \overline{F(x,y)}\cdot E(x,y)\cdot new^{l}(x) + */ + Cudd_Ref(p = Cudd_bddAnd(bdd, E, Cudd_Not(*F))); + Cudd_Ref(q = Cudd_bddAnd(bdd, neW[l], p)); + Cudd_RecursiveDeref(bdd,p); + Cudd_Ref(U[l] = Cudd_bddAnd(bdd, ty, q)); + Cudd_RecursiveDeref(bdd,q); + if(pr>1){(void) fprintf(stdout,"U[%d]",l);Cudd_PrintDebug(bdd,U[l],n<<1,pr);} + /* Eliminate from new[l] the states with no paths to the sink(s). + ** new^{l}(x)=\exists_y U^{l}(x,y) + */ + Cudd_RecursiveDeref(bdd,neW[l]); + Cudd_Ref(neW[l] = Cudd_bddExistAbstract(bdd, U[l], ycube)); + + for (m = l; m >= 1; m--) { + /* Find usable backward edges from level m-1 to level m. + ** UB(x,y) = new^{m}(x) \cdot F(x,y) \cdot new^{m-1}(y) + */ + Cudd_Ref(r = Cudd_bddSwapVariables(bdd, neW[m-1], x, y, n)); + Cudd_Ref(q = Cudd_bddAnd(bdd, r, *F)); + Cudd_RecursiveDeref(bdd,r); + Cudd_Ref(UB = Cudd_bddAnd(bdd, neW[m], q)); + Cudd_RecursiveDeref(bdd,q); + if(pr>2){(void) fprintf(stdout,"UB");Cudd_PrintDebug(bdd,UB,n<<1,pr);} + /* Find usable forward edges. + ** UF(x,y) = new^{m}(y) \cdot \overline{F(x,y)} \cdot E(x,y) + ** \cdot new^{m-1}(x) + */ + Cudd_Ref(p = Cudd_bddAnd(bdd, E, Cudd_Not(*F))); + Cudd_Ref(q = Cudd_bddAnd(bdd, neW[m-1], p)); + Cudd_RecursiveDeref(bdd,p); + Cudd_Ref(r = Cudd_bddSwapVariables(bdd, neW[m], x, y, n)); + Cudd_Ref(UF = Cudd_bddAnd(bdd, r, q)); + Cudd_RecursiveDeref(bdd,q); + Cudd_RecursiveDeref(bdd,r); + if(pr>2){(void) fprintf(stdout,"UF");Cudd_PrintDebug(bdd,UF,n<<1,pr);} + /* U^{m-1}(x,y) = UB(y,x) + UF(x,y) */ + Cudd_Ref(r = Cudd_bddSwapVariables(bdd, UB, x, y, n)); + Cudd_RecursiveDeref(bdd,UB); + Cudd_Ref(U[m-1] = Cudd_bddOr(bdd, UF, r)); + Cudd_RecursiveDeref(bdd,UF); + Cudd_RecursiveDeref(bdd,r); + if(pr>2){(void)fprintf(stdout,"U[%d]",m-1); + Cudd_PrintDebug(bdd,U[m-1],n<<1,pr);} + /* new[m-1](x) = \exists_{y}U^{m-1}(x,y) */ + Cudd_RecursiveDeref(bdd,neW[m-1]); + Cudd_Ref(neW[m-1] = Cudd_bddExistAbstract(bdd, U[m-1], ycube)); + /* Compute maximal disjoint interlayer edge set. */ + propagate_maximal_flow(bdd, m, neW, U, x, y, z, n, pryz, prxz, stats); + if(pr>0) { + (void)fprintf(stdout,"U[%d]",m-1); + Cudd_PrintDebug(bdd,U[m-1],n<<1,pr); + } + } /* prune next layer */ + + return; + +} /* end of maximal_pull */ + + +/**Function******************************************************************** + + Synopsis [Pulls flow though a layer.] + + Description [Pulls flow though a layer. propagate_maximal_flow only + affects U[m-1] and new[m-1]. At the end of this function, the edges + in U[m] are guaranteed to drain all the flow supplied by the edges + in U[m-1]. This effect is obtained by pruning U[m-1]. After the + pruned U[m-1] is computed, new[m-1] is updated to keep track of what + nodes are still useful. + + The pruning is performed without actually measuring the in-potential + and the out-potential of each node. Instead, pairs of nodes from U[m-1] + and U[m] are matched. To avoid counting, the procedure computes sets of + paths that connect layer m-1 to layer m+1 and are edge-disjoint. + + Two paths from layer m-1 to layer m+1 are disjoint if they have distinct + end-point or if they have distinct middle points. What condition to + enforce depends on the "shape" of the layers.] + + SideEffects [Changes U[m-1] and new[m-1]] + + SeeAlso [trellis rhombus hourglass] + +******************************************************************************/ +static void +propagate_maximal_flow( + DdManager * bdd, + int m /* center of current bilayer */, + DdNode ** neW /* array of reachable or useful nodes */, + DdNode ** U /* array of usable or useful edges */, + DdNode ** x, + DdNode ** y, + DdNode ** z /* arrays of variables for rows and columns */, + int n /* number of x variables */, + DdNode * pryz, + DdNode * prxz /* priority functions */, + flowStats * stats) +{ + DdNode *rN; + double mtl, mtc, mtr; /* minterms for left, center, right levels */ + int pr; /* print control */ + + pr = stats->pr; + + mtl = Cudd_CountMinterm(bdd, neW[m-1], n); + mtc = Cudd_CountMinterm(bdd, neW[m], n); + + /* rN(y) = \exists_x U^{m}(x,y) */ + Cudd_Ref(rN = Cudd_bddExistAbstract(bdd, U[m], xcube)); + mtr = Cudd_CountMinterm(bdd, rN, n); + Cudd_RecursiveDeref(bdd,rN); + + if (pr > 0) { + (void) fprintf(stdout, "layer = %d mtl = %g mtc = %g mtr = %g", + m, mtl, mtc, mtr); + } + + if ((mtc > MANY_TIMES * mtl) || (mtc > MANY_TIMES * mtr)) { + if (pr>0) (void) fprintf(stdout, " R\n"); + rhombus(bdd, m, neW, U, x, y, z, n, pryz, prxz, stats); + } else if (mtr > MANY_TIMES * mtc) { + if (pr>0) (void) fprintf(stdout, " H\n"); + hourglass(bdd, m, neW, U, x, y, z, n, pryz, prxz, stats); + } else { + if (pr>0) (void) fprintf(stdout, " T\n"); + trellis(bdd, m, neW, U, x, y, z, n, pryz, prxz, stats); + } + return; + +} /* end of propagate_maximal_flow */ + + +/**Function******************************************************************** + + Synopsis [Selects edges from a trellis-type bilayer.] + + Description [Selects edges from a trellis-type bilayer. Used to pull flow. + First a matching is found in the left layer. Then the paths are extended + (if possible) through the right layer. This process is repeated until a + maximal flow is found.] + + SideEffects [None] + + SeeAlso [rhombus hourglass trellisPush] + +******************************************************************************/ +static void +trellis( + DdManager * bdd, + int m /* center level of current bilayer */, + DdNode ** neW /* array of node levels */, + DdNode ** U /* array of edge layers */, + DdNode ** x, + DdNode ** y, + DdNode ** z /* arrays of variables for rows and columns */, + int n /* number of x variables */, + DdNode * pryz, + DdNode * prxz /* priority functions */, + flowStats * stats) +{ + DdNode *one, *zero, + *p, *q, *r, + *Uin, /* edges to be matched from U[m-1] */ + *Uout, /* edges to be matched from U[m] */ + *P, + *LU, *RU, /* left-unique and right-unique sets of edges */ + *D, + *Ml, *Mr; /* nodes matched from left and right */ + int k, + pr; /* print control */ + + pr = stats->pr; + + one = Cudd_ReadOne(bdd); + zero = Cudd_Not(one); + + /*Uout(x,y)=U^m(x,y)*/ + Cudd_Ref(Uout = U[m]); + if(pr>3){(void)fprintf(stdout,"Uout");Cudd_PrintDebug(bdd,Uout,n<<1,pr);} + /*Uin(x,y)=U^{m-1}(x,y)*/ + Cudd_Ref(Uin = U[m-1]); + if(pr>3){(void)fprintf(stdout,"Uin");Cudd_PrintDebug(bdd,Uin,n<<1,pr);} + + for(k = 0; k < MAXFPIT; k++) { + stats->fpit++; + /*LU(x,y)=Uin(x,y)\cdot\overline{\exists_{z}(Uin(z,y)\cdot\Pi(x,z))}*/ + Cudd_Ref(p = Cudd_bddSwapVariables(bdd, Uin, x, z, n)); + Cudd_Ref(r = Cudd_bddAndAbstract(bdd, p, prxz, zcube)); + Cudd_RecursiveDeref(bdd,p); + Cudd_Ref(LU = Cudd_bddAnd(bdd, Uin, Cudd_Not(r))); + Cudd_RecursiveDeref(bdd,r); + if(pr>3){(void)fprintf(stdout,"LU");Cudd_PrintDebug(bdd,LU,n<<1,pr);} + /*D(x,y)= LU(x,y)\cdot \overline{\exists_{z}(LU(x,z)\cdot \Pi(y,z))}*/ + Cudd_Ref(p = Cudd_bddSwapVariables(bdd, LU, y, z, n)); + Cudd_Ref(r = Cudd_bddAndAbstract(bdd, p, pryz, zcube)); + Cudd_RecursiveDeref(bdd,p); + Cudd_Ref(D = Cudd_bddAnd(bdd, LU, Cudd_Not(r))); + Cudd_RecursiveDeref(bdd,r); + Cudd_RecursiveDeref(bdd,LU); + if(pr>3){(void)fprintf(stdout,"D");Cudd_PrintDebug(bdd,D,n<<1,pr);} + /*Ml(y)=\exists_{x}D(x,y)*/ + Cudd_Ref(Ml = Cudd_bddExistAbstract(bdd, D, xcube)); + if(pr>3){(void)fprintf(stdout,"Ml");Cudd_PrintDebug(bdd,Ml,n,pr);} + /*P(x,y)=Ml(x)\cdot Uout(x,y)*/ + Cudd_Ref(p = Cudd_bddSwapVariables(bdd, Ml, x, y, n)); + Cudd_Ref(P = Cudd_bddAnd(bdd, p, Uout)); + Cudd_RecursiveDeref(bdd,p); + Cudd_RecursiveDeref(bdd,Ml); + if(pr>3){(void)fprintf(stdout,"P");Cudd_PrintDebug(bdd,P,n<<1,pr);} + /*RU(x,y)= P(x,y)\cdot \overline{\exists_{z}(P(x,z)\cdot \Pi(y,z))}*/ + Cudd_Ref(p = Cudd_bddSwapVariables(bdd, P, y, z, n)); + Cudd_Ref(r = Cudd_bddAndAbstract(bdd, p, pryz, zcube)); + Cudd_RecursiveDeref(bdd,p); + Cudd_Ref(RU = Cudd_bddAnd(bdd, P, Cudd_Not(r))); + Cudd_RecursiveDeref(bdd,r); + Cudd_RecursiveDeref(bdd,P); + if(pr>3){(void)fprintf(stdout,"RU");Cudd_PrintDebug(bdd,RU,n<<1,pr);} + /*Mr(x)=\exists_{y}RU(x,y)*/ + Cudd_Ref(Mr = Cudd_bddExistAbstract(bdd, RU, ycube)); + if(pr>3){(void)fprintf(stdout,"Mr");Cudd_PrintDebug(bdd,Mr,n,pr);} + /*D(x,y)=D(x,y)\cdot Mr(y)*/ + Cudd_Ref(p = Cudd_bddSwapVariables(bdd, Mr, x, y, n)); + Cudd_RecursiveDeref(bdd,Mr); + Cudd_Ref(q = Cudd_bddAnd(bdd, D, p)); + Cudd_RecursiveDeref(bdd,p); + Cudd_RecursiveDeref(bdd,D); + D = q; + if(pr>3){(void)fprintf(stdout,"D");Cudd_PrintDebug(bdd,D,n<<1,pr);} + /*Uin(x,y)=Uin(x,y)-D(x,y)*/ + Cudd_Ref(p = Cudd_bddAnd(bdd, Uin, Cudd_Not(D))); + Cudd_RecursiveDeref(bdd,Uin); + Uin = p; + if(pr>3){(void)fprintf(stdout,"Uin");Cudd_PrintDebug(bdd,Uin,n<<1,pr);} + /*Uout(x,y)=Uout(x,y)-RU(x,y)*/ + Cudd_Ref(p = Cudd_bddAnd(bdd, Uout, Cudd_Not(RU))); + Cudd_RecursiveDeref(bdd,Uout); + Cudd_RecursiveDeref(bdd,RU); + Uout = p; + if(pr>3){(void)fprintf(stdout,"Uout");Cudd_PrintDebug(bdd,Uout,n<<1,pr);} + /*\KW{if}(($D(x,y)=zero$)~~\KW{or}~~($Uin(x,y)=zero$)~~\KW{or} + ($Uout(x,y)=zero$))~~KW{break}*/ + if ((D == zero)||(Uin == zero)||(Uout == zero)) { + Cudd_RecursiveDeref(bdd,D); + break; + } + Cudd_RecursiveDeref(bdd,D); + + } /* Next least fixed point iteration with smaller Uin and Uout */ + if (k == MAXFPIT) (void) fprintf(stderr, + "Trellis: WARNING! MAXFPIT (%d) exceeded processing Layer %d.\n", + MAXFPIT, m); + + if (Uin != zero) { + /* $U^{m-1}(x,y) = U^{m-1}(x,y)-Uin(x,y)$*/ + Cudd_Ref(p = Cudd_bddAnd(bdd, U[m-1], Cudd_Not(Uin))); + Cudd_RecursiveDeref(bdd,U[m-1]); + U[m-1] = p; + /* $new^{m-1}(x,y) = \esists_yU^{m-1}(x,y)$*/ + Cudd_RecursiveDeref(bdd,neW[m-1]); + Cudd_Ref(neW[m-1] = Cudd_bddExistAbstract(bdd, U[m-1], ycube)); + } + if(pr>2){(void)fprintf(stdout,"U[%d]",m-1); Cudd_PrintDebug(bdd,U[m-1],n<<1,pr);} + if(pr>2){(void)fprintf(stdout,"new[%d]",m-1); + Cudd_PrintDebug(bdd,neW[m-1],n,pr);} + + Cudd_RecursiveDeref(bdd,Uin); + Cudd_RecursiveDeref(bdd,Uout); + + return; + +} /* end of trellis */ + + +/**Function******************************************************************** + + Synopsis [Selects edges from a rhombus-type bilayer.] + + Description [Selects edges from a rhombus-type bilayer. Used to pull flow. + Makes the left layer left-unique and the right layer right-unique. Prunes + and repeats until convergence to a maximal flow. It makes sure that all + intermediate points of the two-arc paths are disjoint at each iteration.] + + SideEffects [None] + + SeeAlso [trellis hourglass rhombusPush] + +******************************************************************************/ +static void +rhombus( + DdManager * bdd, + int m /* center of current bilayer */, + DdNode ** neW, + DdNode ** U /* arrays for flow propagation */, + DdNode ** x, + DdNode ** y, + DdNode ** z /* arrays of variables for rows and columns */, + int n /* number of x variables */, + DdNode * pryz, + DdNode * prxz /* priority functions */, + flowStats * stats) +{ + DdNode *one, *zero, + *p, *q, *r, + *Uin, /* edges to be matched from U[m-1] */ + *Uout, /* edges to be matched from U[m] */ + *P, + *LU, *RU, /* left-unique and right-unique sets of edges */ + *Ml, *Mr; /* nodes matched from left and right */ + int k, + pr; /* print control */ + + pr = stats->pr; + + one = Cudd_ReadOne(bdd); + zero = Cudd_Not(one); + + /*Uout(x,y)=U^m(x,y)*/ + Cudd_Ref(Uout = U[m]); + if(pr>3){(void)fprintf(stdout,"Uout");Cudd_PrintDebug(bdd,Uout,n<<1,pr);} + + /*Uin(x,y)=U^{m-1}(x,y)*/ + Cudd_Ref(Uin = U[m-1]); + if(pr>3){(void)fprintf(stdout,"Uin");Cudd_PrintDebug(bdd,Uin,n<<1,pr);} + + for(k = 0; k < MAXFPIT; k++) { + stats->fpit++; + /*LU(x,y)=Uin(x,y)\cdot\overline{\exists_{z}(Uin(z,y)\cdot\Pi(x,z))}*/ + Cudd_Ref(p = Cudd_bddSwapVariables(bdd, Uin, x, z, n)); + Cudd_Ref(r = Cudd_bddAndAbstract(bdd, p, prxz, zcube)); + Cudd_RecursiveDeref(bdd,p); + Cudd_Ref(LU = Cudd_bddAnd(bdd, Uin, Cudd_Not(r))); + Cudd_RecursiveDeref(bdd,r); + if(pr>3){(void)fprintf(stdout,"LU");Cudd_PrintDebug(bdd,LU,n<<1,pr);} + /*Ml(y)=\exists_{x}LU(x,y)*/ + Cudd_Ref(Ml = Cudd_bddExistAbstract(bdd, LU, xcube)); + if(pr>3){(void)fprintf(stdout,"Ml");Cudd_PrintDebug(bdd,Ml,n,pr);} + /*P(x,y)=Ml(x)\cdot Uout(x,y)*/ + Cudd_Ref(p = Cudd_bddSwapVariables(bdd, Ml, x, y, n)); + Cudd_Ref(P = Cudd_bddAnd(bdd, p, Uout)); + Cudd_RecursiveDeref(bdd,p); + Cudd_RecursiveDeref(bdd,Ml); + if(pr>3){(void)fprintf(stdout,"P");Cudd_PrintDebug(bdd,P,n<<1,pr);} + /*RU(x,y)= P(x,y)\cdot \overline{\exists_{z}(P(x,z)\cdot \Pi(y,z))}*/ + Cudd_Ref(p = Cudd_bddSwapVariables(bdd, P, y, z, n)); + Cudd_Ref(r = Cudd_bddAndAbstract(bdd, p, pryz, zcube)); + Cudd_RecursiveDeref(bdd,p); + Cudd_Ref(RU = Cudd_bddAnd(bdd, P, Cudd_Not(r))); + Cudd_RecursiveDeref(bdd,r); + Cudd_RecursiveDeref(bdd,P); + if(pr>3){(void)fprintf(stdout,"RU");Cudd_PrintDebug(bdd,RU,n<<1,pr);} + /*Mr(x)=\exists_{y}RU(x,y)*/ + Cudd_Ref(Mr = Cudd_bddExistAbstract(bdd, RU, ycube)); + if(pr>3){(void)fprintf(stdout,"Mr");Cudd_PrintDebug(bdd,Mr,n,pr);} + /*LU(x,y)=LU(x,y)\cdot Mr(y)*/ + Cudd_Ref(p = Cudd_bddSwapVariables(bdd, Mr, x, y, n)); + Cudd_RecursiveDeref(bdd,Mr); + Cudd_Ref(q = Cudd_bddAnd(bdd, LU, p)); + Cudd_RecursiveDeref(bdd,p); + Cudd_RecursiveDeref(bdd,LU); + LU = q; + if(pr>3){(void)fprintf(stdout,"LU");Cudd_PrintDebug(bdd,LU,n<<1,pr);} + /*Uin(x,y)=Uin(x,y)-LU(x,y)*/ + Cudd_Ref(p = Cudd_bddAnd(bdd, Uin, Cudd_Not(LU))); + Cudd_RecursiveDeref(bdd,Uin); + Uin = p; + if(pr>3){(void)fprintf(stdout,"Uin");Cudd_PrintDebug(bdd,Uin,n<<1,pr);} + /*Uout(x,y)=Uout(x,y)-RU(x,y)*/ + Cudd_Ref(p = Cudd_bddAnd(bdd, Uout, Cudd_Not(RU))); + Cudd_RecursiveDeref(bdd,Uout); + Cudd_RecursiveDeref(bdd,RU); + Uout = p; + if(pr>3){(void)fprintf(stdout,"Uout");Cudd_PrintDebug(bdd,Uout,n<<1,pr);} + /*\KW{if}(($LU(x,y)=zero$)~~\KW{or}~~($Uin(x,y)=zero$)~~\KW{or} + ($Uout(x,y)=zero$))~~KW{break}*/ + if((LU == zero)||(Uin == zero)||(Uout == zero)) { + Cudd_RecursiveDeref(bdd,LU); + break; + } + Cudd_RecursiveDeref(bdd,LU); + + } /* Next least fixed point iteration with smaller Uin and Uout */ + if (k == MAXFPIT) (void) fprintf(stderr, + "Rhombus: WARNING! MAXFPIT (%d) exceeded processing Layer %d.\n", + MAXFPIT, m); + + if (Uin != zero) { + /* $U^{m-1}(x,y) = U^{m-1}(x,y)-Uin(x,y)$*/ + Cudd_Ref(p = Cudd_bddAnd(bdd, U[m-1], Cudd_Not(Uin))); + Cudd_RecursiveDeref(bdd,U[m-1]); + U[m-1] = p; + /* $new^{m-1}(x,y) = \esists_yU^{m-1}(x,y)$*/ + Cudd_RecursiveDeref(bdd,neW[m-1]); + Cudd_Ref(neW[m-1] = Cudd_bddExistAbstract(bdd, U[m-1], ycube)); + } + if(pr>2){(void)fprintf(stdout,"U[%d]",m-1); Cudd_PrintDebug(bdd,U[m-1],n<<1,pr);} + if(pr>2){ + (void)fprintf(stdout,"new[%d]",m-1); + Cudd_PrintDebug(bdd,neW[m-1],n,pr); + } + Cudd_RecursiveDeref(bdd,Uin); + Cudd_RecursiveDeref(bdd,Uout); + + return; + +} /* end of rhombus */ + + +/**Function******************************************************************** + + Synopsis [Selects edges from a hourglass-type bilayer.] + + Description [Selects edges from a hourglass-type bilayer. Used to + pull flow. Method described in paper. More general, but more + expensive than the others.] + + SideEffects [None] + + SeeAlso [trellis rhombus hourglassPush] + +******************************************************************************/ +static void +hourglass( + DdManager * bdd, + int m /* center level of current bilayer */, + DdNode ** neW, + DdNode ** U /* arrays for flow propagation */, + DdNode ** x, + DdNode ** y, + DdNode ** z /* arrays of variables for rows and columns */, + int n /* number of x variables */, + DdNode * pryz, + DdNode * prxz /* priority functions */, + flowStats * stats) +{ + DdNode *one, *zero, + *przy, + *p, *q, *r, + *Uin, /* edges to be matched from U[m-1] */ + *Uout, /* edges to be matched from U[m] */ + *P, *Q, + *PA, *D; + int k, + pr; /* print control */ + + pr = stats->pr; + + one = Cudd_ReadOne(bdd); + zero = Cudd_Not(one); + + /* Build priority function. */ + Cudd_Ref(p = Cudd_bddSwapVariables(bdd, pryz, y, z, n)); + Cudd_Ref(przy = Cudd_bddAdjPermuteX(bdd,p,x,n)); + Cudd_RecursiveDeref(bdd,p); + if(pr>2){(void)fprintf(stdout,"przy");Cudd_PrintDebug(bdd,przy,n*3,pr);} + + /*Uout(x,y)=U^m(x,y)*/ + Cudd_Ref(Uout = U[m]); + if(pr>1){(void)fprintf(stdout,"Uout");Cudd_PrintDebug(bdd,Uout,n<<1,pr);} + + /*Uin(x,y)=U^{m-1}(x,y)*/ + Cudd_Ref(Uin = U[m-1]); + if(pr>1){(void)fprintf(stdout,"Uin");Cudd_PrintDebug(bdd,Uin,n<<1,pr);} + + for(k = 0; k < MAXFPIT; k++) { + stats->fpit++; + /*P(x,y,z)=Uin(x,y)\cdot Uout(y,z)*/ + Cudd_Ref(p = Cudd_bddSwapVariables(bdd, Uout, y, z, n)); + if(pr>2){(void)fprintf(stdout,"p");Cudd_PrintDebug(bdd,p,n<<1,pr);} + Cudd_Ref(q = Cudd_bddSwapVariables(bdd, p, x, y, n)); + Cudd_RecursiveDeref(bdd,p); + if(pr>2){(void)fprintf(stdout,"q");Cudd_PrintDebug(bdd,q,n<<1,pr);} + Cudd_Ref(P = Cudd_bddAnd(bdd, Uin, q)); + Cudd_RecursiveDeref(bdd,q); + if(pr>1){(void)fprintf(stdout,"P");Cudd_PrintDebug(bdd,P,n*3,pr);} + /*PA(x,z)=\exists_yP(x,y,z)*/ + Cudd_Ref(PA = Cudd_bddExistAbstract(bdd, P, ycube)); + if(pr>2){(void)fprintf(stdout,"PA");Cudd_PrintDebug(bdd,PA,n<<1,pr);} + if(pr>3) { + Cudd_Ref(p = Cudd_bddExistAbstract(bdd, PA, xcube)); + (void) fprintf(stdout,"p");Cudd_PrintDebug(bdd,p,n,pr); + Cudd_RecursiveDeref(bdd,p); + Cudd_Ref(p = Cudd_bddExistAbstract(bdd, PA, zcube)); + (void) fprintf(stdout,"p");Cudd_PrintDebug(bdd,p,n,pr); + Cudd_RecursiveDeref(bdd,p); + } + /*Q(x,z)= PA(x,z)\cdot \overline{\exists_{y}(PA(x,y)\cdot \Pi(z,y))}*/ + Cudd_Ref(p = Cudd_bddSwapVariables(bdd, PA, y, z, n)); + Cudd_Ref(r = Cudd_bddAndAbstract(bdd, p, przy, ycube)); + Cudd_RecursiveDeref(bdd,p); + Cudd_Ref(Q = Cudd_bddAnd(bdd, PA, Cudd_Not(r))); + Cudd_RecursiveDeref(bdd,r); + Cudd_RecursiveDeref(bdd,PA); + if(pr>2){(void)fprintf(stdout,"Q");Cudd_PrintDebug(bdd,Q,n<<1,pr);} + if(pr>3) { + Cudd_Ref(p = Cudd_bddExistAbstract(bdd, Q, xcube)); + (void) fprintf(stdout,"p");Cudd_PrintDebug(bdd,p,n,pr); + Cudd_RecursiveDeref(bdd,p); + } + /*D(x,z)= Q(x,z)\cdot \overline{\exists_{y}(Q(y,z)\cdot \Pi(x,y))}*/ + Cudd_Ref(p = Cudd_bddSwapVariables(bdd, Q, x, y, n)); + Cudd_Ref(q = Cudd_bddSwapVariables(bdd, prxz, y, z, n)); + Cudd_Ref(r = Cudd_bddAndAbstract(bdd, p, q, ycube)); + Cudd_RecursiveDeref(bdd,p); + Cudd_RecursiveDeref(bdd,q); + Cudd_Ref(D = Cudd_bddAnd(bdd, Q, Cudd_Not(r))); + Cudd_RecursiveDeref(bdd,r); + Cudd_RecursiveDeref(bdd,Q); + if(pr>1){(void)fprintf(stdout,"D");Cudd_PrintDebug(bdd,D,n<<1,pr);} + /*P(x,y,z)=P(x,y,z)\cdot D(x,z)*/ + Cudd_Ref(p = Cudd_bddAnd(bdd, P, D)); + Cudd_RecursiveDeref(bdd,D); + Cudd_RecursiveDeref(bdd,P); + P = p; + if(pr>2){(void)fprintf(stdout,"P");Cudd_PrintDebug(bdd,P,n*3,pr);} + /*Uin(x,y)=Uin(x,y)-\exists_zP(x,y,z)*/ + Cudd_Ref(p = Cudd_bddExistAbstract(bdd, P, zcube)); + if(pr>3){(void)fprintf(stdout,"p");Cudd_PrintDebug(bdd,p,n<<1,pr);} + Cudd_Ref(q = Cudd_bddAnd(bdd, Uin, Cudd_Not(p))); + Cudd_RecursiveDeref(bdd,p); + Cudd_RecursiveDeref(bdd,Uin); + Uin = q; + if(pr>1){(void)fprintf(stdout,"Uin");Cudd_PrintDebug(bdd,Uin,n<<1,pr);} + /*Uout(x,y)=Uout(x,y)-\exists_zP(z,x,y)*/ + Cudd_Ref(p = Cudd_bddSwapVariables(bdd, P, x, y, n)); + if(pr>3){(void)fprintf(stdout,"p");Cudd_PrintDebug(bdd,p,n*3,pr);} + Cudd_Ref(r = Cudd_bddSwapVariables(bdd, p, y, z, n)); + Cudd_RecursiveDeref(bdd,p); + if(pr>3){(void)fprintf(stdout,"r");Cudd_PrintDebug(bdd,r,n*3,pr);} + Cudd_Ref(p = Cudd_bddExistAbstract(bdd, r, zcube)); + Cudd_RecursiveDeref(bdd,r); + if(pr>3){(void)fprintf(stdout,"p");Cudd_PrintDebug(bdd,p,n<<1,pr);} + Cudd_Ref(q = Cudd_bddAnd(bdd, Uout, Cudd_Not(p))); + Cudd_RecursiveDeref(bdd,p); + Cudd_RecursiveDeref(bdd,Uout); + Uout = q; + if(pr>1){(void)fprintf(stdout,"Uout");Cudd_PrintDebug(bdd,Uout,n<<1,pr);} + /*\KW{if}(($P(x,y,z)=zero$)~~\KW{or}~~($Uin(x,y)=zero$)~~\KW{or} + ($Uout(x,y)=zero$))~~KW{break}*/ + if((P == zero)||(Uin == zero)||(Uout == zero)) { + Cudd_RecursiveDeref(bdd,P); + break; + } + Cudd_RecursiveDeref(bdd,P); + + } /* Next least fixed point iteration with smaller P */ + if (k == MAXFPIT) (void) fprintf(stderr, + "Hourglass: WARNING! MAXFPIT (%d) exceeded processing Layer %d.\n", + MAXFPIT, m); + + if (Uin != zero) { + /* $U^{m-1}(x,y) = U^{m-1}(x,y)-Uin(x,y)$*/ + Cudd_Ref(p = Cudd_bddAnd(bdd, U[m-1], Cudd_Not(Uin))); + Cudd_RecursiveDeref(bdd,U[m-1]); + U[m-1] = p; + /* $new^{m-1}(x,y) = \esists_yU^{m-1}(x,y)$*/ + Cudd_RecursiveDeref(bdd,neW[m-1]); + Cudd_Ref(neW[m-1] = Cudd_bddExistAbstract(bdd, U[m-1], ycube)); + } + if(pr>1){(void)fprintf(stdout,"U[%d]",m-1); Cudd_PrintDebug(bdd,U[m-1],n<<1,pr);} + if(pr>1){(void)fprintf(stdout,"new[%d]",m-1); + Cudd_PrintDebug(bdd,neW[m-1],n,pr);} + + Cudd_RecursiveDeref(bdd,Uin); + Cudd_RecursiveDeref(bdd,Uout); + Cudd_RecursiveDeref(bdd,przy); + + return; + +} /* end of hourglass */ + + +/**Function******************************************************************** + + Synopsis [Pushes flow through useful edges.] + + Description [Pushes flow from the source(s) to the sink(s) through + useful edges.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +static void +maximal_push( + DdManager * bdd, + int l /* Depth of layered network for current phase */, + DdNode ** U /* array of edge sets for flow propagation */, + DdNode ** F /* edge and flow relations */, + DdNode ** x, + DdNode ** y, + DdNode ** z /* arrays of variables for rows and columns */, + int n /* number of x variables */, + DdNode * pryz, + DdNode * prxz /* priority functions */, + flowStats * stats) +{ + DdNode *p, *q, *r, + *UT, + *lN, *cN, *rN; /* left, center, right nodes of bilayer */ + double mtl, mtc, mtr; + int m, + pr; /* print control */ + + pr = stats->pr; + + if (l == 0) { + /* F(x,y) = F(x,y) + U^{0}(x,y) */ + Cudd_Ref(q = Cudd_bddOr(bdd, *F, U[0])); + Cudd_RecursiveDeref(bdd,*F); + *F = q; + if(pr>3){(void) fprintf(stdout,"F");Cudd_PrintDebug(bdd,*F,n<<1,pr);} + return; + } + + for (m = 1; m < l; m++) { + /* lN(x) = \exists_y U^{m-1}(x,y) */ + Cudd_Ref(lN = Cudd_bddExistAbstract(bdd, U[m-1], ycube)); + mtl = Cudd_CountMinterm(bdd, lN, n); + Cudd_RecursiveDeref(bdd,lN); + + /* cN(y) = \exists_x U^{m-1}(x,y) */ + Cudd_Ref(cN = Cudd_bddExistAbstract(bdd, U[m-1], xcube)); + mtc = Cudd_CountMinterm(bdd, cN, n); + Cudd_RecursiveDeref(bdd,cN); + + /* rN(y) = \exists_x U^{m}(x,y) */ + Cudd_Ref(rN = Cudd_bddExistAbstract(bdd, U[m], xcube)); + mtr = Cudd_CountMinterm(bdd, rN, n); + Cudd_RecursiveDeref(bdd,rN); + + if (pr > 0) { + (void) fprintf(stdout, "layer = %d mtl = %g mtc = %g mtr = %g", + m, mtl, mtc, mtr); + } + if ((mtc > MANY_TIMES * mtl) && !(mtr > MANY_TIMES * mtl)) { + if (pr>0) (void) fprintf(stdout, " R\n"); + rhombusPush(bdd, m, U, x, y, z, n, pryz, prxz, stats); + } else if (mtl > MANY_TIMES * mtc) { + if (pr>0) (void) fprintf(stdout, " H\n"); + hourglassPush(bdd, m, U, x, y, z, n, pryz, prxz, stats); + } else { + if (pr>0) (void) fprintf(stdout, " T\n"); + trellisPush(bdd, m, U, x, y, z, n, pryz, prxz, stats); + } + + /* F(x,y) = F(x,y) + U^{m-1}(x,y) \cdot \overline{F(y,x)} */ + Cudd_Ref(p = Cudd_bddSwapVariables(bdd, *F, x, y, n)); + Cudd_Ref(q = Cudd_bddAnd(bdd, Cudd_Not(p), U[m-1])); + Cudd_RecursiveDeref(bdd,p); + Cudd_Ref(r = Cudd_bddOr(bdd, *F, q)); + Cudd_RecursiveDeref(bdd,q); + Cudd_RecursiveDeref(bdd,*F); + *F = r; + if(pr>3){(void) fprintf(stdout,"F");Cudd_PrintDebug(bdd,*F,n<<1,pr);} + + /* F(x,y) = F(x,y) - U^{m-1}(y,x) */ + Cudd_Ref(r = Cudd_bddSwapVariables(bdd, U[m-1], x, y, n)); + Cudd_Ref(q = Cudd_bddAnd(bdd, *F, Cudd_Not(r))); + Cudd_RecursiveDeref(bdd,r); + Cudd_RecursiveDeref(bdd,*F); + *F = q; + if(pr>3){(void) fprintf(stdout,"F");Cudd_PrintDebug(bdd,*F,n<<1,pr);} + + } /* Push maximal flow to next layer */ + + /*F(x,y)=F(x,y)+U^{l-1}(x,y)\cdot\overline{F(y,x)}*/ + Cudd_Ref(p = Cudd_bddSwapVariables(bdd, *F, x, y, n)); + Cudd_Ref(q = Cudd_bddAnd(bdd, Cudd_Not(p), U[l-1])); + Cudd_RecursiveDeref(bdd,p); + Cudd_Ref(r = Cudd_bddOr(bdd, *F, q)); + Cudd_RecursiveDeref(bdd,q); + Cudd_RecursiveDeref(bdd,*F); + *F = r; + if(pr>3){(void) fprintf(stdout,"F");Cudd_PrintDebug(bdd,*F,n<<1,pr);} + + /*F(y,x)=F(y,x)-U^{l-1}(x,y)*/ + Cudd_Ref(r = Cudd_bddSwapVariables(bdd, U[l-1], x, y, n)); + Cudd_Ref(q = Cudd_bddAnd(bdd, *F, Cudd_Not(r))); + Cudd_RecursiveDeref(bdd,r); + Cudd_RecursiveDeref(bdd,*F); + *F = q; + if(pr>1){(void) fprintf(stdout,"F");Cudd_PrintDebug(bdd,*F,n<<1,pr);} + + /*UT(x,y)=\exists_y(U^{l-1}(y,x))\cdot U^{l}(x,y)*/ + Cudd_Ref(p = Cudd_bddExistAbstract(bdd, U[l-1], xcube)); + if(pr>4){(void) fprintf(stdout,"p");Cudd_PrintDebug(bdd,p,n,pr);} + Cudd_Ref(q = Cudd_bddSwapVariables(bdd, p, x, y, n)); + Cudd_RecursiveDeref(bdd,p); + if(pr>4){(void) fprintf(stdout,"q");Cudd_PrintDebug(bdd,q,n,pr);} + Cudd_Ref(UT = Cudd_bddAnd(bdd, U[l], q)); + Cudd_RecursiveDeref(bdd,q); + if(pr>2){(void) fprintf(stdout,"UT");Cudd_PrintDebug(bdd,UT,n<<1,pr);} + + /*F(x,y)=F(x,y)+UT(x,y)\cdot\overline{F(y,x)}*/ + Cudd_Ref(p = Cudd_bddSwapVariables(bdd, *F, x, y, n)); + Cudd_Ref(q = Cudd_bddAnd(bdd, Cudd_Not(p), UT)); + Cudd_RecursiveDeref(bdd,p); + Cudd_Ref(r = Cudd_bddOr(bdd, *F, q)); + Cudd_RecursiveDeref(bdd,q); + Cudd_RecursiveDeref(bdd,*F); + *F = r; + if(pr>3){(void) fprintf(stdout,"F");Cudd_PrintDebug(bdd,*F,n<<1,pr);} + + /*F(y,x)=F(y,x)-UT(x,y)*/ + Cudd_Ref(r = Cudd_bddSwapVariables(bdd, UT, x, y, n)); + Cudd_RecursiveDeref(bdd,UT); + Cudd_Ref(q = Cudd_bddAnd(bdd, *F, Cudd_Not(r))); + Cudd_RecursiveDeref(bdd,r); + Cudd_RecursiveDeref(bdd,*F); + *F = q; + if(pr>1){(void) fprintf(stdout,"F");Cudd_PrintDebug(bdd,*F,n<<1,pr);} + + return; + +} /* end of maximal_push */ + + +/**Function******************************************************************** + + Synopsis [] + + Description [] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +static void +trellisPush( + DdManager * bdd, + int m /* Current layer */, + DdNode ** U /* Array of edge sets for flow propagation */, + DdNode ** x, + DdNode ** y, + DdNode ** z /* Arrays of variables for rows and columns */, + int n /* Number of x variables */, + DdNode * pryz, + DdNode * prxz /* Priority functions */, + flowStats * stats) +{ + DdNode *one, *zero, + *p, *r, + *Uin, /* Edges to be matched from U[m-1] */ + *Uout, /* Edges to be matched from U[m] */ + *RU, *LU, + *P, + *Ml; + + int i, + pr; /* Print control */ + + pr = stats->pr; + + one = Cudd_ReadOne(bdd); + zero = Cudd_Not(one); + + /*Uout(x,y)=U^m(x,y)*/ + Cudd_Ref(Uout = U[m]); + if(pr>3){(void)fprintf(stdout,"Uout");Cudd_PrintDebug(bdd,Uout,n<<1,pr);} + + /*Uin(x,y)=U^{m-1}(x,y)*/ + Cudd_Ref(Uin = U[m-1]); + if(pr>3){(void)fprintf(stdout,"Uin");Cudd_PrintDebug(bdd,Uin,n<<1,pr);} + + for(i=0; ifpit++; + /*LU(x,y)=Uin(x,y)\cdot\overline{\exists_{z}(Uin(z,y)\cdot\Pi(x,z))}*/ + Cudd_Ref(p = Cudd_bddSwapVariables(bdd, Uin, x, z, n)); + Cudd_Ref(r = Cudd_bddAndAbstract(bdd, p, prxz, zcube)); + Cudd_RecursiveDeref(bdd,p); + Cudd_Ref(LU = Cudd_bddAnd(bdd, Uin, Cudd_Not(r))); + Cudd_RecursiveDeref(bdd,r); + if(pr>3){(void)fprintf(stdout,"LU");Cudd_PrintDebug(bdd,LU,n<<1,pr);} + + /*Ml(y)=\exists_{x}LU(x,y)*/ + Cudd_Ref(Ml = Cudd_bddExistAbstract(bdd, LU, xcube)); + if(pr>3){(void)fprintf(stdout,"Ml");Cudd_PrintDebug(bdd,Ml,n,pr);} + + /*P(x,y)=Ml(x)\cdot Uout(x,y)*/ + Cudd_Ref(p = Cudd_bddSwapVariables(bdd, Ml, x, y, n)); + Cudd_Ref(P = Cudd_bddAnd(bdd, p, Uout)); + Cudd_RecursiveDeref(bdd,p); + Cudd_RecursiveDeref(bdd,Ml); + if(pr>3){(void)fprintf(stdout,"P");Cudd_PrintDebug(bdd,P,n<<1,pr);} + + /*RU(x,y)= P(x,y)\cdot \overline{\exists_{z}(P(x,z)\cdot \Pi(y,z))}*/ + Cudd_Ref(p = Cudd_bddSwapVariables(bdd, P, y, z, n)); + Cudd_Ref(r = Cudd_bddAndAbstract(bdd, p, pryz, zcube)); + Cudd_RecursiveDeref(bdd,p); + Cudd_Ref(RU = Cudd_bddAnd(bdd, P, Cudd_Not(r))); + Cudd_RecursiveDeref(bdd,r); + Cudd_RecursiveDeref(bdd,P); + if(pr>3){(void)fprintf(stdout,"RU");Cudd_PrintDebug(bdd,RU,n<<1,pr);} + + /*Uin(x,y)=Uin(x,y)-LU(x,y)*/ + Cudd_Ref(p = Cudd_bddAnd(bdd, Uin, Cudd_Not(LU))); + Cudd_RecursiveDeref(bdd,Uin); + Uin = p; + if(pr>3){(void)fprintf(stdout,"Uin");Cudd_PrintDebug(bdd,Uin,n<<1,pr);} + + /*Uout(x,y)=Uout(x,y)-RU(x,y)*/ + Cudd_Ref(p = Cudd_bddAnd(bdd, Uout, Cudd_Not(RU))); + Cudd_RecursiveDeref(bdd,Uout); + Cudd_RecursiveDeref(bdd,RU); + Uout = p; + if(pr>3){(void)fprintf(stdout,"Uout");Cudd_PrintDebug(bdd,Uout,n<<1,pr);} + + /*\KW{if}(($LU(x,y)=zero$)~~\KW{or}~~($Uin(x,y)=zero$))~~KW{break}*/ + if((LU == zero)||(Uin == zero)) { + Cudd_RecursiveDeref(bdd,LU); + break; + } + + Cudd_RecursiveDeref(bdd,LU); + + } /* Next least fixed point iteration with smaller Uin and Uout */ + if (i == MAXFPIT) (void) fprintf(stderr, + "TrellisPush: ERROR! MAXFPIT (%d) exceeded at layer %d.\n", + MAXFPIT, m); + + /* $U^{m}(x,y) = U^{m}(x,y)-Uout(x,y)$*/ + if (Uout != zero) { + Cudd_Ref(p = Cudd_bddAnd(bdd, U[m], Cudd_Not(Uout))); + Cudd_RecursiveDeref(bdd,U[m]); + U[m] = p; + if(pr>3){(void)fprintf(stdout,"U[%d]",m); + Cudd_PrintDebug(bdd,U[m],n<<1,pr);} + } + + Cudd_RecursiveDeref(bdd,Uin); + Cudd_RecursiveDeref(bdd,Uout); + +} /* end of trellisPush */ + + +/**Function******************************************************************** + + Synopsis [] + + Description [] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +static void +rhombusPush( + DdManager * bdd, + int m /* Current layer */, + DdNode ** U /* Array of edge sets for flow propagation */, + DdNode ** x, + DdNode ** y, + DdNode ** z /* Arrays of variables for rows and columns */, + int n /* Number of x variables */, + DdNode * pryz, + DdNode * prxz /* Priority functions */, + flowStats * stats) +{ + DdNode *one, *zero, + *p, *r, + *Uin, /* Edges to be matched from U[m-1] */ + *Uout, /* Edges to be matched from U[m] */ + *RU, *LU, + *P, + *Ml; + + int i, + pr; /* Print control */ + + pr = stats->pr; + + one = Cudd_ReadOne(bdd); + zero = Cudd_Not(one); + + /*Uout(x,y)=U^m(x,y)*/ + Cudd_Ref(Uout = U[m]); + if(pr>3){(void)fprintf(stdout,"Uout");Cudd_PrintDebug(bdd,Uout,n<<1,pr);} + + /*Uin(x,y)=U^{m-1}(x,y)*/ + Cudd_Ref(Uin = U[m-1]); + if(pr>3){(void)fprintf(stdout,"Uin");Cudd_PrintDebug(bdd,Uin,n<<1,pr);} + + for(i = 0; i < MAXFPIT; i++) { + stats->fpit++; + /*RU(x,y)=Uin(x,y)\cdot\overline{\exists_{z}(Uin(x,z)\cdot\Pi(y,z))}*/ + Cudd_Ref(p = Cudd_bddSwapVariables(bdd, Uin, y, z, n)); + Cudd_Ref(r = Cudd_bddAndAbstract(bdd, p, pryz, zcube)); + Cudd_RecursiveDeref(bdd,p); + Cudd_Ref(RU = Cudd_bddAnd(bdd, Uin, Cudd_Not(r))); + Cudd_RecursiveDeref(bdd,r); + if(pr>3){(void)fprintf(stdout,"RU");Cudd_PrintDebug(bdd,RU,n<<1,pr);} + + /*Ml(y)=\exists_{x}RU(x,y)*/ + Cudd_Ref(Ml = Cudd_bddExistAbstract(bdd, RU, xcube)); + if(pr>3){(void)fprintf(stdout,"Ml");Cudd_PrintDebug(bdd,Ml,n,pr);} + + /*P(x,y)=Ml(x)\cdot Uout(x,y)*/ + Cudd_Ref(p = Cudd_bddSwapVariables(bdd, Ml, x, y, n)); + Cudd_Ref(P = Cudd_bddAnd(bdd, p, Uout)); + Cudd_RecursiveDeref(bdd,p); + Cudd_RecursiveDeref(bdd,Ml); + if(pr>3){(void)fprintf(stdout,"P");Cudd_PrintDebug(bdd,P,n<<1,pr);} + + /*LU(x,y)= P(x,y)\cdot \overline{\exists_{z}(P(z,y)\cdot \Pi(x,z))}*/ + Cudd_Ref(p = Cudd_bddSwapVariables(bdd, P, x, z, n)); + Cudd_Ref(r = Cudd_bddAndAbstract(bdd, p, prxz, zcube)); + Cudd_RecursiveDeref(bdd,p); + Cudd_Ref(LU = Cudd_bddAnd(bdd, P, Cudd_Not(r))); + Cudd_RecursiveDeref(bdd,r); + Cudd_RecursiveDeref(bdd,P); + if(pr>3){(void)fprintf(stdout,"LU");Cudd_PrintDebug(bdd,LU,n<<1,pr);} + + /*Uin(x,y)=Uin(x,y)-RU(x,y)*/ + Cudd_Ref(p = Cudd_bddAnd(bdd, Uin, Cudd_Not(RU))); + Cudd_RecursiveDeref(bdd,Uin); + Uin = p; + if(pr>3){(void)fprintf(stdout,"Uin");Cudd_PrintDebug(bdd,Uin,n<<1,pr);} + + /*Uout(x,y)=Uout(x,y)-LU(x,y)*/ + Cudd_Ref(p = Cudd_bddAnd(bdd, Uout, Cudd_Not(LU))); + Cudd_RecursiveDeref(bdd,Uout); + Cudd_RecursiveDeref(bdd,LU); + Uout = p; + if(pr>3){(void)fprintf(stdout,"Uout");Cudd_PrintDebug(bdd,Uout,n<<1,pr);} + + /*\KW{if}(($RU(x,y)=zero$)~~\KW{or}~~($Uin(x,y)=zero$))~~KW{break}*/ + if((RU == zero)||(Uin == zero)) { + Cudd_RecursiveDeref(bdd,RU); + break; + } + + Cudd_RecursiveDeref(bdd,RU); + + } /* Next least fixed point iteration with smaller Uin and Uout */ + if (i == MAXFPIT) (void) fprintf(stderr, + "RhombusPush: ERROR! MAXFPIT (%d) exceeded at layer %d.\n", + MAXFPIT, m); + + /* $U^{m}(x,y) = U^{m}(x,y)-Uout(x,y)$*/ + if (Uout != zero) { + Cudd_Ref(p = Cudd_bddAnd(bdd, U[m], Cudd_Not(Uout))); + Cudd_RecursiveDeref(bdd,U[m]); + U[m] = p; + if(pr>3){(void)fprintf(stdout,"U[%d]",m); + Cudd_PrintDebug(bdd,U[m],n<<1,pr);} + } + + Cudd_RecursiveDeref(bdd,Uin); + Cudd_RecursiveDeref(bdd,Uout); + + return; + +} /* end of rhombusPush */ + + +/**Function******************************************************************** + + Synopsis [] + + Description [] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +static void +hourglassPush( + DdManager * bdd, + int m /* Current layer */, + DdNode ** U /* Array of edge sets for flow propagation */, + DdNode ** x, + DdNode ** y, + DdNode ** z /* Arrays of variables for rows and columns */, + int n /* Number of x variables */, + DdNode * pryz, + DdNode * prxz /* Priority functions */, + flowStats * stats) +{ + DdNode *one, *zero, + *przy, + *p, *q, *r, + *Uin, /* Edges to be matched from U[m-1] */ + *Uout, /* Edges to be matched from U[m] */ + *P, *Q, + *PA, *D; + + int i, + pr; /* Print control */ + + pr = stats->pr; + + one = Cudd_ReadOne(bdd); + zero = Cudd_Not(one); + + /* Build priority function. */ + Cudd_Ref(p = Cudd_bddSwapVariables(bdd, pryz, y, z, n)); + Cudd_Ref(przy = Cudd_bddAdjPermuteX(bdd,p,x,n)); + Cudd_RecursiveDeref(bdd,p); + if(pr>2){(void)fprintf(stdout,"przy");Cudd_PrintDebug(bdd,przy,n*3,pr);} + + /*Uout(x,y)=U^m(x,y)*/ + Cudd_Ref(Uout = U[m]); + if(pr>3){(void)fprintf(stdout,"Uout");Cudd_PrintDebug(bdd,Uout,n<<1,pr);} + + /*Uin(x,y)=U^{m-1}(x,y)*/ + Cudd_Ref(Uin = U[m-1]); + if(pr>3){(void)fprintf(stdout,"Uin");Cudd_PrintDebug(bdd,Uin,n<<1,pr);} + + for(i = 0; i < MAXFPIT; i++) { + stats->fpit++; + /*P(x,y,z)=Uin(x,y)\cdot Uout(y,z)*/ + Cudd_Ref(p = Cudd_bddSwapVariables(bdd, Uout, y, z, n)); + if(pr>2){(void)fprintf(stdout,"p");Cudd_PrintDebug(bdd,p,n<<1,pr);} + Cudd_Ref(q = Cudd_bddSwapVariables(bdd, p, x, y, n)); + Cudd_RecursiveDeref(bdd,p); + if(pr>2){(void)fprintf(stdout,"q");Cudd_PrintDebug(bdd,q,n<<1,pr);} + Cudd_Ref(P = Cudd_bddAnd(bdd, Uin, q)); + Cudd_RecursiveDeref(bdd,q); + if(pr>1){(void)fprintf(stdout,"P");Cudd_PrintDebug(bdd,P,n*3,pr);} + + /*PA(x,z)=\exists_yP(x,y,z)*/ + Cudd_Ref(PA = Cudd_bddExistAbstract(bdd, P, ycube)); + if(pr>2){(void)fprintf(stdout,"PA");Cudd_PrintDebug(bdd,PA,n<<1,pr);} + if(pr>3) { + Cudd_Ref(p = Cudd_bddExistAbstract(bdd, PA, xcube)); + (void) fprintf(stdout,"p");Cudd_PrintDebug(bdd,p,n,pr); + Cudd_RecursiveDeref(bdd,p); + Cudd_Ref(p = Cudd_bddExistAbstract(bdd, PA, zcube)); + (void) fprintf(stdout,"p");Cudd_PrintDebug(bdd,p,n,pr); + Cudd_RecursiveDeref(bdd,p); + } + + /*Q(x,z)= PA(x,z)\cdot \overline{\exists_{y}(PA(x,y)\cdot \Pi(z,y))}*/ + Cudd_Ref(p = Cudd_bddSwapVariables(bdd, PA, y, z, n)); + Cudd_Ref(r = Cudd_bddAndAbstract(bdd, p, przy, ycube)); + Cudd_RecursiveDeref(bdd,p); + Cudd_Ref(Q = Cudd_bddAnd(bdd, PA, Cudd_Not(r))); + Cudd_RecursiveDeref(bdd,r); + Cudd_RecursiveDeref(bdd,PA); + if(pr>2){(void)fprintf(stdout,"Q");Cudd_PrintDebug(bdd,Q,n<<1,pr);} + if(pr>3) { + Cudd_Ref(p = Cudd_bddExistAbstract(bdd, Q, xcube)); + (void) fprintf(stdout,"p");Cudd_PrintDebug(bdd,p,n,pr); + Cudd_RecursiveDeref(bdd,p); + } + + /*D(x,z)= Q(x,z)\cdot \overline{\exists_{y}(Q(y,z)\cdot \Pi(x,y))}*/ + Cudd_Ref(p = Cudd_bddSwapVariables(bdd, Q, x, y, n)); + Cudd_Ref(q = Cudd_bddSwapVariables(bdd, prxz, y, z, n)); + Cudd_Ref(r = Cudd_bddAndAbstract(bdd, p, q, ycube)); + Cudd_RecursiveDeref(bdd,p); + Cudd_RecursiveDeref(bdd,q); + Cudd_Ref(D = Cudd_bddAnd(bdd, Q, Cudd_Not(r))); + Cudd_RecursiveDeref(bdd,r); + Cudd_RecursiveDeref(bdd,Q); + if(pr>1){(void)fprintf(stdout,"D");Cudd_PrintDebug(bdd,D,n<<1,pr);} + + /*P(x,y,z)=P(x,y,z)\cdot D(x,z)*/ + Cudd_Ref(p = Cudd_bddAnd(bdd, P, D)); + Cudd_RecursiveDeref(bdd,D); + Cudd_RecursiveDeref(bdd,P); + P = p; + if(pr>2){(void)fprintf(stdout,"P");Cudd_PrintDebug(bdd,P,n*3,pr);} + + /*Uin(x,y)=Uin(x,y)-\exists_zP(x,y,z)*/ + Cudd_Ref(p = Cudd_bddExistAbstract(bdd, P, zcube)); + if(pr>3){(void)fprintf(stdout,"p");Cudd_PrintDebug(bdd,p,n<<1,pr);} + Cudd_Ref(q = Cudd_bddAnd(bdd, Uin, Cudd_Not(p))); + Cudd_RecursiveDeref(bdd,p); + Cudd_RecursiveDeref(bdd,Uin); + Uin = q; + if(pr>1){(void)fprintf(stdout,"Uin");Cudd_PrintDebug(bdd,Uin,n<<1,pr);} + + /*Uout(x,y)=Uout(x,y)-\exists_zP(z,x,y)*/ + Cudd_Ref(p = Cudd_bddSwapVariables(bdd, P, x, y, n)); + if(pr>3){(void)fprintf(stdout,"p");Cudd_PrintDebug(bdd,p,n*3,pr);} + Cudd_Ref(r = Cudd_bddSwapVariables(bdd, p, y, z, n)); + Cudd_RecursiveDeref(bdd,p); + if(pr>3){(void)fprintf(stdout,"r");Cudd_PrintDebug(bdd,r,n*3,pr);} + Cudd_Ref(p = Cudd_bddExistAbstract(bdd, r, zcube)); + Cudd_RecursiveDeref(bdd,r); + if(pr>3){(void)fprintf(stdout,"p");Cudd_PrintDebug(bdd,p,n<<1,pr);} + Cudd_Ref(q = Cudd_bddAnd(bdd, Uout, Cudd_Not(p))); + Cudd_RecursiveDeref(bdd,p); + Cudd_RecursiveDeref(bdd,Uout); + Uout = q; + if(pr>1){(void)fprintf(stdout,"Uout");Cudd_PrintDebug(bdd,Uout,n<<1,pr);} + + /*\KW{if}(($P(x,y,z)=zero$)~~\KW{or}~~($Uin(x,y)=zero$)~~\KW{or} + ($Uout(x,y)=zero$))~~KW{break}*/ + if((P == zero)||(Uin == zero)||(Uout == zero)) { + Cudd_RecursiveDeref(bdd,P); + break; + } + + Cudd_RecursiveDeref(bdd,P); + + } /* Next least fixed point iteration with smaller P */ + if (i == MAXFPIT) (void) fprintf(stderr, + "HourglassPush: ERROR! MAXFPIT (%d) exceeded at layer %d.\n", + MAXFPIT, m); + + /* $U^{m}(x,y) = U^{m}(x,y)-Uout(x,y)$*/ + if (Uout != zero) { + Cudd_Ref(p = Cudd_bddAnd(bdd, U[m], Cudd_Not(Uout))); + Cudd_RecursiveDeref(bdd,U[m]); + U[m] = p; + } + if(pr>1){(void)fprintf(stdout,"U[%d]",m); Cudd_PrintDebug(bdd,U[m],n<<1,pr);} + + Cudd_RecursiveDeref(bdd,Uin); + Cudd_RecursiveDeref(bdd,Uout); + Cudd_RecursiveDeref(bdd,przy); + + return; + +} /* end of hourglassPush */ diff --git a/distr/nanotrav/ntrShort.c b/distr/nanotrav/ntrShort.c new file mode 100644 index 0000000..4016558 --- /dev/null +++ b/distr/nanotrav/ntrShort.c @@ -0,0 +1,578 @@ +/**CFile*********************************************************************** + + FileName [ntrShort.c] + + PackageName [ntr] + + Synopsis [Symbolic shortest paths algorithms.] + + Description [This file contains the functions that implement the + symbolic version of several shortest path algorithms described in the + JFM paper on ADDs.] + + Author [Fabio Somenzi, Iris Bahar] + + 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 "ntr.h" +#include "cuddInt.h" + +/*---------------------------------------------------------------------------*/ +/* Constant declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Stucture declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Type declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Variable declarations */ +/*---------------------------------------------------------------------------*/ + +#ifndef lint +static char rcsid[] UTIL_UNUSED = "$Id: ntrShort.c,v 1.4 2004/08/13 18:28:28 fabio Exp fabio $"; +#endif + +/*---------------------------------------------------------------------------*/ +/* Macro declarations */ +/*---------------------------------------------------------------------------*/ + +/**AutomaticStart*************************************************************/ + +/*---------------------------------------------------------------------------*/ +/* Static function prototypes */ +/*---------------------------------------------------------------------------*/ + +static DdNode * ntrBellman (DdManager *dd, DdNode *D, DdNode *source, DdNode **x, DdNode **y, int vars, int pr); +static DdNode * ntrWarshall (DdManager *dd, DdNode *D, DdNode **x, DdNode **y, int vars, int pr); +static DdNode * ntrSquare (DdManager *dd, DdNode *D, DdNode **x, DdNode **y, DdNode **z, int vars, int pr, int st); + +/**AutomaticEnd***************************************************************/ + +/*---------------------------------------------------------------------------*/ +/* Definition of exported functions */ +/*---------------------------------------------------------------------------*/ + +/**Function******************************************************************** + + Synopsis [Computes shortest paths in a state graph.] + + Description [Computes shortest paths in the state transition graph of + a network. Three methods are availabe: +
            +
          • Bellman-Ford algorithm for single-source shortest paths; the + algorithm computes the distance (number of transitions) from the initial + states to all states. +
          • Floyd-Warshall algorithm for all-pair shortest paths. +
          • Repeated squaring algorithm for all-pair shortest paths. +
          + The function returns 1 in case of success; 0 otherwise. + ] + + SideEffects [ADD variables are created in the manager.] + + SeeAlso [] + +******************************************************************************/ +int +Ntr_ShortestPaths( + DdManager * dd, + BnetNetwork * net, + NtrOptions * option) +{ + NtrPartTR *TR; + DdNode *edges, *source, *res, *r, *q, *bddSource; + DdNode **xadd, **yadd, **zadd; + int i; + int pr = option->verb; + int algorithm = option->shortPath; + int selectiveTrace = option->selectiveTrace; + int nvars = net->nlatches; + + /* Set background to infinity for shortest paths. */ + Cudd_SetBackground(dd,Cudd_ReadPlusInfinity(dd)); + + /* Build the monolithic TR. */ + TR = Ntr_buildTR(dd,net,option,NTR_IMAGE_MONO); + + /* Build the ADD variable vectors for x and y. */ + xadd = ALLOC(DdNode *, nvars); + yadd = ALLOC(DdNode *, nvars); + for(i = 0; i < nvars; i++) { + q = Cudd_addIthVar(dd,TR->x[i]->index); + Cudd_Ref(q); + xadd[i] = q; + q = Cudd_addIthVar(dd,TR->y[i]->index); + Cudd_Ref(q); + yadd[i] = q; + } + + /* Convert the transition relation BDD into an ADD... */ + q = Cudd_BddToAdd(dd,TR->part[0]); + Cudd_Ref(q); + /* ...replacing zeroes with infinities... */ + r = Cudd_addIte(dd,q,Cudd_ReadOne(dd),Cudd_ReadPlusInfinity(dd)); + Cudd_Ref(r); + Cudd_RecursiveDeref(dd,q); + /* ...and zeroing the diagonal. */ + q = Cudd_addXeqy(dd,nvars,xadd,yadd); + Cudd_Ref(q); + edges = Cudd_addIte(dd,q,Cudd_ReadZero(dd),r); + Cudd_Ref(edges); + Cudd_RecursiveDeref(dd,r); + Cudd_RecursiveDeref(dd,q); + + switch(algorithm) { + case NTR_SHORT_BELLMAN: + bddSource = Ntr_initState(dd,net,option); + source = Cudd_BddToAdd(dd,bddSource); + Cudd_Ref(source); + res = ntrBellman(dd,edges,source,xadd,yadd,nvars,pr); + if (res == NULL) return(0); + Cudd_Ref(res); + Cudd_RecursiveDeref(dd,source); + Cudd_RecursiveDeref(dd,bddSource); + if (pr >= 0) { + (void) fprintf(stdout,"Distance Matrix"); + Cudd_PrintDebug(dd,res,nvars,pr); + } + break; + case NTR_SHORT_FLOYD: + res = ntrWarshall(dd,edges,xadd,yadd,nvars,pr); + if (res == NULL) return(0); + Cudd_Ref(res); + if (pr >= 0) { + (void) fprintf(stdout,"Distance Matrix"); + Cudd_PrintDebug(dd,res,2*nvars,pr); + } + break; + case NTR_SHORT_SQUARE: + /* Create a third set of ADD variables. */ + zadd = ALLOC(DdNode *, nvars); + for(i = 0; i < nvars; i++) { + int level; + level = Cudd_ReadIndex(dd,TR->x[i]->index); + q = Cudd_addNewVarAtLevel(dd,level); + Cudd_Ref(q); + zadd[i] = q; + } + /* Compute the shortest paths. */ + res = ntrSquare(dd,edges,zadd,yadd,xadd,nvars,pr,selectiveTrace); + if (res == NULL) return(0); + Cudd_Ref(res); + /* Dispose of the extra variables. */ + for(i = 0; i < nvars; i++) { + Cudd_RecursiveDeref(dd,zadd[i]); + } + FREE(zadd); + if (pr >= 0) { + (void) fprintf(stdout,"Distance Matrix"); + Cudd_PrintDebug(dd,res,2*nvars,pr); + } + break; + default: + (void) printf("Unrecognized method. Try again.\n"); + return(0); + } + + /* Here we should compute the paths. */ + + /* Clean up. */ + Ntr_freeTR(dd,TR); + Cudd_RecursiveDeref(dd,edges); + Cudd_RecursiveDeref(dd,res); + for(i = 0; i < nvars; i++) { + Cudd_RecursiveDeref(dd,xadd[i]); + Cudd_RecursiveDeref(dd,yadd[i]); + } + FREE(xadd); + FREE(yadd); + + if (option->autoDyn & 1) { + (void) printf("Order after short path computation\n"); + if (!Bnet_PrintOrder(net,dd)) return(0); + } + + return(1); + +} /* end of Ntr_ShortestPaths */ + + +/*---------------------------------------------------------------------------*/ +/* Definition of internal functions */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Definition of static functions */ +/*---------------------------------------------------------------------------*/ + + +/**Function******************************************************************** + + Synopsis [Bellman-Ford algorithm for single-source shortest paths.] + + Description [Bellman-Ford algorithm for single-source shortest + paths. Returns the vector of the distances of all states from the + initial states. In case of multiple initial states the distance for + each state is from the nearest initial state. Negative-weight + cycles are detected, though only in the naive way. (Lack of + convergence after nodes-1 iterations.) In such a case, a constant + ADD with value minus infinity is returned. Bellman-Ford is based on + matrix-vector multiplication. The matrix is the distance matrix + D(x,y), such that D(a,b) is the length of the arc connecting state a + to state b. The vector V(x) stores the distances of all states from + the initial states. The actual vector used in the matrix-vector + multiplication is diff(x), that holds those distances that have + changed during the last update.] + + SideEffects [] + + SeeAlso [ntrWarshall ntrSquare] + +******************************************************************************/ +static DdNode * +ntrBellman( + DdManager *dd, + DdNode *D, + DdNode *source, + DdNode **x, + DdNode **y, + int vars, + int pr) +{ + DdNode *u, *w, *V, *min, *diff; + DdApaNumber i, nodes, one; + int digits = vars + 1; + + /* To avoid overflow when there are many variables, use APA. */ + nodes = Cudd_NewApaNumber(digits); + Cudd_ApaPowerOfTwo(digits,nodes,vars); + i = Cudd_NewApaNumber(digits); + one = Cudd_NewApaNumber(digits); + Cudd_ApaSetToLiteral(digits,one,1); + +#if 0 + /* Find the distances from the initial state along paths using one + ** arc. */ + w = Cudd_Cofactor(dd,D,source); /* works only if source is a cube */ + Cudd_Ref(w); + V = Cudd_addSwapVariables(dd,w,x,y,vars); + Cudd_Ref(V); + Cudd_RecursiveDeref(dd,w); +#endif + + /* The initial states are at distance 0. The other states are + ** initially at infinite distance. */ + V = Cudd_addIte(dd,source,Cudd_ReadZero(dd),Cudd_ReadPlusInfinity(dd)); + Cudd_Ref(V); + + /* Selective trace algorithm. For the next update, only consider the + ** nodes whose distance has changed in the last update. */ + diff = V; + Cudd_Ref(diff); + + for (Cudd_ApaSetToLiteral(digits,i,1); + Cudd_ApaCompare(digits,i,digits,nodes) < 0; + Cudd_ApaAdd(digits,i,one,i)) { + if (pr>2) {(void) printf("V"); Cudd_PrintDebug(dd,V,vars,pr);} + /* Compute the distances via triangulation as a function of x. */ + w = Cudd_addTriangle(dd,diff,D,x,vars); + Cudd_Ref(w); + Cudd_RecursiveDeref(dd,diff); + u = Cudd_addSwapVariables(dd,w,x,y,vars); + Cudd_Ref(u); + Cudd_RecursiveDeref(dd,w); + if (pr>2) {(void) printf("u"); Cudd_PrintDebug(dd,u,vars,pr);} + + /* Take the minimum of the previous distances and those just + ** computed. */ + min = Cudd_addApply(dd,Cudd_addMinimum,V,u); + Cudd_Ref(min); + Cudd_RecursiveDeref(dd,u); + if (pr>2) {(void) printf("min"); Cudd_PrintDebug(dd,min,vars,pr);} + + if (V == min) { /* convergence */ + Cudd_RecursiveDeref(dd,min); + if (pr>0) { + (void) printf("Terminating after "); + Cudd_ApaPrintDecimal(stdout,digits,i); + (void) printf(" iterations\n"); + } + break; + } + /* Find the distances that decreased. */ + diff = Cudd_addApply(dd,Cudd_addDiff,V,min); + Cudd_Ref(diff); + if (pr>2) {(void) printf("diff"); Cudd_PrintDebug(dd,diff,vars,pr);} + Cudd_RecursiveDeref(dd,V); + V = min; + } + /* Negative cycle detection. */ + if (Cudd_ApaCompare(digits,i,digits,nodes) == 0 && + diff != Cudd_ReadPlusInfinity(dd)) { + (void) printf("Negative cycle\n"); + Cudd_RecursiveDeref(dd,diff); + Cudd_RecursiveDeref(dd,V); + V = Cudd_ReadMinusInfinity(dd); + Cudd_Ref(V); + } + + Cudd_Deref(V); + FREE(i); + FREE(nodes); + FREE(one); + return(V); + +} /* end of ntrBellman */ + + +/**Function******************************************************************** + + Synopsis [Floyd-Warshall algorithm for all-pair shortest paths.] + + Description [] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +static DdNode * +ntrWarshall( + DdManager *dd, + DdNode *D, + DdNode **x, + DdNode **y, + int vars, + int pr) +{ + DdNode *one, *zero; + DdNode *xminterm, *w, *V, *V2; + DdNode *P, *R; + int i; + int nodes; + int k,u; + long start_time; + if (vars > 30) + nodes = 1000000000; + else + nodes = 1 << vars; + + one = DD_ONE(dd); + zero = DD_ZERO(dd); + Cudd_Ref(R = D); /* make copy of original matrix */ + + /* Extract pivot row and column from D */ + start_time = util_cpu_time(); + for (k = 0; k < nodes; k++) { + if (k % 10000 == 0) { + (void) printf("Starting iteration %d at time %s\n", + k,util_print_time(util_cpu_time() - start_time)); + } + Cudd_Ref(xminterm = one); + u = k; + for (i = vars-1; i >= 0; i--) { + if (u&1) { + Cudd_Ref(w = Cudd_addIte(dd,x[i],xminterm,zero)); + } else { + Cudd_Ref(w = Cudd_addIte(dd,x[i],zero,xminterm)); + } + Cudd_RecursiveDeref(dd,xminterm); + xminterm = w; + u >>= 1; + } + + Cudd_Ref(V = Cudd_Cofactor(dd,R,xminterm)); + Cudd_RecursiveDeref(dd,xminterm); + if (pr>2) {(void) printf("V"); Cudd_PrintDebug(dd,V,vars,pr);} + + + Cudd_Ref(xminterm = one); + u = k; + for (i = vars-1; i >= 0; i--) { + if (u&1) { + Cudd_Ref(w = Cudd_addIte(dd,y[i],xminterm,zero)); + } else { + Cudd_Ref(w = Cudd_addIte(dd,y[i],zero,xminterm)); + } + Cudd_RecursiveDeref(dd,xminterm); + xminterm = w; + u >>= 1; + } + + Cudd_Ref(V2 = Cudd_Cofactor(dd,R,xminterm)); + Cudd_RecursiveDeref(dd,xminterm); + if (pr>2) {(void) printf("V2"); Cudd_PrintDebug(dd,V2,vars,pr);} + + Cudd_Ref(P = Cudd_addOuterSum(dd,R,V,V2)); + + Cudd_RecursiveDeref(dd,V); + Cudd_RecursiveDeref(dd,V2); + Cudd_RecursiveDeref(dd,R); + R = P; + if (pr>2) {(void) printf("R"); Cudd_PrintDebug(dd,R,vars,pr);} + } + + Cudd_Deref(R); + return(R); + +} /* end of ntrWarshall */ + + +/**Function******************************************************************** + + Synopsis [Repeated squaring algorithm for all-pairs shortest paths.] + + Description [] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +static DdNode * +ntrSquare( + DdManager *dd /* manager */, + DdNode *D /* D(z,y): distance matrix */, + DdNode **x /* array of x variables */, + DdNode **y /* array of y variables */, + DdNode **z /* array of z variables */, + int vars /* number of variables in each of the three arrays */, + int pr /* verbosity level */, + int st /* use the selective trace algorithm */) +{ + DdNode *zero; + DdNode *I; /* identity matirix */ + DdNode *w, *V, *P, *M, *R, *RT; + DdNode *diff, *min, *minDiag; + int n; + int neg; + long start_time; + + zero = Cudd_ReadZero(dd); + /* Make a working copy of the original matrix. */ + R = D; + Cudd_Ref(R); + I = Cudd_addXeqy(dd,vars,z,y); /* identity matrix */ + Cudd_Ref(I); + + /* Make a copy of the matrix for the selective trace algorithm. */ + diff = R; + Cudd_Ref(diff); + + start_time = util_cpu_time(); + for (n = vars; n >= 0; n--) { + printf("Starting iteration %d at time %s\n",vars-n, + util_print_time(util_cpu_time() - start_time)); + + /* Check for negative cycles: They are identified by negative + ** elements on the diagonal. + */ + + /* Extract values from the diagonal. */ + Cudd_Ref(w = Cudd_addIte(dd,I,R,zero)); + minDiag = Cudd_addFindMin(dd,w); /* no need to ref */ + neg = Cudd_V(minDiag) < 0; + Cudd_RecursiveDeref(dd,w); + if (neg) { + Cudd_RecursiveDeref(dd,diff); + (void) printf("Negative cycle after %d iterations!\n",vars-n); + break; + } + + /* Prepare the first operand of matrix multiplication: + ** diff(z,y) -> RT(x,y) -> V(x,z) + */ + + /* RT(x,y) */ + Cudd_Ref(RT = Cudd_addSwapVariables(dd,diff,x,z,vars)); + Cudd_RecursiveDeref(dd,diff); + /* V(x,z) */ + Cudd_Ref(V = Cudd_addSwapVariables(dd,RT,y,z,vars)); + Cudd_RecursiveDeref(dd,RT); + if (pr > 0) { + double pathcount; + (void) printf("V"); Cudd_PrintDebug(dd,V,2*vars,pr); + pathcount = Cudd_CountPath(V); + (void) printf("Path count = %g\n", pathcount); + } + + /* V(x,z) * R(z,y) -> P(x,y) */ + Cudd_Ref(P = Cudd_addTriangle(dd,V,R,z,vars)); + Cudd_RecursiveDeref(dd,V); + /* P(x,y) => M(z,y) */ + Cudd_Ref(M = Cudd_addSwapVariables(dd,P,x,z,vars)); + Cudd_RecursiveDeref(dd,P); + if (pr>0) {(void) printf("M"); Cudd_PrintDebug(dd,M,2*vars,pr);} + + /* min(z,y) */ + Cudd_Ref(min = Cudd_addApply(dd,Cudd_addMinimum,R,M)); + Cudd_RecursiveDeref(dd,M); + + if (R == min) { + Cudd_RecursiveDeref(dd,min); + if (pr>0) {printf("Done after %d iterations\n",vars-n+1); } + break; + } + /* diff(z,y) */ + if (st) { + Cudd_Ref(diff = Cudd_addApply(dd,Cudd_addDiff,min,R)); + } else { + Cudd_Ref(diff = min); + } + Cudd_RecursiveDeref(dd,R); + R = min; /* keep a copy of matrix at current iter. */ + if (pr > 0) { + double pathcount; + (void) printf("R"); Cudd_PrintDebug(dd,R,2*vars,pr); + pathcount = Cudd_CountPath(R); + (void) printf("Path count = %g\n", pathcount); + } + + if (n == 0) { + (void) printf("Negative cycle!\n"); + break; + } + + } + Cudd_RecursiveDeref(dd,I); + Cudd_Deref(R); + return(R); + +} /* end of ntrSquare */ diff --git a/distr/nanotrav/ntrZddTest.c b/distr/nanotrav/ntrZddTest.c new file mode 100644 index 0000000..dbe23cf --- /dev/null +++ b/distr/nanotrav/ntrZddTest.c @@ -0,0 +1,468 @@ +/**CFile*********************************************************************** + + FileName [ntrZddTest.c] + + PackageName [ntr] + + Synopsis [ZDD test functions.] + + 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.] + +******************************************************************************/ + +#include "ntr.h" +#include "cuddInt.h" + +/*---------------------------------------------------------------------------*/ +/* Constant declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Stucture declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Type declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Variable declarations */ +/*---------------------------------------------------------------------------*/ + +#ifndef lint +static char rcsid[] UTIL_UNUSED = "$Id: ntrZddTest.c,v 1.14 2004/08/13 18:28:28 fabio Exp fabio $"; +#endif + +/*---------------------------------------------------------------------------*/ +/* Macro declarations */ +/*---------------------------------------------------------------------------*/ + +/**AutomaticStart*************************************************************/ + +/*---------------------------------------------------------------------------*/ +/* Static function prototypes */ +/*---------------------------------------------------------------------------*/ + +static int reorderZdd (BnetNetwork *net, DdManager *dd, NtrOptions *option); + +/**AutomaticEnd***************************************************************/ + +/*---------------------------------------------------------------------------*/ +/* Definition of exported functions */ +/*---------------------------------------------------------------------------*/ + + +/**Function******************************************************************** + + Synopsis [Tests ZDDs.] + + Description [Tests ZDDs. Returns 1 if successful; 0 otherwise.] + + SideEffects [Creates ZDD variables in the manager.] + + SeeAlso [] + +******************************************************************************/ +int +Ntr_testZDD( + DdManager * dd, + BnetNetwork * net, + NtrOptions * option) +{ + DdNode **zdd; /* array of converted outputs */ + int nz; /* actual number of ZDDs */ + int result; + int i, j; + BnetNode *node; /* auxiliary pointer to network node */ + int pr = option->verb; + int level; /* aux. var. used to print variable orders */ + char **names; /* array used to print variable orders */ + int nvars; + + /* Build an array of ZDDs for the output functions or for the + ** specified node. */ + Cudd_AutodynDisable(dd); + Cudd_AutodynDisableZdd(dd); + zdd = ALLOC(DdNode *,net->noutputs); + result = Cudd_zddVarsFromBddVars(dd,1); + if (result == 0) return(0); + if (option->node == NULL) { + for (nz = 0; nz < net->noutputs; nz++) { + if (!st_lookup(net->hash,net->outputs[nz],&node)) { + return(0); + } + zdd[nz] = Cudd_zddPortFromBdd(dd, node->dd); + if (zdd[nz]) { + Cudd_Ref(zdd[nz]); + (void) printf("%s", node->name); + result = Cudd_zddPrintDebug(dd,zdd[nz],Cudd_ReadZddSize(dd),pr); + if (result == 0) return(0); + } else { + (void) printf("Conversion to ZDD failed.\n"); + } + } + } else { + if (!st_lookup(net->hash,option->node,&node)) { + return(0); + } + zdd[0] = Cudd_zddPortFromBdd(dd, node->dd); + if (zdd[0]) { + Cudd_Ref(zdd[0]); + (void) printf("%s", node->name); + result = Cudd_zddPrintDebug(dd,zdd[0],Cudd_ReadZddSize(dd),pr); + if (result == 0) return(0); + } else { + (void) printf("Conversion to ZDD failed.\n"); + } + nz = 1; + } + +#ifdef DD_DEBUG + result = Cudd_CheckKeys(dd); + if (result != 0) { + (void) fprintf(stderr,"Error reported by Cudd_CheckKeys\n"); + return(0); + } +#endif + + if (option->autoDyn & 1) { + Cudd_AutodynEnable(dd,CUDD_REORDER_SAME); + } + if (option->autoDyn & 2) { + Cudd_AutodynEnableZdd(dd,CUDD_REORDER_SAME); + } + + /* Convert the ZDDs back to BDDs and check identity. */ + for (i = 0; i < nz; i++) { + DdNode *checkBdd; + checkBdd = Cudd_zddPortToBdd(dd,zdd[i]); + if (checkBdd) { + Cudd_Ref(checkBdd); + if (option->node == NULL) { + if (!st_lookup(net->hash,net->outputs[i],&node)) { + return(0); + } + } else { + if (!st_lookup(net->hash,option->node,&node)) { + return(0); + } + } + if (checkBdd != node->dd) { + (void) fprintf(stdout,"Equivalence failed at node %s", + node->name); + result = Cudd_PrintDebug(dd,checkBdd,Cudd_ReadZddSize(dd),pr); + if (result == 0) return(0); + } + Cudd_RecursiveDeref(dd,checkBdd); + } else { + (void) printf("Conversion to BDD failed.\n"); + } + } + +#ifdef DD_DEBUG + result = Cudd_CheckKeys(dd); + if (result != 0) { + (void) fprintf(stderr,"Error reported by Cudd_CheckKeys\n"); + return(0); + } +#endif + + /* Play with the ZDDs a little. */ + if (nz > 2) { + DdNode *f; + DdNode *g1, *g2, *g; + f = Cudd_zddIte(dd,zdd[0],zdd[1],zdd[2]); + if (f == NULL) return(0); + cuddRef(f); + g1 = Cudd_zddIntersect(dd,zdd[0],zdd[1]); + if (g1 == NULL) { + Cudd_RecursiveDerefZdd(dd,f); + return(0); + } + cuddRef(g1); + g2 = Cudd_zddDiff(dd,zdd[2],zdd[0]); + if (g2 == NULL) { + Cudd_RecursiveDerefZdd(dd,f); + Cudd_RecursiveDerefZdd(dd,g1); + return(0); + } + cuddRef(g2); + g = Cudd_zddUnion(dd,g1,g2); + if (g == NULL) { + Cudd_RecursiveDerefZdd(dd,f); + Cudd_RecursiveDerefZdd(dd,g1); + Cudd_RecursiveDerefZdd(dd,g2); + return(0); + } + cuddRef(g); + Cudd_RecursiveDerefZdd(dd,g1); + Cudd_RecursiveDerefZdd(dd,g2); + if (g != f) { + (void) fprintf(stderr,"f != g!\n"); + } + Cudd_RecursiveDerefZdd(dd,g); + Cudd_RecursiveDerefZdd(dd,f); + } + +#ifdef DD_DEBUG + result = Cudd_CheckKeys(dd); + if (result != 0) { + (void) fprintf(stderr,"Error reported by Cudd_CheckKeys\n"); + return(0); + } +#endif + + /* Perform ZDD reordering. */ + result = reorderZdd(net,dd,option); + if (result == 0) return(0); + + /* Print final ZDD order. */ + nvars = Cudd_ReadZddSize(dd); + names = ALLOC(char *, nvars); + if (names == NULL) return(0); + for (i = 0; i < nvars; i++) { + names[i] = NULL; + } + if (option->reordering != CUDD_REORDER_NONE) { + for (i = 0; i < net->npis; i++) { + if (!st_lookup(net->hash,net->inputs[i],&node)) { + FREE(names); + return(0); + } + level = Cudd_ReadPermZdd(dd,node->var); + names[level] = node->name; + } + for (i = 0; i < net->nlatches; i++) { + if (!st_lookup(net->hash,net->latches[i][1],&node)) { + FREE(names); + return(0); + } + level = Cudd_ReadPermZdd(dd,node->var); + names[level] = node->name; + } + (void) printf("New order\n"); + for (i = 0, j = 0; i < nvars; i++) { + if (names[i] == NULL) continue; + if((j%8 == 0)&&j) (void) printf("\n"); + (void) printf("%s ",names[i]); + j++; + } + (void) printf("\n"); + } + FREE(names); + + /* Dispose of ZDDs. */ + for (i = 0; i < nz; i++) { + Cudd_RecursiveDerefZdd(dd,zdd[i]); + } + FREE(zdd); + return(1); + +} /* end of Ntr_testZDD */ + + +/**Function******************************************************************** + + Synopsis [Builds ZDD covers.] + + Description [] + + SideEffects [Creates ZDD variables in the manager.] + + SeeAlso [] + +******************************************************************************/ +int +Ntr_testISOP( + DdManager * dd, + BnetNetwork * net, + NtrOptions * option) +{ + DdNode **zdd; /* array of converted outputs */ + DdNode *bdd; /* return value of Cudd_zddIsop */ + int nz; /* actual number of ZDDs */ + int result; + int i; + BnetNode *node; /* auxiliary pointer to network node */ + int pr = option->verb; + + /* Build an array of ZDDs for the output functions or the specified + ** node. */ + Cudd_zddRealignEnable(dd); + Cudd_AutodynDisableZdd(dd); + zdd = ALLOC(DdNode *,net->noutputs); + result = Cudd_zddVarsFromBddVars(dd,2); + if (result == 0) return(0); + if (option->node == NULL) { + nz = net->noutputs; + for (i = 0; i < nz; i++) { + if (!st_lookup(net->hash,net->outputs[i],&node)) { + return(0); + } + bdd = Cudd_zddIsop(dd, node->dd, node->dd, &zdd[i]); + if (bdd != node->dd) return(0); + Cudd_Ref(bdd); + Cudd_RecursiveDeref(dd,bdd); + if (zdd[i]) { + Cudd_Ref(zdd[i]); + (void) printf("%s", node->name); + result = Cudd_zddPrintDebug(dd,zdd[i],Cudd_ReadZddSize(dd),pr); + if (result == 0) return(0); + if (option->printcover) { + int *path; + DdGen *gen; + char *str = ALLOC(char,Cudd_ReadSize(dd)+1); + if (str == NULL) return(0); + (void) printf("Testing iterator on ZDD paths:\n"); + Cudd_zddForeachPath(dd,zdd[i],gen,path) { + str = Cudd_zddCoverPathToString(dd,path,str); + (void) printf("%s 1\n", str); + } + (void) printf("\n"); + FREE(str); + result = Cudd_zddPrintCover(dd,zdd[i]); + + if (result == 0) return(0); + } + } else { + (void) printf("Conversion to ISOP failed.\n"); + return(0); + } + } + } else { + nz = 1; + if (!st_lookup(net->hash,option->node,&node)) { + return(0); + } + bdd = Cudd_zddIsop(dd, node->dd, node->dd, &zdd[0]); + if (bdd != node->dd) return(0); + Cudd_Ref(bdd); + Cudd_RecursiveDeref(dd,bdd); + if (zdd[0]) { + Cudd_Ref(zdd[0]); + (void) printf("%s", node->name); + result = Cudd_zddPrintDebug(dd,zdd[0],Cudd_ReadZddSize(dd),pr); + if (result == 0) return(0); + if (option->printcover) { + int *path; + DdGen *gen; + char *str = ALLOC(char,Cudd_ReadSize(dd)+1); + if (str == NULL) return(0); + (void) printf("Testing iterator on ZDD paths:\n"); + Cudd_zddForeachPath(dd,zdd[0],gen,path) { + str = Cudd_zddCoverPathToString(dd,path,str); + (void) printf("%s 1\n", str); + } + (void) printf("\n"); + FREE(str); + + result = Cudd_zddPrintCover(dd,zdd[0]); + if (result == 0) return(0); + } + } else { + (void) printf("Conversion to ISOP failed.\n"); + return(0); + } + } + if (option->autoDyn) { + Cudd_AutodynEnableZdd(dd,CUDD_REORDER_SAME); + } + + /* Perform ZDD reordering. */ + result = reorderZdd(net,dd,option); + if (result == 0) return(0); + + /* Dispose of ZDDs. */ + for (i = 0; i < nz; i++) { + Cudd_RecursiveDerefZdd(dd,zdd[i]); + } + FREE(zdd); + + return(1); + +} /* end of Ntr_testISOP */ + + +/*---------------------------------------------------------------------------*/ +/* Definition of internal functions */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Definition of static functions */ +/*---------------------------------------------------------------------------*/ + + +/**Function******************************************************************** + + Synopsis [Applies reordering to the ZDDs.] + + Description [Explicitly applies reordering to the ZDDs. Returns 1 if + successful; 0 otherwise.] + + SideEffects [None] + + SeeAlso [] + +*****************************************************************************/ +static int +reorderZdd( + BnetNetwork * net, + DdManager * dd /* DD Manager */, + NtrOptions * option) +{ + int result; /* return value from functions */ + + /* Perform the final reordering. */ + if (option->reordering != CUDD_REORDER_NONE) { + (void) printf("Number of inputs = %d\n",net->ninputs); + + dd->siftMaxVar = 1000000; + result = Cudd_zddReduceHeap(dd,option->reordering,1); + if (result == 0) return(0); + + /* Print symmetry stats if pertinent */ + if (option->reordering == CUDD_REORDER_SYMM_SIFT || + option->reordering == CUDD_REORDER_SYMM_SIFT_CONV) + Cudd_zddSymmProfile(dd, 0, dd->sizeZ - 1); + } + + return(1); + +} /* end of reorderZdd */ + diff --git a/distr/nanotrav/rcn25.blif b/distr/nanotrav/rcn25.blif new file mode 100644 index 0000000..c11dbe0 --- /dev/null +++ b/distr/nanotrav/rcn25.blif @@ -0,0 +1,335 @@ +.model rcn25 +.outputs n0 n1 n2 n3 n4 n5 n6 n7 n8 n9 n10 n11 n12 n13 n14 n15 n16 n17 \ +n18 n19 n20 n21 n22 n23 n24 + +.latch nn0 n0 2 +.latch nn1 n1 2 +.latch nn2 n2 2 +.latch nn3 n3 2 +.latch nn4 n4 2 +.latch nn5 n5 2 +.latch nn6 n6 2 +.latch nn7 n7 2 +.latch nn8 n8 2 +.latch nn9 n9 2 +.latch nn10 n10 2 +.latch nn11 n11 2 +.latch nn12 n12 2 +.latch nn13 n13 2 +.latch nn14 n14 2 +.latch nn15 n15 2 +.latch nn16 n16 2 +.latch nn17 n17 2 +.latch nn18 n18 2 +.latch nn19 n19 2 +.latch nn20 n20 2 +.latch nn21 n21 2 +.latch nn22 n22 2 +.latch nn23 n23 2 +.latch nn24 n24 2 + +.names n0 s0 +0 1 +.names n0 c1 +1 1 +.names n1 n0 c1 s1 +100 1 +010 1 +001 1 +111 1 +.names n1 n0 c1 c2 +11- 1 +1-1 1 +-11 1 +.names n2 n1 c2 s2 +100 1 +010 1 +001 1 +111 1 +.names n2 n1 c2 c3 +11- 1 +1-1 1 +-11 1 +.names n3 n2 c3 s3 +100 1 +010 1 +001 1 +111 1 +.names n3 n2 c3 c4 +11- 1 +1-1 1 +-11 1 +.names n4 n3 c4 s4 +100 1 +010 1 +001 1 +111 1 +.names n4 n3 c4 c5 +11- 1 +1-1 1 +-11 1 +.names n5 n4 c5 s5 +100 1 +010 1 +001 1 +111 1 +.names n5 n4 c5 c6 +11- 1 +1-1 1 +-11 1 +.names n6 n5 c6 s6 +100 1 +010 1 +001 1 +111 1 +.names n6 n5 c6 c7 +11- 1 +1-1 1 +-11 1 +.names n7 n6 c7 s7 +100 1 +010 1 +001 1 +111 1 +.names n7 n6 c7 c8 +11- 1 +1-1 1 +-11 1 +.names n8 n7 c8 s8 +100 1 +010 1 +001 1 +111 1 +.names n8 n7 c8 c9 +11- 1 +1-1 1 +-11 1 +.names n9 n8 c9 s9 +100 1 +010 1 +001 1 +111 1 +.names n9 n8 c9 c10 +11- 1 +1-1 1 +-11 1 +.names n10 n9 c10 s10 +100 1 +010 1 +001 1 +111 1 +.names n10 n9 c10 c11 +11- 1 +1-1 1 +-11 1 +.names n11 n10 c11 s11 +100 1 +010 1 +001 1 +111 1 +.names n11 n10 c11 c12 +11- 1 +1-1 1 +-11 1 +.names n12 n11 c12 s12 +100 1 +010 1 +001 1 +111 1 +.names n12 n11 c12 c13 +11- 1 +1-1 1 +-11 1 +.names n13 n12 c13 s13 +100 1 +010 1 +001 1 +111 1 +.names n13 n12 c13 c14 +11- 1 +1-1 1 +-11 1 +.names n14 n13 c14 s14 +100 1 +010 1 +001 1 +111 1 +.names n14 n13 c14 c15 +11- 1 +1-1 1 +-11 1 +.names n15 n14 c15 s15 +100 1 +010 1 +001 1 +111 1 +.names n15 n14 c15 c16 +11- 1 +1-1 1 +-11 1 +.names n16 n15 c16 s16 +100 1 +010 1 +001 1 +111 1 +.names n16 n15 c16 c17 +11- 1 +1-1 1 +-11 1 +.names n17 n16 c17 s17 +100 1 +010 1 +001 1 +111 1 +.names n17 n16 c17 c18 +11- 1 +1-1 1 +-11 1 +.names n18 n17 c18 s18 +100 1 +010 1 +001 1 +111 1 +.names n18 n17 c18 c19 +11- 1 +1-1 1 +-11 1 +.names n19 n18 c19 s19 +100 1 +010 1 +001 1 +111 1 +.names n19 n18 c19 c20 +11- 1 +1-1 1 +-11 1 +.names n20 n19 c20 s20 +100 1 +010 1 +001 1 +111 1 +.names n20 n19 c20 c21 +11- 1 +1-1 1 +-11 1 +.names n21 n20 c21 s21 +100 1 +010 1 +001 1 +111 1 +.names n21 n20 c21 c22 +11- 1 +1-1 1 +-11 1 +.names n22 n21 c22 s22 +100 1 +010 1 +001 1 +111 1 +.names n22 n21 c22 c23 +11- 1 +1-1 1 +-11 1 +.names n23 n22 c23 s23 +100 1 +010 1 +001 1 +111 1 +.names n23 n22 c23 c24 +11- 1 +1-1 1 +-11 1 +.names n24 n23 c24 s24 +100 1 +010 1 +001 1 +111 1 +.names n24 n23 c24 c25 +11- 1 +1-1 1 +-11 1 +.names n24 c25 s25 +10 1 +01 1 +.names n24 c25 s26 +11 1 + +.names s25 s26 of +00 0 + +.names n0 of s0 n1 nn0 +101- 1 +0--1 1 +.names n0 of s1 n2 nn1 +101- 1 +0--1 1 +.names n0 of s2 n3 nn2 +101- 1 +0--1 1 +.names n0 of s3 n4 nn3 +101- 1 +0--1 1 +.names n0 of s4 n5 nn4 +101- 1 +0--1 1 +.names n0 of s5 n6 nn5 +101- 1 +0--1 1 +.names n0 of s6 n7 nn6 +101- 1 +0--1 1 +.names n0 of s7 n8 nn7 +101- 1 +0--1 1 +.names n0 of s8 n9 nn8 +101- 1 +0--1 1 +.names n0 of s9 n10 nn9 +101- 1 +0--1 1 +.names n0 of s10 n11 nn10 +101- 1 +0--1 1 +.names n0 of s11 n12 nn11 +101- 1 +0--1 1 +.names n0 of s12 n13 nn12 +101- 1 +0--1 1 +.names n0 of s13 n14 nn13 +101- 1 +0--1 1 +.names n0 of s14 n15 nn14 +101- 1 +0--1 1 +.names n0 of s15 n16 nn15 +101- 1 +0--1 1 +.names n0 of s16 n17 nn16 +101- 1 +0--1 1 +.names n0 of s17 n18 nn17 +101- 1 +0--1 1 +.names n0 of s18 n19 nn18 +101- 1 +0--1 1 +.names n0 of s19 n20 nn19 +101- 1 +0--1 1 +.names n0 of s20 n21 nn20 +101- 1 +0--1 1 +.names n0 of s21 n22 nn21 +101- 1 +0--1 1 +.names n0 of s22 n23 nn22 +101- 1 +0--1 1 +.names n0 of s23 n24 nn23 +101- 1 +0--1 1 +.names n0 of s24 nn24 +101 1 + +.end diff --git a/distr/nanotrav/rcn25.out b/distr/nanotrav/rcn25.out new file mode 100644 index 0000000..a44f970 --- /dev/null +++ b/distr/nanotrav/rcn25.out @@ -0,0 +1,521 @@ +# Nanotrav Version #0.12, Release date 2003/12/31 +# ./nanotrav -p 1 -envelope rcn25.blif +# CUDD Version 2.4.2 +Order before final reordering +n0 n1 n2 n3 n4 n5 n6 n7 +n8 n9 n10 n11 n12 n13 n14 n15 +n16 n17 n18 n19 n20 n21 n22 n23 +n24 +Number of inputs = 25 +@@@@@@@@@@@@@@@@@@@@@@@@@ +S0: 1 nodes 1 leaves 3.35544e+07 minterms +Envelope[1]: 68 nodes 1 leaves 1.95734e+07 minterms +Envelope[2]: 131 nodes 1 leaves 1.53791e+07 minterms +Envelope[3]: 240 nodes 1 leaves 1.30489e+07 minterms +Envelope[4]: 351 nodes 1 leaves 1.07188e+07 minterms +Envelope[5]: 365 nodes 1 leaves 9.08766e+06 minterms +Envelope[6]: 672 nodes 1 leaves 7.88374e+06 minterms +Envelope[7]: 977 nodes 1 leaves 6.85458e+06 minterms +Envelope[8]: 1697 nodes 1 leaves 6.16039e+06 minterms +Envelope[9]: 2507 nodes 1 leaves 5.53173e+06 minterms +Envelope[10]: 2728 nodes 1 leaves 4.99328e+06 minterms +Envelope[11]: 4877 nodes 1 leaves 4.56022e+06 minterms +Envelope[12]: 7131 nodes 1 leaves 4.15173e+06 minterms +Envelope[13]: 10837 nodes 1 leaves 3.83181e+06 minterms +Envelope[14]: 16376 nodes 1 leaves 3.53694e+06 minterms +Envelope[15]: 18686 nodes 1 leaves 3.26485e+06 minterms +Envelope[16]: 27175 nodes 1 leaves 3.03016e+06 minterms +Envelope[17]: 37624 nodes 1 leaves 2.81134e+06 minterms +Envelope[18]: 42091 nodes 1 leaves 2.62598e+06 minterms +Envelope[19]: 64761 nodes 1 leaves 2.45532e+06 minterms +Envelope[20]: 88199 nodes 1 leaves 2.29512e+06 minterms +Envelope[21]: 112012 nodes 1 leaves 2.15501e+06 minterms +Envelope[22]: 148131 nodes 1 leaves 2.02284e+06 minterms +Envelope[23]: 178957 nodes 1 leaves 1.90343e+06 minterms +Envelope[24]: 213207 nodes 1 leaves 1.79426e+06 minterms +Envelope[25]: 251015 nodes 1 leaves 1.69064e+06 minterms +Envelope[26]: 278969 nodes 1 leaves 1.59836e+06 minterms +Envelope[27]: 298983 nodes 1 leaves 1.51117e+06 minterms +Envelope[28]: 310186 nodes 1 leaves 1.4295e+06 minterms +Envelope[29]: 314312 nodes 1 leaves 1.35474e+06 minterms +Envelope[30]: 312346 nodes 1 leaves 1.2838e+06 minterms +Envelope[31]: 308909 nodes 1 leaves 1.21948e+06 minterms +Envelope[32]: 304183 nodes 1 leaves 1.15867e+06 minterms +Envelope[33]: 298541 nodes 1 leaves 1.10083e+06 minterms +Envelope[34]: 292868 nodes 1 leaves 1.04754e+06 minterms +Envelope[35]: 286698 nodes 1 leaves 996946 minterms +Envelope[36]: 280610 nodes 1 leaves 949953 minterms +Envelope[37]: 274275 nodes 1 leaves 905778 minterms +Envelope[38]: 267711 nodes 1 leaves 863616 minterms +Envelope[39]: 261513 nodes 1 leaves 824606 minterms +Envelope[40]: 255196 nodes 1 leaves 787378 minterms +Envelope[41]: 248890 nodes 1 leaves 752197 minterms +Envelope[42]: 242617 nodes 1 leaves 719152 minterms +Envelope[43]: 236080 nodes 1 leaves 687560 minterms +Envelope[44]: 230130 nodes 1 leaves 658155 minterms +Envelope[45]: 224259 nodes 1 leaves 629967 minterms +Envelope[46]: 218166 nodes 1 leaves 603079 minterms +Envelope[47]: 212397 nodes 1 leaves 577815 minterms +Envelope[48]: 206597 nodes 1 leaves 553658 minterms +Envelope[49]: 201169 nodes 1 leaves 531033 minterms +Envelope[50]: 195784 nodes 1 leaves 509531 minterms +Envelope[51]: 190388 nodes 1 leaves 488904 minterms +Envelope[52]: 185402 nodes 1 leaves 469490 minterms +Envelope[53]: 180396 nodes 1 leaves 450891 minterms +Envelope[54]: 175724 nodes 1 leaves 433247 minterms +Envelope[55]: 171253 nodes 1 leaves 416458 minterms +Envelope[56]: 166524 nodes 1 leaves 400345 minterms +Envelope[57]: 162304 nodes 1 leaves 385129 minterms +Envelope[58]: 158158 nodes 1 leaves 370518 minterms +Envelope[59]: 154136 nodes 1 leaves 356541 minterms +Envelope[60]: 150218 nodes 1 leaves 343262 minterms +Envelope[61]: 146293 nodes 1 leaves 330504 minterms +Envelope[62]: 142731 nodes 1 leaves 318444 minterms +Envelope[63]: 139152 nodes 1 leaves 306873 minterms +Envelope[64]: 135570 nodes 1 leaves 295766 minterms +Envelope[65]: 132114 nodes 1 leaves 285183 minterms +Envelope[66]: 128777 nodes 1 leaves 275032 minterms +Envelope[67]: 125644 nodes 1 leaves 265348 minterms +Envelope[68]: 122532 nodes 1 leaves 256089 minterms +Envelope[69]: 119388 nodes 1 leaves 247191 minterms +Envelope[70]: 116557 nodes 1 leaves 238707 minterms +Envelope[71]: 113576 nodes 1 leaves 230531 minterms +Envelope[72]: 110737 nodes 1 leaves 222700 minterms +Envelope[73]: 107964 nodes 1 leaves 215170 minterms +Envelope[74]: 105272 nodes 1 leaves 207896 minterms +Envelope[75]: 102720 nodes 1 leaves 200935 minterms +Envelope[76]: 100098 nodes 1 leaves 194214 minterms +Envelope[77]: 97630 nodes 1 leaves 187719 minterms +Envelope[78]: 95248 nodes 1 leaves 181488 minterms +Envelope[79]: 92891 nodes 1 leaves 175479 minterms +Envelope[80]: 90738 nodes 1 leaves 169733 minterms +Envelope[81]: 88566 nodes 1 leaves 164201 minterms +Envelope[82]: 86372 nodes 1 leaves 158855 minterms +Envelope[83]: 84200 nodes 1 leaves 153722 minterms +Envelope[84]: 82108 nodes 1 leaves 148752 minterms +Envelope[85]: 80162 nodes 1 leaves 143977 minterms +Envelope[86]: 78254 nodes 1 leaves 139369 minterms +Envelope[87]: 76349 nodes 1 leaves 134921 minterms +Envelope[88]: 74645 nodes 1 leaves 130668 minterms +Envelope[89]: 72849 nodes 1 leaves 126558 minterms +Envelope[90]: 71140 nodes 1 leaves 122588 minterms +Envelope[91]: 69484 nodes 1 leaves 118779 minterms +Envelope[92]: 67898 nodes 1 leaves 115076 minterms +Envelope[93]: 66429 nodes 1 leaves 111539 minterms +Envelope[94]: 64879 nodes 1 leaves 108113 minterms +Envelope[95]: 63332 nodes 1 leaves 104807 minterms +Envelope[96]: 61892 nodes 1 leaves 101634 minterms +Envelope[97]: 60487 nodes 1 leaves 98554 minterms +Envelope[98]: 59076 nodes 1 leaves 95579 minterms +Envelope[99]: 57675 nodes 1 leaves 92712 minterms +Envelope[100]: 56346 nodes 1 leaves 89943 minterms +Envelope[101]: 55101 nodes 1 leaves 87270 minterms +Envelope[102]: 53857 nodes 1 leaves 84669 minterms +Envelope[103]: 52673 nodes 1 leaves 82155 minterms +Envelope[104]: 51498 nodes 1 leaves 79722 minterms +Envelope[105]: 50375 nodes 1 leaves 77355 minterms +Envelope[106]: 49253 nodes 1 leaves 75077 minterms +Envelope[107]: 48157 nodes 1 leaves 72867 minterms +Envelope[108]: 47096 nodes 1 leaves 70729 minterms +Envelope[109]: 46100 nodes 1 leaves 68652 minterms +Envelope[110]: 45047 nodes 1 leaves 66635 minterms +Envelope[111]: 44107 nodes 1 leaves 64689 minterms +Envelope[112]: 43198 nodes 1 leaves 62806 minterms +Envelope[113]: 42227 nodes 1 leaves 60981 minterms +Envelope[114]: 41297 nodes 1 leaves 59228 minterms +Envelope[115]: 40371 nodes 1 leaves 57524 minterms +Envelope[116]: 39479 nodes 1 leaves 55874 minterms +Envelope[117]: 38623 nodes 1 leaves 54279 minterms +Envelope[118]: 37792 nodes 1 leaves 52739 minterms +Envelope[119]: 37000 nodes 1 leaves 51264 minterms +Envelope[120]: 36185 nodes 1 leaves 49837 minterms +Envelope[121]: 35400 nodes 1 leaves 48443 minterms +Envelope[122]: 34580 nodes 1 leaves 47093 minterms +Envelope[123]: 33793 nodes 1 leaves 45782 minterms +Envelope[124]: 33084 nodes 1 leaves 44519 minterms +Envelope[125]: 32388 nodes 1 leaves 43292 minterms +Envelope[126]: 31710 nodes 1 leaves 42089 minterms +Envelope[127]: 31025 nodes 1 leaves 40920 minterms +Envelope[128]: 30350 nodes 1 leaves 39778 minterms +Envelope[129]: 29683 nodes 1 leaves 38664 minterms +Envelope[130]: 29050 nodes 1 leaves 37589 minterms +Envelope[131]: 28418 nodes 1 leaves 36551 minterms +Envelope[132]: 27804 nodes 1 leaves 35547 minterms +Envelope[133]: 27184 nodes 1 leaves 34573 minterms +Envelope[134]: 26621 nodes 1 leaves 33636 minterms +Envelope[135]: 26074 nodes 1 leaves 32724 minterms +Envelope[136]: 25528 nodes 1 leaves 31831 minterms +Envelope[137]: 24996 nodes 1 leaves 30967 minterms +Envelope[138]: 24472 nodes 1 leaves 30133 minterms +Envelope[139]: 23993 nodes 1 leaves 29324 minterms +Envelope[140]: 23514 nodes 1 leaves 28535 minterms +Envelope[141]: 23008 nodes 1 leaves 27769 minterms +Envelope[142]: 22525 nodes 1 leaves 27029 minterms +Envelope[143]: 22039 nodes 1 leaves 26318 minterms +Envelope[144]: 21561 nodes 1 leaves 25624 minterms +Envelope[145]: 21094 nodes 1 leaves 24950 minterms +Envelope[146]: 20685 nodes 1 leaves 24289 minterms +Envelope[147]: 20249 nodes 1 leaves 23651 minterms +Envelope[148]: 19794 nodes 1 leaves 23023 minterms +Envelope[149]: 19369 nodes 1 leaves 22418 minterms +Envelope[150]: 18976 nodes 1 leaves 21837 minterms +Envelope[151]: 18589 nodes 1 leaves 21272 minterms +Envelope[152]: 18201 nodes 1 leaves 20723 minterms +Envelope[153]: 17806 nodes 1 leaves 20198 minterms +Envelope[154]: 17419 nodes 1 leaves 19684 minterms +Envelope[155]: 17049 nodes 1 leaves 19180 minterms +Envelope[156]: 16672 nodes 1 leaves 18691 minterms +Envelope[157]: 16315 nodes 1 leaves 18214 minterms +Envelope[158]: 16005 nodes 1 leaves 17741 minterms +Envelope[159]: 15679 nodes 1 leaves 17284 minterms +Envelope[160]: 15341 nodes 1 leaves 16836 minterms +Envelope[161]: 14999 nodes 1 leaves 16397 minterms +Envelope[162]: 14667 nodes 1 leaves 15962 minterms +Envelope[163]: 14365 nodes 1 leaves 15544 minterms +Envelope[164]: 14066 nodes 1 leaves 15138 minterms +Envelope[165]: 13792 nodes 1 leaves 14743 minterms +Envelope[166]: 13539 nodes 1 leaves 14361 minterms +Envelope[167]: 13283 nodes 1 leaves 13992 minterms +Envelope[168]: 13022 nodes 1 leaves 13632 minterms +Envelope[169]: 12765 nodes 1 leaves 13280 minterms +Envelope[170]: 12497 nodes 1 leaves 12938 minterms +Envelope[171]: 12257 nodes 1 leaves 12605 minterms +Envelope[172]: 11990 nodes 1 leaves 12279 minterms +Envelope[173]: 11716 nodes 1 leaves 11958 minterms +Envelope[174]: 11436 nodes 1 leaves 11646 minterms +Envelope[175]: 11180 nodes 1 leaves 11345 minterms +Envelope[176]: 10939 nodes 1 leaves 11056 minterms +Envelope[177]: 10717 nodes 1 leaves 10771 minterms +Envelope[178]: 10488 nodes 1 leaves 10493 minterms +Envelope[179]: 10255 nodes 1 leaves 10221 minterms +Envelope[180]: 10013 nodes 1 leaves 9957 minterms +Envelope[181]: 9810 nodes 1 leaves 9699 minterms +Envelope[182]: 9568 nodes 1 leaves 9449 minterms +Envelope[183]: 9355 nodes 1 leaves 9206 minterms +Envelope[184]: 9176 nodes 1 leaves 8967 minterms +Envelope[185]: 8990 nodes 1 leaves 8733 minterms +Envelope[186]: 8810 nodes 1 leaves 8512 minterms +Envelope[187]: 8621 nodes 1 leaves 8297 minterms +Envelope[188]: 8421 nodes 1 leaves 8091 minterms +Envelope[189]: 8200 nodes 1 leaves 7895 minterms +Envelope[190]: 7992 nodes 1 leaves 7705 minterms +Envelope[191]: 7816 nodes 1 leaves 7519 minterms +Envelope[192]: 7641 nodes 1 leaves 7338 minterms +Envelope[193]: 7475 nodes 1 leaves 7161 minterms +Envelope[194]: 7307 nodes 1 leaves 6986 minterms +Envelope[195]: 7137 nodes 1 leaves 6814 minterms +Envelope[196]: 6956 nodes 1 leaves 6644 minterms +Envelope[197]: 6784 nodes 1 leaves 6477 minterms +Envelope[198]: 6642 nodes 1 leaves 6315 minterms +Envelope[199]: 6515 nodes 1 leaves 6157 minterms +Envelope[200]: 6377 nodes 1 leaves 6000 minterms +Envelope[201]: 6221 nodes 1 leaves 5847 minterms +Envelope[202]: 6069 nodes 1 leaves 5699 minterms +Envelope[203]: 5919 nodes 1 leaves 5555 minterms +Envelope[204]: 5797 nodes 1 leaves 5417 minterms +Envelope[205]: 5662 nodes 1 leaves 5282 minterms +Envelope[206]: 5535 nodes 1 leaves 5149 minterms +Envelope[207]: 5414 nodes 1 leaves 5018 minterms +Envelope[208]: 5293 nodes 1 leaves 4890 minterms +Envelope[209]: 5170 nodes 1 leaves 4765 minterms +Envelope[210]: 5057 nodes 1 leaves 4644 minterms +Envelope[211]: 4948 nodes 1 leaves 4526 minterms +Envelope[212]: 4856 nodes 1 leaves 4410 minterms +Envelope[213]: 4763 nodes 1 leaves 4296 minterms +Envelope[214]: 4651 nodes 1 leaves 4183 minterms +Envelope[215]: 4568 nodes 1 leaves 4076 minterms +Envelope[216]: 4488 nodes 1 leaves 3972 minterms +Envelope[217]: 4406 nodes 1 leaves 3869 minterms +Envelope[218]: 4322 nodes 1 leaves 3771 minterms +Envelope[219]: 4249 nodes 1 leaves 3677 minterms +Envelope[220]: 4177 nodes 1 leaves 3586 minterms +Envelope[221]: 4102 nodes 1 leaves 3496 minterms +Envelope[222]: 4021 nodes 1 leaves 3408 minterms +Envelope[223]: 3949 nodes 1 leaves 3322 minterms +Envelope[224]: 3871 nodes 1 leaves 3238 minterms +Envelope[225]: 3800 nodes 1 leaves 3158 minterms +Envelope[226]: 3740 nodes 1 leaves 3079 minterms +Envelope[227]: 3674 nodes 1 leaves 3002 minterms +Envelope[228]: 3618 nodes 1 leaves 2926 minterms +Envelope[229]: 3552 nodes 1 leaves 2852 minterms +Envelope[230]: 3485 nodes 1 leaves 2780 minterms +Envelope[231]: 3428 nodes 1 leaves 2711 minterms +Envelope[232]: 3370 nodes 1 leaves 2643 minterms +Envelope[233]: 3304 nodes 1 leaves 2575 minterms +Envelope[234]: 3244 nodes 1 leaves 2510 minterms +Envelope[235]: 3177 nodes 1 leaves 2447 minterms +Envelope[236]: 3112 nodes 1 leaves 2385 minterms +Envelope[237]: 3054 nodes 1 leaves 2324 minterms +Envelope[238]: 2999 nodes 1 leaves 2268 minterms +Envelope[239]: 2947 nodes 1 leaves 2212 minterms +Envelope[240]: 2892 nodes 1 leaves 2157 minterms +Envelope[241]: 2831 nodes 1 leaves 2104 minterms +Envelope[242]: 2769 nodes 1 leaves 2052 minterms +Envelope[243]: 2709 nodes 1 leaves 2001 minterms +Envelope[244]: 2644 nodes 1 leaves 1952 minterms +Envelope[245]: 2569 nodes 1 leaves 1903 minterms +Envelope[246]: 2505 nodes 1 leaves 1855 minterms +Envelope[247]: 2432 nodes 1 leaves 1807 minterms +Envelope[248]: 2361 nodes 1 leaves 1760 minterms +Envelope[249]: 2289 nodes 1 leaves 1715 minterms +Envelope[250]: 2215 nodes 1 leaves 1673 minterms +Envelope[251]: 2169 nodes 1 leaves 1632 minterms +Envelope[252]: 2114 nodes 1 leaves 1591 minterms +Envelope[253]: 2063 nodes 1 leaves 1551 minterms +Envelope[254]: 2011 nodes 1 leaves 1512 minterms +Envelope[255]: 1957 nodes 1 leaves 1473 minterms +Envelope[256]: 1902 nodes 1 leaves 1434 minterms +Envelope[257]: 1852 nodes 1 leaves 1396 minterms +Envelope[258]: 1805 nodes 1 leaves 1359 minterms +Envelope[259]: 1763 nodes 1 leaves 1322 minterms +Envelope[260]: 1711 nodes 1 leaves 1287 minterms +Envelope[261]: 1653 nodes 1 leaves 1255 minterms +Envelope[262]: 1604 nodes 1 leaves 1223 minterms +Envelope[263]: 1557 nodes 1 leaves 1193 minterms +Envelope[264]: 1515 nodes 1 leaves 1164 minterms +Envelope[265]: 1482 nodes 1 leaves 1136 minterms +Envelope[266]: 1447 nodes 1 leaves 1108 minterms +Envelope[267]: 1416 nodes 1 leaves 1081 minterms +Envelope[268]: 1383 nodes 1 leaves 1054 minterms +Envelope[269]: 1353 nodes 1 leaves 1028 minterms +Envelope[270]: 1323 nodes 1 leaves 1003 minterms +Envelope[271]: 1290 nodes 1 leaves 978 minterms +Envelope[272]: 1252 nodes 1 leaves 954 minterms +Envelope[273]: 1215 nodes 1 leaves 931 minterms +Envelope[274]: 1174 nodes 1 leaves 908 minterms +Envelope[275]: 1144 nodes 1 leaves 887 minterms +Envelope[276]: 1120 nodes 1 leaves 867 minterms +Envelope[277]: 1102 nodes 1 leaves 848 minterms +Envelope[278]: 1082 nodes 1 leaves 830 minterms +Envelope[279]: 1061 nodes 1 leaves 812 minterms +Envelope[280]: 1045 nodes 1 leaves 795 minterms +Envelope[281]: 1031 nodes 1 leaves 778 minterms +Envelope[282]: 1015 nodes 1 leaves 763 minterms +Envelope[283]: 1004 nodes 1 leaves 748 minterms +Envelope[284]: 996 nodes 1 leaves 733 minterms +Envelope[285]: 983 nodes 1 leaves 719 minterms +Envelope[286]: 964 nodes 1 leaves 705 minterms +Envelope[287]: 949 nodes 1 leaves 691 minterms +Envelope[288]: 938 nodes 1 leaves 677 minterms +Envelope[289]: 925 nodes 1 leaves 663 minterms +Envelope[290]: 913 nodes 1 leaves 650 minterms +Envelope[291]: 907 nodes 1 leaves 637 minterms +Envelope[292]: 901 nodes 1 leaves 624 minterms +Envelope[293]: 887 nodes 1 leaves 611 minterms +Envelope[294]: 878 nodes 1 leaves 598 minterms +Envelope[295]: 872 nodes 1 leaves 585 minterms +Envelope[296]: 860 nodes 1 leaves 573 minterms +Envelope[297]: 852 nodes 1 leaves 561 minterms +Envelope[298]: 842 nodes 1 leaves 549 minterms +Envelope[299]: 834 nodes 1 leaves 537 minterms +Envelope[300]: 826 nodes 1 leaves 526 minterms +Envelope[301]: 819 nodes 1 leaves 515 minterms +Envelope[302]: 808 nodes 1 leaves 505 minterms +Envelope[303]: 797 nodes 1 leaves 495 minterms +Envelope[304]: 789 nodes 1 leaves 485 minterms +Envelope[305]: 773 nodes 1 leaves 475 minterms +Envelope[306]: 758 nodes 1 leaves 465 minterms +Envelope[307]: 742 nodes 1 leaves 455 minterms +Envelope[308]: 727 nodes 1 leaves 445 minterms +Envelope[309]: 711 nodes 1 leaves 435 minterms +Envelope[310]: 698 nodes 1 leaves 425 minterms +Envelope[311]: 677 nodes 1 leaves 415 minterms +Envelope[312]: 662 nodes 1 leaves 405 minterms +Envelope[313]: 653 nodes 1 leaves 395 minterms +Envelope[314]: 638 nodes 1 leaves 386 minterms +Envelope[315]: 625 nodes 1 leaves 377 minterms +Envelope[316]: 611 nodes 1 leaves 368 minterms +Envelope[317]: 603 nodes 1 leaves 359 minterms +Envelope[318]: 598 nodes 1 leaves 350 minterms +Envelope[319]: 588 nodes 1 leaves 342 minterms +Envelope[320]: 581 nodes 1 leaves 334 minterms +Envelope[321]: 576 nodes 1 leaves 326 minterms +Envelope[322]: 566 nodes 1 leaves 318 minterms +Envelope[323]: 555 nodes 1 leaves 311 minterms +Envelope[324]: 546 nodes 1 leaves 305 minterms +Envelope[325]: 537 nodes 1 leaves 299 minterms +Envelope[326]: 526 nodes 1 leaves 293 minterms +Envelope[327]: 515 nodes 1 leaves 287 minterms +Envelope[328]: 505 nodes 1 leaves 281 minterms +Envelope[329]: 493 nodes 1 leaves 275 minterms +Envelope[330]: 481 nodes 1 leaves 270 minterms +Envelope[331]: 468 nodes 1 leaves 265 minterms +Envelope[332]: 455 nodes 1 leaves 260 minterms +Envelope[333]: 446 nodes 1 leaves 255 minterms +Envelope[334]: 438 nodes 1 leaves 250 minterms +Envelope[335]: 433 nodes 1 leaves 245 minterms +Envelope[336]: 430 nodes 1 leaves 240 minterms +Envelope[337]: 421 nodes 1 leaves 235 minterms +Envelope[338]: 415 nodes 1 leaves 230 minterms +Envelope[339]: 405 nodes 1 leaves 225 minterms +Envelope[340]: 397 nodes 1 leaves 220 minterms +Envelope[341]: 390 nodes 1 leaves 215 minterms +Envelope[342]: 382 nodes 1 leaves 210 minterms +Envelope[343]: 374 nodes 1 leaves 205 minterms +Envelope[344]: 368 nodes 1 leaves 200 minterms +Envelope[345]: 357 nodes 1 leaves 195 minterms +Envelope[346]: 349 nodes 1 leaves 190 minterms +Envelope[347]: 345 nodes 1 leaves 185 minterms +Envelope[348]: 343 nodes 1 leaves 180 minterms +Envelope[349]: 338 nodes 1 leaves 175 minterms +Envelope[350]: 329 nodes 1 leaves 170 minterms +Envelope[351]: 318 nodes 1 leaves 165 minterms +Envelope[352]: 312 nodes 1 leaves 160 minterms +Envelope[353]: 305 nodes 1 leaves 156 minterms +Envelope[354]: 298 nodes 1 leaves 152 minterms +Envelope[355]: 291 nodes 1 leaves 148 minterms +Envelope[356]: 284 nodes 1 leaves 144 minterms +Envelope[357]: 274 nodes 1 leaves 140 minterms +Envelope[358]: 267 nodes 1 leaves 136 minterms +Envelope[359]: 258 nodes 1 leaves 132 minterms +Envelope[360]: 250 nodes 1 leaves 129 minterms +Envelope[361]: 242 nodes 1 leaves 126 minterms +Envelope[362]: 239 nodes 1 leaves 123 minterms +Envelope[363]: 230 nodes 1 leaves 120 minterms +Envelope[364]: 224 nodes 1 leaves 117 minterms +Envelope[365]: 218 nodes 1 leaves 114 minterms +Envelope[366]: 217 nodes 1 leaves 111 minterms +Envelope[367]: 216 nodes 1 leaves 108 minterms +Envelope[368]: 214 nodes 1 leaves 105 minterms +Envelope[369]: 213 nodes 1 leaves 102 minterms +Envelope[370]: 213 nodes 1 leaves 99 minterms +Envelope[371]: 210 nodes 1 leaves 96 minterms +Envelope[372]: 206 nodes 1 leaves 93 minterms +Envelope[373]: 203 nodes 1 leaves 90 minterms +Envelope[374]: 199 nodes 1 leaves 87 minterms +Envelope[375]: 195 nodes 1 leaves 84 minterms +Envelope[376]: 191 nodes 1 leaves 81 minterms +Envelope[377]: 188 nodes 1 leaves 78 minterms +Envelope[378]: 186 nodes 1 leaves 75 minterms +Envelope[379]: 184 nodes 1 leaves 72 minterms +Envelope[380]: 183 nodes 1 leaves 70 minterms +Envelope[381]: 183 nodes 1 leaves 68 minterms +Envelope[382]: 182 nodes 1 leaves 66 minterms +Envelope[383]: 181 nodes 1 leaves 64 minterms +Envelope[384]: 179 nodes 1 leaves 62 minterms +Envelope[385]: 179 nodes 1 leaves 60 minterms +Envelope[386]: 178 nodes 1 leaves 58 minterms +Envelope[387]: 177 nodes 1 leaves 56 minterms +Envelope[388]: 175 nodes 1 leaves 54 minterms +Envelope[389]: 171 nodes 1 leaves 52 minterms +Envelope[390]: 168 nodes 1 leaves 50 minterms +Envelope[391]: 164 nodes 1 leaves 48 minterms +Envelope[392]: 159 nodes 1 leaves 46 minterms +Envelope[393]: 153 nodes 1 leaves 45 minterms +Envelope[394]: 148 nodes 1 leaves 44 minterms +Envelope[395]: 144 nodes 1 leaves 43 minterms +Envelope[396]: 140 nodes 1 leaves 42 minterms +Envelope[397]: 135 nodes 1 leaves 41 minterms +Envelope[398]: 132 nodes 1 leaves 40 minterms +Envelope[399]: 127 nodes 1 leaves 39 minterms +Envelope[400]: 122 nodes 1 leaves 38 minterms +Envelope[401]: 118 nodes 1 leaves 37 minterms +Envelope[402]: 114 nodes 1 leaves 36 minterms +Envelope[403]: 107 nodes 1 leaves 35 minterms +Envelope[404]: 100 nodes 1 leaves 34 minterms +Envelope[405]: 95 nodes 1 leaves 33 minterms +Envelope[406]: 92 nodes 1 leaves 32 minterms +Envelope[407]: 89 nodes 1 leaves 31 minterms +Envelope[408]: 84 nodes 1 leaves 30 minterms +Envelope[409]: 81 nodes 1 leaves 29 minterms +Envelope[410]: 78 nodes 1 leaves 28 minterms +Envelope[411]: 73 nodes 1 leaves 27 minterms +Envelope[412]: 70 nodes 1 leaves 26 minterms +Envelope[413]: 67 nodes 1 leaves 25 minterms +Envelope[414]: 63 nodes 1 leaves 24 minterms +Envelope[415]: 59 nodes 1 leaves 23 minterms +Envelope[416]: 56 nodes 1 leaves 22 minterms +Envelope[417]: 55 nodes 1 leaves 21 minterms +Envelope[418]: 54 nodes 1 leaves 20 minterms +Envelope[419]: 53 nodes 1 leaves 19 minterms +Envelope[420]: 52 nodes 1 leaves 18 minterms +Envelope[421]: 52 nodes 1 leaves 17 minterms +Envelope[422]: 50 nodes 1 leaves 16 minterms +Envelope[423]: 47 nodes 1 leaves 15 minterms +Envelope[424]: 44 nodes 1 leaves 14 minterms +Envelope[425]: 40 nodes 1 leaves 13 minterms +Envelope[426]: 36 nodes 1 leaves 12 minterms +Envelope[427]: 33 nodes 1 leaves 11 minterms +Envelope[428]: 31 nodes 1 leaves 10 minterms +Envelope[429]: 30 nodes 1 leaves 9 minterms +Envelope[430]: 29 nodes 1 leaves 8 minterms +Envelope[431]: 29 nodes 1 leaves 7 minterms +Envelope[432]: 29 nodes 1 leaves 6 minterms +Envelope[433]: 28 nodes 1 leaves 5 minterms +Envelope[434]: 27 nodes 1 leaves 4 minterms +depth = 434 +Envelope: 27 nodes 1 leaves 4 minterms +**** 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: 10 +Arc violation threshold: 10 +GA population size: 0 +Number of crossovers for GA: 0 +Next reordering threshold: 4004 +**** CUDD non-modifiable parameters **** +Memory in use: 240456716 +Peak number of nodes: 9643592 +Peak number of live nodes: 3171948 +Number of BDD variables: 50 +Number of ZDD variables: 0 +Number of cache entries: 4194304 +Number of cache look-ups: 53170021 +Number of cache hits: 30653976 +Number of cache insertions: 22515985 +Number of cache collisions: 15665382 +Number of cache deletions: 3483568 +Cache used slots = 97.84% (expected 98.41%) +Soft limit for cache size: 7645866 +Number of buckets in unique table: 3677184 +Used buckets in unique table: 71.16% (expected 71.15%) +Number of BDD and ADD nodes: 5843265 +Number of ZDD nodes: 0 +Number of dead BDD and ADD nodes: 4325974 +Number of dead ZDD nodes: 0 +Total number of nodes allocated: 15264438 +Total number of nodes reclaimed: 7806126 +Garbage collections so far: 2 +Time for garbage collection: 2.38 sec +Reorderings so far: 0 +Time for reordering: 0.00 sec +Final size: 869 +total time = 66.53 sec +Runtime Statistics +------------------ +Machine name: jobim.colorado.edu +User time 66.5 seconds +System time 0.6 seconds + +Average resident text size = 0K +Average resident data+stack size = 0K +Maximum resident size = 0K + +Virtual text size = 131815K +Virtual data size = 297K + data size initialized = 25K + data size uninitialized = 137K + data size sbrk = 135K +Virtual memory limit = 358400K (4194304K) + +Major page faults = 5 +Minor page faults = 80223 +Swaps = 0 +Input blocks = 0 +Output blocks = 0 +Context switch (voluntary) = 6 +Context switch (involuntary) = 1991 diff --git a/distr/nanotrav/s27.blif b/distr/nanotrav/s27.blif new file mode 100644 index 0000000..42861a8 --- /dev/null +++ b/distr/nanotrav/s27.blif @@ -0,0 +1,30 @@ +.model s27.bench +.inputs G0 G1 G2 G3 +.outputs G17 +.latch G10 G5 0 +.latch G11 G6 0 +.latch G13 G7 0 +.names G11 G17 +0 1 +.names G14 G11 G10 +00 1 +.names G5 G9 G11 +00 1 +.names G2 G12 G13 +00 1 +.names G0 G14 +0 1 +.names G14 G6 G8 +11 1 +.names G1 G7 G12 +00 1 +.names G12 G8 G15 +1- 1 +-1 1 +.names G3 G8 G16 +1- 1 +-1 1 +.names G16 G15 G9 +0- 1 +-0 1 +.end diff --git a/distr/nanotrav/s27.out b/distr/nanotrav/s27.out new file mode 100644 index 0000000..b9746f6 --- /dev/null +++ b/distr/nanotrav/s27.out @@ -0,0 +1,95 @@ +# Nanotrav Version #0.12, Release date 2003/12/31 +# ./nanotrav -p 1 -trav s27.blif +# CUDD Version 2.4.2 +Order before final reordering +G0 G1 G2 G3 G5 G6 G7 +Number of inputs = 7 +Building transition relation. Time = 0.00 sec +@@@ +Transition relation: 1 parts 3 latches 9 nodes +Traversing. Time = 0.00 sec +S0: 4 nodes 1 leaves 1 minterms +From[1]: 5 nodes 1 leaves 4 minterms +Reached[1]: 5 nodes 1 leaves 5 minterms +5 +5e+0 +From[2]: 4 nodes 1 leaves 1 minterms +Reached[2]: 3 nodes 1 leaves 6 minterms +6 +6e+0 +depth = 2 +R: 3 nodes 1 leaves 6 minterms +**** 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: 10 +Arc violation threshold: 10 +GA population size: 0 +Number of crossovers for GA: 0 +Next reordering threshold: 4004 +**** CUDD non-modifiable parameters **** +Memory in use: 4737772 +Peak number of nodes: 1022 +Peak number of live nodes: 95 +Number of BDD variables: 10 +Number of ZDD variables: 0 +Number of cache entries: 32768 +Number of cache look-ups: 180 +Number of cache hits: 26 +Number of cache insertions: 151 +Number of cache collisions: 1 +Number of cache deletions: 0 +Cache used slots = 0.46% (expected 0.46%) +Soft limit for cache size: 11264 +Number of buckets in unique table: 2816 +Used buckets in unique table: 4.97% (expected 5.15%) +Number of BDD and ADD nodes: 150 +Number of ZDD nodes: 0 +Number of dead BDD and ADD nodes: 75 +Number of dead ZDD nodes: 0 +Total number of nodes allocated: 150 +Total number of nodes reclaimed: 12 +Garbage collections so far: 0 +Time for garbage collection: 0.00 sec +Reorderings so far: 0 +Time for reordering: 0.00 sec +Final size: 16 +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 = 131815K +Virtual data size = 297K + data size initialized = 25K + data size uninitialized = 137K + data size sbrk = 135K +Virtual memory limit = 358400K (4194304K) + +Major page faults = 0 +Minor page faults = 1424 +Swaps = 0 +Input blocks = 0 +Output blocks = 0 +Context switch (voluntary) = 1 +Context switch (involuntary) = 0 diff --git a/distr/nanotrav/tst.sh b/distr/nanotrav/tst.sh new file mode 100755 index 0000000..c51e67e --- /dev/null +++ b/distr/nanotrav/tst.sh @@ -0,0 +1,9 @@ +#! /bin/sh +# +# $Id: tst.sh,v 1.2 1998/05/03 08:41:38 fabio Exp fabio $ +# +./nanotrav -p 1 -cover C17.blif > C17.tst +./nanotrav -p 1 -ordering dfs -autodyn -automethod sifting -reordering sifting -drop C880.blif > C880.tst +./nanotrav -p 1 -trav s27.blif > s27.tst +./nanotrav -p 1 -autodyn -reordering sifting -trav mult32a.blif > mult32a.tst +./nanotrav -p 1 -envelope rcn25.blif > rcn25.tst diff --git a/distr/nanotrav/ucbqsort.c b/distr/nanotrav/ucbqsort.c new file mode 100644 index 0000000..b1a430e --- /dev/null +++ b/distr/nanotrav/ucbqsort.c @@ -0,0 +1,228 @@ +#if defined(__GNUC__) && (__GNUC__ >2 || __GNUC_MINOR__ >=7) +#define UNUSED __attribute__ ((unused)) +#else +#define UNUSED +#endif + +#ifndef lint +static char rcsid[] UNUSED = "$Id: ucbqsort.c,v 1.4 2004/01/01 07:06:06 fabio Exp fabio $"; +#endif + +/* @(#)qsort.c 4.2 (Berkeley) 3/9/83 */ + +/* + * qsort.c: + * Our own version of the system qsort routine which is faster by an average + * of 25%, with lows and highs of 10% and 50%. + * The THRESHold below is the insertion sort threshold, and has been adjusted + * for records of size 48 bytes. + * The MTHREShold is where we stop finding a better median. + */ + +#ifdef __cplusplus +extern "C" { +#endif + +typedef int (*QSFP)(const void *, const void *); +extern void qsort ( char *base, int n, int size, QSFP compar); + +#define THRESH 4 /* threshold for insertion */ +#define MTHRESH 6 /* threshold for median */ + +static QSFP qcmp; /* the comparison routine */ +static int qsz; /* size of each record */ +static int thresh; /* THRESHold in chars */ +static int mthresh; /* MTHRESHold in chars */ + +static void qst (char *base, char *max); + +#ifdef __cplusplus +} +#endif + +/* + * qsort: + * First, set up some global parameters for qst to share. Then, quicksort + * with qst(), and then a cleanup insertion sort ourselves. Sound simple? + * It's not... + */ +#undef min +#undef max +void +qsort( + char *base, + int n, + int size, + QSFP compar) +{ + register char c, *i, *j, *lo, *hi; + char *min, *max; + + if (n <= 1) + return; + qsz = size; + qcmp = compar; + thresh = qsz * THRESH; + mthresh = qsz * MTHRESH; + max = base + n * qsz; + if (n >= THRESH) { + qst(base, max); + hi = base + thresh; + } else { + hi = max; + } + /* + * First put smallest element, which must be in the first THRESH, in + * the first position as a sentinel. This is done just by searching + * the first THRESH elements (or the first n if n < THRESH), finding + * the min, and swapping it into the first position. + */ + for (j = lo = base; (lo += qsz) < hi; ) + if ((*qcmp)(j, lo) > 0) + j = lo; + if (j != base) { + /* swap j into place */ + for (i = base, hi = base + qsz; i < hi; ) { + c = *j; + *j++ = *i; + *i++ = c; + } + } + /* + * With our sentinel in place, we now run the following hyper-fast + * insertion sort. For each remaining element, min, from [1] to [n-1], + * set hi to the index of the element AFTER which this one goes. + * Then, do the standard insertion sort shift on a character at a time + * basis for each element in the frob. + */ + for (min = base; (hi = min += qsz) < max; ) { + while ((*qcmp)(hi -= qsz, min) > 0) + /* void */; + if ((hi += qsz) != min) { + for (lo = min + qsz; --lo >= min; ) { + c = *lo; + for (i = j = lo; (j -= qsz) >= hi; i = j) + *i = *j; + *i = c; + } + } + } +} + +/* + * qst: + * Do a quicksort + * First, find the median element, and put that one in the first place as the + * discriminator. (This "median" is just the median of the first, last and + * middle elements). (Using this median instead of the first element is a big + * win). Then, the usual partitioning/swapping, followed by moving the + * discriminator into the right place. Then, figure out the sizes of the two + * partions, do the smaller one recursively and the larger one via a repeat of + * this code. Stopping when there are less than THRESH elements in a partition + * and cleaning up with an insertion sort (in our caller) is a huge win. + * All data swaps are done in-line, which is space-losing but time-saving. + * (And there are only three places where this is done). + */ + +static void +qst(char *base, char *max) +{ + register char c, *i, *j, *jj; + register int ii; + char *mid, *tmp; + int lo, hi; + + /* + * At the top here, lo is the number of characters of elements in the + * current partition. (Which should be max - base). + * Find the median of the first, last, and middle element and make + * that the middle element. Set j to largest of first and middle. + * If max is larger than that guy, then it's that guy, else compare + * max with loser of first and take larger. Things are set up to + * prefer the middle, then the first in case of ties. + */ + lo = max - base; /* number of elements as chars */ + do { + mid = i = base + qsz * ((lo / qsz) >> 1); + if (lo >= mthresh) { + j = ((*qcmp)((jj = base), i) > 0 ? jj : i); + if ((*qcmp)(j, (tmp = max - qsz)) > 0) { + /* switch to first loser */ + j = (j == jj ? i : jj); + if ((*qcmp)(j, tmp) < 0) + j = tmp; + } + if (j != i) { + ii = qsz; + do { + c = *i; + *i++ = *j; + *j++ = c; + } while (--ii); + } + } + /* + * Semi-standard quicksort partitioning/swapping + */ + for (i = base, j = max - qsz; ; ) { + while (i < mid && (*qcmp)(i, mid) <= 0) + i += qsz; + while (j > mid) { + if ((*qcmp)(mid, j) <= 0) { + j -= qsz; + continue; + } + tmp = i + qsz; /* value of i after swap */ + if (i == mid) { + /* j <-> mid, new mid is j */ + mid = jj = j; + } else { + /* i <-> j */ + jj = j; + j -= qsz; + } + goto swap; + } + if (i == mid) { + break; + } else { + /* i <-> mid, new mid is i */ + jj = mid; + tmp = mid = i; /* value of i after swap */ + j -= qsz; + } + swap: + ii = qsz; + do { + c = *i; + *i++ = *jj; + *jj++ = c; + } while (--ii); + i = tmp; + } + /* + * Look at sizes of the two partitions, do the smaller + * one first by recursion, then do the larger one by + * making sure lo is its size, base and max are update + * correctly, and branching back. But only repeat + * (recursively or by branching) if the partition is + * of at least size THRESH. + */ + i = (j = mid) + qsz; + if ((lo = j - base) <= (hi = max - i)) { + if (lo >= thresh) + qst(base, j); + base = i; + lo = hi; + } else { + if (hi >= thresh) + qst(i, max); + max = j; + } + } while (lo >= thresh); +} + +/*---------------------------------------------------------------------------*/ +/* Static function prototypes */ +/*---------------------------------------------------------------------------*/ + diff --git a/distr/obj/Makefile b/distr/obj/Makefile new file mode 100644 index 0000000..e11f37b --- /dev/null +++ b/distr/obj/Makefile @@ -0,0 +1,110 @@ +# $Id: Makefile,v 1.3 2001/03/19 07:34:37 fabio Exp fabio $ +# +# obj: CUDD's C++ interface +#--------------------------------------------------------------------------- +.SUFFIXES: .o .cc .u + +CPP = g++ +RANLIB = ranlib +# Define EXE as .exe for MS-DOS and derivatives. +PURE = +EXE = +#EXE = .exe + +MFLAG = +ICFLAGS = -g +XCFLAGS = +CPPFLAGS = +CFLAGS = $(ICFLAGS) $(MFLAG) $(XCFLAGS) $(CPPFLAGS) +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 = ./libobj.a $(WHERE)/cudd/libcudd.a $(WHERE)/mtr/libmtr.a \ + $(WHERE)/st/libst.a $(WHERE)/util/libutil.a $(WHERE)/epd/libepd.a + +MNEMLIB = + +BLIBS = -kL. -klobj -kL$(WHERE)/cudd -klcudd -kL$(WHERE)/mtr -klmtr \ + -kL$(WHERE)/st -klst -kL$(WHERE)/util -klutil -kL$(WHERE)/epd -klepd + +LINTLIBS = ./llib-lobj.ln $(WHERE)/cudd/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 = obj +PSRC = cuddObj.cc +PHDR = cuddObj.hh $(INCLUDE)/cudd.h +POBJ = $(PSRC:.cc=.o) +PUBJ = $(PSRC:.cc=.u) +TARGET = test$(P)$(EXE) +TARGETu = test$(P)-u + +# files for the test program +SRC = test$(P).cc +OBJ = $(SRC:.cc=.o) +UBJ = $(SRC:.cc=.u) + +#------------------------------------------------------ + +lib$(P).a: $(POBJ) + ar rv $@ $? + $(RANLIB) $@ + +.cc.o: $(PHDR) + $(CPP) -c $< -I$(INCLUDE) $(CFLAGS) $(DDDEBUG) + +optimize_dec: lib$(P).b + +lib$(P).b: $(PUBJ) + ar rv $@ $? + $(RANLIB) $@ + +.cc.u: $(PHDR) + cxx -j $< -I$(INCLUDE) $(CFLAGS) + +# if the header files change, recompile +$(POBJ): $(PHDR) +$(PUBJ): $(PHDR) +$(OBJ): $(PHDR) +$(UBJ): $(PHDR) + +$(TARGET): $(SRC) $(OBJ) $(HDR) $(LIBS) $(MNEMLIB) + $(PURE) $(CPP) $(CFLAGS) $(LDFLAGS) -o $@ $(OBJ) $(LIBS) $(MNEMLIB) -lm + +# optimize (DECstations and Alphas only: uses u-code) +$(TARGETu): $(SRC) $(UBJ) $(HDR) $(LIBS:.a=.b) + cxx -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/distr/obj/cuddObj.cc b/distr/obj/cuddObj.cc new file mode 100644 index 0000000..41df58a --- /dev/null +++ b/distr/obj/cuddObj.cc @@ -0,0 +1,5552 @@ +/**CFile*********************************************************************** + + FileName [cuddObj.cc] + + PackageName [cuddObj] + + Synopsis [Functions for the C++ object-oriented encapsulation of CUDD.] + + 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.] + +******************************************************************************/ + +#include "cuddObj.hh" + +// --------------------------------------------------------------------------- +// Variable declarations +// --------------------------------------------------------------------------- + +#ifndef lint +static char rcsid[] UTIL_UNUSED = "$Id: cuddObj.cc,v 1.13 2009/02/21 19:41:38 fabio Exp fabio $"; +#endif + +// --------------------------------------------------------------------------- +// Members of class DD +// --------------------------------------------------------------------------- + + +DD::DD(Cudd *ddManager, DdNode *ddNode) { + ddMgr = ddManager; + node = ddNode; + if (node != 0) Cudd_Ref(node); + if (ddMgr->isVerbose()) { + cout << "Standard DD constructor for node " << hex << long(node) << + " ref = " << Cudd_Regular(node)->ref << "\n"; + } + +} // DD::DD + + +DD::DD() { + ddMgr = 0; + node = 0; + +} // DD::DD + + +DD::DD(const DD &from) { + ddMgr = from.ddMgr; + node = from.node; + if (node != 0) { + Cudd_Ref(node); + if (ddMgr->isVerbose()) { + cout << "Copy DD constructor for node " << hex << long(node) << + " ref = " << Cudd_Regular(node)->ref << "\n"; + } + } + +} // DD::DD + + +DD::~DD() {} + + +inline DdManager * +DD::checkSameManager( + const DD &other) const +{ + DdManager *mgr = ddMgr->p->manager; + if (mgr != other.ddMgr->p->manager) { + ddMgr->p->errorHandler("Operands come from different manager."); + } + return mgr; + +} // DD::checkSameManager + + +inline void +DD::checkReturnValue( + const DdNode *result) const +{ + if (result == 0) { + DdManager *mgr = ddMgr->p->manager; + Cudd_ErrorType errType = Cudd_ReadErrorCode(mgr); + switch (errType) { + case CUDD_MEMORY_OUT: + ddMgr->p->errorHandler("Out of memory."); + break; + case CUDD_TOO_MANY_NODES: + break; + case CUDD_MAX_MEM_EXCEEDED: + ddMgr->p->errorHandler("Maximum memory exceeded."); + break; + case CUDD_INVALID_ARG: + ddMgr->p->errorHandler("Invalid argument."); + break; + case CUDD_INTERNAL_ERROR: + ddMgr->p->errorHandler("Internal error."); + break; + case CUDD_NO_ERROR: + default: + ddMgr->p->errorHandler("Unexpected error."); + break; + } + } + +} // DD::checkReturnValue + + +inline void +DD::checkReturnValue( + const int result, + const int expected) const +{ + if (result != expected) { + DdManager *mgr = ddMgr->p->manager; + Cudd_ErrorType errType = Cudd_ReadErrorCode(mgr); + switch (errType) { + case CUDD_MEMORY_OUT: + ddMgr->p->errorHandler("Out of memory."); + break; + case CUDD_TOO_MANY_NODES: + break; + case CUDD_MAX_MEM_EXCEEDED: + ddMgr->p->errorHandler("Maximum memory exceeded."); + break; + case CUDD_INVALID_ARG: + ddMgr->p->errorHandler("Invalid argument."); + break; + case CUDD_INTERNAL_ERROR: + ddMgr->p->errorHandler("Internal error."); + break; + case CUDD_NO_ERROR: + default: + ddMgr->p->errorHandler("Unexpected error."); + break; + } + } + +} // DD::checkReturnValue + + +Cudd * +DD::manager() const +{ + return ddMgr; + +} // DD::manager + + +inline DdNode * +DD::getNode() const +{ + return node; + +} // DD::getNode + + +int +DD::nodeCount() const +{ + return Cudd_DagSize(node); + +} // DD::nodeCount + + +// --------------------------------------------------------------------------- +// Members of class ABDD +// --------------------------------------------------------------------------- + + +ABDD::ABDD(Cudd *bddManager, DdNode *bddNode) : DD(bddManager,bddNode) {} +ABDD::ABDD() : DD() {} +ABDD::ABDD(const ABDD &from) : DD(from) {} + + +ABDD::~ABDD() { + if (node != 0) { + Cudd_RecursiveDeref(ddMgr->p->manager,node); + if (ddMgr->isVerbose()) { + cout << "ADD/BDD destructor called for node " << hex << + long(node) << " ref = " << Cudd_Regular(node)->ref << "\n"; + } + } + +} // ABDD::~ABDD + + +int +ABDD::operator==( + const ABDD& other) const +{ + this->checkSameManager(other); + return node == other.node; + +} // ABDD::operator== + + +int +ABDD::operator!=( + const ABDD& other) const +{ + this->checkSameManager(other); + return node != other.node; + +} // ABDD::operator!= + + +void +ABDD::print( + int nvars, + int verbosity) const +{ + cout.flush(); + int retval = Cudd_PrintDebug(ddMgr->p->manager,node,nvars,verbosity); + if (retval == 0) ddMgr->p->errorHandler("print failed"); + +} // ABDD::print + + +// --------------------------------------------------------------------------- +// Members of class BDD +// --------------------------------------------------------------------------- + +BDD::BDD(Cudd *bddManager, DdNode *bddNode) : ABDD(bddManager,bddNode) {} +BDD::BDD() : ABDD() {} +BDD::BDD(const BDD &from) : ABDD(from) {} + + +int +BDD::operator==( + const BDD& other) const +{ + this->checkSameManager(other); + return node == other.node; + +} // BDD::operator== + + +int +BDD::operator!=( + const BDD& other) const +{ + this->checkSameManager(other); + return node != other.node; + +} // BDD::operator!= + + +BDD +BDD::operator=( + const BDD& right) +{ + if (this == &right) return *this; + if (right.node != 0) Cudd_Ref(right.node); + if (node != 0) { + Cudd_RecursiveDeref(ddMgr->p->manager,node); + if (ddMgr->isVerbose()) { + cout << "BDD dereferencing for node " << hex << long(node) << + " ref = " << Cudd_Regular(node)->ref << "\n"; + } + } + node = right.node; + ddMgr = right.ddMgr; + if (node != 0 && ddMgr->isVerbose()) { + cout << "BDD assignment for node " << hex << long(node) << + " ref = " << Cudd_Regular(node)->ref << "\n"; + } + return *this; + +} // BDD::operator= + + +int +BDD::operator<=( + const BDD& other) const +{ + DdManager *mgr = this->checkSameManager(other); + return Cudd_bddLeq(mgr,node,other.node); + +} // BDD::operator<= + + +int +BDD::operator>=( + const BDD& other) const +{ + DdManager *mgr = this->checkSameManager(other); + return Cudd_bddLeq(mgr,other.node,node); + +} // BDD::operator>= + + +int +BDD::operator<( + const BDD& other) const +{ + DdManager *mgr = this->checkSameManager(other); + return node != other.node && Cudd_bddLeq(mgr,node,other.node); + +} // BDD::operator< + + +int +BDD::operator>( + const BDD& other) const +{ + DdManager *mgr = this->checkSameManager(other); + return node != other.node && Cudd_bddLeq(mgr,other.node,node); + +} // BDD::operator> + + +BDD +BDD::operator!() const +{ + return BDD(ddMgr, Cudd_Not(node)); + +} // BDD::operator! + + +BDD +BDD::operator~() const +{ + return BDD(ddMgr, Cudd_Not(node)); + +} // BDD::operator~ + + +BDD +BDD::operator*( + const BDD& other) const +{ + DdManager *mgr = this->checkSameManager(other); + DdNode *result = Cudd_bddAnd(mgr,node,other.node); + this->checkReturnValue(result); + return BDD(ddMgr, result); + +} // BDD::operator* + + +BDD +BDD::operator*=( + const BDD& other) +{ + DdManager *mgr = this->checkSameManager(other); + DdNode *result = Cudd_bddAnd(mgr,node,other.node); + this->checkReturnValue(result); + Cudd_Ref(result); + Cudd_RecursiveDeref(mgr,node); + node = result; + return *this; + +} // BDD::operator*= + + +BDD +BDD::operator&( + const BDD& other) const +{ + DdManager *mgr = this->checkSameManager(other); + DdNode *result = Cudd_bddAnd(mgr,node,other.node); + this->checkReturnValue(result); + return BDD(ddMgr, result); + +} // BDD::operator& + + +BDD +BDD::operator&=( + const BDD& other) +{ + DdManager *mgr = this->checkSameManager(other); + DdNode *result = Cudd_bddAnd(mgr,node,other.node); + this->checkReturnValue(result); + Cudd_Ref(result); + Cudd_RecursiveDeref(mgr,node); + node = result; + return *this; + +} // BDD::operator&= + + +BDD +BDD::operator+( + const BDD& other) const +{ + DdManager *mgr = this->checkSameManager(other); + DdNode *result = Cudd_bddOr(mgr,node,other.node); + this->checkReturnValue(result); + return BDD(ddMgr, result); + +} // BDD::operator+ + + +BDD +BDD::operator+=( + const BDD& other) +{ + DdManager *mgr = this->checkSameManager(other); + DdNode *result = Cudd_bddOr(mgr,node,other.node); + this->checkReturnValue(result); + Cudd_Ref(result); + Cudd_RecursiveDeref(mgr,node); + node = result; + return *this; + +} // BDD::operator+= + + +BDD +BDD::operator|( + const BDD& other) const +{ + DdManager *mgr = this->checkSameManager(other); + DdNode *result = Cudd_bddOr(mgr,node,other.node); + this->checkReturnValue(result); + return BDD(ddMgr, result); + +} // BDD::operator| + + +BDD +BDD::operator|=( + const BDD& other) +{ + DdManager *mgr = this->checkSameManager(other); + DdNode *result = Cudd_bddOr(mgr,node,other.node); + this->checkReturnValue(result); + Cudd_Ref(result); + Cudd_RecursiveDeref(mgr,node); + node = result; + return *this; + +} // BDD::operator|= + + +BDD +BDD::operator^( + const BDD& other) const +{ + DdManager *mgr = this->checkSameManager(other); + DdNode *result = Cudd_bddXor(mgr,node,other.node); + this->checkReturnValue(result); + return BDD(ddMgr, result); + +} // BDD::operator^ + + +BDD +BDD::operator^=( + const BDD& other) +{ + DdManager *mgr = this->checkSameManager(other); + DdNode *result = Cudd_bddXor(mgr,node,other.node); + this->checkReturnValue(result); + Cudd_Ref(result); + Cudd_RecursiveDeref(mgr,node); + node = result; + return *this; + +} // BDD::operator^= + + +BDD +BDD::operator-( + const BDD& other) const +{ + DdManager *mgr = this->checkSameManager(other); + DdNode *result = Cudd_bddAnd(mgr,node,Cudd_Not(other.node)); + this->checkReturnValue(result); + return BDD(ddMgr, result); + +} // BDD::operator- + + +BDD +BDD::operator-=( + const BDD& other) +{ + DdManager *mgr = this->checkSameManager(other); + DdNode *result = Cudd_bddAnd(mgr,node,Cudd_Not(other.node)); + this->checkReturnValue(result); + Cudd_Ref(result); + Cudd_RecursiveDeref(mgr,node); + node = result; + return *this; + +} // BDD::operator-= + + +// --------------------------------------------------------------------------- +// Members of class ADD +// --------------------------------------------------------------------------- + + +ADD::ADD(Cudd *bddManager, DdNode *bddNode) : ABDD(bddManager,bddNode) {} +ADD::ADD() : ABDD() {} +ADD::ADD(const ADD &from) : ABDD(from) {} + + +int +ADD::operator==( + const ADD& other) const +{ + this->checkSameManager(other); + return node == other.node; + +} // ADD::operator== + + +int +ADD::operator!=( + const ADD& other) const +{ + this->checkSameManager(other); + return node != other.node; + +} // ADD::operator!= + + +ADD +ADD::operator=( + const ADD& right) +{ + if (this == &right) return *this; + if (right.node != 0) Cudd_Ref(right.node); + if (node != 0) { + Cudd_RecursiveDeref(ddMgr->p->manager,node); + } + node = right.node; + ddMgr = right.ddMgr; + return *this; + +} // ADD::operator= + + +int +ADD::operator<=( + const ADD& other) const +{ + DdManager *mgr = this->checkSameManager(other); + return Cudd_addLeq(mgr,node,other.node); + +} // ADD::operator<= + + +int +ADD::operator>=( + const ADD& other) const +{ + DdManager *mgr = this->checkSameManager(other); + return Cudd_addLeq(mgr,other.node,node); + +} // ADD::operator>= + + +int +ADD::operator<( + const ADD& other) const +{ + DdManager *mgr = this->checkSameManager(other); + return node != other.node && Cudd_addLeq(mgr,node,other.node); + +} // ADD::operator< + + +int +ADD::operator>( + const ADD& other) const +{ + DdManager *mgr = this->checkSameManager(other); + return node != other.node && Cudd_addLeq(mgr,other.node,node); + +} // ADD::operator> + + +ADD +ADD::operator-() const +{ + return ADD(ddMgr, Cudd_addNegate(ddMgr->p->manager,node)); + +} // ADD::operator- + + +ADD +ADD::operator*( + const ADD& other) const +{ + DdManager *mgr = this->checkSameManager(other); + DdNode *result = Cudd_addApply(mgr,Cudd_addTimes,node,other.node); + this->checkReturnValue(result); + return ADD(ddMgr, result); + +} // ADD::operator* + + +ADD +ADD::operator*=( + const ADD& other) +{ + DdManager *mgr = this->checkSameManager(other); + DdNode *result = Cudd_addApply(mgr,Cudd_addTimes,node,other.node); + this->checkReturnValue(result); + Cudd_Ref(result); + Cudd_RecursiveDeref(mgr,node); + node = result; + return *this; + +} // ADD::operator*= + + +ADD +ADD::operator+( + const ADD& other) const +{ + DdManager *mgr = this->checkSameManager(other); + DdNode *result = Cudd_addApply(mgr,Cudd_addPlus,node,other.node); + this->checkReturnValue(result); + return ADD(ddMgr, result); + +} // ADD::operator+ + + +ADD +ADD::operator+=( + const ADD& other) +{ + DdManager *mgr = this->checkSameManager(other); + DdNode *result = Cudd_addApply(mgr,Cudd_addPlus,node,other.node); + this->checkReturnValue(result); + Cudd_Ref(result); + Cudd_RecursiveDeref(mgr,node); + node = result; + return *this; + +} // ADD::operator+= + + +ADD +ADD::operator-( + const ADD& other) const +{ + DdManager *mgr = this->checkSameManager(other); + DdNode *result = Cudd_addApply(mgr,Cudd_addMinus,node,other.node); + this->checkReturnValue(result); + return ADD(ddMgr, result); + +} // ADD::operator- + + +ADD +ADD::operator-=( + const ADD& other) +{ + DdManager *mgr = this->checkSameManager(other); + DdNode *result = Cudd_addApply(mgr,Cudd_addMinus,node,other.node); + this->checkReturnValue(result); + Cudd_Ref(result); + Cudd_RecursiveDeref(mgr,node); + node = result; + return *this; + +} // ADD::operator-= + + +ADD +ADD::operator~() const +{ + return ADD(ddMgr, Cudd_addCmpl(ddMgr->p->manager,node)); + +} // ADD::operator~ + + +ADD +ADD::operator&( + const ADD& other) const +{ + DdManager *mgr = this->checkSameManager(other); + DdNode *result = Cudd_addApply(mgr,Cudd_addTimes,node,other.node); + this->checkReturnValue(result); + return ADD(ddMgr, result); + +} // ADD::operator& + + +ADD +ADD::operator&=( + const ADD& other) +{ + DdManager *mgr = this->checkSameManager(other); + DdNode *result = Cudd_addApply(mgr,Cudd_addTimes,node,other.node); + this->checkReturnValue(result); + Cudd_Ref(result); + Cudd_RecursiveDeref(mgr,node); + node = result; + return *this; + +} // ADD::operator&= + + +ADD +ADD::operator|( + const ADD& other) const +{ + DdManager *mgr = this->checkSameManager(other); + DdNode *result = Cudd_addApply(mgr,Cudd_addOr,node,other.node); + this->checkReturnValue(result); + return ADD(ddMgr, result); + +} // ADD::operator| + + +ADD +ADD::operator|=( + const ADD& other) +{ + DdManager *mgr = this->checkSameManager(other); + DdNode *result = Cudd_addApply(mgr,Cudd_addOr,node,other.node); + this->checkReturnValue(result); + Cudd_Ref(result); + Cudd_RecursiveDeref(mgr,node); + node = result; + return *this; + +} // ADD::operator|= + + +// --------------------------------------------------------------------------- +// Members of class ZDD +// --------------------------------------------------------------------------- + + +ZDD::ZDD(Cudd *bddManager, DdNode *bddNode) : DD(bddManager,bddNode) {} +ZDD::ZDD() : DD() {} +ZDD::ZDD(const ZDD &from) : DD(from) {} + + +ZDD::~ZDD() { + if (node != 0) { + Cudd_RecursiveDerefZdd(ddMgr->p->manager,node); + if (ddMgr->isVerbose()) { + cout << "ZDD destructor called for node " << hex << long(node) << + " ref = " << Cudd_Regular(node)->ref << "\n"; + } + } + +} // ZDD::~ZDD + + +ZDD +ZDD::operator=( + const ZDD& right) +{ + if (this == &right) return *this; + if (right.node != 0) Cudd_Ref(right.node); + if (node != 0) { + Cudd_RecursiveDerefZdd(ddMgr->p->manager,node); + if (ddMgr->isVerbose()) { + cout << "ZDD dereferencing for node " << hex << long(node) << + " ref = " << node->ref << "\n"; + } + } + node = right.node; + ddMgr = right.ddMgr; + if (node != 0 && ddMgr->isVerbose()) { + cout << "ZDD assignment for node " << hex << long(node) << + " ref = " << node->ref << "\n"; + } + return *this; + +} // ZDD::operator= + + +int +ZDD::operator==( + const ZDD& other) const +{ + this->checkSameManager(other); + return node == other.node; + +} // ZDD::operator== + + +int +ZDD::operator!=( + const ZDD& other) const +{ + this->checkSameManager(other); + return node != other.node; + +} // ZDD::operator!= + + +int +ZDD::operator<=( + const ZDD& other) const +{ + DdManager *mgr = this->checkSameManager(other); + return Cudd_zddDiffConst(mgr,node,other.node) == Cudd_ReadZero(mgr); + +} // ZDD::operator<= + + +int +ZDD::operator>=( + const ZDD& other) const +{ + DdManager *mgr = this->checkSameManager(other); + return Cudd_zddDiffConst(mgr,other.node,node) == Cudd_ReadZero(mgr); + +} // ZDD::operator>= + + +int +ZDD::operator<( + const ZDD& other) const +{ + DdManager *mgr = this->checkSameManager(other); + return node != other.node && + Cudd_zddDiffConst(mgr,node,other.node) == Cudd_ReadZero(mgr); + +} // ZDD::operator< + + +int +ZDD::operator>( + const ZDD& other) const +{ + DdManager *mgr = this->checkSameManager(other); + return node != other.node && + Cudd_zddDiffConst(mgr,other.node,node) == Cudd_ReadZero(mgr); + +} // ZDD::operator> + + +void +ZDD::print( + int nvars, + int verbosity) const +{ + cout.flush(); + int retval = Cudd_zddPrintDebug(ddMgr->p->manager,node,nvars,verbosity); + if (retval == 0) ddMgr->p->errorHandler("print failed"); + +} // ZDD::print + + +ZDD +ZDD::operator*( + const ZDD& other) const +{ + DdManager *mgr = this->checkSameManager(other); + DdNode *result = Cudd_zddIntersect(mgr,node,other.node); + this->checkReturnValue(result); + return ZDD(ddMgr, result); + +} // ZDD::operator* + + +ZDD +ZDD::operator*=( + const ZDD& other) +{ + DdManager *mgr = this->checkSameManager(other); + DdNode *result = Cudd_zddIntersect(mgr,node,other.node); + this->checkReturnValue(result); + Cudd_Ref(result); + Cudd_RecursiveDerefZdd(mgr,node); + node = result; + return *this; + +} // ZDD::operator*= + + +ZDD +ZDD::operator&( + const ZDD& other) const +{ + DdManager *mgr = this->checkSameManager(other); + DdNode *result = Cudd_zddIntersect(mgr,node,other.node); + this->checkReturnValue(result); + return ZDD(ddMgr, result); + +} // ZDD::operator& + + +ZDD +ZDD::operator&=( + const ZDD& other) +{ + DdManager *mgr = this->checkSameManager(other); + DdNode *result = Cudd_zddIntersect(mgr,node,other.node); + this->checkReturnValue(result); + Cudd_Ref(result); + Cudd_RecursiveDerefZdd(mgr,node); + node = result; + return *this; + +} // ZDD::operator&= + + +ZDD +ZDD::operator+( + const ZDD& other) const +{ + DdManager *mgr = this->checkSameManager(other); + DdNode *result = Cudd_zddUnion(mgr,node,other.node); + this->checkReturnValue(result); + return ZDD(ddMgr, result); + +} // ZDD::operator+ + + +ZDD +ZDD::operator+=( + const ZDD& other) +{ + DdManager *mgr = this->checkSameManager(other); + DdNode *result = Cudd_zddUnion(mgr,node,other.node); + this->checkReturnValue(result); + Cudd_Ref(result); + Cudd_RecursiveDerefZdd(mgr,node); + node = result; + return *this; + +} // ZDD::operator+= + + +ZDD +ZDD::operator|( + const ZDD& other) const +{ + DdManager *mgr = this->checkSameManager(other); + DdNode *result = Cudd_zddUnion(mgr,node,other.node); + this->checkReturnValue(result); + return ZDD(ddMgr, result); + +} // ZDD::operator| + + +ZDD +ZDD::operator|=( + const ZDD& other) +{ + DdManager *mgr = this->checkSameManager(other); + DdNode *result = Cudd_zddUnion(mgr,node,other.node); + this->checkReturnValue(result); + Cudd_Ref(result); + Cudd_RecursiveDerefZdd(mgr,node); + node = result; + return *this; + +} // ZDD::operator|= + + +ZDD +ZDD::operator-( + const ZDD& other) const +{ + DdManager *mgr = this->checkSameManager(other); + DdNode *result = Cudd_zddDiff(mgr,node,other.node); + this->checkReturnValue(result); + return ZDD(ddMgr, result); + +} // ZDD::operator- + + +ZDD +ZDD::operator-=( + const ZDD& other) +{ + DdManager *mgr = this->checkSameManager(other); + DdNode *result = Cudd_zddDiff(mgr,node,other.node); + this->checkReturnValue(result); + Cudd_Ref(result); + Cudd_RecursiveDerefZdd(mgr,node); + node = result; + return *this; + +} // ZDD::operator-= + + +// --------------------------------------------------------------------------- +// Members of class Cudd +// --------------------------------------------------------------------------- + + +Cudd::Cudd( + unsigned int numVars, + unsigned int numVarsZ, + unsigned int numSlots, + unsigned int cacheSize, + unsigned long maxMemory) +{ + p = new capsule; + p->manager = Cudd_Init(numVars,numVarsZ,numSlots,cacheSize,maxMemory); + p->errorHandler = defaultError; + p->verbose = 0; // initially terse + p->ref = 1; + +} // Cudd::Cudd + + +Cudd::Cudd( + Cudd& x) +{ + p = x.p; + x.p->ref++; + +} // Cudd::Cudd + + +Cudd::~Cudd() +{ + if (--p->ref == 0) { + int retval = Cudd_CheckZeroRef(p->manager); + if (retval != 0) { + cerr << retval << " unexpected non-zero reference counts\n"; + } else if (p->verbose) { + cerr << "All went well\n"; + } + Cudd_Quit(p->manager); + delete p; + } + +} // Cudd::~Cudd + + +Cudd& +Cudd::operator=( + const Cudd& right) +{ + right.p->ref++; + if (--p->ref == 0) { // disconnect self + int retval = Cudd_CheckZeroRef(p->manager); + if (retval != 0) { + cerr << retval << " unexpected non-zero reference counts\n"; + } + Cudd_Quit(p->manager); + delete p; + } + p = right.p; + return *this; + +} // Cudd::operator= + + +PFC +Cudd::setHandler( + PFC newHandler) +{ + PFC oldHandler = p->errorHandler; + p->errorHandler = newHandler; + return oldHandler; + +} // Cudd::setHandler + + +PFC +Cudd::getHandler() const +{ + return p->errorHandler; + +} // Cudd::getHandler + + +inline void +Cudd::checkReturnValue( + const DdNode *result) const +{ + if (result == 0) { + if (Cudd_ReadErrorCode(p->manager) == CUDD_MEMORY_OUT) { + p->errorHandler("Out of memory."); + } else { + p->errorHandler("Internal error."); + } + } + +} // Cudd::checkReturnValue + + +inline void +Cudd::checkReturnValue( + const int result) const +{ + if (result == 0) { + if (Cudd_ReadErrorCode(p->manager) == CUDD_MEMORY_OUT) { + p->errorHandler("Out of memory."); + } else { + p->errorHandler("Internal error."); + } + } + +} // Cudd::checkReturnValue + + +void +Cudd::info() const +{ + cout.flush(); + int retval = Cudd_PrintInfo(p->manager,stdout); + this->checkReturnValue(retval); + +} // Cudd::info + + +BDD +Cudd::bddVar() +{ + DdNode *result = Cudd_bddNewVar(p->manager); + this->checkReturnValue(result); + return BDD(this, result); + +} // Cudd::bddVar + + +BDD +Cudd::bddVar( + int index) +{ + DdNode *result = Cudd_bddIthVar(p->manager,index); + this->checkReturnValue(result); + return BDD(this, result); + +} // Cudd::bddVar + + +BDD +Cudd::bddOne() +{ + DdNode *result = Cudd_ReadOne(p->manager); + this->checkReturnValue(result); + return BDD(this, result); + +} // Cudd::bddOne + + +BDD +Cudd::bddZero() +{ + DdNode *result = Cudd_ReadLogicZero(p->manager); + this->checkReturnValue(result); + return BDD(this, result); + +} // Cudd::bddZero + + +ADD +Cudd::addVar() +{ + DdNode *result = Cudd_addNewVar(p->manager); + this->checkReturnValue(result); + return ADD(this, result); + +} // Cudd::addVar + + +ADD +Cudd::addVar( + int index) +{ + DdNode *result = Cudd_addIthVar(p->manager,index); + this->checkReturnValue(result); + return ADD(this, result); + +} // Cudd::addVar + + +ADD +Cudd::addOne() +{ + DdNode *result = Cudd_ReadOne(p->manager); + this->checkReturnValue(result); + return ADD(this, result); + +} // Cudd::addOne + + +ADD +Cudd::addZero() +{ + DdNode *result = Cudd_ReadZero(p->manager); + this->checkReturnValue(result); + return ADD(this, result); + +} // Cudd::addZero + + +ADD +Cudd::constant( + CUDD_VALUE_TYPE c) +{ + DdNode *result = Cudd_addConst(p->manager, c); + this->checkReturnValue(result); + return ADD(this, result); + +} // Cudd::constant + + +ADD +Cudd::plusInfinity() +{ + DdNode *result = Cudd_ReadPlusInfinity(p->manager); + this->checkReturnValue(result); + return ADD(this, result); + +} // Cudd::plusInfinity + + +ADD +Cudd::minusInfinity() +{ + DdNode *result = Cudd_ReadMinusInfinity(p->manager); + this->checkReturnValue(result); + return ADD(this, result); + +} // Cudd::minusInfinity + + +ZDD +Cudd::zddVar( + int index) +{ + DdNode *result = Cudd_zddIthVar(p->manager,index); + this->checkReturnValue(result); + return ZDD(this, result); + +} // Cudd::zddVar + + +ZDD +Cudd::zddOne( + int i) +{ + DdNode *result = Cudd_ReadZddOne(p->manager,i); + this->checkReturnValue(result); + return ZDD(this, result); + +} // Cudd::zddOne + + +ZDD +Cudd::zddZero() +{ + DdNode *result = Cudd_ReadZero(p->manager); + this->checkReturnValue(result); + return ZDD(this, result); + +} // Cudd::zddZero + + +void +defaultError( + string message) +{ + cerr << message << "\n"; + exit(1); + +} // defaultError + + +// --------------------------------------------------------------------------- +// Members of class BDDvector +// --------------------------------------------------------------------------- + + +BDDvector::BDDvector(int size, Cudd *manager, DdNode **nodes) +{ + if (manager == 0 && nodes != 0) defaultError("Nodes with no manager"); + p = new capsule; + p->size = size; + p->manager = manager; + p->vect = new BDD[size]; + p->ref = 1; + for (int i = 0; i < size; i++) { + if (nodes == 0) { + p->vect[i] = BDD(); + } else { + p->vect[i] = BDD(manager, nodes[i]); + } + } + if (manager != 0 && manager->isVerbose()) { + cout << "Standard BDDvector constructor for vector " << hex << long(p) + << "\n"; + } + +} // BDDvector::BDDvector + + +BDDvector::BDDvector(const BDDvector &from) +{ + p = from.p; + p->ref++; + if (p->manager != 0 && p->manager->isVerbose()) { + cout << "Copy BDDvector constructor for vector " << hex << long(p) + << "\n"; + } + +} // BDDvector::BDDvector + + +BDDvector::~BDDvector() +{ + if (p->manager != 0 && p->manager->isVerbose()) { + cout << "BDDvector destructor for vector " << hex << long(p) << + " ref = " << p->ref << "\n"; + } + if (--p->ref == 0) { + delete [] p->vect; + delete p; + } + +} // BDDvector::~BDDvector + + +BDDvector& +BDDvector::operator=( + const BDDvector& right) +{ + right.p->ref++; + if (--p->ref == 0) { // disconnect self + for (int i = 1; i < p->size; i++) { + delete &(p->vect[i]); + } + delete p->vect; + delete p; + } + p = right.p; + return *this; + +} // BDDvector::operator= + + +BDD& +BDDvector::operator[](int i) const +{ + if (i >= p->size) + (p->manager->getHandler())("Out-of-bounds access attempted"); + return p->vect[i]; + +} // BDDvector::operator[] + + +// --------------------------------------------------------------------------- +// Members of class ADDvector +// --------------------------------------------------------------------------- + + +ADDvector::ADDvector(int size, Cudd *manager, DdNode **nodes) +{ + if (manager == 0 && nodes != 0) defaultError("Nodes with no manager"); + p = new capsule; + p->size = size; + p->manager = manager; + p->vect = new ADD[size]; + p->ref = 1; + for (int i = 0; i < size; i++) { + if (nodes == 0) { + p->vect[i] = ADD(); + } else { + p->vect[i] = ADD(manager, nodes[i]); + } + } + if (manager != 0 && manager->isVerbose()) { + cout << "Standard ADDvector constructor for vector " << hex << long(p) + << "\n"; + } + +} // ADDvector::ADDvector + + +ADDvector::ADDvector(const ADDvector &from) +{ + p = from.p; + p->ref++; + if (p->manager != 0 && p->manager->isVerbose()) { + cout << "Copy ADDvector constructor for vector " << hex << long(p) + << "\n"; + } + +} // ADDvector::ADDvector + + +ADDvector::~ADDvector() +{ + if (p->manager != 0 && p->manager->isVerbose()) { + cout << "ADDvector destructor for vector " << hex << long(p) << + " ref = " << p->ref << "\n"; + } + if (--p->ref == 0) { + delete [] p->vect; + delete p; + } + +} // ADDvector::~ADDvector + + +ADDvector& +ADDvector::operator=( + const ADDvector& right) +{ + right.p->ref++; + if (--p->ref == 0) { // disconnect self + for (int i = 1; i < p->size; i++) { + delete &(p->vect[i]); + } + delete p->vect; + delete p; + } + p = right.p; + return *this; + +} // ADDvector::operator= + + +ADD& +ADDvector::operator[](int i) const +{ + if (i >= p->size) + (p->manager->getHandler())("Out-of-bounds access attempted"); + return p->vect[i]; + +} // ADDvector::operator[] + + +// --------------------------------------------------------------------------- +// Members of class ZDDvector +// --------------------------------------------------------------------------- + + +ZDDvector::ZDDvector(int size, Cudd *manager, DdNode **nodes) +{ + if (manager == 0 && nodes != 0) defaultError("Nodes with no manager"); + p = new capsule; + p->size = size; + p->manager = manager; + p->vect = new ZDD[size]; + p->ref = 1; + for (int i = 0; i < size; i++) { + if (nodes == 0) { + p->vect[i] = ZDD(); + } else { + p->vect[i] = ZDD(manager, nodes[i]); + } + } + if (manager != 0 && manager->isVerbose()) { + cout << "Standard ZDDvector constructor for vector " << hex << long(p) + << "\n"; + } + +} // ZDDvector::ZDDvector + + +ZDDvector::ZDDvector(const ZDDvector &from) +{ + p = from.p; + p->ref++; + if (p->manager != 0 && p->manager->isVerbose()) { + cout << "Copy ZDDvector constructor for vector " << hex << long(p) + << "\n"; + } + +} // ZDDvector::ZDDvector + + +ZDDvector::~ZDDvector() +{ + if (p->manager != 0 && p->manager->isVerbose()) { + cout << "ZDDvector destructor for vector " << hex << long(p) << + " ref = " << p->ref << "\n"; + } + if (--p->ref == 0) { + delete [] p->vect; + delete p; + } + +} // ZDDvector::~ZDDvector + + +ZDDvector& +ZDDvector::operator=( + const ZDDvector& right) +{ + right.p->ref++; + if (--p->ref == 0) { // disconnect self + for (int i = 1; i < p->size; i++) { + delete &(p->vect[i]); + } + delete p->vect; + delete p; + } + p = right.p; + return *this; + +} // ZDDvector::operator= + + +ZDD& +ZDDvector::operator[](int i) const +{ + if (i >= p->size) + (p->manager->getHandler())("Out-of-bounds access attempted"); + return p->vect[i]; + +} // ZDDvector::operator[] + + +// --------------------------------------------------------------------------- +// All the rest +// --------------------------------------------------------------------------- + + +ADD +Cudd::addNewVarAtLevel( + int level) +{ + DdNode *result = Cudd_addNewVarAtLevel(p->manager, level); + this->checkReturnValue(result); + return ADD(this, result); + +} // Cudd::addNewVarAtLevel + + +BDD +Cudd::bddNewVarAtLevel( + int level) +{ + DdNode *result = Cudd_bddNewVarAtLevel(p->manager, level); + this->checkReturnValue(result); + return BDD(this, result); + +} // Cudd::bddNewVarAtLevel + + +void +Cudd::zddVarsFromBddVars( + int multiplicity) +{ + int result = Cudd_zddVarsFromBddVars(p->manager, multiplicity); + this->checkReturnValue(result); + +} // Cudd::zddVarsFromBddVars + + +void +Cudd::AutodynEnable( + Cudd_ReorderingType method) +{ + Cudd_AutodynEnable(p->manager, method); + +} // Cudd::AutodynEnable + + +void +Cudd::AutodynDisable() +{ + Cudd_AutodynDisable(p->manager); + +} // Cudd::AutodynDisable + + +int +Cudd::ReorderingStatus( + Cudd_ReorderingType * method) const +{ + return Cudd_ReorderingStatus(p->manager, method); + +} // Cudd::ReorderingStatus + + +void +Cudd::AutodynEnableZdd( + Cudd_ReorderingType method) +{ + Cudd_AutodynEnableZdd(p->manager, method); + +} // Cudd::AutodynEnableZdd + + +void +Cudd::AutodynDisableZdd() +{ + Cudd_AutodynDisableZdd(p->manager); + +} // Cudd::AutodynDisableZdd + + +int +Cudd::ReorderingStatusZdd( + Cudd_ReorderingType * method) const +{ + return Cudd_ReorderingStatusZdd(p->manager, method); + +} // Cudd::ReorderingStatusZdd + + +int +Cudd::zddRealignmentEnabled() const +{ + return Cudd_zddRealignmentEnabled(p->manager); + +} // Cudd::zddRealignmentEnabled + + +void +Cudd::zddRealignEnable() +{ + Cudd_zddRealignEnable(p->manager); + +} // Cudd::zddRealignEnable + + +void +Cudd::zddRealignDisable() +{ + Cudd_zddRealignDisable(p->manager); + +} // Cudd::zddRealignDisable + + +int +Cudd::bddRealignmentEnabled() const +{ + return Cudd_bddRealignmentEnabled(p->manager); + +} // Cudd::bddRealignmentEnabled + + +void +Cudd::bddRealignEnable() +{ + Cudd_bddRealignEnable(p->manager); + +} // Cudd::bddRealignEnable + + +void +Cudd::bddRealignDisable() +{ + Cudd_bddRealignDisable(p->manager); + +} // Cudd::bddRealignDisable + + +ADD +Cudd::background() +{ + DdNode *result = Cudd_ReadBackground(p->manager); + this->checkReturnValue(result); + return ADD(this, result); + +} // Cudd::background + + +void +Cudd::SetBackground( + ADD bg) +{ + DdManager *mgr = p->manager; + if (mgr != bg.manager()->p->manager) { + p->errorHandler("Background comes from different manager."); + } + Cudd_SetBackground(mgr, bg.getNode()); + +} // Cudd::SetBackground + + +unsigned int +Cudd::ReadCacheSlots() const +{ + return Cudd_ReadCacheSlots(p->manager); + +} // Cudd::ReadCacheSlots + + +double +Cudd::ReadCacheLookUps() const +{ + return Cudd_ReadCacheLookUps(p->manager); + +} // Cudd::ReadCacheLookUps + + +double +Cudd::ReadCacheUsedSlots() const +{ + return Cudd_ReadCacheUsedSlots(p->manager); + +} // Cudd::ReadCacheUsedSlots + + +double +Cudd::ReadCacheHits() const +{ + return Cudd_ReadCacheHits(p->manager); + +} // Cudd::ReadCacheHits + + +unsigned int +Cudd::ReadMinHit() const +{ + return Cudd_ReadMinHit(p->manager); + +} // Cudd::ReadMinHit + + +void +Cudd::SetMinHit( + unsigned int hr) +{ + Cudd_SetMinHit(p->manager, hr); + +} // Cudd::SetMinHit + + +unsigned int +Cudd::ReadLooseUpTo() const +{ + return Cudd_ReadLooseUpTo(p->manager); + +} // Cudd::ReadLooseUpTo + + +void +Cudd::SetLooseUpTo( + unsigned int lut) +{ + Cudd_SetLooseUpTo(p->manager, lut); + +} // Cudd::SetLooseUpTo + + +unsigned int +Cudd::ReadMaxCache() const +{ + return Cudd_ReadMaxCache(p->manager); + +} // Cudd::ReadMaxCache + + +unsigned int +Cudd::ReadMaxCacheHard() const +{ + return Cudd_ReadMaxCacheHard(p->manager); + +} // Cudd::ReadMaxCacheHard + + +void +Cudd::SetMaxCacheHard( + unsigned int mc) +{ + Cudd_SetMaxCacheHard(p->manager, mc); + +} // Cudd::SetMaxCacheHard + + +int +Cudd::ReadSize() const +{ + return Cudd_ReadSize(p->manager); + +} // Cudd::ReadSize + + +int +Cudd::ReadZddSize() const +{ + return Cudd_ReadZddSize(p->manager); + +} // Cudd::ReadZddSize + + +unsigned int +Cudd::ReadSlots() const +{ + return Cudd_ReadSlots(p->manager); + +} // Cudd::ReadSlots + + +unsigned int +Cudd::ReadKeys() const +{ + return Cudd_ReadKeys(p->manager); + +} // Cudd::ReadKeys + + +unsigned int +Cudd::ReadDead() const +{ + return Cudd_ReadDead(p->manager); + +} // Cudd::ReadDead + + +unsigned int +Cudd::ReadMinDead() const +{ + return Cudd_ReadMinDead(p->manager); + +} // Cudd::ReadMinDead + + +int +Cudd::ReadReorderings() const +{ + return Cudd_ReadReorderings(p->manager); + +} // Cudd::ReadReorderings + + +long +Cudd::ReadReorderingTime() const +{ + return Cudd_ReadReorderingTime(p->manager); + +} // Cudd::ReadReorderingTime + + +int +Cudd::ReadGarbageCollections() const +{ + return Cudd_ReadGarbageCollections(p->manager); + +} // Cudd::ReadGarbageCollections + + +long +Cudd::ReadGarbageCollectionTime() const +{ + return Cudd_ReadGarbageCollectionTime(p->manager); + +} // Cudd::ReadGarbageCollectionTime + + +int +Cudd::ReadSiftMaxVar() const +{ + return Cudd_ReadSiftMaxVar(p->manager); + +} // Cudd::ReadSiftMaxVar + + +void +Cudd::SetSiftMaxVar( + int smv) +{ + Cudd_SetSiftMaxVar(p->manager, smv); + +} // Cudd::SetSiftMaxVar + + +int +Cudd::ReadSiftMaxSwap() const +{ + return Cudd_ReadSiftMaxSwap(p->manager); + +} // Cudd::ReadSiftMaxSwap + + +void +Cudd::SetSiftMaxSwap( + int sms) +{ + Cudd_SetSiftMaxSwap(p->manager, sms); + +} // Cudd::SetSiftMaxSwap + + +double +Cudd::ReadMaxGrowth() const +{ + return Cudd_ReadMaxGrowth(p->manager); + +} // Cudd::ReadMaxGrowth + + +void +Cudd::SetMaxGrowth( + double mg) +{ + Cudd_SetMaxGrowth(p->manager, mg); + +} // Cudd::SetMaxGrowth + + +MtrNode * +Cudd::ReadTree() const +{ + return Cudd_ReadTree(p->manager); + +} // Cudd::ReadTree + + +void +Cudd::SetTree( + MtrNode * tree) +{ + Cudd_SetTree(p->manager, tree); + +} // Cudd::SetTree + + +void +Cudd::FreeTree() +{ + Cudd_FreeTree(p->manager); + +} // Cudd::FreeTree + + +MtrNode * +Cudd::ReadZddTree() const +{ + return Cudd_ReadZddTree(p->manager); + +} // Cudd::ReadZddTree + + +void +Cudd::SetZddTree( + MtrNode * tree) +{ + Cudd_SetZddTree(p->manager, tree); + +} // Cudd::SetZddTree + + +void +Cudd::FreeZddTree() +{ + Cudd_FreeZddTree(p->manager); + +} // Cudd::FreeZddTree + + +unsigned int +DD::NodeReadIndex() const +{ + return Cudd_NodeReadIndex(node); + +} // DD::NodeReadIndex + + +int +Cudd::ReadPerm( + int i) const +{ + return Cudd_ReadPerm(p->manager, i); + +} // Cudd::ReadPerm + + +int +Cudd::ReadPermZdd( + int i) const +{ + return Cudd_ReadPermZdd(p->manager, i); + +} // Cudd::ReadPermZdd + + +int +Cudd::ReadInvPerm( + int i) const +{ + return Cudd_ReadInvPerm(p->manager, i); + +} // Cudd::ReadInvPerm + + +int +Cudd::ReadInvPermZdd( + int i) const +{ + return Cudd_ReadInvPermZdd(p->manager, i); + +} // Cudd::ReadInvPermZdd + + +BDD +Cudd::ReadVars( + int i) +{ + DdNode *result = Cudd_ReadVars(p->manager, i); + this->checkReturnValue(result); + return BDD(this, result); + +} // Cudd::ReadVars + + +CUDD_VALUE_TYPE +Cudd::ReadEpsilon() const +{ + return Cudd_ReadEpsilon(p->manager); + +} // Cudd::ReadEpsilon + + +void +Cudd::SetEpsilon( + CUDD_VALUE_TYPE ep) +{ + Cudd_SetEpsilon(p->manager, ep); + +} // Cudd::SetEpsilon + + +Cudd_AggregationType +Cudd::ReadGroupcheck() const +{ + return Cudd_ReadGroupcheck(p->manager); + +} // Cudd::ReadGroupcheck + + +void +Cudd::SetGroupcheck( + Cudd_AggregationType gc) +{ + Cudd_SetGroupcheck(p->manager, gc); + +} // Cudd::SetGroupcheck + + +int +Cudd::GarbageCollectionEnabled() const +{ + return Cudd_GarbageCollectionEnabled(p->manager); + +} // Cudd::GarbageCollectionEnabled + + +void +Cudd::EnableGarbageCollection() +{ + Cudd_EnableGarbageCollection(p->manager); + +} // Cudd::EnableGarbageCollection + + +void +Cudd::DisableGarbageCollection() +{ + Cudd_DisableGarbageCollection(p->manager); + +} // Cudd::DisableGarbageCollection + + +int +Cudd::DeadAreCounted() const +{ + return Cudd_DeadAreCounted(p->manager); + +} // Cudd::DeadAreCounted + + +void +Cudd::TurnOnCountDead() +{ + Cudd_TurnOnCountDead(p->manager); + +} // Cudd::TurnOnCountDead + + +void +Cudd::TurnOffCountDead() +{ + Cudd_TurnOffCountDead(p->manager); + +} // Cudd::TurnOffCountDead + + +int +Cudd::ReadRecomb() const +{ + return Cudd_ReadRecomb(p->manager); + +} // Cudd::ReadRecomb + + +void +Cudd::SetRecomb( + int recomb) +{ + Cudd_SetRecomb(p->manager, recomb); + +} // Cudd::SetRecomb + + +int +Cudd::ReadSymmviolation() const +{ + return Cudd_ReadSymmviolation(p->manager); + +} // Cudd::ReadSymmviolation + + +void +Cudd::SetSymmviolation( + int symmviolation) +{ + Cudd_SetSymmviolation(p->manager, symmviolation); + +} // Cudd::SetSymmviolation + + +int +Cudd::ReadArcviolation() const +{ + return Cudd_ReadArcviolation(p->manager); + +} // Cudd::ReadArcviolation + + +void +Cudd::SetArcviolation( + int arcviolation) +{ + Cudd_SetArcviolation(p->manager, arcviolation); + +} // Cudd::SetArcviolation + + +int +Cudd::ReadPopulationSize() const +{ + return Cudd_ReadPopulationSize(p->manager); + +} // Cudd::ReadPopulationSize + + +void +Cudd::SetPopulationSize( + int populationSize) +{ + Cudd_SetPopulationSize(p->manager, populationSize); + +} // Cudd::SetPopulationSize + + +int +Cudd::ReadNumberXovers() const +{ + return Cudd_ReadNumberXovers(p->manager); + +} // Cudd::ReadNumberXovers + + +void +Cudd::SetNumberXovers( + int numberXovers) +{ + Cudd_SetNumberXovers(p->manager, numberXovers); + +} // Cudd::SetNumberXovers + + +unsigned long +Cudd::ReadMemoryInUse() const +{ + return Cudd_ReadMemoryInUse(p->manager); + +} // Cudd::ReadMemoryInUse + + +long +Cudd::ReadPeakNodeCount() const +{ + return Cudd_ReadPeakNodeCount(p->manager); + +} // Cudd::ReadPeakNodeCount + + +long +Cudd::ReadNodeCount() const +{ + return Cudd_ReadNodeCount(p->manager); + +} // Cudd::ReadNodeCount + + +long +Cudd::zddReadNodeCount() const +{ + return Cudd_zddReadNodeCount(p->manager); + +} // Cudd::zddReadNodeCount + + +void +Cudd::AddHook( + DD_HFP f, + Cudd_HookType where) +{ + int result = Cudd_AddHook(p->manager, f, where); + this->checkReturnValue(result); + +} // Cudd::AddHook + + +void +Cudd::RemoveHook( + DD_HFP f, + Cudd_HookType where) +{ + int result = Cudd_RemoveHook(p->manager, f, where); + this->checkReturnValue(result); + +} // Cudd::RemoveHook + + +int +Cudd::IsInHook( + DD_HFP f, + Cudd_HookType where) const +{ + return Cudd_IsInHook(p->manager, f, where); + +} // Cudd::IsInHook + + +void +Cudd::EnableReorderingReporting() +{ + int result = Cudd_EnableReorderingReporting(p->manager); + this->checkReturnValue(result); + +} // Cudd::EnableReorderingReporting + + +void +Cudd::DisableReorderingReporting() +{ + int result = Cudd_DisableReorderingReporting(p->manager); + this->checkReturnValue(result); + +} // Cudd::DisableReorderingReporting + + +int +Cudd::ReorderingReporting() +{ + return Cudd_ReorderingReporting(p->manager); + +} // Cudd::ReorderingReporting + + +int +Cudd::ReadErrorCode() const +{ + return Cudd_ReadErrorCode(p->manager); + +} // Cudd::ReadErrorCode + + +void +Cudd::ClearErrorCode() +{ + Cudd_ClearErrorCode(p->manager); + +} // Cudd::ClearErrorCode + + +FILE * +Cudd::ReadStdout() const +{ + return Cudd_ReadStdout(p->manager); + +} // Cudd::ReadStdout + + +void +Cudd::SetStdout(FILE *fp) +{ + Cudd_SetStdout(p->manager, fp); + +} // Cudd::SetStdout + + +FILE * +Cudd::ReadStderr() const +{ + return Cudd_ReadStderr(p->manager); + +} // Cudd::ReadStderr + + +void +Cudd::SetStderr(FILE *fp) +{ + Cudd_SetStderr(p->manager, fp); + +} // Cudd::SetStderr + + +unsigned int +Cudd::ReadNextReordering() const +{ + return Cudd_ReadNextReordering(p->manager); + +} // Cudd::ReadNextReordering + + +double +Cudd::ReadSwapSteps() const +{ + return Cudd_ReadSwapSteps(p->manager); + +} // Cudd::ReadSwapSteps + + +unsigned int +Cudd::ReadMaxLive() const +{ + return Cudd_ReadMaxLive(p->manager); + +} // Cudd::ReadMaxLive + + +void +Cudd::SetMaxLive(unsigned int maxLive) +{ + Cudd_SetMaxLive(p->manager, maxLive); + +} // Cudd::SetMaxLive + + +unsigned long +Cudd::ReadMaxMemory() const +{ + return Cudd_ReadMaxMemory(p->manager); + +} // Cudd::ReadMaxMemory + + +void +Cudd::SetMaxMemory(unsigned long maxMem) +{ + Cudd_SetMaxMemory(p->manager, maxMem); + +} // Cudd::SetMaxMemory + + +int +Cudd::bddBindVar(int index) +{ + return Cudd_bddBindVar(p->manager, index); + +} // Cudd::bddBindVar + + +int +Cudd::bddUnbindVar(int index) +{ + return Cudd_bddUnbindVar(p->manager, index); + +} // Cudd::bddUnbindVar + + +int +Cudd::bddVarIsBound(int index) const +{ + return Cudd_bddVarIsBound(p->manager, index); + +} // Cudd::bddVarIsBound + + +ADD +ADD::ExistAbstract( + const ADD& cube) const +{ + DdManager *mgr = this->checkSameManager(cube); + DdNode *result = Cudd_addExistAbstract(mgr, node, cube.node); + this->checkReturnValue(result); + return ADD(ddMgr, result); + +} // ADD::ExistAbstract + + +ADD +ADD::UnivAbstract( + const ADD& cube) const +{ + DdManager *mgr = this->checkSameManager(cube); + DdNode *result = Cudd_addUnivAbstract(mgr, node, cube.node); + this->checkReturnValue(result); + return ADD(ddMgr, result); + +} // ADD::UnivAbstract + + +ADD +ADD::OrAbstract( + const ADD& cube) const +{ + DdManager *mgr = this->checkSameManager(cube); + DdNode *result = Cudd_addOrAbstract(mgr, node, cube.node); + this->checkReturnValue(result); + return ADD(ddMgr, result); + +} // ADD::OrAbstract + + +ADD +ADD::Plus( + const ADD& g) const +{ + DdManager *mgr = this->checkSameManager(g); + DdNode *result = Cudd_addApply(mgr, Cudd_addPlus, node, g.node); + this->checkReturnValue(result); + return ADD(ddMgr, result); + +} // ADD::Plus + + +ADD +ADD::Times( + const ADD& g) const +{ + DdManager *mgr = this->checkSameManager(g); + DdNode *result = Cudd_addApply(mgr, Cudd_addTimes, node, g.node); + this->checkReturnValue(result); + return ADD(ddMgr, result); + +} // ADD::Times + + +ADD +ADD::Threshold( + const ADD& g) const +{ + DdManager *mgr = this->checkSameManager(g); + DdNode *result = Cudd_addApply(mgr, Cudd_addThreshold, node, g.node); + this->checkReturnValue(result); + return ADD(ddMgr, result); + +} // ADD::Threshold + + +ADD +ADD::SetNZ( + const ADD& g) const +{ + DdManager *mgr = this->checkSameManager(g); + DdNode *result = Cudd_addApply(mgr, Cudd_addSetNZ, node, g.node); + this->checkReturnValue(result); + return ADD(ddMgr, result); + +} // ADD::SetNZ + + +ADD +ADD::Divide( + const ADD& g) const +{ + DdManager *mgr = this->checkSameManager(g); + DdNode *result = Cudd_addApply(mgr, Cudd_addDivide, node, g.node); + this->checkReturnValue(result); + return ADD(ddMgr, result); + +} // ADD::Divide + + +ADD +ADD::Minus( + const ADD& g) const +{ + DdManager *mgr = this->checkSameManager(g); + DdNode *result = Cudd_addApply(mgr, Cudd_addMinus, node, g.node); + this->checkReturnValue(result); + return ADD(ddMgr, result); + +} // ADD::Minus + + +ADD +ADD::Minimum( + const ADD& g) const +{ + DdManager *mgr = this->checkSameManager(g); + DdNode *result = Cudd_addApply(mgr, Cudd_addMinimum, node, g.node); + this->checkReturnValue(result); + return ADD(ddMgr, result); + +} // ADD::Minimum + + +ADD +ADD::Maximum( + const ADD& g) const +{ + DdManager *mgr = this->checkSameManager(g); + DdNode *result = Cudd_addApply(mgr, Cudd_addMaximum, node, g.node); + this->checkReturnValue(result); + return ADD(ddMgr, result); + +} // ADD::Maximum + + +ADD +ADD::OneZeroMaximum( + const ADD& g) const +{ + DdManager *mgr = this->checkSameManager(g); + DdNode *result = Cudd_addApply(mgr, Cudd_addOneZeroMaximum, node, g.node); + this->checkReturnValue(result); + return ADD(ddMgr, result); + +} // ADD::OneZeroMaximum + + +ADD +ADD::Diff( + const ADD& g) const +{ + DdManager *mgr = this->checkSameManager(g); + DdNode *result = Cudd_addApply(mgr, Cudd_addDiff, node, g.node); + this->checkReturnValue(result); + return ADD(ddMgr, result); + +} // ADD::Diff + + +ADD +ADD::Agreement( + const ADD& g) const +{ + DdManager *mgr = this->checkSameManager(g); + DdNode *result = Cudd_addApply(mgr, Cudd_addAgreement, node, g.node); + this->checkReturnValue(result); + return ADD(ddMgr, result); + +} // ADD::Agreement + + +ADD +ADD::Or( + const ADD& g) const +{ + DdManager *mgr = this->checkSameManager(g); + DdNode *result = Cudd_addApply(mgr, Cudd_addOr, node, g.node); + this->checkReturnValue(result); + return ADD(ddMgr, result); + +} // ADD::Or + + +ADD +ADD::Nand( + const ADD& g) const +{ + DdManager *mgr = this->checkSameManager(g); + DdNode *result = Cudd_addApply(mgr, Cudd_addNand, node, g.node); + this->checkReturnValue(result); + return ADD(ddMgr, result); + +} // ADD::Nand + + +ADD +ADD::Nor( + const ADD& g) const +{ + DdManager *mgr = this->checkSameManager(g); + DdNode *result = Cudd_addApply(mgr, Cudd_addNor, node, g.node); + this->checkReturnValue(result); + return ADD(ddMgr, result); + +} // ADD::Nor + + +ADD +ADD::Xor( + const ADD& g) const +{ + DdManager *mgr = this->checkSameManager(g); + DdNode *result = Cudd_addApply(mgr, Cudd_addXor, node, g.node); + this->checkReturnValue(result); + return ADD(ddMgr, result); + +} // ADD::Xor + + +ADD +ADD::Xnor( + const ADD& g) const +{ + DdManager *mgr = this->checkSameManager(g); + DdNode *result = Cudd_addApply(mgr, Cudd_addXnor, node, g.node); + this->checkReturnValue(result); + return ADD(ddMgr, result); + +} // ADD::Xnor + + +ADD +ADD::Log() const +{ + DdManager *mgr = ddMgr->p->manager; + DdNode *result = Cudd_addMonadicApply(mgr, Cudd_addLog, node); + this->checkReturnValue(result); + return ADD(ddMgr, result); + +} // ADD::Log + + +ADD +ADD::FindMax() const +{ + DdManager *mgr = ddMgr->p->manager; + DdNode *result = Cudd_addFindMax(mgr, node); + this->checkReturnValue(result); + return ADD(ddMgr, result); + +} // ADD::FindMax + + +ADD +ADD::FindMin() const +{ + DdManager *mgr = ddMgr->p->manager; + DdNode *result = Cudd_addFindMin(mgr, node); + this->checkReturnValue(result); + return ADD(ddMgr, result); + +} // ADD::FindMin + + +ADD +ADD::IthBit( + int bit) const +{ + DdManager *mgr = ddMgr->p->manager; + DdNode *result = Cudd_addIthBit(mgr, node, bit); + this->checkReturnValue(result); + return ADD(ddMgr, result); + +} // ADD::IthBit + + +ADD +ADD::ScalarInverse( + const ADD& epsilon) const +{ + DdManager *mgr = this->checkSameManager(epsilon); + DdNode *result = Cudd_addScalarInverse(mgr, node, epsilon.node); + this->checkReturnValue(result); + return ADD(ddMgr, result); + +} // ADD::ScalarInverse + + +ADD +ADD::Ite( + const ADD& g, + const ADD& h) const +{ + DdManager *mgr = this->checkSameManager(g); + this->checkSameManager(h); + DdNode *result = Cudd_addIte(mgr, node, g.node, h.node); + this->checkReturnValue(result); + return ADD(ddMgr, result); + +} // ADD::Ite + + +ADD +ADD::IteConstant( + const ADD& g, + const ADD& h) const +{ + DdManager *mgr = this->checkSameManager(g); + this->checkSameManager(h); + DdNode *result = Cudd_addIteConstant(mgr, node, g.node, h.node); + this->checkReturnValue(result); + return ADD(ddMgr, result); + +} // ADD::IteConstant + + +ADD +ADD::EvalConst( + const ADD& g) const +{ + DdManager *mgr = this->checkSameManager(g); + DdNode *result = Cudd_addEvalConst(mgr, node, g.node); + this->checkReturnValue(result); + return ADD(ddMgr, result); + +} // ADD::EvalConst + + +int +ADD::Leq( + const ADD& g) const +{ + DdManager *mgr = this->checkSameManager(g); + return Cudd_addLeq(mgr, node, g.node); + +} // ADD::Leq + + +ADD +ADD::Cmpl() const +{ + DdManager *mgr = ddMgr->p->manager; + DdNode *result = Cudd_addCmpl(mgr, node); + this->checkReturnValue(result); + return ADD(ddMgr, result); + +} // ADD::Cmpl + + +ADD +ADD::Negate() const +{ + DdManager *mgr = ddMgr->p->manager; + DdNode *result = Cudd_addNegate(mgr, node); + this->checkReturnValue(result); + return ADD(ddMgr, result); + +} // ADD::Negate + + +ADD +ADD::RoundOff( + int N) const +{ + DdManager *mgr = ddMgr->p->manager; + DdNode *result = Cudd_addRoundOff(mgr, node, N); + this->checkReturnValue(result); + return ADD(ddMgr, result); + +} // ADD::RoundOff + + +ADD +Cudd::Walsh( + ADDvector x, + ADDvector y) +{ + int n = x.count(); + DdNode **X = ALLOC(DdNode *,n); + DdNode **Y = ALLOC(DdNode *,n); + for (int i = 0; i < n; i++) { + X[i] = x[i].getNode(); + Y[i] = y[i].getNode(); + } + DdNode *result = Cudd_addWalsh(p->manager, X, Y, n); + FREE(X); + FREE(Y); + this->checkReturnValue(result); + return ADD(this, result); + +} // ADD::Walsh + + +ADD +Cudd::addResidue( + int n, + int m, + int options, + int top) +{ + DdNode *result = Cudd_addResidue(p->manager, n, m, options, top); + this->checkReturnValue(result); + return ADD(this, result); + +} // Cudd::addResidue + + +BDD +BDD::AndAbstract( + const BDD& g, + const BDD& cube) const +{ + DdManager *mgr = this->checkSameManager(g); + this->checkSameManager(cube); + DdNode *result = Cudd_bddAndAbstract(mgr, node, g.node, cube.node); + this->checkReturnValue(result); + return BDD(ddMgr, result); + +} // BDD::AndAbstract + + +BDD +BDD::AndAbstractLimit( + const BDD& g, + const BDD& cube, + unsigned int limit) const +{ + DdManager *mgr = this->checkSameManager(g); + this->checkSameManager(cube); + DdNode *result = Cudd_bddAndAbstractLimit(mgr, node, g.node, + cube.node, limit); + this->checkReturnValue(result); + return BDD(ddMgr, result); + +} // BDD::AndAbstractLimit + + +int +Cudd::ApaNumberOfDigits( + int binaryDigits) const +{ + return Cudd_ApaNumberOfDigits(binaryDigits); + +} // Cudd::ApaNumberOfDigits + + +DdApaNumber +Cudd::NewApaNumber( + int digits) const +{ + return Cudd_NewApaNumber(digits); + +} // Cudd::NewApaNumber + + +void +Cudd::ApaCopy( + int digits, + DdApaNumber source, + DdApaNumber dest) const +{ + Cudd_ApaCopy(digits, source, dest); + +} // Cudd::ApaCopy + + +DdApaDigit +Cudd::ApaAdd( + int digits, + DdApaNumber a, + DdApaNumber b, + DdApaNumber sum) const +{ + return Cudd_ApaAdd(digits, a, b, sum); + +} // Cudd::ApaAdd + + +DdApaDigit +Cudd::ApaSubtract( + int digits, + DdApaNumber a, + DdApaNumber b, + DdApaNumber diff) const +{ + return Cudd_ApaSubtract(digits, a, b, diff); + +} // Cudd::ApaSubtract + + +DdApaDigit +Cudd::ApaShortDivision( + int digits, + DdApaNumber dividend, + DdApaDigit divisor, + DdApaNumber quotient) const +{ + return Cudd_ApaShortDivision(digits, dividend, divisor, quotient); + +} // Cudd::ApaShortDivision + + +void +Cudd::ApaShiftRight( + int digits, + DdApaDigit in, + DdApaNumber a, + DdApaNumber b) const +{ + Cudd_ApaShiftRight(digits, in, a, b); + +} // Cudd::ApaShiftRight + + +void +Cudd::ApaSetToLiteral( + int digits, + DdApaNumber number, + DdApaDigit literal) const +{ + Cudd_ApaSetToLiteral(digits, number, literal); + +} // Cudd::ApaSetToLiteral + + +void +Cudd::ApaPowerOfTwo( + int digits, + DdApaNumber number, + int power) const +{ + Cudd_ApaPowerOfTwo(digits, number, power); + +} // Cudd::ApaPowerOfTwo + + +void +Cudd::ApaPrintHex( + FILE * fp, + int digits, + DdApaNumber number) const +{ + cout.flush(); + int result = Cudd_ApaPrintHex(fp, digits, number); + this->checkReturnValue(result); + +} // Cudd::ApaPrintHex + + +void +Cudd::ApaPrintDecimal( + FILE * fp, + int digits, + DdApaNumber number) const +{ + cout.flush(); + int result = Cudd_ApaPrintDecimal(fp, digits, number); + this->checkReturnValue(result); + +} // Cudd::ApaPrintDecimal + + +DdApaNumber +ABDD::ApaCountMinterm( + int nvars, + int * digits) const +{ + DdManager *mgr = ddMgr->p->manager; + return Cudd_ApaCountMinterm(mgr, node, nvars, digits); + +} // ABDD::ApaCountMinterm + + +void +ABDD::ApaPrintMinterm( + int nvars, + FILE * fp) const +{ + cout.flush(); + DdManager *mgr = ddMgr->p->manager; + int result = Cudd_ApaPrintMinterm(fp, mgr, node, nvars); + this->checkReturnValue(result); + +} // ABDD::ApaPrintMinterm + + +void +ABDD::EpdPrintMinterm( + int nvars, + FILE * fp) const +{ + EpDouble count; + char str[24]; + cout.flush(); + DdManager *mgr = ddMgr->p->manager; + int result = Cudd_EpdCountMinterm(mgr, node, nvars, &count); + this->checkReturnValue(result,0); + EpdGetString(&count, str); + fprintf(fp, "%s\n", str); + +} // ABDD::ApaPrintMinterm + + +BDD +BDD::UnderApprox( + int numVars, + int threshold, + int safe, + double quality) const +{ + DdManager *mgr = ddMgr->p->manager; + DdNode *result = Cudd_UnderApprox(mgr, node, numVars, threshold, safe, quality); + this->checkReturnValue(result); + return BDD(ddMgr, result); + +} // BDD::UnderApprox + + +BDD +BDD::OverApprox( + int numVars, + int threshold, + int safe, + double quality) const +{ + DdManager *mgr = ddMgr->p->manager; + DdNode *result = Cudd_OverApprox(mgr, node, numVars, threshold, safe, quality); + this->checkReturnValue(result); + return BDD(ddMgr, result); + +} // BDD::OverApprox + + +BDD +BDD::RemapUnderApprox( + int numVars, + int threshold, + double quality) const +{ + DdManager *mgr = ddMgr->p->manager; + DdNode *result = Cudd_RemapUnderApprox(mgr, node, numVars, threshold, quality); + this->checkReturnValue(result); + return BDD(ddMgr, result); + +} // BDD::RemapUnderApprox + + +BDD +BDD::RemapOverApprox( + int numVars, + int threshold, + double quality) const +{ + DdManager *mgr = ddMgr->p->manager; + DdNode *result = Cudd_RemapOverApprox(mgr, node, numVars, threshold, quality); + this->checkReturnValue(result); + return BDD(ddMgr, result); + +} // BDD::RemapOverApprox + + +BDD +BDD::ExistAbstract( + const BDD& cube) const +{ + DdManager *mgr = this->checkSameManager(cube); + DdNode *result = Cudd_bddExistAbstract(mgr, node, cube.node); + this->checkReturnValue(result); + return BDD(ddMgr, result); + +} // BDD::ExistAbstract + + +BDD +BDD::XorExistAbstract( + const BDD& g, + const BDD& cube) const +{ + DdManager *mgr = this->checkSameManager(g); + this->checkSameManager(cube); + DdNode *result = Cudd_bddXorExistAbstract(mgr, node, g.node, cube.node); + this->checkReturnValue(result); + return BDD(ddMgr, result); + +} // BDD::XorExistAbstract + + +BDD +BDD::UnivAbstract( + const BDD& cube) const +{ + DdManager *mgr = this->checkSameManager(cube); + DdNode *result = Cudd_bddUnivAbstract(mgr, node, cube.node); + this->checkReturnValue(result); + return BDD(ddMgr, result); + +} // BDD::UnivAbstract + + +BDD +BDD::BooleanDiff( + int x) const +{ + DdManager *mgr = ddMgr->p->manager; + DdNode *result = Cudd_bddBooleanDiff(mgr, node, x); + this->checkReturnValue(result); + return BDD(ddMgr, result); + +} // BDD::BooleanDiff + + +int +BDD::VarIsDependent( + const BDD& var) const +{ + DdManager *mgr = ddMgr->p->manager; + return Cudd_bddVarIsDependent(mgr, node, var.node); + +} // BDD::VarIsDependent + + +double +BDD::Correlation( + const BDD& g) const +{ + DdManager *mgr = this->checkSameManager(g); + return Cudd_bddCorrelation(mgr, node, g.node); + +} // BDD::Correlation + + +double +BDD::CorrelationWeights( + const BDD& g, + double * prob) const +{ + DdManager *mgr = this->checkSameManager(g); + return Cudd_bddCorrelationWeights(mgr, node, g.node, prob); + +} // BDD::CorrelationWeights + + +BDD +BDD::Ite( + const BDD& g, + const BDD& h) const +{ + DdManager *mgr = this->checkSameManager(g); + this->checkSameManager(h); + DdNode *result = Cudd_bddIte(mgr, node, g.node, h.node); + this->checkReturnValue(result); + return BDD(ddMgr, result); + +} // BDD::Ite + + +BDD +BDD::IteConstant( + const BDD& g, + const BDD& h) const +{ + DdManager *mgr = this->checkSameManager(g); + this->checkSameManager(h); + DdNode *result = Cudd_bddIteConstant(mgr, node, g.node, h.node); + this->checkReturnValue(result); + return BDD(ddMgr, result); + +} // BDD::IteConstant + + +BDD +BDD::Intersect( + const BDD& g) const +{ + DdManager *mgr = this->checkSameManager(g); + DdNode *result = Cudd_bddIntersect(mgr, node, g.node); + this->checkReturnValue(result); + return BDD(ddMgr, result); + +} // BDD::Intersect + + +BDD +BDD::And( + const BDD& g) const +{ + DdManager *mgr = this->checkSameManager(g); + DdNode *result = Cudd_bddAnd(mgr, node, g.node); + this->checkReturnValue(result); + return BDD(ddMgr, result); + +} // BDD::And + + +BDD +BDD::AndLimit( + const BDD& g, + unsigned int limit) const +{ + DdManager *mgr = this->checkSameManager(g); + DdNode *result = Cudd_bddAndLimit(mgr, node, g.node, limit); + this->checkReturnValue(result); + return BDD(ddMgr, result); + +} // BDD::AndLimit + + +BDD +BDD::Or( + const BDD& g) const +{ + DdManager *mgr = this->checkSameManager(g); + DdNode *result = Cudd_bddOr(mgr, node, g.node); + this->checkReturnValue(result); + return BDD(ddMgr, result); + +} // BDD::Or + + +BDD +BDD::Nand( + const BDD& g) const +{ + DdManager *mgr = this->checkSameManager(g); + DdNode *result = Cudd_bddNand(mgr, node, g.node); + this->checkReturnValue(result); + return BDD(ddMgr, result); + +} // BDD::Nand + + +BDD +BDD::Nor( + const BDD& g) const +{ + DdManager *mgr = this->checkSameManager(g); + DdNode *result = Cudd_bddNor(mgr, node, g.node); + this->checkReturnValue(result); + return BDD(ddMgr, result); + +} // BDD::Nor + + +BDD +BDD::Xor( + const BDD& g) const +{ + DdManager *mgr = this->checkSameManager(g); + DdNode *result = Cudd_bddXor(mgr, node, g.node); + this->checkReturnValue(result); + return BDD(ddMgr, result); + +} // BDD::Xor + + +BDD +BDD::Xnor( + const BDD& g) const +{ + DdManager *mgr = this->checkSameManager(g); + DdNode *result = Cudd_bddXnor(mgr, node, g.node); + this->checkReturnValue(result); + return BDD(ddMgr, result); + +} // BDD::Xnor + + +int +BDD::Leq( + const BDD& g) const +{ + DdManager *mgr = this->checkSameManager(g); + return Cudd_bddLeq(mgr, node, g.node); + +} // BDD::Leq + + +BDD +ADD::BddThreshold( + CUDD_VALUE_TYPE value) const +{ + DdManager *mgr = ddMgr->p->manager; + DdNode *result = Cudd_addBddThreshold(mgr, node, value); + this->checkReturnValue(result); + return BDD(ddMgr, result); + +} // ADD::BddThreshold + + +BDD +ADD::BddStrictThreshold( + CUDD_VALUE_TYPE value) const +{ + DdManager *mgr = ddMgr->p->manager; + DdNode *result = Cudd_addBddStrictThreshold(mgr, node, value); + this->checkReturnValue(result); + return BDD(ddMgr, result); + +} // ADD::BddStrictThreshold + + +BDD +ADD::BddInterval( + CUDD_VALUE_TYPE lower, + CUDD_VALUE_TYPE upper) const +{ + DdManager *mgr = ddMgr->p->manager; + DdNode *result = Cudd_addBddInterval(mgr, node, lower, upper); + this->checkReturnValue(result); + return BDD(ddMgr, result); + +} // ADD::BddInterval + + +BDD +ADD::BddIthBit( + int bit) const +{ + DdManager *mgr = ddMgr->p->manager; + DdNode *result = Cudd_addBddIthBit(mgr, node, bit); + this->checkReturnValue(result); + return BDD(ddMgr, result); + +} // ADD::BddIthBit + + +ADD +BDD::Add() const +{ + DdManager *mgr = ddMgr->p->manager; + DdNode *result = Cudd_BddToAdd(mgr, node); + this->checkReturnValue(result); + return ADD(ddMgr, result); + +} // BDD::Add + + +BDD +ADD::BddPattern() const +{ + DdManager *mgr = ddMgr->p->manager; + DdNode *result = Cudd_addBddPattern(mgr, node); + this->checkReturnValue(result); + return BDD(ddMgr, result); + +} // ADD::BddPattern + + +BDD +BDD::Transfer( + Cudd& destination) const +{ + DdManager *mgr = ddMgr->p->manager; + DdNode *result = Cudd_bddTransfer(mgr, destination.p->manager, node); + this->checkReturnValue(result); + return BDD(&destination, result); + +} // BDD::Transfer + + +void +Cudd::DebugCheck() +{ + int result = Cudd_DebugCheck(p->manager); + this->checkReturnValue(result == 0); + +} // Cudd::DebugCheck + + +void +Cudd::CheckKeys() +{ + int result = Cudd_CheckKeys(p->manager); + this->checkReturnValue(result == 0); + +} // Cudd::CheckKeys + + +BDD +BDD::ClippingAnd( + const BDD& g, + int maxDepth, + int direction) const +{ + DdManager *mgr = this->checkSameManager(g); + DdNode *result = Cudd_bddClippingAnd(mgr, node, g.node, maxDepth, + direction); + this->checkReturnValue(result); + return BDD(ddMgr, result); + +} // BDD::ClippingAnd + + +BDD +BDD::ClippingAndAbstract( + const BDD& g, + const BDD& cube, + int maxDepth, + int direction) const +{ + DdManager *mgr = this->checkSameManager(g); + this->checkSameManager(cube); + DdNode *result = Cudd_bddClippingAndAbstract(mgr, node, g.node, cube.node, + maxDepth, direction); + this->checkReturnValue(result); + return BDD(ddMgr, result); + +} // BDD::ClippingAndAbstract + + +ADD +ADD::Cofactor( + const ADD& g) const +{ + DdManager *mgr = this->checkSameManager(g); + DdNode *result = Cudd_Cofactor(mgr, node, g.node); + this->checkReturnValue(result); + return ADD(ddMgr, result); + +} // ADD::Cofactor + + +BDD +BDD::Cofactor( + const BDD& g) const +{ + DdManager *mgr = this->checkSameManager(g); + DdNode *result = Cudd_Cofactor(mgr, node, g.node); + this->checkReturnValue(result); + return BDD(ddMgr, result); + +} // BDD::Cofactor + + +BDD +BDD::Compose( + const BDD& g, + int v) const +{ + DdManager *mgr = this->checkSameManager(g); + DdNode *result = Cudd_bddCompose(mgr, node, g.node, v); + this->checkReturnValue(result); + return BDD(ddMgr, result); + +} // BDD::Compose + + +ADD +ADD::Compose( + const ADD& g, + int v) const +{ + DdManager *mgr = this->checkSameManager(g); + DdNode *result = Cudd_addCompose(mgr, node, g.node, v); + this->checkReturnValue(result); + return ADD(ddMgr, result); + +} // ADD::Compose + + +ADD +ADD::Permute( + int * permut) const +{ + DdManager *mgr = ddMgr->p->manager; + DdNode *result = Cudd_addPermute(mgr, node, permut); + this->checkReturnValue(result); + return ADD(ddMgr, result); + +} // ADD::Permute + + +ADD +ADD::SwapVariables( + ADDvector x, + ADDvector y) const +{ + int n = x.count(); + DdManager *mgr = ddMgr->p->manager; + DdNode **X = ALLOC(DdNode *,n); + DdNode **Y = ALLOC(DdNode *,n); + for (int i = 0; i < n; i++) { + X[i] = x[i].node; + Y[i] = y[i].node; + } + DdNode *result = Cudd_addSwapVariables(mgr, node, X, Y, n); + FREE(X); + FREE(Y); + this->checkReturnValue(result); + return ADD(ddMgr, result); + +} // ADD::SwapVariables + + +BDD +BDD::Permute( + int * permut) const +{ + DdManager *mgr = ddMgr->p->manager; + DdNode *result = Cudd_bddPermute(mgr, node, permut); + this->checkReturnValue(result); + return BDD(ddMgr, result); + +} // BDD::Permute + + +BDD +BDD::SwapVariables( + BDDvector x, + BDDvector y) const +{ + int n = x.count(); + DdManager *mgr = ddMgr->p->manager; + DdNode **X = ALLOC(DdNode *,n); + DdNode **Y = ALLOC(DdNode *,n); + for (int i = 0; i < n; i++) { + X[i] = x[i].node; + Y[i] = y[i].node; + } + DdNode *result = Cudd_bddSwapVariables(mgr, node, X, Y, n); + FREE(X); + FREE(Y); + this->checkReturnValue(result); + return BDD(ddMgr, result); + +} // BDD::SwapVariables + + +BDD +BDD::AdjPermuteX( + BDDvector x) const +{ + int n = x.count(); + DdManager *mgr = ddMgr->p->manager; + DdNode **X = ALLOC(DdNode *,n); + for (int i = 0; i < n; i++) { + X[i] = x[i].node; + } + DdNode *result = Cudd_bddAdjPermuteX(mgr, node, X, n); + FREE(X); + this->checkReturnValue(result); + return BDD(ddMgr, result); + +} // BDD::AdjPermuteX + + +ADD +ADD::VectorCompose( + ADDvector vector) const +{ + DdManager *mgr = ddMgr->p->manager; + int n = Cudd_ReadSize(mgr); + DdNode **X = ALLOC(DdNode *,n); + for (int i = 0; i < n; i++) { + X[i] = vector[i].node; + } + DdNode *result = Cudd_addVectorCompose(mgr, node, X); + FREE(X); + this->checkReturnValue(result); + return ADD(ddMgr, result); + +} // ADD::VectorCompose + + +ADD +ADD::NonSimCompose( + ADDvector vector) const +{ + DdManager *mgr = ddMgr->p->manager; + int n = Cudd_ReadSize(mgr); + DdNode **X = ALLOC(DdNode *,n); + for (int i = 0; i < n; i++) { + X[i] = vector[i].node; + } + DdNode *result = Cudd_addNonSimCompose(mgr, node, X); + FREE(X); + this->checkReturnValue(result); + return ADD(ddMgr, result); + +} // ADD::NonSimCompose + + +BDD +BDD::VectorCompose( + BDDvector vector) const +{ + DdManager *mgr = ddMgr->p->manager; + int n = Cudd_ReadSize(mgr); + DdNode **X = ALLOC(DdNode *,n); + for (int i = 0; i < n; i++) { + X[i] = vector[i].node; + } + DdNode *result = Cudd_bddVectorCompose(mgr, node, X); + FREE(X); + this->checkReturnValue(result); + return BDD(ddMgr, result); + +} // BDD::VectorCompose + + +void +BDD::ApproxConjDecomp( + BDD* g, + BDD* h) const +{ + DdManager *mgr = ddMgr->p->manager; + DdNode **pieces; + int result = Cudd_bddApproxConjDecomp(mgr, node, &pieces); + this->checkReturnValue(result == 2); + *g = BDD(ddMgr, pieces[0]); + *h = BDD(ddMgr, pieces[1]); + Cudd_RecursiveDeref(mgr,pieces[0]); + Cudd_RecursiveDeref(mgr,pieces[1]); + FREE(pieces); + +} // BDD::ApproxConjDecomp + + +void +BDD::ApproxDisjDecomp( + BDD* g, + BDD* h) const +{ + DdManager *mgr = ddMgr->p->manager; + DdNode **pieces; + int result = Cudd_bddApproxDisjDecomp(mgr, node, &pieces); + this->checkReturnValue(result == 2); + *g = BDD(ddMgr, pieces[0]); + *h = BDD(ddMgr, pieces[1]); + Cudd_RecursiveDeref(mgr,pieces[0]); + Cudd_RecursiveDeref(mgr,pieces[1]); + FREE(pieces); + +} // BDD::ApproxDisjDecomp + + +void +BDD::IterConjDecomp( + BDD* g, + BDD* h) const +{ + DdManager *mgr = ddMgr->p->manager; + DdNode **pieces; + int result = Cudd_bddIterConjDecomp(mgr, node, &pieces); + this->checkReturnValue(result == 2); + *g = BDD(ddMgr, pieces[0]); + *h = BDD(ddMgr, pieces[1]); + Cudd_RecursiveDeref(mgr,pieces[0]); + Cudd_RecursiveDeref(mgr,pieces[1]); + FREE(pieces); + +} // BDD::IterConjDecomp + + +void +BDD::IterDisjDecomp( + BDD* g, + BDD* h) const +{ + DdManager *mgr = ddMgr->p->manager; + DdNode **pieces; + int result = Cudd_bddIterDisjDecomp(mgr, node, &pieces); + this->checkReturnValue(result == 2); + *g = BDD(ddMgr, pieces[0]); + *h = BDD(ddMgr, pieces[1]); + Cudd_RecursiveDeref(mgr,pieces[0]); + Cudd_RecursiveDeref(mgr,pieces[1]); + FREE(pieces); + +} // BDD::IterDisjDecomp + + +void +BDD::GenConjDecomp( + BDD* g, + BDD* h) const +{ + DdManager *mgr = ddMgr->p->manager; + DdNode **pieces; + int result = Cudd_bddGenConjDecomp(mgr, node, &pieces); + this->checkReturnValue(result == 2); + *g = BDD(ddMgr, pieces[0]); + *h = BDD(ddMgr, pieces[1]); + Cudd_RecursiveDeref(mgr,pieces[0]); + Cudd_RecursiveDeref(mgr,pieces[1]); + FREE(pieces); + +} // BDD::GenConjDecomp + + +void +BDD::GenDisjDecomp( + BDD* g, + BDD* h) const +{ + DdManager *mgr = ddMgr->p->manager; + DdNode **pieces; + int result = Cudd_bddGenDisjDecomp(mgr, node, &pieces); + this->checkReturnValue(result == 2); + *g = BDD(ddMgr, pieces[0]); + *h = BDD(ddMgr, pieces[1]); + Cudd_RecursiveDeref(mgr,pieces[0]); + Cudd_RecursiveDeref(mgr,pieces[1]); + FREE(pieces); + +} // BDD::GenDisjDecomp + + +void +BDD::VarConjDecomp( + BDD* g, + BDD* h) const +{ + DdManager *mgr = ddMgr->p->manager; + DdNode **pieces; + int result = Cudd_bddVarConjDecomp(mgr, node, &pieces); + this->checkReturnValue(result == 2); + *g = BDD(ddMgr, pieces[0]); + *h = BDD(ddMgr, pieces[1]); + Cudd_RecursiveDeref(mgr,pieces[0]); + Cudd_RecursiveDeref(mgr,pieces[1]); + FREE(pieces); + +} // BDD::VarConjDecomp + + +void +BDD::VarDisjDecomp( + BDD* g, + BDD* h) const +{ + DdManager *mgr = ddMgr->p->manager; + DdNode **pieces; + int result = Cudd_bddVarDisjDecomp(mgr, node, &pieces); + this->checkReturnValue(result == 2); + *g = BDD(ddMgr, pieces[0]); + *h = BDD(ddMgr, pieces[1]); + Cudd_RecursiveDeref(mgr,pieces[0]); + Cudd_RecursiveDeref(mgr,pieces[1]); + FREE(pieces); + +} // BDD::VarDisjDecomp + + +BDD +ABDD::FindEssential() const +{ + DdManager *mgr = ddMgr->p->manager; + DdNode *result = Cudd_FindEssential(mgr, node); + this->checkReturnValue(result); + return BDD(ddMgr, result); + +} // ABDD::FindEssential + + +int +BDD::IsVarEssential( + int id, + int phase) const +{ + DdManager *mgr = ddMgr->p->manager; + return Cudd_bddIsVarEssential(mgr, node, id, phase); + +} // BDD::IsVarEssential + + +void +ABDD::PrintTwoLiteralClauses( + char **names, + FILE *fp) const +{ + DdManager *mgr = ddMgr->p->manager; + int result = Cudd_PrintTwoLiteralClauses(mgr, node, names, fp); + this->checkReturnValue(result); + +} // ABDD::PrintTwoLiteralClauses + + +void +BDDvector::DumpBlif( + char ** inames, + char ** onames, + char * mname, + FILE * fp, + int mv) const +{ + DdManager *mgr = p->manager->getManager(); + int n = p->size; + DdNode **F = ALLOC(DdNode *,n); + for (int i = 0; i < n; i ++) { + F[i] = p->vect[i].getNode(); + } + int result = Cudd_DumpBlif(mgr, n, F, inames, onames, mname, fp, mv); + FREE(F); + p->manager->checkReturnValue(result); + +} // BDDvector::DumpBlif + + +void +BDDvector::DumpDot( + char ** inames, + char ** onames, + FILE * fp) const +{ + DdManager *mgr = p->manager->getManager(); + int n = p->size; + DdNode **F = ALLOC(DdNode *,n); + for (int i = 0; i < n; i ++) { + F[i] = p->vect[i].getNode(); + } + int result = Cudd_DumpDot(mgr, n, F, inames, onames, fp); + FREE(F); + p->manager->checkReturnValue(result); + +} // BDDvector::DumpDot + + +void +ADDvector::DumpDot( + char ** inames, + char ** onames, + FILE * fp) const +{ + DdManager *mgr = p->manager->getManager(); + int n = p->size; + DdNode **F = ALLOC(DdNode *,n); + for (int i = 0; i < n; i ++) { + F[i] = p->vect[i].getNode(); + } + int result = Cudd_DumpDot(mgr, n, F, inames, onames, fp); + FREE(F); + p->manager->checkReturnValue(result); + +} // ADDvector::DumpDot + + +void +BDDvector::DumpDaVinci( + char ** inames, + char ** onames, + FILE * fp) const +{ + DdManager *mgr = p->manager->getManager(); + int n = p->size; + DdNode **F = ALLOC(DdNode *,n); + for (int i = 0; i < n; i ++) { + F[i] = p->vect[i].getNode(); + } + int result = Cudd_DumpDaVinci(mgr, n, F, inames, onames, fp); + FREE(F); + p->manager->checkReturnValue(result); + +} // BDDvector::DumpDaVinci + + +void +ADDvector::DumpDaVinci( + char ** inames, + char ** onames, + FILE * fp) const +{ + DdManager *mgr = p->manager->getManager(); + int n = p->size; + DdNode **F = ALLOC(DdNode *,n); + for (int i = 0; i < n; i ++) { + F[i] = p->vect[i].getNode(); + } + int result = Cudd_DumpDaVinci(mgr, n, F, inames, onames, fp); + FREE(F); + p->manager->checkReturnValue(result); + +} // ADDvector::DumpDaVinci + + +void +BDDvector::DumpDDcal( + char ** inames, + char ** onames, + FILE * fp) const +{ + DdManager *mgr = p->manager->getManager(); + int n = p->size; + DdNode **F = ALLOC(DdNode *,n); + for (int i = 0; i < n; i ++) { + F[i] = p->vect[i].getNode(); + } + int result = Cudd_DumpDDcal(mgr, n, F, inames, onames, fp); + FREE(F); + p->manager->checkReturnValue(result); + +} // BDDvector::DumpDDcal + + +void +BDDvector::DumpFactoredForm( + char ** inames, + char ** onames, + FILE * fp) const +{ + DdManager *mgr = p->manager->getManager(); + int n = p->size; + DdNode **F = ALLOC(DdNode *,n); + for (int i = 0; i < n; i ++) { + F[i] = p->vect[i].getNode(); + } + int result = Cudd_DumpFactoredForm(mgr, n, F, inames, onames, fp); + FREE(F); + p->manager->checkReturnValue(result); + +} // BDDvector::DumpFactoredForm + + +BDD +BDD::Constrain( + const BDD& c) const +{ + DdManager *mgr = this->checkSameManager(c); + DdNode *result = Cudd_bddConstrain(mgr, node, c.node); + this->checkReturnValue(result); + return BDD(ddMgr, result); + +} // BDD::Constrain + + +BDD +BDD::Restrict( + const BDD& c) const +{ + DdManager *mgr = this->checkSameManager(c); + DdNode *result = Cudd_bddRestrict(mgr, node, c.node); + this->checkReturnValue(result); + return BDD(ddMgr, result); + +} // BDD::Restrict + + +BDD +BDD::NPAnd( + const BDD& g) const +{ + DdManager *mgr = this->checkSameManager(g); + DdNode *result = Cudd_bddNPAnd(mgr, node, g.node); + this->checkReturnValue(result); + return BDD(ddMgr, result); + +} // BDD::NPAnd + + +ADD +ADD::Constrain( + const ADD& c) const +{ + DdManager *mgr = this->checkSameManager(c); + DdNode *result = Cudd_addConstrain(mgr, node, c.node); + this->checkReturnValue(result); + return ADD(ddMgr, result); + +} // ADD::Constrain + + +BDDvector +BDD::ConstrainDecomp() const +{ + DdManager *mgr = ddMgr->p->manager; + DdNode **result = Cudd_bddConstrainDecomp(mgr, node); + this->checkReturnValue((DdNode *)result); + int size = Cudd_ReadSize(mgr); + for (int i = 0; i < size; i++) { + Cudd_Deref(result[i]); + } + BDDvector vect(size, ddMgr, result); + FREE(result); + return vect; + +} // BDD::ConstrainDecomp + + +ADD +ADD::Restrict( + const ADD& c) const +{ + DdManager *mgr = this->checkSameManager(c); + DdNode *result = Cudd_addRestrict(mgr, node, c.node); + this->checkReturnValue(result); + return ADD(ddMgr, result); + +} // ADD::Restrict + + +BDDvector +BDD::CharToVect() const +{ + DdManager *mgr = ddMgr->p->manager; + DdNode **result = Cudd_bddCharToVect(mgr, node); + this->checkReturnValue((DdNode *)result); + int size = Cudd_ReadSize(mgr); + for (int i = 0; i < size; i++) { + Cudd_Deref(result[i]); + } + BDDvector vect(size, ddMgr, result); + FREE(result); + return vect; + +} // BDD::CharToVect + + +BDD +BDD::LICompaction( + const BDD& c) const +{ + DdManager *mgr = this->checkSameManager(c); + DdNode *result = Cudd_bddLICompaction(mgr, node, c.node); + this->checkReturnValue(result); + return BDD(ddMgr, result); + +} // BDD::LICompaction + + +BDD +BDD::Squeeze( + const BDD& u) const +{ + DdManager *mgr = this->checkSameManager(u); + DdNode *result = Cudd_bddSqueeze(mgr, node, u.node); + this->checkReturnValue(result); + return BDD(ddMgr, result); + +} // BDD::Squeeze + + +BDD +BDD::Minimize( + const BDD& c) const +{ + DdManager *mgr = this->checkSameManager(c); + DdNode *result = Cudd_bddMinimize(mgr, node, c.node); + this->checkReturnValue(result); + return BDD(ddMgr, result); + +} // BDD::Minimize + + +BDD +BDD::SubsetCompress( + int nvars, + int threshold) const +{ + DdManager *mgr = ddMgr->p->manager; + DdNode *result = Cudd_SubsetCompress(mgr, node, nvars, threshold); + this->checkReturnValue(result); + return BDD(ddMgr, result); + +} // BDD::SubsetCompress + + +BDD +BDD::SupersetCompress( + int nvars, + int threshold) const +{ + DdManager *mgr = ddMgr->p->manager; + DdNode *result = Cudd_SupersetCompress(mgr, node, nvars, threshold); + this->checkReturnValue(result); + return BDD(ddMgr, result); + +} // BDD::SupersetCompress + + +MtrNode * +Cudd::MakeTreeNode( + unsigned int low, + unsigned int size, + unsigned int type) +{ + return Cudd_MakeTreeNode(p->manager, low, size, type); + +} // Cudd::MakeTreeNode + + +/* This is incorrect, but we'll wait for this one. +void +Cudd::Harwell( + FILE * fp, + DdManager * dd, + ADD* E, + ADD** x, + ADD** y, + ADD** xn, + ADD** yn_, + int * nx, + int * ny, + int * m, + int * n, + int bx, + int sx, + int by, + int sy, + int pr) +{ + DdManager *mgr = p->manager; + int result = Cudd_addHarwell(fp, mgr, E, x, y, xn, yn_, nx, ny, m, n, bx, sx, by, sy, pr); + this->checkReturnValue(result); + +} // Cudd::Harwell +*/ + + +void +Cudd::PrintLinear() +{ + cout.flush(); + int result = Cudd_PrintLinear(p->manager); + this->checkReturnValue(result); + +} // Cudd::PrintLinear + + +int +Cudd::ReadLinear( + int x, + int y) +{ + return Cudd_ReadLinear(p->manager, x, y); + +} // Cudd::ReadLinear + + +BDD +BDD::LiteralSetIntersection( + const BDD& g) const +{ + DdManager *mgr = this->checkSameManager(g); + DdNode *result = Cudd_bddLiteralSetIntersection(mgr, node, g.node); + this->checkReturnValue(result); + return BDD(ddMgr, result); + +} // BDD::LiteralSetIntersection + + +ADD +ADD::MatrixMultiply( + const ADD& B, + ADDvector z) const +{ + int nz = z.count(); + DdManager *mgr = this->checkSameManager(B); + DdNode **Z = ALLOC(DdNode *,nz); + for (int i = 0; i < nz; i++) { + Z[i] = z[i].node; + } + DdNode *result = Cudd_addMatrixMultiply(mgr, node, B.node, Z, nz); + FREE(Z); + this->checkReturnValue(result); + return ADD(ddMgr, result); + +} // ADD::MatrixMultiply + + +ADD +ADD::TimesPlus( + const ADD& B, + ADDvector z) const +{ + int nz = z.count(); + DdManager *mgr = this->checkSameManager(B); + DdNode **Z = ALLOC(DdNode *,nz); + for (int i = 0; i < nz; i++) { + Z[i] = z[i].node; + } + DdNode *result = Cudd_addTimesPlus(mgr, node, B.node, Z, nz); + FREE(Z); + this->checkReturnValue(result); + return ADD(ddMgr, result); + +} // ADD::TimesPlus + + +ADD +ADD::Triangle( + const ADD& g, + ADDvector z) const +{ + int nz = z.count(); + DdManager *mgr = this->checkSameManager(g); + DdNode **Z = ALLOC(DdNode *,nz); + for (int i = 0; i < nz; i++) { + Z[i] = z[i].node; + } + DdNode *result = Cudd_addTriangle(mgr, node, g.node, Z, nz); + FREE(Z); + this->checkReturnValue(result); + return ADD(ddMgr, result); + +} // ADD::Triangle + + +BDD +BDD::PrioritySelect( + BDDvector x, + BDDvector y, + BDDvector z, + const BDD& Pi, + DD_PRFP Pifunc) const +{ + int n = x.count(); + DdManager *mgr = ddMgr->p->manager; + DdNode **X = ALLOC(DdNode *,n); + DdNode **Y = ALLOC(DdNode *,n); + DdNode **Z = ALLOC(DdNode *,n); + for (int i = 0; i < n; i++) { + X[i] = x[i].node; + Y[i] = y[i].node; + Z[i] = z[i].node; + } + DdNode *result = Cudd_PrioritySelect(mgr, node, X, Y, Z, Pi.node, n, Pifunc); + FREE(X); + FREE(Y); + FREE(Z); + this->checkReturnValue(result); + return BDD(ddMgr, result); + +} // BDD::PrioritySelect + + +BDD +Cudd::Xgty( + BDDvector z, + BDDvector x, + BDDvector y) +{ + int N = z.count(); + DdManager *mgr = p->manager; + DdNode **X = ALLOC(DdNode *,N); + DdNode **Y = ALLOC(DdNode *,N); + DdNode **Z = ALLOC(DdNode *,N); + for (int i = 0; i < N; i++) { + X[i] = x[i].getNode(); + Y[i] = y[i].getNode(); + Z[i] = z[i].getNode(); + } + DdNode *result = Cudd_Xgty(mgr, N, Z, X, Y); + FREE(X); + FREE(Y); + FREE(Z); + this->checkReturnValue(result); + return BDD(this, result); + +} // Cudd::Xgty + + +BDD +Cudd::Xeqy( + BDDvector x, + BDDvector y) +{ + int N = x.count(); + DdManager *mgr = p->manager; + DdNode **X = ALLOC(DdNode *,N); + DdNode **Y = ALLOC(DdNode *,N); + for (int i = 0; i < N; i++) { + X[i] = x[i].getNode(); + Y[i] = y[i].getNode(); + } + DdNode *result = Cudd_Xeqy(mgr, N, X, Y); + FREE(X); + FREE(Y); + this->checkReturnValue(result); + return BDD(this, result); + +} // BDD::Xeqy + + +ADD +Cudd::Xeqy( + ADDvector x, + ADDvector y) +{ + int N = x.count(); + DdManager *mgr = p->manager; + DdNode **X = ALLOC(DdNode *,N); + DdNode **Y = ALLOC(DdNode *,N); + for (int i = 0; i < N; i++) { + X[i] = x[i].getNode(); + Y[i] = y[i].getNode(); + } + DdNode *result = Cudd_addXeqy(mgr, N, X, X); + FREE(X); + FREE(Y); + this->checkReturnValue(result); + return ADD(this, result); + +} // ADD::Xeqy + + +BDD +Cudd::Dxygtdxz( + BDDvector x, + BDDvector y, + BDDvector z) +{ + int N = x.count(); + DdManager *mgr = p->manager; + DdNode **X = ALLOC(DdNode *,N); + DdNode **Y = ALLOC(DdNode *,N); + DdNode **Z = ALLOC(DdNode *,N); + for (int i = 0; i < N; i++) { + X[i] = x[i].getNode(); + Y[i] = y[i].getNode(); + Z[i] = z[i].getNode(); + } + DdNode *result = Cudd_Dxygtdxz(mgr, N, X, Y, Z); + FREE(X); + FREE(Y); + FREE(Z); + this->checkReturnValue(result); + return BDD(this, result); + +} // Cudd::Dxygtdxz + + +BDD +Cudd::Dxygtdyz( + BDDvector x, + BDDvector y, + BDDvector z) +{ + int N = x.count(); + DdManager *mgr = p->manager; + DdNode **X = ALLOC(DdNode *,N); + DdNode **Y = ALLOC(DdNode *,N); + DdNode **Z = ALLOC(DdNode *,N); + for (int i = 0; i < N; i++) { + X[i] = x[i].getNode(); + Y[i] = y[i].getNode(); + Z[i] = z[i].getNode(); + } + DdNode *result = Cudd_Dxygtdyz(mgr, N, X, Y, Z); + FREE(X); + FREE(Y); + FREE(Z); + this->checkReturnValue(result); + return BDD(this, result); + +} // Cudd::Dxygtdyz + + +BDD +Cudd::Inequality( + int c, + BDDvector x, + BDDvector y) +{ + int N = x.count(); + DdManager *mgr = p->manager; + DdNode **X = ALLOC(DdNode *,N); + DdNode **Y = ALLOC(DdNode *,N); + for (int i = 0; i < N; i++) { + X[i] = x[i].getNode(); + Y[i] = y[i].getNode(); + } + DdNode *result = Cudd_Inequality(mgr, N, c, X, Y); + FREE(X); + FREE(Y); + this->checkReturnValue(result); + return BDD(this, result); + +} // Cudd::Inequality + + +BDD +Cudd::Disequality( + int c, + BDDvector x, + BDDvector y) +{ + int N = x.count(); + DdManager *mgr = p->manager; + DdNode **X = ALLOC(DdNode *,N); + DdNode **Y = ALLOC(DdNode *,N); + for (int i = 0; i < N; i++) { + X[i] = x[i].getNode(); + Y[i] = y[i].getNode(); + } + DdNode *result = Cudd_Disequality(mgr, N, c, X, Y); + FREE(X); + FREE(Y); + this->checkReturnValue(result); + return BDD(this, result); + +} // Cudd::Disequality + + +BDD +Cudd::Interval( + BDDvector x, + unsigned int lowerB, + unsigned int upperB) +{ + int N = x.count(); + DdManager *mgr = p->manager; + DdNode **X = ALLOC(DdNode *,N); + for (int i = 0; i < N; i++) { + X[i] = x[i].getNode(); + } + DdNode *result = Cudd_bddInterval(mgr, N, X, lowerB, upperB); + FREE(X); + this->checkReturnValue(result); + return BDD(this, result); + +} // Cudd::Interval + + +BDD +BDD::CProjection( + const BDD& Y) const +{ + DdManager *mgr = this->checkSameManager(Y); + DdNode *result = Cudd_CProjection(mgr, node, Y.node); + this->checkReturnValue(result); + return BDD(ddMgr, result); + +} // BDD::CProjection + + +int +BDD::MinHammingDist( + int *minterm, + int upperBound) const +{ + DdManager *mgr = ddMgr->p->manager; + int result = Cudd_MinHammingDist(mgr, node, minterm, upperBound); + return result; + +} // BDD::MinHammingDist + + +ADD +Cudd::Hamming( + ADDvector xVars, + ADDvector yVars) +{ + int nVars = xVars.count(); + DdManager *mgr = p->manager; + DdNode **X = ALLOC(DdNode *,nVars); + DdNode **Y = ALLOC(DdNode *,nVars); + for (int i = 0; i < nVars; i++) { + X[i] = xVars[i].getNode(); + Y[i] = yVars[i].getNode(); + } + DdNode *result = Cudd_addHamming(mgr, X, Y, nVars); + FREE(X); + FREE(Y); + this->checkReturnValue(result); + return ADD(this, result); + +} // Cudd::Hamming + + +/* We'll leave these two out for the time being. +void +Cudd::Read( + FILE * fp, + ADD* E, + ADD** x, + ADD** y, + ADD** xn, + ADD** yn_, + int * nx, + int * ny, + int * m, + int * n, + int bx, + int sx, + int by, + int sy) +{ + DdManager *mgr = p->manager; + int result = Cudd_addRead(fp, mgr, E, x, y, xn, yn_, nx, ny, m, n, bx, sx, by, sy); + this->checkReturnValue(result); + +} // Cudd::Read + + +void +Cudd::Read( + FILE * fp, + BDD* E, + BDD** x, + BDD** y, + int * nx, + int * ny, + int * m, + int * n, + int bx, + int sx, + int by, + int sy) +{ + DdManager *mgr = p->manager; + int result = Cudd_bddRead(fp, mgr, E, x, y, nx, ny, m, n, bx, sx, by, sy); + this->checkReturnValue(result); + +} // Cudd::Read +*/ + + +void +Cudd::ReduceHeap( + Cudd_ReorderingType heuristic, + int minsize) +{ + int result = Cudd_ReduceHeap(p->manager, heuristic, minsize); + this->checkReturnValue(result); + +} // Cudd::ReduceHeap + + +void +Cudd::ShuffleHeap( + int * permutation) +{ + int result = Cudd_ShuffleHeap(p->manager, permutation); + this->checkReturnValue(result); + +} // Cudd::ShuffleHeap + + +ADD +ADD::Eval( + int * inputs) const +{ + DdManager *mgr = ddMgr->p->manager; + DdNode *result = Cudd_Eval(mgr, node, inputs); + this->checkReturnValue(result); + return ADD(ddMgr, result); + +} // ADD::Eval + + +BDD +BDD::Eval( + int * inputs) const +{ + DdManager *mgr = ddMgr->p->manager; + DdNode *result = Cudd_Eval(mgr, node, inputs); + this->checkReturnValue(result); + return BDD(ddMgr, result); + +} // BDD::Eval + + +BDD +ABDD::ShortestPath( + int * weight, + int * support, + int * length) const +{ + DdManager *mgr = ddMgr->p->manager; + DdNode *result = Cudd_ShortestPath(mgr, node, weight, support, length); + this->checkReturnValue(result); + return BDD(ddMgr, result); + +} // ABDD::ShortestPath + + +BDD +ABDD::LargestCube( + int * length) const +{ + DdManager *mgr = ddMgr->p->manager; + DdNode *result = Cudd_LargestCube(mgr, node, length); + this->checkReturnValue(result); + return BDD(ddMgr, result); + +} // ABDD::LargestCube + + +int +ABDD::ShortestLength( + int * weight) const +{ + DdManager *mgr = ddMgr->p->manager; + int result = Cudd_ShortestLength(mgr, node, weight); + this->checkReturnValue(result != CUDD_OUT_OF_MEM); + return result; + +} // ABDD::ShortestLength + + +BDD +BDD::Decreasing( + int i) const +{ + DdManager *mgr = ddMgr->p->manager; + DdNode *result = Cudd_Decreasing(mgr, node, i); + this->checkReturnValue(result); + return BDD(ddMgr, result); + +} // BDD::Decreasing + + +BDD +BDD::Increasing( + int i) const +{ + DdManager *mgr = ddMgr->p->manager; + DdNode *result = Cudd_Increasing(mgr, node, i); + this->checkReturnValue(result); + return BDD(ddMgr, result); + +} // BDD::Increasing + + +int +ABDD::EquivDC( + const ABDD& G, + const ABDD& D) const +{ + DdManager *mgr = this->checkSameManager(G); + this->checkSameManager(D); + return Cudd_EquivDC(mgr, node, G.node, D.node); + +} // ABDD::EquivDC + + +int +ADD::EqualSupNorm( + const ADD& g, + CUDD_VALUE_TYPE tolerance, + int pr) const +{ + DdManager *mgr = this->checkSameManager(g); + return Cudd_EqualSupNorm(mgr, node, g.node, tolerance, pr); + +} // ADD::EqualSupNorm + + +double * +ABDD::CofMinterm() const +{ + DdManager *mgr = ddMgr->p->manager; + double *result = Cudd_CofMinterm(mgr, node); + this->checkReturnValue((DdNode *)result); + return result; + +} // ABDD::CofMinterm + + +BDD +BDD::SolveEqn( + const BDD& Y, + BDD* G, + int ** yIndex, + int n) const +{ + DdManager *mgr = this->checkSameManager(Y); + DdNode **g = ALLOC(DdNode *,n); + DdNode *result = Cudd_SolveEqn(mgr, node, Y.node, g, yIndex, n); + this->checkReturnValue(result); + for (int i = 0; i < n; i++) { + G[i] = BDD(ddMgr, g[i]); + Cudd_RecursiveDeref(mgr,g[i]); + } + FREE(g); + return BDD(ddMgr, result); + +} // BDD::SolveEqn + + +BDD +BDD::VerifySol( + BDD* G, + int * yIndex, + int n) const +{ + DdManager *mgr = ddMgr->p->manager; + DdNode **g = ALLOC(DdNode *,n); + for (int i = 0; i < n; i++) { + g[i] = G[i].node; + } + DdNode *result = Cudd_VerifySol(mgr, node, g, yIndex, n); + FREE(g); + this->checkReturnValue(result); + return BDD(ddMgr, result); + +} // BDD::VerifySol + + +BDD +BDD::SplitSet( + BDDvector xVars, + double m) const +{ + int n = xVars.count(); + DdManager *mgr = ddMgr->p->manager; + DdNode **X = ALLOC(DdNode *,n); + for (int i = 0; i < n; i++) { + X[i] = xVars[i].node; + } + DdNode *result = Cudd_SplitSet(mgr, node, X, n, m); + FREE(X); + this->checkReturnValue(result); + return BDD(ddMgr, result); + +} // BDD::SplitSet + + +BDD +BDD::SubsetHeavyBranch( + int numVars, + int threshold) const +{ + DdManager *mgr = ddMgr->p->manager; + DdNode *result = Cudd_SubsetHeavyBranch(mgr, node, numVars, threshold); + this->checkReturnValue(result); + return BDD(ddMgr, result); + +} // BDD::SubsetHeavyBranch + + +BDD +BDD::SupersetHeavyBranch( + int numVars, + int threshold) const +{ + DdManager *mgr = ddMgr->p->manager; + DdNode *result = Cudd_SupersetHeavyBranch(mgr, node, numVars, threshold); + this->checkReturnValue(result); + return BDD(ddMgr, result); + +} // BDD::SupersetHeavyBranch + + +BDD +BDD::SubsetShortPaths( + int numVars, + int threshold, + int hardlimit) const +{ + DdManager *mgr = ddMgr->p->manager; + DdNode *result = Cudd_SubsetShortPaths(mgr, node, numVars, threshold, hardlimit); + this->checkReturnValue(result); + return BDD(ddMgr, result); + +} // BDD::SubsetShortPaths + + +BDD +BDD::SupersetShortPaths( + int numVars, + int threshold, + int hardlimit) const +{ + DdManager *mgr = ddMgr->p->manager; + DdNode *result = Cudd_SupersetShortPaths(mgr, node, numVars, threshold, hardlimit); + this->checkReturnValue(result); + return BDD(ddMgr, result); + +} // BDD::SupersetShortPaths + + +void +Cudd::SymmProfile( + int lower, + int upper) const +{ + Cudd_SymmProfile(p->manager, lower, upper); + +} // Cudd::SymmProfile + + +unsigned int +Cudd::Prime( + unsigned int pr) const +{ + return Cudd_Prime(pr); + +} // Cudd::Prime + + +void +ABDD::PrintMinterm() const +{ + cout.flush(); + DdManager *mgr = ddMgr->p->manager; + int result = Cudd_PrintMinterm(mgr, node); + this->checkReturnValue(result); + +} // ABDD::PrintMinterm + + +void +BDD::PrintCover() const +{ + cout.flush(); + DdManager *mgr = ddMgr->p->manager; + int result = Cudd_bddPrintCover(mgr, node, node); + this->checkReturnValue(result); + +} // BDD::PrintCover + + +void +BDD::PrintCover( + const BDD& u) const +{ + this->checkSameManager(u); + cout.flush(); + DdManager *mgr = ddMgr->p->manager; + int result = Cudd_bddPrintCover(mgr, node, u.node); + this->checkReturnValue(result); + +} // BDD::PrintCover + + +int +BDD::EstimateCofactor( + int i, + int phase) const +{ + DdManager *mgr = ddMgr->p->manager; + int result = Cudd_EstimateCofactor(mgr, node, i, phase); + this->checkReturnValue(result != CUDD_OUT_OF_MEM); + return result; + +} // BDD::EstimateCofactor + + +int +BDD::EstimateCofactorSimple( + int i) const +{ + int result = Cudd_EstimateCofactorSimple(node, i); + return result; + +} // BDD::EstimateCofactorSimple + + +int +Cudd::SharingSize( + DD* nodes, + int n) const +{ + DdNode **nodeArray = ALLOC(DdNode *,n); + for (int i = 0; i < n; i++) { + nodeArray[i] = nodes[i].getNode(); + } + int result = Cudd_SharingSize(nodeArray, n); + FREE(nodeArray); + this->checkReturnValue(result > 0); + return result; + +} // Cudd::SharingSize + + +double +ABDD::CountMinterm( + int nvars) const +{ + DdManager *mgr = ddMgr->p->manager; + double result = Cudd_CountMinterm(mgr, node, nvars); + this->checkReturnValue(result != (double) CUDD_OUT_OF_MEM); + return result; + +} // ABDD::CountMinterm + + +double +ABDD::CountPath() const +{ + double result = Cudd_CountPath(node); + this->checkReturnValue(result != (double) CUDD_OUT_OF_MEM); + return result; + +} // ABDD::CountPath + + +BDD +ABDD::Support() const +{ + DdManager *mgr = ddMgr->p->manager; + DdNode *result = Cudd_Support(mgr, node); + this->checkReturnValue(result); + return BDD(ddMgr, result); + +} // ABDD::Support + + +int +ABDD::SupportSize() const +{ + DdManager *mgr = ddMgr->p->manager; + int result = Cudd_SupportSize(mgr, node); + this->checkReturnValue(result != CUDD_OUT_OF_MEM); + return result; + +} // ABDD::SupportSize + + +BDD +BDDvector::VectorSupport() const +{ + int n = p->size; + DdManager *mgr = p->manager->getManager(); + DdNode **F = ALLOC(DdNode *,n); + for (int i = 0; i < n; i++) { + F[i] = p->vect[i].getNode(); + } + DdNode *result = Cudd_VectorSupport(mgr, F, n); + FREE(F); + p->manager->checkReturnValue(result); + return BDD(p->manager, result); + +} // BDDvector::VectorSupport + + +int +BDDvector::nodeCount() const +{ + int n = p->size; + DdNode **nodeArray = ALLOC(DdNode *,n); + for (int i = 0; i < n; i++) { + nodeArray[i] = p->vect[i].getNode(); + } + int result = Cudd_SharingSize(nodeArray, n); + FREE(nodeArray); + p->manager->checkReturnValue(result > 0); + return result; + +} // BDDvector::nodeCount + + +BDD +ADDvector::VectorSupport() const +{ + int n = p->size; + DdManager *mgr = p->manager->getManager(); + DdNode **F = ALLOC(DdNode *,n); + for (int i = 0; i < n; i++) { + F[i] = p->vect[i].getNode(); + } + DdNode *result = Cudd_VectorSupport(mgr, F, n); + FREE(F); + p->manager->checkReturnValue(result); + return BDD(p->manager, result); + +} // ADDvector::VectorSupport + + +int +BDDvector::VectorSupportSize() const +{ + int n = p->size; + DdManager *mgr = p->manager->getManager(); + DdNode **F = ALLOC(DdNode *,n); + for (int i = 0; i < n; i++) { + F[i] = p->vect[i].getNode(); + } + int result = Cudd_VectorSupportSize(mgr, F, n); + FREE(F); + p->manager->checkReturnValue(result != CUDD_OUT_OF_MEM); + return result; + +} // BDDvector::VectorSupportSize + + +int +ADDvector::VectorSupportSize() const +{ + int n = p->size; + DdManager *mgr = p->manager->getManager(); + DdNode **F = ALLOC(DdNode *,n); + for (int i = 0; i < n; i++) { + F[i] = p->vect[i].getNode(); + } + int result = Cudd_VectorSupportSize(mgr, F, n); + FREE(F); + p->manager->checkReturnValue(result != CUDD_OUT_OF_MEM); + return result; + +} // ADDvector::VectorSupportSize + + +void +ABDD::ClassifySupport( + const ABDD& g, + BDD* common, + BDD* onlyF, + BDD* onlyG) const +{ + DdManager *mgr = this->checkSameManager(g); + DdNode *C, *F, *G; + int result = Cudd_ClassifySupport(mgr, node, g.node, &C, &F, &G); + this->checkReturnValue(result); + *common = BDD(ddMgr, C); + *onlyF = BDD(ddMgr, F); + *onlyG = BDD(ddMgr, G); + +} // ABDD::ClassifySupport + + +int +ABDD::CountLeaves() const +{ + return Cudd_CountLeaves(node); + +} // ABDD::CountLeaves + + +void +BDD::PickOneCube( + char * string) const +{ + DdManager *mgr = ddMgr->p->manager; + int result = Cudd_bddPickOneCube(mgr, node, string); + this->checkReturnValue(result); + +} // BDD::PickOneCube + + +BDD +BDD::PickOneMinterm( + BDDvector vars) const +{ + int n = vars.count(); + DdManager *mgr = ddMgr->p->manager; + DdNode **V = ALLOC(DdNode *,n); + for (int i = 0; i < n; i++) { + V[i] = vars[i].node; + } + DdNode *result = Cudd_bddPickOneMinterm(mgr, node, V, n); + FREE(V); + this->checkReturnValue(result); + return BDD(ddMgr, result); + +} // BDD::PickOneMinterm + + +DdGen * +ABDD::FirstCube( + int ** cube, + CUDD_VALUE_TYPE * value) const +{ + DdManager *mgr = ddMgr->p->manager; + DdGen *result = Cudd_FirstCube(mgr, node, cube, value); + this->checkReturnValue((DdNode *)result); + return result; + +} // ABDD::FirstCube + + +int +NextCube( + DdGen * gen, + int ** cube, + CUDD_VALUE_TYPE * value) +{ + return Cudd_NextCube(gen, cube, value); + +} // NextCube + + +BDD +Cudd::bddComputeCube( + BDD * vars, + int * phase, + int n) +{ + DdManager *mgr = p->manager; + DdNode **V = ALLOC(DdNode *,n); + for (int i = 0; i < n; i++) { + V[i] = vars[i].getNode(); + } + DdNode *result = Cudd_bddComputeCube(mgr, V, phase, n); + FREE(V); + this->checkReturnValue(result); + return BDD(this, result); + +} // Cudd::bddComputeCube + + +ADD +Cudd::addComputeCube( + ADD * vars, + int * phase, + int n) +{ + DdManager *mgr = p->manager; + DdNode **V = ALLOC(DdNode *,n); + for (int i = 0; i < n; i++) { + V[i] = vars[i].getNode(); + } + DdNode *result = Cudd_addComputeCube(mgr, V, phase, n); + FREE(V); + this->checkReturnValue(result); + return ADD(this, result); + +} // Cudd::addComputeCube + + +DdGen * +BDD::FirstNode( + BDD* fnode) const +{ + DdManager *mgr = ddMgr->p->manager; + DdNode *Fn; + DdGen *result = Cudd_FirstNode(mgr, node, &Fn); + this->checkReturnValue((DdNode *)result); + *fnode = BDD(ddMgr, Fn); + return result; + +} // DD::FirstNode + + +int +Cudd::NextNode( + DdGen * gen, + BDD * nnode) +{ + DdNode *nn; + int result = Cudd_NextNode(gen, &nn); + *nnode = BDD(this, nn); + return result; + +} // Cudd::NextNode + + +int +GenFree( + DdGen * gen) +{ + return Cudd_GenFree(gen); + +} // GenFree + + +int +IsGenEmpty( + DdGen * gen) +{ + return Cudd_IsGenEmpty(gen); + +} // IsGenEmpty + + +BDD +Cudd::IndicesToCube( + int * array, + int n) +{ + DdNode *result = Cudd_IndicesToCube(p->manager, array, n); + this->checkReturnValue(result); + return BDD(this, result); + +} // Cudd::IndicesToCube + + +void +Cudd::PrintVersion( + FILE * fp) const +{ + cout.flush(); + Cudd_PrintVersion(fp); + +} // Cudd::PrintVersion + + +double +Cudd::AverageDistance() const +{ + return Cudd_AverageDistance(p->manager); + +} // Cudd::AverageDistance + + +long +Cudd::Random() +{ + return Cudd_Random(); + +} // Cudd::Random + + +void +Cudd::Srandom( + long seed) +{ + Cudd_Srandom(seed); + +} // Cudd::Srandom + + +double +ABDD::Density( + int nvars) const +{ + DdManager *mgr = ddMgr->p->manager; + double result = Cudd_Density(mgr, node, nvars); + this->checkReturnValue(result != (double) CUDD_OUT_OF_MEM); + return result; + +} // ABDD::Density + + +int +ZDD::Count() const +{ + DdManager *mgr = ddMgr->p->manager; + int result = Cudd_zddCount(mgr, node); + this->checkReturnValue(result != CUDD_OUT_OF_MEM); + return result; + +} // ZDD::Count + + +double +ZDD::CountDouble() const +{ + DdManager *mgr = ddMgr->p->manager; + double result = Cudd_zddCountDouble(mgr, node); + this->checkReturnValue(result != (double) CUDD_OUT_OF_MEM); + return result; + +} // ZDD::CountDouble + + +ZDD +ZDD::Product( + const ZDD& g) const +{ + DdManager *mgr = this->checkSameManager(g); + DdNode *result = Cudd_zddProduct(mgr, node, g.node); + this->checkReturnValue(result); + return ZDD(ddMgr, result); + +} // ZDD::Product + + +ZDD +ZDD::UnateProduct( + const ZDD& g) const +{ + DdManager *mgr = this->checkSameManager(g); + DdNode *result = Cudd_zddUnateProduct(mgr, node, g.node); + this->checkReturnValue(result); + return ZDD(ddMgr, result); + +} // ZDD::UnateProduct + + +ZDD +ZDD::WeakDiv( + const ZDD& g) const +{ + DdManager *mgr = this->checkSameManager(g); + DdNode *result = Cudd_zddWeakDiv(mgr, node, g.node); + this->checkReturnValue(result); + return ZDD(ddMgr, result); + +} // ZDD::WeakDiv + + +ZDD +ZDD::Divide( + const ZDD& g) const +{ + DdManager *mgr = this->checkSameManager(g); + DdNode *result = Cudd_zddDivide(mgr, node, g.node); + this->checkReturnValue(result); + return ZDD(ddMgr, result); + +} // ZDD::Divide + + +ZDD +ZDD::WeakDivF( + const ZDD& g) const +{ + DdManager *mgr = this->checkSameManager(g); + DdNode *result = Cudd_zddWeakDivF(mgr, node, g.node); + this->checkReturnValue(result); + return ZDD(ddMgr, result); + +} // ZDD::WeakDivF + + +ZDD +ZDD::DivideF( + const ZDD& g) const +{ + DdManager *mgr = this->checkSameManager(g); + DdNode *result = Cudd_zddDivideF(mgr, node, g.node); + this->checkReturnValue(result); + return ZDD(ddMgr, result); + +} // ZDD::DivideF + + +MtrNode * +Cudd::MakeZddTreeNode( + unsigned int low, + unsigned int size, + unsigned int type) +{ + return Cudd_MakeZddTreeNode(p->manager, low, size, type); + +} // Cudd::MakeZddTreeNode + + +BDD +BDD::zddIsop( + const BDD& U, + ZDD* zdd_I) const +{ + DdManager *mgr = this->checkSameManager(U); + DdNode *Z; + DdNode *result = Cudd_zddIsop(mgr, node, U.node, &Z); + this->checkReturnValue(result); + *zdd_I = ZDD(ddMgr, Z); + return BDD(ddMgr, result); + +} // BDD::Isop + + +BDD +BDD::Isop( + const BDD& U) const +{ + DdManager *mgr = this->checkSameManager(U); + DdNode *result = Cudd_bddIsop(mgr, node, U.node); + this->checkReturnValue(result); + return BDD(ddMgr, result); + +} // BDD::Isop + + +double +ZDD::CountMinterm( + int path) const +{ + DdManager *mgr = ddMgr->p->manager; + double result = Cudd_zddCountMinterm(mgr, node, path); + this->checkReturnValue(result != (double) CUDD_OUT_OF_MEM); + return result; + +} // ZDD::CountMinterm + + +void +Cudd::zddPrintSubtable() const +{ + cout.flush(); + Cudd_zddPrintSubtable(p->manager); + +} // Cudd::zddPrintSubtable + + +ZDD +BDD::PortToZdd() const +{ + DdManager *mgr = ddMgr->p->manager; + DdNode *result = Cudd_zddPortFromBdd(mgr, node); + this->checkReturnValue(result); + return ZDD(ddMgr, result); + +} // BDD::PortToZdd + + +BDD +ZDD::PortToBdd() const +{ + DdManager *mgr = ddMgr->p->manager; + DdNode *result = Cudd_zddPortToBdd(mgr, node); + this->checkReturnValue(result); + return BDD(ddMgr, result); + +} // ZDD::PortToBdd + + +void +Cudd::zddReduceHeap( + Cudd_ReorderingType heuristic, + int minsize) +{ + int result = Cudd_zddReduceHeap(p->manager, heuristic, minsize); + this->checkReturnValue(result); + +} // Cudd::zddReduceHeap + + +void +Cudd::zddShuffleHeap( + int * permutation) +{ + int result = Cudd_zddShuffleHeap(p->manager, permutation); + this->checkReturnValue(result); + +} // Cudd::zddShuffleHeap + + +ZDD +ZDD::Ite( + const ZDD& g, + const ZDD& h) const +{ + DdManager *mgr = this->checkSameManager(g); + this->checkSameManager(h); + DdNode *result = Cudd_zddIte(mgr, node, g.node, h.node); + this->checkReturnValue(result); + return ZDD(ddMgr, result); + +} // ZDD::Ite + + +ZDD +ZDD::Union( + const ZDD& Q) const +{ + DdManager *mgr = this->checkSameManager(Q); + DdNode *result = Cudd_zddUnion(mgr, node, Q.node); + this->checkReturnValue(result); + return ZDD(ddMgr, result); + +} // ZDD::Union + + +ZDD +ZDD::Intersect( + const ZDD& Q) const +{ + DdManager *mgr = this->checkSameManager(Q); + DdNode *result = Cudd_zddIntersect(mgr, node, Q.node); + this->checkReturnValue(result); + return ZDD(ddMgr, result); + +} // ZDD::Intersect + + +ZDD +ZDD::Diff( + const ZDD& Q) const +{ + DdManager *mgr = this->checkSameManager(Q); + DdNode *result = Cudd_zddDiff(mgr, node, Q.node); + this->checkReturnValue(result); + return ZDD(ddMgr, result); + +} // ZDD::Diff + + +ZDD +ZDD::DiffConst( + const ZDD& Q) const +{ + DdManager *mgr = this->checkSameManager(Q); + DdNode *result = Cudd_zddDiffConst(mgr, node, Q.node); + this->checkReturnValue(result); + return ZDD(ddMgr, result); + +} // ZDD::DiffConst + + +ZDD +ZDD::Subset1( + int var) const +{ + DdManager *mgr = ddMgr->p->manager; + DdNode *result = Cudd_zddSubset1(mgr, node, var); + this->checkReturnValue(result); + return ZDD(ddMgr, result); + +} // ZDD::Subset1 + + +ZDD +ZDD::Subset0( + int var) const +{ + DdManager *mgr = ddMgr->p->manager; + DdNode *result = Cudd_zddSubset0(mgr, node, var); + this->checkReturnValue(result); + return ZDD(ddMgr, result); + +} // ZDD::Subset0 + + +ZDD +ZDD::Change( + int var) const +{ + DdManager *mgr = ddMgr->p->manager; + DdNode *result = Cudd_zddChange(mgr, node, var); + this->checkReturnValue(result); + return ZDD(ddMgr, result); + +} // ZDD::Change + + +void +Cudd::zddSymmProfile( + int lower, + int upper) const +{ + Cudd_zddSymmProfile(p->manager, lower, upper); + +} // Cudd::zddSymmProfile + + +void +ZDD::PrintMinterm() const +{ + cout.flush(); + DdManager *mgr = ddMgr->p->manager; + int result = Cudd_zddPrintMinterm(mgr, node); + this->checkReturnValue(result); + +} // ZDD::PrintMinterm + + +void +ZDD::PrintCover() const +{ + cout.flush(); + DdManager *mgr = ddMgr->p->manager; + int result = Cudd_zddPrintCover(mgr, node); + this->checkReturnValue(result); + +} // ZDD::PrintCover + + +void +ZDDvector::DumpDot( + char ** inames, + char ** onames, + FILE * fp) const +{ + DdManager *mgr = p->manager->getManager(); + int n = p->size; + DdNode **F = ALLOC(DdNode *,n); + for (int i = 0; i < n; i ++) { + F[i] = p->vect[i].getNode(); + } + int result = Cudd_zddDumpDot(mgr, n, F, inames, onames, fp); + FREE(F); + p->manager->checkReturnValue(result); + +} // ZDDvector::DumpDot diff --git a/distr/obj/cuddObj.hh b/distr/obj/cuddObj.hh new file mode 100644 index 0000000..92ac761 --- /dev/null +++ b/distr/obj/cuddObj.hh @@ -0,0 +1,782 @@ +/**CHeaderFile*************************************************************** + + FileName [cuddObj.hh] + + PackageName [cudd] + + Synopsis [Class definitions for C++ object-oriented encapsulation of + CUDD.] + + Description [Class definitions for C++ object-oriented encapsulation of + CUDD.] + + 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: cuddObj.hh,v 1.11 2009/02/21 19:41:38 fabio Exp fabio $] + +******************************************************************************/ + +#ifndef _CPPCUDD +#define _CPPCUDD + +/*---------------------------------------------------------------------------*/ +/* Nested includes */ +/*---------------------------------------------------------------------------*/ + +#include +#include +#include "util.h" +#include "cudd.h" + +using std::cout; +using std::cerr; +using std::endl; +using std::hex; +using std::string; + +/*---------------------------------------------------------------------------*/ +/* Type definitions */ +/*---------------------------------------------------------------------------*/ + +class ADD; +class BDD; +class ZDD; +class Cudd; +class BDDvector; +class ADDvector; +class ZDDvector; + +typedef void (*PFC)(string); // error function type + +/*---------------------------------------------------------------------------*/ +/* Class definitions */ +/*---------------------------------------------------------------------------*/ + + +/**Class*********************************************************************** + + Synopsis [Base class for all decision diagrams in CUDD.] + + Description [] + + SeeAlso [Cudd ABDD ADD BDD ZDD] + +******************************************************************************/ +class DD { + friend class ABDD; + friend class ADD; + friend class BDD; + friend class ZDD; + Cudd *ddMgr; + DdNode *node; + inline DdManager * checkSameManager(const DD &other) const; + inline void checkReturnValue(const DdNode *result) const; + inline void checkReturnValue(const int result, const int expected = 1) + const; +public: + DD(Cudd *ddManager, DdNode *ddNode); + DD(); + DD(const DD &from); + virtual ~DD(); + Cudd *manager() const; + inline DdNode * getNode() const; + int nodeCount() const; + unsigned int NodeReadIndex() const; + +}; // DD + + +/**Class*********************************************************************** + + Synopsis [Class for ADDs and BDDs.] + + Description [] + + SeeAlso [Cudd ADD BDD] + +******************************************************************************/ +class ABDD : public DD { + friend class BDD; + friend class ADD; + friend class Cudd; +public: + ABDD(Cudd *bddManager, DdNode *bddNode); + ABDD(); + ABDD(const ABDD &from); + virtual ~ABDD(); + int operator==(const ABDD &other) const; + int operator!=(const ABDD &other) const; + void print(int nvars, int verbosity = 1) const; + DdApaNumber ApaCountMinterm(int nvars, int * digits) const; + void ApaPrintMinterm(int nvars, FILE * fp = stdout) const; + void EpdPrintMinterm(int nvars, FILE * fp = stdout) const; + BDD FindEssential() const; + void PrintTwoLiteralClauses(char ** names, FILE * fp = stdout) const; + BDD ShortestPath(int * weight, int * support, int * length) const; + BDD LargestCube(int * length) const; + int ShortestLength(int * weight) const; + int EquivDC(const ABDD& G, const ABDD& D) const; + double * CofMinterm() const; + void PrintMinterm() const; + double CountMinterm(int nvars) const; + double CountPath() const; + BDD Support() const; + int SupportSize() const; + void ClassifySupport(const ABDD& g, BDD* common, BDD* onlyF, BDD* onlyG) + const; + int CountLeaves() const; + DdGen * FirstCube(int ** cube, CUDD_VALUE_TYPE * value) const; + double Density(int nvars) const; + +}; // ABDD + + +/**Class*********************************************************************** + + Synopsis [Class for BDDs.] + + Description [] + + SeeAlso [Cudd] + +******************************************************************************/ +class BDD : public ABDD { + friend class Cudd; +public: + BDD(Cudd *bddManager, DdNode *bddNode); + BDD(); + BDD(const BDD &from); + int operator==(const BDD& other) const; + int operator!=(const BDD& other) const; + BDD operator=(const BDD& right); + int operator<=(const BDD& other) const; + int operator>=(const BDD& other) const; + int operator<(const BDD& other) const; + int operator>(const BDD& other) const; + BDD operator!() const; + BDD operator~() const; + BDD operator*(const BDD& other) const; + BDD operator*=(const BDD& other); + BDD operator&(const BDD& other) const; + BDD operator&=(const BDD& other); + BDD operator+(const BDD& other) const; + BDD operator+=(const BDD& other); + BDD operator|(const BDD& other) const; + BDD operator|=(const BDD& other); + BDD operator^(const BDD& other) const; + BDD operator^=(const BDD& other); + BDD operator-(const BDD& other) const; + BDD operator-=(const BDD& other); + BDD AndAbstract(const BDD& g, const BDD& cube) const; + BDD AndAbstractLimit(const BDD& g, const BDD& cube, unsigned int limit) + const; + BDD UnderApprox( + int numVars, + int threshold = 0, + int safe = 0, + double quality = 1.0) const; + BDD OverApprox( + int numVars, + int threshold = 0, + int safe = 0, + double quality = 1.0) const; + BDD RemapUnderApprox(int numVars, int threshold = 0, double quality = 1.0) + const; + BDD RemapOverApprox(int numVars, int threshold = 0, double quality = 1.0) + const; + BDD ExistAbstract(const BDD& cube) const; + BDD XorExistAbstract(const BDD& g, const BDD& cube) const; + BDD UnivAbstract(const BDD& cube) const; + BDD BooleanDiff(int x) const; + int VarIsDependent(const BDD& var) const; + double Correlation(const BDD& g) const; + double CorrelationWeights(const BDD& g, double * prob) const; + BDD Ite(const BDD& g, const BDD& h) const; + BDD IteConstant(const BDD& g, const BDD& h) const; + BDD Intersect(const BDD& g) const; + BDD And(const BDD& g) const; + BDD AndLimit(const BDD& g, unsigned int limit) const; + BDD Or(const BDD& g) const; + BDD Nand(const BDD& g) const; + BDD Nor(const BDD& g) const; + BDD Xor(const BDD& g) const; + BDD Xnor(const BDD& g) const; + int Leq(const BDD& g) const; + ADD Add() const; + BDD Transfer(Cudd& destination) const; + BDD ClippingAnd(const BDD& g, int maxDepth, int direction) const; + BDD ClippingAndAbstract(const BDD& g, const BDD& cube, int maxDepth, + int direction) const; + BDD Cofactor(const BDD& g) const; + BDD Compose(const BDD& g, int v) const; + BDD Permute(int * permut) const; + BDD SwapVariables(BDDvector x, BDDvector y) const; + BDD AdjPermuteX(BDDvector x) const; + BDD VectorCompose(BDDvector vector) const; + void ApproxConjDecomp(BDD* g, BDD* h) const; + void ApproxDisjDecomp(BDD* g, BDD* h) const; + void IterConjDecomp(BDD* g, BDD* h) const; + void IterDisjDecomp(BDD* g, BDD* h) const; + void GenConjDecomp(BDD* g, BDD* h) const; + void GenDisjDecomp(BDD* g, BDD* h) const; + void VarConjDecomp(BDD* g, BDD* h) const; + void VarDisjDecomp(BDD* g, BDD* h) const; + int IsVarEssential(int id, int phase) const; + BDD Constrain(const BDD& c) const; + BDD Restrict(const BDD& c) const; + BDD NPAnd(const BDD& g) const; + BDDvector ConstrainDecomp() const; + BDDvector CharToVect() const; + BDD LICompaction(const BDD& c) const; + BDD Squeeze(const BDD& u) const; + BDD Minimize(const BDD& c) const; + BDD SubsetCompress(int nvars, int threshold) const; + BDD SupersetCompress(int nvars, int threshold) const; + BDD LiteralSetIntersection(const BDD& g) const; + BDD PrioritySelect(BDDvector x, BDDvector y, BDDvector z, const BDD& Pi, + DD_PRFP Pifunc) const; + BDD CProjection(const BDD& Y) const; + int MinHammingDist(int *minterm, int upperBound) const; + BDD Eval(int * inputs) const; + BDD Decreasing(int i) const; + BDD Increasing(int i) const; + BDD SolveEqn(const BDD& Y, BDD* G, int ** yIndex, int n) const; + BDD VerifySol(BDD* G, int * yIndex, int n) const; + BDD SplitSet(BDDvector xVars, double m) const; + BDD SubsetHeavyBranch(int numVars, int threshold) const; + BDD SupersetHeavyBranch(int numVars, int threshold) const; + BDD SubsetShortPaths(int numVars, int threshold, int hardlimit) const; + BDD SupersetShortPaths(int numVars, int threshold, int hardlimit) const; + void PrintCover() const; + void PrintCover(const BDD& u) const; + int EstimateCofactor(int i, int phase) const; + int EstimateCofactorSimple(int i) const; + void PickOneCube(char * string) const; + BDD PickOneMinterm(BDDvector vars) const; + DdGen * FirstNode(BDD* fnode) const; + BDD zddIsop(const BDD& U, ZDD* zdd_I) const; + BDD Isop(const BDD& U) const; + ZDD PortToZdd() const; + +}; // BDD + + +/**Class*********************************************************************** + + Synopsis [Class for ADDs.] + + Description [] + + SeeAlso [Cudd] + +******************************************************************************/ +class ADD : public ABDD { + friend class Cudd; +public: + ADD(Cudd *bddManager, DdNode *bddNode); + ADD(); + ADD(const ADD &from); + int operator==(const ADD& other) const; + int operator!=(const ADD& other) const; + ADD operator=(const ADD& right); + // Relational operators + int operator<=(const ADD& other) const; + int operator>=(const ADD& other) const; + int operator<(const ADD& other) const; + int operator>(const ADD& other) const; + // Arithmetic operators + ADD operator-() const; + ADD operator*(const ADD& other) const; + ADD operator*=(const ADD& other); + ADD operator+(const ADD& other) const; + ADD operator+=(const ADD& other); + ADD operator-(const ADD& other) const; + ADD operator-=(const ADD& other); + // Logical operators + ADD operator~() const; + ADD operator&(const ADD& other) const; + ADD operator&=(const ADD& other); + ADD operator|(const ADD& other) const; + ADD operator|=(const ADD& other); + ADD ExistAbstract(const ADD& cube) const; + ADD UnivAbstract(const ADD& cube) const; + ADD OrAbstract(const ADD& cube) const; + ADD Plus(const ADD& g) const; + ADD Times(const ADD& g) const; + ADD Threshold(const ADD& g) const; + ADD SetNZ(const ADD& g) const; + ADD Divide(const ADD& g) const; + ADD Minus(const ADD& g) const; + ADD Minimum(const ADD& g) const; + ADD Maximum(const ADD& g) const; + ADD OneZeroMaximum(const ADD& g) const; + ADD Diff(const ADD& g) const; + ADD Agreement(const ADD& g) const; + ADD Or(const ADD& g) const; + ADD Nand(const ADD& g) const; + ADD Nor(const ADD& g) const; + ADD Xor(const ADD& g) const; + ADD Xnor(const ADD& g) const; + ADD Log() const; + ADD FindMax() const; + ADD FindMin() const; + ADD IthBit(int bit) const; + ADD ScalarInverse(const ADD& epsilon) const; + ADD Ite(const ADD& g, const ADD& h) const; + ADD IteConstant(const ADD& g, const ADD& h) const; + ADD EvalConst(const ADD& g) const; + int Leq(const ADD& g) const; + ADD Cmpl() const; + ADD Negate() const; + ADD RoundOff(int N) const; + BDD BddThreshold(CUDD_VALUE_TYPE value) const; + BDD BddStrictThreshold(CUDD_VALUE_TYPE value) const; + BDD BddInterval(CUDD_VALUE_TYPE lower, CUDD_VALUE_TYPE upper) const; + BDD BddIthBit(int bit) const; + BDD BddPattern() const; + ADD Cofactor(const ADD& g) const; + ADD Compose(const ADD& g, int v) const; + ADD Permute(int * permut) const; + ADD SwapVariables(ADDvector x, ADDvector y) const; + ADD VectorCompose(ADDvector vector) const; + ADD NonSimCompose(ADDvector vector) const; + ADD Constrain(const ADD& c) const; + ADD Restrict(const ADD& c) const; + ADD MatrixMultiply(const ADD& B, ADDvector z) const; + ADD TimesPlus(const ADD& B, ADDvector z) const; + ADD Triangle(const ADD& g, ADDvector z) const; + ADD Eval(int * inputs) const; + int EqualSupNorm(const ADD& g, CUDD_VALUE_TYPE tolerance, int pr) const; + +}; // ADD + + +/**Class*********************************************************************** + + Synopsis [Class for ZDDs.] + + Description [] + + SeeAlso [Cudd] + +******************************************************************************/ +class ZDD : public DD { + friend class Cudd; +public: + ZDD(Cudd *bddManager, DdNode *bddNode); + ZDD(); + ZDD(const ZDD &from); + ~ZDD(); + ZDD operator=(const ZDD& right); + int operator==(const ZDD& other) const; + int operator!=(const ZDD& other) const; + int operator<=(const ZDD& other) const; + int operator>=(const ZDD& other) const; + int operator<(const ZDD& other) const; + int operator>(const ZDD& other) const; + void print(int nvars, int verbosity = 1) const; + ZDD operator*(const ZDD& other) const; + ZDD operator*=(const ZDD& other); + ZDD operator&(const ZDD& other) const; + ZDD operator&=(const ZDD& other); + ZDD operator+(const ZDD& other) const; + ZDD operator+=(const ZDD& other); + ZDD operator|(const ZDD& other) const; + ZDD operator|=(const ZDD& other); + ZDD operator-(const ZDD& other) const; + ZDD operator-=(const ZDD& other); + int Count() const; + double CountDouble() const; + ZDD Product(const ZDD& g) const; + ZDD UnateProduct(const ZDD& g) const; + ZDD WeakDiv(const ZDD& g) const; + ZDD Divide(const ZDD& g) const; + ZDD WeakDivF(const ZDD& g) const; + ZDD DivideF(const ZDD& g) const; + double CountMinterm(int path) const; + BDD PortToBdd() const; + ZDD Ite(const ZDD& g, const ZDD& h) const; + ZDD Union(const ZDD& Q) const; + ZDD Intersect(const ZDD& Q) const; + ZDD Diff(const ZDD& Q) const; + ZDD DiffConst(const ZDD& Q) const; + ZDD Subset1(int var) const; + ZDD Subset0(int var) const; + ZDD Change(int var) const; + void PrintMinterm() const; + void PrintCover() const; + +}; // ZDD + + +/**Class*********************************************************************** + + Synopsis [Class for CUDD managers.] + + Description [] + + SeeAlso [DD] + +******************************************************************************/ +class Cudd { + friend class DD; + friend class ABDD; + friend class ADD; + friend class BDD; + friend class ZDD; + struct capsule { + DdManager *manager; + PFC errorHandler; + int verbose; + int ref; + }; + capsule *p; +public: + Cudd( + unsigned int numVars = 0, + unsigned int numVarsZ = 0, + unsigned int numSlots = CUDD_UNIQUE_SLOTS, + unsigned int cacheSize = CUDD_CACHE_SLOTS, + unsigned long maxMemory = 0); + Cudd(Cudd& x); + ~Cudd(); + PFC setHandler(PFC newHandler); + PFC getHandler() const; + DdManager *getManager() const {return p->manager;} + inline void makeVerbose() {p->verbose = 1;} + inline void makeTerse() {p->verbose = 0;} + inline int isVerbose() const {return p->verbose;} + inline void checkReturnValue(const DdNode *result) const; + inline void checkReturnValue(const int result) const; + Cudd& operator=(const Cudd& right); + void info() const; + BDD bddVar(); + BDD bddVar(int index); + BDD bddOne(); + BDD bddZero(); + ADD addVar(); + ADD addVar(int index); + ADD addOne(); + ADD addZero(); + ADD constant(CUDD_VALUE_TYPE c); + ADD plusInfinity(); + ADD minusInfinity(); + ZDD zddVar(int index); + ZDD zddOne(int i); + ZDD zddZero(); + ADD addNewVarAtLevel(int level); + BDD bddNewVarAtLevel(int level); + void zddVarsFromBddVars(int multiplicity); + void AutodynEnable(Cudd_ReorderingType method); + void AutodynDisable(); + int ReorderingStatus(Cudd_ReorderingType * method) const; + void AutodynEnableZdd(Cudd_ReorderingType method); + void AutodynDisableZdd(); + int ReorderingStatusZdd(Cudd_ReorderingType * method) const; + int zddRealignmentEnabled() const; + void zddRealignEnable(); + void zddRealignDisable(); + int bddRealignmentEnabled() const; + void bddRealignEnable(); + void bddRealignDisable(); + ADD background(); + void SetBackground(ADD bg); + unsigned int ReadCacheSlots() const; + double ReadCacheUsedSlots() const; + double ReadCacheLookUps() const; + double ReadCacheHits() const; + unsigned int ReadMinHit() const; + void SetMinHit(unsigned int hr); + unsigned int ReadLooseUpTo() const; + void SetLooseUpTo(unsigned int lut); + unsigned int ReadMaxCache() const; + unsigned int ReadMaxCacheHard() const; + void SetMaxCacheHard(unsigned int mc); + int ReadSize() const; + int ReadZddSize() const; + unsigned int ReadSlots() const; + unsigned int ReadKeys() const; + unsigned int ReadDead() const; + unsigned int ReadMinDead() const; + int ReadReorderings() const; + long ReadReorderingTime() const; + int ReadGarbageCollections() const; + long ReadGarbageCollectionTime() const; + int ReadSiftMaxVar() const; + void SetSiftMaxVar(int smv); + int ReadSiftMaxSwap() const; + void SetSiftMaxSwap(int sms); + double ReadMaxGrowth() const; + void SetMaxGrowth(double mg); + MtrNode * ReadTree() const; + void SetTree(MtrNode * tree); + void FreeTree(); + MtrNode * ReadZddTree() const; + void SetZddTree(MtrNode * tree); + void FreeZddTree(); + int ReadPerm(int i) const; + int ReadPermZdd(int i) const; + int ReadInvPerm(int i) const; + int ReadInvPermZdd(int i) const; + BDD ReadVars(int i); + CUDD_VALUE_TYPE ReadEpsilon() const; + void SetEpsilon(CUDD_VALUE_TYPE ep); + Cudd_AggregationType ReadGroupcheck() const; + void SetGroupcheck(Cudd_AggregationType gc); + int GarbageCollectionEnabled() const; + void EnableGarbageCollection(); + void DisableGarbageCollection(); + int DeadAreCounted() const; + void TurnOnCountDead(); + void TurnOffCountDead(); + int ReadRecomb() const; + void SetRecomb(int recomb); + int ReadSymmviolation() const; + void SetSymmviolation(int symmviolation); + int ReadArcviolation() const; + void SetArcviolation(int arcviolation); + int ReadPopulationSize() const; + void SetPopulationSize(int populationSize); + int ReadNumberXovers() const; + void SetNumberXovers(int numberXovers); + unsigned long ReadMemoryInUse() const; + long ReadPeakNodeCount() const; + long ReadNodeCount() const; + long zddReadNodeCount() const; + void AddHook(DD_HFP f, Cudd_HookType where); + void RemoveHook(DD_HFP f, Cudd_HookType where); + int IsInHook(DD_HFP f, Cudd_HookType where) const; + void EnableReorderingReporting(); + void DisableReorderingReporting(); + int ReorderingReporting(); + int ReadErrorCode() const; + void ClearErrorCode(); + FILE *ReadStdout() const; + void SetStdout(FILE *); + FILE *ReadStderr() const; + void SetStderr(FILE *); + unsigned int ReadNextReordering() const; + double ReadSwapSteps() const; + unsigned int ReadMaxLive() const; + void SetMaxLive(unsigned int); + unsigned long ReadMaxMemory() const; + void SetMaxMemory(unsigned long); + int bddBindVar(int); + int bddUnbindVar(int); + int bddVarIsBound(int) const; + ADD Walsh(ADDvector x, ADDvector y); + ADD addResidue(int n, int m, int options, int top); + int ApaNumberOfDigits(int binaryDigits) const; + DdApaNumber NewApaNumber(int digits) const; + void ApaCopy(int digits, DdApaNumber source, DdApaNumber dest) const; + DdApaDigit ApaAdd(int digits, DdApaNumber a, DdApaNumber b, DdApaNumber + sum) const; + DdApaDigit ApaSubtract(int digits, DdApaNumber a, DdApaNumber b, + DdApaNumber diff) const; + DdApaDigit ApaShortDivision(int digits, DdApaNumber dividend, DdApaDigit + divisor, DdApaNumber quotient) const; + void ApaShiftRight(int digits, DdApaDigit in, DdApaNumber a, DdApaNumber + b) const; + void ApaSetToLiteral(int digits, DdApaNumber number, DdApaDigit literal) + const; + void ApaPowerOfTwo(int digits, DdApaNumber number, int power) const; + void ApaPrintHex(FILE * fp, int digits, DdApaNumber number) const; + void ApaPrintDecimal(FILE * fp, int digits, DdApaNumber number) const; + void DebugCheck(); + void CheckKeys(); + MtrNode * MakeTreeNode(unsigned int low, unsigned int size, unsigned int type); + // void Harwell(FILE * fp, ADD* E, ADD** x, ADD** y, ADD** xn, ADD** yn_, int * nx, int * ny, int * m, int * n, int bx, int sx, int by, int sy, int pr); + void PrintLinear(); + int ReadLinear(int x, int y); + BDD Xgty(BDDvector z, BDDvector x, BDDvector y); + BDD Xeqy(BDDvector x, BDDvector y); + ADD Xeqy(ADDvector x, ADDvector y); + BDD Dxygtdxz(BDDvector x, BDDvector y, BDDvector z); + BDD Dxygtdyz(BDDvector x, BDDvector y, BDDvector z); + BDD Inequality(int c, BDDvector x, BDDvector y); + BDD Disequality(int c, BDDvector x, BDDvector y); + BDD Interval(BDDvector x, unsigned int lowerB, unsigned int upperB); + ADD Hamming(ADDvector xVars, ADDvector yVars); + // void Read(FILE * fp, ADD* E, ADD** x, ADD** y, ADD** xn, ADD** yn_, int * nx, int * ny, int * m, int * n, int bx, int sx, int by, int sy); + // void Read(FILE * fp, BDD* E, BDD** x, BDD** y, int * nx, int * ny, int * m, int * n, int bx, int sx, int by, int sy); + void ReduceHeap(Cudd_ReorderingType heuristic, int minsize); + void ShuffleHeap(int * permutation); + void SymmProfile(int lower, int upper) const; + unsigned int Prime(unsigned int pr) const; + int SharingSize(DD* nodes, int n) const; + BDD bddComputeCube(BDD * vars, int * phase, int n); + ADD addComputeCube(ADD * vars, int * phase, int n); + int NextNode(DdGen * gen, BDD * nnode); + BDD IndicesToCube(int * array, int n); + void PrintVersion(FILE * fp) const; + double AverageDistance() const; + long Random(); + void Srandom(long seed); + MtrNode * MakeZddTreeNode(unsigned int low, unsigned int size, unsigned int type); + void zddPrintSubtable() const; + void zddReduceHeap(Cudd_ReorderingType heuristic, int minsize); + void zddShuffleHeap(int * permutation); + void zddSymmProfile(int lower, int upper) const; + //void DumpDot(int n, ZDD* f, char ** inames, char ** onames, FILE * fp); + +}; // Cudd + + +/**Class*********************************************************************** + + Synopsis [Class for BDD vectors.] + + Description [] + + SeeAlso [BDD] + +******************************************************************************/ +class BDDvector { + struct capsule { + Cudd *manager; + BDD *vect; + int size; + int ref; + }; + capsule *p; +public: + BDDvector(int size, Cudd *manager = 0, DdNode **nodes = 0); + BDDvector(const BDDvector &from); + ~BDDvector(); + BDDvector& operator=(const BDDvector& right); + BDD& operator[](int i) const; + int count() const {return p->size;} + Cudd *manager() const {return p->manager;} + void DumpDot(char ** inames = 0, char ** onames = 0, FILE * fp = stdout) + const; + void DumpDaVinci( + char ** inames = 0, + char ** onames = 0, + FILE * fp = stdout) const; + void DumpBlif( + char ** inames = 0, + char ** onames = 0, + char * mname = 0, + FILE * fp = stdout, + int mv = 0) const; + void DumpDDcal(char ** inames = 0, char ** onames = 0, FILE * fp = stdout) + const; + void DumpFactoredForm( + char ** inames = 0, + char ** onames = 0, + FILE * fp = stdout) const; + BDD VectorSupport() const; + int nodeCount() const; + int VectorSupportSize() const; + +}; // BDDvector + + +/**Class*********************************************************************** + + Synopsis [Class for ADD vectors.] + + Description [] + + SeeAlso [ADD] + +******************************************************************************/ +class ADDvector { + struct capsule { + Cudd *manager; + ADD *vect; + int size; + int ref; + }; + capsule *p; +public: + ADDvector(int size, Cudd *manager = 0, DdNode **nodes = 0); + ADDvector(const ADDvector &from); + ~ADDvector(); + ADDvector& operator=(const ADDvector& right); + ADD& operator[](int i) const; + int count() const {return p->size;} + Cudd *manager() const {return p->manager;} + void DumpDot(char ** inames = 0, char ** onames = 0, FILE * fp = stdout) + const; + void DumpDaVinci( + char ** inames = 0, + char ** onames = 0, + FILE * fp = stdout) const; + BDD VectorSupport() const; + int VectorSupportSize() const; + +}; // ADDvector + + +/**Class*********************************************************************** + + Synopsis [Class for ZDD vectors.] + + Description [] + + SeeAlso [ZDD] + +******************************************************************************/ +class ZDDvector { + struct capsule { + Cudd *manager; + ZDD *vect; + int size; + int ref; + }; + capsule *p; +public: + ZDDvector(int size, Cudd *manager = 0, DdNode **nodes = 0); + ZDDvector(const ZDDvector &from); + ~ZDDvector(); + ZDDvector& operator=(const ZDDvector& right); + ZDD& operator[](int i) const; + int count() const {return p->size;} + Cudd *manager() const {return p->manager;} + void DumpDot(char ** inames = 0, char ** onames = 0, FILE * fp = stdout) + const; + +}; // ZDDvector + + +extern void defaultError(string message); +extern int NextCube(DdGen * gen, int ** cube, CUDD_VALUE_TYPE * value); +extern int GenFree(DdGen * gen); +extern int IsGenEmpty(DdGen * gen); + +#endif diff --git a/distr/obj/test.out b/distr/obj/test.out new file mode 100644 index 0000000..5f57d12 --- /dev/null +++ b/distr/obj/test.out @@ -0,0 +1,516 @@ +Entering testBdd +f: 3 nodes 1 leaves 1 minterms +11 1 + +g: 3 nodes 1 leaves 3 minterms +0- 1 +11 1 + +f and g are not complementary +f is less than or equal to g +g: 2 nodes 1 leaves 2 minterms +1- 1 + +h: 2 nodes 1 leaves 2 minterms +-1 1 + +x + h has 3 nodes +h: 3 nodes 1 leaves 3 minterms +01 1 +1- 1 + +Entering testAdd +r: 6 nodes 3 leaves 3 minterms +01 1 +10 1 +11 2 + +s: 4 nodes 2 leaves 1 minterms +11 3 + +s: 1 nodes 1 leaves 4 minterms +-- inf + +p is less than or equal to r +r: 4 nodes 2 leaves 3 minterms +01 1 +1- 1 + +Entering testAdd2 +f: 7 nodes 4 leaves 4 minterms +00 0.1 +01 0.2 +10 0.3 +11 0.4 + +l: 7 nodes 4 leaves 4 minterms +00 -2.30259 +01 -1.60944 +10 -1.20397 +11 -0.916291 + +r: 7 nodes 4 leaves 4 minterms +00 -0.230259 +01 -0.321888 +10 -0.361192 +11 -0.366516 + +e: 1 nodes 1 leaves 4 minterms +-- 1.84644 + +Entering testZdd +s: 3 nodes 3 minterms +1- 1 +01 1 + +v is less than s +s: 1 nodes 1 minterms +01 1 + +Entering testBdd2 +f: 7 nodes 1 leaves 7 minterms +01-1 1 +101- 1 +1101 1 +111- 1 + +Irredundant cover of f: +1-1- 1 +-1-1 1 + +Number of minterms (arbitrary precision): 7 +Number of minterms (extended precision): 7.000000e+00 +Two-literal clauses of f: + x2 | x3 + x1 | x2 + x0 | x3 + x0 | x1 + +vect[0] +1--- 1 + +vect[1] +0--- 1 +-1-- 1 + +vect[2] +10-- 1 +--1- 1 + +vect[3] +0--- 1 +-10- 1 +---1 1 + +digraph "DD" { +size = "7.5,10" +center = true; +edge [dir = none]; +{ node [shape = plaintext]; + edge [style = invis]; + "CONST NODES" [style = invis]; +" x0 " -> " x1 " -> " x2 " -> " x3 " -> "CONST NODES"; +} +{ rank = same; node [shape = box]; edge [style = invis]; +" v0 " -> " v1 " -> " v2 " -> " v3 "; } +{ rank = same; " x0 "; +"0x3e"; +"0x7b"; +"0x7e"; +"0x3a"; +} +{ rank = same; " x1 "; +"0x7a"; +"0x7d"; +"0x3b"; +} +{ rank = same; " x2 "; +"0x6b"; +"0x7c"; +} +{ rank = same; " x3 "; +"0x6c"; +} +{ rank = same; "CONST NODES"; +{ node [shape = box]; "0x34"; +} +} +" v0 " -> "0x3a" [style = solid]; +" v1 " -> "0x3e" [style = solid]; +" v2 " -> "0x7b" [style = solid]; +" v3 " -> "0x7e" [style = solid]; +"0x3e" -> "0x3b"; +"0x3e" -> "0x34" [style = dashed]; +"0x7b" -> "0x7a"; +"0x7b" -> "0x6b" [style = dashed]; +"0x7e" -> "0x7d"; +"0x7e" -> "0x34" [style = dashed]; +"0x3a" -> "0x34"; +"0x3a" -> "0x34" [style = dotted]; +"0x7a" -> "0x6b"; +"0x7a" -> "0x34" [style = dashed]; +"0x7d" -> "0x7c"; +"0x7d" -> "0x6c" [style = dashed]; +"0x3b" -> "0x34"; +"0x3b" -> "0x34" [style = dotted]; +"0x6b" -> "0x34"; +"0x6b" -> "0x34" [style = dotted]; +"0x7c" -> "0x6c"; +"0x7c" -> "0x34" [style = dashed]; +"0x6c" -> "0x34"; +"0x6c" -> "0x34" [style = dotted]; +"0x34" [label = "1"]; +} +Entering testBdd3 +f: 10 nodes 1 leaves 50 minterms +0-0-0- 1 +0-0-10 1 +0-100- 1 +0-1010 1 +0-11-- 1 +10-00- 1 +10-010 1 +10-1-- 1 +11000- 1 +110010 1 +1101-- 1 +1110-1 1 +111101 1 + +f1: 5 nodes 1 leaves 36 minterms +0---0- 1 +0---10 1 +10--0- 1 +10--10 1 + +f1 is less than or equal to f +g: 6 nodes 1 leaves 62 minterms +0----- 1 +10---- 1 +110--- 1 +1110-- 1 +11110- 1 + +h: 8 nodes 1 leaves 51 minterms +0-0-0- 1 +0-0-10 1 +0-100- 1 +0-1010 1 +0-11-- 1 +10-00- 1 +10-010 1 +10-1-- 1 +11000- 1 +110010 1 +1101-- 1 +111--1 1 + +g * h == f +Entering testZdd2 +p[0]: 3 nodes 1 leaves 64 minterms +----0-0 1 +----1-1 1 + +p[1]: 5 nodes 1 leaves 64 minterms +--0-0-0 1 +--0-10- 1 +--1-0-1 1 +--1-11- 1 + +p[2]: 7 nodes 1 leaves 64 minterms +0-0-0-0 1 +0-0-10- 1 +0-10--- 1 +1-0-0-1 1 +1-0-11- 1 +1-11--- 1 + +p[3]: 8 nodes 1 leaves 64 minterms +0-0-0-1 1 +0-0-11- 1 +0-11--- 1 +11----- 1 + +digraph "DD" { +size = "7.5,10" +center = true; +edge [dir = none]; +{ node [shape = plaintext]; + edge [style = invis]; + "CONST NODES" [style = invis]; +" a2 " -> " b2 " -> " a1 " -> " b1 " -> " a0 " -> " b0 " -> " c0 " -> "CONST NODES"; +} +{ rank = same; node [shape = box]; edge [style = invis]; +" s0 " -> " s1 " -> " s2 " -> " c3 "; } +{ rank = same; " a2 "; +"0xb5"; +"0xb4"; +} +{ rank = same; " b2 "; +"0x3b"; +} +{ rank = same; " a1 "; +"0xb2"; +"0xb3"; +} +{ rank = same; " b1 "; +"0x6c"; +} +{ rank = same; " a0 "; +"0xb1"; +"0xb0"; +} +{ rank = same; " b0 "; +"0x8b"; +} +{ rank = same; " c0 "; +"0xaf"; +} +{ rank = same; "CONST NODES"; +{ node [shape = box]; "0x34"; +} +} +" s0 " -> "0xb0" [style = solid]; +" s1 " -> "0xb2" [style = solid]; +" s2 " -> "0xb4" [style = solid]; +" c3 " -> "0xb5" [style = solid]; +"0xb5" -> "0x3b"; +"0xb5" -> "0xb3" [style = dashed]; +"0xb4" -> "0xb3"; +"0xb4" -> "0xb3" [style = dotted]; +"0x3b" -> "0x34"; +"0x3b" -> "0x34" [style = dotted]; +"0xb2" -> "0xb1"; +"0xb2" -> "0xb1" [style = dotted]; +"0xb3" -> "0x6c"; +"0xb3" -> "0xb1" [style = dashed]; +"0x6c" -> "0x34"; +"0x6c" -> "0x34" [style = dotted]; +"0xb1" -> "0x8b"; +"0xb1" -> "0xaf" [style = dashed]; +"0xb0" -> "0xaf"; +"0xb0" -> "0xaf" [style = dotted]; +"0x8b" -> "0x34"; +"0x8b" -> "0x34" [style = dotted]; +"0xaf" -> "0x34"; +"0xaf" -> "0x34" [style = dotted]; +"0x34" [label = "1"]; +} +z[0]: 4 nodes 2 minterms +00000000100010 1 +00000000010001 1 + +z[1]: 10 nodes 4 minterms +00001000101000 1 +00001000010010 1 +00000100100100 1 +00000100010001 1 + +z[2]: 16 nodes 6 minterms +10001010000000 1 +10000100101000 1 +10000100010010 1 +01001001000000 1 +01000100100100 1 +01000100010001 1 + +z[3]: 10 nodes 4 minterms +10100000000000 1 +01001010000000 1 +01000100101000 1 +01000100010010 1 + +z[0] +----1-1 1 +----0-0 1 +z[1] +--1-11- 1 +--1-0-1 1 +--0-10- 1 +--0-0-0 1 +z[2] +1-11--- 1 +1-0-11- 1 +1-0-0-1 1 +0-10--- 1 +0-0-10- 1 +0-0-0-0 1 +z[3] +11----- 1 +0-11--- 1 +0-0-11- 1 +0-0-0-1 1 +digraph "ZDD" { +size = "7.5,10" +center = true; +edge [dir = none]; +{ node [shape = plaintext]; + edge [style = invis]; + "CONST NODES" [style = invis]; +" a2+ " -> " a2- " -> " b2+ " -> " a1+ " -> " a1- " -> " b1+ " -> " b1- " -> " a0+ " -> " a0- " -> " b0+ " -> " b0- " -> " c0+ " -> " c0- " -> "CONST NODES"; +} +{ rank = same; node [shape = box]; edge [style = invis]; +" s0 " -> " s1 " -> " s2 " -> " c3 "; } +{ rank = same; " a2+ "; +"0x6e"; +"0x77"; +} +{ rank = same; " a2- "; +"0x6a"; +"0x75"; +} +{ rank = same; " b2+ "; +"0x71"; +} +{ rank = same; " a1+ "; +"0x57"; +"0x65"; +"0x5e"; +} +{ rank = same; " a1- "; +"0x55"; +"0x63"; +} +{ rank = same; " b1+ "; +"0x5f"; +} +{ rank = same; " b1- "; +"0x5a"; +} +{ rank = same; " a0+ "; +"0x50"; +"0x42"; +"0x49"; +} +{ rank = same; " a0- "; +"0x4e"; +"0x40"; +} +{ rank = same; " b0+ "; +"0x4a"; +} +{ rank = same; " b0- "; +"0x45"; +} +{ rank = same; " c0+ "; +"0x39"; +} +{ rank = same; " c0- "; +"0x38"; +} +{ rank = same; "CONST NODES"; +{ node [shape = box]; "0x35"; +"0x34"; +} +} +" s0 " -> "0x42" [style = solid]; +" s1 " -> "0x57" [style = solid]; +" s2 " -> "0x6e" [style = solid]; +" c3 " -> "0x77" [style = solid]; +"0x6e" -> "0x65"; +"0x6e" -> "0x6a" [style = dashed]; +"0x77" -> "0x71"; +"0x77" -> "0x75" [style = dashed]; +"0x6a" -> "0x5e"; +"0x6a" -> "0x35" [style = dashed]; +"0x75" -> "0x65"; +"0x75" -> "0x35" [style = dashed]; +"0x71" -> "0x34"; +"0x71" -> "0x35" [style = dashed]; +"0x57" -> "0x50"; +"0x57" -> "0x55" [style = dashed]; +"0x65" -> "0x5f"; +"0x65" -> "0x63" [style = dashed]; +"0x5e" -> "0x5a"; +"0x5e" -> "0x55" [style = dashed]; +"0x55" -> "0x49"; +"0x55" -> "0x35" [style = dashed]; +"0x63" -> "0x50"; +"0x63" -> "0x35" [style = dashed]; +"0x5f" -> "0x34"; +"0x5f" -> "0x35" [style = dashed]; +"0x5a" -> "0x34"; +"0x5a" -> "0x35" [style = dashed]; +"0x50" -> "0x4a"; +"0x50" -> "0x4e" [style = dashed]; +"0x42" -> "0x39"; +"0x42" -> "0x40" [style = dashed]; +"0x49" -> "0x45"; +"0x49" -> "0x40" [style = dashed]; +"0x4e" -> "0x39"; +"0x4e" -> "0x35" [style = dashed]; +"0x40" -> "0x38"; +"0x40" -> "0x35" [style = dashed]; +"0x4a" -> "0x34"; +"0x4a" -> "0x35" [style = dashed]; +"0x45" -> "0x34"; +"0x45" -> "0x35" [style = dashed]; +"0x39" -> "0x34"; +"0x39" -> "0x35" [style = dashed]; +"0x38" -> "0x34"; +"0x38" -> "0x35" [style = dashed]; +"0x35" [label = "0"]; +"0x34" [label = "1"]; +} +Entering testBdd4 +f: 5 nodes 1 leaves 3 minterms +000----------- 1 +11------------ 1 + +g: 5 nodes 1 leaves 3 minterms +000 1 +11- 1 + +f and h are identical +**** 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: 8436016 +Peak number of nodes: 1022 +Peak number of live nodes: 35 +Number of BDD variables: 14 +Number of ZDD variables: 14 +Number of cache entries: 262144 +Number of cache look-ups: 396 +Number of cache hits: 91 +Number of cache insertions: 303 +Number of cache collisions: 0 +Number of cache deletions: 162 +Cache used slots = 0.11% (expected 0.05%) +Soft limit for cache size: 29696 +Number of buckets in unique table: 7424 +Used buckets in unique table: 1.58% (expected 1.69%) +Unique lookups: 475 +Unique links: 6 (0.0126316 per lookup) +Number of BDD and ADD nodes: 78 +Number of ZDD nodes: 49 +Number of dead BDD and ADD nodes: 60 +Number of dead ZDD nodes: 35 +Total number of nodes allocated: 247 +Total number of nodes reclaimed: 85 +Number of recursive calls: 1265 +Garbage collections so far: 1 +Time for garbage collection: 0.00 sec +Reorderings so far: 0 +Time for reordering: 0.00 sec +Node swaps in reordering: 0 diff --git a/distr/obj/testobj.cc b/distr/obj/testobj.cc new file mode 100644 index 0000000..bac6cb8 --- /dev/null +++ b/distr/obj/testobj.cc @@ -0,0 +1,496 @@ +/**CFile*********************************************************************** + + FileName [testobj.cc] + + PackageName [cuddObj] + + Synopsis [Test program for the C++ object-oriented encapsulation of CUDD.] + + 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.] + +******************************************************************************/ + +#include "cuddObj.hh" +#include + +/*---------------------------------------------------------------------------*/ +/* Variable declarations */ +/*---------------------------------------------------------------------------*/ + +#ifndef lint +static char rcsid[] UTIL_UNUSED = "$Id: testobj.cc,v 1.5 2004/08/13 18:11:07 fabio Exp fabio $"; +#endif + +/*---------------------------------------------------------------------------*/ +/* Static function prototypes */ +/*---------------------------------------------------------------------------*/ + +static void testBdd(Cudd& mgr, int verbosity); +static void testAdd(Cudd& mgr, int verbosity); +static void testAdd2(Cudd& mgr, int verbosity); +static void testZdd(Cudd& mgr, int verbosity); +static void testBdd2(Cudd& mgr, int verbosity); +static void testBdd3(Cudd& mgr, int verbosity); +static void testZdd2(Cudd& mgr, int verbosity); +static void testBdd4(Cudd& mgr, int verbosity); + + +/*---------------------------------------------------------------------------*/ +/* Definition of exported functions */ +/*---------------------------------------------------------------------------*/ + +/**Function******************************************************************** + + Synopsis [Main program for testobj.] + + Description [] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +int +main() +{ + int verbosity = 2; + + Cudd mgr(0,2); + // mgr.makeVerbose(); // trace constructors and destructors + testBdd(mgr,verbosity); + testAdd(mgr,verbosity); + testAdd2(mgr,verbosity); + testZdd(mgr,verbosity); + testBdd2(mgr,verbosity); + testBdd3(mgr,verbosity); + testZdd2(mgr,verbosity); + testBdd4(mgr,verbosity); + mgr.info(); + return 0; + +} // main + + +/**Function******************************************************************** + + Synopsis [Test basic operators on BDDs.] + + Description [Test basic operators on BDDs. The function returns void + because it relies on the error hadling done by the interface. The + default error handler causes program termination.] + + SideEffects [Creates BDD variables in the manager.] + + SeeAlso [testBdd2 testBdd3 testBdd4] + +******************************************************************************/ +static void +testBdd( + Cudd& mgr, + int verbosity) +{ + cout << "Entering testBdd\n"; + // Create two new variables in the manager. If testBdd is called before + // any variable is created in mgr, then x gets index 0 and y gets index 1. + BDD x = mgr.bddVar(); + BDD y = mgr.bddVar(); + + BDD f = x * y; + cout << "f"; f.print(2,verbosity); + + BDD g = y + !x; + cout << "g"; g.print(2,verbosity); + + cout << "f and g are" << (f == !g ? "" : " not") << " complementary\n"; + cout << "f is" << (f <= g ? "" : " not") << " less than or equal to g\n"; + + g = f | ~g; + cout << "g"; g.print(2,verbosity); + + BDD h = f = y; + cout << "h"; h.print(2,verbosity); + + cout << "x + h has " << (x+h).nodeCount() << " nodes\n"; + + h += x; + cout << "h"; h.print(2,verbosity); + +} // testBdd + + +/**Function******************************************************************** + + Synopsis [Test basic operators on ADDs.] + + Description [Test basic operators on ADDs. The function returns void + because it relies on the error hadling done by the interface. The + default error handler causes program termination.] + + SideEffects [May create ADD variables in the manager.] + + SeeAlso [testAdd2] + +******************************************************************************/ +static void +testAdd( + Cudd& mgr, + int verbosity) +{ + cout << "Entering testAdd\n"; + // Create two ADD variables. If we called method addVar without an + // argument, we would get two new indices. If testAdd is indeed called + // after testBdd, then those indices would be 2 and 3. By specifying the + // arguments, on the other hand, we avoid creating new unnecessary BDD + // variables. + ADD p = mgr.addVar(0); + ADD q = mgr.addVar(1); + + // Test arithmetic operators. + ADD r = p + q; + cout << "r"; r.print(2,verbosity); + + // CUDD_VALUE_TYPE is double. + ADD s = mgr.constant(3.0); + s *= p * q; + cout << "s"; s.print(2,verbosity); + + s += mgr.plusInfinity(); + cout << "s"; s.print(2,verbosity); + + // Test relational operators. + cout << "p is" << (p <= r ? "" : " not") << " less than or equal to r\n"; + + // Test logical operators. + r = p | q; + cout << "r"; r.print(2,verbosity); + +} // testAdd + + +/**Function******************************************************************** + + Synopsis [Test some more operators on ADDs.] + + Description [Test some more operators on ADDs. The function returns void + because it relies on the error hadling done by the interface. The + default error handler causes program termination.] + + SideEffects [May create ADD variables in the manager.] + + SeeAlso [testAdd] + +******************************************************************************/ +static void +testAdd2( + Cudd& mgr, + int verbosity) +{ + cout << "Entering testAdd2\n"; + // Create two ADD variables. If we called method addVar without an + // argument, we would get two new indices. + int i; + ADDvector x(2); + for (i = 0; i < 2; i++) { + x[i] = mgr.addVar(i); + } + + // Build a probability density function: [0.1, 0.2, 0.3, 0.4]. + ADD f0 = x[1].Ite(mgr.constant(0.2), mgr.constant(0.1)); + ADD f1 = x[1].Ite(mgr.constant(0.4), mgr.constant(0.3)); + ADD f = x[0].Ite(f1, f0); + cout << "f"; f.print(2,verbosity); + + // Compute the entropy. + ADD l = f.Log(); + cout << "l"; l.print(2,verbosity); + ADD r = f * l; + cout << "r"; r.print(2,verbosity); + + ADD e = r.MatrixMultiply(mgr.constant(-1.0/log(2.0)),x); + cout << "e"; e.print(2,verbosity); + +} // testAdd2 + + +/**Function******************************************************************** + + Synopsis [Test basic operators on ZDDs.] + + Description [Test basic operators on ZDDs. The function returns void + because it relies on the error hadling done by the interface. The + default error handler causes program termination.] + + SideEffects [May create ZDD variables in the manager.] + + SeeAlso [testZdd2] + +******************************************************************************/ +static void +testZdd( + Cudd& mgr, + int verbosity) +{ + cout << "Entering testZdd\n"; + ZDD v = mgr.zddVar(0); + ZDD w = mgr.zddVar(1); + + ZDD s = v + w; + cout << "s"; s.print(2,verbosity); + + cout << "v is" << (v < s ? "" : " not") << " less than s\n"; + + s -= v; + cout << "s"; s.print(2,verbosity); + +} // testZdd + + +/**Function******************************************************************** + + Synopsis [Test vector operators on BDDs.] + + Description [Test vector operators on BDDs. The function returns void + because it relies on the error hadling done by the interface. The + default error handler causes program termination.] + + SideEffects [May create BDD variables in the manager.] + + SeeAlso [testBdd testBdd3 testBdd4] + +******************************************************************************/ +static void +testBdd2( + Cudd& mgr, + int verbosity) +{ + cout << "Entering testBdd2\n"; + // Loop indices are best declared in the loops themselves, but + // some compilers won't let us do that. + int i; + BDDvector x(4); + for (i = 0; i < 4; i++) { + x[i] = mgr.bddVar(i); + } + + // Create the BDD for the Achilles' Heel function. + BDD p1 = x[0] * x[2]; + BDD p2 = x[1] * x[3]; + BDD f = p1 + p2; + cout << "f"; f.print(4,verbosity); + cout << "Irredundant cover of f:" << endl; f.PrintCover(); + cout << "Number of minterms (arbitrary precision): "; f.ApaPrintMinterm(4); + cout << "Number of minterms (extended precision): "; f.EpdPrintMinterm(4); + const char* inames[] = {"x0", "x1", "x2", "x3"}; + cout << "Two-literal clauses of f:" << endl; + f.PrintTwoLiteralClauses((char **)inames); cout << endl; + + BDDvector vect = f.CharToVect(); + for (i = 0; i < vect.count(); i++) { + cout << "vect[" << i << "]" << endl; vect[i].PrintCover(); + } + + // v0,...,v3 suffice if testBdd2 is called before testBdd3. + const char* onames[] = {"v0", "v1", "v2", "v3", "v4", "v5"}; + vect.DumpDot((char **)inames,(char **)onames); + +} // testBdd2 + + +/**Function******************************************************************** + + Synopsis [Test additional operators on BDDs.] + + Description [Test additional operators on BDDs. The function returns + void because it relies on the error hadling done by the + interface. The default error handler causes program termination.] + + SideEffects [May create BDD variables in the manager.] + + SeeAlso [testBdd testBdd2 testBdd4] + +******************************************************************************/ +static void +testBdd3( + Cudd& mgr, + int verbosity) +{ + cout << "Entering testBdd3\n"; + BDDvector x(6); + for (int i = 0; i < 6; i++) { + x[i] = mgr.bddVar(i); + } + + BDD G = x[4] + !x[5]; + BDD H = x[4] * x[5]; + BDD E = x[3].Ite(G,!x[5]); + BDD F = x[3] + !H; + BDD D = x[2].Ite(F,!H); + BDD C = x[2].Ite(E,!F); + BDD B = x[1].Ite(C,!F); + BDD A = x[0].Ite(B,!D); + BDD f = !A; + cout << "f"; f.print(6,verbosity); + + BDD f1 = f.RemapUnderApprox(6); + cout << "f1"; f1.print(6,verbosity); + cout << "f1 is" << (f1 <= f ? "" : " not") << " less than or equal to f\n"; + + BDD g; + BDD h; + f.GenConjDecomp(&g,&h); + cout << "g"; g.print(6,verbosity); + cout << "h"; h.print(6,verbosity); + cout << "g * h " << (g * h == f ? "==" : "!=") << " f\n"; + +} // testBdd3 + + +/**Function******************************************************************** + + Synopsis [Test cover manipulation with BDDs and ZDDs.] + + Description [Test cover manipulation with BDDs and ZDDs. The + function returns void because it relies on the error hadling done by + the interface. The default error handler causes program + termination. This function builds the BDDs for a transformed adder: + one in which the inputs are transformations of the original + inputs. It then creates ZDDs for the covers from the BDDs.] + + SideEffects [May create BDD and ZDD variables in the manager.] + + SeeAlso [testZdd] + +******************************************************************************/ +static void +testZdd2( + Cudd& mgr, + int verbosity) +{ + cout << "Entering testZdd2\n"; + int N = 3; // number of bits + // Loop indices are best declared in the loops themselves, but + // some compilers won't let us do that. + int i; + // Create variables. + BDDvector a(N,&mgr); + BDDvector b(N,&mgr); + BDDvector c(N+1,&mgr); + for (i = 0; i < N; i++) { + a[N-1-i] = mgr.bddVar(2*i); + b[N-1-i] = mgr.bddVar(2*i+1); + } + c[0] = mgr.bddVar(2*N); + // Build functions. + BDDvector s(N,&mgr); + for (i = 0; i < N; i++) { + s[i] = a[i].Xnor(c[i]); + c[i+1] = a[i].Ite(b[i],c[i]); + } + + // Create array of outputs and print it. + BDDvector p(N+1,&mgr); + for (i = 0; i < N; i++) { + p[i] = s[i]; + } + p[N] = c[N]; + for (i = 0; i < p.count(); i++) { + cout << "p[" << i << "]"; p[i].print(2*N+1,verbosity); + } + const char* inames[] = {"a2", "b2", "a1", "b1", "a0", "b0", "c0"}; + const char* onames[] = {"s0", "s1", "s2", "c3"}; + p.DumpDot((char **)inames,(char **)onames); + + // Create ZDD variables and build ZDD covers from BDDs. + mgr.zddVarsFromBddVars(2); + ZDDvector z(N+1,&mgr); + for (i = 0; i < N+1; i++) { + ZDD temp; + BDD dummy = p[i].zddIsop(p[i],&temp); + z[i] = temp; + } + + // Print out covers. + for (i = 0; i < z.count(); i++) { + cout << "z[" << i << "]"; z[i].print(4*N+2,verbosity); + } + for (i = 0; i < z.count(); i++) { + cout << "z[" << i << "]\n"; z[i].PrintCover(); + } + const char* znames[] = {"a2+", "a2-", "b2+", "b2-", "a1+", "a1-", "b1+", + "b1-", "a0+", "a0-", "b0+", "b0-", "c0+", "c0-"}; + z.DumpDot((char **)znames,(char **)onames); + +} // testZdd2 + + +/**Function******************************************************************** + + Synopsis [Test transfer between BDD managers.] + + Description [Test transfer between BDD managers. The + function returns void because it relies on the error hadling done by + the interface. The default error handler causes program + termination.] + + SideEffects [May create BDD variables in the manager.] + + SeeAlso [testBdd testBdd2 testBdd3] + +******************************************************************************/ +static void +testBdd4( + Cudd& mgr, + int verbosity) +{ + cout << "Entering testBdd4\n"; + BDD x = mgr.bddVar(0); + BDD y = mgr.bddVar(1); + BDD z = mgr.bddVar(2); + + BDD f = !x * !y * !z + x * y; + cout << "f"; f.print(3,verbosity); + + Cudd otherMgr(0,0); + BDD g = f.Transfer(otherMgr); + cout << "g"; g.print(3,verbosity); + + BDD h = g.Transfer(mgr); + cout << "f and h are" << (f == h ? "" : " not") << " identical\n"; + +} // testBdd4 diff --git a/distr/setup.sh b/distr/setup.sh new file mode 100755 index 0000000..cb40032 --- /dev/null +++ b/distr/setup.sh @@ -0,0 +1,18 @@ +#! /bin/sh +CREATE="ln -s" +if test -d include + then + : + else + mkdir include + cd include + $CREATE ../cudd/cudd.h . + $CREATE ../cudd/cuddInt.h . + $CREATE ../epd/epd.h . + $CREATE ../dddmp/dddmp.h . + $CREATE ../mtr/mtr.h . + $CREATE ../obj/cuddObj.hh . + $CREATE ../st/st.h . + $CREATE ../util/util.h . + $CREATE ../mnemosyne/mnemosyne.h . +fi diff --git a/distr/shutdown.sh b/distr/shutdown.sh new file mode 100755 index 0000000..724917d --- /dev/null +++ b/distr/shutdown.sh @@ -0,0 +1,2 @@ +#! /bin/sh +rm -rf include *.bak *~ diff --git a/distr/sis/Makefile.sis b/distr/sis/Makefile.sis new file mode 100644 index 0000000..fb0c3e6 --- /dev/null +++ b/distr/sis/Makefile.sis @@ -0,0 +1,97 @@ +# $Id$ +# +# Cudd - DD package +#--------------------------- +.SUFFIXES: .o .c .u + +RANLIB = ranlib + +CAD = /projects/octtools/octtools/$(MACHINE) +SIS = .. +LINTCREATEFLAG = -C + +# files for the package +P = bdd +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 cuddBddPort.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 cuddPwPt.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 +POBJ = $(PSRC:.c=.o) +PHDR = cudd.h cuddInt.h cuddBdd.h + +# files for the test program +TARGET = testcudd +SRC = testcudd.c +OBJ = $(SRC:.c=.o) +HDR = + +LIBS = ../util/libutil.a ../st/libst.a +LINTLIBS= ../util/llib-lutil.ln ../st/llib-lst.ln +INCLUDE = -I$(CAD)/include -I$(SIS)/include + +CFLAGS = -g $(INCLUDE) +LDFLAGS = -g +LINTFLAGS = $(INCLUDE) ${LINTEXTRAS} + +#------------------------------------------------------ + +$(TARGET): $(PHDR) $(OBJ) $(POBJ) $(LIBS) + $(CC) $(LDFLAGS) -o $(TARGET) $(OBJ) $(POBJ) $(LIBS) + +lint: $(PSRC) $(PHDR) $(SRC) $(HDR) + lint $(LINTFLAGS) $(SRC) $(PSRC) $(LINTLIBS) + +install: lib$(P).a llib-l$(P).ln + +lib$(P).a: $(POBJ) + ar cr $@ $? + $(RANLIB) $@ + +unpack: lib$(P).a + @for i in $(POBJ); do \ + ln -s $(SIS)/$(P)/$$i $(SIS)/unpack; \ + done + +llib-l$(P).ln: $(PSRC) $(PHDR) + lint $(LINTFLAGS) ${LINTCREATEFLAG}$(P) -n $(PSRC) + +clean: + rm -f $(TARGET) *.a *.ln *.o \ + [Tt]ags [Mm]ake.out lint malloc.out gmon.out __.SYMDEF *~ + +tags: _force + @for i in $(PSRC) $(PHDR); do \ + cwd=`pwd`; ctags -a $$cwd/$$i; + done; + +strip_depend: + sed '/^#--DO NOT CHANGE ANYTHING AFTER THIS LINE/,$$d' Makefile >mktemp + mv mktemp Makefile + +depend: + sed '/^#--DO NOT CHANGE ANYTHING AFTER THIS LINE/,$$d' Makefile >mktemp + echo '#--DO NOT CHANGE ANYTHING AFTER THIS LINE' >>mktemp + $(CAD)/bin/cc-M $(CFLAGS) $(PSRC) | \ + sed 's|$(CAD)|$$(CAD)|g' | \ + grep -v '/usr/include' >>mktemp + mv mktemp Makefile + +#-------------------------- IBM 3090 support ----------------- +IBMHOST = opua +IBMDIST = /users2/sis +ibmdist: $(PSRC) $(PHDR) + rdist -Richw $(PSRC) $(PHDR) $(IBMHOST):$(IBMDIST) +#------------------------------------------------------------- +_force: + diff --git a/distr/sis/cuddBdd.h b/distr/sis/cuddBdd.h new file mode 100644 index 0000000..2a688d7 --- /dev/null +++ b/distr/sis/cuddBdd.h @@ -0,0 +1,382 @@ +/**CHeaderFile***************************************************************** + + FileName [cuddBdd.h] + + PackageName [cudd] + + Synopsis [Defines interface for the CU package to work with the + ucb interface.] + + Description [] + + Author [Abelardo Pardo] + + Copyright [Copyright (c) 1994-1996 The Univ. of Colorado. + All rights reserved. + + Permission is hereby granted, without written agreement and without license + or royalty fees, to use, copy, modify, and distribute this software and its + documentation for any purpose, provided that the above copyright notice and + the following two paragraphs appear in all copies of this software. + + IN NO EVENT SHALL THE UNIVERSITY OF COLORADO BE LIABLE TO ANY PARTY FOR + DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF + COLORADO HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + THE UNIVERSITY OF COLORADO SPECIFICALLY DISCLAIMS ANY WARRANTIES, + INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN + "AS IS" BASIS, AND THE UNIVERSITY OF COLORADO HAS NO OBLIGATION TO PROVIDE + MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.] + + Revision [$Id: cuddBdd.h,v 1.2 1996/07/30 20:42:04 bobbie Exp $] + +******************************************************************************/ + +#ifndef _BDD +#define _BDD + +/*---------------------------------------------------------------------------*/ +/* Nested includes */ +/*---------------------------------------------------------------------------*/ + +#include "var_set.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/*---------------------------------------------------------------------------*/ +/* Constant declarations */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Stucture declarations */ +/*---------------------------------------------------------------------------*/ + +#define boolean int +/* + * foreach macro in the most misesque tradition + * bdd_gen_free always returns 0 + * + * CAUTION: in the context of the port to the CUDD package, it is assumed that + * dynamic reordering will not occur while there are open generators. It is + * the user's responsibility to make sure dynamic reordering doesn't occur. + * As long as new nodes are not created during generation, and you don't + * explicitly call dynamic reordering, you should be okay. + */ + +/* + * foreach_bdd_cube(fn, gen, cube) + * bdd_t *fn; + * bdd_gen *gen; + * array_t *cube; - return + * + * foreach_bdd_cube(fn, gen, cube) { + * ... + * } + */ +#define foreach_bdd_cube(fn, gen, cube)\ + for((gen) = bdd_first_cube(fn, &cube);\ + bdd_is_gen_empty(gen) ? bdd_gen_free(gen) : TRUE;\ + (void) bdd_next_cube(gen, &cube)) + +/* + * foreach_bdd_node(fn, gen, node) + * bdd_t *fn; + * bdd_gen *gen; + * bdd_node *node; - return + */ +#define foreach_bdd_node(fn, gen, node)\ + for((gen) = bdd_first_node(fn, &node);\ + bdd_is_gen_empty(gen) ? bdd_gen_free(gen) : TRUE;\ + (void) bdd_next_node(gen, &node)) + +/* + * Default settings. + */ +#define BDD_NO_LIMIT ((1<<30)-2) +#define BDD_DFLT_ITE_ON TRUE +#define BDD_DFLT_ITE_RESIZE_AT 75 +#define BDD_DFLT_ITE_MAX_SIZE 1000000 +#define BDD_DFLT_ITE_CONST_ON TRUE +#define BDD_DFLT_ITE_CONST_RESIZE_AT 75 +#define BDD_DFLT_ITE_CONST_MAX_SIZE 1000000 +#define BDD_DFLT_ADHOC_ON TRUE +#define BDD_DFLT_ADHOC_RESIZE_AT 0 +#define BDD_DFLT_ADHOC_MAX_SIZE 10000000 +#define BDD_DFLT_GARB_COLLECT_ON TRUE +#define BDD_DFLT_DAEMON NIL(void) +#define BDD_DFLT_MEMORY_LIMIT BDD_NO_LIMIT +#define BDD_DFLT_NODE_RATIO 2.0 +#define BDD_DFLT_INIT_BLOCKS 10 + + +/*---------------------------------------------------------------------------*/ +/* Type declarations */ +/*---------------------------------------------------------------------------*/ + +typedef struct DdManager bdd_manager; /* referenced via a pointer only */ +typedef unsigned int bdd_variableId; /* the id of the variable in a bdd node */ +typedef struct DdNode bdd_node; /* referenced via a pointer only */ +typedef int bdd_literal; /* integers in the set { 0, 1, 2 } */ + +/* This is to avoid problems with the mnemosyne library, which redefines +** free. +*/ +#ifdef MNEMOSYNE +#undef free +#endif + +typedef struct bdd_t { + boolean free; /* TRUE if this is free, FALSE otherwise ... */ + bdd_node *node; /* ptr to the top node of the function */ + bdd_manager *mgr; /* the manager */ +} bdd_t; + +/* + * Initialization data structure. Not supported in CMU package. + */ +typedef struct bdd_mgr_init { + struct { + boolean on; /* TRUE/FALSE: is the cache on */ + unsigned int resize_at; /* percentage at which to resize (e.g. 85% is 85); doesn't apply to adhoc */ + unsigned int max_size; /* max allowable number of buckets; for adhoc, max allowable number of entries */ + } ITE_cache, + ITE_const_cache, + adhoc_cache; + struct { + boolean on; /* TRUE/FALSE: is the garbage collector on */ + } garbage_collector; + struct { + void (*daemon)(); /* used for callback when memory limit exceeded */ + unsigned int limit; /* upper bound on memory allocated by the manager; in megabytes */ + } memory; + struct { + float ratio; /* allocate new bdd_nodes to achieve ratio of used to unused nodes */ + unsigned int init_blocks; /* number of bdd_nodeBlocks initially allocated */ + } nodes; +} bdd_mgr_init; + +/* + * Match types for BDD minimization. + */ +typedef enum { + BDD_MIN_TSM, /* two-side match */ + BDD_MIN_OSM, /* one-side match */ + BDD_MIN_OSDM /* one-side DC match */ +} bdd_min_match_type_t; + +/* + * Statistics and Other Queries + */ +typedef struct bdd_cache_stats { + unsigned int hits; + unsigned int misses; + unsigned int collisions; + unsigned int inserts; +} bdd_cache_stats; + +typedef struct bdd_stats { + struct { + bdd_cache_stats hashtable; /* the unique table; collisions and inserts fields not used */ + bdd_cache_stats itetable; + bdd_cache_stats consttable; + bdd_cache_stats adhoc; + } cache; /* various cache statistics */ + struct { + unsigned int calls; + struct { + unsigned int trivial; + unsigned int cached; + unsigned int full; + } returns; + } ITE_ops, + ITE_constant_ops, + adhoc_ops; + struct { + unsigned int total; + } blocks; /* bdd_nodeBlock count */ + struct { + unsigned int used; + unsigned int unused; + unsigned int total; + unsigned int peak; + } nodes; /* bdd_node count */ + struct { + unsigned int used; + unsigned int unused; + unsigned int total; + unsigned int blocks; + } extptrs; /* bdd_t count */ + struct { + unsigned int times; /* the number of times the garbage-collector has run */ + unsigned int nodes_collected; /* cumulative number of nodes collected over life of manager */ + long runtime; /* cumulative CPU time spent garbage collecting */ + } gc; + struct { + int first_sbrk; /* value of sbrk at start of manager; used to analyze memory usage */ + int last_sbrk; /* value of last sbrk (see "man sbrk") fetched; used to analyze memory usage */ + unsigned int manager; + unsigned int nodes; + unsigned int hashtable; + unsigned int ext_ptrs; + unsigned int ITE_cache; + unsigned int ITE_const_cache; + unsigned int adhoc_cache; + unsigned int total; + } memory; /* memory usage */ +} bdd_stats; + +/* + * Traversal of BDD Formulas + */ + +typedef struct bdd_gen bdd_gen; + +/* + * These are the hooks for stuff that uses bdd's + * + * There are three hooks, and users may use them in whatever + * way they wish; these hooks are guaranteed to never be used + * by the bdd package. + */ +typedef struct bdd_external_hooks { + char *network; + char *mdd; + char *undef1; +} bdd_external_hooks; + +/* + * Dynamic reordering. + */ +typedef enum { + BDD_REORDER_SIFT, + BDD_REORDER_WINDOW, + BDD_REORDER_NONE, + BDD_REORDER_SAME, + BDD_REORDER_RANDOM, + BDD_REORDER_RANDOM_PIVOT, + BDD_REORDER_SIFT_CONVERGE, + BDD_REORDER_SYMM_SIFT, + BDD_REORDER_SYMM_SIFT_CONV, + BDD_REORDER_WINDOW2, + BDD_REORDER_WINDOW3, + BDD_REORDER_WINDOW4, + BDD_REORDER_WINDOW2_CONV, + BDD_REORDER_WINDOW3_CONV, + BDD_REORDER_WINDOW4_CONV, + BDD_REORDER_GROUP_SIFT, + BDD_REORDER_GROUP_SIFT_CONV, + BDD_REORDER_ANNEALING, + BDD_REORDER_GENETIC +} bdd_reorder_type_t; + + +/*---------------------------------------------------------------------------*/ +/* Variable declarations */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Macro declarations */ +/*---------------------------------------------------------------------------*/ + +/* + * BDD Manager Allocation And Destruction + */ +extern void bdd_end (bdd_manager *); +extern void bdd_register_daemon (bdd_manager *, void (*daemon)()); +extern void bdd_set_mgr_init_dflts (bdd_mgr_init *); +extern bdd_manager *bdd_start (int); +extern bdd_manager *bdd_start_with_params (int, bdd_mgr_init *); + +/* + * BDD Variable Allocation + */ +extern bdd_t *bdd_create_variable (bdd_manager *); +extern bdd_t *bdd_get_variable (bdd_manager *, bdd_variableId); + +/* + * BDD Formula Management + */ +extern bdd_t *bdd_dup (bdd_t *); +extern void bdd_free (bdd_t *); + +/* + * Operations on BDD Formulas + */ +extern bdd_t *bdd_and (bdd_t *, bdd_t *, boolean, boolean); +extern bdd_t *bdd_and_smooth (bdd_t *, bdd_t *, array_t *); +extern bdd_t *bdd_between (bdd_t *, bdd_t *); +extern bdd_t *bdd_cofactor (bdd_t *, bdd_t *); +extern bdd_t *bdd_compose (bdd_t *, bdd_t *, bdd_t *); +extern bdd_t *bdd_consensus (bdd_t *, array_t *); +extern bdd_t *bdd_cproject (bdd_t *, array_t *); +extern bdd_t *bdd_else (bdd_t *); +extern bdd_t *bdd_ite (bdd_t *, bdd_t *, bdd_t *, boolean, boolean, boolean); +extern bdd_t *bdd_minimize (bdd_t *, bdd_t *); +extern bdd_t *bdd_minimize_with_params (bdd_t *, bdd_t *, bdd_min_match_type_t, boolean, boolean, boolean); +extern bdd_t *bdd_not (bdd_t *); +extern bdd_t *bdd_one (bdd_manager *); +extern bdd_t *bdd_or (bdd_t *, bdd_t *, boolean, boolean); +extern bdd_t *bdd_smooth (bdd_t *, array_t *); +extern bdd_t *bdd_substitute (bdd_t *, array_t *, array_t *); +extern bdd_t *bdd_then (bdd_t *); +extern bdd_t *bdd_top_var (bdd_t *); +extern bdd_t *bdd_xnor (bdd_t *, bdd_t *); +extern bdd_t *bdd_xor (bdd_t *, bdd_t *); +extern bdd_t *bdd_zero (bdd_manager *); + +/* + * Queries about BDD Formulas + */ +extern boolean bdd_equal (bdd_t *, bdd_t *); +extern boolean bdd_is_cube (bdd_t *); +extern boolean bdd_is_tautology (bdd_t *, boolean); +extern boolean bdd_leq (bdd_t *, bdd_t *, boolean, boolean); + +extern double bdd_count_onset (bdd_t *, array_t *); +extern bdd_manager *bdd_get_manager (bdd_t *); +extern bdd_node *bdd_get_node (bdd_t *, boolean *); +extern void bdd_get_stats (bdd_manager *, bdd_stats *); +extern var_set_t *bdd_get_support (bdd_t *); +extern array_t *bdd_get_varids (array_t *); +extern unsigned int bdd_num_vars (bdd_manager *); +extern void bdd_print (bdd_t *); +extern void bdd_print_stats (bdd_stats, FILE *); +extern int bdd_size (bdd_t *); +extern bdd_variableId bdd_top_var_id (bdd_t *); +extern bdd_t *bdd_create_variable_after (bdd_manager *, bdd_variableId); +extern bdd_variableId bdd_get_id_from_level (bdd_manager *, long); +extern long bdd_top_var_level (bdd_manager *, bdd_t *); + +extern int bdd_gen_free (bdd_gen *); + +/* + * These are NOT to be used directly; only indirectly in the macros. + */ +extern bdd_gen *bdd_first_cube (bdd_t *, array_t **); +extern boolean bdd_next_cube (bdd_gen *, array_t **); +extern bdd_gen *bdd_first_node (bdd_t *, bdd_node **); +extern boolean bdd_next_node (bdd_gen *, bdd_node **); +extern boolean bdd_is_gen_empty (bdd_gen *); + +/* + * Miscellaneous + */ +extern void bdd_set_gc_mode (bdd_manager *, boolean); + +extern bdd_external_hooks *bdd_get_external_hooks (bdd_manager *); + +extern void bdd_dynamic_reordering (bdd_manager *, bdd_reorder_type_t); + +extern int bdd_read_reordering_flag (bdd_manager *); + +#ifdef __cplusplus +} +#endif + +#endif /* _BDD */ diff --git a/distr/sis/cuddBddPort.c b/distr/sis/cuddBddPort.c new file mode 100644 index 0000000..7b97956 --- /dev/null +++ b/distr/sis/cuddBddPort.c @@ -0,0 +1,1954 @@ +/**CFile*********************************************************************** + + FileName [cuddBddPort.c] + + PackageName [cudd] + + Synopsis [SIS interface to the Decision Diagram Package of the + University of Colorado.] + + Description [This file implements an interface between the functions in + the Berkeley BDD package and the functions provided by the CUDD (decision + diagram) package from the University of Colorado. The CUDD package is a + generic implementation of a decision diagram data structure. For the time + being, only Boole expansion is implemented and the leaves in the + in the nodes can be the constants zero, one or any arbitrary value.] + + Author [Abelardo Pardo] + + Copyright [Copyright (c) 1994-1996 The Univ. of Colorado. + All rights reserved. + + Permission is hereby granted, without written agreement and without license + or royalty fees, to use, copy, modify, and distribute this software and its + documentation for any purpose, provided that the above copyright notice and + the following two paragraphs appear in all copies of this software. + + IN NO EVENT SHALL THE UNIVERSITY OF COLORADO BE LIABLE TO ANY PARTY FOR + DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF + COLORADO HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + THE UNIVERSITY OF COLORADO SPECIFICALLY DISCLAIMS ANY WARRANTIES, + INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN + "AS IS" BASIS, AND THE UNIVERSITY OF COLORADO HAS NO OBLIGATION TO PROVIDE + MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.] + +******************************************************************************/ + +#include "util.h" +#include "array.h" +#include "st.h" + +#ifdef EXTERN +#undef EXTERN +#endif +#define EXTERN +#include "cuddInt.h" +#include "cuddBdd.h" + + +/*---------------------------------------------------------------------------*/ +/* Constant declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Stucture declarations */ +/*---------------------------------------------------------------------------*/ + +struct bdd_gen { + bdd_manager *manager; + DdGen *ddGen; + array_t *cube; +}; + +/*---------------------------------------------------------------------------*/ +/* Type declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Variable declarations */ +/*---------------------------------------------------------------------------*/ + +#ifndef lint +static char rcsid[] DD_UNUSED = "$Id: cuddBddPort.c,v 1.11 1996/05/08 06:13:08 fabio Exp $"; +#endif + +/*---------------------------------------------------------------------------*/ +/* Macro declarations */ +/*---------------------------------------------------------------------------*/ + + +/**AutomaticStart*************************************************************/ + +/*---------------------------------------------------------------------------*/ +/* Static function prototypes */ +/*---------------------------------------------------------------------------*/ + +static bdd_t * bdd_construct_bdd_t (DdManager *mgr, DdNode * fn); + +/**AutomaticEnd***************************************************************/ + + +/*---------------------------------------------------------------------------*/ +/* Definition of exported functions */ +/*---------------------------------------------------------------------------*/ + + +/**Function******************************************************************** + + Synopsis [Terminates the bdd package.] + + SideEffects [] + +******************************************************************************/ +void +bdd_end(mgr) +bdd_manager *mgr; +{ + if (mgr->hooks != NULL) FREE(mgr->hooks); + Cudd_Quit(mgr); + +} /* end of bdd_end */ + + +/**Function******************************************************************** + + Synopsis [Initialize manager with the options given in mgr_init.] + + SideEffects [] + +******************************************************************************/ +void +bdd_set_mgr_init_dflts(mgr_init) +bdd_mgr_init *mgr_init; +{ + fprintf(stderr,"CU DD Package: bdd_set_mgr_init_dflts translated to no-op\n"); + return; + +} /* end of bdd_set_mgr_init_dflts */ + + +/**Function******************************************************************** + + Synopsis [Starts the manager with nvariables variables.] + + SideEffects [] + +******************************************************************************/ +bdd_manager * +bdd_start(nvariables) +int nvariables; +{ + DdManager *mgr; + bdd_external_hooks *hooks; + + mgr = Cudd_Init((unsigned int)nvariables,0,CUDD_UNIQUE_SLOTS, + CUDD_CACHE_SLOTS,0); + + hooks = ALLOC(bdd_external_hooks,1); + hooks->mdd = hooks->network = hooks->undef1 = (char *) 0; + mgr->hooks = (char *) hooks; + + return (bdd_manager *)mgr; + +} /* end of bdd_start */ + + +/**Function******************************************************************** + + Synopsis [Starts the manager with parameters.] + + SideEffects [] + +******************************************************************************/ +bdd_manager * +bdd_start_with_params(nvariables, mgr_init) +int nvariables; +bdd_mgr_init *mgr_init; +{ + fprintf(stderr,"CU DD Package: bdd_start_with_parameters bypassed\n"); + return (bdd_manager *)Cudd_Init((unsigned int)nvariables,0, + CUDD_UNIQUE_SLOTS,CUDD_CACHE_SLOTS,0); + +} /* end of bdd_start_with_params */ + + +/**Function******************************************************************** + + Synopsis [Creates a new variable in the manager.] + + SideEffects [] + +******************************************************************************/ +bdd_t * +bdd_create_variable(mgr) +bdd_manager *mgr; +{ + DdNode *var; + DdManager *dd = (DdManager *) mgr; + DdNode *one = DD_ONE(dd); + + if (dd->size >= CUDD_MAXINDEX -1) return(NULL); + do { + dd->reordered = 0; + var = cuddUniqueInter(dd,dd->size,one,Cudd_Not(one)); + } while (dd->reordered == 1); + + if (var == NULL) return(NULL); + cuddRef(var); + return(bdd_construct_bdd_t(dd,var)); + +} /* end of bdd_create_variable */ + + +/**Function******************************************************************** + + Synopsis [Creates a new variable and positions it after the + variable with the specified index.] + + SideEffects [] + +******************************************************************************/ +bdd_t * +bdd_create_variable_after(mgr, after_id) +bdd_manager *mgr; +bdd_variableId after_id; +{ + DdNode *var; + DdManager *dd = (DdManager *) mgr; + int level; + + if (after_id >= dd->size) return(NULL); + level = 1 + dd->perm[after_id]; + var = Cudd_bddNewVarAtLevel(dd,level); + if (var == NULL) return(NULL); + cuddRef(var); + return(bdd_construct_bdd_t(dd,var)); + +} /* end of bdd_create_variable_after */ + + +/**Function******************************************************************** + + Synopsis [Returns the BDD representing the variable with given ID.] + + SideEffects [] + +******************************************************************************/ +bdd_t * +bdd_get_variable(mgr, variable_ID) +bdd_manager *mgr; +bdd_variableId variable_ID; /* unsigned int */ +{ + DdNode *var; + DdManager *dd = (DdManager *) mgr; + DdNode *one = DD_ONE(dd); + + if (variable_ID >= CUDD_MAXINDEX -1) return(NULL); + do { + dd->reordered = 0; + var = cuddUniqueInter(dd,(int)variable_ID,one,Cudd_Not(one)); + } while (dd->reordered == 1); + + if (var == NULL) return(NULL); + cuddRef(var); + return(bdd_construct_bdd_t(dd,var)); + +} /* end of bdd_get_variable */ + + +/**Function******************************************************************** + + Synopsis [Creates a copy of the BDD.] + + SideEffects [] + +******************************************************************************/ +bdd_t * +bdd_dup(f) +bdd_t *f; +{ + cuddRef(f->node); + return(bdd_construct_bdd_t((DdManager *)f->mgr,f->node)); + +} /* end of bdd_dup */ + + +/**Function******************************************************************** + + Synopsis [Deletes the BDD of f.] + + SideEffects [] + +******************************************************************************/ +void +bdd_free(f) +bdd_t *f; +{ + if (f == NULL) { + fail("bdd_free: trying to free a NULL bdd_t"); + } + + if (f->free == TRUE) { + fail("bdd_free: trying to free a freed bdd_t"); + } + + Cudd_RecursiveDeref((DdManager *)f->mgr,f->node); + /* This is a bit overconservative. */ + f->node = 0; + f->mgr = 0; + f->free = 0; + FREE(f); + return; + +} /* end of bdd_free */ + + +/**Function******************************************************************** + + Synopsis [And of two BDDs.] + + SideEffects [] + +******************************************************************************/ +bdd_t * +bdd_and(f, g, f_phase, g_phase) +bdd_t *f; +bdd_t *g; +boolean f_phase; +boolean g_phase; +{ + DdManager *dd; + DdNode *newf,*newg,*fandg; + bdd_t *result; + + /* Make sure both BDDs belong to the same manager. */ + assert(f->mgr == g->mgr); + + /* Modify the phases of the operands according to the parameters. */ + if (!f_phase) { + newf = Cudd_Not(f->node); + } else { + newf = f->node; + } + if (!g_phase) { + newg = Cudd_Not(g->node); + } else { + newg = g->node; + } + + /* Perform the AND operation */ + dd = (DdManager *)f->mgr; + fandg = Cudd_bddAnd((DdManager *)f->mgr,newf,newg); + if (fandg == NULL) return(NULL); + cuddRef(fandg); + result = bdd_construct_bdd_t(dd,fandg); + + return(result); + +} /* end of bdd_and */ + + +/**Function******************************************************************** + + Synopsis [Abstracts variables from the product of two BDDs.] + + SideEffects [] + +******************************************************************************/ +bdd_t * +bdd_and_smooth(f, g, smoothing_vars) +bdd_t *f; +bdd_t *g; +array_t *smoothing_vars; /* of bdd_t *'s */ +{ + int i; + bdd_t *variable; + DdNode *cube,*tmpDd,*result; + DdManager *mgr; + + /* Make sure both operands belong to the same manager. */ + assert(f->mgr == g->mgr); + + /* The Boulder package needs the smothing variables passed as a cube. + ** Therefore we must build that cube from the indices of variables + ** in the array before calling the procedure. + */ + mgr = (DdManager *)f->mgr; + Cudd_Ref(cube = DD_ONE(mgr)); + for (i = 0; i < array_n(smoothing_vars); i++) { + variable = array_fetch(bdd_t *,smoothing_vars,i); + + /* Make sure the variable belongs to the same manager. */ + assert(mgr == variable->mgr); + + tmpDd = Cudd_bddAnd(mgr,cube,variable->node); + if (tmpDd == NULL) { + Cudd_RecursiveDeref(mgr,cube); + return(NULL); + } + cuddRef(tmpDd); + Cudd_RecursiveDeref(mgr, cube); + cube = tmpDd; + } + + /* Perform the smoothing */ + result = Cudd_bddAndAbstract(mgr,f->node,g->node,cube); + if (result == NULL) { + Cudd_RecursiveDeref(mgr, cube); + return(NULL); + } + cuddRef(result); + /* Get rid of temporary results. */ + Cudd_RecursiveDeref(mgr, cube); + + /* Build the bdd_t structure for the result */ + return(bdd_construct_bdd_t(mgr,result)); + +} /* end of bdd_and_smooth */ + + +/**Function******************************************************************** + + Synopsis [Return a minimum size BDD between bounds.] + + SideEffects [] + +******************************************************************************/ +bdd_t * +bdd_between(f_min, f_max) +bdd_t *f_min; +bdd_t *f_max; +{ + bdd_t *temp, *ret; + + temp = bdd_or(f_min, f_max, 1, 0); + ret = bdd_minimize(f_min, temp); + bdd_free(temp); + return(ret); + +} /* end of bdd_between */ + + +/**Function******************************************************************** + + Synopsis [Computes the cofactor of f with respect to g.] + + SideEffects [] + +******************************************************************************/ +bdd_t * +bdd_cofactor(f, g) +bdd_t *f; +bdd_t *g; +{ + DdNode *result; + + /* Make sure both operands belong to the same manager */ + assert(f->mgr == g->mgr); + + /* We use Cudd_bddConstrain instead of Cudd_Cofactor for generality. */ + result = Cudd_bddConstrain((DdManager *)f->mgr,f->node,g->node); + if (result == NULL) return(NULL); + cuddRef(result); + return(bdd_construct_bdd_t((DdManager *)f->mgr,result)); + +} /* end of bdd_cofactor */ + + +/**Function******************************************************************** + + Synopsis [Functional composition of a function by a variable.] + + SideEffects [] + +******************************************************************************/ +bdd_t * +bdd_compose(f, v, g) +bdd_t *f; +bdd_t *v; +bdd_t *g; +{ + DdNode *result; + + /* Make sure all operands belong to the same manager. */ + assert(f->mgr == g->mgr); + assert(f->mgr == v->mgr); + + result = Cudd_bddCompose(f->mgr,f->node,g->node,(int)Cudd_Regular(v->node)->index); + if (result == NULL) return(NULL); + cuddRef(result); + return(bdd_construct_bdd_t(f->mgr,result)); + +} /* end of bdd_compose */ + + +/**Function******************************************************************** + + Synopsis [Universal Abstraction of Variables.] + + SideEffects [] + +******************************************************************************/ +bdd_t * +bdd_consensus(f, quantifying_vars) +bdd_t *f; +array_t *quantifying_vars; /* of bdd_t *'s */ +{ + int i; + bdd_t *variable; + DdNode *cube,*tmpDd,*result; + bdd_manager *mgr; + + /* The Boulder package needs the smothing variables passed as a cube. + ** Therefore we must build that cube from the indices of the variables + ** in the array before calling the procedure. + */ + mgr = f->mgr; + Cudd_Ref(cube = DD_ONE(mgr)); + for (i = 0; i < array_n(quantifying_vars); i++) { + variable = array_fetch(bdd_t *,quantifying_vars,i); + + /* Make sure the variable belongs to the same manager */ + assert(mgr == variable->mgr); + + tmpDd = Cudd_bddAnd(mgr,cube,variable->node); + if (tmpDd == NULL) { + Cudd_RecursiveDeref(mgr, cube); + return(NULL); + } + cuddRef(tmpDd); + Cudd_RecursiveDeref(mgr, cube); + cube = tmpDd; + } + + /* Perform the consensus */ + result = Cudd_bddUnivAbstract(mgr,f->node,cube); + if (result == NULL) { + Cudd_RecursiveDeref(mgr, cube); + return(NULL); + } + cuddRef(result); + /* Get rid of temporary results */ + Cudd_RecursiveDeref(mgr, cube); + + /* Build the bdd_t structure for the result */ + return(bdd_construct_bdd_t(mgr,result)); + +} /* end of bdd_consensus */ + + +/**Function******************************************************************** + + Synopsis [The compatible projection function.] + + Description [The compatible projection function. The reference minterm + is chosen based on the phases of the quantifying variables. If all + variables are in positive phase, the minterm 111...111 is used as + reference.] + + SideEffects [] + +******************************************************************************/ +bdd_t * +bdd_cproject(f, quantifying_vars) +bdd_t *f; +array_t *quantifying_vars; /* of bdd_t* */ +{ + DdManager *dd; + DdNode *cube; + DdNode *res; + bdd_t *fi; + int nvars, i; + + if (f == NULL) { + fail ("bdd_cproject: invalid BDD"); + } + + nvars = array_n(quantifying_vars); + if (nvars <= 0) { + fail("bdd_cproject: no projection variables"); + } + dd = f->mgr; + + cube = DD_ONE(dd); + cuddRef(cube); + for (i = nvars - 1; i >= 0; i--) { + DdNode *tmpp; + fi = array_fetch(bdd_t *, quantifying_vars, i); + tmpp = Cudd_bddAnd(dd,fi->node,cube); + if (tmpp == NULL) { + Cudd_RecursiveDeref(dd,cube); + return(NULL); + } + cuddRef(tmpp); + Cudd_RecursiveDeref(dd,cube); + cube = tmpp; + } + + res = Cudd_CProjection(dd,f->node,cube); + if (res == NULL) { + Cudd_RecursiveDeref(dd,cube); + return(NULL); + } + cuddRef(res); + Cudd_RecursiveDeref(dd,cube); + + return(bdd_construct_bdd_t(dd,res)); + +} /* end of bdd_cproject */ + + +/**Function******************************************************************** + + Synopsis [ITE.] + + SideEffects [] + +******************************************************************************/ +bdd_t * +bdd_ite(i, t, e, i_phase, t_phase, e_phase) +bdd_t *i; +bdd_t *t; +bdd_t *e; +boolean i_phase; +boolean t_phase; +boolean e_phase; +{ + DdNode *newi,*newt,*newe,*ite; + + /* Make sure both bdds belong to the same mngr */ + assert(i->mgr == t->mgr); + assert(i->mgr == e->mgr); + + /* Modify the phases of the operands according to the parameters */ + if (!i_phase) { + newi = Cudd_Not(i->node); + } else { + newi = i->node; + } + if (!t_phase) { + newt = Cudd_Not(t->node); + } else { + newt = t->node; + } + if (!e_phase) { + newe = Cudd_Not(e->node); + } else { + newe = e->node; + } + + /* Perform the ITE operation */ + ite = Cudd_bddIte(i->mgr,newi,newt,newe); + if (ite == NULL) return(NULL); + cuddRef(ite); + return(bdd_construct_bdd_t(i->mgr,ite)); + +} /* end of bdd_ite */ + + +/**Function******************************************************************** + + Synopsis [Restric operator as described in Coudert et al. ICCAD90.] + + SideEffects [] + +******************************************************************************/ +bdd_t * +bdd_minimize(f, c) +bdd_t *f; +bdd_t *c; +{ + DdNode *result; + + /* Make sure both operands belong to the same manager. */ + assert(f->mgr == c->mgr); + + result = Cudd_bddRestrict(f->mgr,f->node,c->node); + if (result == NULL) return(NULL); + cuddRef(result); + + return(bdd_construct_bdd_t(f->mgr,result)); + +} /* end of bdd_minimize */ + + +/**Function******************************************************************** + + Synopsis [Parametrized version of the Restrict operator.] + + Description [Parametrized version of the Restrict operator. Currently + defaults to bdd_minimize.] + + SideEffects [] + +******************************************************************************/ +/*ARGSUSED*/ +bdd_t * +bdd_minimize_with_params(f, c, match_type, compl, no_new_vars, return_min) +bdd_t *f; +bdd_t *c; +bdd_min_match_type_t match_type; +boolean compl; +boolean no_new_vars; +boolean return_min; +{ + return(bdd_minimize(f,c)); + +} /* end of bdd_minimize_with_params */ + + +/**Function******************************************************************** + + Synopsis [Negation.] + + SideEffects [] + +******************************************************************************/ +bdd_t * +bdd_not(f) +bdd_t *f; +{ + DdNode *result; + + Cudd_Ref(result = Cudd_Not(f->node)); + return(bdd_construct_bdd_t((DdManager *)f->mgr,result)); + +} /* end of bdd_not */ + + +/**Function******************************************************************** + + Synopsis [Returns the one BDD.] + + SideEffects [] + +******************************************************************************/ +bdd_t * +bdd_one(mgr) +bdd_manager *mgr; +{ + DdNode *result; + + Cudd_Ref(result = DD_ONE((DdManager *)mgr)); + return(bdd_construct_bdd_t((DdManager *)mgr,result)); + +} /* end of bdd_one */ + + +/**Function******************************************************************** + + Synopsis [Or of two BDDs.] + + SideEffects [] + +******************************************************************************/ +bdd_t * +bdd_or(f, g, f_phase, g_phase) +bdd_t *f; +bdd_t *g; +boolean f_phase; +boolean g_phase; +{ + DdNode *newf,*newg,*forg; + bdd_t *result; + + /* Make sure both bdds belong to the same mngr */ + assert(f->mgr == g->mgr); + + /* Modify the phases of the operands according to the parameters */ + if (f_phase) { + newf = Cudd_Not(f->node); + } else { + newf = f->node; + } + if (g_phase) { + newg = Cudd_Not(g->node); + } else { + newg = g->node; + } + + /* Perform the OR operation */ + forg = Cudd_bddAnd(f->mgr,newf,newg); + if (forg == NULL) return(NULL); + forg = Cudd_Not(forg); + cuddRef(forg); + result = bdd_construct_bdd_t(f->mgr,forg); + + return(result); + +} /* end of bdd_or */ + + +/**Function******************************************************************** + + Synopsis [Existential abstraction of variables.] + + SideEffects [] + +******************************************************************************/ +bdd_t * +bdd_smooth(f, smoothing_vars) +bdd_t *f; +array_t *smoothing_vars; /* of bdd_t *'s */ +{ + int i; + bdd_t *variable; + DdNode *cube,*tmpDd,*result; + bdd_manager *mgr; + + /* The Boulder package needs the smothing variables passed as a cube. + ** Therefore we must build that cube from the indices of the variables + ** in the array before calling the procedure. + */ + mgr = f->mgr; + Cudd_Ref(cube = DD_ONE(mgr)); + for (i = 0; i < array_n(smoothing_vars); i++) { + variable = array_fetch(bdd_t *,smoothing_vars,i); + + /* Make sure the variable belongs to the same manager. */ + assert(mgr == variable->mgr); + + tmpDd = Cudd_bddAnd(mgr,cube,variable->node); + if (tmpDd == NULL) { + Cudd_RecursiveDeref(mgr, cube); + return(NULL); + } + cuddRef(tmpDd); + Cudd_RecursiveDeref(mgr, cube); + cube = tmpDd; + } + + /* Perform the smoothing */ + result = Cudd_bddExistAbstract(mgr,f->node,cube); + if (result == NULL) { + Cudd_RecursiveDeref(mgr, cube); + return(NULL); + } + cuddRef(result); + + /* Get rid of temporary results */ + Cudd_RecursiveDeref(mgr, cube); + + /* Build the bdd_t structure for the result */ + return(bdd_construct_bdd_t(mgr,result)); + +} /* end of bdd_smooth */ + + +/**Function******************************************************************** + + Synopsis [Permutes the variables.] + + SideEffects [] + +******************************************************************************/ +bdd_t * +bdd_substitute(f, old_array, new_array) +bdd_t *f; +array_t *old_array; /* of bdd_t *'s */ +array_t *new_array; /* of bdd_t *'s */ +{ + int maxOld; + int i,varIndex,from,to; + int *permut; + bdd_t *variable; + DdNode *result; + + /* Make sure both arrays have the same number of elements. */ + assert(array_n(old_array) == array_n(new_array)); + + /* Detect what is the highest index of variable to rename. */ + maxOld = 0; + for (i = 0; i < array_n(old_array); i++) { + variable = array_fetch(bdd_t *, old_array, i); + /* Make sure the variable belongs to this manager. */ + assert(f->mgr == variable->mgr); + + varIndex = Cudd_Regular(variable->node)->index; + if (varIndex > maxOld) { + maxOld = varIndex; + } + } + maxOld++; + + /* Allocate and fill the array with the trivial permutation. */ + permut = ALLOC(int, maxOld); + for (i = 0; i < maxOld; i++) permut[i] = i; + + /* Modify the permutation by looking at both arrays old and new. */ + for (i = 0; i < array_n(old_array); i++) { + variable = array_fetch(bdd_t *, old_array, i); + from = Cudd_Regular(variable->node)->index; + variable = array_fetch(bdd_t *, new_array, i); + /* Make sure the variable belongs to this manager. */ + assert(f->mgr == variable->mgr); + + to = Cudd_Regular(variable->node)->index; + permut[from] = to; + } + + result = Cudd_bddPermute(f->mgr,f->node,permut); + FREE(permut); + if (result == NULL) return(NULL); + cuddRef(result); + return(bdd_construct_bdd_t(f->mgr,result)); + +} /* end of bdd_substitute */ + + +/**Function******************************************************************** + + Synopsis [Returns the Then branch of the BDD.] + + SideEffects [] + +******************************************************************************/ +bdd_t * +bdd_then(f) +bdd_t *f; +{ + DdNode *result; + + result = Cudd_T(f->node); + result = Cudd_NotCond(result,Cudd_IsComplement(f->node)); + cuddRef(result); + return(bdd_construct_bdd_t(f->mgr,result)); + +} /* end of bdd_then */ + + +/**Function******************************************************************** + + Synopsis [Returns the else branch of a BDD.] + + SideEffects [] + +******************************************************************************/ +bdd_t * +bdd_else(f) +bdd_t *f; +{ + DdNode *result; + + result = Cudd_E(f->node); + result = Cudd_NotCond(result,Cudd_IsComplement(f->node)); + cuddRef(result); + return(bdd_construct_bdd_t(f->mgr,result)); + +} /* end of bdd_else */ + + +/**Function******************************************************************** + + Synopsis [Returns the BDD of the top variable.] + + Description [Returns the BDD of the top variable of the argument. If + the argument is constant, it returns the constant function itself.] + + SideEffects [] + +******************************************************************************/ +bdd_t * +bdd_top_var(f) +bdd_t *f; +{ + DdNode *result; + + if (Cudd_IsConstant(f->node)) { + result = f->node; + } else { + result = f->mgr->vars[Cudd_Regular(f->node)->index]; + } + cuddRef(result); + return(bdd_construct_bdd_t(f->mgr,result)); + +} /* end of bdd_top_var */ + + +/**Function******************************************************************** + + Synopsis [Computes the exclusive nor of two BDDs.] + + SideEffects [] + +******************************************************************************/ +bdd_t * +bdd_xnor(f, g) +bdd_t *f; +bdd_t *g; +{ + DdNode *result; + + /* Make sure both operands belong to the same manager. */ + assert(f->mgr == g->mgr); + + result = Cudd_bddIte(f->mgr,f->node,g->node,Cudd_Not(g->node)); + if (result == NULL) return(NULL); + cuddRef(result); + return(bdd_construct_bdd_t(f->mgr,result)); + +} /* end of bdd_xnor */ + + +/**Function******************************************************************** + + Synopsis [Computes the exclusive or of two BDDs.] + + SideEffects [] + +******************************************************************************/ +bdd_t * +bdd_xor(f, g) +bdd_t *f; +bdd_t *g; +{ + DdNode *result; + + /* Make sure both operands belong to the same manager. */ + assert(f->mgr == g->mgr); + + result = Cudd_bddIte(f->mgr,f->node,Cudd_Not(g->node),g->node); + if (result == NULL) return(NULL); + cuddRef(result); + return(bdd_construct_bdd_t(f->mgr,result)); + +} /* end of bdd_xor */ + + +/**Function******************************************************************** + + Synopsis [Returns the constant zero BDD.] + + SideEffects [] + +******************************************************************************/ +bdd_t * +bdd_zero(mgr) +bdd_manager *mgr; +{ + DdNode *result; + + Cudd_Ref(result = Cudd_Not(DD_ONE((mgr)))); + return(bdd_construct_bdd_t(mgr,result)); + +} /* end of bdd_zero */ + + +/**Function******************************************************************** + + Synopsis [Equality check.] + + SideEffects [] + +******************************************************************************/ +boolean +bdd_equal(f, g) +bdd_t *f; +bdd_t *g; +{ + return(f->node == g->node); + +} /* end of bdd_equal */ + + +/**Function******************************************************************** + + Synopsis [Returns a BDD included in the intersection of f and g.] + + SideEffects [] + +******************************************************************************/ +bdd_t * +bdd_intersects(f, g) +bdd_t *f; +bdd_t *g; +{ + DdNode *result; + + /* Make sure both operands belong to the same manager. */ + assert(f->mgr == g->mgr); + + result = Cudd_bddIntersect(f->mgr,f->node,g->node); + if (result == NULL) return(NULL); + cuddRef(result); + return(bdd_construct_bdd_t(f->mgr,result)); + +} /* end of bdd_intersects */ + + +/**Function******************************************************************** + + Synopsis [Checks a BDD for tautology.] + + SideEffects [] + +******************************************************************************/ +boolean +bdd_is_tautology(f, phase) +bdd_t *f; +boolean phase; +{ + if (phase) { + return(f->node == DD_ONE(f->mgr)); + } else { + return(f->node == Cudd_Not(DD_ONE(f->mgr))); + } + +} /* end of bdd_is_tautology */ + + +/**Function******************************************************************** + + Synopsis [Tests for containment of f in g.] + + SideEffects [] + +******************************************************************************/ +boolean +bdd_leq(f, g, f_phase, g_phase) +bdd_t *f; +bdd_t *g; +boolean f_phase; +boolean g_phase; +{ + DdNode *newf, *newg; + + /* Make sure both operands belong to the same manager. */ + assert(f->mgr == g->mgr); + + if (f_phase) { + newf = f->node; + } else { + newf = Cudd_Not(f->node); + } + if (g_phase) { + newg = g->node; + } else { + newg = Cudd_Not(g->node); + } + + return(Cudd_bddLeq(f->mgr,newf,newg)); + +} /* end of bdd_leq */ + + +/**Function******************************************************************** + + Synopsis [Counts the number of minterms in the on set.] + + SideEffects [] + +******************************************************************************/ +double +bdd_count_onset(f, var_array) +bdd_t *f; +array_t *var_array; /* of bdd_t *'s */ +{ + return(Cudd_CountMinterm(f->mgr,f->node,array_n(var_array))); + +} /* end of bdd_count_onset */ + + +/**Function******************************************************************** + + Synopsis [Obtains the manager of the BDD.] + + SideEffects [] + +******************************************************************************/ +bdd_manager * +bdd_get_manager(f) +bdd_t *f; +{ + return(f->mgr); + +} /* end of bdd_get_manager */ + + +/**Function******************************************************************** + + Synopsis [Returns the node of the BDD.] + + SideEffects [Sets is_complemented.] + +******************************************************************************/ +bdd_node * +bdd_get_node(f, is_complemented) +bdd_t *f; +boolean *is_complemented; /* return */ +{ + if (Cudd_IsComplement(f->node)) { + *is_complemented = TRUE; + return(Cudd_Regular(f->node)); + } + *is_complemented = FALSE; + return(f->node); + +} /* end of bdd_get_node */ + + +/**Function******************************************************************** + + Synopsis [Returns the free field of the BDD.] + + SideEffects [] + +******************************************************************************/ +int +bdd_get_free(f) +bdd_t *f; +{ + return (f->free); + +} /* end of bdd_get_free */ + + +/**Function******************************************************************** + + Synopsis [Obtains some statistics of the BDD package.] + + SideEffects [Sets stats.] + +******************************************************************************/ +/*ARGSUSED*/ +void +bdd_get_stats(mgr, stats) +bdd_manager *mgr; +bdd_stats *stats; /* return */ +{ + stats->nodes.total = mgr->keys; + stats->nodes.used = mgr->keys - mgr->dead; + stats->nodes.unused = mgr->dead; + stats->cache.itetable.hits = (unsigned int) Cudd_ReadCacheHits(mgr); + stats->cache.itetable.misses = (unsigned int) + (Cudd_ReadCacheLookUps(mgr) - Cudd_ReadCacheHits(mgr)); + stats->cache.itetable.collisions = mgr->cachecollisions; + stats->cache.itetable.inserts = mgr->cacheinserts; + stats->gc.times = Cudd_ReadGarbageCollections(mgr); + return; + +} /* end of bdd_get_stats */ + + +/**Function******************************************************************** + + Synopsis [Obtains the support of the BDD.] + + SideEffects [] + +******************************************************************************/ +var_set_t * +bdd_get_support(f) +bdd_t *f; +{ + DdNode *support, *scan; + var_set_t *result; + + support = Cudd_Support(f->mgr,f->node); + if (support == NULL) return(NULL); + cuddRef(support); + + result = var_set_new((int) f->mgr->size); + scan = support; + while (!cuddIsConstant(scan)) { + var_set_set_elt(result, scan->index); + scan = cuddT(scan); + } + Cudd_RecursiveDeref(f->mgr,support); + + return(result); + +} /* end of bdd_get_support */ + + +/**Function******************************************************************** + + Synopsis [Obtains the array of indices of an array of variables.] + + SideEffects [] + +******************************************************************************/ +array_t * +bdd_get_varids(var_array) +array_t *var_array; +{ + int i; + int index; + bdd_t *var; + array_t *result = array_alloc(int,array_n(var_array)); + + for (i = 0; i < array_n(var_array); i++) { + var = array_fetch(bdd_t *, var_array, i); + index = Cudd_Regular(var->node)->index; + (void) array_insert_last(int, result, index); + } + return(result); + +} /* end of bdd_get_varids */ + + +/**Function******************************************************************** + + Synopsis [Returns the number of variables in the manager.] + + SideEffects [] + +******************************************************************************/ +unsigned int +bdd_num_vars(mgr) +bdd_manager *mgr; +{ + return(mgr->size); + +} /* end of bdd_num_vars */ + + +/**Function******************************************************************** + + Synopsis [Prints the BDD.] + + SideEffects [] + +******************************************************************************/ +void +bdd_print(f) +bdd_t *f; +{ + (void) cuddP(f->mgr,f->node); + +} /* end of bdd_print */ + + +/**Function******************************************************************** + + Synopsis [Prints statistics about the package.] + + SideEffects [] + +******************************************************************************/ +void +bdd_print_stats(stats, file) +bdd_stats stats; +FILE *file; +{ +#ifndef DD_STATS + fprintf(stderr,"CU DD package: bdd_print_stats: Statistics turned off. No output\n"); +#else + fprintf(file,"CU DD Package Statistics\n"); + fprintf(file," Cache hits : %d\n",stats.cache.itetable.hits); + fprintf(file," Cache misses : %d\n",stats.cache.itetable.misses); + fprintf(file," Cache collisions : %d\n",stats.cache.itetable.collisions); + fprintf(file," Cache inserts: %d\n",stats.cache.itetable.inserts); +#endif + return; + +} /* end of bdd_print_stats */ + + +/**Function******************************************************************** + + Synopsis [Computes the number of nodes of a BDD.] + + SideEffects [] + +******************************************************************************/ +int +bdd_size(f) +bdd_t *f; +{ + return(Cudd_DagSize(f->node)); + +} /* end of bdd_size */ + + +/**Function******************************************************************** + + Synopsis [Accesses the id of the top variable.] + + SideEffects [] + +******************************************************************************/ +bdd_variableId +bdd_top_var_id(f) +bdd_t *f; +{ + return(Cudd_Regular(f->node)->index); + +} /* end of bdd_top_var_id */ + + +/**Function******************************************************************** + + Synopsis [Accesses the external_hooks field of the manager.] + + SideEffects [] + +******************************************************************************/ +bdd_external_hooks * +bdd_get_external_hooks(mgr) +bdd_manager *mgr; +{ + return((bdd_external_hooks *)(mgr->hooks)); + +} /* end of bdd_get_external_hooks */ + + +/**Function******************************************************************** + + Synopsis [Registers a new hook with the manager.] + + SideEffects [] + +******************************************************************************/ +/*ARGSUSED*/ +void +bdd_register_daemon(mgr, daemon) +bdd_manager *mgr; +void (*daemon)(); +{ + fprintf(stderr,"CU DD Package: bdd_register_daemon translated to no-op.\n"); + return; + +} /* end of bdd_register_daemon */ + + +/**Function******************************************************************** + + Synopsis [Turns on or off garbage collection.] + + SideEffects [] + +******************************************************************************/ +void +bdd_set_gc_mode(mgr, no_gc) +bdd_manager *mgr; +boolean no_gc; +{ + if (no_gc) { + Cudd_DisableGarbageCollection(mgr); + } else { + Cudd_EnableGarbageCollection(mgr); + } + return; + +} /* end of bdd_set_gc_mode */ + + +/**Function******************************************************************** + + Synopsis [Reorders the BDD pool.] + + SideEffects [] + +******************************************************************************/ +void +bdd_dynamic_reordering(mgr, algorithm_type) +bdd_manager *mgr; +bdd_reorder_type_t algorithm_type; +{ + switch (algorithm_type) { + case BDD_REORDER_SIFT: + mgr->autoMethod = CUDD_REORDER_SIFT; + mgr->autoDyn = 1; + break; + case BDD_REORDER_WINDOW: + case BDD_REORDER_WINDOW4: + mgr->autoMethod = CUDD_REORDER_WINDOW4; + mgr->autoDyn = 1; + break; + case BDD_REORDER_NONE: + mgr->autoDyn = 0; + break; + case BDD_REORDER_SAME: + mgr->autoDyn = 1; + break; + case BDD_REORDER_RANDOM: + mgr->autoMethod = CUDD_REORDER_RANDOM; + mgr->autoDyn = 1; + break; + case BDD_REORDER_RANDOM_PIVOT: + mgr->autoMethod = CUDD_REORDER_RANDOM_PIVOT; + mgr->autoDyn = 1; + break; + case BDD_REORDER_SIFT_CONVERGE: + mgr->autoMethod = CUDD_REORDER_SIFT_CONVERGE; + mgr->autoDyn = 1; + break; + case BDD_REORDER_SYMM_SIFT: + mgr->autoMethod = CUDD_REORDER_SYMM_SIFT; + mgr->autoDyn = 1; + break; + case BDD_REORDER_SYMM_SIFT_CONV: + mgr->autoMethod = CUDD_REORDER_SYMM_SIFT_CONV; + mgr->autoDyn = 1; + break; + case BDD_REORDER_WINDOW2: + mgr->autoMethod = CUDD_REORDER_WINDOW2; + mgr->autoDyn = 1; + break; + case BDD_REORDER_WINDOW3: + mgr->autoMethod = CUDD_REORDER_WINDOW3; + mgr->autoDyn = 1; + break; + case BDD_REORDER_WINDOW2_CONV: + mgr->autoMethod = CUDD_REORDER_WINDOW2_CONV; + mgr->autoDyn = 1; + break; + case BDD_REORDER_WINDOW3_CONV: + mgr->autoMethod = CUDD_REORDER_WINDOW3_CONV; + mgr->autoDyn = 1; + break; + case BDD_REORDER_WINDOW4_CONV: + mgr->autoMethod = CUDD_REORDER_WINDOW4_CONV; + mgr->autoDyn = 1; + break; + case BDD_REORDER_GROUP_SIFT: + mgr->autoMethod = CUDD_REORDER_GROUP_SIFT; + mgr->autoDyn = 1; + break; + case BDD_REORDER_GROUP_SIFT_CONV: + mgr->autoMethod = CUDD_REORDER_GROUP_SIFT_CONV; + mgr->autoDyn = 1; + break; + case BDD_REORDER_ANNEALING: + mgr->autoMethod = CUDD_REORDER_ANNEALING; + mgr->autoDyn = 1; + break; + case BDD_REORDER_GENETIC: + mgr->autoMethod = CUDD_REORDER_GENETIC; + mgr->autoDyn = 1; + break; + default: + fprintf(stderr,"CU DD Package: Reordering algorithm not considered\n"); + } + +} /* end of bdd_dynamic_reordering */ + + +/**Function******************************************************************** + + Synopsis [Calls reordering explicitly.] + + SideEffects [] + +******************************************************************************/ +void +bdd_reorder(mgr) +bdd_manager *mgr; +{ + (void) Cudd_ReduceHeap(mgr,mgr->autoMethod,10); /* 10 = whatever (Verbatim from file ddTable.c) */ + return; + +} /* end of bdd_reorder */ + + +/**Function******************************************************************** + + Synopsis [Read the number of reorderings the package has performed + so far.] + + SideEffects [] + +******************************************************************************/ +int +bdd_read_reorderings(mgr) +bdd_manager *mgr; +{ + return Cudd_ReadReorderings((DdManager *)mgr); + +} /* end of bdd_read_reorderings */ + + +/**Function******************************************************************** + + Synopsis [Gets the id variable for one level in the BDD.] + + SideEffects [] + +******************************************************************************/ +bdd_variableId +bdd_get_id_from_level(mgr, level) +bdd_manager *mgr; +long level; +{ + return(mgr->invperm[level]); + +} /* end of bdd_get_id_from_level */ + + +/**Function******************************************************************** + + Synopsis [Gets the level of the top variable of the BDD.] + + SideEffects [] + +******************************************************************************/ +long +bdd_top_var_level(mgr, fn) +bdd_manager *mgr; +bdd_t *fn; +{ + return((long) cuddI(mgr,Cudd_Regular(fn->node)->index)); + +} /* end of bdd_top_var_level */ + + +/**Function******************************************************************** + + Synopsis [Returns TRUE if the argument BDD is a cube; FALSE + otherwise.] + + SideEffects [] + +******************************************************************************/ +boolean +bdd_is_cube(f) +bdd_t *f; +{ + struct DdManager *manager; + + if (f == NULL) { + fail("bdd_is_cube: invalid BDD"); + } + if (f->free) fail ("Freed BDD passed to bdd_is_cube"); + manager = (DdManager *) f->mgr; + return((boolean)cuddCheckCube(manager,f->node)); + +} /* end of bdd_is_cube */ + + +/**Function******************************************************************** + + Synopsis [Calls the garbage collector explicitly.] + + SideEffects [] + +******************************************************************************/ +void +bdd_gc(mgr) +bdd_manager *mgr; +{ + cuddGarbageCollect(mgr,1); + +} /* end of bdd_gc */ + + +/**Function******************************************************************** + + Synopsis [Computes the shared size of an array of BDDs.] + + Description [Computes the shared size of an array of BDDs. Returns + CUDD_OUT_OF_MEM in case of failure.] + + SideEffects [] + +******************************************************************************/ +long +bdd_size_multiple(bddArray) +array_t *bddArray; +{ + DdNode **nodeArray; + bdd_t *bddUnit; + long result; + int i; + + nodeArray = ALLOC(DdNode *, array_n(bddArray)); + if (nodeArray == NULL) return(CUDD_OUT_OF_MEM); + for (i = 0; i < array_n(bddArray); i++) { + bddUnit = array_fetch(bdd_t *, bddArray, i); + nodeArray[i] = bddUnit->node; + } + + result = Cudd_SharingSize(nodeArray,array_n(bddArray)); + + /* Clean up */ + FREE(nodeArray); + + return(result); + +} /* end of bdd_size_multiple */ + + +/**Function******************************************************************** + + Synopsis [Returns the first cube of the function. + A generator is also returned, which will iterate over the rest.] + + Description [Defines an iterator on the onset of a BDD. Two routines + are provided: bdd_first_cube, which extracts one cube from a BDD and + returns a bdd_gen structure containing the information necessary to + continue the enumeration; and bdd_next_cube, which returns 1 if + another cube was found, and 0 otherwise. A cube is represented as an + array of bdd_literal (which are integers in {0, 1, 2}), where 0 + represents negated literal, 1 for literal, and 2 for don't care. + Returns a disjoint cover. A third routine is there to clean up.] + + SideEffects [] + + SeeAlso [bdd_next_cube bdd_gen_free] + +******************************************************************************/ +bdd_gen * +bdd_first_cube(fn, cube) +bdd_t *fn; +array_t **cube; /* of bdd_literal */ +{ + bdd_manager *manager; + bdd_gen *gen; + int i; + int *icube; + CUDD_VALUE_TYPE value; + + /* Make sure we receive a valid bdd_t. (So to speak.) */ + assert(fn != 0); + + manager = fn->mgr; + + /* Initialize the generator. */ + gen = ALLOC(bdd_gen,1); + if (gen == NULL) return(NULL); + gen->manager = manager; + + gen->cube = array_alloc(bdd_literal, manager->size); + if (gen->cube == NULL) { + fail("Bdd Package: Out of memory in bdd_first_cube"); + } + + gen->ddGen = Cudd_FirstCube(manager,fn->node,&icube,&value); + if (gen->ddGen == NULL) { + fail("Cudd Package: Out of memory in bdd_first_cube"); + } + + if (!Cudd_IsGenEmpty(gen->ddGen)) { + /* Copy icube to the array_t cube. */ + for (i = 0; i < manager->size; i++) { + int myconst = icube[i]; + array_insert(bdd_literal, gen->cube, i, myconst); + } + *cube = gen->cube; + } + + return(gen); + +} /* end of bdd_first_cube */ + + +/**Function******************************************************************** + + Synopsis [Gets the next cube on the generator. Returns {TRUE, + FALSE} when {more, no more}.] + + SideEffects [] + + SeeAlso [bdd_first_cube bdd_gen_free] + +******************************************************************************/ +boolean +bdd_next_cube(gen, cube) +bdd_gen *gen; +array_t **cube; /* of bdd_literal */ +{ + int retval; + int *icube; + CUDD_VALUE_TYPE value; + int i; + + retval = Cudd_NextCube(gen->ddGen,&icube,&value); + if (!Cudd_IsGenEmpty(gen->ddGen)) { + /* Copy icube to the array_t cube. */ + for (i = 0; i < gen->manager->size; i++) { + int myconst = icube[i]; + array_insert(bdd_literal, gen->cube, i, myconst); + } + *cube = gen->cube; + } + + return(retval); + +} /* end of bdd_next_cube */ + + +/**Function******************************************************************** + + Synopsis [Gets the first node in the BDD and returns a generator.] + + SideEffects [] + + SeeAlso [bdd_next_node] + +******************************************************************************/ +bdd_gen * +bdd_first_node(fn, node) +bdd_t *fn; +bdd_node **node; /* return */ +{ + bdd_manager *manager; + bdd_gen *gen; + + /* Make sure we receive a valid bdd_t. (So to speak.) */ + assert(fn != 0); + + manager = fn->mgr; + + /* Initialize the generator. */ + gen = ALLOC(bdd_gen,1); + if (gen == NULL) return(NULL); + gen->manager = manager; + gen->cube = NULL; + + gen->ddGen = Cudd_FirstNode(manager,fn->node,node); + if (gen->ddGen == NULL) { + fail("Cudd Package: Out of memory in bdd_first_node"); + } + + return(gen); + +} /* end of bdd_first_node */ + + +/**Function******************************************************************** + + Synopsis [Gets the next node in the BDD. Returns {TRUE, FALSE} when + {more, no more}.] + + SideEffects [] + + SeeAlso [bdd_first_node] + +******************************************************************************/ +boolean +bdd_next_node(gen, node) +bdd_gen *gen; +bdd_node **node; /* return */ +{ + return(Cudd_NextNode(gen->ddGen,node)); + +} /* end of bdd_next_node */ + + +/**Function******************************************************************** + + Synopsis [Frees up the space used by the generator. Returns an int + so that it is easier to fit in a foreach macro. Returns 0 (to make it + easy to put in expressions).] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +int +bdd_gen_free(gen) +bdd_gen *gen; +{ + if (gen->cube != NULL) array_free(gen->cube); + Cudd_GenFree(gen->ddGen); + FREE(gen); + return(0); + +} /* end of bdd_gen_free */ + + +/**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 [] + + SeeAlso [bdd_first_cube bdd_next_cube bdd_first_node bdd_next_node + bdd_gen_free] + +******************************************************************************/ +boolean +bdd_is_gen_empty(gen) +bdd_gen *gen; +{ + return(Cudd_IsGenEmpty(gen->ddGen)); + +} /* end of bdd_is_gen_empty */ + + +/**Function******************************************************************** + + Synopsis [Function that creates a variable of a given index.] + + SideEffects [] + +******************************************************************************/ +bdd_t * +bdd_var_with_index(manager, index) +bdd_manager *manager; +int index; +{ + DdNode *var; + + var = Cudd_bddIthVar(manager, index); + cuddRef(var); + return(bdd_construct_bdd_t(manager, var)); + +} /* end of bdd_var_with_index */ + + +/**Function******************************************************************** + + Synopsis [Temporary function that is empty.] + + SideEffects [] + +******************************************************************************/ +/*ARGSUSED*/ +void +bdd_new_var_block(f, n) +bdd_t *f; +long n; +{ + return; + +} /* end of bdd_new_var_block */ + + +/*---------------------------------------------------------------------------*/ +/* Definition of internal functions */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Definition of static functions */ +/*---------------------------------------------------------------------------*/ + + +/**Function******************************************************************** + + Synopsis [Builds the bdd_t structure.] + + Description [Builds the bdd_t structure from manager and node. + Assumes that the reference count of the node has already been + increased.] + + SideEffects [] + +******************************************************************************/ +static bdd_t * +bdd_construct_bdd_t(mgr,fn) +DdManager *mgr; +DdNode * fn; +{ + bdd_t *result; + + result = ALLOC(bdd_t, 1); + if (result == NULL) { + Cudd_RecursiveDeref(mgr,fn); + return(NULL); + } + result->mgr = mgr; + result->node = fn; + result->free = FALSE; + return(result); + +} /* end of bdd_construct_bdd_t */ diff --git a/distr/sis/cuddPwPt.c b/distr/sis/cuddPwPt.c new file mode 100644 index 0000000..823f7b9 --- /dev/null +++ b/distr/sis/cuddPwPt.c @@ -0,0 +1,147 @@ +/**CFile*********************************************************************** + + FileName [cuddPwPt.c] + + PackageName [cudd] + + Synopsis [Emulation functions for the power package in SIS.] + + Description [This file contains functions that are necessary for the + power package in SIS. This package directly calls a few functions of + the CMU BDD package. Therefore, functions with identical names and + equivalent functionality are provided here. + External procedures included in this file: +
            +
          • cmu_bdd_zero() +
          • cmu_bdd_one() +
          • cmu_bdd_if_index() +
          + Internal procedures included in this module: +
            +
          • +
          ] + + Author [Fabio Somenzi] + + Copyright [This file was created at the University of Colorado at + Boulder. The University of Colorado at Boulder makes no warranty + about the suitability of this software for any purpose. It is + presented on an AS IS basis.] + +******************************************************************************/ + +#include "util.h" +#include "array.h" +#include "st.h" +#include "cuddInt.h" +#include "cuddBdd.h" + +/*---------------------------------------------------------------------------*/ +/* Constant declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Stucture declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Type declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Variable declarations */ +/*---------------------------------------------------------------------------*/ + +#ifndef lint +static char rcsid[] DD_UNUSED = "$Id: cuddPwPt.c,v 1.3 1997/01/18 19:43:19 fabio Exp $"; +#endif + +/*---------------------------------------------------------------------------*/ +/* Macro declarations */ +/*---------------------------------------------------------------------------*/ + +/**AutomaticStart*************************************************************/ + +/*---------------------------------------------------------------------------*/ +/* Static function prototypes */ +/*---------------------------------------------------------------------------*/ + +/**AutomaticEnd***************************************************************/ + + +/*---------------------------------------------------------------------------*/ +/* Definition of exported functions */ +/*---------------------------------------------------------------------------*/ + + +/**Function******************************************************************** + + Synopsis [Returns a pointer to the one constant.] + + Description [Returns a pointer to the one constant. Used by the power + package in SIS. For new code, use Cudd_ReadOne instead.] + + SideEffects [None] + + SeeAlso [Cudd_ReadOne] + +******************************************************************************/ +bdd_node * +cmu_bdd_one(dd) +bdd_manager *dd; +{ + return((bdd_node *)((DdManager *)dd)->one); + +} /* end of cmu_bdd_one */ + + +/**Function******************************************************************** + + Synopsis [Returns a pointer to the zero constant.] + + Description [Returns a pointer to the zero constant. Used by the power + package in SIS. For new code, use Cudd_ReadZero instead.] + + SideEffects [None] + + SeeAlso [Cudd_ReadZero] + +******************************************************************************/ +bdd_node * +cmu_bdd_zero(dd) +bdd_manager *dd; +{ + return((bdd_node *)Cudd_Not(((DdManager *)dd)->one)); + +} /* end of cmu_bdd_zero */ + + +/**Function******************************************************************** + + Synopsis [Returns the index of the top variable in a BDD.] + + Description [Returns the index of the top variable in a BDD. Used by + the power package in SIS. For new code, use Cudd_ReadIndex instead.] + + SideEffects [None] + + SeeAlso [Cudd_ReadIndex] + +******************************************************************************/ +int +cmu_bdd_if_index(dd, node) +bdd_manager *dd; +bdd_node *node; +{ + return(Cudd_Regular(node)->index); + +} /* end of cmu_bdd_if_index */ + + +/*---------------------------------------------------------------------------*/ +/* Definition of internal functions */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Definition of static functions */ +/*---------------------------------------------------------------------------*/ diff --git a/distr/sis/st.c b/distr/sis/st.c new file mode 100644 index 0000000..426c79c --- /dev/null +++ b/distr/sis/st.c @@ -0,0 +1,554 @@ +/* + * Revision Control Information + * + * /projects/hsis/CVS/utilities/st/st.c,v + * serdar + * 1.1 + * 1993/07/29 01:00:13 + * + */ +#include +#include "util.h" +#include "st.h" + +#define ST_NUMCMP(x,y) ((x) != (y)) +#define ST_NUMHASH(x,size) (ABS((long)x)%(size)) +#define ST_PTRHASH(x,size) ((int)((unsigned long)(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)\ + ((int)((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 *); + +st_table * +st_init_table_with_params( + ST_PFICPCP compare, + ST_PFICPI hash, + int size, + int density, + double grow_factor, + int reorder_flag) +{ + int i; + st_table *newt; + + newt = ALLOC(st_table, 1); + if (newt == NIL(st_table)) { + return NIL(st_table); + } + newt->compare = (int (*)(const char *, const char *)) compare; + newt->hash = (int (*)(char *, int)) hash; + newt->num_entries = 0; + newt->max_density = density; + newt->grow_factor = grow_factor; + newt->reorder_flag = reorder_flag; + if (size <= 0) { + size = 1; + } + newt->num_bins = size; + newt->bins = ALLOC(st_table_entry *, size); + if (newt->bins == NIL(st_table_entry *)) { + FREE(newt); + return NIL(st_table); + } + for(i = 0; i < size; i++) { + newt->bins[i] = 0; + } + return newt; +} + +st_table * +st_init_table(ST_PFICPCP compare, ST_PFICPI 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) +{ + register st_table_entry *ptr, *next; + int i; + + for(i = 0; i < table->num_bins ; i++) { + ptr = table->bins[i]; + while (ptr != NIL(st_table_entry)) { + next = ptr->next; + FREE(ptr); + ptr = next; + } + } + FREE(table->bins); + 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, char *key, char **value) +{ + int hash_val; + register st_table_entry *ptr, **last; + + hash_val = do_hash(key, table); + + FIND_ENTRY(table, hash_val, key, ptr, last); + + if (ptr == NIL(st_table_entry)) { + return 0; + } else { + if (value != NIL(char *)) { + *value = ptr->record; + } + return 1; + } +} + +int +st_lookup_int(st_table *table, char *key, int *value) +{ + int hash_val; + register st_table_entry *ptr, **last; + + hash_val = do_hash(key, table); + + FIND_ENTRY(table, hash_val, key, ptr, last); + + if (ptr == NIL(st_table_entry)) { + return 0; + } else { + if (value != NIL(int)) { + *value = (int) (util_ptrint) 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, newt)\ +{\ + if (table->num_entries/table->num_bins >= table->max_density) {\ + rehash(table);\ + hash_val = do_hash(key,table);\ + }\ + \ + newt = ALLOC(st_table_entry, 1);\ + \ + newt->key = key;\ + newt->record = value;\ + newt->next = table->bins[hash_val];\ + table->bins[hash_val] = newt;\ + table->num_entries++;\ +} + +int +st_insert(st_table *table, char *key, char *value) +{ + int hash_val; + st_table_entry *newt; + register st_table_entry *ptr, **last; + + hash_val = do_hash(key, table); + + FIND_ENTRY(table, hash_val, key, ptr, last); + + if (ptr == NIL(st_table_entry)) { + 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); + } + newt = ALLOC(st_table_entry, 1); + if (newt == NIL(st_table_entry)) { + return ST_OUT_OF_MEM; + } + newt->key = key; + newt->record = value; + newt->next = table->bins[hash_val]; + table->bins[hash_val] = newt; + 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 *newt; + + 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); + newt = ALLOC(st_table_entry, 1); + if (newt == NIL(st_table_entry)) { + return ST_OUT_OF_MEM; + } + newt->key = key; + newt->record = value; + newt->next = table->bins[hash_val]; + table->bins[hash_val] = newt; + table->num_entries++; + return 1; +} + +int +st_find_or_add(st_table *table, char *key, char ***slot) +{ + int hash_val; + st_table_entry *newt, *ptr, **last; + + hash_val = do_hash(key, table); + + FIND_ENTRY(table, hash_val, key, ptr, last); + + if (ptr == NIL(st_table_entry)) { + 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); + } + newt = ALLOC(st_table_entry, 1); + if (newt == NIL(st_table_entry)) { + return ST_OUT_OF_MEM; + } + newt->key = key; + newt->record = (char *) 0; + newt->next = table->bins[hash_val]; + table->bins[hash_val] = newt; + table->num_entries++; + if (slot != NIL(char **)) *slot = &newt->record; + return 0; + } else { + if (slot != NIL(char **)) *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 == NIL(st_table_entry)) { + return 0; + } else { + if (slot != NIL(char **)) { + *slot = &ptr->record; + } + return 1; + } +} + +static int +rehash(st_table *table) +{ + register 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 = ALLOC(st_table_entry *, table->num_bins); + if (table->bins == NIL(st_table_entry *)) { + 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 != NIL(st_table_entry)) { + 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; + } + } + FREE(old_bins); + + return 1; +} + +st_table * +st_copy(st_table *old_table) +{ + st_table *new_table; + st_table_entry *ptr, *newptr, *next, *newt; + int i, j, num_bins = old_table->num_bins; + + new_table = ALLOC(st_table, 1); + if (new_table == NIL(st_table)) { + return NIL(st_table); + } + + *new_table = *old_table; + new_table->bins = ALLOC(st_table_entry *, num_bins); + if (new_table->bins == NIL(st_table_entry *)) { + FREE(new_table); + return NIL(st_table); + } + for(i = 0; i < num_bins ; i++) { + new_table->bins[i] = NIL(st_table_entry); + ptr = old_table->bins[i]; + while (ptr != NIL(st_table_entry)) { + newt = ALLOC(st_table_entry, 1); + if (newt == NIL(st_table_entry)) { + for (j = 0; j <= i; j++) { + newptr = new_table->bins[j]; + while (newptr != NIL(st_table_entry)) { + next = newptr->next; + FREE(newptr); + newptr = next; + } + } + FREE(new_table->bins); + FREE(new_table); + return NIL(st_table); + } + *newt = *ptr; + newt->next = new_table->bins[i]; + new_table->bins[i] = newt; + ptr = ptr->next; + } + } + return new_table; +} + +int +st_delete(st_table *table, char **keyp, char **value) +{ + int hash_val; + char *key = *keyp; + register st_table_entry *ptr, **last; + + hash_val = do_hash(key, table); + + FIND_ENTRY(table, hash_val, key, ptr ,last); + + if (ptr == NIL(st_table_entry)) { + return 0; + } + + *last = ptr->next; + if (value != NIL(char *)) *value = ptr->record; + *keyp = ptr->key; + FREE(ptr); + table->num_entries--; + return 1; +} + +int +st_delete_int(st_table *table, int *keyp, char **value) +{ + int hash_val; + char *key = (char *) (util_ptrint) *keyp; + register st_table_entry *ptr, **last; + + hash_val = do_hash(key, table); + + FIND_ENTRY(table, hash_val, key, ptr ,last); + + if (ptr == NIL(st_table_entry)) { + return 0; + } + + *last = ptr->next; + if (value != NIL(char *)) *value = ptr->record; + *keyp = (int) (util_ptrint) ptr->key; + FREE(ptr); + table->num_entries--; + return 1; +} + +int +st_foreach(st_table *table, ST_PFSR func, 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 != NIL(st_table_entry)) { + 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 */ + FREE(ptr); + ptr = *last; + } + } + } + return 1; +} + +int +st_strhash(char *string, int modulus) +{ + register int val = 0; + register int c; + + while ((c = *string++) != '\0') { + val = val*997 + c; + } + + return ((val < 0) ? -val : val)%modulus; +} + +int +st_numhash(char *x, int size) +{ + return ST_NUMHASH(x, size); +} + +int +st_ptrhash(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 = ALLOC(st_generator, 1); + if (gen == NIL(st_generator)) { + return NIL(st_generator); + } + gen->table = table; + gen->entry = NIL(st_table_entry); + gen->index = 0; + return gen; +} + + +int +st_gen(st_generator *gen, char **key_p, char **value_p) +{ + register int i; + + if (gen->entry == NIL(st_table_entry)) { + /* try to find next entry */ + for(i = gen->index; i < gen->table->num_bins; i++) { + if (gen->table->bins[i] != NIL(st_table_entry)) { + gen->index = i+1; + gen->entry = gen->table->bins[i]; + break; + } + } + if (gen->entry == NIL(st_table_entry)) { + 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, char **key_p, long *value_p) +{ + register int i; + + if (gen->entry == NIL(st_table_entry)) { + /* try to find next entry */ + for(i = gen->index; i < gen->table->num_bins; i++) { + if (gen->table->bins[i] != NIL(st_table_entry)) { + gen->index = i+1; + gen->entry = gen->table->bins[i]; + break; + } + } + if (gen->entry == NIL(st_table_entry)) { + return 0; /* that's all folks ! */ + } + } + *key_p = gen->entry->key; + if (value_p != NIL(long)) { + *value_p = (long) gen->entry->record; + } + gen->entry = gen->entry->next; + return 1; +} + + +void +st_free_gen(st_generator *gen) +{ + FREE(gen); +} diff --git a/distr/sis/st.h b/distr/sis/st.h new file mode 100644 index 0000000..a1d8619 --- /dev/null +++ b/distr/sis/st.h @@ -0,0 +1,97 @@ +/* + * 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 ST_INCLUDED +#define ST_INCLUDED + +#ifdef __cplusplus +extern "C" { +#endif + +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 { + int (*compare)(const char *, const char *); + int (*hash)(char *, int); + 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_PFICPCP)(const char *, const char *); /* type for comparison function */ +typedef int (*ST_PFICPI)(char *, int); /* type for hash function */ + +extern st_table *st_init_table_with_params (ST_PFICPCP, ST_PFICPI, int, int, double, int); +extern st_table *st_init_table (ST_PFICPCP, ST_PFICPI); +extern void st_free_table (st_table *); +extern int st_lookup (st_table *, char *, char **); +extern int st_lookup_int (st_table *, char *, int *); +extern int st_insert (st_table *, 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 *, char **, char **); +extern int st_delete_int (st_table *, int *, char **); +extern int st_foreach (st_table *, ST_PFSR, char *); +extern int st_strhash (char *, int); +extern int st_numhash (char *, int); +extern int st_ptrhash (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 *, char **, char **); +extern int st_gen_int (st_generator *, 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 + +#ifdef __cplusplus +} +#endif + +#endif /* ST_INCLUDED */ diff --git a/distr/st/Makefile b/distr/st/Makefile new file mode 100644 index 0000000..5fdc949 --- /dev/null +++ b/distr/st/Makefile @@ -0,0 +1,64 @@ +# $Id: Makefile,v 1.3 2004/01/01 06:53:06 fabio Exp fabio $ +# +# st -- hash table package +#--------------------------------------------------------------------------- +.SUFFIXES: .c .o .u + +CC = gcc +RANLIB = ranlib + +MFLAG = +ICFLAGS = -g -O6 -Wall +CFLAGS = $(ICFLAGS) $(MFLAG) $(XCFLAGS) + +LINTFLAGS = -u -n + +# this is to create the lint library +LINTSWITCH = -o + +P = st +PSRC = st.c +PHDR = st.h +POBJ = $(PSRC:.c=.o) +PUBJ = $(PSRC:.c=.u) + +WHERE = .. +INCLUDE = $(WHERE)/include + +#--------------------------- + +lib$(P).a: $(POBJ) + ar rv $@ $? + $(RANLIB) $@ + +.c.o: $(PHDR) + $(CC) -c $< -I$(INCLUDE) $(CFLAGS) + +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) + +lint: llib-l$(P).ln + +llib-l$(P).ln: $(PSRC) $(PHDR) + lint $(LINTFLAGS) $(LINTSWITCH)$(P) -I$(INCLUDE) $(PSRC) + +tags: $(PSRC) $(PHDR) + ctags $(PSRC) $(PHDR) + +all: lib$(P).a lib$(P).b llib-l$(P).ln tags + +clean: + rm -f *.o *.u .pure *.warnings + +distclean: clean + rm -f lib*.a lib$(P).b llib-l$(P).ln tags *~ *.bak *.qv *.qx diff --git a/distr/st/doc/stAllAbs.html b/distr/st/doc/stAllAbs.html new file mode 100644 index 0000000..927c116 --- /dev/null +++ b/distr/st/doc/stAllAbs.html @@ -0,0 +1,96 @@ + +st package abstract (Internal) + + +

          st package abstract (Internal)

          +

          +
          + + + +
          +
          st_add_direct() +
          Place 'value' in 'table' under the key 'key'. + +
          st_copy() +
          Return a copy of old_table and all its members. + +
          st_count() +
          Returns the number of entries in the table `table'. + +
          st_delete_int() +
          Delete the entry with the key pointed to by `keyp'. + +
          st_delete() +
          Delete the entry with the key pointed to by `keyp'. + +
          st_find_or_add() +
          Lookup `key' in `table'. + +
          st_find() +
          Lookup `key' in `table'. + +
          st_foreach_item_int() +
          Iteration macro. + +
          st_foreach_item() +
          Iteration macro. + +
          st_foreach() +
          Iterates over the elements of a table. + +
          st_free_gen() +
          Reclaims the resources associated with `gen'. + +
          st_free_table() +
          Free a table. + +
          st_gen_int() +
          Returns the next (key, value) pair in the generation sequence. + +
          st_gen() +
          returns the next (key, value) pair in the generation sequence. + +
          st_init_gen() +
          Initializes a generator. + +
          st_init_table_with_params() +
          Create a table with given parameters. + +
          st_init_table() +
          Create and initialize a table. + +
          st_insert() +
          Insert value in table under the key 'key'. + +
          st_is_member() +
          Checks whethere `key' is in `table'. + +
          st_lookup_int() +
          Lookup up `key' in `table'. + +
          st_lookup() +
          Lookup up `key' in `table'. + +
          st_numcmp() +
          Number comparison function. + +
          st_numhash() +
          Number hash function. + +
          st_ptrcmp() +
          Pointer comparison function. + +
          st_ptrhash() +
          Pointer hash function. + +
          st_strhash() +
          String hash function. + +
          + +
          + +Generated automatically by extdoc on 20040102 + + diff --git a/distr/st/doc/stAllDet.html b/distr/st/doc/stAllDet.html new file mode 100644 index 0000000..e56d883 --- /dev/null +++ b/distr/st/doc/stAllDet.html @@ -0,0 +1,462 @@ + +The st package (Internal) + + +

          The st package (Internal)

          +

          +

          +
          + + +
          + + + + + +
          + + +
          + +
          +int 
          +st_add_direct(
          +  st_table * table, 
          +  void * key, 
          +  void * value 
          +)
          +
          +
          Place 'value' in 'table' under the key 'key'. This is done without checking if 'key' is in 'table' already. This should only be used if you are sure there is not already an entry for 'key', since it is undefined which entry you would later get from st_lookup or st_find_or_add. Returns 1 if successful; ST_OUT_OF_MEM otherwise. +

          + +

          Side Effects None +

          + +

          +st_table * 
          +st_copy(
          +  st_table * old_table 
          +)
          +
          +
          Return a copy of old_table and all its members. (st_table *) 0 is returned if there was insufficient memory to do the copy. +

          + +

          Side Effects None +

          + +

          + 
          +st_count(
          +   table 
          +)
          +
          +
          Returns the number of entries in the table `table'. +

          + +

          Side Effects None +

          + +

          +int 
          +st_delete_int(
          +  st_table * table, 
          +  void * keyp, 
          +  int * value 
          +)
          +
          +
          Delete the entry with the key pointed to by `keyp'. `value' must be a pointer to an integer. If the entry is found, 1 is returned, the variable pointed by `keyp' is set to the actual key and the variable pointed by `value' is set to the corresponding entry. (This allows the freeing of the associated storage.) If the entry is not found, then 0 is returned and nothing is changed. +

          + +

          Side Effects None +

          + +

          See Also st_delete + + +
          +int 
          +st_delete(
          +  st_table * table, 
          +  void * keyp, 
          +  void * value 
          +)
          +
          +
          Delete the entry with the key pointed to by `keyp'. If the entry is found, 1 is returned, the variable pointed by `keyp' is set to the actual key and the variable pointed by `value' is set to the corresponding entry. (This allows the freeing of the associated storage.) If the entry is not found, then 0 is returned and nothing is changed. +

          + +

          Side Effects None +

          + +

          See Also st_delete_int + + +
          +int 
          +st_find_or_add(
          +  st_table * table, 
          +  void * key, 
          +  void * slot 
          +)
          +
          +
          Lookup `key' in `table'. If not found, create an entry. In either case set slot to point to the field in the entry where the value is stored. The value associated with `key' may then be changed by accessing directly through slot. Returns 1 if an entry already existed, 0 if it did not exist and creation was successful; ST_OUT_OF_MEM otherwise. As an example:
           char **slot; 
           char *key; 
           char *value = (char *) item_ptr <-- ptr to a malloc'd structure 
           if (st_find_or_add(table, key, &slot) == 1) { 
           FREE(*slot); <-- free the old value of the record 
           } 
           *slot = value; <-- attach the new value to the record 
          This replaces the equivelent code:
           if (st_lookup(table, key, &ovalue) == 1) { 
           FREE(ovalue); 
           } 
           st_insert(table, key, value); 
          +

          + +

          Side Effects None +

          + +

          See Also st_find + + +
          +int 
          +st_find(
          +  st_table * table, 
          +  void * key, 
          +  void * slot 
          +)
          +
          +
          Like st_find_or_add, but does not create an entry if one is not found. +

          + +

          Side Effects None +

          + +

          See Also st_find_or_add + + +
          + 
          +st_foreach_item_int(
          +   table, 
          +   gen, 
          +   key, 
          +   value 
          +)
          +
          +
          An iteration macro which loops over all the entries in `table', setting `key' to point to the key and `value' to the associated value (if it is not nil). `value' is assumed to be a pointer to an integer. `gen' is a generator variable used internally. Sample usage:
           char *key; 
           int value; 
           st_generator *gen; 
           st_foreach_item_int(table, gen, &key, &value) { 
           process_item(value); 
           } 
          +

          + +

          Side Effects None +

          + +

          See Also st_foreach_item +st_foreach + + +
          + 
          +st_foreach_item(
          +   table, 
          +   gen, 
          +   key, 
          +   value 
          +)
          +
          +
          An iteration macro which loops over all the entries in `table', setting `key' to point to the key and `value' to the associated value (if it is not nil). `gen' is a generator variable used internally. Sample usage:
           char *key, *value; 
           st_generator *gen; 
           st_foreach_item(table, gen, &key, &value) { 
           process_item(value); 
           } 
          +

          + +

          Side Effects None +

          + +

          See Also st_foreach_item_int +st_foreach + + +
          +int 
          +st_foreach(
          +  st_table * table, 
          +  ST_PFSR  func, 
          +  char * arg 
          +)
          +
          +
          For each (key, value) record in `table', st_foreach call func with the arguments
           (*func)(key, value, arg) 
          If func returns ST_CONTINUE, st_foreach continues processing entries. If func returns ST_STOP, st_foreach stops processing and returns immediately. If func returns ST_DELETE, then the entry is deleted from the symbol table and st_foreach continues. In the case of ST_DELETE, it is func's responsibility to free the key and value, if necessary.

          The routine returns 1 if all items in the table were generated and 0 if the generation sequence was aborted using ST_STOP. The order in which the records are visited will be seemingly random. +

          + +

          Side Effects None +

          + +

          See Also st_foreach_item +st_foreach_item_int + + +
          +void 
          +st_free_gen(
          +  st_generator * gen 
          +)
          +
          +
          After generating all items in a generation sequence, this routine must be called to reclaim the resources associated with `gen'. +

          + +

          Side Effects None +

          + +

          See Also st_init_gen + + +
          +void 
          +st_free_table(
          +  st_table * table 
          +)
          +
          +
          Any internal storage associated with table is freed. It is the user's responsibility to free any storage associated with the pointers he placed in the table (by perhaps using st_foreach). +

          + +

          Side Effects None +

          + +

          See Also st_init_table +st_init_table_with_params + + +
          +int 
          +st_gen_int(
          +  st_generator * gen, 
          +  void * key_p, 
          +  int * value_p 
          +)
          +
          +
          Given a generator returned by st_init_gen(), this routine returns the next (key, value) pair in the generation sequence. `value_p' must be a pointer to an integer. The pointer `value_p' can be zero which means no value will be returned. When there are no more items in the generation sequence, the routine returns 0. +

          + +

          Side Effects None +

          + +

          See Also st_gen + + +
          +int 
          +st_gen(
          +  st_generator * gen, 
          +  void * key_p, 
          +  void * value_p 
          +)
          +
          +
          Given a generator returned by st_init_gen(), this routine returns the next (key, value) pair in the generation sequence. The pointer `value_p' can be zero which means no value will be returned. When there are no more items in the generation sequence, the routine returns 0. While using a generation sequence, deleting any (key, value) pair other than the one just generated may cause a fatal error when st_gen() is called later in the sequence and is therefore not recommended. +

          + +

          Side Effects None +

          + +

          See Also st_gen_int + + +
          +st_generator * 
          +st_init_gen(
          +  st_table * table 
          +)
          +
          +
          Returns a generator handle which when used with st_gen() will progressively return each (key, value) record in `table'. +

          + +

          Side Effects None +

          + +

          See Also st_free_gen + + +
          +st_table * 
          +st_init_table_with_params(
          +  ST_PFICPCP  compare, 
          +  ST_PFICPI  hash, 
          +  int  size, 
          +  int  density, 
          +  double  grow_factor, 
          +  int  reorder_flag 
          +)
          +
          +
          The full blown table initializer. compare and hash are the same as in st_init_table. density is the largest the average number of entries per hash bin there should be before the table is grown. grow_factor is the factor the table is grown by when it becomes too full. size is the initial number of bins to be allocated for the hash table. If reorder_flag is non-zero, then every time an entry is found, it is moved to the top of the chain.

          st_init_table(compare, hash) is equivelent to

           st_init_table_with_params(compare, hash, ST_DEFAULT_INIT_TABLE_SIZE, ST_DEFAULT_MAX_DENSITY, ST_DEFAULT_GROW_FACTOR, ST_DEFAULT_REORDER_FLAG); 
          +

          + +

          Side Effects None +

          + +

          See Also st_init_table +st_free_table + + +
          +st_table * 
          +st_init_table(
          +  ST_PFICPCP  compare, 
          +  ST_PFICPI  hash 
          +)
          +
          +
          Create and initialize a table with the comparison function compare_fn and hash function hash_fn. compare_fn is
           int compare_fn(const char *key1, const char *key2) 
          It returns <,=,> 0 depending on whether key1 <,=,> key2 by some measure.

          hash_fn is

           int hash_fn(char *key, int modulus) 
          It returns a integer between 0 and modulus-1 such that if compare_fn(key1,key2) == 0 then hash_fn(key1) == hash_fn(key2).

          There are five predefined hash and comparison functions in st. For keys as numbers:

           st_numhash(key, modulus) { return (unsigned int) key % modulus; } 
           st_numcmp(x,y) { return (int) x - (int) y; } 
          For keys as pointers:
           st_ptrhash(key, modulus) { return ((unsigned int) key/4) % modulus } 
           st_ptrcmp(x,y) { return (int) x - (int) y; } 
          For keys as strings:
           st_strhash(x,y) - a reasonable hashing function for strings 
           strcmp(x,y) - the standard library function 
          It is recommended to use these particular functions if they fit your needs, since st will recognize certain of them and run more quickly because of it. +

          + +

          Side Effects None +

          + +

          See Also st_init_table_with_params +st_free_table + + +
          +int 
          +st_insert(
          +  st_table * table, 
          +  void * key, 
          +  void * value 
          +)
          +
          +
          Insert value in table under the key 'key'. Returns 1 if there was an entry already under the key; 0 if there was no entry under the key and insertion was successful; ST_OUT_OF_MEM otherwise. In either of the first two cases the new value is added. +

          + +

          Side Effects None +

          + +

          + 
          +st_is_member(
          +   table, 
          +   key 
          +)
          +
          +
          Returns 1 if there is an entry under `key' in `table', 0 otherwise. +

          + +

          Side Effects None +

          + +

          See Also st_lookup + + +
          +int 
          +st_lookup_int(
          +  st_table * table, 
          +  void * key, 
          +  int * value 
          +)
          +
          +
          Lookup up `key' in `table'. If an entry is found, 1 is returned and if `value' is not nil, the variable it points to is set to the associated integer value. If an entry is not found, 0 is return and the variable pointed by `value' is unchanged. +

          + +

          Side Effects None +

          + +

          See Also st_lookup + + +
          +int 
          +st_lookup(
          +  st_table * table, 
          +  void * key, 
          +  void * value 
          +)
          +
          +
          Lookup up `key' in `table'. If an entry is found, 1 is returned and if `value' is not nil, the variable it points to is set to the associated value. If an entry is not found, 0 is returned and the variable pointed by value is unchanged. +

          + +

          Side Effects None +

          + +

          See Also st_lookup_int + + +
          +int 
          +st_numcmp(
          +  const char * x, 
          +  const char * y 
          +)
          +
          +
          integer number comparison function. +

          + +

          Side Effects None +

          + +

          See Also st_init_table +st_numhash + + +
          +int 
          +st_numhash(
          +  char * x, 
          +  int  size 
          +)
          +
          +
          Integer number hash function. +

          + +

          Side Effects None +

          + +

          See Also st_init_table +st_numcmp + + +
          +int 
          +st_ptrcmp(
          +  const char * x, 
          +  const char * y 
          +)
          +
          +
          Pointer comparison function. +

          + +

          Side Effects None +

          + +

          See Also st_init_table +st_ptrhash + + +
          +int 
          +st_ptrhash(
          +  char * x, 
          +  int  size 
          +)
          +
          +
          Pointer hash function. +

          + +

          Side Effects None +

          + +

          See Also st_init_table +st_ptrcmp + + +
          +int 
          +st_strhash(
          +  char * string, 
          +  int  modulus 
          +)
          +
          +
          String hash function. +

          + +

          Side Effects None +

          + +

          See Also st_init_table + + + +
          + +
          + +Generated automatically by extdoc on 20040102 + + diff --git a/distr/st/doc/stExtAbs.html b/distr/st/doc/stExtAbs.html new file mode 100644 index 0000000..5302461 --- /dev/null +++ b/distr/st/doc/stExtAbs.html @@ -0,0 +1,96 @@ + +st package abstract + + +

          st package abstract

          +

          Symbol table package.

          +
          + + + +
          +
          st_add_direct() +
          Place 'value' in 'table' under the key 'key'. + +
          st_copy() +
          Return a copy of old_table and all its members. + +
          st_count() +
          Returns the number of entries in the table `table'. + +
          st_delete_int() +
          Delete the entry with the key pointed to by `keyp'. + +
          st_delete() +
          Delete the entry with the key pointed to by `keyp'. + +
          st_find_or_add() +
          Lookup `key' in `table'. + +
          st_find() +
          Lookup `key' in `table'. + +
          st_foreach_item_int() +
          Iteration macro. + +
          st_foreach_item() +
          Iteration macro. + +
          st_foreach() +
          Iterates over the elements of a table. + +
          st_free_gen() +
          Reclaims the resources associated with `gen'. + +
          st_free_table() +
          Free a table. + +
          st_gen_int() +
          Returns the next (key, value) pair in the generation sequence. + +
          st_gen() +
          returns the next (key, value) pair in the generation sequence. + +
          st_init_gen() +
          Initializes a generator. + +
          st_init_table_with_params() +
          Create a table with given parameters. + +
          st_init_table() +
          Create and initialize a table. + +
          st_insert() +
          Insert value in table under the key 'key'. + +
          st_is_member() +
          Checks whethere `key' is in `table'. + +
          st_lookup_int() +
          Lookup up `key' in `table'. + +
          st_lookup() +
          Lookup up `key' in `table'. + +
          st_numcmp() +
          Number comparison function. + +
          st_numhash() +
          Number hash function. + +
          st_ptrcmp() +
          Pointer comparison function. + +
          st_ptrhash() +
          Pointer hash function. + +
          st_strhash() +
          String hash function. + +
          + +
          + +Generated automatically by extdoc on 20040102 + + diff --git a/distr/st/doc/stExtDet.html b/distr/st/doc/stExtDet.html new file mode 100644 index 0000000..43cb6f4 --- /dev/null +++ b/distr/st/doc/stExtDet.html @@ -0,0 +1,463 @@ + +The st package + + +

          The st package

          +

          Symbol table package.

          +

          +
          + + +
          + + +The st library provides functions to create, maintain, + and query symbol tables. + + +
          + + +
          + +
          +int 
          +st_add_direct(
          +  st_table * table, 
          +  void * key, 
          +  void * value 
          +)
          +
          +
          Place 'value' in 'table' under the key 'key'. This is done without checking if 'key' is in 'table' already. This should only be used if you are sure there is not already an entry for 'key', since it is undefined which entry you would later get from st_lookup or st_find_or_add. Returns 1 if successful; ST_OUT_OF_MEM otherwise. +

          + +

          Side Effects None +

          + +

          +st_table * 
          +st_copy(
          +  st_table * old_table 
          +)
          +
          +
          Return a copy of old_table and all its members. (st_table *) 0 is returned if there was insufficient memory to do the copy. +

          + +

          Side Effects None +

          + +

          + 
          +st_count(
          +   table 
          +)
          +
          +
          Returns the number of entries in the table `table'. +

          + +

          Side Effects None +

          + +

          +int 
          +st_delete_int(
          +  st_table * table, 
          +  void * keyp, 
          +  int * value 
          +)
          +
          +
          Delete the entry with the key pointed to by `keyp'. `value' must be a pointer to an integer. If the entry is found, 1 is returned, the variable pointed by `keyp' is set to the actual key and the variable pointed by `value' is set to the corresponding entry. (This allows the freeing of the associated storage.) If the entry is not found, then 0 is returned and nothing is changed. +

          + +

          Side Effects None +

          + +

          See Also st_delete + + +
          +int 
          +st_delete(
          +  st_table * table, 
          +  void * keyp, 
          +  void * value 
          +)
          +
          +
          Delete the entry with the key pointed to by `keyp'. If the entry is found, 1 is returned, the variable pointed by `keyp' is set to the actual key and the variable pointed by `value' is set to the corresponding entry. (This allows the freeing of the associated storage.) If the entry is not found, then 0 is returned and nothing is changed. +

          + +

          Side Effects None +

          + +

          See Also st_delete_int + + +
          +int 
          +st_find_or_add(
          +  st_table * table, 
          +  void * key, 
          +  void * slot 
          +)
          +
          +
          Lookup `key' in `table'. If not found, create an entry. In either case set slot to point to the field in the entry where the value is stored. The value associated with `key' may then be changed by accessing directly through slot. Returns 1 if an entry already existed, 0 if it did not exist and creation was successful; ST_OUT_OF_MEM otherwise. As an example:
           char **slot; 
           char *key; 
           char *value = (char *) item_ptr <-- ptr to a malloc'd structure 
           if (st_find_or_add(table, key, &slot) == 1) { 
           FREE(*slot); <-- free the old value of the record 
           } 
           *slot = value; <-- attach the new value to the record 
          This replaces the equivelent code:
           if (st_lookup(table, key, &ovalue) == 1) { 
           FREE(ovalue); 
           } 
           st_insert(table, key, value); 
          +

          + +

          Side Effects None +

          + +

          See Also st_find + + +
          +int 
          +st_find(
          +  st_table * table, 
          +  void * key, 
          +  void * slot 
          +)
          +
          +
          Like st_find_or_add, but does not create an entry if one is not found. +

          + +

          Side Effects None +

          + +

          See Also st_find_or_add + + +
          + 
          +st_foreach_item_int(
          +   table, 
          +   gen, 
          +   key, 
          +   value 
          +)
          +
          +
          An iteration macro which loops over all the entries in `table', setting `key' to point to the key and `value' to the associated value (if it is not nil). `value' is assumed to be a pointer to an integer. `gen' is a generator variable used internally. Sample usage:
           char *key; 
           int value; 
           st_generator *gen; 
           st_foreach_item_int(table, gen, &key, &value) { 
           process_item(value); 
           } 
          +

          + +

          Side Effects None +

          + +

          See Also st_foreach_item +st_foreach + + +
          + 
          +st_foreach_item(
          +   table, 
          +   gen, 
          +   key, 
          +   value 
          +)
          +
          +
          An iteration macro which loops over all the entries in `table', setting `key' to point to the key and `value' to the associated value (if it is not nil). `gen' is a generator variable used internally. Sample usage:
           char *key, *value; 
           st_generator *gen; 
           st_foreach_item(table, gen, &key, &value) { 
           process_item(value); 
           } 
          +

          + +

          Side Effects None +

          + +

          See Also st_foreach_item_int +st_foreach + + +
          +int 
          +st_foreach(
          +  st_table * table, 
          +  ST_PFSR  func, 
          +  char * arg 
          +)
          +
          +
          For each (key, value) record in `table', st_foreach call func with the arguments
           (*func)(key, value, arg) 
          If func returns ST_CONTINUE, st_foreach continues processing entries. If func returns ST_STOP, st_foreach stops processing and returns immediately. If func returns ST_DELETE, then the entry is deleted from the symbol table and st_foreach continues. In the case of ST_DELETE, it is func's responsibility to free the key and value, if necessary.

          The routine returns 1 if all items in the table were generated and 0 if the generation sequence was aborted using ST_STOP. The order in which the records are visited will be seemingly random. +

          + +

          Side Effects None +

          + +

          See Also st_foreach_item +st_foreach_item_int + + +
          +void 
          +st_free_gen(
          +  st_generator * gen 
          +)
          +
          +
          After generating all items in a generation sequence, this routine must be called to reclaim the resources associated with `gen'. +

          + +

          Side Effects None +

          + +

          See Also st_init_gen + + +
          +void 
          +st_free_table(
          +  st_table * table 
          +)
          +
          +
          Any internal storage associated with table is freed. It is the user's responsibility to free any storage associated with the pointers he placed in the table (by perhaps using st_foreach). +

          + +

          Side Effects None +

          + +

          See Also st_init_table +st_init_table_with_params + + +
          +int 
          +st_gen_int(
          +  st_generator * gen, 
          +  void * key_p, 
          +  int * value_p 
          +)
          +
          +
          Given a generator returned by st_init_gen(), this routine returns the next (key, value) pair in the generation sequence. `value_p' must be a pointer to an integer. The pointer `value_p' can be zero which means no value will be returned. When there are no more items in the generation sequence, the routine returns 0. +

          + +

          Side Effects None +

          + +

          See Also st_gen + + +
          +int 
          +st_gen(
          +  st_generator * gen, 
          +  void * key_p, 
          +  void * value_p 
          +)
          +
          +
          Given a generator returned by st_init_gen(), this routine returns the next (key, value) pair in the generation sequence. The pointer `value_p' can be zero which means no value will be returned. When there are no more items in the generation sequence, the routine returns 0. While using a generation sequence, deleting any (key, value) pair other than the one just generated may cause a fatal error when st_gen() is called later in the sequence and is therefore not recommended. +

          + +

          Side Effects None +

          + +

          See Also st_gen_int + + +
          +st_generator * 
          +st_init_gen(
          +  st_table * table 
          +)
          +
          +
          Returns a generator handle which when used with st_gen() will progressively return each (key, value) record in `table'. +

          + +

          Side Effects None +

          + +

          See Also st_free_gen + + +
          +st_table * 
          +st_init_table_with_params(
          +  ST_PFICPCP  compare, 
          +  ST_PFICPI  hash, 
          +  int  size, 
          +  int  density, 
          +  double  grow_factor, 
          +  int  reorder_flag 
          +)
          +
          +
          The full blown table initializer. compare and hash are the same as in st_init_table. density is the largest the average number of entries per hash bin there should be before the table is grown. grow_factor is the factor the table is grown by when it becomes too full. size is the initial number of bins to be allocated for the hash table. If reorder_flag is non-zero, then every time an entry is found, it is moved to the top of the chain.

          st_init_table(compare, hash) is equivelent to

           st_init_table_with_params(compare, hash, ST_DEFAULT_INIT_TABLE_SIZE, ST_DEFAULT_MAX_DENSITY, ST_DEFAULT_GROW_FACTOR, ST_DEFAULT_REORDER_FLAG); 
          +

          + +

          Side Effects None +

          + +

          See Also st_init_table +st_free_table + + +
          +st_table * 
          +st_init_table(
          +  ST_PFICPCP  compare, 
          +  ST_PFICPI  hash 
          +)
          +
          +
          Create and initialize a table with the comparison function compare_fn and hash function hash_fn. compare_fn is
           int compare_fn(const char *key1, const char *key2) 
          It returns <,=,> 0 depending on whether key1 <,=,> key2 by some measure.

          hash_fn is

           int hash_fn(char *key, int modulus) 
          It returns a integer between 0 and modulus-1 such that if compare_fn(key1,key2) == 0 then hash_fn(key1) == hash_fn(key2).

          There are five predefined hash and comparison functions in st. For keys as numbers:

           st_numhash(key, modulus) { return (unsigned int) key % modulus; } 
           st_numcmp(x,y) { return (int) x - (int) y; } 
          For keys as pointers:
           st_ptrhash(key, modulus) { return ((unsigned int) key/4) % modulus } 
           st_ptrcmp(x,y) { return (int) x - (int) y; } 
          For keys as strings:
           st_strhash(x,y) - a reasonable hashing function for strings 
           strcmp(x,y) - the standard library function 
          It is recommended to use these particular functions if they fit your needs, since st will recognize certain of them and run more quickly because of it. +

          + +

          Side Effects None +

          + +

          See Also st_init_table_with_params +st_free_table + + +
          +int 
          +st_insert(
          +  st_table * table, 
          +  void * key, 
          +  void * value 
          +)
          +
          +
          Insert value in table under the key 'key'. Returns 1 if there was an entry already under the key; 0 if there was no entry under the key and insertion was successful; ST_OUT_OF_MEM otherwise. In either of the first two cases the new value is added. +

          + +

          Side Effects None +

          + +

          + 
          +st_is_member(
          +   table, 
          +   key 
          +)
          +
          +
          Returns 1 if there is an entry under `key' in `table', 0 otherwise. +

          + +

          Side Effects None +

          + +

          See Also st_lookup + + +
          +int 
          +st_lookup_int(
          +  st_table * table, 
          +  void * key, 
          +  int * value 
          +)
          +
          +
          Lookup up `key' in `table'. If an entry is found, 1 is returned and if `value' is not nil, the variable it points to is set to the associated integer value. If an entry is not found, 0 is return and the variable pointed by `value' is unchanged. +

          + +

          Side Effects None +

          + +

          See Also st_lookup + + +
          +int 
          +st_lookup(
          +  st_table * table, 
          +  void * key, 
          +  void * value 
          +)
          +
          +
          Lookup up `key' in `table'. If an entry is found, 1 is returned and if `value' is not nil, the variable it points to is set to the associated value. If an entry is not found, 0 is returned and the variable pointed by value is unchanged. +

          + +

          Side Effects None +

          + +

          See Also st_lookup_int + + +
          +int 
          +st_numcmp(
          +  const char * x, 
          +  const char * y 
          +)
          +
          +
          integer number comparison function. +

          + +

          Side Effects None +

          + +

          See Also st_init_table +st_numhash + + +
          +int 
          +st_numhash(
          +  char * x, 
          +  int  size 
          +)
          +
          +
          Integer number hash function. +

          + +

          Side Effects None +

          + +

          See Also st_init_table +st_numcmp + + +
          +int 
          +st_ptrcmp(
          +  const char * x, 
          +  const char * y 
          +)
          +
          +
          Pointer comparison function. +

          + +

          Side Effects None +

          + +

          See Also st_init_table +st_ptrhash + + +
          +int 
          +st_ptrhash(
          +  char * x, 
          +  int  size 
          +)
          +
          +
          Pointer hash function. +

          + +

          Side Effects None +

          + +

          See Also st_init_table +st_ptrcmp + + +
          +int 
          +st_strhash(
          +  char * string, 
          +  int  modulus 
          +)
          +
          +
          String hash function. +

          + +

          Side Effects None +

          + +

          See Also st_init_table + + + +
          + +
          + +Generated automatically by extdoc on 20040102 + + diff --git a/distr/st/st.c b/distr/st/st.c new file mode 100644 index 0000000..4d85262 --- /dev/null +++ b/distr/st/st.c @@ -0,0 +1,1065 @@ +/**CFile*********************************************************************** + + FileName [st.c] + + PackageName [st] + + Synopsis [Symbol table package.] + + Description [The st library provides functions to create, maintain, + and query symbol tables.] + + SeeAlso [] + + Author [] + + Copyright [] + +******************************************************************************/ + +#include "util.h" +#include "st.h" + +/*---------------------------------------------------------------------------*/ +/* Constant declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Stucture declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Type declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Variable declarations */ +/*---------------------------------------------------------------------------*/ + +#ifndef lint +static char rcsid[] UTIL_UNUSED = " $Id: st.c,v 1.11 2004/02/11 22:31:59 fabio Exp fabio $"; +#endif + +/*---------------------------------------------------------------------------*/ +/* Macro declarations */ +/*---------------------------------------------------------------------------*/ + +#define ST_NUMCMP(x,y) ((x) != (y)) + +#define ST_NUMHASH(x,size) (ABS((long)x)%(size)) + +#if SIZEOF_VOID_P == 8 +#define st_shift 3 +#else +#define st_shift 2 +#endif + +#define ST_PTRHASH(x,size) ((unsigned int)((unsigned long)(x)>>st_shift)%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)\ + ((int)((table->hash == st_ptrhash) ? ST_PTRHASH((char *)(key),(table)->num_bins) :\ + (table->hash == st_numhash) ? ST_NUMHASH((char *)(key), (table)->num_bins) :\ + (*table->hash)((char *)(key), (table)->num_bins))) + +#define PTR_NOT_EQUAL(table, ptr, user_key)\ +(ptr != NIL(st_table_entry) && !EQUAL(table->compare, (char *)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) != NIL(st_table_entry) && (table)->reorder_flag) {\ + *(last) = (ptr)->next;\ + (ptr)->next = (table)->bins[hash_val];\ + (table)->bins[hash_val] = (ptr);\ + } + +/* This macro does not check if memory allocation fails. Use at you own risk */ +#define ADD_DIRECT(table, key, value, hash_val, newt)\ +{\ + if (table->num_entries/table->num_bins >= table->max_density) {\ + rehash(table);\ + hash_val = do_hash(key,table);\ + }\ + \ + newt = ALLOC(st_table_entry, 1);\ + \ + newt->key = (char *)key;\ + newt->record = value;\ + newt->next = table->bins[hash_val];\ + table->bins[hash_val] = newt;\ + table->num_entries++;\ +} + +/**AutomaticStart*************************************************************/ + +/*---------------------------------------------------------------------------*/ +/* Static function prototypes */ +/*---------------------------------------------------------------------------*/ + +static int rehash (st_table *); + +/**AutomaticEnd***************************************************************/ + + +/*---------------------------------------------------------------------------*/ +/* Definition of exported functions */ +/*---------------------------------------------------------------------------*/ + +/**Function******************************************************************** + + Synopsis [Create and initialize a table.] + + Description [Create and initialize a table with the comparison function + compare_fn and hash function hash_fn. compare_fn is +
          +	int compare_fn(const char *key1, const char *key2)
          +  
          + It returns <,=,> 0 depending on whether key1 <,=,> key2 by some measure.

          + hash_fn is +

          +	int hash_fn(char *key, int modulus)
          +  
          + It returns a integer between 0 and modulus-1 such that if + compare_fn(key1,key2) == 0 then hash_fn(key1) == hash_fn(key2).

          + There are five predefined hash and comparison functions in st. + For keys as numbers: +

          +	 st_numhash(key, modulus) { return (unsigned int) key % modulus; }
          +  
          +
          +	 st_numcmp(x,y) { return (int) x - (int) y; }
          +  
          + For keys as pointers: +
          +	 st_ptrhash(key, modulus) { return ((unsigned int) key/4) % modulus }
          +  
          +
          +	 st_ptrcmp(x,y) { return (int) x - (int) y; }
          +  
          + For keys as strings: +
          +         st_strhash(x,y) - a reasonable hashing function for strings
          +  
          +
          +	 strcmp(x,y) - the standard library function
          +  
          + It is recommended to use these particular functions if they fit your + needs, since st will recognize certain of them and run more quickly + because of it.] + + SideEffects [None] + + SeeAlso [st_init_table_with_params st_free_table] + +******************************************************************************/ +st_table * +st_init_table(ST_PFICPCP compare, ST_PFICPI 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); + +} /* st_init_table */ + + +/**Function******************************************************************** + + Synopsis [Create a table with given parameters.] + + Description [The full blown table initializer. compare and hash are + the same as in st_init_table. density is the largest the average + number of entries per hash bin there should be before the table is + grown. grow_factor is the factor the table is grown by when it + becomes too full. size is the initial number of bins to be allocated + for the hash table. If reorder_flag is non-zero, then every time an + entry is found, it is moved to the top of the chain.

          + st_init_table(compare, hash) is equivelent to +

          +  st_init_table_with_params(compare, hash, ST_DEFAULT_INIT_TABLE_SIZE,
          +			    ST_DEFAULT_MAX_DENSITY,
          +			    ST_DEFAULT_GROW_FACTOR,
          +			    ST_DEFAULT_REORDER_FLAG);
          +  
          + ] + + SideEffects [None] + + SeeAlso [st_init_table st_free_table] + +******************************************************************************/ +st_table * +st_init_table_with_params( + ST_PFICPCP compare, + ST_PFICPI hash, + int size, + int density, + double grow_factor, + int reorder_flag) +{ + int i; + st_table *newt; + + newt = ALLOC(st_table, 1); + if (newt == NIL(st_table)) { + return NIL(st_table); + } + newt->compare = compare; + newt->hash = hash; + newt->num_entries = 0; + newt->max_density = density; + newt->grow_factor = grow_factor; + newt->reorder_flag = reorder_flag; + if (size <= 0) { + size = 1; + } + newt->num_bins = size; + newt->bins = ALLOC(st_table_entry *, size); + if (newt->bins == NIL(st_table_entry *)) { + FREE(newt); + return NIL(st_table); + } + for(i = 0; i < size; i++) { + newt->bins[i] = 0; + } + return newt; + +} /* st_init_table_with_params */ + + +/**Function******************************************************************** + + Synopsis [Free a table.] + + Description [Any internal storage associated with table is freed. + It is the user's responsibility to free any storage associated + with the pointers he placed in the table (by perhaps using + st_foreach).] + + SideEffects [None] + + SeeAlso [st_init_table st_init_table_with_params] + +******************************************************************************/ +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 != NIL(st_table_entry)) { + next = ptr->next; + FREE(ptr); + ptr = next; + } + } + FREE(table->bins); + FREE(table); + +} /* st_free_table */ + + +/**Function******************************************************************** + + Synopsis [Lookup up `key' in `table'.] + + Description [Lookup up `key' in `table'. If an entry is found, 1 is + returned and if `value' is not nil, the variable it points to is set + to the associated value. If an entry is not found, 0 is returned + and the variable pointed by value is unchanged.] + + SideEffects [None] + + SeeAlso [st_lookup_int] + +******************************************************************************/ +int +st_lookup(st_table *table, void *key, void *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 == NIL(st_table_entry)) { + return 0; + } else { + if (value != NIL(void)) { + *(char **)value = ptr->record; + } + return 1; + } + +} /* st_lookup */ + + +/**Function******************************************************************** + + Synopsis [Lookup up `key' in `table'.] + + Description [Lookup up `key' in `table'. If an entry is found, 1 is + returned and if `value' is not nil, the variable it points to is + set to the associated integer value. If an entry is not found, 0 is + return and the variable pointed by `value' is unchanged.] + + SideEffects [None] + + SeeAlso [st_lookup] + +******************************************************************************/ +int +st_lookup_int(st_table *table, void *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 == NIL(st_table_entry)) { + return 0; + } else { + if (value != NIL(int)) { + *value = (int) (long) ptr->record; + } + return 1; + } + +} /* st_lookup_int */ + + +/**Function******************************************************************** + + Synopsis [Insert value in table under the key 'key'.] + + Description [Insert value in table under the key 'key'. Returns 1 + if there was an entry already under the key; 0 if there was no entry + under the key and insertion was successful; ST_OUT_OF_MEM otherwise. + In either of the first two cases the new value is added.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +int +st_insert(st_table *table, void *key, void *value) +{ + int hash_val; + st_table_entry *newt; + st_table_entry *ptr, **last; + + hash_val = do_hash(key, table); + + FIND_ENTRY(table, hash_val, key, ptr, last); + + if (ptr == NIL(st_table_entry)) { + 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); + } + newt = ALLOC(st_table_entry, 1); + if (newt == NIL(st_table_entry)) { + return ST_OUT_OF_MEM; + } + newt->key = (char *)key; + newt->record = (char *)value; + newt->next = table->bins[hash_val]; + table->bins[hash_val] = newt; + table->num_entries++; + return 0; + } else { + ptr->record = (char *)value; + return 1; + } + +} /* st_insert */ + + +/**Function******************************************************************** + + Synopsis [Place 'value' in 'table' under the key 'key'.] + + Description [Place 'value' in 'table' under the key 'key'. This is + done without checking if 'key' is in 'table' already. This should + only be used if you are sure there is not already an entry for + 'key', since it is undefined which entry you would later get from + st_lookup or st_find_or_add. Returns 1 if successful; ST_OUT_OF_MEM + otherwise.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +int +st_add_direct(st_table *table, void *key, void *value) +{ + int hash_val; + st_table_entry *newt; + + 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); + newt = ALLOC(st_table_entry, 1); + if (newt == NIL(st_table_entry)) { + return ST_OUT_OF_MEM; + } + newt->key = (char *)key; + newt->record = (char *)value; + newt->next = table->bins[hash_val]; + table->bins[hash_val] = newt; + table->num_entries++; + return 1; + +} /* st_add_direct */ + + +/**Function******************************************************************** + + Synopsis [Lookup `key' in `table'.] + + Description [Lookup `key' in `table'. If not found, create an + entry. In either case set slot to point to the field in the entry + where the value is stored. The value associated with `key' may then + be changed by accessing directly through slot. Returns 1 if an + entry already existed, 0 if it did not exist and creation was + successful; ST_OUT_OF_MEM otherwise. As an example: +
          +      char **slot;
          +  
          +
          +      char *key;
          +  
          +
          +      char *value = (char *) item_ptr <-- ptr to a malloc'd structure
          +  
          +
          +      if (st_find_or_add(table, key, &slot) == 1) {
          +  
          +
          +	 FREE(*slot); <-- free the old value of the record
          +  
          +
          +      }
          +  
          +
          +      *slot = value;  <-- attach the new value to the record
          +  
          + This replaces the equivelent code: +
          +      if (st_lookup(table, key, &ovalue) == 1) {
          +  
          +
          +         FREE(ovalue);
          +  
          +
          +      }
          +  
          +
          +      st_insert(table, key, value);
          +  
          + ] + + SideEffects [None] + + SeeAlso [st_find] + +******************************************************************************/ +int +st_find_or_add(st_table *table, void *key, void *slot) +{ + int hash_val; + st_table_entry *newt, *ptr, **last; + + hash_val = do_hash(key, table); + + FIND_ENTRY(table, hash_val, key, ptr, last); + + if (ptr == NIL(st_table_entry)) { + 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); + } + newt = ALLOC(st_table_entry, 1); + if (newt == NIL(st_table_entry)) { + return ST_OUT_OF_MEM; + } + newt->key = (char *)key; + newt->record = (char *) 0; + newt->next = table->bins[hash_val]; + table->bins[hash_val] = newt; + table->num_entries++; + if (slot != NIL(void)) *(char ***)slot = &newt->record; + return 0; + } else { + if (slot != NIL(void)) *(char ***)slot = &ptr->record; + return 1; + } + +} /* st_find_or_add */ + + +/**Function******************************************************************** + + Synopsis [Lookup `key' in `table'.] + + Description [Like st_find_or_add, but does not create an entry if + one is not found.] + + SideEffects [None] + + SeeAlso [st_find_or_add] + +******************************************************************************/ +int +st_find(st_table *table, void *key, void *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 == NIL(st_table_entry)) { + return 0; + } else { + if (slot != NIL(void)) { + *(char ***)slot = &ptr->record; + } + return 1; + } + +} /* st_find */ + + +/**Function******************************************************************** + + Synopsis [Return a copy of old_table and all its members.] + + Description [Return a copy of old_table and all its members. + (st_table *) 0 is returned if there was insufficient memory to do + the copy.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +st_table * +st_copy(st_table *old_table) +{ + st_table *new_table; + st_table_entry *ptr, *newptr, *next, *newt; + int i, j, num_bins = old_table->num_bins; + + new_table = ALLOC(st_table, 1); + if (new_table == NIL(st_table)) { + return NIL(st_table); + } + + *new_table = *old_table; + new_table->bins = ALLOC(st_table_entry *, num_bins); + if (new_table->bins == NIL(st_table_entry *)) { + FREE(new_table); + return NIL(st_table); + } + for(i = 0; i < num_bins ; i++) { + new_table->bins[i] = NIL(st_table_entry); + ptr = old_table->bins[i]; + while (ptr != NIL(st_table_entry)) { + newt = ALLOC(st_table_entry, 1); + if (newt == NIL(st_table_entry)) { + for (j = 0; j <= i; j++) { + newptr = new_table->bins[j]; + while (newptr != NIL(st_table_entry)) { + next = newptr->next; + FREE(newptr); + newptr = next; + } + } + FREE(new_table->bins); + FREE(new_table); + return NIL(st_table); + } + *newt = *ptr; + newt->next = new_table->bins[i]; + new_table->bins[i] = newt; + ptr = ptr->next; + } + } + return new_table; + +} /* st_copy */ + + +/**Function******************************************************************** + + Synopsis [Delete the entry with the key pointed to by `keyp'.] + + Description [Delete the entry with the key pointed to by `keyp'. If + the entry is found, 1 is returned, the variable pointed by `keyp' is + set to the actual key and the variable pointed by `value' is set to + the corresponding entry. (This allows the freeing of the associated + storage.) If the entry is not found, then 0 is returned and nothing + is changed.] + + SideEffects [None] + + SeeAlso [st_delete_int] + +******************************************************************************/ +int +st_delete(st_table *table, void *keyp, void *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 == NIL(st_table_entry)) { + return 0; + } + + *last = ptr->next; + if (value != NIL(void)) *(char **)value = ptr->record; + *(char **)keyp = ptr->key; + FREE(ptr); + table->num_entries--; + return 1; + +} /* st_delete */ + + +/**Function******************************************************************** + + Synopsis [Delete the entry with the key pointed to by `keyp'.] + + Description [Delete the entry with the key pointed to by `keyp'. + `value' must be a pointer to an integer. If the entry is found, 1 + is returned, the variable pointed by `keyp' is set to the actual key + and the variable pointed by `value' is set to the corresponding + entry. (This allows the freeing of the associated storage.) If the + entry is not found, then 0 is returned and nothing is changed.] + + SideEffects [None] + + SeeAlso [st_delete] + +******************************************************************************/ +int +st_delete_int(st_table *table, void *keyp, int *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 == NIL(st_table_entry)) { + return 0; + } + + *last = ptr->next; + if (value != NIL(int)) *value = (int) (long) ptr->record; + *(char **)keyp = ptr->key; + FREE(ptr); + table->num_entries--; + return 1; + +} /* st_delete_int */ + + +/**Function******************************************************************** + + Synopsis [Iterates over the elements of a table.] + + Description [For each (key, value) record in `table', st_foreach + call func with the arguments +
          +	  (*func)(key, value, arg)
          +  
          + If func returns ST_CONTINUE, st_foreach continues processing + entries. If func returns ST_STOP, st_foreach stops processing and + returns immediately. If func returns ST_DELETE, then the entry is + deleted from the symbol table and st_foreach continues. In the case + of ST_DELETE, it is func's responsibility to free the key and value, + if necessary.

          + + The routine returns 1 if all items in the table were generated and 0 + if the generation sequence was aborted using ST_STOP. The order in + which the records are visited will be seemingly random.] + + SideEffects [None] + + SeeAlso [st_foreach_item st_foreach_item_int] + +******************************************************************************/ +int +st_foreach(st_table *table, ST_PFSR func, 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 != NIL(st_table_entry)) { + 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 */ + FREE(ptr); + ptr = *last; + } + } + } + return 1; + +} /* st_foreach */ + + +/**Function******************************************************************** + + Synopsis [String hash function.] + + Description [String hash function.] + + SideEffects [None] + + SeeAlso [st_init_table] + +******************************************************************************/ +int +st_strhash(char *string, int modulus) +{ + int val = 0; + int c; + + while ((c = *string++) != '\0') { + val = val*997 + c; + } + + return ((val < 0) ? -val : val)%modulus; + +} /* st_strhash */ + + +/**Function******************************************************************** + + Synopsis [Number hash function.] + + Description [Integer number hash function.] + + SideEffects [None] + + SeeAlso [st_init_table st_numcmp] + +******************************************************************************/ +int +st_numhash(char *x, int size) +{ + return ST_NUMHASH(x, size); + +} /* st_numhash */ + + +/**Function******************************************************************** + + Synopsis [Pointer hash function.] + + Description [Pointer hash function.] + + SideEffects [None] + + SeeAlso [st_init_table st_ptrcmp] + +******************************************************************************/ +int +st_ptrhash(char *x, int size) +{ + return ST_PTRHASH(x, size); + +} /* st_ptrhash */ + + +/**Function******************************************************************** + + Synopsis [Number comparison function.] + + Description [integer number comparison function.] + + SideEffects [None] + + SeeAlso [st_init_table st_numhash] + +******************************************************************************/ +int +st_numcmp(const char *x, const char *y) +{ + return ST_NUMCMP(x, y); + +} /* st_numcmp */ + + +/**Function******************************************************************** + + Synopsis [Pointer comparison function.] + + Description [Pointer comparison function.] + + SideEffects [None] + + SeeAlso [st_init_table st_ptrhash] + +******************************************************************************/ +int +st_ptrcmp(const char *x, const char *y) +{ + return ST_NUMCMP(x, y); + +} /* st_ptrcmp */ + + +/**Function******************************************************************** + + Synopsis [Initializes a generator.] + + Description [Returns a generator handle which when used with + st_gen() will progressively return each (key, value) record in + `table'.] + + SideEffects [None] + + SeeAlso [st_free_gen] + +******************************************************************************/ +st_generator * +st_init_gen(st_table *table) +{ + st_generator *gen; + + gen = ALLOC(st_generator, 1); + if (gen == NIL(st_generator)) { + return NIL(st_generator); + } + gen->table = table; + gen->entry = NIL(st_table_entry); + gen->index = 0; + return gen; + +} /* st_init_gen */ + + +/**Function******************************************************************** + + Synopsis [returns the next (key, value) pair in the generation + sequence. ] + + Description [Given a generator returned by st_init_gen(), this + routine returns the next (key, value) pair in the generation + sequence. The pointer `value_p' can be zero which means no value + will be returned. When there are no more items in the generation + sequence, the routine returns 0. + + While using a generation sequence, deleting any (key, value) pair + other than the one just generated may cause a fatal error when + st_gen() is called later in the sequence and is therefore not + recommended.] + + SideEffects [None] + + SeeAlso [st_gen_int] + +******************************************************************************/ +int +st_gen(st_generator *gen, void *key_p, void *value_p) +{ + int i; + + if (gen->entry == NIL(st_table_entry)) { + /* try to find next entry */ + for(i = gen->index; i < gen->table->num_bins; i++) { + if (gen->table->bins[i] != NIL(st_table_entry)) { + gen->index = i+1; + gen->entry = gen->table->bins[i]; + break; + } + } + if (gen->entry == NIL(st_table_entry)) { + return 0; /* that's all folks ! */ + } + } + *(char **)key_p = gen->entry->key; + if (value_p != NIL(void)) { + *(char **)value_p = gen->entry->record; + } + gen->entry = gen->entry->next; + return 1; + +} /* st_gen */ + + +/**Function******************************************************************** + + Synopsis [Returns the next (key, value) pair in the generation + sequence.] + + Description [Given a generator returned by st_init_gen(), this + routine returns the next (key, value) pair in the generation + sequence. `value_p' must be a pointer to an integer. The pointer + `value_p' can be zero which means no value will be returned. When + there are no more items in the generation sequence, the routine + returns 0.] + + SideEffects [None] + + SeeAlso [st_gen] + +******************************************************************************/ +int +st_gen_int(st_generator *gen, void *key_p, int *value_p) +{ + int i; + + if (gen->entry == NIL(st_table_entry)) { + /* try to find next entry */ + for(i = gen->index; i < gen->table->num_bins; i++) { + if (gen->table->bins[i] != NIL(st_table_entry)) { + gen->index = i+1; + gen->entry = gen->table->bins[i]; + break; + } + } + if (gen->entry == NIL(st_table_entry)) { + return 0; /* that's all folks ! */ + } + } + *(char **)key_p = gen->entry->key; + if (value_p != NIL(int)) { + *value_p = (int) (long) gen->entry->record; + } + gen->entry = gen->entry->next; + return 1; + +} /* st_gen_int */ + + +/**Function******************************************************************** + + Synopsis [Reclaims the resources associated with `gen'.] + + Description [After generating all items in a generation sequence, + this routine must be called to reclaim the resources associated with + `gen'.] + + SideEffects [None] + + SeeAlso [st_init_gen] + +******************************************************************************/ +void +st_free_gen(st_generator *gen) +{ + FREE(gen); + +} /* st_free_gen */ + + +/*---------------------------------------------------------------------------*/ +/* Definition of internal functions */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Definition of static functions */ +/*---------------------------------------------------------------------------*/ + +/**Function******************************************************************** + + Synopsis [Rehashes a symbol table.] + + Description [Rehashes a symbol table.] + + SideEffects [None] + + SeeAlso [st_insert] + +******************************************************************************/ +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 = ALLOC(st_table_entry *, table->num_bins); + if (table->bins == NIL(st_table_entry *)) { + 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 != NIL(st_table_entry)) { + 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; + } + } + FREE(old_bins); + + return 1; + +} /* rehash */ diff --git a/distr/st/st.h b/distr/st/st.h new file mode 100644 index 0000000..dbb14bb --- /dev/null +++ b/distr/st/st.h @@ -0,0 +1,232 @@ +/**CHeaderFile***************************************************************** + + FileName [st.h] + + PackageName [st] + + Synopsis [Symbol table package.] + + Description [The st library provides functions to create, maintain, + and query symbol tables.] + + SeeAlso [] + + Author [] + + Copyright [] + + Revision [$Id: st.h,v 1.10 2004/01/02 07:40:31 fabio Exp fabio $] + +******************************************************************************/ + +#ifndef ST_INCLUDED +#define ST_INCLUDED + +/*---------------------------------------------------------------------------*/ +/* Nested includes */ +/*---------------------------------------------------------------------------*/ + +#ifdef __cplusplus +extern "C" { +#endif + +/*---------------------------------------------------------------------------*/ +/* Constant declarations */ +/*---------------------------------------------------------------------------*/ + +#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_OUT_OF_MEM -10000 + +/*---------------------------------------------------------------------------*/ +/* Stucture declarations */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Type declarations */ +/*---------------------------------------------------------------------------*/ + +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 { + int (*compare)(const char *, const char *); + int (*hash)(char *, int); + 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; +}; + +enum st_retval {ST_CONTINUE, ST_STOP, ST_DELETE}; + +typedef enum st_retval (*ST_PFSR)(char *, char *, char *); + +typedef int (*ST_PFICPCP)(const char *, const char *); /* type for comparison function */ + +typedef int (*ST_PFICPI)(char *, int); /* type for hash function */ + +/*---------------------------------------------------------------------------*/ +/* Variable declarations */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Macro declarations */ +/*---------------------------------------------------------------------------*/ + +/**Macro*********************************************************************** + + Synopsis [Checks whethere `key' is in `table'.] + + Description [Returns 1 if there is an entry under `key' in `table', 0 + otherwise.] + + SideEffects [None] + + SeeAlso [st_lookup] + +******************************************************************************/ +#define st_is_member(table,key) st_lookup(table,key,(char **) 0) + + +/**Macro*********************************************************************** + + Synopsis [Returns the number of entries in the table `table'.] + + Description [Returns the number of entries in the table `table'.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +#define st_count(table) ((table)->num_entries) + + +/**Macro*********************************************************************** + + Synopsis [Iteration macro.] + + Description [An iteration macro which loops over all the entries in + `table', setting `key' to point to the key and `value' to the + associated value (if it is not nil). `gen' is a generator variable + used internally. Sample usage: +

          +     	char *key, *value;
          +  
          +
          +	st_generator *gen;
          +  
          +
          +
          +	st_foreach_item(table, gen, &key, &value) {
          +  
          +
          +	    process_item(value);
          +  
          +
          +	}
          +  
          + ] + + SideEffects [None] + + SeeAlso [st_foreach_item_int st_foreach] + +******************************************************************************/ +#define st_foreach_item(table, gen, key, value) \ + for(gen=st_init_gen(table); st_gen(gen,key,value) || (st_free_gen(gen),0);) + + +/**Macro*********************************************************************** + + Synopsis [Iteration macro.] + + Description [An iteration macro which loops over all the entries in + `table', setting `key' to point to the key and `value' to the + associated value (if it is not nil). `value' is assumed to be a + pointer to an integer. `gen' is a generator variable used + internally. Sample usage: +
          +     	char *key;
          +  
          +
          +	int value;
          +  
          +
          +	st_generator *gen;
          +  
          +
          +
          +	st_foreach_item_int(table, gen, &key, &value) {
          +  
          +
          +	    process_item(value);
          +  
          +
          +	}
          +  
          + ] + + SideEffects [None] + + SeeAlso [st_foreach_item st_foreach] + +******************************************************************************/ +#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);) + +/**AutomaticStart*************************************************************/ + +/*---------------------------------------------------------------------------*/ +/* Function prototypes */ +/*---------------------------------------------------------------------------*/ + +extern st_table *st_init_table_with_params (ST_PFICPCP, ST_PFICPI, int, int, double, int); +extern st_table *st_init_table (ST_PFICPCP, ST_PFICPI); +extern void st_free_table (st_table *); +extern int st_lookup (st_table *, void *, void *); +extern int st_lookup_int (st_table *, void *, int *); +extern int st_insert (st_table *, void *, void *); +extern int st_add_direct (st_table *, void *, void *); +extern int st_find_or_add (st_table *, void *, void *); +extern int st_find (st_table *, void *, void *); +extern st_table *st_copy (st_table *); +extern int st_delete (st_table *, void *, void *); +extern int st_delete_int (st_table *, void *, int *); +extern int st_foreach (st_table *, ST_PFSR, char *); +extern int st_strhash (char *, int); +extern int st_numhash (char *, int); +extern int st_ptrhash (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 *, void *, void *); +extern int st_gen_int (st_generator *, void *, int *); +extern void st_free_gen (st_generator *); + +/**AutomaticEnd***************************************************************/ + +#ifdef __cplusplus +} /* end of extern "C" */ +#endif + +#endif /* ST_INCLUDED */ diff --git a/distr/util/Makefile b/distr/util/Makefile new file mode 100644 index 0000000..71d9e5e --- /dev/null +++ b/distr/util/Makefile @@ -0,0 +1,65 @@ +# $Id$ +# +# util -- miscellaneous utility routines +#--------------------------------------------------------------------------- +.SUFFIXES: .c .o .u + +CC = gcc +RANLIB = ranlib + +FLAGS = -DUNIX +MFLAG = +ICFLAGS = -g +CFLAGS = $(ICFLAGS) $(MFLAG) $(XCFLAGS) + +LINTFLAGS = -u -n + +# this is to create the lint library +LINTSWITCH = -o + +P = util +PSRC = cpu_time.c cpu_stats.c getopt.c safe_mem.c strsav.c texpand.c \ + ptime.c prtime.c pipefork.c pathsearch.c stub.c \ + tmpfile.c datalimit.c +POBJ = $(PSRC:.c=.o) +PUBJ = $(PSRC:.c=.u) +PHDR = util.h + +WHERE = .. +INCLUDE = $(WHERE)/include + +lib$(P).a: $(POBJ) + ar rv $@ $? + $(RANLIB) $@ + +.c.o: $(PHDR) + $(CC) -c $< -I$(INCLUDE) $(FLAGS) $(CFLAGS) + +optimize_dec: lib$(P).b + +lib$(P).b: $(PUBJ) + ar rv $@ $? + $(RANLIB) $@ + +.c.u: $(PHDR) + cc -j $< -I$(INCLUDE) $(FLAGS) $(XCFLAGS) + +# if the header files change, recompile +$(POBJ): $(PHDR) +$(PUBJ): $(PHDR) + +lint: llib-l$(P).ln + +llib-l$(P).ln: $(PSRC) $(PHDR) + lint $(LINTFLAGS) $(LINTSWITCH)$(P) -I$(INCLUDE) $(PSRC) + +tags: $(PSRC) $(PHDR) + ctags $(PSRC) $(PHDR) + +all: lib$(P).a lib$(P).b llib-l$(P).ln tags + +clean: + rm -f *.o *.u core *.warnings + +distclean: clean + rm -f lib$(P).a lib$(P).b llib-l$(P).ln tags *.bak *~ .pure diff --git a/distr/util/cpu_stats.c b/distr/util/cpu_stats.c new file mode 100644 index 0000000..40117d4 --- /dev/null +++ b/distr/util/cpu_stats.c @@ -0,0 +1,89 @@ +/* LINTLIBRARY */ + +#include "util.h" + + +#ifdef BSD +#include +#include +#include + +#if defined(_IBMR2) +#define etext _etext +#define edata _edata +#define end _end +#endif + +extern int end, etext, edata; + +#endif + +void +util_print_cpu_stats(FILE *fp) +{ +#ifdef BSD + struct rusage rusage; + struct rlimit rlp; + long text, data, vm_limit, vm_soft_limit; + double user, system, scale; + char hostname[257]; + long vm_text, vm_init_data, vm_uninit_data, vm_sbrk_data; + + /* Get the hostname */ + (void) gethostname(hostname, 256); + hostname[256] = '\0'; /* just in case */ + + /* Get the virtual memory sizes */ + vm_text = (long) (((long) (&etext)) / 1024.0 + 0.5); + vm_init_data = (long) (((long) (&edata) - (long) (&etext)) / 1024.0 + 0.5); + vm_uninit_data = (long) (((long) (&end) - (long) (&edata)) / 1024.0 + 0.5); + vm_sbrk_data = (long) (((long) sbrk(0) - (long) (&end)) / 1024.0 + 0.5); + + /* Get virtual memory limits */ + (void) getrlimit(RLIMIT_DATA, &rlp); + vm_limit = (long) (rlp.rlim_max / 1024.0 + 0.5); + vm_soft_limit = (long) (rlp.rlim_cur / 1024.0 + 0.5); + + /* Get usage stats */ + (void) getrusage(RUSAGE_SELF, &rusage); + user = rusage.ru_utime.tv_sec + rusage.ru_utime.tv_usec/1.0e6; + system = rusage.ru_stime.tv_sec + rusage.ru_stime.tv_usec/1.0e6; + scale = (user + system)*100.0; + if (scale == 0.0) scale = 0.001; + + (void) fprintf(fp, "Runtime Statistics\n"); + (void) fprintf(fp, "------------------\n"); + (void) fprintf(fp, "Machine name: %s\n", hostname); + (void) fprintf(fp, "User time %6.1f seconds\n", user); + (void) fprintf(fp, "System time %6.1f seconds\n\n", system); + + text = (int) (rusage.ru_ixrss / scale + 0.5); + data = (int) ((rusage.ru_idrss + rusage.ru_isrss) / scale + 0.5); + (void) fprintf(fp, "Average resident text size = %5ldK\n", text); + (void) fprintf(fp, "Average resident data+stack size = %5ldK\n", data); + (void) fprintf(fp, "Maximum resident size = %5ldK\n\n", + rusage.ru_maxrss/2); + (void) fprintf(fp, "Virtual text size = %5ldK\n", + vm_text); + (void) fprintf(fp, "Virtual data size = %5ldK\n", + vm_init_data + vm_uninit_data + vm_sbrk_data); + (void) fprintf(fp, " data size initialized = %5ldK\n", + vm_init_data); + (void) fprintf(fp, " data size uninitialized = %5ldK\n", + vm_uninit_data); + (void) fprintf(fp, " data size sbrk = %5ldK\n", + vm_sbrk_data); + (void) fprintf(fp, "Virtual memory limit = %5ldK (%ldK)\n\n", + vm_soft_limit, vm_limit); + + (void) fprintf(fp, "Major page faults = %ld\n", rusage.ru_majflt); + (void) fprintf(fp, "Minor page faults = %ld\n", rusage.ru_minflt); + (void) fprintf(fp, "Swaps = %ld\n", rusage.ru_nswap); + (void) fprintf(fp, "Input blocks = %ld\n", rusage.ru_inblock); + (void) fprintf(fp, "Output blocks = %ld\n", rusage.ru_oublock); + (void) fprintf(fp, "Context switch (voluntary) = %ld\n", rusage.ru_nvcsw); + (void) fprintf(fp, "Context switch (involuntary) = %ld\n", rusage.ru_nivcsw); +#else + (void) fprintf(fp, "Usage statistics not available\n"); +#endif +} diff --git a/distr/util/cpu_time.c b/distr/util/cpu_time.c new file mode 100644 index 0000000..2a4be92 --- /dev/null +++ b/distr/util/cpu_time.c @@ -0,0 +1,76 @@ +/* LINTLIBRARY */ + +#include +#include "util.h" + +#ifdef IBM_WATC /* IBM Waterloo-C compiler (same as bsd 4.2) */ +#define void int +#define BSD +#endif + +#ifdef BSD +#include +#include +#include +#endif + +#if defined(UNIX60) || defined(UNIX100) || defined(__CYGWIN32__) +#include +#include +#endif + +#ifdef vms /* VAX/C compiler -- times() with 100 HZ clock */ +#include +#include +#endif + + + +/* + * util_cpu_time -- return a long which represents the elapsed processor + * time in milliseconds since some constant reference + */ +long +util_cpu_time() +{ + long t = 0; + +#ifdef BSD + struct rusage rusage; + (void) getrusage(RUSAGE_SELF, &rusage); + t = (long) rusage.ru_utime.tv_sec*1000 + rusage.ru_utime.tv_usec/1000; +#endif + +#ifdef IBMPC + long ltime; + (void) time(<ime); + t = ltime * 1000; +#endif + +#ifdef UNIX60 /* times() with 60 Hz resolution */ + struct tms buffer; + times(&buffer); + t = buffer.tms_utime * 16.6667; +#endif + +#ifdef UNIX100 + struct tms buffer; /* times() with 100 Hz resolution */ + times(&buffer); + t = buffer.tms_utime * 10; +#endif + +#ifdef __CYGWIN32__ + /* Works under Windows NT but not Windows 95. */ + struct tms buffer; /* times() with 1000 Hz resolution */ + times(&buffer); + t = buffer.tms_utime; +#endif + +#ifdef vms + tbuffer_t buffer; /* times() with 100 Hz resolution */ + times(&buffer); + t = buffer.proc_user_time * 10; +#endif + + return t; +} diff --git a/distr/util/datalimit.c b/distr/util/datalimit.c new file mode 100644 index 0000000..f140414 --- /dev/null +++ b/distr/util/datalimit.c @@ -0,0 +1,50 @@ +/* $Id: datalimit.c,v 1.5 2007/08/24 18:17:31 fabio Exp fabio $ */ + +#ifndef HAVE_SYS_RESOURCE_H +#define HAVE_SYS_RESOURCE_H 1 +#endif +#ifndef HAVE_SYS_TIME_H +#define HAVE_SYS_TIME_H 1 +#endif +#ifndef HAVE_GETRLIMIT +#define HAVE_GETRLIMIT 1 +#endif + +#if HAVE_SYS_RESOURCE_H == 1 +#if HAVE_SYS_TIME_H == 1 +#include +#endif +#include +#endif + +#ifndef RLIMIT_DATA_DEFAULT +#define RLIMIT_DATA_DEFAULT 67108864 /* assume 64MB by default */ +#endif + +#ifndef EXTERN +# ifdef __cplusplus +# define EXTERN extern "C" +# else +# define EXTERN extern +# endif +#endif + +EXTERN unsigned long getSoftDataLimit(void); + +unsigned long +getSoftDataLimit(void) +{ +#if HAVE_SYS_RESOURCE_H == 1 && HAVE_GETRLIMIT == 1 && defined(RLIMIT_DATA) + struct rlimit rl; + int result; + + result = getrlimit(RLIMIT_DATA, &rl); + if (result != 0 || rl.rlim_cur == RLIM_INFINITY) + return((unsigned long) RLIMIT_DATA_DEFAULT); + else + return((unsigned long) rl.rlim_cur); +#else + return((unsigned long) RLIMIT_DATA_DEFAULT); +#endif + +} /* end of getSoftDataLimit */ diff --git a/distr/util/getopt.c b/distr/util/getopt.c new file mode 100644 index 0000000..6ed10a8 --- /dev/null +++ b/distr/util/getopt.c @@ -0,0 +1,72 @@ +/* LINTLIBRARY */ + +#include +#include "util.h" + + +/* 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. + */ + +char *util_optarg; /* Global argument pointer. */ +int util_optind = 0; /* Global argv index. */ +static char *scan; + + +void +util_getopt_reset() +{ + util_optarg = 0; + util_optind = 0; + scan = 0; +} + + + +int +util_getopt(int argc, char * const argv[], char const *optstring) +{ + register int c; + register char *place; + + util_optarg = NIL(char); + + if (scan == NIL(char) || *scan == '\0') { + if (util_optind == 0) util_optind++; + if (util_optind >= argc) return EOF; + place = argv[util_optind]; + if (place[0] != '-' || place[1] == '\0') return EOF; + util_optind++; + if (place[1] == '-' && place[2] == '\0') return EOF; + scan = place+1; + } + + c = *scan++; + place = strchr(optstring, c); + if (place == NIL(char) || c == ':') { + (void) fprintf(stderr, "%s: unknown option %c\n", argv[0], c); + return '?'; + } + if (*++place == ':') { + if (*scan != '\0') { + util_optarg = scan; + scan = NIL(char); + } else { + if (util_optind >= argc) { + (void) fprintf(stderr, "%s: %c requires an argument\n", + argv[0], c); + return '?'; + } + util_optarg = argv[util_optind]; + util_optind++; + } + } + return c; +} diff --git a/distr/util/pathsearch.c b/distr/util/pathsearch.c new file mode 100644 index 0000000..67c34b8 --- /dev/null +++ b/distr/util/pathsearch.c @@ -0,0 +1,94 @@ +/* LINTLIBRARY */ + +#include +#include "util.h" + +static int check_file (char const *, char const *); + +char * +util_path_search(char const *prog) +{ +#ifdef UNIX + return util_file_search(prog, getenv("PATH"), (char *) "x"); +#else + return util_file_search(prog, NIL(char), (char *) "x"); +#endif +} + + +char * +util_file_search( + char const *file, /* file we're looking for */ + char *path, /* search path, colon separated */ + char const *mode /* "r", "w", or "x" */) +{ + int quit; + char *buffer, *filename, *save_path, *cp; + + if (path == 0 || strcmp(path, "") == 0) { + path = (char *) "."; /* just look in the current directory */ + } + + save_path = path = strsav(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 = strsav(file); + } else { + buffer = ALLOC(char, strlen(path) + strlen(file) + 4); + (void) sprintf(buffer, "%s/%s", path, file); + } + filename = util_tilde_expand(buffer); + FREE(buffer); + + /* see if we can access it */ + if (check_file(filename, mode)) { + FREE(save_path); + return filename; + } + FREE(filename); + path = ++cp; + } while (! quit); + + FREE(save_path); + return 0; +} + + +static int +check_file(char const *filename, char const *mode) +{ +#ifdef UNIX + int access_mode = /*F_OK*/ 0; + + if (strcmp(mode, "r") == 0) { + access_mode = /*R_OK*/ 4; + } else if (strcmp(mode, "w") == 0) { + access_mode = /*W_OK*/ 2; + } else if (strcmp(mode, "x") == 0) { + access_mode = /*X_OK*/ 1; + } + return access(filename, access_mode) == 0; +#else + 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; +#endif +} diff --git a/distr/util/pipefork.c b/distr/util/pipefork.c new file mode 100644 index 0000000..78167b3 --- /dev/null +++ b/distr/util/pipefork.c @@ -0,0 +1,93 @@ +/* + * Revision Control Information + * + * $Id: pipefork.c,v 1.6 2004/08/18 00:06:42 fabio Exp fabio $ + * + */ +/* LINTLIBRARY */ + +#include "util.h" +#include + +/* + * util_pipefork - fork a command and set up pipes to and from + * + * Rick L Spickelmier, 3/23/86 + * Richard Rudell, 4/6/86 + * Rick L Spickelmier, 4/30/90, got rid of slimey vfork semantics + * + * Returns: + * 1 for success, with toCommand and fromCommand pointing to the streams + * 0 for failure + */ + +/* ARGSUSED */ +int +util_pipefork( + char * const *argv, /* normal argv argument list */ + FILE **toCommand, /* pointer to the sending stream */ + FILE **fromCommand, /* pointer to the reading stream */ + int *pid) +{ +#ifdef UNIX + int forkpid, waitPid; + int topipe[2], frompipe[2]; + char buffer[1024]; + int status; + + /* create the PIPES... + * fildes[0] for reading from command + * fildes[1] for writing to command + */ + (void) pipe(topipe); + (void) pipe(frompipe); + +#ifdef __CYGWIN32__ + if ((forkpid = fork()) == 0) { +#else + if ((forkpid = vfork()) == 0) { +#endif + /* child here, connect the pipes */ + (void) dup2(topipe[0], fileno(stdin)); + (void) dup2(frompipe[1], fileno(stdout)); + + (void) close(topipe[0]); + (void) close(topipe[1]); + (void) close(frompipe[0]); + (void) close(frompipe[1]); + + (void) execvp(argv[0], argv); + (void) sprintf(buffer, "util_pipefork: can not exec %s", argv[0]); + perror(buffer); + (void) _exit(1); + } + + if (pid) { + *pid = forkpid; + } + +#ifdef __CYGWIN32__ + waitPid = waitpid(-1, &status, WNOHANG); +#else + waitPid = wait3(&status, WNOHANG, NULL); +#endif + + /* parent here, use slimey vfork() semantics to get return status */ + if (waitPid == forkpid && WIFEXITED(status)) { + return 0; + } + if ((*toCommand = fdopen(topipe[1], "w")) == NULL) { + return 0; + } + if ((*fromCommand = fdopen(frompipe[0], "r")) == NULL) { + return 0; + } + (void) close(topipe[0]); + (void) close(frompipe[1]); + return 1; +#else + (void) fprintf(stderr, + "util_pipefork: not implemented on your operating system\n"); + return 0; +#endif +} diff --git a/distr/util/prtime.c b/distr/util/prtime.c new file mode 100644 index 0000000..236eafb --- /dev/null +++ b/distr/util/prtime.c @@ -0,0 +1,21 @@ +/* LINTLIBRARY */ + +#include +#include "util.h" + + +/* + * util_print_time -- massage a long which represents a time interval in + * milliseconds, into a string suitable for output + * + * Hack for IBM/PC -- avoids using floating point + */ + +char * +util_print_time(unsigned long t) +{ + static char s[40]; + + (void) sprintf(s, "%lu.%02lu sec", t/1000, (t%1000)/10); + return s; +} diff --git a/distr/util/ptime.c b/distr/util/ptime.c new file mode 100644 index 0000000..4510857 --- /dev/null +++ b/distr/util/ptime.c @@ -0,0 +1,9 @@ +/* LINTLIBRARY */ +#include "util.h" + +/* backwards compatibility */ +long +ptime() +{ + return util_cpu_time(); +} diff --git a/distr/util/restart.c b/distr/util/restart.c new file mode 100644 index 0000000..b81dcb8 --- /dev/null +++ b/distr/util/restart.c @@ -0,0 +1,137 @@ +#include +#include "util.h" + +#if (defined(sun) && ! defined(sparc)) || defined(vax) + +#include +#include +#include + +static char *save_stack_base; +static char *stack_lo_addr; +static char *stack_hi_addr; +static int stack_size; + +static int restart_global_flag; +static char *old_file_name; +static char *new_file_name; + +char *util_save_sp; /* set by util_restart_save_state() */ +extern char *sbrk(); + +static void +grow_stack() +{ + int i, space[256]; + + for(i = 0; i < 256; i++) { + space[i] = 0; + } + if ((char *) &i > stack_lo_addr) { + grow_stack(); + } +} + + +/* ARGSUSED */ +static int +handle_sigquit(int sig, int code, struct sigcontext *scp) +{ + if (util_restart_save_state()) { + /* we are restarting ! -- return from signal */ + + } else { + /* copy stack to user data space */ + stack_lo_addr = util_save_sp; + stack_size = stack_hi_addr - stack_lo_addr + 1; + save_stack_base = sbrk(stack_size); + (void) memcpy(save_stack_base, stack_lo_addr, stack_size); + + /* write a new executable */ + (void) fprintf(stderr, "Writing executable %s ...\n", new_file_name); + (void) util_save_image(old_file_name, new_file_name); + + /* terminate if signal was a QUIT */ + if (sig == SIGQUIT) { + (void) _exit(1); + } + } +} + + +static void +restart_program() +{ + (void) fprintf(stderr, "Continuing execution ...\n"); + + /* create the stack */ + grow_stack(); + +#ifdef vax + asm("movl _util_save_sp,sp"); +#endif +#ifdef sun + asm("movl _util_save_sp,sp"); +#endif + + /* copy the stack back from user space */ + (void) memcpy(stack_lo_addr, save_stack_base, stack_size); + + /* remove the sbrk for the stack */ + if (sbrk(-stack_size) < 0) { + perror("sbrk"); + } + + util_restart_restore_state(); /* jump back into handle_sigquit() */ +} + +void +util_restart(char const *old, char const *neW, int interval) +{ + struct itimerval itimer; + +#ifdef vax +#ifdef ultrix + stack_hi_addr = (char *) 0x7fffe3ff; /* ultrix */ +#else + stack_hi_addr = (char *) 0x7fffebff; /* bsd 4.3 */ +#endif +#endif +#ifdef sun + stack_hi_addr = (char *) 0x0effffff; /* Sun OS 3.2, 3.4 */ +#endif + + old_file_name = old; + new_file_name = neW; + + (void) signal(SIGQUIT, handle_sigquit); + + if (interval > 0) { + (void) signal(SIGVTALRM, handle_sigquit); + itimer.it_interval.tv_sec = interval; + itimer.it_interval.tv_usec = 0; + itimer.it_value.tv_sec = interval; + itimer.it_value.tv_usec = 0; + if (setitimer(ITIMER_VIRTUAL, &itimer, (struct itimerval *) 0) < 0) { + perror("setitimer"); + exit(1); + } + } + + if (restart_global_flag) { + restart_program(); + } + restart_global_flag = 1; +} + +#else + +/* ARGSUSED */ +void +util_restart(char const *old, char const *neW, int interval) +{ + (void) fprintf(stderr, + "util_restart: not supported on your operating system/hardware\n"); +} + +#endif diff --git a/distr/util/safe_mem.c b/distr/util/safe_mem.c new file mode 100644 index 0000000..597cc89 --- /dev/null +++ b/distr/util/safe_mem.c @@ -0,0 +1,97 @@ +/* LINTLIBRARY */ + +#include +#include "util.h" + +/* + * These are interface routines to be placed between a program and the + * system memory allocator. + * + * It forces well-defined semantics for several 'borderline' cases: + * + * malloc() of a 0 size object is guaranteed to return something + * which is not 0, and can safely be freed (but not dereferenced) + * free() accepts (silently) an 0 pointer + * realloc of a 0 pointer is allowed, and is equiv. to malloc() + * For the IBM/PC it forces no object > 64K; note that the size argument + * to malloc/realloc is a 'long' to catch this condition + * + * The function pointer MMoutOfMemory() contains a vector to handle a + * 'out-of-memory' error (which, by default, points at a simple wrap-up + * and exit routine). + */ + +#ifdef __cplusplus +extern "C" { +#endif + +extern char *MMalloc(long); +extern void MMout_of_memory(long); +extern char *MMrealloc(char *, long); + +void (*MMoutOfMemory)(long) = MMout_of_memory; + +#ifdef __cplusplus +} +#endif + + +/* MMout_of_memory -- out of memory for lazy people, flush and exit */ +void +MMout_of_memory(long size) +{ + (void) fflush(stdout); + (void) fprintf(stderr, "\nout of memory allocating %lu bytes\n", + (unsigned long) size); + exit(1); +} + + +char * +MMalloc(long size) +{ + char *p; + +#ifdef IBMPC + if (size > 65000L) { + if (MMoutOfMemory != (void (*)(long)) 0 ) (*MMoutOfMemory)(size); + return NIL(char); + } +#endif + if (size == 0) size = sizeof(long); + if ((p = (char *) malloc((unsigned long) size)) == NIL(char)) { + if (MMoutOfMemory != 0 ) (*MMoutOfMemory)(size); + return NIL(char); + } + return p; +} + + +char * +MMrealloc(char *obj, long size) +{ + char *p; + +#ifdef IBMPC + if (size > 65000L) { + if (MMoutOfMemory != 0 ) (*MMoutOfMemory)(size); + return NIL(char); + } +#endif + if (obj == NIL(char)) return MMalloc(size); + if (size <= 0) size = sizeof(long); + if ((p = (char *) realloc(obj, (unsigned long) size)) == NIL(char)) { + if (MMoutOfMemory != 0 ) (*MMoutOfMemory)(size); + return NIL(char); + } + return p; +} + + +void +MMfree(char *obj) +{ + if (obj != 0) { + free(obj); + } +} diff --git a/distr/util/saveimage.c b/distr/util/saveimage.c new file mode 100644 index 0000000..32332ef --- /dev/null +++ b/distr/util/saveimage.c @@ -0,0 +1,229 @@ +/* LINTLIBRARY */ + + +/* + * saveimage.c -- + * + * Function to save an executable copy of the current process's + * image in a file. + * + */ + +#include +#include "util.h" + +#ifdef BSD +#include +#include +#include +#include + +extern int errno; + +#define BUFSIZE 8192 + +extern long lseek(); /* For lint */ +extern int getpagesize(); +extern char *sbrk(); + +static int copy_file(); +static int pad_file(); + + +int +util_save_image(char const *orig_file_name, char const *save_file_name) +{ + int origFd = -1, saveFd = -1; + char *start_data, *end_data, *start_text, *end_round; + struct exec old_hdr, new_hdr; + struct stat old_stat; + int n, page_size, length_text, length_data; + + if ((origFd = open(orig_file_name, 0)) < 0) { + perror(orig_file_name); + (void) fprintf(stderr, "Cannot open original a.out file\n"); + goto bad; + } + + if (fstat(origFd, &old_stat) < 0) { + perror(orig_file_name); + (void) fprintf(stderr, "Cannot stat original a.out file\n"); + goto bad; + } + + /* + * Read the a.out header from the original file. + */ + if (read(origFd, (char *) &old_hdr, sizeof(old_hdr)) != sizeof(old_hdr)) { + perror(orig_file_name); + (void) fprintf(stderr, "Cannot read original a.out header\n"); + goto bad; + } + if (N_BADMAG(old_hdr)) { + (void) fprintf(stderr, "File %s has a bad magic number (%o)\n", + orig_file_name, old_hdr.a_magic); + goto bad; + } + if (old_hdr.a_magic != ZMAGIC) { + (void) fprintf(stderr, "File %s is not demand-paged\n", orig_file_name); + goto bad; + } + + /* + * Open the output file. + */ + if (access(save_file_name, /* F_OK */ 0) == 0) { + (void) unlink(save_file_name); + } + if ((saveFd = creat(save_file_name, 0777)) < 0) { + if (errno == ETXTBSY) { + (void) unlink(save_file_name); + saveFd = creat(save_file_name, 0777); + } + if (saveFd < 0) { + perror(save_file_name); + (void) fprintf(stderr, "Cannot create save file.\n"); + goto bad; + } + } + + /* + * Find out how far the data segment extends. + */ + new_hdr = old_hdr; + end_data = sbrk(0); + page_size = getpagesize(); + n = ((((int) end_data) + page_size - 1) / page_size) * page_size; + end_round = (char *) n; + if (end_round > end_data) { + end_data = sbrk(end_round - end_data); + } + +#ifdef vax + start_text = 0; + length_text = new_hdr.a_text; + start_data = (char *) old_hdr.a_text; + length_data = end_data - start_data; +#endif vax +#ifdef sun + start_text = (char *) N_TXTADDR(old_hdr) + sizeof(old_hdr); + length_text = old_hdr.a_text - sizeof(old_hdr); + start_data = (char *) N_DATADDR(old_hdr); + length_data = end_data - start_data; +#endif sun + new_hdr.a_data = end_data - start_data; + new_hdr.a_bss = 0; + + /* + * First, the header plus enough pad to extend up to N_TXTOFF. + */ + if (write(saveFd, (char *) &new_hdr, (int) sizeof(new_hdr)) != + sizeof(new_hdr)) { + perror("write"); + (void) fprintf(stderr, "Error while copying header.\n"); + goto bad; + } + if (! pad_file(saveFd, N_TXTOFF(old_hdr) - sizeof(new_hdr))) { + (void) fprintf(stderr, "Error while padding.\n"); + goto bad; + } + + + /* + * Copy our text segment + */ + if (write(saveFd, start_text, length_text) != length_text) { + perror("write"); + (void) fprintf(stderr, "Error while copying text segment.\n"); + goto bad; + } + + + /* + * Copy our data segment + */ + if (write(saveFd, start_data, length_data) != length_data) { + perror("write"); + (void) fprintf(stderr, "Error while copying data segment.\n"); + goto bad; + } + + /* + * Copy the symbol table and everything else. + * This takes us to the end of the original file. + */ + (void) lseek(origFd, (long) N_SYMOFF(old_hdr), 0); + if (! copy_file(origFd, saveFd, old_stat.st_size - N_SYMOFF(old_hdr))) { + (void) fprintf(stderr, "Error while copying symbol table.\n"); + goto bad; + } + (void) close(origFd); + (void) close(saveFd); + return 1; + +bad: + if (origFd >= 0) (void) close(origFd); + if (saveFd >= 0) (void) close(saveFd); + return 0; +} + + +static int +copy_file(inFd, outFd, nbytes) +int inFd, outFd; +unsigned long nbytes; +{ + char buf[BUFSIZE]; + int nread, ntoread; + + while (nbytes > 0) { + ntoread = nbytes; + if (ntoread > sizeof buf) ntoread = sizeof buf; + if ((nread = read(inFd, buf, ntoread)) != ntoread) { + perror("read"); + return (0); + } + if (write(outFd, buf, nread) != nread) { + perror("write"); + return (0); + } + nbytes -= nread; + } + + return (1); +} + + +static int +pad_file(outFd, nbytes) +int outFd; +int nbytes; +{ + char buf[BUFSIZE]; + int nzero; + + nzero = (nbytes > sizeof(buf)) ? sizeof(buf) : nbytes; + bzero(buf, nzero); + while (nbytes > 0) { + nzero = (nbytes > sizeof(buf)) ? sizeof(buf) : nbytes; + if (write(outFd, buf, nzero) != nzero) { + perror("write"); + return (0); + } + nbytes -= nzero; + } + + return (1); +} +#else + +/* ARGSUSED */ +int +util_save_image(char const *orig_file_name, char const *save_file_name) +{ + (void) fprintf(stderr, + "util_save_image: not implemented on your operating system\n"); + return 0; +} + +#endif diff --git a/distr/util/state.c b/distr/util/state.c new file mode 100644 index 0000000..ef830aa --- /dev/null +++ b/distr/util/state.c @@ -0,0 +1,82 @@ +#ifdef lint +util_restart_save_state() +{ + return 0; +} + + +util_restart_restore_state() +{ +} + +#else + +static char rcsid[] = "$Id: state.c,v 1.1 1997/11/04 22:38:50 fabio Exp $"; + +#ifdef vax +int util_restart_state[32]; + +util_restart_save_state() +{ + asm("movl sp,_util_save_sp"); + asm("movl r1,_util_restart_state"); + asm("movl r2,_util_restart_state+4"); + asm("movl r3,_util_restart_state+8"); + asm("movl r4,_util_restart_state+12"); + asm("movl r5,_util_restart_state+16"); + asm("movl r6,_util_restart_state+20"); + asm("movl r7,_util_restart_state+24"); + asm("movl r8,_util_restart_state+28"); + asm("movl r9,_util_restart_state+32"); + asm("movl r10,_util_restart_state+36"); + asm("movl r11,_util_restart_state+40"); + asm("movl 8(fp),_util_restart_state+44"); + asm("movl 12(fp),_util_restart_state+48"); + asm("movl 16(fp),_util_restart_state+52"); + asm("movl $0,r0"); +} + +util_restart_restore_state() +{ + asm("movl _util_restart_state,r1"); + asm("movl _util_restart_state+4,r2"); + asm("movl _util_restart_state+8,r3"); + asm("movl _util_restart_state+12,r4"); + asm("movl _util_restart_state+16,r5"); + asm("movl _util_restart_state+20,r6"); + asm("movl _util_restart_state+24,r7"); + asm("movl _util_restart_state+28,r8"); + asm("movl _util_restart_state+32,r9"); + asm("movl _util_restart_state+36,r10"); + asm("movl _util_restart_state+40,r11"); + asm("movl _util_restart_state+44,ap"); + asm("movl _util_restart_state+48,fp"); + asm("addl3 fp,$4,sp"); + asm("movl _util_restart_state+52,r0"); + asm("jmp (r0)"); +} +#endif + + +#if defined(sun) && ! defined(sparc) +int util_restart_state[32]; + +util_restart_save_state() +{ + asm("movel sp,_util_save_sp"); + asm("movel sp@,_util_restart_state"); + asm("movel sp@(0x4),_util_restart_state+4"); + asm("moveml #0xFFFF,_util_restart_state+8"); + return 0; +} + +util_restart_restore_state() +{ + asm("moveml _util_restart_state+8,#0xFFFF"); + asm("movel _util_restart_state+4,sp@(0x4)"); + asm("movel _util_restart_state,sp@"); + return 1; +} +#endif + +#endif diff --git a/distr/util/strsav.c b/distr/util/strsav.c new file mode 100644 index 0000000..454e237 --- /dev/null +++ b/distr/util/strsav.c @@ -0,0 +1,14 @@ +/* LINTLIBRARY */ + +#include +#include "util.h" + + +/* + * util_strsav -- save a copy of a string + */ +char * +util_strsav(char const *s) +{ + return strcpy(ALLOC(char, strlen(s)+1), s); +} diff --git a/distr/util/stub.c b/distr/util/stub.c new file mode 100644 index 0000000..93f57e6 --- /dev/null +++ b/distr/util/stub.c @@ -0,0 +1,82 @@ +/* LINTLIBRARY */ + +#ifdef LACK_SYS5 + +char * +memcpy(s1, s2, n) +char *s1, *s2; +int n; +{ + extern bcopy(); + bcopy(s2, s1, n); + return s1; +} + +char * +memset(s, c, n) +char *s; +int c; +int n; +{ + extern bzero(); + register int i; + + if (c == 0) { + bzero(s, n); + } else { + for(i = n-1; i >= 0; i--) { + *s++ = c; + } + } + return s; +} + +char * +strchr(s, c) +char *s; +int c; +{ + extern char *index(); + return index(s, c); +} + +char * +strrchr(s, c) +char *s; +int c; +{ + extern char *rindex(); + return rindex(s, c); +} + + +#endif + +#ifndef UNIX +#include + +FILE * +popen(string, mode) +const char *string; +const char *mode; +{ + (void) fprintf(stderr, "popen not supported on your operating system\n"); + return NULL; +} + + +int +pclose(fp) +FILE *fp; +{ + (void) fprintf(stderr, "pclose not supported on your operating system\n"); + return -1; +} +#endif + +/* put something here in case some compilers abort on empty files ... */ +int +util_do_nothing() +{ + return 1; +} diff --git a/distr/util/test-res.c b/distr/util/test-res.c new file mode 100644 index 0000000..e7af9c9 --- /dev/null +++ b/distr/util/test-res.c @@ -0,0 +1,57 @@ +#include +#include "util.h" + + +main(argc, argv, environ) +int argc; +char **argv; +char **environ; +{ + int i; + char **ep, *prog; + + prog = util_path_search(argv[0]); + if (prog == NIL(char)) { + (void) fprintf(stderr, "Cannot find current executable\n"); + exit(1); + } + util_restart(prog, "a.out", 0); + + i = recur(10); + (void) fprintf(stderr, "terminated normally with i = %d\n", i); + + (void) printf("argc is %d\n", argc); + + for(i = 0, ep = argv; *ep != 0; i++, ep++) { + (void) printf("%08x (%08x-%08x)\targv[%d]:\t%s\n", + ep, *ep, *ep + strlen(*ep), i, *ep); + } + + i = 0; + for(i = 0, ep = environ; *ep != 0; ep++, i++) { + (void) printf("%08x (%08x-%08x)\tenviron[%d]:\t%s\n", + ep, *ep, *ep + strlen(*ep), i, *ep); + } + + (void) fprintf(stderr, "returning with status=4\n"); + return 4; +} + + +recur(cnt) +{ + int i, j, sum; + + if (cnt > 0) { + return recur(cnt-1); + } else { + sum = 0; + for(j = 0; j < 20; j++) { + for(i = 0; i < 100000; i++) { + sum += 1; + } + (void) printf("done loop %d\n", j); + } + return sum; + } +} diff --git a/distr/util/test-sav.c b/distr/util/test-sav.c new file mode 100644 index 0000000..3140671 --- /dev/null +++ b/distr/util/test-sav.c @@ -0,0 +1,39 @@ +#include +#include "util.h" + + +/* ARGSUSED */ +static int +saveit(prog, file2) +char *prog, *file2; +{ + char *file1; + + /* get current executable name by searching the path ... */ + file1 = util_path_search(prog); + if (file1 == 0) { + (void) fprintf(stderr, "cannot locate current executable\n"); + return 1; + } + + /* users name for the new executable -- perform tilde-expansion */ + if (! util_save_image(file1, file2)) { + (void) fprintf(stderr, "error occured during save ...\n"); + return 1; + } + FREE(file1); + return 0; +} + +int restart; + +main(argc, argv) +char **argv; +{ + if (restart) { + (void) printf("restarted ...\n"); + exit(0); + } + restart = 1; + exit(saveit(argv[0], "foobar")); +} diff --git a/distr/util/texpand.c b/distr/util/texpand.c new file mode 100644 index 0000000..c14defe --- /dev/null +++ b/distr/util/texpand.c @@ -0,0 +1,57 @@ +/* LINTLIBRARY */ + +#include +#include "util.h" + +#ifdef BSD +#include +#endif + + +char * +util_tilde_expand(char const *fname) +{ +#ifdef BSD + struct passwd *userRecord; + char username[256], *filename; + register int i, j; + + filename = ALLOC(char, strlen(fname) + 256); + + /* Clear the return string */ + i = 0; + filename[0] = '\0'; + + /* Tilde? */ + if (fname[0] == '~') { + j = 0; + i = 1; + while ((fname[i] != '\0') && (fname[i] != '/')) { + username[j++] = fname[i++]; + } + username[j] = '\0'; + + if (username[0] == '\0') { + /* ~/ resolves to home directory of current user */ + if ((userRecord = getpwuid(getuid())) != 0) { + (void) strcat(filename, userRecord->pw_dir); + } else { + i = 0; + } + } else { + /* ~user/ resolves to home directory of 'user' */ + if ((userRecord = getpwnam(username)) != 0) { + (void) strcat(filename, userRecord->pw_dir); + } else { + i = 0; + } + } + } + + /* Concantenate remaining portion of file name */ + (void) strcat(filename, fname + i); + return filename; +#else + return strsav(fname); +#endif +} diff --git a/distr/util/tmpfile.c b/distr/util/tmpfile.c new file mode 100644 index 0000000..35b6fbb --- /dev/null +++ b/distr/util/tmpfile.c @@ -0,0 +1,42 @@ +/* + * tmpfile -- open an unnamed temporary file + * + * This is the ANSI C standard routine; we have hacks here because many + * compilers/systems do not have it yet. + */ + +/* LINTLIBRARY */ + + +#include +#include "util.h" + + +#ifdef UNIX + +FILE * +tmpfile() +{ + FILE *fp; + char *filename, *junk; + + junk = strsav((char *)"/usr/tmp/cudd-XXXXXX"); + filename = mktemp(junk); + if ((fp = fopen(filename, "w+")) == NULL) { + FREE(junk); + return NULL; + } + (void) unlink(filename); + FREE(junk); + return fp; +} + +#else + +FILE * +tmpfile() +{ + return fopen("utiltmp", "w+"); +} + +#endif diff --git a/distr/util/util.h b/distr/util/util.h new file mode 100644 index 0000000..152e117 --- /dev/null +++ b/distr/util/util.h @@ -0,0 +1,212 @@ +/* $Id: util.h,v 1.8 2007/08/24 18:17:31 fabio Exp fabio $ */ + +#ifndef UTIL_H +#define UTIL_H + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(__GNUC__) +# define UTIL_INLINE __inline__ +# if __GNUC__ > 2 || __GNUC_MINOR__ >= 7 +# define UTIL_UNUSED __attribute__ ((unused)) +# else +# define UTIL_UNUSED +# endif +#else +# define UTIL_INLINE +# define UTIL_UNUSED +#endif + +#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 + +#if SIZEOF_VOID_P == 8 && SIZEOF_INT == 4 +typedef long util_ptrint; +#else +typedef int util_ptrint; +#endif + +/* #define USE_MM */ /* choose libmm.a as the memory allocator */ + +/* these are too entrenched to get away with changing the name */ +#define strsav util_strsav +#include +extern char *optarg; +extern int optind, opterr; + +#define NIL(type) ((type *) 0) + +#if defined(USE_MM) || defined(MNEMOSYNE) +/* + * assumes the memory manager is either libmm.a or libmnem.a + * 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 + * libmnem.a: + * - reports memory leaks + * - is used in conjunction with the mnemalyse postprocessor + */ +#ifdef MNEMOSYNE +#include "mnemosyne.h" +#define ALLOC(type, num) \ + ((num) ? ((type *) malloc(sizeof(type) * (num))) : \ + ((type *) malloc(sizeof(long)))) +#else +#define ALLOC(type, num) \ + ((type *) malloc(sizeof(type) * (num))) +#endif +#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((char *) (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(apollo) || defined(__osf__) || defined(__SVR4) || defined(__GNUC__) +#define VOID_OR_INT void +#define VOID_OR_CHAR void +#else +#define VOID_OR_INT int +#define VOID_OR_CHAR char +#endif + + +/* No machines seem to have much of a problem with these */ +#include +#include + + +/* Some machines fail to define some functions in stdio.h */ +#if !defined(__STDC__) && !defined(__cplusplus) +extern FILE *popen(), *tmpfile(); +extern int pclose(); +#endif + + +/* most machines don't give us a header file for these */ +#if (defined(__STDC__) || defined(__cplusplus) || defined(ultrix)) && !defined(MNEMOSYNE) || defined(__SVR4) +# include +#else +# ifndef _IBMR2 + extern VOID_OR_INT abort(), exit(); +# endif +# if !defined(MNEMOSYNE) && !defined(_IBMR2) + extern VOID_OR_INT free (void *); + extern VOID_OR_CHAR *malloc(), *realloc(); +# endif + extern char *getenv(); + extern int system(); + extern double atof(); +#endif + + +/* some call it strings.h, some call it string.h; others, also have memory.h */ +#if defined(__STDC__) || defined(__cplusplus) || defined(_IBMR2) || defined(ultrix) +#include +#else +/* ANSI C string.h -- 1/11/88 Draft Standard */ +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 + + +#ifdef __STDC__ +#include +#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) ; +#endif +#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 + + +/* These arguably do NOT belong in util.h */ +#define ABS(a) ((a) < 0 ? -(a) : (a)) +#define MAX(a,b) ((a) > (b) ? (a) : (b)) +#define MIN(a,b) ((a) < (b) ? (a) : (b)) + + +#ifndef USE_MM +extern char *MMalloc (long); +extern void MMout_of_memory (long); +extern void (*MMoutOfMemory) (long); +extern char *MMrealloc (char *, long); +#endif + +extern long util_cpu_time (void); +extern int util_getopt (int, char * const *, char const *); +extern void util_getopt_reset (void); +extern char *util_path_search (char const *); +extern char *util_file_search (char const *, char *, char const *); +extern int util_pipefork (char * const *, FILE **, FILE **, int *); +extern void util_print_cpu_stats (FILE *); +extern char *util_print_time (unsigned long); +extern int util_save_image (char const *, char const *); +extern char *util_strsav (char const *); +extern char *util_tilde_expand (char const *); +extern void util_restart (char const *, char const *, int); + + +/* util_getopt() global variables (ack !) */ +extern int util_optind; +extern char *util_optarg; + +extern unsigned long getSoftDataLimit (void); + +#ifdef __cplusplus +} +#endif + +#endif /* UTIL_H */