public DelayedIntersection(BinnedUnion tA, Term tB) { Contract.Requires(tA != null && tB != null); OuterSymbol = null; parent = null; AUnions = new BinnedUnion[1]; BUnions = new BinnedUnion[1]; Results = new BinnedUnion[1]; AUnions[0] = tA; BUnions[0] = new BinnedUnion(tB); Results[0] = new BinnedUnion(tA.index); }
public DelayedIntersection(Symbol s, ImmutableArray <Term> tAs, ImmutableArray <Term> tBs, DelayedIntersection parent) { Contract.Requires(s != null && tAs != null && tBs != null && parent != null); Contract.Requires(tAs.Length > 0 && tBs.Length > 0 && tAs.Length == tBs.Length); Contract.Requires(s.Arity == tAs.Length); OuterSymbol = s; AUnions = new BinnedUnion[tAs.Length]; BUnions = new BinnedUnion[tAs.Length]; Results = new BinnedUnion[tAs.Length]; var owner = tAs[0].Owner; for (int i = 0; i < tAs.Length; ++i) { AUnions[i] = new BinnedUnion(tAs[i]); BUnions[i] = new BinnedUnion(tBs[i]); Results[i] = new BinnedUnion(owner); } this.parent = parent; }
internal bool MkIntersection(Term t, out Term tintr) { Contract.Assert(t != null && t.Owner == Term.Owner); if (t == Term) { tintr = t; return(true); } var result = new DelayedIntersection(this, t); var intrStack = new Stack <DelayedIntersection>(); intrStack.Push(result); //// Uses a depth-first expansion to compute //// f(t1,...,tn) /\ f(t1',...,tn') as //// f(t1 /\ t1',..., tn /\ tn'). int pos; Term max; bool wasAdded; Set <Term> binA, binB; BinnedUnion unnA = null, unnB = null, intr = null; DelayedIntersection top; while (intrStack.Count > 0) { top = intrStack.Peek(); if (top.MoveBin(out pos)) { unnA = top.AUnions[pos]; unnB = top.BUnions[pos]; intr = top.Results[pos]; } else { intrStack.Pop(); continue; } foreach (var kv in unnA.binMap) { binA = kv.Value; if (!unnB.binMap.TryFindValue(kv.Key, out binB)) { continue; } if (kv.Key.Kind == SymbolKind.ConSymb) { max = index.MkApply(((ConSymb)kv.Key).SortSymbol, TermIndex.EmptyArgs, out wasAdded); } else if (kv.Key.Kind == SymbolKind.MapSymb) { max = index.MkApply(((MapSymb)kv.Key).SortSymbol, TermIndex.EmptyArgs, out wasAdded); } else if (kv.Key == stringSymb) { IntersectStrings(binA, binB, top.Results[pos]); continue; } else if (kv.Key == trueSymb) { IntersectUsrConsts(binA, binB, top.Results[pos]); continue; } else if (kv.Key == realSymb) { IntersectNumerics( binA, top.AUnions[pos].intervals, binB, top.BUnions[pos].intervals, top.Results[pos]); continue; } else { throw new NotImplementedException(); } if (binA.Contains(max)) { foreach (var b in binB) { intr.Add(b); } continue; } else if (binB.Contains(max)) { foreach (var a in binA) { intr.Add(a); } continue; } //// Now both bins only contain terms starting with f(....) foreach (var a in binA) { if (binB.Contains(a)) { intr.Add(a); continue; } else if (a.Groundness == Groundness.Ground) { foreach (var b in binB) { if (index.IsGroundMember(b, a)) { intr.Add(a); break; } } } else { foreach (var b in binB) { if (b.Groundness == Groundness.Ground) { if (index.IsGroundMember(a, b)) { intr.Add(b); } } else { intrStack.Push(new DelayedIntersection(a.Symbol, a.Args, b.Args, top)); } } } } } } if (result.Results[0].binMap.Count == 0) { tintr = null; return(false); } else { tintr = result.Results[0].Term; return(true); } }