72 lines
1.9 KiB
Mathematica
72 lines
1.9 KiB
Mathematica
|
|
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];
|
||
|
|
|
||
|
|
|