Je suis un concepteur de circuits analogiques. Récemment, j'ai commencé à étudier Python comme passe-temps.
Le simulateur de circuit d'analyse numérique de SPICE est souvent utilisé dans les travaux de conception de circuits analogiques. Cependant, le simulateur d'analyse numérique à lui seul n'approfondit pas la compréhension du circuit en cours de conception. Parfois, il est nécessaire de simplifier le circuit que vous concevez, de formuler une équation de circuit et de la résoudre. La résolution des équations de circuit est une tâche laborieuse. C'est correct de le résoudre pour le moment, mais j'ai obtenu des résultats pour le moment, comme il y avait une erreur de calcul et je n'ai pas pu obtenir un résultat utile, la formule obtenue était compliquée et je n'ai pas pu avoir de perspicacité et je n'avais pas besoin de la résoudre. On peut dire qu'il est difficile de s'en débarrasser. Donc, cette fois, j'ai rendu possible la résolution de l'équation du circuit en utilisant Sympy. Lors de la création du programme, j'étais conscient de réduire autant que possible le nombre de lieux que les humains entrent.
・ Concepteur de circuits fatigué de résoudre la conception de circuits ・ J'ai joué avec python et Jupyter-notebook ・ J'ai un peu touché sympy
La situation supposée est la suivante «J'ai fini de dessiner un schéma de circuit dans un cahier et de formuler une équation. Il y a tellement d'équations qu'il faudra du temps pour les résoudre. Je ne sais pas si je peux obtenir des résultats significatifs même si je les résolve ... Très bien, laisse sympy le faire! "
Python: 3.7.4、SymPy: 1.6.2
À titre d'exemple simple, calculons la fonction de transfert du circuit illustré ci-dessous. Les constantes des composants du circuit sont des symboles plutôt que des nombres.
Tout d'abord, formulons vous-même l'équation du circuit comme indiqué dans la figure ci-dessous. Quand il s'agit de laisser sympy résoudre des équations de circuit, vous n'avez pas à trouver des moyens de réduire le nombre d'équations, ce qui économise l'énergie de votre tête.
Après avoir confirmé que les inconnues (ici ZP, ZM, IT, VOUT) et le nombre d'équations correspondent, la création de l'équation du circuit est terminée.
À partir de là, exécutons-le sur Jupyter-notebook.
Du coup, tout le code est ci-dessous.
Tous les codes
#Entrez l'équation du circuit
ce = """
ZP = RP / (1 + s*CP*RP)
ZM = RM / (1 + s*CM*RM)
VIN = (s*LP + ZP + ZM)*IT
VOUT = ZM * IT
"""
#Entrez inconnu
uk = "ZP, ZM, IT, VOUT"
#Entrez la variable que vous souhaitez rechercher
wn = "VOUT"
#----------------------------------------------------
#Ci-dessous, il n'y a pas de place pour l'utilisateur pour entrer
#Réglage initial
from sympy import *
from IPython.display import Math
from collections import Counter
#Extraire le symbole de l'équation du circuit et le déclarer comme symbole
rep_char = ["+", "-", "*", "/", "s", "=", "\n", "(", ")"]
ce_rep = ce
for i in range(len(rep_char)):
ce_rep = ce_rep.replace(rep_char[i], " ")
ce_sym = ce_rep.split()
ce_sym = list(Counter(ce_sym).keys())
for i in reversed(range(len(ce_sym))): #Effacer les nombres dans la liste
if ce_sym[i].isdecimal():
del ce_sym[i]
s = Symbol("s", real=True)
for i in range(len(ce_sym)):
exec(ce_sym[i] + " = Symbol(\"" + ce_sym[i] + "\", real=True)")
#Générer un tableau pour l'affichage TeX
ce_tex = []
for i in range(len(ce_sym)):
if len(ce_sym[i]) == 1:
ce_tex.append(ce_sym[i][0])
else:
ce_tex.append(ce_sym[i][0] + "_{" + ce_sym[i][1:] + "}")
#Générer une équation de circuit et une liste de symboles inconnus
start = 3
ind_eq = -1
ind_rt = 2
ce_sol = []
while True:
ind_eq = ce.find("=", ind_eq+1)
ind_rt = ce.find("\n", ind_rt+1)
if ind_rt == -1:
break
exec("ce_sol.append(" + ce[start:ind_eq] + "-(" + ce[ind_eq+1: ind_rt] + "))")
start=ind_rt + 1
exec("uk_sol = " + uk)
exec("wn_sol = " + wn)
#Résoudre et organiser des équations
if len(uk_sol) != len(ce_sol):
print("Alignez le nombre d'inconnues sur le nombre d'équations.")
else:
sol = solve(ce_sol, uk_sol, dict=True)[0][wn_sol]
#Organiser la molécule du dénominateur
nu = collect(expand(numer(sol)), s) #Numérateur, molécule
de = collect(expand(denom(sol)), s) #dénominateur, dénominateur
sol = nu / de
#Afficher des expressions
sol_tex = latex(sol)
for i in range(len(ce_sym)):
sol_tex = sol_tex.replace(latex(ce_sym[i]), ce_tex[i])
display(Math(sol_tex))
Si vous faites cela, vous obtiendrez les résultats suivants:
\displaystyle \frac{C_{P} R_{M} R_{P} V_{IN} s + R_{M} V_{IN}}{C_{M} C_{P} L_{P} R_{M} R_{P} s^{3} + R_{M} + R_{P} + s^{2} \left(C_{M} L_{P} R_{M} + C_{P} L_{P} R_{P}\right) + s \left(C_{M} R_{M} R_{P} + C_{P} R_{M} R_{P} + L_{P}\right)}
Expliquons le déroulement du programme et ses détails.
#Entrez l'équation du circuit
ce = """
ZP = RP / (1 + s*CP*RP)
ZM = RM / (1 + s*CM*RM)
VIN = (s*LP + ZP + ZM)*IT
VOUT = ZM * IT
"""
#Entrez inconnu
uk = "ZP, ZM, IT, VOUT"
#Entrez la variable que vous souhaitez rechercher
wn = "VOUT"
Entrez l'équation du circuit, les inconnues et les variables que vous souhaitez rechercher. Lorsque vous entrez des équations de circuit, commencez par des majuscules pour les paramètres autres que s. En effet, il n'est pas pratique que le résultat du calcul soit affiché dans TeX.
python
from sympy import *
from IPython.display import Math
from collections import Counter
Importez le module. Aucun commentaire spécial n'est nécessaire.
python
rep_char = ["+", "-", "*", "/", "s", "=", "\n", "(", ")"]
ce_rep = ce
for i in range(len(rep_char)):
ce_rep = ce_rep.replace(rep_char[i], " ")
ce_sym = ce_rep.split()
ce_sym = list(Counter(ce_sym).keys())
for i in reversed(range(len(ce_sym))): #Effacer les nombres dans la liste
if ce_sym[i].isdecimal():
del ce_sym[i]
Ici, le traitement suivant est effectué __ (i) L'équation de circuit ce est entrée dans STEP1 __ ZP = RP / (1 + sCPRP) ZM = RM / (1 + sCM+RM) VIN = (sLP + ZP + ZM)*IT VOUT = ZM * IT
__ (ii) Remplacez les opérateurs (+ - * /), s, saut de ligne (\ n), etc. par des espaces de l'équation du circuit d'entrée (ce à l'étape 1) __ ce_rep: ZP RP 1 CP RP ZM RM 1 CM RM VIN LP ZP ZM IT VOUT ZM IT
__ (iii) Extraire les symboles qui apparaissent dans l'équation __ ce_sym: ['ZP', 'RP', '1', 'CP', 'ZM', 'RM', 'CM', 'VIN', 'LP', 'IT', 'VOUT']
__ (iii) Trouvez le numéro dans la liste obtenue ci-dessus et supprimez-le (dans ce cas, 1 est supprimé) __ ce_sym: ['ZP', 'RP', 'CP', 'ZM', 'RM', 'CM', 'VIN', 'LP', 'IT', 'VOUT']
Maintenant que nous avons une liste des symboles utilisés dans l'équation de circuit dans le processus ci-dessus Déclarez-le comme symbole Sympy.
python
s = Symbol("s", real=True)
for i in range(len(ce_sym)):
exec(ce_sym[i] + " = Symbol(\"" + ce_sym[i] + "\", real=True)")
Code en cours d'exécution dans __exec: __ ZP = Symbol("ZP", real=True) RP = Symbol("RP", real=True) CP = Symbol("CP", real=True) ZM = Symbol("ZM", real=True) RM = Symbol("RM", real=True) CM = Symbol("CM", real=True) VIN = Symbol("VIN", real=True) LP = Symbol("LP", real=True) IT = Symbol("IT", real=True) VOUT = Symbol("VOUT", real=True)
python
ce_tex = []
for i in range(len(ce_sym)):
if len(ce_sym[i]) == 1:
ce_tex.append(ce_sym[i][0])
else:
ce_tex.append(ce_sym[i][0] + "_{" + ce_sym[i][1:] + "}")
Je veux afficher le résultat de sortie dans TeX, donc je vais créer une liste pour cela. Sur la base de la liste de ce_sym, la liste ce_tex à subordonner après le deuxième caractère est générée [^ 1]. Exemple: VOUT → V_ {OUT}, $ V_ {OUT} $
ce_tex: ['Z_{P}', 'R_{P}', 'C_{P}', 'Z_{M}', 'R_{M}', 'C_{M}', 'V_{IN}', 'L_{P}', 'I_{T}', 'V_{OUT}']
__ (Référence) ce_sym: __ obtenu dans STEP3 ['ZP', 'RP', 'CP', 'ZM', 'RM', 'CM', 'VIN', 'LP', 'IT', 'VOUT']
[^ 1]: Notez que si vous utilisez le symbole BW1, l'affichage Tex ne sera pas $ BW_1 $, mais sera $ B_ {W1} $.
python
start = 3
ind_eq = -1
ind_rt = 2
ce_sol = []
while True:
ind_eq = ce.find("=", ind_eq+1)
ind_rt = ce.find("\n", ind_rt+1)
if ind_rt == -1:
break
exec("ce_sol.append(" + ce[start:ind_eq] + "-(" + ce[ind_eq+1: ind_rt] + "))")
start=ind_rt + 1
exec("uk_sol = " + uk)
exec("wn_sol = " + wn)
L'équation et la liste de symboles inconnus sont générées par le traitement suivant.
__ (i) L'équation de circuit ce est entrée dans STEP1 __ ce: ZP = RP / (1 + sCPRP) ZM = RM / (1 + sCMRM) VIN = (s*LP + ZP + ZM)*IT VOUT = ZM * IT
Trouvez l'égal '=' et le saut de ligne '\ n'de __ (ii) ce et créez une liste avec le côté droit décalé vers le côté gauche __ ce_sol: -RP/(CPRPs + 1) + ZP, -RM/(CMRMs + 1) + ZM, -IT*(LPs + ZM + ZP) + VIN, -ITZM + VOUT
__ (iii) Exécutez le code suivant pour l'inconnu (uk) et la variable (wn) que vous voulez trouver __ uk_sol = ZP, ZM, IT, VOUT wn_sol = VOUT
C'est la partie qui résout finalement l'équation.
python
if len(uk_sol) != len(ce_sol):
print("Alignez le nombre d'inconnues sur le nombre d'équations.")
else:
sol = solve(ce_sol, uk_sol, dict=True)[0][wn_sol]
#Organiser la molécule du dénominateur
nu = collect(expand(numer(sol)), s) #Numérateur, molécule
de = collect(expand(denom(sol)), s) #dénominateur, dénominateur
sol = nu / de
Si le nombre d'inconnues et le nombre d'équations ne sont pas les mêmes, une solution ne peut pas être obtenue, donc nous vérifions cela en premier.
L'équation est résolue par le code suivant.
sol = solve(ce_sol, uk_sol, dict=True)[0][wn_sol]
Si vous exécutez la résolution (ce_sol, uk_sol, dict = True), vous obtiendrez toutes les solutions inconnues comme ci-dessous. En ajoutant [0] [wn_sol], seule la solution (VOUT cette fois) que vous voulez trouver est extraite.
Résultat de l'exécution de ___sol = résoudre (ce_sol, uk_sol, dict = True): __ ZP: RP/(CPRPs + 1) ZM: RM/(CMRMs + 1) IT: VIN * (CM * RM * s + 1) * (CP ~ omis ~ VOUT: RM * VIN * (CP * RP * s + 1 ~ omis ~
Après avoir trouvé la solution, la molécule dénominatrice est organisée pour s.
La solution obtenue est difficile à lire comme indiqué ci-dessous.
sol:
#Afficher des expressions
sol_tex = latex(sol)
for i in range(len(ce_sym)):
sol_tex = sol_tex.replace(latex(ce_sym[i]), ce_tex[i])
display(Math(sol_tex))
Par conséquent, afin de rendre l'affichage de l'équation plus facile à voir, il est converti en affichage TeX. Par exemple, s'il s'agit de VOUT, remplacez-le par V_ {OUT}.
Le résultat final est le suivant, et la lisibilité a été améliorée en utilisant l'affichage TeX.
La formule est remplacée pour afficher TeX, mais elle peut se comporter de manière inattendue selon le nom du symbole. Par exemple, l'utilisation du symbole ac remplace \ fr ac dans le code TeX. Pour cette raison, les symboles doivent commencer par des lettres majuscules.
C'est tout pour l'explication. Puisque l'utilisateur n'entre que l'équation du circuit, l'inconnu et la variable à obtenir, l'équation du circuit peut être résolue avec le minimum d'effort requis. L'effort économisé peut être utilisé pour interpréter les résultats obtenus. Par exemple, la formule pourrait être simplifiée à partir de la relation de grandeur des termes.
Les humains ont mis en place l'équation du circuit cette fois, mais je pense que même la mise en place de l'équation du circuit peut être gênante (pas de temps). Dans ce cas, vous pouvez également automatiser la formulation des équations de circuit en utilisant un package python appelé Lcapy. Tout ce que l'utilisateur a à faire est de dessiner un schéma électrique. J'ai écrit un article de commentaire à ce sujet, donc si vous êtes intéressé, jetez-y également un œil.
[Circuit x Python] Comment activer le package d'analyse de circuit linéaire Lcapy [Circuit x Python] Comment trouver la fonction de transfert d'un circuit en utilisant Lcapy [Circuit x Python] Comment développer et calculer les fonctions de transfert à l'aide de Lcapy