Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/macos/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Prolog中属性变量的删除_Prolog - Fatal编程技术网

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.