例如:
B1 = 1*A1 + 2*A2;
B2 = 3*A1 + 4*A2;
B1,B2,A1,A2均为2乘2矩阵。
如何有效地定义B的矩阵?做类似的事情:
[B1;B2] = [1 2;3 4]*[A1;A2]
失败了。我想做这样的事情,因为我的任务不仅仅是定义两个矩阵,所以我可以手工输入。
答案 0 :(得分:7)
使用matrix-multiplication
我们假设有一个2D
数组scale
来存储缩放参数。所以,对于我们的情况,我们会有 -
scale = [1 2;3 4];
首先,让我们将A-matrices
叠加为3D阵列 -
A = cat(3,A1,A2); % Add more matrices here
最后,计算本身可以在重构为2D
之后实现为矩阵乘法,并且在矩阵乘法之后再进行一次整形以将那些B-matrices
堆叠为3D数组 -
B = reshape(reshape(A,4,[])*scale.',2,2,[])
答案 1 :(得分:5)
我使用类似于TroyHaskin的方法,但使用kron
:
A1 = 1i*ones(2); % Using imaginary numbers so the result is easier to verify visually.
A2 = magic(2); % [1,3; 4,2]
C = [1 2; 3 4];
B = sum(cat(3,kron(C(:,1),A1),kron(C(:,2),A2)),3);
B =
2.0000 + 1.0000i 6.0000 + 1.0000i
8.0000 + 1.0000i 4.0000 + 1.0000i
4.0000 + 3.0000i 12.0000 + 3.0000i
16.0000 + 3.0000i 8.0000 + 3.0000i
生成的B
数组包含B1
和B2
“垂直堆叠”(即沿着1 st 维度),使得B1 = B(1:2,:); B2 = B(3:4,:);
。
可以使用以下内容将Divakar建议重新整形为3d数组:
B_3D = permute(reshape(B,2,2,[]),[1,3,2]);
% ... or straight away using:
B_3D = permute(reshape(sum(cat(3,kron(C(:,1),A1),kron(C(:,2),A2)),3),2,2,[]),[1,3,2]);
如果您发现使用单元格更容易,B
可以使用以下内容转换为Nx1
2x2
矩阵B_C = mat2cell(B,2*ones(size(B,1)/2,1),2);
矩阵。
isequal(B_C{1}, 1*A1 + 2*A2)
ans =
1
isequal(B_C{2}, 3*A1 + 4*A2)
ans =
1
验证
{{1}}
答案 2 :(得分:3)
对我来说,一个相当直接的解决方案是沿着第三维执行标量乘法,然后为每一对组合系数 #Taking the first df1 into consideration which has 2017-Q1 as the last quarter
startQtr <- "2014-Q2" #This value is dynamically achieved and will change as we move ahead. Next quarter, the value changes to 2014-Q3 and so on
if(length(df1[["FISC_QTR_VAL"]][nrow(df1)-11] == startQtr) == 1){
if(nrow(df1[df1$Revenue < 0,]) == 0 & nrow(df1[df1$Revenue == 0,]) == 0){
df1 <- df1 %>% slice((nrow(df1)-11):(nrow(df1)))
}
}
它以产生一个单元阵列sum
。单元阵列源于B
的输出要求。
cellfun
答案 3 :(得分:-1)
使用varargin,varargout,repmat,repelem,diag ...制作一个三维数组(结果)并计算沿第三维的总和:
function varargout = linear_comb(coef,varargin)
if exist('repelem') == 0 % octave friendly
repelem = @(a,n) repelems(a,[1:numel(a);repmat(n,1,numel(a))]);
end
matdim = size(varargin{1},1);
Nvar = length(varargin);
Ncoef = size(coef, 1);
result = reshape( repmat(cell2mat(varargin),1,Ncoef) * diag(repelem(reshape(coef',1,numel(coef)),matdim)), [matdim,matdim, Nvar*Ncoef]);
for i = 1:Ncoef
varargout{i} = sum(result(:,:,Nvar*(i-1) +1:Nvar*i),3);
end
end
%%example
coef=[1 2 3;3 4 1;5 6 9;7 8 4];
a1=[1 2;3 4];a2=[5 6; 7 8];a3=[9 10;11 12];
[b1 b2 b3 b4]=linear_comb(coef,a1,a2,a3)
编辑:更多解释
通过矩阵对标量进行多重处理与对角矩阵的多重化相同,其对角线元素等于矩阵的标量。 所以在我们的例子中有2 * 2矩阵:a * A === diag([a a])* A;
a * A === diag(repelem(a,size(A,1)))* A;
所有其他的东西都是重塑和重新调整以调整和扩展矩阵的大小以进行乘法。 varargin和varargout用于处理可变长度的输入和输出,因此我们可以编写
[b1 b2 b3 ..bn] = linear_comb(coef, a1, a2 ,...am);
答案 4 :(得分:-2)
如果您熟悉C编程,则可以轻松创建一个mex函数来执行此操作。由于这是一个可分离的操作,您也可以非常轻松地使用openMP来并行化它。
这些方面的东西:
#include "mex.h"
void mexFunction (int nlhs, mxArray *plhs[],
int nrhs, const mxArray *prhs[])
{
plhs[0] = mxCreateDoubleMatrix(4,2,mxREAL);
double* c_matrix = (double*) mxGetPr(prhs[0]);
double* a1 = (double*) mxGetPr(prhs[1]);
double* a2 = (double*) mxGetPr(prhs[2]);
double* out = (double*) mxGetPr(plhs[0]);
double alpha_1 = c_matrix[0];
double alpha_2 = c_matrix[2];
double alpha_3 = c_matrix[1];
double alpha_4 = c_matrix[3];
for (int i = 0;i<2;i++)
for (int j=0; j<2; j++)
{
out[i+j*4] = alpha_1*a1[i+j*2]+alpha_2*a2[i+j*2];
out[2+i+j*4] = alpha_3*a1[i+j*2]+alpha_4*a2[i+j*2];
}
}
所有尺寸都是硬编码的,没有进行检查,但这可能就是您所需要的。只需使用mex编译它。 内部for循环可以使用openMP进行并行化,如果你熟悉它,请使用pragma。但对于这样小的矩阵来说,这似乎并不值得。