Move tools module for ClojureScript compatibility, and style fixes
This commit is contained in:
parent
64d43756b6
commit
4bd92503a3
@ -2,24 +2,27 @@
|
|||||||
(:gen-class)
|
(:gen-class)
|
||||||
(:require [propeller.gp :as gp]
|
(:require [propeller.gp :as gp]
|
||||||
[propeller.push.core :as push]
|
[propeller.push.core :as push]
|
||||||
(propeller.problems [simple-regression :refer [regression-error-function]]
|
(propeller.problems [simple-regression :as regression]
|
||||||
[string-classification :refer [string-classification-error-function]])))
|
[string-classification :as string-classif])))
|
||||||
|
|
||||||
(defn -main
|
(defn -main
|
||||||
"Runs propel-gp, giving it a map of arguments."
|
"Runs propel-gp, giving it a map of arguments."
|
||||||
[& args]
|
[& args]
|
||||||
(gp/gp (update-in (merge {:instructions push/default-instructions
|
(gp/gp
|
||||||
:error-function regression-error-function
|
(update-in
|
||||||
:max-generations 500
|
(merge
|
||||||
:population-size 500
|
{:instructions push/default-instructions
|
||||||
:max-initial-plushy-size 50
|
:error-function regression/error-function
|
||||||
:step-limit 100
|
:max-generations 500
|
||||||
:parent-selection :lexicase
|
:population-size 500
|
||||||
:tournament-size 5
|
:max-initial-plushy-size 50
|
||||||
:umad-rate 0.1
|
:step-limit 100
|
||||||
:variation {:umad 0.5 :crossover 0.5}
|
:parent-selection :lexicase
|
||||||
:elitism false}
|
:tournament-size 5
|
||||||
(apply hash-map
|
:umad-rate 0.1
|
||||||
(map read-string args)))
|
:variation {:umad 0.5 :crossover 0.5}
|
||||||
[:error-function]
|
:elitism false}
|
||||||
#(if (fn? %) % (eval %)))))
|
(apply hash-map
|
||||||
|
(map read-string args)))
|
||||||
|
[:error-function]
|
||||||
|
#(if (fn? %) % (eval %)))))
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
(ns propeller.gp
|
(ns propeller.gp
|
||||||
(:require [propeller.push.core :refer [instruction-table]]
|
(:require (propeller [genome :as genome]
|
||||||
(propeller [genome :as genome]
|
[variation :as variation])
|
||||||
[variation :as variation])))
|
[propeller.push.core :as push]))
|
||||||
|
|
||||||
(defn report
|
(defn report
|
||||||
"Reports information each generation."
|
"Reports information each generation."
|
||||||
@ -33,14 +33,14 @@
|
|||||||
(require '[propeller.push.instructions boolean char code input-output
|
(require '[propeller.push.instructions boolean char code input-output
|
||||||
numeric polymorphic string])
|
numeric polymorphic string])
|
||||||
(println "Done. Registered instructions:")
|
(println "Done. Registered instructions:")
|
||||||
(println (sort (keys @instruction-table))))
|
(println (sort (keys @push/instruction-table))))
|
||||||
;;
|
;;
|
||||||
(loop [generation 0
|
(loop [generation 0
|
||||||
population (repeatedly
|
population (repeatedly
|
||||||
population-size
|
population-size
|
||||||
#(hash-map :plushy
|
#(hash-map :plushy
|
||||||
(genome/make-random-plushy instructions
|
(genome/make-random-plushy instructions
|
||||||
max-initial-plushy-size)))]
|
max-initial-plushy-size)))]
|
||||||
(let [evaluated-pop (sort-by :total-error
|
(let [evaluated-pop (sort-by :total-error
|
||||||
(map (partial error-function argmap)
|
(map (partial error-function argmap)
|
||||||
population))]
|
population))]
|
||||||
|
@ -1,9 +1,8 @@
|
|||||||
(ns propeller.problems.simple-regression
|
(ns propeller.problems.simple-regression
|
||||||
(:require [propeller.genome :refer [plushy->push]]
|
(:require [propeller.genome :as genome]
|
||||||
[propeller.push.interpreter :refer [interpret-program]]
|
(propeller.push [interpreter :as interpreter]
|
||||||
[propeller.push.state :refer [empty-state
|
[state :as state])
|
||||||
peek-stack]]
|
[propeller.tools.math :as math]))
|
||||||
[tools.math :as math]))
|
|
||||||
|
|
||||||
;; =============================================================================
|
;; =============================================================================
|
||||||
;; Problem: f(x) = 7x^2 - 20x + 13
|
;; Problem: f(x) = 7x^2 - 20x + 13
|
||||||
@ -19,20 +18,20 @@
|
|||||||
[x]
|
[x]
|
||||||
(+ (* x x x) x 3))
|
(+ (* x x x) x 3))
|
||||||
|
|
||||||
(defn regression-error-function
|
(defn error-function
|
||||||
"Finds the behaviors and errors of an individual. The error is the absolute
|
"Finds the behaviors and errors of an individual. The error is the absolute
|
||||||
deviation between the target output value and the program's selected behavior,
|
deviation between the target output value and the program's selected behavior,
|
||||||
or 1000000 if no behavior is produced. The behavior is here defined as the
|
or 1000000 if no behavior is produced. The behavior is here defined as the
|
||||||
final top item on the INTEGER stack."
|
final top item on the INTEGER stack."
|
||||||
[argmap individual]
|
[argmap individual]
|
||||||
(let [program (plushy->push (:plushy individual))
|
(let [program (genome/plushy->push (:plushy individual))
|
||||||
inputs (range -10 11)
|
inputs (range -10 11)
|
||||||
correct-outputs (map target-function inputs)
|
correct-outputs (map target-function inputs)
|
||||||
outputs (map (fn [input]
|
outputs (map (fn [input]
|
||||||
(peek-stack
|
(state/peek-stack
|
||||||
(interpret-program
|
(interpreter/interpret-program
|
||||||
program
|
program
|
||||||
(assoc empty-state :input {:in1 input})
|
(assoc state/empty-state :input {:in1 input})
|
||||||
(:step-limit argmap))
|
(:step-limit argmap))
|
||||||
:integer))
|
:integer))
|
||||||
inputs)
|
inputs)
|
||||||
|
@ -1,13 +1,13 @@
|
|||||||
(ns propeller.problems.string-classification
|
(ns propeller.problems.string-classification
|
||||||
(:require [propeller.genome :as genome]
|
(:require [propeller.genome :as genome]
|
||||||
(propeller.push [state :as state]
|
(propeller.push [interpreter :as interpreter]
|
||||||
[interpreter :as interpreter])))
|
[state :as state])))
|
||||||
|
|
||||||
;; =============================================================================
|
;; =============================================================================
|
||||||
;; String classification
|
;; String classification
|
||||||
;; =============================================================================
|
;; =============================================================================
|
||||||
|
|
||||||
(defn string-classification-error-function
|
(defn error-function
|
||||||
"Finds the behaviors and errors of an individual: Error is 0 if the value and
|
"Finds the behaviors and errors of an individual: Error is 0 if the value and
|
||||||
the program's selected behavior match, or 1 if they differ, or 1000000 if no
|
the program's selected behavior match, or 1 if they differ, or 1000000 if no
|
||||||
behavior is produced. The behavior is here defined as the final top item on
|
behavior is produced. The behavior is here defined as the final top item on
|
||||||
|
@ -1,6 +1,4 @@
|
|||||||
(ns propeller.push.core
|
(ns propeller.push.core)
|
||||||
(:require [propeller.push.state :refer [get-args-from-stacks
|
|
||||||
push-to-stack]]))
|
|
||||||
|
|
||||||
;; =============================================================================
|
;; =============================================================================
|
||||||
;; PushGP Instructions
|
;; PushGP Instructions
|
||||||
@ -13,6 +11,8 @@
|
|||||||
;; TMH: ERCs?
|
;; TMH: ERCs?
|
||||||
;; =============================================================================
|
;; =============================================================================
|
||||||
|
|
||||||
|
(def instruction-table (atom (hash-map)))
|
||||||
|
|
||||||
;; Set of original propel instructions
|
;; Set of original propel instructions
|
||||||
(def default-instructions
|
(def default-instructions
|
||||||
(list :in1
|
(list :in1
|
||||||
@ -46,12 +46,6 @@
|
|||||||
"G"
|
"G"
|
||||||
"T"))
|
"T"))
|
||||||
|
|
||||||
(def instruction-table (atom (hash-map)))
|
|
||||||
|
|
||||||
(defmacro def-instruction
|
|
||||||
[instruction definition]
|
|
||||||
`(swap! instruction-table assoc '~instruction ~definition))
|
|
||||||
|
|
||||||
;; Number of blocks opened by instructions (default = 0)
|
;; Number of blocks opened by instructions (default = 0)
|
||||||
(def opens {:exec_dup 1
|
(def opens {:exec_dup 1
|
||||||
:exec_if 2})
|
:exec_if 2})
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
(ns propeller.push.instructions.boolean
|
(ns propeller.push.instructions.boolean
|
||||||
(:require [propeller.push.core :refer [def-instruction]]
|
(:require [propeller.push.utils :refer [def-instruction
|
||||||
[propeller.push.utils :refer [make-instruction]]))
|
make-instruction]]))
|
||||||
|
|
||||||
;; =============================================================================
|
;; =============================================================================
|
||||||
;; BOOLEAN Instructions
|
;; BOOLEAN Instructions
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
(ns propeller.push.instructions.char
|
(ns propeller.push.instructions.char
|
||||||
(:require [propeller.push.core :refer [def-instruction]]
|
(:require [propeller.push.utils :refer [def-instruction
|
||||||
[propeller.push.utils :refer [make-instruction]]
|
make-instruction]]
|
||||||
[tools.character :as char]))
|
[propeller.tools.character :as char]))
|
||||||
|
|
||||||
;; =============================================================================
|
;; =============================================================================
|
||||||
;; CHAR Instructions
|
;; CHAR Instructions
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
(ns propeller.push.instructions.code
|
(ns propeller.push.instructions.code
|
||||||
(:require [propeller.push.core :refer [def-instruction]]
|
(:require (propeller.push [state :as state]
|
||||||
[propeller.push.state :as state]
|
[utils :refer [def-instruction
|
||||||
[propeller.push.utils :refer [make-instruction]]))
|
make-instruction]])))
|
||||||
|
|
||||||
;; =============================================================================
|
;; =============================================================================
|
||||||
;; CODE and EXEC Instructions
|
;; CODE and EXEC Instructions
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
(ns propeller.push.instructions.input-output
|
(ns propeller.push.instructions.input-output
|
||||||
(:require [propeller.push.state :as state]
|
(:require (propeller.push [state :as state]
|
||||||
[propeller.push.core :refer [def-instruction]]))
|
[utils :refer [def-instruction]])))
|
||||||
|
|
||||||
;; =============================================================================
|
;; =============================================================================
|
||||||
;; INPUT and OUTPUT Instructions
|
;; INPUT and OUTPUT Instructions
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
(ns propeller.push.instructions.numeric
|
(ns propeller.push.instructions.numeric
|
||||||
(:require [propeller.push.core :refer [def-instruction]]
|
(:require [propeller.push.utils :refer [def-instruction
|
||||||
[propeller.push.utils :refer [generate-functions
|
generate-functions
|
||||||
make-instruction]]
|
make-instruction]]
|
||||||
[tools.math :as math]))
|
[propeller.tools.math :as math]))
|
||||||
|
|
||||||
;; =============================================================================
|
;; =============================================================================
|
||||||
;; FLOAT and INTEGER Instructions (polymorphic)
|
;; FLOAT and INTEGER Instructions (polymorphic)
|
||||||
|
@ -1,11 +1,8 @@
|
|||||||
(ns propeller.push.instructions.polymorphic
|
(ns propeller.push.instructions.polymorphic
|
||||||
(:require [propeller.push.core :refer [def-instruction]]
|
(:require (propeller.push [state :as state]
|
||||||
[propeller.push.state :refer [empty-stack?
|
[utils :refer [def-instruction
|
||||||
peek-stack
|
generate-functions
|
||||||
pop-stack
|
make-instruction]])))
|
||||||
push-to-stack]]
|
|
||||||
[propeller.push.utils :refer [generate-functions
|
|
||||||
make-instruction]]))
|
|
||||||
|
|
||||||
;; =============================================================================
|
;; =============================================================================
|
||||||
;; Polymorphic Instructions
|
;; Polymorphic Instructions
|
||||||
@ -24,10 +21,10 @@
|
|||||||
;; would negate the effect of the duplication)
|
;; would negate the effect of the duplication)
|
||||||
(defn- _dup
|
(defn- _dup
|
||||||
[stack state]
|
[stack state]
|
||||||
(let [top-item (peek-stack state stack)]
|
(let [top-item (state/peek-stack state stack)]
|
||||||
(if (empty-stack? state stack)
|
(if (state/empty-stack? state stack)
|
||||||
state
|
state
|
||||||
(push-to-stack state stack top-item))))
|
(state/push-to-stack state stack top-item))))
|
||||||
|
|
||||||
;; Duplicates n copies of the top item (i.e leaves n copies there). Does not pop
|
;; Duplicates n copies of the top item (i.e leaves n copies there). Does not pop
|
||||||
;; its argument (since that would negate the effect of the duplication). The
|
;; its argument (since that would negate the effect of the duplication). The
|
||||||
@ -39,10 +36,10 @@
|
|||||||
(if (or (and (= stack :integer)
|
(if (or (and (= stack :integer)
|
||||||
(>= (count (:integer state)) 2))
|
(>= (count (:integer state)) 2))
|
||||||
(and (not= stack :integer)
|
(and (not= stack :integer)
|
||||||
(not (empty-stack? state :integer))
|
(not (state/empty-stack? state :integer))
|
||||||
(not (empty-stack? state stack))))
|
(not (state/empty-stack? state stack))))
|
||||||
(let [n (peek-stack state :integer)
|
(let [n (state/peek-stack state :integer)
|
||||||
item-to-duplicate (peek-stack state stack)]
|
item-to-duplicate (state/peek-stack state stack)]
|
||||||
nil)
|
nil)
|
||||||
state))
|
state))
|
||||||
|
|
||||||
@ -54,7 +51,7 @@
|
|||||||
;; Pushes TRUE onto the BOOLEAN stack if the stack is empty. Otherwise FALSE
|
;; Pushes TRUE onto the BOOLEAN stack if the stack is empty. Otherwise FALSE
|
||||||
(defn- _empty
|
(defn- _empty
|
||||||
[stack state]
|
[stack state]
|
||||||
(push-to-stack state :boolean (empty-stack? state stack)))
|
(state/push-to-stack state :boolean (state/empty-stack? state stack)))
|
||||||
|
|
||||||
;; Empties the given stack
|
;; Empties the given stack
|
||||||
(defn- _flush
|
(defn- _flush
|
||||||
@ -64,7 +61,7 @@
|
|||||||
;; Pops the given stack
|
;; Pops the given stack
|
||||||
(defn- _pop
|
(defn- _pop
|
||||||
[stack state]
|
[stack state]
|
||||||
(pop-stack state stack))
|
(state/pop-stack state stack))
|
||||||
|
|
||||||
;; Rotates the top three items on the stack (i.e. pulls the third item out and
|
;; Rotates the top three items on the stack (i.e. pulls the third item out and
|
||||||
;; pushes it on top). Equivalent to (yank state stack-type 2)
|
;; pushes it on top). Equivalent to (yank state stack-type 2)
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
(ns propeller.push.instructions.string
|
(ns propeller.push.instructions.string
|
||||||
(:require [propeller.push.core :refer [def-instruction]]
|
(:require [propeller.push.utils :refer [def-instruction
|
||||||
[propeller.push.utils :refer [make-instruction]]))
|
make-instruction]]))
|
||||||
|
|
||||||
;; =============================================================================
|
;; =============================================================================
|
||||||
;; STRING Instructions
|
;; STRING Instructions
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
(ns propeller.push.interpreter
|
(ns propeller.push.interpreter
|
||||||
(:require [propeller.push.core :refer [instruction-table]]
|
(:require (propeller.push [core :as push]
|
||||||
[propeller.push.state :as state]))
|
[state :as state])))
|
||||||
|
|
||||||
(defn interpret-one-step
|
(defn interpret-one-step
|
||||||
"Takes a Push state and executes the next instruction on the exec stack."
|
"Takes a Push state and executes the next instruction on the exec stack."
|
||||||
@ -8,7 +8,7 @@
|
|||||||
(let [popped-state (state/pop-stack state :exec)
|
(let [popped-state (state/pop-stack state :exec)
|
||||||
first-instruction-raw (first (:exec state))
|
first-instruction-raw (first (:exec state))
|
||||||
first-instruction (if (keyword? first-instruction-raw)
|
first-instruction (if (keyword? first-instruction-raw)
|
||||||
(first-instruction-raw @instruction-table)
|
(first-instruction-raw @push/instruction-table)
|
||||||
first-instruction-raw)]
|
first-instruction-raw)]
|
||||||
(cond
|
(cond
|
||||||
(fn? first-instruction)
|
(fn? first-instruction)
|
||||||
|
@ -1,6 +1,10 @@
|
|||||||
(ns propeller.push.utils
|
(ns propeller.push.utils
|
||||||
(:require [propeller.push.core :refer [def-instruction]]
|
(:require (propeller.push [core :as push]
|
||||||
[propeller.push.state :as state]))
|
[state :as state])))
|
||||||
|
|
||||||
|
(defmacro def-instruction
|
||||||
|
[instruction definition]
|
||||||
|
`(swap! push/instruction-table assoc '~instruction ~definition))
|
||||||
|
|
||||||
;; A utility function for making Push instructions. Takes a state, a function
|
;; A utility function for making Push instructions. Takes a state, a function
|
||||||
;; to apply to the args, the stacks to take the args from, and the stack to
|
;; to apply to the args, the stacks to take the args from, and the stack to
|
||||||
|
@ -1,53 +1,62 @@
|
|||||||
(ns propeller.session
|
(ns propeller.session
|
||||||
(:require (propeller [gp :as gp]
|
(:require (propeller [genome :as genome]
|
||||||
[variation :as variation]
|
[gp :as gp]
|
||||||
[selection :as selection]
|
[selection :as selection]
|
||||||
[genome :as genome])
|
[variation :as variation])
|
||||||
(propeller.push [interpreter :as interpreter]
|
(propeller.push [core :as push]
|
||||||
[core :as push]
|
[interpreter :as interpreter]
|
||||||
[state :as state])
|
[state :as state])
|
||||||
(propeller.problems [simple-regression :refer [regression-error-function]]
|
(propeller.problems [simple-regression :as regression]
|
||||||
[string-classification :refer [string-classification-error-function]])))
|
[string-classification :as string-classif])))
|
||||||
|
|
||||||
#_(interpreter/interpret-program '(1 2 integer_+) empty-push-state 1000)
|
#_(interpreter/interpret-program
|
||||||
|
'(1 2 integer_add) state/empty-state 1000)
|
||||||
|
|
||||||
#_(interpreter/interpret-program '(3 5 integer_= exec_if (1 "yes") (2 "no"))
|
#_(interpreter/interpret-program
|
||||||
empty-push-state
|
'(3 5 :integer_eq :exec_if (1 "yes") (2 "no"))
|
||||||
1000)
|
state/empty-state
|
||||||
|
1000)
|
||||||
|
|
||||||
#_(interpreter/interpret-program '(in1 string_reverse 1 string_take "?" string_= exec_if
|
#_(interpreter/interpret-program
|
||||||
(in1 " I am asking." string_concat)
|
'(in1 :string_reverse 1 :string_take "?" :string_eq :exec_if
|
||||||
(in1 " I am saying." string_concat))
|
(in1 " I am asking." :string_concat)
|
||||||
(assoc empty-push-state :input {:in1 "Can you hear me?"})
|
(in1 " I am saying." :string_concat))
|
||||||
1000)
|
(assoc state/empty-state :input {:in1 "Can you hear me?"})
|
||||||
|
1000)
|
||||||
|
|
||||||
#_(interpreter/interpret-program '(in1 string_reverse 1 string_take "?" string_= exec_if
|
#_(interpreter/interpret-program
|
||||||
(in1 " I am asking." string_concat)
|
'(in1 :string_reverse 1 :string_take "?" :string_eq :exec_if
|
||||||
(in1 " I am saying." string_concat))
|
(in1 " I am asking." :string_concat)
|
||||||
(assoc empty-push-state :input {:in1 "I can hear you."})
|
(in1 " I am saying." :string_concat))
|
||||||
1000)
|
(assoc state/empty-state :input {:in1 "I can hear you."})
|
||||||
|
1000)
|
||||||
|
|
||||||
#_(genome/plushy->push (genome/make-random-plushy push/default-instructions 20))
|
#_(genome/plushy->push
|
||||||
|
(genome/make-random-plushy push/default-instructions 20))
|
||||||
|
|
||||||
#_(interpreter/interpret-program (genome/plushy->push (genome/make-random-plushy push/default-instructions 20))
|
#_(interpreter/interpret-program
|
||||||
(assoc empty-push-state :input {:in1 "I can hear you."})
|
(genome/plushy->push
|
||||||
1000)
|
(genome/make-random-plushy push/default-instructions 20))
|
||||||
|
(assoc state/empty-state :input {:in1 "I can hear you."})
|
||||||
|
1000)
|
||||||
|
|
||||||
|
;; =============================================================================
|
||||||
;; Target function: f(x) = x^3 + x + 3
|
;; Target function: f(x) = x^3 + x + 3
|
||||||
|
;; =============================================================================
|
||||||
|
|
||||||
#_(gp/gp {:instructions push/default-instructions
|
#_(gp/gp {:instructions push/default-instructions
|
||||||
:error-function regression-error-function
|
:error-function regression/error-function
|
||||||
:max-generations 50
|
:max-generations 50
|
||||||
:population-size 200
|
:population-size 200
|
||||||
:max-initial-plushy-size 50
|
:max-initial-plushy-size 50
|
||||||
:step-limit 100
|
:step-limit 100
|
||||||
:parent-selection :tournament
|
:parent-selection :tournament
|
||||||
:tournament-size 5})
|
:tournament-size 5})
|
||||||
|
|
||||||
#_(gp/gp {:instructions push/default-instructions
|
#_(gp/gp {:instructions push/default-instructions
|
||||||
:error-function string-classification-error-function
|
:error-function string-classif/error-function
|
||||||
:max-generations 50
|
:max-generations 50
|
||||||
:population-size 200
|
:population-size 200
|
||||||
:max-initial-plushy-size 50
|
:max-initial-plushy-size 50
|
||||||
:step-limit 100
|
:step-limit 100
|
||||||
:parent-selection :lexicase})
|
:parent-selection :lexicase})
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
(ns tools.calculus)
|
(ns propeller.tools.calculus)
|
||||||
|
|
||||||
(defonce ^:const dx 0.0001)
|
(defonce ^:const dx 0.0001)
|
||||||
|
|
@ -1,4 +1,4 @@
|
|||||||
(ns tools.character)
|
(ns propeller.tools.character)
|
||||||
|
|
||||||
(defn is-letter
|
(defn is-letter
|
||||||
"Returns true if the given character is a letter, A-Z or a-z."
|
"Returns true if the given character is a letter, A-Z or a-z."
|
@ -1,10 +1,10 @@
|
|||||||
(ns tools.distributions
|
(ns propeller.tools.distributions
|
||||||
(:require [tools.math :as math])
|
(:require (propeller.tools [calculus :as calculus]
|
||||||
(:require [tools.calculus :as calculus]))
|
[math :as math])))
|
||||||
|
|
||||||
;; -----------------------------------------------------------------------------
|
;; =============================================================================
|
||||||
;; NORMAL
|
;; NORMAL
|
||||||
;; -----------------------------------------------------------------------------
|
;; =============================================================================
|
||||||
|
|
||||||
(defn- box-muller
|
(defn- box-muller
|
||||||
"Given two uniformly distributed random variables (from 0 to 1), returns a
|
"Given two uniformly distributed random variables (from 0 to 1), returns a
|
@ -1,4 +1,4 @@
|
|||||||
(ns tools.math)
|
(ns propeller.tools.math)
|
||||||
|
|
||||||
(defonce PI #?(:clj Math/PI
|
(defonce PI #?(:clj Math/PI
|
||||||
:cljs js/Math.PI))
|
:cljs js/Math.PI))
|
@ -1,5 +1,5 @@
|
|||||||
(ns tools.metrics
|
(ns propeller.tools.metrics
|
||||||
(:require [tools.math :as math]))
|
(:require [propeller.tools.math :as math]))
|
||||||
|
|
||||||
(defn mean
|
(defn mean
|
||||||
"Returns the mean of a collection."
|
"Returns the mean of a collection."
|
Loading…
x
Reference in New Issue
Block a user