t12の計算時にペンローズ擬似逆行列を用いるのがポイント。
パレートフロントはSTOMで希求水準をたくさん設定して求めるのが正攻法なのだろうが、横着してMatlabのboundary()コマンドを利用した。そのため実際はパレート最適値ではない点も拾ってグラフに描画されている。
値を代入するタイミング(つまりsubsコマンドを呼び出すタイミング)によって値が異なるのが気持ち悪い。
見た目は動いてるように見えるが、最初のトレードオフ比Tの計算で、非対角項(つまりトレードオフ比)が負になっている(教科書では正の値)。
(教科書の値) T = -1.0 0.711 1.405 -1.0 T2 = -1.0 1.0 1.0 -1.0 (計算値) T = -1.0000 -0.6977 -1.4334 -1.0000 T2 = -1.0000 1.0375 0.9639 -1.0000
clear; close all hidden; f1 = @(x) x(:,1); f2 = @(x) x(:,2); g1 = @(x) 1-x(:,1).^2-x(:,2).^2+0.1*cos(16*atan2(x(:,1),x(:,2))); g2 = @(x) (x(:,1)-0.5).^2+(x(:,2)-0.5).^2-0.5; f1i = 0; f2i = 0; f1a = 0.4; f2a = 0.25; % dx = 0.01; dx = 0.005; x1 = 0:dx:pi; x2 = 0:dx:pi; length(x1) [X1,X2] = meshgrid(x1,x2); X1vec = reshape(X1.',1,[]); X2vec = reshape(X2.',1,[]); Xvec = [X1vec;X2vec]'; Xpossible = Xvec(find(g1(Xvec)<=0 & g2(Xvec)<=0),:); figure(1); plot(Xpossible(:,1),Xpossible(:,2),'o'); % 希求水準f1a=0.4,f2a=0.25に対するパレート最適値(赤丸の点) w1 = 1/(f1a-f1i); w2 = 1/(f2a-f2i); C = max(w1*(f1(Xpossible)-f1a),w2*(f2(Xpossible)-f2a)); xopt = Xpossible(find(C==min(C)),:); x1opt = xopt(:,1); x2opt = xopt(:,2); f1opt = f1(xopt) f2opt = f2(xopt) hold on; plot(f1opt,f2opt,'ro'); plot(f1a,f2a,'xk'); %トレードオフ比t12の計算 syms f1_symbol(x1,x2) f2_symbol(x1,x2) g1_symbol(x1,x2) g2_symbol(x1,x2); f1_symbol(x1,x2) = @(x1,x2) x1; f2_symbol(x1,x2) = @(x1,x2) x2; g1_symbol(x1,x2) = @(x1,x2) 1-x1^2-x2^2+0.1*cos(16*atan2(x1,x2)); g2_symbol(x1,x2) = @(x1,x2) (x1-0.5)^2+(x2-0.5)^2-0.5; grad_f1 = gradient(f1_symbol); grad_f2 = gradient(f2_symbol); grad_g1 = gradient(g1_symbol); grad_g2 = gradient(g2_symbol); N = [grad_g1,grad_g2]; N = simplify(N); P = eye(2) - N*inv(transpose(N)*N)*transpose(N);%Pの計算はペンローズ擬似逆行列にする grad_F1 = P*grad_f1; grad_F2 = P*grad_f2; grad_F1v = eval(subs(grad_F1,{x1 x2},{x1opt x2opt}));%計算負荷が高すぎるのでここで値を代入する grad_F2v = eval(subs(grad_F2,{x1 x2},{x1opt x2opt}));%計算負荷が高すぎるのでここで値を代入する t12 = -transpose(grad_F2v)*pinv(grad_F1v*... transpose(grad_F1v))*grad_F1v;%t12の計算もペンローズ逆行列で計算する t21 = 1/t12; T = [-1 t12; t21 -1] % パレートフロントを求める % Matlabのboundary()コマンドを利用して外周の点を広い、f1<1, f2<1となるようにフィルタをかける。 k = boundary(Xpossible(:,1),Xpossible(:,2)); Xk = Xpossible(k,:); Xb1 = Xk(:,1); Xb2 = Xk(:,2); Xc = Xk(find(Xb1<1 & Xb2<1),:); Xc1 = Xc(:,1); Xc2 = Xc(:,2); plot(Xc1,Xc2,'xk'); big; % トレードオフ比=1となるようなx1,x2の値(希求水準)を求める Ds = []; hw = waitbar(0,'Running...'); for idx=1:length(Xc) Xp = Xc(idx,:); Xp1 = Xp(1); Xp2 = Xp(2); try grad_F1v = eval(subs(grad_F1,{x1 x2},{Xp1 Xp2}));%計算負荷が高すぎるのでここで値を代入する grad_F2v = eval(subs(grad_F2,{x1 x2},{Xp1 Xp2}));%計算負荷が高すぎるのでここで値を代入する t12 = -transpose(grad_F2v)*pinv(grad_F1v*... transpose(grad_F1v))*grad_F1v;%t12の計算もペンローズ逆行列で計算する D = (t12-1)^2; Ds(end+1) = D; % disp(sprintf('%d %.3g %.3g %.3g %.3g',idx, Xp1, Xp2, t12, D)); waitbar(idx/length(Xc),hw); end end figure(2); plot(Ds,'-'); ylim([-0.1,1]); Xopt2 = Xc(find(Ds==min(Ds)),:) f1opt2 = f1(Xopt2) f2opt2 = f2(Xopt2) grad_F1v = eval(subs(grad_F1,{x1 x2},{Xopt2(1) Xopt2(2)}));%計算負荷が高すぎるのでここで値を代入する grad_F2v = eval(subs(grad_F2,{x1 x2},{Xopt2(1) Xopt2(2)}));%計算負荷が高すぎるのでここで値を代入する t12 = -transpose(grad_F2v)*pinv(grad_F1v*... transpose(grad_F1v))*grad_F1v;%t12の計算もペンローズ逆行列で計算する t21 = 1/t12; T2 = [-1 t12; t21 -1] figure(1); plot(f1opt2,f2opt2,'rx'); axis equal; big;