优雅的方法来防止在递归中堆叠



我正在尝试移植此遗传算法,我发挥了递归功能,以从一代人到另一代促进。

但是,由于我是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
    }

这防止了一个太深的嵌套呼叫,该调用会产生您所描述的错误。

相关内容

  • 没有找到相关文章

最新更新