I am trying to implement a map / function which has the equation Bernoulli Shift Map
x_n+1 = 2* x_n mod 1
The output of this map will be a binary number which will be either 0/1.
So, I generated the first sample x_1 using rand. The following is the code. The problem is I am getting real numbers. When using a digital calculator, I can get binary, whereas when using Matlab, I am getting real numbers. Please help where I am going wrong. Thank you.
>> x = rand();
>> x
x =
0.1647
>> y = mod(2* x,1)
y =
0.3295
The dyadic transformation seems to be a transformation from [0,1) continuous to [0,1) continuous. I see nothing wrong with your test code if you are trying to implement the dyadic mapping. You should be expecting output in the [0,1)
I misunderstood your question because I focused on the assumption you had that the output should be binary [0 or 1], which is wrong.
To reproduce the output of the dyadic transformation as in the link you provided, your code works fine (for 1 value), and you can use this function to calculate N terms (assuming a starting term x0) :
function x = dyadic(x0,n)
x = zeros(n,1) ; %// preallocate output vector
x(1) = x0 ; %// assign first term
for k=2:n
x(k) = mod( 2*x(k-1) , 1) ; %// calculate all terms of the serie
end
Note that the output does not have to be binary, it has to be between 0 and 1.
In the case of integers, the result of mod(WhateverInteger,1) is always 0, but in the case of Real numbers (which is what you use here), the result of mod(AnyRealNumber,1) will be the fractional part, so a number between 0 and 1. (1 is mathematically excluded, 0 is possible by the mod(x,1) operation, but in the case of your serie it means all the successive term will be zero too).
Related
I am working on developing a suite classifiers for EEG signals and I will be needing a zero-crossings around mean function, defined in the following manner:
Ideally if I have some vector with a range of values representing a sinusoid or any time varying signal, I will want to return a vector of Booleans of the same size as the vector saying if that particular value is a mean crossing. I have the following Matlab implementation:
ZX = #(x) sum(((x - mean(x)>0) & (x - mean(x)<0)) | ((x - mean(x)<0) & (x - mean(x)>0)));
Testing it on toy data:
[0 4 -6 9 -20 -5]
Yields:
0
EDIT:
Yet I believe it should return:
3
What am I missing here?
An expression like:
((x-m)>0) & ((x-m)<0)
is always going to return a vector of all zeros because no individual element of x is both greater and less than zero. You need to take into account the subscripts on the xs in the definition of ZX:
((x(1:end-1)-m)>0) & ((x(2:end)-m)<0)
You can use the findpeaks function on -abs(x), where x is your original data, to find the peak locations. This would give you the zero crossings in general for continuous signals which do not have zero as an actual maximum of the signal.
t = 0:0.01:10;
x = sin(pi*t);
plot(t,x)
grid
y = -abs(x);
[P,L] = findpeaks(y,t);
hold on
plot(L,P,'*')
A simple solution is to use movprod, and count the products which are negative, i.e.,
cnt = sum(sign(movprod(x-mean(x),2))<0);
With your toy example, you will get cnt = 3.
Problem : How do I use a continuous map - The Link1: Bernoulli Shift Map to model binary sequence?
Concept :
The Dyadic map also called as the Bernoulli Shift map is expressed as x(k+1) = 2x(k) mod 1. In Link2: Symbolic Dynamics, explains that the Bernoulli Map is a continuous map and is used as the Shift Map. This is explained further below.
A numeric trajectory can be symbolized by partitioning into appropriate regions and assigning it with a symbol. A symbolic orbit is obtained by writing down the sequence of symbols corresponding to the successive partition elements visited by the point in its orbit. One can learn much about the dynamics of the system by studying its symbolic orbits. This link also says that the Bernoulli Shift Map is used to represent symbolic dynamics.
Question :
How is the Bernoulli Shift Map used to generate the binary sequence? I tried like this, but this is not what the document in Link2 explains. So, I took the numeric output of the Map and converted to symbols by thresholding in the following way:
x = rand();
y = mod(2* x,1) % generate the next value after one iteration
y =
0.3295
if y >= 0.5 then s = 1
else s = 0
where 0.5 is the threshold value, called the critical value of the Bernoulli Map.
I need to represent the real number as fractions as explained here on Page 2 of Link2.
Can somebody please show how I can apply the Bernoulli Shift Map to generate symbolized trajectory (also called time series) ?
Please correct me if my understanding is wrong.
How do I convert a real valued numeric time series into symbolized i.e., how do I use the Bernoulli Map to model binary orbit /time series?
You can certainly compute this in real number space, but you risk hitting precision problems (depending on starting point). If you're interested in studying orbits, you may prefer to work in a rational fraction representation. There are more efficient ways to do this, but the following code illustrates one way to compute a series derived from that map. You'll see the period-n definition on page 2 of your Link 2. You should be able to see from this code how you could easily work in real number space as an alternative (in that case, the matlab function rat will recover a rational approximation from your real number).
[EDIT] Now with binary sequence made explicit!
% start at some point on period-n orbit
period = 6;
num = 3;
den = 2^period-1;
% compute for this many steps of the sequence
num_steps = 20;
% for each step
for n = 1:num_steps
% * 2
num = num * 2;
% mod 1
if num >= den
num = num - den;
end
% simplify rational fraction
g = gcd(num, den);
if g > 1
num = num / g;
den = den / g;
end
% recover 8-bit binary representation
bits = 8;
q = 2^bits;
x = num / den * q;
b = dec2bin(x, bits);
% display
fprintf('%4i / %4i == 0.%s\n', num, den, b);
end
Ach... for completeness, here's the real-valued version. Pure mathematicians should look away now.
% start at some point on period-n orbit
period = 6;
num = 3;
den = 2^period-1;
% use floating point approximation
x = num / den;
% compute for this many steps of the sequence
num_steps = 20;
% for each step
for n = 1:num_steps
% apply map
x = mod(x*2, 1);
% display
[num, den] = rat(x);
fprintf('%i / %i\n', num, den);
end
And, for extra credit, why is this implementation fast but daft? (HINT: try setting num_steps to 50)...
% matlab vectorised version
period = 6;
num = 3;
den = 2^period-1;
x = zeros(1, num_steps);
x(1) = num / den;
y = filter(1, [1 -2], x);
[a, b] = rat(mod(y, 1));
disp([a' b']);
OK, this is supposed to be an answer, not a question, so let's answer my own questions...
It's fast because it uses Matlab's built-in (and highly optimised) filter function to handle the iteration (that is, in practice, the iteration is done in C rather than in M-script). It's always worth remembering filter in Matlab, I'm constantly surprised by how it can be turned to good use for applications that don't look like filtering problems. filter cannot do conditional processing, however, and does not support modulo arithmetic, so how do we get away with it? Simply because this map has the property that whole periods at the input map to whole periods at the output (because the map operation is multiply by an integer).
It's daft because it very quickly hits the aforementioned precision problems. Set num_steps to 50 and watch it start to get wrong answers. What's happening is the number inside the filter operation is getting to be so large (order 10^14) that the bit we actually care about (the fractional part) is no longer representable in the same double-precision variable.
This last bit is something of a diversion, which has more to do with computation than maths - stick to the first implementation if your interest lies in symbol sequences.
If you only want to deal with rational type of output, you'll first have to convert the starting term of your series into a rational number if it is not. You can do that with:
[N,D] = rat(x0) ;
Once you have a numerator N and a denominator D, it is very easy to calculate the series x(k+1)=mod(2*x(k), 1) , and you don't even need a loop.
for the part 2*x(k), it means all the Numerator(k) will be multiplied by successive power of 2, which can be done by matrix multiplication (or bsxfun for the lover of the function):
so 2*x(k) => in Matlab N.*(2.^(0:n-1)) (N is a scalar, the numerator of x0, n is the number of terms you want to calculate).
The Mod1 operation is also easy to translate to rational number: mod(x,1)=mod(Nx,Dx)/Dx (Nx and Dx being the numerator and denominator of x.
If you do not need to simplify the denominator, you could get all the numerators of the series in one single line:
xn = mod( N.*(2.^(0:n-1).'),D) ;
but for visual comfort, it is sometimes better to simplify, so consider the following function:
function y = dyadic_rat(x0,n)
[N,D] = rat(x0) ; %// get Numerator and Denominator of first element
xn = mod( N.*(2.^(0:n-1).'),D) ; %'// calculate all Numerators
G = gcd( xn , D ) ; %// list all "Greatest common divisor"
y = [xn./G D./G].' ; %'// output simplified Numerators and Denominators
If I start with the example given in your wiki link (x0=11/24), I get:
>> y = dyadic_rat(11/24,8)
y =
11 11 5 2 1 2 1 2
24 12 6 3 3 3 3 3
If I start with the example given by Rattus Ex Machina (x0=3/(2^6-1)), I also get the same result:
>> y = dyadic_rat(3/63,8)
y =
1 2 4 8 16 11 1 2
21 21 21 21 21 21 21 21
I have the following function:
I have to generate 2000 random numbers from this function and then make a histogram.
then I have to determine how many of them is greater that 2 with P(X>2).
this is my function:
%function [ output_args ] = Weibullverdeling( X )
%UNTITLED Summary of this function goes here
% Detailed explanation goes here
for i=1:2000
% x= rand*1000;
%x=ceil(x);
x=i;
Y(i) = 3*(log(x))^(6/5);
X(i)=x;
end
plot(X,Y)
and it gives me the following image:
how can I possibly make it to tell me how many values Do i Have more than 2?
Very simple:
>> Y_greater_than_2 = Y(Y>2);
>> size(Y_greater_than_2)
ans =
1 1998
So that's 1998 values out of 2000 that are greater than 2.
EDIT
If you want to find the values between two other values, say between 1 and 4, you need to do something like:
>> Y_between = Y(Y>=1 & Y<=4);
>> size(Y_between)
ans =
1 2
This is what I think:
for i=1:2000
x=rand(1);
Y(i) = 3*(log(x))^(6/5);
X(i)=x;
end
plot(X,Y)
U is a uniform random variable from which you can get the X. So you need to use rand function in MATLAB.
After which you implement:
size(Y(Y>2),2);
You can implement the code directly (here k is your root, n is number of data points, y is the highest number of distribution, x is smallest number of distribution and lambda the lambda in your equation):
X=(log(x+rand(1,n).*(y-x)).*lambda).^(1/k);
result=numel(X(X>2));
Lets split it and explain it detailed:
You want the k-th root of a number:
number.^(1/k)
you want the natural logarithmic of a number:
log(number)
you want to multiply sth.:
numberA.*numberB
you want to get lets say 1000 random numbers between x and y:
(x+rand(1,1000).*(y-x))
you want to combine all of that:
x= lower_bound;
y= upper_bound;
n= No_Of_data;
lambda=wavelength; %my guess
k= No_of_the_root;
X=(log(x+rand(1,n).*(y-x)).*lambda).^(1/k);
So you just have to insert your x,y,n,lambda and k
and then check
bigger_2 = X(X>2);
which would return only the values bigger than 2 and if you want the number of elements bigger than 2
No_bigger_2=numel(bigger_2);
I'm going to go with the assumption that what you've presented is supposed to be a random variate generation algorithm based on inversion, and that you want real-valued (not complex) solutions so you've omitted a negative sign on the logarithm. If those assumptions are correct, there's no need to simulate to get your answer.
Under the stated assumptions, your formula is the inverse of the complementary cumulative distribution function (CCDF). It's complementary because smaller values of U give larger values of X, and vice-versa. Solve the (corrected) formula for U. Using the values from your Matlab implementation:
X = 3 * (-log(U))^(6/5)
X / 3 = (-log(U))^(6/5)
-log(U) = (X / 3)^(5/6)
U = exp(-((X / 3)^(5/6)))
Since this is the CCDF, plugging in a value for X gives the probability (or proportion) of outcomes greater than X. Solving for X=2 yields 0.49, i.e., 49% of your outcomes should be greater than 2.
Make suitable adjustments if lambda is inside the radical, but the algebra leading to solution is similar. Unless I messed up my arithmetic, the proportion would then be 55.22%.
If you still are required to simulate this, knowing the analytical answer should help you confirm the correctness of your simulation.
Say I have two functions f(x), g(x), and a vector:
xval=1:0.01:2
For each of these individual x values, I want to define a vector of y-values, covering the y-interval bounded by the two functions (or possibly a matrix where columns are x-values, and rows are y-values).
How would I go about creating a loop that would handle this for me? I have absolutely no idea myself, but I'm sure some of you have something right up your sleeve. I've been sweating over this problem for a few hours by now.
Thanks in advance.
Since you wish to generate a matrix, I assume the number of values between f(x) and g(x) should be the same for every xval. Let's call that number of values n_pt. Then, we also know what the dimensions of your result matrix rng will be.
n_pt = 10;
xval = 1 : 0.01 : 2;
rng = zeros(n_pt, length(xval));
Now, into the loop. Once we know what the y-values returned by f(x) and g(x) are, we can use linspace to give us n_pt equally spaced points between them.
for n = 1 : length(xval)
y_f = f(xval(n))
y_g = g(xval(n))
rng(:, n) = linspace(y_f, y_g, n_pt)';
end
This is nice because with linspace you don't need to worry about whether y_f > y_g, y_f == y_g or y_f < y_g. That's all taken care of already.
For demsonstration, I run this example for xval = 1 : 0.1 : 2 and the two sinusoids f = #(x) sin(2 * x) and g = #(x) sin(x) * 2. The points are plotted using plot(xval, rng, '*k');.
I'm trying to use MatLab code as a way to learn math as a programmer.
So reading I'm this post about subspaces and trying to build some simple matlab functions that do it for me.
Here is how far I got:
function performSubspaceTest(subset, numArgs)
% Just a quick and dirty function to perform subspace test on a vector(subset)
%
% INPUT
% subset is the anonymous function that defines the vector
% numArgs is the the number of argument that subset takes
% Author: Lasse Nørfeldt (Norfeldt)
% Date: 2012-05-30
% License: http://creativecommons.org/licenses/by-sa/3.0/
if numArgs == 1
subspaceTest = #(subset) single(rref(subset(rand)+subset(rand))) ...
== single(rref(rand*subset(rand)));
elseif numArgs == 2
subspaceTest = #(subset) single(rref(subset(rand,rand)+subset(rand,rand))) ...
== single(rref(rand*subset(rand,rand)));
end
% rand just gives a random number. Converting to single avoids round off
% errors.
% Know that the code can crash if numArgs isn't given or bigger than 2.
outcome = subspaceTest(subset);
if outcome == true
display(['subset IS a subspace of R^' num2str(size(outcome,2))])
else
display(['subset is NOT a subspace of R^' num2str(size(outcome,2))])
end
And these are the subset that I'm testing
%% Checking for subspaces
V = #(x) [x, 3*x]
performSubspaceTest(V, 1)
A = #(x) [x, 3*x+1]
performSubspaceTest(A, 1)
B = #(x) [x, x^2, x^3]
performSubspaceTest(B, 1)
C = #(x1, x3) [x1, 0, x3, -5*x1]
performSubspaceTest(C, 2)
running the code gives me this
V =
#(x)[x,3*x]
subset IS a subspace of R^2
A =
#(x)[x,3*x+1]
subset is NOT a subspace of R^2
B =
#(x)[x,x^2,x^3]
subset is NOT a subspace of R^3
C =
#(x1,x3)[x1,0,x3,-5*x1]
subset is NOT a subspace of R^4
The C is not working (only works if it only accepts one arg).
I know that my solution for numArgs is not optimal - but it was what I could come up with at the current moment..
Are there any way to optimize this code so C will work properly and perhaps avoid the elseif statments for more than 2 args..?
PS: I couldn't seem to find a build-in matlab function that does the hole thing for me..
Here's one approach. It tests if a given function represents a linear subspace or not. Technically it is only a probabilistic test, but the chance of it failing is vanishingly small.
First, we define a nice abstraction. This higher order function takes a function as its first argument, and applies the function to every row of the matrix x. This allows us to test many arguments to func at the same time.
function y = apply(func,x)
for k = 1:size(x,1)
y(k,:) = func(x(k,:));
end
Now we write the core function. Here func is a function of one argument (presumed to be a vector in R^m) which returns a vector in R^n. We apply func to 100 randomly selected vectors in R^m to get an output matrix. If func represents a linear subspace, then the rank of the output will be less than or equal to m.
function result = isSubspace(func,m)
inputs = rand(100,m);
outputs = apply(func,inputs);
result = rank(outputs) <= m;
Here it is in action. Note that the functions take only a single argument - where you wrote c(x1,x2)=[x1,0,x2] I write c(x) = [x(1),0,x(2)], which is slightly more verbose, but has the advantage that we don't have to mess around with if statements to decide how many arguments our function has - and this works for functions that take input in R^m for any m, not just 1 or 2.
>> v = #(x) [x,3*x]
>> isSubspace(v,1)
ans =
1
>> a = #(x) [x(1),3*x(1)+1]
>> isSubspace(a,1)
ans =
0
>> c = #(x) [x(1),0,x(2),-5*x(1)]
>> isSubspace(c,2)
ans =
1
The solution of not being optimal barely scratches the surface of the problem.
I think you're doing too much at once: rref should not be used and is complicating everything. especially for numArgs greater then 1.
Think it through: [1 0 3 -5] and [3 0 3 -5] are both members of C, but their sum [4 0 6 -10] (which belongs in C) is not linear product of the multiplication of one of the previous vectors (e.g. [2 0 6 -10] ). So all the rref in the world can't fix your problem.
So what can you do instead?
you need to check if
(randn*subset(randn,randn)+randn*subset(randn,randn)))
is a member of C, which, unless I'm mistaken is a difficult problem: Conceptually you need to iterate through every element of the vector and make sure it matches the predetermined condition. Alternatively, you can try to find a set such that C(x1,x2) gives you the right answer. In this case, you can use fminsearch to solve this problem numerically and verify the returned value is within a defined tolerance:
[s,error] = fminsearch(#(x) norm(C(x(1),x(2)) - [2 0 6 -10]),[1 1])
s =
1.999996976386119 6.000035034493023
error =
3.827680714104862e-05
Edit: you need to make sure you can use negative numbers in your multiplication, so don't use rand, but use something else. I changed it to randn.