Change of variable in MATLAB? - matlab

I have defined several anonymous functions which normally depend on three variables eta1, eta2, y. There is the following relationship between eta1 eta2 and y
eta1=#(y) ((i*alpha1*lambda_0)^(1/3))*y+eta01;
eta2=#(y) ((i*alpha2*lambda_0)^(1/3))*y+eta02;
So I basically give values for y and then I am able to plot h1b(y=whatever) via arrayfun:
DW1=#(eta) blablabla
N3Y=#(y) i*alpha1*(DW1(eta1(y))*conj(U2(eta2(y)))+W1(eta1(y))...
*conj(DU2(eta2(y))));
h1b=#(y) -(1/(lambda_0*alphats))*(betats*N3Y(y));
vec=arrayfun(h1b,eta1(0:0.01:N));
plot(abs(vec),0:0.01:N)
My question: is there a way to retrieve h1b formally depending on eta1 instead of y, as an anonymous function? Without evaluating y, subsequently eta1,eta2 and then h1b, which is what I do.

Lets clarify. So you currently have:
syms y eta1 eta2;
eta1(y), eta2(y)
W1(eta1), DW1(eta1)
U2(eta2) DU2(eta2)
Hence you also have:
N3Y(W1,DW1,U2,DW2)
or:
N3Y(eta1,eta2)
or:
N3Y(y)
Hence, you have:
h1b(N3Y)
or:
h1b(eta1,eta2)
or:
h1b(y)
So, h1b depends solely on eta1 and eta2, so if you dot want to manipulate kinky eval and simplify calls, why you just dont create two versions of your functions, one with y and other with etas?.
You dont need to rewrite, the ys versions are just evaluated from the etas versions.

Related

How to define custom functions in Maple?

I'm new to Maple and I'm looking for a simple way to automate some tasks. In particular, I'm looking for a way to define custom "action" that perform some steps automatically.
As as an example I would like to define a quick way to compute the determinant of the Hessian of a polynomial. Currently the way I do this is opening Maple, create a new worksheet than performing the following commands:
p := (x, y) -> x^2*y + 3*x^3 + y^3
with(VectorCalculus):
h := Hessian(p(x, y), [x, y])
Determinant(h)
What I would like to do is to compute the hessian determinant directly with something like
HessDet(p)
where HessDet would be a custom command that performs the operations above. How does one achieve something like this in Maple?
First things first: The value assigned to your p is a procedure which can return a polynomial expression, but not itself a polynomial. It's important not to muddle expressions and procedures. Doing so is a common cause of problems for new users.
Being able to throw around p(x,y) may be visually pleasing to your eye, but it serves little programmatic purpose here. The fact that the formal parameters of procedure p happen to be called x and y, along with the fact that you called procedure p with arguments x and y, is actually just another common source of confusion. Don't create procedures merely to call them in this way.
Also, your call p(x,y) makes it look magic that your code snippet "knows" how many arguments would be required by procedure p. So it's already a muddle to have your candidate HessDet accept p as a procedure.
So instead let's keep it straightforward, by writing HessDet to accept a polynomial rather than a procedure. We can programmatically ascertain the names in which this expression of of type polynom.
restart;
HessDet:=proc(p::algebraic)
local H,vars;
vars:=indets(p,
And(name,Non(constant),
satisfies(u->type(p,polynom(anything,u)))));
H:=VectorCalculus:-Hessian(p,[vars[]]);
LinearAlgebra:-Determinant(H);
end proc:
Now some examples of using it,
P := x^2*y + 3*x^3 + y^3;
HessDet(P);
p := (x, y) -> x^2*y + 3*x^3 + y^3;
HessDet(p(x,y));
HessDet(x^3-x^2+4*x);
HessDet(s^2*t + 3*s^3 + t^3);
HessDet(s[r]^2*t[r] + 3*s[r]^3 + t[r]^3);
You might also wonder how you could re-use this custom procedure across sessions, without having to type it in each time. Two reasonable ways are:
Put the (above) defining plaintext definition of HessDet inside a personal initialization file.
Create a (.mla) Maple Library Archive file, then Save your HessDet to that, and then augment the Library search path in your initialization file.
It might look like 2) is more effort, but only the Save step is needed for repeats, and you can store many custom procedures to the same archive. Your choice...
[edit] The OP has asked for clarification of the first part of the above procedure HessDet, which I suspect means the call to indets.
If P is assigned an expression then then the call indets(P,name) will return a set of all the names present in that expression. Basically, it returns the set of all indeterminate subexpressions of the expression which are of type name in Maple's technical sense.
For example,
P := x*y + sin(a*Pi)*x;
x y + sin(a Pi) x
indets( P,
name );
{Pi, a, x, y}
Perhaps the name of the constant Pi is not wanted here. Ie,
indets( P,
And( name,
Non(constant) ) );
{a, x, y}
Perhaps we want only the non-constant names in which the expression is a polynomial? Ie,
indets( P,
And( name,
Non(constant),
satisfies(u->type(p,polynom(anything,u))) ) );
{x, y}
That last result is an advanced way of using the following tests:
type(P, polynom(anything, x));
true
type(P, polynom(anything, y));
true
type(P, polynom(anything, a));
false
A central issue here is that the OP made no mention of what kind of polynomials are to be handled by the custom procedure. So I guessed with some defensive coding, in hope of less surprises later on. The original Question states that the input could be a "polynomial", but we weren't told what kind of coefficients there might be.
Perhaps the coefficients will always be real and exact or numeric. Perhaps the custon procedure should throw an error when not supplied such. These details weren't mentioned in the Question.

MATLAB: Defining a function in terms of another function

If I have a function f(x,y), I want to know how to define another function (say g) where g(x) = f(x,y), where y has been defined beforehand, either explicitly or as the input of another function.
I know this is probably quite simple but my code does not seem to work and I cannot find a solution in the documentation.
You are probably looking for anonymous functions.
A very common use-case is minimiziation. You often need to minimize a function of multiple variables along a single parameter. This leaves you without the option of just passing in constants for the remaining parameters.
An anonymous definition of g would look like this:
g = #(x) f(x, y)
y would have to be a variable defined in the current workspace. The value of y is bound permanently to the function. Whether you do clear y or assign a different value to it, the value of y used in g will be whatever it was when you first created the function handle.
As another, now deleted, answer mentioned, you could use the much uglier approach of using global variables.
The disadvantages are that your code will be hard to read and maintain. The value of the variable can change in many places. Finally, there are simply better ways of doing it available in modern versions of MATLAB like nested functions, even if anonymous functions don't work for you for some reason.
The advantages are that you can make g a simple stand alone function. Unlike the anonymous version, you will get different results if you change the value of y in the base workspace, just be careful not to clear it.
The main thing to remember with globals is that each function/workspace wishing to share the value must declare the name global (before assigning to it to avoid a warning).
In the base workspace:
global y
y = ...
In g.m:
function [z] = g(x)
global y;
z = f(x, y);
I am not particularly recommending this technique, but it helps to be aware of it in case you can't express g as a single statement.
A note about warnings. Both anonymous functions and globals will warn you about assigning to a variable that already exists. That is why putting a global declaration as the first line of a function is generally good practice.
f = #(a,b) a^2 + b^2;
y = 4;
g = #(x) f(x,y);
g(2)
ans = 20

string input to anonymous function in MATLAB

In matlab i know i can convert string into anonymous function with str2func.
For example;
s= '#(x) x.^2';
h= str2func(s);
h(2) would be 4
But what if i do not know the number of unknown? Let's say user of this program will enter lots of function to get a numerical solution of a system. When the user enters x^2, i should add #(x) to its beginning then convert it to a function. But in programming time i do not know how many function the user will enter with how many unknown. #(x) may should be #(x,y) as well as #(x,y,z). If the user enters the number of unknowns, how can i create and add the necessary prefix at runtime?
ps: number of unknown can be any integer number.
You need to know not only the quantity of variables but also their names and order. An expression may read x(c). Even if you know that the expression has two variables in it and are able to parse out x and c, you won't be able to tell if the user intended to define something like #(x, c) x(c), #(c, x) x(c) or even something like #(c, d) x(c) where x is actually a function.
Parsing the expressions just to get the names they use is something that you shouldn't have to do.
Restricting the variable names that are allowed can be messy. If the user is expecting MATLAB syntax and you are parsing as MATLAB, why make your life harder? Also, when you introduce a restriction like one-letter variable names only, you have to ask yourself if there will ever be a situation where you need more than 27 variables.
It would be much safer all around to have the user list the names of the variables they plan on using before the function, e.g. (x, y, pi) pi*(x^2 + y). Now all you have to do is prepend # and not worry about whether pi is a built-in or an argument. In my opinion the notation is quite clean.

Create vector-valued function with arbitrary components

Good evening everyone,
I want to create a function
f(x) = [f1(x), f2(x), ... , fn(x)]
in MatLab, with an arbitrary form and number for the fi. In my current case they are meant to be basis elements for a finite-dimensional function space, so for example a number of multi variable polynomials. I want to able to be able to set form (e.g. hermite/lagrange polynomials, ...) and number via arguments in some sort of "function creating" function, so I would like to solve this for arbitrary functions fi.
Assume for now that the fi are fi:R^d -> R, so vector input to scalar output. This means the result from f should be a n-dim vector containing the output of all n functions. The number of functions n could be fairly large, as there is permutation involved. I also need to evaluate the resulting function very often, so I hope to do it as efficiently as possible.
Currently I see two ways to do this:
Create a cell with each fi using a loop, using something like
funcell{i}=matlabFunction(createpoly(degree, x),'vars',{x})
and one of the functions from the symbolic toolbox and a symbolic x (vector). It is then possible to create the desired function with cellfun, e.g.
f=#(x) cellfun(#(v) v(x), funcell)
This is relatively short, easy and what can be found when doing searches. It even allows extension to vector output using 'UniformOutput',false and cell2mat. On the downside it is very inefficient, first during creation because of matlabFunction and then during evaluation because of cellfun.
The other idea I had is to create a string and use eval. One way to do this would be
stringcell{i}=[char(createpoly(degree, x)),';']
and then use strjoin. In theory this should yield an efficient function. There are two problems however. The first is the use of eval (mostly on principle), the second is inserting the correct arguments. The symbolic toolbox does not allow symbols of the form x(i), so the resulting string will not contain them either. The only remedy I have so far is some sort of string replacement on the xi that are allowed, but this is also far from elegant.
So I do have ways to do what I need right now, but I would appreciate any ideas for a better solution.
From my understanding of the problem, you could do the straightforward:
Initialization step:
my_fns = cell(n, 1); %where n is number of functions
my_fns{1} = #f1; % Assuming f1 is defined in f1.m etc...
my_fns{2} = #f2;
Evaluation at x:
z = zeros(n, 1);
for i=1:n,
z(i) = my_fns{i}(x)
end
For example if you put it in my_evaluate.m:
function z = my_evaluate(my_fns, x)
z = zeros(n, 1);
for i=1:n,
z(i) = my_fns{i}(x)
end
How might this possibly be sped up?
Depends on if you have special structure than can be exploited.
Are there calculations common to some subset of f1 through fn that need not be repeated with each function call? Eg. if the common calculation step is costly, you could do y = f_helper(x) and z(i) = fi(x, y).
Can the functions f1...fn be vector / matrix friendly, allowing evaluation of multiple points with each function call?
The big issue is how fast your function calls f1 through fn are, not how you collect the results from those calls in a vector.

Can I Expand "Nested" Symbolic Functions in Matlab?

I'm trying to model the effect of different filter "building blocks" on a system which is a construct based on these filters.
I would like the basic filters to be "modular", i.e. they should be "replaceable", without rewriting the construct which is based upon the basic filters.
For example, I have a system of filters G_0, G_1, which is defined in terms of some basic filters called H_0 and H_1.
I'm trying to do the following:
syms z
syms H_0(z) H_1(z)
G_0(z)=H_0(z^(4))*H_0(z^(2))*H_0(z)
G_1(z)=H_1(z^(4))*H_0(z^(2))*H_0(z)
This declares the z-domain I'd like to work in, and a construct of two filters G_0,G_1, based on the basic filters H_0,H_1.
Now, I'm trying to evaluate the construct in terms of some basic filters:
H_1(z) = 1+z^-1
H_0(z) = 1+0*z^-1
What I would like to get at this point is an expanded polynomial of z.
E.g. for the declarations above, I'd like to see that G_0(z)=1, and that G_1(z)=1+z^(-4).
I've tried stuff like "subs(G_0(z))", "formula(G_0(z))", "formula(subs(subs(G_0(z))))", but I keep getting result in terms of H_0 and H_1.
Any advice? Many thanks in advance.
Edit - some clarifications:
In reality, I have 10-20 transfer functions like G_0 and G_1, so I'm trying to avoid re-declaring all of them every time I change the basic blocks H_0 and H_1. The basic blocks H_0 and H_1 would actually be of a much higher degree than they are in the example here.
G_0 and G_1 will not change after being declared, only H_0 and H_1 will.
H_0(z^2) means using z^2 as an argument for H_0(z). So wherever z appears in the declaration of H_0, z^2 should be plugged in
The desired output is a function in terms of z, not H_0 and H_1.
A workable hack is having an m-File containing the declarations of the construct (G_0 and G_1 in this example), which is run every time H_0 and H_1 are redefined. I was wondering if there's a more elegant way of doing it, along the lines of the (non-working) code shown above.
This seems to work quite nicely, and is very easily extendable. I redefined H_0 to H_1 as an example only.
syms z
H_1(z) = 1+z^-1;
H_0(z) = 1+0*z^-1;
G_0=#(Ha,z) Ha(z^(4))*Ha(z^(2))*Ha(z);
G_1=#(Ha,Hb,z) Hb(z^(4))*Ha(z^(2))*Ha(z);
G_0(H_0,z)
G_1(H_0,H_1,z)
H_0=#(z) H_1(z);
G_0(H_0,z)
G_1(H_0,H_1,z)
This seems to be a namespace issue. You can't define a symbolic expression or function in terms of arbitrary/abstract symfuns and then later on define these symfuns explicitly and be able to use them to obtain an exploit form of the original symbolic expression or function (at least not easily). Here's an example of how a symbolic function can be replaced by name:
syms z y(z)
x(z) = y(z);
y(z) = z^2; % Redefines y(z)
subs(x,'y(z)',y)
Unfortunately, this method depends on specifying the function(s) to be substituted exactly – because strings are used, Matlab sees arbitrary/abstract symfuns with different arguments as different functions. So the following example does not work as it returns y(z^2):
syms z y(z)
x(z) = y(z^2); % Function of z^2 instead
y(z) = z^2;
subs(x,'y(z)',y)
But if the last line was changed to subs(x,'y(z^2)',y) it would work.
So one option might be to form strings for case, but that seems overly complex and inelegant. I think that it would make more sense to simply not explicitly (re)define your arbitrary/abstract H_0, H_1, etc. functions and instead use other variables. In terms of the simple example:
syms z y(z)
x(z) = y(z^2);
y_(z) = z^2; % Create new explicit symfun
subs(x,y,y_)
which returns z^4. For your code:
syms z H_0(z) H_1(z)
G_0(z) = H_0(z^4)*H_0(z^2)*H_0(z);
G_1(z) = H_1(z^4)*H_0(z^2)*H_0(z);
H_0_(z) = 1+0*z^-1;
H_1_(z) = 1+z^-1;
subs(G_0, {H_0, H_1}, {H_0_, H_1_})
subs(G_1, {H_0, H_1}, {H_0_, H_1_})
which returns
ans(z) =
1
ans(z) =
1/z^4 + 1
You can then change H_0_ and H_1_, etc. at will and use subs to evaluateG_1andG_2` again.