gclm-constrained-decoding / tests /test_fsm_builder.py
uuugi's picture
Initial release of GCLM: Code, Paper, Benchmarks and Examples
44810a8 verified
Raw
History Blame Contribute Delete
2.28 kB
import pytest
import torch
from core.fsm_builder import ReachabilityFSM
def test_fsm_basic_reachability():
# Linear graph: 0 -> 1 -> 2 (Goal)
vocab_size = 10
fsm = ReachabilityFSM(num_states=3, vocab_size=vocab_size)
fsm.add_transition(0, token_id=1, to_state=1)
fsm.add_transition(1, token_id=2, to_state=2)
fsm.set_goal_states([2])
# Max steps = 2
reach = fsm.build_reachability(max_steps=2, allow_early_finish=True)
# t = 0: only state 2 is True
assert reach[0, 2].item() is True
assert reach[0, 1].item() is False
assert reach[0, 0].item() is False
# t = 1: state 1 and 2 are True
assert reach[1, 2].item() is True
assert reach[1, 1].item() is True
assert reach[1, 0].item() is False
# t = 2: state 0, 1, 2 are all True
assert reach[2, 0].item() is True
assert reach[2, 1].item() is True
assert reach[2, 2].item() is True
def test_fsm_deadend_reachability():
# Branching graph:
# 0 -> 1 -> 2 (Goal) via token 1, 2 (needs 2 steps)
# 0 -> 3 -> 4 (Dead-end) via token 3, 4 (sink)
vocab_size = 10
fsm = ReachabilityFSM(num_states=5, vocab_size=vocab_size)
fsm.add_transition(0, token_id=1, to_state=1)
fsm.add_transition(1, token_id=2, to_state=2)
fsm.add_transition(0, token_id=3, to_state=3)
fsm.add_transition(3, token_id=4, to_state=4)
fsm.set_goal_states([2])
reach = fsm.build_reachability(max_steps=5, allow_early_finish=True)
# States 3 and 4 should NEVER be reachable to goal
for t in range(6):
assert reach[t, 3].item() is False
assert reach[t, 4].item() is False
# State 0 is reachable only when t >= 2
assert reach[0, 0].item() is False
assert reach[1, 0].item() is False
assert reach[2, 0].item() is True
assert reach[3, 0].item() is True
def test_fsm_multi_goal():
# 0 -> 1 (Goal A), 0 -> 2 (Goal B)
vocab_size = 5
fsm = ReachabilityFSM(num_states=3, vocab_size=vocab_size)
fsm.add_transition(0, 1, 1)
fsm.add_transition(0, 2, 2)
fsm.set_goal_states([1, 2])
reach = fsm.build_reachability(max_steps=1)
assert reach[0, 1].item() is True
assert reach[0, 2].item() is True
assert reach[0, 0].item() is False
assert reach[1, 0].item() is True