I have this function with all variables in the unit square:
(x + y)^(1/2) - 6*y*(x + y)^5 - (x + y)^6 + (x - 1)/(2*(x + y)^(1/2))
ezplot yields this figure:
I want to numerically find 2 points in this plot: First, the minimum value of x on the green line (that is, approx. (0.11, 0.4)) and second, the maximum value of y on the green line (that is, approx. (0.15, 0.43)). These approximate value are just rough estimates from the figure. How can I retrieve these 2 values numerically in matlab?
Ezplot. You need the handle.
h = ezplot('(x + y)^(1/2) - 6*y*(x + y)^5 - (x + y)^6 + (x - 1)/(2*(x + y)^(1/2))', [0 1]);
Get the data.
data = get(h, 'ContourMatrix')
Remove first column
data = data(:,2:end)
You have what you need. First row are 'x' values and second row are 'y' values.
x_min = min(data(1,:));
y_max = max(data(2,:));
Related
I am trying to implement Midpoint formulas y[n+1/2] = y[n] + h/2 f (x[n], y[n]) and y[n+1] = y[n] + h *f (x[n] + h/2, y[n + 1/2])
so it solves ODE using midpoint method.
My function is
function [ x, y ] = Midpoint_ODE ( f, xRange, yInitial, numSteps )
% f = name of file with function
% xrange Interval
% x(1) first meaning of x
% x(2) second meaning of x
x=zeros(numSteps+1,1);
x(1) = xRange(1);
h = ( xRange(2) - xRange(1) ) / numSteps; % calculated step size
y(1,:) = transpose(yInitial);
for n = 1 : numSteps
y(n+0.5,:)= (y(n) + (h * 0.5)*(transpose(feval( f, x(n), y(n)))));
y(n+1,:) = y(n,:) + h * transpose(feval(f, x(n)+ (h/2), y(n+0.5,:))); %evaluating the function
end
But I get an error :
**Index in position 1 is invalid. Array indices must be positive integers or logical values.
Error in Midpoint_ODE (line 11)Index in position 1 is invalid. Array indices must be positive integers or logical values.
Error in Midpoint_ODE (line 11)**
I checked it a couple of times, and can't get what's wrong and if I missed some logical piece.
You do not need to keep the half-step value. Thus the easiest is to not have in in the list of values
for n = 1 : numSteps
yhalfstep = (y(n,:) + (h * 0.5)*(transpose(feval( f, x(n), y(n,:)))));
y(n+1,:) = y(n,:) + h * transpose(feval( x(n)+ (h/2), yhalfstep));
end
Also remember that in matlab and similar, a single-index access to a multi-dimensional array gives back the element of the flattened array (column first). That is, in a=[ 1,2;3,4;5,6] you get from a(3) the number 5 as the 3rd element in the first column, while a(3,:) gives the 3rd row [5,6].
I am trying to reduce number of iterations required to calculate multiplication using the CORDIC algorithm because I am using this algorithm in a continuous function to calculate square function. Here is the algorithm assuming -1<x<1'
function z=square(x)
y=x;
z=0;
for i=1:15
if (x > 0)
x = x - 2^(-i);
z = z + y*2^(-i);
else
x = x + 2^(-i);
z = z - y*2^(-i);
end
end
return
end
I already know the close value to multiplication result (from the previous result (call it pr)) and value of x (the value of x is continuous) . Does it help in anyway to decrease number of iterations?
If you are multiplying twice by the same constant, say a.x and a.x', then you can multiply and add with the delta a.(x' - x), which has less significant digits.
In case both factors vary, you can still use
x'.y' = (x'- x).(y' - y) + x.(y' - y) + (x' - x).y + x.y
where maybe the first term is neglectible.
For a square,
x'² = (x'- x)² + 2.x.(x' - x) + x²
I have a mathematical function E which I want to minimize. I get from solving this 16 possible solutions x1, x2, ..., x16, only two of which that actually minimize the function (located at a minimum). Using a for loop, I can then plug all of these 16 solutions into the original function, and select the solutions I need by applying some criteria via if statements (plotting E vs E(x) if x is real and positive, if first derivative of E is below a threshold, and if the second derivative of E is positive).
That way I only plot the solutions I'm interested in. However, I would now like to extract the relevant x that I plot. Here's a sample MATLAB code that plots the way I just described. I want to extract the thetas that I actually end up plotting. How to do that?
format long
theta_s = 0.77944100;
sigma = 0.50659500;
Delta = 0.52687700;
%% Defining the coefficients of the 4th degree polynomial
alpha = cos(2*theta_s);
beta = sin(2*theta_s);
gamma = 2*Delta^2/sigma^2;
a = -gamma^2 - beta^2*Delta^2 - alpha^2*Delta^2 + 2*alpha*Delta*gamma;
b = 2*alpha*gamma - 2*Delta*gamma - 2*alpha^2*Delta + 2*alpha*Delta^2 -...
2*beta^2*Delta;
c = 2*gamma^2 - 2*alpha*Delta*gamma - 2*gamma - alpha^2 + 4*alpha*Delta +...
beta^2*Delta^2 - beta^2 - Delta^2;
d = -2*alpha*gamma + 2*Delta*gamma + 2*alpha + 2*beta^2*Delta - 2*Delta;
e = beta^2 - gamma^2 + 2*gamma - 1;
%% Solve the polynomial numerically.
P = [a b c d e];
R = roots(P);
%% Solve r = cos(2x) for x: x = n*pi +- 1/2 * acos(r). Using n = 0 and 1.
theta = [1/2.*acos(R) -1/2.*acos(R) pi+1/2.*acos(R) pi-1/2.*acos(R)];
figure;
hold on;
x = 0:1/1000:2*pi;
y_1 = sigma*cos(x - theta_s) + sqrt(1 + Delta*cos(2*x));
y_2 = sigma*cos(x - theta_s) - sqrt(1 + Delta*cos(2*x));
plot(x,y_1,'black');
plot(x,y_2,'black');
grid on;
%% Plot theta if real, if positive, if 1st derivative is ~zero, and if 2nd derivative is positive
for j=1:numel(theta);
A = isreal(theta(j));
x_j = theta(j);
y_j = sigma*cos(x_j - theta_s) + sqrt(1 + Delta*cos(2*x_j));
FirstDer = sigma* sin(theta(j) - theta_s) + Delta*sin(2*theta(j))/...
sqrt(1 + Delta*cos(2*theta(j)));
SecDer = -sigma*cos(theta(j)-theta_s) - 2*Delta*cos(2*theta(j))/...
(1 + Delta*cos(2*theta(j)))^(1/2) - Delta^2 * (sin(2*theta(j)))^2/...
(1 + Delta*cos(2*theta(j)))^(3/2);
if A == 1 && x_j>=0 && FirstDer < 1E-7 && SecDer > 0
plot(x_j,y_j,['o','blue'])
end
end
After you finish all plotting, get the axes handle:
ax = gca;
then write:
X = get(ax.Children,{'XData'});
And X will be cell array of all the x-axis values from all lines in the graph. One cell for each line.
For the code above:
X =
[1.961054062875753]
[4.514533853417446]
[1x6284 double]
[1x6284 double]
(First, the code all worked. Thanks for the effort there.)
There are options here. A are couple below
Record the values as you generate them
Within the "success" if statement, simply record the values. See edits to your code below.
This would always be the preferred option for me, it just seems much more efficient.
xyResults = zeros(0,2); %%% INITIALIZE HERE
for j=1:numel(theta);
A = isreal(theta(j));
x_j = theta(j);
y_j = sigma*cos(x_j - theta_s) + sqrt(1 + Delta*cos(2*x_j));
FirstDer = sigma* sin(theta(j) - theta_s) + Delta*sin(2*theta(j))/...
sqrt(1 + Delta*cos(2*theta(j)));
SecDer = -sigma*cos(theta(j)-theta_s) - 2*Delta*cos(2*theta(j))/...
(1 + Delta*cos(2*theta(j)))^(1/2) - Delta^2 * (sin(2*theta(j)))^2/...
(1 + Delta*cos(2*theta(j)))^(3/2);
if A == 1 && x_j>=0 && FirstDer < 1E-7 && SecDer > 0
xyResults(end+1,:) = [x_j y_j]; %%%% RECORD HERE
plot(x_j,y_j,['o','blue'])
end
end
Get the result from the graphics objects
You can get the data you want from the actual graphics objects. This would be the option if there was just no way to capture the data as it was generated.
%First find the objects witht the data you want
% (Ideally you could record handles to the lines as you generated
% them above. But then you could also simply record the answer, so
% let's assume that direct record is not possible.)
% (BTW, 'findobj' is an underused, powerful function.)
h = findobj(0,'Marker','o','Color','b','type','line')
%Then get the `xdata` filed from each
capturedXdata = get(h,'XData');
capturedXdata =
2×1 cell array
[1.96105406287575]
[4.51453385341745]
%Then get the `ydata` filed from each
capturedYdata = get(h,'YData');
capturedYdata =
2×1 cell array
[1.96105406287575]
[4.51453385341745]
I have a question regarding Matlab's option to publish in PDF. Say I have the following code:
%1D functions and plotting
%1. We calculate y given the following function: y(x) = 2x^2 +
%3x + 1, for x = 10.
x = 10;
y = 2*x.^2 + 3*x + 1
%2. We calculate y given the following function: y(x) = ax^2 + bx + c, with a
%=2, b=3, c=0 and x = 100.
a=2;
b=3;
c=0;
x=100;
y = a*x.^2 + b*x + c
. . . more code follows here
When I choose to publish this as PDF the answers to problems 1 and 2 (where I calculate two different values for the variable 'y') do not appear at the line where I calculate the value (where I write y = 2*x.^2 + 3*x + 1 for instance). Instead, the values of the 'y' variables appear at the end of the document where it says 'y = 231' and 'y = 20300'. Is there any way I can get this to be included right after I define the variable without separating the document into cells? Or is this a default thing that I can not do anything about? I would really appreciate any input!
The general approach (indipendent of the output format) is to restart the paragraph with line break and %%:
%% 1. We calculate y given the following function: y(x) = 2x^2 +
% 3x + 1, for x = 10.
x = 10;
y = 2*x.^2 + 3*x + 1
%% 2. We calculate y given the following function: y(x) = ax^2 + bx + c, with a
% =2, b=3, c=0 and x = 100.
a=2;
b=3;
c=0;
x=100;
y = a*x.^2 + b*x + c
I'm very new to matlab so sorry if this is a dumb question. I have to following matrices:
im = imread('image.jpg'); %<370x366 double>
[y,x] = find(im); %x & y both <1280x1 double>
theta; %<370x366 double> computed from gradient of image
I can currently plot points one at a time like this:
plot(x(502) + 120*cos(theta(y(502),x(502))),y(502) + 120*sin(theta(y(502),x(502))));
But what I want to do is some how increment an accumulator array, I want to increment the location of acc by 1 for every time value for that location is found.
So if x(502) + 120*cos(theta(y(502),x(502))),y(502) + 120*sin(theta(y(502),x(502)) = (10,10) then acc(10,10) should be incremented by 1. I'm working with a very large data set so I want to avoid for-loops and use something like this:
acc = zeros(size(im));
%increment value when point lands in that location
acc(y,x) = acc(x + 120*cos(theta(y,x)),y + 120*sin(theta(y,x)),'*b')) + 1;
It would be nice if the 120 could actually be another matrix containing different radius values as well.
Do
i = find(im);
instead of
[y,x] = find(im)
wthis will give you linear indice of non zero values
Also, create a meshgrid
[x,y] = meshgrid(1:366,1:370)
Now you can index both coordinated and values linearly, for example
x(520) is 520-th point x coordinate
im(520) is 520-th point gray value
theta(520) is 520-th gradient value
So, now you can just plot it:
plot(x(i) + 120*cos(theta(i)),y(i) + 120*sin(theta(i)),'b*');
x(i) means a column of i-th values
x(i) + 120*cos(theta(i)) means a column of results
ACCUMULATING
I think in this case it is ok to loop for accumulating:
acc=zeros(size(im));
for ii=1:length(i)
xx=round(x(ii) + 120*cos(theta(ii)));
yy=round(y(ii) + 120*sin(theta(ii)));
acc(xx,yy)=acc(xx,yy)+1;
end;
The factor (120 in the example) can be matrix of size of im or scalar. The .* will do it.
im = imread('image.jpg');
[y, x] = meshgrid(1 : size(im, 1), 1 : size(im, 2));
factor = 120 * ones(size(im));
theta = gradient(double(image)); % just for example
acc = zeros(size(im));
increment = ((x + factor .* cos(theta)) == 10) & ((y + factor .* sin(theta)) == 10);
acc = acc + increment;
But the comparison to 10 will rarely be true, so you need to allow some range. For example (9,11).
e = 1;
increment = abs((x + factor .* cos(theta)) - 10) < e & abs((y + factor .* sin(theta)) - 10) < e;