2 3 2
4 6 4
2 3 2
可分为
2 3 2
和
1
2
1
/>
使用整数算术对分离性进行实际测试似乎很简单,但是事实证明,分解为带有整数系数的一维滤波器是一个更加困难的问题。困难似乎在于以下事实:行或列之间的比率可能是非整数(理性分数),例如在上面的示例中,比率为2、1 / 2、3 / 2和2/3。
我真的不想使用像SVD这样的重型方法,因为对于我的需求而言,计算量很大,并且(b)仍然不一定有助于确定整数系数。
有什么想法吗?
系数可以为正,负或零,并且在某些病理情况下,一维矢量或两个矢量之和为零,例如
可分为
-1 2 -1
0 0 0
1 -2 1
和
1 -2 1
#1 楼
我已经回答了@Phonon
的答案,并对其进行了一些修改,以便它仅对最上面一行和最左边一列使用GCD方法,而不是对行/列总和使用GCD方法。这似乎可以更好地处理病理病例。如果顶行或左列全为零,则仍然可能失败,但是可以在应用此方法之前检查这些情况。@Phonon
对此的原始想法。#2 楼
得到它了!发布MATLAB代码,将在今晚或明天发布说明。% Two original arrays
N = 3;
range = 800;
a = round( range*(rand(N,1)-0.5) )
b = round( range*(rand(1,N)-0.5) )
% Create a matrix;
M = a*b;
N = size(M,1);
% Sanity check
disp([num2str(rank(M)) ' <- this should be 1!']);
% Sum across rows and columns
Sa = M * ones(N,1);
Sb = ones(1,N) * M;
% Get rid of zeros
SSa = Sa( Sa~=0 );
SSb = Sb( Sb~=0 );
if isempty(SSa) | isempty(SSb)
break;
end
% Sizes of array without zeros
Na = numel(SSa);
Nb = numel(SSb);
% Find Greatest Common Divisor of Sa and Sb.
Ga = SSa(1);
Gb = SSb(1);
for l=2:Na
Ga = gcd(Ga,SSa(l));
end
for l=2:Nb
Gb = gcd(Gb,SSb(l));
end
%Divide by the greatest common divisor
Sa = Sa / Ga;
Sb = Sb / Gb;
%Scale one of the vectors
MM = Sa * Sb;
Sa = Sa * (MM(1) / M(1));
disp('Two arrays found:')
Sa
Sb
disp('Sa * Sb = ');
Sa*Sb
disp('Original = ');
M
评论
$ \ begingroup $
谢谢-太好了-昨晚我躺在床上醒来,正在考虑分解系数等,但是像这样使用GCD会更加简单和优雅。不幸的是,仍然需要解决一些问题-它需要同时使用正系数和负系数,这可能会导致情况恶化,例如A = [-2 1 0 -1 2]; B = [2 -3 6 0 -1]; M = A'* B;。这里的问题是sum(A)= 0,所以Sb = [0 0 0 0 0]。我将尝试修改您的算法,以便它使用系数的绝对值之和,看看是否有帮助。再次感谢你的帮助。
$ \ endgroup $
– Paul R
2012年3月29日在9:13
$ \ begingroup $
OK-看来您仍然可以使用abs(M)来获得GCD并进行缩放,即Sa = abs(M)* ones(N,1); Sb = ones(1,N)* abs(M);然后按照上述步骤继续操作,但最后还看不到如何将符号恢复为Sa,Sb。我在上面的原始问题中添加了一个病理示例来说明问题。
$ \ endgroup $
– Paul R
2012年3月29日9:59
$ \ begingroup $
我想我现在有一个可行的解决方案-我将其发布为一个单独的答案,但是您可以从中获得潜在的想法。再次感谢 !
$ \ endgroup $
– Paul R
2012年3月29日14:50
#3 楼
也许我正在解决这个问题,但似乎可以: mathbf {a_i} $,$ i = 0,1,\ ldots,N-1 $。对于每一行索引$ j> 0 $:
将$ \ mathbf {a_j} $除以$ \ mathbf {a_0} $,可得出$ j $行中每个元素与零行$ \ mathbf {r_j} $中对应元素之比。这需要使用浮点数或其他分数运算来完成。
检查$ \ mathbf {r_j} $中的元素以确定它们是否恒定。在此比较中,您需要允许一些公差,以便进行浮点舍入。
如果$ \ mathbf {r_j} $中的值是常数,则$ \ mathbf {a_j} $行是标量$ \ mathbf {a_0} $行的倍数。将行$ j $与行$ 0 $的比率存储在列表$ \ mathbf {x} $中。 $ \ mathbf {a_0} $,因此您将无法以这种方式分解矩阵。停止检查。
如果在上述测试中所有行均被视为行0的常数倍,则获取行比标量$ \ mathbf {x} $的列表,然后用最小比率对其进行归一化:
$$
x_ {k,norm} = \ frac {x_k} {\ min_ {i = 0} ^ {N-1} x_i}
$$
这样做之后,比率$ \ mathbf {x_ {norm}} $的归一化列表将为值最小的行包含值1。规范。您想查看是否可以通过某种方式缩放此列表以产生包含所有整数系数的列表。蛮力方法只能进行线性搜索,即计算:
$$
\ mathbf {x_ {scaled}} = K \ mathbf {x_ {norm}},K = 1、2,\ ldots,M
$$$
对于$ K $的每个值,在计算比例比例列表后,您需要检查每个值以查看它们是否为整数值(再次具有一定的容差)。将$ M $设置为等于您愿意在行间比率中寻找的最大分母。
不是最优雅的方法,可能有更好的方法,但是它应该可以工作,易于实现,并且对于中等大小的矩阵应该相对较快。
评论
$ \ begingroup $
谢谢-我想在陷入细节之前,我可能正在朝着这个方向前进。对我来说,并不是总是100%清楚会使用此方法得出解决方案,但是无论如何,我可能应该对此进行编码,并通过一些示例进行尝试。我有一种预感,可能需要逐行和逐列地应用它,以查看哪种方法产生了“最佳”解决方案。感谢您抽出宝贵的时间来详细说明细节-我会忙着处理,并告诉您如何解决。
$ \ endgroup $
– Paul R
2012年3月28日在17:16
$ \ begingroup $
您是否找不到行的第一个元素的最大公约数,并以此来确定您的基向量?
$ \ endgroup $
–吉姆·克莱(Jim Clay)
2012年3月28日在17:59
$ \ begingroup $
@JimClay:是的,如果您有可用的功能,那实际上就是最后要做的事情。
$ \ endgroup $
–Jason R
2012年3月28日在18:07
#4 楼
另一种方法是找到与内核$ A $的可分离近似值$ x \ otimes y \ otimes z $,并查看其接近程度。
两种方法可以做到这一点,即最小化
$ | A-x \ otimes y \ otimes z | $:
1)蛮力优化$ x \ y \ z $;这需要时间〜固定的$ y $和$ z $的长度之和,而不是其长度的乘积
2,最优的$ x $只是一个投影,因此请优化
$ x \ y \ z \ x \ y \ z \ ... $。
(摘自数学上的近似卷积作为可分离卷积的和
。 stackexchange。)
评论
$ \ begingroup $
尽量不要用无法解释的链接回答问题。最好在答案中解释必要的细节,并仅包含链接以供参考;这样,如果链接中断,答案的基本细节仍然存在。
$ \ endgroup $
–山姆·马洛尼(Sam Maloney)
13年4月21日在0:08
$ \ begingroup $
@SamMaloney:我认为没有必要这样做。该链接详细说明了所有内容。它仍会在“问答”搜索中弹出。那为什么不呢?
$ \ endgroup $
–那雷什
2013年4月21日在2:46
$ \ begingroup $
@Naresh之所以仅提及它,是因为堆栈交换站点的目标之一是建立一个已回答问题的存储库,以备将来参考。因此,尽管我知道该特定链接是指向另一个SE站点的,并且应该相当安全,但通常的最佳做法是不要指望从现在起仍在运行的链接。在答案中给出这些“两种简单方法”的概述将确保即使链接的问题出了问题也能保留信息。正如我所说,这更多地是对答案链接最佳实践的一般性评论。
$ \ endgroup $
–山姆·马洛尼(Sam Maloney)
13年4月22日在18:39
评论
我记得在大学时曾试图解决这个问题。我几乎成功了,但我不记得如何。 =)既然您提到它,我就不能停止考虑它!@Phonon:呵呵-继续思考-我可以从中获得一些启发。 ;-)
除了double或float值,是否可以做同样的事情?
@DiegoCatalano:请参阅下面的丹尼斯答案,以及他在math.stackexchange.com上链接到的问题-我认为这可能适用于更通用的浮点系数情况。
似乎有人称其为“逆外积”: