给定两个函数,找到一个阈值,使得一个总是大于另一个

时间:2019-12-26 21:33:34

标签: python recursion proof

我已经在Python中实现了以下两个功能:

def c(m, n):
    if m == 0:
        return 0
    elif m == 1 and n >= 0:
        return n**2+n+1
    elif m > 1 and n == 0:
        return c(m-1, 1)
    elif m > 1 and n > 0:
        return c(m-1, c(m, n-1))

def d(n):
    exp_num = n-1
    result = 2
    while exp_num != -1:
        result = result**2
        exp_num -= 1
    final_result = 2**result
    return final_result

其中输入mn都是自然数。我被要求找到一个x,这样对于所有数字y >= xc(y,y) > d(y)

一些输入和输出:

c(1, 1) = 3

c(2, 2) = 183

d(1) = 16

d(2) = 65536

d(3) = 115792089237316195423570985008687907853269984665640564039457584007913129639936

您可以看到d的增长速度远远超过c。我该如何解决这个问题?任何帮助将非常感激。

1 个答案:

答案 0 :(得分:1)

函数c是Ackermann–Péter function的变体。

它之所以成名,是因为它不是Primitive Recursive,在这里,它的目的是意味着随着数量变得非常大,它很快就会用完堆栈空间。

问题是找到最小值x,使得y> = x时c(y,y)> d(y)。

我们认为这是c(3,3),但无法计算。我们确实计算了1和2:

d(1)= 16,d(2)= 65536,d(3)= 115792089237316195423570985008687907853269984665640564039457584007913129639936

c(1)= 3,c(2,2)= 183,c(3,3)=?

由于它不是原始递归的,因此c(3,3)难以计算(即耗尽堆栈空间)。但是,我们可以获取一个较低的 通过限制函数定义中的递归。

操作如下。

# Will use Memoization which eliminates repeated calculations in recursive functions
class Memoize:
    def __init__(self, fn):
        self.fn = fn
        self.memo = {}

    def __call__(self, *args):
        if args not in self.memo:
            self.memo[args] = self.fn(*args)
        return self.memo[args]

@Memoize
def c(m, n, cnt = 0, MAX_RECURSION = 20):
    " Refactor function c to have a max recursion depth "

    if cnt > MAX_RECURSION:
        return 0   # We know the return value is always >= 0, but normally
                   # much larger.  By quitting early and returning zero we are
                   # ensuring our final computation will be smaller than it would
                   # otherwise if we had not limited the recurison depth
                   #

    if m == 0:
        return 0
    elif m == 1 and n >= 0:
        return n**2+n+1
    elif m > 1 and n == 0:
        return c(m-1, 1, cnt+1)
    elif m > 1 and n > 0:
        return c(m-1, c(m, n-1, cnt+1), cnt+1)

def d(n):
    exp_num = n-1
    result = 2
    while exp_num != -1:
        result = result**2
        exp_num -= 1
    final_result = 2**result
    return final_result


value_d = d(3)
value_c = c(3, 3)

print('Number of digits in d(3) is {}'.format(len(str(value_d))))
#>>> Number of digits in d(3) is 78

print('Number of digits in c(3, 3) is {}'.format(len(str(value_c))))
#>>>Number of digits in c(3, 3) is 74176

因此,我们看到c(3,3)比d(3)多了约1K位数。自从我们在计算c(3,3)的早期就停止了递归以来,情况将会更加严重。