I'm trying to convert a symbolic expression to an array in python.
For example, I have this symbolic expression:
import sympy as sp
import numpy as np
A,B = sp.symbols("A B")
G = 3*A**2*B - 2*A*B + A**2
What I want is to convert this to an array looking as follows:
[3*A**2*B,-2*A*B,A**2]
I know how to do this in Matlab, but I need to do it in Python as well.
What I've tried:
I've converted the symbolic expression to a polynomial, which allowed me to collect the coefficients.
C = G.as_poly().coeffs()
This gets me halfway there:
C = [3,-2,1]
But I want to have at least a similar list for all the variables.
Does anyone have an idea?
You can use as_ordered_terms to get an ordered list of all the terms:
G.as_ordered_terms()
gives
[3*A**2*B, A**2, -2*A*B]
Alternatively, you can use args to get all the top-level arguments of the object.
G.args
This will give a tuple:
(A**2, -2*A*B, 3*A**2*B)
Related
I am trying to implement a function using a Sympy expression with multiple parameters. For example, I used the following code:
import sympy
a = sympy.symbols("a")
ad = sympy.symbols("ad")
x = sympy.symbols("x")
c = sympy.symbols("c")
f = (ad*a)*c + x
func = sympy.lambdify((a,ad,x,c),f)
And what I would like to evaluate is the following:
func(M_A,M_B,0,1)
When I use two matrices M_A and M_B, the function performs just an element-wise multiplication, but I need it to be a matrix multiplication for the objects a and ad. I do know that it is possible to do so when I define the variables using MatrixSymbol instead of symbols, but this is not possible in my case as I have implemented a scenario which uses diagonal matrices where element-wise or matrix multiplication would not make a difference. Further, it is also possible to do something like this with normal symbols
x_vars = [symbols("x"+i) for i in range(1,4)]
trans_mat = np.random.random([3,3])
y_vars = trans_mat.dot(x_vars)
which just does not seem to work when I am using MatrixSymbol.
So, I was thinking if I could just compute the expression and perform all the manipulations using the regular symbols and at the end replace all the multiplication operators with numpy.matmul. Please let me know if this is possible somehow, or any other suggestion which can help is also welcome.
Thanks!
Doing help(func) we can see the code produced by lambdify:
Help on function _lambdifygenerated:
_lambdifygenerated(a, ad, x, c)
Created with lambdify. Signature:
func(a, ad, x, c)
Expression:
a*ad*c + x
Source code:
def _lambdifygenerated(a, ad, x, c):
return a*ad*c + x
That's a straightforward translation to python/numpy. Sounds like you want (a#ad)*c+x.
I'm trying to use the following function of QuTip library:
coherent_dm(N=10, alpha = c, offset=0, method='operator')
It's output is a matrix and it's input is a complex number "c", however I want to get the matrices for a list of multiple "c" numbers, but if I define "c" as:
t = np.linspace(0,2*np.pi,100)
c = 2*np.exp(-t*1j) + 0.1*10*(1 - np.exp(-t*1j))
And run the code it gives me "dimension mismatch" error. In this case I tried to run a list of a 100 complex numbers as input "c" expecting an output of a 100 matrices. Any ideas on how to solve this problem would be appreciated.
coherent_dm returns a qutip.Qobj instance. This is a specialized object that fulfills the __array__ interface, but is not actually a numpy array. Internally, it appears to contain a sparse matrix. That means that you can not readily make coherent_dm return more than one matrix at a time, or even concatenate the results of multiple calls into a single array.
Your best bet is therefore probably to use a list comprehension:
result = [coherent_dm(N=10, alpha=i, offset=0, method='operator') for i in c]
I am trying to pass image1 in my code when i copy and paste this as text it looks like this ∑(i=1,n)(a+m*x*(i)-y*(i))^2.
but it does not work.
following is my code which is working with a different syntax:
from sympy import symbols,sympify,solve,Eq,Symbol
from sympy import symbols,Eq,sympify,summation
expr = **('summation((m * x*(i) + a - y*(i))^2, (i, 0, n))')**
Eq1 = Eq(sympify(expr))
print(Eq1)
values = {2001,10,2,3,5}
arr_symbols = list(Eq1.free_symbols)
print(arr_symbols)
Method1(arr_symbols,values,expr)
def Method1(arr_symbols,Values,expr):
from sympy import symbols, Eq, solve, pprint, integrate, sympify
z = symbols('z')
Formula = Eq(sympify(expr),z)
print(Formula)
index = 0
for i in Values:
Formula = Formula.subs(arr_symbols[index],i)
index+=1
print(solve(Formula))
but what i want to do is to use ∑(i=1,n)(a+m*x*(i)-y*(i))^2 and ask sympy to convert it for me.
SymPy can represent this equation, but it can only parse Python. You might be able to write extensions to its parser to handle this sort of thing (see https://docs.sympy.org/latest/modules/parsing.html). It should be possible in principle, although it might not be straightforward. I would only recommend doing this the syntax of your expressions is already very close to Python. If it isn't (and it looks like it isn't), it would be better to a real parsing library like ANTLR to build up a grammar for your expressions. You can then use that to parse into SymPy (see for example how the sympy.parsing.latex module is written).
I don't know if there is pre-existing library in Python that handles your types of expressions. I'm not aware of any. At best you might be able to find a grammar that someone has already written, so you don't have to write it yourself.
If you are, given a, m and values for x and y and are trying to compute the sum of the squares of the residuals, then it would be better to write a function that does that or do something like this:
>>> x = [1, 2, 3]
>>> y = [4, 7, 11]
>>> a = 2
>>> m = 5
>>> sum((a + m*xi - yi)**2 for xi, yi in zip(x, y))
70
it cannot be done.
we have to pass latex code.
I want to extract dependency information between the variables in a string that contains a Python 3 NumPy expression. For example:
import numpy as np
a = np.array([10, 20, 30])
b = np.array([10, 20, 30])
c = np.array([10, 20, 30])
d = 100
# The expression string will only contain numbers, arrays, and `NumPy` functions.
expression = 'b[1:3] = a[0:3:2] + np.sum(c[:]) + d'
deps = extract_dependencies(expression)
Then, the result should be:
deps: {
'b[0]': [],
'b[1]': ['a[0]', 'c[0]', 'c[1]', 'c[2]', 'd']
'b[2]': ['a[2]', 'c[0]', 'c[1]', 'c[2]', 'd']
}
My problem is that I can't figure out how to implement extract_dependencies().
This is easy to solve if all the symbols in the expression are either not arrays or arrays with single-element indexing (e.g., foo, bar[0], baz[2]). It can be done by using either regular expressions or some basic text parsing.
However, if the variables are arrays, things get more complicated. For basic operations, one could use regular expressions to find the variables in the expression string, and then extract and map array indices accordingly. For example it is easy to extract and match the indices of the expression a[0:2] = b[1:3]. Things become more tricky when functions are used as part of the expression string because they are essentially "black boxes". You can't account for all possible function signatures, behaviors, and return values unless you hard code every single one of them.
I was wondering if this could be solved using some clever use of Python's eval, exec, or ast trees.
Any ideas? :)
Thank you.
PS: The expression string is eventually evaluated using the asteval library. Hence, a solution that utilizes asteval will get extra points! :)
I (main author of asteval) think this is not possible, at least not in general.
As you say, even with your expression
expression = 'b[1:3] = a[0:3:2] + np.sum(c[:]) + d'
you need to know:
how strides work: That [x:y:n] slice means (x, x+n, x+2n, ...) up to y-1. OK, that's not too hard for 1D arrays.
what np.sum() does -- that it returns a value with arrays summed along an axis. What happens if c = np.array([[5, 4], [9,- 2]])? The expression works, but the element-by-element dependencies change. Which means that you have to know what np.sum does in detail.
what d is. What happens if it changes from a scalar to is a 2-element array?
Basically, you're asking to figure out element-by-element dependencies lexically. You have to know what a, c, d, and np.sum are to know what the resulting dependencies will be. You cannot tell from the words alone.
Python views slices and function calls as operations to be done at run time. So it parses this expression then expects that whatever is held by d can be added to the result of whatever np.sum returns with the function argument returned by evaluating an "all-null slice" on whatever c is. If those two things cannot be added together, it will fail at run time.
I am trying to solve a "very simple" problem. Not so simple in Python. Given a large matrix A and another smaller matrix B I want to substitute certain elements of A with B.
In Matlab is would look like this:
Given A, row_coord = [1,5,6] col_coord = [2,4], and a matrix B of size(3X2), A[row_coord, col_coord] = B
In Python I tried to use product(row_coord, col_coord) from the itertools to generate the set of all indexes that need to be accessible in A but it does not work. All examples on submatrix substitution refer to block-wise row_coord = col_coord examples. Nothing concrete except for the http://comments.gmane.org/gmane.comp.python.numeric.general/11912 seems to relate to the problem that I am facing and the code in the link does not work.
Note: I know that I can implement what I need via the double for-loop, but on my data such a loop adds 9 secs to the run of one iteration and I am looking for a faster way to implement this.
Any help will be greatly appreciated.
Assuming you're using numpy arrays then (in the case where your B is a scalar) the following code should work to assign the chosen elements to the value of B.
itertools.product will create all of the coordinate pairs which we then convert into a numpy array and use in indexing your original array:
import numpy as np
from itertools import product
A = np.zeros([20,20])
col_coord = [0,1,3]
row_coord = [1,2]
coords = np.array(list(product(row_coord, col_coord)))
B = 1
A[coords[:,0], coords[:,1]] = B
I used this excellent answer by unutbu to work out how to do the indexing.