Dynamic-Calibration/utils/YALMIP-master/operators/kullbackleibler.m

72 lines
1.9 KiB
Mathematica
Raw Permalink Normal View History

2019-12-18 11:25:45 +00:00
function varargout = kullbackleibler(varargin)
% KULLBACKLEIBLER
%
% y = KULLBACKLEIBLER(x,y)
%
% Computes/declares the convex Kullback-Leibler divergence sum(x.*log(x./y))
% Alternatively -sum(x.*log(y/x)), i.e., negated perspectives of log(y)
%
% See also ENTROPY, CROSSENTROPY
switch class(varargin{1})
case 'double'
if nargin == 1
z = varargin{1};
z = reshape(z,[],2);
x = z(:,1);
y = z(:,2);
else
x = varargin{1}(:);
y = varargin{2}(:);
end
l = log(x./y);
l(x<=0) = 0;
l = real(l);
varargout{1} = sum(x.*l);
case {'sdpvar','ndsdpvar'}
varargin{1} = reshape(varargin{1},[],1);
varargin{2} = reshape(varargin{2},[],1);
if length(varargin{1})~=length(varargin{2})
if length(varargin{1})==1
varargin{1} = repmat(varargin{1},length(varargin{2}),1);
elseif length(varargin{2})==1
varargin{2} = repmat(varargin{2},length(varargin{1}),1);
else
error('Dimension mismatch in kullbackleibler')
end
end
varargout{1} = yalmip('define',mfilename,[varargin{1};varargin{2}]);
case 'char'
X = varargin{3};
F = [X >= 0];
operator = struct('convexity','convex','monotonicity','none','definiteness','none','model','callback');
operator.range = [-inf inf];
operator.domain = [0 inf];
operator.derivative = @derivative;
varargout{1} = F;
varargout{2} = operator;
varargout{3} = X;
otherwise
error('SDPVAR/KULLBACKLEIBLER called with CHAR argument?');
end
function df = derivative(x)
z = abs(reshape(x,[],2));
x = z(:,1);
y = z(:,2);
% Use KL = -Entropy + Cross Entropy
df = [1+log(x);0*y] + [-log(y);-x./y];