如何将SWI-Prolog中的tuples_in/2转换为GNU Prolog中的fd_relation/2以实现正确的三路径查询?
在GNU Prolog中实现三段路径查询的解决方案
你遇到的问题核心是GNU Prolog的fd_relation/2和SWI-Prolog的tuples_in/2参数要求完全不同:fd_relation(Tuples, Vars)要求Vars是一个扁平的变量列表(每个元组对应这组变量的一组取值),而不是像tuples_in那样接受嵌套的列表列表作为参数,这就是触发type_error(fd_variable)报错的原因。
下面提供两种可行的解决方案:
方法一:拆分嵌套变量适配fd_relation/2
我们可以把每个路径段的变量单独提取成扁平列表,分别和trains中的元组建立关系,这样就能满足fd_relation的参数规范:
trains([[1,2,0,1], % from station, to station, departs at, arrives at [2,3,4,5], [2,3,0,1], [3,4,5,6], [3,4,2,3], [3,4,8,9]]). threepath(A, D, Ps) :- Ps = [[A,B,T0,T1],[B,C,T2,T3],[C,D,T4,T5]], % 时间衔接约束 T2 #> T1, T4 #> T3, trains(Ts), % 为每个路径段单独建立CLP(FD)关系 fd_relation(Ts, [A,B,T0,T1]), fd_relation(Ts, [B,C,T2,T3]), fd_relation(Ts, [C,D,T4,T5]).
方法二:用member/2结合约束(更直观)
如果不需要严格依赖CLPFD的关系谓词,用member/2遍历列车列表并结合时间约束会更易懂,代码逻辑也更清晰:
trains([[1,2,0,1], % from station, to station, departs at, arrives at [2,3,4,5], [2,3,0,1], [3,4,5,6], [3,4,2,3], [3,4,8,9]]). threepath(A, D, [Path1, Path2, Path3]) :- trains(Ts), % 匹配第一段路径:从A到B member(Path1, Ts), Path1 = [A,B,_T0,T1], % 匹配第二段路径:从B到C,且出发时间晚于第一段到达时间 member(Path2, Ts), Path2 = [B,C,T2,T3], T2 #> T1, % 匹配第三段路径:从C到D,且出发时间晚于第二段到达时间 member(Path3, Ts), Path3 = [C,D,T4,_T5], T4 #> T3.
测试结果
运行查询?- threepath(1, 4, Ps).,两种方法都会返回预期结果:
Ps = [[1, 2, 0, 1], [2, 3, 4, 5], [3, 4, 8, 9]].
内容的提问来源于stack exchange,提问作者sail0r
相关产品推荐
相关产品推荐

