I have the following function:
import sympy as sp
def inverted(q, m, a, nu):
return (-1)**(m+1)*(a/m)**m*sp.exp(m)*q**(-nu)*sp.diff(1/(sp.sqrt(a**2+q**2))*(sp.sqrt(a**2+q**2)-a)**(nu), a, m+1)
I want to define some lambda function such that
f100 = lambda a, q: inverted(q, 100, a, 0)
However, when I try to examine
q = sp.symbols('q')
f100(1000.0, q)
I get the following output:
ValueError:
Can't calculate 101st derivative wrt 10.
Obviously, what is happening is when I call f100(1000.0, q), the function refers back to inverted and the issue arises. I was hoping for a way around this.
Seems like you have to make a a variable first so diff works. It doesn't work if you fix a before (I think because you differentiate with respect to a). You can substitute a with 1000 afterwards.
import sympy as sp
def inverted(q, m, a, nu):
return (-1)**(m+1)*(a/m)**m*sp.exp(m)*q**(-nu)*sp.diff(1/(sp.sqrt(a**2+q**2))*(sp.sqrt(a**2+q**2)-a)**(nu), a, m+1)
f100 = lambda a, q: inverted(q, 100, a, 0)
q, a = sp.symbols('q, a')
print(f100(a, q).subs(a, 1000))
Related
I'm trying to solve the cosine formula using sympy. (A is angle and a, b, c is sides)
sol = solve(a**2-b**2-c**2+2*b*c*cos(pi/180*A), [A, a, b, c])
print(sol)
And I end up getting results like this:
[(90.0000000000000, 5.00000000000000, 4.00000000000000, 3.00000000000000), (270.000000000000, 5.00000000000000, 4.00000000000000, 3.00000000000000)]
But it's impossible for a triangle to have a 270ยบ interior angle.
I tried to do A, B, C <= 180 and solve(a**2-b**2-c**2+2*b*c*cos(pi/180*A), [A<=180, a, b, c]).I also try to use exclude=[A<=180] in the solve(), but it don't work too.
Let's understand what's happening:
from sympy import *
a, b, c, A = symbols("a, b, c, A")
eq = a**2-b**2-c**2+2*b*c*cos(pi/180*A)
eq is a trigonometric equation involving the cosine function, which is periodic with a period of 2*pi. Suppose you want to solve cos(x) = y where y is contained in (-1, 1]: you will get two solutions! For example, suppose you want to solve cos(x) = 0.5: one solution is x=60deg and the other is x=300deg.
Now let's focus on your equation. You have one equation with 4 symbols. Let's assume that a,b,c are known quantities and asks Sympy to solve for A (the unknown, which I assume it is the angle in degrees).
We can filter out the solutions in two approaches.
First approach
Substitute the known values a, b, c into eq and then solve for A with a specified constraint:
# substitution dictionary
d = {a: 1, b: 1, c: 1}
# solve the equation asking to find the solution for which A <= 180
sol = solve([eq.subs(d), A <= 180], A)
print(sol)
# out: (-oo < A) & (A <= 180) & (Eq(A, 60) | Eq(A, 300))
Here, SymPy produced a boolean solution (meaning it is a combination of one or more solutions with the And and Or objects). Let's try to simplify it a bit:
sol2 = sol.as_set()
print(sol2)
# out: {60}
Now we can extract it with:
A_num = list(sol2)[0]
print(A_num)
# 60
Second approach
Obtain a fully symbolic solution, then substitute the known values and filter out according to your rules:
sol = solve(eq, A)
for i, s in enumerate(sol):
print("sol", i+1, ":", s)
# output:
# sol 1 : 180*(-acos((-a**2 + b**2 + c**2)/(2*b*c)) + 2*pi)/pi
# sol 2 : 180*acos((-a**2 + b**2 + c**2)/(2*b*c))/pi
# substitution dictionary
d = {a: 1, b: 1, c: 1}
sol = [s.subs(d) for s in sol]
# apply custom filter:
sol = [s for s in sol if s <= 180]
sol = sol[0]
print(sol)
# out: 60
When doing (ad hoc example)
from scipy import optimize
def fit_func(x, a, b):
return a*x + b
optimize.curve_fit(fit_func, x_data, y_data)
how can I put bounds like a>b? I know the option bounds, but it appears it does accept only explicit numbers.
Maybe some if in the definition of fit_func?
You can try with a workaround, instead of defining the function as:
def fit_func1(x, a, b):
return a*x + b
with constraint a>b, you can do:
def fit_func2(x, this_much_a_is_bigger_than_b, b):
return (a+this_much_a_is_bigger_than_b)*x + b
with constraint this_much_a_is_bigger_than_b > 0, 0 being an explicit number, and fit_func2 function is equivalent to the fit_func1 from a mathematical perspective.
Then you can have:
a = b + this_much_a_is_bigger_than_b
b = b
Curce_fit only supports box constraints (via least_squares). There are workarounds, but I'd rather change variables to e.g a and b-a
My aim is to take a triple (A, B, C), compute three "neighbours", and then output the maximum of each of those neighbours to a list.
For example, the neighbours of (sqrt(6), 4*sqrt(3), 9*sqrt(2)) are
(sqrt(3)*sqrt(2), 3*sqrt(2), 4*sqrt(3))
(4*sqrt(3), 35*sqrt(3)*sqrt(2), 9*sqrt(2))
(sqrt(3)*sqrt(2), 9*sqrt(2), 14*sqrt(3))
so the values 14*sqrt(3), 36*sqrt(6), 4*sqrt(3) would be the output.
When I try this:
A = 1*sqrt(6)
B = 4*sqrt(3)
C = 9*sqrt(2)
def nbhs_1(triple):
X = triple[0]
Y = triple[1]
Z = triple[2]
print((X.canonicalize_radical(), (X * Y - Z).canonicalize_radical(), Y.canonicalize_radical()))
def nbhs_2(triple):
X = triple[0]
Y = triple[1]
Z = triple[2]
print((Y.canonicalize_radical(), (Y * Z - X).canonicalize_radical(), Z.canonicalize_radical()))
def nbhs_3(triple):
X = triple[0]
Y = triple[1]
Z = triple[2]
print((X.canonicalize_radical(), Z.canonicalize_radical(), (X * Z - Y).canonicalize_radical()))
result_1 = nbhs_1((A, B, C))
result_2 = nbhs_2((A, B, C))
result_3 = nbhs_3((A, B, C))
print(result_1)
print(result_2)
print(result_3)
l = [max(result_1), max(result_2), max(result_3)]
I get 'NoneType' object is not iterable.
The main problem is that you are not structuring the function properly:
It is recommended that you expose your arguments within the function call. Don't def nbhs_1(triple), do instead def nbhs_1(X, Y, Z). In this way you can actually have one single function that does what you want (easier to maintain)
Return your result. At the moment you are printing the outcome of the function call but you are not returning those results.
I'm also not sure the canonicalize_radical() call is also done properly. Python is object-oriented and by writing var.canonicalize_radical() you are inferring that var should itself know about this function (e.g. the function is part of var) but that sounds wrong. The correct call may be canonicalize_radical(var)
Basically, this should be closer to a correct solution:
A=1*sqrt(6)
B=4*sqrt(3)
C=9*sqrt(2)
def nbhs(X, Y, Z):
out1 = canonicalize_radical(X)
out2 = canonicalize_radical(X*Y-Z)
out3 = canonicalize_radical(Y)
return out1, out2, out3
l = [max(nbhs(A, B, C)), max(nbhs(B, A, C)), max(nbhs(C, B, A))]
The problem is that you are not calling the functions nbhs_1, nbhs_2, and nbhs_3 and also the functions aren't returning any values
from math import sqrt
A=1*sqrt(6)
B=4*sqrt(3)
C=9*sqrt(2)
triple = (A, B, C)
def nbhs_1(triple):
X=triple[0]
Y=triple[1]
Z=triple[2]
return (X.canonicalize_radical(),(X*Y-Z).canonicalize_radical(),Y.canonicalize_radical())
def nbhs_2(triple):
X=triple[0]
Y=triple[1]
Z=triple[2]
return (Y.canonicalize_radical(),(Y*Z-X).canonicalize_radical(),Z.canonicalize_radical())
def nbhs_3(triple):
X=triple[0]
Y=triple[1]
Z=triple[2]
return (X.canonicalize_radical(),Z.canonicalize_radical(),(X*Z-Y).canonicalize_radical())
l=[max(nbhs_1(triple)),max(nbhs_2(triple)),max(nbhs_3(triple))]
I have a sympy expression involving two variables a, b. I would now like to evaluate this expression for specific values of a and b. Using a lambda like
import sympy
def get_expression(a, b):
# Complex function with a simple result. I have no control here.
return a*b + 2
a = sympy.Symbol('a')
b = sympy.Symbol('b')
z = get_expression(a, b)
f = lambda a, b: z
print(f(1, 1))
only gives
a*b + 2
though.
Any hints?
Turns out that lambdify is what I need:
f = sympy.lambdify([a, b], z)
print(f(1, 1))
I looked through several questions here on SO, but I could not find a solution for this problem:
I calculate a fourier transformation in sympy with fourier_transform(exp(-tau*abs(t)), t, w). I assigned tau, t and w with tau, t, w = symbols('tau t w'). How can I put the result of the FT into a function, e.g. something like
g(tau, w) = fourier_transform(exp(-tau*abs(t)), t, w)
? When I write it like that, I get the error can't assign to function call. When I do it like
g = fourier_transform(exp(-tau*abs(t)), t, w)
then I can not call it (as usually) with g(tau, w) or something similar. Is there a way to do that?
Edit: What I want to have as a final result is:
g(tau, w) = 2*tau/(tau**2 + 4*pi**2*w**2)
and I can call g simply with (f.eks) g(2, 3).
Edit II: Python call:
>>> fourier_transform(exp(-tau*abs(t)), t, w)
2*tau/(tau**2 + 4*pi**2*w**2)
Just if you want an inline solution, you can use lambda to approach so:
g = lambda tau,w: ourier_transform(exp(-tau*abs(t)), t, w)
Assuming the t is a local variable.
By the way, you can also use the standard function definition, but never try to define a function as a variable.
So you create your g method and use the fourier_transform inside the g method like this:
But you have to provide the t also
def g(tau, w):
return fourier_transform(exp(-tau*abs(t)), t, w)