jAADD.BDD Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of aadd Show documentation
Show all versions of aadd Show documentation
This project implements Affine Arithmetic Decision Diagrams (AADD) in Java. AADD permit in particular the symbolic execution of Java codes.
The newest version!
package jAADD;
import java.util.function.BiFunction;
import java.util.function.Function;
import static jAADD.AADDMgr.ONE;
import static jAADD.AADDMgr.ZERO;
/**
* The class BDD implements an ROBDD.
* It is derived from the super class DD.
* It has exactly two leaves that are either ONE or ZERO.
* @author Christoph Grimm, Carna Zivkovic
*/
public class BDD extends DD implements Cloneable {
/**
* Creates a new leaf node.
* The class is not needed for users as in BDD there exist only two leaf nodes,
* ONE and ZERO. It is used only once.
* Therefore it is private. Use ONE and ZERO to get a leaf.
* @param value Value of leaf ... DONT USE THIS CONSTRUCTOR unless you know what you do.
*/
BDD(Boolean value) {
super(value);
}
/**
* Use this to get a leaf node of a given boolean value.
*/
public static BDD newLeaf(boolean value) {
if (value) return ONE;
else return ZERO;
}
public static BDD ONE() { return AADDMgr.ONE; }
public static BDD ZERO() { return AADDMgr.ZERO; }
/**
* Creates an internal node with a given index.
* index must refer to an existing condition.
* It must be smaller than maxIndex.
* @param index is the index of the node level.
* @param T is the true child; no copy is made.
* @param F is the false child; no copy is made.
*/
public BDD(int index, BDD T, BDD F) {
super(index, T, F);
}
/**
* Creates an internal node and a new condition.
* @param cond an affine form that models the condition.
* @param T sub-BDD for true; no copy is made.
* @param F sub-BDD for false; no copy is made.
*/
// public BDD(AffineForm cond, BDD T, BDD F) {
// super(cond, T, F);
// }
/**
* Clone method. Copies the tree structure, but not conditions.
* The leaves are not copied for BDD, where ONE and ZERO are merged.
*/
@Override
public BDD clone() {
if ( isInternal() ) {
BDD klon = new BDD(index, (BDD) T, (BDD) F);
klon.T = ((BDD) T).clone(); // deep copy
klon.F = ((BDD) F).clone(); // deep copy
return klon;
}
else // for leaves
{
return this; // shallow copy for leaves (ONE, ZERO) of BDD.
}
}
protected BDD T() { return (BDD) T; }
protected BDD F() { return (BDD) F; }
/**
* Applies a unary operator on a BDD and returns its result.
* It works recursively.
* @param op a function on the BDD with a parameter.
* @return a new BDD that is the result of the applied function.
*/
private BDD Apply(Function op) {
// Recursion stops at leaves.
if (isLeaf()) return op.apply(this);
// Otherwise we recurse to T and E nodes.
return new BDD(index, T().Apply(op), F().Apply(op));
// Check for reduction not possible as complement is only operation and does not
// introduce redundancies.
}
/**
* Computes the complementary function of a given BDD.
* @return complementary of this.
*/
public BDD negate() {
// For leaves stop recursion
Function negate = (a) -> {
if (a == ONE) return ZERO;
else return ONE;
};
// Otherwise recursion to leaves and apply negate there.
return this.Apply(negate);
}
/**
* Applies a binary operator passed as las parameter on the BDD
* passed as first two parameters and returns result.
* @param op the operation
* @param g parameter 2
* @return result of binary operation on the parameters
*/
public BDD Apply(BiFunction op, BDD g) {
assert ( g != null );
BDD fT, fF, gT, gF; // T, F of this and/or g
int idx;
// Iteration to leaves.
// It ends iteration and applies operation.
if (isLeaf() && g.isLeaf() )
return newLeaf(op.apply(Value(), g.Value()));
// Recursion, with new node that has
// the *largest* indices.
if (index <= g.index) {
idx = index;
fT = T(); fF = F();
} else {
idx = g.index;
fT = fF = this;
}
if (g.index <= index) {
gT = g.T(); gF = g.F();
} else {
gT = gF = g;
}
// do the recursion
BDD Tr = fT.Apply(op, gT);
BDD Fr = fF.Apply(op, gF);
// now, the operation is finished, but
// we check for redundancies that we can reduce before
// setting up and returning the result.
if (Tr == Fr) return Tr;
else return new BDD(idx, Tr, Fr);
}
public BDD and(BDD other) {
BiFunction and = (a, b) -> a && b;
return this.Apply(and, other);
}
public BDD or(BDD other) {
BiFunction or = (a, b) -> a || b;
return this.Apply(or, other);
}
public BDD xor(BDD other) {
BiFunction xor = (a, b) -> a != b;
return this.Apply(xor, other);
}
public BDD nand(BDD other) {
BiFunction nand = (a, b) -> !(a && b);
return this.Apply(nand, other);
}
public BDD nor(BDD other) {
BiFunction or = (a, b) -> !(a || b);
return this.Apply(or, other);
}
public BDD xnor(BDD other) {
BiFunction xnor = (a, b) -> (a == b);
return this.Apply(xnor, other);
}
/**
* Compares this BDD with other BDD for exact equality.
* @param other
* @return
*/
public boolean equals(BDD other) {
if (this == other ) return true;
if (other == null || this.getClass() != other.getClass()) return false;
if (isLeaf()) {
return other == this;
} else
return (T().equals(other.T()) && F().equals(other.F()));
}
/**
* The ITE function merges BDD in an if-then-else-function.
* Note, that the condition itself that is this BDD, is also a BDD.
* The parameters are not changed.
*/
public BDD ITE(BDD t, BDD e) // throws CloneNotSupportedException
{
if (this == ONE) return t.clone();
else if (this == ZERO) return e.clone();
BDD ct = this.and(t);
BDD cne = this.negate().and(e);
return ct.or(cne);
}
public AADD ITE(AADD t, AADD e) {
assert( t != null);
assert( e != null);
if (this == ONE) return t.clone();
else if (this == ZERO) return e.clone();
AADD Temp1 = t.AmultB(this);
AADD Temp2 = e.AmultB(this.negate());
return Temp1.add(Temp2);
}
}