File size: 3,463 Bytes
8948114
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
55
56
"""AksharaLP v3 agreement / grammar-consistency features (identical rules in release/space/js/aksharalp.mjs).
Scored incrementally when word i is appended to a hypothesis; returns (pos, neg) counts:
  1. participle -> auxiliary agreement (gender/number):  रहा था / रही थी / रहे थे ok;  रहा थे / रहे हूँ / रही था violations.
  2. subject pronoun -> auxiliary person/number in the same clause: मैं..हूँ, हम..हैं, तुम..हो, आप..हैं ok; मैं..है, तुम..हूँ violations.
Only uses the words already chosen from per-token candidate lists; it never adds words."""
AUX = {"था": "ms", "थी": "fs", "थे": "mp", "थीं": "fp", "हूँ": "1s", "हूं": "1s", "है": "3s", "हैं": "pl", "हो": "2p"}
PART = {}
for w, g in (("रहा", "ms"), ("रही", "fs"), ("रहे", "mp"), ("चुका", "ms"), ("चुकी", "fs"), ("चुके", "mp"), ("सका", "ms"), ("सकी", "fs"), ("सके", "mp"),
             ("गया", "ms"), ("गई", "fs"), ("गयी", "fs"), ("गए", "mp"), ("गये", "mp"), ("हुआ", "ms"), ("हुई", "fs"), ("हुए", "mp"),
             ("लिया", "ms"), ("ली", "fs"), ("लिए", "mp"), ("लिये", "mp"), ("दिया", "ms"), ("दी", "fs"), ("दिए", "mp"), ("दिये", "mp"),
             ("किया", "ms"), ("की", "fs"), ("किए", "mp"), ("किये", "mp"), ("आया", "ms"), ("आई", "fs"), ("आए", "mp"), ("आये", "mp")):
    PART[w] = g
SUBJ = {"मैं": "1s", "मै": "1s", "हम": "pl", "तुम": "2p", "आप": "hon", "तू": "2s"}
BOUND = {"कि", "और", "पर", "लेकिन", "तो", "जब", "क्योंकि", "अगर", "या", "मगर", "जो", ",", ".", "?", "!", "।"}
# participle class x auxiliary class -> violation?
BAD_PA = {("ms", "fs"), ("ms", "mp"), ("ms", "fp"), ("ms", "pl"), ("fs", "ms"), ("fs", "mp"), ("mp", "ms"), ("mp", "fs"), ("mp", "1s"), ("mp", "3s")}
# subject x auxiliary -> +1 ok / -1 violation (absent = neutral)
SA = {("1s", "1s"): 1, ("1s", "3s"): -1, ("1s", "pl"): -1, ("1s", "2p"): -1,
      ("pl", "pl"): 1, ("pl", "1s"): -1, ("pl", "3s"): -1,
      ("2p", "2p"): 1, ("2p", "1s"): -1, ("2p", "3s"): -1,
      ("hon", "pl"): 1, ("hon", "1s"): -1, ("hon", "3s"): -1,
      ("2s", "3s"): 1, ("2s", "1s"): -1}


def _part_class(w):
    g = PART.get(w)
    if g: return g
    if len(w) > 2 and w.endswith("ता"): return "ms"
    if len(w) > 2 and w.endswith("ती"): return "fs"
    if len(w) > 2 and w.endswith("ते"): return "mp"
    return None


def agree_feats(words, i):
    """contribution of words[i] given words[:i]; i=None -> 0 (no end-of-sentence term)."""
    if i is None or i <= 0: return 0, 0
    w = words[i]; a = AUX.get(w)
    if a is None: return 0, 0
    pos = neg = 0
    pc = _part_class(words[i - 1])
    if pc is not None:
        if (pc, a) in BAD_PA: neg += 1
        else: pos += 1
    for j in range(i - 1, max(-1, i - 9), -1):          # nearest subject pronoun in the clause
        u = words[j]
        if u in BOUND: break
        s = SUBJ.get(u)
        if s:
            v = SA.get((s, a), 0); pos += v > 0; neg += v < 0
            break
    return pos, neg


def agree_score(words, i, wp=1.0, wn=1.0):
    p, n = agree_feats(words, i); return wp * p - wn * n