我正在处理涉及图形的项目,我有一个属性变量列表,每个属性变量代表图中的一个节点。每个节点都有几个属性,例如相邻节点,起始节点的距离等。我想从列表中删除单个节点,但是当我使用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.
我能够通过优先级而不是密钥调用delete_from_heap来使其正常工作,但是,如果两个项具有相同的优先级并且选择了错误的项,则会导致问题。在我的应用程序中,这个问题通常不会出现,但看起来通常应该有一个更好的方法来使用属性变量和现有规则。
答案 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.
随着时间的推移,一些东西已经丢失......对不起