Prolog路径规划应用开发求助:最便宜路径实现故障
修复你的Prolog最便宜路径实现问题
看起来你在搭建基于Prolog的路径规划系统时,最便宜路径的功能出了问题。我来帮你拆解问题根源,再给出修正后的完整实现:
问题分析
你的代码里有几个核心问题导致功能失效:
- 路径与成本计算不匹配:
path/3生成的是纯节点列表(比如[gdansk, sopot, gdynia]),但path_cost/2试图从这个列表里匹配train事实——节点列表根本不包含交通工具的成本信息,自然无法计算。 - 忽略飞机成本:
path_cost/2只处理了火车的费用,完全漏掉了飞机的成本项。 - 成本结构解析错误:你的train/plane事实里,成本是
cena(5)这种结构化数据,直接拿它做sum运算,Prolog无法识别为数值进行计算。
修正后的代码实现
我们需要重构路径的表示逻辑,让它能跟踪每一段行程的成本,同时修正成本计算的逻辑:
1. 保留原有的交通工具事实
% train/plane(name, from, to, departure, arrival, price). train(p1, gdansk, sopot, odjazd(10:15), przyjazd(10:30), cena(5)). train(p2, sopot, gdynia, odjazd(11:00), przyjazd(11:30), cena(5)). train(p3, sopot, gdynia, odjazd(11:15), przyjazd(11:45), cena(5)). plane(s1, gdansk, warszawa, odlot(16:00), przylot(17:15), cena(300)). plane(s2, gdansk, wroclaw, odlot(14:00), przylot(15:30), cena(300)). plane(s3, gdansk, poznan, odlot(18:00), przylot(19:30), cena(200)).
2. 重构路径谓词,跟踪行程段与累计成本
修改path/4,让它生成包含每一段交通工具的路径,并实时累计总成本:
% path(From, To, Path, TotalCost) % Path是行程段的列表,TotalCost是该路径的总成本 path(From, To, Path, TotalCost) :- path(From, To, [], Path, 0, TotalCost). % 终止条件:到达目的地,总成本累计完成 path(To, To, _, [], TotalCost, TotalCost). % 递归条件:找到从当前节点出发的交通工具,前往下一个节点并累计成本 path(From, To, Visited, [Leg|Rest], CurrentCost, TotalCost) :- \+ member(From, Visited), % 避免循环访问同一节点 dif(From, To), % 匹配火车或飞机的行程段,并提取成本数值 (train(Name, From, Next, Dep, Arr, cena(Cost)) ; plane(Name, From, Next, Dep, Arr, cena(Cost))), NewCost is CurrentCost + Cost, % 累计当前段的成本 path(Next, To, [From|Visited], Rest, NewCost, TotalCost).
3. 实现最便宜路径查询
现在可以用aggregate_all/3来筛选出总成本最小的路径:
% path_min_cost(From, To, MinCost, OptimalPath) % 返回从From到To的最便宜路径及其总成本 path_min_cost(From, To, MinCost, OptimalPath) :- aggregate_all(min(C, P), path(From, To, P, C), min(MinCost, OptimalPath)).
4. 可选:纯节点路径转换(如果需要)
如果你还是需要得到仅包含节点的路径,可以添加一个辅助谓词:
% path_to_nodes(Path, Nodes) - 将行程段列表转换为纯节点列表 path_to_nodes([], [_]). path_to_nodes([train(_, From, To, _, _, _)|Rest], [From|Nodes]) :- path_to_nodes(Rest, [To|Nodes]). path_to_nodes([plane(_, From, To, _, _, _)|Rest], [From|Nodes]) :- path_to_nodes(Rest, [To|Nodes]).
测试示例
查询从gdansk到gdynia的最便宜路径:
?- path_min_cost(gdansk, gdynia, MinCost, Path). MinCost = 10, Path = [train(p1, gdansk, sopot, odjazd(10:15), przyjazd(10:30), cena(5)), train(p2, sopot, gdynia, odjazd(11:00), przyjazd(11:30), cena(5))] ; MinCost = 10, Path = [train(p1, gdansk, sopot, odjazd(10:15), przyjazd(10:30), cena(5)), train(p3, sopot, gdynia, odjazd(11:15), przyjazd(11:45), cena(5))].
如果需要纯节点路径:
?- path_min_cost(gdansk, gdynia, MinCost, Path), path_to_nodes(Path, Nodes). MinCost = 10, Path = [...], Nodes = [gdansk, sopot, gdynia] ; ...
后续扩展建议
- 最快路径:需要解析
odjazd/1、przyjazd/1等时间结构,计算每段行程的耗时并累计,再用aggregate_all/3筛选最小总耗时的路径。 - 限制最晚到达时间的最便宜路径:在递归条件中添加到达时间检查,确保每一段的到达时间不超过限制,同时累计成本。
- 限制最高价格的最快路径:在递归中检查累计成本不超过上限,同时计算总耗时,筛选最小耗时的路径。
内容的提问来源于stack exchange,提问作者Konrad
相关产品推荐
相关产品推荐

