【问题标题】:Vectorizing complex assignment logic in numpy在 numpy 中向量化复杂的赋值逻辑
【发布时间】:2015-10-14 16:28:17
【问题描述】:

我在模拟中有一些复杂的分配逻辑,我想针对性能进行优化。当前的逻辑被实现为一组嵌套在各种 numpy 数组上的 for 循环。我想对这个赋值逻辑进行矢量化,但不知道这是否可行

import numpy as np
from itertools import izip

def reverse_enumerate(l):
    return izip(xrange(len(l)-1, -1, -1), reversed(l))

materials = np.array([[1, 0, 1, 1],
                     [1, 1, 0, 0],
                     [0, 1, 1, 1],
                     [1, 0, 0, 1]])

vectors = np.array([[1, 1, 0, 0],
                   [0, 0, 1, 1]])

prices = np.array([10, 20, 30, 40])
demands = np.array([1, 1, 1, 1])

supply_by_vector = np.zeros(len(vectors)).astype(int)

#go through each material and assign it to the first vector that the material covers
for m_indx, material in enumerate(materials):
    #find the first vector where the material covers the SKU
    for v_indx, vector in enumerate(vectors):
        if (vector <= material).all():
            supply_by_vector[v_indx] = supply_by_vector[v_indx] + 1
            break

original_supply_by_vector = np.copy(supply_by_vector)
profit_by_vector = np.zeros(len(vectors))
remaining_ask_by_sku = np.copy(demands)

#calculate profit by assigning material from vectors to SKUs to satisfy demand
#go through vectors in reverse order (so lowest priority vectors are used up first)
profit = 0.0
for v_indx, vector in reverse_enumerate(vectors):
    for sku_indx, price in enumerate(prices):
        available = supply_by_vector[v_indx]
        if available == 0:
            continue

        ask = remaining_ask_by_sku[sku_indx]
        if ask <= 0:
            continue

        if vector[sku_indx]:
            assign = ask if available > ask else available
            remaining_ask_by_sku[sku_indx] = remaining_ask_by_sku[sku_indx] - assign
            supply_by_vector[v_indx] = supply_by_vector[v_indx] - assign

            profit_by_vector[v_indx] = profit_by_vector[v_indx] + assign*price
            profit = profit + assign * price

print 'total profit:', profit
print 'unfulfilled demand:', remaining_ask_by_sku
print 'original supply:', original_supply_by_vector

结果:

total profit: 80.0
unfulfilled demand: [0 1 0 0]
original supply: [1 2]

【问题讨论】:

  • 滚动代码块会阻碍普通读者。

标签: python numpy vectorization


【解决方案1】:

似乎嵌套循环的第二部分/组中最内层嵌套循环内的迭代之间存在依赖关系,对我来说,即使不是不可能矢量化,这似乎也很困难。所以,这篇文章基本上是一个部分解决方案,试图向量化第一组两个嵌套循环,它们是 -

supply_by_vector = np.zeros(len(vectors)).astype(int)
for m_indx, material in enumerate(materials):
    #find the first vector where the material covers the SKU
    for v_indx, vector in enumerate(vectors):
        if (vector <= material).all():
            supply_by_vector[v_indx] = supply_by_vector[v_indx] + 1
            break

整个部分可以用一行矢量化代码替换,就像这样 -

supply_by_vector = ((vectors[:,None] <= materials).all(2)).sum(1)

【讨论】:

    猜你喜欢
    • 2018-12-08
    • 1970-01-01
    • 1970-01-01
    • 2010-12-22
    • 2021-06-20
    • 1970-01-01
    • 1970-01-01
    • 2022-01-03
    • 1970-01-01
    相关资源
    最近更新 更多