[Circuit x Python] Comment résoudre symboliquement les équations de circuit en utilisant sympy

introduction

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.

Pour des gens comme ça

・ 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! "

environnement

Python: 3.7.4、SymPy: 1.6.2

Circuit à analyser

À 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. image.png

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. image.png

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.

Tous les codes

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.

ÉTAPE 1: Entrez l'équation du circuit et inconnu

#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.

ÉTAPE 2: module d'importation

python


from sympy import *
from IPython.display import Math
from collections import Counter

Importez le module. Aucun commentaire spécial n'est nécessaire.

ÉTAPE 3: Extraire le symbole de l'équation du circuit et le déclarer comme symbole

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)

ÉTAPE 4: générer un tableau pour l'affichage TeX

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} $.

ÉTAPE 5: Générer l'équation du circuit et la liste des symboles inconnus

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

ÉTAPE 6: Résolvez et organisez des équations

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: $\displaystyle \frac{CP RM RP VIN s + RM VIN}{CM CP LP RM RP s^{3} + RM + RP + s^{2} \left(CM LP RM + CP LP RP\right) + s \left(CM RM RP + CP RM RP + LP\right)}$

    #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. $\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)}$

Nom de variable

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.

en conclusion

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

Recommended Posts

[Circuit x Python] Comment résoudre symboliquement les équations de circuit en utilisant sympy
[Circuit x Python] Comment développer et calculer les fonctions de transfert à l'aide de Lcapy
[Python] Résoudre des équations avec sympy
[Circuit x Python] Comment trouver la fonction de transfert d'un circuit en utilisant Lcapy
Comment installer Python à l'aide d'Anaconda
Comment résoudre des équations linéaires simultanées
[Circuit x Python] Comment activer le package d'analyse de circuit linéaire Lcapy
Comment effacer Python 2.x sur Mac.
Résolvons des équations linéaires simultanées avec Python sympy!
[Algorithm x Python] Comment utiliser la liste
Résolvez des équations simultanées en un instant en utilisant Python
Comment installer python
Comment utiliser SymPy
Comment configurer un environnement Python à l'aide de pyenv
Comment soumettre automatiquement des formulaires Microsoft à l'aide de python (version Mac)
Résolvez des équations différentielles normales simultanées avec Python et SymPy.
Comment créer un package Python à l'aide de VS Code
Comment quitter lors de l'utilisation de Python dans Terminal (Mac)
Comment récupérer plusieurs tableaux à l'aide de slice en python.
[Introduction à Python] Comment arrêter la boucle en utilisant break?
Comment exécuter une commande à l'aide d'un sous-processus en Python
[Introduction à Python] Comment écrire des instructions répétitives à l'aide d'instructions for
[2020.8 dernière] Comment installer Python
Comment installer Python [Windows]
[Introduction à Python] Comment écrire des branches conditionnelles en utilisant des instructions if
python3: Comment utiliser la bouteille (2)
[Python] Comment utiliser la liste 1
Comment mettre à jour Tkinter de Python vers la version 8.6
Comment transloquer un tableau à deux dimensions en utilisant uniquement python [Note]
Publier sur Twitter en utilisant Python
Comment utiliser Python Argparse
Commencez à Selenium en utilisant python
Python: comment utiliser pydub
[Python] Comment utiliser checkio
Comment exécuter Notepad ++ Python
Comment changer la version de Python
13th Offline en temps réel Comment résoudre les problèmes d'écriture avec Python
Comment développer en Python
Comment mettre à jour le blog FC2, etc. en utilisant XMLRPC avec Python
[python] Comment juger scalaire
[Python] Comment utiliser input ()
Comment utiliser Python lambda
[Python] Comment utiliser virtualenv
python3: Comment utiliser la bouteille (3)
python3: Comment utiliser la bouteille
Convertir le code python 3.x en python 2.x
Comment utiliser les octets Python
Comment afficher des formules en latex lors de l'utilisation de Sympy (> = 1.4) dans Google Colaboratory
Comment obtenir des abonnés et des abonnés de Python à l'aide de l'API Mastodon
17e comment résoudre les problèmes d'écriture en temps réel hors ligne avec Python
Comment écrire en temps réel hors ligne Résolution des problèmes E04 avec Python
Comment créer un environnement Python à l'aide de Virtualenv sur Ubuntu 18.04 LTS
Comment mettre à jour une source de données de classeur packagée Tableau à l'aide de Python
Comment écrire hors ligne en temps réel Résolution des problèmes F01 avec Python
Comment installer Theano sur Mac OS X 10.10 (en utilisant pyenv, anaconda)
[Python] Comment FFT des données mp3