2015-01-24 2 views
2

У меня есть функция с именем f = 0.5/(z-3). Я хотел бы знать, что бы коэффициенты p и q были, если f было записано в следующем виде: q/(1-p * z), но, к сожалению, функция sympy match возвращает None. Я делаю что-то неправильно? или какой правильный способ сделать что-то подобное? Вот код:Соответствующие коэффициенты в Python SymPy Pattern Matching

z = symbols('z') 
p, q = Wild('p'), Wild('q') 
print (0.5/(z-3)).match(q/(1-p*z)) 

EDIT: Мой ожидается ответ: Q = -1/6, р = 1/3

Один из способов конечно

p, q = symbols('p q') 
f = 0.5/(z-3) 
print solve(f - q/(1-p*z), p, q,rational=True) 

Но Я не знаю, как это сделать при сопоставлении шаблонов, или если он способен делать что-то подобное.

Заранее спасибо =)

+0

@NPE Я отредактировал вопрос –

+1

'q/(1-p * z)' равно '(q/p)/(1/p-z)' если 'p! = 0'. И '(0.5/(z-3)). Match ((q/p)/(1/p-z), old = True)' возвращает '{q_: -0.166666666666667, p_: 1/3}'. Однако я не знаю, как найти это преобразование алгоритмически. – unutbu

+0

Использование 'solve' кажется хорошим методом для меня. – asmeurer

ответ

2

Если вы начинаете путем преобразования в линейной форме,

1/(2*z - 6) == q/(1 - p*z) 
           # multiply both sides 
           # by (2*z - 6) * (1 - p*z) 
1 - p*z == q * (2*z - 6) 

затем

from sympy import Eq, solve, symbols, Wild 

z = symbols("z") 
p,q = symbols("p q", cls=Wild) 

solve(Eq(1 - p*z, q*(2*z - 6)), (p,q)) 

дает

{p_: 1/3, q_: -1/6} 

, как ожидалось.

Edit: Я нашел несколько иной подход:

  1. solve(Eq(f, g)) эквивалентно solve(f - g) (неявно == 0)

  2. Мы можем уменьшить f - g как simplify(f - g), но по умолчанию она Безразлично ничего не делать, потому что полученное уравнение более чем в 1,7 раза длиннее исходного (значение по умолчанию для аргумента ratio). Если указать более высокое соотношение, как simplify(f - g, ratio=5), мы получаем

    >>> simplify(1/(2*z-6) - q/(1-p*z), ratio=5) 
    (z*p_ + 2*q_*(z - 3) - 1)/(2*(z - 3)*(z*p_ - 1)) 
    
  3. Это теперь в форме решатель будет заниматься:

    >>> solve(_, (p,q)) 
    {p_: 1/3, q_: -1/6} 
    
+0

Разве это не то же самое решение, о котором я упомянул в вопросе? –

+1

@AhmadSiavosh: Я переформатировал уравнения, прежде чем подключать их к решателю, преобразовывая их из нелинейного в линейный (в терминах z). Этого достаточно, чтобы позволить решателю справиться с ними и вернуть символический, а не числовой ответ. К сожалению, я не уверен, как сделать это автоматически, но я все еще читаю ;-). –

+0

Правильно, спасибо –

1

модели согласовань SymPy в делает только минимальный алгебраические манипуляции, чтобы соответствовать вещам. В этом случае он не соответствует, потому что в знаменателе нет 1. Лучше было бы соответствовать a/(b + c*z) и манипулировать a, b и c в p и q. solve может показать вам точную формулу:

In [7]: solve(Eq(a/(b + c*z), q/(1 - p*z)), (q, p)) 
Out[7]: 
⎧ -c  a⎫ 
⎨p: ───, q: ─⎬ 
⎩ b  b⎭ 

Наконец, это всегда хорошая идея использовать exclude при построении Wild объекта, как Wild('a', exclude=[z]). В противном случае вы можете получить непредвиденное поведение, например

In [11]: a, b = Wild('a'), Wild('b') 

In [12]: S(2).match(a + b*z) 
Out[12]: 
⎧   2⎫ 
⎨a: 0, b: ─⎬ 
⎩   z⎭ 

Это технически правильно, но, вероятно, не то, что вы хотите.

+0

Спасибо, часть об «исключении» очень помогла. –