一般に、Optimization Toolbox の関数は、非線形制約関数を評価する前に、目的関数を評価します。しかし、非線形制約関数が、同じ "x" の値で目的関数が評価される前に、ある特定の "x" の値を渡される可能性も考えられます。
目的関数の "x" の値に対応する値を確実に共有するためには、以下のように修正する必要があります。
function [x,fval] = runsharedvalues(a,b,c,d,lower)
objval = []; % 共有させたい値の初期値
xcheck = [];
x0 = [-1 1]; % 最適化パラメータの初期値
options = optimset('LargeScale','off');
[x,fval] = fmincon(@objfun,x0,[],[],[],[],[],[],@constrfun,options);
% 目的関数
function f = objfun(x)
% Variable objval shared with constrfun
objval = exp(x(1))*(a*x(1)^2+b*x(2)^2+c*x(1)*x(2)+d*x(2)+1);
f = objval;
xcheck = x; % cnstrfun で共有するxcheck
end
% 制約関数
function [con,ceq] = constrfun(x)
% 現在の x が objfun 関数で評価された objval で使われている x と
% 一致しない場合を除き、objval の値を再利用する。
% 一致しなければ、objval の値は再計算する。
if any(x ~= xcheck)
objval = exp(x(1))*(a*x(1)^2+b*x(2)^2+c*x(1)*x(2)+d*x(2)+1);
end
con(1) = -objval + lower;
con(2:3) = [1.5 + x(1)*x(2) - x(1) - x(2); -x(1)*x(2) - 10];
ceq = [];
end
end
"x" の値は、テンポラリ変数 "xcheck" に代入されています。これにより、非線形制約関数が呼び出されたとき、"objval" が現在の "x" の値に基づいた値であるかどうかを確認することができます。もし、現在の値 "x" の値で評価されていない場合には、制約関数内にて、再度 objval を計算しなおします。