640 likes | 946 Views
Integrity constraints & constraint logic programming. Henning Christiansen Roskilde University, Denmark henning@ruc.dk INAP’99, Invited DDLP’99 talk. Constraint logic programming (CLP). 1980'ies: Built-in constraint solvers, e.g., CLP(R) 1990'ies: Constraint solving as programming paradigm,
E N D
Integrity constraints&constraint logic programming Henning Christiansen Roskilde University, Denmark henning@ruc.dk INAP’99, Invited DDLP’99 talk
Constraint logic programming (CLP) • 1980'ies: Built-in constraint solvers, e.g., CLP(R) • 1990'ies: Constraint solving as programming paradigm, • language support, e.g., Constraint Handling Rules (CHR) • 2000'ies: Efficient (WAM-like) impl's of CHR and • similar programming languages • CLP expands to more and more applications • This talk: Applying CLP for evaluation of integrity constraints
Motivation • Names of phenomena overlap: • Integrity constraint/constraint logic programming
Motivation • Names of phenomena overlap: • Integrity constraint/constraint logic programming • IC's: Knowledge about database for improved query-answering: • – controlling update request • – intentional answers • – semantic query optimization • – usually avioded, approximated by update routines/simple checks
Motivation • Names of phenomena overlap: • Integrity constraint/constraint logic programming • IC's: Knowledge about database for improved query-answering: • – controlling update request • – intentional answers • – semantic query optimization • – usually avioded, approximated by update routines/simple checks • CLP: A declarative, computational paradigm • – delay’s • – incrementality: self-simplifying, self-specializing code • – produces general (quantified) answers Relevant for ICs!
The idea: Lazy negation-as-failure • Restrict to positive DDB's (with ”=” and ”dif”), and IC's as ”denials”: • bottom :- father(A,_), mother(A,_) • bottom:- father(A,C), father(B,C), dif(A,B) • tested by negation-as-failure that bottom is not the case.
The idea: Lazy negation-as-failure • Restrict to positive DDB's (with ”=” and ”dif”), and IC's as ”denials”: • bottom :- father(A,_), mother(A,_) • bottom:- father(A,C), father(B,C), dif(A,B) • tested by negation-as-failure that bottom is not the case. • Lazyness?? • A prospective update => a (constrained) ”hole” in the database • Procedure delays when ”hole” is met • Resulting computation: • – known part of DB checked, specialized constr’s remain for ”holes”, • – wakes up when update arrives, checking it • – ... and mutating into new specialized constraints for future updates.
The idea: Lazy negation-as-failure • Restrict to positive DDB's (with ”=” and ”dif”), and IC's as ”denials”: • bottom :- father(A,_), mother(A,_) • bottom:- father(A,C), father(B,C), dif(A,B) • tested by negation-as-failure that bottom is not the case. • Lazyness?? • A prospective update => a (constrained) ”hole” in the database • Procedure delays when ”hole” is met • Resulting computation: • – known part of DB checked, specialized constr’s remain for ”holes”, • – wakes up when update arrives, checking it • – ... and mutating into new specialized constraints for future updates. • I.e. Incrementality!
A meta-logic approach to lazy negation-as-failure • Ground representation of object language, e.g.: • DB0 = • [(bottom:- dif('A','B'), father('A','C'), father('B','C')), • (bottom:- dif('A','B'), mother('A','C'), mother('B','C')), • (bottom:- father('A','Z'), mother('A','X')), • (father(john,mary):- true), • (mother(jane,mary):- true) ]
A meta-logic approach to lazy negation-as-failure • Ground representation of object language, e.g.: • DB0 = • [(bottom:- dif('A','B'), father('A','C'), father('B','C')), • (bottom:- dif('A','B'), mother('A','C'), mother('B','C')), • (bottom:- father('A','Z'), mother('A','X')), • (father(john,mary):- true), • (mother(jane,mary):- true) ] • Instance constraints: • instance(s,t) iff s, t name object S, T with T an instance of S • Example: instance(p('X'), p(a))
Instance constraints reflect object var’s to Prolog • Example: • instance(p('X'), Z) <==> Z = p(ZX) • Object unification = 2*instance + 1 Prolog unification
Instance constraints reflect object var’s to Prolog • Example: • instance(p('X'), Z) <==> Z = p(ZX) • Object unification = 2*instance + 1 Prolog unification • Example: • Object level: p(a,X) = p(Y,b) • Meta-level (= Prolog): • instance(p(a,'X'), Z1), instance(p('Y',b), Z2), Z1=Z2 • Z1 = p(a, ZX), Z2 = p(ZY,b), Z1=Z2 • ZX=b, XY=a • Thus: Semantic prop’s of ground repr. with efficiency of nonground repr.
Solving instance constraints... (sketch) • Straight-forward recursive decomposition, delay’s when first argument is a variable • Interacts with user constraint • constant(X) iff ”X names an object constant” • Examples: • instance(p('X'), Z) <==> Z = p(ZX) • instance(p(X), Z) <==> Z = p(ZX), instance(X,ZX) • instance(p(X),Z), constant(X) <==> constant(X), Z = p(X) • I.e. meta-var’s covered by constant take ”active” part in computation
Lazy negation-as-failure (top-level procedure) • Declaratively: • fails(p,q) iff p, q names of P, Q where Q fails in P, • i.e. no with P |– Q • Top-level of implementation: • fails(P,Q):- instance(Q,Q1), fails1(P,Q1). • where fails1(p,q1) iff p, q names of P, Q1 where not P |– Q1 • fails1/2 implemented by constraint solver and auxiliary constraints.
Lazy negation-as-failure (top-level procedure) • Declaratively: • fails(p,q) iff p, q names of P, Q where Q fails in P, • i.e. no with P |– Q • Top-level of implementation: • fails(P,Q):- instance(Q,Q1), fails1(P,Q1). • where fails1(p,q1) iff p, q names of P, Q1 where not P |– Q1 • fails1/2 implemented by constraint solver and auxiliary constraints. • ... but let’s see some examples first
IC’s evaluated by lazy negation-as-failure (examples) • DB0 = • [(bottom:- dif('A','B'), father('A','C'), father('B','C')), • (bottom:- dif('A','B'), mother('A','C'), mother('B','C')), • (bottom:- father('A','Z'), mother('A','X')), • (father(john,mary):- true), • (mother(jane,mary):- true) ]
IC’s evaluated by lazy negation-as-failure (examples) • DB0 = • [(bottom:- dif('A','B'), father('A','C'), father('B','C')), • (bottom:- dif('A','B'), mother('A','C'), mother('B','C')), • (bottom:- father('A','Z'), mother('A','X')), • (father(john,mary):- true), • (mother(jane,mary):- true) ] • Q:fails(DB0, bottom)
IC’s evaluated by lazy negation-as-failure (examples) • DB0 = • [(bottom:- dif('A','B'), father('A','C'), father('B','C')), • (bottom:- dif('A','B'), mother('A','C'), mother('B','C')), • (bottom:- father('A','Z'), mother('A','X')), • (father(john,mary):- true), • (mother(jane,mary):- true) ] • Q:fails(DB0, bottom) • A:yes
IC’s evaluated by lazy negation-as-failure (examples) • DB0 = • [(bottom:- dif('A','B'), father('A','C'), father('B','C')), • (bottom:- dif('A','B'), mother('A','C'), mother('B','C')), • (bottom:- father('A','Z'), mother('A','X')), • (father(john,mary):- true), • (mother(jane,mary):- true) ] • Q:fails(DB0& [Clause], bottom)
IC’s evaluated by lazy negation-as-failure (examples) • DB0 = • [(bottom:- dif('A','B'), father('A','C'), father('B','C')), • (bottom:- dif('A','B'), mother('A','C'), mother('B','C')), • (bottom:- father('A','Z'), mother('A','X')), • (father(john,mary):- true), • (mother(jane,mary):- true) ] • Q:fails(DB0& [Clause], bottom) • A: ... a complicated expression ready for all possibilities: • Clause could be a father clause, • a mother clause, • or a new IC, i.e, bottom:- ...
IC’s evaluated by lazy negation-as-failure (examples) • DB0 = • [(bottom:- dif('A','B'), father('A','C'), father('B','C')), • (bottom:- dif('A','B'), mother('A','C'), mother('B','C')), • (bottom:- father('A','Z'), mother('A','X')), • (father(john,mary):- true), • (mother(jane,mary):- true) ] • Q:constant(A), constant(B), • fails(DB0 & [(father(A,B):- true)],bottom)
IC’s evaluated by lazy negation-as-failure (examples) • DB0 = • [(bottom:- dif('A','B'), father('A','C'), father('B','C')), • (bottom:- dif('A','B'), mother('A','C'), mother('B','C')), • (bottom:- father('A','Z'), mother('A','X')), • (father(john,mary):- true), • (mother(jane,mary):- true) ] • Q:constant(A), constant(B), • fails(DB0 & [(father(A,B):- true)],bottom) • A:fails1(jane=A),fails1((mary=B, dif(john,A)))
IC’s evaluated by lazy negation-as-failure (examples) • DB0 = • [(bottom:- dif('A','B'), father('A','C'), father('B','C')), • (bottom:- dif('A','B'), mother('A','C'), mother('B','C')), • (bottom:- father('A','Z'), mother('A','X')), • (father(john,mary):- true), • (mother(jane,mary):- true) ] • Q:constant(A), constant(B), no_duplicates( ... ), • fails(DB0 & [(father(A,B):- true)],bottom) • A:fails1(jane=A), fails1(mary=B)
Observations (preliminary) • Constraint solver produces residual constraints similar to "simplification method" [Nicolas, 82; Sadri,Kowalski, 88], but here as by-product of checking the whole, parameterized database • A flavour of constructive negation (later example: instantiates variables)
Incrementality for sequences of updates • A new user constraint (example): • clause_pattern(F,(father(X,Y):-true),(constant(X),constant(Y))) • iff all clauses in F obey pattern and constraints • A new residual constraint: • fails1(Prog,Atom*Clause(s),Continue) • iff • for (each) instance of clause H:-B in Clause(s), • the query H=Atom,B,Continue fails in Prog.
Incrementality for sequences of updates (example) • DB0 = • [(bottom:- dif('A','B'), father('A','C'), father('B','C')), • (bottom:- dif('A','B'), mother('A','C'), mother('B','C')), • (bottom:- father('A','Z'), mother('A','X')), • (father(john,mary):- true), • (mother(jane,mary):- true) ] • Q:clause_pattern(F,(father(X,Y):-true),(constant(X),constant(Y))), • fails1(DB0 & F, bottom), no_duplicates(...)
Incrementality for sequences of updates (example) • DB0 = • [(bottom:- dif('A','B'), father('A','C'), father('B','C')), • (bottom:- dif('A','B'), mother('A','C'), mother('B','C')), • (bottom:- father('A','Z'), mother('A','X')), • (father(john,mary):- true), • (mother(jane,mary):- true) ] • Q:clause_pattern(F,(father(X,Y):-true),(constant(X),constant(Y))), • fails1(DB0 & F, bottom), no_duplicates(...) • A:fails1(DB0 & F,father(A1,Z1)*F,mother(A1,X1)), • fails1(DB0 & F,father(B2,mary)*F, dif(john,B2)), • fails1(DB0 & F,(father(A3,C3),father(B3,C3))*F, dif(A3,B3)) • NB: Optimization for symmetric literals applied
View update, lazy N-a-F co-operates with abduction • A constraint-based proof predicate for program synthesis: • demo(p,q) iff p, q names of P, Q where Q succeds in P
View update, lazy N-a-F co-operates with abduction • A constraint-based proof predicate for program synthesis: • demo(p,q) iff p, q names of P, Q where Q succeds in P • DB1 = [(bottom:- ....), ..., • (sibling('A','B'):- ....), ..., • (father(john,mary):- true), • (mother(jane,mary):- true) ]
View update, lazy N-a-F co-operates with abduction • A constraint-based proof predicate for program synthesis: • demo(p,q) iff p, q names of P, Q where Q succeds in P • DB1 = [(bottom:- ....), ..., • (sibling('A','B'):- ....), ..., • (father(john,mary):- true), • (mother(jane,mary):- true) ] • Q:clause_pattern(F, (father...), ...), • clause_pattern(M, (mother...), ...), • fails1(DB1 & F & M, bottom), no_duplicates(...) • demo(DB1 & F & M, sibling(bob,mary)).
View update, lazy N-a-F co-operates with abduction • A constraint-based proof predicate for program synthesis: • demo(p,q) iff p, q names of P, Q where Q succeds in P • DB1 = [(bottom:- ....), ..., • (sibling('A','B'):- ....), ..., • (father(john,mary):- true), • (mother(jane,mary):- true) ] • Q:clause_pattern(F, (father...), ...), • clause_pattern(M, (mother...), ...), • fails1(DB1 & F & M, bottom), no_duplicates(...) • demo(DB1 & F & M, sibling(bob,mary)). • A:F = [(father(john,bob):-true) | F1], or • M = [(mother(jane,bob):-true) | F1]
”Co-operative” human-machine dialogue (example) • U: Isn’t aunt Dora the mother of Mary? Let's ask... • Q:demo(DB0, mother(dora,mary)) • A:no
”Co-operative” human-machine dialogue (example) • U: Isn’t aunt Dora the mother of Mary? Let's ask... • Q:demo(DB0, mother(dora,mary)) • A:no • U: !?!?Hmmmm, perhaps they forgot to add it to the database? • Q:fails(DB0 & [(mother(dora,mary):-true)], bottom)
”Co-operative” human-machine dialogue (example) • U: Isn’t aunt Dora the mother of Mary? Let's ask... • Q:demo(DB0, mother(dora,mary)) • A:no • U: !?!?Hmmmm, perhaps they forgot to add it to the database? • Q:fails(DB0 & [(mother(dora,mary):-true)], bottom) • A:no • U: ... but why? I'm confused ... do you have a mother for Mary? • Q:constant(A), demo(DB0, mother(A, mary))
”Co-operative” human-machine dialogue (example) • U: Isn’t aunt Dora the mother of Mary? Let's ask... • Q:demo(DB0, mother(dora,mary)) • A:no • U: !?!?Hmmmm, perhaps they forgot to add it to the database? • Q:fails(DB0 & [(mother(dora,mary):-true)], bottom) • A:no • U: ... but why? I'm confused ... do you have a mother for Mary? • Q:constant(A), demo(DB0, mother(A, mary)) • A:A = jane(no more answers)
”Co-operative” human-machine dialogue (example) • U: Isn’t aunt Dora the mother of Mary? Let's ask... • Q:demo(DB0, mother(dora,mary)) • A:no • U: !?!?Hmmmm, perhaps they forgot to add it to the database? • Q:fails(DB0 & [(mother(dora,mary):-true)], bottom) • A:no • U: ... but why? I'm confused ... do you have a mother for Mary? • Q:constant(A), demo(DB0, mother(A, mary)) • A:A = jane(no more answers) • U: So Jane is the only known mother, but why can't we add aunt Dora? • Q:constant(A), fails(DB0 & [(mother(A,mary):- true)], bottom)
”Co-operative” human-machine dialogue (example) • U: Isn’t aunt Dora the mother of Mary? Let's ask... • Q:demo(DB0, mother(dora,mary)) • A:no • U: !?!?Hmmmm, perhaps they forgot to add it to the database? • Q:fails(DB0 & [(mother(dora,mary):-true)], bottom) • A:no • U: ... but why? I'm confused ... do you have a mother for Mary? • Q:constant(A), demo(DB0, mother(A, mary)) • A:A = jane(no more answers) • U: So Jane is the only known mother, but why can't we add aunt Dora? • Q:constant(A), fails(DB0 & [(mother(A,mary):- true)], bottom) • A:A = jane(no more answers) • U: ... so Jane is the only possible mother...
Observations (continued) • Constraint solver produces residual constraints similar to "simplification method" [Nicolas, 82; Sadri, Kowalski, 88], but here as by-product of checking the whole, parameterized database • A flavour of constructive negation
Observations (continued) • Constraint solver produces residual constraints similar to "simplification method" [Nicolas, 82; Sadri, Kowalski, 88], but here as by-product of checking the whole, parameterized database • A flavour of constructive negation • Implies an incremental evaluation of IC’s: for each update, evaluate it, and prepare for next update
Observations (continued) • Constraint solver produces residual constraints similar to "simplification method" [Nicolas, 82; Sadri, Kowalski, 88], but here as by-product of checking the whole, parameterized database • A flavour of constructive negation • Implies an incremental evaluation of IC’s: for each update, evaluate it, and prepare for next update • Use of constraints provides optimal interleaving with abductive procedure for free for view update(opp. algorithms [Decker, Kowalski & al, Denecker & al, ...] with explicit scheduling)
Observations (continued) • Constraint solver produces residual constraints similar to "simplification method" [Nicolas, 82; Sadri, Kowalski, 88], but here as by-product of checking the whole, parameterized database • A flavour of constructive negation • Implies an incremental evaluation of IC’s: for each update, evaluate it, and prepare for next update • Use of constraints provides optimal interleaving with abductive procedure for free for view update(opp. algorithms [Decker, Kowalski & al, Denecker & al, ...] with explicit scheduling) • IC’s used to produce useful answers in human-machine dialogue (though not giving ”arguments”)
Observations (continued) • Constraint solver produces residual constraints similar to "simplification method" [Nicolas, 82; Sadri, Kowalski, 88], but here as by-product of checking the whole, parameterized database • A flavour of constructive negation • Implies an incremental evaluation of IC’s: for each update, evaluate it, and prepare for next update • Use of constraints provides optimal interleaving with abductive procedure for free for view update(opp. algorithms [Decker, Kowalski & al, Denecker & al, ...] with explicit scheduling) • IC’s used to produce useful answers in human-machine dialogue (though not giving ”arguments”) • ... now, let’s have a look at that constraint solver
Constraint solver for lazy negation-as-failure– Simplified CHR’s; first version for known program and query
fails1(_,true) <=> fail Constraint solver for lazy negation-as-failure– Simplified CHR’s; first version for known program and query
fails1(_,true) <=> fail fails1(P, (Q1,(A=B),Q2)) <=> (A=B -> fails1(P,(Q1,Q2));true) Constraint solver for lazy negation-as-failure– Simplified CHR’s; first version for known program and query
fails1(_,true) <=> fail fails1(P, (Q1,(A=B),Q2)) <=> (A=B -> fails1(P,(Q1,Q2));true) fails1(P, (Q1,dif(A,B),Q2)) <=> A==Bor both are constants or one is a variable free in(Q1,Q2) | (A==B -> true;fails1(P,(Q1,Q2))) Constraint solver for lazy negation-as-failure– Simplified CHR’s; first version for known program and query
fails1(_,true) <=> fail fails1(P, (Q1,(A=B),Q2)) <=> (A=B -> fails1(P,(Q1,Q2));true) fails1(P, (Q1,dif(A,B),Q2)) <=> A==Bor both are constants or one is a variable free in(Q1,Q2) | (A==B -> true;fails1(P,(Q1,Q2))) fails1(P, (Q1, A, Q2)) <=> A names an atom | fails1(P, A*P, (Q1,Q2)) Constraint solver for lazy negation-as-failure– Simplified CHR’s; first version for known program and query
fails1(_,true) <=> fail fails1(P, (Q1,(A=B),Q2)) <=> (A=B -> fails1(P,(Q1,Q2));true) fails1(P, (Q1,dif(A,B),Q2)) <=> A==Bor both are constants or one is a variable free in(Q1,Q2) | (A==B -> true;fails1(P,(Q1,Q2))) fails1(P, (Q1, A, Q2)) <=> A names an atom | fails1(P, A*P, (Q1,Q2)) fails1(_, _*[], _) <=> true Constraint solver for lazy negation-as-failure– Simplified CHR’s; first version for known program and query
fails1(_,true) <=> fail fails1(P, (Q1,(A=B),Q2)) <=> (A=B -> fails1(P,(Q1,Q2));true) fails1(P, (Q1,dif(A,B),Q2)) <=> A==Bor both are constants or one is a variable free in(Q1,Q2) | (A==B -> true;fails1(P,(Q1,Q2))) fails1(P, (Q1, A, Q2)) <=> A names an atom | fails1(P, A*P, (Q1,Q2)) fails1(_, _*[], _) <=> true fails1(P, A*[C|Cs], Cont) <=> fails1(P, A*C, Cont), fails1(P, A*Cs, Cont) Constraint solver for lazy negation-as-failure– Simplified CHR’s; first version for known program and query
fails1(_,true) <=> fail fails1(P, (Q1,(A=B),Q2)) <=> (A=B -> fails1(P,(Q1,Q2));true) fails1(P, (Q1,dif(A,B),Q2)) <=> A==Bor both are constants or one is a variable free in(Q1,Q2) | (A==B -> true;fails1(P,(Q1,Q2))) fails1(P, (Q1, A, Q2)) <=> A names an atom | fails1(P, A*P, (Q1,Q2)) fails1(_, _*[], _) <=> true fails1(P, A*[C|Cs], Cont) <=> fails1(P, A*C, Cont), fails1(P, A*Cs, Cont) fails1(P,A*(H:-B), Cont) <=> copy_term((A,Cont),(A1,Cont1)), instance((H:-B),(H1,B1)), fails1(P,(H1=A1,B1, Cont1)) Constraint solver for lazy negation-as-failure– Simplified CHR’s; first version for known program and query