【问题标题】:Combinatorics 1 to 1 mapping for Power Groups功率组的组合 1 对 1 映射
【发布时间】:2020-10-04 01:36:06
【问题描述】:

问题描述:


我正在制作一个函数,它为我提供了基于单个索引的多个描述符的特定组合的定义。我的输入是一组原始特征X = [feat0,feat1,feat2,feat3,feat4],一个要使用的权力列表pow = [1,2,3],以及一个组大小列表sizes = [1,3,5]。有效的输出可能如下所示:

  feat0^2 * feat4^3 * feat1^1

此输出有效,因为 feat0feat4feat1 存在于 X 中,它们的幂存在于 pow 中,并且组合的特征数在 sizes 中。

无效的边缘情况包括:

  1. X 中不存在的值,pow 中不存在的幂,sizes 中不存在组合大小
  2. 与另一个相同的组合无效:feat0^2 * feat1^3feat1^3 * feat0^2 相同
  3. 包含多个相同特征的组合无效:feat0^1 * feat0^3 * feat2^2 无效

在后台,我将这些分组编码为元组列表。所以feat0^2 * feat4^3 * feat1^1 将表示为[(0,2), (4,3), (1,1)],其中元组中的第一个元素是特征索引,第二个元素是幂。

问题:


我的问题是,如何创建特定组合到索引i 的一对一映射?我想获得可能组合的数量,并能够将整数 i 插入函数,并让该函数生成特定组合。像这样的:

X = [0.123, 0.111, 11, -5]
pow = [1,2,3]
sizes = [1,3]

#getting total number of combinations
numCombos = get_num_combos(X,pow,sizes)

#getting a random index corresponding to a grouping
i = random.randint(0, numCombos)

#getting grouping
grouping = generate_grouping(i, X, pow, sizes)

print(grouping)

导致类似

[(0,1), (1,2), (3,1)]

到目前为止,弄清楚不考虑各种边缘情况的一代并不太难,但我不知道如何解释边缘情况 2 和 3;确保i 的任何值在代数上都不会与i 的任何其他值等价,并且同一特征不会在分组中多次出现。

当前进展


#computes the n choose k of a list and a size
def get_num_groupings(n, k):
    return int(math.factorial(n)/(math.factorial(k)*math.factorial(n-k)))

import numpy as np
import bisect

i = 150

n = 5
m = 3
sizes = [1, 3, 5]

#computing the number of elements in each group length
numElements = [m**k * get_num_groupings(n, k) for k in sizes]

#index bins for each group size
bins = list(np.cumsum(numElements))[:-1]

#getting the current group size
binIdx = bisect.bisect_left(bins,i)
curSize = sizes[binIdx]

#adding idx 0 to bins
bins = [0]+bins

#getting the location of i in the bin
z = i - bins[binIdx]

#getting the product index and combination rank
pi = z // m**k
ci = z % m**k

#getting the indexes of the powers
pidx = [(pi // m**(curSize - (num+1)))%m for num in range(curSize)]

#getting the indexes of the features
#TODO cidx = unrank(i, range(n))

这是基于Mad Physicist 的回答。虽然我还没有弄清楚如何获得cidx。为了我自己的理解,重写了一些变量名。据我所知,这种实现是通过在逻辑上分离变量组合以及它们各自拥有的权力来实现的。到目前为止,我可以从索引i 获得权力,一旦unrank 被熨平,我应该能够获得使用特征的索引。

【问题讨论】:

  • 显示你到目前为止的发现。您可能需要自定义排名和取消排名功能
  • 完成。哇,这是一个非常长的条目

标签: python algorithm data-science combinatorics


【解决方案1】:

让我们看一个与想要什么密切相关的稍微不同的问题:生成所有可能的有效组合。

如果您选择大小和幂,则查找所有可能的combinations 特征相当简单:

from itertools import combinations, product

n = len(X)
m = len(powers)
k = size = ...  # e.g. 3
pow = ...   # e.g. [1, 2, 3]

特征的唯一组合的迭代器由下式给出

def elements(X, size, pow):
    for x in combinations(X, size):
        yield sum(e**p for p, e in zip(pow, x))

等效的单线他会

(sum(e**p for p, e in zip(pow, x)) for x in combinations(X, size))

这个生成器正好有n choose k 独特的元素。根据定义,这些元素满足您的所有条件。

现在您可以遍历所有可能的大小和product 的幂来获得所有选项:

def all_features(X, sizes, powers):
    for size in sizes:
        for pow in product(powers, repeat=size):
            for x in combinations(X, size):
                yield sum(e**p for p, e in zip(pow, x)) 

元素总数是m**k * n choose k中每个k的总和。

现在您已经计算了可能性,您可以使用combinatorial number system 计算元素到索引的映射,反之亦然。 here 显示了组合的示例排序和取消排序函数。您可以在调整大小和电源箱的索引后使用它们。

为了说明我的意思,假设您具有三个功能(在链接的答案中给出):

  1. choose(n, k)计算n选择k
  2. rank(combo) 接受特定commination 的有序索引并返回排名。
  3. unrank(ind, k) 接受排名和大小,并返回相应组合的 k 索引。

然后,您可以计算每个尺寸组的偏移量以及该组内每个幂的步长。让我们通过 n = 5m = 3sizes = [1, 3, 5] 来完成您的具体示例。

每种尺寸的元素数量由下式给出

elements = [m**k * choose(n, k) for k in sizes]

可能的安排总数为sum(elements)

3**1 * choose(5, 1) + 3**3 * choose(5, 3) + 3**5 * choose(5, 5) = 3 * 5 + 27 * 10 + 243 * 1 = 15 + 270 + 243 = 528

累积和对于索引和元素之间的转换很有用:

cumsum = [0, 15, 285]

当你得到一个索引时,你可以使用bisect检查它属于哪个bin。

假设您获得了index = 55。因为15 < 55 < 285,你的偏移量是15,size = 3。在size = 3 组中,您的偏移量为z = 55 - 15 = 40

k = 3 组内,有m**k = 3**3 = 27 电源产品。产品索引为pi = z // m**k,组合排名为ci = z % m**k

所以功率指数由下式给出

pidx = [(pi // m**(k - 1)) % m, (pi // m**(k - 2)) % m, ...]

同样,组合的索引由下式给出

cidx = unrank(ci, k)

您可以使用类似的方法将所有这些索引转换为值

sum(X[q]**powers[p] for p, q in zip(pidx, cidx))

【讨论】:

  • 顺便说一句,我想我应该注意,我一直在努力思考你的回答,感觉就像几个小时,每次我去写一个问题,你在我之前回答它得到机会。一定是终结者的眼睛。真的,虽然这个答案很棒
  • @Warlax56。对不起,我在的地方已经很晚了。答案是一团糟,有机会我会清理它
  • @Warlax56。星期一我会给你一些东西。这些函数在链接的问题中具有不同的名称,但它们是相同的函数。与他们一起玩以确定哪个是哪个。
  • answered a previous question 与您链接的那个有点相似。
  • @Warlax56。我会尽我所能,但链接的问题显示了您需要的三个功能,名称略有不同。我已经在这里向您展示了其余的内容。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-11-07
  • 1970-01-01
  • 2010-09-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-08-17
相关资源
最近更新 更多