Exemplo n.º 1
0
        private void PrintQueryResult(QueryResult queryResult)
        {
            var args = queryResult.TheQuery.Arguments.Select(arg => arg.Name).ToArray();

            view.PrintOutput(Colors.DimGray, "> ");
            view.PrintOutput(Colors.LightGray,
                string.Format("{0}({1})?\n", queryResult.TheQuery.Name, string.Join(", ", args)));
            if (queryResult.Solutions != null && (queryResult.Solutions.Any() == queryResult.Result))
            {
                if (queryResult.Solutions.Any())
                {
                    var c = queryResult.Solutions.Count;
                    view.PrintOutput(Colors.DimGray,
                        string.Format("  {0} решени{1}\n", c, c == 1 ? "е" : (c < 5 ? "я" : "й")));
                    foreach (var solution in queryResult.Solutions)
                    {
                        view.PrintOutput(SyntaxColors.Atom, "  ");
                        foreach (var atom in solution.Keys)
                        {
                            var value = solution[atom];
                            view.PrintOutput(SyntaxColors.Atom, string.Format("{0}", atom));
                            view.PrintOutput(Colors.White,
                                string.Format(" = {0}{1}", value, atom == solution.Keys.Last() ? "" : ", "));
                        }
                        view.PrintOutput(Colors.White, "\n");
                    }
                }
                else
                {
                    view.PrintOutput(Colors.LightCoral, "  Решений нет\n");
                }
            }
            else
            {
                if (queryResult.Result)
                {
                    view.PrintOutput(Colors.LightGreen, "  Истина\n");
                }
                else
                {
                    view.PrintOutput(Colors.LightCoral, "  Ложь\n");
                }
            }
        }
Exemplo n.º 2
0
        private static QueryResult ApplyLogicalOperator(QueryResult v1, ConditionOperator? @operator, QueryResult v2)
        {
            if (v1 == null)
            {
                return v2;
            }

            if (@operator == ConditionOperator.And)
            {
                IEnumerable<Dictionary<string, string>> solutions;
                bool includeSolutions = true;
                if (v1.Solutions != null)
                {
                    if (v2.Solutions != null)
                    {
                        var v2Solutions = new List<string>();
                        v2.Solutions.ForEach(solution => v2Solutions.Add(Stringify(solution)));

                        solutions = v1.Solutions.Where(s => v2Solutions.Contains(Stringify(s)));
                    }
                    else
                    {
                        solutions = v1.Solutions;
                    }
                }
                else
                {
                    if (v2.Solutions != null)
                    {
                        solutions = v2.Solutions;
                    }
                    else
                    {
                        includeSolutions = false;
                        solutions = new List<Dictionary<string, string>>();
                    }
                }

                if (includeSolutions)
                {
                    var solutionList = solutions.ToList();
                    return new QueryResult(solutionList.Any(), v2.TheQuery, solutionList);
                }
                return new QueryResult(v1.Result & v2.Result, v2.TheQuery);
            }
            if (v1.Result) return v1;
            if (v2.Result) return v2;
            return new QueryResult(false, v2.TheQuery);
        }
Exemplo n.º 3
0
        private static QueryResult ResolveQuery(Query query)
        {
            if (_cache.ContainsKey(query))
            {
                if (_cache[query] == null)
                {
                    if (query.HasAtoms)
                    {
                        _cache[query] = new QueryResult(false, query, new List<Dictionary<string, string>>());
                    }
                    else
                    {
                        _cache[query] = new QueryResult(false, query);
                    }
                }
                return _cache[query];
            }

            _cache.Add(query, null);

            if (!query.HasAtoms) // Если нет атомов, то запрос простой (возвращает true или false)
            {
                // Попытка 1:
                // Ищем факт с именем запроса
                // И таким же набором аргументов (порядок важен)
                if (_facts.Any(fact => fact.Name == query.Name && fact.Arguments.SequenceEqual(query.Arguments)))
                {
                    return AddToCacheAndReturn(query, new QueryResult(true, query));
                }

                // Попытка 2:
                // Найти все правила с именем запроса
                // И аналогичным количеством аргументов
                var matchingRules = _rules.FindAll(rule => rule.Name == query.Name
                                                           &&
                                                           rule.Arguments.Count == query.Arguments.Count);

                // Если есть такие правила, то играем в дедукцию
                // Подставляем каждому правилу вместо атомов аргументы запроса
                // И рекурсивно вычисляем каждое условие
                if (matchingRules.Any())
                {
                    foreach (var rule in matchingRules)
                    {
                        QueryResult finalResult = null;
                        foreach (var condition in rule.Conditions)
                        {
                            // Подставляем вместо атомов аргументы запроса
                            var conditionArgs = ReplaceAtomsWithNames(rule.Arguments, query.Arguments,
                                condition.Condition.Arguments);

                            // Вычисляем значение запроса
                            var conditionQuery = new Query(condition.Condition.Name, conditionArgs);

                            QueryResult queryResult;
                            if (_cache.ContainsKey(conditionQuery))
                            {
                                if (_cache[query] == null)
                                {
                                    return AddToCacheAndReturn(query, new QueryResult(false, query));
                                }
                                queryResult = _cache[query];
                            }
                            else
                            {
                                queryResult = ResolveQuery(conditionQuery);
                            }

                            if (condition.Condition.IsNegated)
                            {
                                if (queryResult.Solutions != null)
                                {
                                    queryResult = new QueryResult(!queryResult.Result, queryResult.TheQuery, queryResult.Solutions);
                                }
                                else
                                {
                                    queryResult = new QueryResult(!queryResult.Result, queryResult.TheQuery);
                                }
                            }

                            // Применяем логический оператор
                            finalResult = ApplyLogicalOperator(finalResult, condition.Operator, queryResult);
                        }
                        if (finalResult != null && finalResult.Result)
                        {
                            return AddToCacheAndReturn(query, new QueryResult(finalResult.Result, query));
                        }
                    }
                }

                // Попытка 3:
                // Не помогла дедукция -- не беда, пробуем индукцию
                // Ищем все правила, в которых наш запрос содержится в качестве условия
                var containingRules = _rules.Where(rule => rule.Conditions.Any(cnd => cnd.Condition.Name == query.Name
                                                                                      &&
                                                                                      cnd.Condition.Arguments.Count ==
                                                                                      query.Arguments.Count))
                    // Отсеиваем правила, которые содержат условия с оператором ИЛИ
                    .Where(rule => rule.Conditions.All(cnd => cnd.Operator != ConditionOperator.Or));

                foreach (var rule in containingRules)
                {
                    foreach (var condition in rule.Conditions)
                    {
                        if (condition.Condition.Name == query.Name && condition.Condition.Arguments.Count ==
                            query.Arguments.Count)
                        {
                            if (CompareArgumentsIgnoringAtoms(condition.Condition.Arguments, query.Arguments))
                            {
                                var nextQuery = new Query(rule.Name,
                                    ReplaceAtomsWithNames(condition.Condition.Arguments, query.Arguments, rule.Arguments));

                                QueryResult result;
                                if (_cache.ContainsKey(nextQuery))
                                {
                                    if (_cache[nextQuery] == null)
                                    {
                                        return AddToCacheAndReturn(query, new QueryResult(false, query));
                                    }
                                    result = _cache[nextQuery];
                                }
                                else
                                {
                                    result = ResolveQuery(nextQuery);
                                }

                                if (result.Result != condition.Condition.IsNegated)
                                {
                                    return AddToCacheAndReturn(query, new QueryResult(true, query));
                                }
                            }
                        }
                    }
                }
            }
            else // Атомы есть
            {
                var solutions = new List<Dictionary<string, string>>();

                // Шаг 1:
                // Найти все факты с именем запроса и нужным количеством аргументов
                var matchingFacts = _facts.FindAll(fact => fact.Name == query.Name
                                                           &&
                                                           fact.Arguments.Count == query.Arguments.Count)
                    // И взять только те, у которых идентичны аргументы, не являющиеся атомами
                    .Where(fact => CompareArgumentsIgnoringAtoms(query.Arguments, fact.Arguments));

                foreach (var fact in matchingFacts)
                {
                    solutions.Add(new Dictionary<string, string>());
                    for (var i = 0; i < query.Arguments.Count; i++)
                    {
                        var arg = query.Arguments.ElementAt(i);
                        if (arg.IsAtom)
                        {
                            var solution = fact.Arguments.ElementAt(i);
                            solutions.Last().Add(arg.Name, solution.Name);
                        }
                    }
                }

                /*
                Friends(X, Y) : Likes(X, Y) AND Knows(X, Y);

                Likes(Max, Jane);
                Knows(Max, Jane);

                Friends(X, Y)?
                */

                // Шаг 2:
                // Пытаемся вычислить все правила с именем запроса
                var matchingRules = _rules.Where(rule => rule.Name == query.Name
                                                         &&
                                                         rule.Arguments.Count == query.Arguments.Count);

                foreach (var rule in matchingRules)
                {
                    var ruleQuery = new Query(rule.Name, ReplaceAtomsWithNames(rule.Arguments, query.Arguments, rule.Arguments));

                    var queryResult = ResolveQuery(ruleQuery);
                    if (queryResult.Result)
                    {
                        solutions.Add(new Dictionary<string, string>());
                        for (var i = 0; i < query.Arguments.Count; i++)
                        {
                            var arg = query.Arguments.ElementAt(i);
                            if (arg.IsAtom)
                            {
                                var solution = ruleQuery.Arguments.ElementAt(i);
                                solutions.Last().Add(arg.Name, solution.Name);
                            }
                        }
                    }
                }

                return AddToCacheAndReturn(query, new QueryResult(solutions.Any(), query, solutions));
            }

            return AddToCacheAndReturn(query, new QueryResult(false, query));
        }
Exemplo n.º 4
0
 private static QueryResult AddToCacheAndReturn(Query query, QueryResult result)
 {
     _cache[query] = result;
     return result;
 }