No BSD License  

Highlights from
PARTPERM -- Partial random permutation of a vector

from PARTPERM -- Partial random permutation of a vector by David Fass
Partial random permutation of a vector.

partperm(x,idx,varargin)
function xPerm = partperm(x,idx,varargin)
%PARTPERM Partial random permutation of a vector.
%
%   X = PARTPERM(A,IDX) randomly permutes the elements of vector A which are 
%   specified by vector IDX.  That is, the elements A(IDX) are randomly
%   interchanged with one another and the resulting (partially permuted) vector 
%   is returned.  No permutation occurs when length(IDX) < 2.
%   
%   By default, the permutation is a "derangement"; that is, no element
%   specified by IDX will appear in its original position.  (The derangement
%   of the specified elements is ensured by repeatedly generating and testing
%   candidate permutation vectors within a WHILE loop.  I have not really
%   thought about the tractability of this approach, but as I understand
%   the MathWorld article <http://mathworld.wolfram.com/Derangement.html>,
%   the probability of a successful derangement under random permutation
%   asymptotes at 1/e ~ .37, so about 1 out of 3 attempted permutations should
%   produce a valid derangement.  Hopefully the WHILE loop is therefor not
%   such a terrible approach.)
% 
%   To disable this "derangement" constraint and thereby allow permuted elements
%   to reappear in their original positions, use the following syntax:
% 
%   X = PARTPERM(A,IDX,'allow') randomly permutes the elements of vector A which
%   are specified by vector IDX, but allows indexed elements to remain unchanged 
%   if that is the natural result of the random permutation (i.e., if after 
%   permutation an element's new location happens to be the same as its original
%   location).
%
%   See also RANDPERM.
%

if isempty(idx) | length(idx)==1,
    xPerm = x;
    %warning('No permutation requested.') 
    return
end
if ~isequal(prod(size(x)),length(x)),
    error('Input X must be a vector.')
end
if ~isequal(prod(size(idx)),length(idx)),
    error('Input IDX must be a vector.')
end

sizeXorig = size(x);
x = x(:);     % Columnize
idx = idx(:);

numPerm = length(idx);
candidatePerm = 1:numPerm;

if isempty(varargin),
    % Find an appropriate permutation of the selected indices...
    % none the same as the original.
    whileCnt = 0;
    while any(candidatePerm == 1:numPerm),
        whileCnt = whileCnt + 1;
        if rem(whileCnt,50) == 0,
            disp(['Tested ' num2str(whileCnt) ' candidates. Searching for identity-free permutation...'])
        end
        candidatePerm = randperm(numPerm);
    end
elseif strcmp(varargin{1},'allow'),
    candidatePerm = randperm(numPerm);
else 
    error('Use flag ''allow'' to permit identities.')
end

idxPerm = idx(candidatePerm);
xPerm = x;
xPerm(idxPerm) = x(idx);
xPerm = reshape(xPerm,sizeXorig);

Contact us at files@mathworks.com