core/tests/test_graph_constraint.py

123 lines
4.9 KiB
Python

"""Tests for generate/graph_constraint.py — PropositionGraph as AdmissibilityRegion.
ADR-0046.
"""
from __future__ import annotations
import pytest
import numpy as np
from generate.graph_planner import GraphEdge, GraphNode, PropositionGraph, Relation
from generate.graph_constraint import build_graph_constraint
from generate.admissibility import AdmissibilityRegion
from generate.intent import IntentTag
@pytest.fixture()
def vocab():
from packs import load_pack
_manifest, manifold = load_pack("en_core_cognition_v1")
return manifold
def _node(node_id, subject, obj):
return GraphNode(
node_id=node_id,
subject=subject,
predicate="addresses",
obj=obj,
source_intent=IntentTag.DEFINITION,
)
class TestBuildGraphConstraint:
def test_returns_admissibility_region(self, vocab):
graph = PropositionGraph().add_node(_node("p0", "light", "truth"))
region = build_graph_constraint(graph, vocab)
assert isinstance(region, AdmissibilityRegion)
def test_non_trivial_constraint(self, vocab):
"""allowed_indices must be a strict subset of the full vocabulary."""
graph = PropositionGraph().add_node(_node("p0", "light", "truth"))
region = build_graph_constraint(graph, vocab, top_k=8)
assert region.allowed_indices is not None
assert len(region.allowed_indices) < len(vocab)
def test_allowed_indices_positive_cga_inner(self, vocab):
"""Every allowed index must score positive cga_inner against at least one anchor."""
from algebra.cga import cga_inner
graph = PropositionGraph().add_node(_node("p0", "light", "truth"))
region = build_graph_constraint(graph, vocab, top_k=8)
assert region.allowed_indices is not None
light_v = np.asarray(vocab.get_versor("light"), dtype=np.float32)
truth_v = np.asarray(vocab.get_versor("truth"), dtype=np.float32)
anchors = [light_v, truth_v]
for idx in region.allowed_indices:
scores = [
float(cga_inner(np.asarray(vocab.get_versor_at(int(idx)), dtype=np.float32), a))
for a in anchors
]
assert max(scores) > 0.0, f"Index {idx} has non-positive CGA score against all anchors"
def test_empty_graph_returns_unconstrained(self, vocab):
"""An empty graph degrades gracefully to an unconstrained region."""
region = build_graph_constraint(PropositionGraph(), vocab)
assert region.allowed_indices is None
assert "unconstrained" in region.label
def test_two_node_graph_unions_neighbourhoods(self, vocab):
"""A two-node graph produces a larger allowed set than a one-node graph."""
graph_one = PropositionGraph().add_node(_node("p0", "light", "truth"))
graph_two = (
PropositionGraph()
.add_node(_node("p0", "light", "truth"))
.add_node(_node("p1", "word", "life"))
)
region_one = build_graph_constraint(graph_one, vocab, top_k=4)
region_two = build_graph_constraint(graph_two, vocab, top_k=4)
count_one = len(region_one.allowed_indices) if region_one.allowed_indices is not None else len(vocab)
count_two = len(region_two.allowed_indices) if region_two.allowed_indices is not None else len(vocab)
assert count_two >= count_one
def test_label_encodes_root_node_ids(self, vocab):
"""The region label must encode the graph's root node IDs."""
graph = PropositionGraph().add_node(_node("p0", "light", "truth"))
region = build_graph_constraint(graph, vocab)
assert "p0" in region.label
def test_round_trip_with_generate(self, vocab):
"""The region produced by build_graph_constraint can be fed to generate() without raising."""
from field.state import FieldState
from generate.stream import generate
from persona.motor import PersonaMotor
graph = PropositionGraph().add_node(_node("p0", "light", "truth"))
region = build_graph_constraint(graph, vocab, top_k=8)
F0 = np.asarray(vocab.get_versor("light"), dtype=np.float64)
state = FieldState(F=F0, node=vocab.index_of("light"), step=0)
persona = PersonaMotor.identity()
result = generate(
state,
vocab,
persona,
max_tokens=4,
region=region,
)
assert result.tokens is not None
def test_oov_nodes_degrade_gracefully(self, vocab):
"""A graph whose nodes are all OOV returns an unconstrained region."""
graph = PropositionGraph().add_node(
GraphNode(
node_id="p0",
subject="xyzzy_not_a_word",
predicate="quux",
obj="zork_also_not_a_word",
source_intent=IntentTag.UNKNOWN,
)
)
region = build_graph_constraint(graph, vocab)
assert region.allowed_indices is None