a b/partyMod/src/LinearStatistic.c
1
2
/**
3
    Linear statistics for conditional inference based on Strasser & Weber (1999)
4
    *\file LinearStatistic.c
5
    *\author $Author$
6
    *\date $Date$
7
*/
8
    
9
#include "party.h"
10
11
12
/**
13
    Computes the linear statistic, formula (1) in the paper\n
14
    *\param x values of the transformation
15
    *\param p dimension of the transformation
16
    *\param y values of the influence function
17
    *\param q dimension of the influence function
18
    *\param weights case weights
19
    *\param n number of observations
20
    *\param ans return value; a pointer to a REALSXP-vector of length pq
21
*/
22
  
23
void C_LinearStatistic (const double *x, const int p,
24
                        const double *y, const int q,
25
                        const double *weights, const int n,
26
                        double *ans) {
27
              
28
    int i, j, k, kp, kn;
29
    double tmp;
30
31
    for (k = 0; k < q; k++) {
32
33
        kn = k * n;
34
        kp = k * p;
35
        for (j = 0; j < p; j++) ans[kp + j] = 0.0;
36
            
37
        for (i = 0; i < n; i++) {
38
                
39
            /* optimization: weights are often zero */
40
            if (weights[i] == 0.0) continue;
41
                
42
            tmp = y[kn + i] * weights[i];
43
                
44
            for (j = 0; j < p; j++)
45
                 ans[kp + j] += x[j*n + i] * tmp;
46
        }
47
    }
48
}
49
50
51
/**
52
    R-interface to C_LinearStatistic \n
53
    *\param x values of the transformation
54
    *\param y values of the influence function
55
    *\param weights case weights
56
*/
57
58
SEXP R_LinearStatistic(SEXP x, SEXP y, SEXP weights) {
59
60
    /* the return value; a vector of type REALSXP */
61
    SEXP ans;
62
63
    /* dimensions */
64
    int n, p, q;
65
66
    /* 
67
     *    only a basic check: we do not coerce objects since this
68
     *    function is for internal use only
69
     */
70
    
71
    if (!isReal(x) || !isReal(y) || !isReal(weights))
72
        error("LinStat: arguments are not of type REALSXP");
73
    
74
    n = nrow(y);
75
    if (nrow(x) != n || LENGTH(weights) != n)
76
        error("LinStat: dimensions don't match");
77
78
    q    = ncol(y);
79
    p    = ncol(x);
80
           
81
    PROTECT(ans = allocVector(REALSXP, p*q));
82
 
83
    C_LinearStatistic(REAL(x), p, REAL(y), q, REAL(weights), n, 
84
                      REAL(ans));
85
86
    UNPROTECT(1);
87
    return(ans);
88
}
89
90
91
/**
92
    Conditional expectation and covariance of the influence function\n
93
    *\param y values of the influence function
94
    *\param q dimension of the influence function
95
    *\param weights case weights
96
    *\param n number of observations
97
    *\param ans return value; an object of class `ExpectCovarInfluence'
98
*/
99
100
void C_ExpectCovarInfluence(const double* y, const int q,
101
                            const double* weights, const int n, 
102
                            SEXP ans) {
103
104
    int i, j, k, jq;
105
    
106
    /* pointers to the slots of object ans */
107
    double *dExp_y, *dCov_y, *dsweights, tmp;
108
    
109
    /*  return values: set to zero initially */
110
    dExp_y = REAL(GET_SLOT(ans, PL2_expectationSym));
111
    for (j = 0; j < q; j++) dExp_y[j] = 0.0;
112
    
113
    dCov_y = REAL(GET_SLOT(ans, PL2_covarianceSym));
114
    for (j = 0; j < q*q; j++) dCov_y[j] = 0.0;
115
    
116
    dsweights = REAL(GET_SLOT(ans, PL2_sumweightsSym));
117
118
    /*  compute the sum of the weights */
119
        
120
    dsweights[0] = 0;
121
    for (i = 0; i < n; i++) dsweights[0] += weights[i];
122
    if (dsweights[0] <= 1) 
123
        error("C_ExpectCovarInfluence: sum of weights is less than one");
124
125
    /*
126
     *    Expectation of the influence function
127
     */
128
129
    for (i = 0; i < n; i++) {
130
131
        /*  observations with zero case weights do not contribute */
132
    
133
        if (weights[i] == 0.0) continue;
134
    
135
        for (j = 0; j < q; j++)
136
            dExp_y[j] += weights[i] * y[j * n + i];
137
    }
138
139
    for (j = 0; j < q; j++)
140
        dExp_y[j] = dExp_y[j] / dsweights[0];
141
142
143
    /*
144
     *    Covariance of the influence function
145
     */
146
147
    for (i = 0; i < n; i++) {
148
149
        if (weights[i] == 0.0) continue;
150
     
151
        for (j = 0; j < q; j++) {
152
            tmp = weights[i] * (y[j * n + i] - dExp_y[j]);
153
            jq = j * q;
154
            for (k = 0; k < q; k++)
155
                dCov_y[jq + k] += tmp * (y[k * n + i] - dExp_y[k]);
156
        }
157
    }
158
159
    for (j = 0; j < q*q; j++)
160
        dCov_y[j] = dCov_y[j] / dsweights[0];
161
}
162
163
164
/**
165
    R-interface to C_ExpectCovarInfluence\n
166
    *\param y values of the influence function
167
    *\param weights case weights
168
*/
169
170
SEXP R_ExpectCovarInfluence(SEXP y, SEXP weights) {
171
172
    SEXP ans;
173
    int q, n;
174
    
175
    if (!isReal(y) || !isReal(weights))
176
        error("R_ExpectCovarInfluence: arguments are not of type REALSXP");
177
    
178
    n = nrow(y);
179
    q = ncol(y);
180
    
181
    if (LENGTH(weights) != n) 
182
        error("R_ExpectCovarInfluence: vector of case weights does not have %d elements", n);
183
184
    /*  allocate storage for return values */
185
    PROTECT(ans = NEW_OBJECT(MAKE_CLASS("ExpectCovarInfluence")));
186
    SET_SLOT(ans, PL2_expectationSym, 
187
             PROTECT(allocVector(REALSXP, q)));
188
    SET_SLOT(ans, PL2_covarianceSym, 
189
             PROTECT(allocMatrix(REALSXP, q, q)));
190
    SET_SLOT(ans, PL2_sumweightsSym, 
191
             PROTECT(allocVector(REALSXP, 1)));
192
193
    C_ExpectCovarInfluence(REAL(y), q, REAL(weights), n, ans);
194
    
195
    UNPROTECT(4);
196
    return(ans);
197
}
198
199
200
/**
201
    Conditional expectation and covariance of the a linear statistic\n
202
    *\param x values of the transformation
203
    *\param p dimension of the transformation
204
    *\param y values of the influence function
205
    *\param q dimension of the influence function
206
    *\param weights case weights
207
    *\param n number of observations
208
    *\param expcovinf an object of class `ExpectCovarInfluence'
209
    *\param ans return value; an object of class `ExpectCovar'
210
*/
211
212
void C_ExpectCovarLinearStatistic(const double* x, const int p, 
213
                                  const double* y, const int q,
214
                                  const double* weights, const int n,
215
                                  const SEXP expcovinf, SEXP ans) {
216
217
    int i, j, k, pq;
218
    double sweights = 0.0, f1, f2, tmp;
219
    double *swx, *CT1, *CT2, *Covy_x_swx, 
220
           *dExp_y, *dCov_y, *dExp_T, *dCov_T;
221
    
222
    pq   = p * q;
223
    
224
    /* the expectation and covariance of the influence function */
225
    dExp_y = REAL(GET_SLOT(expcovinf, PL2_expectationSym));
226
    dCov_y = REAL(GET_SLOT(expcovinf, PL2_covarianceSym));
227
    sweights = REAL(GET_SLOT(expcovinf, PL2_sumweightsSym))[0];
228
229
    if (sweights <= 1.0) 
230
        error("C_ExpectCovarLinearStatistic: sum of weights is less than one");
231
232
    /* prepare for storing the results */
233
    dExp_T = REAL(GET_SLOT(ans, PL2_expectationSym));
234
    dCov_T = REAL(GET_SLOT(ans, PL2_covarianceSym));
235
236
    /* allocate storage: all helpers, initially zero */
237
    swx = Calloc(p, double);               /* p x 1  */
238
    CT1 = Calloc(p * p, double);           /* p x p  */
239
240
    for (i = 0; i < n; i++) {
241
242
        /*  observations with zero case weights do not contribute */
243
        if (weights[i] == 0.0) continue;
244
    
245
        for (k = 0; k < p; k++) {
246
            tmp = weights[i] * x[k * n + i];
247
            swx[k] += tmp;
248
249
            /* covariance part */
250
            for (j = 0; j < p; j++) {
251
                CT1[j * p + k] += tmp * x[j * n + i];
252
            }
253
        }
254
    }
255
256
    /*
257
    *   dExp_T: expectation of the linear statistic T
258
    */
259
260
    for (k = 0; k < p; k++) {
261
        for (j = 0; j < q; j++)
262
            dExp_T[j * p + k] = swx[k] * dExp_y[j];
263
    }
264
265
    /* 
266
    *   dCov_T:  covariance of the linear statistic T
267
    */
268
269
    f1 = sweights/(sweights - 1);
270
    f2 = (1/(sweights - 1));
271
272
    if (pq == 1) {
273
        dCov_T[0] = f1 * dCov_y[0] * CT1[0];
274
        dCov_T[0] -= f2 * dCov_y[0] * swx[0] * swx[0];
275
    } else {
276
        /* two more helpers needed */
277
        CT2 = Calloc(pq * pq, double);            /* pq x pq */
278
        Covy_x_swx = Calloc(pq * q, double);      /* pq x q  */
279
        
280
        C_kronecker(dCov_y, q, q, CT1, p, p, dCov_T);
281
        C_kronecker(dCov_y, q, q, swx, p, 1, Covy_x_swx);
282
        C_kronecker(Covy_x_swx, pq, q, swx, 1, p, CT2);
283
284
        for (k = 0; k < (pq * pq); k++)
285
            dCov_T[k] = f1 * dCov_T[k] - f2 * CT2[k];
286
287
        /* clean up */
288
        Free(CT2); Free(Covy_x_swx);
289
    }
290
291
    /* clean up */
292
    Free(swx); Free(CT1); 
293
}
294
295
296
/**
297
    R-interface to C_ExpectCovarLinearStatistic\n
298
    *\param x values of the transformation
299
    *\param y values of the influence function
300
    *\param weights case weights
301
    *\param expcovinf an object of class `ExpectCovarInfluence'
302
*/
303
304
SEXP R_ExpectCovarLinearStatistic(SEXP x, SEXP y, SEXP weights, 
305
                                  SEXP expcovinf) {
306
    
307
    SEXP ans;
308
    int n, p, q, pq;
309
310
    /* determine the dimensions and some checks */
311
312
    n  = nrow(x);
313
    p  = ncol(x);
314
    q  = ncol(y);
315
    pq = p * q;
316
    
317
    if (nrow(y) != n)
318
        error("y does not have %d rows", n);
319
    if (LENGTH(weights) != n) 
320
        error("vector of case weights does not have %d elements", n);
321
322
    PROTECT(ans = NEW_OBJECT(MAKE_CLASS("ExpectCovar")));
323
    SET_SLOT(ans, PL2_expectationSym, 
324
             PROTECT(allocVector(REALSXP, pq)));
325
    SET_SLOT(ans, PL2_covarianceSym, 
326
             PROTECT(allocMatrix(REALSXP, pq, pq)));
327
328
    C_ExpectCovarLinearStatistic(REAL(x), p, REAL(y), q, 
329
        REAL(weights), n, expcovinf, ans);
330
    
331
    UNPROTECT(3);
332
    return(ans);
333
}
334
335
336
/**
337
    Linear Statistic with permuted indices\n
338
    *\param x values of the transformation
339
    *\param p dimension of the transformation
340
    *\param y values of the influence function
341
    *\param q dimension of the influence function
342
    *\param n number of observations
343
    *\param nperm number of permutations
344
    *\param indx indices for the x-part
345
    *\param perm (permuted) indices for the y-part
346
    *\param ans return value; a pointer to a REALSXP-vector of length pq
347
*/
348
349
void C_PermutedLinearStatistic(const double *x, const int p,
350
                               const double *y, const int q,
351
                               const int n, const int nperm,
352
                               const int *indx, const int *perm, 
353
                               double *ans) {
354
355
    int i, j, k, kp, kn, knpi;
356
357
    for (k = 0; k < q; k++) {
358
359
        kn = k * n;
360
        kp = k * p;
361
        for (j = 0; j < p; j++) ans[kp + j] = 0.0;
362
            
363
        for (i = 0; i < nperm; i++) {
364
                
365
            knpi = kn + perm[i];
366
367
            for (j = 0; j < p; j++)
368
                ans[kp + j] += x[j*n + indx[i]] * y[knpi];
369
        }
370
    }
371
}
372
373
374
/**
375
    Linear Statistic with permuted indices\n
376
    *\param x values of the transformation
377
    *\param y values of the influence function
378
    *\param indx indices for the x-part
379
    *\param perm (permuted) indices for the y-part
380
*/
381
382
SEXP R_PermutedLinearStatistic(SEXP x, SEXP y, SEXP indx, SEXP perm) {
383
384
    SEXP ans;
385
    int n, nperm, p, q, i, *iperm, *iindx;
386
387
    /* 
388
       only a basic check
389
    */
390
391
    if (!isReal(x) || !isReal(y))
392
        error("R_PermutedLinearStatistic: arguments are not of type REALSXP");
393
    
394
    if (!isInteger(perm))
395
        error("R_PermutedLinearStatistic: perm is not of type INTSXP");
396
    if (!isInteger(indx))
397
        error("R_PermutedLinearStatistic: indx is not of type INTSXP");
398
    
399
    n = nrow(y);
400
    nperm = LENGTH(perm);
401
    iperm = INTEGER(perm);
402
    if (LENGTH(indx)  != nperm)
403
        error("R_PermutedLinearStatistic: dimensions don't match");
404
    iindx = INTEGER(indx);
405
406
    if (nrow(x) != n)
407
        error("R_PermutedLinearStatistic: dimensions don't match");
408
409
    for (i = 0; i < nperm; i++) {
410
        if (iperm[i] < 0 || iperm[i] > (n - 1) )
411
            error("R_PermutedLinearStatistic: perm is not between 1 and nobs");
412
        if (iindx[i] < 0 || iindx[i] > (n - 1) )
413
            error("R_PermutedLinearStatistic: indx is not between 1 and nobs");
414
    }
415
416
    q    = ncol(y);
417
    p    = ncol(x);
418
           
419
    PROTECT(ans = allocVector(REALSXP, p*q));
420
    
421
    C_PermutedLinearStatistic(REAL(x), p, REAL(y), q, n, nperm,
422
                 iindx, iperm, REAL(ans));
423
    
424
    UNPROTECT(1);
425
    return(ans);
426
}