如何在Prolog中制作事实(任何)?

时间:2014-06-01 09:08:46

标签: 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)).

我正在尝试制定规则,要求用户输入树的特定参数,然后寻找合适的参数。像这样。

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.

(抱歉我的英文:))

===== UPDATE =====

我最终得到了这个代码,感谢你:) 还会添加对用户输入的检查。

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 .

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

2 个答案:

答案 0 :(得分:0)

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

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

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

答案 1 :(得分:0)

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

% wood(Wood, Leaves, Softness, Color, OnTouch).
wood(oak, leafed, hard, gray_brown, smalltexture).

然后,您可以修改what_wood/1谓词,以便当用户输入属性的原子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_attribute/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_attribute/2以避免在测试时创建选择点。您还可以重写此谓词,以利用已有的有效属性值的事实:

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