Free cookie consent management tool by TermsFeed Policy Generator

source: branches/HeuristicLab.Problems.GPDL/HeuristicLab.Problems.GPDL/3.4/ProblemGenerator.cs @ 9528

Last change on this file since 9528 was 9528, checked in by gkronber, 11 years ago

#2026 worked on HL integration of GPDL compiler

File size: 29.0 KB
Line 
1using System;
2using System.CodeDom.Compiler;
3using System.Collections.Generic;
4using System.IO;
5using System.Linq;
6using System.Text;
7using HeuristicLab.Optimization;
8using Microsoft.CSharp;
9
10public class ProblemGenerator {
11  #region templates
12
13  private string usings = @"
14using HeuristicLab.Common;
15using HeuristicLab.Core;
16using HeuristicLab.Data;
17using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
18using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
19using HeuristicLab.Random;
20using HeuristicLab.PluginInfrastructure;
21using HeuristicLab.Optimization;
22using HeuristicLab.Optimization.Operators;
23using HeuristicLab.Operators;
24using HeuristicLab.Parameters;
25using System.Collections.Generic;
26using System.Linq;
27using System;
28using System.Threading;
29using HeuristicLab.Algorithms.OffspringSelectionGeneticAlgorithm;
30using HeuristicLab.SequentialEngine;
31using HeuristicLab.Selection;
32";
33
34  private string mainClassTemplate = @"
35namespace ?PROBLEMNAME? {
36  public sealed class ?IDENT?Main {
37    public ?IDENT?Main() {
38      Initialize();
39    }   
40    public void Initialize() {
41      var problem = new ?IDENT?Problem();
42      var wh = new AutoResetEvent(false);
43      var ga = new OffspringSelectionGeneticAlgorithm();
44      ga.Engine = new SequentialEngine();
45      ga.Problem = problem;
46      ga.PopulationSize.Value = 1000;
47      ga.MaximumGenerations.Value = 100;
48      ga.ComparisonFactorLowerBound.Value = 0;
49      ga.ComparisonFactorUpperBound.Value = 0;
50      ga.MutationProbability.Value = 0.15;
51      ga.Mutator = ga.MutatorParameter.ValidValues.OfType<MultiSymbolicExpressionTreeManipulator>().First();
52      var ts = ga.SelectorParameter.ValidValues.OfType<GenderSpecificSelector>().First();
53      ga.Selector = ts;
54      ga.Prepare();
55      ga.ExceptionOccurred += (sender, args) => {
56        Console.WriteLine(args.Value);
57        wh.Set();
58      };
59      ga.Stopped += (sender, args) => {
60         Console.WriteLine(""Finished"");
61         Console.WriteLine(""Evaluated solutions: "" + ((IntValue)(ga.Results[""EvaluatedSolutions""]).Value).Value);
62         Console.WriteLine(""Best quality: "" + ((DoubleValue)(ga.Results[""BestQuality""]).Value).Value);
63         wh.Set();
64      };
65      ga.Crossover = ga.CrossoverParameter.ValidValues.First();
66      ga.Start();   
67      while(!wh.WaitOne(500)) {
68         if(ga.Results.ContainsKey(""BestQuality"")) {
69           int evalSolutions = ((IntValue)(ga.Results[""EvaluatedSolutions""]).Value).Value;
70           double quality = ((DoubleValue)(ga.Results[""BestQuality""]).Value).Value;
71           Console.WriteLine(""{0}\t{1} "", evalSolutions, quality);
72         }
73      };
74    }
75  }
76}";
77
78  private string problemClassTemplate = @"
79namespace ?PROBLEMNAME? {
80  [StorableClass]
81  [Item(""?IDENT?Problem"", """")]
82  public sealed class ?IDENT?Problem : SingleObjectiveHeuristicOptimizationProblem<?IDENT?Evaluator, ISymbolicExpressionTreeCreator> {
83    public new ?IDENT?Evaluator Evaluator {
84      get { return (?IDENT?Evaluator)base.Evaluator; }
85      set { base.Evaluator = value; }
86    }
87    public IValueParameter<ISymbolicExpressionGrammar> GrammarParameter {
88      get { return (IValueParameter<ISymbolicExpressionGrammar>)Parameters[""SymbolicExpressionTreeGrammar""]; }
89    }
90
91    [Storable]
92    public ISymbolicExpressionGrammar Grammar { get { return GrammarParameter.Value; } }
93
94    [StorableConstructor]
95    private ?IDENT?Problem(bool deserializing) : base(deserializing) {
96       Initialize();
97    }
98    private ?IDENT?Problem(?IDENT?Problem original, Cloner cloner) : base(original, cloner) {
99      Initialize();
100    }
101    public ?IDENT?Problem() {
102      Parameters.Add(new ValueParameter<ISymbolicExpressionGrammar>(""SymbolicExpressionTreeGrammar"", new ?IDENT?Grammar(this)));
103      Parameters.Add(new FixedValueParameter<IntValue>(""MaximumSymbolicExpressionTreeDepth"", new IntValue(15)));
104      Parameters.Add(new FixedValueParameter<IntValue>(""MaximumSymbolicExpressionTreeLength"", new IntValue(100)));
105      Parameters.Add(new FixedValueParameter<IntValue>(""MaximumFunctionDefinitions"", new IntValue(0)));
106      Parameters.Add(new FixedValueParameter<IntValue>(""MaximumFunctionArguments"", new IntValue(0)));
107      Parameters[""MaximumFunctionDefinitions""].Hidden = true;
108      Parameters[""MaximumFunctionArguments""].Hidden = true;
109      Initialize();
110
111      Evaluator = new ?IDENT?Evaluator(this);
112      SolutionCreator = new ProbabilisticTreeCreator();
113
114 
115      Maximization.Value = Evaluator.Maximization;
116      MaximizationParameter.Hidden = true;
117   
118      InitializeOperators();
119    }   
120
121    private void Initialize() {
122      ?INITCODE?
123    }
124
125    private void InitializeOperators() {
126      Operators.AddRange(ApplicationManager.Manager.GetInstances<ISymbolicExpressionTreeOperator>());
127      Operators.Add(new SymbolicExpressionSymbolFrequencyAnalyzer());
128      Operators.Add(new MinAverageMaxSymbolicExpressionTreeLengthAnalyzer());
129      Operators.Add(new SymbolicExpressionTreeLengthAnalyzer());
130      Operators.Add(new BestSymbolicExpressionTreeAnalyzer());
131      ParameterizeOperators();
132    }
133    private void ParameterizeOperators() {
134      var operators = Parameters.OfType<IValueParameter>().Select(p => p.Value).OfType<IOperator>().Union(Operators).ToList();
135
136      foreach (var op in operators.OfType<ISymbolicExpressionTreeGrammarBasedOperator>()) {
137        op.SymbolicExpressionTreeGrammarParameter.ActualName = GrammarParameter.Name;
138      }
139      foreach (var op in operators.OfType<ISymbolicExpressionTreeSizeConstraintOperator>()) {
140        op.MaximumSymbolicExpressionTreeDepthParameter.ActualName = ""MaximumSymbolicExpressionTreeDepth"";
141        op.MaximumSymbolicExpressionTreeLengthParameter.ActualName = ""MaximumSymbolicExpressionTreeLength"";
142      }
143      foreach (var op in operators.OfType<ISymbolicExpressionTreeArchitectureAlteringOperator>()) {
144        op.MaximumFunctionArgumentsParameter.ActualName = ""MaximumFunctionArguments"";
145        op.MaximumFunctionDefinitionsParameter.ActualName = ""MaximumFunctionDefinitions"";
146      }
147      foreach (var op in operators.OfType<ISymbolicExpressionTreeCrossover>()) {
148        op.ParentsParameter.ActualName = SolutionCreator.SymbolicExpressionTreeParameter.ActualName;
149        op.ChildParameter.ActualName = SolutionCreator.SymbolicExpressionTreeParameter.ActualName;
150      }
151      foreach (var op in operators.OfType<ISymbolicExpressionTreeManipulator>()) {
152        op.SymbolicExpressionTreeParameter.ActualName = SolutionCreator.SymbolicExpressionTreeParameter.ActualName;
153      }
154      foreach (var op in operators.OfType<ISymbolicExpressionTreeAnalyzer>()) {
155        op.SymbolicExpressionTreeParameter.ActualName = SolutionCreator.SymbolicExpressionTreeParameter.ActualName;
156      }
157      foreach(var op in operators.OfType<BestSymbolicExpressionTreeAnalyzer>()) {
158        op.QualityParameter.ActualName = Evaluator.QualityParameter.Name;
159      }
160    }
161
162
163    public override IDeepCloneable Clone(Cloner cloner) {
164      return new ?IDENT?Problem(this, cloner);
165    }
166
167    public double Calculate(ISymbolicExpressionTree solution) {
168      InitSymbolStream(solution);
169      try {
170      ?FITNESSFUNCTION?
171      } catch(Exception e) {
172        var formatter = new SymbolicExpressionTreeStringFormatter();
173        Console.WriteLine(formatter.Format(solution));
174        throw;
175      }
176    }
177
178    ?ADDITIONALCODE?
179
180    private ISymbolicExpressionTreeNode rootNode;
181    private void InitSymbolStream(ISymbolicExpressionTree solution) {   
182      this.rootNode =  solution.Root.GetSubtree(0).GetSubtree(0);
183    }
184
185    ?INTERPRETERSOURCE?
186
187    ?CONSTRAINTSSOURCE?
188
189  }
190}";
191
192  private string symbolClassTemplate = @"
193namespace ?PROBLEMNAME? {
194  [StorableClass]
195  [Item(""?IDENT?"", """")]
196  public sealed class ?IDENT? : Symbol {
197    public override int MinimumArity {
198      get { return 0; }
199    }
200    public override int MaximumArity {
201      get { return byte.MaxValue; }
202    }
203
204    internal ?PROBLEMNAME?Problem problem;
205
206    [StorableConstructor]
207    private ?IDENT?(bool deserializing) : base(deserializing) { }
208    private ?IDENT?(?IDENT? original, Cloner cloner) : base(original, cloner) {
209      this.problem = original.problem;
210    }
211    public override IDeepCloneable Clone(Cloner cloner) {
212      return new ?IDENT?(this, cloner);
213    }
214    public ?IDENT?(?PROBLEMNAME?Problem problem) : base(""?IDENT?"", string.Empty) {
215      this.problem = problem;
216    }
217  }
218}";
219
220  private string terminalSymbolClassTemplate = @"
221namespace ?PROBLEMNAME? {
222  [StorableClass]
223  [Item(""?IDENT?"", """")]
224  public sealed class ?IDENT? : Symbol {
225    public override int MinimumArity {
226      get { return 0; }
227    }
228    public override int MaximumArity {
229      get { return 0; }
230    }
231
232    internal ?PROBLEMNAME?Problem problem;
233
234    [StorableConstructor]
235    private ?IDENT?(bool deserializing) : base(deserializing) { }
236    private ?IDENT?(?IDENT? original, Cloner cloner) : base(original, cloner) {
237      this.problem = original.problem;
238    }
239    public override IDeepCloneable Clone(Cloner cloner) {
240      return new ?IDENT?(this, cloner);
241    }
242    public ?IDENT?(?PROBLEMNAME?Problem problem) : base(""?IDENT?"", string.Empty) {
243      this.problem = problem;
244    }
245    public override ISymbolicExpressionTreeNode CreateTreeNode() {
246      return new ?IDENT?TreeNode(this);
247    }
248  }
249}";
250
251  private string treeNodeClassTemplate = @"
252namespace ?PROBLEMNAME? {
253  [StorableClass]
254  public sealed class ?IDENT?TreeNode : SymbolicExpressionTreeTerminalNode {
255    public new ?IDENT? Symbol {
256      get { return (?IDENT?)base.Symbol; }
257    }
258
259    ?FIELDS?
260
261    [StorableConstructor]
262    private ?IDENT?TreeNode(bool deserializing) : base(deserializing) { }
263    private ?IDENT?TreeNode(?IDENT?TreeNode original, Cloner cloner)
264      : base(original, cloner) {
265      ?CLONECODE?
266    }
267    public ?IDENT?TreeNode(?IDENT? symbol) : base(symbol) { }
268
269    public override bool HasLocalParameters {
270      get { return true; }
271    }
272
273    public override void ResetLocalParameters(IRandom random) {
274      base.ResetLocalParameters(random);
275      ?RESETFIELDSCODE?
276    }
277
278    public override void ShakeLocalParameters(IRandom random, double shakingFactor) {
279      base.ShakeLocalParameters(random, shakingFactor);
280      ?SHAKEFIELDSCODE?
281    }
282
283    public override IDeepCloneable Clone(Cloner cloner) {
284      return new ?IDENT?TreeNode(this, cloner);
285    }   
286  }
287}";
288
289  private string grammarClassTemplate = @"
290namespace ?PROBLEMNAME? {
291  [NonDiscoverableType]
292  [StorableClass]
293  [Item(""?IDENT?Grammar"", """")]
294  public class ?IDENT?Grammar : SymbolicExpressionGrammar {
295    [StorableConstructor]
296    protected ?IDENT?Grammar(bool deserializing) : base(deserializing) { }
297    protected ?IDENT?Grammar(?IDENT?Grammar original, Cloner cloner) : base(original, cloner) { }
298    public ?IDENT?Grammar(?IDENT?Problem problem)
299      : base(ItemAttribute.GetName(typeof(?IDENT?Grammar)), ItemAttribute.GetDescription(typeof(?IDENT?Grammar))) {
300      Initialize(problem);
301    }
302    public override IDeepCloneable Clone(Cloner cloner) {
303      return new ?IDENT?Grammar(this, cloner);
304    }
305
306    private void Initialize(?IDENT?Problem problem) {
307      ?CREATESYMBOLS?
308      var rootSymbol = ?ROOTSYMBOL?;
309
310      ?SETSUBTREECOUNTS?
311
312      // set start symbol
313      AddAllowedChildSymbol(StartSymbol, rootSymbol);
314
315      ?SETALLOWEDSUBTREECOUNTS?
316    }
317  }
318}
319";
320  private string evaluatorClassTemplate = @"
321namespace ?PROBLEMNAME? {
322  [StorableClass]
323  [Item(""?IDENT?Evaluator"", """")] 
324  public class ?IDENT?Evaluator : SingleSuccessorOperator, ISingleObjectiveEvaluator {
325    private const string SymbolicExpressionTreeParameterName = ""SymbolicExpressionTree"";
326    private const string QualityParameterName = ""Quality"";
327
328    public override bool CanChangeName { get { return false; } }
329
330    #region parameter properties
331    public ILookupParameter<ISymbolicExpressionTree> SymbolicExpressionTreeParameter {
332      get { return (ILookupParameter<ISymbolicExpressionTree>)Parameters[SymbolicExpressionTreeParameterName]; }
333    }
334    public ILookupParameter<DoubleValue> QualityParameter {
335      get { return (ILookupParameter<DoubleValue>)Parameters[QualityParameterName]; }
336    }
337    #endregion
338    public bool Maximization { get { return ?MAXIMIZATION?; }  }
339
340    public ?IDENT?Problem problem;
341
342    [StorableConstructor]
343    protected ?IDENT?Evaluator(bool deserializing) : base(deserializing) { }
344    protected ?IDENT?Evaluator(?IDENT?Evaluator original, Cloner cloner)
345      : base(original, cloner) {
346      this.problem = original.problem;
347    }
348    public ?IDENT?Evaluator(?IDENT?Problem problem)
349      : base() {
350      Parameters.Add(new LookupParameter<ISymbolicExpressionTree>(SymbolicExpressionTreeParameterName));
351      Parameters.Add(new LookupParameter<DoubleValue>(QualityParameterName));
352      this.problem = problem;
353    }
354    [StorableHook(HookType.AfterDeserialization)]
355    private void AfterDeserialization() {
356    }
357    public override IDeepCloneable Clone(Cloner cloner) {
358      return new ?IDENT?Evaluator(this, cloner);
359    }
360
361    public override IOperation Apply() {
362      var solution = SymbolicExpressionTreeParameter.ActualValue;
363      double quality = problem.Calculate(solution);
364      QualityParameter.ActualValue = new DoubleValue(quality);
365      return base.Apply();
366    }
367  }
368}
369";
370  #endregion
371
372  private StringBuilder problemSourceCode;
373
374  public ProblemGenerator() {
375    problemSourceCode = new StringBuilder();
376  }
377
378  public IProblem GenerateFromAst(GPDefNode definition) {
379    problemSourceCode.AppendLine(usings);
380
381    GenerateSymbols(definition.NonTerminals);
382    GenerateSymbols(definition.Terminals);
383
384    GenerateTreeNodes(definition.Terminals);
385    GenerateGrammar(definition);
386
387    GenerateEvaluator(definition);
388    GenerateProblem(definition);
389    GenerateMain(definition);
390
391    problemSourceCode.Replace("?PROBLEMNAME?", definition.Name);
392
393    using (var stream = new StreamWriter(definition.Name + ".cs")) {
394      stream.WriteLine(problemSourceCode.ToString());
395    }
396
397    using (var csc = new CSharpCodeProvider(new Dictionary<string, string>() { { "CompilerVersion", "v4.0" } })) {
398      var parameters = new CompilerParameters(new[] { "mscorlib.dll", "System.Core.dll", "System.dll", "System.Drawing.dll" }, Path.ChangeExtension(Path.GetRandomFileName(), ".dll"), true);
399      parameters.ReferencedAssemblies.Add(@"HeuristicLab.Common-3.3.dll");
400      parameters.ReferencedAssemblies.Add(@"HeuristicLab.Common.Resources-3.3.dll");
401      parameters.ReferencedAssemblies.Add(@"HeuristicLab.Core-3.3.dll");
402      parameters.ReferencedAssemblies.Add(@"HeuristicLab.Data-3.3.dll");
403      parameters.ReferencedAssemblies.Add(@"HeuristicLab.Encodings.SymbolicExpressionTreeEncoding-3.4.dll");
404      parameters.ReferencedAssemblies.Add(@"HeuristicLab.Random-3.3.dll");
405      parameters.ReferencedAssemblies.Add(@"HeuristicLab.Persistence-3.3.dll");
406      parameters.ReferencedAssemblies.Add(@"HeuristicLab.PluginInfrastructure-3.3.dll");
407      parameters.ReferencedAssemblies.Add(@"HeuristicLab.Optimization-3.3.dll");
408      parameters.ReferencedAssemblies.Add(@"HeuristicLab.Optimization.Operators-3.3.dll");
409      parameters.ReferencedAssemblies.Add(@"HeuristicLab.Operators-3.3.dll");
410      parameters.ReferencedAssemblies.Add(@"HeuristicLab.Collections-3.3.dll");
411      parameters.ReferencedAssemblies.Add(@"HeuristicLab.Parameters-3.3.dll");
412      parameters.ReferencedAssemblies.Add(@"HeuristicLab.Problems.DataAnalysis-3.4.dll");
413      parameters.ReferencedAssemblies.Add(@"ALGLIB-3.7.0.dll");
414      parameters.ReferencedAssemblies.Add(@"HeuristicLab.Problems.Instances-3.3.dll");
415      parameters.ReferencedAssemblies.Add(@"HeuristicLab.Problems.Instances.DataAnalysis-3.3.dll");
416      parameters.ReferencedAssemblies.Add(@"HeuristicLab.SequentialEngine-3.3.dll");
417      parameters.ReferencedAssemblies.Add(@"HeuristicLab.ParallelEngine-3.3.dll");
418      parameters.ReferencedAssemblies.Add(@"HeuristicLab.Algorithms.GeneticAlgorithm-3.3.dll");
419      parameters.ReferencedAssemblies.Add(@"HeuristicLab.Algorithms.OffspringSelectionGeneticAlgorithm-3.3.dll");
420      parameters.ReferencedAssemblies.Add(@"HeuristicLab.Selection-3.3.dll");
421
422      CompilerResults results = csc.CompileAssemblyFromSource(parameters, problemSourceCode.ToString());
423      results.Errors.Cast<CompilerError>().ToList().ForEach(error => Console.WriteLine(error.Line + " " + error.ErrorText));
424
425      var asm = results.CompiledAssembly;
426      AppDomain.CurrentDomain.Load(asm.GetName());
427      var problem = Activator.CreateInstance(asm.FullName, definition.Name + "." + definition.Name + "Problem").Unwrap();
428      return (HeuristicLab.Optimization.IProblem)problem;
429    }
430  }
431
432
433
434  private void GenerateEvaluator(GPDefNode definition) {
435    var evaluatorClassCode =
436      evaluatorClassTemplate
437        .Replace("?IDENT?", definition.Name)
438        .Replace("?MAXIMIZATION?", definition.FitnessFunctionNode.Maximization ? "true" : "false");
439    problemSourceCode.AppendLine(evaluatorClassCode).AppendLine();
440  }
441
442  private void GenerateMain(GPDefNode definition) {
443    var mainClassCode =
444      mainClassTemplate
445        .Replace("?IDENT?", definition.Name);
446
447    problemSourceCode.AppendLine(mainClassCode).AppendLine();
448  }
449
450
451  private void GenerateProblem(GPDefNode definition) {
452    var problemClassCode =
453      problemClassTemplate
454        .Replace("?IDENT?", definition.Name)
455        .Replace("?FITNESSFUNCTION?", definition.FitnessFunctionNode.SrcCode)
456        .Replace("?INTERPRETERSOURCE?", GenerateInterpreterSource(definition))
457        .Replace("?INITCODE?", definition.InitCodeNode.SrcCode)
458        .Replace("?ADDITIONALCODE?", definition.ClassCodeNode.SrcCode)
459        .Replace("?CONSTRAINTSSOURCE?", GenerateConstraintMethods(definition.Terminals));
460
461    problemSourceCode.AppendLine(problemClassCode).AppendLine();
462  }
463
464  private string GenerateConstraintMethods(List<SymbolNode> symbols) {
465    var sb = new StringBuilder();
466    var terminals = symbols.OfType<TerminalNode>();
467    foreach (var t in terminals) {
468      sb.AppendLine(GenerateConstraintMethods(t));
469    }
470    return sb.ToString();
471  }
472
473  private string GenerateConstraintMethods(TerminalNode t) {
474    var sb = new StringBuilder();
475    foreach (var c in t.Constraints) {
476      var fieldType = t.FieldDefinitions.First(d => d.Identifier == c.Ident).Type;
477      if (c.Type == ConstraintNodeType.Range) {
478        sb.AppendFormat("public {0} GetMax{1}_{2}() {{ return {3}; }}", fieldType, t.Ident, c.Ident, c.RangeMaxExpression).AppendLine();
479        sb.AppendFormat("public {0} GetMin{1}_{2}() {{ return {3}; }}", fieldType, t.Ident, c.Ident, c.RangeMinExpression).AppendLine();
480      } else if (c.Type == ConstraintNodeType.Set) {
481        sb.AppendFormat("public IEnumerable<{0}> GetAllowed{1}_{2}() {{ return {3}; }}", fieldType, t.Ident, c.Ident, c.SetExpression).AppendLine();
482      }
483    }
484    return sb.ToString();
485  }
486
487  private string GenerateInterpreterSource(GPDefNode definition) {
488    var sb = new StringBuilder();
489    var g = new Grammar(definition.NonTerminals, definition.Terminals, definition.Rules);
490    string formalParameter = definition.NonTerminals.Single(nt => nt.Ident == g.RootSymbol).FormalParameters;
491    var actualParameterEnumerable =
492      SourceReader.ExtractFormalParameters(formalParameter).Select(e => e.RefOrOut + " " + e.Identifier);
493    string actualParameter = string.Empty;
494    if (actualParameterEnumerable.Any()) {
495      foreach (var e in actualParameterEnumerable) {
496        actualParameter += ", " + e;
497      }
498    }
499    sb.AppendFormat("void {0}({1}) {{ {0}(rootNode {2}); }}", g.RootSymbol, formalParameter, actualParameter).AppendLine();
500
501    foreach (var s in definition.NonTerminals) {
502      sb.AppendLine(GenerateInterpreterMethod(g, s));
503    }
504    foreach (var s in definition.Terminals) {
505      sb.AppendLine(GenerateTerminalInterpreterMethod(g, (TerminalNode)s));
506    }
507    return sb.ToString();
508  }
509
510  private string GenerateTerminalInterpreterMethod(Grammar g, TerminalNode s) {
511    var sb = new StringBuilder();
512    if (!s.FormalParameters.Any())
513      sb.AppendFormat("private void {0}(ISymbolicExpressionTreeNode tree) {{", s.Ident);
514    else
515      sb.AppendFormat("private void {0}(ISymbolicExpressionTreeNode tree, {1}) {{", s.Ident, s.FormalParameters);
516    sb.AppendFormat("if (tree.Symbol == null || tree.Symbol.Name != \"{0}\") throw new InvalidOperationException();", s.Ident).AppendLine();
517    sb.AppendFormat("var cur = ({0}TreeNode)tree;", s.Ident).AppendLine();
518    foreach (var element in s.FieldDefinitions) {
519      sb.AppendFormat("{0} = cur.{0}", element.Identifier).AppendLine(";");
520    }
521    sb.AppendLine("}");
522    return sb.ToString();
523  }
524
525  private string GenerateInterpreterMethod(Grammar g, SymbolNode s) {
526    var sb = new StringBuilder();
527    if (!s.FormalParameters.Any())
528      sb.AppendFormat("private void {0}(ISymbolicExpressionTreeNode tree) {{", s.Ident);
529    else
530      sb.AppendFormat("private void {0}(ISymbolicExpressionTreeNode tree, {1}) {{", s.Ident, s.FormalParameters);
531    sb.AppendLine(g.GetLocalDefinitions(s.Ident));
532    sb.AppendFormat("ISymbolicExpressionTreeNode subtree = null;").AppendLine();
533    sb.AppendFormat("if (tree.Symbol== null || tree.Symbol.Name != \"{0}\") throw new InvalidOperationException();", s.Ident).AppendLine();
534    var alts = g.GetAlternatives(s.Ident);
535    var lookahead = alts.Select(seq => seq.First());
536    if (lookahead.Count() > 1) {
537      sb.AppendLine("System.Diagnostics.Debug.Assert(tree.SubtreeCount == 1);");
538      sb.AppendLine("subtree = tree.GetSubtree(0);");
539      int i = 0;
540      sb.AppendFormat("if(subtree.Symbol.Name == \"{0}\") {{ ", lookahead.First()).AppendLine();
541      foreach (var e in g.GetSequenceWithSemanticActions(s.Ident, i++)) {
542        sb.AppendLine(GenerateSourceForAction(e));
543      }
544      foreach (var l in lookahead.Skip(1)) {
545        sb.AppendFormat("}} else if(subtree.Symbol.Name == \"{0}\") {{ ", l).AppendLine();
546        foreach (var e in g.GetSequenceWithSemanticActions(s.Ident, i++)) {
547          sb.AppendLine(GenerateSourceForAction(e));
548        }
549      }
550      sb.AppendFormat("}} else throw new System.InvalidOperationException(\"In {0} found symbol \"+tree.Symbol.Name+\". Expected one of: {1}\");", s.Ident, lookahead.Aggregate("", (acc, l) => acc + l + " ")).AppendLine();
551    } else {
552      int eIdx = 0;
553      foreach (var e in g.GetSequenceWithSemanticActions(s.Ident, 0)) {
554        if (e is CallSymbolNode) {
555          sb.AppendFormat("subtree = tree.GetSubtree({0});", eIdx++);
556        }
557        sb.AppendLine(GenerateSourceForAction(e));
558      }
559    }
560    sb.AppendLine("}");
561    return sb.ToString();
562  }
563
564  private string GenerateSourceForAction(RuleExprNode e) {
565    var action = e as RuleActionNode;
566    var call = e as CallSymbolNode;
567    if (action != null) {
568      return action.SrcCode + ";";
569    } else if (call != null) {
570      if (!call.ActualParameter.Any())
571        return string.Format("{0}(subtree);", call.Ident);
572      else
573        return string.Format("{0}(subtree, {1});", call.Ident, call.ActualParameter);
574    } else {
575      throw new ArgumentException();
576    }
577  }
578
579  private void GenerateGrammar(GPDefNode definition) {
580    IEnumerable<SymbolNode> ntSymbols = definition.NonTerminals;
581    IEnumerable<SymbolNode> tSymbols = definition.Terminals;
582    List<RuleNode> ruleNodes = definition.Rules;
583    var g = new Grammar(ntSymbols, tSymbols, ruleNodes);
584    Console.WriteLine(g);
585
586    var grammarClassCode =
587      grammarClassTemplate
588        .Replace("?IDENT?", definition.Name)
589        .Replace("?CREATESYMBOLS?", GenerateGrammarSymbolDefinitionSource(g))
590        .Replace("?ROOTSYMBOL?", "_" + g.RootSymbol)
591        .Replace("?SETSUBTREECOUNTS?", GenerateGrammarSubtreeCountDefinitionSource(g))
592        .Replace("?SETALLOWEDSUBTREECOUNTS?", GenerateGrammarAllowedSubtreeDefinitionSource(g));
593
594
595    problemSourceCode.AppendLine(grammarClassCode).AppendLine();
596  }
597
598  private string GenerateGrammarSymbolDefinitionSource(Grammar g) {
599    StringBuilder sb = new StringBuilder();
600    foreach (var sy in g.Symbols) {
601      sb.AppendFormat("var _{0} = new {0}(problem); AddSymbol(_{0});", sy).AppendLine();
602    }
603    return sb.ToString();
604  }
605
606  private string GenerateGrammarSubtreeCountDefinitionSource(Grammar g) {
607    StringBuilder sb = new StringBuilder();
608    foreach (var sy in g.Symbols) {
609      var alt = g.GetAlternatives(sy);
610      if (alt.Count() > 0) {
611        var minSeqLength = alt.Min(seq => seq.Count);
612        var maxSeqLength = alt.Max(seq => seq.Count);
613        sb.AppendFormat("SetSubtreeCount(_{0}, {1}, {2});", sy, maxSeqLength, minSeqLength).AppendLine();
614      } else {
615        sb.AppendFormat("SetSubtreeCount(_{0}, {1}, {2});", sy, 0, 0).AppendLine();
616      }
617    }
618    return sb.ToString();
619  }
620
621  private string GenerateGrammarAllowedSubtreeDefinitionSource(Grammar g) {
622    StringBuilder sb = new StringBuilder();
623    foreach (var sy in g.Symbols) {
624      foreach (var seq in g.GetAlternatives(sy)) {
625        for (int argIdx = 0; argIdx < seq.Count; argIdx++) {
626          var childSy = seq[argIdx];
627          sb.AppendFormat("AddAllowedChildSymbol(_{0}, _{1}, {2});", sy, childSy, argIdx).AppendLine();
628        }
629      }
630    }
631    return sb.ToString();
632  }
633
634  private void GenerateTreeNodes(IEnumerable<SymbolNode> symbols) {
635    foreach (var s in symbols.OfType<TerminalNode>()) {
636      var classCode = treeNodeClassTemplate
637        .Replace("?IDENT?", s.Ident)
638        .Replace("?RESETFIELDSCODE?", GenerateNodeInitSourceCode(s))
639        .Replace("?SHAKEFIELDSCODE?", GenerateNodeUpdateSourceCode(s))
640        ;
641
642      StringBuilder fieldSource = new StringBuilder();
643      StringBuilder cloningSource = new StringBuilder();
644      foreach (var par in s.FieldDefinitions) {
645        fieldSource.AppendLine("[Storable]");
646        fieldSource.Append("internal ").Append(par.Type).Append(" ").Append(par.Identifier).AppendLine(";");
647
648        cloningSource.Append("this.").Append(par.Identifier)
649          .Append("=").Append("(").Append(par.Type).Append(")")
650          .Append("original.").Append(par.Identifier).AppendLine(";");
651
652      }
653
654      classCode = classCode.Replace("?FIELDS?", fieldSource.ToString());
655      classCode = classCode.Replace("?CLONECODE?", cloningSource.ToString());
656
657      problemSourceCode
658        .AppendLine(classCode)
659        .AppendLine();
660    }
661  }
662
663  private string GenerateNodeInitSourceCode(TerminalNode s) {
664    var sb = new StringBuilder();
665    sb.AppendLine("var problem = Symbol.problem;");
666    foreach (var f in s.FieldDefinitions) {
667      var cType = GetConstraintTypeFor(f.Identifier, s.Constraints);
668      if (cType == ConstraintNodeType.Range) {
669        sb.AppendFormat("var max_{1} = problem.GetMax{0}_{1}();", s.Ident, f.Identifier).AppendLine();
670        sb.AppendFormat("var min_{1} = problem.GetMin{0}_{1}();", s.Ident, f.Identifier).AppendLine();
671        sb.AppendFormat("{0} = min_{0} + random.NextDouble() * (max_{0} - min_{0});", f.Identifier).AppendLine();
672      } else if (cType == ConstraintNodeType.Set) {
673        sb.AppendFormat("var set_{1} = problem.GetAllowed{0}_{1}().ToList();", s.Ident, f.Identifier).AppendLine();
674        sb.AppendFormat("{0} = set_{0}[random.Next(set_{0}.Count())];", f.Identifier).AppendLine();
675      }
676    }
677    return sb.ToString();
678  }
679
680  private string GenerateNodeUpdateSourceCode(TerminalNode s) {
681    var sb = new StringBuilder();
682    sb.AppendLine("var problem = Symbol.problem;");
683    foreach (var f in s.FieldDefinitions) {
684      var cType = GetConstraintTypeFor(f.Identifier, s.Constraints);
685      if (cType == ConstraintNodeType.Range) {
686        sb.AppendFormat("var max_{1} = problem.GetMax{0}_{1}();", s.Ident, f.Identifier).AppendLine();
687        sb.AppendFormat("var min_{1} = problem.GetMin{0}_{1}();", s.Ident, f.Identifier).AppendLine();
688        sb.AppendFormat("{0} = min_{0} + random.NextDouble() * (max_{0} - min_{0});", f.Identifier).AppendLine();
689      } else if (cType == ConstraintNodeType.Set) {
690        sb.AppendFormat("var set_{1} = problem.GetAllowed{0}_{1}().ToList();", s.Ident, f.Identifier).AppendLine();
691        sb.AppendFormat("{0} = set_{0}[random.Next(set_{0}.Count())];", f.Identifier).AppendLine();
692      }
693    }
694    return sb.ToString();
695  }
696
697  private ConstraintNodeType GetConstraintTypeFor(string id, IEnumerable<ConstraintNode> contraints) {
698    return contraints.Single(c => c.Ident == id).Type;
699  }
700
701  private void GenerateSymbols(List<SymbolNode> symbols) {
702    foreach (var s in symbols.OfType<NonTerminalNode>()) {
703      problemSourceCode
704        .AppendLine(symbolClassTemplate.Replace("?IDENT?", s.Ident))
705        .AppendLine();
706    }
707    foreach (var s in symbols.OfType<TerminalNode>()) {
708      problemSourceCode
709        .AppendLine(terminalSymbolClassTemplate.Replace("?IDENT?", s.Ident))
710        .AppendLine();
711    }
712  }
713}
Note: See TracBrowser for help on using the repository browser.