예제 #1
0
        /// <summary>
        /// Finds the minimal elements, in the partial order induced by unification, of the partial model facts.
        /// The number of minimal elements gives a lower bound on the number of distinct facts that must appear in an valid model.
        /// </summary>
        private void BuildPartialModelLowerBounds()
        {
            //// Step 1. Bin facts by head symbol.
            Term pattern;
            LinkedList <Term> gbin;
            Map <Term, MutableTuple <bool> > ngbin;
            var grdBins = new Map <Symbol, LinkedList <Term> >(Symbol.Compare);

            //// A term maps to true if it is deleted from the bin.
            var ngBins = new Map <Symbol, Map <Term, MutableTuple <bool> > >(Symbol.Compare);

            foreach (var f in Facts.Facts)
            {
                pattern = MkPattern(f);
                if (pattern == f)
                {
                    Contract.Assert(pattern.Groundness == Groundness.Ground);
                    if (!grdBins.TryFindValue(f.Symbol, out gbin))
                    {
                        gbin = new LinkedList <Term>();
                        grdBins.Add(f.Symbol, gbin);
                    }

                    gbin.AddLast(f);
                }
                else
                {
                    Contract.Assert(pattern.Groundness == Groundness.Variable);
                    if (!ngBins.TryFindValue(f.Symbol, out ngbin))
                    {
                        ngbin = new Map <Term, MutableTuple <bool> >(Term.Compare);
                        ngBins.Add(f.Symbol, ngbin);
                    }

                    if (!ngbin.ContainsKey(pattern))
                    {
                        ngbin.Add(pattern, new MutableTuple <bool>(false));
                    }
                }
            }

            //// Step 2. Any non-ground fact that matches with a ground fact is not minimal.
            Matcher matcher;

            foreach (var kv in ngBins)
            {
                ngbin = kv.Value;
                if (!grdBins.TryFindValue(kv.Key, out gbin))
                {
                    continue;
                }

                foreach (var p in ngbin)
                {
                    matcher = new Matcher(p.Key);
                    foreach (var g in gbin)
                    {
                        if (matcher.TryMatch(g))
                        {
                            p.Value.Item1 = true;
                            break;
                        }
                    }
                }

                PruneBin(ngbin);
            }

            //// Step 3. Iteratively compute the minimal elements until a fixpoint is reached.
            Term mgu;
            bool changed;
            LinkedList <Term> newGLBs;

            foreach (var kv in ngBins)
            {
                ngbin   = kv.Value;
                changed = true;
                while (changed)
                {
                    changed = false;
                    newGLBs = null;
                    foreach (var p1 in ngbin)
                    {
                        foreach (var p2 in ngbin.GetEnumerable(p1.Key))
                        {
                            if (p1.Key == p2.Key)
                            {
                                continue;
                            }
                            else if (Unifier.IsUnifiable(p1.Key, p2.Key, x => MkNormalizedVar(Facts.Index, x), out mgu))
                            {
                                if (mgu != p1.Key)
                                {
                                    p1.Value.Item1 = true;
                                }

                                if (mgu != p2.Key)
                                {
                                    p2.Value.Item1 = true;
                                }

                                if (mgu != p1.Key && mgu != p2.Key && !ngbin.ContainsKey(mgu))
                                {
                                    changed = true;
                                    if (newGLBs == null)
                                    {
                                        newGLBs = new LinkedList <Term>();
                                    }

                                    newGLBs.AddLast(mgu);
                                }
                            }
                        }
                    }

                    PruneBin(ngbin, newGLBs);
                }
            }

            //// Step 4. Create lower bounds
            Cardinality card;

            foreach (var kv in ngBins)
            {
                grdBins.TryFindValue(kv.Key, out gbin);
                if (gbin == null)
                {
                    card = new Cardinality(new BigInteger(kv.Value.Count));
                }
                else
                {
                    card = new Cardinality(new BigInteger(kv.Value.Count) + new BigInteger(gbin.Count));
                }

                AddConstraint(varMap[(UserSymbol)kv.Key].Item3 >= new CardCnst(card));
            }

            foreach (var kv in grdBins)
            {
                if (ngBins.ContainsKey(kv.Key))
                {
                    continue;
                }

                AddConstraint(varMap[(UserSymbol)kv.Key].Item3 >= new CardCnst(new Cardinality(new BigInteger(kv.Value.Count))));
            }
        }
예제 #2
0
        private bool Propagate(CardVar cvar)
        {
            Cardinality    cd;
            CardRange      lhs, rhs;
            CardRange      intr, intrp;
            CardConstraint con;
            var            stack = new Stack <CardConstraint>();

            EnqueueConstraints(cvar, stack);
            while (stack.Count > 0)
            {
                con          = stack.Pop();
                lhs          = GetRange(con.Lhs);
                rhs          = Eval(con.Rhs);
                con.IsQueued = false;

                switch (con.Op)
                {
                case CardConstraint.OpKind.LEq:
                    if ((cd = Cardinality.Min(lhs.Upper, rhs.Upper)) != lhs.Upper)
                    {
                        if (cd < lhs.Lower)
                        {
                            return(false);
                        }

                        UpdateRange(con.Lhs, lhs = new CardRange(lhs.Lower, cd));
                        EnqueueConstraints(con.Lhs, stack);
                    }

                    if (rhs.Lower < lhs.Lower)
                    {
                        foreach (var rhsvar in con.RhsVars)
                        {
                            rhs = GetRange(rhsvar);
                            if (Eval(con.Rhs, rhsvar, rhs.Lower, false) >= lhs.Lower)
                            {
                                continue;
                            }

                            intr = new CardRange(rhs.Lower, Cardinality.Min(lhs.Lower, rhs.Upper));
                            while (intr.Lower + 1 < intr.Upper)
                            {
                                intrp = intr.Bisect(true);
                                if (Eval(con.Rhs, rhsvar, intrp.Lower, false) >= lhs.Lower)
                                {
                                    intr = new CardRange(intr.Lower, intrp.Lower);
                                }
                                else
                                {
                                    intr = new CardRange(intrp.Lower, intr.Upper);
                                }
                            }

                            if (Eval(con.Rhs, rhsvar, intr.Lower, false) >= lhs.Lower)
                            {
                                if (intr.Lower > rhs.Lower)
                                {
                                    UpdateRange(rhsvar, new CardRange(intr.Lower, rhs.Upper));
                                    EnqueueConstraints(rhsvar, stack);
                                    continue;
                                }
                            }
                            else if (Eval(con.Rhs, rhsvar, intr.Upper, false) >= lhs.Lower)
                            {
                                if (intr.Upper > rhs.Lower)
                                {
                                    UpdateRange(rhsvar, new CardRange(intr.Upper, rhs.Upper));
                                    EnqueueConstraints(rhsvar, stack);
                                    continue;
                                }
                            }
                            else
                            {
                                return(false);
                            }
                        }
                    }

                    break;

                case CardConstraint.OpKind.GEq:
                    if ((cd = Cardinality.Max(lhs.Lower, rhs.Lower)) != lhs.Lower)
                    {
                        if (cd > lhs.Upper)
                        {
                            return(false);
                        }

                        UpdateRange(con.Lhs, lhs = new CardRange(cd, lhs.Upper));
                        EnqueueConstraints(con.Lhs, stack);
                    }

                    if (rhs.Upper > lhs.Upper)
                    {
                        foreach (var rhsvar in con.RhsVars)
                        {
                            rhs = GetRange(rhsvar);
                            if (Eval(con.Rhs, rhsvar, rhs.Upper, true) <= lhs.Upper)
                            {
                                continue;
                            }

                            intr = new CardRange(rhs.Lower, Cardinality.Min(rhs.Upper, lhs.Upper));
                            while (intr.Lower + 1 < intr.Upper)
                            {
                                intrp = intr.Bisect(false);
                                if (Eval(con.Rhs, rhsvar, intrp.Upper, true) <= lhs.Upper)
                                {
                                    intr = new CardRange(intrp.Upper, intr.Upper);
                                }
                                else
                                {
                                    intr = new CardRange(intr.Lower, intrp.Upper);
                                }
                            }

                            if (Eval(con.Rhs, rhsvar, intr.Upper, true) <= lhs.Upper)
                            {
                                if (intr.Upper < rhs.Upper)
                                {
                                    UpdateRange(rhsvar, new CardRange(rhs.Lower, intr.Upper));
                                    EnqueueConstraints(rhsvar, stack);
                                    continue;
                                }
                            }
                            else if (Eval(con.Rhs, rhsvar, intr.Lower, true) <= lhs.Upper)
                            {
                                if (intr.Lower < rhs.Upper)
                                {
                                    UpdateRange(rhsvar, new CardRange(rhs.Lower, intr.Lower));
                                    EnqueueConstraints(rhsvar, stack);
                                    continue;
                                }
                            }
                            else
                            {
                                return(false);
                            }
                        }
                    }

                    break;

                default:
                    throw new NotImplementedException();
                }
            }

            return(true);
        }
예제 #3
0
 public static Cardinality Max(Cardinality v1, Cardinality v2)
 {
     return(v1 >= v2 ? v1 : v2);
 }
예제 #4
0
 public CardCnst(Cardinality value)
 {
     Value = value;
 }
예제 #5
0
 public static Cardinality Min(Cardinality v1, Cardinality v2)
 {
     return(v1 <= v2 ? v1 : v2);
 }