【问题标题】:Reduce Cell of vectors according to some conditions根据某些条件减少向量的单元格
【发布时间】:2015-01-26 08:13:47
【问题描述】:

A 成为向量单元。为方便起见,将这些向量表示为V1V2、...

我想找到没有“巧合”的最大向量集。当满足以下任一条件时,两个向量 VnVm 之间会发生重合:

  • 这两个向量有一些共同的值,即Vn(i)==Vm(j) 对应一些ij
  • 这两个向量有两个在100 中不同的值,即abs(Vn(i)-Vm(j))==100 对于某些ij

例子:

A = {[2 5],[8 9 2],[33 77 4],[102 6],[10 66 17 7],[110 99],[1 4 3],[15 41 88]}

Possible_Result = {[2 5],[33 77 4],[10 66 17 7],[15 41 88]}

为了不使我的问题复杂化,在几个可能的结果之间选择一个结果并不重要。

【问题讨论】:

  • 非常有趣的问题。我能看到你这样做的唯一方法是蛮力(à la Luis Mendo)。顺便说一句,这是knapsack problem 的重新表述,它是NP-complete problem。目前没有多项式时间算法可以有效地解决这个问题,所以解决这个问题最直观的方法是蛮力。我希望你的数据集不是很大,因为随着数据集变大,这类问题会以指数级增长!
  • @rayryeng 非常有见地的评论让我觉得我的代码实际上可能没有找到最大集合。也许最好的方法是“蛮力”:测试所有个可能的子集,看看它们是否满足你的条件。我的方法只是在进行所有成对比较的意义上“粗暴”,而不是测试所有可能的子集
  • @rayryeng 我确实知道背包问题,但我没有看到这是它的一个实例。无论如何,我认为我的答案现在找到了一个最大子集;但当然是在非多项式(实际上是指数)时间内。有时使用蛮力会产生一种奇怪的内在满足感:-D
  • @rayryeng 直觉好!
  • @LuisMendo - 我还是会这么说。最终,您将根据查看一对项目来选择单个项目。成本将是成对的,而不是单独的。

标签: matlab cell knapsack-problem


【解决方案1】:

这是一种蛮力方法:

  1. 根据您问题中的规则确定向量之间的“巧合”。
  2. 对于每个可能的子集,通过确定其向量之间是否存在重合来测试其有效性。
  3. 在所有有效子集中,选择一个具有最大向量数的子集。

这可能,主要是因为它是蛮力的(尝试所有可能的子集),其次是因为它使用cellfun 和一个匿名函数。

内存使用率很低,因为每个子集(由逻辑值向量指定)都是动态定义的。这依赖于可以枚举所有可能子集的集合,子集编号和子集描述之间的对应关系只是二进制扩展。

%// STEP 1
%// Definition of "coincidence" between two vectors x and y:
f = @(x,y) nnz(ismember(bsxfun(@minus, x(:),y(:).'), [-100 0 100])); %' 
%// Generate all combinations:
[ii, jj] = ndgrid(1:numel(A));
%// Test for each pair of vectors for coincidences:
M = cellfun(f, A(ii), A(jj)); %// m(k,l)>0 indicates coincidence betwen vectors k and l
M = triu(M,1); %// consider each pair only once; and disregard self-coincidences

%// STEP 2
%// Test if each subset is valid, using (part of) matrix M:
valid = ones(1,2^numel(A)); %// this will store whether each subset is valid
num = NaN(1,2^numel(A)); %// this will store number of vectors in each subset
for n = 1:2^numel(A) %// there are 2^numel(A) possible subsets
    s = logical(dec2bin(n-1)-'0'); %// 1: vector is present. 0: is absent
    num(n) = sum(s); %// number of vectors in the subset
    if nnz(M(s,s)) %// if there are coincidences...
        valid(n) = 0; %// ...then this subset is not valid
    end
end

%// STEP 3
%// Find *first* (in the order of ss) valid subset with maximum number of elements:
[~, t] = max(valid.*num); %'// (it'd be easy to output *all* maximum subsets)
A_solution = A(logical(dec2bin(t-1)-'0'));

【讨论】:

  • 如果 A = {[109 146],[111 142],[117 146],[117 154],[117 155]};我得到:{[109 146],[111 142]} !!!通常结果应包括 [117 154] 或 [117 155]。
  • @bzak 你是对的。我没有考虑到一旦你删除了一个元素,它与其他元素的重合也应该被删除。请查看编辑后的答案
  • ??? [~, col] = find(m,1); |错误:表达式或语句不正确——可能是不平衡的 (、{ 或 [.
  • @bzak 您使用哪个 Matlab 版本?试试[val, col] = find(m,1);
  • @bzak - 函数的输出变量抑制(即~)仅从 MATLAB R2009b 开始受支持。不幸的是,您缺少这种(相当漂亮的)语法的一个版本。因此,使用虚拟变量代替 ~ 并在完成后将其清除(即根据 Luis Mendo 的 val)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-02-01
  • 1970-01-01
  • 2011-08-30
  • 1970-01-01
  • 2013-06-03
  • 1970-01-01
相关资源
最近更新 更多