All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.github.javabdd.BDDFactory Maven / Gradle / Ivy

//////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2003-2023 John Whaley and others
//
// See the CONTRIBUTORS file(s) distributed with this work for additional
// information regarding copyright ownership.
//
// This program and the accompanying materials are made available under the
// terms of the GNU Library General Public License v2 or later, which is
// available at https://spdx.org/licenses/LGPL-2.0-or-later.html
//
// SPDX-License-Identifier: LGPL-2.0-or-later
//////////////////////////////////////////////////////////////////////////////

package com.github.javabdd;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.math.BigInteger;
import java.security.AccessControlException;
import java.util.Arrays;
import java.util.BitSet;
import java.util.Collection;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.StringTokenizer;

/**
 * Interface for the creation and manipulation of BDDs.
 *
 * @see com.github.javabdd.BDD
 */
public abstract class BDDFactory {
    private static final boolean DEBUG = false;

    private static final boolean ASSERT_FILL_IN_VAR_INDICES = false;

    public static final String getProperty(String key, String def) {
        try {
            return System.getProperty(key, def);
        } catch (AccessControlException e) {
            return def;
        }
    }

    /**
     * Initializes a BDD factory with the given initial node table size and operation cache size. Uses the "java"
     * factory.
     *
     * @param nodenum initial node table size
     * @param cachesize operation cache size
     * @return BDD factory object
     */
    public static BDDFactory init(int nodenum, int cachesize) {
        String bddpackage = getProperty("bdd", "java");
        return init(bddpackage, nodenum, cachesize);
    }

    /**
     * Initializes a BDD factory of the given type with the given initial node table size and operation cache size. The
     * type is a string that can be "j", "java", "test", "typed", or a name of a class that has an init() method that
     * returns a BDDFactory. If it fails, it falls back to the "java" factory.
     *
     * @param bddpackage BDD package string identifier
     * @param nodenum initial node table size
     * @param cachesize operation cache size
     * @return BDD factory object
     */
    public static BDDFactory init(String bddpackage, int nodenum, int cachesize) {
        try {
            if (bddpackage.equals("j") || bddpackage.equals("java")) {
                return JFactory.init(nodenum, cachesize);
            } else if (bddpackage.equals("zdd")) {
                BDDFactory bdd = JFactory.init(nodenum, cachesize);
                ((JFactory)bdd).ZDD = true;
                return bdd;
            } else {
                System.err.println("Unknown BDD package: " + bddpackage);
            }
        } catch (LinkageError e) {
            System.err.println("Could not load BDD package " + bddpackage + ": " + e.getLocalizedMessage());
        }
        try {
            Class c = Class.forName(bddpackage);
            Method m = c.getMethod("init", new Class[] {int.class, int.class});
            return (BDDFactory)m.invoke(null, new Object[] {nodenum, cachesize});
        } catch (ClassNotFoundException e) {
        } catch (NoSuchMethodException e) {
        } catch (IllegalAccessException e) {
        } catch (InvocationTargetException e) {
        }
        // falling back to default java implementation.
        return JFactory.init(nodenum, cachesize);
    }

    /**
     * Logical 'and'.
     */
    public static final BDDOp and = new BDDOp(0, "and");

    /**
     * Logical 'xor'.
     */
    public static final BDDOp xor = new BDDOp(1, "xor");

    /**
     * Logical 'or'.
     */
    public static final BDDOp or = new BDDOp(2, "or");

    /**
     * Logical 'nand'.
     */
    public static final BDDOp nand = new BDDOp(3, "nand");

    /**
     * Logical 'nor'.
     */
    public static final BDDOp nor = new BDDOp(4, "nor");

    /**
     * Logical 'implication'.
     */
    public static final BDDOp imp = new BDDOp(5, "imp");

    /**
     * Logical 'bi-implication'.
     */
    public static final BDDOp biimp = new BDDOp(6, "biimp");

    /**
     * Set difference.
     */
    public static final BDDOp diff = new BDDOp(7, "diff");

    /**
     * Less than.
     */
    public static final BDDOp less = new BDDOp(8, "less");

    /**
     * Inverse implication.
     */
    public static final BDDOp invimp = new BDDOp(9, "invimp");

    /**
     * Enumeration class for binary operations on BDDs. Use the static fields in BDDFactory to access the different
     * binary operations.
     */
    public static class BDDOp {
        final int id;

        final String name;

        private BDDOp(int id, String name) {
            this.id = id;
            this.name = name;
        }

        @Override
        public String toString() {
            return name;
        }
    }

    /**
     * Construct a new BDDFactory.
     */
    protected BDDFactory() {
        String s = this.getClass().toString();
        if (DEBUG) {
            s = s.substring(s.lastIndexOf('.') + 1);
            System.out.println("Using BDD package: " + s);
        }
    }

    /**
     * Returns true if this is a ZDD factory, false otherwise.
     *
     * @return true if this is a ZDD factory, false otherwise
     */
    public boolean isZDD() {
        return false;
    }

    /**
     * Get the constant false BDD.
     *
     * 

* Compare to bdd_false. *

* * @return constant false BDD */ public abstract BDD zero(); /** * Get the constant true BDD. * *

* Compare to bdd_true. *

* * @return constant true BDD */ public abstract BDD one(); /** * Get the constant universe BDD. (The universe BDD differs from the one BDD in ZDD mode.) * *

* Compare to bdd_true. *

* * @return constant universe BDD */ public BDD universe() { return one(); } /** * Get an empty BDDVarSet. * *

* Compare to bdd_true. *

* * @return empty BDDVarSet */ public BDDVarSet emptySet() { return new BDDVarSet.DefaultImpl(one()); } /** * Build a cube from an array of variables. * *

* Compare to bdd_buildcube. *

* * @param value bitset * @param variables BDDs for variables * @return cube */ public BDD buildCube(int value, List variables) { BDD result = universe(); Iterator i = variables.iterator(); // int z = 0; while (i.hasNext()) { BDD var = i.next(); if ((value & 0x1) != 0) { var = var.id(); } else { var = var.not(); } result.andWith(var); // ++z; value >>= 1; } return result; } /** * Build a cube from an array of variables. * *

* Compare to bdd_ibuildcube. *

* * @param value bitset * @param variables variables indices * @return cube */ public BDD buildCube(int value, int[] variables) { BDD result = universe(); for (int z = 0; z < variables.length; z++, value >>= 1) { BDD v; if ((value & 0x1) != 0) { v = ithVar(variables[variables.length - z - 1]); } else { v = nithVar(variables[variables.length - z - 1]); } result.andWith(v); } return result; } /** * Builds a BDD variable set from an integer array. The integer array {@code varset} holds the variable numbers. The * BDD variable set is represented by a conjunction of all the variables in their positive form. * *

* Compare to bdd_makeset. *

* * @param varset variable array * @return BDD variable set */ public BDDVarSet makeSet(int[] varset) { BDDVarSet res = emptySet(); int varnum = varset.length; for (int v = varnum - 1; v >= 0; --v) { res.unionWith(varset[v]); } return res; } /**** STARTUP / SHUTDOWN ****/ /** * Compare to bdd_init. * * @param nodenum the initial number of BDD nodes * @param cachesize the size of caches used by the BDD operators */ protected abstract void initialize(int nodenum, int cachesize); /** * Returns true if this BDD factory is initialized, false otherwise. * *

* Compare to bdd_isrunning. *

* * @return true if this BDD factory is initialized */ public abstract boolean isInitialized(); /** * Reset the BDD factory to its initial state. Everything is reallocated from scratch. This is like calling done() * followed by initialize(). */ public void reset() { int nodes = getNodeTableSize(); int cache = getCacheSize(); domain = null; fdvarnum = 0; firstbddvar = 0; done(); initialize(nodes, cache); } /** * This function frees all memory used by the BDD package and resets the package to its uninitialized state. The BDD * package is no longer usable after this call. * *

* Compare to bdd_done. *

*/ public abstract void done(); /** * Sets the error condition. This will cause the BDD package to throw an exception at the next garbage collection. * * @param code the error code to set */ public abstract void setError(int code); /** * Clears any outstanding error condition. */ public abstract void clearError(); /**** CACHE/TABLE PARAMETERS ****/ /** * Set the maximum available number of BDD nodes. * *

* Compare to bdd_setmaxnodenum. *

* * @param size maximum number of nodes * @return old value */ public abstract int setMaxNodeNum(int size); /** * Set minimum percentage of nodes to be reclaimed after a garbage collection. If this percentage is not reclaimed, * the node table will be grown. The range of x is 0..1. The default is .20. * *

* Compare to bdd_setminfreenodes. *

* * @param x number from 0 to 1 * @return old value */ public abstract double setMinFreeNodes(double x); /** * Set maximum number of nodes by which to increase node table after a garbage collection. * *

* Compare to bdd_setmaxincrease. *

* * @param x maximum number of nodes by which to increase node table * @return old value */ public abstract int setMaxIncrease(int x); /** * Set factor by which to increase node table after a garbage collection. The amount of growth is still limited by * {@code setMaxIncrease()}. * * @param x factor by which to increase node table after GC * @return old value */ public abstract double setIncreaseFactor(double x); /** * Sets the cache ratio for the operator caches. When the node table grows, operator caches will also grow to * maintain the ratio. * *

* Compare to bdd_setcacheratio. *

* * @param x cache ratio * @return old cache ratio */ public abstract double setCacheRatio(double x); /** * Sets the node table size. * * @param n new size of table * @return old size of table */ public abstract int setNodeTableSize(int n); /** * Sets cache size. * * @param n new cache size * @return old cache size */ public abstract int setCacheSize(int n); /**** VARIABLE NUMBERS ****/ /** * Returns the number of defined variables. * *

* Compare to bdd_varnum. *

* * @return number of defined variables */ public abstract int varNum(); /** * Set the number of used BDD variables. It can be called more than one time, but only to increase the number of * variables. * *

* Compare to bdd_setvarnum. *

* * @param num new number of BDD variables * @return old number of BDD variables */ public abstract int setVarNum(int num); /** * Add extra BDD variables. Extends the current number of allocated BDD variables with num extra variables. * *

* Compare to bdd_extvarnum. *

* * @param num number of BDD variables to add * @return old number of BDD variables */ public int extVarNum(int num) { int start = varNum(); if (num < 0 || num > 0x3FFFFFFF) { throw new BDDException(); } setVarNum(start + num); return start; } /** * Returns a BDD representing the I'th variable. (One node with the children true and false.) The requested variable * must be in the (zero-indexed) range defined by {@code setVarNum}. * *

* Compare to bdd_ithvar. *

* * @param var the variable number * @return the I'th variable on success, otherwise the constant false BDD */ public abstract BDD ithVar(int var); /** * Returns a BDD representing the negation of the I'th variable. (One node with the children false and true.) The * requested variable must be in the (zero-indexed) range defined by {@code setVarNum}. * *

* Compare to bdd_nithvar. *

* * @param var the variable number * @return the negated I'th variable on success, otherwise the constant false BDD */ public abstract BDD nithVar(int var); /**** INPUT / OUTPUT ****/ /** * Prints all used entries in the node table. * *

* Compare to bdd_printall. *

*/ public abstract void printAll(); /** * Prints the node table entries used by a BDD. * *

* Compare to bdd_printtable. *

* * @param b BDD */ public abstract void printTable(BDD b); /** * Loads a BDD from a file. * *

* Compare to bdd_load. *

* * @param filename filename * @return BDD * @throws IOException In case of an I/O error. */ public BDD load(String filename) throws IOException { BufferedReader r = null; try { r = new BufferedReader(new FileReader(filename)); BDD result = load(r); return result; } finally { if (r != null) { try { r.close(); } catch (IOException e) { } } } } // TODO: error code from bdd_load (?) /** * Loads a BDD from the given input. * *

* Compare to bdd_load. *

* * @param ifile reader * @return BDD * @throws IOException In case of an I/O error. */ public BDD load(BufferedReader ifile) throws IOException { return load(ifile, null); } /** * Loads a BDD from the given input, translating BDD variables according to the given map. * *

* Compare to bdd_load. *

* * @param ifile reader * @param translate variable translation map * @return BDD * @throws IOException In case of an I/O error. */ public BDD load(BufferedReader ifile, int[] translate) throws IOException { tokenizer = null; int lh_nodenum = Integer.parseInt(readNext(ifile)); int vnum = Integer.parseInt(readNext(ifile)); // Check for constant true / false if (lh_nodenum == 0 && vnum == 0) { int r = Integer.parseInt(readNext(ifile)); return r == 0 ? zero() : universe(); } // Not actually used. int[] loadvar2level = new int[vnum]; for (int n = 0; n < vnum; n++) { loadvar2level[n] = Integer.parseInt(readNext(ifile)); } if (vnum > varNum()) { setVarNum(vnum); } LoadHash[] lh_table = new LoadHash[lh_nodenum]; for (int n = 0; n < lh_nodenum; n++) { lh_table[n] = new LoadHash(); lh_table[n].first = -1; lh_table[n].next = n + 1; } lh_table[lh_nodenum - 1].next = -1; int lh_freepos = 0; BDD root = null; for (int n = 0; n < lh_nodenum; n++) { int key = Integer.parseInt(readNext(ifile)); int var = Integer.parseInt(readNext(ifile)); if (translate != null) { var = translate[var]; } int lowi = Integer.parseInt(readNext(ifile)); int highi = Integer.parseInt(readNext(ifile)); BDD low, high; low = loadhash_get(lh_table, lh_nodenum, lowi); high = loadhash_get(lh_table, lh_nodenum, highi); if (low == null || high == null || var < 0) { throw new BDDException("Incorrect file format"); } BDD b = ithVar(var); root = b.ite(high, low); b.free(); if (low.isZero() || low.isOne()) { low.free(); } if (high.isZero() || high.isOne()) { high.free(); } int hash = key % lh_nodenum; int pos = lh_freepos; lh_freepos = lh_table[pos].next; lh_table[pos].next = lh_table[hash].first; lh_table[hash].first = pos; lh_table[pos].key = key; lh_table[pos].data = root; } @SuppressWarnings("null") BDD tmproot = root.id(); for (int n = 0; n < lh_nodenum; n++) { lh_table[n].data.free(); } lh_table = null; loadvar2level = null; return tmproot; } /** * Used for tokenization during loading. */ protected StringTokenizer tokenizer; /** * Read the next token from the file. * * @param ifile reader * @return next string token * @throws IOException In case of an I/O error. */ protected String readNext(BufferedReader ifile) throws IOException { while (tokenizer == null || !tokenizer.hasMoreTokens()) { String s = ifile.readLine(); if (s == null) { throw new BDDException("Incorrect file format"); } tokenizer = new StringTokenizer(s); } return tokenizer.nextToken(); } /** * LoadHash is used to hash during loading. */ protected static class LoadHash { int key; BDD data; int first; int next; } /** * Gets a BDD from the load hash table. * * @param lh_table load hash table * @param lh_nodenum node number * @param key key * @return BDD */ protected BDD loadhash_get(LoadHash[] lh_table, int lh_nodenum, int key) { if (key < 0) { return null; } if (key == 0) { return zero(); } if (key == 1) { return universe(); } int hash = lh_table[key % lh_nodenum].first; while (hash != -1 && lh_table[hash].key != key) { hash = lh_table[hash].next; } if (hash == -1) { return null; } return lh_table[hash].data; } /** * Saves a BDD to a file. * *

* Compare to bdd_save. *

* * @param filename filename * @param var BDD * @throws IOException In case of an I/O error. */ public void save(String filename, BDD var) throws IOException { BufferedWriter is = null; try { is = new BufferedWriter(new FileWriter(filename)); save(is, var); } finally { if (is != null) { try { is.close(); } catch (IOException e) { } } } } // TODO: error code from bdd_save (?) /** * Saves a BDD to an output writer. * *

* Compare to bdd_save. *

* * @param out writer * @param r BDD * @throws IOException In case of an I/O error. */ public void save(BufferedWriter out, BDD r) throws IOException { if (r.isOne() || r.isZero()) { out.write("0 0 " + (r.isOne() ? 1 : 0) + "\n"); return; } out.write(r.nodeCount() + " " + varNum() + "\n"); for (int x = 0; x < varNum(); x++) { out.write(var2Level(x) + " "); } out.write("\n"); // Map visited = new HashMap(); BitSet visited = new BitSet(getNodeTableSize()); save_rec(out, visited, r.id()); // for (Iterator it = visited.keySet().iterator(); it.hasNext(); ) { // BDD b = (BDD) it.next(); // if (b != r) b.free(); // } } /** * Helper function for save(). * * @param out writer * @param visited visited nodes bitset * @param root root BDD * @return bitset index * @throws IOException In case of an I/O error. */ protected int save_rec(BufferedWriter out, BitSet visited, BDD root) throws IOException { if (root.isZero()) { root.free(); return 0; } if (root.isOne()) { root.free(); return 1; } int i = root.hashCode(); if (visited.get(i)) { root.free(); return i; } int v = i; visited.set(i); BDD h = root.high(); BDD l = root.low(); int rootvar = root.var(); root.free(); int lo = save_rec(out, visited, l); int hi = save_rec(out, visited, h); out.write(i + " "); out.write(rootvar + " "); out.write(lo + " "); out.write(hi + "\n"); return v; } // TODO: bdd_blockfile_hook // TODO: bdd_versionnum, bdd_versionstr /**** REORDERING ****/ /** * Convert from a BDD level to a BDD variable. * *

* Compare to bdd_level2var. *

* * @param level BDD level * @return BDD variable */ public abstract int level2Var(int level); /** * Convert from a BDD variable to a BDD level. * *

* Compare to bdd_var2level. *

* * @param var BDD variable * @return BDD level */ public abstract int var2Level(int var); /** * No reordering. */ public static final ReorderMethod REORDER_NONE = new ReorderMethod(0, "NONE"); /** * Reordering using a sliding window of 2. */ public static final ReorderMethod REORDER_WIN2 = new ReorderMethod(1, "WIN2"); /** * Reordering using a sliding window of 2, iterating until no further progress. */ public static final ReorderMethod REORDER_WIN2ITE = new ReorderMethod(2, "WIN2ITE"); /** * Reordering using a sliding window of 3. */ public static final ReorderMethod REORDER_WIN3 = new ReorderMethod(5, "WIN3"); /** * Reordering using a sliding window of 3, iterating until no further progress. */ public static final ReorderMethod REORDER_WIN3ITE = new ReorderMethod(6, "WIN3ITE"); /** * Reordering where each block is moved through all possible positions. The best of these is then used as the new * position. Potentially a very slow but good method. */ public static final ReorderMethod REORDER_SIFT = new ReorderMethod(3, "SIFT"); /** * Same as REORDER_SIFT, but the process is repeated until no further progress is done. Can be extremely slow. */ public static final ReorderMethod REORDER_SIFTITE = new ReorderMethod(4, "SIFTITE"); /** * Selects a random position for each variable. Mostly used for debugging purposes. */ public static final ReorderMethod REORDER_RANDOM = new ReorderMethod(7, "RANDOM"); /** * Enumeration class for method reordering techniques. Use the static fields in BDDFactory to access the different * reordering techniques. */ public static class ReorderMethod { final int id; final String name; private ReorderMethod(int id, String name) { this.id = id; this.name = name; } @Override public String toString() { return name; } } /** * Reorder the BDD with the given method. * *

* Compare to bdd_reorder. *

* * @param m reorder method */ public abstract void reorder(ReorderMethod m); /** * Enables automatic reordering. If method is REORDER_NONE then automatic reordering is disabled. * *

* Compare to bdd_autoreorder. *

* * @param method reorder method */ public abstract void autoReorder(ReorderMethod method); /** * Enables automatic reordering with the given (maximum) number of reorderings. If method is REORDER_NONE then * automatic reordering is disabled. * *

* Compare to bdd_autoreorder_times. *

* * @param method reorder method * @param max maximum number of reorderings */ public abstract void autoReorder(ReorderMethod method, int max); /** * Returns the current reorder method as defined by autoReorder. * *

* Compare to bdd_getreorder_method. *

* * @return ReorderMethod */ public abstract ReorderMethod getReorderMethod(); /** * Returns the number of allowed reorderings left. This value can be defined by autoReorder. * *

* Compare to bdd_getreorder_times. *

* * @return number of allowed reorderings left */ public abstract int getReorderTimes(); /** * Disable automatic reordering until enableReorder is called. Reordering is enabled by default as soon as any * variable blocks have been defined. * *

* Compare to bdd_disable_reorder. *

*/ public abstract void disableReorder(); /** * Enable automatic reordering after a call to disableReorder. * *

* Compare to bdd_enable_reorder. *

*/ public abstract void enableReorder(); /** * Enables verbose information about reordering. A value of zero means no information, one means some information * and greater than one means lots of information. * * @param v the new verbose level * @return the old verbose level */ public abstract int reorderVerbose(int v); /** * This function sets the current variable order to be the one defined by neworder. The variable parameter neworder * is interpreted as a sequence of variable indices and the new variable order is exactly this sequence. The array * must contain all the variables defined so far. If, for instance the current number of variables is 3 and neworder * contains [1; 0; 2] then the new variable order is v1 < v0 < v2. * *

* Note that this operation must walk through the node table many times, and therefore it is much more efficient to * call this when the node table is small. *

* * @param neworder new variable order */ public abstract void setVarOrder(int[] neworder); /** * Gets the current variable order. * * @return variable order */ public int[] getVarOrder() { int n = varNum(); int[] result = new int[n]; for (int i = 0; i < n; ++i) { result[i] = level2Var(i); } return result; } /** * Make a new BDDPairing object. * *

* Compare to bdd_newpair. *

* * @return BDD pairing */ public abstract BDDPairing makePair(); /** * Make a new pairing that maps from one variable to another. * * @param oldvar old variable * @param newvar new variable * @return BDD pairing */ public BDDPairing makePair(int oldvar, int newvar) { BDDPairing p = makePair(); p.set(oldvar, newvar); return p; } /** * Make a new pairing that maps from one variable to another BDD. * * @param oldvar old variable * @param newvar new BDD * @return BDD pairing */ public BDDPairing makePair(int oldvar, BDD newvar) { BDDPairing p = makePair(); p.set(oldvar, newvar); return p; } /** * Make a new pairing that maps from one BDD domain to another. * * @param oldvar old BDD domain * @param newvar new BDD domain * @return BDD pairing */ public BDDPairing makePair(BDDDomain oldvar, BDDDomain newvar) { BDDPairing p = makePair(); p.set(oldvar, newvar); return p; } /** * Swap two variables. * *

* Compare to bdd_swapvar. *

* * @param v1 first variable * @param v2 second variable */ public abstract void swapVar(int v1, int v2); /**** VARIABLE BLOCKS ****/ /** * Adds a new variable block for reordering. * *

* Creates a new variable block with the variables in the variable set var. The variables in var must be contiguous. *

* *

* The fixed parameter sets the block to be fixed (no reordering of its child blocks is allowed) or free. *

* *

* Compare to bdd_addvarblock. *

* * @param var variable * @param fixed fixed or free */ public void addVarBlock(BDDVarSet var, boolean fixed) { int[] v = var.toArray(); int first, last; if (v.length < 1) { throw new BDDException("Invalid parameter for addVarBlock"); } first = last = v[0]; for (int n = 1; n < v.length; n++) { if (v[n] < first) { first = v[n]; } if (v[n] > last) { last = v[n]; } } addVarBlock(first, last, fixed); } // TODO: handle error code for addVarBlock. /** * Adds a new variable block for reordering. * *

* Creates a new variable block with the variables numbered first through last, inclusive. *

* *

* The fixed parameter sets the block to be fixed (no reordering of its child blocks is allowed) or free. *

* *

* Compare to bdd_intaddvarblock. *

* * @param first first variable number * @param last last variable number * @param fixed fixed or free */ public abstract void addVarBlock(int first, int last, boolean fixed); // TODO: handle error code for addVarBlock. // TODO: fdd_intaddvarblock (?) /** * Add a variable block for all variables. * *

* Adds a variable block for all BDD variables declared so far. Each block contains one variable only. More variable * blocks can be added later with the use of addVarBlock -- in this case the tree of variable blocks will have the * blocks of single variables as the leafs. *

* *

* Compare to bdd_varblockall. *

*/ public abstract void varBlockAll(); /** * Clears all the variable blocks that have been defined by calls to addVarBlock. * *

* Compare to bdd_clrvarblocks. *

*/ public abstract void clearVarBlocks(); /** * Prints an indented list of the variable blocks. * *

* Compare to bdd_printorder. *

*/ public abstract void printOrder(); /**** BDD STATS ****/ /** * Counts the number of shared nodes in a collection of BDDs. Counts all distinct nodes that are used in the BDDs -- * if a node is used in more than one BDD then it only counts once. * *

* Compare to bdd_anodecount. *

* * @param r collection of BDDs * @return number of shared nodes */ public abstract int nodeCount(Collection r); /** * Get the number of allocated nodes. This includes both dead and active nodes. * *

* Compare to bdd_getallocnum. *

* * @return number of allocated nodes */ public abstract int getNodeTableSize(); /** * Get the number of active nodes in use. Note that dead nodes that have not been reclaimed yet by a garbage * collection are counted as active. * *

* Compare to bdd_getnodenum. *

* * @return number of active nodes in use */ public abstract int getNodeNum(); /** * Get the current size of the cache, in entries. * * @return size of cache */ public abstract int getCacheSize(); /** * Calculate the gain in size after a reordering. The value returned is (100*(A-B))/A, where A is previous number of * used nodes and B is current number of used nodes. * *

* Compare to bdd_reorder_gain. *

* * @return gain in size after a reordering */ public abstract int reorderGain(); /** * Print cache statistics. * *

* Compare to bdd_printstat. *

*/ public abstract void printStat(); /** * Stores statistics about garbage collections. */ public static class GCStats { public int nodes; public int freenodes; public long time; public long sumtime; public int num; protected GCStats() { } @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append("Garbage collection #"); sb.append(num); sb.append(": "); sb.append(nodes); sb.append(" nodes / "); sb.append(freenodes); sb.append(" free"); sb.append(" / "); sb.append((float)time / (float)1000); sb.append("s / "); sb.append((float)sumtime / (float)1000); sb.append("s total"); return sb.toString(); } } /** * Singleton object for GC statistics. */ protected GCStats gcstats = new GCStats(); /** * Stores statistics about the last variable reordering. */ public static class ReorderStats { public long time; public int usednum_before, usednum_after; protected ReorderStats() { } public int gain() { if (usednum_before == 0) { return 0; } return (100 * (usednum_before - usednum_after)) / usednum_before; } @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append("Went from "); sb.append(usednum_before); sb.append(" to "); sb.append(usednum_after); sb.append(" nodes, gain = "); sb.append(gain()); sb.append("% ("); sb.append(time / 1000f); sb.append(" sec)"); return sb.toString(); } } /** * Singleton object for reorder statistics. */ protected ReorderStats reorderstats = new ReorderStats(); /** * Stores statistics about the operator cache. */ public static class CacheStats { protected boolean enabled = false; public long uniqueAccess; public long uniqueChain; public long uniqueHit; public long uniqueMiss; public long opAccess; public long opHit; public long opMiss; public long swapCount; protected CacheStats() { } void copyFrom(CacheStats that) { this.uniqueAccess = that.uniqueAccess; this.uniqueChain = that.uniqueChain; this.uniqueHit = that.uniqueHit; this.uniqueMiss = that.uniqueMiss; this.opAccess = that.opAccess; this.opHit = that.opHit; this.opMiss = that.opMiss; this.swapCount = that.swapCount; } public void enableMeasurements() { enabled = true; } public void disableMeasurements() { enabled = false; } public void resetMeasurements() { uniqueAccess = 0; uniqueChain = 0; uniqueHit = 0; uniqueMiss = 0; opAccess = 0; opHit = 0; opMiss = 0; swapCount = 0; } @Override public String toString() { StringBuilder sb = new StringBuilder(); String newLine = getProperty("line.separator", "\n"); sb.append(newLine); sb.append("Cache statistics"); sb.append(newLine); sb.append("----------------"); sb.append(newLine); sb.append("Unique Access: "); sb.append(uniqueAccess); sb.append(newLine); sb.append("Unique Chain: "); sb.append(uniqueChain); sb.append(newLine); sb.append("=> Ave. chain = "); if (uniqueAccess > 0) { sb.append(((float)uniqueChain) / ((float)uniqueAccess)); } else { sb.append((float)0); } sb.append(newLine); sb.append("Unique Hit: "); sb.append(uniqueHit); sb.append(newLine); sb.append("Unique Miss: "); sb.append(uniqueMiss); sb.append(newLine); sb.append("=> Hit rate = "); if (uniqueHit + uniqueMiss > 0) { sb.append((uniqueHit) / ((float)uniqueHit + uniqueMiss)); } else { sb.append((float)0); } sb.append(newLine); sb.append("Operator Access: "); sb.append(opAccess); sb.append(newLine); sb.append("Operator Hits: "); sb.append(opHit); sb.append(newLine); sb.append("Operator Miss: "); sb.append(opMiss); sb.append(newLine); sb.append("=> Hit rate = "); if (opHit + opMiss > 0) { sb.append((opHit) / ((float)opHit + opMiss)); } else { sb.append((float)0); } sb.append(newLine); sb.append("Swap count = "); sb.append(swapCount); sb.append(newLine); return sb.toString(); } } /** * Singleton object for operator cache statistics. */ protected CacheStats cachestats = new CacheStats(); /** * Return the current operator cache statistics for this BDD factory. * * @return operator cache statistics */ public CacheStats getCacheStats() { return cachestats; } /** * Stores statistics about the maximum BDD nodes usage. */ public static class MaxUsedBddNodesStats { protected boolean enabled = false; protected int maxUsedBddNodes; protected MaxUsedBddNodesStats() { } void copyFrom(MaxUsedBddNodesStats that) { this.maxUsedBddNodes = that.maxUsedBddNodes; } public void enableMeasurements() { enabled = true; } public void disableMeasurements() { enabled = false; } public void resetMeasurements() { maxUsedBddNodes = 0; } public void newMeasurement(int newUsedBddNodes) { maxUsedBddNodes = Math.max(newUsedBddNodes, maxUsedBddNodes); } public int getMaxUsedBddNodes() { return maxUsedBddNodes; } @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append("Max used BDD nodes: "); sb.append(maxUsedBddNodes); return sb.toString(); } } /** * Singleton object for maximum used BDD nodes statistics. */ protected MaxUsedBddNodesStats maxusedbddnodesstats = new MaxUsedBddNodesStats(); /** * Return the current maximum used BDD nodes statistics for this BDD factory. * * @return maximum used BDD nodes statistics */ public MaxUsedBddNodesStats getMaxUsedBddNodesStats() { return maxusedbddnodesstats; } /** * Stores statistics about the maximum memory usage. The data is obtained through best effort, and may not be * entirely accurate. */ public static class MaxMemoryStats { protected boolean enabled = false; protected long maxMemoryBytes; protected MaxMemoryStats() { } void copyFrom(MaxMemoryStats that) { this.maxMemoryBytes = that.maxMemoryBytes; } public void enableMeasurements() { enabled = true; } public void disableMeasurements() { enabled = false; } public void resetMeasurements() { maxMemoryBytes = 0; } public void newMeasurement() { long newMemoryBytes = Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory(); maxMemoryBytes = Math.max(newMemoryBytes, maxMemoryBytes); } public long getMaxMemoryBytes() { return maxMemoryBytes; } @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append("Max memory: "); sb.append(maxMemoryBytes); sb.append(" bytes"); return sb.toString(); } } /** * Singleton object for maximum memory usage statistics. */ protected MaxMemoryStats maxmemorystats = new MaxMemoryStats(); /** * Return the current maximum memory usage statistics for this BDD factory. * * @return maximum memory usage statistics */ public MaxMemoryStats getMaxMemoryStats() { return maxmemorystats; } // TODO: bdd_sizeprobe_hook // TODO: bdd_reorder_probe ///// FINITE DOMAINS ///// protected BDDDomain[] domain; protected int fdvarnum; protected int firstbddvar; /** * Implementors must implement this factory method to create BDDDomain objects of the correct type. * * @param a index of this domain * @param b size of this domain * @return BDD domain */ protected BDDDomain createDomain(int a, BigInteger b) { return new BDDDomain(a, b) { @Override public BDDFactory getFactory() { return BDDFactory.this; } }; } /** * Creates a new finite domain block of the given size. Allocates log 2 (|domainSize|) BDD variables for the domain. * * @param domainSize domainSize * @return BDD domain */ public BDDDomain extDomain(long domainSize) { return extDomain(BigInteger.valueOf(domainSize)); } public BDDDomain extDomain(BigInteger domainSize) { return extDomain(new BigInteger[] {domainSize})[0]; } /** * Extends the set of finite domain blocks with domains of the given sizes. Each entry in domainSizes is the size of * a new finite domain which later on can be used for finite state machine traversal and other operations on finite * domains. Each domain allocates log 2 (|domainSizes[i]|) BDD variables to be used later. The ordering is * interleaved for the domains defined in each call to extDomain. This means that assuming domain D0 needs 2 BDD * variables x1 and x2 , and another domain D1 needs 4 BDD variables y1, y2, y3 and y4, then the order then will be * x1, y1, x2, y2, y3, y4. The new domains are returned in order. The BDD variables needed to encode the domain are * created for the purpose and do not interfere with the BDD variables already in use. * *

* Compare to fdd_extdomain. *

* * @param dom domain sizes * @return BDD domains */ public BDDDomain[] extDomain(int[] dom) { BigInteger[] a = new BigInteger[dom.length]; for (int i = 0; i < a.length; ++i) { a[i] = BigInteger.valueOf(dom[i]); } return extDomain(a); } public BDDDomain[] extDomain(long[] dom) { BigInteger[] a = new BigInteger[dom.length]; for (int i = 0; i < a.length; ++i) { a[i] = BigInteger.valueOf(dom[i]); } return extDomain(a); } public BDDDomain[] extDomain(BigInteger[] domainSizes) { int offset = fdvarnum; int binoffset; int extravars = 0; int n, bn; boolean more; int num = domainSizes.length; /* Build domain table */ if (domain == null) /* First time */ { domain = new BDDDomain[num]; } else /* Allocated before */ { if (fdvarnum + num > domain.length) { int fdvaralloc = domain.length + Math.max(num, domain.length); BDDDomain[] d2 = new BDDDomain[fdvaralloc]; System.arraycopy(domain, 0, d2, 0, domain.length); domain = d2; } } /* Create bdd variable tables */ for (n = 0; n < num; n++) { domain[n + fdvarnum] = createDomain(n + fdvarnum, domainSizes[n]); extravars += domain[n + fdvarnum].varNum(); } binoffset = firstbddvar; int bddvarnum = varNum(); if (firstbddvar + extravars > bddvarnum) { setVarNum(firstbddvar + extravars); } /* Set correct variable sequence (interleaved) */ for (bn = 0, more = true; more; bn++) { more = false; for (n = 0; n < num; n++) { if (bn < domain[n + fdvarnum].varNum()) { more = true; domain[n + fdvarnum].ivar[bn] = binoffset++; } } } if (isZDD()) { // Need to rebuild varsets for existing domains. for (n = 0; n < fdvarnum; n++) { domain[n].var.free(); domain[n].var = makeSet(domain[n].ivar); } } for (n = 0; n < num; n++) { domain[n + fdvarnum].var = makeSet(domain[n + fdvarnum].ivar); } fdvarnum += num; firstbddvar += extravars; BDDDomain[] r = new BDDDomain[num]; System.arraycopy(domain, offset, r, 0, num); return r; } /** * This function takes two finite domain blocks and merges them into a new one, such that the new one is encoded * using both sets of BDD variables. * *

* Compare to fdd_overlapdomain. *

* * @param d1 first domain * @param d2 second domain * @return BDD domain */ public BDDDomain overlapDomain(BDDDomain d1, BDDDomain d2) { BDDDomain d; int n; int fdvaralloc = domain.length; if (fdvarnum + 1 > fdvaralloc) { fdvaralloc += fdvaralloc; BDDDomain[] domain2 = new BDDDomain[fdvaralloc]; System.arraycopy(domain, 0, domain2, 0, domain.length); domain = domain2; } d = domain[fdvarnum]; d.realsize = d1.realsize.multiply(d2.realsize); d.ivar = new int[d1.varNum() + d2.varNum()]; for (n = 0; n < d1.varNum(); n++) { d.ivar[n] = d1.ivar[n]; } for (n = 0; n < d2.varNum(); n++) { d.ivar[d1.varNum() + n] = d2.ivar[n]; } d.var = makeSet(d.ivar); // bdd_addref(d.var); fdvarnum++; return d; } /** * Returns a BDD defining all the variable sets used to define the variable blocks in the given array. * *

* Compare to fdd_makeset. *

* * @param v variable block array * @return BDD variable set */ public BDDVarSet makeSet(BDDDomain[] v) { BDDVarSet res = emptySet(); int n; for (n = 0; n < v.length; n++) { res.unionWith(v[n].set()); } return res; } /** * Clear all allocated finite domain blocks that were defined by extDomain() or overlapDomain(). * *

* Compare to fdd_clearall. *

*/ public void clearAllDomains() { domain = null; fdvarnum = 0; firstbddvar = 0; } /** * Returns the number of finite domain blocks defined by calls to extDomain(). * *

* Compare to fdd_domainnum. *

* * @return number of finite domain blocks */ public int numberOfDomains() { return fdvarnum; } /** * Returns the ith finite domain block, as defined by calls to extDomain(). * * @param i index * @return finite domain block */ public BDDDomain getDomain(int i) { if (i < 0 || i >= fdvarnum) { throw new IndexOutOfBoundsException(); } return domain[i]; } // TODO: fdd_file_hook, fdd_strm_hook /** * Creates a variable ordering from a string. The resulting order can be passed into {@code setVarOrder()}. Example: * in the order "A_BxC_DxExF", the bits for A are first, followed by the bits for B and C interleaved, followed by * the bits for D, E, and F interleaved. * *

* Obviously, domain names cannot contain the 'x' or '_' characters. *

* * @param reverseLocal whether to reverse the bits of each domain * @param ordering string representation of ordering * @return int[] of ordering * @see com.github.javabdd.BDDFactory#setVarOrder(int[]) */ public int[] makeVarOrdering(boolean reverseLocal, String ordering) { int varnum = varNum(); int nDomains = numberOfDomains(); int[][] localOrders = new int[nDomains][]; for (int i = 0; i < localOrders.length; ++i) { localOrders[i] = new int[getDomain(i).varNum()]; } for (int i = 0; i < nDomains; ++i) { BDDDomain d = getDomain(i); int nVars = d.varNum(); for (int j = 0; j < nVars; ++j) { if (reverseLocal) { localOrders[i][j] = nVars - j - 1; } else { localOrders[i][j] = j; } } } BDDDomain[] doms = new BDDDomain[nDomains]; int[] varorder = new int[varnum]; // System.out.println("Ordering: "+ordering); StringTokenizer st = new StringTokenizer(ordering, "x_", true); int numberOfDomains = 0, bitIndex = 0; boolean[] done = new boolean[nDomains]; for (int i = 0;; ++i) { String s = st.nextToken(); BDDDomain d; for (int j = 0;; ++j) { if (j == numberOfDomains()) { throw new BDDException("bad domain: " + s); } d = getDomain(j); if (s.equals(d.getName())) { break; } } if (done[d.getIndex()]) { throw new BDDException("duplicate domain: " + s); } done[d.getIndex()] = true; doms[i] = d; if (st.hasMoreTokens()) { s = st.nextToken(); if (s.equals("x")) { ++numberOfDomains; continue; } } bitIndex = fillInVarIndices(doms, i - numberOfDomains, numberOfDomains + 1, localOrders, bitIndex, varorder); if (!st.hasMoreTokens()) { break; } if (s.equals("_")) { numberOfDomains = 0; } else { throw new BDDException("bad token: " + s); } } for (int i = 0; i < doms.length; ++i) { if (!done[i]) { throw new BDDException("missing domain #" + i + ": " + getDomain(i)); } } while (bitIndex < varorder.length) { varorder[bitIndex] = bitIndex; ++bitIndex; } int[] test = new int[varorder.length]; System.arraycopy(varorder, 0, test, 0, varorder.length); Arrays.sort(test); for (int i = 0; i < test.length; ++i) { if (test[i] != i) { throw new BDDException(test[i] + " != " + i); } } return varorder; } /** * Helper function for makeVarOrder(). * * @param doms domains * @param domainIndex domain index * @param numDomains number of domains * @param localOrders local orders * @param bitIndex bit index * @param varorder variable order * @return bit index */ static int fillInVarIndices(BDDDomain[] doms, int domainIndex, int numDomains, int[][] localOrders, int bitIndex, int[] varorder) { // calculate size of largest domain to interleave int maxBits = 0; for (int i = 0; i < numDomains; ++i) { BDDDomain d = doms[domainIndex + i]; maxBits = Math.max(maxBits, d.varNum()); } // interleave the domains for (int bitNumber = 0; bitNumber < maxBits; ++bitNumber) { for (int i = 0; i < numDomains; ++i) { BDDDomain d = doms[domainIndex + i]; if (bitNumber < d.varNum()) { int di = d.getIndex(); int local = localOrders[di][bitNumber]; if (ASSERT_FILL_IN_VAR_INDICES) { if (local >= d.vars().length) { throw new AssertionError("bug!"); } if (bitIndex >= varorder.length) { throw new AssertionError("bug2!"); } } varorder[bitIndex++] = d.vars()[local]; } } } return bitIndex; } /**** BIT VECTORS ****/ /** * Implementors must implement this factory method to create BDDBitVector objects of the correct type. * * @param a bit number * @return BDD bit vector */ protected BDDBitVector createBitVector(int a) { return new BDDBitVector(a) { @Override public BDDFactory getFactory() { return BDDFactory.this; } }; } /** * Build a bit vector that is constant true or constant false. * *

* Compare to bvec_true, bvec_false. *

* * @param bitnum bit number * @param b bit value * @return BDD bit vector */ public BDDBitVector buildVector(int bitnum, boolean b) { BDDBitVector v = createBitVector(bitnum); v.initialize(b); return v; } /** * Build a bit vector that corresponds to a constant value. * *

* Compare to bvec_con. *

* * @param bitnum bit number * @param val bit value * @return BDD bit vector */ public BDDBitVector constantVector(int bitnum, long val) { BDDBitVector v = createBitVector(bitnum); v.initialize(val); return v; } public BDDBitVector constantVector(int bitnum, BigInteger val) { BDDBitVector v = createBitVector(bitnum); v.initialize(val); return v; } /** * Build a bit vector using variables offset, offset+step, offset+2*step, ... , offset+(bitnum-1)*step. * *

* Compare to bvec_var. *

* * @param bitnum bit number * @param offset offset * @param step step * @return BDD bit vector */ public BDDBitVector buildVector(int bitnum, int offset, int step) { BDDBitVector v = createBitVector(bitnum); v.initialize(offset, step); return v; } /** * Build a bit vector using variables from the given BDD domain. * *

* Compare to bvec_varfdd. *

* * @param d BDD domain * @return BDD bit vector */ public BDDBitVector buildVector(BDDDomain d) { BDDBitVector v = createBitVector(d.varNum()); v.initialize(d); return v; } /** * Build a bit vector using the given variables. * *

* compare to bvec_varvec. *

* * @param var variables * @return BDD bit vector */ public BDDBitVector buildVector(int[] var) { BDDBitVector v = createBitVector(var.length); v.initialize(var); return v; } ///// CALLBACKS ///// /** Garbage collection statistics callback. */ @FunctionalInterface public static interface GCStatsCallback { /** * Garbage collection statistics callback. * * @param stats The statistics. * @param pre Whether this callback is invoked before ({@code true}) or after ({@code false}) garbage * collection. */ public void gc(GCStats stats, boolean pre); } /** Variable reorder statistics callback. */ @FunctionalInterface public static interface ReorderStatsCallback { /** * Variable reorder statistics callback. * * @param stats The statistics. * @param pre Whether this callback is invoked before ({@code true}) or after ({@code false}) reordering. */ public void reorder(ReorderStats stats, boolean pre); } /** Node table resize statistics callback. */ @FunctionalInterface public static interface ResizeStatsCallback { /** * Node table resize statistics callback. * * @param oldsize The old node table size. * @param newsize The new node table size. */ public void resize(int oldsize, int newsize); } /** Operator cache statistics callback. */ @FunctionalInterface public static interface CacheStatsCallback { /** * Operator cache statistics callback. * * @param stats The statistics. */ public void cache(CacheStats stats); } /** Maximum BDD nodes usage statistics callback. */ @FunctionalInterface public static interface MaxUsedBddNodesStatsCallback { /** * Maximum BDD nodes usage statistics callback. * * @param stats The statistics. */ public void maxUsedBddNodes(MaxUsedBddNodesStats stats); } /** Maximum memory usage statistics callback. */ @FunctionalInterface public static interface MaxMemoryStatsCallback { /** * Maximum memory usage statistics callback. * * @param stats The statistics. */ public void maxMemory(MaxMemoryStats stats); } /** Continuously BDD nodes usage and BDD operations statistics callback. */ @FunctionalInterface public static interface ContinuousStatsCallback { /** * Continuously BDD nodes usage and BDD operations statistics callback. * * @param usedBddNodes The number of currently used BDD nodes. Represents a platform-independent measure that * approximates memory use. * @param opMiss The number of BDD operations performed until now that could not be taken from the operation * cache. Represents a platform-independent measure of approximates running time. */ public void continuous(int usedBddNodes, long opMiss); } /** The registered garbage collection statistics callbacks, or {@code null} if none registered. */ protected List gcCallbacks = null; /** The registered variable reorder statistics callbacks, or {@code null} if none registered. */ protected List reorderCallbacks = null; /** The registered node table resize statistics callbacks, or {@code null} if none registered. */ protected List resizeCallbacks = null; /** The registered operator cache statistics callbacks, or {@code null} if none registered. */ protected List cacheCallbacks = null; /** The registered maximum BDD nodes usage statistics callbacks, or {@code null} if none registered. */ protected List maxUsedBddNodesCallbacks = null; /** The registered maximum memory usage statistics callbacks, or {@code null} if none registered. */ protected List maxMemoryCallbacks = null; /** * The registered continuously BDD nodes usage and BDD operations statistics callbacks, or {@code null} if none * registered. */ protected List continuousCallbacks = null; /** * Register a garbage collection statistics callback. * * @param callback The callback to register. */ public void registerGcStatsCallback(GCStatsCallback callback) { if (gcCallbacks == null) { gcCallbacks = new LinkedList<>(); } gcCallbacks.add(callback); } /** * Register a variable reorder statistics callback. * * @param callback The callback to register. */ public void registerReorderStatsCallback(ReorderStatsCallback callback) { if (reorderCallbacks == null) { reorderCallbacks = new LinkedList<>(); } reorderCallbacks.add(callback); } /** * Register a node table resize statistics callback. * * @param callback The callback to register. */ public void registerResizeStatsCallback(ResizeStatsCallback callback) { if (resizeCallbacks == null) { resizeCallbacks = new LinkedList<>(); } resizeCallbacks.add(callback); } /** * Register an operator cache statistics callback. * * @param callback The callback to register. */ public void registerCacheStatsCallback(CacheStatsCallback callback) { if (cacheCallbacks == null) { cacheCallbacks = new LinkedList<>(); } cacheCallbacks.add(callback); } /** * Register a maximum BDD nodes usage statistics callback. * * @param callback The callback to register. */ public void registerMaxUsedBddNodesStatsCallback(MaxUsedBddNodesStatsCallback callback) { if (maxUsedBddNodesCallbacks == null) { maxUsedBddNodesCallbacks = new LinkedList<>(); } maxUsedBddNodesCallbacks.add(callback); } /** * Register a maximum memory usage statistics callback. * * @param callback The callback to register. */ public void registerMaxMemoryStatsCallback(MaxMemoryStatsCallback callback) { if (maxMemoryCallbacks == null) { maxMemoryCallbacks = new LinkedList<>(); } maxMemoryCallbacks.add(callback); } /** * Register a continuously BDD nodes usage and BDD operations statistics callback. * * @param callback The callback to register. */ public void registerContinuousStatsCallback(ContinuousStatsCallback callback) { if (continuousCallbacks == null) { continuousCallbacks = new LinkedList<>(); } continuousCallbacks.add(callback); } /** * Unregister a garbage collection statistics callback. * * @param callback The callback to unregister. * @throws IllegalArgumentException If callback is not registered. */ public void unregisterGcStatsCallback(GCStatsCallback callback) { if (gcCallbacks != null) { for (Iterator iter = gcCallbacks.iterator(); iter.hasNext();) { if (iter.next() == callback) { iter.remove(); if (gcCallbacks.isEmpty()) { gcCallbacks = null; } return; } } } throw new IllegalArgumentException(); } /** * Unregister a variable reorder statistics callback. * * @param callback The callback to unregister. * @throws IllegalArgumentException If callback is not registered. */ public void unregisterReorderStatsCallback(ReorderStatsCallback callback) { if (reorderCallbacks != null) { for (Iterator iter = reorderCallbacks.iterator(); iter.hasNext();) { if (iter.next() == callback) { iter.remove(); if (reorderCallbacks.isEmpty()) { reorderCallbacks = null; } return; } } } throw new IllegalArgumentException(); } /** * Unregister a node table resize statistics callback. * * @param callback The callback to unregister. * @throws IllegalArgumentException If callback is not registered. */ public void unregisterResizeStatsCallback(ResizeStatsCallback callback) { if (resizeCallbacks != null) { for (Iterator iter = resizeCallbacks.iterator(); iter.hasNext();) { if (iter.next() == callback) { iter.remove(); if (resizeCallbacks.isEmpty()) { resizeCallbacks = null; } return; } } } throw new IllegalArgumentException(); } /** * Unregister an operator cache statistics callback. * * @param callback The callback to unregister. * @throws IllegalArgumentException If callback is not registered. */ public void unregisterCacheStatsCallback(CacheStatsCallback callback) { if (cacheCallbacks != null) { for (Iterator iter = cacheCallbacks.iterator(); iter.hasNext();) { if (iter.next() == callback) { iter.remove(); if (cacheCallbacks.isEmpty()) { cacheCallbacks = null; } return; } } } throw new IllegalArgumentException(); } /** * Unregister a maximum BDD nodes usage statistics callback. * * @param callback The callback to unregister. * @throws IllegalArgumentException If callback is not registered. */ public void unregisterMaxUsedBddNodesStatsCallback(MaxUsedBddNodesStatsCallback callback) { if (maxUsedBddNodesCallbacks != null) { for (Iterator iter = maxUsedBddNodesCallbacks.iterator(); iter.hasNext();) { if (iter.next() == callback) { iter.remove(); if (maxUsedBddNodesCallbacks.isEmpty()) { maxUsedBddNodesCallbacks = null; } return; } } } throw new IllegalArgumentException(); } /** * Unregister a maximum memory usage statistics callback. * * @param callback The callback to unregister. * @throws IllegalArgumentException If callback is not registered. */ public void unregisterMaxMemoryStatsCallback(MaxMemoryStatsCallback callback) { if (maxMemoryCallbacks != null) { for (Iterator iter = maxMemoryCallbacks.iterator(); iter.hasNext();) { if (iter.next() == callback) { iter.remove(); if (maxMemoryCallbacks.isEmpty()) { maxMemoryCallbacks = null; } return; } } } throw new IllegalArgumentException(); } /** * Unregister a continuously BDD nodes usage and BDD operations statistics callback. * * @param callback The callback to unregister. * @throws IllegalArgumentException If callback is not registered. */ public void unregisterContinuousStatsCallback(ContinuousStatsCallback callback) { if (continuousCallbacks != null) { for (Iterator iter = continuousCallbacks.iterator(); iter.hasNext();) { if (iter.next() == callback) { iter.remove(); if (continuousCallbacks.isEmpty()) { continuousCallbacks = null; } return; } } } throw new IllegalArgumentException(); } /** * Returns whether this BDD factory has a registered garbage collection statistics callback. * * @return {@code true} if such a callback is registered, {@code false} otherwise. */ public boolean hasGcStatsCallback() { return gcCallbacks != null; } /** * Returns whether this BDD factory has a registered variable reorder statistics callback. * * @return {@code true} if such a callback is registered, {@code false} otherwise. */ public boolean hasReorderStatsCallback() { return reorderCallbacks != null; } /** * Returns whether this BDD factory has a registered node table resize statistics callback. * * @return {@code true} if such a callback is registered, {@code false} otherwise. */ public boolean hasResizeStatsCallback() { return resizeCallbacks != null; } /** * Returns whether this BDD factory has a registered operator cache statistics callback. * * @return {@code true} if such a callback is registered, {@code false} otherwise. */ public boolean hasCacheStatsCallback() { return cacheCallbacks != null; } /** * Returns whether this BDD factory has a registered maximum BDD nodes usage statistics callback. * * @return {@code true} if such a callback is registered, {@code false} otherwise. */ public boolean hasMaxUsedBddNodesStatsCallback() { return maxUsedBddNodesCallbacks != null; } /** * Returns whether this BDD factory has a registered maximum memory usage statistics callback. * * @return {@code true} if such a callback is registered, {@code false} otherwise. */ public boolean hasMaxMemoryStatsCallback() { return maxMemoryCallbacks != null; } /** * Returns whether this BDD factory has a registered continuously BDD nodes usage and BDD operations statistics * callback. * * @return {@code true} if such a callback is registered, {@code false} otherwise. */ public boolean hasContinuousStatsCallback() { return continuousCallbacks != null; } /** * Invoke all registered garbage collection statistics callbacks. * * @param pre Whether this callback is invoked before ({@code true}) or after ({@code false}) garbage collection. */ public void invokeGcStatsCallbacks(boolean pre) { if (gcCallbacks != null) { for (GCStatsCallback callback: gcCallbacks) { callback.gc(gcstats, pre); } } } /** * Invoke all registered variable reorder statistics callbacks. * * @param pre Whether this callback is invoked before ({@code true}) or after ({@code false}) reordering. */ public void invokeReorderStatsCallbacks(boolean pre) { if (reorderCallbacks != null) { for (ReorderStatsCallback callback: reorderCallbacks) { callback.reorder(reorderstats, pre); } } } /** * Invoke all registered node table resize statistics callbacks. * * @param oldsize The old node table size. * @param newsize The new node table size. */ public void invokeResizeStatsCallbacks(int oldsize, int newsize) { if (resizeCallbacks != null) { for (ResizeStatsCallback callback: resizeCallbacks) { callback.resize(oldsize, newsize); } } } /** Invoke all registered operator cache statistics callbacks. */ public void invokeCacheStatsCallbacks() { if (cacheCallbacks != null) { for (CacheStatsCallback callback: cacheCallbacks) { callback.cache(cachestats); } } } /** Invoke all registered maximum BDD nodes usage statistics callbacks. */ public void invokeMaxUsedBddNodesStatsCallbacks() { if (maxUsedBddNodesCallbacks != null) { for (MaxUsedBddNodesStatsCallback callback: maxUsedBddNodesCallbacks) { callback.maxUsedBddNodes(maxusedbddnodesstats); } } } /** Invoke all registered maximum memory usage statistics callbacks. */ public void invokeMaxMemoryStatsCallbacks() { if (maxMemoryCallbacks != null) { for (MaxMemoryStatsCallback callback: maxMemoryCallbacks) { callback.maxMemory(maxmemorystats); } } } /** * Invoke all registered continuously BDD nodes usage and BDD operations statistics callbacks. * * @param usedBddNodes The number of currently used BDD nodes. Represents a platform-independent measure that * approximates memory use. * @param opMiss The number of BDD operations performed until now that could not be taken from the operation * cache. Represents a platform-independent measure of approximates running time. */ public void invokeContinuousStatsCallbacks(int usedBddNodes, long opMiss) { if (continuousCallbacks != null) { for (ContinuousStatsCallback callback: continuousCallbacks) { callback.continuous(usedBddNodes, opMiss); } } } /** * Default garbage collection statistics callback. * * @param stats The statistics. * @param pre Whether this callback is invoked before ({@code true}) or after ({@code false}) garbage collection. */ public static void defaultGcStatsCallback(GCStats stats, boolean pre) { if (pre) { if (stats.freenodes != 0) { System.out.println("Starting GC cycle #" + (stats.num + 1) + ": " + stats.nodes + " nodes / " + stats.freenodes + " free"); } } else { System.out.println(stats.toString()); } } /** * Default variable reorder statistics callback. * * @param stats The statistics. * @param pre Whether this callback is invoked before ({@code true}) or after ({@code false}) reordering. */ public static void defaultReorderStatsCallback(ReorderStats stats, boolean pre) { if (pre) { System.out.println("Start reordering"); } else { System.out.println("End reordering. " + stats); } } /** * Default node table resize statistics callback. * * @param oldsize The old node table size. * @param newsize The new node table size. */ public static void defaultResizeStatsCallback(int oldsize, int newsize) { StringBuilder sb = new StringBuilder(); sb.append("Went from "); sb.append(oldsize); sb.append(" to "); sb.append(newsize); sb.append(" nodes"); System.out.println(sb.toString()); } /** * Default operator cache statistics callback. * * @param stats The statistics. */ public static void defaultCacheStatsCallback(CacheStats stats) { System.out.println(stats.toString()); } /** * Default maximum BDD nodes usage statistics callback. * * @param stats The statistics. */ public static void defaultMaxUsedBddNodesStatsCallback(MaxUsedBddNodesStats stats) { System.out.println(stats.toString()); } /** * Default maximum memory usage statistics callback. * * @param stats The statistics. */ public static void defaultMaxMemoryStatsCallback(MaxMemoryStats stats) { System.out.println(stats.toString()); } /** * Default continuously BDD nodes usage and BDD operations statistics callback. * * @param usedBddNodes The number of currently used BDD nodes. Represents a platform-independent measure that * approximates memory use. * @param opMiss The number of BDD operations performed until now that could not be taken from the operation * cache. Represents a platform-independent measure of approximates running time. */ public static void defaultContinuousStatsCallback(int usedBddNodes, long opMiss) { StringBuilder sb = new StringBuilder(); sb.append("Used BDD nodes: "); sb.append(usedBddNodes); sb.append(", operation count: "); sb.append(opMiss); System.out.println(sb.toString()); } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy