How to make a graph of a three-branches function in matlab - matlab-figure

How can I make this function's graph in Matlab, so that its body is depicted in the same graph (plot or subplot)?
t0=0.15
x(t)= 1, if 0<=t<(t0/2)
-2, if (t0/2)<=t<=(3/2)*t0
0, else

The real question you should be asking is "How to define a function that has branches?", since plotting is easy once the function is defined.
Here's a way using anonymous functions:
x_t = #(t,t0)1*(0<=t & t<t0/2)-2*(t0/2<=t & t<=(3/2)*t0); %// the 1* is redundant, I only
%// left it there for clarity
Note that the & operator expects arrays and not scalars.
Here's a way using heaviside (aka step) functions (not exactly what you wanted, due to its behavior on the transition point, but worth mentioning):
x_t = #(t,t0)1*heaviside(t)+(-1-2)*heaviside(t-t0/2)+2*heaviside(t-t0*3/2);
Note that in this case, you need to "negate" the previous heaviside once you leave its area of validity.
After defining this function, simply evaluate and plot.
t0 = 0.15;
tt = -0.1:0.01:0.5;
xx = x_t(tt,t0);
plot(tt,xx); %// Or scatter(), or any other plotting function
BTW, t0 does not have to be an input to x_t - if it is defined before x_t, the value of t0 that exists in the workspace at that time will be captured and used, but this also means that if t0 changes later, this will not affect x_t.

I'm not sure of what you want, but would it be it?
clc
close all
clear
t0 = 0.15;
t = 0:0.01:0.15;
x = zeros(size(t));
x(0 <= t & t < (t0/2)) = 1;
x((t0/2) <= t & t <= (3/2)*t0) = -2;
figure, plot(t, x, 'rd')
which gives,
Everything depends on the final t, for example if the end t is 0.3, then you'll get,

Related

Creating fractal image in a plot MATLAB but the plot is empty

I am writing a function to create a fractal image in a plot. When I run my code, a plot pops up but it is empty. I think the issues lies somewhere in my if/elseif statements, but I am having a hard time finding it. My code is:
function [] = fractal(x, y, N)
close all
start = [x, y];
X = zeros(N+1,1);
Y = zeros(N+1,1);
X = start;
hold on
for i = 1:N
prob = rand;
if prob >= 0.01
X(i+1,:) = 0;
Y(i+1,:) = 0.16*y(1);
elseif prob == 0.02:0.86
X(i+1,:) = (0.85*x(i))-(0.04*y(i));
Y(i+1,:) = (-0.04*x(i))+(0.85*y(i))+1.6;
elseif prob == 0.87:0.94
X(i+1,:) = (0.2*x(i))-(0.26*y(i));
Y(i+1,:) = (0.23*x(i))+(0.22*y(i))+1.6;
elseif prob == 0.95:1.0
X(i+1,:) = (-0.15*x(i))+(0.28*y(i));
Y(i+1,:) = (0.26*x(i))+(0.24*y(i))+0.44;
plot(X(i,:),Y(i,:),'.','Markersize',1)
axis equal
end
end
end
When I run my code with
>> fractal(1,1,1000)
... a plot comes up but it is empty.
Yup... it's your if statements, but there are more issues with your code though but we will tackle those later. Let's first address your if statements. If you want to compare in a range of values for examples, you need use the AND (&&) statement. In addition, you should place your plot code outside of any if/elseif/else statement. You currently have it inside your last elseif statement so plot will only run if the last condition is satisfied.
To be explicit, if you wish to compare if a value is in between a certain range, do something like:
if (prob >= a && prob < b)
and for elseif:
elseif (prob >= a && prob < b)
a and b are the lower and upper limits of what you want to compare. This includes a but excludes b in the comparison.
I also have a several comments and recommendations with your current code in order to get this to work:
You run your function with a single x and y value, but you are trying to access this x and y in your for loop as if these were arrays. I'm assuming this is recursive in nature so you need to actually use X and Y in your if/else conditions instead of x and y.
Since you are using single values, it is superfluous to use : to access the second dimension. Just leave that out.
You create X and Y but then overwrite X to be the starting location as a 2D array... I think you meant to replace X and Y's first element with the starting location instead.
Your first if statement I think is incorrect. You'd want to access Y(i) not Y(1) no?... given the behaviour of your code thus far.
Your first condition will definitely mess things up for you. This is saying that as long as the value is greater than or equal to 0.01, execute that statement. Otherwise, try and execute the other conditions which may in fact never work because you are looking for values that are greater than 0.01 where the first condition already handles that for you. I assume you meant to check if it was less than 0.01 instead.
Doing value comparecondition array in MATLAB means that this statement is true provided that any one of the values in array matches the condition provided by value. This will have unintended side effects with your current code.
Make sure that your ranges covered for each if statement are continuous (i.e. no gaps or disconnects between ranges). Right now, you are checking for values in 0.01 intervals. rand generates random values between 0 and 1 exclusive. What if you had a value of 0.15? None of your if conditions handle this so you need to use what I talked about above.
You are most likely getting a blank plot because your MarkerSize attribute is very small.... you set it to 1 pixel. Unless you have super human vision, you can't really visualize this. Make the MarkerSize larger.
Use drawnow; after you plot to immediately update the results to screen.
Therefore, with refactoring your code, you should make it look something like this:
function [] = fractal(x, y, N)
close all
start = [x, y];
X = zeros(N+1,1);
Y = zeros(N+1,1);
%// Change - Initialize first elements of X and Y to be the starting positions
X(1) = start(1);
Y(1) = start(2);
hold on
for i = 1:N
prob = rand;
if prob <= 0.01 %// Change
X(i+1) = 0;
Y(i+1) = 0.16*Y(i); %// Change
elseif (prob > 0.01 && prob <= 0.86) %// Change
X(i+1) = (0.85*X(i))-(0.04*Y(i)); %// Change
Y(i+1) = (-0.04*X(i))+(0.85*Y(i))+1.6; %// Change
elseif (prob > 0.86 && prob <= 0.94) %// Change
X(i+1) = (0.2*X(i))-(0.26*Y(i)); %// Change
Y(i+1) = (0.23*X(i))+(0.22*Y(i))+1.6; %// Change
elseif (prob > 0.94 && prob <= 1.0) %// Change
X(i+1) = (-0.15*X(i))+(0.28*Y(i)); %// Change
Y(i+1) = (0.26*X(i))+(0.24*Y(i))+0.44; %// Change
end
%// Change - move outside of if/else blocks
%// Also make marker size larger
plot(X(i),Y(i),'.','Markersize',18); %// Change
axis equal
%// Add just for kicks
drawnow;
end
end
I now get this figure when I do fractal(1,1,1000):
.... cool fractal btw!

ODE with time dependent input, How to speed Up without using interpolation?

I am trying to solve a system of ODEs and my input excitation is a function of time.
I have been using interp1 inside the integration function, but this doesn't seems like a very efficient way to do this. I know it is not, because once I change the input excitation to a sin function, which does not require an interp1 call inside the function, I get much much faster results. But doing interpolation every step takes about 10–20 times longer to converge. So, is there a better way of solving ODEs for arbitrary time dependent excitation, without needing to do interpolation or some other tricks to speed up?
I am just copying a modified version of a simple example from The MathWorks here:
Input Excitation is a gradually increasing sin function, but after some time later it becomes a constant amplitude sin function.
Dt = 0.01; % sampling time step
Amp0 = 2; % Final Amplitude of signal
Dur_G = 10; % Duration of gradually increasing part of signal
Dur_tot = 25; % Duration of total signal
t_G = 0 : Dt : Dur_G; % time of gradual part
A = linspace(0, Amp0, length(t_G));
carrier_1 = sin(5*t_G); % Unit Normal Signal
carrier_A0 = Amp0*sin(5*t_G);
out_G = A.*carrier_1; % Gradually Increasing Signal
% Total Signal with Gradual Constant Amplitude Parts
t_C = Dur_G+Dt:Dt:Dur_tot; % time of constant part
out_C = Amp0*sin(5*t_C); % Signal of constant part
ft = [t_G t_C]; % total time
f = [out_G out_C]; % total signal
figure; plot(ft, f, '-b'); % input excitation
function dydt = myode(t,y,ft,f)
f = interp1(ft,f,t); % Interpolate the data set (ft,f) at time t
g = 2; % a constant
dydt = -f.*y + g; % Evaluate ODE at time t
tspan = [1 5]; ic = 1;
opts = odeset('RelTol',1e-2,'AbsTol',1e-4);
[t,y] = ode45(#(t,y) myode(t,y,ft,f), tspan, ic, opts);
figure;
plot(t,y);
Note that I explained only first part of my problem above, which is solving system for a gradually increasing sin function.
In the second part, I need to solve it for an arbitrary input excitation (e.g., a ground acceleration input).
For this example, you could use griddedInterpolant class to get a bit of a speed-up:
ft = linspace(0,5,25);
f = ft.^2 - ft - 3;
Fp = griddedInterpolant(ft,f);
gt = linspace(1,6,25);
g = 3*sin(gt-0.25);
Gp = griddedInterpolant(gt,g);
tspan = [1 5];
ic = 1;
opts = odeset('RelTol',1e-2,'AbsTol',1e-4);
[t,y] = ode45(#(t,y)myode(t,y,Fp,Gp),tspan,ic,opts);
figure;
plot(t,y);
The ODE function is then:
function dydt = myode(t,y,Fp,Gp)
f = Fp(t); % Interpolate the data set (ft,f) at time t
g = Gp(t); % Interpolate the data set (gt,g) at time t
dydt = -f.*y + g; % Evaluate ODE at time t
On my system with R2015b, the call to ode45 is about three times faster (0.011 sec vs. 0.035 sec) for your example. You could get a bit more speed by switching to ode23. You can read more about the griddedInterpolant class here.
If your actual system, discretely switches between inputs particular points in time, then you should probably solve the problem piecewise by integrating each case separately. See this question and this question. If the system switches based on the value of the state variable(s), then you should use event location (see this question). However, if "solving ODEs for random time dependent excitation" means that you're adding random noise to the system, then you have an SDE rather than an ODE, which is a completely different beast.

NLMS Algorithm is not converging, multiple implementation resulting equally

The Normalized Least Mean Square algorithm is used in digital filtering, it basically tries to imitate an "unknown" filter so their difference (which is considered the error) tends to zero. The "factor" of convergence is that the error will start very high and with the continuous run of the algorithm it will be smaller.
The only difference between NLMS and LMS (which is its successor) is that NLMS normalizes the entry of the filter, so it won't be ease to high input power.
There are equations for both of the algorithms in the wiki page: https://en.wikipedia.org/wiki/Least_mean_squares_filter that is similar to my implementation of it.
I'm currently using an adaptative plant so I can filter a white noise input into a lowpass filter and try to adapt my algorithm coefficients to immitate the lowpass, its implemented in matlab:
clear all;close all;clc;
fid = fopen('ruidoBranco.pcm', 'rb');
s = fread(fid, 'int16');
fclose(fid);
itera = length(s);
L = 50;
passo = 0.00000000001;
H = passaBaixa(L,1000,2);
W = zeros(L,1);
y = zeros(itera,1);
sav_erro = zeros(itera,1);
for i=(L+1):itera,
D=0;
Y=0;
for j=1:(L),
Y = Y + W(j,1)*s(i-j,1);
D = D + H(j,1)*s(i-j,1);
end
erro = D-Y;
k=passo*erro;
for j=1:(L),
W(j,1) = W(j,1)+(k*s(i-j,1)/(s(i-j,1)^2+0.000001));
end
sav_erro(i,1) = (erro);
end
subplot(2,1,1);
plot(sav_erro);
subplot(2,1,2);
plot(W);
hold on;
plot(H,'r');
fid = fopen('saidaFIR.pcm', 'wb');
fwrite(fid,sav_erro,'int16');
fclose(fid);
The "passaBaixa" function is the lowpass filter that I was saying before:
function H = passaBaixa(M,FC,op)
iteracoes = M;
FS=8000;
FC=FC/FS;
M=iteracoes;
H = zeros(iteracoes,1);
for i=1:iteracoes,
if(i-M/2==0)
H(i,1)=2*pi*FC;
else
H(i,1)=sin(2*pi*FC*(i-M/2))/(i-M/2);
end
if(op==1)
H(i,1)=H(i,1);
else if (op==2)
H(i,1) = H(i,1)*(0.42-0.5*cos(2*pi*i/M)+0.08*cos(4*pi*i/M));
else
H(i,1)=H(i,1)*(0.54-0.46*cos(2*pi*i/M));
end
end
end
soma = sum(H);
for i=1:iteracoes,
H(i,1)=H(i,1)/soma;
end
end
The file ruidoBranco.pcm is simply an white noise generated with 80.000 samples.
The obtained result is the following:
In which the top plot is the error and the bottom plot is the impulse response of the low pass filter (red) and the "adapted" algorithm filter (blue).
Its not converging, it should look something like this:
As you can see the top plot converge into almost 0 error and the bottom plot has no more blue because its behind the red one (since it almost perfectly ajusted its coeficients to the filter)
I would like to know if there are any visible mistakes made by my implementation and perhaps this might be a future reference for people with similar mistakes.
The fix was that I wasn't using the correct multiplication for the algorithm, it needs to be a dot product instead of simple the power of 2
so the fix is in the for loop:
dotprod = dot(s(i-j,1),s(i-j,1));
for j=1:(L),
W(j,1) = W(j,1)+(k*s(i-j,1)/dotprod);
end

MATLAB loop optimization

I have a matrix, matrix_logical(50000,100000), that is a sparse logical matrix (a lot of falses, some true). I have to produce a matrix, intersect(50000,50000), that, for each pair, i,j, of rows of matrix_logical(50000,100000), stores the number of columns for which rows i and j have both "true" as the value.
Here is the code I wrote:
% store in advance the nonzeros cols
for i=1:50000
nonzeros{i} = num2cell(find(matrix_logical(i,:)));
end
intersect = zeros(50000,50000);
for i=1:49999
a = cell2mat(nonzeros{i});
for j=(i+1):50000
b = cell2mat(nonzeros{j});
intersect(i,j) = numel(intersect(a,b));
end
end
Is it possible to further increase the performance? It takes too long to compute the matrix. I would like to avoid the double loop in the second part of the code.
matrix_logical is sparse, but it is not saved as sparse in MATLAB because otherwise the performance become the worst possible.
Since the [i,j] entry counts the number of non zero elements in the element-wise multiplication of rows i and j, you can do it by multiplying matrix_logical with its transpose (you should convert to numeric data type first, e.g matrix_logical = single(matrix_logical)):
inter = matrix_logical * matrix_logical';
And it works both for sparse or full representation.
EDIT
In order to calculate numel(intersect(a,b))/numel(union(a,b)); (as asked in your comment), you can use the fact that for two sets a and b, you have
length(union(a,b)) = length(a) + length(b) - length(intersect(a,b))
so, you can do the following:
unLen = sum(matrix_logical,2);
tmp = repmat(unLen, 1, length(unLen)) + repmat(unLen', length(unLen), 1);
inter = matrix_logical * matrix_logical';
inter = inter ./ (tmp-inter);
If I understood you correctly, you want a logical AND of the rows:
intersct = zeros(50000, 50000)
for ii = 1:49999
for jj = ii:50000
intersct(ii, jj) = sum(matrix_logical(ii, :) & matrix_logical(jj, :));
intersct(jj, ii) = intersct(ii, jj);
end
end
Doesn't avoid the double loop, but at least works without the first loop and the slow find command.
Elaborating on my comment, here is a distance function suitable for pdist()
function out = distfun(xi,xj)
out = zeros(size(xj,1),1);
for i=1:size(xj,1)
out(i) = sum(sum( xi & xj(i,:) )) / sum(sum( xi | xj(i,:) ));
end
In my experience, sum(sum()) is faster for logicals than nnz(), thus its appearance above.
You would also need to use squareform() to reshape the output of pdist() appropriately:
squareform(pdist(martrix_logical,#distfun));
Note that pdist() includes a 'jaccard' distance measure, but it is actually the Jaccard distance and not the Jaccard index or coefficient, which is the value you are apparently after.

How to speed this kind of for-loop?

I would like to compute the maximum of translated images along the direction of a given axis. I know about ordfilt2, however I would like to avoid using the Image Processing Toolbox.
So here is the code I have so far:
imInput = imread('tire.tif');
n = 10;
imMax = imInput(:, n:end);
for i = 1:(n-1)
imMax = max(imMax, imInput(:, i:end-(n-i)));
end
Is it possible to avoid using a for-loop in order to speed the computation up, and, if so, how?
First edit: Using Octave's code for im2col is actually 50% slower.
Second edit: Pre-allocating did not appear to improve the result enough.
sz = [size(imInput,1), size(imInput,2)-n+1];
range_j = 1:size(imInput, 2)-sz(2)+1;
range_i = 1:size(imInput, 1)-sz(1)+1;
B = zeros(prod(sz), length(range_j)*length(range_i));
counter = 0;
for j = range_j % left to right
for i = range_i % up to bottom
counter = counter + 1;
v = imInput(i:i+sz(1)-1, j:j+sz(2)-1);
B(:, counter) = v(:);
end
end
imMax = reshape(max(B, [], 2), sz);
Third edit: I shall show the timings.
For what it's worth, here's a vectorized solution using IM2COL function from the Image Processing Toolbox:
imInput = imread('tire.tif');
n = 10;
sz = [size(imInput,1) size(imInput,2)-n+1];
imMax = reshape(max(im2col(imInput, sz, 'sliding'),[],2), sz);
imshow(imMax)
You could perhaps write your own version of IM2COL as it simply consists of well crafted indexing, or even look at how Octave implements it.
Check out the answer to this question about doing a rolling median in c. I've successfully made it into a mex function and it is way faster than even ordfilt2. It will take some work to do a max, but I'm sure it's possible.
Rolling median in C - Turlach implementation

Resources