Saltar al contenido principal
LibreTexts Español

5.3: Matrices de doble índice

  • Page ID
    87468
  • \( \newcommand{\vecs}[1]{\overset { \scriptstyle \rightharpoonup} {\mathbf{#1}} } \)

    \( \newcommand{\vecd}[1]{\overset{-\!-\!\rightharpoonup}{\vphantom{a}\smash {#1}}} \)

    \( \newcommand{\id}{\mathrm{id}}\) \( \newcommand{\Span}{\mathrm{span}}\)

    ( \newcommand{\kernel}{\mathrm{null}\,}\) \( \newcommand{\range}{\mathrm{range}\,}\)

    \( \newcommand{\RealPart}{\mathrm{Re}}\) \( \newcommand{\ImaginaryPart}{\mathrm{Im}}\)

    \( \newcommand{\Argument}{\mathrm{Arg}}\) \( \newcommand{\norm}[1]{\| #1 \|}\)

    \( \newcommand{\inner}[2]{\langle #1, #2 \rangle}\)

    \( \newcommand{\Span}{\mathrm{span}}\)

    \( \newcommand{\id}{\mathrm{id}}\)

    \( \newcommand{\Span}{\mathrm{span}}\)

    \( \newcommand{\kernel}{\mathrm{null}\,}\)

    \( \newcommand{\range}{\mathrm{range}\,}\)

    \( \newcommand{\RealPart}{\mathrm{Re}}\)

    \( \newcommand{\ImaginaryPart}{\mathrm{Im}}\)

    \( \newcommand{\Argument}{\mathrm{Arg}}\)

    \( \newcommand{\norm}[1]{\| #1 \|}\)

    \( \newcommand{\inner}[2]{\langle #1, #2 \rangle}\)

    \( \newcommand{\Span}{\mathrm{span}}\) \( \newcommand{\AA}{\unicode[.8,0]{x212B}}\)

    \( \newcommand{\vectorA}[1]{\vec{#1}}      % arrow\)

    \( \newcommand{\vectorAt}[1]{\vec{\text{#1}}}      % arrow\)

    \( \newcommand{\vectorB}[1]{\overset { \scriptstyle \rightharpoonup} {\mathbf{#1}} } \)

    \( \newcommand{\vectorC}[1]{\textbf{#1}} \)

    \( \newcommand{\vectorD}[1]{\overrightarrow{#1}} \)

    \( \newcommand{\vectorDt}[1]{\overrightarrow{\text{#1}}} \)

    \( \newcommand{\vectE}[1]{\overset{-\!-\!\rightharpoonup}{\vphantom{a}\smash{\mathbf {#1}}}} \)

    \( \newcommand{\vecs}[1]{\overset { \scriptstyle \rightharpoonup} {\mathbf{#1}} } \)

    \( \newcommand{\vecd}[1]{\overset{-\!-\!\rightharpoonup}{\vphantom{a}\smash {#1}}} \)

    Concepto

    Las matrices de doble índice (y más generalmente, las matrices multi-índice), son extremadamente importantes en la implementación de métodos numéricos. Sin embargo, conceptualmente, son bastante similares a las matrices singleindex, y en la medida en que esta sección puede ser bastante corta: solo consideramos la “innovación diferencial”. De hecho, como veremos en breve, una matriz de doble índice realmente es una matriz de índice único en cuanto a representación interna en memoria o “espacio de direcciones”: los dos índices son solo una forma conveniente de acceder a una matriz de índice único.

    La referencia por dos índices (o tres índices,...) puede ser conveniente por diversas razones: en una malla rectilínea\(10 \times 10\) estructurada, los dos índices podrían representar la ubicación de un punto en una cuadrícula “cartesiana” -en la que almacenamos, en cada ubicación de matriz, digamos el valor del campo de temperatura (a \(10 \times 10\)matriz); en una malla tridimensional no estructurada (o una muestra aleatoria de Monte Carlo), el primer índice podría representar la etiqueta/orden de un punto dentro de una muestra de, por ejemplo, 1000 longitud, y el segundo índice podría representar la dirección de coordenadas espaciales (por ejemplo,\(1,2,3\) para el \(x, y, z\)direcciones) - en la que almacenamos, en las ubicaciones de la matriz, la coordenada del punto (una\(1000 \times 3\) matriz); y más notablemente, los dos índices podrían representar las filas y columnas de una\(m \times n\) matriz - en la que almacenamos los valores de la matriz (un \(m \times n\)matriz). (Discutimos las matrices en profundidad más adelante.) Recordemos que los índices juegan el papel de la variable independiente y la matriz valora el papel de la variable dependiente.

    Para una matriz de doble índice, al igual que para una matriz de índice único, primero introducimos un nombre de variable, array_name, pero ahora esta matriz de doble índice está asociada a\(m \times n\) elementos: podemos pensar en una matriz de doble índice como\(m\) filas por\(n\) columnas, como lo haremos visualizar en breve. Luego indexamos este array_name para acceder a cualquier elemento particular de la matriz: en particular, array_name\((i, j)\) es el puntero al elemento\(i, j\) de la matriz. Como siempre, el puntero es la ubicación en la memoria en la que almacenamos el valor de la matriz.

    De hecho, incluso esta matriz de doble índice se almacena en ubicaciones contiguas en la memoria. (Es en este sentido que una matriz de doble índice es internamente equivalente a una matriz de índice único; aprovecharemos esta equivalencia más adelante). MATLAB almacena una matriz de doble índice como “first address fastest”: array_name\((1,1), \ldots\), array_name\((\mathrm{m}, 1)\), array_name, array_name\((1,2), \ldots\), array_name\((\mathrm{m}, 2), \ldots\), array_name\((\mathrm{m}, \mathrm{n})\). En cuanto al caso de índice único, basta con pasar a una función simplemente la variable array_name -la dirección del primer elemento- ya que las direcciones de todos los demás elementos se pueden deducir fácilmente (en la práctica, gracias a la información de cabecera apropiada). Y por supuesto, en cuanto a una matriz de índice único, trataremos de definir de manera similar operaciones en toda la matriz, tal como se representa por array_name, en lugar de tratar cada índice por separado.

    Una nota sobre nomenclatura: también podemos pensar en matrices de índice único y doble índice como matrices “onedimensionales” y “bidimensionales”. Sin embargo, reservaremos “dimensión” para el sentido álgebra lineal: un vector con\(n\) entradas es miembro del espacio\(n\) -dimensional. De ahí que la “dimensión” del álgebra lineal sea análoga a la longitud de MATLAB. (Y solo para asegurarse de que este párrafo, al intentar evitar confusiones, sea lo suficientemente confuso: para evitar la confusión de la longitud de MATLAB con la “longitud” del álgebra lineal de un vector nos referiremos a este último como la “norma” del vector. Volvemos a este punto en la Unidad 3.)

    Asignación y Acceso

    Comenzamos con un ejemplo sencillo y luego explicamos la sintaxis.

    >> A = [1,2,3;4,5,6] 
    A = 
        1 2 3 
        4 5 6 
    >> size_of_A = size(A) 
    size_of_A = 
        2 3 
    >> A(2,2) 
    ans = 
        5 
    >>
    

    Vemos que una coma separa elementos dentro de una fila, y un punto y coma separa distintas filas.

    La función size devuelve una matriz de índice único de longitud 2: el primer elemento es el número de filas - el límite para el primer índice - y el segundo elemento es el número de columnas - el límite para el segundo índice. Por último, vemos que podemos acceder a elementos individuales de\(\mathrm{A}\) as (digamos)\(\mathrm{A}(2,2)\). Por supuesto, nuestra interpretación como filas y columnas no es más que un artificio -pero un artificio muy útil que invocamos en muchas ocasiones- para la visualización e interpretación.

    Nuestra matriz de índice único de fila es un caso especial de matriz de doble índice:

    >> X = [1,3,4] 
    X = 
        1 3 4 
    >> size(X) 
    ans = 
        1 3 
    >> X(1,3) 
    ans = 
        4 
    >>
    

    Y ahora podemos introducir sistemáticamente una matriz de índice único de columna como

    >> X_col = [1;3;4] 
    X_col = 
        1 3 4 
    >> size(X_col) 
    ans = 
        3 1 
    >> X_col(3,1) 
    ans = 
        4
    >>
    

    Tenga en cuenta que en este caso cada fila es de longitud 1 por lo que no requerimos delimitadores de coma. Tenga en cuenta que las operaciones en MATLAB requieren arreglos de tamaño similar, así que siempre asegúrese de que los pares de operandos de matriz de índice único sean matrices de filas o ambas matrices de columnas. Esto se asegura mejor mediante la inicialización de la matriz con ceros y asignación consistente.

    La operación de transposición es muy conveniente: “voltea” los dos índices. De ahí

    >> A_transp = A' 
    A_transp = 
        1 4 
        2 5 
        3 6 
    >> X' 
    ans = 
        1 
        3 
        4 
    >> size(X') 
    ans = 
        3 1 
    >>
    

    Las filas se convierten en columnas y las columnas se vuelven filas. (De hecho, el operador transpose es un caso especial de una reconfiguración de la función MATLAB más general que nos permite “cambiar el tamaño” de una matriz).

    Como siempre, el lector debe anotar mentalmente el código más expandido que efectúa cualquier operación en particular para asegurarse de que la operación sea bien entendida: en este caso

    >> for i = 1:size(A,1) 
        for j = 1:size(A,2) 
            A_transp_too(j,i) = A(i,j); 
        end 
       end 
    >> A_transp_too 
    
    A_transp_too = 
        1 4 
        2 5 
        3 6 
    >>
    

    Tenga en cuenta que\(\operatorname{size}(A, 1)\) y\(\operatorname{size}(A, 2)\) convenientemente devuelva el primer elemento y el segundo elemento de tamaño (A).

    En cuanto a las matrices de índice único, podemos asignar directamente una matriz completa de doble índice: B = A crea una nueva matriz B idéntica a A en términos de tamaño así como valores; también podemos asignar o reasignar cualquier elemento particular de la matriz según lo seleccionado por el índice, por ejemplo,\((1,1)=0\) B. A menudo podemos crear la matriz deseada como una asignación más modificación de una matriz existente.

    También podemos crear una matriz con un bucle “double” for:

    >> m = 2;n = 3; 
    >> A = zeros(m,n); 
    >> for i = 1:size(A,1) 
        for j = 1:size(A,2) 
            A_too(i,j) = j + (i-1)*size(A,2); 
        end 
       end 
    >> A_too 
    A_too = 
        1 2 3 
        4 5 6 
    >>
    

    Tenga en cuenta que la inicialización de matrices de índices múltiples es particularmente importante ya que estas matrices tienden a ser más grandes y la administración de la memoria es aún más problemática.

    Sin embargo, la concatenación también funciona para matrices de índices múltiples y puede ser muy efectiva.

    >> R1 = [1,2,3]; R2 = [4,5,6]; 
    >> C1 = [1;4]; C2 = [2;5]; C3 = [3;6]; 
    >> A_too_too = [R1; R2] 
    
    A_too_too = 
        1 2 3 
        4 5 6 
    >> A_too_too_too = [C1,C2,C3] 
    
    A_too_too_too = 
        1 2 3 
        4 5 6 
    >> A_four_times = [A_too, A_too; A_too, A_too]
    
    A_four_times = 
        1 2 3 1 2 3 
        4 5 6 4 5 6 
        1 2 3 1 2 3 
        4 5 6 4 5 6 
    >> A_four_times_also = [[A_too;A_too],[A_too;A_too]] 
    
    A_four_times_also = 
        1 2 3 1 2 3 
        4 5 6 4 5 6 
        1 2 3 1 2 3 
        4 5 6 4 5 6 
    >> A_four_times_expand_by_one = [A_four_times,[C1;C2]; [R1,R2],0] 
    
    A_four_times_expand_by_one = 
        1 2 3 1 2 3 1 
        4 5 6 4 5 6 4 
        1 2 3 1 2 3 2 
        4 5 6 4 5 6 5 
        1 2 3 4 5 6 0 
    >>
    

    Los procedimientos generales para la concatenación son algo difíciles de describir sucintamente -siempre debemos combinar entidades que “coincidan” en la dirección en la que concatenamos- pero los casos anteriores incluyen la mayoría de las instancias relevantes en los métodos numéricos.

    También podemos hacer direccionamiento indirecto para matrices de doble índice, como ilustramos en nuestra matriz a_Four_times. En particular, deje que ind1vec e ind2vec sean matrices de índice único dadas por (digamos)

    >> ind1vec = [2,3] 
    ind1vec = 
        2 3 
    >> ind2vec = [2:4] 
    ind2vec = 
        2 3 4 
    >>
    

    Entonces

    >> extracted = A_four_times(ind1vec,ind2vec) 
    extracted = 
        5 6 4 
        2 3 1 
    >>
    

    que de hecho se implementa como

    >> for i = 1:length(ind1vec) 
        for j = 1:length(ind2vec) 
            extracted_too(i,j) = A_four_times(ind1vec(i),ind2vec(j)); 
        end 
       end 
    >> extracted_too 
    
    extracted_too = 
        5 6 4 
        2 3 1 
    >>
    

    Esto puede ser muy útil para extraer filas y columnas, como ahora describimos.

    En particular, para extraer digamos la fila 1 o la columna 2 de A, solo necesitamos hacer

    >> R1_too = A(1,1:size(A,2)) 
    R1_too = 
        1 2 3 
    >> C2_too = A(1:size(A,1),2) 
    C2_too = 
        2 
        5 
    >>
    

    De hecho, MATLAB proporciona convenientemente un extremo de función que, cuando aparece en el lugar del\(k^{\text {th }}\) índice\((k=1\) o\(k=2)\), evalúa a (digamos para nuestra matriz A) tamaño\((\mathrm{A}, \mathrm{k})\). Entonces podemos escribir de manera más sucinta

    >> R1_too_too = A(1,1:end) 
    R1_too_too = 
        1 2 3 
    >> R1_too_too_too = A(1,:) 
    R1_too_too_too = 
        1 2 3 
    >>
    

    donde en la última línea vemos que MATLAB admite aún más abreviatura: un dos puntos en lugar de un índice se interpreta como\(1:\) final para ese índice.

    Finalmente, hay una manera simple de crear una matriz de índice único a partir de una matriz de múltiples índices:

    >> A_single_index = A(:) 
    A_single_index = 
        1 
        4 
        2 
        5 
        3 
        6 
    >>
    

    Tenga en cuenta que probablemente no sea una buena idea aprovechar la forma de índice único anterior ya que la forma de esta matriz de índice único es bastante sensible a cómo especificamos el argumento index. (La traducción de dos puntos no es única para una matriz de índice único y de hecho se interpreta como una elección particular de remodelación). Introducimos lo anterior solo para ilustrar el concepto de “todas las matrices son realmente matrices de índice único” y el orden de “primer índice más rápido (o columna principal)”, y también porque la remodelación de un solo índice es conveniente a veces para ciertas operaciones globales (ver más abajo).

    Operaciones

    En lo que respecta a las operaciones aritméticas, las matrices multi-índice “se comportan” exactamente de la misma manera que las matrices de índice único:\(-,+, . *, . /\), - todas realizan las operaciones necesarias elemento por elemento. De hecho, en estas operaciones, la matriz de doble índice se trata esencialmente como una matriz de índice único. (Obsérvese que por ejemplo\(3.2 * \mathrm{~A}\) multiplica cada elemento de\(\mathrm{A}\) por\(3.2\).) Lo mismo es cierto para las operaciones relacionales y lógicas (así como find): las operaciones se realizan elemento por elemento y la salida es una matriz multi-índice del mismo tamaño que los dos operandos.

    Para las operaciones de datos, hay más opciones. Siempre que sea posible, lo más fácil es efectuar la operación en términos de matrices de índice único. El operador de dos puntos nos permite encontrar el mínimo sobre (digamos) la primera fila como

    >> min(A(1,:))
    ans = 
        1 
    >>
    

    o de manera similar el mínimo sobre cualquier columna dada.

    Si queremos encontrar el mínimo sobre todos los elementos de toda la matriz, podemos interpretar la matriz multi-índice en su forma de índice único “subyacente”: por ejemplo,

    >> A = [1,2,3;4,5,6] 
    A = 
        1 2 3 
        4 5 6 
    >> min(A(:)) 
    ans = 
        1 
    >>
    

    En la mayoría de los casos, los constructos simples anteriores bastan.

    Sin embargo, también es fácil aplicar (digamos) la función min sobre el primer índice para producir una matriz de filas que contenga el mínimo sobre cada columna, o realizar la función min sobre el segundo índice para producir una matriz de columnas que contenga el mínimo sobre cada fila:

    >> min(A,[],1) 
    ans =     
        1 2 3 
    >> min(A,[],2) 
    ans = 
        1 
        4 
    >>
    

    Tenga en cuenta que el segundo argumento nulo en min anterior se explicará en breve, cuando discutamos las funciones con mayor detalle. Esencialmente, min toma tres argumentos, pero el segundo argumento es opcional y, por lo tanto, si no se establece, MATLAB no se quejará. Los nulos son útiles para entradas opcionales o para entradas que se pueden establecer en valores predeterminados.

    En general, el valor predeterminado con MATLAB —cuando se aplican funciones de “índice único” a matrices multi-índice— es realizar la operación sobre columnas para producir una fila:

    >> min(A) 
    ans = 
        1 2 3 
    >>
    

    Tenga en cuenta que min no\((A)\) es lo mismo que min\((A(:))\) en que A es de tamaño\([2,3]\) mientras que\(A(:)\) se “reconfigura” automáticamente para que sea una matriz de índice único.

    Aprovechamos esta oportunidad para volver a visitar el bucle for. Digamos que deseamos encontrar el número de dos vectores en una\(2 \times m\) matriz que residen en el primer cuadrante. Podemos escribir el bucle for basado en un índice como

    twovecs = [[1;-1],[1;1],[-3;1],[.2;.5]]; 
    num_in_quad_1 = 0; 
    for j = 1:size(twovecs,2) 
        if( twovecs(1,j) >=0 && twovecs(2,j) >=0 ) 
            num_in_quad_1 = num_in_quad_1 + 1; 
        end 
    end 
    num_in_quad_1
    

    que va a funcionar bien. Sin embargo, también podemos usar para nuestro “contador” no un índice sino más bien los datos en sí, como en

    twovecs = [[1;-1],[1;1],[-3;1],[.2;.5]]; 
    num_in_quad_1 = 0; 
    for vec = twovecs; 
        if( vec(1) >= 0 && vec(2) >= 0) 
            num_in_quad_1 = num_in_quad_1 + 1;
        end 
    end 
    num_in_quad_1
    

    que también funciona bien. En esta segunda forma, dentro del bucle for, el argumento de bucle vec se establece primero en la primera columna de twovecs,\([1 ;-1]\), vec se establece luego en las segundas columnas de twovecs,\([1 ; 1]\), y así sucesivamente. Es importante tener en cuenta que, para cualquier matriz de doble índice, el argumento loop se establece en cada columna de la matriz y el bucle se ejecuta el número de veces de columna. (En particular, el comportamiento es independiente de la asignación agrupada por columnas de dos vecesutilizadas en este ejemplo). Esto también implica que, si se usa una matriz de índice único de columna para la construcción del bucle como en for\(i=[1: 10]\) ', entonces se\(i\) establecería en el vector\([1: 10]\)' y el bucle se ejecuta solo una vez. Tenga en cuenta que el comportamiento es completamente diferente del caso de proporcionar una matriz de índice único de fila, como en for\(i=1: 10\).

    Por último, este parece un buen lugar para señalar que hay muchos miles de funciones de MATLAB y para cada una muchas veces bastantes opciones y argumentos opcionales. Si encuentra que está haciendo una operación en particular relativamente simple muchas veces, o una operación bastante complicada quizás solo unas pocas veces, tal vez valga la pena buscar una función incorporada de MATLAB sintácticamente sucinta y eficiente que pueda hacer el truco. No obstante, en muchos otros casos será más efectivo escribir tu propio código. Las funciones incorporadas de МАTLAB son un medio y no un fin.


    This page titled 5.3: Matrices de doble índice is shared under a CC BY-NC-SA 4.0 license and was authored, remixed, and/or curated by Masayuki Yano, James Douglass Penn, George Konidaris, & Anthony T Patera (MIT OpenCourseWare) via source content that was edited to the style and standards of the LibreTexts platform; a detailed edit history is available upon request.