haltonset: understanding skip and leap - matlab

If i read the doc of how to construct a Halton quasi-random point set and it mentions that it's possible to 'skip' the first values and then retain the 'leap' values.
Don't understand what the 'skip' and 'leap' really mean.
Have tried the following:
>> p = haltonset(1,'Skip',50,'Leap',10); d = haltonset(1,'Skip',51,'Leap',9);
>> p(2:10), d(1:9)
ans =
0.7344
0.0703
0.7891
0.4766
0.5859
0.1797
0.9922
0.3164
0.6602
ans =
0.7969
0.7344
0.8828
0.5391
0.8516
0.6484
0.9609
0.6172
0.7539
>> p(2:10) == d(1:9)
ans =
0
0
0
0
0
0
0
0
0
Thought that it might be that that this would save 10 values to p and 9 to d. Also thought that d would have the same values as p. But this was not the case.
I then tested if the 'leap' would be the same as a normal way to make a vector
- ex: (1:leap:10)
>> p = haltonset(1,'Skip',50,'Leap',1); d = haltonset(1,'Skip',50,'Leap',2);
>> p(1:2:10)==d(1:5)
ans =
1
0
0
0
0
>> p = haltonset(1,'Skip',0,'Leap',1); d = haltonset(1,'Skip',0,'Leap',2);
>> p(1:2:10)==d(1:5)
ans =
1
0
0
0
0
but this seemed not to be the case..
Can anybody give a plain English explanation of how to interpreted the 'skip' and 'leap' variables.

I find the following description to be very clear [quoting this documentation page]:
Imagine a simple 1-D sequence that produces the integers from 1 to 10.
This is the basic sequence and the first three points are [1,2,3]:
Now look at how Scramble, Leap, and Skip work together:
Scramble: Scrambling shuffles the points in one of several
different ways. In this example, assume a scramble turns the sequence
into 1,3,5,7,9,2,4,6,8,10. The first three points are now [1,3,5]:
Skip: A Skip value specifies the number of initial points to
ignore. In this example, set the Skip value to 2. The sequence is now
5,7,9,2,4,6,8,10 and the first three points are [5,7,9]:
Leap: A Leap value specifies the number of points to ignore for
each one you take. Continuing the example with the Skip set to 2, if
you set the Leap to 1, the sequence uses every other point. In this
example, the sequence is now 5,9,4,8 and the first three points are
[5,9,4]:
EDIT:
Let me show with an example:
%# create 1D sequences (x: picked, .: ignored)
p00 = haltonset(1,'Skip',0,'Leap',0); %# xxxxxxxxxxxxxxx
p50 = haltonset(1,'Skip',5,'Leap',0); %# .....xxxxxxxxxx
p02 = haltonset(1,'Skip',0,'Leap',2); %# x..x..x..x..x..
p52 = haltonset(1,'Skip',5,'Leap',2); %# .....x..x..x..x
%# each pair of these are equal
[p50(1:10) p00(6:15)] %# skip vs. noskip
[p02(1:5) p00(1:3:13)] %# leap vs. noleap
[p52(1:4) p00(6:3:15)] %# skip+leap vs. noskip+noleap
In general:
skip = 50;
leap = 10;
p00 = haltonset(1,'Skip',0,'Leap',0);
p = haltonset(1,'Skip',skip,'Leap',leap);
num = 9;
[p(1:num) p00(skip+1:leap+1:num*leap+num-leap+skip)]

Related

Clean MATLAB time series data

I have a Matlab time series data set, which consist of a signal that can only be 1 or 0. How can I get rid of all the values except for the changing ones?
For example:
1
1
1
0
1
0
0
0
should ideally result in
1
0
1
0
while keeping the correct time values as well of course.
Thing is, that I need to find the frequency of the signal. The time should be measured from 0->1 to the next time 0->1 occurs. The smallest time / highest frequency is what I need in the end.
Thanks!
You can use the getsamples method to get a time series which contains a subset of the original samples. Remains to identify the indices where the time series has changed, for this purpose you can use diff and logical indexing:
ts = timeseries([1 1 1 0 1 0 0 0],1:8)
ts.getsamples([true;squeeze(diff(ts.Data)) ~= 0])
A simple and clever call to to diff should be sufficient:
>> A = [1; 1; 1; 0; 1; 0; 0; 0];
>> B = A(diff([-Inf; A]) ~= 0)
B =
1
0
1
0
The code is quite simple. diff finds pairs of differences in an array. Concretely, given an array A, the output is of the following structure:
B = [A(2) - A(1), A(3) - A(2), ..., A(N) - A(N-1)];
N is the total length of the signal. This results in a N-1 length signal. As such, a trick that you can use is to append the array A with -Inf (or some high non-zero value) so that when you find the difference between the first element of this appended array and the actual first element of the true array, you will get some non-zero change. That is registered with diff([-Inf; A]). The next thing you'll want is to check is to see where the differences are non-zero. Whenever there is a non-zero difference, that is a position that you want to keep because there has been a change that occurred. This produces a logical array and so the last step is to use this to index into your array A and thus get the result.
This only extracts out the signal you need however. If you'd like to extract the time in between unique elements, supposing you had some time vector t that was as long as your signal stored in A. You would first record the logical vector in a separate variable, then index into both your time array and the signal array to extract out what you need (original idea from user dfri):
ind = diff([-Inf; A]) ~= 0;
times = t(ind);
B = A(ind);
You can make use of diff and logical to save the results as a logical array, used as a subsequent index filter in your data (say t for time and y for boolean values ))
%// example
t = 0:0.01:0.07;
y = [1,1,1,0,1,0,0,0];
%// find indices to keep
keep = [true logical(diff(y))];
%// truncated data
tTrunc = t(keep)
yTrunc = y(keep)
with the results for the example as follows
tTrunc =
0 0.0300 0.0400 0.0500
yTrunc =
1 0 1 0

MATLAB - Create repeated sequences of ones and zeros with loops

I am trying to create a single column vector (out), which is comprised of a sequence of ones and zeros. These should occur in sets of length B and C respectively, which are repeated A number of times. For example:
out=[1
0
0
1
0
0
1
0
0]
It is currently set up as:
out=[0]; %not ideal, but used to initially define 'out'
A=3;
B=1;
C=2;
for i = 1:length(A)
for ii = 1:length(B)
out(end+1,1) = ones(ii,1);
end
for iii = 1:length(C)
out(end+1,1) = zeros(iii,1);
end
end
This is not working - current output:
out=[0
1
0]
How can I correct these loops to get the desired output? Also, is there a better way of achieving this with the given the inputs?
Many thanks.
1) You do not need to use length as this returns the length of an array type, so A,B,C will all be length of 1.
2) Just directly use the values as shown below. Also you can initialize an empty array with empty brackets []
3) If you're using the zeros and ones commands, these generate whole arrays/matrices and do not need to be in a loop. If you want to keep your loop version, just use =1 or =0
out=[]; %--> you can use this instead
A=3;
B=1;
C=2;
for i = 1:A
out(end+1:end+B,1) = ones(B,1);
out(end+1:end+C,1) = zeros(C,1);
end
... or of course to be more "Matlaby" just do what David said in the comments repmat([ones(B,1);zeros(C,1)],A,1), but the above is there to help you on your way.
How about some modulo arithmetic?
result = double(mod(0:(B+C)*A-1, B+C)<B).';
Example:
>> B = 2; %// number of ones in each period
>> C = 4; %// number of zeros in each period
>> A = 3; %// number of periods
>> result = double(mod(0:(B+C)*A-1, B+C)<B).'
result =
1
1
0
0
0
0
1
1
0
0
0
0
1
1
0
0
0
0
I can suggest 2 ways:
a)Using for loop-
A=3;
B=2;
C=3;
OneVector=ones(1,B); % B is the length of ones.
zeroVector=zeros(1,C); % C is the length of zeros.
combinedVector=cat(2,OneVector,zeroVector);
Warehouse=[]; % to save data
for(i=1:A)
Warehouse=cat(2,Warehouse,combinedVector);
end
b)using repmat:
OneVector=ones(1,B); % B is the length of ones.
zeroVector=zeros(1,C); % C is the length of zeros.
combinedVector=cat(2,OneVector,zeroVector);
Warehouse=repmat(combinedVector, [A,1]);
I hope, this will solve your problem.

A different method to check if an element is even in matlab?

This was the original question:
Write a script that asks the user for two positive numbers a and b and calculates the sum of the even numbers in the range [a,b]. The script should print a message with the range and the sum values as shown in the example below.
Enter the first number of the range: 3
Enter the last number of the range: 12
The sum of the even numbers in the range [3,12] is 40
I was able to solve it using the Rem function
a=input('Enter the first number of the range: ',d);
b=input('Enter the last number of the range: ',d);
m=0
For i=a:b;
If rem(i,2)=0
m=i+m;
End
End
fprintf('The sum of the even numbers in the range [%d,%d] is %d\n',a,b,m)
My question is, since I knew about the Rem function I was able to solve it. How does one do this without knowing the Rem function, and this brought up another question. What if they wanted me to list the prime numbers, what is the method of check in that case?
How about just
if ~mod(a,2)
m = sum(a:2:b)
else
m = sum(a+1:2:b)
end
In this case mod is only used to check only a. This is the only check that is needed
There are many ways to check if a number is even or not
here is one alternative:
round(number/2) == (number/2)
Sample 1
>> number
number =
81
>> ans
ans =
0
Sample 2
>> number
number =
92
>> ans
ans =
1
There is also an inbuilt function ( isprime ) for checking if a number is prime or not
Example from mathworks:
>> isprime([2 3 0 6 10])
ans =
1 1 0 0 0
For the sum of even numbers, you could use:
numbers = 2*(ceil(a/2):floor(b/2)); %// even numbers in the given range
result = sum(numbers);
To save operations, you can multiply by 2 only at the end:
result = 2*sum((ceil(a/2):floor(b/2)));
Or compute the result directly:
x = ceil(a/2);
y = floor(b/2);
result = (y+x)*(y-x+1);

Two FOR statements coupled into one

Is is possible to put two for statements into one statement. Something like
A = [ 0 0 0 5
0 2 0 0
1 3 0 0
0 0 4 0];
a=size(A);
b=size(A);
ind=0;
c=0;
for ({i=1:a},{j=1:b})
end
Your question is very broad, but one thing to consider is that in MATLAB you can often take advantage of linear indexing (instead of subscripting), without actually having to reshape the array. For example,
>> A = [ 0 0 0 5
0 2 0 0
1 3 0 0
0 0 4 0];
>> A(3,2)
ans =
3
>> A(7) % A(3+(2-1)*size(A,1))
ans =
3
You can often use this to your advantage in a for loop over all the elements:
for ii=1:numel(A),
A(ii) = A(ii) + 1; % or something more useful
end
Is the same as:
for ii=1:size(A,2),
for jj=1:size(A,1),
A(jj,ii) = A(jj,ii) + 1;
end
end
But to address your specific goal in this problem, as you stated in the comments ("I am storing the non zero elements in another matrix; with elements like the index number, value, row number and column number."), of making sparse matrix representation, it comes to this:
>> [i,j,s] = find(A);
>> [m,n] = size(A);
>> S = sparse(i,j,s,m,n)
S =
(3,1) 1
(2,2) 2
(3,2) 3
(4,3) 4
(1,4) 5
But that's not really relevant to the broader question.
Actually you can combine multiple loops into one for, however it would require you to loop over a vector containing all elements rather than the individual elements.
Here is a way to do it:
iRange = 1:2;
jRange = 1:3;
[iL jL] = ndgrid(iRange,jRange);
ijRange = [iL(:) jL(:)]';
for ij = ijRange
i = ij(1); j = ij(2);
end
Note that looping over the variables may be simpler, but perhaps this method has some advantages as well.
No
read this http://www.mathworks.com/help/matlab/matlab_prog/loop-control-statements.html
i also don't see any added value even if it was possible
No I don't think you can put two for loops in one line.
Depends on your operation, you may be able to reshape it and use one for loop. If you are doing something as simple as just printing out all elements,
B = reshape(A,a*b,1);
for i=1:a*b
c = B(i);
...
end

matlab fxn: find contiguous regions and return bounds in struct array

This is half a question and half a challenge to the matlab gurus out there:
I'd like to have a function take in a logical array (false/true) and give the beginning and ending of all the contiguous regions containing trues, in a struct array.
Something like this:
b = getBounds([1 0 0 1 1 1 0 0 0 1 1 0 0])
should return
b = 3x1 struct array with fields:
beg
end
and
>> b(2)
ans =
beg: 4
end: 6
I already have an implementation, but I don't really know how to deal with struct arrays well so I wanted to ask how you would do it - I have to go through mat2cell and deal, and when I have to deal with much larger struct arrays it becomes cumbersome. Mine looks like this:
df = diff([0 foo 0]);
a = find(df==1); l = numel(a);
a = mat2cell(a',ones(1,l))
[s(1:l).beg] = deal(a{:});
b = (find(df==-1)-1);
b = mat2cell(b',ones(1,l))
[s(1:l).end] = deal(b{:});
I don't see why you are using mat2cell, etc. You are making too much of the problem.
Given a boolean row vector V, find the beginning and end points of all groups of ones in the sequence.
V = [1 0 0 1 1 1 0 0 0 1 1 0 0];
You get most of it from diff. Thus
D = diff(V);
b.beg = 1 + find(D == 1);
This locates the beginning points of all groups of ones, EXCEPT for possibly the first group. So add a simple test.
if V(1)
b.beg = [1,b.beg];
end
Likewise, every group of ones must end before another begins. So just find the end points, again worrying about the last group if it will be missed.
b.end = find(D == -1);
if V(end)
b.end(end+1) = numel(V);
end
The result is as we expect.
b
b =
beg: [1 4 10]
end: [1 6 11]
In fact though, we can do all of this even more easily. A simple solution is to always append a zero to the beginning and end of V, before we do the diff. See how this works.
D = diff([0,V,0]);
b.beg = find(D == 1);
b.end = find(D == -1) - 1;
Again, the result is as expected.
b
b =
beg: [1 4 10]
end: [1 6 11]
By the way, I might avoid the use of end here, even as a structure field name. It is a bad habit to get into, using matlab keywords as variable names, even if they are only field names.
This is what I went with:
df = diff([0 foo 0]);
s = struct('on',num2cell(find(df==1)), ...
'off',num2cell(find(df==-1)-1));
I forgot about num2cell and the nice behavior of struct with cell arrays.