from sympy import *
x,y,s = symbols('xys')
z = (1 - 2*x*x)
w = (1 + 2*x*x)
q = 2*x*x*2*y*y
sub = {2*x*x: s}
print w.subs(sub)
print z.subs(sub)
print q
print q.subs(sub)
The output I get:
1 + s
1 - 2*x**2
4*x**2*y**2
4*x**2*y**2
The output I expect:
1 + s
1 - s
4*x**2*y**2
2*y**2*s
Do I do something wrong?
Sympy seems to be inconsistent in what it matches. For instance, changing the sign on the matching substitution expression allows z to be matched with. I would consider adding this example to this issue. I would also try the Sympy mailing list. Remember, this project isn't even to version number 1.0 yet so things aren't going to be perfect just yet with it (or probably ever as with any software).
Related
I have a relatively simple complex sympy expression which one can easily read the coefficients off of the variables. However coeff function does not appear to be working correctly
import sympy as sp
a,b = sp.symbols("a, b")
expr = 2640.0*a - 4.5*(1 + 1j)*(264.0*a + 264.0*b) - 4.5*(+1 - 1j)*(264.0*a + 264.0*b)
print(expr.coeff(a))
> 2640.00000000000
print(sp.simplify(expr))
> 264.0*a - 2376.0*b
I would expect the output of expr.coeff(a) to return 264.0 but it clearly isnt? Any help is appreciated.
coeff gives coefficients of the expression at the top level. If you use expand before looking for the coefficient then you will get the mathematical (not expression-dependent-literal) coefficient. If you know the expression is linear in the symbol of interest, you could also differentiate once:
>>> expr.diff(a)
264.000000000000
>>> expr.expand().coeff(a)
264.000000000000
Poly automatically expands expressions and allows queries for monomials, too:
>>> Poly(expr).coeff_monomial(a)
264.000000000000
Your first expression has 2640.0 as the coefficient of a. As you can see, the coefficient becomes zero only after simplifying it. Indeed, if you print the coefficient after simplifying the expression, you get 264.0
import sympy as sp
a,b = sp.symbols("a, b")
expr = 2640.0*a - 4.5*(1 + 1j)*(264.0*a + 264.0*b) - 4.5*(+1 - 1j)*(264.0*a + 264.0*b)
print(expr.coeff(a))
# 2640.00000000000
print(sp.simplify(expr))
# 264.0*a - 2376.0*b
print(sp.simplify(expr).coeff(a)) # <--- Simplified expression
# 264.000000000000
Good day,
I am trying to write a function for the following equation:
Where B and N are given and I am solving for A.
I was reading up and it seemed like sympy was the way to go so I started to declare the known variables, but when it came to the sigma notation with the factorial, I had no idea of how to approach it since A is an unknown.
Here is what I came up with:
from sympy import Eq, var, solve
from math import *
A = var('A')
channels = raw_input("Enter the number of channels: ")
#GOS = raw_input("Enter GOS: ")
Sigma = A
for i in range(0,channels+1):
Sigma += (A**i / factorial(i))
# equation = Eq((A**channels / factorial(channels)) / Sigma)
# print solve(equation)
which gives me the error TypeError: cannot concatenate 'str' and 'int' objects
This makes sense to me, but my lack of knowledge with sympy makes me unable to figure out how to fix it.
EDIT: Looking around a bit more, I edited my code to this:
from sympy import *
A = symbols('A')
channels = raw_input("Enter the number of channels: ")
GOS = raw_input("Enter GOS: ")
Sigma = summation(A**i / factorial(i), (i, 0,channels))
print Sigma
# equation = Eq((A**channels / factorial(channels)) / Sigma)
Now I get NameError: name 'i' is not defined
Thanks in advance.
First of all, the error ( name 'i' not defined) is because you havent defined it. so you need to give an initial value for i.
secondly, I have tried to make your program run. got an error free solution with this code:
from sympy import *
A = symbols('A')
channels = raw_input("Enter the number of channels: ")
GOS = raw_input("Enter GOS: ")
# note that I convert the string 'channel' to an int
# convert to float if channel could also be a floating number
channels = int(channels)
Sigma = A
for i in range(0,channels+1):
Sigma += (A**i / factorial(i))
print Sigma
The result,
inputs: channels = 3, GOS = 1
output: A**3/6 + A**2/2 + 2*A + 1
EDIT: Out of interest I started looking further into your problem (also because I could realize this question would not stop just by a datatype issue).
The Solve function has 2 inputs, the equation and the symbol to calculate.
it solves the equation == 0. so the variable B has to be subtracted from the equation. (I supposed the input GOS is the B variable in the function)
equation = (A**channels / factorial(channels)) / Sigma
print(solve(equation-int(GOS), A))
running the code with the lines above (add them under the code) gave these outputs:
A**3/6 + A**2/2 + 2*A + 1
[-2 - sqrt(2), -2 + sqrt(2)]
I must notice that if the GOS does not intersect the function it gives large results with additional parameter I (capital i, might indicate imaginary i).
I hoped this helped solving your problem.
To describe a similar sum as at the top of the page, when I use the asmeurer's recommendation summation, I get the error -TypeError: 'Symbol' object is not subscriptable." What could be the possible cause of this error? I imported the libraries below. There is a continuation of the code, but I did not add it to avoid confusion.
import sympy as sympy
from sympy import *
from sympy import summation, symbols
class FQ():
def integrate(self):
for k in range(1, self.Nt):
i = symbols('i', integer=True)
self.Sigma = summation(self.u[i+1][j], (i, 0, k - 1))
#second attempt
def integrate(self, alpha, Nt, Nx, L):
for k in range(1, self.Nt):
for j in range(1, self.Nx-1):
#define sum
for i in range(1, self.Nt):
Sigma = summation(u[i+1][j], (i, 0, k-1))
You can also perform the summation in SymPy using the summation function
i = symbols('i')
summation(A**i/factorial(i), (i, 0, N)
Another note: you are starting with Sigma = A, meaning your final result is A + ΣA^i/i! instead of just ΣA^i/i! (you can see in the output from #Petrus1904's answer there is a 2*A instead of A). If you want to use a loop to compute a summation you should initialize the variable to 0.
I am working with some long equations but not really complex, and I wanted to use sympy to simplify and "factorize" them. But I have encountered a few problems. Here is a list of some minimal examples:
Problem 1: symmetry
from sympy import *
from __future__ import division
a = symbols('a')
b = symbols('b')
expr = 1/12*b + 1
expr.subs(1/12*b, a)
expr.subs(b*1/12, a)
The first line gives the expected result (ie. a+1) while in the second one there is no substitution.
Problem 2: factorized expressions
Some parts of the expression are factorized and when I expand the expression they get simplified, thus making the substitution impossible. For example
(((x+1)**2-x).expand()).subs(x**2+2*x, y+1)
will give x^2+x+1 and what I am looking for is y+2-x.
Question
Is there a way to solve these problems ? Or maybe I should use another symbolic mathematical tool ? Any suggestions are welcomed.
There is a major gotcha in SymPy, which is that, because of the way Python works, number/number gives a floating point (or does integer division if you use Python 2 and don't from __future__ import division).
In the first case and in your original expression, Python evaluates 1/12*b from left to right. 1/12 is evaluated by Python to give 0.08333333333333333, which is then multiplied by b. In the second case, b*1 is evaluated as b. Then b/12 is evaluated by SymPy (because b is a SymPy object), to give Rational(1, 12)*b.
Due to the inexact nature of floating point numbers, SymPy does not see the float 0.08333333333333333 as equal to the rational 1/12.
There is some more discussion of this issue here. As a workaround, you should avoid direct integer/integer without wrapping it somehow, so that SymPy can create a rational. The following will all create a rational:
b/12
Rational(1, 12)*b
S(1)/12*b
For (((x+1)**2-x).expand()).subs(x**2+2*x, y+1) the issue is that x**2 + 2*x does not appear exactly in the expression, which is x**2 + x + 1. SymPy generally only replaces things that it sees exactly.
It seems you don't mind adding and subtracting an x to make the replacement work. So I would suggest doing instead (((x+1)**2-x).expand()).subs(x**2, y+1 - 2*x). By only substituting a single term (x**2), the substitution will always work, and the 2*x will cancel out to leave whatever x term remains (in this case, -x).
Here's a possible solution to your problems:
from sympy import *
a = symbols('a')
b = symbols('b')
expr = 1 / 12 * b + 1
print(expr.subs((1 / 12) * b, a))
print(expr.subs(b * (1 / 12), a))
x = symbols('x')
y = symbols('y')
expr = ((x + 1)**2 - x).expand()
print(expr.subs(x**2 + x, y - x + 1))
Regarding problem 1, note that 1/12*b and b*1/12 are not the same thing in sympy. The first is a floating number mutliplied by a symbol, whereas the second is an exact symbolic expression (you can check it out by a simple print statement). Since expr contains 1/12*b, it is not surprising that the second subs does not work.
Regarding problem 2, the subs rule you provide is ambiguous. In particular the substitution rule implies that equation x**2+2*x==y+1. However, this equation has many interpretations, e.g,
x**2 == y + 1 - 2*x (this is the one you consider),
x**2 + x == y + 1 - x,
x == (y + 1 - x**2)/2,
For this reason, I consider sympy refusing to perform a substitution is actually a correct approach.
If it is the first interpretation you want, it is better to explicitly provide it in the subs rule, i.e.,
(((x+1)**2-x).expand()).subs(x**2, -2*x + y + 1)
-x + y + 2
I have the following expression :
p/l
which I extract from a matrix. I later define p and l with following code
from sympy.abc import c,G,M,J,l,u,v,w
us = (2*G*M/c**2)
a = (J/(M*c))
p = (u**2 + a**2*cos(v))
l = (u**2 - us*u + a**2)
I want to substitute the expression p/l and describe it instead with all of the expressions above. I tried doing the following. If g is a sympy.Matrix object and the first element is defined as p/l, then
g[0,0].subs([(p,u**2 + a**2*cos(v)),(l,u**2 - us*u + a**2)])
should do the trick, yet instead I still get p/l, the expression remains unchanged. If I simply type p/l in an ipython session, I get the output
(J**2*cos(v)/(M**2*c**2) + u**2)/(-2*G*M*u/c**2 + J**2/(M**2*c**2) + u**2)
Which is what I desire. (Well almost, I would prefer applying simplify on it first as such : (J**2*cos(v) + M**2*c**2*u**2)/(-2*G*M**3*u + J**2 + M**2*c**2*u**2) ).
You are substituting expressions with identical expressions, the result of the substitution is thus identical to the original expression.
Make sure not to confuse SymPy symbols and Python variables:
# Python variable: `p` stores an addition object:
p = (u**2 + a**2*cos(v))
# SymPy symbol, it's just a symbol, no expressions:
p = Symbol('p')
# express symbol-expression relation in some way, like:
{p: (u**2 + a**2*cos(v))}
Here is my equation:
import math
import pandas as pd
import numpy as np
ha = 8.14
k = 0.0187
Do = 0.1738
Di = 0.0138
L = 3
F = 20
Ta = 293
Ts = 113
pi = 3.14159265
Q = (pi*(Ta-Ts))/(((1/ha*Do))+(1/(2*k))*math.log(Do/Di)) * L
h = (Q*3600)/F
Basically, I want the outputs for when F = np.arange(20,100,10)
is this possible?
I tried
a = np.arange(20,100,10)
F = 20 + i
for i in range(a):
print h
not sure why this doesn't work?
any ideas?
When you use numpy you should try to not use explicit loops, as numpy's main virtue is to execute implicitly the loops with the speed of a compiled language.
To come to our problem, it is simply
F = np.arange(20,100,10)
h = Q*3600/F
print h
where I use the array F just as a normal Python variable, and it's up to numpy magics to recognize the need for a loop.
Remember: you can use numpy's arrays in your expressions just like you would use a scalar and, as far as your usage is a sensible one, Python will compute an array-zed result.
Side Note use np.pi instead of 3.14159...
You need to define a function that takes in parameters. then you can call in that function based on a set of parameters. Bellow I show you an example with a sin(x) function because I'm sure you can figure out hwo to adapt it to your needs
import math
points = np.arange(20, 100, 10)
def sine(x, a=1.0, b=2.0):
return a*math.sin(b*x)
for i in points:
print(sine(i,b=i), end=" ")
-0.8509193596391765 0.9978032744219705 -0.8012247906768953 -0.6501275235748956 -0.2620839590180966 -0.7736233386803075 -0.5444763096196569 0.8272184413093554
this will call your sin function with various parameter b and will calculate it in different points x
The way you're doing it should always print out exactly the same number. Since you've already calculated everything. You don't have a function anywhere, and by putting it all in a for loop won't automagically change anything.
Unless it's some for of pandas magic in interpreter I don't know about. (In that case sorry, I'm not a big user of pandas)
Currently your code is giving Q and h a specific value, and never changes that value again.
Explanation:
In the code below
Q = 4
W = Q
print(Q)
print(W)
you are saying: name Q refers to value 4 and name W refers to the current value of Q(that is 4, regardless whether Q changes later on or not).
If you type Q = 10, W will not change:
Q = 10
print(Q)
print(W)
Therefore you need functions that will be calculated each time you call them:
def Q():
return (pi*(Ta-Ts))/(((1/ha*Do))+(1/(2*k))*math.log(Do/Di)) * L
def h():
return (Q()*3600)/F
for i in np.arange(20,100,10):
F = 20 + i
print h()
The above explanation is a bit oversimplified, so you might want to check this link.