Mercurial > lasercutter
diff src/clojure/contrib/datalog/softstrat.clj @ 10:ef7dbbd6452c
added clojure source goodness
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Sat, 21 Aug 2010 06:25:44 -0400 |
parents | |
children |
line wrap: on
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/clojure/contrib/datalog/softstrat.clj Sat Aug 21 06:25:44 2010 -0400 1.3 @@ -0,0 +1,161 @@ 1.4 +;; Copyright (c) Jeffrey Straszheim. All rights reserved. The use and 1.5 +;; distribution terms for this software are covered by the Eclipse Public 1.6 +;; License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) which can 1.7 +;; be found in the file epl-v10.html at the root of this distribution. By 1.8 +;; using this software in any fashion, you are agreeing to be bound by the 1.9 +;; terms of this license. You must not remove this notice, or any other, 1.10 +;; from this software. 1.11 +;; 1.12 +;; softstrat.clj 1.13 +;; 1.14 +;; A Clojure implementation of Datalog -- Soft Stratification 1.15 +;; 1.16 +;; straszheimjeffrey (gmail) 1.17 +;; Created 28 Feburary 2009 1.18 + 1.19 + 1.20 +(ns clojure.contrib.datalog.softstrat 1.21 + (:use clojure.contrib.datalog.util 1.22 + clojure.contrib.datalog.database 1.23 + clojure.contrib.datalog.literals 1.24 + clojure.contrib.datalog.rules 1.25 + clojure.contrib.datalog.magic) 1.26 + (:use [clojure.set :only (union intersection difference)]) 1.27 + (:use [clojure.contrib.seq :only (indexed)]) 1.28 + (:require [clojure.contrib.graph :as graph])) 1.29 + 1.30 + 1.31 +;;; Dependency graph 1.32 + 1.33 +(defn- build-rules-graph 1.34 + "Given a rules-set (rs), build a graph where each predicate symbol in rs, 1.35 + there is a node n, and for each rule (<- h b-1 b-2 ...), there are edges 1.36 + from the (literal-predicate h) -> (literal-predicate b-*), one for each 1.37 + b-*." 1.38 + [rs] 1.39 + (let [preds (all-predicates rs) 1.40 + pred-map (predicate-map rs) 1.41 + step (fn [nbs pred] 1.42 + (let [rules (pred-map pred) 1.43 + preds (reduce (fn [pds lits] 1.44 + (reduce (fn [pds lit] 1.45 + (if-let [pred (literal-predicate lit)] 1.46 + (conj pds pred) 1.47 + pds)) 1.48 + pds 1.49 + lits)) 1.50 + #{} 1.51 + (map :body rules))] 1.52 + (assoc nbs pred preds))) 1.53 + neighbors (reduce step {} preds)] 1.54 + (struct graph/directed-graph preds neighbors))) 1.55 + 1.56 +(defn- build-def 1.57 + "Given a rules-set, build its def function" 1.58 + [rs] 1.59 + (let [pred-map (predicate-map rs) 1.60 + graph (-> rs 1.61 + build-rules-graph 1.62 + graph/transitive-closure 1.63 + graph/add-loops)] 1.64 + (fn [pred] 1.65 + (apply union (map set (map pred-map (graph/get-neighbors graph pred))))))) 1.66 + 1.67 + 1.68 +;;; Soft Stratificattion REQ Graph 1.69 + 1.70 +(defn- req 1.71 + "Returns a rules-set that is a superset of req(lit) for the lit at 1.72 + index lit-index" 1.73 + [rs soft-def rule lit-index] 1.74 + (let [head (:head rule) 1.75 + body (:body rule) 1.76 + lit (nth body lit-index) 1.77 + pre (subvec (vec body) 0 lit-index)] 1.78 + (conj (-> lit literal-predicate soft-def (magic-transform (all-predicates rs))) 1.79 + (build-rule (magic-literal lit) pre)))) 1.80 + 1.81 +(defn- rule-dep 1.82 + "Given a rule, return the set of rules it depends on." 1.83 + [rs mrs soft-def rule] 1.84 + (let [step (fn [nrs [idx lit]] 1.85 + (if (negated? lit) 1.86 + (union nrs (req rs soft-def rule idx)) 1.87 + nrs))] 1.88 + (intersection mrs 1.89 + (reduce step empty-rules-set (-> rule :body indexed))))) 1.90 + 1.91 +(defn- soft-strat-graph 1.92 + "The dependency graph for soft stratification." 1.93 + [rs mrs] 1.94 + (let [soft-def (build-def rs) 1.95 + step (fn [nbrs rule] 1.96 + (assoc nbrs rule (rule-dep rs mrs soft-def rule))) 1.97 + nbrs (reduce step {} mrs)] 1.98 + (struct graph/directed-graph mrs nbrs))) 1.99 + 1.100 +(defn- build-soft-strat 1.101 + "Given a rules-set (unadorned) and an adorned query, return the soft 1.102 + stratified list. The rules will be magic transformed, and the 1.103 + magic seed will be appended." 1.104 + [rs q] 1.105 + (let [ars (adorn-rules-set rs q) 1.106 + mrs (conj (magic-transform ars) 1.107 + (seed-rule q)) 1.108 + gr (soft-strat-graph ars mrs)] 1.109 + (map make-rules-set (graph/dependency-list gr)))) 1.110 + 1.111 + 1.112 +;;; Work plan 1.113 + 1.114 +(defstruct soft-strat-work-plan 1.115 + :query 1.116 + :stratification) 1.117 + 1.118 +(defn build-soft-strat-work-plan 1.119 + "Return a work plan for the given rules-set and query" 1.120 + [rs q] 1.121 + (let [aq (adorn-query q)] 1.122 + (struct soft-strat-work-plan aq (build-soft-strat rs aq)))) 1.123 + 1.124 +(defn get-all-relations 1.125 + "Return a set of all relation names defined in this workplan" 1.126 + [ws] 1.127 + (apply union (map all-predicates (:stratification ws)))) 1.128 + 1.129 + 1.130 +;;; Evaluate 1.131 + 1.132 +(defn- weak-consq-operator 1.133 + [db strat] 1.134 + (trace-datalog (println) 1.135 + (println) 1.136 + (println "=============== Begin iteration ===============")) 1.137 + (let [counts (database-counts db)] 1.138 + (loop [strat strat] 1.139 + (let [rs (first strat)] 1.140 + (if rs 1.141 + (let [new-db (apply-rules-set db rs)] 1.142 + (if (= counts (database-counts new-db)) 1.143 + (recur (next strat)) 1.144 + new-db)) 1.145 + db))))) 1.146 + 1.147 +(defn evaluate-soft-work-set 1.148 + ([ws db] (evaluate-soft-work-set ws db {})) 1.149 + ([ws db bindings] 1.150 + (let [query (:query ws) 1.151 + strat (:stratification ws) 1.152 + seed (seed-predicate-for-insertion query) 1.153 + seeded-db (project-literal db seed [bindings] is-query-var?) 1.154 + fun (fn [data] 1.155 + (weak-consq-operator data strat)) 1.156 + equal (fn [db1 db2] 1.157 + (= (database-counts db1) (database-counts db2))) 1.158 + new-db (graph/fixed-point seeded-db fun nil equal) 1.159 + pt (build-partial-tuple query bindings)] 1.160 + (select new-db (literal-predicate query) pt)))) 1.161 + 1.162 + 1.163 + 1.164 +;; End of file