Question

I'm trying to use an equation that I've generated using sympy.Eq(func, var) in a lambda. It seems to be returning a list of 'Add' objects, which I'm not sure how to use. I tried typecasting to astr before using eval, and i tried from sympy import I, which i think has something to do with the problem.

Here's the code, and the error message:

py solid.py -v y = (x-1.0)(x-3.0)*2 1.0 3.0 -axis y --method disk


Here is a running example:

import sys
import argparse
import math
from scipy import integrate
from sympy import Symbol, Eq, solve, I
import numpy
import pylab

parser = argparse.ArgumentParser(description='Find the volume of the solid of rotation defined. Use * for multiplication and ** to raise a power. Bounds are set equal to the implicit variable. Trailing .0\'s must be used for constants, and parentheses must be escaped ( e.g. \(x-2\) ). Answers are accurate to 6 decimals')
parser.add_argument('var', choices='xy', help='x|y')
parser.add_argument('=', metavar='=', choices='=')
parser.add_argument('equation', help='continous function')
parser.add_argument('a', type=float, help='bound \'a\'')
parser.add_argument('b', type=float, help='bound \'b\'')
parser.add_argument('-axis', choices='xy', help='axis of revolution (default == x)')
parser.add_argument('-m', choices='ds', help='method (disk/shell)')
parser.add_argument('-g', action='store_true', help='show graph')
parser.add_argument('-v', action='store_true', help='verbose (for debugging)')
args = parser.parse_args()


y = Symbol('y')
x =  Symbol('x')

def solve_for_implicit(func, var):
  if var == 'x':
      equation = Eq(eval(func), x)
      func = solve(equation, y)
  else:
      equation = Eq(eval(func), y)
      func = solve(equation, x)

  return func

def volume(var, func, a, b, axis=None, method=None):
  if axis == None: axis = 'x'
  if method == 's': method = 'shell'
  if method == 'd': method = 'disk'

  if var == axis and axis == 'x':
      if args.v: print 'x = y about x'

      if not method == 'disk':
          pass
      else:
          pass

  elif var == axis and axis == 'y':
      # SHELL METHOD
      if args.v: print 'y = x about y'
      if not method == 'disk':
          # this is what should be used for y = x about y
          if args.v: print 'using SHELL method'
          func = eval('lambda x: ' + 'x*(' + func + ')')
          integral = integrate.quad(func, a, b)
          if args.v: print 'integral from', a, 'to', b, '=', integral[0]
          answer = 2 * math.pi * integral[0]
          if args.v: print '2*pi*', integral[0], '=', answer
      else:
          func = solve_for_implicit(func, var)
          print func[0]
          func = eval('lambda y: ' + '(' + str(func[0]) + ')**2')
          integral = integrate.quad(func, a, b)
          if args.v: print 'integral=', integral[0]
          answer = math.pi * integral[0]

  elif not var == axis and axis == 'y':
      # DISK METHOD
      if args.v: print 'x = y about y -- '
      if not method == 'shell':
          pass
      else:
          pass

  elif not var == axis and axis == 'x':
      # DISK
      if args.v: print 'y = x about x --',
      if not method == 'shell':
          pass
      else:
          pass

  return answer


print volume(args.var, args.equation, args.a, args.b, args.axis, args.m)
if args.g: graph(args.equation, args.a, args.b)

Traceback (most recent call last):
File "solid.py", line 136, in print volume(args.var, args.equation, args.a, args.b, args.axis, args.m) File "solid.py", line 75, in volume func = eval('lambda y: ' + '(' + func[0] + ')**2') TypeError: cannot concatenate 'str' and 'Add' objects

and when I try typecasting it to a str() first i get this:

File "solid.py", line 136, in print volume(args.var, args.equation, args.a, args.b, args.axis, args.m) File "solid.py", line 76, in volume integral = integrate.quad(func, a, b) File "/usr/lib/python2.6/dist-packages/scipy/integrate/quadpack.py", line 185, in quad retval = _quad(func,a,b,args,full_output,epsabs,epsrel,limit,points) File "/usr/lib/python2.6/dist-packages/scipy/integrate/quadpack.py", line 249, in _quad return _quadpack._qagse(func,a,b,args,full_output,epsabs,epsrel,limit) quadpack.error: Supplied function does not return a valid float.

also, print func[0] gives:

2.33333333333333 + (0.296296296296298 - y/2 + (-0.0877914951989024 + (0.592592592592595 - y)2/4)(1/2))(1/3)*(1/2 - I*3(1/2)/2) + 0.444444444444444/((1/2 - I*3*(1/2)/2)(0.296296296296298 - y/2 + (-0.0877914951989024 + (0.592592592592595 - y)2/4)(1/2))**(1/3))

thanks for your help everyone, sorry for not providing a complete script before.

Was it helpful?

Solution

"I tried typecasting to astr before using eval, and i tried from sympy import I, which i think has something to do with the problem"

Yes, without a doubt that's exactly the problem. I'm sure Numpy has docuemntation on how to use the Add objects. Converting them to strings and then evaluating them definitely is not the right solution.

Except reading the documentation, you can also inspect the objects with dir(func) to see what functions and attributes it has. In the interpreter there is also a nifty help function, so you can type help(func) and get information.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top