Skip to content

Commit 13f9f1b

Browse files
Merge pull request #794 from JuliaSymbolics/v4
feat: V4
2 parents 80ccd13 + d73822e commit 13f9f1b

Some content is hidden

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

49 files changed

+7388
-3088
lines changed

.github/workflows/benchmark_pr.yml

Lines changed: 14 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -4,75 +4,22 @@ on:
44
pull_request_target:
55
branches:
66
- master
7+
- v4
78

89
permissions:
910
pull-requests: write
1011

1112
jobs:
12-
generate_plots:
13-
runs-on: ubuntu-latest
14-
15-
steps:
16-
- uses: actions/checkout@v4
17-
- uses: julia-actions/setup-julia@v2
18-
with:
19-
version: "1"
20-
- uses: julia-actions/cache@v2
21-
- name: Extract Package Name from Project.toml
22-
id: extract-package-name
23-
run: |
24-
PACKAGE_NAME=$(grep "^name" Project.toml | sed 's/^name = "\(.*\)"$/\1/')
25-
echo "::set-output name=package_name::$PACKAGE_NAME"
26-
- name: Build AirspeedVelocity
27-
env:
28-
JULIA_NUM_THREADS: 2
29-
run: |
30-
# Lightweight build step, as sometimes the runner runs out of memory:
31-
julia -e 'ENV["JULIA_PKG_PRECOMPILE_AUTO"]=0; import Pkg; Pkg.add("AirspeedVelocity")'
32-
julia -e 'ENV["JULIA_PKG_PRECOMPILE_AUTO"]=0; import Pkg; Pkg.build("AirspeedVelocity")'
33-
- name: Add ~/.julia/bin to PATH
34-
run: |
35-
echo "$HOME/.julia/bin" >> $GITHUB_PATH
36-
- name: Run benchmarks
37-
run: |
38-
echo $PATH
39-
ls -l ~/.julia/bin
40-
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.repository.default_branch}}" --output-dir=results/ --tune --exeflags="-O3 --threads=auto"
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@v4
48-
with:
49-
name: plots
50-
path: plots
51-
- name: Create markdown table from benchmarks
52-
run: |
53-
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
54-
echo '### Benchmark Results' > body.md
55-
echo '' >> body.md
56-
echo '' >> body.md
57-
cat table.md >> body.md
58-
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-
64-
- name: Find Comment
65-
uses: peter-evans/find-comment@v2
66-
id: fcbenchmark
67-
with:
68-
issue-number: ${{ github.event.pull_request.number }}
69-
comment-author: 'github-actions[bot]'
70-
body-includes: Benchmark Results
71-
72-
- name: Comment on PR
73-
uses: peter-evans/create-or-update-comment@v3
74-
with:
75-
comment-id: ${{ steps.fcbenchmark.outputs.comment-id }}
76-
issue-number: ${{ github.event.pull_request.number }}
77-
body-path: body.md
78-
edit-mode: replace
13+
bench:
14+
name: "Benchmarks"
15+
strategy:
16+
matrix:
17+
version:
18+
- "1"
19+
- "lts"
20+
runs-on: ubuntu-latest
21+
steps:
22+
- uses: MilesCranmer/AirspeedVelocity.jl@action-v1
23+
with:
24+
julia-version: "${{ matrix.version }}"
25+
script: "benchmark/benchmarks.jl"

.github/workflows/ci.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ on:
33
pull_request:
44
branches:
55
- master
6+
- v4
67
push:
78
branches:
89
- master
@@ -20,6 +21,7 @@ jobs:
2021
version:
2122
- 'min'
2223
- '1'
24+
fail-fast: false
2325
steps:
2426
- uses: actions/checkout@v4
2527
- uses: julia-actions/setup-julia@v2

Project.toml

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,51 +6,64 @@ version = "3.32.0"
66
[deps]
77
AbstractTrees = "1520ce14-60c1-5f80-bbc7-55ef81b5835c"
88
ArrayInterface = "4fba245c-0d91-5ea0-9b3e-6abc04ee57a9"
9-
Bijections = "e2ed5e7c-b2de-5872-ae92-c73ca462fb04"
10-
ChainRulesCore = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4"
119
Combinatorics = "861a8166-3701-5b0c-9a16-15d98fcdc6aa"
1210
ConstructionBase = "187b0558-2788-49d3-abe0-74a17ed4e7c9"
1311
DataStructures = "864edb3b-99cc-5e75-8d2d-829cb0a9cfe8"
1412
DocStringExtensions = "ffbed154-4ef7-542d-bbb7-c09d3a79fcae"
1513
DynamicPolynomials = "7c1d4256-1411-5781-91ec-d7bc3513ac07"
14+
EnumX = "4e289a0a-7415-4d19-859d-a7e5c4648b56"
1615
ExproniconLite = "55351af7-c7e9-48d6-89ff-24e801d99491"
1716
LabelledArrays = "2ee39098-c373-598a-b85f-a56591580800"
1817
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
18+
MacroTools = "1914dd2f-81c6-5fcd-8719-6d5c9610ff09"
19+
Moshi = "2e0e35c7-a2e4-4343-998d-7ef72827ed2d"
1920
MultivariatePolynomials = "102ac46a-7ee4-5c85-9060-abc95bfdeaa3"
21+
MutableArithmetics = "d8a4904e-b15c-11e9-3269-09a3773c0cb0"
2022
NaNMath = "77ba4419-2d1f-58cd-9bb1-8ffee604a2e3"
23+
PrecompileTools = "aea7be01-6a6a-4083-8856-8a6e6704d82a"
24+
ReadOnlyArrays = "988b38a3-91fc-5605-94a2-ee2116b3bd83"
2125
Setfield = "efcf1570-3423-57d1-acb7-fd33fddbac46"
2226
SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf"
2327
SpecialFunctions = "276daf66-3868-5448-9aa4-cd146d93841b"
2428
StaticArrays = "90137ffa-7385-5640-81b9-e52037218182"
2529
SymbolicIndexingInterface = "2efcf032-c050-4f8e-a9bb-153293bab1f5"
2630
TaskLocalValues = "ed4db957-447d-4319-bfb6-7fa9ae7ecf34"
2731
TermInterface = "8ea1fca8-c5ef-4a55-8b96-4e9afe9c9a3c"
28-
TimerOutputs = "a759f4b9-e2f1-59dc-863e-4aeb61b1ea8f"
29-
Unityper = "a7c27f48-0311-42f6-a7f8-2c11e75eb415"
32+
WeakCacheSets = "d30d5f5c-d141-4870-aa07-aabb0f5fe7d5"
3033

3134
[weakdeps]
35+
ChainRulesCore = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4"
36+
Distributions = "31c24e10-a181-5473-b8eb-7969acd0382f"
3237
LabelledArrays = "2ee39098-c373-598a-b85f-a56591580800"
3338
ReverseDiff = "37e2e3b7-166d-5795-8a7a-e32c996b4267"
3439

3540
[extensions]
41+
SymbolicUtilsChainRulesCoreExt = "ChainRulesCore"
42+
SymbolicUtilsDistributionsExt = "Distributions"
3643
SymbolicUtilsLabelledArraysExt = "LabelledArrays"
3744
SymbolicUtilsReverseDiffExt = "ReverseDiff"
3845

3946
[compat]
4047
AbstractTrees = "0.4"
4148
ArrayInterface = "7.8"
42-
Bijections = "0.1.2, 0.2"
4349
ChainRulesCore = "1"
4450
Combinatorics = "1 - 1.0.2"
4551
ConstructionBase = "1.5.7"
4652
DataStructures = "0.18, 0.19"
4753
DocStringExtensions = "0.8, 0.9"
48-
DynamicPolynomials = "0.5, 0.6"
54+
DynamicPolynomials = "0.6.4"
55+
EnumX = "1.0.5"
4956
ExproniconLite = "0.10.14"
5057
LabelledArrays = "1.5"
51-
MultivariatePolynomials = "0.5"
58+
LinearAlgebra = "1"
59+
MacroTools = "0.5.16"
60+
Moshi = "0.3.6"
61+
MultivariatePolynomials = "0.5.12"
62+
MutableArithmetics = "1.6.5"
5263
NaNMath = "0.3, 1.1.2"
5364
OhMyThreads = "0.7"
65+
PrecompileTools = "1.2.1"
66+
ReadOnlyArrays = "0.2.0"
5467
ReverseDiff = "1"
5568
RuntimeGeneratedFunctions = "0.5.13"
5669
Setfield = "0.7, 0.8, 1"
@@ -59,8 +72,6 @@ StaticArrays = "0.12, 1.0"
5972
SymbolicIndexingInterface = "0.3"
6073
TaskLocalValues = "0.1.2"
6174
TermInterface = "2.0"
62-
TimerOutputs = "0.5"
63-
Unityper = "0.1.2"
6475
julia = "1.10"
6576

6677
[extras]

benchmark/Project.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,5 @@
11
[deps]
2+
3+
[sources]
4+
WeakCacheSets = {url="https://github.com/JuliaCollections/WeakCacheSets.jl"}
5+
Moshi = {url="https://github.com/AayushSabharwal/Moshi.jl", rev="as/mutable-adt"}

benchmark/benchmarks.jl

Lines changed: 49 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,17 @@ SUITE = BenchmarkGroup()
77

88
@syms a b c d x y[1:3] z[1:2, 1:2]; Random.seed!(123);
99

10+
function random_term(len; atoms, funs, fallback_atom=1)
11+
xs = rand(atoms, len)
12+
while length(xs) > 1
13+
xs = map(Iterators.partition(xs, 2)) do xy
14+
x = xy[1]; y = get(xy, 2, fallback_atom)
15+
rand(funs)(x, y)
16+
end
17+
end
18+
xs[]
19+
end
20+
1021
let r = @rule(~x => ~x), rs = RuleSet([r]),
1122
acr = @rule(~x::is_literal_number + ~y => ~y)
1223

@@ -34,16 +45,6 @@ let r = @rule(~x => ~x), rs = RuleSet([r]),
3445
overhead["simplify"]["noop:Sym"] = @benchmarkable simplify($a)
3546
overhead["simplify"]["noop:Term"] = @benchmarkable simplify($(a+2))
3647

37-
function random_term(len; atoms, funs, fallback_atom=1)
38-
xs = rand(atoms, len)
39-
while length(xs) > 1
40-
xs = map(Iterators.partition(xs, 2)) do xy
41-
x = xy[1]; y = get(xy, 2, fallback_atom)
42-
rand(funs)(x, y)
43-
end
44-
end
45-
xs[]
46-
end
4748
ex1 = random_term(1000, atoms=[a, b, c, d, a^(-1), b^(-1), 1, 2.0], funs=[+, *])
4849
ex2 = random_term(1000, atoms=[a, b, c, d, a^(-1), b^(-1), 1, 2.0], funs=[/, *])
4950

@@ -55,15 +56,17 @@ let r = @rule(~x => ~x), rs = RuleSet([r]),
5556
overhead["substitute"] = BenchmarkGroup()
5657

5758

58-
overhead["substitute"]["a"] = @benchmarkable substitute(subs_expr, $(Dict(a=>1))) setup=begin
59+
# we use `fold = false` since otherwise it dynamic dispatches to `sin`/`cos` whenever
60+
# both arguments in the contained addition are substituted.
61+
overhead["substitute"]["a"] = @benchmarkable substitute(subs_expr, $(Dict(a=>1)); fold = false) setup=begin
5962
subs_expr = (sin(a+b) + cos(b+c)) * (sin(b+c) + cos(c+a)) * (sin(c+a) + cos(a+b))
6063
end
6164

62-
overhead["substitute"]["a,b"] = @benchmarkable substitute(subs_expr, $(Dict(a=>1, b=>2))) setup=begin
65+
overhead["substitute"]["a,b"] = @benchmarkable substitute(subs_expr, $(Dict(a=>1, b=>2)); fold = false) setup=begin
6366
subs_expr = (sin(a+b) + cos(b+c)) * (sin(b+c) + cos(c+a)) * (sin(c+a) + cos(a+b))
6467
end
6568

66-
overhead["substitute"]["a,b,c"] = @benchmarkable substitute(subs_expr, $(Dict(a=>1, b=>2, c=>3))) setup=begin
69+
overhead["substitute"]["a,b,c"] = @benchmarkable substitute(subs_expr, $(Dict(a=>1, b=>2, c=>3)); fold = false) setup=begin
6770
subs_expr = (sin(a+b) + cos(b+c)) * (sin(b+c) + cos(c+a)) * (sin(c+a) + cos(a+b))
6871
end
6972

@@ -94,6 +97,38 @@ let
9497
(-f*(g + (-d*g) / d)) / (i + (-c*(h + (-e*g) / d)) / b + (-f*g) / d)) / d
9598
pform["simplify_fractions"] = @benchmarkable simplify_fractions($ex)
9699
pform["iszero"] = @benchmarkable SymbolicUtils.fraction_iszero($ex)
97-
pform["isone"] = @benchmarkable SymbolicUtils.fraction_isone($o)
100+
pform["isone"] = @benchmarkable SymbolicUtils.fraction_isone($ex)
101+
pform["isone:noop"] = @benchmarkable SymbolicUtils.fraction_isone($o)
102+
pform["iszero:noop"] = @benchmarkable SymbolicUtils.fraction_iszero($o)
98103
pform["easy_iszero"] = @benchmarkable SymbolicUtils.fraction_iszero($((b*(h + (-e*g) / d)) / b + (e*g) / d - h))
99104
end
105+
106+
let
107+
arith = SUITE["arithmetic"] = BenchmarkGroup()
108+
atoms = [a, b, c, d, a^2, b^2, a^1.5, (b + c), b^c, 1, 2.0]
109+
funs = [+, *]
110+
exs = [random_term(5; atoms, funs) for _ in 1:50]
111+
@static if isdefined(SymbolicUtils, :SymReal)
112+
arith["addition"] = @benchmarkable SymbolicUtils.add_worker(SymReal, $exs)
113+
elseif isdefined(SymbolicUtils, :add_worker)
114+
arith["addition"] = @benchmarkable SymbolicUtils.add_worker($exs)
115+
else
116+
exs = Tuple(exs)
117+
arith["addition"] = @benchmarkable +($(exs)...)
118+
end
119+
120+
funs = [*, /]
121+
exs = [random_term(5; atoms, funs) for _ in 1:50]
122+
@static if isdefined(SymbolicUtils, :SymReal)
123+
arith["multiplication"] = @benchmarkable SymbolicUtils.mul_worker(SymReal, $exs)
124+
elseif isdefined(SymbolicUtils, :mul_worker)
125+
arith["multiplication"] = @benchmarkable SymbolicUtils.mul_worker($exs)
126+
else
127+
exs = Tuple(exs)
128+
arith["multiplication"] = @benchmarkable *($(exs)...)
129+
end
130+
131+
ex1 = random_term(50; atoms, funs)
132+
ex2 = random_term(50; atoms, funs)
133+
arith["division"] = @benchmarkable $ex1 / $ex2
134+
end

docs/src/api.md

Lines changed: 14 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
```@docs
77
SymbolicUtils.@syms
88
SymbolicUtils.term
9-
SymbolicUtils.Sym
109
```
1110

1211
### Inspecting Terms
@@ -20,14 +19,6 @@ SymbolicUtils.sorted_arguments
2019
SymbolicUtils.showraw
2120
```
2221

23-
### Term Types
24-
```@docs
25-
SymbolicUtils.Term
26-
SymbolicUtils.Add
27-
SymbolicUtils.Mul
28-
SymbolicUtils.Pow
29-
```
30-
3122
### Metadata
3223
```@docs
3324
SymbolicUtils.hasmetadata
@@ -74,7 +65,6 @@ SymbolicUtils.substitute
7465
## Polynomial Forms
7566

7667
```@docs
77-
SymbolicUtils.PolyForm
7868
SymbolicUtils.simplify_fractions
7969
SymbolicUtils.quick_cancel
8070
SymbolicUtils.flatten_fractions
@@ -84,36 +74,30 @@ SymbolicUtils.flatten_fractions
8474

8575
### Core Functions
8676
```@docs
87-
SymbolicUtils.toexpr
88-
SymbolicUtils.cse
77+
SymbolicUtils.Code.toexpr
78+
SymbolicUtils.Code.cse
8979
```
9080

9181
### Code Generation Types
9282
```@docs
93-
SymbolicUtils.Assignment
94-
SymbolicUtils.Let
95-
SymbolicUtils.Func
96-
SymbolicUtils.DestructuredArgs
97-
SymbolicUtils.LiteralExpr
98-
SymbolicUtils.ForLoop
83+
SymbolicUtils.Code.Assignment
84+
SymbolicUtils.Code.Let
85+
SymbolicUtils.Code.Func
86+
SymbolicUtils.Code.DestructuredArgs
87+
SymbolicUtils.Code.LiteralExpr
88+
SymbolicUtils.Code.ForLoop
9989
```
10090

10191
### Array Operations
10292
```@docs
103-
SymbolicUtils.SetArray
104-
SymbolicUtils.MakeArray
105-
SymbolicUtils.MakeSparseArray
106-
SymbolicUtils.MakeTuple
93+
SymbolicUtils.Code.SetArray
94+
SymbolicUtils.Code.MakeArray
95+
SymbolicUtils.Code.MakeSparseArray
96+
SymbolicUtils.Code.MakeTuple
10797
```
10898

10999
### Parallelism
110100
```@docs
111-
SymbolicUtils.SpawnFetch
112-
SymbolicUtils.Multithreaded
101+
SymbolicUtils.Code.SpawnFetch
102+
SymbolicUtils.Code.Multithreaded
113103
```
114-
115-
## Utilities
116-
117-
```@docs
118-
SymbolicUtils.@timerewrite
119-
```

0 commit comments

Comments
 (0)