Saltar al contenido principal

Funciones sobre estructuras de álgebra lineal

Introducción​

Notación de vectores, matrices y tensores​

En el módulo Math, las estructuras multidimensionales no solo se necesitan para cálculos, sino que son también un posible tipo de resultado de funciones que no devuelven un único valor escalar. Un ejemplo son las funciones de cadenas de texto que buscan determinados patrones en un texto. Todas las posiciones y longitudes de los resultados se devuelven entonces en una matriz.

En principio, los vectores, las matrices y los tensores pueden crearse en el módulo Math mediante la sintaxis [ ... ]. Son posibles todos los tipos de datos numéricos, pero no <str>. Como elementos pueden utilizarse términos, constantes o también contenidos de otras variables. El tipo de datos de la estructura es siempre aquel en el que todos los elementos pueden representarse de la mejor manera posible.

Algunos ejemplos son:

num = 3.14159; // example for a variable as source
vec = [1, -2, false, num, 5];     // data type is <dbl> to represent num
mat = [ [ 1.1, num ] // 1st row
, [-num, 2.2 ] // 2nd row
, [ 3.1, 3.2 ] ]; // 3rd row
ten = [ [ [ 111, num, 113 ] // 1st matrix, first row
, [ 121, 122, 123 ] ] // second row
, [ [ 211, 212, 213 ] // 2nd matrix, first row
, [ 221, 222, num ] ] // second row
, [ [ 311, 312, 313 ] // 3rd matrix, first row
, [ 321, num, 323 ] ] // second row
, [ [ num, 412, 413 ] // 4th matrix, first row
, [ 421, 422, 423 ] ] ]; // second row

Siempre que los subelementos (filas de una matriz, matrices de un tensor) tengan el mismo tamaño, el tamaño de la estructura queda determinado únicamente por el número de elementos y subelementos. En el ejemplo, vec tiene 5 elementos (según el uso, en filas o columnas), mat tiene 3 filas y 2 columnas y ten tiene 4 láminas de matriz con 2 filas y 3 columnas cada una. Las diferencias de tamaño se notifican como error durante la traducción; no se realiza ningún relleno automático (padding).

Acceso a elementos individuales​

Un elemento de un vector, de una matriz o de un tensor también se direcciona mediante la sintaxis [ ... ], donde los índices (como es habitual en los lenguajes de programación) empiezan siempre en 0. Los índices también pueden proceder de variables o de cálculos.

v_num = vec[3]; // liest das 4. Element des Vektors
m_num = mat[0, 1]; // liest in der 1. Zeile das 2. Element
t_422 = ten[3, 1, 1]; // liest aus der 4. Matrix, 2. Zeile, 2. Spalte

Operaciones elementales sobre objetos multidimensionales​

Las siguientes operaciones están implementadas directamente en la notación habitual de fórmulas:

  • La comparación == y != es posible sobre objetos multidimensionales, siempre que ambos operandos tengan el mismo tamaño.

  • La suma y la resta de objetos multidimensionales son posibles, siempre que ambos operandos tengan el mismo tamaño.

    M_Sum = M_1 + M_2;
    M_Dif = M_1 - M_2;
  • Multiplicación de un objeto multidimensional por un escalar numérico. El resultado es un objeto de las mismas dimensiones en el que cada elemento individual está escalado en consecuencia. Es aplicable la ley conmutativa.

    M_Scaled_0 = M_Base * 2.56;
    M_Scaled_1 = 2.56 * M_Base;
    • División de un objeto multidimensional por un escalar numérico. El resultado es un objeto de las mismas dimensiones en el que cada elemento individual está escalado en consecuencia. La división por una matriz o un vector no está permitida.
    M_Scaled_2 = M_Base / 2.56;
  • La multiplicación de dos objetos multidimensionales es posible, siempre que el número de columnas del primero coincida con el número de filas del segundo operando. El resultado es un objeto multidimensional con el número de filas del primer operando y el número de columnas del segundo. Aquí, un vector no distingue entre filas y columnas, de modo que como primer operando se interpreta como vector fila y como segundo operando como vector columna. Esto cubre con seguridad el 95 % de la interpretación habitual en aplicaciones técnicas, sin tener que trabajar con una función de transposición.

    M_mult = M_1 * M_2;
    V_row = V_1 * M; // V_1 interpreted as row-vector
    V_col = M * V_2; // v_2 interpreted as column-vector
    ScalarProduct = V_1 * V_2; // by definition
    CrossProduct = Cross(V_1, V_2); // := V_1 x V_2

Asignación de un vector, de una matriz o de un tensor​

En principio, una variable solo puede escribirse o crearse en un único punto del conjunto de fórmulas. Esto se aplica igualmente a vectores, matrices y tensores.

Sin embargo, existe aquí la posibilidad de escribir indirectamente elementos individuales de la estructura en esta asignación. En este caso, el acceso indexado a un elemento debe aparecer en el texto de la fórmula después de la asignación propiamente dicha de la estructura, para que el compilador pueda incorporar la asignación del elemento a la asignación de la estructura completa.

Las referencias circulares no están permitidas.

M_spare = Matrix(3, 3); // erzeugt zunächst eine 3x3 Matrix mit 0
M_spare[0,1] = 101; // ergänzt die erste Zuweisung für Element [0,1]
M_spare[1,2] = 202;       // ergänzt die erste Zuweisung für Element [1,2] 
M_spare[2,0] = 303;       // ergänzt die erste Zuweisung für Element [2,0] 

Siempre que se utilice la matriz M_spare, tendrá ahora el siguiente contenido:

MSpare=[010100020230300]M_{\rm{Spare}} = \left[ \begin{array}{ccc} 0&101&0\\ 0&0&202\\ 303&0&0 \end{array} \right]

Esta notación mejora la legibilidad del texto de la fórmula, especialmente en el caso de matrices o vectores dispersos.

u_long = Vector(50, 3.14);           // create a very long vector
u_long[ 3] = -3.14;
u_long[25] = -3.14;
u_long[44] = u_long[10] + u_long[11];    // not allowed !!!

Para la actualización temporal del vector, todas las fuentes de datos tienen la misma consideración. Por tanto, el valor del vector completo cambia siempre que cambia al menos un elemento. No existe un "estado intermedio" en el que la asignación de los elementos aún no se haya realizado o se haya realizado solo parcialmente.

Exportación de partes de un objeto multidimensional​

Para extraer una parte determinada de un objeto multidimensional pueden utilizarse las funciones GetCol(), GetRow() o GetSlice(). Así, de una matriz se puede exportar una fila o columna determinada, o de un tensor con varias láminas de matriz, una matriz individual. GetSub() permite la exportación arbitraria de un área definida en cada dimensión por un rango de índices de filas/columnas/láminas.

Funciones​

Construcción de vectores "Vector"​

Las siguientes funciones pueden utilizarse para construir un vector

u = Vector(size); // Mit 0 initialisierter Vektor der Dimension size x 1
u = Vector(size, v); // Mit v initialisierter Vektor der Dimension size x 1

La orientación del vector como vector fila o vector columna no está fijada y se interpreta de la mejor manera posible en cada uso.

Vector unitario "Normalize"​

Con la función Normalize() se determina un vector unitario para el vector dado.

e⃗=v⃗∣∣v⃗∣∣\vec{e}=\frac{\vec{v}}{||\vec{v}||}

Si el módulo del vector es cero, se devuelve un vector nulo o el valor de sustitución v⃗0\vec{v}_0, para que los pasos de cálculo posteriores no se bloqueen.

ev1 = Normalize(v);
ev2 = Normalize(v, v0);

Construcción de matrices "Matrix"​

Las siguientes funciones pueden utilizarse para construir una matriz

A = Matrix(rows, columns); // Mit 0 initialisierte Matrix der Dimensionen rows x columns
B = Matrix(rows, columns, v); // Mit v initialisierte Matrix der Dimensionen rows x columns

Matriz identidad "MIdent"​

La siguiente función devuelve una matriz identidad de dimensiones size x size

I = MIdent(size);
I=[10⋯001⋱⋮⋮⋱⋱00⋯01]I = \left[ {\begin{array}{cccc} 1&0& \cdots &0\\ 0&1& \ddots & \vdots \\ \vdots & \ddots & \ddots &0\\ 0& \cdots &0&1 \end{array}} \right]

Matriz de rotación "MRot"​

Es posible definir matrices de rotación de los siguientes tipos

R_2 = MRot(alpha); // 2D-Rotationsmatrix um den Winkel alpha gegen den Uhrzeigersinn
R_3 = MRot(alpha, axis); // 3D-Rotationsmatrix um die mit axis bezeichnete Achse: x:0, y:1, z:2
M_3ypr = MRotYPR(y,p,r); // 3D-Rotationsmatrix, die eine durch Yaw, Pitch und Roll
// beschriebene Rotation beschreibt
M_3euler = MRotEuler(a,b,g); // 3D-Rotationsmatrix, die eine durch a, b, g beschriebene
// Euler-Rotation beschreibt

Con

  • cα=cos(α)c\alpha = cos(\alpha) y

  • sα=sin(α)s\alpha = sin(\alpha) se tiene

MRot(α)=[cα−sαsαcα]MRot(\alpha) = \left[ {\begin{array}{cc} c\alpha & -s\alpha\\ s\alpha & c\alpha \end{array}} \right] MRot(α,0)=[1.00.00.00.0cα−sα0.0sαcα]MRot(\alpha, 0) = \left[ {\begin{array}{ccc} 1.0 & 0.0 & 0.0 \\ 0.0 & c\alpha & -s\alpha\\ 0.0 & s\alpha & c\alpha \end{array}} \right] MRot(α,1)=[cα0.0sα0.01.00.0−sα0.0cα]MRot(\alpha, 1) = \left[ {\begin{array}{ccc} c\alpha & 0.0 & s\alpha \\ 0.0 & 1.0 & 0.0\\ -s\alpha & 0.0 & c\alpha \end{array}} \right] MRot(α,2)=[cα−sα0.0sαcα0.00.00.01.0]MRot(\alpha, 2) = \left[ {\begin{array}{ccc} c\alpha & -s\alpha & 0.0 \\ s\alpha & c\alpha & 0.0\\ 0.0 & 0.0 & 1.0 \end{array}} \right]

Véase también: Matriz de rotación – Wikipedia

Con

  • cψ=cos(ψ)c\psi=cos(\psi), sψ=sin(ψ)s\psi=sin(\psi) (Yaw),
  • cθ=cos(θ)c\theta=cos(\theta), sθ=sin(θ)s\theta=sin(\theta) (Pitch) y
  • cϕ=cos(ϕ)c\phi=cos(\phi), sϕ=sin(ϕ)s\phi=sin(\phi) (Roll) se tiene
MRotYPR(ψ,θ,ϕ)=[cθ⋅cψsϕ⋅sθ⋅cψ−cϕ⋅sψcϕ⋅sθ⋅cψ+sϕ⋅sψcθ⋅sψsϕ⋅sθ⋅sψ+cϕ⋅cψcϕ⋅sθ⋅sψ−sϕ⋅cψ−sθsϕ⋅cθcϕ⋅cθ]\rm{MRotYPR}(\psi,\theta,\phi) = \left[ {\begin{array}{ccc} c\theta \cdot c\psi & s\phi \cdot s\theta \cdot c\psi - c\phi \cdot s\psi & c\phi \cdot s\theta \cdot c\psi + s\phi \cdot s\psi \\ c\theta \cdot s\psi & s\phi \cdot s\theta \cdot s\psi + c\phi \cdot c\psi & c\phi \cdot s\theta \cdot s\psi - s\phi \cdot c\psi \\ - s\theta & s\phi \cdot c\theta & c\phi \cdot c\theta \end{array}} \right]

Véase también: Ángulos de Euler

Con

  • cα=cos(α)c\alpha=cos(\alpha), sα=sin(α)s\alpha=sin(\alpha) (input Z-axis),
  • cβ=cos(β)c\beta=cos(\beta), sβ=sin(β)s\beta=sin(\beta) (node line, rotated X-axis) y
  • cγ=cos(γ)c\gamma=cos(\gamma), sγ=sin(γ)s\gamma=sin(\gamma) (output Z-axis) se tiene
MRotEuler(α,β,γ)=[cα⋅cγ−sα⋅cβ⋅sγ−cα⋅sγ−sα⋅cβ⋅cγsα⋅sβsα⋅cγ+cα⋅cβ⋅sγ−sα⋅sγ+cα⋅cβ⋅cγ−cα⋅sβsβ⋅sγsβ⋅cγcβ]\rm{MRotEuler}(\alpha,\beta,\gamma) = \left[ {\begin{array}{ccc} c\alpha \cdot c\gamma - s\alpha \cdot c\beta \cdot s\gamma& - c\alpha \cdot s\gamma - s\alpha \cdot c\beta \cdot c\gamma& s\alpha \cdot s\beta \\ s\alpha \cdot c\gamma + c\alpha \cdot c\beta \cdot s\gamma& - s\alpha \cdot s\gamma + c\alpha \cdot c\beta \cdot c\gamma& - c\alpha \cdot s\beta \\ s\beta \cdot s\gamma & s\beta \cdot c\gamma & c\beta \end{array}} \right]

Véase también: Ángulos de Euler

Construcción de tensores "Tensor"​

Para construir un tensor con slices láminas de dimensión rows x columns se utiliza

T = Tensor(slices, rows, columns);

Propiedades de vectores, matrices y tensores​

Comprobación del tipo de una variable "isScalar", "isVector", "isMatrix", "isTensor"​

Las siguientes funciones devuelven respectivamente un true si la variable posee la estructura consultada. Esto puede ser útil cuando una función, p. ej., sFind(), devuelve tanto un escalar (-1, no encontrado) como una matriz con resultados y el procesamiento posterior depende de ello.

test1 = isScalar(var);
test2 = isVector(var);
test3 = isMatrix(var);
test4 = isTensor(var);

Consulta de las dimensiones de un objeto "SizeOf"​

La consulta de las dimensiones de un objeto devuelve un vector de dimensiones, p. ej.

VectorSize = SizeOf(v); // => [ 1, size ]
MatrixSize = SizeOf(M); // => [ 2, columns, rows]
TensorSize = SizeOf(T); // => [ 3, columns, rows, slices ]

En él, el primer componente devuelve el número de dimensiones y los siguientes, el número de elementos en la dimensión respectiva.

Funciones de acceso "GetCol", "GetRow", "GetSlice", "GetSub"​

consejo

Estas funciones sirven para recortar partes de un objeto multidimensional, de modo que, por lo general, resulte de nuevo un objeto multidimensional. Para el acceso a un elemento individual es más eficaz utilizar la sintaxis de índices.

La sección de un objeto multidimensional en un índice de columna columnIndex determinado puede realizarse de la siguiente manera

v1 = GetCol(D, columnIndex);
v2 = GetCol(D, {...}); // Konfiguration verpflichtend!
// Konfiguration für alle Varianten
vx = GetCol(..., { col: <uint> // verpflichtend, falls kein columnIndex
, rBeg: <uint>
, rEnd: <uint>
, sBeg: <uint>
, sEnd: <uint>
});

Para un vector, el resultado es un elemento individual; para una matriz, un vector; y para un tensor, una matriz en el índice de columna indicado. En estructuras de orden superior, las áreas copiadas también pueden restringirse mediante el objeto de configuración.

PropiedadValorDescripción
col<uint>Índice de columna para el plano de corte
rBeg<uint>Indicación opcional de rango para filas
rEnd<uint>Indicación opcional de rango para filas
sBeg<uint>Indicación opcional de rango para láminas
sEnd<uint>Indicación opcional de rango para láminas

La sección de un objeto multidimensional en un índice de fila determinado puede realizarse de la siguiente manera

v1 = GetRow(D, rowIndex);
v2 = GetRow(D, {...});               // Konfiguration verpflichtend!
// Konfiguration für alle Varianten
vx = GetRow(..., { cBeg: <uint>
, cEnd: <uint>
, row: <uint> // verpflichtend, falls kein rowIndex
, sBeg: <uint>
, sEnd: <uint>
});

Para un vector, el resultado es un elemento individual; para una matriz, un vector; y para un tensor, una matriz en el índice de fila indicado. En estructuras de orden superior, las áreas copiadas también pueden restringirse mediante el objeto de configuración.

PropiedadValorDescripción
row<uint>Índice de fila para el plano de corte
cBeg<uint>Indicación opcional de rango para columnas
cEnd<uint>Indicación opcional de rango para columnas
sBeg<uint>Indicación opcional de rango para láminas
sEnd<uint>Indicación opcional de rango para láminas

La sección de un objeto multidimensional en un índice de lámina determinado puede realizarse de la siguiente manera

v1 = GetSlice(D, sliceIndex);
v2 = GetSlice(D, {...});                // Konfiguration verpflichtend!
// Konfiguration für alle Varianten
vx = GetSlice(..., { cBeg: <uint>
, cEnd: <uint>
, rBeg: <uint>
, rEnd: <uint>
, slice:<uint> // verpflichtend, falls kein sliceIndex
});

Para un vector, el resultado es un elemento individual; para una matriz, un vector; y para un tensor, una matriz en el índice de lámina indicado. En estructuras de orden superior, las áreas copiadas también pueden restringirse mediante el objeto de configuración.

PropiedadValorDescripción
slice<uint>Índice de lámina para el plano de corte
cBeg<uint>Indicación opcional de rango para columnas
cEnd<uint>Indicación opcional de rango para columnas
rBeg<uint>Indicación opcional de rango para filas
rEnd<uint>Indicación opcional de rango para filas

La extracción de una subestructura de datos de una estructura de datos se realiza de la siguiente manera

D1 = GetSub(D, { cBeg: <uint>
, cEnd: <uint>
, rBeg: <uint>
, rEnd: <uint>
, sBeg: <uint>
, sEnd: <uint>
});
PropiedadValorDescripción
cBeg<uint>Indicación opcional de rango para columnas
cEnd<uint>Indicación opcional de rango para columnas
rBeg<uint>Indicación opcional de rango para filas
rEnd<uint>Indicación opcional de rango para filas
sBeg<uint>Indicación opcional de rango para láminas
sEnd<uint>Indicación opcional de rango para láminas

Funciones de procesamiento​

Transposición "Trans"​

La transposición de una matriz M x N devuelve una matriz N x M en la que se intercambian filas y columnas, y se calcula de la siguiente manera

A_t = Trans(A);
A=[a11a12⋯a1N⋮⋱⋱⋮aM1aM2⋯aMN],AT=[a11⋯aM1a12⋱aM2⋮⋱⋮a1N⋯aMN]A = \left[\begin{array}{cccc} {{a_{11}}}&{{a_{12}}}& \cdots &{{a_{1N}}}\\ \vdots & \ddots & \ddots & \vdots \\ {{a_{M1}}}&{{a_{M2}}}& \cdots &{{a_{MN}}} \end{array}\right],A^T = \left[ \begin{array}{ccc} {{a_{11}}}& \cdots &{{a_{M1}}}\\ {{a_{12}}}& \ddots &{{a_{M2}}}\\ \vdots & \ddots & \vdots \\ {{a_{1N}}}& \cdots &{{a_{MN}}} \end{array}\right]

Producto vectorial "Cross"​

El producto vectorial de dos vectores u y v de longitud 2 o 3 devuelve un vector perpendicular a ambos, con la longitud del área abarcada por los dos vectores, y se calcula de la siguiente manera

w = Cross(u, v);
w⃗=[uxuyuz]×[vxvyvz]=[uyvz−uzvyuzvx−uxvzuxvy−uyvx]\vec{w}=\left[ {\begin{array}{c} {{u_x}}\\ {{u_y}}\\ {{u_z}} \end{array}} \right] \times \left[ {\begin{array}{c} {{v_x}}\\ {{v_y}}\\ {{v_z}} \end{array}} \right] = \left[ {\begin{array}{c} {{u_y}{v_z} - {u_z}{v_y}}\\ {{u_z}{v_x} - {u_x}{v_z}}\\ {{u_x}{v_y} - {u_y}{v_x}} \end{array}} \right]

Descomposición LU "LUDecomp"​

La descomposición LU de una matriz M devuelve una matriz triangular inferior L y una matriz triangular superior U en forma de un tensor con dos láminas, y puede realizarse de la siguiente manera

T = LUDecomp(M);
L = GetSlice(T, 0);
U = GetSlice(T, 1);

Determinante "Det"​

El determinante d de una matriz cuadrada M puede calcularse de la siguiente manera

d = Det(M);

Longitud del vector "Length"​

Cálculo de la longitud de un vector; véase también abs(...)

len = Length(v);
len=v02+v12+...+vn−12len = \sqrt{v_0^2 + v_1^2 + ... + v_{n-1}^2}