calculating the function limit interatively - matlab

How to calculate the limit of a function interatively in Matlab, by closer to the given limit value? The accuracy of closing is 10^(-7)
I suppose that that the taylor formula should be used, but don't know how to apply it there.
The function itself is :
The limit is 88.
In other words, the assignment is to present limits as series with assigned variables, compute them step-by-step, approach the limits' value with 10^(-7) precision.
example code of task:
syms x;
F=log(1+sin(x))/(sin(4*x));
a=limit(F,x,0);
disp(a)
sum=taylor(F,x,0,'Order',7);
disp(sum)
disp (subs(sum,x,0))

Calculating it with MATLAB is quite easy, when using the Symbolic Toolbox. The limit function is what you need:
syms x
limit((x^2-9*x-10)/(sqrt(x+6)-4),x,10)
ans =
88
If you want to calculate it by hand, you don't need Taylor series, you'll need L'Hopital's rule, which states
(image: wikipedia)
This leads to
To calculate this in MATLAB, you could use the diff function to get the derivative and do something like
syms x
f(x) = x^2-9*x-10;
g(x) = sqrt(x+6)-4;
r(x) = diff(f(x)) / diff(g(x));
r(10)
ans =
88
Well, as we are using MATLAB, we can of course just use Taylor series expansion and let MATLAB do the job. MATLAB has a taylor function which creates the Taylor expansion. As the Taylor expansion is exact around the expansion point and the error increases, the further away you are from that point, it is best to use 10 as expansion point.
syms x
t(x) = taylor((x^2-9*x-10)/(sqrt(x+6)-4),x,10,'Order',6);
t(10)
ans =
88

OK, now that I know what you're after, what you could perhaps do is use that taylor command and expand about a point that is quite far off from where you want to compute the limit. If we set the expansion point to be where you want to evaluate the limit, no matter what order polynomial you choose, you will get the correct result which is what I'm assuming you're not after.
Start at an expansion point that is far away, then keep incrementally increasing the order of polynomial of the Taylor series until you get your desired accuracy. You don't want to choose an expansion point that is too far away, or you will never get the right answer. As such, I'm going to expand at x = 7.
Something like this:
true_val = 88; %// Define true value
syms x;
f = (x^2-9*x-10)/(sqrt(x+6)-4); %// Define function
order = 2; %// Start with second order
format long g; %// For better formatting
while true %// Keep iterating...
% // Get Taylor polynomial centered at x = 7 of the current order
pol = taylor(f, x, 7, 'Order', order);
%// Evaluate the Taylor series
val = double(subs(pol, x, 10));
%// Show the results
disp(['Order: ' num2str(order)]);
disp('Result');
disp(val);
%// Check to see if we have at least 1e-7 accuracy then break out if yes
if abs(true_val - val) < 1e-7
break;
end
%// Increment the order by 1
order = order + 1;
end
This is what I get:
Order: 2
Result
86.9892652074553
Order: 3
Result
88.0453290425764
Order: 4
Result
87.9954798755339
Order: 5
Result
88.0005926106152
Order: 6
Result
87.9999105029301
Order: 7
Result
88.0000147335223
Order: 8
Result
87.999997429935
Order: 9
Result
88.0000004672668
Order: 10
Result
87.9999999123696

Related

Zero crossings around mean

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.

Matlab use fminsearch to optimize a interval of numbers

In Matlab I want to use fminsearch to optimize a interval of numbers given a object function fun to minimize. The integer numbers can be selected from 1 to 30, and the number of integers is fixed to 5 for now. Assume the step size is 1. It will optimize many vectors such as:
[1 2 3 4 5]
[2 3 4 5 6]
[7 8 9 10 11]
[12 13 14 15 16]
In the long run, I may also try to optimize the step size and number of integers in the vector.
I want to know how to use fminsearch to properly realize this or maybe use other functions in the toolbox? Any suggestion will be appreciated.
First of all, as stated in documentation, fminsearch can only find minimum of unconstrained functions. fminbnd, on the other hand, can handle the bound constraint, however, non of these functions are meant to solve discrete functions. So you probably want to think of other options, ga for example.
Despite the fact that fminsearch does not handle constraints, but still you can use it to solve your optimization problem with cost of some unnecessary extra iterations. In this answer I assume that there is a fun function that takes an interval from a specific range as its argument and the objective is to find the interval that minimizes it.
Since the interval has a fixed step size and length, the problem is single-variable and we only need to find its start point. We can use floor to convert a continuous problem to a discrete one. To cover the bound constraint we can check for feasibility of intervals and return Inf for infeasible ones. That will be something like this:
%% initialization of problem parameters
minval = 1;
maxval = 30;
step = 1;
count = 5;
%% the objective function
fun = #(interval) sum((interval-5).^2, 2);
%% a function that generates an interval from its initial value
getinterval = #(start) floor(start) + (0:(count-1)) * step;
%% a modified objective function that handles constraints
objective = #(start) f(start, fun, getinterval, minval, maxval);
%% finding the interval that minimizes the objective function
y = fminsearch(objective, (minval+maxval)/2);
best = getinterval(y);
eval = fun(best);
disp(best)
disp(eval)
where f function is:
function y = f(start, fun, getinterval, minval, maxval)
interval = getinterval(start);
if (min(interval) < minval) || (max(interval) > maxval)
y = Inf;
else
y = fun(interval);
end
end

Matlab : Help in modulus operation

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).

determine the frequency of a number if a simulation

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.

MATLAB: Test if anonymous vector is a subset of R^n

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.