I am trying to implement the fmincon function in MATLAB. I am getting a warning with an algorithm change to evaluate my function (warning shown at the end of post). I wanted to use fminsearch, but I have 2 constraints I need to follow. It doesn't make sense for MATLAB to change algorithms to evaluate my function because my constraints are very simple. I have provided the constraint and piece of code:
Constraints:
theta(0) + theta(1) < 1
theta(0), theta(1), theta(2), theta(3) > 0
% Solve MLE using fmincon
ret_1000 = returns(1:1000);
A = [1 1 0 0];
b = [.99999];
lb = [0; 0; 0; 0];
ub = [1; 1; 1; 1];
Aeq = [];
beq = [];
noncoln = [];
init_guess = [.2;.5; long_term_sigma; initial_sigma];
%option = optimset('FunValCheck', 1000);
options = optimset('fmincon');
options = optimset(options, 'MaxFunEvals', 10000);
[x, maxim] = fmincon(#(theta)Log_likeli(theta, ret_1000), init_guess, A, b, Aeq, beq, lb, ub, noncoln, options);
Warning:
Warning: The default trust-region-reflective algorithm does not solve problems with the constraints you
have specified. FMINCON will use the active-set algorithm instead. For information on applicable
algorithms, see Choosing the Algorithm in the documentation.
> In fmincon at 486
In GARCH_loglikeli at 30
Local minimum possible. Constraints satisfied.
fmincon stopped because the predicted change in the objective function
is less than the selected value of the function tolerance and constraints
are satisfied to within the selected value of the constraint tolerance.
<stopping criteria details>
No active inequalities.
All matlab variables are double my default. You can force a double using, double(variableName), you can get the type of a variable using class(variableName). I would use the class on all your variables to make sure they are what you expect. I don't have fmincon, but I tried a variant of your code on fminsearch and it worked like a charm:
op = optimset('fminsearch');
op = optimset(op,'MaxFunEvals',1000,'MaxIter',1000);
a = sqrt(2);
banana = #(x)100*(x(2)-x(1)^2)^2+(a-x(1))^2;
[x,fval] = fminsearch(banana, [-1.2, 1],op)
Looking at the matlab documentation, I think your input variables are not correct:
x = fmincon(fun,x0,A,b,Aeq,beq,lb,ub,nonlcon,options)
I think you need:
% Let's be ultra specific to solve this syntax issue
fun = #(theta) Log_likeli(theta, ret_1000);
x0 = init_guess;
% A is defined as A
% b is defined as b
Aeq = [];
beq = [];
% lb is defined as lb
% ub is not defined, not sure if that's going to be an issue
% with the solver having lower, but not upper bounds probably isn't
% but thought it was worth a mention
ub = [];
nonlcon = [];
% options is defined as options
x = fmincon(fun,x0,A,b,Aeq,beq,lb,ub,nonlcon,options)
Related
How can multiple surfaces be plotted on the axes but surfaces uses a different colormap?.
Using colormap("...") changes it for the entire figure, not just a single surface.
Thanks
Do You mean on same axes?
I haven't found a function that does this directly. But it is possible to pass the desired colors in the surf function.
Way I found:
Convert the data to a 0-1 scale and then convert to the desired colormap.
Example with hot and jet colormaps:
tx = ty = linspace (-8, 8, 41)';
[xx, yy] = meshgrid (tx, ty);
r = sqrt (xx .^ 2 + yy .^ 2) + eps;
tz = sin (r) ./ r ;
function normalized = normalize_01(data)
data_min = min(min(data))
data_max = max(max(data))
normalized = (data - data_min)/(data_max - data_min)
endfunction
function rgb = data2rgb(data, color_bits, cmap)
grays = normalize_01(data)
indexes = gray2ind(grays, color_bits)
rgb = ind2rgb(indexes, cmap)
endfunction
color_bits = 128
cmap_1 = hot(color_bits)
rgb_1 = data2rgb(tz, color_bits, cmap_1)
surf(tx, ty, tz, rgb_1)
hold on
cmap_2 = jet(color_bits)
rgb_2 = data2rgb(tz+3, color_bits, cmap_2)
surf(tx, ty, tz+3, rgb_2)
But if you also need a colorbar, this way might not be useful. Unless you find a way to manually add two colorbar like I did with the cmap.
I am developing a finite element software that minimizes the energy of a mechanical structure. Using octave and its optim package, I run into a strange issue: The lm_feasible algorithm doesn't calculate at all when I use more than 300 degrees of freedom (DoF). Another algorithm (sqp) performs the calculation but doesn't work well when I complexify the structure and are out of my test case.
Is there a limit in the number of DoF with lm_feasible algorithm?
If so, how many DoF are maximally possible?
To give an overview and general idea of how the code works:
[x,y] = geometryGenerator()
U = zeros(lenght(x)*2,1);
U(1:2:end-1) = x;
U(2:2:end) = y;
%Non geometric argument are not optimised, and fixed during calculation
fct =#(U)complexFunctionOfEnergyIWrap(U(1:2:end-1),U(2:2:end), variousMaterialPropertiesAndOtherArgs)
para = optimset("f_equc_idx",contEq,"lb",lb,"ub",ub,"objf_grad",dEne,"objf_hessian",d2Ene,"MaxIter",1000);
[U,eneFinale,cvg,outp] = nonlin_min(fct,U,para)
Full example:
clear
pkg load optim
function [x,y] = geometryGenerator(r,elts = 100)
teta = linspace(0,pi,elts = 100);
x = r * cos(teta);
y = r * sin(teta);
endfunction
function ene = complexFunctionOfEnergyIWrap (x,y,E,P, X,Y)
ene = 0;
for i = 1:length(x)-1
ene += E*(x(i)/X(i))^4+ E*(y(i)/Y(i))^4- P *(x(i)^2+(x(i+1)^2)-x(i)*x(i+1))*abs(y(i)-y(i+1));
endfor
endfunction
[x,y] = geometryGenerator(5,100)
%Little distance from axis to avoid division by zero
x +=1e-6;
y +=1e-6;
%Saving initial geometry
X = x;
Y = y;
%Vectorisation of the function
%% Initial vector
U = zeros(length(x)*2,1);
U(1:2:end-1) = linspace(min(x),max(x),length(x));
U(2:2:end) = linspace(min(y),max(y),length(y));
%%Constraints
Aeq = zeros(3,length(U));
%%% Blocked bottom
Aeq(1,1) = 1;
Aeq(2,2) = 1;
%%% Sliding top
Aeq(3,end-1) = 1;
%%%Initial condition
beq = zeros(3,1);
beq(1) = U(1);
beq(2) = U(2);
beq(3) = U(end-1);
contEq = #(U) Aeq * U - beq;
%Parameter
Mat = 0.2e9;
pressure = 50;
%% Vectorized function. Non geometric argument are not optimised, and fixed during calculation
fct =#(U)complexFunctionOfEnergyIWrap(U(1:2:end-1),U(2:2:end), Mat, pressure, X, Y)
para = optimset("Algorithm","lm_feasible","f_equc_idx",contEq,"MaxIter",1000);
[U,eneFinale,cvg,outp] = nonlin_min(fct,U,para)
xFinal = U(1:2:end-1);
yFinal = U(2:2:end);
plot(x,y,';Initial geo;',xFinal,yFinal,'--x;Final geo;')
Finite Element Method is typically formulated as the optimal criteria for the minimization problem, which is equivalent to the Virtual Work Principle (see books like Hughes of Bathe). The Virtual Work, represents a set of linear (or nonlinear) equations which can be solved more efficiently (with fsolve).
If for some motive you must solve the problem as an optimization problem, then, if you are considering linear elasticity, your strain energy is quadratic, thus you could use the qp Octave function.
To use sparse matrices could also be helpful.
I want to traverse all the elements in the set Q = [0, 2^16) in a non sequential manner. To do so I need a function f(x) Q --> Q which gives the order in which the set will be sorted. for example:
f(0) = 2345
f(1) = 4364
f(2) = 24
(...)
To recover the order I would need the inverse function f'(x) Q --> Q which would output:
f(2345) = 0
f(4364) = 1
f(24) = 2
(...)
The function must be bijective, for each element of Q the function uniquely maps to another element of Q.
How can I generate such a function or are there any know functions that do this?
EDIT: In the following answer, f(x) is "what comes after x", not "what goes in position x". For example, if your first number is 5, then f(5) is the next element, not f(1). In retrospect, you probably thought of f(x) as "what goes in position x". The function defined in this answer is much weaker if used as "what goes in position x".
Linear congruential generators fit your needs.
A linear congruential generator is defined by the equation
f(x) = a*x+c (mod m)
for some constants a, c, and m. In this case, m = 65536.
An LCG has full period (the property you want) if the following properties hold:
c and m are relatively prime.
a-1 is divisible by all prime factors of m.
If m is a multiple of 4, a-1 is a multiple of 4.
We'll go with a = 5, c = 1.
To invert an LCG, we solve for f(x) in terms of x:
x = (a^-1)*(f(x) - c) (mod m)
We can find the inverse of 5 mod 65536 by the extended Euclidean algorithm, or since we just need this one computation, we can plug it into Wolfram Alpha. The result is 52429.
Thus, we have
f(x) = (5*x + 1) % 65536
f^-1(x) = (52429 * (x - 1)) % 65536
There's many approaches to solving this.
Since your set size is small, the requirement for generating the function and its inverse can simply be done via memory lookup. So once you choose your permutation, you can store the forward and reverse directions in lookup tables.
One approach to creating a permutation is mapping out all elements in an array and then randomly swapping them "enough" times. C code:
int f[PERM_SIZE], inv_f[PERM_SIZE];
int i;
// start out with identity permutation
for (i=0; i < PERM_SIZE; ++i) {
f[i] = i;
inv_f[i] = i;
}
// seed your random number generator
srand(SEED);
// look "enough" times, where we choose "enough" = size of array
for (i=0; i < PERM_SIZE; ++i) {
int j, k;
j = rand()%PERM_SIZE;
k = rand()%PERM_SIZE;
swap( &f[i], &f[j] );
}
// create inverse of f
for (i=0; i < PERM_SIZE; ++i)
inv_f[f[i]] = i;
Enjoy
I'm trying to compute the Fourier coefficients for a waveform using MATLAB. The coefficients can be computed using the following formulas:
T is chosen to be 1 which gives omega = 2pi.
However I'm having issues performing the integrals. The functions are are triangle wave (Which can be generated using sawtooth(t,0.5) if I'm not mistaking) as well as a square wave.
I've tried with the following code (For the triangle wave):
function [ a0,am,bm ] = test( numTerms )
b_m = zeros(1,numTerms);
w=2*pi;
for i = 1:numTerms
f1 = #(t) sawtooth(t,0.5).*cos(i*w*t);
f2 = #(t) sawtooth(t,0.5).*sin(i*w*t);
am(i) = 2*quad(f1,0,1);
bm(i) = 2*quad(f2,0,1);
end
end
However it's not getting anywhere near the values I need. The b_m coefficients are given for a
triangle wave and are supposed to be 1/m^2 and -1/m^2 when m is odd alternating beginning with the positive term.
The major issue for me is that I don't quite understand how integrals work in MATLAB and I'm not sure whether or not the approach I've chosen works.
Edit:
To clairify, this is the form that I'm looking to write the function on when the coefficients have been determined:
Here's an attempt using fft:
function [ a0,am,bm ] = test( numTerms )
T=2*pi;
w=1;
t = [0:0.1:2];
f = fft(sawtooth(t,0.5));
am = real(f);
bm = imag(f);
func = num2str(f(1));
for i = 1:numTerms
func = strcat(func,'+',num2str(am(i)),'*cos(',num2str(i*w),'*t)','+',num2str(bm(i)),'*sin(',num2str(i*w),'*t)');
end
y = inline(func);
plot(t,y(t));
end
Looks to me that your problem is what sawtooth returns the mathworks documentation says that:
sawtooth(t,width) generates a modified triangle wave where width, a scalar parameter between 0 and 1, determines the point between 0 and 2π at which the maximum occurs. The function increases from -1 to 1 on the interval 0 to 2πwidth, then decreases linearly from 1 to -1 on the interval 2πwidth to 2π. Thus a parameter of 0.5 specifies a standard triangle wave, symmetric about time instant π with peak-to-peak amplitude of 1. sawtooth(t,1) is equivalent to sawtooth(t).
So I'm guessing that's part of your problem.
After you responded I looked into it some more. Looks to me like it's the quad function; not very accurate! I recast the problem like this:
function [ a0,am,bm ] = sotest( t, numTerms )
bm = zeros(1,numTerms);
am = zeros(1,numTerms);
% 2L = 1
L = 0.5;
for ii = 1:numTerms
am(ii) = (1/L)*quadl(#(x) aCos(x,ii,L),0,2*L);
bm(ii) = (1/L)*quadl(#(x) aSin(x,ii,L),0,2*L);
end
ii = 0;
a0 = (1/L)*trapz( t, t.*cos((ii*pi*t)/L) );
% now let's test it
y = ones(size(t))*(a0/2);
for ii=1:numTerms
y = y + am(ii)*cos(ii*2*pi*t);
y = y + bm(ii)*sin(ii*2*pi*t);
end
figure; plot( t, y);
end
function a = aCos(t,n,L)
a = t.*cos((n*pi*t)/L);
end
function b = aSin(t,n,L)
b = t.*sin((n*pi*t)/L);
end
And then I called it like:
[ a0,am,bm ] = sotest( t, 100 );
and I got:
Sweetness!!!
All I really changed was from quad to quadl. I figured that out by using trapz which worked great until the time vector I was using didn't have enough resolution, which led me to believe it was a numerical issue rather than something fundamental. Hope this helps!
To troubleshoot your code I would plot the functions you are using and investigate, how the quad function samples them. You might be undersampling them, so make sure your minimum step size is smaller than the period of the function by at least factor 10.
I would suggest using the FFTs that are built-in to Matlab. Not only is the FFT the most efficient method to compute a spectrum (it is n*log(n) dependent on the length n of the array, whereas the integral in n^2 dependent), it will also give you automatically the frequency points that are supported by your (equally spaced) time data. If you compute the integral yourself (might be needed if datapoints are not equally spaced), you might calculate frequency data that are not resolved (closer spacing than 1/over the spacing in time, i.e. beyond the 'Fourier limit').
I am learning MatLab on my own, and I have this assignment in my book which I don't quite understand. Basically I am writing a function that will calculate sine through the use of Taylor series. My code is as follows so far:
function y = sine_series(x,n);
%SINE_SERIES: computes sin(x) from series expansion
% x may be entered as a vector to allow for multiple calculations simultaneously
if n <= 0
error('Input must be positive')
end
j = length(x);
k = [1:n];
y = ones(j,1);
for i = 1:j
y(i) = sum((-1).^(k-1).*(x(i).^(2*k -1))./(factorial(2*k-1)));
end
The book is now asking me to include an optional output err which will calculate the difference between sin(x) and y. The book hints that I may use nargout to accomplish this, but there are no examples in the book on how to use this, and reading the MatLab help on the subject did not make my any wiser.
If anyone can please help me understand this, I would really appreciate it!
The call to nargout checks for the number of output arguments a function is called with. Depending on the size of nargout you can assign entries to the output argument varargout. For your code this would look like:
function [y varargout]= sine_series(x,n);
%SINE_SERIES: computes sin(x) from series expansion
% x may be entered as a vector to allow for multiple calculations simultaneously
if n <= 0
error('Input must be positive')
end
j = length(x);
k = [1:n];
y = ones(j,1);
for i = 1:j
y(i) = sum((-1).^(k-1).*(x(i).^(2*k -1))./(factorial(2*k-1)));
end
if nargout ==2
varargout{1} = sin(x)'-y;
end
Compare the output of
[y] = sine_series(rand(1,10),3)
and
[y err] = sine_series(rand(1,10),3)
to see the difference.