Created
June 6, 2018 12:23
-
-
Save whilo/03ebf7328b2abbf9090ca9294398970f to your computer and use it in GitHub Desktop.
Klipse Anglican experiment.
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 anglican.runtime$macros | |
"Runtime library" | |
(:require [clojure.string :as str] | |
[clojure.core.matrix :as m] | |
[clojure.core.matrix.linear :as ml] | |
[anglican.runtime :refer [distribution]] | |
#?(:cljs [goog.string.format])) | |
) | |
(defn- cljs-env? | |
"Take the &env from a macro, and tell whether we are expanding into cljs." | |
[env] | |
(boolean (:ns env))) | |
(defmacro if-cljs | |
"Return then if we are generating cljs code and else for Clojure code. | |
https://groups.google.com/d/msg/clojurescript/iBY5HaQda4A/w1lAQi9_AwsJ" | |
[then else] | |
(if (cljs-env? &env) then else)) | |
(defn format | |
"Similar to Java String's format function for cljs." | |
[s & args] | |
(goog.string.format s (into-array args))) | |
(defprotocol distribution | |
"random distribution" | |
(sample* [this] | |
"draws a sample from the distribution") | |
(observe* [this value] | |
"return the probability [density] of the value")) | |
(defmacro defdist | |
"defines distribution" | |
[name & args] | |
(let [[docstring parameters & args] | |
(if (string? (first args)) | |
args | |
`(~(format "%s distribution" name) ~@args)) | |
[bindings & methods] | |
(if (vector? (first args)) | |
args | |
`[[] ~@args]) | |
record-name (symbol (format "%s-distribution" name)) | |
variables (take-nth 2 bindings)] | |
`(do | |
(declare ~name) | |
(defrecord ~record-name [~@parameters ~@variables] | |
;; TODO | |
; Object | |
; (toString [~'this] | |
; (str (list '~(qualify name) ~@parameters))) | |
anglican.runtime$macros$distribution | |
~@methods) | |
(defn ~name ~docstring ~parameters | |
(let ~bindings | |
(~(symbol (format "->%s" record-name)) | |
~@parameters ~@variables))) | |
(if-cljs | |
(extend-protocol cljs.core/IPrintWithWriter | |
~record-name | |
(cljs.core/-pr-writer [o# writer# opts#] | |
(cljs.core/-write writer# (str o#)))) | |
;; TODO macro hygene? | |
(defmethod print-method ~record-name | |
[~'o ~'m] | |
(print-simple (str ~'o) ~'m)))))) | |
(do | |
;; bootstrap the uniform distribution | |
;; was imported from Apache Commons | |
(defrecord uniform-continuous-distribution [min max] | |
anglican.runtime$macros/distribution | |
(sample* [this] | |
(let [len (- max min)] | |
(+ min (* len (rand))))) | |
(observe* [this value] | |
(if (<= min value max) | |
(log (/ 1 (- max min))) | |
js/Number.NEGATIVE_INFINITY))) | |
(defn uniform-continuous | |
"Uniform continuous distribution" | |
[min max] | |
(->uniform-continuous-distribution min max)) | |
(extend-protocol cljs.core/IPrintWithWriter | |
uniform-continuous-distribution | |
(cljs.core/-pr-writer | |
[o writer opts] | |
(cljs.core/-write writer (str (type o)))))) | |
(sample* (uniform-continuous 0 3)) | |
(anglican.runtime$macros/defdist bernoulli | |
"Bernoulli distribution" | |
[p] [dist (uniform-continuous 0.0 1.0)] | |
(sample* [this] (if (< (sample* dist) p) 1 0)) | |
(observe* [this value] | |
(log (case value | |
1 p | |
0 (- 1. p) | |
0.)))) | |
(sample* (bernoulli 0.8)) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment