using System; using System.Collections; using System.Collections.Generic; using HeuristicLab.Core; namespace HeuristicLab.Problems.MetaOptimization { 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.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(); } } }