internal void Refine(ISolver <TSet> solver, TSet other) { if (!StackHelper.TryEnsureSufficientExecutionStack()) { StackHelper.CallOnEmptyStack(Refine, solver, other); return; } TSet thisAndOther = solver.And(_set, other); if (!solver.IsEmpty(thisAndOther)) { // The sets overlap, now check if this is contained in other TSet thisMinusOther = solver.And(_set, solver.Not(other)); if (!solver.IsEmpty(thisMinusOther)) { // This is not contained in other, minterms may need to be split if (_left is null) { Debug.Assert(_right is null); _left = new PartitionTree(thisAndOther); _right = new PartitionTree(thisMinusOther); } else { Debug.Assert(_right is not null); _left.Refine(solver, other); _right.Refine(solver, other); } } } }
/// <summary> /// Given an array of predidates {p_1, p_2, ..., p_n} where n>=0, /// enumerate all satisfiable Boolean combinations Tuple({b_1, b_2, ..., b_n}, p) /// where p is satisfiable and equivalent to p'_1 & p'_2 & ... & p'_n, /// where p'_i = p_i if b_i = true and p'_i is Not(p_i). Otherwise, if n=0 /// return Tuple({},True). /// </summary> /// <param name="preds">array of predicates</param> /// <returns>all minterms of the given predicate sequence</returns> public List <TPredicate> GenerateMinterms(params TPredicate[] preds) { if (preds.Length == 0) { return(new List <TPredicate> { _algebra.True }); } // The minterms will be solved using non-equivalent predicates, i.e., the equivalence classes of preds. The // following code maps each predicate to an equivalence class and also stores for each equivalence class the // predicates belonging to it, so that a valuation for the original predicates may be reconstructed. var tree = new PartitionTree(_algebra); var seen = new HashSet <EquivalenceClass>(); for (int i = 0; i < preds.Length; i++) { // Use a wrapper that overloads Equals to be logical equivalence as the key if (seen.Add(new EquivalenceClass(_algebra, preds[i]))) { // Push each equivalence class into the partition tree tree.Refine(preds[i]); } } // Return all minterms as the leaves of the partition tree return(tree.GetLeafPredicates()); }
/// <summary> /// Constructor /// </summary> /// <param name="partition"></param> /// <param name="item"></param> public PartitionTree(PartitionAsForest partition, int item) : base(partition.UniverseSize) { this.partition = partition; this.item = item; parent = null; rank = 0; mCount = 1; }
/// <summary> /// Union of two sets /// </summary> /// <param name="s"></param> /// <param name="t"></param> public virtual void Join(ISet s, ISet t) { PartitionTree partitionTree1 = (PartitionTree)s; PartitionTree partitionTree2 = (PartitionTree)t; CheckArguments(partitionTree1, partitionTree2); partitionTree2.parent = partitionTree1; mCount--; }
/// <summary> /// Default constructor /// </summary> /// <param name="n">the size of the partition</param> public PartitionAsForest(int n) : base(n) { forrest = new PartitionTree[mUniverseSize]; for (int j = 0; j < mUniverseSize; j++) { forrest[j] = new PartitionTree(this, j); } mCount = mUniverseSize; }
/// <summary> /// Check for two sets if they are valid arguments for a set-join /// </summary> /// <param name="s"></param> /// <param name="t"></param> protected virtual void CheckArguments(PartitionTree s, PartitionTree t) { if (!IsMember(s) || s.parent != null || !IsMember(t) || t.parent != null || s == t) { throw new ArgumentException("incompatible sets"); } else { return; } }
/// <summary> /// Given an array of predidates {p_1, p_2, ..., p_n} where n>=0, /// enumerate all satisfiable Boolean combinations Tuple({b_1, b_2, ..., b_n}, p) /// where p is satisfiable and equivalent to p'_1 & p'_2 & ... & p'_n, /// where p'_i = p_i if b_i = true and p'_i is Not(p_i). Otherwise, if n=0 /// return Tuple({},True). /// </summary> /// <param name="preds">array of predicates</param> /// <returns>all minterms of the given predicate sequence</returns> public List <TPredicate> GenerateMinterms(IEnumerable <TPredicate> preds) { var tree = new PartitionTree(_algebra.True); foreach (TPredicate pred in preds) { // Push each predicate into the partition tree tree.Refine(_algebra, pred); } // Return all minterms as the leaves of the partition tree return(tree.GetLeafPredicates()); }
/// <summary> /// Given an array of sets {p_1, p_2, ..., p_n} where n>=0, /// enumerate all satisfiable (non-empty) Boolean combinations Tuple({b_1, b_2, ..., b_n}, p) /// where p is satisfiable and equivalent to p'_1 & p'_2 & ... & p'_n, /// where p'_i = p_i if b_i = true and p'_i is Not(p_i). Otherwise, if n=0 return Tuple({},True). /// </summary> /// <param name="solver">The solver to use for processing the sets.</param> /// <param name="sets">The sets from which to generate the minterms.</param> /// <returns>All minterms of the given set sequence</returns> public static List <TSet> GenerateMinterms(ISolver <TSet> solver, HashSet <TSet> sets) { var tree = new PartitionTree(solver.Full); foreach (TSet set in sets) { // Push each set into the partition tree tree.Refine(solver, set); } // Return all minterms as the leaves of the partition tree return(tree.GetLeafSets()); }
/// <summary> /// Comparison /// </summary> /// <param name="obj"></param> /// <returns></returns> public override int CompareTo(object obj) { PartitionTree partitionTree = (PartitionTree)obj; return(item - partitionTree.item); }
/// <summary> /// Emtpies the tree /// </summary> public override void Purge() { parent = null; rank = 0; mCount = 1; }