File: deptree.py

package info (click to toggle)
frog 0.12.17-7.1
  • links: PTS, VCS
  • area: main
  • in suites: jessie, jessie-kfreebsd
  • size: 2,140 kB
  • ctags: 575
  • sloc: sh: 11,167; cpp: 5,146; python: 765; makefile: 38
file content (124 lines) | stat: -rwxr-xr-x 3,050 bytes parent folder | download | duplicates (2)
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
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
from itertools import izip


class Node:

	def __init__(self):
		self.outgoingRelation = None
		self.incomingRelations = set()


class DependencyTree:

	def __init__(self, numTokens):
		self.nodes = [Node() for i in xrange(numTokens)]
		self.relations = []

	def addRelation(self, source, dest, relType):
		rel = (self.nodes[source], self.nodes[dest], relType)
		self.relations.append(rel)
		self.nodes[source].outgoingRelation = (dest, relType)
		self.nodes[dest].incomingRelations.add((source, relType))

	def removeRelation(self, source):
		dest, relType = self.nodes[source].outgoingRelation
		rel = (self.nodes[source], self.nodes[dest], relType)
		self.relations.remove(rel)
		self.nodes[source].outgoingRelation = None
		self.nodes[dest].incomingRelations.remove((source, relType))

	def findCycle(self):
		visitedNodes = set()
		for node in self.nodes:
			if node not in visitedNodes:
				result = self.visitNode(node, visitedNodes)
				if result:
					return result

	def visitNode(self, node, visitedNodes):
		currentNodes = set()
		currentNode = node
		path = []

		while currentNode.outgoingRelation:
			currentNodes.add(currentNode)
			visitedNodes.add(currentNode)

			path.append(currentNode)
			
			dest, relType = currentNode.outgoingRelation
			dest = self.nodes[dest]
			if dest in currentNodes:
				return path[path.index(dest):]
			elif dest in visitedNodes:
				return None
			else:
				currentNode = dest

		return None


class Constraint:

	def __init__(self, weight):
		self.weight = weight

	def isSatisfied(self, tree):
		raise NotImplementedError

	def getValue(self, tree):
		if self.isSatisfied(tree):
			return self.weight
		else:
			return 0.0


class HasIncomingRel(Constraint):

	def __init__(self, tokenIndex, relType, weight):
		Constraint.__init__(self, weight)
		self.tokenIndex = tokenIndex
		self.relType = relType

	def isSatisfied(self, tree):
		return self.relType in [rel[1] for rel in tree.nodes[self.tokenIndex].incomingRelations]


class HasDependency(Constraint):

	def __init__(self, tokenIndex, headIndex, relType, weight):
		Constraint.__init__(self, weight)
		self.tokenIndex = tokenIndex
		self.headIndex = headIndex
		self.relType = relType

	def isSatisfied(self, tree):
		return tree.nodes[self.tokenIndex].outgoingRelation == (self.headIndex, self.relType)


class DependencyDirection(Constraint):

	ROOT, LEFT, RIGHT = range(3)

	def __init__(self, tokenIndex, direction, weight):
		Constraint.__init__(self, weight)
		self.tokenIndex = tokenIndex
		self.direction = direction

	def isSatisfied(self, tree):
		return tree.nodes[self.tokenIndex].outgoingRelation != None and int(tree.nodes[self.tokenIndex].outgoingRelation[0] - self.tokenIndex > 0) == self.direction


def writeDepTree(tree, sentence, stream=None):
	for node, token in izip(tree.nodes, sentence):
		line = list(token)

		if node.outgoingRelation:
			headIndex, relType = node.outgoingRelation
			line[6:8] = str(headIndex + 1), relType
		else:
			line[6:8] = "0", "ROOT"

		print >> stream, "\t".join(line)

	print >> stream