(full-reset)

(racer-read-file "z:/temp/people+pets.racer")

;;; ----------------------------

;;; Explain: Shell (get-racer- tab), completion, lambda-list, ... 

;;; ----------------------------

;;; Concepts ("classes") in an subclass-of hierachy

;;; Explain subsumption between cat-liker and cat-owner: 

;;; "Class reasoning"

#| 

(equivalent cat_liker 
            (and person
                 (some likes cat))) 

(equivalent cat_owner 
            (and person 
                 (some has_pet cat))) 

(define-primitive-role has_pet 
                       :parents likes ...)

|# 

;;; Show role hierachy (has_pet is subrole of likes) 
;;; Position in class hierarchy computed from definitions

;;; Explain old-lady 

#|

(equivalent old_lady 
            (and person female elderly))
 
(implies old_lady 
         (and (all has_pet cat) 
              (some has_pet animal)))

|#

;;; Class / concept consistency
;;; there are no mad cows

#| 

(define-concept mad_cow 
                (and cow 
                     (some eats 
                           (and brain 
                                (some part_of sheep))))) 

(implies cow vegetarian) 

(define-concept vegetarian 
                (and animal 
                     (all eats (not animal))
                     (all eats (not (some part_of animal)))))

(implies sheep animal) 

|# 

;;; ----------------------------
 
;;; "Individual reasoning"

;;; Individual Minnie (Individuals Tab -> Assertion Tab)
;;; Old_lady not explicit 

;;; ABox Graph : Minnie has_pet Tom
;;; Select Tom -> Describe -> Cat
;;; Assertions Tab: nothing was asserted for Tom
;;; Is a cat by inference (see old_lady)
;;; Interplay of definitions <-> individuals (TBox <-> ABox)

;;; The classes an individual is an instance of 
;;; is computed from the definitions! 
;;; multiple classification 

;;; ----------------------------

;;;
;;; ABox Queries 
;;; (Go to ABox Graph!)
;;; 

(concept-instances cat_owner)

(retrieve (?x) 
          (?x cat_owner))

(retrieve (?x ?y)
          (and (?x cat_owner) 
               (?x ?y has_pet)))

(retrieve (?x ?y)
          (and (?x cat_owner)
               (?x ?y has_pet)
               (?y cat)))

(retrieve (?x ?y (direct-types ?y)) 
          (and (?x pet_owner)
               (?x ?y has_pet))
          :dont-show-lambdas-p t)

;;;
;;; Queries involving negation
;;; 2 types of negation
;;; 

(retrieve (?x)
          (?x (not pet_owner)))

(retrieve (?x) 
          (neg (?x pet_owner)))

;;;
;;; OWA 
;;;

(retrieve (?x)
          (?x (and cat_owner
                   (all has_pet cat))))

(retrieve (?x)
          (?x (and dog_owner 
                   (all has_pet dog))))

(equivalent duck_owner 
                (and pet_owner
                     (some has_pet duck)))

(retrieve (?x)
          (?x duck_owner))

(retrieve (?x)
          (?x (and duck_owner 
                   (all has_pet duck))))

;;; whats the difference? OWA! 
;;; Why did it work for Minnie? Definition
;;; Why did it work for Joe? At-most 1 pet

(instance Walt (at-most 3 has_pet))

(retrieve (?x) 
          (?x (and duck_owner 
                   (all has_pet duck))))

;;; still not sufficent, might be the same individual! 
;;; no UNA assumed 

(all-different Huey Dewey Louie)

(retrieve (?x) 
          (?x (and duck_owner
                   (all has_pet duck))))

;;; at last... 

;;;
;;; Some more advanced queries
;;; Aggregation:
;;; 

(retrieve (?x (count ?y) (group-by ?x)) 
          (?x ?y has_pet))

;;; Nested Queries

(retrieve (?x ((lambda (x)
                 (let ((pets 
                         (retrieve `(?y) `(,x ?y has_pet)))) 
                     `(has ,(length pets) pets ,@pets)))
                 ?x))
          (?x pet_owner)
          :dont-show-lambdas-p t)

(retrieve (?x ((lambda (x)
                 (let ((pets 
                         (retrieve `(?y) `(,x ?y has_pet)))) 
                   (format nil "~A has ~A pets:~{ ~S~}" 
                           x
                           (length pets) 
                           (maplist cadar pets))))
                 ?x))
          (?x pet_owner)
          :dont-show-lambdas-p t)

;;;
;;; An optimized version with query pre-compilation: 
;;; 

(delete-all-queries)

(with-future-bindings (?x)

  (prepare-abox-query (?y)
                      (?x ?y has_pet)
                      :id :pet-query))

(retrieve (?x
           ((lambda (x)
              (with-nrql-settings (:bindings `((?x ,x)))
                 (let ((pets 
                        (execute-or-reexecute-query :pet-query)))
                   (format nil "~A has ~A pets:~{ ~S~}" 
                           x
                           (length pets)
                           (maplist cadar pets)))))
              ?x))

           (?x pet_owner)
           :dont-show-lambdas-p t)

;;;
;;; Datatype Queries 
;;; 

(define-concrete-domain-attribute age :type real)

(instance Louie (= age 1.0))

(instance Dewey (= age 2.0))

(instance Huey (= age 3.0))

(enable-data-substrate-mirroring)

(retrieve (?x ?*age) 
          (and (?x duck)
               (?*x ?*age age)))

;;;
;;; Universal Quantification
;;; with "neg" and "project-to"
;;; Oldest duck: 
;;; 

(retrieve (?x ?*age-of-x)
          (and (?x duck)
               (?*x ?*age-of-x age)
               (neg (project-to (?*age-of-x)
                     (and (?y duck)
                          (?*y ?*age-of-y age)
                          (?*age-of-x ?*age-of-y  
                                      (:satisfies
                                       (:predicate <))))))))        

;;; Youngest duck: 

(retrieve (?x ?*age-of-x)
          (and (?x duck)
               (?*x ?*age-of-x age)
               (neg (project-to (?*age-of-x)
                     (and (?y duck)
                          (?*y ?*age-of-y age)
                          (?*age-of-x ?*age-of-y  
                                      (:satisfies
                                       (:predicate >))))))))        

;;;
;;; Rules  
;;; 

(firerule (and (?x person) 
               (neg (?x pet_owner)))

          ((related ?x (new-ind pet-of ?x) has_pet)))

(retrieve (?y) 
          (and (Kevin ?y has_pet)
               (?y pet)))

(individual-instance? Kevin
                      (or dog_owner cat_owner duck_owner))

(firerule (and (?x pet) 
               (neg (?x (or cat dog duck))))

          ((instance ?x 
             (lambda (nth (random 3) '(cat dog duck))))))

(individual-instance? Kevin (or dog_owner cat_owner duck_owner))

(firerule (and (?x pet) 
               (neg (?x (or cat dog duck))))

          ((instance ?x 
             (lambda 
                (nth (random 3) '(cat dog duck))))))

;;; non-monotonic due to NEG, doesn't fire twice 

;;;
;;; Reasoning with queries / rules
;;; 

(report-inconsistent-queries-and-rules)

(firerule (?x old_lady)

          ((related ?x (new-ind another-dog-for ?x) has_pet)
           (instance (new-ind another-dog-for ?x) dog)))

(dont-report-inconsistent-queries-and-rules)

;;;
;;; HTML Report Generation 
;;; 

(evaluate 

 (let ((res (retrieve '(?x ?y) '(and (?x ?y has_pet)))))

   (with-html ( "/home/mi.wessel/temp/pets.html") 

              (html (head)
                    (html (title) 
                          (content "Query Evaluation Output")))

              (html (body)

                    (html (h1)
                          (content "Query Evaluation Output"))

                    (html (h2)
                          (content "Query Head"))
                    (content (query-head :last))

                    (html (h2)
                          (content "Query Body"))
                    (content (query-body :last))

                    (html (h2)
                          (content "Query Answer"))

                    (html (table :border 1)

                          (let ((count 0))

                            (maplist 
                             (lambda (bindings) 

                               (html (tr)
                                     (html (th :colspan 2)
                                           (content
                                            (format nil
                                                    "Result Tuple No. ~A" 
                                                    (incf count)))))

                               (maplist 
                                (lambda (var-val)
                                  (let ((var (first var-val))
                                        (val (second var-val)))

                                    (html (tr)
                                          (html (td)
                                                (content var))
                                          (html (td)
                                                (content val)))))
                                bindings))

                             res)))))))

(evaluate
 (publish-file "/home/mi.wessel/temp/pets.html"
               "/pets.html"
               "text/html"))

;;; http://localhost:8080/pets.html

;;;
;;; SPARQL Queries to OWL version 
;;; 

(full-reset)

(owl-read-file "/home/mi.wessel/temp/people+pets.owl")

(sparql-answer-query "prefix pets: <http://cohse.semanticweb.org/ontologies/people#> select ?x where { ?x rdf:type pets:cat }")

(sparql-answer-query "prefix pets: <http://cohse.semanticweb.org/ontologies/people#> select ?x ?y where { ?x rdf:type pets:old_lady ; pets:has_pet ?y . ?y rdf:type pets:cat . }")



