I've started out with MATLAB a few hours ago and began with plotting some simple functions, e.g.:
k = -20:20;
a = 0.01;
x_k = exp(-a * k.^2)
f_1 = figure(1);
plot(k, x_k)
This works fine and plots each value of k on the x-axis, with its corresponding function response at the y-axis. Now I've defined my own function:
function [y] = triangle(t, a)
if (a <= t) & (t <= 0)
y = (1/a * t + 1) * a
elseif (0 <= t) & (t <= a)
y = (-1/a * t + 1) * a
else
error('Function not defined for these values')
end
end
I now want to plot triangle for a range of t with a specific parameter a. So I call:
a = 1;
int = (2 * a) / 20;
t = -a:int:a;
f_1 = figure(1);
plot(t, triangle(t, a))
… but my function errors out because the entire t array (vector, I suppose?) is passed to it instead of each element of t.
How do I plot my triangle function for a specific a, over a defined range?
I've also tried fplot(triangle(a), t) (since fplot accepts a function as an argument) but that again complains about triangle not receiving enough input arguments—rightly so, but I need to pass a to it as well.
The problem of this is the that you pass a vector to your function triangle but you want to check every single if-statement for each single value of the vetor t. So either you use a for-loop within the function triangle or you could also do it by using this:
function [y] = triangle(t, a)
y = ((a <= t) & (t <= 0)) .* ((1/a * t + 1) * a) + ((0 <= t) & (t <= a)) .* ((-1/a * t + 1) * a);
end
I know it looks somehow weird, but if you need me to explain it a bif more in detail, I can do this for you ;-)
EDIT: Let's shortly examine the problem: You pass a vector t to the function, which means that the first if statement if (a <= t) & (t <= 0) splitted looks like this:
(a <= t) % resulting in:
ans =
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1
(t <= 0) % resulting in:
ans =
1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0
so combining them via the AND operator (& for vectors), this obviously gives you
ans =
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
So this branch wont be executed. The elseif gives you:
(0 <= t)
ans =
0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1
(t <= a)
ans =
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
((0 <= t) & (t <= a))
ans =
0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1
so this won't be executed either even though you'd want it to be executed for the second half of your values because you'd like to check the two statements for each value-pair on it's own.
So by leaving away the statements completely you could do it like I posted above: simply multiply the result of the logical statements elementwise with the piecewise function which will yield the result you want to calculate :-)
The best approach is to define the triangle function so that it admits vector inputs. You and do it with logical indexing, which selects a range of values of t depending on a logical condition:
function [y] = triangle(t, a)
y = NaN(size(t)); %// pre-allocate and define NaN as default return value
ind = (a <= t) & (t <= 0); %// select first range
y(ind) = (1/a * t(ind) + 1) * a; %//compute output for first range
ind = (0 <= t) & (t <= a); %// select second range
y(ind) = (-1/a * t(ind) + 1) * a; %//compute output for second range
end
This returns NaN for out-of-range values. As an example, for your t,
>> triangle(t, a)
ans =
Columns 1 through 13
NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN 1.0000 0.9000 0.8000
Columns 14 through 21
0.7000 0.6000 0.5000 0.4000 0.3000 0.2000 0.1000 0
Once you define the function like this, you can do plot(t, triangle(t, a)).
To pass your function to fplot, you need to use an anonymous function (like what is called a lambda in many other programming languages).
This is done with the # syntax in matlab (see help function_handle for how to use this).
So your fplot try should be:
fplot(#(x) triangle(x,a), t([1 end]))
Note that the t input for fplot is the bounds in which you want to evaluate your function, not the values to evaluate itself (you can use bounds in combination with fplot's third input argument for some control over that).
That said, as other posters also noted, the part of your example input where t<0 end up right in your else branch and yields an error.
Related
I want to run turnMatrix(30,X) in MATLAB. I get this error message:
Undefined function or variable 'X'.
If I change X to 1 it is successful. My code is below.
function turnMatrix(d,b)
a = d * pi / 180 ;
if b == X % 1
R = [1 0 0 0 ; 0 cos(a) -sin(a) 0 ; 0 sin(a) cos(a) 0 ; 0 0 0 1];
elseif b == Y % 2
R = [cos(a) 0 sin(a) 0 ; 0 1 0 0 ; -sin(a) 0 cos(a) 0 ; 0 0 0 1];
elseif b == Z % 3
R = [1 0 0 0 ; 0 cos(a) -sin(a) 0 ; 0 sin(a) cos(a) 0 ; 0 0 0 1];
end
R
end
It looks like you are really expecting/wanting to specify the second input as a characters/string, that is
turnMatrix(30,'X')
Note the single quotes around 'X', which say that it is literally the character string 'X', not the value of the variable X.
Then inside the function you need
if b == 'X'
elseif b == 'Y'
elseif b == 'Z'
end
That is, compare the value of variable b to the character 'X'. The way you have it, you are trying to compare the value of variable b to the value of variable X, but variable X doesn't exist and hence the error.
Note also, that if you were comparing anything other than a single character (and even in the single character case) you'd be better off using a switch-case construct rather than if-else
switch b
case 'X'
case 'Y'
case 'Z'
end
let us consider following code for impulse function
function y=impulse_function(n);
y=0;
if n==0
y=1;
end
end
this code
>> n=-2:2;
>> i=1:length(n);
>> f(i)=impulse_function(n(i));
>>
returns result
f
f =
0 0 0 0 0
while this code
>> n=-2:2;
>> for i=1:length(n);
f(i)=impulse_function(n(i));
end
>> f
f =
0 0 1 0 0
in both case i is 1 2 3 4 5,what is different?
Your function is not defined to handle vector input.
Modify your impluse function as follows:
function y=impulse_function(n)
[a b]=size(n);
y=zeros(a,b);
y(n==0)=1;
end
In your definition of impulse_function, whole array is compared to zero and return value is only a single number instead of a vector.
In the first case you are comparing an array to the value 0. This will give the result [0 0 1 0 0], which is not a simple true or false. So the statement y = 0; will not get executed and f will be [0 0 0 0 0] as shown.
In the second you are iterating through the array value by value and passing it to the function. Since the array contains the value 0, then you will get 1 back from the function in the print out of f (or [0 0 1 0 0], which is an impulse).
You'll need to modify your function to take array inputs.
Perhaps this example will clarify the issue further:
cond = 0;
if cond == 0
disp(cond) % This will print 0 since 0 == 0
end
cond = 1;
if cond == 0
disp(cond) % This won't print since since 1 ~= 0 (not equal)
end
cond = [-2 -1 0 1 2];
if cond == 0
disp(cond) % This won't print since since [-2 -1 0 1 2] ~= 0 (not equal)
end
You could define your impulse function simply as this one -
impulse_function = #(n) (1:numel(n)).*n==0
Sample run -
>> n = -6:4
n =
-6 -5 -4 -3 -2 -1 0 1 2 3 4
>> out = impulse_function(n)
out =
0 0 0 0 0 0 1 0 0 0 0
Plot code -
plot(n,out,'o') %// data points
hold on
line([0 0],[1 0]) %// impulse point
Plot result -
You can write an even simpler function:
function y=impulse_function(n);
y = n==0;
Note that this will return y as a type logical array but that should not affect later numerical computations.
If I know that K = kron ( A , B ),where kron is the Kronecker product of matrices as defined in MATLAB, how can I find A and B from a given matrix K?
for example suppose that
K = [1 0 0 0 ;0 1 0 0 ; 0 1 0 0 ;0 1 0 0 ;1 0 0 0 ;0 1 0 0 ;0 1 0 0 ;0 1 0 0 ;1 0 0 0 ;0 1 0 0 ;0 1 0 0 ;0 1 0 0 ;0 0 1 0 ;0 0 0 1 ;0 0 0 1 ;0 0 0 1 ]
is there any way to find A and B, such that K = kron ( A , B )?
In this case, A and B are as follows:
A = [ 1 0 ; 1 0 ; 1 0 ; 0 1 ]
B = [ 1 0 ; 0 1 ; 0 1 ; 0 1 ]
Short Discussion and Solution Code
You can't find both A and B, given a K, because there could be many possible A's and B's to produce a certain kron matrix, K. Thus, alongwith K, you need either A or B to get the remaining input B or A respectively.
Case #1 Given A and K (kron matrix), you can find B with -
B = K(1:size(K,1)/size(A,1),1:size(K,2)/size(A,2))./A(1)
Case #2 Given B and K (kron matrix), you can find A with -
A = K(1:size(B,1):end,1:size(B,2):end)./B(1)
Thus, if not the entire other input, you would at least need to know the size of it and one of the elements of it, preferably the first element.
Function Code
You can very easily convert that to a function code for an easy plug-n-play usage -
%// INVERSE_KRON Inverse of Kronecker tensor product to find one of the inputs.
% // INVERSE_KRON(K,ARRAY,INPUT_ID) finds one of the inputs used for calculating the
% // Kronecker tensor product given the other input and the ID of that other input.
% // Thus, if K was obtained with K = KRON(A,B), one must use -
% // A = INVERSE_KRON(K,B,2) to find A, and
% // B = INVERSE_KRON(K,A,1) to find B.
function out = inverse_kron(K,array,input_id)
switch input_id
case 1
out = K(1:size(K,1)/size(array,1),1:size(K,2)/size(array,2))./array(1);
case 2
out = K(1:size(array,1):end,1:size(array,2):end)./array(1);
otherwise
error('The Input ID must be either 1 or 2')
end
return;
Typical use case would look like this -
K = kron(A,B); %// Get kron product
A = inverse_kron(K,B,2) %// Recover A
B = inverse_kron(K,A,1) %// Recover B
Note: For a vector case, one other related question and answer could be found here.
I have code like below:
N=10;
R=[1 1 1 1 1 0 0 0 0 0;1 1 1 1 1 1 1 1 1 1];
p=[0.1,0.2,0.01];
B = zeros(N , N);
B(1:N,1:N) = eye(N);
C=[B;R];
for q=p(1:length(p))
Rp=C;
for i=1:N
if(rand < p)
Rp(i,:) = 0;
end
end
end
from this code I vary the value of p. So for different value of p, i am getting different Rp. Now I want to get the total number of "1"'s from each Rp matrix. it means may be for p1 I am getting Rp1=5, for p2, Rp=4.
For example
Rp1=[1 0 0 0 0;0 1 0 0 0;0 0 0 0 0],
Rp2=[1 0 0 0 0;0 1 0 0 0;1 0 0 0 0],
Rp3=[0 0 0 0 0;0 1 0 0 0;0 0 0 0 0],
So total result will be 2,3,1.
I want to get this result.
If the matrix contains only 0 and 1 you are trying to count the nonzero values and there is a function for that called nnz
n = nnz(Rp);
As I mentioned in the comments you should replace
if(rand < p)
with
if(rand < q)
Then you can add the number of nonzero values to a vector like
r = [];
for q=p(1:length(p))
Rp=C;
for i=1:N
if(rand < p)
Rp(i,:) = 0;
end
end
r = [r nnz(Rp)];
end
Then r will contain your desired result. There are many ways to improve your code as mentioned in other answers and comments.
Assuming Rp is your matrix, then simply do one of the following:
If your matrix only contains zeros and ones
sum(Rp(:))
Or if your matrix contains multiple values:
sum(Rp(:)==1)
Note that for two dimensional matrices sum(Rp(:)) is the same as sum(sum(Rp))
I think your real question is how to save this result, you can do this by assigning it to an indexed varable, for example:
S(count) = sum(Rp(:));
This will require you to add a count variable that increases with one every step of the loop. It will be good practice (and efficient) to initialize your variable properly before the loop:
S = zeros(length(p),1);
If you need to count the 1's in any matrix M you should be able to do sum(M(:)==1)
MATLAB: What does the "greater than" symbol in the expression: (1-X).*(X>1) mean or do?
X is a column vector and theoretically each element of X lies in the range 0 to 1 inclusive. Numerically due to finite precision, an element might be slightly in excess of 1.0, so this may be a sort of condition or constraint.
Any ideas?
In the context you describe, it is essentially "selecting" elements greater than 1 and subtracting them from 1; all other elements in the result (those in positions where X <= 1) will be 0 because they have been multiplied by the zero from the result of X > 1. Here is an example:
>> X = [0 0.5 1 1.5 2];
>> X > 1
ans =
0 0 0 1 1
>> (1 - X)
ans =
1.0000 0.5000 0 -0.5000 -1.0000
>> (1 - X) .* (X > 1)
ans =
0 0 0 -0.5000 -1.0000
In the last result, the three zeros in the first result have been multiplied (elementwise) with the first three values in the middle result, and the two ones have been multiplied by the last two values in the middle result. In this way, it has effectively selected the results of (1 - X) in the positions where X > 1 to begin with.
Obviously, if there are never any values of X greater than 1, then the result will always be all zeros.
The expression (X > 1) returns true (logical '1') for every element that is greater than 1, and false (logical '0') otherwise. Therefore, X > 1 produces a boolean vector (of the same size as X) containing '1's where the corresponding elements in X are greater than 1. I strongly recommend that you get more familiar with MATLAB operators.
As for the rest of the expression:
(1 - X) simply returns an vector of the same dimensions as X, where each element is the result of subtracting the corresponding element in X from 1.
.* is an element-wise multiplication, so the final result is a vector (of the same dimensions as X), where the i-th element equals (1 - Xi) if Xi>1, and 0 otherwise.
Example
>> X = [-1 4 0 2 -3];
>> X > 1
ans =
0 1 0 1 0
>> 1 - X
ans =
2 -3 1 -1 4
>> (1 - X) .* (X > 1)
ans =
0 -3 0 -1 0