Constraint Programming хорошо сочетается с Prolog, если вы придерживаетесь чистой логики.Но, как вы демонстрируете, нельзя свободно смешивать процедурные элементы, такие как cut (!) и if-then-else (->;) с логикой ограничения.
Использование if-then-else или сокращений безопасно только в том случае, если условие влечет за собой (то есть, безусловно, верно) или отключено (безоговорочно, ложно) в «время установки ограничения».На практике это означает, что такие условия не должны содержать проблемных переменных (переменных домена и т. Д.), А только проблемных параметров (констант), которые известны априори.Выделенные языки моделирования различают эти две вещи, но Пролог этого не делает.
Как НЕ выражать альтернативы в моделях ограничений
Вышеприведенное означает, что вы не можете использовать cut / if- затем - чтобы выразить альтернативу, которую вы хотели выразить.Может быть заманчиво просто избавиться от аспекта условного выбора условного выбора и переписать его как чистую дизъюнкцию.Например, вы можете переписать
( Usage #>= 1000 -> Rate#=7, Bonus#=100 % WRONG
; Rate#=9, Bonus#=0
)
как чистую дизъюнкцию
( Usage #>= 1000, Rate#=7, Bonus#=100 % INEFFICIENT
; Usage #< 1000, Rate#=9, Bonus#=0
)
Хотя теперь это логически правильно, не делайте этого!Пролог исследует альтернативы (выраженные с помощью точки с запятой (;) или нескольких предложений) с помощью обратного отслеживания, т. Е. С нетерпением сначала выбирая одну альтернативу, а затем возвращаясь к другой.Это обычно разрушает любую надежду на эффективную программу ограничения!В программе ограничений весь поиск должен находиться в подпрограмме поиска / маркировки.
Ограничения Reified
Если и условие, и ветви альтернатив являются ограничениями, которыеЕсли у вас есть реализованная реализация (т.е. реализация, которая может отражать истинность ограничения в булевой переменной), вам повезло: вы можете переписать всю условную альтернативу с помощью специальных связок для ограничений reified (в ECLiPSe: and
, or
, neg
, =>
, #=
).Для приведенного выше примера:
Usage #>= 1000 => Rate#=7 and Bonus#=100, % OK
Usage #< 1000 => Rate#=9 and Bonus#=0
или
Usage #>= 1000 and Rate#=7 and Bonus#=100 or % OK
Usage #< 1000 and Rate#=9 and Bonus#=0
К сожалению, только базовые арифметические ограничения имеют уточненные версии и могут комбинироваться таким образом!
Использование других встроенных ограничений
В некотором смысле, работа с альтернативами является наиболее сложной частью решения проблемы, и многие встроенные ограничения решают эту проблему.Поэтому стоит проверить, можно ли смоделировать проблему поверх существующих встроенных ограничений , при этом не имеет явных различий в модели.Кандидатами являются элемент / 3 , таблица / 2 . дизъюнктивный / 2 и многие другие.
Задержка выбора
Последнее решение - отложить исследование альтернатив до истиныусловие может быть решено однозначно.В ECLiPSe это проще всего с пунктами задержки.Используя пример OP:
delay choice(A, B) if var(A);var(B). % wait for A,B to be known
choice(A, B) :-
( (A>3 ; B>3) -> % can now use normal Prolog tests
write("expression 1")
;
write("expression 2")
).
Это работает, но будет действовать только после создания экземпляров A и B.Если, как и в этом случае, условие может быть исправлено, мы можем сделать несколько лучше:
choice(A, B) :-
Bool #= (A#>3 or B#>3),
delayed_choice(Bool).
delay delayed_choice(Bool) if var(Bool).
delayed_choice(1) :- write("expression 1").
delayed_choice(0) :- write("expression 2").
Это будет действовать, когда условие удовлетворяется доменами:
?- choice(A, B), B #> 3.
expression 1
Превращение общих дизъюнкций в ограничение
ECLiPSe имеет изящную функцию, называемую Обобщенное распространение в библиотеке (пропия) .Это может эффективно превратить дизъюнкции Пролога в ограничение, используя простую аннотацию.Начиная с правильной, но неэффективной формулировки выше, мы можем написать:
?- ( Usage #>= 1000, Rate#=7, Bonus#=100
; Usage #< 1000, Rate#=9, Bonus#=0
) infers most.
Usage = Usage{-1.0Inf .. 1.0Inf}
Rate = Rate{[7, 9]}
Bonus = Bonus{[0, 100]}
There is 1 delayed goal.
Yes (0.00s cpu)
Как показывают домены Rate
и Bonus
, полезная информация была извлечена из дизъюнкции, даже до применения альтернативной альтернативы.можно решить.