Free cookie consent management tool by TermsFeed Policy Generator

Ignore:
Timestamp:
04/15/10 19:58:42 (15 years ago)
Author:
gkronber
Message:

Fixed bugs in ADF operators and added test classes for ADF operators. #290 (Implement ADFs)

Location:
trunk/sources/HeuristicLab.Encodings.SymbolicExpressionTreeEncoding/3.3/ArchitectureAlteringOperators
Files:
1 added
7 edited

Legend:

Unmodified
Added
Removed
  • trunk/sources/HeuristicLab.Encodings.SymbolicExpressionTreeEncoding/3.3/ArchitectureAlteringOperators/ArgumentCreater.cs

    r3338 r3360  
    9696        // append a new argument branch after expanding all argument nodes
    9797        var clonedBranch = (SymbolicExpressionTreeNode)replacedBranch.Clone();
    98         ReplaceArgumentsInBranch(clonedBranch, invocationNode.SubTrees);
     98        clonedBranch = ReplaceArgumentsInBranch(clonedBranch, invocationNode.SubTrees);
    9999        invocationNode.InsertSubTree(newArgumentIndex, clonedBranch);
    100100      }
     
    113113      foreach (var subtree in symbolicExpressionTree.Root.SubTrees) {
    114114        // when the changed function is known in the branch then update the number of arguments
    115         var matchingSymbol = subtree.Grammar.Symbols.Where(s => s.Name == selectedDefunBranch.FunctionName).SingleOrDefault();
     115        var matchingSymbol = subtree.Grammar.Symbols.OfType<InvokeFunction>().Where(s => s.FunctionName == selectedDefunBranch.FunctionName).SingleOrDefault();
    116116        if (matchingSymbol != null) {
    117117          subtree.Grammar.SetMinSubtreeCount(matchingSymbol, selectedDefunBranch.NumberOfArguments);
    118118          subtree.Grammar.SetMaxSubtreeCount(matchingSymbol, selectedDefunBranch.NumberOfArguments);
     119          foreach (var child in subtree.GetAllowedSymbols(0)) {
     120            for (int i = 0; i < subtree.Grammar.GetMaxSubtreeCount(matchingSymbol); i++) {
     121              subtree.Grammar.SetAllowedChild(matchingSymbol, child, i);
     122            }
     123          }
    119124        }
    120125      }
     
    122127    }
    123128
    124     private static void ReplaceArgumentsInBranch(SymbolicExpressionTreeNode branch, IList<SymbolicExpressionTreeNode> argumentTrees) {
    125       // check if any subtree is an argument node
    126       for (int subtreeIndex = 0; subtreeIndex < branch.SubTrees.Count; subtreeIndex++) {
    127         var subtree = branch.SubTrees[subtreeIndex];
    128         var argNode = subtree as ArgumentTreeNode;
    129         if (argNode != null) {
    130           // replace argument nodes by a clone of the original subtree that provided the result for the argument node
    131           branch.SubTrees[subtreeIndex] = (SymbolicExpressionTreeNode)argumentTrees[argNode.Symbol.ArgumentIndex].Clone();
    132         } else {
    133           // recursively replace arguments in all branches
    134           ReplaceArgumentsInBranch(subtree, argumentTrees);
     129    private static SymbolicExpressionTreeNode ReplaceArgumentsInBranch(SymbolicExpressionTreeNode branch, IList<SymbolicExpressionTreeNode> argumentTrees) {
     130      if (branch is ArgumentTreeNode) {
     131        var argNode = branch as ArgumentTreeNode;
     132        // replace argument nodes by a clone of the original subtree that provided the result for the argument node
     133        return (SymbolicExpressionTreeNode)argumentTrees[argNode.Symbol.ArgumentIndex].Clone();
     134      } else {
     135        // call recursively for all subtree
     136        List<SymbolicExpressionTreeNode> subtrees = new List<SymbolicExpressionTreeNode>(branch.SubTrees);
     137        while (branch.SubTrees.Count > 0) branch.SubTrees.RemoveAt(0);
     138        foreach (var subtree in subtrees) {
     139          branch.AddSubTree(ReplaceArgumentsInBranch(subtree, argumentTrees));
    135140        }
     141        return branch;
    136142      }
    137143    }
  • trunk/sources/HeuristicLab.Encodings.SymbolicExpressionTreeEncoding/3.3/ArchitectureAlteringOperators/ArgumentDeleter.cs

    r3338 r3360  
    6565        // argument deletion by consolidation is not possible => abort
    6666        return false;
     67      // the argument to be removed is always the one with the largest index
     68      // (otherwise we would have to decrement the index of the larger argument symbols)
    6769      var removedArgument = (from sym in selectedDefunBranch.Grammar.Symbols.OfType<Argument>()
    68                              select sym.ArgumentIndex).Distinct().SelectRandom(random);
     70                             select sym.ArgumentIndex).Distinct().OrderBy(x => x).Last();
    6971      // find invocations of the manipulated funcion and remove the specified argument tree
    70       var invocationNodes = from node in symbolicExpressionTree.IterateNodesPrefix().OfType<InvokeFunctionTreeNode>()
    71                             where node.Symbol.FunctionName == selectedDefunBranch.FunctionName
    72                             select node;
     72      var invocationNodes = (from node in symbolicExpressionTree.IterateNodesPrefix().OfType<InvokeFunctionTreeNode>()
     73                             where node.Symbol.FunctionName == selectedDefunBranch.FunctionName
     74                             select node).ToList();
    7375      foreach (var invokeNode in invocationNodes) {
    7476        invokeNode.RemoveSubTree(removedArgument);
     
    7880
    7981      // delete the dynamic argument symbol that matches the argument to be removed
    80       var matchingSymbol = selectedDefunBranch.Grammar.Symbols.OfType<Argument>().Where(s => s.ArgumentIndex == removedArgument).First();
     82      var matchingSymbol = selectedDefunBranch.Grammar.Symbols.OfType<Argument>().Where(s => s.ArgumentIndex == removedArgument).Single();
    8183      selectedDefunBranch.Grammar.RemoveSymbol(matchingSymbol);
     84      selectedDefunBranch.NumberOfArguments--;
    8285      // reduce arity in known functions of all root branches
    8386      foreach (var subtree in symbolicExpressionTree.Root.SubTrees) {
    84         var matchingInvokeSymbol = subtree.Grammar.Symbols.OfType<InvokeFunction>().Where(s => s.FunctionName == selectedDefunBranch.FunctionName).FirstOrDefault();
     87        var matchingInvokeSymbol = subtree.Grammar.Symbols.OfType<InvokeFunction>().Where(s => s.FunctionName == selectedDefunBranch.FunctionName).SingleOrDefault();
    8588        if (matchingInvokeSymbol != null) {
    86           subtree.Grammar.SetMinSubtreeCount(matchingInvokeSymbol, selectedDefunBranch.NumberOfArguments - 1);
    87           subtree.Grammar.SetMaxSubtreeCount(matchingInvokeSymbol, selectedDefunBranch.NumberOfArguments - 1);
     89          subtree.Grammar.SetMinSubtreeCount(matchingInvokeSymbol, selectedDefunBranch.NumberOfArguments);
     90          subtree.Grammar.SetMaxSubtreeCount(matchingInvokeSymbol, selectedDefunBranch.NumberOfArguments);
    8891        }
    8992      }
    90       selectedDefunBranch.NumberOfArguments--;
    9193      return true;
    9294    }
  • trunk/sources/HeuristicLab.Encodings.SymbolicExpressionTreeEncoding/3.3/ArchitectureAlteringOperators/ArgumentDuplicater.cs

    r3338 r3360  
    6464        return false;
    6565
    66       var selectedDefunBranch = SelectRandomBranch(random, functionDefiningBranches);
    67       var argumentNodes = from node in IterateNodesPrefix(selectedDefunBranch)
    68                           where node is ArgumentTreeNode
    69                           select (ArgumentTreeNode)node;
    70       if (argumentNodes.Count() == 0 || argumentNodes.Count() >= maxFunctionArguments)
     66      var selectedDefunBranch = functionDefiningBranches.SelectRandom(random);
     67      var argumentSymbols = selectedDefunBranch.Grammar.Symbols.OfType<Argument>();
     68      if (argumentSymbols.Count() == 0 || argumentSymbols.Count() >= maxFunctionArguments)
    7169        // when no argument or number of arguments is already at max allowed value => abort
    7270        return false;
    73       var distinctArgumentIndexes = (from node in argumentNodes
    74                                      select node.ArgumentIndex).Distinct().ToList();
    75       var selectedArgumentIndex = distinctArgumentIndexes[random.Next(distinctArgumentIndexes.Count)];
    76       var newArgumentIndex = allowedArgumentIndexes.Except(from argNode in argumentNodes select argNode.ArgumentIndex).First();
     71      var selectedArgumentSymbol = argumentSymbols.SelectRandom(random);
     72      var takenIndexes = argumentSymbols.Select(s => s.ArgumentIndex);
     73      var newArgumentIndex = allowedArgumentIndexes.Except(takenIndexes).First();
     74
     75      var newArgSymbol = new Argument(newArgumentIndex);
     76
    7777      // replace existing references to the original argument with references to the new argument randomly in the selectedBranch
     78      var argumentNodes = selectedDefunBranch.IterateNodesPrefix().OfType<ArgumentTreeNode>();
    7879      foreach (var argNode in argumentNodes) {
    79         if (argNode.ArgumentIndex == selectedArgumentIndex) {
     80        if (argNode.Symbol == selectedArgumentSymbol) {
    8081          if (random.NextDouble() < 0.5) {
    81             argNode.ArgumentIndex = newArgumentIndex;
     82            argNode.Symbol = newArgSymbol;
    8283          }
    8384        }
    8485      }
    8586      // find invocations of the functions and duplicate the matching argument branch
    86       var invocationNodes = from node in symbolicExpressionTree.IterateNodesPrefix()
    87                             let invokeNode = node as InvokeFunctionTreeNode
    88                             where invokeNode != null
    89                             where invokeNode.InvokedFunctionName == selectedDefunBranch.Name
    90                             select invokeNode;
     87      var invocationNodes = from node in symbolicExpressionTree.IterateNodesPrefix().OfType<InvokeFunctionTreeNode>()
     88                            where node.Symbol.FunctionName == selectedDefunBranch.FunctionName
     89                            select node;
    9190      foreach (var invokeNode in invocationNodes) {
    92         var argumentBranch = invokeNode.SubTrees[selectedArgumentIndex];
     91        var argumentBranch = invokeNode.SubTrees[selectedArgumentSymbol.ArgumentIndex];
    9392        var clonedArgumentBranch = (SymbolicExpressionTreeNode)argumentBranch.Clone();
    9493        invokeNode.InsertSubTree(newArgumentIndex, clonedArgumentBranch);
    9594      }
    96       // register the new argument node and increase the number of arguments of the ADF
    97       selectedDefunBranch.AddDynamicSymbol("ARG" + newArgumentIndex);
     95      // register the new argument symbol and increase the number of arguments of the ADF
     96      selectedDefunBranch.Grammar.AddSymbol(newArgSymbol);
     97      selectedDefunBranch.Grammar.SetMinSubtreeCount(newArgSymbol, 0);
     98      selectedDefunBranch.Grammar.SetMaxSubtreeCount(newArgSymbol, 0);
     99      // allow the argument as child of any other symbol
     100      foreach (var symb in selectedDefunBranch.Grammar.Symbols)
     101        for (int i = 0; i < selectedDefunBranch.Grammar.GetMaxSubtreeCount(symb); i++) {
     102          selectedDefunBranch.Grammar.SetAllowedChild(symb, newArgSymbol, i);
     103        }
    98104      selectedDefunBranch.NumberOfArguments++;
     105
    99106      // increase the arity of the changed ADF in all branches that can use this ADF
    100107      foreach (var subtree in symbolicExpressionTree.Root.SubTrees) {
    101         if (subtree.DynamicSymbols.Contains(selectedDefunBranch.Name)) {
    102           subtree.SetDynamicSymbolArgumentCount(selectedDefunBranch.Name, selectedDefunBranch.NumberOfArguments);
     108        var matchingInvokeSymbol = (from symb in subtree.Grammar.Symbols.OfType<InvokeFunction>()
     109                                    where symb.FunctionName == selectedDefunBranch.FunctionName
     110                                    select symb).SingleOrDefault();
     111        if (matchingInvokeSymbol != null) {
     112          subtree.Grammar.SetMinSubtreeCount(matchingInvokeSymbol, selectedDefunBranch.NumberOfArguments);
     113          subtree.Grammar.SetMaxSubtreeCount(matchingInvokeSymbol, selectedDefunBranch.NumberOfArguments);
     114          foreach (var child in subtree.GetAllowedSymbols(0)) {
     115            for (int i = 0; i < subtree.Grammar.GetMaxSubtreeCount(matchingInvokeSymbol); i++) {
     116              subtree.Grammar.SetAllowedChild(matchingInvokeSymbol, child, i);
     117            }
     118          }
    103119        }
    104120      }
    105       Debug.Assert(grammar.IsValidExpression(symbolicExpressionTree));
    106121      return true;
    107122    }
  • trunk/sources/HeuristicLab.Encodings.SymbolicExpressionTreeEncoding/3.3/ArchitectureAlteringOperators/RandomArchitectureAlteringOperator.cs

    r3294 r3360  
    6565
    6666    public override void ModifyArchitecture(IRandom random, SymbolicExpressionTree tree, ISymbolicExpressionGrammar grammar, IntValue maxTreeSize, IntValue maxTreeHeight, IntValue maxFunctionDefiningBranches, IntValue maxFunctionArguments, out bool success) {
    67       var selectedOperator = Operators[random.Next(Operators.Count)];
     67      var selectedOperator = Operators.SelectRandom(random);
    6868      selectedOperator.ModifyArchitecture(random, tree, grammar, maxTreeSize, maxTreeHeight, maxFunctionDefiningBranches, maxFunctionArguments, out success);
    6969    }
  • trunk/sources/HeuristicLab.Encodings.SymbolicExpressionTreeEncoding/3.3/ArchitectureAlteringOperators/SubroutineCreater.cs

    r3338 r3360  
    4242  [StorableClass]
    4343  public sealed class SubroutineCreater : SymbolicExpressionTreeArchitectureAlteringOperator {
     44    private const double ARGUMENT_CUTOFF_PROBABILITY = 0.05;
     45
    4446    public override sealed void ModifyArchitecture(
    4547      IRandom random,
     
    6264        // allowed maximum number of ADF reached => abort
    6365        return false;
    64       string formatString = new StringBuilder().Append('0', (int)Math.Log10(maxFunctionDefiningBranches) + 1).ToString(); // >= 100 functions => ###
     66      if (symbolicExpressionTree.Size + 4 > maxTreeSize)
     67        // defining a new function causes an size increase by 4 nodes (max) if the max tree size is reached => abort
     68        return false;
     69      string formatString = new StringBuilder().Append('0', (int)Math.Log10(maxFunctionDefiningBranches * 10 - 1)).ToString(); // >= 100 functions => ###
    6570      var allowedFunctionNames = from index in Enumerable.Range(0, maxFunctionDefiningBranches)
    6671                                 select "ADF" + index.ToString(formatString);
    67       // find all body branches
    68       var bodies = from node in symbolicExpressionTree.IterateNodesPrefix()
    69                    where node.Symbol is Defun || node.Symbol is StartSymbol
     72
     73      // select a random body (either the result producing branch or an ADF branch)
     74      var bodies = from node in symbolicExpressionTree.Root.SubTrees
    7075                   select new { Tree = node, Size = node.GetSize() };
    7176      var totalNumberOfBodyNodes = bodies.Select(x => x.Size).Sum();
    72       // select a random body
    7377      int r = random.Next(totalNumberOfBodyNodes);
    7478      int aggregatedNumberOfBodyNodes = 0;
     
    8185      // sanity check
    8286      if (selectedBody == null) throw new InvalidOperationException();
    83       // select a random node in the selected branch
    84       var allCutPoints = (from parent in selectedBody.IterateNodesPrefix()
    85                           from subtree in parent.SubTrees
    86                           select new { Parent = parent, ReplacedBranchIndex = parent.SubTrees.IndexOf(subtree), ReplacedBranch = subtree }).ToList();
    87       if (allCutPoints.Count == 0)
     87
     88      // select a random cut point in the selected branch
     89      var allCutPoints = from parent in selectedBody.IterateNodesPrefix()
     90                         from subtree in parent.SubTrees
     91                         select new { Parent = parent, ReplacedBranchIndex = parent.SubTrees.IndexOf(subtree), ReplacedBranch = subtree };
     92      if (allCutPoints.Count() == 0)
    8893        // no cut points => abort
    8994        return false;
    90       var selectedCutPoint = allCutPoints[random.Next(allCutPoints.Count)];
     95      string newFunctionName = allowedFunctionNames.Except(functionDefiningBranches.Select(x => x.FunctionName)).First();
     96      var selectedCutPoint = allCutPoints.SelectRandom(random);
    9197      // select random branches as argument cut-off points (replaced by argument terminal nodes in the function)
    92       List<SymbolicExpressionTreeNode> argumentBranches = SelectRandomArgumentBranches(selectedCutPoint.ReplacedBranch, random, 0.25, maxFunctionArguments);
    93       string functionName = allowedFunctionNames.Except(functionDefiningBranches.Select(x => x.Name)).First();
     98      List<SymbolicExpressionTreeNode> argumentBranches = SelectRandomArgumentBranches(selectedCutPoint.ReplacedBranch, random, ARGUMENT_CUTOFF_PROBABILITY, maxFunctionArguments);
    9499      SymbolicExpressionTreeNode functionBody = selectedCutPoint.ReplacedBranch;
    95100      // disconnect the function body from the tree
    96101      selectedCutPoint.Parent.RemoveSubTree(selectedCutPoint.ReplacedBranchIndex);
    97102      // disconnect the argument branches from the function
    98       DisconnectBranches(functionBody, argumentBranches);
    99       // and insert a function invocation symbol instead
    100       var invokeNode = (InvokeFunctionTreeNode)(new InvokeFunction()).CreateTreeNode();
    101       invokeNode.InvokedFunctionName = functionName;
     103      functionBody = DisconnectBranches(functionBody, argumentBranches);
     104      // insert a function invocation symbol instead
     105      var invokeNode = (InvokeFunctionTreeNode)(new InvokeFunction(newFunctionName)).CreateTreeNode();
    102106      selectedCutPoint.Parent.InsertSubTree(selectedCutPoint.ReplacedBranchIndex, invokeNode);
     107      // add the branches selected as argument as subtrees of the function invocation node
    103108      foreach (var argumentBranch in argumentBranches)
    104109        invokeNode.AddSubTree(argumentBranch);
     
    106111      // insert a new function defining branch
    107112      var defunNode = (DefunTreeNode)(new Defun()).CreateTreeNode();
    108       defunNode.Name = functionName;
     113      defunNode.FunctionName = newFunctionName;
    109114      defunNode.AddSubTree(functionBody);
    110115      symbolicExpressionTree.Root.AddSubTree(defunNode);
    111       // copy known symbols from originating branch into new branch
    112       foreach (var knownSymbol in selectedBody.DynamicSymbols) {
    113         defunNode.AddDynamicSymbol(knownSymbol, selectedBody.GetDynamicSymbolArgumentCount(knownSymbol));
    114       }
    115       // add function arguments as known symbols to new branch
    116       for (int i = 0; i < argumentBranches.Count; i++) {
    117         defunNode.AddDynamicSymbol("ARG" + i);
    118       }
    119       // add new function name to original branch
    120       selectedBody.AddDynamicSymbol(functionName, argumentBranches.Count);
     116      // the grammar in the newly defined function is a clone of the grammar of the originating branch
     117      defunNode.Grammar = (ISymbolicExpressionGrammar)selectedBody.Grammar.Clone();
     118      // remove all argument symbols from grammar
     119      var oldArgumentSymbols = defunNode.Grammar.Symbols.OfType<Argument>().ToList();
     120      foreach (var oldArgSymb in oldArgumentSymbols)
     121        defunNode.Grammar.RemoveSymbol(oldArgSymb);
     122      // find unique argument indexes and matching symbols in the function defining branch
     123      var newArgumentIndexes = (from node in defunNode.IterateNodesPrefix().OfType<ArgumentTreeNode>()
     124                                select node.Symbol.ArgumentIndex).Distinct();
     125      // add argument symbols to grammar of function defining branch
     126      GrammarModifier.AddDynamicArguments(defunNode.Grammar, defunNode.Symbol, newArgumentIndexes);
     127      defunNode.NumberOfArguments = newArgumentIndexes.Count();
     128      if (defunNode.NumberOfArguments != argumentBranches.Count) throw new InvalidOperationException();
     129      // add invoke symbol for newly defined function to the original branch
     130      var allowedParents = from symb in selectedBody.Grammar.Symbols
     131                           where !(symb is ProgramRootSymbol)
     132                           select symb;
     133      var allowedChildren = from symb in selectedBody.Grammar.Symbols
     134                            where selectedBody.Grammar.IsAllowedChild(selectedBody.Symbol, symb, 0)
     135                            select symb;
     136      GrammarModifier.AddDynamicSymbol(selectedBody.Grammar, selectedBody.Symbol, defunNode.FunctionName, defunNode.NumberOfArguments);
     137
     138      // when the new function body was taken from another function definition
     139      // add invoke symbol for newly defined function to all branches that are allowed to invoke the original branch
     140      if (selectedBody.Symbol is Defun) {
     141        var originalFunctionDefinition = selectedBody as DefunTreeNode;
     142        foreach (var subtree in symbolicExpressionTree.Root.SubTrees) {
     143          var originalBranchInvokeSymbol = (from symb in subtree.Grammar.Symbols.OfType<InvokeFunction>()
     144                                            where symb.FunctionName == originalFunctionDefinition.FunctionName
     145                                            select symb).SingleOrDefault();
     146          // when the original branch can be invoked from the subtree then also allow invocation of the function
     147          if (originalBranchInvokeSymbol != null) {
     148            allowedParents = from symb in subtree.Grammar.Symbols
     149                             where !(symb is ProgramRootSymbol)
     150                             select symb;
     151            allowedChildren = from symb in subtree.Grammar.Symbols
     152                              where subtree.Grammar.IsAllowedChild(subtree.Symbol, symb, 0)
     153                              select symb;
     154            GrammarModifier.AddDynamicSymbol(subtree.Grammar, subtree.Symbol, defunNode.FunctionName, defunNode.NumberOfArguments);
     155          }
     156        }
     157      }
    121158      return true;
    122159    }
    123160
    124     private static void DisconnectBranches(SymbolicExpressionTreeNode node, List<SymbolicExpressionTreeNode> argumentBranches) {
     161    private static SymbolicExpressionTreeNode DisconnectBranches(SymbolicExpressionTreeNode node, List<SymbolicExpressionTreeNode> argumentBranches) {
     162      if (argumentBranches.Contains(node)) {
     163        var argumentIndex = argumentBranches.IndexOf(node);
     164        var argSymbol = new Argument(argumentIndex);
     165        return argSymbol.CreateTreeNode();
     166      }
    125167      // remove the subtrees so that we can clone only the root node
    126168      List<SymbolicExpressionTreeNode> subtrees = new List<SymbolicExpressionTreeNode>(node.SubTrees);
     
    128170      // recursively apply function for subtrees or append a argument terminal node
    129171      foreach (var subtree in subtrees) {
    130         if (argumentBranches.Contains(subtree)) {
    131           node.AddSubTree(MakeArgumentNode(argumentBranches.IndexOf(subtree)));
    132         } else {
    133           DisconnectBranches(subtree, argumentBranches);
    134           node.AddSubTree(subtree);
    135         }
    136       }
    137     }
    138 
    139     private static SymbolicExpressionTreeNode MakeArgumentNode(int argIndex) {
    140       var node = (ArgumentTreeNode)(new Argument()).CreateTreeNode();
    141       node.ArgumentIndex = argIndex;
     172        node.AddSubTree(DisconnectBranches(subtree, argumentBranches));
     173      }
    142174      return node;
    143175    }
     
    145177    private static List<SymbolicExpressionTreeNode> SelectRandomArgumentBranches(SymbolicExpressionTreeNode selectedRoot,
    146178      IRandom random,
    147       double argumentProbability,
     179      double cutProbability,
    148180      int maxArguments) {
     181      // breadth first determination of argument cut-off points
     182      // we must make sure that we cut off all original argument nodes and that the number of new argument is smaller than the limit
    149183      List<SymbolicExpressionTreeNode> argumentBranches = new List<SymbolicExpressionTreeNode>();
    150       foreach (var subTree in selectedRoot.SubTrees) {
    151         if (random.NextDouble() < argumentProbability) {
    152           if (argumentBranches.Count < maxArguments)
    153             argumentBranches.Add(subTree);
    154         } else {
    155           foreach (var argBranch in SelectRandomArgumentBranches(subTree, random, argumentProbability, maxArguments))
    156             if (argumentBranches.Count < maxArguments)
    157               argumentBranches.Add(argBranch);
     184      if (selectedRoot is ArgumentTreeNode) {
     185        argumentBranches.Add(selectedRoot);
     186        return argumentBranches;
     187      } else {
     188        // get the number of argument nodes (which must be cut-off) in the sub-trees
     189        var numberOfArgumentsInSubtrees = (from subtree in selectedRoot.SubTrees
     190                                           let nArgumentsInTree = subtree.IterateNodesPrefix().OfType<ArgumentTreeNode>().Count()
     191                                           select nArgumentsInTree).ToList();
     192        // determine the minimal number of new argument nodes for each sub-tree
     193        var minNewArgumentsForSubtrees = numberOfArgumentsInSubtrees.Select(x => x > 0 ? 1 : 0).ToList();
     194        if (minNewArgumentsForSubtrees.Sum() > maxArguments) {
     195          argumentBranches.Add(selectedRoot);
     196          return argumentBranches;
    158197        }
    159       }
    160       return argumentBranches;
    161     }
    162    
    163     private static IEnumerable<string> UsedFunctionNames(SymbolicExpressionTree symbolicExpressionTree) {
    164       return from node in symbolicExpressionTree.IterateNodesPrefix()
    165              where node.Symbol is Defun
    166              select ((DefunTreeNode)node).Name;
     198        // cut-off in the sub-trees in random order
     199        var randomIndexes = (from index in Enumerable.Range(0, selectedRoot.SubTrees.Count)
     200                             select new { Index = index, OrderValue = random.NextDouble() }).OrderBy(x => x.OrderValue).Select(x => x.Index);
     201        foreach (var subtreeIndex in randomIndexes) {
     202          var subtree = selectedRoot.SubTrees[subtreeIndex];
     203          minNewArgumentsForSubtrees[subtreeIndex] = 0;
     204          // => cut-off at 0..n points somewhere in the current sub-tree
     205          // determine the maximum number of new arguments that should be created in the branch
     206          // as the maximum for the whole branch minus already added arguments minus minimal number of arguments still left
     207          int maxArgumentsFromBranch = maxArguments - argumentBranches.Count - minNewArgumentsForSubtrees.Sum();
     208          // when no argument is allowed from the current branch then we have to include the whole branch into the function
     209          // otherwise: choose randomly wether to cut off immediately or wether to extend the function body into the branch
     210          if (maxArgumentsFromBranch == 0) {
     211            // don't cut at all => the whole sub-tree branch is included in the function body
     212            // (we already checked ahead of time that there are no arguments left over in the subtree)
     213          } else if (random.NextDouble() >= cutProbability) {
     214            argumentBranches.AddRange(SelectRandomArgumentBranches(subtree, random, cutProbability, maxArgumentsFromBranch));
     215          } else {
     216            // cut-off at current sub-tree
     217            argumentBranches.Add(subtree);
     218          }
     219        }
     220        return argumentBranches;
     221      }
    167222    }
    168223  }
  • trunk/sources/HeuristicLab.Encodings.SymbolicExpressionTreeEncoding/3.3/ArchitectureAlteringOperators/SubroutineDeleter.cs

    r3338 r3360  
    4141  [StorableClass]
    4242  public sealed class SubroutineDeleter : SymbolicExpressionTreeArchitectureAlteringOperator {
    43     private const int MAX_TRIES = 100;
    4443    public override sealed void ModifyArchitecture(
    4544      IRandom random,
     
    6867      symbolicExpressionTree.Root.RemoveSubTree(defunSubtreeIndex);
    6968
    70       // get all cut points that contain an invokation of the deleted defun
    71       var invocationCutPoints = from node in symbolicExpressionTree.IterateNodesPrefix()
    72                                 where node.SubTrees.Count > 0
    73                                 from argIndex in Enumerable.Range(0, node.SubTrees.Count)
    74                                 let subtree = node.SubTrees[argIndex] as InvokeFunctionTreeNode
    75                                 where subtree != null
    76                                 where subtree.InvokedFunctionName == selectedDefunBranch.Name
    77                                 select new { Parent = node, ReplacedChildIndex = argIndex, ReplacedChild = subtree };
    78       // deletion by random regeneration
    79       foreach (var cutPoint in invocationCutPoints) {
    80         SymbolicExpressionTreeNode replacementTree = null;
    81         int targetSize = random.Next(cutPoint.ReplacedChild.GetSize());
    82         int targetHeight = cutPoint.ReplacedChild.GetHeight();
    83         int tries = 0;
    84         do {
    85           try {
    86             replacementTree = ProbabilisticTreeCreator.PTC2(random, grammar, cutPoint.Parent.Symbol, targetSize, targetHeight);
    87           }
    88           catch (ArgumentException) {
    89             // try different size
    90             targetSize = random.Next(cutPoint.ReplacedChild.GetSize());
    91             if (tries++ > MAX_TRIES) throw;
    92           }
    93         } while (replacementTree == null);
    94         cutPoint.Parent.RemoveSubTree(cutPoint.ReplacedChildIndex);
    95         cutPoint.Parent.InsertSubTree(cutPoint.ReplacedChildIndex, replacementTree);
    96       }
    9769      // remove references to deleted function
    9870      foreach (var subtree in symbolicExpressionTree.Root.SubTrees) {
    99         if (subtree.DynamicSymbols.Contains(selectedDefunBranch.Name)) {
    100           subtree.RemoveDynamicSymbol(selectedDefunBranch.Name);
     71        var matchingInvokeSymbol = (from symb in subtree.Grammar.Symbols.OfType<InvokeFunction>()
     72                                    where symb.FunctionName == selectedDefunBranch.FunctionName
     73                                    select symb).SingleOrDefault();
     74        if (matchingInvokeSymbol != null) {
     75          subtree.Grammar.RemoveSymbol(matchingInvokeSymbol);
    10176        }
    10277      }
    103       Debug.Assert(grammar.IsValidExpression(symbolicExpressionTree));
     78
     79      DeletionByRandomRegeneration(random, symbolicExpressionTree, selectedDefunBranch);
    10480      return true;
     81    }
     82
     83    private static void DeletionByRandomRegeneration(IRandom random, SymbolicExpressionTree symbolicExpressionTree, DefunTreeNode selectedDefunBranch) {
     84      // find first invocation and replace it with a randomly generated tree
     85      // can't find all invocations in one step because once we replaced a top level invocation
     86      // the invocations below it are removed already
     87      var invocationCutPoint = (from node in symbolicExpressionTree.IterateNodesPrefix()
     88                                from subtree in node.SubTrees.OfType<InvokeFunctionTreeNode>()
     89                                where subtree.Symbol.FunctionName == selectedDefunBranch.FunctionName
     90                                select new { Parent = node, ReplacedChildIndex = node.SubTrees.IndexOf(subtree), ReplacedChild = subtree }).FirstOrDefault();
     91      while (invocationCutPoint != null) {
     92        // deletion by random regeneration
     93        SymbolicExpressionTreeNode replacementTree = null;
     94        // TODO: should weight symbols by tickets
     95        var selectedSymbol = invocationCutPoint.Parent.GetAllowedSymbols(invocationCutPoint.ReplacedChildIndex).SelectRandom(random);
     96
     97        int minPossibleSize = invocationCutPoint.Parent.Grammar.GetMinExpressionLength(selectedSymbol);
     98        int maxSize = Math.Max(minPossibleSize, invocationCutPoint.ReplacedChild.GetSize());
     99        int minPossibleHeight = invocationCutPoint.Parent.Grammar.GetMinExpressionDepth(selectedSymbol);
     100        int maxHeight = Math.Max(minPossibleHeight, invocationCutPoint.ReplacedChild.GetHeight());
     101
     102        replacementTree = ProbabilisticTreeCreator.PTC2(random, invocationCutPoint.Parent.Grammar, selectedSymbol, maxSize, maxHeight, 0, 0);
     103        invocationCutPoint.Parent.RemoveSubTree(invocationCutPoint.ReplacedChildIndex);
     104        invocationCutPoint.Parent.InsertSubTree(invocationCutPoint.ReplacedChildIndex, replacementTree);
     105
     106        invocationCutPoint = (from node in symbolicExpressionTree.IterateNodesPrefix()
     107                              from subtree in node.SubTrees.OfType<InvokeFunctionTreeNode>()
     108                              where subtree.Symbol.FunctionName == selectedDefunBranch.FunctionName
     109                              select new { Parent = node, ReplacedChildIndex = node.SubTrees.IndexOf(subtree), ReplacedChild = subtree }).FirstOrDefault();
     110      }
    105111    }
    106112  }
  • trunk/sources/HeuristicLab.Encodings.SymbolicExpressionTreeEncoding/3.3/ArchitectureAlteringOperators/SubroutineDuplicater.cs

    r3338 r3360  
    4848      IntValue maxFunctionDefiningBranches, IntValue maxFunctionArguments,
    4949      out bool success) {
    50       success = DuplicateRandomSubroutine(random, symbolicExpressionTree, grammar, maxTreeSize.Value, maxTreeHeight.Value, maxFunctionDefiningBranches.Value, maxFunctionArguments.Value);
     50      success = DuplicateSubroutine(random, symbolicExpressionTree, grammar, maxTreeSize.Value, maxTreeHeight.Value, maxFunctionDefiningBranches.Value, maxFunctionArguments.Value);
    5151    }
    5252
    53     public static bool DuplicateRandomSubroutine(
     53    public static bool DuplicateSubroutine(
    5454      IRandom random,
    5555      SymbolicExpressionTree symbolicExpressionTree,
     
    6666        return false;
    6767      var selectedBranch = functionDefiningBranches.SelectRandom(random);
    68       var clonedBranch = (DefunTreeNode)selectedBranch.Clone();
    69       clonedBranch.Name = allowedFunctionNames.Except(UsedFunctionNames(symbolicExpressionTree)).First();
    70       foreach (var node in symbolicExpressionTree.IterateNodesPrefix()) {
    71         var invokeFunctionNode = node as InvokeFunctionTreeNode;
    72         // find all invokations of the old function
    73         if (invokeFunctionNode != null && invokeFunctionNode.InvokedFunctionName == selectedBranch.Name) {
    74           // add the new function name to the list of known functions in the branches that used the originating function
    75           var branch = symbolicExpressionTree.GetTopLevelBranchOf(invokeFunctionNode);
    76           branch.AddDynamicSymbol(clonedBranch.Name, clonedBranch.NumberOfArguments);
    77           // flip coin wether to replace with newly defined function
    78           if (random.NextDouble() < 0.5) {
    79             invokeFunctionNode.InvokedFunctionName = clonedBranch.Name;
    80           }
     68      var duplicatedDefunBranch = (DefunTreeNode)selectedBranch.Clone();
     69      string newFunctionName = allowedFunctionNames.Except(UsedFunctionNames(symbolicExpressionTree)).First();
     70      duplicatedDefunBranch.FunctionName = newFunctionName;
     71      symbolicExpressionTree.Root.SubTrees.Add(duplicatedDefunBranch);
     72      duplicatedDefunBranch.Grammar = (ISymbolicExpressionGrammar)selectedBranch.Grammar.Clone();
     73      // add an invoke symbol for each branch that is allowed to invoke the original function
     74      foreach (var subtree in symbolicExpressionTree.Root.SubTrees) {
     75        var matchingInvokeSymbol = (from symb in subtree.Grammar.Symbols.OfType<InvokeFunction>()
     76                                    where symb.FunctionName == selectedBranch.FunctionName
     77                                    select symb).SingleOrDefault();
     78        if (matchingInvokeSymbol != null) {
     79          GrammarModifier.AddDynamicSymbol(subtree.Grammar, subtree.Symbol, duplicatedDefunBranch.FunctionName, duplicatedDefunBranch.NumberOfArguments);
    8180        }
    8281      }
    83       Debug.Assert(grammar.IsValidExpression(symbolicExpressionTree));
     82      // for all invoke nodes of the original function replace the invoke of the original function with an invoke of the new function randomly
     83      var originalFunctionInvocations = from node in symbolicExpressionTree.IterateNodesPrefix().OfType<InvokeFunctionTreeNode>()
     84                                        where node.Symbol.FunctionName == selectedBranch.FunctionName
     85                                        select node;
     86      foreach (var originalFunctionInvokeNode in originalFunctionInvocations) {
     87        var newInvokeSymbol = (from symb in originalFunctionInvokeNode.Grammar.Symbols.OfType<InvokeFunction>()
     88                               where symb.FunctionName == duplicatedDefunBranch.FunctionName
     89                               select symb).Single();
     90        // flip coin wether to replace with newly defined function
     91        if (random.NextDouble() < 0.5) {
     92          originalFunctionInvokeNode.Symbol = newInvokeSymbol;
     93        }
     94      }
    8495      return true;
    85     }
    86 
    87     private static bool ContainsNode(SymbolicExpressionTreeNode branch, SymbolicExpressionTreeNode node) {
    88       if (branch == node) return true;
    89       else foreach (var subtree in branch.SubTrees) {
    90           if (ContainsNode(subtree, node)) return true;
    91         }
    92       return false;
    9396    }
    9497
     
    9699      return from node in symbolicExpressionTree.IterateNodesPrefix()
    97100             where node.Symbol is Defun
    98              select ((DefunTreeNode)node).Name;
     101             select ((DefunTreeNode)node).FunctionName;
    99102    }
    100 
    101 
    102103  }
    103104}
Note: See TracChangeset for help on using the changeset viewer.