
    /hE                     d    S SK Jr  S SKJr  S SKJrJr   " S S\5      rS r\	S:X  a  \" 5         gg)	    )reduce)ParserI)ProbabilisticTreeTreec                   \    \ rS rSrSrSS jrS rSS jrS rS r	S r
S	 rS
 rS rS rSrg)ViterbiParser   a	  
A bottom-up ``PCFG`` parser that uses dynamic programming to find
the single most likely parse for a text.  The ``ViterbiParser`` parser
parses texts by filling in a "most likely constituent table".
This table records the most probable tree representation for any
given span and node value.  In particular, it has an entry for
every start index, end index, and node value, recording the most
likely subtree that spans from the start index to the end index,
and has the given node value.

The ``ViterbiParser`` parser fills in this table incrementally.  It starts
by filling in all entries for constituents that span one element
of text (i.e., entries where the end index is one greater than the
start index).  After it has filled in all table entries for
constituents that span one element of text, it fills in the
entries for constitutants that span two elements of text.  It
continues filling in the entries for constituents spanning larger
and larger portions of the text, until the entire table has been
filled.  Finally, it returns the table entry for a constituent
spanning the entire text, whose node value is the grammar's start
symbol.

In order to find the most likely constituent with a given span and
node value, the ``ViterbiParser`` parser considers all productions that
could produce that node value.  For each production, it finds all
children that collectively cover the span and have the node values
specified by the production's right hand side.  If the probability
of the tree formed by applying the production to the children is
greater than the probability of the current entry in the table,
then the table is updated with this new tree.

A pseudo-code description of the algorithm used by
``ViterbiParser`` is:

| Create an empty most likely constituent table, *MLC*.
| For width in 1...len(text):
|   For start in 1...len(text)-width:
|     For prod in grammar.productions:
|       For each sequence of subtrees [t[1], t[2], ..., t[n]] in MLC,
|         where t[i].label()==prod.rhs[i],
|         and the sequence covers [start:start+width]:
|           old_p = MLC[start, start+width, prod.lhs]
|           new_p = P(t[1])P(t[1])...P(t[n])P(prod)
|           if new_p > old_p:
|             new_tree = Tree(prod.lhs, t[1], t[2], ..., t[n])
|             MLC[start, start+width, prod.lhs] = new_tree
| Return MLC[0, len(text), start_symbol]

:type _grammar: PCFG
:ivar _grammar: The grammar used to parse sentences.
:type _trace: int
:ivar _trace: The level of tracing output that should be generated
    when parsing a text.
c                     Xl         X l        g)ab  
Create a new ``ViterbiParser`` parser, that uses ``grammar`` to
parse texts.

:type grammar: PCFG
:param grammar: The grammar used to parse texts.
:type trace: int
:param trace: The level of tracing that should be used when
    parsing a text.  ``0`` will generate no tracing output;
    and higher numbers will produce more verbose tracing
    output.
N_grammar_trace)selfgrammartraces      J/var/www/auris/envauris/lib/python3.13/site-packages/nltk/parse/viterbi.py__init__ViterbiParser.__init__K   s          c                     U R                   $ Nr   r   s    r   r   ViterbiParser.grammar[   s    }}r   c                     Xl         g)a  
Set the level of tracing output that should be generated when
parsing a text.

:type trace: int
:param trace: The trace level.  A trace level of ``0`` will
    generate no tracing output; and higher trace levels will
    produce more verbose tracing output.
:rtype: None
N)r   )r   r   s     r   r   ViterbiParser.trace^   s	     r   c              #     #    [        U5      nU R                  R                  U5        0 nU R                  (       a  [	        S5        [        [        U5      5       H=  nX   nXBX3S-   U4'   U R                  S:  d  M"  U R                  XC[        U5      5        M?     [        S[        U5      S-   5       H^  nU R                  (       a  [	        SSU-  -   5        [        [        U5      U-
  S-   5       H  nXfU-   4nU R                  XrU5        M     M`     UR                  S[        U5      U R                  R                  5       45      nUb  Uv   g g 7f)Nz;Inserting tokens into the most likely constituents table...   z$Finding the most likely constituentsz spanning %d text elements...r   )listr   check_coverager   printrangelen_trace_lexical_insertion_add_constituents_spanninggetstart)	r   tokensconstituentsindextokenlengthr&   spantrees	            r   parseViterbiParser.parsek   s4     f$$V,  ;;TU3v;'EME49	501{{Q--eCKH	 ( As6{Q/F{{:5>? s6{V3a78v~.//FK 9 0 CK1D1D1F GHJ s   A7E=CEc           	         SnU(       Gar  SnU R                  X5      nU GHM  u  pgU Vs/ s H  n[        U[        5      (       d  M  UPM     n	n[        S XR	                  5       5      n
UR                  5       R                  5       n[        XU
S9nUR                  US   US   UR                  5       45      nU R                  S:  a^  Ub  X:w  aV  Ub"  UR	                  5       UR	                  5       :  a  [        SS	S
9  O
[        SS	S
9  U R                  XjU[        U5      5        Ub%  UR	                  5       UR	                  5       :  d  GM0  XUS   US   UR                  5       4'   SnGMP     U(       a  GMq  ggs  snf )aJ  
Find any constituents that might cover ``span``, and add them
to the most likely constituents table.

:rtype: None
:type span: tuple(int, int)
:param span: The section of the text for which we are
    trying to find possible constituents.  The span is
    specified as a pair of integers, where the first integer
    is the index of the first token that should be included in
    the constituent; and the second integer is the index of
    the first token that should not be included in the
    constituent.  I.e., the constituent should cover
    ``text[span[0]:span[1]]``, where ``text`` is the text
    that we are parsing.

:type constituents: dict(tuple(int,int,Nonterminal) -> ProbabilisticToken or ProbabilisticTree)
:param constituents: The most likely constituents table.  This
    table records the most probable tree representation for
    any given span and node value.  In particular,
    ``constituents(s,e,nv)`` is the most likely
    ``ProbabilisticTree`` that covers ``text[s:e]``
    and has a node value ``nv.symbol()``, where ``text``
    is the text that we are parsing.  When
    ``_add_constituents_spanning`` is called, ``constituents``
    should contain all possible constituents that are shorter
    than ``span``.

:type tokens: list of tokens
:param tokens: The text we are parsing.  This is only used for
    trace output.
TFc                 &    XR                  5       -  $ r   prob)prts     r   <lambda>:ViterbiParser._add_constituents_spanning.<locals>.<lambda>   s    ffhr   r2   r   r   Nz
   Insert: endz
  Discard:)_find_instantiations
isinstancer   r   r3   lhssymbolr   r%   r   r    _trace_productionr"   )r   r,   r(   r'   changedinstantiations
productionchildrencsubtreespnoder-   s                r   r$   (ViterbiParser._add_constituents_spanning   sK   H G "66tJN )7$
'/Gx!:a3FAxG6//BST!~~'..0(a@ !$$d1gtAw
8H%IJ;;?yAI9499;(>!,C8!,C8..zdCKP9499; 6GKa$q':>>3C!CD"G% )7 g Hs   E>E>c                     / nU R                   R                  5        H>  nU R                  UR                  5       X5      nU H  nUR	                  XF45        M     M@     U$ )aa  
:return: a list of the production instantiations that cover a
    given span of the text.  A "production instantiation" is
    a tuple containing a production and a list of children,
    where the production's right hand side matches the list of
    children; and the children cover ``span``.  :rtype: list
    of ``pair`` of ``Production``, (list of
    (``ProbabilisticTree`` or token.

:type span: tuple(int, int)
:param span: The section of the text for which we are
    trying to find production instantiations.  The span is
    specified as a pair of integers, where the first integer
    is the index of the first token that should be covered by
    the production instantiation; and the second integer is
    the index of the first token that should not be covered by
    the production instantiation.
:type constituents: dict(tuple(int,int,Nonterminal) -> ProbabilisticToken or ProbabilisticTree)
:param constituents: The most likely constituents table.  This
    table records the most probable tree representation for
    any given span and node value.  See the module
    documentation for more information.
)r   productions
_match_rhsrhsappend)r   r,   r(   rvrB   
childlists	childlists          r   r;   "ViterbiParser._find_instantiations   sW    0 --335J)94NJ'			:12 ( 6
 	r   c                    Uu  pEXE:  a	  US:X  a  / /$ XE:  d  US:X  a  / $ / n[        XES-   5       HM  nUR                  XGUS   45      nUc  M  U R                  USS Xu4U5      n	Xi V
s/ s H  o/U
-   PM
     sn
-  nMO     U$ s  sn
f )a  
:return: a set of all the lists of children that cover ``span``
    and that match ``rhs``.
:rtype: list(list(ProbabilisticTree or token)

:type rhs: list(Nonterminal or any)
:param rhs: The list specifying what kinds of children need to
    cover ``span``.  Each nonterminal in ``rhs`` specifies
    that the corresponding child should be a tree whose node
    value is that nonterminal's symbol.  Each terminal in ``rhs``
    specifies that the corresponding child should be a token
    whose type is that terminal.
:type span: tuple(int, int)
:param span: The section of the text for which we are
    trying to find child lists.  The span is specified as a
    pair of integers, where the first integer is the index of
    the first token that should be covered by the child list;
    and the second integer is the index of the first token
    that should not be covered by the child list.
:type constituents: dict(tuple(int,int,Nonterminal) -> ProbabilisticToken or ProbabilisticTree)
:param constituents: The most likely constituents table.  This
    table records the most probable tree representation for
    any given span and node value.  See the module
    documentation for more information.
 r   r   N)r!   r%   rK   )r   rL   r,   r(   r&   r:   rO   splitlrightsrs              r   rK   ViterbiParser._match_rhs   s    4  <C2I4K<3"9I 
5'*E  %A!78A}QR5,M71sQw77
	 +  8s   )Bc                     SSUS   -  -   nUSUS   US   -
  -  -  nUSXCS   -
  -  S-   -  nUSU-  -  nU R                   S:  a
  US	 S
US S
3n[        U5        g)aK  
Print trace output indicating that a given production has been
applied at a given location.

:param production: The production that has been applied
:type production: Production
:param p: The probability of the tree produced by the production.
:type p: float
:param span: The span of the production
:type span: tuple
:rtype: None
|.r   =r   | z%s   z<40r8   z12.10fN)r   r    )r   rB   rF   r,   widthstrs         r   r?   ViterbiParser._trace_production$  s     C$q'M!sd1gQ'((se1go&--tj  ;;?IQqj*Cc
r   c                 V    SSU-  -   S-   SX2-
  S-
  -  -   S-   nXA -  n[        U5        g )Nz   Insert: |r[   r\   r   r]   )r    )r   r*   r)   r_   r`   s        r   r#   &ViterbiParser._trace_lexical_insertion;  s<    sU{*S03%-!:K3LLtSc
r   c                      SU R                   -  $ )Nz<ViterbiParser for %r>r   r   s    r   __repr__ViterbiParser.__repr__@  s    '$--77r   r   N)r   )r^   )__name__
__module____qualname____firstlineno____doc__r   r   r   r.   r$   r;   rK   r?   r#   re   __static_attributes__rS   r   r   r   r      s?    5n 'RB#H@*X.
8r   r   c                  h   SSK n SSKnSSKJn  SSKJn  SSKJn  UR                  S5      nUR                  S5      nSU4S	U4/n[        5         [        [        U5      5       H9  n[        US
-   S SXx   S    35        [        SXx   S
   -  5        [        5         M;     [        SS
[        U5      4-  SS9   [        U R                  R                  5       R                  5       5      S
-
  n	Xy   u  pU
R!                  5       nU" U5      n0 n[        SU
 SU SU 35        UR#                  S5        UR                  5       nUR%                  U5      nUR                  5       U-
  nU(       a  ['        S US5      [        U5      -  OSn[        U5      nU H  nS
UUR)                  5       '   M     [        5         [        S5        [        S5        [        SUUU4-  5        UR+                  5       nU(       a  ['        S US5      [        U5      -  nOSn[        S5        [        SS[        U5      U4-  5        [        5         [        SSS9  U R                  R                  5       R                  5       R-                  5       R/                  S5      (       a  SS KJn  [        S!5        U" U6   [        5         [        S"SS9  U R                  R                  5       R                  5       R-                  5       R/                  S5      (       a  U H  n[        U5        M     gg!   [        S5         g= f)#z
A demonstration of the probabilistic parsers.  The user is
prompted to select which demo to run, and how many parses should
be found; and then each parser is run on the same demo, and a
summary of the results are displayed.
r   N)tokenize)PCFG)r   a7  
    S -> NP VP [1.0]
    NP -> Det N [0.5] | NP PP [0.25] | 'John' [0.1] | 'I' [0.15]
    Det -> 'the' [0.8] | 'my' [0.2]
    N -> 'man' [0.5] | 'telescope' [0.5]
    VP -> VP PP [0.1] | V NP [0.7] | V [0.2]
    V -> 'ate' [0.35] | 'saw' [0.65]
    PP -> P NP [1.0]
    P -> 'with' [0.61] | 'under' [0.39]
    a  
    S    -> NP VP         [1.0]
    VP   -> V NP          [.59]
    VP   -> V             [.40]
    VP   -> VP PP         [.01]
    NP   -> Det N         [.41]
    NP   -> Name          [.28]
    NP   -> NP PP         [.31]
    PP   -> P NP          [1.0]
    V    -> 'saw'         [.21]
    V    -> 'ate'         [.51]
    V    -> 'ran'         [.28]
    N    -> 'boy'         [.11]
    N    -> 'cookie'      [.12]
    N    -> 'table'       [.13]
    N    -> 'telescope'   [.14]
    N    -> 'hill'        [.5]
    Name -> 'Jack'        [.52]
    Name -> 'Bob'         [.48]
    P    -> 'with'        [.61]
    P    -> 'under'       [.39]
    Det  -> 'the'         [.41]
    Det  -> 'a'           [.31]
    Det  -> 'my'          [.28]
    zI saw the man with my telescopez:the boy saw Jack with Bob under the table with a telescoper   z>3z: z     %rzWhich demo (%d-%d)? r8   r9   zBad sentence numberz
sent: z	
parser: z

grammar:    c                 &    XR                  5       -   $ r   r2   abs     r   r6   demo.<locals>.<lambda>  s    ALr   z)Time (secs)   # Parses   Average P(parse)z)-----------------------------------------z%11.4f%11d%19.14fc                 &    XR                  5       -   $ r   r2   rr   s     r   r6   ru     s    FFHr   z*------------------------------------------z%11s%11d%19.14fzn/azDraw parses (y/n)? y)
draw_treesz  please wait...zPrint parses (y/n)? )systimenltkrn   nltk.grammarro   
nltk.parser   
fromstringr    r!   r"   intstdinreadlinestriprT   r   	parse_allr   freezekeyslower
startswithnltk.draw.treerx   )ry   rz   rn   ro   r   	toy_pcfg1	toy_pcfg2demosisnumsentr   r'   parser
all_parsesr5   parsesaverage
num_parsesrF   rx   r.   s                         r   demor   I  s    !(		I 	I< 
+I6	EyQE 
G3u:Qr
"UXa[M*+i%(1+%&  

 As5z?
2<399%%'--/014 ZZ\F7#FJ	HTF*VHKy
AB
LLO		Af%F99;?DFL(&!4s6{BRS  VJ!"
188:  
G	
56	
56	
z7 ;
;<__F,fa83v;F	
67	
uc&k15
56 
G	
S)
yy!!#))+66s;;- !F 
G	
 c*
yy!!#))+66s;;E%L  <_#$s   9:L" "L1__main__N)
	functoolsr   nltk.parse.apir   	nltk.treer   r   r   r   rg   rS   r   r   <module>r      s:     " -n8G n8l	xv zF r   