• No results found

An instance of the DS data structure contains the following members:

The definition and use of the elements of d0 are determined by the particular application and are mostly up to the user. A typical use might use a vector of structures. For example, suppose the objective function requires a vector of observations on a dependent variable as well as on K independent variables. Then:

struct DS d0;

d0 = dsCreate;

y = rndn(20,1);

x = rndn(20,5);

d0 = reshape(d0,2,1);

d0[1].dataMatrix = y;

d0[2].dataMatrix = X;

The d0 instance would be passed to the optimization program which then passes it to your procedure computing the objective function. For example:

struct DS d0;

d0.dataMatrix MxK matrix, data

d0.dataArray N-dimensional array, data d0.type scalar

d0.dname string d0.vnames string array

14-8

GAUSS User Guide

proc lpr(struct PV p1, struct DS d1);

local u;

u = d0[1].dataMatrix - d0[2].dataMatrix * pvUnpack(p1,"beta");

retp(u'u);

endp;

A particular application may require setting other members of the DS instance for particular purposes, but in general you may use them for your own purposes. For example, d0.dname could be set to a GAUSS dataset name from which you read the data in the objective function procedure, or d0.vnames could be set to the variable names of the columns of the data stored in d0.dataMatrix, or d0.type could be an indicator variable for the elements of a vector of DS instances.

The following are complete examples of the use of the PV and DS structures. The first example fits a set of data to the Micherlitz model. It illustrates packing and unpacking by index.

#include sqpsolvemt.sdf struct DS Y;

Y = dsCreate;

Y.dataMatrix = 3.183|

3.059|

2.871|

2.622|

2.541|

2.184|

2.110|

2.075|

2.018|

1.903|

1.770|

Run-Time Library Structures

1.762|

1.550;

struct DS X;

X = dsCreate;

X.dataMatrix = seqa(1,1,13);

struct DS Z;

Z = reshape(Z,2,1);

Z[1] = Y;

Z[2] = X;

struct SQPsolveMTControl c1;

c1 = sqpSolveMTcontrolCreate; /* initializes */

/* default values */

c1.bounds = 0~100; /* constrains parameters */

/* to be positive */

c1.CovType = 1;

c1.output = 1;

c1.printIters = 0;

c1.gradProc = &grad;

struct PV par1;

par1 = pvCreate(1);

start = { 2, 4, 2 };

par1 = pvPacki(par1,start,"Parameters",1);

struct SQPsolveMTout out1;

out1 = SQPsolveMT(&Micherlitz,par1,Z,c1);

14-10

GAUSS User Guide

estimates = pvGetParVector(out1.par);

print " parameter estimates ";

print estimates;

print;

print " standard errors ";

print sqrt(diag(out1.moment));

proc Micherlitz(struct PV par1,struct DS Z);

local p0,e,s2;

p0 = pvUnpack(par1,1);

e = Z[1].dataMatrix - p0[1] - p0[2]*exp(-p0[3]

*Z[2].dataMatrix);

s2 = moment(e,0)/(rows(e)-1);

retp( (2/rows(e))*(e.*e/s2 + ln(2*pi*s2)));

endp;

proc grad(struct PV par1, struct DS Z);

local p0,e,e1,e2,e3,w,g,s2;

p0 = pvUnpack(par1,1);

w = exp(-p0[3]*Z[2].dataMatrix);

e = z[1].dataMatrix - p0[1] - p0[2] * w;

s2 = moment(e,0) / rows(e);

e1 = - ones(rows(e),1);

e2 = -w;

e3 = p0[2]*Z[2].dataMatrix.*w;

w = (1 - e.*e / s2) / rows(e);

g = e.*e1 + w*(e'e1);

g = g ~ (e.*e2 + w*(e'e2));

Run-Time Library Structures

g = g ~ (e.*e3 + w*(e'e3));

retp(4*g/(rows(e)*s2));

endp;

This example estimates parameters of a “confirmatory factor analysis” model.

#include sqpsolvemt.sdf lambda = { 1.0 0.0,

0.5 0.0, 0.0 1.0, 0.0 0.5 };

lmask = { 0 0, 1 0, 0 0, 0 1 };

phi = { 1.0 0.3, 0.3 1.0 };

theta = { 0.6 0.0 0.0 0.0, 0.0 0.6 0.0 0.0, 0.0 0.0 0.6 0.0, 0.0 0.0 0.0 0.6 };

tmask = { 1 0 0 0,

0 1 0 0,

0 0 1 0,

0 0 0 1 };

struct PV par0;

par0 = pvCreate;

14-12

GAUSS User Guide

par0 = pvPackm(par0,lambda,"lambda",lmask);

par0 = pvPacks(par0,phi,"phi");

par0 = pvPacksm(par0,theta,"theta",tmask);

struct SQPsolveMTControl c0;

c0 = sqpSolveMTcontrolCreate;

lind = pvGetIndex(par0,"lambda"); /* get indices of */

/* lambda parameters */

/* in parameter vector */

tind = pvGetIndex(par0,"theta"); /* get indices of */

/* theta parameters */

/* in parameter vector */

c0.bounds = ones(pvLength(par0),1).*(-1e250~1e250);

c0.bounds[lind,1] = zeros(rows(lind),1);

c0.bounds[lind,2] = 10*ones(rows(lind),1);

c0.bounds[tind,1] = .001*ones(rows(tind),1);

c0.bounds[tind,2] = 100*ones(rows(tind),1);

c0.ineqProc = &ineq;

c0.covType = 1;

struct DS d0;

d0 = dsCreate;

d0.dataMatrix = loadd("maxfact");

struct SQPsolveMTOut out0;

out0 = SQPsolveMT(&lpr,par0,d0,c0);

lambdahat = pvUnpack(out0.par,"lambda");

Run-Time Library Structures

phihat = pvUnpack(out0.par,"phi");

thetahat = pvUnpack(out0.par,"theta");

print "estimates";

print;

print "lambda" lambdahat;

print;

print "phi" phihat;

print;

print "theta" thetahat;

struct PV stderr;

stderr = out0.par;

if not scalmiss(out0.moment);

stderr =

pvPutParVector(stderr,sqrt(diag(out0.moment)));

lambdase = pvUnpack(stderr,"lambda");

phise = pvUnpack(stderr,"phi");

thetase = pvUnpack(stderr,"theta");

print "standard errors";

print;

print "lambda" lambdase;

print;

print "phi" phise;

print;

print "theta" thetase;

endif;

14-14

GAUSS User Guide

local lambda,phi,theta,sigma,logl;

lambda = pvUnpack(par1,"lambda");

phi = pvUnpack(par1,"phi");

theta = pvUnpack(par1,"theta");

sigma = lambda*phi*lambda' + theta;

logl = -lnpdfmvn(data1.dataMatrix,sigma);

retp(logl);

endp;

proc ineq(struct PV par1, struct DS data1);

local lambda,phi,theta,sigma,e;

lambda = pvUnpack(par1,"lambda");

phi = pvUnpack(par1,"phi");

theta = pvUnpack(par1,"theta");

sigma = lambda*phi*lambda' + theta;

e = eigh(sigma) - .001; /* eigenvalues of sigma */

e = e | eigh(phi) - .001; /* eigenvalues of phi */

retp(e);

endp;

N-Dimensional Arrays 15

In GAUSS, internally, matrices and arrays are separate data types. Matrices, which are 2-dimensional objects, are stored in memory in row major order. Therefore, a 3x2 matrix is stored as follows:

[1,1] [1,2] [2,1] [2,2] [3,1] [3,2]

The slowest moving dimension in memory is indexed on the right, and the fastest moving dimension is indexed on the left. This is true of N-dimensional arrays as well.

A 4x3x2 array is stored in the following way:

[1,1,1] [1,1,2] [1,2,1] [1,2,2] [1,3,1] [1,3,2]

[2,1,1] [2,1,2] [2,2,1] [2,2,2] [2,3,1] [2,3,2]

[3,1,1] [3,1,2] [3,2,1] [3,2,2] [3,3,1] [3,3,2]

[4,1,1] [4,1,2] [4,2,1] [4,2,2] [4,3,1] [4,3,2]

A complex N-dimensional array is stored in memory in the same way. Like complex matrices, complex arrays are stored with the entire real part first, followed by the entire imaginary part.

Every N-dimensional array has a corresponding Nx1 vector of orders that contains the sizes of each dimension of the array. This is stored with the array and can be accessed with getorders. The first element of the vector of orders corresponds to the slowest moving dimension, and the last element corresponds to the fastest moving dimension

15-2

GAUSS User Guide

(refer to the Glossary of Terms at the end of the chapter for clear definitions of these terms). The vector of orders for a 6x5x4x3x2 array, which has 5 dimensions, is the following 5x1 vector:

Two terms that are important in working with N-dimensional arrays are ‘dimension index’ and ‘dimension number.’ A dimension index specifies a dimension based on indexing the vector of orders. It is a scalar, 1-to-N, where 1 corresponds to the dimension indicated by the first element of the vector of orders of the array (the slowest moving dimension) and N corresponds to the dimension indicated by the last element of the vector of orders (the fastest moving dimension).

A dimension number specifies dimensions by numbering them in the same order that one would add dimensions to an array. In other words, the dimensions of an N-dimensional array are numbered such that the fastest moving dimension has a dimension number of 1, and the slowest moving dimension has a dimension number of N.

A 6x5x4x3x2 array has 5 dimensions, so the first element of the vector of orders (in this case, 6) refers to the size of dimension number 5. Since the index of this element in the vector of orders is 1, the dimension index of the corresponding dimension (dimension number 5) is also 1.

You will find references to both dimension index and dimension number in the documentation for the functions that manipulate arrays.

There are a number of functions that have been designed to manipulate arrays. These functions allow you to manipulate a subarray within the array by passing in a locator vector to index any subarray that comprises a contiguous block of memory within the larger block. A vector of indices of an N-dimensional array is a [1-to-N]x1 vector of base 1 indices into the array, where the first element corresponds to the first element in a vector of orders. An Nx1 vector of indices locates the scalar whose position is indicated by the indices. For a 4x3x2 array x, the 3x1 vector of indices:

3 2 1

N-Dimensional Arrays

indexes the [3,2,1] element of x. A 2x1 vector of indices for this 3-dimensional example, references the 1-dimensional array whose starting location is given by the indices.

Because the elements of the vector of indices are always in the same order (the first element of the vector of indices corresponds to the slowest moving dimension of the array, the second element to the second slowest moving dimension, and so on), each unique vector of indices locates a unique subarray.

In general, an [N-K]x1 vector of indices locates a K-dimensional subarray that begins at the position indicated by the indices. The sizes of the dimensions of the

K-dimensional subarray correspond to the last K elements of the vector of orders of the N-dimensional array. For a 6x5x4x3x2 array y, the 2x1 vector of indices:

2 5

locates the 4x3x2 subarray in y that begins at [2,5,1,1,1] and ends at [2,5,4,3,2].

Related documents