I would like to find the values of the function for which its derivative is equal to zero.
function val = Heart(x1, x2)
val=(1.25*x2-sqrt(abs(x1))).^2+x1.^2-1;
endfunction;
I've tried it with the numderivative function.
Scilab cannot solve this problem in the way your function is currently defined because Heart() is an implicit function. As answered here, Scilab is not capable of doing implicit differentiation. Moreover, your equation actually defines a 3D surface, so what you can calculate are actually partial derivatives.
If you want to find the x1 values in which the derivative in relation to x1 of the implicit curve 0=Heart(x1,x2) are zero, you can use the method presented in this answer from your own previous question to solve this.
If you inspect the plot of heart curve, you'll see that there are only two points where the derivative is zero (two maxima): they are located in the upper part of the curve and are near x1=-0.6 and x1=0.6, respectively. To find more approximate values of these points, you should do the following:
Take the upper part of the heart (use Wolfram|Alpha to find it) and define a new function.
Use numderivative() to define its derivative, d_heart(). The answer we are looking for are the zeros of this function.
Use fsolve() to solve 0=d_heart(x1). You should input two guesses and they can be -0.6 and 0.6.
Something like this:
function y = heart_up(x1)
y = 4/5 * (sqrt(abs(x1))+sqrt(1-x1.^2))
endfunction
function y = d_heart(x1)
y = numderivative(heart_up, x1);
endfunction
x1 = fsolve(-0.6, d_heart); y1 = heart_up(x1);
x2 = fsolve( 0.6, d_heart); y2 = heart_up(x2);
You can visualize that heart_up() is really the upper part of the heart and that the results are right by plotting them:
x = -1:0.01:1;
contour2d(x, 2*x, Heart, [0 0]);
plot2d(x, heart_up(x), 2);
plot2d([x1 x2], [y1 y2], -2);
Is it possible to shorten (improve) this script? I think of the Jacobian Heart function, evaluate it and find the points where it is zero. Some rides !!!
Following the indications of luispauloml:
[function val = Heart(x1, x2)
val=(1.25*x2-sqrt(abs(x1))).^2+x1.^2-1;
endfunction;
function y = heart_up(x1)
y = 4/5 * (sqrt(abs(x1))+sqrt(1-x1.^2))
endfunction
function y = heart_down(x1)
y = 4/5 * (sqrt(abs(x1))-sqrt(1-x1.^2))
endfunction
function y = du_heart(x1)
y = numderivative(heart_up, x1);
endfunction
function y = dd_heart(x1)
y = numderivative(heart_down, x1);
endfunction
x1 = fsolve(-0.6, du_heart); y1 = heart_up(x1);disp(y1,"y1",x1,"x1");
x2 = fsolve( 0.6, du_heart); y2 = heart_up(x2);disp(y2,"y2",x2,"x2");
x3 = fsolve( 0.0, du_heart); y3 = heart_up(x3);disp(y3,"y3",x3,"x3");
x4 = fsolve( 0.0, dd_heart); y4 = heart_down(x4);disp(y4,"y4",x4,"x4");
x = -1:0.01:1;
contour2d(x, 2*x, Heart, \[0 0\]);
plot(\[x1 x2\],\[y1 y2\],'gd');
plot(\[x3 x4\],\[y3 y4\],'rx');
replot(\[-1.415,-1,1.415,1.415\]);][1]
Another possible solution is:
With this function we have begun to familiarize ourselves with Scilab.
In the script that I propose we have found the critical or extreme points of the Heart function.
We call your attention in reading the comments !!!!
function val = Hxyg(x,y)
val=(1.25*y-sqrt(abs(x))).^2+x.^2-1;
endfunction;
x = -1:0.01:1;
contour2d(x, 2*x, Hxyg, [0 0]);
replot([-1.415,-1,1.415,1.415]);
//We define the Hxy function with x as additional input argument( as a parameter)
//Since y, will be our unknown, we have interposed x and y in the argument list of the Hxy function
//(y it is the unknown and x is the parameter).
//This will be necessary to determine the intersects on the Y axis
function val = Hxy(y,x)
val=(1.25*y-sqrt(abs(x))).^2+x.^2-1; // switched .^ to ^ to handle vectors
endfunction;
function [val] = HH(v)//v:(y,x)
x=v(2);
y=v(1);
val=Hxy(y,x);
endfunction;
function Jpx=dfx(v)//v:(y,x)
Jpx=numderivative(HH,v);
Jpx=Jpx(2);
endfunction
//Find the local maxima.
function Z = flm(v)//v:(y,x)
Z = [ HH(v)
dfx(v)
]
endfunction
//v:(y,x)
xlm1=fsolve([1.4;-0.4],flm)
disp(xlm1)
xlm2=fsolve([1.4;0.4],flm)
disp(xlm2)
plot([xlm1(2) xlm2(2)],[xlm1(1) xlm2(1)],'gx')
//Find the y-intercepts. Hxy(y,x)
//the Hxy function uses x as a parameters.
//We define the Hxy function with x as additional input argument( as a parameter),
//which is declared after the y unknown. Then we pass a list as the second input argument
//of the fsolve function after initial value of Hxy function argument; in this situation only variable y.
//The first element of the list is the Hxy function. The additional variable x is directly passed to the Hxy function.
x=0.0;
yint1=fsolve(1,list(Hxy,x))// --->Hxy(y,x)=>1.5625*y^2-1
disp(yint1)
yint2=fsolve(-1,list(Hxy,x))// ---> Hxy(y,x)=>1.5625*y^2-1
disp(yint2)
plot([x x],[yint1 yint2],'rx')
Heart Critical points or extreme points
Related
I'm having trouble writing this code. So, I'm trying to make a code for
func = y*x(n) + z * x(n)
All the values are arbitrary and x(n) is the value at the position n. I need to plot a graph at each nth position. So if x(1) = 5 I plot a point at when x=1 and y=5. The issue is that I can't figure out how to make an arbitrary array and don't know how to get the answer for func when I add x(n) value at the nth position. I also am having trouble plotting a graph, but think this is because I can't figure out to use the array yet.
I'm new to MatLab.
So if I am following y & z are just constants? I think the confusion is typically this would be written something like "y = ax +bx"
Like Cris Luengo mentioned in the comments above, you should should go over some basic Matlab tutorials as this is very basic.
% y and Z are constants
y = 1;
z = 2;
%this makes x = [0,1,2,...10];
x = 0:1:10;
func = y.*x + z.*x;
plot(func)
This should do the trick:
% Define X as a range between -10 to 10 (+1 on every step)...
x = -10:10;
% Define your constants...
y = 3;
z = -1;
% Define the function...
fun = #(x) (y .* x) + (z .* x);
% Plot X on the x-axis and fun(x) on the y-axis...
% fun(x) numerically evaluates fun for the given x
plot(x,fun(x));
Refer to this page for more information about anonymous functions.
Consider a function y(x) sampled in an array of values, represented by the arrays x and y. If I have another x value x0, I can evaluate y(x0) using spline
y0 = spline(x,y,x0);
Now, I can also write
pp = spline(x,y);
y0 = ppval(pp,x0);
MY QUESTION: If I already have the coefficient and x matrices, my_coefs (size(my_coefs) = [length(y),4]) and x, how can I create a piecewise polynomial My_pp such that pp.coefs = my_coefs and that y0 = ppval(My_pp,x0)?
OK, There is no "spline object", but rather a piecewise polynomial object. So, if my_coefs was attained by break-points my_x then the code needed is
my_spline = mkpp(my_x,my_coefs);
y0 = ppval(my_spline, x0);
In case that dimensions are dazzeling here, which they are, then
my_coefs is 4*n
my_x is n
y0 is N
x0 is N
let's consider a two dimensional fonction f(x,y)
and tree points A,B,C with ABC a triangle
and i want to integrate the function f over the triangle ABC,
is there a way to do that in matlab?
thank you.
You can create a new function h(x,y), that returns f(x,y) if (x,y) is inside the polygon, and 0 otherwise.
For instance:
A = [0, 0];
B = [0, 5];
C = [5, 0];
triangleX = [A(1) B(1) C(1)];
triangleY = [A(2) B(2) C(2)];
f = #(x,y) (1);
h = #(x,y) (inpolygon(x, y, triangleX, triangleY) .* f(x,y));
q = integral2(h, min(triangleX), max(triangleX), min(triangleY), max(triangleY)
'Method', 'iterated')
Outputs (which may be close enough for you):
q =
12.500070877352647
And another function:
f = #(x,y) (x .* y);
q = integral2(#foo, min(triangleX), max(triangleX), min(triangleY), max(triangleY),
'Method', 'iterated')
q =
26.042038561947592
Notice that the integral2 documentation states:
When integrating over nonrectangular regions, the best performance and
accuracy occurs when ymin, ymax, (or both) are function handles. Avoid
setting integrand function values to zero to integrate over a
nonrectangular region. If you must do this, specify 'iterated' method.
So it'll be better if instead of using the above solution, you write two functions that given an x coordinate, give you the minimal and maximal y coordinates of the polygon (triangle).
I found the correct answer,
thanks to this https://math.stackexchange.com/questions/954409/double-integral-over-an-arbitrary-triangle
function r = intm2(f, t)
% f: function
% t: three points of a triangle
% r: integration of f over t
a = t(1,:);
b = t(2,:);
c = t(3,:);
jg = abs((b(1)-a(1))*(c(2)-a(2))-(c(1)-a(1))*(b(2)-a(2)));
ftilda = #(u,v) f(a(1)+u*(b(1)-a(1))+v*(c(1)-a(1)), a(2)+u*(b(2)-a(2))+v*(c(2)- a(2)));
fy = #(x) 1-x;
r = jg * integral2(ftilda, 0,1, 0,fy);
end
I'm trying to create a function, that has two output arguments:
1. The calculated f(x) value
2. The gradient
But it's calling itself recursively all the time.
What am I doing wrong?
function [y, gra] = f1(x)
y = x^2
syms z
gra = gradient(f1(z))
Thanks.
edit:
Now I have this:
function [y, gra] = f1(x)
y = x^2
if nargout == 2
syms x
gra = gradient(f1(x))
end
edit 2:
I'm trying to use the function in the following:
[y, grad] = f1(5);
y_derived = grad(10);
I think this is what you want to do:
function [y, gra] = f1(x)
f=#(x) x^2;
y=f(x); %// calculate y
syms z %// initialise symbolic variable
gra=gradient(f(z),z); %// symbolic differentiation
This will return g as a symbolic function. To calculate a value, you can use subs(gra,z,123), or, if you are going to evaluate it many times, do gradFunc=matlabFunction(gra) then gradFunc(v) where v is a vector or matrix of points you want to evaluate.
That's because the argument into gradient is your function name f1(z). As such, it keeps calling f1 when your original function is also called f1, and so the function keeps calling itself until you hit a recursion limit.
I think you meant to put gradient(y) instead. Try replacing your gradient call so that it is doing:
gra = gradient(y);
I'm trying to get Matlab to take this as a function of x_1 through x_n and y_1 through y_n, where k_i and r_i are all constants.
So far my idea was to take n from the user and make two 1×n vectors called x and y, and for the x_i just pull out x(i). But I don't know how to make an arbitrary sum in MATLAB.
I also need to get the gradient of this function, which I don't know how to do either. I was thinking maybe I could make a loop and add that to the function each time, but MATLAB doesn't like that.
I don't believe a loop is necessary for this calculation. MATLAB excels at vectorized operations, so would something like this work for you?
l = 10; % how large these vectors are
k = rand(l,1); % random junk values to work with
r = rand(l,1);
x = rand(l,1);
y = rand(l,1);
vals = k(1:end-1) .* (sqrt(diff(x).^2 + diff(y).^2) - r(1:end-1)).^2;
sum(vals)
EDIT: Thanks to #Amro for correcting the formula and simplifying it with diff.
You can solve for the gradient symbolically with:
n = 10;
k = sym('k',[1 n]); % Create n variables k1, k2, ..., kn
x = sym('x',[1 n]); % Create n variables x1, x2, ..., xn
y = sym('y',[1 n]); % Create n variables y1, y2, ..., yn
r = sym('r',[1 n]); % Create n variables r1, r2, ..., rn
% Symbolically sum equation
s = sum((k(1:end-1).*sqrt((x(2:end)-x(1:end-1)).^2+(y(2:end)-y(1:end-1)).^2)-r(1:end-1)).^2)
grad_x = gradient(s,x) % Gradient with respect to x vector
grad_y = gradient(s,y) % Gradient with respect to y vector
The symbolic sum and gradients can be evaluated and converted to floating point with:
% n random data values for k, x, y, and r
K = rand(1,n);
X = rand(1,n);
Y = rand(1,n);
R = rand(1,n);
% Substitute in data for symbolic variables
S = double(subs(s,{[k,x,y,r]},{[K,X,Y,R]}))
GRAD_X = double(subs(grad_x,{[k,x,y,r]},{[K,X,Y,R]}))
GRAD_Y = double(subs(grad_y,{[k,x,y,r]},{[K,X,Y,R]}))
The gradient function is the one overloaded for symbolic variables (type help sym/gradient) or see the more detailed documentation online).
Yes, you could indeed do this with a loop, considering that x, y, k, and r are already defined.
n = length(x);
s = 0;
for j = 2 : n
s = s + k(j-1) * (sqrt((x(j) - x(j-1)).^2 + (y(j) - y(j-1)).^2) - r(j-1)).^2
end
You should derive the gradient analytically and then plug in numbers. It should not be too hard to expand these terms and then find derivatives of the resulting polynomial.
Vectorized solution is something like (I wonder why do you use sqrt().^2):
is = 2:n;
result = sum( k(is - 1) .* abs((x(is) - x(is-1)).^2 + (y(is) - y(is-1)).^2 - r(is-1)));
You can either compute gradient symbolically or rewrite this code as a function and make a standard +-eps calculation. If you need a gradient to run optimization (you code looks like a fitness function) you could use algorithms that calculate them themselves, for example, fminsearch can do this