This may not be a question, just an observation, but is sympy supposed to work this way.
I have a two complicated expression, A and E, and I am trying to find out if they are equivalent. If I simplify one, say E, and use Eq(A,E) it does not return True, but the two separated with "==". If would have expected that sympy would be smart enough to work out they are equal. Eq(simplify(A),E) returns True. Here is the code ...
from sympy import *
B = symbols('B')
C = symbols('C')
F = symbols('F')
G = symbols('G')
H = symbols('H')
A = (B - C)*(G*(B + C) - (B - C - F)*H)**2
D = 2*(B**2+B*F-C**2)**2
E = A/D
ED=simplify(E*D)
print("E*D= {0}").format(str(ED))
print("A = {0}").format(str(A))
print("0 = {0}").format(str(simplify(A-ED)))
print("T = {0}").format(Eq(A,ED))
print("T = {0}").format(Eq(simplify(A),ED))
and the output
E*D= (B - C)*(G*(B + C) + H*(-B + C + F))**2
A = (B - C)*(G*(B + C) - H*(B - C - F))**2
0 = 0
T = (B - C)*(G*(B + C) - H*(B - C - F))**2 == (B - C)*(G*(B + C) + H*(-B + C + F))**2
T = True
Note the -H versus +H in the last expression.
Equality does not do any simplification and two objects are identical only if they are structurally (not mathematically) zero. Proving mathematical equality (in general) is not a simple problem so if they aren't identical (as in this case) SymPy doesn't even begin chasing the "equality rabbit" to its hole :-). This is the expected behavior. If you want to let SymPy try some simplification on its own, try using the equals method:
>>> A.equals(simplify(E*D))
True
Related
I am trying to simplify expressions containing exponents on SymPy. However, the desired results are not returned.
This is what I have tried thus far:
import sympy as sp
a, b, c, d = sp.symbols("a b c d", real = True, positive = True)
exp1 = (a - b + c)**3
exp2 = (a - b + c)**3 - ((a - b + c)**2 - d)**sp.Rational(3, 2)
Exp1 = exp1**sp.Rational(1, 3)
print(Exp1)
Output[1]: ((a - b + c)**3)**(1/3)
The expected result for Exp1 was a - b + c since I assumsed all the variales are positive.
Exp2 = exp2.subs(d, 0)
print(Exp2)
Output[2]: (a - b + c)**3 - (a - b + c)**2*Abs(a - b + c)
The expected result for Exp2 was 0.
Is there a way of forcing Sympy to return the fully simplified expressions or results when the base of the exponent has more than one variable.
The following answers did not help solve my problem:
Answer 1
Answer 2
Answer 3
Use the force option:
>>> powdenest(Exp1, force=True)
a - b + c
You can read the docstring for cbrt to get an explanation of how the principle root concept keeps cbrt(x**3) from being returned as x.
Pardon my ignorance, but I'm very new to coding in python. I have a pretty simple function; it just needs to make a calculation based on b's relative location to a and c:
a = 6
b = 3
c = 2
def function(a, b, c):
if ((a >= b) & (b >= c)):
return b - c
elif ((a <= b) & (b >= c)):
return a - c
else:
return 0
t = function(a, b, c)
print(t)
When I run it with simple numbers like above, it gives me the right answer no matter what I make b. (In this case 1)
But When I run it with a,b, and c as Numpy Arrays, it only returns b - c across the entire "t" array.
It's not too much different, but here's what I'm using for the array version:
def function(a, b, c):
if ((a >= b) & (b >= c)).any():
return b - c
elif ((a <= b) & (b >= c)).any():
return a - c
else:
return 0
t = function(a, b, c[i>1])
print(t)
(The [i>1] is there because there is a variable amount of array input, and another function will be used for when [i = 0])
I've also tried this:
t = np.where(((prev2 >= Head_ELV) & (Head_ELV >= Bottom_ELV)).any, Head_ELV - Bottom_ELV, 0)
but ran into the same result.
Would a while-loop work better?
I don't think you need looping here as the problem can be solved using array operations. You could try the below, assuming the arrays are of the same length.
# import numpy to be able to work with arrays
import numpy as np
def function(a, b, c):
# declare array t with only zeros
t = np.zeros_like(a)
# declare filters
mask_1 = (a >= b) * (b >= c)
mask_2 = (a <= b) * (b >= c)
# modifying t based on the filters above
t[mask_1] = (b - c)[mask_1]
t[mask_2] = (a - c)[mask_2]
return t
# example 2d arrays
a = np.array([[1800,5], [5,5]])
b = np.array([[3416,2], [3,4]])
c = np.array([[1714,2], [3,4]])
# run function
function(a, b, c)
I have searched a lot through the questions and, honestly, couldn't find something that applies to my case.
I am working with the SymPy library in order to perform large calculations and it has been working tremendously well. However, my recent results have became too convoluted. So, I began to implement more definitions and symbols in order to perform several substitutions and narrow down the expression to a more feasible form. I have been able to do this, 'manually', for a lot of terms, which are too much particular to allow any kind of automation. But, there is a specific family of contributions in my expression that could be greatly simplified if I could run this simple substitution rule.
Let A be my complete expression. In this image, the dots represent already simplified terms and the summation represents the general setup behind my query. My goal is to rewrite it like this.
The T_k are just denoting generic terms; in fact, they are composed by several literal Symbols. In my code, the rho letter is associated to a single variable, Symbol-type. So, with that said, my problem could be exemplified as follows:
# sympy symbols: rho, a, b, c, d
# sympy functions: f, g, h
A = (a * b) * f(rho) + (c * d) * g(rho) + (a * c * d * b) * h(rho)
# apply some clever substitution method ???
A.subs(???)
>>> f(a * b) * rho + g(c * d) * rho + h(a * c * d * b) * rho
Of course, in the above example, I could do it "by hand". The problem lies when there is a lot of terms like that. I tried to achieve my goal using lambda expressions, but couldn't make it work. The idea was: for any generic lambda t, I could try to input the map {t * f(rho) : f(t) * rho}, for each symbolic function (# f, g, h), but not caring about the particular companion terms.
I tried defining, for instance, genSub_f = lambda t: A.subs(t * f(rho), f(t) * rho). However, in order to make the substitution, I would have to call genSub_f(a * b), which works, but it's not practicable, since one would have to detain prior knowledge about the combinations of symbols that are going along with f(rho). How to proceed?
You could use Wild symbols for this however there are a few ways to obtain your desired output.
One complication is it seems you don't want to apply the substitution
f(a*b)*rho -> f(a*b*rho). There are a few ways to achieve this, however first I'll give an answer that does result in this substitution:
from sympy import *
rho, a, b, c, d = symbols("rho, a, b, c, d")
f, g, h = symbols("f, g, h", cls=Function)
A = (a * b) * f(rho) + (c * d) * g(rho) + (a * c * d * b) * h(rho)
w1, w2 = symbols("w1, w2", cls=Wild)
for ff in [f, g, h]:
A = A.replace(w1*ff(w2), w2*ff(w1))
print(A) # f(a*b*rho) + g(c*d*rho) + h(a*b*c*d*rho)
So what about excluding the substitution rho*f(a*b) -> f(a*b*rho)?
One approach is to exclude rho from the Wild matches by defining your Wild symbol w1 like so (we also have to exclude the substitution 1*f(...) -> ...*f(1)). This results in your desired output:
A = (a * b) * f(rho) + (c * d) * g(rho) + (a * c * d * b) * h(rho)
w1 = Wild("w1", exclude=[rho, 1]) # exclude unwanted substitutions
w2 = Wild("w2")
for ff in [f, g, h]:
A = A.replace(w1*ff(w2), w2*ff(w1))
print(A) # rho*f(a*b) + rho*g(c*d) + rho*h(a*b*c*d)
However, another way to achieve your desired output is to use match instead of replace. This way you won't have to explicitly exclude rho (with this approach the replacement is done manually so there's no need to worry about avoiding 'double' application of the replacement rules):
A = (a * b) * f(rho) + (c * d) * g(rho) + (a * c * d * b) * h(rho)
w1, w2, w3 = symbols("w1, w2, w3", cls=Wild)
for ff in [f, g, h]:
m = A.match(w1*ff(w2) + w3)
if m:
A = m[w2]*ff(m[w1]) + m[w3] # manual replacement
print(A) # rho*f(a*b) + rho*g(c*d) + rho*h(a*b*c*d)
I have a function named f = 0.5/(z-3). I would like to know what would the coefficients p and q be if f was written in the following form: q/(1-p*z) but unfortunately sympy match function returns None. Am I doing something wrong? or what is the right way of doing something like this?
Here is the code:
z = symbols('z')
p, q = Wild('p'), Wild('q')
print (0.5/(z-3)).match(q/(1-p*z))
EDIT:
My expected answer is: q=-1/6 and p = 1/3
One way of course is
p, q = symbols('p q')
f = 0.5/(z-3)
print solve(f - q/(1-p*z), p, q,rational=True)
But I don't know how to do that in pattern matching, or if it's capable of doing something like this.
Thanks in Advance =)
If you start by converting to linear form,
1 / (2*z - 6) == q / (1 - p*z)
# multiply both sides
# by (2*z - 6) * (1 - p*z)
1 - p*z == q * (2*z - 6)
then
from sympy import Eq, solve, symbols, Wild
z = symbols("z")
p,q = symbols("p q", cls=Wild)
solve(Eq(1 - p*z, q*(2*z - 6)), (p,q))
gives
{p_: 1/3, q_: -1/6}
as expected.
Edit: I found a slightly different approach:
solve(Eq(f, g)) is equivalent to solve(f - g) (implicitly ==0)
We can reduce f - g like simplify(f - g), but by default it doesn't do anything because the resulting equation is more than 1.7 times longer than the original (default value for ratio argument).
If we specify a higher ratio, like simplify(f - g, ratio=5), we get
>>> simplify(1/(2*z-6) - q/(1-p*z), ratio=5)
(z*p_ + 2*q_*(z - 3) - 1)/(2*(z - 3)*(z*p_ - 1))
This is now in a form the solver will deal with:
>>> solve(_, (p,q))
{p_: 1/3, q_: -1/6}
SymPy's pattern matcher only does minimal algebraic manipulation to match things. It doesn't match in this case because there is no 1 in the denominator. It would be better to match against a/(b + c*z) and manipulate a, b, and c into the p and q. solve can show you the exact formula:
In [7]: solve(Eq(a/(b + c*z), q/(1 - p*z)), (q, p))
Out[7]:
⎧ -c a⎫
⎨p: ───, q: ─⎬
⎩ b b⎭
Finally, it's always a good idea to use exclude when constructing Wild object, like Wild('a', exclude=[z]). Otherwise you can get unexpected behavior like
In [11]: a, b = Wild('a'), Wild('b')
In [12]: S(2).match(a + b*z)
Out[12]:
⎧ 2⎫
⎨a: 0, b: ─⎬
⎩ z⎭
which is technically correct, but probably not what you want.
Basicly, what I need for the program to do is to act a as simple fraction calculator (for addition, subtraction, multiplication and division) for the a single line of input, for example:
-input: 1/7 + 3/5
-output: 26/35
My initial code:
import sys
def euclid(numA, numB):
while numB != 0:
numRem = numA % numB
numA = numB
numB = numRem
return numA
for wejscie in sys.stdin:
wyjscie = wejscie.split(' ')
a, b = [int(x) for x in wyjscie[0].split("/")]
c, d = [int(x) for x in wyjscie[2].split("/")]
if wyjscie[1] == '+':
licz = a * d + b * c
mian= b * d
nwd = euclid(licz, mian)
konA = licz/nwd
konB = mian/nwd
wynik = str(konA) + '/' + str(konB)
print(wynik)
elif wyjscie[1] == '-':
licz= a * d - b * c
mian= b * d
nwd = euclid(licz, mian)
konA = licz/nwd
konB = mian/nwd
wynik = str(konA) + '/' + str(konB)
print(wynik)
elif wyjscie[1] == '*':
licz= a * c
mian= b * d
nwd = euclid(licz, mian)
konA = licz/nwd
konB = mian/nwd
wynik = str(konA) + '/' + str(konB)
print(wynik)
else:
licz= a * d
mian= b * c
nwd = euclid(licz, mian)
konA = licz/nwd
konB = mian/nwd
wynik = str(konA) + '/' + str(konB)
print(wynik)
Which I reduced to:
import sys
def euclid(numA, numB):
while numB != 0:
numRem = numA % numB
numA = numB
numB = numRem
return numA
for wejscie in sys.stdin:
wyjscie = wejscie.split(' ')
a, b = [int(x) for x in wyjscie[0].split("/")]
c, d = [int(x) for x in wyjscie[2].split("/")]
if wyjscie[1] == '+':
print("/".join([str((a * d + b * c)/euclid(a * d + b * c, b * d)),str((b * d)/euclid(a * d + b * c, b * d))]))
elif wyjscie[1] == '-':
print("/".join([str((a * d - b * c)/euclid(a * d - b * c, b * d)),str((b * d)/euclid(a * d - b * c, b * d))]))
elif wyjscie[1] == '*':
print("/".join([str((a * c)/euclid(a * c, b * d)),str((b * d)/euclid(a * c, b * d))]))
else:
print("/".join([str((a * d)/euclid(a * d, b * c)),str((b * c)/euclid(a * d, b * c))]))
Any advice on how to improve this futher is welcome.
Edit: one more thing that I forgot to mention - the code can not make use of any libraries apart from sys.
Probably the biggest improvement you could make would be to use Python (2.6)'s fractions library:
>>> import fractions
>>> fractions.Fraction(1,7) + fractions.Fraction("3/5")
Fraction(26, 35)
I'd create a class containing numerator and denominator fields (both integers) and implementing __add__, __sub__, __mul__, and __div__ methods. Then you can simply use ordinary math functions to combine the instances.
It might be overkill for your purposes, but the code will be a lot cleaner.
In fact, the class-based approach is exactly how the fractions module is implemented. Normally I'd suggest examining the source code of the fractions module to see how it's written, but since this is for homework I'm not sure that would be allowed. It might be worth checking out after the assignment is over, just to see how a full-blown fractional-number type is implemented.
You could factor out the code that reduces the fraction to lowest terms from the individual '+', '-', etc. That should make the code a little cleaner and more compact and readable.
Factoring out euclid into a helper function is a good idea. I'd suggest trying to further break up your code into more helper functions.
One idea is to create four functions (add, subtract, multiply, divide) like this one:
def multiply(val1, val2):
# Unpack the tuples.
numerator1, denominator1 = val1
numerator2, denoninator2 = val2
# Figure out the resulting numerator and denominator here.
# Return the result as a tuple.
return numerator, denominator
Refactor your code to use the helper functions and I think your main code will be cleaner.
You could use memoization on the euclid function which may help speed up depending on the input data. However this will use more memory
You can also use a tuple assignment in euclid
def euclid(numA, numB):
while numB != 0:
numA, numB = numB, numA % numB
return numA
map is faster here
a, b, c, d = map(int, wyjscie[0].split("/")+wyjscie[2].split("/"))
You can also optimize the euclid function . Instead of using Euclid's algorithm you can use Binary GCD.
Two ways to implement the algorithm can be found here, unfortunately the code is in C. Still I don't think is that hard if you translate it to python .