docs: def add_stroke(self, new_stroke):
          """
          Update the beam so that it considers `new_stroke`.
  
          When a `new_stroke` comes, it can either belong to a symbol for which
          at least one other stroke was already made or belong to a symbol for
          which `new_stroke` is the first stroke.
  
          The number of hypotheses after q strokes without pruning is
  
              f: N_0 -> N_0
              f(0) = 1
              f(1) = m
              f(q) = f(q-1)*(m+n)
  
          The number of time the single symbol classifier has to be called, when
          already q hypotheses exist:
  
              f_s: N_0 -> N_0
              f_s(q) = q*n + 1 (upper bound)
  
          Parameters
          ----------
          new_stroke : list of dicts
              A list of dicts [{'x': 12, 'y': 34, 'time': 56}, ...] which
              represent a point.
          """
          global single_clf
          if len(self.hypotheses) == 0:  # Don't put this in the constructor!
              self.hypotheses = [{'segmentation': [],
                                  'symbols': [],
                                  'geometry': {},
                                  'probability': Decimal(1)
                                  }]
          stroke_nr = len(self.history['data'])
          new_history = deepcopy(self.history)
          new_history['data'].append(new_stroke)
          new_beam = Beam()
          new_beam.history = new_history
  
          evaluated_segmentations = []
  
          # Get new guesses by assuming new_stroke belongs to an already begun
          # symbol
          had_multisymbol = False
          for hyp in self.hypotheses:
              # Add stroke to last n symbols (seperately)
              for i in range(min(self.n, len(hyp['segmentation']))):
                  # Build stroke data
                  new_strokes = {'data': [], 'id': -1}
                  for stroke_index in hyp['segmentation'][-(i+1)]:
                      curr_stroke = self.history['data'][stroke_index]
                      new_strokes['data'].append(curr_stroke)
                  new_strokes['data'].append(new_stroke)
  
                  new_seg = deepcopy(hyp['segmentation'])
                  new_seg[-(i+1)].append(stroke_nr)
  
                  if new_seg in evaluated_segmentations:
                      continue
                  else:
                      evaluated_segmentations.append(new_seg)
  
                  # Predict this new collection of strokes
                  guesses = single_clf.predict(new_strokes)[:self.m]
                  for guess in guesses:
                      if guess['semantics'].split(";")[1] == "::MULTISYMBOL::":
                          # This was a wrong segmentation. Ignore it.
                          had_multisymbol = True
                          continue
                      sym = {'symbol': guess['semantics'],
                             'probability': guess['probability']}
                      new_sym = deepcopy(hyp['symbols'])
                      new_sym[-(i+1)] = sym
                      b = {'segmentation': new_seg,
                           'symbols': new_sym,
                           'geometry': deepcopy(hyp['geometry']),
                           'probability': None
                           }
                      new_beam.hypotheses.append(b)
  
          if len(self.hypotheses) <= 1 or had_multisymbol:
              self._add_hypotheses_assuming_new_stroke(new_stroke,
                                                       stroke_nr,
                                                       new_beam)
  
          for hyp in new_beam.hypotheses:
              hyp['probability'] = _calc_hypothesis_probability(hyp)
  
          # Get probability again
  
          # Get geometry of each beam entry
          # TODO
  
          # Update probabilities
          # TODO
  
          # Normalize to sum=1
          self.hypotheses = new_beam.hypotheses
          self.history = new_beam.history
          self._prune()
          new_probs = softmax([h['probability']
                               for h in self.hypotheses])
          for hyp, prob in zip(self.hypotheses, new_probs):
              hyp['probability'] = prob