Free cookie consent management tool by TermsFeed Policy Generator

Ignore:
Timestamp:
04/22/08 23:52:28 (17 years ago)
Author:
gkronber
Message:

simplified and improved ChangeNodeTypeManipulation (ticket #120)

Location:
trunk/sources/HeuristicLab.StructureIdentification
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/sources/HeuristicLab.StructureIdentification/Manipulation/ChangeNodeTypeManipulation.cs

    r163 r167  
    6666      IFunctionTree selectedChild;
    6767      int selectedChildIndex;
    68       if (parent == null) {
     68      if(parent == null) {
    6969        selectedChildIndex = 0;
    7070        selectedChild = root;
     
    7474      }
    7575
    76       if (selectedChild.SubTrees.Count == 0) {
     76      if(selectedChild.SubTrees.Count == 0) {
    7777        IFunctionTree newTerminal = ChangeTerminalType(parent, selectedChild, selectedChildIndex, gardener, random);
    78         if (parent == null) {
     78        if(parent == null) {
    7979          // no parent means the new child is the initial operator
    8080          // and we have to update the value in the variable
     
    9191      } else {
    9292        List<IFunctionTree> uninitializedBranches;
    93         IFunctionTree newFunction = ChangeFunctionType(parent, selectedChild, selectedChildIndex, gardener, random, out uninitializedBranches);
    94         if (parent == null) {
     93        IFunctionTree newFunctionTree = ChangeFunctionType(parent, selectedChild, selectedChildIndex, gardener, random, out uninitializedBranches);
     94        // in rare cases the function creates a tree that breaks the size limits
     95        // calculate the height and size difference and
     96        // check if the size of the new tree is still in the allowed bounds
     97        int oldChildSize = gardener.GetTreeSize(selectedChild);
     98        int oldChildHeight = gardener.GetTreeSize(selectedChild);
     99        int newChildSize = gardener.GetTreeSize(newFunctionTree);
     100        int newChildHeight = gardener.GetTreeHeight(newFunctionTree);
     101        if((treeHeight.Data - oldChildHeight) + newChildHeight > maxTreeHeight ||
     102          (treeSize.Data - oldChildSize) + newChildSize > maxTreeSize) {
     103          // if size-constraints are violated don't change anything
     104          return null;
     105        }
     106        if(parent == null) {
    95107          // no parent means the new function is the initial operator
    96108          // and we have to update the value in the variable
    97           scope.GetVariable(scope.TranslateName("FunctionTree")).Value = newFunction;
    98           root = newFunction;
     109          scope.GetVariable(scope.TranslateName("FunctionTree")).Value = newFunctionTree;
     110          root = newFunctionTree;
    99111        } else {
    100112          // remove the old child
    101113          parent.RemoveSubTree(selectedChildIndex);
    102114          // add the new child as sub-tree of parent
    103           parent.InsertSubTree(selectedChildIndex, newFunction);
     115          parent.InsertSubTree(selectedChildIndex, newFunctionTree);
    104116        }
    105         // recalculate size and height
    106         treeSize.Data = gardener.GetTreeSize(root);
    107         treeHeight.Data = gardener.GetTreeHeight(root);
     117        // update size and height
     118        treeSize.Data = (treeSize.Data - oldChildSize) + newChildSize;
     119        treeHeight.Data = gardener.GetTreeHeight(root); // must recalculate height because we can't know wether the manipulated branch was the deepest branch
    108120        // check if whole tree is ok
    109         // check if the size of the new tree is still in the allowed bounds
    110         if (!gardener.IsValidTree(root) ||
    111           treeHeight.Data > maxTreeHeight ||
    112           treeSize.Data > maxTreeSize) {
     121        if(!gardener.IsValidTree(root))
    113122          throw new InvalidProgramException();
    114         }
    115123        // return a composite operation that initializes all created sub-trees
    116124        return gardener.CreateInitializationOperation(uninitializedBranches, scope);
    117125      }
    118126    }
     127 
    119128
    120129    private IFunctionTree ChangeTerminalType(IFunctionTree parent, IFunctionTree child, int childIndex, TreeGardener gardener, MersenneTwister random) {
     
    146155      int minArity;
    147156      int maxArity;
    148       // only allow functions where we can keep all existing sub-trees
    149       // we don't want to create new sub-trees here
    150       // this restriction can be removed if we add code that creates sub-trees where necessary (gkronber 22.04.08)
    151       allowedFunctions = allowedFunctions.Where(f => {
    152         gardener.GetMinMaxArity(f, out minArity, out maxArity);
    153         return minArity <= actualArity;
    154       }).ToList();
    155157      // create a new tree-node for a randomly selected function
    156158      IFunctionTree newTree = new FunctionTree(allowedFunctions[random.Next(allowedFunctions.Count)]);
     
    159161      if (actualArity > maxArity)
    160162        actualArity = maxArity;
    161       // get the allowed size and height for new sub-trees
    162       // use the size of the smallest subtree as the maximal allowed size for new subtrees to
    163       // prevent that we ever create trees over the MaxTreeSize limit
    164       int maxSubTreeSize = child.SubTrees.Select(subTree => gardener.GetTreeSize(subTree)).Min();
    165       int maxSubTreeHeight = gardener.GetTreeHeight(child) - 1;
     163      if(actualArity < minArity)
     164        actualArity = minArity;
    166165      // create a list that holds old sub-trees that we can reuse in the new tree
    167166      List<IFunctionTree> availableSubTrees = new List<IFunctionTree>(child.SubTrees);
     
    181180          availableSubTrees.Remove(selectedSubTree); // the branch shouldn't be available for the following slots
    182181        } else {
    183           // no existing matching tree found => create a new one
    184           IFunctionTree freshTree = gardener.CreateRandomTree(allowedSubFunctions, maxSubTreeSize, maxSubTreeHeight);
     182          // no existing matching tree found => create a new tree of minimal size
     183          IFunctionTree freshTree = gardener.CreateRandomTree(allowedSubFunctions, 1, 1);
    185184          freshSubTrees.AddRange(gardener.GetAllSubTrees(freshTree));
    186185          newTree.InsertSubTree(i, freshTree);
  • trunk/sources/HeuristicLab.StructureIdentification/TreeGardener.cs

    r163 r167  
    5353      this.random = random;
    5454      this.funLibrary = funLibrary;
    55 
    5655      this.allFunctions = new List<IFunction>();
    5756      terminals = new List<IFunction>();
    5857      functions = new List<IFunction>();
    59 
    6058      // init functions and terminals based on constraints
    6159      foreach (IFunction fun in funLibrary.Group.Operators) {
     
    6866        }
    6967      }
    70 
    7168      allFunctions.AddRange(functions);
    7269      allFunctions.AddRange(terminals);
Note: See TracChangeset for help on using the changeset viewer.