¿Puede Sympy simplificar una expresión racional recopilando varios términos?
Dada una expresión racional E
como la que se muestra a continuación, busco usar Sympy para simplificarla a algo parecido a F
(definido en el segundo bloque del código de Python a continuación):
import sympy as sp
a, b, c, d, n, t, A, B, C = sp.symbols('a, b, c, d, n, t, A, B, C', real = True)
E = n/(c-b) * ( B - (c-b)/(c-a)*A - (b-a)/(c-a)*B ) * (c-t)/(c-b) + n/(c-b) * ( (d-c)/(d-b)*B + (c-b)/(d-b)*C - B ) * (t-b)/(c-b)
print(sp.pretty( E ))
print(sp.pretty( E.simplify() ))
esto imprime
⎛ B⋅(-c + d) C⋅(-b + c)⎞ ⎛ A⋅(-b + c) B⋅(-a + b) ⎞
n⋅(-b + t)⋅⎜-B + ────────── + ──────────⎟ n⋅(c - t)⋅⎜- ────────── - ────────── + B⎟
⎝ -b + d -b + d ⎠ ⎝ -a + c -a + c ⎠
───────────────────────────────────────── + ─────────────────────────────────────────
2 2
(-b + c) (-b + c)
-n⋅((a - c)⋅(b - t)⋅(-B⋅(b - d) + B⋅(c - d) + C⋅(b - c)) + (b - d)⋅(c - t)⋅(A⋅(b - c) + B⋅(a - b) - B⋅(a - c)))
────────────────────────────────────────────────────────────────────────────────────────────────────────────────
2
(a - c)⋅(b - c) ⋅(b - d)
Sin embargo, la expresión puede simplificarse aún más, manualmente, cuyo resultado he etiquetado F
:
F = n/(c-a) * (B - A) * (c-t)/(c-b) + n/(d-b) * (C - B) * (t-b)/(c-b)
print(sp.pretty( F ))
print((F-E).simplify())
Esto produce
n⋅(-A + B)⋅(c - t) n⋅(-B + C)⋅(-b + t)
────────────────── + ───────────────────
(-a + c)⋅(-b + c) (-b + c)⋅(-b + d)
0
He buscado en varias opciones, incluyendo factor()
, collect()
y apart()
, pero ninguna de ellas parece producir expresiones que tengan la misma estructura que F
. ¿Algún consejo sobre cómo proceder?
Además, me preguntaba si la bonita función de impresión de Sympy se puede ajustar de alguna manera para
- Mantenga el orden original de las variables tanto en el numerador como en el denominador (por ejemplo,
B - A
en lugar de-A + B
). Actualmente, el orden está invertido en la mayoría de los casos, lo que se ve bastante feo con los signos menos iniciales. - Muestre fracciones compuestas como productos de fracciones simples (por ejemplo ,
a/b c/d
en lugar deac/bd
), aunque en ciertos casos, por supuesto, puede ser ambiguo dónde/cómo "dividir" dichas fracciones compuestas.
Respuestas
La situación aquí es que tienes una Add
de dos términos. Cada término por separado se puede simplificar usando factor
pero los factores a cancelar son diferentes para cada uno, por lo que llamando factor
al conjunto Add
no se encuentra la posible cancelación.
Con eso en mente, debemos tener cuidado de procesar los términos de Add
forma independiente, lo que podemos hacer accediendo a .args
:
In [122]: E.func(*(factor(term) for term in E.args))
Out[122]:
n⋅(A - B)⋅(-c + t) n⋅(B - C)⋅(-b + t)
────────────────── - ──────────────────
(a - c)⋅(b - c) (b - c)⋅(b - d)
El orden de las variables en realidad lo determina la impresora cuando muestra la expresión y no es necesariamente el mismo que el orden interno de los argumentos o necesariamente el orden utilizado cuando creó la expresión. Sin embargo, una llamada a signsimp
puede normalizar los signos menos en la expresión
In [123]: signsimp(_)
Out[123]:
n⋅(A - B)⋅(c - t) n⋅(B - C)⋅(b - t)
- ───────────────── + ─────────────────
(a - c)⋅(b - c) (b - c)⋅(b - d)