【问题标题】:Prolog - if condition 1 AND condition 2 do xProlog - 如果条件 1 AND 条件 2 执行 x
【发布时间】:2015-09-26 22:51:05
【问题描述】:

我想在prolog中编写等效的伪函数:

function underhundred(X){

    if (X >= 0 && X <=100) return 1;
    else return 0;

}

我试过写这个,但它没有编译:

underhundred(X,L) :- L is (X => 0, X =< 100 -> L = 1; L = 0) . 

在谓词之间不使用序言的情况下,正确的写法是什么?

【问题讨论】:

    标签: prolog


    【解决方案1】:

    如果您确实想使用目标L=1L=0 并且X 是整数,请使用

    :- use_module(library(clpfd)).
    

    物化就像一个魅力!

    ?- X in 0..100 #<==> L.
    L in 0..1, X in 0..100#<==>L.
    

    如果X 被实例化怎么办?

    ?- X in 0..100 #<==> L, X=(-7).
    L = 0, X = -7.                    % out of bounds: -7 < 0       =< 100
    
    ?- X in 0..100 #<==> L, X=55.
    L = 1, X = 55.                    % within bounds:      0 =< 55 =< 100
    
    ?- X in 0..100 #<==> L, X=111.   
    L = 0, X = 111.                   % out of bounds:      0       =< 100 < 111
    

    【讨论】:

    • 你会如何回答这个问题来接受实数?
    • @user27815。如果您对浮点运算感兴趣...(is)/2 会这样做。或者您想要对浮点数或有理数进行约束求解?然后,考虑使用clpq 和/或clpr。如果您想要X in 0..100 #&lt;==&gt; L, X = 111 之类的东西,而不是整数,而是浮点数(或任意精度的有理数),请检查是否已经发布了符合您需求的问题。如果没有,请发布一个新问题。
    • 这个问题并没有指定该函数只适用于整数。所以我认为这可能是一个提供两者兼而有之的答案的好地方。
    • @user27815。我同意这个问题没有明确指定域。但是 OP 使用的所有数字都是整数。此外,OP 提到了 Prolog 谓词 between/3,它仅适用于整数。
    【解决方案2】:

    Prolog 查询成功或失败。如果成功,它将返回它所做的绑定。

    您可以使用 clpfd 将这个谓词编写为:

    :-use_module(library(clpfd)).
    
    under_hundred_clpfd(X):-
    X in 0..100.
    

    (您可能更喜欢 between_0_100? 之类的名称,如果您确实希望小于 100,那么您可以在 inf..99 中使用 X)。 一些查询:

    ?-under_hundred_clpfd(5).
    true.
    
    ?-under_hundred_clpfd(101).
    false.
    
    ?-under_hundred_clpfd(X).
    X in 0..100.
    

    传统的写法是:

     under_hundred(X):-
     X>=0,
     X=<100.
    

    但这种方式不适用于未实例化的变量。

    ?-under_hundred(X).
    ERROR: >/2: Arguments are not sufficiently instantiated
    

    所以就像你说的那样,你可能需要设置一个 between/3 或 length/2 目标才能获得解决方案或类似的构造。

    underhundred(X):-
      length(_,X),
      X>=0,
      X=<100.
    

    这不是一个很好的解决方案,因为在回溯时它会陷入无限循环。 between/3 表现更好,但你不想要它:)。

    【讨论】:

    • OP 想要“返回 1”或“返回 0”并指定 underhundred/2(不是 underhundred/1)。切换到 arity 2 并为另一种情况编写第二个子句怎么样?
    • 我只是想说明,实际上您可能不想返回 1 或零。由于目标的成功或失败传达了该信息..
    • 我明白了。如果您想使用谓词作为某些 if-then-else 的条件(例如 (-&gt;)/2(*-&gt;)/2if/3),逻辑上的可靠性很容易丢失,并且还有其他很好的代数属性!这对于 clpfd 约束更为严重,因为这些约束通常不是立即决定的,而是延迟并在稍后的某个时间执行(通常由labeling/2 触发)。上述控制结构可能全部在它们提交过早时破坏逻辑含义。但是,如果我们用一个额外的参数来具体化underhundred 的真实性,我们可以完全避免这些问题!
    • 我尽量不使用 if-then-else :)
    • 底线:if-then-else or negation or cut plus clpfd = havoc!错误的答案,没有任何警告标志! is/2 在这些情况下会引发实例化错误,而 clpfd 不会。当心!
    【解决方案3】:

    如果问题的重点是如何在 Prolog 中编写 if-then-else 构造,那么按照所提出的定义的合理答案是:

    underhundred(X,L) :-
       (  X >= 0, X =< 100  )
       -> L = 1
       ;  L = 0.
    

    这只有在X 被充分实例化后调用underhundred(X,L) 才有用。

    【讨论】:

    • 您所做的最后一次布局更改是有问题的。 cfarxiv.org/pdf/0911.2899
    • @repeat -- 我从那篇论文中的这个建议中获得灵感:“程序员不记得逗号和分号的相对优先级;a,b;c 表示 (a,b);c 但是这个事实并不明显。因此,建议使用布局和括号来指示优先级。省略外括号在这里很好,因为子句的整个主体只是一个 if-then-else 语句。
    猜你喜欢
    • 2010-10-14
    • 2020-02-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-12-15
    • 1970-01-01
    • 2015-09-25
    • 2018-09-14
    相关资源
    最近更新 更多