sympy icon indicating copy to clipboard operation
sympy copied to clipboard

AttributeError: 'NoneType' object has no attribute 'primitive' calling integrate in sympy 1.12

Open nasser1 opened this issue 10 months ago • 4 comments

I do not know if this is known or reported before. Feel free to close if so.

I see number of exceptions AttributeError: 'NoneType' object has no attribute 'primitive'. Here is just one example out of many

from sympy import *
x,e,d=symbols('x e d')
integrand="ln(-2*x*(d*e**(1/2)/(-d)**(1/2)-e*x)/(e*x**2+d))/(e*x**2+d)"
integrate( sympify(integrand), x)

gives

raceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python3.11/site-packages/sympy/integrals/integrals.py", line 1567, in integrate
    return integral.doit(**doit_flags)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.11/site-packages/sympy/integrals/integrals.py", line 612, in doit
    antideriv = self._eval_integral(
                ^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.11/site-packages/sympy/integrals/integrals.py", line 967, in _eval_integral
    return NonElementaryIntegral(f, x).doit(risch=False)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.11/site-packages/sympy/integrals/integrals.py", line 612, in doit
    antideriv = self._eval_integral(
                ^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.11/site-packages/sympy/integrals/integrals.py", line 1084, in _eval_integral
    h = heurisch_wrapper(g, x, hints=[])
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.11/site-packages/sympy/integrals/heurisch.py", line 143, in heurisch_wrapper
    res = heurisch(f, x, rewrite, hints, mappings, retries, degree_offset,
          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.11/site-packages/sympy/integrals/heurisch.py", line 585, in heurisch
    u_split = _splitter(denom)
              ^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.11/site-packages/sympy/integrals/heurisch.py", line 563, in _splitter
    q_split = _splitter(cancel(q / s))
              ^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.11/site-packages/sympy/integrals/heurisch.py", line 551, in _splitter
    c, q = p.as_poly(y).primitive()
           ^^^^^^^^^^^^^^^^^^^^^^
AttributeError: 'NoneType' object has no attribute 'primitive'


Version info

>>> import sympy
>>> sympy.__version__
'1.12'

>python --version
Python 3.11.8
>

For reference the anti derivative should be

integrand =  Log[-2*x*(d*e^(1/2)/(-d)^(1/2) - e*x)/(e*x^2 + d)]/(e*x^2 + d)
Integrate[integrand,x]

(1/(4 Sqrt[-d] Sqrt[e]))(-2 Log[(Sqrt[e] x)/Sqrt[-d]] Log[Sqrt[-d]-Sqrt[e] x]+Log[Sqrt[-d]-Sqrt[e] x]^2+2 Log[(d Sqrt[e] x)/(-d)^(3/2)] Log[Sqrt[-d]+Sqrt[e] x]-2 Log[Sqrt[-d]+Sqrt[e] x] Log[(d+Sqrt[-d] Sqrt[e] x)/(2 d)]+2 Log[Sqrt[-d]-Sqrt[e] x] Log[(2 (Sqrt[-d] Sqrt[e] x+e x^2))/(d+e x^2)]-2 Log[Sqrt[-d]+Sqrt[e] x] Log[(2 (Sqrt[-d] Sqrt[e] x+e x^2))/(d+e x^2)]+2 PolyLog[2,1+(Sqrt[e] x)/Sqrt[-d]]-2 PolyLog[2,(d-Sqrt[-d] Sqrt[e] x)/(2 d)]-2 PolyLog[2,1+(d Sqrt[e] x)/(-d)^(3/2)])

nasser1 avatar Apr 15 '24 18:04 nasser1

I see number of exceptions AttributeError: 'NoneType' object has no attribute 'primitive'. Here is just one example out of many

I assume that you have a script and a big bank of test examples or something. Could you perhaps share that somehow?

oscarbenjamin avatar Apr 16 '24 01:04 oscarbenjamin

I see number of exceptions AttributeError: 'NoneType' object has no attribute 'primitive'. Here is just one example out of many

I assume that you have a script and a big bank of test examples or something. Could you perhaps share that somehow?

I got these from Computer Algebra Independent Integration Tests which lists exceptions generated. Note that the command shown on these pages should be string.

i.e. when it says on the above link

integrate(a**x/(b**x),x)

It is actually entered in the test program as

integrate(S( "a**x/(b**x)" ) ,x)

Also the symbols command is needed before, which is now not shown.

nasser1 avatar Apr 16 '24 05:04 nasser1

I got these from Computer Algebra Independent Integration Tests which lists exceptions generated

Oh, very nice.

It would be good to add something in CI to keep track of these examples. It would be better to have test results for the whole database rather than tracking a separate GitHub issue for each case.

Is the code for these examples publicly available somewhere?

Perhaps if we could turn those tests into doctests we could do snapshot testing with them using something like pytest-accept: https://github.com/max-sixty/pytest-accept

oscarbenjamin avatar Apr 16 '24 12:04 oscarbenjamin

Is the code for these examples publicly available somewhere?

The integration problems were collected from different sources such as by Albert Rich Rubi test suite and from contributions by others.

There are 367 test files. With total of 107,000 integrals.

Each report page for each file contains an appendix with link to plain text input file that contains all the integration problems in that file, in each CAS own syntax,

For example for sympy, here link to report 1 and you will see an appendix there. Following that there is link to download the python file with all the integration problems for sympy for that one test file.

This below is simplified version of my python script that runs on one file only and at the end gives percentage solved and failed. The input file that contains the integration problem and this script need to be in same folder.

#minimal example showing how to run CAS integration test on one
#input file to call sympy integrate command. The input file name
#is now hardcoded inside the main function below

#Run this script using the command
#
# python ./test_one_CAS_integration.py
#
#At the end it will give % passed and % failed for this one file.
#Do the same for different integration test input files.

#version: April 17, 2024

from sympy import *
import multiprocessing as mp
import os, sys, datetime, ntpath, time

def doTheIntegration(q1,q2):
    problem     = q1.get()
    integrand   = S(problem[0])
    theVar      = S(problem[1])
    anti = integrate(integrand ,theVar)
    if str(anti).find("Integral") == -1:
        result=1
    else:
        result=0

    q2.put([result,anti])


if __name__ == "__main__":

    input_test_file="input.py"

    try:
        exec(open(input_test_file).read())  #This reads lst
    except Exception as ee:
        print("Failed to open file of integration problems. [",input_test_file, "]", type(ee).__name__)
        sys.exit(1)        
        
    number_passed = 0
    number_failed = 0

    for counter, item in enumerate(lst,start=1):        
        q1= mp.Queue()
        q2= mp.Queue()
        q1.put([item[0],item[1]]) #integrand, variable
        process = mp.Process(target=doTheIntegration, args=(q1,q2,))  
        process.start() 
        try:
            result = q2.get(True,30) #30 seconds timeout
            if result[0]==1:
               number_passed = number_passed + 1 
               print("#",counter," PASSED")
            else:
               number_failed = number_failed + 1 
               print("#",counter," FAILED")
        except Exception as ee:
            number_failed = number_failed + 1 
            print("#",counter," TIMED OUT")

    print("TEST Summary: Passed ", number_passed*100/len(lst),
          "%, Failed ", number_failed*100/len(lst),"%")
                    
        

Running the above using python ./test_one_CAS_integration.py gives

>python ./test_one_CAS_integration_file.py 
# 1  PASSED
# 2  PASSED
# 3  PASSED
# 4  PASSED
# 5  PASSED
# 6  PASSED
# 7  PASSED
# 8  PASSED
# 9  PASSED
# 10  PASSED
# 11  PASSED
# 12  PASSED
# 13  PASSED
# 14  PASSED
# 15  PASSED
# 16  PASSED
# 17  PASSED
# 18  PASSED
# 19  FAILED
# 20  PASSED
# 21  PASSED
etc...
 172  PASSED
# 173  FAILED
# 174  FAILED
# 175  PASSED
TEST Summary: Passed  93.71428571428571 %, Failed  6.285714285714286 %

The independent CAS integration program just does more book keeping and statistics and generates the Latex for the reports and so on. But the above script is the basic idea. Feel free to use and modify as you need.

nasser1 avatar Apr 17 '24 05:04 nasser1