- From: Geoff Chappell <geoff@sover.net>
- Date: Wed, 5 Jan 2005 22:07:52 -0500
- To: "'Bijan Parsia'" <bparsia@isr.umd.edu>, <www-rdf-logic@w3.org>
> -----Original Message----- > From: www-rdf-logic-request@w3.org [mailto:www-rdf-logic-request@w3.org] > On Behalf Of Bijan Parsia > Sent: Wednesday, January 05, 2005 10:28 AM > To: www-rdf-logic@w3.org > Subject: Re: RDF as a syntax for OWL (was Re: same-syntax extensions to > RDF) > [...] > > Jos, I have a way way easier challenge: do the negation normal form > transformation > > Specification: Given an input graph, produce an output graph such that > all negations appear only on class names in a class expression. > > Actually, let's make it even easier! Only for ALC > > I'll even give the rules: > I'll use ~ for not (complementOf) > & for conjunction (intersectionOf) > v for disjunction (unionOf) > some for existential quantification (someValuesFrom) > all for universal quantification (allValuesFrom) > I'll use fairly normal infixy syntax. I'll happily convert to > something else. > > For (compound) class expressions C and D > nnf(~~C)) => nnf(C) > nnf(~(C & D)) => nnf(~C) v nnf(~D) > nnf(~(C v D)) => nnf(~C) & nnf(~D) > nnf(~some(P, C)) => all(P, nnf(C)) > nnf(~all(P, C)) => some(P, nnf(C)) > > Base case: for atomic class name C > nnf(C) => C > nnf(~C) => ~C > > That's almost the prolog program :) > > I'll accept the binary restriction on & and v. > > To make it easier, I'll allow for the class expressions to be isolated > (i.e., not part of an axiom), if that helps. > > I believe this exercise will be illuminating to anyone who tries it. Given the challenge, I had to give it a try in RDF Gateway's rule language ;-) The results don't really rebut the ugliness claim, but do demonstrate that it's doable in at least one of the available frameworks. BTW, I'm not denying this was a bit of a pain, nor in any way trying to be an advocate for the forcing of fol into rdf syntax. I ended up with rulebase below. With it I could convert a graph to nnf form with a few lines - e.g: var ds = new datasource("inet?parsetype=auto&url=c:/kill/nnftest.rdf"); select ?p ?s ?o using #ds rulebase nnf where {[rdf:type] ?c [owl:Class]} and nnf(?c ?p ?s ?o); The rules may not be 100% though I tested them with a decent number of cases (but no pathological ones). rulebase nnf { infer nnf(?cin, ?p, ?s, ?o) from nnf_pos(?cin, ?cout, ?p, ?s, ?o); infer nnf_pos(?cin, ?cout, ?p, ?s, ?o) from isAnon(?cin) and {[owl:complementOf] ?cin ?x} and nnf_neg(?x, ?cout, ?p, ?s, ?o); // nnf(~~C)) => nnf(C) infer nnf_neg(?cin, ?cout, ?p, ?s, ?o) from isAnon(?cin) and {[owl:complementOf] ?cin ?x} and nnf_pos(?y, ?cout, ?p, ?s, ?o); // nnf(~(C & D)) => nnf(~C) v nnf(~D) infer nnf_neg(?cin, ?cout, ?p, ?s, ?o) from isAnon(?cin) and {[owl:intersectionOf] ?cin ?l} and negateCompleteList(?l, ?cout, [owl:unionOf], ?p ?s ?o); // nnf(~(C v D)) => nnf(~C) & nnf(~D) infer nnf_neg(?cin, ?cout, ?p, ?s, ?o) from isAnon(?cin) and {[owl:unionOf] ?cin ?l} and negateCompleteList(?l, ?cout, [owl:intersectionOf], ?p ?s ?o); // nnf(~some(P, C)) => all(P, nnf(C)) infer nnf_neg(?cin, ?cout, ?p, ?s, ?o) from isAnon(?cin) and {[owl:onProperty] ?cin ?prop} and {[owl:someValuesFrom] ?cin ?svc} and ?cout=newid() and nnf_pos(?svc, ?svcout, ?a ?b ?c) and ( statement(?a ?b ?c ?p ?s ?o) or statement([owl:onProperty] ?cout ?prop ?p ?s ?o) or statement([owl:allValuesFrom] ?cout ?svcout ?p ?s ?o) ); // nnf(~all(P, C)) => some(P, nnf(C)) infer nnf_neg(?cin, ?cout, ?p, ?s, ?o) from isAnon(?cin) and {[owl:onProperty] ?cin ?prop} and {[owl:allValuesFrom] ?cin ?vc} and ?cout=newid() and nnf_pos(?vc, ?vcout, ?a ?b ?c) and ( statement(?a ?b ?c ?p ?s ?o) or statement([owl:onProperty] ?cout ?prop ?p ?s ?o) or statement([owl:someValuesFrom] ?cout ?vcout ?p ?s ?o) ); // nnf(C) => C infer nnf_pos(?cin, ?cout, ?p, ?s, ?o) from instr(?cin, 'guid') <> 0 and ?cout=?cin and ?s=?cin and {?p ?s ?o}; // nnf(~C) => ~C infer nnf_neg(?cin, ?cout, ?p, ?s, ?o) from instr(?cin, 'guid') <> 0 and ?cout=newid() and ( (?s=?cin and {?p ?s ?o}) or statement([owl:complementOf] ?cout ?cin ?p ?s ?o) ) //helpers infer negateCompleteList(?l, ?cout, ?pred, ?p, ?s, ?o) from ?newlist=newid() and ?cout=newid() and ( negateList(?l, ?newlist, ?p ?s ?o) or statement([rdf:type] ?cout [owl:Class] ?p ?s ?o) or statement(?pred ?cout ?newlist ?p ?s ?o) ); infer negateList(?l, ?newlist, ?p ?s ?o) from {[rdf:first] ?l ?first} and {[rdf:rest] ?l ?rest} and switch(?l) ( case ?rest=[rdf:nil]: ?newrest=[rdf:nil] default: ?newrest=newid() ) and nnf_neg(?first, ?firstout, ?a ?b ?c) and ( statement(?a ?b ?c ?p ?s ?o) or statement([rdf:first] ?newlist ?firstout ?p ?s ?o) or statement([rdf:rest] ?newlist ?newrest ?p ?s ?o) or negateList(?rest ?newrest ?p ?s ?o) ); infer statement(?pin ?sin ?oin ?pout ?sout ?oout) from ?pout=?pin and ?sout=?sin and ?oout=?oin; infer isAnon(?x) from instr(?x, 'guid') = 0; } > Actually, just trying stating the rules using RDF triples in your > favorite syntax. > > Cheers, > Bijan Parsia. Rgds, Geoff Chappell
Received on Thursday, 6 January 2005 03:07:59 UTC