Prolog中属性变量的删除
我正在做一个涉及图形的项目,我有一个属性变量列表,每个变量代表图形中的一个节点。每个节点都有多个属性,例如相邻节点、到起始节点的距离等。我想从列表中删除单个节点,但使用“删除”时,会出现以下错误:Prolog中属性变量的删除,prolog,Prolog,我正在做一个涉及图形的项目,我有一个属性变量列表,每个变量代表图形中的一个节点。每个节点都有多个属性,例如相邻节点、到起始节点的距离等。我想从列表中删除单个节点,但使用“删除”时,会出现以下错误: ERROR: uhook/3: Undefined procedure: adjs:attr_unify_hook/2 例如,如果我在程序中包含delete(旧顶点、节点、新顶点),就会出现此错误 如果将顶点存储在二进制堆中,并尝试使用delete\u from\u heap从堆中删除顶点,也会出现
ERROR: uhook/3: Undefined procedure: adjs:attr_unify_hook/2
例如,如果我在程序中包含delete(旧顶点、节点、新顶点)
,就会出现此错误
如果将顶点存储在二进制堆中,并尝试使用delete\u from\u heap
从堆中删除顶点,也会出现完全相同的错误
如果我首先删除节点的所有属性,我就能够在节点上成功地使用delete和delete\u from\u heap
,但这会给我的程序带来问题,因为我想以后再使用这些属性;我只是不希望节点包含在列表或二进制堆中
这是一个bug,还是我处理属性变量不正确
编辑:
谢谢!这适用于列表。现在我正在尝试做一些类似的事情,从二进制堆中删除属性变量。我有个规矩
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_使其工作,但是,如果两个项具有相同的优先级,并且它选择了错误的项,那么这确实会导致问题。在我的应用程序中,这个问题并不经常出现,但似乎总有一种更好的方法可以将属性变量与现有规则结合使用 您无意中统一了一个属性附加了另一个术语的变量。涉及属性变量的统一在相应模块中触发attr\u unified\u 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.
请注意,这仍然会留下一个choicepoint。您可以使用一次/1
提交到第一个也是唯一的解决方案,因为您已经知道列表中的每个节点都是唯一的:
?- once(list0_var_list([A,B,C,D], B, Ls)).
Ls = [A, C, D].
使用这样的谓词而不是delete/3
可以安全地检测变量的相等性,并从列表中删除给定的变量,而不会触发任何统一挂钩
<>请注意,<代码>删除/ 3 <强> DeRebug < /St>(参见文档),并考虑以下情况:
?- delete([A,B,C], A, Cs).
Cs = [].
这表明当涉及变量时,您不能安全地使用
delete/3
。我自己使用属性变量进行图形表示的测试。我记得我发现很难适应所需的特定编程风格。嗯
/* 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).
随着时间的流逝,有些东西已经失去了。。。抱歉您需要发布一些代码,以明确您在此处试图执行的操作。您似乎也在使用,但在哪种实现以及如何实现?谢谢!是否可以对二进制堆执行类似的操作?谢谢!我也实现了Dijkstra'a算法。我有一个没有二进制堆的工作实现,但我最终使用二进制堆使它工作起来。令人惊讶的是,我发现使用像您实现的最小_距离规则来获得到起点的最近距离要比使用二进制堆(以到起点的距离为优先级并删除最小优先级)更快。我的想法是,这是由于在Prolog中表示二进制堆的方式,因为它不使用数组,但一开始我很惊讶,二进制堆的实现速度较慢
?- 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.