File size: 1,757 Bytes
3e363e2 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 | """Typed relation-sequence composition utilities used by path reasoning."""
from __future__ import annotations
from collections.abc import Mapping, Sequence
import torch
from torch import Tensor
def compose_relation_sequence(
relation_sequence: Sequence[str],
relation_states: Mapping[str, Tensor],
query_state: Tensor,
) -> Tensor:
"""Compose relation states with position-aware gated products.
The operation is deliberately inductive: relation IDs select supplied
graph-derived states, not a closed-world entity table. PAT remains the
learned path encoder; this utility gives the reasoning core an explicit
compositional state for supervision and diagnostics.
"""
if query_state.ndim == 2:
query_state = query_state[0]
if not relation_sequence:
return torch.zeros_like(query_state)
states = [
relation_states.get(relation, torch.zeros_like(query_state))
for relation in relation_sequence
]
result = states[0]
for index, state in enumerate(states[1:], start=1):
gate = 1.0 / float(index + 1)
result = torch.tanh(
result * (1.0 - gate) + state * gate + query_state * (gate / 2.0)
)
return result
def relation_sequence_score(
relation_sequence: Sequence[str],
relation_states: Mapping[str, Tensor],
query_state: Tensor,
) -> Tensor:
"""Return query compatibility for a composed relation sequence."""
composed = compose_relation_sequence(
relation_sequence, relation_states, query_state
)
if query_state.ndim == 2:
query_state = query_state[0]
return torch.nn.functional.cosine_similarity(
composed.unsqueeze(0), query_state.unsqueeze(0), dim=-1
).squeeze(0)
|