'Merge the states in a given stash.
:param stash:       The stash (default: \'active\')
:param merge_func:  If provided, instead of using state.merge, call this function with the states as the argument.
Should return the merged state.
:returns:           The result SimulationManager.
:rtype:             SimulationManager'

def merge(self, merge_func=None, stash=None):

    stash = ('active' if (stash is None) else stash)
    self.prune(from_stash=stash)
    to_merge = self.stashes[stash]
    not_to_merge = []
    merge_groups = []
    while (len(to_merge) > 0):
        (g, to_merge) = self._filter_states((lambda s: (s.addr == to_merge[0].addr)), to_merge)
        if (len(g) <= 1):
            not_to_merge.extend(g)
        else:
            merge_groups.append(g)
    for g in merge_groups:
        try:
            m = (self._merge_states(g) if (merge_func is None) else merge_func(*g))
            not_to_merge.append(m)
        except SimMergeError:
            l.warning('SimMergeError    while    merging    %d    states', len(g), exc_info=True)
            not_to_merge.extend(g)
    new_stashes = self._copy_stashes()
    new_stashes[stash] = not_to_merge
    return self._successor(new_stashes)
