【问题标题】:How to pack spheres in python?如何在python中打包球体?
【发布时间】:2017-02-19 12:06:47
【问题描述】:

我正在尝试使用 python 在正方形中模拟大小均匀的随机封闭包装球体。 球体不应重叠但我不知道该怎么做

我到目前为止:

代码:

import random, math, pylab

def show_conf(L, sigma, title, fname):
    pylab.axes()
    for [x, y] in L:
        for ix in range(-1, 2):
            for iy in range(-1, 2):
                cir = pylab.Circle((x + ix, y + iy), radius=sigma,  fc='r')
                pylab.gca().add_patch(cir)
    pylab.axis('scaled')
    pylab.xlabel('eixo x')
    pylab.ylabel('eixo y')
    pylab.title(title)
    pylab.axis([0.0, 1.0, 0.0, 1.0])
    pylab.savefig(fname)
    pylab.close()

L = []
N = 8 ** 2

for i in range(N):
    posx = float(random.uniform(0, 1))
    posy = float(random.uniform(0, 1))
    L.append([posx, posy])

print L

N = 8 ** 2
eta = 0.3
sigma = math.sqrt(eta / (N * math.pi))
Q = 20
ltilde = 5*sigma

N_sqrt = int(math.sqrt(N) + 0.5)


titulo1 = '$N=$'+str(N)+', $\eta =$'+str(eta)
nome1 = 'inicial'+'_N_'+str(N) + '_eta_'+str(eta) + '.png'
show_conf(L, sigma, titulo1, nome1)

【问题讨论】:

  • 您应该查看 LIGGGHTS,它旨在准确模拟您的需求

标签: python optimization mathematical-optimization packing


【解决方案1】:

如果您想要更新版本的@leopold.talirz 解决方案,我建议您使用以下解决方案:

from cvxpy import *
import numpy as np
import matplotlib.pyplot as plt
import dccp

n = 10
r = np.linspace(1,5,n)

c = Variable(shape=(n,2))
constr = []
for i in range(n-1):
    for j in range(i+1,n):
        constr.append(norm(c[i,:]-c[j,:])>=r[i]+r[j])
prob = Problem(Minimize(max(max(abs(c),axis=1)+r)), constr)
#prob = Problem(Minimize(max_entries(normInf(c,axis=1)+r)), constr)
prob.solve(method = 'dccp', ccp_times = 1)

l = max(max(abs(c),axis=1)+r).value*2
pi = np.pi
ratio = pi*sum(square(r)).value/square(l).value
print("ratio =", ratio)
print(prob.status)

# plot
plt.figure(figsize=(5,5))
circ = np.linspace(0,2*pi)
x_border = [-l/2, l/2, l/2, -l/2, -l/2]
y_border = [-l/2, -l/2, l/2, l/2, -l/2]
for i in range(n):
    plt.plot(c[i,0].value+r[i]*np.cos(circ),c[i,1].value+r[i]*np.sin(circ),'b')
plt.plot(x_border,y_border,'g')
plt.axes().set_aspect('equal')
plt.xlim([-l/2,l/2])
plt.ylim([-l/2,l/2])
plt.show()

【讨论】:

    【解决方案2】:

    这是一个非常困难的问题(可能np-hard)。应该有很多可用的资源。

    在我介绍一些更通用的方法之前,请查看this wikipedia-site 以了解当前最知名的一些 N(正方形中的 N 个圆圈)的包装模式的概述。

    您很幸运,python 中有一个现有的循环打包实现(启发式!),它在很大程度上基于现代优化理论(difference of convex-functions + Concave-convex-procedure)。

    • 所使用的方法描述为here(学术论文和软件链接;2016 年!)
    • 使用的软件包是here
      • 有一个带有circle_packing.py 的示例目录(与输出一起发布在下面)
    • 以下示例也适用于不同形状的圆

    来自上述软件包的例子(沉新月的例子)

    __author__ = 'Xinyue'
    from cvxpy import *
    import numpy as np
    import matplotlib.pyplot as plt
    import dccp
    
    n = 10
    r = np.linspace(1,5,n)
    
    c = Variable(n,2)
    constr = []
    for i in range(n-1):
        for j in range(i+1,n):
            constr.append(norm(c[i,:]-c[j,:])>=r[i]+r[j])
    prob = Problem(Minimize(max_entries(max_entries(abs(c),axis=1)+r)), constr)
    #prob = Problem(Minimize(max_entries(normInf(c,axis=1)+r)), constr)
    prob.solve(method = 'dccp', ccp_times = 1)
    
    l = max_entries(max_entries(abs(c),axis=1)+r).value*2
    pi = np.pi
    ratio = pi*sum_entries(square(r)).value/square(l).value
    print "ratio =", ratio
    print prob.status
    
    # plot
    plt.figure(figsize=(5,5))
    circ = np.linspace(0,2*pi)
    x_border = [-l/2, l/2, l/2, -l/2, -l/2]
    y_border = [-l/2, -l/2, l/2, l/2, -l/2]
    for i in xrange(n):
        plt.plot(c[i,0].value+r[i]*np.cos(circ),c[i,1].value+r[i]*np.sin(circ),'b')
    plt.plot(x_border,y_border,'g')
    plt.axes().set_aspect('equal')
    plt.xlim([-l/2,l/2])
    plt.ylim([-l/2,l/2])
    plt.show()
    

    输出

    为您的任务修改:大小相等的圆圈

    只需替换:

    r = np.linspace(1,5,n)
    

    与:

    r = [1 for i in range(n)]
    

    输出

    64 个圆圈的有趣示例(这需要一些时间!)

    【讨论】:

    • 您好,当我尝试执行 circle_packing.py 示例时,我收到以下错误:
    • 问题标题是关于'spheres'的,这个例子怎么修改为3维?
    • @RobinDeSchepper 我有同样的问题,它似乎和c = Variable(n,3) 一样简单。当然,您需要调整绘图。
    猜你喜欢
    • 2014-05-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-23
    • 2014-06-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多