MatLab: Code for a sparse version of Horner's rule - matlab

I have written code to evaluate polynomials
p(x)=a_0+x(a_1+x(a_2+x(a_3+...+x(a_(n-1)+xa_n)...)))
using Horner's rule as follows
function [answer ] = Simple( a,x )
%Simple takes two arguments that are in order and returns the value of the
%polynomial p(x). Simple is called by typing Simple(a,x)
% a is a row vector
%x is the associated scalar value
n=length(a);
result=a(n);
if (any(a~=floor(a))
error('The values in a must be integers')
end
for j=n-1:-1:1 %for loop working backwards through the vector a
result=x*result+a(j);
end
answer=result;
end
I am now trying to write a code for a sparse version of this ie
p(x)=x^(i_1)(b_1+x^((i_2)-(i_1))(b_2+x^((i_3)-(i_2))(b_3+...+x^((i_(k-1))-(i_(k-2)))(b_(k-1)+x^((i_k)-(i(k-1)))b_k)...)))
I think I need the inputs to be a row vector of i and a row vector of b and a scalar value x. Any ideas where I can find this? I am unsure how to code it myself.

One way to answer this is to look at an intermediate term in p(x),
this will be
...(b_j + x^(i_(j+1) - i_j)(...
instead of the usual ...(a_j + x(..., thus you need to change the line result=x*result+a(j);.
Also there is a slight flaw in your formula for p(x), it should be p(x) = x^(i_1 - 1)(..., this comes from the fact that p(x) = a_1 x^0 + a_2 x^1 + ... + a_n x^(n-1) which comes from the fact that indexes of matrices in Matlab start at 1 instead of 0. Here is the full code
function [answer ] = SparseHorner( a,x )
% SparseHorner takes two arguments that are in order and returns the value of the
% polynomial p(x). SparseHorner is called by typing SparseHorner(a,x)
% a is a sparse row vector
% x is the associated scalar value
%// Find the entries where a is nonzero
[xInd yInd aVal] = find(a);
if any(aVal~=floor(aVal))
error('The values in a must be integers')
end
%// a is a row vector so only yInd's values change
ind = yInd;
result=aVal(end);
%// for loop working backwards through the vector a
%// numel is better than length
for j=(numel(ind)-1):-1:1
%// a(ind(j)) is much slower than aVal(j)
result=x^(ind(j+1)-ind(j))*result + aVal(j);
end
answer=result*x^(ind(1)-1);
end
Note that this treats a differently than Matlab's polyval, the latter has p(x) = a_1 x^n + ... + a_n; if you want to be consistent, then add the line a = fliplr(a) near the beginning of the function.

Related

MATLAB: how do I create a vector where each element is a function of the previous element

Working in Matlab.
I am trying to create a vector where each element is a function of the previous element. The goal is to put the first 50 (or so) values of a logistical function in a vector. So I start with 0.200, with r=4 (for example), the second element would then be 40.200(1-0.200)=0.640.
The third element would take the value 0.64 and perform the same function on that number, and so on...
I have tried a for-loop, but since there is no counter in the function, the loop doesn't work.
EDIT: I have created the following function:
n = 0;
x = 0.200;
for n=0:100
x=4*x*(1-x)
n=n+1
end
This gives the first 100 values. But I fail to get them as values in a vector...
Any suggestions on how to solve this would be appreciated.
You need to use indexing for the x vector you are creating. The way you currently have it coded, everything is going into a scalar x and not a vector x. E.g.,
n = 50; % the number of elements you want to fill
x = zeros(1,n); % allocate a vector to hold the numbers
x(1) = 0.200; % set the first value
for k=2:n % loop through the remaining values
x(k) = 4*x(k-1)*(1-x(k-1)); % set the next value using the previous value
end
Note that in the above code all of the usages of x other than the initial allocation involve indexing, e.g. x(1) and x(k) and x(k-1).

Implementing a Function using for-loops and matrix multiplication in matlab

My goal is to implement a function which performs fourier synthesis in matlab, as part of learning the language. The function implements the following expression:
y = sum(ak*exp((i*2*pi*k*t)/T)
where k is the index, ak is a vector of fourier coefficients, t is a time vector of sampled times, and T is the period of the signal.
I have tried something like this:
for counter = -N:1:N
k = y+N+1;
y(k) = ak(k)*exp((i*2*pi*k*t)/T);
% y is a vector of length 2N+1
end
However, this gives me an error that the sides do not have equal numbers of items within them. This makes sense to me, since t is a vector of arbitrary length, and thus I am trying to make y(k) equal to numerous things rather than one thing. Instead, I suspect I need to try something like:
for counter = -N:1:N
k=y+N+1;
for t = 0:1/fs:1
%sum over t elements for exponential operation
end
%sum over k elements to generate y(k)
end
However, I'm supposedly able to implement this using purely matrix multiplication. How could I do this? I've tried to wrap my head around what Matlab is doing, but honestly, it's so far from the other languages I know that I don't really have any sense of what matlab's doing under the hood. Understanding how to change between operations on matrices and operations in for loops would be profoundly helpful.
You can use kron to reach your goal without for loops, i.e., matrix representation:
y = a*exp(1j*2*pi*kron(k.',t)/T);
where a,k and t are all assumed as row-vectors
Example
N = 3;
k = -N:N;
t = 1:0.5:5;
T = 15;
a = 1:2*N+1;
y = a*exp(1j*2*pi*kron(k.',t)/T);
such that
y =
Columns 1 through 6:
19.1335 + 9.4924i 10.4721 + 10.6861i 2.0447 + 8.9911i -4.0000 + 5.1962i -6.4721 + 0.7265i -5.4611 - 2.8856i
Columns 7 through 9:
-2.1893 - 4.5489i 1.5279 - 3.9757i 4.0000 - 1.7321i

Double for loop MATLAB

I need to do an estimation procedure for n time series (n vectors of T observations). I have the formula to evaluate my variable (using a for loop) but I need to repeat this n times (the number of vectors).
h0 = var(residuals);
ht=zeros(T,n); ht(T,1)=h0;
for i=2:T
ht(i) = theta(1) + theta(2)*residuals(i-1)^2 + theta(3)*ht(i-1);
end
So this loop calculates ht for all of the observations in series one, but I need another for loop that helps me to use this formula for all of the series.
Edit: This is what I've done based on the below answer:
function ht = VarEQ(theta,residuals)
[T,n] = size(residuals)
for k=1:n
h0 = var(residuals(:,k));
ht=zeros(T,n); ht(1,k)=h0;
for i=2:T
ht(i,k) = theta(1,k) + theta(2,k)*residuals(i-1,k)^2 + theta(3,k)*ht(i-1,k);
end
end
end
Current problem:
Now ht is all columns of zero and just the last column of correct values.
Variables
var is a 1xn row vector of variances. Using k, I want just the scalar for each residual.
theta is a 3xn matrix of parameters.
residuals is a Txn matrix.
This seems simple given what you already have set up:
function ht = VarEQ(theta,residuals)
[T,n] = size(residuals)
ht=zeros(T,n); % Initialise matrix OUTSIDE loop so it isn't over-written!
for k=1:n % additional loop for series 1 to n
ht(1,k) = var(residuals(:,k));;
for i = 2:T
% Ensure you are referencing the kth series
ht(i,k) = theta(1,k) + theta(2,k)*residuals(i-1,k)^2 + theta(3,k)*ht(i-1,k);
end
end
end
Note: previously, all columns of ht were the same, because theta and residuals were the same for each series!
With your updated code, and the updated code in this answer, that has been fixed.

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

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.