#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;
using System.Collections.Generic;
using HeuristicLab.Core;
namespace HeuristicLab.Encodings.ParameterConfigurationEncoding {
public class ParameterCombinationsEnumerator : IEnumerator {
private IOptimizable node;
private List enumerators;
private EnumeratorCollectionEnumerator valueEnumerator;
private bool initialized = false;
public ParameterCombinationsEnumerator(IOptimizable node) {
this.node = node;
this.enumerators = new List();
}
public IOptimizable Current {
get { return node; }
}
object IEnumerator.Current {
get {
if (!initialized)
throw new InvalidOperationException("Enumeration not started. Call MoveNext!");
return Current;
}
}
public void Dispose() { }
public bool MoveNext() {
if (!initialized) {
foreach (var enu in enumerators) {
enu.Reset();
if (!enu.MoveNext())
return false;
}
initialized = true;
} else {
int i = 0;
bool ok = false;
while (!ok && i < enumerators.Count) {
if (enumerators[i].MoveNext()) {
ok = true;
} else {
i++;
}
}
if (ok) {
for (int k = i - 1; k >= 0; k--) {
enumerators[k].Reset();
enumerators[k].MoveNext();
}
} else {
return false;
}
}
var pc = node as IParameterConfiguration;
if (pc != null && valueEnumerator != null) {
pc.ActualValue = ((IValueConfiguration)valueEnumerator.Current).ActualValue;
pc.UpdateActualValueIndexToItem((IValueConfiguration)valueEnumerator.Current);
}
var vc = node as IValueConfiguration;
if (vc != null && valueEnumerator != null) {
vc.ActualValue.Value = (IItem)valueEnumerator.Current;
}
return true;
}
public void Reset() {
enumerators.Clear();
valueEnumerator = null;
initialized = false;
var pc = node as IParameterConfiguration;
if (pc != null) {
valueEnumerator = new EnumeratorCollectionEnumerator();
foreach (var valueConfiguration in pc.ValueConfigurations.CheckedItems) {
if (valueConfiguration.Value.Optimize) {
var enumerator = new ParameterCombinationsEnumerator(valueConfiguration.Value);
enumerator.Reset();
valueEnumerator.AddEnumerator(enumerator);
} else {
valueEnumerator.AddEnumerator(new List { valueConfiguration.Value }.GetEnumerator());
}
}
valueEnumerator.Reset();
enumerators.Add(valueEnumerator);
}
var rangeVc = node as RangeValueConfiguration;
if (rangeVc != null) {
valueEnumerator = new EnumeratorCollectionEnumerator();
valueEnumerator.AddEnumerator(rangeVc.RangeConstraint.GetCombinations().GetEnumerator());
valueEnumerator.Reset();
enumerators.Add(valueEnumerator);
}
var parameterizedVc = node as ParameterizedValueConfiguration;
if (parameterizedVc != null) {
foreach (var parameterConfiguration in parameterizedVc.ParameterConfigurations) {
if (parameterConfiguration.Optimize) {
var enumerator = new ParameterCombinationsEnumerator(parameterConfiguration);
enumerator.Reset();
enumerators.Add(enumerator);
}
}
enumerators.Reverse(); // this makes the list of combinations better readable
}
}
}
///
/// Enumerator which can enumerate all elements of a list of enumerators
///
///
public class EnumeratorCollectionEnumerator : IEnumerator {
private List> enumerators = new List>();
private IEnumerator> currentEnumerator;
public EnumeratorCollectionEnumerator() { }
public void AddEnumerator(IEnumerator enumerator) {
enumerators.Add(enumerator);
}
public void Dispose() { }
public T Current {
get { return currentEnumerator.Current.Current; }
}
object IEnumerator.Current {
get { return this.Current; }
}
public bool MoveNext() {
bool ok = currentEnumerator.Current != null && currentEnumerator.Current.MoveNext();
if (!ok) {
ok = currentEnumerator.MoveNext();
if (!ok)
return false;
else
return this.MoveNext();
}
return true;
}
public void Reset() {
foreach (var enu in enumerators) {
enu.Reset();
}
currentEnumerator = enumerators.GetEnumerator();
currentEnumerator.Reset();
currentEnumerator.MoveNext();
}
}
}