Hi I have a question about how to achieve the following behaviour in Matlab.
A.x=pi
A.sin=#()sin(A.x)
A.sin() % Returns 1.2246e-16, essentially 0 so all good so far.
% Now for the problem
A.x = pi/2
A.sin() % Returns 1.2246e-16, meaning the new A.x is not used. It should return 1.
Does anyone have any ideas how to achieve this. I know I could define A.sin as #(x) sin(x) then provide A.x but would rather find an alternative.
Thanks.
Create this class:
classdef mytrig
properties
x
end
methods
function out = sin(obj)
out = sin(obj.x);
end
end
end
Then at the command line:
>> A = mytrig;
>> A.x = pi;
>> A.sin
ans =
1.2246e-016
>> A.x = pi/2;
>> A.sin
ans =
1
The way you're doing it at the moment won't work, because when you create the function handle A.sin=#()sin(A.x), the function handle captures a copy of the current workspace, including x, which then remains fixed afterwards, even if you subsequently change x. If you want to be able to change x afterwards yourself, these best way would be to be implement a class as above.
Hope that helps!
Once you assign a value to a variable in Matlab, it is fixed.
If you want to have something that is updated automatically, please look into classes.
If you don't like classes, you could also define a function, for example
myAsin = #()sin(A.x)
Can't test it now, but as it is a function you should be getting the updated value when you call it after A.x is updated.
Related
I think inputparser is doing that, but I couldn't find an example that shows how.
In my function, I define a struct named opts which contain the parameters that control the function. Example :
function y = f(x, extraOpts)
opts= struct( ...
'N', 100, ...
'visualize', 1, ... % etc
);
do_things(x, opts);
end
Fields of opts have default values, but I want to be able to change them selectively. So I want to call the function with something like this:
f(x, {'visualize', 0});
in which case .N remains 100 but .visualize becomes 0.
How can I achieve this with MATLAB? Also not sure if it will require the extraOpts parameter. I would of course prefer a way with function y = f(x) :)
Thanks for any help !
You can use MATLAB's inputParser class:
http://www.mathworks.com/help/matlab/ref/inputparser-class.html
http://blogs.mathworks.com/community/2012/02/13/parsing-inputs/
EDIT: I guess I'll just put the code in as well...
function y = f(x, extraOpts)
p = inputParser;
p.addRequired('x', #(x) length(x)>1);
p.addOptional('visualize', 1, #isscalar);
p.addOptional('N', 100, #isscalar);
p.parse(x, extraOpts{:});
do_things(x, extraOpts);
end
You might need to store the results of the parse, perhaps something along the lines of:
inputs = p.parse(x, extraOpts{:});
do_things(inputs)
END EDIT
Alternatively, you could do something like redefine your function to take the number of values in your struct though it's not as powerful as the input parser solution:
function y = f(N, visualize)
if nargin < 2
visualize = 0
end
if nargin < 1
visualize = 0
N = 100
end
I couldn't make the answer work, but I found another solution with inputParser, let me paste here for future reference :
function y = f2(extraOpts)
p = inputParser;
p.addParamValue('par1', 'defaultValue1');
p.addParamValue('par2', def2, #isnumeric);
p.addParamValue('par3', def3, #isnumeric);
p.parse(extraOpts{:});
extraOpts = p.Results;
end
the drawback is that I needed to separate the two inputs x and extraOpts and had to call f2 as a subroutine, defined in the same file as f. Maybe there is a more elegant way for this (i.e. one that does not require another function), but the example I have seen was also doing like that, and since it works, it's good for me :)
I define a class CellArrayHandle whose only property is a cell array of function handles:
classdef CellArrayHandle < handle
properties
cel % cell array of function handles
end
end
Suppose myHandle is an object of CellArrayHandle, so myHandle.cel is a n-by-1 cell array of function handles, i.e myHandle.cel{i} is a function handle for i = 1 to n.
I want to do some update (for e.g. i=1), but the following does not work:
myHandle.cel{1} = #(x) myHandle.cel{1}(x) + 0.5;
Matlab says "Maximum recursion limit of 500 reached", so it seems to be understood as an infinite recursion. However the fowllowing works:
f = #(x) f(x) + 0.5;
for a function handle f.
It seems when I encapsulate a function handle into a class as a property, the above update method will not work.
I do not understand the difference between the former and the latter. Could any people help me on this point? Thank you very much.
Best regards,
Frank
The difference stems from the semantics of a handle class:
You can assign the handle object to multiple variables or pass it to functions without causing MATLAB to make a copy of the original object.
Or, to borrow the original idea of Highlander, when you instantiate a handle class, "there can be only one" (glob of the instance in memory which all variables you assign it to only creating references and not new copies).
Consider the example script:
f = #(x) x;
f = #(x) f(x) + 0.25;
f = #(x) f(x) + 0.50;
b = CellArrayHandle();
b.cel{1} = #(x) x;
b.cel{1} = #(x) b.cel{1}(x) + 0.25;
b.cel{1} = #(x) b.cel{1}(x) + 0.5;
fval = f(1);
bval = b.cel{1}(1);
If I debug this script and look at the stack right before fval evaluates, I see:
K>> dbstack
> In #(x)x
In #(x)f(x)+0.25
In #(x)f(x)+0.5
So Matlab was able to create a copy of the current f function handles during the creation of subsequent f handles and could form a stack.
When I do the same thing to b, I get this:
K>> dbstack
> In #(x)b.cel{1}(x)+0.5
In #(x)b.cel{1}(x)+0.5
In #(x)b.cel{1}(x)+0.5
In #(x)b.cel{1}(x)+0.5
In #(x)b.cel{1}(x)+0.5
In #(x)b.cel{1}(x)+0.5
...
This happens because each assignment to a property of b makes the property of b that value without creating a new instance of the class. So the assignment is inherently infinitely recursive.
You can fix this by not having the class inherit from handle but from value (the default). By removing the < handle from the classdef, and repeating the dbstack of the handle call, we have
K>> dbstack
> In #(x)x
In #(x)b.cel{1}(x)+0.25
In #(x)b.cel{1}(x)+0.5
And this happens because each assignment to a property of b now makes a copy of the current b, instantiates a new b, and stores the old definition of b within the function handle to form the proper stack.
I see the following behavior in 2013a and 2014a on Windows computers:
Someone sends me a .mat file. In this file, a function fi(th, beta) is defined. On the command line I call fi for two values (actually beta is a matrix). Then, I click "edit value" for fi and don't change anything. Then, when I call fi(th, beta) again I get a completely different value.
How can this be? How can I tell what is the "correct" value?
The reason behind your issue is that when clicking edit value on a function handle, it gets updated. In your function, D is used, which was a variable during creation of the function handle. Suppose D now has another value, fi will use the new value after pressing edit value. Let me give you an example:
>> k = 2;
>> f = #(x)k*x;
>> f(4)
ans =
8
>> k = 4;
>> f(4)
ans =
8
In this example, k is changed after f is defined. However, f will have its original definition. When I use edit value and don't change anything, it will nevertheless use the new value of k.
>> f % only to show the function has not changed
f =
#(x)k*x
>> f(4)
ans =
16
I hope this clearifies your problem.
Your question regarding the correct value thus depends on the values and function handles used inside the function handle.
I have a function and I want to each time change its input and integrate over a certain interval. For example, I first write an m file:
function y = myfun(x)
y = 1 ./ (x.^3 - 2*x - 5);
Now I want to integrate functions like myfun(x-2) or myfun(2*x). Does anyone know how I should pass them? Integral(myfun(x-2),a,b) creates an error.
Thanks
I suggest calling integral on a handle for your function as below:
h1 = #(x)myfun(x);
h2 = #(x)myfun(x-2);
h3 = #(x)myfun(x.^2);
integral(h1,a,b);
integral(h2,a,b);
integral(h3,a,b);
This should trick the integral function into thinking that you are just defining myfun as a function of x while allowing you to pass whatever expression you want to it. You could also pass additional parameters this way, such as:
h = #(x)myfun(x, params);
integral(h,a,b);
Where params could be a list of parameters that you use in your definition of myfun.
I hope that helps.
EDIT: I tested this on a server that I have access to which does have the integral function and it seemed to work. Hopefully this answers your question.
I have one file with the following code:
function fx=ff(x)
fx=x;
I have another file with the following code:
function g = LaplaceTransform(s,N)
g = ff(x)*exp(-s*x);
a=0;
b=1;
If=0;
h=(b-a)/N;
If=If+g(a)*h/2+g(b)*h/2;
for i=1:(N-1)
If=If+g(a+h*i)*h;
end;
If
Whenever I run the second file, I get the following error:
Undefined function or variable 'x'.
What I am trying to do is integrate the function g between 0 and 1 using trapezoidal approximations. However, I am unsure how to deal with x and that is clearly causing problems as can be seen with the error.
Any help would be great. Thanks.
Looks like what you're trying to do is create a function in the variable g. That is, you want the first line to mean,
"Let g(x) be a function that is calculated like this: ff(x)*exp(-s*x)",
rather than
"calculate the value of ff(x)*exp(-s*x) and put the result in g".
Solution
You can create a subfunction for this
function result = g(x)
result = ff(x) * exp(-s * x);
end
Or you can create an anonymous function
g = #(x) ff(x) * exp(-s * x);
Then you can use g(a), g(b), etc to calculate what you want.
You can also use the TRAPZ function to perform trapezoidal numerical integration. Here is an example:
%# parameters
a = 0; b = 1;
N = 100; s = 1;
f = #(x) x;
%# integration
X = linspace(a,b,N);
Y = f(X).*exp(-s*X);
If = trapz(X,Y) %# value returned: 0.26423
%# plot
area(X,Y, 'FaceColor',[.5 .8 .9], 'EdgeColor','b', 'LineWidth',2)
grid on, set(gca, 'Layer','top', 'XLim',[a-0.5 b+0.5])
title('$\int_0^1 f(x) e^{-sx} \,dx$', 'Interpreter','latex', 'FontSize',14)
The error message here is about as self-explanatory as it gets. You aren't defining a variable called x, so when you reference it on the first line of your function, MATLAB doesn't know what to use. You need to either define it in the function before referencing it, pass it into the function, or define it somewhere further up the stack so that it will be accessible when you call LaplaceTransform.
Since you're trying to numerically integrate with respect to x, I'm guessing you want x to take on values evenly spaced on your domain [0,1]. You could accomplish this using e.g.
x = linspace(a,b,N);
EDIT: There are a couple of other problems here: first, when you define g, you need to use .* instead of * to multiply the elements in the arrays (by default MATLAB interprets multiplication as matrix multiplication). Second, your calls g(a) and g(b) are treating g as a function instead of as an array of function values. This is something that takes some getting used to in MATLAB; instead of g(a), you really want the first element of the vector g, which is given by g(1). Similarly, instead of g(b), you want the last element of g, which is given by g(length(g)) or g(end). If this doesn't make sense, I'd suggest looking at a basic MATLAB tutorial to get a handle on how vectors and functions are used.