Free cookie consent management tool by TermsFeed Policy Generator

source: branches/SimulationCore/HeuristicLab.SimulationCore.Samples/3.3/GameOfLifeDiscreteEventSimulation.cs @ 12734

Last change on this file since 12734 was 10454, checked in by abeham, 11 years ago

#1610: updated core, implemented card game sample

File size: 7.5 KB
Line 
1using System;
2using System.Collections.Generic;
3using HeuristicLab.Analysis;
4using HeuristicLab.Common;
5using HeuristicLab.Core;
6using HeuristicLab.Optimization;
7using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
8using HeuristicLab.Random;
9
10namespace HeuristicLab.SimulationCore.Samples {
11
12  #region Model
13  [StorableClass]
14  public sealed class GameOfLifeModel : IModel {
15    [Storable]
16    public double CurrentTime { get; set; }
17    [Storable]
18    public bool[,] Grid { get; set; }
19
20    private GameOfLifeModel(GameOfLifeModel original, Cloner cloner) {
21      cloner.RegisterClonedObject(original, this);
22      CurrentTime = original.CurrentTime;
23      Grid = (bool[,])original.Grid.Clone();
24    }
25    public GameOfLifeModel(int width, int height) {
26      Grid = new bool[height, width];
27    }
28
29    public object Clone() { return Clone(new Cloner()); }
30    public IDeepCloneable Clone(Cloner cloner) {
31      return new GameOfLifeModel(this, cloner);
32    }
33  }
34  #endregion
35
36  #region Simulation
37  [Item("Game of Life (discrete event)", "A discrete event based implementation of the game of life simulation.")]
38  [Creatable("Simulations")]
39  public class GameOfLifeDiscreteEventSimulation : DiscreteEventSimulation<GameOfLifeModel> {
40    public override Type ProblemType { get { return typeof(GameOfLifeScenario); } }
41
42    private GameOfLifeScenario Scenario {
43      get { return (GameOfLifeScenario)base.Problem; }
44      set { base.Problem = value; }
45    }
46
47    private GameOfLifeDiscreteEventSimulation(GameOfLifeDiscreteEventSimulation original, Cloner cloner)
48      : base(original, cloner) {
49      RegisterScenarioEventHandlers();
50    }
51    public GameOfLifeDiscreteEventSimulation() {
52      PrepareSimulation();
53      Scenario = new GameOfLifeScenario();
54      Parameterize();
55      RegisterScenarioEventHandlers();
56    }
57
58    public override IDeepCloneable Clone(Cloner cloner) {
59      return new GameOfLifeDiscreteEventSimulation(this, cloner);
60    }
61
62    [StorableHook(HookType.AfterDeserialization)]
63    private void AfterDeserialization() {
64      RegisterScenarioEventHandlers();
65    }
66
67    private void PrepareSimulation() {
68      InitialAction = new InitializeGameOfLifeBoardAction();
69      Activities = new IActivity<GameOfLifeModel>[] { new BoardActivity() };
70      Reporters = new IReporter<GameOfLifeModel>[] { new GameOfLifeStateReporter() };
71    }
72
73    private void RegisterScenarioEventHandlers() {
74      Scenario.WidthParameter.Value.ValueChanged += ParametersChanged;
75      Scenario.HeightParameter.Value.ValueChanged += ParametersChanged;
76      Scenario.AliveRateParameter.Value.ValueChanged += ParametersChanged;
77    }
78
79    protected override void OnProblemChanged() {
80      base.OnProblemChanged();
81      Parameterize();
82      RegisterScenarioEventHandlers();
83    }
84
85    protected override void OnPrepared() {
86      base.OnPrepared();
87      PrepareSimulation();
88    }
89
90    private void ParametersChanged(object sender, EventArgs e) {
91      Parameterize();
92    }
93
94    private void Parameterize() {
95      Model = new GameOfLifeModel(Scenario.WidthParameter.Value.Value, Scenario.HeightParameter.Value.Value);
96      ((InitializeGameOfLifeBoardAction)InitialAction).AliveRate = Scenario.AliveRateParameter.Value.Value;
97    }
98  }
99  #endregion
100
101  #region Activities
102  [StorableClass]
103  sealed class BoardActivity : Activity<GameOfLifeModel> {
104    public override IEnumerable<Type> MonitoredActions {
105      get { return new[] { typeof(InitializeGameOfLifeBoardAction), typeof(UpdateGameOfLifeBoardAction) }; }
106    }
107
108    [StorableConstructor]
109    private BoardActivity(bool deserializing) : base(deserializing) { }
110    private BoardActivity(BoardActivity original, Cloner cloner) : base(original, cloner) { }
111    public BoardActivity() : base(new SortedListEventQueue<GameOfLifeModel>()) { }
112
113    public override void ManageEvents(GameOfLifeModel model, IAction<GameOfLifeModel> lastAction) {
114      EventQueue.Push(model.CurrentTime + 1, new UpdateGameOfLifeBoardAction());
115    }
116
117    public override IDeepCloneable Clone(Cloner cloner) {
118      return new BoardActivity(this, cloner);
119    }
120  }
121  #endregion
122
123  #region Reporters
124  [StorableClass]
125  sealed class GameOfLifeStateReporter : Reporter<GameOfLifeModel> {
126
127    [StorableConstructor]
128    private GameOfLifeStateReporter(bool deserializing) : base(deserializing) { }
129    private GameOfLifeStateReporter(GameOfLifeStateReporter original, Cloner cloner) : base(original, cloner) { }
130    public GameOfLifeStateReporter() { }
131
132    public override void UpdateReporting(GameOfLifeModel model, ResultCollection results) {
133      var heatmap = new HeatMap(model.Grid.GetLength(0), model.Grid.GetLength(1));
134      for (var i = 0; i < heatmap.Rows; i++)
135        for (var j = 0; j < heatmap.Columns; j++)
136          heatmap[i, j] = model.Grid[i, j] ? 1 : 0;
137
138      if (!results.ContainsKey("Visualization"))
139        results.Add(new Result("Visualization", heatmap));
140      else results["Visualization"].Value = heatmap;
141    }
142
143    public override IDeepCloneable Clone(Cloner cloner) {
144      return new GameOfLifeStateReporter(this, cloner);
145    }
146  }
147  #endregion
148
149  #region Actions
150  [StorableClass]
151  sealed class InitializeGameOfLifeBoardAction : Action<GameOfLifeModel> {
152    [Storable]
153    public double AliveRate { get; set; }
154
155    private InitializeGameOfLifeBoardAction(InitializeGameOfLifeBoardAction original, Cloner cloner)
156      : base(original, cloner) {
157      AliveRate = original.AliveRate;
158    }
159    public InitializeGameOfLifeBoardAction() {
160      AliveRate = 0.2;
161    }
162
163    public override void Execute(GameOfLifeModel model) {
164      var random = new FastRandom();
165      var rows = model.Grid.GetLength(0);
166      var cols = model.Grid.GetLength(1);
167      for (var i = 0; i < rows; i++)
168        for (var j = 0; j < cols; j++) {
169          if (random.NextDouble() < AliveRate) model.Grid[i, j] = true;
170        }
171    }
172
173    public override IDeepCloneable Clone(Cloner cloner) {
174      return new InitializeGameOfLifeBoardAction(this, cloner);
175    }
176  }
177
178  [StorableClass]
179  sealed class UpdateGameOfLifeBoardAction : Action<GameOfLifeModel> {
180    private UpdateGameOfLifeBoardAction(UpdateGameOfLifeBoardAction original, Cloner cloner) : base(original, cloner) { }
181    public UpdateGameOfLifeBoardAction() { }
182
183    public override void Execute(GameOfLifeModel model) {
184      var rows = model.Grid.GetLength(0);
185      var cols = model.Grid.GetLength(1);
186      var newGrid = new bool[rows, cols];
187      for (var i = 0; i < rows; i++)
188        for (var j = 0; j < cols; j++) {
189          var neighbors = 0;
190          if (i > 0 && j > 0 && model.Grid[i - 1, j - 1]) neighbors++;
191          if (i > 0 && model.Grid[i - 1, j]) neighbors++;
192          if (i > 0 && j < cols - 1 && model.Grid[i - 1, j + 1]) neighbors++;
193          if (j > 0 && model.Grid[i, j - 1]) neighbors++;
194          if (j < cols - 1 && model.Grid[i, j + 1]) neighbors++;
195          if (i < rows - 1 && j > 0 && model.Grid[i + 1, j - 1]) neighbors++;
196          if (i < rows - 1 && model.Grid[i + 1, j]) neighbors++;
197          if (i < rows - 1 && j < cols - 1 && model.Grid[i + 1, j + 1]) neighbors++;
198          if ((model.Grid[i, j] && neighbors == 2) || neighbors == 3) newGrid[i, j] = true;
199        }
200      model.Grid = newGrid;
201    }
202
203    public override IDeepCloneable Clone(Cloner cloner) {
204      return new UpdateGameOfLifeBoardAction(this, cloner);
205    }
206  }
207  #endregion
208}
Note: See TracBrowser for help on using the repository browser.