-
Notifications
You must be signed in to change notification settings - Fork 157
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
Tests for rewrite hellper #1026
Merged
ChrisRackauckas
merged 9 commits into
JuliaSymbolics:master
from
TorkelE:tests_for_rewrite_hellper
Mar 18, 2024
Merged
Changes from all commits
Commits
Show all changes
9 commits
Select commit
Hold shift + click to select a range
8ebbb69
rewrite helpers module
shashi 4637afc
include include
shashi 972f574
test init
TorkelE 7f98242
up
TorkelE 637b8e6
up
TorkelE 8616f8f
finish (bar errors)
TorkelE 9a9f10e
slight formatting
TorkelE a5de10a
test fix
TorkelE 4d37631
add entries in docs
TorkelE File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,134 @@ | ||
""" | ||
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 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, 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 | ||
|
||
""" | ||
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. | ||
|
||
Examples: | ||
```julia | ||
@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`. | ||
``` | ||
""" | ||
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 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 | ||
|
||
""" | ||
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) | ||
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 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)) | ||
return acc | ||
end | ||
end | ||
|
||
module RewriteHelpers | ||
import Symbolics: filterchildren, unwrap | ||
export replace, occursin, filterchildren, unwrap | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,102 @@ | ||
|
||
# Fetch packages. | ||
using Symbolics | ||
using Symbolics.RewriteHelpers | ||
using Test | ||
|
||
@variables t X(t) Y(t) Z(t) | ||
@syms a b | ||
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) | ||
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 = a + 5b^2 | ||
|
||
# Test for variables. | ||
@test occursin(X, ex1) | ||
@test occursin(X, ex2) | ||
@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 | ||
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 | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should probably move
ModelingToolkit.fixedpoint_sub
here as well?