I have got the following situation (in Sympy 1.8):
from sympy import *
u = symbols('u') # not necessarily positive
term = sqrt(1/u**2)/sqrt(u**2)
The term renders as
How can I simplify this to 1/u**2, i.e. ?
I have tried many functions from https://docs.sympy.org/latest/tutorial/simplification.html, and some arguments listed in https://docs.sympy.org/latest/modules/simplify/simplify.html but could not get it to work.
The variable needs to be declared as real number:
u=symbols('u', real=True)
Then the term is auto-simplified.
(I suggested a corresponding Sympy documentation change.)
Related
I'm trying to compose two functions and I get a bizzare result
'''
#!/usr/bin/python
from sympy import *
init_printing(use_unicode=True)
x= symbols('x')
f = x/(x+1);
g = x/(x+2);
print(compose(f,g))
This shows : x/((x + 1)*(x + 2))
Should be x/(2x+2)
I don't get it. Does anyone has an idea?
Thanks
Despite being available in the top-level sympy namespace under the plain name compose, sympy.compose doesn't actually do general function composition.
sympy.compose is actually sympy.polys.polytools.compose. It's actually a function for polynomial composition. When you try to compose x/(x+1) and x/(x+2), it ends up interpreting these inputs as multivariate polynomials in 3 variables, x, 1/(x+1), and 1/(x+2), and the results are total nonsense.
Given a symbol s, which ultimately will be an Array, I want to define the following expression
A = Array([-s[1]/2, s[0]/2])
but I'd like A to be evaluated only when I compute some other expressions containing it, because s changes over time. I tried
A = UnevaluatedExpr(Array([-s[1]/2,s[0]/2]))
but I got the error TypeError: 'Symbol' object is not subscriptable, which make me think that some evaluation is performed on s.
Thanks for your patience, I'm just learning Sympy and I'm used to Maxima where this kind of construct is straightforward. To be more precise, with Maxima the full working code I'm trying to translate into Sympy is (in Maxima everything is a symbol, colon is the assignment operator, ev forces evaluation with custom values, the dot before diff is the vector scalar product):
A: [-s[2],s[1]]/2; /* define A in terms of subscripted symbols */
P1: [x1,y1];
P2: [x2,y2];
segment: P1+t*(P2-P1); /* --> [t*(x2-x1)+x1,t*(y2-y1)+y1] */
factor(integrate(ev(A,s=segment).diff(segment,t),t,0,1)); /* integrates the scalar product of A evaluated over segment and the derivative of segment */
Follow up
Thanks to Oscar answer I was able to come up with a working Sympy translation of the above Maxima code (improvements are welcomed!):
from sympy import *
def dotprod(*vectors): # scalar product, is there a built in better way?
return sum(Mul(*x) for x in zip(*vectors))
s = IndexedBase('s')
A = Array([-s[1]/2,s[0]/2])
t,x1,y1,x2,y2 = symbols('t x1 y1 x2 y2')
P1 = Array([x1,y1])
P2 = Array([x2,y2])
segment = P1 + t * (P2-P1)
dotprod(A.subs(s,segment),segment.diff(t)).integrate((t,0,1)).factor()
Apart from the IndexedBase magic the structure of the code in Maxima and Sympy is very similar.
I'm not sure I understand what you want. It's possible that your problem is better approached in a different way rather than using Array. In any case a direct answer to your question is that you can use IndexedBase to make a subscriptable symbol:
In [1]: s = IndexedBase('s')
In [2]: A = Array([-s[1]/2, s[0]/2])
In [3]: A
Out[3]:
⎡-s[1] s[0]⎤
⎢────── ────⎥
⎣ 2 2 ⎦
I consider following matrices:
M1 = Matrix([[1/7,2/7],[3/7,4/7]])
M2 = Matrix([[1,2],[3,4]])/7
which are evidently identical, but when I determine their determinant I obtain different results:
print(M1.det())
print(M2.det())
giving the following results:
-0.0408163265306122
-2/49
I would like the first result to be expressed as a rational and not as a floating point.
This is an example of one of the gochas and pitfalls from SymPy's documentation. My answer will basically reiterate what is said there. I highly recommend going through it.
When you type 1/7, the Python interpreter changes it into a float before SymPy has a chance to identify it as a rational number. In order for SymPy to evaluate it before Python does, you need to use some other method. You have already shown one of those other methods with M2: divide a SymPy object by 7 instead of a Python int by 7. Here are a few other ways:
from sympy import *
M = Matrix([[Rational(1, 7),Rational(2, 7)],[Rational(3, 7),Rational(4, 7)]]) # create a Rational object
print(det(M))
M = Matrix([[S(1)/7,S(2)/7],[S(3)/7,S(4)/7]]) # divide a SymPy Integer by 7
print(det(M))
M = Matrix([[S("1/7"),S("2/7")],[S("3/7"),S("4/7")]]) # let SymPy interpret it
print(det(M))
M = Matrix([[1,2],[3,4]])/7 # divide a SymPy Matrix by 7
print(det(M))
M = S("Matrix([[1/7,2/7],[3/7,4/7]])") # throw the whole thing into SymPy
print(det(M))
All of the above will give rational determinants. There are probably many more ways to make SymPy identify a rational number.
Using sympy how do I keep fractions separate from variables
Mul(Fraction(3,5), Pow(K, Integer(2)))
2
3⋅K
────
5
to
3 2
─ K
5
I know this simplified version is not too bad, but when i have really big equations, it gets messy
I'm not very familiar with pretty printing or LaTeX printing but I managed to come up with something. Put UnevaluatedExpr in each of the arguments of Mul:
from sympy import *
from fractions import Fraction
K = symbols("K")
expr1 = Mul(UnevaluatedExpr(Fraction(3,5)), UnevaluatedExpr(Pow(K, Integer(2))))
expr2 = Mul(UnevaluatedExpr(pi/5), UnevaluatedExpr(Pow(K, Integer(2))))
expr3 = ((UnevaluatedExpr(S(1)*3123456789/512345679) * UnevaluatedExpr(Pow(K, Integer(2)))))
pprint(expr1)
pprint(expr2)
pprint(expr3)
Produces:
2
3/5⋅K
π 2
─⋅K
5
1041152263 2
──────────⋅K
170781893
I couldn't find a way to make it print a stacked fraction for the slashed fraction 3/5. Longer fractions seem to work though. If you are printing in LaTeX however, the documentation suggests something like latex(expr1, fold_frac_powers=False) to correct this.
Too bad I couldn't find an elegant solution like putting init_printing(div_stack_symbols=False) at the top of the document.
To elaborate on Maelstrom's Answer, you need to do 2 things to make this work like you want:
Create the separate fraction you want as its own expression.
Prevent the numerator or denominator from being modified when the expression is combined with other expressions.
What Maelstrom showed will work, but it's much more complicated than what's actually needed. Here's a much cleaner solution:
from sympy import *
K = symbols("K")
# Step 1: make the fraction
# This seems to be a weird workaround to prevent fractions from being broken
# apart. See the note after this code block.
lh_frac = UnevaluatedExpr(3) / 5
# Step 2: prevent the fraction from being modified
# Creating a new multiplication expression will normally modify the involved
# expressions as sympy sees fit. Setting evaluate to False prevents that.
expr = Mul(lh_frac , Pow(K, 2), evaluate=False)
pprint(expr)
gives:
3 2
-*K
5
Important Note:
Doing lh_frac = UnevaluatedExpr(3) / 5 is not how fractions involving 2 literal numbers should typically be created. Normally, you would do:
lh_frac = Rational(3, 5)
as shown in the sympy docs. However, that gives undesirable output for our use case right now:
2
3*K
----
5
This outcome is surprising to me; setting evaluate to False inside Mul should be sufficient to do what we want. I have an open question about this.
In doing symbolic math with Sympy I encountered the following problem:
from sympy import *
txx, tyx, txy, tyy, tp, tn = symbols('t_xx t_yx t_xy t_yy t_p t_n', complex=True)
#define a complex symbol
tp = txx-I*tyx
Abs(tp), arg(tp)
#will just return |txx-i*tyx|, arg(txx-i*tyx)
However, the absolute value and argument returned is not in the form of sqrt(txx**2+tyx**2), atan(tyx/txx) as you would expect for complex numbers.
I also tried
simplify(Abs(tp).expand(complex=True))
#returns |Retxx-i*Retyx+i*Imtxx+Imtxy|, but no further simplification
which worked again for complex numbers but not the symbol of complex symbol defined here. Is this not implemented yet or am I not doing it right?
If you define your symbol list with the attribute real=True, then you will get the correct expression for Abs(tp). With your sympy symbols given as complex, then Abs() does not know the real and imaginary parts of these pieces txx, tyx, etc so the output of Abs() can not give you what you expected.