Erreur d’exécution 7 mémoire insuffisante fichiers lourds
Bonjour,
Pour une application de métrologie, j'ai une série de cordonnées X et Y de 3000 points environ et je souhaite calculer le plus petit cercle circonscrit qui englobe tout les points.
Je sais qu'un cercle est entièrement défini par 3 points donc j'ai réalisé une macro qui calcule tout les cercles possibles, qui sélectionne ceux qui englobent tout les points puis qui affiche le plus petit de tous.
La macro marche nickel pour un nombre de points à 200-300 mais pour plus de points cela ne fonctionne plus j'ai un problème de "mémoire insuffisante".
Bon je comprends bien que le calcul soit pas évident car le système doit calculer les diamètres de tous les trios de points donc une matrice 3000x3000x3000 soit 27 milliards de données.
Avant de revoir entièrement mon code pour qu'il soit (beaucoup) plus rapide et plus léger, je souhaite savoir si quelqu'un parmi vous aurait une solution plus simple permettant de "débloquer" la mémoire ou je ne sais pas quoi..
Merci d'avance.
Lucas
Bonjour,
sans voir ni données ni code, pas facile de proposer quelque chose .
Puisque l'on a les coordonnées de tous les points:
le centre du cercle doit se trouver au milieu de la différence des ordonnées extrêmes et au milieu de la différence des abscisses extrêmes ?
et son rayon la différence la plus grande ?
Merci de ta réponse !
Et non ce n'est pas si simple... (voir photo PJ)
Comme prévu voila la macro et Excel en PJ, je suis pas du tout un pro des macros donc c'est possible que ce ne soit pas bien agencé...
L'énoncé est en réalité à peine plus compliqué que décrit précédemment :
Un scanner prend des valeurs X Y de points sur une longueur de 2 mètres environ, tout les 0,8mm donc environ 2700 valeurs.
L'énoncé précis est de calculer tout les plus petits cercles circonscrits sur des distances de 1000mm et de prendre le plus grand comme résultat final.
En gros trouver le plus petit cercle circonscrit entre les points allant de 0mm à 1000mm, puis de 0,8mm à 1000,8mm puis de 1,6mm à 1001,6mm etc... Et le résultat final correspond au plus grand de tous ces cercles.
Ce qui me bloque dans mon programme c'est la variable "V", qui correspond au nombre de points allant être comparés mutuellement. Le programme tourne actuellement en 1 minute avec V=10 sauf qu'il faut que la valeur de V soit d'environ... 1350.
Voilà voilà je pense que j'ai donné tout les éléments.
Merci beaucoup si tu peux faire quelque chose
Après une lecture rapide :
Peut-être modifier la structure des test avec des goto . mais ce n'est pas ce qui va accélérer le traitement.
Pas compris l'utilité de tableaux à 3 dimensions.
Pour rendre le traitement plus rapide il faudrait passer par un tableau plutôt que de faire de multiples lectures/écritures dans la feuille, et copier le tableau final des résultats dans la feuille en fin de traitement
on peut appliquer ce que j'ai proposé sur un échantillon (de 1350 valeurs). Cet échantillon se déplaçant de 0.8 ( une cellule vers le bas).
A chaque itération les coordonnées du centre et le diamètre sont stockés dans un tableau.
En fin on choisit le plus grand ???
Pour comprendre ce que tu fais, il faut que je me familiarise avec tes index paramétrés.
A+
Merci encore pour ton aide !
Etant donné qu'un cercle est formé par 3 points, et qu'on veut tester tous les trios de points ceci fait bien un tableau à 3 dimensions ?
Ex : Le diamètre du cercle formé par les points 1,4 et 25 sera placé en D[1,4,25], le cercle formé par les points 8,2 et 26 en D[8,2,26], son abscisse en X[8,2,26] etc...
Oui c'est vrai que c'est une bonne idée d'éviter de réécrire dans le tableau. Mais je me suis pas trop penché sur la question du temps d'écriture, disons qu'une fois que le problème de mémoire sera résolu je pourrai m'attaquer à l'optimisation du temps
Quand tu dis "ce que j'ai proposé" tu parles de ton message précédent avec les coordonnées des points aux abscisses et ordonnées extrêmes ? Si oui ce n'est pas toujours vrai, le cercle n'est pas toujours formé par les points extrêmes par rapport à l'origine. Regarde l'image dans mon message précédent
Moi j'ai utilisé cette méthode :
Et ceci fonctionne pour une quantité de points à comparer assez faible.
Merci pour ton aide en tous cas j'espère qu'on ne va pas tarder à aboutir à une solution.
Un premier jet, qui ne prend pas tout en compte:
Sub Cercles()
Dim DL As Long, Plage As Range, T, DerIt As Long, V As Integer, TF()
Dim OK As Boolean, x As Long, D1 As Integer, D2 As Integer, D As Integer
Dim MinX As Integer, MinY As Integer, MaxX As Integer, MaxY As Integer
V = 1350 'nombre de valeurs dans l'échantillon
T = Range("C5:E" & Range("C" & Rows.Count).End(xlUp).Row) ' tableau des données
DerIt = UBound(T, 1) - 1350 'détermine la dernière itération
For i = 1 To DerIt
MinX = 10000: MinY = 10000: MaxX = -10000: MaxY = -10000
For j = 0 To V - 1
If Not IsError(T(i + j, 2)) And Not IsError(T(i + j, 3)) Then
If T(i + j, 2) > MaxX Then MaxX = T(i + j, 2)
If T(i + j, 3) > MaxY Then MaxY = T(i + j, 3)
If T(i + j, 2) < MinX Then MinX = T(i + j, 2)
If T(i + j, 3) < MinY Then MinY = T(i + j, 3)
End If
Next
x = x + 1 'augmentation taille du tableau final
ReDim Preserve TF(1 To 5, 1 To x)
D1 = MaxX - MinX
D2 = MaxY - MinY
If D1 > D2 Then
D = D1
Else
D = D2
End If
TF(1, x) = i
TF(2, x) = (MaxX + MinX) / 2
TF(3, x) = (MaxY + MinY) / 2
TF(4, x) = D
Next
Range("G5").Resize(UBound(TF, 2), UBound(TF, 1)) = Application.Transpose(TF)
End SubEdit :pas vu le message précédent avant d'envoyer celui ci
le cercle n'est pas toujours formé par les points extrêmes par rapport à l'origine
et mon code va donc à la poubelle !
Bonjour,
Pour mois un tableau à 2 dimensions semble suffisant : (3000 lignes et 9 colonnes) pour appliquer les calculs du tableau de ton pdf.
Si on pouvait disposer de toute la série de points...
Après quand on dispose de ce tableau complet pour trouver le plus petit cercle, je ne suis sur de rien, mais ça ne me parait pas infaisable...
En tout cas 3 dimensions me parait injustifié.
A+
Merci encore !
Mais tu utilises la méthode que tu as décris avant pour ton algorithme ?
Moi j'ai utilisé la méthode "essai-erreur" sur wikipedia, ils disent que la méthode est "peu performante"... C'est peut être pour ça que ça ne marche pas...
Je risque de devoir tout recommencer
Bonjour à tous,
Oulalaaa, ça me parait bien compliqué tout ça.
Pas besoin de calculer tous les cercles.
Calcul le barycentre de tous tes points, ça sera le centre de ton cercle circonscrit.
Sur le plan c'est simple. X= (moyenne des x), Y = (moyenne des y)
Et pour avoir son rayon tu calcules sa distance à tous les points et tu prends le maxi.
Distance de 2 points : =RACINE((x2-X)^2+(y2-Y)^2)
eric
Edit : enfin je pense...
Merci pour vos réponses !
@galopin01 toute la série de points et disponible dans le fichier .xlsm de mon deuxième message.
@eriiic Et non ce n'est pas si simple.. (voir PJ).
Sur Wikipédia, il y a clairement marqué que la méthode pour calculer tout les cercles (celle que j'ai fais) est la plus simple à programmer mais la moins performante.
On ne peux pas "débloquer la mémoire" ? Si je l’exécute sur un PC plus puissant il y a des chances que cela fonctionne et que j'ai pas "erreur mémoire insuffisante"?
Lucas
Effectivement, c'était un mauvais souvenir. Valable uniquement pour 3 points (triangle)
Il te faut la valeur exacte ou une approchée suffit ?
C'est pour une application de métrologie donc il faut la valeur exacte.
Si l'on fait une estimation/une valeur approchée, on risque de rejeter un certain nombre de pièces conformes et de valider un certains nombre de pièces non conformes.
La machine (qui est un prototype) envoie des coordonnées de points de manière très précise, ce serait dommage de perdre toute cette précision à cause d'un mauvais programme qui donne une valeur "approchée" du résultat..
La valeur exacte peut faire plusieurs milliers de décimales
Si une valeur approchée à 5-6 décimales te suffit tu peux voir avec le solveur.
Tu peux changer la convergence dans les options
Tu peux aussi tester le modèle évolutionnaire mais c'est plus long. Le GRC a l'air de bien convenir.
Test avec 129 points
eric
Bonjour,
J'ai discuté de ce problème toute la matinée avec un expert, on a revu l'ensemble de vos messages et ce que proposait @eriic mais il semblerait que la mémoire soit largement dépassée et qu'une optimisation du calcul ne suffira pas à régler le problème.
Il faut changer de méthode pour que le système ai moins de données à stocker et à traiter. Je pense que je vais me pencher sur l'algorythme de crystal avec la marche de jarvis pour déterminer l'enveloppe convexe.
De cette manière j'ai uniquement les points de l'enveloppe convexe à considérer (reste encore à déterminer l'enveloppe convexe).
Merci à tous pour votre aide !
On pourrait diminuer le nombre d'itérations (et ainsi la mémoire utilisée ?) dans la détermination des points d'un cercle.
avec
For A = 4 + T To 4 + T + V
For B = 4 + T To 4 + T + V
For C = 4 + T To 4 + T + V
If A = B Or B = C Or C = A Thenon va déterminer toutes les permutations possibles, donc on traitera, par exemple, Point 1-point 2-Point3, mais aussi Point 1-point 3-Point2, et Point 3-point 2-Point1, ....
Il suffit d'avoir 1 fois ces 3 point qu'importe l'ordre où on les trouve pour déterminer le cercle.
Avec
For A = 4 + T To 4 + T + V
For B =A + 1 To 4 + T + V
For C =B + 1 To 4 + T + Von élimine ces redondances.
Est ce que ça ça sera suffisant ?
Bien vu @Algoplus ! Cela donne les mêmes résultats et à divisé mon temps de calcul par 2
Cependant cela ne règle pas le problème de quantité de données