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)