【发布时间】:2016-02-17 20:10:56
【问题描述】:
我希望能够以编程方式生成一组给定长度的二进制序列,同时避免任何两个序列之间的相似性。 我将在两个序列之间定义“相似”:
如果序列 A 可以通过位移 A(非循环)和填充 0 来转换为序列 B(或 B 到 A),则 A 和 B 是相似的(note:bit-仅允许在 一个 序列上进行移位,否则两者总是可以移位到仅包含 0 的序列)
例如:A = 01010101B = 10101010C = 10010010
在此示例中,A 和 B 相似,因为 A 的一次左移会导致 B (A 不相似,因为其中一个的位移不会导致另一个。
如果没有大小为 2 的子集相似,则定义的序列集合是不相似的。
我相信对于给定的序列长度可能有多个集合,并且大概集合的大小将明显小于总可能性(总可能性 = 2 ^ 序列长度)。
我需要一种方法来为给定的序列长度生成一个集合。是否存在可以实现此目的的算法?一次选择一个序列并检查所有先前选择的序列对于我的用例来说是不可接受的(但如果不存在更好的方法可能必须这样做!)。
我尝试根据素数和黄金比例生成整数集,然后转换为二进制。这似乎是一种可行的方法,但我无法让它按预期工作。
更新:我用 C# 编写了一个函数,它使用素数模来生成集合但没有成功。我也尝试过使用斐波那契数列,它找到了一个几乎不同的集合,但与可能性的数量相比,它的大小非常小:
private List<string> GetSequencesFib(int sequenceLength)
{
var sequences = new List<string>();
long current = 21;
long prev = 13;
long prev2 = 8;
long size = (long)Math.Pow(2, sequenceLength);
while (current < size)
{
current = prev + prev2;
sequences.Add(current.ToBitString(sequenceLength));
prev2 = prev;
prev = current;
}
return sequences;
}
这会生成一组大小为 41 的序列,它们的相似度大约为 60% (sequenceLength = 32)。它从 21 开始,因为较低的值产生的序列大多为 0,与任何其他序列相似。
通过将相似性条件放宽到只允许少量的连续位移,不同序列的比例接近 100%。这在我的用例中可能是可以接受的。
更新 2:
我已经按照 DCHE 的建议实现了一个函数,通过选择所有大于给定序列长度最大值一半的奇数:
private static List<string> GetSequencesOdd(int length)
{
var sequences = new List<string>();
long max = (long)(Math.Pow(2, length));
long quarterMax = max / 4;
for (long n = quarterMax * 2 + 1; n < max; n += 2)
{
sequences.Add(n.ToBitString(length));
}
return sequences;
}
根据我的要求,这会产生一个完全不同的集合。我可以理解为什么这在数学上也有效。
【问题讨论】:
-
确切的非相似性要求是什么?您可以通过随机创建一个序列来轻松生成序列,除了 MSB 和 LSB 必须为 1,然后使用您喜欢的任何策略(例如,简单的情况:递增计数器并将其与中间位异或)多次翻转中间的位有必要的。 MSB 和 LSB 为 1 保证任何生成值的移位量都不会与任何其他值相似。但在这种情况下,即使在技术上满足您的要求,序列也会“看起来非常相似”。
-
@Jon 接收到的序列有可能被移位并且前导位或尾随位丢失(归零)。序列需要唯一标识。通过最初根据上述定义选择可能的序列,我希望避免错误识别。我将尝试实施您的建议并稍后更新。需要一个可行的实现,但我也对问题背后的数学非常感兴趣!
标签: c# algorithm binary sequence