两个二进制表示的交叉
Crossover of two binary representations
我正在尝试快速实现以下问题,理想情况下它可以在 numba 函数中运行。问题如下:我有两个随机整数 a
& b
并考虑它们的长度 L
的二进制表示,例如
L=4: a=10->1010
, b=6->0110
.
这是输入函数的信息。然后我在相同的随机位置将两个二进制表示分成两个并融合两个结果之一,例如
L=4: a=1|010
, b=0|110
---> c=1110
或 0010
.
两个结果中的一个以相等的概率被选择,这就是函数的结果。剪切发生在二进制表示的第一个 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
你损失了 很多 的字符串和整数转换时间。请尝试使用位操作。屏蔽您想要的项目并在没有所有转换的情况下构建输出。试试这些步骤:
- size = [较大数字的长度]有很多方法可以得到这个。
- 制作遮罩模板,
size
1位。
- 选择你的随机位置,
pos
randint
是一个糟糕的 anem,因为它隐藏了你正在使用的功能。
- 制作两个掩码:l_mask = mask << pos; r_mask = 面具 >> 位置。这为您的输入提供了两个互斥且详尽的 bit-maps。
- 掷随机硬币,50-50 的机会。 < 0.5 结果将是 ...
- (a & l_mask) | (b & 掩码)
- 对于 >= 0.5 结果,在该表达式中切换
a
和 b
。
您可以通过意识到不需要“人类可读”的二进制表示来执行二进制操作来改进您的代码。
例如,创建遮罩:
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
我正在尝试快速实现以下问题,理想情况下它可以在 numba 函数中运行。问题如下:我有两个随机整数 a
& b
并考虑它们的长度 L
的二进制表示,例如
L=4: a=10->1010
, b=6->0110
.
这是输入函数的信息。然后我在相同的随机位置将两个二进制表示分成两个并融合两个结果之一,例如
L=4: a=1|010
, b=0|110
---> c=1110
或 0010
.
两个结果中的一个以相等的概率被选择,这就是函数的结果。剪切发生在二进制表示的第一个 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
你损失了 很多 的字符串和整数转换时间。请尝试使用位操作。屏蔽您想要的项目并在没有所有转换的情况下构建输出。试试这些步骤:
- size = [较大数字的长度]有很多方法可以得到这个。
- 制作遮罩模板,
size
1位。 - 选择你的随机位置,
pos
randint
是一个糟糕的 anem,因为它隐藏了你正在使用的功能。 - 制作两个掩码:l_mask = mask << pos; r_mask = 面具 >> 位置。这为您的输入提供了两个互斥且详尽的 bit-maps。
- 掷随机硬币,50-50 的机会。 < 0.5 结果将是 ...
- (a & l_mask) | (b & 掩码)
- 对于 >= 0.5 结果,在该表达式中切换
a
和b
。
您可以通过意识到不需要“人类可读”的二进制表示来执行二进制操作来改进您的代码。
例如,创建遮罩:
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