#region License Information
/* HeuristicLab
* Copyright (C) 2002-2014 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.Data;
using HeuristicLab.Operators;
using HeuristicLab.Optimization;
using HeuristicLab.Parameters;
using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
namespace HeuristicLab.Algorithms.VOffspringSelectionGeneticAlgorithm {
[Item("ProbabilitiesGenerator", "An operator the generates the probability vector for Multi Crossovers/Mutators")]
[StorableClass]
public class ProbabilitiesGenerator : SingleSuccessorOperator, IAnalyzer {
public bool EnabledByDefault {
get { return false; }
}
public ValueParameter SuccessfulOffspringFlagParameter {
get { return (ValueParameter)Parameters["SuccessfulOffspringFlag"]; }
}
public ValueParameter OperatorNameVariableParameter {
get { return (ValueParameter)Parameters["OperatorNameVariable"]; }
}
public LookupParameter OperatorParameter {
get { return (LookupParameter)Parameters["Operator"]; }
}
public LookupParameter ProbablilitiesParameter {
get { return (LookupParameter)Parameters["Probabilities"]; }
}
public ValueParameter MinimumOperatorUsageParameter {
get { return (ValueParameter)Parameters["MinimumOperatorUsage"]; }
}
public LookupParameter> GeneratedOffspringParameter {
get { return (LookupParameter>)Parameters["GeneratedOffspring"]; }
}
public ValueLookupParameter ResultsParameter {
get { return (ValueLookupParameter)Parameters["Results"]; }
}
public override IDeepCloneable Clone(Cloner cloner) {
return new ProbabilitiesGenerator(this, cloner);
}
[StorableConstructor]
private ProbabilitiesGenerator(bool deserializing) : base(deserializing) { }
private ProbabilitiesGenerator(ProbabilitiesGenerator original, Cloner cloner) : base(original, cloner) { }
public ProbabilitiesGenerator()
: base() {
Parameters.Add(new ValueParameter("SuccessfulOffspringFlag", "The name of the flag which indicates if the individual was successful.", new StringValue("SuccessfulOffspring")));
Parameters.Add(new ValueParameter("OperatorNameVariable", "The properties of the successful offspring that should be collected.", new StringValue("SelectedCrossoverOperator")));
Parameters.Add(new LookupParameter("Probabilities", "The probability vector a multi crossover/mutator uses to decide which operator to use"));
Parameters.Add(new LookupParameter("Operator", "The multioperator that contains the list of used crossovers/mutators", "Crossover"));
Parameters.Add(new ValueParameter("MinimumOperatorUsage", "Minimum percentage of operator usage. ", new DoubleValue(0.05)));
Parameters.Add(new LookupParameter>("GeneratedOffspring", "Temporary store of the offspring population."));
Parameters.Add(new ValueLookupParameter("Results", "The result collection where the population diversity analysis results should be stored."));
}
public override IOperation Apply() {
if (GeneratedOffspringParameter.ActualValue == null) {
GeneratedOffspringParameter.ActualValue = new ItemList();
}
var offspring = GeneratedOffspringParameter.ActualValue;
string operatorName = OperatorNameVariableParameter.Value.Value;
string succssFlag = SuccessfulOffspringFlagParameter.Value.Value;
Dictionary operatorCount = new Dictionary();
Dictionary successfulOperatorCount = new Dictionary();
var crossover = OperatorParameter.ActualValue;
if (crossover.GetType().GetInterfaces().Any(x => x.IsGenericType &&
x.GetGenericTypeDefinition() == typeof(ICheckedMultiOperator<>))) {
for (int i = 0; i < offspring.Count; i++) {
// fetch values from scopes
IVariable tmpVar;
if (!offspring[i].Variables.TryGetValue(succssFlag, out tmpVar))
throw new InvalidOperationException(Name + ": Could not determine if an offspring was successful or not.");
BoolValue success = (tmpVar.Value as BoolValue);
if (success == null) throw new InvalidOperationException(Name + ": The variable that indicates whether an offspring is successful or not must contain a BoolValue.");
if (!offspring[i].Variables.TryGetValue(operatorName, out tmpVar))
throw new InvalidOperationException(Name + ": Could not determine operator an offspring was created with.");
StringValue op = (tmpVar.Value as StringValue);
if (op == null) throw new InvalidOperationException(Name + ": The variable the contains the operator name must be a string.");
if (!operatorCount.ContainsKey(op.Value)) {
operatorCount.Add(op.Value, 1);
} else {
operatorCount[op.Value]++;
}
if (success.Value) {
if (!successfulOperatorCount.ContainsKey(op.Value)) {
successfulOperatorCount.Add(op.Value, 1);
} else {
successfulOperatorCount[op.Value]++;
}
}
}
dynamic opCrossover = (dynamic)crossover;
int crossoverCount = (int)opCrossover.Operators.Count;
int checkedCrossoverCount = Enumerable.Count(opCrossover.Operators.CheckedItems);
dynamic[] crossoverNames = new dynamic[checkedCrossoverCount];
dynamic checkedItemsArray = Enumerable.ToArray(opCrossover.Operators.CheckedItems);
for (int i = 0; i < checkedCrossoverCount; i++) {
crossoverNames[i] = checkedItemsArray[i];
}
//initialize probabilities vector
if (ProbablilitiesParameter.ActualValue == null) {
ProbablilitiesParameter.ActualValue = new DoubleArray(crossoverCount);
ResultsParameter.ActualValue.Add(new Result("Probabilities", ProbablilitiesParameter.ActualValue));
for (int i = 0; i < crossoverCount; i++) {
ProbablilitiesParameter.ActualValue[i] = 1.0;
}
return base.Apply();
}
//fill probabilities vector
for (int i = 0; i < crossoverCount; i++) {
var cxNames = Enumerable.Where(crossoverNames, x => x.Index == i);
if (Enumerable.Any(cxNames)) {
var cxName = (string)Enumerable.Single(cxNames).Value.ItemName;
if (operatorCount.Any(x => x.Key.Contains(cxName))) {
int overallCount = operatorCount.Single(x => x.Key.Contains(cxName)).Value;
int successCount = 0;
if (successfulOperatorCount.Any(x => x.Key.Contains(cxName))) {
successCount = successfulOperatorCount.Single(x => x.Key.Contains(cxName)).Value;
}
double ratio = successCount / (double)overallCount;
if (ratio < MinimumOperatorUsageParameter.Value.Value) {
ratio = MinimumOperatorUsageParameter.Value.Value;
}
ProbablilitiesParameter.ActualValue[i] = ratio;
} else {
ProbablilitiesParameter.ActualValue[i] = MinimumOperatorUsageParameter.Value.Value;
}
} else {
ProbablilitiesParameter.ActualValue[i] = 0.0;
}
}
GeneratedOffspringParameter.ActualValue.Clear();
}
return base.Apply();
}
}
}