Created
March 24, 2013 16:55
-
-
Save anonymous/5232625 to your computer and use it in GitHub Desktop.
A neural network in Titan and Clojure implementing the xor function
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(ns martha.core | |
(:require [clojurewerkz.titanium.graph :as g] | |
[clojurewerkz.titanium.vertices :as v] | |
[clojurewerkz.titanium.edges :as e] | |
[clojurewerkz.titanium.types :as t] | |
[ogre.core :as q])) | |
(def conf {:storage {:backend "embeddedcassandra" | |
:hostname "127.0.0.1" | |
:keyspace "martha" | |
:cassandra-config-dir | |
(str "file://" | |
(System/getProperty "user.dir") | |
"/resources/cassandra.yaml")}}) | |
(def graph (g/open conf)) | |
(defn get-all-edges [] | |
(seq (.getEdges graph))) | |
(defn get-all-vertices [] | |
(seq (.getVertices graph))) | |
(defn clear-graph [] | |
(g/transact! | |
(doseq [edge (get-all-edges)] (.remove edge)) | |
(doseq [vs (get-all-vertices)] (v/delete! vs)))) | |
(defn new-network [] | |
(clear-graph) | |
(g/transact! | |
(let [input1 (v/create! {:type "input" :threshold 0.5 :energy 0 :input 0}) | |
input2 (v/create! {:type "input" :threshold 0.5 :energy 0 :input 1}) | |
hidden1 (v/create! {:type "hidden" :threshold 1.5 :energy 0}) | |
hidden2 (v/create! {:type "hidden" :threshold 0.5 :energy 0}) | |
output (v/create! {:type "output" :threshold 0.5 :energy 0})] | |
(e/connect! input1 :link hidden1 {:weight 1}) | |
(e/connect! input1 :link hidden2 {:weight 1}) | |
(e/connect! input2 :link hidden1 {:weight 1}) | |
(e/connect! input2 :link hidden2 {:weight 1}) | |
(e/connect! hidden1 :link output {:weight -1}) | |
(e/connect! hidden2 :link output {:weight 1})))) | |
(defn activated? [u] | |
(<= (v/get u :threshold) | |
(v/get u :energy))) | |
(defn propogate [firing] | |
(q/query firing | |
;;Edges that are firing | |
q/--E> | |
(q/as "active") | |
;;Vertices that are being hit | |
q/in-vertex | |
(q/as "vertex") | |
;;Accumulate energy | |
(q/select (q/prop :weight) identity) | |
(q/side-effect (fn [[weight u]] (v/update! u :energy + weight))) | |
;;Pull out the touched vertices | |
(q/transform second) | |
(q/dedup) | |
;;Breadth first | |
q/gather | |
q/scatter | |
q/to-list!)) | |
(defn xor-nn [& args] | |
(new-network) | |
(g/transact! | |
(doseq [u (get-all-vertices)] (v/assoc! u :energy 0)) | |
;;Load input | |
(let [update-input #(v/assoc! % :energy (nth args (v/get % :input))) | |
active-inputs (q/query (v/find-by-kv :type "input") | |
(q/side-effect update-input) | |
(q/filter activated?) | |
(q/to-list!))] | |
;;Loop through network, propogating energy and filtering thresholds | |
(loop [firing active-inputs] | |
(let [receivers (propogate firing) | |
;;Filter out only the active vertices | |
activated (doall (filter activated? receivers))] | |
(when (not (empty? activated)) | |
(recur activated)))) | |
(q/query (v/find-by-kv :type "output") | |
(q/transform #(if (activated? %) 1 0)) | |
q/into-vec!)))) | |
;; martha.core> (xor-nn 0 0) | |
;; [0] | |
;; nil | |
;; martha.core> (xor-nn 0 1) | |
;; [1] | |
;; nil | |
;; martha.core> (xor-nn 1 0) | |
;; [1] | |
;; nil | |
;; martha.core> (xor-nn 1 1) | |
;; [0] | |
;; nil |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment