2

I have any Symbols:

In [1]: from sympy import *

In [2]: import numpy as np

In [3]: x=Symbol('x')

And I created any matrix:

In [4]: a=Matrix([[2*x**2,3+x],[4*x**3,-5*x]])

In [5]: a
Out[5]:
  Matrix([
          [2*x**2, x + 3],
          [4*x**3,  -5*x]])

if x=1 I want to evaluate the matrix a. I use the command eval:

In [6]: x=1

In [7]: eval('a')

Out[7]:
  Matrix([
          [2*x**2, x + 3],
          [4*x**3,  -5*x]]) 

I want to obtain this ouput:

Out[7]:
  Matrix([
          [2, 4],
          [4, -5]]) 

What's wrong with what I am doing?

Bach
  • 6,145
  • 7
  • 36
  • 61
  • 1
    possible duplicate of [How to substitute symbol for matrix using symPy and numPy](http://stackoverflow.com/questions/16904924/how-to-substitute-symbol-for-matrix-using-sympy-and-numpy) – aruisdante May 27 '14 at 16:51

1 Answers1

0

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.

unutbu
  • 842,883
  • 184
  • 1,785
  • 1,677
  • Thank u for your answer. but i have other problem: – user3680668 May 27 '14 at 17:14
  • Thank u for your answer. But i have other problem: If what happen if you have two or more variables that you define like symbol and have assign one valor. For example y = sy.Symbol('y') an y=exp(5) and you have a = sy.Matrix([[2*x**2,3+x*y],[4*x**3+y,-5*x]]). How you do for obtain the new result. – user3680668 May 27 '14 at 17:26
  • You can add more substitutions to the `dict`: `a.subs(dict(x=1, y=exp(5)))`. – unutbu May 27 '14 at 17:30
  • if you before defined the variable x=1 and y=exp(5) you can write a.subs(dict(x,y)) – user3680668 May 27 '14 at 17:34
  • No, that's not true. `dict(x, y)` will raise a `TypeError: dict expected at most 1 arguments, got 2`. If `x = 1` has already been assigned, then you could use `a.subs({'x':x})`, however. The dict key is the string `repr` of the `Symbol`, the dict value is the new value to be substituted. – unutbu May 27 '14 at 17:37
  • But i need to separete the variable's value like x=1 and y=exp(5) of the matrix a, I want the matrix a change the automatic form only change x and y. How do it?? – user3680668 May 27 '14 at 17:42