1
votes

Tentative de vérification des points à l'intérieur d'un cercle à l'aide de Numpy

Je suis nouveau sur numpy et j'ai été chargé de la situation suivante: j'ai besoin de créer deux tableaux numpy d'entiers aléatoires (entre 0 + 1). Un tableau numpy représente les coordonnées x et l'autre représente les coordonnées y. Je dois ensuite vérifier si les points tombent à l'intérieur d'un cercle de rayon un en utilisant squareroot (x ^ 2 + y ^ 2) Je suis actuellement en train d'essayer de mettre mes tableaux au carré et de les additionner. Ce qui est probablement une tâche très simple ne me donne aucune fin de problème.

import matplotlib.pyplot as plt
import numpy as np

plots = 100

dataOne = np.random.random(size = plots)
dataTwo = np.random.random(size = plots)

circle = plt.Circle((0,0), 1, alpha = 0.1)
plt.gca().add_patch(circle)
plt.xlim(0, 5)
plt.ylim(0, 5)
plt.show()

squareDataOne = dataOne ** 2
squareDataTwo = dataTwo ** 2

if squareDataOne + squareDataTwo < 1:
    print("Now check square-root!")

Je continue de recevoir un message d'erreur: La valeur de vérité d'un tableau avec plus d'un élément est ambiguë. Utilisez a.any () ou a.all (). Quelqu'un pourrait-il expliquer pourquoi Python / Numpy n'aime pas ça? On m'a dit d'essayer d'utiliser une expression booléenne pour découper le tableau. Quelqu'un peut-il fournir des suggestions sur la meilleure façon d'intégrer cela dans mon code donné? Toute suggestion ou astuce pour un débutant est appréciée.


2 commentaires

Double possible de Comment filtrer un tableau numpy en utilisant une condition en python


Quelle sortie recherchez-vous? Les indices des paires (x, y)? Ou êtes-vous censé les tracer?


5 Réponses :


2
votes

squareDataOne ressemble à ceci:

[ True False  True  True  True  True  True  True False False  True False
  True False False  True  True  True  True  True False  True False False
  True  True False  True  True  True  True  True  True  True  True  True
  True  True False False  True False]

squareData2 est similaire. L'expression dans votre instruction if :

squareDataOne + squareDataTwo < 1

produit ce tableau:

[7.43871942e-02 2.73007883e-01 5.23115388e-03 6.57541340e-01
 3.08779564e-01 1.24098667e-02 5.08258990e-01 6.52590269e-01
 8.90656103e-02 3.76389212e-02 2.12513661e-01 2.79683875e-01
 7.76233370e-01 6.48353342e-02 8.01663208e-01 8.69331480e-01
 4.34903542e]

Donc, votre L'instruction if attend une valeur True ou False et obtient ce tableau. Le message d'erreur vous indique que Python ne sait pas comment transformer ce tableau en une seule valeur True ou False .

Je ne sais pas comprenez suffisamment bien la logique de votre code pour savoir ce que vous devez faire pour résoudre ce problème. De toute évidence, vous avez beaucoup de données, et pourtant vous prévoyez de décider d'un événement binaire; si vous devez afficher "Maintenant, vérifiez la racine carrée!" ou non. Je ne sais pas comment vous devriez faire cela.


1 commentaires

j'aime que tu réponds mieux que le mien.



0
votes

Je dois ensuite vérifier si les points se trouvent dans un cercle de rayon un en utilisant squareroot (x ^ 2 + y ^ 2)

Vous pouvez utiliser le filtrage de tableau

pt_norm = (squareDataOne + squareDataTwo)
r_inside_circle = np.sqrt(pt_norm[pt_norm < 1])

Cela donnera vous le rayon de tous les points qui tombent à l'intérieur du cercle dans r_inside_circle . Au fur et à mesure que vous augmentez la valeur plots , vous verrez que (4.0 * len (r_inside_circle)) / len (dataOne) s'approche de PI.


0 commentaires

0
votes

Je pense que vous voulez remplacer ceci:

# Calculate radii
radii = (squareDataOne + squareDataTwo)**0.5

# Create a boolean array (True/False values) for filtering
incircle = radii < 1

# Print the number of points inside the circle (Python 3.6+ for the f-string)
print(f"There are {np.sum(incircle)} points inside the circle")

# Plot the points within the circle
plt.scatter(dataOne[incircle], dataTwo[incircle])

par quelque chose comme:

if squareDataOne + squareDataTwo < 1:
    print("Now check square-root!")

Le dataOne [incircle] et dataTwo [incircle] extraira uniquement ces éléments (c'est-à-dire [x, y] paires de coordonnées) de chaque tableau où la valeur de incircle est True .


1 commentaires

Je vérifie généralement si la magnitude est inférieure au rayon au carré car faire le calcul de la racine carrée sur tous les points coûte beaucoup plus cher que de calculer le carré une fois



0
votes
plots = 100
...
num_inside = np.sum(inside_circle)
# Check if all points are inside.
if num_inside == plots:
    print('All inside.')

# If what you really want to achieve is to estimate the area of one quarter of a circle
# using Monte Carlo Sampling.
print(num_inside / plots)    # Your estimate.
print(np.pi / 4)             # Actual area.

output:
0.79
0.7853981633974483

0 commentaires

0
votes

Voici un exemple d'utilisation du rayon ** 2 et du préfiltrage avec un cadre englobant. Ces optimisations sont utiles pour les grands ensembles.

Le préfiltrage avec un cadre englobant et Radius ** 2 est 10 fois plus rapide. Ce code s'exécute en 0,128 seconde:

import time
import numpy as np

plots = 10000000
radius = 1
center = np.array([0,0])

all_points = np.random.randint(low = -5, high = 5, size = plots*2).reshape(-1, 2)
print('All Points: ' + str(len(all_points)))

start_time = time.time()

in_circle_points = all_points[((all_points[:, 0] - center[0])**2 + (all_points[:, 1] - center[1])**2)**0.5 <= radius ]

print('In Circle: ' + str(len(in_circle_points)))
print('Elapsed time: ' + str(time.time() - start_time) + ' seconds')

Le rayon ** 2 est 4x plus rapide. Ce code s'exécute en 0,349 seconde:

import time
import numpy as np

plots = 10000000
radius = 1
center = np.array([0,0])

all_points = np.random.randint(low = -5, high = 5, size = plots*2).reshape(-1, 2)
print('All Points: ' + str(len(all_points)))

start_time = time.time()

# Use squared to avoid cost of sqrt
radius_squared = radius**2
in_circle_points = all_points[((all_points[:, 0] - center[0])**2 + (all_points[:, 1] - center[1])**2) <= radius_squared ]

print('In Circle: ' + str(len(in_circle_points)))
print('Elapsed time: ' + str(time.time() - start_time) + ' seconds')

Sans aucune optimisation. Ce code s'exécute en 1,185 secondes:

import time
import numpy as np

plots = 10000000
radius = 1
center = np.array([0,0])

all_points = np.random.randint(low = -5, high = 5, size = plots*2).reshape(-1, 2)
print('All Points: ' + str(len(all_points)))

start_time = time.time()

# Limit expensive circle search to only points within box bounding circle
bounding_box_lowerleft = center - np.array([radius, radius])
bounding_box_upperright = center + np.array([radius, radius])
in_box_points = all_points[(all_points[:, 0] < bounding_box_upperright[0]) & (all_points[:,0] > bounding_box_lowerleft[0]) & (all_points[:, 1] < bounding_box_upperright[1]) & (all_points[:,1] > bounding_box_lowerleft[1])]
    
print('In Box: ' + str(len(in_box_points)))

# Use squared to avoid cost of sqrt
radius_squared = radius**2
in_circle_points = in_box_points[((in_box_points[:, 0] - center[0])**2 + (in_box_points[:, 1] - center[1])**2) <= radius_squared ]

print('In Circle: ' + str(len(in_circle_points)))
print('Elapsed time: ' + str(time.time() - start_time) + ' seconds')


0 commentaires