如何在Prolog中生成事实(any)?

如何在Prolog中生成事实(any)?,prolog,Prolog,我有一个数据库,它由树的列表和关于这些树的事实组成。例如: softness(soft). softness(hard). softness(veryhard). color(gray_brown). color(soft_red). color(light). color(dark). wood(oak, leafes(leafed), softness(hard), color(gray_brown), on_touch(smalltexture)). 我试图制定一个规则,要求用户输入

我有一个数据库,它由树的列表和关于这些树的事实组成。例如:

softness(soft).
softness(hard).
softness(veryhard).

color(gray_brown).
color(soft_red).
color(light).
color(dark).

wood(oak, leafes(leafed), softness(hard), color(gray_brown), on_touch(smalltexture)).
我试图制定一个规则,要求用户输入树的特定参数,然后寻找合适的参数。像这样

what_wood(A, B):-
    wood(A, B, _, _, _);
    wood(A, _, B, _, _);
    wood(A, _, _, B, _);
    wood(A, _, _, _, B);
    wood(A, B, _, _); %I have one tree with three parameters =/
    wood(A, _, B, _);
    wood(A, _, _, B).

what_wood(A) :-
    write('Leafes: '), read(X), what_wood(A, leafes(X)),
    write('Softness: '), read(Y), what_wood(A, softness(Y)),
    write('Color: '), read(Z), what_wood(A, color(Z)),
    write('On touch: '), read(Q), what_wood(A, on_touch(Q)).
所以我的问题是——如果用户想将参数指定为“any”,有没有这样的方法

leafes(leafed).
leafes(coniferous).
leafes(any):-
    leafes(X). %this one doesn't work. Prints false
    %leafes(leafed);leafes(coniferous). %Of course this doesn't work too.
(对不起我的英语:))

====更新=====

多亏了你,我最终得到了这段代码:) 还将为用户输入添加检查

wood(oak, leafed).
wood(oak, hard).
wood(oak, gray_brown).
wood(oak, smalltexture).

wood(beech, leafed).
wood(beech, hard).
wood(beech, soft_red).
wood(beech, largetexture).


wood(yew, leafed).
wood(yew, veryhard).
wood(yew, dark).

...

what_wood(A, B, C, D, E):-
wood(A, B), wood(A, C), wood(A, D), wood(A, E).
what_wood(A) :-
    write('Leafes: '), read(X), convert(X, Leaves),
    write('Softness: '), read(Y), convert(Y, Softness),
    write('Color: '), read(Z), convert(Z, Color),
    write('On touch: '), read(Q), convert(Q, OnTouch),
    what_wood(A, Leaves, Softness, Color, OnTouch).

convert(any, _) :-
    !.
convert(Attrib, Attrib).
此代码返回的答案与

A = oak ; 
A = oak ;
...
A = beech ;
A = beech .

但这是另一个与当前问题无关的故事。

Prolog是一种具有干净关系数据模型的语言。我会选择不同的模式,分离每个属性:比如

wood(oak, leafes(leafed)).
wood(oak, softness(hard)).
...

通过这种方式,您可以依赖于通常的关系模式来应用于您的“应用程序”。具体来说,Prolog使用查询作为过程…

假设wood属性的数量是固定的,在您的示例中,您可以使用以下事实定义谓词
wood/5

% wood(Wood, Leaves, Softness, Color, OnTouch).
wood(oak, leafed, hard, gray_brown, smalltexture).
然后,您可以修改
what_wood/1
谓词,这样当用户为属性输入atom
any
时,它在尝试匹配
wood/5
事实时使用匿名变量。比如:

what_wood(Wood) :-
    write('Leafes: '), read(Leafes0), convert(Leafes0, Leafes),
    write('Softness: '), read(Softness0), convert(Softness0, Softness),
    write('Color: '), read(Color), convert(Color0, Color),
    write('On touch: '), read(OnTouch), convert(OnTouch0, OnTouch),
    wood(Wood, Leaves, Softness, Color, OnTouch).

convert(any, _) :-
    !.
convert(Attribute, Attribute).
下一步是检查用户输入值的有效性,例如,如果无效,则重复该问题。例如,您可以定义一个
read_属性/2
谓词,该谓词将执行读取操作,并在用户输入有效值之前重复该谓词:

read_attribute(Attribute, Value) :-
    repeat,
        write('Value for '), write(Attribute), write(': '),
        read(Value),
    valid_attribute(Attribute, Value),
    !.

valid_attribute(leafes, leafed).
valid_attribute(leafes, coniferous).
valid_attribute(leafes, any).
...
这可以从几个方面加以改进。例如,通过在询问属性值时打印属性的可能值,以便用户知道哪些值被接受为有效值。谓词
valid\u属性/2
也可以重写,以避免在测试时创建选择点。您还可以重写此谓词,以利用已存在的有效属性值的事实:

valid_attribute(Attribute, Value) :-
    Test =.. [Attribute, Value],
    once(Test).

您可以查询
?-leaves(X)。
查询中出现的变量是存在量化的,即“是否存在某种“leaves”?”如果您对特定的答案不感兴趣,您也可以使用
\uu
i.o.
X
。我已经知道这一点。问题是:当用户提示“leaves(any)”时,prolog会给出“leaves(leaved);leaves(conicored)”。这并不是prolog的正确用法。当您查询
leaves(any)
时,您询问的是一个没有变量的事实
leaves(Any)
确实是查询它的正确方法。您的示例也是一个无限循环。它不显示“假”,而是无限循环,连续显示“真”结果。好吧,这是一个很好的观点!您的模式看起来更好。我将尝试更改我的数据库,看看是否可以完成我的任务。谢谢!这种转换以我想要的方式工作。另外,感谢您提供用户输入检查。真的帮了我很多忙。