'Starting from the alignment in ``alignment_info``, look at
neighboring alignments iteratively for the best one
There is no guarantee that the best alignment in the alignment
space will be found, because the algorithm might be stuck in a
local maximum.
:param j_pegged: If specified, the search will be constrained to
alignments where ``j_pegged`` remains unchanged
:type j_pegged: int
:return: The best alignment found from hill climbing
:rtype: AlignmentInfo'

def hillclimb(self, alignment_info, j_pegged=None):

    alignment = alignment_info
    max_probability = self.prob_t_a_given_s(alignment)
    while True:
        old_alignment = alignment
        for neighbor_alignment in self.neighboring(alignment, j_pegged):
            neighbor_probability = self.prob_t_a_given_s(neighbor_alignment)
            if (neighbor_probability > max_probability):
                alignment = neighbor_alignment
                max_probability = neighbor_probability
        if (alignment == old_alignment):
            break
    alignment.score = max_probability
    return alignment
