Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/sources/HeuristicLab.Encodings.SymbolicExpressionTreeEncoding/3.3/Creators/ProbabilisticTreeCreator.cs @ 3237

Last change on this file since 3237 was 3237, checked in by gkronber, 14 years ago

Worked on symbolic expression tree encoding.
Added view for expression trees (simple textual view in s-exp format).
Implemented SubtreeCrossover.
Fixed bugs in ProbabilisticTreeCreator.
#937 (Data types and operators for symbolic expression tree encoding)

File size: 11.1 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2008 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
4 *
5 * This file is part of HeuristicLab.
6 *
7 * HeuristicLab is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * HeuristicLab is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
19 */
20#endregion
21
22using HeuristicLab.Core;
23using HeuristicLab.Data;
24using HeuristicLab.Random;
25using System;
26using System.Linq;
27using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
28using System.Collections.Generic;
29
30namespace HeuristicLab.Encodings.SymbolicExpressionTreeEncoding {
31  [StorableClass]
32  [Item("ProbabilisticTreeCreator", "An operator that creates new symbolic expression trees with uniformly distributed size")]
33  public class ProbabilisticTreeCreator : SymbolicExpressionTreeCreator {
34    private const int MAX_TRIES = 100;
35    public ProbabilisticTreeCreator()
36      : base() {
37    }
38
39    protected override SymbolicExpressionTree Create(IRandom random, ISymbolicExpressionGrammar grammar, IntValue maxTreeSize, IntValue maxTreeHeight) {
40      return Apply(random, grammar, maxTreeSize.Value, maxTreeHeight.Value);
41    }
42
43    public SymbolicExpressionTree Apply(IRandom random, ISymbolicExpressionGrammar grammar, int maxTreeSize, int maxTreeHeight) {
44      // tree size is limited by the grammar and by the explicit size constraints
45      int allowedMinSize = grammar.MinimalExpressionLength(grammar.StartSymbol);
46      int allowedMaxSize = Math.Min(maxTreeSize, grammar.MaximalExpressionLength(grammar.StartSymbol));
47      // select a target tree size uniformly in the possible range (as determined by explicit limits and limits of the grammar)
48      int treeSize = random.Next(allowedMinSize, allowedMaxSize);
49      SymbolicExpressionTree tree = new SymbolicExpressionTree();
50      int tries = 0;
51      do {
52        try {
53          tree.Root = PTC2(random, grammar, grammar.StartSymbol, treeSize+1, maxTreeHeight+1);
54          //// determine possible root symbols to create a tree of the target size
55          //var possibleRootSymbols = from symbol in grammar.AllowedSymbols(grammar.StartSymbol, 0)
56          //                          where treeSize <= grammar.MaximalExpressionLength(symbol)
57          //                          where treeSize >= grammar.MinimalExpressionLength(symbol)
58          //                          select symbol;
59          //Symbol rootSymbol = SelectRandomSymbol(random, possibleRootSymbols);
60          //tree.Root = PTC2(random, grammar, rootSymbol, treeSize, maxTreeHeight);
61        }
62        catch (ArgumentException) {
63          // try a different size
64          treeSize = random.Next(allowedMinSize, allowedMaxSize);
65          tries = 0;
66        }
67        if (tries++ >= MAX_TRIES) {
68          // try a different size
69          treeSize = random.Next(allowedMinSize, allowedMaxSize);
70          tries = 0;
71        }
72      } while (tree.Root == null || tree.Size > maxTreeSize || tree.Height > maxTreeHeight);
73      return tree;
74    }
75
76    private Symbol SelectRandomSymbol(IRandom random, IEnumerable<Symbol> symbols) {
77      var symbolList = symbols.ToList();
78      return symbolList[random.Next(symbolList.Count)];
79    }
80
81
82    private SymbolicExpressionTreeNode PTC2(IRandom random, ISymbolicExpressionGrammar grammar, Symbol rootSymbol, int size, int maxDepth) {
83      SymbolicExpressionTreeNode root = rootSymbol.CreateTreeNode();
84      if (size <= 1 || maxDepth <= 1) return root;
85      List<object[]> list = new List<object[]>();
86      int currentSize = 1;
87      int totalListMinSize = grammar.MinimalExpressionLength(rootSymbol) - 1;
88
89      int actualArity = SampleArity(random, grammar, rootSymbol, size);
90      for (int i = 0; i < actualArity; i++) {
91        // insert a dummy sub-tree and add the pending extension to the list
92        root.AddSubTree(null);
93        list.Add(new object[] { root, i, 2 });
94      }
95
96      // while there are pending extension points and we have not reached the limit of adding new extension points
97      while (list.Count > 0 && totalListMinSize + currentSize < size) {
98        int randomIndex = random.Next(list.Count);
99        object[] nextExtension = list[randomIndex];
100        list.RemoveAt(randomIndex);
101        SymbolicExpressionTreeNode parent = (SymbolicExpressionTreeNode)nextExtension[0];
102        int argumentIndex = (int)nextExtension[1];
103        int extensionDepth = (int)nextExtension[2];
104        if (extensionDepth + grammar.MinimalExpressionDepth(parent.Symbol) >= maxDepth) {
105          parent.RemoveSubTree(argumentIndex);
106          SymbolicExpressionTreeNode branch = CreateMinimalTree(random, grammar, grammar.AllowedSymbols(parent.Symbol, argumentIndex));
107          parent.InsertSubTree(argumentIndex, branch); // insert a smallest possible tree
108          currentSize += branch.GetSize();
109          totalListMinSize -= branch.GetSize();
110        } else {
111          var allowedSubFunctions = from s in grammar.AllowedSymbols(parent.Symbol, argumentIndex)
112                                    where grammar.MinimalExpressionDepth(parent.Symbol) + extensionDepth - 1 < maxDepth
113                                    where grammar.MaximalExpressionLength(s) > size - totalListMinSize - currentSize ||
114                                          totalListMinSize + currentSize >= size * 0.9 // if the necessary size is almost reached then also allow
115                                    // terminals or terminal-branches
116                                    select s;
117          Symbol selectedSymbol = SelectRandomSymbol(random, allowedSubFunctions);
118          SymbolicExpressionTreeNode newTree = selectedSymbol.CreateTreeNode();
119          parent.RemoveSubTree(argumentIndex);
120          parent.InsertSubTree(argumentIndex, newTree);
121          currentSize++;
122          totalListMinSize--;
123
124          actualArity = SampleArity(random, grammar, selectedSymbol, size - currentSize);
125          for (int i = 0; i < actualArity; i++) {
126            // insert a dummy sub-tree and add the pending extension to the list
127            newTree.AddSubTree(null);
128            list.Add(new object[] { newTree, i, extensionDepth + 1 });
129          }
130          totalListMinSize += grammar.MinimalExpressionLength(selectedSymbol);
131        }
132      }
133      // fill all pending extension points
134      while (list.Count > 0) {
135        int randomIndex = random.Next(list.Count);
136        object[] nextExtension = list[randomIndex];
137        list.RemoveAt(randomIndex);
138        SymbolicExpressionTreeNode parent = (SymbolicExpressionTreeNode)nextExtension[0];
139        int a = (int)nextExtension[1];
140        int d = (int)nextExtension[2];
141        parent.RemoveSubTree(a);
142        parent.InsertSubTree(a,
143          CreateMinimalTree(random, grammar, grammar.AllowedSymbols(parent.Symbol, a))); // append a tree with minimal possible height
144      }
145      return root;
146    }
147
148    private int SampleArity(IRandom random, ISymbolicExpressionGrammar grammar, Symbol symbol, int targetSize) {
149      // select actualArity randomly with the constraint that the sub-trees in the minimal arity can become large enough
150      int minArity = grammar.MinSubTrees(symbol);
151      int maxArity = grammar.MaxSubTrees(symbol);
152      if (maxArity > targetSize) {
153        maxArity = targetSize;
154      }
155      // the min number of sub-trees has to be set to a value that is large enough so that the largest possible tree is at least tree size
156      // if 1..3 trees are possible and the largest possible first sub-tree is smaller larger than the target size then minArity should be at least 2
157      long aggregatedLongestExpressionLength = 0;
158      for (int i = 0; i < maxArity; i++) {
159        aggregatedLongestExpressionLength += (from s in grammar.AllowedSymbols(symbol, i)
160                                              select grammar.MaximalExpressionLength(s)).Max();
161        if (aggregatedLongestExpressionLength < targetSize) minArity = i;
162        else break;
163      }
164
165      // the max number of sub-trees has to be set to a value that is small enough so that the smallest possible tree is at most tree size
166      // if 1..3 trees are possible and the smallest possible first sub-tree is already larger than the target size then maxArity should be at most 0
167      long aggregatedShortestExpressionLength = 0;
168      for (int i = 0; i < maxArity; i++) {
169        aggregatedShortestExpressionLength += (from s in grammar.AllowedSymbols(symbol, i)
170                                               select grammar.MinimalExpressionLength(s)).Min();
171        if (aggregatedShortestExpressionLength > targetSize) {
172          maxArity = i;
173          break;
174        }
175      }
176      if (minArity > maxArity) throw new ArgumentException();
177      return random.Next(minArity, maxArity + 1);
178    }
179
180    private SymbolicExpressionTreeNode CreateMinimalTree(IRandom random, ISymbolicExpressionGrammar grammar, IEnumerable<Symbol> symbols) {
181      // determine possible symbols that will lead to the smallest possible tree
182      var possibleSymbols = (from s in symbols
183                             group s by grammar.MinimalExpressionLength(s) into g
184                             orderby g.Key
185                             select g).First();
186      var selectedSymbol = SelectRandomSymbol(random, possibleSymbols);
187      // build minimal tree by recursive application
188      var tree = selectedSymbol.CreateTreeNode();
189      for (int i = 0; i < grammar.MinSubTrees(selectedSymbol); i++)
190        tree.AddSubTree(CreateMinimalTree(random, grammar, grammar.AllowedSymbols(selectedSymbol, i)));
191      return tree;
192    }
193
194    //private bool IsRecursiveExpansionPossible(Symbol symbol) {
195    //  return FindCycle(function, new Stack<IFunction>());
196    //}
197
198    //private Dictionary<IFunction, bool> inCycle = new Dictionary<IFunction, bool>();
199    //private bool FindCycle(IFunction function, Stack<IFunction> functionChain) {
200    //  if (inCycle.ContainsKey(function)) {
201    //    return inCycle[function];
202    //  } else if (IsTerminal(function)) {
203    //    inCycle[function] = false;
204    //    return false;
205    //  } else if (functionChain.Contains(function)) {
206    //    inCycle[function] = true;
207    //    return true;
208    //  } else {
209    //    functionChain.Push(function);
210    //    bool result = false;
211    //    // all slot indexes
212    //    for (int i = 0; i < function.MaxSubTrees; i++) {
213    //      foreach (IFunction subFunction in GetAllowedSubFunctions(function, i)) {
214    //        result |= FindCycle(subFunction, functionChain);
215    //      }
216    //    }
217
218    //    functionChain.Pop();
219    //    inCycle[function] = result;
220    //    return result;
221    //  }
222    //}
223
224  }
225}
Note: See TracBrowser for help on using the repository browser.