删除最小点数以获得单调函数

时间:2018-02-06 16:11:38

标签: matlab function discrete-mathematics

给定:n个离散数据点[ti,xi],它应描述单调函数(ti =时间,xi =数据)。一些点是“异常值”,或者违反单调函数规则(x {i + 1}> = x {i}用于增加,x {i + 1}< = x {i}用于递减)。

我试图找到一种算法来确定我必须消除的最小数据点数才能获得单调函数。我也知道它是增加还是减少。

我尝试使用移动中值滤波器并识别在滤波函数之上或之下的某些方差的点,但我无法识别所有点。

这个问题的最佳方法是什么?

我正在使用MATLAB,但解决方案肯定可以推广。

2 个答案:

答案 0 :(得分:1)

这是一个使用Patience sort从给定数组中找到增长最长的子序列的解决方案。解决方案不一定是唯一的,但保证其长度大于或等于任何其他增加的子序列。如果您只想知道最长增长子序列的长度,则可以使用更简单的函数。

function subsequence = PatienceLIS(sequence)
   % Use patience sort to generate a (not necessarily unique)
   %   longest increasing subsequence from a given sequence

   subInds = [];   % indices of subsequence elements
   for s = 1:numel(sequence)
      % put new element on first stack with top element > sequence(s)
      newStack = find(sequence(s) <= [sequence(subInds) inf], 1);
      subInds(newStack) = s;   % put current index on top of newStack
      if (newStack > 1)
         % point to the index currently to the left
         pred(s) = subInds(newStack - 1);
      end
   end
   % recover the subsequence indices
   % last element in subsequence is found from last subInds
   pathInds = subInds(end);
   while (pred(pathInds(1)) > 0)
      pathInds = [pred(pathInds(1)) pathInds];   % add predecessor index to list
   end
   subsequence = sequence(pathInds);   % recover subsequence from indices
end

示例运行:

x = [7 4 11 -1 13 12 10 8 5 14 14 12 15 6 1 3 2 9];

>> PatienceLIS(x)
ans =

    4   11   12   14   15

答案 1 :(得分:0)

我想到了有限用途的递归解决方案(因为它不会导致最长的子序列),但也许

  1. ...它可以扩展以满足您的需求。
  2. ...它可以告诉你为什么这不是一个小问题。
  3. function [pts_to_remove, monoseq] = q48647287
    
    sequence = randi(1000,1000,1,'int16');
    [pts_to_remove, monoseq] = remove_pts(sequence, false, 0);
    % Now we can try to setdiff different subsets of `monoseq` from `sequence` and rerun the 
    % algorithm. Among the results we'll take the longest `monoseq`, and repeat the procedure as 
    % many times as needed.
    % Of course it needs to be (dis)proven mathematically whether this approach can result in 
    % the longest possible subsequence.
    
    end
    
    function [pts_removed, seq] = remove_pts(seq, shouldIncrease, rem_pts_so_far)
    
      if shouldIncrease
        d = diff([-Inf; seq]) >= 0;
      else
        d = diff([ Inf; seq]) <= 0;
      end
    
      to_rem = sum(~d);
      if to_rem % > 0
        pts_removed = remove_pts(seq(d), shouldIncrease, rem_pts_so_far + to_rem);
      else
        pts_removed = rem_pts_so_far;
      end
    
    end