Use the subs method:
import sympy as sy
x = sy.Symbol('x')
a = sy.Matrix([[2*x**2,3+x],[4*x**3,-5*x]])
print(a.subs(dict(x=1)))
# [2, 4]
# [4, -5]
or the evalf method:
print(a.evalf(subs=dict(x=1)))
# [2.0, 4.0]
# [4.0, -5.0]
If you have more than one Symbol to substitute, just add them to the substitution dict. For example,
a.subs(dict(x=1, y=exp(5)))
Note that if you define
x = sy.Symbol('x')
then you are binding the name x
to the object sy.Symbol('x')
. If later on you assign
x = 1
then you are rebinding the name x
to a different object, the int
1. The old Symbol
object still exists, its just the name x
no longer references it. (In Python names (aka variables) simply map to objects).
Meanwhile if you bind a
to a Matrix
:
a = sy.Matrix([[2*x**2,3+x],[4*x**3,-5*x]])
that Matrix
object may use the the Symbol
whose repr
is x
. Note carefully that this x
is not the Python variable, rather it is the Symbol
object itself.
So reassigning x
to 1 has no impact on a
. That is why
eval('a')
does not substitute the new binding for x
. Instead eval('a')
simply looks up the bare name a
in the global namespace, finds that it maps to the Matrix
object and returns that Matrix
.
If you want the Matrix to automatically update when x
is changed, one possible solution would be to subclass Matrix
and define a new property that performs the subs
call for you. For example,
import sympy as sy
import math
class UpdatingMatrix(sy.Matrix):
def __init__(self, *args):
super(UpdatingMatrix, self).__init__(*args)
self._names = set([symbol.name for expr in self.mat
for symbol in expr.free_symbols])
@property
def val(self):
return self.subs({name:eval(name) for name in self._names})
x = sy.Symbol('x')
y = sy.Symbol('y')
a = UpdatingMatrix([[2*x**2,3+x*y],[4*x**3,-5*x]])
x = 100
y = 1
print(a.val)
yields
[ 20000, 103]
[4000000, -500]
Note that you have to use a.val
to see the updated value; I don't see a way to automatically change a
itself when performing an assignment like x = 1
. That might not be desirable anyway, since if that were possible, then a
could not update itself a second time in you were to later assign x = 2
(since a
would no longer depend on x
.) With the solution above, each time you access a.val
, the substitutions are re-applied, so a.val
would return the value of a
with respect to the current values of x
and y
.