Prolog 中的简化旅行推销员

发布于 2024-12-19 02:15:32 字数 688 浏览 2 评论 0原文

我浏览过类似的问题,但找不到与我的问题相关的任何内容。我正在努力寻找一种算法或一组“循环”,使用事实数据库找到从 CityACityB 的路径

distance(City1,City2,Distance)

。到目前为止我已经设法做的事情如下,但它总是在 write(X), 处回溯,然后完成最终迭代,这就是我想要它做的事情,但仅限于特定的情况程度。

例如,我不希望它打印出任何死胡同的城市名称,或使用最终迭代。我希望它基本上建立一条从 CityACityB 的路径,在路径上写下它要去的城市的名称。

我希望有人能帮助我!

all_possible_paths(CityA, CityB) :-
    write(CityA),
    nl,
    loop_process(CityA, CityB).

loop_process(CityA, CityB) :- 
    CityA == CityB.
loop_process(CityA, CityB) :-
    CityA \== CityB,
    distance(CityA, X, _),
    write(X),
    nl,
    loop_process(X, CityB).

I've looked through the similar questions but can't find anything that's relevant to my problem. I'm struggling to find an algorithm or set of 'loops' that will find a path from CityA to CityB, using a database of

distance(City1,City2,Distance)

facts. What I've managed to do so far is below, but it always backtracks at write(X), and then completes with the final iteration, which is what I want it to do but only to a certain extent.

For example, I don't want it to print out any city names that are dead ends, or to use the final iteration. I want it to basically make a path from CityA to CityB, writing the name of the cities it goes to on the path.

I hope somebody can help me!

all_possible_paths(CityA, CityB) :-
    write(CityA),
    nl,
    loop_process(CityA, CityB).

loop_process(CityA, CityB) :- 
    CityA == CityB.
loop_process(CityA, CityB) :-
    CityA \== CityB,
    distance(CityA, X, _),
    write(X),
    nl,
    loop_process(X, CityB).

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

歌枕肩 2024-12-26 02:15:32

我试图向您展示如何实现您正在做的事情,以便您可以更好地理解它是如何工作的。所以既然你的OP不是很完整,我就采取了一些自由行动!以下是我正在处理的事实:

road(birmingham,bristol, 9).
road(london,birmingham, 3).
road(london,bristol, 6).
road(london,plymouth, 5).
road(plymouth,london, 5).
road(portsmouth,london, 4).
road(portsmouth,plymouth, 8).

这是我们将调用的谓词来查找路径,get_road/4。它基本上称为工作谓词,它有两个累加器(一个用于已访问的点,一个用于我们经过的距离)。

get_road(Start, End, Visited, Result) :-
    get_road(Start, End, [Start], 0, Visited, Result).

这是工作谓词,
get_road/6 : get_road(+Start, +End, +Waypoints, +DistanceAcc, -Visited, -TotalDistance) :
第一个子句告诉我们,如果我们的第一个点和最后一个点之间有一条路,我们就可以在这里结束。

get_road(Start, End, Waypoints, DistanceAcc, Visited, TotalDistance) :-
    road(Start, End, Distance),
    reverse([End|Waypoints], Visited),
    TotalDistance is DistanceAcc + Distance.

第二个子句告诉我们,如果我们的第一个点和中间点之间有一条路,我们可以采用它,然后求解 get_road(intermediate, end)。

get_road(Start, End, Waypoints, DistanceAcc, Visited, TotalDistance) :-
    road(Start, Waypoint, Distance),
    \+ member(Waypoint, Waypoints),
    NewDistanceAcc is DistanceAcc + Distance,
    get_road(Waypoint, End, [Waypoint|Waypoints], NewDistanceAcc, Visited, TotalDistance).

用法如下:

?- get_road(portsmouth, plymouth, Visited, Distance).

和收益:

Visited = [portsmouth, plymouth],
Distance = 8 ;
Visited = [portsmouth, london, plymouth],
Distance = 9 ;
Visited = [portsmouth, plymouth, london, plymouth],
Distance = 18 ;
false.

希望对你有帮助。

I tried to demonstrate how you can achieve what you're working on so that you can understand better how it works. So since your OP wasn't very complete, I took some liberties ! Here are the facts I'm working with :

road(birmingham,bristol, 9).
road(london,birmingham, 3).
road(london,bristol, 6).
road(london,plymouth, 5).
road(plymouth,london, 5).
road(portsmouth,london, 4).
road(portsmouth,plymouth, 8).

Here is the predicate we will call to find our paths, get_road/4. It basically calls the working predicate, that has two accumulators (one for the points already visited and one for the distance we went through).

get_road(Start, End, Visited, Result) :-
    get_road(Start, End, [Start], 0, Visited, Result).

Here is the working predicate,
get_road/6 : get_road(+Start, +End, +Waypoints, +DistanceAcc, -Visited, -TotalDistance) :
The first clause tells that if there is a road between our first point and our last point, we can end here.

get_road(Start, End, Waypoints, DistanceAcc, Visited, TotalDistance) :-
    road(Start, End, Distance),
    reverse([End|Waypoints], Visited),
    TotalDistance is DistanceAcc + Distance.

The second clause tells that if there is a road between our first point and an intermediate point, we can take it and then solve get_road(intermediate, end).

get_road(Start, End, Waypoints, DistanceAcc, Visited, TotalDistance) :-
    road(Start, Waypoint, Distance),
    \+ member(Waypoint, Waypoints),
    NewDistanceAcc is DistanceAcc + Distance,
    get_road(Waypoint, End, [Waypoint|Waypoints], NewDistanceAcc, Visited, TotalDistance).

Usage is as follows :

?- get_road(portsmouth, plymouth, Visited, Distance).

And yields :

Visited = [portsmouth, plymouth],
Distance = 8 ;
Visited = [portsmouth, london, plymouth],
Distance = 9 ;
Visited = [portsmouth, plymouth, london, plymouth],
Distance = 18 ;
false.

I hope it will be helpful to you.

套路撩心 2024-12-26 02:15:32

请将纯净部分与不纯净部分分开(I/O,如 write/1nl/0 以及 (==)/2(\==)/2)。只要它们与您的纯代码完全交错,您就不能期望太多。

也许您想要起点、终点和之间的路径之间的关系。

该路径应该是非循环的还是允许循环

要确保元素 X 不会出现在列表 Xs 中,请使用目标 maplist(dif(X),Xs)。
您不需要任何进一步的辅助谓词来使其成为良好的关系!

Please separate the pure part from the impure (I/O, like write/1, nl/0 but also (==)/2 and (\==)/2). As long as they are entirely interlaced with your pure code you cannot expect much.

Probably you want a relation between a starting point, an end point and a path in between.

Should that path be acyclic or do you permit cycles?

To ensure that an element X does not occur in a list Xs use the goal maplist(dif(X),Xs).
You do not need any further auxiliary predicates to make this a nice relation!

帅气称霸 2024-12-26 02:15:32

您应该返回一个成功列表作为 all_possible_paths 中的 Out 变量。然后写出该清单。不要在同一过程中同时执行这两项操作。

You should return a successful list as an Out variable in all_possible_paths. Then write out that list. Don't do both in the same procedure.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文