超出本地堆栈

时间:2017-10-03 20:58:50

标签: prolog

所以我有这些事实:

border(germany, france).
border(france, spain).
border(spain, portugal).

还有一些其他的边界可以让我从葡萄牙到俄罗斯(这里有太多的事实要发布,但实际上有可能从葡萄牙到俄罗斯)。 我做了这个谓词,告诉你当你从P1到P2时你越过的国家数量:

crossedCountries(P1,P2,0):- (border(P1,P2);border(P2,P1)).
crossedCountries(P1,P2,Num):-
(border(P1,Z);border(Z,P1)),
(crossedCountries(Z,P2,Num1);crossedCountries(P2,Z,Num1)),!,

Num is Num1 + 1.

当我必须跨越3个,4个或5个或5个国家时一切顺利,但如果它太远,它只会给我错误

ERROR: Out of local stack

有人可以指点我吗?

2 个答案:

答案 0 :(得分:1)

我注意到的第一行是代码片段#2的第四行:

(crossedCountries(Z,P2,Num1);crossedCountries(P2,Z,Num1)),!,

之前已经处理了对称性,我发现它只是至少循环的原因,但很可能是堆栈溢出错误。

    border(germany, france).
    border(france, spain).
    border(spain, portugal).

    crossedCountries(P1,P2,0):-
        border(P1,P2);
        border(P2,P1).

    crossedCountries(P1,P2,Num):-
        (
          border(P1,Z);
          border(Z,P1)
        ),
        crossedCountries(Z,P2,Num1),
        Num is Num1 + 1.

答案 1 :(得分:1)

这个问题是一个经典的图遍历问题,你想知道从一个特定节点到另一个特定节点的不同唯一路径(或者在这种情况下,只是两者之间的国家数)。

出现循环问题是因为您在确定路线时可能会多次访问同一个国家/地区(“节点”)。因此,如果有从A到B到C到D的路线,您最终可能会做A到B到A到B到C到B到C到B到A ......并且永远不会到达D.

不考虑此问题的解决方案可能如下所示:

border(germany, france).
border(france, spain).
border(spain, portugal).
border(germany, austria).
border(austria, slovakia).
border(slovakia, poland).
border(poland, germany).

bordering(Country1, Country2) :-
    border(Country1, Country2).
bordering(Country1, Country2) :-
    border(Country2, Country1).

crossedCountries(C1, C2, 0):-
    bordering(C1, C2).

crossedCountries(C1, C2, Num):-
    bordering(C1, Z),
    crossedCountries(Z, C2, Num1),
    Num is Num1 + 1.

你得到这样的结果:

| ?- crossedCountries(germany, spain, N).

N = 1 ? ;

N = 3 ? ;

N = 5 ? ;

...

这是因为有效途径是德国 - 法国 - 西班牙,德国 - 法国 - 德国 - 法国 - 西班牙等。

常见的补救措施是跟踪访问过的国家(“节点”)。这可以通过添加参数来跟踪它们来完成。另外,为了使结果更清晰,我添加了一个Path参数来查看通过国家/地区的实际解决方案路径(如果需要,可以省略此参数):

crossedCountries(P1, P2, [P1|Path], Num) :-
    crossedCountries(P1, P2, [P1], Path, Num).

crossedCountries(P1, P2, Visited, [P2], 0) :-
    neighbors(P1, P2),
    \+ member(P2, Visited).

crossedCountries(P1, P2, Visited, [Z|Path], Num) :-
    neighbors(P1, Z),
    \+ member(Z, Visited),
    crossedCountries(Z, P2, [Z|Visited], Path, Num1),
    Num is Num1 + 1.

现在查询结果如下:

| ?- crossedCountries(germany, spain, Path, N).

N = 1
Path = [germany,france,spain] ? ;

no
| ?- crossedCountries(germany, poland, Path, N).

N = 0
Path = [germany,poland] ? a

N = 2
Path = [germany,austria,slovakia,poland]

no
| ?-