#region License Information /* HeuristicLab * Copyright (C) 2002-2019 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 HEAL.Attic; using HeuristicLab.Common; using HeuristicLab.Core; using HeuristicLab.Data; using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding; using HeuristicLab.Parameters; using HeuristicLab.Problems.DataAnalysis.Symbolic; using System.Collections.Generic; using System.Linq; namespace HeuristicLab.Algorithms.EvolvmentModelsOfModels { [Item("EMMMultyPointMutatorNodeTypeSaving", "Selects a random tree node and changes the symbol.")] [StorableType("8A24C715-BEFD-4396-9264-31F949330B1A")] public sealed class EMMMultyPointsMutatorNodeTypeSaving : SymbolicExpressionTreeManipulator { private const string MapParameterName = "Map"; private const string MutationProbabilityParameterName = "MutationProbability"; public ILookupParameter> MapParameter { get { return (ILookupParameter>)Parameters[MapParameterName]; } } public List ModelSet => MapParameter.ActualValue.ModelSet; public List> Map => MapParameter.ActualValue.Map; public ILookupParameter MutationProbabilityParameter { get { return (ILookupParameter)Parameters[MutationProbabilityParameterName]; } } public PercentValue MutationProbability => MutationProbabilityParameter.ActualValue; [StorableConstructor] private EMMMultyPointsMutatorNodeTypeSaving(StorableConstructorFlag _) : base(_) { } private EMMMultyPointsMutatorNodeTypeSaving(EMMMultyPointsMutatorNodeTypeSaving original, Cloner cloner) : base(original, cloner) { } public EMMMultyPointsMutatorNodeTypeSaving() : base() { Parameters.Add(new LookupParameter>(MapParameterName)); Parameters.Add(new LookupParameter(MutationProbabilityParameterName)); } public override IDeepCloneable Clone(Cloner cloner) { return new EMMMultyPointsMutatorNodeTypeSaving(this, cloner); } protected override void Manipulate(IRandom random, ISymbolicExpressionTree symbolicExpressionTree) { EMMOnePointMutatorPart(random, symbolicExpressionTree, ModelSet, Map, MutationProbability); } private static bool SymbolTypeCheck(ISymbol nSymbol, IEnumerable allSymbols) { foreach (var pSymbol in allSymbols) { if (nSymbol == pSymbol) return true; } return false; } public void EMMOnePointMutatorPart(IRandom random, ISymbolicExpressionTree symbolicExpressionTree, List modelSet, List> map, PercentValue mutationProbability) { List allowedSymbols = new List(); var probability = (1 / mutationProbability.Value) / (symbolicExpressionTree.Length); // probability for each node to mutate var allAllowedSymbols = symbolicExpressionTree.Root.Grammar.AllowedSymbols.Where(s => !(s is Defun) && !(s is GroupSymbol) && !(s is ProgramRootSymbol) && !(s is StartSymbol) ); symbolicExpressionTree.Root.ForEachNodePostfix(node => {//for each node in tree - try to mutate if (SymbolTypeCheck(node.Symbol, allAllowedSymbols)) { // we do not want to touch StartSymbol if (random.NextDouble() < probability) { // ok. this node decide to mutate if (node.Symbol.MaximumArity > 0) { foreach (var symbol in allAllowedSymbols) {// add in list all nodes with the same arity if ((symbol.MaximumArity == node.Symbol.MaximumArity) && (symbol.MinimumArity == node.Symbol.MinimumArity)) { allowedSymbols.Add(symbol); } } } else { // for terminal nodes add the same type of nodes allowedSymbols.Add(node.Symbol); } int pTemp = random.Next(modelSet.Count); if (node is TreeModelTreeNode treeNode) { pTemp = treeNode.TreeNumber; } //remember the cluster number var weights = allowedSymbols.Select(s => s.InitialFrequency).ToList(); // set up probabilities #pragma warning disable CS0618 // Type or member is obsolete var newSymbol = allowedSymbols.SelectRandom(weights, random); // create new node from the chosen symbol type. For terminal nodes it means that we have only one possible variant. #pragma warning restore CS0618 // Type or member is obsolete node = newSymbol.CreateTreeNode(); if (node is TreeModelTreeNode treeNode2) { // make right mutation for tree model treeNode2.TreeNumber = pTemp; MapParameter.ActualValue.NodeForMutationChange(random, treeNode2); } else if (node.HasLocalParameters) { // make local parameters set up for other node types node.ResetLocalParameters(random); } allowedSymbols.Clear(); // clean before the next node } } }); } } }