Example #1
0
            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);
                        }
                    }
                }
            }
Example #2
0
 private void IntersectUsrConsts(Set <Term> s1, Set <Term> s2, BinnedUnion result)
 {
     foreach (var t in s1)
     {
         if (s2.Contains(t))
         {
             result.Add(t);
         }
     }
 }
Example #3
0
 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);
 }
Example #4
0
                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;
                }
Example #5
0
            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);
                }
            }
Example #6
0
            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);
                }
            }