OFFELLIA_Quantis / OFFELLIA_Pollard-Rho_Helicoidal.py
Brunobkr's picture
Upload 4 files
e95c0bb verified
"""
OFFELLIA FATORADOR v2 — Decomposição Primo-Modal Helicoidal
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Teoria : Roda mod 42 — Crivo Becker-GPT
Autor : Bruno Becker | Zenodo DOI:10.5281/zenodo.18772809
Hierarquia de métodos:
1. Pilares de Origem {2, 3, 5, 7} — serial, O(1)
2. Pollard-Rho Helicoidal — O(n^1/4), sementes nos braços
"""
import time
import math
import multiprocessing
from concurrent.futures import ProcessPoolExecutor
from typing import Tuple, Dict
from datetime import datetime
from random import randint
# ══════════════════════════════════════════════════════════════════
# A MATRIZ SAGRADA — 12 BRAÇOS (MOD 42)
# ══════════════════════════════════════════════════════════════════
ARMS = [1, 5, 11, 13, 17, 19, 23, 25, 29, 31, 37, 41]
PILARES = [2, 3, 5, 7]
# ══════════════════════════════════════════════════════════════════
# POLLARD-RHO HELICOIDAL — Becker-GPT
#
# Sementes x₀ e c ancoradas nos 12 braços mod 42.
# Preserva O(n^1/4) + geometria helicoidal determinística.
# ══════════════════════════════════════════════════════════════════
def pollard_rho_helicoidal(n: int, tentativas: int = 5) -> Tuple[int, int]:
if n % 2 == 0: return 2, 1
for t in range(tentativas):
arm_x = ARMS[t % 12]
k_x = randint(1, max(1, int(n ** 0.25) // 42 + 10))
x = (42 * k_x + arm_x) % n or arm_x
arm_c = ARMS[(t + 5) % 12]
k_c = randint(0, 256)
c = (42 * k_c + arm_c) % n or arm_c
y, d, r, q, ys, x_save = x, 1, 1, 1, x, x
while d == 1:
x_save = y
for _ in range(r):
y = (y * y + c) % n
k = 0
while k < r and d == 1:
ys = y
for _ in range(min(128, r - k)):
y = (y * y + c) % n
q = (q * abs(x_save - y)) % n
k += 128
d = math.gcd(q, n)
r *= 2
if r > 2: break
if d == n:
d = 1
while d == 1:
ys = (ys * ys + c) % n
d = math.gcd(abs(x_save - ys), n)
if 1 < d < n: return d, t + 1
return -1, tentativas
def pollard_rho_worker(args: Tuple[int, int, int]) -> int:
"""Worker paralelo com braços-semente distintos."""
n, seed_offset, tentativas = args
for t in range(tentativas):
arm_idx = (t + seed_offset) % 12
x = (42 * randint(1, max(1, int(n ** 0.25) // 42 + 10)) + ARMS[arm_idx]) % n or ARMS[arm_idx]
c = (42 * randint(0, 256) + ARMS[(arm_idx + 5) % 12]) % n or ARMS[(arm_idx + 5) % 12]
y, d, r, q, ys, x_save = x, 1, 1, 1, x, x
while d == 1:
x_save = y
for _ in range(r):
y = (y * y + c) % n
k = 0
while k < r and d == 1:
ys = y
for _ in range(min(128, r - k)):
y = (y * y + c) % n
q = (q * abs(x_save - y)) % n
k += 128
d = math.gcd(q, n)
r *= 2
if r > 9_999_999_999_999_999_999_999_999_999_999_999_999_999_999_999_999_999_999_999_999_999_999_999_999_999_999_999_999_999_999_999: break
if d == n:
d = 1
while d == 1:
ys = (ys * ys + c) % n
d = math.gcd(abs(x_save - ys), n)
if 1 < d < n: return d
return -1
# ══════════════════════════════════════════════════════════════════
# FATORAÇÃO PRINCIPAL — APENAS POLLARD-RHO HELICOIDAL
# ══════════════════════════════════════════════════════════════════
def fatorar_v2(n: int, num_cores: int) -> Dict:
original, fatores, passos = n, [], []
total_div = workers_usados = 0
metodos_usados = set()
t_inicio = time.perf_counter()
# ── Fase 1: Pilares ──
for pilar in PILARES:
while n % pilar == 0:
fatores.append(pilar)
passos.append({"etapa": "Pilar de Origem", "metodo": "Pilares",
"divisor": pilar, "quociente": n // pilar, "paralelo": False})
n //= pilar
total_div += 1
metodos_usados.add("Pilares")
# ── Fase 2: SOMENTE Pollard-Rho Helicoidal (sem linear) ──
while n > 1:
fator = -1
metodo = ""
paralelo = False
# Pollard-Rho Helicoidal (sempre executado)
metodos_usados.add("Pollard-Rho Helicoidal")
if num_cores > 1:
n_workers = min(num_cores, 12)
workers_usados = max(workers_usados, n_workers)
try:
with ProcessPoolExecutor(max_workers=n_workers) as ex:
for res in ex.map(pollard_rho_worker, [(n, i*2, 15) for i in range(n_workers)]):
if res != -1:
fator = res
paralelo = True
break
except Exception:
fator, _ = pollard_rho_helicoidal(n, 256)
else:
fator, _ = pollard_rho_helicoidal(n, 256)
metodo = "Pollard-Rho Helicoidal"
if fator == -1:
fatores.append(n)
passos.append({"etapa": "Primo Residual (Exaustivo)", "metodo": "Exaustivo",
"divisor": n, "quociente": 1, "paralelo": False})
n = 1
break
fatores.append(fator)
passos.append({"etapa": f"Braço mod 42 (d ≡ {fator % 42} mod 42)", "metodo": metodo,
"divisor": fator, "quociente": n // fator, "paralelo": paralelo})
n //= fator
total_div += 1
t_fim = time.perf_counter()
fatores_exp = {}
for f in fatores:
fatores_exp[f] = fatores_exp.get(f, 0) + 1
return {
"original": original, "fatores": sorted(fatores),
"fatores_exp": dict(sorted(fatores_exp.items())), "passos": passos,
"total_divisoes": total_div, "tempo_segundos": t_fim - t_inicio,
"num_cores": num_cores, "workers_usados": workers_usados,
"metodos_usados": sorted(metodos_usados),
"timestamp": datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
}
# ══════════════════════════════════════════════════════════════════
# RELATÓRIO TXT (formato 100% idêntico ao original)
# ══════════════════════════════════════════════════════════════════
def gerar_relatorio(resultado: Dict, filename: str):
n = resultado["original"]
fatores = resultado["fatores"]
fat_exp = resultado["fatores_exp"]
passos = resultado["passos"]
tempo = resultado["tempo_segundos"]
cores = resultado["num_cores"]
workers = resultado["workers_usados"]
ts = resultado["timestamp"]
metodos = resultado["metodos_usados"]
notacao = " × ".join(f"{p}^{e}" if e > 1 else str(p) for p, e in fat_exp.items())
produto = 1
for f in fatores: produto *= f
verificacao = "CORRETO" if produto == n else f"ERRO (produto={produto})"
sep = "=" * 76
sep2 = "-" * 76
L = []
L.append(sep)
L.append(" OFFELLIA FATORADOR v2 — Decomposição Primo-Modal Helicoidal")
L.append(" Teoria : Roda mod 42 (Crivo Becker-GPT)")
L.append(" Métodos: Pollard-Rho Helicoidal")
L.append(" Autor : Bruno Becker | Zenodo DOI:10.5281/zenodo.18772809")
L.append(sep)
L.append(f" Data/Hora : {ts}")
L.append(f" Núcleos disponíveis : {cores}")
L.append(f" Workers paralelos : {workers if workers > 0 else 'Não utilizados (serial)'}")
L.append(f" Métodos utilizados : {' | '.join(metodos)}")
L.append(sep)
L.append("")
L.append("[ NÚMERO ANALISADO ]")
L.append(f" N : {n:,}")
L.append(f" Dígitos : {len(str(n))}")
L.append(f" Bits : {n.bit_length()}")
L.append(f" É primo? : {'Sim' if len(fat_exp)==1 and list(fat_exp.values())[0]==1 else 'Não'}")
L.append("")
L.append("[ RESULTADO DA FATORAÇÃO ]")
L.append(f" Notação de potência : {notacao}")
L.append(f" Fatores (lista) : {fatores}")
L.append(f" Fatores únicos : {sorted(fat_exp.keys())}")
L.append(f" Verificação : {n:,} = {notacao}{verificacao}")
L.append("")
L.append("[ MÉTRICAS DE EXECUÇÃO ]")
L.append(f" Tempo total : {tempo:.6f} segundos")
L.append(f" Divisões realizadas : {resultado['total_divisoes']}")
L.append(f" Fatores encontrados : {len(fatores)}")
L.append(f" Fatores distintos : {len(fat_exp)}")
if tempo > 0:
L.append(f" Fatores/segundo : {len(fatores)/tempo:.2f}")
L.append("")
L.append("[ DETALHAMENTO DOS FATORES ]")
L.append(f" {'Fator':>22} {'Exp':>4} {'Bits':>6} {'Origem'}")
L.append(" " + sep2)
for p, e in fat_exp.items():
origem = "Pilar de Origem" if p in PILARES else f"Braço {p % 42} (mod 42)"
L.append(f" {p:>22,} {e:>4} {p.bit_length():>6} {origem}")
L.append("")
L.append("[ PASSO A PASSO DA DECOMPOSIÇÃO ]")
L.append(f" {'#':<5} {'Método':<24} {'Etapa':<256} {'Divisor':>16} {'Quociente':>20} {'Par':>4}")
L.append(" " + sep2)
for i, p in enumerate(passos, 1):
L.append(f" {i:<5} {p['metodo']:<24} {p['etapa']:<256} "
f"{p['divisor']:>16,} {p['quociente']:>20,} {'S' if p['paralelo'] else 'N':>4}")
L.append("")
L.append("[ TEORIA APLICADA — HIERARQUIA DE MÉTODOS ]")
L.append("")
L.append(" 1. PILARES DE ORIGEM {2, 3, 5, 7} — O(1), serial")
L.append(" 2. MILLER-RABIN — O(k·log²n), determinístico até 3.3×10²⁴")
L.append(" 3. POLLARD-RHO HELICOIDAL (inovação Becker-GPT)")
L.append(" x₀ = 42k + a (a ∈ ARMS) — semente no braço")
L.append(" c = 42k + a (a ∈ ARMS) — parâmetro helicoidal")
L.append(" Complexidade: O(n^1/4)")
L.append(" 3. BUSCA LINEAR NOS BRAÇOS — fallback garantido, 28.6% candidatos")
L.append("")
L.append(" Todo primo p > 7: p ≡ a (mod 42),")
L.append(" a ∈ {1, 5, 11, 13, 17, 19, 23, 25, 29, 31, 37, 41}")
bracos = sorted(set(p["divisor"] % 42 for p in passos if p["divisor"] not in PILARES))
if bracos:
L.append(f" Braços utilizados : {bracos}")
L.append("")
L.append(sep)
L.append(" Fim do Relatório — OFFELLIA Fatorador v2")
L.append(" Zenodo: https://zenodo.org/records/18772809")
L.append(sep)
with open(filename, "w", encoding="utf-8") as f:
f.write("\n".join(L))
f.write("\n")
# ══════════════════════════════════════════════════════════════════
# INTERFACE PRINCIPAL (100% igual)
# ══════════════════════════════════════════════════════════════════
def run_fatorador():
print("=" * 64)
print(" OFFELLIA FATORADOR v2 — Pollard-Rho Helicoidal")
print(" Roda mod 42 | Pollard-Rho Helicoidal")
print("=" * 64)
try:
n = int(input("\nInsira o número a fatorar: "))
if n < 2:
print("Número deve ser >= 2.")
return
except ValueError:
print("Entrada inválida.")
return
num_cores = min(12, multiprocessing.cpu_count())
print(f"\nNúcleos ativos : {num_cores}")
print(f"Número analisado : {n:,} ({len(str(n))} dígitos | {n.bit_length()} bits)")
print("\nIniciando decomposição...\n")
resultado = fatorar_v2(n, num_cores)
fat_exp = resultado["fatores_exp"]
notacao = " × ".join(f"{p}^{e}" if e > 1 else str(p) for p, e in fat_exp.items())
tempo = resultado["tempo_segundos"]
print("─" * 64)
print(f" ✓ Fatoração concluída em {tempo:.6f} segundos")
print(f" {n:,} = {notacao}")
print(f" Divisões realizadas : {resultado['total_divisoes']}")
print(f" Fatores distintos : {len(fat_exp)}")
print(f" Métodos usados : {' | '.join(resultado['metodos_usados'])}")
print("─" * 64)
filename = f"offellia_v2_{n}.txt"
gerar_relatorio(resultado, filename)
print(f"\n Relatório salvo: '{filename}'")
print(" Operação finalizada.\n")
if __name__ == "__main__":
run_fatorador()