Free cookie consent management tool by TermsFeed Policy Generator

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

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

initial import of GPDL parser plugin

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