def solve(F, groups): allEmployees = 0 for g in groups: allEmployees += g.employees G = len(groups) print("Solving for {} floors with {} employees in {} groups".format( F, allEmployees, G)) # A binary search would be much better here, of course, but meh for wcs in range(1, allEmployees + 1): m = Model() x = [m.add_var(var_type=INTEGER) for i in range(F * G)] for i, g in enumerate(groups): m += xsum(x[i * F + f] for f in g.floors) >= g.employees for f in range(F): m += xsum(x[f + g * F] for g in range(G)) <= wcs m.objective = xsum(0 for i in range(F * G)) m.max_gap = 0.05 status = m.optimize(max_seconds=3000) if status == OptimizationStatus.OPTIMAL: print('optimal solution cost {} found'.format(m.objective_value)) elif status == OptimizationStatus.FEASIBLE: print('sol.cost {} found, best possible: {}'.format( m.objective_value, m.objective_bound)) elif status == OptimizationStatus.NO_SOLUTION_FOUND: print('no feasible solution found, lower bound is: {}'.format( m.objective_bound)) if status == OptimizationStatus.OPTIMAL or status == OptimizationStatus.FEASIBLE: print( '===================================================================' ) print('solution:') for v in m.vars: if abs(v.x) > 1e-6: # only printing non-zeros print('{} : {}'.format(v.name, v.x)) return wcs
def runSolver(k): # return dict, k m = Model(solver_name=CBC) ####################### ###### Variables ###### ####################### """ x[s1][r] = binary var if student s1 is in room r n x k matrix Room 0 1 2 3 Student [1 0 0 0] 0 [1 1 0 1] 1 [1 1 0 1] 2 """ x = [[ m.add_var(name='x_{}_{}'.format(i, l), var_type='B') for l in range(k) ] for i in range(n)] """ y[r][s1][s2] = binary var if s1 and s2 are in room r Each entry of s is a sqaure n x n matrix [(0, 0) ... (i, 0)] [ ... ... ... ] [(j, 0) ... (i, j)] all entries below the diagonal are repeated. """ y = [] for l in range(k): y.append([[ m.add_var(name='y_{}_{}_{}'.format(i, j, l), var_type='B') for i in range(n) ] for j in range(n)]) ####################### ##### Constraints ##### ####################### # https://cs.stackexchange.com/questions/12102/express-boolean-logic-operations-in-zero-one-integer-linear-programming-ilp?fbclid=IwAR0DTuP7zy4KUkgU_Vxip-21mMd0Gysw_EE1-BwGJtMz3BdPmDbTaAoPGI8 for l in range(k): for i in range(n): for j in range(i + 1, n): m += x[i][l] + x[j][l] - 1 <= y[l][i][j] m += x[i][l] >= y[l][i][j] m += x[j][l] >= y[l][i][j] # ensures each student can only be in 1 room for i in range(n): m += xsum(x[i][l] for l in range(k)) == 1 # ensures that rooms have at least 1 person for l in range(k): m += xsum(x[i][l] for i in range(n)) >= 1 # ensures each room meets stress requirement for l in range(k): m += xsum(y[l][i][j] * getStress(i, j) for i in range(n) for j in range(i + 1, n)) <= S_MAX / k # optimize for happiness m.objective = maximize( xsum(y[l][i][j] * getHappiness(i, j) for l in range(k) for i in range(n) for j in range(i + 1, n))) solution = {} m.max_gap = 0.05 status = m.optimize(max_seconds=300) if status == OptimizationStatus.OPTIMAL: print('optimal solution cost {} found'.format(m.objective_value)) elif status == OptimizationStatus.FEASIBLE: print('sol.cost {} found, best possible: {}'.format( m.objective_value, m.objective_bound)) elif status == OptimizationStatus.NO_SOLUTION_FOUND: print('no feasible solution found, lower bound is: {}'.format( m.objective_bound)) elif status == OptimizationStatus.INFEASIBLE: print('infeasible: ') if status == OptimizationStatus.OPTIMAL or status == OptimizationStatus.FEASIBLE: print('solution:') for v in m.vars: if abs(v.x) > 1e-6: # only printing non-zeros print('{} : {}'.format(v.name, v.x)) student_room = v.name.split('_') if student_room[0] == 'x': solution[int(student_room[1])] = int(student_room[2]) solution = dict(sorted(solution.items(), key=lambda item: item[1])) return solution
def solve(self, list_of_locations, list_of_homes, starting_car_location, adjacency_matrix, input_file, params=[]): """ Solve the problem using an MST/DFS approach. Input: list_of_locations: A list of locations such that node i of the graph corresponds to name at index i of the list list_of_homes: A list of homes starting_car_location: The name of the starting location for the car adjacency_matrix: The adjacency matrix from the input file Output: A cost of how expensive the current solution is A list of locations representing the car path A dictionary mapping drop-off location to a list of homes of TAs that got off at that particular location NOTE: all outputs should be in terms of indices not the names of the locations themselves """ conn = sqlite3.connect('models.sqlite') c = conn.cursor() seen = c.execute( 'SELECT best_objective_bound FROM models WHERE input_file = (?)', (input_file, )).fetchone() self.log_new_entry(input_file) home_indices = convert_locations_to_indices(list_of_homes, list_of_locations) location_indices = convert_locations_to_indices( list_of_locations, list_of_locations) edge_scale = 1.0 if "--approx" in params: edge_scale = 1 / 10000 G, message = adjacency_matrix_to_graph(adjacency_matrix, edge_scale) E = list(G.to_directed().edges(data='weight')) starting_car_index = list_of_locations.index(starting_car_location) start_paths = [ convert_locations_to_indices([starting_car_location], list_of_locations) ] num_random_paths = 5 if "-r" in params: num_random_paths = int(params[params.index("-r") + 1]) for i in range(num_random_paths): start_paths.append(self.generate_random(G, starting_car_index)) if seen: output_file = 'submissions/submission_final/{}.out'.format( input_file.split('.')[0]) print(output_file) if not "--no-prev" in params and os.path.isfile(output_file): start_paths.append( convert_locations_to_indices( utils.read_file(output_file)[0], list_of_locations)) best_start_path_cost = float('inf') best_start_path_index = -1 for i, path in enumerate(start_paths): walk_cost, dropoffs = self.find_best_dropoffs( G, home_indices, path) cost, msg = cost_of_solution(G, path, dropoffs) if cost < best_start_path_cost: best_start_path_cost = cost best_start_path_index = i start_path = start_paths[best_start_path_index] print("Starting path:") if best_start_path_index == num_random_paths: print("SAVED PATH:", start_path) elif best_start_path_index >= 0: print("RANDOM PATH:", start_path) else: print("No start path found") print("Starting cost:", best_start_path_cost) # number of nodes and list of vertices, not including source or sink n, V, H = len(list_of_locations), location_indices, home_indices bigNum = (2 * n) model = Model() # does the car drive from i to j? x = [model.add_var(var_type=BINARY) for e in E] # does the kth TA walk from i to j? over all num_homes TAs t = [[model.add_var(var_type=BINARY) for e in E] for k in H] # car flow from vertex u to vertex v f = [model.add_var(var_type=INTEGER) for e in E] \ + [model.add_var(var_type=INTEGER) for v in V] \ + [model.add_var(var_type=INTEGER)] # kth TA flow from vertex u to vertex v f_t = [[model.add_var(var_type=BINARY) for e in E] + [model.add_var(var_type=BINARY) for v in V] for k in H] for i in range(len(f)): model += f[i] >= 0 # For each vertex v where v != source and v != sink, Sum{x_(u, v)} = Sum{x_(v, w)} for v in V: model += xsum([x[i] for i in range(len(E)) if E[i][1] == v]) == xsum( [x[i] for i in range(len(E)) if E[i][0] == v]) # For each vertex v where v != sink, Sum{f_(u, v)} = Sum{f_(v, w)} for j in range(len(V)): model += xsum([f[i] for i in range(len(E)) if E[i][1] == V[j]]) + (f[-1] if V[j] == starting_car_index else 0) \ == xsum([f[i] for i in range(len(E)) if E[i][0] == V[j]]) + f[len(E) + j] # For each edge (u, v) where u != source and v != sink, f_(u, v) <= (big number) * x_(u, v) for i in range(len(E)): model += f[i] <= bigNum * x[i] # For edge (source, start vertex), f_(source, start vertex) <= (big number) model += f[-1] <= bigNum # For each edge (u, sink), f_(u, sink) <= Sum{x_(w, u)} for j in range(len(V)): model += f[j + len(E)] \ <= xsum([x[i] for i in range(len(E)) if E[i][1] == V[j]]) # For just the source vertex, f_(source,start vertex)} = Sum{x_(a, b)} model += f[-1] == xsum(x) # For every TA for every edge, can't flow unless edge is walked along for i in range(len(t)): for j in range(len(E)): model += f_t[i][j] <= t[i][j] # For every TA for every non-home vertex, flow in equals flow out for i in range(len(H)): for j in range(len(V)): if V[j] != H[i]: model += xsum(f_t[i][k] for k in range(len(E)) if E[k][1] == V[j]) + f_t[i][len(E) + j] \ == xsum(f_t[i][k] for k in range(len(E)) if E[k][0] == V[j]) # For every TA, flow out of the source vertex is exactly 1 for k in f_t: model += xsum(k[len(E) + i] for i in range(len(V))) == 1 # For every TA for every edge out of source, can't flow unless car visits vertex for k in f_t: for i in range(len(V)): model += k[len(E) + i] <= xsum( x[j] for j in range(len(E)) if E[j][1] == V[i]) # For every TA, flow into the home vertex is exactly 1 for i in range(len(H)): model += xsum(f_t[i][j] for j in range(len(E)) if E[j][1] == H[i]) + f_t[i][len(E) + H[i]] == 1 # objective function: minimize the distance model.objective = minimize(2.0/3.0 * xsum([x[i] * E[i][2] for i in range(len(E))]) \ + xsum([xsum([t[i][j] * E[j][2] for j in range(len(E))]) for i in range(len(t))])) # WINNING ONLINE model.max_gap = 0.00001 model.emphasis = 2 model.symmetry = 2 if "--no-model-start" not in params: model.start = self.construct_starter(x, t, G, home_indices, start_path) timeout = 300 if "-t" in params: timeout = int(params[params.index("-t") + 1]) if timeout != -1: status = model.optimize(max_seconds=timeout) else: status = model.optimize() objective_value = model.objective_value / edge_scale objective_bound = model.objective_bound / edge_scale if status == OptimizationStatus.OPTIMAL: print('optimal solution cost {} found'.format(objective_value)) self.log_update_entry(Fore.GREEN + "Optimal cost={}.".format(objective_value) + Style.RESET_ALL) else: print("!!!! TIMEOUT !!!!") self.log_update_entry(Fore.RED + "Timeout!" + Style.RESET_ALL) if status == OptimizationStatus.FEASIBLE: print('sol.cost {} found, best possible: {}'.format( objective_value, objective_bound)) self.log_update_entry("Feasible cost={}, bound={}.".format( objective_value, objective_bound)) elif status == OptimizationStatus.NO_SOLUTION_FOUND: print('no feasible solution found, lower bound is: {}'.format( objective_bound)) self.log_update_entry( "Failed, bound={}.".format(objective_bound)) # if no solution found, return inf cost if model.num_solutions == 0: conn.close() return float('inf'), [], {} # printing the solution if found out.write('Route with total cost %g found. \n' % (objective_value)) if "-v" in params: out.write('\nEdges (In, Out, Weight):\n') for i in E: out.write(str(i) + '\t') out.write('\n\nCar - Chosen Edges:\n') for i in x: out.write(str(i.x) + '\t') out.write('\n\nCar - Flow Capacities:\n') for i in f: out.write(str(i.x) + '\t') out.write('\n\nTAs - Home Indices:\n') for i in H: out.write(str(i) + '\n') out.write('\nTAs - Chosen Edges:\n') for i in t: for j in range(len(i)): out.write(str(i[j].x) + '\t') out.write('\n') out.write('\nTAs - Flow Capacities:\n') for i in f_t: for j in range(len(i)): out.write(str(i[j].x) + '\t') out.write('\n') out.write('\nActive Edges:\n') for i in range(len(x)): if (x[i].x >= 1.0): out.write('Edge from %i to %i with weight %f \n' % (E[i][0], E[i][1], E[i][2])) out.write('\n') list_of_edges = [E[i] for i in range(len(x)) if x[i].x >= 1.0] car_path_indices = self.construct_path(starting_car_index, list_of_edges, input_file) walk_cost, dropoffs_dict = self.find_best_dropoffs( G, home_indices, car_path_indices) updated = False if not seen: print("SAVING", input_file) c.execute('INSERT INTO models (input_file, best_objective_bound, optimal) VALUES (?, ?, ?)', \ (input_file, objective_value, status == OptimizationStatus.OPTIMAL)) conn.commit() elif objective_value <= seen[0]: updated = True print("UPDATING", input_file) c.execute('UPDATE models SET best_objective_bound = ?, optimal = ? WHERE input_file = ?', \ (objective_value, status == OptimizationStatus.OPTIMAL, input_file)) conn.commit() if not "-s" in params: print("Walk cost =", walk_cost, "\n") if updated: self.log_update_entry(Fore.GREEN + "Updated" + Style.RESET_ALL) else: self.log_update_entry(Fore.RED + "Not Updated" + Style.RESET_ALL) conn.close() return objective_value, car_path_indices, dropoffs_dict
def tsp_mip_solver(input_data): # parse the input lines = input_data.split('\n') nodeCount = int(lines[0]) points = [] for i in range(1, nodeCount + 1): line = lines[i] parts = line.split() points.append(Point(float(parts[0]), float(parts[1]))) print('Points parsed!') # calculate distance matrix d_m = [[length(q, p) for q in points] for p in points] print('Distance matrix ready!') # declare MIP model m = Model(solver_name='GRB') print('-Model instatiated!', datetime.datetime.now()) # states search emphasis # - '0' (default) balanced approach # - '1' (feasibility) aggressively searches for feasible solutions # - '2' (optimality) explores search space to tighten dual gap m.emphasis = 0 # whenever the distance of the lower and upper bounds is less or # equal max_gap*100%, the search can be finished m.max_gap = 0.05 # specifies number of used threads # 0 uses solver default configuration, # -1 uses the number of available processing cores # ≥1 uses the specified number of threads. # An increased number of threads may improve the solution time but also increases # the memory consumption. Each thread needs to store a different model instance! m.threads = 0 # controls the generation of cutting planes # cutting planes usually improve the LP relaxation bound but also make the solution time of the LP relaxation larger # -1 means automatic # 0 disables completely # 1 (default) generates cutting planes in a moderate way # 2 generates cutting planes aggressively # 3 generates even more cutting planes m.cuts = -1 m.preprocess = 1 m.pump_passes = 20 m.sol_pool_size = 1 nodes = set(range(nodeCount)) # instantiate "entering and leaving" variables x = [[m.add_var(name="x{}_{}".format(p, q), var_type='B') for q in nodes] for p in nodes] # instantiate subtour elimination variables y = [m.add_var(name="y{}".format(i)) for i in nodes] print('-Variables instantiated', datetime.datetime.now()) # declare objective function m.objective = minimize( xsum(d_m[i][j] * x[i][j] for i in nodes for j in nodes)) print('-Objective declared!', datetime.datetime.now()) # declare constraints # leave each city only once for i in tqdm(nodes): m.add_constr(xsum(x[i][j] for j in nodes - {i}) == 1) # enter each city only once for i in tqdm(nodes): m.add_constr(xsum(x[j][i] for j in nodes - {i}) == 1) # subtour elimination constraints for (i, j) in tqdm(product(nodes - {0}, nodes - {0})): if i != j: m.add_constr(y[i] - (nodeCount + 1) * x[i][j] >= y[j] - nodeCount) print('-Constraints declared!', datetime.datetime.now()) #Maximum time in seconds that the search can go on if a feasible solution #is available and it is not being improved mssi = 1000 #default = inf # specifies maximum number of nodes to be explored in the search tree (default = inf) mn = 1000000 #default = 1073741824 # optimize model m within a processing time limit of 'ms' seconds ms = 3000 #default = inf # executes the optimization print('-Optimizer start.', datetime.datetime.now()) #status = m.optimize(max_seconds = ms,max_seconds_same_incumbent = mssi,max_nodes = mn) status = m.optimize(max_seconds=ms, max_seconds_same_incumbent=mssi) print('Opt. Status:', status) print('MIP Sol. Obj.:', m.objective_value) print('Dual Bound:', m.objective_bound) print('Dual gap:', m.gap) sol = [0] c_node = 0 for j in range(nodeCount - 1): for i in range(nodeCount): if round(m.var_by_name("x{}_{}".format(c_node, i)).x) != 0: sol.append(i) c_node = i break obj = m.objective_value # prepare the solution in the specified output format if status == OptimizationStatus.OPTIMAL: output_data = '%.2f' % obj + ' ' + str(1) + '\n' output_data += ' '.join(map(str, sol)) elif status == OptimizationStatus.FEASIBLE: output_data = '%.2f' % obj + ' ' + str(0) + '\n' output_data += ' '.join(map(str, sol)) return output_data
def fl_mip_solver(input_data): # Modify this code to run your optimization algorithm # parse the input lines = input_data.split('\n') parts = lines[0].split() facility_count = int(parts[0]) customer_count = int(parts[1]) facilities = [] for i in range(1, facility_count+1): parts = lines[i].split() facilities.append(Facility(i-1, float(parts[0]), int(parts[1]), Point(float(parts[2]), float(parts[3])) )) customers = [] for i in range(facility_count+1, facility_count+1+customer_count): parts = lines[i].split() customers.append(Customer(i-1-facility_count, int(parts[0]), Point(float(parts[1]), float(parts[2])))) print('F count:',facility_count) print('C count:',customer_count) # instantiates setup cost vector set_cost = [f.setup_cost for f in facilities] # instantiates proportional capacity matrix such that Cap[i,j] represents the demand of # customer 'j' as a fraction of the total capacity of facility 'i' Cap = [[c.demand/f.capacity for c in customers] for f in facilities] # instantiates distance matrix in such a way that "sum_{j \in M} D[i,j]*at[i,j]" is the total # distance cost for facility 'i' D = [[length(c.location, f.location) for c in customers] for f in facilities] # declares MIP model #m = Model(solver_name=CBC) m = Model(solver_name='GRB') print('-Model instatiated!',datetime.datetime.now()) # states search emphasis # - '0' (default) balanced approach # - '1' (feasibility) aggressively searches for feasible solutions # - '2' (optimality) explores search space to tighten dual gap m.emphasis = 2 # whenever the distance of the lower and upper bounds is less or # equal max_gap*100%, the search can be finished m.max_gap = 0.05 # specifies number of used threads # 0 uses solver default configuration, # -1 uses the number of available processing cores # ≥1 uses the specified number of threads. # An increased number of threads may improve the solution time but also increases # the memory consumption. Each thread needs to store a different model instance! m.threads = -1 # controls the generation of cutting planes # cutting planes usually improve the LP relaxation bound but also make the solution time of the LP relaxation larger # -1 means automatic # 0 disables completely # 1 (default) generates cutting planes in a moderate way # 2 generates cutting planes aggressively # 3 generates even more cutting planes m.cuts=-1 m.preprocess=1 m.pump_passes=10 m.sol_pool_size=1 # instantiates open facilities variables op = [m.add_var(name="op{}".format(i),var_type='B') for i in range(facility_count)] # instantiates matrix of atribution variables # (line 'i' is an atribution vector for facility 'i') # e.g.: At[3][4] returns whether customer 4 is assigned to facility 3 At = [[m.add_var(name="At{},{}".format(i,j) ,var_type='B') for j in range(customer_count)] for i in range(facility_count)] print('-Variables declared!',datetime.datetime.now()) # instantiates objective function # m.objective = minimize("setup costs" + "distance costs") # Form example: # m.objective = minimize( # xsum(dist[i, j] * x[i, j] for (i, j) in product(F, C)) + xsum(y[i] for i in F) ) m.objective = minimize( xsum(set_cost[i]*op[i] for i in range(facility_count)) + xsum(sum(D[i][j]*At[i][j] for j in range(customer_count)) for i in range(facility_count)) ) print('-Objective declared!',datetime.datetime.now()) # instatiates capacity constraints # -can be expressed as "sum_{j \in M} Cap[i,j]*At[i,j] <= op[i]" for all facilities 'i' # -if a facility is closed (op[i]=0), its effective capacity is 0 for i in range(facility_count): m.add_lazy_constr( xsum(Cap[i][j]*At[i][j] for j in range(customer_count)) <= op[i] ) # instantiates assignment constraints (maximum of 1 facility per customer) # -can be expressed as: "sum of elements over of each column of 'At' == 1" for i in range(customer_count): m += xsum(At[j][i] for j in range(facility_count)) == 1 print('-Contraints processed!',datetime.datetime.now()) #Maximum time in seconds that the search can go on if a feasible solution #is available and it is not being improved mssi = 1000 #default = inf # specifies maximum number of nodes to be explored in the search tree (default = inf) mn = 40000 #default = 1073741824 # optimize model m within a processing time limit of 'ms' seconds ms = 3000 #default = inf print('-Optimizer start.',datetime.datetime.now()) # executes the optimization #status = m.optimize(max_seconds = ms,max_seconds_same_incumbent = mssi,max_nodes = mn) status = m.optimize(max_seconds = ms , max_seconds_same_incumbent = mssi) final_obj = m.objective_value print('Opt. Status:',status) print('MIP Sol. Obj.:',final_obj) print('Dual Bound:',m.objective_bound) print('Dual gap:',m.gap) used=[i for i in range(facility_count) if m.vars[i].x==1] solution=[None] * customer_count for i in range(facility_count): for j in range(customer_count): if round(m.vars[i*customer_count + j + facility_count].x) == 1: solution[j]=i # parse output varibles and convert to conventional solution output format # calculate the cost of the solution obj = sum([facilities[f].setup_cost for f in used]) for customer in customers: obj += length(customer.location, facilities[solution[customer.index]].location) if status == OptimizationStatus.OPTIMAL: # prepare the solution in the specified output format output_data = '%.2f' % obj + ' ' + str(1) + '\n' output_data += ' '.join(map(str, solution)) elif status == OptimizationStatus.FEASIBLE: output_data = '%.2f' % obj + ' ' + str(0) + '\n' output_data += ' '.join(map(str, solution)) return output_data
def mip_solver(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]))) # a trivial algorithm for filling the knapsack # it takes items in-order until the knapsack is full value = 0 weight = 0 taken = [0]*len(items) # declare value vector val_vec = [item.value for item in items] # declare weight vector scaled by capacity wgt_vec = [item.weight/capacity for item in items] # start MIP solver m = Model(solver_name='GRB') print('-Model instatiated!',datetime.datetime.now()) # states search emphasis # - '0' (default) balanced approach # - '1' (feasibility) aggressively searches for feasible solutions # - '2' (optimality) explores search space to tighten dual gap m.emphasis = 2 # whenever the distance of the lower and upper bounds is less or # equal max_gap*100%, the search can be finished m.max_gap = 0.05 # specifies number of used threads # 0 uses solver default configuration, # -1 uses the number of available processing cores # ≥1 uses the specified number of threads. # An increased number of threads may improve the solution time but also increases # the memory consumption. Each thread needs to store a different model instance! m.threads = -1 # controls the generation of cutting planes # cutting planes usually improve the LP relaxation bound but also make the solution time of the LP relaxation larger # -1 means automatic # 0 disables completely # 1 (default) generates cutting planes in a moderate way # 2 generates cutting planes aggressively # 3 generates even more cutting planes m.cuts=-1 m.preprocess=1 m.pump_passes=10 m.sol_pool_size=1 # instantiates taken items variable vector taken = [m.add_var(name="it{}".format(i),var_type='B') for i in range(item_count)] print('-Variables declared!',datetime.datetime.now()) # instantiates objective function m.objective = maximize( xsum( val_vec[i]*taken[i] for i in range(item_count) ) ) print('-Objective declared!',datetime.datetime.now()) m.add_constr( xsum( wgt_vec[i]*taken[i] for i in range(item_count)) <=1 ) print('-Contraints processed!',datetime.datetime.now()) #Maximum time in seconds that the search can go on if a feasible solution #is available and it is not being improved mssi = 1000 #default = inf # specifies maximum number of nodes to be explored in the search tree (default = inf) mn = 40000 #default = 1073741824 # optimize model m within a processing time limit of 'ms' seconds ms = 3000 #default = inf print('-Optimizer start.',datetime.datetime.now()) # executes the optimization #status = m.optimize(max_seconds = ms,max_seconds_same_incumbent = mssi,max_nodes = mn) status = m.optimize(max_seconds = ms , max_seconds_same_incumbent = mssi) final_obj = m.objective_value print('Opt. Status:',status) print('MIP Sol. Obj.:',final_obj) print('Dual Bound:',m.objective_bound) print('Dual gap:',m.gap) sol = [round(it.x) for it in taken] value = int(final_obj) taken = sol # prepare the solution in the specified output format if status == OptimizationStatus.OPTIMAL: output_data = str(value) + ' ' + str(1) + '\n' output_data += ' '.join(map(str, taken)) elif status == OptimizationStatus.FEASIBLE: output_data = str(value) + ' ' + str(0) + '\n' output_data += ' '.join(map(str, taken)) if item_count == 10000: output_data=greedy(input_data) return output_data