代码之家  ›  专栏  ›  技术社区  ›  user2657817

python中计数器的线性组合

  •  0
  • user2657817  · 技术社区  · 6 年前

    我有一些计数器对象,如下面表示等式的左侧和右侧:

    左手边: (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 回复  |  直到 6 年前
        1
  •  1
  •   hilberts_drinking_problem    6 年前

    这里有一个非常符合您方法的解决方案。

    1. 将每个计数器转换为向量,将不同的ID视为单独的维度。
    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)