Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/sources/HeuristicLab.Encodings.SymbolicExpressionTreeEncoding/3.3/DefaultSymbolicExpressionGrammar.cs @ 3294

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

Added first version of architecture altering operators for ADFs. #290 (Implement ADFs)

File size: 10.1 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2010 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 System;
23using System.Collections.Generic;
24using System.Linq;
25using System.Text;
26using HeuristicLab.Core;
27using System.Xml;
28using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
29using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.GeneralSymbols;
30
31namespace HeuristicLab.Encodings.SymbolicExpressionTreeEncoding {
32  [StorableClass]
33  [Item("DefaultSymbolicExpressionGrammar", "Represents a grammar that defines the syntax of symbolic expression trees.")]
34  public class DefaultSymbolicExpressionGrammar : Item, ISymbolicExpressionGrammar {
35    [Storable]
36    private int minFunctionDefinitions;
37    [Storable]
38    private int maxFunctionDefinitions;
39    [Storable]
40    private int minFunctionArguments;
41    [Storable]
42    private int maxFunctionArguments;
43
44    [Storable]
45    private Dictionary<string, int> minSubTreeCount;
46    [Storable]
47    private Dictionary<string, int> maxSubTreeCount;
48    [Storable]
49    private Dictionary<string, List<HashSet<string>>> allowedFunctions;
50    [Storable]
51    private HashSet<Symbol> allSymbols;
52
53    public DefaultSymbolicExpressionGrammar(int minFunctionDefinitions, int maxFunctionDefinitions, int minFunctionArguments, int maxFunctionArguments)
54      : base() {
55      this.minFunctionDefinitions = minFunctionDefinitions;
56      this.maxFunctionDefinitions = maxFunctionDefinitions;
57      this.minFunctionArguments = minFunctionArguments;
58      this.maxFunctionArguments = maxFunctionArguments;
59      minSubTreeCount = new Dictionary<string, int>();
60      maxSubTreeCount = new Dictionary<string, int>();
61      allowedFunctions = new Dictionary<string, List<HashSet<string>>>();
62      allSymbols = new HashSet<Symbol>();
63      cachedMinExpressionLength = new Dictionary<Symbol, int>();
64      cachedMaxExpressionLength = new Dictionary<Symbol, int>();
65      cachedMinExpressionDepth = new Dictionary<Symbol, int>();
66      Initialize();
67    }
68
69    private void Initialize() {
70      programRootSymbol = new ProgramRootSymbol();
71      var defunSymbol = new Defun();
72      startSymbol = new StartSymbol();
73      var invokeFunctionSymbol = new InvokeFunction();
74
75      SetMinSubTreeCount(programRootSymbol, minFunctionDefinitions + 1);
76      SetMaxSubTreeCount(programRootSymbol, maxFunctionDefinitions + 1);
77      SetMinSubTreeCount(startSymbol, 1);
78      SetMaxSubTreeCount(startSymbol, 1);
79      SetMinSubTreeCount(defunSymbol, 1);
80      SetMaxSubTreeCount(defunSymbol, 1);
81      SetMinSubTreeCount(invokeFunctionSymbol, minFunctionArguments);
82      SetMaxSubTreeCount(invokeFunctionSymbol, maxFunctionArguments);
83      AddAllowedSymbols(programRootSymbol, 0, startSymbol);
84      for (int argumentIndex = 1; argumentIndex < maxFunctionDefinitions + 1; argumentIndex++) {
85        AddAllowedSymbols(programRootSymbol, argumentIndex, defunSymbol);
86      }
87    }
88
89    public void AddAllowedSymbols(Symbol parent, int argumentIndex, Symbol allowedChild) {
90      allSymbols.Add(parent); allSymbols.Add(allowedChild);
91      if (!allowedFunctions.ContainsKey(parent.Name)) {
92        allowedFunctions[parent.Name] = new List<HashSet<string>>();
93      }
94      while (allowedFunctions[parent.Name].Count <= argumentIndex)
95        allowedFunctions[parent.Name].Add(new HashSet<string>());
96      allowedFunctions[parent.Name][argumentIndex].Add(allowedChild.Name);
97      ClearCaches();
98    }
99
100    public void SetMaxSubTreeCount(Symbol parent, int nSubTrees) {
101      maxSubTreeCount[parent.Name] = nSubTrees;
102      ClearCaches();
103    }
104
105    public void SetMinSubTreeCount(Symbol parent, int nSubTrees) {
106      minSubTreeCount[parent.Name] = nSubTrees;
107      ClearCaches();
108    }
109
110    private void ClearCaches() {
111      cachedMinExpressionLength.Clear();
112      cachedMaxExpressionLength.Clear();
113      cachedMinExpressionDepth.Clear();
114    }
115
116    private void symbol_ToStringChanged(object sender, EventArgs e) {
117      OnToStringChanged();
118    }
119
120    #region ISymbolicExpressionGrammar Members
121
122    private Symbol programRootSymbol;
123    public Symbol ProgramRootSymbol {
124      get { return programRootSymbol; }
125    }
126
127    private Symbol startSymbol;
128    public Symbol StartSymbol {
129      get { return startSymbol; }
130    }
131
132    public IEnumerable<Symbol> GetAllowedSymbols(Symbol parent, int argumentIndex) {
133      return from name in allowedFunctions[parent.Name][argumentIndex]
134             from sym in allSymbols
135             where name == sym.Name
136             select sym;
137    }
138
139
140    private Dictionary<Symbol, int> cachedMinExpressionLength;
141    public int GetMinExpressionLength(Symbol start) {
142      if (!cachedMinExpressionLength.ContainsKey(start)) {
143        cachedMinExpressionLength[start] = int.MaxValue; // prevent infinite recursion
144        cachedMinExpressionLength[start] = 1 + (from argIndex in Enumerable.Range(0, GetMinSubTreeCount(start))
145                                                let minForSlot = (from symbol in GetAllowedSymbols(start, argIndex)
146                                                                  select GetMinExpressionLength(symbol)).DefaultIfEmpty(0).Min()
147                                                select minForSlot).DefaultIfEmpty(0).Sum();
148      }
149      return cachedMinExpressionLength[start];
150    }
151
152    private Dictionary<Symbol, int> cachedMaxExpressionLength;
153    public int GetMaxExpressionLength(Symbol start) {
154      if (!cachedMaxExpressionLength.ContainsKey(start)) {
155        cachedMaxExpressionLength[start] = int.MaxValue; // prevent infinite recursion
156        long sumOfMaxTrees = 1 + (from argIndex in Enumerable.Range(0, GetMaxSubTreeCount(start))
157                                  let maxForSlot = (long)(from symbol in GetAllowedSymbols(start, argIndex)
158                                                          select GetMaxExpressionLength(symbol)).DefaultIfEmpty(0).Max()
159                                  select maxForSlot).DefaultIfEmpty(0).Sum();
160        long limit = int.MaxValue;
161        cachedMaxExpressionLength[start] = (int)Math.Min(sumOfMaxTrees, limit);
162      }
163      return cachedMaxExpressionLength[start];
164    }
165
166    private Dictionary<Symbol, int> cachedMinExpressionDepth;
167    public int GetMinExpressionDepth(Symbol start) {
168      if (!cachedMinExpressionDepth.ContainsKey(start)) {
169        cachedMinExpressionDepth[start] = int.MaxValue; // prevent infinite recursion
170        cachedMinExpressionDepth[start] = 1 + (from argIndex in Enumerable.Range(0, GetMinSubTreeCount(start))
171                                               let minForSlot = (from symbol in GetAllowedSymbols(start, argIndex)
172                                                                 select GetMinExpressionDepth(symbol)).DefaultIfEmpty(0).Min()
173                                               select minForSlot).DefaultIfEmpty(0).Max();
174      }
175      return cachedMinExpressionDepth[start];
176    }
177
178    public int GetMinSubTreeCount(Symbol start) {
179      return minSubTreeCount[start.Name];
180    }
181
182    public int GetMaxSubTreeCount(Symbol start) {
183      return maxSubTreeCount[start.Name];
184    }
185
186    public bool IsValidExpression(SymbolicExpressionTree expression) {
187      if (expression.Root.Symbol != ProgramRootSymbol) return false;
188      // check dynamic symbols
189      foreach (var branch in expression.Root.SubTrees) {
190        foreach (var dynamicNode in branch.DynamicSymbols) {
191          if (!dynamicNode.StartsWith("ARG")) {
192            if (FindDefinitionOfDynamicFunction(expression.Root, dynamicNode) == null) return false;
193          }
194        }
195      }
196      return IsValidExpression(expression.Root);
197    }
198
199    #endregion
200    private bool IsValidExpression(SymbolicExpressionTreeNode root) {
201      if (root.SubTrees.Count < GetMinSubTreeCount(root.Symbol)) return false;
202      if (root.SubTrees.Count > GetMaxSubTreeCount(root.Symbol)) return false;
203      if (root.Symbol is Defun || root.Symbol is StartSymbol) {
204        // check references to dynamic symbols
205        if (!CheckDynamicSymbolsInBranch(root, root.SubTrees[0])) return false;
206      }
207      for (int i = 0; i < root.SubTrees.Count; i++) {
208        if (!GetAllowedSymbols(root.Symbol, i).Contains(root.SubTrees[i].Symbol)) return false;
209        if (!IsValidExpression(root.SubTrees[i])) return false;
210      }
211      return true;
212    }
213
214    private SymbolicExpressionTreeNode FindDefinitionOfDynamicFunction(SymbolicExpressionTreeNode root, string dynamicNode) {
215      return (from node in root.SubTrees.OfType<DefunTreeNode>()
216              where node.Name == dynamicNode
217              select node).FirstOrDefault();
218    }
219
220    private bool CheckDynamicSymbolsInBranch(SymbolicExpressionTreeNode root, SymbolicExpressionTreeNode node) {
221      var argNode = node as ArgumentTreeNode;
222      var invokeNode = node as InvokeFunctionTreeNode;
223      if (argNode != null) {
224        if (!root.DynamicSymbols.Contains("ARG" + argNode.ArgumentIndex)) return false;
225      } else if (invokeNode != null) {
226        if (!root.DynamicSymbols.Contains(invokeNode.InvokedFunctionName)) return false;
227        if (root.GetDynamicSymbolArgumentCount(invokeNode.InvokedFunctionName) != invokeNode.SubTrees.Count()) return false;
228      }
229      foreach (var subtree in node.SubTrees) {
230        if (!CheckDynamicSymbolsInBranch(root, subtree)) return false;
231      }
232      return true;
233    }
234
235  }
236}
Note: See TracBrowser for help on using the repository browser.