module graphemes /* Experiments with distinctive-feature analysis for graphemes. Given some set of graphemes (e.g. the twenty-six characters of the lower-case English alphabet), and some set of binary (or n-ary) distinctive features (e.g. ASCENDER, DESCENDER, BOWL, OPEN, CROSS, ...), together with information about the values of particular features for particular graphemes (ASCENDER is true for b, d, f, h, k, l, and maybe t; DESCENDER is true for g, j, p, q, at least in the simple grade-school script I'm taking as my guide), we'd like to establish which sets of features suffice to distinguish the graphemes from each other, and also which sufficient sets could be reduced to smaller sets by eliminating features. It's not clear that this is the best way to perform this work, but it seems like an interesting approach. */ /* This module describes the abstractions; the sets of graphemes being analysed and the features being proposed should go in a separate module. */ abstract sig Grapheme {} abstract sig Feature { sic : set Grapheme, non : set Grapheme, unk : set Grapheme }{ no (sic & non) no (sic & unk) no (non & unk) (sic + non + unk) = Grapheme } abstract sig Value {} one sig pos, neg, unk extends Value {} fun fv[g : Grapheme, f : Feature] : Value { (g in f.sic) => pos else (g in f.non) => neg else unk } pred indistinct[fs : set Feature, g1, g2 : Grapheme] { all f : fs | fv[g1,f] = fv[g2,f] } fun clump[g : Grapheme, fs : set Feature] : set Grapheme { { g2 : Grapheme | indistinct[fs, g, g2] } } fun fset[g : Grapheme] : set Feature { { f : Feature | g in f.sic } } pred show_indistinct[g : Grapheme, gs : set Grapheme] { gs = clump[g, Feature] #gs > 1 } run show_indistinct pred distinctive[fs : set Feature, gs : set Grapheme] { all disj g1, g2 : gs | some f : fs | fv[g1,f] != fv[g2,f] } // Revisions: // 2010-03-26 : CMSMcQ : made file