Ejemplo n.º 1
0
        }         //ProcessOr

        /// <summary>
        /// Processes an atom.
        /// </summary>
        /// <param name="atomToRun"></param>
        /// <param name="excludedFacts"></param>
        /// <returns></returns>
        private IEnumerator <Fact> ProcessAtom(Atom atomToRun, IList <Fact> excludedFacts)
        {
            if (atomToRun is AtomFunction)
            {
                // an atom function is either positive or negative, it does not return any fact
                // if this atom function is wrapped in naf, then the base result is negated,
                // leading to a positive result if the underlying function is negative!
                if (((AtomFunction)atomToRun).PositiveRelation != atomToRun.Negative)
                {
                    return(FactEnumeratorFactory.NewSingleFactEnumerator(NAF));
                }
            }
            else
            {
                if (atomToRun.Negative)
                {
                    // a negative atom, fails if any matching fact is found
                    // and succeed if no data collection (ie returns one dummy fact as a token)
                    // if no facts are actually found
                    // Bug #1332214 pinpointed that excludedFacts should not be applied on Negative atoms
                    IEnumerator matchResult = Select(atomToRun, null);
                    if ((matchResult == null) || (!matchResult.MoveNext()))
                    {
                        return(FactEnumeratorFactory.NewSingleFactEnumerator(NAF));
                    }
                }
                else
                {
                    return(Select(atomToRun, excludedFacts));
                }
            }

            return(null);
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Gets a list of facts matching a particular atom.
        /// </summary>
        /// <param name="filter">The atom to match</param>
        /// <param name="excludedFacts">A list of facts not to return, or null</param>
        /// <returns>An IList containing the matching facts (empty if no match, but never null).</returns>
        public IEnumerator <Fact> Select(Atom filter, IList <Fact> excludedFacts)
        {
            if (Logger.IsInferenceEngineVerbose)
            {
                Logger.InferenceEngineSource.TraceEvent(TraceEventType.Verbose,
                                                        0,
                                                        "FactBase.Select: " + filter + " - Excluding: " + Misc.IListToString((IList)excludedFacts));
            }

            // if the predicate map does not contain an entry for the filter signature or if this entry is empty, return empty result
            if ((!predicateMap.ContainsKey(filter.Signature)) || (predicateMap[filter.Signature].Count == 0))
            {
                if (Logger.IsInferenceEngineVerbose)
                {
                    Logger.InferenceEngineSource.TraceEvent(TraceEventType.Verbose, 0, "No fact matching signature: " + filter.Signature);
                }
                return(EMPTY_SELECT_RESULT.GetEnumerator());
            }

            // if the filter contains only variables, everything should be returned
            if (filter.OnlyVariables)
            {
                if (Logger.IsInferenceEngineVerbose)
                {
                    Logger.InferenceEngineSource.TraceEvent(TraceEventType.Verbose, 0, "Filter with no Ind or Fun -> Return all facts matching signature: " + filter.Signature);
                }
                return(FactEnumeratorFactory.NewFactListExcludingEnumerator(signatureMap[filter.Signature], excludedFacts));
            }

            // we build result lists and will reduce the biggest ones from the smallest ones
            ICollection <Fact> resultList = null;
            int smallestList           = Int32.MaxValue;
            int positionOfSmallestList = -1;

            for (int position = 0; position < filter.Members.Length; position++)
            {
                if (filter.Members[position] is Individual)
                {
                    bool   matched        = false;
                    object predicateValue = filter.Members[position].Value;
                    IDictionary <object, IDictionary <int, ICollection <Fact> > > predicateValueMap;

                    if (predicateMap[filter.Signature].TryGetValue(predicateValue.GetType(), out predicateValueMap))
                    {
                        IDictionary <int, ICollection <Fact> > predicatePositionMap;

                        if (predicateValueMap.TryGetValue(predicateValue, out predicatePositionMap))
                        {
                            if ((predicatePositionMap.ContainsKey(position)) && (predicatePositionMap[position].Count > 0))
                            {
                                if (Logger.IsInferenceEngineVerbose)
                                {
                                    Logger.InferenceEngineSource.TraceEvent(TraceEventType.Verbose,
                                                                            0,
                                                                            "Matched predicateValue: " + predicateValue + " [" + predicateValue.GetType() + "]");
                                }

                                if (predicatePositionMap[position].Count < smallestList)
                                {
                                    resultList             = predicatePositionMap[position];
                                    smallestList           = predicatePositionMap[position].Count;
                                    positionOfSmallestList = position;

                                    if (Logger.IsInferenceEngineVerbose)
                                    {
                                        Logger.InferenceEngineSource.TraceEvent(TraceEventType.Verbose,
                                                                                0,
                                                                                "Smallest list of size: " + smallestList + " at position: " + positionOfSmallestList);
                                    }
                                }

                                matched = true;
                            }
                        }
                    }

                    // no match found on a particular individual predicate? early return an empty result!
                    if (!matched)
                    {
                        if (Logger.IsInferenceEngineVerbose)
                        {
                            Logger.InferenceEngineSource.TraceEvent(TraceEventType.Verbose, 0, "No match -> Return no fact");
                        }

                        return(EMPTY_SELECT_RESULT.GetEnumerator());
                    }
                }
            }

            // only one predicate in the filter and we matched it, no need for post matching, return filtered results directly
            if ((filter.Members.Length == 1) && (resultList != null))
            {
                if (Logger.IsInferenceEngineVerbose)
                {
                    Logger.InferenceEngineSource.TraceEvent(TraceEventType.Verbose, 0, "One member filter and got resultList -> Return facts immediatly");
                }

                return(FactEnumeratorFactory.NewFactListExcludingEnumerator(resultList, excludedFacts));
            }

            // we have not been able to match anything (the filter might contain only variables or functions),
            // let's load all the facts matching the signature of the filter
            if (resultList == null)
            {
                resultList = signatureMap[filter.Signature];

                if (Logger.IsInferenceEngineVerbose)
                {
                    Logger.InferenceEngineSource.TraceEvent(TraceEventType.Verbose, 0, "No resultList -> Used the list matching the signature, which contains: " + resultList.Count);
                }
            }

            // we append a fact as a result only if it matches the filter predicates
            // if a predicate has been previously matched, we do not compare it again in the matching process: we add its position
            // to the ignore list
            IList <int> ignoredPredicates = null;

            if (positionOfSmallestList != -1)
            {
                ignoredPredicates = new List <int>();
                ignoredPredicates.Add(positionOfSmallestList);
            }

            return(FactEnumeratorFactory.NewFactListPredicateMatchingEnumerator(resultList,
                                                                                filter,
                                                                                strictTyping,
                                                                                ignoredPredicates,
                                                                                excludedFacts));
        }