Automata

Tensor trains can represent compactly deterministic finite automata and weighted finite automata that read a fixed number of symbols.

[1]:
import torch
import tntorch as tn

For instance, weight_mask produces an automaton that accepts a string iff it has a certain amount of 1’s:

[2]:
m = tn.weight_mask(N=4, weight=2)
m
[2]:
4D TT tensor:

  2   2   2   2
  |   |   |   |
 (0) (1) (2) (3)
 / \ / \ / \ / \
1   2   3   2   1

All accepted input strings can be retrieved alphabetically via accepted_inputs():

[3]:
tn.accepted_inputs(m)
[3]:
tensor([[0, 0, 1, 1],
        [0, 1, 0, 1],
        [0, 1, 1, 0],
        [1, 0, 0, 1],
        [1, 0, 1, 0],
        [1, 1, 0, 0]])

On the other hand, weight() produces an automaton that is a little different. Instead of accepting or rejecting strings, it just counts how many 1’s the string has:

[4]:
m = tn.weight(N=4)
print(m[0, 0, 0, 0])
print(m[0, 1, 0, 0])
print(m[1, 0, 1, 1])
tensor(0.)
tensor(1.)
tensor(3.)

Applications

TT automata come in handy to group and sum tensor entries, which is important to obtain advanced metrics for sensitivity analysis. See also the tutorial on Boolean logic with *tntorch*.