我有 map of Romania来自Russell和Norvig关于人工智能的书。我在城市之间创建了这样的链接:
link(oradea, zerind, 71).
link(oradea, sibiu, 151).
link(zerind, arad, 75).
link(arad, sibiu, 140).
link(arad, timisoara, 118).
link(timisoara, lugoj, 111).
link(lugoj, mehadia, 70).
link(mehadia, drobeta, 75).
link(drobeta, craiova, 120).
我想找到与奥拉迪亚或阿拉德联系的城市,但当我问这个时:
(link(X, arad, _); link(arad, X, _));(link(X, oradea, _); link(oradea, X, _)).
它返回:
X = zerind ;
X = sibiu ;
X = timisoara ;
X = zerind ;
X = sibiu.
如何让它只返回一次解决方案?
答案 0 :(得分:3)
?- setof(t, Dist^((link(X, arad, Dist) ; link(arad, X, Dist)) ;
(link(X, oradea, Dist) ; link(oradea, X, Dist))), _).
X = sibiu ;
X = timisoara ;
X = zerind.
答案 1 :(得分:2)
实现此目标的一种简单方法是使用setof/3
,从而消除解决方案列表中的重复项:
?- setof(X, Dist^((link(X, arad, Dist) ; link(arad, X, Dist)) ;
(link(X, oradea, Dist) ; link(orade, X, Dist))), All).
此查询与您的查询之间存在差异,因为在此列表中,所有解决方案都放在列表中,而不是一次一个。但您可以使用member/2
来获得相同的行为:
?- setof(X, Dist^((link(X, arad, Dist) ; link(arad, X, Dist)) ;
(link(X, oradea, Dist) ; link(oradea, X, Dist))), All),
member(X, All).
X = sibiu,
All = [sibiu, timisoara, zerind] ;
X = timisoara,
All = [sibiu, timisoara, zerind] ;
X = zerind,
All = [sibiu, timisoara, zerind].
修改:false' answer是一个更好的解决方案,因为它不会构建不必要的列表All
。
答案 2 :(得分:0)
另一种只获得解决方案的方法是动态使用数据库来存储解决方案:
?- retractall(sol(_)),
(link(X,arad,_) ; link(arad,X,_) ; link(X,oradea,_) ; link(oradea,X,_)),
\+ sol(X),
assertz(sol(X)).
观察:
setof/3
的解决方案更好,应该首选。
为了避免让数据库留下垃圾事实(不良副作用),你可以最后清理它们:
?- (
retractall(sol(_)),
(link(X,arad,_);link(arad, X, _) ; link(X,oradea,_);link(oradea,X,_)),
\+ sol(X), assertz(sol(X))
;
retractall(sol(_)), fail
).