在序列中生成随机“断点”,彼此之间的距离最小

时间:2013-10-06 21:42:48

标签: algorithm matlab

我有一个包含n元素的序列,我希望随机放置k“断点”,每个至少minDist彼此远离n=9, k=2, minDist=2 (和目的)。例如,对于[2 4][2 5][2 6][2 7][3 5][3 6][3 7][4 6][4 7][5 7] ,我想以相同的概率生成以下之一:

{{1}}

到目前为止,我已经提出:随机放置一个,“禁用”周围所需的节点数量,然后选择另一个随机数,但这让我觉得有点不高效。我在MATLAB中编程,但任何语言都没问题。

我将使用它来初始化一些遗传算法的总体,所以我希望每个可能性都同样可能,以确保我覆盖整个搜索空间。只是确定性地分配断点是不够的。

4 个答案:

答案 0 :(得分:1)

这是一个生成所有可能断点组合的函数,您可以将它们存储在列表中而不是打印它们,然后统一选择其中一个:

static void breakpointCombinations(List<int> possiblePositions, List<int> breakpointCombination, int remainingBreakpoints, int minSpace, int currentPos)
{
    if (remainingBreakpoints == 0)
    {
        foreach (int tempPos in breakpointCombination)
        {
            Console.Write(tempPos + " ");
        }
        Console.WriteLine();
    }

    else if (remainingBreakpoints * minSpace > possiblePositions.Count - currentPos)
        return;

    else
    {
        if (currentPos >= minSpace - 1)
        {
            breakpointCombination.Add(possiblePositions[currentPos]);
            breakpointCombinations(possiblePositions, breakpointCombination, remainingBreakpoints - 1, minSpace, currentPos + minSpace);
            breakpointCombination.Remove(possiblePositions[currentPos]);
        }

        breakpointCombinations(possiblePositions, breakpointCombination, remainingBreakpoints, minSpace, currentPos + 1);
    }
}

对函数的调用(在本例中,10个元素,2个断点,最小空间为2):

static void Main(string[] args)
{
    List<int> Positions = new List<int>();
    for (int i = 0; i < 10; i++)
    {
        Positions.Add(i);
    }

    breakpointCombinations(Positions, new List<int>(), 2, 2, 0);
}

从你的例子中暗示,2的空格意味着在2个断点之间应该至少有一个位置(这意味着[2,4]是合法的),我从开头处理空格并结束同一个(这在示例中不一致),这意味着如果元素是[0,...,9],则第一个合法断点位于元素1,最后一个位于元素8。

答案 1 :(得分:1)

如果你不介意有随机(但很小)的计算时间,你可以使用拒绝方法

  1. 随机生成具有均匀分布的暂定断点;
  2. 检查它们是否符合您的限制;
  3. 如果他们不重复,则重复。
  4. 这确保了每个有效断点组合的概率相等,而不必最初生成所有这些组合。

    在Matlab中:

    done = 0;
    while ~done
      breakPoints = sort(randi(n,1,k));
      done = all(diff([0 breakPoints n]) >= minDist);
    end
    

答案 2 :(得分:0)

根据您的规范,您可以从左侧开始,并在每个k-1元素之后放置minDist次。

如果您希望您的分部更加统一分发,则必须修改您的规范。

答案 3 :(得分:0)

实际上,如果你想覆盖整个搜索空间,你就不应该选择随机点。

相反,你应该选择所有的点,也许是随机顺序。

以下是选择k = 2的所有积分的简单方法:

n=9;
minDist = 2;
p = [];
for x = minDist:n-minDist*2
   for y = x+minDist:n-minDist
     p = [p;x y]
   end
end

对于低k值,您可以简单地添加嵌套循环。

一旦掌握了所有积分,随机挑选它们应该是微不足道的。