7070function is_holonomic (y, x)
7171 y = value (y)
7272
73+ # technically, polynomials are not holonomic, but practically we can include them
7374 if is_polynomial (y, x)
74- return false
75+ return true
7576 end
7677
7778 if is_number (y)
7879 return true
7980 end
8081
8182 if is_term (y)
82- return operation (y) in [sin, cos, sinh, cosh, exp]
83+ return operation (y) in [sin, cos, sinh, cosh, exp] &&
84+ is_polynomial (args (y)[1 ], x)
8385 end
8486
8587 if is_pow (y)
@@ -113,6 +115,7 @@ function blender(y, x; n = 3)
113115 end
114116 end
115117
118+ basis = expand (x + basis + x * basis)
116119 return split_terms (basis, x)
117120end
118121
@@ -289,11 +292,40 @@ function apply_coefs(q, ker, x)
289292 for (coef, expr) in zip (q, ker)
290293 s += beautify (coef) * expr
291294 end
292- s = simplify (s)
295+
296+ try
297+ s = simplify (s)
298+ catch e
299+ # println(e)
300+ end
301+
293302 c, a = atomize (s)
294303 return beautify (c) * a
295304end
296305
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+
297329"""
298330 The main entry point for symbolic integration.
299331
304336 Returns:
305337 the integral or nothing if no solution
306338"""
307- function integrate_symbolic (eq, x; abstol = 1e-6 , radius = 1.0 )
339+ function integrate_symbolic (eq, x; abstol = 1e-6 , radius = 1.0 , verbose = false )
308340 eq = expand (eq)
309341
310342 if is_holonomic (eq, x)
@@ -323,27 +355,18 @@ function integrate_symbolic(eq, x; abstol = 1e-6, radius = 1.0)
323355
324356 eqs, vars, frags = make_eqs (eq, x, ker)
325357
326- try
327- if length (eqs) != length (vars)
328- eqs = make_square (eq, x, vars, frags)
329- end
330- A, b = make_Ab (eqs, vars)
331- q = A \ b
332- q = value .(q)
333- sol = apply_coefs (q, ker, x)
358+ sol = solve_eqs (eq, x, ker, eqs, vars; abstol, radius, verbose)
334359
335- # test if sol is the correct integral of eq
336- S = subs_symbols (eq, x; include_x = true , radius)
337- err = substitute ( diff (sol , x) - eq, S )
338-
339- if abs (err) < abstol
340- return sol
341- else
342- return nothing
360+ if sol == nothing
361+ try
362+ eqs = make_square (eq , x, vars, frags )
363+ sol = solve_eqs (eq, x, ker, eqs, vars; abstol, radius, verbose)
364+ catch e
365+ if verbose
366+ @warn (e)
367+ end
343368 end
344- catch e
345- # println(e)
346369 end
347370
348- return nothing
371+ return sol
349372end
0 commit comments