コード例 #1
0
def expand_and_filter_children(candidate, target, max_factor_num_digits):
    if candidate.num_fixed_digits_left <= candidate.num_fixed_digits_right:
        children = candidate.generate_children_left()
    else:
        children = candidate.generate_children_right()

    children = filter_digit_length(children, min(max_factor_num_digits, target.num_digits))
#    children = [child for child in children if child.as_int <= target.as_int]
#            children = [child for child in children if child.num_digits <= target.num_digits]
    children = filter_correct_digits_left(children, target)
    children = filter_small_products(children, target)
    children = filter_large_products(children, target)
    return children
コード例 #2
0
ファイル: factorization_algos.py プロジェクト: tanbur/allstar
def factor1(target):
    start_time = time()
    num_states = 1

    if not isinstance(target, IntegerBaseFixed):
        target = IntegerBaseFixed(target)

    key_func = partial(product_to_error, target=target)
    frontier = BinarySearchTree(key_func)

    for i, j in itertools.combinations_with_replacement(xrange(BASE), 2):
        frontier.insert(ProductFixed(i, j))

    solved = False
    while len(frontier):

        candidate = frontier.pop_min()

        #print
        #print IntegerBaseFixed.from_int(target)
        #print candidate
        #from time import sleep
        #sleep(1)

        if candidate.as_int() == target:
            print 'Solution!', candidate
            break

        children = candidate.generate_children()
        children = filter_digit_length(children, target)
        children = filter_correct_digits(children, target)

        for child in children:
            frontier.insert(child)
        num_states += len(children)

        if not num_states % 10000:
            print 'Checked:', num_states

    end_time = time()
    print 'States checked:', num_states
    print 'Time taken: {:.2f}s'.format(end_time - start_time)
コード例 #3
0
def factor2(target):

    import multiprocessing
    if 1:
        pool = multiprocessing.Pool(10)
    else:
        pool = None

    print factorisation_summary(target)

    start_time = time()
    num_states = 0

    if not isinstance(target, IntegerBaseFixed):
        target = IntegerBaseFixed(target, None, None)

    solved = False


#### SET HEURISTIC

#    key_func = partial(product_to_dual_error, target=target, comb_func=min)
    key_func = partial(product_to_simple_error, target=target)
#    key_func = partial(product_to_hamming_distance_padded, target=target)
    frontiers = defaultdict(lambda : BinarySearchTree(key_func))

####


    # Find the maximum number of digits
    max_factor_num_digits = target_to_max_factor_num_digits(target, 0)

    start_nodes = []

#    init_p_digits = [0 for _ in xrange(max_factor_num_digits)]
#    init_q_digits = [0 for _ in xrange(max_factor_num_digits)]

    import math
    sqrt = math.sqrt(target.as_int)
    init_p_digits = map(int, int_to_digits(int(sqrt)))
    init_q_digits = init_p_digits[:]
    assert len(init_p_digits) == max_factor_num_digits
    print init_p_digits

    for p0, q0 in itertools.combinations_with_replacement(xrange(BASE), 2):
        for pn, qn in itertools.combinations_with_replacement(xrange(1, BASE), 2):

            p_digits = init_p_digits[:]
            p_digits[0] = p0
            p_digits[-1] = pn
            p = IntegerBaseFixed(p_digits, 1, 1)

            q_digits = init_q_digits[:]
            q_digits[0] = q0
            q_digits[-1] = qn
            q = IntegerBaseFixed(q_digits, 1, 1)

            prod = ProductFixed(p, q)
            start_nodes.append(prod)
            num_states += 1

    # Do some preprocessing to get in the right range immediately by fixing the
    # larger powers
    start_nodes = filter_correct_digits_left(start_nodes, target)
#    for _ in start_nodes:
#        print _
#    return
    while 0 < len(start_nodes) < 10:
        print len(start_nodes)
        start_nodes = list(itertools.chain(*[node.generate_children_right() for node in start_nodes]))
        start_nodes = filter_digit_length(start_nodes, min(max_factor_num_digits, target.num_digits))
        start_nodes = [node for node in start_nodes if node.as_int <= target.as_int]
        start_nodes = filter_small_products(start_nodes, target)

    print len(start_nodes)
    return

    for prod in start_nodes:
        frontiers[prod.num_fixed_digits].insert(prod)

    _iter = 0
    while sum(map(len, frontiers.itervalues())):
    #for _iter in xrange(1000):

        _iter += 1
        # Now queue the stuff we want to expand
        # First work out how many we want
### Budget
        budget = 1000
        dig_to_num_instances = {dig: len(tree) for dig, tree in frontiers.iteritems()}

        # Filter out zero instances
#        dig_to_num_instances = {dig: num for dig, num in dig_to_num_instances.iteritems() if num != 0}
        # And instances with too many digits
#        dig_to_num_instances = {dig: num for dig, num in dig_to_num_instances.iteritems() if dig < max_factor_num_digits}

        total_inst = sum(dig_to_num_instances.values())
        if total_inst > budget:

            # Blind sweeper
#            dig_to_expand = sorted(dig_to_num_instances.keys())[_iter % len(dig_to_num_instances)]
#            dig_to_num_instances = {}
#            dig_to_num_instances[dig_to_expand] = budget

#            dig_to_num_instances = alloc_by_exp_weight(dig_to_num_instances, budget)
            dig_to_num_instances = alloc_flat(dig_to_num_instances, 1)
#            dig_to_num_instances = alloc_exp_interp(dig_to_num_instances, 1, 5)
#            dig_to_num_instances = alloc_exp_increasing(dig_to_num_instances, 1.3)
            # Shitty measure that's relative to how many instances there are of each digit. Prone to getting stuck
            #instances_per_iter = min(total_inst, desired_instances_to_expand)
            #dig_to_num_instances = {dig: int(num * instances_per_iter / total_inst) for dig, num in dig_to_num_instances.iteritems()}


        # Do some normalisation
        dig_to_num_instances = {dig: min(max(num, MIN_TO_EXPAND), len(frontiers[dig])) for dig, num in dig_to_num_instances.iteritems()}



######### Printing

        # Print out how we are allocating the budget
        if not _iter % 100 or 1:
#            sleep(0.2)
            print 'Num instances checked:', num_states
            print 'Solution location:'
            find_solution_root_fixed(frontiers, target)
#
#            keys = sorted(frontiers.keys())
#            print 'Budget Allocation:'
#            for dig in keys[-5:]:
#                num_inst = len(frontiers[dig])
#                if num_inst == 0:
#                    continue
#                print dig, dig_to_num_instances.get(dig, 0), num_inst
            print
        #print dig_to_num_instances
        #print {dig: len(tree) for dig, tree in frontiers.iteritems()}
        #print

#########





        # Now get them
        to_expand = []
        for num_dig, num_inst in dig_to_num_instances.iteritems():
            frontier = frontiers[num_dig]
            for _ in xrange(num_inst):
                to_expand.append(frontier.pop_min())
#                if len(frontier):
#                    to_expand.append(frontier.pop_min())
#                if len(frontier):
#                    to_expand.append(pop_index(frontier, key_func, int(len(frontier) / 2)))


### Old linear implementation
#        for candidate in to_expand:
#            #print
#            #print IntegerBaseFixed.from_int(target)
#            #print candidate
#            #from time import sleep
#            #sleep(1)
#
#            if candidate.num_fixed_digits_left <= candidate.num_fixed_digits_right:
#                children = candidate.generate_children_left()
#            else:
#                children = candidate.generate_children_right()
#
#            children = filter_digit_length(children, min(max_factor_num_digits, target.num_digits))
#            children = [child for child in children if child.as_int <= target.as_int]
##            children = [child for child in children if child.num_digits <= target.num_digits]
#            children = filter_correct_digits_left(children, target)
#            children = filter_small_products(children, target)
#
#            for child in children:
#                if child.as_int == target.as_int:
#                    print 'Solution!', child
#                    solved = True
#                    break
#
#                frontiers[child.num_fixed_digits].insert(child)
#
#            num_states += len(children)


### New parallelisable approach
        mapper = partial(expand_and_filter_children, target=target,
                         max_factor_num_digits=max_factor_num_digits)

        if pool is None:
            children = map(mapper, to_expand)
        else:
            children = pool.map(mapper, to_expand)

        children = itertools.chain(*children)
        for child in children:
            num_states += 1
            if child.as_int == target.as_int:
                print 'Solution!', child
                solved = True
                break

            frontiers[child.num_fixed_digits].insert(child)

        #print 'Checked:', num_states
        if solved:
            break

    end_time = time()
    assert solved
    print 'Iterations:', _iter
    print 'States checked:', num_states
    print 'Time taken: {:.2f}s'.format(end_time - start_time)
    return num_states, round(end_time - start_time, 2)
コード例 #4
0
ファイル: factorization_algos.py プロジェクト: tanbur/allstar
def factor2(target):
    start_time = time()
    num_states = 0

    if not isinstance(target, IntegerBaseFixed):
        target = IntegerBaseFixed(target)

    solved = False
    key_func = partial(product_to_hamming_distance, target=target)
    frontiers = defaultdict(lambda : BinarySearchTree(key_func))


    # Find the maximum number of digits
    max_factor_num_digits = target_to_max_factor_num_digits(target, 0)

    for i, j in itertools.combinations_with_replacement(xrange(BASE), 2):
        prod = Product(i, j)
        frontiers[prod.factor_num_digits].insert(prod)
        num_states += 1

    _iter = 0
    while sum(map(len, frontiers.itervalues())):
    #for _iter in xrange(1000):

        _iter += 1
        # Now queue the stuff we want to expand
        # First work out how many we want
        budget = 1000
        dig_to_num_instances = {dig: len(tree) for dig, tree in frontiers.iteritems()}

        # Filter out zero instances
#        dig_to_num_instances = {dig: num for dig, num in dig_to_num_instances.iteritems() if num != 0}
        # And instances with too many digits
#        dig_to_num_instances = {dig: num for dig, num in dig_to_num_instances.iteritems() if dig < max_factor_num_digits}

        total_inst = sum(dig_to_num_instances.values())
        if total_inst > budget:

            # Blind sweeper
#            dig_to_expand = sorted(dig_to_num_instances.keys())[_iter % len(dig_to_num_instances)]
#            dig_to_num_instances = {}
#            dig_to_num_instances[dig_to_expand] = budget

#            dig_to_num_instances = alloc_by_exp_weight(dig_to_num_instances, budget)
#            dig_to_num_instances = alloc_flat(dig_to_num_instances, 1)
#            dig_to_num_instances = alloc_exp_interp(dig_to_num_instances, 1, 5)
            dig_to_num_instances = alloc_exp_increasing(dig_to_num_instances, 1.3)
            # Shitty measure that's relative to how many instances there are of each digit. Prone to getting stuck
            #instances_per_iter = min(total_inst, desired_instances_to_expand)
            #dig_to_num_instances = {dig: int(num * instances_per_iter / total_inst) for dig, num in dig_to_num_instances.iteritems()}


        # Do some normalisation
        dig_to_num_instances = {dig: min(max(num, MIN_TO_EXPAND), len(frontiers[dig])) for dig, num in dig_to_num_instances.iteritems()}

        # Print out how we are allocating the budget
        if not _iter % 100 or 0:
#            sleep(0.2)
            print 'Num instances checked:', num_states
            print 'Solution location:'
            find_solution_root(frontiers, target)
#
#
#            keys = sorted(frontiers.keys())
#            print 'Budget Allocation:'
#            for dig in keys[-5:]:
#                num_inst = len(frontiers[dig])
#                if num_inst == 0:
#                    continue
#                print dig, dig_to_num_instances.get(dig, 0), num_inst
            print
        #print dig_to_num_instances
        #print {dig: len(tree) for dig, tree in frontiers.iteritems()}
        #print

        # Now get them
        to_expand = []
        for num_dig, num_inst in dig_to_num_instances.iteritems():
            frontier = frontiers[num_dig]
            for _ in xrange(num_inst):
                to_expand.append(frontier.pop_min())

        for candidate in to_expand:
            #print
            #print IntegerBaseFixed.from_int(target)
            #print candidate
            #from time import sleep
            #sleep(1)

            children = candidate.generate_children()
            children = filter_digit_length(children, min(max_factor_num_digits, target.num_digits))
            children = filter_correct_digits(children, target)
            #children = filter_large_products(children, target)
            children = [child for child in children if child.as_int <= target.as_int]

            for child in children:
                if child.as_int == target.as_int:
                    print 'Solution!', child
                    solved = True
                    break

                frontiers[child.factor_num_digits].insert(child)

            num_states += len(children)

        #print 'Checked:', num_states
        if solved:
            break

    end_time = time()
    print 'Iterations:', _iter
    print 'States checked:', num_states
    print 'Time taken: {:.2f}s'.format(end_time - start_time)
コード例 #5
0
ファイル: dev_comp_errors.py プロジェクト: tanbur/allstar
def analyse(target, error_func, max_states=100000):

    start_time = time()
    num_states = 0

    if not isinstance(target, IntegerBase):
        target = IntegerBase(target)

    key_func = partial(error_func, target=target)
    frontiers = defaultdict(lambda : BinarySearchTree(key_func))

    # Find the maximum number of digits
    max_factor_num_digits = target_to_max_factor_num_digits(target, 0)

    for i, j in itertools.combinations_with_replacement(xrange(BASE), 2):
        prod = Product(i, j)
        frontiers[prod.factor_num_digits].insert(prod)
        num_states += 1

    solved = False
    _iter = 0
    while 0 < sum(map(len, frontiers.itervalues())) < max_states:
    #for _iter in xrange(1000):

        _iter += 1
        dig_to_num_instances = {dig: len(tree) for dig, tree in frontiers.iteritems()}
        find_solution_root(frontiers, target)


        # Now get them
        to_expand = []
        for num_dig, num_inst in dig_to_num_instances.iteritems():
            frontier = frontiers[num_dig]
            for _ in xrange(num_inst):
                to_add = frontier.pop_min()
                to_expand.append(to_add)

        for candidate in to_expand:
            #print
            #print IntegerBase.from_int(target)
            #print candidate
            #from time import sleep
            #sleep(1)

            children = candidate.generate_children()
            children = filter_digit_length(children, max_factor_num_digits)
            children = filter_correct_digits(children, target)
            #children = filter_large_products(children, target)
            #children = [child for child in children if child.as_int <= target.as_int]

            for child in children:
                if child.as_int == target.as_int:
                    print 'Solution!', child
                    solved = True
                    break

                frontiers[child.factor_num_digits].insert(child)

            num_states += len(children)

        if solved:
            break

    end_time = time()
#    print 'Iterations:', _iter
    print 'States checked:', num_states
#    print 'Time taken: {:.2f}s'.format(end_time - start_time)
    print