Перевод команды map и некоторых других из Mathematica в MATLAB

Я сделал это до сих пор:

РЕДАКТИРОВАТЬ---------------

steps=@ (m) 2*randi([0,1],[1,m])-1;
Walk1D =@ (n) [0,cumsum(steps(n))];
findend=@ (x) x(end);
LastPoint1D=@(n) findend(Walk1D(n));

nsteps=200;
nsq=floor(sqrt(nsteps));
MeanSquareDistance1D= @ (n,m) m.*sum((LastPoint1D(n)).^2)./m;
r2D=MeanSquareDistance1D(100,1000)

data=[ ];
for i=10:20:90
data=[data; i , MeanSquareDistance1D(i,2000)]
end

Единственная проблема сейчас заключается в том, что второй столбец «данных» должен давать мне значения около

10
30
50
70
90

но не совсем. Только приблизительно. Например, "данные" должны быть:

10  10.184
30  27.51
50  50.306
70  68.394
90  90.414

Может быть, неправильно указана сумма?


person George    schedule 17.02.2011    source источник
comment
Этот предыдущий вопрос может вам помочь: функция карты в MATLAB?   -  person gnovice    schedule 17.02.2011
comment
Спасибо, я видел этот вопрос, но моя проблема в том, что я не могу выразить данные как есть.   -  person George    schedule 18.02.2011


Ответы (3)


Из вашего кода я предполагаю, что вы хотите рассчитать среднеквадратичное расстояние для одномерного случайного блуждания.

Среднеквадратичное расстояние с запаздыванием tt - это средний квадрат разницы между двумя позициями на случайном блуждании, разделенных tt шагами. Я предполагаю, что data должен быть массивом, где первый столбец - это tt, а второй столбец - соответствующее среднеквадратичное расстояние, и где есть дополнительный параметр, который указывает общее количество шагов в вашем случайном блуждании.

Вот как бы я рассчитал data

%# define parameters
nSteps = 2000;
listOfLags = 10:20:90; %# must be 1-by-n vector

%# create random walk
%# steps can be +1 or -1, add all of them via cumsum
randomWalk = cumsum(randi([0 2],nSteps)-1);

%# calculate msd for the desired lags
%# use a loop for readability
nLags = length(listOfLags);
data = zeros(nLags,2);
data(:,1) = listOfLags;

for lag = listOfLags
    %# lag takes on every lag value, so use logical indexing to find
    %# which lag (in terms of entry into data) we're currently working on

    %# This line corresponds to
    %# 1. get all distances traveled within a duration of `lag`
    %#    vectorOfDistances = randomWalk(lag+1:end) - randomWalk(1:nSteps-lag)
    %#    i.e. the first element is randomWalk(lag+1)-randomWalk(1)
    %# 2. square all: (vectorOfDistances).^2
    %# 3. average all squared distances 
    data(listOfLags==lag,2) = mean( (randomWalk(lag+1:end) - randomWalk(1:end-lag)).^2);
end

%# plot the results
plot(data(:,1),data(:,2),'.')
xlabel('lag'),ylabel('mean squared displacement')
person Jonas    schedule 22.02.2011
comment
Прежде всего, еще раз спасибо! Мне трудно следить за вашим кодом, потому что я сформулировал его по-другому (Walk1D, LastPoint1D и т. Д.). Я редактирую свое исходное сообщение через минуту, чтобы показать вам, где я попал. (Я пробовал ваш код но дает мне неопределенную функцию или переменную "лагает".) - person George; 22.02.2011
comment
Если ты не можешь помочь, все в порядке, Джонас, ты мне помог более чем достаточно ... У тебя нет на меня всего времени :) - person George; 22.02.2011
comment
@ Джордж: извините за ошибку. Если вы делаете то, что я думаю, вы, скорее всего, делаете это неправильно, поскольку для среднего квадрата расстояния вам нужно взять среднее значение по вектору расстояний, и ваш LastPoint1D возвращает скаляр, а m.*()./m не на самом деле делать что-нибудь, кроме циклов отходов. - person Jonas; 22.02.2011
comment
Я должен сделать что-то вроде (sum ((LastPoint (n) -LastPoint (0)). ^ 2)) ./ m, но как? - person George; 22.02.2011
comment
Я сделал это так (с помощью): steps1 = @ (n, m) randi ([- 1 1], n, m); LastPoint_1D = @ (n, m) сумма (шаги1 (n, m)); MeanSquareDistance1D = @ (n, m) среднее (LastPoint_1D (n, m). ^ 2); - person George; 23.02.2011

Хотя Matlab поддерживает анонимные функции и имеет элементарную поддержку функционального программирования, он не особенно хорошо поддерживается или идиоматичен. Подход Matlab состоит в том, чтобы вместо этого использовать векторы (имя Matlab для массивов) везде, где это возможно, и использовать функции, которые оцениваются по этим векторам.

Вместо

Walk1D =@ (n) cumsum(steps(n));

который не работает, потому что аргумент cumsum (который ожидает вектор) - это просто steps(n) (единственный элемент вектора steps!), идиоматический подход Matlab должен сделать что-то вроде:

Nsteps = 100;  
steps = randn(1, Nsteps);
walk1D = cumsum(steps);

и Т. Д.

Если вам это действительно нужно, эквивалентами Matlab оператора "map" функционального программирования являются cellfun и arrayfun.

(Кроме того: наследие Matlab уходит корнями в Fortran, по сравнению с Mathematica, вдохновленным Lisp. Анонимные функции в Matlab ограничены простыми выражениями, поэтому часто бывает необходимо использовать традиционную именованную функцию, хранящуюся в отдельном файле .m. I часто кажется, что конструкции функционального программирования в Matlab в основном являются новинкой, хотя иногда и полезны.)

person nibot    schedule 17.02.2011
comment
Здравствуйте, функция Walk1D работает нормально, но спасибо за ваш подход. У меня проблема с записью данных выше, потому что я немного не понимаю, что писать! - person George; 18.02.2011

Я бы немного прокомментировал ваш вклад в Mathematica, предлагая улучшения эффективности

Walk1D[n_] :=  Join[{0},Accumulate[steps[n]]]
LastPoint1D[n_] := Total[steps[n]]

Вот тайминги, показывающие разницу

In[51]:= steps[n_Integer] := RandomInteger[{-10, 10}, n]

In[52]:= Walk1D[n_] := Join[{0}, Accumulate[steps[n]]]

In[53]:= Walk1Da[n_] := FoldList[Plus, 0, steps[n]]

In[56]:= BlockRandom[SeedRandom[1]; AbsoluteTiming[r = Walk1D[10^7];]]

Out[56]= {0.3650000, Null}

In[57]:= BlockRandom[SeedRandom[1]; AbsoluteTiming[r = Walk1Da[10^7];]]

Out[57]= {1.1370000, Null}
person Sasha    schedule 17.02.2011