Merges a list of states.

        :param states:      the states to merge
        :returns SimState:  the resulting state

def _merge_states(self, states):
        """
        Merges a list of states.

        :param states:      the states to merge
        :returns SimState:  the resulting state
        """

        if self._hierarchy:
            optimal, common_history, others = self._hierarchy.most_mergeable(states)
        else:
            optimal, common_history, others = states, None, []

        if len(optimal) >= 2:
            # We found optimal states (states that share a common ancestor) to merge.
            # Compute constraints for each state starting from the common ancestor,
            # and use them as merge conditions.
            constraints = [s.history.constraints_since(common_history) for s in optimal]

            o = optimal[0]
            m, _, _ = o.merge(*optimal[1:],
                              merge_conditions=constraints,
                              common_ancestor=common_history.strongref_state
                              )

        else:
            l.warning(
                "Cannot find states with common history line to merge. Fall back to the naive merging strategy "
                "and merge all states."
                )
            s = states[0]
            m, _, _ = s.merge(*states[1:])

            others = []

        if self._hierarchy:
            self._hierarchy.add_state(m)

        if len(others):
            others.append(m)
            return self._merge_states(others)
        else:
            return m