Skip to content

Instantly share code, notes, and snippets.

@jccc
Created July 25, 2013 19:36
Show Gist options
  • Select an option

  • Save jccc/6083025 to your computer and use it in GitHub Desktop.

Select an option

Save jccc/6083025 to your computer and use it in GitHub Desktop.
(ns clj-bunnies.simpleabm)
(def SIZE 5)
(def HISTORY 3)
(def EAT-RATE 1)
(def METABOLIC-RATE 0.3)
(def MOVE-RANGE 1)
(defn grass
[s]
(if
(<=
(->
s
:grass
:energy)
0)
(->
s
(assoc-in
[:grass
:location]
[(rand-int SIZE) (rand-int SIZE)])
(assoc-in
[:grass
:energy]
4))
s))
(defn init-state
[]
{:rabbit
{:energy 5
:location [(rand-int SIZE) (rand-int SIZE)]
:memory
{:last-n-states (vec (repeat HISTORY nil))
:last-n-energy (vec (repeat HISTORY nil))
:expected-util {}}}
:grass
{:energy 4
:location [(rand-int SIZE) (rand-int SIZE)]}})
(defn eat
[state]
(if
(=
(->
state
:rabbit
:location)
(->
state
:grass
:location))
(let [transfer-amt
(min
EAT-RATE
(->
state
:grass
:energy))]
(->
state
(update-in
[:rabbit
:energy]
+
transfer-amt)
(update-in
[:grass
:energy]
-
transfer-amt)))
state))
(defn metabolize
[state]
(update-in
state
[:rabbit :energy]
-
METABOLIC-RATE))
(defn avg
[c]
(/
(reduce + c)
(count c)))
(defn expected-utility
[state cs]
(avg
(get-in
state
[:rabbit
:memory
:expected-util
cs]
[1])))
(defn in-bounds? [[x y]]
(and
(> x -1)
(< x SIZE)
(> y -1)
(< y SIZE)))
(defn make-move
[state loc]
(assoc-in
state
[:rabbit
:location]
loc))
(defn compress-state
[state]
(let [[rx ry] (->
state
:rabbit
:location)
[gx gy] (->
state
:grass
:location)]
(+
(java.lang.Math/abs
(- rx gx))
(java.lang.Math/abs
(- ry gy)))))
(defn behavior
[state]
(let [[lx ly] (->
state
:rabbit
:location)
[bm cs] (rand-nth
(val
(first
(reduce
(fn [m [l cs :as v]]
(update-in
m
[(expected-utility state cs)]
conj
v))
(sorted-map-by >)
(list*
[[lx ly]
(compress-state state)]
(for [i (range -1 2) ;direction
j (range -1 2) ;direction
r (range 1 (inc MOVE-RANGE))
:let [loc [(+ lx (* r i)) (+ ly (* r j))]]
:while (in-bounds? loc)]
[loc
(compress-state
(make-move state loc))]))))))]
(->
state
(make-move bm)
(update-in [:rabbit :memory :last-n-states] conj cs))))
(defn indexed [s]
(map vector (range) s))
(defn discounted-diffs
[r]
(if (nil? (first r)) 0
(reduce
+
(for [[i j] (indexed
(for [[a b]
(partition 2 1 r)]
(- b a)))]
(* (/ 1 (inc i)) j)))))
(defn learn
[state]
(let [s (->
state
:rabbit
:memory
:last-n-states
first)
r (discounted-diffs
(->
state
:rabbit
:memory
:last-n-energy))]
(->
state
(update-in
[:rabbit
:memory
:expected-util]
#(merge-with
concat
%
{s (list r)}))
(update-in
[:rabbit
:memory
:last-n-states]
subvec 1)
(update-in
[:rabbit
:memory
:last-n-energy]
#(->
%
(subvec 1)
(conj
(->
state
:rabbit
:energy)))))))
(defn bunny
[s]
(->
s
(behavior)
(metabolize)
(eat)
(learn)))
(defn dead?
[s]
(if
(<=
(->
s
:rabbit
:energy)
0)
(->
s
(assoc-in
[:grass
:location]
[(rand-int SIZE) (rand-int SIZE)])
(assoc-in
[:rabbit
:energy]
5))
s))
(defn step
[s]
(->
s
(grass)
(bunny)))
;(take 100 (iterate step (init-state)))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment