Fuente: https://docs.sympy.org/latest/tutorials/intro-tutorial/gotchas.html
Problemas
Para empezar, debemos dejar claro algo sobre SymPy. SymPy no es nada más
que una biblioteca de Python, como NumPy
, Django
, o incluso módulos en el
Biblioteca estándar de Python sys
o re
. Lo que esto significa es que SymPy no
No agregar nada al lenguaje Python. Limitaciones inherentes a la
El lenguaje Python también es inherente a SymPy. También significa que SymPy intenta
Utilice modismos de Python siempre que sea posible, lo que facilita la programación con SymPy.
aquellos que ya están familiarizados con la programación con Python. Como ejemplo sencillo,
SymPy usa la sintaxis de Python para crear expresiones. Multiplicación implícita (como
3x
o 3 x
) no está permitido en Python y, por lo tanto, no está permitido en SymPy.
Multiplicar 3
y x
, debes escribir 3*x
con el *
.
Símbolos
Una consecuencia de este hecho es que SymPy se puede utilizar en cualquier entorno. donde Python está disponible. Simplemente lo importamos, como lo haríamos con cualquier otro. biblioteca:
from sympy import *
Esto importa todas las funciones y clases de SymPy a nuestro interactivo Sesión de Python. Ahora supongamos que comenzamos a hacer un cálculo.
x + 1 Traceback (most recent call last): ... NameError: name 'x' is not defined
¡Ups! ¿Que pasó aquí? Intentamos usar la variable. x
, pero nos dice
eso x
no está definido. En Python, las variables no tienen significado hasta que
están definidos. SymPy no es diferente. A diferencia de muchas manipulaciones simbólicas
sistemas que haya utilizado, en SymPy, las variables no se definen automáticamente.
Para definir variables debemos utilizar symbols
.
x = symbols('x')
x + 1 x + 1
symbols
toma una cadena de nombres de variables separados por espacios o comas,
y crea símbolos a partir de ellos. Luego podemos asignarlos a nombres de variables.
Más adelante, investigaremos algunas formas convenientes en las que podemos solucionar este problema.
Por ahora, definamos simplemente los nombres de variables más comunes, x
, y
, y
z
, para uso durante el resto de esta sección
x, y, z = symbols('x y z')
Como nota final, observamos que el nombre de un Símbolo y el nombre del La variable a la que está asignada no necesita tener nada que ver entre sí.
a, b = symbols('b a')
a b
b a
Aquí hemos hecho lo muy confuso de asignar un símbolo con el nombre
a
a la variable b
y un símbolo del nombre b
a la variable
a
. Ahora la variable de Python llamada a
apunta al símbolo SymPy llamado
b
, y viceversa. Qué confuso. También podríamos haber hecho algo como
crazy = symbols('unrelated')
crazy + 1 unrelated + 1
Esto también muestra que los símbolos pueden tener nombres de más de un carácter si desear.
Por lo general, la mejor práctica es asignar símbolos a las variables de Python del mismo nombre, aunque hay excepciones: Los nombres de los símbolos pueden contener caracteres que no están permitidos en los nombres de variables de Python, o que simplemente quieran evitar escribir nombres largos asignando símbolos con nombres largos a una sola letra Python variables.
Para evitar confusiones, a lo largo de este tutorial, los nombres de los símbolos y las variables de Python Los nombres siempre coincidirán. Además, la palabra “Símbolo” se referirá a un El símbolo SymPy y la palabra "variable" se referirán a una variable de Python.
Finalmente, asegurémonos de comprender la diferencia entre símbolos SymPy y Variables de Python. Considera lo siguiente:
x = symbols('x')
expr = x + 1
x = 2
print(expr)
¿Cuál crees que será el resultado de este código? si pensaras 3
,
te equivocas. veamos que pasa realmente
x = symbols('x')
expr = x + 1
x = 2
print(expr) x + 1
Cambiando x
a 2
no tuvo ningún efecto sobre expr
. Esto es porque x = 2
cambia la variable de Python x
a 2
, pero no tiene ningún efecto en SymPy
Símbolo x
, que fue lo que usamos para crear expr
. cuando creamos
expr
, la variable de Python x
era un símbolo. Después de que lo creamos, nosotros
cambió la variable de Python x
a 2. Pero expr
sigue siendo el mismo. Este
El comportamiento no es exclusivo de SymPy. Todos los programas Python funcionan de esta manera: si un
se cambia la variable, las expresiones que ya fueron creadas con esa variable
no cambie automáticamente. Por ejemplo
x = 'abc'
expr = x + 'def'
expr 'abcdef'
x = 'ABC'
expr 'abcdef'
Para cambiar el valor de un símbolo en una expresión, use subs
x = symbols('x')
expr = x + 1
expr.subs(x, 2) 3
En este ejemplo, si queremos saber qué expr
es con el nuevo valor de
x
, necesitamos reevaluar el código que creó expr
, a saber, expr =
x + 1
. Esto puede resultar complicado si se crean varias líneas. expr
. Uno
La ventaja de utilizar un sistema de cálculo simbólico como SymPy es que podemos
construir una representación simbólica para expr
y luego sustituir x
con
valores. La forma correcta de hacer esto en SymPy es usar subs
, Cuál podría ser
discutido con más detalle más adelante.
x = symbols('x')
expr = x + 1
expr.subs(x, 2) 3
Signos iguales
Otra consecuencia muy importante del hecho de que SymPy no se extiende
La sintaxis de Python es esa =
no representa igualdad en SymPy. Más bien
es la asignación de variables de Python. Esto está codificado en el lenguaje Python,
y SymPy no intenta cambiar eso.
Puedes pensar, sin embargo, que ==
, que se utiliza para pruebas de igualdad en
Python, se usa para SymPy como igualdad. Esto tampoco es del todo correcto. Dejar
veamos qué pasa cuando usamos ==
.
x + 1 == 4 Falseen lugar de tratar
x + 1 == 4
simbólicamente, acabamos de llegar False
. En
simpy, ==
representa una prueba exacta de igualdad estructural. Esto significa que
a == b
significa que estamos preguntando si . Siempre recibimos un bool
como
el resultado de ==
. Hay un objeto separado, llamado Eq
, que puede ser
utilizado para crear igualdades simbólicas
Eq(x + 1, 4) Eq(x + 1, 4)Hay una advertencia adicional sobre
==
también. Supongamos que queremos saber
si . Podríamos intentar algo como esto:
(x + 1)**2 == x**2 + 2*x + 1 FalseTenemos
False
de nuevo. Sin embargo, es igual . Qué esta pasando aqui? ¿Encontramos un error en SymPy o simplemente no es potente? ¿Suficiente para reconocer este hecho algebraico básico?
Recuerda desde arriba que ==
representa exacta de igualdad estructural.
"Exacta" aquí significa que dos expresiones se compararán igual ==
sólo si
son exactamente iguales estructuralmente. Aquí,
son No es lo mismo estructuralmente. Uno es la potencia de la suma de dos términos, y el otro es la suma de tres términos.
Resulta que al usar SymPy como biblioteca, tener ==
prueba de exactitud
La igualdad estructural es mucho más útil que representar valores simbólicos.
igualdad, o hacer que pruebe la igualdad matemática. Sin embargo, como nuevo
usuario, probablemente le interesarán más los dos últimos. ya hemos visto
una alternativa a la representación simbólica de las igualdades, Eq
. para probar si
dos cosas son iguales, es mejor recordar el hecho básico de que si
aprenderemos Más adelante que la función para hacer esto se llama simplify
. Este
El método no es infalible; de hecho, se puede demostrar teóricamente que es imposible.
determinar si dos expresiones simbólicas son idénticamente iguales en
general, pero para la mayoría de las expresiones comunes, funciona bastante bien.
a = (x + 1)**2
b = x**2 + 2*x + 1
simplify(a - b) 0
c = x**2 - 2*x + 1
simplify(a - c) 4*x
También existe un método llamado equals
que prueba si dos expresiones son
iguales evaluándolos numéricamente en puntos aleatorios.
a = cos(x)**2 - sin(x)**2
b = cos(2*x)
a.equals(b) True
Dos notas finales: ^
y /
Quizás hayas notado que hemos estado usando **
para la exponenciación en su lugar
de la norma ^
. Esto se debe a que SymPy sigue las convenciones de Python. En
Pitón, ^
representa lógica exclusiva o. SymPy sigue esta convención:
True ^ False True
True ^ True False
Xor(x, y) x ^ y
Finalmente, conviene realizar una pequeña discusión técnica sobre cómo funciona SymPy. Cuando
escribes algo como x + 1
, el símbolo SymPy x
se agrega a la
Python entero 1
. Las reglas del operador de Python permiten que SymPy le diga a Python
que los objetos SymPy saben cómo agregarse a las entradas de Python, y así 1
es
convertido automáticamente al objeto SymPy Integer.
Este tipo de magia del operador ocurre automáticamente detrás de escena, y usted Rara vez necesitamos siquiera saber lo que está sucediendo. Sin embargo, hay uno excepción. Siempre que combine un objeto SymPy y un objeto SymPy, o un SymPy objeto y un objeto Python, obtienes un objeto SymPy, pero siempre que combinas dos objetos Python, SymPy nunca entra en juego, por lo que obtienes un Python objeto.
type(Integer(1) + 1) <class 'sympy.core.numbers.Integer'>
type(1 + 1) <... 'int'>
Por lo general, esto no es gran cosa. Las entradas de Python funcionan de manera muy similar a SymPy Números enteros, pero hay una excepción importante: la división. En SymPy, el La división de dos Enteros da un Racional:
Integer(1)/Integer(3) 1/3
type(Integer(1)/Integer(3)) <class 'sympy.core.numbers.Rational'>
Pero en Python /
representa división entera o punto flotante
división, dependiendo de si estás en Python 2 o Python 3, y dependiendo
sobre si has corrido o no from __future__ import division
en pitón 2
que ya no es compatible con versiones superiores a SymPy 1.5.1:
from __future__ import division
1/2 0.5
Para evitar esto, podemos construir el objeto racional explícitamente.
Rational(1, 2) 1/2
Este problema también surge cada vez que tenemos una expresión simbólica más grande con
int/int
en eso. Por ejemplo:
x + 1/2 x + 0.5
Esto sucede porque Python primero evalúa 1/2
en 0.5
, y luego
que se convierte en un tipo SymPy cuando se agrega a x
. Nuevamente podemos obtener
alrededor de esto creando explícitamente un Racional:
x + Rational(1, 2) x + 1/2
Hay varios consejos para evitar esta situación en los errores y trampas. documento.
Otras lecturas
Para obtener más información sobre los temas tratados en esta sección, consulte Errores y dificultades .
No hay comentarios.:
Publicar un comentario