在 Prolog 中查找连接到顶点的所有节点
Finding all nodes connected to a vertex in Prolog
我对寻路算法很好奇,所以我看了一下Dijkstra的。我使用 this 视频作为指导(这就是我的图表的基础)。这是我正在使用的图表:
我现在希望能够找到给定顶点的所有连接。我认为我应该为此使用 findall
,我试图在下面的 all_connections
目标中使用它。但是,对于 main
,我的输出是 [b,b,b,b]
。为什么会这样?这是没有意义的。如果你明白我做错了什么,请告诉我。
connection(s, c, 3).
connection(c, l, 2).
connection(l, i, 4).
connection(l, j, 4).
connection(i, j, 6).
connection(i, k, 4).
connection(j, k, 4).
connection(k, e, 5).
connection(e, g, 2).
connection(g, h, 2).
connection(h, f, 3).
connection(f, d, 5).
connection(d, a, 4).
connection(b, d, 4).
connection(b, a, 3).
connection(b, s, 2).
connection(b, h, 1).
connection(a, s, 7).
are_connected(A, B, Score) :-
connection(A, B, Score);
connection(B, A, Score).
all_connections(A, Z) :-
findall(A, are_connected(A, _, _), Z).
main :-
all_connections(b, X),
write(X).
恭喜您解决了问题。如果您 post 解决方案作为答案,我们可以投票。
这是对其他事情的评论:由于您是一个相对初学者,现在是学习良好编码约定的最佳时机。具体来说,这个:
are_connected(A, B, Score) :-
connection(A, B, Score);
connection(B, A, Score).
非常糟糕。 Prolog 的析取是一个非常强大但常常令人困惑的工具。当你使用它的时候,使用应该真正突出。否则很容易将您的代码误认为是:
are_connected(A, B, Score) :-
connection(A, B, Score),
connection(B, A, Score).
按照你的写法,分号很容易在行尾漏掉。经验法则:永远不要在行尾使用 ;
。
备选方案:
are_connected(A, B, Score) :-
connection(A, B, Score).
are_connected(A, B, Score) :-
connection(B, A, Score).
(此转换仅适用于您定义的整个主体是析取。)
are_connected(A, B, Score) :-
( connection(A, B, Score)
; connection(B, A, Score) ).
或:
are_connected(A, B, Score) :-
(
connection(A, B, Score)
;
connection(B, A, Score)
).
你懂的。这些变体中的每一个都清楚地表明您正在做的事情与使用连词非常不同。
以下是我解决问题的方法:
are_connected(A, B, S) :-
connection(A, B, S)
;
connection(B, A, S).
非常感谢 Isabelle 给我关于正确约定的建议。
我对寻路算法很好奇,所以我看了一下Dijkstra的。我使用 this 视频作为指导(这就是我的图表的基础)。这是我正在使用的图表:
我现在希望能够找到给定顶点的所有连接。我认为我应该为此使用 findall
,我试图在下面的 all_connections
目标中使用它。但是,对于 main
,我的输出是 [b,b,b,b]
。为什么会这样?这是没有意义的。如果你明白我做错了什么,请告诉我。
connection(s, c, 3).
connection(c, l, 2).
connection(l, i, 4).
connection(l, j, 4).
connection(i, j, 6).
connection(i, k, 4).
connection(j, k, 4).
connection(k, e, 5).
connection(e, g, 2).
connection(g, h, 2).
connection(h, f, 3).
connection(f, d, 5).
connection(d, a, 4).
connection(b, d, 4).
connection(b, a, 3).
connection(b, s, 2).
connection(b, h, 1).
connection(a, s, 7).
are_connected(A, B, Score) :-
connection(A, B, Score);
connection(B, A, Score).
all_connections(A, Z) :-
findall(A, are_connected(A, _, _), Z).
main :-
all_connections(b, X),
write(X).
恭喜您解决了问题。如果您 post 解决方案作为答案,我们可以投票。
这是对其他事情的评论:由于您是一个相对初学者,现在是学习良好编码约定的最佳时机。具体来说,这个:
are_connected(A, B, Score) :-
connection(A, B, Score);
connection(B, A, Score).
非常糟糕。 Prolog 的析取是一个非常强大但常常令人困惑的工具。当你使用它的时候,使用应该真正突出。否则很容易将您的代码误认为是:
are_connected(A, B, Score) :-
connection(A, B, Score),
connection(B, A, Score).
按照你的写法,分号很容易在行尾漏掉。经验法则:永远不要在行尾使用 ;
。
备选方案:
are_connected(A, B, Score) :-
connection(A, B, Score).
are_connected(A, B, Score) :-
connection(B, A, Score).
(此转换仅适用于您定义的整个主体是析取。)
are_connected(A, B, Score) :-
( connection(A, B, Score)
; connection(B, A, Score) ).
或:
are_connected(A, B, Score) :-
(
connection(A, B, Score)
;
connection(B, A, Score)
).
你懂的。这些变体中的每一个都清楚地表明您正在做的事情与使用连词非常不同。
以下是我解决问题的方法:
are_connected(A, B, S) :-
connection(A, B, S)
;
connection(B, A, S).
非常感谢 Isabelle 给我关于正确约定的建议。