Summation of cell array of function handles - matlab

I have a cell array with size (n,1) that includes a function handle. Every cell has to include specific function handle and the summation of function handles in the previous cells. How can I perform this operation? To clarify this is an illustration.
A = cell(size(ones(n,1)));
for i = 1 : n
A{i,1} = #(x) A{i-1,1} + i .* x;
end
How to get A{n,1} at x = 2 (for example)

You are actually pretty close, but you need to add a special case for i = 1 and you need to call the function:
n = 10;
A = cell(size(ones(n,1)));
A{1,1} = #(x) 1 .* x;
for ii = 2 : n
A{ii,1} = #(x) A{ii-1,1}(x) + ii .* x;
end
I replaced i with ii, to avoid confusion with complex numbers. For the case n = 10:
>> A{n}(2)
ans =
110

Recalling #gnovice comment, you can also just make a cell array of the handles, and then call a function that sums them up to n:
N = 10;
A = cell(N,1);
A{1} = #(x) 1.*x;
for k = 2:N
A{k} = #(x) k.*x;
end
% the following function sums the output of A{1}(x) to A{n}(x):
f = #(n,x) sum(cellfun(#(c) c(x),A(1:n)));
The result:
>> f(5,2)
ans =
30
>> f(N,2)
ans =
110
This way, every change of the functions in A will have an immediate effect upon redefining f:
>> A{3} = #(x) -x;
>> f = #(n,x) sum(cellfun(#(c) c(x),A(1:n)));
>> f(N,2)
ans =
102
>> f(5,2)
ans =
22

Related

double sum in Matlab

I would like to write a Matlab code to calculate the following:
\sum_{k=0}^{N-1} \frac{1}{k!} \sum_{i=0}^{k} {k \choose i}(a-1)^{k-i} a^k
and my code is:
N = 3;
a = [3 4];
for k = 0:N-1
f = 0;
for i = 0:k
f = f + nchoosek(k,i).* a.^k .* (a-1).^(k-i);
end
sumoff = sum(f);
all = (( 1./ (factorial(k))).*sumoff);
end
overall= sum(all);
'all' variable gives different value when it is inside the for loop rather than outside. But I want it to calculate when k = 0:N-1. What am I doing wrong?
Thank you.
The issue is your current code overwrites all on every iteration. Moving it outside the loop also doesn't work because you'll only save the result of the last iteration.
To save the all of every iteration, define all as a vector and then assign each intermediate result into that vector:
N = 3;
a = [3 4];
% preallocate a vector for `all`
all = nan(N-1, 1);
for k = 0:N-1
f = 0;
for i = 0:k
f = f + nchoosek(k,i) .* a.^k .* (a-1).^(k-i);
end
sumoff = sum(f);
% assign your intermediate result into the `all` vector
all(k+1) = ((1./(factorial(k))) .* sumoff);
end
overall = sum(all);

Cumulative count of unique element in Matlab array

Working with Matlab 2019b.
x = [10 10 10 20 20 30]';
How do I get a cumulative count of unique elements in x, which should look like:
y = [1 2 3 1 2 1]';
EDIT:
My real array is actually much longer than the example given above. Below are the methods I tested:
x = randi([1 100], 100000, 1);
x = sort(x);
% method 1: check neighboring values in one loop
tic
y = ones(size(x));
for ii = 2:length(x)
if x(ii) == x(ii-1)
y(ii) = y(ii-1) + 1;
end
end
toc
% method 2 (Wolfie): count occurrence of unique values explicitly
tic
u = unique(x);
y = zeros(size(x));
for ii = 1:numel(u)
idx = (x == u(ii));
y(idx) = 1:nnz(idx);
end
toc
% method 3 (Luis Mendo): triangular matrix
tic
y = sum(triu(x==x'))';
toc
Results:
Method 1: Elapsed time is 0.016847 seconds.
Method 2: Elapsed time is 0.037124 seconds.
Method 3: Elapsed time is 10.350002 seconds.
EDIT:
Assuming that x is sorted:
x = [10 10 10 20 20 30].';
x = sort(x);
d = [1 ;diff(x)];
f = find(d);
d(f) = f;
ic = cummax(d);
y = (2 : numel(x) + 1).' - ic;
When x is unsorted use this:
[s, is] = sort(x);
d = [1 ;diff(s)];
f = find(d);
d(f) = f;
ic = cummax(d);
y(is) = (2 : numel(s) + 1).' - ic;
Original Answer that only works on GNU Octave:
Assuming that x is sorted:
x = [10 10 10 20 20 30].';
x = sort(x);
[~, ic] = cummax(x);
y = (2 : numel(x) + 1).' - ic;
When x is unsorted use this:
[s, is] = sort(x);
[~, ic] = cummax(s);
y(is) = (2 : numel(s) + 1).' - ic;
You could loop over the unique elements, and set their indices to 1:n each time...
u = unique(x);
y = zeros(size(x));
for ii = 1:numel(u)
idx = (x == u(ii));
y(idx) = 1:nnz(idx);
end
This is a little inefficient because it generates an intermediate matrix, when actually only a triangular half is needed:
y = sum(triu(x==x.')).';
Here's a no-for-loop version. On my machine it's a bit faster than the previous working methods:
% if already sorted, can omit this first and last line
[s, is] = sort(x);
[u,~,iu] = unique(s);
c = accumarray(iu,1);
cs = cumsum([0;c]);
z = (1:numel(x))'-repelem(cs(1:end-1),c);
y(is) = z;

Create general symbolic array using MATLAB

I want to generate array or 1 x M matrix with variables such as (please note that sum goes from i=1 to m-1):
Because I want to use Obj later as a general array depends on given M for some optimization purposes. I tried following code in MATLAB but that symbolic L does not support:
function testSymbolic
M=3;
Obj = ones(1,M);
L = sym('L', [1 M]);
tempL = log(1-L);
for m=1:M
Obj(1,m) = log((L(m))/(1+L(m))) + sum(tempL(1,1:m-1),2);
end
Obj
However, when I see that following when I run separately:
L = sym('L', [1 3])
L =
[ L1, L2, L3]
L(1)
ans =
L1
can some one please help me to fix this issue?
Try
M = 3;
for i = 1:M
L(i) = sym(['L(' num2str(i) ')'])
end
tempL = log(1-L);
for m=1:M
Obj(1,m) = log((L(m))/(1+L(m))) + sum(tempL(1:m-1));
end
This yields e.g.
Obj(3)
ans =
log(L(3)/(L(3) + 1)) + log(1 - L(1)) + log(1 - L(2))
EDIT:
Considering you want to calculate the maximum of the Obj-vector I would suggest this:
clear;
M = 3;
L = sym('L', [1 M]);
tempL = log(1-L);
for m=1:M
Obj(1,m) = real(log((L(m))/(1+L(m))) + sum(tempL(1:m-1)));
end
F = matlabFunction(Obj,'vars',{L})
ft = #(v) (max (-F(v)));
Now you can optimize ft.

How to create a matrix of functions dynamically

I want to create a matrix of functions, however I'd like to dynamically generate it. For example:
myMatrix = zeros(3);
test = #(x) x*y;
for ii = 1:3
myMatrix(ii) = test(ii);
end
something like that to generate: #(y) [y, 2*y, 3*y]
I do not have access to the sym library.
You can't make a matrix of functions, but you can make cell of function handles, e.g.
cellOfFunctions = {};
for i = 1:3
cellOfFunctions{end + 1} = #(y) y*i;
end
Then you can get each handle as follows (for the first function handle):
fh1 = cellOfFunctions{1};
Then execute it with y = 3:
result = fh1(3);
Depending on your purposes, you can make a single function which generates the matrix you have in your example:
>> f = #(y) bsxfun(#times, 1:3, y(:));
>> f(2:5)
ans =
2 4 6
3 6 9
4 8 12
5 10 15

To handle rational number without losing accuracy of computation in Matlab?

I want to use this rational number in computations without losing the accuracy of the picture in Matlab:
f = 359.0 + 16241/16250.0
I think storing, for instance by f = uint64(359.0 + 16241/16250.0) loses accuracy, seen as 360 in Matlab.
I think the best way to handle the thing is never to store the value but to store its factors like
% f = a + b/c
a = 359
b = 16241
c = 16250
and then doing computation by the variables a, b and c, and giving the result as a picture.
Is this a good way to maintain the accuracy?
As you suggest, if you absolutely don't want to lose accuracy when storing a rational number, the best solution probably is to store the number in terms of its integer components.
Instead of your three components (f = a + b/c) you can reduce the reprentation to two components: f = n/d. Thus each rational number would be defined (and stored) as the two-component integer vector [n d]. For example, the number f in your example corresponds to n=5849991 and d=16250.
To simplify handling rational numbers stored this way, you could define a helper function which converts from the [n d] representation to n/d before applyling the desired operation:
useInteger = #(x, nd, fun) fun(x,double(nd(1))/double(nd(2)));
Then
>> x = sqrt(pi);
>> nd = int64([5849991 16250]);
>> useInteger(x, nd, #plus)
ans =
361.7719
>> useInteger(x, nd, #times)
ans =
638.0824
If you want to achieve arbitrarily high precision in computations, you should consider using variable-precision arithmetic (vpa) with string arguments. With that approach you get to specify how many digits you want:
>> vpa('sqrt(pi)*5849991/16250', 50)
ans =
638.08240465923757600307902117159072301901656248436
Perhaps create a Rational class and define the needed operations (plus,minus,times,etc.). Start with something like this:
Rational.m
classdef Rational
properties
n;
d;
end
methods
function obj = Rational(n,d)
GCD = gcd(n,d);
obj.n = n./GCD;
obj.d = d./GCD;
end
function d = dec(obj)
d = double(obj.n)/double(obj.d);
end
% X .* Y
function R = times(X,Y)
chkxy(X,Y);
if isnumeric(X),
N = X .* Y.n; D = Y.d;
elseif isnumeric(Y),
N = X.n .* Y; D = X.d;
else
N = X.n .* Y.n; D = X.d .* Y.d;
end
R = Rational(N,D);
end
% X * Y
function R = mtimes(X,Y)
R = times(X,Y);
end
% X ./ Y
function R = rdivide(X,Y)
if isnumeric(Y),
y = Rational(1,Y);
else
y = Rational(Y.d,Y.n);
end
R = times(X,y);
end
% X / Y
function R = mrdivide(X,Y)
R = rdivide(X,Y);
end
% X + Y
function R = plus(X,Y)
chkxy(X,Y);
if isnumeric(X),
N = X.*Y.d + Y.n; D = Y.d;
elseif isnumeric(Y),
N = Y.*X.d + X.n; D = X.d;
else
D = lcm(X.d,Y.d);
N = sum([X.n Y.n].*(D./[X.d Y.d]));
end
R = Rational(N,D);
end
% X - Y
function R = minus(X,Y)
R = plus(X,-Y);
end
% -X
function R = uminus(X)
R = Rational(-X.n,X.d);
end
function chkxy(X,Y)
if (~isa(X, 'Rational') && ~isnumeric(X)) || ...
(~isa(Y, 'Rational') && ~isnumeric(Y)),
error('X and Y must be Rational or numeric.');
end
end
end
end
Examples
Construct objects:
>> clear all % reset class definition
>> r1 = Rational(int64(1),int64(2))
r1 =
Rational with properties:
n: 1
d: 2
>> r2 = Rational(int64(3),int64(4))
r2 =
Rational with properties:
n: 3
d: 4
Add and subtract:
>> r1+r2
ans =
Rational with properties:
n: 5
d: 4
>> r1-r2
ans =
Rational with properties:
n: -1
d: 4
Multiply and divide:
>> r1*r2
ans =
Rational with properties:
n: 3
d: 8
>> r1/r2
ans =
Rational with properties:
n: 2
d: 3
Get decimal value:
>> r12 = r1/r2; % 2/3 ((1/2)/(3/4))
>> f = r12.dec
f =
0.6667
Extension to LuisMendo's answer
I got this as the error for your suggestion by py
>>> a = 638.08240465923757600307902117159072301901656248436059
>>> a
638.0824046592376 % do not know if Python is computing here with exact number
>>> b = 638.0824
>>> ave = abs(b+a)/2
>>> diff = abs(b-a)
>>> ave = abs(b+a)/2
>>> diff/ave
7.30193709165014e-09
which is more than the proposed error storing error above.
I run in WolframAlpha
x = sqrt(pi)
x*5849991/16250
and get
509.11609919757198016211937362635174599076143654820109
I am not sure if this is what you meant in your comment of your answer.
Extension to chappjc's answer.
I have now
[B,T,F] = tfrwv(data1, 1:length(data1), length(data1)); % here F double
fs = Rational(uint64(5849991), uint64(16250));
t = 1/fs;
imagesc(T*t, F*fs, B);
I run it
Error using .*
Integers can only be combined with integers of
the same class, or scalar doubles.
Error in .* (line 23)
N = X .* Y.n; D = Y.d;
Error in * (line 34)
R = times(X,Y);
How can you multiply in this class the double with Rational?