【问题标题】:Prolog: How do I remove symmetrical values in predicatesProlog:如何删除谓词中的对称值
【发布时间】:2022-01-16 01:53:39
【问题描述】:

我有一个关于删除对称值的问题 我的谓词。这些谓词在我的数据库中,我使用了 assertz 将它们添加到那里。

所以我有:

foo(a,b).
foo(b,a).
foo(c,d).
foo(e,f).
foo(f,e).

我正在尝试删除

foo(b,a).
foo(f,e).

我试图制定这条规则:

remove :- foo(A,B),foo(B,A),retract(foo(B,A)).

但是,这会删除我数据库中的所有谓词,我不知道如何 防止这种情况发生。

如果有人可以帮助我,我将不胜感激!

谢谢。

【问题讨论】:

    标签: database duplicates prolog


    【解决方案1】:

    retract/1 有两种不同的语义:

    • 立即更新视图:回溯后,收回的子句不再可见(它们立即变得不可见)。
    • 逻辑更新视图:在回溯时,撤回的子句仍然可以看到(它们仅在下一次谓词调用时才变得不可见)。此更新视图是 ISO 标准。

    在逻辑更新视图中,例如调用谓词remove/1时:

    • 首先它看到foo(a,b)foo(b,a),因此它收回foo(b,a)
    • 之后,在回溯时,它看到了foo(b,a)foo(a,b),因此它也撤回了foo(a,b)

    要解决此问题,您可以使用 ISO 内置谓词 once/1(防止回溯)。

    :- dynamic foo/2.
    
    foo(a,b).
    foo(b,a). 
    foo(c,d).
    foo(e,f).
    foo(f,e).
    
    remove :- 
        once( ( foo(A, B),
                foo(B, A),
                retract(foo(B, A)) ) ).
    

    只撤回一个对称的事实,你可以问:

    ?- listing(foo), remove, listing(foo).
    :- dynamic foo/2.
    
    foo(a, b).
    foo(b, a). % <== only this fact is retracted!
    foo(c, d).
    foo(e, f).
    foo(f, e).
    
    :- dynamic foo/2.
    
    foo(a, b).
    foo(c, d).
    foo(e, f).
    foo(f, e).
    
    true.
    

    收回所有对称事实,您可以定义:

    remove_all_sym :-
        (   remove
        ->  remove_all_sym
        ;   true ).
    

    例子:

    ?- listing(foo), remove_all_sym, listing(foo).
    :- dynamic foo/2.
    
    foo(a, b).
    foo(b, a). % <== this fact is retracted!
    foo(c, d).
    foo(e, f).
    foo(f, e). % <== this fact is retracted!
    
    :- dynamic foo/2.
    
    foo(a, b).
    foo(c, d).
    foo(e, f).
    

    注意更好的选择是避免将对称事实插入数据库:

    assert_foo(A, B) :-
        (   foo(B, A)          
        ->  true                
        ;   assertz(foo(A, B)) ).
    

    【讨论】:

    • 你是救生员,非常感谢它终于奏效了!
    • 如果使用 SWI-Prolog,那么更好的方法是使用 assertz/2erase/1
    • @GuyCoder 要在 SWI-Prolog 中使用 erase/1,您必须具有对要从数据库中删除的子句的引用,但在删除子句时,该引用是未知的谓词remove/0。 OP 如何用erase/1 解决?你能详细说明一下吗?
    • @slago 使用 SWI-Prolog 作为存储数据库,我使用 library(persistency)
    • @GuyCoder 这是真的!正如我所说,我同意你的观点,这将是更一般情况下的最佳解决方案(显然,如果正在使用 SWI-Prolog)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多