Python 如何使这种广度优先搜索更快?

Python 如何使这种广度优先搜索更快?,python,python-3.x,performance,search,Python,Python 3.x,Performance,Search,我有一个搜索算法,它寻找加法和乘法函数的组合,以从特定的数字范围中获得特定的数字范围。它正在搜索最短的程序,一个类似于AAMMA的程序,其中初始数字被添加、添加、乘、乘、添加,其中结束数字在r到s的范围内。它必须适用于起始范围p到q的每个数字 输入是a和m,即为每个函数添加和乘以(num+a)、(num*m)的值。我所做的是尝试所有函数的组合,直到找到一个有效的,如果分支太大,就停止它。如果我发现“程序”有效,我会在起始范围内的所有其他数字上尝试该程序。它会一直这样做,直到找到没有到达范围的分支

我有一个搜索算法,它寻找加法和乘法函数的组合,以从特定的数字范围中获得特定的数字范围。它正在搜索最短的程序,一个类似于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'