Matlab piecewise function in same plot as continuous - matlab

I'm trying to plot a piecewise function as an interpolation for the function f(x) = 1/(1+25x^2). This is how I plotted two functions previously when I wasn't dealing with piecewise.
z = linspace(-1,1,200);
yexact = 1./(1+25.*z.^2);
plot(z,yexact)
N=2;
x = size(N+1);
for i = 1:(N+1)
x(i) = -1+(1+cos(((2*i+1)*pi)/(2*(N+1))));
end
a = polyfit(x,1./(1+25.*x.^2),N);
yinter = polyval(a,z);
plot(z,yexact,z,yinter);
title('N = 2');
legend('exact','interpolation');
This was done for N = 2, 5, 10, 15, 20, 30. Now I need to change this to work for piecewise with the same N values. The x(i)'s are the intervals and the P(i)'s are the slopes of the piecewise function. So for N = 2, I need to plot P(1) from x(1) to x(2) and P(2) from x(2) to x(3).
N=2;
x = size(N+1);
P = size(N);
for i = 1:(N+1)
x(i) = -1 + 2*i/N;
end
for i = 1:N
P(i) = (1/(1+25*(x(i)).^2)) + ((i-1-x(i))/(x(i+1)-x(i)))*((1/(1+25*(x(i+1)).^2))-(1/(1+25*(x(i)).^2)));
end

All you have to do is to define your N values as a vector and, then, iterate over it. Into each iteration, the result returned by the computation over the current N value is plotted over the existing axis (for more information, visit this link of the official Matlab documentation).
Here is an example:
z = linspace(-1,1,200);
yexact = 1./(1+25.*z.^2);
plot(z,yexact);
hold on;
for n = [2 5 10]
x = size(n+1);
for i = 1:(n+1)
x(i) = -1+(1+cos(((2*i+1)*pi)/(2*(n+1))));
end
a = polyfit(x,1./(1+25.*x.^2),n);
yinter = polyval(a,z);
plot(z,yinter);
end
hold off;
And here is the resulting output:

Related

Sigmoid function in Logistic Regression

function g = sigmoid(z)
g = zeros(size(z));
data = load('ex2data1.txt');
y = data(:, 3);
theta = [0;1;2];
m = length(y);
one = ones(m,1);
X1 = data(:, [1, 2]);
X = [one X1];
zz = theta' * X';
ztr = zz';
g = 1/ (1 + exp(-ztr));
end
No matter what value i give z i am getting a 1x100 matrix with 1 being the first entry and rest are 0s, how is this supposed to work, is this working correctly ?
your function sigmoid is not dependent on the input z since it is used only in the line g = zeros(size(z)); and g is re-assigned again at the end of the function.

How to plot a discrete signal in matlab?

I want to plot a function y[n] = x[n+2]. My problem is that it does not plot in right range or even does not draw the zero sample points.
n = 1:6;
x = 1:1:8;
f = figure;
subplot(1,2,1)
stem(n, x(n));
axis([-3,8, 0, 7]);
xlabel('n');
ylabel('x[n]');
title('Subplot 1')
subplot(1,2,2)
stem(n, x(n + 2));
xlabel('n');
ylabel('y[n]');
title('Subplot 2')
How to change the variables n or x to get the right plot?
In the end, it ought to look like this:
You are confusing the concept of indices with your dependent variable. You should construct a function x which transforms an input n using the relationship that you know
function y = x(n)
% Set all outputs to 0
y = zeros(size(n));
% Replace the values that fall between 0 and 6 with their same value
y(n >= 0 & n <= 6) = n(n >= 0 & n <= 6);
end
Then you should pass this function a range of n values to evaluate.
nvalues = -3:8;
yvalues = x(nvalues);
stem(nvalues, yvalues)
You can also apply a transformation to the n values
nvalues = -3:8;
yvalues = x(nvalues + 2);
stem(nvalues, yvalues)

Plot solution of second order equation in MATLAB

Could you please help me with the following question:
I want to solve a second order equation with two unknowns and use the results to plot an ellipse.
Here is my function:
fun = #(x) [x(1) x(2)]*V*[x(1) x(2)]'-c
V is 2x2 symmetric matrix, c is a positive constant and there are two unknowns, x1 and x2.
If I solve the equation using fsolve, I notice that the solution is very sensitive to the initial values
fsolve(fun, [1 1])
Is it possible to get the solution to this equation without providing an exact starting value, but rather a range? For example, I would like to see the possible combinations for x1, x2 \in (-4,4)
Using ezplot I obtain the desired graphical output, but not the solution of the equation.
fh= #(x1,x2) [x1 x2]*V*[x1 x2]'-c;
ezplot(fh)
axis equal
Is there a way to have both?
Thanks a lot!
you can take the XData and YData from ezplot:
c = rand;
V = rand(2);
V = V + V';
fh= #(x1,x2) [x1 x2]*V*[x1 x2]'-c;
h = ezplot(fh,[-4,4,-4,4]); % plot in range
axis equal
fun = #(x) [x(1) x(2)]*V*[x(1) x(2)]'-c;
X = fsolve(fun, [1 1]); % specific solution
hold on;
plot(x(1),x(2),'or');
% possible solutions in range
x1 = h.XData;
x2 = h.YData;
or you can use vector input to fsolve:
c = rand;
V = rand(2);
V = V + V';
x1 = linspace(-4,4,100)';
fun2 = #(x2) sum(([x1 x2]*V).*[x1 x2],2)-c;
x2 = fsolve(fun2, ones(size(x1)));
% remove invalid values
tol = 1e-2;
x2(abs(fun2(x2)) > tol) = nan;
plot(x1,x2,'.b')
However, the easiest and most straight forward approach is to rearrange the ellipse matrix form in a quadratic equation form:
k = rand;
V = rand(2);
V = V + V';
a = V(1,1);
b = V(1,2);
c = V(2,2);
% rearange terms in the form of quadratic equation:
% a*x1^2 + (2*b*x2)*x1 + (c*x2^2) = k;
% a*x1^2 + (2*b*x2)*x1 + (c*x2^2 - k) = 0;
x2 = linspace(-4,4,1000);
A = a;
B = (2*b*x2);
C = (c*x2.^2 - k);
% solve regular quadratic equation
dicriminant = B.^2 - 4*A.*C;
x1_1 = (-B - sqrt(dicriminant))./(2*A);
x1_2 = (-B + sqrt(dicriminant))./(2*A);
x1_1(dicriminant < 0) = nan;
x1_2(dicriminant < 0) = nan;
% plot
plot(x1_1,x2,'.b')
hold on
plot(x1_2,x2,'.g')
hold off

MATLAB two for loops for a range and a recurrence equation

I have been given a recurrence equation: X(n) = AX(n-1)/1+BX(n-1). I am having trouble plotting this solution into MATLAB 2014b, which returns a figure which plots multiple curves that range from O:10 on a single graph. This is what I have so far in terms of making a range in the form of y:
function questions1 ()
N = 100; %Xn in the form of n
X = zeros (N,1);
X(1) = 0;
A = 2;
B = 1;
for y = 0:10; %this is the range from 0:10 to plot curves
for n = 2:N;
X(n) = A*X(n-1)/1+B*X(n-1); %this is the recurrence equation
end
end
hold on;
plot(X);
hold off;
Notice that
X(0)=0
x(1)=a*x(0)/1+b*x(0)=a*0+b*0=0
x(2)=a*x(1)+b*x(1)=a*0+b*0=0
..
∀n, x(n)=0
So your recursive equation is quite bad..
And you're replacing x(n) on each y-iteration, here is a fix:
function question1()
N = 100; %Xn in the form of n
X = zeros(N,1);
X(1) = 0;
A = 2;
B = 1;
hold on;
for y = 0:10; %this is the range from 0:10 to plot curves
for n = 2:N;
X(n) = A*X(n-1)/1+B*X(n-1); %this is the recurrence equation
end
plot(X);
end
hold off;

How can I (efficiently) compute a moving average of a vector?

I've got a vector and I want to calculate the moving average of it (using a window of width 5).
For instance, if the vector in question is [1,2,3,4,5,6,7,8], then
the first entry of the resulting vector should be the sum of all entries in [1,2,3,4,5] (i.e. 15);
the second entry of the resulting vector should be the sum of all entries in [2,3,4,5,6] (i.e. 20);
etc.
In the end, the resulting vector should be [15,20,25,30]. How can I do that?
The conv function is right up your alley:
>> x = 1:8;
>> y = conv(x, ones(1,5), 'valid')
y =
15 20 25 30
Benchmark
Three answers, three different methods... Here is a quick benchmark (different input sizes, fixed window width of 5) using timeit; feel free to poke holes in it (in the comments) if you think it needs to be refined.
conv emerges as the fastest approach; it's about twice as fast as coin's approach (using filter), and about four times as fast as Luis Mendo's approach (using cumsum).
Here is another benchmark (fixed input size of 1e4, different window widths). Here, Luis Mendo's cumsum approach emerges as the clear winner, because its complexity is primarily governed by the length of the input and is insensitive to the width of the window.
Conclusion
To summarize, you should
use the conv approach if your window is relatively small,
use the cumsum approach if your window is relatively large.
Code (for benchmarks)
function benchmark
clear all
w = 5; % moving average window width
u = ones(1, w);
n = logspace(2,6,60); % vector of input sizes for benchmark
t1 = zeros(size(n)); % preallocation of time vectors before the loop
t2 = t1;
th = t1;
for k = 1 : numel(n)
x = rand(1, round(n(k))); % generate random row vector
% Luis Mendo's approach (cumsum)
f = #() luisMendo(w, x);
tf(k) = timeit(f);
% coin's approach (filter)
g = #() coin(w, u, x);
tg(k) = timeit(g);
% Jubobs's approach (conv)
h = #() jubobs(u, x);
th(k) = timeit(h);
end
figure
hold on
plot(n, tf, 'bo')
plot(n, tg, 'ro')
plot(n, th, 'mo')
hold off
xlabel('input size')
ylabel('time (s)')
legend('cumsum', 'filter', 'conv')
end
function y = luisMendo(w,x)
cs = cumsum(x);
y(1,numel(x)-w+1) = 0; %// hackish way to preallocate result
y(1) = cs(w);
y(2:end) = cs(w+1:end) - cs(1:end-w);
end
function y = coin(w,u,x)
y = filter(u, 1, x);
y = y(w:end);
end
function jubobs(u,x)
y = conv(x, u, 'valid');
end
function benchmark2
clear all
w = round(logspace(1,3,31)); % moving average window width
n = 1e4; % vector of input sizes for benchmark
t1 = zeros(size(n)); % preallocation of time vectors before the loop
t2 = t1;
th = t1;
for k = 1 : numel(w)
u = ones(1, w(k));
x = rand(1, n); % generate random row vector
% Luis Mendo's approach (cumsum)
f = #() luisMendo(w(k), x);
tf(k) = timeit(f);
% coin's approach (filter)
g = #() coin(w(k), u, x);
tg(k) = timeit(g);
% Jubobs's approach (conv)
h = #() jubobs(u, x);
th(k) = timeit(h);
end
figure
hold on
plot(w, tf, 'bo')
plot(w, tg, 'ro')
plot(w, th, 'mo')
hold off
xlabel('window size')
ylabel('time (s)')
legend('cumsum', 'filter', 'conv')
end
function y = luisMendo(w,x)
cs = cumsum(x);
y(1,numel(x)-w+1) = 0; %// hackish way to preallocate result
y(1) = cs(w);
y(2:end) = cs(w+1:end) - cs(1:end-w);
end
function y = coin(w,u,x)
y = filter(u, 1, x);
y = y(w:end);
end
function jubobs(u,x)
y = conv(x, u, 'valid');
end
Another possibility is to use cumsum. This approach probably requires fewer operations than conv does:
x = 1:8
n = 5;
cs = cumsum(x);
result = cs(n:end) - [0 cs(1:end-n)];
To save a little time, you can replace the last line by
%// clear result
result(1,numel(x)-n+1) = 0; %// hackish way to preallocate result
result(1) = cs(n);
result(2:end) = cs(n+1:end) - cs(1:end-n);
If you want to preserve the size of your input vector, I suggest using filter
>> x = 1:8;
>> y = filter(ones(1,5), 1, x)
y =
1 3 6 10 15 20 25 30
>> y = (5:end)
y =
15 20 25 30