How to call SymPy Python function linear_eq_to_matrix

#1

I’m using SymPy in Julia to solve a system of equations and I would like to be able to call the SymPy function linear_eq_to_matrix as documented on this page: http://docs.sympy.org/latest/modules/solvers/solveset.html

I have a Python script containing the following code that uses the function:

``````#!/usr/local/bin/python
from sympy import *
x, y, z = symbols('x y z')
eqns = [x + 2*y + 3*z - 1, 3*x + y + z + 6, 2*x + 4*y + 9*z - 2]
print("eqns = ", eqns)
A, b = linear_eq_to_matrix(eqns, [x, y, z])
print("A = ", A)
print("b = ", b)
``````

When I run this, I get the expected output:

``````eqns =  [x + 2*y + 3*z - 1, 3*x + y + z + 6, 2*x + 4*y + 9*z - 2]
A =  Matrix([[1, 2, 3], [3, 1, 1], [2, 4, 9]])
b =  Matrix([[1], [-6], [2]])
``````

Now, when I try to do the same thing in Julia, I have tried the following input file:

``````#!/usr/local/bin/julia
using SymPy
@vars x y z
eqns = ([x + 2*y + 3*z - 1, 3*x + y + z + 6, 2*x + 4*y + 9*z - 2])
println("eqns = ", eqns)
A, b = linear_eq_to_matrix(eqns, ([x, y, z]))
println("A = ", A)
println("b = ", b)
``````

But this fails with the following output/error:

``````eqns = SymPy.Sym[x + 2*y + 3*z - 1, 3*x + y + z + 6, 2*x + 4*y + 9*z - 2]
ERROR: LoadError: UndefVarError: linear_eq_to_matrix not defined
Stacktrace:
[2] include(::String) at ./sysimg.jl:14
[3] process_options(::Base.JLOptions) at ./client.jl:305
[4] _start() at ./client.jl:371
``````

I have tried to figure out how to use PyCall or something similar to directly call this function but with no success. I have confirmed that I am calling/using the same versions of Python/SymPy in Julia so that’s not the issue. I have also confirmed that the SymPy function “solveset” which is documented on the link I provided above does work as expected in both Julia and Python, so it seems like Julia should be able to call “linear_eq_to_matrix” somehow, even if it’s a bit clunky.

Can someone please show me how to do this? Thanks.

#2

Apparently that function isn’t explicitly wrapped by SymPy, but you can call the Python function directly by:

``````A, b = SymPy.sympy["linear_eq_to_matrix"](eqns, x, y, z)
``````

#3

I just noticed that using either [“linear_eq_to_matrix”] or [:linear_eq_to_matrix] will work.

Would it be possible for you to comment on why either syntax is acceptable? And help me know if there are certain times I would need to use one or the other?

If I need to start a new topic for this though that’s fine too.

Thanks so much for your help!

#4

I am pretty sure the difference is negligible. You can always use `@time` before the function to see which one takes slightly longer. And by negligible, I mean you should only worry about it if you use it in a humongous loop in which case you should be far more concerned with SymPy’s slowness, because it is written in Python, than with the difference between the 2 PyCall syntaxes.

#5

Either syntax works. As explained in the PyCall README, doing `foo[:bar]` or `foo["bar"]` are both analogous to `foo.bar` in Python, but `foo[:bar]` will try to convert the result to a native Julia type if possible while `foo["bar"]` will always return a `PyObject`. Whenever I have something that I know returns a function/method object, which will get left as a `PyObject` anyway, I tend to use `foo["bar"]` to avoid the type-introspection step, but in most cases it won’t make a noticeable performance difference.

#6

Excellent. Thanks for the quick and very helpful feedback guys. Code on!

#7

If speed isn’t an issue, I have a PR adding a `sympy_str` macro, so that you can call this as `sympy"linear_eq_to_matrix"(...)`. The advantage is this will check beyond the `sympy` module to try and resolve the call, which is needed for some calls.