-
Notifications
You must be signed in to change notification settings - Fork 121
/
Copy pathsubstitute.jl
72 lines (66 loc) · 2.11 KB
/
substitute.jl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
"""
substitute(expr, dict; fold=true)
substitute any subexpression that matches a key in `dict` with
the corresponding value. If `fold=false`,
expressions which can be evaluated won't be evaluated.
```julia
julia> substitute(1+sqrt(y), Dict(y => 2), fold=true)
2.414213562373095
julia> substitute(1+sqrt(y), Dict(y => 2), fold=false)
1 + sqrt(2)
```
"""
function substitute(expr, dict; fold=true)
haskey(dict, expr) && return dict[expr]
if iscall(expr)
op = substitute(operation(expr), dict; fold=fold)
if fold
canfold = !(op isa Symbolic)
args = map(arguments(expr)) do x
x′ = substitute(x, dict; fold=fold)
canfold = canfold && !(x′ isa Symbolic)
x′
end
canfold && return op(args...)
args
else
args = map(x->substitute(x, dict, fold=fold), arguments(expr))
end
maketerm(typeof(expr),
op,
args,
metadata(expr))
elseif expr isa Arr
return substitute(expr.value, dict; fold=fold)
elseif expr isa AbstractArray
res = []
for e in expr
push!(res, substitute(e, dict; fold=fold))
end
return res
else
expr
end
end
"""
occursin(needle::Symbolic, haystack::Symbolic)
Determine whether the second argument contains the first argument. Note that
this function doesn't handle associativity, commutativity, or distributivity.
"""
Base.occursin(needle::Symbolic, haystack::Symbolic) = _occursin(needle, haystack)
Base.occursin(needle, haystack::Symbolic) = _occursin(needle, haystack)
Base.occursin(needle::Symbolic, haystack) = _occursin(needle, haystack)
function _occursin(needle, haystack)
isequal(needle, haystack) && return true
if iscall(haystack)
args = arguments(haystack)
for arg in args
if needle isa Integer || needle isa AbstractFloat
isequal(needle, arg) && return true
else
occursin(needle, arg) && return true
end
end
end
return false
end