class_docstr: Translation model that keeps track of vacant positions in the target
  sentence to decide where to place translated words
  
  >>> bitext = []
  >>> bitext.append(AlignedSent(['klein', 'ist', 'das', 'haus'], ['the', 'house', 'is', 'small']))
  >>> bitext.append(AlignedSent(['das', 'haus', 'war', 'ja', 'groß'], ['the', 'house', 'was', 'big']))
  >>> bitext.append(AlignedSent(['das', 'buch', 'ist', 'ja', 'klein'], ['the', 'book', 'is', 'small']))
  >>> bitext.append(AlignedSent(['ein', 'haus', 'ist', 'klein'], ['a', 'house', 'is', 'small']))
  >>> bitext.append(AlignedSent(['das', 'haus'], ['the', 'house']))
  >>> bitext.append(AlignedSent(['das', 'buch'], ['the', 'book']))
  >>> bitext.append(AlignedSent(['ein', 'buch'], ['a', 'book']))
  >>> bitext.append(AlignedSent(['ich', 'fasse', 'das', 'buch', 'zusammen'], ['i', 'summarize', 'the', 'book']))
  >>> bitext.append(AlignedSent(['fasse', 'zusammen'], ['summarize']))
  >>> src_classes = {'the': 0, 'a': 0, 'small': 1, 'big': 1, 'house': 2, 'book': 2, 'is': 3, 'was': 3, 'i': 4, 'summarize': 5 }
  >>> trg_classes = {'das': 0, 'ein': 0, 'haus': 1, 'buch': 1, 'klein': 2, 'groß': 2, 'ist': 3, 'war': 3, 'ja': 4, 'ich': 5, 'fasse': 6, 'zusammen': 6 }
  
  >>> ibm5 = IBMModel5(bitext, 5, src_classes, trg_classes)
  
  >>> print(round(ibm5.head_vacancy_table[1][1][1], 3))
  1.0
  >>> print(round(ibm5.head_vacancy_table[2][1][1], 3))
  0.0
  >>> print(round(ibm5.non_head_vacancy_table[3][3][6], 3))
  1.0
  
  >>> print(round(ibm5.fertility_table[2]['summarize'], 3))
  1.0
  >>> print(round(ibm5.fertility_table[1]['book'], 3))
  1.0
  
  >>> print(round(ibm5.p1, 3))
  0.033
  
  >>> test_sentence = bitext[2]
  >>> test_sentence.words
  ['das', 'buch', 'ist', 'ja', 'klein']
  >>> test_sentence.mots
  ['the', 'book', 'is', 'small']
  >>> test_sentence.alignment
  Alignment([(0, 0), (1, 1), (2, 2), (3, None), (4, 3)])
docstr: Sample the most probable alignments from the entire alignment
  space according to Model 4
  
  Note that Model 4 scoring is used instead of Model 5 because the
  latter is too expensive to compute.
  
  First, determine the best alignment according to IBM Model 2.
  With this initial alignment, use hill climbing to determine the
  best alignment according to a IBM Model 4. Add this
  alignment and its neighbors to the sample set. Repeat this
  process with other initial alignments obtained by pegging an
  alignment point. Finally, prune alignments that have
  substantially lower Model 4 scores than the best alignment.
  
  :param sentence_pair: Source and target language sentence pair
      to generate a sample of alignments from
  :type sentence_pair: AlignedSent
  
  :return: A set of best alignments represented by their ``AlignmentInfo``
      and the best alignment of the set for convenience
  :rtype: set(AlignmentInfo), AlignmentInfo
docstr_tok: ["Sample","the","most","probable","alignments","from","the","entire","alignment","space","according","to","Model","4","Note","that","Model","4","scoring","is","used","instead","of","Model","5","because","the","latter","is","too","expensive","to","compute",".","First",",","determine","the","best","alignment","according","to","IBM","Model","2",".","With","this","initial","alignment",",","use","hill","climbing","to","determine","the","best","alignment","according","to","a","IBM","Model","4",".","Add","this","alignment","and","its","neighbors","to","the","sample","set",".","Repeat","this","process","with","other","initial","alignments","obtained","by","pegging","an","alignment","point",".","Finally",",","prune","alignments","that","have","substantially","lower","Model","4","scores","than","the","best","alignment",".",":","param","sentence_pair",":","Source","and","target","language","sentence","pair","to","generate","a","sample","of","alignments","from",":","type","sentence_pair",":","AlignedSent",":","return",":","A","set","of","best","alignments","represented","by","their","``","AlignmentInfo","``","and","the","best","alignment","of","the","set","for","convenience",":","rtype",":","set","(","AlignmentInfo",")",",","AlignmentInfo"]
code: def sample(self, sentence_pair):
      """
      Sample the most probable alignments from the entire alignment
      space according to Model 4
  
      Note that Model 4 scoring is used instead of Model 5 because the
      latter is too expensive to compute.
  
      First, determine the best alignment according to IBM Model 2.
      With this initial alignment, use hill climbing to determine the
      best alignment according to a IBM Model 4. Add this
      alignment and its neighbors to the sample set. Repeat this
      process with other initial alignments obtained by pegging an
      alignment point. Finally, prune alignments that have
      substantially lower Model 4 scores than the best alignment.
  
      :param sentence_pair: Source and target language sentence pair
          to generate a sample of alignments from
      :type sentence_pair: AlignedSent
  
      :return: A set of best alignments represented by their ``AlignmentInfo``
          and the best alignment of the set for convenience
      :rtype: set(AlignmentInfo), AlignmentInfo
      """
      sampled_alignments, best_alignment = super().sample(sentence_pair)
      return self.prune(sampled_alignments), best_alignment
  
imports: import warnings
  from collections import defaultdict
  from math import factorial
  from nltk.translate import AlignedSent, Alignment, IBMModel, IBMModel4
  from nltk.translate.ibm_model import Counts, longest_target_sentence_length
label_desc: Use image node_id 5 for calling the IBMModel5 obj's underlying member method code with example usage: obj.sample(sentence_pair) and returns: self,  best_alignment