проблема пролога; отображение университетов того же ранга - PullRequest
1 голос
/ 06 января 2011

Извините за тупое название, но не смог обобщить вопрос. Надеюсь, кто-то с опытом Пролог может помочь мне здесь. Итак, у меня есть база данных, которая в основном перечисляет университеты и их рейтинг, то есть: Оксфорд (1), Уорик (2) и т. Д. Вопрос требует от меня написать правило, которое возвращает все названия университетов, которые имеют одинаковый рейтинг , Заранее спасибо.

1 Ответ

1 голос
/ 07 января 2011

Я полагаю, что для этого потребуется немного метапрограммирования, но только немного. Вам, вероятно, придется предоставить некоторые отзывы о моих предположениях в этом ответе, чтобы получить надежное решение. Но я думаю, что участие в нем поможет вам быстрее (и мы оба узнаем кое-что по ходу дела), чем задавать последовательность уточняющих комментариев.

Нашей непосредственной целью будет найти эти «университетские» факты с помощью того, что SWI-Prolog называет «Изучение программы» (ссылки ниже, но вы можете найти его в разделе Руководства ). Если мы можем сделать это, мы можем запросить эти факты, чтобы получить конкретный рейтинг, получая при этом все университеты одного ранга.

Из того, что вы сказали, есть ряд «фактов» формы «УНИВЕРСИТЕТ (RANK)». Обычно, если вы обращаетесь к файлу, содержащему их из SWI-Prolog, они будут динамическими предикатами и (если вы не сделали что-то явное, чтобы избежать этого), добавленные в модуль [user]. Такая база данных часто называется «базой фактов». Факты здесь означают пункты только с головой (без тела); динамические предикаты, как правило, могут иметь предложения с телами или без них.

SWI-Prolog имеет три различных механизма базы данных. Мы обсуждаем базу данных предложений, которая управляется не только путем консультаций, но и с помощью мета-предикатов assert / retract. Мы будем называть их «динамическими» предикатами.

Вот модификация фрагмента кода , который Ян Вилемейкер предоставляет для генерации (посредством обратного отслеживания) всех встроенных предикатов , теперь переназначенных для генерации динамического предикатов:

    generate_dynamic(Name/Arity) :-  
        predicate_property(user:Head, dynamic),  
        functor(Head, Name, Arity).  % get arity: number of args  

В вашем случае вас интересуют только некоторые динамические предикаты, так что это может дать слишком много результатов. Один из способов сузить ситуацию - установить Arity = 1, поскольку ваши университетские факты состоят только из предикатов с одним аргументом.

Еще один способ сузить ситуацию - это отсутствие тела. Если эта проверка необходима, мы можем включить вызов clause / 2 (задокументировано на той же странице, ссылка на которую приведена выше). Если у нас есть «факт» (предложение без тела), то результирующий вызов clause / 2 возвращает второй аргумент (тело), ​​установленный для атома true.

В качестве заключительного замечания, на веб-сайте Яна используется SWI-Prolog для доставки своих страниц, но полученные ссылки не всегда хорошо вырезаны и вставлены. Если приведенная выше ссылка не работает для вас, вы можете перейти к разделу 4.14 Руководства или попробуйте эту ссылку на зеркальную копию документации, которая выглядит не совсем актуальной (см. Различие в нумерации разделов и отсутствие фрагмента кода Яна).

И не стесняйтесь задавать вопросы, если я сказал что-то, что требует разъяснения, или предположил что-то, что не относится к вашей настройке.

Добавлено: Давайте закончим ответ, показывая, как запросить список университетов, заданных как таковые или полученных из «базы фактов», как описано выше. Затем у нас есть несколько комментариев о дизайне и обучении в конце.

Предположим, LU = [Оксфорд, Уорик, ...] в руке, список всех возможных университетов. Помимо эффективности, мы можем даже не заботиться о том, есть ли в списке несколько вещей, которые не являются университетами или не ранжируются, в зависимости от характера запроса, который вы хотите выполнить.

listUniversityRank(LU,V,R) :-  % LU: list of universities  
    member(V,LU),  
    call(V(R)).  

Приведенный выше фрагмент определяет предикат listUniversityRank / 2 , который мы предоставили бы список университетов и который, в свою очередь, вызывал бы динамически сгенерированную цель для каждого члена списка, чтобы найти его ранг. Такой предикат может быть использован несколькими способами для достижения вашей цели поиска «всех названий университетов, имеющих одинаковый рейтинг».

Например, мы могли бы спросить конкретный ранг R = 1, какие университеты разделяют этот ранг. Вызов listUniversityRank (LU, V, R) с R, связанным с 1, достиг бы этого, по крайней мере, в том смысле, что он будет возвращаться через все такие имена университетов. Если вы хотите собрать эти имена в список, вы можете использовать findall / 3 .

В этом отношении вы можете начать перечислять «все названия университетов, имеющих одинаковый ранг», составив список всех возможных рангов, используя setof / 3 , чтобы собрать решения для R в списке UniversityRank (LU, _, R). setof аналогично findall , но сортирует результаты и удаляет дубликаты.

Теперь давайте оглянемся назад и подумаем о том, как усердно мы работаем для достижения поставленной цели, и какой может быть конструкция, облегчающая жизнь для этой цели. Нам нужен список названий университетов с определенным свойством (все имеют одинаковый ранг). Было бы проще, если бы у нас был список названий университетов для начала. Как отмечает Little Bobby Tables в одном из Комментариев к Вопросу, нам трудно сказать, что такое университет, а что нет, если в нашей программе есть факты, подобные foo (3).

Но здесь происходит нечто большее. Использование названий университетов для создания «фактов», различных предикатов для каждого отдельного университета, скрывает отношения университета и ранга, которые мы хотели бы запросить. Если бы нам пришлось сделать это снова, наверняка, мы бы предпочли представить эти отношения с помощью одного предиката с двумя аргументами, скажем, universityRank / 2 , который напрямую связывает каждое название университета и соответствующий ранг. Меньше предикатов, лучший дизайн (потому что их легче запрашивать, без сложного метапрограммирования).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...