포트 this Genetic Algorithm, 을 포트에 연결하려고 시도했으며 한 세대에서 다른 세대로 발전하기 위해 재귀 함수를 만들었습니다.재귀에서 StackOverflow를 방지하는 우아한 방법
그러나 C# (및 일반적으로)에서 재귀를 처음 접했을 때 분명히 너무 많은 세대 (약 4500 개가 넘었을 때)의 StackOverflowException이 발생했습니다.
문제를 해결하기 위해 Generation()에서 bool을 반환 했으므로 유전자 알고리즘이 최대 적합성 (목표)에 도달하면 true를 반환합니다. 그렇지 않으면 Generation()을 반환합니다.
오버플로가 발생하면 (생성> 4500) 거짓을 반환합니다.
Now Main()에서 Generation()이 true를 반환 할 때까지 계속 실행하려면 while 루프를 사용하므로 완료 될 때까지 반복을 시작합니다.
이 방법은 Task.Run을 수행하는 것보다 효율적이므로이 방법을 사용했습니다.
이 좋은 방법입니까? 성능 저하없이 StackOverflow를 막는 더 좋은 방법이 있습니까?
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
스택 오버 플로우가 발생하는 지점에 이르면 비 재귀 적 방법으로 변경하는 것이 좋습니다. 알고리즘은 기본적으로 "친구 생성, 돌연변이 생성, 필터 생성, 반복"이므로이 경우 실제로는 매우 간단합니다. 재귀보다 내 루프처럼 들린다.실제로 이것은 재귀 (제대로 구현 된 경우)보다 성능면에서 훨씬 좋습니다. – Paul