#region License Information
/* HeuristicLab
* Copyright (C) 2002-2011 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
*
* This file is part of HeuristicLab.
*
* HeuristicLab is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* HeuristicLab is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with HeuristicLab. If not, see .
*/
#endregion
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
using HeuristicLab.Common;
using HeuristicLab.Core;
using HeuristicLab.Parameters;
using HeuristicLab.Data;
using HeuristicLab.Optimization;
using System.Threading;
using HeuristicLab.SimulationCore.AgentBased;
using HeuristicLab.Analysis;
namespace HeuristicLab.SimulationCore.Samples {
[Item("GameOfLifeSimulation", "A game of life simulation.")]
[Creatable("Simulations")]
[StorableClass]
public sealed class GameOfLifeSimulation: AgentBasedSimulation {
public override Type ProblemType {
get { return typeof(GameOfLifeScenario); }
}
private GameOfLifeScenario Scenario {
get {
return Problem as GameOfLifeScenario;
}
}
public ValueParameter IterationsParameter {
get { return (ValueParameter)Parameters["Iterations"]; }
}
public GameOfLifeSimulation() : base() {
Parameters.Add(new ValueParameter("Iterations", "The number of iterations.", new IntValue(100)));
Initialize();
}
[StorableConstructor]
private GameOfLifeSimulation(bool deserializing) : base(deserializing) { }
[StorableHook(HookType.AfterDeserialization)]
private void AfterDeserialization() {
Initialize();
}
private GameOfLifeSimulation(GameOfLifeSimulation original, Cloner cloner)
: base(original, cloner) {
Initialize();
}
public override IDeepCloneable Clone(Cloner cloner) {
return new GameOfLifeSimulation(this, cloner);
}
private GameOfLifeAgent GetAgent(int x, int y) {
int width = Scenario.WidthParameter.Value.Value;
int height = Scenario.HeightParameter.Value.Value;
if (x >= width || y >= height)
throw new Exception("invalid index");
int index = x + y * width;
return Agents[index] as GameOfLifeAgent;
}
private void Initialize() {
if (Scenario != null) {
Scenario.WidthParameter.ValueChanged += new EventHandler(WidthParameter_ValueChanged);
if(Scenario.WidthParameter.Value != null)
Scenario.WidthParameter.Value.ValueChanged += new EventHandler(Width_ValueChanged);
Scenario.HeightParameter.ValueChanged += new EventHandler(HeightParameter_ValueChanged);
if (Scenario.HeightParameter.Value != null)
Scenario.HeightParameter.Value.ValueChanged += new EventHandler(Height_ValueChanged);
}
}
void Width_ValueChanged(object sender, EventArgs e) {
CreateAgents();
}
void Height_ValueChanged(object sender, EventArgs e) {
CreateAgents();
}
void HeightParameter_ValueChanged(object sender, EventArgs e) {
CreateAgents();
}
void WidthParameter_ValueChanged(object sender, EventArgs e) {
CreateAgents();
}
public IEnumerable GetNeighbors(GameOfLifeAgent agent) {
int width = Scenario.WidthParameter.Value.Value;
int height = Scenario.HeightParameter.Value.Value;
int index = Agents.IndexOf(agent);
List result = new List();
int y = index / width;
int x = index - (y * width);
for (int x1 = x - 1; x1 <= x + 1; x1++) {
for (int y1 = y - 1; y1 <= y + 1; y1++) {
if (x1 >= 0 && y1 >= 0 && x1 < width && y1 < height &&
(x1 != x || y1 != y)) {
GameOfLifeAgent neighbor = GetAgent(x1, y1);
result.Add(neighbor);
}
}
}
return result;
}
private void CreateAgents() {
Agents.Clear();
int width = Scenario.WidthParameter.Value.Value;
int height = Scenario.HeightParameter.Value.Value;
for (int i = 0; i < width * height; i++) {
Agents.Add(new GameOfLifeAgent(this));
}
InitAgents();
}
protected override void OnProblemChanged() {
base.OnProblemChanged();
Initialize();
CreateAgents();
}
private void InitAgents() {
double rate = Scenario.AliveRateParameter.Value.Value;
int width = Scenario.WidthParameter.Value.Value;
int height = Scenario.HeightParameter.Value.Value;
Random rand = new Random();
for (int i = 0; i < width * height; i++) {
GameOfLifeAgent agent = Agents[i] as GameOfLifeAgent;
agent.Alive = rand.NextDouble() < rate;
}
}
protected override void OnPrepared() {
base.OnPrepared();
InitAgents();
}
private void UpdateResults() {
int width = Scenario.WidthParameter.Value.Value;
int height = Scenario.HeightParameter.Value.Value;
HeatMap cells = new HeatMap(width, height);
for (int i = 0; i < width * height; i++) {
int y = i / width;
int x = i - (y * width);
if (GetAgent(x, y).Alive)
cells[x, y] = 1;
else
cells[x, y] = 0;
}
Results["Cells"].Value = cells;
IntValue currentIterations = (Results["CurrentIterations"].Value as IntValue);
currentIterations.Value++;
}
protected override void Run(CancellationToken cancellationToken) {
int iterations = IterationsParameter.Value.Value;
int width = Scenario.WidthParameter.Value.Value;
int height = Scenario.HeightParameter.Value.Value;
int start = 0;
if (Results.ContainsKey("CurrentIterations")) {
start = (Results["CurrentIterations"].Value as IntValue).Value;
} else {
Results.Add(new Result("CurrentIterations", new IntValue(0)));
Results.Add(new Result("Cells", new HeatMap(width, height)));
}
for (int i = start; i < iterations; i++) {
cancellationToken.ThrowIfCancellationRequested();
base.Step();
UpdateResults();
Thread.Sleep(250);
}
}
}
}