📄 chainmult.m
字号:
q.Lvar=node(1:i); q.Rvar=node(i+1:end); if ~isempty(field), y=orig; y=setfield(y,field{:},q); else y=q; end TreeStack('push',y); end stop=1; % forked new trees on stack endelse y=node; [y.Lvar,stop]=SplitOneLevel(node.Lvar,[idx 1],stop); if (stop~=1), stop=0; % Must reset to 0, since it could be -1 at this point [y.Rvar,stop]=SplitOneLevel(node.Rvar,[idx 2],stop); if (stop~=1), stop=-1; y=node; % we're done with this tree end endend% ==================================================================================% genFwdStruct:% Generate structure describing forward-chain only.% Use for non-optimized case.% ==================================================================================function list = genFwdStruct(N)if N==0, list={};elseif N==1, list = {'A'};else c = char('A'+(0:N-1)); list.Lvar = c(1); list.Rvar = c(2); for i=3:N, y.Lvar = list; y.Rvar = c(i); list=y; end endlist={list};% ==================================================================================% TreeStack:% Implement a stack that can hold structure trees.% ==================================================================================function [t,ok]=TreeStack(op,push)persistent trees;if ~iscell(trees), trees={}; endok = 1;switch opcase 'pop' % pop if isempty(trees), ok=0; t=[]; trees={}; else t=trees{end}; trees=trees(1:end-1); endcase 'push' trees(end+1)={push}; t=trees;case 'query' t=trees;case 'reset' trees={}; t=trees;otherwise, error('Unknown operation requested.');end% ==================================================================================% convertCell2Str:% Print the chain multiply permutation expression.%% chain is a vector cell array of 3-element vector indices% describing the chain multiplication.%% varNames is an optional cell string array containing one% string per variable name. These variable names are used% during construction of the MATLAB string expressions.% If omitted, variable names are 'A', B', ...% Ex:% {[4 5 -1] [3 -1 -2] [2 -2 -1] [1 -1 0]} % A * (B * (C*(D*E)))% {[3 4 -1] [-1 5 -2] [2 -2 -1] [1 -1 0]} % A * (B * ((C*D)*E))% {[2 3 -1] [-1 4 -2] [-2 5 -1] [1 -1 0]} % A * (((B*C)*D) * E)% {[3 4 -1] [2 -1 -2] [-2 5 -1] [1 -1 0]} % A * ((B*(C*D)) * E)% {[2 3 -1] [4 5 -2] [-1 -2 -3] [1 -3 0]} % A * ((B*C) * (D*E))% ==================================================================================function str = convertCell2Str(chain,varNames)if nargin<2 || isempty(varNames), % Generate as many default variable names as required % % xxx Find max non-temporary (positive) index specified % across all input vectors: varNames = cellstr(char(double('A') + (0:25))');endstr = '';temp_strs = {};for i=1:length(chain), x1_idx = chain{i}(1); % x1 matrix index x2_idx = chain{i}(2); % x2 matrix index if length(chain{i})==3, % skip single-input case x12_idx = chain{i}(3); % x12 result index % Get size vectors of x1 and x2 % Each size vector specifies [rows cols] ch1 = getMatrixStr(x1_idx, temp_strs, varNames); ch2 = getMatrixStr(x2_idx, temp_strs, varNames); % Multiply these together: if x12_idx == 0, % Last operation: str = ['Y = ' ch1 '*' ch2 ';']; else temp_strs{-x12_idx} = ['(' ch1 '*' ch2 ')']; end else % 2-input case: ch1 = getMatrixStr(x1_idx, temp_strs, varNames); str = ['Y = ' ch1 ';']; endend% -----------------------------------------------------------function x_str = getMatrixStr(x_idx, temp_strs, varNames)% getMatrixStr Return string for i'th matrix chain operation% temp_strs is a list of string expressions describing the% contents of each generated temp.if x_idx<0, % Get temporary-variable string expression: x_str = temp_strs{-x_idx}; elseif x_idx>0, % Return variable name of i'th input matrix % 1st = A, 2nd = B, etc. if x_idx>26, error('Too many input variables for prettyPrintVars.'); end % Get name for x_idx'th variable: % x_str = char(double('A') + x_idx-1); x_str = varNames{x_idx}; else error(['Input index to matrix multiplier pair cannot be ' ... 'specified as the output matrix (index 0).']);end% ==================================================================================% convertCell2Struct:% ==================================================================================function c = convertCell2Struct(chain)c={}; temp={};for i=1:length(chain), if length(chain{i})==3, % skip single-input case x1_idx = chain{i}(1); % x1 matrix index x2_idx = chain{i}(2); % x2 matrix index x12_idx = chain{i}(3); % x12 result index % Get references to input matrices % Use letter variable names, or % structure entry from temp storage: p.Lvar=getMatrixRef(x1_idx, temp); p.Rvar=getMatrixRef(x2_idx, temp); if x12_idx == 0, % output area specified for destination % we are done: c=p; else % A temporary storage area has been specified tempIdx = -x12_idx; % create positive temp index temp{tempIdx} = p; end endend% ----------------------------------------------------function x_ref = getMatrixRef(x_idx, temp_refs)% getMatrixRef%% Positive indices are taken to be input matrices,% negative indices are temp matrices.% The 0'th index is the output matrix, and is not available% for use in intermediate results (at least in the enumerated% specifications).% If index is negative, return size-vector from temp_sizes% Otherwise, return size-vector from matrix_sizesif x_idx<0, x_ref = temp_refs{-x_idx};elseif x_idx>0, x_ref = char('A'-1+x_idx);else error(['Input index to matrix multiplier pair cannot be ' ... 'specified as the output matrix (index 0).']);end% ==================================================================================% convertStruct2Cell:% Converts cell-array of structures in P (representing multiple enumerations% of the chain multiplication problem) into a cell-array of cell-arrays% of "program" vectors.% ==================================================================================function y=convertStruct2Cell(pc)% If this is one structure, wrap it in a cell-array:single_struct = ~iscell(pc);if single_struct, pc={pc};end% Is this a single-variable problem?if length(pc)==1, if ~isstruct(pc{1}), y={{[1 0]}}; return end end for i=1:length(pc), p=pc{i}; localRecursion(p,0); c=localRecursion(p,1); % Overwrite last result index with the output index (0): c{end}(3)=0; y{i}=c;end% Convert back from nested cells if needed:if single_struct, y=y{1};end% ------------------------------------------------function c=localRecursion(p,init)persistent Gtemp chainResult;if nargin>1, if init==0, Gtemp=[]; chainResult={}; else c=chainResult; return endendfreeList=[];% Get depth order:% [1 2] -> Left is deeper than Right% [2 1] -> Right is deeper than LeftDepthOrder = getDepthOrder(p);children = {p.Lvar p.Rvar};children = children(DepthOrder);for i=1:2, % Get "left" contribution % If .Lvar is a string, use it directly % If .Lvar is a struct, it's the child if isstruct(children{i}), % Get child computation's temp name c=localRecursion(children{i}); % c(3) is the destination result{i}=c(3); % numeric, neg. temp index % Consumed the temp variable % record index for free'ing after use freeList(end+1)=c(3); else result{i}=children{i}; end % Convert to # if a character: if ischar(result{i}), result{i} = result{i}-'A'+1; endend[T,Gtemp]=allocTemp(Gtemp);c = [result{DepthOrder} T];chainResult{end+1}=c;Gtemp=freeTemp(Gtemp,freeList);% ----------------------------------------------------function depthOrder= getDepthOrder(p)% Determine ordering of depth of subtree p% % [1 2] -> Left is deeper than Right% [2 1] -> Right is deeper than Left%depthOrder = [2 1];%depthOrder = [1 2];cntL=descendDepth(p.Lvar,0);cntR=descendDepth(p.Rvar,0);if cntL>=cntR, depthOrder = [1 2];else depthOrder = [2 1];end% ----------------------------------------------------function cnt = descendDepth(p,cnt)if isstruct(p), cntL = descendDepth(p.Lvar,cnt+1); cntR = descendDepth(p.Rvar,cnt+1); cnt = max(cntL,cntR);end% ----------------------------------------------------function Gtemp=freeTemp(Gtemp,idx)% Return temp variable - no longer being used:% Temp index is negative, and so are the entries% in the global temp list:if isempty(Gtemp), error('No temps in list - cannot free.');endfor j=1:length(idx), i=find(Gtemp==idx(j)); if isempty(i), error('Temp index not found - cannot free'); end Gtemp(i)=[];end% ----------------------------------------------------function [tnew,Gtemp]=allocTemp(Gtemp)% Determine index of next temp to use% Maintain cache of all active temp #'s in Gtempif ~isempty(Gtemp), % Get +ve # of all temps currently in use posTemp=-Gtemp; maxTemp=max(posTemp); % Determine all temps possible in this range tempList=1:maxTemp; % Find which ones were not used ("holes" in the temp list) unused = setdiff(tempList,posTemp); if ~isempty(unused), % Get lowest-numbered "hole" to use as a temp nextTemp=min(unused); else nextTemp=maxTemp+1; endelse nextTemp=1; % no temps used yetend% Use -ve # for temp:tnew=-nextTemp;% Put into global list:Gtemp(end+1)=tnew;% ==================================================================================% convertStruct2Str:% ==================================================================================function c=convertStruct2Str(p)L=p.Lvar;if isstruct(L), L=convertStruct2Str(L);endR=p.Rvar;if isstruct(R), R=convertStruct2Str(R);endc=['(' L '*' R ')'];% [EOF] chainmult.m
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -