【问题标题】:Fast response for subset queries子集查询的快速响应
【发布时间】:2017-01-25 00:58:04
【问题描述】:

我有一个包含 10,000 个从 1 到 1,000 的整数向量的数据库。每个向量的长度可以达到 1,000。例如,它可能如下所示:

vec1: 1 2 56 78
vec2: 23 34 35 36 37 38
vec3: 1 2 3 4 5 7
vec4: 2 3 4 6 100
...
vec10000: 13 234

现在,我想以快速响应特定类型请求的方式存储此数据库。每个请求都会以整数向量的形式出现,最长可达 10,000:

query: 1 2 3 4 5 7 56 78 100

响应应该是作为该查询字符串子集的向量的索引。例如,在上面的列表中,只有vec1vec3 是查询的子集,所以这种情况下的响应应该是

response: 1 3

此数据库不会更改,因此您可以以任何可能的方式对其进行预处理。您可以指定查询也来自任何协议,只要信息相同。例如,它可以是排序列表或布尔表。

对数据库和查询进行编码以实现最高响应率的最佳策略是什么?

【问题讨论】:

  • 任何向量的内容可以是什么,即。向量中的最大数量?
  • @vish4071 "integers range from 1 to 1,000" -- 这是数据库和查询中的字母表。
  • 矢量内容是唯一的吗? IE。它们可以作为集合存储吗?
  • @wflynny 绝对。您可以将它们视为集合,因为重复的元素被视为一个。
  • 这是 Python 问题还是数据库问题?您想知道如何构建数据库以便可以查询(例如使用 SQL)并返回子集向量的索引,还是想知道如何构建您在 Python 中描述的数据?

标签: database algorithm data-structures


【解决方案1】:

由于您使用的是python,这种方法看起来很简单。 (对于任何其他语言,它也是可实现的,但将包括模运算等。)

因此,对于从 1 到 1000 的每个数字,为​​其分配一个素数。所以,

1 => 2
2 => 3
3 => 5
4 => 7
...
...
25 => 97
...
...
1000 => 7919

对于每一个集合,用它的值作为集合中所有值的乘积的哈希函数。

例如。如果你的向量,vec-x = {1,2,5,25}, vec-x = 2 * 3 * 11 * 97

同样,您的查询向量可以按上述方式计算。设它的值为 Q。

如果 Q % vec-i == 0,它是一个子集,否则不是。

【讨论】:

  • 谢谢!来考虑一下。我不使用素数和乘法,而是使用位和and 运算(确切地说是and not)怎么样?
  • 这有什么帮助。我没有得到你的方法。
  • 和你的方法差不多。对于预处理,将整数向量转换为一个大整数。在二进制中,该整数将在向量指定的那些位置具有 1。 (例如,[1 2 5] 将变为 1011,即十进制的 19。)
  • 我们对查询做同样的事情,将其转换为一个大整数,特定位置为 1,其余为 0。
  • 在确认A 是否是B 的子集时,只需执行A and (not B)。如果此值不为 0,则 A 不是 B 的子集。
【解决方案2】:

如何将向量列表预处理为指示矩阵并使用矩阵乘法,例如:

import numpy as np

# generate 10000 random vectors with length in [0-1000]
# and elements in [0-1000]
vectors = [np.random.randint(1000, size=n)
           for n in np.random.randint(1000, size=10000)]

# generate indicator matrix
database = np.zeros((10000, 1000), dtype='int8')
for i, vector in enumerate(vectors):
    database[i, vector] = 1
lengths = database.sum(axis=1)

def query(ints):
    tmp = np.zeros(1000, dtype='int8')
    tmp[ints] = 1
    return np.where(database.dot(tmp) == lengths)[0]

数据库行和转换后的查询的点积将等于查询中行的元素数。如果这个数字等于行中元素的总数,那么我们找到了一个子集。请注意,这使用基于 0 的索引。

这是为您的示例数据修改的

vectors = [[1, 2, 56, 78],
           [23, 34, 35, 36, 37, 38],
           [1, 2, 3, 4, 5, 7],
           [2, 3, 4, 6, 100],
           [13, 234]]
database = np.zeros((5, 1000), dtype='int8')
for i, vector in enumerate(vectors):
    database[i, vector] = 1
lengths = database.sum(axis=1)

print query([1, 2, 3, 4, 5, 7, 56, 78, 100])
# [0, 2] 0-based indexing

【讨论】:

    猜你喜欢
    • 2012-02-16
    • 2017-11-12
    • 1970-01-01
    • 1970-01-01
    • 2018-05-02
    • 2013-08-31
    • 2013-09-20
    • 1970-01-01
    • 2022-11-29
    相关资源
    最近更新 更多