2014-12-16 27 views
5

Sto provando a generare un codice efficiente per generare un numero di vettori di posizione casuali che poi uso per calcolare una funzione di correlazione della coppia. Mi chiedo se ci sia un modo semplice per impostare un vincolo sulla distanza minima consentita tra due punti posizionati nella mia scatola.Come posso impostare un vincolo di distanza minimo per generare punti con numpy.random.rand?

Il mio codice attualmente è il seguente:

def pointRun(number, dr): 
""" 
Compute the 3D pair correlation function 
for a random distribution of 'number' particles 
placed into a 1.0x1.0x1.0 box. 
""" 
## Create array of distances over which to calculate. 
    r = np.arange(0., 1.0+dr, dr) 

## Generate list of arrays to define the positions of all points, 
## and calculate number density. 
    a = np.random.rand(number, 3) 
    numberDensity = len(a)/1.0**3 

## Find reference points within desired region to avoid edge effects. 
    b = [s for s in a if all(s > 0.4) and all(s < 0.6) ] 

## Compute pairwise correlation for each reference particle 
    dist = scipy.spatial.distance.cdist(a, b, 'euclidean') 
    allDists = dist[(dist < np.sqrt(3))] 

## Create histogram to generate radial distribution function, (RDF) or R(r) 
    Rr, bins = np.histogram(allDists, bins=r, density=False) 

## Make empty containers to hold radii and pair density values. 
    radii = [] 
    rhor = [] 

## Normalize RDF values by distance and shell volume to get pair density. 
    for i in range(len(Rr)): 
     y = (r[i] + r[i+1])/2. 
     radii.append(y) 
     x = np.average(Rr[i])/(4./3.*np.pi*(r[i+1]**3 - r[i]**3)) 
     rhor.append(x) 

## Generate normalized pair density function, by total number density 
    gr = np.divide(rhor, numberDensity) 
    return radii, gr 

ho già provato con un ciclo che calcola le distanze per ogni punto come è stato fatto e quindi accettata o rifiutata. Questo metodo era molto lento se uso molti punti.

+1

Potrebbe essere possibile utilizzare una variante di [questo algoritmo] (http://stackoverflow.com/questions/6002407/placing-random-circles-without-overlap-and-without-using-brute-force/6002708 # 6002708), ma l'avvertenza è che ha una risoluzione minima (e più alto è il più costoso è). – Rufflewind

risposta

1

Come ho capito, stai cercando un algoritmo per creare molti punti casuali in una casella in modo che nessun due punti siano più vicini di una distanza minima. Se questo è il tuo problema, allora puoi sfruttare la fisica statistica e risolverla usando il software di dinamica molecolare. Inoltre, hai bisogno della dinamica molecolare o di Monte Carlo per ottenere la soluzione esatta di questo problema.

Si posizionano N atomi in una scatola rettangolare, si crea un'interazione ripugnante di un raggio fisso tra di essi (come l'interazione Lennard-Jones spostata) e si esegue la simulazione per un po 'di tempo (finché non si vede che i punti si distribuiscono uniformemente in tutto la scatola). Secondo le leggi della fisica statistica è possibile dimostrare che le posizioni dei punti sarebbero al massimo casuali dato il vincolo che i punti non possono essere più vicini di una certa distanza. Questo non sarebbe vero se si utilizza un algoritmo iterativo, come l'immissione punti uno per uno e rifiutando loro se si sovrappongono

vorrei stima un tempo di esecuzione di alcuni secondi per 10000 punti, e diversi minuti per 100k. Io uso OpenMM per tutte le mie simulazioni di dinamiche moelcular.