tree.doctest 39 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102
  1. .. Copyright (C) 2001-2019 NLTK Project
  2. .. For license information, see LICENSE.TXT
  3. ===============================
  4. Unit tests for nltk.tree.Tree
  5. ===============================
  6. >>> from nltk.tree import *
  7. Some trees to run tests on:
  8. >>> dp1 = Tree('dp', [Tree('d', ['the']), Tree('np', ['dog'])])
  9. >>> dp2 = Tree('dp', [Tree('d', ['the']), Tree('np', ['cat'])])
  10. >>> vp = Tree('vp', [Tree('v', ['chased']), dp2])
  11. >>> tree = Tree('s', [dp1, vp])
  12. >>> print(tree)
  13. (s (dp (d the) (np dog)) (vp (v chased) (dp (d the) (np cat))))
  14. The node label is accessed using the `label()` method:
  15. >>> dp1.label(), dp2.label(), vp.label(), tree.label()
  16. ('dp', 'dp', 'vp', 's')
  17. >>> print(tree[1,1,1,0])
  18. cat
  19. The `treepositions` method returns a list of the tree positions of
  20. subtrees and leaves in a tree. By default, it gives the position of
  21. every tree, subtree, and leaf, in prefix order:
  22. >>> print(tree.treepositions())
  23. [(), (0,), (0, 0), (0, 0, 0), (0, 1), (0, 1, 0), (1,), (1, 0), (1, 0, 0), (1, 1), (1, 1, 0), (1, 1, 0, 0), (1, 1, 1), (1, 1, 1, 0)]
  24. In addition to `str` and `repr`, several methods exist to convert a
  25. tree object to one of several standard tree encodings:
  26. >>> print(tree.pformat_latex_qtree())
  27. \Tree [.s
  28. [.dp [.d the ] [.np dog ] ]
  29. [.vp [.v chased ] [.dp [.d the ] [.np cat ] ] ] ]
  30. There is also a fancy ASCII art representation:
  31. >>> tree.pretty_print()
  32. s
  33. ________|_____
  34. | vp
  35. | _____|___
  36. dp | dp
  37. ___|___ | ___|___
  38. d np v d np
  39. | | | | |
  40. the dog chased the cat
  41. >>> tree.pretty_print(unicodelines=True, nodedist=4)
  42. s
  43. ┌──────────────┴────────┐
  44. │ vp
  45. │ ┌────────┴──────┐
  46. dp │ dp
  47. ┌──────┴──────┐ │ ┌──────┴──────┐
  48. d np v d np
  49. │ │ │ │ │
  50. the dog chased the cat
  51. Trees can be initialized from treebank strings:
  52. >>> tree2 = Tree.fromstring('(S (NP I) (VP (V enjoyed) (NP my cookie)))')
  53. >>> print(tree2)
  54. (S (NP I) (VP (V enjoyed) (NP my cookie)))
  55. Trees can be compared for equality:
  56. >>> tree == Tree.fromstring(str(tree))
  57. True
  58. >>> tree2 == Tree.fromstring(str(tree2))
  59. True
  60. >>> tree == tree2
  61. False
  62. >>> tree == Tree.fromstring(str(tree2))
  63. False
  64. >>> tree2 == Tree.fromstring(str(tree))
  65. False
  66. >>> tree != Tree.fromstring(str(tree))
  67. False
  68. >>> tree2 != Tree.fromstring(str(tree2))
  69. False
  70. >>> tree != tree2
  71. True
  72. >>> tree != Tree.fromstring(str(tree2))
  73. True
  74. >>> tree2 != Tree.fromstring(str(tree))
  75. True
  76. >>> tree < tree2 or tree > tree2
  77. True
  78. Tree Parsing
  79. ============
  80. The class method `Tree.fromstring()` can be used to parse trees, and it
  81. provides some additional options.
  82. >>> tree = Tree.fromstring('(S (NP I) (VP (V enjoyed) (NP my cookie)))')
  83. >>> print(tree)
  84. (S (NP I) (VP (V enjoyed) (NP my cookie)))
  85. When called on a subclass of `Tree`, it will create trees of that
  86. type:
  87. >>> tree = ImmutableTree.fromstring('(VP (V enjoyed) (NP my cookie))')
  88. >>> print(tree)
  89. (VP (V enjoyed) (NP my cookie))
  90. >>> print(type(tree))
  91. <class 'nltk.tree.ImmutableTree'>
  92. >>> tree[1] = 'x'
  93. Traceback (most recent call last):
  94. . . .
  95. ValueError: ImmutableTree may not be modified
  96. >>> del tree[0]
  97. Traceback (most recent call last):
  98. . . .
  99. ValueError: ImmutableTree may not be modified
  100. The ``brackets`` parameter can be used to specify two characters that
  101. should be used as brackets:
  102. >>> print(Tree.fromstring('[S [NP I] [VP [V enjoyed] [NP my cookie]]]',
  103. ... brackets='[]'))
  104. (S (NP I) (VP (V enjoyed) (NP my cookie)))
  105. >>> print(Tree.fromstring('<S <NP I> <VP <V enjoyed> <NP my cookie>>>',
  106. ... brackets='<>'))
  107. (S (NP I) (VP (V enjoyed) (NP my cookie)))
  108. If ``brackets`` is not a string, or is not exactly two characters,
  109. then `Tree.fromstring` raises an exception:
  110. >>> Tree.fromstring('<VP <V enjoyed> <NP my cookie>>', brackets='')
  111. Traceback (most recent call last):
  112. . . .
  113. TypeError: brackets must be a length-2 string
  114. >>> Tree.fromstring('<VP <V enjoyed> <NP my cookie>>', brackets='<<>>')
  115. Traceback (most recent call last):
  116. . . .
  117. TypeError: brackets must be a length-2 string
  118. >>> Tree.fromstring('<VP <V enjoyed> <NP my cookie>>', brackets=12)
  119. Traceback (most recent call last):
  120. . . .
  121. TypeError: brackets must be a length-2 string
  122. >>> Tree.fromstring('<<NP my cookie>>', brackets=('<<','>>'))
  123. Traceback (most recent call last):
  124. . . .
  125. TypeError: brackets must be a length-2 string
  126. (We may add support for multi-character brackets in the future, in
  127. which case the ``brackets=('<<','>>')`` example would start working.)
  128. Whitespace brackets are not permitted:
  129. >>> Tree.fromstring('(NP my cookie\n', brackets='(\n')
  130. Traceback (most recent call last):
  131. . . .
  132. TypeError: whitespace brackets not allowed
  133. If an invalid tree is given to Tree.fromstring, then it raises a
  134. ValueError, with a description of the problem:
  135. >>> Tree.fromstring('(NP my cookie) (NP my milk)')
  136. Traceback (most recent call last):
  137. . . .
  138. ValueError: Tree.fromstring(): expected 'end-of-string' but got '(NP'
  139. at index 15.
  140. "...y cookie) (NP my mil..."
  141. ^
  142. >>> Tree.fromstring(')NP my cookie(')
  143. Traceback (most recent call last):
  144. . . .
  145. ValueError: Tree.fromstring(): expected '(' but got ')'
  146. at index 0.
  147. ")NP my coo..."
  148. ^
  149. >>> Tree.fromstring('(NP my cookie))')
  150. Traceback (most recent call last):
  151. . . .
  152. ValueError: Tree.fromstring(): expected 'end-of-string' but got ')'
  153. at index 14.
  154. "...my cookie))"
  155. ^
  156. >>> Tree.fromstring('my cookie)')
  157. Traceback (most recent call last):
  158. . . .
  159. ValueError: Tree.fromstring(): expected '(' but got 'my'
  160. at index 0.
  161. "my cookie)"
  162. ^
  163. >>> Tree.fromstring('(NP my cookie')
  164. Traceback (most recent call last):
  165. . . .
  166. ValueError: Tree.fromstring(): expected ')' but got 'end-of-string'
  167. at index 13.
  168. "... my cookie"
  169. ^
  170. >>> Tree.fromstring('')
  171. Traceback (most recent call last):
  172. . . .
  173. ValueError: Tree.fromstring(): expected '(' but got 'end-of-string'
  174. at index 0.
  175. ""
  176. ^
  177. Trees with no children are supported:
  178. >>> print(Tree.fromstring('(S)'))
  179. (S )
  180. >>> print(Tree.fromstring('(X (Y) (Z))'))
  181. (X (Y ) (Z ))
  182. Trees with an empty node label and no children are supported:
  183. >>> print(Tree.fromstring('()'))
  184. ( )
  185. >>> print(Tree.fromstring('(X () ())'))
  186. (X ( ) ( ))
  187. Trees with an empty node label and children are supported, but only if the
  188. first child is not a leaf (otherwise, it will be treated as the node label).
  189. >>> print(Tree.fromstring('((A) (B) (C))'))
  190. ( (A ) (B ) (C ))
  191. >>> print(Tree.fromstring('((A) leaf)'))
  192. ( (A ) leaf)
  193. >>> print(Tree.fromstring('(((())))'))
  194. ( ( ( ( ))))
  195. The optional arguments `read_node` and `read_leaf` may be used to
  196. transform the string values of nodes or leaves.
  197. >>> print(Tree.fromstring('(A b (C d e) (F (G h i)))',
  198. ... read_node=lambda s: '<%s>' % s,
  199. ... read_leaf=lambda s: '"%s"' % s))
  200. (<A> "b" (<C> "d" "e") (<F> (<G> "h" "i")))
  201. These transformation functions are typically used when the node or
  202. leaf labels should be parsed to a non-string value (such as a feature
  203. structure). If node and leaf labels need to be able to include
  204. whitespace, then you must also use the optional `node_pattern` and
  205. `leaf_pattern` arguments.
  206. >>> from nltk.featstruct import FeatStruct
  207. >>> tree = Tree.fromstring('([cat=NP] [lex=the] [lex=dog])',
  208. ... read_node=FeatStruct, read_leaf=FeatStruct)
  209. >>> tree.set_label(tree.label().unify(FeatStruct('[num=singular]')))
  210. >>> print(tree)
  211. ([cat='NP', num='singular'] [lex='the'] [lex='dog'])
  212. The optional argument ``remove_empty_top_bracketing`` can be used to
  213. remove any top-level empty bracketing that occurs.
  214. >>> print(Tree.fromstring('((S (NP I) (VP (V enjoyed) (NP my cookie))))',
  215. ... remove_empty_top_bracketing=True))
  216. (S (NP I) (VP (V enjoyed) (NP my cookie)))
  217. It will not remove a top-level empty bracketing with multiple children:
  218. >>> print(Tree.fromstring('((A a) (B b))'))
  219. ( (A a) (B b))
  220. Parented Trees
  221. ==============
  222. `ParentedTree` is a subclass of `Tree` that automatically maintains
  223. parent pointers for single-parented trees. Parented trees can be
  224. created directly from a node label and a list of children:
  225. >>> ptree = (
  226. ... ParentedTree('VP', [
  227. ... ParentedTree('VERB', ['saw']),
  228. ... ParentedTree('NP', [
  229. ... ParentedTree('DET', ['the']),
  230. ... ParentedTree('NOUN', ['dog'])])]))
  231. >>> print(ptree)
  232. (VP (VERB saw) (NP (DET the) (NOUN dog)))
  233. Parented trees can be created from strings using the classmethod
  234. `ParentedTree.fromstring`:
  235. >>> ptree = ParentedTree.fromstring('(VP (VERB saw) (NP (DET the) (NOUN dog)))')
  236. >>> print(ptree)
  237. (VP (VERB saw) (NP (DET the) (NOUN dog)))
  238. >>> print(type(ptree))
  239. <class 'nltk.tree.ParentedTree'>
  240. Parented trees can also be created by using the classmethod
  241. `ParentedTree.convert` to convert another type of tree to a parented
  242. tree:
  243. >>> tree = Tree.fromstring('(VP (VERB saw) (NP (DET the) (NOUN dog)))')
  244. >>> ptree = ParentedTree.convert(tree)
  245. >>> print(ptree)
  246. (VP (VERB saw) (NP (DET the) (NOUN dog)))
  247. >>> print(type(ptree))
  248. <class 'nltk.tree.ParentedTree'>
  249. .. clean-up:
  250. >>> del tree
  251. `ParentedTree`\ s should never be used in the same tree as `Tree`\ s
  252. or `MultiParentedTree`\ s. Mixing tree implementations may result in
  253. incorrect parent pointers and in `TypeError` exceptions:
  254. >>> # Inserting a Tree in a ParentedTree gives an exception:
  255. >>> ParentedTree('NP', [
  256. ... Tree('DET', ['the']), Tree('NOUN', ['dog'])])
  257. Traceback (most recent call last):
  258. . . .
  259. TypeError: Can not insert a non-ParentedTree into a ParentedTree
  260. >>> # inserting a ParentedTree in a Tree gives incorrect parent pointers:
  261. >>> broken_tree = Tree('NP', [
  262. ... ParentedTree('DET', ['the']), ParentedTree('NOUN', ['dog'])])
  263. >>> print(broken_tree[0].parent())
  264. None
  265. Parented Tree Methods
  266. ------------------------
  267. In addition to all the methods defined by the `Tree` class, the
  268. `ParentedTree` class adds six new methods whose values are
  269. automatically updated whenver a parented tree is modified: `parent()`,
  270. `parent_index()`, `left_sibling()`, `right_sibling()`, `root()`, and
  271. `treeposition()`.
  272. The `parent()` method contains a `ParentedTree`\ 's parent, if it has
  273. one; and ``None`` otherwise. `ParentedTree`\ s that do not have
  274. parents are known as "root trees."
  275. >>> for subtree in ptree.subtrees():
  276. ... print(subtree)
  277. ... print(' Parent = %s' % subtree.parent())
  278. (VP (VERB saw) (NP (DET the) (NOUN dog)))
  279. Parent = None
  280. (VERB saw)
  281. Parent = (VP (VERB saw) (NP (DET the) (NOUN dog)))
  282. (NP (DET the) (NOUN dog))
  283. Parent = (VP (VERB saw) (NP (DET the) (NOUN dog)))
  284. (DET the)
  285. Parent = (NP (DET the) (NOUN dog))
  286. (NOUN dog)
  287. Parent = (NP (DET the) (NOUN dog))
  288. The `parent_index()` method stores the index of a tree in its parent's
  289. child list. If a tree does not have a parent, then its `parent_index`
  290. is ``None``.
  291. >>> for subtree in ptree.subtrees():
  292. ... print(subtree)
  293. ... print(' Parent Index = %s' % subtree.parent_index())
  294. ... assert (subtree.parent() is None or
  295. ... subtree.parent()[subtree.parent_index()] is subtree)
  296. (VP (VERB saw) (NP (DET the) (NOUN dog)))
  297. Parent Index = None
  298. (VERB saw)
  299. Parent Index = 0
  300. (NP (DET the) (NOUN dog))
  301. Parent Index = 1
  302. (DET the)
  303. Parent Index = 0
  304. (NOUN dog)
  305. Parent Index = 1
  306. Note that ``ptree.parent().index(ptree)`` is *not* equivalent to
  307. ``ptree.parent_index()``. In particular, ``ptree.parent().index(ptree)``
  308. will return the index of the first child of ``ptree.parent()`` that is
  309. equal to ``ptree`` (using ``==``); and that child may not be
  310. ``ptree``:
  311. >>> on_and_on = ParentedTree('CONJP', [
  312. ... ParentedTree('PREP', ['on']),
  313. ... ParentedTree('COJN', ['and']),
  314. ... ParentedTree('PREP', ['on'])])
  315. >>> second_on = on_and_on[2]
  316. >>> print(second_on.parent_index())
  317. 2
  318. >>> print(second_on.parent().index(second_on))
  319. 0
  320. The methods `left_sibling()` and `right_sibling()` can be used to get a
  321. parented tree's siblings. If a tree does not have a left or right
  322. sibling, then the corresponding method's value is ``None``:
  323. >>> for subtree in ptree.subtrees():
  324. ... print(subtree)
  325. ... print(' Left Sibling = %s' % subtree.left_sibling())
  326. ... print(' Right Sibling = %s' % subtree.right_sibling())
  327. (VP (VERB saw) (NP (DET the) (NOUN dog)))
  328. Left Sibling = None
  329. Right Sibling = None
  330. (VERB saw)
  331. Left Sibling = None
  332. Right Sibling = (NP (DET the) (NOUN dog))
  333. (NP (DET the) (NOUN dog))
  334. Left Sibling = (VERB saw)
  335. Right Sibling = None
  336. (DET the)
  337. Left Sibling = None
  338. Right Sibling = (NOUN dog)
  339. (NOUN dog)
  340. Left Sibling = (DET the)
  341. Right Sibling = None
  342. A parented tree's root tree can be accessed using the `root()`
  343. method. This method follows the tree's parent pointers until it
  344. finds a tree without a parent. If a tree does not have a parent, then
  345. it is its own root:
  346. >>> for subtree in ptree.subtrees():
  347. ... print(subtree)
  348. ... print(' Root = %s' % subtree.root())
  349. (VP (VERB saw) (NP (DET the) (NOUN dog)))
  350. Root = (VP (VERB saw) (NP (DET the) (NOUN dog)))
  351. (VERB saw)
  352. Root = (VP (VERB saw) (NP (DET the) (NOUN dog)))
  353. (NP (DET the) (NOUN dog))
  354. Root = (VP (VERB saw) (NP (DET the) (NOUN dog)))
  355. (DET the)
  356. Root = (VP (VERB saw) (NP (DET the) (NOUN dog)))
  357. (NOUN dog)
  358. Root = (VP (VERB saw) (NP (DET the) (NOUN dog)))
  359. The `treeposition()` method can be used to find a tree's treeposition
  360. relative to its root:
  361. >>> for subtree in ptree.subtrees():
  362. ... print(subtree)
  363. ... print(' Tree Position = %s' % (subtree.treeposition(),))
  364. ... assert subtree.root()[subtree.treeposition()] is subtree
  365. (VP (VERB saw) (NP (DET the) (NOUN dog)))
  366. Tree Position = ()
  367. (VERB saw)
  368. Tree Position = (0,)
  369. (NP (DET the) (NOUN dog))
  370. Tree Position = (1,)
  371. (DET the)
  372. Tree Position = (1, 0)
  373. (NOUN dog)
  374. Tree Position = (1, 1)
  375. Whenever a parented tree is modified, all of the methods described
  376. above (`parent()`, `parent_index()`, `left_sibling()`, `right_sibling()`,
  377. `root()`, and `treeposition()`) are automatically updated. For example,
  378. if we replace ``ptree``\ 's subtree for the word "dog" with a new
  379. subtree for "cat," the method values for both the "dog" subtree and the
  380. "cat" subtree get automatically updated:
  381. >>> # Replace the dog with a cat
  382. >>> dog = ptree[1,1]
  383. >>> cat = ParentedTree('NOUN', ['cat'])
  384. >>> ptree[1,1] = cat
  385. >>> # the noun phrase is no longer the dog's parent:
  386. >>> print(dog.parent(), dog.parent_index(), dog.left_sibling())
  387. None None None
  388. >>> # dog is now its own root.
  389. >>> print(dog.root())
  390. (NOUN dog)
  391. >>> print(dog.treeposition())
  392. ()
  393. >>> # the cat's parent is now the noun phrase:
  394. >>> print(cat.parent())
  395. (NP (DET the) (NOUN cat))
  396. >>> print(cat.parent_index())
  397. 1
  398. >>> print(cat.left_sibling())
  399. (DET the)
  400. >>> print(cat.root())
  401. (VP (VERB saw) (NP (DET the) (NOUN cat)))
  402. >>> print(cat.treeposition())
  403. (1, 1)
  404. ParentedTree Regression Tests
  405. -----------------------------
  406. Keep track of all trees that we create (including subtrees) using this
  407. variable:
  408. >>> all_ptrees = []
  409. Define a helper funciton to create new parented trees:
  410. >>> def make_ptree(s):
  411. ... ptree = ParentedTree.convert(Tree.fromstring(s))
  412. ... all_ptrees.extend(t for t in ptree.subtrees()
  413. ... if isinstance(t, Tree))
  414. ... return ptree
  415. Define a test function that examines every subtree in all_ptrees; and
  416. checks that all six of its methods are defined correctly. If any
  417. ptrees are passed as arguments, then they are printed.
  418. >>> def pcheck(*print_ptrees):
  419. ... for ptree in all_ptrees:
  420. ... # Check ptree's methods.
  421. ... if ptree.parent() is not None:
  422. ... i = ptree.parent_index()
  423. ... assert ptree.parent()[i] is ptree
  424. ... if i > 0:
  425. ... assert ptree.left_sibling() is ptree.parent()[i-1]
  426. ... if i < (len(ptree.parent())-1):
  427. ... assert ptree.right_sibling() is ptree.parent()[i+1]
  428. ... assert len(ptree.treeposition()) > 0
  429. ... assert (ptree.treeposition() ==
  430. ... ptree.parent().treeposition() + (ptree.parent_index(),))
  431. ... assert ptree.root() is not ptree
  432. ... assert ptree.root() is not None
  433. ... assert ptree.root() is ptree.parent().root()
  434. ... assert ptree.root()[ptree.treeposition()] is ptree
  435. ... else:
  436. ... assert ptree.parent_index() is None
  437. ... assert ptree.left_sibling() is None
  438. ... assert ptree.right_sibling() is None
  439. ... assert ptree.root() is ptree
  440. ... assert ptree.treeposition() == ()
  441. ... # Check ptree's children's methods:
  442. ... for i, child in enumerate(ptree):
  443. ... if isinstance(child, Tree):
  444. ... # pcheck parent() & parent_index() methods
  445. ... assert child.parent() is ptree
  446. ... assert child.parent_index() == i
  447. ... # pcheck sibling methods
  448. ... if i == 0:
  449. ... assert child.left_sibling() is None
  450. ... else:
  451. ... assert child.left_sibling() is ptree[i-1]
  452. ... if i == len(ptree)-1:
  453. ... assert child.right_sibling() is None
  454. ... else:
  455. ... assert child.right_sibling() is ptree[i+1]
  456. ... if print_ptrees:
  457. ... print('ok!', end=' ')
  458. ... for ptree in print_ptrees: print(ptree)
  459. ... else:
  460. ... print('ok!')
  461. Run our test function on a variety of newly-created trees:
  462. >>> pcheck(make_ptree('(A)'))
  463. ok! (A )
  464. >>> pcheck(make_ptree('(A (B (C (D) (E f)) g) h)'))
  465. ok! (A (B (C (D ) (E f)) g) h)
  466. >>> pcheck(make_ptree('(A (B) (C c) (D d d) (E e e e))'))
  467. ok! (A (B ) (C c) (D d d) (E e e e))
  468. >>> pcheck(make_ptree('(A (B) (C (c)) (D (d) (d)) (E (e) (e) (e)))'))
  469. ok! (A (B ) (C (c )) (D (d ) (d )) (E (e ) (e ) (e )))
  470. Run our test function after performing various tree-modification
  471. operations:
  472. **__delitem__()**
  473. >>> ptree = make_ptree('(A (B (C (D) (E f) (Q p)) g) h)')
  474. >>> e = ptree[0,0,1]
  475. >>> del ptree[0,0,1]; pcheck(ptree); pcheck(e)
  476. ok! (A (B (C (D ) (Q p)) g) h)
  477. ok! (E f)
  478. >>> del ptree[0,0,0]; pcheck(ptree)
  479. ok! (A (B (C (Q p)) g) h)
  480. >>> del ptree[0,1]; pcheck(ptree)
  481. ok! (A (B (C (Q p))) h)
  482. >>> del ptree[-1]; pcheck(ptree)
  483. ok! (A (B (C (Q p))))
  484. >>> del ptree[-100]
  485. Traceback (most recent call last):
  486. . . .
  487. IndexError: index out of range
  488. >>> del ptree[()]
  489. Traceback (most recent call last):
  490. . . .
  491. IndexError: The tree position () may not be deleted.
  492. >>> # With slices:
  493. >>> ptree = make_ptree('(A (B c) (D e) f g (H i) j (K l))')
  494. >>> b = ptree[0]
  495. >>> del ptree[0:0]; pcheck(ptree)
  496. ok! (A (B c) (D e) f g (H i) j (K l))
  497. >>> del ptree[:1]; pcheck(ptree); pcheck(b)
  498. ok! (A (D e) f g (H i) j (K l))
  499. ok! (B c)
  500. >>> del ptree[-2:]; pcheck(ptree)
  501. ok! (A (D e) f g (H i))
  502. >>> del ptree[1:3]; pcheck(ptree)
  503. ok! (A (D e) (H i))
  504. >>> ptree = make_ptree('(A (B c) (D e) f g (H i) j (K l))')
  505. >>> del ptree[5:1000]; pcheck(ptree)
  506. ok! (A (B c) (D e) f g (H i))
  507. >>> del ptree[-2:1000]; pcheck(ptree)
  508. ok! (A (B c) (D e) f)
  509. >>> del ptree[-100:1]; pcheck(ptree)
  510. ok! (A (D e) f)
  511. >>> ptree = make_ptree('(A (B c) (D e) f g (H i) j (K l))')
  512. >>> del ptree[1:-2:2]; pcheck(ptree)
  513. ok! (A (B c) f (H i) j (K l))
  514. **__setitem__()**
  515. >>> ptree = make_ptree('(A (B (C (D) (E f) (Q p)) g) h)')
  516. >>> d, e, q = ptree[0,0]
  517. >>> ptree[0,0,0] = 'x'; pcheck(ptree); pcheck(d)
  518. ok! (A (B (C x (E f) (Q p)) g) h)
  519. ok! (D )
  520. >>> ptree[0,0,1] = make_ptree('(X (Y z))'); pcheck(ptree); pcheck(e)
  521. ok! (A (B (C x (X (Y z)) (Q p)) g) h)
  522. ok! (E f)
  523. >>> ptree[1] = d; pcheck(ptree)
  524. ok! (A (B (C x (X (Y z)) (Q p)) g) (D ))
  525. >>> ptree[-1] = 'x'; pcheck(ptree)
  526. ok! (A (B (C x (X (Y z)) (Q p)) g) x)
  527. >>> ptree[-100] = 'y'
  528. Traceback (most recent call last):
  529. . . .
  530. IndexError: index out of range
  531. >>> ptree[()] = make_ptree('(X y)')
  532. Traceback (most recent call last):
  533. . . .
  534. IndexError: The tree position () may not be assigned to.
  535. >>> # With slices:
  536. >>> ptree = make_ptree('(A (B c) (D e) f g (H i) j (K l))')
  537. >>> b = ptree[0]
  538. >>> ptree[0:0] = ('x', make_ptree('(Y)')); pcheck(ptree)
  539. ok! (A x (Y ) (B c) (D e) f g (H i) j (K l))
  540. >>> ptree[2:6] = (); pcheck(ptree); pcheck(b)
  541. ok! (A x (Y ) (H i) j (K l))
  542. ok! (B c)
  543. >>> ptree[-2:] = ('z', 'p'); pcheck(ptree)
  544. ok! (A x (Y ) (H i) z p)
  545. >>> ptree[1:3] = [make_ptree('(X)') for x in range(10)]; pcheck(ptree)
  546. ok! (A x (X ) (X ) (X ) (X ) (X ) (X ) (X ) (X ) (X ) (X ) z p)
  547. >>> ptree[5:1000] = []; pcheck(ptree)
  548. ok! (A x (X ) (X ) (X ) (X ))
  549. >>> ptree[-2:1000] = ['n']; pcheck(ptree)
  550. ok! (A x (X ) (X ) n)
  551. >>> ptree[-100:1] = [make_ptree('(U v)')]; pcheck(ptree)
  552. ok! (A (U v) (X ) (X ) n)
  553. >>> ptree[-1:] = (make_ptree('(X)') for x in range(3)); pcheck(ptree)
  554. ok! (A (U v) (X ) (X ) (X ) (X ) (X ))
  555. >>> ptree[1:-2:2] = ['x', 'y']; pcheck(ptree)
  556. ok! (A (U v) x (X ) y (X ) (X ))
  557. **append()**
  558. >>> ptree = make_ptree('(A (B (C (D) (E f) (Q p)) g) h)')
  559. >>> ptree.append('x'); pcheck(ptree)
  560. ok! (A (B (C (D ) (E f) (Q p)) g) h x)
  561. >>> ptree.append(make_ptree('(X (Y z))')); pcheck(ptree)
  562. ok! (A (B (C (D ) (E f) (Q p)) g) h x (X (Y z)))
  563. **extend()**
  564. >>> ptree = make_ptree('(A (B (C (D) (E f) (Q p)) g) h)')
  565. >>> ptree.extend(['x', 'y', make_ptree('(X (Y z))')]); pcheck(ptree)
  566. ok! (A (B (C (D ) (E f) (Q p)) g) h x y (X (Y z)))
  567. >>> ptree.extend([]); pcheck(ptree)
  568. ok! (A (B (C (D ) (E f) (Q p)) g) h x y (X (Y z)))
  569. >>> ptree.extend(make_ptree('(X)') for x in range(3)); pcheck(ptree)
  570. ok! (A (B (C (D ) (E f) (Q p)) g) h x y (X (Y z)) (X ) (X ) (X ))
  571. **insert()**
  572. >>> ptree = make_ptree('(A (B (C (D) (E f) (Q p)) g) h)')
  573. >>> ptree.insert(0, make_ptree('(X (Y z))')); pcheck(ptree)
  574. ok! (A (X (Y z)) (B (C (D ) (E f) (Q p)) g) h)
  575. >>> ptree.insert(-1, make_ptree('(X (Y z))')); pcheck(ptree)
  576. ok! (A (X (Y z)) (B (C (D ) (E f) (Q p)) g) (X (Y z)) h)
  577. >>> ptree.insert(-4, make_ptree('(X (Y z))')); pcheck(ptree)
  578. ok! (A (X (Y z)) (X (Y z)) (B (C (D ) (E f) (Q p)) g) (X (Y z)) h)
  579. >>> # Note: as with ``list``, inserting at a negative index that
  580. >>> # gives a position before the start of the list does *not*
  581. >>> # raise an IndexError exception; it just inserts at 0.
  582. >>> ptree.insert(-400, make_ptree('(X (Y z))')); pcheck(ptree)
  583. ok! (A
  584. (X (Y z))
  585. (X (Y z))
  586. (X (Y z))
  587. (B (C (D ) (E f) (Q p)) g)
  588. (X (Y z))
  589. h)
  590. **pop()**
  591. >>> ptree = make_ptree('(A (B (C (D) (E f) (Q p)) g) h)')
  592. >>> ptree[0,0].pop(1); pcheck(ptree)
  593. ParentedTree('E', ['f'])
  594. ok! (A (B (C (D ) (Q p)) g) h)
  595. >>> ptree[0].pop(-1); pcheck(ptree)
  596. 'g'
  597. ok! (A (B (C (D ) (Q p))) h)
  598. >>> ptree.pop(); pcheck(ptree)
  599. 'h'
  600. ok! (A (B (C (D ) (Q p))))
  601. >>> ptree.pop(-100)
  602. Traceback (most recent call last):
  603. . . .
  604. IndexError: index out of range
  605. **remove()**
  606. >>> ptree = make_ptree('(A (B (C (D) (E f) (Q p)) g) h)')
  607. >>> e = ptree[0,0,1]
  608. >>> ptree[0,0].remove(ptree[0,0,1]); pcheck(ptree); pcheck(e)
  609. ok! (A (B (C (D ) (Q p)) g) h)
  610. ok! (E f)
  611. >>> ptree[0,0].remove(make_ptree('(Q p)')); pcheck(ptree)
  612. ok! (A (B (C (D )) g) h)
  613. >>> ptree[0,0].remove(make_ptree('(Q p)'))
  614. Traceback (most recent call last):
  615. . . .
  616. ValueError: ParentedTree('Q', ['p']) is not in list
  617. >>> ptree.remove('h'); pcheck(ptree)
  618. ok! (A (B (C (D )) g))
  619. >>> ptree.remove('h');
  620. Traceback (most recent call last):
  621. . . .
  622. ValueError: 'h' is not in list
  623. >>> # remove() removes the first subtree that is equal (==) to the
  624. >>> # given tree, which may not be the identical tree we give it:
  625. >>> ptree = make_ptree('(A (X x) (Y y) (X x))')
  626. >>> x1, y, x2 = ptree
  627. >>> ptree.remove(ptree[-1]); pcheck(ptree)
  628. ok! (A (Y y) (X x))
  629. >>> print(x1.parent()); pcheck(x1)
  630. None
  631. ok! (X x)
  632. >>> print(x2.parent())
  633. (A (Y y) (X x))
  634. Test that a tree can not be given multiple parents:
  635. >>> ptree = make_ptree('(A (X x) (Y y) (Z z))')
  636. >>> ptree[0] = ptree[1]
  637. Traceback (most recent call last):
  638. . . .
  639. ValueError: Can not insert a subtree that already has a parent.
  640. >>> pcheck()
  641. ok!
  642. [more to be written]
  643. ImmutableParentedTree Regression Tests
  644. --------------------------------------
  645. >>> iptree = ImmutableParentedTree.convert(ptree)
  646. >>> type(iptree)
  647. <class 'nltk.tree.ImmutableParentedTree'>
  648. >>> del iptree[0]
  649. Traceback (most recent call last):
  650. . . .
  651. ValueError: ImmutableParentedTree may not be modified
  652. >>> iptree.set_label('newnode')
  653. Traceback (most recent call last):
  654. . . .
  655. ValueError: ImmutableParentedTree may not be modified
  656. MultiParentedTree Regression Tests
  657. ----------------------------------
  658. Keep track of all trees that we create (including subtrees) using this
  659. variable:
  660. >>> all_mptrees = []
  661. Define a helper funciton to create new parented trees:
  662. >>> def make_mptree(s):
  663. ... mptree = MultiParentedTree.convert(Tree.fromstring(s))
  664. ... all_mptrees.extend(t for t in mptree.subtrees()
  665. ... if isinstance(t, Tree))
  666. ... return mptree
  667. Define a test function that examines every subtree in all_mptrees; and
  668. checks that all six of its methods are defined correctly. If any
  669. mptrees are passed as arguments, then they are printed.
  670. >>> def mpcheck(*print_mptrees):
  671. ... def has(seq, val): # uses identity comparison
  672. ... for item in seq:
  673. ... if item is val: return True
  674. ... return False
  675. ... for mptree in all_mptrees:
  676. ... # Check mptree's methods.
  677. ... if len(mptree.parents()) == 0:
  678. ... assert len(mptree.left_siblings()) == 0
  679. ... assert len(mptree.right_siblings()) == 0
  680. ... assert len(mptree.roots()) == 1
  681. ... assert mptree.roots()[0] is mptree
  682. ... assert mptree.treepositions(mptree) == [()]
  683. ... left_siblings = right_siblings = ()
  684. ... roots = {id(mptree): 1}
  685. ... else:
  686. ... roots = dict((id(r), 0) for r in mptree.roots())
  687. ... left_siblings = mptree.left_siblings()
  688. ... right_siblings = mptree.right_siblings()
  689. ... for parent in mptree.parents():
  690. ... for i in mptree.parent_indices(parent):
  691. ... assert parent[i] is mptree
  692. ... # check left siblings
  693. ... if i > 0:
  694. ... for j in range(len(left_siblings)):
  695. ... if left_siblings[j] is parent[i-1]:
  696. ... del left_siblings[j]
  697. ... break
  698. ... else:
  699. ... assert 0, 'sibling not found!'
  700. ... # check ight siblings
  701. ... if i < (len(parent)-1):
  702. ... for j in range(len(right_siblings)):
  703. ... if right_siblings[j] is parent[i+1]:
  704. ... del right_siblings[j]
  705. ... break
  706. ... else:
  707. ... assert 0, 'sibling not found!'
  708. ... # check roots
  709. ... for root in parent.roots():
  710. ... assert id(root) in roots, 'missing root'
  711. ... roots[id(root)] += 1
  712. ... # check that we don't have any unexplained values
  713. ... assert len(left_siblings)==0, 'unexpected sibling'
  714. ... assert len(right_siblings)==0, 'unexpected sibling'
  715. ... for v in roots.values(): assert v>0, roots #'unexpected root'
  716. ... # check treepositions
  717. ... for root in mptree.roots():
  718. ... for treepos in mptree.treepositions(root):
  719. ... assert root[treepos] is mptree
  720. ... # Check mptree's children's methods:
  721. ... for i, child in enumerate(mptree):
  722. ... if isinstance(child, Tree):
  723. ... # mpcheck parent() & parent_index() methods
  724. ... assert has(child.parents(), mptree)
  725. ... assert i in child.parent_indices(mptree)
  726. ... # mpcheck sibling methods
  727. ... if i > 0:
  728. ... assert has(child.left_siblings(), mptree[i-1])
  729. ... if i < len(mptree)-1:
  730. ... assert has(child.right_siblings(), mptree[i+1])
  731. ... if print_mptrees:
  732. ... print('ok!', end=' ')
  733. ... for mptree in print_mptrees: print(mptree)
  734. ... else:
  735. ... print('ok!')
  736. Run our test function on a variety of newly-created trees:
  737. >>> mpcheck(make_mptree('(A)'))
  738. ok! (A )
  739. >>> mpcheck(make_mptree('(A (B (C (D) (E f)) g) h)'))
  740. ok! (A (B (C (D ) (E f)) g) h)
  741. >>> mpcheck(make_mptree('(A (B) (C c) (D d d) (E e e e))'))
  742. ok! (A (B ) (C c) (D d d) (E e e e))
  743. >>> mpcheck(make_mptree('(A (B) (C (c)) (D (d) (d)) (E (e) (e) (e)))'))
  744. ok! (A (B ) (C (c )) (D (d ) (d )) (E (e ) (e ) (e )))
  745. >>> subtree = make_mptree('(A (B (C (D) (E f)) g) h)')
  746. Including some trees that contain multiple parents:
  747. >>> mpcheck(MultiParentedTree('Z', [subtree, subtree]))
  748. ok! (Z (A (B (C (D ) (E f)) g) h) (A (B (C (D ) (E f)) g) h))
  749. Run our test function after performing various tree-modification
  750. operations (n.b., these are the same tests that we ran for
  751. `ParentedTree`, above; thus, none of these trees actually *uses*
  752. multiple parents.)
  753. **__delitem__()**
  754. >>> mptree = make_mptree('(A (B (C (D) (E f) (Q p)) g) h)')
  755. >>> e = mptree[0,0,1]
  756. >>> del mptree[0,0,1]; mpcheck(mptree); mpcheck(e)
  757. ok! (A (B (C (D ) (Q p)) g) h)
  758. ok! (E f)
  759. >>> del mptree[0,0,0]; mpcheck(mptree)
  760. ok! (A (B (C (Q p)) g) h)
  761. >>> del mptree[0,1]; mpcheck(mptree)
  762. ok! (A (B (C (Q p))) h)
  763. >>> del mptree[-1]; mpcheck(mptree)
  764. ok! (A (B (C (Q p))))
  765. >>> del mptree[-100]
  766. Traceback (most recent call last):
  767. . . .
  768. IndexError: index out of range
  769. >>> del mptree[()]
  770. Traceback (most recent call last):
  771. . . .
  772. IndexError: The tree position () may not be deleted.
  773. >>> # With slices:
  774. >>> mptree = make_mptree('(A (B c) (D e) f g (H i) j (K l))')
  775. >>> b = mptree[0]
  776. >>> del mptree[0:0]; mpcheck(mptree)
  777. ok! (A (B c) (D e) f g (H i) j (K l))
  778. >>> del mptree[:1]; mpcheck(mptree); mpcheck(b)
  779. ok! (A (D e) f g (H i) j (K l))
  780. ok! (B c)
  781. >>> del mptree[-2:]; mpcheck(mptree)
  782. ok! (A (D e) f g (H i))
  783. >>> del mptree[1:3]; mpcheck(mptree)
  784. ok! (A (D e) (H i))
  785. >>> mptree = make_mptree('(A (B c) (D e) f g (H i) j (K l))')
  786. >>> del mptree[5:1000]; mpcheck(mptree)
  787. ok! (A (B c) (D e) f g (H i))
  788. >>> del mptree[-2:1000]; mpcheck(mptree)
  789. ok! (A (B c) (D e) f)
  790. >>> del mptree[-100:1]; mpcheck(mptree)
  791. ok! (A (D e) f)
  792. >>> mptree = make_mptree('(A (B c) (D e) f g (H i) j (K l))')
  793. >>> del mptree[1:-2:2]; mpcheck(mptree)
  794. ok! (A (B c) f (H i) j (K l))
  795. **__setitem__()**
  796. >>> mptree = make_mptree('(A (B (C (D) (E f) (Q p)) g) h)')
  797. >>> d, e, q = mptree[0,0]
  798. >>> mptree[0,0,0] = 'x'; mpcheck(mptree); mpcheck(d)
  799. ok! (A (B (C x (E f) (Q p)) g) h)
  800. ok! (D )
  801. >>> mptree[0,0,1] = make_mptree('(X (Y z))'); mpcheck(mptree); mpcheck(e)
  802. ok! (A (B (C x (X (Y z)) (Q p)) g) h)
  803. ok! (E f)
  804. >>> mptree[1] = d; mpcheck(mptree)
  805. ok! (A (B (C x (X (Y z)) (Q p)) g) (D ))
  806. >>> mptree[-1] = 'x'; mpcheck(mptree)
  807. ok! (A (B (C x (X (Y z)) (Q p)) g) x)
  808. >>> mptree[-100] = 'y'
  809. Traceback (most recent call last):
  810. . . .
  811. IndexError: index out of range
  812. >>> mptree[()] = make_mptree('(X y)')
  813. Traceback (most recent call last):
  814. . . .
  815. IndexError: The tree position () may not be assigned to.
  816. >>> # With slices:
  817. >>> mptree = make_mptree('(A (B c) (D e) f g (H i) j (K l))')
  818. >>> b = mptree[0]
  819. >>> mptree[0:0] = ('x', make_mptree('(Y)')); mpcheck(mptree)
  820. ok! (A x (Y ) (B c) (D e) f g (H i) j (K l))
  821. >>> mptree[2:6] = (); mpcheck(mptree); mpcheck(b)
  822. ok! (A x (Y ) (H i) j (K l))
  823. ok! (B c)
  824. >>> mptree[-2:] = ('z', 'p'); mpcheck(mptree)
  825. ok! (A x (Y ) (H i) z p)
  826. >>> mptree[1:3] = [make_mptree('(X)') for x in range(10)]; mpcheck(mptree)
  827. ok! (A x (X ) (X ) (X ) (X ) (X ) (X ) (X ) (X ) (X ) (X ) z p)
  828. >>> mptree[5:1000] = []; mpcheck(mptree)
  829. ok! (A x (X ) (X ) (X ) (X ))
  830. >>> mptree[-2:1000] = ['n']; mpcheck(mptree)
  831. ok! (A x (X ) (X ) n)
  832. >>> mptree[-100:1] = [make_mptree('(U v)')]; mpcheck(mptree)
  833. ok! (A (U v) (X ) (X ) n)
  834. >>> mptree[-1:] = (make_mptree('(X)') for x in range(3)); mpcheck(mptree)
  835. ok! (A (U v) (X ) (X ) (X ) (X ) (X ))
  836. >>> mptree[1:-2:2] = ['x', 'y']; mpcheck(mptree)
  837. ok! (A (U v) x (X ) y (X ) (X ))
  838. **append()**
  839. >>> mptree = make_mptree('(A (B (C (D) (E f) (Q p)) g) h)')
  840. >>> mptree.append('x'); mpcheck(mptree)
  841. ok! (A (B (C (D ) (E f) (Q p)) g) h x)
  842. >>> mptree.append(make_mptree('(X (Y z))')); mpcheck(mptree)
  843. ok! (A (B (C (D ) (E f) (Q p)) g) h x (X (Y z)))
  844. **extend()**
  845. >>> mptree = make_mptree('(A (B (C (D) (E f) (Q p)) g) h)')
  846. >>> mptree.extend(['x', 'y', make_mptree('(X (Y z))')]); mpcheck(mptree)
  847. ok! (A (B (C (D ) (E f) (Q p)) g) h x y (X (Y z)))
  848. >>> mptree.extend([]); mpcheck(mptree)
  849. ok! (A (B (C (D ) (E f) (Q p)) g) h x y (X (Y z)))
  850. >>> mptree.extend(make_mptree('(X)') for x in range(3)); mpcheck(mptree)
  851. ok! (A (B (C (D ) (E f) (Q p)) g) h x y (X (Y z)) (X ) (X ) (X ))
  852. **insert()**
  853. >>> mptree = make_mptree('(A (B (C (D) (E f) (Q p)) g) h)')
  854. >>> mptree.insert(0, make_mptree('(X (Y z))')); mpcheck(mptree)
  855. ok! (A (X (Y z)) (B (C (D ) (E f) (Q p)) g) h)
  856. >>> mptree.insert(-1, make_mptree('(X (Y z))')); mpcheck(mptree)
  857. ok! (A (X (Y z)) (B (C (D ) (E f) (Q p)) g) (X (Y z)) h)
  858. >>> mptree.insert(-4, make_mptree('(X (Y z))')); mpcheck(mptree)
  859. ok! (A (X (Y z)) (X (Y z)) (B (C (D ) (E f) (Q p)) g) (X (Y z)) h)
  860. >>> # Note: as with ``list``, inserting at a negative index that
  861. >>> # gives a position before the start of the list does *not*
  862. >>> # raise an IndexError exception; it just inserts at 0.
  863. >>> mptree.insert(-400, make_mptree('(X (Y z))')); mpcheck(mptree)
  864. ok! (A
  865. (X (Y z))
  866. (X (Y z))
  867. (X (Y z))
  868. (B (C (D ) (E f) (Q p)) g)
  869. (X (Y z))
  870. h)
  871. **pop()**
  872. >>> mptree = make_mptree('(A (B (C (D) (E f) (Q p)) g) h)')
  873. >>> mptree[0,0].pop(1); mpcheck(mptree)
  874. MultiParentedTree('E', ['f'])
  875. ok! (A (B (C (D ) (Q p)) g) h)
  876. >>> mptree[0].pop(-1); mpcheck(mptree)
  877. 'g'
  878. ok! (A (B (C (D ) (Q p))) h)
  879. >>> mptree.pop(); mpcheck(mptree)
  880. 'h'
  881. ok! (A (B (C (D ) (Q p))))
  882. >>> mptree.pop(-100)
  883. Traceback (most recent call last):
  884. . . .
  885. IndexError: index out of range
  886. **remove()**
  887. >>> mptree = make_mptree('(A (B (C (D) (E f) (Q p)) g) h)')
  888. >>> e = mptree[0,0,1]
  889. >>> mptree[0,0].remove(mptree[0,0,1]); mpcheck(mptree); mpcheck(e)
  890. ok! (A (B (C (D ) (Q p)) g) h)
  891. ok! (E f)
  892. >>> mptree[0,0].remove(make_mptree('(Q p)')); mpcheck(mptree)
  893. ok! (A (B (C (D )) g) h)
  894. >>> mptree[0,0].remove(make_mptree('(Q p)'))
  895. Traceback (most recent call last):
  896. . . .
  897. ValueError: MultiParentedTree('Q', ['p']) is not in list
  898. >>> mptree.remove('h'); mpcheck(mptree)
  899. ok! (A (B (C (D )) g))
  900. >>> mptree.remove('h');
  901. Traceback (most recent call last):
  902. . . .
  903. ValueError: 'h' is not in list
  904. >>> # remove() removes the first subtree that is equal (==) to the
  905. >>> # given tree, which may not be the identical tree we give it:
  906. >>> mptree = make_mptree('(A (X x) (Y y) (X x))')
  907. >>> x1, y, x2 = mptree
  908. >>> mptree.remove(mptree[-1]); mpcheck(mptree)
  909. ok! (A (Y y) (X x))
  910. >>> print([str(p) for p in x1.parents()])
  911. []
  912. >>> print([str(p) for p in x2.parents()])
  913. ['(A (Y y) (X x))']
  914. ImmutableMultiParentedTree Regression Tests
  915. -------------------------------------------
  916. >>> imptree = ImmutableMultiParentedTree.convert(mptree)
  917. >>> type(imptree)
  918. <class 'nltk.tree.ImmutableMultiParentedTree'>
  919. >>> del imptree[0]
  920. Traceback (most recent call last):
  921. . . .
  922. ValueError: ImmutableMultiParentedTree may not be modified
  923. >>> imptree.set_label('newnode')
  924. Traceback (most recent call last):
  925. . . .
  926. ValueError: ImmutableMultiParentedTree may not be modified
  927. ProbabilisticTree Regression Tests
  928. ----------------------------------
  929. >>> prtree = ProbabilisticTree("S", [ProbabilisticTree("NP", ["N"], prob=0.3)], prob=0.6)
  930. >>> print(prtree)
  931. (S (NP N)) (p=0.6)
  932. >>> import copy
  933. >>> prtree == copy.deepcopy(prtree) == prtree.copy(deep=True) == prtree.copy()
  934. True
  935. >>> prtree[0] is prtree.copy()[0]
  936. True
  937. >>> prtree[0] is prtree.copy(deep=True)[0]
  938. False
  939. >>> imprtree = ImmutableProbabilisticTree.convert(prtree)
  940. >>> type(imprtree)
  941. <class 'nltk.tree.ImmutableProbabilisticTree'>
  942. >>> del imprtree[0]
  943. Traceback (most recent call last):
  944. . . .
  945. ValueError: ImmutableProbabilisticTree may not be modified
  946. >>> imprtree.set_label('newnode')
  947. Traceback (most recent call last):
  948. . . .
  949. ValueError: ImmutableProbabilisticTree may not be modified
  950. Squashed Bugs
  951. =============
  952. This used to discard the ``(B b)`` subtree (fixed in svn 6270):
  953. >>> print(Tree.fromstring('((A a) (B b))'))
  954. ( (A a) (B b))