function [dsav, xsav, itssav, rhosav] = ... sddtensor(A, kmax, alphamin, lmax, rhomin) %SDDTENSOR Semidiscrete Tensor Decomposition. % [D, X] = SDDTENSOR(A) produces discrete matrices stored in the cell % array X and a vector D that can be used to generate the 10-term tensor % SDD that approximates A. The X cell array is formatted as follows: the % first cell holds the component of each decomposed vectors from the first % dimension, the second cell goes with the second dimension, and so % on. The kth term of the SDD would be given by D(k) times the outer % product of X{1}(:,K) x X{2}(:,k) x ... x X{n}(:,k) where n is the order % of A. If A were a simple matrix, then X{1} and X{2} would be equivalent, % respectively, to the X and Y generated by the regular SDD routine. % % [D, X, ITS] = SDDTENSOR(...) also returns the number of inner % iterations for each outer iteration. % % [D, X, ITS, RHO] = SDDTENSOR(...) also returns a vector RHO containing % the norm-squared of the residual after each outer iteration. % % [...] = SDDTENSOR(A, K) produces a K-term tensor SDD. The default is 10. % % [...] = SDDTENSOR(A, K, TOL) stops the inner iterations after the % improvement is less than TOL. The default is 0.01. % % [...] = SDDTENSOR(A, K, TOL, L) specifies that the maximum number of % inner iterations is L. The default is 10. % % [...] = SDDTENSOR(A, K, TOL, L, R) produces an SDD approximation that % either has K terms or such that norm(A - B, 'fro') < R where B is the % tensor SDD approximation. The default is zero. % % %SDDPACK: Software for the Semidiscrete Decomposition. %Copyright (c) 1999 Tamara G. Kolda and Dianne P. O'Leary. % This program is free software; you can redistribute it and/or modify it % under the terms of the GNU General Public License as published by the Free % Software Foundation; either version 2 of the License, or (at your option) % any later version. % % This program is distributed in the hope that it will be useful, but % WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY % or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License % for more details. % % You should have received a copy of the GNU General Public License along % with this program; if not, write to the Free Software Foundation, Inc., 59 % Temple Place - Suite 330, Boston, MA 02111-1307, USA. %%% Check Input Arguments if ~exist('A') error('Incorrect number of inputs.'); end if ~exist('kmax') kmax = 10; end if ~exist('alphamin') alphamin = 0.01; end if ~exist('lmax') lmax = 10; end if ~exist('rhomin') rhomin = 0; else rhomin = rhomin^2; end %%% Initialization n = ndims(A); % order of A m = size(A); % vector of dimensions of A tmp = A .* A; % compute residual norm squared for j = 1 : n tmp = sum(tmp); end rho = tmp; clear tmp; iitssav = []; %%% Outer Loop for k = 1 : kmax %%% Initialize y for Inner Loop x = cell(n,1); for j = 1 : n x{j} = ones(m(j),1); end %%% Inner Loop for l = 1 : lmax for j = 1 : n s = product(A, x, j); [x{j}, xcnt(j), tmp] = sddtsolve(s, m(j)); end %%% Check Progress Axsqr = tmp * xcnt(n); beta = Axsqr / prod(xcnt); if (l > 1) alpha = (beta - betabar) / betabar; if (alpha <= alphamin) break end end betabar = beta; end % l-loop %%% Save d = sqrt(Axsqr) / prod(xcnt); A = A - d * expand(x); for j = 1 : n xsav{j}(:,k) = x{j}; end dsav(k, 1) = d; rho = max([rho - beta, 0]); rhosav(k) = rho; itssav(k) = l; %%% Threshold Test if (rho < rhomin) break; end end % k-loop return %----------------------------------------------------------------------% function B = expand(x) %EXPAND Expand a decomposed tensor to a full tensor. % % B = EXPAND(X) returns B, a full tensor, that is the result of the outer % product of all the elements of X. % %For use with SDDTENSOR. %Tamara G. Kolda, Oak Ridge National Laboratory, 1999. %Dianne P. O'Leary, University of Maryland and ETH, 1999. n = size(x, 1); for j = 1 : n m(j) = size(x{j}, 1); end tmp = x{1}; for j = 2 : n tmp = tmp * x{j}'; tmp = reshape(tmp, prod(m(1:j)), 1); end B = reshape(tmp, m); %----------------------------------------------------------------------% function s = product(A,x,idx) %PRODUCT Product (contracted) of a tensor and decomposed tensor. % % S = PRODUCT(A,X) computes the inner product of a tesnor A with a % decomposed tensor X. S is a scalar. % % S = PRODUCT(A,X,I) computes the contracted inner product of a tensor A % with a decomposed tensor X without its Ith component. % %For use with SDDTENSOR. %Tamara G. Kolda, Oak Ridge National Laboratory, 1999. %Dianne P. O'Leary, University of Maryland and ETH, 1999. if exist('idx') str = 'tmp = squeeze(A('; for i = 1 : ndims(A) if i == idx str = [str 'i']; else str = [str ':']; end if i == ndims(A) str = [str '));']; else str = [str ',']; end end jj = [1 : idx-1, idx+1 : ndims(A)]; for i = 1 : size(A, idx) eval(str); if ndims(A) == 2 n = 1; m = length(tmp); else n = ndims(tmp); m = size(tmp); end for j = n : -1 : 1 tmp = reshape (tmp, prod(m(1 : j-1)), m(j)); tmp = tmp * x{jj(j)}; end s(i) = tmp; end else tmp = A; n = ndims(tmp); m = size(tmp); for j = n : -1 : 1 tmp = reshape (tmp, prod(m(1 : j-1)), m(j)); tmp = tmp * x{j}; end s = tmp; end %----------------------------------------------------------------------% function [x, imax, fmax] = sddtsolve(s, m) %SDDTSOLVE Solve SDD subproblem % [X] = SDDTSOLVE(S, M) computes max(X'S)/(X'X) where M is the size of S. % % [X, I] = SDDTSOLVE(S, M) additionally returns number of nonzeros in X. % % [X, I, F] = SDDTSOLVE(S, M) additionally returns value of function at % the optimum. % %For use with SDDTENSOR. %Tamara G. Kolda, Oak Ridge National Laboratory, 1999. %Dianne P. O'Leary, University of Maryland and ETH, 1999. for i = 1 : m if s(i) < 0 x(i, 1) = -1; s(i) = -s(i); else x(i, 1) = 1; end end [sorts, indexsort] = sort(-s); sorts = -sorts; clear f f(1) = sorts(1); for i = 2 : m f(i) = sorts(i) + f(i - 1); end f = (f.^2) ./ [1:m]; imax = 1; fmax = f(1); for i = 2 : m if f(i) >= fmax imax = i; fmax = f(i); end end for i = (imax + 1) : m x(indexsort(i)) = 0; end return