2016-11-30 3 views
0

Я создаю программу, которая должна разрешать поиск по графику, но функция, которая должна возвращать список узлов-преемников, терпит неудачу, когда вызов findall/3 оценивается как false. Когда я пытаюсь найти функцию findall самостоятельно вне функции find_successors, она работает отлично, но по какой-то причине внутри функции find_successors она просто считывает false. Пройдя через графический отладчик, я даже вижу, как он находит все решения. Вот код:findall/3 неверно оценивает значение false

find_successors(Start, Out) :- 
    entity(Start), 
    (findall(X, is_a(Start, X), O), append([], O, OL1); OL1 = []), 
    (findall(X, is_a(X, Start), O), OL2 = O; OL2 = []), 

    (findall(X, has(Start, X), O), append([], O, OL3); OL3 = []), 
    (findall(X, has(X, Start), O), append([], O, OL4); OL4 = []), 

    (findall(X, able_to(Start, X), O), append([], O, OL5); OL5 =[]), 
    (findall(X, able_to(X, Start), O), append([], O, OL6); OL6 = []), 

    (findall(X, used_to(Start, X), O), append([], O, OL7); OL7 = []), 
    (findall(X, used_to(X, Start), O), append([], O, OL8); OL8 = []), 

    append([OL1, OL2, OL3, OL4, OL5, OL6, OL7, OL8], Out). 

entity(wings). 
entity(fly). 
entity(bird). 
entity(legs). 
entity(feathers). 
entity('body covering'). 
entity(animal). 
entity(dog). 
entity(fur). 
entity(aves). 
entity(reptile). 
entity(snake). 
entity(scales). 

f_is_a(bird, aves). 
f_is_a(bird, animal). 
f_is_a(snake, reptile). 
f_is_a(snake, animal). 
f_is_a(dog, mammal). 
f_is_a(dog, animal). 
f_is_a(feathers, 'body covering'). 
f_is_a(fur, 'body covering'). 
f_is_a(mammal, animal). 
f_is_a(reptile, animal). 
f_is_a(aves, animal). 
is_a(X, H) :- !, f_is_a(X, H). 
is_a(X, H) :- !, \+f_is_a(X, P), H = X. 
is_a(X, H) :- !, is_a(X, P), is_a(P, H). 

f_has(bird, wings). 
f_has(bird, feathers). 
f_has(bird, legs). 
f_has(aves, wings). 
f_has(aves, feathers). 
f_has(aves, legs). 
f_has(dog, legs). 
f_has(dog, fur). 
f_has(mammal, legs). 
f_has(mammal, fur). 
f_has(snake, scales). 
f_has(reptile, scales). 
has(X, H) :- !, f_has(X, H). 
has(X, H) :- !, \+f_has(X, P), H = X. 
has(X, H) :- !, has(X, P), has(P, H). 

used_to(wings, fly). 
used_to(legs, walk). 

able_to(bird, fly). 
able_to(bird, walk). 
able_to(dog, walk). 
able_to(X, Y) :- used_to(X1, Y), has(X, X1). 

ответ

2

Вы продолжать пытаться повторно использовать ту же переменную, но как только переменная связана, вы не можете использовать его снова. Итак, все это:

 here    here 
     |     | 
     v     v 
(findall(X, is_a(Start, X), O), append([], O, OL1); OL1 = []), 
(findall(X, is_a(X, Start), O), OL2 = O; OL2 = []), 

(findall(X, has(Start, X), O), append([], O, OL3); OL3 = []), 
(findall(X, has(X, Start), O), append([], O, OL4); OL4 = []), 

(findall(X, able_to(Start, X), O), append([], O, OL5); OL5 =[]), 
(findall(X, able_to(X, Start), O), append([], O, OL6); OL6 = []), 

(findall(X, used_to(Start, X), O), append([], O, OL7); OL7 = []), 
(findall(X, used_to(X, Start), O), append([], O, OL8); OL8 = []), 

И каждая из этих линий очень, очень странная. Мне нужно сломать его, чтобы на самом деле выяснить, что происходит. Принимая только один из них:

( findall(X, used_to(Start, X), O), 
    append([], O, OL7) 
; OL7 = [] 
) 

(это, кстати, как вы должны попытаться написать дизъюнкции, в противном случае они легко неверно истолкован)

append([], A, B) точно такой же, как A = B.

Затем findall/3 всегда удается, даже если нет решений; он просто дает вам пустой список!

?- findall(X, between(2, 1, X), Xs). 
Xs = []. 

Так что все это совершенно не нужно, вы можете точно так же выбросить все, кроме вызова findall/3.

Примечание на стороне: дизъюнкция, которую вы используете, не делает то, что вы думаете. Вот небольшой пример:

?- (A = 1 ; A = 2). 

Как вы думаете, что происходит?

+0

В обычном случае это самые глупые ошибки, за которые я застрял достаточно долго, чтобы смутить себя в стеке над потоком ... Но я смущен вашей запиской ... После запуска этого примера он дал мне точно Ответ, который я ожидал, это 'A = 1; A = 2' – bendl

0

Вы должны позвонить нам по телефону find_successors(Start, Out) и сообщить ожидаемые значения.

Без этого трудно сказать, где ваш код неправильный, но ... какой-то конкретный пункт ...

(1) append/3 concatenate объединяет третий аргумент со списком, который объединяет элементы из первого и второго списков; так

append([], O, OL1) 

с первым аргументом без элементов в нем, унифицировать O с OL1 так неполезным; Вы можете написать все строки в виде

(findall(X, is_a(Start, X), O), append([], O, OL1); OL1 = []), 

в

(findall(X, is_a(Start, X), OL1) ; OL1 = []), 

(2) findall/3 возвращение справедливо также, когда унифицировать третий аргумент с пустым списком (если не найти значение), так Я не понимаю, почему вы пишете

(findall(X, is_a(Start, X), OL1) ; OL1 = []), 

, когда вторая часть (OL1 = []) никогда не выполняется (если я не ошибаюсь), и когда OL1 унифицирована с [], когда findall/3 ничего не нашли; Я думаю, вы можете просто написать

findall(X, is_a(Start, X), OL1), 

(3) Я знаю только append с тремя аргументами; так что я не понимаю смысл

append([OL1, OL2, OL3, OL4, OL5, OL6, OL7, OL8], Out) 

Ваше намерение было написать

append([], [OL1, OL2, OL3, OL4, OL5, OL6, OL7, OL8], Out) 

?

В этом случае, принимая в счете (1) и (2), вы можете написать find_successors/2 просто как

find_successors(Start, [OL1, OL2, OL3, OL4, OL5, OL6, OL7, OL8]) :- 
    entity(Start), 
    findall(X, is_a(Start, X), OL1), 
    findall(X, is_a(X, Start), OL2), 
    findall(X, has(Start, X), OL3), 
    findall(X, has(X, Start), OL4), 
    findall(X, able_to(Start, X), OL5), 
    findall(X, able_to(X, Start), OL6), 
    findall(X, used_to(Start, X), OL7), 
    findall(X, used_to(X, Start), OL8). 

(4) Я не люблю сокращений (!), так что, может быть, я ошибаюсь, но ... почему вы положили ! в качестве первого элемента в is_a/2?

is_a(X, H) :- !, f_is_a(X, H). 
is_a(X, H) :- !, \+f_is_a(X, P), H = X. 
is_a(X, H) :- !, is_a(X, P), is_a(P, H). 

Если я не ошибаюсь, огранка в первом пункте (!, f_is_a(X, H)) отключить второй и третий пункт так, если f_is_a(X, H) неудачно, второй и третий пункты никогда не уточнена.

Вы уверены, что ваши намерения не

is_a(X, H) :- f_is_a(X, H), !. 
is_a(X, H) :- \+f_is_a(X, P), H = X, !. 
is_a(X, H) :- is_a(X, P), is_a(P, H), !. 

или лучше

is_a(X, H) :- f_is_a(X, H), !. 
is_a(X, X) :- \+f_is_a(X, _), !. 
is_a(X, H) :- is_a(X, P), is_a(P, H), !. 

?

Или не разрезать вообще?

(5) проблема с обрезкой с has/3; Я подозреваю, что

has(X, H) :- !, f_has(X, H). 
has(X, H) :- !, \+f_has(X, P), H = X. 
has(X, H) :- !, has(X, P), has(P, H). 

неправильно, и что ваше намерение было

has(X, H) :- f_has(X, H), !. 
has(X, H) :- \+f_has(X, P), H = X, !. 
has(X, H) :- has(X, P), has(P, H), !. 

или лучше

has(X, H) :- f_has(X, H), !. 
has(X, X) :- \+f_has(X, _), !. 
has(X, H) :- has(X, P), has(P, H), !. 

Или не вырезано вообще?

 Смежные вопросы

  • Нет связанных вопросов^_^