Exemple #1
0
def remove_epsilon(fsa: Fsa) -> Fsa:
    '''Remove epsilons (symbol zero) in the input Fsa.

    Caution:
      It only works on for CPU and doesn't support autograd.

    Args:
      fsa:
        The input FSA. It can be either a single FSA or an FsaVec.
        Must be top-sorted.
    Returns:
        The result Fsa, it's equivalent to the input `fsa` under
        tropical semiring but will be epsilon-free.
        It will be the same as the input `fsa` if the input
        `fsa` is epsilon-free. Otherwise, a new epsilon-free fsa
        is returned and the input `fsa` is NOT modified.
    '''
    assert fsa.is_cpu()
    assert fsa.requires_grad is False
    if fsa.properties & fsa_properties.EPSILON_FREE != 0:
        return fsa

    ragged_arc, arc_map = _k2.remove_epsilon(fsa.arcs)
    aux_labels = None
    if hasattr(fsa, 'aux_labels'):
        aux_labels = index_attr(fsa.aux_labels, arc_map)
    out_fsa = Fsa(ragged_arc, aux_labels)

    for name, value in fsa.named_non_tensor_attr():
        setattr(out_fsa, name, value)

    return out_fsa
Exemple #2
0
def remove_epsilon(fsa: Fsa) -> Fsa:
    '''Remove epsilons (symbol zero) in the input Fsa.

    Args:
      fsa:
        The input FSA. It can be either a single FSA or an FsaVec.
        Works either for CPU or GPU, but the algorithm is different.
        We can only use the CPU algorithm if the input is top-sorted,
        and the GPU algorithm, while it works for CPU, may not be
        very fast.
        `fsa` must be free of epsilon loops that have score
        greater than 0.
    Returns:
      The resulting Fsa, it's equivalent to the input `fsa` under
      tropical semiring but will be epsilon-free.
      It will be the same as the input `fsa` if the input
      `fsa` is epsilon-free. Otherwise, a new epsilon-free fsa
      is returned and the input `fsa` is NOT modified.
    '''
    if fsa.properties & fsa_properties.EPSILON_FREE != 0:
        return fsa

    ragged_arc, arc_map = _k2.remove_epsilon(fsa.arcs, fsa.properties)

    out_fsa = k2.utils.fsa_from_unary_function_ragged(fsa, ragged_arc, arc_map)
    return out_fsa
Exemple #3
0
def remove_epsilon(fsa: Fsa) -> Fsa:
    '''Remove epsilons (symbol zero) in the input Fsa.

    Args:
      fsa:
        The input FSA. It can be either a single FSA or an FsaVec.
        Works either for CPU or GPU, but the algorithm is different.
        We can only use the CPU algorithm if the input is top-sorted,
        and the GPU algorithm, while it works for CPU, may not be
        very fast.

        `fsa` must be free of epsilon loops that have score
        greater than 0.

    Returns:
      The resulting Fsa is equivalent to the input `fsa` under the
      tropical semiring but will be epsilon-free.  Any linear tensor
      attributes, such as 'aux_labels', will have been turned into
      ragged labels after removing fillers (i.e. labels whose
      value equals fsa.XXX_filler if the attribute name is XXX),
      counting -1's on final-arcs as fillers even if the filler
      value for that attribute is not -1.
    '''
    ragged_arc, arc_map = _k2.remove_epsilon(fsa.arcs, fsa.properties)

    out_fsa = k2.utils.fsa_from_unary_function_ragged(fsa, ragged_arc, arc_map,
                                                      remove_filler=True)

    if hasattr(out_fsa, 'aux_labels') and \
            isinstance(out_fsa.aux_labels, k2.RaggedInt):
        out_fsa.aux_labels = k2.ragged.remove_values_eq(out_fsa.aux_labels, 0)

    return out_fsa
Exemple #4
0
def remove_epsilon(fsa: Fsa) -> Fsa:
    '''Remove epsilons (symbol zero) in the input Fsa.

    Caution:
      It only works on for CPU and doesn't support autograd.

    Args:
      fsa:
        The input FSA. It can be either a single FSA or an FsaVec.
        Must be top-sorted.
    Returns:
        The result Fsa, it's equivalent to the input ``fsa`` under
        tropical semiring but will be epsilon-free.
        It will be the same as the input ``fsa`` if the input
        ``fsa`` is epsilon-free. Otherwise, a new epsilon-free fsa
        is returned and the input ``fsa`` is NOT modified.
    '''
    properties = getattr(fsa, 'properties', None)
    if properties is not None and properties & fsa_properties.EPSILON_FREE != 0:
        return fsa

    ragged_arc = _k2.remove_epsilon(fsa.arcs)
    out_fsa = Fsa(ragged_arc)
    for name, value in fsa.named_non_tensor_attr():
        setattr(out_fsa, name, value)
    return out_fsa
Exemple #5
0
    def test_without_empty_list(self):
        for device in self.devices:
            s = '''
                0 1 0 0
                0 1 1 0
                1 2 -1 0
                2
            '''
            scores = torch.tensor([1, 2, 3],
                                  dtype=torch.float32,
                                  device=device,
                                  requires_grad=True)
            scores_copy = scores.detach().clone().requires_grad_(True)
            src = k2.Fsa.from_str(s).to(device)
            src.scores = scores
            src.attr1 = "hello"
            src.attr2 = "k2"
            float_attr = torch.tensor([0.1, 0.2, 0.3],
                                      dtype=torch.float32,
                                      requires_grad=True,
                                      device=device)

            src.float_attr = float_attr.detach().clone().requires_grad_(True)
            src.int_attr = torch.tensor([1, 2, 3],
                                        dtype=torch.int32,
                                        device=device)
            src.ragged_attr = k2.RaggedInt(
                '[ [10 20] [30 40 50] [60 70] ]').to(device)

            ragged_arc, arc_map = _k2.remove_epsilon(src.arcs, src.properties)
            dest = k2.utils.fsa_from_unary_function_ragged(
                src, ragged_arc, arc_map)
            assert dest.attr1 == src.attr1
            assert dest.attr2 == src.attr2

            expected_arc_map = k2.RaggedInt('[ [1] [0 2] [2] ]')
            self.assertEqual(str(arc_map), str(expected_arc_map))

            expected_int_attr = k2.RaggedInt('[ [2] [1 3] [3] ]')
            self.assertEqual(str(dest.int_attr), str(expected_int_attr))

            expected_ragged_attr = k2.RaggedInt(
                '[ [30 40 50] [10 20 60 70] [60 70] ]')
            self.assertEqual(str(dest.ragged_attr),
                             str(expected_ragged_attr))

            expected_float_attr = torch.empty_like(dest.float_attr)
            expected_float_attr[0] = float_attr[1]
            expected_float_attr[1] = float_attr[0] + float_attr[2]
            expected_float_attr[2] = float_attr[2]

            assert torch.all(torch.eq(dest.float_attr,
                                      expected_float_attr))

            expected_scores = torch.empty_like(dest.scores)
            expected_scores[0] = scores_copy[1]
            expected_scores[1] = scores_copy[0] + scores_copy[2]
            expected_scores[2] = scores_copy[2]

            assert torch.all(torch.eq(dest.scores, expected_scores))

            scale = torch.tensor([10, 20, 30]).to(float_attr)

            (dest.float_attr * scale).sum().backward()
            (expected_float_attr * scale).sum().backward()
            assert torch.all(torch.eq(src.float_attr.grad, float_attr.grad))

            (dest.scores * scale).sum().backward()
            (expected_scores * scale).sum().backward()
            assert torch.all(torch.eq(scores.grad, scores_copy.grad))