使用if和for循环优化功能

时间:2019-08-05 04:51:18

标签: python numpy optimization numba

我有两个功能。一个叫另一个。这是运行两个功能的完整代码和数据。

import numpy as np

agents={(-71.60000000000002, 41.1): 1, (-71.40000000000003, 41.90000000000001): 1, (-71.80000000000001, 41.2): 1, (-71.20000000000005, 41.400000000000006): 1, (-71.30000000000004, 41.50000000000001): 1, (-71.70000000000002, 41.70000000000001): 1, (-71.50000000000003, 42.000000000000014): 1, (-71.50000000000003, 41.2): 1, (-71.40000000000003, 42.000000000000014): 1, (-71.20000000000005, 41.60000000000001): 1, (-71.70000000000002, 42.000000000000014): 1, (-71.50000000000003, 41.60000000000001): 1, (-71.40000000000003, 41.50000000000001): 1, (-71.50000000000003, 41.90000000000001): 1, (-71.70000000000002, 41.50000000000001): 1, (-71.40000000000003, 41.80000000000001): 1, (-71.30000000000004, 41.60000000000001): 1, (-71.70000000000002, 41.80000000000001): 2, (-71.60000000000002, 41.60000000000001): 2, (-71.20000000000005, 41.50000000000001): 2, (-71.50000000000003, 41.70000000000001): 2, (-71.40000000000003, 41.400000000000006): 2, (-71.50000000000003, 41.80000000000001): 2, (-71.80000000000001, 41.400000000000006): 2, (-71.30000000000004, 41.400000000000006): 2, (-71.40000000000003, 41.70000000000001): 2, (-71.60000000000002, 41.80000000000001): 2, (-71.70000000000002, 41.90000000000001): 2, (-71.30000000000004, 41.70000000000001): 2, (-71.60000000000002, 41.90000000000001): 2, (-71.60000000000002, 42.000000000000014): 2}
all_houses=[(-71.60000000000002, 41.70000000000001), (-71.70000000000002, 42.000000000000014), (-71.20000000000005, 41.400000000000006), (-71.60000000000002, 41.1), (-71.50000000000003, 41.70000000000001), (-71.50000000000003, 41.90000000000001), (-71.30000000000004, 41.400000000000006), (-71.30000000000004, 41.60000000000001), (-71.40000000000003, 41.90000000000001), (-71.80000000000001, 41.300000000000004), (-71.70000000000002, 41.300000000000004), (-71.60000000000002, 41.2), (-71.30000000000004, 41.70000000000001), (-71.60000000000002, 41.90000000000001), (-71.40000000000003, 41.400000000000006), (-71.60000000000002, 42.000000000000014), (-71.50000000000003, 41.50000000000001), (-71.50000000000003, 42.000000000000014), (-71.70000000000002, 41.90000000000001), (-71.70000000000002, 41.80000000000001), (-71.50000000000003, 41.60000000000001), (-71.40000000000003, 41.50000000000001), (-71.30000000000004, 41.50000000000001), (-71.70000000000002, 41.60000000000001), (-71.9, 41.300000000000004), (-71.50000000000003, 41.400000000000006), (-71.40000000000003, 41.70000000000001), (-71.60000000000002, 41.60000000000001), (-71.50000000000003, 41.80000000000001), (-71.40000000000003, 41.60000000000001), (-71.40000000000003, 41.80000000000001), (-71.80000000000001, 41.400000000000006), (-71.60000000000002, 41.80000000000001), (-71.20000000000005, 41.50000000000001), (-71.60000000000002, 41.400000000000006), (-71.60000000000002, 41.50000000000001), (-71.40000000000003, 42.000000000000014), (-71.50000000000003, 41.2), (-71.80000000000001, 41.2), (-71.70000000000002, 41.400000000000006), (-71.20000000000005, 41.60000000000001), (-71.70000000000002, 41.50000000000001), (-71.70000000000002, 41.70000000000001)]
empty_houses=[(-71.9, 41.300000000000004), (-71.60000000000002, 41.2), (-71.40000000000003, 41.60000000000001), (-71.70000000000002, 41.400000000000006), (-71.80000000000001, 41.400000000000006), (-71.50000000000003, 41.60000000000001), (-71.70000000000002, 41.300000000000004), (-71.20000000000005, 41.50000000000001), (-71.40000000000003, 42.000000000000014), (-71.40000000000003, 41.80000000000001), (-71.50000000000003, 41.50000000000001), (-71.60000000000002, 41.80000000000001)]
agent=[-71.50000000000003, 42.000000000000014]
spacing=0.1
similarity_threshhold=0.21

def is_unsatisfied(x, y,all_houses,agents,spacing,empty_houses):

        """
        Checking if an agent is unsatisfied or satisified at its current
        position.
        """

        race = agents[(x,y)]
        count_similar = 0
        count_different = 0
        min_width=min(np.array(all_houses)[:,0])
        max_width=max(np.array(all_houses)[:,0])
        min_height=min(np.array(all_houses)[:,1])
        max_height=max(np.array(all_houses)[:,1])

        if x > min_width and y > min_height and (x-spacing, y-spacing) not in empty_houses:
            if (x-spacing, y-spacing) in agents:
                if agents[(x-spacing, y-spacing)] == race:
                    count_similar += 1
                else:
                    count_different += 1
            else:
                pass
        if y > min_height and (x,y-spacing) not in empty_houses:
            if (x,y-spacing) in agents:
                if agents[(x,y-spacing)] == race:
                    count_similar += 1
                else:
                    count_different += 1
            else:
                pass
        if x < (max_width-spacing) and y > min_height and (x+spacing,y-spacing) not in empty_houses:
            if (x+spacing,y-spacing) in agents:
                if agents[(x+spacing,y-spacing)] == race:
                    count_similar += 1
                else:
                    count_different += 1
            else:
                pass
        if x > min_width and (x-spacing,y) not in empty_houses:
            if (x-spacing,y) in agents:
                if agents[(x-spacing,y)] == race:
                    count_similar += 1
                else:
                    count_different += 1
            else:
                pass
        if x < (max_width-spacing) and (x+spacing,y) not in empty_houses:
            if (x+spacing,y) in agents:
                if agents[(x+spacing,y)] == race:
                    count_similar += 1
                else:
                    count_different += 1
            else:
                pass
        if x > min_width and y < (max_height-spacing) and (x-spacing,y+spacing) not in empty_houses:
            if (x-spacing,y+spacing) in agents:
                if agents[(x-spacing,y+spacing)] == race:
                    count_similar += 1
                else:
                    count_different += 1  
            else:
                pass
        if x > min_width and y < (max_height-spacing) and (x,y+spacing) not in empty_houses:
            if (x,y+spacing) in agents:
                if agents[(x,y+spacing)] == race:
                    count_similar += 1
                else:
                    count_different += 1
            else:
                pass
        if x < (max_width-spacing) and y < (max_height-spacing) and (x+spacing,y+spacing) not in empty_houses:
            if (x+spacing,y+spacing) in agents:
                if agents[(x+spacing,y+spacing)] == race:
                    count_similar += 1
                else:
                    count_different += 1
            else:
                pass

        if (count_similar+count_different) == 0:
            return False
        else:
            return float(count_similar)/(count_similar+count_different) < similarity_threshhold

def find_unsatisifed(agents,all_houses,spacing,empty_houses):       
    for agent in agents:
        print(is_unsatisfied(agent[0],agent[1],all_houses,agents,spacing,empty_houses))

find_unsatisifed(agents,all_houses,spacing,empty_houses)

我想同时优化find_unsatisfiedis_unsatisfied。函数运行得更快,因为我必须处理变量代理中的至少5000个数据元素以及所有房屋以及empty_houses中的至少400个数据。

is_unsatisfied获取一个业务代表的坐标,并检查网格上围绕它的所有业务代表是否种族相同。 (在这种情况下,竞赛为1或2)。 find_unsatisfied使用代理字典并在每个必要的代理上运行is_unsatisfied函数。

我尝试了numba,但由于这些函数实际上是类中的方法,因此无法正常工作,并通过numba不支持的geopandas库获取其数据。然后,我尝试在类之外创建一个函数并将其传递给我,但由于循环并没有真正运行,因此它实际上无法正常工作。我是这样做的

from numba import jit, autojit, int_, void, float_,bool_

@jit()
def is_unsatisfied_numbized(instance, x, y):

    """
    Checking if an agent is unsatisfied or satisified at its current
    position.
    """

    race = instance.agents[(x,y)]
    count_similar = 0
    count_different = 0
    min_width=min(np.array(instance.all_houses)[:,0])
    max_width=max(np.array(instance.all_houses)[:,0])
    min_height=min(np.array(instance.all_houses)[:,1])
    max_height=max(np.array(instance.all_houses)[:,1])

    if x > min_width and y > min_height and (x-instance.spacing, y-instance.spacing) not in instance.empty_houses:
        if (x-instance.spacing, y-instance.spacing) in instance.agents:
            if instance.agents[(x-instance.spacing, y-instance.spacing)] == race:
                count_similar += 1
            else:
                count_different += 1
        else:
            pass
    if y > min_height and (x,y-instance.spacing) not in instance.empty_houses:
        if (x,y-instance.spacing) in instance.agents:
            if instance.agents[(x,y-instance.spacing)] == race:
                count_similar += 1
            else:
                count_different += 1
        else:
            pass
    if x < (max_width-instance.spacing) and y > min_height and (x+instance.spacing,y-instance.spacing) not in instance.empty_houses:
        if (x+instance.spacing,y-instance.spacing) in instance.agents:
            if instance.agents[(x+instance.spacing,y-instance.spacing)] == race:
                count_similar += 1
            else:
                count_different += 1
        else:
            pass
    if x > min_width and (x-instance.spacing,y) not in instance.empty_houses:
        if (x-instance.spacing,y) in instance.agents:
            if instance.agents[(x-instance.spacing,y)] == race:
                count_similar += 1
            else:
                count_different += 1
        else:
            pass
    if x < (max_width-instance.spacing) and (x+instance.spacing,y) not in instance.empty_houses:
        if (x+instance.spacing,y) in instance.agents:
            if instance.agents[(x+instance.spacing,y)] == race:
                count_similar += 1
            else:
                count_different += 1
        else:
            pass
    if x > min_width and y < (max_height-instance.spacing) and (x-instance.spacing,y+instance.spacing) not in instance.empty_houses:
        if (x-instance.spacing,y+instance.spacing) in instance.agents:
            if instance.agents[(x-instance.spacing,y+instance.spacing)] == race:
                count_similar += 1
            else:
                count_different += 1  
        else:
            pass
    if x > min_width and y < (max_height-instance.spacing) and (x,y+instance.spacing) not in instance.empty_houses:
        if (x,y+instance.spacing) in instance.agents:
            if instance.agents[(x,y+instance.spacing)] == race:
                count_similar += 1
            else:
                count_different += 1
        else:
            pass
    if x < (max_width-instance.spacing) and y < (max_height-instance.spacing) and (x+instance.spacing,y+instance.spacing) not in instance.empty_houses:
        if (x+instance.spacing,y+instance.spacing) in instance.agents:
            if instance.agents[(x+instance.spacing,y+instance.spacing)] == race:
                count_similar += 1
            else:
                count_different += 1
        else:
            pass

    if (count_similar+count_different) == 0:
        return False
    else:
        return float(count_similar)/(count_similar+count_different) < instance.similarity_threshhold

class geo():

  def __init__(self):
        #parameters in here

  def is_unsatisfied(self,x,y):
        is_unsatisfied_numbized(self, x, y)

  def update_normal(self):

        for i in range(100):
            n_changes = 0
            for agent in self.agents:
                if self.is_unsatisfied(agent[0], agent[1]):
                    n_changes += 1
            print(n_changes)
            print(i)
            if n_changes == 0:
                break    

这东西不起作用。

是否有任何想法我在哪里做错了,或者有没有其他建议可以优化没有numba的两个功能。也许使用numpy进行矢量化操作。

1 个答案:

答案 0 :(得分:0)

要在不使用numba的情况下优化功能,可以执行以下操作:

1。防止两次测试相同的条件

不同于您进行检查

If A and B:
    Do X
If A and C: 
    Do Y

,您可以将if语句组合在一起,例如

If A:
    If B: 
        Do X
    If C: 
        Do Y

2。降低条件复杂度。您经常测试

if X not in empty_houses:
   if X in agents:
       Do A 

,您可以将其简化为

targetList = [i for i in agents if i not in empty_houses]
if X in targetList:
    Do A