x+I'm using sympy to compute the Jacobian of a fairly complicated expression, and the resulting expressions are all in terms of the lowest-level symbols that I've defined. However, it would be very nice to have it in terms of some of the higher level expressions. For example, consider the basic snippet below.
>>> from sympy import *
>>> x, y = symbols('x, y')
>>> z = x + y
>>> f = z**2
>>> pprint(f)
2
(x + y)
Here, f is shown as (x + y)^2, but I would like it to be shown as z^2. Is there a way to do this in sympy?
Edit
Declaring z as a symbol and then substituting in x+y after the fact allowed me to get the Jacobian in terms of z, but my substitution wasn't able to handle the case when the terms were factored out. For example:
>>> from sympy import *
>>> x, y, z = symbols('x, y, z')
>>> f = z**2
>>> F = Matrix([f.subs(z, x+y)]).jacobian(Matrix([x, y]))
>>> F
Matrix([[2*x + 2*y, 2*x + 2*y]])
>>> F.subs(x+y, z)
Matrix([[2*x + 2*y, 2*x + 2*y]])
>>> F.subs(2*x+2*y, 2*z)
Matrix([[2*z, 2*z]])
Here, substituting x+y for z doesn't work because the expression has been expanded out to be 2x + 2y. Can F be rewritten in terms of x+y to make the substitution work no matter how it's been factored?
The subs function always works well with replacing symbols; in your case you are trying to replace a sum and that will not work well unless that sum actually literally appears as an argument in the expression tree, e.g. exp(x + y).subs(x + y, z) -> exp(z). So there are two approaches:
for a simple relationship like x + y -> z, solve for one of the variables and do the replacement x -> z - y
get your expression tree tidied up to expose the sum,
e.g.
>>> factor_terms(F).subs(x + y, z), F.subs(x, z - y)
(Matrix([[2*z, 2*z]]), Matrix([[2*z, 2*z]]))
sympy shows formulas using symbols.
Here you have two symbols x and y. z is not a symbol. It's an Add object.
>>> type(x)
<class 'sympy.core.symbol.Symbol'>
>>> type(z)
<class 'sympy.core.add.Add'>
You must create another symbol z and when you try to do something to z, let's say evaluate, diff etc, you can specify that z is x+y
Related
I want to make an integral by parts step by step, so I'm trying to write the first term: u*v (evaluated between A and B) but I have no idea of how to insert the usual bar to indicate the evaluation.
The closest thing that SymPy printers have is Subs, the inert form of substitution of one expression for another. For example
>>> u, v = x, sin(x)
>>> pprint(Subs(u*v, x, pi) - Subs(u*v, x, 0))
- (x⋅sin(x))│ + (x⋅sin(x))│
│x=0 │x=π
Or, in LaTeX terms,
>>> latex(Subs(u*v, x, pi) - Subs(u*v, x, 0))
'- \\left. x \\sin{\\left (x \\right )} \\right|_{\\substack{ x=0 }} + \\left. x \\sin{\\left (x \\right )} \\right|_{\\substack{ x=\\pi }}'
There is no logic for printing the bar with x = b on top and x = a at the bottom, because there is no class like Subs but with two substitutions for x.
To actually evaluate (not to print) such a thing, one can use
>>> (u*v).subs(x, pi) - (u*v).subs(x, 0)
0
Or, for tricky improper integrals where a limit has to be taken,
>>> (u*v)._eval_interval(x, S(0), pi)
0
The internal method _eval_interval takes limits instead of direct evaluation when needed.
I've been trying this now for hours. I think I don't understand a basic concept, that's why I couldn't answer this question to myself so far.
What I'm trying is to implement a simple mathematical function, like this:
f(x) = x**2 + 1
After that I want to derive that function.
I've defined the symbol and function with:
x = sympy.Symbol('x')
f = sympy.Function('f')(x)
Now I'm struggling with defining the equation to this function f(x). Something like f.exp("x**2 + 1") is not working.
I also wonder how I could get a print out to the console of this function after it's finally defined.
sympy.Function is for undefined functions. Like if f = Function('f') then f(x) remains unevaluated in expressions.
If you want an actual function (like if you do f(1) it evaluates x**2 + 1 at x=1, you can use a Python function
def f(x):
return x**2 + 1
Then f(Symbol('x')) will give a symbolic x**2 + 1 and f(1) will give 2.
Or you can assign the expression to a variable
f = x**2 + 1
and use that. If you want to substitute x for a value, use subs, like
f.subs(x, 1)
Here's your solution:
>>> import sympy
>>> x = sympy.symbols('x')
>>> f = x**2 + 1
>>> sympy.diff(f, x)
2*x
Another possibility (isympy command prompt):
>>> type(x)
<class 'sympy.core.symbol.Symbol'>
>>> f = Lambda(x, x**2)
>>> f
2
x ↦ x
>>> f(3)
9
Calculating the derivative works like that:
>>> g = Lambda(x, diff(f(x), x))
>>> g
x ↦ 2x
>>> g(3)
6
Have a look to:
Sympy how to define variables for functions, integrals and polynomials
You can define it according to ways:
a python function with def as describe above
a python expression g=x**2 + 1
I recommended :
first, define a symbolic variable
x = sympy.symbols('x')
second, define a symbolic function
f = sympy.Function('f')(x)
define a formula
f = x**x+1
if you have so many variable can use this function
def symbols_builder(arg):
globals()[arg]=sp.symbols(str(arg))
if you have so many functions can use this function
def func_build(name, *args):
globals()[name]=sp.Function(str(name))(args)
I have a complicated equation which is function of several variables and I want to manipulate like this example:
y = (x + a) / z
x = y*z - a
Is it possible to do this kind of manipulation matlab or python?
If there is possibility then please point out method or function to do this operation.
I tried following code in Sympy Shell:
x,y,z,a = symbols ('x y z a')
solve ( y = (x-a)/z, x)
I am getting following error:
Traceback (most recent call last):
File "<string>", line 1
SyntaxError: non-keyword arg after keyword arg
In Matlab you'd need the symbolic math toolbox (which I don't have so I can't test) and then you should be able to do use the solve function:
syms y x a z
solve(y == (x+a)/z, x)
I have NO experince with sympy but pretty sure based on the docs this is how you do it:
from sympy import solve, Poly, Eq, Function, exp
from sympy.abc import x, y, z, a
solve(y - (x+a)/z, x)
SymPy is a Python library, so your SymPy code needs to be valid Python. In Python, = is the assignment operator, which is why solve ( y = (x-a)/z, x) gives a SyntaxError. See http://docs.sympy.org/latest/gotchas.html#equals-signs.
To create an equality in SymPy use Eq, like solve(Eq(y, (x - a)/z, x), or use the fact that expressions in SymPy are assumed to be equal to zero, like solve(y - (x - a)/z, x).
I'm looking for an example of operations with logarithms in Python. I've tried with sympy and numpy and I still can't do what I want. For example, for an input like this:
log(x+1)+log(4-x)=log(100) # it's just an example
the output should give me the x value. I need to do this with any other functions like log(x+1)=4 or log(x)-log(x+1)=log(x).
Is there some method or somewhere (documentation or similar) where can I find how to do this?
I may be misunderstanding what you need to do because you said you tried sympy already. However, it looks like you just want to solve for x in an algebraic equation.
Solving for x in the equation
log(x+1)+log(4-x)=log(100)
using sympy would be
>>> from sympy import Symbol, solve, log
>>> x = Symbol('x')
>>> solve(log(x+1) + log(4-x) - log(100), x)
[3/2 - 5*sqrt(15)*I/2, 3/2 + 5*sqrt(15)*I/2]
If you want, you can check that these two solutions are correct with numpy.
>>> import numpy as np
>>> a = 3/2 - 5*np.sqrt(15)*1j/2
>>> b = 3/2 + 5*np.sqrt(15)*1j/2
>>> np.log(a + 1) + np.log(4-a)
(4.6051701859880918+0j)
>>> np.log(b + 1) + np.log(4-b)
(4.6051701859880918+0j)
>>> np.log(100)
4.6051701859880918
Is that not what you are looking for?
Since log is a non-linear function, you will need to use a non-linear solver like scipy.optimize.fsolve. It take in a function and a guess value and returns the answer in the form of an array. For simplicity reason, I defined the function as a lambda function since we don't need it outside of this line, but creating a function using standard def methods would work as well. The [0] on the back end get the value out of the array to return just the float.
import scipy.optimize
import math
scipy.optimize.fsolve(lambda x: math.log(x+1) - 4, 5)[0] # 5 is guess value
>>> 53.598
# Check
math.exp(4) - 1
>>> 53.598
Good advice already given. I just note that you can also check the answer in SymPy.
>>> L, R = log(x+1)+log(4-x), log(100)
>>> eq = Eq(L, R)
>>> eq
log(-x + 4) + log(x + 1) == log(100)
>>> sol = solve(eq)
>>> [eq.subs(x, i) for i in sol]
[True, True]
So in the Eq form the solutions were verified automatically. This is not always
true but you can use numerical evaluation to check the value:
>>> f = eq.lhs - eq.rhs; f
log(-x + 4) + log(x + 1) - log(100)
>>> f.subs(x, sol[0])
-log(100) + log(5/2 - 5*sqrt(15)*I/2) + log(5/2 + 5*sqrt(15)*I/2)
>>> _.n()
0.e-124 + 0.e-125*I
>>> f.subs(x, sol[0]).n(chop=True) # the small numbers can be chopped
0
I am trying to manipulate variables in sympy, so that after I can input them into a Python function which requires the input to be “normal” Python code. For example:
I would like to input (where x is a sympy symbol):
y = x**3 + x**2 + 3*x +5
Then, in the same code I would later like to be able to insert y into another function, lets say:
OtherFunction(y)
where y is no longer the “type” sympy symbol, but rather interpreted as if I had directly input
OtherFunction(x**3 + x**2 + 3*x +5)
Is there a way to do this?
This is already how Python works. When you define y as you show, you are creating a Python variable, y, that has the value of a SymPy expression. So if you call some function, passing y, you are actually passin the expression:
>>> y = x**3 + x**2 + 3*x +5
>>> def foo(x):
... print 'got',x
...
>>> foo(y)
got x**3 + x**2 + 3*x + 5