Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/sources/HeuristicLab.Encodings.SymbolicExpressionTreeEncoding/3.3/ArchitectureAlteringOperators/SubroutineDuplicater.cs @ 3338

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

Fixed bugs related to dynamic symbol constraints with ADFs. #290 (Implement ADFs)

File size: 5.0 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  /// Manipulates a symbolic expression by duplicating a preexisting function-defining branch.
38  /// As described in Koza, Bennett, Andre, Keane, Genetic Programming III - Darwinian Invention and Problem Solving, 1999, pp. 88
39  /// </summary>
40  [Item("SubroutineDuplicater", "Manipulates a symbolic expression by duplicating a preexisting function-defining branch.")]
41  [StorableClass]
42  public sealed class SubroutineDuplicater : 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 = DuplicateRandomSubroutine(random, symbolicExpressionTree, grammar, maxTreeSize.Value, maxTreeHeight.Value, maxFunctionDefiningBranches.Value, maxFunctionArguments.Value);
51    }
52
53    public static bool DuplicateRandomSubroutine(
54      IRandom random,
55      SymbolicExpressionTree symbolicExpressionTree,
56      ISymbolicExpressionGrammar grammar,
57      int maxTreeSize, int maxTreeHeight,
58      int maxFunctionDefiningBranches, int maxFunctionArguments) {
59      var functionDefiningBranches = symbolicExpressionTree.IterateNodesPrefix().OfType<DefunTreeNode>();
60
61      string formatString = new StringBuilder().Append('0', (int)Math.Log10(maxFunctionDefiningBranches) + 1).ToString(); // >= 100 functions => ###
62      var allowedFunctionNames = from index in Enumerable.Range(0, maxFunctionDefiningBranches)
63                                 select "ADF" + index.ToString(formatString);
64      if (functionDefiningBranches.Count() == 0 || functionDefiningBranches.Count() == maxFunctionDefiningBranches)
65        // no function defining branches to duplicate or already reached the max number of ADFs
66        return false;
67      var selectedBranch = functionDefiningBranches.SelectRandom(random);
68      var clonedBranch = (DefunTreeNode)selectedBranch.Clone();
69      clonedBranch.Name = allowedFunctionNames.Except(UsedFunctionNames(symbolicExpressionTree)).First();
70      foreach (var node in symbolicExpressionTree.IterateNodesPrefix()) {
71        var invokeFunctionNode = node as InvokeFunctionTreeNode;
72        // find all invokations of the old function
73        if (invokeFunctionNode != null && invokeFunctionNode.InvokedFunctionName == selectedBranch.Name) {
74          // add the new function name to the list of known functions in the branches that used the originating function
75          var branch = symbolicExpressionTree.GetTopLevelBranchOf(invokeFunctionNode);
76          branch.AddDynamicSymbol(clonedBranch.Name, clonedBranch.NumberOfArguments);
77          // flip coin wether to replace with newly defined function
78          if (random.NextDouble() < 0.5) {
79            invokeFunctionNode.InvokedFunctionName = clonedBranch.Name;
80          }
81        }
82      }
83      Debug.Assert(grammar.IsValidExpression(symbolicExpressionTree));
84      return true;
85    }
86
87    private static bool ContainsNode(SymbolicExpressionTreeNode branch, SymbolicExpressionTreeNode node) {
88      if (branch == node) return true;
89      else foreach (var subtree in branch.SubTrees) {
90          if (ContainsNode(subtree, node)) return true;
91        }
92      return false;
93    }
94
95    private static IEnumerable<string> UsedFunctionNames(SymbolicExpressionTree symbolicExpressionTree) {
96      return from node in symbolicExpressionTree.IterateNodesPrefix()
97             where node.Symbol is Defun
98             select ((DefunTreeNode)node).Name;
99    }
100
101
102  }
103}
Note: See TracBrowser for help on using the repository browser.