From 5cdffffaec6b791d8b7583e1a4b85650df0dc6c0 Mon Sep 17 00:00:00 2001 From: Khushi Pal Date: Wed, 18 Jun 2025 21:40:17 +0530 Subject: [PATCH 1/3] Add classical implementation of Shor's Algorithm (#12318) --- cryptography/shor_algorithm.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 cryptography/shor_algorithm.py diff --git a/cryptography/shor_algorithm.py b/cryptography/shor_algorithm.py new file mode 100644 index 000000000000..e69de29bb2d1 From d37302382265732e2da77bab07a67124e3465226 Mon Sep 17 00:00:00 2001 From: Khushi Pal Date: Wed, 18 Jun 2025 22:13:58 +0530 Subject: [PATCH 2/3] =?UTF-8?q?Add=20classical=20Shor=E2=80=99s=20Algorith?= =?UTF-8?q?m=20implementation=20with=20tests=20(#12318)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- cryptography/__init__.py | 0 cryptography/shor_algorithm.py | 102 ++++++++++++++++++++++ cryptography/tests/__init__.py | 0 cryptography/tests/test_shor_algorithm.py | 36 ++++++++ 4 files changed, 138 insertions(+) create mode 100644 cryptography/__init__.py create mode 100644 cryptography/tests/__init__.py create mode 100644 cryptography/tests/test_shor_algorithm.py diff --git a/cryptography/__init__.py b/cryptography/__init__.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/cryptography/shor_algorithm.py b/cryptography/shor_algorithm.py index e69de29bb2d1..4f070fe67ca1 100644 --- a/cryptography/shor_algorithm.py +++ b/cryptography/shor_algorithm.py @@ -0,0 +1,102 @@ +""" +Classical simulation of Shor's Algorithm to factor integers. + +Source: https://en.wikipedia.org/wiki/Shor%27s_algorithm +""" + +import random +import math +from typing import Tuple, Union + + +def is_prime(n: int) -> bool: + """ + Check if a number is prime. + + >>> is_prime(2) + True + >>> is_prime(4) + False + """ + if n < 2: + return False + if n in (2, 3): + return True + if n % 2 == 0: + return False + r = int(math.isqrt(n)) + for i in range(3, r + 1, 2): + if n % i == 0: + return False + return True + + +def modexp(a: int, b: int, m: int) -> int: + """ + Modular exponentiation: (a^b) % m + + >>> modexp(2, 5, 13) + 6 + """ + result = 1 + a = a % m + while b > 0: + if b & 1: + result = (result * a) % m + a = (a * a) % m + b >>= 1 + return result + + +def shor_classical(N: int, max_attempts: int = 10) -> Union[str, Tuple[int, int]]: + """ + Classical approximation of Shor's Algorithm to factor a number. + + >>> result = shor_classical(15) + >>> isinstance(result, tuple) + True + >>> sorted(result) == [3, 5] + True + + >>> shor_classical(13) # Prime + 'No factors: 13 is prime' + """ + if N <= 1: + return "Failure: input must be > 1" + if N % 2 == 0: + return 2, N // 2 + if is_prime(N): + return f"No factors: {N} is prime" + + for _ in range(max_attempts): + a = random.randrange(2, N - 1) + g = math.gcd(a, N) + if g > 1: + return g, N // g + + r = 1 + while r < N: + if modexp(a, r, N) == 1: + break + r += 1 + else: + continue + + if r % 2 != 0: + continue + x = modexp(a, r // 2, N) + if x == N - 1: + continue + + factor1 = math.gcd(x - 1, N) + factor2 = math.gcd(x + 1, N) + if factor1 not in (1, N) and factor2 not in (1, N): + return factor1, factor2 + + return "Failure: try more attempts" + + +if __name__ == "__main__": + import doctest + + doctest.testmod() diff --git a/cryptography/tests/__init__.py b/cryptography/tests/__init__.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/cryptography/tests/test_shor_algorithm.py b/cryptography/tests/test_shor_algorithm.py new file mode 100644 index 000000000000..6c12e748a2a2 --- /dev/null +++ b/cryptography/tests/test_shor_algorithm.py @@ -0,0 +1,36 @@ +import pytest +from cryptography.shor_algorithm import shor_classical + + +def test_small_composite(): + factors = shor_classical(15) + assert set(factors) == {3, 5} + + +def test_medium_composite(): + factors = shor_classical(21) + assert set(factors) == {3, 7} + + +def test_even_number(): + factors = shor_classical(18) + assert set(factors) == {2, 9} + + +def test_prime_number(): + result = shor_classical(13) + assert isinstance(result, str) + assert "prime" in result.lower() + + +def test_invalid_input(): + result = shor_classical(1) + assert isinstance(result, str) + assert "failure" in result.lower() + + +def test_larger_composite_number(): + result = shor_classical(91) + assert isinstance(result, (tuple, str)) + if isinstance(result, tuple): + assert all(isinstance(x, int) for x in result) From c568a092f3532cb341fabac9197a3dc47966a084 Mon Sep 17 00:00:00 2001 From: Khushi Pal <114483555+khushipy@users.noreply.github.com> Date: Fri, 20 Jun 2025 09:57:50 +0530 Subject: [PATCH 3/3] Update shor_algorithm.py --- cryptography/shor_algorithm.py | 43 ++++++++++++++++------------------ 1 file changed, 20 insertions(+), 23 deletions(-) diff --git a/cryptography/shor_algorithm.py b/cryptography/shor_algorithm.py index 4f070fe67ca1..110d3278b40d 100644 --- a/cryptography/shor_algorithm.py +++ b/cryptography/shor_algorithm.py @@ -4,9 +4,9 @@ Source: https://en.wikipedia.org/wiki/Shor%27s_algorithm """ -import random import math -from typing import Tuple, Union +import random +from typing import Any def is_prime(n: int) -> bool: @@ -24,11 +24,8 @@ def is_prime(n: int) -> bool: return True if n % 2 == 0: return False - r = int(math.isqrt(n)) - for i in range(3, r + 1, 2): - if n % i == 0: - return False - return True + r = math.isqrt(n) + return all(n % i != 0 for i in range(3, r + 1, 2)) def modexp(a: int, b: int, m: int) -> int: @@ -48,7 +45,7 @@ def modexp(a: int, b: int, m: int) -> int: return result -def shor_classical(N: int, max_attempts: int = 10) -> Union[str, Tuple[int, int]]: +def shor_classical(n: int, max_attempts: int = 10) -> str | tuple[int, int]: """ Classical approximation of Shor's Algorithm to factor a number. @@ -61,22 +58,22 @@ def shor_classical(N: int, max_attempts: int = 10) -> Union[str, Tuple[int, int] >>> shor_classical(13) # Prime 'No factors: 13 is prime' """ - if N <= 1: + if n <= 1: return "Failure: input must be > 1" - if N % 2 == 0: - return 2, N // 2 - if is_prime(N): - return f"No factors: {N} is prime" + if n % 2 == 0: + return 2, n // 2 + if is_prime(n): + return f"No factors: {n} is prime" for _ in range(max_attempts): - a = random.randrange(2, N - 1) - g = math.gcd(a, N) + a = random.randrange(2, n - 1) + g = math.gcd(a, n) if g > 1: - return g, N // g + return g, n // g r = 1 - while r < N: - if modexp(a, r, N) == 1: + while r < n: + if modexp(a, r, n) == 1: break r += 1 else: @@ -84,13 +81,13 @@ def shor_classical(N: int, max_attempts: int = 10) -> Union[str, Tuple[int, int] if r % 2 != 0: continue - x = modexp(a, r // 2, N) - if x == N - 1: + x = modexp(a, r // 2, n) + if x == n - 1: continue - factor1 = math.gcd(x - 1, N) - factor2 = math.gcd(x + 1, N) - if factor1 not in (1, N) and factor2 not in (1, N): + factor1 = math.gcd(x - 1, n) + factor2 = math.gcd(x + 1, n) + if factor1 not in (1, n) and factor2 not in (1, n): return factor1, factor2 return "Failure: try more attempts" pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy