2016-06-26 16 views
5

ho bisogno di scegliere a caso un vettore n-dimensionale di lunghezza 1. La mia idea migliore è quella di scegliere un punto casuale nella sfera di normalizzarlo:Computazionalmente selezionando un punto a caso su un Ipersfera

import random 

def point(n): 
    sq = 0 
    v = [] 
    while len(v) < n: 
     x = 1 - 2*random.random() 
     v.append(x) 
     sq = sq + x*x 
     if sq > 1: 
      sq = 0 
      v = [] 
    l = sq**(0.5) 
    return [x/l for x in v] 

L'unico problema è che lo volume of an n-ball diventa più piccolo man mano che la dimensione aumenta, quindi l'uso di una distribuzione uniforme da random.random richiede molto tempo anche per piccoli n come 17. Esiste un modo migliore (più veloce) per ottenere un punto casuale su una n-sfera?

+0

È possibile trovare l'algoritmo [qui] (http://stackoverflow.com/a/34402858/4081336). –

+0

@LeandroCaniglia Bene, quell'algoritmo riguarda solo n = 3 –

+0

A caso, vuoi dire che deve essere distribuito uniformemente? Queste cose si complicano abbastanza facilmente, quindi non scommetterei che ciò che stai facendo ora funzioni in questo senso. – Bakuriu

risposta

5

Secondo Muller, M. E. "A Note on a Method for Generating Points Uniformly on N-Dimensional Spheres" si avrebbe bisogno di creare un vettore di n variabili casuali gaussiana e dividere per la sua lunghezza:

import random 
import math 

def randnsphere(n): 
    v = [random.gauss(0, 1) for i in range(0, n)] 
    inv_len = 1.0/math.sqrt(sum(coord * coord for coord in v)) 
    return [coord * inv_len for coord in v] 

Come affermato da @Bakuriu nei commenti, utilizzando numpy.random in grado di offrire un vantaggio di prestazione quando lavorando con vettori più grandi.

+0

Rispetto per il taglio in uso divisione. – YBerman

+0

@YBerman L'ho appena modificato di nuovo dopo averlo rimosso per l'ottimizzazione prematura percepita;) –

+2

Puoi prendere in considerazione l'uso di 'numpy.random' per gestire questi vettori. Probabilmente è molto efficiente. – Bakuriu