Как упростить циклы в Python и Matlab

1

Я пользователь C и MATLAB. Когда я начал изучать Python (неделю назад), я заметил, что я не использую полный потенциал MATLAB, в частности операции с массивами. Я часто использую циклы, вероятно, потому, что я изучил программирование на C.

В предыдущем совете я научился использовать cumsum и другие эффективные операции массива, например:

alpha = [1e-4,1e-3,1e-4,1e-1,1e-2,1e-3,1e-6,1e-3];
zeta = alpha / (dz*dz)
nz = 101
l=[0.3,0.1,0.2,0.1,0.1,0.1,0.2];
wz = cumsum(l*(nz-1));
nl = lenght(l);   

Возможно ли упростить следующий код в Python (Numpy) или MATLAB?

      A = zeros(nz,nz);
      i=1;
      for j = 2:wz(i)-1
        A(j,j-1) = zeta(1,1);
        A(j,j) = -2*zeta(1,1);
        A(j,j+1) = zeta(1,1); % layer 1 nodes 
      end

      %cicle to n-layers
      for i=2:nl
          for j=wz(i-1):wz(i-1)
              A(j,j-1) = zeta(1,i-1);
              A(j,j) = -zeta(1,i-1)-zeta(1,i);
              A(j,j+1) = zeta(1,i); 
          end

          for j=wz(i-1)+1:wz(i)
              A(j,j-1) = zeta(1,i);
              A(j,j) = -2*zeta(1,i);
              A(j,j+1) = zeta(1,i);
          end

      end
end
  • 2
    Нам было бы легче, если бы вы в одном или двух предложениях объяснили, что должен делать код, а не просто дали нам простой код ...
  • 0
    @Hans Этот код принадлежит 1D Equation Heat Solver, примененному к многослойной структуре. альфа - это массив с коэффициентами диффузии на слой, l - это массив с высотами на слой, wz - это массив, который агрегирует совокупную сумму точек (дискретных точек), а A - это «матрица состояний». После вычисления матрицы состояний я реализую решатель од.
Показать ещё 2 комментария
Теги:
arrays
numpy
for-loop

2 ответа

1
Лучший ответ

Я изменил код ниже, имея возможность запускать его на своей машине бок о бок. Есть еще несколько вопросов (есть ли A, чтобы получить больше в конечном цикле?, что такое dz?). Проблема, с которой вы столкнулись, прежде чем запускать это, заключалась в том, что я забыл, что idx_matrix должен быть логичным.

dz=0.1;
alpha = [1e-4,1e-3,1e-4,1e-1,1e-2,1e-3,1e-6,1e-3];
zeta = alpha / (dz*dz);
nz = 101;
l=[0.3,0.1,0.2,0.1,0.1,0.1,0.2];
wz = cumsum(l*(nz-1));
nl = length(l);

A = zeros(nz);
i=1;

%replaces 1st loop
j_start = 2;
j_end = wz(i)-1;

idx_matrix = false(size(A));
idx_matrix(j_start:j_end,j_start:j_end) = eye(j_end-j_start+1);
A(idx_matrix) = -2*zeta(1,1);

idx_matrix(idx_matrix) = false;
idx_matrix(j_start:j_end,j_start-1:j_end-1) = eye(j_end-j_start+1);
A(idx_matrix) = zeta(1,1);

idx_matrix(idx_matrix) = false;
idx_matrix(j_start:j_end,j_start+1:j_end+1) = eye(j_end-j_start+1);
A(idx_matrix) = zeta(1,1);

%cicle to n-layers
for i=2:nl

    %replaces 3rd loop
    j_start = wz(i-1);
    A(j_start,j_start) = -zeta(1,i-1)-zeta(1,i);
    A(j_start,j_start-1) = zeta(1,i-1);
    A(j_start,j_start+1) = zeta(1,i);

    %replaces 4th loop
    j_start = wz(i-1)+1;
    j_end = min(wz(i),size(A,2)-1);
    idx_matrix = false(size(A));
    idx_matrix(j_start:j_end,j_start:j_end) = eye(j_end-j_start+1);
    A(idx_matrix) = -2*zeta(1,i);

    idx_matrix(idx_matrix) = false;
    idx_matrix(j_start:j_end,j_start-1:j_end-1) = eye(j_end-j_start+1);
    A(idx_matrix) = zeta(1,i);

    idx_matrix(idx_matrix) = false;
    idx_matrix(j_start:j_end,j_start+1:j_end+1) = eye(j_end-j_start+1);
    A(idx_matrix) = zeta(1,i);

end
  • 0
    спасибо за ответ В вашем коде есть ошибка ??? Индексы индексов должны быть либо действительными положительными целыми числами, либо логическими. A (idx_matrix) = -2 * дзета (1,1); Это так рано в коде, что я не могу понять, что вы хотите сделать. Да, третий цикл, может быть заданием, я не нашел лучшего пути к этой инструкции. (Это представляет границу между слоями, если вы читаете мое описание кода в @Hans)
  • 0
    Аааа, а "ты матрица" это массив (A = нули (nz)) это ошибка или нет?
Показать ещё 6 комментариев
1

Чтобы упростить ваши циклы, вы можете использовать функцию spdiags.

http://www.mathworks.fr/help/techdoc/ref/spdiags.html

Например, ваш первый цикл может быть записан как:

A=full(spdiags(repmat([zeta(1,1),-2*zeta(1,1),zeta(1,1)],wz(i),1),[-1 0 1],wz(i),wz(i)))
  • 0
    спасибо за ссылку, но это не решает мою проблему =) Я пытаюсь найти способ упростить проблему, другими словами преобразовать проблему итерации в векторную задачу
  • 0
    Я отредактировал ответ, чтобы показать вам, как использовать spdiags в вашем случае,
Показать ещё 6 комментариев

Ещё вопросы

Сообщество Overcoder
Наверх
Меню