#region License Information
/* HeuristicLab
* Copyright (C) 2002-2012 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 HeuristicLab.Common;
using HeuristicLab.Core;
using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
namespace HeuristicLab.Encodings.ConditionActionEncoding {
[Item("XCSModel", "Represents a model of XCS")]
[StorableClass]
public class XCSModel : ReadOnlyItemCollection, IXCSModel {
public int ClassifierCount { get { return Count; } }
[Storable]
private IClassifierComparer comparer;
public IClassifierComparer ClassifierComparer {
get { return comparer; }
set { comparer = value; }
}
[StorableConstructor]
protected XCSModel(bool deserializing) : base(deserializing) { }
protected XCSModel(XCSModel original, Cloner cloner)
: base(original, cloner) {
name = (string)original.name.Clone();
description = (string)original.description.Clone();
if (original.comparer != null) {
comparer = (IClassifierComparer)original.comparer.Clone();
}
}
public override IDeepCloneable Clone(Cloner cloner) {
return new XCSModel(this, cloner);
}
public XCSModel() : base(new ItemCollection()) { }
public XCSModel(IItemCollection collection)
: base(collection) {
this.name = ItemName;
this.description = ItemDescription;
}
public IEnumerable GetAction(IEnumerable classifiers) {
foreach (var classifier in classifiers) {
yield return GetAction(classifier);
}
}
public IAction GetAction(IInput classifier) {
var matchedClassifiers = new ItemCollection();
foreach (var xcsClassifier in this) {
if (xcsClassifier.Classifier.MatchInput(classifier)) {
matchedClassifiers.Add(xcsClassifier);
}
}
if (matchedClassifiers.Count == 0) {
return null;
}
IDictionary predictionArray = CreatePredictionArray(matchedClassifiers);
return predictionArray.OrderByDescending(x => x.Value).First().Key;
}
private IDictionary CreatePredictionArray(ItemCollection matchedClassifiers) {
if (ClassifierComparer == null) {
throw new ArgumentException("No classifier comparer specified!");
}
var predictionArray = new Dictionary(ClassifierComparer);
var fitnessSumPerAction = new Dictionary(ClassifierComparer);
foreach (var xcsClassifier in matchedClassifiers) {
var action = xcsClassifier.Classifier.Action;
if (predictionArray.ContainsKey(action)) {
predictionArray[action] += xcsClassifier.Prediction.Value * xcsClassifier.Fitness.Value;
fitnessSumPerAction[action] += xcsClassifier.Fitness.Value;
} else {
predictionArray[action] = xcsClassifier.Prediction.Value * xcsClassifier.Fitness.Value;
fitnessSumPerAction[action] = xcsClassifier.Fitness.Value;
}
}
var actions = new List(predictionArray.Keys);
foreach (var action in actions) {
if (fitnessSumPerAction[action] != 0) {
predictionArray[action] = predictionArray[action] / fitnessSumPerAction[action];
}
}
return predictionArray;
}
public IXCSSolution CreateConditionActionSolution(IConditionActionProblemData problemData) {
return new XCSSolution(this, problemData);
}
IConditionActionSolution IConditionActionModel.CreateConditionActionSolution(IConditionActionProblemData problemData) {
return CreateConditionActionSolution(problemData);
}
#region INamedItem Members
[Storable]
protected string name;
public string Name {
get { return name; }
set {
if (!CanChangeName) throw new NotSupportedException("Name cannot be changed.");
if (!(name.Equals(value) || (value == null) && (name == string.Empty))) {
CancelEventArgs e = value == null ? new CancelEventArgs(string.Empty) : new CancelEventArgs(value);
OnNameChanging(e);
if (!e.Cancel) {
name = value == null ? string.Empty : value;
OnNameChanged();
}
}
}
}
public virtual bool CanChangeName {
get { return true; }
}
[Storable]
protected string description;
public string Description {
get { return description; }
set {
if (!CanChangeDescription) throw new NotSupportedException("Description cannot be changed.");
if (!(description.Equals(value) || (value == null) && (description == string.Empty))) {
description = value == null ? string.Empty : value;
OnDescriptionChanged();
}
}
}
public virtual bool CanChangeDescription {
get { return true; }
}
public override string ToString() {
return Name;
}
public event EventHandler> NameChanging;
protected virtual void OnNameChanging(CancelEventArgs e) {
var handler = NameChanging;
if (handler != null) handler(this, e);
}
public event EventHandler NameChanged;
protected virtual void OnNameChanged() {
var handler = NameChanged;
if (handler != null) handler(this, EventArgs.Empty);
OnToStringChanged();
}
public event EventHandler DescriptionChanged;
protected virtual void OnDescriptionChanged() {
var handler = DescriptionChanged;
if (handler != null) handler(this, EventArgs.Empty);
}
#endregion
}
}