I have a MATLAB code and I'm trying to convert it to Python. I used the eval() to evaluate my symbolic arrays in MATLAB. But I couldn't find how to solve this in Python. Here's a simple example:
MATLAB Code:
%values to be assigned
input = [10 20 30; ...
15 25 20; ...
20 20 10]
%decision variables
x_1_1 = input(1)
x_2_1 = input(2)
x_3_1 = input(3)
x_1_2 = input(4)
x_2_2 = input(5)
x_3_2 = input(6)
x_1_3 = input(7)
x_2_3 = input(8)
x_3_3 = input(9)
%symbolic arrray
symbolic_eq = sym('x_',[3,3])
%any math operation
m = [-1 0 0 ; ...
0 -1 0 ; ...
0 1 -1 ]
% new equations for symbolic array
multp_eq = m*symbolic_eq
% get results
results = eval(multp_eq)
Python code:
from sympy import *
import numpy as np
#values to be assigned
input = np.array([[10, 20, 30, 15, 25, 20, 20, 20, 10]])
#decision variables
x_1_1 = input[0]
x_2_1 = input[1]
x_3_1 = input[2]
x_1_2 = input[3]
x_2_2 = input[4]
x_3_2 = input[5]
x_1_3 = input[6]
x_2_3 = input[7]
x_3_3 = input[8]
#symbolic array (edited)
symbolic_eq = symarray('x', (4, 4))
symbolic_eq = np.array(symbolic_eq [1:, 1:])
#any math operation
m = np.array([[-1, 0, 0 ],
[ 0, -1, 0 ],
[ 0, 1, -1 ]])
#new equations for symbolic array
multp_eq = m*symbolic_eq
# get results
results = eval(multp_eq)
Also, for both MATLAB and Python, how can I define my input() variables easily?
The main problem with your code was you needed to do the substitution (with the method .subs()
before you could evaluate your expression. This is done by providing a list tuples containing the variable and its value. Here I build this list in a for loop.
A few extra comments about your code. In general, avoid the commands like from sympy import *
. It fills your namespace for no good reason. Finally, I see no "good" reasons to go to indices starting from 1 rather than 0. I suggest to consider switching to the native indexing, as it often makes the code cleaner.
import sympy as sp
import numpy as np
#values to be assigned
aninput = np.array([[10, 20, 30],
[15, 25, 20],
[20, 20, 10]])
#symbolic array (edited)
symbolic_eq = sp.symarray('x', (4, 4))
symbolic_eq = symbolic_eq [1:, 1:]
thesubs = []
for index, theinput in np.ndenumerate(aninput):
thesubs.append((symbolic_eq[index], aninput[index]))
print(thesubs)
#any math operation
m = sp.Matrix([[-1, 0, 0 ],
[ 0, -1, 0 ],
[ 0, 1, -1 ]])
#new equations for symbolic array
multp_eq = m*symbolic_eq
# get results
results = multp_eq.subs(thesubs)
results
Finally, this code will not run very fast. If you want to do this operation for a large number of input array of values, you should consider using sympy.lambdify
instead of .subs
.
function = sp.lambdify(np.array(symbolic_eq).flatten(), multp_eq, modules="numpy" )
Then you just have to call the function to get the answer:
result = function(*aninput.flatten())
On my machine, and for this simple example, this last line is almost 400 times faster than the one using subs. However, if the size of your imput array can increase, then this solution can run into some limitations (to 256 values if I remember).