Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/sources/HeuristicLab.Problems.ArtificialAnt/3.3/AntTrailView.cs @ 3238

Last change on this file since 3238 was 3238, checked in by gkronber, 15 years ago

Implemented a solution visualizer for the artificial ant problem. #952 (Artificial Ant Problem for 3.3)

File size: 10.6 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2010 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
4 *
5 * This file is part of HeuristicLab.
6 *
7 * HeuristicLab is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * HeuristicLab is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
19 */
20#endregion
21
22using System;
23using System.Drawing;
24using System.Windows.Forms;
25using HeuristicLab.Core.Views;
26using HeuristicLab.Data;
27using HeuristicLab.MainForm;
28using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
29using System.Collections.Generic;
30
31namespace HeuristicLab.Problems.ArtificialAnt {
32  [View("AntTrail View")]
33  [Content(typeof(AntTrail), true)]
34  public sealed partial class AntTrailView : ItemView {
35    private const int N_FOOD_ITEMS = 89;
36    private const int WORLD_WIDTH = 32;
37    private const int WORLD_HEIGHT = 32;
38    private const int FOOD = 1;
39    private const int EMPTY = 0;
40    private int[] SANTA_FE_TRAIL = new int[] {
41      0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
42      0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
43      0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0,
44      0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0,
45      0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0,
46      0, 0, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
47      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
48      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
49      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
50      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
51      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
52      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
53      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
54      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
55      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0,
56      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
57      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
58      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
59      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
60      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0,
61      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
62      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
63      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0,
64      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
65      0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
66      0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
67      0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
68      0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
69      0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
70      0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
71      0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
72      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
73    };
74
75    private const int MAX_TIME_STEPS = 600;
76
77    private int[] trail;
78    private int currentLocation;
79    private int currentDirection;
80    Stack<SymbolicExpressionTreeNode> nodeStack;
81
82    public new AntTrail Content {
83      get { return (AntTrail)base.Content; }
84      set { base.Content = value; }
85    }
86
87    public AntTrailView() {
88      InitializeComponent();
89      ResetTrailInterpreter();
90    }
91
92    public AntTrailView(AntTrail content)
93      : this() {
94      Content = content;
95    }
96
97    protected override void DeregisterContentEvents() {
98      Content.SymbolicExpressionTreeChanged -= new EventHandler(Content_SymbolicExpressionTreeChanged);
99      base.DeregisterContentEvents();
100    }
101    protected override void RegisterContentEvents() {
102      base.RegisterContentEvents();
103      Content.SymbolicExpressionTreeChanged += new EventHandler(Content_SymbolicExpressionTreeChanged);
104    }
105
106    protected override void OnContentChanged() {
107      base.OnContentChanged();
108      if (Content == null) {
109        pictureBox.Image = null;
110        pictureBox.Enabled = false;
111      } else {
112        pictureBox.Enabled = true;
113        GenerateImage();
114      }
115    }
116
117    private void ResetTrailInterpreter() {
118      nodeStack = new Stack<SymbolicExpressionTreeNode>();
119      currentLocation = 0;
120      currentDirection = 0;
121      trail = new int[WORLD_HEIGHT * WORLD_WIDTH];
122      Array.Copy(SANTA_FE_TRAIL, trail, SANTA_FE_TRAIL.Length);
123    }
124
125
126    private void GenerateImage() {
127      if ((pictureBox.Width > 0) && (pictureBox.Height > 0)) {
128        if (Content == null) {
129          pictureBox.Image = null;
130        } else {
131          ResetTrailInterpreter();
132          SymbolicExpressionTree expression = Content.SymbolicExpressionTree;
133
134          Bitmap bitmap = new Bitmap(pictureBox.Width, pictureBox.Height);
135          using (Graphics graphics = Graphics.FromImage(bitmap)) {
136            int cellHeight = pictureBox.Height / WORLD_HEIGHT;
137            int cellWidth = pictureBox.Width / WORLD_WIDTH;
138            // draw world
139            for (int i = 0; i < WORLD_HEIGHT; i++) {
140              graphics.DrawLine(Pens.Black, 0, i * cellHeight, pictureBox.Width, i * cellHeight);
141            }
142            for (int j = 0; j < WORLD_WIDTH; j++) {
143              graphics.DrawLine(Pens.Black, j * cellWidth, 0, j * cellWidth, pictureBox.Height);
144            }
145            for (int i = 0; i < WORLD_HEIGHT; i++) {
146              for (int j = 0; j < WORLD_WIDTH; j++) {
147                if (trail[i * WORLD_HEIGHT + j] == FOOD) graphics.FillEllipse(Brushes.LightBlue, j * cellWidth, i * cellHeight, cellWidth, cellHeight);
148              }
149            }
150            // step ant and draw trail
151            nodeStack.Clear();
152            int step = 0;
153            while (step < MAX_TIME_STEPS) {
154              // expression evaluated completly => start at root again
155              if (nodeStack.Count == 0)
156                nodeStack.Push(expression.Root.SubTrees[0]);
157
158              var currentNode = nodeStack.Pop();
159              if (currentNode.Symbol is Left) {
160                currentDirection = (currentDirection + 3) % 4;
161                step++;
162              } else if (currentNode.Symbol is Right) {
163                currentDirection = (currentDirection + 1) % 4;
164                step++;
165              } else if (currentNode.Symbol is Move) {
166                currentLocation = NextField();
167                trail[currentLocation] = EMPTY;
168                float currentCellX = currentLocation % WORLD_WIDTH;
169                float currentCellY = currentLocation / WORLD_HEIGHT;
170                graphics.FillRectangle(Brushes.Brown,
171                  currentCellX * cellWidth + cellWidth * 0.25f, currentCellY * cellHeight + cellHeight * 0.25f,
172                  cellWidth * 0.5f, cellHeight * 0.5f);
173                step++;
174              } else if (currentNode.Symbol is IfFoodAhead) {
175                if (trail[NextField()] == FOOD) {
176                  nodeStack.Push(currentNode.SubTrees[0]);
177                } else {
178                  nodeStack.Push(currentNode.SubTrees[1]);
179                }
180              } else if (currentNode.Symbol is Prog2) {
181                nodeStack.Push(currentNode.SubTrees[1]);
182                nodeStack.Push(currentNode.SubTrees[0]);
183              } else if (currentNode.Symbol is Prog3) {
184                nodeStack.Push(currentNode.SubTrees[2]);
185                nodeStack.Push(currentNode.SubTrees[1]);
186                nodeStack.Push(currentNode.SubTrees[0]);
187              } else {
188                throw new InvalidOperationException(currentNode.Symbol.ToString());
189              }
190
191             
192            }
193          }
194          pictureBox.Image = bitmap;
195        }
196      }
197    }
198
199    private int NextField() {
200      int currentLocationX = currentLocation % WORLD_WIDTH;
201      int currentLocationY = currentLocation / WORLD_HEIGHT;
202
203      switch (currentDirection) {
204        case 0:
205          currentLocationX = (currentLocationX + 1) % WORLD_WIDTH; // EAST
206          break;
207        case 1:
208          currentLocationY = (currentLocationY + 1) % WORLD_HEIGHT; // SOUTH
209          break;
210        case 2:
211          currentLocationX = (currentLocationX + WORLD_WIDTH - 1) % WORLD_WIDTH; // WEST
212          break;
213        case 3:
214          currentLocationY = (currentLocationY + WORLD_HEIGHT - 1) % WORLD_HEIGHT; // NORTH
215          break;
216        default:
217          throw new InvalidOperationException();
218      }
219      return currentLocationY * WORLD_WIDTH + currentLocationX;
220    }
221
222    void Content_SymbolicExpressionTreeChanged(object sender, EventArgs e) {
223      if (InvokeRequired)
224        Invoke(new EventHandler(Content_SymbolicExpressionTreeChanged), sender, e);
225      else
226        GenerateImage();
227    }
228
229    private void pictureBox_SizeChanged(object sender, EventArgs e) {
230      GenerateImage();
231    }
232  }
233}
Note: See TracBrowser for help on using the repository browser.