【问题标题】:How to construct a list from two lists in prolog如何从prolog中的两个列表构造一个列表
【发布时间】:2015-10-30 15:01:10
【问题描述】:

我是 prolog 的新手,我发现很难以递归方式思考。假设我有两个列表:list1[0,0,0,1,1,0,1,1],list2[1,0,1,0,0,0,1,1]。当 list1 或 list 2 在相应位置有 1 时,我想返回一个有 1 的列表。

merge([H1|[]],[H2|[]],[H3|[]]):- H2 = 1, H3 = 1, H1 is 1.
merge([H1|T1],[H2|T2],[H3|T3]):- merge(T1,T2,T3), H2 = 1, H3 = 1, H1 is 1.

我知道我不能以上述形式扭动,但这与我现在所能做到的一样接近序言形式。递归似乎太难了!

【问题讨论】:

    标签: list prolog clpfd clpb


    【解决方案1】:

    解决此类任务的一个好方法是首先描述每个列表的单个元素之间的关系,然后使用maplist/[2,3,4] 将相同的推理扩展到列表。

    例如:

    either_is_one(0, 1, 1).
    either_is_one(1, 0, 1).
    either_is_one(1, 1, 1).
    

    但是如果两个列表中的 在特定位置都没有“1”,情况会怎样呢?现在,我假设您将其与“0”联系起来:

    either_is_one(0, 0, 0).
    

    然后,很简单,我们使用maplist/4 将这些元素的列表 相互关联:

    ?- maplist(either_is_one, [0,0,0,1,1,0,1,1], [1,0,1,0,0,0,1,1], Ls).
    Ls = [1, 0, 1, 1, 1, 0, 1, 1] ;
    false.
    

    请注意,这是完全纯粹的,也适用于其他方向。例如:

    ?- length(As, _), maplist(either_is_one, As, Bs, Cs).
    As = Bs, Bs = Cs, Cs = [] ;
    As = [0],
    Bs = Cs, Cs = [1] ;
    As = Cs, Cs = [1],
    Bs = [0]
    As = Bs, Bs = Cs, Cs = [1] ;
    etc.
    

    【讨论】:

    • 谢谢,它成功了。对了,如果我想把这个Ls存起来以备后用,是不是每次要用Ls都要调用这个maplist,还是可以保存?
    • 你可以很容易地为这个your_relation(As, Bs, Cs) :- maplist(either_is_one, As, Bs, Cs).引入一个新的关系
    【解决方案2】:

    使用!

    向@mat 致敬!实际上是两次:一次给评论者,一次给 实施者。

    :- use_module(library(clpb))。 bool_bool_or(A,B,AB) :- sat(AB =:= A + B)。

    使用maplist/4的示例查询:

    ?- maplist(bool_bool_or, [1,1,1], Bs, ABs)。 ABs = [1,1,1],Bs = [_X,_Y,_Z],sat(_X=:=_X),sat(_Y=:=_Y),sat(_Z=:=_Z)。 ?- maplist(bool_bool_or, [1,1,1], _, ABs)。 AB = [1,1,1]。 ?- maplist(bool_bool_or, [0,0,0,1,1,0,1,1], [1,0,1,0,0,0,1,1], ABs)。 AB = [1,0,1,1,1,0,1,1]。

    【讨论】:

      【解决方案3】:

      中使用合适的算术表达式怎么样?

      :- use_module(library(clpfd)).
      
      z_z_max(A,B,AB) :-
         [A,B,AB] ins 0..1,
         AB #= max(A,B).
      

      使用maplist/3的示例查询:

      ?- maplist(z_z_max, [0,0,0,1,1,0,1,1], [1,0,1,0,0,0,1,1], Ls).
      Ls = [1,0,1,1,1,0,1,1].           % succeeds deterministically
      

      提供了一个高级接口来控制流优化,可以将回溯搜索速度提高几个数量级。使用它!

      【讨论】:

      • +1!如果有人对布尔变量进行推理,我还建议检查 CLP(B) 约束。例如:bool_bool_or(X, Y, Or) :- sat(Or =:= X + Y).,例如可在 SICStus Prolog 中与 library(clpb) 一起使用。示例查询:?- maplist(bool_bool_or, [1,1,1], _, Cs).,产生:Cs = [1, 1, 1]
      • 我还做了一些微基准测试。 clpfd 是AB is A+B 的 2 倍,令人印象深刻...虽然 4-facts-variant 是最快的...当然,一旦我们放眼大局,它就会被颠倒过来!
      • 关于速度:我建议在整个过程中简单地使用 CLP(FD) 约束,而忘记较低级别的整数运算,因为如今即使是速度优势也无法证明使用较低级别的功能是合理的。只有在使用更新的、更具声明性的功能时,系统才会改进(并赶上)。在实践中,我会使用 CLP(FD) 或 CLP(B) 版本,或者如果其余大小写与表达式不匹配,则使用拼写版本。
      • 我们在同一页面上......这并不奇怪。
      猜你喜欢
      • 2018-02-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-04-28
      • 1970-01-01
      • 1970-01-01
      • 2016-01-12
      • 2013-02-07
      相关资源
      最近更新 更多