Skip to content

Extending torchtsetlin

The models are thin layers over torchtsetlin.functional. To build a new variant, subclass TsetlinMachineBase and implement the output layer and feedback policy:

class MyTM(tt.TsetlinMachineBase):
    def __init__(self, n_features, n_clauses, T, **kw):
        self.T = T
        super().__init__(n_features, n_clauses, **kw)

    def _votes(self, clause_out, clamp=True):            # (B, C) bool -> (B, n_outputs)
        ...

    def _coerce_targets(self, y, n, device):             # validate / convert targets
        ...

    def _select_feedback(self, votes, y, clause_out):    # -> (type_i, type_ii, aux) masks (B, C)
        ...

Optional hooks: _accumulate_weights(acc, aux, clause_out, sel_fire_i, sel_fire_ii) and _commit_weights(acc) for clause weights; _encode, _evaluate, _feedback_counts for a different input structure (this is how the convolutional mix-in works); rules() for interpretation.

The generic update() handles input coercion, lazy initialisation, chunking, dropout masks, counting feedback events and applying them with functional.apply_feedback.

Using the functional API directly

from torchtsetlin import functional as F
lit = F.to_literals(x)                                   # (B, 2F)
include = (state >= N).float()
c = F.clause_outputs(lit, include, empty_value=True)     # (B, C)
v = F.vote_sums(c, weights, T)
n_true, n_false, n_ib = F.type_i_counts(lit, sel_fire_i, sel_nofire_i)
n2 = F.type_ii_counts(lit, sel_fire_ii)
F.apply_feedback(state, n_true, n_false, n_ib, n2, n_states=N, s=s)

Everything is plain tensor code, so torch.compile, custom CUDA kernels or alternative sampling schemes can be dropped in.