Microsoft 365 Utilisation matrices creuses - VBA

ClémentLu

XLDnaute Nouveau
Bonjour,
Je me permets de vous faire cette demande car cela fait quelques jours que je recherche des solution mais je n'arrive clairement pas à déterminer quelle solution va être optimale à mon problème...
Avant tout, si une réponse à mon problème a déjà été décrite quelque part je m'excuse par avance même s'il me semble avoir déjà fait un bon tour des forums....

Voici donc mon problème:
Je souhaite utiliser un stockage CSR de matrices creuses (stockage de trois vecteurs plutôt que d'une matrice comprenant une majorité de zéro, existant dans la bibliothèque Eigen en C++). Pour cela j'ai actuellement créé un module de classe comprenant ces trois vecteurs comme suit :
VB:
Option Explicit

Private cAA() As Double
Private cJA() As Integer
Private cIA() As Integer

Mon problème actuellement est que je n'arrive pas à redimensionner mes vecteurs donc clairement je n'arrive pas à utiliser ma classe...

J'ai cru voir qu'une utilisation de collection pouvait être une alternative mais j'ai vraiment besoin de fixer un vecteur ne contenant que des réels et les deux suivants ne contenant que des entiers...
Bien évidemment, je ne sais pas à l'avance la taille de mes vecteurs donc j'ai vraiment besoin de pouvoir les redimensionner à souhait...

J'ai aussi vu qu'il était possible de déclarer un type plutôt qu'une classe mais cela m'a l'air bien moins puissant et mes calculs vont vite devenir exigeants donc je ne sais pas si cela serait une bonne solution.

Je pense que je suis arrivé au bout de mes tonnes de questionnements :rolleyes:

Merci d'avance au(x) courageux qui me répondront !
 
Solution
Bonjour.
Ceci n'a pas l'air de poser de problème :
Module de classe nommé CSR :
VB:
Option Explicit
Private cAA() As Double, cJA() As Integer, cIA() As Integer
Public Property Let Dimens(ByVal UB As Long)
   ReDim cAA(1 To UB), cJA(1 To UB), cIA(1 To UB)
   End Property
Public Property Get Dimens() As Long
   Dimens = UBound(cAA)
   End Property
Module standard :
VB:
Option Explicit
Sub Test()
   Dim X As CSR
   Set X = New CSR
   X.Dimens = 10
   MsgBox X.Dimens
   End Sub
Affiche 10
Remarque: Ça ne semble avoir aucun rapport avec ce dont vous dites souhaiter disposer comme type de rangement de données. Cochez la référence Microfoft Scripting Runtime est utilisez des Dictionary plutôt que vos objets de type du nom de la classe.

Dranreb

XLDnaute Barbatruc
Bonjour.
Ceci n'a pas l'air de poser de problème :
Module de classe nommé CSR :
VB:
Option Explicit
Private cAA() As Double, cJA() As Integer, cIA() As Integer
Public Property Let Dimens(ByVal UB As Long)
   ReDim cAA(1 To UB), cJA(1 To UB), cIA(1 To UB)
   End Property
Public Property Get Dimens() As Long
   Dimens = UBound(cAA)
   End Property
Module standard :
VB:
Option Explicit
Sub Test()
   Dim X As CSR
   Set X = New CSR
   X.Dimens = 10
   MsgBox X.Dimens
   End Sub
Affiche 10
Remarque: Ça ne semble avoir aucun rapport avec ce dont vous dites souhaiter disposer comme type de rangement de données. Cochez la référence Microfoft Scripting Runtime est utilisez des Dictionary plutôt que vos objets de type du nom de la classe.
 
Dernière édition:

Dranreb

XLDnaute Barbatruc
Ceci, sans module de classe, semblerait plus en accord avec ce que vous disiez :
VB:
Option Explicit
Sub Test()
   Dim Dic As New Dictionary
   CSR(Dic, 32767, 32767) = 123.45
   MsgBox CSR(Dic, 32767, 32767)
   End Sub
Property Let CSR(ByVal Dic As Dictionary, ByVal X As Integer, ByVal Y As Integer, ByVal Val As Double)
   Dim Clé As Long
   Clé = &H10000 * X + Y
   If Val <> 0 Then
      Dic(Clé) = Val
   ElseIf Dic.Exists(Clé) Then
      Dic.Remove Clé
      End If
   End Property
Property Get CSR(ByVal Dic As Dictionary, ByVal X As Integer, ByVal Y As Integer) As Double
   Dim Clé As Long
   Clé = &H10000 * X + Y
   If Dic.Exists(Clé) Then CSR = Dic(Clé)
   End Property
 

ClémentLu

XLDnaute Nouveau
Merci beaucoup pour votre réponse !

En fait j'essayais d'imposer une taille à mes vecteurs en traitant A.AI en tant que vecteur dans un module classique, ce qui explique que ça ne marchait pas....


J'ai donc bien défini de nouvelles properties afin de pouvoir modifier la taille de chacun de mes vecteurs ainsi que ce leur contenu. Point positif, je peux effectivement maintenant redimensionner mes vecteurs sans soucis !
Point négatif, quand j'essaye de remplir un de mes vecteurs, excel se ferme....
Le premier vecteur que je rempli et qui génère la fermeture est A.AA, et j'ai défini le remplissage comme suit :

VB:
Property Let AA(vec() As Double)
    cAA = vec
End Property

Code qui me semble plutôt classique... J'ai bien vérifié que la dimension de A.AA était la même que celle du vecteur que je compte lui associer...



Pour ce qui est de la deuxième solution que vous me proposez (avec les dictionnaires), je pense ne pas avoir été clair sur mes ambitions pour ce code. En fait l'objectif est de ne pas traiter les termes nuls de ma matrice, je la rempli élément par élément et les classe ensuite (toute cette partie est déjà écrite et fonctionne).
Maintenant, je n'ai absolument aucune connaissance en dictionnaire donc peut-être ai-je mal compris ce que vous m'avez proposé...

Bien cordialement.
 

Dranreb

XLDnaute Barbatruc
Comme vous le voyez dans la Sub Test c'est un moyen d'accéder en lecture ou écriture à une valeur Double indexée par deux indices X et Y compris entre 1 et 32767, sans que les valeur nulles y soient réellement enregistrées.
Il n'est pas nécessaire que les dimensions d'un tableau dynamique soient définies pour lui affecter un autre tableau: ça le redimensionne. Mais j'ai eu la surprise de découvrir il n'y a pas très longtemps qu'une Property Let pour une propriété tableau plante dans une procédure où il est récupéré d'un de ses paramètre. Il vaut mieux une méthode, que j'appelle généralement Init, pour tout initialiser.
 

ClémentLu

XLDnaute Nouveau
Après relecture de votre Sub et quelques recherches sur les dictionnaires, je comprends enfin ce que vous m'avez conseillé !!
Il est vrai que votre technique de stockage est très habile et je n'y aurai sûrement jamais pensé tout seul !
Cependant, j'aimerai pouvoir stocker mes variables dans un ordre bien précis ... Or un dictionnaire, sauf erreur de ma part, n'a pas d'ordre réel... (ou alors est-il classé par ordre de clé ?)
Pour vous donner un ordre de grandeur, mes x et y varient de 0 à au moins 2000.
De plus, je n'ai pas le même nombre de x que de y (même s'il suffit de mettre une condition en fixant l'un d'eux nul quand le dernier terme est passé).

Je pense donc, malgré vos conseiller, garder ma classe ! La méthode init fonctionne bien, il me reste plus qu'à trouver une solution pour bien dimensionner mes tableaux mais je devrais réussir à me débrouiller par moi même maintenant !

Merci mille fois pour toute l'aide que vous m'avez apporté !

Je renverrai un message si jamais je me trouve encore face à un problème que je n'arrive pas à résoudre.
 

ClémentLu

XLDnaute Nouveau
Je fais une étude éléments finis 2D !
J'ai donc une matrice qui, dans l'idéal devrait avoir une taille d'environ 10 000x10 000 avec maximum 5 éléments non nuls par ligne.
J'ai donc fait un premier programme qui faisait mon étude en stockant les matrices entièrement mais je me retrouve vite limité à un petit peu moins de 2 000 mailles (ie matrice 2 000x2 000) avec des temps de calculs longs (plusieurs heures), quand Excel ne plante pas....
Je veux donc gagner de l'espace de stockage à travers le stockage CSR de mes matrices.


Pour information, le stockage CSR revient à stocker dans AA les éléments non nuls de ma matrice dans le sens de lecture, dans JA le numéro de colonne de ces éléments et dans JA le nombre d'éléments non nuls de chaque ligne.
(Ce stockage peut paraitre surprenant dans un premier temps mais il permet d'effectuer des multiplications matrice/vecteur ainsi que matrice/matrice relativement facilement)
 

Dranreb

XLDnaute Barbatruc
Vous devriez joindre un classeur montrant ce que vous avez et ce que vous voulez calculer.
Ce n'est pas clair pour moi qu'il ne faille le numéro de ligne. Est-ce bien ce que vous dites ? Mais il y aura le même nombre d'éléments pour chaque valeur d'un numéro de colonne alors ? Non, ça ne m'est pas clair du tout.
 

ClémentLu

XLDnaute Nouveau
Je vous ai joint un classeur avec la méthode de stockage que j'utilise. Vous verrez que cette fois je stock mes trois vecteurs indépendamment !

Vous verrez qu'il est bien possible de ne pas stocker les numéros de ligne ! Cela permet de gagner en espace de stockage (le dernier vecteur est en général plus petit que les deux autres).
 

Pièces jointes

  • sparse.xlsm
    28 KB · Affichages: 4

Discussions similaires

Statistiques des forums

Discussions
312 100
Messages
2 085 293
Membres
102 853
dernier inscrit
jetstream69