Beispiel #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))));
            }
        }