Free cookie consent management tool by TermsFeed Policy Generator

Ignore:
Timestamp:
04/22/08 18:05:14 (17 years ago)
Author:
gkronber
Message:

merged FunctionsAndStructIdRefactoring-branch (r142, r143, r144, r145, r146, r147, r148, r149, r152, r153) back into the trunk (ticket #112)

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/sources/HeuristicLab.StructureIdentification/Recombination/SinglePointCrossOver.cs

    r23 r155  
    2929using HeuristicLab.Data;
    3030using HeuristicLab.Constraints;
     31using HeuristicLab.Functions;
    3132
    3233namespace HeuristicLab.StructureIdentification {
     
    4445      AddVariableInfo(new VariableInfo("MaxTreeHeight", "The maximal allowed height of the tree", typeof(IntData), VariableKind.In));
    4546      AddVariableInfo(new VariableInfo("MaxTreeSize", "The maximal allowed size (number of nodes) of the tree", typeof(IntData), VariableKind.In));
    46       AddVariableInfo(new VariableInfo("OperatorTree", "The tree to mutate", typeof(IOperator), VariableKind.In));
    47       AddVariableInfo(new VariableInfo("TreeSize", "The size (number of nodes) of the tree", typeof(IntData), VariableKind.In));
    48       AddVariableInfo(new VariableInfo("TreeHeight", "The height of the tree", typeof(IntData), VariableKind.In));
     47      AddVariableInfo(new VariableInfo("FunctionTree", "The tree to mutate", typeof(IFunctionTree), VariableKind.In | VariableKind.New));
     48      AddVariableInfo(new VariableInfo("TreeSize", "The size (number of nodes) of the tree", typeof(IntData), VariableKind.New));
     49      AddVariableInfo(new VariableInfo("TreeHeight", "The height of the tree", typeof(IntData), VariableKind.New));
    4950    }
    5051
     
    7778    }
    7879
    79 
    8080    private IOperation Cross(TreeGardener gardener, int maxTreeSize, int maxTreeHeight,
    8181      IScope scope, MersenneTwister random, IScope parent1, IScope parent2, IScope child) {
    82       List<IOperator> newOperators;
    83       IOperator newTree = Cross(gardener, parent1, parent2,
    84         random, maxTreeSize, maxTreeHeight, out newOperators);
    85 
    86       if(!gardener.IsValidTree(newTree)) {
    87         throw new InvalidProgramException();
    88       }
     82      List<IFunctionTree> newBranches;
     83      IFunctionTree newTree = Cross(gardener, parent1, parent2,
     84        random, maxTreeSize, maxTreeHeight, out newBranches);
     85
    8986
    9087      int newTreeSize = gardener.GetTreeSize(newTree);
    9188      int newTreeHeight = gardener.GetTreeHeight(newTree);
    92       child.AddVariable(new Variable("OperatorTree", newTree));
    93       child.AddVariable(new Variable("TreeSize", new IntData(newTreeSize)));
    94       child.AddVariable(new Variable("TreeHeight", new IntData(newTreeHeight)));
    95 
    96       // check if the size of the new tree is still in the allowed bounds
    97       if (newTreeHeight > maxTreeHeight ||
     89      child.AddVariable(new HeuristicLab.Core.Variable(scope.TranslateName("FunctionTree"), newTree));
     90      child.AddVariable(new HeuristicLab.Core.Variable(scope.TranslateName("TreeSize"), new IntData(newTreeSize)));
     91      child.AddVariable(new HeuristicLab.Core.Variable(scope.TranslateName("TreeHeight"), new IntData(newTreeHeight)));
     92
     93      // check if the new tree is valid and if the size of is still in the allowed bounds
     94      if(!gardener.IsValidTree(newTree) ||
     95        newTreeHeight > maxTreeHeight ||
    9896        newTreeSize > maxTreeSize) {
    9997        throw new InvalidProgramException();
    10098      }
    101 
    102 
    103       return gardener.CreateInitializationOperation(newOperators, child);
    104     }
    105 
    106 
    107     private IOperator Cross(TreeGardener gardener, IScope f, IScope g, MersenneTwister random, int maxTreeSize, int maxTreeHeight, out List<IOperator> newOperators) {
    108       IOperator tree0 = f.GetVariableValue<IOperator>("OperatorTree", false);
     99      return gardener.CreateInitializationOperation(newBranches, child);
     100    }
     101
     102
     103    private IFunctionTree Cross(TreeGardener gardener, IScope f, IScope g, MersenneTwister random, int maxTreeSize, int maxTreeHeight, out List<IFunctionTree> newBranches) {
     104      IFunctionTree tree0 = f.GetVariableValue<IFunctionTree>("FunctionTree", false);
    109105      int tree0Height = f.GetVariableValue<IntData>("TreeHeight", false).Data;
    110106      int tree0Size = f.GetVariableValue<IntData>("TreeSize", false).Data;
    111107
    112       IOperator tree1 = g.GetVariableValue<IOperator>("OperatorTree", false);
     108      IFunctionTree tree1 = g.GetVariableValue<IFunctionTree>("FunctionTree", false);
    113109      int tree1Height = g.GetVariableValue<IntData>("TreeHeight", false).Data;
    114110      int tree1Size = g.GetVariableValue<IntData>("TreeSize", false).Data;
    115111
    116112      if(tree0Size == 1 && tree1Size == 1) {
    117         return CombineTerminals(gardener, tree0, tree1, random, maxTreeHeight, out newOperators);
     113        return CombineTerminals(gardener, tree0, tree1, random, maxTreeHeight, out newBranches);
    118114      } else {
    119115        // we are going to insert tree1 into tree0 at a random place so we have to make sure that tree0 is not a terminal
    120116        // in case both trees are higher than 1 we swap the trees with probability 50%
    121117        if(tree0Height == 1 || (tree1Height > 1 && random.Next(2) == 0)) {
    122           IOperator tmp = tree0; tree0 = tree1; tree1 = tmp;
     118          IFunctionTree tmp = tree0; tree0 = tree1; tree1 = tmp;
    123119          int tmpHeight = tree0Height; tree0Height = tree1Height; tree1Height = tmpHeight;
    124120          int tmpSize = tree0Size; tree0Size = tree1Size; tree1Size = tmpSize;
     
    126122
    127123        // save the root because later on we change tree0 and tree1 while searching a valid tree configuration
    128         IOperator root = tree0;
     124        IFunctionTree root = tree0;
    129125        int rootSize = tree0Size;
    130126
     
    132128        int tree0Level = random.Next(tree0Height - 1); // since we checked before that the height of tree0 is > 1 this is OK
    133129        int tree1Level = random.Next(tree1Height);
    134         tree0 = gardener.GetRandomNode(tree0, tree0Level);
    135         tree1 = gardener.GetRandomNode(tree1, tree1Level);
     130        tree0 = gardener.GetRandomBranch(tree0, tree0Level);
     131        tree1 = gardener.GetRandomBranch(tree1, tree1Level);
    136132
    137133        // recalculate the size and height of tree1 (the one that we want to insert) because we need to check constraints later on
     
    140136
    141137        List<int> possibleChildIndices = new List<int>();
    142         TreeGardener.OperatorEqualityComparer comparer = new TreeGardener.OperatorEqualityComparer();
    143138
    144139        // Now tree0 is supposed to take tree1 as one if its children. If this is not possible,
    145140        // then go down in either of the two trees as far as possible. If even then it is not possible
    146141        // to merge the trees then throw an exception
    147         // find the list of allowed indices (regarding allowed sub-operators, maxTreeSize and maxTreeHeight)
    148         for(int i = 0; i < tree0.SubOperators.Count; i++) {
    149           int subOperatorSize = gardener.GetTreeSize(tree0.SubOperators[i]);
    150 
    151           // the index is ok when the operator is allowed as sub-operator and we don't violate the maxSize and maxHeight constraints
    152           if(GetAllowedOperators(tree0, i).Contains(tree1, comparer) &&
    153             rootSize - subOperatorSize + tree1Size < maxTreeSize &&
     142        // find the list of allowed indices (regarding allowed sub-trees, maxTreeSize and maxTreeHeight)
     143        for(int i = 0; i < tree0.SubTrees.Count; i++) {
     144          int subTreeSize = gardener.GetTreeSize(tree0.SubTrees[i]);
     145
     146          // the index is ok when the function is allowed as sub-tree and we don't violate the maxSize and maxHeight constraints
     147          if(gardener.GetAllowedSubFunctions(tree0.Function, i).Contains(tree1.Function) &&
     148            rootSize - subTreeSize + tree1Size < maxTreeSize &&
    154149            tree0Level + tree1Height < maxTreeHeight) {
    155150            possibleChildIndices.Add(i);
     
    158153
    159154        while(possibleChildIndices.Count == 0) {
    160           // ok we couln't find a possible configuration given the current tree0 and tree1
     155          // we couln't find a possible configuration given the current tree0 and tree1
    161156          // possible reasons for this are:
    162           //  - tree1 is not allowed as sub-operator of tree0
     157          //  - tree1 is not allowed as sub-tree of tree0
    163158          //  - appending tree1 as child of tree0 would create a tree that exceedes the maxTreeHeight
    164159          //  - replacing any child of tree0 with tree1 woulde create a tree that exceedes the maxTeeSize
     
    166161          //  - go up in tree0 => the insert position allows larger trees
    167162          //  - go down in tree1 => the tree that is inserted becomes smaller
    168           //  - however we have to get lucky to solve the 'allowed sub-operators' problem
     163          //  - however we have to get lucky to solve the 'allowed sub-trees' problem
    169164          if(tree1Height == 1 || (tree0Level>0 && random.Next(2) == 0)) {
    170165            // go up in tree0
    171166            tree0Level--;
    172             tree0 = gardener.GetRandomNode(root, tree0Level);
    173           } else if(tree1.SubOperators.Count > 0) {
     167            tree0 = gardener.GetRandomBranch(root, tree0Level);
     168          } else if(tree1.SubTrees.Count > 0) {
    174169            // go down in node2:
    175             tree1 = tree1.SubOperators[random.Next(tree1.SubOperators.Count)];
     170            tree1 = tree1.SubTrees[random.Next(tree1.SubTrees.Count)];
    176171            tree1Size = gardener.GetTreeSize(tree1);
    177172            tree1Height = gardener.GetTreeHeight(tree1);
     
    183178          // recalculate the list of possible indices
    184179          possibleChildIndices.Clear();
    185           for(int i = 0; i < tree0.SubOperators.Count; i++) {
    186             int subOperatorSize = gardener.GetTreeSize(tree0.SubOperators[i]);
    187 
    188             // when the operator is allowed as sub-operator and we don't violate the maxSize and maxHeight constraints
     180          for(int i = 0; i < tree0.SubTrees.Count; i++) {
     181            int subTreeSize = gardener.GetTreeSize(tree0.SubTrees[i]);
     182
     183            // when the function is allowed as sub-tree and we don't violate the maxSize and maxHeight constraints
    189184            // the index is ok
    190             if(GetAllowedOperators(tree0, i).Contains(tree1, comparer) &&
    191               rootSize - subOperatorSize + tree1Size < maxTreeSize &&
     185            if(gardener.GetAllowedSubFunctions(tree0.Function, i).Contains(tree1.Function) &&
     186              rootSize - subTreeSize + tree1Size < maxTreeSize &&
    192187              tree0Level + tree1Height < maxTreeHeight) {
    193188              possibleChildIndices.Add(i);
     
    203198        // replace the existing sub-tree at a random index in tree0 with tree1
    204199        int selectedIndex = possibleChildIndices[random.Next(possibleChildIndices.Count)];
    205         tree0.RemoveSubOperator(selectedIndex);
    206         tree0.AddSubOperator(tree1, selectedIndex);
     200        tree0.RemoveSubTree(selectedIndex);
     201        tree0.InsertSubTree(selectedIndex, tree1);
    207202
    208203        // no new operators where needed
    209         newOperators = new List<IOperator>();
     204        newBranches = new List<IFunctionTree>();
    210205        return root;
    211206      }
    212207    }
    213208
    214     private ICollection<IOperator> GetAllowedOperators(IOperator tree0, int i) {
    215       ItemList slotList = (ItemList)tree0.GetVariable(GPOperatorLibrary.ALLOWED_SUBOPERATORS).Value;
    216       return ((ItemList)slotList[i]).OfType<IOperator>().ToArray();
    217     }
    218 
    219     private IOperator CombineTerminals(TreeGardener gardener, IOperator f, IOperator g, MersenneTwister random, int maxTreeHeight, out List<IOperator> newOperators) {
    220       newOperators = new List<IOperator>();
    221       ICollection<IOperator> possibleParents = gardener.GetPossibleParents(new List<IOperator>() { f, g });
     209
     210    // take f and g and create a tree that has f and g as sub-trees
     211    // example
     212    //       O
     213    //      /|\
     214    //     g 2 f
     215    //
     216    private IFunctionTree CombineTerminals(TreeGardener gardener, IFunctionTree f, IFunctionTree g, MersenneTwister random, int maxTreeHeight, out List<IFunctionTree> newBranches) {
     217      newBranches = new List<IFunctionTree>();
     218      // determine the set of possible parent functions
     219      ICollection<IFunction> possibleParents = gardener.GetPossibleParents(new List<IFunction>() { f.Function, g.Function });
    222220      if(possibleParents.Count == 0) throw new InvalidProgramException();
    223 
    224       IOperator parent = (IOperator)possibleParents.ElementAt(random.Next(possibleParents.Count())).Clone();
     221      // and select a random one
     222      IFunctionTree parent = new FunctionTree(possibleParents.ElementAt(random.Next(possibleParents.Count())));
    225223
    226224      int minArity;
    227225      int maxArity;
    228       gardener.GetMinMaxArity(parent, out minArity, out maxArity);
    229 
     226      gardener.GetMinMaxArity(parent.Function, out minArity, out maxArity);
    230227      int nSlots = Math.Max(2, minArity);
    231 
    232       HashSet<IOperator>[] slotSets = new HashSet<IOperator>[nSlots];
    233 
    234       SubOperatorsConstraintAnalyser analyser = new SubOperatorsConstraintAnalyser();
    235       analyser.AllPossibleOperators = new List<IOperator>() { g, f };
     228      // determine which slot can take which sub-trees
     229      List<IFunctionTree>[] slots = new List<IFunctionTree>[nSlots];
    236230      for(int slot = 0; slot < nSlots; slot++) {
    237         HashSet<IOperator> slotSet = new HashSet<IOperator>(analyser.GetAllowedOperators(parent, slot));
    238         slotSets[slot] = slotSet;
    239       }
    240 
    241       int[] slotSequence = Enumerable.Range(0, slotSets.Count()).OrderBy(slot => slotSets[slot].Count()).ToArray();
    242 
    243       IOperator[] selectedOperators = new IOperator[nSlots];
     231        ICollection<IFunction> allowedSubFunctions = gardener.GetAllowedSubFunctions(parent.Function, slot);
     232        List<IFunctionTree> allowedTrees = new List<IFunctionTree>();
     233        if(allowedSubFunctions.Contains(f.Function)) allowedTrees.Add(f);
     234        if(allowedSubFunctions.Contains(g.Function)) allowedTrees.Add(g);
     235        slots[slot] = allowedTrees;
     236      }
     237      // fill the slots in the order of degrees of freedom
     238      int[] slotSequence = Enumerable.Range(0, slots.Count()).OrderBy(slot => slots[slot].Count()).ToArray();
     239
     240      // tmp arry to store the tree for each sub-tree slot of the parent
     241      IFunctionTree[] selectedFunctionTrees = new IFunctionTree[nSlots];
     242
     243      // fill the sub-tree slots of the parent starting with the slots that can take potentially both functions (f and g)
    244244      for(int i = 0; i < slotSequence.Length; i++) {
    245245        int slot = slotSequence[i];
    246         HashSet<IOperator> slotSet = slotSets[slot];
    247         if(slotSet.Count() == 0) {
    248           var allowedOperators = GetAllowedOperators(parent, slot);
    249           selectedOperators[slot] = gardener.CreateRandomTree(allowedOperators, 1, 1, true);
    250           newOperators.AddRange(gardener.GetAllOperators(selectedOperators[slot]));
     246        List<IFunctionTree> allowedTrees = slots[slot];
     247        // when neither f nor g fit into the slot => create a new random tree
     248        if(allowedTrees.Count() == 0) {
     249          var allowedFunctions = gardener.GetAllowedSubFunctions(parent.Function, slot);
     250          selectedFunctionTrees[slot] = gardener.CreateRandomTree(allowedFunctions, 1, 1, true);
     251          newBranches.AddRange(gardener.GetAllSubTrees(selectedFunctionTrees[slot]));
    251252        } else {
    252           IOperator selectedOperator = slotSet.ElementAt(random.Next(slotSet.Count()));
    253           selectedOperators[slot] = selectedOperator;
     253          // select randomly which tree to insert into this slot
     254          IFunctionTree selectedTree = allowedTrees[random.Next(allowedTrees.Count())];
     255          selectedFunctionTrees[slot] = selectedTree;
     256          // remove the tree that we used in this slot from following function-sets
    254257          for(int j = i + 1; j < slotSequence.Length; j++) {
    255258            int otherSlot = slotSequence[j];
    256             slotSets[otherSlot].Remove(selectedOperator);
    257           }
    258         }
    259       }
    260 
    261       for(int i = 0; i < selectedOperators.Length; i++) {
    262         parent.AddSubOperator(selectedOperators[i], i);
     259            slots[otherSlot].Remove(selectedTree);
     260          }
     261        }
     262      }
     263      // actually append the sub-trees to the parent tree
     264      for(int i = 0; i < selectedFunctionTrees.Length; i++) {
     265        parent.InsertSubTree(i, selectedFunctionTrees[i]);
    263266      }
    264267
Note: See TracChangeset for help on using the changeset viewer.