SWI Prolog if语句,它们是如何工作的? 生成一个简单的网格

我意识到我已经编辑出了原始代码中的if语句,这不利于可读性和问题的清晰度。 只是跳到答案,解释他们如何使用一个小例子程序。

要了解更多在Prolog中使用if语句的复杂程序,我将创建一个简单的平台生成器,生成一些对象并将它们放置在网格中。 首先,我试图通过在序言中尝试生成事物的想法来生成一个简单的“世界”。 计划是创建一个包含10000个项目的50个列表的网格,但实际上不应该那么复杂,但我不能让if语句正常工作,因为我的印象是,我从根本上误解了它们的工作原理,认为他们工作。 会发生什么情况是没有满足条件,if语句没有被调用,但整个谓词被调用空变量和评估没有实例化。

  • 创建一个具有X轴和Y轴的简单累加器,并限制它们在失败谓词之前走多远。
  • 如果Y行数已经达到,则终止
  • 创建一个新的[id,point(X,Y),Image],稍后会填充一些东西
  • 如果X =行的末尾,X是0,否则创建下一个点
  • 码:

    generate(WorldList) :- generate_world(WorldList,0,_,10000,0,_,50).
    
    generate_world([H|T],X,_,XEnd,Y,_,YEnd) :-
        %Y has been filled with 50 rows, end recursion
        not(Y > YEnd),
        %iterate X by 1, store in XNew
        XNew is X + 1,  
        %create a new [id,point(X,Y), Image]
        H = [XNew,point(_,_)],
        %if X has reached 10k, add 1 to Y and create a new row
        X = XEnd -> YNew is Y + 1, 
        generate_world(T,0,_,XEnd,YNew,_,YEnd);
        %continue adding items to current row Y
        generate_world(T,XNew,_,XEnd,Y,_,YEnd).
    generate_world([],_,_,_,_,_,_).
    

    我在做一些明显错误的事情,或者你应该如何使用prolog条件语句,甚至可以像这样使用它们?

    我期望它的工作方式是评估一个术语,然后在下面的左边或者如果它是真的,或者如果它是错误的右边。 发生这种情况,但我不明白为什么整个谓词再次被调用,因为它也清空了被评估的变量。 我的脑袋疼。

    文档的内容如下:http://www.swi-prolog.org/pldoc/man?predicate=-%3E/2

    @damianodamiano发现了这个问题, if prolog中的语句需要被()标签包围。 我仍然想要更详细地解释他们在选择点,回溯和其他我可能不知道的Prolog特定事物方面的实际工作方式。


    你的谓词一旦停止运行就会停止,因为在not(By > YEnd)By没有实例化(注意By也是一个单例变量,每个单例变量都是无用的,并且可能导致错误)。 在这里,我发布了两个实现,第一个没有if语句(个人喜欢),第二个语句(我已经把22作为简洁的界限......)。

    首次实施:

    generateList(L):-
        generateWL(L,0,2,0,2).
    generateWL([],0,_,Y,Y). %you can add a ! here
    generateWL(L,MaxX,MaxX,R,MaxR):- %you can add a ! here
        R1 is R+1,
        generateWL(L,0,MaxX,R1,MaxR).
    generateWL([H|T],X,MaxX,R,MaxR):-
        X < MaxX,
        R < MaxR,
        X1 is X+1,
        H = [X1,point(X1,R)],
        generateWL(T,X1,MaxX,R,MaxR).
    
    ?- generateList(WL).
    WL = [[1, point(1, 0)], [2, point(2, 0)], [1, point(1, 1)], [2, point(2, 1)]]
    false
    

    如果你想防止回溯,只需添加我已注释的两个剪辑。

    第二次实施

    generateList2(L):-
        generateWLIf(L,0,2,0,2).
    
    generateWLIf([H|T],X,MaxX,R,MaxR):-
        (   X < MaxX, R < MaxR ->    
            X1 is X+1,
            H = [X1,point(X1,R)],
            generateWL(T,X1,MaxX,R,MaxR)
        ;   X = MaxX, R < MaxR ->  
            R1 is R+1,
            generateWL([H|T],0,MaxX,R1,MaxR)
        ;   R = MaxR ->  T = []).
    
    ?- generateList2(WL).
    WL = [[1, point(1, 0)], [2, point(2, 0)], [1, point(1, 1)], [2, point(2, 1)]]
    

    (继续评论)

    我期望的[条件语句]的工作方式是评估一个术语,然后在下面的左边或者如果它是真的,或者如果它是错误的,则执行右边的操作。 发生这种情况,但我不明白为什么整个谓词再次被调用,因为它也清空了被评估的变量。

    你可能意味着它回溯,原因是比较not(Y > YEnd)最终失败,并且没有其他任何子句(如果两者都没有)。

    此外,您的基本情况是没有意义的,因为列表输出不是输入。 而你想与XNew比较而不是X

    generate(WorldList) :-
      generate_world(WorldList,1,10000,1,50).
    
    generate_world(T,X,XEnd,Y,YEnd) :-
      ( Y = YEnd ->
        T = []
      ; T = [point(X,Y)|Rest], XNew is X + 1,
        ( XNew = XEnd -> YNew is Y + 1,
          generate_world(Rest,1,XEnd,YNew,YEnd)
        ; generate_world(Rest,XNew,XEnd,Y,YEnd) ) ).
    

    这看起来很有效,因为它可以完成你所描述的内容,但这不是很好的设计。 现在你必须一直通过这个庞大的列表,更新一个位置意味着解构列表。

    你的问题:

    我创建了一个简单的平台生成器,生成一些对象并将它们放置在网格中。 首先,我试图通过在序言中尝试生成事物的想法来生成一个简单的“世界”。 计划是创建一个包含10000个项目的50个列表的网格

    在Prolog中通过具有谓词location/3 (例如,参数是坐标和内容)解决得更好。

    location(1,1,something).
    location(1,2,something).
    location(1,3,somethingelse).
    ...
    

    这个谓词是动态创建的,使用assert/3


    这是基于我对ISO-prolog和其他答案的理解,归结为if then else在Prolog中起作用的本质。

    if谓词->强制评估其周围由()分组的复杂术语。 外括号将if语句标识为( if -> then ; else ) ,其中ifthenelse是每个要评估的术语形式的目标,它们返回yesno ,也按()分组。 无论thenelse被调用,通过OR运算符分开; 取决于由if表示的评估术语的yesno结果。 外部分组是非常必要的,而内部分组是非必要的,但鉴于您可以嵌套另一个if语句作为第一个结果中的()包围的术语,所以我认为最好添加它们,这可能会产生不想要的结果,并使代码更难以阅读,以及任何非分组嵌套; 将确定右侧为else

    选择点是在有变量的情况下创建的,这些变量可以有多个可能的答案作为可能的解决方案。 这意味着内的if ,如果一个术语可以以多种方式来满足,Prolog的会尽量满足这一目标作为一个单独的目标,然后用结果来确定周围长期的结果。 如果一个目标失败了,它的行为就像普通的代码,并且不会进一步满足目标。

    如果选择点位于整个if语句部分之前,则将再次检查整个部分。

    示例程序来澄清这个想法。

    fact(a).
    fact(f).
    
    start :-
            (
                %The entire complex term is evaluated as yes
                (fact(a), write('first if'), nl) -> 
                    %triggers the first line
                    (write('first then'),nl) ; 
                    (write('first else'),nl)        
            ),
            (
                %The entire complex term is evaluated as no
                (fact(B), write('second if'), B = b, nl) -> 
                    (write('second then'),nl) ; 
                    %triggers the second line
                    (write('second else'),nl)
            ).
    

    并输出?- start.

    first if
    first then
    second ifsecond ifsecond else
    
    链接地址: http://www.djcxy.com/p/66949.html

    上一篇: SWI Prolog if statements, how do they work? Generating a simple grid

    下一篇: Logical Negation in Prolog