Sympy evalf for real symbol - python

This Sympy code works as I expect:
>>> x = sp.Symbol("x")
>>> y = sp.Symbol("y")
>>> z = sp.Symbol("z")
>>> (x+y+z).evalf(subs={"x":1, "y":2, "z":3})
6.0
However, if I use real-valued Symbols instead, the expression isn't simplified:
>>> x = sp.Symbol("x", real=True)
>>> y = sp.Symbol("y", real=True)
>>> z = sp.Symbol("z", real=True)
>>> (x+y+z).evalf(subs={"x":1, "y":2, "z":3})
x + y + z
I was unable to find an explanation for this by searching with keywords like sympy symbol real evalf - I only get unrelated results.
Why isn't the expression simplified in the second case? How can I substitute in values for real-valued Symbols and evaluate the expression?

Use the symbols as keys for the dictionary of substitutions, rather than string names:
>>> (x + y + z).evalf(subs={x: 1, y: 2, z: 3})
6.00000000000000
There appears to be an inconsistency between how complex and real symbols are treated:
>>> x = sp.Symbol('x')
>>> x.subs(x, 1)
1
>>> x.subs('x', 1)
1
>>> x = sp.Symbol('x', real=True)
>>> x.subs(x, 1)
1
>>> x.subs('x', 1)
x
I can't find anything relevant about this in the documentation, and the built-in help text isn't useful either. My best guess is that a string 'x' is naively converted using sp.Symbol, and the resulting symbol is always a complex-valued symbol that doesn't match the real-valued one with the same name.
I would consider this behaviour a bug and file a bug report (or look for an existing report). IMO, if a string is usable at all, it should match any symbol with that name; and an expression shouldn't be able to contain two different variables with the same name and different types; and trying to substitute in a variable with a matching name and incompatible type should probably raise an exception:
>>> x = sp.Symbol('x')
>>> # why allow this?
>>> broken = sp.Symbol('x', real=True) + x
>>> broken # if the types matched, it would simplify to 2*x
x + x
>>> # surely 2 is the only value that makes sense?
>>> broken.subs('x', 1)
x + 1
>>> x.subs('x', 1)
1
>>> # If this is allowed at all, surely the result should be 1?
>>> x.subs(sp.Symbol('x', real=True), 1)
x

Related

Setting the domain of a function in Python SymPy

I was wondering if it is somehow possible to set the domain of a math. function. For example, when I define the following expression
>>> import sympy as syp
>>> x = syp.Symbol('x')
>>> miles_to_km = x * 1.609344
>>> miles_to_km.evalf()
1.609344*x
Is it possible to limit the domain so that x is in the range [0, inf)? So the goal is that I could then use the sympy.plot function that produces a graph that starts at 0 and only includes positive x-values in contrast to
If we check the manual by doing:
help(syp.plot)
You will get:
...
expr : Expression representing the function of single variable
range: (x, 0, 5), A 3-tuple denoting the range of the free variable.
...
So, you can:
>>> import sympy as syp
>>> x = syp.Symbol('x')
>>> miles_to_km = x * 1.609344
>>> syp.plot(miles_to_km, (x,0,10))
which will give you the following output:

Sympy parser doesn't pass the right constant

>>>from sympy.parsing.sympy_parser import (parse_expr, ... standard_transformations, function_exponentiation)
>>> transformations = standard_transformations + (function_exponentiation,)
>>>parse= parse_expr('2x', transformations=transformations)
parse = parse_expr("2x", transformations=transformations)
>>> parse.coeff("x",0)
2
>>> parse.coeff("x")
2
>>> parse = parse_expr("2x+5", transformations=transformations)
>>> parse.coeff("x")
2
>>> parse.coeff("x",0)
5
I am quite new to python and sympy.
The problem here is that any time I want to get the constant 0 it returns the coefficient of x. But this doesn't happen when the constant is not zero(shown in the second equation). I am trying to use this to solve linear equations in which I don't know the user input. But it keeps giving me a wrong answer when there is no constant attached after x.
There is some discussion on Github: https://github.com/sympy/sympy/issues/5657
One way to do it is to convert to a polynomial:
>>> (2*x + 3).as_poly()
Poly(2*x + 3, x, domain='ZZ')
>>> (2*x + 3).as_poly().nth(0)
3
>>> (2*x + 3).as_poly().nth(1)
2
>>> (2*x).as_poly().nth(0)
0
>>> (2*x).as_poly().nth(1)
2
Unfortunately converting to a Poly first is slower.

Sympy: working with equalities manually

I'm currently doing a maths course where my aim is to understand the concepts and process rather than crunch through problem sets as fast as possible. When solving equations, I'd like to be able to poke at them myself rather than have them solved for me.
Let's say we have the very simple equation z + 1 = 4- if I were to solve this myself, I would obviously subtract 1 from both sides, but I can't figure out if sympy provides a simple way to do this. At the moment the best solution I can come up with is:
from sympy import *
z = symbols('z')
eq1 = Eq(z + 1, 4)
Eq(eq1.lhs - 1, eq1.rhs - 1)
# Output:
# z == 3
Where the more obvious expression eq1 - 1 only subtracts from the left-hand side. How can I use sympy to work through equalities step-by-step like this (i.e. without getting the solve() method to just given me the answer)? Any pointers to the manipulations that are actually possible with sympy equalities would be appreciated.
There is a "do" method and discussion at https://github.com/sympy/sympy/issues/5031#issuecomment-36996878 that would allow you to "do" operations to both sides of an Equality. It's not been accepted as an addition to SymPy but it is a simple add-on that you can use. It is pasted here for convenience:
def do(self, e, i=None, doit=False):
"""Return a new Eq using function given or a model
model expression in which a variable represents each
side of the expression.
Examples
========
>>> from sympy import Eq
>>> from sympy.abc import i, x, y, z
>>> eq = Eq(x, y)
When the argument passed is an expression with one
free symbol that symbol is used to indicate a "side"
in the Eq and an Eq will be returned with the sides
from self replaced in that expression. For example, to
add 2 to both sides:
>>> eq.do(i + 2)
Eq(x + 2, y + 2)
To add x to both sides:
>>> eq.do(i + x)
Eq(2*x, x + y)
In the preceding it was actually ambiguous whether x or i
was to be added but the rule is that any symbol that are
already in the expression are not to be interpreted as the
dummy variable. If we try to add z to each side, however, an
error is raised because now it is unclear whether i or z is being
added:
>>> eq.do(i + z)
Traceback (most recent call last):
...
ValueError: not sure what symbol is being used to represent a side
The ambiguity must be resolved by indicating with another parameter
which is the dummy variable representing a side:
>>> eq.do(i + z, i)
Eq(x + z, y + z)
Alternatively, if only one Dummy symbol appears in the expression then
it will be automatically used to represent a side of the Eq.
>>> eq.do(2*Dummy() + z)
Eq(2*x + z, 2*y + z)
Operations like differentiation must be passed as a
lambda:
>>> Eq(x, y).do(lambda i: i.diff(x))
Eq(1, 0)
Because doit=False by default, the result is not evaluated. to
evaluate it, either use the doit method or pass doit=True.
>>> _.doit == Eq(x, y).do(lambda i: i.diff(x), doit=True)
True
"""
if not isinstance(e, (FunctionClass, Lambda, type(lambda:1))):
e = S(e)
imaybe = e.free_symbols - self.free_symbols
if not imaybe:
raise ValueError('expecting a symbol')
if imaybe and i and i not in imaybe:
raise ValueError('indicated i not in given expression')
if len(imaybe) != 1 and not i:
d = [i for i in imaybe if isinstance(i, Dummy)]
if len(d) != 1:
raise ValueError(
'not sure what symbol is being used to represent a side')
i = set(d)
else:
i = imaybe
i = i.pop()
f = lambda side: e.subs(i, side)
else:
f = e
return self.func(*[f(side) for side in self.args], evaluate=doit)
from sympy.core.relational import Equality
Equality.do = do

Differentiating a product with an unknown function - sympy

I tried various searches but couldn't find a good google string to bring up the right results.
I have a product of the form
y = x*f(x)
where f is a function of x which is not known. I want sympy to differentiate y with respect to x. Does anyone know how I can do this?
How about:
>>> x = sympy.Symbol("x")
>>> f = sympy.Function("f")
>>> y = x * f(x)
>>> y
x*f(x)
>>> y.diff(x)
x*Derivative(f(x), x) + f(x)

Sympy "global" substitution

I have a number of symbolic expressions in sympy, and I may come to realize that one of the coefficients is zero. I would think, perhaps because I am used to mathematica, that the following makes sense:
from sympy import Symbol
x = Symbol('x')
y = Symbol('y')
f = x + y
x = 0
f
Surprisingly, what is returned is x + y. Is there any way, aside from explicitly calling "subs" on every equation, for f to return just y?
I think subs is the only way to do this. It looks like a sympy expression is something unto itself. It does not reference the pieces that made it up. That is f only has the expression x+y, but doesn't know it has any link back to the python objects x and y. Consider the code below:
from sympy import Symbol
x = Symbol('x')
y = Symbol('y')
z = Symbol('z')
f1 = x + y
f2 = z + f1
f1 = f1.subs(x,0)
print(f1)
print(f2)
The output from this is
y
x + y + z
So even though f1 has changed f2 hasn't. To my knowledge subs is the only way to get done what you want.
I don't think there is a way to do that automatically (or at least no without modifying SymPy).
The following question from SymPy's FAQ explains why:
Why doesn't changing one variable change another that depends it?
The short answer is "because it doesn't depend on it." :-) Even though
you are working with equations, you are still working with Python
objects. The equations you are typing use the values present at the
time of creation to "fill in" values, just like regular python
definitions. They are not altered by changes made afterwards. Consider
the following:
>>> a = Symbol('a') # create an object with name 'a' for variable a to point to
>>> b = a + 1; b # create another object that refers to what 'a' refers to
a + 1
>>> a = 4; a # a now points to the literal integer 4, not Symbol('a')
4
>>> b # but b is still pointing at Symbol('a')
a + 1
Changing quantity a does not change b; you are not working with a set
of simultaneous equations. It might be helpful to remember that the
string that gets printed when you print a variable refering to a sympy
object is the string that was give to it when it was created; that
string does not have to be the same as the variable that you assign it
to:
>>> r, t, d = symbols('rate time short_life')
>>> d = r*t; d
rate*time
>>> r=80; t=2; d # we haven't changed d, only r and t
rate*time
>>> d=r*t; d # now d is using the current values of r and t
160
Maybe this is not what you're looking for (as it was already explained by others), but this is my solution to substitute several values at once.
def GlobalSubs(exprNames, varNames, values=[]):
if ( len(values) == 0 ): # Get the values from the
for varName in varNames: # variables when not defined
values.append( eval(varName) ) # as argument.
# End for.
# End if.
for exprName in exprNames: # Create a temp copy
expr = eval(exprName) # of each expression
for i in range(len(varNames)): # and substitute
expr = expr.subs(varNames[i], values[i]) # each variable.
# End for.
yield expr # Return each expression.
# End for.
It works even for matrices!
>>> x, y, h, k = symbols('x, y, h, k')
>>> A = Matrix([[ x, -h],
... [ h, x]])
>>> B = Matrix([[ y, k],
... [-k, y]])
>>> x = 2; y = 4; h = 1; k = 3
>>> A, B = GlobalSubs(['A', 'B'], ['x', 'h', 'y', 'k'])
>>> A
Matrix([
[2, -1],
[1, 2]])
>>> B
Matrix([
[ 4, 3],
[-3, 4]])
But don't try to make a module with this. It won't work. This will only work when the expressions, the variables and the function are defined into the same file, so everything is global for the function and it can access them.

Categories

Resources