Sympy สามารถลดความซับซ้อนของนิพจน์เชิงเหตุผลโดยการรวบรวมคำศัพท์หลายคำได้หรือไม่?

Aug 19 2020

ด้วยนิพจน์ที่มีเหตุผลEเช่นด้านล่างฉันต้องการใช้ Sympy เพื่อลดความซับซ้อนของสิ่งที่ดูเหมือนF(กำหนดไว้ในบล็อกที่สองของโค้ด Python ด้านล่าง):

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

นี้พิมพ์

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

อย่างไรก็ตามนิพจน์สามารถ - ปรับให้ง่ายขึ้นด้วยตนเองซึ่งเป็นผลลัพธ์ที่ฉันระบุว่า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())

เอาต์พุตนี้

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


0

ฉันได้มองเข้าไปในตัวเลือกต่าง ๆ รวมทั้งfactor(), collect()และแต่ไม่มีของเหล่านี้ดูเหมือนจะแสดงออกอัตราผลตอบแทนที่มีรูปแบบเดียวกันกับapart() Fมีคำแนะนำเกี่ยวกับวิธีดำเนินการต่อหรือไม่?

นอกจากนี้ฉันสงสัยว่าฟังก์ชันการพิมพ์สวย ๆ ของ Sympy สามารถปรับแต่งได้หรือไม่

  1. รักษาลำดับเดิมของตัวแปรทั้งในตัวเศษและตัวส่วน (เช่นB - Aแทนที่จะเป็น-A + B) ขณะนี้คำสั่งซื้อถูกพลิกในกรณีส่วนใหญ่ซึ่งดูค่อนข้างน่าเกลียดเมื่อมีเครื่องหมายลบนำหน้า
  2. แสดงเศษส่วนเชิงประกอบเป็นผลคูณของเศษส่วนอย่างง่าย (เช่นa/b c/dแทนที่จะเป็นac/bd) แม้ว่าในบางกรณีอาจมีความคลุมเครือว่าจะ "แยก" เศษส่วนเชิงประกอบดังกล่าวได้อย่างไร

คำตอบ

2 OscarBenjamin Aug 23 2020 at 21:35

สถานการณ์ในที่นี้คือคุณมีAddสองเทอม คำศัพท์แต่ละคำที่แยกจากกันสามารถทำให้ง่ายขึ้นได้โดยใช้factorแต่ปัจจัยในการยกเลิกนั้นแตกต่างกันไปสำหรับแต่ละคำดังนั้นการเรียกfactorโดยรวมจึงAddไม่พบการยกเลิกที่เป็นไปได้

ด้วยเหตุนี้เราจึงต้องระมัดระวังในการดำเนินการตามเงื่อนไขที่Addเป็นอิสระซึ่งเราสามารถทำได้โดยการเข้าถึง.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) 

ลำดับของตัวแปรถูกกำหนดโดยเครื่องพิมพ์เมื่อแสดงนิพจน์และไม่จำเป็นต้องเหมือนกับลำดับภายในของ args หรือจำเป็นต้องเป็นลำดับที่ใช้เมื่อคุณสร้างนิพจน์ การเรียกร้องให้signsimpสามารถทำให้เครื่องหมายลบในนิพจน์เป็นปกติได้

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