@@ -31,7 +31,7 @@ function equiv(y, x)
3131 if is_add (y)
3232 return sum (equiv (u, x) for u in args (y))
3333 elseif is_mul (y)
34- return prod (isdependent (u, x) ? u : 1 for u in args (y))
34+ return prod (isdependent (u, x) ? u : 1 for u in args (y))
3535 elseif is_div (y)
3636 return expand_fraction (y, x)
3737 elseif is_number (y)
@@ -132,21 +132,22 @@ end
132132 Returns:
133133 a dict of sym : value pairs
134134"""
135- function subs_symbols (eq, x; include_x = false , radius = 5.0 )
135+ function subs_symbols (eq, x; include_x = false , radius = 5.0 , as_complex = true )
136136 S = Dict ()
137137 for v in get_variables (value (eq))
138138 if ! isequal (v, x)
139- S[v] = randn ()
139+ S[v] = as_complex ? Complex ( randn ()) : randn ()
140140 end
141141 end
142142
143143 if include_x
144- S[x] = randn ()
144+ S[x] = as_complex ? Complex ( randn ()) : randn ()
145145 end
146146
147147 return S
148148end
149149
150+
150151"""
151152 Splits terms into a part dependent on x and a part constant w.r.t. x
152153 For example, `atomize(a*sin(b*x), x)` is `(a, sin(b*x))`)
209210function make_eqs (eq, x, basis)
210211 frags = Dict ()
211212
212- for d in terms (eq)
213- c, a = atomize (d , x)
213+ for term in terms (eq)
214+ c, a = atomize (term , x)
214215 frags[a] = c
215216 end
216217
@@ -219,8 +220,8 @@ function make_eqs(eq, x, basis)
219220 for (i, b) in enumerate (basis)
220221 db = expand_fraction (diff (b, x), x)
221222
222- for d in terms (db)
223- c, a = atomize (d , x)
223+ for term in terms (db)
224+ c, a = atomize (term , x)
224225 frags[a] = get (frags, a, 0 ) + c * θ[i]
225226 end
226227
@@ -277,7 +278,14 @@ function make_square(eq, x, vars, frags)
277278 for i in 1 : n
278279 S = subs_symbols (eq, x; include_x = true )
279280 q = sum (substitute (k, S) * v for (k, v) in frags)
280- push! (eqs, q ~ 0 )
281+ Q = (q ~ 0 )
282+ if Q isa Array
283+ # Q returns a complex array
284+ # a different pathway is needed here!
285+ return nothing
286+ else
287+ push! (eqs, Q)
288+ end
281289 end
282290
283291 return eqs
@@ -303,29 +311,6 @@ function apply_coefs(q, ker, x)
303311 return beautify (c) * a
304312end
305313
306- function solve_eqs (eq, x, ker, eqs, vars; abstol = 1e-6 , radius = 1.0 , verbose = false )
307- try
308- A, b = make_Ab (eqs, vars)
309- q = A \ b
310- q = value .(q)
311- sol = apply_coefs (q, ker, x)
312-
313- # test if sol solves ∫ eq dx
314- S = subs_symbols (eq, x; include_x = true , radius)
315- err = substitute (diff (sol, x) - eq, S)
316-
317- if abs (err) < abstol
318- return sol
319- end
320- catch e
321- if verbose
322- @warn (e)
323- end
324- end
325-
326- return nothing
327- end
328-
329314"""
330315 The main entry point for symbolic integration.
331316
@@ -336,31 +321,49 @@ end
336321 Returns:
337322 the integral or nothing if no solution
338323"""
339- function integrate_symbolic (eq, x; abstol = 1e-6 , radius = 1.0 , verbose = false )
324+ function integrate_symbolic (eq, x; abstol = 1e-6 , radius = 1.0 , verbose = false , num_steps = 2 )
340325 eq = expand (eq)
326+ coef, eq = atomize (eq, x)
341327
342328 if is_holonomic (eq, x)
343329 basis = blender (eq, x)
344330 else
345331 basis = generate_homotopy (eq, x)
346332 end
333+
334+ for k = 1 : num_steps
335+ sol = try_symbolic (eq, x, basis; abstol, radius, verbose)
336+
337+ if sol != nothing
338+ return coef * sol
339+ end
340+
341+ if k < num_steps
342+ basis = expand_basis_symbolic (basis, x)
343+ end
344+ end
345+
346+ return nothing
347+ end
347348
349+
350+ function try_symbolic (eq, x, basis; abstol = 1e-6 , radius = 1.0 , verbose = false )
348351 ker = best_hints (eq, x, basis)
349352
350353 if ker == nothing
351354 return nothing
352355 end
353356
354357 ker = [atomize (y, x)[2 ] for y in ker]
355-
356358 eqs, vars, frags = make_eqs (eq, x, ker)
357-
358359 sol = solve_eqs (eq, x, ker, eqs, vars; abstol, radius, verbose)
359360
360361 if sol == nothing
361362 try
362363 eqs = make_square (eq, x, vars, frags)
363- sol = solve_eqs (eq, x, ker, eqs, vars; abstol, radius, verbose)
364+ if eqs != nothing
365+ sol = solve_eqs (eq, x, ker, eqs, vars; abstol, radius, verbose= false )
366+ end
364367 catch e
365368 if verbose
366369 @warn (e)
@@ -370,3 +373,36 @@ function integrate_symbolic(eq, x; abstol = 1e-6, radius = 1.0, verbose = false)
370373
371374 return sol
372375end
376+
377+
378+ function solve_eqs (eq, x, ker, eqs, vars; abstol = 1e-6 , radius = 1.0 , verbose = false )
379+ try
380+ A, b = make_Ab (eqs, vars)
381+ q = A \ b
382+ q = value .(q)
383+ sol = apply_coefs (q, ker, x)
384+
385+ # test if sol solves ∫ eq dx
386+ S = subs_symbols (eq, x; include_x = true , radius)
387+ err = substitute (diff (sol, x) - eq, S)
388+
389+ if abs (err) < abstol
390+ return sol
391+ end
392+ catch e
393+ if verbose
394+ @warn (e)
395+ end
396+ end
397+
398+ return nothing
399+ end
400+
401+
402+ function expand_basis_symbolic (basis, x)
403+ b = sum (basis)
404+ basis = split_terms (expand ((1 + x)* (b + diff (b, x))), x)
405+
406+ return basis
407+ end
408+
0 commit comments