我有一个充满事实的数据库,例如:
overground( watfordjunction , watfordhighstreet , 2 ).
overground( watfordhighstreet , bushey , 3 ).
overground( bushey , carpenderspark , 3 ).
overground( carpenderspark , hatchend , 2 ).
例如:watford交界处到watfordhighstreet需要2分钟。
然后我设计了一条规则,以便我可以测试是否可以完成从任何车站到另一个车站的旅程,包括任何反向旅程。
isjourney( Station1 , Station2 ) :-
overground( Station1 , _ , _ ) ,
overground( _ , Station2 , _ ) ;
overground( Station2 , _ , _ ) ,
overground( _ , Station1 , _ )
.
isjourney( Station1 , Station2 ) :-
overground( Station1 , Station3 , _ ) ,
isjourney( Station3 , Station2 )
.
isjourney( Station1 , Station2 ) :-
overground( Station4 , Station2 , _ ) ,
isjourney( Station1 , Station4 )
.
(原谅下划线,我无法粘贴它们)
最后我提出了一个可行的方法,但是我只是在试错后才想出来,所以我无法解释它是如何工作的,甚至是它的作用......任何有经验的人都可以向我解释它的作用?
答案 0 :(得分:1)
你的第一个条款是错误的。 它应该是
isjourney(Station1, Station2):-
overground(Station1, Station2, _).
其他条款似乎没问题,但你可以把它们放在一个条款中:
isjourney(Station1,Station2):-
(overground(Station1,Station3,_), isjourney(Station3,Station2)) ;
(overground(Station3,Station2,_), isjourney(Station1,Station3)) .
基本上你所说的是,如果地上Station1和Station2成功,或者有一个中间站(Station3),你可以从Station1到Station3,然后从Station3到Station2(或者反向旅程)。
答案 1 :(得分:1)
我假设你正在服用@DavidGregg正在服用的同一个班级。我对https://stackoverflow.com/questions/8789021/basic-prolog-but-struggling/8794162#8794162的回答可能对您有帮助。
FWIW,prolog变量_
是匿名/“不关心”变量。名为____
的变量是不匿名/“不关心”。匿名变量与任何东西统一,统一不会延续,所以给出的事实如下:
number(1).
letter(a).
一个谓词,如
foo :- number(_) , letter(_).
会成功,而
foo :- number(____) , letter(____) .
不会。
在你的第一个条款中
isjourney( Station1 , Station2 ) :-
overground( Station1 , _ , _ ) ,
overground( _ , Station2 , _ ) ;
overground( Station2 , _ , _ ) ,
overground( _ , Station1 , _ )
.
你确定它与你认为它绑定的方式有关吗?
就像过程语言的语法一样,prolog的AND和OR运算符的优先级不同。如果您要使用OR运算符;
,则应该对事物进行括号化以使预期的绑定清晰。不过,恕我直言,更好的是完全避免它:
isjourney( Station1 , Station2 ) :-
overground( Station1 , _ , _ ) ,
overground( _ , Station2 , _ )
.
isjourney( Station1 , Station2 ) :-
overground( Station2 , _ , _ ) ,
overground( _ , Station1 , _ )
.
您的基本想法是正确的:A站和B站之间的路线存在如果
我相信你遗漏了一个案例:A站和B站直接相邻。
但是,我要注意,显式检查电台的存在并不是必要的:如果电台不存在,则谓词不能成功。
我倾向于写谓词
isjourney(A,B) :-
station_exists(A) , % verify that station A exists
station_exists(B) , % verify that station B exists
(
route_exists(A,B) % verify that a route exists between A and B
; % in either direction
route_exists(B,A)
)
.
route_exists(A,B) :- % 1st, check for directly adjacent stations
overground(A,B,_) ,
.
route_exists(A,B) :- % 2nd, check for indirect routes
overground(A,T,_) ,
route_exists(T,B)
.
% =========================================================
% check for the existence of a station
% we want the cut to alternatives. A station exists or it doesn't
% we don't want backtracking to succeed by finding every instance
% of the station
% in the route map.
% =========================================================
station_exists(X) :- overground(X,_,_) , ! .
station_exists(X) :- overground(_,X,_) , ! .
回溯当然应该列举两个方向上的所有可能路线。
正如我在上面的回答中所指出的,如果图中存在一个循环,该解决方案仍然容易受到无底递归的影响(例如,如果站A链接到站B,站B链接到站C和A) )。您可以选择检测此类周期。
答案 2 :(得分:0)
我猜你试图回答与the person in this question相同的事情。
首先,你应该使用你的问题2回答:
基本情况,如果有直接旅程:
is_journey(Station1, Station2) :-
q2(Station1, Station2).
不是基本情况,你必须使用中间件:
is_journey(Station1, Station2) :-
q2(Station1, StationTemp),
is_journey(StationTemp, Station2).
现在,这不会处理周期:你可能会陷入无限循环,所以要处理它们,你应该选择:
首先,我们调用一个谓词,它将调用相同的谓词但有3个参数(最后一个跟踪所使用的站点):
is_journey(Station1, Station2) :-
is_journey(Station1, Station2, [Station1]).
然后我们使用相同的基本情况:
is_journey(Station1, Station2, _) :-
q2(Station1, Station2).
然后我们使用几乎相同的递归情况,但我们检查Visited
中的成员身份,并在继续递归时更新Visited
:
is_journey(Station1, Station2, Visited) :-
q2(Station1, StationTemp),
\+ member(StationTemp, Visited),
is_journey(StationTemp, Station2, [StationTemp|Visited]).
BTW我不认为你的OP谓词是正确的,因为它只检查两个站是否真的是站,而不是两者都是直接连接。