在numpy中矢量化复杂的赋值逻辑

时间:2015-10-14 16:28:17

标签: python numpy vectorization

我在模拟中有一些复杂的分配逻辑,我想优化性能。当前逻辑在一系列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]

1 个答案:

答案 0 :(得分:0)

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

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)