private static void FillExtensionLengths(TreeExtensionPoint extension, int maxDepth)
        {
            var grammar   = extension.Parent.Grammar;
            int maxLength = int.MinValue;
            int minLength = int.MaxValue;

            foreach (ISymbol s in grammar.GetAllowedChildSymbols(extension.Parent.Symbol, extension.ChildIndex))
            {
                if (s.InitialFrequency > 0.0)
                {
                    int max = grammar.GetMaximumExpressionLength(s, maxDepth - extension.ExtensionPointDepth);
                    maxLength = Math.Max(maxLength, max);
                    int min = grammar.GetMinimumExpressionLength(s);
                    minLength = Math.Min(minLength, min);
                }
            }

            extension.MaximumExtensionLength = maxLength;
            extension.MinimumExtensionLength = minLength;
        }
    private static void FillExtensionLengths(TreeExtensionPoint extension, int maxDepth) {
      var grammar = extension.Parent.Grammar;
      int maxLength = int.MinValue;
      int minLength = int.MaxValue;
      foreach (ISymbol s in grammar.GetAllowedChildSymbols(extension.Parent.Symbol, extension.ChildIndex)) {
        if (s.InitialFrequency > 0.0) {
          int max = grammar.GetMaximumExpressionLength(s, maxDepth - extension.ExtensionPointDepth);
          maxLength = Math.Max(maxLength, max);
          int min = grammar.GetMinimumExpressionLength(s);
          minLength = Math.Min(minLength, min);
        }
      }

      extension.MaximumExtensionLength = maxLength;
      extension.MinimumExtensionLength = minLength;
    }
    private static bool TryCreateFullTreeFromSeed(IRandom random, ISymbolicExpressionTreeNode root,
      int targetLength, int maxDepth) {
      List<TreeExtensionPoint> extensionPoints = new List<TreeExtensionPoint>();
      int currentLength = 0;
      int actualArity = SampleArity(random, root, targetLength, maxDepth);
      if (actualArity < 0) return false;

      for (int i = 0; i < actualArity; i++) {
        // insert a dummy sub-tree and add the pending extension to the list
        var dummy = new SymbolicExpressionTreeNode();
        root.AddSubtree(dummy);
        var x = new TreeExtensionPoint { Parent = root, ChildIndex = i, ExtensionPointDepth = 0 };
        FillExtensionLengths(x, maxDepth);
        extensionPoints.Add(x);
      }
      //necessary to use long data type as the extension point length could be int.MaxValue
      long minExtensionPointsLength = extensionPoints.Select(x => (long)x.MinimumExtensionLength).Sum();
      long maxExtensionPointsLength = extensionPoints.Select(x => (long)x.MaximumExtensionLength).Sum();

      // while there are pending extension points and we have not reached the limit of adding new extension points
      while (extensionPoints.Count > 0 && minExtensionPointsLength + currentLength <= targetLength) {
        int randomIndex = random.Next(extensionPoints.Count);
        TreeExtensionPoint nextExtension = extensionPoints[randomIndex];
        extensionPoints.RemoveAt(randomIndex);
        ISymbolicExpressionTreeNode parent = nextExtension.Parent;
        int argumentIndex = nextExtension.ChildIndex;
        int extensionDepth = nextExtension.ExtensionPointDepth;

        if (parent.Grammar.GetMinimumExpressionDepth(parent.Symbol) > maxDepth - extensionDepth) {
          ReplaceWithMinimalTree(random, root, parent, argumentIndex);
          int insertedTreeLength = parent.GetSubtree(argumentIndex).GetLength();
          currentLength += insertedTreeLength;
          minExtensionPointsLength -= insertedTreeLength;
          maxExtensionPointsLength -= insertedTreeLength;
        } else {
          //remove currently chosen extension point from calculation
          minExtensionPointsLength -= nextExtension.MinimumExtensionLength;
          maxExtensionPointsLength -= nextExtension.MaximumExtensionLength;

          var symbols = from s in parent.Grammar.GetAllowedChildSymbols(parent.Symbol, argumentIndex)
                        where s.InitialFrequency > 0.0
                        where parent.Grammar.GetMinimumExpressionDepth(s) <= maxDepth - extensionDepth
                        where parent.Grammar.GetMinimumExpressionLength(s) <= targetLength - currentLength - minExtensionPointsLength
                        select s;
          if (maxExtensionPointsLength < targetLength - currentLength)
            symbols = from s in symbols
                      where parent.Grammar.GetMaximumExpressionLength(s, maxDepth - extensionDepth) >= targetLength - currentLength - maxExtensionPointsLength
                      select s;
          var allowedSymbols = symbols.ToList();

          if (allowedSymbols.Count == 0) return false;
          var weights = allowedSymbols.Select(x => x.InitialFrequency).ToList();

#pragma warning disable 612, 618
          var selectedSymbol = allowedSymbols.SelectRandom(weights, random);
#pragma warning restore 612, 618

          ISymbolicExpressionTreeNode newTree = selectedSymbol.CreateTreeNode();
          if (newTree.HasLocalParameters) newTree.ResetLocalParameters(random);
          parent.RemoveSubtree(argumentIndex);
          parent.InsertSubtree(argumentIndex, newTree);

          var topLevelNode = newTree as SymbolicExpressionTreeTopLevelNode;
          if (topLevelNode != null)
            topLevelNode.SetGrammar((ISymbolicExpressionTreeGrammar)root.Grammar.Clone());

          currentLength++;
          actualArity = SampleArity(random, newTree, targetLength - currentLength, maxDepth - extensionDepth);
          if (actualArity < 0) return false;
          for (int i = 0; i < actualArity; i++) {
            // insert a dummy sub-tree and add the pending extension to the list
            var dummy = new SymbolicExpressionTreeNode();
            newTree.AddSubtree(dummy);
            var x = new TreeExtensionPoint { Parent = newTree, ChildIndex = i, ExtensionPointDepth = extensionDepth + 1 };
            FillExtensionLengths(x, maxDepth);
            extensionPoints.Add(x);
            maxExtensionPointsLength += x.MaximumExtensionLength;
            minExtensionPointsLength += x.MinimumExtensionLength;
          }
        }
      }
      // fill all pending extension points
      while (extensionPoints.Count > 0) {
        int randomIndex = random.Next(extensionPoints.Count);
        TreeExtensionPoint nextExtension = extensionPoints[randomIndex];
        extensionPoints.RemoveAt(randomIndex);
        ISymbolicExpressionTreeNode parent = nextExtension.Parent;
        int a = nextExtension.ChildIndex;
        ReplaceWithMinimalTree(random, root, parent, a);
      }
      return true;
    }
        private static bool TryCreateFullTreeFromSeed(IRandom random, ISymbolicExpressionTreeNode root,
                                                      int targetLength, int maxDepth)
        {
            List <TreeExtensionPoint> extensionPoints = new List <TreeExtensionPoint>();
            int currentLength = 0;
            int actualArity   = SampleArity(random, root, targetLength, maxDepth);

            if (actualArity < 0)
            {
                return(false);
            }

            for (int i = 0; i < actualArity; i++)
            {
                // insert a dummy sub-tree and add the pending extension to the list
                var dummy = new SymbolicExpressionTreeNode();
                root.AddSubtree(dummy);
                var x = new TreeExtensionPoint {
                    Parent = root, ChildIndex = i, ExtensionPointDepth = 0
                };
                FillExtensionLengths(x, maxDepth);
                extensionPoints.Add(x);
            }
            //necessary to use long data type as the extension point length could be int.MaxValue
            long minExtensionPointsLength = extensionPoints.Select(x => (long)x.MinimumExtensionLength).Sum();
            long maxExtensionPointsLength = extensionPoints.Select(x => (long)x.MaximumExtensionLength).Sum();

            // while there are pending extension points and we have not reached the limit of adding new extension points
            while (extensionPoints.Count > 0 && minExtensionPointsLength + currentLength <= targetLength)
            {
                int randomIndex = random.Next(extensionPoints.Count);
                TreeExtensionPoint nextExtension = extensionPoints[randomIndex];
                extensionPoints.RemoveAt(randomIndex);
                ISymbolicExpressionTreeNode parent = nextExtension.Parent;
                int argumentIndex  = nextExtension.ChildIndex;
                int extensionDepth = nextExtension.ExtensionPointDepth;

                if (parent.Grammar.GetMinimumExpressionDepth(parent.Symbol) > maxDepth - extensionDepth)
                {
                    ReplaceWithMinimalTree(random, root, parent, argumentIndex);
                    int insertedTreeLength = parent.GetSubtree(argumentIndex).GetLength();
                    currentLength            += insertedTreeLength;
                    minExtensionPointsLength -= insertedTreeLength;
                    maxExtensionPointsLength -= insertedTreeLength;
                }
                else
                {
                    //remove currently chosen extension point from calculation
                    minExtensionPointsLength -= nextExtension.MinimumExtensionLength;
                    maxExtensionPointsLength -= nextExtension.MaximumExtensionLength;

                    var symbols = from s in parent.Grammar.GetAllowedChildSymbols(parent.Symbol, argumentIndex)
                                  where s.InitialFrequency > 0.0
                                  where parent.Grammar.GetMinimumExpressionDepth(s) <= maxDepth - extensionDepth
                                  where parent.Grammar.GetMinimumExpressionLength(s) <= targetLength - currentLength - minExtensionPointsLength
                                  select s;
                    if (maxExtensionPointsLength < targetLength - currentLength)
                    {
                        symbols = from s in symbols
                                  where parent.Grammar.GetMaximumExpressionLength(s, maxDepth - extensionDepth) >= targetLength - currentLength - maxExtensionPointsLength
                                  select s;
                    }
                    var allowedSymbols = symbols.ToList();

                    if (allowedSymbols.Count == 0)
                    {
                        return(false);
                    }
                    var weights = allowedSymbols.Select(x => x.InitialFrequency).ToList();

#pragma warning disable 612, 618
                    var selectedSymbol = allowedSymbols.SelectRandom(weights, random);
#pragma warning restore 612, 618

                    ISymbolicExpressionTreeNode newTree = selectedSymbol.CreateTreeNode();
                    if (newTree.HasLocalParameters)
                    {
                        newTree.ResetLocalParameters(random);
                    }
                    parent.RemoveSubtree(argumentIndex);
                    parent.InsertSubtree(argumentIndex, newTree);

                    var topLevelNode = newTree as SymbolicExpressionTreeTopLevelNode;
                    if (topLevelNode != null)
                    {
                        topLevelNode.SetGrammar((ISymbolicExpressionTreeGrammar)root.Grammar.Clone());
                    }

                    currentLength++;
                    actualArity = SampleArity(random, newTree, targetLength - currentLength, maxDepth - extensionDepth);
                    if (actualArity < 0)
                    {
                        return(false);
                    }
                    for (int i = 0; i < actualArity; i++)
                    {
                        // insert a dummy sub-tree and add the pending extension to the list
                        var dummy = new SymbolicExpressionTreeNode();
                        newTree.AddSubtree(dummy);
                        var x = new TreeExtensionPoint {
                            Parent = newTree, ChildIndex = i, ExtensionPointDepth = extensionDepth + 1
                        };
                        FillExtensionLengths(x, maxDepth);
                        extensionPoints.Add(x);
                        maxExtensionPointsLength += x.MaximumExtensionLength;
                        minExtensionPointsLength += x.MinimumExtensionLength;
                    }
                }
            }
            // fill all pending extension points
            while (extensionPoints.Count > 0)
            {
                int randomIndex = random.Next(extensionPoints.Count);
                TreeExtensionPoint nextExtension = extensionPoints[randomIndex];
                extensionPoints.RemoveAt(randomIndex);
                ISymbolicExpressionTreeNode parent = nextExtension.Parent;
                int a = nextExtension.ChildIndex;
                ReplaceWithMinimalTree(random, root, parent, a);
            }
            return(true);
        }