Index: branches/3136_Structural_GP/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/StructureTemplate/StructureTemplate.cs
===================================================================
--- branches/3136_Structural_GP/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/StructureTemplate/StructureTemplate.cs	(revision 18067)
+++ branches/3136_Structural_GP/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/StructureTemplate/StructureTemplate.cs	(revision 18068)
@@ -1,3 +1,4 @@
 ﻿using System;
+using System.Linq;
 using System.Collections.Generic;
 using HeuristicLab.Core;
@@ -17,10 +18,8 @@
       get => template; 
       set {
-        if(template != value) {
-          template = value;
-          tree = Parser.Parse(template);
-          GetSubFunctions(Tree);
-          OnChanged();
-        }
+        template = value;
+        tree = Parser.Parse(template);
+        GetSubFunctions(Tree);
+        OnChanged();
       } 
     }
@@ -31,7 +30,8 @@
 
     [Storable]
-    public IDictionary<SubFunctionTreeNode, SubFunction> SubFunctions { get; private set; } = new Dictionary<SubFunctionTreeNode, SubFunction>();
+    public IReadOnlyDictionary<string, SubFunction> SubFunctions { get; private set; } = new Dictionary<string, SubFunction>();
 
     protected InfixExpressionParser Parser { get; set; } = new InfixExpressionParser();
+
     #endregion
 
@@ -57,16 +57,28 @@
 
     private void GetSubFunctions(ISymbolicExpressionTree tree) {
-      int count = 1;
-      SubFunctions.Clear();
+      var subFunctions = new Dictionary<string, SubFunction>();
       foreach (var node in tree.IterateNodesPrefix())
-        if (node is SubFunctionTreeNode subFunctionTreeNode) { 
-          var subFunction = new SubFunction() { 
-            Name = $"f{count++}({string.Join(",", subFunctionTreeNode.Arguments)})", 
-            FunctionArguments = subFunctionTreeNode.Arguments 
-          };
-          subFunctionTreeNode.SubFunction = subFunction;
-          SubFunctions.Add(subFunctionTreeNode, subFunction);
+        if (node is SubFunctionTreeNode subFunctionTreeNode) {
+          if (!subFunctionTreeNode.Arguments.Any())
+            throw new ArgumentException($"The sub-function '{subFunctionTreeNode}' requires inputs (e.g. {subFunctionTreeNode.Name}(var1, var2)).");
+
+          if (subFunctions.TryGetValue(subFunctionTreeNode.Name, out SubFunction v)) {
+            if(!v.Arguments.SequenceEqual(subFunctionTreeNode.Arguments))
+              throw new ArgumentException(
+                $"The sub-function '{v.Name}' has (at least two) different signatures " + 
+                $"({v.Name}({string.Join(",", v.Arguments)}) <> {subFunctionTreeNode.Name}({string.Join(",", subFunctionTreeNode.Arguments)})).");
+          } else {
+            var subFunction = new SubFunction() {
+              Name = subFunctionTreeNode.Name,
+              Arguments = subFunctionTreeNode.Arguments
+            };
+            subFunction.Changed += OnSubFunctionChanged;
+            subFunctions.Add(subFunction.Name, subFunction);
+          }
         }
+      SubFunctions = subFunctions;
     }
+
+    private void OnSubFunctionChanged(object sender, EventArgs e) => OnChanged();
   }
 }
Index: branches/3136_Structural_GP/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/StructureTemplate/SubFunction.cs
===================================================================
--- branches/3136_Structural_GP/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/StructureTemplate/SubFunction.cs	(revision 18067)
+++ branches/3136_Structural_GP/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/StructureTemplate/SubFunction.cs	(revision 18068)
@@ -18,5 +18,4 @@
     private const string MaximumSymbolicExpressionTreeDepthParameterName = "MaximumSymbolicExpressionTreeDepth";
     private const string MaximumSymbolicExpressionTreeLengthParameterName = "MaximumSymbolicExpressionTreeLength";
-    private const string FunctionArgumentsParameterName = "Function Arguments";
     #endregion
 
@@ -25,5 +24,4 @@
     public IFixedValueParameter<IntValue> MaximumSymbolicExpressionTreeDepthParameter => (IFixedValueParameter<IntValue>)Parameters[MaximumSymbolicExpressionTreeDepthParameterName];
     public IFixedValueParameter<IntValue> MaximumSymbolicExpressionTreeLengthParameter => (IFixedValueParameter<IntValue>)Parameters[MaximumSymbolicExpressionTreeLengthParameterName];
-    public IValueParameter<ReadOnlyItemList<StringValue>> FunctionArgumentsParameter => (IValueParameter<ReadOnlyItemList<StringValue>>)Parameters[FunctionArgumentsParameterName];
     #endregion
 
@@ -44,18 +42,9 @@
     }
 
-    public IEnumerable<string> FunctionArguments { // TODO: gehört weg
-      get => FunctionArgumentsParameter.Value.Select(x => x.Value); 
-      set {
-        var varSym = (Variable)Grammar.GetSymbol("Variable");
-        if (varSym == null)
-          throw new ArgumentException($"No variable symbol existent.");
+    public IEnumerable<string> Arguments { get; set; }
+    #endregion
 
-        FunctionArgumentsParameter.Value = new ItemList<StringValue>(value.Select(x => new StringValue(x))).AsReadOnly();
-
-        varSym.AllVariableNames = FunctionArguments;
-        varSym.VariableNames = FunctionArguments;
-        varSym.Enabled = true;
-      } 
-    }
+    #region Events
+    public event EventHandler Changed;
     #endregion
 
@@ -65,6 +54,12 @@
       Parameters.Add(new FixedValueParameter<IntValue>(MaximumSymbolicExpressionTreeDepthParameterName, new IntValue(10)));
       Parameters.Add(new FixedValueParameter<IntValue>(MaximumSymbolicExpressionTreeLengthParameterName, new IntValue(30)));
-      Parameters.Add(new ValueParameter<ReadOnlyItemList<StringValue>>(FunctionArgumentsParameterName, new ReadOnlyItemList<StringValue>()));
+
+      // TODO: separate events for each parameter
+      GrammarParameter.ValueChanged += OnParameterValueChanged;
+      MaximumSymbolicExpressionTreeDepthParameter.Value.ValueChanged += OnParameterValueChanged; 
+      MaximumSymbolicExpressionTreeLengthParameter.Value.ValueChanged += OnParameterValueChanged;
     }
+
+    private void OnParameterValueChanged(object sender, EventArgs e) => Changed?.Invoke(this, EventArgs.Empty);
 
     protected SubFunction(SubFunction original, Cloner cloner) { }
Index: branches/3136_Structural_GP/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/SubFunctionSymbol.cs
===================================================================
--- branches/3136_Structural_GP/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/SubFunctionSymbol.cs	(revision 18067)
+++ branches/3136_Structural_GP/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/SubFunctionSymbol.cs	(revision 18068)
@@ -9,6 +9,6 @@
   [Item("SubFunctionSymbol", "Symbol that represents a sub function.")]
   public class SubFunctionSymbol : Symbol {
-    public override int MinimumArity => 1;
-    public override int MaximumArity => byte.MaxValue;
+    public override int MinimumArity => 0;
+    public override int MaximumArity => 1;
 
     public SubFunctionSymbol() : base("SubFunctionSymbol", "Symbol that represents a sub function.") { }
Index: branches/3136_Structural_GP/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/SubFunctionTreeNode.cs
===================================================================
--- branches/3136_Structural_GP/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/SubFunctionTreeNode.cs	(revision 18067)
+++ branches/3136_Structural_GP/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/SubFunctionTreeNode.cs	(revision 18068)
@@ -10,5 +10,5 @@
 namespace HeuristicLab.Problems.DataAnalysis.Symbolic {
   [StorableType("05130B5F-0125-4367-A4E9-C42D1085024E")]
-  public class SubFunctionTreeNode : SymbolicExpressionTreeNode { //TODO: as TerminalNode? -> but has children in a fully builded tree
+  public class SubFunctionTreeNode : SymbolicExpressionTreeNode {
 
     #region Properties
@@ -17,6 +17,4 @@
     public IEnumerable<string> Arguments { get; set; } = Enumerable.Empty<string>();
     
-    public SubFunction SubFunction { get; set; }
-
     public string Name { get; set; }
     #endregion
@@ -28,7 +26,5 @@
     protected SubFunctionTreeNode(StorableConstructorFlag _) : base(_) { }
 
-    protected SubFunctionTreeNode(SubFunctionTreeNode original, Cloner cloner) : base(original, cloner) {
-      this.SubFunction = original.SubFunction;
-    }
+    protected SubFunctionTreeNode(SubFunctionTreeNode original, Cloner cloner) : base(original, cloner) { }
     #endregion
 
@@ -40,5 +36,5 @@
       if (string.IsNullOrEmpty(Name))
         return base.ToString();
-      return Name;
+      return $"{Name}({string.Join(",", Arguments)})";
     }
     
