Skip to content

Latest commit

 

History

History
320 lines (225 loc) · 9.71 KB

README.md

File metadata and controls

320 lines (225 loc) · 9.71 KB

Symbolic Computation

{:.no_toc}

* TOC {:toc}

Top

Questions to David Rotermund

pip install sympy

Overview tutorials

Basic Operations
Printing
Simplification
Calculus
Solvers
Matrices
Basics Contains a description of operations for the basic modules. Subcategories include: absolute basics, manipulation, assumptions, functions, simplification, calculus, solvers, and some other subcategories.
Code Generation Contains a description of methods for the generation of compilable and executable code.
Logic Contains method details for the logic and sets modules.
Matrices Discusses methods for the matrices, tensor and vector modules.
Number Theory Documents methods for the Number theory module.
Physics Contains documentation for Physics methods.
Utilities Contains docstrings for methods of several utility modules. Subcategories include: Interactive, Parsing, Printing, Testing, Utilities.
Topics Contains method docstrings for several modules. Subcategories include : Plotting, Polynomials, Geometry, Category Theory, Cryptography, Differential, Holonomic, Lie Algebra, and Stats.
Assumptions
Calculus
Combinatorics
Functions
Integrals
Series
Simplify
Solvers
abc
Algebras
Concrete
Core
Discrete
Numerical Evaluation
Numeric Computation
Term Rewriting
import sympy

x, y = sympy.symbols("x y")

expr = sympy.cos(x) + 1
z = expr.subs(x, y**2)
print(z) # -> cos(y**2) + 1
import sympy

x, y = sympy.symbols("x y")

y = sympy.diff(sympy.sin(x) * sympy.exp(x), x)
print(y) # -> exp(x)*sin(x) + exp(x)*cos(x)
import sympy

x, y = sympy.symbols("x y")

y = sympy.integrate(sympy.cos(x), x)
print(y)  # -> sin(x)
import sympy

x, y, z = sympy.symbols("x y z")
y = sympy.cos(x)
z = y.series(x, 0, 8) # around x = 0 , up order 7

print(z)  # -> 1 - x**2/2 + x**4/24 - x**6/720 + O(x**8)
import sympy

x, y, z = sympy.symbols("x y z")
y = sympy.simplify(sympy.sin(x) ** 2 + sympy.cos(x) ** 2)

print(y)  # -> 1
solveset(equation, variable=None, domain=S.Complexes)

Recall from the gotchas section of this tutorial that symbolic equations in SymPy are not represented by = or ==, but by Eq.

import sympy

x, y, z = sympy.symbols("x y z")

z = sympy.Eq(x, y)

Output:

$$x=y$$

import sympy

x, y, z = sympy.symbols("x y z")

y = sympy.Eq(x**2 - x, 0)
z = sympy.solveset(y, x)
print(z) # -> {0, 1}
import sympy

# Undefined functions
f = sympy.symbols("f", cls=sympy.Function)

x = sympy.symbols("x")


diffeq = sympy.Eq(f(x).diff(x, x) - 2 * f(x).diff(x) + f(x), sympy.sin(x))

print(diffeq)  # -> Eq(f(x) - 2*Derivative(f(x), x) + Derivative(f(x), (x, 2)), sin(x))

result = sympy.dsolve(diffeq, f(x))
print(result)  # -> Eq(f(x), (C1 + C2*x)*exp(x) + cos(x)/2)
import sympy

x, y = sympy.symbols("x y")

expr = sympy.cos(x) + 1
print(expr)  # -> cos(x) + 1
expr = expr.subs(x, 0.333 * sympy.pi)
print(expr)  # -> cos(0.333*pi) + 1
print(sympy.N(expr)) # -> 1.50090662536071

Plot your function

import sympy
import inspect
import numpy as np
import matplotlib.pyplot as plt

f = sympy.symbols("f", cls=sympy.Function)
x = sympy.symbols("x")
diffeq = sympy.Eq(f(x).diff(x, x) - 2 * f(x).diff(x) + f(x), sympy.sin(x))
result = sympy.dsolve(diffeq, f(x))

symbols = list(result.rhs.free_symbols)

f = sympy.lambdify(symbols, result.rhs, "numpy")


print("The arguments of the result:")
print(inspect.getfullargspec(f).args)
print("The source code behind f:")
print(inspect.getsource(f))

np_x = np.linspace(0, 2 * np.pi, 100)

plt.plot(f(x=np_x, C1=1.0, C2=1.0))
plt.xlabel("x")
plt.ylabel("f(x)")
plt.show()

image1

Assumptions about the symbols

C1 = sympy.symbols('C1', positive=True)
real=True The symbol represents a real number.
positive=True The symbol represents a positive number.
negative=True The symbol represents a negative number.
integer=True The symbol represents an integer.
prime=True The symbol represents a prime number.
odd=True The symbol represents an odd number.
even=True The symbol represents an even number.

Limiting the range of a symbol

import sympy

x = sympy.symbols("x")
sympy.solve([x**2 - 1, x >= 0.5, x <= 3], x)

Example: Gain function of the quadratic integrate and fire neuron

import sympy
import numpy as np
import matplotlib.pyplot as plt

tau_value: float = 10e-3  # s
a0_value: float = 0.1e3  # V^-1
uc_value: float = -55.0e-3  # V
urest_value: float = -70.0e-3  # V
r_value: float = 10e6  # Ohm
uthr_value: float = -40e-3  # V

u = sympy.symbols("u", cls=sympy.Function, real=True)
urest, uc, uthr = sympy.symbols("urest uc uthr", real=True)
t, tau, a0, r, i = sympy.symbols("t tau a0 r i", real=True, positive=True)

c0, c1, c2 = sympy.symbols("c0 c1 c2", real=True)

diffeq_rhs = (a0 * (u(t) - urest) * (u(t) - uc) + r * i) / tau
diffeq_rhs = sympy.expand(diffeq_rhs)
diffeq_rhs = sympy.collect(diffeq_rhs, u(t))

c0_coeffs = diffeq_rhs.coeff(u(t), 0)
c1_coeffs = diffeq_rhs.coeff(u(t), 1)
c2_coeffs = diffeq_rhs.coeff(u(t), 2)

diffeq_rhs = diffeq_rhs.subs(c0_coeffs, c0)
diffeq_rhs = diffeq_rhs.subs(c1_coeffs, c1)
diffeq_rhs = diffeq_rhs.subs(c2_coeffs, c2)

diffeq = sympy.Eq(u(t).diff(t), diffeq_rhs)

solved_diffeq = sympy.dsolve(diffeq, u(t), ics={u(0): urest}, simplify=False)
solved_diffeq = solved_diffeq.subs(u(t), uthr)
solved_diffeq = sympy.simplify(solved_diffeq)

solved2_diffeq = sympy.solve(solved_diffeq, t)[0]

solved2_diffeq = solved2_diffeq.subs(c0, c0_coeffs)
solved2_diffeq = solved2_diffeq.subs(c1, c1_coeffs)
solved2_diffeq = solved2_diffeq.subs(c2, c2_coeffs)
solved2_diffeq = sympy.simplify(solved2_diffeq)

solved2_diffeq = solved2_diffeq.subs(tau, tau_value)
solved2_diffeq = solved2_diffeq.subs(a0, a0_value)
solved2_diffeq = solved2_diffeq.subs(uc, uc_value)
solved2_diffeq = solved2_diffeq.subs(urest, urest_value)
solved2_diffeq = solved2_diffeq.subs(r, r_value)
solved2_diffeq = solved2_diffeq.subs(uthr, uthr_value)
solved2_diffeq = sympy.simplify(solved2_diffeq)


print("The final function")
print(solved2_diffeq)
print()


thr_func = sympy.lambdify(i, solved2_diffeq, "numpy")

i = 4 * 1e-9 * np.arange(0, 1000, dtype=np.complex128) / 1000
z = thr_func(i)
z = 1.0 / z
z[z < 0] = 0
z = z.astype(dtype=np.float32)

plt.plot(i * 1e9, z)
plt.xlabel("Input [nA]")
plt.ylabel("Rate [Hz]")
plt.show()

image_qiaf.png