Python 如何使这种广度优先搜索更快?
我有一个搜索算法,它寻找加法和乘法函数的组合,以从特定的数字范围中获得特定的数字范围。它正在搜索最短的程序,一个类似于AAMMA的程序,其中初始数字被添加、添加、乘、乘、添加,其中结束数字在r到s的范围内。它必须适用于起始范围p到q的每个数字 输入是a和m,即为每个函数添加和乘以(num+a)、(num*m)的值。我所做的是尝试所有函数的组合,直到找到一个有效的,如果分支太大,就停止它。如果我发现“程序”有效,我会在起始范围内的所有其他数字上尝试该程序。它会一直这样做,直到找到没有到达范围的分支而不经过检查为止 我知道搜索不是非常典型,但我不认为有重复的可能性,所以我没有包括一个找到的列表 它适用于较小的范围和输入,如Python 如何使这种广度优先搜索更快?,python,python-3.x,performance,search,Python,Python 3.x,Performance,Search,我有一个搜索算法,它寻找加法和乘法函数的组合,以从特定的数字范围中获得特定的数字范围。它正在搜索最短的程序,一个类似于AAMMA的程序,其中初始数字被添加、添加、乘、乘、添加,其中结束数字在r到s的范围内。它必须适用于起始范围p到q的每个数字 输入是a和m,即为每个函数添加和乘以(num+a)、(num*m)的值。我所做的是尝试所有函数的组合,直到找到一个有效的,如果分支太大,就停止它。如果我发现“程序”有效,我会在起始范围内的所有其他数字上尝试该程序。它会一直这样做,直到找到没有到达范围的分支
Problem3("1 2 2 3 10 20")
但是对于更大的范围,我的测试用例需要很长时间
Problem3("8 13 28 91 375383947 679472915")
我还没看到完整的。从这里开始,我最好的方法是什么,多线程(希望不是),以某种方式使我的内部函数更快,或者干脆放弃这种方法
def Problem3(s):
a,m,p,q,r,s = list(map(int, s.split(" ")))
print(str(a) + "-C-" + str(m) + " processor")
print("Input guarenteed between " + str(p) + " and " + str(q))
print("Output is real number between " + str(r) + " and " + str(s))
open_set = queue.Queue()
# curr path depth
open_set.put([p, "", 0])
while not open_set.empty():
subroot = open_set.get()
multiCurr = subroot[0] * m
addCurr = subroot[0] + a
depth = subroot[2] + 1
if r <= addCurr <= s:
truePath = True
#If we find a working path, we need to check if it works for the other things
path = subroot[1] + "A"
for x in range(p, q+1):
for op in path:
if op == "A":
x += a
if op == "M":
x *= m
if r <= x <= s:
pass
else:
truePath = False
break
if truePath:
print("Found " + path + " at depth " + str(depth) + " with starting number " + str(p) + ", output " + str())
if r <= multiCurr <= s:
truePath = True
path = subroot[1] + "M"
for x in range(p, q+1):
for op in path:
if op == "A":
x += a
if op == "M":
x *= m
if r <= x <= s:
pass
else:
truePath = False
break
if truePath:
print("Found " + path + " at depth " + str(depth) + " with starting number " + str(p) + ", output " + str())
if addCurr > s and multiCurr > s:
pass
elif multiCurr > s:
open_set.put([addCurr, subroot[1] + "A", depth])
elif addCurr > s:
open_set.put([multiCurr, subroot[1] + "M", depth])
else:
open_set.put([multiCurr, subroot[1] + "M", depth])
open_set.put([addCurr, subroot[1] + "A", depth])
def问题3:
a、 m,p,q,r,s=list(map(int,s.split(“”))
打印(str(a)+“-C-”+str(m)+“处理器”)
打印(“输入保证在“+str(p)+”和“+str(q)”之间”)
打印(“输出为“+str(r)+”和“+str(s)”之间的实数)
open_set=queue.queue()
#当前路径深度
open_set.put([p,”,0])
未打开时\u set.empty():
subroot=open_set.get()
multiCurr=副轨道[0]*m
addCurr=副轨道[0]+a
深度=副行程[2]+1
如果r您不需要测试范围(p,q+1)
序列中的每个值。您只需要测试p
和q
。如果它适用于最小值和最大值,那么它将适用于这两者之间的所有值,因为问题已经简化为乘法和加法。实际上,您只需测试程序(q)
的进度,将其保持在s
以下,直到您创建了将程序(p)
置于r
或以上的最短程序
然而,对于呼吸优先搜索来说,这并不是一个大问题;你的第二个例子需要测试17.6万亿个可能的州;最短的解决方案是44个字符长,因此呼吸优先搜索将探索2**44个州,准确地说是17592186044416!即使使用像C这样的编译编程语言,也需要很长很长时间才能找到使用这种搜索的解决方案。相反,您可以使用一点数学知识生成字符串
您可以使用int(math.log(s//q,m))
计算此处所需的最大乘法次数,这是在q
开始时,您可以使用m
乘法的次数,但仍然低于s
。你不能再使用乘法了!使用math.ceil(math.log(r/p,m))
可以找到将p
置于或高于r
的最小乘法次数。要最小化程序长度,请从这两个数字中选择较低的值
然后,在每个M
乘法之前,开始拟合A
加法。通过将i
作为要跟随的M
字符数,然后将r
和s
除以M**i
来实现。这些信息通知将数字a
添加到p
和q
以及随后的乘法使其最接近r
和s
;通过与当前p
和q
的差异,您可以计算在此处插入的A
字符的最小数量,以保持在[r,s]
范围内。对于p
,向上取整;对于q
,向下取整
对后续的M
操作重复此步骤,每次使用结果更新p
和q
值:
import math
def problem3(s):
a, m, p, q, r, s = map(int, s.split())
p_mult = math.ceil(math.log(math.ceil(r / p), m))
q_mult = int(math.log(s // q, m))
mult = min(p_mult, q_mult)
program = []
for i in range(mult, -1, -1):
p_additions = math.ceil((math.ceil(r / (m ** i)) - p) / a)
q_additions = ((s // (m ** i)) - q) // a
additions = min(p_additions, q_additions)
program += [additions * 'A']
if i:
p, q = (p + (additions * a)) * m, (q + (additions * a)) * m
program += ['M']
return ''.join(program)
这是一个封闭形式的解决方案,无需搜索。结果保证是最短的:
>>> problem3("1 2 2 3 10 20")
'AMM'
>>> problem3("8 13 28 91 375383947 679472915")
'AAAAAAMAAMAAAAAAAAAAAMAAAAAMAAAMAAAAMAAAAAAA'