当前位置: 首页 > 面试题库 >

用Python快速计算Pareto前沿

冯野
2023-03-14
问题内容

我在3D空间中有一组点,需要从中找到帕累托边界。执行速度在这里非常重要,随着我添加测试点,时间会很快增加。

点集如下所示:

[[0.3296170319979843, 0.0, 0.44472108843537406], [0.3296170319979843,0.0, 0.44472108843537406], [0.32920760896951373, 0.0, 0.4440408163265306], [0.32920760896951373, 0.0, 0.4440408163265306], [0.33815192743764166, 0.0, 0.44356462585034007]]

现在,我正在使用以下算法:

def dominates(row, candidateRow):
    return sum([row[x] >= candidateRow[x] for x in range(len(row))]) == len(row)

def simple_cull(inputPoints, dominates):
    paretoPoints = set()
    candidateRowNr = 0
    dominatedPoints = set()
    while True:
        candidateRow = inputPoints[candidateRowNr]
        inputPoints.remove(candidateRow)
        rowNr = 0
        nonDominated = True
        while len(inputPoints) != 0 and rowNr < len(inputPoints):
            row = inputPoints[rowNr]
            if dominates(candidateRow, row):
                # If it is worse on all features remove the row from the array
                inputPoints.remove(row)
                dominatedPoints.add(tuple(row))
            elif dominates(row, candidateRow):
                nonDominated = False
                dominatedPoints.add(tuple(candidateRow))
                rowNr += 1
            else:
                rowNr += 1

        if nonDominated:
            # add the non-dominated point to the Pareto frontier
            paretoPoints.add(tuple(candidateRow))

        if len(inputPoints) == 0:
            break
    return paretoPoints, dominatedPoints

在此处找到:http : //code.activestate.com/recipes/578287-multiDimension-pareto-
front/

在一组解决方案中找到一组非主导解决方案的最快方法是什么?或者,简而言之,Python可以比该算法做得更好吗?


问题答案:

如果您担心实际速度,则一定要使用numpy(因为聪明的算法调整可能比使用数组操作获得的收益要小得多)。这是三个都计算相同功能的解决方案。该is_pareto_efficient_dumb解决方案在大多数情况下较慢,但随着成本增加而变得更快,在许多点上,该is_pareto_efficient_simple解决方案都比哑解决方案有效得多,并且最终is_pareto_efficient函数可读性较差,但最快(所以所有这些都是帕累托高效的!)。

import numpy as np


# Very slow for many datapoints.  Fastest for many costs, most readable
def is_pareto_efficient_dumb(costs):
    """
    Find the pareto-efficient points
    :param costs: An (n_points, n_costs) array
    :return: A (n_points, ) boolean array, indicating whether each point is Pareto efficient
    """
    is_efficient = np.ones(costs.shape[0], dtype = bool)
    for i, c in enumerate(costs):
        is_efficient[i] = np.all(np.any(costs[:i]>c, axis=1)) and np.all(np.any(costs[i+1:]>c, axis=1))
    return is_efficient


# Fairly fast for many datapoints, less fast for many costs, somewhat readable
def is_pareto_efficient_simple(costs):
    """
    Find the pareto-efficient points
    :param costs: An (n_points, n_costs) array
    :return: A (n_points, ) boolean array, indicating whether each point is Pareto efficient
    """
    is_efficient = np.ones(costs.shape[0], dtype = bool)
    for i, c in enumerate(costs):
        if is_efficient[i]:
            is_efficient[is_efficient] = np.any(costs[is_efficient]<c, axis=1)  # Keep any point with a lower cost
            is_efficient[i] = True  # And keep self
    return is_efficient


# Faster than is_pareto_efficient_simple, but less readable.
def is_pareto_efficient(costs, return_mask = True):
    """
    Find the pareto-efficient points
    :param costs: An (n_points, n_costs) array
    :param return_mask: True to return a mask
    :return: An array of indices of pareto-efficient points.
        If return_mask is True, this will be an (n_points, ) boolean array
        Otherwise it will be a (n_efficient_points, ) integer array of indices.
    """
    is_efficient = np.arange(costs.shape[0])
    n_points = costs.shape[0]
    next_point_index = 0  # Next index in the is_efficient array to search for
    while next_point_index<len(costs):
        nondominated_point_mask = np.any(costs<costs[next_point_index], axis=1)
        nondominated_point_mask[next_point_index] = True
        is_efficient = is_efficient[nondominated_point_mask]  # Remove dominated points
        costs = costs[nondominated_point_mask]
        next_point_index = np.sum(nondominated_point_mask[:next_point_index])+1
    if return_mask:
        is_efficient_mask = np.zeros(n_points, dtype = bool)
        is_efficient_mask[is_efficient] = True
        return is_efficient_mask
    else:
        return is_efficient

分析测试(使用从正态分布中得出的点):

含10,000个样本,有2个成本:

is_pareto_efficient_dumb: Elapsed time is 1.586s
is_pareto_efficient_simple: Elapsed time is 0.009653s
is_pareto_efficient: Elapsed time is 0.005479s

拥有1,000,000个样本,有2个成本:

is_pareto_efficient_dumb: Really, really, slow
is_pareto_efficient_simple: Elapsed time is 1.174s
is_pareto_efficient: Elapsed time is 0.4033s

使用10,000个样本,需要15个费用:

is_pareto_efficient_dumb: Elapsed time is 4.019s
is_pareto_efficient_simple: Elapsed time is 6.466s
is_pareto_efficient: Elapsed time is 6.41s

请注意,如果您担心效率问题,可以通过预先对数据重新排序来进一步提高2倍左右的速度,请参见此处。



 类似资料:
  • 问题内容: 我正在使用NLTK在语料库中搜索n- gram,但是在某些情况下会花费很长时间。我已经注意到,计算n元语法在其他软件包中并不罕见(显然,Haystack具有某些功能)。如果我放弃NLTK,这是​​否意味着可以以更快的方式在语料库中查找n- gram?如果是这样,我可以使用什么来加快速度? 问题答案: 由于您没有指明是想要单词级还是字符级的n-gram,因此我将假设前者,而不会失去一般性

  • 我对python是全新的,我正在尝试在其中实现quicksort。有人能帮我完成我的代码吗? 我不知道如何连接这三个数组并打印它们。

  • 问题内容: 我正在为大型视频文件创建MD5校验和。我当前正在使用代码: 但这会创建一个内存缓冲区,并且对于大型视频文件而言并不理想。Swift中是否有一种方法可以计算读取文件流的MD5校验和,从而使内存占用量最小? 问题答案: 您可以分块计算MD5校验和,例如在?中有没有一个MD5库不需要同时输入全部内容?。 这是使用Swift的可能实现(现已针对Swift 5更新) 需要自动释放池来释放所返回的

  • 问题内容: 我必须为重复对象的排列评估以下公式 其中和(总共有n个对象,其中r1类似于1种,r2类似于第二种,依此类推,该公式表示此类对象的排列数目)。 我需要一个有效的编码解决方案,因为在Java中使用大整数并不能证明在大情况下是有效的。 提前致谢。 问题答案: 您可以使用 设计来解决您的问题。 请参阅此链接以供参考 要么 像这样 : 资源

  • 主要内容:快速排序算法的实现提到排序算法,多数人最先想到的就是快速排序算法。快速排序算法是在分治算法基础上设计出来的一种排序算法,和其它排序算法相比,快速排序算法具有效率高、耗费资源少、容易实现等优点。 快速排序算法的实现思路是: 从待排序序列中任选一个元素(假设为 pivot)作为中间元素,将所有比 pivot 小的元素移动到它的左边,所有比 pivot 大的元素移动到它的右边; pivot 左右两边的子序列看作是两个待排

  • Python包含的内容很多,加上各种标准库、拓展库,乱花渐欲迷人眼。我一直希望写一个快速的、容易上手的Python教程,而且言语简洁,循序渐进,让没有背景的读者也可以从基础开始学习。我将在每一篇中专注于一个小的概念,希望在闲暇时可以很快读完。 基于 Python 3.5。 小提醒 教程基于Python 2.7,测试环境为Linux。我会提醒Python 3中有变化的地方。 标准库的一些包不适用于W

  • 现在,我在上实现行计数,如下所示 如果数据达到百万,时间计算是很大的。我想要实时计算,但我不想使用Mapreduce 如何快速计算行数。

  • 问题内容: 我只需要一个简单的示例,说明如何轻松地将python图标放置在我的系统托盘上。这意味着:我运行该程序,没有窗口出现,只有一个托盘图标(我有一个png文件)出现在系统托盘中,当我右键单击它时,菜单上会显示一些选项(当我单击时,在一个选项上,将运行一个函数)。那可能吗?我根本不需要任何窗户… 示例/代码片段非常感谢!:D 问题答案: 对于Windows和Gnome 来呀!wxPython是