【问题标题】:Generate random points distributed like cities?生成像城市一样分布的随机点?
【发布时间】:2011-02-18 16:42:42
【问题描述】:

如何生成 1000 个随机点,其分布类似于 例如,城镇和城市俄亥俄州?
恐怕我无法准确定义“像城市一样分布”; 均匀分布的中心+小高斯云 很容易但临时。
补充:必须有一个二维分布族 具有可以变化以匹配给定点集的聚类参数?

【问题讨论】:

    标签: algorithm random cluster-analysis


    【解决方案1】:

    也许你可以看看 Walter Christaller 的 Theory of Central Places。我想某处一定有一些发电机,或者你可以自己做饭。

    【讨论】:

    • 很有趣,谢谢。这导致了“空间统计”和“空间点模式”,其中有很多论文和几本书,但到目前为止还没有入口点/没有代码。
    【解决方案2】:

    从目标区域的水景模型开始(如果是虚构的地方,也可以制作一个模型),然后将河流交汇处、湖岸、湖河交汇处附近的城市聚集在一起。然后制作连接这些主要城市的假想高速公路。现在在这些高速公路上以合理的间距散布一些中间城市,更喜欢在高速公路的交叉点附近。现在在空旷的地方洒一些小镇。

    【讨论】:

      【解决方案3】:

      具有泊松簇大小的高斯簇运行良好。

      问题:生成与给定城市大致相似的随机点,例如在美国。

      子问题:
      a) 用数字行描述集群,这样“集群 A 就像集群 B” 简化为“clusternumbers(A) 就像“clusternumbers(B)”。
      通过下面的 fcluster 运行 N=100 然后 1000 个点,ncluster=25,给出

      N 100 ncluster 25: 22 + 3  r 117
      sizes: av 4     10   9   8   7   6   6   5   5   4   4   4 ...
      radii: av 117  202 198 140 134  64  62  28 197 144 148 132 ...
      
      N 1000 cluster 25: 22 + 3  r 197
      sizes: av 45  144 139 130  85  84  69  63  43  38  33  30  ...
      radii: av 197  213 279 118 146 282 154 245 212 243 226 235 ...
      

      b) 找到具有 2 或 3 个参数的随机生成器的组合 可以变化以生成不同的聚类。
      具有泊松聚类大小的高斯聚类可以很好地匹配城市聚类:

      def randomclusters( N, ncluster=25,  radius=1, box=box ):
          """ -> N 2d points: Gaussian clusters, Poisson cluster sizes """
          pts = []
          lam = eval( str( N // ncluster ))
          clustersize = lambda: np.random.poisson(lam - 1) + 1
              # poisson 2:  14  27  27  18   9   4  %
              # poisson 3:   5  15  22  22  17  10  %
          while len(pts) < N:
              u = uniformrandom2(box)
              csize = clustersize()
              if csize == 1:
                  pts.append( u )
              else:
                  pts.extend( inbox( gauss2( u, radius, csize )))
          return pts[:N]
      
      
          # Utility functions --
      
      import scipy.cluster.hierarchy as hier
      
      def fcluster( pts, ncluster, method="average", criterion="maxclust" ):
          """ -> (pts, Y pdist, Z linkage, T fcluster, clusterlists)
              ncluster = n1 + n2 + ... (including n1 singletons)
              av cluster size = len(pts) / ncluster
          """
              # Clustering is pretty fast:
              # sort pdist, then like Kruskal's MST, O( N^2 ln N )
              # Many metrics and parameters are possible; these satisfice.
          pts = np.asarray(pts)
          Y = scipy.spatial.distance.pdist( pts )  # N*(N-1)/2
          Z = hier.linkage( Y, method )  # N-1, like mst
          T = hier.fcluster( Z, ncluster, criterion=criterion )
          clusters = clusterlists(T)
          return (pts, Y, Z, T, clusters)
      
      def clusterlists(T):
          """ T = hier.fcluster( Z, t ) e.g. [a b a b c a]
              -> [ [0 2 5] [1 3] ] sorted by len, no singletons [4]
          """
          clists = [ [] for j in range( max(T) + 1 )]
          for j, c in enumerate(T):
              clists[c].append( j )
          clists.sort( key=len, reverse=True )
          n1 = np.searchsorted(  map( len, clists )[::-1], 2 )
          return clists[:-n1]
      
      def radius( x ):
          """ rms |x - xmid| """
          return np.sqrt( np.mean( np.var( x, axis=0 )))
              # * 100  # 1 degree lat/long ~ 70 .. 111 km
      

      【讨论】:

        【解决方案4】:

        在 java 中,这是通过 new Random().nextGaussian() 提供的。由于有java源码,大家可以看看:

        synchronized public double nextGaussian() {
            // See Knuth, ACP, Section 3.4.1 Algorithm C.
            if (haveNextNextGaussian) {
                haveNextNextGaussian = false;
                return nextNextGaussian;
            } else {
                double v1, v2, s;
                do {
                    v1 = 2 * nextDouble() - 1; // between -1 and 1
                    v2 = 2 * nextDouble() - 1; // between -1 and 1
                    s = v1 * v1 + v2 * v2;
                } while (s >= 1 || s == 0);
                double multiplier = StrictMath.sqrt(-2 * StrictMath.log(s)/s);
                nextNextGaussian = v2 * multiplier;
                haveNextNextGaussian = true;
                return v1 * multiplier;
            }
        }
        

        使用绘制 30000 栋房屋

        x = r.nextGaussian() * rad/4 + rad;
        y = r.nextGaussian() * rad/4 + rad;
        

        造就了这座美丽的城市:

        【讨论】:

          猜你喜欢
          • 2017-12-28
          • 1970-01-01
          • 2016-03-02
          • 1970-01-01
          • 1970-01-01
          • 2017-02-27
          • 1970-01-01
          • 2020-01-10
          • 2020-12-30
          相关资源
          最近更新 更多