// Graphviz visuallizes the current internal topology of the Builder. func (b *Builder) Graphviz(w io.Writer) { fmt.Fprintln(w, "digraph {") fmt.Fprintln(w, " // lexical transitions") for p, es := range b.transitions { if es != nil { for xqw := range es.Range() { x, qw := word.Id(xqw.Key), xqw.Value fmt.Fprintf(w, " %d -> %d [label=%q]\n", p, qw.State, fmt.Sprintf("%s : %g", b.vocab.StringOf(x), qw.Weight)) } } } fmt.Fprintln(w, " // back-off transitions") for i, s := range b.backoff { fmt.Fprintf(w, " %d -> %d [label=%q,style=dashed]\n", i, s.State, fmt.Sprintf("%g", s.Weight)) } fmt.Fprintln(w, "}") }
// link links each state p to the first state q with at least one // lexical transition along p's back-off chain. func (b *Builder) link() { // Children of _STATE_EMPTY directly backs off the _STATE_EMPTY. for xqw := range b.transitions[_STATE_EMPTY].Range() { q := xqw.Value.State if q != STATE_NIL { b.backoff[q].State = _STATE_EMPTY } } // States are created with STATE_NIL as the default back-off. Except // for _STATE_EMPTY, having a STATE_NIL back-off means the back-off // is yet to be computed. for i, es := range b.transitions[_STATE_EMPTY+1:] { if es != nil { for xqw := range es.Range() { p, x, q := StateId(i+1), word.Id(xqw.Key), xqw.Value.State if q != STATE_NIL { b.linkTransition(p, x, q) } } } } }