Reputation: 429
I wrote the following code in python3 (with the intention to compute then draw nullclines of a 2-D dynamic system):
import sympy as sm
x1, x2 = sm.symbols('x1 x2')
x = [x1, x2]
sys = sm.Matrix([(x1 - sm.log(x2))*(x2-x1*x1),
x2**2 - 4])
solutions = list(map(lambda dx: sm.solve(sm.Eq(dx, 0)), sys))
print(solutions)
What I see is
[[{x1: -sqrt(x2)}, {x1: sqrt(x2)}, {x1: log(x2)}], [-2, 2]]
This [-2,2] gives me a big problem, as I want to draw the solutions next. Since I want to work with sys
whether or not each element contains both variables. I'd like to iterate over the dictionaries and plot sm.Eq(list(solutions[i][j].keys())[0], list(solutions[i][j].values())[0])
but I can't guarantee a dictionary like this
I saw that if I add + x1 - sm.log(sm.exp(x1))
to sys[1]
it will give me the consistent dictionary form, but is there a way for me to force sys
' element to contain both in a more elegant way? I don't want to look in each element for both coordinates and if one isn't present to add the redundant expression to it
Upvotes: 2
Views: 209
Reputation:
The argument dict=True
does that. With sm.solve(sm.Eq(dx, 0), dict=True)
the output of your code is
[[{x1: -sqrt(x2)}, {x1: sqrt(x2)}, {x1: log(x2)}], [{x2: -2}, {x2: 2}]]
That said, I'm not sure that you win anything versus using simply plot_implicit
directly on the equations in sys
. Consider that the different solutions you get will have different domains of definition, as the curves turn around or go sideways (parabolas, etc). Going to be a headache to plot all those pieces.
Here is how it works with plot_implicit
import sympy as sm
x1, x2 = sm.symbols('x1 x2')
eqs = [(x1 - sm.log(x2))*(x2-x1*x1), x2**2 - 4]
window = [(x1, -3, 3), (x2, -3, 3)]
plots = [plot_implicit(eq, *window, show=False) for eq in eqs]
combined_plots = plots[0]
for k in range(1, len(plots)):
combined_plots.extend(plots[k])
combined_plots.show()
Upvotes: 3