2012-04-12 3 views
2

Я пытаюсь использовать constrain X, чтобы не быть значением в списке.Использование in_set/2 Constraint

От SICStus Prolog manual:

?X in_set +FDSet 

Я не могу понять, как преобразовать список в FDSet, хотя. У меня есть список целых чисел [2,3,8,9], и я хочу ограничить домен переменной X тем, что не был в этом списке. Как мне это сделать? Благодарю.

ответ

4

Судя по documentation, а как насчет list_to_fdset/2? Вы можете перевести на FDSet, а затем построить его дополнение, а затем сообщение in_set/2. Если ваша версия не имеет list_to_fdset/2, вы можете легко преобразовать список в обычное выражение домена, а затем отправить отрицательное ограничение in/2. В вашем примере, вы бы тогда пост:

#\ X in {2}\/{3}\/{8}\/{9} 

и у вас есть только описать связь между списком и выражением домена, состоящим из одиночек, который легко:

list_domain([I|Is], Dom) :- 
     foldl(integer_domain_, Is, {I}, Dom). 

integer_domain_(I, D0, D0 \/ {I}). 

Пример запросы:

?- list_domain([1,2,3], Dom). 
Dom = {1}\/{2}\/{3}. 

?- list_domain([1,2,3], Dom), X in Dom. 
Dom = {1}\/{2}\/{3}, 
X in 1..3. 
+0

О: 'X in \ ({2} \/{3} \/{8} \/{9})' – false

0

Я реализовал один, как здесь ..

/** Constraint domain to memebers of a list (of numbers only) **/ 

domain_list_constraint(_, []) :- !. 
domain_list_constraint(DomainVar, List) :- member(E, List), 
           (atom(E)->atom_number(E, I), 
           DomainVar #= I; 
           DomainVar #= E). 
+2

Это * generate-and-test * и лишает силу ограничений. Точка 'in/2' должна детерминистически определять область переменной. Вместо обратного отслеживания (с 'member/2') вы должны детерминистически преобразовать список в выражение домена, а затем отправить одно ограничение' in/2', чтобы полностью использовать ограничения CLP (FD). – mat

+0

hmm ,, звучит хорошо !!! я увижу, смогу ли я реализовать этот путь. Спасибо за совет. –

Смежные вопросы