Matlab: Fsolve giving incorrect roots - matlab

I'm trying to solve this system:
x = a + e(c - e*x/((x^2+y^2)^(3/2)))
y = b + c(d - e*y/((x^2+y^2)^(3/2)))
I'm using fsolve, but not matter what I put in as the starting points for the iteration, I get the answer that the starting points are the roots of the equation.
close all, clear all, clc
a = 1;
b = 2;
c = 3;
d = 4;
e = 5;
fsolve(#u1FsolveFUNC, [1,2])
Function:
function outvar = u1FsolveFUNC(invar)
global a b c d e
outvar = [...
-invar(1) + a + e*(c - e*(invar(1) / ((invar(1)^2 + invar(2)^2)^(3/2)))) ;
-invar(2) + b + e*(d - e*(invar(2) / ((invar(1)^2 + invar(2)^2)^(3/2))))]
end
I could try with [1,2] as invariables, and it will say that that is a root to the equation, alltough the correct answer for [1,2] is [12.76,15.52]
Ideas?

If you write your script like this
a = 1;
b = 2;
c = 3;
d = 4;
e = 5;
f = #(XY) [...
-XY(1) + a + e*(c - e*(XY(1) ./ (XY(1).^2 + XY(2).^2).^(3/2)))
-XY(2) + b + e*(d - e*(XY(2) ./ (XY(1).^2 + XY(2).^2).^(3/2)))];
fsolve(f, [1,2])
it is a lot clearer and cleaner. Moreover, it works :)
It works because you haven't declared a,b,c,d and e to be global before you assigned values to them. You then try to import them in your function, but at that time, they are still not defined as being global, so MATLAB thinks you just initialized a bunch of globals, setting their initial values to empty ([]).
And the solution to an empty equation is the initial value (I immediately admit, this is a bit counter-intuitive).
So this equation involves some inverse-square law...Gravity? Electrodynamics?
Note that, depending on the values of a-e, there may be multiple solutions; see this figure:
Solutions are those points [X,Y] where Z is simultaneously zero for both equations. for the values you give, there is a point like that at
[X,Y] = [15.958213798693690 13.978039302961506]
but also at
[X,Y] = [0.553696225634946 0.789264790080377]
(there's possibly even more...)

When you are using global command you have to use the command with all the variables in each function (and main workspace).
eg.
Main script
global a b c d e % Note
a = 1; b = 2; c = 3; d = 4; e = 5;
fsolve(#u1FsolveFUNC,[1,2])
Function
function outvar = u1FsolveFUNC(invar)
global a b c d e % Note
outvar = [-invar(1) + a + e*(c - e*(invar(1) / ((invar(1)^2 + invar(2)^2)^(3/2)))) ; -invar(2) + b + e*(d - e*(invar(2) / ((invar(1)^2 + invar(2)^2)^(3/2))))]

Related

How to Compute f(x) for a=1 and various values of the parameter b on the interval 0<x<3

I tried using below codes with no luck
f = 0;
a = 1;
b = [1 2 3.5];
for x = 0:3
f = (a * b * x).^(b-1)*exp(-a*x.^b);
end
disp (f);
Assuming the domain is x and the comparison parameter is b we can loop through the values of b to create three distinct vectors for which the function, f is plotted for. Here the value of b is swapped on each iteration of the for-loop. The resultant end up being f with 3 rows by 4 columns where the columns correspond to the x-values/domain and the rows correspond to the value of parameter, b.
x = (0:3);
a = 1;
B = [1 2 3.5];
for Parameter_Index = 1: length(B)
b = B(Parameter_Index);
f(Parameter_Index,:) = (a.*b.*x).^(b-1).*exp(-a.*x.^b);
end
plot(x,f(1,:),x,f(2,:),x,f(3,:));
xlabel("x"); ylabel("f(x)");
legend("B = " + num2str(B(1)),"B = " + num2str(B(2)),"B = " + num2str(B(3)));
Ran using MATLAB R2019b

Trying to get a MATLAB function to take an array of inputs

I'm trying to call a numerical integration function (namely one that uses the trapazoidal method) to compute a definite integral. However, I want to pass more than one value of 'n' to the following function,
function I = traprule(f, a, b, n)
if ~isa(f, 'function_handle')
error('Your first argument was not a function handle')
end
h = (b-a)./ n;
x = a:h:b;
S = 0;
for j = 2:n
S = S + f(x(j));
end
I = (h/2)*(f(a) + 2*S + f(b)); %computes indefinite integral
end
I'm using; f = #(x) 1/x, a = 1 and b = 2. I'm trying to pass n = 10.^(1:10) too, however, I get the following output for I when I do so,
I =
Columns 1 through 3
0.693771403175428 0.069377140317543 0.006937714031754
Columns 4 through 6
0.000693771403175 0.000069377140318 0.000006937714032
Columns 7 through 9
0.000000693771403 0.000000069377140 0.000000006937714
Column 10
0.000000000693771
Any ideas on how to get the function to take n = 10.^(1:10) so I get an output something like,
I = 0.693771403175428, 0.693153430481824, 0.693147243059937 ... and so on for increasing powers of 10?
In the script where you are calling this from, simply iterate over n
k = 3;
f = #(x)1./x;
a = 1; b = 2;
I = zeros(k,1);
for n = 1:k
I(n) = traprule(f, a, b, 10^n);
end
% output: I = 0.693771403175428
% 0.693153430481824
% 0.693147243059937
Then I will contain all of the outputs. Alternatively you can adapt your function to use the same logic to loop over the elements of n if it is passed
as a vector.
Note, you can improve the efficiency of your traprule code by removing the for loop:
% This loop operates on every element of x individually, and is inefficient
S = 0;
for j = 2:n
S = S + f(x(j));
end
% If you ensure you use element-wise equations like f=#(x)1./x instead of f=#(x)1/x
% Then you can use this alternative:
S = sum(f(x(2:n)));

Not enough input arguments error in matlab

This is my matlab code , I got Not enough input argument error in line 2 and i don't know how to fix it. Anyhelp ? Thanks in advance .
function [] = Integr1( F,a,b )
i = ((b - a)/500);
x = a;k = 0; n = 0;
while x <= b
F1 = F(x);
x = x + i;
F2 = F(x);
m = ((F1+F2)*i)/2;
k = k +m;
end
k
x = a; e = 0; o = 0;
while x <= (b - 2*i)
x = x + i;
e = e + F(x);
x = x + i;
o = o + F(x);
end
n = (i/3)*(F(a) + F(b) + 2*o + 4*e)
This code performs integration by the trapezoidal rule. The last line of code gave it away. Please do not just push the Play button in your MATLAB editor. Don't even think about it, and ignore that it's there. Instead, go into your Command Prompt, and you need to define the inputs that go into this function. These inputs are:
F: A function you want to integrate:
a: The starting x point
b: The ending x point
BTW, your function will not do anything once you run it. You probably want to return the integral result, and so you need to modify the first line of your code to this:
function n = Integr1( F,a,b )
The last line of code assigns n to be the area under the curve, and that's what you want to return.
Now, let's define your parameters. A simple example for F is a linear function... something like:
F = #(x) 2*x + 3;
This defines a function y = 2*x + 3. Next define the starting and ending points:
a = 1; b = 4;
I made them 1 and 4 respectively. Now you can call the code:
out = Integr1(F, a, b);
out should contain the integral of y = 2*x + 3 from x = 1 to x = 4.

Manually changing RGB to HSI matlab

I would like to preface this by saying, I know some functions, including RGB2HSI could do this for me, but I would like to do it manually for a deeper understanding.
So my goal here is to change my RGB image to HSI color scheme. The image is in .raw format, and i am using the following formulas on the binary code to try and convert it.
theta = arccos((.5*(R-G) + (R-B))/((R-G).^2 + (R-B).*(G-B)).^.5);
S = 1 - 3./(R + G + B)
I = 1/3 * (R + G + B)
if B <= G H = theta if B > G H = 360 - theta
So far I have tried two different things, that have resulted in two different errors. The first attempted was the following,
for iii = 1:196608
C(iii) = acosd((.5*(R-G) + (R-B))/((R-G).^2 + (R-B).*(G-B)).^.5);
S(iii) = 1 - 3./(R + G + B);
I(iii) = 1/3 * (R + G + B);
end
Now in attempting this I knew it was grossly inefficent, but I wanted to see if it was a viable option. It was not, and the computer ran out of memory and refused to even run it.
My second attempt was this
fid = fopen('color.raw');
R = fread(fid,512*384*3,'uint8', 2);
fseek(fid, 1, 'bof');
G = fread(fid, 512*384*3, 'uint8', 2);
fseek(fid, 2, 'bof');
B = fread(fid, 512*384*3, 'uint8', 2);
fclose(fid);
R = reshape(R, [512 384]);
G = reshape(G, [512 384]);
B = reshape(B, [512 384]);
C = acosd((.5*(R-G) + (R-B))/((R-G).^2 + (R-B).*(G-B)).^.5);
S = 1 - 3./(R + G + B);
I = 1/3 * (R + G + B);
if B <= G
H = B;
if B > G
H = 360 - B;
end
end
H = H/360;
figure(1);
imagesc(H * S * I)
There were several issues with this that I need help with. First of all, the matrix 'C' has different dimensions than S and I so multiplication is impossible, so my first question is, how would I call up each pixel so I could perform the operations on them individually to avoid this dilemma.
Secondly the if loops refused to work, if I put them after "imagesc" nothing would happen, and if i put them before "imagesc" then the computer would not recognize what variable H was. Where is the correct placement of the ends?
Normally, the matrix 'C' have same dimensions as S and I because:
C = acosd((.5*(R-G) + (R-B))/((R-G).^2 + (R-B).*(G-B)).^.5);
should be
C = acosd((.5*(R-G) + (R-B))./((R-G).^2 + (R-B).*(G-B)).^.5);
elementwise division in the middle was missing . Another point is:
if B <= G
H = B;
if B > G
H = 360 - B;
end
end
should be
H = zeros(size(B));
H(find(B <= G)) = B(find(B <= G));
H(find(B > G)) = 360 - B(find(B > G));

Matlab: Polynomial Expansion Routine

In Mathematica, it's easy to expand terms like
(ax^2+bx+c)^n
But is there anyway I can do this in Matlab?
For any arbitrary expression: not without the Symbolic Toolbox.
http://www.mathworks.com/help/toolbox/symbolic/expand.html
However, if you wish to expand polynomials, you can use the conv function. Just run it in a loop.
a = 1;
b = 2;
c = 3;
n = 5;
soln = [a b c];
for i=1:n-1
soln = conv(soln,[a b c]);
end
You can also use my sympoly toolbox.
>> sympoly a b c x
>> (a*x^2+b*x+c)^3
ans =
c^3 + 3*b*c^2*x + 3*b^2*c*x^2 + b^3*x^3 + 3*a*c^2*x^2 + 6*a*b*c*x^3 + 3*a*b^2*x^4 + 3*a^2*c*x^4 + 3*a^2*b*x^5 + a^3*x^6