'Trains a ProbabilisticDependencyGrammar based on the list of input
DependencyGraphs.  This model is an implementation of Eisner\'s (1996)
Model C, which derives its statistics from head-word, head-tag,
child-word, and child-tag relationships.
:param graphs: A list of dependency graphs to train from.
:type: list(DependencyGraph)'

def train(self, graphs):

    productions = []
    events = defaultdict(int)
    tags = {}
    for dg in graphs:
        for node_index in range(1, len(dg.nodes)):
            children = list(chain(*dg.nodes[node_index][u'deps'].values()))
            nr_left_children = dg.left_children(node_index)
            nr_right_children = dg.right_children(node_index)
            nr_children = (nr_left_children + nr_right_children)
            for child_index in range((0 - (nr_left_children + 1)), (nr_right_children + 2)):
                head_word = dg.nodes[node_index][u'word']
                head_tag = dg.nodes[node_index][u'tag']
                if (head_word in tags):
                    tags[head_word].add(head_tag)
                else:
                    tags[head_word] = set([head_tag])
                child = u'STOP'
                child_tag = u'STOP'
                prev_word = u'START'
                prev_tag = u'START'
                if (child_index < 0):
                    array_index = (child_index + nr_left_children)
                    if (array_index >= 0):
                        child = dg.nodes[children[array_index]][u'word']
                        child_tag = dg.nodes[children[array_index]][u'tag']
                    if (child_index != (-1)):
                        prev_word = dg.nodes[children[(array_index + 1)]][u'word']
                        prev_tag = dg.nodes[children[(array_index + 1)]][u'tag']
                    if (child != u'STOP'):
                        productions.append(DependencyProduction(head_word, [child]))
                    head_event = (u'(head    (%s    %s)    (mods    (%s,    %s,    %s)    left))' % (child, child_tag, prev_tag, head_word, head_tag))
                    mod_event = (u'(mods    (%s,    %s,    %s)    left))' % (prev_tag, head_word, head_tag))
                    events[head_event] += 1
                    events[mod_event] += 1
                elif (child_index > 0):
                    array_index = ((child_index + nr_left_children) - 1)
                    if (array_index < nr_children):
                        child = dg.nodes[children[array_index]][u'word']
                        child_tag = dg.nodes[children[array_index]][u'tag']
                    if (child_index != 1):
                        prev_word = dg.nodes[children[(array_index - 1)]][u'word']
                        prev_tag = dg.nodes[children[(array_index - 1)]][u'tag']
                    if (child != u'STOP'):
                        productions.append(DependencyProduction(head_word, [child]))
                    head_event = (u'(head    (%s    %s)    (mods    (%s,    %s,    %s)    right))' % (child, child_tag, prev_tag, head_word, head_tag))
                    mod_event = (u'(mods    (%s,    %s,    %s)    right))' % (prev_tag, head_word, head_tag))
                    events[head_event] += 1
                    events[mod_event] += 1
    self._grammar = ProbabilisticDependencyGrammar(productions, events, tags)
