MATRIX

<< Click to Display Table of Contents >>

Navigation:  Gekko User Manual > Gekko statements >

MATRIX

Previous pageReturn to chapter overviewNext page

A Gekko matrix contains two-dimensional cells with numeric values. Matrix names always start with the symbol #, like the other collection types list and map. You can import/export matrices to/from Excel, but only if the cells of the matrix are numerical values. Matrices can be manipulated with the usual linear algebra operators and functions, like adding, multiplying, inverting, etc. See the list of matrix functions in the end of this section.

 

If you need to manipulate data "cells" of non-numeric values (like for instance an Excel spreadsheet with values, dates and strings), instead of a matrix, you should use a nested list. Nested lists can be of any dimension, and indexing, selecting, looping etc. works similarly for nested lists and matrices.

 

See the SHEET statement if you need to transfer Excel cells into a matrix (or nested list).

 

NOTE: Instead of the former SHOW statement for printing matrices, you should use PRT in Gekko 3.0.

 

 


 

Syntax

 

#m = expression;
matrix #m = expression;
matrix < ROWNAMES = #list  COLNAMES = #list > #m = expression;

matrix ?;                                 //show/count matrices in open databanks

 

It is no longer legal to use for instance matrix m = ... ;, omitting the '#'.

 

ROWNAMES =

A list containing the names (labels) of the rows of the matrix, to be shown with PRT. You may use quotes (') when creating the list elements, if you need special characters like blanks etc.

COLNAMES =

A list containing the names (labels) of the cols of the matrix, to be shown with PRT. You may use quotes (') when creating the list elements, if you need special characters like blanks etc.

name

The name of the matrix.

expression

Any expression. You may omit the expression if you just need to decorate an already existing matrix with row- or colnames.

?

Query regarding a particular matrix, or all matrices

 

Note to Excel users: to import data from a spreadsheet, use the SHEET statement (SHEET<import matrix>). To export a matrix #m from Gekko to Excel, you can use export <xlsx> #m file = matrix.xlsx;.

 


 

Examples

 

The MATRIX statement supports quite a lot of the more common matrix capabilities. More capabilities will be added over time. Regarding matrix functions, please consult the Gekko functions page, under the 'Matrix functions' section (for instance determinant, inverse, transpose, diagonal, summation, etc.). These functions are also shown at the end of this help page.

 

You may construct a 2x2 matrix like this:

 

#= [1, 2; 3, 4];  //or: matrix #m = [1, 2; 3, 4]; 

 

The commas separate the row items, and the ';' separates columns. The MATRIX keyword may be omitted, since the right-hand side is guaranteed to be a matrix defintion. To construct matrices, you may use values or other matrices instead of the fixed numbers shown here. In general, matrices are referred to by means of the '#' indicator, just like lists. Use PRT to print out a matrix:

 

prt #m;

 

This will print out the following:

 

#m
                     1                2
    1           1.0000           2.0000
    2           3.0000           4.0000

 

Note: after printng a matrix like this, you may use Copy-button in the main Gekko window to copy/paste the matrix to Excel. To decorate with custom row- and col-names, you may do the following (you may alternatively use listfiles to contain the labels, cf. LIST):

 

#rn = ('Agriculture', 'Services etc.');
#cn = ('Employed', 'Unemployed');
<rownames=#rn colnames=#cn> #= [1, 2; 3, 4];
prt #m;

 

This will print the following labeled matrix:

 

 #m
                      Employed     Unemployed 
  Agriculture           1.0000         2.0000 
  Services etc.         3.0000         4.0000

 

You may concatenate existing matrices like this:

 

#= [#m1; #m2];               //column-wise
#= [#m1, #m2];               //row-wise
#= [#m1, #m2; #m3 ,#m4];     //both

 

You may get a list of all matrices or a particular matrix with

 

matrix ?;

 

You may construct matrices filled with 0's, 1's or missing values by means of the functions zeros(n, k), ones(n, k), or miss(n, k), for instance:

 

#= zeros(5, 10);

 

You can use +, -, * and / on two matrices, to add, subtract, multiply or divide. Regarding division, you can only divide a matrix by a value or a 1x1 matrix. Otherwise, use the element-by-element functions multiply() and divide().

 

You may index a matrix by means of the indexer []. For instance:

 

%= #m[2, 4];

 

This picks out the element in row 2, column 4. Please note that the indexes are 1-based. The inverse operation:

 

#m[2, 4] = %v;

 

Sub-matrices can be picked out by means of the range dots ('..'), for instance:

 

#m2 = #m[1..2, 5..7];

 

This picks out rows 1 and 2, and combines them with columns 5, 6 and 7. Note that these ranges may not be descending, for instance #m[2..1, 7..5]. The inverse operation:

 

#m[1..2, 5..7] = #m2;

 

To select a full row or column, use an 'empty' range like this:

 

#m2 = #m[3, ..];

 

This selects all the items in row 3. You may also use for instance '2..' to pick out the elements from 2 and onwards, or '..10' to pick out the elements from 1 up to and including 10. Use '..' to pick out all rows/columns.

 

For a column vector #c (that is, a n x 1 matrix), you may omit the column index, so in that case, these two will amount to the same:

 

%= #c[5];
%= #c[5, 1];

 

You may pack and unpack matrices from timeseries, for instance:

 

reset;
time 2001 2003;
x1 = 1, 2, 3; 
x2 = 3, 4, 5;
#m;
#= pack(2001, 2003,x1, x2);
y1 = #m[.., 1].unpack(2001, 2003);
y2 = #m[.., 2].unpack(2001, 2003);
p<n> x1, y1, x2, y2;

 

This will pack the two timeseries x1 and x2 into a 3 x 2 matrix #m (with data from 2001-2003). You may unpack back to two timeseries again with the unpack() function as shown. The indexes [.., 1] and [.., 2] pick out all rows of the two columns in #m. You may also consult the pack/unpack example in the R_RUN section. Column vectors can be handy, when you use them as a list of values:

 

#= [100; 150; 120];
for val %= 1 to #m.rows();
  tell 'Index {%i} has value {#m[%i]}';
end;

 

This will print out the numbers 100, 150 and 120:

 

 Index 1 has value 100
 Index 2 has value 150
 Index 3 has value 120

 

Since #m is a column vector, you may use #m[%i] instead of the more cumbersome #m[%i, 1].

 

There are min, max, avg and sum functions, working on rows or columns. For instance, you may decorate a matrix with grand totals like in the code below (where the third row and column are totals). The functions sumr() and sumc() sum the rows and columns, respectively. The last expression, #m.sumc().sumr(), could just as well have been stated as #m.sumr().sumc(). The divide(#m1, #m2) function divides two matrices element by element, but #m2 may have only 1 row or column stated. In that case, the function works on rows or columns, respectively.

 

#= [1, 2; 3, 4];
prt [#m, #m.sumr(); #m.sumc(), #m.sumc().sumr()];
prt divide(#m, #m.sumr());
prt divide(#m, #m.sumc());

 

Output:

 

 [#m, #m.sumr(); #m.sumc(), #m.sumc().sumr()]
                    1              2              3 
     1         1.0000         2.0000         3.0000 
     2         3.0000         4.0000         7.0000 
     3         4.0000         6.0000        10.0000 
 
 divide(#m, #m.sumr())
                    1              2 
     1         0.3333         0.6667 
     2         0.4286         0.5714 
 
 divide(#m, #m.sumc())
                    1              2 
     1         0.2500         0.3333 
     2         0.7500         0.6667

 

In the first print, the rows sum to 1, and in the second print, the columns sum to 1. Matrices can be exported and imported from Excel, for instance:

 

#= [1, 2, 3; 4, 5, 6];
export <xlsx> #m file = m.xlsx;
sheet <import matrix> #m2 file=m.xlsx;
prt #m, #m2;

 

The example below estimates a linear least squares model with five parameters. You may consult the OLS section to see the same parameters calculated via the OLS solver, or the R_RUN section to see the same parameters calculated via the R interface.

 

reset;
create lna1, pcp, bul1;
lna1 <1998 2010> = data(' 166.223000  173.221000  179.571000  187.343000  194.888000  202.959000  
209.426000  215.134000  222.716000  230.520000  238.518000  246.654000  254.991000') ;
pcp <1998 2010>   = data(' 0.9502030   0.9699920   1.0000000   1.0235000   1.0401100   1.0605400   
1.0754700   1.0977800   1.1121200   1.1314800   1.1513000   1.1717600   1.1871600')  ;
bul1 <1998 2010>  = data(' 0.0684791   0.0591698   0.0560344   0.0535439   0.0535003   0.0631703   
0.0649875   0.0578112   0.0473207   0.0404508   0.0467488   0.0472923   0.0475191')  ;
time 2000 2010;
create s0, s1, s2, s3, s4, s5;
s0 = dlog(lna1);
s1 = dlog(pcp);
s2 = dlog(pcp.1);
s3 = bul1;
s4 = bul1.1;
s5 = 1;
#= pack(2000, 2010, s1, s2, s3, s4, s5);
#= pack(2000, 2010, s0);
#= inv(t(#x)*#x)*t(#x)*#y;  //OLS formula
prt #b;

 

The statements produce the following parameter estimates:

 #b
                      1 
     1           0.1445 
     2           0.6139 
     3           0.1867 
     4          -0.3509 
     5           0.0298 

 

 

 


 

Matrix functions

 

Matrix functions:

 

Function name

Description

Examples

avgc(x)

Average over cols.

Returns: matrix

#m2 = avgc(#m1);

avgr(x)

Average over rows

Returns: matrix

#m2 = avgr(#m1);

chol(x)

chol(x, type)

Cholesky decomposition of matrix x. Accepts type (string), either 'upper' or 'lower'.

Returns: matrix

#m2 = chol(#m1, 'upper');

cols(x)

Returns the number of colums of x

Returns: val

%= cols(#m);

design(x)

Returns a "design" matrix, equivalent to the same Gauss function. The function is practical for aggregating rows or columns.

 

Input: is a n x 1 column matrix

Returns: n x k matrix of 0's and 1's. The input numbers specify the columns in which the 1's should be placed.

 

In the example, a 4 x 5 matrix #x of 1's is defined, and by means of the aggregation matrix #m, it is aggregated from size 4 x 5 to 4 x 3. In this case, the new column 1 is the old columns 2 and 3, the new column 2 is the old column 5, and the new column 3 is the old columns 1 and 4.

#= [3; 1; 1; 3; 2];
#= design(#a);
#= ones(4, 5);
#m, #* #d;
 
#m
                   1              2              3 
    1         0.0000         0.0000         1.0000 
    2         1.0000         0.0000         0.0000 
    3         1.0000         0.0000         0.0000 
    4         0.0000         0.0000         1.0000 
    5         0.0000         1.0000         0.0000 
 
#* #d
                   1              2              3 
    1         2.0000         1.0000         2.0000 
    2         2.0000         1.0000         2.0000 
    3         2.0000         1.0000         2.0000 
    4         2.0000         1.0000         2.0000 

det(x)

Determinant of a matrix.

Returns: val

%= det(#m);

diag(x)

Diagonal. If x is a n x n symmetric matrix, the method returns the diagonal as a n x 1 matrix. If x is a n x 1 column vector, the method returns a n x n matrix with this column vector on the diagonal (and zeroes elsewhere).

Returns: matrix

#m2 = diag(#m1);

divide(x1, x2)

Element by element division of the two matrices. If x2 is a row vector, each x1 column will be divided with the corresponding value from the row vector.  And if x2 is a column vector, each x1 row will be divided with the corresponding value from the column vector.

Returns: matrix

#= divide(#x1, #x2);

i(n)

Returns a n x n identity matrix.

Returns: matrix

#= i(10);

inv(x)

Inverse of matrix x

Returns: matrix

#m2 = inv(#m1);

maxc(x)

Max over cols

Returns: matrix

#m2 = maxc(#m1);

maxr(x)

Max over rows

Returns: matrix

#m2 = maxr(#m1);

minc(x)

Min over cols

Returns: matrix

#m2 = minc(#m1);

minr(x)

Min over rows

Returns: matrix

#m2 = minr(#m1);

m(r, c) or miss(r, c)

Returns a n x k matrix filled with missing values. Cf. also m() function for values.

Returns: matrix

#= m(5, 10);

multiply(x1, x2)

Element by element multiplication of the two matrices. If x2 is a row vector, each x1 column will be multiplied with the corresponding value from the row vector.  And if x2 is a column vector, each x1 row will be multiplied with the corresponding value from the column vector.

Returns: matrix

#= multiply(#x1, #x2);

ones(n, k)

Returns a n x k matrix filled with 1's

Returns: matrix

#= ones(5, 10);

pack(v1, v2, ...)

pack(<t1 t2>, v1, v2, ...)

Using period t1-t2, the timeseries v1, v2, ... are packed into a n x k matrix, where n is the number of observations and k is the number of variables. If the period is omitted, the global time period is used.

Returns: matrix

#= pack(<2020 2030>, x, y, z); Returns: a 11 x 3 matrix #m with the values.

rows(x)

Returns the number of rows of x.

Returns: val

%= rows(#m);

sumc(x)

Sum over cols

Returns: matrix

#m2 = sumc(#m1);

sumr(x)

Sum over rows

Returns: matrix

#m2 = sumr(#m1);

t(x)

Returns the transpose of a matrix.

Returns: matrix

#m2 = t(#m1);

trace(x)

Returns the trace of a matrix.

Returns: val

%= trace(#m);

unpack(m)

unpack(<t1 t2>, m)

The column matrix m (with only one column) is unpacked into a timeseries spanning the period t1-t2. If the period is omitted, the local/global time period is used.

The unpack() function is not strictly necessary: you may alternatively assign a nx1 matrix directly to a series (see example).

Returns: series

//This picks out the second column of #m (and all the rows).

= #m[.., 2].unpack(<2020 2030>);  
<2020 2030> = #m[.., 2].unpack();  //same
<2020 2030> = #m[.., 2]; //also works

zeros(n, k)

Returns a n x k matrix filled with 0's. Zeroes() can be used as alias.

Returns: matrix

#= zeros(5, 10);

 

 

 


 

Note

 

See the page with syntax diagrams if the basics of names, expressions, etc. is confusing.

 

You may use m() to indicate a missing value for a matrix element. You can also use m(r, c) to get a matrix with missing values.

 

Note that an assignment like #m1 = #m2;, where #m2 is a matrix, #m1 will become a copy of #m2, not a reference to it. The same is the case regarding function arguments, where manipulating #m1 inside the function body of f(#m1) will not affect #m1 after the function has been left.

 

Matrices are printed with PRT, the former SHOW statement is obsolete.

 

Regarding variable types and the Gekko type system, see the VAR section. In this appendix, variable assignment rules, including variable types, is explained in more detail.

 

A Gekko matrix only supports numeric values inside the cells. It relates to the following in different languages:

 

Gekko: #m= [1, 2; 3, 4];

R: matrix data structure, = matrix(c(1, 2, 3, 4), nrow=2, ncol=2)

Python: list of lists (with numeric values), = [[1, 2], [3, 4]]

Matlab: two-dimensional array of numeric values

 

 

 


 

Related statements

 

VAL, SERIES, LIST, SHEET