/// <summary> /// Restrict the leaf predicates with psi /// </summary> BDG <T, S> RestrictLeaves(T psi) { var key = new Tuple <T, BDG <T, S> >(psi, this); BDG <T, S> val; if (!algebra.restrictLeafCache.TryGetValue(key, out val)) { if (this.IsLeaf) { val = this.algebra.MkLeaf(this.algebra.leafAlgebra.MkAnd(this.LeafCondition, psi), true); } else { var t = TrueCase.RestrictLeaves(psi); var f = FalseCase.RestrictLeaves(psi); if (t == TrueCase && f == FalseCase) { val = this; } else { val = this.algebra.MkNode(this.BranchCondition, t, f); } } algebra.restrictLeafCache[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); }