def ilp(prods, n_prods, alpha): S1, S2, S3, S4 = segregate(prods, n_prods, alpha) x = np.array([0.0 for i in range(n_prods)]) d = 0 for prod in S1: x[prod.index] = 1 d = d + (prod.q - alpha) rev = [-1.0 for i in range(n_prods)] qdiff = [-1.0 for i in range(n_prods)] for prod in S2: ind = prod.index rev[ind] = prod.r qdiff[ind] = prod.q - alpha for prod in S3: ind = prod.index rev[ind] = prod.r qdiff[ind] = prod.q - alpha m = Model('ilp') m.verbose = False y = [m.add_var(var_type=BINARY) for i in range(n_prods)] m.objective = maximize(xsum(rev[i] * y[i] for i in range(n_prods))) m += xsum(qdiff[i] * y[i] for i in range(n_prods)) >= -1 * d m.optimize() selected = np.array([y[i].x for i in range(n_prods)]) import pdb pdb.set_trace() selected = np.floor(selected + 0.01) import pdb pdb.set_trace() return x + selected, d
def set_opt_model_func(model, profile, in_committee, committeesize): load = {} for cand in profile.candidates: for i, voter in enumerate(profile): load[(voter, cand)] = model.add_var(lb=0.0, ub=1.0, var_type=mip.CONTINUOUS, name=f"load{i}-{cand}") # constraint: the committee has the required size model += mip.xsum(in_committee[cand] for cand in profile.candidates) == committeesize for cand in profile.candidates: for voter in profile: if cand not in voter.approved: load[(voter, cand)] = 0 # a candidate's load is distributed among his approvers for cand in profile.candidates: model += (mip.xsum( voter.weight * load[(voter, cand)] for voter in profile if cand in profile.candidates) >= in_committee[cand]) loadbound = model.add_var(lb=0, ub=committeesize, var_type=mip.CONTINUOUS, name="loadbound") for voter in profile: model += mip.xsum(load[(voter, cand)] for cand in voter.approved) <= loadbound # maximizing the negative distance makes code more similar to the other methods here model.objective = mip.maximize(-loadbound)
def set_opt_model_func(model, profile, in_committee, committeesize, previously_found_committees, scorefct): max_hamming_distance = model.add_var( var_type=mip.INTEGER, lb=0, ub=profile.num_cand, name="max_hamming_distance", ) model += mip.xsum(in_committee[cand] for cand in profile.candidates) == committeesize for voter in profile: not_approved = [ cand for cand in profile.candidates if cand not in voter.approved ] # maximum Hamming distance is greater of equal than the Hamming distances # between individual voters and the committee model += max_hamming_distance >= mip.xsum( 1 - in_committee[cand] for cand in voter.approved) + mip.xsum( in_committee[cand] for cand in not_approved) # find a new committee that has not been found before for committee in previously_found_committees: model += mip.xsum(in_committee[cand] for cand in committee) <= committeesize - 1 # maximizing the negative distance makes code more similar to the other methods here model.objective = mip.maximize(-max_hamming_distance)
def do_matching(graph, visualize=True): print("Starting model") weights = dict() graph = {int(key): graph[key] for key in graph} E = set() V = graph.keys() for v in V: original = v for u, weight in graph[original]: s, t = (u, v) if u < v else (v, u) edge = (s, t) E.add(edge) weights[original, u] = weight if visualize: graph = nx.Graph() graph.add_nodes_from(V) graph.add_edges_from(E) nx.draw_kamada_kawai(graph) plt.show() model = Model("Maximum matching") edge_vars = {e: model.add_var(var_type=BINARY) for e in E} for v in V: model += xsum(edge_vars[s, t] for s, t in E if v in [s, t]) <= 1 model.objective = maximize( xsum( xsum(((weights[edge] + weights[edge[1], edge[0]]) / 2) * edge_vars[edge] for edge in E) for edge in E)) model.optimize(max_seconds=300) return sorted([e for e in E if edge_vars[e].x > .01])
def mip_optimization(cal_df, y, constrain=3, daily_weights=None): """Mixed integer linear programming optimization with constraints. Args: y (numpy.ndarray): sum of daily features (dim=#ofdays) constrain (int): minimum days in office daily_weights (array): weighting of days, e.g. if you prefer to come on mondays Return: """ # daily weighting u = np.ones(len(y)) if daily_weights == None else daily_weights I = range(len(y)) # idx for days for summation m = Model("knapsack") # MIP model w = [m.add_var(var_type=BINARY) for i in I] # weights to optimize m.objective = maximize(xsum(y[i] * w[i] for i in I)) # optimization function m += xsum(w[i] * u[i] for i in I) <= constrain # constraint m.optimize() #selected = [i for i in I if w[i].x >= 0.99] selected = [w[i].x for i in I] df = pd.DataFrame(columns=["home_office"], index=cal_df.index, data={'home_office': selected}) return df
def test_knapsack(solver: str): p = [10, 13, 18, 31, 7, 15] w = [11, 15, 20, 35, 10, 33] c, I = 47, range(len(w)) m = Model("knapsack", solver_name=solver) x = [m.add_var(var_type=BINARY) for i in I] m.objective = maximize(xsum(p[i] * x[i] for i in I)) m += xsum(w[i] * x[i] for i in I) <= c, "cap" m.optimize() assert m.status == OptimizationStatus.OPTIMAL assert round(m.objective_value) == 41 m.constr_by_name("cap").rhs = 60 m.optimize() assert m.status == OptimizationStatus.OPTIMAL assert round(m.objective_value) == 51 # modifying objective function m.objective = m.objective + 10 * x[0] + 15 * x[1] assert abs(m.objective.expr[x[0]] - 20) <= 1e-10 assert abs(m.objective.expr[x[1]] - 28) <= 1e-10
def test_linexpr_x(solver: str, val: int): m = Model("bounds", solver_name=solver) x = m.add_var(lb=0, ub=2 * val) y = m.add_var(lb=val, ub=2 * val) obj = x - y assert obj.x is None # No solution yet. m.objective = maximize(obj) m.optimize() assert m.status == OptimizationStatus.OPTIMAL assert round(m.objective_value) == val assert round(x.x) == 2 * val assert round(y.x) == val # Check that the linear expression value is equal to the same expression # calculated from the values of the variables. assert abs((x + y).x - (x.x + y.x)) < TOL assert abs((x + 2 * y).x - (x.x + 2 * y.x)) < TOL assert abs((x + 2 * y + x).x - (x.x + 2 * y.x + x.x)) < TOL assert abs((x + 2 * y + x + 1).x - (x.x + 2 * y.x + x.x + 1)) < TOL assert abs((x + 2 * y + x + 1 + x / 2).x - (x.x + 2 * y.x + x.x + 1 + x.x / 2)) < TOL
def knapsack(): p = [10, 13, 18, 31, 7, 15] w = [11, 15, 20, 35, 10, 33] c, I = 47, range(len(w)) m = Model("knapsack") x = [m.add_var(var_type=BINARY) for i in I] m.objective = maximize(xsum(p[i] * x[i] for i in I)) m += xsum(w[i] * x[i] for i in I) <= c print(m.optimize())
def do_matching_stable(graph, visualize=True, individual=1, communal=10000000): print("Starting model") weights = dict() graph = {int(key): graph[key] for key in graph} E = set() V = graph.keys() inputs = {v: [] for v in V} outputs = {v: [] for v in V} for v in V: original = v for u, weight in graph[original]: s, t = (u, v) if u < v else (v, u) edge = (s, t) E.add(edge) weights[(original, u)] = weight outputs[original].append(u) inputs[u].append(original) if visualize: graph = nx.Graph() graph.add_nodes_from(V) graph.add_edges_from(E) nx.draw_kamada_kawai(graph) plt.show() model = Model("Rogue Couples based") edge_vars = {e: model.add_var(var_type=BINARY) for e in E} undirected = dict() for e in E: undirected[e] = edge_vars[e] undirected[e[1], e[0]] = edge_vars[e] rogue_vars = {e: model.add_var(var_type=BINARY) for e in E} partners = dict() for v in V: partners[v] = model.add_var() partners[v] = xsum(edge_vars[s, t] for s, t in E if v in [s, t]) model += partners[v] <= 1 for (u, v), rogue_var in rogue_vars.items(): v_primes = [ vp for vp in outputs[u] if weights[(u, vp)] < weights[(u, v)] ] u_primes = [ up for up in outputs[v] if weights[(v, up)] < weights[(v, u)] ] model += 1 - partners[v] - partners[u] + xsum( undirected[u, vp] for vp in v_primes) + xsum(undirected[up, v] for up in u_primes) <= rogue_var model.objective = maximize(individual * xsum( ((weights[edge] + weights[edge[1], edge[0]]) / 2) * edge_vars[edge] for edge in E) - communal * xsum(rogue_vars[edge] for edge in E)) model.optimize(max_seconds=300) return sorted([e for e in E if edge_vars[e].x > .01])
def set_opt_model_func(model, profile, in_committee, committeesize, previously_found_committees, scorefct): num_voters = len(profile) # optimization goal: variable "satisfaction" satisfaction = model.add_var(ub=num_voters, var_type=mip.INTEGER, name="satisfaction") model += mip.xsum(in_committee[cand] for cand in profile.candidates) == committeesize # a partition of voters into `committeesize` many sets partition = {} for cand in profile.candidates: for voter in range(len(profile)): partition[(cand, voter)] = model.add_var(var_type=mip.BINARY, name="partition") for voter in range(len(profile)): # every voter has to be part of a voter partition set model += mip.xsum(partition[(cand, voter)] for cand in profile.candidates) == 1 for cand in profile.candidates: # every voter set in the partition has to contain # at least (num_voters // committeesize) candidates model += mip.xsum(partition[(cand, voter)] for voter in range(len(profile))) >= ( num_voters // committeesize - num_voters * (1 - in_committee[cand])) # every voter set in the partition has to contain # at most ceil(num_voters/committeesize) candidates model += mip.xsum( partition[(cand, voter)] for voter in range(len(profile))) <= ( num_voters // committeesize + bool(num_voters % committeesize) + num_voters * (1 - in_committee[cand])) # if in_committee[i] = 0 then partition[(i,j) = 0 model += (mip.xsum(partition[(cand, voter)] for voter in range(len(profile))) <= num_voters * in_committee[cand]) # constraint for objective variable "satisfaction" model += (mip.xsum(partition[(cand, voter)] * (cand in profile[voter].approved) for voter in range(len(profile)) for cand in profile.candidates) >= satisfaction) # find a new committee that has not been found before for committee in previously_found_committees: model += mip.xsum(in_committee[cand] for cand in committee) <= committeesize - 1 # optimization objective model.objective = mip.maximize(satisfaction)
def test_variable_bounds(solver: str, val: int): m = Model("bounds", solver_name=solver) x = m.add_var(var_type=INTEGER, lb=0, ub=2 * val) y = m.add_var(var_type=INTEGER, lb=val, ub=2 * val) m.objective = maximize(x - y) m.optimize() assert m.status == OptimizationStatus.OPTIMAL assert round(m.objective_value) == val assert round(x.x) == 2 * val assert round(y.x) == val
def random_knapsack(n: int, interval): I = range(n) p = [randrange(*interval) for _ in I] w = [randrange(*interval) for _ in I] c = round(sum(interval) / 2 * n) m = Model("random-knapsack") x = [m.add_var(var_type=BINARY) for i in I] m.objective = maximize(xsum(p[i] * x[i] for i in I)) m += xsum(w[i] * x[i] for i in I) <= c start = monotonic() print(m.optimize()) print(f"DURATION: {(monotonic() - start) * 1000} ms")
def solve_model(model, varrange, state_values, min_frames=True, output=True, relaxation=False): size = len(varrange) max_damage = 0 min_r_frames = 0 min_d_frames = 0 dps = 0 solution = { 'dataTable' : [], 'decisionVariables' : [] } # testpath = os.getcwd() + '/lptemplates/lpfiles/TESTING.lp' model.objective = mip.maximize(mip.xsum(state_values['damage'][i]*varrange[i] for i in range(size))) # model.write(testpath) # a test file for debugging if not output: model.verbose = 0 model.optimize(relax=relaxation) # right here is where you'd change model properties for speed print(model.status) if model.status not in [mip.OptimizationStatus.OPTIMAL]: solution['dataTable'].append({'id' : 'status', 'value' : 'INFEASIBLE'}) solution['decisionVariables'].append({'id' : 'N/A', 'value' : 'N/A'}) return solution max_damage = model.objective_value if min_frames: model += mip.xsum(state_values['damage'][i]*varrange[i] for i in range(size)) == max_damage model.objective = mip.minimize(mip.xsum(state_values['realframes'][i]*varrange[i] for i in range(size))) model.optimize(relax=relaxation) for i in range(size): if abs(varrange[i].x) > 1e-6: # only non-zeros if 'Dummy' in varrange[i].name: continue solution['decisionVariables'].append({'id' : [varrange[i].name], 'value' : varrange[i].x}) min_r_frames += varrange[i].x*state_values['realframes'][i] min_d_frames += varrange[i].x*state_values['frames'][i] if min_r_frames <= 0: dps = 0 else: dps = round((60*max_damage/min_r_frames), 2) solution['dataTable'].append({'id' : 'Max Damage', 'value' : max_damage}) solution['dataTable'].append({'id' : 'DPS', 'value' : dps}) solution['dataTable'].append({'id' : 'Dragon Time', 'value' : min_d_frames}) solution['dataTable'].append({'id' : 'Real Time', 'value' : min_r_frames}) if output: print('solution:') for v in model.vars: if abs(v.x) > 1e-6: # only printing non-zeros print('{} : {}'.format(v.name, v.x)) print(model.status) for statistic in solution['dataTable']: print('{:11} : {:10}'.format(statistic['id'], statistic['value'])) return solution
def do_matching_double_matches(graph, wants_two_matches=None): print("Starting model") weights = dict() graph = {int(key): graph[key] for key in graph} E = set() V = graph.keys() if not wants_two_matches: wants_two_matches = {v: True for v in V} inputs = {v: [] for v in V} outputs = {v: [] for v in V} for v in V: original = v for u, weight in graph[original]: s, t = (u, v) if u < v else (v, u) edge = (s, t) E.add(edge) weights[(original, u)] = weight outputs[original].append(u) inputs[u].append(original) model = Model("Allow double matches based") edge_vars = {e: model.add_var(var_type=BINARY) for e in E} undirected = dict() for e in E: undirected[e] = edge_vars[e] undirected[e[1], e[0]] = edge_vars[e] is_best = {e: model.add_var(var_type=BINARY) for e in undirected.keys()} penalty = {v: model.add_var(var_type=BINARY) for v in V} happiness = {v: model.add_var() for v in V} epsilon = .0000001 C = 1e3 for v in V: model += xsum(edge_vars[s, t] for s, t in E if v in [s, t]) <= 1 + penalty[v] * wants_two_matches[v] model += happiness[v] <= xsum(edge_vars[s, t] for s, t in E if v in [s, t]) * C if outputs[v]: model += xsum(is_best[(v, m)] for m in outputs[v]) == 1 for m in outputs[v]: model += happiness[v] <= undirected[(v, m)] * weights[ (v, m)] + (1 - is_best[(v, m)]) * C else: happiness[v] <= 0 model.objective = maximize( xsum(happiness[v] for v in V) - epsilon * xsum(penalty[v] for v in V)) model.optimize(max_seconds=300) return sorted([e for e in E if edge_vars[e].x > .01])
def create_mip(solver, J, dur, S, c, r, EST, relax=False, sense=MINIMIZE): """Creates a mip model to solve the RCPSP""" NR = len(c) mip = Model(solver_name=solver) sd = sum(dur[j] for j in J) vt = CONTINUOUS if relax else BINARY x = [ { t: mip.add_var("x(%d,%d)" % (j, t), var_type=vt) for t in range(EST[j], sd + 1) } for j in J ] TJ = [set(x[j].keys()) for j in J] T = set() for j in J: T = T.union(TJ[j]) if sense == MINIMIZE: mip.objective = minimize(xsum(t * x[J[-1]][t] for t in TJ[-1])) else: mip.objective = maximize(xsum(t * x[J[-1]][t] for t in TJ[-1])) # one time per job for j in J: mip += xsum(x[j][t] for t in TJ[j]) == 1, "selTime(%d)" % j # precedences for (u, v) in S: mip += ( xsum(t * x[v][t] for t in TJ[v]) >= xsum(t * x[u][t] for t in TJ[u]) + dur[u], "prec(%d,%d)" % (u, v), ) # resource usage for t in T: for ir in range(NR): mip += ( xsum( r[ir][j] * x[j][tl] for j in J[1:-1] for tl in TJ[j].intersection( set(range(t - dur[j] + 1, t + 1)) ) ) <= c[ir], "resUsage(%d,%d)" % (ir, t), ) return mip
def test_float(solver: str, val: int): m = Model("bounds", solver_name=solver) x = m.add_var(lb=0, ub=2 * val) y = m.add_var(lb=val, ub=2 * val) obj = x - y # No solution yet. __float__ MUST return a float type, so it returns nan. assert obj.x is None assert math.isnan(float(obj)) m.objective = maximize(obj) m.optimize() assert m.status == OptimizationStatus.OPTIMAL # test vars. assert x.x == float(x) assert y.x == float(y) # test linear expressions. assert float(x + y) == (x + y).x
def optimize_player_strategy(player_cards: List[int], opponent_cards: List[int], payoff_matrix: Matrix) -> Strategy: """ Get the optimal strategy for the player, by solving a simple linear program based on payoff matrix. """ lp = mip.Model("player_strategy", solver_name=mip.CBC) lp.verbose = False # the problems are simple and we don't need to see the output x = [ lp.add_var(f"x_{card}", var_type=mip.CONTINUOUS) for card in player_cards ] v = lp.add_var("v", var_type=mip.CONTINUOUS, lb=-mip.INF) for opponent_card in opponent_cards: transposed_row = [ payoff_matrix[(player_card, opponent_card)] for player_card in player_cards ] constraint = (mip.xsum(transposed_row[i] * x_i for i, x_i in enumerate(x)) - v >= 0) lp += constraint, f"strategy_against_{opponent_card}" logging.debug(f"constraint={constraint}") lp += mip.xsum(x) == 1, "probability_distribution" lp.objective = mip.maximize(v) # all variables are continuous so we only need to solve relaxed problem lp.optimize(max_seconds=30, relax=True) if lp.status is not mip.OptimizationStatus.OPTIMAL: logging.error(f"lp.status={lp.status}") raise RuntimeError( f"Solver couldn't optimize the problem and returned status {lp.status}" ) strategy = Strategy( card_probabilities={ card: lp.var_by_name(f"x_{card}").x for card in player_cards }, expected_value=lp.var_by_name("v").x, ) logging.debug(f"strategy.expected_value={strategy.expected_value}") logging.debug("\n") return strategy
def do_matching_two_round(graph): print("Starting model") weights = dict() graph = {int(key): graph[key] for key in graph} E = set() V = graph.keys() inputs = {v: [] for v in V} outputs = {v: [] for v in V} for v in V: original = v for u, weight in graph[original]: s, t = (u, v) if u < v else (v, u) edge = (s, t) E.add(edge) weights[(original, u)] = weight outputs[original].append(u) inputs[u].append(original) model = Model("Rogue Couples based") edge_vars = {e: model.add_var(var_type=BINARY) for e in E} undirected = dict() for e in E: undirected[e] = edge_vars[e] undirected[e[1], e[0]] = edge_vars[e] second_vars = {e: model.add_var(var_type=BINARY) for e in E} partners = dict() second_round_partners = dict() for v in V: partners[v] = model.add_var() model += partners[v] == xsum(edge_vars[s, t] for s, t in E if v in [s, t]) model += partners[v] <= 1 for v in V: second_round_partners[v] = model.add_var() model += second_round_partners[v] == xsum(second_vars[s, t] for s, t in E if v in [s, t]) model += second_round_partners[v] <= 1 for e in E: u, v = e model += second_vars[(u, v)] <= 2 - partners[v] - partners[u] model.objective = maximize( xsum(((weights[edge] + weights[edge[1], edge[0]]) / 2) * (edge_vars[edge] + second_vars[edge]) for edge in E)) model.optimize(max_seconds=1000) return sorted([e for e in E if edge_vars[e].x > .01] + [e for e in E if second_vars[e].x > .01])
def Int_Knapsack(f,d, V_d, Kf): p = list(np.ones((len(V_d),),dtype=int)) m = Model("knapsack") #x = [m.add_var(var_type=BINARY) for i in list(V_d.keys())] x = [(i,m.add_var(var_type=BINARY)) for i in list(V_d.keys())] m.objective = maximize(xsum(p[i] * x[i][1] for i in range(len(x)))) m += xsum(V_d[x[i][0]] * x[i][1] for i in range(len(x))) <= Kf[f] m.optimize() #selected = [i for i in list(V_d.keys()) if x[i].x >= 0.99] selected = [x[i][0] for i in range(len(x)) if x[i][1].x >= 0.99] #print("selected items: {}".format(selected)) y=(d,selected,f) return y #sol = Int_Knapsack(f,d,V_d, Kf)
def max_utilitarian_welfare_allocation(utilities: Dict[int, List[float]], m: Model) -> None: """ Computes (one of) the item allocation(s) which maximizes utilitarian welfare, returning the optimized model. :param utilities: the dictionary representing the utility profile, where each key is an agent and its value an array of floats such that the i-th float is the utility of the i-th item for the key-agent. :param m: the MIP model which represents the integer linear program. """ agents, items = len(utilities), len(list(utilities.values())[0]) m.objective = maximize( xsum(utilities[agent][item] * m.var_by_name('assign_{}_{}'.format(item, agent)) for item in range(items) for agent in range(agents))) m.optimize()
def set_opt_model_func(model, profile, in_committee, committeesize): # utility[(voter, x)] contains (intended binary) variables counting the number of approved # candidates in the selected committee by `voter`. This utility[(voter, x)] is true for # exactly the number of candidates in the committee approved by `voter` for all # x = 1...committeesize. utility = {} iteration = len(satisfaction_constraints) marginal_scorefcts = [ scores.get_marginal_scorefct(f"atleast{i + 1}") for i in range(iteration + 1) ] max_in_committee = {} for i, voter in enumerate(profile): # maximum number of approved candidates that this voter can have in a committee max_in_committee[voter] = min(len(voter.approved), committeesize) for x in range(1, max_in_committee[voter] + 1): utility[(voter, x)] = model.add_var(var_type=mip.BINARY, name=f"utility({i},{x})") # constraint: the committee has the required size model += mip.xsum(in_committee) == committeesize # constraint: utilities are consistent with actual committee for voter in profile: model += mip.xsum( utility[voter, x] for x in range(1, max_in_committee[voter] + 1)) == mip.xsum( in_committee[cand] for cand in voter.approved) # additional constraints from previous iterations for prev_iteration in range(iteration): model += (mip.xsum( float(marginal_scorefcts[prev_iteration](x)) * voter.weight * utility[(voter, x)] for voter in profile for x in range(1, max_in_committee[voter] + 1)) >= satisfaction_constraints[prev_iteration] - ACCURACY) # objective: the at-least-y score of the committee in iteration y model.objective = mip.maximize( mip.xsum( float(marginal_scorefcts[iteration](x)) * voter.weight * utility[(voter, x)] for voter in profile for x in range(1, max_in_committee[voter] + 1)))
def get_lineups(self, slate, ptcol, lineups, salcap=50000): positions = slate['positions'] pool= pd.concat(slate['players'].values(),ignore_index='True').drop(columns='position')\ .drop_duplicates().reset_index(drop=True) #Establish positions eligibility data structure elig = [[ 1 if plyr['name'] in list(slate['players'][pos]['name']) else 0 for i, pos in enumerate(positions) ] for skip, plyr in pool.iterrows()] pts = list(pool[ptcol]) #Set up player salary list sal = list(pool['salary']) #Set up range just for short reference I = range(len(pts)) J = range(len(positions)) #Set up results results = [] m = Model() m.verbose = False x = [[m.add_var(var_type=BINARY) for j in J] for i in I] m.objective = maximize( xsum(x[i][j] * elig[i][j] * pts[i] for i in I for j in J)) #Apply salary cap constraint m += xsum((x[i][j] * sal[i] for i in I for j in J)) <= salcap #Apply one player per position constraint for j in J: m += xsum(x[i][j] for i in I) == 1 #apply max one position per player constraint for i in I: m += xsum(x[i][j] for j in J) <= 1 for lineup in range(lineups): print(lineup) m.optimize() #Add lineup to results idx = [(i, j) for i in I for j in J if x[i][j].x >= 0.99] results.append( pd.concat([pool.iloc[i:i + 1] for i, j in idx], ignore_index=True)) results[-1]['position'] = [positions[j] for i, j in idx] #Apply constraint to ensure this player combination will not be repeated (cannot have three overlapping players for diversity) m += xsum(x[i][j] for i, skip in idx for j in J) <= len(positions) - 3 return results
def ILP_optA_solution(tasks, cpu, tk, model=Model()): # init A = cpu.A M = cpu.M Sk = tk.s tasks = [t for t in tasks if t != tk] n = len(tasks) I = [t.W(Sk) for t in tasks] a = [t.a for t in tasks] Ak = opt(tasks, cpu, tk) if (n <= 0): return 0 if (Ak == 0): Ak = A # Ak = A # model = Model() model.clear() x = { i: model.add_var(obj=0, var_type="C", name="x[%d]" % i) for i in range(n) } y = { i: model.add_var(obj=0, var_type="C", name="y[%d]" % i) for i in range(n) } model.objective = maximize( xsum((1 / M) * x[i] + (a[i] / Ak) * y[i] for i in range(n))) model.verbose = False for i in range(n): model += x[i] + y[i] <= I[i] for i in range(n): model += x[i] <= xsum((1 / M) * x[j] for j in range(n)) for i in range(n): model += y[i] <= xsum((a[j] / Ak) * y[j] for j in range(n)) model.optimize() return model.objective_value
def maximize_sum(plfs, max_costs): # pylint: disable=too-many-locals m = Model("bid-landscapes") costs = LinExpr() objective = LinExpr() xs = [] ws = [] for (i, plf) in enumerate(plfs): k = len(plf) w = [m.add_var(var_type=CONTINUOUS) for _ in range(0, k)] x = [m.add_var(var_type=BINARY) for _ in range(0, k - 1)] xs.append(x) ws.append(w) m += xsum(w[i] for i in range(0, k)) == 1 for i in range(0, k): m += w[i] >= 0 m += w[0] <= x[0] for i in range(1, k - 1): m += w[i] <= x[i - 1] + x[i] m += w[k - 1] <= x[k - 2] m += xsum(x[k] for k in range(0, k - 1)) == 1 for i in range(0, k): costs.add_term(w[i] * plf.a[i]) objective.add_term(w[i] * plf.b[i]) m += costs <= max_costs m.objective = maximize(objective) start = monotonic() print(m.optimize()) print(f"DURATION: {(monotonic() - start) * 1000} ms") optimum = [] for (i, plf) in enumerate(plfs): k = len(plf) u_i = sum(ws[i][j].x * plf.a[j] for j in range(0, k)) v_i = sum(ws[i][j].x * plf.b[j] for j in range(0, k)) optimum.append(Line(cost=u_i, revenue=v_i, plf=plf)) return optimum
def set_opt_model_func(model, profile, in_committee, committeesize, previously_found_committees, scorefct): # utility[(voter, l)] contains (intended binary) variables counting the number of approved # candidates in the selected committee by `voter`. This utility[(voter, l)] is true for # exactly the number of candidates in the committee approved by `voter` for all # l = 1...committeesize. # # If scorefct(l) > 0 for l >= 1, we assume that scorefct is monotonic decreasing and # therefore in combination with the objective function the following interpreation is # valid: # utility[(voter, l)] indicates whether `voter` approves at least l candidates in the # committee (this is the case for scorefct "pav", "slav" or "geom"). utility = {} for i, voter in enumerate(profile): for l in range(1, committeesize + 1): utility[(voter, l)] = model.add_var(var_type=mip.BINARY, name=f"utility-v{i}-l{l}") # TODO: could be faster with lb=0.0, ub=1.0, var_type=mip.CONTINUOUS # constraint: the committee has the required size model += mip.xsum(in_committee) == committeesize # constraint: utilities are consistent with actual committee for voter in profile: model += mip.xsum( utility[voter, l] for l in range(1, committeesize + 1)) == mip.xsum( in_committee[cand] for cand in voter.approved) # find a new committee that has not been found yet by excluding previously found committees for committee in previously_found_committees: model += mip.xsum(in_committee[cand] for cand in committee) <= committeesize - 1 # objective: the PAV score of the committee model.objective = mip.maximize( mip.xsum( float(scorefct(l)) * voter.weight * utility[(voter, l)] for voter in profile for l in range(1, committeesize + 1)))
def set_opt_model_func(model, profile, in_committee, committeesize, previously_found_committees, scorefct): load = {} for cand in profile.candidates: for voter in profile: load[(voter, cand)] = model.add_var(lb=0.0, ub=1.0, var_type=mip.CONTINUOUS) # constraint: the committee has the required size model += mip.xsum(in_committee[cand] for cand in profile.candidates) == committeesize for cand in profile.candidates: for voter in profile: if cand not in voter.approved: load[(voter, cand)] = 0 # a candidate's load is distributed among his approvers for cand in profile.candidates: model += (mip.xsum( voter.weight * load[(voter, cand)] for voter in profile if cand in profile.candidates) >= in_committee[cand]) # find a new committee that has not been found before for committee in previously_found_committees: model += mip.xsum(in_committee[cand] for cand in committee) <= committeesize - 1 loadbound = model.add_var(lb=0, ub=committeesize, var_type=mip.CONTINUOUS, name="loadbound") for voter in profile: model += mip.xsum(load[(voter, cand)] for cand in voter.approved) <= loadbound # maximizing the negative distance makes code more similar to the other methods here model.objective = mip.maximize(-loadbound)
def solve_it_mip(input_data): from mip import Model, xsum, maximize, BINARY lines = input_data.split('\n') firstLine = lines[0].split() item_count = int(firstLine[0]) capacity = int(firstLine[1]) I = range(item_count) knapsack = [0] * item_count values = [0] * item_count weights = [0] * item_count for i in range(1, item_count + 1): line = lines[i] parts = line.split() values[i - 1] = int(parts[0]) weights[i - 1] = int(parts[1]) m = Model("knapsack") x = [m.add_var(var_type=BINARY) for i in I] m.objective = maximize(xsum(values[i] * x[i] for i in I)) m += xsum(weights[i] * x[i] for i in I) <= capacity m.verbose = 0 #m.emphasis = 1 status = m.optimize() selected = [i for i in I if x[i].x >= 0.99] for index in selected: knapsack[index] = knapsack[index] + 1 output_data = f"{int(m.objective_value)} {1}\n" + " ".join( map(str, knapsack)) return output_data
def test_knapsack(solver: str): p = [10, 13, 18, 31, 7, 15] w = [11, 15, 20, 35, 10, 33] c, I = 47, range(len(w)) m = Model('knapsack', solver_name=solver) x = [m.add_var(var_type=BINARY) for i in I] m.objective = maximize(xsum(p[i] * x[i] for i in I)) m += xsum(w[i] * x[i] for i in I) <= c, 'cap' m.optimize() assert m.status == OptimizationStatus.OPTIMAL assert round(m.objective_value) == 41 m.constr_by_name('cap').rhs = 60 m.optimize() assert m.status == OptimizationStatus.OPTIMAL assert round(m.objective_value) == 51
def set_opt_model_func(model, profile, in_committee, committeesize): # utility[(voter, x)] contains (intended binary) variables counting the number of approved # candidates in the selected committee by `voter`. This utility[(voter, x)] is true for # exactly the number of candidates in the committee approved by `voter` for all # x = 1...committeesize. # # If marginal_scorefct(x) > 0 for x >= 1, we assume that marginal_scorefct is monotonic # decreasing and therefore in combination with the objective function the following # interpreation is valid: # utility[(voter, x)] indicates whether `voter` approves at least x candidates in the # committee (this is the case for marginal_scorefct "pav", "slav" or "geom"). utility = {} max_in_committee = {} for i, voter in enumerate(profile): max_in_committee[voter] = min(len(voter.approved), committeesize) for x in range(1, max_in_committee[voter] + 1): utility[(voter, x)] = model.add_var(var_type=mip.BINARY, name=f"utility({i},{x})") # constraint: the committee has the required size model += mip.xsum(in_committee) == committeesize # constraint: utilities are consistent with actual committee for voter in profile: model += mip.xsum( utility[voter, x] for x in range(1, max_in_committee[voter] + 1)) == mip.xsum( in_committee[cand] for cand in voter.approved) # objective: the Thiele score of the committee model.objective = mip.maximize( mip.xsum( float(marginal_scorefct(x)) * voter.weight * utility[(voter, x)] for voter in profile for x in range(1, max_in_committee[voter] + 1)))
Groups = set(range(GROUP_COUNT)) People = set(range(len(people))) Voices = set(range(4)) model = Model("Optimizing Choir Groups") X = [[model.add_var(var_type=BINARY) for g in Groups] for p in People] A = [[[model.add_var(var_type=BINARY) for g in Groups] for p1 in People] for p2 in People] # objective function # scaling wishes with 1/sqrt(#wishes) #model.objective = maximize(xsum(L[p1][p2] * A[p1][p2][g]/math.sqrt(sum(L[p1])+1) for p1 in People for p2 in People for g in Groups)) # scaling wishes with 1/(#wishes) model.objective = maximize( xsum(L[p1][p2] * A[p1][p2][g] / max(sum(L[p1]), 1) for p1 in People for p2 in People for g in Groups)) # scaling wishes with 1 #model.objective = maximize(xsum(L[p1][p2] * A[p1][p2][g] for p1 in People for p2 in People for g in Groups)) # constraint defining A[p1][p2][g] = X[p1][g]*X[p2][g] for p1 in People: for p2 in People: for g in Groups: model += A[p1][p2][g] <= X[p1][g] model += A[p1][p2][g] <= X[p2][g] # constraints on group size for g in Groups: model += xsum(X[p][g] for p in People) <= MAX_GROUP_SIZE