【问题标题】:Creating the @< BIP in prolog在序言中创建@< BIP
【发布时间】:2012-04-01 17:12:46
【问题描述】:

我基本上是在尝试在 prolog 中创建 @

所以一些示例输入:

?- at_less(1.2,0)
yes
?-at_less(0,1.2)
no
?-at_less(f(1,2,a),f(1,2,b)).
yes

显然我不想使用 @

%atom_pr(+A1,+A2): A1 @< A2, where A1 and A2 are atoms.

atom_pr(L1,L2):-
    atom_codes(L1,First), %atom codes for first
    atom_codes(L2,Second),%atom codes for second
    code_compare(First,Second). %compare the codes, return true or false

code_compare([HF|TF],[HS|TS]):-
    (   HF=HS ->
    code_compare(TF,TS)
    ;
    HF<HS ->
    true
    ;
    fail
    ).
code_compare([],X):-
    true.
code_compare([],[]).

%(I understand this is probably not the most efficient way of going about this, but I'm %just beginning!)

我可以为所有常量做类似的事情,而不仅仅是原子吗?有没有类似 atom_codes/2 的命令?如果不是,我唯一能想到的就是把它分解成大量的 if -> else 语句,检查第一个是不是原子,第二个不是等等,但这似乎是一个也许有点乏味/糟糕的方法?

提前感谢您的帮助!

编辑:多亏了下面的帮助,我得到了一个正在运行的程序(至少据我所知)。我已经把它放在下面的代码中,以防其他人在这里徘徊。但是,我认为它的效率极低,因此还有很大的改进空间:)

%flat_pr(+F1, +F2): F1@<F2, where F1 and F2 are flat ground terms
flat_pr(F1,F2):-

    (   compound(F1) ->   %these ifs here to check what type F1 and F2 are
    (   compound(F2) ->   %comparing/succeeding/failing as appropriate
    compound_compare(F1,F2) %(atom>integer>float>compound)
    ;                       % I believe these ifs could definitely be cut down though
    (   atom(F2) ->
    true
    ;
    (   float(F2) ->
    true
    ;
    (   integer(F2) ->
    true
    )
    )
    )
    )
    )

    ;

    (   atom(F1) ->
    (   compound(F2) ->
    false

    ;
    (   atom(F2) ->
    atom_pr(F1,F2)
    ;
    (   float(F2) ->
    false
    ;
    (   integer(F2) ->
    false
    )
    )
    )
    )
    )

    ;

    (   float(F1) ->
    (   compound(F2) ->
    false

    ;
    (   atom(F2) ->
    true

    ;
    (   float(F2) ->
    number_pr(F1,F2)
    ;
    (   integer(F2) ->
    true
    )
    )
    )
    )
    ;
    fail
    )

    ;

    (   integer(F1) ->
    (   compound(F2) ->
    false

    ;
    (   atom(F2) ->
    true

    ;
    (   float(F2) ->
    false

    ;
    (   integer(F2) ->
    number_pr(F1,F2)
    )
    )
    )
    )
    )
    .

compound_compare(F1,F2):-  %compares compounds (arity first)
    functor(F1,N1,A1),    %get arity
    functor(F2,N2,A2),
        (   A1<A2 ->      %compare arity
    true
    ;
    (   A1>A2 ->
    false
    )
    ;
    (   A1=A2 ->      %if arity the same
    F1 =.. L1,       %compound -> list
    F2 =.. L2,
    list_compare(L1,L2)  %compare the lists
    )
    )
    .

list_compare([],[]).  %base case
list_compare([H|T],[H1|T1]):-
    (   flat_pr(H,H1) ->    %if H@<H1
    list_compare(T,T1)     %compare Tails
    ;
    false               %else false
    )
    .

atom_pr(L1,L2):-
    atom_codes(L1,First), %atom codes for first
    atom_codes(L2,Second),%atom codes for second
    code_compare(First,Second). %compare the codes, return true or false

number_pr(L1,L2):-   %simple number comparison...straight forward
    (   L1=<L2 ->
    true
    ;
    fail
    ).

code_compare([HF|TF],[HS|TS]):- %just runs through atom codes
    (   HF=HS ->
    code_compare(TF,TS)
    ;
    HF<HS ->
    true
    ;
    fail
    ).
code_compare([],X):-
    true.
code_compare([],[]).

不过,我很乐意看到改进这一点的方法!干杯

【问题讨论】:

    标签: list prolog compare


    【解决方案1】:

    不确定 BIN-Prolog 但在 SWI-Prolog atom_codes 中可以解决问题:

    ?- atom_codes('jack\&^',K). 
    K = [106, 97, 99, 107, 38, 94].
    
    ?- atom_codes('17.2345',K). 
    K = [49, 55, 46, 50, 51, 52, 53].
    

    更新: 如果您需要比较术语,1) 冻结它们(见进一步)以使术语接地,2) 使用 unif (=..) 将术语转换为列表,例如,f(1,2) 变为 [f, 1,2],然后对于每个元素: a) 如果是原子或数字,则使用 atom_codes; b) 如果它是一个术语,递归地应用相同的过程。

    冻结确保变量按出现的顺序进行比较。我所说的“冻结”是指以下谓词,取自经典的 Sterling 和 Shapiro 的著作《序言的艺术》:

    numvars('#VAR'(N),N,N1) :- N1 is N+1.
    numvars(Term,N1,N2) :- nonvar(Term), functor(Term,_,N),
                              numvars(0,N,Term,N1,N2).
    numvars(N,N,_,N1,N1).
    numvars(I,N,Term,N1,N3) :- I<N, I1 is I+1,
              arg(I1,Term,Arg), numvars(Arg,N1,N2),
              numvars(I1,N,Term,N2,N3).
    
    frz(A,B) :- frz(A,B,0).
    frz(A,B,Min) :- copy_term(A,B), numvars(B,Min,_),!.
    

    【讨论】:

    • Atom 代码在某些方面很有帮助,但我应该如何处理“f(1,2,a,3)”之类的问题呢? atom_codes(f(1,2,a,3)) 给我一个错误?
    • 我已经更新了我的答案,因为我无法在评论中包含代码片段。
    • 非常感谢;我认为冻结的事情有点过头了:)(我基本上假设我正在使用平坦的地面术语,至少目前是这样)。 =.. 非常有帮助!如果我理解正确,您是在建议我将化合物转换为列表,然后只使用 atom_codes 来比较它们(并且 =.. 这个列表是否应该包含化合物)?
    • 是的。如果您获得的列表包含术语(我认为您称它们为“化合物”),您应该递归地重复该过程。如果不行,你真的很绝望,明天我可以给你写解决方案……
    • 感谢您的提议,但我相信我现在可以使用它了 :) 非常感谢您的帮助!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-10-29
    • 2018-12-16
    • 1970-01-01
    • 1970-01-01
    • 2016-08-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多