在 python 中:缺少随机性(分数布朗运动)

In python: missing randomness (fractional Brownian motion)

我是 Python 的新手。我有两个脚本用于生成和绘制 2D 晶格,其值以分形图像的形式表示空间分布的属性。第一个脚本包含生成分形的函数(正统名称:具有傅里叶逆变换的光谱合成),而第二个脚本只是调用函数,绘图它,广告将其写入 .csv 文件。 函数依赖多次random.gauss(0.0, sigma)调用来获得正态分布的随机数。它还调用 random.random() 因为它需要其他随机数。 下面是代码感谢任何愿意提供帮助的人!

问题:情节总是显示相同的模式,因此让我觉得代码中有些东西不是随机的。我的意图是每次 运行 代码时都获得不同的分形图像。是什么让它不是随机的?是第二个脚本中的 seed=122 吗? PS:请注意,由于该过程引入了给定程度的周期性,并且由于我不希望显示该周期性,因此绘制的点阵小于生成的点阵.特别是,我使用 size(plotted)=101x101,而 size(generated)=256x256.

第一个脚本:函数本身

from __future__ import division #Avoids the floor of the mathematical result of division if the args are ints or longs
import numpy
import random
import math
import pylab

def SpectralSynthesisFM2D(max_level, sigma, H, seed=0, normalise=True, bounds=[0,1]):
  """
  ________________________________________________________________________
  Args:
      max_level : Maximum number of recursions (N = 2^max_level)
      sigma     : Initial standard deviation
      H         : Roughness constant (Hurst exponent), varies form 0.0 to 1.0
      H=0.8 is a good representation of many natural phenomena (Voss, 1985)
      seed      : seed value for random number generator
      normalise : normalizes the data using bound
      bounds    : used for normalization of the grid data
  Result:     
      Output is given in the form of an array (grid) which holds surface
      values for a square region.  
  _________________________________________________________________________
  """   

  N = int(2**max_level)
  A = numpy.zeros((N,N), dtype = complex)
  random.seed() #Seeds the random number generator
  PI = 3.141592
  for i in range(0,int((N-1)/2)):
    for j in range(0,int((N-1)/2)):
      phase = 2*PI*random.random() #/random.randrange(1,Arand)
      if i != 0 or j != 0:
        rad = pow((i*i + j*j),(-(H+1)/2) )*random.gauss(0.0, sigma)
      else:
        rad = 0.0

      A[i][j] = rad*math.cos(phase) + rad*math.sin(phase)*j 

      if i ==0: 
        i0 = 0
      else:
        i0 = N - i

      if j==0:
        j0 = 0
      else:
        j0 = N - j

      A[i0][j0] = rad * math.cos(phase) - rad*math.sin(phase)*j

  for i in range(1,int((N-1)/2)):
    for j in range(1,int((N-1)/2)):
      phase = 2*PI*random.random() #/random.randrange(1,Arand)
      rad = pow((i*i + j*j),(-(H+1)/2) )*random.gauss(0.0, sigma)
      A[i][N-j] = rad * math.cos(phase) + rad* math.sin(phase)*j
      A[N-i][j] = rad * math.cos(phase) - rad* math.sin(phase)*j

  Grid = numpy.real(pylab.ifft2(( A ))) #Implements the Discrete Inverse Fast Fourier Transform on a 2D lattice (grid)
  if(normalise):
        Grid += numpy.amin(Grid)*-1 + bounds[0]
        Grid = (Grid/numpy.amax(Grid)) * bounds[1]
  return Grid

第二个脚本:绘制函数并获取分形图像:

from __future__ import division #Avoids the floor of the mathematical result of division if the args are ints or longs
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.colors as mc
import SSFM2D 


#Parameter assignments
max_level=8               #This is the exponent controlling the grid size. In this case N=2^8=256. Use only integers.
N=2**max_level
sigma=1                   #Variation for random Gauss generation (standardised normal distribution)
H=0.8                     #Hurst exponent (0.8 is a recommended value for natural phenomena)
seed=122                    #Setting the seed for random Gauss generation
print ('The lattice size is '+str(N)+'x'+str(N))


#Lattice initialization
Lattice=np.zeros((256,256))


#Calling Spectral fBm function
Lattice=SSFM2D.SpectralSynthesisFM2D(max_level, sigma, H, seed, normalise=True, bounds=[0,1])


#Plotting the lattice
M=np.zeros((101,101))     #Lattice to be plotted. Size(M) != size(Lattice) to minimize visual fBm periodic features. 
for i in range(0,101):
    for j in range(0,101):
        M[i][j]=Lattice[i][j]


#Lattice statistics              
print M[-101:,-101:].sum()
print M[-101:,-101:].max()
print M[-101:,-101:].min()
print M[-101:,-101:].mean()        


#Writing X, Y and values to a .csv file from scratch
import numpy
import csv
with open('C:\Users\Francesco\Desktop\Python_files\csv\fBm_256x256.csv', 'w') as f: # Change directory if necessary
    writer = csv.writer(f)
    writer.writerow(['X', 'Y', 'Value'])
    for (x, y), val in numpy.ndenumerate(M):
        writer.writerow([x, y, val])

# Plotting - Showing interpolation of randomization
plt.imshow(M[-101:,-101:].T, origin='lower',interpolation='nearest',cmap='Blues', norm=mc.Normalize(vmin=0,vmax=M.max()))
title_string=('fBm: Inverse FFT on Spectral Synthesis')
subtitle_string=('Lattice size: 101x101')
plt.suptitle(title_string, y=0.99, fontsize=17)
plt.title(subtitle_string, fontsize=9)
plt.show()

# Makes a custom list of tick mark intervals for colour bar (assumes minimum is always zero)
numberOfTicks = 5
ticksListIncrement = M.max()/(numberOfTicks)
ticksList = []
for i in range((numberOfTicks+1)):
    ticksList.append(ticksListIncrement * i) 

cb=plt.colorbar(orientation='horizontal', format='%0.2f', ticks=ticksList) 
cb.set_label('Values') 
plt.show()
plt.xlim(0, 100)
plt.xlabel('Easting (Cells)') 
plt.ylim(100, 0)
plt.ylabel('Northing (Cells)')

通常一个seed用于初始化一个随机数生成器。 same seed -> 相同的随机数序列(这对测试非常有用)。

import random

random.seed(22)

for i in range(10):
    print(random.randint(0, 100))

所以无论你运行那个程序多少次(甚至在什么机器上),输出总是一样的。

但是当你想要 'real' 随机性(或至少更好的随机性)时,你最好调用

random.seed()  # or: random.seed(None)

没有参数。 python 然后使用当前系统时间调用 seed - 这提供了一些随机性的来源。

因为我不知道你的图书馆,所以我不能确定,但​​我敢打赌它以类似的方式工作。您可以尝试设置 seed=Noneseed=random.randint(something).

无论如何:一定要阅读你的库的 api 文档并检查 seed 做了什么。