Найти все решения в прологе
В прологе я пытаюсь объединить все действительные пары потребностей с ресурсами
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 полностью сформирована, и я могу просто напечатать "." завершить программу (вместо того, чтобы прервать ее).
Он только генерирует первое действительное решение. Почему это происходит?
1 ответ
Вы структурировали свой 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
структурирован.