How to change the heaviside function -- and how to use the new function with symbolic objects?
Mostrar comentarios más antiguos
Hi.
I created this function (it is equal to the heaviside function):
function Y = fzine( X )
Y = zeros(size(X));
Y(X > 0) = 1;
eng = symengine;
if strcmp(eng.kind,'maple')
Y(X == 0) = nan;
else
Y(X == 0) = 0;
end
Now, why if
syms x
I get:
>> heaviside(x)
ans =
heaviside(x)
BUT
>> fzine(x) ??? Error using ==> sym.sym>notimplemented at 2621 Function 'gt' is not implemented for MuPAD symbolic objects.
Error in ==> sym.sym>sym.gt at 801 notimplemented('gt');
Error in ==> fzine at 7 Y(X > 0) = 1;
The two functions (fzine and heaviside) share the same code...?
1 comentario
Andrew Newell
el 10 de Abr. de 2011
Editada: Andrew Newell
el 6 de Jun. de 2013
Note to readers of this question: To see how the accepted answer relates to the question, read How to change the heaviside function -- and how to use the new function with symbolic objects?, How to change the heaviside function -- and how to use the new function with symbolic objects?, and How to change the heaviside function -- and how to use the new function with symbolic objects? in that order.
Respuesta aceptada
Más respuestas (13)
Andrew Newell
el 9 de Abr. de 2011
The symbolic toolbox cannot evaluate X > 0 for a symbolic variable X. You can make a small change in your function so it can handle a symbolic variable:
function Y = fzine( X )
Y = zeros(size(X));
Y(double(X) > 0) = 1;
eng = symengine;
if strcmp(eng.kind,'maple')
Y(X == 0) = nan;
else
Y(X == 0) = 0;
end
Now if you try
fzine(sym(1))
you get
ans =
1
(you can also input a double variable). It still won't handle fzine(x); but notice that
heaviside(x)
just returns the name of the function. It isn't trying to actually evaluate heaviside(x).
12 comentarios
condor
el 9 de Abr. de 2011
Walter Roberson
el 9 de Abr. de 2011
fzine = @(x) evalin(symengine,subs('piecewise([x > 0, 1], [Otherwise, 0])'))
condor
el 10 de Abr. de 2011
Walter Roberson
el 10 de Abr. de 2011
What happens if you try
subs('piecewise([x > 0,1],[Otherwise,0])',x,5)
condor
el 10 de Abr. de 2011
Walter Roberson
el 10 de Abr. de 2011
I mean, what happens if you type that at the command line?
condor
el 10 de Abr. de 2011
Walter Roberson
el 10 de Abr. de 2011
It means that piecewise is working. I bet class() of the above result would show sym, a symbolic 1.
So then,
fzine = @(x) subs('piecewise([x > 0,1],[Otherwise,0])','x',x);
condor
el 10 de Abr. de 2011
condor
el 10 de Abr. de 2011
Walter Roberson
el 10 de Abr. de 2011
Looks like it.
condor
el 10 de Abr. de 2011
Andrew Newell
el 10 de Abr. de 2011
Here is a numerical version of what you wish to do. First, the function:
function y = heavy0(x)
y = 0*x;
y(x>0) = 1;
Now solve with it:
costi= @(x) heavy0(x-10)*2+heavy0(x-50)*2.5+heavy0(x-100)*3+15;
delta = @(x) 1.3*costi(x)+costi(x)-x;
fzero(delta,0)
ans =
39.1000
This also works for problems where the solution is the zero point of a heaviside function:
costi = @(x) heavy0(x-10)+x-10;
fzero(costi,1)
ans =
10
Paulo Silva
el 9 de Abr. de 2011
0 votos
good question, I'm also clueless about why that happens
Walter Roberson
el 9 de Abr. de 2011
0 votos
Your fzine is probably not in the private directory of the symbolic functions, so probably you are not getting the correct methods invoked for all items.
condor
el 9 de Abr. de 2011
0 votos
condor
el 9 de Abr. de 2011
0 votos
condor
el 9 de Abr. de 2011
0 votos
condor
el 10 de Abr. de 2011
4 comentarios
condor
el 10 de Abr. de 2011
Andrew Newell
el 10 de Abr. de 2011
Right. Heaviside is calling a function in the MuPad engine.
Walter Roberson
el 10 de Abr. de 2011
Odd... your path says 2010b, which is restricted to using MuPad and cannot use Maple. I wonder if the internals of the symbolic toolbox still say Maple in places ??
condor
el 10 de Abr. de 2011
Andrew Newell
el 10 de Abr. de 2011
Here is a different way you could approach this problem:
fzine = (x + abs(x))/2;
delta = fzine+15+12*x;
simplify(solve(delta))
ans =
-5/4
In fact, you could define your function this way:
function Y = fzine( X )
Y = (X + abs(X))/2;
Y(X~=0) = Y/X;
This now behaves almost exactly like the Heaviside function. Even the derivative works:
>> fd = simplify(diff(fzine(x)))
fd =
-(abs(x) - x*sign(x))/(2*x^2)
>> subs(fd,-2)
ans =
0
>> subs(fd,2)
ans =
0
The only difference is for x=0:
>> subs(fd,0)
ans =
NaN
(the derivative of heaviside gives Inf).
EDIT: Another difference occurs if you try this:
y = fzine(x);
subs(y,0)
ans =
NaN
EDIT: I think the problem with the original function is not just the greater than sign. It is the conditional commands, which make it impossible for the function to return an explicit symbolic expression. For more general cases, you could replace a lot of if/then conditions by expressions involving ... (drum roll) heaviside.
6 comentarios
condor
el 10 de Abr. de 2011
condor
el 10 de Abr. de 2011
Andrew Newell
el 10 de Abr. de 2011
Mind you, it is not exactly the same as heaviside, so it's risky to use. Why not use heaviside?
condor
el 10 de Abr. de 2011
Andrew Newell
el 10 de Abr. de 2011
Sorry, I got a bit hasty there (I'm trying to keep up with your comments!). I added a line above.
condor
el 10 de Abr. de 2011
condor
el 10 de Abr. de 2011
1 comentario
Walter Roberson
el 10 de Abr. de 2011
1) I don't know. I used the piecewise version in Maple and it gave only the first (391/10) solution.
2) I do not have the Symbolic Toolbox so I cannot check or test the heaviside source code myself.
Andrew Newell
el 10 de Abr. de 2011
0 votos
@Condor, I think you are mistaken that the function heaviside uses the same code as the other functions we have considered. heaviside is an interface to MuPAD code, which creates a MuPAD object that can be manipulated according to the rules in MuPAD. For example, operators like diff and int can act on heaviside, while they cannot on Walter's version of fzine. My function behaves a little more like a symbolic object, but I have described some shortcomings.
You can easily create a function that gives the correct numerical answer for a numerical input. But you want it to do more than that. You want it to create that MuPAD object even though we don't even know the properties of MuPAD objects.
It's an interesting exercise seeing where attempts to recreate heaviside fall short, but do we really need to go further with this? Why not just use heaviside?
7 comentarios
condor
el 10 de Abr. de 2011
condor
el 10 de Abr. de 2011
condor
el 10 de Abr. de 2011
Andrew Newell
el 10 de Abr. de 2011
Yes, it is much slower than using heaviside.
Andrew Newell
el 10 de Abr. de 2011
The difference in value at x=0 only matters if your solution turns out to be 10, 50, or 100 in the example you've given. But you could check that these aren't solutions by substituting, e.g., subs(costi,10).
condor
el 10 de Abr. de 2011
Andrew Newell
el 10 de Abr. de 2011
Then you would be better off treating this as a numerical problem in Matlab itself instead of MuPAD. Implementing a numerical version of heaviside is trivial, and you can use FZERO to find the solution.
Konstantinos
el 18 de Mayo de 2013
Editada: Walter Roberson
el 18 de Mayo de 2013
The way I found so you can do your job is for example:
I wanted to find the Z transform of the following:
syms n z
x2 = n*heaviside(n) + (6-2*n)*heaviside(n-6) + (n-6)*heaviside(n-6);
ztrans(x2, n, z)
and it would give me a wrong value because of the heaviside(n-6). So I fixed it by instead using:
x2 = n*heaviside(n) + (6-2*n)*heaviside(n-5.5) + (n-6)*heaviside(n-5.5);
Basically I guess using some double inbetween your discrete values will fix all the problems. I could have also changed heaviside(n) to heaviside(n+0.5) but there wasn't a point in this particular example. Hope this helps.
Categorías
Más información sobre Functional Programming en Centro de ayuda y File Exchange.
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!