使用嵌套循环进行3D网格搜索的Python优化

时间:2016-04-22 08:10:08

标签: python for-loop optimization

想象一下,我们有一个带有离散点的3D网格。 3维(包括间隔终点)的范围是:

in x:[4000,7000],步长1000,y:[0.0,2.0],步长1.0,z:[ - 0.75,0.75],步长0.25

现在应该对[4000,7000,100],[0.0,2.0,0.1],[ - 0.75,0.75,0.05]范围内的所有点进行以下任务(大约20000 = 31 * 21 * 31点) ):

找到包含该点的最小立方体。但是网格中有漏洞(每个点应该有一个"物理"对应物作为文件,但有些没有)。我尝试了以下非常简单的代码(我称之为cuboid' cube'):

def findcubesnew(startvalues, endvalues, resols, \
  loopvalues, refvalues, modelpath):

  cubearray = []
  startvalue1 = startvalues[0]
  endvalue1 = endvalues[0]
  resol1 = resols[0]
  refvalue1 = refvalues[0]
  loopstop1 = loopvalues[0][0]
  loopstart1 = loopvalues[1][0]
  startvalue2 = startvalues[1]
  endvalue2 = endvalues[1]
  resol2 = resols[1]
  refvalue2 = refvalues[1]
  loopstop2 = loopvalues[0][1]
  loopstart2 = loopvalues[1][1]
  startvalue3 = startvalues[2]
  endvalue3 = endvalues[2]
  resol3 = resols[2]
  refvalue3 = refvalues[2]
  loopstop3 = loopvalues[0][2]
  loopstart3 = loopvalues[1][2]
  refmass = refvalues[3]
  refveloc = refvalues[4]

  for start1 in numpy.arange(startvalue1, loopstop1 + resol1, resol1):
    for end1 in numpy.arange(loopstart1, endvalue1 + resol1, resol1):
      for start2 in numpy.arange(startvalue2, loopstop2 + resol2, resol2):
        for end2 in numpy.arange(loopstart2, endvalue2 + resol2, resol2):
          for start3 in numpy.arange(startvalue3, loopstop3 + resol3, resol3):
            for end3 in numpy.arange(loopstart3, endvalue3 + resol3, resol3):
              if glob.glob(*start1*start2*start3) and \
                if glob.glob(modelpath/*start1*start2*end3) and \
                if glob.glob(modelpath/*start1*end2*start3) and \
                if glob.glob(modelpath/*start1*end2*end3) and \
                if glob.glob(modelpath/*end1*start2*start3) and \
                if glob.glob(modelpath/*end1*start2*end3) and \
                if glob.glob(modelpath/*end1*end2*start3) and \
                if glob.glob(modelpath/*end1*end2*end3):
                  cubearray.append((start1, end1, start2, end2, start3, end3))
                else:
                  pass
  return cubearray

foundcubearray = findcubesnew([metalstart, tempstart, loggstart], \
  [metalend, tempend, loggend], [metalresol, tempresol, loggresol], \
  looplimitarray, [refmetal, reftemp, reflogg, refmass, refveloc], \
  modelpath)
if foundcubearray:
  bestcube = findsmallestcubenew(foundcubearray, \
    [metalresol, tempresol, loggresol])
  ....

因此,我进入x方向的循环,从下网格边界到我们想要获得长方体的所需点下方的最大值,以及从该点之后的最小值到更高网格边界的另一个循环。类似地,对于y方向和z方向,并且环彼此嵌套。 if部分是没有格式字符串等的伪代码,并检查所有具有这些值的文件(以及其他数量可能在文件名中也是如此)确实存在(存在长方体的所有角落)。

如果点的一个或多个坐标与网格中的值一致,此代码也会找到点或线或矩形,但它不是问题(实际上是期望的)。

这里的瓶颈是寻找长方体需要相当长的时间(最小的长方体可以很容易和快速地找到,如果有多个具有相同(最小)的尺寸,我不在乎选择哪一个)。另外,我需要读入网格的开始和结束值,步长,我的点的参考值(坐标)和一些其他变量。有什么方法可以优化代码?每点大约需要1.4秒,所以~20000点大约需要8小时,这太长了。

我知道如果我找到了最小的长方体,例如对于点4500,0.5,0.1,我可以立即告诉多维数据集内的所有其他点有限制[4000,5000; 0.0,1.0; 0,0.25]具有相同的最小长方体。我仍然对一个优化所有20000次运行的计算时间的解决方案感兴趣。这个应用是恒星模型的插值程序,其中需要在插值点周围具有长方体形状的8个网格点。

P.S。:我希望延续线断裂和缩进是正确的。在我的代码中它们不存在,虽然每行超过80个字符并不是一个好的风格:)。

1 个答案:

答案 0 :(得分:0)

我的建议是不要使用glob。如果我正确读取数字,那么modelpath目录最多可包含20,000个文件,并且内部循环体中可能有8个globs。我很惊讶每点只需要1.4秒!

文件名只是用作布尔值,对吧?重要的是文件是否存在。

我会创建一个与3D网格尺寸相同的布尔三维数组,初始化为False。然后读取目录的内容,将每个文件名转换为3D索引并将其设置为True。

然后使用布尔数组搜索点,而不是文件系统。

希望这有帮助。