private void IntersectStrings(Set <Term> s1, Set <Term> s2, BinnedUnion result) { bool wasAdded; var stringTerm = index.MkApply(stringSymb, TermIndex.EmptyArgs, out wasAdded); if (s1.Contains(stringTerm)) { foreach (var t in s2) { result.Add(t); } } else if (s2.Contains(stringTerm)) { foreach (var t in s1) { result.Add(t); } } else { foreach (var t in s1) { if (s2.Contains(t)) { result.Add(t); } } } }
private void IntersectUsrConsts(Set <Term> s1, Set <Term> s2, BinnedUnion result) { foreach (var t in s1) { if (s2.Contains(t)) { result.Add(t); } } }
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); } }
private void IntersectNumerics(Set <Term> s1, IntIntervals i1, Set <Term> s2, IntIntervals i2, BinnedUnion result) { bool wasAdded; var realTrm = index.MkApply(realSymb, TermIndex.EmptyArgs, out wasAdded); var intTrm = index.MkApply(index.SymbolTable.GetSortSymbol(BaseSortKind.Integer), TermIndex.EmptyArgs, out wasAdded); var natTrm = index.MkApply(index.SymbolTable.GetSortSymbol(BaseSortKind.Natural), TermIndex.EmptyArgs, out wasAdded); var posTrm = index.MkApply(index.SymbolTable.GetSortSymbol(BaseSortKind.PosInteger), TermIndex.EmptyArgs, out wasAdded); var negTrm = index.MkApply(index.SymbolTable.GetSortSymbol(BaseSortKind.NegInteger), TermIndex.EmptyArgs, out wasAdded); //// Handle the case where one side contains Real if (s1.Contains(realTrm)) { foreach (var t in s2) { result.Add(t); } if (i2 != null) { foreach (var kv in i2.CanonicalForm) { result.Add(index.MkApply( rngSymb, new Term[] { index.MkCnst(new Rational(kv.Key, BigInteger.One), out wasAdded), index.MkCnst(new Rational(kv.Value, BigInteger.One), out wasAdded) }, out wasAdded)); } } return; } else if (s2.Contains(realTrm)) { foreach (var t in s1) { result.Add(t); } if (i1 != null) { foreach (var kv in i1.CanonicalForm) { result.Add(index.MkApply( rngSymb, new Term[] { index.MkCnst(new Rational(kv.Key, BigInteger.One), out wasAdded), index.MkCnst(new Rational(kv.Value, BigInteger.One), out wasAdded) }, out wasAdded)); } } return; } else { //// Need to keep all real constants common to both sets. var sA = s1.Count <= s2.Count ? s1 : s2; var sB = s2.Count >= s1.Count ? s2 : s1; foreach (var t in sA) { if (t.Symbol.Kind == SymbolKind.BaseCnstSymb && sB.Contains(t)) { result.Add(t); } } } //// Handle the case where one side contains Integer. if (s1.Contains(intTrm)) { foreach (var t in s2) { if (t.Symbol.Kind != SymbolKind.BaseCnstSymb || s1.Contains(t)) { result.Add(t); } } if (i2 != null) { foreach (var kv in i2.CanonicalForm) { result.Add(index.MkApply( rngSymb, new Term[] { index.MkCnst(new Rational(kv.Key, BigInteger.One), out wasAdded), index.MkCnst(new Rational(kv.Value, BigInteger.One), out wasAdded) }, out wasAdded)); } } return; } else if (s2.Contains(intTrm)) { foreach (var t in s1) { if (t.Symbol.Kind != SymbolKind.BaseCnstSymb || s2.Contains(t)) { result.Add(t); } result.Add(t); } if (i1 != null) { foreach (var kv in i1.CanonicalForm) { result.Add(index.MkApply( rngSymb, new Term[] { index.MkCnst(new Rational(kv.Key, BigInteger.One), out wasAdded), index.MkCnst(new Rational(kv.Value, BigInteger.One), out wasAdded) }, out wasAdded)); } } return; } //// Neither set contains all reals or all integers. //// First take intersections of intervals: O(n) if (i1 != null && i2 != null) { BigInteger aS, aE, bS, bE, s, e; using (var itA = i1.CanonicalForm.GetEnumerator()) { using (var itB = i2.CanonicalForm.GetEnumerator()) { var cont = itA.MoveNext() && itB.MoveNext(); while (cont) { aS = itA.Current.Key; aE = itA.Current.Value; bS = itB.Current.Key; bE = itB.Current.Value; s = aS > bS ? aS : bS; e = aE < bE ? aE : bE; cont = aE <= bE?itA.MoveNext() : itB.MoveNext(); if (s <= e) { result.Add(index.MkApply( rngSymb, new Term[] { index.MkCnst(new Rational(s, BigInteger.One), out wasAdded), index.MkCnst(new Rational(e, BigInteger.One), out wasAdded) }, out wasAdded)); } } } } } //// Next consider intervals intersecting with Nat, Pos, and Neg. if (i2 != null) { bool hasNat = s1.Contains(natTrm); bool hasPos = s1.Contains(posTrm); bool hasNeg = s1.Contains(negTrm); if (hasNat || hasPos || hasNeg) { var nonNegLB = hasNat ? BigInteger.Zero : BigInteger.One; foreach (var kv in i2.CanonicalForm) { if (hasNeg) { if (kv.Key < BigInteger.Zero) { result.Add(index.MkApply( rngSymb, new Term[] { index.MkCnst(new Rational(kv.Key, BigInteger.One), out wasAdded), index.MkCnst(new Rational(BigInteger.Min(kv.Value, BigInteger.MinusOne), BigInteger.One), out wasAdded) }, out wasAdded)); } } if (hasNat || hasPos) { if (kv.Value >= nonNegLB) { result.Add(index.MkApply( rngSymb, new Term[] { index.MkCnst(new Rational(BigInteger.Max(kv.Key, nonNegLB), BigInteger.One), out wasAdded), index.MkCnst(new Rational(kv.Value, BigInteger.One), out wasAdded) }, out wasAdded)); } } } } } if (i1 != null) { bool hasNat = s2.Contains(natTrm); bool hasPos = s2.Contains(posTrm); bool hasNeg = s2.Contains(negTrm); if (hasNat || hasPos || hasNeg) { var nonNegLB = hasNat ? BigInteger.Zero : BigInteger.One; foreach (var kv in i1.CanonicalForm) { if (hasNeg) { if (kv.Key < BigInteger.Zero) { result.Add(index.MkApply( rngSymb, new Term[] { index.MkCnst(new Rational(kv.Key, BigInteger.One), out wasAdded), index.MkCnst(new Rational(BigInteger.Min(kv.Value, BigInteger.MinusOne), BigInteger.One), out wasAdded) }, out wasAdded)); } } if (hasNat || hasPos) { if (kv.Value >= nonNegLB) { result.Add(index.MkApply( rngSymb, new Term[] { index.MkCnst(new Rational(BigInteger.Max(kv.Key, nonNegLB), BigInteger.One), out wasAdded), index.MkCnst(new Rational(kv.Value, BigInteger.One), out wasAdded) }, out wasAdded)); } } } } } //// Finally, consider intersections between the sorts Nat, Pos, Neg. if (s1.Contains(natTrm)) { if (s2.Contains(natTrm)) { result.Add(natTrm); } else if (s2.Contains(posTrm)) { result.Add(posTrm); } } else if (s2.Contains(natTrm)) { if (s1.Contains(natTrm)) { result.Add(natTrm); } else if (s1.Contains(posTrm)) { result.Add(posTrm); } } else if (s1.Contains(posTrm) && s2.Contains(posTrm)) { result.Add(posTrm); } if (s1.Contains(negTrm) && s2.Contains(negTrm)) { result.Add(negTrm); } }