Я полностью согласен с lurker данные организации данных. Кроме того, я бы сказал, что ваше заявление о проблеме заставляет меня думать о комбинаторной оптимизации.В этом случае я всегда рекомендую сформулировать его как CSP с использованием Constraint Programming и использоватьProlog (CLP (FD)).
Constraint Satisfaction Проблемы
Вообще говоря, проблемы CP являются те, которые состоят из:
- набор X = {x_1, x_2, ..., x_n} переменных.
- Коллекция D = {D (x_1), D (x_2), ..., D (X_n)} доменов на каждой переменной, то есть: множество значений, что эти переменные могут быть назначены к (например, D (x_i) = {1, 2, 3})
- Множество с ограничений между переменными (например, A> B)
раствор к Задача ограничения ограничений (CSP) - это назначение val ues {x_1 = V_1, x_2 = V_2, ..., x_N = V_N}, который удовлетворяет всем ограничениям в C. Это суть. Если вы хотите узнать больше об этих проблемах, я предлагаю вам найти книгу в вашей местной библиотеке, должно быть много.
Я бы рекомендовал вам использовать эту формулировку, потому что библиотеки CLP (FD) имеют решатели, которые могут быть использованы для поиска решения проблем, сформулированных в CP. Используя CP, вы можете структурировать свою программу в следующих частях:
- Определение проблемы: определить начальные домены переменных решения.
- Применить набор ограничений. То есть: «свяжите» свои переменные с условиями, которые должны быть выполнены.
- Позвоните в решатель, который автоматически присваивает значения вашим переменным решения в указанном домене и удовлетворяет всем вашим ограничениям.
Реализация СНТ в Прологе
Я написал небольшой пример, чтобы показать вам, как это будет сделано в SWI-Prolog. Начнем с того, я предполагаю, что вы структурировать входные данные следующим образом:
course(ece2090,1,m,13,16).
course(ece3520,1,tu,11,14).
course(ece4420,1,w,13,16).
ta(joel, [ece2090,ece2010,ece3520,ece4420], [m([13,16])]).
ta(sam, [ece2090,ece4420],[]).
ta(pete, [ece3520],[w([13,16])]).
ta(alan, [ece3520],[m([13,16],[19,21]),w([12,14])]).
Обратите внимание, что я позволившая наличность каждый ТОТ, чтобы быть немного более сложным, чем в ваших исходных спецификациях. Поскольку вы хотите найти все возможные решения своей проблемы, я буду кодировать решение как список списков, где каждый внутренний список может принимать значение от 0 до 1 (это переменные «», домен). Каждый внешний список соответствует каждому курсу, тогда как внутренние списки соответствуют назначениям TA для этого конкретного курса.
% TA1, TA2, ...
Assignments = [ [1, 0, ...] , % Course 1
[0, 1, ...] , % Course 2
[0, 0, ...] | ... ] % ...
Если бы мы имели только 2 ТЕ (скажем, Джоэл и Сэм), указанное решение будет означать, что Джоэл назначен на первый курс в то время как Сэм относятся ко второму. Что вы хотите сделать, так это определить неограниченные переменные с доменом 0..1
, применить все необходимые ограничения, а затем автоматически решить его (т. Е. ярлык).
timetable(ASs) :-
findall(C, course(C,_,_,_,_), Cs), % Gets all courses.
findall(TA, ta(TA,_,_), TAs), % Gets all T.A.'s
length(TAs, Nta),
assign(Cs, TAs, Nta, ASs), % ASs is a list of assignments.
append(ASs,Xs),
sum(Xs,#>,0), % Applies an extra constraint
% to discard solutions with no
% assignments.
label(Xs). % Starts the solver.
Здесь assign/4
генерирует список назначений, как определено выше. Однако значения не связаны ни 0, ни 1. В списке ASs
будет выглядеть примерно так:
% TA1, TA2, ...
Assignments = [ [X1, 0, ...] , % Course 1
[ 0, X1, ...] , % Course 2
[ 0, 0, ...] | ... ] % ...
В сущности, assign/4
предикат просто помещая 0
для каждого элемента TA-конечно, что не соответствует, a priori, любое из условий (т.е. присвоение - 0
, если у TA нет полномочий для обучения курсу или если он/она занят в это конкретное время).
Если бы это была ваша домашняя работа, я предлагаю вам прекратить читать здесь и попытаться обеспечить вашу собственную реализацию assign/4
. Я оставлю свое, если вы не знакомы с CP или хотите найти немного вдохновения. Я использовал предикат available(?TA,+C)
, который преуспевает, когда преподаватель TA
доступен для обучения курсу C
и имеет необходимые полномочия для этого. Кроме того, предикат assign_(?Xs:list, +TAs:list, ?Ms:list)
является простым предикатом, который свяжет переменные (X
) с 0, когда TA
не является членом списка доступных TA в Ms
.
assign([], _, _, []). % Stops recursion.
assign([C|Cs], TAs, Nta, [AS|ASs]) :- % Iterates through courses.
length(AS, Nta), % Generates a new list with Nta elements.
AS ins 0..1, % Sets the domain for each element in the list.
findall(TA, available(TA,C), Ms), % Finds all possible TA's for course C.
assign_(AS, TAs, Ms), % Ms now has 0s for the unavailable TA's.
sum(AS, #=<, 1), % Sets a constraint: only one TA can be assigned to a course.
assign(Cs,TAs,Nta,ASs). % Continues for the rest of courses.
% Helper predicate:
assign_([],[],_).
assign_([_|Xs],[TA|TAs],Ms) :-
memberchk(TA,Ms),
assign_(Xs,TAs,Ms).
assign_([0|Xs],[_|TAs],Ms) :-
assign_(Xs,TAs,Ms).
См. sum/3
, чтобы понять, как применяются ограничения. Чтобы завершить программу, вам просто нужно обеспечить реализацию предиката available/2
. Затем, следующий вызов даст вам один ответ:
?- timetable(Solution).
Если вы хотите, чтобы каждые из возможных решений, вы бы просто использовать findall/3
снова:
?- findall(S, timetable(S), AllSolutions).
Я действительно не проверил мои программы, ее был предназначен только для иллюстрации, но, надеюсь, вы найдете его полезным в любом случае.
ПРИМЕЧАНИЕ: Помните, что комбинаторные проблемы (и особенно этот, в котором вы хотите все решения) являются вычислительно сложными. Я предполагаю, что вы хотите найти тех, кто позже оптимизирует ваше расписание. В этом случае я бы посоветовал вам сделать это в самой программе (т. Е. labeling/2
).
Будет ли [[ece2090,1, sam], [ece3520,1, joel], [ece4420,1, joel]] 'считаться действительным? И «НЕТ» действительно разрешено для ТА в правильном решении? Может ли более одного из них быть «НЕТ»? – lurker
Пока что ни одно из них не является желательным, но являются решениями в том смысле, что они правильны по форме. Это то, что я имел в виду. Я хочу отобразить все решения, тогда я попытаюсь сузить набор решений. Я собираюсь в порядке, хотя. – PowerOfKaishin