151 lines
4.2 KiB
Matlab
Executable File
151 lines
4.2 KiB
Matlab
Executable File
function y = mpower(x,d)
|
|
%MPOWER (overloaded)
|
|
|
|
if (numel(d)>1) || (size(x,1) ~= size(x,2))
|
|
error('Inputs must be a scalar and a square matrix. To compute elementwise POWER, use POWER (.^) instead.');
|
|
end
|
|
|
|
if isa(d,'sdpvar')
|
|
if numel(x) > 1
|
|
if isa(x,'sdpvar')
|
|
error('x^d not support SDPVARMATRIX^SDPVARSCALAR')
|
|
else
|
|
if isnumeric(x)
|
|
[V,D] = eig(x);
|
|
if ~isreal(D)
|
|
error('Matrix power x^d requires x to have real eigenvalues');
|
|
end
|
|
D = real(D);
|
|
y = V*diag(diag(D).^d)*inv(V);
|
|
y.extra.createTime = definecreationtime;
|
|
return
|
|
else
|
|
error('Object class not support in x^d');
|
|
end
|
|
end
|
|
end
|
|
d = flush(d);d.conicinfo = [0 0];
|
|
y = power_internal1(d,x);
|
|
if isa(y,'sdpvar')
|
|
y.extra.createTime = definecreationtime;
|
|
end
|
|
return
|
|
end
|
|
|
|
x = flush(x);
|
|
|
|
% Trivial cases
|
|
if d==0
|
|
y = eye(x.dim(1),x.dim(2))^0;
|
|
return
|
|
end
|
|
if d==1
|
|
y = x;
|
|
return
|
|
end
|
|
|
|
% Check for special case norm(x)^2 which many users try to do
|
|
if d==2
|
|
if length(x)==1
|
|
base = getbase(x);
|
|
if isequal(base,[0 1])
|
|
if strcmp(x.extra.opname,'norm')
|
|
model = yalmip('extstruct',getvariables(x));
|
|
z = model.arg{1};
|
|
if (isequal(model.arg{2},2) & min(size(z))==1) | isequal(model.arg{2},'fro')
|
|
z = reshape(model.arg{1},[],1);
|
|
y = real(z'*z);
|
|
y.extra.createTime = definecreationtime;
|
|
return
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
|
|
% Fractional and negative powers
|
|
if (ceil(d)-d>0) | (d<0)
|
|
if x.dim(1)>1 | x.dim(2)>1
|
|
error('Only scalars can have negative or non-integer powers');
|
|
else
|
|
base = getbase(x);
|
|
if isequal(base,sparse([0 1])) % Simple unit scalar
|
|
[mt,variabletype,hashM,hash] = yalmip('monomtable');
|
|
var = getvariables(x);
|
|
% hash = randn(size(mt,2),1);
|
|
% hashM = mt*hash;
|
|
hashV = (mt(var,:)*d)*hash;
|
|
previous_var = find(abs(hashM - hashV) < 1e-20);
|
|
if isempty(previous_var)
|
|
newmt = mt(getvariables(x),:)*d;
|
|
mt(end+1,:) = newmt;
|
|
yalmip('setmonomtable',mt,[variabletype newvariabletypegen(newmt)]);
|
|
y = recover(size(mt,1));
|
|
else
|
|
y = recover(previous_var);
|
|
end
|
|
elseif (size(base,2) == 2) & base(1)==0
|
|
% Something like a*t^-d
|
|
y = base(2)^d*recover(getvariables(x))^d;
|
|
else
|
|
% Bummer, something more complex, add an internal equality constraint
|
|
y = (yalmip('define','mpower_internal',x))^d;
|
|
end
|
|
end
|
|
y.extra.createTime = definecreationtime;
|
|
return
|
|
end
|
|
|
|
% Integer power of matrix
|
|
if x.dim(1)>1 | x.dim(2)>1
|
|
switch d
|
|
case 0
|
|
y = 1;
|
|
case 1
|
|
y = x;
|
|
otherwise
|
|
y = x*mpower(x,d-1);
|
|
end
|
|
else %Integer power of scalar
|
|
|
|
base = x.basis;
|
|
if isequal(base,[0 1]) % Unit scalar can be done fast
|
|
[mt,variabletype,hashes,hash] = yalmip('monomtable');
|
|
var = x.lmi_variables;
|
|
newmt = mt(var,:)*d;
|
|
newhash = newmt*hash;
|
|
previous_var = findhash(hashes , newhash,length(hashes));
|
|
if isempty(previous_var)
|
|
mt = [mt;newmt];
|
|
yalmip('setmonomtable',mt,[variabletype newvariabletypegen(newmt)]);
|
|
y = x;
|
|
y.lmi_variables = size(mt,1);
|
|
else
|
|
y = x;
|
|
y.lmi_variables = previous_var;
|
|
end
|
|
|
|
else % General scalar
|
|
switch d
|
|
case 0
|
|
y = 1;
|
|
case 1
|
|
y = x;
|
|
case 2
|
|
y = x*x;
|
|
otherwise
|
|
if even(d)
|
|
z = mpower(x,d/2);
|
|
y = z*z;
|
|
else
|
|
y = x*mpower(x,d-1);
|
|
end
|
|
end
|
|
end
|
|
y.extra.createTime = definecreationtime;
|
|
end
|
|
|
|
|
|
|