From 8ebbb6956572cd58be39bf4907cbb2e88c314aa9 Mon Sep 17 00:00:00 2001 From: Shashi Gowda Date: Thu, 21 Dec 2023 14:00:06 -0500 Subject: [PATCH 1/9] rewrite helpers module --- src/rewrite-helpers.jl | 85 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 85 insertions(+) create mode 100644 src/rewrite-helpers.jl diff --git a/src/rewrite-helpers.jl b/src/rewrite-helpers.jl new file mode 100644 index 000000000..40229a1e0 --- /dev/null +++ b/src/rewrite-helpers.jl @@ -0,0 +1,85 @@ +""" + replace(expr::Symbolic, rules...) +Walk the expression and replace subexpressions according to `rules`. `rules` +could be rules constructed with `@rule`, a function, or a pair where the +left hand side is matched with equality (using `isequal`) and is replaced by the right hand side. + +Rules will be applied left-to-right simultaneously, +so only one pattern will be applied to any subexpression, +and the patterns will only be applied to the input text, +not the replacements. + +Set `fixpoint = true` to repeatedly apply rules until no +change to the expression remains to be made. +""" +function _replace(expr::Symbolic, rules...; fixpoint=false) + rs = map(r -> r isa Pair ? (x -> isequal(x, r[1]) ? r[2] : nothing) : r, rules) + R = Prewalk(Chain(rs)) + if fixpoint + Fixpoint(R)(expr) + else + R(expr) + end +end +# Fix ambiguity +function Base.replace(expr::Num, r::Pair, rules::Pair...) + _replace(unwrap(expr), r, rules...) +end + +function Base.replace(expr::Num, rules...) + _replace(unwrap(expr), rules...) +end + +function Base.replace(expr::Symbolic, r, rules...) + _replace(expr, r, rules) +end + + +Base.occursin(x::Num, y::Num) = occursin(unwrap(x), unwrap(y)) +@wrapped function Base.occursin(r::Any, y::Real) + y = unwrap(y) + if isequal(r, y) + return true + elseif r isa Function + if r(y) + return true + end + end + + if istree(y) + return r(operation(y)) || + any(y->occursin(r, y), arguments(y)) + else + return false + end +end + +function filterchildren!(r::Any, y::Union{Num, Symbolic}, acc) + y = unwrap(y) + if isequal(r, y) + push!(acc, y) + return acc + elseif r isa Function + if r(y) + push!(acc, y) + return acc + end + end + + if istree(y) + if r(operation(y)) + push!(acc, y) + end + foreach(c->filterchildren!(r, c, acc), + arguments(y)) + return acc + end +end + +filterchildren(r, y) = filterchildren!(r, y, []) + +module RewriteHelpers +import Symbolics: is_derivative, filterchildren, unwrap +export replace, occursin, is_derivative, + filterchildren, unwrap +end From 4637afc3d08ef8f3da498cd8cbaee5da385542ea Mon Sep 17 00:00:00 2001 From: Shashi Gowda Date: Fri, 22 Dec 2023 09:48:18 -0500 Subject: [PATCH 2/9] include include --- src/Symbolics.jl | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Symbolics.jl b/src/Symbolics.jl index 4e9fd9703..fe5ddb087 100644 --- a/src/Symbolics.jl +++ b/src/Symbolics.jl @@ -50,6 +50,7 @@ import MacroTools: splitdef, combinedef, postwalk, striplines include("wrapper-types.jl") include("num.jl") +include("rewrite-helpers.jl") include("complex.jl") """ From 972f5743010612a019579bb2b8c1550dd93736a7 Mon Sep 17 00:00:00 2001 From: Torkel Date: Sat, 23 Dec 2023 00:24:19 +0100 Subject: [PATCH 3/9] test init --- src/rewrite-helpers.jl | 10 ++++ test/rewrite_helpers.jl | 103 ++++++++++++++++++++++++++++++++++++++++ test/runtests.jl | 1 + 3 files changed, 114 insertions(+) create mode 100644 test/rewrite_helpers.jl diff --git a/src/rewrite-helpers.jl b/src/rewrite-helpers.jl index 40229a1e0..f8655247d 100644 --- a/src/rewrite-helpers.jl +++ b/src/rewrite-helpers.jl @@ -34,7 +34,17 @@ function Base.replace(expr::Symbolic, r, rules...) _replace(expr, r, rules) end +""" + occursin(x, y) +Checks whether `x` occurs in `y`. Parses `y`, returning `true` on any occurrence of x. +Example: +```julia +@syms x y z +occursin(x, y + z*(3+x)) # returns `true`. +occursin(x, log(y) + 10*(z-y) # returns `false`. +``` +""" Base.occursin(x::Num, y::Num) = occursin(unwrap(x), unwrap(y)) @wrapped function Base.occursin(r::Any, y::Real) y = unwrap(y) diff --git a/test/rewrite_helpers.jl b/test/rewrite_helpers.jl new file mode 100644 index 000000000..a715588a5 --- /dev/null +++ b/test/rewrite_helpers.jl @@ -0,0 +1,103 @@ +# Fetch packages. +using Symbolics +using Symbolics.RewriteHelpers +using Test + +@variables t X(t) Y(t) Z(t) V(t) W(t) +@syms a b c d e f g +D = Differential(t) +my_f(x, y) = x^3 + 2y + +# Check replace function. +let + @test isequal(replace(X + X + X, X =>1), 3) + @test isequal(replace(X + X + X, Y => 1), 3X) + @test isequal(replace(X + X + X, X => Y), 3Y) + @test isequal(replace(X + Y^2 - Z, Y^2 => Z), X) + + @test isequal(replace(a + a + a, a =>1), 3) # Errors. + @test isequal(replace(a + X + b, a + X =>b), 2b) # Errors. + @test isequal(replace(log(log(log(a))), a => b + C), log(log(log(b+c)))) # Errors. + + +end + +# Check is_derivative function +let + # Single expressions. + @test is_derivative(D) # Errors. + @test !is_derivative(t) # Errors. + @test !is_derivative(X) # Errors. + @test !is_derivative(a) # Errors. + @test !is_derivative(1) # Errors. + + # Composite expressions. + @test is_derivative(D(X)) # Errors. + @test !is_derivative(D(X) + 3) # Errors. + @test is_derivative(D(X + 2a*Y)) # Errors. + @test !is_derivative(D(X) + D(Y)) # Errors. + @test !is_derivative(my_f(X)) # Errors. + + +end + +# Test occursin function. +let + ex1 = 2X^a - log(b + my_f(Y,Y)) - 3 + ex2 = X^(Y^(Z-a)) +log(log(log(b))) + ex3 = sin(X) + sin(Y) + a*a*a*(1-X) + ex4 = exp(a)/(pi*a) + D(Y) + D(my_f(1,Z)) + ex5 = 1 + + # Test X + @test occursin(X, ex1) # Errors + @test occursin(X, ex2) + @test occursin(X, ex3) # Errors + @test !occursin(X, ex4) # Errors + @test !occursin(X, ex5) # Errors + + # Test Y + @test occursin(Y, ex1) # Errors + @test occursin(Y, ex2) # Errors + @test occursin(Y, ex3) # Errors + @test occursin(Y, ex4) # Errors + @test !occursin(Y, ex5) # Errors + + # Test Z + @test !occursin(Z, ex1) # Errors. + @test !occursin(Z, ex2) # Errors. + @test !occursin(Z, ex3) # Errors. + @test occursin(Z, ex4) # Errors. + @test !occursin(Z, ex5) # Errors + + # Test a + @test occursin(a, ex1) # Errors. + @test occursin(a, ex2) # Errors. + @test occursin(a, ex3) # Errors. + @test occursin(a, ex4) # Errors. + @test !occursin(a, ex5) + + # Test b + @test occursin(b, ex1) # Errors + @test occursin(b, ex2) # Errors + @test !occursin(b, ex3) # Errors + @test !occursin(b, ex4) # Errors + @test !occursin(b, ex5) + + # Checks composites. + @test occursin(a + b, a + b + c) # Should this work? +end + +# Check filterchildren function. +let + filterchildren(a, a) + filterchildren(a, a + 1) # Errors. + filterchildren(X, X + 1) # Errors. + filterchildren(X, X + a*(a + X)) # Errors. + filterchildren(X, D(X)) # Errors. + filterchildren(D, D(X)) # Errors. + filterchildren(D, D(X+Y)) # Errors. + + +end + diff --git a/test/runtests.jl b/test/runtests.jl index f151d0384..fe58b97fd 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -39,6 +39,7 @@ if GROUP == "All" || GROUP == "Core" @safetestset "Build Function Test" begin include("build_function.jl") end @safetestset "Build Function Array Test" begin include("build_function_arrayofarray.jl") end @safetestset "Build Function Array Test Named Tuples" begin include("build_function_arrayofarray_named_tuples.jl") end + @safetestset "Rewrite Helper Function Test" begin include("rewrite_helpers.jl") end VERSION >= v"1.9" && @safetestset "Build Targets Test" begin include("build_targets.jl") end @safetestset "Latexify Test" begin include("latexify.jl") end @safetestset "Domain Test" begin include("domains.jl") end From 7f98242498abf2746b2026af8010d59f99e717fa Mon Sep 17 00:00:00 2001 From: Torkel Date: Fri, 15 Mar 2024 14:29:59 -0400 Subject: [PATCH 4/9] up --- test/rewrite_helpers.jl | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/rewrite_helpers.jl b/test/rewrite_helpers.jl index a715588a5..f5bbc7520 100644 --- a/test/rewrite_helpers.jl +++ b/test/rewrite_helpers.jl @@ -8,6 +8,8 @@ using Test D = Differential(t) my_f(x, y) = x^3 + 2y +occursin(x -> true, a+b) + # Check replace function. let @test isequal(replace(X + X + X, X =>1), 3) From 637b8e673d34cc1dcd1e7117e71077ecce85dba9 Mon Sep 17 00:00:00 2001 From: Torkel Date: Fri, 15 Mar 2024 15:51:37 -0400 Subject: [PATCH 5/9] up --- src/rewrite-helpers.jl | 55 ++++++++++++++++++++++++++++++++++-------- 1 file changed, 45 insertions(+), 10 deletions(-) diff --git a/src/rewrite-helpers.jl b/src/rewrite-helpers.jl index f8655247d..4ee8a65ef 100644 --- a/src/rewrite-helpers.jl +++ b/src/rewrite-helpers.jl @@ -35,18 +35,30 @@ function Base.replace(expr::Symbolic, r, rules...) end """ - occursin(x, y) -Checks whether `x` occurs in `y`. Parses `y`, returning `true` on any occurrence of x. + occursin(c, x) +Returns true if any part of `x` fufills the condition given in c. c can be a function or an expression. +If it is a function, returns true if x is true for any part of x. If c is an expression, returns +true if x contains c. -Example: +Examples: ```julia -@syms x y z -occursin(x, y + z*(3+x)) # returns `true`. -occursin(x, log(y) + 10*(z-y) # returns `false`. +@syms x y +Symbolics.occursin(x, log(x) + x + 1) # returns `true`. +Symbolics.occursin(x, log(y) + y + 1) # returns `false`. +``` + +```julia +@variables t X(t) +D = Differential(t) +Symbolics.occursin(Symbolics.is_derivative, X + D(X) + D(X^2)) # returns `true`. ``` """ Base.occursin(x::Num, y::Num) = occursin(unwrap(x), unwrap(y)) @wrapped function Base.occursin(r::Any, y::Real) + _occursin(r, y) +end + +function _occursin(r, y) y = unwrap(y) if isequal(r, y) return true @@ -58,14 +70,15 @@ Base.occursin(x::Num, y::Num) = occursin(unwrap(x), unwrap(y)) if istree(y) return r(operation(y)) || - any(y->occursin(r, y), arguments(y)) + any(y->_occursin(r, y), arguments(y)) else return false end end -function filterchildren!(r::Any, y::Union{Num, Symbolic}, acc) +function filterchildren!(r::Any, y, acc) y = unwrap(y) + r = unwrap(r) if isequal(r, y) push!(acc, y) return acc @@ -77,8 +90,10 @@ function filterchildren!(r::Any, y::Union{Num, Symbolic}, acc) end if istree(y) - if r(operation(y)) - push!(acc, y) + if isequal(r, operation(y)) + push!(acc, operation(y)) + elseif r isa Function && r(operation(y)) + push!(acc, operation(y)) end foreach(c->filterchildren!(r, c, acc), arguments(y)) @@ -86,6 +101,26 @@ function filterchildren!(r::Any, y::Union{Num, Symbolic}, acc) end end +""" +filterchildren(c, x) +Returns all parts of `x` that fufills the condition given in c. c can be a function or an expression. +If it is a function, returns everything for which the function is `true`. If c is an expression, returns +all expressions that matches it. + +Examples: +```julia +@syms x +Symbolics.filterchildren(x, log(x) + x + 1) +``` +returns `[x, x]` + +```julia +@variables t X(t) +D = Differential(t) +Symbolics.filterchildren(Symbolics.is_derivative, X + D(X) + D(X^2)) +``` +returns `[Differential(t)(X(t)^2), Differential(t)(X(t))]` +""" filterchildren(r, y) = filterchildren!(r, y, []) module RewriteHelpers From 8616f8f87ed7c11e69f7b0f658b69f1fb1b2d675 Mon Sep 17 00:00:00 2001 From: Torkel Date: Fri, 15 Mar 2024 17:47:53 -0400 Subject: [PATCH 6/9] finish (bar errors) --- src/Symbolics.jl | 2 +- src/rewrite-helpers.jl | 44 ++++++------ test/diff.jl | 22 ++++++ test/rewrite_helpers.jl | 149 ++++++++++++++++++++-------------------- 4 files changed, 120 insertions(+), 97 deletions(-) diff --git a/src/Symbolics.jl b/src/Symbolics.jl index fe5ddb087..cb177dd88 100644 --- a/src/Symbolics.jl +++ b/src/Symbolics.jl @@ -97,7 +97,7 @@ using DiffRules, SpecialFunctions, NaNMath using SparseArrays -export Differential, expand_derivatives +export Differential, expand_derivatives, is_derivative include("diff.jl") diff --git a/src/rewrite-helpers.jl b/src/rewrite-helpers.jl index 4ee8a65ef..3acf86cec 100644 --- a/src/rewrite-helpers.jl +++ b/src/rewrite-helpers.jl @@ -12,26 +12,31 @@ not the replacements. Set `fixpoint = true` to repeatedly apply rules until no change to the expression remains to be made. """ -function _replace(expr::Symbolic, rules...; fixpoint=false) - rs = map(r -> r isa Pair ? (x -> isequal(x, r[1]) ? r[2] : nothing) : r, rules) - R = Prewalk(Chain(rs)) - if fixpoint - Fixpoint(R)(expr) - else - R(expr) - end -end -# Fix ambiguity function Base.replace(expr::Num, r::Pair, rules::Pair...) _replace(unwrap(expr), r, rules...) end +# Fix ambiguity function Base.replace(expr::Num, rules...) _replace(unwrap(expr), rules...) end -function Base.replace(expr::Symbolic, r, rules...) - _replace(expr, r, rules) +function Base.replace(expr::Symbolic, rules...) + _replace(unwrap(expr), rules...) +end + +function Base.replace(expr::Symbolic, r::Pair, rules::Pair...) + _replace(expr, r, rules...) +end + +function _replace(expr::Symbolic, rules...; fixpoint=false) + rs = map(r -> r isa Pair ? (x -> isequal(x, r[1]) ? r[2] : nothing) : r, rules) + R = Prewalk(Chain(rs)) + if fixpoint + Fixpoint(R)(expr) + else + R(expr) + end end """ @@ -53,16 +58,16 @@ D = Differential(t) Symbolics.occursin(Symbolics.is_derivative, X + D(X) + D(X^2)) # returns `true`. ``` """ -Base.occursin(x::Num, y::Num) = occursin(unwrap(x), unwrap(y)) -@wrapped function Base.occursin(r::Any, y::Real) +function Base.occursin(r::Function, y::Union{Num, Symbolic}) _occursin(r, y) end +Base.occursin(r::Num, y::Num) = occursin(unwrap(r), unwrap(y)) +Base.occursin(r::Num, y::Symbolic) = occursin(unwrap(r), unwrap(y)) + function _occursin(r, y) y = unwrap(y) - if isequal(r, y) - return true - elseif r isa Function + if r isa Function if r(y) return true end @@ -124,7 +129,6 @@ returns `[Differential(t)(X(t)^2), Differential(t)(X(t))]` filterchildren(r, y) = filterchildren!(r, y, []) module RewriteHelpers -import Symbolics: is_derivative, filterchildren, unwrap -export replace, occursin, is_derivative, - filterchildren, unwrap +import Symbolics: filterchildren, unwrap +export replace, occursin, filterchildren, unwrap end diff --git a/test/diff.jl b/test/diff.jl index 7486a78e7..21e0ae032 100644 --- a/test/diff.jl +++ b/test/diff.jl @@ -348,3 +348,25 @@ let @test isequal(expand_derivatives(Differential(t)(im*t)), im) @test isequal(expand_derivatives(Differential(t)(t^2 + im*t)), 2t + im) end + + +# Check `is_derivative` function +let + @variables t X(t) Y(t) + @syms a b + D = Differential(t) + + # Single expressions. + @test !Symbolics.is_derivative(Symbolics.unwrap(D)) + @test !Symbolics.is_derivative(Symbolics.unwrap(t)) + @test !Symbolics.is_derivative(Symbolics.unwrap(X)) + @test !Symbolics.is_derivative(Symbolics.unwrap(a)) + @test !Symbolics.is_derivative(Symbolics.unwrap(1)) + + # Composite expressions. + @test Symbolics.is_derivative(Symbolics.unwrap(D(X))) + @test !Symbolics.is_derivative(Symbolics.unwrap(D(X) + 3)) + @test Symbolics.is_derivative(Symbolics.unwrap(D(X + 2a*Y))) + @test !Symbolics.is_derivative(Symbolics.unwrap(D(X) + D(Y))) + @test !Symbolics.is_derivative(Symbolics.unwrap(my_f(X, D(Y)))) +end \ No newline at end of file diff --git a/test/rewrite_helpers.jl b/test/rewrite_helpers.jl index f5bbc7520..d74abe8e5 100644 --- a/test/rewrite_helpers.jl +++ b/test/rewrite_helpers.jl @@ -1,46 +1,20 @@ + # Fetch packages. using Symbolics using Symbolics.RewriteHelpers using Test -@variables t X(t) Y(t) Z(t) V(t) W(t) -@syms a b c d e f g +@variables t X(t) Y(t) Z(t) +@syms a b D = Differential(t) my_f(x, y) = x^3 + 2y -occursin(x -> true, a+b) - # Check replace function. let @test isequal(replace(X + X + X, X =>1), 3) @test isequal(replace(X + X + X, Y => 1), 3X) @test isequal(replace(X + X + X, X => Y), 3Y) @test isequal(replace(X + Y^2 - Z, Y^2 => Z), X) - - @test isequal(replace(a + a + a, a =>1), 3) # Errors. - @test isequal(replace(a + X + b, a + X =>b), 2b) # Errors. - @test isequal(replace(log(log(log(a))), a => b + C), log(log(log(b+c)))) # Errors. - - -end - -# Check is_derivative function -let - # Single expressions. - @test is_derivative(D) # Errors. - @test !is_derivative(t) # Errors. - @test !is_derivative(X) # Errors. - @test !is_derivative(a) # Errors. - @test !is_derivative(1) # Errors. - - # Composite expressions. - @test is_derivative(D(X)) # Errors. - @test !is_derivative(D(X) + 3) # Errors. - @test is_derivative(D(X + 2a*Y)) # Errors. - @test !is_derivative(D(X) + D(Y)) # Errors. - @test !is_derivative(my_f(X)) # Errors. - - end # Test occursin function. @@ -49,57 +23,80 @@ let ex2 = X^(Y^(Z-a)) +log(log(log(b))) ex3 = sin(X) + sin(Y) + a*a*a*(1-X) ex4 = exp(a)/(pi*a) + D(Y) + D(my_f(1,Z)) - ex5 = 1 - - # Test X - @test occursin(X, ex1) # Errors + ex5 = a + 5b^2 + + # Test for variables. + @test occursin(X, ex1) @test occursin(X, ex2) - @test occursin(X, ex3) # Errors - @test !occursin(X, ex4) # Errors - @test !occursin(X, ex5) # Errors - - # Test Y - @test occursin(Y, ex1) # Errors - @test occursin(Y, ex2) # Errors - @test occursin(Y, ex3) # Errors - @test occursin(Y, ex4) # Errors - @test !occursin(Y, ex5) # Errors - - # Test Z - @test !occursin(Z, ex1) # Errors. - @test !occursin(Z, ex2) # Errors. - @test !occursin(Z, ex3) # Errors. - @test occursin(Z, ex4) # Errors. - @test !occursin(Z, ex5) # Errors - - # Test a - @test occursin(a, ex1) # Errors. - @test occursin(a, ex2) # Errors. - @test occursin(a, ex3) # Errors. - @test occursin(a, ex4) # Errors. - @test !occursin(a, ex5) - - # Test b - @test occursin(b, ex1) # Errors - @test occursin(b, ex2) # Errors - @test !occursin(b, ex3) # Errors - @test !occursin(b, ex4) # Errors - @test !occursin(b, ex5) - - # Checks composites. - @test occursin(a + b, a + b + c) # Should this work? + @test occursin(X, ex3) + @test !occursin(X, ex4) + @test occursin(Y, ex1) + @test occursin(Y, ex2) + @test occursin(Y, ex3) + @test occursin(Y, ex4) + @test !occursin(Z, ex1) + @test occursin(Z, ex2) + @test !occursin(Z, ex3) + @test occursin(Z, ex4) + + # Test for variables. + @test_broken occursin(a, ex1) + @test_broken occursin(a, ex2) + @test_broken occursin(a, ex3) + @test_broken occursin(a, ex4) + @test occursin(a, ex5) + @test_broken occursin(b, ex1) + @test_broken occursin(b, ex2) + @test !occursin(b, ex3) + @test !occursin(b, ex4) + @test occursin(b, ex5) + + # Test for function. + @test !occursin(is_derivative, ex1) + @test !occursin(is_derivative, ex2) + @test !occursin(is_derivative, ex3) + @test occursin(is_derivative, ex4) end # Check filterchildren function. let - filterchildren(a, a) - filterchildren(a, a + 1) # Errors. - filterchildren(X, X + 1) # Errors. - filterchildren(X, X + a*(a + X)) # Errors. - filterchildren(X, D(X)) # Errors. - filterchildren(D, D(X)) # Errors. - filterchildren(D, D(X+Y)) # Errors. - - + ex1 = 2X^a - log(b + my_f(Y,Y)) - 3 + ex2 = X^(Y^(Z-a)) +log(log(log(b))) + ex3 = sin(X) + sin(Y) + a*a*a*(1-X) + ex4 = exp(a)/(pi*a) + D(Y) + D(my_f(1,Z)) + ex5 = a + 5b^2 + + # Test for variables. + @test isequal(filterchildren(X, ex1), [X]) + @test isequal(filterchildren(X, ex2), [X]) + @test isequal(filterchildren(X, ex3), [X, X]) + @test isequal(filterchildren(X, ex4), []) + @test isequal(filterchildren(Y, ex1), [Y, Y]) + @test isequal(filterchildren(Y, ex2), [Y]) + @test isequal(filterchildren(Y, ex3), [Y]) + @test isequal(filterchildren(Y, ex4), [Y]) + @test isequal(filterchildren(Z, ex1), []) + @test isequal(filterchildren(Z, ex2), [Z]) + @test isequal(filterchildren(Z, ex3), []) + @test isequal(filterchildren(Z, ex4), [Z]) + + # Test for variables. + + @test isequal(filterchildren(a, ex1), [a]) + @test isequal(filterchildren(a, ex2), [a]) + @test isequal(filterchildren(a, ex3), [a]) + @test isequal(filterchildren(a, ex4), [a, a]) + @test isequal(filterchildren(a, ex5), [a]) + @test isequal(filterchildren(b, ex1), [b]) + @test isequal(filterchildren(b, ex2), [b]) + @test isequal(filterchildren(b, ex3), []) + @test isequal(filterchildren(b, ex4), []) + @test isequal(filterchildren(b, ex5), [b]) + + # Test for function. + @test isequal(filterchildren(is_derivative, ex1), []) + @test isequal(filterchildren(is_derivative, ex2), []) + @test isequal(filterchildren(is_derivative, ex3), []) + @test isequal(filterchildren(is_derivative, ex4), [D(Y), D(my_f(1,Z))]) end From 9a9f10ea894918146423aa1c9203643f85780b80 Mon Sep 17 00:00:00 2001 From: Torkel Date: Fri, 15 Mar 2024 18:02:01 -0400 Subject: [PATCH 7/9] slight formatting --- src/rewrite-helpers.jl | 44 +++++++++++++++++++++--------------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/src/rewrite-helpers.jl b/src/rewrite-helpers.jl index 3acf86cec..b2a7d0249 100644 --- a/src/rewrite-helpers.jl +++ b/src/rewrite-helpers.jl @@ -81,6 +81,28 @@ function _occursin(r, y) end end +""" +filterchildren(c, x) +Returns all parts of `x` that fufills the condition given in c. c can be a function or an expression. +If it is a function, returns everything for which the function is `true`. If c is an expression, returns +all expressions that matches it. + +Examples: +```julia +@syms x +Symbolics.filterchildren(x, log(x) + x + 1) +``` +returns `[x, x]` + +```julia +@variables t X(t) +D = Differential(t) +Symbolics.filterchildren(Symbolics.is_derivative, X + D(X) + D(X^2)) +``` +returns `[Differential(t)(X(t)^2), Differential(t)(X(t))]` +""" +filterchildren(r, y) = filterchildren!(r, y, []) + function filterchildren!(r::Any, y, acc) y = unwrap(y) r = unwrap(r) @@ -106,28 +128,6 @@ function filterchildren!(r::Any, y, acc) end end -""" -filterchildren(c, x) -Returns all parts of `x` that fufills the condition given in c. c can be a function or an expression. -If it is a function, returns everything for which the function is `true`. If c is an expression, returns -all expressions that matches it. - -Examples: -```julia -@syms x -Symbolics.filterchildren(x, log(x) + x + 1) -``` -returns `[x, x]` - -```julia -@variables t X(t) -D = Differential(t) -Symbolics.filterchildren(Symbolics.is_derivative, X + D(X) + D(X^2)) -``` -returns `[Differential(t)(X(t)^2), Differential(t)(X(t))]` -""" -filterchildren(r, y) = filterchildren!(r, y, []) - module RewriteHelpers import Symbolics: filterchildren, unwrap export replace, occursin, filterchildren, unwrap From a5de10aba44241e9305f015b4ceedbfae1bfa757 Mon Sep 17 00:00:00 2001 From: Torkel Date: Fri, 15 Mar 2024 18:23:40 -0400 Subject: [PATCH 8/9] test fix --- test/diff.jl | 1 + 1 file changed, 1 insertion(+) diff --git a/test/diff.jl b/test/diff.jl index 21e0ae032..e8bcc238a 100644 --- a/test/diff.jl +++ b/test/diff.jl @@ -355,6 +355,7 @@ let @variables t X(t) Y(t) @syms a b D = Differential(t) + my_f(x, y) = x^3 + 2y # Single expressions. @test !Symbolics.is_derivative(Symbolics.unwrap(D)) From 4d37631eec573e5f3ccde8be2bb6961252bd5553 Mon Sep 17 00:00:00 2001 From: Torkel Date: Mon, 18 Mar 2024 12:46:13 -0400 Subject: [PATCH 9/9] add entries in docs --- docs/src/manual/derivatives.md | 1 + docs/src/manual/expression_manipulation.md | 3 +++ 2 files changed, 4 insertions(+) diff --git a/docs/src/manual/derivatives.md b/docs/src/manual/derivatives.md index ffd752794..bbbda2fe4 100644 --- a/docs/src/manual/derivatives.md +++ b/docs/src/manual/derivatives.md @@ -13,6 +13,7 @@ the differentials down to basic one-variable expressions. ```@docs Differential expand_derivatives +is_derivative ``` !!! note diff --git a/docs/src/manual/expression_manipulation.md b/docs/src/manual/expression_manipulation.md index 9d9bfae33..3dfbbd44b 100644 --- a/docs/src/manual/expression_manipulation.md +++ b/docs/src/manual/expression_manipulation.md @@ -28,4 +28,7 @@ Symbolics.diff2term Symbolics.solve_for Symbolics.degree Symbolics.coeff +Symbolics.replace +Symbolics.occursin +Symbolics.filterchildren ```