private static ISet <ITreeProgram <TOutput> > GetSubOffspring( ITreeProgram <TOutput> subProg1, ITreeProgram <TOutput> subProg2) { var offspring = new HashSet <ITreeProgram <TOutput> > { subProg1, subProg2 }; // check if children differ (different sub-structure) or no children -> nothing to do in this branch if (subProg1.Input == null || subProg2.Input == null || subProg1.Input.Count != subProg2.Input.Count || subProg1.Input.Count == 0) { return(offspring); } // programs have same number of children, iterate recursively to get possible children in each sub-branch var numChildren = subProg1.Input.Count; var subChildren = new List <IEnumerable <ITreeProgram <TOutput> > >(numChildren); for (var i = 0; i < numChildren; i++) { subChildren.Add(GetSubOffspring(subProg1.Input[i], subProg2.Input[i]).ToList()); } // gets all combinations of possible sub-branches var childrenCombinations = subChildren.GetAllCombinations().ToList(); var subOffspring = new HashSet <ITreeProgram <TOutput> >(); // if sub-programs are the same function, we only need one of them if (subProg1.GetType() == subProg2.GetType()) { offspring.Remove(subProg2); } // for each sub-program, creates new sub-programs for each combination foreach (var subProg in offspring) { foreach (var childCombination in childrenCombinations) { subOffspring.Add(subProg.CreateNew(childCombination)); } } return(subOffspring); }