0001 function Mn = powermanifold(M, n)
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040 assert(n >= 1, 'n must be an integer larger than or equal to 1.');
0041
0042 Mn.name = @() sprintf('[%s]^%d', M.name(), n);
0043
0044 Mn.dim = @() n*M.dim();
0045
0046 Mn.inner = @inner;
0047 function val = inner(x, u, v)
0048 val = 0;
0049 for i = 1 : n
0050 val = val + M.inner(x{i}, u{i}, v{i});
0051 end
0052 end
0053
0054 Mn.norm = @(x, d) sqrt(Mn.inner(x, d, d));
0055
0056 Mn.dist = @dist;
0057 function d = dist(x, y)
0058 sqd = 0;
0059 for i = 1 : n
0060 sqd = sqd + M.dist(x{i}, y{i})^2;
0061 end
0062 d = sqrt(sqd);
0063 end
0064
0065 Mn.typicaldist = @typicaldist;
0066 function d = typicaldist()
0067 sqd = 0;
0068 for i = 1 : n
0069 sqd = sqd + M.typicaldist()^2;
0070 end
0071 d = sqrt(sqd);
0072 end
0073
0074 Mn.proj = @proj;
0075 function u = proj(x, u)
0076 for i = 1 : n
0077 u{i} = M.proj(x{i}, u{i});
0078 end
0079 end
0080
0081 Mn.tangent = @tangent;
0082 function u = tangent(x, u)
0083 for i = 1 : n
0084 u{i} = M.tangent(x{i}, u{i});
0085 end
0086 end
0087
0088 if isfield(M, 'tangent2ambient_is_identity')
0089 Mn.tangent2ambient_is_identity = M.tangent2ambient_is_identity;
0090 else
0091 Mn.tangent2ambient_is_identity = true;
0092 end
0093
0094 if isfield(M, 'tangent2ambient')
0095 Mn.tangent2ambient = @tangent2ambient;
0096 else
0097 Mn.tangent2ambient = @(x, u) u;
0098 end
0099 function u = tangent2ambient(x, u)
0100 for i = 1 : n
0101 u{i} = M.tangent2ambient(x{i}, u{i});
0102 end
0103 end
0104
0105 if nargin(M.egrad2rgrad) > 2
0106 warning('manopt:powermanifold:egrad2rgrad', ...
0107 ['Power manifolds call M.egrad2rgrad with only two ', ...
0108 'inputs:\nstoredb and key won''t be available.']);
0109 end
0110 Mn.egrad2rgrad = @egrad2rgrad;
0111 function g = egrad2rgrad(x, g)
0112 for i = 1 : n
0113 g{i} = M.egrad2rgrad(x{i}, g{i});
0114 end
0115 end
0116
0117 if nargin(M.ehess2rhess) > 4
0118 warning('manopt:powermanifold:ehess2rhess', ...
0119 ['Power manifolds call M.ehess2rhess with only four ', ...
0120 'inputs:\nstoredb and key won''t be available.']);
0121 end
0122 Mn.ehess2rhess = @ehess2rhess;
0123 function h = ehess2rhess(x, eg, eh, h)
0124 for i = 1 : n
0125 h{i} = M.ehess2rhess(x{i}, eg{i}, eh{i}, h{i});
0126 end
0127 end
0128
0129 Mn.exp = @expo;
0130 function x = expo(x, u, t)
0131 if nargin < 3
0132 t = 1.0;
0133 end
0134 for i = 1 : n
0135 x{i} = M.exp(x{i}, u{i}, t);
0136 end
0137 end
0138
0139 Mn.retr = @retr;
0140 function x = retr(x, u, t)
0141 if nargin < 3
0142 t = 1.0;
0143 end
0144 for i = 1 : n
0145 x{i} = M.retr(x{i}, u{i}, t);
0146 end
0147 end
0148
0149 if isfield(M, 'log')
0150 Mn.log = @loga;
0151 end
0152 function u = loga(x, y)
0153 u = cell(n, 1);
0154 for i = 1 : n
0155 u{i} = M.log(x{i}, y{i});
0156 end
0157 end
0158
0159 Mn.hash = @hash;
0160 function str = hash(x)
0161 str = '';
0162 for i = 1 : n
0163 str = [str M.hash(x{i})];
0164 end
0165 str = ['z' hashmd5(str)];
0166 end
0167
0168 Mn.lincomb = @lincomb;
0169 function x = lincomb(x, a1, u1, a2, u2)
0170 if nargin == 3
0171 for i = 1 : n
0172 x{i} = M.lincomb(x{i}, a1, u1{i});
0173 end
0174 elseif nargin == 5
0175 for i = 1 : n
0176 x{i} = M.lincomb(x{i}, a1, u1{i}, a2, u2{i});
0177 end
0178 else
0179 error('Bad usage of powermanifold.lincomb');
0180 end
0181 end
0182
0183 Mn.rand = @rand;
0184 function x = rand()
0185 x = cell(n, 1);
0186 for i = 1 : n
0187 x{i} = M.rand();
0188 end
0189 end
0190
0191 Mn.randvec = @randvec;
0192 function u = randvec(x)
0193 u = cell(n, 1);
0194 for i = 1 : n
0195 u{i} = M.randvec(x{i});
0196 end
0197 u = Mn.lincomb(x, 1/sqrt(n), u);
0198 end
0199
0200 Mn.zerovec = @zerovec;
0201 function u = zerovec(x)
0202 u = cell(n, 1);
0203 for i = 1 : n
0204 u{i} = M.zerovec(x{i});
0205 end
0206 end
0207
0208 if isfield(M, 'transp')
0209 Mn.transp = @transp;
0210 end
0211 function u = transp(x1, x2, u)
0212 for i = 1 : n
0213 u{i} = M.transp(x1{i}, x2{i}, u{i});
0214 end
0215 end
0216
0217 if isfield(M, 'pairmean')
0218 Mn.pairmean = @pairmean;
0219 end
0220 function y = pairmean(x1, x2)
0221 y = cell(n, 1);
0222 for i = 1 : n
0223 y{i} = M.pairmean(x1{i}, x2{i});
0224 end
0225 end
0226
0227
0228
0229 if isfield(M, 'vec')
0230 rand_x = M.rand();
0231 zero_u = M.zerovec(rand_x);
0232 len_vec = length(M.vec(rand_x, zero_u));
0233
0234 Mn.vec = @(x, u_mat) vec(x, u_mat, len_vec, M, n);
0235
0236 if isfield(M, 'mat')
0237 Mn.mat = @(x, u_vec) mat(x, u_vec, len_vec, M, n);
0238 end
0239
0240 end
0241
0242 function u_vec = vec(x, u_mat, len_vec, M, n)
0243 u_vec = zeros(len_vec, n);
0244 for i = 1 : n
0245 u_vec(:, i) = M.vec(x{i}, u_mat{i});
0246 end
0247 u_vec = u_vec(:);
0248 end
0249
0250 function u_mat = mat(x, u_vec, len_vec, M, n)
0251 u_mat = cell(n, 1);
0252 u_vec = reshape(u_vec, len_vec, n);
0253 for i = 1 : n
0254 u_mat{i} = M.mat(x{i}, u_vec(:, i));
0255 end
0256 end
0257
0258 if isfield(M, 'vecmatareisometries')
0259 Mn.vecmatareisometries = M.vecmatareisometries;
0260 else
0261 Mn.vecmatareisometries = @() false;
0262 end
0263
0264 if isfield(M, 'lie_identity')
0265 Mn.lie_identity = @lie_identity;
0266 end
0267 function I = lie_identity()
0268 I_M = M.lie_identity();
0269 I = cell(n, 1);
0270 for k = 1 : n
0271 I{k} = I_M;
0272 end
0273 end
0274
0275 end