Skip to content

Commit 106072a

Browse files
committed
Merge tag 'v0.14.1' into constant-optimization
[Diff since v0.14.0](v0.14.0...v0.14.1) **Merged pull requests:** - Add built-in random sampling (#57) (@MilesCranmer) - Add better errors for `rand` (#58) (@MilesCranmer)
2 parents 1655a8e + 9aed074 commit 106072a

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

52 files changed

+2730
-1152
lines changed

.github/workflows/CI.yml

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -27,16 +27,16 @@ jobs:
2727
fail-fast: false
2828
matrix:
2929
julia-version:
30-
- '1.8.3'
30+
- '1'
3131
os:
3232
- ubuntu-latest
3333
- windows-latest
3434
- macOS-latest
3535
include:
3636
- os: ubuntu-latest
37-
julia-version: '1.7.2'
37+
julia-version: '1.7'
3838
- os: ubuntu-latest
39-
julia-version: '1.6.7'
39+
julia-version: '1.6'
4040

4141
steps:
4242
- uses: actions/checkout@v2
@@ -50,12 +50,24 @@ jobs:
5050
uses: julia-actions/julia-buildpkg@v1
5151
- name: "Run tests"
5252
run: |
53-
julia --color=yes --project=. -e 'import Pkg; Pkg.add("Coverage")'
54-
julia --color=yes --inline=yes --depwarn=yes --code-coverage=user --project=. -e 'import Pkg; Pkg.test(coverage=true)'
55-
julia --color=yes --project=. coverage.jl
53+
julia --color=yes -e 'import Pkg; Pkg.add("Coverage")'
54+
julia --color=yes --threads=auto --check-bounds=yes --depwarn=yes --code-coverage=user -e 'import Coverage; import Pkg; Pkg.activate("."); Pkg.test(coverage=true)'
55+
julia --color=yes coverage.jl
5656
shell: bash
5757
- name: Coveralls
58-
uses: coverallsapp/github-action@master
58+
uses: coverallsapp/github-action@v2
5959
with:
60-
github-token: ${{ secrets.GITHUB_TOKEN }}
61-
path-to-lcov: coverage-lcov.info
60+
parallel: true
61+
path-to-lcov: lcov.info
62+
flag-name: julia-${{ matrix.julia-version }}-${{ matrix.os }}-${{ github.event_name }}
63+
64+
coveralls:
65+
name: Indicate completion to coveralls
66+
runs-on: ubuntu-latest
67+
needs: test
68+
steps:
69+
- name: Finish
70+
uses: coverallsapp/github-action@v2
71+
with:
72+
parallel-finished: true
73+

.github/workflows/benchmark_pr.yml

Lines changed: 2 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ jobs:
1616
- uses: actions/checkout@v2
1717
- uses: julia-actions/setup-julia@v1
1818
with:
19-
version: "1.8"
19+
version: "1.9"
2020
- uses: julia-actions/cache@v1
2121
- name: Extract Package Name from Project.toml
2222
id: extract-package-name
@@ -38,16 +38,7 @@ jobs:
3838
echo $PATH
3939
ls -l ~/.julia/bin
4040
mkdir results
41-
benchpkg ${{ steps.extract-package-name.outputs.package_name }} --rev="${{github.event.repository.default_branch}},${{github.event.pull_request.head.sha}}" --url=${{ github.event.repository.clone_url }} --bench-on="${{github.event.pull_request.head.sha}}" --output-dir=results/ --tune
42-
- name: Create plots from benchmarks
43-
run: |
44-
mkdir -p plots
45-
benchpkgplot ${{ steps.extract-package-name.outputs.package_name }} --rev="${{github.event.repository.default_branch}},${{github.event.pull_request.head.sha}}" --npart=10 --format=png --input-dir=results/ --output-dir=plots/
46-
- name: Upload plot as artifact
47-
uses: actions/upload-artifact@v2
48-
with:
49-
name: plots
50-
path: plots
41+
benchpkg ${{ steps.extract-package-name.outputs.package_name }} --rev="${{github.event.repository.default_branch}},${{github.event.pull_request.head.sha}}" --url=${{ github.event.repository.clone_url }} --bench-on="${{github.event.pull_request.head.sha}}" --output-dir=results/ --tune --exeflags="-O3 --threads=auto"
5142
- name: Create markdown table from benchmarks
5243
run: |
5344
benchpkgtable ${{ steps.extract-package-name.outputs.package_name }} --rev="${{github.event.repository.default_branch}},${{github.event.pull_request.head.sha}}" --input-dir=results/ --ratio > table.md
@@ -56,11 +47,6 @@ jobs:
5647
echo '' >> body.md
5748
cat table.md >> body.md
5849
echo '' >> body.md
59-
echo '' >> body.md
60-
echo '### Benchmark Plots' >> body.md
61-
echo 'A plot of the benchmark results have been uploaded as an artifact to the workflow run for this PR.' >> body.md
62-
echo 'Go to "Actions"->"Benchmark a pull request"->[the most recent run]->"Artifacts" (at the bottom).' >> body.md
63-
6450
- name: Find Comment
6551
uses: peter-evans/find-comment@v2
6652
id: fcbenchmark

.github/workflows/check-format.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ jobs:
1414
runs-on: ${{ matrix.os }}
1515
strategy:
1616
matrix:
17-
julia-version: [1.8]
17+
julia-version: [1]
1818
julia-arch: [x86]
1919
os: [ubuntu-latest]
2020
steps:

CITATION.cff

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
cff-version: 1.2.0
2+
message: "If you use this software, please cite it using as below."
3+
authors:
4+
- family-names: "Cranmer"
5+
given-names: "Miles"
6+
orcid: "https://orcid.org/0000-0002-6458-3423"
7+
title: "Interpretable Machine Learning for Science with PySR & SymbolicRegression.jl"
8+
version: 1.0.0
9+
date-released: 2023-05-02
10+
doi: 10.48550/arXiv.2305.01582
11+
url: "https://github.com/MilesCranmer/pysr_paper"

CITATION.md

Lines changed: 0 additions & 27 deletions
This file was deleted.

Project.toml

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,49 @@
11
name = "DynamicExpressions"
22
uuid = "a40a106e-89c9-4ca8-8020-a735e8728b6b"
33
authors = ["MilesCranmer <miles.cranmer@gmail.com>"]
4-
version = "0.7.0"
4+
version = "0.14.1"
55

66
[deps]
77
Compat = "34da2185-b29b-5c13-b0c7-acf172513d20"
88
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
99
LoopVectorization = "bdcacae8-1622-11e9-2a5c-532679323890"
1010
MacroTools = "1914dd2f-81c6-5fcd-8719-6d5c9610ff09"
11+
PackageExtensionCompat = "65ce6f38-6b18-4e1d-a461-8949797d7930"
1112
PrecompileTools = "aea7be01-6a6a-4083-8856-8a6e6704d82a"
1213
Printf = "de0858da-6303-5e67-8744-51eddeeeb8d7"
1314
Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"
1415
Reexport = "189a3867-3050-52da-a836-e630ba90ab69"
15-
Requires = "ae029012-a4dd-5104-9daa-d747884805df"
16-
SymbolicUtils = "d1185830-fcd6-423d-90d6-eec64667417b"
1716
TOML = "fa267f1f-6049-4f14-aa54-33bafae1ed76"
17+
18+
[weakdeps]
19+
SymbolicUtils = "d1185830-fcd6-423d-90d6-eec64667417b"
1820
Zygote = "e88e6eb3-aa80-5325-afca-941959d7151f"
1921

22+
[extensions]
23+
DynamicExpressionsSymbolicUtilsExt = "SymbolicUtils"
24+
DynamicExpressionsZygoteExt = "Zygote"
25+
2026
[compat]
27+
Aqua = "0.7"
2128
Compat = "3.37, 4"
2229
LoopVectorization = "0.12"
2330
MacroTools = "0.4, 0.5"
31+
PackageExtensionCompat = "1"
2432
PrecompileTools = "1"
2533
Reexport = "1"
2634
SymbolicUtils = "0.19, ^1.0.5"
2735
Zygote = "0.6"
2836
julia = "1.6"
2937

3038
[extras]
39+
Aqua = "4c88cf16-eb10-579e-8560-4a9242c79595"
3140
ForwardDiff = "f6369f11-7733-5829-9624-2563aa707210"
3241
SafeTestsets = "1bc83da4-3b8d-516f-aca4-4fe02f6d838f"
3342
SpecialFunctions = "276daf66-3868-5448-9aa4-cd146d93841b"
43+
StaticArrays = "90137ffa-7385-5640-81b9-e52037218182"
44+
SymbolicUtils = "d1185830-fcd6-423d-90d6-eec64667417b"
3445
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
46+
Zygote = "e88e6eb3-aa80-5325-afca-941959d7151f"
3547

3648
[targets]
37-
test = ["Test", "SafeTestsets", "SpecialFunctions", "ForwardDiff"]
49+
test = ["Test", "SafeTestsets", "Aqua", "SpecialFunctions", "ForwardDiff", "StaticArrays", "SymbolicUtils", "Zygote"]

README.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
*Ridiculously fast dynamic expressions.*
66

7-
[![](https://img.shields.io/badge/docs-dev-blue.svg)](https://symbolicml.org/DynamicExpressions.jl/dev) [![CI](https://github.com/SymbolicML/DynamicExpressions.jl/actions/workflows/CI.yml/badge.svg)](https://github.com/SymbolicML/DynamicExpressions.jl/actions/workflows/CI.yml) [![Coverage Status](https://coveralls.io/repos/github/SymbolicML/DynamicExpressions.jl/badge.svg?branch=master)](https://coveralls.io/github/SymbolicML/DynamicExpressions.jl?branch=master)
7+
[![](https://img.shields.io/badge/docs-dev-blue.svg)](https://symbolicml.org/DynamicExpressions.jl/dev) [![CI](https://github.com/SymbolicML/DynamicExpressions.jl/actions/workflows/CI.yml/badge.svg)](https://github.com/SymbolicML/DynamicExpressions.jl/actions/workflows/CI.yml) [![Coverage Status](https://coveralls.io/repos/github/SymbolicML/DynamicExpressions.jl/badge.svg?branch=master)](https://coveralls.io/github/SymbolicML/DynamicExpressions.jl?branch=master) [![Aqua QA](https://raw.githubusercontent.com/JuliaTesting/Aqua.jl/master/badge.svg)](https://github.com/JuliaTesting/Aqua.jl)
88

99
DynamicExpressions.jl is the backbone of [SymbolicRegression.jl](https://github.com/MilesCranmer/SymbolicRegression.jl) and
1010
[PySR](https://github.com/MilesCranmer/PySR).
@@ -100,6 +100,8 @@ More importantly: we can change `expression` throughout runtime, and expect the
100100
We can also compute gradients with the same speed:
101101

102102
```julia
103+
using Zygote # trigger extension
104+
103105
operators = OperatorEnum(;
104106
binary_operators=[+, -, *],
105107
unary_operators=[cos],

benchmark/Project.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
[deps]
22
BenchmarkTools = "6e4b80f9-dd63-53aa-95a3-0cdb28fa8baf"
33
Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"
4+
Zygote = "e88e6eb3-aa80-5325-afca-941959d7151f"

benchmark/benchmark_utils.jl

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,11 @@ function random_node(tree::Node{T})::Node{T} where {T}
88
if tree.degree == 0
99
return tree
1010
end
11-
b = 0
12-
c = 0
13-
if tree.degree >= 1
14-
b = count_nodes(tree.l)
15-
end
16-
if tree.degree == 2
17-
c = count_nodes(tree.r)
11+
b = count_nodes(tree.l)
12+
c = if tree.degree == 2
13+
count_nodes(tree.r)
14+
else
15+
0
1816
end
1917

2018
i = rand(1:(1 + b + c))
@@ -27,7 +25,7 @@ function random_node(tree::Node{T})::Node{T} where {T}
2725
return random_node(tree.r)
2826
end
2927

30-
function make_random_leaf(nfeatures::Int, ::Type{T})::Node{T} where {T}
28+
function make_random_leaf(nfeatures::Integer, ::Type{T})::Node{T} where {T}
3129
if rand() > 0.5
3230
return Node(; val=randn(T))
3331
else
@@ -37,7 +35,7 @@ end
3735

3836
# Add a random unary/binary operation to the end of a tree
3937
function append_random_op(
40-
tree::Node{T}, operators, nfeatures::Int; makeNewBinOp::Union{Bool,Nothing}=nothing
38+
tree::Node{T}, operators, nfeatures::Integer; makeNewBinOp::Union{Bool,Nothing}=nothing
4139
)::Node{T} where {T}
4240
nuna = length(operators.unaops)
4341
nbin = length(operators.binops)
@@ -66,7 +64,7 @@ function append_random_op(
6664
end
6765

6866
function gen_random_tree_fixed_size(
69-
node_count::Int, operators, nfeatures::Int, ::Type{T}
67+
node_count::Integer, operators, nfeatures::Integer, ::Type{T}
7068
)::Node{T} where {T}
7169
tree = make_random_leaf(nfeatures, T)
7270
cur_size = count_nodes(tree)

benchmark/benchmarks.jl

Lines changed: 44 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
using DynamicExpressions, BenchmarkTools, Random
22
using DynamicExpressions.EquationUtilsModule: is_constant
3+
using Zygote
4+
if PACKAGE_VERSION < v"0.14.0"
5+
@eval using DynamicExpressions: Node as GraphNode
6+
else
7+
@eval using DynamicExpressions: GraphNode
8+
end
39

410
include("benchmark_utils.jl")
511

@@ -65,13 +71,15 @@ end
6571

6672
# These macros make the benchmarks work on older versions:
6773
#! format: off
68-
@generated function _convert(::Type{N}, t; preserve_sharing) where {N<:Node}
74+
@generated function _convert(::Type{N}, t; preserve_sharing) where {N}
6975
PACKAGE_VERSION < v"0.7.0" && return :(convert(N, t))
70-
return :(convert(N, t; preserve_sharing=preserve_sharing))
76+
PACKAGE_VERSION < v"0.14.0" && return :(convert(N, t; preserve_sharing=preserve_sharing))
77+
return :(convert(N, t)) # Assume type used to infer sharing
7178
end
7279
@generated function _copy_node(t; preserve_sharing)
7380
PACKAGE_VERSION < v"0.7.0" && return :(copy_node(t; preserve_topology=preserve_sharing))
74-
return :(copy_node(t; preserve_sharing=preserve_sharing))
81+
PACKAGE_VERSION < v"0.14.0" && return :(copy_node(t; preserve_sharing=preserve_sharing))
82+
return :(copy_node(t)) # Assume type used to infer sharing
7583
end
7684
@generated function get_set_constants!(tree)
7785
!(@isdefined set_constants!) && return :(set_constants(tree, get_constants(tree)))
@@ -98,14 +106,42 @@ function benchmark_utilities()
98106
:is_constant,
99107
:get_set_constants!,
100108
:index_constants,
109+
:string_tree,
110+
:hash,
101111
)
112+
has_both_modes = [:copy, :convert]
113+
if PACKAGE_VERSION >= v"0.14.0"
114+
append!(
115+
has_both_modes,
116+
[
117+
:simplify_tree,
118+
:count_nodes,
119+
:count_constants,
120+
:get_set_constants!,
121+
:index_constants,
122+
:string_tree,
123+
],
124+
)
125+
end
126+
if PACKAGE_VERSION >= v"0.14.1"
127+
append!(has_both_modes, [:hash])
128+
end
102129

103130
operators = OperatorEnum(; binary_operators=[+, -, /, *], unary_operators=[cos, exp])
104-
105131
for func_k in all_funcs
106132
suite[func_k] = let s = BenchmarkGroup()
107-
for k in (:break_sharing, :preserve_sharing)
108-
k == :preserve_sharing && !(func_k in (:copy, :convert)) && continue
133+
for k in (
134+
if func_k in has_both_modes
135+
[:break_sharing, :preserve_sharing]
136+
else
137+
[:break_sharing]
138+
end
139+
)
140+
preprocess = if k == :preserve_sharing && PACKAGE_VERSION >= v"0.14.0"
141+
tree -> GraphNode(tree)
142+
else
143+
identity
144+
end
109145

110146
f = if func_k == :copy
111147
tree -> _copy_node(tree; preserve_sharing=(k == :preserve_sharing))
@@ -115,7 +151,7 @@ function benchmark_utilities()
115151
tree;
116152
preserve_sharing=(k == :preserve_sharing),
117153
)
118-
elseif func_k in (:simplify_tree, :combine_operators)
154+
elseif func_k in (:simplify_tree, :combine_operators, :string_tree)
119155
g = getfield(@__MODULE__, func_k)
120156
tree -> f_tree_op(g, tree, operators)
121157
else
@@ -130,7 +166,7 @@ function benchmark_utilities()
130166
setup=(
131167
ntrees=100;
132168
n=20;
133-
trees=[gen_random_tree_fixed_size(n, $operators, 5, Float32) for _ in 1:ntrees]
169+
trees=[$preprocess(gen_random_tree_fixed_size(n, $operators, 5, Float32)) for _ in 1:ntrees]
134170
)
135171
)
136172
#! format: on

0 commit comments

Comments
 (0)