/// <summary> /// Creates a leaf with LeafCondition pred. /// If simplify=true, checks if pred is unsat (returns False) or valid (returns True). /// Assumes that if simplify=false then pred is neither unsat nor valid. /// </summary> public BDG <T, S> MkLeaf(T pred, bool simplify = false) { BDG <T, S> val; if (simplify) { if (!MkLeafCache1.TryGetValue(pred, out val)) { if (!leafAlgebra.IsSatisfiable(pred)) { val = _False; } else if (!leafAlgebra.IsSatisfiable(leafAlgebra.MkNot(pred))) { val = _True; } else { val = new BDG <T, S>(this, default(S), pred, null, null); } MkLeafCache1[pred] = val; } } else { if (!MkLeafCache2.TryGetValue(pred, out val)) { val = new BDG <T, S>(this, default(S), pred, null, null); MkLeafCache2[pred] = val; } } return(val); }
internal BDG(CartesianAlgebra <T, S> alg, S nodePred, T leafPred, BDG <T, S> tCase, BDG <T, S> fCase) { this.algebra = alg; this.BranchCondition = nodePred; this.LeafCondition = leafPred; this.TrueCase = tCase; this.FalseCase = fCase; this.Depth = (tCase == null ? 0 : Math.Max(tCase.Depth, fCase.Depth) + 1); }
public CartesianAlgebra(IBooleanAlgebra <T> leafAlg, IBooleanAlgebra <S> nodeAlg) { this.leafAlgebra = leafAlg; this.nodeAlgebra = nodeAlg; this._True = new BDG <T, S>(this, default(S), leafAlg.True, null, null); this._False = new BDG <T, S>(this, default(S), leafAlg.False, null, null); MkLeafCache1[leafAlg.True] = _True; MkLeafCache2[leafAlg.True] = _True; MkLeafCache1[leafAlg.False] = _False; MkLeafCache2[leafAlg.False] = _False; MkNotCache[_True] = _False; MkNotCache[_False] = _True; this.mintermGenerator = new MintermGenerator <IMonadicPredicate <T, S> >(this); }
public IMonadicPredicate <T, S> MkAnd(IMonadicPredicate <T, S> predicate1, IMonadicPredicate <T, S> predicate2) { //using Depth as a heuristic BDG <T, S> p1 = (BDG <T, S>)predicate1; BDG <T, S> p2 = (BDG <T, S>)predicate2; if (p1.Depth <= p2.Depth) { return(p2.MkAnd(p1)); } else { return(p1.MkAnd(p2)); } }
/// <summary> /// Assumes that pred is sat and ~pred is sat /// </summary> internal BDG <T, S> MkNode(S pred, BDG <T, S> t, BDG <T, S> f) { if (t == f) { return(t); } BDG <T, S> val; var key = new Tuple <S, BDG <T, S>, BDG <T, S> >(pred, t, f); if (!MkNodeCache.TryGetValue(key, out val)) { val = new BDG <T, S>(this, pred, default(T), t, f); MkNodeCache[key] = val; } return(val); }
/// <summary> /// Apply the transformation f to all leaves. /// </summary> internal BDG <T, S> TransformLeaves(Func <T, T> func) { BDG <T, S> val = null; var key = new Tuple <Func <T, T>, BDG <T, S> >(func, this); //if (!Algebra.TransformLeavesCache.TryGetValue(key, out val)) //{ if (this.IsLeaf) { var newPred = func(LeafCondition); val = algebra.MkLeaf(newPred, true); } else { var t = this.TrueCase.TransformLeaves(func); var f = this.FalseCase.TransformLeaves(func); val = algebra.MkNode(this.BranchCondition, t, f); } //Algebra.TransformLeavesCache[key] = val; //} return(val); }
/// <summary> /// Maintains the node invariant: sat(path & nodePred) and sat(path & ~nodePred) /// </summary> BDG <T, S> MkAnd(S path, BDG <T, S> that) { var key = new Tuple <S, BDG <T, S>, BDG <T, S> >(path, this, that); BDG <T, S> val; if (!algebra.MkAndCache.TryGetValue(key, out val)) { if (this.IsLeaf) { if (path.Equals(algebra.nodeAlgebra.True)) { val = that.RestrictLeaves(this.LeafCondition); } else { val = that.Restrict(path, this.LeafCondition); } } else if (that.IsLeaf) { val = this.RestrictLeaves(that.LeafCondition); //path is not relevant } else { var path_and_thatCond = algebra.nodeAlgebra.MkAnd(path, that.BranchCondition); if (!algebra.nodeAlgebra.IsSatisfiable(path_and_thatCond)) { //path implies ~that.BranchCondition var t = this.TrueCase.MkAnd(algebra.nodeAlgebra.MkAnd(path, this.BranchCondition), that.FalseCase); var f = this.FalseCase.MkAnd(algebra.nodeAlgebra.MkAnd(path, algebra.nodeAlgebra.MkNot(this.BranchCondition)), that.FalseCase); if (t == this.TrueCase && f == this.FalseCase) { val = this; } else { val = this.algebra.MkNode(this.BranchCondition, t, f); } } else { var path_and_not_thatCond = algebra.nodeAlgebra.MkAnd(path, algebra.nodeAlgebra.MkNot(that.BranchCondition)); if (!algebra.nodeAlgebra.IsSatisfiable(path_and_not_thatCond)) { //path implies that.BranchCondition var t = this.TrueCase.MkAnd(algebra.nodeAlgebra.MkAnd(path, this.BranchCondition), that.TrueCase); var f = this.FalseCase.MkAnd(algebra.nodeAlgebra.MkAnd(path, algebra.nodeAlgebra.MkNot(this.BranchCondition)), that.TrueCase); if (t == this.TrueCase && f == this.FalseCase) { val = this; } else { val = this.algebra.MkNode(this.BranchCondition, t, f); } } else { //both cases are possible var t = this.TrueCase.MkAnd(algebra.nodeAlgebra.MkAnd(path, this.BranchCondition), that); var f = this.FalseCase.MkAnd(algebra.nodeAlgebra.MkAnd(path, algebra.nodeAlgebra.MkNot(this.BranchCondition)), that); if (t == this.TrueCase && f == this.FalseCase) { val = this; } else { val = this.algebra.MkNode(this.BranchCondition, t, f); } } } } algebra.MkAndCache[key] = val; } return(val); }
/// <summary> /// Makes the conjunction of this and that /// </summary> public BDG <T, S> MkAnd(BDG <T, S> that) { return(MkAnd(algebra.nodeAlgebra.True, that)); }