~ubuntu-branches/ubuntu/precise/weka/precise

« back to all changes in this revision

Viewing changes to weka/classifiers/functions/pace/PaceMatrix.java

  • Committer: Bazaar Package Importer
  • Author(s): Soeren Sonnenburg
  • Date: 2008-02-24 09:18:45 UTC
  • Revision ID: james.westby@ubuntu.com-20080224091845-1l8zy6fm6xipbzsr
Tags: upstream-3.5.7+tut1
ImportĀ upstreamĀ versionĀ 3.5.7+tut1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 *    This program is free software; you can redistribute it and/or modify
 
3
 *    it under the terms of the GNU General Public License as published by
 
4
 *    the Free Software Foundation; either version 2 of the License, or (at
 
5
 *    your option) any later version.
 
6
 *
 
7
 *    This program is distributed in the hope that it will be useful, but
 
8
 *    WITHOUT ANY WARRANTY; without even the implied warranty of
 
9
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
10
 *    General Public License for more details.
 
11
 *
 
12
 *    You should have received a copy of the GNU General Public License
 
13
 *    along with this program; if not, write to the Free Software
 
14
 *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
 
15
 
 
16
/*
 
17
 *    PaceMatrix.java
 
18
 *    Copyright (C) 2002 University of Waikato, Hamilton, New Zealand
 
19
 *
 
20
 */
 
21
 
 
22
package weka.classifiers.functions.pace;
 
23
 
 
24
import weka.core.matrix.DoubleVector;
 
25
import weka.core.matrix.FlexibleDecimalFormat;
 
26
import weka.core.matrix.IntVector;
 
27
import weka.core.matrix.Matrix;
 
28
import weka.core.matrix.Maths;
 
29
 
 
30
import java.util.Random;
 
31
import java.text.DecimalFormat;
 
32
 
 
33
/**
 
34
 * Class for matrix manipulation used for pace regression. <p>
 
35
 *
 
36
 * REFERENCES <p>
 
37
 * 
 
38
 * Wang, Y. (2000). "A new approach to fitting linear models in high
 
39
 * dimensional spaces." PhD Thesis. Department of Computer Science,
 
40
 * University of Waikato, New Zealand. <p>
 
41
 * 
 
42
 * Wang, Y. and Witten, I. H. (2002). "Modeling for optimal probability
 
43
 * prediction." Proceedings of ICML'2002. Sydney. <p>
 
44
 *
 
45
 * @author Yong Wang (yongwang@cs.waikato.ac.nz)
 
46
 * @version $Revision: 1.5 $
 
47
 */
 
48
public class PaceMatrix 
 
49
  extends Matrix {
 
50
  
 
51
  /** for serialization */
 
52
  static final long serialVersionUID = 2699925616857843973L;
 
53
    
 
54
  /* ------------------------
 
55
     Constructors
 
56
     * ------------------------ */
 
57
  
 
58
  /** Construct an m-by-n PACE matrix of zeros. 
 
59
      @param m    Number of rows.
 
60
      @param n    Number of colums.
 
61
  */
 
62
  public PaceMatrix( int m, int n ) {
 
63
    super( m, n );
 
64
  }
 
65
 
 
66
  /** Construct an m-by-n constant PACE matrix.
 
67
      @param m    Number of rows.
 
68
      @param n    Number of colums.
 
69
      @param s    Fill the matrix with this scalar value.
 
70
  */
 
71
  public PaceMatrix( int m, int n, double s ) {
 
72
    super( m, n, s );
 
73
  }
 
74
    
 
75
  /** Construct a PACE matrix from a 2-D array.
 
76
      @param A    Two-dimensional array of doubles.
 
77
      @throws  IllegalArgumentException All rows must have the same length
 
78
  */
 
79
  public PaceMatrix( double[][] A ) {
 
80
    super( A );
 
81
  }
 
82
 
 
83
  /** Construct a PACE matrix quickly without checking arguments.
 
84
      @param A    Two-dimensional array of doubles.
 
85
      @param m    Number of rows.
 
86
      @param n    Number of colums.
 
87
  */
 
88
  public PaceMatrix( double[][] A, int m, int n ) {
 
89
    super( A, m, n );
 
90
  }
 
91
    
 
92
  /** Construct a PaceMatrix from a one-dimensional packed array
 
93
      @param vals One-dimensional array of doubles, packed by columns (ala Fortran).
 
94
      @param m    Number of rows.
 
95
      @throws  IllegalArgumentException Array length must be a multiple of m.
 
96
  */
 
97
  public PaceMatrix( double vals[], int m ) {
 
98
    super( vals, m );
 
99
  }
 
100
    
 
101
  /** Construct a PaceMatrix with a single column from a DoubleVector 
 
102
      @param v    DoubleVector
 
103
  */
 
104
  public PaceMatrix( DoubleVector v ) {
 
105
    this( v.size(), 1 );
 
106
    setMatrix( 0, v.size()-1, 0, v );
 
107
  }
 
108
    
 
109
  /** Construct a PaceMatrix from a Matrix 
 
110
      @param X    Matrix 
 
111
  */
 
112
  public PaceMatrix( Matrix X ) {
 
113
    super( X.getRowDimension(), X.getColumnDimension() );
 
114
    A = X.getArray();
 
115
  }
 
116
    
 
117
  /* ------------------------
 
118
     Public Methods
 
119
     * ------------------------ */
 
120
 
 
121
  /** Set the row dimenion of the matrix
 
122
   *  @param rowDimension the row dimension
 
123
   */
 
124
  public void setRowDimension( int rowDimension ) 
 
125
  {
 
126
    m = rowDimension;
 
127
  }
 
128
 
 
129
  /** Set the column dimenion of the matrix
 
130
   *  @param columnDimension the column dimension
 
131
   */
 
132
  public void setColumnDimension( int columnDimension ) 
 
133
  {
 
134
    n = columnDimension;
 
135
  }
 
136
 
 
137
  /** 
 
138
   * Clone the PaceMatrix object.
 
139
   * 
 
140
   * @return the clone
 
141
   */
 
142
  public Object clone () {
 
143
    PaceMatrix X = new PaceMatrix(m,n);
 
144
    double[][] C = X.getArray();
 
145
    for (int i = 0; i < m; i++) {
 
146
      for (int j = 0; j < n; j++) {
 
147
        C[i][j] = A[i][j];
 
148
      }
 
149
    }
 
150
    return (Object) X;
 
151
  }
 
152
    
 
153
  /** Add a value to an element and reset the element
 
154
   *  @param i    the row number of the element
 
155
   *  @param j    the column number of the element
 
156
   *  @param s    the double value to be added with
 
157
   */
 
158
  public void setPlus(int i, int j, double s) {
 
159
    A[i][j] += s;
 
160
  }
 
161
 
 
162
  /** Multiply a value with an element and reset the element
 
163
   *  @param i    the row number of the element
 
164
   *  @param j    the column number of the element
 
165
   *  @param s    the double value to be multiplied with
 
166
   */
 
167
  public void setTimes(int i, int j, double s) {
 
168
    A[i][j] *= s;
 
169
  }
 
170
 
 
171
  /** Set the submatrix A[i0:i1][j0:j1] with a same value 
 
172
   *  @param i0 the index of the first element of the column
 
173
   *  @param i1 the index of the last element of the column
 
174
   *  @param j0 the index of the first column
 
175
   *  @param j1 the index of the last column
 
176
   *  @param s the value to be set to
 
177
   */
 
178
  public void setMatrix( int i0, int i1, int j0, int j1, double s ) {
 
179
    try {
 
180
      for( int i = i0; i <= i1; i++ ) {
 
181
        for( int j = j0; j <= j1; j++ ) {
 
182
          A[i][j] = s;
 
183
        }
 
184
      }
 
185
    } catch( ArrayIndexOutOfBoundsException e ) {
 
186
      throw new ArrayIndexOutOfBoundsException( "Index out of bounds" );
 
187
    }
 
188
  }
 
189
  
 
190
  /** Set the submatrix A[i0:i1][j] with the values stored in a
 
191
   *  DoubleVector
 
192
   *  @param i0 the index of the first element of the column
 
193
   *  @param i1 the index of the last element of the column
 
194
   *  @param j  the index of the column
 
195
   *  @param v the vector that stores the values*/
 
196
  public void setMatrix( int i0, int i1, int j, DoubleVector v ) {
 
197
    for( int i = i0; i <= i1; i++ ) {
 
198
      A[i][j] = v.get(i-i0);
 
199
    }
 
200
  }
 
201
 
 
202
  /** Set the whole matrix from a 1-D array 
 
203
   *  @param v    1-D array of doubles
 
204
   *  @param columnFirst   Whether to fill the column first or the row.
 
205
   *  @throws  ArrayIndexOutOfBoundsException Submatrix indices
 
206
   */
 
207
  public void setMatrix ( double[] v, boolean columnFirst ) {
 
208
    try {
 
209
      if( v.length != m * n ) 
 
210
        throw new IllegalArgumentException("sizes not match.");
 
211
      int i, j, count = 0;
 
212
      if( columnFirst ) {
 
213
        for( i = 0; i < m; i++ ) {
 
214
          for( j = 0; j < n; j++ ) {
 
215
            A[i][j] = v[count];
 
216
            count ++;
 
217
          }
 
218
        }
 
219
      }
 
220
      else {
 
221
        for( j = 0; j < n; j++ ) {
 
222
          for( i = 0; i < m; i++ ){
 
223
            A[i][j] = v[count];
 
224
            count ++;
 
225
          }
 
226
        }
 
227
      }
 
228
 
 
229
    } catch( ArrayIndexOutOfBoundsException e ) {
 
230
      throw new ArrayIndexOutOfBoundsException( "Submatrix indices" );
 
231
    }
 
232
  }
 
233
 
 
234
  /** Returns the maximum absolute value of all elements 
 
235
      @return the maximum value
 
236
  */
 
237
  public double maxAbs () {
 
238
    double ma = Math.abs(A[0][0]);
 
239
    for (int j = 0; j < n; j++) {
 
240
      for (int i = 0; i < m; i++) {
 
241
        ma = Math.max(ma, Math.abs(A[i][j]));
 
242
      }
 
243
    }
 
244
    return ma;
 
245
  }
 
246
 
 
247
  /** Returns the maximum absolute value of some elements of a column,
 
248
      that is, the elements of A[i0:i1][j].
 
249
      @param i0 the index of the first element of the column
 
250
      @param i1 the index of the last element of the column
 
251
      @param j  the index of the column
 
252
      @return the maximum value */
 
253
  public double maxAbs ( int i0, int i1, int j ) {
 
254
    double m = Math.abs(A[i0][j]);
 
255
    for (int i = i0+1; i <= i1; i++) {
 
256
      m = Math.max(m, Math.abs(A[i][j]));
 
257
    }
 
258
    return m;
 
259
  }
 
260
 
 
261
  /** Returns the minimum absolute value of some elements of a column,
 
262
      that is, the elements of A[i0:i1][j].
 
263
      @param i0 the index of the first element of the column
 
264
      @param i1 the index of the last element of the column
 
265
      @param column the index of the column
 
266
      @return the minimum value 
 
267
  */
 
268
  public double minAbs ( int i0, int i1, int column ) {
 
269
    double m = Math.abs(A[i0][column]);
 
270
    for (int i = i0+1; i <= i1; i++) {
 
271
      m = Math.min(m, Math.abs(A[i][column]));
 
272
    }
 
273
    return m;
 
274
  }
 
275
    
 
276
  /** Check if the matrix is empty
 
277
   *   @return true if the matrix is empty
 
278
   */
 
279
  public boolean  isEmpty(){
 
280
    if(m == 0 || n == 0) return true;
 
281
    if(A == null) return true;
 
282
    return false;
 
283
  }
 
284
    
 
285
  /** Return a DoubleVector that stores a column of the matrix 
 
286
   *  @param j the index of the column
 
287
   *  @return the column
 
288
   */
 
289
  public DoubleVector  getColumn( int j ) {
 
290
    DoubleVector v = new DoubleVector( m );
 
291
    double [] a = v.getArray();
 
292
    for(int i = 0; i < m; i++)
 
293
      a[i] = A[i][j];
 
294
    return v;
 
295
  }
 
296
 
 
297
  /** Return a DoubleVector that stores some elements of a column of the
 
298
   *  matrix 
 
299
   *  @param i0 the index of the first element of the column
 
300
   *  @param i1 the index of the last element of the column
 
301
   *  @param j  the index of the column
 
302
   *  @return the DoubleVector
 
303
   */
 
304
  public DoubleVector  getColumn( int i0, int i1, int j ) {
 
305
    DoubleVector v = new DoubleVector( i1-i0+1 );
 
306
    double [] a = v.getArray();
 
307
    int count = 0;
 
308
    for( int i = i0; i <= i1; i++ ) {
 
309
      a[count] = A[i][j];
 
310
      count++;
 
311
    }
 
312
    return v;
 
313
  }
 
314
  
 
315
  
 
316
  /** Multiplication between a row (or part of a row) of the first matrix
 
317
   *  and a column (or part or a column) of the second matrix.
 
318
   *  @param i the index of the row in the first matrix
 
319
   *  @param j0 the index of the first column in the first matrix
 
320
   *  @param j1 the index of the last column in the first matrix
 
321
   *  @param B the second matrix
 
322
   *  @param l the index of the column in the second matrix
 
323
   *  @return the result of the multiplication
 
324
   */
 
325
  public double  times( int i, int j0, int j1, PaceMatrix B, int l ) {
 
326
    double s = 0.0;
 
327
    for(int j = j0; j <= j1; j++ ) {
 
328
      s += A[i][j] * B.A[j][l];
 
329
    }
 
330
    return s;
 
331
  }
 
332
  
 
333
  /** Decimal format for converting a matrix into a string
 
334
   *  @return the default decimal format
 
335
   */
 
336
  protected DecimalFormat []  format() {
 
337
    return format(0, m-1, 0, n-1, 7, false );
 
338
  }
 
339
  
 
340
  /** Decimal format for converting a matrix into a string
 
341
   *  @param digits the number of digits
 
342
   *  @return the decimal format
 
343
   */
 
344
  protected DecimalFormat []  format( int digits ) {
 
345
    return format(0, m-1, 0, n-1, digits, false);
 
346
  }
 
347
 
 
348
  /** Decimal format for converting a matrix into a string
 
349
   *  @param digits the number of digits
 
350
   *  @param trailing
 
351
   *  @return the decimal format
 
352
   */
 
353
  protected DecimalFormat []  format( int digits, boolean trailing ) {
 
354
    return format(0, m-1, 0, n-1, digits, trailing);
 
355
  }
 
356
  
 
357
  /** Decimal format for converting a matrix into a string
 
358
   *  @param i0
 
359
   *  @param i1
 
360
   *  @param j
 
361
   *  @param digits the number of digits
 
362
   *  @param trailing
 
363
   *  @return the decimal format
 
364
   */
 
365
  protected DecimalFormat  format(int i0, int i1, int j, int digits, 
 
366
                                  boolean trailing) {
 
367
    FlexibleDecimalFormat df = new FlexibleDecimalFormat(digits, trailing);
 
368
    df.grouping( true );
 
369
    for(int i = i0; i <= i1; i ++ )
 
370
      df.update( A[i][j] );
 
371
    return df;
 
372
  }
 
373
  
 
374
  /** Decimal format for converting a matrix into a string
 
375
   *  @param i0
 
376
   *  @param i1
 
377
   *  @param j0
 
378
   *  @param j1
 
379
   *  @param trailing
 
380
   *  @param digits the number of digits
 
381
   *  @return the decimal format
 
382
   */
 
383
  protected DecimalFormat []  format(int i0, int i1, int j0, int j1, 
 
384
                                     int digits, boolean trailing) {
 
385
    DecimalFormat [] f = new DecimalFormat[j1-j0+1];
 
386
    for( int j = j0; j <= j1; j++ ) {
 
387
      f[j] = format(i0, i1, j, digits, trailing);
 
388
    }
 
389
    return f;
 
390
  }
 
391
  
 
392
  /** 
 
393
   * Converts matrix to string
 
394
   * 
 
395
   * @return the matrix as string
 
396
   */ 
 
397
  public String  toString() {
 
398
    return toString( 5, false );
 
399
  }
 
400
  
 
401
  /** 
 
402
   * Converts matrix to string
 
403
   * 
 
404
   * @param digits number of digits after decimal point
 
405
   * @param trailing true if trailing zeros are padded
 
406
   * @return the matrix as string
 
407
   */ 
 
408
  public String  toString( int digits, boolean trailing ) {
 
409
    
 
410
    if( isEmpty() ) return "null matrix";
 
411
    
 
412
    StringBuffer text = new StringBuffer();
 
413
    DecimalFormat [] nf = format( digits, trailing );
 
414
    int numCols = 0;
 
415
    int count = 0;
 
416
    int width = 80;
 
417
    int lenNumber;
 
418
    
 
419
    int [] nCols = new int[n];
 
420
    int nk=0;
 
421
    for( int j = 0; j < n; j++ ) {
 
422
      lenNumber = nf[j].format( A[0][j]).length(); 
 
423
      if( count + 1 + lenNumber > width -1 ) {
 
424
        nCols[nk++]  = numCols;
 
425
        count = 0;
 
426
        numCols = 0;
 
427
      }
 
428
      count += 1 + lenNumber;
 
429
      ++numCols;
 
430
    }
 
431
    nCols[nk] = numCols;
 
432
    
 
433
    nk = 0;
 
434
    for( int k = 0; k < n; ) {
 
435
      for( int i = 0; i < m; i++ ) {
 
436
        for( int j = k; j < k + nCols[nk]; j++)
 
437
          text.append( " " + nf[j].format( A[i][j]) );
 
438
        text.append("\n");
 
439
      }
 
440
      k += nCols[nk];
 
441
      ++nk;
 
442
      text.append("\n");
 
443
    }
 
444
    
 
445
    return text.toString();
 
446
  }
 
447
  
 
448
  /** Squared sum of a column or row in a matrix
 
449
   * @param j the index of the column or row
 
450
   * @param i0 the index of the first element
 
451
   * @param i1 the index of the last element
 
452
   * @param col if true, sum over a column; otherwise, over a row
 
453
   * @return the squared sum
 
454
   */
 
455
  public double sum2( int j, int i0, int i1, boolean col ) {
 
456
    double s2 = 0;
 
457
    if( col ) {   // column 
 
458
      for( int i = i0; i <= i1; i++ ) 
 
459
        s2 += A[i][j] * A[i][j];
 
460
    }
 
461
    else {
 
462
      for( int i = i0; i <= i1; i++ ) 
 
463
        s2 += A[j][i] * A[j][i];
 
464
    }
 
465
    return s2;
 
466
  }
 
467
  
 
468
  /** Squared sum of columns or rows of a matrix
 
469
   * @param col if true, sum over columns; otherwise, over rows
 
470
   * @return the squared sum
 
471
   */
 
472
  public double[] sum2( boolean col ) {
 
473
    int l = col ? n : m;
 
474
    int p = col ? m : n;
 
475
    double [] s2 = new double[l];
 
476
    for( int i = 0; i < l; i++ ) 
 
477
      s2[i] = sum2( i, 0, p-1, col );
 
478
    return s2;
 
479
  }
 
480
 
 
481
  /** Constructs single Householder transformation for a column
 
482
   *
 
483
   @param j    the index of the column
 
484
   @param k    the index of the row
 
485
   @return     d and q 
 
486
  */
 
487
  public double [] h1( int j, int k ) {
 
488
    double dq[] = new double[2];
 
489
    double s2 = sum2(j, k, m-1, true);  
 
490
    dq[0] = A[k][j] >= 0 ? - Math.sqrt( s2 ) : Math.sqrt( s2 );
 
491
    A[k][j] -= dq[0];
 
492
    dq[1] = A[k][j] * dq[0];
 
493
    return dq;
 
494
  }
 
495
  
 
496
  /** Performs single Householder transformation on one column of a matrix
 
497
   *
 
498
   @param j    the index of the column 
 
499
   @param k    the index of the row
 
500
   @param q    q = - u'u/2; must be negative
 
501
   @param b    the matrix to be transformed
 
502
   @param l    the column of the matrix b
 
503
  */
 
504
  public void h2( int j, int k, double q, PaceMatrix b, int l ) {
 
505
    double s = 0, alpha;
 
506
    for( int i = k; i < m; i++ )
 
507
      s += A[i][j] * b.A[i][l];
 
508
    alpha = s / q;
 
509
    for( int i = k; i < m; i++ )
 
510
      b.A[i][l] += alpha * A[i][j];
 
511
  }
 
512
  
 
513
  /** Constructs the Givens rotation
 
514
   *  @param a 
 
515
   *  @param b
 
516
   *  @return a double array that stores the cosine and sine values
 
517
   */
 
518
  public double []  g1( double a, double b ) {
 
519
    double cs[] = new double[2];
 
520
    double r = Maths.hypot(a, b);
 
521
    if( r == 0.0 ) {
 
522
      cs[0] = 1;
 
523
      cs[1] = 0;
 
524
    }
 
525
    else {
 
526
      cs[0] = a / r;
 
527
      cs[1] = b / r;
 
528
    }
 
529
    return cs;
 
530
  }
 
531
  
 
532
  /** Performs the Givens rotation
 
533
   * @param cs a array storing the cosine and sine values
 
534
   * @param i0 the index of the row of the first element
 
535
   * @param i1 the index of the row of the second element
 
536
   * @param j the index of the column
 
537
   */
 
538
  public void  g2( double cs[], int i0, int i1, int j ){
 
539
    double w =   cs[0] * A[i0][j] + cs[1] * A[i1][j];
 
540
    A[i1][j] = - cs[1] * A[i0][j] + cs[0] * A[i1][j];
 
541
    A[i0][j] = w;
 
542
  }
 
543
  
 
544
  /** Forward ordering of columns in terms of response explanation.  On
 
545
   *  input, matrices A and b are already QR-transformed. The indices of
 
546
   *  transformed columns are stored in the pivoting vector.
 
547
   *  
 
548
   *@param b     the PaceMatrix b
 
549
   *@param pvt   the pivoting vector
 
550
   *@param k0    the first k0 columns (in pvt) of A are not to be changed
 
551
   **/
 
552
  public void forward( PaceMatrix b, IntVector pvt, int k0 ) {
 
553
    for( int j = k0; j < Math.min(pvt.size(), m); j++ ) {
 
554
      steplsqr( b, pvt, j, mostExplainingColumn(b, pvt, j), true );
 
555
    }
 
556
  }
 
557
 
 
558
  /** Returns the index of the column that has the largest (squared)
 
559
   *  response, when each of columns pvt[ks:] is moved to become the
 
560
   *  ks-th column. On input, A and b are both QR-transformed.
 
561
   *  
 
562
   * @param b    response
 
563
   * @param pvt  pivoting index of A
 
564
   * @param ks   columns pvt[ks:] of A are to be tested 
 
565
   * @return the index of the column
 
566
   */
 
567
  public int  mostExplainingColumn( PaceMatrix b, IntVector pvt, int ks ) {
 
568
    double val;
 
569
    int [] p = pvt.getArray();
 
570
    double ma = columnResponseExplanation( b, pvt, ks, ks );
 
571
    int jma = ks;
 
572
    for( int i = ks+1; i < pvt.size(); i++ ) {
 
573
      val = columnResponseExplanation( b, pvt, i, ks );
 
574
      if( val > ma ) {
 
575
        ma = val;
 
576
        jma = i;
 
577
      }
 
578
    }
 
579
    return jma;
 
580
  }
 
581
  
 
582
  /** Backward ordering of columns in terms of response explanation.  On
 
583
   *  input, matrices A and b are already QR-transformed. The indices of
 
584
   *  transformed columns are stored in the pivoting vector.
 
585
   * 
 
586
   *  A and b must have the same number of rows, being the (pseudo-)rank. 
 
587
   *  
 
588
   * @param b     PaceMatrix b
 
589
   * @param pvt   pivoting vector
 
590
   * @param ks    number of QR-transformed columns; psuedo-rank of A 
 
591
   * @param k0    first k0 columns in pvt[] are not to be ordered.
 
592
   */
 
593
  public void backward( PaceMatrix b, IntVector pvt, int ks, int k0 ) {
 
594
    for( int j = ks; j > k0; j-- ) {
 
595
      steplsqr( b, pvt, j, leastExplainingColumn(b, pvt, j, k0), false );
 
596
    }
 
597
  }
 
598
 
 
599
  /** Returns the index of the column that has the smallest (squared)
 
600
   *  response, when the column is moved to become the (ks-1)-th
 
601
   *  column. On input, A and b are both QR-transformed.
 
602
   *  
 
603
   * @param b    response
 
604
   * @param pvt  pivoting index of A
 
605
   * @param ks   psudo-rank of A
 
606
   * @param k0   A[][pvt[0:(k0-1)]] are excluded from the testing.
 
607
   * @return the index of the column
 
608
   */
 
609
  public int  leastExplainingColumn( PaceMatrix b, IntVector pvt, int ks, 
 
610
                                     int k0 ) {
 
611
    double val;
 
612
    int [] p = pvt.getArray();
 
613
    double mi = columnResponseExplanation( b, pvt, ks-1, ks );
 
614
    int jmi = ks-1;
 
615
    for( int i = k0; i < ks - 1; i++ ) {
 
616
      val = columnResponseExplanation( b, pvt, i, ks );
 
617
      if( val <= mi ) {
 
618
        mi = val;
 
619
        jmi = i;
 
620
      }
 
621
    }
 
622
    return jmi;
 
623
  }
 
624
  
 
625
  /** Returns the squared ks-th response value if the j-th column becomes
 
626
   *  the ks-th after orthogonal transformation.  A[][pvt[ks:j]] (or
 
627
   *  A[][pvt[j:ks]], if ks > j) and b[] are already QR-transformed
 
628
   *  on input and will remain unchanged on output.
 
629
   *
 
630
   *  More generally, it returns the inner product of the corresponding
 
631
   *  row vector of the response PaceMatrix. (To be implemented.)
 
632
   *
 
633
   *@param b    PaceMatrix b
 
634
   *@param pvt  pivoting vector
 
635
   *@param j    the column A[pvt[j]][] is to be moved
 
636
   *@param ks   the target column A[pvt[ks]][]
 
637
   *@return     the squared response value */
 
638
  public double  columnResponseExplanation( PaceMatrix b, IntVector pvt,
 
639
                                            int j, int ks ) {
 
640
    /*  Implementation: 
 
641
     *
 
642
     *  If j == ks - 1, returns the squared ks-th response directly.
 
643
     *
 
644
     *  If j > ks -1, returns the ks-th response after
 
645
     *  Householder-transforming the j-th column and the response.
 
646
     *
 
647
     *  If j < ks - 1, returns the ks-th response after a sequence of
 
648
     *  Givens rotations starting from the j-th row. */
 
649
 
 
650
    int k, l;
 
651
    double [] xxx = new double[n];
 
652
    int [] p = pvt.getArray();
 
653
    double val;
 
654
    
 
655
    if( j == ks -1 ) val = b.A[j][0];
 
656
    else if( j > ks - 1 ) {
 
657
      int jm = Math.min(n-1, j);
 
658
      DoubleVector u = getColumn(ks,jm,p[j]);
 
659
      DoubleVector v = b.getColumn(ks,jm,0);
 
660
      val = v.innerProduct(u) / u.norm2();
 
661
    }
 
662
    else {                 // ks > j
 
663
      for( k = j+1; k < ks; k++ ) // make a copy of A[j][]
 
664
        xxx[k] = A[j][p[k]];
 
665
      val = b.A[j][0];
 
666
      double [] cs;
 
667
      for( k = j+1; k < ks; k++ ) {
 
668
        cs = g1( xxx[k], A[k][p[k]] );
 
669
        for( l = k+1; l < ks; l++ ) 
 
670
          xxx[l] = - cs[1] * xxx[l] + cs[0] * A[k][p[l]];
 
671
        val = - cs[1] * val + cs[0] * b.A[k][0];
 
672
      }
 
673
    }
 
674
    return val * val;  // or inner product in later implementation???
 
675
  }
 
676
 
 
677
  /** 
 
678
   * QR transformation for a least squares problem<br/>
 
679
   *            A x = b<br/>
 
680
   * implicitly both A and b are transformed. pvt.size() is the psuedo-rank of 
 
681
   * A.
 
682
   *  
 
683
   * @param b    PaceMatrix b
 
684
   * @param pvt  pivoting vector
 
685
   * @param k0   the first k0 columns of A (indexed by pvt) are pre-chosen. 
 
686
   *            (But subject to rank examination.) 
 
687
   * 
 
688
   *            For example, the constant term may be reserved, in which
 
689
   *            case k0 = 1.
 
690
   **/
 
691
  public void  lsqr( PaceMatrix b, IntVector pvt, int k0 ) {
 
692
    final double TINY = 1e-15;
 
693
    int [] p = pvt.getArray();
 
694
    int ks = 0;  // psuedo-rank
 
695
    for(int j = 0; j < k0; j++ )   // k0 pre-chosen columns
 
696
      if( sum2(p[j],ks,m-1,true) > TINY ){ // large diagonal element 
 
697
        steplsqr(b, pvt, ks, j, true);
 
698
        ks++;
 
699
      }
 
700
      else {                     // collinear column
 
701
        pvt.shiftToEnd( j );
 
702
        pvt.setSize(pvt.size()-1);
 
703
        k0--;
 
704
        j--;
 
705
      }
 
706
        
 
707
    // initial QR transformation
 
708
    for(int j = k0; j < Math.min( pvt.size(), m ); j++ ) {
 
709
      if( sum2(p[j], ks, m-1, true) > TINY ) { 
 
710
        steplsqr(b, pvt, ks, j, true);
 
711
        ks++;
 
712
      }
 
713
      else {                     // collinear column
 
714
        pvt.shiftToEnd( j );
 
715
        pvt.setSize(pvt.size()-1);
 
716
        j--;
 
717
      }
 
718
    }
 
719
        
 
720
    b.m = m = ks;           // reset number of rows
 
721
    pvt.setSize( ks );
 
722
  }
 
723
    
 
724
  /** QR transformation for a least squares problem <br/>
 
725
   *            A x = b <br/>
 
726
   * implicitly both A and b are transformed. pvt.size() is the psuedo-rank of A.
 
727
   *  
 
728
   * @param b    PaceMatrix b
 
729
   * @param pvt  pivoting vector
 
730
   * @param k0   the first k0 columns of A (indexed by pvt) are pre-chosen. 
 
731
   *            (But subject to rank examination.) 
 
732
   * 
 
733
   *            For example, the constant term may be reserved, in which
 
734
   *            case k0 = 1.
 
735
   **/
 
736
  public void  lsqrSelection( PaceMatrix b, IntVector pvt, int k0 ) {
 
737
    int numObs = m;         // number of instances
 
738
    int numXs = pvt.size();
 
739
 
 
740
    lsqr( b, pvt, k0 );
 
741
 
 
742
    if( numXs > 200 || numXs > numObs ) { // too many columns.  
 
743
      forward(b, pvt, k0);
 
744
    }
 
745
    backward(b, pvt, pvt.size(), k0);
 
746
  }
 
747
    
 
748
  /** 
 
749
   * Sets all diagonal elements to be positive (or nonnegative) without
 
750
   * changing the least squares solution 
 
751
   * @param Y the response
 
752
   * @param pvt the pivoted column index
 
753
   */
 
754
  public void positiveDiagonal( PaceMatrix Y, IntVector pvt ) {
 
755
     
 
756
    int [] p = pvt.getArray();
 
757
    for( int i = 0; i < pvt.size(); i++ ) {
 
758
      if( A[i][p[i]] < 0.0 ) {
 
759
        for( int j = i; j < pvt.size(); j++ ) 
 
760
          A[i][p[j]] = - A[i][p[j]];
 
761
        Y.A[i][0] = - Y.A[i][0];
 
762
      }
 
763
    }
 
764
  }
 
765
 
 
766
  /** Stepwise least squares QR-decomposition of the problem
 
767
   *              A x = b
 
768
   @param b    PaceMatrix b
 
769
   @param pvt  pivoting vector
 
770
   @param ks   number of transformed columns
 
771
   @param j    pvt[j], the column to adjoin or delete
 
772
   @param adjoin   to adjoin if true; otherwise, to delete */
 
773
  public void  steplsqr( PaceMatrix b, IntVector pvt, int ks, int j, 
 
774
                         boolean adjoin ) {
 
775
    final int kp = pvt.size(); // number of columns under consideration
 
776
    int [] p = pvt.getArray();
 
777
        
 
778
    if( adjoin ) {     // adjoining 
 
779
      int pj = p[j];
 
780
      pvt.swap( ks, j );
 
781
      double dq[] = h1( pj, ks );
 
782
      int pk;
 
783
      for( int k = ks+1; k < kp; k++ ){
 
784
        pk = p[k];
 
785
        h2( pj, ks, dq[1], this, pk);
 
786
      }
 
787
      h2( pj, ks, dq[1], b, 0 ); // for matrix. ???
 
788
      A[ks][pj] = dq[0];
 
789
      for( int k = ks+1; k < m; k++ )
 
790
        A[k][pj] = 0;
 
791
    }
 
792
    else {          // removing 
 
793
      int pj = p[j];
 
794
      for( int i = j; i < ks-1; i++ ) 
 
795
        p[i] = p[i+1];
 
796
      p[ks-1] = pj;
 
797
      double [] cs;
 
798
      for( int i = j; i < ks-1; i++ ){
 
799
        cs = g1( A[i][p[i]], A[i+1][p[i]] );
 
800
        for( int l = i; l < kp; l++ ) 
 
801
          g2( cs, i, i+1, p[l] );
 
802
        for( int l = 0; l < b.n; l++ )
 
803
          b.g2( cs, i, i+1, l );
 
804
      }
 
805
    }
 
806
  }
 
807
    
 
808
  /** Solves upper-triangular equation <br/>
 
809
   *    R x = b <br/>
 
810
   *  On output, the solution is stored in b
 
811
   *  @param b the response
 
812
   *  @param pvt the pivoting vector
 
813
   *  @param kp the number of the first columns involved 
 
814
   */
 
815
  public void  rsolve( PaceMatrix b, IntVector pvt, int kp) {
 
816
    if(kp == 0) b.m = 0;
 
817
    int i, j, k;
 
818
    int [] p = pvt.getArray();
 
819
    double s;
 
820
    double [][] ba = b.getArray();
 
821
    for( k = 0; k < b.n; k++ ) {
 
822
      ba[kp-1][k] /= A[kp-1][p[kp-1]];
 
823
      for( i = kp - 2; i >= 0; i-- ){
 
824
        s = 0;
 
825
        for( j = i + 1; j < kp; j++ )
 
826
          s += A[i][p[j]] * ba[j][k];
 
827
        ba[i][k] -= s;
 
828
        ba[i][k] /= A[i][p[i]];
 
829
      }
 
830
    } 
 
831
    b.m = kp;
 
832
  }
 
833
    
 
834
  /** Returns a new matrix which binds two matrices together with rows. 
 
835
   *  @param b  the second matrix
 
836
   *  @return the combined matrix
 
837
   */
 
838
  public PaceMatrix  rbind( PaceMatrix b ){
 
839
    if( n != b.n ) 
 
840
      throw new IllegalArgumentException("unequal numbers of rows.");
 
841
    PaceMatrix c = new PaceMatrix( m + b.m, n );
 
842
    c.setMatrix( 0, m - 1, 0, n - 1, this );
 
843
    c.setMatrix( m, m + b.m - 1, 0, n - 1, b );
 
844
    return c;
 
845
  }
 
846
 
 
847
  /** Returns a new matrix which binds two matrices with columns.
 
848
   *  @param b the second matrix 
 
849
   *  @return the combined matrix
 
850
   */
 
851
  public PaceMatrix  cbind( PaceMatrix b ) {
 
852
    if( m != b.m ) 
 
853
      throw new IllegalArgumentException("unequal numbers of rows: " + 
 
854
                                         m + " and " + b.m);
 
855
    PaceMatrix c = new PaceMatrix(m, n + b.n);
 
856
    c.setMatrix( 0, m - 1, 0, n - 1, this );
 
857
    c.setMatrix( 0, m - 1, n, n + b.n - 1, b );
 
858
    return c;
 
859
  }
 
860
 
 
861
  /** Solves the nonnegative linear squares problem. That is, <p>
 
862
   *   <center>   min || A x - b||, subject to x >= 0.  </center> <p>
 
863
   * 
 
864
   *  For algorithm, refer to P161, Chapter 23 of C. L. Lawson and
 
865
   *  R. J. Hanson (1974).  "Solving Least Squares
 
866
   *  Problems". Prentice-Hall.
 
867
   *    @param b the response
 
868
   *  @param pvt vector storing pivoting column indices
 
869
   *    @return solution */
 
870
  public DoubleVector nnls( PaceMatrix b, IntVector pvt ) {
 
871
    int j, t, counter = 0, jm = -1, n = pvt.size();
 
872
    double ma, max, alpha, wj;
 
873
    int [] p = pvt.getArray();
 
874
    DoubleVector x = new DoubleVector( n );
 
875
    double [] xA = x.getArray();
 
876
    PaceMatrix z = new PaceMatrix(n, 1);
 
877
    PaceMatrix bt;
 
878
        
 
879
    // step 1 
 
880
    int kp = 0; // #variables in the positive set P
 
881
    while ( true ) {         // step 2 
 
882
      if( ++counter > 3*n )  // should never happen
 
883
        throw new RuntimeException("Does not converge");
 
884
      t = -1;
 
885
      max = 0.0;
 
886
      bt = new PaceMatrix( b.transpose() );
 
887
      for( j = kp; j <= n-1; j++ ) {   // W = A' (b - A x) 
 
888
        wj = bt.times( 0, kp, m-1, this, p[j] );
 
889
        if( wj > max ) {        // step 4
 
890
          max = wj;
 
891
          t = j;
 
892
        }
 
893
      }
 
894
            
 
895
      // step 3 
 
896
      if ( t == -1) break; // optimum achieved 
 
897
            
 
898
      // step 5 
 
899
      pvt.swap( kp, t );       // move variable from set Z to set P
 
900
      kp++;
 
901
      xA[kp-1] = 0;
 
902
      steplsqr( b, pvt, kp-1, kp-1, true );
 
903
      // step 6
 
904
      ma = 0;
 
905
      while ( ma < 1.5 ) {
 
906
        for( j = 0; j <= kp-1; j++ ) z.A[j][0] = b.A[j][0];
 
907
        rsolve(z, pvt, kp); 
 
908
        ma = 2; jm = -1;
 
909
        for( j = 0; j <= kp-1; j++ ) {  // step 7, 8 and 9
 
910
          if( z.A[j][0] <= 0.0 ) { // alpha always between 0 and 1
 
911
            alpha = xA[j] / ( xA[j] - z.A[j][0] ); 
 
912
            if( alpha < ma ) {
 
913
              ma = alpha; jm = j;
 
914
            }
 
915
          }
 
916
        }
 
917
        if( ma > 1.5 ) 
 
918
          for( j = 0; j <= kp-1; j++ ) xA[j] = z.A[j][0];  // step 7 
 
919
        else { 
 
920
          for( j = kp-1; j >= 0; j-- ) { // step 10
 
921
            // Modified to avoid round-off error (which seemingly 
 
922
            // can cause infinite loop).
 
923
            if( j == jm ) { // step 11 
 
924
              xA[j] = 0.0;
 
925
              steplsqr( b, pvt, kp, j, false );
 
926
              kp--;  // move variable from set P to set Z
 
927
            }
 
928
            else xA[j] += ma * ( z.A[j][0] - xA[j] );
 
929
          }
 
930
        }
 
931
      }
 
932
    }
 
933
    x.setSize(kp);
 
934
    pvt.setSize(kp);
 
935
    return x;
 
936
  }
 
937
 
 
938
  /** Solves the nonnegative least squares problem with equality
 
939
   *    constraint. That is, <p>
 
940
   *  <center> min ||A x - b||, subject to x >= 0 and c x = d. </center> <p>
 
941
   *
 
942
   *  @param b the response
 
943
   *  @param c coeficients of equality constraints
 
944
   *  @param d constants of equality constraints
 
945
   *  @param pvt vector storing pivoting column indices
 
946
   *  @return the solution
 
947
   */
 
948
  public DoubleVector nnlse( PaceMatrix b, PaceMatrix c, PaceMatrix d, 
 
949
                             IntVector pvt ) {
 
950
    double eps = 1e-10 * Math.max( c.maxAbs(), d.maxAbs() ) /
 
951
    Math.max( maxAbs(), b.maxAbs() );
 
952
        
 
953
    PaceMatrix e = c.rbind( new PaceMatrix( times(eps) ) );
 
954
    PaceMatrix f = d.rbind( new PaceMatrix( b.times(eps) ) );
 
955
 
 
956
    return e.nnls( f, pvt );
 
957
  }
 
958
 
 
959
  /** Solves the nonnegative least squares problem with equality
 
960
   *    constraint. That is, <p>
 
961
   *  <center> min ||A x - b||,  subject to x >= 0 and || x || = 1. </center>
 
962
   *  <p>
 
963
   *  @param b the response 
 
964
   *  @param pvt vector storing pivoting column indices
 
965
   *  @return the solution
 
966
   */
 
967
  public DoubleVector nnlse1( PaceMatrix b, IntVector pvt ) {
 
968
    PaceMatrix c = new PaceMatrix( 1, n, 1 );
 
969
    PaceMatrix d = new PaceMatrix( 1, b.n, 1 );
 
970
        
 
971
    return nnlse(b, c, d, pvt);
 
972
  }
 
973
 
 
974
  /** Generate matrix with standard-normally distributed random elements
 
975
      @param m    Number of rows.
 
976
      @param n    Number of colums.
 
977
      @return An m-by-n matrix with random elements.  */
 
978
  public static Matrix randomNormal( int m, int n ) {
 
979
    Random random = new Random();
 
980
     
 
981
    Matrix A = new Matrix(m,n);
 
982
    double[][] X = A.getArray();
 
983
    for (int i = 0; i < m; i++) {
 
984
      for (int j = 0; j < n; j++) {
 
985
        X[i][j] = random.nextGaussian();
 
986
      }
 
987
    }
 
988
    return A;
 
989
  }
 
990
 
 
991
  /**
 
992
   * for testing only
 
993
   * 
 
994
   * @param args the commandline arguments - ignored
 
995
   */
 
996
  public static void  main( String args[] ) {
 
997
    System.out.println("================================================" + 
 
998
                       "===========");
 
999
    System.out.println("To test the pace estimators of linear model\n" + 
 
1000
                       "coefficients.\n");
 
1001
 
 
1002
    double sd = 2;     // standard deviation of the random error term
 
1003
    int n = 200;       // total number of observations
 
1004
    double beta0 = 100;   // intercept
 
1005
    int k1 = 20;       // number of coefficients of the first cluster
 
1006
    double beta1 = 0;  // coefficient value of the first cluster
 
1007
    int k2 = 20;      // number of coefficients of the second cluster
 
1008
    double beta2 = 5; // coefficient value of the second cluster 
 
1009
    int k = 1 + k1 + k2;
 
1010
 
 
1011
    DoubleVector beta = new DoubleVector( 1 + k1 + k2 );
 
1012
    beta.set( 0, beta0 );
 
1013
    beta.set( 1, k1, beta1 );
 
1014
    beta.set( k1+1, k1+k2, beta2 );
 
1015
 
 
1016
    System.out.println("The data set contains " + n + 
 
1017
                       " observations plus " + (k1 + k2) + 
 
1018
                       " variables.\n\nThe coefficients of the true model"
 
1019
                       + " are:\n\n" + beta );
 
1020
        
 
1021
    System.out.println("\nThe standard deviation of the error term is " + 
 
1022
                       sd );
 
1023
        
 
1024
    System.out.println("===============================================" 
 
1025
                       + "============");
 
1026
                
 
1027
    PaceMatrix X = new PaceMatrix( n, k1+k2+1 );
 
1028
    X.setMatrix( 0, n-1, 0, 0, 1 );
 
1029
    X.setMatrix( 0, n-1, 1, k1+k2, random(n, k1+k2) );
 
1030
        
 
1031
    PaceMatrix Y = new 
 
1032
      PaceMatrix( X.times( new PaceMatrix(beta) ).
 
1033
                  plusEquals( randomNormal(n,1).times(sd) ) );
 
1034
 
 
1035
    IntVector pvt = (IntVector) IntVector.seq(0, k1+k2);
 
1036
 
 
1037
    /*System.out.println( "The OLS estimate (by jama.Matrix.solve()) is:\n\n" + 
 
1038
      (new PaceMatrix(X.solve(Y))).getColumn(0) );*/
 
1039
        
 
1040
    X.lsqrSelection( Y, pvt, 1 );
 
1041
    X.positiveDiagonal( Y, pvt );
 
1042
 
 
1043
    PaceMatrix sol = (PaceMatrix) Y.clone();
 
1044
    X.rsolve( sol, pvt, pvt.size() );
 
1045
    DoubleVector betaHat = sol.getColumn(0).unpivoting( pvt, k );
 
1046
    System.out.println( "\nThe OLS estimate (through lsqr()) is: \n\n" + 
 
1047
                        betaHat );
 
1048
 
 
1049
    System.out.println( "\nQuadratic loss of the OLS estimate (||X b - X bHat||^2) = " + 
 
1050
                        ( new PaceMatrix( X.times( new 
 
1051
                          PaceMatrix(beta.minus(betaHat)) )))
 
1052
                        .getColumn(0).sum2() );
 
1053
 
 
1054
    System.out.println("=============================================" + 
 
1055
                       "==============");
 
1056
    System.out.println("             *** Pace estimation *** \n");
 
1057
    DoubleVector r = Y.getColumn( pvt.size(), n-1, 0);
 
1058
    double sde = Math.sqrt(r.sum2() / r.size());
 
1059
        
 
1060
    System.out.println( "Estimated standard deviation = " + sde );
 
1061
 
 
1062
    DoubleVector aHat = Y.getColumn( 0, pvt.size()-1, 0).times( 1./sde );
 
1063
    System.out.println("\naHat = \n" + aHat );
 
1064
        
 
1065
    System.out.println("\n========= Based on chi-square mixture ============");
 
1066
 
 
1067
    ChisqMixture d2 = new ChisqMixture();
 
1068
    int method = MixtureDistribution.NNMMethod;
 
1069
    DoubleVector AHat = aHat.square();
 
1070
    d2.fit( AHat, method ); 
 
1071
    System.out.println( "\nEstimated mixing distribution is:\n" + d2 );
 
1072
        
 
1073
    DoubleVector ATilde = d2.pace2( AHat );
 
1074
    DoubleVector aTilde = ATilde.sqrt().times(aHat.sign());
 
1075
    PaceMatrix YTilde = new 
 
1076
      PaceMatrix((new PaceMatrix(aTilde)).times( sde ));
 
1077
    X.rsolve( YTilde, pvt, pvt.size() );
 
1078
    DoubleVector betaTilde = 
 
1079
    YTilde.getColumn(0).unpivoting( pvt, k );
 
1080
    System.out.println( "\nThe pace2 estimate of coefficients = \n" + 
 
1081
                        betaTilde );
 
1082
    System.out.println( "Quadratic loss = " + 
 
1083
                        ( new PaceMatrix( X.times( new 
 
1084
                          PaceMatrix(beta.minus(betaTilde)) )))
 
1085
                        .getColumn(0).sum2() );
 
1086
        
 
1087
    ATilde = d2.pace4( AHat );
 
1088
    aTilde = ATilde.sqrt().times(aHat.sign());
 
1089
    YTilde = new PaceMatrix((new PaceMatrix(aTilde)).times( sde ));
 
1090
    X.rsolve( YTilde, pvt, pvt.size() );
 
1091
    betaTilde = YTilde.getColumn(0).unpivoting( pvt, k );
 
1092
    System.out.println( "\nThe pace4 estimate of coefficients = \n" + 
 
1093
                        betaTilde );
 
1094
    System.out.println( "Quadratic loss = " + 
 
1095
                        ( new PaceMatrix( X.times( new 
 
1096
                          PaceMatrix(beta.minus(betaTilde)) )))
 
1097
                        .getColumn(0).sum2() );
 
1098
        
 
1099
    ATilde = d2.pace6( AHat );
 
1100
    aTilde = ATilde.sqrt().times(aHat.sign());
 
1101
    YTilde = new PaceMatrix((new PaceMatrix(aTilde)).times( sde ));
 
1102
    X.rsolve( YTilde, pvt, pvt.size() );
 
1103
    betaTilde = YTilde.getColumn(0).unpivoting( pvt, k );
 
1104
    System.out.println( "\nThe pace6 estimate of coefficients = \n" + 
 
1105
                        betaTilde );
 
1106
    System.out.println( "Quadratic loss = " + 
 
1107
                        ( new PaceMatrix( X.times( new 
 
1108
                          PaceMatrix(beta.minus(betaTilde)) )))
 
1109
                        .getColumn(0).sum2() );
 
1110
        
 
1111
    System.out.println("\n========= Based on normal mixture ============");
 
1112
        
 
1113
    NormalMixture d = new NormalMixture();
 
1114
    d.fit( aHat, method ); 
 
1115
    System.out.println( "\nEstimated mixing distribution is:\n" + d );
 
1116
        
 
1117
    aTilde = d.nestedEstimate( aHat );
 
1118
    YTilde = new PaceMatrix((new PaceMatrix(aTilde)).times( sde ));
 
1119
    X.rsolve( YTilde, pvt, pvt.size() );
 
1120
    betaTilde = YTilde.getColumn(0).unpivoting( pvt, k );
 
1121
    System.out.println( "The nested estimate of coefficients = \n" + 
 
1122
                        betaTilde );
 
1123
    System.out.println( "Quadratic loss = " + 
 
1124
                        ( new PaceMatrix( X.times( new 
 
1125
                          PaceMatrix(beta.minus(betaTilde)) )))
 
1126
                        .getColumn(0).sum2() );
 
1127
        
 
1128
        
 
1129
    aTilde = d.subsetEstimate( aHat );
 
1130
    YTilde = new PaceMatrix((new PaceMatrix(aTilde)).times( sde ));
 
1131
    X.rsolve( YTilde, pvt, pvt.size() );
 
1132
    betaTilde = 
 
1133
    YTilde.getColumn(0).unpivoting( pvt, k );
 
1134
    System.out.println( "\nThe subset estimate of coefficients = \n" + 
 
1135
                        betaTilde );
 
1136
    System.out.println( "Quadratic loss = " + 
 
1137
                        ( new PaceMatrix( X.times( new 
 
1138
                          PaceMatrix(beta.minus(betaTilde)) )))
 
1139
                        .getColumn(0).sum2() );
 
1140
        
 
1141
    aTilde = d.empiricalBayesEstimate( aHat );
 
1142
    YTilde = new PaceMatrix((new PaceMatrix(aTilde)).times( sde ));
 
1143
    X.rsolve( YTilde, pvt, pvt.size() );
 
1144
    betaTilde = YTilde.getColumn(0).unpivoting( pvt, k );
 
1145
    System.out.println( "\nThe empirical Bayes estimate of coefficients = \n"+
 
1146
                        betaTilde );
 
1147
        
 
1148
    System.out.println( "Quadratic loss = " + 
 
1149
                        ( new PaceMatrix( X.times( new 
 
1150
                          PaceMatrix(beta.minus(betaTilde)) )))
 
1151
                        .getColumn(0).sum2() );
 
1152
        
 
1153
  }
 
1154
}
 
1155
 
 
1156
 
 
1157