【问题标题】:How to express a Total Order Relation in Prolog?Prolog中如何表达全序关系?
【发布时间】:2011-10-18 03:56:38
【问题描述】:

在 Prolog 中表达全序关系的最佳方式是什么?

例如,假设我有一组事实

person(tim)
person(ana)
person(jack)
...

关于一个人的财富,我想表达以下事实:对于每两个人 X 和 Y,如果不是 (X==Y),则要么 X 比 Y 富有,要么 Y 比 X 富有。

所以我的问题是richer 子句应该能够实例化它的变量,并确保richer(X, Y) 和richer(Y, X) 永远不会同时出现。

这是一个更好的例子,可以理解我的意思:

person(tim).
person(john).
happier(tim, john).

hates(X, Y) :- person(X), person(Y), richer(Y, X).
hates(X, Y) :- person(X), person(Y), richer(X, Y), happier(Y, X).

现在查询 hats(john, tim) 的答案应该返回 true,因为如果 richer 满足上述属性,那么这两个 hats 子句之一必须为 true。在基于分辨率的推理引擎中,我可以断言事实 (richer(X, Y) V richer(Y, X)) 并且谓词 hats(john, tim) 可以被证明是正确的。 我不希望能够以相同的方式在 Prolog 中以相同的方式表达这一点。但是,我怎样才能实现这个条件,以便给定的例子可以工作?

还要注意,我不知道谁更富有:蒂姆或约翰。我刚才说一个比另一个更富有。

谢谢。

【问题讨论】:

    标签: prolog relationship


    【解决方案1】:

    你不能在纯 Prolog 中写一个谓词应该是一个全序:这将需要更高阶的逻辑,因为你想声明一个关于谓词的属性。

    这是一个谓词,用于检查关系是否是有限集上的全序:

    is_total_order(Foo,Set):-
        forall(
               (member(X,Set),
            member(Y,Set)),
               (
            XY =.. [Foo,X,Y],
            YX =.. [Foo,Y,X],
            (call(XY);call(YX)),                %checking if the relationship is total
            \+ (call(XY),call(YX), X\=Y)        %checking if it's an order
               )
              ).
    

    运算符 =../2(univ 运算符)从列表(即:X =.. [foo,4,2].-> X = foo(4,2))和谓词调用创建谓词/1 调用另一个谓词。 如您所见,我们使用对其他谓词进行操作的元谓词。

    对于无限集的总顺序,事情变得更加复杂,因为我们无法像以前那样检查每一对。我什至不认为它可以写出来,因为证明一段关系是一个全序并不是一件小事。

    不过,这并没有声明谓词是全序;它只是检查是否存在。

    【讨论】:

    • 感谢您的回答。但是,这只能用作一致性检查,以验证我的程序中的事实并不矛盾。我希望更富有的人具有生成能力。我已经更新了我的示例以反映这一点。
    • 你可以这样:讨厌(X,Y):-人(X),人(Y),(更丰富(Y,X);更快乐(Y,X))。但这不是你想要的。另一个想法是首先创建一个您不知道的事实列表(模拟一个开放世界),然后尝试每种组合并仅在所有情况下结果为真时才返回真。这应该对调用总顺序 rel 的每个谓词进行。我不建议它 xD 也许你应该使用本体/定理证明器? ://
    【解决方案2】:

    所以我相信你的问题是代表这三个人之间关系的最佳方式。如果您实际上并不关心他们的财富#,只关心他们的相对顺序,您可以添加这样的谓词 -

    is_richer(tim, anna).
    is_richer(anna, jack).
    

    然后是一个谓词来查找所有 X 比 - 更富有的人

    richer(X, Z) :-
       is_richer(X, Z).
    richer(X, Z) :-
       is_richer(X, Y),
       richer(Y, Z).
    

    如果您的 is_richer 谓词包含循环(在此示例中,如果您添加了 is_richer(jack, ti​​m)),这可能会爆炸。您需要跟踪您在此树中访问过的位置。

    更丰富的示例是:

    ?- richer(X, Y).
    X=tim
    Y=anna ;
    X=anna
    Y=jack ;
    X=tim
    y=jack ;
    no
    

    【讨论】:

    • 但我不知道安娜是否比杰克富有。我已经更新了我的示例以反映这一点。
    猜你喜欢
    • 1970-01-01
    • 2013-08-21
    • 2012-03-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-19
    • 1970-01-01
    相关资源
    最近更新 更多