0

I would like to calculate the following function efficiently, and therefore preferably with a function handle.enter image description here

In the given equation only "s" is the variable. The rest are some known constants but they are changing inside the loop. I would like to obtain this as a function handle because later I need to find the roots of this function.

This question is related to this one which I asked recently. But the answer seems to be inefficient and I am not able to obtain a single function handle for this whole thing. Is there any way?

My trial:

K=10;
N=4;

for ii=1:K
    for jj=1:N
f{ii,jj}=@(x) p_th0{ii}(jj).*log(p_th1{ii}(jj)/p_th0{ii}(jj)).*(p_th1{ii}(jj)/p_th0{ii}(jj)).^x;
    end
end

function y = sum_of_functions(f,x)
   y = 0;
   for ii=1:numel(f)
    y = y + f{ii}(x);
   end
end

r = FindRoots(@(x)sum_of_functions(f,x),A,B,2^5,0);

In this code "x" (corresponding to "s" in the formula) is the variable for which the roots are later found. "p_th0" and "p_th1" are cells of some known constants (changing inside outer while loop). In the code above this part f{ii,jj}=@(x) is missing the term to which we need to divide the sum. So it only considers double sum over the numerator in the given figure.

I also need to note that, I am unhappy about not having a single function handle for the whole thing. What I have is just a cell with some functions and for every time I need to evaluate the sum, I must build the sum first. Instead I would want to build the sum of the function handle once and just use this function handle in "FindRoots".

  • 1
    I would just write a single function that computes this. I don’t understand at all how you got to your previous question now. You’re overthinking this, I think. – Cris Luengo Sep 30 '19 at 18:50
  • Why would you need function handles for this? Can you give sample inputs and outputs? – beaker Sep 30 '19 at 18:50
  • @beaker yes please wait a bit. – Seyhmus Güngören Sep 30 '19 at 18:51
  • @CrisLuengo I dont think so but may be you are right if I am missing something. I agree to have just a single function but how? I cannot sum the function handles from my previous question. For example let K=10 and mk=4. If p0 and p1 are known, then we should be able to sum the function handles to obtain the final function handle. Let me put a bit more material about my trial. – Seyhmus Güngören Sep 30 '19 at 18:56

1 Answers1

1

It will be much more efficient if you forget about anonymous functions and just write a single function to compute your values.

f = @(x)theFunction(p_th0,p_th1,x);
r = FindRoots(f,A,B,2^5,0);

function y = theFunction(p_th0,p_th1,x);
   K = numel(p_th0);
   N = numel(p_th0{1});
   y = 0;
   for ii=1:K
      for jj=1:N
         B = p_th1{ii}(jj)/p_th0{ii}(jj);
         A = p_th0{ii}(jj).*log(B);
         y = y + A .* B.^x;
      end
   end
end

If you create a nested function, and return a handle to that, then you can even pre-compute some of those calculations. This is a rather fancy solution, but it is more efficient than the code above.

f = getFunctionHandle(p_th0,p_th1);
r = FindRoots(f,A,B,2^5,0);

function out = getFunctionHandle(p_th0,p_th1);
   K = numel(p_th0);
   N = numel(p_th0{1});
   A = zeros(K,N);
   B = zeros(K,N);
   for ii=1:K
      for jj=1:N
         B(ii,jj) = p_th1{ii}(jj)/p_th0{ii}(jj);
         A(ii,jj) = p_th0{ii}(jj).*log(B(ii,jj));
      end
   end

   % nested function
   function y = func(x)
      y = 0;
      for ii=1:numel(A)
         y = y + A .* B.^x;
      end
   end

   out = func(x)
end
Cris Luengo
  • 55,762
  • 10
  • 62
  • 120