def _partial_constraints_add(problem, row_increment, column_increment, index_to_row_to_column, first_to_second_to_is, name): t_square = len(index_to_row_to_column) t = int(round(math.sqrt(t_square))) assert t**2 == t_square first_index_to_second_index_to_row_to_column = LpVariable.matrix( name, (list(range(t_square)), list( range(t_square)), list(range(t - row_increment)), list(range(t - column_increment))), lowBound=0, upBound=1, cat=LpInteger) for first_index in range(t_square): for second_index in range(t_square): for row in range(t - row_increment): for column in range(t - column_increment): problem += \ first_index_to_second_index_to_row_to_column[first_index][second_index][row][column] <= \ index_to_row_to_column[first_index][row][column] problem += \ first_index_to_second_index_to_row_to_column[first_index][second_index][row][column] <= \ index_to_row_to_column[second_index][row + row_increment][column + column_increment] problem += first_to_second_to_is[first_index][second_index] == \ lpSum(SolverLP._flatten( first_index_to_second_index_to_row_to_column[first_index][second_index])) return first_index_to_second_index_to_row_to_column
def _partial_objective(index_to_row_to_column, first_to_second_to_probability, name): t_square = len(index_to_row_to_column) first_to_second_to_is = LpVariable.matrix( name, (list(range(t_square)), list(range(t_square))), lowBound=0, upBound=1, cat=LpInteger) objective = [ lpDot(first_to_second_to_is[first][second], first_to_second_to_probability[first][second]) for first in range(t_square) for second in range(t_square) if first != second ] return first_to_second_to_is, objective
def L1_E3(n, m, l, c, a, b, d, D): model = LpProblem('Bodegas', LpMinimize) # Variables de decisiones. var_name = [ str(i) + str(j) for i in range(1, n + 1) for j in range(1, m + 1) ] var_name.sort() var_temp = LpVariable.matrix('x', var_name, cat='Integer', lowBound=0) x = np.array(var_temp).reshape(2, 5) # Funcion objetiva: fun_obj = lpSum(lpSum(c[j] * x[i][j] for j in range(m)) for i in range(n)) - lpSum(c[j] * d[j] for j in range(m)) model += fun_obj # Restrinciones: for i in range(n): for k in range(l): model += lpSum(x[i][j] * a[j][k] for j in range(m)) == lpSum(x[i][j] * b[i][k] for j in range(m)) for j in range(m): model += lpSum(x[i][j] for i in range(n)) >= d[j] for i in range(n): model += lpSum(x[i][j] for j in range(m)) >= D[i] for i in range(n): for j in range(m): model += x[i][j] >= 0 model.solve() model_status = LpStatus[model.status] print('Modelo:', model) print(model_status) print('Ganancia total: ', model.objective.value()) print('Variables de desiciones:') for var in model.variables(): try: print(var.name, '=', var.value()) except: print('Error: Couldn\'t find value')
def run_optimisation(self): # Declare problem instance, max/min problem self.prob = LpProblem("Squad", LpMaximize) # Declare decision variable - 1 if a player is part of the squad else 0 self.decision = LpVariable.matrix("decision", list(self.data_length), 0, 1, LpInteger) # Objective function -> Maximize specified optimisation parameter self.prob += lpSum(self.opt_param_list[i] * self.decision[i] for i in self.data_length) # Constraint definition self.add_constraints() # solve problem self.prob.solve() # extract selected players and return return [ self.opt_id_list[i] for i in self.data_length if self.decision[i].varValue ]
def _predict(self, left_index_to_right_index_to_probability, top_index_to_bottom_index_to_probability, return_log_objective=False): print('Solving lp') t_square = left_index_to_right_index_to_probability.shape[0] t = int(round(math.sqrt(t_square))) assert t**2 == t_square problem = LpProblem(name="permutation", sense=LpMaximize) index_to_row_to_column = LpVariable.matrix( 'index_to_row_to_column', (list(range(t_square)), list(range(t)), list(range(t))), lowBound=0, upBound=1, cat=LpInteger, ) left_index_to_right_index_to_is_left, horizontal_objective = \ SolverLP._partial_objective( index_to_row_to_column, left_index_to_right_index_to_probability, 'left_index_to_right_index_to_is_left' ) top_index_to_bottom_index_to_is_top, vertical_objective = \ SolverLP._partial_objective( index_to_row_to_column, top_index_to_bottom_index_to_probability, 'top_index_to_bottom_index_to_is_top' ) problem += lpSum(horizontal_objective + vertical_objective) left_index_to_right_index_to_row_to_column_to_is = SolverLP._partial_constraints_add( problem, 0, 1, index_to_row_to_column, left_index_to_right_index_to_is_left, 'left_index_to_right_index_to_row_to_column_to_is') top_index_to_bottom_index_to_row_to_column_to_is = SolverLP._partial_constraints_add( problem, 1, 0, index_to_row_to_column, top_index_to_bottom_index_to_is_top, 'top_index_to_bottom_index_to_row_to_column_to_is') # Each element has single position for index in range(t_square): problem += 1 == lpSum(index_to_row_to_column[index][row][column] for row in range(t) for column in range(t)) # Each position has single stander for row in range(t): for column in range(t): problem += 1 == lpSum( index_to_row_to_column[index][row][column] for index in range(t_square)) # Here comes the voodoo, you do not really need, for sanity or debug probably problem += t * (t - 1) == lpSum( SolverLP._flatten(left_index_to_right_index_to_is_left)) problem += t * (t - 1) == lpSum( SolverLP._flatten(top_index_to_bottom_index_to_is_top)) problem.writeLP('current-problem.lp') problem.solve() if LpStatusOptimal != problem.status: print('Warning: status is ', LpStatus[problem.status]) prediction = [ np.argmax([ index_to_row_to_column[index][row][column].value() for row in range(t) for column in range(t) ]) for index in range(t_square) ] return (prediction, None) if return_log_objective else prediction
def optimise_selection( schedule_input: pd.DataFrame, selection_limit: int, black_points_limit: int, rounds: List[str], loser: Optional[str] = None, ) -> Dict[str, Any]: """ Optimise player selection. :param schedule_input: Players and their schedule. :param selection_limit: Number of players to choose. :param black_points_limit: Maximum number of black points. :param rounds: Rounds to play :param loser: Selected loser :return: Optimal selection """ LOGGER.info("Optimising selection") schedule = schedule_input.copy() black_extra = 0 selection_limit_extra = 0 extra_loss = 0 if loser: loser_record = schedule[schedule["player"].str.lower() == loser.lower()].iloc[0] if loser_record.empty: LOGGER.warning("Unable to find player %s in draw", loser) loser = None else: loser = loser_record.player # extra_loss = TennisPoolEmulator.rounds_to_score( # rounds=loser_record.rounds, # black=loser_record.black, # loser=True # ) extra_loss = TennisPoolEmulator.probabilities_to_score( round_probs=loser_record[rounds], black=loser_record.black, loser=True) schedule.loc[schedule.player == loser, "potency"] = extra_loss black_extra = loser_record.black selection_limit_extra = 1 LOGGER.info( "Allowing %d extra black points, because of your selected loser", black_extra, ) LOGGER.info( "Adding the loser to your selection, and simultaneously increasing the limit of your" "selection, such that your loser is taken into account.") black_points_limit += black_extra players = schedule["player"].tolist() potency = schedule["potency"].tolist() black_points = schedule["black"].tolist() param_player = range(len(schedule)) # Declare problem instance, maximization problem probability = LpProblem("PlayerSelection", LpMaximize) # Declare decision variable x, which is 1 if a # player is part of the selection and 0 else param_x = LpVariable.matrix("x", list(param_player), 0, 1, LpInteger) # Objective function -> Maximise potency probability += sum(potency[p] * param_x[p] for p in param_player) # Constraint definition probability += sum(param_x[p] for p in param_player) == (selection_limit + selection_limit_extra) probability += (sum(black_points[p] * param_x[p] for p in param_player) <= black_points_limit) if loser: probability += param_x[players.index(loser)] == 1 # Start solving the problem instance probability.solve() # Extract solution player_selection = [ players[p] for p in param_player if param_x[p].varValue ] LOGGER.info("Optimiser finished") if loser: LOGGER.warning( "Do note you're going to lose %d points because of your loser.", -extra_loss) return { "schedule": schedule[schedule["player"].isin( player_selection)].copy().reset_index(), "loser": extra_loss, }
from pulp import * players = bbal_data['Player'] salary = bbal_data['Salary'] std_score = bbal_data['STD_Score'] points = bbal_data['PTS'] fix = bbal_data['Fix'] owner = bbal_data['Status'] P = range(len(players)) S = 200 prob = LpProblem("Optimal_Lineup", LpMaximize) # Declare decision variable x, which is 1 if a # player is part of the portfolio and 0 else x = LpVariable.matrix("x", list(P), 0, 1, LpInteger) # Objective function -> Maximize z-score prob += sum(std_score[p] * x[p] for p in P) # Constraint definition prob += sum(x[p] for p in P) == 13 prob += sum(salary[p] * x[p] for p in P) <= 200 # Can add more constraints # Start solving the problem instance prob.solve() # Extract solution lineup = [players[p] for p in P if x[p].varValue]