def someThing(): import pulp pulp.combination([1, 2, 3, 4], 2) # 2的组合 pulp.allcombinations([1, 2, 3, 4], 2) # 2以下组合 pulp.permutation([1, 2, 3, 4], 2) # 2的排列 pulp.allpermutations([1, 2, 3, 4], 2) # 2以下排列 pass
def set_partitioning_problem(): max_tables = 5 max_table_size = 4 guests = "A B C D E F G I J K L M N O P Q R".split() def happiness(table): """ Find the happiness of the table - by calculating the maximum distance between the letters. """ return abs(ord(table[0]) - ord(table[-1])) # Create list of all possible tables. possible_tables = [tuple(c) for c in pulp.allcombinations(guests, max_table_size)] # Create a binary variable to state that a table setting is used. x = pulp.LpVariable.dicts("table", possible_tables, lowBound=0, upBound=1, cat=pulp.LpInteger) seating_model = pulp.LpProblem("Wedding Seating Model", pulp.LpMinimize) seating_model += pulp.lpSum([happiness(table) * x[table] for table in possible_tables]) # Specify the maximum number of tables. seating_model += pulp.lpSum([x[table] for table in possible_tables]) <= max_tables, "Maximum_number_of_tables" # A guest must seated at one and only one table. for guest in guests: seating_model += pulp.lpSum([x[table] for table in possible_tables if guest in table]) == 1, "Must_seat_{}".format(guest) if False: # I've taken the optimal solution from a previous solving. x is the variable dictionary. solution = { ("M", "N"): 1.0, ("E", "F", "G"): 1.0, ("A", "B", "C", "D"): 1.0, ("I", "J", "K", "L"): 1.0, ("O", "P", "Q", "R"): 1.0, } for k, v in solution.items(): x[k].setInitialValue(v) #x[k].fixValue() if True: seating_model.solve() else: # I usually turn msg=True so I can see the messages from the solver confirming it loaded the solution correctly. solver = pulp.PULP_CBC_CMD(msg=True, warmStart=True) #solver = pulp.CPLEX_CMD(msg=True, warmStart=True) #solver = pulp.GUROBI_CMD(msg=True, warmStart=True) #solver = pulp.CPLEX_PY(msg=True, warmStart=True) #solver = pulp.GUROBI(msg=True, warmStart=True) seating_model.solve(solver) print("The choosen tables are out of a total of {}:".format(len(possible_tables))) for table in possible_tables: if x[table].value() == 1.0: print(table)
def main(): player_names = list(VOTES.keys()) table_permutations = pulp.allcombinations(player_names, len(player_names)) possible_setups = flatmap(mapper, table_permutations) possible_setups = list(filter(is_teachable, possible_setups)) included = pulp.LpVariable.dicts('Included setups', possible_setups, 0, 1, pulp.LpInteger) problem = pulp.LpProblem('Game Seating Problem', pulp.LpMaximize) problem += pulp.lpSum( [objective(setup) * included[setup] for setup in possible_setups]) for player in player_names: problem += pulp.lpSum([ included[setup] for setup in possible_setups if player in setup ]) == 1, f"Must seat {player}" problem.solve() print([(objective(setup), *setup) for setup in possible_setups if included[setup].value() == 1])
def __repr__(self): return '{}({})'.format(self.name, self.position) PEOPLE_NAMES = 'A B C D E F G H I J K L M'.split() people = [Person(name) for name in PEOPLE_NAMES] def happiness(project): return -len(set([person.position for person in project])) # create list of all possible project combinations possible_project_combinations = [ tuple(c) for c in pulp.allcombinations(people, max_project_size) ] # create a binary variable to state that a project setting is used x = pulp.LpVariable.dicts('project', possible_project_combinations, lowBound=0, upBound=1, cat=pulp.LpInteger) alocs_model = pulp.LpProblem("People Allocation Model", pulp.LpMinimize) alocs_model += sum([ happiness(project) * x[project] for project in possible_project_combinations ])
max_tables = 5 max_table_size = 4 guests = 'A B C D E F G I J K L M N O P Q R'.split() def happiness(table): """ Find the happiness of the table - by calculating the maximum distance between the letters """ return abs(ord(table[0]) - ord(table[-1])) #create list of all possible tables possible_tables = [ tuple(c) for c in pulp.allcombinations(guests, max_table_size) ] #create a binary variable to state that a table setting is used x = pulp.LpVariable.dicts('table', possible_tables, lowBound=0, upBound=1, cat=pulp.LpInteger) seating_model = pulp.LpProblem("Wedding Seating Model", pulp.LpMinimize) seating_model += sum( [happiness(table) * x[table] for table in possible_tables]) #specify the maximum number of tables
"scenario_loss", labels, 0, nbottles, ) # The worst loss is worse than each scenario loss for i in labels: prob += worst_loss >= scenario_loss[i] # An scenario is generated by the overlapping of underlying # labels. For each such set, if every underlying label has a non-zero # allocation, then the allocations to all the labels must be added to # the scenario loss scenario2labels = {i : set() for i in labels} for label_set in allcombinations(nonzeros, npoisoned): scenario = 0 for label in label_set: scenario |= label for label in label_set: scenario2labels[scenario].add(label) for scenario in labels: prob += scenario_loss[scenario] == lpSum(allocs[label0] for label0 in scenario2labels[scenario]) prob.writeLP("drunk_mice.lp") prob.solve() alloc = [0] * len(labels) for l in nonzeros: alloc[l] = int(allocs[l].value())
import pulp max_tables = 5 max_table_size = 4 guests = 'A B C D E F G I J K L M N O P Q R'.split() def happiness(table): """ Find the happiness of the table - by calculating the maximum distance between the letters """ return abs(ord(table[0]) - ord(table[-1])) #create list of all possible tables possible_tables = [tuple(c) for c in pulp.allcombinations(guests, max_table_size)] #create a binary variable to state that a table setting is used x = pulp.LpVariable.dicts('table', possible_tables, lowBound = 0, upBound = 1, cat = pulp.LpInteger) seating_model = pulp.LpProblem("Wedding Seating Model", pulp.LpMinimize) seating_model += sum([happiness(table) * x[table] for table in possible_tables]) #specify the maximum number of tables seating_model += sum([x[table] for table in possible_tables]) <= max_tables, \ "Maximum_number_of_tables"
def _tables(self): tables = pulp.allcombinations(self.humans, self.max_table_size) return (table for table in tables if len(table) > 1)
def main(target_number, dispo_file_path, previous_groups_file_path): # Warning print("\nWarning: Names have to be carefuly and properly written in files") # Import arguments # target_number is the desired number of people in each group # Groups will be made plus/minus 1 person of target_number target_number = int(target_number) ## File of availabilities (imported from a doodle and already pre-processed) ### Header = "Name" + dates ### Each row is name and 0 or 1 for each date dispo_file = dispo_file_path ## File of previous groups ### Template: list of previous groups in the format [Ordinal of session, [list of people names]] previous_groups_file = previous_groups_file_path # Generate data for solving the optimization problem ## Create lists of data ### constraints is the availability list of people list (0 or 1) ### all dates and people are in the same order in their list than in the constraint matrix constraints = [] people_names = [] date_names = [] previous_groups_raw = [] ## Read dispo file to generate constraint matrix but also names and dates with open(dispo_file) as csvfile: import csv csv = csv.reader(csvfile, delimiter=',') header = True for row in csv: if header: date_names = row[1:] header = False else: people_names.append(unidecode.unidecode(row[0])) constraints.append(row[1:]) people = [i for i in range(len(people_names))] dates = [j for j in range(len(date_names))] ## Import the file of previous groups with open(previous_groups_file) as json_file: previous_groups_raw = json.load(json_file) ## Transform the raw file into a dictionnary with keys people that plays the current session and value list of tuples (person, ordinal session play with this person) -- the same person can appear several times here ## Update the number of last played session for each to people to normalize the optimization function previous_groups = {people: [] for people in people_names} last_played_session = {people: 0 for people in people_names} for session in previous_groups_raw: for person in session[1]: for other_person in session[1]: if person != other_person: try: last_played_session[unidecode.unidecode(person)] = max( session[0], last_played_session[unidecode.unidecode(person)]) previous_groups[unidecode.unidecode(person)].append( [other_person, session[0]]) except: pass # Generate liste of possible groups to give as input ## Create list of all possibilites group_only_combinations = [ tuple(c) for c in pulp.allcombinations(people, target_number + 1) ] ### Remove undesired combinations #### Only groups of target_number - 1 to target_number + 1 people are considered group_only_combinations = [ x for x in group_only_combinations if len(x) >= target_number - 1 ] #### Remove combinations of 3 of 5 people in setting in which they are not suited if len(people_names) % target_number == 1: group_only_combinations = [ x for x in group_only_combinations if len(x) >= target_number ] if ((target_number != 2) and (len(people_names) % target_number == target_number - 1)): group_only_combinations = [ x for x in group_only_combinations if len(x) <= target_number ] combinations = [(date, combi) for (date, combi) in product(dates, group_only_combinations)] ### Remove impossible date/person matches (such that this constraint is already addressed) def possible(combi): possible = True for person in combi[1]: if int(constraints[person][combi[0]]) == 0: possible = False return (possible) combinations = [x for x in combinations if possible(x)] # Define the optimization function of the problem ## Binary variable to state that a setting is used x = pulp.LpVariable.dicts( 'Create groups based on availability constraints and people turnover', combinations, lowBound=0, upBound=1, cat=pulp.LpInteger) ## Fitness function ### Sum of ordinals of people that already play together in this session ; quantity to minimize (if they play recently, ordinal is higher) def fitness(combi): fitness = 0 n = len(combi[1]) for i in range(0, n): name = unidecode.unidecode(people_names[combi[1][i]]) to_normalized_number_session = last_played_session[name] for j in range(0, n): another_name = unidecode.unidecode(people_names[combi[1][j]]) for (person, session) in previous_groups[name]: if person == another_name: fitness += session / to_normalized_number_session return (fitness) ## Optimization problem problem = pulp.LpProblem("Casting", pulp.LpMinimize) ## Objective function ### Sum of exponential of fitness function for all groups, such that an optimum has to be achieved in each combi to get a global optimum problem += sum([exp(fitness(combi)) * x[combi] for combi in combinations]) # Define the constraints of optimization problem ## Availability constraint is already assumed at the moment of selection of possibilities ## Every person plays once for person in people: problem += sum([ x[combi] for combi in combinations if person in combi[1] ]) == 1, "%s must play" % person ## Each date is used at most once for date in dates: problem += sum([ x[combi] for combi in combinations if date == combi[0] ]) <= 1, "%s can not be used twice" % date ## Group sizes are as close as possible to target_number - this translates into a number of dates to match if (len(people) / float(target_number)) % 1 != 0.5: problem += sum([x[combi] for combi in combinations]) == round( len(people) / target_number), "Group sizes close to targer number" else: problem += sum([ x[combi] for combi in combinations ]) == int(len(people) / target_number ) + 1, "Group sizes close to targer number / low bound" # Solve the model and return the solution ## Solve the model problem.solve() ## Check that constraints are satisfied problem = False for combi in combinations: if x[combi].value() == 1.0: for person in combi[1]: if constraints[person][combi[0]] == "0": problem = True if problem: return ("Constraints not respected") ## Print the solution and return cost (scale 0-1) cost = 0 print("\nGroups are:\n") separator = ", " for combi in combinations: if x[combi].value() == 1.0: cost += exp(fitness(combi)) print(date_names[combi[0]] + ": " + separator.join([people_names[person] for person in combi[1]]) + "\n") print("Cost function is " + str(cost))
for i, p in enumerate(pn): i += counter local_counter += 1 dot.node(str(i), p) for j in set(preferences[i][0]): dot.edge(str(i), str(j)) for j in set(preferences[i][1]): dot.edge(str(i), str(j), color="red") counter += local_counter dot.render(f'sociogram{s}') assert sum([i*j for i,j in zip(tents.keys(), tents.values())]) >= sum([len(p) for p in participants]), "Not enough capacity." # generate all possible participant combinations up to the maximum tent capacity possible_tents = [tuple(c) for p in participants for c in pulp.allcombinations(p, max(tents.keys()))] def happiness(person, tent): like = sum([(i in tent) for i in preferences[person][0]]) dislike = sum([(i in tent) for i in preferences[person][1]]) return like - (2 * dislike) ** 1.5 def tent_happiness(tent): """ Find the happiness of the tent """ #like = sum([(i in tent) for p in tent for i in preferences[p][0]]) #dislike = sum([(i in tent) for p in tent for i in preferences[p][1]]) return sum([happiness(person, tent) for person in tent]) # create a binary variable to state that a tent setting is used