Ett avståndsexempel
Följande exempel kommer också från en
föreläsning. Problemtexten lyder: "Bestäm den punkt som
ligger närmast origo och som samtidigt ligger på sfären, (x-1)^2+y^2+z^2=1,
och i planet x+y+z=1."
Steg 1: karakterisera
objektfunktion och bivillkor
På föreläsningen visade vi att det räcker att
minimera x^2+y^2+z^2,
kvadratroten behövs inte, med andra ord. Objektfunktionen är
ickelinjär (en kvadratsumma, så vi kunde ha valt en
specialrutin för denna typ av objektfunktion). Vi har två
likhetsbivillkor, ett linjärt (planet) och ett ickelinjärt
(sfären).
Steg 2: skriv objektfunktion
och bivillkor på standardform
Objektfunktionen är redan på standardform, liksom det
linjära bivillkoret. Vi skriver det ickelinjära villkoret som
(x-1)^2+y^2+z^2-1=0
(optimeringsrutinen
vill ha en nolla i ena ledet).
Steg 3:
förpackning; vi inför de vektorer och matriser som
behövs för att definiera objektfunktion och bivillkor
Vi inför först x
som vektorn som lagrar variablerna, detta för att visa på
ett potentiellt problem. x(1)
svarar mot x (usch!), x(2) mot y och x(3) mot z. För att slippa
göra fel byter vi beteckning och döper vektorn till w i stället, så w(1) svarar mot x, w(2) mot y och w(3) mot z
Likhetsbivillkoret definieras av radvektorn
A_eq och skalären B_eq, där A_eq * w = Beq. Så, A_eq = [1, 1, 1]; och B_eq = 1; . Det ickelinjära
bivillkoret definieras via en funktion, [in_eq, eq] = constr_fun(w),
som hanterar både ickelinjära likhetsbivillkor och
ickelinjära olikhetsbivillkor. Funktionen returnerar avvikelsen
från bivillkoren, så i rutinen kommer vi att bilda
eq
= (w(1)-1)^2 + w(2)^2 + w(3)^2 - 1;
Så, om avvikelsen, eq,
är noll, så uppfyller w
bivillkoret och om eq
är skilt från noll så är bivillkoret inte
uppfyllt.
Eftersom vi inte har något olikhetsbivillkor
sätter vi in_eq till
en tom variabel [] .
Steg 4: skriv Matlabkoden
Jag har valt att lägga de tre rutinerna i en fil, avst_ex.m .
function avst_ex
A =
[];
% inget linjärt olikhetsbivillkor
B = [];
A_eq = [1, 1,
1]; % linjärt likhetsbivillkor
B_eq = 1;
LB =
[];
% inga enkla gränser
UB = [];
w_guess = [1; 1;
0]; %
start-gissning
[w_opt, obj_val] =
fmincon(@obj_fun, w_guess, A, B, A_eq, B_eq, LB, UB, @constr_fun)
function obj_val = obj_fun(w)
obj_val =
sum(w.^2); %
objektfunktion
function [in_eq, eq] =
constr_fun(w)
in_eq =
[];
% inget ickelinjärt
olikhetsbivillkor
eq = (w(1) -
1)^2 + w(2)^2 + w(3)^2 - 1; %
ickelinjärt likhetsbivillkor
Körning (i redigerad form)
>> avst_ex
w_opt =
1.8350e-01
4.0825e-01
4.0825e-01
obj_val =
3.6701e-01
% facit från
föreläsningen
>> s = 1 / sqrt(6);
>> [1-2*s, s, s]
ans =
1.8350e-01 4.0825e-01 4.0825e-01 % stämmer
Antag nu att vi sätter w_guess
= [1; -1; -1]; . Rutinen konvergerar fortfarande men hittar i
stället ett lokalt maximum
(det största avståndet i själva verket; se
föreläsningen). Vi har alltså inga garantier för att vi
hittar ett lokalt minimum. Rutinen använder gradienten (bland
annat) för
att avgöra när den skall stanna, men gradienten ger oss inte
information om vi har min eller max, för det krävs ju
andraderivator (Hessian). Rutinen är en kvasi-Newton-rutin som
approximerar (inversen av) Hessianen av Lagrangefunktionen.
>> avst_ex
w_opt =
1.8165e+00
-4.0812e-01
-4.0838e-01
obj_val =
3.6330e+00
