2013-03-04 11 views
6

Używam sympy rozwiązać wielomian:Ignoruj ​​wyimaginowane korzenie w 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 jest lista możliwych rozwiązań. Muszę jednak zignorować te wyobrażone i wykorzystywać tylko prawdziwe rozwiązania. Chciałbym też, aby rozwiązanie było wartością, a nie wyrażeniem. Teraz wygląda na to:

[-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] 

Potrzebuję wartości ostatniego wyrażenia (-2.227756). Czy istnieją funkcje w sympy, aby to uprościć?

+4

SymPy nie jest najprawdopodobniej odpowiednią biblioteką do użycia, jeśli interesuje Cię tylko zmienna/podwójna aproksymacja korzenia. Jeśli używasz numpy/scipy, prawdopodobnie uzyskasz lepszą wydajność i prostszy kod. A jeśli wybierzesz sympy over numpy/scipy, ponieważ jest on mniejszy, możesz uzyskać jeszcze mniejszy z mpmath, który jest używany wewnątrz sympy do numerowania (arbitralnej precyzji nie ograniczonej przez maszynę). – Krastanov

Odpowiedz

0

Jak Krastonov wspomniał mpmath warunkiem łatwiejszą metodę:

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

Udało mi się po prostu zignorować rozwiązania zawierające znak "I" i użyć .evalf() do oceny wyrażenia. Kod jest teraz:

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

Lepszym sposobem odfiltrowania prawdziwych korzeni jest sprawdzenie ' root.is_real'. – asmeurer

9

Jeśli ustawisz x być prawdziwe, SymPy tylko daje realne rozwiązania

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

Próbuję rozwiązać równanie za pomocą tej metody, ale nadal zwraca wymyślone rozwiązania – Alex

+0

Czy używasz rozwiązania? Zauważ, że nowy 'rozwiązaćset' ignoruje założenia ustawione na Symbolach (użyj' solveset (domain = S.Reals) 'do rozwiązania w prawdziwej domenie.Jeśli używasz rozwiązania, jest to błąd, który powinien być [zgłoszony] (https: //github.com/sympy/sympy/issues/new) – asmeurer

+0

Próbowałem obu: rozwiązać, z założeniami, rozwiązać i rozwiązać zestaw z domeną = S.Reals. Rozwiązać po prostu pominięcie założeń dotyczących zmiennej, która ma zostać rozwiązana (jak rozwiązać), przybywając do rozwiązań w 30 sekund, podczas gdy zestaw układów z domeną nie był w stanie dotrzeć do rozwiązania w ciągu 20 minut.Czy to może być duplikat? (https://github.com/sympy/sympy/issues/9973) – Alex

0

solve() nie ma spójnego wyjścia dla różnych typów rozwiązań, należy użyć 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

To jest dokładnie ten rodzaj rzeczy, które real_roots jest dla i jest szczególnie zastosowanie do przypadku, w którym współczynniki są liczbami całkowitymi:

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(...), ...] 

Wartość przypadkach CRootOf mogą być oceniany według potrzebnej precyzji i nie powinien zawierać żadnej części urojonej. Na przykład,

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

Uwaga: O ile pamiętam, rozwiązywać odeśle korzenie, że nie był w stanie potwierdzić spełnione założenia (czyli jeśli nie zostały one uznane za fałszywe na założeniu, następnie są one zwracane). Ponadto, jeśli chcesz bardziej spójne wyjście z rozwiązania, @PyRick, ustaw flagę dict=True.