def test_cplex(self, ilp): """Test method for CPLEX.""" try: ilp.solve(pulp.CPLEX_PY()) assert round(pulp.value(ilp.objective), 0) == 5 except pulp.solvers.PulpSolverError: pytest.fail(f"Solver not installed")
def find_angle_assignments(self): """Sets up and solves a linear solver""" prob = pl.LpProblem(self.word.word, pl.LpMinimize) equation = ["one", "two"] lp_variables = {} for link in self.links: for label in link.get_labels(): if label != "none": lp_variables[label] = pl.LpVariable( label, 0, None, pl.LpContinuous) lp_disc = [lp_variables[x] for x in self.attaching_disc] objective = pl.LpAffineExpression([(x, 1) for x in lp_disc]) link_equations = [] region_equations = [] num_of_edges = 0 for link in self.links: for equation in link.get_equations(): link_equations.append([ pl.LpAffineExpression([(lp_variables[x], 1) for x in equation["labels"] if x != "none"]), equation["constant"], ]) for region in self.regions: num_of_edges += len(region.get_equation()) / 2 # skips adding removed face to linear model if region.get_equation()[0] in self.removed_region.get_equation(): continue region_equations.append([ pl.LpAffineExpression([(lp_variables[str(x)], 1) for x in region.get_equation()]), len(region.get_equation()) - 2, ]) prob += objective, "minimize attaching disc" for equation in link_equations: prob += equation[0] >= equation[1] for equation in region_equations: prob += equation[0] <= equation[1] solver = pl.CPLEX_PY(msg=0) prob.solve(solver) self.curvature = pl.value( prob.objective) - (len(self.attaching_disc) - 2) angle_labels = [x.name for x in prob.variables()] angles = [x.varValue for x in prob.variables()] self.angle_assignments = dict(zip(angle_labels, angles))
def _get_solver(solver_name, timelimit): if solver_name == "cplex": return pulp.CPLEX_PY(msg=0, timeLimit=timelimit) elif solver_name == "gurobi": return pulp.GUROBI(msg=0, timeLimit=timelimit) elif solver_name == "glpk": return pulp.GLPK(msg=0, options=["--tmlim", str(timelimit)]) elif solver_name == "cbc": return pulp.COIN(msg=0, maxSeconds=timelimit) elif solver_name == "scip": return pulp.SCIP(msg=0, options=["-c", f"set limits time {timelimit}"]) raise ValueError("Invalid Solver Name")
def solve(self, solver="cbc", timeout=None): """Solves this problem and returns the problem result. :param solver: The solver that should be used. Currently supported are "cbc", "gurobi", "glpk" and "cplex", defaults to "cbc" :type solver: str, optional :return: Result. :rtype: solver.SolverResult """ assert solver in [ "gurobi", "cbc", "glpk", "cplex" ], "solver must be in ['gurobi','cbc','glpk','cplex']" if timeout != None: assert isinstance( timeout, int), "timeout must be specified in seconds as integer value" if solver == "gurobi": gurobi_options = [ ("MIPGap",0), ("MIPGapAbs",0), ("FeasibilityTol",1e-9),\ ("IntFeasTol",1e-9),("NumericFocus",3)] if timeout != None: gurobi_options.append(("TimeLimit", str(timeout))) self.__pulpmodel.setSolver(pulp.GUROBI_CMD(options=gurobi_options)) elif solver == "cbc": cbc_options = ["--integerT", "0"] self.__pulpmodel.setSolver( pulp.PULP_CBC_CMD(gapRel=1e-9, timeLimit=timeout, options=cbc_options)) elif solver == "glpk": glpk_options = ["--tmlim", str(timeout)] if timeout != None else [] self.__pulpmodel.setSolver(pulp.GLPK_CMD(options=glpk_options)) elif solver == "cplex": self.__pulpmodel.setSolver(pulp.CPLEX_PY(timeLimit=timeout)) self.__pulpmodel.solve() status = { 1: "optimal", 0: "notsolved", -1: "infeasible", -2: "unbounded", -3: "undefined" }[self.__pulpmodel.status] result_vector = np.array([var.value() for var in self.__variables]) dual_result_vector = np.array( [constr.pi for constr in self.__constraints]) value = self.__pulpmodel.objective.value() return SolverResult(status, result_vector, dual_result_vector, value)
def solve(self, milp_msg, epgap=0): epgap = 0.05 if epgap is None else epgap if self.solver_name == 'cbc' or self.solver_name == 'cplex': try: if self.solver_name == 'cbc': #self.prob.solve(solvers.PULP_CBC_CMD(msg=milp_msg, maxSeconds=None, fracGap=None)) self.prob.solve( pulp.PULP_CBC_CMD(msg=milp_msg, fracGap=epgap)) if self.solver_name == 'cplex': self.prob.solve(pulp.CPLEX_PY(msg=milp_msg, epgap=epgap)) except Exception: raise Exception('The MILP solver failed. ') if self.prob.status != 1 and self.prob.status != -1: raise Exception('MILP solution is ' + LpStatus[self.prob.status]) for variable in self.prob.variables(): self.solved_variables[variable.name] = variable.varValue return self.solved_variables, self.prob.status
def solve(self): P = self.P cplex_solver = pulp.CPLEX_PY(msg=0, mip=self.binary) if cplex_solver.available(): cplex_solver.buildSolverModel(P) logFile = 'solver_{0}.log'.format(self.name) cplex_solver.solverModel.set_log_stream(logFile) cplex_solver.solverModel.set_results_stream(logFile) cplex_solver.solverModel.set_warning_stream(logFile) cplex_solver.solverModel.set_error_stream(logFile) cplex_solver.callSolver(P) logger.info('Solving by cplex. Logfile: ' + logFile) status = cplex_solver.findSolutionValues(P) self.duration = cplex_solver.solverModel.get_dettime() self.nodes = cplex_solver.solverModel.solution.progress.get_num_nodes_processed( ) #P.setSolver(cplex_solver) else: logger.info('Solving by pulp standard solver') startTime = time.time() status = P.solve() self.duration = time.time() - startTime self.nodes = 0 if self.binary: #Round solutions to change values like 0.999999 to 1 self.P.roundSolution() self.objective = pulp.value(self.P.objective) self.y_val = {i: self.y_var[i].varValue for i in self.N} self.x_val = {(i, j): self.x_var[(i, j)].varValue for i, j in product(self.N, self.N)} #print('{0} problem objective value: {1}'.format(self.name,self.objective)) #print('Log file: {0}'.format(logFile)) return status
def mlboptimizeFD(num): # get the path to the slate path = get_my_path() path = functools.reduce(lambda x, f: f(x), [os.path.dirname] * 1, path) const_path = os.path.join(path, "slates", "MLBslateFD.csv") out_path = os.path.join(path, "slates", "output_fanduel.csv") # while True: # num = input("How many lineups do you want to generate?") # try: # val = int(num) # break; # except ValueError: # try: # float(num) # print("Input is an float number.") # print("Input number is: ", val) # break; # except ValueError: # print("This is not a number. Please enter a valid number") # print() # set the optimizer based on the user input for the site # enter the parameters optimizer = MLBFanduel(num_lineups=int(num), overlap=4, solver=pulp.CPLEX_PY(msg=0), players_filepath=const_path, output_filepath=out_path) # create the indicators used to set the constraints to be used by the formula optimizer.create_indicators() # generate the lineups with the formula and the indicators lineups = optimizer.generate_lineups(formula=optimizer.type_1) # fill the lineups with player names - send in the positions indicator filled_lineups = optimizer.fill_lineups(lineups) # save the lineups # optimizer.save_file(optimizer.header, filled_lineups) # optimizer.save_file(optimizer.header, filled_lineups, show_proj=True) return filled_lineups
def solve_relaxation(self): cplex_solver = pulp.CPLEX_PY(msg=0, mip=False) cplex_solver.buildSolverModel(self.P) logFile = 'bc.log' if logFile is not None: cplex_solver.solverModel.set_log_stream(logFile) cplex_solver.solverModel.set_results_stream(logFile) cplex_solver.solverModel.set_warning_stream(logFile) cplex_solver.solverModel.set_error_stream(logFile) #Add dual values from previous if self.dual is not None: cplex_solver.solverModel.start.set_start([], [], [], [], self.reduced_cost, self.dual) cplex_solver.callSolver(self.P) status = cplex_solver.findSolutionValues(self.P) if status == -1: raise InfeasibleSubproblem self.P.roundSolution() self.lb = pulp.value(self.P.objective) self.y_relax = {key: pulp.value(self.y_var[key]) for key in self.y_var} self.x_relax = {key: pulp.value(self.x_var[key]) for key in self.x_var} self.dual = cplex_solver.solverModel.solution.get_dual_values() self.reduced_cost = cplex_solver.solverModel.solution.get_reduced_costs( ) #Check if integer self.is_integer = True self.y_noninteger = {} for key, value in self.y_relax.items(): if not value.is_integer(): self.is_integer = False self.y_noninteger[key] = value
def extract(self, x, W=[], K=5, gamma=1.0, ordering=True, post_ordering=False, post_ordering_mode='greedy', intervention=False, cost_type='uniform', ordering_cost_type='uniform', use_threshold=True, solver='cplex', time_limit=300, log_stream=False, mdl_name='', log_name='', init_sols={}, verbose=False): self.x_ = x self.y_ = self.mdl_.predict(x.reshape(1, -1))[0] self.W_ = W if len(W) != 0 else list(range(self.D_)) self.K_ = min(K, self.D_) if (gamma == 0.0): ordering = False if (ordering == False): gamma = 0.0 self.gamma_ = gamma cost_type = 'normalize' if intervention else cost_type self.A_, self.C_, self.I_ = self.AC_.generateActions( x, cost_type=cost_type, use_threshold=use_threshold) self.lb_ = [np.min(A_d) for A_d in self.A_] self.ub_ = [np.max(A_d) for A_d in self.A_] C = self.M_ prob = pulp.LpProblem(mdl_name) # variables act = [ pulp.LpVariable('act_{}'.format(d), cat='Continuous', lowBound=self.lb_[d], upBound=self.ub_[d]) for d in range(self.D_) ] pi = [[ pulp.LpVariable('pi_{}_{}'.format(d, i), cat='Binary') for i in range(len(self.A_[d])) ] for d in range(self.D_)] xi = [ pulp.LpVariable('xi_{}'.format(t), cat='Continuous', lowBound=0, upBound=1) for t in range(self.T_) ] phi = [[ pulp.LpVariable('phi_{}_{}'.format(t, l), cat='Binary') for l in range(self.L_[t]) ] for t in range(self.T_)] if (ordering): LB, UB = self.getOrderingBounds(K, C) sigma = [[ pulp.LpVariable('sig_{}_{}'.format(k, d), cat='Binary') for d in range(self.D_) ] for k in range(self.K_)] pik = [[[ pulp.LpVariable('pik_{}_{}_{}'.format(k, d, i), cat='Binary') for i in range(len(self.A_[d])) ] for d in range(self.D_)] for k in range(self.K_)] epsilon = [[ pulp.LpVariable('ips_{}_{}'.format(k, d), cat='Continuous') for d in range(self.D_) ] for k in range(self.K_)] delta = [[ pulp.LpVariable('dlt_{}_{}'.format(k, d), cat='Continuous') for d in range(self.D_) ] for k in range(self.K_)] zeta = [ pulp.LpVariable('zta_{}'.format(k), cat='Continuous', lowBound=0) for k in range(self.K_) ] if (cost_type == 'SCM' or cost_type == 'DACE'): dist = [ pulp.LpVariable('dist_{}'.format(d), cat='Continuous', lowBound=0) for d in range(self.D_) ] # set initial values {val: [val_1, val_2, ...], ...} if (len(init_sols) != 0): for val, sols in init_sols.items(): if (val == 'act'): for d, v in enumerate(sols): act[d].setInitialValue(v) elif (val == 'pi'): for d, vs in enumerate(sols): for i, v in enumerate(vs): pi[d][i].setInitialValue(v) elif (val == 'xi'): for d, v in enumerate(sols): xi[d].setInitialValue(v) elif (val == 'phi'): for t, vs in enumerate(sols): for l, v in enumerate(vs): phi[t][l].setInitialValue(v) elif (val == 'sigma'): for l, d in enumerate(sols): for d_ in range(self.D_): v = 1 if d_ == d else 0 sigma[l][d].setInitialValue(v) for k in range(l + 1, self.K_): for d_ in range(self.D_): sigma[k][d].setInitialValue(0) # objective function if (ordering): if (cost_type == 'NONE'): prob += pulp.lpDot([self.gamma_] * self.K_, zeta) prob += pulp.lpDot([self.gamma_] * self.K_, zeta) >= 0 elif (cost_type == 'SCM' or cost_type == 'DACE'): prob += pulp.lpSum(dist) + pulp.lpDot([self.gamma_] * self.K_, zeta) prob += pulp.lpSum(dist) + pulp.lpDot([self.gamma_] * self.K_, zeta) >= 0 for d in range(self.D_): prob += dist[d] - pulp.lpDot(flatten(self.C_[d]), flatten(pi)) >= 0 prob += dist[d] + pulp.lpDot(flatten(self.C_[d]), flatten(pi)) >= 0 else: prob += pulp.lpDot(flatten(self.C_), flatten(pi)) + pulp.lpDot( [self.gamma_] * self.K_, zeta) prob += pulp.lpDot(flatten(self.C_), flatten(pi)) + pulp.lpDot( [self.gamma_] * self.K_, zeta) >= 0 else: if (cost_type == 'SCM' or cost_type == 'DACE'): prob += pulp.lpSum(dist) prob += pulp.lpSum(dist) >= 0 for d in range(self.D_): prob += dist[d] - pulp.lpDot(flatten(self.C_[d]), flatten(pi)) >= 0 prob += dist[d] + pulp.lpDot(flatten(self.C_[d]), flatten(pi)) >= 0 else: prob += pulp.lpDot(flatten(self.C_), flatten(pi)) prob += pulp.lpDot(flatten(self.C_), flatten(pi)) >= 0 # constraint: sum_{i} pi_{d,i} == 1 for d in range(self.D_): prob += pulp.lpSum(pi[d]) == 1 # constraint: sum_{d} pi_{d,i_d} >= D - K prob += pulp.lpSum( [pi[d][list(self.A_[d]).index(0)] for d in range(self.D_)]) >= self.D_ - self.K_ # constraint: sum_{d in G} a_{d,1} pi_{d,1} = 0 for G in self.feature_categories_: prob += pulp.lpDot( [self.A_[d][0] for d in G if len(self.A_[d]) != 0], [pi[d][0] for d in G if len(self.A_[d]) != 0]) == 0 # constraint: sum_{d} w_d xi_d + b >= 0 if (self.y_ == 0): prob += pulp.lpDot(self.coef_, xi) >= -self.intercept_ + 1e-8 else: prob += pulp.lpDot(self.coef_, xi) <= -self.intercept_ - 1e-8 # constraint: a_d = sum_{i} a_{d,i} pi_{d,i} if (intervention): _, B_ = interaction_matrix(self.X_, interaction_type='causal') # B_, _ = interaction_matrix(self.X_, interaction_type='causal') B = B_ + np.eye(self.D_) for d in range(self.D_): A_d = [[B[d][d_] * a for a in self.A_[d_]] for d_ in range(self.D_)] prob += act[d] - pulp.lpDot(flatten(A_d), flatten(pi)) == 0 else: for d in range(self.D_): prob += act[d] - pulp.lpDot(self.A_[d], pi[d]) == 0 # constraints (Tree Ensemble): for t in range(self.T_): # constraint: sum_{l} phi_{t,l} = 1 prob += pulp.lpSum(phi[t]) == 1 # constraint: xi_t = sum_{l} h_{t,l} phi_{t,l} prob += xi[t] - pulp.lpDot(self.H_[t], phi[t]) == 0 # constraint: D * phi_{t,l} <= sum_{d} sum_{i in I_{t,l,d}} pi_{d,i} for l in range(self.L_[t]): anc = self.AC_.ancestors_[t][l] prob += len(anc) * phi[t][l] - pulp.lpDot( flatten([self.I_[t][l][d] for d in anc]), flatten([pi[d] for d in anc])) <= 0 if (ordering): I_act = [(abs(a) > self.tol_).astype(int) for a in self.A_] # constraint: sigma_{k,d} = sum_{i} pi^(k)_{d,i} for k in range(self.K_): for d in range(self.D_): if (d in self.feature_categories_flatten_ and self.x_[d] == 1): prob += sigma[k][d] == 0 else: prob += pulp.lpDot(I_act[d], pik[k][d]) - sigma[k][d] == 0 # constraint: pis_{d,i} = sum_{k} pi^(k)_{d,i} for d in range(self.D_): for i in range(len(self.A_[d])): prob += pulp.lpSum([pik[k][d][i] for k in range(self.K_) ]) - pi[d][i] == 0 # constraint: sum_{d in G} a_{d,1} pi^(k)_{d,1} = 0 for G in self.feature_categories_: prob += pulp.lpDot( [self.A_[d][0] for d in G if len(self.A_[d]) != 0], [pik[k][d][0] for d in G if len(self.A_[d]) != 0]) == 0 # constraint: sum_{k} sigma_{k,d} <= 1 for d in range(self.D_): prob += pulp.lpSum([sigma[k][d] for k in range(self.K_)]) <= 1 # constraint: sum_{d} sigma_{k,d} <= 1 for k in range(self.K_): prob += pulp.lpSum(sigma[k]) <= 1 # constraint: sum_{d} sigma_{k,d} >= sum_{d} sigma_{k+1,d} for k in range(self.K_ - 1): prob += pulp.lpSum(sigma[k]) - pulp.lpSum(sigma[k + 1]) >= 0 # constraint: delta_{0,d} = 0 for d in range(self.D_): prob += delta[0][d] == 0 # constraint: delta_{k,d} = sum_{l}^{k-1} sum_{d'} C_{d,d'} epsilon_{l,d'} = sum_{d'} C_{d,d'} epsilon_{k-1,d'} + delta_{k-1,d} for k in range(1, self.K_): for d in range(self.D_): # prob += delta[k][d] - pulp.lpDot(list(C[d])*(k), flatten(epsilon[:k+1])) == 0 prob += delta[k][d] - delta[k - 1][d] - pulp.lpDot( C[d], epsilon[k - 1]) == 0 # constraint: epsilon_{k,d} >= sum_{i} a_{d,i} pi^(k)_{d,i} - delta_{k,d} - U_d (1 - sigma_{k,d}) # constraint: epsilon_{k,d} <= sum_{i} a_{d,i} pi^(k)_{d,i} - delta_{k,d} - L_d (1 - sigma_{k,d}) # constraint: epsilon_{k,d} >= L_d sigma_{k,d} # constraint: epsilon_{k,d} <= U_d sigma_{k,d} for k in range(self.K_): for d in range(self.D_): prob += epsilon[k][d] - pulp.lpDot(self.A_[d], pik[k][ d]) + delta[k][d] - UB[k][d] * sigma[k][d] >= -UB[k][d] prob += epsilon[k][d] - pulp.lpDot(self.A_[d], pik[k][ d]) + delta[k][d] - LB[k][d] * sigma[k][d] <= -LB[k][d] prob += epsilon[k][d] - LB[k][d] * sigma[k][d] >= 0 prob += epsilon[k][d] - UB[k][d] * sigma[k][d] <= 0 # constraint: zeta_k >= sum_{d} w_d * epsilon_{k,d} # constraint: zeta_k >= - sum_{d} w_d * epsilon_{k,d} weights = self.AC_.getFeatureWeight(cost_type=ordering_cost_type) for k in range(self.K_): prob += zeta[k] - pulp.lpDot(weights, epsilon[k]) >= 0 prob += zeta[k] + pulp.lpDot(weights, epsilon[k]) >= 0 if (len(log_name) != 0): prob.writeLP(log_name + '.lp') s = time.perf_counter() prob.solve(solver=pulp.CPLEX_PY(msg=log_stream, warm_start=(len(init_sols) != 0), timeLimit=time_limit, options=['set output clonelog -1'])) t = time.perf_counter() - s if (prob.status != 1): # prob.solve(solver=pulp.CPLEX_PY(msg=True)) return -1 obj = prob.objective.value() if (cost_type == 'SCM' or cost_type == 'DACE'): c_ordinal = np.sum([d.value() for d in dist]) else: c_ordinal = np.sum([ c * round(p.value()) for c, p in zip(flatten(self.C_), flatten(pi)) ]) c_ordering = np.sum([z.value() for z in zeta]) if ordering else 0.0 a = np.array([ np.sum([ self.A_[d][i] * round(pi[d][i].value()) for i in range(len(self.A_[d])) ]) for d in range(self.D_) ]) if (intervention): a_actual = np.array([a_.value() for a_ in act]) sig = np.array([[round(s.value()) for s in sigma[k]] for k in range(self.K_)]) if ordering else [] ret = OrderedAction( x, a, sig, gamma=gamma, time=t, obj=obj, c_ordinal=c_ordinal, c_ordering=c_ordering, target_name=self.target_name_, target_labels=self.target_labels_, label_before=int(self.y_), label_after=int(1 - self.y_), feature_names=self.feature_names_, feature_types=self.feature_types_, feature_categories=self.feature_categories_, interaction_matrix=self.M_, post_ordering=post_ordering, weights=self.AC_.getFeatureWeight(cost_type=ordering_cost_type), post_ordering_mode=post_ordering_mode) # save initial values self.init_sols_ = {} self.init_sols_['act'] = [a_ for a_ in a] self.init_sols_['pi'] = [] for pi_d in pi: self.init_sols_['pi'].append([round(p.value()) for p in pi_d]) self.init_sols_['xi'] = [np.clip(x.value(), 0, 1) for x in xi] self.init_sols_['phi'] = [] for phi_t in phi: self.init_sols_['phi'].append([round(p.value()) for p in phi_t]) if (ret.ordered_): self.init_sols_['sigma'] = ret.order_ return ret
from nhl.fanduel import Fanduel as NHLFanduel from nhl.draftkings import Draftkings as NHLDraftkings """EXAMPLE SHOWING HOW TO RUN THE NHL OPTIMIZER""" while True: site = input("Select 1 for Draftkings or 2 for Fanduel: ") if site not in ('1', '2'): print('Try Again...') continue print() # set the optimizer based on the user input for the site if site == '1': #enter the parameters optimizer = NHLDraftkings( num_lineups=150, overlap=4, solver=pulp.CPLEX_PY(msg=0), players_filepath= 'nhl/example_inputs/players_inputs/player_17791.csv', goalies_filepath= 'nhl/example_inputs/goalies_inputs/goalie_17791.csv', output_filepath=f'nhl/example_output_draftkings.csv') else: #enter the parameters optimizer = NHLFanduel( num_lineups=150, overlap=4, solver=pulp.CPLEX_PY(msg=0), players_filepath= 'nhl/example_inputs/players_inputs/player_17791.csv', goalies_filepath= 'nhl/example_inputs/goalies_inputs/goalie_17791.csv',
P += x[u, v] <= y[v] #Max p ambulance posts P += pulp.lpSum(y[u] for u in N) <= p return P problems = { 'binary': createLp(N, p, w, D, True), 'relaxed': createLp(N, p, w, D, False) } values = {} for name, P in problems.items(): #call solver in this way, instead of using P.solve(), to set the cplex logs streams cplex_solver = pulp.CPLEX_PY(msg=0) if cplex_solver.available(): cplex_solver.buildSolverModel(P) logFile = 'solver_{0}.log'.format(name) cplex_solver.solverModel.set_log_stream(logFile) cplex_solver.solverModel.set_results_stream(logFile) cplex_solver.solverModel.set_warning_stream(logFile) cplex_solver.solverModel.set_error_stream(logFile) cplex_solver.callSolver(P) status = cplex_solver.findSolutionValues(P) P.setSolver(cplex_solver) else: print('Cplex solver not available, using standard')
for j in range(no_of_villages) if i != j]) == 0 for j in range(no_of_villages): if i != j: # 13 prob += y_i_j[i][j] <= max_distance * x_i_j[i][j] # 15 prob += y_i_j[i][j] >= 0 if i != start_village - 1: # 14 prob += y_i_j[start_village - 1][i] == d_i_j[start_village - 1][i] * \ x_i_j[start_village - 1][i] # Solve status = prob.solve(pl.CPLEX_PY(msg=0)) if (status == 1): # If there is an optimal solution print the result path_list = [] for v in prob.variables(): if (v.varValue == 1 and v.name[0] == "x"): temp = (v.name[2:]).split('_') path_list.append((int(temp[0]), int(temp[1]))) while len(path_list) != 0: print("\nA path is", start_village, end='') curr = start_village distance = 0 for src, dest in path_list: if src == curr:
def type_1(self, lineups): """ Sets up the pulp LP problem, adds all of the constraints and solves for the maximum value for each generated lineup. Type 1 constraints include: - 3-2 stacking (1 line of 3 players and one seperate line of 2 players) - goalies stacking - team stacking Returns a single lineup (i.e all of the players either set to 0 or 1) indicating if a player was included in a lineup or not. """ #define the pulp object problem prob = pulp.LpProblem('NHL', pulp.LpMaximize) #define the player and goalie variables skaters_lineup = [ pulp.LpVariable("player_{}".format(i + 1), cat="Binary") for i in range(self.num_skaters) ] goalies_lineup = [ pulp.LpVariable("goalie_{}".format(i + 1), cat="Binary") for i in range(self.num_goalies) ] #add the max player constraints prob += (pulp.lpSum(skaters_lineup[i] for i in range(self.num_skaters)) == 8) prob += (pulp.lpSum(goalies_lineup[i] for i in range(self.num_goalies)) == 1) #add the positional constraints prob += (2 <= pulp.lpSum(self.positions['C'][i] * skaters_lineup[i] for i in range(self.num_skaters))) prob += (pulp.lpSum(self.positions['C'][i] * skaters_lineup[i] for i in range(self.num_skaters)) <= 3) prob += (3 <= pulp.lpSum(self.positions['W'][i] * skaters_lineup[i] for i in range(self.num_skaters))) prob += (pulp.lpSum(self.positions['W'][i] * skaters_lineup[i] for i in range(self.num_skaters)) <= 4) prob += (2 <= pulp.lpSum(self.positions['D'][i] * skaters_lineup[i] for i in range(self.num_skaters))) prob += (pulp.lpSum(self.positions['D'][i] * skaters_lineup[i] for i in range(self.num_skaters)) <= 3) #add the salary constraint prob += ((pulp.lpSum(self.skaters_df.loc[i, 'sal'] * skaters_lineup[i] for i in range(self.num_skaters)) + pulp.lpSum(self.goalies_df.loc[i, 'sal'] * goalies_lineup[i] for i in range(self.num_goalies))) <= self.salary_cap) # exactly 3 teams for the 8 skaters constraint used_team = [ pulp.LpVariable("u{}".format(i + 1), cat="Binary") for i in range(self.num_teams) ] for i in range(self.num_teams): prob += (used_team[i] <= pulp.lpSum( self.skaters_teams[k][i] * skaters_lineup[k] for k in range(self.num_skaters))) prob += (pulp.lpSum(self.skaters_teams[k][i] * skaters_lineup[k] for k in range(self.num_skaters)) <= 6 * used_team[i]) prob += (pulp.lpSum(used_team[i] for i in range(self.num_teams)) >= 3) # no goalies against skaters constraint for i in range(self.num_goalies): prob += ( 6 * goalies_lineup[i] + pulp.lpSum(self.goalies_opponents[k][i] * skaters_lineup[k] for k in range(self.num_skaters)) <= 6) # Must have at least one complete line in each lineup line_stack_3 = [ pulp.LpVariable("ls3{}".format(i + 1), cat="Binary") for i in range(self.num_lines) ] for i in range(self.num_lines): prob += (3 * line_stack_3[i] <= pulp.lpSum( self.team_lines[k][i] * skaters_lineup[k] for k in range(self.num_skaters))) prob += (pulp.lpSum(line_stack_3[i] for i in range(self.num_lines)) >= 1) # Must have at least 2 lines with at least 2 players line_stack_2 = [ pulp.LpVariable("ls2{}".format(i + 1), cat="Binary") for i in range(self.num_lines) ] for i in range(self.num_lines): prob += (2 * line_stack_2[i] <= pulp.lpSum( self.team_lines[k][i] * skaters_lineup[k] for k in range(self.num_skaters))) prob += (pulp.lpSum(line_stack_2[i] for i in range(self.num_lines)) >= 2) #variance constraints - each lineup can't have more than the num overlap of any combination of players in any previous lineups for i in range(len(lineups)): prob += (( pulp.lpSum(lineups[i][k] * skaters_lineup[k] for k in range(self.num_skaters)) + pulp.lpSum(lineups[i][self.num_skaters + k] * goalies_lineup[k] for k in range(self.num_goalies))) <= self.overlap) #add the objective prob += pulp.lpSum( (pulp.lpSum(self.skaters_df.loc[i, 'proj'] * skaters_lineup[i] for i in range(self.num_skaters)) + pulp.lpSum(self.goalies_df.loc[i, 'proj'] * goalies_lineup[i] for i in range(self.num_goalies)))) #solve the problem status = prob.solve(pulp.CPLEX_PY(msg=0)) #check if the optimizer found an optimal solution if status != pulp.LpStatusOptimal: print('Only {} feasible lineups produced'.format(len(lineups)), '\n') return None # Puts the output of one lineup into a format that will be used later lineup_copy = [] for i in range(self.num_skaters): if skaters_lineup[i].varValue >= 0.9 and skaters_lineup[ i].varValue <= 1.1: lineup_copy.append(1) else: lineup_copy.append(0) for i in range(self.num_goalies): if goalies_lineup[i].varValue >= 0.9 and goalies_lineup[ i].varValue <= 1.1: lineup_copy.append(1) else: lineup_copy.append(0) return lineup_copy
class CustomPuLPSolver(PuLPSolver): LP_SOLVER = pulp.CPLEX_PY(msg=0)
import pulp from nfl_dp_optimizer import Fanduel optimizer = Fanduel(num_lineups=10, overlap=4, solver=pulp.CPLEX_PY(msg=0)) optimizer.create_indicators() # generate the lineups with the formula and the indicators lineups = optimizer.create_lineups(eqn=optimizer.no_stacking) # fill the lineups with player names - send in the positions indicator filled_lineups = optimizer.fill_lineups(lineups) # save the lineups optimizer.save(filled_lineups) optimizer.save(filled_lineups, show_proj=True)
# initializing LP LP = pulp.LpProblem('LP',pulp.LpMaximize) #-----------CREATING VARIABLES #Option 1: #x = pulp.LpVariable.dicts("x", range(duration), cat=pulp.LpBinary) #Option 2: #y = {} #for i in range(duration): # y[i] = pulp.LpVariable("y_"+str(i), cat='Binary') #---------------------------- # adding variables x1 = pulp.LpVariable("x1", cat='Integer', lowBound=0) x2 = pulp.LpVariable("x2", cat='Integer', lowBound=0) #constraints LP += 100>= x1+2*x2 LP += 100>= 2*x1+x2 #obj function LP += 20*x1+30*x2 # if mip=False -> Integer constraints are ignored # if msg=False -> Optimization script is not displayed status = LP.solve(pulp.CPLEX_PY(mip=True, msg=False, timeLimit=15,epgap=None)) print( 'LP status: ' + pulp.LpStatus[status] + '') print(x1.value(),x2.value())
#prob+=compD[l][o] >=r[l][o]+Csums[l][o]*(process_days[o][l]/orderPool['order_num'][o]) #prob+=pulp.LpSum([h[i][(i,t)] for i in modelList for t in Tm[i]])*1/2== sum([R[l][t] for t in TL]) #prob+=r[l][o]+Pday[l][o]<=(orderPool['deli_date'][o]-datetime.datetime.strptime(plan_dates[0],'%Y-%m-%d')).days #prob+=r[l][o]>=max(0,(orderPool['epst'][o]-datetime.datetime.strptime(plan_dates[0],'%Y-%m-%d')).days) #prob+=pulp.lpSum([order_spd[(order_spd['order_id'==o])&(order_spd['line_o']==l)&(order_spd['day_process']==Pday[l][o])] for l in prod_line])==orderPool['order_num'][o] #prob+=compD[l][o]<=(orderPool['deli_date'][o]-datetime.datetime.strptime(plan_dates[0],'%Y-%m-%d')).days #prob+=pulp.lpSum([Csums[l][o] for l in prod_line for o in orderList])==orderPool['order_num'].sum() #5.every line cannot made two orders at the same time #eps=1e-2 #for o in orderList: #prob+=Cmax+eps*pulp.lpSum([r[l][o] for l in prod_line])-eps*pulp.lpSum([compD[l][o] for l in prod_line]) prob.writeLP("APSModel.lp") prob.solve(pulp.CPLEX_PY()) print("Status:", pulp.LpStatus[prob.status]) #for o in orderList: #for l in prod_line: #print((l,o),r[l,o].value(),compD[l,o].value(),Cmax[l,o].value()) a=[] for v in prob.variables(): #print(v.name, "=", v.varValue) a.append((v.name,v.varValue)) rlt_df=pd.DataFrame(a) rlt_df.to_csv("test.csv")
min_covering_set += ind_cos #Constraints #for j in Indicators: # Ax = np.sum([coverage_A[j, i] * x[i] for i in Issues]) for j in Issues: for k in Attributes: min_covering_set += np.sum([coverage_A[j, i] * x[i] for i in Indicators]) + (v_issueattributeselect[k] * t[j]) >= b_issuecost[j] for i in Indicators: for k in Attributes: min_covering_set += w_indicatorattributeselect[k] * x[i] <= coverage_N[i, k] #Solver #min_covering_set.solve() min_covering_set.solve(pulp.CPLEX_PY()) #Print the result for i in Indicators: print 'The indicator %s gets a score of %s' % (i, x[i].value()) for i in Indicators: print x[i].varValue for i in Indicators: print x[i].name for i in min_covering_set.variables(): print 'The indicator %s gets a score of' % (i) flow = pd.Series('', index=c_indicatorcost)