Search code examples
sympyequationsimplification

How can I convince Sympy to come to the same simplification SAINT does for the 1961 MIT undergrad calculus problem?


The program for James R Slagle's MIT thesis A heuristic program that solves symbolic integration problems in freshman calculus, symbolic automatic integrator (SAINT) is famous(ish) for being the first practical "expert system" symbolic integrator and able to solve all of the problems on the MIT Undergraduate Calculus test (pedantically, a couple were missed, but it could have solved them; detailed here in this excellent YouTube video)

His thesis is freely available here: https://dspace.mit.edu/handle/1721.1/11997

I was excited to try Sympy on this because it looked approachable and was a reasonably difficult simplification I happened to already have an answer to .. however, Sympy doesn't simplify the integral to such a good(subjective?) simplification as the 1961 program (though it does return an equivalent result!)


Question and Speculation

How can I convince Sympy to simplify to the same equation?
Why doesn't it come to the same, seemingly-simpler result?

Perhaps it chooses the first possible outcome, or tan**3 is determined to be worse? if so, why doesn't it simplify SAINT's output?)

Perhaps it sets off down a different branch when it finds some matching Fu-routine?

Exam problem 3c

MIT problem 3c

Sympy simplification

from sympy import *
x = symbols("x", real=True)  # should this be assumed?
expr_inner = (x**4) / ((1 - x**2)**Rational(5,2))
expr_integral = integrate((expr_inner), x)
print(simplify(expr_integral))

(x**4*asin(x) + 4*x**3*sqrt(1 - x**2)/3 - 2*x**2*asin(x) - x*sqrt(1 - x**2) + asin(x))/(x**4 - 2*x**2 + 1)

Proof of Equality

from sympy import *
x = symbols("x", real=True)  # should this be assumed?
expr_saint = asin(x) + Rational(1,3)*tan(asin(x))**3 - tan(asin(x))
expr_sympy = (x**4*asin(x) + 4*x**3*sqrt(1 - x**2)/3 - 2*x**2*asin(x) - x*sqrt(1 - x**2) + asin(x))/(x**4 - 2*x**2 + 1)
expr_saint.equals(expr_sympy)  # alternatively simplify(expr_saint - expr_sympy) https://stackoverflow.com/a/37115190/

True

Equations Display

init_printing display


Solution

  • The main part is factoring out asin(x) and pulling it separate from the fraction. After this, sympy can prove the two expressions are equal:

    from sympy import *
    from IPython.display import Math, display
    x = symbols("x", real=True)  # should this be assumed?
    expr_saint = asin(x) + Rational(1,3)*tan(asin(x))**3 - tan(asin(x))
    expr_sympy = (x**4*asin(x) + 4*x**3*sqrt(1 - x**2)/3 - 2*x**2*asin(x) - x*sqrt(1 - x**2) + asin(x))/(x**4 - 2*x**2 + 1)
    
    r=[]
    r.append(latex(expr_sympy))
    expr_sympy = expr_sympy.collect(asin(x))
    r.append(latex(expr_sympy))
    expr_sympy = apart(expr_sympy,asin(x))
    r.append(latex(expr_sympy))
    
    display(Math(" \\Longrightarrow ".join(r)))
    
    display(simplify(expr_saint - expr_sympy))
    

    Output:

    enter image description here