简体   繁体   中英

Fibonacci-like sequence that is composite for 10,000 terms

Please teach me how to optimize my code...

I am looking to find Fibonacci sequences of the equation a*Xn-1 - (c*c)Xn-2 . I am looking for a, c values with a GCD of 1 that will result in a Fibonacci sequence that is composite from the 10th term to the 10,000th term. However, for each term in the sequence, I also want the value of the term + 1 and the value of the term - 1 to be composite as well.

As the numbers get very large, the code is taking incredibly long to complete. To test primality, I am using the from sympy.ntheory import isprime function. Instead of using a list, I am using two variables to represent my Fibonacci sequence. I am using recursion to analyze smaller intervals and gradually move up to the maximum. The print statements should help understand what the code is doing as it runs.

Here is my code:

from math import gcd
from sympy.ntheory import isprime


def check_pairs(a_c_pairs, start_checking_from, increment, max):
    end_checking_at = start_checking_from + increment
    pairs_that_passed_the_composite_test = []  # list of the successful pairs

    print()
    print(f"{a_c_pairs = }")
    print(f"{start_checking_from = }, {end_checking_at = }, {increment = }, {max = }")
    print()
    print(f"Number of terms to check: {len(a_c_pairs)}")

    count = 1
    for a, c in a_c_pairs:  # checking for each of the provided pairs
        print(f"{count}/{len(a_c_pairs)}: {a=}, {c=}, result=", end="")
        count += 1

        first_term = 0
        second_term = 1

        fail = False
        # iterating through each term in the sequence without using a list
        for i in range(end_checking_at):
            third_term = a*second_term - (c*c)*first_term

            if not i < start_checking_from:  # if the term is in our targeted range, check if that term is prime
                if isprime(third_term) or isprime(third_term + 1) or isprime(third_term - 1):
                    fail = True
                    print("FAIL")
                    break

            # set values for the loop to calculate the next term in the sequence
            first_term = second_term
            second_term = third_term

        if not fail:  # after the entire sequence has been analyzed, if none of the terms were prime
            print("pass")
            pairs_that_passed_the_composite_test.append([a, c])

    if not end_checking_at == max:
        check_pairs(pairs_that_passed_the_composite_test,
                    start_checking_from + increment, increment, max)
    else:
        print()
        print("FINAL LIST OF PAIRS:")
        for a, c in pairs_that_passed_the_composite_test:
            print(a, c)

        return


# these pairs have passed up to 3000 terms
a_c_pairs = [
    [11, 3],
    [34, 3],
    [37, 3],
    [38, 3],
    [40, 3],
    [41, 3],
    [53, 3],
    [56, 3],
    [59, 3],
    [61, 3],
    [65, 3],
    [71, 3],
    [77, 3],
    [82, 3],
    [89, 3],
    [94, 3],
    [95, 3],
    [98, 3],
    [37, 5],
    [39, 5],
    [42, 5],
    [43, 5],
    [46, 5],
    [51, 5],
    [54, 5],
    [57, 5],
    [64, 5],
    [73, 5],
    [74, 5],
    [77, 5],
    [86, 5],
    [89, 5],
    [91, 5],
    [98, 5],
    [53, 7],
    [55, 7],
    [64, 7],
    [71, 7],
    [75, 7],
    [79, 7],
    [81, 7],
    [83, 7],
    [87, 7],
    [92, 7],
    [99, 7],
    [100, 7],
    [86, 9],
    [89, 9],
    [94, 9],
    [97, 9],
    [98, 9]
]

check_pairs(a_c_pairs, 2000, 500, 3000)

Checking if a number is prime is expensive for huge numbers. Although there are algorithm with polynomial complexity like AKS to do that, the of the polynomial is big (ie. O(n^7) where n is the size of the tested number N in bits). Non-deterministic algorithms have a lower polynomial complexity, but this is still quite big. For example, the Miller Rabin test can do that in O(n^4) assuming the unproven generalized Riemann hypothesis is true (which appear to be the case so far). For moderately large numbers like the one fitting in 64 bits, you can check only few bases resulting in a fast primality test. For huge numbers, researchers are actively working on designing better algorithm (especially deterministic generalist unconditional tests) and finding theoretical algorithmic complexity bounds of such an algorithm. Unfortunately, AFAIK O(n^4) is close to the best known complexity (without any huge hidden constants) to test if a number is composite or not.

The problem is the Fibonacci sequence grow very quickly. For the standard version, the number of bit to represent the ith element is close to 2 i / 3 . Thus, the computation time will be quite big for i = 10 000 since it would require to work on numbers with roughly 6700 bits requiring millions of billion iterations in the worst case (ie. a prime number). No mainstream computer can do that quickly yet (and probably not in the next 20 years).

The only possible solution to fix that is to design a specific primality test the numbers you generate which seems to be rather a very hard task at first glance. If there is no relation between prime numbers and Fibonacci numbers, then there is no better solution than using the state-of-the-art algorithms (which are too slow in your case). Otherwise, if there is any relation, such a problem is off-topic on stack overflow, but you can ask this question on math.stackexchange.com .

Few side notes: If third_term-1 is even, then only third_term need to be checked (since other are not prime numbers). If third_term-1 is odd, third_term is not a prime and either third_term-1 or third_term+1 is not a prime number. Moreover, note that there is a relation between the GCD and the Fibonacci numbers and there is a relation between GCD and prime numbers so there might be a relation between Fibonacci numbers and prime ones.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM