Switch branches/tags
Nothing to show
Find file
Fetching contributors…
Cannot retrieve contributors at this time
114 lines (96 sloc) 5.5 KB
;; Copyright (c) Jeffrey Straszheim. All rights reserved. The use and
;; distribution terms for this software are covered by the Eclipse Public
;; License 1.0 ( which can
;; be found in the file epl-v10.html at the root of this distribution. By
;; using this software in any fashion, you are agreeing to be bound by the
;; terms of this license. You must not remove this notice, or any other,
;; from this software.
;; example.clj
;; A Clojure implementation of Datalog - Example
;; straszheimjeffrey (gmail)
;; Created 2 March 2009
;; Converted to Clojure1.4 by Martin Trojer 2012.
(ns datalog.example
(:use [datalog.datalog :only (build-work-plan run-work-plan)]
[datalog.rules :only (<- ?- rules-set)]
[datalog.database :only (make-database add-tuples)]
[datalog.util :only (*trace-datalog*)]))
(def db-base
(relation :employee [:id :name :position])
(index :employee :name)
(relation :boss [:employee-id :boss-id])
(index :boss :employee-id)
(relation :can-do-job [:position :job])
(index :can-do-job :position)
(relation :job-replacement [:job :can-be-done-by])
;;(index :job-replacement :can-be-done-by)
(relation :job-exceptions [:id :job])))
(def db
(add-tuples db-base
[:employee :id 1 :name "Bob" :position :boss]
[:employee :id 2 :name "Mary" :position :chief-accountant]
[:employee :id 3 :name "John" :position :accountant]
[:employee :id 4 :name "Sameer" :position :chief-programmer]
[:employee :id 5 :name "Lilian" :position :programmer]
[:employee :id 6 :name "Li" :position :technician]
[:employee :id 7 :name "Fred" :position :sales]
[:employee :id 8 :name "Brenda" :position :sales]
[:employee :id 9 :name "Miki" :position :project-management]
[:employee :id 10 :name "Albert" :position :technician]
[:boss :employee-id 2 :boss-id 1]
[:boss :employee-id 3 :boss-id 2]
[:boss :employee-id 4 :boss-id 1]
[:boss :employee-id 5 :boss-id 4]
[:boss :employee-id 6 :boss-id 4]
[:boss :employee-id 7 :boss-id 1]
[:boss :employee-id 8 :boss-id 7]
[:boss :employee-id 9 :boss-id 1]
[:boss :employee-id 10 :boss-id 6]
[:can-do-job :position :boss :job :management]
[:can-do-job :position :accountant :job :accounting]
[:can-do-job :position :chief-accountant :job :accounting]
[:can-do-job :position :programmer :job :programming]
[:can-do-job :position :chief-programmer :job :programming]
[:can-do-job :position :technician :job :server-support]
[:can-do-job :position :sales :job :sales]
[:can-do-job :position :project-management :job :project-management]
[:job-replacement :job :pc-support :can-be-done-by :server-support]
[:job-replacement :job :pc-support :can-be-done-by :programming]
[:job-replacement :job :payroll :can-be-done-by :accounting]
[:job-exceptions :id 4 :job :pc-support]))
(def rules
(<- (:works-for :employee ?x :boss ?y) (:boss :employee-id ?e-id :boss-id ?b-id)
(:employee :id ?e-id :name ?x)
(:employee :id ?b-id :name ?y))
(<- (:works-for :employee ?x :boss ?y) (:works-for :employee ?x :boss ?z)
(:works-for :employee ?z :boss ?y))
(<- (:employee-job* :employee ?x :job ?y) (:employee :name ?x :position ?pos)
(:can-do-job :position ?pos :job ?y))
(<- (:employee-job* :employee ?x :job ?y) (:job-replacement :job ?y :can-be-done-by ?z)
(:employee-job* :employee ?x :job ?z))
(<- (:employee-job* :employee ?x :job ?y) (:can-do-job :job ?y)
(:employee :name ?x :position ?z)
(if = ?z :boss))
(<- (:employee-job :employee ?x :job ?y) (:employee-job* :employee ?x :job ?y)
(:employee :id ?id :name ?x)
(not! :job-exceptions :id ?id :job ?y))
(<- (:bj :name ?x :boss ?y) (:works-for :employee ?x :boss ?y)
(not! :employee-job :employee ?y :job :pc-support))))
(def wp-1 (build-work-plan rules (?- :works-for :employee '??name :boss ?x)))
(run-work-plan wp-1 db {'??name "Albert"})
;;({:boss "Li", :employee "Albert"} {:boss "Sameer", :employee "Albert"} {:boss "Bob", :employee "Albert"})
(def wp-2 (build-work-plan rules (?- :employee-job :employee '??name :job ?x)))
(binding [*trace-datalog* true]
(run-work-plan wp-2 db {'??name "Li"}))
;; ({:job :server-support, :employee "Li"} {:job :pc-support, :employee "Li"})
(def wp-3 (build-work-plan rules (?- :bj :name '??name :boss ?x)))
(run-work-plan wp-3 db {'??name "Albert"})
;; ({:boss "Sameer", :name "Albert"})
(def wp-4 (build-work-plan rules (?- :works-for :employee ?x :boss ?y)))
(run-work-plan wp-4 db {})
;; ({:boss "Bob", :employee "Miki"} {:boss "Li", :employee "Albert"} {:boss "Sameer", :employee "Lilian"} {:boss "Bob", :employee "Li"} {:boss "Bob", :employee "Lilian"} {:boss "Fred", :employee "Brenda"} {:boss "Bob", :employee "Fred"} {:boss "Bob", :employee "John"} {:boss "Mary", :employee "John"} {:boss "Sameer", :employee "Albert"} {:boss "Bob", :employee "Sameer"} {:boss "Bob", :employee "Albert"} {:boss "Bob", :employee "Brenda"} {:boss "Bob", :employee "Mary"} {:boss "Sameer", :employee "Li"})