Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
224 commits
Select commit Hold shift + click to select a range
ae00a40
bump deps
ogeagla Feb 21, 2024
43a2448
stabilize a couple tests
ogeagla Feb 21, 2024
c95151d
rename some high-level functions/records/protocols to use 'find formu…
ogeagla Feb 21, 2024
39fbd8c
more renaming
ogeagla Feb 21, 2024
635b1d9
java class scaffold
ogeagla Feb 22, 2024
3abc4ae
java class scaffold
ogeagla Feb 22, 2024
22e17a7
java test class scaffold
ogeagla Feb 22, 2024
75893cd
FindFormula template from symja
ogeagla Feb 23, 2024
73dbab5
bump deps; fix tests
ogeagla Mar 17, 2025
ac69792
bump deps
ogeagla Dec 22, 2025
79362e2
fix typo
ogeagla Dec 22, 2025
3036b4f
perf-oriented JVM opts + perf profile scripts
ogeagla Dec 22, 2025
094b925
slight perf improvement
ogeagla Dec 22, 2025
fe04e41
slight perf improvement
ogeagla Dec 22, 2025
9356d25
update deptree info
ogeagla Dec 22, 2025
b247eec
improve GC tuning
ogeagla Dec 22, 2025
98b5fa6
project meta
ogeagla Dec 22, 2025
bda3d33
java API for closyr WIP
ogeagla Dec 23, 2025
6ab69fd
java API for closyr WIP
ogeagla Dec 23, 2025
5395712
java API for closyr WIP
ogeagla Dec 23, 2025
a121934
java API for closyr WIP
ogeagla Dec 23, 2025
533751d
PRNG improvements
ogeagla Dec 23, 2025
44dbd74
add deterministic mode using PRNG seed / doc update for Java API
ogeagla Dec 23, 2025
9296521
reorg readme
ogeagla Dec 23, 2025
f62d2fb
random-seed using PRNG improvements
ogeagla Dec 23, 2025
b87ea43
random-seed using PRNG improvements
ogeagla Dec 23, 2025
f150ce7
GUI for random-seed
ogeagla Dec 23, 2025
99b6865
wip
ogeagla Dec 23, 2025
b4b06cf
deterministic benchmark
ogeagla Dec 23, 2025
5f3cbef
wip
ogeagla Dec 23, 2025
e4f9ba6
wip
ogeagla Dec 23, 2025
58c8919
run junit script
ogeagla Dec 23, 2025
9cebdfa
simplify api
ogeagla Dec 24, 2025
5aacd09
log less during tests
ogeagla Dec 24, 2025
26d4299
fix junit test runner
ogeagla Dec 24, 2025
0e3ee98
style
ogeagla Dec 24, 2025
0008f97
style
ogeagla Dec 24, 2025
665c2be
bump junit deps
ogeagla Dec 27, 2025
ab64603
random seed used in Java API
ogeagla Dec 28, 2025
80221ab
better reporting
ogeagla Dec 28, 2025
a977604
couple extra datasets
ogeagla Dec 28, 2025
50c54ee
show obj fn in GUI
ogeagla Dec 28, 2025
33ef46c
use new datasets as benchmarks
ogeagla Dec 28, 2025
63ef3ec
use unicode font when available to print out GUI data at the bottom
ogeagla Dec 28, 2025
f492de4
symja obj fn text
ogeagla Dec 28, 2025
505c826
symja obj fn text widgets
ogeagla Dec 28, 2025
8896092
fix run junit tests
ogeagla Dec 28, 2025
b416345
readme arch diagram
ogeagla Dec 28, 2025
43fe7ec
rare bug and test case to confirm fix
ogeagla Dec 29, 2025
0c23dd9
ns graph
ogeagla Dec 29, 2025
2d3f8a9
more/better tests
ogeagla Dec 29, 2025
5ec536b
whitelist/blacklist for mutations
ogeagla Dec 29, 2025
5f74f99
whitelist/blacklist for mutations in GUI
ogeagla Dec 29, 2025
606becb
gui status label style
ogeagla Dec 29, 2025
df01a8a
ns graph
ogeagla Dec 29, 2025
a1393a6
gui setting to change log steps
ogeagla Dec 29, 2025
3bbb379
gui ns refactor
ogeagla Dec 29, 2025
d623b3c
gui ns refactor
ogeagla Dec 29, 2025
f70060d
gui ns refactor
ogeagla Dec 29, 2025
cb8d17b
provide user with input data when they draw custom data in sketchpad
ogeagla Dec 30, 2025
e0cd015
fix lein cloverage
ogeagla Dec 30, 2025
e6dd327
fix lein cloverage docs
ogeagla Dec 30, 2025
69dd096
http server and webapp
ogeagla Dec 30, 2025
e59fbf8
update deps
ogeagla Dec 30, 2025
9a15d19
http tests
ogeagla Dec 31, 2025
28c9209
server start/stop
ogeagla Dec 31, 2025
6be7dd4
webapp obj data vs best fn chart
ogeagla Dec 31, 2025
a7ad3b3
webapp input data editor
ogeagla Dec 31, 2025
bff29a3
UI nits
ogeagla Dec 31, 2025
efd06e4
UI nits
ogeagla Dec 31, 2025
26bac9f
webapp more data presets
ogeagla Dec 31, 2025
cae2e38
UI nits
ogeagla Dec 31, 2025
8cfee2d
display latex of formula
ogeagla Dec 31, 2025
9586bdc
latex results styling for huge formulas
ogeagla Dec 31, 2025
978df06
fix stop job which has been paused
ogeagla Dec 31, 2025
5b690d5
input data panel style (shorter)
ogeagla Dec 31, 2025
8aa234a
webapp ui style
ogeagla Dec 31, 2025
bb0918e
webapp job history
ogeagla Dec 31, 2025
b83c706
webapp break up js code
ogeagla Dec 31, 2025
24af7c3
dont log report when using webapp
ogeagla Dec 31, 2025
3ba4f6d
better results other solns
ogeagla Dec 31, 2025
8418d7a
copy latex src popup
ogeagla Dec 31, 2025
9483e2d
show stopped jobs in job history
ogeagla Dec 31, 2025
1e6eba0
can remove jobs from history
ogeagla Dec 31, 2025
1e61d52
less logging
ogeagla Dec 31, 2025
3eeaa3f
skip Hold() fns
ogeagla Dec 31, 2025
c36577e
bump deps
ogeagla Jan 1, 2026
b095354
more bench fns
ogeagla Jan 1, 2026
ce62493
exclude mutations in webapp
ogeagla Jan 1, 2026
ff91c82
logging
ogeagla Jan 1, 2026
df86a56
style
ogeagla Jan 1, 2026
e622993
preset dataset badges
ogeagla Jan 1, 2026
d565b30
preset dataset badges
ogeagla Jan 1, 2026
4859b59
job history seed
ogeagla Jan 1, 2026
8b06b93
perf improvements in ga
ogeagla Jan 2, 2026
1235c77
adaptive mutation
ogeagla Jan 2, 2026
3357eaa
deps graph
ogeagla Jan 2, 2026
942379f
gui / cli options for adaptive mode / quiet logging
ogeagla Jan 2, 2026
fce24a1
gui / cli options for adaptive mode / quiet logging
ogeagla Jan 2, 2026
e0b0ab5
best score progression chart
ogeagla Jan 2, 2026
3470fdf
best score progression chart
ogeagla Jan 2, 2026
3f31d05
webapp icons
ogeagla Jan 3, 2026
d23c159
feynman transition formula
ogeagla Jan 3, 2026
268eb3f
style
ogeagla Jan 3, 2026
f866396
adaptive thresholds
ogeagla Jan 3, 2026
30c6e9a
edit data points chart fix
ogeagla Jan 3, 2026
7929179
best fn chart y range constrain
ogeagla Jan 3, 2026
b1a1461
style
ogeagla Jan 3, 2026
a6c1df0
style
ogeagla Jan 3, 2026
a74847d
eval cache wip
ogeagla Jan 3, 2026
3a6489a
eval cache wip
ogeagla Jan 3, 2026
02843be
eval cache java api
ogeagla Jan 3, 2026
846e752
logging
ogeagla Jan 3, 2026
c795a27
tests
ogeagla Jan 3, 2026
b3663a2
options for scoring method
ogeagla Jan 4, 2026
de1d349
webapp main content make wider
ogeagla Jan 4, 2026
e55baaa
ui data fix scoring method display while job in progress
ogeagla Jan 4, 2026
a6ce7a1
ui data fix job history
ogeagla Jan 4, 2026
2b0b73a
ui data improve
ogeagla Jan 4, 2026
49964cf
test / lint
ogeagla Jan 4, 2026
1f0d095
style
ogeagla Jan 5, 2026
63f44d9
keep going feature; continue job
ogeagla Jan 6, 2026
64cb289
ns graph
ogeagla Jan 6, 2026
13937bd
docs
ogeagla Jan 6, 2026
f6d4202
more fixes / logging
ogeagla Jan 6, 2026
b391af2
disable adaptive mode during deterministic mode
ogeagla Jan 6, 2026
f611dcb
logging
ogeagla Jan 6, 2026
5f9adaf
logging
ogeagla Jan 6, 2026
bee1610
continue job uses correct config from form
ogeagla Jan 6, 2026
ace637c
logging
ogeagla Jan 6, 2026
efefbbf
logging
ogeagla Jan 6, 2026
b79faa2
style
ogeagla Jan 6, 2026
9212c57
style
ogeagla Jan 6, 2026
365056f
quicker input data chart updates
ogeagla Jan 7, 2026
323b8e6
docs
ogeagla Jan 7, 2026
7409e72
scoring method badge in job history
ogeagla Jan 7, 2026
e7444a4
scoring method badge in job history only
ogeagla Jan 7, 2026
a924207
job history based on keep going nesting level
ogeagla Jan 7, 2026
07ddfc6
job history based on keep going nesting level
ogeagla Jan 7, 2026
8d80c1c
job history max nesting level
ogeagla Jan 7, 2026
e2c5d2e
job history max nesting level
ogeagla Jan 7, 2026
6b4e6cb
job history item improve/worsen badge
ogeagla Jan 7, 2026
f62510c
job history item improve/worsen badge
ogeagla Jan 7, 2026
6659339
bump deps
ogeagla Jan 8, 2026
e3209ee
show eta and elapsed time for running job
ogeagla Jan 8, 2026
175f225
show eta and elapsed time for done job
ogeagla Jan 8, 2026
d433a45
job history nesting level colors
ogeagla Jan 8, 2026
edb7efb
job history nesting level colors
ogeagla Jan 8, 2026
eb35a5f
todos
ogeagla Jan 8, 2026
ffe80dc
todos
ogeagla Jan 8, 2026
cfcf429
todos
ogeagla Jan 8, 2026
bc4f177
todos
ogeagla Jan 8, 2026
31cc69c
style
ogeagla Jan 8, 2026
f34d1f7
todos
ogeagla Jan 8, 2026
b05b458
todos
ogeagla Jan 8, 2026
ff40d71
todos
ogeagla Jan 8, 2026
37b6676
concurrent jobs + tabbed results
ogeagla Jan 9, 2026
ed22401
delete job trees
ogeagla Jan 9, 2026
d4b8984
default config webapp
ogeagla Jan 9, 2026
c43f87a
style
ogeagla Jan 9, 2026
3462399
collapse parts of job trees
ogeagla Jan 9, 2026
1b423d2
copy shortcuts style
ogeagla Jan 9, 2026
18a23a1
bump deps
ogeagla Jan 9, 2026
dfb31a8
style
ogeagla Jan 9, 2026
cb7d8f0
todos
ogeagla Jan 9, 2026
fb2b1bd
todos
ogeagla Jan 9, 2026
5154500
style
ogeagla Jan 9, 2026
3eae082
todos
ogeagla Jan 9, 2026
86ef8d4
todos
ogeagla Jan 9, 2026
d6ac6f3
todos
ogeagla Jan 9, 2026
5785dd6
todos
ogeagla Jan 9, 2026
affd63f
todos
ogeagla Jan 9, 2026
6432239
fix concurrent eval cache bug
ogeagla Jan 9, 2026
bf43aba
mutation groups
ogeagla Jan 9, 2026
02f4f5c
close all active jobs when you close the webapp web site
ogeagla Jan 9, 2026
bf22409
show all scores
ogeagla Jan 9, 2026
31541f0
trig translator
ogeagla Jan 9, 2026
a6963c9
todos
ogeagla Jan 9, 2026
54ac3ee
sparklines for each scoring method
ogeagla Jan 10, 2026
606795b
job labels / names
ogeagla Jan 10, 2026
fdc93be
consistent chart domains
ogeagla Jan 10, 2026
796156c
todos
ogeagla Jan 10, 2026
ec51a7f
todos
ogeagla Jan 10, 2026
fac7809
can start job concurrently from main config panel
ogeagla Jan 10, 2026
11f25f5
compare running score with parent job. show all scores in history item
ogeagla Jan 10, 2026
58e1a72
job history scores
ogeagla Jan 10, 2026
f4350dc
job history delete single item preserves subtree and lifts it
ogeagla Jan 10, 2026
8da0749
job history for stopped jobs: jobs show up in correct place in the jo…
ogeagla Jan 10, 2026
bf9eba2
webapp data input brushes
ogeagla Jan 11, 2026
dd7a1ee
webapp data input brushes + fixes
ogeagla Jan 11, 2026
8761326
default dataset
ogeagla Jan 11, 2026
be44d3b
dataset label regresion fix
ogeagla Jan 11, 2026
d8917a8
todos
ogeagla Jan 11, 2026
9800318
todos
ogeagla Jan 11, 2026
075ce32
todos
ogeagla Jan 11, 2026
b6c3773
long running fn test
ogeagla Jan 11, 2026
466e96d
todos
ogeagla Jan 11, 2026
82e2e3d
todos
ogeagla Jan 11, 2026
9507a01
show stopped jobs in webapp UI
ogeagla Jan 11, 2026
c60de3d
wip configurable simplicity bias
ogeagla Jan 11, 2026
db482f8
fix frontend bug
ogeagla Jan 11, 2026
4347346
configable simplicity bias max contribution
ogeagla Jan 11, 2026
8d53449
configable simplicity bias fixes
ogeagla Jan 11, 2026
a4f6cee
configable simplicity bias fixes
ogeagla Jan 11, 2026
4ab2154
show unbiased score
ogeagla Jan 11, 2026
9cf0ea0
tweak bias
ogeagla Jan 11, 2026
02b1b48
log
ogeagla Jan 12, 2026
50024b5
ns graph
ogeagla Jan 12, 2026
f65cf06
add simplicity bias to eval cache key
ogeagla Jan 12, 2026
fcf0237
fix test
ogeagla Jan 12, 2026
c0f3428
ensure no thread exhaustion when doing expr processing
ogeagla Jan 12, 2026
ec7e4c0
style
ogeagla Jan 12, 2026
4e9731c
tweak simplicity bias config
ogeagla Jan 12, 2026
eb1e58e
tweak simplicity bias config
ogeagla Jan 12, 2026
e3ee54e
tweak simplicity bias config
ogeagla Jan 12, 2026
592c369
tweak simplicity bias config
ogeagla Jan 12, 2026
391091b
tweak simplicity bias config
ogeagla Jan 12, 2026
0657ea3
fix tests
ogeagla Jan 12, 2026
66f2174
less logging during tests
ogeagla Jan 12, 2026
e7600ed
less logging during tests
ogeagla Jan 12, 2026
bd3cddb
shorter bench tests
ogeagla Jan 12, 2026
8a9a5dd
todos
ogeagla Jan 12, 2026
4d6a13b
format done job scores
ogeagla Jan 12, 2026
0bffe15
show simplicity bias for updates/stopped jobs
ogeagla Jan 13, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
80 changes: 80 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
# CLAUDE.md - Notes for Claude Code

## Project Overview
Closyr is a symbolic regression tool that uses genetic algorithms to find mathematical formulas that fit data points.

## Key Architecture

### Symja Math Library
- Uses `org.matheclipse.core` (Symja) for symbolic math
- **Critical**: Parser creates different symbol objects than `F/x` or `F/Dummy "x"`
- The system uses `ops-common/sym-x` which is `(F/Dummy "x")` as the variable
- When parsing formula strings, the parser creates its own `x` symbol objects

### Phenotype Structure
A phenotype is a map with:
- `:sym` - The ISymbol used in the expression (should be `ops-common/sym-x`)
- `:expr` - The IExpr mathematical expression
- `:util` - ExprEvaluator instance
- `:id` - UUID
- `:score` - Double score from evaluation

### Evaluation Flow
1. `expr->fn` wraps expression: `Function({sym}, expr)`
2. `eval-phenotype-on-expr-args` evaluates the function at input values
3. **Critical**: The `:sym` in the phenotype MUST match the symbol used inside `:expr`

### Thread Safety
- **Critical**: Symja's `ExprEvaluator` is NOT thread-safe
- Has internal mutable state (ArrayDeque stacks) that corrupts under concurrent access
- When using `pmap` for parallel scoring, ALWAYS create a fresh `ExprEvaluator` per evaluation
- Never share `ExprEvaluator` instances across threads

## Keep Going Feature (Implemented)

### Overview
Allows continuing evolution from a completed/stopped job's results by seeding the new population with previous formulas.

### Implementation
1. **Formula Parsing** (`src/closyr/ops/initialize.clj`):
- `parse-formula->phenotype` - Parses formula string to phenotype
- `seeded-phenotypes` - Creates population seeded from formulas (default 80% seeded, 20% fresh)
- Uses recursive tree-walk to replace parser's `x` symbol with `ops-common/sym-x`

2. **API Endpoint** (`src/closyr/web/handlers/api.clj`):
- `POST /api/jobs/:id/continue` - Continue from a completed/stopped job
- Accepts `xs`, `ys`, and `config` (including `freshPercent`)

3. **Frontend** (`resources/public/js/solver-history.js`):
- "Keep Going" button in history items
- `keepGoingFromHistory(index)` function

### Key Technical Solution
The Symja parser creates its own Symbol instances for "x" that are NOT equal to `F/x` or `(F/Dummy "x")`.
Solution: Recursive tree-walk that replaces any symbol named "x" with `ops-common/sym-x`:

```clojure
(defn- make-tree-replacer [^ISymbol target-sym]
(ops-common/as-function
(fn tree-replace [^IExpr ie]
(cond
(and (.isSymbol ie) (= "x" (str ie))) target-sym
(instance? IAST ie) (.map ^IAST ie (make-tree-replacer target-sym))
:else ie))))
```

### Tests
- `test/closyr/seeded_evolution_test.clj` - Comprehensive tests for formula parsing and seeded evolution

### Error Handling
Robust error handling at multiple levels prevents crashes during evolution:
1. **Formula validation** (`api.clj`): `valid-seed-formula?` filters corrupted formulas before seeding
2. **Scoring** (`ga.clj`): `with-score` catches exceptions, returns min-score
3. **Competition** (`ga.clj`): `compete` catches exceptions, keeps parents unchanged
4. **Evaluation** (`eval.clj`): Returns infinity vectors on failure instead of throwing

## Build/Test Commands
- `lein test` - Run all tests
- `lein test :only ns/test-name` - Run specific test
- `lein run --web 3000` - Start the web server
- `lein run` - Start the java GUI
539 changes: 517 additions & 22 deletions README.md

Large diffs are not rendered by default.

103 changes: 53 additions & 50 deletions doc/depstree.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[ch.qos.logback/logback-classic "1.5.0"]
[ch.qos.logback/logback-core "1.5.0"]
[ch.qos.logback/logback-classic "1.5.23"]
[ch.qos.logback/logback-core "1.5.23"]
[clojure-complete "0.2.5" :exclusions [[org.clojure/clojure]]]
[flames "0.5.0"]
[http-kit "2.6.0"]
Expand All @@ -26,30 +26,30 @@
[org.swinglabs/swingx "1.6.1" :scope "runtime"]
[com.jhlabs/filters "2.0.235" :scope "runtime"]
[org.swinglabs/swing-worker "1.1" :scope "runtime"]
[metosin/malli "0.14.0"]
[metosin/malli "0.20.0"]
[borkdude/dynaload "0.3.5"]
[borkdude/edamame "1.3.23"]
[fipp "0.6.26"]
[borkdude/edamame "1.4.32"]
[fipp "0.6.29"]
[org.clojure/core.rrb-vector "0.1.2"]
[mvxcvi/arrangement "2.1.0"]
[org.clojure/test.check "1.1.1"]
[nrepl "0.8.3" :exclusions [[org.clojure/clojure]]]
[org.apache.logging.log4j/log4j-api "2.22.1"]
[org.apache.logging.log4j/log4j-core "2.22.1"]
[org.clojure/clojure "1.11.1"]
[org.clojure/core.specs.alpha "0.2.62"]
[org.clojure/spec.alpha "0.3.218"]
[org.clojure/core.async "1.6.681"]
[org.clojure/tools.analyzer.jvm "1.2.3"]
[org.clojure/core.memoize "1.0.253"]
[org.clojure/core.cache "1.0.225"]
[org.clojure/data.priority-map "1.1.0"]
[org.clojure/tools.analyzer "1.1.1"]
[org.clojure/tools.reader "1.3.6"]
[org.apache.logging.log4j/log4j-api "2.25.3"]
[org.apache.logging.log4j/log4j-core "2.25.3"]
[org.clojure/clojure "1.12.4"]
[org.clojure/core.specs.alpha "0.4.74"]
[org.clojure/spec.alpha "0.5.238"]
[org.clojure/core.async "1.8.741"]
[org.clojure/tools.analyzer.jvm "1.3.2"]
[org.clojure/core.memoize "1.1.266"]
[org.clojure/core.cache "1.1.234"]
[org.clojure/data.priority-map "1.2.0"]
[org.clojure/tools.analyzer "1.2.0"]
[org.clojure/tools.reader "1.5.0"]
[org.ow2.asm/asm "9.2"]
[org.clojure/data.csv "1.1.0"]
[org.clojure/tools.cli "1.1.230"]
[org.knowm.xchart/xchart "3.8.7"]
[org.clojure/tools.cli "1.2.245"]
[org.knowm.xchart/xchart "3.8.8"]
[com.madgag/animated-gif-lib "1.4"]
[de.erichseifert.vectorgraphics2d/VectorGraphics2D "0.13"]
[de.rototor.pdfbox/graphics2d "3.0.1"]
Expand All @@ -65,57 +65,60 @@
[org.junit.jupiter/junit-jupiter-engine "5.10.1" :scope "runtime"]
[org.junit.platform/junit-platform-engine "1.10.1" :scope "runtime"]
[org.junit.jupiter/junit-jupiter-params "5.10.1"]
[org.matheclipse/matheclipse-core "3.1.0-20240219.223701-64" :exclusions [[org.slf4j/slf4j-api] [com.fasterxml.jackson.core/jackson-core]]]
[com.esotericsoftware/kryo "5.6.0"]
[org.matheclipse/matheclipse-core "3.1.0-SNAPSHOT" :exclusions [[org.slf4j/slf4j-api] [com.fasterxml.jackson.core/jackson-core]]]
[com.esotericsoftware/kryo "5.6.2"]
[com.esotericsoftware/minlog "1.3.1"]
[com.esotericsoftware/reflectasm "1.11.9"]
[org.objenesis/objenesis "3.3"]
[org.objenesis/objenesis "3.4"]
[com.github.freva/ascii-table "1.8.0"]
[com.univocity/univocity-parsers "2.9.1"]
[commons-io "2.18.0"]
[de.labathome/AdaptiveQuadrature "1.0.2"]
[it.unimi.dsi/fastutil-core "8.5.13"]
[org.apache.commons/commons-csv "1.10.0"]
[org.apache.commons/commons-lang3 "3.14.0"]
[org.apfloat/apfloat "1.13.0"]
[org.choco-solver/choco-solver "4.10.15-20240118.152009-24"]
[it.unimi.dsi/fastutil-core "8.5.15"]
[org.apache.commons/commons-csv "1.13.0"]
[commons-codec "1.17.2"]
[org.apache.commons/commons-lang3 "3.17.0"]
[org.apfloat/apfloat "1.14.1-SNAPSHOT"]
[org.choco-solver/choco-solver "4.10.18" :exclusions [[org.knowm.xchart/xchart]]]
[dk.brics.automaton/automaton "1.11-8"]
[net.sf.trove4j/trove4j "3.0.3"]
[org.ehcache/sizeof "0.4.3"]
[org.codehaus.janino/janino "3.1.12"]
[org.codehaus.janino/commons-compiler "3.1.12"]
[org.gavaghan/geodesy "1.1.3"]
[org.hipparchus/hipparchus-clustering "3.1-20240212.230522-23"]
[org.hipparchus/hipparchus-core "3.1-20240212.230522-23"]
[org.hipparchus/hipparchus-stat "3.1-20240212.230522-23"]
[org.hipparchus/hipparchus-fft "3.1-20240212.230522-23"]
[org.hipparchus/hipparchus-fitting "3.1-20240212.230522-23"]
[org.hipparchus/hipparchus-ode "3.1-20240212.230522-23"]
[org.hipparchus/hipparchus-optim "3.1-20240212.230522-23"]
[org.jgrapht/jgrapht-io "1.5.3-20240118.050300-19"]
[org.hipparchus/hipparchus-clustering "4.0-20250316.160502-27"]
[org.hipparchus/hipparchus-stat "4.0-20250316.160502-27"]
[org.hipparchus/hipparchus-fft "4.0-20250316.160502-27"]
[org.hipparchus/hipparchus-fitting "4.0-20250316.160502-27"]
[org.hipparchus/hipparchus-ode "4.0-20250316.160502-27"]
[org.hipparchus/hipparchus-optim "4.0-20250316.160502-27"]
[org.jgrapht/jgrapht-io "1.5.3-SNAPSHOT"]
[org.antlr/antlr4-runtime "4.13.1"]
[org.apache.commons/commons-text "1.11.0"]
[org.jgrapht/jgrapht-core "1.5.3-20240118.050300-19"]
[org.jgrapht/jgrapht-core "1.5.3-SNAPSHOT"]
[org.jheaps/jheaps "0.14"]
[org.logicng/logicng-j11 "2.4.3"]
[org.matheclipse/matheclipse-external "3.1.0-20240219.223701-64"]
[com.fasterxml.jackson.core/jackson-databind "2.16.1"]
[com.fasterxml.jackson.core/jackson-annotations "2.16.1"]
[com.google.guava/guava "33.0.0-jre"]
[org.logicng/logicng "2.6.0"]
[org.matheclipse/matheclipse-external "3.1.0-SNAPSHOT"]
[com.fasterxml.jackson.core/jackson-databind "2.18.3"]
[com.fasterxml.jackson.core/jackson-annotations "2.18.3"]
[com.google.guava/guava "33.4.0-jre"]
[com.google.code.findbugs/jsr305 "3.0.2"]
[com.google.errorprone/error_prone_annotations "2.23.0"]
[com.google.errorprone/error_prone_annotations "2.36.0"]
[com.google.guava/failureaccess "1.0.2"]
[com.google.guava/listenablefuture "9999.0-empty-to-avoid-conflict-with-guava"]
[com.google.j2objc/j2objc-annotations "2.8"]
[org.checkerframework/checker-qual "3.41.0"]
[io.pebbletemplates/pebble "3.2.2"]
[com.google.j2objc/j2objc-annotations "3.0.0"]
[org.checkerframework/checker-qual "3.43.0"]
[io.pebbletemplates/pebble "3.2.3"]
[org.unbescape/unbescape "1.1.6.RELEASE"]
[org.matheclipse/matheclipse-parser "3.1.0-20240219.223701-64"]
[org.hipparchus/hipparchus-core "4.0-20250316.160502-27"]
[org.matheclipse/matheclipse-parser "3.1.0-SNAPSHOT"]
[org.organicdesign/Paguro "3.10.3"]
[org.jetbrains/annotations "23.0.0"]
[org.matheclipse/matheclipse-gpl "3.1.0-20240219.223701-64" :exclusions [[org.slf4j/slf4j-api] [com.fasterxml.jackson.core/jackson-core]]]
[org.apache.logging.log4j/log4j-1.2-api "2.22.1"]
[org.slf4j/jcl-over-slf4j "2.0.12"]
[org.slf4j/slf4j-api "2.0.12"]
[us.hebi.matlab.mat/mfl-core "0.5.15"]
[org.matheclipse/matheclipse-gpl "3.1.0-SNAPSHOT" :exclusions [[org.slf4j/slf4j-api] [com.fasterxml.jackson.core/jackson-core]]]
[org.apache.logging.log4j/log4j-1.2-api "2.24.3"]
[org.slf4j/jcl-over-slf4j "2.0.17"]
[org.slf4j/slf4j-api "2.0.17"]
[seesaw "1.5.0"]
[com.fifesoft/rsyntaxtextarea "2.5.6"]
[com.jgoodies/forms "1.2.1"]
Expand Down
Binary file added doc/problem_table_easy.pdf
Binary file not shown.
Binary file added doc/problem_table_hard.pdf
Binary file not shown.
Binary file added doc/problem_table_medium.pdf
Binary file not shown.
Binary file modified nomis-ns-graph.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
7 changes: 7 additions & 0 deletions perf-profile/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# How to run

In project root:

```sh
lein run -m clojure.main ./perf-profile/profile_test.clj # or other profile class
```
104 changes: 104 additions & 0 deletions perf-profile/benchmark.clj
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
(ns benchmark
(:require [closyr.ops.common :as ops-common]
[closyr.ops.eval :as ops-eval]
[closyr.ops.initialize :as ops-init]
[closyr.ops :as ops]
[closyr.ga :as ga]
[closyr.util.prng :as prng]))

(defn benchmark-evolution
"Benchmark evolution with optional deterministic mode.
When random-seed is provided, runs in deterministic (single-threaded) mode."
[pop-size n-iters max-leafs xs-max & {:keys [random-seed]}]
(binding [ga/*deterministic-mode* (some? random-seed)]
(when random-seed
(prng/set-random-seed! random-seed))
(let [phenos (ops-init/initial-phenotypes pop-size)
muts (ops-init/initial-mutations)
xs (vec (range 0.1 xs-max 0.2))
ys (mapv #(+ (* % %) (Math/sin %)) xs)
input-xs-list (ops-common/exprs->exprs-list (ops-common/doubles->exprs xs))
run-args {:input-xs-list input-xs-list
:input-xs-count (count xs)
:input-xs-vec xs
:input-ys-vec ys
:input-ys-arr (double-array ys)}
run-config {:max-leafs max-leafs}
score-fn (partial ops/score-fn run-args run-config)
mut-fn (partial ops/mutation-fn run-config muts)
cross-fn (partial ops/crossover-fn run-config muts)
ga-config (ga/initialize phenos score-fn mut-fn cross-fn)]

;; Warmup
(dotimes [_ 3] (ga/evolve ga-config))

;; Timed run
(let [start (System/nanoTime)
result (loop [config ga-config, i 0]
(if (< i n-iters)
(recur (ga/evolve config) (inc i))
config))
elapsed-ms (/ (- (System/nanoTime) start) 1e6)]
{:pop-size pop-size
:iters n-iters
:elapsed-ms elapsed-ms
:ms-per-iter (/ elapsed-ms n-iters)
:phenos-per-sec (/ (* pop-size n-iters 1000) elapsed-ms)
:deterministic (some? random-seed)}))))

(println "\n=== Evolution Benchmark ===\n")

(def results* (atom []))

(doseq [pop-size [10 100 500 1000 10000]]
(swap! results* concat ["\n"])
(doseq [xs-max [5.0 20.0]]
(doseq [max-leafs [40 120]]
(let [result (benchmark-evolution pop-size 10 max-leafs xs-max)]
(swap! results* concat [(format "Pop %4d, XsMax %4f, MaxLeafs %4d: %6.1f ms/iter, %8.0f phenos/sec\n"
pop-size
xs-max
max-leafs
(:ms-per-iter result)
(:phenos-per-sec result))])))))

(println "\n=== Parallel Benchmark Done ===")
(println "\n=== Results (Parallel Mode) ===")
(println (apply str @results*))

;; Deterministic benchmark
(println "\n=== Deterministic Benchmark (single-threaded) ===\n")

(def deterministic-results* (atom []))

(doseq [pop-size [10 100 500 1000]]
(swap! deterministic-results* concat ["\n"])
(doseq [xs-max [5.0 20.0]]
(doseq [max-leafs [40 120]]
(let [result (benchmark-evolution pop-size 10 max-leafs xs-max :random-seed 12345)]
(swap! deterministic-results* concat [(format "Pop %4d, XsMax %4.1f, MaxLeafs %4d: %6.1f ms/iter, %8.0f phenos/sec (deterministic)\n"
pop-size
xs-max
max-leafs
(:ms-per-iter result)
(:phenos-per-sec result))])))))

(println "\n=== Results (Deterministic Mode) ===")
(println (apply str @deterministic-results*))

;; Comparison summary
(println "\n=== Parallel vs Deterministic Comparison ===\n")

(doseq [pop-size [100 1000 5000]]
(let [parallel-result (benchmark-evolution pop-size 10 40 5.0)
deterministic-result (benchmark-evolution pop-size 10 40 5.0 :random-seed 42)
speedup (/ (:phenos-per-sec parallel-result) (:phenos-per-sec deterministic-result))]
(println (format "Pop %4d: Parallel %8.0f phenos/sec, Deterministic %8.0f phenos/sec, Speedup: %.2fx"
pop-size
(:phenos-per-sec parallel-result)
(:phenos-per-sec deterministic-result)
speedup))))

(println "\n=== All Benchmarks Complete ===")

(System/exit 0)
49 changes: 49 additions & 0 deletions perf-profile/eval_comparison.clj
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
(ns eval-comparison
(:require [closyr.ops.common :as ops-common]
[closyr.ops.eval :as ops-eval])
(:import [org.matheclipse.core.expression F]
[org.matheclipse.core.interfaces IExpr IAST ISymbol]))

(defn compare-eval []
(let [x ops-common/sym-x
expr (F/Plus (F/Sin x) (F/Times x x))
util (ops-common/new-util)
pheno {:sym x :util util :expr expr :id (java.util.UUID/randomUUID)}

xs (vec (range 0.1 10.0 0.1))
n (count xs)
xs-list (ops-common/exprs->exprs-list (ops-common/doubles->exprs xs))
run-args {:input-xs-list xs-list :input-xs-count n}

;; Pre-compute for isolated tests
fn-expr (ops-common/expr->fn pheno)
ast (F/ast xs-list fn-expr)]

(println "\n=== Evaluation Time Breakdown ===\n")
(println "Points:" n)

;; Warmup
(dotimes [_ 50] (ops-eval/eval-vec-pheno pheno run-args))

(println "\n1. Current optimized eval-vec-pheno (1000x):")
(time (dotimes [_ 1000] (ops-eval/eval-vec-pheno pheno run-args)))

(println "\n2. Just the .eval call (1000x):")
(time (dotimes [_ 1000] (.eval util ast)))

(println "\n3. Just result extraction from pre-computed result (1000x):")
(let [^IAST result (.eval util ast)]
(time (dotimes [_ 1000]
(loop [i (int 0), acc (transient [])]
(if (< i n)
(let [^IExpr e (.getArg result (inc i) F/Infinity)
v (if (.isReal e)
(ops-common/expr->double e)
Double/POSITIVE_INFINITY)]
(recur (unchecked-inc-int i) (conj! acc v)))
(persistent! acc))))))

(println "\nConclusion: .eval is ~95% of eval time, extraction is ~5%")
(println "\n=== Done ===")))

(compare-eval)
Loading