2016-02-28 1 views
0

J'essaie d'implémenter une recherche de grille (en Python, si c'est important) sur une sphère dans R^n, où n est inconnue.Recherche de grille sur un cube/sphère dans R^n

L'entrée inclut le rayon et le centre de la sphère, ainsi qu'un hyperparamètre theta, qui contrôle la résolution de la grille. Je voudrais exprimer chaque point dans cette sphère en fonction de ces trois paramètres.

Je suis également prêt à considérer la recherche de cube, en répétant SEULEMENT les faces du cube. (à savoir, itérer le L_inf sphere)

Si je savais que n = 2, ce que je ferais est:

import numpy as np 

def enumerate_2d_sphere(R,theta,center=(0,0)): 
    for n in xrange(int(2*np.pi/theta)+1): 
     degree = n*theta 
     point =(center[0]+R*np.cos(degree),center[1]+R*np.sin(degree)) 
     yield point 

for p in enumerate_2d_sphere(1,0.1): 
    print p 

Depuis n peut être arbitrairement grand, je suis à la recherche d'un moyen de parcourir la sphère \ cube efficacement.

Des idées?

++++++++++++++++++++++++++++++++++++++++++++++ +++++++++++++++

Je fini par utiliser une version modifiée de ce qui a suggéré strubbly:

import itertools 
import numpy as np 
import matplotlib.pyplot as plt 

def f(d, center, scale=1): 
    dim = len(center) 
    print d/-2.0 
    diff = scale * np.array([d/-2.0 for _ in xrange(dim)]) 
    bias = diff + center 
    for i in range(dim): 
     l = ([ xrange(1,d) for _ in xrange(i)] + 
      [[0,d]] + 
      [ xrange(d+1) for _ in xrange(dim-i-1)] 
      ) 
     for r in itertools.product(*l): 
      yield scale*np.array(r)+bias 
#example for R^2: 
center = (1,1.5) 
data = np.array([x for x in f(20,center,scale = 0.1)]) 


plt.scatter(data[:,0], data[:,1],color='r',s=100,alpha=0.5) 
plt.scatter(center[0], center[1],color='b',s=300,alpha=0.5) 
plt.show() 

La figure de sortie:

enter image description here

Une option de plus, est de générer uniformly distributed samples on the sphere. Notez que le nombre d'échantillons contrôle la « densité » (ou densité attendue) des points:

import numpy as np 
def generate_random_points(R,center,quantity=1000): 
    """ 
    :param R: float 
    :param center: np.array 
    :param quantity: int 
    """ 
    dim = len(center) 
    for n in xrange(quantity): 
     s = np.random.normal(0, 1,dim) 
     r = np.sqrt(np.dot(s,s)) 
     s = (R/r) * s 
     yield s+center 

La pire méthode (en termes de simplicité et d'efficacité) serait de générer des points sur la sphère en utilisant enumeration of n-1 angles. Le manque d'efficacité découle du besoin de calculer les produits sin et cos souvent (même si cela peut être piraté aussi)

+1

Pouvez-vous expliquer un peu plus ce que vous voulez? Par exemple, supposons que R = 10, n = 2, c = (0, 0), thêta = 1. Que signifie représenter tous les points de ce disque en fonction de R, c et thêta? –

+0

J'ai ajouté un exemple – omerbp

Répondre

1

Vous pouvez utiliser des coordonnées sphériques en n dimensions (voir par ex. wikipedia) ou vous pouvez utiliser les coordonnées euclidiennes en réglant simplement la dernière coordonnée pour obtenir le rayon correct (plus ou moins). Les deux sont de bons paramétrages et vous donneront tous les points sur la sphère - avec le bon nombre de paramètres à parcourir.

Mais ils ne conduisent pas naturellement à un élément de surface (volume) constant - comme il est facile de le voir en pensant simplement à la sphère 3. Il n'y a pas de solution facile à ce problème.

Je pense qu'une approche possible consisterait à utiliser le paramétrage de la grille dimensionnelle n-1 mais à subdiviser la nième composante en un nombre variable de valeurs en fonction du volume.

Les faces du n-cube sont plus faciles: il suffit de générer les n paires de faces où la nième coordonnée est minimale ou maximale. Ainsi, par exemple, en considérant le n-cube de taille 1 commençant à l'origine:

Définissez la première coordonnée à zéro et énumérer une grille sur le reste. Puis réglez-le à un et recommencez. Puis répétez pour la deuxième coordonnée. Etc.

Voici un moyen simple de le faire en utilisant itertools.product. J'ai mis à l'échelle la boîte en coordonnées entières pour plus de simplicité et d'efficacité: vous devrez redimensionner et déplacer le centre. Donc n est le nombre de dimensions et d le nombre de subdivisions le long de chaque axe.

import itertools 

def f(n,d): 

    for i in range(n): 
     l = ([ range(1,d-1) for _ in range(i)] + 
      [[0,d-1]] + 
      [ range(d) for _ in range(n-i-1)] 
      ) 
     for r in itertools.product(*l): 
      yield r 

print(list(f(4,3))) 
+0

Exemple de ce que je voulais dire par «mise à l'échelle avec la surface et non le volume "- pense à un algorithme qui génère tout point à l'intérieur d'une balle, et jette tous les points qui se trouvent à l'intérieur de la balle. Votre solution peut être implémentée uniquement en utilisant la récursivité, n'est-ce pas? – omerbp

+0

Eh bien, je pense que ce serait facile avec la récursivité mais non, pas nécessaire. Par exemple, vous pouvez utiliser 'itertools.product' ou écrire votre propre équivalent .. – strubbly

+0

Je vais ajouter une version simple du code – strubbly

0

Je ne pense pas que la fonction de recherche de la grille sklearn ait cette option, mais la mise en œuvre manuelle ne devrait pas être difficile

  • itérer sur les valeurs de n
  • pour chaque n, itérer sur n paramètres d'angle différents avec la foulée thêta de 0 à 360
  • si vous wan't le volume de la sphère, itérer également sur le rayon - si vous voulez seulement la surface, gardez le rayon constant
+0

La dimension 'n' est inconnue avant l'exécution, donc il peut y avoir beaucoup plus d'angles que deux ... – omerbp

+1

N'a pas remarqué cela ... est-ce que ça doit être la recherche de grilles, ou est le code manuel aussi très bien? –

+0

Notez qu'en 3D un angle de 0 à 360 tandis que l'autre de 0 à 180, et je ne suis pas sûr de ce qui se passe dans les dimensions «n» ... – omerbp