【问题标题】:Crossover of two binary representations两个二进制表示的交叉
【发布时间】:2021-02-13 09:01:56
【问题描述】:

我正在尝试快速实现以下问题,理想情况下它可以在 numba 函数中工作。问题如下:我有两个随机整数ab 并考虑它们的二进制表示长度L,例如

L=4: a=10->1010, b=6->0110.

这是输入函数的信息。然后我在同一个随机位置将两个二进制表示一分为二,并融合两个结果之一,例如

L=4: a=1|010b=0|110 ---> c=11100010

以相等的概率选择两个结果中的一个,这就是函数的结果。切割发生在二进制表示的第一个 1/0 和最后一个 0/​​1 之间。

这是我目前的代码:

def func(a,b,l):
    bin_a = [int(i) for i in str(bin(a))[2:].zfill(l)]
    bin_b = [int(i) for i in str(bin(b))[2:].zfill(l)]
    randint = random.randint(1, l - 1)
    print("randint", randint)
    if random.random() < 0.5:
        result = bin_a[0:randint]+bin_b[randint:l]
    else:
        result = bin_b[0:randint] + bin_a[randint:l]
    return result

我感觉可能有很多我没有想到的解决这个问题的捷径。此外,我的代码在 numba 中不起作用:/。感谢您的帮助!

编辑:这是我的代码的更新,感谢 Prunes 的帮助!它也可以用作 numba 函数。如果没有进一步的改进,我会关闭这个问题。

def func2(a,b,l):
    randint = random.randint(1, l - 1)
    print("randint", randint)

    bitlist_l = [1]*randint+[0]*(l-randint)
    bitlist_r = [0]*randint+[1]*(l-randint)
    print("bitlist_l", bitlist_l)
    print("bitlist_r", bitlist_r)
    l_mask = 0
    r_mask = 0
    for i in range(l):
        l_mask = (l_mask << 1) | bitlist_l[i]
        r_mask = (r_mask << 1) | bitlist_r[i]
    print("l_mask", l_mask)
    print("r_mask", r_mask)
    if random.random() < 0.5:
        c = (a & l_mask) | (b & r_mask)
    else:
        c = (b & l_mask) | (a & r_mask)
    return c

【问题讨论】:

  • 如果您不确定代码效率低下的地方,那么您需要对其进行分析。就目前而言,这个问题不再适用于 Stack Overflow。相反,它会转到 StackExchange.CodeReview .... 但请先阅读他们的发布指南。

标签: python numpy numba


【解决方案1】:

在字符串和 int 之间转换会损失 很多 时间。请尝试位操作。屏蔽您想要的项目并在不进行所有转换的情况下构建输出。请尝试以下步骤:

  • size = [以位为单位的较大数字的长度] 有很多方法可以得到这个。
  • 制作掩码模板,size 1-bits。
  • 选择你的随机位置,pos randint 是一个糟糕的问题,因为它会影响你正在使用的功能。
  • 制作两个掩码:l_mask = mask > 位置。这为您的输入提供了两个互斥且详尽的位图。
  • 翻转你的随机硬币,50-50 的机会。
  • (a & l_mask) | (b & rmask)
  • 对于 >= 0.5 结果,在该表达式中切换 ab

【讨论】:

  • 谢谢,但是如何跳过转换?据我了解,Mask 是一个布尔列表/数组,我可以将其应用于二进制列表,但我仍然需要创建它?
  • 掩码可以是简单的int,2^size-1
  • 谢谢,我已经更新了我的帖子。我不确定是否仍然存在效率低下的问题。也许你可以看看:)
【解决方案2】:

您可以通过意识到您不需要“人类可读”的二进制表示来执行二进制操作来改进您的代码。

例如,创建掩码:

m = (1<<randompos) - 1

交叉可以这样完成:

c = (a if coinflip else b) ^ ((a^b)&m)

仅此而已。

完整示例:

# create random sample
a,b = np.random.randint(1<<32,size=2)
randompos = np.random.randint(1,32)
coinflip = np.random.randint(2)
randompos
# 12
coinflip
# 0

# do the crossover
m = (1<<randompos) - 1
c = (a if coinflip else b) ^ ((a^b)&m)
 
# check
for i in (a,b,m,c):
    print(f"{i:032b}")
 
# 11100011110111000001001111100011
# 11010110110000110010101001111011
# 00000000000000000000111111111111
# 11010110110000110010001111100011

【讨论】:

  • 哦,哇,我明白了。这确实改善了计算时间。谢谢:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-08-23
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多