CLP – (Constraint Logic Programs) Programação Lógica com Restrições Ruben Carlo Benante Doutorando em Ciência da Computação pelo CIn – UFPE, Recife-PE Mestre em Filosofia pela UNESP, Marília-SP Bacharel em Ciência da Computação pela UNESP, S.J.Rio Preto-SP [email protected]Disciplina de MCI Prof. Jacques Robin Baseado nas transparências disponibilizadas na internet por Marriott & Stuckey
97
Embed
CLP – (Constraint Logic Programs) Programação Lógica com Restrições
CLP – (Constraint Logic Programs) Programação Lógica com Restrições. Ruben Carlo Benante Doutorando em Ciência da Computação pelo CIn – UFPE, Recife-PE Mestre em Filosofia pela UNESP, Marília-SP Bacharel em Ciência da Computação pela UNESP, S.J.Rio Preto-SP [email protected] Disciplina de MCI - PowerPoint PPT Presentation
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
CLP – (Constraint Logic Programs)Programação Lógica com Restrições
Ruben Carlo Benante Doutorando em Ciência da
Computação peloCIn – UFPE, Recife-PE
Mestre em Filosofia pela UNESP, Marília-SP
Bacharel em Ciência da Computação pela UNESP, S.J.Rio Preto-SP
[email protected] Disciplina de MCI Prof. Jacques Robin Baseado nas transparências
disponibilizadas na internet por Marriott & Stuckey
Capítulo 4: Programação Lógica com Restrições Restrições Definidas pelo Usuário Programando com Regras Avaliação Árvores de Derivação e Falhas
Finitas Avaliação de Objetivos Árvores de Derivação Simplificadas O esquema CLP
Capítulo 7: Controle de Busca Estimando a eficiência de um
programa CLP Ordenando as Regras Ordenando os Literais Adicionando Restrições Redundantes Minimização
Capítulo 8: Modelos com Domínios Finitos Domínios e Rótulos Restrições Complexas Rotulando (Labelling) Modelando Problemas Diferentes
Capítulo 4: Restrições Definidas pelo Usuário (RDU) Muitos exemplos de modelagem podem
ser particionados em duas partes: Uma descrição geral do objeto ou processo Uma informação específica sobre uma
situação real O programador deve ser capaz de definir
suas próprias restrições específicas ao problema
As Regras permitem isso
Regras
II1
I2
V+
--3_--
--
VR1 R2
Uma RDU para definir o modelo de circuito elétrico:parallel_resistors(V,I,R1,R2)
parallel_resistors(V,I,R1,R2) :-
V = I1 * R1, V = I2 * R2, I1 + I2 = I.
E uma regra definindo-a:
Usando Regrasparallel_resistors(V,I,R1,R2) :-
V = I1 * R1, V = I2 * R2, I1 + I2 = I.
Comportamento com resistores de 10 e 5 Ohmsparallel_resistors( , , , )V I R R R R1 2 1 10 2 5
Comportamento com bateria de 10V, com resistores iguaisparallel_resistors( , , , )10 I R R
Isso representa a restrição: (substituição macro)10 1 10 2 1 2 I R I R I I I
Restrições Definidas pelo Usuário (RDU) RDU: p(t1,...,tn) onde p é um predicado
n-ário e t1,...,tn são expressões literal: uma restrição primária ou RDU objetivo (goal): uma seqüência de
literais L1,...,Lm regra: A :- B onde A é RDU e B é um
objetivo programa: uma seqüência de regras
Renomeação (Renamings) Uma renomeação r é um mapa bijetivo de
variáveis em variáveis Um objeto sintático é uma restrição, um
RDU, um objetivo ou uma regra Aplicar uma renomeação em um objeto
sintático nos dá um objeto com cada variável x substituída por r(x)
variante o’ de um objeto o tem sua renomeação como r(o’)=o
Não é substituição de macros
Reescrita de RDU objetivo G da forma (ou vazio m=0 [])
L1, ..., Li-1, Li, Li+1, ..., Lm Li é da forma p(t1,...,tn) R é da forma p(s1,...,sn) :- B r é a renomeação das variáveis em r(R) e
não em G A reescrita de G com Li por R usando a
renomeação r é L1,...,Li-1,t1=r(s1),...,tn=r(sn),r(B),Li+1,...,Lm
Programando com Regras
Considere a função fatorial. Como poderemos escrever regras para o predicado fac(N,F) onde(F = N!) ?
NN
N N N!
( )!
1 01 1
if if
(R1) fac(0,1).(R2) fac(N,N*F) :- N >= 1, fac(N-1, F).
Note que a definição é recursiva (em termos dela mesma) e imita a definição matemática
Programando com Regras
(R1) fac(0,1).(R2) fac(N,N*F) :- N >= 1, fac(N-1, F).
Reescrevendo o objetivo fac(2,X) (i.e. o que é 2!)fac X( , )2fac X
RN X N F N fac N F
( , )
, , , ( , )
2
22 1 1
fac X
RN X N F N fac N F
RN X N F N N N F N F N fac N F
( , )
, , , ( , )
, , , ' , ' ' , ' , ( ' , ' )
2
22 1 1
22 1 1 1 1
fac X
RN X N F N fac N F
RN X N F N N N F N F N fac N F
RN X N F N N N F N F N N F
( , )
, , , ( , )
, , , ' , ' ' , ' , ( ' , ' )
, , , ' , ' ' , ' , ' , '
2
22 1 1
22 1 1 1 1
12 1 1 1 1 0 1
Simplificado na variável X, a resposta é X = 2
Avaliação (Evaluation) Em cada passo da reescrita, deveremos
checar se a conjunção de restrições primitivas pode ser satisfeita
A derivação faz isso Em cada passo, os literais…
Restrição primitiva: são adicionados ao lado direito (das restrições)
RDU: são reescritos
Avaliação estado: <G1| C1> onde G1 é um objetivo
e C1 é uma restrição Passo de derivação: G1 é L1, L2, ..., Lm
L1 é uma restrição primitiva, C2 is C1 /\ L1•Se solv(C /\ L1) = false então G2 = [] •Senão G2 = L2, ..., Lm
L1 é uma RDU, C2 é C1 e G2 é a reescrita de G1 com L1 usando alguma regra e a renomeação
Avaliação derivação de <G0 | C0>:
Onde cada <Gi | Ci> até <Gi+1 | Ci+1> é um passo de derivação
derivação de G é a derivação do estado <G | true>
G C G C G C0 0 1 1 2 2| | |
Derivação de fac(1,Y)fac Y true( , )|1fac Y true
R
N Y N F N fac N F true
( , )|
, , , ( , )|
1
2
1 1 1
fac Y trueR
N Y N F N fac N F true
Y N F N fac N F N
( , )|
, , , ( , )|
, , ( , )|
12
1 1 1
1 1 1
fac Y trueR
N Y N F N fac N F true
Y N F N fac N F N
N fac N F N Y N F
( , )|
, , , ( , )|
, , ( , )|
, ( , )|
12
1 1 1
1 1 1
1 1 1
fac Y trueR
N Y N F N fac N F true
Y N F N fac N F N
N fac N F N Y N F
fac N F N Y N F N
( , )|
, , , ( , )|
, , ( , )|
, ( , )|
( , )|
12
1 1 1
1 1 1
1 1 1
1 1 1
fac Y trueR
N Y N F N fac N F true
Y N F N fac N F N
N fac N F N Y N F
fac N F N Y N F NR
N F N Y N F N
( , )|
, , , ( , )|
, , ( , )|
, ( , )|
( , )|
, |
12
1 1 1
1 1 1
1 1 1
1 1 11
1 0 11 1
fac Y trueR
N Y N F N fac N F true
Y N F N fac N F N
N fac N F N Y N F
fac N F N Y N F NR
N F N Y N F N
F N Y N F N N
( , )|
, , , ( , )|
, , ( , )|
, ( , )|
( , )|
, |
|
12
1 1 1
1 1 1
1 1 1
1 1 11
1 0 11 1
11 1 1 0
fac Y trueR
N Y N F N fac N F true
Y N F N fac N F N
N fac N F N Y N F
fac N F N Y N F NR
N F N Y N F N
F N Y N F N N
( , )|
, , , ( , )|
, , ( , )|
, ( , )|
( , )|
, |
|
[]|
12
1 1 1
1 1 1
1 1 1
1 1 11
1 0 11 1
11 1 1 0
1
N Y N F N N F1 1 0 1
Resposta simplificada em Y é Y = 1
Derivações Para a derivação iniciando em <G0 | C0> Estado de sucesso: <[] | C> onde solv(C) !
= false Derivação de sucesso: o último estado é
de sucesso resposta: simpl(C, vars(<G0 | C0>)) Estado de falha: <[] | C> onde solv(C) =
false Derivação falha: o último estado é de falha
Árvores de derivação Árvore de derivação para o objetivo G
Raíz é < G | true > Os filhos de cada estado são estados
alcançáveis em um passo de derivação Codifica todas as possíveis derivações Quando o literal mais à esquerda é uma
restrição primitiva, somente há um filho Caso contrário, os filhos estão ordenados
conforme a ordem das regras
Exemplo de Árvores de Derivação fac Y true
R RY true N Y N F N fac N F true
Y N F N fac N F C N
N fac N F C C Y N F
fac N F C C NR R
N F C N N F N F N
( , )|
, | , , , ( , )|
[]| , , ( , )|
, ( , )|
( , )|
, | ' , ' ' ,
11 2
1 0 1 1 1 1
1 0 1 1 1 1
1 1 2 1
1 3 2 11 2
1 0 1 3 1
' , ( ' , ' )|
| ' ' , ' , ( ' , ' )| '
[]| ' , ( ' , ' )| ' '
[]| '
1 1 3
1 4 3 1 0 1 1 6 3 1
5 4 1 1 1 7 6
8 7 1
fac N F C
F C C N F N F N fac N F C C N N
C C F N fac N F C C F N F
C C N
Derivação falhou
Derivação falhou
resposta: Y = 1
Árvore de Derivação O exemplo anterior mostrou três
derivações, 2 falharam e uma foi bem sucedida
Falha finita: Se a árvore de derivação é finita e todas as derivações falham
Árvore de Derivação Infinita: algumas derivações são infinitas
Exemplo de árvore de derivação infinita(S1) stupid(X) :- stupid(X).(S2) stupid(1).
stupid X trueS S
X X stupid X true X true
stupid X X X XS S
X X stupid X X X X X X
stupid X X X X X X X XS S
( )|
' , ( ' )| |
( ' )| ' []|
' ' ' , ( ' ' )| ' ' | '
( ' ' )| ' ' ' ' []| ' '
1 21
11 2
1
11 2
Resposta: X=1
Resposta: X=1
Derivação Infinita
Avaliação de Objetivos A Avaliação de um objetivo realiza uma busca
em profundidade, e na direção da esquerda para a direita
Quando encontra um estado de sucesso, o sistema retorna a resposta
O usuário pode perguntar por outras respostas, o que faz a busca continuar
A execução pára quando o usuário não pede mais respostas ou a árvore inteira é explorada
A execução entra em laço infinito se a árvore é infinita e não apresenta resposta
Árvores de Derivação Simplificadas As árvores de derivação são muito
grandes Uma forma simplificada tem a
informação considerada mais útil Restrições na forma simplificada
(variáveis na forma do objetivo inicial, e como parte dos estados do objetivo)
Remoção de estados sem interesse
Estados Simplificados Estado simplificado: <G0 | C0> na
derivação de G substitua C0 por C1=simpl(C0, vars(G,G0)) se x=t em C1 substitua x por t em G0 levando
à G1 substitua C1 por C2=simpl(C1, vars(G,G1))
Exemplo fac N F N Y N F N N N F FY N F
fac N F N Y FN
fac F Y F
( ' , ' )| ' 'vars { , ' , '}
( ' , ' )| ' ''
( , ' )| '
1 1 1 1
1 0
1
replace by 0 and simplify again
Derivação Simplificada Um estado é critico se ele é o primeiro
ou o último estado de uma derivação, ou se o primeiro literal é uma RDU
Uma derivação simplificada para o objetivo G contém todos os estados críticos na forma simplificada
Similarmente para uma árvore de derivação simplificada
Exemplo de Árvore Simplificada
fac Y trueR R
false fac F Y FR R
Y false
( , )|
[]| ( , )|
[]| []|
11 2
01 2
1
Nota: estados de falha são <[] | false> e estados de sucesso contém as respostas
O Esquema CLP O esquema define uma família de
linguagens de programação Uma linguagem CLP(X) é definida por
Domínio de restrição X Resolvedor para o domínio de restrição X Simplificador para o domínio de restrição X
Nos exemplos usamos CLP(Real) Outro exemplo seria o CLP(Tree)
CLP(R)
Os elementos são árvores contendo constantes reais
Restrições são para árvores e para aritimética
{ , }
{ , , , , }
Capítulo 5: Modelando Escolha as variáveis que serão
usadas para representar os parâmetros do problema (isto pode ser trivial ou difícil)
Modele as relações idealizadas entre estas variáveis usando as restrições primitivas disponíveis no domínio
Exemplo de Modelagem
W
P
Uma viajante deseja atravessar o rio infestado de tubarões tão rápido quanto possível. A rota mais rápida é atravessar o rio nadando em linha reta, deixando que a correnteza faça a parte dela livremente. Ela deseja saber onde (P) ela vai parar após essa tarefa?
Largura do rio: WVelocidade do rio: SPosição da nadadora: PVelocidade da nadadora: R
R
S
Exemplo de ModelagemRaciocínio: enquanto a nadadora atravessa o rio na sua largura, gastando um tempo T, ela segue junto com a correnteza para o rio abaixo uma distância P dada pela velocidade do rio, com o mesmo tempo T. Daí o modelo:river(W, S, R, P) :- T = W/R, P = S*T.
Supondo que ela nade a R=1.5m/s, a velocidade do rio é de S=1m/s e seu comprimento é de W=24m.
river(24, 1, 1.5, P).
A única resposta é P = 16 Largura do rio: WVelocidade do rio: SPosição da nadadora: PVelocidade da nadadora: R
Exemplo de Modelagem (cont.)
Se ela nada numa velocidade entre 1 e 1.3 m/s e não pode se afastar mais que 20m do ponto de origem, será que ela conseguirá?
1 <= R, R <= 1.3, P <= 20, river(24,1,R,P).
Esta é a flexibilidade do modelo baseado em restrições!
Escolhas mais complicadas
Uma opção de “call” dá ao seu portador o direito de comprar 100 ações a um preço de exercício E fixo
Uma opção de “put” dá ao seu portador o direito de vender 100 ações a um preço de exercício E fixo
O pagamento (lucro ou prejuízo) de uma opção é determinado por seu custo C e pelo preço corrente da ação S
e.g. custo do call C=$200, Exercício E=$300 Preço do mercado = $2, não utiliza o call:
• pagamento = -$200 Preço do mercado = $9, utiliza o call:
• pagamento = $400
0 1 2 3 4 5 6 7call, buying
call, selling-200-100
0100200
Opções de Mercadocall C=200, E = 300 put C=100, E = 300
0 1 2 3 4 5 6
butterfly-100-50
050
100
Operação Borboleta: Compre um “call” por C=100 com E=500 e outro por C=400 com E=100. Venda dois “calls” por C=200, com E=300
0 1 2 3 4 5 6 7put, buying
put, selling-200-100
0100200
Opções de MercadoPG= S – E – C (para compra de “call”)PG = E + C – S (para venda de “call”)
MU primeiro arg fixo segundo livre sumlist([1],S). L=[1,2],S > Z, sumlist(L,S).
Estados na árvore de derivação com a chamada de sumlist<sumlist([1], S)|true><sumlist(L’,S’)|[1]=[N’|L’]/\S=N’+S’><sumlist(L’’,S’’)|[]=[N’’|L’’]/\S’=N’’+S’’><N’’=0,S’’=0|/\S’=N’’+S’’>
Coloque regras que “parecem levar a respostas rápidas” antes (acima) das outras
(isto tende a mover os estados de sucesso para a esquerda da árvore)
Ordenando Literais Restrições Primitivas
Coloque uma restrição no ponto mais à esquerda possível no qual ela poderia causar uma falha (para um determinado MU)
fac(N,F) com N fixo e F livrefac(N, F) :- N = 0,F = 1.fac(N, FF) :- N >= 1, FF = N * F,
N1 = N - 1, fac(N1, F).
fac(N, F) :- N = 0,F = 1.fac(N, FF) :- N >= 1, N1 = N - 1,
fac(N1, F), FF = N * F.
Ordenando Literais RDU:
Coloque os literais determinísticos antes dos outros
determinístico: o literal p(s1,...,sn) em um programa é determinístico para uma árvore de derivação se a cada ponto de escolha onde ele é reescrito, todas as derivações falham, exceto uma, antes da reescrita da RDU (em outras palavras: no máximo uma tem sucesso)
Predicados Deterministicos sumlist(L,S) é determinístico para o MU L
fixo e S livre. Não é para L livre e S fixo. sum(N,S) é similar Predicados determinísticos requerem
menos busca para achar uma resposta CUIDADO! Mover predicados pode mudá-
lo de determinístico para não_determinístico (o bom é que o inverso também é válido!)
Adicionando Restrições Redundantes Uma restrição que pode ser removida de uma
regra sem alterar as respostas válidas de uma árvore é chamada de redundante. (Pode alterar a ordem.)
Restrição de Resposta Redundante (ARC): o mesmo conjunto de respostas para: H :- L1, ..., Li, Li+1, ..., Ln H :- L1, ..., Li, r, Li+1, ..., Ln
Vantagem (para um conjunto de restrições C, num MU) <L1,...,Li,r|C> falha, mas não <L1,...,Li|C>
Adicionando Restrições Redundantes (ARC)
A restrição N >= 1 adicionada ao programa sum é uma ARC.
Outro exemplo: sum(N,7) (novo MU)sum N true
Ssum N S N N S N N
Ssum N S N N S N N
Ssum N S N N S N N
Ssum N S N N S
( , )|
( ' , ' )| ' ' ' '
( ' ' , ' ' )| ' ' ' ' ' ' ' '
( ' ' ' , ' ' ' )| ' ' ' ' ' ' ' ' ' ' ' '
( ' ' ' ' , ' ' ' ' )| ' ' ' ' ' ' ' '
78
1 6 08
2 4 2 08
3 1 3 08
4 3
4 0N N' ' ' ' ' ' ' '
Adicionando Restrições Redundantes (ARC)Sabemos que cada soma é não-negativa
Exemplo de MinimizaçãoObjetivominimize(leaf(t(a),X,D), D):Após encontrar X = h /\ D = 3, o objetivofica:D < 3, leaf(t(a),X,D), o que faz quenunca se visite nós com profundidadesuperior a 3 (?)
h
j k
i
d
m
o p
n
l
e
b
f
s r
q r
g
c
a
falseDDL
DDXktleafL
DDXitleafL
DDXdtleafL
DDXbtleafL
DDXatleaf
trueDXatleafD
)043([]1
3)4,),((3
3)3,),((3
3)2,),((2
3)1,),((2
3),),((
),),((,3
Exemplo de MinimizaçãoMelhore o leaf para o MU com D limitado superiormente: adicione uma ARC
Minimização A busca pode nem sempre ser beneficiada
pelos limites e.g. minimize(leaf(t(a),X,D), -D) Ainda deve visitar todos os nós antes de achar
um nó folha de maior profundidade A formulação original é superior, uma vez que
envolve menos restrições (a restrição redundante D>=0 não diminui o espaço de busca)
Conceito-Chave: lembre-se do MU de E<m, G, com m fixo.
Capítulo 8: Domínios e Rótulos
Novos requisitos: precisamos definir os domínios e as variáveis aritmético X :: [1,2,3,4] ou X :: [1..4] não-aritmético X :: [red, blue, yellow] multiplas variáveis [X,Y,Z] :: [0..10]
Se nenhum domínio é dado, é usado o padrão, por exemplo [-10000..10000]
Exemplo de DomíniosObjetivo para o problema do peso da sacola do contrabandista:[W,P,C] :: [0..9], 4*W + 3*P + 2*C <= 9,15*W + 10*P + 7*C >= 30.
O sistema CLP(FD) retorna unknown.
Mas como achar uma solução?
Devemos chamar um resolvedor completo (com backtracking)
D W D P D C( ) [ .. ], ( ) [ .. ], ( ) [ .. ] 0 2 0 3 0 4
Rótulos (Labelling) O predicado interno labeling chama
o resolvedor de restrições completo labeling(Vs) toma uma lista de
variáveis de domínio finito Vs e encontra uma solução
Forma típica de um programa de domínio finito Variáveis e domínios são definidos As restrições que modelam o problema são dadas O labeling é adicionado para chamar o resolvedor
completo A minimização pode ser aplicada no labeling Exemplo:
Observe: 3 variáveis estão fixadas e todos os domínios estão reduzidos. O labeling tenta S=0, S=1, ..., S=8 (que falham imediatamente) e então S=9. Depois E=0, E=1, E=2, E=3 (que falham imediatamente) e E=4 (que eventualmente falha), então E=5 dá como resposta:
O labeling tentaria primeiro S, M, O (a escolha já está dada pelo domínio). Melhor que E ou N. Muito melhor que Y primeiro.
Escolha do Valor do Domínio O valor da variáveis somente afeta a
ordem em que os ramos da árvore é explorado
Conhecimento específico do problema pode levar a uma busca mais rápida da solução
Também é importante para a otimização: Boas soluções encontradas cedo reduzem a
busca posterior
Eficiência da Rotulagem Podemos utilizar ambas ordenações
(de variáveis e de valores) juntas
10--19
30--39
50--59
70--79
1
10
100
1000
10000
DefaultFirst-failMiddleout
Número de escolhas diferentes para o problema dasN-Rainhas com estratégias diferentes
• Padrão• Primeira a falhar• Primeiro no meio
Divisão de Domínios(Domain Splitting)
O labeling não precisa ser do tipo Ligar uma variável a um valor
Ele simplesmente deve reduzir o domínio de uma variável
Divisão de Domínios divide o domínio corrente de uma determinada variável pela metade
Modelando diferentemente o (mesmo) Problema Visões diferentes de um problema levam
a diferentes modelos Modelos diferentes = Conjunto de
variáveis diferentes Dependendo das capacidades do
resolvedor, um modelo pode requerer menos busca que outro para achar uma resposta
A comparação empírica pode ser a medida do tempo ou esforço gasto
Modelando diferentemente o (mesmo) Problema
Problema de simples atribuição: quatro trabalhadores w1,w2,w3,w4 e quatro produtos p1,p2,p3,p4. Atribua um produto a um trabalhador de modo que o lucro L >= 19
p p p pwwww
1 2 3 41 7 1 3 42 8 2 5 13 4 3 7 24 3 1 6 3
A matriz de Lucro é:
Modelo 1: Pesquisa de Operações
p p p pwwww
1 2 3 41 7 1 3 42 8 2 5 13 4 3 7 24 3 1 6 3
16 variáveis booleanas Bij significando que otrabalhador i está com o produto j
193632734
528437
1
1
44434241
34333231
24232221
14131211
4
14
1
4
14
1
PBBBBBBBBBBBBBBBB
P
B
B
i ijj
j iji
11 restrições primárias,28 escolhas para achar todas as quatro soluções
B23
Somatória de j é 1 (um só produto por trabalhador)Somatória de i é 1 (um só trabalhador por produto)
Modelo 2: melhorUsando a desigualdade e restrições complexas. Quatro variáveis W1,W2,W3,W4 correspondendo aos trabalhadores
p p p pwwww
1 2 3 41 7 1 3 42 8 2 5 13 4 3 7 24 3 1 6 3
alldifferent W W W Welement W WPelement W WPelement W WPelement W WPP WP WP WP WPP
Resolvedor baseado em Consistência do Arco O resolvedor baseado em consistência do
arco dá informações muito mais acuradas dos valores possíveis para as variáveis
Outra vantagem é que este resolvedor trabalha tão bem com valores limitados quanto com coleções, enquanto o resolvedor baseado em limites trabalha bem apenas com restrições aritméticas
O programador define a RDU como uma relação binária com múltiplos fatos, e as rotula com a palavra reservada “consistent”, que indica ao CLP que ele deve resolver a relação utilizando consistência de arcos.
Predicados de aridade maior se resolvem pela consistência de hiper-arcos e com predicados unários, consistência de nós.
No exemplo anterior, no objetivo 2, ao invés de fazer o backtracking pelas diferentes regras (caso do objetivo 1), é utilizada a consistência de arcos para avaliar a relação likes. Assim, as desigualdades e as restrições levam ao seguinte domínio:
A execução do labeling leva D(N)={joaquim}, e a consistência do arco devolve
D(M)={pedro}, D(E)={bernardo}Assim nenhuma outra escolha é necessária para achar a primeira solução. Se for pedida outra solução, o backtraking faz imediatamente D(N)={bernardo} e as restrições da consistência do arco se propagam, não sendo necessária nenhuma outra escolha para a segunda solução
Restrição Reified Uma restrição reified r B
adiciona uma variável booleana B a uma restrição primitiva r
Se r ocorre, então B = 1 Se r não ocorre, então B = 0 A propagação é em ambas as
direções
Restrição Reified Usada para construir combinações
complexas sem usar “escolhas” Imagine que queremos que, das nossas 4
restrições primitivas, sejam satisfeitas apenas 2 ou 3. Isso geraria regras com muitas combinações…