I have two same dimensioned vectors sig1 and sig2, both have more than 1 million data. With the condition that whenever the value of a vector falls below a threshold, a pointer will point to alternate vector (switching). This way I want to form a new vector sws from the pointer's values. Below code works fine, the only issue is, it takes long time. Is there any other way to speed up the code? :
thresh = -70;
i=1;
flag1 = 1; % 1 means sig1, 0 means sig2
flag2 = 0; % 1 means switch happened in this loop, 0 means no switch happened in this loop
while(i <= numel(sws))
if(flag1 == 1)
sws(i)=sig1(i);
else
sws(i)=sig2(i);
end
if(sws(i) < thresh)
if(flag2==1)
i=i+1;
else
flag1 = ~flag1;
end
flag2= ~flag2;
else
flag2 = 0;
i=i+1;
end
end
Related
I have created this code from scratch. I want to make a plot and/or histogram of my "Observed" and "State" (these are 2 matrices). Some problem occurs at the 200th iteration, where my State matrix just becomes all 0's, there is no data being input into the State matrix. Can anyone troubleshoot the code? My possible states are {1,2,3}.
UPDATE:
When I adjust my n value, it adjusts how much of length T it will fill. So, n=5, only runs for 1/5 of T and n=1, run for entire length of T. I need an nxT matrix at the end (5X1000). The problem lies in the way I setup my for loops.
I still cannot solve the error though.
%Initialize A,pi,T
N = 3; # of states
%A is transition prob matrix
A = [.99,.005,.005;.005,.990,.005;.005,.005,.990];
%pi is initial state vector
pi = [1/3,1/3,1/3];
%T is # of observations per simulation
T = 1000;
%n is # of simulations
n = 5;
%Allocate space for the state matrix
State = zeros(n,T);
Observe = zeros(n,T);
%Create dummy emission matrix, must be row stochastic
B = ones(n,T)./T;
%loop over # of simulations
for i=1:1:n
x = rand(1);
if x <= (1/3)
State(i,1) = 1;
elseif x > (1/3) && x <= (2/3)
State(i,1) = 2;
else
State(i,1) = 3;
end
if State(i,1) == 1
b = -1;
elseif State(i,1) == 2
b = 0;
else
b = 1;
end
Observe(i,1)= normrnd(b,1);
for k=2:1:T
%Possible state 1,2,3
State(k) = randsample(N, 1, true, A(State(k-1),:));
if State == 1
c = -1;
elseif State == 2
c = 0;
else
c = 1;
end
Observe(i,k)= normrnd(c,1);
end
end
State(k) = randsample(N, 1, true, A(State(k-1),:));
This line is missing index (i) in position 1 inside State(k-1). It should be:
State(i,k) = randsample(N, 1, true, A(State(i,k-1),:));
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 have a short (and I reckon silly as well) question about manipulation of variables in Matlab codes. How can I keep a constant value of a variable (assigned during the execution of the code), while the code executes further? So basically put the value into the memory and don't change it all. As an example of the code on which I am working right now:
if SystemTriggered ==1;
if Accelerationflag == 1;
for n = 1:1:100
AOrder = 1/2*HMSpeed^2/(Acc+n*2*pi);
if AOrder<Alim;
k = n;
Accelerationflag = 0;
break;
end
end
end
Offset = k;
AccOffset = PhaseIni - Offset*2*pi;
%Derivation conditions
if My condition here;
HmSpeedReached = 1;
end
end
So I am looking for an option, how I can keep the calculated value of "Offset" when I got "HmSpeedReached =1". Since we have a "for" cycle in the beginning (that will assign a value to K and then to Offset), so I just need to keep that number as a value of the variable all the time, after the condition of HmSpeedReached is satisfied...
Thank you in advance.
If I understand correctly then you want the following:
Keep assigning Offset = k whilst looping through your code
If HmSpeedReached = 1 has been set, then don't change the Offset value
This code (adapted from yours) should work
% Initially make sure HmSpeedReached is not equal to 1
HmSpeedReached = 0;
% Your code with addition...
if SystemTriggered ==1;
if Accelerationflag == 1;
for n = 1:1:100
AOrder = 1/2*HMSpeed^2/(Acc+n*2*pi);
if AOrder<Alim;
k = n;
Accelerationflag = 0;
break;
end
end
end
% Add a condition here to check if Offset should be updated, if HmSpeedReached is not 1
if HmSpeedReached ~= 1
Offset = k;
end
AccOffset = PhaseIni - Offset*2*pi;
%Derivation conditions
if My condition here;
HmSpeedReached = 1;
end
end
If instead you want to save a vector of Offset values, every time some condition is met, then use something like this:
Offset = [];
HmSpeedReached = 0;
if SystemTriggered ==1;
if Accelerationflag == 1;
for n = 1:1:100
AOrder = 1/2*HMSpeed^2/(Acc+n*2*pi);
if AOrder<Alim;
k = n;
Accelerationflag = 0;
break;
end
end
end
% Add a condition here to check if Offset should be updated, if HmSpeedReached is not 1
if CONDITION FOR SAVING OFFSET
Offset = [Offset, k];
end
AccOffset = PhaseIni - Offset*2*pi;
%Derivation conditions
if My condition here;
HmSpeedReached = 1;
end
end
Assign HmSpeedReached = 0 at the top and test for HmSpeedReached equal zero as a condition to change the variable Offset.
I am getting this error in MatLab when trying to fill in an array. MatLab is saying that the assignment B(j, 1) = z(z-counter) contains a negative or non integer value. However when I look at the variables values in the workspace after trying to execute the code.
j =1, counter =1, z =1
for j= 1:1:totalSizeOfMatrix
if( j <= totalNumberInBottom)
if( mod(j, lengthOfBottomRow) == 1)
counter= counter +1;
end
z = mod(j,lengthOfBottomRow);
B(j,1) = z(z-counter);
end
if( j > totalNumberInBottom && j <= totalNumberNotInTop)
if( mod(j, lengthOfSecondRow) == 1)
counter= counter +1;
end
z = mod(j,lengthOfSecondRow);
B(j,1) = z(z-counter);
end
if( j > totalNumberInBottom)
if( mod(j, lengthOfTopRow) == 1)
counter= counter +1;
end
z = mod(j,lengthOfTopRow);
B(j,1) = z(z-counter);
end
end
If z = 1 and counter = 1, then z - counter is zero.
Therefore, z(z-counter) is trying to access z(0), which is an error.
range = min(x):0.0001:max(x);
N = numel(range);
x = sort(x);
hit = 0;
i=1;
for j = 1:(N-1)
if range(j) <= x(i) && x(i) < range(j+1)
hit = hit + 1;
i = i+1;
if x(i) == x(i-1)
while x(i) == x(i-1) % If there are more than one of the same
hit = hit + 1; % numbers in succession, this allows x and
i = i+1; % hit to carry on incrementing.
end %while
end %if
end %if
end %for
disp(hit)
This code compares 'range' and 'x'. It checks to see if 'x' is between values in 'range', if so the 'hit' counter gets incremented and so does the current value of 'x'.
Problem is, on some random values of x (as far as I can tell they are random), although they should satisfy the inequality in the 'IF' statement, the 'IF' statement gets ignored, the for loop continues and thus the final 'hit' value is wrong.
'x' is usually a 1D array about a million or so wide.
for this example, let
`x = [-2.1792 -2.1759 -2.1758 -2.1748 -2.1658 -2.1648 -2.1646 -2.1604 -2.1603 -2.1550]`
'hit' should equal '10' but instead outputs '2' since it decides to skip the 'IF' statement at 'j=35'.
To clarify. When 'j=35', range(j) = -2.1758 and i=3 meaning x(i)=-2.1758
I'm pretty sure that:
range(j) <= x(i) && x(i) < range(j+1)
-2.1758 <= -2.1758 && -2.1758 < -2.1757 %**edited, meant -2.1757 not -2.1759**
Is true.
I hope I'm just doing something silly here that I can't see. Sorry if it's a badly formatted question, it's my first here.
Cheers in advance.
A subsequent number x(i) could pass this test:
if range(j) <= x(i) && x(i) < range(j+1)
Without actually being equal to its neighbor:
if x(i) == x(i-1)
It could be infinitesimally larger and thus you move to the next j and it is out of range. Your inner while needs the same condition as the outer if. And you can skip the if COND while COND and just do while COND since it will work the same.
Would the following code not be simpler, faster, and give the same result?
x = sort(x)
hit = sum(diff(x)==0);