Линейная комбинация счетчиков в Python - PullRequest
0 голосов
/ 09 декабря 2018

У меня есть несколько объектов Counter, как показано ниже, представляющих левую и правую части уравнения:

Левая сторона: (Counter({22.99: 1}), Counter({12.011: 2, 15.999: 2}), Counter({12.011: 7}))

Правая сторона: Counter({12.011: 15, 15.999: 1})

Моя цель - найти общие элементы между обеими сторонами уравнения, а затем определить линейную комбинацию левой, которая может дать мне правую сторону.

В приведенном выше примере уравнение для решения будет выглядеть следующим образом:

2A*12.011 + 7B*12.011 = 15W*12.011

2A*15.999 = W*15.999

Я предполагаю, что эта операция будет включать преобразование словаря счетчика в матрицу для решения системы линейных уравнений, но я застряло том, как это сделать.

1 Ответ

0 голосов
/ 09 декабря 2018

Вот решение, очень похожее на ваш подход.

  1. Преобразование каждого счетчика в вектор, рассматривая различные идентификаторы как отдельные измерения.
  2. Решите систему линейныхуравнения.

from collections import Counter
import numpy as np
from scipy import linalg


lhs = (Counter({22.99: 1}), Counter({12.011: 2, 15.999: 2}), Counter({12.011: 7}))
rhs = Counter({12.011: 15, 15.999: 1})

# get unique keys that occur in any Counter in 2D
# each unique key represents a separate dimension
ks = np.array([*set().union(rhs, *lhs)])[:, None]

# get a helper function to convert Counters to vectors
ctr_to_vec = np.vectorize(Counter.__getitem__)

lhs_mat = ctr_to_vec(lhs, ks)
rhs_vec = ctr_to_vec(rhs, ks)

# compute coefficients solving the least-squares problem
coefs = linalg.lstsq(lhs_mat, rhs_vec)[0]

is_linear_comb = np.allclose(lhs_mat @ coefs, rhs_vec)
...