code: def allowed_transitions(
      tag_vocab: Union[Vocabulary, dict],
      encoding_type: str = None,
      include_start_end: bool = False,
  ) -> List[Tuple[int, int]]:
      r"""
      给定一个 ``id`` 到 ``label`` 的映射表，返回所有可以跳转的 ``(from_tag_id, to_tag_id)`` 列表。
  
      :param tag_vocab: 支持类型为 tag 或 tag-label 。只有 tag 的,比如 ``"B"`` 、 ``"M"``，也可以是 ``"B-NN"`` 、 ``"M-NN"``，
          tag 和 label之间一定要用 ``"-"`` 隔开。如果传入 :class:`dict` ，格式需要形如 ``{0:"O", 1:"B-tag1"}`` ，即 **index 在前，tag 在后** 。
      :param encoding_type: 支持 ``["bio", "bmes", "bmeso", "bioes", None]``。默认为 ``None``，通过 ``tag_vocab`` 自动推断
      :param include_start_end: 是否包含开始与结尾的转换。比如在 ``bio`` 中， ``b/o`` 可以在开头，但是 ``i`` 不能在开头；
  
              - 为 ``True`` -- 返回的结果中会包含 ``(start_idx, b_idx), (start_idx, o_idx)`` ，但是不包含 ``(start_idx, i_idx)`` ；
                其中 ``start_idx=len(id2label)``，``end_idx=len(id2label)+1`` ；
              - 为 ``False`` , 返回的结果中不含与开始结尾相关的内容；
      :return: 一系列元组构成的列表，内部的 :class:`Tuple` 是可以进行跳转的 ``(from_tag_id, to_tag_id)``。
      """
      if encoding_type is None:
          encoding_type = _get_encoding_type_from_tag_vocab(tag_vocab)
      else:
          encoding_type = encoding_type.lower()
          _check_tag_vocab_and_encoding_type(tag_vocab, encoding_type)
  
      pad_token = "<pad>"
      unk_token = "<unk>"
  
      if isinstance(tag_vocab, Vocabulary):
          id_label_lst = list(tag_vocab.idx2word.items())
          pad_token = tag_vocab.padding
          unk_token = tag_vocab.unknown
      else:
          id_label_lst = list(tag_vocab.items())
  
      num_tags = len(tag_vocab)
      start_idx = num_tags
      end_idx = num_tags + 1
      allowed_trans = []
      if include_start_end:
          id_label_lst += [(start_idx, "start"), (end_idx, "end")]
  
      def split_tag_label(from_label):
          from_label = from_label.lower()
          if from_label in ["start", "end"]:
              from_tag = from_label
              from_label = ""
          else:
              from_tag = from_label[:1]
              from_label = from_label[2:]
          return from_tag, from_label
  
      for from_id, from_label in id_label_lst:
          if from_label in [pad_token, unk_token]:
              continue
          from_tag, from_label = split_tag_label(from_label)
          for to_id, to_label in id_label_lst:
              if to_label in [pad_token, unk_token]:
                  continue
              to_tag, to_label = split_tag_label(to_label)
              if _is_transition_allowed(
                  encoding_type, from_tag, from_label, to_tag, to_label
              ):
                  allowed_trans.append((from_id, to_id))
      return allowed_trans
  
file_path: fastNLP/fastNLP/modules/torch/decoder/crf.py
imports: from typing import Union, List, Tuple
  import torch
  from torch import nn
  from ....core.metrics.span_f1_pre_rec_metric import _get_encoding_type_from_tag_vocab, _check_tag_vocab_and_encoding_type
  from ....core.vocabulary import Vocabulary
label_desc: Use image node_id 1 for calling a global function with example usage: allowed_transitions(tag_vocab, encoding_type, include_start_end) and returns: allowed_trans, from_tag,  from_label