\chapter{Матрицы}
\label{chap:matrices}

Матрицы представляют собой одно- или двумерные массивы чисел с
плавающей точкой двойной точности. Пользователи Hansl, привыкшие к
другим языкам матриц, должны учитывать, что многоиндексные объекты не
поддерживаются. В матрицах есть лишь строки и столбцы.

\section{Индексация матрицы}
\label{sec:mat-index}

Доступ к отдельным элементам матрицы осуществляется через синтаксис
\verb|[r,c]|, где индексирование начинается с 1. Например,
\texttt{X[3,4]} указывает элемент $X$ в третьей строке четвертого
столбца. Для иллюстрации примера осуществим следующие действия:
\begin{code}
  matrix X = zeros(2,3)
  X[2,1] = 4
  print X
\end{code}
в результате приводит к 
\begin{code}
X (2 x 3)

  0   0   0 
  4   0   0 
\end{code}

Вот еще несколько дополнительных способов доступа к элементам матрицы:
\begin{enumerate}
\item Если матрица имеет только одну строку (столбец), спецификацию
  столбца (строки) можно не указывать, как в \texttt{x[3]}.
\item Включение запятой без указания строки или столбца означает
  «взять их все», как в \texttt{x[4,]} (четвертая строка, все
  столбцы).
\item Для квадратных матриц можно использовать специальный синтаксис
  \texttt{x[diag]} для доступа к диагонали.
\item Последовательные строки или столбцы могут быть указаны с помощью
  символа двоеточия (\texttt{:}), как в \texttt{x[,2:4]} (столбцы со 2
  по 4).  Обратите внимание на то, что, в отличие от некоторых других
  языков, синтаксис \texttt{[m:n]} здесь недопустим, если $m>n$.
\item Можно использовать вектор для хранения индексов
  матрицы. Например. если $e = [2,3,6]$, то \texttt{X[,e]} содержит
  второй, третий и шестой столбцы $X$.
\end{enumerate}
Более того, матрицы могут быть пустыми (нулевые строки и столбцы).  В
приведенном выше примере матрица \texttt{X} была построена с помощью
функции \texttt{zeros()}, смысл которой должен быть очевидным, но
элементы матрицы также могут быть указаны напрямую, как в
\begin{code}
scalar a = 2*3
matrix A = { 1, 2, 3 ; 4, 5, a }
\end{code}
Матрица определяется строками; элементы в каждой строке разделяются
запятыми, а строки отделяются точкой с запятой. Все выражение должно
быть заключено в фигурные скобки. Пробелы внутри скобок не имеют
значения. Вышеприведенное выражение определяет матрицу $2\times3$.

Важно отметить, что каждый элемент должен быть числовым значением,
именем скалярной переменной или выражением, которое оценивается как
скаляр. В приведенном выше примере скаляру \texttt{a} сначала было
присвоено значение, а затем он используется при построении
матриц. (Также обратите внимание, что \texttt{a} и \texttt{A} --- это
два отдельных идентификатора, так как в Gretl есть чувствительность к
регистру).

\section{Матричные операции}
\label{sec:mat-op}

Сумма матриц, их разность и произведение получаются через \texttt{+},
\texttt{-} и \texttt{*}, соответственно. Главный оператор (\texttt{'})
Может действовать или как унарный оператор, и в этом случае он
заменяет предыдущую матрицу; или как двоичный оператор, и в этом
случае он действует как в обычной матричной алгебре, умножая
транспонирование первой матрицы на вторую.\footnote{Фактически, в этом
  случае используется оптимизированный алгоритм; поэтому всегда
  необходимо использовать \texttt{a'a} вместо \texttt{a'*a} для
  достижения максимальной точности и производительности.}  Ошибки
появляются, если существует проблема согласованности матриц. Например:
\begin{code}
  matrix a = {11, 22 ; 33, 44}  # a квадратная 2 x 2
  matrix b = {1,2,3; 3,2,1}     # b имеет размер 2 x 3

  matrix c = a'         # c это транспонированная a
  matrix d = a*b        # d имеет размер 2x3 и равна a на b

  matrix gina = b'd     # верно: gina имеет размер 3x3
  matrix lina = d + b   # верно: lina имеет размер 2x3

  /* -- приведет к ошибкам, если раскомментировать ----- */

  # pina = a + b  # сумма несоответствия
  # rina = d * b  # произведение несоответствия
\end{code}

Другие заслуживающие внимания матричные операторы включают \texttt{\^}
(степень матрицы), \texttt{**} (произведение Кронекера) и операторы
«конкатенации», \verb|~| (горизонтальные) и \texttt{|}
(вертикальный). Читателям предлагается опробовать их через следующий
код:
\begin{code}
matrix A = {2,1;0,1}
matrix B = {1,1;1,0}
matrix KP = A ** B
matrix PWR = A^3 
matrix HC = A ~ B
matrix VC = A | B

print A B KP PWR HC VC
\end{code}
Обратите внимание, в частности, что $A^3 = A \cdot A \cdot A$, и
результат отличается от того, который вы получаете, возводя в третью
стерень каждый элемент $A$ отдельно. Hansl также поддерживает левое и
правое «деление» матриц с помощью операторов \verb'\' и \verb'/'
соответственно. Выражение \verb|A\b| решает уравнение $Ax = b$ для
неизвестного $x$. Предполагается, что $A$ --- это матрица размера
$m \times n$ с полным рангом столбца. Если $A$ квадратная, то
применяется метод LU-разложения. Если $m > n$, QR-разложение
используется для поиска решения с помощью метода наименьших
квадратов. В большинстве случаев это численно более надежно и
эффективно, чем явное инвертирование $A$.  Поэлементные операции
поддерживаются так называемыми «точечными» операторами, которые
получаются, если поставить точку (``\texttt{.}'') перед
соответствующим оператором. Например, код
\begin{code}
A = {1,2; 3,4}
B = {-1,0; 1,-1}
eval A * B
eval A .* B
\end{code}
приведет к такому результату
\begin{code}
   1   -2 
   1   -4 
  -1    0 
   3   -4 
\end{code}

Легко проверить, что первая выполняемая операция --- это обычное
умножение матриц $A \cdot B$, тогда как вторая --- произведение Адамара
(поэлементное). Фактически, точечные операторы являются более общими и
мощными, чем показано в примере выше; см. главу о матрицах в
Руководстве пользователя \GUG{}.  Операторы точки и конкатенации менее
жесткие, чем обычные матричные операции с точки зрения требований
согласованности: в большинстве случаев Hansl будет пытаться сделать
«очевидное». Например, общая вещь для Hansl --- это \texttt{Y = X ./ w},
где $X$ --- это матрица размера $n \times k$, а $w$ --- вектор размера
$n \times 1$. Результатом для $Y$ будет матрица размера $n \times k$,
в которой каждая строка $X$ делится на соответствующий элемент $w$.  В
правильных матричных обозначениях эту операцию следует записать как
\[
  Y = \langle w \rangle^{-1} X,
\]
где $\langle \cdot \rangle$ обозначает диагональную
матрицу. Буквальный перевод приведенного выше выражения означал бы
создание диагональной матрицы из $w$, а затем ее инвертирование, что в
вычислительном отношении намного сложнее, чем использование точечной
операции. Подробное обсуждение этого момента приведено в Руководстве
пользователя \GUG.  Hansl предоставляет достаточно полный набор
матричных функций, то есть функций, которые производят и / или
работают с матрицами. Полный список см. в Справочнике по командам, но
в основном необходимый комплект для «выживания» приведен в таблице
~\ref{tab:essential-matfuncs}. Более того, большинство скалярных
функций, таких как \texttt{abs(), log()} и т. д. работают с матрицами
поэлементно.

\begin{table}[htbp]
  \centering
  \small
  \begin{tabular}{rp{0.6\textwidth}}
    \textbf{Функция(и)} & \textbf{Задача} \\
    \hline
    \texttt{rows(X), cols(X)} & вернуть  соответственное  количество строк и столбцов $X$ \\
    \texttt{zeros(r,c), ones(r,c)} & составить матрицы из $r$ строк и $c$ столбцов, наполнить нулями и единицами соответственно \\
    \texttt{mshape(X,r,c)} & переставить элементы $X$ в
    матрицу с $r$ строками и $c$ столбцами \\
    \texttt{I(n)} & вывести единичную матрицу размера $n$ \\
    \texttt{seq(a,b)} & сгенерировать вектор-строку, содержащий целые числа от $a$ до $b$ \\
    \texttt{inv(A)} & если возможно, инвертировать матрицу $A$ \\
    \texttt{maxc(A), minc(A), meanc(A)} & составить вектор-строку с максимальным, минимальным, средним каждого столбца $A$ соответственно   \\
    \texttt{maxr(A), minr(A), meanr(A)} & составить вектор-столбец с максимальным, минимальным, средним каждой строки $A$ соответственно \\
    \texttt{mnormal(r,c), muniform(r,c)} & сгенерировать $r \times c$   матрицы, заполненные стандартными гауссовыми и однородными псевдослучайными
  числами соответственно \\
    \hline
  \end{tabular}
  \caption{Основной набор матричных функций Hansl}
  \label{tab:essential-matfuncs}
\end{table}

Следующий фрагмент кода предназначен для краткого примера всех
вышеупомянутых функций.

\begin{code}
# пример: OLS с использованием матриц

# установить размер выборки:
scalar T = 256

# построить вектор коэффициентов путем прямого удаления 
matrix beta = {1.5, 2.5, -0.5} # прим.: вектор-строка

# построить матрицу независимых переменных
matrix Z = mnormal(T, cols(beta)) # встроенные функции

# построить завис.переменную: внимательно см. на
# использование "точечных" и транспонир. операторов

matrix y = {1.2} .+ Z*beta' + mnormal(T, 1)

# оценить
matrix X = 1 ~ Z  # оператор конкатенации
matrix beta_hat1 = inv(X'X) * (X'y) # OLS вручную
matrix beta_hat2 = mols(y, X)       # с помощью встроен. функции
matrix beta_hat3 = X\y              # с помощью деления матрицы

print beta_hat1 beta_hat2 beta_hat3
\end{code}

\section{Матричные указатели}
\label{sec:mat-pointers}

Для передачи параметров функциям Hansl использует соглашение «по
значению». То есть, когда переменная передается функции в качестве
аргумента, функция фактически получает копию переменной, а это
означает, что значение переменной на начальном уровне не изменяется
действиями, которые происходят внутри функции. Но использование
указателей позволяет функции и ее вызывающей стороне взаимодействовать
таким образом,что внешняя переменная может быть изменена самой
функцией.

Этот механизм используется некоторыми встроенными матричными функциями
для предоставления более одного «возвращаемого» значения. Первичный
результат всегда обеспечивается собственно возвращаемым значением, но
некоторые вспомогательные значения могут извлекаться с помощью
«указателей» аргументов; это использование отмечается добавлением
символа амперсанда ``\texttt{\&}'' перед именем переменной аргумента.

Функция \texttt{eigensym}, которая выполняет собственный анализ
симметричных матриц, иллюстрирует вышеуказанное объяснение. В
приведенном ниже примере первый аргумент $A$ представляет входные
данные, то есть матрицу, для которой требуется провести анализ. Эта
переменная вообще не будет изменена при вызове функции. Первичным
результатом является вектор собственных значений оператора $A$,
который здесь присваивается переменной \texttt{ev}. Второй
(необязательный) аргумент \texttt{\&V} (который можно читать как
«адрес \texttt{V}») используется для получения правых собственных
векторов $A$. Переменная, названная таким образом, должна быть задана,
но она необязательно должна иметь требуемый размер для получения
результата, т.к. она будет изменена по мере необходимости.
\begin{code}
matrix A = {1,2 ; 2,5}
matrix V
matrix ev = eigensym(A, &V)
print A ev V
\end{code}

%%% Local Variables: 
%%% mode: latex
%%% TeX-master: "hansl-primer"
%%% End: 
