Home > manopt > tools > powermanifold.m

powermanifold

PURPOSE ^

Returns a structure describing a power manifold M^n = M x M x ... x M.

SYNOPSIS ^

function Mn = powermanifold(M, n)

DESCRIPTION ^

 Returns a structure describing a power manifold M^n = M x M x ... x M.

 function Mn = powermanifold(M, n)

 Input: a manifold structure M and an integer n >= 1.
 
 Output: a manifold structure Mn representing M x ... x M (n copies of M)
 with the metric of M extended element-wise. Points and vectors are stored
 as cells of size nx1.

 This code is for prototyping uses. The structures returned are often
 inefficient representations of power manifolds owing to their use of
 for-loops, but they should allow to rapidly try out an idea.

 Example (an inefficient representation of the oblique manifold (3, 10)):
 Mn = powermanifold(spherefactory(3), 10)
 disp(Mn.name());
 x = Mn.rand()

 See also: productmanifold

CROSS-REFERENCE INFORMATION ^

This function calls: This function is called by:

SUBFUNCTIONS ^

SOURCE CODE ^

0001 function Mn = powermanifold(M, n)
0002 % Returns a structure describing a power manifold M^n = M x M x ... x M.
0003 %
0004 % function Mn = powermanifold(M, n)
0005 %
0006 % Input: a manifold structure M and an integer n >= 1.
0007 %
0008 % Output: a manifold structure Mn representing M x ... x M (n copies of M)
0009 % with the metric of M extended element-wise. Points and vectors are stored
0010 % as cells of size nx1.
0011 %
0012 % This code is for prototyping uses. The structures returned are often
0013 % inefficient representations of power manifolds owing to their use of
0014 % for-loops, but they should allow to rapidly try out an idea.
0015 %
0016 % Example (an inefficient representation of the oblique manifold (3, 10)):
0017 % Mn = powermanifold(spherefactory(3), 10)
0018 % disp(Mn.name());
0019 % x = Mn.rand()
0020 %
0021 % See also: productmanifold
0022 
0023 % This file is part of Manopt: www.manopt.org.
0024 % Original author: Nicolas Boumal, Dec. 30, 2012.
0025 % Contributors:
0026 % Change log:
0027 %   NB, July 4, 2013: Added support for vec, mat, tangent.
0028 %                     Added support for egrad2rgrad and ehess2rhess.
0029 
0030     
0031     assert(n >= 1, 'n must be an integer larger than or equal to 1.');
0032     
0033     Mn.name = @() sprintf('[%s]^%d', M.name(), n);
0034     
0035     Mn.dim = @() n*M.dim();
0036     
0037     Mn.inner = @inner;
0038     function val = inner(x, u, v)
0039         val = 0;
0040         for i = 1 : n
0041             val = val + M.inner(x{i}, u{i}, v{i});
0042         end
0043     end
0044 
0045     Mn.norm = @(x, d) sqrt(Mn.inner(x, d, d));
0046 
0047     Mn.dist = @dist;
0048     function d = dist(x, y)
0049         sqd = 0;
0050         for i = 1 : n
0051             sqd = sqd + M.dist(x{i}, y{i})^2;
0052         end
0053         d = sqrt(sqd);
0054     end
0055 
0056     Mn.typicaldist = @typicaldist;
0057     function d = typicaldist()
0058         sqd = 0;
0059         for i = 1 : n
0060             sqd = sqd + M.typicaldist()^2;
0061         end
0062         d = sqrt(sqd);
0063     end
0064     
0065     Mn.proj = @proj;
0066     function u = proj(x, u)
0067         for i = 1 : n
0068             u{i} = M.proj(x{i}, u{i});
0069         end
0070     end
0071     
0072     Mn.tangent = @tangent;
0073     function u = tangent(x, u)
0074         for i = 1 : n
0075             u{i} = M.tangent(x{i}, u{i});
0076         end
0077     end
0078     
0079     if isfield(M, 'tangent2ambient')
0080         Mn.tangent2ambient = @tangent2ambient;
0081     else
0082         Mn.tangent2ambient = @(x, u) u;
0083     end
0084     function u = tangent2ambient(x, u)
0085         for i = 1 : n
0086             u{i} = M.tangent2ambient(x{i}, u{i});
0087         end
0088     end
0089     
0090     Mn.egrad2rgrad = @egrad2rgrad;
0091     function g = egrad2rgrad(x, g)
0092         for i = 1 : n
0093             g{i} = M.egrad2rgrad(x{i}, g{i});
0094         end
0095     end
0096     
0097     Mn.ehess2rhess = @ehess2rhess;
0098     function h = ehess2rhess(x, eg, eh, h)
0099         for i = 1 : n
0100             h{i} = M.ehess2rhess(x{i}, eg{i}, eh{i}, h{i});
0101         end
0102     end
0103     
0104     Mn.exp = @expo;
0105     function x = expo(x, u, t)
0106         if nargin < 3
0107             t = 1.0;
0108         end
0109         for i = 1 : n
0110             x{i} = M.exp(x{i}, u{i}, t);
0111         end
0112     end
0113     
0114     Mn.retr = @retr;
0115     function x = retr(x, u, t)
0116         if nargin < 3
0117             t = 1.0;
0118         end
0119         for i = 1 : n
0120             x{i} = M.retr(x{i}, u{i}, t);
0121         end
0122     end
0123     
0124     if isfield(M, 'log')
0125         Mn.log = @loga;
0126     end
0127     function u = loga(x, y)
0128         u = cell(n, 1);
0129         for i = 1 : n
0130             u{i} = M.log(x{i}, y{i});
0131         end
0132     end
0133     
0134     Mn.hash = @hash;
0135     function str = hash(x)
0136         str = '';
0137         for i = 1 : n
0138             str = [str M.hash(x{i})]; %#ok<AGROW>
0139         end
0140         str = ['z' hashmd5(str)];
0141     end
0142 
0143     Mn.lincomb = @lincomb;
0144     function x = lincomb(x, a1, u1, a2, u2)
0145         if nargin == 3
0146             for i = 1 : n
0147                 x{i} = M.lincomb(x{i}, a1, u1{i});
0148             end
0149         elseif nargin == 5
0150             for i = 1 : n
0151                 x{i} = M.lincomb(x{i}, a1, u1{i}, a2, u2{i});
0152             end
0153         else
0154             error('Bad usage of powermanifold.lincomb');
0155         end
0156     end
0157 
0158     Mn.rand = @rand;
0159     function x = rand()
0160         x = cell(n, 1);
0161         for i = 1 : n
0162             x{i} = M.rand();
0163         end
0164     end
0165 
0166     Mn.randvec = @randvec;
0167     function u = randvec(x)
0168         u = cell(n, 1);
0169         for i = 1 : n
0170             u{i} = M.randvec(x{i});
0171         end
0172         u = Mn.lincomb(x, 1/sqrt(n), u);
0173     end
0174 
0175     Mn.zerovec = @zerovec;
0176     function u = zerovec(x)
0177         u = cell(n, 1);
0178         for i = 1 : n
0179             u{i} = M.zerovec(x{i});
0180         end
0181     end
0182 
0183     if isfield(M, 'transp')
0184         Mn.transp = @transp;
0185     end
0186     function u = transp(x1, x2, u)
0187         for i = 1 : n
0188             u{i} = M.transp(x1{i}, x2{i}, u{i});
0189         end
0190     end
0191 
0192     if isfield(M, 'pairmean')
0193         Mn.pairmean = @pairmean;
0194     end
0195     function y = pairmean(x1, x2)
0196         y = cell(n, 1);
0197         for i = 1 : n
0198             y{i} = M.pairmean(x1{i}, x2{i});
0199         end
0200     end
0201 
0202     % Compute the length of a vectorized tangent vector of M at x, assuming
0203     % this length is independent of the point x (that should be fine).
0204     if isfield(M, 'vec')
0205         rand_x = M.rand();
0206         zero_u = M.zerovec(rand_x);
0207         len_vec = length(M.vec(rand_x, zero_u));
0208 
0209         Mn.vec = @vec;
0210         
0211         if isfield(M, 'mat')
0212             Mn.mat = @mat;
0213         end
0214         
0215     end
0216     
0217     function u_vec = vec(x, u_mat)
0218         u_vec = zeros(len_vec, n);
0219         for i = 1 : n
0220             u_vec(:, i) = M.vec(x{i}, u_mat{i});
0221         end
0222         u_vec = u_vec(:);
0223     end
0224 
0225     function u_mat = mat(x, u_vec)
0226         u_mat = cell(n, 1);
0227         u_vec = reshape(u_vec, len_vec, n);
0228         for i = 1 : n
0229             u_mat{i} = M.mat(x{i}, u_vec(:, i));
0230         end
0231     end
0232 
0233     if isfield(M, 'vecmatareisometries')
0234         Mn.vecmatareisometries = M.vecmatareisometries;
0235     else
0236         Mn.vecmatareisometries = @() false;
0237     end
0238 
0239 end

Generated on Sat 12-Nov-2016 14:11:22 by m2html © 2005