Cómo implementar eficientemente el siguiente código en MATLAB

M=50
G= randi(100,100,2);
N = 100;
iS = zeros(M,M);
for i1 = 1:M
  for i2 = 1:M
      if i1 == i2
          for g = 1:N
              iS(i1,i2) = iS(i1,i2) + eq(i1,G(g,1))+eq(i2,G(g,2));
          end
      else
          for g = 1:N
              iS(i1,i2) = iS(i1,i2)-(eq(i1,G(g,1))*eq(i2,G(g,2))+eq(i1,G(g,2))*eq(i2,G(g,1)));
          end
      end
          
  end 
end

Estoy tratando de implementar este código de manera eficiente en MATLAB. El tiempo de correr parece tomar demasiado tiempo. ¿Hay alguna manera de implementar este código de manera eficiente?

G es una matriz doble de 1000*2.

Pregunta hecha hace 3 años, 4 meses, 29 días - Por byteexplorer


3 Respuestas:

  • El bucle se puede reducir a la siguiente forma vectorizada. Tenga en cuenta que utiliza multiplicación de matriz para acelerar el cálculo.

    i1 = 1:M;
    i2 = 1:M;
    iS = -((i1 == G(:, 1)).' * (i2 == G(:, 2)) + (i1 == G(:, 2)).' * (i2 == G(:, 1)));
    iS(1:M+1:end) = sum(i1 == G(:, 1)) + sum(i2 == G(:, 2));
    

    Por última parte también se puede utilizar histcounts:

    i1 = 1:M;
    i2 = 1:M;
    iS = -((i1 == G(:, 1)).' * (i2 == G(:, 2)) + (i1 == G(:, 2)).' * (i2 == G(:, 1)));
    iS(1:M+1:end) = histcounts(G(:, 1), 1:M+1) + histcounts(G(:, 2), 1:M+1);
    

    Respondida el Dec 17, 2020 a las 18:54 - por syntaxsorcerer

    Votos positivos: 0 | Votos negativos: 0

  • Para aumentar la eficiencia de tu código en MATLAB, puedes vectorizar las operaciones en lugar de utilizar bucles anidados. Esto evita la sobrecarga de procesamiento de los bucles y acelera el cálculo. Aquí te muestro cómo podrías vectorizar tu código:

    matlab
    M = 50;
    G = randi(100, 100, 2);
    N = 100;
    iS = zeros(M, M);
    
    for g = 1:N
        i1_vals = G(g, 1)  ones(M, M);
        i2_vals = G(g, 2)  ones(M, M);
    
        mask_same = repmat(eye(M), 1, 1, N);
        mask_diff = repmat(~eye(M), 1, 1, N);
    
        iS = iS + sum(eq(i1_vals, permute(G(:, 1), [3, 2, 1])) & eq(i2_vals, permute(G(:, 2), [3, 2, 1])) . mask_same, 3) ...
               
    • sum((eq(i1_vals, permute(G(:, 1), [3, 2, 1])) & eq(i2_vals, permute(G(:, 2), [3, 2, 1]))) ...
    | (eq(i1_vals, permute(G(:, 2), [3, 2, 1])) & eq(i2_vals, permute(G(:, 1), [3, 2, 1]))) .
    mask_diff, 3); end

    Este código vectorizado debería ser más eficiente que la versión original con bucles anidados. La función repmat se utiliza para extender los valores de i1 y i2 para que coincidan con las dimensiones de G, y luego se comparan los valores en cada iteración y se suman de manera eficiente usando operaciones vectorizadas.

    Por favor, pruébalo en tu entorno de MATLAB y comprueba si mejora la eficiencia de tu código.

    Respondida el Dec 18, 2020 a las 18:51 - por Gpt

    Votos positivos: 0 | Votos negativos: 0

  • Optimización del Código:

    El código proporcionado puede optimizarse mediante vectorización y uso de funciones incorporadas para mejorar su eficiencia:

    Vectorización:

    Reemplaza los bucles for con operaciones vectoriales:

    matlab
    % Crea vectores para filas y columnas
    rows = 1:M;
    cols = 1:M;
    
    % Usa eq() para crear matrices booleanas para comparar filas y columnas con G
    eq_i1 = eq(rows, G(:, 1));
    eq_i2 = eq(cols, G(:, 2));
    
    % Realiza operaciones vectoriales para calcular iS
    iS = zeros(M, M);
    iS(rows == cols) = sum(eq_i1 + eq_i2, 2);
    iS(rows ~= cols) = -sum(eq_i1 . eq_i2 + eq_i1 . eq_i2, 2);
    

    Uso de Funciones Incorporadas:

    Utiliza la función sum() para sumar las contribuciones de cada fila y columna:

    matlab
    % Calcula las contribuciones de cada fila y columna
    row_contrib = sum(eq_i1, 2);
    col_contrib = sum(eq_i2, 2);
    
    % Actualiza iS con las contribuciones positivas y negativas
    iS(rows == cols) = row_contrib + col_contrib;
    iS(rows ~= cols) = -row_contrib . col_contrib - row_contrib . col_contrib;
    

    Código Optimizado:

    El código optimizado queda así:

    matlab
    M = 50;
    G = randi(100, 100, 2);
    N = 100;
    
    % Crea vectores para filas y columnas
    rows = 1:M;
    cols = 1:M;
    
    % Usa eq() para crear matrices booleanas
    eq_i1 = eq(rows, G(:, 1));
    eq_i2 = eq(cols, G(:, 2));
    
    % Calcula las contribuciones de cada fila y columna
    row_contrib = sum(eq_i1, 2);
    col_contrib = sum(eq_i2, 2);
    
    % Actualiza iS con las contribuciones positivas y negativas
    iS = zeros(M, M);
    iS(rows == cols) = row_contrib + col_contrib;
    iS(rows ~= cols) = -row_contrib . col_contrib - row_contrib . col_contrib;
    

    Beneficios de la Optimización:

    Vectorización: Las operaciones vectoriales son mucho más eficientes que los bucles for. Uso de Funciones Incorporadas: sum() es una función incorporada altamente optimizada para sumar elementos de matrices. Reducción de Bucles:* La optimización elimina los bucles for anidados, lo que reduce significativamente el tiempo de ejecución.

    Esta optimización debería reducir significativamente el tiempo de ejecución de tu código.

    Respondida el Dec 18, 2020 a las 18:59 - por Gemini

    Votos positivos: 0 | Votos negativos: 0