"""Semantic utilities for ALAN items."""
from __future__ import annotations
from dataclasses import dataclass
from typing import List
@dataclass(frozen=True)
class NPMeaning:
noun: str
feminine: bool
plural: bool
adjectives: tuple[str, ...]
role: str # AGENT/RECIPIENT/THEME
use_irregular: bool
@dataclass(frozen=True)
class SentenceMeaning:
verb: str
tense: str # PRES/PAST
use_irregular_verb: bool
subj: NPMeaning
obj1: NPMeaning
obj2: NPMeaning | None = None
def to_meaning(sf) -> SentenceMeaning:
"""Convert SentenceFeatures to SentenceMeaning."""
def np_to_meaning(np):
return NPMeaning(
noun=np.noun_id,
feminine=np.feminine,
plural=np.plural,
adjectives=tuple(np.adjectives),
role=np.role,
use_irregular=np.use_irregular,
)
return SentenceMeaning(
verb=sf.verb_id,
tense=sf.tense,
use_irregular_verb=sf.use_irregular_verb,
subj=np_to_meaning(sf.subject),
obj1=np_to_meaning(sf.obj1),
obj2=np_to_meaning(sf.obj2) if sf.obj2 else None,
)
def meanings_equal(a: SentenceMeaning, b: SentenceMeaning) -> bool:
return a == b
def semantic_distance(a: SentenceMeaning, b: SentenceMeaning) -> int:
"""Count feature differences between two meanings."""
dist = 0
if a.verb != b.verb or a.tense != b.tense or a.use_irregular_verb != b.use_irregular_verb:
dist += 1
for np_a, np_b in [(a.subj, b.subj), (a.obj1, b.obj1)]:
if np_a != np_b:
dist += 1
if a.obj2 or b.obj2:
if (a.obj2 or NPMeaning("", False, False, tuple(), "", False)) != (
b.obj2 or NPMeaning("", False, False, tuple(), "", False)
):
dist += 1
return dist