Statistiques
| Révision :

root / tmp / org.txm.analec.rcp / src matt / JamaPlus / SparseMatrix.java @ 3243

Historique | Voir | Annoter | Télécharger (7,71 ko)

1
/*
2
 * To change this template, choose Tools | Templates
3
 * and open the template in the editor.
4
 */
5
package JamaPlus;
6

    
7
import JamaPlus.SparseSVD.SparseSVDException;
8
import java.util.*;
9
import java.util.logging.Level;
10
import java.util.logging.Logger;
11

    
12
/**
13
 *
14
 * @author Bernard Victorri
15
 */
16
public class SparseMatrix {
17
  private int m, n, nnz;
18
  private int[] colpts, rowinds;
19
  private double[] vals;
20
  private double[] tempRow;  // stockage temporaire pour certains calculs (opb)
21

    
22
  public SparseMatrix(int m, int n) { // null matrix
23
    this.m = m;
24
    this.n = n;
25
    nnz = 0;
26
    colpts = new int[n+1];
27
    rowinds = new int[0];
28
    vals = new double[0];
29
  }
30

    
31
   private static class Triple implements Comparable<Triple> {
32
    int row;
33
    int col;
34
    double val;
35

    
36
    private Triple(int row, int col, double val) {
37
      this.row = row;
38
      this.col = col;
39
      this.val = val;
40
    }
41
    private Triple(int row, int col) {
42
      this.row = row;
43
      this.col = col;
44
    }
45
    public int compareTo(Triple t) {
46
      int res = col - t.col;
47
      if(res==0) res = row - t.row;
48
      return res;
49
    }
50
  }
51

    
52
 public SparseMatrix(int m, int n, ArrayList<Integer> rows, ArrayList<Integer> cols,
53
          ArrayList<Double> values) {
54
    this.m = m;
55
    this.n = n;
56
    nnz = rows.size();
57
    if (nnz!=cols.size()||nnz!=rows.size())
58
      throw new ArrayIndexOutOfBoundsException(
59
              "Size of lines, cols and values don't agree");
60
    colpts = new int[n+1];
61
    rowinds = new int[nnz];
62
    vals = new double[nnz];
63
    Triple[] triples = new Triple[nnz];
64
    for(int i=0; i<nnz; i++) 
65
     triples[i] = new Triple(rows.get(i), cols.get(i), values.get(i));    
66
    Arrays.sort(triples);
67
    colpts[0] = 0;
68
    int c = 0;
69
    for(int i=0; i<nnz; i++) {
70
      if(i>0 && triples[i].row == triples[i-1].row && triples[i].col == triples[i-1].col) 
71
        throw new ArrayIndexOutOfBoundsException(
72
              "Two values with same row and column numbers");
73
      while(c<triples[i].col) colpts[++c] = i;
74
      rowinds[i] = triples[i].row;
75
      vals[i] = triples[i].val;
76
    }
77
    while(c<n) colpts[++c] = nnz;
78
  }
79

    
80
public SparseMatrix(int m, int n, ArrayList<Integer> rows, ArrayList<Integer> cols,
81
          double value) {
82
    this.m = m;
83
    this.n = n;
84
    nnz = rows.size();
85
    if (nnz!=cols.size()||nnz!=rows.size())
86
      throw new ArrayIndexOutOfBoundsException(
87
              "Size of lines, cols and values don't agree");
88
    colpts = new int[n+1];
89
    rowinds = new int[nnz];
90
        vals = new double[nnz];
91
    Triple[] triples = new Triple[nnz];
92
    for(int i=0; i<nnz; i++) 
93
     triples[i] = new Triple(rows.get(i), cols.get(i));    
94
    Arrays.sort(triples);
95
    colpts[0] = 0;
96
    int c = 0;
97
    for(int i=0; i<nnz; i++) {
98
      if(i>0 && triples[i].row == triples[i-1].row && triples[i].col == triples[i-1].col) 
99
        throw new ArrayIndexOutOfBoundsException(
100
              "Two values with same row and column numbers");
101
      while(c<triples[i].col) colpts[++c] = i;
102
      rowinds[i] = triples[i].row;
103
      vals[i] = value;
104
    }
105
    while(c<n) colpts[++c] = nnz;
106
  }
107

    
108
  private SparseMatrix(int m, int n, int nnz, int[] colpts, int[] rowinds, double[] vals) {
109
    this.m = m;
110
    this.n = n;
111
    this.nnz = nnz;
112
    this.colpts = colpts;
113
    this.rowinds = rowinds;
114
    this.vals = vals;
115
  }
116

    
117
  public SparseMatrix(Matrix mat) {  // convert a dense matrix
118
    m = mat.getRowDimension();
119
    n = mat.getColumnDimension();
120
    long nbval = mat.getNumberNonZeroValues();
121
    if (nbval>Integer.MAX_VALUE) throw new ArrayIndexOutOfBoundsException(
122
              "Number of non-zero values exceeds 32 bits integer");
123
    nnz = (int) nbval;
124
    colpts = new int[n+1];
125
    rowinds = new int[nnz];
126
    vals = new double[nnz];
127
    int nval = 0;
128
    for (int j = 0; j<n; j++) {
129
      colpts[j] = nval;
130
      for (int i = 0; i<m; i++) if (mat.get(i, j)!=0) {
131
          rowinds[nval] = i;
132
          vals[nval++] = mat.get(i, j);
133
        }
134
    }
135
    colpts[n] = nnz;
136
  }
137

    
138
  public SparseMatrix copy() {
139
    int[] colpts1 = new int[n+1];
140
    int[] rowinds1 = new int[nnz];
141
    double[] vals1 = new double[nnz];
142
    System.arraycopy(colpts, 0, colpts1, 0, n+1);
143
    System.arraycopy(rowinds, 0, rowinds1, 0, nnz);
144
    System.arraycopy(vals, 0, vals1, 0, nnz);
145
    return new SparseMatrix(m, n, nnz, colpts1, rowinds1, vals1);
146
  }
147

    
148
  public int getRowDimension() {
149
    return m;
150
  }
151

    
152
  public int getColumnDimension() {
153
    return n;
154
  }
155

    
156
  public double get(int i, int j) {
157
    try {
158
      for (int nval = colpts[j]; nval<colpts[j+1]; nval++)
159
        if (rowinds[nval]==i) return vals[nval];
160
      return 0;
161
    } catch (ArrayIndexOutOfBoundsException ex) {
162
      throw new ArrayIndexOutOfBoundsException("Sparse matrix : "
163
              +ex.getLocalizedMessage());
164
    }
165
  }
166

    
167
  public SparseMatrix transpose() {
168
    int[] colpts1 = new int[m+1];
169
    int[] rowinds1 = new int[nnz];
170
    double[] vals1 = new double[nnz];
171
    for (int v = 0; v<nnz; v++) colpts1[rowinds[v]]++;  // nnz in each row
172
    colpts1[m] = nnz-colpts1[m-1];
173
    for (int r = m-1; r>0; r--)
174
      colpts1[r] = colpts1[r+1]-colpts1[r-1]; // starting point of the previous row
175
    colpts1[0] = 0;
176
    int i = 0;
177
    for (int c = 0; c<n; c++) while (i<colpts[c+1]) {
178
        int j = colpts1[rowinds[i]+1]++;  // j : index of the value in the new vectors
179
        rowinds1[j] = c;
180
        vals1[j] = vals[i++];
181
      }
182
    return new SparseMatrix(n, m, nnz, colpts1, rowinds1, vals1);
183
  }
184

    
185
  public void nulColumnSuppression() {
186
    ArrayList<Integer> colpts1 = new ArrayList<Integer>();
187
    colpts1.add(0);
188
    for (int i = 0; i<n; i++) if (colpts[i+1]>colpts[i])
189
        colpts1.add(colpts[i+1]);
190
    n = colpts1.size()-1;
191
    colpts = new int[n+1];
192
    for (int i = 0; i<=n; i++) colpts[i] = colpts1.get(i);
193
  }
194

    
195
  public double elementSum() {
196
    double s = 0;
197
    for (int i = 0; i<nnz; i++) s += vals[i];
198

    
199
    return s;
200
  }
201

    
202
  public Matrix lineSum() {
203
    double[] S = new double[m];
204
    for (int i = 0; i<nnz; i++) S[rowinds[i]] += vals[i];
205

    
206
    return new Matrix(S, m);
207
  }
208

    
209
  public Matrix columnSum() {
210
    double[] S = new double[n];
211
    for (int i = 0; i<n; i++) for (int j = colpts[i]; j<colpts[i+1]; j++)
212
        S[i] += vals[j];
213

    
214
    return new Matrix(S, 1);
215
  }
216

    
217
  public SparseMatrix timesEquals(double s) {
218
    for (int i = 0; i<nnz; i++) {
219
      vals[i] *= s;
220
    }
221
    return this;
222
  }
223

    
224
  public SparseMatrix firstColumnTimesEqual(Matrix B) {
225
    double[][] A = B.getArray();
226
    for (int i = 0; i<n; i++) for (int j = colpts[i]; j<colpts[i+1]; j++)
227
        vals[j] *= A[rowinds[j]][0];
228
    return this;
229
  }
230

    
231
  public SparseMatrix firstLineTimesEqual(Matrix B) {
232
    double[][] A = B.getArray();
233
    for (int i = 0; i<n; i++) for (int j = colpts[i]; j<colpts[i+1]; j++)
234
        vals[j] *= A[0][i];
235
    return this;
236
  }
237

    
238
  public void opa(double x[], double y[]) {
239
    // Computes y = Ax (x et y : length n)
240
    Arrays.fill(y, 0);
241
    for (int i = 0; i<n; i++) for (int j = colpts[i]; j<colpts[i+1]; j++)
242
        y[rowinds[j]] += vals[j]*x[i];
243
  }
244

    
245
  public void opb(double x[], double y[]) {
246
    // Computes y = A'Ax (x et y : length n)
247
    if (tempRow==null) tempRow = new double[m];
248
    else Arrays.fill(tempRow, 0);
249
    Arrays.fill(y, 0);
250
    for (int i = 0; i<n; i++) for (int j = colpts[i]; j<colpts[i+1]; j++)
251
        tempRow[rowinds[j]] += vals[j]*x[i];
252
    for (int i = 0; i<n; i++) for (int j = colpts[i]; j<colpts[i+1]; j++)
253
        y[i] += vals[j]*tempRow[rowinds[j]];
254
  }
255

    
256
  public SparseSVD svd(int dim) throws SparseSVD.SparseSVDException {
257
    return new SparseSVD(this, dim);
258
  }
259

    
260
  /** Analyse factorielle de correspondances
261
  @return     Analyse factorielle de correspondances
262
  @see Analyse factorielle de correspondances
263
   */
264
  public SparseAFC afc() {
265
    try {
266
      return new SparseAFC(this);
267
    } catch (SparseSVDException ex) {
268
      return null;
269
    }
270
  }
271
}