我有一个包含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中编程,但任何语言都没问题。
我将使用它来初始化一些遗传算法的总体,所以我希望每个可能性都同样可能,以确保我覆盖整个搜索空间。只是确定性地分配断点是不够的。
答案 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)
如果你不介意有随机(但很小)的计算时间,你可以使用拒绝方法:
这确保了每个有效断点组合的概率相等,而不必最初生成所有这些组合。
在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值,您可以简单地添加嵌套循环。
一旦掌握了所有积分,随机挑选它们应该是微不足道的。