gusucode.com > qit_matlab_0.10.0工具箱源码程序 > qit/@lmap/reorder.m

    function [s] = reorder(s, perm)
% REORDER  Change the relative order of subsystems in an lmap.
%  [S] = reorder(T, perm);
%    reorder(T, {[], [3 2 1]}); % ignore first index, reverse the order of subsystems in the second
%    reorder(T, {[5 2]});       % swap subsystems 2 and 5 in the first index
%
%  Reorders the subsystems of the lmap T according to permutation
%  cell vector perm == {p_1, p_2, ...}.
%  perm contains one permutation vector p_i for each index i of T.
%  If there are more indices than permutation vectors, the extra indices remain untouched.
%
%  The contents of each permutation vector p_i may be either empty (nothing is done to that index), 
%  exactly two subsystem numbers (to be swapped), or a full permutation of subsystem numbers.
%  Two subsystems to be swapped must be in decreasing order so as not
%  to mistake the full identity permutation [1 2] for a swap.
%
%  NOTE: The full permutations are interpreted in the same sense as the
%  MATLAB function permute() understands them, i.e. the permutation
%  vector is the new ordering of the old subsystem indices.
%  This is the inverse of the mathematically more common "one-line" notation.

% Ville Bergholm 2009-2011


% number of indices
n_ind = order(s);

if (length(perm) < n_ind)
  perm{n_ind} = []; % all missing permutations filled in with []
end

total_d = [];
total_perm = [];
last_used_index = 0;

% loop over indices
for k = 1:n_ind

  this_perm = perm{k};  % requested subsystem permutation for this index
  this_dim  = s.dim{k}; % subsystem dims for this index

  % number of subsystems
  n = length(this_dim);

  % total dimension
  dd(k) = prod(this_dim);

  % avoid a subtle problem with the input syntax
  if isequal(this_perm, [1 2])
    this_perm = [];
  end

  temp = 1:n;
  switch (length(this_perm))
    case 0
      % [], no change
      % let the dimensions vector be, lump all subsystems in this index into one
      this_dim = dd(k);
      this_perm = 1;
      n = 1;

    case 2
      % swap two subsystems
      temp(this_perm(1)) = this_perm(2);
      temp(this_perm(2)) = this_perm(1);
      this_perm = temp;

      s.dim{k} = this_dim(this_perm); % reorder the dimensions vector

    otherwise
      % full permutation
      if (length(setxor(temp, this_perm)) ~= 0)
        error('Invalid permutation for index %d.', k);
      end

      s.dim{k} = this_dim(this_perm); % reorder the dimensions vector
  end

  % big-endian ordering is more natural for users, but Matlab funcs
  % prefer little-endian, so we reverse it
  total_d    = [total_d,    fliplr(this_dim)];
  total_perm = [total_perm, last_used_index + fliplr(n+1 -this_perm)];
  last_used_index = last_used_index + n;
end


T = full(s.data); % FIXME Matlab 7.6 reshape is broken (sparse matrices cause problems with singleton dimensions)

% tensor into another tensor which has one index per subsystem, permute dimensions, back into a tensor with the original number of indices
s.data = reshape(permute(reshape(T, total_d), total_perm), [dd 1]);