Skip to content

fix: treat im as imaginary unit in string parsing#168

Merged
MilesCranmer merged 4 commits into
SymbolicML:masterfrom
MilesCranmerBot:bot/fix-im-string-parse
Mar 8, 2026
Merged

fix: treat im as imaginary unit in string parsing#168
MilesCranmer merged 4 commits into
SymbolicML:masterfrom
MilesCranmerBot:bot/fix-im-string-parse

Conversation

@MilesCranmerBot

Copy link
Copy Markdown
Contributor

This ports the im parsing fix from SymbolicRegression.jl to DynamicExpressions.jl, where string expression parsing belongs.

What changed

  • Normalize parsed expressions so symbol im is treated as Julia's imaginary unit constant.
  • Preserve existing behavior when "im" is explicitly provided in variable_names.
  • Add parser tests for both cases.

Context: requested in astroautomata/SymbolicRegression.jl#582 (comment)

Co-authored-by: Miles Cranmer <miles.cranmer@gmail.com>
@github-actions

github-actions Bot commented Mar 4, 2026

Copy link
Copy Markdown
Contributor

Benchmark Results (Julia v1)

Time benchmarks
master cf03c77... master / cf03c77...
eval/ComplexF32/evaluation 6.95 ± 0.43 ms 6.88 ± 0.43 ms 1.01 ± 0.089
eval/ComplexF64/evaluation 10.3 ± 0.83 ms 10.3 ± 0.75 ms 0.999 ± 0.11
eval/Float32/derivative 11.2 ± 1.2 ms 11.4 ± 0.97 ms 0.985 ± 0.13
eval/Float32/derivative_turbo 11.2 ± 1.1 ms 11.4 ± 0.88 ms 0.983 ± 0.12
eval/Float32/evaluation 2.49 ± 0.24 ms 2.47 ± 0.23 ms 1.01 ± 0.14
eval/Float32/evaluation_bumper 0.616 ± 0.019 ms 0.602 ± 0.016 ms 1.02 ± 0.041
eval/Float32/evaluation_turbo 0.541 ± 0.039 ms 0.527 ± 0.034 ms 1.03 ± 0.099
eval/Float32/evaluation_turbo_bumper 0.61 ± 0.018 ms 0.605 ± 0.016 ms 1.01 ± 0.04
eval/Float64/derivative 14.4 ± 1.6 ms 13.9 ± 1.5 ms 1.03 ± 0.16
eval/Float64/derivative_turbo 14.4 ± 2.1 ms 14 ± 1.3 ms 1.03 ± 0.18
eval/Float64/evaluation 2.87 ± 0.26 ms 2.87 ± 0.28 ms 1 ± 0.13
eval/Float64/evaluation_bumper 1.28 ± 0.042 ms 1.26 ± 0.039 ms 1.01 ± 0.046
eval/Float64/evaluation_turbo 1.05 ± 0.062 ms 1.02 ± 0.071 ms 1.03 ± 0.093
eval/Float64/evaluation_turbo_bumper 1.28 ± 0.045 ms 1.27 ± 0.041 ms 1.01 ± 0.049
utils/combine_operators/break_sharing 0.0422 ± 0.002 ms 0.0441 ± 0.0018 ms 0.957 ± 0.061
utils/convert/break_sharing 28 ± 3.7 μs 28.4 ± 3.8 μs 0.985 ± 0.18
utils/convert/preserve_sharing 0.108 ± 0.012 ms 0.106 ± 0.011 ms 1.01 ± 0.16
utils/copy/break_sharing 28.5 ± 4.9 μs 28.5 ± 3.9 μs 0.999 ± 0.22
utils/copy/preserve_sharing 0.11 ± 0.019 ms 0.106 ± 0.01 ms 1.04 ± 0.21
utils/count_constant_nodes/break_sharing 13.5 ± 1.8 μs 13.4 ± 1.5 μs 1.01 ± 0.17
utils/count_constant_nodes/preserve_sharing 0.09 ± 0.01 ms 0.0899 ± 0.011 ms 1 ± 0.17
utils/count_depth/break_sharing 14.1 ± 1.6 μs 14.5 ± 1.6 μs 0.971 ± 0.16
utils/count_nodes/break_sharing 12.7 ± 1.4 μs 13 ± 1.4 μs 0.981 ± 0.15
utils/count_nodes/preserve_sharing 0.0914 ± 0.01 ms 0.0909 ± 0.01 ms 1.01 ± 0.16
utils/get_set_constants!/break_sharing 0.0339 ± 0.0049 ms 0.0345 ± 0.004 ms 0.983 ± 0.18
utils/get_set_constants!/preserve_sharing 0.182 ± 0.013 ms 0.182 ± 0.013 ms 1 ± 0.1
utils/get_set_constants_parametric 0.0523 ± 0.0089 ms 0.0515 ± 0.0086 ms 1.01 ± 0.24
utils/has_constants/break_sharing 7.72 ± 1.6 μs 7.82 ± 1.7 μs 0.987 ± 0.3
utils/has_operators/break_sharing 2.69 ± 0.35 μs 2.67 ± 0.36 μs 1.01 ± 0.19
utils/hash/break_sharing 24.4 ± 1.9 μs 26.1 ± 2.7 μs 0.933 ± 0.12
utils/hash/preserve_sharing 0.107 ± 0.011 ms 0.105 ± 0.01 ms 1.02 ± 0.14
utils/index_constant_nodes/break_sharing 29.5 ± 3.1 μs 31.3 ± 4.1 μs 0.944 ± 0.16
utils/index_constant_nodes/preserve_sharing 0.108 ± 0.01 ms 0.111 ± 0.011 ms 0.974 ± 0.14
utils/is_constant/break_sharing 8.21 ± 1.7 μs 8.23 ± 1.7 μs 0.996 ± 0.29
utils/simplify_tree/break_sharing 31 ± 1.8 μs 31.5 ± 1.7 μs 0.985 ± 0.079
utils/simplify_tree/preserve_sharing 0.118 ± 0.011 ms 0.117 ± 0.0093 ms 1.01 ± 0.12
utils/string_tree/break_sharing 0.464 ± 0.037 ms 0.454 ± 0.021 ms 1.02 ± 0.093
utils/string_tree/preserve_sharing 0.557 ± 0.023 ms 0.553 ± 0.022 ms 1.01 ± 0.058
time_to_load 0.172 ± 0.0029 s 0.173 ± 0.0046 s 0.995 ± 0.031
Memory benchmarks
master cf03c77... master / cf03c77...
eval/ComplexF32/evaluation 0.987 k allocs: 2.53 MB 0.978 k allocs: 2.5 MB 1.01
eval/ComplexF64/evaluation 1 k allocs: 5.11 MB 0.993 k allocs: 5.06 MB 1.01
eval/Float32/derivative 4.63 k allocs: 17.4 MB 4.68 k allocs: 17.6 MB 0.99
eval/Float32/derivative_turbo 4.69 k allocs: 17.7 MB 4.67 k allocs: 17.6 MB 1
eval/Float32/evaluation 0.957 k allocs: 1.25 MB 0.966 k allocs: 1.26 MB 0.991
eval/Float32/evaluation_bumper 0.303 k allocs: 0.393 MB 0.303 k allocs: 0.393 MB 1
eval/Float32/evaluation_turbo 0.978 k allocs: 1.27 MB 0.945 k allocs: 1.23 MB 1.03
eval/Float32/evaluation_turbo_bumper 0.303 k allocs: 0.393 MB 0.303 k allocs: 0.393 MB 1
eval/Float64/derivative 4.78 k allocs: 0.0349 GB 4.79 k allocs: 0.035 GB 0.997
eval/Float64/derivative_turbo 4.81 k allocs: 0.0352 GB 4.78 k allocs: 0.035 GB 1.01
eval/Float64/evaluation 1.01 k allocs: 2.58 MB 1 k allocs: 2.57 MB 1.01
eval/Float64/evaluation_bumper 0.303 k allocs: 0.771 MB 0.303 k allocs: 0.771 MB 1
eval/Float64/evaluation_turbo 0.987 k allocs: 2.53 MB 0.996 k allocs: 2.55 MB 0.991
eval/Float64/evaluation_turbo_bumper 0.303 k allocs: 0.771 MB 0.303 k allocs: 0.771 MB 1
utils/combine_operators/break_sharing 4 allocs: 0.953 kB 4 allocs: 0.953 kB 1
utils/convert/break_sharing 2 k allocs: 0.123 MB 2 k allocs: 0.123 MB 1
utils/convert/preserve_sharing 2.4 k allocs: 0.192 MB 2.4 k allocs: 0.192 MB 1
utils/copy/break_sharing 2 k allocs: 0.123 MB 2 k allocs: 0.123 MB 1
utils/copy/preserve_sharing 2.4 k allocs: 0.192 MB 2.4 k allocs: 0.192 MB 1
utils/count_constant_nodes/break_sharing 4 allocs: 0.953 kB 4 allocs: 0.953 kB 1
utils/count_constant_nodes/preserve_sharing 0.404 k allocs: 0.0696 MB 0.404 k allocs: 0.0696 MB 1
utils/count_depth/break_sharing 4 allocs: 0.953 kB 4 allocs: 0.953 kB 1
utils/count_nodes/break_sharing 4 allocs: 0.953 kB 4 allocs: 0.953 kB 1
utils/count_nodes/preserve_sharing 0.404 k allocs: 0.0696 MB 0.404 k allocs: 0.0696 MB 1
utils/get_set_constants!/break_sharing 0.898 k allocs: 25.2 kB 0.898 k allocs: 25.2 kB 1
utils/get_set_constants!/preserve_sharing 1.7 k allocs: 0.138 MB 1.7 k allocs: 0.138 MB 1
utils/get_set_constants_parametric 1.42 k allocs: 0.0663 MB 1.42 k allocs: 0.0663 MB 1
utils/has_constants/break_sharing 4 allocs: 0.203 kB 4 allocs: 0.203 kB 1
utils/has_operators/break_sharing 4 allocs: 0.203 kB 4 allocs: 0.203 kB 1
utils/hash/break_sharing 0.104 k allocs: 2.52 kB 0.104 k allocs: 2.52 kB 1
utils/hash/preserve_sharing 0.504 k allocs: 0.0711 MB 0.504 k allocs: 0.0711 MB 1
utils/index_constant_nodes/break_sharing 2.1 k allocs: 0.094 MB 2.1 k allocs: 0.094 MB 1
utils/index_constant_nodes/preserve_sharing 2.5 k allocs: 0.163 MB 2.5 k allocs: 0.163 MB 1
utils/is_constant/break_sharing 4 allocs: 0.203 kB 4 allocs: 0.203 kB 1
utils/simplify_tree/break_sharing 0.104 k allocs: 2.52 kB 0.104 k allocs: 2.52 kB 1
utils/simplify_tree/preserve_sharing 0.504 k allocs: 0.0711 MB 0.504 k allocs: 0.0711 MB 1
utils/string_tree/break_sharing 11.9 k allocs: 0.999 MB 11.9 k allocs: 0.999 MB 1
utils/string_tree/preserve_sharing 12.3 k allocs: 1.07 MB 12.3 k allocs: 1.07 MB 1
time_to_load 0.145 k allocs: 11 kB 0.145 k allocs: 11 kB 1

@codecov

codecov Bot commented Mar 4, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 88.88889% with 1 line in your changes missing coverage. Please review.
✅ Project coverage is 59.43%. Comparing base (68d60d4) to head (cf03c77).
⚠️ Report is 2 commits behind head on master.

Files with missing lines Patch % Lines
src/Parse.jl 88.88% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master     #168      +/-   ##
==========================================
+ Coverage   59.33%   59.43%   +0.09%     
==========================================
  Files          30       30              
  Lines        2673     2682       +9     
==========================================
+ Hits         1586     1594       +8     
- Misses       1087     1088       +1     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@MilesCranmer MilesCranmer left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@MilesCranmerBot please implement the suggestions

Comment thread test/test_parse.jl
Comment thread src/Parse.jl Outdated
Co-authored-by: Miles Cranmer <miles.cranmer@gmail.com>
@MilesCranmerBot

MilesCranmerBot commented Mar 4, 2026

Copy link
Copy Markdown
Contributor Author

Implemented review suggestions:

  • Updated the im parsing test to evaluate on real/complex inputs and assert output eltype/values.
  • Dropped @unstable on _replace_imaginary_unit_symbol(::Expr) (always an Expr).

Commit: ec8cb53

@MilesCranmer

Copy link
Copy Markdown
Member

@MilesCranmerBot formatter check failed

@MilesCranmer MilesCranmer merged commit 29ebdab into SymbolicML:master Mar 8, 2026
11 of 13 checks passed
@MilesCranmer

Copy link
Copy Markdown
Member

@MilesCranmerBot please backport to release-v1

@MilesCranmerBot

Copy link
Copy Markdown
Contributor Author

Done — opened release-v1 backport PR: #169

I ran a targeted local validation for the im parse paths (0.1im + x and im + x2). Full Pkg.test() is heavier and was not re-run after the final compatibility patch.

github-actions Bot referenced this pull request Mar 23, 2026
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants