I get the error 'Add' object is not callable' when trying to display an integral with limits. However, works perfectly fine without the use of limits or when differentiating.
"Equation" is a randomly generated equation
from random import *
from sympy import *
from fractions import *
def IntegrateBetweenLimitsQuestion(Equation):
x, y = symbols('x,y')
a = 0
b = 0
while b == a:#so the limits cannot be the same number
b = randint(-5,5) #upperlimit
a = randint(-5,5) #lowerlimit
LimitQuestion = Integral(Equation(x, a, b))
return(LimitQuestion)
Try slip a comma after Equation: Integral(Equation, (x, a, b))
Related
Intro
We have been working on a recent project and have been looking for a suitable system to calculate some values. SymPy was recommended as being a rich mathematical library. However, we have been unable to make it "work" with our project.
The issue we have been struggling with specifically is that many of the values we would be using have been rounded numerous times and are likely susceptible to float errors. To work around this on a previous project, we used Interval Arithmetic for JavaScript to fairly effective use. mpmath for Python appears to be similar, but SymPy not only uses mpmath, but also offers other potentially useful functions we may need in the future.
Problem
A sample equation that we have been working on lately is a = b * (1 + c * d * e) and we are looking to solve for e when all other variables are known. However, some of the variables need to be represented as a range of values as we don't know the exact value, but a small range.
Code
from sympy import *
from sympy.sets.setexpr import SetExpr
a, b, c, d, e = symbols('a b c d e')
b = 40
c = 1
d = 0.1
a = SetExpr(Interval(45.995, 46.005))
equ = Eq(b * (1 + c * d * e), a)
solveset(equ, e)
ValueError: The argument '45.995*I' is not comparable.
This was just the latest attempt, but I have tried setting domains, setting inequalities for symbols, using AccumBounds, and numerous other solutions but I can't help but think that we have completely overlooked something simple.
Solution
It appears that that using one interval is doable with the code provided by the selected answer, but it doesn't extend to multiple symbols requiring intervals or ranges of values. It appears we will be extending the mpmath library to support additional interval functions.
There is an intervalmath module in SymPy in the plotting module for some reason. It doesn't subclass Basic though so can't be used directly in an expression. We can however use lambdify to substitute it into an expression as
from sympy import *
from sympy.plotting.intervalmath import interval
b = 40
c = 1
d = 0.1
a, e = symbols('a, e', real=True)
equ = Eq(b * (1 + c * d * e), a)
sol_e, = solveset(equ, e)
f_e = lambdify(a, sol_e)
int_a = interval(45.995, 46.005)
int_e = f_e(a=int_a)
print(int_e)
This gives
[1.498750, 1.501250]
I don't think the intervalmath module is used much though so there's a good chance it might not fully work in your real problem.
Using sets is probably a better approach and it seems that imageset can do this:
In [16]: set_e = imageset(Lambda(a, sol_e), Interval(45.995, 46.005))
In [17]: set_e
Out[17]: [1.49875, 1.50125]
I'm not sure how well this works with more than one symbol/interval though.
EDIT: For completeness I'm showing how you would use intervalmath with more than one interval:
from sympy import *
from sympy.plotting.intervalmath import interval
b = 40
d = 0.1
a, c, e = symbols('a, c, e', real=True)
equ = Eq(b * (1 + c * d * e), a)
sol_e, = solveset(equ, e)
f_e = lambdify((a, c), sol_e)
int_a = interval(45.995, 46.005)
int_c = interval(0.95, 1.05)
int_e = f_e(a=int_a, c=int_c)
print(int_e)
That gives
[1.427381, 1.580263]
I have different locations, and I need to calculate the distance between them:
Location Lat Long Distance
A -20 -50 (A-B)+(A-C)+(A-D)
B -20.3 -51 (B-A)+(B-C)+(B-D)
C -21 -50 (C-A)+(C-B)+(C-D)
D -20.8 -50.2 (D-A)+(D-B)+(D-C)
Would anyone know me?
I'm using this equation to calculate the distance between two points, but I don't know how to calculate between several points.
R = 6373.0
dist_lat=lat2-lat
dist_lon=long2-lon
a= np.sin(dist_lat/2)**2 + np.cos(lat) * np.cos(lat2) * np.sin(dist_lon/2)**2
b= 2 * np.arctan2(np.sqrt(a), np.sqrt(1 - a))
Dist= R * b
this is my first time with python so beware, also I made this rather quickly - it is probably buggy.
Tested on python2.7.
import numpy as np
import itertools as it
# these are the points
points = {
'A' :{'lat':-20 ,'lon':-50}
,'B':{'lat':-20.3 ,'lon':-51}
,'C':{'lat':-21 ,'lon':-50}
,'D':{'lat':-20.8 ,'lon':-50.2}
}
# this calculates the distance beween two points
# basicly your formula wrapped in a function
# - used below
def distance(a, b):
R = 6373.0
dist_lat = a['lat']-b['lat']
dist_lon = a['lon']-b['lon']
x = np.sin(dist_lat/2)**2 + np.cos(b['lat']) * np.cos(a['lat']) * np.sin(dist_lon/2)**2
y = 2 * np.arctan2(np.sqrt(x), np.sqrt(1 - x))
return R * y
distances = {}
# produce the distance beween all combinations
# see: https://docs.python.org/2/library/itertools.html
# - uses above function
for x in it.combinations(points.keys(), 2):
distances[ ''.join(x) ] = distance(points[x[0]],points[x[1]])
# for every starting point
# - filter the distance it is involved in
# - sum
for CH in ('A','B','C','D'):
print CH,' ', sum(dict((key,value) for key, value in distances.iteritems() if CH in key).values())
output:
$ python2.7 test.py
A 6983.4634697
B 9375.21128818
C 5859.5650322
D 9472.23979008
I'm trying to setup sympy to calculate derivatives. When I test it with simple equation, I'm finding the same answer (equality is true between sympy calculation and my own calculation). However when I try with more complicated ones, when it doesnt work (I checked answers with wolfram alpha too).
Here is my code:
from __future__ import division
from sympy import simplify, cos, sin, expand
from sympy import *
x, y, z, t = symbols('x y z t')
k, m, n = symbols('k m n', integer=True)
f, g, h = symbols('f g h', cls=Function)
equation = (x**3*y-x*y**3)/(x**2+y**2)
equation2 = (x**4*y+4*x**2*y**3-y**5)/((x**2+y**2)**2)
pprint(equation)
print ""
pprint(equation2)
print diff(equation,x) == equation2
This is a common "gotcha" in Sympy. For creating symbolic equalities, you should use sympy.Eq and not = or == (see the tutorial). For your example,
Eq(equation.diff(x), equation2).simplify()
True
Note, as above, that you may have to call simplify() in order to see wheather the Eq object corresponds to True or False
This code:
from sympy import *
x = Symbol('x', positive=True)
vp = Symbol('vp', positive=True)
num = integrate( (vp*sin(x))**2, (x, 0, 2*pi))
den = integrate( 1 , (x, 0, 2*pi))
print " num =",num
print " den =",den
vrms = sqrt(num/den)
print "vrms =",vrms
print "simplified vrms = ",simplify(vrms)
Returns this:
num = pi*vp**2
den = 2*pi
vrms = sqrt(2)*vp/2
simplified vrms = sqrt(2)*vp/2
How can I get it to take the last step? I'd like it return this:
vrms = vp/sqrt(2)
SymPy automatically canonicalizes rational power of rational numbers to a form with positive exponents and reduced powers. Because this happens automatically, it will happen with every such number that appears in any expression, meaning there is no way to make sqrt(2)/2 result in 1/sqrt(2).
So it looks like sqrt(2)/2 is simpler than 1/sqrt(2).
Thank you, sandwich.
Indeed, much of the code in the example is superfluous. I was worried that how the symbols were defined and calculated could be relevant.
Question is I have the Debye's formula and need to use Simpson's rule to write a function cv(T) that calculates Cv for a given temperature.
So Cv = 9*Vpk_B*(T/theta_D)3 (integral from 0 to theta_D/T) x4*ex / (ex - 1)**2
So for this integral how do I make a function to evaluate the integral using Simpson's method? The integral is 0 to theta_D/T here for the formula.
Here is what I have so far
from __future__ import division, print_function
from math import e
import numpy as np
# constants
V = 1000 # cm**3 of solid aluminum
p = 6.022*10**28 # number density in m**-3
k_b = 1.380*10**-23 # Boltzmann's constant in J*K**-1
theta_D = 428 # Debye temperature in K
N = 50 # sample points
def cV(T):
return 9*V*p*k_b*(T / theta_D)**3 * (x**4 * e**x / (e**x - 1)**2)
def debye(T, a, b, N):
If this is a homework question, you should tag it as such and provide your attempted code for your function debye. If this is real life, you're probably better off using scipy.integrate.quad than rolling your own:
from scipy.integrate import quad
def debye(T, a, b):
return quad(cV, a, b)[0]
No need to give the number of quadrature points: quad handles this for you. Note that you should define your integrand function, cV as a function of x, not T.