处理非常大的树状数据结构:OutOfMemoryException

时间:2012-06-22 20:25:47

标签: c# tree

我正在创建一个象棋程序的变体,需要同时生成和遍历一个非常大的树状结构。每个节点有10个bool,一个int,8个ulongs,一个短[64]和2个ulong [64] s。根节点接收一些初始参数,然后从那里以编程方式(递归地)确定有效的子节点。

基本上,当用户和程序轮流遍历子节点到子节点时,我的程序会不断增长此树。每次“选择”新的子节点时,不再需要它的父节点和兄弟节点并被丢弃。当树(平均)达到大约60的深度(从初始根节点)时,有效子节点的数量将自然地开始减少直到大约75的深度,树被解析为一个最终节点,没有更多的孩子。

这背后的逻辑看起来相当直接,但我经常遇到一个OutOfMemoryException,直接杀死任何进一步的进展。

以下是“每代”有效儿童的平均值:

Generation    New Nodes
1             1    
2             20
3             4,000
4             30,000
5             2,200,000
6             > 50,000,000

在我的实际节目中,我甚至无法完全扩展第五代。当我不保留节点特定数据时(我清除节点的数据,一旦它被用来确定它自己的孩子)我可以完全扩展第5代,但是在第六代中途打了一个非常坚固的墙。

理想情况下,我希望我的程序最终到达并在“当前”节点之后维护8代节点。我看的越多,看起来就越不可能。

我厌倦了用sqlite数据库运行它,但是它无法足够快地生成树。

有没有人知道处理非常大的树结构的任何潜在替代方案?

2 个答案:

答案 0 :(得分:1)

您的问题没有一般性答案。我将假设计算这个大树以确定您的计算机程序的最佳移动?

在这种情况下,定义一系列动作的效用函数可能会有所帮助,它可以衡量在游戏中进行这一系列动作的价值。如果目标是达到最高分或类似值,则该分数是一个很好的效用函数。

有时您无法提出准确的效用函数,在这种情况下,通常的方法是对效用进行启发式评估。基本上它是近似值或最佳猜测值。启发式越好对手越好。

您希望进行实用程序测量的原因是执行修剪。例如,将遍历树深度 - 先进行几次并计算最小和最大效用。这些值可以帮助您修剪完整的算法,这意味着您可以使用这些边界来确定您的树遍历算法是否可以在完成之前终止。

同样,这一切都取决于你的游戏机制以及你如何遍历树,但希望这可以让你思考正确的方向。

答案 1 :(得分:0)

通常,您在构建树时进行评​​估,这已经为您提供了边缘的权重。使用这些权重来查看哪些路径将评估比其他路径更强的路径,并且只要您可以看到哪些路段更有价值,就可以在这些路径上工作。由于您已经在算法中遇到了第五代的问题,因此您只能选择在更高权重的分支上进行深入研究,并选择其中一个,从而忽略其他多个分支。只是一个想法...也许你可以在第三代运行这个,选择走哪条路。据我所知,国际象棋可能会让你只用更多可移动的棋子进行动作,因为他们的probalby会对游戏产生更大的影响,与第五代动作相比,这可能不是最好的解决方案。非常有趣的问题!

你应该调查国际象棋编程:Chess programming wiki

以下是关于引擎的更多内容:Chess programming wiki on Engines

还有一个论坛,讨论了不同的方法!