diff --git a/.github/workflows/clojure.yml b/.github/workflows/clojure.yml index 32fc0dd..561788e 100644 --- a/.github/workflows/clojure.yml +++ b/.github/workflows/clojure.yml @@ -3,8 +3,8 @@ name: Clojure CI on: push: branches: [ "master" ] - pull_request: - branches: [ "master" ] +# pull_request: +# branches: [ "master" ] jobs: build: diff --git a/README.md b/README.md index de0b4af..0119e2c 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,7 @@ # closyr +[![Clojure CI](https://github.com/ogeagla/closyr/actions/workflows/clojure.yml/badge.svg?branch=master)](https://github.com/ogeagla/closyr/actions/workflows/clojure.yml) + ![icon_v5_qtr.png](resources%2Ficons%2Ficon_v5_qtr.png) A Symbolic Regression tool to search for symbolic expressions which minimize residuals to an objective, written in Clojure. diff --git a/src/closyr/ga.clj b/src/closyr/ga.clj index 8116757..412cb01 100644 --- a/src/closyr/ga.clj +++ b/src/closyr/ga.clj @@ -84,4 +84,5 @@ :mutation-fn mutation-fn :crossover-fn crossover-fn})) (catch Exception e - (log/error "Err in evolve: " e)))) + (log/error "Err in evolve: " e) + (throw e)))) diff --git a/src/closyr/ops/common.clj b/src/closyr/ops/common.clj index f1b8c56..0c7c5d0 100644 --- a/src/closyr/ops/common.clj +++ b/src/closyr/ops/common.clj @@ -188,7 +188,7 @@ (go-loop [c 0] (when-not @done?* ;; wait sequence in ms looks like: 100, 316, 1000, ... - ( c 6) (reset! report-done?* true) diff --git a/src/closyr/ops/eval.clj b/src/closyr/ops/eval.clj index 683fb85..2584d5f 100644 --- a/src/closyr/ops/eval.clj +++ b/src/closyr/ops/eval.clj @@ -54,6 +54,40 @@ (str expr) " : " (or (.getMessage e) e))))) +(defn- parseable-eval-result? + [eval-p] + (not (or (nil? eval-p) + (= "Indeterminate" (str eval-p))))) + + +(defn- result-args->doubles + [^IExpr eval-p i] + (try + (let [^IExpr res (.getArg eval-p (inc i) F/Infinity)] + (if (.isReal res) + (ops-common/expr->double res) + Double/POSITIVE_INFINITY)) + (catch Exception e + (log/error "Error in evaling function on input values: " (str eval-p) " : " e) + Double/POSITIVE_INFINITY))) + + +(defn- result-args->constant-input + [^IExpr eval-p ^IExpr new-expr i] + (try + (let [^IExpr arg0 (.getArg eval-p 0 F/Infinity)] + (ops-common/expr->double + (if (.isReal new-expr) + new-expr + (if (.isBuiltInSymbol arg0) + eval-p + arg0)))) + (catch Exception e + (log/error "Error in evaling function on const xs vector: " + (str eval-p) " : " (.getMessage e)) + (throw e)))) + + (defn eval-vec-pheno "Evaluate a phenotype's expr on input xs/ys vecs" [p @@ -61,36 +95,12 @@ :as run-args}] (let [^IExpr new-expr (:expr p) ^IExpr eval-p (eval-phenotype-on-expr-args p input-xs-list)] - (when-not (or (nil? eval-p) (= "Indeterminate" (str eval-p))) - (let [vs (mapv - (fn [i] - (try - (let [^IExpr res (.getArg eval-p (inc i) F/Infinity)] - (if (.isReal res) - (ops-common/expr->double res) - Double/POSITIVE_INFINITY)) - (catch Exception e - (log/error "Error in evaling function on input values: " (str eval-p) " : " e) - Double/POSITIVE_INFINITY))) - (range (dec (.size eval-p)))) - vs (if (= input-xs-count (count vs)) - vs - (mapv - (fn [i] - (try - (let [^IExpr arg0 (.getArg eval-p 0 F/Infinity)] - (ops-common/expr->double - (if (.isReal new-expr) - new-expr - (if (.isBuiltInSymbol arg0) - eval-p - arg0)))) - (catch Exception e - (log/error "Error in evaling function on const xs vector: " - (str eval-p) " : " (.getMessage e)) - (throw e)))) - (range input-xs-count)))] - vs)))) + (when (parseable-eval-result? eval-p) + (mapv + (if (= input-xs-count (dec (.size eval-p))) + (partial result-args->doubles eval-p) + (partial result-args->constant-input eval-p new-expr)) + (range input-xs-count))))) (defn- clamp-oversampled-ys diff --git a/src/closyr/ops/initialize.clj b/src/closyr/ops/initialize.clj index 19344e1..69f731f 100644 --- a/src/closyr/ops/initialize.clj +++ b/src/closyr/ops/initialize.clj @@ -56,15 +56,15 @@ :modifier-fn (fn ^IExpr [{^IAST expr :expr ^ISymbol x-sym :sym :as pheno}] (F/Subtract expr (F/Divide 1 F/C10)))} - ;; {:op :modify-fn - ;; :label "+1/100" - ;; :modifier-fn (fn ^IExpr [{^IAST expr :expr ^ISymbol x-sym :sym :as pheno}] - ;; (F/Plus expr (F/Divide 1 F/C100)))} - ;; - ;; {:op :modify-fn - ;; :label "-1/100" - ;; :modifier-fn (fn ^IExpr [{^IAST expr :expr ^ISymbol x-sym :sym :as pheno}] - ;; (F/Subtract expr (F/Divide 1 F/C100)))} + {:op :modify-fn + :label "+1/100" + :modifier-fn (fn ^IExpr [{^IAST expr :expr ^ISymbol x-sym :sym :as pheno}] + (F/Plus expr (F/Divide 1 F/C100)))} + + {:op :modify-fn + :label "-1/100" + :modifier-fn (fn ^IExpr [{^IAST expr :expr ^ISymbol x-sym :sym :as pheno}] + (F/Subtract expr (F/Divide 1 F/C100)))} {:op :modify-fn :label "+Sin" @@ -196,15 +196,15 @@ :modifier-fn (fn ^IExpr [{^IAST expr :expr ^ISymbol x-sym :sym :as pheno}] (F/Times expr F/C10))} - ;; {:op :modify-fn - ;; :label "/100" - ;; :modifier-fn (fn ^IExpr [{^IAST expr :expr ^ISymbol x-sym :sym :as pheno}] - ;; (F/Times expr (F/Divide 1 F/C100)))} - ;; - ;; {:op :modify-fn - ;; :label "*100" - ;; :modifier-fn (fn ^IExpr [{^IAST expr :expr ^ISymbol x-sym :sym :as pheno}] - ;; (F/Times expr F/C100))} + {:op :modify-fn + :label "/100" + :modifier-fn (fn ^IExpr [{^IAST expr :expr ^ISymbol x-sym :sym :as pheno}] + (F/Times expr (F/Divide 1 F/C100)))} + + {:op :modify-fn + :label "*100" + :modifier-fn (fn ^IExpr [{^IAST expr :expr ^ISymbol x-sym :sym :as pheno}] + (F/Times expr F/C100))} {:op :modify-fn :label "*1.1" @@ -251,20 +251,20 @@ (F/Divide (F/C1) ie) ie))} - ;; {:op :modify-leafs - ;; :label "x/100" - ;; :leaf-modifier-fn (fn ^IExpr [leaf-count {^IAST expr :expr ^ISymbol x-sym :sym :as pheno} ^IExpr ie] - ;; (if (and (.isSymbol ie) (ops-common/should-modify-leaf leaf-count pheno)) - ;; (F/Divide ie (F/C100)) - ;; ie))} - ;; - ;; - ;; {:op :modify-leafs - ;; :label "100*x" - ;; :leaf-modifier-fn (fn ^IExpr [leaf-count {^IAST expr :expr ^ISymbol x-sym :sym :as pheno} ^IExpr ie] - ;; (if (and (.isSymbol ie) (ops-common/should-modify-leaf leaf-count pheno)) - ;; (F/Times ie (F/C100)) - ;; ie))} + {:op :modify-leafs + :label "x/100" + :leaf-modifier-fn (fn ^IExpr [leaf-count {^IAST expr :expr ^ISymbol x-sym :sym :as pheno} ^IExpr ie] + (if (and (.isSymbol ie) (ops-common/should-modify-leaf leaf-count pheno)) + (F/Divide ie (F/C100)) + ie))} + + + {:op :modify-leafs + :label "100*x" + :leaf-modifier-fn (fn ^IExpr [leaf-count {^IAST expr :expr ^ISymbol x-sym :sym :as pheno} ^IExpr ie] + (if (and (.isSymbol ie) (ops-common/should-modify-leaf leaf-count pheno)) + (F/Times ie (F/C100)) + ie))} {:op :modify-leafs :label "-1*x" @@ -357,19 +357,19 @@ (F/Subtract ie (F/Divide 1 F/C10)) ie))} - ;; {:op :modify-leafs - ;; :label "x+1/100" - ;; :leaf-modifier-fn (fn ^IExpr [leaf-count {^IAST expr :expr ^ISymbol x-sym :sym :as pheno} ^IExpr ie] - ;; (if (and (.isSymbol ie) (ops-common/should-modify-leaf leaf-count pheno)) - ;; (F/Plus ie (F/Divide 1 F/C100)) - ;; ie))} - ;; - ;; {:op :modify-leafs - ;; :label "x-1/100" - ;; :leaf-modifier-fn (fn ^IExpr [leaf-count {^IAST expr :expr ^ISymbol x-sym :sym :as pheno} ^IExpr ie] - ;; (if (and (.isSymbol ie) (ops-common/should-modify-leaf leaf-count pheno)) - ;; (F/Subtract ie (F/Divide 1 F/C100)) - ;; ie))} + {:op :modify-leafs + :label "x+1/100" + :leaf-modifier-fn (fn ^IExpr [leaf-count {^IAST expr :expr ^ISymbol x-sym :sym :as pheno} ^IExpr ie] + (if (and (.isSymbol ie) (ops-common/should-modify-leaf leaf-count pheno)) + (F/Plus ie (F/Divide 1 F/C100)) + ie))} + + {:op :modify-leafs + :label "x-1/100" + :leaf-modifier-fn (fn ^IExpr [leaf-count {^IAST expr :expr ^ISymbol x-sym :sym :as pheno} ^IExpr ie] + (if (and (.isSymbol ie) (ops-common/should-modify-leaf leaf-count pheno)) + (F/Subtract ie (F/Divide 1 F/C100)) + ie))} {:op :modify-leafs :label "c/2" @@ -428,20 +428,20 @@ (F/Divide F/C1 ie) ie))} - ;; {:op :modify-leafs - ;; :label "c+1/100" - ;; :leaf-modifier-fn (fn ^IExpr [leaf-count {^IAST expr :expr ^ISymbol x-sym :sym :as pheno} ^IExpr ie] - ;; (if (and (.isNumber ie) (ops-common/should-modify-leaf leaf-count pheno)) - ;; (do - ;; (F/Plus ie (F/Divide 1 F/C100))) - ;; ie))} - ;; - ;; {:op :modify-leafs - ;; :label "c-1/100" - ;; :leaf-modifier-fn (fn ^IExpr [leaf-count {^IAST expr :expr ^ISymbol x-sym :sym :as pheno} ^IExpr ie] - ;; (if (and (.isNumber ie) (ops-common/should-modify-leaf leaf-count pheno)) - ;; (F/Subtract ie (F/Divide 1 F/C100)) - ;; ie))} + {:op :modify-leafs + :label "c+1/100" + :leaf-modifier-fn (fn ^IExpr [leaf-count {^IAST expr :expr ^ISymbol x-sym :sym :as pheno} ^IExpr ie] + (if (and (.isNumber ie) (ops-common/should-modify-leaf leaf-count pheno)) + (do + (F/Plus ie (F/Divide 1 F/C100))) + ie))} + + {:op :modify-leafs + :label "c-1/100" + :leaf-modifier-fn (fn ^IExpr [leaf-count {^IAST expr :expr ^ISymbol x-sym :sym :as pheno} ^IExpr ie] + (if (and (.isNumber ie) (ops-common/should-modify-leaf leaf-count pheno)) + (F/Subtract ie (F/Divide 1 F/C100)) + ie))} {:op :modify-leafs :label "c+1/2" diff --git a/src/closyr/ops/modify.clj b/src/closyr/ops/modify.clj index 4b1bcec..9bf373e 100644 --- a/src/closyr/ops/modify.clj +++ b/src/closyr/ops/modify.clj @@ -126,6 +126,17 @@ [:plus :times :divide12 :divide21 :minus12 :minus21]) +(defn- check-modification-result + [max-leafs ^IExpr new-expr ^IExpr prev-expr] + (let [new-leafs (some-> new-expr (.leafCount)) + new-is-invalid? (or (nil? new-leafs) + (nil? new-expr) + (> new-leafs max-leafs)) + discount-mod? (or new-is-invalid? + (= (str prev-expr) (str new-expr)))] + [new-is-invalid? discount-mod?])) + + (defn crossover "Do phenotype crossover on their expr AST" [max-leafs @@ -150,12 +161,7 @@ :exp12 (F/Power e1-part e2-part) :exp21 (F/Power e2-part e1-part)) - new-leafs (some-> new-expr (.leafCount)) - new-is-invalid? (or (nil? new-leafs) - (nil? new-expr) - (> new-leafs max-leafs)) - discount-mod? (or new-is-invalid? - (= (str e1) (str new-expr)))] + [new-is-invalid? discount-mod?] (check-modification-result max-leafs new-expr e1)] (if discount-mod? ;; keep last op: @@ -185,7 +191,7 @@ mods []] (if (zero? mods-left-to-apply) {:new-pheno pheno :iters iters :mods mods} - (let [mod-to-apply (rand-nth initial-muts) + (let [mod-to-apply (rand-nth initial-muts) ;; get the util from the discard: {^IExpr expr-prior :expr @@ -205,17 +211,12 @@ " due to: " (or (.getMessage e) e))) pheno)) - new-leafs (some-> new-expr (.leafCount)) - new-is-invalid? (or (nil? new-leafs) - (nil? new-expr) - (> new-leafs max-leafs)) - discount-mod? (or new-is-invalid? - (= (str expr-prior) (str new-expr))) + [new-is-invalid? discount-mod?] (check-modification-result max-leafs new-expr expr-prior) ;; stop modification loop if too big or something went wrong: - count-to-go (if new-is-invalid? - 0 - (dec mods-left-to-apply))] + count-to-go (if new-is-invalid? + 0 + (dec mods-left-to-apply))] (recur ;; count the mod only if expr actually changed and new mod is valid: (if discount-mod? iters (inc iters)) diff --git a/src/closyr/symbolic_regression.clj b/src/closyr/symbolic_regression.clj index df10f23..8941756 100644 --- a/src/closyr/symbolic_regression.clj +++ b/src/closyr/symbolic_regression.clj @@ -249,7 +249,7 @@ (go-loop [chart-iter 0] - (gui-chan)] (try @@ -435,6 +435,8 @@ (defprotocol ISolverStateController + "Interface which allows creation and iteration of the symbolic regression GA solver" + (init [this] "Initialize solver state") @@ -615,6 +617,8 @@ (defprotocol ISymbolicRegressionSolver + "A top-level interface to start the solver using CLI or GUI args" + (solve [this] "Run the solver on either CLI of GUI args. When using GUI, we block on getting a signal from the @@ -660,22 +664,15 @@ (defn run-app-without-gui "Run app without GUI and with fake placeholder input data" - [] + [xs ys] (run-solver {:initial-phenos (ops-init/initial-phenotypes 100) :initial-muts (ops-init/initial-mutations) :iters 20 :use-gui? false :use-flamechart false - :input-xs-exprs (->> (range 50) - (map (fn [i] (* Math/PI (/ i 15.0)))) - ops-common/doubles->exprs) - :input-ys-exprs (->> (range 50) - (map (fn [i] - (+ 2.0 - (/ i 10.0) - (Math/sin (* Math/PI (/ i 15.0)))))) - ops-common/doubles->exprs)})) + :input-xs-exprs (ops-common/doubles->exprs xs) + :input-ys-exprs (ops-common/doubles->exprs ys)})) (defn- run-app-with-gui diff --git a/src/closyr/ui/gui.clj b/src/closyr/ui/gui.clj index b865a9f..c9f240a 100644 --- a/src/closyr/ui/gui.clj +++ b/src/closyr/ui/gui.clj @@ -237,7 +237,7 @@ brush-label:line sketchpad-on-click:line-brush}) -(def selectable-input-fns +(def ^:private selectable-input-fns (input-data/input-y-fns-data sketchpad-size* sketch-input-x-count*)) diff --git a/src/closyr/ui/icons.clj b/src/closyr/ui/icons.clj index a6c1c85..0617feb 100644 --- a/src/closyr/ui/icons.clj +++ b/src/closyr/ui/icons.clj @@ -9,7 +9,7 @@ ;; https://en-human-begin.blogspot.com/2007/11/javas-icons-by-default.html ;; https://coderanch.com/t/571308/java/built-Java-icons -(def all-icons +(def ^:private all-icons ["Button.rolloverIconType" "Button.textIconGap" "CheckBox.textIconGap" @@ -67,7 +67,7 @@ "Tree.openIcon"]) -(defn get-builtin-icons +(defn- get-builtin-icons [] ;; Hashtable defs = UIManager.getDefaults(); ;; Enumeration en = defs.keys(); diff --git a/test/closyr/ga_test.clj b/test/closyr/ga_test.clj index b6e6d9c..29fcb0e 100644 --- a/test/closyr/ga_test.clj +++ b/test/closyr/ga_test.clj @@ -51,3 +51,11 @@ (count initial-pop))) (is (= @count* 101))))) + + +(deftest can-handle-exception-and-rethrow + (testing "error in scoring" + (with-redefs-fn {#'ga/with-score (fn [_ _] (throw (Exception.)))} + (fn [] + (let [pop1 (ga/initialize initial-pop score-fn mutation-fn crossover-fn)] + (is (thrown? Exception (ga/evolve pop1)))))))) diff --git a/test/closyr/ops_common_test.clj b/test/closyr/ops_common_test.clj index a2efaa0..4a5ce37 100644 --- a/test/closyr/ops_common_test.clj +++ b/test/closyr/ops_common_test.clj @@ -84,9 +84,9 @@ (deftest simplify-with-slow-functions (testing "simplify takes a long time logs the slow fn" - (binding [ops-common/*long-simplify-thresh-ms* 500] + (binding [ops-common/*long-simplify-thresh-ms* 10] (with-redefs-fn {#'ops-common/simplify (fn [^IAST expr] - (Thread/sleep 600) + (Thread/sleep 10) (F/Simplify expr))} (fn [] (let [x (F/Dummy "x")] diff --git a/test/closyr/ops_eval_test.clj b/test/closyr/ops_eval_test.clj index 2aa85ca..24dd5cd 100644 --- a/test/closyr/ops_eval_test.clj +++ b/test/closyr/ops_eval_test.clj @@ -120,6 +120,15 @@ {:input-xs-list (ops-common/exprs->exprs-list (ops-common/doubles->exprs [0.5])) :input-xs-count 1})))))) + (testing "with failing conversion throws exception 2" + (is (thrown? Exception + (with-redefs-fn {#'ops-eval/result-args->constant-input (fn [_ _ _] (throw (Exception. "Test exception")))} + (fn [] + (ops-eval/eval-vec-pheno + (ops-common/->phenotype x (F/Subtract x F/C1D2) nil) + {:input-xs-list (ops-common/exprs->exprs-list (ops-common/doubles->exprs [0.5 1.0])) + :input-xs-count 1})))))) + (testing "can eval various fns for simple inputs 2" (is (= (mapv ops-common/expr->double diff --git a/test/closyr/ops_modify_test.clj b/test/closyr/ops_modify_test.clj index ce61ec1..f48108f 100644 --- a/test/closyr/ops_modify_test.clj +++ b/test/closyr/ops_modify_test.clj @@ -460,6 +460,12 @@ [:modify-fn "-1/10" "-11/10+x+Cos(x)/Sqrt(x)-x*Sin(1/2-x)"] + [:modify-fn + "+1/100" + "-99/100+x+Cos(x)/Sqrt(x)-x*Sin(1/2-x)"] + [:modify-fn + "-1/100" + "-101/100+x+Cos(x)/Sqrt(x)-x*Sin(1/2-x)"] [:modify-fn "+Sin" "-1+x+Cos(x)/Sqrt(x)-x*Sin(1/2-x)+Sin(x)"] @@ -538,6 +544,12 @@ [:modify-fn "*10" "10*(-1+x+Cos(x)/Sqrt(x)-x*Sin(1/2-x))"] + [:modify-fn + "/100" + "1/100*(-1+x+Cos(x)/Sqrt(x)-x*Sin(1/2-x))"] + [:modify-fn + "*100" + "100*(-1+x+Cos(x)/Sqrt(x)-x*Sin(1/2-x))"] [:modify-fn "*1.1" "1.1*(-1+x+Cos(x)/Sqrt(x)-x*Sin(1/2-x))"] @@ -559,6 +571,12 @@ [:modify-leafs "1/x" "-1+1/x+Cos(1/x)/Sqrt(1/x)-Sin(1/2-1/x)/x"] + [:modify-leafs + "x/100" + "-1+x/100+(10*Cos(x/100))/Sqrt(x)-1/100*x*Sin(1/2-x/100)"] + [:modify-leafs + "100*x" + "-1+100*x+Cos(100*x)/(10*Sqrt(x))-100*x*Sin(1/2-100*x)"] [:modify-leafs "-1*x" "-1-x+Cos(x)/Sqrt(-x)+x*Sin(1/2+x)"] @@ -598,6 +616,12 @@ [:modify-leafs "x-1/10" "-11/10+x+Cos(1/10-x)/Sqrt(-1/10+x)+(1/10-x)*Sin(3/5-x)"] + [:modify-leafs + "x+1/100" + "-99/100+x+Cos(1/100+x)/Sqrt(1/100+x)-(1/100+x)*Sin(49/100-x)"] + [:modify-leafs + "x-1/100" + "-101/100+x+Cos(1/100-x)/Sqrt(-1/100+x)+(1/100-x)*Sin(51/100-x)"] [:modify-leafs "c/2" "-1/2+x+Cos(x)/x^(1/4)-1/2*x*Sin(1/4-x/2)"] @@ -622,6 +646,12 @@ [:modify-leafs "1/c" "-1+x+Cos(x)/x^2-x*Sin(2-x)"] + [:modify-leafs + "c+1/100" + "-99/100+x+Cos(x)/x^(49/100)-99/100*x*Sin(51/100-99/100*x)"] + [:modify-leafs + "c-1/100" + "-101/100+x+Cos(x)/x^(51/100)-101/100*x*Sin(49/100-101/100*x)"] [:modify-leafs "c+1/2" "-1/2+x+Cos(x)-1/2*x*Sin(1-x/2)"] @@ -655,18 +685,9 @@ [:modify-ast-head "^->*" "-1+x-1/2*x*Cos(x)-x*Sin(1/2-x)"] - #_[:modify-ast-head - "/->*" - "-1+x+Cos(x)/Sqrt(x)-x*Sin(1/2-x)"] - #_[:modify-ast-head - "/->+" - "-1+x+Cos(x)/Sqrt(x)-x*Sin(1/2-x)"] [:modify-branches "b derivative" "1-3/2*Cos(x)/x^(5/2)+15/8*Sin(x)/x^(7/2)-Sin(x)/(2*x^(3/2))"] - #_[:modify-branches - "b simplify" - "-1+x+Cos(x)/Sqrt(x)-x*Sin(1/2-x)"] [:modify-branches "b sin" "-Sin(1-x-Sin(Sin(1/Sqrt(x))*Sin(Cos(x)))+Sin(x*Sin(Sin(Sin(1/2-Sin(x))))))"] diff --git a/test/closyr/ops_test.clj b/test/closyr/ops_test.clj index 36a833a..8e926a8 100644 --- a/test/closyr/ops_test.clj +++ b/test/closyr/ops_test.clj @@ -115,7 +115,7 @@ (binding [ops/*long-running-mutation-thresh-ms* 100] (with-redefs-fn {#'ops-modify/apply-modifications (fn [max-leafs mods-count initial-muts p-winner p-discard] - (Thread/sleep 500) + (Thread/sleep 200) {:new-pheno p-winner :iters 1 :mods []})} (fn [] (is (= diff --git a/test/closyr/symbolic_regression_test.clj b/test/closyr/symbolic_regression_test.clj index 1c2cad9..2518987 100644 --- a/test/closyr/symbolic_regression_test.clj +++ b/test/closyr/symbolic_regression_test.clj @@ -99,7 +99,7 @@ (:final-population (with-redefs-fn {#'symreg/config->log-steps (fn [_ _] 10)} (fn [] - (symreg/run-app-without-gui)))))) + (symreg/run-app-without-gui [1 2 3] [6 12 99])))))) 100))) (testing "with gui launcher" @@ -114,7 +114,7 @@ (is (= (count (:initial-phenos res)) 50)) (is (= (count (:initial-muts res)) - 86)) + 96)) (is (= (count (:input-xs-exprs res)) 50)) (is (= (count (:input-ys-exprs res)) @@ -219,13 +219,13 @@ (