Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/282.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 当一个彻底的搜索花费的时间太长时,我如何找到一个最佳的组合?_Python_C#_Algorithm_Mathematical Optimization_Linear Programming - Fatal编程技术网

Python 当一个彻底的搜索花费的时间太长时,我如何找到一个最佳的组合?

Python 当一个彻底的搜索花费的时间太长时,我如何找到一个最佳的组合?,python,c#,algorithm,mathematical-optimization,linear-programming,Python,C#,Algorithm,Mathematical Optimization,Linear Programming,免责声明:我是一个完全的业余爱好者,没有正式的培训,只是自学了一点C#和Python 有47个插槽。每一项必须由一项填写。 这些插槽分为8组。 项目分为相同的8组。 每个插槽只能由同一组的一个项目填充。 同一项目可用于填充多个插槽 每个项目由一个名称、一个组和9个统计数据组成 item ("name", "group", "stat1", "stat2", "stat3", ..., "

免责声明:我是一个完全的业余爱好者,没有正式的培训,只是自学了一点C#和Python

有47个插槽。每一项必须由一项填写。 这些插槽分为8组。 项目分为相同的8组。
每个插槽只能由同一组的一个项目填充。
同一项目可用于填充多个插槽

每个项目由一个名称、一个组和9个统计数据组成

item ("name", "group", "stat1", "stat2", "stat3", ..., "stat9")

exampleItem (exampleName, groupA, 3, 8, 19, ..., 431)
每个插槽由一个ID和一个组组成

slot1 (1, groupC)
在每个插槽中填充一个项目(遵循上述规则)

然后把每个不同的数据加起来

stat1Total=item1(stat1)+item2(stat1)+item3(stat1)+...+item47(stat1)
目标是:
-在每个插槽中填充相应组的项目。(无空插槽)
-使stat1Total、stat2Total和stat3Total达到一定数量(stat1Goal、stat2Goal、stat3Goal)
-让stat1Total、stat2Total和stat3Total尽可能少地超过该金额
-最大化所有其他STATTOTALL,每个STATTOTALL都有权重

输出满足上述目标的项目的最佳组合。(如果两个或多个组合都是最佳组合,则输出所有组合

我试图搜索所有可能的组合以获得最佳输出,但总的来说,这将达到2.16x10^16个可能的组合,因此我认为这是不可行的。
现在我不知道如何解决这个问题,我读的关于整数规划的书越多,我就越困惑

为了说明这个问题,我将给出一个包含3个插槽、2个组和5个项目的简化示例:

SlotA、SlotB和SlotC必须分别由5项中的一项填写。
插槽A和SlotB属于组1,SlotC属于组2。
这些项目被归为相同的组。因此,我们有属于组1的项目1、项目2和项目3,以及属于组2的项目4和项目5

这意味着SlotA和SlotB只能由项目1、项目2和项目3填充。您可以想象插槽是不同形状的孔,并且项目的形状适合这些孔。您不能将星形销钉装入方形孔,也不能将项目5装入SlotB,因为它不适合

项目本身具有不同的统计信息。在本例中,我们假设每个项目只具有它所属的组和2个统计信息:StatDark、StatLight。这些统计信息可以采用0到10之间的整数值

Item1(Group1, StatDark=3, StatLight=5)
Item2(Group1, StatDark=7, StatLight=1)
Item3(Group1, StatDark=2, StatLight=5)
Item4(Group2, StatDark=1, StatLight=6)
Item5(Group2, StatDark=2, StatLight=5)
本例的目标是:
-在遵守分组规则的情况下,用一个项目填充每个插槽
-使所有选定项目的所有StatDark之和等于或大于9
-将StatDark降至9以上(9以上的每个StatDark都是无用和浪费的)
-最大化所有选定项目的所有StatLight之和

在这种情况下,最佳解决方案是:
SlotA和SlotB:Item2和Item3
SlotC:项目4

以下是指向此示例的完整表格的链接:

我希望这个例子能让这个问题更容易理解。

数学模型 我将介绍一个二进制变量:

x[i,j] = 1 if item i is assigned to slot j
         0 otherwise
这是我们的第一个问题:有许多(i,j)组合是不允许的。智能模型会尝试不生成禁止的组合。因此我们需要实现一个稀疏变量,而不是完全分配的变量。只有当
allowed(i,j)
为真时,我们才会分配和使用
x[i,j]

此外,引入一个连续变量
xstat[s]
,用于计算每个stat的总值

一旦我们有了这些,我们就可以写下约束条件:

  sum( i | allowed(i,j),  x[i,j] ) = 1  for all slots j          (exactly one item in each slot)
  xstat[s] = sum( (i,j) | allowed(i,j),  x[i,j] * stat[i,s])     (calculate total stats)  
  xstat['StatDark'] >= 9                                         
目标是两个目标的加权和:

  minimize xstat['StatDark'] - 9
  maximize xstat['StatLight']
因此,我们:

  maximize -w1*(xstat['StatDark'] - 9) +  w2*xstat['StatLight']
对于用户提供的重量w1和w2

这两个问题使问题稍微复杂一些。此外,我们需要对数据进行一些处理,使其适合在优化模型中使用

Python代码 讨论 合并的表
如下所示:

Item   Slot   Group
-----------------------
Item1   SlotA   Group1
        SlotB   Group1
Item2   SlotA   Group1
        SlotB   Group1
Item3   SlotA   Group1
        SlotB   Group1
Item4   SlotC   Group2
Item5   SlotC   Group2 
assignItemsToSlots:
MAXIMIZE
-0.3*xstat_StatDark + 0.7*xstat_StatLight + 2.6999999999999997
SUBJECT TO
_C1: x_('Item1',_'SlotA') + x_('Item2',_'SlotA') + x_('Item3',_'SlotA') = 1

_C2: x_('Item1',_'SlotB') + x_('Item2',_'SlotB') + x_('Item3',_'SlotB') = 1

_C3: x_('Item4',_'SlotC') + x_('Item5',_'SlotC') = 1

_C4: xstat_StatDark >= 9

_C5: - 3 x_('Item1',_'SlotA') - 3 x_('Item1',_'SlotB')
 - 7 x_('Item2',_'SlotA') - 7 x_('Item2',_'SlotB') - 2 x_('Item3',_'SlotA')
 - 2 x_('Item3',_'SlotB') - x_('Item4',_'SlotC') - 2 x_('Item5',_'SlotC')
 + xstat_StatDark = 0

_C6: - 5 x_('Item1',_'SlotA') - 5 x_('Item1',_'SlotB') - x_('Item2',_'SlotA')
 - x_('Item2',_'SlotB') - 5 x_('Item3',_'SlotA') - 5 x_('Item3',_'SlotB')
 - 6 x_('Item4',_'SlotC') - 5 x_('Item5',_'SlotC') + xstat_StatLight = 0

VARIABLES
0 <= x_('Item1',_'SlotA') <= 1 Integer
0 <= x_('Item1',_'SlotB') <= 1 Integer
0 <= x_('Item2',_'SlotA') <= 1 Integer
0 <= x_('Item2',_'SlotB') <= 1 Integer
0 <= x_('Item3',_'SlotA') <= 1 Integer
0 <= x_('Item3',_'SlotB') <= 1 Integer
0 <= x_('Item4',_'SlotC') <= 1 Integer
0 <= x_('Item5',_'SlotC') <= 1 Integer
xstat_StatDark Continuous
xstat_StatLight Continuous
Status: Optimal
Objective: 8.099999999999998
    item   slot
0  Item2  SlotB
1  Item3  SlotA
2  Item4  SlotC
项目、槽列为我们提供了允许的组合

dict
statv
提供了一种方便的数据结构来访问stat贡献:

{('Item1', 'StatDark'): 3,
 ('Item1', 'StatLight'): 5,
 ('Item2', 'StatDark'): 7,
 ('Item2', 'StatLight'): 1,
 ('Item3', 'StatDark'): 2,
 ('Item3', 'StatLight'): 5,
 ('Item4', 'StatDark'): 1,
 ('Item4', 'StatLight'): 6,
 ('Item5', 'StatDark'): 2,
 ('Item5', 'StatLight'): 5}
生成的MIP模型如下所示:

Item   Slot   Group
-----------------------
Item1   SlotA   Group1
        SlotB   Group1
Item2   SlotA   Group1
        SlotB   Group1
Item3   SlotA   Group1
        SlotB   Group1
Item4   SlotC   Group2
Item5   SlotC   Group2 
assignItemsToSlots:
MAXIMIZE
-0.3*xstat_StatDark + 0.7*xstat_StatLight + 2.6999999999999997
SUBJECT TO
_C1: x_('Item1',_'SlotA') + x_('Item2',_'SlotA') + x_('Item3',_'SlotA') = 1

_C2: x_('Item1',_'SlotB') + x_('Item2',_'SlotB') + x_('Item3',_'SlotB') = 1

_C3: x_('Item4',_'SlotC') + x_('Item5',_'SlotC') = 1

_C4: xstat_StatDark >= 9

_C5: - 3 x_('Item1',_'SlotA') - 3 x_('Item1',_'SlotB')
 - 7 x_('Item2',_'SlotA') - 7 x_('Item2',_'SlotB') - 2 x_('Item3',_'SlotA')
 - 2 x_('Item3',_'SlotB') - x_('Item4',_'SlotC') - 2 x_('Item5',_'SlotC')
 + xstat_StatDark = 0

_C6: - 5 x_('Item1',_'SlotA') - 5 x_('Item1',_'SlotB') - x_('Item2',_'SlotA')
 - x_('Item2',_'SlotB') - 5 x_('Item3',_'SlotA') - 5 x_('Item3',_'SlotB')
 - 6 x_('Item4',_'SlotC') - 5 x_('Item5',_'SlotC') + xstat_StatLight = 0

VARIABLES
0 <= x_('Item1',_'SlotA') <= 1 Integer
0 <= x_('Item1',_'SlotB') <= 1 Integer
0 <= x_('Item2',_'SlotA') <= 1 Integer
0 <= x_('Item2',_'SlotB') <= 1 Integer
0 <= x_('Item3',_'SlotA') <= 1 Integer
0 <= x_('Item3',_'SlotB') <= 1 Integer
0 <= x_('Item4',_'SlotC') <= 1 Integer
0 <= x_('Item5',_'SlotC') <= 1 Integer
xstat_StatDark Continuous
xstat_StatLight Continuous
Status: Optimal
Objective: 8.099999999999998
    item   slot
0  Item2  SlotB
1  Item3  SlotA
2  Item4  SlotC

我不理解这个问题。可能是用一个小数据集和预期的解决方案来演示这个问题。@ErwinKalvelagen用一个简单的例子编辑了这篇文章。希望这能让它现在更容易理解。正如问题描述的那样,似乎对象分组将问题严格地划分为子问题。这准确吗?意思是g:如果你能为N组中的一组制定一个解决方法,你可以对其余组重复这个过程,因为没有“重叠”。这是一个正确的观察结果吗?哇,这太棒了!非常感谢!我仍在努力理解其中一些实际上在做什么,但这是一个很大的帮助!