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 %
0028 %   July  4, 2013 (NB):
0029 %       Added support for vec, mat, tangent.
0030 %       Added support for egrad2rgrad and ehess2rhess.
0031 %
0032 %   Feb. 10, 2020 (NB):
0033 %       Added warnings about calling egrad2rgrad and ehess2rhess without
0034 %       storedb and key, even if the base manifold allows them.
0035 %
0036 %   Jan. 4, 2021 (NB):
0037 %       Changes for compatibility with Octave 6.1.0: see len_vec.
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})]; %#ok<AGROW>
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     % Compute the length of a vectorized tangent vector of M at x, assuming
0228     % this length is independent of the point x (that should be fine).
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

Generated on Fri 30-Sep-2022 13:18:25 by m2html © 2005