2016-04-22 79 views
1

想象一下,我们有一个具有离散点的3D网格。 3维(包括间隔端点)的范围为:使用嵌套循环的3D网格搜索的Python优化

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分):

找到包含该点的最小长方体。然而,网格中存在漏洞(每个点应该有一个“物理”对应文件,但有些不会)。我尝试以下非常简单的代码(在这里我叫立方体“立方体”):

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个字符不是一种好的方式:)。

回答

0

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

文件名正被用作布尔值,对不对?重要的是该文件是否存在。

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

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

希望这会有所帮助。

+0

确实,不是for循环会减慢程序速度,但if-clause ...停用8-fold if子句,但仍然在20000模型中追加坐标约4秒。我会尝试你的建议,用numpy.zeros((4,3,7))创建数组,并从所有20000个文件中的(84)模型中读取文件名“values”,并将它们转换为数组索引并设置分别。数组值为1. – bproxauf

+0

问题解决了,它是globbing :)问题已被标记为回答...再次感谢 – bproxauf