You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

406 lines
9.2 KiB

//==============================================================================
//
// Copyright (c) 2002-
// Authors:
// * Dave Parker <david.parker@comlab.ox.ac.uk> (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.Collections;
import java.util.Comparator;
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<JDDNode>
{
private Vector<JDDNode> 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<JDDNode>();
array = 0;
arrayBuilt = false;
}
/**
* Appends a variable to this JDDVars container.
* <br>
* [ 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!
* <br>
* This method is deprecated, better use copy() or copyVarsFrom() instead.
* These simplify variable reference count debugging.
*/
@Deprecated
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;
}
/**
* Copy JDDNodes from another JDDVars, merge into the existing variables,
* sorting by the variable indices. Afterwards, this JDDVars container
* is fully sorted by variable indices, i.e., the existing variables are
* sorted as well.
* @param ddv the new variables
*/
public void mergeVarsFrom(JDDVars ddv) {
copyVarsFrom(ddv);
sortByIndex();
}
/**
* Remove variable v from container. Does not decrease the refcount.
*/
public void removeVar(JDDNode v)
{
vars.remove(v);
if (arrayBuilt) DDV_FreeArray(array);
arrayBuilt = false;
}
/**
* 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.
* <br>[ REFS: <i>none</i>, DEREFS: <i>none</i> ]
*/
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.
* <br>
* This method is deprecated, please use copy() and
* copyVarsFrom() instead.
* This simplifies reference counting debugging.
*/
@Deprecated
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<JDDNode> 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.<br>
* <br> [ REFS: <i>the variables in the returned JDDVars container</i>, 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.<br>
* <br>[ REFS: <i>result</i>, DEREFS: <i>none</i> ]
*/
public JDDNode toCubeSet()
{
JDDNode result = JDD.Constant(1);
for (JDDNode var : vars) {
result = JDD.And(result, var.copy());
}
return result;
}
/**
* Constructs a 0/1-ADD that is the conjunction of
* the negated variables, i.e.,
* And(Not(v_1), Not(v_2), ..., Not(v_n))
* <br>[ REFS: <i>result</i>, DEREFS: <i>none</i> ]
*/
public JDDNode allZero()
{
JDDNode result = JDD.Constant(1);
for (JDDNode var : vars) {
result = JDD.And(result, JDD.Not(var.copy()));
}
return result;
}
/** Sort the variables in this container by their variable index. */
public void sortByIndex()
{
if (arrayBuilt) DDV_FreeArray(array);
arrayBuilt = false;
Collections.sort(vars, new Comparator<JDDNode>() {
@Override
public int compare(JDDNode a, JDDNode b)
{
return new Integer(a.getIndex()).compareTo(b.getIndex());
}
});
}
}
//------------------------------------------------------------------------------