I'm all new to Matlab and I'm supposed to use this function to find all 3 zero spots.
f.m (my file where the function can be found)
function fval = f(x)
% FVAL = F(X), compute the value of a test function in x
fval = exp(-x) - exp(-2*x) + 0.05*x - 0.25;
So obviously I write "type f" to read my function but then I try to do like fzero ('f', 0) and I get the ans 0.4347 and I assume that's 1 of my 3 zero spots but how to find the other 2?
From fzero documentation
x = fzero(fun,x0) tries to find a zero of fun near x0, if x0 is a scalar. fun is a function handle. The value x returned by fzero is near a point where fun changes sign, or NaN if the search fails. In this case, the search terminates when the search interval is expanded until an Inf, NaN, or complex value is found.
So it can't find all zeros by itself, only one! Which one depends on your inputted x0.
Here's an example of how to find some more zeros, if you know the interval. However it just repeatedly calls fzero for different points in the interval (and then still can miss a zero if your discretization is to coarse), a more clever technique will obviously be faster:
http://www.mathworks.nl/support/solutions/en/data/1-19BT9/index.html?product=ML&solution=1-19BT9
As you can see in the documentation and the example above, the proper way for calling fzero is with a function handle (#fun), so in your case:
zero1 = fzero(#f, 0);
From this info you can also see that the actual roots are at 0.434738, 1.47755 and 4.84368. So if you call fzero with 0.4, 1.5 and 4.8 you probably get those values out of it (convergence of fzero depends on which algorithm it uses and what function you feed it).
Just to complement Gunther Struyf's answer: there's a nice function on the file exchange by Stephen Morris called FindRealRoots. This function finds an approximation to all roots of any function on any interval.
It works by approximating the function with a Chebyshev polynomial, and then compute the roots of that polynomial. This obviously only works well with continuous, smooth and otherwise well-behaved functions, but the function you give seems to have those qualities.
You would use this something like so:
%# find approximate roots
R = FindRealRoots(#f, -1, 10, 100);
%# refine all roots thus found
for ii = 1:numel(R)
R(ii) = fzero(#f, R(ii)); end
Related
Is there any method to find the root of a polynomial, not in matrix form, in MATLAB?
I know, to find roots of a polynomial (say, p(x) = x^.2 - 4), I should do the following:
p = [1 0 -4];
r = roots(p)
What I wanted to know if there is some way to find the root of a function (say p(x) = x^.2 - 4) already present in polynomial form (not in matrix form) in my matlab code? Like anything similar to r = roots(p(x)) (this doesn't work, of course).
Root is good
First of all the solution using roots is probably the one that will give you the most accurate and fastest results if you are indeed working with polynomials. I will acknowledge that it might be an issue if your function is not a polynomial.
Finding the roots of a function
If you don't want to use roots that means you will probably have to represent your polynomial as an anonymous function. Then you can use any root-finding algorithm on that function. Wikipedia has a few of them listed. What is tricky is that in general they don't guarantee that they will find one root, let alone all of them. So you might need as much prior information on your function as you can.
In matlab you can use fzero. The issue with it is that it only finds one zero and that it will only find zeros where the function changes sign (it wouldn't work on p(x) = x² for example). This is how you would implement it:
p = #(x) x.^2 - 4; % Define your polynomial as an anonymous function
x0 = 12; % Initial guess for the zero
% Find a root
fzero(p, x0)
>>> ans = 2
% Now with a different initial guess for a different solution
x0 = -12;
fzero(p, x0)
>>> ans = -2
As you can see this works only if you want to find a root and don't care which one it is.
Problem
The issue is that you polynomials with integer or rational coefficients have a way of finding the roots by using square-free factorization. Yet you can only apply that if you have some way of storing and accessing those coefficients in matlab. The anonymous functions don't allow you to do that. That's why roots works with a matrix and not an anonymous function.
error: 'y' undefined near line 8 column 12
error: called from computeCost at line 8 column 3
Here is my code:
1;
function J = computeCost(X, y, theta)
%COMPUTECOST Compute cost for linear regression
% J = COMPUTECOST(X, y, theta) computes the cost of using theta as the
% parameter for linear regression to fit the data points in X and y
% Initialize some useful values
m = length(y); % number of training examples
% You need to return the following variables correctly
J = 0;
% ====================== YOUR CODE HERE ======================
% Instructions: Compute the cost of a particular choice of theta
% You should set J to the cost.
J = sum(( X * theta - y ) .^2 )/( 2 * m );
% =========================================================================
end
I am guessing it's an error from Coursera ML course assignment. I think you are trying to run the file which contains the implementation of function computeCost(X, y, theta), not the file which calls the computeCost(,,) function with values of X, y, theta. This is why you are getting the error as you aren't providing y.
Run the file which is calling computeCost() function, not the file which contains the implementation of computeCost() function.
That is:
For Week2 Assignment 1: Run ex1.m file
For Week3 Assignment 2: Run ex2.m file
There are two things happening here. First you are defining your function dynamically as opposed to in its own file; not sure why you would prefer that.
Second, after having defined this computeCost function, you are calling it from a context where you did not pass a y argument (or presumably, you didn't pass any arguments to it, and y happens to be the first one detected as missing inside the function).
Since this is a cost function and your code looks suspiciously like code from Andrew Ng's Machine Learning course on Coursera, I am going to go out on a limb here and guess that you called computeCost from something else that was supposed to use it as a cost function to be optimised, e.g. fminunc. Typically functions like fminunc expect a function handle as an argument, but they expect a very specific function handle too. If you look at the help of fminunc, it states that:
FCN should accept a vector (array) defining the unknown variables,
and return the objective function value, optionally with gradient.
Therefore, if you want to pass a function that is to be computed with three arguments, you need to "wrap" it into your own handle, which you can define on the spot, e.g. #(x) computeCost(x, y, t) (assuming 'y' and 't' exist already).
So, I'm guessing that instead of calling fminunc like so: fminunc( #(x) computeCost(x, y, t),
you probably called it like so: fminunc( #computeCost )
or even like so: fminunc( computeCost ) (which evaluates the function first, rather than pass a function handle as an argument).
Basically, go back to the code given to you by coursera, or read the notes carefully. You're calling things the wrong way.
Actually, you are trying to run a function and you can't run it until you provide the desired no. of parameters. Doing so, you may encounter the following error:
computeCost error: 'y' undefined near line 7 column 12
error: called from computeCost at line 7 column 3
As you see, here I'm calling this function without passing any argument.
SOLUTION:
You can test your code by running 'ex1' script. After that submit your work by calling 'submit' script.
I searched the forum and found this thread, but it does not cover my question
Two ways around -inf
From a Machine Learning class, week 3, I am getting -inf when using log(0), which later turns into an NaN. The NaN results in no answer being given in a sum formula, so no scalar for J (a cost function which is the result of matrix math).
Here is a test of my function
>> sigmoid([-100;0;100])
ans =
3.7201e-44
5.0000e-01
1.0000e+00
This is as expected. but the hypothesis requires ans = 1-sigmoid
>> 1-ans
ans =
1.00000
0.50000
0.00000
and the Log(0) gives -Inf
>> log(ans)
ans =
0.00000
-0.69315
-Inf
-Inf rows do not add to the cost function, but the -Inf carries through to NaN, and I do not get a result. I cannot find any material on -Inf, but am thinking there is a problem with my sigmoid function.
Can you provide any direction?
The typical way to avoid infinity in these cases is to add eps to the operand:
log(ans + eps)
eps is a very, very small value, and won't affect the output for values of ans unless ans is zero:
>> z = [-100;0;100];
>> g = 1 ./ (1+exp(-z));
>> log(1-g + eps)
ans =
0.0000
-0.6931
-36.0437
Adding to the answers here, I really do hope you would provide some more context to your question (in particular, what are you actually trying to do.
I will go out on a limb and guess the context, just in case this is useful. You are probably doing machine learning, and trying to define a cost function based on the negative log likelihood of a model, and then trying to differentiate it to find the point where this cost is at its minimum.
In general for a reasonable model with a useful likelihood that adheres to Cromwell's rule, you shouldn't have these problems, but, in practice it happens. And presumably in the process of trying to calculate a negative log likelihood of a zero probability you get inf, and trying to calculate a differential between two points produces inf / inf = nan.
In this case, this is an 'edge case', and generally in computer science edge cases need to be spotted as exceptional circumstances and dealt with appropriately. The reality is that you can reasonably expect that inf isn't going to be your function's minimum! Therefore, whether you remove it from the calculations, or replace it by a very large number (whether arbitrarily or via machine precision) doesn't really make a difference.
So in practice you can do either of the two things suggested by others here, or even just detect such instances and skip them from the calculation. The practical result should be the same.
-inf means negative infinity. Which is the correct answer because log of (0) is minus infinity by definition.
The easiest thing to do is to check your intermediate results and if the number is below some threshold (like 1e-12) then just set it to that threshold. The answers won't be perfect but they will still be pretty close.
Using the following as the sigmoid function:
function g = sigmoid(z)
g = 1 ./ (1 + e.^-z);
end
Then the following code runs with no issues. Choose the threshold value in the 'max' statement to be less than the expected noise in your measurements and then you're good to go
>> a = sigmoid([-100, 0, 100])
a =
3.7201e-44 5.0000e-01 1.0000e+00
>> b = 1-a
b =
1.00000 0.50000 0.00000
>> c = max(b, 1e-12)
c =
1.0000e+00 5.0000e-01 1.0000e-12
>> d = log(c)
d =
0.00000 -0.69315 -27.63102
I encountered some problems while trying to solve an integration equations using MapleSoft.There are 4 functions that are important. Here is my code defining the functions and trying to solve the problem:
"T is the starting point of the problem where it's given."
{T := proc (t) options operator, arrow; sqrt(t)/(sqrt(t)+sqrt(1-t))^2 end proc;}
"Now I solved for the inverse of function T."
V := proc (t) options operator, arrow;([solve(t = T(y), y, useassumptions)], [0 <= t and t <= 1]) end proc; '
"Only the first solution to the above is the correct inverse as we can see from the plot below."
sol := [allvalues(V(t))]; plot([t, T(t), op(1, sol), op(2, sol)], t = 0 .. 1, legend = [typeset("Curve: ", "t"), typeset("Curve: ", "T(t)"), typeset("Curve: ", "V(t)"), typeset("Curve: ", "V2(t)")]);
"Now I define the first solution as my inverse function called V1."
V1 := proc (t) options operator, arrow; evalf(op(1, sol)) end proc
"As the problem required, I have to find the derivative of V1. I call it dV."
dV := proc (t) options operator, arrow; diff(V1(t), t) end proc
"Then define a new function called F"
F := proc (t) options operator, arrow; -10*ln(1-t*(1-exp(-1))) end proc
"With V1(t), F(t), dV(t) defined, we define a new function U."
U := proc (t,lambda) options operator, arrow; piecewise(t <= .17215, min(IVF(V1(t)), max(0, 12-(1/4)/(lambda^2*dV(t)^2))), .17215 <= t, min(IVF(V1(t)), max(0, 12-(1/4)*.7865291304*lambda^-2))) end proc;
"Next I will be trying to find the value of lambda, such that the"
solve(int(U(t,lambda)*dV(t),t=0..1)= R,lambda)
"where the R will be a real number, let's say 2.93 for now."
I think the code works fine all the way till the last step where I had to solve the integration. I couldn't figure out why.
I was trying to progress further, solving the U, i.e U(t) will be 0 if t<=0.17215 and 12-(1/4)/(lambda^2*dV(t)^2)<=0 or t>=0.17215 and 12-(1/4)*0.7865291304*lambda^-2<=0 and so on so forth. But had problem solving the inequality. For example, solve(12-1/4*lambda^-2*dV(t)^-2<=0,t). The programme runs indefinitely.
Appreciate your input!
I'm guessing that by IVF(V1(t)) you really meant F(V(t)) .
It seemed to me that computation of your dV(t) (and perhaps V(t) sometimes) for very small t might exhibit some numerical difficulty.
And I was worried that using a narrower range of integration like, say, t=1.0e-2 .. 1.0, might mess with some significant contribution to the integral from that portion.
So below I've constructed V and dV so that they raised Digits (only) for greater working precision on (only) their own body of calculations.
And I've switched it from symbolic integration to numeric/float integration. And I've added the epsilon option for that, in case you need to control the accuracy tolerance more finely.
Some of these details help with the speed issues you mentioned above. And some of those details slow the computation down a bit, while perhaps giving a greater sense of robustness of it.
The plotting command calls below are just there for illustration. Comment them out if you please.
I used Maple 2018.0 for these. If you have difficulties then please report your particular version used.
restart;
T:=sqrt(x)/(sqrt(x)+sqrt(1-x))^2:
Vexpr:=solve(t=T,x,explicit)[1]:
Vexpr:=simplify(combine(Vexpr)) assuming t>0, t<1:
The procedure for computing V is constructed next. It's constructed in this subtle way for two reasons:
1) It internally raises working precision Digits to avoid round-off error.
2) It creates (and throws away) an empty list []. The effect of this is that it will not run under fast hardware-precision evalhf mode. This is key later on, during the numeric integration.
V:=subs(__dummy=Vexpr,
proc(t)
if not type(t,numeric) then
return 'procname'(t);
end if;
[];
Digits:=100;
evalf(__dummy);
end proc):
V(0.25);
0.2037579200498004992002294012453548811286405373\
653346413644953624868320875151070347969077227713469370
V(1e-9);
1.0000000040000000119998606410199120814521886485524\
-18
22617659574502917213370846924673012122642160567565 10
Let's plot T and V,
plot([T, V(x)], x=0..1);
Now let's create a procedure for the derivative of V, using the same technique so that it too raises Digits (only internal to itself) and will not run under evalhf.
dV:=subs(__dummy=diff(Vexpr,t),
proc(t)
if not type(t,numeric) then
return 'procname'(t);
end if;
[];
Digits:=100;
evalf(__dummy);
end proc):
Note that calling dV(t) for unknown symbol t makes it return unevaluated. This is convenient later on.
dV(t);
dV(t)
dV(0.25);
2.44017580084567947538393626436824494366329948208270464559139762\
2347525580165201957710520046760103982
dV(1e-15);
-5.1961525404198771358909147606209930290335590838862019038834313\
73611362758951860627325613490378754702
evalhf(dV(1e-15)); # I want this to error-out.
Error, unable to evaluate expression to hardware floats: []
This is your F.
F:=t->-10*ln(1-t*(1-exp(-1))):
Now create the procedure U. This too returns unevaluated when either of its argument is not an actual number. Note that lambda is its second parameter.
U:=proc(t,lambda)
if not ( type(t,numeric) and
type(lambda,numeric) ) then
return 'procname'(args);
end if;
piecewise(t <= .17215,
min(F(V(t)), max(0, 12-(1/4)/(lambda^2*dV(t)^2))),
t >= .17215,
min(F(V(t)), max(0, 12-(1/4)*.7865291304*lambda^(-2))));
end proc:
Let's try a particular value of t=0.2 and lambda=2.5.
evalf(U(0.2, 2.5));
.6774805135
Let's plot it. This takes a little while. Note that it doesn't seem to blow up for small t.
plot3d([Re,Im](U(t,lambda)),
t=0.0001 .. 1.0, lambda=-2.0 .. 2.0,
color=[blue,red]);
Let's also plot dV. This takes a while, since dV raises Digits. Note that it appears accurate (not blowing up) for small t.
plot(dV, 0.0 .. 1.0, color=[blue,red], view=-1..4);
Now let's construct a procedure H which computes the integral numerically.
Note that lambda is it's first parameter, which it passes as the second argument to U. This relates to your followup Comment.
The second parameter of H is passed to evalf(Int(...)) to specify its accuracy tolerance.
Note that the range of integration is 0.001 to 1.0 (for t). You can try a lower end-point closer to 0.0 but it will take even longer for compute (and may not succeed).
There is a complicated interplay between the lower end-point of numeric integration, and accuracy tolerance eps, and the numeric behavior for U and V and dV for very small t.
(The working precision Digits is set to 15 inside H. That's just to allow the method _d01ajc to be used. It's still the case that V and dV will raise working precision for their own computations, at each numeric invocation of the integrand. Also, I'm using unapply and a forced choice of numeric integration method as a tricky way to prevent evalf(Int(...)) from wasting a lot of time poking at the integrand to find singularities. You don't need to completely understand all these details. I'm just explaining that I had reasons for this complicated set-up.)
H:=proc(lambda,eps)
local res,t;
Digits:=15;
res:=evalf(Int(unapply(U(t,lambda)*dV(t),t),
1e-3..1,
epsilon=eps, method=_d01ajc) - R);
if type(res,numeric) then
res;
else
Float(undefined);
end if;
end proc:
Let's try calling H for a specific R. Note that it's not fast.
R:=2.93;
R := 2.93
H(0.1,1e-3);
-2.93
H(0.2,1e-5);
0.97247264305333
Let's plot H for a fixed integration tolerance. This takes quite a while.
[edited] I originally plotted t->H(t,1e-3) here. But your followup Comment showed a misunderstanding in the purpose of the first parameter of that operator. The t in t->H(t,1e-3) is just a dummy name and DOES NOT relate to the t parameter of V and dV, and the second parameter of U, and the integration varaible. What matters is that this dummy is passed as the first argument to H, which in turn passes it as the second argument to U, which is used for lambda. Since there was confusion earlier, I'll use the dummy name LAMBDA now.
plot(LAMBDA->H(LAMBDA,1e-3), 0.13 .. 0.17 , adaptive=false, numpoints=15);
Now let's try and find the value of that root (intercept).
[edited] Here too I was earlier using the dummy name t for the first argument of H. It's just a dummy name and does not relate to the t parameter of V and dV, and the second parameter of U, and the variable of integration. So I'll change it below to LAMBDA to lessen confusion.
This is not fast. I'm minimizing the absolute value because numeric accuracy issues make this problematic for numeric root-finder fsolve.
Osol:=Optimization:-Minimize('abs(H(LAMBDA,1e-3))', LAMBDA=0.15..0.17);
[ -8 ]
Osol := [1.43561000000000 10 , [LAMBDA = 0.157846355888300]]
We can pick off the numeric value of lambda (which "solved" the integration).
rhs(Osol[2,1]);
0.157846355888300
If we call H using this value then we'll get a residual (similar to the first entry in Osol, but without absolute value being taken).
H(rhs(Osol[2,1]), 1e-3);
-8
-1.435610 10
Now you have the tools to try and obtain the root more accurately. To do so you may experiment with:
tighter (smaller) eps the tolerance of numeric integration.
A lower end-point of the integration closer to 0.0
Even higher Digits forced within the procedures V and dV.
That will require patience, since the computations take a while, and since the numeric integration can fail (taking forever) when those three aspects are not working properly together.
I've I edit the body of procedure H and change the integration range to instead be 1e-4 .. 1.0 then I get the following result (specifying 1e-5 for eps in the call to H).
Osol:=Optimization:-Minimize('abs(H(LAMBDA,1e-5))', LAMBDA=0.15..0.17);
[ -7 ]
Osol := [1.31500690000000 10 , [LAMBDA = 0.157842787382700]]
So it's plausible that this approximate root lambda is accurate to perhaps 4 or 5 decimal places.
Good luck.
I'd like to write a Mathematica function that takes an expression as argument, takes the derivative of that expression, and then does something to the expression. So (as a toy example) I'd like to write
F[f_] = D[f, x] * 2
so that
F[x^2] = 4x
Instead, I get
F[x^2] = 0
Can someone point me to the relevant docs? I spent some time poking around the Mathematica reference, but didn't find anything helpful.
You've used assignment = when you mean to use delayed assignment :=. When you evaluate F[f_]=D[f,x]*2 using (non-delayed) assignment, Mathematica looks at D[f,x] and sees that f (an unassigned symbol) does not depend on x; hence, its derivative is 0. Thus, F[f_]=0 for any arguments to F, which is what it returns later.
If you want F to be evaluated only after you have specified what f_ should be, you need to use delayed assignment by replacing = with :=.