Consider the following sympy code:
from sympy import Add
from sympy.abc import x
t1 = 2+2*x
t2 = x
myeq = sp.UnevaluatedExpr(Add(sp.UnevaluatedExpr(t1), sp.UnevaluatedExpr(t2), evaluate=False))
# BUG! Will print: x + 2*x + 2
# Yet it should print: 2+2*x+x
print(myeq)
This code snippet was adapted from this answer. There the terms are simpler, so Add preserved the order. But how can I make Add preserve the order in this case as well?
(Remark: If we change the terms to t1=x and t2=x**2 my approach with using the sp.UnevaluatedExpr works, but the original answer that did not have those terms does not. Alas, for my specific case, not even using sp.UnevaluatedExpr works.)
This is not a bug...
... but more a missing feature. All of it being documented.
Here is what SymPy means by unevaluated.
By unevaluated it is meant that the value inside of it will not
interact with the expressions outside of it to give simplified
outputs.
In your example, the terms 2*x and x were not simplified, as is expected.
Order of input
What you are seeing is SymPy not preserving the order in which you input your terms. This is documented under the expression tree section.
The arguments of the commutative operations Add and Mul are stored in
an arbitrary (but consistent!) order, which is independent of the
order inputted.
This should not be a problem since Add and Mul are commutative.
Although, if for some reason you want to preserve the order of input due to non-commutativity of multiplication, you can do so.
In SymPy, you can create noncommutative Symbols using Symbol('A',
commutative=False), and the order of multiplication for
noncommutative Symbols is kept the same as the input)
As for now, there does not seem to be non-commutative addition.
Related
I want to simplify a sympy expression where the arguments are matrix elements using the function expand_log.
As a simple example let's look at the expression log(exp(x)), which should be simplified to x.
As the tutorial explains, simplifications will only be applied if the required assumptions hold, i.e. in this case, x must be real.
If I have a scalar quantity, I can specify this assumption when creating the variable as shown here.
However, I use a matrix symbol which does not allow specifying assumptions at creation. I instead tried using the new assumptions module:
import sympy as sym
from sympy.assumptions import assuming, Q
x = sym.MatrixSymbol('x',1,2)
expr = sym.log(sym.exp(x[0,0]))
with assuming(Q.real(x[0,0])):
display(sym.expand_log(expr))
The output still is log(exp(x[0, 0])).
So it seems to me that the expand_log function is not aware of the assumption that I specify in the assuming context manager.
Setting force=True yields the desired result but I want to avoid not checking assumptions at all.
Does anyone have an idea how to circumvent this problem?
I have a very complicated function of two variables, let's call them x and y. I want to create a Python program where the user can input two values, a and b, where a is the value of that complicated function of x and y, and b = math.atan(y/x). This program should then output the values of x and y.
I am clueless as to where to start. I have tried to make the function into that of just one variable, then generate many random values for x and pick the closest one, but I have learnt that this is horribly inefficient and produces a result which is only accurate to about 2 significant figures, which is pretty horrible. Is there a better way to do this? Many thanks!
(P.S. I did not reveal the function here due to copyright issues. For the sake of example, you can consider the function
a = 4*math.atan(math.sqrt(math.tan(x)*math.tan(y)/math.tan(x+y)))
where y = x * math.tan(b).)
Edit: After using the approach of the sympy library, it appears as though the program ignores my second equation (the complicated one). I suspect it is too complicated for sympy to handle. Thus, I am asking for another approach which does not utilise sympy.
You could use sympy and import the trigonometric functions from sympy.
from sympy.core.symbol import symbols
from sympy.solvers.solveset import nonlinsolve
from sympy import sqrt, tan, atan
y = symbols('y', real=True)
a,b = 4,5 # user-given values
eq2 = a - 4*atan(sqrt(tan(y/tan(b))*tan(y)/tan((y/tan(b))+y)))
S = nonlinsolve( [eq2], [y] )
print(S)
It'll return you a series of conditions ( ConditionSet object ) for possible adequate results.
If that wasn't clear enough, you can read the docs for nonlinsolve.
Is there any disadvantage of not passing sympy symbols to functions?
def compute(alpha,a): #or def compute(a)
return 3*alpha+a
alpha = sympy.symbols("alpha")
expr = compute(alpha,3)
I don't have to pass alpha to compute() (I assume because it's a global variable), and right now, I think it makes the code better readable when I leave it out.
Is this considered bad design? I suppose this is a general "what to do with global variables in python" question, as has been asked here, but the answers said it would depend on the specific usecase.
I still have to create the alpha symbol before I call that function, it's just not obvious if i do not include it.
In contrast to lists (which the other question is about), SymPy treats symbols (and expressions) as immutable. Moreover, they are uniquely identified by the string you pass to Symbol or symbols. For illustration consider the following:
from sympy import Symbol
print({Symbol("a"), Symbol("a")})
>>> {a}
Therefore declaring a SymPy symbol as a global variable does not pose such a big issue – it’s like globally defining some mathematical constant. For example it cannot happen that some reasonable code using this symbol changes it.¹
So, depending on the context, it can make sense to:
define alpha globally,
pass alpha as a parameter to the function,
define alpha within the function at each call (which is possible, since symbols only depend on the associated string).
Without further context, it’s impossible to say which applies to your situation.
¹ Note that unreasonable code can still do this, e.g.:
from sympy.abc import a
from sympy.abc import a as a_2
a.name = "b"
print(a_2)
>>> b
Defining commonly used Symbols at the top of the file (i.e., globally) is perfectly good practice. As others have pointed out, even if it gets defined again, it won't really matter because two symbols with the same name are considered equal. One important caveat here: if you use assumptions, like real=True, then that does matter. So you should avoid using two symbols with the same name but different assumptions.
In your example, if alpha is always supposed to be the symbol Symbol('alpha'), then it doesn't make sense to have an argument to a function that never changes.
Another way you can do things, by the way, is to not have the function at all, but just use the expression with symbolic variables
alpha, a = symbols('alpha a')
expr = 3*alpha + a
and then use subs when you want to substitute a value
expr.subs({a: 3}) # or expr.subs(a, 3)
Say, I have an equation f(x) = x**2 + 1, I need to find the value of f(2).
Easiest way is to create a function, accept a parameter and return the value.
But the problem is, f(x) is created dynamically and so, a function cannot be written beforehand to get the value.
I am using cvxpy for an optimization value. The equation would look something like below:
x = cvx.Variable()
Si = [(cvx.square(prev[i] + cvx.sqrt(200 - cvx.square(x))) for i in range(3)]
prev is an array of numbers. There will be a Si[0] Si[1] Si[2].
How do i find the value of Si[0] for x=20?
Basically, Is there any way to substitue the said Variable and find the value of equation When using cvxpy ?
Set the value of the variables and then you can obtain the value of the expression, like so:
>>> x.value = 3
>>> Si[0].value
250.281099844341
(although it won't work for x = 20 because then you'd be taking the square root of a negative number).
The general solution to interpreting code on-the-fly in Python is to use the built-in eval() but eval is dangerous with user-supplied input which could do all sorts of nasty to your system.
Fortunately, there are ways to "sandbox" eval using its additional parameters to only give the expression access to known "safe" operations. There is an example of how to limit access of eval to only white-listed operations and specifically deny it access to the built-ins. A quick look at that implementation looks close to correct, but I won't claim it is foolproof.
The sympy.sympify I mentioned in my comment uses eval() inside and carries the same warning.
In parallel to your cvx versions, you can use lambda to define functions on the fly :
f=[lambda x,i=j : (prev[i] + (200 - x*x)**.5)**2 for j in range(3)] #(*)
Then you can evaluate f[0](20), f[1](20), and so on.
(*) the i=j is needed to fit each j in the associated function.
When I try to differentiate a symbol with SymPy I get the following
In : x=Symbol('x')
In : diff(x,x)
Out: 1
When I differentiate the symbol respect to its conjugate the result is
In [55]: diff(x,x.conjugate())
Out[55]: 0
However, when I try to differentiate the conjugate of the symbol SymPy doesn't do it
In : diff(x.conjugate(),x)
Out: Derivative(conjugate(x), x)
This is still correct, but the result should be zero. How can I make SimPy perform the derivative of a conjugate?
I'm not sure about the mathematics if diff(conjugate(x), x) should be zero. The fact that diff(x,x.conjugate()) gives zero has nothing to do with mathematics (and might even be considered a SymPy bug). It gives zero simply because x does not contain conjugate(x) (symbolically), so it sees it as a constant with respect to it. This is probably wrong, since x is not a constant with respect to conjugate(x). The fact that SymPy lets you take derivatives with respect to defined functions is probably a bug, actually. It is supposed to allow things like diff(f(x)**2, f(x)), where f = Function('f') is an undefined function, but for defined functions, it is probably mathematically incorrect (or at least not what you expect).
See http://docs.sympy.org/latest/modules/core.html?highlight=derivative#sympy.core.function.Derivative, particularly the section on derivatives wrt non-Symbols. To paraphrase, taking derivatives with respect to a function is just a notational convenience and does not represent a mathematical chain rule. Rather, something like diff(x, conjugate(x)) should be thought of as something like diff(x.subs(conjugate(x), dummy), dummy).subs(dummy, conjugate(x)).
Regarding conjugate(x).diff(x), this gives an unevaluated derivative because no derivative is defined for conjugate. I'm not sure if any closed-form answer is possible here anyway. Probably this is the most useful thing that SymPy could return. I can't find any good answers anywhere as to what a reasonable answer for this should be (you should ask on math SE to get a better answer about it).