def narrow_region(frontier, target, max_states=100): ''' Given a frontier to start with, run through the largest powers of BASE until we get a decent number of starting states >>> base = 2 >>> target = IntegerBaseFixed(1031 * 1093, None, None, base=2) >>> num_digits = target_to_max_factor_num_digits(target, base=2, moe=0) >>> frontier = generate_starting_products(num_digits, base=2) >>> frontier = narrow_region(frontier, target, 5) >>> for prod in frontier: ... print prod.num_fixed_digits_left, prod.num_fixed_digits_right, prod 1 6 10000100001x10000100001=100010000110001000001 1 6 10000000001x10001000001=100010000100001000001 1 7 10000000001x10000110001=100001100100000110001 1 7 10000010001x10000100001=100001100101000110001 1 7 10000010001x10000110001=100010000101101000001 ''' frontier = deque(frontier) while len(frontier) < max_states: prod = frontier.popleft() assert prod.base == target.base children = generate_children(prod, 'r') for child in children: if child.as_int == target.as_int: return deque([child]) if has_potential_children(child, target): frontier.append(child) return frontier
def factorize(target, base=BASE): ''' Simple breadth first factorization algorithm >>> factorize(143, 2) (11, 13) >>> factorize(169, 2) (13, 13) >>> factorize(289, 2) (17, 17) >>> factorize(323, 2) (17, 19) >>> factorize(309485009822787627980424653, 2) (17592186044443L, 17592186044471L) ''' target = IntegerBaseFixed(target, None, None, base) num_digits = target_to_max_factor_num_digits(target, base=base, moe=0) frontier = deque(generate_starting_products(num_digits, base)) # Now narrow starting from the right, in case we have a very low or very # high factor frontier = narrow_region(frontier, target, max_states=100) if len(frontier) == 1: prod = frontier[0] assert prod.as_int == target.as_int p, q = prod.p.as_int, prod.q.as_int return order(p, q) while len(frontier): prod = frontier.popleft() if prod.num_fixed_digits_left > prod.num_fixed_digits_right: children = generate_children(prod, 'r') else: children = generate_children(prod, 'l') for child in children: if child.as_int == target.as_int: p, q = child.p.as_int, child.q.as_int return order(p, q) if has_potential_children(child, target): frontier.append(child) print 'No factorization found!'