2016-01-17 4 views
0

У меня есть сценарий, который требует нескольких параметров для запуска. Мне интересно исследовать результаты по мере изменения параметров, поэтому я определяю несколько массивов scan вверху, обертывая весь код несколькими for loops и устанавливая значения параметров для текущих значений сканирования.Есть ли более элегантный способ написать эти циклы?

Это ошибка склонная и неэлегантная. Процесс изменения кода: 1) сброс scan переменных вверху, 2) комментарий, например b = scan2(j2) и 3) раскоммент b=b0.

Что является лучшим методом, позволяющим устанавливать переменные в массивы и затем запускать код для всех таких комбинаций? Пример моего кода Теперь:

close all 
clear all 

%scan1 = linspace(1,4,10); 
scan1 = 0; 
scan2 = linspace(0,1,10); 
scan3 = linspace(-1,0,10); 

for j3 = 1:length(scan3) 
    for j2 = 1:length(scan2) 
    for j1 = 1:length(scan1) 

     a = a0; 
     %b = scan2(j2); 
     b = b0; 
     %c = c0; 
     c = scan3(j3); 
     d = scan2(j2); 

     %(CODE BLOCK THAT DEPENDS ON variables a,b,c,d...) 

    end 

    end 

end 
+0

На данный момент нет общего правила. Векторизация кода в значительной степени зависит от того, что именно происходит в циклах, например. матричное умножение, суммирование или что-то еще. – freude

+0

Хм. Я на самом деле не пытаюсь это процитировать, я просто хочу улучшить организацию. Я мог бы, например, создать массив 1xN для каждого параметра в верхней части, избегая комментирования бизнеса, но я немного обеспокоен использованием памяти ... и кажется излишним иметь тройной цикл, когда часто я только петлю 1 сканирование. – ConfusinglyCuriousTheThird

+0

Я пытаюсь понять ваш код, есть ли конкретная причина перечислять переменные 'scan', отличные от ваших параметров? Не могли бы вы переименовать их в 'scana'' scanb' и т. Д. И итераторы на' ja' 'jb' и т. Д.? – Daniel

ответ

4

На основе this idea, чтобы использовать один для цикла для моделирования нескольких циклов, я попытался адаптировать его к вашему корпусу. Выполняя хорошую эффективность памяти и удобство использования, это решение работает медленнее, чем использование отдельных для циклов.

%define your parameters 
p.a = 1; 
p.b = linspace(1,4,4); 
p.c = linspace(11,15,5); 
p.d = linspace(101,104,4); 
p.e = 5; 
iterations=structfun(@numel,p); 
iterator=cell(1,numel(iterations)); 
for jx = 1:prod(iterations) 
    [iterator{:}]=ind2sub(iterations(:).',jx);%.' 
    %This line uses itertor to extract the corresponding elemets of p and creates a struct which only contains scalars. 
    q=cell2struct(cellfun(@(a,b)(a(b)),struct2cell(p),iterator(:),'uniform',false),fieldnames(p)); 
    %__ (CODE THAT DEPENDS ON q.a to q.e here) __ 

end 

Для сценариев, которые я проверил это добавляет вычислительную нагрузку ниже 0.0002 с на итерации, которая 0.0002.*prod(iterations) с в общей сложности.

+0

Очень круто! Я предполагаю, что это медленнее из-за «структуры»? В моем случае скорость не является проблемой для циклов оболочки: у меня есть код внутри, который занимает больше порядков, поэтому это будет вариант. – ConfusinglyCuriousTheThird

+0

Ячейки массивов, структура, вызывающая ind2sub, все эти три вещи добавляют накладные расходы по сравнению с чистым циклом, равным примерно 0,002 с на итерацию. – Daniel

+1

Вы имеете в виду 'ind2sub (iterations (:). ', J)' вместо 'ind2sub (iterations (:).', 3)' в первой строке цикла? –

0

Один из способов, чтобы сделать один вектор, содержащий все комбинации параметров, используя ndgrid. Для достаточно больших сканов параметров это может стать проблемой памяти, но в противном случае, по крайней мере гораздо чисты, требуется только один цикл и без повторного назначения позже в коде:

a0vec = 1; 
b0vec = linspace(1,4,4); 
c0vec = linspace(11,15,5); 
d0vec = linspace(101,104,4); 
e0vec = 5; 

[a0s,b0s,c0s,d0s,e0s] = ndgrid(a0vec,b0vec,c0vec,d0vec,e0vec);  
N = numel(a0s); 

for j = 1:N 

    a0 = a0s(j); 
    b0 = b0s(j); 
    c0 = c0s(j); 
    d0 = d0s(j); 
    e0 = e0s(j); 

    %__ (CODE THAT DEPENDS ON a0 - e0 here) __ 

end 

все еще хотел бы видеть ваши предложения !

+0

Так как ваш профиль говорит 'python': как насчет использования этого языка и генератора, чтобы не хранить все эти значения в памяти? :) По поводу соответствующей заметки: какие вещи продолжаются в цикле? Что-то сложное, или, возможно, векционируемое? –

+0

@ AndrasDeak хорошее предложение! И быстрый взгляд предполагает, что у Matlab нет синтаксиса, подобного генератору. Что касается памяти, я просто запустил номера, а сетка 100x100x100 x 20 удваивает занятие менее чем на 0,2 гигабайта, так что это будет работать в моем случае. Код составляет ~ 1000 строк, это действительно вопрос хорошей практики кодирования! – ConfusinglyCuriousTheThird

+0

Действительно, я уверен, что MATLAB не может поддерживать ничего подобного генераторам. Если ваше пространство параметров всегда мало, ваш ответ кажется вполне разумным. –

Смежные вопросы