//============================================================================== // // Copyright (c) 2002- // Authors: // * Dave Parker (University of Oxford, formerly University of Birmingham) // //------------------------------------------------------------------------------ // // This file is part of PRISM. // // PRISM is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; either version 2 of the License, or // (at your option) any later version. // // PRISM is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with PRISM; if not, write to the Free Software Foundation, // Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // //============================================================================== package jdd; import java.util.Iterator; import java.util.Vector; /** * Container for MTBDD variables. * Each variable is represented by a JDDNode (result of JDD.Var(), a projection function). * * It is assumed in general that each JDDNode held in a JDDVars container * counts as a single reference and that a JDDVars object is cleared using derefAll() * when no longer used. This will dereference all the variables contained in the JDDVars * object. */ public class JDDVars implements Iterable { private Vector vars; private long array; private boolean arrayBuilt; private native long DDV_BuildArray(); private native void DDV_FreeArray(long a); private native int DDV_GetIndex(long dd); static { try { System.loadLibrary("jdd"); } catch (UnsatisfiedLinkError e) { System.out.println(e); System.exit(1); } } /** * Constructor. */ public JDDVars() { vars = new Vector(); array = 0; arrayBuilt = false; } /** * Appends a variable to this JDDVars container. *
* [ DEREFs: var (on derefAll call) ] */ public void addVar(JDDNode var) { vars.addElement(var); if (arrayBuilt) DDV_FreeArray(array); arrayBuilt = false; } /** * Appends the variables of another JDDVars container to this container. * Does not increase the refcount of the JDDNodes! */ public void addVars(JDDVars ddv) { vars.addAll(ddv.vars); if (arrayBuilt) DDV_FreeArray(array); arrayBuilt = false; } /** * Creates a copy of this JDDVars container, * containing referenced copies of each variable JDDNode in this container. */ public JDDVars copy() { JDDVars result = new JDDVars(); for (JDDNode var : this) { result.addVar(var.copy()); } return result; } /** * Copies variables from another JDDVars container, * appending to this container. * Does a (referencing) copy of each of the variable JDDNodes. */ public void copyVarsFrom(JDDVars ddv) { for (JDDNode var : ddv) { addVar(var.copy()); } } /** * Copy an array of JDDVars[] by copying each JDDVars container. * The copy will have fully referenced JDDNodes. */ public static JDDVars[] copyArray(JDDVars[] vararray) { JDDVars[] result = new JDDVars[vararray.length]; for (int i = 0; i< vararray.length; i++) { result[i] = vararray[i].copy(); } return result; } /** * Removes the JDDNodes contained in ddv from this JDDVars container. * Does not decrease the refcount! */ public void removeVars(JDDVars ddv) { vars.removeAll(ddv.vars); if (arrayBuilt) DDV_FreeArray(array); arrayBuilt = false; } /** Returns the number of variables stored in this JDDVars container. */ public int getNumVars() { return vars.size(); } /** * Returns the JDDNode for the i-th stored variable. *
[ REFS: none, DEREFS: none ] */ public JDDNode getVar(int i) { return (JDDNode)vars.elementAt(i); } /** * Returns the internal Cudd pointer for the i-th stored variable. */ public long getVarPtr(int i) { return ((JDDNode)vars.elementAt(i)).ptr(); } /** * Returns the Cudd variable index for the i-th stored variable. */ public int getVarIndex(int i) { return DDV_GetIndex(((JDDNode)vars.elementAt(i)).ptr()); } /** * Returns the minimal Cudd variable index for the stored variables, * or -1 if there are no stored variables. */ public int getMinVarIndex() { int i, j, n, min; n = vars.size(); if (n == 0) return -1; min = getVarIndex(0); for (i = 1; i < n; i++) { j = getVarIndex(i); if (j < min) min = j; } return min; } /** * Returns the maximal Cudd variable index for the stored variables, * or -1 if there are no stored variables. */ public int getMaxVarIndex() { int i, j, n, max; n = vars.size(); if (n == 0) return -1; max = getVarIndex(0); for (i = 1; i < n; i++) { j = getVarIndex(i); if (j > max) max = j; } return max; } /** * Increases the refcount of all contained JDDNodes. */ public void refAll() { int i; for (i = 0; i < vars.size(); i++) { JDD.Ref((JDDNode)vars.elementAt(i)); } } /** * Decreases the refcount of all contained JDDNodes. */ public void derefAll() { int i; for (i = 0; i < vars.size(); i++) { JDD.Deref((JDDNode)vars.elementAt(i)); } } /** * Calls derefAll on all JDDVars elements of a JDDVars[] array. */ public static void derefAllArray(JDDVars[] vars) { for (JDDVars v : vars) { v.derefAll(); } } /** * Constructs a JNI array for the stored variables * that can be passed to the C-based functions. */ public long array() { if (arrayBuilt) { return array; } else { array = DDV_BuildArray(); arrayBuilt = true; return array; } } /** * Returns the number of stored variables. */ public int n() { return vars.size(); } @Override public Iterator iterator() { return vars.iterator(); } @Override public String toString() { int i; String s = "{"; for (i = 0; i < vars.size() - 1; i++) { s = s + getVarIndex(i) + ", "; } if (vars.size() > 0) { s = s + getVarIndex(vars.size() - 1); } s += "}"; return s; } /** * Converts a DD cubeset (conjunction of variables) * to a corresponding JDDVars array.
*
[ REFS: the variables in the returned JDDVars container, DEREFS: cubeSet ] */ public static JDDVars fromCubeSet(JDDNode cubeSet) { try { JDDVars result = new JDDVars(); JDDNode current = cubeSet; // We do not need to bother with reference manipulation, // as we only call getThen() and getElse(), which do not increase // the refcount while (!current.equals(JDD.ONE)) { if (current.isConstant()) { // may not be any other constant than ONE throw new IllegalArgumentException("JDDVars.fromCubeSet: The argument is not a cubeset"); } if (!current.getElse().equals(JDD.ZERO)) { // else always has to point to ZERO throw new IllegalArgumentException("JDDVars.fromCubeSet: The argument is not a cubeset"); } int index = current.getIndex(); JDDNode var = JDD.Var(index); result.addVar(var); current = current.getThen(); } return result; } finally { JDD.Deref(cubeSet); } } /** * Constructs a DD cubeset (conjunction of variables) * corresponding to this JDDVars container.
*
[ REFS: result, DEREFS: none ] */ public JDDNode toCubeSet() { JDDNode result = JDD.Constant(1); for (JDDNode var : vars) { result = JDD.And(result, var.copy()); } return result; } } //------------------------------------------------------------------------------