I've tried to use a script that evaluates the Pochhammer symbol (rising factorial) in Matlab, but it fails to evaluate pochhammer(x,n) whenever x is a negative number even though the expression is valid when x is negative (Wolfram Alpha and Mathematica give answers for Pochhammer(-3,2)).
Can anyone help me get pochhammer working in Matlab for negative arguments?
I assume that you're referring to this Pochhammer function. Note that pochhammer (not capitalized) is part of MuPAD, which is a separate environment available with Matlab's Symbolic Math Toolbox. You can access MuPAD by typing mupad in the Matlab command window.
If, however, like a normal Matlab user, you wish to use the pochhammer function from Matlab itself and program with it, you cannot run it from the regular command window or Editor in the normal fashion, as you discovered. Instead, you must use
evalin(symengine,'pochhammer(-3,2)')
or the more flexible
feval(symengine,'pochhammer',-3,2)
See more here. These both return symbolic numbers as results and only work for scalar inputs. If you require double-precision output and have vector inputs (only works for the the second one, n) use
mfun('pochhammer',-3,-3:3)
This is equivalent to using MuPAD's map function, so you could also write:
feval(symengine,'map',sym(-3:3),'n->pochhammer(-3,n)')
However, if you're not working with symbolic math at all, there may be no reason to use this function instead of a fully double-precision solution. The Pochhammer symbol is defined simply as the ratio of two gamma functions and can be implemented efficiently as (x and n must be the same dimensions or scalar – additionally, neither x nor x-n can be an integer less than or equal to zero, where the gamma function is singular):
poch = #(x,n)gamma(x+n)./gamma(x);
If n and x are integers you should use round to ensure that the output is exactly integer. The only pitfall is that for sufficiently large values of x and/or n this naïve implementation will overflow to Inf (or NaN). In these cases you'll need to do something else such as use the symbolic version (which may or may not return Inf when cast back to double). For integer values of n (and scalar n>=0), something like the following can be used
poch = #(x,n)prod(bsxfun(#plus,x(:),0:n-1),2);
Note that even for integers this can be up 20 times slower than the gamma version.
The numerical command pochhammer for Matlab (not MuPAD) was introduced in matlab version R2014b.
Related
I need to take derivatives in Matlab of a lot of equations w.r.t. generic functions, which will provide me with generic derivatives, of the type:
diff(f(x,y),x)
or
D([1],f(x,y)).
What I need is to transform these derivatives into actual symbolic variables, in order to be able to use solve, etc. What I am doing now, but which is highly inefficient, is brute force string replacement. Here is a minimal working example of what I am doing:
syms x y
f(x,y) = sym('f(x,y)')
jacobian(f)
first_d = jacobian(f)
strrep(char(first_d),'D([1], f)(x, y)','fx')
In my real application, I have lots of derivatives to take from lots of equations, so looping such replacements is not the smartest thing to do. Can anybody shed some light into a more efficient solution?
Note: I'm using R2014b. Symbolic Math functionality has changed greatly in recent versions and continues to do so. Users on different versions may need to do slightly different things to achieve the results below, which relies on accessing undocumented functionality.
First, since this is about performance, it is sufficient to simply declare
syms f(x,y)
which also defines x and y as symbolic variables.
As I mention in my comments above, Matlab/MuPAD's symbolic math is all about manipulating strings. Doing this more directly and and adding in you own knowledge of the problem can help speed things up. You want to avoid unnecessary conversions between strings and the sym/symfun types.
1. The first thing to do is investigate how a particular symbolic math function is handling input and output and what lower level private functions it is calling. In the case of your jacobian function example, type edit jacobian in your command window to view the code in the Editor. Much of what you see may be confusing, but you should see this line:
res = mupadmex('symobj::jacobian',Fsym.s,v.s);
This calls the low level 'symobj::jacobian' function and passes in string versions of the function and variables. To call this yourself, you can do (this also assumes you know your variables are x and y):
syms f(x,y)
first_d = mupadmex('symobj::jacobian',char(f),char([x,y]))
This returns [ diff(f(x, y), x), diff(f(x, y), y)]. The undocumented mupadmex function is a direct way of calling MuPAD function from within Matlab – there are others, which are documented.
2. You'll notice that that the first_d output above is symfun class. We actually don't want want the output to be converted back to a symbolic function. To avoid this, we can pass an addition argument to mupadmex:
syms f(x,y)
first_d = mupadmex('symobj::jacobian',char(f),char([x,y]),0)
with now returns the string matrix([[diff(f(x, y), x), diff(f(x, y), y)]]). (I only know this trick of adding the additional 0 argument from having browsed through a lot of Symbolic Math toolbox code.)
3. From this string, we can now find and replace various patterns for partial derivatives with simple variables. The strrep function that you're using is generally a good choice for this. It is much faster than regexprep. However, if you have a large number of different, but similar, patterns to replace, you might do a performance comparison between the two. That would probably be the subject of a separate question.
I'm not sure what your overall goal is or the full extent of your problem, but here is my final code for your example:
syms f(x,y)
first_d = mupadmex('symobj::jacobian',char(f),char([x,y]),0)
first_d = strrep(first_d(9:end-2),'diff(f(x, y), x)','fx');
first_d = sym(strrep(first_d,'diff(f(x, y), y)','fy'));
This returns the symbolic vector [ fx, fy]. If you want a symfun, you'll need to modify the last line slightly. In some simple testing, this basic example is about 10% faster than calling jacobian and converting the result back to a string. If you directly specify the inputs as strings instead of allocating a symbolic function, the result is about 30% faster then your original:
first_d = mupadmex('symobj::jacobian','f(x,y)','[x,y]',0)
first_d = strrep(first_d(9:end-2),'diff(f(x, y), x)','fx');
first_d = sym(strrep(first_d,'diff(f(x, y), y)','fy'));
Using subs, as in this answer, while convenient, is the slowest approach. Converting back and forth to and from strings is costly.
I have a problem in numerical evaluation of symbolic expression. To simplify my question. I write the follow lines for an example.
syms a b c d e f
x = [a+b*c+d^e,b+log(c+d);exp(c)*b/c+f,f*c+e^2];
a = 2;
b = 3;
c = 1.5;
d = 1;
e = -2;
f = -1;
fx = eval(x);
x is a matrix the elements of which are symbolic expressions. I need to evaluate x given different values of [a,b,c,d,e,f] to get a numerical matrix fx. In my real program, such evaluation needs to be implemented million times and both the size of matrix x and the number of parameters (a,b,...,d) are much larger.
In Matlab 7.1, my program runs well. However, when I run it in Matlab 2013b, it becomes quite slow. I find that "eval(x)" runs faster in 7.1 than in 2013b due to their difference in default symbolic computation packages (Maple for 7.1 and MuPAD for 2013b).
So my question is that is there any more efficient way to evaluate a symbolic expression than using function "eval" in Matlab 2013b?
For symbolic computation, I recommend using subs() instead of eval(). You get full power and symbolic accuracy if you use subs().
When you use eval(), the symbolic expression would be converted to a character string (such as is displayed) and then the MATLAB parser and full runtime would be applied to calculate the meaning of the character string, using normal MATLAB double precision (or appropriate MATLAB numeric type). This process involves MATLAB using its JIT analyzer and so on. It is a bit "heavy handed" computationally.
See the MATLAB documentation here for subs().
I'm trying to write a generic function for finding the cosine of a value inputted into the function. The formula for cosine that I'm using is:
n
cosx = sum((-1)^n*x^(2n)/(2n)!)
n=1
I've looked at the matlab documentation and this page implies that the "sum" function should be able to do it so I tried to test it by entering:
sum(x^n, n=1..3)
but it just gives me "Error: The expression to the left of the equals sign is not a valid target for an assignment".
Is summing an infinite series something that matlab is able to do by default or do I have to simulate it using a function and loops?
Well if you want to approximate it to a finite number of terms you can do it in Matlab without toolboxes or loops:
sumCos = #(x, n)(sum(((-1).^(0:n)).*(x.^(2*(0:n)))./(factorial(2*(0:n)))));
and then use it like this
sumCos(pi, 30)
The first parameter is the angle, the second is the number of terms you want to take the series to (i.e. effects the precision). This is a numerical solution which I think is really what you're after.
btw I took the liberty of correcting your initial sum, surely n must start from 0 if you are trying to approximate cos
If you want to understand my formula (which surely you do) then you need to read up on some essential Matlab basics namely the colon operator and then the concept of using . to perform element-wise operations.
In MATLAB itself, no, you cannot solve an infinite sum. You would have to estimate it as you suggested. The page you were looking at is part of the Symbolic Math toolbox, which is an add-on to MATLAB. In particular, you were looking at MuPAD, which is rather similar to Mathematica. It is a symbolic math workspace, whereas MATLAB is more of a numeric math workspace. If you own the Symbolic Math toolbox, you can either use MuPAD as you tried to above, or you can use the symsum function from within MATLAB itself to carry out sums of series.
I am working MuPad in order to have a symbolic tool to find solution for an equation. But I am working with matrices.
Consider this:
blck := A -> matrix([
[A[1..linalg::matdim(A)[1]/2,1..linalg::matdim(a)[2]/2],
A[1..linalg::matdim(A)[1]/2,linalg::matdim(A)[2]/2+1..linalg::matdim(A)[2]]],
[A[linalg::matdim(A)[1]/2+1..linalg::matdim(A)[1],1..linalg::matdim(A)[2]/2],
A[linalg::matdim(A)[1]/2+1..linalg::matdim(A)[1],linalg::matdim(A)[2]/2+1..linalg::matdim(A)[2]]]
])
This function enables me to have a block representation of a matrix and it works. Now consider this function
myfun := A -> matrix([[blck(A)[1,1]*blck(A)[2,2]*blck(A)[2,1],blck(A)[1,1]],
[blck(A)[1,1],blck(A)[1,1]]])
This will manipulate a little a matrix and returns matrix whose components are combined somehow. The problem is that, considering that I cannot tell MuPad that matrix A and its components are matrices and not reals, it happens that MuPad will show me matrix products in different order
For example. Consider
myfun(matrix([[A11,A12],[A21,A22]]))
The first component of the returned matrix, element (1,1), is A11*A21*A22 which is incorrect being A11,A12,A21,A22 matrices!
How can i tell MuPad that A11,A12,A21 and A22 are matrices so that MuPad will expand products correctly?
You can have matrices in matrices in MuPAD, as long as you explicitly put them in there. Just telling the system to treat A1*A2 as non-commutative is more difficult and not well supported. You could go full-blown, create your own datatype and implement arithmetic accordingly, but that's not necessarily easy if you still want simplifications to happen.
I am computing a Fourier transformation in MATLAB, when computing coefficients C[0] and C[n*f0], I got pretty nasty result because MATLAB doesn't recognize my variable "n" as integer. I currently compute with "n" as a symbolic variable (syms n;). How to change symbolic n to symbolic integer n?
Looking at the MATLAB documenation, to add the assumption "n is integer" in R2008b or later, you have to write
evalin(symengine,'assume(n,Type::Integer)')
This answers your question, however, I'm not really sure it solves your problem.
When you do a Fourier transform, you are performing a heavy numeric operation on your data, consequently all variables involved in that need to have concrete values. Your n probably should be an integer, but not just by type, it should contain an actual number. If you declare it using syms, it will potentially not contain a number, so you be sure you really need the symbolic toolbox!
If you do, and n is the result of a calculation that yield one specific integer, you can convert it to normal numerical form using uint32(n) or similar, see the help on conversions, e.g.
Y = fft(X,uint32(n))
Update: The error message you give in the comment implies that your n is in fact not an integer... I doubt you will be able to use it with fft.