MatLab: identical function gets two different results - matlab

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.

Related

Calculating the numeric derivative

So i'm a little confounded by how to structure my problem.
So the assignment states as following:
Type a m-file numerical_derivative.m that performs numerical derivation. Use
it to calculate f'(-3) when f(x) = 3x^2 /(ln(1-x))
In the m-file you to use h = 10^-6 and have the following mainfunction:
function y = numericalderivative (f, x)
% Calculates the numerical value in the case of f in punk x.
% --- Input ---
% f: function handle f(x)
% x: the point where the derivative is calculated
% --- output ---
% y: the numerical derivative of f on the point x
If I want to save it as a file and run the program in matlab, does't it make it redundant to use handles then?
I won't give you the answer to your homework, but perhaps a simpler example would help.
Consider the following problem
Write a function named fdiff which takes the following two arguments:
A function f represented by a function handle which takes one argument,
and a point x which can be assumed to be in the domain of the f.
Write fdiff so that it returns the value f(x) - f(x-1)
Solution (would be in the file named fdiff.m)
function result = fdiff(f, x)
result = f(x) - f(x-1);
end
Example Use Cases
>> my_function1 = #(x) 3*x^2 /(log(1-x));
>> fdiff(my_function1, -3)
ans =
-10.3477
>> my_function2 = #(x) x^2;
>> fdiff(my_function2, 5)
ans =
9
What you've created with fdiff is a function which takes another function as an input. As you can see it doesn't just work for 3*x^2 /(log(1-x)) but any function you want to define.
The purpose of your assignment is to create something very similar, except instead of computing f(x) - f(x-1), you are asked write a function which approximates f'(x). Your use-case will be nearly identical to the first example except instead of fdiff your function will be named numericalderivative.
Note
In case it's not clear, the second example defines the my_function2 as x^2. The value returned by fdiff(my_function2, 5) is therefore 5^2 - 4^2 = 9.
When you make this as a function file and run this in MATLAB without any input arguments i.e., 'f' and 'x', it will give you the error: 'not enough input arguments'. In order to run the file you have to type something like numericalderivative (3x^2 /(ln(1-x)), 5), which gives the value of the numerical derivative at x = 5.
Functions and, in MATLAB function files are a simple implementation of the DRY programming method. You're being asked to create a function that takes a handle and an x file, then return the derivative of that function handle and that x value. The point of the function file is to be able to re-use your function with either multiple function handles or multiple x values. This is useful as it simply involves passing a function handle and a numeric value to a function.
In your case your script file or command window code would look something like:
func = #(x) (3*x^2)/log(1-x);
x = -3;
num_deriv = numericalderivative(func,x);
You should write the code to make the function numericalderivative work.

Is there any way around Error: ()-indexing must appear last in an index expression?

For whatever reason, Matlab does not allow repeating round brackets () - the iterator.
This blocks direct access to outputs of functions which are multidimensional array and makes dictionary object immutable, among other applications.
For example,
func1=#(x)[sin(x);cos(x)];
% let S be some large struct where everything is stored
func2=#(str)S.(str);
% let D be some containers.Map object where everything is stored
D(key)=[1;2];
In all of the 3 cases above, it is useful to be able to access the array elements directly. But any of
func1(Pi)(i); func2(f1)(i); D(key)(i)
will result in the error
()-indexing must appear last in an index expression.
Is there anyway around this besides creating a temporary variable?
As well, if your answer is that temporary variable is the ONLY way to go, would you kindly show me whether the creation of a second variable will result in duplication of the data in memory?
For the first function you could use getfield (but this use of getfield is not documented, so I wouldn't recommend it):
>> func1 = #(x) [sin(x); cos(x)];
>> func1(4.8)
ans =
-0.9962
0.0875
>> getfield(func1(4.8), {1})
ans =
-0.9962
Or you could define an indexing function to extract the desired element(s):
>> index = #(x,n) x(n);
>> index(func1(4.8), 1)
ans =
-0.9962
Another possibility is to define func1 as a (cell)-array of functions, instead of an array-valued function, so that you can separately refer to each value :
>> func1 = {#(x) sin(x), #(x) cos(x)};
>> func1{1}(4.8)
ans =
-0.9962
For the second function the first two methods above are applicable:
>> S.fieldA = [11 22 33];
>> func2 = #(str) S.(str);
>> getfield(func2('fieldA'), {3})
ans =
33
>> index(func2('fieldA'), 3)
ans =
33
For containers.Map, applying getfield twice seems to work as well (again, I wouldn't recommend it):
>> D = containers.Map({'abc', 'def'}, {10, [20 30]});
>> getfield(getfield(D,{'def'}), {2})
ans =
30
Or use the indexing function:
>> index(D('def'), 2)
ans =
30
I would recommend the indexing function approach, which is safe and general.
I believe there is a way, and it's right here on SO: this question.
However, like the comments said it is quite ugly and the temp variable way is much more readable.
As for your follow up question, in general assigning the same array to a different variable will not generate a deep copy and only the reference is duplicated. This holds true until you modify the array using the copied reference, at which point Matlab steps in and performs the deep copy. See this Mathworks article on the subject.

octave plot does not work properly

CODE DELETED
Hi, the code above is my (slightly modified) rooo.m file.
I'm just trying to plot the function by typing into (octave) terminal
x = 1:1:40;
plot(x, rooo(x), '+');
But this will only print the graph of y=1.
I believe it's because of the y = 1; in the first line (btw the function itself returns the right value, say when I type rooo(3)).
When I change it to some other number (say b), the graph will show y =b.
Does anyone have an idea why this is happening??
I think it's not working because if you type rooo(x) at the command line, it will return a scalar result of 1, instead of a vector. The 1 < n logical condition doesn't work as you intended to when n is a vector.
Here is a suggestion to make it work (maybe not the most elegant but it seems to work):
CODE DELETED
Which, when called as in your question, gives the following plot
The results seem to be different from the ones reported in MATLAB though.
An alternative, if you don't want to modify your function, is to change the way you call it:
>> x = 1:1:40;
>> y = ones(size(x));
>> for k=1:length(x)
y(k) = rooo(x(k));
end
>> plot(x,y,'+')
This gives the same result as the above suggestion.
It's not working because you never enter the while loop with x starting at 1. Since
1 < n == 1 < x is false at the very beginning, the function returns.
However when you call rooo(3) or actually rooo(Anything > 1) it does work. With x = 1.1:1:40 the plot looks like this ( I made it with Matlab) :

Error with recursive function in m-file

I'm working on chapter 8 of A Course in Mathematical Biology. The textbook uses Maple, but includes this link, Computer course of Chapter 8 in Matlab. I'm told to put the following in an m-file:
% defining a recursive function in an m-file
function y = plot_traj(a)
RM = inline('a*x.*exp(-x)', 'a', 'x')
% Note that we are using an inline function. Sometimes it’s easier to do this.
% collecting list of x-coordinates
for i = 1:31,
X(i) = i - 1
end
% collecting list of y-coordinates
for i = 1:30,
Y(i+1)=RM(a,iter(i));
iter(i+1) = Y(i+1);
end
y = plot(X, Y, '*');
Now, save your m-file (as plot traj.m) and close it. Type the following into the command window:
>> plot traj(0.8)
>> plot traj(1.0)
>> plot traj(5.0)
>> plot traj(8.0)
>> plot traj(13.0)
>> plot traj(14.5)
>> plot traj(20.0)
However, when I type plot traj(0.8) into the command window I get this:
>> plot_traj(0.8)
Undefined function or variable "iter".
Error in plot_traj (line 13)
Y(i)=RM(a,iter(i));
I don't see anything wrong with line 13, and I've made sure that my code is exactly what is in the chapter. I've been doing fine with the codes up until this point. I'd appreciate it if anyone could provide some assistance. Thank you.
The problem at line 13 is that the iter local variable array has not been defined. So on the first iteration, the code tries to access iter(1) and fails. I looked at the link you provided and they missed it too. Based on previous examples in the Matlab_Course.pdf (and figure 8.6), the iter array should be initialized as
iter(1) = 1.0;
Just add this line prior to the for loop and you should be good to continue. I suspect also that this line should be added too (again based on the document)
Y(1)=iter(1);
to make sure that both iter and Y have the same length.
Note that it is a good habit to pre-allocate memory to arrays to avoid the internal resizing of matrices/arrays on each iteration of the loop (which can have a negative impact on performance). For this loop
for i = 1:30,
Y(i+1)=RM(a,iter(i));
iter(i+1) = Y(i+1);
end
you can observe that i iterates over 1 through 30, and we always populate Y(i+1) and iter(i+1). So both Y and iter are 31x1 vectors. We can allocate memory to each prior to entering the for loop as
iter = zeros(31,1);
Y = zeros(31,1);
iter(1) = 1;
Y(1) = iter(1);
The same should be done for X as well.

Matlab, function handle auto use parameter

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.