Poniżej funkcji rekurencyjnej, który wytwarza wszystkich możliwych zestawów parametrów jako wektory kolumny tablicy:
function idx=dynloop(varargin)
if nargin==1
idx=varargin{1};
else
idx=dynloop(varargin{2:end});
idx=[repelem(varargin{1},size(idx,2));
repmat(idx,[1,length(varargin{1})])];
end
return
Przykład Wydajność: pętla ponad 5:7
, następnie 8
, następnie [2,3,5,7]
:
>> idx = dynloop(5:7,8,[2,3,5,7])
idx =
5 5 5 5 6 6 6 6 7 7 7 7
8 8 8 8 8 8 8 8 8 8 8 8
2 3 5 7 2 3 5 7 2 3 5 7
Dane wyjściowe są równoważne z danymi z ndgrid
(z tym, że moim zdaniem jest to bardziej intuicyjny kształt). (Również niektóre Wstępna analiza porównawcza wykazała, może to być nieznacznie szybciej niżndgrid
... Do ustalenia?!)
Główna pętla: Teraz wystarczy użyć jednej pętli do iterację kolumny idx
. Zauważ, że ta koncepcja rozwiązania jest podobna do this solution, jak skomentował @ Daniel dla OP.
Weight = 45000:5000:75000;
Altitude = 10000;
Speed = 0.2:0.1:0.9;
idx = dynloop(Weight,Altitude,Speed);
for ii=1:size(idx,2)
params = idx(:,ii);
%// do stuff with params!
%// ...
end
EDIT: aby obsługiwać zarówno ciąg i wejść numerycznych
prosty mod do pierwotnej funkcji rekurencyjnej napisałem pozwala mu powrócić indeksów, zamiast rzeczywistych elementów, więc komórki smyczkowe są w porządku:
function idx=dynloop(varargin)
if nargin==1
idx=1:length(varargin{1});
else
idx=dynloop(varargin{2:end});
idx=[repelem(1:length(varargin{1}),size(idx,2));
repmat(idx,[1,length(varargin{1})]);];
end
return
Więc w sumie, czynność przypuszczalnie działać tak:
function yourMainFcn(varargin)
idx=dynloop(varargin{:});
for ii=1:size(idx,2)
params = cellfun(@(x,k) numORcell(x,k),...
varargin,num2cell(idx(:,ii).'),... %//'
'UniformOutput',0);
%// do stuff with params!
%// ...
disp(params)
end
end
gdzie funkcja numORcell
odpowiednio analizuje numeryczny w porównaniu z danymi komórki:
function y=numORcell(x,k)
if iscell(x)
y=x{k};
else
y=x(k);
end
end
przykład z łańcuchów:
Weight = 45000:5000:75000;
Altitude = 10000;
Speed = 0.2:0.1:0.9;
Names = {'Foo','Bar'};
>> yourMainFcn(Names,Altitude,Weight)
'Foo' [10000] [45000]
'Foo' [10000] [50000]
'Foo' [10000] [55000]
'Foo' [10000] [60000]
'Foo' [10000] [65000]
'Foo' [10000] [70000]
'Foo' [10000] [75000]
'Bar' [10000] [45000]
'Bar' [10000] [50000]
'Bar' [10000] [55000]
'Bar' [10000] [60000]
'Bar' [10000] [65000]
'Bar' [10000] [70000]
'Bar' [10000] [75000]
lub zamiast:
>> yourMainFcn(Names,Names,Speed,Names)
'Foo' 'Foo' [0.2] 'Foo'
'Foo' 'Foo' [0.2] 'Bar'
'Foo' 'Foo' [0.3] 'Foo'
'Foo' 'Foo' [0.3] 'Bar'
'Foo' 'Foo' [0.4] 'Foo'
...
'Foo' 'Foo' [0.9] 'Bar'
'Foo' 'Bar' [0.2] 'Foo'
...
'Foo' 'Bar' [0.9] 'Bar'
'Bar' 'Foo' [0.2] 'Foo'
...
'Bar' 'Foo' [0.9] 'Bar'
...
'Bar' 'Bar' [0.8] 'Foo'
'Bar' 'Bar' [0.8] 'Bar'
'Bar' 'Bar' [0.9] 'Foo'
'Bar' 'Bar' [0.9] 'Bar'
Zadanie lewej do czytnika : Jeśli przechowywanie wszystkich indeksów w idx
jest problemem z pamięcią, musisz wykonać dość ciężką pętlę. Mimo to możesz utworzyć funkcję, która określa z bieżącego zestawu indeksów następny zestaw indeksów leksykograficznych, co oznacza, że będziesz musiał tylko przechowywać jeden zestaw indeksów i powtarzać je na końcu każdej pętli.
Szukasz [coś w tym stylu] (http://stackoverflow.com/a/34840222/2732801)? – Daniel
Chciałbym parsować plik wejściowy i przekazać wyniki jako argumenty do funkcji. – excaza
Naprawdę nie jest konieczne wykonywanie żadnych analiz. po prostu napisz kod, aby użyć maksymalnej liczby pętli (np. pętla na wadze, wysokość, prędkość, temperatura, klapy itp.). w przypadku, gdy jeden z parametrów jest stały, to w rzeczywistości nie będzie pętli, ale wystarczy raz ustawić indeks i przejść do następnej pętli. –