using System; using System.Collections.Generic; using System.Linq; namespace HeuristicLab.Problems.ProgramSynthesis.Push.Configuration { using HeuristicLab.Common; using HeuristicLab.Core; using HeuristicLab.Persistence.Default.CompositeSerializers.Storable; using HeuristicLab.Problems.ProgramSynthesis.Push.Expressions; using HeuristicLab.Problems.ProgramSynthesis.Push.Extensions; using HeuristicLab.Problems.ProgramSynthesis.Push.Stack; [StorableClass] public abstract class PushConfigurationBase : NamedItem, IExpressionsConfiguration { protected PushConfigurationBase() { Name = "Push Configuration"; enabledExpressions = ExpressionTable.ExpressionNames.ToList(); expressionsPerStackCount = new Dictionary(); InitExpressionsPerStackCount(); } [StorableConstructor] protected PushConfigurationBase(bool deserializing) : base(deserializing) { } protected PushConfigurationBase(PushConfigurationBase origin, Cloner cloner) : base(origin, cloner) { enabledExpressions = origin.EnabledExpressions.ToList(); expressionsPerStackCount = origin.expressionsPerStackCount.ToDictionary(x => x.Key, x => x.Value); InExpressionCount = origin.InExpressionCount; Seed = origin.Seed; } [Storable] public int Seed { get; set; } [Storable] public int InExpressionCount { get; private set; } [Storable] private readonly Dictionary expressionsPerStackCount; public IReadOnlyDictionary ExpressionsPerStackCount { get { return expressionsPerStackCount; } } public event EventHandler EnabledExpressionsChanged; [Storable] protected readonly List enabledExpressions; public bool IsStackEnabled(StackTypes type) { int count; return expressionsPerStackCount.TryGetValue(type, out count) && count > 0; } public IReadOnlyList EnabledExpressions { get { return enabledExpressions; } set { var removedExpressions = enabledExpressions.ToList(); enabledExpressions.Clear(); enabledExpressions.AddRange(value); if (EnabledExpressionsChanged != null) { EnabledExpressionsChanged(this, new EnabledExpressionsChangedEventArgs(value, removedExpressions)); } } } private void InitExpressionsPerStackCount() { foreach (StackTypes type in Enum.GetValues(typeof(StackTypes))) { if (type == StackTypes.None) continue; expressionsPerStackCount.Add(type, 0); } foreach (var expressionName in ExpressionTable.ExpressionNames) { var type = ExpressionTable.TypeToNameTable.Single(x => x.Value == expressionName).Key; var attribute = ExpressionTable.TypeToAttributeTable[type]; if (expressionsPerStackCount.ContainsKey(attribute.StackType)) { expressionsPerStackCount[attribute.StackType]++; } foreach (var additionalStackType in attribute.AdditionalStackDependencies.ToValues()) expressionsPerStackCount[additionalStackType]++; } } public void SetEnabledStacks(StackTypes types) { // Disable all enabledExpressions.Clear(); foreach (StackTypes type in Enum.GetValues(typeof(StackTypes))) { if (type == StackTypes.None) continue; expressionsPerStackCount[type] = 0; } var expressionNames = ExpressionTable.StackDependencyToNamesTable .Where(pair => types.HasFlag(pair.Key)) .SelectMany(pair => pair.Value); EnableExpressions(expressionNames); } public void EnableExpressionOfStack(StackTypes types) { EnableExpressions(ExpressionTable.StackTypeToNamesTable[types]); } public void EnableExpressionDependentOnStack(StackTypes types) { var names = ExpressionTable.StackDependencyToNamesTable[types].Where( name => { var type = ExpressionTable.NameToTypeTable[name]; var attribute = ExpressionTable.TypeToAttributeTable[type]; return (attribute.StackType | attribute.AdditionalStackDependencies) .ToEnumerable() .All(IsStackEnabled); }); EnableExpressions(names); } private void EnableExpressions(IEnumerable expressionNames) { var addedExpressions = expressionNames as IList ?? expressionNames.ToList(); foreach (var expressionName in addedExpressions.Except(EnabledExpressions)) EnableExpression(expressionName, false); if (EnabledExpressionsChanged != null) { EnabledExpressionsChanged(this, new EnabledExpressionsChangedEventArgs(addedExpressions, new string[0])); } } public void DisableExpressionsOfStack(StackTypes types) { DisableExpressions(ExpressionTable.StackTypeToNamesTable[types]); } public void DisableExpressionsDependentOnStack(StackTypes types) { var names = ExpressionTable.StackDependencyToNamesTable .Where(pair => pair.Key.HasFlag(types)) .SelectMany(pair => pair.Value); DisableExpressions(names); } private void DisableExpressions(IEnumerable expressionNames) { var removedExpressions = expressionNames as IList ?? expressionNames.ToList(); foreach (var expressionName in removedExpressions.Intersect(EnabledExpressions)) DisableExpression(expressionName, false); if (EnabledExpressionsChanged != null) { EnabledExpressionsChanged(this, new EnabledExpressionsChangedEventArgs(new string[0], removedExpressions)); } } public void EnableExpression(string expressionName) { EnableExpression(expressionName, true); } private void EnableExpression(string expressionName, bool triggerExpressionChanged) { if (enabledExpressions.Contains(expressionName)) return; var type = ExpressionTable.TypeToNameTable.Single(x => x.Value == expressionName).Key; var attribute = ExpressionTable.TypeToAttributeTable[type]; enabledExpressions.Add(expressionName); if (expressionsPerStackCount.ContainsKey(attribute.StackType)) expressionsPerStackCount[attribute.StackType]++; foreach (var additionalStackType in attribute.AdditionalStackDependencies.ToValues().Where(expressionsPerStackCount.ContainsKey)) expressionsPerStackCount[additionalStackType]++; if (EnabledExpressionsChanged != null && triggerExpressionChanged) { EnabledExpressionsChanged(this, new EnabledExpressionsChangedEventArgs( new[] { expressionName }, new string[0])); } } public void DisableExpression(string expressionName) { DisableExpression(expressionName, true); } public void DisableExpression(string expressionName, bool triggerExpressionChanged) { if (!EnabledExpressions.Contains(expressionName)) return; var type = ExpressionTable.TypeToNameTable.Single(x => x.Value == expressionName).Key; var attribute = ExpressionTable.TypeToAttributeTable[type]; enabledExpressions.Remove(expressionName); if (expressionsPerStackCount.ContainsKey(attribute.StackType)) expressionsPerStackCount[attribute.StackType]--; foreach (var additionalStackType in attribute.AdditionalStackDependencies.ToValues().Where(expressionsPerStackCount.ContainsKey)) expressionsPerStackCount[additionalStackType]--; if (EnabledExpressionsChanged != null && triggerExpressionChanged) { EnabledExpressionsChanged(this, new EnabledExpressionsChangedEventArgs( new string[0], new[] { expressionName })); } } public void EnableExpression() where T : Expression { var attribute = ExpressionTable.TypeToAttributeTable[typeof(T)]; EnableExpression(attribute.Name); } public void DisableExpression() where T : Expression { var attribute = ExpressionTable.TypeToAttributeTable[typeof(T)]; DisableExpression(attribute.Name); } public void SetExpression(string name, bool state) { if (state) EnableExpression(name); else DisableExpression(name); } public void SetExpression(bool state) where T : Expression { if (state) EnableExpression(); else DisableExpression(); } public void EnableStack(StackTypes type, bool enableDependencies = false) { EnableExpressionOfStack(type); if (enableDependencies) EnableExpressionDependentOnStack(type); } public void DisableStack(StackTypes type, bool disableDependencies = false) { DisableExpressionsOfStack(type); if (disableDependencies) DisableExpressionsDependentOnStack(type); } public void SetStack(StackTypes type, bool state, bool setDependencies = false) { if (state) EnableStack(type, setDependencies); else DisableStack(type, setDependencies); } public void InitInExpressions(int totalInputArgumentCount) { InExpressionCount = totalInputArgumentCount; for (var i = 0; i < ExpressionTable.InExpressionTable.Count; i++) { var expression = ExpressionTable.InExpressionTable[i]; var expressionName = ExpressionTable.TypeToNameTable[expression.GetType()]; DisableExpression(expressionName); } if (totalInputArgumentCount > ExpressionTable.InExpressionTable.Count) throw new InvalidOperationException("More input arguments defined as InExpression types"); for (var i = 0; i < totalInputArgumentCount; i++) { var expression = ExpressionTable.InExpressionTable[i]; var expressionName = ExpressionTable.TypeToNameTable[expression.GetType()]; EnableExpression(expressionName); } } } }