删除Prolog中的属性变量

时间:2015-09-03 21:54:00

标签: prolog

我正在处理涉及图形的项目,我有一个属性变量列表,每个属性变量代表图中的一个节点。每个节点都有几个属性,例如相邻节点,起始节点的距离等。我想从列表中删除单个节点,但是当我使用delete时,我收到以下错误:

ERROR: uhook/3: Undefined procedure: adjs:attr_unify_hook/2

例如,如果我在程序中包含delete(OldVertices, Node, NewVertices),则会收到此错误。

如果我将顶点存储在二进制堆中,并且尝试使用delete_from_heap从堆中删除顶点,我也会得到完全相同的错误。

如果我第一次删除它的所有属性,我能够在节点上成功使用delete和delete_from_heap,但这会导致我的程序出现问题,因为我想稍后使用这些属性;我只是不希望节点包含在列表或二进制堆中。

这是一个错误,还是我错误地处理了属性变量?

编辑:

谢谢!这适用于列表。现在我尝试做类似的事情从二进制堆中删除属性变量。我有一个规则

delheap(Heap, Key, NewHeap) :-  
    delete_from_heap(Heap, A1, A0, NewHeap),
    get_attr(Key, dist, A1),
    A0 == Key.

然而,当我测试时,我得到以下结果:

?- TLO = [3-A, 4-B], put_attr(A, dist, 3), put_attr(B, dist, 4), list_to_heap(TLO, H), delheap(H, A, Hq).
Correct to: "dijkstra_av:delheap(H,A,Hq)"? yes
TLO = [3-A, 4-B],  H = heap(t(A, 3, [t(B, 4, [])]), 2),  Hq = heap(t(B, 4, []), 1),  put_attr(A, dist, 3),  put_attr(B, dist, 4).

哪种方法很好,但是当我尝试用B:

?- TLO = [3-A, 4-B], put_attr(A, dist, 3), put_attr(B, dist, 4), list_to_heap(TLO, H), delheap(H, B, Hq).
Correct to: "dijkstra_av:delheap(H,A,Hq)"? yes
TLO = [3-A, 4-B], false.

编辑2:

我能够通过优先级而不是密钥调用delete_from_heap来使其正常工作,但是,如果两个项具有相同的优先级并且选择了错误的项,则会导致问题。在我的应用程序中,这个问题通常不会出现,但看起来通常应该有一个更好的方法来使用属性变量和现有规则。

2 个答案:

答案 0 :(得分:5)

您无意中统一具有与其他术语相关联的属性的变量。涉及属性变量的统一会在相应的模块中触发attr_unify_hook/2,并且您不会定义此类挂钩,因为您只使用属性作为访问数据的快速方式,并且可能对这些变量之间的任何统一不感兴趣。

要从列表中删除变量,请使用例如(==)/2

list0_var_list(Ls0, V, Ls) :-
        select(V0, Ls0, Ls),
        V0 == V.

示例查询:

?- list0_var_list([A,B,C,D], B, Ls).
Ls = [A, C, D] ;
false.

请注意,这仍留有一个选择点。您可以使用once/1提交第一个也是唯一的解决方案,因为您已经知道列表中的每个节点都是唯一的:

?- once(list0_var_list([A,B,C,D], B, Ls)).
Ls = [A, C, D].

使用这样的谓词而不是delete/3可以安全地检测变量的相等性并从列表中删除给定的变量,而不会触发任何统一挂钩。

另请注意delete/3 已弃用(请参阅文档),并考虑以下情况:

?- delete([A,B,C], A, Cs).
Cs = [].

这表明在涉及变量时无法安全地使用delete/3

答案 1 :(得分:2)

我自己的测试使用属性变量进行图形表示。我记得我发现很难适应所需的特定编程风格。 HTH

/*  File:    dijkstra_av.pl
    Author:  Carlo,,,
    Created: Aug  3 2012
    Modified:Oct 28 2012
    Purpose: learn graph programming with attribute variables
*/

:- module(dijkstra_av, [dijkstra_av/3,
            dijkstra_edges/3]).

dijkstra_av(Graph, Start, Solution) :-
    setof(X, Y^D^(member(d(X,Y,D), Graph) ; member(d(Y,X,D), Graph)), Xs),
    length(Xs, L),
    length(Vs, L),
    aggregate_all(sum(D), member(d(_, _, D), Graph), Infinity),
    catch((algo(Graph, Infinity, Xs, Vs, Start, Solution),
           throw(sol(Solution))
          ), sol(Solution), true).

dijkstra_edges(Graph, Start, Edges) :-
    dijkstra_av(Graph, Start, Solution),
    maplist(nodes_to_edges(Graph), Solution, Edges).

nodes_to_edges(Graph, s(Node, Dist, Nodes), s(Node, Dist, Edges)) :-
    join_nodes(Graph, Nodes, Edges).

join_nodes(_Graph, [_Last], []).
join_nodes(Graph, [N,M|Ns], [e(N,M,D)|Es]) :-
    aggregate_all(min(X), member(d(N, M, X), Graph), D),
    join_nodes(Graph, [M|Ns], Es).

algo(Graph, Infinity, Xs, Vs, Start, Solution) :-
    pairs_keys_values(Ps, Xs, Vs),
    maplist(init_adjs(Ps), Graph),
    maplist(init_dist(Infinity), Ps),
    %ord_memberchk(Start-Sv, Ps),
    memberchk(Start-Sv, Ps),
    put_attr(Sv, dist, 0),
    time(main_loop(Vs)),
    maplist(solution(Start), Vs, Solution).

solution(Start, V, s(N, D, [Start|P])) :-
    get_attr(V, name, N),
    get_attr(V, dist, D),
    rpath(V, [], P).

rpath(V, X, P) :-
    get_attr(V, name, N),
    (   get_attr(V, previous, Q)
    ->  rpath(Q, [N|X], P)
    ;   P = X
    ).

init_dist(Infinity, N-V) :-
    put_attr(V, name, N),
    put_attr(V, dist, Infinity).

init_adjs(Ps, d(X, Y, D)) :-
    %ord_memberchk(X-Xv, Ps),
    %ord_memberchk(Y-Yv, Ps),
    memberchk(X-Xv, Ps),
    memberchk(Y-Yv, Ps),
    adj_add(Xv, Yv, D),
    adj_add(Yv, Xv, D).

adj_add(X, Y, D) :-
    (   get_attr(X, adjs, L)
    ->  put_attr(X, adjs, [Y-D|L])
    ;   put_attr(X, adjs, [Y-D])
    ).

main_loop([]).
main_loop([Q|Qs]) :-
    smallest_distance(Qs, Q, U, Qn),
    put_attr(U, assigned, true),
    get_attr(U, adjs, As),
    update_neighbours(As, U),
    main_loop(Qn).

smallest_distance([A|Qs], C, M, [T|Qn]) :-
    get_attr(A, dist, Av),
    get_attr(C, dist, Cv),
    (   Av < Cv
    ->  (N,T) = (A,C)
    ;   (N,T) = (C,A)
    ),
    !, smallest_distance(Qs, N, M, Qn).
smallest_distance([], U, U, []).

update_neighbours([V-Duv|Vs], U) :-
    (   get_attr(V, assigned, true)
    ->  true
    ;   get_attr(U, dist, Du),
        get_attr(V, dist, Dv),
        Alt is Du + Duv,
        (   Alt < Dv
        ->  put_attr(V, dist, Alt),
        put_attr(V, previous, U)
        ;   true
        )
    ),
    update_neighbours(Vs, U).
update_neighbours([], _).

:- begin_tests(dijkstra_av).

small([d(a,b,2),d(a,b,1),d(b,c,1),d(c,d,1),d(a,d,3),d(a,d,2)]).

test(1) :-
    nl,
    small(S),
    time(dijkstra_av(S, a, L)),
    maplist(writeln, L).

test(2) :-
    open(salesman, read, F),
    readf(F, L),
    close(F),
    nl,
    dijkstra_av(L, penzance, R),
    maplist(writeln, R).

readf(F, [d(X,Y,D)|R]) :-
    read(F, dist(X,Y,D)), !, readf(F, R).
readf(_, []).

test(3) :-
    nl, small(S),
    time(dijkstra_edges(S, a, Es)),
    maplist(writeln, Es).

:- end_tests(dijkstra_av).

测试单元的存在允许:

?- run_tests(dijkstra_av).
% PL-Unit: dijkstra_av 
% 122 inferences, 0.000 CPU in 0.000 seconds (100% CPU, 1015009 Lips)
% 475 inferences, 0.002 CPU in 0.002 seconds (100% CPU, 283613 Lips)
s(a,0,[a])
s(b,1,[a,b])
s(c,2,[a,b,c])
s(d,2,[a,d])
.
ERROR: /home/carlo/prolog/dijkstra_av.pl:115:
    test 2: received error: open/3: source_sink `salesman' does not exist (No such file or directory)

% 122 inferences, 0.000 CPU in 0.000 seconds (100% CPU, 2027285 Lips)
% 619 inferences, 0.001 CPU in 0.001 seconds (100% CPU, 899941 Lips)
s(a,0,[])
s(b,1,[e(a,b,1)])
s(c,2,[e(a,b,1),e(b,c,1)])
s(d,2,[e(a,d,2)])
Warning: /home/carlo/prolog/dijkstra_av.pl:127:
    PL-Unit: Test 3: Test succeeded with choicepoint
 done
% 1 test failed
% 2 tests passed
false.
随着时间的推移,一些东西已经丢失......对不起

相关问题