我正在尝试移植此遗传算法,我发挥了递归功能,以从一代人到另一代促进。
但是,由于我是C#中的新递归(通常(,当有太多世代(超过4500左右(时,我显然会撞到StackoverflowException。
。为了解决该问题,我使Generation((返回Bool,因此当遗传算法达到Max Fitness(目标(时,它会返回真实。否则它将返回Generation((。
如果它要溢出(生成> 4500(,它将返回false。
现在在main((中,要保持generation((运行直到返回true,我使用一段时间循环,因此它将从递归开始直到完成为止。
这比完成任务要高效。
这是好习惯吗?还有其他优雅的方法可以防止堆叠式流体而不牺牲性能?
supers.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);
}
}
避免堆栈溢出的最佳方法是不使用递归。您已经可以通过解决方法找到答案了。现在,您只需要问自己一个问题,即您从递归中获得了什么?如果您的return Generation();
函数中的CC_1语句已更改为return false;
,则您将返回主循环,然后再调用Generation()
。
当然进行了这种更改,现在您可以做很多其他整理。您不再需要堆栈重置,您不再需要检查生成限制的IF语句,并且您的所有重复都是从while循环完成的。
所以您的两种方法:
public bool Generation()
{
TotalGenerationNumber++;
// Work
return HasReachedGoal;
}
static void Main(string[] args)
{
Population population = new Population();
bool hasCompleted = false;
while (!hasCompleted) // Until it reaches its goal
{
hasCompleted = population.Generation();
}
Console.WriteLine("End. Generations: " + population.TotalGenerationNumber);
}
请注意,在Tidyup中,我引入了一个称为hasCompleted
的Bool变量,因为我发现在while条件下使用变量更可读,并且更喜欢在循环本身内进行工作。
我认为,在这种情况下,您最好准备循环并发送要检查的数据中的数据。然后,如果它返回false,则更新数据。这样的东西:
Population population = new Population();
var input = new InputDto() { ... };
while (!population.Generation(input)) // Until it reaches its goal
{
// update input
}
这防止了一个太深的嵌套呼叫,该调用会产生您所描述的错误。