Как перечислить все предикаты, имеющие определенный атом?

другой способ задать вопрос:

Как я могу перечислить все свойства атома?

Например:

movie(agora).
director(agora, 'Alejandro Amenabar')
duration(agora, '2h').

Итак, я хотел бы получить все предикаты, которые имеют агору для аргумента. В данном случае это будет: фильм, режиссер, продолжительность, с остальными параметрами ("Алехандро Аменабар", "2ч").

Я нашел: это и это вопросы, но я не мог понять.

Я хочу иметь значение false в «ответе переменной», если PersonInvited что-то не нравится в фильме.

Мой запрос будет:

answer(Answer, personInvited, personWhoMadeInvitation, Movie)

Ответ: мне не нравится этот режиссер

answer(false, personInvited, personWhoMadeInvitation, Movie):-
    director(Movie, DirectorName),not(like(personInvited,DirectorName)).

То же самое произойдет с любым свойством, например жанром.

Ответ: мне не нравится этот жанр

answer(false, personInvited, personWhoMadeInvitation, Movie):-
    genre(Movie, Genre), not(like(personInvited,Genre)).

Итак, я хочу обобщить эту ситуацию, вместо того, чтобы повторять каждую особенность каждого объекта.


person titusfx    schedule 29.09.2015    source источник
comment
Вас устраивает концепция реляционных баз данных?   -  person    schedule 30.09.2015
comment
Что вы ожидаете в результате для неосновного факта, такого как succ(X,s(X)) ? Запрос :- succ(agora, Y). выполнен успешно, но этого ли вы хотите? Как насчет предикатов из библиотеки? :- member(agora, List). тоже преуспевает.   -  person lambda.xy.x    schedule 30.09.2015
comment
Во-первых, как я могу перечислить все свойства атома — бессмысленный вопрос в контексте Пролога. Затем, когда вы определяете таблицы фактов, это будет схема вашей базы данных, если хотите. Если вы знаете схему своей базы данных, вы можете писать к ней запросы. Бывают случаи, когда вы можете захотеть динамически запрашивать саму схему, но я очень сомневаюсь, что это ваше намерение. TL;DR Вы пытаетесь решить проблему, которую создали сами.   -  person    schedule 30.09.2015
comment
Как уже намекали другие, я также думаю, что вам нужен другой подход. Однако было бы полезно, если бы вы предоставили более подробную информацию о проблеме, которую пытаетесь решить. Похоже, у вас есть объекты (фильмы?) и свойства этих объектов (режиссер, продолжительность). Если это так, было бы разумно использовать модульный или объектный подход для представления ваших данных. Это позволит вам легко запросить объект о его свойствах.   -  person Paulo Moura    schedule 30.09.2015
comment
@Boris Борис, мне более или менее комфортно с этими понятиями. И да, я хочу динамически запрашивать саму схему.   -  person titusfx    schedule 01.10.2015
comment
Если вы действительно хотите запросить схему (все еще не убеждены: возможно, лучший дизайн базы данных с правильной нормализацией сделает это ненужным), внимательно посмотрите на ответ @CapelliC. Важно отметить, что помещение всего в модуль сделает его подход чище.   -  person    schedule 01.10.2015
comment
Все еще не ясно. Обычно это происходит так: у вас есть база данных, она содержит информацию. Затем вы пишете запросы, и Пролог пытается доказать их на основе базы данных. Если запрос может быть подтвержден, он завершается успешно, сообщая о выполненных привязках переменных. Это ваша правда или да + привязки переменных. Если на основе доступных данных невозможно доказать истинность запроса, он терпит неудачу. Это ваша ложь или нет. Можете ли вы описать (даже без кода), какие у вас данные, какие у вас будут вопросы и какие ответы вы ожидаете?   -  person    schedule 01.10.2015
comment
PS: как сейчас, я не могу понять, кто кого куда приглашает и т.д. Если человек не совсем понимает, то как вы объясните это компьютеру???   -  person    schedule 01.10.2015
comment
@Boris, я хочу смоделировать диалог между двумя людьми. Один человек по имени Са, скажи другому по имени Ма, если он хочет посмотреть Агору (фильм). А другой говорит: мне не нравится этот директор. Для меня это означает, что Ма сказала «Нет» (что неверно в моей переменной «Ответ») на приглашение. Это простой пример, если я хочу обобщить этот тип рассуждений, то есть, если кто-то говорит, что ему что-то не нравится в фильме, это означает, что я не смотрю фильм.   -  person titusfx    schedule 01.10.2015
comment
@Boris, в моей базе данных есть информация, что Ма не нравится режиссер фильма. Что Са пригласит Ма, и Правило (которое я пытаюсь обобщить) таково: если кто-то (Ма) говорит, что мне что-то не нравится в фильме, это означает, что я не хочу смотреть этот фильм.   -  person titusfx    schedule 01.10.2015
comment
Пожалуйста, напишите все это в своем вопросе, внимательно, как будто вы объясняете это идиоту. Старайтесь, чтобы он был как можно меньше (минимальный полезный пример лучше).   -  person    schedule 01.10.2015
comment
Я думаю, было бы хорошо, если бы вы могли изменить способ хранения своих данных, чтобы они были похожи на тройки rdf. т. е. отношение (агора, фильм). отношение('Алехандро Аменабар', направляет, агора). отношение(агора, продолжительность, 2ч).   -  person user27815    schedule 01.10.2015
comment
@user27815 user27815 действительно, как и ответ augu, но проблема в том, чтобы написать для каждого режиссера, жанра, свойства объекта одно и то же, это не чистый декларативный код. Я думал, используя метапрограммирование, я мог бы сделать это чистым способом.   -  person titusfx    schedule 01.10.2015


Ответы (6)


вот моя попытка, используя SWI-Prolog

?- current_predicate(so:F/N), N>0, length(As,N), Head =.. [F|As], clause(so:Head,Body), As=[A|_], A==agora.

обратите внимание, что я закодировал в модуле имя так факты, поэтому я уточняю с помощью имени модуля соответствующие вызовы. Такие встроенные функции (пункт/2 и current_predicate/1) совместимы с ISO, а модули (в SWI-prolog) - нет. Так что я не уверен в переносимости и т.д.

пункт/2 — это встроенная функция, позволяющая легко писать метаинтерпретации. См. ссылку для потрясающего введения в эту историческую «сильную сторону» Пролога.

Два последних вызова (я имею в виду As=[A|_], A==agora) избегают сопоставления предложений, имеющих переменную в качестве первого аргумента.

person CapelliC    schedule 30.09.2015
comment
Я не понял вашего ответа до сих пор, что я пытаюсь сделать свой собственный. Я сделал примерно то же, что и вы, но я не использовал условие, я не знаю, почему вы его использовали. Я придумал общее решение и конкретное, как у вас, но короче. Выложу общий. ?- current_predicate(PredicateName/Arity), Arity › 1, Term =.. [PredicateName, agora, OtherParameter], Term. - person titusfx; 02.10.2015
comment
пункт/2 позволяет проверять базу данных (предикаты) без их вызова, то есть без создания (потенциально труднообнаружимых) проблем из-за побочных эффектов, подразумеваемых оценкой. Кроме того, убедитесь, что вы поняли комментарий @lambda.xy.x. - person CapelliC; 02.10.2015

Я нашел два решения, второе, на мой взгляд, чище, но они разные.

Параметры:

  • PredName: имя предиката.
  • Arity: Arity предиката.
  • ParamValue: если я хочу фильтровать по одному конкретному параметру.
  • PosParam: позиция параметра в предикате.
  • ListParam: все значения параметров posibles values ​​(всегда должны быть переменными).

Решение 1:

filter_predicate(PredName, Arity, ParamValue,PosParam, ListParam):-
    current_predicate(PredName/Arity),
    Arity >= PosParam,
    nth(PosParam, ListParam, ParamValue),
    append([PredName], ListParam, PredList),
    GlobalArity is Arity + 1,
    length(PredList, GlobalArity),
    Predicate =.. PredList,
    Predicate.

Запрос

filter_predicate(PredName, Arity, agora, 1, Pm).

Вывод

Arity = 2                                                                              
Pm = [agora,'Alejandro Amenabar']
PredName = director ? 

yes

Решение 2:

filter_predicate(PredName, Arity, ParamList):-
    current_predicate(PredName/Arity),
    append([PredName], ParamList, PredList), 
    GlobalArity is Arity + 1,
    length(PredList, GlobalArity),
    Predicate =.. PredList,
    Predicate.

Запрос 1:

filter_predicate(PredName, Arity, [agora, X]).

Вывод

Arity = 2
PredName = director
X = 'Alejandro Amenabar' ? 

Запрос 2:

filter_predicate(PredName, Arity, [X, 'Alejandro Amenabar']).

Вывод

Arity = 2
PredName = director
X = agora ? 
person titusfx    schedule 02.10.2015
comment
@CapelliC, я не мог использовать пункт / 2, я получаю ошибку разрешения. Так что мое решение без него. Для вашего объяснения это будет медленнее, но, по крайней мере, легче читать. ;) Спасибо - person titusfx; 02.10.2015

Использование чтения строк в списки с прологом

Все ваши предикаты находятся в файле my_file.pl.

например my_file.pl содержит:

movie(agora).
director(agora, 'Alejandro Amenabar').
duration(agora, '2h').

Вы можете использовать:

getLines(File,L):-
 setup_call_cleanup(
 open(File, read, In),
 readData(In, L),
 close(In)
 ).

readData(In, L):-
  read_term(In, H, []),
  (   H == end_of_file
  ->  L = []
  ;   L = [H|T],
      readData(In,T)
  ).


pred_arg_file(Pred,Argue,File):-
  getLines(File,L),
  member(M,L),
  M=..List,
  member(Argue,List),
  List=[Pred|_].

Затем вы можете запросить:

 ?-pred_arg_file(Pred,agora,'my_file.pl').
 Pred = movie ;
 Pred = director ;
 Pred = duration ;
 false

or

?- findall(Pred,pred_arg_file(Pred,agora,'my_file.pl'),Preds).
Preds = [movie,director,duration].

Если вы хотите вернуть свойства, верните весь список, а не только заголовок.

pred_arg_file(List,Argue,File):-
  getLines(File,L),
  member(M,L),
  M=..List,
  member(Argue,List).
person user27815    schedule 30.09.2015
comment
Это может быть правильно, но это очень плохая идея с самого начала. OP, похоже, не может понять, как должны выглядеть его данные и как их запрашивать. - person ; 30.09.2015
comment
Я подумал, что было бы полезно, если бы у вас был большой файл, и вы не знали, какие предикаты были определены. Как бы вы вернули список предикатов. Я думал, что что-то вроде listing/0 будет работать, но он просто выводит на консоль и не возвращает список. - person user27815; 30.09.2015
comment
Если в файле правильный пролог, то все же лучше проконсультироваться с ним. Вы можете легко перечислить все предикаты, используя current_predicate/1, например. если это был файл модуля (как здесь) - person ; 30.09.2015
comment
current_predicate/1 возвращает много вещей, которых нет в файле? Например, «prolog_event_hook/1». Значит, нужно их фильтровать? Если файл не является модулем, вы не сможете сделать его модулем, не зная всех предикатов в нем. Чтобы вы могли поместить их в начало файла. - person user27815; 30.09.2015
comment
Вы можете обернуть его в модуль, не изменяя исходный файл. Однако все это совершенно не относится к делу: то, что пытается сделать OP, почти наверняка не нужно. - person ; 30.09.2015
comment
@user27815 user27815 это решение, я тоже думал, что оно не выглядит декларативным. Я хочу быть декларативным. - person titusfx; 01.10.2015

Насколько я понимаю, вы должны изменить представление данных, чтобы вы могли запрашивать отношения. Как указывалось в других ответах, поэтому используйте тройки, вы можете легко написать код, чтобы изменить все ваши отношения в эту форму как единое целое. Затем вам нужно решить, как лучше всего хранить лайки и антипатии. Это повлияет на то, как работает отрицание. В этом примере:

relation(starwars,is,movie).
relation(lucas, directs,starwars).
relation(agora, is,movie).
relation('Alejandro Amenabar', directs, agora).
relation(agora, duration, '2h').

like(ma,'Alejandro Amenabar').
like(ma,movie).
like(ma,'2h').

ma_does_not_want_to_go(Film):-
  relation(Film,is,movie),
  relation(Film,_,Test), \+like(ma,Test).
ma_does_not_want_to_go(Film):-
  relation(Film,is,movie),
  relation(Test,_,Film), \+like(ma,Test).

ma_wants_to_go(Film):-
  relation(Film,is,movie),
  \+ma_does_not_want_to_go(Film).

sa_invites_ma(Film,true):-
  ma_wants_to_go(Film).

sa_invites_ma(Film,false):-
  ma_does_not_want_to_go(Film).
person user27815    schedule 01.10.2015
comment
Вы могли бы сделать это лучше с помощью dif/2. - person user27815; 01.10.2015

Черновик решения, использующего Logtalk с GNU Prolog в качестве внутреннего компилятора:

% a movie protocol
:- protocol(movie).

    :- public([
        director/1,
        duration/1,
        genre/1
    ]).

:- end_protocol.


% a real movie
:- object('Agora',
    implements(movie)).

    director('Alejandro Amenabar').
    duration(120).
    genre(drama).

:- end_object.


% another real movie
:- object('The Terminator',
    implements(movie)).

    director('James Cameron').
    duration(112).
    genre(syfy).

:- end_object.


% a prototype person
:- object(person).

    :- public([
        likes_director/1,
        likes_genre/1
    ]).

    :- public(likes/1).
    likes(Movie) :-
        conforms_to_protocol(Movie, movie),
        (   Movie::genre(Genre),
            ::likes_genre(Genre) ->
            true
        ;   Movie::director(Director),
            ::likes_director(Director) ->
            true
        ;   fail
        ).

:- end_object.


% a real person
:- object(mauricio,
    extends(person)).

    likes_director('Ridlye Scott').

    likes_genre(drama).
    likes_genre(syfy).

:- end_object.

Некоторые примеры запросов:

$ gplgt
...

| ?- {movies}.
...

(5 ms) yes
| ?- mauricio::likes('Agora').

true ? 

yes
| ?- mauricio::likes(Movie).  

Movie = 'Agora' ? ;

Movie = 'The Terminator' ? ;

no

| ?- 'The Terminator'::director(Director).

Director = 'James Cameron'

yes

Код можно улучшить несколькими способами, но этого должно быть достаточно, чтобы дать вам четкое представление о том, как оценить это решение.

person Paulo Moura    schedule 01.10.2015

Если я правильно понял ваш вопрос, то предлагаю следующее:

Что, если вы измените свою схему или, следуя этой идее, вы можете создать метод, который имитирует то же самое.

class(movie, agora).
property(director, agora, 'Alejandro Amenabar').
property(duration, agora, '2h').

Если вам нужны типы агор, запрос будет таким:

class(Type, agora)

Если вам нужны все свойства агоры, это будет:

property( PropertyName, agora, Value).
person augu    schedule 01.10.2015
comment
Это именно то, что я хочу, но я не хочу писать свойство (NameProperty, Object, Value) для каждого объекта, который я хочу использовать, или для каждого объекта, чтобы получить все его свойства. - person titusfx; 01.10.2015
comment
@Mauricio Вы до сих пор не объяснили свой вариант использования в своем вопросе. У меня есть подозрение, что если вы приложите усилия, чтобы правильно определить свою проблему, вы найдете прямое ее решение. - person ; 01.10.2015
comment
@Борис, спасибо. Я просто редактирую свой вопрос. Я все еще застрял, я новичок в прологе:/ - person titusfx; 01.10.2015