Пролог: foreach или forall для решения ограничений?

Я пытаюсь планировать проект с помощью пролога SWI и CLP. Мне удалось поддерживать последовательные зависимости, но я стараюсь избегать двойного бронирования людей.

У меня есть список с именем Schedule, содержащий такие элементы, как [taskname, starttime], где starttime - это свободная переменная для решателя ограничений. Они уже ограничены последовательными зависимостями.

Я пытаюсь написать такой цикл, чтобы исключить двойное бронирование:

  forall /* or maybe foreach*/ (isa(P,person), (
    % Filter scheduled tasks on that person...
    include(\[T,S]^(assigned(T,P)), Schedule, HisSchedule),
    % Present what serialized expects..
    maplist(\[T,S]^S^true, HisSchedule, Sts),
    % duration is just user-defined data... 
    maplist(\[T,S]^D^(duration(T,D)), HisSchedule, Dus),
    % Hit it...
    serialized(Sts, Dus)
  )),

С foreach он всегда терпит неудачу, а с другой - всегда успешно, ничего не ограничивая.

Расписание является глобальным, поскольку этот цикл касается, и цель состоит в том, чтобы ограничить его элементы времени начала, используя сериализованный. OTOH, HisSchedule, Sts и Dus зависят от конкретного человека. Поэтому я думаю, что мне нужен foreach, чтобы сделать расписание счастливым, но, в общем, сделать его счастливым. Это проблема? И если так, как я могу это исправить?

2 ответа

Решение

forall/2 встроенная функция предлагается некоторыми системами Prolog, она в значительной степени опирается на немонотонные конструкции и никогда не была разработана для совместной работы с ограничениями. То же самое верно для foreach/2 который пытается быть немного умнее.

Ответы, решения, ограничения

Итак, в чем здесь большая, фундаментальная проблема? Многие Пролог получили свою нынешнюю форму, когда ограничения не были широко известны. Таким образом, многие конструкции принимают успех цели как "да" как абсолютную истину. Но с ограничениями все немного по-другому. Успешная цель дает ответ, который теперь может вообще не содержать решения! По этой причине успех уже не тот, что раньше. Вот пример использования SICStus:

| ?- asserta(clpfd:full_answer).
yes
| ?- X mod 2 #= 1.
clpfd:(X mod 2#=1),
X in inf..sup ? 
yes
| ?- X mod 2 #= 1, X mod 2 #= 0.
clpfd:(X mod 2#=0),
clpfd:(X mod 2#=1),
X in inf..sup ? ;
no
| ?- X mod 2 #= 1, X mod 2 #= 0, X in 0..9.
no

Ответы теперь могут вообще не содержать решения, другими словами, они могут быть ложными.

В вашем примере include/3 очень проблематично, так как forall/2, Ах, а также setof/3 сходит с ума от ограничений:

| ?- setof(t, (I in 1..3 ; I in 3..5 ), _). % SICStus
yes

?- setof(t, (I in 1..3 ; I in 3..5 ),_).  % SWI
I = 3.

Если вообще, правильный ответ будет I in 1..5,

Чтобы решить эту проблему, сначала преобразуйте реляционные данные в списки:

   ...,
   setof(P, isa(P, person), Ps),
   maplist(perperson(P,Global),Ps),
   ...

Я сам исправил это так:

  findall(Per, isa(Per,person), People),
  maplist(nodoublebookings(Schedule),People),

nodoublebookings(Schedule, Per):-
  include(\[T,S]^(assigned(T,Per)), Schedule, HisSchedule),
  maplist(\[T,S]^S^true, HisSchedule, Sts),
  maplist(\[T,S]^D^(duration(T,D)), HisSchedule, Dus),
  serialized(Sts, Dus).

Почему-то я не мог писать nodoublebookings как лямбду.

Другие вопросы по тегам