在 Python 2.7x 中声明变量以避免以后出现问题

Declaring variables in Python 2.7x to avoid issues later

我是 Python 的新手,来自 MATLAB,很久以前来自 C。我在 MATLAB 中编写了一个脚本,它模拟河流中的沉积物运输作为马尔可夫过程。该代码将随机直径的圆随机放置在指定尺寸的矩形区域内。圆圈的大小不均匀,是从指定的大小范围内随机抽取的。我不知道我将通过循环放置操作执行多少次,所以我使用 while 循环来完成该过程。为了更加面向社区,我正在将 MATLAB 脚本翻译成 Python。我使用在线工具 OMPC 开始,并一直从自动翻译版本手动完成它(不是很有帮助,这并不奇怪)。为了调试代码,我使用 MATLAB 生成的结果通常 与Python 中的结果进行比较和对比。我似乎很清楚,我声明变量的方式会在脚本中进行计算时引入问题。下面是代码执行的不同实例之间存在一致性问题的两个示例。首先,代码生成了我认为是数组中的数组,因为脚本返回的结果如下所示:

此结果是在 overlap_logix 操作中为以下代码片段生成的:

CenterCoord_Array = np.asarray(CenterCoordinates)
Diameter_Array = np.asarray(Diameter)
dist_check = ((CenterCoord_Array[:,0] - x_Center) ** 2 + (CenterCoord_Array[:,1] - y_Center) ** 2) ** 0.5
radius_check = (Diameter_Array / 2) + radius
radius_check_update = np.reshape(radius_check,(len(radius_check),1))
radius_overlap = (radius_check_update >= dist_check)
    # Now actually check the overalp condition.
    if np.sum([radius_overlap]) == 0:
        # The new circle does not overlap so proceed.
        newCircle_Found = 1
        debug_value = 2
    elif np.sum([radius_overlap]) == 1:
        # The new circle overlaps with one other circle
        overlap = np.arange(0,len(radius_overlap), dtype=int)
        overlap_update = np.reshape(overlap,(len(overlap),1))
        overlap_logix = (radius_overlap == 1)
        idx_true = overlap_update[overlap_logix]
        radius = dist_check(idx_true,1) - (Diameter(idx_true,1) / 2)

针对变量产生了相同 运行 的类似结果:

这是工作 MATLAB 版本的相同代码片段(根据要求):

distcheck = ((Circles.CenterCoordinates(1,:)-x_Center).^2 +  (Circles.CenterCoordinates(2,:)-y_Center).^2).^0.5;
radius_check = (Circles.Diameter ./ 2) + radius;
radius_overlap = (radius_check >= distcheck);
    % Now actually check the overalp condition.
    if sum(radius_overlap) == 0
        % The new circle does not overlap so proceed.
        newCircle_Found = 1;
        debug_value = 2;
    elseif sum(radius_overlap) == 1
        % The new circle overlaps with one other circle
        temp = 1:size(radius_overlap,2);
        idx_true = temp(radius_overlap == 1);
        radius = distcheck(1,idx_true) - (Circles.Diameter(1,idx_true)/2);

在 Python 版本中,我从列表创建了数组,以便更轻松地对内容进行操作(代码片段的前两行)。数组结果中的数组和创建数组以访问数据向我暗示我错误地声明了变量类型,但我不确定。此外,一些变量有一个大小,例如,(2L,)(数字维度将随着圆圈的放置而改变)没有第二个维度。当我尝试在与另一个大小为 (2L,1L) 的数组的操作中使用该数组时,这会产生明显的问题。由于这些问题,我开始重塑数组,然后我停止了,因为我认为这些是 hack,因为我错误地声明了一个或多个变量。其次,对于同样的 运行 我遇到了以下错误:

对于操作:

radius = dist_check(idx_true,1) - (Diameter(idx_true,1) / 2)

出现在上述代码片段的底部。我已将整个脚本发布在下面 link 因为自己执行脚本可能更有用:

https://github.com/smchartrand/MarkovProcess_Bedload

我已将代码设置为 运行,其中包含一些初始参数值,因此无需做出决定;这些参数值在基于 MATLAB 的脚本中产生了预期的结果,绘制时看起来像这样:

因此,我似乎特别对第 151-165 行的操作有疑问,具体取决于测试值 np.sum([radius_overlap]) 我认为这是因为我错误地声明了变量类型,但我真的不确定。我可以自信地说,Python版本和MATLAB版本在while循环的第一步输出和进入while循环第二步的代码行127上是一致的。在代码的这一点之下,上面记录的问题最终导致脚本崩溃。有时脚本执行到 15% 完成,有时它不会执行到 5% - 这是由于圆圈放置的随机性质。我正在 Spyder (Python 2.7) IDE 中准备代码,并将公开共享工作代码作为我研究的一部分。如果能提供任何帮助来识别我在 python 编码实践中的错误和误用,我将不胜感激。

我相信我已经回答了我自己的问题,也许它对以后的人有用。我的主要教学资源可以在以下三个网页找到:

Whosebug Question 176011

SciPy FAQ

SciPy NumPy for Matlab users

第三个网页对来自 MATLAB 的我很有帮助。这是修改后的工作 python 代码片段,它与上面提供的原始片段相关:

dist_check = ((CenterCoordinates[0,:] - x_Center) ** 2 + (CenterCoordinates[1,:] - y_Center) ** 2) ** 0.5
radius_check = (Diameter / 2) + radius
radius_overlap = (radius_check >= dist_check)
# Now actually check the overalp condition.
if np.sum([radius_overlap]) == 0:
    # The new circle does not overlap so proceed.
    newCircle_Found = 1
    debug_value = 2
elif np.sum([radius_overlap]) == 1:
    # The new circle overlaps with one other circle
    overlap = np.arange(0,len(radius_overlap[0]), dtype=int).reshape(1, len(radius_overlap[0]))
    overlap_logix = (radius_overlap == 1)
    idx_true = overlap[overlap_logix]
    radius = dist_check[idx_true] - (Diameter[0,idx_true] / 2)

最后我很清楚,对于这个例子来说,使用 numpy 数组比使用列表来存储填充矩形区域的每次迭代的结果更直接。对于更正后的代码片段,这意味着我初始化了变量:

  • 中心坐标,和
  • 直径

as numpy arrays 而我在发布的问题中将它们初始化为列表。这使得一些数学运算更加直接。我还错误地使用括号 () 索引变量,而不是使用方括号 [] 的正确方法。这是我所做的一个更正示例,它帮助代码按预期执行:

  • 不正确:半径 = dist_check(idx_true,1) - (直径(idx_true,1) / 2)
  • 正确:半径 = dist_check[idx_true] - (直径[0,idx_true] / 2)

此示例还表明我遇到了数组维度问题,我逐个变量更正了这些问题。我仍然不确定我的工作代码是否是最 pythonic 或最有效的随机填充矩形区域的方法,但我已经成功测试了大约 100 次。修改后的工作代码可以在这里下载:

Working Python Script to Randomly Fill Rectangular Area with Circles

这是成功 运行 工作代码的最终结果图:

我的主要经验教训是 (1) numpy 数组对于重复的数值计算更有效,以及 (2) 我创建的数组的维数并不总是我所期望的,在建立时必须小心阵列。感谢那些看过我的问题并要求澄清的人。