Free cookie consent management tool by TermsFeed Policy Generator

source: branches/HeuristicLab.Problems.GPDL/CodeGenerator/BruteForceCodeGen.cs @ 10394

Last change on this file since 10394 was 10394, checked in by gkronber, 10 years ago

#2026 fixed a bug in generation of terminal nodes

File size: 6.7 KB
Line 
1using System;
2using System.Collections.Generic;
3using System.Diagnostics;
4using System.Linq;
5using System.Text;
6using HeuristicLab.Grammars;
7
8namespace CodeGenerator {
9  public class BruteForceCodeGen {
10
11    private string solverTemplate = @"
12
13namespace ?PROBLEMNAME? {
14  public sealed class ?IDENT?Solver {
15
16    private readonly ?IDENT?Problem problem;
17    private readonly Random random;
18
19    private IEnumerable<Tree> GenerateTrees(int parentState, int depth) {
20      if(depth<=1) {
21        if(Grammar.subtreeCount[parentState] == 0)
22          foreach(var terminal in CreateTerminalNodes(parentState, problem))
23            yield return terminal;
24      } else if(Grammar.subtreeCount[parentState] == 1) {
25        for(int altIdx = 0; altIdx < Grammar.transition[parentState].Length; altIdx++) {
26          var targetState = Grammar.transition[parentState][altIdx];
27          foreach(var subtree in GenerateTrees(targetState, depth - 1)) {
28            var solution = new Tree(altIdx, new Tree[1] {subtree});
29            yield return solution;
30          }
31        }
32      } else if(Grammar.subtreeCount[parentState] > 1) {
33        var nums = Enumerable.Range(1, depth - 1);
34        var depthCombinations = CartesianProduct(Enumerable.Repeat(nums, Grammar.subtreeCount[parentState]))
35           .Where(comb => comb.Max() == depth - 1);
36        foreach(var depthCombination in depthCombinations) {
37          var trees = new IEnumerable<Tree>[Grammar.subtreeCount[parentState]];
38          var depthCombinationEnumerator = depthCombination.GetEnumerator();
39          depthCombinationEnumerator.MoveNext();
40          for(int subtreeIdx = 0; subtreeIdx < Grammar.subtreeCount[parentState]; subtreeIdx++) {
41            trees[subtreeIdx] = GenerateTrees(Grammar.transition[parentState][subtreeIdx], depthCombinationEnumerator.Current);
42            depthCombinationEnumerator.MoveNext();
43          }
44          foreach(var e in CartesianProduct(trees)) {
45            yield return new Tree(-1, e.ToArray()); // altIdx is ignored
46          }
47        }
48      }
49    }
50
51    public IEnumerable<IEnumerable<T>> CartesianProduct<T>(IEnumerable<IEnumerable<T>> sets) {
52      if(sets.Count() == 1) {
53        foreach(var e in sets.First()) {
54          yield return new T[] {e};
55        }
56      }
57      else {
58        var firstSet = sets.First();
59        foreach(var e in firstSet) {
60          foreach(var p in CartesianProduct(sets.Skip(1))) {
61            yield return new T[] {e}.Concat(p);
62          }
63        }
64      }
65    }
66
67    private static IEnumerable<Tree> CreateTerminalNodes(int state, ?IDENT?Problem problem) {
68      switch(state) {
69        ?CREATETERMINALNODECODE?
70        default: { throw new ArgumentException(""Unknown state index"" + state); }
71      }
72    }
73
74    public static void Main(string[] args) {
75      var problem = new ?IDENT?Problem();
76      var solver = new ?IDENT?Solver(problem);
77      solver.Start();
78    }
79
80    public ?IDENT?Solver(?IDENT?Problem problem) {
81      this.problem = problem;
82      this.random = new Random();
83    }
84
85    private void Start() {
86      const int MAX_SECONDS = 100000;
87      var bestF = ?MAXIMIZATION? ? double.NegativeInfinity : double.PositiveInfinity;
88      int n = 0;
89      long sumDepth = 0;
90      long sumSize = 0;
91      var sumF = 0.0;
92      var terminationTimer = new Stopwatch();
93      var sw = new System.Diagnostics.Stopwatch();
94      sw.Start();
95      terminationTimer.Start();
96      for(int depth = 1; terminationTimer.Elapsed.TotalSeconds < MAX_SECONDS; depth ++) {
97        Console.WriteLine(""Depth {0}:"", depth);
98        foreach(var t in GenerateTrees(0, depth)) {
99          var f = problem.Evaluate(t);
100          // t.PrintTree(0); Console.WriteLine();
101          var size = t.GetSize();
102          sumSize += size;
103          sumDepth += depth;
104          n++;   
105          sumF += f;
106          if (problem.IsBetter(f, bestF)) {
107            bestF = f;
108            t.PrintTree(0); Console.WriteLine();
109            Console.WriteLine(""{0}\t{1}\t(size={2}, depth={3})"", n, bestF, size, depth);
110          }
111          if (n % 1000 == 0) {
112            sw.Stop();
113            Console.WriteLine(""{6,5:0.0s}: {0}\tbest: {1:0.000}\t(avg: {2:0.000})\t(avg size: {3:0.0})\t(avg. depth: {4:0.0})\t({5:0.00} sols/ms)"",
114                              n, bestF, sumF/1000.0, sumSize/1000.0, sumDepth/1000.0, 1000.0 / sw.ElapsedMilliseconds, terminationTimer.Elapsed.TotalSeconds);
115            sumSize = 0;
116            sumDepth = 0;
117            sumF = 0.0;
118            sw.Restart();
119            if(terminationTimer.Elapsed.TotalSeconds >= MAX_SECONDS) break;
120          }
121        }
122        Console.WriteLine(""n={0}"",n);
123      }
124    }
125  }
126}";
127
128    public void Generate(IGrammar grammar, IEnumerable<TerminalNode> terminals, bool maximization, SourceBuilder problemSourceCode) {
129      var solverSourceCode = new SourceBuilder();
130      solverSourceCode.Append(solverTemplate)
131        .Replace("?MAXIMIZATION?", maximization.ToString().ToLowerInvariant())
132        .Replace("?CREATETERMINALNODECODE?", GenerateCreateTerminalCode(grammar, terminals))
133      ;
134
135      problemSourceCode.Append(solverSourceCode.ToString());
136    }
137
138    private string GenerateCreateTerminalCode(IGrammar grammar, IEnumerable<TerminalNode> terminals) {
139      Debug.Assert(grammar.Symbols.First().Equals(grammar.StartSymbol));
140      var sb = new SourceBuilder();
141      var allSymbols = grammar.Symbols.ToList();
142      foreach (var s in grammar.Symbols) {
143        if (grammar.IsTerminal(s)) {
144          sb.AppendFormat("case {0}: {{", allSymbols.IndexOf(s)).BeginBlock();
145          var terminal = terminals.Single(t => t.Ident == s.Name);
146          if (terminal.Constraints.Any(c => c.Type == ConstraintNodeType.Range)) {
147            throw new NotSupportedException("Sorry the brute force solver does not support RANGE constraints");
148          }
149          sb.AppendFormat("{0}Tree t = null;", terminal.Ident).AppendLine();
150          // create nested loop to produce all combinations of values (only set constraints)
151          foreach (var constr in terminal.Constraints) {
152            sb.AppendFormat("foreach(var {1} in problem.GetAllowed{0}_{1}()) {{;", terminal.Ident, constr.Ident).BeginBlock();
153          }
154          sb.AppendFormat("t = new {0}Tree();", terminal.Ident).AppendLine();
155
156          foreach (var constr in terminal.Constraints) {
157            sb.AppendFormat("t.{0} = {0};", constr.Ident);
158          }
159          sb.AppendLine("yield return t; ");
160
161          foreach (var _ in terminal.Constraints) {
162            sb.AppendLine("}").EndBlock();
163          }
164
165
166          sb.AppendLine(" break; }");
167        }
168      }
169      return sb.ToString();
170    }
171  }
172}
Note: See TracBrowser for help on using the repository browser.