I am using the generalized hypergeometric function in Matlab by calling hypergeom(a,b,z).
This function produces for a = 1 and a = 2, b = 2 and z = 5:
>>hypergeom(1,2,5)
29.4826318205153
>>hypergeom(2,2,5)
148.413159102577
Now, I want to evaluate the hypergeometric over a vector of a values. So if I enter hypergeom(1:2,2,5) I would expect the output:
[29.4826318205153, 148.413159102577]
However, when I enter this in Matlab I get:
>>hypergeom(1:2,2,5)
-0.25
So a single value is returned, for a vector of input values for a. How do I correctly call hypergeom in Matlab so that I get the same lenght of the output vector as the length of the input vector of a?
EDIT:
In this specific calculation I am evaluating the so-called Confluent hypergeometric function (solution to Kummer's differential equation, see: https://en.wikipedia.org/wiki/Confluent_hypergeometric_function). This is the 1F1 function. This means that length(N) = 1 and length(D) = 1.
The standard built-in function hypergeom is the generalized hypergeometric function, which does not allow the computation of hypergeom(1:2,2,5) in the way I want it.
Patrick Mousaw uploaded his Matlab code for the confluent hypergeometric function(https://nl.mathworks.com/matlabcentral/fileexchange/29766-confluent-hypergeometric-function), which is the version of the hypergeometric function I am using. A slight adaptation to his code, allowing for elementwise multiplication, returns exactly what I want. :)
I'm not entirely familiar with the generalised hypergeometric function, but it seems to me you have the function arguments the other way round, in terms of what is a 'parameter' (in the mathematical sense) and what is an 'input'. From the documentation:
HYPERGEOM(N, D, Z) is the generalized hypergeometric function F(N, D, Z),
also known as the Barnes extended hypergeometric function and denoted by
jFk where j = length(N) and k = length(D). For scalar a, b and c,
HYPERGEOM([a,b],c,z) is the Gauss hypergeometric function 2F1(a,b;c;z).
From wikipedia, I see the formula is:
So, as far as I understand it, this function is a vectorised function of the array Z, for parameter vectors
and
. I.e. to evaluate the generalised hypergeometric function for appropriate parameter vectors N and D, such that length(N)=5 and length(D)=2 (i.e.
) on a vector
, you'll call hypergeom(N,D,Z), and you should get an output vector of M elements out, one for each element of Z.
In this specific calculation I am evaluating the so-called Confluent hypergeometric function (solution to Kummer's differential equation, see: https://en.wikipedia.org/wiki/Confluent_hypergeometric_function). This is the 1F1 function. This means that length(N) = 1 and length(D) = 1.
The standard built-in function hypergeom is the generalized hypergeometric function, which does not allow the computation of hypergeom(1:2,2,5) in the way I want it.
Patrick Mousaw uploaded his Matlab code for the confluent hypergeometric function(https://nl.mathworks.com/matlabcentral/fileexchange/29766-confluent-hypergeometric-function), which is the version of the hypergeometric function I am using. A slight adaptation to his code, allowing for elementwise multiplication, returns exactly what I want. :)
Related
I have this signal:
x(t) = t*sin(m*pi*t)*heaviside(-m*pi-t)+t*cos(k*pi*t)*heaviside(t-k*pi)+sin(k*pi*t)*cos(m*pi*t)*(heaviside(t+m*pi)-heaviside(t-k*pi));
and I want to calculate the values only from -5pi to 5pi with a step of pi/100 using Matlab. How could I do it?
Provided you have defined m and k somewhere, and you have the matlab symbolic toolbox which provides the heaviside function, this is how it is done:
% First we define the function
x = #(t) t*sin(m*pi*t)*heaviside(-m*pi-t)+t*cos(k*pi*t)*heaviside(t-k*pi)+sin(k*pi*t)*cos(m*pi*t)*(heaviside(t+m*pi)-heaviside(t-k*pi));
% Then we define the values for which we want to compute the function
t_values = -5*pi:pi/100:5*pi;
% Finally we evaluate the function
x_values = x(t_values)
Details
First line we define your function as an anonymous function which is a handy tool in matlab.
Then we create a vector of values from -5pi to 5*pi with steps of pi/100. For this we use the matlab colon syntax. It makes it short and efficient.
Finally we evaluate the function on each of the t_values by passing the vector to the anonymous function.
Note: If you don't have the symbolic toolbox, you could easily implement heaviside yourself.
I want to integrate p(x)*f(x) where p(x) is a polynomial and f(x) is a function. I am working in MATLAB.
I have the coefficients of the polynomial in a vector.
p=[2,3,4,5];
funct=#(x) xˆ2;
I know how to integrate the function by itself, as well as how to integrate the polynomial by itself. However, I just can't find any info on how to take the integral of the product.
Here is what I tried:
p2=poly2sym(p)
integral(funct*p2,-1,1)
but p2 is not a function handle.
Help is appreciated!
Yes, p2 is not a function handle – it's a symbolic expression, but integral performs numerical integration and requires a function handle that returns floating point values. Even if p2 was a function handle, multiply function handles (e.g., funct*p2) is not valid. Additionally, funct needs to be vectorized.
Instead of poly2sym, you can evaluate your integral numerically with polyval like this:
p = [2,3,4,5];
funct = #(x)x.^2; % use element-wise power to vectorize
p2 = #(x)polyval(p,x);
integral(#(x)funct(x).*p2(x),-1,1) % evaluate two handles into one
which returns 4.533333333333333. Or you could compute this particular integral symbolically using int:
p = [2,3,4,5];
syms x;
funct = x^2;
p2 = poly2sym(p,x);
int(funct*p2,x,-1,1)
which returns the exact rational value of 68/15 (use vpa or double to convert to decimal or floating point, respectively).
I have been working on solving some equation in a more complicated context. However, I want to illustrate my question through the following simple example.
Consider the following two functions:
function y=f1(x)
y=1-x;
end
function y=f2(x)
if x<0
y=0;
else
y=x;
end
end
I want to solve the following equation: f1(x)=f2(x). The code I used is:
syms x;
x=solve(f1(x)-f2(x));
And I got the following error:
??? Error using ==> sym.sym>notimplemented at 2621
Function 'lt' is not implemented for MuPAD symbolic objects.
Error in ==> sym.sym>sym.lt at 812
notimplemented('lt');
Error in ==> f2 at 3
if x<0
I know the error is because x is a symbolic variable and therefore I could not compare x with 0 in the piecewise function f2(x).
Is there a way to fix this and solve the equation?
First, make sure symbolic math is even the appropriate solution method for your problem. In many cases it isn't. Look at fzero and fsolve amongst many others. A symbolic method is only needed if, for example, you want a formula or if you need to ensure precision.
In such an old version of Matlab, you may want to break up your piecewise function into separate continuous functions and solve them separately:
syms x;
s1 = solve(1-x^2,x) % For x >= 0
s2 = solve(1-x,x) % For x < 0
Then you can either manually examine or numerically compare the outputs to determine if any or all of the solutions are valid for the chosen regime – something like this:
s = [s1(double(s1) >= 0);s2(double(s2) < 0)]
You can also take advantage of the heaviside function, which is available in much older versions.
syms x;
f1 = 1-x;
f2 = x*heaviside(x);
s = solve(f1-f2,x)
Yes, the Heaviside function is 0.5 at zero – this gives it the appropriate mathematical properties. You can shift it to compare values other than zero. This is a standard technique.
In Matlab R2012a+, you can take advantage of assumptions in addition to the normal relational operators. To add to #AlexB's comment, you should convert the output of any logical comparison to symbolic before using isAlways:
isAlways(sym(x<0))
In your case, x is obviously not "always" on one side or the other of zero, but you may still find this useful in other cases.
If you want to get deep into Matlab's symbolic math, you can create piecewise functions using MuPAD, which are accessible from Matlab – e.g., see my example here.
In Mathematica, Gamma[a, z] refers to the upper incomplete Gamma function whereas in Matlab, gammainc(z, a) refers to the regularized lower incomplete Gamma function. I want to know how I can obtain the Mathematica result using Matlab? In this link, the method for obtaining same Matlab result using Mathematica was explained, but I couldn't find a strategy of getting one via Matlab.
You have several options. In addition to the version offered by #MarkMcClure
y = (1-gammainc(z,a)).*gamma(a)
you can also use additional arguments to get the upper regularized gamma function directly:
y = gammainc(z,a,'upper').*gamma(a)
Note that the order of the arguments is opposite to that of Mathematica's function.
The above are strictly numeric functions, but Mathematica's Gamma evaluates symbolically. You can use Matlab's igamma in the symbolic toolbox. Note that this function is not regularized and used the same argument order as Mathematica's function – it's as close to a direct equivalent as you'll find (but obviously slower for numeric evaluation):
syms a z;
y = igamma(a,z)
In older versions of Matlab, this function may not be directly available. You can however, still access the MuPAD version via:
y = feval(symengine,'igamma',a,z)
or something like
y = evalin(symengine,['igamma(' char(a) ',' char(z) ')'])
According to Wikipedia,
Thus, in Mathematica you might have
Gamma[1, 2] // N
While in Matlab you could have
gamma(1)-gammainc(2,1)
Both return 0.135335
I'm trying to use fsolve in matlab to solve a system of nonlinear equations numerically. Here is a test sample of my program, k1 and R are parameters and x0 is the start point.
function y=f(k1, R, x0)
pair=fsolve(#system,x0);
y=pair(1);
function r=system(v)
int1=#(x) exp(k1*x);
int2=#(x) exp(k1*x^2)/(x^4);
r(1)=exp(v(1))*quadl(int1,0,v(1));
r(2)=exp(k1*v(2))*quadl(int2,v(1),20)*k1*R;
end
end
The strange thing is when I run this program, matlab keeps telling me that I should use .^ instead of ^ in int2=#(x) exp(k1*x^2)/(x^4). I am confused because the x in that function handle is supposed to be a scalar when it is used by quadl. Why should I have to use .^ in this case?
Also I see that a lot of the examples provided in online documentations also use .^ even though they are clearly taking power of a scalar, as in here. Can anybody help explain why?
Thanks in advance.
in the function int2 you have used matrix power (^) where you should use element-wise power (.^). Also, you have used matrix right division (/) where you should use element-wise division (./). This is needed, since quadl (and friends) will evaluate the integrand int2 for a whole array of x's at a time for reasons of efficiency.
So, use this:
function y = f(k1, R, x0)
pair = fsolve(#system,x0);
y = pair(1);
function r = system(v)
int1 = #(x) exp(k1*x);
int2 = #(x) exp(k1*x.^2)./(x.^4);
r(1) = exp( v(1)) * quadl(int1,0,v(1));
r(2) = exp(k1*v(2)) * k1*R*quadl(int2,v(1),20);
end
end
Also, have a look at quadgk or integral (if you're on newer Matlab).
By the way, I assume your real functions int1 and int2 are different functions? Because these functions are of course trivial to solve analytically...
Internally MATLAB will evaluate the function fun for necessary values of x, which is more than one and x is a vector. a and b are only used to describe the limits of integration. From the documentation
fun is a function handle. It accepts a vector x and returns a vector y, the function fun evaluated at each element of x. Limits a and b must be finite.
Hence, you must use .^ to operate on individual elements of vector x.