How to calculate 2x + 4 = 10 using sympy? - python

How to calculate 2x + 4 = 10 using Sympy? Is it even possible?
It does not run on Sympy gamma but it runs on Wolframalpha and Cymath. Is it normal or is there some built-in library that should be used with this type of equation?

To represent it,
>>> from sympy.abc import x
>>> from sympy import S, Eq, solve
>>> eq = Eq(2*x + 4, 10)
>>> pprint(eq)
2*x + 4 = 10
To solve it:
>>> solve(eq)
[3]
To interpret input:
>>> s = '2*x + 4 = 10'
>>> eq = Eq(*map(S, s.split('=')))

Related

How to use sympy to convert all standalone integers in an expression that aren't exponents to 1

Is there a way to use sympy to find/replace all standalone integers (that aren't exponents) to 1.
For example, converting the following:
F(x) = (2/x^2) + (3/x^3) + 4
To:
F(x) = (1/x^2) + (1/x^3) + 1
I've searched extensively on stackoverflow for sympy expression.match/replace/find solutions, and have tried using a Wildcard symbol to find and replace all numbers in the expression but I keep running into the issue of matching and replacing the exponents (2 and 3 in this example) as well as they are also considered numbers.
Is there a simple (pythonic) way to achieve the above?
Thanks!
setdefault used with replace is a nice way to go. The single expression below has 3 steps:
mask off powers and record
change Rationals to 1 (to handle integers in numer or denom)
restore powers
>>> from sympy.abc import x
>>> from sympy import Dummy
>>> eq = (2/x**2) + (3/x**3) + 4 + 1/x/8
>>> reps = {}
>>> eq = eq.replace(lambda x: x.is_Pow, lambda x: reps.setdefault(x, Dummy())
).replace(lambda x: x.is_Rational, lambda x: 1
).xreplace({v:k for k,v in reps.items()})
1 + 1/x + 1/x**2 + 1/x**3
You can write a function that will recurse into your expression. For any expression expr, expr.args will give you the components of that expression. expr.is_constant() will tell you if it's a constant. expr.is_Pow will tell you if it's an exponential expression, so you can choose not to drill down into these expressions.
import sympy
def get_constants(expr):
c = set()
for x in expr.args:
if x.is_constant(): c |= {x}
if not x.is_Pow:
c |= get_constants(x)
return c
Now, you can get all the constants in said expression, and replace each of these constants using expr.replace().
def replace_constants(expr, repl):
for const in get_constants(expr):
expr = expr.replace(const, repl)
return expr
With your example expression, we get:
x = sympy.symbols('x')
F = 2/x**2 + 3/x**3 + 4
G = replace_constants(F, 1)
print(F) # 4 + 2/x**2 + 3/x**3
print(G) # 1 + x**(-2) + x**(-3)

SymPy cannot evaluate dot product of *metamorphosed* vectors

I am working with SymPy vectors:
from sympy import *
from sympy.vector import *
N = CoordSys3D('N')
x = symbols('x')
v = x * N.i + x**2 * N.j
vf=factor(v)
vf1=vf.as_independent(Vector)[1]
type(vf1)
# sympy.core.add.Add
I need to calculate dot(vf1,vf1). But SymPy does not evaluate the dot product:
ss = dot(vf1,vf1)
ss
# 1 + 2*Dot(N.i, N.j*x) + Dot(N.j*x, N.j*x)
I suspect, this is because vf1 has been metamorphosed into another type, i.e. sympy.core.add.Add).
Is there a way to make SymPy evaluate ss? Is there a way to cast vf1 as a sympy.vector...?
EDIT
I have written a function that does the dot product. But I need to do this the SymPy way, so I don't have to re-implement my own version of every function in sympy.vector.
Yes, the as_independent does not respect the class of Add or Mul that it is dealing with and only uses Mul/Add (instead of VectorMul/VectorAdd in your case). This can be fixed with a transform:
>>> from sympy.core.rules import Transform
>>> T = Transform(lambda x: (VectorMul if x.is_Mul else VectorAdd)(*x.args),
... lambda x: x.is_Add or x.is_Mul and any(isinstance(i,BaseVector)
... for i in x.args))
>>> vf1.xreplace(T)
N.i + x*N.j
>>> dot(_,_)
x**2 + 1

Sympy evalf doesn't work with 1 variable subs() in 2 variable expression

For a college project in python using Sympy, i need to evaluate the output of a 2 var symbolic function after partial substitution, eg:
f = (x-1)/sqrt((x-10)^2+(y-10)^2) / x = 1 => f = 0
If i use an 1 var func, it works fine:
>>> from sympy import *
>>> x = symbols('x')
>>> F = 1-x
>>> F.evalf(subs={x: 1})
0.e-125
But in the case of a 2 var function, subs doesn't seem to do the substitution right:
>>> from sympy import *
>>> x,y = symbols('x y')
>>> F = (x-1)/sqrt((x-10)**2+(y-10)**2)
>>> F.evalf(subs={x: 1})
(x - 1.0)*((x - 10.0)**2 + (y - 10.0)**2)**(-0.5)
I expected F = 0 since x = 1
I'm not a sympy expert but I found a counter example when the value of y makes the expression non-zero:
>>> F.evalf(subs={x:1,y:float("nan")})
nan
when y is nan, the result is not zero. So it's not possible to simplify the expression not knowing the value of y (note: sympy happily evaluates F.evalf(subs={x:1,y:oo}) to 0 even if the result should be nan as well)
As mentioned above if y = nan creates a math exception, and so the substitution never happens.
But i found out if i just use subs then i get what i want:
>>> F.subs(x,1)
0
now if i explicitly substitute y = nan only then i get the nan answer
>>> F.subs(y,nan)
nan
Im guessing evalf is just checking for more exceptions before it evaluates the substitution.

set output in sympy for 2**3 * 2**4 = 2**7 instead of 128

I would like to set the output in sympy for expression 2**3 * 2**4 = to 2**7 instead of 128. Is there an easy way?
This 'works' , tho may not be what you really want
>>> from sympy import *
>>> x = Symbol('2')
>>> x
2
>>> x**3 * x**7
2**10
>>> z = x**3 * x**7
>>> z
2**10
>>> str(z)
'2**10'
>>> eval(str(z))
1024
added note (using suggestion by #if.... )
>>> two = Symbol('2', positive=True, integer=True)
>>> z = two**3 * two**7
>>> z
2**10
# a little cleaner perhaps than eval(str(z))
# but requiring you to remember the name `two`
>>> z.subs(two, 2)
1024
addition also 'works'
>>> two**3 + two**7
2**7 + 2**3
>>> ((two**3 + two**7)).subs(two,two)
2**7 + 2**3
>>> ((two**3 + two**7)).subs(two, 2)
136
Not really; you're asking to alter the default display of integers to be something outside the standard set of choices. Regardless of the implementation details, this will boil down to you writing a function that accepts an integer and produces the exponent form you want to see, as a character string.

how to combine exponents? (x**a)**b => x**(a*b)?

how to simplify exponents in equations in sympy
from sympy import symbols
a,b,c,d,e,f=symbols('abcdef')
j=(a**b**5)**(b**10)
print j
(a**(b**5))**(b**10) #ans even after using expand simplify
# desired output
a**(b**15)
and if it is not possible with sympy which module should i import in python?
edit
even if i define 'b' as real,and also all other symbols
b=symbols('b',real=True)
not getting simplified exponents
it simplifies only if exponents are constants
a=symbols('a',real=True)
b=symbols('b',real=True)
(a**5)**10
a**50 #simplifies only if exp are numbers
(a**b**5)**b**10
(a**(b**5))**b**10 #no simplification
(xm)n = xmn is true only if m, n are real.
>>> import math
>>> x = math.e
>>> m = 2j*math.pi
>>> (x**m)**m # (e^(2πi))^(2πi) = 1^(2πi) = 1
(1.0000000000000016+0j)
>>> x**(m*m) # e^(2πi×2πi) = e^(-4π²) ≠ 1
(7.157165835186074e-18-0j)
AFAIK, sympy supports complex numbers, so I believe this simplification should not be done unless you can prove b is real.
Edit: It is also false if x is not positive.
>>> x = -2
>>> m = 2
>>> n = 0.5
>>> (x**m)**n
2.0
>>> x**(m*n)
-2.0
Edit(by gnibbler): Here is the original example with Kenny's restrictions applied
>>> from sympy import symbols
>>> a,b=symbols('ab', real=True, positive=True)
>>> j=(a**b**5)**(b**10)
>>> print j
a**(b**15)
a,b,c=symbols('abc',real=True,positive=True)
(a**b**5)**b**10
a**(b**15)#ans
This may be related to this bug.

Categories