我試圖端口this Genetic Algorithm, ,我做了一個遞歸函數從一代推進到另一代。但是,因爲我是C#中的新遞歸(一般情況下),當代數太多(大約4500)時,我顯然遇到了StackOverflowException。優雅的方法來防止遞歸中的StackOverflow
爲了解決這個問題,我讓Generation()返回一個bool,所以當遺傳算法達到最大適應度(目標)時,它會返回true。否則它返回Generation()。
如果它即將溢出(代> 4500),則返回false。
Now在Main()中,爲了使Generation()繼續運行直到它返回true,我使用一個while循環,因此它將在遞歸開始之前一直運行,直到它完成。
這比做Task.Run更有效率,所以我採用了這種方法。
這是一個很好的做法嗎?有沒有更好的方法來防止StackOverflows而不犧牲性能?
Population.cs:
class Population
{
public int GenerationNumber { get; private set; }
public int TotalGenerationNumber { get; private set; }
public const int StackGenerationLimit = 4500;
public Population()
{
GenerationNumber = 0;
TotalGenerationNumber = 0;
}
public bool Generation()
{
// Work
// if(HasReachedGoal) return true;
GenerationNumber++;
if(GenerationNumber > StackGenerationLimit)
{
return false;
} else
{
return Generation();
}
}
public void ResetStack()
{
TotalGenerationNumber += GenerationNumber; // I store the total number of generation for information purposes
GenerationNumber = 0; // Reset the recursion depth value
}
}
Program.cs的
class Program
{
static void Main(string[] args)
{
Population population = new Population();
while (!population.Generation()) // Until it reaches its goal
{
population.ResetStack();
}
Console.WriteLine("End. Generations: " + population.TotalGenerationNumber);
}
}
通常你不必保持遞歸方法運行 – EpicKip
如果你得到了一個stackoverflow的點,你應該考慮改變方法到一個非遞歸的方法。在這種情況下,它實際上非常簡單,因爲算法基本上是「配對生成,變異代,過濾器生成,重複」。聽起來更像是一個循環,而不是遞歸。事實上,這在性能方面比遞歸更好(如果正確實施)。 – Paul