예제 #1
0
def multi_way_partitioning(items, bin_count):
    """
    Greedily divide weighted items equally across bins (multi-way partition problem)
    
    This approximately minimises the difference between the largest and smallest
    sum of weights in a bin.
    
    Parameters
    ----------
    items : iterable((item :: any) : (weight :: number))
        Weighted items
    bin_count : int
        Number of bins
        
    Returns
    -------
    bins : bag(bin :: frozenbag(item :: any))
        Bins with the items
        
    References
    ----------
    .. [1] http://stackoverflow.com/a/6855546/1031434 describes the greedy algorithm
    .. [2] http://ijcai.org/Proceedings/09/Papers/096.pdf defines the problem and describes algorithms
    """
    bins = [_Bin() for _ in range(bin_count)]
    for item, weight in sorted(items, key=lambda x: x[1], reverse=True):
        bin_ = min(bins, key=lambda bin_: bin_.weights_sum)
        bin_.add(item, weight)
    return bag(frozenbag(bin_.items) for bin_ in bins)
예제 #2
0
 def __derivative_of_variable(me, w, p):
     ww, iww, _, _ = me.__variable_context(w)
     pp = ww[w] + frozenbag([p])
     if pp in iww:
         dwdp = iww[pp]
     else:
         dwdp = Function(w.function_space())
         ww[dwdp] = pp
         iww[pp] = dwdp
     return dwdp
 def test_happy_days(self, items, bin_count, ideal_distance):
     '''When any other input, ...'''
     bins = multi_way_partitioning(items, bin_count)
     
     # Fill as many bins as possible
     assert bins.count(frozenbag()) == max(bin_count - len(items), 0)
     
     # Relative error to ideal solution should be acceptable
     actual_distance = self.get_distance(self.reapply_weights(items, bins))
     assert actual_distance >= (ideal_distance - 1e8), 'bug in test'
     assert actual_distance <= 1.3 * ideal_distance
예제 #4
0
 def __form_derivative_recursive(me, pp, FF, iFF):
     if pp in iFF:
         dFdpp = iFF[pp]
     else:
         pp0 = bag(pp)
         p = pp0.pop()
         pp0 = frozenbag(pp0)
         dFdpp0 = me.__form_derivative_recursive(pp0, FF, iFF)
         dFdpp = me.__derivative_of_form(dFdpp0, p)
         FF[dFdpp] = pp
         iFF[pp] = dFdpp
     return dFdpp
예제 #5
0
 def __derivative_of_form(me, F, p):
     FF, iFF = me.__form_context(F)
     pp = FF[F] + frozenbag([p])
     if pp in iFF:
         dFdp = iFF[pp]
     else:
         dFdp = derivative(F, me.m, p)
         for w in F.coefficients():
             if (w in me.uu) or (w in me.vv):
                 dFdp = dFdp + derivative(F, w, me.__derivative_of_variable(w, p))
         FF[dFdp] = pp
         iFF[pp] = dFdp
     return dFdp
예제 #6
0
    def get_optimal(self):
        """
		Restituisce la politica ottimale

		Returns
		-----------------------------------
		(frozenbag) optimal
			Politica ottimale appresa
		"""

        optimal = self.env.get_init_state()
        while not self.env.is_terminal_state(optimal):
            optimal = frozenbag(
                list(optimal) + [self.get_argmax_action(optimal)])
        return optimal
예제 #7
0
    def compute_derivative_of_quantity_of_interest(me, derivative_directions_pp, output_direction_z):
        pp = frozenbag(derivative_directions_pp)
        if output_direction_z is not None:
            me.z.vector()[:] = output_direction_z.vector()[:].copy()

        me.__check_if_m_changed_and_update_accordingly()
        me.__check_if_z_changed_and_update_accordingly()
        me.num_changed_p = 0
        for p in pp.unique_elements():
            me.__check_if_p_changed_and_update_accordingly(p)
        # print('me.num_changed_p=', me.num_changed_p)

        # me.solved_variables.clear()

        if output_direction_z is not None:
            F = me.__form_derivative_recursive(pp, me.GG, me.iGG)
        else:
            F = me.__form_derivative_recursive(pp, me.QQ, me.iQQ)

        return me._evaluate_form(F)
예제 #8
0
    def __init__(me, quantity_of_interest_form_Q, state_equation_S, state_bcs,
                 parameter_m, state_variable_u):
        me.Q = quantity_of_interest_form_Q
        me.S = state_equation_S
        me.m = parameter_m
        me.u = state_variable_u

        me.uu = {me.u : frozenbag()}
        me.iuu = {frozenbag(): me.u}

        me.bcs = state_bcs
        me.zero_bcs = [DirichletBC(bc) for bc in me.bcs]
        for bc in me.zero_bcs:
            bc.homogenize()

        me.SS = {me.S : frozenbag()}
        me.iSS = {frozenbag() : me.S}

        me.QQ = {me.Q : frozenbag()}
        me.iQQ = {frozenbag() : me.Q}

        me.M = me.m.function_space()
        me.V = me.u.function_space()
        me.Z = me.Q.arguments()[0].function_space()

        me.v = Function(me.V) # Adjoint variable
        me.z = Function(me.Z)
        S2 = replace(me.S, {TestFunction(me.V) : me.v})
        Q2 = replace(me.Q, {TestFunction(me.Z) : me.z})
        lagrangian = Q2 + S2

        me.A = derivative(lagrangian, me.u, TestFunction(me.V)) # Adjoint equation
        me.G = derivative(lagrangian, me.m, TestFunction(me.M))

        me.vv = {me.v : frozenbag()}
        me.ivv = {frozenbag() : me.v}

        me.AA = {me.A : frozenbag()}
        me.iAA = {frozenbag() : me.A}

        me.GG = {me.G : frozenbag()}
        me.iGG = {frozenbag() : me.G}

        me.solved_variables = set()

        me.all_right_hand_sides = dict() # equation -> rhs form

        me.__incremental_state_solver, me.__incremental_adjoint_solver = me.__make_solvers()

        #

        n_hash_vecs = 10
        me.__M_hash_vecs = np.random.randn(n_hash_vecs, me.M.dim())
        # me.__V_hash_vecs = np.random.randn(n_hash_vecs, me.V.dim())
        me.__Z_hash_vecs = np.random.randn(n_hash_vecs, me.Z.dim())

        me.__m_hash = me.__compute_function_hash(me.m)
        me.__z_hash = me.__compute_function_hash(me.z)
        me.__pp_hashes = dict() # derivative direction p -> hash vector
        me.__hash_tol = 1e-14

        me.num_changed_p = 0
예제 #9
0
파일: p88.py 프로젝트: domspad/euler
def calc_k(bag):
	prod = reduce(lambda x,y: x*y, bag, 1)
	return prod - sum(bag) + len(bag)



found_ks = defaultdict(int)
FOUND_KS = set()

for e,pf in enumerate(prime_fact_upto(N)):
	if e < 2:
		continue
	if e % 100 == 0:
		print e
partitions = partition(trans_pf_dict_to_bag(pf))
bags = set(frozenbag(map(lambda x: reduce(lambda y,z: y*z, x, 1), p)) for p in partitions)
for k in map(calc_k, bags):
	FOUND_KS.add(k)
	if found_ks[k] == 0:
		found_ks[k] = e

print sum(set((found_ks[i] for i in xrange(2,12001))))

########################################################################

#dp method?
N = 100
K = N/2

# prod_partitions = [[(,)]*K for i in xrange(N)]
 def test_one_bin(self):
     '''When one bin, return single bin containing all items'''
     assert multi_way_partitioning([(1,2), (2,3)], bin_count=1) == bag([frozenbag([1,2])])
 def test_one_item(self):
     '''When one item, return 1 singleton and x empty bins'''
     assert multi_way_partitioning([(1,2)], bin_count=2) == bag([frozenbag([1]), frozenbag()])
 def test_no_items(self):
     '''When no items, return empty bins'''
     assert multi_way_partitioning([], bin_count=2) == bag([frozenbag(), frozenbag()])