LINUX.ORG.RU

[пролог,не пойму] рекурсия


0

1

Категорически вас приветствую.

Есть 2 базы. Одна имеет вид:

doctorate(258,"Dio Lewis Holl","Ph.D.","The University of Chicago",1925,"UnitedStates","Dissertation","Viscous Fluid Motion in Eccentric Cylinders").

Другая:

advisor(10,258).
advisor(10,38464).

Другими словами: вторая база содержит 2 поля с ID. Первый ID содержитсжя 2 первой базе(см. пример). Первая база содержит и другую информацию: имена, названия университетов и тд. Мне нужно пройтись по базе задав или ID или имя и вывести из базы нр. 1, имя.

Если я работаю только со второй базой, то проблем с рекурсией нет. Например я делаю так:

ancestor(X,Y):-advisor(X,Y).
ancestor(X,Y):- advisor(X,Z),ancestor(Z,Y).
ancestor(10,Y).

И получаю 2 результата:

?- ancestor(10,Y).
Y = 258 ;
Y = 38464 ;

Если я пытаюсь определить имена к этим ID(например 258,38464) пролог возвращает только один результат.

ancestor(X,Y):-advisor(X,Y).
ancestor(X,Y,NAME):- doctorate(Y,NAME,_,_,_,_,_,_),ancestor(X,Y).
ancestor(10,Y,NAME), writef("%s\n",[NAME]).

Получается:

?- ancestor(10,Y,NAME), writef("%s\n",[NAME]).
Dio Lewis Holl
Y = 258,
NAME = [68, 105, 111, 32, 76, 101, 119, 105, 115|...] ;

Тоесть есть имя только для ID 258. И ещё не нужная строка NAME.

Подскажите как сделать правильно, а также как избавиться от строки NAME....

Спасибо!


> пролог возвращает только один результат.

Что вполне естественно, ведь в отличие от первого примера результат берётся из первой базы, где всего 1 запись.

избавиться от строки NAME

Что имеется ввиду под избавиться ?

Kirakishou
()

В любом случае, вот вам 2 варианта:

doctorate(1,"David","Ph.D.","The University of Chicago",1925,"UnitedStates","Dissertation","Viscous Fluid Motion in Eccentric Cylinders"). 
doctorate(10,"Alan","Ph.D.","The University of Chicago",1925,"UnitedStates","Dissertation","Viscous Fluid Motion in Eccentric Cylinders"). 
doctorate(258,"Dio Lewis Holl","Ph.D.","The University of Chicago",1925,"UnitedStates","Dissertation","Viscous Fluid Motion in Eccentric Cylinders").
doctorate(38464,"John","Ph.D.","The University of Chicago",1925,"UnitedStates","Dissertation","Viscous Fluid Motion in Eccentric Cylinders").

advisor(1,10).
advisor(10,258).
advisor(10,38464).

ancestor(X, Y):- advisor(X, Y).
ancestor(X, Y):- advisor(X, Z), ancestor(Z, Y).
ancestor(X, Y, NAME):- ancestor(X, Y), doctorate(Y, NAME, _,_,_,_,_,_).

print_doctorate(Id):-
  doctorate(Id, Name, _,_,_,_,_,_),
  string_to_atom(Name, N),
  write(N), nl.

:- ancestor(1, Y), print_doctorate(Y).
:- ancestor(1, _, NAME), string_to_atom(NAME, N), writef("%s\n", N).
Kirakishou
()
Ответ на: комментарий от Kirakishou

Спасибо за разяснения, ваш вариант с print_doctorate(Id) печатает имя так как мне нужно. Но к сожалению я так и не понял как мне извлекать информацию рекурсивно из 2 баз.

Вот если я в вашем примере вызываю:

ancestor(10, Y).

Получается(как и в моём первом):

Y=258;
Y=34464;

Мне хотелось бы:


Y = 258
NAME = имя_1;
Y = 34464
NAME = имя_2;
....

когда я пытаюсь вызвать предикат из вашего решения ?- ancestor(10,Y,NAME).

получаю:

Y = 258,
NAME = [68, 105, 111, 32, 76, 101, 119, 105, 115|...] .
false.

Уже совсем запутался. -.-

ciiccii
() автор топика
Ответ на: комментарий от ciiccii

Так, давайте по порядку. Во первых, интерпретатор всегда печатает _все_ переменные в запросе (за исключением ситуации с несколькими встроенными предикатами, но не будем сейчас на них отвлекаться). Это во первых, во вторых, печатает он их так, как умеет, например, строки он печатает как массив кодов символов, поэтому надо добавлять string_to_atom. В третьих, информация должна вытягиваться рекурсивно, по крайней мере, у меня всё работает.

Как я понимаю, вам нужен такой вариант:

doctorate(1,"David","Ph.D.","The University of Chicago",1925,"UnitedStates","Dissertation","Viscous Fluid Motion in Eccentric Cylinders"). 
doctorate(10,"Alan","Ph.D.","The University of Chicago",1925,"UnitedStates","Dissertation","Viscous Fluid Motion in Eccentric Cylinders"). 
doctorate(258,"Dio Lewis Holl","Ph.D.","The University of Chicago",1925,"UnitedStates","Dissertation","Viscous Fluid Motion in Eccentric Cylinders").
doctorate(38464,"John","Ph.D.","The University of Chicago",1925,"UnitedStates","Dissertation","Viscous Fluid Motion in Eccentric Cylinders").

advisor(1,10).
advisor(10,258).
advisor(10,38464).

ancestor(X, Y):- advisor(X, Y).
ancestor(X, Y):- advisor(X, Z), ancestor(Z, Y).
ancestor(X, Y, NAME):-
  ancestor(X, Y),
  doctorate(Y, N, _,_,_,_,_,_),
  string_to_atom(N, NAME).

Пример запроса:

?- ancestor(1, Y, NAME).
Y = 10,
NAME = 'Alan' ;
Y = 258,
NAME = 'Dio Lewis Holl' ;
Y = 38464,
NAME = 'John' ;
false.

Kirakishou
()
Ответ на: комментарий от Kirakishou

Извини, появился ещё один вопрос, помогите если есть время.

Задание тоже, но теперь нужно проводить поиск не по ID, а по имени. Я сделал так, но програма не работает.

getid(ID,NAME1):- doctorate(ID,NAME1,_,_,_,_,_,_).
ancestor(ID,Y):- advisor(ID,Y).
ancestor(ID, Y):- advisor(ID, Z), ancestor(Z, Y).
ancestor(ID,Y,NAME1,NAME):-
  getid(ID,NAME1),
  ancestor(ID,Y),
  doctorate(Y,N,_,_,_,_,_,_),
  string_to_atom(N, NAME).

Спасибо.

ciiccii
() автор топика
Ответ на: комментарий от ciiccii

Я сделал так, но програма не работает.

Вообще-то, она работает:

?- ancestor(_, Y, "David", N).
Y = 10,
N = 'Alan' ;
Y = 258,
N = 'Dio Lewis Holl' ;
Y = 38464,
N = 'John' ;
false.

Или вам нужно что-то другое ?

Kirakishou
()
Ответ на: комментарий от Kirakishou

Пожалуйста. Если что - обращайтесь, я Пролог люблю :)

Извиняюсь за оффтоп, но не подскажешь книги по прологу для нубов? Желательно на русском, но можно и на английском. С особенностями swi-prolog.

vurdalak ★★★★★
()
Ответ на: комментарий от vurdalak

С особенностями swi-prolog.

Таких нет. Так что стандартный книжный набор + мануалы swi.

dmsh
()
Ответ на: комментарий от Kirakishou

Похоже я вам буду обязан по гроб жизни :). У меня есть ещё один вопрос. Базы теже, задание проверить есть, ли кто-то, кто написал бы свою работу, раньше своего научного руководителя?

Поготовил пример, в котором точно должно выдать true/yes.

doctorate(8,"Carlos Alberto Berenstein","Ph.D.","New York University",1965,"UnitedStates","Dissertation","Convolution Operators and Related Quasianalytic Classes").
doctorate(9,"Carlos  Moreno","Ph.D.","New York University",1961"UnitedStates","Dissertation","Zeros of Exponential Polynomials and Diophantine Analysis").
doctorate(10,"John  Stevens","Ph.D.","New York University",1962,"UnitedStates","Dissertation","Multiplicity Varieties and Elimination Theory over a Polynomial Ring").


advisor(8,10).
advisor(9,10).
advisor(10,10).


И сам код. Если не трудно, объясните в каком месте я делаю ошибку?

child(ID,aID):-advisor(ID,aID).
child(ID,aID):-advisor(Z,aID),child(ID,Z).
getyearV(aID,YEARV):-doctorate(aID,_,_,_,YEARV,_,_,_).
getyear(ID,YEAR):-doctorate(ID,_,_,_,YEAR,_,_,_).
yesno(ID,aID,YEAR,YEARV,YY):-
  child(ID,aID),
  getyearV(aID,YEARV),
  getyear(ID,YEAR),
  doctorate(aID,_,_,_,YY,_,_,_),
  YEAR<YEARV.

ciiccii
() автор топика
Ответ на: комментарий от dmsh

хм, вот этот код работает на половину - т.е. он находит такие случаи если они есть, но продолжает выводить их бесконечно пока, не нажать ".". Если он ничего не находит, код входит в бесконечный цикл и висит в нём. Как оптимизировать его поведение? Спасибо!

Вот сам код:

['adv.facts'].
['doc.facts'].
[user].
child(Y,ID):-advisor(Y,ID).
child(Y,ID):-advisor(Z,ID),child(Y,Z).
getyear(ID,YEAR):-doctorate(ID,_,_,_,YEAR,_,_,_).
yesno(ID,Y,NAME,NAME1,YEAR,YEARV):-
  child(ID,ID),
  getyear(ID,YEARV),
  getyear(Y,YEAR),
  doctorate(Y,N,_,_,_,_,_,_),
  doctorate(ID,NN,_,_,_,_,_,_),
  string_to_atom(N,NAME),
  string_to_atom(NN,NAME1),
  YEAR<YEARV.
ciiccii
() автор топика
Ответ на: комментарий от ciiccii

Значит твоем графе есть циклы.

Открой уже книжку, это хрестоматийный пример.

dmsh
()
Ответ на: комментарий от vurdalak

Мне пока приходилось более-менее внимательно изучать лишь «Алгоритмы искусственного интеллекта на языке PROLOG» Братко. Для начинающих весьма неплохо (и на русском), правда мне не очень понравилось, как у него описан алгоритм унификации, на котором строится весь пролог. Но это не проблема - сам по себе алгоритм очень простой и о нём почитать можно и в других источниках, если то, что есть у Братко, вам не понравится.

Ещё хвалят Л. Стерлинг, Э. Шапиро: «Искусство программирования на языке Пролог», но при беглом взгляде сложилось впечатление, что для новичков это не совсем то, что им нужно.

Насчёт особенностей swi-prolog - фактически, никаких особенностей у него нет, по крайней мере таких, по которым стоило бы писать/читать отдельную книгу. Вообще, большинство релизаций пролога (за исключением, разве что, Visual Prolog) следуют стандарту, при этом добавляя лишь десяток-другой предикатов (например, freeze для ленивых вычислений; как правило, функции ввода вывода, т.к. в стандартном прологе с ними уж больно скудно), небольшое расширения языка для работы с модулями (в стандарте модулей нет), плюс пару каких нибудь ключей интерпретатору (например, указывающих выполнять «настоящую» унификацию, а не её упрощённый вариант без occurs check). Поэтому достаточно выучить сам пролог, а особенности конкретной реализации изучаются по документации к ней за пару дней.

Теперь, что есть у меня:

  • Клоксин, Меллиш: Программирование на языке Пролог
  • Richard O'Keefe: The Craft of Prolog
  • Covington, Nute, Vellino: Prolog Programming in Depth
  • Братко: Алгоритмы искусственного интеллекта на языке PROLOG
  • Стерлинг, Шапиро: Искусство программирования на языке Пролог
  • Малпас Дж.: Реляционный язык Пролог и его применение
  • Ещё парочка статей и публикаций, затрагивающий Пролог

Заинтересованные могут сообщить мне свой email.

Насчёт Братко, правда, есть один момент - свежее издание гуляет в сети лишь в отвратительном качестве. К счастью, первая часть книги по содержанию почти полностью совпадает с предыдущим изданием, которое имеется в нормальном качестве. Т.е., читаете обновлённое издание, есть что-то непонятно из-за плохого скана - сверяетесь со старым изданием. К тому моменту, когда вы доберётесь до второй части книги (её сверять уже не с чем), Пролог вы будете знать уже достаточно хорошо, чтобы неразборчивый скан не стал для вас помехой - всё и так будет понятно из контекста.

Kirakishou
()
Ответ на: комментарий от mclaudt

Пока лишь хобби, но в ближайшем будующем планирую попробовать написать что-нибудь практическое.

Kirakishou
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.