If I have a matrix and I want to apply a function to each row of the matrix. This function has three possible outputs, either x = 0, x = 1, or x > 0. There's a couple things I'm running into trouble with...
1) The cases that output x = 1 or x > 0 are different and I'm not sure how to differentiate between the two when writing my script.
2) My function isn't counting correctly? I think this might be a problem with how I have my loop set up?
This is what I've come up with. Logically, I feel like this should work (except for the hiccup w/ the first problem I've stated)
[m n] = size(matrix);
a = 0; b = 0; c = 0;
for i = 1 : m
x(i) = function(matrix(m,:));
if x > 0
a = a + 1;
end
if x == 0
b = b + 1;
end
if x == 1
c = c + 1;
end
end
First you probably have an error in line 4. It probably should be i instead of m.
x(i) = function(matrix(i,:));
You can calculate a, b and c out of the loop:
a = sum(x>0);
b = sum(x==0);
c = sum(x==1);
If you want to distinguish x==1 and x>0 then may be with sum(xor(x==1,x>0)).
Also you may have problem with precision error when comparing double values with 0 and 1.
Related
I am sending a matrix to my function modifikuj, where I want to replace the elements of the matrix with:
1 if element is a prime number
0 if element is a composite number
0.5 if element is 1
I dont understand why it is not working. I just started with MATLAB, and I created this function:
function B = modifikuj(A)
[n,m] = size(A);
for i = 1:n
for j = 1:m
prost=1;
if (A(i,j) == 1)
A(i,j) = 0.5;
else
for k = 2:(A(i,j))
if(mod(A(i,j),k) == 0)
prost=0;
end
end
if(prost==1)
A(i,j)=1;
else
A(i,j)=0;
end
end
end
end
With
A = [1,2;3,4];
D = modifikuj(A);
D should be:
D=[0.5, 1; 1 0];
In MATLAB you'll find you can often avoid loops, and there's plenty of built in functions to ease your path. Unless this is a coding exercise where you have to use a prescribed method, I'd do the following one-liner to get your desired result:
D = isprime( A ) + 0.5*( A == 1 );
This relies on two simple tests:
isprime( A ) % 1 if prime, 0 if not prime
A == 1 % 1 if == 1, 0 otherwise
Multiplying the 2nd test by 0.5 gives your desired condition for when the value is 1, since it will also return 0 for the isprime test.
You are not returning anything from the function. The return value is supposed to be 'B' according to your code but this is not set. Change it to A.
You are looping k until A(i,j) which is always divisible by itself, loop to A(i,j)-1
With the code below I get [0.5,1;1,0].
function A = modifikuj(A)
[n,m] = size(A);
for i = 1:n
for j = 1:m
prost=1;
if (A(i,j) == 1)
A(i,j) = 0.5;
else
for k = 2:(A(i,j)-1)
if(mod(A(i,j),k) == 0)
prost=0;
end
end
if(prost==1)
A(i,j)=1;
else
A(i,j)=0;
end
end
end
end
In addition to #EuanSmith's answer. You can also use the in built matlab function in order to determine if a number is prime or not.
The following code will give you the desired output:
A = [1,2;3,4];
A(A==1) = 0.5; %replace 1 number with 0.5
A(isprime(A)) = 1; %replace prime number with 1
A(~ismember(A,[0.5,1])) = 0; %replace composite number with 0
I've made the assumption that the matrice contains only integer.
If you only want to learn, you can also preserve the for loop with some improvement since the function mod can take more than 1 divisor as input:
function A = modifikuj(A)
[n,m] = size(A);
for i = 1:n
for j = 1:m
k = A(i,j);
if (k == 1)
A(i,j) = 0.5;
else
if all(mod(k,2:k-1)) %check each modulo at the same time.
A(i,j)=1;
else
A(i,j)=0;
end
end
end
end
And you can still improve the prime detection:
2 is the only even number to test.
number bigger than A(i,j)/2 are useless
so instead of all(mod(k,2:k-1)) you can use all(mod(k,[2,3:2:k/2]))
Note also that the function isprime is a way more efficient primality test since it use the probabilistic Miller-Rabin algorithme.
I'm trying to figure out how to perform a successive XOR on a row in matlab, where each element is the result of XORing itself and the previous element, for example:
If the row is
x = [1 0 1 1]
I would want the result to be:
x[0] = 1
x[1] = x[0]^x[1] = 1
x[2] = x[1]^x[2] = 0
x[3] = x[2]^x[3] = 1
x = [1 1 0 1]
I have tried using xor(A,B) but this only seems to work on multiple arrays at once. I also have tried this loop:
for k = 10000:1
for i = 1:64
allchallenge_full(k,i+1) = xor(allchallenge_full(k,i).^allchallenge_full(k,i+1))
end
end
But this simply results in all 1s.
Any suggestions are appreciated! Thank you!
If the input x is just zeros and ones:
result = mod(cumsum(x), 2);
To apply it on each row of a matrix x:
result = mod(cumsum(x,2), 2);
If you want to keep things simple, a for loop, together with the xor function (^ in Matlab represents the raising to a power), should work fine:
x = [1 0 1 1];
for i = 2:numel(x)
x(i) = xor(x(i-1),x(i));
end
The final output is the expected one:
x =
1 1 0 1
Remember that, in Matlab, indexing is one-based and not zero-based as in many other programming languages. The first element of x is, therefore, x(1) and not x(0).
k = 0.019;
Pstar = 100;
H = 33;
h = 0.1;
X = 36;
N = round(X/h);
t = zeros(1,N+1);
P = zeros(1,N+1);
P(1) = 84;
t(1) = 0;
yHeun = zeros(1,N+1);
yHeun(1)=84;
a = 1; b = 100;
while b-a >0.5
c = (a+b)/2;
for n = 1:N
t(n+1) = t(n) + h;
Inside = nthroot(sin(2*pi*t/12),15);
Harvest = c*0.5*(Inside+1);
P(n+1) = P(n) + h*(k*P(n)*(Pstar-P(n))-Harvest(n));
if P < 0
P = 0;
end
yHeun(n+1) = yHeun(n) + h*0.5*((k*P(n)*(Pstar-P(n))-Harvest(n))+(k*P(n+1)*(Pstar-P(n+1))-Harvest(n+1)));
end
if sign(yHeun(c)) == sign(yHeun(a))
c = a;
else
c = b;
end
end
disp(['The root is between ' num2str(a) ' and ' num2str(b) '.'])
This is the code i'm trying to run and i know it probably sucks but im terrible at coding and every time i try to run the code, it says:
Attempted to access yHeun(50.5); index must be a positive integer or
logical.
Error in Matlab3Q4 (line 30)
if sign(yHeun(c)) == sign(yHeun(a))
I don't have ANY idea how to make yHeun(c or a or whatever) return anything that would be an integer. I dont think i did the while+for loop right either.
Question: "Begin with the higher bound of H being 100 (the high value results in a population of 0 after 36 months), and the lower bound being 1. Put the solver from Problem #3 above in the middle of a while loop and keep bisecting the higher and lower bounds of H until the difference between the higher and lower bound is less than 0.5."
I guess that line 30 (with the error) is this one:
if sign(yHeun(c)) == sign(yHeun(a))
Here, I guess c is equal to 50.5, as a result of c = (a+b)/2 above (BTW you can discover whether I guessed right by debugging - try adding disp(c) before line 30).
To force a number to be an integer, use floor:
c = floor((a+b)/2);
It seems you are trying to use some sort of divide-and-conquer algorithm; it should be enough to stop when b - a is equal to 1.
I have a function that I was wondering if it was possible to vectorize it and not have to use a for loop. The code is below.
a=1:2:8
for jj=1:length(a)
b(jj)=rtfib(a(jj)); %fibbonacci function
end
b
output below:
a =
1 3 5 7
>>>b =
1 3 8 21
I was trying to do it this way
t = 0:.01:10;
y = sin(t);
but doing the code below doesn't work any suggestions?
ps: I'm trying to keep the function rtfib because of it's speed and I need to use very large Fibonacci numbers. I'm using octave 3.8.1
a=1:2:8
b=rtfib(a)
Here's the rtfib code below as requested
function f = rtfib(n)
if (n == 0)
f = 0;
elseif (n==1)
f=1;
elseif (n == 2)
f = 2;
else
fOld = 2;
fOlder = 1;
for i = 3 : n
f = fOld + fOlder;
fOlder = fOld;
fOld = f;
end
end
end
You can see that your function rtfib actually computes every Fibonacci number up to n.
You can modify it so that is stores and returns all these number, so that you only have to call the function once with the maximum number you need:
function f = rtfib(n)
f=zeros(1,n+1);
if (n >= 0)
f(1) = 0;
end
if (n>=1)
f(2)=1;
end
if (n >= 2)
f(3) = 2;
end
if n>2
fOld = 2;
fOlder = 1;
for i = 3 : n
f(i+1) = fOld + fOlder;
fOlder = fOld;
fOld = f(i+1);
end
end
end
(It will return fibonnaci(n) in f(n+1), if you don't need the 0 you could change it so that it returns fibonnaci(n) in f(n) if you prefer)
Then you only need to call
>>f=rtfib(max(a));
>>b=f(a+1)
b =
1 3 8 21
If you don't want to store everything you could modify the function rtfib a little more, so that it takes the the array a as input, compute the Fibonacci numbers up to max(a) but only stores the one needed, and it would directly return b.
Both solutions will slow down rtfib itself but it will be a lot faster than calculating the Fibonacci numbers from 0 each time.
Let me describe my problem with an example. Suppose we have matrix A:
A =
1 0 1
1 1 1
0 1 1
and matrix B:
B =
1 1
1 1
How do i write function C = func(A, B) to check if B exists in A or not?
If it exists in A, the function returns C = [0 0 0; 0 1 1; 0 1 1], and if it does not, the function returns C = [0 0 0; 0 0 0; 0 0 0];.
Edit:
It should be mentioned that if A is m-by-n, and B is p-by-q, then m > p and p > q always.
Thanks in advance.
The most efficient requires the signal processing toolbox. Then you can simply use xcorr2(). Following your example, the following should work:
C = xcorr2 (A, B);
[Row, Col] = find (C == max (C(:)));
%% these are not the coordinates for the center of the best match, you will
%% have to find where those really are
%% The best way to understand this is to strip the "padding"
row_shift = (size (B, 1) - 1)/2;
col_shift = (size (B, 2) - 1)/2;
C = C(1+row_shift:end-row_shift, 1+col_shift:end-col_shift)
[Row, Col] = find (C == max (C(:)));
if (B == A(Row-row_shift:Row+row_shift, Col-col_shift:Col+col_shift))
disp ("B shows up in A");
endif
The code above looks a bit convoluted because I'm trying to cover inputs of any size (still only odd sized) but should work.
If you don't have this toolbox, I think you can use the Octave code for it which should require only small adjustments. Basically, the only three lines that matter follow (note that the code is under GPL):
[ma,na] = size(a);
[mb,nb] = size(b);
c = conv2 (a, conj (b (mb:-1:1, nb:-1:1)));
In Octave, if you are using at least the signal package 1.2.0, xcorr2 can also take an extra option "coeff" which calculates the normalized cross correlation. This will have a value of 1 when the match is perfect, so you can simplify this with:
C = xcorr2 (A, B, "coeff");
if (any (C(:) == 1)
display ("B shows up in A");
endif
I would do a loop to check resized sub-matrix of A. My code stops after B is found once but it could be updated to count the number of found occurrences.
A = [1 0 1; 1 1 1; 0 1 1; 0 0 0];
B = [1 1; 1 1];
[m n] = size(A);
[p q] = size(B);
found = 0;
x = 0;
while ~found && (x+p-1 < m)
y = 0;
x = x + 1;
while ~found && (y+q-1 < n)
y = y + 1;
A(x:x+p-1,y:y+q-1)
found = isequal(A(x:x+p-1,y:y+q-1),B);
end
end
fprintf('Found Matrix B in A(%d:%d, %d:%d)\n',x,x+p-1,y,y+q-1);
Maybe there is some vectored way, but this is a straight forward function which just slides across A and checks for B:
function ret=searchmat(A,B)
ret=zeros(size(A));
for k=0:size(A,1)-size(B,1)
for l=0:size(A,2)-size(B,2)
if isequal(A(1+k:size(B,1)+k,1+l:size(B,2)+l),B)
ret(1+k:size(B,1)+k,1+l:size(B,2)+l)=1; % or B as you wish
end
end
end
end
If B is discovered more than once, it's also marked with ones. If you want to quit after the first match, you can just put in a return statement in the if clause.