Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/sources/HeuristicLab.Encodings.SymbolicExpressionTreeEncoding/3.3/ArchitectureAlteringOperators/ArgumentCreater.cs @ 3294

Last change on this file since 3294 was 3294, checked in by gkronber, 12 years ago

Added first version of architecture altering operators for ADFs. #290 (Implement ADFs)

File size: 7.1 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2010 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
4 *
5 * This file is part of HeuristicLab.
6 *
7 * HeuristicLab is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * HeuristicLab is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
19 */
20#endregion
21
22using System;
23using System.Linq;
24using HeuristicLab.Core;
25using HeuristicLab.Data;
26using HeuristicLab.Operators;
27using HeuristicLab.Optimization;
28using HeuristicLab.Parameters;
29using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
30using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.GeneralSymbols;
31using System.Collections.Generic;
32using System.Text;
33using System.Diagnostics;
34
35namespace HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.ArchitectureAlteringOperators {
36  /// <summary>
37  /// Creates a new argument within one function-defining branch of a symbolic expression tree.
38  /// As described in Koza, Bennett, Andre, Keane, Genetic Programming III - Darwinian Invention and Problem Solving, 1999, pp. 106
39  /// </summary>
40  [Item("ArgumentCreater", "Manipulates a symbolic expression by creating a new argument within one function-defining branch.")]
41  [StorableClass]
42  public sealed class ArgumentCreater : SymbolicExpressionTreeArchitectureAlteringOperator {
43    public override sealed void ModifyArchitecture(
44      IRandom random,
45      SymbolicExpressionTree symbolicExpressionTree,
46      ISymbolicExpressionGrammar grammar,
47      IntValue maxTreeSize, IntValue maxTreeHeight,
48      IntValue maxFunctionDefiningBranches, IntValue maxFunctionArguments,
49      out bool success) {
50      success = CreateNewArgument(random, symbolicExpressionTree, grammar, maxTreeSize.Value, maxTreeHeight.Value, maxFunctionDefiningBranches.Value, maxFunctionArguments.Value);
51    }
52
53    public static bool CreateNewArgument(
54      IRandom random,
55      SymbolicExpressionTree symbolicExpressionTree,
56      ISymbolicExpressionGrammar grammar,
57      int maxTreeSize, int maxTreeHeight,
58      int maxFunctionDefiningBranches, int maxFunctionArguments) {
59
60      var functionDefiningBranches = symbolicExpressionTree.IterateNodesPrefix().OfType<DefunTreeNode>();
61
62      var allowedArgumentIndexes = Enumerable.Range(0, maxFunctionArguments);
63
64      if (functionDefiningBranches.Count() == 0)
65        // no function defining branch found => abort
66        return false;
67      // select a random function defining branch
68      var selectedDefunBranch = SelectRandomBranch(random, functionDefiningBranches);
69      // select a random cut point in the function defining branch
70      // the branch at the cut point is to be replaced by a new argument node
71      var cutPoints = (from node in IterateNodesPrefix(selectedDefunBranch)
72                       where node.SubTrees.Count > 0
73                       from subtree in node.SubTrees
74                       select new { Parent = node, ReplacedChildIndex = node.SubTrees.IndexOf(subtree), ReplacedChild = subtree }).ToList();
75
76      if (cutPoints.Count() == 0)
77        // no cut point found => abort;
78        return false;
79      var selectedCutPoint = cutPoints[random.Next(cutPoints.Count)];
80      var existingArguments = from node in IterateNodesPrefix(selectedDefunBranch)
81                              let argNode = node as ArgumentTreeNode
82                              where argNode != null
83                              select argNode;
84      var newArgumentIndex = allowedArgumentIndexes.Except(existingArguments.Select(x => x.ArgumentIndex)).First();
85      // replace the branch at the cut point with an argument node
86      var newArgNode = MakeArgumentNode(newArgumentIndex);
87      var replacedBranch = selectedCutPoint.ReplacedChild;
88      selectedCutPoint.Parent.RemoveSubTree(selectedCutPoint.ReplacedChildIndex);
89      selectedCutPoint.Parent.InsertSubTree(selectedCutPoint.ReplacedChildIndex, newArgNode);
90      // find all invokations of the selected ADF and attach a cloned version of the originally cut out branch
91      var invocationNodes = from node in symbolicExpressionTree.IterateNodesPrefix().OfType<InvokeFunctionTreeNode>()
92                            where node.InvokedFunctionName == selectedDefunBranch.Name
93                            select node;
94      // append a new argument branch after preprocessing
95      foreach (var invocationNode in invocationNodes) {
96        var clonedBranch = (SymbolicExpressionTreeNode)replacedBranch.Clone();
97        ReplaceArgumentsInBranch(clonedBranch, invocationNode.SubTrees);
98        invocationNode.InsertSubTree(newArgumentIndex, clonedBranch);
99      }
100      // adapt the known functions informations
101      selectedDefunBranch.NumberOfArguments++;
102      selectedDefunBranch.AddDynamicSymbol("ARG" + newArgumentIndex, 0);
103      foreach (var subtree in symbolicExpressionTree.Root.SubTrees) {
104        if (subtree.DynamicSymbols.Contains(selectedDefunBranch.Name)) {
105          subtree.SetDynamicSymbolArgumentCount(selectedDefunBranch.Name, selectedDefunBranch.NumberOfArguments);
106        }
107      }
108      Debug.Assert(grammar.IsValidExpression(symbolicExpressionTree));
109      return true;
110    }
111
112    private static void ReplaceArgumentsInBranch(SymbolicExpressionTreeNode branch, IList<SymbolicExpressionTreeNode> argumentTrees) {
113      // check if any subtree is an argument node
114      for (int subtreeIndex = 0; subtreeIndex < branch.SubTrees.Count; subtreeIndex++) {
115        var subtree = branch.SubTrees[subtreeIndex];
116        var argNode = subtree as ArgumentTreeNode;
117        if (argNode != null) {
118          // replace argument nodes by a clone of the original subtree that provided the result for the argument node
119          branch.SubTrees[subtreeIndex] = (SymbolicExpressionTreeNode)argumentTrees[argNode.ArgumentIndex].Clone();
120        } else {
121          // recursively replace arguments in all branches
122          ReplaceArgumentsInBranch(subtree, argumentTrees);
123        }
124      }
125    }
126
127    private static IEnumerable<SymbolicExpressionTreeNode> IterateNodesPrefix(SymbolicExpressionTreeNode tree) {
128      yield return tree;
129      foreach (var subTree in tree.SubTrees) {
130        foreach (var node in IterateNodesPrefix(subTree)) {
131          yield return node;
132        }
133      }
134    }
135
136    private static T SelectRandomBranch<T>(IRandom random, IEnumerable<T> branches) {
137      var list = branches.ToList();
138      return list[random.Next(list.Count)];
139    }
140
141    private static SymbolicExpressionTreeNode MakeArgumentNode(int argIndex) {
142      var node = (ArgumentTreeNode)(new Argument()).CreateTreeNode();
143      node.ArgumentIndex = argIndex;
144      return node;
145    }
146  }
147}
Note: See TracBrowser for help on using the repository browser.