Solving an equation for a variable - python

How can I get this to give me x = z*y/a ?
from sympy import *
x,y,a,z = symbols('x y a z')
z = a*x/y
solve(z,x) # returns 0!
# would like to get z*y/a

solve(z,x) correctly returns 0 because your code is effectively asking:
What's the value of x that would cause z to become 0?
What you really want to do (as described here) is solve a*x/y==z which can be done as follows:
from sympy import *
x,y,a,z = symbols('x y a z')
equation = a*x/y
new_eq = solve(equation - z, x) # its value is [y*z/a]

Don't assign z = a*x/y, and don't pass z to solve.
solve(expr, symbol) determines what values of symbol will make expr equal 0. If you want to figure out what value of x makes z equal a*x/y, you want z - a*x/y to equal 0:
solve(z - a*x/y, x)
You do not want to assign z = a*x/y. = means something entirely different from equality.

I think the answer to this question can be of help. Applied to your example, this gives:
>>> from sympy import *
>>> x,y,a,z = symbols('x y a z')
>>> l = z
>>> r = a*x/y
>>> solve(l-r,x)
[y*z/a]

As all the other answers points out the solution,
I would like to emphasize on the use of Eq instances here.
An Eq object represents An equal relation between two objects.
For using an Eq object, your code should look something like this:
In []: a, x, y, z = symbols('a, x, y, z')
In []: foo = Eq(z, a*x/y)
In []: solve(foo, x)
Out[]: [y*z/a]

Related

Curve translation in Python does not reach expected value

Suppose I have two curves, f(x) and g(x), and I want to evaluate if g(x) is a translation of f(x).
I used Sympy Curve to do the job with the function translate. However, I need help to reach the correct result. Consider the two functions:
f(x) = -x^2 and g(x) = -(x+5)^2 + 8
Notice that g is vertically translated by 8 and horizontally translated by 5. Why at is not equal to b in the following Python code?
from sympy import expand, Symbol, Curve, oo
x = Symbol('x')
f = -x**2
g = -(x+5)**2+8
a = Curve((x, f), (x, -oo, oo))
at = a.translate(5,8)
b = Curve((x, g), (x, -oo, oo))
a, at, b, at == b
>>> (Curve((x, -x**2), (x, -10, 10)),
Curve((x + 5, 8 - x**2), (x, -10, 10)),
Curve((x, 8 - (x + 5)**2), (x, -10, 10)),
False)
How could I make this analysis work using this or any other method?
Curve is probably not the right way to do this. If you have univariate functions for which you want to know a x and y translation will make them equal, you could use something like the following:
>>> dx,dy = Symbols('dx dy')
>>> eq = Eq(f.subs(x,x-dx)+dy)
>>> solve_undetermined_coeffs(eq,g),(dx,dy),x)
[(-5, 8)]
If there are no values of dx and dy that will solve the equality, then an empty list will be returned.
Thanks to #smichr for the reference about solve_undetermined_coeffs. Here you can find a full answer to my initial problem in Python 3.8.10 and Sympy 1.11.1.
from sympy import symbols, Eq, solve_undetermined_coeffs
x, dx, dy = symbols('x dx dy')
f = -x**2
g = -(x+5)**2+8
eq = Eq(f.subs(x,x-dx)+dy,g)
solve_undetermined_coeffs(eq,[dx,dy],x)

Getting the derivative of a function as a function with sympy (for later evaluation and substitution)

I want to work with generic functions as long as possible, and only substitute functions at the end.
I'd like to define a function as the derivative of another one, define a generic expression with the function and its derivative, and substitute the function at the end.
Right now my attempts is as follows, but I get the error 'Derivative' object is not callable:
from sympy import Function
x, y, z = symbols('x y z')
f = Function('f')
df = f(x).diff(x) # <<< I'd like this to be a function of dummy variable x
expr = f(x) * df(z) + df(y) + df(0) # df is unfortunately not callable
# At the end, substitute with example function
expr.replace(f, Lambda(X, cos(X))) # should return: -cos(x)*sin(z) - sin(y) - sin(0)
I think I got it to work with integrals as follows:
I= Lambda( x, integrate( f(y), (y, 0, x))) but that won't work for derivatives.
If that helps, I'm fine restricting myself to functions of a single variable for now.
As a bonus, I'd like to get this to work with any combination (products, derivatives, integrals) of the original function.
It's pretty disappointing that f.diff(x) doesn't work, as you say. Maybe someone will create support it sometime in the future. In the mean time, there are 2 ways to go about it: either substitute x for your y, z, ... OR lambdify df.
I think the first option will work more consistently in the long run (for example, if you decide to extend to multivariate calculus). But the expr in second option is far more natural.
Using substitution:
from sympy import *
x, y, z = symbols('x y z')
X = Symbol('X')
f = Function('f')
df = f(x).diff(x)
expr = f(x) * df.subs(x, z) + df.subs(x, y) + df.subs(x, 0)
print(expr.replace(f, Lambda(X, cos(X))).doit())
Lambdifying df:
from sympy import *
x, y, z = symbols('x y z')
X = Symbol('X')
f = Function('f')
df = lambda t: f(t).diff(t) if isinstance(t, Symbol) else f(X).diff(X).subs(X, t)
expr = f(x) * df(z) + df(y) + df(0)
print(expr.replace(f, Lambda(X, cos(X))).doit())
Both give the desired output.

Get a second implicit derivative with SymPy

we have the follow cell in jupyter kernel python3:
from sympy.interactive.printing import init_printing
from sympy.core.symbol import symbols
from sympy.geometry.util import idiff
init_printing(use_unicode=True)
x = symbols('x')
y = symbols('y')
then just run:
eq = x ** 2 - x * y + y ** 2 - 3
eqd1 = idiff(eq, y, x)
eqd1
we get the correct answer: 2x-y / x-2y
but if run the code:
eqd2 = idiff(eqd1, y, x)
eqd2
we get: x/y but the answer realy is: 18/(x-2y)² or 6(x²-xy+y²)/(x-2y)³
x/y and 18/(x-2y)² don't looks like a equal expression or factorial one of another
Running
eqd2 = idiff(eq, y, x, n=2)
simplify(expand(eqd2))
Produces
6(x2-xy+y2)/(x3-6x2y-12xy2-8y3)
which is the correct result (after a bit more simplification).

Implicit Differentiation Sympy

I've been doing derivatives in sympy, and I didn't know how that would syntactically be written. I tried looking it up, but none of the solutions made sense. For example, if I'm trying to differentiate x**5 + y**2 + z**4 = 8xyz by computation, how would I do that? Would z be a symbol, or a function like in regular derivatives? Thank you.
For two variables you can use idiff.
In your case, the simplest way is to set x and y to be functions of z, like
x = Function('x')(z)
y = Function('y')(z)
Then normal diff(expr, z) will take the derivative correctly.
You commented you used idiff, here is the corresponding code for those who want to know:
from sympy import symbols, idiff, simplify
x, y, z = symbols('x y z')
ex = x**5 + y**2 + z**4 - 8*x*y*z
ex_d = simplify(idiff(ex,(x,y),z))
display(ex_d)
In idiff(ex,(x,y),z), (x,y) are the dependent variables, and z the variable the derivative is being taken with respect to.

sympy solve function as function

I want to solve f(x) from
(Eq(2*f(x)+f(1/x),1/x))
the expected output is
f(x) = (2-x^2)/(3*x)
I try
solve((Eq(2*f(x)+f(1/x),1/x)),f(x))
This answer contains f(1/x) : (-x*f(1/x) + 1)/(2*x)
How to get f(x) = (2-x^2)/(3*x) in sympy?
I don't think sympy will solve functional equations like this in the way you want, but you could separate your particular equation into two: 2y+z = 1/x and 2z+y = x where y(1/x) = z(x) and let sympy solve for both y and z:
In [5]: x, y, z = Symbol('x'), Symbol('y'), Symbol('z')
In [6]: solve((Eq(2*y+z,1/x), Eq(2*z+y,x)),y,z)
Out[6]: {y: (-x**2 + 2)/(3*x), z: (2*x**2 - 1)/(3*x)}
So y is the f(x) that you want here.

Categories