@@ -2,7 +2,7 @@ using Symbolics
2
2
3
3
const SAFE_ALTERNATIVES = Dict (log => slog, sqrt => ssqrt, cbrt => scbrt)
4
4
5
- function isolate (lhs, var; warns= true , conditions= [])
5
+ function isolate (lhs, var; warns= true , conditions= [], complex_roots = true , periodic_roots = true )
6
6
rhs = Vector {Any} ([0 ])
7
7
original_lhs = deepcopy (lhs)
8
8
lhs = unwrap (lhs)
@@ -74,12 +74,21 @@ function isolate(lhs, var; warns=true, conditions=[])
74
74
power = args[2 ]
75
75
new_roots = []
76
76
77
- for i in eachindex (rhs)
78
- for k in 0 : (args[2 ] - 1 )
79
- r = wrap (term (^ , rhs[i], (1 // power)))
80
- c = wrap (term (* , 2 * (k), pi )) * im / power
81
- root = r * Base. MathConstants. e^ c
82
- push! (new_roots, root)
77
+ if complex_roots
78
+ for i in eachindex (rhs)
79
+ for k in 0 : (args[2 ] - 1 )
80
+ r = wrap (term (^ , rhs[i], (1 // power)))
81
+ c = wrap (term (* , 2 * (k), pi )) * im / power
82
+ root = r * Base. MathConstants. e^ c
83
+ push! (new_roots, root)
84
+ end
85
+ end
86
+ else
87
+ for i in eachindex (rhs)
88
+ push! (new_roots, wrap (term (^ , rhs[i], (1 // power))))
89
+ if iseven (power)
90
+ push! (new_roots, wrap (term (- , new_roots[end ])))
91
+ end
83
92
end
84
93
end
85
94
rhs = []
@@ -97,7 +106,7 @@ function isolate(lhs, var; warns=true, conditions=[])
97
106
ia_conditions! (oper, lhs, rhs, conditions)
98
107
invop = left_inverse (oper)
99
108
invop = get (SAFE_ALTERNATIVES, invop, invop)
100
- if is_periodic (oper)
109
+ if is_periodic (oper) && periodic_roots
101
110
# make this global somehow so the user doesnt need to declare it on his own
102
111
new_var = gensym ()
103
112
new_var = (@variables $ new_var)[1 ]
@@ -118,7 +127,7 @@ function isolate(lhs, var; warns=true, conditions=[])
118
127
return rhs, conditions
119
128
end
120
129
121
- function attract (lhs, var; warns = true )
130
+ function attract (lhs, var; warns = true , complex_roots = true , periodic_roots = true )
122
131
if n_func_occ (simplify (lhs), var) <= n_func_occ (lhs, var)
123
132
lhs = simplify (lhs)
124
133
end
@@ -133,7 +142,9 @@ function attract(lhs, var; warns = true)
133
142
end
134
143
lhs = attract_trig (lhs, var)
135
144
136
- n_func_occ (lhs, var) == 1 && return isolate (lhs, var, warns = warns, conditions= conditions)
145
+ if n_func_occ (lhs, var) == 1
146
+ return isolate (lhs, var; warns, conditions, complex_roots, periodic_roots)
147
+ end
137
148
138
149
lhs, sub = turn_to_poly (lhs, var)
139
150
@@ -151,12 +162,12 @@ function attract(lhs, var; warns = true)
151
162
new_var = collect (keys (sub))[1 ]
152
163
new_var_val = collect (values (sub))[1 ]
153
164
154
- roots, new_conds = isolate (lhs, new_var, warns = warns)
165
+ roots, new_conds = isolate (lhs, new_var; warns = warns, complex_roots, periodic_roots )
155
166
append! (conditions, new_conds)
156
167
new_roots = []
157
168
158
169
for root in roots
159
- new_sol, new_conds = isolate (new_var_val - root, var, warns = warns)
170
+ new_sol, new_conds = isolate (new_var_val - root, var; warns = warns, complex_roots, periodic_roots )
160
171
append! (conditions, new_conds)
161
172
push! (new_roots, new_sol)
162
173
end
@@ -166,7 +177,7 @@ function attract(lhs, var; warns = true)
166
177
end
167
178
168
179
"""
169
- ia_solve(lhs, var)
180
+ ia_solve(lhs, var; kwargs... )
170
181
This function attempts to solve transcendental functions by first checking
171
182
the "smart" number of occurrences in the input LHS. By smart here we mean
172
183
that polynomials are counted as 1 occurrence. for example `x^2 + 2x` is 1
@@ -195,6 +206,13 @@ we throw an error to tell the user that this is currently unsolvable by our cove
195
206
- lhs: a Num/SymbolicUtils.BasicSymbolic
196
207
- var: variable to solve for.
197
208
209
+ # Keyword arguments
210
+ - `warns = true`: Whether to emit warnings for unsolvable expressions.
211
+ - `complex_roots = true`: Whether to consider complex roots of `x ^ n ~ y`, where `n` is an integer.
212
+ - `periodic_roots = true`: If `true`, isolate `f(x) ~ y` as `x ~ finv(y) + n * period` where
213
+ `is_periodic(f) == true`, `finv = left_inverse(f)` and `period = fundamental_period(f)`. `n`
214
+ is a new anonymous symbolic variable.
215
+
198
216
# Examples
199
217
```jldoctest
200
218
julia> solve(a*x^b + c, x)
@@ -238,17 +256,17 @@ See also: [`left_inverse`](@ref), [`inverse`](@ref), [`is_periodic`](@ref),
238
256
# References
239
257
[^1]: [R. W. Hamming, Coding and Information Theory, ScienceDirect, 1980](https://www.sciencedirect.com/science/article/pii/S0747717189800070).
240
258
"""
241
- function ia_solve (lhs, var; warns = true )
259
+ function ia_solve (lhs, var; warns = true , complex_roots = true , periodic_roots = true )
242
260
nx = n_func_occ (lhs, var)
243
261
sols = []
244
262
conditions = []
245
263
if nx == 0
246
264
warns && @warn (" Var not present in given expression" )
247
265
return []
248
266
elseif nx == 1
249
- sols, conditions = isolate (lhs, var, warns = warns)
267
+ sols, conditions = isolate (lhs, var; warns = warns, complex_roots, periodic_roots )
250
268
elseif nx > 1
251
- sols, conditions = attract (lhs, var, warns = warns)
269
+ sols, conditions = attract (lhs, var; warns = warns, complex_roots, periodic_roots )
252
270
end
253
271
254
272
isequal (sols, nothing ) && return nothing
0 commit comments