1+ function  similarities  =  computeSubspacesSimilarities(X , Y , varargin )
2+ %  computeSubspacesSimilarities: Compute similarities between sets of subspaces.
3+ %  This function calculates the similarities between two sets of subspaces represented
4+ %  by multi-dimensional arrays X and Y. The similarity is defined based on the squared
5+ %  singular values of the cross-covariance matrix of the subspaces.
6+ % 
7+ %  Parameters:
8+ %  X: A num_dim_x x num_sub_dim_x x num_sets_x 3D matrix representing the first set of subspaces.
9+ %  - num_dim_x: dimension of the original vector space.
10+ %  - num_sub_dim_x: dimension of each subspace in X.
11+ %  - num_sets_x: number of subspaces in X.
12+ % 
13+ %  Y: A num_dim_y x num_sub_dim_y x num_sets_y 3D matrix representing the second set of subspaces.
14+ %  - num_dim_y: dimension of the original vector space.
15+ %  - num_sub_dim_y: dimension of each subspace in Y.
16+ %  - num_sets_y: number of subspaces in Y.
17+ % 
18+ %  varargin: A string flag that determines the method of computation.
19+ %  - If not specified or empty, similarities are based on the average of cos^2 theta,
20+ %  computed efficiently using the trace of the cross-covariance matrix.
21+ %  - If set to 'F', the function uses Singular Value Decomposition (SVD) to compute all
22+ %  canonical angles and outputs both the average and the cos^2 of the first theta.
23+ % 
24+ %  Return:
25+ %  similarities: A 4D matrix containing the computed similarities.
26+ %  - size: num_sets_x x num_sets_y x num_sub_dim_x x num_sub_dim_y.
27+ %  - Each element (i, j, k, l) represents the similarity between the k-th subspace of the
28+ %  i-th set in X and the l-th subspace of the j-th set in Y.
29+ %  - if vargin is set to 'F', similarities becomes a 3D matrix of size
30+ %  num_sets_x x num_sets_y x min(num_sub_dim_x, num_sub_dim_y).
31+ % 
32+ %  Example Usage:
33+ %  sim = computeSubspacesSimilarities(X, Y);
34+ %  % Computes the subspace similarities between X and Y using the default method.
35+ % 
36+ %  sim = computeSubspacesSimilarities(X, Y, 'F');
37+ %  % Computes the subspace similarities using SVD for all canonical angles.
38+ % 
39+ %  Notes:
40+ %  - The function normalizes the similarity by the number of singular values used in the computation.
41+ %  - For high-dimensional data, using the default method (without 'F') is computationally more efficient.
42+ % 
43+ %  Last Update: 2023/10 by Santos Enoque
44+ %  Computer Vision Laboratory, University of Tsukuba
45+ %  http://www.cvlab.cs.tsukuba.ac.jp/
46+ 
47+ x_size =  size(X );
48+ x_size =  length(x_size );
49+ y_size =  size(Y );
50+ y_size =  length(y_size );
51+ %  Check if the size of any of the subspaces is less than 3 or greater than 4
52+ if  any(x_size  <  3  |  x_size  >  4 ) ||  any(y_size  <  3  |  y_size  >  4 )
53+  error(' The size of each subspace must be greater than or equal to 3 and less than or equal to 4.' 
54+ end 
55+ 
56+ use_svd =  false ;
57+ 
58+ %  Check if an additional input argument is provided
59+ if  nargin  ==  3 
60+  %  If the additional input argument is 'F', set the flag for using SVD to true
61+  if  varargin{1 } ==  ' F' 
62+  use_svd =  true ;
63+  end 
64+ end 
65+ %  Ensure X and Y are 3D matrices, even if they are 4D initially
66+ X =  X(: ,: ,: );
67+ Y =  Y(: ,: ,: );
68+ 
69+ %  Get dimensions information of input subspaces X and Y
70+ [~ , num_dim_x , num_sets_x ] =  size(X );
71+ [~ , num_dim_y , num_sets_y ] =  size(Y );
72+ 
73+ %  If SVD is not used, compute similarities using cross-covariance
74+ if  ~use_svd 
75+  %  Compute the squared cross-covariance matrix and reshape it to a 4D matrix
76+  cross_cov_squared =  reshape((X(: ,: )'  *  Y(: , : )).^2 , num_dim_x , num_sets_x , num_dim_y , num_sets_y );
77+  
78+  %  Cumulatively sum the squared cross-covariance matrix along dimensions
79+  similarities =  cumsum(cumsum(cross_cov_squared , 1 ), 3 );
80+  
81+  %  Normalize the similarities by the minimum dimension between X and Y subspaces
82+  for  i =  1 : num_dim_x 
83+  for  j =  1 : num_dim_y 
84+  similarities(i , : , j , : ) =  similarities(i , : , j , : ) /  min([i , j ]);
85+  end 
86+  end 
87+  
88+  %  Rearrange dimensions of the similarities matrix for consistent output format
89+  similarities =  permute(similarities , [2 , 4 , 1 , 3 ]);
90+  
91+  %  If SVD is used, compute similarities using singular values
92+ else 
93+  %  Compute the cross-covariance matrix and reshape it to a 4D matrix
94+  cross_cov =  reshape((X(: ,: )'  *  Y(: , : )), num_dim_x , num_sets_x , num_dim_y , num_sets_y );
95+  
96+  %  Rearrange dimensions of the cross-covariance matrix for consistent computation
97+  cross_cov =  permute(cross_cov , [1 , 3 , 2 , 4 ]);
98+  
99+  %  Initialize the similarities matrix with zeros
100+  num_dim =  min([num_dim_x , num_dim_y ]);
101+  similarities =  zeros(num_sets_x , num_sets_y , num_dim );
102+  
103+  %  Compute cumulative sum of squared singular values for each pair of subspaces
104+  for  i =  1 : num_sets_x 
105+  for  j =  1 : num_sets_y 
106+  similarities(i , j , : ) =  cumsum(svd(cross_cov(: , : , i , j )).^2 , 1 );
107+  end 
108+  end 
109+  
110+  %  Normalize the similarities by the dimensionality
111+  for  i =  1 : num_dim 
112+  similarities(: , : , i ) =  similarities(: , : , i ) /  i ;
113+  end 
114+ end 
115+ end 
0 commit comments