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)
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
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
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
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
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)
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
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()])