Sympy peut-il simplifier une expression rationnelle en collectant plusieurs termes ?

Aug 19 2020

Étant donné une expression rationnelle Etelle que celle ci-dessous, je cherche à utiliser Sympy pour la simplifier en quelque chose qui ressemble à F(défini dans le deuxième bloc de code Python ci-dessous):

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() ))

Cela 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) 

Cependant, l'expression peut être - manuellement - simplifiée davantage, dont le résultat que j'ai étiqueté 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())

Cela produit

n⋅(-A + B)⋅(c - t)   n⋅(-B + C)⋅(-b + t)
────────────────── + ───────────────────
(-a + c)⋅(-b + c)     (-b + c)⋅(-b + d) 


0

J'ai examiné diverses options, notamment factor(), collect()et apart(), mais aucune d'entre elles ne semble produire d'expressions ayant la même structure que F. Des pointeurs sur la façon de procéder?

De plus, je me demandais si la jolie fonction d'impression de Sympy pouvait être modifiée d'une manière ou d'une autre pour

  1. Conservez l'ordre d'origine des variables au numérateur et au dénominateur (par exemple B - Aau lieu de -A + B). Actuellement, l'ordre est inversé dans la plupart des cas, ce qui semble plutôt moche avec les principaux signes moins.
  2. Afficher les fractions composites comme des produits de fractions simples (par exemple a/b c/dau lieu de ac/bd), bien que dans certains cas, il puisse bien sûr être ambigu où/comment "séparer" ces fractions composites.

Réponses

2 OscarBenjamin Aug 23 2020 at 21:35

La situation ici est que vous avez un Addde deux termes. Chaque terme séparément peut être simplifié en utilisant factormais les facteurs à annuler sont différents pour chacun, donc l'appel factordans son ensemble Addne permet pas de trouver l'annulation possible.

Dans cet esprit, nous devons faire attention à traiter les termes de Addmanière indépendante, ce que nous pouvons faire en accédant à .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) 

L'ordre des variables est en fait déterminé par l'imprimante lors de l'affichage de l'expression et n'est pas nécessairement le même que l'ordre interne des arguments ou nécessairement l'ordre utilisé lors de la création de l'expression. Un appel à signsimppeut normaliser les signes moins dans l'expression

In [123]: signsimp(_)
Out[123]: 
  n⋅(A - B)⋅(c - t)   n⋅(B - C)⋅(b - t)
- ───────────────── + ─────────────────
   (a - c)⋅(b - c)     (b - c)⋅(b - d)