在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).
该计划的这一部分的目的是将每个班级与教师配对,这两个班级都具有教授班级的资格,并且在此期间不可用。它应该给出一个清单。
?- 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]]
如果你仔细观察,你会发现最后没有句号,也没有真/假的陈述。这将导致人们相信它是无限循环的。然而,情况并非如此,因为Bag矩阵已完全形成,我只需键入"。"结束程序(而不是,你知道,中止它)。
它只生成第一个有效的解决方案。为什么会这样?
答案 0 :(得分:0)
您已构建了test
谓词,以便为bagof/3
和needs(N)
的每个实例组合调用resources(R)
,因此它会收集make_bid
的每个结果在它自己的bagof/3
结果中:
ece3520 1 joel
Bag = [[ece3520, 1, tu, 11, 14, joel, _G4310]]
第一行是write
谓词中的make_bid
。对于Bag
/ make_bid
对,needs
的单个查询的resources
结果为_G4310
。列表中的最后一个参数_
发生是因为您的谓词使用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
的每个元素都是一个列表,其最后一个元素是一个匿名变量,因为这就是{{1}}的结构。