Finding minimizers numerically in Matlab with 'fsolve' - matlab

I'm completely new to Matlab and I've been having some problems with my code.
I need to use 'fsolve' to locate minimizers to a nonlinear optimization problem, but I can't get it to work.
I've been using the 'Solution Process of Nonlinear System' part from mathworks.
My code is the following:
function F = myfun(x)
F = [4*x(4) + 2*x(1) - x(3)*(2*x(1) + 4) + 4*x(1)*(x(1).^2 + x(2) - 11) + 2*x(2).^2 - 14;
x(3) - 10*x(4) + 2*x(2) + 4*x(2)*(x(2).^2 + x(1) - 7) + 2*x(1).^2 - 22;
x(2) - (x(1) + 2).^2;
4*x(1) - 10*x(2);];
x0 = [-5;-5];
options = optimoptions('fsolve','Display','iter');
[x,fval] = fsolve(#myfun,x0,options);
end
Where it says that; the value assigned to x appears to be unused as well as; not enough input arguments. But accoring to the mathworks page, I've done the exact same thing as them, so I'm sort of lost now.

There are several things that you are not doing correctly:
The function myfun must only contain equations (as mentioned in Florian's comment).
fsolve, x0 and options must be called from a separate script or from the Command Window.
The initial point array x0 must have at least as many elements as variables (x(4), x(3), x(2), x(1)) present in the equations in myfun.
Edit your function myfun, make sure that it only contains equations and save it in your working directory.
function F = myfun(x)
F = [4*x(4) + 2*x(1) - x(3)*(2*x(1) + 4) + 4*x(1)*(x(1)^2 + x(2) - 11) + 2*x(2)^2 - 14;
x(3) - 10*x(4) + 2*x(2) + 4*x(2)*(x(2)^2 + x(1) - 7) + 2*x(1)^2 - 22;
x(2) - (x(1) + 2)^2;
4*x(1) - 10*x(2)];
end
Note that you don't need to use the element-wise power operator .^. Using the ^ operator will be enough to define powers in your equations.
Now in the Command Window enter the following instructions:
x0 = [-5;-5;-5;-5];
options = optimoptions('fsolve','Display','iter');
[x,fval] = fsolve(#myfun,x0,options);
Note that I modified x0 to have at least 4 elements in order to match the number of equations that you defined in myfun. These are just sample values, so you should modify x0 with the values of your problem.
This is a fragment of the output:
Norm of First-order Trust-region
Iteration Func-count f(x) step optimality radius
0 5 81521 4.27e+04 1
1 10 12608.5 1 1.15e+04 1
2 15 966.243 2.5 1.71e+03 2.5
3 20 408.322 6.25 685 6.25
4 21 408.322 15.625 685 15.6
5 26 263.815 3.90625 244 3.91
6 27 263.815 9.76563 244 9.77
7 32 205.88 2.44141 272 2.44
8 37 138.11 6.10352 206 6.1
9 42 93.4561 6.10352 105 6.1
10 47 64.0129 6.10352 42.3 6.1
...

Related

How do you factor over a Z field?

I have to factorize a polynomial e.g.
over the field of Z5 using Matlab or Mupad.
And i tried everything read a lot of Matlab and Mupad documentation and still can't find it, so i am guessing it is the math i don't know that's going to help me factor it.
Don't kill a mosquito with a cannon!
You only need to find a root between 0, 1, 2, -2, -1.
Also, given that x5 = x, the problem reduces to finding x such that
2x + 2x^4 + x^3 + 2x^2 - 3 = 0
and since x ≠ 0, x^4 = 1 hence
2x + x^3 + 2x^2 - 1 = 0
Well, let's try!
1: 2 + 1 + 2 - 1 -> -1
2: -1 + 3 - 2 - 1 -> -1
-2: 1 - 3 + 3 - 1 -> 0 -> root!
Then the polynomial is divisible by (x - 3), and you can repeat the procedure with the quotient until there are no roots left.
Addendum
After dividing by (x - 3) we get
x4 + x2 + 1
which we can expressed as
(x2 + 1)2 - x2
or
((x2 + 1) - x)((x2 + 1) + x)
To find the factors of degree 2 programmatically, just try with x2 + ax + b for a and b between 0 and 4.
I found a mupad command to do what i needed.
Still thanks for exaplaining the math behind it.

The roots of the characteristic polynomial and the eigenvalues are not the same

This is matrix B
B = [1 2 0 ; 2 4 6 ; 0 6 5]
The result of eig(B) is:
{-2.2240, 1.5109, 10.7131}
and the characteristic polynomial of B by this link is
syms x
polyB = charpoly(B,x)
x^3 - 10*x^2 - 11*x + 36
but the answer of solve(polyB) is
133/(9*(3^(1/2)*5492^(1/2)*(i/3) + 1009/27)^(1/3)) + ((3^(1/2)*5492^(1/2)*i)/3 + 1009/27)^(1/3) + 10/3
(3^(1/2)*(133/(9*(3^(1/2)*5492^(1/2)*(i/3) + 1009/27)^(1/3)) - ((3^(1/2)*5492^(1/2)*i)/3 + 1009/27)^(1/3))*i)/2 - 133/(18*(3^(1/2)*5492^(1/2)*(i/3) + 1009/27)^(1/3)) - ((3^(1/2)*5492^(1/2)*i)/3 + 1009/27)^(1/3)/2 + 10/3
10/3 - 133/(18*(3^(1/2)*5492^(1/2)*(i/3) + 1009/27)^(1/3)) - ((3^(1/2)*5492^(1/2)*i)/3 + 1009/27)^(1/3)/2 - (3^(1/2)*(133/(9*(3^(1/2)*5492^(1/2)*(i/3) + 1009/27)^(1/3)) - ((3^(1/2)*5492^(1/2)*i)/3 + 1009/27)^(1/3))*i)/2
which I don't know what it is while I expect it to be the eigenvalues of B. What is the problem?
I do not understand why you add x and symbolic maths, they are not required for your task.
B = [1 2 0 ; 2 4 6 ; 0 6 5]
cp=charpoly(B)
eig2=roots(cp)
returns:
eig2 =
10.7131
-2.2240
1.5109
However, if for some reason you insist in using symbolic (which you should not for a numerical task), you can do
double(solve(polyB))
ans =
10.7131 + 0.0000i
-2.2240 - 0.0000i
1.5109 - 0.0000i
(note imaginary parts is zero)
Since I do not have MATLAB in this machine, I will use SymPy instead:
>>> from sympy import *
>>> B = Matrix([[1, 2, 0],
[2, 4, 6],
[0, 6, 5]])
Computing the characteristic polynomial and its roots:
>>> s = Symbol('s')
>>> p = (s*eye(3) - B).det()
>>> p
s**3 - 10*s**2 - 11*s + 36
>>> roots = solve(p,s)
Computing floating-point approximations of the three roots:
>>> [ r.evalf() for r in roots ]
[1.51092975992931 - 0.e-22*I, -2.22404024437578 + 0.e-22*I, 10.7131104844465 - 0.e-20*I]
Since B is symmetric, its eigenvalues must be real. Note that the imaginary parts of the floating-point approximations of the roots are indeed equal to zero.
Printing in LaTeX, the exact values of the roots are:
Note that some roots are "longer" than others, i.e., they require more symbols. However, they are exact. Using floating-point arithmetic, all roots have the same "size", but they are approximations.

Assigning curve fitting polynomial value to a vector

I am trying to get a vector of different torque values with respect to speed of an electric motor. To do that I used some torque values at certain speeds and tried to fit a curve to them.
tpdata=[0 10 20 30 40 50 60 65 70 75 80 85 90 93.3 95.8 98 99 100];
pdata=[3.3 3.05 2.81 2.79 2.80 2.88 3.02 3.12 3.20 3.28 3.13 2.75 2.10 1.5 1 0.5 0.25 0];
I modified it according to my need
u=2880/690
ydata=pdata*3.65*u
tsdata=tpdata*30/u
I used the curve fitting tool to get the constants.
p1 = -2.4592e-20
p2 = 1.51e-16
p3 = -2.7946e-13
p4 = 2.3662e-10
p5 = -1.0391e-07
p6 = 2.3887e-05
p7 = -0.0024883
p8 = 0.035497
p9 = 50.272
I want to assign the solution of the fitted polynomial (from 1 rpm to 720 rpm) to a vector that I named as y (torque values)
I can get the solution plot but I cannot see them or assign them as a vector.
for i=1:720
y = p1*i^8 + p2*i^7 + p3*i^6 + p4*i^5 + p5*i^4 + p6*i^3 + p7*i^2 + p8*i + p9;
plot(i,y,'d');
hold on
grid on
end
When I add y=zeros(1,720) and change y to y(1,i) the script fails.
What is the reason of this?
You are saving the solution each time in y that is being overwritten in the next loop. You should probably do like this:
for i=1:720
y(i) = p1*i^8 + p2*i^7 + p3*i^6 + p4*i^5 + p5*i^4 + p6*i^3 + p7*i^2 + p8*i + p9;
end
plot(y,'d');
hold on
grid on
Now you get a vector y(1x720). You dont need to do y=zeros(1,720)...

Numerical solutions of a nonlinear equation with different independent values in matlab

For example, if I have this function: g = t^3 - 5*t^2 + 2
And g = [3 4 6 2 9 10 17 1]
I would like to solve the equation for each g[i] and obtain the resulting t vector.
This might guide you:
>> syms t g %// define symbolic variables
>> y = t^3 - 5*t^2 + 2 - g; %// define y so that equation is: y=0
>> g_data = [3 4 6 2 9 10 17 1]; %// define g values
>> n = 1; %// choose first value. Or use a loop: for n = 1:numel(g_data)
>> s = solve(subs(y, g, g_data(n))) %// substitute g value and solve equation y=0
s =
25/(9*((108^(1/2)*527^(1/2))/108 + 277/54)^(1/3)) + ((108^(1/2)*527^(1/2))/108 + 277/54)^(1/3) + 5/3
5/3 - ((108^(1/2)*527^(1/2))/108 + 277/54)^(1/3)/2 - 25/(18*((108^(1/2)*527^(1/2))/108 + 277/54)^(1/3)) - (3^(1/2)*(25/(9*((108^(1/2)*527^(1/2))/108 + 277/54)^(1/3)) - ((108^(1/2)*527^(1/2))/108 + 277/54)^(1/3))*i)/2
5/3 - ((108^(1/2)*527^(1/2))/108 + 277/54)^(1/3)/2 - 25/(18*((108^(1/2)*527^(1/2))/108 + 277/54)^(1/3)) + (3^(1/2)*(25/(9*((108^(1/2)*527^(1/2))/108 + 277/54)^(1/3)) - ((108^(1/2)*527^(1/2))/108 + 277/54)^(1/3))*i)/2
>> double(s) %// show solutions as floating point values
ans =
5.039377328113847
-0.019688664056924 + 0.445027607060817i
-0.019688664056924 - 0.445027607060817i

Have a trouble with the function roots

Hey guys I have multiple problems with using function 'roots'.
I Have to find zeros of 's^1000 + 1'.
I made Y = zeros(1,1000) then manually changed the 1000th matrice to '1'. but then 'root' function does not work with it !
Another problem is that I am having trouble with matrix multiplication. The question is finding zeros(roots) of (s^6 + 6*s^5 + 15*s^4 + 20*s^3 + 15*s^2 + 6*s +1)*(s^6 + 6s^5 + 15*s^4 +15*s^2 +6*s +1) so i did:
a = [1 6 15 20 15 6 1]
b = [1 6 15 0 15 6 1]
y = a.*b;
roots(y)
but this gives me
-27.9355 + 0.0000i
-8.2158 + 0.0000i
0.1544 + 0.9880i
0.1544 - 0.9880i
-0.1217 + 0.0000i
-0.0358 + 0.0000i
where I calculate the original equation with wolfram then I have made matrix as :
p = [1 12 66 200 375 492 524 492 375 200 66 12 1]
roots(p)
and this gives me :
-3.1629 + 2.5046i
-3.1629 - 2.5046i
0.3572 + 0.9340i
0.3572 - 0.9340i
-1.0051 + 0.0000i
-1.0025 + 0.0044i
-1.0025 - 0.0044i
-0.9975 + 0.0044i
-0.9975 - 0.0044i
-0.9949 + 0.0000i
-0.1943 + 0.1539i
-0.1943 - 0.1539i
and I think the second solution is right (that is what wolfram alpha gave me)
How would you answer these two questions through matlab guys?
To multiply polynomials, you convolve their coefficients:
>> roots(conv(a,b))
ans =
-3.1629 + 2.5046i
-3.1629 - 2.5046i
0.3572 + 0.9340i
0.3572 - 0.9340i
-1.0051
-1.0025 + 0.0044i
-1.0025 - 0.0044i
-0.9974 + 0.0044i
-0.9974 - 0.0044i
-0.9950
-0.1943 + 0.1539i
-0.1943 - 0.1539i
Q1
Using roots to find the roots of s1000 + 1 is a bit of an overkill. The solution is given by this code snippet (corrected the first version; may be deduced using De Moivre's formula):
n = 1000;
k = 0:n-1
u = (2*k + 1)*pi / n;
s = cos(u) + 1i*sin(u)
Also, this method is approx. 100000 times faster.
Q2
Multiplying two polynomials to find the roots of their product is a bit of an overkill. :-) The union of the two polynomials' root sets is the root set of the product polynomial:
s = [roots(a);roots(b)]
Also, this method is more accurate.
1) The vector describing s^1000 + 1 should end with a 1 as well.
2)
a = [1 6 15 20 15 6 1]
b = [1 6 15 0 15 6 1]
y = a.*b;
This is a DOT product, multiplication of polynomials do not multiply element-wise.
Question 1
You need to include the coefficient of x^0 in the vector of coefficients, so there are 1001 entries with the first and last being 1
coeffs=zeros(1001,1);
coeffs([1,1001])=1;
roots(coeffs)
Question 2
To multiply the coefficients of polynomials you need to use convolution:
roots(conv(a,b))