MATLAB code for adding two signals for different time intervals - matlab

I have got two sine waves shifted 180 degrees from each other. I would like to create another signal from these two, but for that I have to add separate intervals separately and the resultant should be continuous as well.
Here are two sine waves:
t = 0:0.00001:0.02;
w= 2*pi*50;
ma = 0.8*sin(w*t);
mb = 0.8*sin(w*t-pi);
Now I want to create another signal mcm. For an interval "0 to 0.005 (quarter cycle)" I want mcm = 1 + ma. For interval "0.005 to 0.01" I want mcm = 1 + mb.
And likewise for the other two quarters.
How do we go about doing it?

Edit after the question was changed in the comment below
Given the need to generalise this to multiple cycles (note the addition of the user defined input n = number of cycles), here is what I would suggest.
Firstly, each function has to be explicitly defined. Secondly, for each point along the length of t, the function that needs to be used at that data point needs to be (explicitly) defined.
Thus in the code below, functions and functionOrder are used to set the functions to be used, and the order/frequency in which they are to be used.
In the Calculate mcm section, a variable ind is used to iterate over the output, and select the function to be used at each point.
% User inputs
f = 50;
n = 3; % number of cycles
inc = 0.00001; % increment
% Preliminaries
t_interval = 1/f;
t = 0:inc:t_interval*n;
t = t(1:end-1);
w = 2*pi*f;
ma = 0.8*sin(w*t);
mb = 0.8*sin(w*t-pi);
% Define mcm
f1 = #(ii) -1 - mb(ii);
f2 = #(ii) 1 - ma(ii);
f3 = #(ii) -1 + mb(ii);
f4 = #(ii) 1 - mb(ii);
functions = {f1, f2, f3, f4};
functionOrder = [1 2 3 4];
% Calculate mcm
ind = repmat(functionOrder, round(t_interval/inc)/length(functionOrder), 1);
ind = reshape(ind, numel(ind), 1);
ind = repmat(ind, n, 1);
mcm = zeros(size(ind));
for ii = 1:length(ind)
mcm(ii) = functions{ind(ii)}(ii);
end
% Plot
figure; plot(t,ma);
hold on; plot(t,mb);
plot(t, mcm);
================================================
Previous answer to the simpler question, without the need for generalisability
The way I would approach this would be a compromise between ease of use in the current situation and ease of replication/dynamism as the example changes.
First create a variable that is in indicator of where ma should be used and mb should be used. Note that using 0 and 1 makes future steps easier: if you had more functions to utilise in this piecewise operation, the construction of this indicator would have to be different.
ind = zeros(size(t)); %indicator
ind(t >= 0.000 && t < 0.005) = 1;
ind(t >= 0.010 && t <=0.015) = 1;
Then, the addition of ma and mb is relatively straightforward.
mcm = 1 + ind.*ma + (1-ind).*mb;
[Note that this follows the mathematical formulation described in the text, but the resulting curve is not continuous. I do not see a way to do this so that ma and mb alternate every quarter cycle and the curve is also continuous.]

Related

Custom-made linspace and logspace in MATLAB

I decided to take a look at two functions linspace and logspace. Below I give two examples, one using MATLAB's built-in linspace and one for logspace along with their hand made implementation. In the first case both the built-in function linspace and the handmade code give the same results. However, this is not true when examining the logspace function. Could you please help me to found the error in the handmade code?
a = 1; b = 5; n = 7;
y = linspace(1,5,7);
yy = zeros(1,n); yy(1) = a;
for i=2:n
yy(i) = yy(i-1) + (b-a)/(n-1);
end
x = logspace(1,5,7);
xx = zeros(1,n); xx(1) = 10^a;
for i=2:n
xx(i) = xx(i-1) + (10^b-10^a)/(n-1);
end
Thank you!
The only difference between linspace and logspace is that they go one step further and take the power of 10 for every element in the linspace array.
As such, you'd simply take your equation for linspace you generated, take the result and raise it to the power of 10. However, with your code, you are relying on the previous result and that is already raised to the power of 10. Therefore, you'll need to take the anti-log to convert the previous result back to a linear form, then use the same logic was used to generate the linspace, then raise it back to the power of 10. Therefore, the relationship is:
xx[n] = 10^(log10(xx[n-1]) + ((b-a)/(n-1)))
You can certainly simplify this, taking advantage of the fact that 10^(log10(z)) = z, as long as z > 0. We can also split up the terms in the power using the property that 10^(m + n) = (10^m) * (10^n). Therefore:
xx[n] = xx[n-1] * (10^((b-a)/(n-1)))
As such, simply take your previous result multiply with 10^((b-a)/(n-1))
a = 1; b = 5; n = 7;
x = logspace(1,5,7);
xx = zeros(1,n); xx(1) = 10^a;
for i=2:n
xx(i) = xx(i-1)*(10^((b-a)/(n-1))); %// Change
end
We get for both x and xx:
>> format long g;
>> x
x =
Columns 1 through 4
10 46.4158883361278 215.443469003188 1000
Columns 5 through 7
4641.58883361278 21544.3469003189 100000
>> xx
xx =
Columns 1 through 4
10 46.4158883361278 215.443469003188 1000
Columns 5 through 7
4641.58883361278 21544.3469003188 100000

Summing scalars and vectors [MATLAB]

First off; I'm not very well taught in programming, but i tend to learn exactly what I need to learn in order to do what I want when programming, I have moderate experience with python, html/css C and matlab. I've now enrolled in a physics-simulation course where I use matlab to compute the trajectory of 500 particles under the influence of 5 force-fields of different magnitude.
So now to my thing; I need to write the following for all i=1...500 particles
f_i = m*g - sum{(f_k/r_k^2)*exp((||vec(x)_i - vec(p)_k||^2)/2*r_k^2)(vec(x)_i - vec(p)_k)}
I hope its not too cluttered
And here is my code so far;
clear all
close all
echo off
%Simulation Parameters-------------------------------------------
h = 0.01; %Time-step h (s)
t_0 = 0; %initial time (s)
t_f = 3; %final time (s)
m = 1; %Particle mass (kg)
L = 5; %Charateristic length (m)
NT = t_f/h; %Number of time steps
g = [0,-9.81];
f = [32 40 28 16 20]; %the force f_k (N)
r = [0.3*L 0.2*L 0.4*L 0.5*L 0.3*L]; %the radii r_k
p = [-0.2*L 0.8*L; -0.3*L -0.8*L; -0.6*L 0.1*L;
0.4*L 0.7*L; 0.8*L -0.3*L];
%Forcefield origin position
%stepper = 'forward_euler'; % use forward Euler time-integration
fprintf('Simulation Parameters set');
%initialization---------------------------------------------------
for i = 1:500 %Gives inital value to each of the 500 particles
particle{i,1}.x = [-L -L];
particle{i,1}.v = [5,10];
particle{i,1}.m = m;
for k = 1:5
C = particle{i}.x - p(k,:);
F = rdivide(f(1,k),r(1,k)^2).*C
%clear C; %Creates elements for array F
end
particle{i}.fi = m*g - sum(F); %Compute attractive force on particle
%clear F; %Clear F for next use
end
What this code seems to do is that it goes into the first loop with index i, then goes through the 'k'-loop and exits it with a value for F then uses that last value for F(k) to compute f_i.
What I want it to do is to put all the values of F(k) from 1-5 and put into a matrix which columns I can sum for f_i. I'd prefer to sum the columns as the first column should represent all F-components in the x-axis and the second column all F-components in the y-axis.
Note that the expression for F in the k-loop is not done.
I fixed it by defining the index for F(k,:)

How do I index codistributed arrays in a spmd block

I am doing a very large calculation (atmospheric absorption) that has a lot of individual narrow peaks that all get added up at the end. For each peak, I have pre-calculated the range over which the value of the peak shape function is above my chosen threshold, and I am then going line by line and adding the peaks to my spectrum. A minimum example is given below:
X = 1:1e7;
K = numel(a); % count the number of peaks I have.
spectrum = zeros(size(X));
for k = 1:K
grid = X >= rng(1,k) & X <= rng(2,k);
spectrum(grid) = spectrum(grid) + peakfn(X(grid),a(k),b(k),c(k)]);
end
Here, each peak has some parameters that define the position and shape (a,b,c), and a range over which to do the calculation (rng). This works great, and on my machine it benchmarks at around 220 seconds to do a complete data set. However, I have a 4 core machine and I would eventually like to run this on a cluster, so I'd like to parallelize it and make it scaleable.
Because each loop relies on the results of the previous iteration, I cannot use parfor, so I am taking my first step into learning how to use spmd blocks. My first try looked like this:
X = 1:1e7;
cores = matlabpool('size');
K = numel(a);
spectrum = zeros(size(X),cores);
spmd
n = labindex:cores:K
N = numel(n);
for k = 1:N
grid = X >= rng(1,n(k)) & X <= rng(2,n(k));
spectrum(grid,labindex) = spectrum(grid,labindex) + peakfn(X(grid),a(n(k)),b(n(k)),c(n(k))]);
end
end
finalSpectrum = sum(spectrum,2);
This almost works. The program crashes at the last line because spectrum is of type Composite, and the documentation for 2013a is spotty on how to turn Composite data into a matrix (cell2mat does not work). This also does not scale well because the more cores I have, the larger the matrix is, and that large matrix has to get copied to each worker, which then ignores most of the data. Question 1: how do I turn a Composite data type into a useable array?
The second thing I tried was to use a codistributed array.
spmd
spectrum = codistributed.zeros(K,cores);
disp(size(getLocalPart(spectrum)))
end
This tells me that each worker has a single vector of size [K 1], which I believe is what I want, but when I try to then meld the above methods
spmd
spectrum = codistributed.zeros(K,cores);
n = labindex:cores:K
N = numel(n);
for k = 1:N
grid = X >= rng(1,n(k)) & X <= rng(2,n(k));
spectrum(grid) = spectrum(grid) + peakfn(X(grid),a(n(k)),b(n(k)),c(n(k))]); end
finalSpectrum = gather(spectrum);
end
finalSpectrum = sum(finalSpectrum,2);
I get Matrix dimensions must agree errors. Since it's in a parallel block, I can't use my normal debugging crutch of stepping through the loop and seeing what the size of each block is at each point to see what's going on. Question 2: what is the proper way to index into and out of a codistributed array in an spmd block?
Regarding question#1, the Composite variable in the client basically refers to a non-distributed variant array stored on the workers. You can access the array from each worker by {}-indexing using its corresponding labindex (e.g: spectrum{1}, spectrum{2}, ..).
For your code that would be: finalSpectrum = sum(cat(2,spectrum{:}), 2);
Now I tried this problem myself using random data. Below are three implementations to compare (see here to understand the difference between distributed and nondistributed arrays). First we start with the common data:
len = 100; % spectrum length
K = 10; % number of peaks
X = 1:len;
% random position and shape parameters
a = rand(1,K); b = rand(1,K); c = rand(1,K);
% random peak ranges (lower/upper thresholds)
ranges = sort(randi([1 len], [2 K]));
% dummy peakfn() function
fcn = #(x,a,b,c) x+a+b+c;
% prepare a pool of MATLAB workers
matlabpool open
1) Serial for-loop:
spectrum = zeros(size(X));
for i=1:size(ranges,2)
r = ranges(:,i);
idx = (r(1) <= X & X <= r(2));
spectrum(idx) = spectrum(idx) + fcn(X(idx), a(i), b(i), c(i));
end
s1 = spectrum;
clear spectrum i r idx
2) SPMD with Composite array
spmd
spectrum = zeros(1,len);
ind = labindex:numlabs:K;
for i=1:numel(ind)
r = ranges(:,ind(i));
idx = (r(1) <= X & X <= r(2));
spectrum(idx) = spectrum(idx) + ...
feval(fcn, X(idx), a(ind(i)), b(ind(i)), c(ind(i)));
end
end
s2 = sum(vertcat(spectrum{:}));
clear spectrum i r idx ind
3) SPMD with co-distributed array
spmd
spectrum = zeros(numlabs, len, codistributor('1d',1));
ind = labindex:numlabs:K;
for i=1:numel(ind)
r = ranges(:,ind(i));
idx = (r(1) <= X & X <= r(2));
spectrum(labindex,idx) = spectrum(labindex,idx) + ...
feval(fcn, X(idx), a(ind(i)), b(ind(i)), c(ind(i)));
end
end
s3 = sum(gather(spectrum));
clear spectrum i r idx ind
All three results should be equal (to within an acceptably small margin of error)
>> max([max(s1-s2), max(s1-s3), max(s2-s3)])
ans =
2.8422e-14

Optimizing repetitive estimation (currently a loop) in MATLAB

I've found myself needing to do a least-squares (or similar matrix-based operation) for every pixel in an image. Every pixel has a set of numbers associated with it, and so it can be arranged as a 3D matrix.
(This next bit can be skipped)
Quick explanation of what I mean by least-squares estimation :
Let's say we have some quadratic system that is modeled by Y = Ax^2 + Bx + C and we're looking for those A,B,C coefficients. With a few samples (at least 3) of X and the corresponding Y, we can estimate them by:
Arrange the (lets say 10) X samples into a matrix like X = [x(:).^2 x(:) ones(10,1)];
Arrange the Y samples into a similar matrix: Y = y(:);
Estimate the coefficients A,B,C by solving: coeffs = (X'*X)^(-1)*X'*Y;
Try this on your own if you want:
A = 5; B = 2; C = 1;
x = 1:10;
y = A*x(:).^2 + B*x(:) + C + .25*randn(10,1); % added some noise here
X = [x(:).^2 x(:) ones(10,1)];
Y = y(:);
coeffs = (X'*X)^-1*X'*Y
coeffs =
5.0040
1.9818
0.9241
START PAYING ATTENTION AGAIN IF I LOST YOU THERE
*MAJOR REWRITE*I've modified to bring it as close to the real problem that I have and still make it a minimum working example.
Problem Setup
%// Setup
xdim = 500;
ydim = 500;
ncoils = 8;
nshots = 4;
%// matrix size for each pixel is ncoils x nshots (an overdetermined system)
%// each pixel has a matrix stored in the 3rd and 4rth dimensions
regressor = randn(xdim,ydim, ncoils,nshots);
regressand = randn(xdim, ydim,ncoils);
So my problem is that I have to do a (X'*X)^-1*X'*Y (least-squares or similar) operation for every pixel in an image. While that itself is vectorized/matrixized the only way that I have to do it for every pixel is in a for loop, like:
Original code style
%// Actual work
tic
estimate = zeros(xdim,ydim);
for col=1:size(regressor,2)
for row=1:size(regressor,1)
X = squeeze(regressor(row,col,:,:));
Y = squeeze(regressand(row,col,:));
B = X\Y;
% B = (X'*X)^(-1)*X'*Y; %// equivalently
estimate(row,col) = B(1);
end
end
toc
Elapsed time = 27.6 seconds
EDITS in reponse to comments and other ideas
I tried some things:
1. Reshaped into a long vector and removed the double for loop. This saved some time.
2. Removed the squeeze (and in-line transposing) by permute-ing the picture before hand: This save alot more time.
Current example:
%// Actual work
tic
estimate2 = zeros(xdim*ydim,1);
regressor_mod = permute(regressor,[3 4 1 2]);
regressor_mod = reshape(regressor_mod,[ncoils,nshots,xdim*ydim]);
regressand_mod = permute(regressand,[3 1 2]);
regressand_mod = reshape(regressand_mod,[ncoils,xdim*ydim]);
for ind=1:size(regressor_mod,3) % for every pixel
X = regressor_mod(:,:,ind);
Y = regressand_mod(:,ind);
B = X\Y;
estimate2(ind) = B(1);
end
estimate2 = reshape(estimate2,[xdim,ydim]);
toc
Elapsed time = 2.30 seconds (avg of 10)
isequal(estimate2,estimate) == 1;
Rody Oldenhuis's way
N = xdim*ydim*ncoils; %// number of columns
M = xdim*ydim*nshots; %// number of rows
ii = repmat(reshape(1:N,[ncoils,xdim*ydim]),[nshots 1]); %//column indicies
jj = repmat(1:M,[ncoils 1]); %//row indicies
X = sparse(ii(:),jj(:),regressor_mod(:));
Y = regressand_mod(:);
B = X\Y;
B = reshape(B(1:nshots:end),[xdim ydim]);
Elapsed time = 2.26 seconds (avg of 10)
or 2.18 seconds (if you don't include the definition of N,M,ii,jj)
SO THE QUESTION IS:
Is there an (even) faster way?
(I don't think so.)
You can achieve a ~factor of 2 speed up by precomputing the transposition of X. i.e.
for x=1:size(picture,2) % second dimension b/c already transposed
X = picture(:,x);
XX = X';
Y = randn(n_timepoints,1);
%B = (X'*X)^-1*X'*Y; ;
B = (XX*X)^-1*XX*Y;
est(x) = B(1);
end
Before: Elapsed time is 2.520944 seconds.
After: Elapsed time is 1.134081 seconds.
EDIT:
Your code, as it stands in your latest edit, can be replaced by the following
tic
xdim = 500;
ydim = 500;
n_timepoints = 10; % for example
% Actual work
picture = randn(xdim,ydim,n_timepoints);
picture = reshape(picture, [xdim*ydim,n_timepoints])'; % note transpose
YR = randn(n_timepoints,size(picture,2));
% (XX*X).^-1 = sum(picture.*picture).^-1;
% XX*Y = sum(picture.*YR);
est = sum(picture.*picture).^-1 .* sum(picture.*YR);
est = reshape(est,[xdim,ydim]);
toc
Elapsed time is 0.127014 seconds.
This is an order of magnitude speed up on the latest edit, and the results are all but identical to the previous method.
EDIT2:
Okay, so if X is a matrix, not a vector, things are a little more complicated. We basically want to precompute as much as possible outside of the for-loop to keep our costs down. We can also get a significant speed-up by computing XT*X manually - since the result will always be a symmetric matrix, we can cut a few corners to speed things up. First, the symmetric multiplication function:
function XTX = sym_mult(X) % X is a 3-d matrix
n = size(X,2);
XTX = zeros(n,n,size(X,3));
for i=1:n
for j=i:n
XTX(i,j,:) = sum(X(:,i,:).*X(:,j,:));
if i~=j
XTX(j,i,:) = XTX(i,j,:);
end
end
end
Now the actual computation script
xdim = 500;
ydim = 500;
n_timepoints = 10; % for example
Y = randn(10,xdim*ydim);
picture = randn(xdim,ydim,n_timepoints); % 500x500x10
% Actual work
tic % start timing
picture = reshape(picture, [xdim*ydim,n_timepoints])';
% Here we precompute the (XT*Y) calculation to speed things up later
picture_y = [sum(Y);sum(Y.*picture)];
% initialize
est = zeros(size(picture,2),1);
picture = permute(picture,[1,3,2]);
XTX = cat(2,ones(n_timepoints,1,size(picture,3)),picture);
XTX = sym_mult(XTX); % precompute (XT*X) for speed
X = zeros(2,2); % preallocate for speed
XY = zeros(2,1);
for x=1:size(picture,2) % second dimension b/c already transposed
%For some reason this is a lot faster than X = XTX(:,:,x);
X(1,1) = XTX(1,1,x);
X(2,1) = XTX(2,1,x);
X(1,2) = XTX(1,2,x);
X(2,2) = XTX(2,2,x);
XY(1) = picture_y(1,x);
XY(2) = picture_y(2,x);
% Here we utilise the fact that A\B is faster than inv(A)*B
% We also use the fact that (A*B)*C = A*(B*C) to speed things up
B = X\XY;
est(x) = B(1);
end
est = reshape(est,[xdim,ydim]);
toc % end timing
Before: Elapsed time is 4.56 seconds.
After: Elapsed time is 2.24 seconds.
This is a speed up of about a factor of 2. This code should be extensible to X being any dimensions you want. For instance, in the case where X = [1 x x^2], you would change picture_y to the following
picture_y = [sum(Y);sum(Y.*picture);sum(Y.*picture.^2)];
and change XTX to
XTX = cat(2,ones(n_timepoints,1,size(picture,3)),picture,picture.^2);
You would also change a lot of 2s to 3s in the code, and add XY(3) = picture_y(3,x) to the loop. It should be fairly straight-forward, I believe.
Results
I sped up your original version, since your edit 3 was actually not working (and also does something different).
So, on my PC:
Your (original) version: 8.428473 seconds.
My obfuscated one-liner given below: 0.964589 seconds.
First, for no other reason than to impress, I'll give it as I wrote it:
%%// Some example data
xdim = 500;
ydim = 500;
n_timepoints = 10; % for example
estimate = zeros(xdim,ydim); %// initialization with explicit size
picture = randn(xdim,ydim,n_timepoints);
%%// Your original solution
%// (slightly altered to make my version's results agree with yours)
tic
Y = randn(n_timepoints,xdim*ydim);
ii = 1;
for x = 1:xdim
for y = 1:ydim
X = squeeze(picture(x,y,:)); %// or similar creation of X matrix
B = (X'*X)^(-1)*X' * Y(:,ii);
ii = ii+1;
%// sometimes you keep everything and do
%// estimate(x,y,:) = B(:);
%// sometimes just the first element is important and you do
estimate(x,y) = B(1);
end
end
toc
%%// My version
tic
%// UNLEASH THE FURY!!
estimate2 = reshape(sparse(1:xdim*ydim*n_timepoints, ...
builtin('_paren', ones(n_timepoints,1)*(1:xdim*ydim),:), ...
builtin('_paren', permute(picture, [3 2 1]),:))\Y(:), ydim,xdim).'; %'
toc
%%// Check for equality
max(abs(estimate(:)-estimate2(:))) % (always less than ~1e-14)
Breakdown
First, here's the version that you should actually use:
%// Construct sparse block-diagonal matrix
%// (Type "help sparse" for more information)
N = xdim*ydim; %// number of columns
M = N*n_timepoints; %// number of rows
ii = 1:N;
jj = ones(n_timepoints,1)*(1:N);
s = permute(picture, [3 2 1]);
X = sparse(ii,jj(:), s(:));
%// Compute ALL the estimates at once
estimates = X\Y(:);
%// You loop through the *second* dimension first, so to make everything
%// agree, we have to extract elements in the "wrong" order, and transpose:
estimate2 = reshape(estimates, ydim,xdim).'; %'
Here's an example of what picture and the corresponding matrix X looks like for xdim = ydim = n_timepoints = 2:
>> clc, picture, full(X)
picture(:,:,1) =
-0.5643 -2.0504
-0.1656 0.4497
picture(:,:,2) =
0.6397 0.7782
0.5830 -0.3138
ans =
-0.5643 0 0 0
0.6397 0 0 0
0 -2.0504 0 0
0 0.7782 0 0
0 0 -0.1656 0
0 0 0.5830 0
0 0 0 0.4497
0 0 0 -0.3138
You can see why sparse is necessary -- it's mostly zeros, but will grow large quickly. The full matrix would quickly consume all your RAM, while the sparse one will not consume much more than the original picture matrix does.
With this matrix X, the new problem
X·b = Y
now contains all the problems
X1 · b1 = Y1
X2 · b2 = Y2
...
where
b = [b1; b2; b3; ...]
Y = [Y1; Y2; Y3; ...]
so, the single command
X\Y
will solve all your systems at once.
This offloads all the hard work to a set of highly specialized, compiled to machine-specific code, optimized-in-every-way algorithms, rather than the interpreted, generic, always-two-steps-away from the hardware loops in MATLAB.
It should be straightforward to convert this to a version where X is a matrix; you'll end up with something like what blkdiag does, which can also be used by mldivide in exactly the same way as above.
I had a wee play around with an idea, and I decided to stick it as a separate answer, as its a completely different approach to my other idea, and I don't actually condone what I'm about to do. I think this is the fastest approach so far:
Orignal (unoptimised): 13.507176 seconds.
Fast Cholesky-decomposition method: 0.424464 seconds
First, we've got a function to quickly do the X'*X multiplication. We can speed things up here because the result will always be symmetric.
function XX = sym_mult(X)
n = size(X,2);
XX = zeros(n,n,size(X,3));
for i=1:n
for j=i:n
XX(i,j,:) = sum(X(:,i,:).*X(:,j,:));
if i~=j
XX(j,i,:) = XX(i,j,:);
end
end
end
The we have a function to do LDL Cholesky decomposition of a 3D matrix (we can do this because the (X'*X) matrix will always be symmetric) and then do forward and backwards substitution to solve the LDL inversion equation
function Y = fast_chol(X,XY)
n=size(X,2);
L = zeros(n,n,size(X,3));
D = zeros(n,n,size(X,3));
B = zeros(n,1,size(X,3));
Y = zeros(n,1,size(X,3));
% These loops compute the LDL decomposition of the 3D matrix
for i=1:n
D(i,i,:) = X(i,i,:);
L(i,i,:) = 1;
for j=1:i-1
L(i,j,:) = X(i,j,:);
for k=1:(j-1)
L(i,j,:) = L(i,j,:) - L(i,k,:).*L(j,k,:).*D(k,k,:);
end
D(i,j,:) = L(i,j,:);
L(i,j,:) = L(i,j,:)./D(j,j,:);
if i~=j
D(i,i,:) = D(i,i,:) - L(i,j,:).^2.*D(j,j,:);
end
end
end
for i=1:n
B(i,1,:) = XY(i,:);
for j=1:(i-1)
B(i,1,:) = B(i,1,:)-D(i,j,:).*B(j,1,:);
end
B(i,1,:) = B(i,1,:)./D(i,i,:);
end
for i=n:-1:1
Y(i,1,:) = B(i,1,:);
for j=n:-1:(i+1)
Y(i,1,:) = Y(i,1,:)-L(j,i,:).*Y(j,1,:);
end
end
Finally, we have the main script which calls all of this
xdim = 500;
ydim = 500;
n_timepoints = 10; % for example
Y = randn(10,xdim*ydim);
picture = randn(xdim,ydim,n_timepoints); % 500x500x10
tic % start timing
picture = reshape(pr, [xdim*ydim,n_timepoints])';
% Here we precompute the (XT*Y) calculation
picture_y = [sum(Y);sum(Y.*picture)];
% initialize
est2 = zeros(size(picture,2),1);
picture = permute(picture,[1,3,2]);
% Now we calculate the X'*X matrix
XTX = cat(2,ones(n_timepoints,1,size(picture,3)),picture);
XTX = sym_mult(XTX);
% Call our fast Cholesky decomposition routine
B = fast_chol(XTX,picture_y);
est2 = B(1,:);
est2 = reshape(est2,[xdim,ydim]);
toc
Again, this should work equally well for a Nx3 X matrix, or however big you want.
I use octave, thus I can't say anything about the resulting performance in Matlab, but would expect this code to be slightly faster:
pictureT=picture'
est=arrayfun(#(x)( (pictureT(x,:)*picture(:,x))^-1*pictureT(x,:)*randn(n_ti
mepoints,1)),1:size(picture,2));

Evolution strategy with individual stepsizes

I'm trying to find a good solution with an evolution strategy for a 30 dimensional minimization problem. Now I have developed with success a simple (1,1) ES and also a self-adaptive (1,lambda) ES with one step size.
The next step is to create a (1,lambda) ES with individual stepsizes per dimension. The problem is that my MATLAB code doesn't work yet. I'm testing on the sphere objective function:
function f = sphere(x)
f = sum(x.^2);
end
The plotted results of the ES with one step size vs. the one with individual stepsizes:
The blue line is the performance of the ES with individual step sizes and the red one is for the ES with one step size.
The code for the (1,lambda) ES with multiple stepsizes:
% Strategy parameters
tau = 1 / sqrt(2 * sqrt(N));
tau_prime = 1 / sqrt(2 * N);
lambda = 10;
% Initialize
xp = (ub - lb) .* rand(N, 1) + lb;
sigmap = (ub - lb) / (3 * sqrt(N));
fp = feval(fitnessfct, xp');
evalcount = 1;
% Evolution cycle
while evalcount <= stopeval
% Generate offsprings and evaluate
for i = 1 : lambda
rand_scalar = randn();
for j = 1 : N
Osigma(j,i) = sigmap(j) .* exp(tau_prime * rand_scalar + tau * randn());
end
O(:,i) = xp + Osigma(:,i) .* rand(N,1);
fo(i) = feval(fitnessfct, O(:,i)');
end
evalcount = evalcount + lambda;
% Select best
[~, sortindex] = sort(fo);
xp = O(:,sortindex(1));
fp = fo(sortindex(1));
sigmap = Osigma(:,sortindex(1));
end
Does anybody see the problem?
Your mutations have a bias: they can only ever increase the parameters, never decrease them. sigmap is a vector of (scaled) upper minus lower bounds: all positive. exp(...) is always positive. Therefore the elements of Osigma are always positive. Then your change is Osigma .* rand(N,1), and rand(N,1) is also always positive.
Did you perhaps mean to use randn(N,1) instead of rand(N,1)? With that single-character change, I find that your code optimizes rather than pessimizing :-).