Skip to content

[WIP] Commutative operations and negative exponent match in rules #752

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 21 commits into
base: master
Choose a base branch
from

Conversation

Bumblebee00
Copy link
Contributor

@Bumblebee00 Bumblebee00 commented Jun 18, 2025

this pr builds on top of defslot and extends negative exponent matching. Before this pr julia symbolic rewriting rules had this unfortunate behaviour:

julia> @syms a x
(a, x)

julia> rule = @rule sin(~x) + cos(~x) => "yes"
sin(~x) + cos(~x) => 1

julia> arguments(sin(x) + cos(x))
2-element SymbolicUtils.SmallVec{Any, Vector{Any}}:
 cos(x)
 sin(x)

julia> rule(sin(x)+cos(x)) # doesnt match bc arguments are ordered cos first and then sin


julia> arguments(sin(a) + cos(a))
2-element SymbolicUtils.SmallVec{Any, Vector{Any}}:
 sin(a)
 cos(a)

julia> rule(sin(a)+cos(a)) # match bc arguments are ordered sin first and then cos
"yes"

there was the acrule macro that helped, but was working only on the first operation of the expression, not every level. with this pr instead every * and + operation creates a matcher that checks all possible orderings of its arguments.

This can also be a bad thing becuse the cases to check could be too many...

Also I refacored the code from my last two pr to make everything clearer and cleaner

Copy link
Contributor

github-actions bot commented Jun 18, 2025

Benchmark Results

master fe18cf5... master / fe18cf5...
overhead/acrule/a+2 0.971 ± 0.27 μs 5.25 ± 0.1 μs 0.185 ± 0.051
overhead/acrule/a+2+b 0.961 ± 0.28 μs 27.6 ± 0.58 μs 0.0349 ± 0.01
overhead/acrule/a+b 0.271 ± 0.023 μs 8.58 ± 0.18 μs 0.0316 ± 0.0027
overhead/acrule/noop:Int 1.55 ± 0.01 ns 1.56 ± 0.01 ns 0.995 ± 0.009
overhead/acrule/noop:Sym 23.8 ± 6.3 ns 18.2 ± 0.061 ns 1.31 ± 0.35
overhead/get_degrees/large_poly 0.156 ± 0.0081 s 0.453 ± 0.031 s 0.345 ± 0.029
overhead/rule/noop:Int 0.036 ± 0.024 μs 0.0361 ± 0.024 μs 0.997 ± 0.93
overhead/rule/noop:Sym 0.0331 ± 0.024 μs 0.0332 ± 0.024 μs 0.997 ± 1
overhead/rule/noop:Term 0.0331 ± 0.024 μs 0.0334 ± 0.024 μs 0.992 ± 1
overhead/ruleset/noop:Int 0.124 ± 0.019 μs 0.123 ± 0.038 μs 1.01 ± 0.35
overhead/ruleset/noop:Sym 0.131 ± 0.037 μs 0.13 ± 0.038 μs 1.01 ± 0.41
overhead/ruleset/noop:Term 5.11 ± 0.8 μs 4.73 ± 0.23 μs 1.08 ± 0.18
overhead/simplify/noop:Int 0.25 ± 0.035 μs 0.287 ± 0.033 μs 0.869 ± 0.16
overhead/simplify/noop:Sym 0.244 ± 0.035 μs 0.264 ± 0.032 μs 0.926 ± 0.18
overhead/simplify/noop:Term 0.0517 ± 0.0055 ms 0.0891 ± 0.0094 ms 0.581 ± 0.087
overhead/simplify/randterm (+, *):serial 0.127 ± 0.0072 s 0.353 ± 0.02 s 0.36 ± 0.029
overhead/simplify/randterm (+, *):thread 0.0727 ± 0.0061 s 0.247 ± 0.033 s 0.295 ± 0.047
overhead/simplify/randterm (/, *):serial 0.257 ± 0.025 ms 0.282 ± 0.026 ms 0.909 ± 0.12
overhead/simplify/randterm (/, *):thread 0.288 ± 0.027 ms 0.315 ± 0.03 ms 0.913 ± 0.12
overhead/substitute/a 0.107 ± 0.011 ms 0.108 ± 0.011 ms 0.988 ± 0.14
overhead/substitute/a,b 0.0891 ± 0.01 ms 0.0926 ± 0.0063 ms 0.962 ± 0.13
overhead/substitute/a,b,c 19.6 ± 1.9 μs 20.8 ± 2.1 μs 0.941 ± 0.13
polyform/easy_iszero 0.041 ± 0.0059 ms 0.0408 ± 0.00082 ms 1.01 ± 0.15
polyform/isone 3.11 ± 0.019 ns 2.79 ± 0.01 ns 1.11 ± 0.0079
polyform/iszero 1.44 ± 0.039 ms 1.44 ± 0.039 ms 1 ± 0.039
polyform/simplify_fractions 1.92 ± 0.075 ms 1.93 ± 0.11 ms 0.993 ± 0.07
time_to_load 1.17 ± 0.0069 s 1.16 ± 0.015 s 1.01 ± 0.014

Benchmark Plots

A plot of the benchmark results have been uploaded as an artifact to the workflow run for this PR.
Go to "Actions"->"Benchmark a pull request"->[the most recent run]->"Artifacts" (at the bottom).

@Bumblebee00 Bumblebee00 changed the title Commutative operations Commutative operations in rules Jun 18, 2025
@Bumblebee00 Bumblebee00 force-pushed the commutative_operations branch 3 times, most recently from 7a0f514 to 562cb99 Compare June 19, 2025 15:51
@Bumblebee00 Bumblebee00 changed the title Commutative operations in rules [WIP] Commutative operations in rules Jun 20, 2025
@Bumblebee00 Bumblebee00 force-pushed the commutative_operations branch 2 times, most recently from f5fddf2 to 860aa70 Compare June 22, 2025 14:18
@Bumblebee00 Bumblebee00 changed the title [WIP] Commutative operations in rules [WIP] Commutative operations and negative exponent match in rules Jun 24, 2025
@Bumblebee00
Copy link
Contributor Author

In this last commit, f0a9bcd i modified the code of pow_term_matcher, that has the job to match a power. previously was:

do the normal pow matcher, if no result check if the data has the form (1/...)^..., if no result check if the data has the form 1/(...^...)

now is:

check if the data has the form (1/...)^...,, if no result do the normal pow matcher, if no result check if the data has the form 1/(...^...)

The reason is that there were some problems with deflsot. A pattern like ((!a) + (!b)*(~x))^(~m) would match with (1/(1+2x))^2 with ~m=2, ~x=1/(1+2x), a=0 and b=1 from their default value. While this match is "correct", we want to match the more logical ~m=-2, ~x=x, ~a=1, ~b=2.

In terms of performace, on every power in the lhs of rule, it has to do an additional three checks (operation(data) === ^) && iscall(arguments(data)[1]) && (operation(arguments(data)[1]) === /) compared to the code before. I don't know if that's too much, I dont think so, but if I can come up with other ways of doing it that dont impact performance I will be happy

@Bumblebee00
Copy link
Contributor Author

To sum up, this pr includes:

  • Associative commutative checks
  • Negative exponent matching
  • Matching of exp as e^x and of sqrt as x^1//2
  • Some bug fixing and refactoring of the defslot feature

@Bumblebee00 Bumblebee00 force-pushed the commutative_operations branch from fe18cf5 to 9bcabec Compare July 4, 2025 15:06
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.

1 participant