;; prototype to better understand rules. Use pellet sparql to compute ;; bindings for the rules and the add the consequents to the kb. Keep doing this ;; until nothing needs to be added. (defvar *srule-something-happened*) (defvar *instance-of-consequents*) (defun find-variables (form) (let ((vars nil)) (labels ((doit (aform) (cond ((and (symbolp aform) (char= (char (string aform) 0) #\?)) (pushnew aform vars)) ((listp aform) (map nil #'doit aform))))) (doit form) vars))) (defvar *trace-srules* t) (defmacro srule (antecedents consequence &key name (enabled t)) (let ((variables (find-variables consequence))) `(lambda(kb) (let ((*default-kb* kb)) (when ,enabled (loop for bound in (sparql `(:select ,',variables (:distinct t) ,@',(eval-uri-reader-macro antecedents)) :kb kb :use-reasoner :pellet) do (when *trace-srules* (format t "Trying rule ~a with bindings ~{~a=~a~^, ~}~%" ,name (apply 'append (mapcar 'list ',variables bound)))) (unless (apply (lambda ,variables ,(eval-uri-reader-macro consequence)) bound) (when *trace-srules* (format t "(not necessary)~%"))))))))) (defun assert-property-value (subject property object) (let ((property-ent (get-entity property)) (subject-ent (get-entity subject)) (object-ent (if (uri-p object) (get-entity object) object)) (kb (kb-kb *default-kb*))) ; (print-db (#"getPropertyValues" kb property-ent subject-ent)) (and (not (#"contains" (#"getPropertyValues" kb property-ent subject-ent) object-ent)) (progn (#"addPropertyValue" kb property-ent subject-ent object-ent) (setq *srule-something-happened* t))))) (defun assert-instance-of (class instance) (let* ((instance-ent (get-entity instance)) (kb (kb-kb *default-kb*)) (class-ent (if (listp class) (to-concept class *default-kb*) (get-entity class)))) (and (not (#"isType" kb instance-ent class-ent)) (progn (push (list instance-ent class-ent) *instance-of-consequents*) (setq *srule-something-happened* t))))) (defun assert-sub-class-of (sub super) (let* ((kb (kb-kb *default-kb*)) (sub-ent (if (listp sub) (to-concept sub *default-kb*) (get-entity sub))) (super-ent (if (listp super) (to-concept super *default-kb*) (get-entity super)))) (and (not (#"isSubclassOf" kb sub-ent super-ent)) (progn (#"addSubClass" kb sub-ent super-ent) (setq *srule-something-happened* t))))) (defun assert-sameas-from (instance1 instance2) (let ((instance1-ent (get-entity instance1)) (instance2-ent (get-entity instance2)) (kb (kb-kb *default-kb*))) (and (not (#"isSameAs" kb instance1-ent instance2-ent)) (progn (#"addSameAs" kb instance1-ent instance2-ent) (setq *srule-something-happened* t))))) (defun assert-different-from (instance1 instance2) (let ((instance1-ent (get-entity instance1)) (instance2-ent (get-entity instance2)) (kb (kb-kb *default-kb*))) (and (not (#"isDifferentFrom" kb instance1-ent instance2-ent)) (progn (#"addDifferent" kb instance1-ent instance2-ent) (setq *srule-something-happened* t))))) (defun assert-individual-exists (ind &rest prop-value-pairs) (and (not (has-entity? ind)) (let* ((name (if (uri-p ind) (uri-full ind) ind)) (aterm (#"makeTermAppl" 'ATermUtils name)) (kb (kb-kb *default-kb*))) (setf (gethash name (kb-name2entity (if (kb-p *default-kb*) *default-kb* (kb *default-kb*)))) `(:individual ., aterm)) (#"addIndividual" kb aterm) (#"addType" kb aterm (get-entity !owl:Thing)) (if prop-value-pairs (loop for (property object) in prop-value-pairs for property-ent = (get-entity property) for object-ent = (if (uri-p object) (get-entity object) object) do (#"addPropertyValue" kb property-ent aterm object-ent))) (#"realize" kb) ; unfortunate but assert-property-value directly after causes null pointer exception in getpropertyvalues unless you do this. (setq *srule-something-happened* t)))) (defmethod apply-srules ((o owl-ontology)) (let ((*srule-something-happened* nil) (*default-kb* (kb o)) (*instance-of-consequents* nil)) (loop with kb-kb = (kb-kb (kb o)) for count from 0 do (setq *srule-something-happened* nil) (setq *instance-of-consequents* nil) (sleep .001) (loop for rule in (srules o) do (funcall rule (kb o))) (when *srule-something-happened* (loop for (instance class) in *instance-of-consequents* do (#"addType" kb-kb instance class)) (multiple-value-bind (is reason) (check-abox-consistency (kb o)) (unless is (error "inconsistent! ~a" (second reason))))) while *srule-something-happened* finally (return count)))) #| ;; should be inconsistent (with-ontology ruletest () ((class !a :partial) (object-property !r1) (object-property !r2) (individual !a1 (type !a) (value !r1 !a2) (value !r2 !a2)) (individual !a2 (type !a))) (setf (srules ruletest) (list (srule ((?x !r1 ?y) (?x !r2 ?z)) (assert-different-from ?y ?z)))) (apply-srules ruletest) (check ruletest) ) (define-ontology biopax+interacts (:base "http://www.biopax.org/prototype") (ontology-annotation !owl:imports !) (object-property !bp2:interacts) (class !bp2:interactor :partial) ) (setf (srules biopax+interacts) (list (srule ((?inter !bp2:PARTICIPANTS ?a) (?inter !bp2:PARTICIPANTS ?x) (?a !bp2:PHYSICAL-ENTITY ?b) (?x !bp2:PHYSICAL-ENTITY ?y) (?b :a !bp2:protein) (?y :a !bp2:protein)) (unless (eq ?b ?y) (assert-property-value ?b !bp2:interacts ?y))))) (setf (srules biopax+interacts) (list (srule ((?inter !bp2:PARTICIPANTS ?a) (?inter !bp2:PARTICIPANTS ?x) (?a !bp2:PHYSICAL-ENTITY ?b) (?x !bp2:PHYSICAL-ENTITY ?y) (?b :a !bp2:protein) (?y :a !bp2:protein)) (unless (eq ?b ?y) (assert-instance-of !bp2:interactor ?b))))) ;; from which I wrote the macro: (loop with kb = (kb biopax+interacts) with kbkb = (kb-kb kb) with interacts-prop = (get-entity !bp2:interacts kb) for (?b ?y) in (sparql '(:select (?b ?y) () (?inter !bp2:PARTICIPANTS ?a) (?inter !bp2:PARTICIPANTS ?x) (?a !bp2:PHYSICAL-ENTITY ?b) (?b :a !bp2:protein) (?y :a !bp2:protein) (?x !bp2:PHYSICAL-ENTITY ?y) ) :kb (kb biopax+interacts) :use-reasoner :pellet) for b-ent = (get-entity ?b kb) for y-ent = (get-entity ?y kb) do (unless (or (eq ?b ?y) (#"contains" (#"getPropertyValues" kbkb interacts-prop b-ent) y-ent)) (princ ".") (#"addPropertyValue" kbkb interacts-prop b-ent y-ent))) FIRE: http://www.cs.concordia.ca/~haarslev/students/Kruthi_Bhoopalam.pdf CARIN: http://citeseer.ifi.unizh.ch/cache/papers/cs/998/http:zSzzSzwww.research.att.comzSz~levyzSzecai96.pdf/levy96carin.pdf From swoop RulesExpressivity.java A rule can be expressed in OWL if it has exactly one common variable, or if it has no common variables and at least one common individual. Checks if a given SWRL rule is DL safe It checks that each variable in r occurs in a non-DL atom in the rule body http://www.kr.tuwien.ac.at/staff/roman/asp_sw/ http://en.wikipedia.org/wiki/Answer_set_programming What are rules used for? ;; http://algernon-j.sourceforge.net/tutorial/4a.html http://www.cs.utexas.edu/users/qr/ http://www.cs.utexas.edu/users/qr/QR-software.html#qpc http://www.cs.cmu.edu/Groups/AI/html/faqs/ai/expert/part1/faq.html http://www.cs.nott.ac.uk/~gmh/faq.html http://www.doc.ic.ac.uk/project/2005/163/g0516311/index.html http://algernon-j.sourceforge.net/ http://www.informatik.uni-ulm.de/pm/fileadmin/pm/events/chr2004/index.html http://citeseer.ifi.unizh.ch/cache/papers/cs/22901/http:zSzzSzwww.kr.tuwien.ac.atzSzstaffzSzeiterzSzet-archivezSztods.pdf/eiter97disjunctive.pdf http://www.cs.man.ac.uk/~bmotik/publications/papers/mmv03optimizing.pd Disjunctive datalog (eiter) http://citeseer.ifi.unizh.ch/cache/papers/cs/22901/http:zSzzSzwww.kr.tuwien.ac.atzSzstaffzSzeiterzSzet-archivezSztods.pdf/eiter97disjunctive.pdf Send JAR landglobal. http://www.csupomona.edu/~jrfisher/www/prolog_tutorial/2_12.html http://www.dis.uniroma1.it/~rosati/publications/rosati-KR-06.pdf http://www.mindswap.org/2005/OWLWorkshop/sub12.pdf http://www.w3.org/TR/rif-ucr/ http://www.w3.org/2005/rules/wg/wiki/OWL_Compatibility Promising: http://www.kr.tuwien.ac.at/staff/tompits/papers/kr-04-coupling.pdf http://www.kr.tuwien.ac.at/staff/roman/semweblp/ http://www.kr.tuwien.ac.at/staff/roman/papers/lpar04_final.ps http://www.dbai.tuwien.ac.at/proj/dlv/man/ http://rewerse.net/publications/download/REWERSE-RP-2005-110.pdf ~lsw/dlv http://faculty.ed.umuc.edu/~meinkej/inss690/hinz.pdf Euler: http://www.agfa.com/w3c/2002/02/thesis/thesis.pdf Datalog Bottom-up is the Trend in the Deductive Database Evaluation Strategy: http://faculty.ed.umuc.edu/~meinkej/inss690/hinz.pdf http://www.manageability.org/blog/stuff/rule_engines/view What I want: Simple forward prop. Computed slots Integrity constraints Issues: - Rule recursion. (is this a problem with forward chaining?) - After assertions, reclassification, check that antecedents that were used to fire a rule still hold (but what about retraction?). Andrea Splendiani But these rules are not problematic.I mean, they are not even graph rewriting... Alan Ruttenberg right. I am looking for "problematic" rules now. Do you have some? Andrea Splendiani Problem is when this rules clash with OWL semantics... Alan Ruttenberg need examples. Andrea Splendiani ?x ?y ?z -> ?z ?y ?y kidding... Andrea Splendiani but that will break OWL. Alan Ruttenberg yes. I don't want to break owl for the sake of it (too easy). I want motivated examples of things you really want to do. If the break owl then that is interesting. Andrea Splendiani I think that SWRL is trying to define constraints of rules that keep inferred statements inside OWL.So...Basically you can use rules in two ways (or even more.. but among them: To specify characteristics of elements in your ontology. Like the famous dad-son-brother->uncle pattern.In this case rules are related to inference/subsumption.Hence SWRL and other attempts to define rule languages.But It's not clear to me this rule languages stuff.... SWRL... RuleML (and sublanguages)... there is even something more around... I don't have a systemantic introduction on which language/intent goals/constraints are and I suspect most of the variety come from the different background of people instead of from the characteristics of rules themselfes.Another way to use the is to "compute on graph patterns".This is theory should be related to graph rewriting...But since here we are not going to delete anything... it's just graph augmentation. Alan Ruttenberg Graph augmentation is easy. I can easily supply that for pellet.that's what srules is. Andrea Splendiani And since our ontology is instance based, this is not clashing (unless you really look for it) with reasoning.Right.So if we have graph augmentation, and we are not touching classes... the rule language itself is not so relevant anymore.Than depends what you want to compute with rules.In BioPAX you have two things you can do:things like assert sameAs when two unificationXref are the same.things like the "interacts" above.But you may have more, for instance, you may define "affects". Alan Ruttenberg defined as... Andrea Splendiani Defined as ?x affects ?y <- ?z rdf:type pathway , ?z consumes ?x, ?z produces ?k, ?w type pathway, ?w consumes ?k, ?w produces ?yproduces and consumes are idealized here... pathway step with interaction that has left right...And ideally you could also have a transitive property to define a flow of information. Alan Ruttenberg no ?x in your body. intentional? Andrea Splendiani like something left in pathwayStep, and right in nextPathwaySetp -> influences that is transitive...there is ?x in the body. Alan Ruttenberg oops. ok. Andrea Splendiani Anyway, then the problem is: complexity.Anyway these are just sketched to give an idea... they get more complex in the real ontology. Alan Ruttenberg good example. thanks. Andrea Splendiani In Jena, you can use a backward engine that schedule come computation on demand, so for these rules you are safe.relatively... try a forward engine that computes all deductions.... that's the same. Alan Ruttenberg so you can think of this in the following way: Imagine that you have forward rules implemented as sparql query + function on bindings + assertion to kb of result. then backwards "rules" are just patterns that get expanded in the sparql query before it is sent. Andrea Splendiani mhh Alan Ruttenberg macros effectively. Andrea Splendiani not sure.macros may not deal with loops.What if you have: (?x asass ?y) <- (?z) and (?z) <- (?x) you keep expanding with macros... Guess backward rule have some sort of dependency graph... but I' not sure... Alan Ruttenberg don't understand the rule. Is it one rule or two? Andrea Splendiani two.But I may be wrong... Alan Ruttenberg what does (?z) <- (?x) mean? Andrea Splendiani Just a rule with ?z <-.?x.... Another difference may come from the fact that you may have more rules instead of a macro.Like: ?x <- rule body1 ?x <- rule body2 with macros you should add some backtracking/search mode... Alan Ruttenberg ok good. I will think about this. |# ;http://dev1.deri.at/mins/ ;jlisa (lisa in abcl) ;http://www.manageability.org/blog/stuff/rule_engines/view ;http://www.agfa.com/w3c/euler/ ; http://www.csupomona.edu/~jrfisher/www/prolog_tutorial/1.html