Sympy può semplificare un'espressione razionale raccogliendo più termini?

Aug 19 2020

Data un'espressione razionale Ecome quella qui sotto, sto cercando di usare Sympy per semplificarla in qualcosa che assomigli F(definito nel secondo blocco di codice Python qui sotto):

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

Questo stampa

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

Tuttavia, l'espressione può essere - manualmente - ulteriormente semplificata, il cui risultato è stato etichettato 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())

Questo esce

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


0

Ho esaminato varie opzioni tra cui factor(), collect()e apart(), ma nessuna di queste sembra produrre espressioni con la stessa struttura di F. Qualche indicazione su come procedere?

Inoltre, mi chiedevo se la bella funzione di stampa di Sympy potesse essere modificata in qualche modo

  1. Mantieni l'ordine originale delle variabili sia al numeratore che al denominatore (ad es . B - Ainvece di -A + B). Attualmente l'ordine è capovolto nella maggior parte dei casi, il che sembra piuttosto brutto con i primi segni meno.
  2. Mostra le frazioni composte come prodotti di frazioni semplici (ad es. a/b c/dinvece di ac/bd), anche se in alcuni casi può ovviamente essere ambiguo dove/come "dividere" tali frazioni composte.

Risposte

2 OscarBenjamin Aug 23 2020 at 21:35

La situazione qui è che hai uno Adddi due termini. Ogni termine separatamente può essere semplificato utilizzando factorma i fattori da annullare sono diversi per ognuno, quindi chiamando factornel complesso Addnon si riesce a trovare l'eventuale cancellazione.

Con questo in mente dobbiamo stare attenti a elaborare i termini Adddell'indipendentemente che possiamo fare accedendo 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) 

L'ordine delle variabili è effettivamente determinato dalla stampante durante la visualizzazione dell'espressione e non è necessariamente uguale all'ordine interno degli argomenti o necessariamente all'ordine utilizzato quando è stata creata l'espressione. Tuttavia, una chiamata a signsimppuò normalizzare i segni meno nell'espressione

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