Changeset 10086 for branches/HeuristicLab.Problems.GPDL/CodeGenerator
- Timestamp:
- 10/27/13 20:17:17 (11 years ago)
- Location:
- branches/HeuristicLab.Problems.GPDL/CodeGenerator
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/HeuristicLab.Problems.GPDL/CodeGenerator/BruteForceCodeGen.cs
r10080 r10086 81 81 nextAlternative = (nextAlternative + 1) % subTrees.Length; 82 82 } while (subTrees[nextAlternative] != null && subTrees[nextAlternative].Done); 83 84 // from the nodes which are not done take the first with minimum count85 //nextAlternative = (from i in Enumerable.Range(0, subTrees.Length)86 // where subTrees[i] == null || !subTrees[i].Done87 // orderby subTrees[i]==null?0:subTrees[i].Count ascending88 // select i).FirstOrDefault(); // possibly there are no children left that can be tried89 83 } else { 90 84 // for sequenceNodes update all sub-trees … … 177 171 178 172 private AttributedGrammar CreateGrammarFromAst(GPDefNode ast) { 173 174 var nonTerminals = ast.NonTerminals.Select(t => new Symbol(t.Ident, GetSymbolAttributes(t.FormalParameters))).ToArray(); 175 var terminals = ast.Terminals.Select(t => new Symbol(t.Ident, GetSymbolAttributes(t.FormalParameters))).ToArray(); 179 176 string startSymbolName = ast.Rules.First().NtSymbol; 180 var startSymbolNode = ast.NonTerminals.Single(nt => nt.Ident == startSymbolName); 177 181 178 // create startSymbol 182 var g = new AttributedGrammar(new Symbol(startSymbolName, ParseSymbolAttributes(startSymbolNode.FormalParameters))); 179 var startSymbol = nonTerminals.Single(s => s.Name == startSymbolName); 180 var g = new AttributedGrammar(startSymbol, nonTerminals, terminals); 181 182 // add all production rules 183 183 foreach (var rule in ast.Rules) { 184 // create nt-symbol 185 var ntSymbolName = rule.NtSymbol; 186 var ntSymbolNode = ast.NonTerminals.Single(nt => nt.Ident == ntSymbolName); 187 var attributes = ParseSymbolAttributes(ntSymbolNode.FormalParameters); 188 var ntSymbol = new Symbol(ntSymbolName, attributes); 189 foreach (var alt in GetAlternatives(rule.Alternatives)) { 184 var ntSymbol = nonTerminals.Single(s => s.Name == rule.NtSymbol); 185 foreach (var alt in GetAlternatives(rule.Alternatives, nonTerminals.Concat(terminals))) { 190 186 g.AddProductionRule(ntSymbol, alt); 191 187 } … … 196 192 } 197 193 198 private IEnumerable<IAttribute> ParseSymbolAttributes(string formalParameters) {194 private IEnumerable<IAttribute> GetSymbolAttributes(string formalParameters) { 199 195 return (from fieldDef in Util.ExtractParameters(formalParameters) 200 196 select new Attribute(fieldDef.Identifier, fieldDef.Type, AttributeType.Parse(fieldDef.RefOrOut))). … … 202 198 } 203 199 204 private IEnumerable<Sequence> GetAlternatives(AlternativesNode altNode ) {200 private IEnumerable<Sequence> GetAlternatives(AlternativesNode altNode, IEnumerable<ISymbol> allSymbols) { 205 201 foreach (var alt in altNode.Alternatives) { 206 yield return GetSequence(alt.Sequence );207 } 208 } 209 210 private Sequence GetSequence(IEnumerable<RuleExprNode> sequence ) {202 yield return GetSequence(alt.Sequence, allSymbols); 203 } 204 } 205 206 private Sequence GetSequence(IEnumerable<RuleExprNode> sequence, IEnumerable<ISymbol> allSymbols) { 211 207 Debug.Assert(sequence.All(s => s is CallSymbolNode || s is RuleActionNode)); 212 208 var l = new List<ISymbol>(); … … 215 211 var actionNode = node as RuleActionNode; 216 212 if (callSymbolNode != null) { 217 l.Add(new Symbol(callSymbolNode.Ident, ParseSymbolAttributes(callSymbolNode.ActualParameter))); 213 Debug.Assert(allSymbols.Any(s => s.Name == callSymbolNode.Ident)); 214 // create a new symbol with actual parameters 215 l.Add(new Symbol(callSymbolNode.Ident, GetSymbolAttributes(callSymbolNode.ActualParameter))); 218 216 } else if (actionNode != null) { 219 217 l.Add(new SemanticSymbol("SEM", actionNode.SrcCode)); … … 313 311 314 312 // make sure we first descent into terminal alternatives -> we just order by number of non-terminals in the alternative 315 var altsWithSemActions = g.GetAlternativesWithSemanticActions(s).OrderBy(alt => alt.Count(symb => g.IsNonTerminal(symb))).ToArray(); 313 var altsWithSemActions = g.GetAlternativesWithSemanticActions(s) 314 .OrderBy(alt => alt.Count(symb => g.IsNonTerminal(symb))).ToArray(); 316 315 317 316 if (altsWithSemActions.Length > 1) { -
branches/HeuristicLab.Problems.GPDL/CodeGenerator/RandomSearchCodeGen.cs
r10080 r10086 20 20 namespace ?PROBLEMNAME? { 21 21 public sealed class ?IDENT?Solver { 22 public sealed class SolverState { 23 private int currentSeed; 24 public Random random; 25 public int depth; 26 public int steps; 27 public int maxDepth; 28 public SolverState(int seed) { 29 this.currentSeed = seed; 30 } 31 32 public SolverState IncDepth() { 33 depth++; 34 if(depth>maxDepth) maxDepth = depth; 35 return this; 36 } 37 public SolverState Prepare() { 38 this.random = new Random(currentSeed); 39 depth = 0; 40 maxDepth = 0; 41 steps = 0; 42 return this; 43 } 44 } 22 45 23 46 public static void Main(string[] args) { … … 38 61 } 39 62 40 41 private Random seedRandom; 42 private int currentSeed; 63 private double TerminalProbForDepth(int depth) { 64 const double baseProb = 0.05; // 5% of all samples are only a terminal node 65 const double probIncPerLevel = 0.05; // for each level the probability to sample a terminal grows by 5% 66 return baseProb + depth * probIncPerLevel; 67 } 68 69 private SolverState _state; 43 70 private void Start() { 44 seedRandom = new Random();71 var seedRandom = new Random(); 45 72 var bestF = ?MAXIMIZATION? ? double.NegativeInfinity : double.PositiveInfinity; 46 73 int n = 0; … … 51 78 // must make sure that calling the start-symbol multiple times in the fitness function always leads to the same path through the grammar 52 79 // so we use a PRNG for generating seeds for a separate PRNG that is reset each time the start symbol is called 53 currentSeed = seedRandom.Next(); 80 81 _state = new SolverState(seedRandom.Next()); 82 54 83 var f = Calculate(); 55 84 56 85 n++; 57 if (IsBetter(f, bestF)) bestF = f; 58 if (n % 100 == 0) { 86 if (IsBetter(f, bestF)) { 87 bestF = f; 88 Console.WriteLine(""{0}\t{1}\t(depth={2})"", n, bestF, _state.maxDepth); 89 } 90 if (n % 1000 == 0) { 59 91 sw.Stop(); 60 Console.WriteLine(""{0}\t{1}\t{2}\t({3:0.00} sols/ms)"", n, bestF, f, 100 .0 / sw.ElapsedMilliseconds);92 Console.WriteLine(""{0}\t{1}\t{2}\t({3:0.00} sols/ms)"", n, bestF, f, 1000.0 / sw.ElapsedMilliseconds); 61 93 sw.Reset(); 62 94 sw.Start(); … … 112 144 } 113 145 146 #region create grammar instance from AST 114 147 private AttributedGrammar CreateGrammarFromAst(GPDefNode ast) { 148 149 var nonTerminals = ast.NonTerminals.Select(t => new Symbol(t.Ident, GetSymbolAttributes(t.FormalParameters))).ToArray(); 150 var terminals = ast.Terminals.Select(t => new Symbol(t.Ident, GetSymbolAttributes(t.FormalParameters))).ToArray(); 115 151 string startSymbolName = ast.Rules.First().NtSymbol; 116 var startSymbolNode = ast.NonTerminals.Single(nt => nt.Ident == startSymbolName); 152 117 153 // create startSymbol 118 var g = new AttributedGrammar(new Symbol(startSymbolName, ParseSymbolAttributes(startSymbolNode.FormalParameters))); 154 var startSymbol = nonTerminals.Single(s => s.Name == startSymbolName); 155 var g = new AttributedGrammar(startSymbol, nonTerminals, terminals); 156 157 // add all production rules 119 158 foreach (var rule in ast.Rules) { 120 // create nt-symbol 121 var ntSymbolName = rule.NtSymbol; 122 var ntSymbolNode = ast.NonTerminals.Single(nt => nt.Ident == ntSymbolName); 123 var attributes = ParseSymbolAttributes(ntSymbolNode.FormalParameters); 124 var ntSymbol = new Symbol(ntSymbolName, attributes); 125 foreach (var alt in GetAlternatives(rule.Alternatives)) { 159 var ntSymbol = nonTerminals.Single(s => s.Name == rule.NtSymbol); 160 foreach (var alt in GetAlternatives(rule.Alternatives, nonTerminals.Concat(terminals))) { 126 161 g.AddProductionRule(ntSymbol, alt); 127 162 } … … 132 167 } 133 168 134 private IEnumerable<IAttribute> ParseSymbolAttributes(string formalParameters) {169 private IEnumerable<IAttribute> GetSymbolAttributes(string formalParameters) { 135 170 return (from fieldDef in Util.ExtractParameters(formalParameters) 136 171 select new Attribute(fieldDef.Identifier, fieldDef.Type, AttributeType.Parse(fieldDef.RefOrOut))). … … 138 173 } 139 174 140 private IEnumerable<Sequence> GetAlternatives(AlternativesNode altNode ) {175 private IEnumerable<Sequence> GetAlternatives(AlternativesNode altNode, IEnumerable<ISymbol> allSymbols) { 141 176 foreach (var alt in altNode.Alternatives) { 142 yield return GetSequence(alt.Sequence );143 } 144 } 145 146 private Sequence GetSequence(IEnumerable<RuleExprNode> sequence ) {177 yield return GetSequence(alt.Sequence, allSymbols); 178 } 179 } 180 181 private Sequence GetSequence(IEnumerable<RuleExprNode> sequence, IEnumerable<ISymbol> allSymbols) { 147 182 Debug.Assert(sequence.All(s => s is CallSymbolNode || s is RuleActionNode)); 148 183 var l = new List<ISymbol>(); … … 151 186 var actionNode = node as RuleActionNode; 152 187 if (callSymbolNode != null) { 153 l.Add(new Symbol(callSymbolNode.Ident, ParseSymbolAttributes(callSymbolNode.ActualParameter))); 188 Debug.Assert(allSymbols.Any(s => s.Name == callSymbolNode.Ident)); 189 // create a new symbol with actual parameters 190 l.Add(new Symbol(callSymbolNode.Ident, GetSymbolAttributes(callSymbolNode.ActualParameter))); 154 191 } else if (actionNode != null) { 155 192 l.Add(new SemanticSymbol("SEM", actionNode.SrcCode)); … … 158 195 return new Sequence(l); 159 196 } 160 197 #endregion 198 199 #region helper methods for terminal symbols 161 200 // produces helper methods for the attributes of all terminal nodes 162 201 private string GenerateConstraintMethods(List<SymbolNode> symbols) { … … 177 216 sb.AppendFormat("public {0} GetMax{1}_{2}() {{ return {3}; }}", fieldType, t.Ident, c.Ident, c.RangeMaxExpression).AppendLine(); 178 217 sb.AppendFormat("public {0} GetMin{1}_{2}() {{ return {3}; }}", fieldType, t.Ident, c.Ident, c.RangeMinExpression).AppendLine(); 218 sb.AppendFormat("public {0} GetRandom{1}_{2}(SolverState _state) {{ return _state.random.NextDouble() * (GetMax{1}_{2}() - GetMin{1}_{2}()) + GetMin{1}_{2}(); }}", fieldType, t.Ident, c.Ident).AppendLine(); 179 219 } else if (c.Type == ConstraintNodeType.Set) { 180 sb.AppendFormat("public IEnumerable<{0}> GetAllowed{1}_{2}() {{ return {3} }}", fieldType, t.Ident, c.Ident, c.SetExpression).AppendLine(); 181 } 182 } 183 return sb.ToString(); 184 } 220 sb.AppendFormat("public IEnumerable<{0}> GetAllowed{1}_{2}() {{ return {3}; }}", fieldType, t.Ident, c.Ident, c.SetExpression).AppendLine(); 221 sb.AppendFormat("public {0} GetRandom{1}_{2}(SolverState _state) {{ var tmp = GetAllowed{1}_{2}().ToArray(); return tmp[_state.random.Next(tmp.Length)]; }}", fieldType, t.Ident, c.Ident).AppendLine(); 222 } 223 } 224 return sb.ToString(); 225 } 226 #endregion 185 227 186 228 private string GenerateInterpreterSource(AttributedGrammar grammar) { … … 197 239 } 198 240 199 private string GenerateTerminalInterpreterMethod(ISymbol s) {200 var sb = new StringBuilder();201 // if the terminal symbol has attributes then we must create values for these attributes202 if (!s.Attributes.Any())203 sb.AppendFormat("private void {0}(Random random) {{", s.Name);204 else205 sb.AppendFormat("private void {0}(Random random, {1}) {{", s.Name, s.GetAttributeString());206 207 // each field must match a formal parameter, assign a value for each parameter208 foreach (var element in s.Attributes) {209 // only works for "IN SET"-Constraints210 sb.AppendFormat("{{ var tmp = GetAllowed{1}_{0}().ToArray(); {0} = tmp[random.Next(tmp.Length)]; }} ", element.Name, s.Name);211 }212 sb.AppendLine("}");213 return sb.ToString();214 }215 216 241 private string GenerateInterpreterMethod(AttributedGrammar g, ISymbol s) { 217 242 var sb = new StringBuilder(); 243 218 244 // if this is the start symbol we additionally have to create the method which can be called from the fitness function 219 220 245 if (g.StartSymbol.Equals(s)) { 221 246 if (!s.Attributes.Any()) … … 234 259 actualParameter = string.Empty; 235 260 236 sb.AppendFormat("{0}( new Random(currentSeed), {1});", g.StartSymbol.Name, actualParameter).AppendLine();261 sb.AppendFormat("{0}(_state.Prepare(), {1});", g.StartSymbol.Name, actualParameter).AppendLine(); 237 262 sb.AppendLine("}"); 238 263 } 239 264 240 265 if (!s.Attributes.Any()) 241 sb.AppendFormat("private void {0}( Random random) {{", s.Name);266 sb.AppendFormat("private void {0}(SolverState _state) {{", s.Name); 242 267 else 243 sb.AppendFormat("private void {0}( Random random, {1}) {{", s.Name, s.GetAttributeString());268 sb.AppendFormat("private void {0}(SolverState _state, {1}) {{", s.Name, s.GetAttributeString()); 244 269 245 270 // generate local definitions … … 250 275 var terminalAlts = altsWithSemActions.Where(alt => alt.Count(g.IsNonTerminal) == 0); 251 276 var nonTerminalAlts = altsWithSemActions.Where(alt => alt.Count(g.IsNonTerminal) > 0); 252 bool hasTerminalAlts = terminalAlts. Count() > 0;253 bool hasNonTerminalAlts = nonTerminalAlts. Count() > 0;277 bool hasTerminalAlts = terminalAlts.Any(); 278 bool hasNonTerminalAlts = nonTerminalAlts.Any(); 254 279 255 280 if (altsWithSemActions.Length > 1) { … … 261 286 // the probability of choosing terminals should depend on the depth of the tree (small likelihood to choose terminals for small depths, large likelihood for large depths) 262 287 if (hasTerminalAlts && hasNonTerminalAlts) { 263 sb.AppendLine("if( random.NextDouble() < 0.5) {");288 sb.AppendLine("if(_state.random.NextDouble() < TerminalProbForDepth(_state.depth)) {"); 264 289 // terminals 265 290 sb.AppendLine("// terminals "); … … 287 312 288 313 private void GenerateSwitchStatement(StringBuilder sb, IEnumerable<Sequence> alts) { 289 sb.AppendFormat("switch( random.Next({0})) {{", alts.Count());314 sb.AppendFormat("switch(_state.random.Next({0})) {{", alts.Count()); 290 315 // generate a case for each alternative 291 316 int i = 0; … … 313 338 } else { 314 339 if (!s.Attributes.Any()) 315 return string.Format("{0}( random);", s.Name);340 return string.Format("{0}(_state.IncDepth()); _state.depth--;", s.Name); 316 341 else 317 return string.Format("{0}(random, {1});", s.Name, s.GetAttributeString()); 318 } 342 return string.Format("{0}(_state.IncDepth(), {1}); _state.depth--;", s.Name, s.GetAttributeString()); 343 } 344 } 345 346 private string GenerateTerminalInterpreterMethod(ISymbol s) { 347 var sb = new StringBuilder(); 348 // if the terminal symbol has attributes then we must samples values for these attributes 349 if (!s.Attributes.Any()) 350 sb.AppendFormat("private void {0}(SolverState _state) {{", s.Name); 351 else 352 sb.AppendFormat("private void {0}(SolverState _state, {1}) {{", s.Name, s.GetAttributeString()); 353 354 // each field must match a formal parameter, assign a value for each parameter 355 foreach (var element in s.Attributes) { 356 sb.AppendFormat("{{ {0} = GetRandom{1}_{0}(_state); }} ", element.Name, s.Name); 357 } 358 sb.AppendLine("}"); 359 return sb.ToString(); 319 360 } 320 361 }
Note: See TracChangeset
for help on using the changeset viewer.