aboutsummaryrefslogtreecommitdiff
path: root/src/clojure/contrib/datalog
diff options
context:
space:
mode:
authorStuart Sierra <mail@stuartsierra.com>2010-01-20 15:39:56 -0500
committerStuart Sierra <mail@stuartsierra.com>2010-01-20 15:39:56 -0500
commit2ede388a9267d175bfaa7781ee9d57532eb4f20f (patch)
treebb42002af196405d7e25cc4e30b4c1c9de5c06d5 /src/clojure/contrib/datalog
parent1bc820d96048a6536706ff999e9892649b53c700 (diff)
Move source files into Maven-style directory structure.
Diffstat (limited to 'src/clojure/contrib/datalog')
-rw-r--r--src/clojure/contrib/datalog/database.clj287
-rw-r--r--src/clojure/contrib/datalog/example.clj116
-rw-r--r--src/clojure/contrib/datalog/literals.clj414
-rw-r--r--src/clojure/contrib/datalog/magic.clj128
-rw-r--r--src/clojure/contrib/datalog/rules.clj207
-rw-r--r--src/clojure/contrib/datalog/softstrat.clj161
-rw-r--r--src/clojure/contrib/datalog/tests/test.clj45
-rw-r--r--src/clojure/contrib/datalog/tests/test_database.clj153
-rw-r--r--src/clojure/contrib/datalog/tests/test_literals.clj187
-rw-r--r--src/clojure/contrib/datalog/tests/test_magic.clj72
-rw-r--r--src/clojure/contrib/datalog/tests/test_rules.clj130
-rw-r--r--src/clojure/contrib/datalog/tests/test_softstrat.clj233
-rw-r--r--src/clojure/contrib/datalog/tests/test_util.clj69
-rw-r--r--src/clojure/contrib/datalog/util.clj89
14 files changed, 0 insertions, 2291 deletions
diff --git a/src/clojure/contrib/datalog/database.clj b/src/clojure/contrib/datalog/database.clj
deleted file mode 100644
index aba41df9..00000000
--- a/src/clojure/contrib/datalog/database.clj
+++ /dev/null
@@ -1,287 +0,0 @@
-;; Copyright (c) Jeffrey Straszheim. All rights reserved. The use and
-;; distribution terms for this software are covered by the Eclipse Public
-;; License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) 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.
-;;
-;; database.clj
-;;
-;; A Clojure implementation of Datalog -- Support for in-memory database
-;;
-;; straszheimjeffrey (gmail)
-;; Created 21 Feburary 2009
-
-
-(ns clojure.contrib.datalog.database
- (:use clojure.contrib.datalog.util)
- (:use clojure.contrib.def)
- (:use [clojure.set :only (union intersection difference)])
- (:use [clojure.contrib.except :only (throwf)]))
-
-
-(defstruct relation
- :schema ; A set of key names
- :data ; A set of tuples
- :indexes) ; A map key names to indexes (in turn a map of value to tuples)
-
-
-;;; DDL
-
-(defmethod print-method ::datalog-database
- [db #^Writer writer]
- (binding [*out* writer]
- (do
- (println "(datalog-database")
- (println "{")
- (doseq [key (keys db)]
- (println)
- (println key)
- (print-method (db key) writer))
- (println "})"))))
-
-(defn datalog-database
- [rels]
- (with-meta rels {:type ::datalog-database}))
-
-(def empty-database (datalog-database {}))
-
-(defmethod print-method ::datalog-relation
- [rel #^Writer writer]
- (binding [*out* writer]
- (do
- (println "(datalog-relation")
- (println " ;; Schema")
- (println " " (:schema rel))
- (println)
- (println " ;; Data")
- (println " #{")
- (doseq [tuple (:data rel)]
- (println " " tuple))
- (println " }")
- (println)
- (println " ;; Indexes")
- (println " {")
- (doseq [key (-> rel :indexes keys)]
- (println " " key)
- (println " {")
- (doseq [val (keys ((:indexes rel) key))]
- (println " " val)
- (println " " (get-in rel [:indexes key val])))
- (println " }"))
- (println " })"))))
-
-(defn datalog-relation
- "Creates a relation"
- [schema data indexes]
- (with-meta (struct relation schema data indexes) {:type ::datalog-relation}))
-
-(defn add-relation
- "Adds a relation to the database"
- [db name keys]
- (assoc db name (datalog-relation (set keys) #{} {})))
-
-(defn add-index
- "Adds an index to an empty relation named name"
- [db name key]
- (assert (empty? (:data (db name))))
- (let [rel (db name)
- inx (assoc (:indexes rel) key {})]
- (assoc db name (datalog-relation (:schema rel)
- (:data rel)
- inx))))
-
-(defn ensure-relation
- "If the database lacks the named relation, add it"
- [db name keys indexes]
- (if-let [rel (db name)]
- (do
- (assert (= (:schema rel) (set keys)))
- db)
- (let [db1 (add-relation db name keys)]
- (reduce (fn [db key] (add-index db name key))
- db1
- indexes))))
-
-
-(defmacro make-database
- "Makes a database, like this
- (make-database
- (relation :fred [:mary :sue])
- (index :fred :mary)
- (relation :sally [:jen :becky])
- (index :sally :jen)
- (index :sally :becky))"
- [& commands]
- (let [wrapper (fn [cur new]
- (let [cmd (first new)
- body (next new)]
- (assert (= 2 (count body)))
- (cond
- (= cmd 'relation)
- `(add-relation ~cur ~(first body) ~(fnext body))
- (= cmd 'index)
- `(add-index ~cur ~(first body) ~(fnext body))
- :otherwise (throwf "%s not recognized" new))))]
- (reduce wrapper `empty-database commands)))
-
-(defn get-relation
- "Get a relation object by name"
- [db rel-name]
- (db rel-name))
-
-(defn replace-relation
- "Add or replace a fully constructed relation object to the database."
- [db rel-name rel]
- (assoc db rel-name rel))
-
-
-;;; DML
-
-
-(defn database-counts
- "Returns a map with the count of elements in each relation."
- [db]
- (map-values #(-> % :data count) db))
-
-(defn- modify-indexes
- "Perform f on the indexed tuple-set. f should take a set and tuple,
- and return the new set."
- [idxs tuple f]
- (into {} (for [ik (keys idxs)]
- (let [im (idxs ik)
- iv (tuple ik)
- os (get im iv #{})
- ns (f os tuple)]
- [ik (if (empty? ns)
- (dissoc im iv)
- (assoc im iv (f os tuple)))]))))
-
-(defn- add-to-indexes
- "Adds the tuple to the appropriate keys in the index map"
- [idxs tuple]
- (modify-indexes idxs tuple conj))
-
-(defn- remove-from-indexes
- "Removes the tuple from the appropriate keys in the index map"
- [idxs tuple]
- (modify-indexes idxs tuple disj))
-
-(defn add-tuple
- "Two forms:
-
- [db relation-name tuple] adds tuple to the named relation. Returns
- the new database.
-
- [rel tuple] adds to the relation object. Returns the new relation."
- ([db rel-name tuple]
- (assert (= (-> tuple keys set) (-> rel-name db :schema)))
- (assoc db rel-name (add-tuple (db rel-name) tuple)))
- ([rel tuple]
- (let [data (:data rel)
- new-data (conj data tuple)]
- (if (identical? data new-data) ; optimization hack!
- rel
- (let [idxs (add-to-indexes (:indexes rel) tuple)]
- (assoc rel :data new-data :indexes idxs))))))
-
-(defn remove-tuple
- "Two forms:
-
- [db relation-name tuple] removes the tuple from the named relation,
- returns a new database.
-
- [rel tuple] removes the tuple from the relation. Returns the new
- relation."
- ([db rel-name tuple] (assoc db rel-name (remove-tuple (db rel-name) tuple)))
- ([rel tuple]
- (let [data (:data rel)
- new-data (disj data tuple)]
- (if (identical? data new-data)
- rel
- (let [idxs (remove-from-indexes (:indexes rel) tuple)]
- (assoc rel :data new-data :indexes idxs))))))
-
-(defn add-tuples
- "Adds a collection of tuples to the db, as
- (add-tuples db
- [:rel-name :key-1 1 :key-2 2]
- [:rel-name :key-1 2 :key-2 3])"
- [db & tupls]
- (reduce #(add-tuple %1 (first %2) (apply hash-map (next %2))) db tupls))
-
-(defn- find-indexes
- "Given a map of indexes and a partial tuple, return the sets of full tuples"
- [idxs pt]
- (if (empty? idxs)
- nil
- (filter identity (for [key (keys pt)]
- (if-let [idx-map (idxs key)]
- (get idx-map (pt key) #{})
- nil)))))
-
-(defn- match?
- "Is m2 contained in m1?"
- [m1 m2]
- (let [compare (fn [key]
- (and (contains? m1 key)
- (= (m1 key) (m2 key))))]
- (every? compare (keys m2))))
-
-(defn- scan-space
- "Computes a stream of tuples from relation rn matching partial tuple (pt)
- and applies fun to each"
- [fun db rn pt]
- (let [rel (db rn)
- idxs (find-indexes (:indexes rel) pt)
- space (if (empty? idxs)
- (:data rel) ; table scan :(
- (reduce intersection idxs))]
- (trace-datalog (when (empty? idxs)
- (println (format "Table scan of %s: %s rows!!!!!"
- rn
- (count space)))))
- (fun #(match? % pt) space)))
-
-(defn select
- "finds all matching tuples to the partial tuple (pt) in the relation named (rn)"
- [db rn pt]
- (scan-space filter db rn pt))
-
-(defn any-match?
- "Finds if there are any matching records for the partial tuple"
- [db rn pt]
- (if (= (-> pt keys set) (:schema (db rn)))
- (contains? (:data (db rn)) pt)
- (scan-space some db rn pt)))
-
-
-;;; Merge
-
-(defn merge-indexes
- [idx1 idx2]
- (merge-with (fn [h1 h2] (merge-with union h1 h2)) idx1 idx2))
-
-(defn merge-relations
- "Merges two relations"
- [r1 r2]
- (assert (= (:schema r1) (:schema r2)))
- (let [merged-indexes (merge-indexes (:indexes r1)
- (:indexes r2))
- merged-data (union (:data r1)
- (:data r2))]
- (assoc r1 :data merged-data :indexes merged-indexes)))
-
-(defn database-merge
- "Merges databases together"
- [dbs]
- (apply merge-with merge-relations dbs))
-
-(defn database-merge-parallel
- "Merges databases together in parallel"
- [dbs]
- (preduce merge-relations dbs))
-
-
-;; End of file
diff --git a/src/clojure/contrib/datalog/example.clj b/src/clojure/contrib/datalog/example.clj
deleted file mode 100644
index 88fcf961..00000000
--- a/src/clojure/contrib/datalog/example.clj
+++ /dev/null
@@ -1,116 +0,0 @@
-;; Copyright (c) Jeffrey Straszheim. All rights reserved. The use and
-;; distribution terms for this software are covered by the Eclipse Public
-;; License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) 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
-
-
-(ns clojure.contrib.datalog.example
- (:use [clojure.contrib.datalog :only (build-work-plan run-work-plan)]
- [clojure.contrib.datalog.rules :only (<- ?- rules-set)]
- [clojure.contrib.datalog.database :only (make-database add-tuples)]
- [clojure.contrib.datalog.util :only (*trace-datalog*)]))
-
-
-
-
-(def db-base
- (make-database
- (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
- (rules-set
- (<- (: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"})
-
-(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"}))
-
-(def wp-3 (build-work-plan rules (?- :bj :name '??name :boss ?x)))
-(run-work-plan wp-3 db {'??name "Albert"})
-
-(def wp-4 (build-work-plan rules (?- :works-for :employee ?x :boss ?y)))
-(run-work-plan wp-4 db {})
-
-
-;; End of file
diff --git a/src/clojure/contrib/datalog/literals.clj b/src/clojure/contrib/datalog/literals.clj
deleted file mode 100644
index 12605160..00000000
--- a/src/clojure/contrib/datalog/literals.clj
+++ /dev/null
@@ -1,414 +0,0 @@
-;; Copyright (c) Jeffrey Straszheim. All rights reserved. The use and
-;; distribution terms for this software are covered by the Eclipse Public
-;; License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) 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.
-;;
-;; literals.clj
-;;
-;; A Clojure implementation of Datalog -- Literals
-;;
-;; straszheimjeffrey (gmail)
-;; Created 25 Feburary 2009
-
-
-(ns clojure.contrib.datalog.literals
- (:use clojure.contrib.datalog.util)
- (:use clojure.contrib.datalog.database)
- (:use [clojure.set :only (intersection)])
- (:use [clojure.contrib.set :only (subset?)])
- (:use [clojure.contrib.seq-utils :only (flatten)]))
-
-
-;;; Type Definitions
-
-(defstruct atomic-literal
- :predicate ; The predicate name
- :term-bindings ; A map of column names to bindings
- :literal-type) ; ::literal or ::negated
-
-(derive ::negated ::literal)
-
-(defstruct conditional-literal
- :fun ; The fun to call
- :symbol ; The fun symbol (for display)
- :terms ; The formal arguments
- :literal-type) ; ::conditional
-
-
-;;; Basics
-
-
-(defmulti literal-predicate
- "Return the predicate/relation this conditional operates over"
- :literal-type)
-
-(defmulti literal-columns
- "Return the column names this applies to"
- :literal-type)
-
-(defmulti literal-vars
- "Returns the logic vars used by this literal"
- :literal-type)
-
-(defmulti positive-vars
- "Returns the logic vars used in a positive position"
- :literal-type)
-
-(defmulti negative-vars
- "Returns the logic vars used in a negative position"
- :literal-type)
-
-(defmethod literal-predicate ::literal
- [l]
- (:predicate l))
-
-(defmethod literal-predicate ::conditional
- [l]
- nil)
-
-(defmethod literal-columns ::literal
- [l]
- (-> l :term-bindings keys set))
-
-(defmethod literal-columns ::conditional
- [l]
- nil)
-
-(defmethod literal-vars ::literal
- [l]
- (set (filter is-var? (-> l :term-bindings vals))))
-
-(defmethod literal-vars ::conditional
- [l]
- (set (filter is-var? (:terms l))))
-
-(defmethod positive-vars ::literal
- [l]
- (literal-vars l))
-
-(defmethod positive-vars ::negated
- [l]
- nil)
-
-(defmethod positive-vars ::conditional
- [l]
- nil)
-
-(defmethod negative-vars ::literal
- [l]
- nil)
-
-(defmethod negative-vars ::negated
- [l]
- (literal-vars l))
-
-(defmethod negative-vars ::conditional
- [l]
- (literal-vars l))
-
-(defn negated?
- "Is this literal a negated literal?"
- [l]
- (= (:literal-type l) ::negated))
-
-(defn positive?
- "Is this a positive literal?"
- [l]
- (= (:literal-type l) ::literal))
-
-
-;;; Building Literals
-
-(def negation-symbol 'not!)
-(def conditional-symbol 'if)
-
-(defmulti build-literal
- "(Returns an unevaluated expression (to be used in macros) of a
- literal."
- first)
-
-(defn build-atom
- "Returns an unevaluated expression (to be used in a macro) of an
- atom."
- [f type]
- (let [p (first f)
- ts (map #(if (is-var? %) `(quote ~%) %) (next f))
- b (if (seq ts) (apply assoc {} ts) nil)]
- `(struct atomic-literal ~p ~b ~type)))
-
-(defmethod build-literal :default
- [f]
- (build-atom f ::literal))
-
-(defmethod build-literal negation-symbol
- [f]
- (build-atom (rest f) ::negated))
-
-(defmethod build-literal conditional-symbol
- [f]
- (let [symbol (fnext f)
- terms (nnext f)
- fun `(fn [binds#] (apply ~symbol binds#))]
- `(struct conditional-literal
- ~fun
- '~symbol
- '~terms
- ::conditional)))
-
-
-;;; Display
-
-(defmulti display-literal
- "Converts a struct representing a literal to a normal list"
- :literal-type)
-
-(defn- display
- [l]
- (conj (-> l :term-bindings list* flatten) (literal-predicate l)))
-
-(defmethod display-literal ::literal
- [l]
- (display l))
-
-(defmethod display-literal ::negated
- [l]
- (conj (display l) negation-symbol))
-
-(defmethod display-literal ::conditional
- [l]
- (list* conditional-symbol (:symbol l) (:terms l)))
-
-
-;;; Sip computation
-
-(defmulti get-vs-from-cs
- "From a set of columns, return the vars"
- :literal-type)
-
-(defmethod get-vs-from-cs ::literal
- [l bound]
- (set (filter is-var?
- (vals (select-keys (:term-bindings l)
- bound)))))
-
-(defmethod get-vs-from-cs ::conditional
- [l bound]
- nil)
-
-
-(defmulti get-cs-from-vs
- "From a set of vars, get the columns"
- :literal-type)
-
-(defmethod get-cs-from-vs ::literal
- [l bound]
- (reduce conj
- #{}
- (remove nil?
- (map (fn [[k v]] (if (bound v) k nil))
- (:term-bindings l)))))
-
-(defmethod get-cs-from-vs ::conditional
- [l bound]
- nil)
-
-
-(defmulti get-self-bound-cs
- "Get the columns that are bound withing the literal."
- :literal-type)
-
-(defmethod get-self-bound-cs ::literal
- [l]
- (reduce conj
- #{}
- (remove nil?
- (map (fn [[k v]] (if (not (is-var? v)) k nil))
- (:term-bindings l)))))
-
-(defmethod get-self-bound-cs ::conditional
- [l]
- nil)
-
-
-(defmulti literal-appropriate?
- "When passed a set of bound vars, determines if this literal can be
- used during this point of a SIP computation."
- (fn [b l] (:literal-type l)))
-
-(defmethod literal-appropriate? ::literal
- [bound l]
- (not (empty? (intersection (literal-vars l) bound))))
-
-(defmethod literal-appropriate? ::negated
- [bound l]
- (subset? (literal-vars l) bound))
-
-(defmethod literal-appropriate? ::conditional
- [bound l]
- (subset? (literal-vars l) bound))
-
-
-(defmulti adorned-literal
- "When passed a set of bound columns, returns the adorned literal"
- (fn [l b] (:literal-type l)))
-
-(defmethod adorned-literal ::literal
- [l bound]
- (let [pred (literal-predicate l)
- bnds (intersection (literal-columns l) bound)]
- (if (empty? bound)
- l
- (assoc l :predicate {:pred pred :bound bnds}))))
-
-(defmethod adorned-literal ::conditional
- [l bound]
- l)
-
-
-(defn get-adorned-bindings
- "Get the bindings from this adorned literal."
- [pred]
- (:bound pred))
-
-(defn get-base-predicate
- "Get the base predicate from this predicate."
- [pred]
- (if (map? pred)
- (:pred pred)
- pred))
-
-
-;;; Magic Stuff
-
-(defn magic-literal
- "Create a magic version of this adorned predicate."
- [l]
- (assert (-> l :literal-type (isa? ::literal)))
- (let [pred (literal-predicate l)
- pred-map (if (map? pred) pred {:pred pred})
- bound (get-adorned-bindings pred)
- ntb (select-keys (:term-bindings l) bound)]
- (assoc l :predicate (assoc pred-map :magic true) :term-bindings ntb :literal-type ::literal)))
-
-(defn literal-magic?
- "Is this literal magic?"
- [lit]
- (let [pred (literal-predicate lit)]
- (when (map? pred)
- (:magic pred))))
-
-(defn build-seed-bindings
- "Given a seed literal, already adorned and in magic form, convert
- its bound constants to new variables."
- [s]
- (assert (-> s :literal-type (isa? ::literal)))
- (let [ntbs (map-values (fn [_] (gensym '?_gen_)) (:term-bindings s))]
- (assoc s :term-bindings ntbs)))
-
-
-;;; Semi-naive support
-
-(defn negated-literal
- "Given a literal l, return a negated version"
- [l]
- (assert (-> l :literal-type (= ::literal)))
- (assoc l :literal-type ::negated))
-
-(defn delta-literal
- "Given a literal l, return a delta version"
- [l]
- (let [pred* (:predicate l)
- pred (if (map? pred*) pred* {:pred pred*})]
- (assoc l :predicate (assoc pred :delta true))))
-
-
-;;; Database operations
-
-(defn- build-partial-tuple
- [lit binds]
- (let [tbs (:term-bindings lit)
- each (fn [[key val :as pair]]
- (if (is-var? val)
- (if-let [n (binds val)]
- [key n]
- nil)
- pair))]
- (into {} (remove nil? (map each tbs)))))
-
-(defn- project-onto-literal
- "Given a literal, and a materialized tuple, return a set of variable
- bindings."
- [lit tuple]
- (let [step (fn [binds [key val]]
- (if (and (is-var? val)
- (contains? tuple key))
- (assoc binds val (tuple key))
- binds))]
- (reduce step {} (:term-bindings lit))))
-
-
-(defn- join-literal*
- [db lit bs fun]
- (let [each (fn [binds]
- (let [pt (build-partial-tuple lit binds)]
- (fun binds pt)))]
- (when (contains? db (literal-predicate lit))
- (apply concat (map each bs)))))
-
-(defmulti join-literal
- "Given a database (db), a literal (lit) and a seq of bindings (bs),
- return a new seq of bindings by joining this literal."
- (fn [db lit bs] (:literal-type lit)))
-
-(defmethod join-literal ::literal
- [db lit bs]
- (join-literal* db lit bs (fn [binds pt]
- (map #(merge binds %)
- (map (partial project-onto-literal lit)
- (select db (literal-predicate lit) pt))))))
-
-(defmethod join-literal ::negated
- [db lit bs]
- (join-literal* db lit bs (fn [binds pt]
- (if (any-match? db (literal-predicate lit) pt)
- nil
- [binds]))))
-
-(defmethod join-literal ::conditional
- [db lit bs]
- (let [each (fn [binds]
- (let [resolve (fn [term]
- (if (is-var? term)
- (binds term)
- term))
- args (map resolve (:terms lit))]
- (if ((:fun lit) args)
- binds
- nil)))]
- (remove nil? (map each bs))))
-
-(defn project-literal
- "Project a stream of bindings onto a literal/relation. Returns a new
- db."
- ([db lit bs] (project-literal db lit bs is-var?))
- ([db lit bs var?]
- (assert (= (:literal-type lit) ::literal))
- (let [rel-name (literal-predicate lit)
- columns (-> lit :term-bindings keys)
- idxs (vec (get-adorned-bindings (literal-predicate lit)))
- db1 (ensure-relation db rel-name columns idxs)
- rel (get-relation db1 rel-name)
- step (fn [rel bindings]
- (let [step (fn [t [k v]]
- (if (var? v)
- (assoc t k (bindings v))
- (assoc t k v)))
- tuple (reduce step {} (:term-bindings lit))]
- (add-tuple rel tuple)))]
- (replace-relation db rel-name (reduce step rel bs)))))
-
-
-;; End of file
diff --git a/src/clojure/contrib/datalog/magic.clj b/src/clojure/contrib/datalog/magic.clj
deleted file mode 100644
index ff6891a4..00000000
--- a/src/clojure/contrib/datalog/magic.clj
+++ /dev/null
@@ -1,128 +0,0 @@
-;; Copyright (c) Jeffrey Straszheim. All rights reserved. The use and
-;; distribution terms for this software are covered by the Eclipse Public
-;; License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) 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.
-;;
-;; magic.clj
-;;
-;; A Clojure implementation of Datalog -- Magic Sets
-;;
-;; straszheimjeffrey (gmail)
-;; Created 18 Feburary 2009
-
-
-(ns clojure.contrib.datalog.magic
- (:use clojure.contrib.datalog.util
- clojure.contrib.datalog.literals
- clojure.contrib.datalog.rules)
- (:use [clojure.set :only (union intersection difference)]))
-
-
-;;; Adornment
-
-(defn adorn-query
- "Adorn a query"
- [q]
- (adorned-literal q (get-self-bound-cs q)))
-
-(defn adorn-rules-set
- "Adorns the given rules-set for the given query. (rs) is a
- rules-set, (q) is an adorned query."
- [rs q]
- (let [i-preds (all-predicates rs)
- p-map (predicate-map rs)]
- (loop [nrs empty-rules-set ; The rules set being built
- needed #{(literal-predicate q)}]
- (if (empty? needed)
- nrs
- (let [pred (first needed)
- remaining (disj needed pred)
- base-pred (get-base-predicate pred)
- bindings (get-adorned-bindings pred)
- new-rules (p-map base-pred)
- new-adorned-rules (map (partial compute-sip bindings i-preds)
- new-rules)
- new-nrs (reduce conj nrs new-adorned-rules)
- current-preds (all-predicates new-nrs)
- not-needed? (fn [pred]
- (or (current-preds pred)
- (-> pred get-base-predicate i-preds not)))
- add-pred (fn [np pred]
- (if (not-needed? pred) np (conj np pred)))
- add-preds (fn [np rule]
- (reduce add-pred np (map literal-predicate (:body rule))))
- new-needed (reduce add-preds remaining new-adorned-rules)]
- (recur new-nrs new-needed))))))
-
-
-;;; Magic !
-
-(defn seed-relation
- "Given a magic form of a query, give back the literal form of its seed
- relation"
- [q]
- (let [pred (-> q literal-predicate get-base-predicate)
- bnds (-> q literal-predicate get-adorned-bindings)]
- (with-meta (assoc q :predicate [pred :magic-seed bnds]) {})))
-
-(defn seed-rule
- "Given an adorned query, give back its seed rule"
- [q]
- (let [mq (build-seed-bindings (magic-literal q))
- sr (seed-relation mq)]
- (build-rule mq [sr])))
-
-(defn build-partial-tuple
- "Given a query and a set of bindings, build a partial tuple needed
- to extract the relation from the database."
- [q bindings]
- (into {} (remove nil? (map (fn [[k v :as pair]]
- (if (is-var? v)
- nil
- (if (is-query-var? v)
- [k (bindings v)]
- pair)))
- (:term-bindings q)))))
-
-(defn seed-predicate-for-insertion
- "Given a query, return the predicate to use for database insertion."
- [q]
- (let [seed (-> q seed-rule :body first)
- columns (-> seed :term-bindings keys)
- new-term-bindings (-> q :term-bindings (select-keys columns))]
- (assoc seed :term-bindings new-term-bindings)))
-
-(defn magic-transform
- "Return a magic transformation of an adorned rules-set (rs). The
- (i-preds) are the predicates of the intension database. These
- default to the predicates within the rules-set."
- ([rs]
- (magic-transform rs (all-predicates rs)))
- ([rs i-preds]
- (let [not-duplicate? (fn [l mh bd]
- (or (not (empty? bd))
- (not (= (magic-literal l)
- mh))))
- xr (fn [rs rule]
- (let [head (:head rule)
- body (:body rule)
- mh (magic-literal head)
- answer-rule (build-rule head
- (concat [mh] body))
- step (fn [[rs bd] l]
- (if (and (i-preds (literal-predicate l))
- (not-duplicate? l mh bd))
- (let [nr (build-rule (magic-literal l)
- (concat [mh] bd))]
- [(conj rs nr) (conj bd l)])
- [rs (conj bd l)]))
- [nrs _] (reduce step [rs []] body)]
- (conj nrs answer-rule)))]
- (reduce xr empty-rules-set rs))))
-
-
-
-;; End of file
diff --git a/src/clojure/contrib/datalog/rules.clj b/src/clojure/contrib/datalog/rules.clj
deleted file mode 100644
index bcfe5c4c..00000000
--- a/src/clojure/contrib/datalog/rules.clj
+++ /dev/null
@@ -1,207 +0,0 @@
-;; Copyright (c) Jeffrey Straszheim. All rights reserved. The use and
-;; distribution terms for this software are covered by the Eclipse Public
-;; License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) 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.
-;;
-;; rules.clj
-;;
-;; A Clojure implementation of Datalog -- Rules Engine
-;;
-;; straszheimjeffrey (gmail)
-;; Created 2 Feburary 2009
-
-
-(ns clojure.contrib.datalog.rules
- (use clojure.contrib.datalog.util)
- (use clojure.contrib.datalog.literals
- clojure.contrib.datalog.database)
- (use [clojure.set :only (union intersection difference)])
- (use [clojure.contrib.set :only (subset?)])
- (use [clojure.contrib.except :only (throwf)]))
-
-
-(defstruct datalog-rule
- :head
- :body)
-
-(defn display-rule
- "Return the rule in a readable format."
- [rule]
- (list* '<-
- (-> rule :head display-literal)
- (map display-literal (:body rule))))
-
-(defn display-query
- "Return a query in a readable format."
- [query]
- (list* '?- (display-literal query)))
-
-
-;;; Check rule safety
-
-(defn is-safe?
- "Is the rule safe according to the datalog protocol?"
- [rule]
- (let [hv (literal-vars (:head rule))
- bpv (apply union (map positive-vars (:body rule)))
- bnv (apply union (map negative-vars (:body rule)))
- ehv (difference hv bpv)
- env (difference bnv bpv)]
- (when-not (empty? ehv)
- (throwf "Head vars %s not bound in body in rule %s" ehv rule))
- (when-not (empty? env)
- (throwf "Body vars %s not bound in negative positions in rule %s" env rule))
- rule))
-
-
-;;; Rule creation and printing
-
-(defn build-rule
- [hd bd]
- (with-meta (struct datalog-rule hd bd) {:type ::datalog-rule}))
-
-(defmacro <-
- "Build a datalog rule. Like this:
-
- (<- (:head :x ?x :y ?y) (:body-1 :x ?x :y ?y) (:body-2 :z ?z) (not! :body-3 :x ?x) (if > ?y ?z))"
- [hd & body]
- (let [head (build-atom hd :clojure.contrib.datalog.literals/literal)
- body (map build-literal body)]
- `(is-safe? (build-rule ~head [~@body]))))
-
-(defmethod print-method ::datalog-rule
- [rule #^Writer writer]
- (print-method (display-rule rule) writer))
-
-(defn return-rule-data
- "Returns an untypted rule that will be fully printed"
- [rule]
- (with-meta rule {}))
-
-(defmacro ?-
- "Define a datalog query"
- [& q]
- (let [qq (build-atom q :clojure.contrib.datalog.literals/literal)]
- `(with-meta ~qq {:type ::datalog-query})))
-
-(defmethod print-method ::datalog-query
- [query #^Writer writer]
- (print-method (display-query query) writer))
-
-
-
-;;; SIP
-
-(defn compute-sip
- "Given a set of bound column names, return an adorned sip for this
- rule. A set of intensional predicates should be provided to
- determine what should be adorned."
- [bindings i-preds rule]
- (let [next-lit (fn [bv body]
- (or (first (drop-while
- #(not (literal-appropriate? bv %))
- body))
- (first (drop-while (complement positive?) body))))
- adorn (fn [lit bvs]
- (if (i-preds (literal-predicate lit))
- (let [bnds (union (get-cs-from-vs lit bvs)
- (get-self-bound-cs lit))]
- (adorned-literal lit bnds))
- lit))
- new-h (adorned-literal (:head rule) bindings)]
- (loop [bound-vars (get-vs-from-cs (:head rule) bindings)
- body (:body rule)
- sip []]
- (if-let [next (next-lit bound-vars body)]
- (recur (union bound-vars (literal-vars next))
- (remove #(= % next) body)
- (conj sip (adorn next bound-vars)))
- (build-rule new-h (concat sip body))))))
-
-
-;;; Rule sets
-
-(defn make-rules-set
- "Given an existing set of rules, make it a 'rules-set' for
- printing."
- [rs]
- (with-meta rs {:type ::datalog-rules-set}))
-
-(def empty-rules-set (make-rules-set #{}))
-
-(defn rules-set
- "Given a collection of rules return a rules set"
- [& rules]
- (reduce conj empty-rules-set rules))
-
-(defmethod print-method ::datalog-rules-set
- [rules #^Writer writer]
- (binding [*out* writer]
- (do
- (print "(rules-set")
- (doseq [rule rules]
- (println)
- (print " ")
- (print rule))
- (println ")"))))
-
-(defn predicate-map
- "Given a rules-set, return a map of rules keyed by their predicates.
- Each value will be a set of rules."
- [rs]
- (let [add-rule (fn [m r]
- (let [pred (-> r :head literal-predicate)
- os (get m pred #{})]
- (assoc m pred (conj os r))))]
- (reduce add-rule {} rs)))
-
-(defn all-predicates
- "Given a rules-set, return all defined predicates"
- [rs]
- (set (map literal-predicate (map :head rs))))
-
-(defn non-base-rules
- "Return a collection of rules that depend, somehow, on other rules"
- [rs]
- (let [pred (all-predicates rs)
- non-base (fn [r]
- (if (some #(pred %)
- (map literal-predicate (:body r)))
- r
- nil))]
- (remove nil? (map non-base rs))))
-
-
-;;; Database operations
-
-(def empty-bindings [{}])
-
-(defn apply-rule
- "Apply the rule against db-1, adding the results to the appropriate
- relation in db-2. The relation will be created if needed."
- ([db rule] (apply-rule db db rule))
- ([db-1 db-2 rule]
- (trace-datalog (println)
- (println)
- (println "--------------- Begin Rule ---------------")
- (println rule))
- (let [head (:head rule)
- body (:body rule)
- step (fn [bs lit]
- (trace-datalog (println bs)
- (println lit))
- (join-literal db-1 lit bs))
- bs (reduce step empty-bindings body)]
- (do (trace-datalog (println bs))
- (project-literal db-2 head bs)))))
-
-(defn apply-rules-set
- [db rs]
- (reduce (fn [rdb rule]
- (apply-rule db rdb rule)) db rs))
-
-
-;; End of file \ No newline at end of file
diff --git a/src/clojure/contrib/datalog/softstrat.clj b/src/clojure/contrib/datalog/softstrat.clj
deleted file mode 100644
index b65434c4..00000000
--- a/src/clojure/contrib/datalog/softstrat.clj
+++ /dev/null
@@ -1,161 +0,0 @@
-;; Copyright (c) Jeffrey Straszheim. All rights reserved. The use and
-;; distribution terms for this software are covered by the Eclipse Public
-;; License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) 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.
-;;
-;; softstrat.clj
-;;
-;; A Clojure implementation of Datalog -- Soft Stratification
-;;
-;; straszheimjeffrey (gmail)
-;; Created 28 Feburary 2009
-
-
-(ns clojure.contrib.datalog.softstrat
- (:use clojure.contrib.datalog.util
- clojure.contrib.datalog.database
- clojure.contrib.datalog.literals
- clojure.contrib.datalog.rules
- clojure.contrib.datalog.magic)
- (:use [clojure.set :only (union intersection difference)])
- (:use [clojure.contrib.seq-utils :only (indexed)])
- (:require [clojure.contrib.graph :as graph]))
-
-
-;;; Dependency graph
-
-(defn- build-rules-graph
- "Given a rules-set (rs), build a graph where each predicate symbol in rs,
- there is a node n, and for each rule (<- h b-1 b-2 ...), there are edges
- from the (literal-predicate h) -> (literal-predicate b-*), one for each
- b-*."
- [rs]
- (let [preds (all-predicates rs)
- pred-map (predicate-map rs)
- step (fn [nbs pred]
- (let [rules (pred-map pred)
- preds (reduce (fn [pds lits]
- (reduce (fn [pds lit]
- (if-let [pred (literal-predicate lit)]
- (conj pds pred)
- pds))
- pds
- lits))
- #{}
- (map :body rules))]
- (assoc nbs pred preds)))
- neighbors (reduce step {} preds)]
- (struct graph/directed-graph preds neighbors)))
-
-(defn- build-def
- "Given a rules-set, build its def function"
- [rs]
- (let [pred-map (predicate-map rs)
- graph (-> rs
- build-rules-graph
- graph/transitive-closure
- graph/add-loops)]
- (fn [pred]
- (apply union (map set (map pred-map (graph/get-neighbors graph pred)))))))
-
-
-;;; Soft Stratificattion REQ Graph
-
-(defn- req
- "Returns a rules-set that is a superset of req(lit) for the lit at
- index lit-index"
- [rs soft-def rule lit-index]
- (let [head (:head rule)
- body (:body rule)
- lit (nth body lit-index)
- pre (subvec (vec body) 0 lit-index)]
- (conj (-> lit literal-predicate soft-def (magic-transform (all-predicates rs)))
- (build-rule (magic-literal lit) pre))))
-
-(defn- rule-dep
- "Given a rule, return the set of rules it depends on."
- [rs mrs soft-def rule]
- (let [step (fn [nrs [idx lit]]
- (if (negated? lit)
- (union nrs (req rs soft-def rule idx))
- nrs))]
- (intersection mrs
- (reduce step empty-rules-set (-> rule :body indexed)))))
-
-(defn- soft-strat-graph
- "The dependency graph for soft stratification."
- [rs mrs]
- (let [soft-def (build-def rs)
- step (fn [nbrs rule]
- (assoc nbrs rule (rule-dep rs mrs soft-def rule)))
- nbrs (reduce step {} mrs)]
- (struct graph/directed-graph mrs nbrs)))
-
-(defn- build-soft-strat
- "Given a rules-set (unadorned) and an adorned query, return the soft
- stratified list. The rules will be magic transformed, and the
- magic seed will be appended."
- [rs q]
- (let [ars (adorn-rules-set rs q)
- mrs (conj (magic-transform ars)
- (seed-rule q))
- gr (soft-strat-graph ars mrs)]
- (map make-rules-set (graph/dependency-list gr))))
-
-
-;;; Work plan
-
-(defstruct soft-strat-work-plan
- :query
- :stratification)
-
-(defn build-soft-strat-work-plan
- "Return a work plan for the given rules-set and query"
- [rs q]
- (let [aq (adorn-query q)]
- (struct soft-strat-work-plan aq (build-soft-strat rs aq))))
-
-(defn get-all-relations
- "Return a set of all relation names defined in this workplan"
- [ws]
- (apply union (map all-predicates (:stratification ws))))
-
-
-;;; Evaluate
-
-(defn- weak-consq-operator
- [db strat]
- (trace-datalog (println)
- (println)
- (println "=============== Begin iteration ==============="))
- (let [counts (database-counts db)]
- (loop [strat strat]
- (let [rs (first strat)]
- (if rs
- (let [new-db (apply-rules-set db rs)]
- (if (= counts (database-counts new-db))
- (recur (next strat))
- new-db))
- db)))))
-
-(defn evaluate-soft-work-set
- ([ws db] (evaluate-soft-work-set ws db {}))
- ([ws db bindings]
- (let [query (:query ws)
- strat (:stratification ws)
- seed (seed-predicate-for-insertion query)
- seeded-db (project-literal db seed [bindings] is-query-var?)
- fun (fn [data]
- (weak-consq-operator data strat))
- equal (fn [db1 db2]
- (= (database-counts db1) (database-counts db2)))
- new-db (graph/fixed-point seeded-db fun nil equal)
- pt (build-partial-tuple query bindings)]
- (select new-db (literal-predicate query) pt))))
-
-
-
-;; End of file
diff --git a/src/clojure/contrib/datalog/tests/test.clj b/src/clojure/contrib/datalog/tests/test.clj
deleted file mode 100644
index 121d264e..00000000
--- a/src/clojure/contrib/datalog/tests/test.clj
+++ /dev/null
@@ -1,45 +0,0 @@
-;; Copyright (c) Jeffrey Straszheim. All rights reserved. The use and
-;; distribution terms for this software are covered by the Eclipse Public
-;; License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) 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.
-;;
-;; test.clj
-;;
-;; A Clojure implementation of Datalog -- Tests
-;;
-;; straszheimjeffrey (gmail)
-;; Created 11 Feburary 2009
-
-(ns clojure.contrib.datalog.tests.test
- (:use [clojure.test :only (run-tests)])
- (:gen-class))
-
-(def test-names [:test-util
- :test-database
- :test-literals
- :test-rules
- :test-magic
- :test-softstrat])
-
-(def test-namespaces
- (map #(symbol (str "clojure.contrib.datalog.tests." (name %)))
- test-names))
-
-(defn run
- "Runs all defined tests"
- []
- (println "Loading tests...")
- (apply require :reload-all test-namespaces)
- (apply run-tests test-namespaces))
-
-(defn -main
- "Run all defined tests from the command line"
- [& args]
- (run)
- (System/exit 0))
-
-
-;; End of file
diff --git a/src/clojure/contrib/datalog/tests/test_database.clj b/src/clojure/contrib/datalog/tests/test_database.clj
deleted file mode 100644
index 77719008..00000000
--- a/src/clojure/contrib/datalog/tests/test_database.clj
+++ /dev/null
@@ -1,153 +0,0 @@
-;; Copyright (c) Jeffrey Straszheim. All rights reserved. The use and
-;; distribution terms for this software are covered by the Eclipse Public
-;; License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) 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.
-;;
-;; test-database.clj
-;;
-;; A Clojure implementation of Datalog -- Database
-;;
-;; straszheimjeffrey (gmail)
-;; Created 12 Feburary 2009
-
-
-(ns clojure.contrib.datalog.tests.test-database
- (:use clojure.test
- clojure.contrib.datalog.database))
-
-
-(def test-db
- (make-database
- (relation :fred [:mary :sue])
- (index :fred :mary)
- (relation :sally [:jen :becky :joan])
- (index :sally :jen)
- (index :sally :becky)))
-
-(deftest test-make-database
- (is (= test-db
- (datalog-database
- {:sally (datalog-relation
- #{:jen :joan :becky}
- #{}
- {:becky {}
- :jen {}})
- :fred (datalog-relation
- #{:sue :mary}
- #{}
- {:mary {}})}))))
-
-
-(deftest test-ensure-relation
- (is (contains? (ensure-relation test-db :bob [:sam :george] [:sam]) :bob))
- (is (contains? (ensure-relation test-db :fred [:mary :sue] [:mary]) :fred))
- (is (thrown? AssertionError (ensure-relation test-db :fred [:bob :joe] []))))
-
-(deftest test-add-tuple
- (let [new-db (add-tuple test-db :fred {:mary 1 :sue 2})]
- (is (= (select new-db :fred {:mary 1}) [{:mary 1 :sue 2}])))
- (is (thrown? AssertionError (add-tuple test-db :fred {:mary 1}))))
-
-(def test-db-1
- (add-tuples test-db
- [:fred :mary 1 :sue 2]
- [:fred :mary 2 :sue 3]
- [:sally :jen 1 :becky 2 :joan 0]
- [:sally :jen 1 :becky 4 :joan 3]
- [:sally :jen 1 :becky 3 :joan 0]
- [:sally :jen 1 :becky 2 :joan 3]
- [:fred :mary 1 :sue 1]
- [:fred :mary 3 :sue 1]))
-
-(deftest test-add-tuples
- (is (= test-db-1
- (datalog-database
- {:sally (datalog-relation
- #{:jen :joan :becky}
- #{{:jen 1, :joan 0, :becky 3}
- {:jen 1, :joan 0, :becky 2}
- {:jen 1, :joan 3, :becky 2}
- {:jen 1, :joan 3, :becky 4}}
- {:becky {3
- #{{:jen 1, :joan 0, :becky 3}}
- 4
- #{{:jen 1, :joan 3, :becky 4}}
- 2
- #{{:jen 1, :joan 0, :becky 2}
- {:jen 1, :joan 3, :becky 2}}}
- :jen {1
- #{{:jen 1, :joan 0, :becky 3}
- {:jen 1, :joan 0, :becky 2}
- {:jen 1, :joan 3, :becky 2}
- {:jen 1, :joan 3, :becky 4}}}})
- :fred (datalog-relation
- #{:sue :mary}
- #{{:sue 2, :mary 1}
- {:sue 1, :mary 1}
- {:sue 3, :mary 2}
- {:sue 1, :mary 3}}
- {:mary {3
- #{{:sue 1, :mary 3}}
- 2
- #{{:sue 3, :mary 2}}
- 1
- #{{:sue 2, :mary 1}
- {:sue 1, :mary 1}}}})}))))
-
-(deftest test-remove-tuples
- (let [db (reduce #(apply remove-tuple %1 (first %2) (next %2))
- test-db-1
- [[:fred {:mary 1 :sue 1}]
- [:fred {:mary 3 :sue 1}]
- [:sally {:jen 1 :becky 2 :joan 0}]
- [:sally {:jen 1 :becky 4 :joan 3}]])]
- (is (= db
- (datalog-database
- {:sally (datalog-relation
- #{:jen :joan :becky}
- #{{:jen 1, :joan 0, :becky 3}
- {:jen 1, :joan 3, :becky 2}}
- {:becky
- {3
- #{{:jen 1, :joan 0, :becky 3}}
- 2
- #{{:jen 1, :joan 3, :becky 2}}}
- :jen
- {1
- #{{:jen 1, :joan 0, :becky 3}
- {:jen 1, :joan 3, :becky 2}}}})
- :fred (datalog-relation
- #{:sue :mary}
- #{{:sue 2, :mary 1}
- {:sue 3, :mary 2}}
- {:mary
- {2
- #{{:sue 3, :mary 2}}
- 1
- #{{:sue 2, :mary 1}}}})})))))
-
-
-
-(deftest test-select
- (is (= (set (select test-db-1 :sally {:jen 1 :becky 2}))
- #{{:jen 1 :joan 0 :becky 2} {:jen 1 :joan 3 :becky 2}}))
- (is (= (set (select test-db-1 :fred {:sue 1})))
- #{{:mary 3 :sue 1} {:mary 1 :sue 1}})
- (is (empty? (select test-db-1 :sally {:joan 5 :jen 1}))))
-
-(deftest test-any-match?
- (is (any-match? test-db-1 :fred {:mary 3}))
- (is (any-match? test-db-1 :sally {:jen 1 :becky 2 :joan 3}))
- (is (not (any-match? test-db-1 :sally {:jen 5})))
- (is (not (any-match? test-db-1 :fred {:mary 1 :sue 5}))))
-
-
-(comment
- (run-tests)
-)
-
-;; End of file
-
diff --git a/src/clojure/contrib/datalog/tests/test_literals.clj b/src/clojure/contrib/datalog/tests/test_literals.clj
deleted file mode 100644
index 36ee5147..00000000
--- a/src/clojure/contrib/datalog/tests/test_literals.clj
+++ /dev/null
@@ -1,187 +0,0 @@
-;; Copyright (c) Jeffrey Straszheim. All rights reserved. The use and
-;; distribution terms for this software are covered by the Eclipse Public
-;; License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) 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.
-;;
-;; test-literals.clj
-;;
-;; A Clojure implementation of Datalog -- Literals tests
-;;
-;; straszheimjeffrey (gmail)
-;; Created 25 Feburary 2009
-
-
-(ns clojure.contrib.datalog.tests.test-literals
- (:use clojure.test)
- (:use clojure.contrib.datalog.literals
- clojure.contrib.datalog.database))
-
-
-(def pl (eval (build-literal '(:fred :x ?x :y ?y :z 3))))
-(def nl (eval (build-literal '(not! :fred :x ?x :y ?y :z 3))))
-(def cl (eval (build-literal '(if > ?x 3))))
-
-(def bl (eval (build-literal '(:fred))))
-
-(def bns {:x '?x :y '?y :z 3})
-
-(deftest test-build-literal
- (is (= (:predicate pl) :fred))
- (is (= (:term-bindings pl) bns))
- (is (= (:predicate nl) :fred))
- (is (= (:term-bindings nl) bns))
- (is (= (:symbol cl) '>))
- (is (= (:terms cl) '(?x 3)))
- (is ((:fun cl) [4 3]))
- (is (not ((:fun cl) [2 4])))
- (is (= (:predicate bl) :fred)))
-
-(deftest test-literal-predicate
- (is (= (literal-predicate pl) :fred))
- (is (= (literal-predicate nl) :fred))
- (is (nil? (literal-predicate cl)))
- (is (= (literal-predicate bl) :fred)))
-
-(deftest test-literal-columns
- (is (= (literal-columns pl) #{:x :y :z}))
- (is (= (literal-columns nl) #{:x :y :z}))
- (is (nil? (literal-columns cl)))
- (is (empty? (literal-columns bl))))
-
-(deftest test-literal-vars
- (is (= (literal-vars pl) #{'?x '?y}))
- (is (= (literal-vars nl) #{'?x '?y}))
- (is (= (literal-vars cl) #{'?x}))
- (is (empty? (literal-vars bl))))
-
-(deftest test-positive-vars
- (is (= (positive-vars pl) (literal-vars pl)))
- (is (nil? (positive-vars nl)))
- (is (nil? (positive-vars cl)))
- (is (empty? (positive-vars bl))))
-
-(deftest test-negative-vars
- (is (nil? (negative-vars pl)))
- (is (= (negative-vars nl) (literal-vars nl)))
- (is (= (negative-vars cl) (literal-vars cl)))
- (is (empty? (negative-vars bl))))
-
-(deftest test-negated?
- (is (not (negated? pl)))
- (is (negated? nl))
- (is (not (negated? cl))))
-
-(deftest test-vs-from-cs
- (is (= (get-vs-from-cs pl #{:x}) #{'?x}))
- (is (empty? (get-vs-from-cs pl #{:z})))
- (is (= (get-vs-from-cs pl #{:x :r}) #{'?x}))
- (is (empty? (get-vs-from-cs pl #{}))))
-
-(deftest test-cs-from-vs
- (is (= (get-cs-from-vs pl #{'?x}) #{:x}))
- (is (= (get-cs-from-vs pl #{'?x '?r}) #{:x}))
- (is (empty? (get-cs-from-vs pl #{}))))
-
-(deftest test-literal-appropriate?
- (is (not (literal-appropriate? #{} pl)))
- (is (literal-appropriate? #{'?x} pl))
- (is (not (literal-appropriate? #{'?x} nl)))
- (is (literal-appropriate? #{'?x '?y} nl))
- (is (not (literal-appropriate? #{'?z} cl)))
- (is (literal-appropriate? #{'?x} cl)))
-
-(deftest test-adorned-literal
- (is (= (literal-predicate (adorned-literal pl #{:x}))
- {:pred :fred :bound #{:x}}))
- (is (= (literal-predicate (adorned-literal nl #{:x :y :q}))
- {:pred :fred :bound #{:x :y}}))
- (is (= (:term-bindings (adorned-literal nl #{:x}))
- {:x '?x :y '?y :z 3}))
- (is (= (adorned-literal cl #{})
- cl)))
-
-(deftest test-get-adorned-bindings
- (is (= (get-adorned-bindings (literal-predicate (adorned-literal pl #{:x})))
- #{:x}))
- (is (= (get-adorned-bindings (literal-predicate pl))
- nil)))
-
-(deftest test-get-base-predicate
- (is (= (get-base-predicate (literal-predicate (adorned-literal pl #{:x})))
- :fred))
- (is (= (get-base-predicate (literal-predicate pl))
- :fred)))
-
-(deftest test-magic-literal
- (is (= (magic-literal pl)
- {:predicate {:pred :fred :magic true}, :term-bindings {}, :literal-type :clojure.contrib.datalog.literals/literal}))
- (is (= (magic-literal (adorned-literal pl #{:x}))
- {:predicate {:pred :fred :magic true :bound #{:x}},
- :term-bindings {:x '?x},
- :literal-type :clojure.contrib.datalog.literals/literal})))
-
-(comment
- (use 'clojure.contrib.stacktrace) (e)
- (use :reload 'clojure.contrib.datalog.literals)
-)
-
-
-(def db1 (make-database
- (relation :fred [:x :y])
- (index :fred :x)
- (relation :sally [:x])))
-
-(def db2 (add-tuples db1
- [:fred :x 1 :y :mary]
- [:fred :x 1 :y :becky]
- [:fred :x 3 :y :sally]
- [:fred :x 4 :y :joe]
- [:sally :x 1]
- [:sally :x 2]))
-
-(def lit1 (eval (build-literal '(:fred :x ?x :y ?y))))
-(def lit2 (eval (build-literal '(not! :fred :x ?x))))
-(def lit3 (eval (build-literal '(if > ?x ?y))))
-(def lit4 (adorned-literal (eval (build-literal '(:joan :x ?x :y ?y))) #{:x}))
-
-(deftest test-join-literal
- (is (= (set (join-literal db2 lit1 [{'?x 1} {'?x 2} {'?x 3}]))
- #{{'?x 1, '?y :mary} {'?x 1, '?y :becky} {'?x 3, '?y :sally}}))
- (is (= (join-literal db2 lit2 [{'?x 1} {'?x 2} {'?x 3}])
- [{'?x 2}]))
- (is (= (join-literal db2 lit3 [{'?x 1 '?y 2} {'?x 3 '?y 1}])
- [{'?x 3 '?y 1}])))
-
-(deftest test-project-literal
- (is (= ((project-literal db2 lit4 [{'?x 1 '?y 3}{'?x 4 '?y 2}]) {:pred :joan :bound #{:x}})
- (datalog-relation
- ;; Schema
- #{:y :x}
-
- ;; Data
- #{
- {:x 1, :y 3}
- {:x 4, :y 2}
- }
-
- ;; Indexes
- {
- :x
- {
- 4
- #{{:x 4, :y 2}}
- 1
- #{{:x 1, :y 3}}
- }
- }))))
-
-
-
-(comment
- (run-tests)
-)
-
-;; End of file
diff --git a/src/clojure/contrib/datalog/tests/test_magic.clj b/src/clojure/contrib/datalog/tests/test_magic.clj
deleted file mode 100644
index 7eabae78..00000000
--- a/src/clojure/contrib/datalog/tests/test_magic.clj
+++ /dev/null
@@ -1,72 +0,0 @@
-;; Copyright (c) Jeffrey Straszheim. All rights reserved. The use and
-;; distribution terms for this software are covered by the Eclipse Public
-;; License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) 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.
-;;
-;; test-magic.clj
-;;
-;; A Clojure implementation of Datalog -- Magic Tests
-;;
-;; straszheimjeffrey (gmail)
-;; Created 18 Feburary 2009
-
-(ns clojure.contrib.datalog.tests.test-magic
- (:use clojure.test)
- (:use clojure.contrib.datalog.magic
- clojure.contrib.datalog.rules))
-
-
-
-(def rs (rules-set
- (<- (:p :x ?x :y ?y) (:e :x ?x :y ?y))
- (<- (:p :x ?x :y ?y) (:e :x ?x :y ?z) (:p :x ?z :y ?y))
- (<- (:e :x ?x :y ?y) (:b :x ?x :y ?y))
- (<- (:e :x ?y :y ?y) (:c :x ?x :y ?y))))
-
-(def q (adorn-query (?- :p :x 1 :y ?y)))
-
-(def ars (adorn-rules-set rs q))
-
-(deftest test-adorn-rules-set
- (is (= ars
- (rules-set
- (<- ({:pred :p :bound #{:x}} :y ?y :x ?x) ({:pred :e :bound #{:x}} :y ?y :x ?x))
- (<- ({:pred :p :bound #{:x}} :y ?y :x ?x) ({:pred :e :bound #{:x}} :y ?z :x ?x)
- ({:pred :p :bound #{:x}} :y ?y :x ?z))
- (<- ({:pred :e :bound #{:x}} :y ?y :x ?y) (:c :y ?y :x ?x))
- (<- ({:pred :e :bound #{:x}} :y ?y :x ?x) (:b :y ?y :x ?x))))))
-
-
-(def m (magic-transform ars))
-
-(deftest test-magic-transform
- (is (= m
- (rules-set
- (<- ({:pred :e :bound #{:x}} :y ?y :x ?y) ({:pred :e :magic true :bound #{:x}} :x ?y) (:c :y ?y :x ?x))
-
- (<- ({:pred :e :bound #{:x}} :y ?y :x ?x) ({:pred :e :magic true :bound #{:x}} :x ?x) (:b :y ?y :x ?x))
-
- (<- ({:pred :p :magic true :bound #{:x}} :x ?z) ({:pred :p :magic true :bound #{:x}} :x ?x)
- ({:pred :e :bound #{:x}} :y ?z :x ?x))
-
- (<- ({:pred :p :bound #{:x}} :y ?y :x ?x) ({:pred :p :magic true :bound #{:x}} :x ?x)
- ({:pred :e :bound #{:x}} :y ?z :x ?x)
- ({:pred :p :bound #{:x}} :y ?y :x ?z))
-
- (<- ({:pred :e :magic true :bound #{:x}} :x ?x) ({:pred :p :magic true :bound #{:x}} :x ?x))
-
- (<- ({:pred :p :bound #{:x}} :y ?y :x ?x) ({:pred :p :magic true :bound #{:x}} :x ?x)
- ({:pred :e :bound #{:x}} :y ?y :x ?x))))))
-
-
-
-
-(comment
- (run-tests)
-)
-
-;; End of file
-
diff --git a/src/clojure/contrib/datalog/tests/test_rules.clj b/src/clojure/contrib/datalog/tests/test_rules.clj
deleted file mode 100644
index 8b80b770..00000000
--- a/src/clojure/contrib/datalog/tests/test_rules.clj
+++ /dev/null
@@ -1,130 +0,0 @@
-;; Copyright (c) Jeffrey Straszheim. All rights reserved. The use and
-;; distribution terms for this software are covered by the Eclipse Public
-;; License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) 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.
-;;
-;; test-rules.clj
-;;
-;; A Clojure implementation of Datalog -- Rule Tests
-;;
-;; straszheimjeffrey (gmail)
-;; Created 12 Feburary 2009
-
-
-(ns clojure.contrib.datalog.tests.test-rules
- (:use clojure.test
- clojure.contrib.datalog.rules
- clojure.contrib.datalog.literals
- clojure.contrib.datalog.database))
-
-
-(def tr-1 (<- (:fred :x ?x :y ?y) (:mary :x ?x :z ?z) (:sally :z ?z :y ?y)))
-(def tr-2 (<- (:fred) (not! :mary :x 3)))
-(def tr-3 (<- (:fred :x ?x :y ?y) (if > ?x ?y) (:mary :x ?x) (:sally :y ?y)))
-
-
-
-(deftest test-rule-safety
- (is (thrown-with-msg? Exception #".*Head vars.*not bound.*"
- (<- (:fred :x ?x) (:sally :y ?y))))
- (is (thrown-with-msg? Exception #".*Body vars.*not bound.*negative position.*"
- (<- (:fred :x ?x) (:becky :x ?x) (not! :sally :y ?y))))
- (is (thrown-with-msg? Exception #".*Body vars.*not bound.*negative position.*"
- (<- (:fred :x ?x) (:becky :x ?x) (if > ?x ?y)))))
-
-
-(deftest test-sip
- (is (= (compute-sip #{:x} #{:mary :sally} tr-1)
- (<- ({:pred :fred :bound #{:x}} :x ?x :y ?y)
- ({:pred :mary :bound #{:x}} :z ?z :x ?x)
- ({:pred :sally :bound #{:z}} :y ?y :z ?z))))
-
- (is (= (compute-sip #{} #{:mary :sally} tr-1)
- (<- (:fred :y ?y :x ?x) (:mary :z ?z :x ?x) ({:pred :sally :bound #{:z}} :y ?y :z ?z))))
-
- (is (= (compute-sip #{} #{:mary} tr-2)
- (<- (:fred) (not! {:pred :mary :bound #{:x}} :x 3))))
-
- (is (= (compute-sip #{} #{} tr-2)
- tr-2))
-
- (is (= (display-rule (compute-sip #{:x} #{:mary :sally} tr-3))
- (display-rule (<- ({:pred :fred :bound #{:x}} :x ?x :y ?y)
- ({:pred :mary :bound #{:x}} :x ?x)
- (:sally :y ?y)
- (if > ?x ?y))))))
- ; Display rule is used because = does not work on
- ; (if > ?x ?y) because it contains a closure
-
-
-(def rs
- (rules-set
- (<- (:path :a ?x :b ?y) (:edge :a ?x :b ?y))
- (<- (:path :a ?x :b ?y) (:edge :a ?x :b ?z) (:path :a ?z :b ?y))
- (<- (:edge :a ?x :b ?y) (:route :a ?x :b ?y) (if not= ?x ?y))))
-
-(deftest test-rules-set
- (is (= (count rs) 3))
- (is (contains? rs (<- (:path :a ?x :b ?y) (:edge :a ?x :b ?z) (:path :a ?z :b ?y)))))
-
-(deftest test-predicate-map
- (let [pm (predicate-map rs)]
- (is (= (pm :path)
- #{(<- (:path :a ?x :b ?y) (:edge :a ?x :b ?y))
- (<- (:path :a ?x :b ?y) (:edge :a ?x :b ?z) (:path :a ?z :b ?y))}))
- (is (= (-> :edge pm count) 1))))
-
-
-(def db1 (make-database
- (relation :fred [:x :y])
- (index :fred :x)
- (relation :sally [:x])
- (relation :ben [:y])))
-
-(def db2 (add-tuples db1
- [:fred :x 1 :y :mary]
- [:fred :x 1 :y :becky]
- [:fred :x 3 :y :sally]
- [:fred :x 4 :y :joe]
- [:fred :x 4 :y :bob]
- [:sally :x 1]
- [:sally :x 2]
- [:sally :x 3]
- [:sally :x 4]
- [:ben :y :bob]))
-
-
-(deftest test-apply-rule
- (is (= (apply-rule db2 empty-database (<- (:becky :y ?y) (:sally :x ?x)
- (:fred :x ?x :y ?y)
- (not! :ben :y ?y)
- (if not= ?x 3)))
- (datalog-database
- {
- :becky
- (datalog-relation
- ;; Schema
- #{:y}
- ;; Data
- #{
- {:y :joe}
- {:y :mary}
- {:y :becky}
- }
- ;; Indexes
- {
- })
- }))))
-
-
-
-
-(comment
- (run-tests)
-)
-
-;; End of file
-
diff --git a/src/clojure/contrib/datalog/tests/test_softstrat.clj b/src/clojure/contrib/datalog/tests/test_softstrat.clj
deleted file mode 100644
index a33d8c96..00000000
--- a/src/clojure/contrib/datalog/tests/test_softstrat.clj
+++ /dev/null
@@ -1,233 +0,0 @@
-;; Copyright (c) Jeffrey Straszheim. All rights reserved. The use and
-;; distribution terms for this software are covered by the Eclipse Public
-;; License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) 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.
-;;
-;; test-softstrat.clj
-;;
-;; A Clojure implementation of Datalog -- Soft Stratification Tests
-;;
-;; straszheimjeffrey (gmail)
-;; Created 28 Feburary 2009
-
-(ns clojure.contrib.datalog.tests.test-softstrat
- (:use clojure.test)
- (:use clojure.contrib.datalog.softstrat
- clojure.contrib.datalog.magic
- clojure.contrib.datalog.rules
- clojure.contrib.datalog.database)
- (:use [clojure.contrib.set :only (subset?)]))
-
-
-
-(def rs1 (rules-set
- (<- (:p :x ?x) (:b :x ?x :y ?y :z ?z) (not! :q :x ?x) (not! :q :x ?y) (not! :q :x ?z))
- (<- (:q :x ?x) (:d :x ?x))))
-
-(def q1 (?- :p :x 1))
-
-(def ws (build-soft-strat-work-plan rs1 q1))
-
-(deftest test-soft-stratification
- (let [soft (:stratification ws)
- q (:query ws)]
- (is (= q (?- {:pred :p :bound #{:x}} :x 1)))
- (is (= (count soft) 4))
- (is (subset? (rules-set
- (<- ({:pred :q :bound #{:x}} :x ?x) ({:pred :q :magic true :bound #{:x}} :x ?x)
- (:d :x ?x))
-
- (<- ({:pred :q :magic true :bound #{:x}} :x ?x) ({:pred :p :magic true :bound #{:x}} :x ?x)
- (:b :z ?z :y ?y :x ?x)))
- (nth soft 0)))
- (is (= (nth soft 1)
- (rules-set
- (<- ({:pred :q :magic true :bound #{:x}} :x ?y) ({:pred :p :magic true :bound #{:x}} :x ?x)
- (:b :z ?z :y ?y :x ?x)
- (not! {:pred :q :bound #{:x}} :x ?x)))))
- (is (= (nth soft 2)
- (rules-set
- (<- ({:pred :q :magic true :bound #{:x}} :x ?z) ({:pred :p :magic true :bound #{:x}} :x ?x)
- (:b :z ?z :y ?y :x ?x)
- (not! {:pred :q :bound #{:x}} :x ?x)
- (not! {:pred :q :bound #{:x}} :x ?y)))))
- (is (= (nth soft 3)
- (rules-set
- (<- ({:pred :p :bound #{:x}} :x ?x) ({:pred :p :magic true :bound #{:x}} :x ?x)
- (:b :z ?z :y ?y :x ?x)
- (not! {:pred :q :bound #{:x}} :x ?x)
- (not! {:pred :q :bound #{:x}} :x ?y)
- (not! {:pred :q :bound #{:x}} :x ?z)))))))
-
-
-(def tdb-1
- (make-database
- (relation :b [:x :y :z])
- (relation :d [:x])))
-
-(def tdb-2
- (add-tuples tdb-1
- [:b :x 1 :y 2 :z 3]))
-
-(deftest test-tdb-2
- (is (= (evaluate-soft-work-set ws tdb-2 {})
- [{:x 1}])))
-
-
-
-(def tdb-3
- (add-tuples tdb-2
- [:d :x 2]
- [:d :x 3]))
-
-(deftest test-tdb-3
- (is (empty? (evaluate-soft-work-set ws tdb-3 {}))))
-
-
-
-;;;;;;;;;;;
-
-
-
-(def db-base
- (make-database
- (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])
-
- (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
- (rules-set
- (<- (: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 ws-1 (build-soft-strat-work-plan rules (?- :works-for :employee '??name :boss ?x)))
-(defn evaluate-1 [name] (set (evaluate-soft-work-set ws-1 db {'??name name})))
-
-(deftest test-ws-1
- (is (= (evaluate-1 "Albert")
- #{{:employee "Albert", :boss "Li"}
- {:employee "Albert", :boss "Sameer"}
- {:employee "Albert", :boss "Bob"}}))
- (is (empty? (evaluate-1 "Bob")))
- (is (= (evaluate-1 "John")
- #{{:employee "John", :boss "Bob"}
- {:employee "John", :boss "Mary"}})))
-
-
-(def ws-2 (build-soft-strat-work-plan rules (?- :employee-job :employee '??name :job ?x)))
-(defn evaluate-2 [name] (set (evaluate-soft-work-set ws-2 db {'??name name})))
-
-(deftest test-ws-2
- (is (= (evaluate-2 "Albert")
- #{{:employee "Albert", :job :pc-support}
- {:employee "Albert", :job :server-support}}))
- (is (= (evaluate-2 "Sameer")
- #{{:employee "Sameer", :job :programming}}))
- (is (= (evaluate-2 "Bob")
- #{{:employee "Bob", :job :accounting}
- {:employee "Bob", :job :management}
- {:employee "Bob", :job :payroll}
- {:employee "Bob", :job :pc-support}
- {:employee "Bob", :job :project-management}
- {:employee "Bob", :job :programming}
- {:employee "Bob", :job :server-support}
- {:employee "Bob", :job :sales}})))
-
-(def ws-3 (build-soft-strat-work-plan rules (?- :bj :name '??name :boss ?x)))
-(defn evaluate-3 [name] (set (evaluate-soft-work-set ws-3 db {'??name name})))
-
-(deftest test-ws-3
- (is (= (evaluate-3 "Albert")
- #{{:name "Albert", :boss "Sameer"}})))
-
-(def ws-4 (build-soft-strat-work-plan rules (?- :works-for :name ?x :boss ?x)))
-
-(deftest test-ws-4
- (is (= (set (evaluate-soft-work-set ws-4 db {}))
- #{{:employee "Miki", :boss "Bob"}
- {:employee "Albert", :boss "Li"}
- {:employee "Lilian", :boss "Sameer"}
- {:employee "Li", :boss "Bob"}
- {:employee "Lilian", :boss "Bob"}
- {:employee "Brenda", :boss "Fred"}
- {:employee "Fred", :boss "Bob"}
- {:employee "John", :boss "Bob"}
- {:employee "John", :boss "Mary"}
- {:employee "Albert", :boss "Sameer"}
- {:employee "Sameer", :boss "Bob"}
- {:employee "Albert", :boss "Bob"}
- {:employee "Brenda", :boss "Bob"}
- {:employee "Mary", :boss "Bob"}
- {:employee "Li", :boss "Sameer"}})))
-
-(comment
- (run-tests)
-)
-
-;; End of file
diff --git a/src/clojure/contrib/datalog/tests/test_util.clj b/src/clojure/contrib/datalog/tests/test_util.clj
deleted file mode 100644
index 9a5d0460..00000000
--- a/src/clojure/contrib/datalog/tests/test_util.clj
+++ /dev/null
@@ -1,69 +0,0 @@
-;; Copyright (c) Jeffrey Straszheim. All rights reserved. The use and
-;; distribution terms for this software are covered by the Eclipse Public
-;; License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) 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.
-;;
-;; test-util.clj
-;;
-;; A Clojure implementation of Datalog -- Utilities Tests
-;;
-;; straszheimjeffrey (gmail)
-;; Created 11 Feburary 2009
-
-(ns clojure.contrib.datalog.tests.test-util
- (:use clojure.test
- clojure.contrib.datalog.util)
- (:use [clojure.contrib.except :only (throwf)]))
-
-(deftest test-is-var?
- (is (is-var? '?x))
- (is (is-var? '?))
- (is (not (is-var? '??x)))
- (is (not (is-var? '??)))
- (is (not (is-var? 'x)))
- (is (not (is-var? "fred")))
- (is (not (is-var? :q))))
-
-(deftest test-map-values
- (let [map {:fred 1 :sally 2}]
- (is (= (map-values #(* 2 %) map) {:fred 2 :sally 4}))
- (is (= (map-values identity {}) {}))))
-
-(deftest test-keys-to-vals
- (let [map {:fred 1 :sally 2 :joey 3}]
- (is (= (set (keys-to-vals map [:fred :sally])) #{1 2}))
- (is (= (set (keys-to-vals map [:fred :sally :becky])) #{1 2}))
- (is (empty? (keys-to-vals map [])))
- (is (empty? (keys-to-vals {} [:fred])))))
-
-(deftest test-reverse-map
- (let [map {:fred 1 :sally 2 :joey 3}
- map-1 (assoc map :mary 3)]
- (is (= (reverse-map map) {1 :fred 2 :sally 3 :joey}))
- (is (or (= (reverse-map map-1) {1 :fred 2 :sally 3 :joey})
- (= (reverse-map map-1) {1 :fred 2 :sally 3 :mary})))))
-
-(def some-maps
- [
- { :a 1 :b 2 }
- { :c 3 :b 3 }
- { :d 4 :a 1 }
- { :g 4 :b 4 }
- { :a 2 :b 1 }
- { :e 1 :f 1 }
- ])
-
-(def reduced (preduce + some-maps))
-(def merged (apply merge-with + some-maps))
-
-(deftest test-preduce
- (is (= reduced merged)))
-
-(comment
- (run-tests)
-)
-
-; End of file
diff --git a/src/clojure/contrib/datalog/util.clj b/src/clojure/contrib/datalog/util.clj
deleted file mode 100644
index b887f85c..00000000
--- a/src/clojure/contrib/datalog/util.clj
+++ /dev/null
@@ -1,89 +0,0 @@
-;; Copyright (c) Jeffrey Straszheim. All rights reserved. The use and
-;; distribution terms for this software are covered by the Eclipse Public
-;; License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) 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.
-;;
-;; util.clj
-;;
-;; A Clojure implementation of Datalog -- Utilities
-;;
-;; straszheimjeffrey (gmail)
-;; Created 3 Feburary 2009
-
-
-(ns clojure.contrib.datalog.util
- (:use [clojure.contrib.seq-utils :only (separate)]))
-
-
-
-;;; Bindings and logic vars. A binding in a hash of logic vars to
-;;; bound values. Logic vars are any symbol prefixed with a \?.
-
-(defn is-var?
- "Is this a logic variable: e.g. a symbol prefixed with a ?"
- [sym]
- (when (symbol? sym)
- (let [name (name sym)]
- (and (= \? (first name))
- (not= \? (fnext name))))))
-
-(defn is-query-var?
- "Is this a query variable: e.g. a symbol prefixed with ??"
- [sym]
- (when (symbol? sym)
- (let [name (name sym)]
- (and (= \? (first name))
- (= \? (fnext name))))))
-
-(defn map-values
- "Like map, but works over the values of a hash map"
- [f hash]
- (let [key-vals (map (fn [[key val]] [key (f val)]) hash)]
- (if (seq key-vals)
- (apply conj (empty hash) key-vals)
- hash)))
-
-(defn keys-to-vals
- "Given a map and a collection of keys, return the collection of vals"
- [m ks]
- (vals (select-keys m ks)))
-
-(defn reverse-map
- "Reverse the keys/values of a map"
- [m]
- (into {} (map (fn [[k v]] [v k]) m)))
-
-
-;;; Preduce -- A parallel reduce over hashes
-
-(defn preduce
- "Similar to merge-with, but the contents of each key are merged in
- parallel using f.
-
- f - a function of 2 arguments.
- data - a collection of hashes."
- [f data]
- (let [data-1 (map (fn [h] (map-values #(list %) h)) data)
- merged (doall (apply merge-with concat data-1))
- ; Groups w/ multiple elements are identified for parallel processing
- [complex simple] (separate (fn [[key vals]] (> (count vals) 1)) merged)
- fold-group (fn [[key vals]] {key (reduce f vals)})
- fix-single (fn [[key [val]]] [key val])]
- (apply merge (concat (pmap fold-group merged) (map fix-single simple)))))
-
-
-;;; Debuging and Tracing
-
-(def *trace-datalog* nil)
-
-(defmacro trace-datalog
- "If *test-datalog* is set to true, run the enclosed commands"
- [& body]
- `(when *trace-datalog*
- ~@body))
-
-
-;; End of file