Free cookie consent management tool by TermsFeed Policy Generator

Ignore:
Timestamp:
04/22/08 18:05:14 (16 years ago)
Author:
gkronber
Message:

merged FunctionsAndStructIdRefactoring-branch (r142, r143, r144, r145, r146, r147, r148, r149, r152, r153) back into the trunk (ticket #112)

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/sources/HeuristicLab.StructureIdentification/TreeGardener.cs

    r23 r155  
    3131using HeuristicLab.Operators;
    3232using HeuristicLab.Selection;
     33using HeuristicLab.Functions;
     34using System.Collections;
    3335
    3436namespace HeuristicLab.StructureIdentification {
    3537  internal class TreeGardener {
    3638    private IRandom random;
    37     private IOperatorLibrary opLibrary;
    38     private List<IOperator> functions;
    39     private List<IOperator> terminals;
    40 
    41     internal IList<IOperator> Terminals {
     39    private GPOperatorLibrary funLibrary;
     40    private List<IFunction> functions;
     41    private List<IFunction> terminals;
     42
     43    internal IList<IFunction> Terminals {
    4244      get { return terminals.AsReadOnly(); }
    4345    }
    44     private List<IOperator> allOperators;
    45 
    46     internal IList<IOperator> AllOperators {
    47       get { return allOperators.AsReadOnly(); }
    48     }
    49 
    50     internal TreeGardener(IRandom random, IOperatorLibrary opLibrary) {
     46    private List<IFunction> allFunctions;
     47
     48    internal IList<IFunction> AllFunctions {
     49      get { return allFunctions.AsReadOnly(); }
     50    }
     51
     52    internal TreeGardener(IRandom random, GPOperatorLibrary funLibrary) {
    5153      this.random = random;
    52       this.opLibrary = opLibrary;
    53 
    54       this.allOperators = new List<IOperator>();
    55       terminals = new List<IOperator>();
    56       functions = new List<IOperator>();
     54      this.funLibrary = funLibrary;
     55
     56      this.allFunctions = new List<IFunction>();
     57      terminals = new List<IFunction>();
     58      functions = new List<IFunction>();
    5759
    5860      // init functions and terminals based on constraints
    59       foreach (IOperator op in opLibrary.Group.Operators) {
     61      foreach (IFunction fun in funLibrary.Group.Operators) {
    6062        int maxA, minA;
    61         GetMinMaxArity(op, out minA, out maxA);
     63        GetMinMaxArity(fun, out minA, out maxA);
    6264        if (maxA == 0) {
    63           terminals.Add(op);
     65          terminals.Add(fun);
    6466        } else {
    65           functions.Add(op);
    66         }
    67       }
    68 
    69       allOperators.AddRange(functions);
    70       allOperators.AddRange(terminals);
     67          functions.Add(fun);
     68        }
     69      }
     70
     71      allFunctions.AddRange(functions);
     72      allFunctions.AddRange(terminals);
    7173    }
    7274
    7375    #region random initialization
    74     internal IOperator CreateRandomTree(ICollection<IOperator> allowedOperators, int maxTreeSize, int maxTreeHeight, bool balanceTrees) {
    75 
    76       int minTreeHeight = allowedOperators.Select(op => ((IntData)op.GetVariable(GPOperatorLibrary.MIN_TREE_HEIGHT).Value).Data).Min();
     76    internal IFunctionTree CreateRandomTree(ICollection<IFunction> allowedFunctions, int maxTreeSize, int maxTreeHeight, bool balanceTrees) {
     77
     78      int minTreeHeight = allowedFunctions.Select(f => ((IntData)f.GetVariable(GPOperatorLibrary.MIN_TREE_HEIGHT).Value).Data).Min();
    7779      if (minTreeHeight > maxTreeHeight)
    7880        maxTreeHeight = minTreeHeight;
    7981
    80       int minTreeSize = allowedOperators.Select(op => ((IntData)op.GetVariable(GPOperatorLibrary.MIN_TREE_SIZE).Value).Data).Min();
     82      int minTreeSize = allowedFunctions.Select(f => ((IntData)f.GetVariable(GPOperatorLibrary.MIN_TREE_SIZE).Value).Data).Min();
    8183      if (minTreeSize > maxTreeSize)
    8284        maxTreeSize = minTreeSize;
     
    8587      int treeSize = random.Next(minTreeSize, maxTreeSize + 1);
    8688
    87       IOperator[] possibleOperators = allowedOperators.Where(op => ((IntData)op.GetVariable(GPOperatorLibrary.MIN_TREE_HEIGHT).Value).Data <= treeHeight &&
    88         ((IntData)op.GetVariable(GPOperatorLibrary.MIN_TREE_SIZE).Value).Data <= treeSize).ToArray();
    89       IOperator selectedOperator = (IOperator)possibleOperators[random.Next(possibleOperators.Length)].Clone();
    90 
    91       IOperator rootOperator = CreateRandomTree(selectedOperator, treeSize, treeHeight, balanceTrees);
    92 
    93       return rootOperator;
    94     }
    95 
    96     internal IOperator CreateRandomTree(int maxTreeSize, int maxTreeHeight, bool balanceTrees) {
     89      IFunction[] possibleFunctions = allowedFunctions.Where(f => ((IntData)f.GetVariable(GPOperatorLibrary.MIN_TREE_HEIGHT).Value).Data <= treeHeight &&
     90        ((IntData)f.GetVariable(GPOperatorLibrary.MIN_TREE_SIZE).Value).Data <= treeSize).ToArray();
     91      IFunction selectedFunction = possibleFunctions[random.Next(possibleFunctions.Length)];
     92
     93      return CreateRandomTree(selectedFunction, treeSize, treeHeight, balanceTrees);
     94    }
     95
     96    internal IFunctionTree CreateRandomTree(int maxTreeSize, int maxTreeHeight, bool balanceTrees) {
    9797      if (balanceTrees) {
    9898        if (maxTreeHeight == 1 || maxTreeSize==1) {
    99           IOperator selectedTerminal = (IOperator)terminals[random.Next(terminals.Count())].Clone();
    100           return selectedTerminal;
     99          IFunction selectedTerminal = terminals[random.Next(terminals.Count())];
     100          return new FunctionTree(selectedTerminal);
    101101        } else {
    102           IOperator[] possibleFunctions = functions.Where(f => GetMinimalTreeHeight(f) <= maxTreeHeight &&
     102          IFunction[] possibleFunctions = functions.Where(f => GetMinimalTreeHeight(f) <= maxTreeHeight &&
    103103            GetMinimalTreeSize(f) <= maxTreeSize).ToArray();
    104           IOperator selectedFunction = (IOperator)possibleFunctions[random.Next(possibleFunctions.Length)].Clone();
    105           MakeBalancedTree(selectedFunction, maxTreeSize - 1, maxTreeHeight - 1);
    106           return selectedFunction;
     104          IFunction selectedFunction = possibleFunctions[random.Next(possibleFunctions.Length)];
     105          FunctionTree root = new FunctionTree(selectedFunction);
     106          MakeBalancedTree(root, maxTreeSize - 1, maxTreeHeight - 1);
     107          return root;
    107108        }
    108109
    109110      } else {
    110         IOperator[] possibleOperators = allOperators.Where(op => GetMinimalTreeHeight(op) <= maxTreeHeight &&
    111           GetMinimalTreeSize(op) <= maxTreeSize).ToArray();
    112         IOperator selectedOperator = (IOperator)possibleOperators[random.Next(possibleOperators.Length)].Clone();
    113         MakeUnbalancedTree(selectedOperator, maxTreeSize - 1, maxTreeHeight - 1);
    114         return selectedOperator;
    115       }
    116     }
    117 
    118     internal IOperator CreateRandomTree(IOperator root, int maxTreeSize, int maxTreeHeight, bool balanceTrees) {
     111        IFunction[] possibleFunctions = allFunctions.Where(f => GetMinimalTreeHeight(f) <= maxTreeHeight &&
     112          GetMinimalTreeSize(f) <= maxTreeSize).ToArray();
     113        IFunction selectedFunction = possibleFunctions[random.Next(possibleFunctions.Length)];
     114        FunctionTree root = new FunctionTree(selectedFunction);
     115        MakeUnbalancedTree(root, maxTreeSize - 1, maxTreeHeight - 1);
     116        return root;
     117      }
     118    }
     119
     120    internal IFunctionTree CreateRandomTree(IFunction rootFunction, int maxTreeSize, int maxTreeHeight, bool balanceTrees) {
     121      IFunctionTree root = new FunctionTree(rootFunction);
    119122      if (balanceTrees) {
    120123        MakeBalancedTree(root, maxTreeSize - 1, maxTreeHeight - 1);
     
    130133
    131134
    132     private void MakeUnbalancedTree(IOperator parent, int maxTreeSize, int maxTreeHeight) {
     135    private void MakeUnbalancedTree(IFunctionTree parent, int maxTreeSize, int maxTreeHeight) {
    133136      if (maxTreeHeight == 0 || maxTreeSize == 0) return;
    134137      int minArity;
    135138      int maxArity;
    136       GetMinMaxArity(parent, out minArity, out maxArity);
     139      GetMinMaxArity(parent.Function, out minArity, out maxArity);
    137140      if (maxArity >= maxTreeSize) {
    138141        maxArity = maxTreeSize;
     
    142145        int maxSubTreeSize = maxTreeSize / actualArity;
    143146        for (int i = 0; i < actualArity; i++) {
    144           IOperator[] possibleOperators = GetAllowedSubOperators(parent, i).Where(op => GetMinimalTreeHeight(op) <= maxTreeHeight &&
    145             GetMinimalTreeSize(op) <= maxSubTreeSize).ToArray();
    146           IOperator selectedOperator = (IOperator)possibleOperators[random.Next(possibleOperators.Length)].Clone();
    147           parent.AddSubOperator(selectedOperator, i);
    148           MakeUnbalancedTree(selectedOperator, maxSubTreeSize - 1, maxTreeHeight - 1);
     147          IFunction[] possibleFunctions = GetAllowedSubFunctions(parent.Function, i).Where(f => GetMinimalTreeHeight(f) <= maxTreeHeight &&
     148            GetMinimalTreeSize(f) <= maxSubTreeSize).ToArray();
     149          IFunction selectedFunction = possibleFunctions[random.Next(possibleFunctions.Length)];
     150          FunctionTree newSubTree = new FunctionTree(selectedFunction);
     151          MakeUnbalancedTree(newSubTree, maxSubTreeSize - 1, maxTreeHeight - 1);
     152          parent.InsertSubTree(i, newSubTree);
    149153        }
    150154      }
     
    152156
    153157    // NOTE: this method doesn't build fully balanced trees because we have constraints on the
    154     // types of possible suboperators which can indirectly impose a limit for the depth of a given suboperator
    155     private void MakeBalancedTree(IOperator parent, int maxTreeSize, int maxTreeHeight) {
     158    // types of possible sub-functions which can indirectly impose a limit for the depth of a given sub-tree
     159    private void MakeBalancedTree(IFunctionTree parent, int maxTreeSize, int maxTreeHeight) {
    156160      if (maxTreeHeight == 0 || maxTreeSize == 0) return; // should never happen anyway
    157161      int minArity;
    158162      int maxArity;
    159       GetMinMaxArity(parent, out minArity, out maxArity);
     163      GetMinMaxArity(parent.Function, out minArity, out maxArity);
    160164      if (maxArity >= maxTreeSize) {
    161165        maxArity = maxTreeSize;
     
    166170        for (int i = 0; i < actualArity; i++) {
    167171          if (maxTreeHeight == 1 || maxSubTreeSize == 1) {
    168             IOperator[] possibleTerminals = GetAllowedSubOperators(parent, i).Where(
    169               op => GetMinimalTreeHeight(op) <= maxTreeHeight &&
    170               GetMinimalTreeSize(op) <= maxSubTreeSize &&
    171               IsTerminal(op)).ToArray();
    172             IOperator selectedTerminal = (IOperator)possibleTerminals[random.Next(possibleTerminals.Length)].Clone();
    173             parent.AddSubOperator(selectedTerminal, i);
     172            IFunction[] possibleTerminals = GetAllowedSubFunctions(parent.Function, i).Where(
     173              f => GetMinimalTreeHeight(f) <= maxTreeHeight &&
     174              GetMinimalTreeSize(f) <= maxSubTreeSize &&
     175              IsTerminal(f)).ToArray();
     176            IFunction selectedTerminal = possibleTerminals[random.Next(possibleTerminals.Length)];
     177            IFunctionTree newTree = new FunctionTree(selectedTerminal);
     178            parent.InsertSubTree(i, newTree);
    174179          } else {
    175             IOperator[] possibleFunctions = GetAllowedSubOperators(parent, i).Where(
    176               op => GetMinimalTreeHeight(op) <= maxTreeHeight &&
    177               GetMinimalTreeSize(op) <= maxSubTreeSize &&
    178               !IsTerminal(op)).ToArray();
    179             IOperator selectedFunction = (IOperator)possibleFunctions[random.Next(possibleFunctions.Length)].Clone();
    180             parent.AddSubOperator(selectedFunction, i);
    181             MakeBalancedTree(selectedFunction, maxSubTreeSize - 1, maxTreeHeight - 1);
     180            IFunction[] possibleFunctions = GetAllowedSubFunctions(parent.Function, i).Where(
     181              f => GetMinimalTreeHeight(f) <= maxTreeHeight &&
     182              GetMinimalTreeSize(f) <= maxSubTreeSize &&
     183              !IsTerminal(f)).ToArray();
     184            IFunction selectedFunction = possibleFunctions[random.Next(possibleFunctions.Length)];
     185            FunctionTree newTree = new FunctionTree(selectedFunction);
     186            parent.InsertSubTree(i, newTree);
     187            MakeBalancedTree(newTree, maxSubTreeSize - 1, maxTreeHeight - 1);
    182188          }
    183189        }
     
    185191    }
    186192
    187     internal CompositeOperation CreateInitializationOperation(ICollection<IOperator> operators, IScope scope) {
     193    internal CompositeOperation CreateInitializationOperation(ICollection<IFunctionTree> trees, IScope scope) {
    188194      // needed for the parameter shaking operation
    189195      CompositeOperation initializationOperation = new CompositeOperation();
    190196      Scope tempScope = new Scope("Temp. initialization scope");
    191197
    192       var parametricOperators = operators.Where(o => o.GetVariable(GPOperatorLibrary.INITIALIZATION) != null);
    193 
    194       foreach (IOperator op in parametricOperators) {
     198      var parametricTrees = trees.Where(t => t.Function.GetVariable(GPOperatorLibrary.INITIALIZATION) != null);
     199
     200      foreach (IFunctionTree tree in parametricTrees) {
    195201        // enqueue an initialization operation for each operator with local variables
    196         IOperator initialization = (IOperator)op.GetVariable(GPOperatorLibrary.INITIALIZATION).Value;
     202        IOperator initialization = (IOperator)tree.Function.GetVariable(GPOperatorLibrary.INITIALIZATION).Value;
    197203        Scope initScope = new Scope();
    198204
    199205        // copy the local variables into a temporary scope used for initialization
    200         foreach (VariableInfo info in op.VariableInfos) {
    201           if (info.Local) {
    202             initScope.AddVariable(op.GetVariable(info.FormalName));
    203           }
     206        foreach (IVariable variable in tree.LocalVariables) {
     207          initScope.AddVariable(variable);
    204208        }
    205209
     
    223227
    224228    #region tree information gathering
    225     internal int GetTreeSize(IOperator tree) {
    226       return 1 + tree.SubOperators.Sum(f => GetTreeSize(f));
    227     }
    228 
    229     internal int GetTreeHeight(IOperator tree) {
    230       if (tree.SubOperators.Count == 0) return 1;
    231       return 1 + tree.SubOperators.Max(f => GetTreeHeight(f));
    232     }
    233 
    234     internal IOperator GetRandomParentNode(IOperator tree) {
    235       List<IOperator> parentNodes = new List<IOperator>();
     229    internal int GetTreeSize(IFunctionTree tree) {
     230      return 1 + tree.SubTrees.Sum(f => GetTreeSize(f));
     231    }
     232
     233    internal int GetTreeHeight(IFunctionTree tree) {
     234      if (tree.SubTrees.Count == 0) return 1;
     235      return 1 + tree.SubTrees.Max(f => GetTreeHeight(f));
     236    }
     237
     238    internal IFunctionTree GetRandomParentNode(IFunctionTree tree) {
     239      List<IFunctionTree> parentNodes = new List<IFunctionTree>();
    236240
    237241      // add null for the parent of the root node
    238242      parentNodes.Add(null);
    239243
    240       TreeForEach(tree, delegate(IOperator op) {
    241         if (op.SubOperators.Count > 0) {
    242           parentNodes.Add(op);
     244      TreeForEach(tree, delegate(IFunctionTree possibleParentNode) {
     245        if (possibleParentNode.SubTrees.Count > 0) {
     246          parentNodes.Add(possibleParentNode);
    243247        }
    244248      });
     
    247251    }
    248252
    249     internal IList<IOperator> GetAllowedSubOperators(IOperator op, int index) {
    250       if (op == null) {
    251         return allOperators;
     253    internal IList<IFunction> GetAllowedSubFunctions(IFunction f, int index) {
     254      if (f == null) {
     255        return allFunctions;
    252256      } else {
    253 
    254         SubOperatorsConstraintAnalyser analyser = new SubOperatorsConstraintAnalyser();
    255         analyser.AllPossibleOperators = allOperators;
    256 
    257         return analyser.GetAllowedOperators(op, index);
    258       }
    259     }
    260     internal void GetMinMaxArity(IOperator root, out int minArity, out int maxArity) {
    261       foreach (IConstraint constraint in root.Constraints) {
     257        ItemList slotList = (ItemList)f.GetVariable(GPOperatorLibrary.ALLOWED_SUBOPERATORS).Value;
     258        List<IFunction> result = new List<IFunction>();
     259        foreach(IFunction function in (ItemList)slotList[index]) {
     260          result.Add(function);
     261        }
     262        return result;
     263      }
     264    }
     265    internal void GetMinMaxArity(IFunction f, out int minArity, out int maxArity) {
     266      foreach (IConstraint constraint in f.Constraints) {
    262267        NumberOfSubOperatorsConstraint theConstraint = constraint as NumberOfSubOperatorsConstraint;
    263268        if (theConstraint != null) {
     
    271276      maxArity = 2;
    272277    }
    273     internal bool IsTerminal(IOperator f) {
     278    internal bool IsTerminal(IFunction f) {
    274279      int minArity;
    275280      int maxArity;
     
    278283    }
    279284
    280     internal IList<IOperator> GetAllowedParents(IOperator child, int childIndex) {
    281       List<IOperator> parents = new List<IOperator>();
    282       foreach (IOperator function in functions) {
    283         IList<IOperator> allowedSubOperators = GetAllowedSubOperators(function, childIndex);
    284         if (allowedSubOperators.Contains(child, new OperatorEqualityComparer())) {
     285    internal IList<IFunction> GetAllowedParents(IFunction child, int childIndex) {
     286      List<IFunction> parents = new List<IFunction>();
     287      foreach (IFunction function in functions) {
     288        ICollection<IFunction> allowedSubFunctions = GetAllowedSubFunctions(function, childIndex);
     289        if (allowedSubFunctions.Contains(child)) {
    285290          parents.Add(function);
    286291        }
     
    289294    }
    290295
    291     internal ICollection<IOperator> GetAllOperators(IOperator root) {
    292       List<IOperator> allOps = new List<IOperator>();
    293       TreeForEach(root, t => { allOps.Add(t); });
    294       return allOps;
     296    internal ICollection<IFunctionTree> GetAllSubTrees(IFunctionTree root) {
     297      List<IFunctionTree> allTrees = new List<IFunctionTree>();
     298      TreeForEach(root, t => { allTrees.Add(t); });
     299      return allTrees;
    295300    }
    296301
    297302    /// <summary>
    298     /// returns the height level of op in the tree
    299     /// if the op == tree => 1
    300     /// if op is in the suboperators of tree => 2
     303    /// returns the height level of branch in the tree
     304    /// if the branch == tree => 1
     305    /// if branch is in the sub-trees of tree => 2
    301306    /// ...
    302     /// if op is not found => -1
     307    /// if branch is not found => -1
    303308    /// </summary>
    304     /// <param name="tree">operator tree to process</param>
    305     /// <param name="op">operater that is searched in the tree</param>
     309    /// <param name="tree">root of the function tree to process</param>
     310    /// <param name="branch">branch that is searched in the tree</param>
    306311    /// <returns></returns>
    307     internal int GetNodeLevel(IOperator tree, IOperator op) {
    308       return GetNodeLevelHelper(tree, op, 1);
    309     }
    310 
    311     private int GetNodeLevelHelper(IOperator tree, IOperator op, int level) {
    312       if (op == tree) return level;
    313 
    314       foreach (IOperator subTree in tree.SubOperators) {
    315         int result = GetNodeLevelHelper(subTree, op, level + 1);
     312    internal int GetBranchLevel(IFunctionTree tree, IFunctionTree branch) {
     313      return GetBranchLevelHelper(tree, branch, 1);
     314    }
     315
     316    // 'tail-recursive' helper
     317    private int GetBranchLevelHelper(IFunctionTree tree, IFunctionTree branch, int level) {
     318      if (branch == tree) return level;
     319
     320      foreach (IFunctionTree subTree in tree.SubTrees) {
     321        int result = GetBranchLevelHelper(subTree, branch, level + 1);
    316322        if (result != -1) return result;
    317323      }
     
    320326    }
    321327
    322     internal bool IsValidTree(IOperator tree) {
    323       if (!tree.IsValid())
    324         return false;
    325       foreach (IOperator subTree in tree.SubOperators) {
    326         if (!subTree.IsValid())
    327           return false;
    328       }
    329 
     328    internal bool IsValidTree(IFunctionTree tree) {
     329      foreach(IConstraint constraint in tree.Function.Constraints) {
     330        if(constraint is NumberOfSubOperatorsConstraint) {
     331          int max = ((NumberOfSubOperatorsConstraint)constraint).MaxOperators.Data;
     332          int min = ((NumberOfSubOperatorsConstraint)constraint).MinOperators.Data;
     333          if(tree.SubTrees.Count < min || tree.SubTrees.Count > max)
     334            return false;
     335        }
     336      }
     337      foreach(IFunctionTree subTree in tree.SubTrees) {
     338        if(!IsValidTree(subTree)) return false;
     339      }
    330340      return true;
    331341    }
    332342
    333     // returns a random node from the specified level in the tree
    334     internal IOperator GetRandomNode(IOperator tree, int level) {
     343    // returns a random branch from the specified level in the tree
     344    internal IFunctionTree GetRandomBranch(IFunctionTree tree, int level) {
    335345      if (level == 0) return tree;
    336       List<IOperator> nodes = GetOperatorsAtLevel(tree, level);
    337       return nodes[random.Next(nodes.Count)];
     346      List<IFunctionTree> branches = GetBranchesAtLevel(tree, level);
     347      return branches[random.Next(branches.Count)];
    338348    }
    339349    #endregion
     
    349359    }
    350360
    351     private void TreeForEach(IOperator tree, Action<IOperator> action) {
     361    private void TreeForEach(IFunctionTree tree, Action<IFunctionTree> action) {
    352362      action(tree);
    353       foreach (IOperator child in tree.SubOperators) {
    354         TreeForEach(child, action);
    355       }
    356     }
    357 
    358     private List<IOperator> GetOperatorsAtLevel(IOperator tree, int level) {
    359       if (level == 1) return new List<IOperator>(tree.SubOperators);
    360 
    361       List<IOperator> result = new List<IOperator>();
    362       foreach (IOperator subOperator in tree.SubOperators) {
    363         result.AddRange(GetOperatorsAtLevel(subOperator, level - 1));
     363      foreach (IFunctionTree subTree in tree.SubTrees) {
     364        TreeForEach(subTree, action);
     365      }
     366    }
     367
     368    private List<IFunctionTree> GetBranchesAtLevel(IFunctionTree tree, int level) {
     369      if (level == 1) return new List<IFunctionTree>(tree.SubTrees);
     370
     371      List<IFunctionTree> branches = new List<IFunctionTree>();
     372      foreach (IFunctionTree subTree in tree.SubTrees) {
     373        branches.AddRange(GetBranchesAtLevel(subTree, level - 1));
     374      }
     375      return branches;
     376    }
     377
     378
     379    #endregion
     380
     381    internal ICollection<IFunction> GetPossibleParents(List<IFunction> list) {
     382      List<IFunction> result = new List<IFunction>();
     383      foreach (IFunction f in functions) {
     384        if (IsPossibleParent(f, list)) {
     385          result.Add(f);
     386        }
    364387      }
    365388      return result;
    366389    }
    367390
    368 
    369     #endregion
    370 
    371     internal class OperatorEqualityComparer : IEqualityComparer<IOperator> {
    372       #region IEqualityComparer<IOperator> Members
    373 
    374       public bool Equals(IOperator x, IOperator y) {
    375         return ((StringData)x.GetVariable(GPOperatorLibrary.TYPE_ID).Value).Data ==
    376           ((StringData)y.GetVariable(GPOperatorLibrary.TYPE_ID).Value).Data;
    377       }
    378 
    379       public int GetHashCode(IOperator obj) {
    380         return ((StringData)obj.GetVariable(GPOperatorLibrary.TYPE_ID).Value).Data.GetHashCode();
    381       }
    382 
    383       #endregion
    384     }
    385 
    386     internal ICollection<IOperator> GetPossibleParents(List<IOperator> list) {
    387       List<IOperator> result = new List<IOperator>();
    388       foreach (IOperator op in functions) {
    389         if (IsPossibleParent(op, list)) {
    390           result.Add(op);
    391         }
    392       }
    393       return result;
    394     }
    395 
    396     private bool IsPossibleParent(IOperator op, List<IOperator> children) {
     391    private bool IsPossibleParent(IFunction f, List<IFunction> children) {
    397392      int minArity;
    398393      int maxArity;
    399       GetMinMaxArity(op, out minArity, out maxArity);
     394      GetMinMaxArity(f, out minArity, out maxArity);
    400395
    401396      // note: we can't assume that the operators in the children list have different types!
     
    409404
    410405      SubOperatorsConstraintAnalyser analyzer = new SubOperatorsConstraintAnalyser();
    411       analyzer.AllPossibleOperators = children;
    412 
    413       List<HashSet<IOperator>> slotSets = new List<HashSet<IOperator>>();
    414 
    415       // we iterate through all slots for sub-operators and calculate the set of
    416       // allowed sub-operators for this slot.
     406      analyzer.AllPossibleOperators = children.Cast<IOperator>().ToArray<IOperator>();
     407
     408      List<HashSet<IFunction>> slotSets = new List<HashSet<IFunction>>();
     409
     410      // we iterate through all slots for sub-trees and calculate the set of
     411      // allowed functions for this slot.
    417412      // we only count those slots that can hold at least one of the children that we should combine
    418413      for (int slot = 0; slot < nSlots; slot++) {
    419         HashSet<IOperator> operatorSet = new HashSet<IOperator>(analyzer.GetAllowedOperators(op, slot));
    420         if (operatorSet.Count() > 0) {
    421           slotSets.Add(operatorSet);
     414        HashSet<IFunction> functionSet = new HashSet<IFunction>(analyzer.GetAllowedOperators(f, slot).Cast<IFunction>());
     415        if (functionSet.Count() > 0) {
     416          slotSets.Add(functionSet);
    422417        }
    423418      }
     
    426421      // hold one of our children.
    427422      // if the number of slots is smaller than the number of children we can be sure that
    428       // we can never combine all children as sub-operators of the operator and thus the operator
     423      // we can never combine all children as sub-trees of the function and thus the function
    429424      // can't be a parent.
    430425      if (slotSets.Count() < children.Count()) {
     
    433428
    434429      // finally we sort the sets by size and beginning from the first set select one
    435       // operator for the slot and thus remove it as possible sub-operator from the remaining sets.
    436       // when we can successfully assign all available children to a slot the operator is a valid parent
    437       // when only a subset of all children can be assigned to slots the operator is no valid parent
     430      // function for the slot and thus remove it as possible sub-tree from the remaining sets.
     431      // when we can successfully assign all available children to a slot the function is a valid parent
     432      // when only a subset of all children can be assigned to slots the function is no valid parent
    438433      slotSets.Sort((p, q) => p.Count() - q.Count());
    439434
     
    441436      for (int i = 0; i < slotSets.Count() - 1; i++) {
    442437        if (slotSets[i].Count > 0) {
    443           IOperator selected = slotSets[i].ElementAt(0);
     438          IFunction selected = slotSets[i].ElementAt(0);
    444439          assignments++;
    445440          for (int j = i + 1; j < slotSets.Count(); j++) {
Note: See TracChangeset for help on using the changeset viewer.