Finding the minimum of a function over an interval - matlab

Upon request by Martin here is the basic problem. There is a function M(x) which is supposed to be minimized over the interval [lb, ub].
M = #(x) (a_1 * x + b_1) * (log((a_1 * x + b_1)/P_1) + X_u)...
+ (a_2 * x + b_2) * (log((a_2 * x + b_2)/P_2) + X_m)...
+ x * (log(x / P_3) + X_d);
lb = max(0, -b_1 / a_1);
ub = -b_2 / a_2;
where the inputs are:
P_1 = 0.6;
P_2 = 0.2;
P_3 = 0.2;
a_1 = 0.7071;
a_2 = -1.7071;
b_1 = 0.0245;
b_2 = 0.9755;
X_u = 44;
X_m = 2.9949;
X_d = 0;
The other option would be to solve for the root of the equation m_dash:
m_dash = #(x) log(((a_1 .* x + b_1).^a_1) .* ((a_2 .* x + b_2).^a_2) .* x)...
- log((P_1.^a_1) .* (P_2.^a_2) .* P_3) + a_1 .* X_u + a_2 .* X_m + X_d;
Any help would be greatly appreciated.

If you want to minimize a function over a certain interval, you can use the fminbnd function from the Optimization Toolbox. If you don't have that toolbox installed, you can either try a free alternative, or instead coerce the built-in function fminsearch to only return results from the interval:
rlv = 1e12; % ridiculously large value
M_hacked= #(x) rlv*((x < lb) + (x > ub)) + M(x);
x_min = fminsearch(M_hacked, (lb + ub)/2)
I introduced a new function, M_hacked, which returns ridiculously large values for x outside of the interval.
This is not be the most elegant solution, but it should do for your problem.

Related

How to compute the derivatives automatically within for-loop in Matlab?

For the purpose of generalization, I hope Matlab can automatically compute the 1st & 2nd derivatives of the associated function f(x). (in case I change f(x) = sin(6x) to f(x) = sin(8x))
I know there exists built-in commands called diff() and syms, but I cannot figure out how to deal with them with the index i in the for-loop. This is the key problem I am struggling with.
How do I make changes to the following set of codes? I am using MATLAB R2019b.
n = 10;
h = (2.0 * pi) / (n - 1);
for i = 1 : n
x(i) = 0.0 + (i - 1) * h;
f(i) = sin(6 * x(i));
dfe(i) = 6 * cos(6 * x(i)); % first derivative
ddfe(i) = -36 * sin(6 * x(i)); % second derivative
end
You can simply use subs and double to do that. For your case:
% x is given here
n = 10;
h = (2.0 * pi) / (n - 1);
syms 'y';
g = sin(6 * y);
for i = 1 : n
x(i) = 0.0 + (i - 1) * h;
f(i) = double(subs(g,y,x(i)));
dfe(i) = double(subs(diff(g),y,x(i))); % first derivative
ddfe(i) = double(subs(diff(g,2),y,x(i))); % second derivative
end
By #Daivd comment, you can vectorize the loop as well:
% x is given here
n = 10;
h = (2.0 * pi) / (n - 1);
syms 'y';
g = sin(6 * y);
x = 0.0 + ((1:n) - 1) * h;
f = double(subs(g,y,x));
dfe = double(subs(diff(g),y,x)); % first derivative
ddfe = double(subs(diff(g,2),y,x)); % second derivative

Matlab function - How to get a "clear" function

I have a very long equation (Taylor polynomial) with coefficients fa, fxa, fya (and so on, see below). These are for approximating the value of the function f at the point A = (a,b). The variables a and b are the two components of the point I want to develop the Taylor polynomial around.
The equation:
t = #(x,y) fa + fxa .* (x-a) + fya .* (y-b) + 1/2 .* fxxa.*(x-a).^2 + ...
1/2 .* fxya .* (x-a).*(y-b) + fyya .* (y-b).^2 + ...
1/6 .* fxxxa .* (x-a).^3 + 1/2 .* fxxya .* (x-a).^2.*(y-b) + ...
1/2 .* fxyya .* (x-a).*(y-b).^2 + 1/6 .* fyyya .* (y-b).^3;
All of the variables named like fxyya, are integer values.
I want to have a version of the fuction t, where my calculated coefficients are acutally "put in" and not only the variable names like fxxy and fxya.
For instance, all 0 terms disappear and so on.
Ho do I get that?
For reference, all of the code:
syms x y;
%f = input('Bitte geben Sie die zu evaluierende Funktion ein:','s');
f = 'exp(x^2+y^3)+x*y*(x+y)';
f = sym(f);
f = symfun(f, symvar(f, 2));
a = 0;
b = 0;
fx = diff(f,x);
fy = diff(f,y);
fxx = diff(fx,x);
fyy = diff(fy,y);
fxy = diff(fx,y);
fxxx = diff(fxx,x);
fxxy = diff(fxx,y);
fxyy = diff(fxy,y);
fyyy = diff(fyy,y);
fa = f(a,b);
fxa = fx(a,b);
fya = fy(a,b);
fxxa = fxx(a,b);
fyya = fyy(a,b);
fxya = fxy(a,b);
fxxxa = fxxx(a,b);
fxxya = fxxy(a,b);
fxyya = fxyy(a,b);
fyyya = fyyy(a,b);
t = #(x,y) fa + fxa .* (x-a) + fya .* (y-b) + 1/2 .* fxxa.*(x-a).^2 + 1/2 .* fxya .* (x-a).*(y-b) + fyya .* (y-b).^2 + 1/6 .* fxxxa .* (x-a).^3 + 1/2 .* fxxya .* (x-a).^2.*(y-b) + 1/2 .* fxyya .* (x-a).*(y-b).^2 + 1/6 .* fyyya .* (y-b).^3;
You can just use subs(t), but below is a cleaner version of your code without the need for subs...
You state that the coefficients are integers, but your example code creates them as analytically differentiated syms variables! Here is an adaptation of your code, which doesn't require subs to be used.
% Set up symbolic x and y, and symbolic function f
syms x y;
f = symfun(exp(x^2+y^3)+x*y*(x+y), [x y]);
% Set up points a and b
a = 0; b = 0;
% Get derivative functions analytically (these need to be evaluated at some points x,y)
fx = diff(f,x); fy = diff(f,y);
fxx = diff(fx,x); fyy = diff(fy,y); fxy = diff(fx,y);
fxxx = diff(fxx,x); fxxy = diff(fxx,y); fxyy = diff(fxy,y);
fyyy = diff(fyy,y);
% Define symbolic function t
t = symfun(f(a,b) + fx(a,b).*(x-a) + fy(a,b).*(y-b) + ...
(1/2).*fxx(a,b).*(x-a).^2 + (1/2).*fxy(a,b).*(x-a).*(y-b) + fyy(a,b).*(y-b).^2 + ...
(1/6).*fxxx(a,b).*(x-a).^3 + (1/2).*fxxy(a,b).*(y-b).*(x-a).^2 + ...
(1/2).*fxyy(a,b).*(x-a).*(y-b).^2 + (1/6).*fyyy(a,b).*(y-b).^3, [x,y]);
t
% output: t(x, y) = x^2*y + x^2 + x*y^2 + y^3 + 1

Built a loop for a definite integral

I am trying to build a loop for a definite integral from 0 to y with step 0.1 for y=0 to y=20 and get a value for each loop iteration (varying y) in a diagram.
int(2.906663106*x*(1/(1+1.38*x^4))^.4311594203 - 3.458929096*x^5/((1/(1+1.38*x^4))^.5688405797*(1+1.38*x^4)^2))
You can use the integral function of Matlab and run this inside a for loop
val = zeros(1,201);
y_step = 0.1;
y_max = 20;
count = 1;
for yy = 0:y_step:y_max
fun = #(x) (2.906663106 .* x .* (1 ./ (1 + 1.38 .* x.^4)).^0.4311594203 - 3.458929096 .* x.^5 ./ ((1 ./ (1 + 1.38 .* x.^4)).^0.5688405797 .* (1 + 1.38 .* x.^4).^2));
intgrl = integral(fun, 0, yy);
val(count) = intgrl;
count = count + 1;
end
figure
plot(val)
You will have each value of the integral in the range [0, yy] during the loop saved in val.
edit: Edited answer due to more detailed question in comment.

How can I fix the link between the multiplier and eqn(x)?

I am right now stuck on a problem in matlab. What I have done is that I have an equation that is passed on into another function which works by the bisection-method.
But I have a multiplier that I am trying to implement which somehow leads to the function crashing.
Before I introduced the multiplier it all worked, I tried breaking it down by entering the multiplier value manually and it didn't work
P_{1} = 0.6;
P_{2} = 0.2;
P_{3} = 0.2;
a_1 = 4/3;
a_2 = -7/3;
b_1 = -1/3;
b_2 = 4/3;
persistent multiplier
multiplier = exp(a_1 * 44 + a_2 * 14 + 0);
eqn = #(x) ((a_1 * x + b_1)^a_1) * ((a_2 * x + b_2)^a_2) * x ...
-(P_{1}^a_1) * (P_{2}^a_2) * P_{3} * multiplier;
Q_{3} = Bisectionmethod(a_1, a_2, b_1, b_2, eqn);
Here is the calculating part of the bisection method.
x_lower = max(0, -b_1 / a_1);
x_upper = -b_2 / a_2;
x_mid = (x_lower + x_upper)/2;
Conditional statement encompassing the method of bisection
while abs(eqn(x_mid)) > 10^(-10)
if (eqn(x_mid) * eqn(x_upper)) < 0
x_lower = x_mid;
else
x_upper = x_mid;
end
x_mid = (x_lower + x_upper)/2;
end
Based on the information you provided this is what I came up with
function Q = Stackoverflow
persistent multiplier
P{1} = 0.6;
P{2} = 0.2;
P{3} = 0.2;
a1 = 4/3;
a2 = -7/3;
b1 = -1/3;
b2 = 4/3;
multiplier = exp(a1 * 44 + a2 * 14 + 0);
eqn = #(x) ((a1 .* x + b1).^a1) .* ((a2 .* x + b2).^a2) .* x -(P{1}.^a1) .* (P{2}.^a2) .* P{3} .* multiplier;
Q{3} = Bisectionmethod(eqn, max([0, -b1/a1]), -b2/a2, 1E-10);
end
function XOut = Bisectionmethod(f, xL, xH, EPS)
if sign(f(xL)) == sign(f(xH))
XOut = [];
error('Cannot bisect interval because can''t ensure the function crosses 0.')
end
x = [xL, xH];
while abs(diff(x)) > EPS
x(sign(f(mean(x))) == sign(f(x))) = mean(x);
end
XOut = mean(x);
end

Radix-4 FFT implementation

The Octave radix-4 FFT code below works fine if I set power of 4 (xp) values case-by-case.
$ octave fft4.m
ans = 1.4198e-015
However, if I uncomment the loop code I get the following error
$ octave fft4.m
error: `stage' undefined near line 48 column 68
error: evaluating argument list element number 1
error: evaluating argument list element number 2
error: called from:
error: r4fftN at line 48, column 22
error: c:\Users\david\Documents\Visual Studio 2010\Projects\mv_fft\fft4.m at line 80, column 7
the "error" refers to a line the in fft function code which otherwise works correctly when xp is not set by a loop ... very strange.
function Z = radix4bfly(x,segment,stageFlag,W)
% For the last stage of a radix-4 FFT all the ABCD multiplers are 1.
% Use the stageFlag variable to indicate the last stage
% stageFlag = 0 indicates last FFT stage, set to 1 otherwise
% Initialize variables and scale to 1/4
a=x(1)*.25;
b=x(2)*.25;
c=x(3)*.25;
d=x(4)*.25;
% Radix-4 Algorithm
A=a+b+c+d;
B=(a-b+c-d)*W(2*segment*stageFlag + 1);
C=(a-b*j-c+d*j)*W(segment*stageFlag + 1);
D=(a+b*j-c-d*j)*W(3*segment*stageFlag + 1);
% assemble output
Z = [A B C D];
end % radix4bfly()
% radix-4 DIF FFT, input signal must be floating point, real or complex
%
function S = r4fftN(s)
% Initialize variables and signals: length of input signal is a power of 4
N = length(s);
M = log2(N)/2;
% Initialize variables for floating point sim
W=exp(-j*2*pi*(0:N-1)/N);
S = complex(zeros(1,N));
sTemp = complex(zeros(1,N));
% FFT algorithm
% Calculate butterflies for first M-1 stages
sTemp = s;
for stage = 0:M-2
for n=1:N/4
S((1:4)+(n-1)*4) = radix4bfly(sTemp(n:N/4:end), floor((n-1)/(4^stage)) *(4^stage), 1, W);
end
sTemp = S;
end
% Calculate butterflies for last stage
for n=1:N/4
S((1:4)+(n-1)*4) = radix4bfly(sTemp(n:N/4:end), floor((n-1)/(4^stage)) * (4^
stage), 0, W);
end
sTemp = S;
% Rescale the final output
S = S*N;
end % r4fftN(s)
% test FFT code
%
xp = 2;
% ERROR if I uncomment loop!
%for xp=1:8
N = 4^xp; % must be power of: 4 16 64 256 1024 4086 ....
x = 2*pi/N * (0:N-1);
x = cos(x);
Y_ref = fft(x);
Y = r4fftN(x);
Y = digitrevorder(Y,4);
%Y = bitrevorder(Y,4);
abs(sum(Y_ref-Y)) % compare fft4 to built-in fft
%end
The problem was the loop-bound for the exponent xp should start from 2 as the fft4 code assumes at least 2 stages of radix-4 butterflies
Sorry folks :(
-David
Please find below a fully worked Matlab implementation of a radix-4 Decimation In Frequency FFT algorithm. I have also provided an overall operations count in terms of complex matrix multiplications and additions. It can be indeed shown that each radix-4 butterfly involves 3 complex multiplications and 8 complex additions. Since there are log_4(N) = log_2(N) / 2 stages and each stage involves N / 4 butterflies, so the operations count is
complex multiplications = (3 / 8) * N * log2(N)
complex additions = N * log2(N)
Here is the code:
% --- Radix-2 Decimation In Frequency - Iterative approach
clear all
close all
clc
% --- N should be a power of 4
N = 1024;
% x = randn(1, N);
x = zeros(1, N);
x(1 : 10) = 1;
xoriginal = x;
xhat = zeros(1, N);
numStages = log2(N) / 2;
W = exp(-1i * 2 * pi * (0 : N - 1) / N);
omegaa = exp(-1i * 2 * pi / N);
mulCount = 0;
sumCount = 0;
M = N / 4;
for p = 1 : numStages;
for index = 0 : (N / (4^(p - 1))) : (N - 1);
for n = 0 : M - 1;
a = x(n + index + 1) + x(n + index + M + 1) + x(n + index + 2 * M + 1) + x(n + index + 3 * M + 1);
b = (x(n + index + 1) - x(n + index + M + 1) + x(n + index + 2 * M + 1) - x(n + index + 3 * M + 1)) .* omegaa^(2 * (4^(p - 1) * n));
c = (x(n + index + 1) - 1i * x(n + index + M + 1) - x(n + index + 2 * M + 1) + 1i * x(n + index + 3 * M + 1)) .* omegaa^(1 * (4^(p - 1) * n));
d = (x(n + index + 1) + 1i * x(n + index + M + 1) - x(n + index + 2 * M + 1) - 1i * x(n + index + 3 * M + 1)) .* omegaa^(3 * (4^(p - 1) * n));
x(n + 1 + index) = a;
x(n + M + 1 + index) = b;
x(n + 2 * M + 1 + index) = c;
x(n + 3 * M + 1 + index) = d;
mulCount = mulCount + 3;
sumCount = sumCount + 8;
end;
end;
M = M / 4;
end
xhat = bitrevorder(x);
tic
xhatcheck = fft(xoriginal);
timeFFTW = toc;
rms = 100 * sqrt(sum(sum(abs(xhat - xhatcheck).^2)) / sum(sum(abs(xhat).^2)));
fprintf('Theoretical multiplications count \t = %i; \t Actual multiplications count \t = %i\n', ...
(3 / 8) * N * log2(N), mulCount);
fprintf('Theoretical additions count \t\t = %i; \t Actual additions count \t\t = %i\n\n', ...
N * log2(N), sumCount);
fprintf('Root mean square with FFTW implementation = %.10e\n', rms);