Free cookie consent management tool by TermsFeed Policy Generator

source: branches/HeuristicLab.Problems.GrammaticalOptimization/HeuristicLab.Problems.GrammaticalOptimization/Problems/SantaFeAntProblem.cs @ 11803

Last change on this file since 11803 was 11803, checked in by gkronber, 9 years ago

#2283 moved problems into a separate folder

File size: 7.5 KB
Line 
1using System;
2using System.Collections.Generic;
3using System.Linq;
4using System.Runtime.InteropServices;
5using System.Runtime.Remoting.Messaging;
6using System.Text;
7using System.Text.RegularExpressions;
8
9namespace HeuristicLab.Problems.GrammaticalOptimization {
10  public class SantaFeAntProblem : IProblem {
11    private const string grammarString = @"
12G(A):
13A -> l | r | m | ?(A)(A) | lA | rA | mA
14";
15
16
17    // original koza grammar
18    // Ant -> left | right | move | if-food-ahead Ant Ant | Ant Ant | Ant Ant Ant
19    //
20    // here we use a modified grammar which has only one syntax tree for each sentence
21
22
23    private readonly IGrammar grammar;
24
25    public SantaFeAntProblem() {
26      this.grammar = new Grammar(grammarString);
27    }
28
29    public double BestKnownQuality(int maxLen) {
30      // for now only an upper bound is returned, ideally all food pellets are discovered
31      return 89;
32    }
33
34    public IGrammar Grammar {
35      get { return grammar; }
36    }
37
38    public double Evaluate(string sentence) {
39      var ant = new Ant();
40      int p = 0;
41      Run(ant, sentence, ref p);
42      return ant.FoodEaten;
43    }
44
45    private void Run(Ant ant, string sentence, ref int p) {
46      while (!ant.Done()) {
47        if (p >= sentence.Length) p = 0; // restart
48        switch (sentence[p]) {
49          case 'r': {
50              ant.TurnRight();
51              p++;
52              break;
53            }
54          case 'l': {
55              ant.TurnLeft();
56              p++;
57              break;
58            }
59          case 'm': {
60              ant.Move();
61              p++;
62              break;
63            }
64          case '?': {
65              p++; // skip p
66              if (ant.IsFoodAhead()) {
67                if (sentence[p] != '(') throw new ArgumentException();
68                p++;
69                Run(ant, sentence, ref p);      // it cannot happen that we run over the the end of the sentence here
70                if (ant.Done()) return;
71                if (sentence[p] != '(') throw new ArgumentException();
72                p++;
73                Skip(sentence, ref p);
74              } else {
75                if (sentence[p] != '(') throw new ArgumentException();
76                p++;
77                Skip(sentence, ref p);
78                if (sentence[p] != '(') throw new ArgumentException();
79                p++;
80                Run(ant, sentence, ref p);    // it cannot happen that we run over the the end of the sentence here
81              }
82              break;
83            }
84          case ')': {
85              p++; // skip
86              return;     // caller must continue processing
87            }
88          default: {
89              throw new ArgumentException();
90            }
91        }
92      }
93    }
94
95    private void Skip(string sentence, ref int p) {
96      int openCount = 1;
97      while (openCount > 0) {
98        if (sentence[p] == '(') openCount++;
99        else if (sentence[p] == ')') openCount--;
100        p++;
101      }
102    }
103
104    public string CanonicalRepresentation(string terminalPhrase) {
105      var sb = new StringBuilder(terminalPhrase);
106      string canonicalPhrase = terminalPhrase;
107      string oldPhrase;
108      do {
109        oldPhrase = canonicalPhrase;
110        sb.Replace("ll", "rr").Replace("rl", "lr").Replace("lr", "").Replace("lll", "r").Replace("rrr", "l");
111        canonicalPhrase = sb.ToString();
112      } while (canonicalPhrase != oldPhrase);
113      sb.Append(terminalPhrase.Length - canonicalPhrase.Length);
114      return sb.ToString();
115    }
116  }
117
118  public class Ant {
119    private const int maxSteps = 600;
120    public enum HeadingEnum { North, East, South, West };
121    public int FoodEaten { get; private set; }
122    private readonly char[][] world = new char[32][];
123    private int posX;
124    private int posY;
125    private int steps;
126    private HeadingEnum heading;
127
128
129
130    public Ant() {
131      world[00] = " ###                            ".ToCharArray();
132      world[01] = "   #                            ".ToCharArray();
133      world[02] = "   #                    .###..  ".ToCharArray();
134      world[03] = "   #                    #    #  ".ToCharArray();
135      world[04] = "   #                    #    #  ".ToCharArray();
136      world[05] = "   ####.#####       .##..    .  ".ToCharArray();
137      world[06] = "            #       .        #  ".ToCharArray();
138      world[07] = "            #       #        .  ".ToCharArray();
139      world[08] = "            #       #        .  ".ToCharArray();
140      world[09] = "            #       #        #  ".ToCharArray();
141      world[10] = "            .       #        .  ".ToCharArray();
142      world[11] = "            #       .        .  ".ToCharArray();
143      world[12] = "            #       .        #  ".ToCharArray();
144      world[13] = "            #       #        .  ".ToCharArray();
145      world[14] = "            #       #  ...###.  ".ToCharArray();
146      world[15] = "            .   .#...  #        ".ToCharArray();
147      world[16] = "            .   .      .        ".ToCharArray();
148      world[17] = "            #   .      .        ".ToCharArray();
149      world[18] = "            #   #      .#...    ".ToCharArray();
150      world[19] = "            #   #          #    ".ToCharArray();
151      world[20] = "            #   #          .    ".ToCharArray();
152      world[21] = "            #   #          .    ".ToCharArray();
153      world[22] = "            #   .      ...#.    ".ToCharArray();
154      world[23] = "            #   .      #        ".ToCharArray();
155      world[24] = " ..##..#####.   #               ".ToCharArray();
156      world[25] = " #              #               ".ToCharArray();
157      world[26] = " #              #               ".ToCharArray();
158      world[27] = " #     .#######..               ".ToCharArray();
159      world[28] = " #     #                        ".ToCharArray();
160      world[29] = " .     #                        ".ToCharArray();
161      world[30] = " .####..                        ".ToCharArray();
162      world[31] = "                                ".ToCharArray();
163
164      posX = 0;
165      posY = 0;
166      heading = HeadingEnum.East;
167      FoodEaten = 0;
168      steps = 0;
169    }
170
171    public bool Done() {
172      return steps > maxSteps;
173    }
174
175    public void TurnRight() {
176      if (steps <= maxSteps) {
177        steps++;
178        if (heading == HeadingEnum.West) heading = HeadingEnum.North;
179        else heading++;
180      }
181    }
182
183    public void TurnLeft() {
184      if (steps <= maxSteps) {
185        steps++;
186        if (heading == HeadingEnum.North) heading = HeadingEnum.West;
187        else heading--;
188      }
189    }
190
191    public void Move() {
192      if (steps <= maxSteps) {
193        steps++;
194        MoveInternal(ref posX, ref posY);
195        if (world[posY][posX] == '#') {
196          FoodEaten++;
197          world[posY][posX] = '.';
198        }
199      }
200    }
201
202    private void MoveInternal(ref int posX, ref int posY) {
203      switch (heading) {
204        case HeadingEnum.North:
205          posY = (posY + 31) % 32;
206          break;
207        case HeadingEnum.East:
208          posX = (posX + 1) % 32;
209          break;
210        case HeadingEnum.South:
211          posY = (posY + 1) % 32;
212          break;
213        case HeadingEnum.West:
214          posX = (posX + 31) % 32;
215          break;
216      }
217    }
218
219    public bool IsFoodAhead() {
220      int nextPosX = posX;
221      int nextPosY = posY;
222      MoveInternal(ref nextPosX, ref nextPosY);
223      return world[nextPosY][nextPosX] == '#';
224    }
225  }
226}
Note: See TracBrowser for help on using the repository browser.