/// <summary> /// Remove, Replace or Insert subtrees /// </summary> /// <param name="tree">The symbolic expression tree</param> /// <param name="parent">The insertion point (ie, the parent node who will receive a new child)</param> /// <param name="oldChild">The subtree to be replaced</param> /// <param name="newChild">The replacement subtree</param> /// <param name="removeSubtree">Flag used to indicate if whole subtrees should be removed (default behavior), or just the subtree root</param> private void Modify(ISymbolicExpressionTree tree, ISymbolicExpressionTreeNode parent, ISymbolicExpressionTreeNode oldChild, ISymbolicExpressionTreeNode newChild, bool removeSubtree = true) { if (oldChild == null && newChild == null) { throw new ArgumentNullException("Cannot deduce operation type from the arguments. Please provide non null operands."); } if (oldChild == null) { // insertion operation parent.AddSubtree(newChild); newChild.Parent = parent; } else if (newChild == null) { // removal operation parent.RemoveSubtree(parent.IndexOfSubtree(oldChild)); if (!removeSubtree) { for (int i = oldChild.SubtreeCount - 1; i >= 0; --i) { var subtree = oldChild.GetSubtree(i); oldChild.RemoveSubtree(i); parent.AddSubtree(subtree); } } } else { // replacement operation var replacementIndex = parent.IndexOfSubtree(oldChild); parent.RemoveSubtree(replacementIndex); parent.InsertSubtree(replacementIndex, newChild); newChild.Parent = parent; if (changedNodes.ContainsKey(oldChild)) { changedNodes.Add(newChild, changedNodes[oldChild]); // so that on double click the original node is restored changedNodes.Remove(oldChild); } else { changedNodes.Add(newChild, oldChild); } } treeState = IsValid(tree) ? TreeState.Valid : TreeState.Invalid; switch (treeState) { case TreeState.Valid: this.grpViewHost.Enabled = true; UpdateModel(Content.Model.SymbolicExpressionTree); break; case TreeState.Invalid: this.grpViewHost.Enabled = false; break; } }
public static ISymbolicExpressionTree CreateTree( IEnumerable <KeyValuePair <string, IEnumerable <string> > > factors, double[] factorCoefficients, string[] variableNames, double[] coefficients, double @const = 0) { if (factorCoefficients.Length == 0 && coefficients.Length == 0 && @const == 0) { throw new ArgumentException(); } // Combine both trees ISymbolicExpressionTreeNode add = (new Addition()).CreateTreeNode(); // Create tree for double variables if (coefficients.Length > 0) { var varTree = CreateTree(variableNames, new int[variableNames.Length], coefficients); foreach (var varNode in varTree.IterateNodesPrefix().OfType <VariableTreeNode>()) { add.AddSubtree(varNode); } } // Create tree for string variables if (factorCoefficients.Length > 0) { var factorTree = CreateTree(factors, factorCoefficients); foreach (var binFactorNode in factorTree.IterateNodesPrefix().OfType <BinaryFactorVariableTreeNode>()) { add.AddSubtree(binFactorNode); } } if (@const != 0.0) { ConstantTreeNode cNode = (ConstantTreeNode) new Constant().CreateTreeNode(); cNode.Value = @const; add.AddSubtree(cNode); } ISymbolicExpressionTree tree = new SymbolicExpressionTree(new ProgramRootSymbol().CreateTreeNode()); ISymbolicExpressionTreeNode startNode = new StartSymbol().CreateTreeNode(); tree.Root.AddSubtree(startNode); startNode.AddSubtree(add); return(tree); }
/// <summary> /// Remove, Replace or Insert subtrees /// </summary> /// <param name="tree">The symbolic expression tree</param> /// <param name="parent">The insertion point (ie, the parent node who will receive a new child)</param> /// <param name="oldChild">The subtree to be replaced</param> /// <param name="newChild">The replacement subtree</param> /// <param name="removeSubtree">Flag used to indicate if whole subtrees should be removed (default behavior), or just the subtree root</param> private void Modify(ISymbolicExpressionTree tree, ISymbolicExpressionTreeNode parent, ISymbolicExpressionTreeNode oldChild, ISymbolicExpressionTreeNode newChild, bool removeSubtree = true) { if (oldChild == null && newChild == null) throw new ArgumentNullException("Cannot deduce operation type from the arguments. Please provide non null operands."); if (oldChild == null) { // insertion operation parent.AddSubtree(newChild); newChild.Parent = parent; } else if (newChild == null) { // removal operation parent.RemoveSubtree(parent.IndexOfSubtree(oldChild)); if (!removeSubtree) { for (int i = oldChild.SubtreeCount - 1; i >= 0; --i) { var subtree = oldChild.GetSubtree(i); oldChild.RemoveSubtree(i); parent.AddSubtree(subtree); } } } else { // replacement operation var replacementIndex = parent.IndexOfSubtree(oldChild); parent.RemoveSubtree(replacementIndex); parent.InsertSubtree(replacementIndex, newChild); newChild.Parent = parent; if (changedNodes.ContainsKey(oldChild)) { changedNodes.Add(newChild, changedNodes[oldChild]); // so that on double click the original node is restored changedNodes.Remove(oldChild); } else { changedNodes.Add(newChild, oldChild); } } treeState = IsValid(tree) ? TreeState.Valid : TreeState.Invalid; switch (treeState) { case TreeState.Valid: this.grpViewHost.Enabled = true; UpdateModel(Content.Model.SymbolicExpressionTree); break; case TreeState.Invalid: this.grpViewHost.Enabled = false; break; } }
public ISymbolicExpressionTree Parse(string str) { ISymbolicExpressionTreeNode root = programRootSymbol.CreateTreeNode(); ISymbolicExpressionTreeNode start = startSymbol.CreateTreeNode(); var allTokens = GetAllTokens(str).ToArray(); ISymbolicExpressionTreeNode mainBranch = ParseS(new Queue <Token>(allTokens)); // only a main branch was given => insert the main branch into the default tree template root.AddSubtree(start); start.AddSubtree(mainBranch); return(new SymbolicExpressionTree(root)); }
public static void Create(IRandom random, ISymbolicExpressionTreeNode seedNode, int maxDepth) { // make sure it is possible to create a trees smaller than maxDepth if (seedNode.Grammar.GetMinimumExpressionDepth(seedNode.Symbol) > maxDepth) { throw new ArgumentException("Cannot create trees of depth " + maxDepth + " or smaller because of grammar constraints.", "maxDepth"); } int arity = seedNode.Grammar.GetMaximumSubtreeCount(seedNode.Symbol); // Throw an exception if the seedNode happens to be a terminal, since in this case we cannot grow a tree. if (arity <= 0) { throw new ArgumentException("Cannot grow tree. Seed node shouldn't have arity zero."); } var allowedSymbols = seedNode.Grammar.AllowedSymbols .Where(s => s.InitialFrequency > 0.0 && seedNode.Grammar.GetMaximumSubtreeCount(s) > 0) .ToList(); for (var i = 0; i < arity; i++) { var possibleSymbols = allowedSymbols .Where(s => seedNode.Grammar.IsAllowedChildSymbol(seedNode.Symbol, s, i) && seedNode.Grammar.GetMinimumExpressionDepth(s) <= maxDepth && seedNode.Grammar.GetMaximumExpressionDepth(s) >= maxDepth) .ToList(); var weights = possibleSymbols.Select(s => s.InitialFrequency).ToList(); #pragma warning disable 612, 618 var selectedSymbol = possibleSymbols.SelectRandom(weights, random); #pragma warning restore 612, 618 var tree = selectedSymbol.CreateTreeNode(); if (tree.HasLocalParameters) { tree.ResetLocalParameters(random); } seedNode.AddSubtree(tree); } // Only iterate over the non-terminal nodes (those which have arity > 0) // Start from depth 2 since the first two levels are formed by the rootNode and the seedNode foreach (var subTree in seedNode.Subtrees) { if (subTree.Grammar.GetMaximumSubtreeCount(subTree.Symbol) > 0) { RecursiveCreate(random, subTree, 2, maxDepth); } } }
private static void RecursiveCreate(IRandom random, ISymbolicExpressionTreeNode root, int currentDepth, int maxDepth) { var arity = root.Grammar.GetMaximumSubtreeCount(root.Symbol); // In the 'Full' grow method, we cannot have terminals on the intermediate tree levels. if (arity <= 0) { throw new ArgumentException("Cannot grow node of arity zero. Expected a function node."); } var allowedSymbols = root.Grammar.AllowedSymbols .Where(s => s.InitialFrequency > 0.0) .ToList(); for (var i = 0; i < arity; i++) { var possibleSymbols = allowedSymbols .Where(s => root.Grammar.IsAllowedChildSymbol(root.Symbol, s, i) && root.Grammar.GetMinimumExpressionDepth(s) - 1 <= maxDepth - currentDepth && root.Grammar.GetMaximumExpressionDepth(s) > maxDepth - currentDepth) .ToList(); if (!possibleSymbols.Any()) { throw new InvalidOperationException("No symbols are available for the tree."); } var weights = possibleSymbols.Select(s => s.InitialFrequency).ToList(); #pragma warning disable 612, 618 var selectedSymbol = possibleSymbols.SelectRandom(weights, random); #pragma warning restore 612, 618 var tree = selectedSymbol.CreateTreeNode(); if (tree.HasLocalParameters) { tree.ResetLocalParameters(random); } root.AddSubtree(tree); } //additional levels should only be added if the maximum depth is not reached yet if (maxDepth > currentDepth) { foreach (var subTree in root.Subtrees) { if (subTree.Grammar.GetMaximumSubtreeCount(subTree.Symbol) > 0) { RecursiveCreate(random, subTree, currentDepth + 1, maxDepth); } } } }
private static void RecursiveCreate(IRandom random, ISymbolicExpressionTreeNode root, int currentDepth, int maxDepth) { var arity = SampleArity(random, root); if (arity == 0) { return; } var allowedSymbols = root.Grammar.AllowedSymbols.Where(s => s.InitialFrequency > 0.0).ToList(); for (var i = 0; i < arity; i++) { var possibleSymbols = allowedSymbols.Where(s => root.Grammar.IsAllowedChildSymbol(root.Symbol, s, i) && root.Grammar.GetMinimumExpressionDepth(s) - 1 <= maxDepth - currentDepth).ToList(); if (!possibleSymbols.Any()) { throw new InvalidOperationException("No symbols are available for the tree."); } var weights = possibleSymbols.Select(s => s.InitialFrequency).ToList(); #pragma warning disable 612, 618 var selectedSymbol = possibleSymbols.SelectRandom(weights, random); #pragma warning restore 612, 618 var tree = selectedSymbol.CreateTreeNode(); if (tree.HasLocalParameters) { tree.ResetLocalParameters(random); } root.AddSubtree(tree); } if (maxDepth > currentDepth) { foreach (var subTree in root.Subtrees) { if (subTree.Grammar.GetMaximumSubtreeCount(subTree.Symbol) != 0) { RecursiveCreate(random, subTree, currentDepth + 1, maxDepth); } } } }
public ISymbolicExpressionTree Import(string str) { str = str.Replace("(", " ( ").Replace(")", " ) "); ISymbolicExpressionTreeNode root = programRootSymbol.CreateTreeNode(); ISymbolicExpressionTreeNode start = startSymbol.CreateTreeNode(); ISymbolicExpressionTreeNode mainBranch = ParseSexp(new Queue <Token>(GetTokenStream(str))); if (mainBranch.Symbol is ProgramRootSymbol) { // when a root symbol was parsed => use main branch as root root = mainBranch; } else { // only a main branch was given => insert the main branch into the default tree template root.AddSubtree(start); start.AddSubtree(mainBranch); } return(new SymbolicExpressionTree(root)); }
/// <summary> /// Genotype-to-Phenotype mapper (iterative 𝜋GE approach, using a list of not expanded nonTerminals). /// </summary> /// <param name="startNode">first node of the tree with arity 1</param> /// <param name="genotype">integer vector, which should be mapped to a tree</param> /// <param name="grammar">grammar to determine the allowed child symbols for each node</param> /// <param name="maxSubtreeCount">maximum allowed subtrees (= number of used genomes)</param> /// <param name="random">random number generator</param> private void MapPIGEIteratively(ISymbolicExpressionTreeNode startNode, IntegerVector genotype, ISymbolicExpressionGrammar grammar, int maxSubtreeCount, IRandom random) { List <ISymbolicExpressionTreeNode> nonTerminals = new List <ISymbolicExpressionTreeNode>(); int genotypeIndex = 0; nonTerminals.Add(startNode); while (nonTerminals.Count > 0) { if (genotypeIndex >= maxSubtreeCount) { // if all genomes were used, only add terminal nodes to the remaining subtrees ISymbolicExpressionTreeNode current = nonTerminals[0]; nonTerminals.RemoveAt(0); current.AddSubtree(GetRandomTerminalNode(current, grammar, random)); } else { // Order: NT = nont % Num. NT int nt = NontVector[genotypeIndex] % nonTerminals.Count; ISymbolicExpressionTreeNode current = nonTerminals[nt]; nonTerminals.RemoveAt(nt); // Content: Rule = rule % Num. Rules ISymbolicExpressionTreeNode newNode = GetNewChildNode(current, genotype, grammar, genotypeIndex, random); int arity = SampleArity(random, newNode, grammar); current.AddSubtree(newNode); genotypeIndex++; // new node has subtrees, so add "arity" number of copies of this node to the nonTerminals list for (int i = 0; i < arity; ++i) { nonTerminals.Add(newNode); } } } }
/// <summary> /// Genotype-to-Phenotype mapper (iterative random approach, where the next non-terminal /// symbol to expand is randomly determined). /// </summary> /// <param name="startNode">first node of the tree with arity 1</param> /// <param name="genotype">integer vector, which should be mapped to a tree</param> /// <param name="grammar">grammar to determine the allowed child symbols for each node</param> /// <param name="maxSubtreeCount">maximum allowed subtrees (= number of used genomes)</param> /// <param name="random">random number generator</param> private void MapRandomIteratively(ISymbolicExpressionTreeNode startNode, IntegerVector genotype, ISymbolicExpressionGrammar grammar, int maxSubtreeCount, IRandom random) { List <ISymbolicExpressionTreeNode> nonTerminals = new List <ISymbolicExpressionTreeNode>(); int genotypeIndex = 0; nonTerminals.Add(startNode); while (nonTerminals.Count > 0) { if (genotypeIndex >= maxSubtreeCount) { // if all genomes were used, only add terminal nodes to the remaining subtrees ISymbolicExpressionTreeNode current = nonTerminals[0]; nonTerminals.RemoveAt(0); current.AddSubtree(GetRandomTerminalNode(current, grammar, random)); } else { // similar to PIGEMapper, but here the current node is determined randomly ... ISymbolicExpressionTreeNode current = nonTerminals.SampleRandom(random); nonTerminals.Remove(current); ISymbolicExpressionTreeNode newNode = GetNewChildNode(current, genotype, grammar, genotypeIndex, random); int arity = SampleArity(random, newNode, grammar); current.AddSubtree(newNode); genotypeIndex++; // new node has subtrees, so add "arity" number of copies of this node to the nonTerminals list for (int i = 0; i < arity; ++i) { nonTerminals.Add(newNode); } } } }
private static ISymbolicExpressionTreeNode DisconnectBranches(ISymbolicExpressionTreeNode node, List <CutPoint> argumentCutPoints) { int argumentIndex = argumentCutPoints.FindIndex(x => x.Child == node); if (argumentIndex != -1) { var argSymbol = new Argument(argumentIndex); return(argSymbol.CreateTreeNode()); } // remove the subtrees so that we can clone only the root node List <ISymbolicExpressionTreeNode> subtrees = new List <ISymbolicExpressionTreeNode>(node.Subtrees); while (node.Subtrees.Count() > 0) { node.RemoveSubtree(0); } // recursively apply function for subtrees or append a argument terminal node foreach (var subtree in subtrees) { node.AddSubtree(DisconnectBranches(subtree, argumentCutPoints)); } return(node); }
// the argumentTrees list contains already expanded trees used as arguments for invocations private ISymbolicExpressionTreeNode MacroExpand(ISymbolicExpressionTreeNode root, ISymbolicExpressionTreeNode node, IList<ISymbolicExpressionTreeNode> argumentTrees) { List<ISymbolicExpressionTreeNode> subtrees = new List<ISymbolicExpressionTreeNode>(node.Subtrees); while (node.SubtreeCount > 0) node.RemoveSubtree(0); if (node.Symbol is InvokeFunction) { var invokeSym = node.Symbol as InvokeFunction; var defunNode = FindFunctionDefinition(root, invokeSym.FunctionName); var macroExpandedArguments = new List<ISymbolicExpressionTreeNode>(); foreach (var subtree in subtrees) { macroExpandedArguments.Add(MacroExpand(root, subtree, argumentTrees)); } return MacroExpand(root, defunNode, macroExpandedArguments); } else if (node.Symbol is Argument) { var argSym = node.Symbol as Argument; // return the correct argument sub-tree (already macro-expanded) return (SymbolicExpressionTreeNode)argumentTrees[argSym.ArgumentIndex].Clone(); } else { // recursive application foreach (var subtree in subtrees) { node.AddSubtree(MacroExpand(root, subtree, argumentTrees)); } return node; } }
public static ISymbolicExpressionTree CreateTree( IEnumerable <KeyValuePair <string, IEnumerable <string> > > factors, double[] factorCoefficients, string[] variableNames, double[] coefficients, double @const = 0) { if (factorCoefficients.Length == 0 && coefficients.Length == 0) { throw new ArgumentException(); } ISymbolicExpressionTree p1 = null; if (coefficients.Length > 0) { p1 = CreateTree(variableNames, new int[variableNames.Length], coefficients, @const); if (factorCoefficients.Length == 0) { return(p1); } } if (factorCoefficients.Length > 0) { var p2 = CreateTree(factors, factorCoefficients); if (p1 == null) { return(p2); } // combine ISymbolicExpressionTreeNode add = p1.Root.GetSubtree(0).GetSubtree(0); foreach (var binFactorNode in p2.IterateNodesPrefix().OfType <BinaryFactorVariableTreeNode>()) { add.AddSubtree(binFactorNode); } return(p1); } throw new ArgumentException(); }
private static ISymbolicExpressionTreeNode ReplaceArgumentsInBranch(ISymbolicExpressionTreeNode branch, IEnumerable <ISymbolicExpressionTreeNode> argumentTrees) { ArgumentTreeNode argNode = branch as ArgumentTreeNode; if (argNode != null) { // replace argument nodes by a clone of the original subtree that provided the result for the argument node return((SymbolicExpressionTreeNode)argumentTrees.ElementAt(argNode.Symbol.ArgumentIndex).Clone()); } else { // call recursively for all subtree List <ISymbolicExpressionTreeNode> subtrees = new List <ISymbolicExpressionTreeNode>(branch.Subtrees); while (branch.Subtrees.Count() > 0) { branch.RemoveSubtree(0); } foreach (var subtree in subtrees) { branch.AddSubtree(ReplaceArgumentsInBranch(subtree, argumentTrees)); } return(branch); } }
private ISymbolicExpressionTreeNode SimplifyAny(ISymbolicExpressionTreeNode original) { // can't simplify this function but simplify all subtrees List<ISymbolicExpressionTreeNode> subtrees = new List<ISymbolicExpressionTreeNode>(original.Subtrees); while (original.Subtrees.Count() > 0) original.RemoveSubtree(0); var clone = (SymbolicExpressionTreeNode)original.Clone(); List<ISymbolicExpressionTreeNode> simplifiedSubtrees = new List<ISymbolicExpressionTreeNode>(); foreach (var subtree in subtrees) { simplifiedSubtrees.Add(GetSimplifiedTree(subtree)); original.AddSubtree(subtree); } foreach (var simplifiedSubtree in simplifiedSubtrees) { clone.AddSubtree(simplifiedSubtree); } if (simplifiedSubtrees.TrueForAll(t => IsConstant(t))) { SimplifyConstantExpression(clone); } return clone; }
private static ISymbolicExpressionTreeNode DisconnectBranches(ISymbolicExpressionTreeNode node, List<CutPoint> argumentCutPoints) { int argumentIndex = argumentCutPoints.FindIndex(x => x.Child == node); if (argumentIndex != -1) { var argSymbol = new Argument(argumentIndex); return argSymbol.CreateTreeNode(); } // remove the subtrees so that we can clone only the root node List<ISymbolicExpressionTreeNode> subtrees = new List<ISymbolicExpressionTreeNode>(node.Subtrees); while (node.Subtrees.Count() > 0) node.RemoveSubtree(0); // recursively apply function for subtrees or append a argument terminal node foreach (var subtree in subtrees) { node.AddSubtree(DisconnectBranches(subtree, argumentCutPoints)); } return node; }
private ISymbolicExpressionTreeNode MakeProduct(ISymbolicExpressionTreeNode a, ISymbolicExpressionTreeNode b) { if (IsConstant(a) && IsConstant(b)) { // fold constants ((ConstantTreeNode)a).Value *= ((ConstantTreeNode)b).Value; return a; } else if (IsConstant(a)) { // a * $ => $ * a return MakeProduct(b, a); } else if (IsConstant(b) && ((ConstantTreeNode)b).Value.IsAlmost(1.0)) { // $ * 1.0 => $ return a; } else if (IsConstant(b) && IsVariable(a)) { // multiply constants into variables weights ((VariableTreeNode)a).Weight *= ((ConstantTreeNode)b).Value; return a; } else if (IsConstant(b) && IsAddition(a)) { // multiply constants into additions return a.Subtrees.Select(x => MakeProduct(x, b)).Aggregate((c, d) => MakeSum(c, d)); } else if (IsDivision(a) && IsDivision(b)) { // (a1 / a2) * (b1 / b2) => (a1 * b1) / (a2 * b2) return MakeFraction(MakeProduct(a.GetSubtree(0), b.GetSubtree(0)), MakeProduct(a.GetSubtree(1), b.GetSubtree(1))); } else if (IsDivision(a)) { // (a1 / a2) * b => (a1 * b) / a2 return MakeFraction(MakeProduct(a.GetSubtree(0), b), a.GetSubtree(1)); } else if (IsDivision(b)) { // a * (b1 / b2) => (b1 * a) / b2 return MakeFraction(MakeProduct(b.GetSubtree(0), a), b.GetSubtree(1)); } else if (IsMultiplication(a) && IsMultiplication(b)) { // merge multiplications (make sure constants are merged) var mul = mulSymbol.CreateTreeNode(); for (int i = 0; i < a.Subtrees.Count(); i++) mul.AddSubtree(a.GetSubtree(i)); for (int i = 0; i < b.Subtrees.Count(); i++) mul.AddSubtree(b.GetSubtree(i)); MergeVariablesAndConstantsInProduct(mul); return mul; } else if (IsMultiplication(b)) { return MakeProduct(b, a); } else if (IsMultiplication(a)) { // a is already an multiplication => append b a.AddSubtree(b); MergeVariablesAndConstantsInProduct(a); return a; } else { var mul = mulSymbol.CreateTreeNode(); mul.AddSubtree(a); mul.AddSubtree(b); MergeVariablesAndConstantsInProduct(mul); return mul; } }
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 ISymbolicExpressionTreeNode AddLagToDynamicNodes(ISymbolicExpressionTreeNode node, int lag) { var laggedTreeNode = node as ILaggedTreeNode; var variableNode = node as VariableTreeNode; var variableConditionNode = node as VariableConditionTreeNode; if (laggedTreeNode != null) laggedTreeNode.Lag += lag; else if (variableNode != null) { var laggedVariableNode = (LaggedVariableTreeNode)laggedVariableSymbol.CreateTreeNode(); laggedVariableNode.Lag = lag; laggedVariableNode.VariableName = variableNode.VariableName; return laggedVariableNode; } else if (variableConditionNode != null) { throw new NotSupportedException("Removal of time lags around variable condition symbols is not allowed."); } var subtrees = new List<ISymbolicExpressionTreeNode>(node.Subtrees); while (node.SubtreeCount > 0) node.RemoveSubtree(0); foreach (var subtree in subtrees) { node.AddSubtree(AddLagToDynamicNodes(subtree, lag)); } return node; }
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; }
// helper to combine the constant factors in products and to combine variables (powers of 2, 3...) private void MergeVariablesAndConstantsInProduct(ISymbolicExpressionTreeNode prod) { var subtrees = new List<ISymbolicExpressionTreeNode>(prod.Subtrees); while (prod.Subtrees.Any()) prod.RemoveSubtree(0); var groupedVarNodes = from node in subtrees.OfType<VariableTreeNode>() let lag = (node is LaggedVariableTreeNode) ? ((LaggedVariableTreeNode)node).Lag : 0 group node by node.VariableName + lag into g orderby g.Count() select g; var constantProduct = (from node in subtrees.OfType<VariableTreeNode>() select node.Weight) .Concat(from node in subtrees.OfType<ConstantTreeNode>() select node.Value) .DefaultIfEmpty(1.0) .Aggregate((c1, c2) => c1 * c2); var unchangedSubtrees = from tree in subtrees where !(tree is VariableTreeNode) where !(tree is ConstantTreeNode) select tree; foreach (var variableNodeGroup in groupedVarNodes) { var representative = variableNodeGroup.First(); representative.Weight = 1.0; if (variableNodeGroup.Count() > 1) { var poly = mulSymbol.CreateTreeNode(); for (int p = 0; p < variableNodeGroup.Count(); p++) { poly.AddSubtree((ISymbolicExpressionTreeNode)representative.Clone()); } prod.AddSubtree(poly); } else { prod.AddSubtree(representative); } } foreach (var unchangedSubtree in unchangedSubtrees) prod.AddSubtree(unchangedSubtree); if (!constantProduct.IsAlmost(1.0)) { prod.AddSubtree(MakeConstant(constantProduct)); } }
// makes sure variable symbols in sums are combined // possible improvement: combine sums of products where the products only reference the same variable private void MergeVariablesInSum(ISymbolicExpressionTreeNode sum) { var subtrees = new List<ISymbolicExpressionTreeNode>(sum.Subtrees); while (sum.Subtrees.Any()) sum.RemoveSubtree(0); var groupedVarNodes = from node in subtrees.OfType<VariableTreeNode>() let lag = (node is LaggedVariableTreeNode) ? ((LaggedVariableTreeNode)node).Lag : 0 group node by node.VariableName + lag into g select g; var unchangedSubtrees = subtrees.Where(t => !(t is VariableTreeNode)); foreach (var variableNodeGroup in groupedVarNodes) { var weightSum = variableNodeGroup.Select(t => t.Weight).Sum(); var representative = variableNodeGroup.First(); representative.Weight = weightSum; sum.AddSubtree(representative); } foreach (var unchangedSubtree in unchangedSubtrees) sum.AddSubtree(unchangedSubtree); }
/// <summary> /// x => x * -1 /// Doesn't create new trees and manipulates x /// </summary> /// <param name="x"></param> /// <returns>-x</returns> private ISymbolicExpressionTreeNode Negate(ISymbolicExpressionTreeNode x) { if (IsConstant(x)) { ((ConstantTreeNode)x).Value *= -1; } else if (IsVariable(x)) { var variableTree = (VariableTreeNode)x; variableTree.Weight *= -1.0; } else if (IsAddition(x)) { // (x0 + x1 + .. + xn) * -1 => (-x0 + -x1 + .. + -xn) var subtrees = new List<ISymbolicExpressionTreeNode>(x.Subtrees); while (x.Subtrees.Any()) x.RemoveSubtree(0); foreach (var subtree in subtrees) { x.AddSubtree(Negate(subtree)); } } else if (IsMultiplication(x) || IsDivision(x)) { // x0 * x1 * .. * xn * -1 => x0 * x1 * .. * -xn var lastSubTree = x.Subtrees.Last(); x.RemoveSubtree(x.SubtreeCount - 1); x.AddSubtree(Negate(lastSubTree)); // last is maybe a constant, prefer to negate the constant } else { // any other function return MakeProduct(x, MakeConstant(-1)); } return x; }
private static void RecursiveCreate(IRandom random, ISymbolicExpressionTreeNode root, int currentDepth, int maxDepth) { var arity = root.Grammar.GetMaximumSubtreeCount(root.Symbol); // In the 'Full' grow method, we cannot have terminals on the intermediate tree levels. if (arity <= 0) throw new ArgumentException("Cannot grow node of arity zero. Expected a function node."); var allowedSymbols = root.Grammar.AllowedSymbols .Where(s => s.InitialFrequency > 0.0) .ToList(); for (var i = 0; i < arity; i++) { var possibleSymbols = allowedSymbols .Where(s => root.Grammar.IsAllowedChildSymbol(root.Symbol, s, i) && root.Grammar.GetMinimumExpressionDepth(s) - 1 <= maxDepth - currentDepth && root.Grammar.GetMaximumExpressionDepth(s) > maxDepth - currentDepth) .ToList(); if (!possibleSymbols.Any()) throw new InvalidOperationException("No symbols are available for the tree."); var weights = possibleSymbols.Select(s => s.InitialFrequency).ToList(); #pragma warning disable 612, 618 var selectedSymbol = possibleSymbols.SelectRandom(weights, random); #pragma warning restore 612, 618 var tree = selectedSymbol.CreateTreeNode(); if (tree.HasLocalParameters) tree.ResetLocalParameters(random); root.AddSubtree(tree); } //additional levels should only be added if the maximum depth is not reached yet if (maxDepth > currentDepth) { foreach (var subTree in root.Subtrees) if (subTree.Grammar.GetMaximumSubtreeCount(subTree.Symbol) > 0) RecursiveCreate(random, subTree, currentDepth + 1, maxDepth); } }
private static void RecursiveCreate(IRandom random, ISymbolicExpressionTreeNode root, int currentDepth, int maxDepth) { var arity = SampleArity(random, root); if (arity == 0) return; var allowedSymbols = root.Grammar.AllowedSymbols.Where(s => s.InitialFrequency > 0.0).ToList(); for (var i = 0; i < arity; i++) { var possibleSymbols = allowedSymbols.Where(s => root.Grammar.IsAllowedChildSymbol(root.Symbol, s, i) && root.Grammar.GetMinimumExpressionDepth(s) - 1 <= maxDepth - currentDepth).ToList(); if (!possibleSymbols.Any()) throw new InvalidOperationException("No symbols are available for the tree."); var weights = possibleSymbols.Select(s => s.InitialFrequency).ToList(); #pragma warning disable 612, 618 var selectedSymbol = possibleSymbols.SelectRandom(weights, random); #pragma warning restore 612, 618 var tree = selectedSymbol.CreateTreeNode(); if (tree.HasLocalParameters) tree.ResetLocalParameters(random); root.AddSubtree(tree); } if (maxDepth > currentDepth) foreach (var subTree in root.Subtrees) if (subTree.Grammar.GetMaximumSubtreeCount(subTree.Symbol) != 0) RecursiveCreate(random, subTree, currentDepth + 1, maxDepth); }
public static void Create(IRandom random, ISymbolicExpressionTreeNode seedNode, int maxDepth) { // make sure it is possible to create a trees smaller than maxDepth if (seedNode.Grammar.GetMinimumExpressionDepth(seedNode.Symbol) > maxDepth) throw new ArgumentException("Cannot create trees of depth " + maxDepth + " or smaller because of grammar constraints.", "maxDepth"); var arity = SampleArity(random, seedNode); // throw an exception if the seedNode happens to be a terminal, since in this case we cannot grow a tree if (arity <= 0) throw new ArgumentException("Cannot grow tree. Seed node shouldn't have arity zero."); var allowedSymbols = seedNode.Grammar.AllowedSymbols.Where(s => s.InitialFrequency > 0.0).ToList(); for (var i = 0; i < arity; i++) { var possibleSymbols = allowedSymbols.Where(s => seedNode.Grammar.IsAllowedChildSymbol(seedNode.Symbol, s, i)).ToList(); var weights = possibleSymbols.Select(s => s.InitialFrequency).ToList(); #pragma warning disable 612, 618 var selectedSymbol = possibleSymbols.SelectRandom(weights, random); #pragma warning restore 612, 618 var tree = selectedSymbol.CreateTreeNode(); if (tree.HasLocalParameters) tree.ResetLocalParameters(random); seedNode.AddSubtree(tree); } // Only iterate over the non-terminal nodes (those which have arity > 0) // Start from depth 2 since the first two levels are formed by the rootNode and the seedNode foreach (var subTree in seedNode.Subtrees) if (subTree.Grammar.GetMaximumSubtreeCount(subTree.Symbol) > 0) RecursiveCreate(random, subTree, 2, maxDepth); }
private static ISymbolicExpressionTreeNode ReplaceArgumentsInBranch(ISymbolicExpressionTreeNode branch, IEnumerable<ISymbolicExpressionTreeNode> argumentTrees) { ArgumentTreeNode argNode = branch as ArgumentTreeNode; if (argNode != null) { // replace argument nodes by a clone of the original subtree that provided the result for the argument node return (SymbolicExpressionTreeNode)argumentTrees.ElementAt(argNode.Symbol.ArgumentIndex).Clone(); } else { // call recursively for all subtree List<ISymbolicExpressionTreeNode> subtrees = new List<ISymbolicExpressionTreeNode>(branch.Subtrees); while (branch.Subtrees.Count() > 0) branch.RemoveSubtree(0); foreach (var subtree in subtrees) { branch.AddSubtree(ReplaceArgumentsInBranch(subtree, argumentTrees)); } return branch; } }