#python #sympy
#питон #сочувствую
Вопрос:
Я хотел бы вернуть ноль за отсутствующий одночлен, но не смог найти никаких указателей в документации sympy. Мое намерение состоит в том, чтобы построить разреженный массив из нескольких выражений. Есть ли простой способ сделать это? МВЕ:
import sympy x, y, z = sympy.symbols('x, y, z') func_1 = 3 x 5 * y 2 * z func_2 = 1 x 2 * y expr_2 = [func_1, func_2] func_vars = [x, y, z] eqs = sympy.parallel_poly_from_expr(expr_2, func_vars) [[eqn.coeff_monomial(m) for m in eqn.monoms()][:-1] for eqn in eqs[0]] # gt;gt;gt; [[1, 5, 2], [1, 2]] # expected [[1,5,2],[1,2,0]]
Обновлено MWE с использованием indexedbase с нелинейной переменной на основе предложений smichr:
def get_coeffs(coeff_dict, func_vars): c = coeff_dict for i in list(c.keys()): b, _ = i.as_base_exp() if b == i: continue if b in c: raise ValueError('multiple generators with %s' % b) if any(k.has(b) for k in c): raise ValueError('cross terms detected with %s' % b) c[b] = c[i] return [coeff_dict[val] for val in func_vars] x = sympy.IndexedBase('x') func_1 = 3 x[0]**2 5 * x[1] 2 * x[2] func_2 = 1 x[0] 2 * x[1] expr_2 = [func_1, func_2] func_vars = [x[0], x[1], x[2]] ([get_coeffs(i.as_coefficients_dict(), func_vars) for i in expr_2]) # I get [[1, 5, 2], [1, 2, 0]]
Комментарии:
1. Я отмечаю, что ваши многочлены линейны в трех генераторах, что говорит о том, что вы вообще не хотите использовать многочлены (возможно, сделайте шаг назад и объясните, почему вы вообще хотите использовать многочлены). Если вы действительно хотите использовать многочлены, то как бы вы в целом решили, когда существуют нетривиальные одночлены, например
x**2*y
, какими должны быть записи в выходном списке?2. В основном я пытаюсь воспроизвести вывод функции Mathematica «Cofficientarrays», которая выдает массивы коэффициентов переменных vars в полиномах полиномов. Это дает список, содержащий разреженные объекты. Это также говорит о том, что для нелинейных уравнений m[i] не являются уникальными. Cofficientarrays по умолчанию присваивает ненулевые коэффициенты только одночленам, в которых переменные отображаются в том же порядке, что и vars.
Ответ №1:
Если вы работаете с линейными уравнениями, то linear_eq_to_matrix
можете работать с необработанными (неполигональными) выражениями, чтобы получить матрицу коэффициентов:
gt;gt;gt; linear_eq_to_matrix([i.as_expr() for i in eqs[0]],[x,y,z]) (Matrix([ [1, 5, 2], [1, 2, 0]]), Matrix([ [-3], [-1]]))
Этот as_coefficients_dict
метод мог бы быть лучшим выбором. И если у вас есть полномочия какой-либо переменной, то результирующий словарь может быть изменен для хранения оснований полномочий с тем же коэффициентом.
gt;gt;gt; x=IndexedBase('x') gt;gt;gt; eq=3 x[0]**2 5 * x[1] 2 * x[2] gt;gt;gt; eq.as_coefficients_dict() defaultdict(lt;class 'int'gt;, {1: 3, x[0]**2: 1, x[2]: 2, x[1]: 5}) gt;gt;gt; c=_ gt;gt;gt; for i in list(c.keys()): ... c[i.as_base_exp()[0]] = c[i] # set values bases of powers ... gt;gt;gt; [_[x[i]] for i in range(4)] # default dict will supply 0 [1, 5, 2, 0]
Комментарии:
1. Это похоже на то, что я хочу, но выдает ошибку, например «Ожидаю символа, но получил x[0]», когда я создаю базу данных с индексом » x » и использую x[0], x[1], x[2] вместо x, y, z. Подход, который я использовал, все еще работает в этом сценарии, но функция linear_eq_to_matrix выдает ошибку. Есть какие-нибудь предложения о том, как поступить в таком случае?
2.
symeqs = Tuple(*eqs[0]).xreplace(reps)
гдеreps = dict(zip((x[0], x[1], ....), numbered_symbols('s')))
тогда кормитьsymeqs
иlist(reps.values())
linear_eq_to_matrix
куда .3. Я попробовал это на более сложном линейном уравнении, и это сработало.
4. Привет, смичр, я подумал, что должен спросить, есть ли способ использовать этот подход, даже если у меня есть нелинейный термин, такой как x[0]**2, такой, что он игнорирует нелинейность и все равно возвращает коэффициент 3 x[0]**2 5 * x[1] 2 * x[2] как 1
5. абсолютно!!!. это была функция, в которой я нуждался. Gracias!
Ответ №2:
Если это просто обычный список, вы можете просто обработать его после обработки. Чтобы дополнить 2D-список x
буквами 0
s с правой стороны, вы можете просто сделать это:
width = max(map(len, x)) for row in x: row.extend([0] * (width - len(row)))
В принципе, вы получаете ширину всего объекта, находя максимальную ширину всех строк. Затем для каждой строки вы просто вставляете столько 0
букв s, сколько требуется после нее, чтобы она была правильной ширины.