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()

## CROSS-REFERENCE INFORMATION

This function calls:
• hashmd5 Computes the MD5 hash of input data.
• lincomb Computes a linear combination of tangent vectors in the Manopt framework.
This function is called by:
• complextest_AD2 Test AD for a complex optimization problem on a power manifold (cell)
• complextest_AD3 Test AD for a complex optimization problem on a manifold which is stored
• realtest_AD2 Test AD for a real optimization problem on a power manifold (cell)
• realtest_AD3 Test AD for a real optimization problem on a manifold which is stored in

## 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 %
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.
0031 %
0032 %   Feb. 10, 2020 (NB):
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
0107                ['Power manifolds call M.egrad2rgrad with only two ', ...
0108                 'inputs:\nstoredb and key won''t be available.']);
0109     end
0112         for i = 1 : n
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