1

我有 罗素和诺维格关于人工智能的书中 的罗马尼亚地图。我在城市之间创建了这样的链接:

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.

我怎样才能让它只返回一次解决方案?

4

3 回答 3

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.
于 2014-12-11T10:25:55.093 回答
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].

编辑:假的答案是一个更好的解决方案,因为它不会建立不必要的列表All

于 2014-12-11T09:49:33.290 回答
0

另一种只获得一次解决方案的方法是在找到解决方案时动态使用数据库来存储解决方案:

?- retractall(sol(_)),
   (link(X,arad,_) ; link(arad,X,_) ; link(X,oradea,_) ; link(oradea,X,_)),
   \+ sol(X),
   assertz(sol(X)).

观察:

  1. 解决方案setof/3更好,应该是首选。

  2. 为了避免给数据库留下垃圾事实(不希望的副作用),您可以最后将它们全部清除:

    ?- ( 
         retractall(sol(_)),
         (link(X,arad,_);link(arad, X, _) ; link(X,oradea,_);link(oradea,X,_)),
         \+ sol(X), assertz(sol(X))
       ;
         retractall(sol(_)), fail
       ).
    
于 2014-12-11T10:46:08.903 回答