def knapsackILP(num_items, items, capacity, num_conflicts, conflicts): if DEBUG >= 1: print(f"numero de itens = {num_items}") print(f"capacidade da mochila = {capacity}") print(f"numero de conflitos = {num_conflicts}") if DEBUG >= 2: print("Itens na ordem em que foram lidos") for item in items: print(item) print() if DEBUG >= 2: print("Conflitos na ordem em que foram lidos") for conflict in conflicts: print(conflict) print() solution = [0] * num_items solution_value = 0 solution_weight = 0 # Começa parte PLI # Criação do resolvedor e das variáveis indicadoras solver = pywraplp.Solver('SolveIntegerProblem', pywraplp.Solver.CBC_MIXED_INTEGER_PROGRAMMING) x = [] for j in range(0, num_items): x.append(solver.IntVar(0.0, 1.0, 'x[%d]' % j)) # Definição das restrições # Restrição de limite de capacidade da mochila solver.Add( sum(x[i] * items[i].weight for i in range(num_items)) <= capacity) # Restrição de objetos incompatíveis for conflict in conflicts: solver.Add(x[conflict[0]] + x[conflict[1]] <= 1) # Definição do Objetivo solver.Maximize(sum(x[i] * items[i].value for i in range(num_items))) param = pywraplp.MPSolverParameters() param.SetDoubleParam(param.RELATIVE_MIP_GAP, 1 / 100000) # Solução final status = solver.Solve(param) solution_value = int(solver.Objective().Value() ) if status == pywraplp.Solver.OPTIMAL else -1 for i in range(num_items): solution[i] = int(x[i].solution_value()) # prepare the solution in the specified output format output_data = str(solution_value) + '\n' output_data += ' '.join(map(str, solution)) return output_data
def mip_ort(facilities, customers): solver = pywraplp.Solver.CreateSolver('SCIP') # solver.SetTimeLimit(15 * 60 * 1000) open = {} for facility in facilities: open[facility] = solver.IntVar(0, 1, '') dist = {} serves = {} for facility in facilities: serves[facility] = {} dist[facility] = {} for customer in customers: dist[facility][customer] = length(facility.location, customer.location) serves[facility][customer] = solver.IntVar( 0, 1, '') # if dist[facility][customer] < 50000 else 0 # a facility can only serve if it is open solver.Add(serves[facility][customer] <= open[facility]) # customer demands dont exceed capacity solver.Add( sum(serves[facility][customer] * customer.demand for customer in customers) <= facility.capacity) for customer in customers: # a customer is served by exactly one facility solver.Add( sum(serves[facility][customer] for facility in facilities) == 1) solver.Minimize( sum(open[facility] * facility.setup_cost + sum(serves[facility][customer] * dist[facility][customer] for customer in customers) for facility in facilities)) solver_parameters = pywraplp.MPSolverParameters() solver_parameters.SetDoubleParam( pywraplp.MPSolverParameters.PRIMAL_TOLERANCE, 0.0001) solver.Solve(solver_parameters) solution = {} for customer in customers: # print("Customer", "%2d" % customer.index, ":", " ".join(map(str, map(int, (serves[facility][customer].solution_value() for facility in facilities))))) for facility in facilities: if serves[facility][customer].solution_value(): solution[customer] = facility break print("-----Problem solved in-----") print('%.3f seconds' % (solver.wall_time() / 1000)) print('%d iterations' % solver.iterations()) print('%d branch-and-bound nodes' % solver.nodes()) return solver.Objective().Value(), solution
def get_init_subs_ort(vehicle_count, vehicle_capacity, depot, customers): shuffle(customers) in_route = {} solver = pywraplp.Solver.CreateSolver('SCIP') for customer in customers: for v in range(vehicle_count): in_route[customer, v] = solver.IntVar(0, 1, '') # only in one route solver.Add( sum(in_route[customer, v] for v in range(vehicle_count)) == 1) for v in range(vehicle_count): solver.Add( sum(in_route[customer, v] * customer.demand for customer in customers) <= vehicle_capacity) ''' objective = 0 for v in range(vehicle_count): subproblems = [] for customer in customers: if in_route[customer, v]: subproblems.append(customer) objective += create_greedy_permutation(len(customers), customers)[1] solver.Minimize(objective) ''' solver_parameters = pywraplp.MPSolverParameters() solver_parameters.SetDoubleParam( pywraplp.MPSolverParameters.PRIMAL_TOLERANCE, 0.0001) solver.Solve(solver_parameters) subproblems = [[] for _ in range(vehicle_count)] for v in range(vehicle_count): for customer in customers: if in_route[customer, v].solution_value(): subproblems[v].append(customer) return subproblems
def run_model(self): # solver.Minimize(1) solver_parameters = pywraplp.MPSolverParameters() solver_parameters.SetDoubleParam(pywraplp.MPSolverParameters.RELATIVE_MIP_GAP, 0.5) self.solver.SetTimeLimit(self.solver_time_limit_mins * 60 * 1000) self.solver.EnableOutput() self.solution = self.solver.Solve() print('Number of variables in model = {}'.format(str(self.solver.NumVariables()))) print('Number of constraints in model = {}'.format(str(self.solver.NumConstraints()))) # get solution if self.solution == pywraplp.Solver.OPTIMAL: print('Solution is found') print('Problem solved in {} milliseconds'.format(str(self.solver.WallTime()))) print('Problem solved in {} iterations'.format(str(self.solver.Iterations()))) print('Problem solved in {} iterations'.format(str(self.solver.Iterations()))) print('Problem objective = {} '.format(str(self.solver.Objective().Value()))) else: raise Exception('No solution exists')
def solve_it(input_data): # Modify this code to run your optimization algorithm # parse the input lines = input_data.split('\n') firstLine = lines[0].split() item_count = int(firstLine[0]) capacity = int(firstLine[1]) items = [] for i in range(1, item_count+1): line = lines[i] parts = line.split() items.append(Item(i-1, int(parts[0]), int(parts[1]))) solver = pywraplp.Solver.CreateSolver('SCIP') taken = {} for item in items: taken[item] = solver.IntVar(0, 1, '') solver.Add(sum(taken[item] * item.weight for item in items) <= capacity) solver.Maximize(sum(taken[item] * item.value for item in items)) # lower tolerance for better solution? solver_parameters = pywraplp.MPSolverParameters() solver_parameters.SetDoubleParam(pywraplp.MPSolverParameters.PRIMAL_TOLERANCE, 0.00001) solver.Solve(solver_parameters) solution = [] for item in items: solution.append(taken[item].solution_value()) # prepare the solution in the specified output format output_data = str(int(solver.Objective().Value())) + ' ' + str(0) + '\n' output_data += ' '.join(str(int(c)) for c in solution) return output_data
def schedule_all(self, timelimit=0): if not self.reservation_list: return self.schedule_dict # populate all the windows, requests, etc self.build_data_structures() # weight the priorities in each timeslice by airmass self.weight_by_airmass() # used to save a metric for when the primary algorithm fails to instantiate primary_algorithm_failed = 0 # Instantiate the ORTools solver try: solver = pywraplp.Solver_CreateSolver(self.algorithm) if not solver: logger.warn(f"Failed to get a valid solver for {self.kernel}.") logger.warn(f"Defaulting to {FALLBACK_ALGORITHM} solver") primary_algorithm_failed = 1 solver = pywraplp.Solver_CreateSolver(FALLBACK_ALGORITHM) except Exception as e: logger.warn( f"Failed to create a valid solver for {self.kernel}: {repr(e)}" ) logger.warn(f"Defaulting to {FALLBACK_ALGORITHM} solver") primary_algorithm_failed = 1 solver = pywraplp.Solver_CreateSolver(FALLBACK_ALGORITHM) self.send_metric('primary_algorithm_failed.occurence', primary_algorithm_failed) # Constraint: Decision variable (isScheduled) must be binary (eq 4) requestLocations = [] vars_by_req_id = defaultdict(list) scheduled_vars = [] solution_hints = [] for r in self.Yik: # create a lut of req_id to decision vars for building the constraints later # [(reqID, window idx, priority, resource, isScheduled)] var = solver.BoolVar(name=f"bool_var_{r[0]}_{len(scheduled_vars)}") scheduled_vars.append(var) vars_by_req_id[r[0]].append((r[0], r[1], r[2], r[3], var)) requestLocations.append((r[0], r[1], r[2], r[3], var)) solution_hints.append(r[4]) # The warm-start hints (not supported in older ortools) if self.warm_starts: logger.info("Using warm start solution this run") solver.SetHint(variables=scheduled_vars, values=solution_hints) # Constraint: One-of (eq 5) i = 0 for oneof in self.oneof_constraints: match = [] for r in oneof: reqid = r.get_ID() match.extend(vars_by_req_id[reqid]) r.skip_constraint2 = True # does this do what I think it does? nscheduled_one = solver.Sum([ isScheduled for reqid, winidx, priority, resource, isScheduled in match ]) solver.Add(nscheduled_one <= 1, 'oneof_constraint_' + str(i)) i = i + 1 # Constraint: And (all or nothing) (eq 6) i = 0 for andconstraint in self.and_constraints: # add decision variable that must be equal to all "and"ed blocks andVar = solver.BoolVar(name=f"and_var_{str(i)}") j = 0 for r in andconstraint: reqid = r.get_ID() match = vars_by_req_id[reqid] nscheduled_and = solver.Sum([ isScheduled for reqid, winidx, priority, resource, isScheduled in match ]) solver.Add(andVar == nscheduled_and, 'and_constraint_' + str(i) + "_" + str(j)) j = j + 1 i = i + 1 # Constraint: No more than one request should be scheduled in each (timeslice, resource) (eq 3) # self.aikt.keys() indexes the requests that occupy each (timeslice, resource) for s in sorted(self.aikt.keys()): match = [] for timeslice in self.aikt[s]: match.append(requestLocations[timeslice]) nscheduled1 = solver.Sum([ isScheduled for reqid, winidx, priority, resource, isScheduled in match ]) solver.Add(nscheduled1 <= 1, 'one_per_slice_constraint_' + s) # Constraint: No request should be scheduled more than once (eq 2) # skip if One-of (redundant) for r in self.reservation_list: if not hasattr(r, 'skip_constraint2'): reqid = r.get_ID() match = vars_by_req_id[reqid] nscheduled2 = solver.Sum([ isScheduled for reqid, winidx, priority, resource, isScheduled in match ]) solver.Add(nscheduled2 <= 1, 'one_per_reqid_constraint_' + str(reqid)) # Objective: Maximize the merit functions of all scheduled requests (eq 1); objective = solver.Maximize( solver.Sum([ isScheduled * (priority + (0.1 / (winidx + 1.0))) for req, winidx, priority, resource, isScheduled in requestLocations ])) # impose a time limit (ms) on the solve if timelimit > 0: solver.SetTimeLimit(int(timelimit * 1000)) params = pywraplp.MPSolverParameters() # Set the tolerance for the model solution to be within 1% of what it thinks is the best solution params.SetDoubleParam(pywraplp.MPSolverParameters.RELATIVE_MIP_GAP, self.mip_gap) # Solve the model solver.EnableOutput() solver.Solve(params) logger.warn("Finished solving schedule") # Return the optimally-scheduled windows r = Result() r.xf = [] for request, winidx, priority, resource, isScheduled in requestLocations: r.xf.append(isScheduled.SolutionValue()) logger.warn("Set SolutionValues of isScheduled") return self.unpack_result(r)
def formulate_and_solve_ortools_model( store_list, cluster_list, distance, volume, minimum_elements_in_a_cluster, maximum_elements_in_a_cluster, maximum_volume_in_a_cluster, enable_minimum_maximum_elements_in_a_cluster): ''' Formulate the model :param store_list: :param cluster_list: :param distance: :param volume: :param minimum_elements_in_a_cluster: :param maximum_elements_in_a_cluster: :param maximum_volume_in_a_cluster: :param enable_minimum_maximum_elements_in_a_cluster: :return: ''' # formulate model solver = pywraplp.Solver('SolveIntegerProblem', pywraplp.Solver.CBC_MIXED_INTEGER_PROGRAMMING) # create variables # y = {} for cluster, store in distance.keys(): y[cluster, store] = solver.BoolVar('y[cluster = {}, {}]'.format( str(cluster), store)) # Add constraints # each store is assigned to one cluster for store in store_list: solver.Add( solver.Sum([y[cluster, store] for cluster in cluster_list]) == 1) if enable_minimum_maximum_elements_in_a_cluster: # minimum number of elements in a cluster for cluster in cluster_list: solver.Add( solver.Sum([y[cluster, store] for store in store_list]) >= minimum_elements_in_a_cluster) # maximum number of elements in a cluster for cluster in cluster_list: solver.Add( solver.Sum([y[cluster, store] for store in store_list]) <= maximum_elements_in_a_cluster) else: # minimum number of elements in a cluster for cluster in cluster_list: solver.Add( solver.Sum([y[cluster, store] for store in store_list]) >= 1) if maximum_volume_in_a_cluster is not None: for cluster in cluster_list: solver.Add( solver.Sum([ volume[store] * y[cluster, store] for store in store_list ]) <= maximum_volume_in_a_cluster) # add objective solver.Minimize( solver.Sum([ distance[cluster, store].WEIGHTED_DISTANCE * y[cluster, store] for cluster, store in distance.keys() ])) # solver.Minimize(1) solver_parameters = pywraplp.MPSolverParameters() solver_parameters.SetDoubleParam( pywraplp.MPSolverParameters.RELATIVE_MIP_GAP, 0.01) # solver.SetTimeLimit(self.solver_time_limit) solver.EnableOutput() solution = solver.Solve() # get solution if solution == pywraplp.Solver.OPTIMAL: print('Optimal solution is found') print('Problem solved in {} milliseconds'.format(str( solver.WallTime()))) print('Problem solved in {} iterations'.format(str( solver.Iterations()))) solution_final = [] for cluster, store in distance.keys(): solution_final.append({ 'CLUSTER': cluster, 'LOCATION_NAME': store, 'VALUE': y[cluster, store].solution_value(), 'DISTANCE': distance[cluster, store].DISTANCE, 'WEIGHTED_DISTANCE': distance[cluster, store].WEIGHTED_DISTANCE, 'VOLUME': volume[store] }) solution = pd.DataFrame(solution_final) solution = solution[solution['VALUE'] == 1] solution = solution[[ 'CLUSTER', 'LOCATION_NAME', 'DISTANCE', 'WEIGHTED_DISTANCE' ]] else: solution = pd.DataFrame() return solution
def optimize(parts, listings, stores, shipping_costs): solver = pywraplp.Solver('lego_mip_optimization', pywraplp.Solver.CBC_MIXED_INTEGER_PROGRAMMING) solver_params = pywraplp.MPSolverParameters() solver.EnableOutput() infinity = solver.infinity() vars_part_listing = [] vars_store = [] # Variable - part listings for pi in range(len(parts)): for li in range(len(listings)): if parts[pi].element_id == listings[li].element_id and parts[ pi].color_id == listings[li].color_id: var = solver.IntVar(0.0, infinity, '{}-{}'.format(pi, li)) vars_part_listing.append(var) else: vars_part_listing.append(None) # Variable - stores for si in range(len(stores)): var = solver.IntVar(0.0, 1.0, 'store-{}'.format(si)) vars_store.append(var) print('Number of variables', solver.NumVariables()) # Constraint - calculate the number of stores for si in range(len(stores)): for li in range(len(listings)): if listings[li].store_id != stores[si].store_id: continue for pi in range(len(parts)): if not (parts[pi].element_id == listings[li].element_id and parts[pi].color_id == listings[li].color_id): continue index = to_var_index(parts, listings, pi, li) solver.Add(vars_part_listing[index] <= vars_store[si] * 10000) # Constraint - minimum quantity for parts for pi, part in enumerate(parts): sum = None for li in range(len(listings)): if not (parts[pi].element_id == listings[li].element_id and parts[pi].color_id == listings[li].color_id): continue index = to_var_index(parts, listings, pi, li) if sum is None: sum = vars_part_listing[index] else: sum += vars_part_listing[index] if sum: solver.Add(sum >= part.qty) # We don't need this anymore since we decreased the number of variables # # Constraint - listings are associated with corresponding parts # for pi, part in enumerate(parts): # for li, listing in enumerate(listings): # if part.element_id != listing.element_id or part.color_id != listing.color_id: # index = to_var_index(parts, listings, pi, li) # solver.Add(vars_part_listing[index] == 0) # # Constraint - dont buy more than the max quantity of the vendor # for pi in range(len(parts)): # for li, listing in enumerate(listings): # if part.element_id != listing.element_id or part.color_id != listing.color_id: # index = to_var_index(parts, listings, pi, li) # solver.Add(vars[index] == 0) # # Constraint - limited number of stores # sum = None # for si in range(len(stores)): # if sum is None: # sum = vars_store[si] # else: # sum += vars_store[si] # solver.Add(sum <= 20) # Objective - minimize price sum = None for pi, part in enumerate(parts): for li, listing in enumerate(listings): if not (parts[pi].element_id == listings[li].element_id and parts[pi].color_id == listings[li].color_id): continue index = to_var_index(parts, listings, pi, li) if not listing.price > 0: print('unrealistic price warning', listing.price) if sum is None: sum = vars_part_listing[index] * listing.price else: sum += vars_part_listing[index] * listing.price print('Number of constraints', solver.NumConstraints()) # Objective - minimize stores for si in range(len(stores)): if sum is None: sum = vars_store[si] * shipping_costs else: sum += vars_store[si] * shipping_costs solver.Minimize(sum) status = solver.Solve(solver_params) optimal_listings = [] if status == pywraplp.Solver.OPTIMAL: for pi in range(len(parts)): sys.stdout.write('{}'.format(parts[pi])) for li in range(len(listings)): if parts[pi].element_id == listings[li].element_id and parts[ pi].color_id == listings[li].color_id: solution = vars_part_listing[to_var_index( parts, listings, pi, li)].solution_value() if solution > 0: sys.stdout.write(' {}'.format(listings[li])) optimal_listings.append(listings[li]) print('') # for si in range(len(stores)): # print(stores[si].store_id, vars_store[si].solution_value()) print('Solution:') print('Objective value =', solver.Objective().Value()) else: print('The problem does not have an optimal solution.') return optimal_listings