2013-03-04 21 views
6

Tôi đang sử dụng sympy để giải quyết một đa thức:Bỏ qua rễ tưởng tượng trong sympy

x = Symbol('x') 
y = solve(int(row["scaleA"])*x**3 + int(row["scaleB"])*x**2 + int(row["scaleC"])*x + int(row["scaleD"]), x) 

y là một danh sách các giải pháp khả thi. Tuy nhiên, tôi cần phải bỏ qua những hình ảnh ảo và chỉ sử dụng các giải pháp thực tế. Ngoài ra, tôi muốn giải pháp như một giá trị không phải là một biểu thức. Ngay bây giờ có vẻ như:

[-2/3 - 55**(1/3)*(-1/2 - sqrt(3)*I/2)/3, -2/3 - 55**(1/3)*(-1/2 + sqrt(3)*I/2)/3, -55**(1/3)/3 - 2/3] 

Tôi cần giá trị của biểu thức cuối cùng (-2.22756). Có chức năng nào trong sympy để đơn giản hóa điều này không?

+4

SymPy có lẽ không phải là thư viện phù hợp để sử dụng nếu bạn chỉ quan tâm đến tính tương đối float/double của gốc. Nếu bạn sử dụng numpy/scipy, bạn có thể sẽ nhận được hiệu suất tốt hơn và mã đơn giản hơn. Và nếu bạn chọn sympy over numpy/scipy vì nó nhỏ hơn bạn có thể nhỏ hơn với mpmath được sử dụng bên trong sympy cho số học (độ chính xác tùy ý không bị giới hạn bởi máy) – Krastanov

Trả lời

0

Như Krastonov đã đề cập mpmath cung cấp một phương pháp dễ dàng hơn:

y = polyroots([int(row["scaleA"]), int(row["scaleB"]), int(row["scaleC"]), int(row["scaleD"])-value]) 
for root in y: 
    if "j" not in str(root): 
     value = root 
-3

Tôi đã quản lý đơn giản là bỏ qua các giải pháp chứa ký tự "I" và sử dụng .evalf() để đánh giá biểu thức. Mã này bây giờ là:

x = Symbol('x') 
    y = solve(int(row["scaleA"])*x**3 + int(row["scaleB"])*x**2 + int(row["scaleC"])*x + int(row["scaleD"]), x) 
    for root in y: 
     if "I" not in str(root): 
      print("This One:" + str(root.evalf())) 
+3

Cách tốt hơn để lọc ra gốc thực là kiểm tra ' root.is_real'. – asmeurer

9

Nếu bạn đặt x là thật, SymPy sẽ chỉ cung cấp cho bạn các giải pháp thực

x = Symbol('x', real=True) 
solve(..., x) 
+0

Tôi đang cố gắng giải phương trình bằng phương pháp này nhưng nó vẫn trả về các giải pháp tưởng tượng – Alex

+0

Bạn đang sử dụng giải pháp? Lưu ý rằng 'solveset' mới bỏ qua các giả định được đặt trên Symbols (sử dụng' solveset (domain = S.Reals) 'để giải quyết trong miền thực. Nếu bạn đang sử dụng giải quyết, đây là một lỗi cần được [báo cáo] (https: //github.com/sympy/sympy/issues/new) – asmeurer

+0

Tôi đã thử cả hai: giải quyết, với các giả định, solveset và solveset với domain = S.Reals Giải quyết đơn giản là bỏ qua các giả định về biến được giải quyết (như giải quyết) đến các giải pháp trong 30 giây, trong khi giải quyết với một tên miền đã không thể đến giải pháp trong 20 phút. Nó có thể là một bản sao? (https://github.com/sympy/sympy/issues/9973) – Alex

0

solve() không có đầu ra nhất quán cho các loại giải pháp khác nhau, vui lòng sử dụng solveset(Eq,x,domain=S.Reals):

from sympy import ImageSet, S 
x = Symbol('x') 
y = solveset(int(row["scaleA"])*x**3 + int(row["scaleB"])*x**2+int(row["scaleC"])*x + int(row["scaleD"]), x, domain=S.Reals) 

http://docs.sympy.org/latest/modules/solvers/solveset.html

1

Đây chính là loại điều mà real_roots được thực hiện cho và đặc biệt áp dụng đối với trường hợp của bạn, nơi các hệ số là các số nguyên:

x = Symbol('x') 
eq = int(row["scaleA"])*x**3 + int(row["scaleB"])*x**2 + int(row["scaleC"])*x + int(row["scaleD"]) 
y = real_roots(eq, x) # gives [CRootOf(...), ...] 

Giá trị của trường CRootOf có thể được đánh giá với bất kỳ độ chính xác nào bạn cần và không được chứa bất kỳ phần ảo nào. Ví dụ,

>>> [i.n(12) for i in real_roots(3*x**3 - 2*x**2 + 7*x - 9, x)] 
[1.07951904858] 

Lưu ý: Khi tôi gọi lại, giải quyết sẽ gửi lại rễ rằng nó đã không thể xác nhận đã gặp gỡ các giả định (tức là nếu chúng không được tìm thấy là sai đối với giả định sau đó họ được trả về). Ngoài ra, nếu bạn muốn sản lượng nhất quán hơn từ giải quyết, @PyRick, hãy đặt cờ dict=True.