Il est souvent difficile de comprendre intuitivement à quoi ressemblera le résultat même s'il est obtenu par une fonction. Par conséquent, dessiner un graphique est la première étape de l'analyse et de la réflexion. Pour le mémo japonais de matplotlib, voir ici. L'intrigue de sympy est ici. Officiel J'ai eu du mal en le regardant.
import
import sympy as sym
sym.init_printing()
Pi = sym.S.Pi #Pi
E = sym.S.Exp1 #Bas du logarithme naturel
I = sym.S.ImaginaryUnit #Unité imaginaire
#Définition des variables à utiliser(Toute une lettre minuscule est un symbole)
(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z) = sym.symbols('a b c d e f g h i j k l m n o p q r s t u v w x y z')
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
from mpl_toolkits.mplot3d import Axes3D
La liste des couleurs a été pré-générée par un autre programme afin qu'il s'agisse d'un anneau avec une luminosité constante dans l'espace colorimétrique L * a * b *. Conçu avec une marge de sécurité pour le contraste plutôt que l'éclat des couleurs, la faiblesse des couleurs n'est pas prise en compte. Chaque liste se compose de 37 chaînes HEX. Le nombre 37 a été sélectionné car il s'agit du nombre premier le plus proche de 36, qui est le nombre qui avance de 360 degrés d'un tour de 10 degrés. (S'il est de 37, il avance de 9,73 degrés par un.) Puisqu'il s'agit d'un nombre premier, peu importe comment vous choisissez la couleur initiale et le nombre d'étapes (il doit s'agir d'une racine primitive), ce sera toujours un ** groupe de patrouilles ** qui passe par 37 couleurs une par une. Il s'agit d'une correspondance intuitive dont la phase avance d'environ 10 pas * 10 degrés. Autant que possible, la même couleur n'apparaît pas et le cycle est long.
def generator_p(start): #Un générateur pour générer des couleurs dans l'ordre si un argument est spécifié, sinon.
prime = 37 #Nombre de listes(Puisqu'il s'agit d'un nombre premier, ce sera toujours la période maximale, peu importe ce que vous spécifiez pour primitive.)
primitive = 8 #La source(La teinte par étape est primitive* 37/Aller à 360 degrés)
g0 = start #Source de départ(Ce qui est réellement retourné est g0* primitive)
while True:
val = yield g0
if val: #Si un argument est passé au générateur, il sera réinitialisé comme source de départ.
g0 = val
g0 += primitive
if g0 >= prime: #Prenez le surplus
g0 -= prime
gen_hexnum = generator_p(0) #Mettez la couleur initiale dans l'argument
gen_hexnum.__next__() #Initialisation du générateur
def hexNum(num, type): #Liste des couleurs
#Couleur de base(Une couleur calme qui peut être utilisée universellement sur fond blanc)
color_basic = ['#9c1954', '#9e1a46', '#9d1e38', '#9a252a', '#962d1c', '#8f350d', '#873c00',
'#7d4300', '#734900', '#674f00', '#5b5300', '#4d5700', '#3e5b00', '#2b5d00',
'#0f6009', '#00611c', '#00632b', '#00643a', '#006449', '#006558', '#006567',
'#006575', '#006482', '#00648e', '#006298', '#0060a0', '#005ea6', '#005baa',
'#0056aa', '#0051a9', '#2f4ca4', '#50459d', '#673d94', '#78358a', '#862d7d', '#902470', '#981e62']
#Couleurs très saturées(Il se démarque, mais vous ne devriez pas l'utiliser beaucoup.)
color_vivid = ['#ffadc7', '#ffadbc', '#ffaeb2', '#ffb0a8', '#ffb29e', '#ffb596', '#f9b88f',
'#f1bc8a', '#e9bf86', '#dfc385', '#d5c685', '#caca87', '#becd8b', '#b2cf90',
'#a6d298', '#99d4a0', '#8dd5aa', '#80d7b4', '#74d7bf', '#6ad8ca', '#61d8d5',
'#5bd7e0', '#59d6e9', '#5dd5f2', '#65d3f9', '#71d1ff', '#7fceff', '#8ecbff',
'#9ec8ff', '#afc4ff', '#bec1ff', '#cdbdfd', '#dab9f7', '#e6b6ef', '#f0b3e6', '#f9b0dc', '#ffaed2']
#Couleur claire(Non utilisé sur fond blanc. Supposé être utilisé sur un fond noir.)
color_thin = ['#ffc3d5', '#ffc3cd', '#ffc3c5', '#ffc4be', '#ffc6b7', '#ffc8b1', '#fbcaac',
'#f5cca9', '#efcfa6', '#e8d2a5', '#e0d4a5', '#d8d7a6', '#cfd9a9', '#c6dbad',
'#bdddb3', '#b5deb9', '#ace0c0', '#a5e0c7', '#9ee1cf', '#98e1d7', '#94e1df',
'#92e1e6', '#92e0ed', '#94dff4', '#99def9', '#9fdcfd', '#a7daff', '#b1d8ff',
'#bbd5ff', '#c5d3ff', '#cfd0ff', '#dacdfc', '#e3cbf7', '#ecc8f2', '#f3c6eb', '#f9c5e4', '#fec4dc']
if (type == 'thin'):
hex_list = color_thin
elif (type == 'vivid'):
hex_list = color_vivid
else:
hex_list = color_basic
if num is not None:
gen_hexnum.send(num)
return hex_list[gen_hexnum.__next__()]
def plot(func, xrange, ylim=None, xlog=None, ylog=None, cn=None, ct='basic', close=None, figs=None, simbol=x):
if figs:
plt.figure(figsize=figs)
X = np.arange(xrange[0], xrange[1], xrange[2])
if hasattr(func, "subs"): # sympy
Y = [func.subs([(simbol, K)]) for K in X]
else: # scipy
Y = [func(K) for K in X]
if ylim:
plt.ylim(ylim)
if xlog:
plt.xscale('log')
else:
plt.xscale('linear')
if ylog:
plt.yscale('log')
else:
plt.yscale('linear')
plt.plot(X, Y, color=hexNum(cn, ct))
if close:
plt.show()
plt.close()
Le simple matplotlib.plot est déroutant, j'ai donc créé une fonction qui n'englobe que les arguments fréquemment utilisés. Il est plus facile à utiliser si vous donnez la fonction, la largeur et la couleur, puis demandez-les.
F = sym.sin(x)/x
G = sym.cos(x)/x
plot(F, (-10, 10, 0.1), cn=0, figs=(10, 6))
plot(G, (-10, 10, 0.1))
plot(F+0.2, (-10, 10, 0.1))
plot(F+0.4, (-10, 10, 0.1))
plot(F+0.6, (-10, 10, 0.1))
plot(F+0.8, (-10, 10, 0.1))
plot(F+1.0, (-10, 10, 0.1))
def A(x):
return np.sin(x)/x
plot(A, (-10, 10, 0.1))
plot(lambda X: (X/9.0)**2, (-10, 10, 0.1), (-0.5, 1.5), close=True)
Pour utiliser sympy confortablement, je veux utiliser toutes les lettres minuscules comme symboles, donc Les noms de fonction et les variables de boucle sont intentionnellement mis en majuscules. Effet de codage couleur par couleur, jugement automatique des fonctions sympy et numpy par hasattr, Avec l'argument close, toutes les options doivent être écrites ensemble à la fin. Je suis satisfait car je peux le tracer assez intuitivement. Cependant, en regardant le graphique, les pôles de $ \ frac {\ cos (x)} {x} $ sont étranges. L'atmosphère est que la ligne au milieu de $ - \ infty \ longrightarrow \ infty $ est dessinée. Y a-t-il une solution?
def plotp(func, t_range=(-4, 4, 100), axis=[-4, 4, -4, 4],
xlog=None, ylog=None, cn=None, ct='basic', close=None, figs=None, simbol=t):
if figs:
plt.figure(figsize=figs)
X, Y = func
t_ndarray = np.linspace(t_range[0], t_range[1], t_range[2]) # ndarray
if hasattr(X, "subs"): # sympy
Xp = np.array([float(sym.N(X.subs([(simbol, T)]))) for T in t_ndarray])
Yp = np.array([float(sym.N(Y.subs([(simbol, T)]))) for T in t_ndarray])
else: # scipy
Xp = [X(K) for K in t_ndarray]
Yp = [Y(K) for K in t_ndarray]
plt.axis(axis)
if xlog:
plt.xscale('log')
else:
plt.xscale('linear')
if ylog:
plt.yscale('log')
else:
plt.yscale('linear')
plt.plot(Xp, Yp, color=hexNum(cn, ct))
if close:
plt.show()
plt.close()
La différence avec plot () est que Func est passé sous la forme d'une liste de deux fonctions et qu'un axe spécifiant les zones x et y est ajouté. Par convention, t est le symbole par défaut. De plus, comme troisième plage de t, elle est spécifiée par le nombre de divisions au lieu de la taille du pas.
X = t**2 * sym.sin(t)
Y = t**2 * sym.cos(t)
plotp([X, Y], (-4 * np.pi, 4 * np.pi, 400), [-100, 100, -100, 100], figs=(6, 6), close=True)
plotp([lambda T: T * np.sin(T), lambda T: T * np.cos(T)], (-4 * np.pi, 4 * np.pi, 400), [-12, 12, -10, 10],
cn=14, figs=(6, 6), close=True)
Sympy et Scipy ont travaillé.
C'est une fonction exprimée au format $ F (x, y) = 0 $. Il semble difficile de gérer directement les fonctions implicites. Utilisez donc plot_implicit de sympy tel quel.
F = x**3 + y**2 -1
sym.plot_implicit(F, (x, -2, 2), (y, -2, 2), line_color=hexNum(2, 'basic'))
Il s'agit d'une équation de courbe elliptique. La couleur semble utilisable, mais elle est claire.
F = x**3 - 2 * x + y**2 > 0
sym.plot_implicit(F, (x, -2, 2), (y, -2, 2), line_color=hexNum(2, 'thin'))
L'avantage est que l'inégalité peut être utilisée.
Une fonction de la forme $ z = f (x, y) $.
from matplotlib import cm
def plot3D(func, xrange=(-2, 2, 0.1), yrange=(-2, 2, 0.1), ptype='plot', simbol=[x, y]):
fig = plt.figure()
ax = Axes3D(fig)
if ptype == 'plot':
ax.plot(func[0], func[1], func[2])
plt.show()
plt.close()
return
X = np.arange(xrange[0], xrange[1], xrange[2])
Y = np.arange(yrange[0], yrange[1], yrange[2])
Xmesh, Ymesh = np.meshgrid(X, Y)
if hasattr(func, "subs"): # sympy
Z = np.array([np.array([float(sym.N(func.subs([(simbol[0], K), (simbol[1], L)]))) for K in X]) for L in Y])
else: # scipy
Z = func(Xmesh, Ymesh)
if ptype == 'surface':
ax.plot_surface(Xmesh, Ymesh, Z, cmap=cm.bwr)
elif ptype == 'wireframe':
ax.plot_wireframe(Xmesh,Ymesh, Z)
elif ptype == 'contour':
ax.contour3D(X, Y, Z)
plt.show()
plt.close()
plot3D(lambda T, U: T * U * np.sin(T), (-4, 4, 0.25), (-4, 4, 0.25), 'surface')
plot3D((x ** 2 - 3 - y ** 2), (-4, 4, 0.25), (-4, 4, 0.25), 'surface')
plot3D((x ** 2 - 3 - y ** 2), (-4, 4, 0.25), (-4, 4, 0.25), 'wireframe')
plot3D((x ** 2 - 3 - y ** 2), (-4, 4, 0.25), (-4, 4, 0.25), 'contour')
La couleur par défaut est utilisée pour la 3D car il vaut mieux voir les hauts et les bas avec une différence de luminosité. J'ai tracé la fonction de la selle de cheval qui apparaît souvent dans la figure de l'univers à courbure négative.
def plotp3(func, simbol=[t], rangeL=[(-4, 4, 100)]):
X, Y, Z = func
t1 = simbol[0]
if len(simbol) >= 2:
u1 = simbol[1]
t_rangeL = rangeL[0]
t_ndarray = np.linspace(t_rangeL[0], t_rangeL[1], t_rangeL[2]) # ndarray
if len(rangeL) >= 2:
u_rangeL = rangeL[1]
u_ndarray = np.linspace(u_rangeL[0], u_rangeL[1], u_rangeL[2]) # ndarray
if len(rangeL) == 1:
Xp = np.array([float(sym.N(X.subs([(t1, T)]))) for T in t_ndarray])
Yp = np.array([float(sym.N(Y.subs([(t1, T)]))) for T in t_ndarray])
Zp = np.array([float(sym.N(Z.subs([(t1, T)]))) for T in t_ndarray])
else:
Xp = np.array([float(sym.N(X.subs([(t1, T), (u1, U)]))) for T in t_ndarray for U in u_ndarray])
Yp = np.array([float(sym.N(Y.subs([(t1, T), (u1, U)]))) for T in t_ndarray for U in u_ndarray])
Zp = np.array([float(sym.N(Z.subs([(t1, T), (u1, U)]))) for T in t_ndarray for U in u_ndarray])
fig = plt.figure()
ax = Axes3D(fig)
ax.plot(Xp, Yp, Zp)
plt.show()
plt.close()
X = 2*sym.cos(t)
Y = 5*sym.sin(t)
Z = t
plotp3([X, Y, Z], [t], [(-5 * np.pi, 5 * np.pi, 200)])
X = (5+2*sym.cos(t))*sym.cos(u)
Y = (5+2*sym.sin(u))*sym.sin(u)
Z = 2*sym.sin(t)-u/sym.oo
plotp3([X, Y, Z], [t, u], [(-np.pi, np.pi, 40), (-np.pi, np.pi, 40)])
Je suis fatigué de cette région. La 3D est sympa par défaut, donc ça va.
X = 2*sym.cos(t)
Y = 5*sym.sin(t)
Z = t
sym.plotting.plot3d_parametric_line(X, Y, Z, (t, -5*np.pi, 5*np.pi))
X = (5+2*sym.cos(t))*sym.cos(u)
Y = (5+2*sym.sin(u))*sym.sin(u)
Z = 2*sym.sin(t)-u/sym.oo
sym.plotting.plot3d_parametric_surface(X, Y, Z, (t, -np.pi, np.pi), (u, -np.pi, np.pi))
Recommended Posts