组合太多

如何解决组合太多

嗨,我正在尝试生成所有可能的工人到建筑物的组合。 (让我解释一下我的场景):

我正在玩《我的世界》MineColonies在这个模组中,你有殖民者,他们可以在建筑物中分配工作。这些工人拥有技能和分配给他们的分数。 (例如敏捷:20,力量:5 等)并且当分配到技能与之相称的殖民者时,建筑物的工作会得到更好的执行...

所以我创建了一个包含所有工人和建筑物的数据库,并希望优化哪些工人在哪些建筑物内工作。

buildings_dict = {1: ['Strength','Focus'],2: ['Adaptability','Athletics'],3: ['KNowledge','Dexterity'],4: ['Adaptability','KNowledge'],6: ['Stamina',5: ['Athletics','Stamina'],7: ['Focus','Agility'],8: ['Dexterity','Creativity'],9: ['Strength',10: ['Adaptability',11: ['Agility','Adaptability'],12: ['Mana',13: ['Strength',14: ['Athletics','Strength'],15: ['Creativity',16: ['KNowledge','Mana'],17: ['Agility','Adaptability']}

workers_dict = {3: {'Mana': 30,'Focus': 1,'Agility': 3,'Stamina': 3,'KNowlege': 30,'Strenght': 8,'Athletics': 13,'Dexterity': 6,'Creativity': 10,'Adaptability': 10,'Intelligence': 10},4: {'Mana': 29,'Focus': 32,'Agility': 22,'Stamina': 28,'KNowlege': 21,'Strenght': 30,'Athletics': 20,'Dexterity': 31,'Creativity': 31,'Adaptability': 8,'Intelligence': 18},5: {'Mana': 13,'Agility': 9,'Stamina': 27,'KNowlege': 9,'Strenght': 13,'Athletics': 15,'Dexterity': 21,'Creativity': 16,'Adaptability': 13,'Intelligence': 28},6: {'Mana': 17,'Focus': 14,'Agility': 10,'Stamina': 17,'KNowlege': 13,'Strenght': 5,'Athletics': 10,'Dexterity': 15,'Creativity': 1,'Adaptability': 11,'Intelligence': 4},7: {'Mana': 1,'Focus': 8,'Agility': 6,'KNowlege': 11,'Strenght': 17,'Athletics': 30,'Dexterity': 1,'Creativity': 5,'Intelligence': 5},8: {'Mana': 6,'Agility': 12,'Stamina': 30,'KNowlege': 20,'Strenght': 15,'Dexterity': 9,'Creativity': 17,'Adaptability': 30,'Intelligence': 19},9: {'Mana': 5,'Focus': 7,'Agility': 19,'Stamina': 5,'KNowlege': 22,'Strenght': 18,'Athletics': 26,'Dexterity': 10,'Creativity': 24,'Adaptability': 20,'Intelligence': 22},10: {'Mana': 8,'Focus': 12,'Agility': 27,'KNowlege': 17,'Strenght': 1,'Athletics': 5,'Creativity': 7,'Adaptability': 29,'Intelligence': 1},11: {'Mana': 1,'Focus': 4,'Agility': 5,'KNowlege': 16,'Strenght': 11,'Athletics': 28,'Dexterity': 11,'Adaptability': 12,12: {'Mana': 7,'Agility': 17,'Stamina': 25,'KNowlege': 23,'Strenght': 4,'Athletics': 8,'Dexterity': 26,'Creativity': 15,13: {'Mana': 2,'Stamina': 21,'KNowlege': 24,'Creativity': 12,14: {'Mana': 9,'Focus': 16,'Agility': 14,'KNowlege': 14,'Strenght': 24,'Creativity': 19,'Adaptability': 23,15: {'Mana': 23,'Focus': 15,'Stamina': 12,'Strenght': 12,'Dexterity': 29,'Adaptability': 19,'Intelligence': 12},17: {'Mana': 21,'Focus': 23,'Agility': 30,'Stamina': 18,'KNowlege': 27,'Strenght': 7,'Adaptability': 22,18: {'Mana': 11,'Focus': 11,'Agility': 4,'Stamina': 7,'KNowlege': 28,'Dexterity': 28,'Creativity': 13,'Intelligence': 30},19: {'Mana': 11,20: {'Mana': 15,'Focus': 20,'Agility': 28,'Stamina': 22,'KNowlege': 18,'Athletics': 23,'Dexterity': 19,'Creativity': 20,'Adaptability': 27,'Intelligence': 20},21: {'Mana': 30,'Strenght': 3,'Athletics': 6,'Dexterity': 17,'Creativity': 4,22: {'Mana': 9,'Focus': 10,'Stamina': 26,'KNowlege': 1,'Adaptability': 14,'Intelligence': 16},23: {'Mana': 4,'KNowledge': 21,'Strength': 25,'Athletics': 12,'Dexterity': 23,'Creativity': 26,'Adaptability': 21,24: {'Mana': 1,'Agility': 18,'Stamina': 24,'KNowledge': 25,'Strength': 20,'Athletics': 9,'Dexterity': 14,'Intelligence': 7},25: {'Mana': 12,'Focus': 13,'Agility': 21,'Stamina': 23,'KNowledge': 11,'Strength': 16,'Athletics': 18,'Dexterity': 24,26: {'Mana': 10,'KNowledge': 17,'Strength': 24,'Adaptability': 5,27: {'Mana': 11,'KNowledge': 15,'Athletics': 17,'Dexterity': 12,'Intelligence': 9},28: {'Mana': 7,'Focus': 21,'KNowledge': 14,'Strength': 15,'Dexterity': 16,'Creativity': 2,29: {'Mana': 12,'Focus': 25,'Agility': 29,'Stamina': 6,'KNowledge': 7,'Strength': 10,'Athletics': 14,'Creativity': 6,'Intelligence': 29},30: {'Mana': 21,'Focus': 17,'Agility': 8,'KNowledge': 22,'Strength': 22,'Dexterity': 13,'Adaptability': 24,'Intelligence': 13}}

抱歉,代码块太长,是的,我意识到 ID 不一定正确(希望使其可重现)。

所以我使用 itertools.permutations 将所有工人组合到建筑物中:

import itertools
workers_ls = list(workers_dict.keys())
combinations = list(itertools.permutations(workers_ls,len(buildings_dict))

(我打算在之后对组合进行评分)

这显然从未完成运行,因为它类似于 27! = 1×10²⁸。 我想知道是否有其他解决方案可以解决我的问题,或者是否有一种无需经过所有组合即可确定最佳解决方案的方法。 (我愿意用其他编码语言工作)

谢谢!

解决方法

我假设您想最大化总产量的总和。例如,当没有分配工人时,总产量为零(或某个不依赖于工人分配的常数)。如果您将具有 Agility 2 和 Focus 3 的工人与具有属性 [Agility,Focus] 的建筑物配对,则将 2+3=5 添加到总产量中。

像这样的问题通常可以通过线性规划来解决。我将使用 pulp 来帮助制定线性规划问题。我还建议您查看 JuliaJuMP

计算总产量的实际规则可能更复杂。如果 (1) 可以定义生产矩阵的一些模拟,并且 (2) 总产量可以表示为(工人、建筑)对的产量之和,您仍然可以使用线性规划。

这里有两种方法可以解决这个问题。第一个允许每个建筑物有多个工人,第二个不允许。

设置

import pandas as pd
import numpy as np
# !pip install pulp
import pulp

df_buildings = pd.DataFrame(buildings_dict).T
df_workers = pd.DataFrame(workers_dict).T

# there are a few typos,e.g. Strenght vs. Strength and Knowlege vs. Knowledge
# let's fix this first
df_workers.Knowledge.fillna(df_workers.Knowlege,inplace=True)
df_workers.Strength.fillna(df_workers.Strenght,inplace=True)
del df_workers["Strenght"],df_workers["Knowlege"]

# fixing some notation
workers = df_workers.index.tolist() # list of workers
buildings =  df_buildings.index.tolist() # list of building

# next,we define production matrix
# production[i,j] will contain the productivity of 
# worker i when assigned to building j
# you could vectorize this step,though it seems fast enough here
production = pd.DataFrame(index=workers,columns=buildings)
for i in df_workers.index:
  for j in df_buildings.index:
    production.loc[i,j] = df_workers.loc[i,df_buildings.loc[j]].sum()

print(production.head())
#    1   2   3   4   6   5   7   8   9   10  11  12  13  14  15  16  17
# 3   9  23  36  40  16  16   4  16   9  13  13  60  11  21  16  60  13
# 4  62  28  52  29  48  48  54  62  62  36  30  50  58  50  62  50  30
# 5  14  28  30  22  42  42  10  37  14  40  22  22  40  28  37  22  22
# 6  19  21  28  24  27  27  24  16  19  28  21  30  22  15  16  30  21
# 7  25  41  12  22  57  57  14   6  25  38  17  12  44  47   6  12  17

每栋楼允许多名工人

prob = pulp.LpProblem("MineColoniesProblem",pulp.LpMaximize)

# in the solved problem,assignment[i,j] == 1 whenever i is assigned to j
assignment = pulp.LpVariable.dicts("Assignment",(workers,buildings),cat="Binary")

# our objective is to maximize the sum of production
prob += sum(assignment[i][j] * production.loc[i,j]
            for i in workers for j in buildings)

# each worker can be assigned to at most one building:
for i in workers:
  prob += sum(assignment[i][j] for j in buildings) <= 1

prob.solve()
# make sure that we got an optimal solution
assert prob.status == 1

# generically,we get an integer solution
assignment_dict = {i: j for i in workers for j in buildings
                   if assignment[i][j].varValue == 1}
print(f"Total production is {prob.objective.value()}") # 1401

# here is the the solution
# assignment_dict_saved = {3: 12,4: 1,5: 5,6: 16,7: 5,8: 6,9: 2,10: 17,11: 6,12: 10,13: 4,14: 6,15: 3,17: 7,18: 3,19: 3,20: 11,21: 12,22: 17,23: 15,24: 4,25: 10,26: 13,27: 9,28: 7,29: 7,30: 2}

每栋楼最多一名工人

prob = pulp.LpProblem("MineColoniesProblem",j]
            for i in workers for j in buildings)

# each worker can be assigned to at most one building:
for i in workers:
  prob += sum(assignment[i][j] for j in buildings) <= 1

# each building has at most one worker
for j in buildings:
  prob += sum(assignment[i][j] for i in workers) <= 1

prob.solve()
# make sure that we got an optimal solution
assert prob.status == 1

# generically,we get an integer solution
assignment_dict = {i: j for i in workers for j in buildings
                   if assignment[i][j].varValue == 1}
# assignment_dict_saved = {3: 16,4: 9,8: 2,10: 11,14: 14,19: 8,20: 17,27: 1,29: 7}
print(f"Total production is {prob.objective.value()}") # 929

我们可以看到,当我们允许每个建筑物有多个工人时,总产量会更高。这是意料之中的,因为最大化问题的约束较少。

我们还可以将优化的生产与随机分配工人到建筑物时的生产进行比较。垂直线对应于最佳生产。看起来我们做得很好。

enter image description here

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?
Java在半透明框架/面板/组件上重新绘画。
Java“ Class.forName()”和“ Class.forName()。newInstance()”之间有什么区别?
在此环境中不提供编译器。也许是在JRE而不是JDK上运行?
Java用相同的方法在一个类中实现两个接口。哪种接口方法被覆盖?
Java 什么是Runtime.getRuntime()。totalMemory()和freeMemory()?
java.library.path中的java.lang.UnsatisfiedLinkError否*****。dll
JavaFX“位置是必需的。” 即使在同一包装中
Java 导入两个具有相同名称的类。怎么处理?
Java 是否应该在HttpServletResponse.getOutputStream()/。getWriter()上调用.close()?
Java RegEx元字符(。)和普通点?