List 将一个列表拆分为两个其他列表的序言

List 将一个列表拆分为两个其他列表的序言,list,prolog,List,Prolog,我试着通读一个列表,检查一个元素,如果元素在KB中,做点什么,把它添加到另一个列表中,如果它不在KB中,那么把它添加到另一个,第三个列表中 我一直在按照程序逻辑思考,但我真的无法理解它。这对我来说是有意义的-但它不起作用 //KB r([a|X],Y,[gone|X]). r([c|X],Y,[gone|X]). r([b|X],Y,[known|X]). r([d|X],Y,[known2|X]). simplify([X|List],[X|NW],Result) :- r(List

我试着通读一个列表,检查一个元素,如果元素在KB中,做点什么,把它添加到另一个列表中,如果它不在KB中,那么把它添加到另一个,第三个列表中

我一直在按照程序逻辑思考,但我真的无法理解它。这对我来说是有意义的-但它不起作用

//KB
r([a|X],Y,[gone|X]).
r([c|X],Y,[gone|X]).
r([b|X],Y,[known|X]).
r([d|X],Y,[known2|X]).

simplify([X|List],[X|NW],Result) :-
    r(List,Nw,NewList),
    !,
    simplify2(NewList,Nw,Result).

simplify2([W|Words],Nw,[W|NewWords]) :-
     simplify2(Words,Nw,NewWords).

simplify2([],[],[]).
查询:

-简化([a,b,c,d,e,f],X,Y)

我想:

X = [e,f]  
Y = [gone,known,gone,known2]

但是上面给出了
X=[a | mem_address]
Y=[d,e]

让我们首先修正语法:

  • Prolog中的其余行注释以
    %
    开头,而不是
    /
  • r/3
    中删除第二个参数;它没有目的
  • MW
    ->
    MW
    simplify/3
  • 在参数之间插入空格(语法上没有错误,但阅读起来有点困难)
现在,让我们删除一些冗余:

  • r/2
    中,您实际上不需要列表尾部
  • 此外,我们不需要列表来说明某个术语“已知”或“已消失”
  • simplify/3
    simplify2/3
    可以合并到同一谓词中
现在,让我们添加一些新内容:

  • r/2
    声明为动态。这允许使用
    assert/1
    retract/1
    更改知识库
  • 对变量使用一致的命名。例如,对于列表头,
    H
    ,对于列表尾,
    T
    ,对于(完整)列表,
    L
我们得到以下结果:

:- dynamic(r/2).

r(a, gone).
r(c, gone).
r(b, known).
r(d, known2).

simplify([], [], []).
simplify([H|T1], L2, L3):-
  (   r(H, Status)
  ->  L2 = T2,
      L3 = [Status|T3]
  ;   L2 = [H|T2],
      L3 = T3
  ),
  simplify(T1, T2, T3).
具有所需的行为:

?- simplify([a,b,c,d,e,f],X,Y).
X = [e, f],
Y = [gone, known, gone, known2].
请注意,在上述步骤中,我是如何执行以下步骤的:

  • 我试图得到语法上有效的序言
  • 一旦程序有了有效的语法,我会尽量简化它,同时保持行为稳定/完整
  • 只有当代码在语法上有效且简化时,我才开始修改它以实现预期的行为

  • 编辑:感谢您指出非稳定行为。程序被相应地编辑。

    首先,您需要使用
    setof
    从知识库(实际上,常用术语是数据库)收集数据。然后很简单:

    r([a|X],Y,[gone|X]).
    r([c|X],Y,[gone|X]).
    r([b|X],Y,[known|X]).
    r([d|X],Y,[known2|X]).
    
    kb(L) :- setof((A,B), r([A|_],_,[B|_]), L).
    
    simplify([], [], []).
    simplify([H|T], T1, [H2|T2]) :- 
        kb(L), 
        member((H,H2), L),
        simplify(T, T1, T2).
    
    simplify([H|T], [H|T1], T2) :-
        simplify(T, T1, T2).
    

    非常神秘。我知道X是“未知”元素。但是Y是什么?顺便说一句,我很好奇你是如何得到一个作为序言列表尾部的内存地址的!尤金,X是未知的,Y是已知的!我想简化(翻译)已知的术语,删除已知的噪声术语,留下一个我可以使用的已知术语列表和一个我可以“学习”的未知术语的单独列表。这给出了所有可能的列表。这是一个错误的好例子,追踪者可以直接向您展示程序。感谢尤金,这很有意义,也是我将使用的方法——我应该更清楚地说,[gone | X]实际上只是X。gone被删除了!但我应该可以根据你的帮助来调整。真的,谢谢lot@false的确我对这个问题的成功感到非常惊讶:-(有没有办法从算法和/或系统上检查稳定性?(我知道有一些关于这个主题的论文,但它们都很正式。)@false在我的阅读清单上,但恐怕我需要一些时间来仔细阅读。谢谢!我只是简单地浏览了一下示例:这种坚定性肯定有点不同。事实上。脚注3注意,我们称之为“坚定的逻辑程序”与O'Keefe完全不同([33],第96页)虽然我们也(需要)在“不变”的意义上使用“steadfast”,但称之为“steadfast谓词”。一般说明:我有200份奖金等待新的贡献者,特别是10k以下的贡献者。还剩3天。如果没有,200个代表将被浪费。还有一句话:如果r(H,Status)有多个解决方案怎么办?