subsasgn.m

来自「张量分析工具」· M 代码 · 共 282 行

M
282
字号
function t = subsasgn(t,s,rhs)%SUBSASGN Subscripted assignment for sparse tensor.%%   We can assign elements to a sptensor in three ways.%%   Case 1: X(R1,R2,...,RN) = Y, in which case we replace the%   rectangular subtensor (or single element) specified by the ranges%   R1,...,RN with Y. The right-hand-side can be a scalar or an%   sptensor. %%   Case 2: X(S) = V, where S is a p x n array of subscripts and V is%   a scalar value or a vector containing p values.%%   Linear indexing is not supported for sparse tensors.%%   Examples%   X = sptensor([30 40 20]) %<-- Create an emtpy 30 x 40 x 20 sptensor%   X(30,40,20) = 7 %<-- Assign a single element to be 7%   X([1,1,1;2,2,2]) = 1 %<-- Assign a list of elements to the same value%   X(11:20,11:20,11:20) = sptenrand([10,10,10],10) %<-- subtensor!%   X(31,41,21) = 7 %<-- grows the size of the tensor%   X(111:120,111:120,111:120) = sptenrand([10,10,10],10) %<-- grows%   X(1,1,1,1) = 4 %<-- increases the number of dimensions from 3 to 4%%   X = sptensor([30]) %<-- empty one-dimensional tensor%   X([4:6]) = 1 %<-- set subtensor to ones (does not increase dimension)%   X([10;12;14]) = (4:6)'  %<-- set three elements%   X(31) = 7 %<-- grow the first dimension%   X(1,1) = 0 %<-- add a dimension, but no nonzeros%%   See also SPTENSOR, TENSOR/SUBSASGN.%%MATLAB Tensor Toolbox.%Copyright 2007, Sandia Corporation.% This is the MATLAB Tensor Toolbox by Brett Bader and Tamara Kolda.% http://csmr.ca.sandia.gov/~tgkolda/TensorToolbox.% Copyright (2007) Sandia Corporation. Under the terms of Contract% DE-AC04-94AL85000, there is a non-exclusive license for use of this% work by or on behalf of the U.S. Government. Export of this data may% require a license from the United States Government.% The full license terms can be found in tensor_toolbox/LICENSE.txt% $Id: subsasgn.m,v 1.16 2007/01/10 01:27:31 bwbader Exp $switch s.type    case '.'        error(['Cannot change field ', s.subs, ' directly.']);    case '()'        % Do nothing if both subscripts and RHS are empty        if isempty(s.subs{1}) && isempty(t.vals)            return;        end        % Figure out if we are doing a subtensor or a list of subscripts...        type = 'error';               if ndims(t) == 1             % Multiple subscripts *or* row vector -> subtensor            if (numel(s.subs) > 1) ...                    || (ndims(s.subs{1}) == 2 && size(s.subs{1},1) == 1)                type = 'subtensor';            % Column vector *or* matrix of subscripts -> subscripts            elseif (ndims(s.subs{1}) == 2)                type = 'subscripts';            end        else            % Multiple subscripts -> subtensor            if numel(s.subs) >= ndims(t)                type = 'subtensor';            % Matrix of subscripts -> subscripts            elseif (ndims(s.subs{1}) == 2) && (size(s.subs{1},2) >= ndims(t))                type = 'subscripts';            end        end                % Case I: Replace a sub-tensor        if isequal(type,'subtensor')                                 % Resize the tensor!            for n = 1:ndims(t)                if ischar(s.subs{n}) && (s.subs{n} == ':')                    newsz(1,n) = t.size(n);                else                    newsz(1,n) = max([t.size(n) s.subs{n}]);                end            end            for n = ndims(t)+1:numel(s.subs)                newsz(1,n) = max(s.subs{n});            end            t.size = newsz;            % Resize existing subscripts if needed            if ~isempty(t.subs) && (size(t.size,2) > size(t.subs,2))                t.subs(:,end+1:size(t.size,2)) = 1;            end            if isa(rhs,'sptensor')                % Delete what currently occupies the specified range                rmloc = subdims(s.subs,t);                kploc = setdiff(1:nnz(t),rmloc);                newsubs = t.subs(kploc,:);                newvals = t.vals(kploc);                % Renumber the subscripts                addsubs = irenumber(rhs, t.size, s.subs);                t.subs = [newsubs; addsubs];                t.vals = [newvals; rhs.vals];                            elseif numel(rhs) == 1 && rhs == 0                % Delete what currently occupies the specified range                rmloc = subdims(s.subs,t);                kploc = setdiff(1:nnz(t),rmloc);                t.subs = t.subs(kploc,:);                t.vals = t.vals(kploc);                           elseif numel(rhs) == 1                                % Determine number of dimensions (may be larger than                % current number)                N = numel(s.subs);                                 % Figure out how many indices are in each dimension                nssubs = zeros(N,1);                for n = 1:N                    if ischar(s.subs{n}) && s.subs{n} == ':'                        s.subs{n} = 1:size(t,n);                    end                    nssubs(n) = numel(s.subs{n});                end                                % Preallocate (discover any memory issues here!)                addsubs = zeros(prod(nssubs),N);                % Generate appropriately sized ones vectors.                o = cell(N,1);                for n = 1:N                    o{n} = ones(nssubs(n),1);                end                % Generate each column of the subscripts in turn                for n = 1:N                    i = o;                    i{n} = s.subs{n}';                    addsubs(:,n) = khatrirao(i);                end                                if ~isempty(t.subs)                    % replace existing values                    [junk,loc] = intersect(t.subs,addsubs,'rows');                    t.vals(loc) = rhs;                    % pare down list of subscripts to add                    addsubs = setdiff(addsubs,t.subs,'rows');                end                t.subs = [t.subs; addsubs];                t.vals = [t.vals; rhs*ones(size(addsubs,1),1)];            else                error('Invalid RHS')            end            return;        elseif isequal(type,'subscripts')            % Case II: Replacing values at specified indices            newsubs = [s.subs{1}];            tt_subscheck(newsubs);            % Error check on subscripts            if size(newsubs,2) < ndims(t)                error('Invalid subscripts');            end                        % Check for expanding the order            if size(newsubs,2) > ndims(t)                t.size(end+1:size(newsubs,2)) = 1;                if ~isempty(t.subs)                    t.subs(:,end+1:size(newsubs,2)) = 1;                end            end            % Copy rhs to newvals            newvals = rhs;            % Error check the RHS is a column vector. We do not bother to            % handle any other type of RHS with the sparse tensor.            tt_valscheck(newvals);            % Determine number of nonzeros being inserted. (This is            % determined by the number of subscripts. Later we will check            % to see that it matches the size of the RHS.)            newnnz = size(newsubs,1);            % Error check on size of newvals            if numel(newvals) == 1                % Special case where newvals is a single element to be                % assigned to multiple RHS. Fix to be correct size.                newvals = newvals * ones(newnnz,1);            elseif size(newvals,1) ~= newnnz                % Sizes don't match!                error('Number of subscripts and number of values do not match!');            end            % Remove duplicates & print warning if any duplicates were            % removed.            [newsubs,idx] = unique(newsubs,'rows');            if size(newsubs,1) ~= newnnz                warning('Duplicate assignments discarded.');            end            newvals = newvals(idx);            % Find which subscripts already exist and their locations            [tf,loc] = ismember(newsubs,t.subs,'rows');            % Split into three groups for processing:            %            % Group A: Elements that already exist and need to be changed            % Group B: Elements that already exist and need to be removed            % Group C: Elements that do not exist and need to be added            %            % Note that we are ignoring any new zero elements, because            % those obviously do not need to be added. Also, it's            % important to process Group A before Group B because the            % processing of Group B may change the locations of the            % remaining elements.            idxa = find((tf .* newvals) ~= 0);            idxb = find((tf .* ~newvals) ~= 0);            idxc = find((~tf .* newvals) ~= 0);            % Process Group A: Changing values            if ~isempty(idxa)                t.vals(loc(idxa)) = newvals(idxa);            end            % Process Group B: Removing values            if ~isempty(idxb)                removesubs = loc(idxb);                keepsubs = setdiff(1:nnz(t),removesubs);                t.subs = t.subs(keepsubs,:);                t.vals = t.vals(keepsubs);            end            % Process Group C: Adding new, nonzero values            if ~isempty(idxc)                t.subs = [t.subs; newsubs(idxc,:)];                t.vals = [t.vals; newvals(idxc)];            end            % Resize the tensor!            for n = 1:length(t.size)                smax = max(newsubs(:,n));                t.size(n) = max(t.size(n), smax);            end            return;        end                error('Invalid call to sptensor/subsasgn');    case '{}'        error('Subscript cell reference not supported for sptensor.');    otherwise        error('Incorrect indexing into sptensor.')end

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?