Вы можете проверить состояние конечной доменной переменной с помощью функций в модуле FD.reflect
. Функция FD.reflect.dom
кажется особенно полезной в этом контексте.
Чтобы получить текущий домен каждого поля в записи, вы можете сопоставить эту функцию с записями:
declare
fun {GetDomains Vec}
{Record.map Vec FD.reflect.dom}
end
Первоначальный результат в вашем примере будет:
vec(a:[1#100] b:[1#100] c:[1#100])
Теперь вы можете сравнить результат этой функции до и после добавления ограничений, чтобы увидеть, если что-нибудь произойдет.
Два ограничения:
- Это будет работать только с ограничениями, которые фактически изменяют домен хотя бы одной переменной. Некоторые ограничения изменяют хранилище ограничений, но не изменяют никакие домены, например ограничение равенства с несвязанной переменной.
- Использование такого отражения плохо работает с параллелизмом, то есть, если ограничения добавляются из нескольких потоков, это приведет к условиям гонки.
Если вам нужен пример использования функции GetDomains
в цикле, дайте мне знать ...
РЕДАКТИРОВАТЬ: С подсказкой из старого сообщения списка рассылки я пришел к этому общему решению, которое должно работать со всеми типами ограничений. Он работает путем умозрительного выполнения ограничения в подчиненном вычислительном пространстве.
declare
Vec = vec(a:{FD.int 1#100} b:{FD.int 1#100} c:{FD.int 1#100})
%% A number of constraints as a list of procedures
Constraints =
[proc {$} Vec.a <: 50 end
proc {$} Vec.b =: Vec.a end
proc {$} Vec.b <: 50 end
proc {$} Vec.a =: Vec.b end
]
%% Tentatively executes a constraint C (represented as a procedure).
%% If it is already entailed by the current constraint store, returns false.
%% Otherwise merges the space (and thereby finally executes the constraint)
%% and returns true.
fun {ExecuteConstraint C}
%% create a compuation space which tentatively executes C
S = {Space.new
proc {$ Root}
{C}
Root = unit
end
}
in
%% check whether the computation space is entailed
case {Space.askVerbose S}
of succeeded(entailed) then false
else
{Wait {Space.merge S}}
true
end
end
for C in Constraints I in 1..4 break:Break do
{System.showInfo "Trying constraint "#I#" ..."}
if {Not {ExecuteConstraint C}} then
{System.showInfo "Constraint "#I#" is already entailed. Stopping."}
{Break}
end
{Show Vec}
end
{Show Vec}