如何确定最佳订单以最大化影响

时间:2017-09-26 17:30:39

标签: python excel algorithm python-3.x solver

免责声明:此问题与算法问题相关,而不是纯Python编码(或Excel解算器)问题

我们目前正在将600多个网站迁移到新平台。部分工作是将组件代码(30+)移植到新平台。 为了解决这个问题,我们已经清点了每个站点上每个组件的用法:

Summary of components usage per site

现在,我们应该找到以哪种顺序移植组件。 基本规则如下:只要移植给定网站使用的所有组件,就可以迁移网站。

目标是尽可能最大限度地增加我们可以迁移的网站数量。

在我的例子中:

  • 如果我们从移植Comp开始。 B,即使Comp,我们也无法迁移网站。 B被大量使用。因此我不会从Comp开始。乙
  • 如果我们从移植Comp开始。 A,我们将能够迁移Site 2并继续使用其他站点。因此,Comp。 A可能是一个很好的候选人
  • 然后,我们可以转到Comp。 C,Comp。 D,最后是Comp。乙

这对于4个组件和5个站点来说相当容易,但对于我们必须处理的金额而言,这是一个真正的噩梦。

什么是系统方法?

3 个答案:

答案 0 :(得分:2)

虽然这是NP难的(请参阅此question for a proof),但只有30个组件,您应该能够通过使用the Held-Karp algorithm的变体来解决所有组合问题,以解决旅行商问题。

主要思想是计算分数,而不是针对每个排列(因为排列太多),而是针对您构建的每个组件的每一组。

将会有2 ^ N套,比N小得多!排列。

要计算每个集合S的分数,您将迭代选择最后一个组件x,并将所有包含x(以及S中的其他组件)的所有网站的分数添加到之前计算的分数中较小的集合Sx。对于每个集合,您可以存储可用的最佳分数,以及最后应添加的组件。

当您计算出添加所有组件的分数时,您可以追溯存储的信息以计算添加组件的顺序。

答案 1 :(得分:1)

我会将您拥有的组件数量概括为N(“N”个组件)。由于组件重构的顺序会影响在该时间实例中可以部署的站点数量,因此这将成为排列的最大化。

  

一组N尺寸的排列量为N!factorial(N)

如果您有4个组件,则组件重构的顺序将有24个不同的排列。从那里,您可以计算每个排列顺序可以迁移的可能站点的数量。

您决定哪个是“最佳”结果。通过选择使用第一个组件重构或组件重构总和产生最多迁移的结果来最大化它。它完全依赖于您的业务逻辑。

答案 2 :(得分:0)

两种算法:

第一个您在示例中主要描述的那个。这样可以提高效率,并以最快的速度完成所有站点的迁移,但可能不是预先提供更多站点的站点

  • 按照使用它们的网站数量排列所有组件(ComponentSiteUsageCount)。
  • 计划组件按ComponentSiteUsageCount的降序进行迁移。
  • 为每个组件迁移交付(CompomentMigrationDate)
  • 指定日期
  • 为每个组件提供数据后,请计划网站迁移。迁移所有组件后,可以迁移站点:

    - 对于每个站点,从最后一个ComponentMigrationDate开始,按ComponentMigrationDate迭代所有组件。在迭代时,检查站点是否具有该组件,站点的第一个组件是SiteMigrationDate。

第二个可能会生成更多迁移得更快的网站

  • 生成所有组件的列表。对于列表中的每个组件,生成仅对此组件具有剩余依赖关系的站点计数(SitesPendingOn)。拿一个最多的,并为其分配一个MigrationOrder(升序号码)。如果列表中没有此类组件,则为每个剩余的(未分配的迁移顺序)生成站点使用计数:ComponentSiteUsageCount。拿一个最多的,并为其分配下一个MigrationOrder。在未分配MigrationOrder的组件上重复循环以获取SitesPendingOn,直到所有组件都分配了MigrationOrder

  • 对于每个站点,从最后一个ComponentMigrationDate开始,按ComponentMigrationDate迭代所有组件。在迭代时,检查站点是否具有该组件,站点的第一个组件是SiteMigrationDate。

第二算法代码 '

import pandas as pd

def get_pending_sites(site_components, component, components):
    count = 0
    for index, site in site_components.iterrows():
        #print('site ...', site['Site'])
        if site[component] > 0. and components[component][0] == 0:
            #print('site uses component')
            other_dependent = False
            for site_component in list(site_components.columns.values)[1:]:
                if site_component != component:
                    if site[site_component] > 0. and components[site_component][0] == 0:
                        #print('site uses other components')
                        other_dependent = True
                        break
            if other_dependent == False:
                count += 1
    #print('count', count)
    return count                

def get_used_sites(site_components, component):
    count = len(site_components[site_components[component] > 0.])
    print ("Component: ", component, " used in sites: ", count)
    return count

def get_most_pending_sites(components):
    most_count = 0
    most_component = None
    for component in components:
        if components[component][0] == 0:
            count = components[component][1]
            if count > most_count:
                most_component = component
                most_count = count
            elif (count == most_count) and (most_component != None):
                if components[component][2] > components[most_component][2] :
                    most_component = component
    return most_component

def get_most_used_sites(components):
    most_count = 0
    most_component = None
    for component in components:
        if components[component][0] == 0:
            count = components[component][2]
            if count > most_count:
                most_component = component
                most_count = count
    return most_component

migration_order = 1
site_components = pd.read_csv('site_components.csv')
#print(site_components.describe())

components = dict.fromkeys(list(site_components.columns.values)[1:])
for component in components:
    components[component] = [0, 0, 0]
    components[component][2] = get_used_sites(site_components, component)

#print(components)

while True:
    print("Components: ", components)
    for component in components:
        if components[component][0] == 0:
            print('starting .....', component)
            components[component][1] = get_pending_sites(site_components, component, components)
            print('finished .....', component, components[component][1], components[component][2])


    while True:
        most_pending_sites_component = get_most_pending_sites(components)
        print('most pending sites components: ', most_pending_sites_component)
        if most_pending_sites_component != None:
            components[most_pending_sites_component][0] = migration_order
            migration_order = migration_order + 1
        else:
            break

    most_used_sites_component = get_most_used_sites(components)
    if most_used_sites_component != None:
        components[most_used_sites_component][0] = migration_order
        migration_order = migration_order + 1
    else:
        break

# order of migration in [0]
print("Components: ", components)

假设:迁移组件所需的时间在所有组件中是统一的 注意:将包含网站和组件的电子表格另存为csv,并删除所有垂直和水平的总计