在序言中找到所有解决方案

Finding all solutions in prolog

在序言中,我试图统一每一个有效的需求与资源配对

needs([ece2090,1,m,13,16]).
needs([ece3520,1,tu,11,14]).
needs([ece4420,1,w,13,16]).

resources([joel, [ece2090,ece2010,ece3520,ece4420],[[m,13,16]]]).
resources([sam, [ece2010,ece4420],[]]).
resources([pete, [ece3520],[[w,13,16]]]).

使用这个公式

make_bid([Class,Sect,Day,Ts,Te],[Name,Cap,Unavail],[Class,Sect,Day,Ts,Te,Name,_]) :-
no_conflict_all_unavailable(Day,Ts,Te,Unavail),
course_capable(Class,Cap),
writef('%w %w %w\n',[Class,Sect,Name]),
fail.

和运行完成此测试。

test(Listing) :- needs(N), resources(R), make_bid(N,R,Listing).

该计划这部分的重点是将每个 class 与一位既有资格教授 class 并且在此期间没有空的老师配对。它应该给出一个列表。

?- test(Listing).
ece3520 1 joel
ece3520 1 pete
ece4420 1 joel
ece4420 1 sam
false.

当运行时,生成以上。这是正确的,但它采用的格式对我来说毫无用处,因为我需要它成为自己的变量才能进行进一步的计算。那么解决办法就是用bagof或者findall吧?

所以我从程序的主体部分删除了 fail 子句,然后将测试更改为此

test(Bag) :- needs(N), resources(R), bagof(Listing,make_bid(N,R,Listing),Bag).

但它生成了这个

ece3520 1 joel
Bag = [[ece3520, 1, tu, 11, 14, joel, _G4310]] 

如果仔细观察,您会发现结尾没有句号,也没有 true/false 语句。这会使人相信它是无限循环的。然而,情况并非如此,因为 Bag 矩阵已完全形成,我可以简单地键入“.”。结束程序(而不是,你知道的,中止它)。

它只生成第一个有效的解决方案。为什么会这样?

您已经构建了 test 谓词,以便为 needs(N)resources(R) 的每个实例组合调用 bagof/3,因此它收集 [=] 的每个结果18=] 在它自己的 bagof/3 结果中:

ece3520 1 joel
Bag = [[ece3520, 1, tu, 11, 14, joel, _G4310]]

第一行是 make_bid 谓词中的 write。第二行是一对 needs/resourcesmake_bid 的单个查询的 Bag 结果。列表中的最后一个参数 _G4310 出现是因为您的谓词使用 _ 并且它是匿名的(从不 used/instantiated)。

您当前的 make_bid 旨在循环写入结果,而不是在多个回溯中实例化它们。所以可以改为:

make_bid([Class, Sect, Day, Ts, Te], [Name, Cap, Unavail], [Class, Sect, Day, Ts, Te, Name, _]) :-
    no_conflict_all_unavailable(Day, Ts, Te, Unavail),
    course_capable(Class, Cap).

(注意:我不确定为什么在第 3 个列表参数的末尾有 _。它代表什么?)

如果你想将整个结果收集在一个列表中,那么你可以使用 findall/3:

findall([Class, Sect, Name], (needs(N), resources(R), make_bid(N, R, [Class, Sect, _, _, _, Name, _]), Listings).

这将收集看起来像 [Class, Sect, Name] 的元素列表。您可以在此处使用 bagof/3,但您需要为不想绑定的 make_bid/3 调用中的变量提供一个存在量词。

如果您想要整个 Listing 列表,则:

findall(L, (needs(N), resources(R), make_bid(N, R, L)), Listings).

但是 Listings 的每个元素都是一个列表,其最后一个元素是一个匿名变量,因为这就是 make_bid/3 的结构。