Can a MATLAB function take mathematical functions as inputs? - algorithm

I am totally new to this site and MATLAB, so please excuse me if my question is naive or a duplicate of some already existing question.
Well, I am a mathematics student, using MATLAB to aid in my project. There is a thing call "L^2 inner product" in which you need 2 mathematical functions, says f(x) and g(x), as inputs. It should work like
inner(f,g)=integrat f(x)*g(x) from 0 to 1.
The problem is I don't know how to write that in MATLAB.
To summarize, I want to make a MATLAB function whose inputs are two mathematical functions, the output is a real number. I know how to make an inline object but I don't know how to proceed further. Any help would be highly appreciated.
PS. I don't know if my tags are appropriate or on topic or not, please bear with me.

I will build on what #transversality condition wrote in greater detail (eg. there should be a .*)
Illustrative example with anonymous functions
h = #sin % This assigns h the function handle of the sin function
% If you know c, c++, this is basically a function pointer
inner = #(f,g)integral(#(x)f(x).*g(x),0,1) % This assigns the variable inner
% the function hanlde of a function which
% takes in two function handles f and g
% and calculates the integral from 0 to 1
% Because of how Matlab works, you want .* here;
% you need f and g to be fine with vector inputs.
inner(h, #cos) %this will calculate $\int_0^1 sin(x)cos(x)dx$
This yields 0.354
Writing inner as a regular function
In the previous example, inner was a variable, and the value of the variable was a function handle to a function which calculates the inner product. You could also just write a function that calculates the inner product. Create a file myinner.m with the following code:
function y = myinner(f, g)
y = integral(#(x)f(x).*g(x),0,1);
You could then call myinner the same way:
myinner(#sin, #cos)
result: 0.354
Note also that the integral function calculates the integral numerically and in strange situations, it's possible to have numerical problems.

Related

Matrix valued undefined functions in SymPy

I'm looking for a possibility to specify matrix quantities that depend on a variables. For scalars that works as follows, using undefined functions:
from sympy import *
x = Function('f')(t)
diff(x,t)
For Matrix Symbols like
x = MatrixSymbol('x',3,3)
i cannot find an equivalent. There is
i,j = Symbols('i j')
x = FunctionMatrix(6,1,Lambda((i,j),f))
but this is not what i need as you need to specify the contents of the matrix. The context is that i have equations
which should be derived in time and contain matrix valued elements.
I cannot deal with the elements of the matrices one by one.
Thanks!
I'm not sure about what you want, but I think you want to make a Matrix with differentiable elements. In that case, see if this works for you.
Create a matrix with function elements:
X = sym.FunctionMatrix(6,1,lambda i,j:sym.Function("x_%d%d" % (i,j))(t))
M = sym.Matrix(X)
M.diff(t)
This results in
Matrix([
[Derivative(x_00(t), t)],
[Derivative(x_10(t), t)],
[Derivative(x_20(t), t)],
[Derivative(x_30(t), t)],
[Derivative(x_40(t), t)],
[Derivative(x_50(t), t)]])
You may then replace stuff as you need.
Also, it may be preferrable if you populate the matrix with the expressions you need before differentiating. Leaving them as undefined functions may make it harder for you to simplify after substitution.

LU decomposing a square matrix matlab gauss elimination

I'm trying to create a program that takes a square (n-by-n) matrix as input, and if it is invertible, will LU decompose the matrix using Gaussian Elimination.
Here is my problem: in class we learned that it is better to change rows so that your pivot is always the largest number (in absolute value) in its column. For example, if the matrix was A = [1,2;3,4] then switching rows it is [3,4;1,2] and then we can proceed with the Gaussian elimination.
My code works properly for matrices that don't require row changes, but for ones that do, it does not. This is my code:
function newgauss(A)
[rows,columns]=size(A);
P=eye(rows,columns); %P is permutation matrix
if(det(A)==0) %% determinante is 0 means no single solution
disp('No solutions or infinite number of solutions')
return;
end
U=A;
L=eye(rows,columns);
pivot=1;
while(pivot<rows)
max=abs(U(pivot,pivot));
maxi=0;%%find maximum abs value in column pivot
for i=pivot+1:rows
if(abs(U(i,pivot))>max)
max=abs(U(i,pivot));
maxi=i;
end
end %%if needed then switch
if(maxi~=0)
temp=U(pivot,:);
U(pivot,:)=U(maxi,:);
U(maxi,:)=temp;
temp=P(pivot,:);
P(pivot,:)=P(maxi,:);
P(maxi,:)=temp;
end %%Grade the column pivot using gauss elimination
for i=pivot+1:rows
num=U(i,pivot)/U(pivot,pivot);
U(i,:)=U(i,:)-num*U(pivot,:);
L(i,pivot)=num;
end
pivot=pivot+1;
end
disp('PA is:');
disp(P*A);
disp('LU is:');
disp(L*U);
end
Clarification: since we are switching rows, we are looking to decompose P (permutation matrix) times A, and not the original A that we had as input.
Explanation of the code:
First I check if the matrix is invertible, if it isn't, stop. If it is, pivot is (1,1)
I find the largest number in column 1, and switch rows
Grade column 1 using Gaussian elimination, turning all but the spot (1,1) to zero
Pivot is now (2,2), find largest number in column 2... Rinse, repeat
Your code seems to work fine from what I can tell, at least for the basic examples A=[1,2;3,4] or A=[3,4;1,2]. Change your function definition to:
function [L,U,P] = newgauss(A)
so you can output your calculated values (much better than using disp, but this shows the correct results too). Then you'll see that P*A = L*U. Maybe you were expecting L*U to equal A directly? You can also confirm that you are correct via Matlab's lu function:
[L,U,P] = lu(A);
L*U
P*A
Permutation matrices are orthogonal matrices, so P−1 = PT. If you want to get back A in your code, you can do:
P'*L*U
Similarly, using Matlab's lu with the permutation matrix output, you can do:
[L,U,P] = lu(A);
P'*L*U
(You should also use error or warning rather than how you're using disp in checking the determinant, but they probably don't teach that.)
Note that the det function is implemented using an LU decomposition itself to compute the determinant... recursive anyone :)
Aside from that, there is a reminder towards the end of the page which suggest using cond instead of det to test for matrix singularity:
Testing singularity using abs(det(X)) <= tolerance is not
recommended as it is difficult to choose the correct tolerance. The
function cond(X) can check for singular and nearly singular
matrices.
COND uses the singular value decomposition (see its implementation: edit cond.m)
For anyone finding this in the future and needing a working solution:
The OP's code doesn't contain the logic for switching elements in L when creating the permutation matrix P. The adjusted code that gives the same output as Matlab's lu(A) function is:
function [L,U,P] = newgauss(A)
[rows,columns]=size(A);
P=eye(rows,columns); %P is permutation matrix
tol = 1E-16; % I believe this is what matlab uses as a warning level
if( rcond(A) <= tol) %% bad condition number
error('Matrix is nearly singular')
end
U=A;
L=eye(rows,columns);
pivot=1;
while(pivot<rows)
max=abs(U(pivot,pivot));
maxi=0;%%find maximum abs value in column pivot
for i=pivot+1:rows
if(abs(U(i,pivot))>max)
max=abs(U(i,pivot));
maxi=i;
end
end %%if needed then switch
if(maxi~=0)
temp=U(pivot,:);
U(pivot,:)=U(maxi,:);
U(maxi,:)=temp;
temp=P(pivot,:);
P(pivot,:)=P(maxi,:);
P(maxi,:)=temp;
% change elements in L-----
if pivot >= 2
temp=L(pivot,1:pivot-1);
L(pivot,1:pivot-1)=L(maxi,1:pivot-1);
L(maxi,1:pivot-1)=temp;
end
end %%Grade the column pivot using gauss elimination
for i=pivot+1:rows
num=U(i,pivot)/U(pivot,pivot);
U(i,:)=U(i,:)-num*U(pivot,:);
L(i,pivot)=num;
end
pivot=pivot+1;
end
end
Hope this helps someone stumbling upon this in the future.

How to apply element-wise operations without using for loops and without influencing the speed

Suppose that I have an RGB image matrix and I want to apply some spatial filters on it.
In general I want to apply element-wise operations (note that it's a college assignment and I'm not permitted to use any built-in functions available in the Image Processing toolbox). I decided to write the filters as functions and then apply bsxfun to these functions on the image.
A simple example would be this:
I want to add 50 to all gray levels of an image and then replace all gray levels with above 200 with 200. Here's my code:
a='C:\Users\sepideh\Desktop\IP_abadpour\S45C-113050518040.jpg';
b=imread(a);
b(:,:,1)=b(:,:,1)+50;
b(:,:,2)=b(:,:,2)+50;
b(:,:,3)=b(:,:,3)+50;
c=reshape(b,[],1);
d=bsxfun(#test,c,200);
test is a function in this form:
function Out = test(in,a)
if in>a
in=200;
end
Out = in;
end
This code won't work because in the second line "in > a" is a matrix having 0's and 1's (I mean all of the elements are not 1 and should not be) so the debugger won't branch into the if statement.
Could you guide me how to write this function and how to apply spatial and fourier analyses on the image, without affecting the performance and run-time speed?
Here's a couple of suggestions:
First of all, you don't need to add 50 to each layer of the RGB matrix individually. You can just do:
b = b + 50;
Why do you reshape b before passing it to bsxfun? The size of the output of bsxfun is the same as your image's, there's really no need in reshaping here anything.
Regarding your test function, note what the official documentation of bsxfun states:
A binary element-wise function of the form C = fun(A,B) accepts arrays A and B of arbitrary but equal size and returns output of the same size. Each element in the output array C is the result of an operation on the corresponding elements of A and B only. fun must also support scalar expansion, such that if A or B is a scalar, C is the result of applying the scalar to every element in the other input array.
So bsxfun performs singleton expansion and "inflates" its two input arrays to the same size, and then applies the specified function to the inflated arrays. The element-wise function fun operates, in fact, on the arrays, not scalars. I don't see any actual gain in employing bsxfun here.
That said, you can simplify your code as shown in Dan's suggestion, or implement it as a function:
function out = test(in, a);
out = in;
out(in > a) = a;
I assume that if you were using the value 210 instead of 200, you'd like to cap all gray levels with 210 as well, so you should really be using a instead of a hard-coded value 200. You could also write your function like so:
function out = test(in, a)
out = min(in, a);
and then invoke it with:
d = test(b, 200);
instead of the more complicated d = bsxfun(#test, b, 200).
Another alternative is to use arrayfun:
d = arrayfun(#(x)test(x, 200), a);
or
d = arrayfun(#test, a, 200 * ones(size(a)));
in which arrayfun will apply test element-wise, and the test function would need to operate only on scalars. However, arrayfun usually runs slower than loops, let alone vectorized operations.
For spatial analysis, check out conv2 just like Dan suggested (or implement your own 2-D convolution, for the sake of practice). For Fourier analysis, consider using the fft2 and ifft2 functions in the frequency domain.
Hope this helps!
So for the example you posted you can just take advantage of the fact that most operators in matlab work on matrices natively:
b=imread(a);
c = a + 50;
c(c > 200) = 200;
It's as simple as that.
For the filtering, if you are allowed, I would have a look at the conv2 function. You can do spatial filtering this way without transforming to the frequency domain (remeber, multiplication of a filter in the frequency domain is the same as convolution in the spatial domain). So for example a basic low pass filter:
lpf = ones(5)./25;
c(:,:,1) = conv2(b(:,:,1), lpf);
c(:,:,2) = conv2(b(:,:,2), lpf);
c(:,:,3) = conv2(b(:,:,3), lpf);

a faster way of implementing the nested loop with gamma function

I am trying to evaluate the following integral:
I can find the area for the following polynomial as follows:
pn =
-0.0250 0.0667 0.2500 -0.6000 0
First using the integration by Simpson's rule
fn=#(x) exp(polyval(pn,x));
area=quad(fn,-10,10);
fprintf('area evaluated by Simpsons rule : %f \n',area)
and the result is area evaluated by Simpsons rule : 11.483072
Then with the following code that evaluates the summation in the above formula with gamma function
a=pn(1);b=pn(2);c=pn(3);d=pn(4);f=pn(5);
area=0;
result=0;
for n=0:40;
for m=0:40;
for p=0:40;
if(rem(n+p,2)==0)
result=result+ (b^n * c^m * d^p) / ( factorial(n)*factorial(m)*factorial(p) ) *...
gamma( (3*n+2*m+p+1)/4 ) / (-a)^( (3*n+2*m+p+1)/4 );
end
end
end
end
result=result*1/2*exp(f)
and this returns 11.4831. More or less the same result with the quad function. Now my question is whether or not it is possible for me to get rid of this nested loop as I will construct the cumulative distribution function so that I can get samples from this distribution using the inverse CDF transform. (for constructing the cdf I will use gammainc i.e. the incomplete gamma function instead of gamma)
I will need to sample from such densities that may have different polynomial coefficients and speed is of concern to me. I can already sample from such densities using Monte Carlo methods but I would like to see whether or not it is possible for me to use exact sampling from the density in order to speed up.
Thank you very much in advance.
There are several things one might do. The simplest is to avoid calling factorial. Instead one can use the relation that
factorial(n) = gamma(n+1)
Since gamma seems to be actually faster than a call to factorial, you can save a bit there. Even better, you can
>> timeit(#() factorial(40))
ans =
4.28681157826087e-05
>> timeit(#() gamma(41))
ans =
2.06671024634146e-05
>> timeit(#() gammaln(41))
ans =
2.17632543333333e-05
Even better, one can do all 4 calls in a single call to gammaln. For example, think about what this does:
gammaln([(3*n+2*m+p+1)/4,n+1,m+1,p+1])*[1 -1 -1 -1]'
Note that this call has no problem with overflows either in case your numbers get large enough. And since gammln is vectorized, that one call is fast. It costs little more time to compute 4 values than it does to compute one.
>> timeit(#() gammaln([15 20 40 30]))
ans =
2.73937416896552e-05
>> timeit(#() gammaln(40))
ans =
2.46521943333333e-05
Admittedly, if you use gammaln, you will need a call to exp at the end to recover the final result. You could do it with a single call to gamma however too. Perhaps like this:
g = gamma([(3*n+2*m+p+1)/4,n+1,m+1,p+1]);
g = g(1)/(g(2)*g(3)*g(4));
Next, you can be more creative in the inner loop on p. Rather than a full loop, coupled with a test to ignore the combinations you don't need, why not just do this?
for p=mod(n,2):2:40
That statement will select only those values of p that would have been used anyway, so now you can drop the if statement completely.
All of the above will give you what I'll guess is about a 5x speed increase in your loops. But it still has a set of nested loops. With some effort, you might be able to improve that too.
For example, rather than computing all of those factorials (or gamma functions) many times, do it ONCE. This should work:
a=pn(1);b=pn(2);c=pn(3);d=pn(4);f=pn(5);
area=0;
result=0;
nlim = 40;
facts = factorial(0:nlim);
gammas = gamma((0:(6*nlim+1))/4);
for n=0:nlim
for m=0:nlim
for p=mod(n,2):2:nlim
result = result + (b.^n * c.^m * d.^p) ...
.*gammas(3*n+2*m+p+1 + 1) ...
./ (facts(n+1).*facts(m+1).*facts(p+1)) ...
./ (-a)^( (3*n+2*m+p+1)/4 );
end
end
end
result=result*1/2*exp(f)
In my test on my machine, I find that your triply nested loops required 4.3 seconds to run. My version above produces the same result, yet required only 0.028418 seconds, a speedup of roughly 150 to 1, despite the triply nested loops.
Well, without even making changes to your code you could install an excellent package from Tom Minka at Microsoft called lightspeed which replaces some built-in matlab functions with much faster versions. I know there's a replacement for gammaln().
You'll get nontrivial speed improvements, though I'm not sure how much, and it's straight-forward to install.

MATLAB: Performance problem with anonymous functions

Optimizing my MATLAB code, I stumbled upon a weird problem regarding anonymous functions.
Like in this thread I realized, that sometimes anonymous functions are running really slow.
But with minimal changes to the function, it runs as fast as subfunctions or nested functions.
I used this (simple) test file to reproduce the behaviour with Matlab R2010b under Windows 7 64-bit:
clear all; close all; clc;
% functions
fn1 = #(x) x^2;
fn2 = #(x) double(x^2);
% variables
x = linspace(-100,100,100000);
N = length(x);
%% anonymous function
y = zeros(1,N);
t = tic;
for i=1:N
y(i) = fn1(x(i));
end
tm.anonymous_1 = toc(t);
%% anonymous function (modified)
y = zeros(1,N);
t = tic;
for i=1:N
y(i) = fn2(x(i));
end
tm.anonymous_2 = toc(t);
%% print
tm
The results I got were:
tm =
anonymous_1: 1.0605
anonymous_2: 0.1217
As you can see the first approach is about 10 times slower.
I have no idea what triggers this speedup/slowdown.
I tried different things, getting nearly the same (fast) timings:
fn2 = #(x) 1 * x^2;
fn2 = #(x) 0 + x^2;
fn2 = #(x) abs(x^2);
fn2 = #(x) x*x;
Before I start profiling all of my functions,
I would like to know if anyone has an explanation for this behaviour?
P.S.: I know that "vectorized" approaches are much faster, but in my case a solver will be evaluating the function for each variable time step, so that is not an option.
It appears that in the case of 'fn2' the Matlab optimizer is able to inline the function, whereas it is unable to do so in the case of 'fn1'.
This probably has to do with what Matlab knows about the scalarity or complexity or structure of the argument and return value. It probably figures out that 'i' (the argument at the call-site) is necessarily scalar, real and non-strctured. Given a scalar argument it then tries to figure out the behaviour of the function. In the case of 'fn2' Matlab's optimizer statically determines that it can always fit all possible results of 'double()' into the target variable 'y(i)'. For some reason only known to the designers of the optimizer, Matlab is unable to come to the same conclusion for 'fn1'. Maybe there are some non-obvious corner-cases, or '^' lacks some piece of meta-data that the optimizer depends on. Anyway, the result is that in case of 'fn1' Matlab apparently re-evaluats the function at every iteration.
Anyway, statically optimizing dynamic languages is something of a black art in compiler design.
I believe that making the return type of a function independent of its argument's types makes it easier for Matlab to optimize. By the way, y = fn1(x); and y = fn2(x); have roughly the same proportion in terms of run time, so it's not the effect of arguments being scalar or complex.

Resources