如何return Prolog中的推荐列表?
How to return a list of recommendations in Prolog?
对于我的作业,我应该列出 20 种潜在的宠物,然后定义关于每只宠物的事实。然后我需要问潜在的宠物主人五个问题,这将有助于决定哪些宠物是好的推荐。我正在尝试 return 基于用户输入的宠物列表,但它只是 return 每次都是正确的,实际上并没有列出推荐的宠物。不知道我要去哪里错了。我只会在我的代码示例中包括一些宠物,所以它不会太长。
pet_advisor.pl:
pet(cat).
pet(chameleon).
pet(chicken).
pet(chinchilla).
pet(cow).
size(cat, small).
sleeps(cat, night).
stays(cat, indoor).
stays(cat, outdoor).
class(cat, mammal).
live(cat, 12)
size(chameleon, small).
sleeps(chameleon, night).
stays(chameleon, indoor).
class(chameleon, reptile).
live(chameleon,5).
size(chicken, small).
sleeps(chicken, night).
stays(chicken, outdoor).
class(chicken, bird).
live(chicken,10).
size(chinchilla, small).
sleeps(chinchilla, day).
stays(chinchilla, indoor).
class(chinchilla, mammal).
live(chinchilla,15).
size(cow, large).
sleeps(cow, night).
stays(cow, outdoor).
class(cow, mammal).
live(cow,22).
pet_size_ok(X) :- pet_size(X), size(Y, X).
sleep_type_ok(X) :- sleep_type(X), sleeps(Y, X).
pet_location_ok(X) :- pet_location(X), stays(Y, X).
kind_ok(X) :- kind(X), class(Y, X).
life_ok(X) :- life(X), live(Y, Z), Z =< X.
which_pet(X) :- pet_size_ok(X), sleep_type_ok(X), pet_location_ok(X), kind_ok(X), life_ok(X).
recommend :- write('Do you want a small, medium, or large sized pet? '), read(Size), nl, assert(pet_size(Size)),
write('Do you want a pet that sleeps during the day or night? '), read(Sleep), nl, assert(sleep_type(Sleep)),
write('Do you want an indoor or outdoor pet? '), read(Place), nl, assert(pet_location(Place)),
write('Do you want a reptile, mammal, bird, or a fish? '), read(Type), nl, assert(kind(Type)),
write('How long do you want your pet to live (years)? '), read(Age), nl, assert(life(Age)),
findall(Pets, which_pet(Pets), Suggestions),
write('I would recommend these pets for you: '), nl, writelist(Suggestions),
retract(pet_size(Size)), retract(sleep_type(Sleep)),
retract(pet_location(Place)),
retract(kind(Type)), retract(life(Age)).
writelist([]).
writelist([H|T]) :- writeonce(H,T), writelist(T).
writeonce(H,T) :- member(H,T).
writeonce(H,T) :- not(member(H,T)), write(H), nl.
所以如果我要回答这样的问题:
小的
夜晚
室内的
哺乳动物
15
它应该 return 包含 [cat, chinchilla] 的列表,但 return 全部都是真实的。
您的代码存在几个问题。首先,对于大多数 Prolog 系统和 Prolog 标准,必须声明不连续谓词。在文件开头添加以下指令:
:- discontiguous([
size/2, sleeps/2, stays/2, class/2, live/2
]).
接下来,您在查询推荐时无需使用动态谓词以及断言和撤回事实:
which_pet(Size, Sleep, Place, Type, Age, Pet) :-
size(Pet, Size),
sleeps(Pet, Sleep),
stays(Pet, Place),
class(Pet, Type),
live(Pet, Age0), Age0 =< Age.
recommend :-
write('Do you want a small, medium, or large sized pet? '), read(Size), nl,
write('Do you want a pet that sleeps during the day or night? '), read(Sleep),
write('Do you want an indoor or outdoor pet? '), read(Place), nl,
write('Do you want a reptile, mammal, bird, or a fish? '), read(Type), nl,
write('How long do you want your pet to live (years)? '), read(Age), nl,
findall(Pet, which_pet(Size,Sleep,Place,Type,Age,Pet), Suggestions),
write('I would recommend these pets for you: '), nl, writelist(Suggestions).
这不是一个理想的重写,因为它的扩展性很差,但比使用动态谓词要好得多。
作为结束语,您用于打印结果的代码执行两个任务,最好将它们分开:(1) 过滤重复项和 (2) 打印唯一结果。我建议您将这些任务分开。可以过滤结果,例如通过使用 setof/2
而不是 findall/3
或在 findall/3
调用构造的列表上调用 sort/2
。我把重写留给你。还使用标准否定控制结构 \+/1
,而不是 legacy/deprecated not/1
谓词。
调用示例:
| ?- recommend.
Do you want a small, medium, or large sized pet? small.
Do you want a pet that sleeps during the day or night? night.
Do you want an indoor or outdoor pet? outdoor.
Do you want a reptile, mammal, bird, or a fish? bird.
How long do you want your pet to live (years)? 20.
I would recommend these pets for you:
chicken
yes
对于我的作业,我应该列出 20 种潜在的宠物,然后定义关于每只宠物的事实。然后我需要问潜在的宠物主人五个问题,这将有助于决定哪些宠物是好的推荐。我正在尝试 return 基于用户输入的宠物列表,但它只是 return 每次都是正确的,实际上并没有列出推荐的宠物。不知道我要去哪里错了。我只会在我的代码示例中包括一些宠物,所以它不会太长。
pet_advisor.pl:
pet(cat).
pet(chameleon).
pet(chicken).
pet(chinchilla).
pet(cow).
size(cat, small).
sleeps(cat, night).
stays(cat, indoor).
stays(cat, outdoor).
class(cat, mammal).
live(cat, 12)
size(chameleon, small).
sleeps(chameleon, night).
stays(chameleon, indoor).
class(chameleon, reptile).
live(chameleon,5).
size(chicken, small).
sleeps(chicken, night).
stays(chicken, outdoor).
class(chicken, bird).
live(chicken,10).
size(chinchilla, small).
sleeps(chinchilla, day).
stays(chinchilla, indoor).
class(chinchilla, mammal).
live(chinchilla,15).
size(cow, large).
sleeps(cow, night).
stays(cow, outdoor).
class(cow, mammal).
live(cow,22).
pet_size_ok(X) :- pet_size(X), size(Y, X).
sleep_type_ok(X) :- sleep_type(X), sleeps(Y, X).
pet_location_ok(X) :- pet_location(X), stays(Y, X).
kind_ok(X) :- kind(X), class(Y, X).
life_ok(X) :- life(X), live(Y, Z), Z =< X.
which_pet(X) :- pet_size_ok(X), sleep_type_ok(X), pet_location_ok(X), kind_ok(X), life_ok(X).
recommend :- write('Do you want a small, medium, or large sized pet? '), read(Size), nl, assert(pet_size(Size)),
write('Do you want a pet that sleeps during the day or night? '), read(Sleep), nl, assert(sleep_type(Sleep)),
write('Do you want an indoor or outdoor pet? '), read(Place), nl, assert(pet_location(Place)),
write('Do you want a reptile, mammal, bird, or a fish? '), read(Type), nl, assert(kind(Type)),
write('How long do you want your pet to live (years)? '), read(Age), nl, assert(life(Age)),
findall(Pets, which_pet(Pets), Suggestions),
write('I would recommend these pets for you: '), nl, writelist(Suggestions),
retract(pet_size(Size)), retract(sleep_type(Sleep)),
retract(pet_location(Place)),
retract(kind(Type)), retract(life(Age)).
writelist([]).
writelist([H|T]) :- writeonce(H,T), writelist(T).
writeonce(H,T) :- member(H,T).
writeonce(H,T) :- not(member(H,T)), write(H), nl.
所以如果我要回答这样的问题: 小的 夜晚 室内的 哺乳动物 15
它应该 return 包含 [cat, chinchilla] 的列表,但 return 全部都是真实的。
您的代码存在几个问题。首先,对于大多数 Prolog 系统和 Prolog 标准,必须声明不连续谓词。在文件开头添加以下指令:
:- discontiguous([
size/2, sleeps/2, stays/2, class/2, live/2
]).
接下来,您在查询推荐时无需使用动态谓词以及断言和撤回事实:
which_pet(Size, Sleep, Place, Type, Age, Pet) :-
size(Pet, Size),
sleeps(Pet, Sleep),
stays(Pet, Place),
class(Pet, Type),
live(Pet, Age0), Age0 =< Age.
recommend :-
write('Do you want a small, medium, or large sized pet? '), read(Size), nl,
write('Do you want a pet that sleeps during the day or night? '), read(Sleep),
write('Do you want an indoor or outdoor pet? '), read(Place), nl,
write('Do you want a reptile, mammal, bird, or a fish? '), read(Type), nl,
write('How long do you want your pet to live (years)? '), read(Age), nl,
findall(Pet, which_pet(Size,Sleep,Place,Type,Age,Pet), Suggestions),
write('I would recommend these pets for you: '), nl, writelist(Suggestions).
这不是一个理想的重写,因为它的扩展性很差,但比使用动态谓词要好得多。
作为结束语,您用于打印结果的代码执行两个任务,最好将它们分开:(1) 过滤重复项和 (2) 打印唯一结果。我建议您将这些任务分开。可以过滤结果,例如通过使用 setof/2
而不是 findall/3
或在 findall/3
调用构造的列表上调用 sort/2
。我把重写留给你。还使用标准否定控制结构 \+/1
,而不是 legacy/deprecated not/1
谓词。
调用示例:
| ?- recommend.
Do you want a small, medium, or large sized pet? small.
Do you want a pet that sleeps during the day or night? night.
Do you want an indoor or outdoor pet? outdoor.
Do you want a reptile, mammal, bird, or a fish? bird.
How long do you want your pet to live (years)? 20.
I would recommend these pets for you:
chicken
yes