private INode GenerateGrowthInitImpl(FunctionNodesFabric fabric, int maxDepth, int curDepth)
        {
            INode node = null;

            if (curDepth == maxDepth)
            {
                return(fabric.GetRandomTerminalNode());
            }

            int nextType;

            if (curDepth < _minDepth && _minDepth <= maxDepth)
            {
                nextType = GetRandomIndex(2);
            }
            else
            {
                nextType = GetRandomIndex(3);
            }

            switch (nextType)
            {
            case 0:
                node = fabric.GetRandomBinNode(
                    this.GenerateGrowthInitImpl(fabric, maxDepth, curDepth + 1),
                    this.GenerateGrowthInitImpl(fabric, maxDepth, curDepth + 1)
                    );
                break;

            case 1:
                node = fabric.GetRandomUnaryNode(
                    this.GenerateGrowthInitImpl(fabric, maxDepth, curDepth + 1));
                break;

            case 2:
                var isNextConst = _r.Next(100) <= 20;
                if (isNextConst && _usedTerminals.Count == fabric.GetTerminalsCount())
                {
                    node = fabric.GetRandomConstNode();
                }
                else if (_usedTerminals.Count < fabric.GetTerminalsCount())
                {
                    var termNode = fabric.GetRandomTerminalNode(_usedTerminals);
                    _usedTerminals.Add(termNode.Name);
                    node = termNode;
                }
                else
                {
                    node = fabric.GetRandomTerminalNode();
                }
                break;

            default:
                break;
            }

            return(node);
        }
        private INode GenerateFullInitImpl(FunctionNodesFabric fabric, int maxDepth, int curDepth)
        {
            INode node = null;

            if (curDepth == maxDepth)
            {
                var isNextConst = _r.Next(100) <= 20;
                if (isNextConst && _usedTerminals.Count == fabric.GetTerminalsCount())
                {
                    return(fabric.GetRandomConstNode());
                }
                if (_usedTerminals.Count < fabric.GetTerminalsCount())
                {
                    var termNode = fabric.GetRandomTerminalNode(_usedTerminals);
                    _usedTerminals.Add(termNode.Name);
                    return(termNode);
                }
                return(fabric.GetRandomTerminalNode());
            }


            var isNextUnary = _r.Next(100) <= 20;

            if (isNextUnary)
            {
                node = fabric.GetRandomUnaryNode(
                    this.GenerateFullInitImpl(fabric, maxDepth, curDepth + 1)
                    );
            }
            else
            {
                node = fabric.GetRandomBinNode(
                    this.GenerateFullInitImpl(fabric, maxDepth, curDepth + 1),
                    this.GenerateFullInitImpl(fabric, maxDepth, curDepth + 1)
                    );
            }

            return(node);
        }