2013-06-04 3 views
0

Je suis confronté à un problème concernant la façon de stocker le facteur triangulaire inférieur d'une matrice symétrique donnée (c'est une matrice de distance) dans un vecteur.vectorisation symétrique de la moitié de la matrice

Généralement, je voudrais générer directement les entrées triangulaires inférieures en donnant seulement les coordonnées (Y,Z) d'un ensemble de points sur une grille rectangulaire: et en fait c'est là que je me suis terriblement coincé. J'ai donc commencé à penser à attaquer le problème d'un point de vue légèrement différent: générer la matrice de distance complète (encore une fois donné les couples (Y,Z)) puis vectoriser à moitié la matrice de distance.

Néanmoins, je n'ai pas vraiment une bonne idée sur la façon d'atteindre l'objectif au moyen de for boucles.

D'ailleurs, je sais aussi qu'il peut y avoir une bibliothèque Java externe qui implémente la fonction vech: vech renvoie le vecteur obtenu en éliminant tous les éléments supradiagonal de la matrice carrée X et empiler le résultat d'une colonne au-dessus de l'autre. Cela a été utilisé dans le calcul matriciel où la matrice sous-jacente est symétrique et il serait inutile de garder les valeurs au-dessus de la diagonale principale.

Substantiellement, étant donné une matrice A = {{a,c},{b,d}}, en appliquant vech(A), le résultat sera vech(A) = {a,b,d}.

EDIT

je veux dire quelque chose comme ce qui suit:

a11 a12 a13 a14 
     a22 a23 a24 
A=   a33 a34 (aij = aji) 
       a44 

stockage Emballé du triangle supérieur de A:

AP = { a11, a12, a22, a13, a23, a33, a14, a24, a34, a44 } 
+3

Pour votre dernière phrase; Qu'avez-vous essayé jusqu'à présent? –

+0

@OliCharlesworth: J'ai essayé plusieurs pour les boucles, mais sans succès, je vais éditer ma question, y compris mon essai. – fpe

+0

Je suggère d'échanger votre question - Demandez d'abord comment faire en utilisant des boucles for-standard, puis mentionnez que vous aimeriez aussi connaître une bibliothèque, sinon cette question tend à ne pas être constructive. – Dukeling

Répondre

2
public static double[] vech(double[][] a) { 
    int na = Math.min(a.length, a[0].length); // Dimension of the matrix 
    int nv = na * (na + 1)/2; // 1 + 2 + 3 + .. + na 
    double[] v = new double[nv]; 
    int k = 0; // index in v. 
    for (int i = 0; i < na; ++i) { 
     for (int j = 0; j <= i; ++j) { 
      v[k] = a[i][j]; 
      ++k; 
     } 
    } 
    return v; 
} 

Case 2x2 Matrix:

Choix [0] [0], [1] [0], [1] [1] (sauter [0] [1])

ordre de rang majeur: (C, C#, Java a [i] [j] est un élément de la rangée i, colonne j.

Le code aplatit le triangle inférieur gauche.

ordre de colonne principal: (MATLAB, SciLab) a [i] [j] est l'élément de la colonne i, ligne j.

Le code aplatit le triangle supérieur droit.

autre séquence

L'autre triangle serait donnée par:

 for (int j = i; j < na; ++j) { 

combinée avec la mise en miroir dans la diagonale principale, on reçoit à nouveau le triangle orignal:

  a[j][i] 
+0

et si je voudrais accéder aux éléments 'v' d'une façon' column-major'? – fpe

+0

La différence entre row-major et column-major est '[i] [j]' '[j] [i]' ou en miroir dans la diagonale principale. –

0

Je ne peux pas penser à une bibliothèque qui vous permettrait de faire cela, même si je suis sûr il y a un quelque part, mais vous pouvez utiliser une boucle comme suit:

ArrayList<ArrayList<int>> matrix = new ArrayList<ArrayList<int>>(); 
// add other arraylists to your matrix here i.e.: 

ArrayList<Integer> first = new ArrayList<Integer>(); 
first.add(1); 
first.add(2); 
first.add(3); 

ArrayList<Integer> second = new ArrayList<Integer>(); 
second.add(4); 
second.add(5); 
second.add(6); 

ArrayList<Integer> third = new ArrayList<Integer>(); 
third.add(7); 
third.add(8); 
third.add(9); 

matrix.add(first); 
matrix.add(second); 
matrix.add(third); 

ArrayList<int> finalArray = new ArrayList<int>(); 

for(int i=0; i<matrix.size(); i++) 
{ 
    ArrayList<Integer> inner = matrix.get(i); 
    for(int j=0; j<i+1; j++) 
    { 
     finalArray.add(inner.get(j)); 
    } 
} 

Cela donne: matrix=[[1, 2, 3], [4, 5, 6], [7, 8, 9]] et finalArray=[1, 4, 5, 7, 8, 9]

Bien sûr, cela est en supposant que votre matrice est structurée à l'aide ArrayLists.

1

Il y a une autre chose intéressante à propos de tout cet emballage. Vous pouvez également définir un algorithme de mappage pour convertir (i, j) position dans une matrice symétrique en un décalage équivalent dans un tableau aplati (comme vous l'avez décrit). Vous pouvez utiliser les idées de Arithmetic progression pour définir une telle correspondance. Je l'ai fait en travaillant sur la classe RandomSymmetricMatrixSource.java en la4j. Ainsi, vous pouvez utiliser ces formules (il ne gère pas le cas lorsque i == j):

int flatten(int i, int j) { 
    int offset = -1; 

    if (i < j) { 
    offset = j - (i + 1) + (int)((((size - 1) + (size - i))/2.0) * i); 
    } else { 
    offset = i - (j + 1) + (int)((((size - 1) + (size - j))/2.0) * j); 
    } 

    return offset; 
} 

, où size est la taille de la matrice symétrique.

+0

Belle autre perspective. –

Questions connexes