
    fU                     V   d dl mZmZmZ d dlZd dlZd dlZd dlmZ d dl	m
Z
 d dl	mZmZmZ  G d d      Z G d dee
j                        Z G d	 d
ee
j                         Z G d dee
j"                        Z G d dee
j$                        Z G d dee
j&                        Zd-dZd Z ej,                  dej.                  ej0                  z  ej2                  z        Zd-dZdZ ej,                  ej;                  dd      ej.                  ej0                  z  ej2                  z        Z ej,                  ej;                  dd      ej.                  ej0                  z  ej2                  z        Zd-dZ d-dZ!d Z"d.dZ#d/dZ$d.dZ%d0d Z&d! Z'd.d"Z(d.d#Z)d.d$Z*d d%l+m,Z, e,ejZ                  fd&       Z.e/d'k(  rhg d(Z0e0D ]  Z1 e2d)e1d* e3 ee1                    e0D ]  Z1 e2d+e1d* e3 e!e1                    e0D ]  Z1 e2d,e1d* e3 e"e1                    yy)1    )divisionprint_functionunicode_literalsN)log)overlaylinint	loglinintc                   V     e Zd ZdZdZdZddZd Zd Zd Z	d Z
 fdZd	 Zd
 Z xZS )
_BaseModelF c                 d    | j                  |      D ]  }| j                  |d|        d| _        y)z- Extract n-grams from tokens and count them.    TN)_extract_ngramscount_ngrammodified)selftokensallow_new_wordsngrams       >/usr/lib/python3/dist-packages/Onboard/pypredict/lm_wrapper.pylearn_tokensz_BaseModel.learn_tokens$   s7    ))&1 	8EUA7	8     c              #   H  K   g }t        |d      }|D ]  }|j                  t        |dd               |D ]h  }|}t        |      D ]V  \  }}t        | j                        D ]9  }||z   dz   t        |      k  s||||z   dz    }	|t        |	      dz
  k(  sJ |	 ; X j yw)a/  
        Extract n-grams from tokens.

        Doctests:
        >>> m = DynamicModel(3)
        >>> list(m._extract_ngrams(["word1", "word2", "<unk>", "word3"]))
        [['word1'], ['word1', 'word2'], ['word2'], ['word3']]
        >>> list(m._extract_ngrams(["word1", "word2", "<s>", "word3"]))
        [['word1'], ['word1', 'word2'], ['word2'], ['<s>'], ['<s>', 'word3'], ['word3']]
        >>> list(m._extract_ngrams(["a", "b", "c", "d"]))
        [['a'], ['a', 'b'], ['a', 'b', 'c'], ['b'], ['b', 'c'], ['b', 'c', 'd'], ['c'], ['c', 'd'], ['d']]
        <unk><s>Tr   N)split_tokensextend	enumeraterangeorderlen)
r   r   token_sectionsunk_sectionssectiontoken_sectionitokennr   s
             r   r   z_BaseModel._extract_ngrams+   s       $FG4# 	FG!!,wt"DE	F
 , 	$M#G$W- $%tzz* $As1uG, '!A#a% 0 CJqL010#	$$	$s   A6B"9)B"c                     dg| j                   z  }dg| j                   z  }| j                         D ]=  }|t        |d         dz
  xx   dz  cc<   |t        |d         dz
  xx   |d   z  cc<   ? ||fS )zc
        Return number of n-gram types and total occurances
        for each n-gram level.
        r   r   )r    iter_ngramsr!   )r   countstotalsngs       r   
get_countsz_BaseModel.get_countsL   s    
 TZZTZZ""$ 	*B3r!u:a< Q& 3r!u:a< BqE) 	* v~r   c                     t        | d      r| j                  |_        | j                         D ]  }|d   }|d   }|j                  ||         |S )zg
        Copy contents of self to model. The order of the destination
        stays unchanged.
        	smoothingr   r   )hasattrr0   r*   r   )r   modelitr   counts        r   copyz_BaseModel.copyX   sZ    
 4%"nnEO""$ 	,BqEEqEEeU+	,
 r   c                    | j                   }t        |      D ]  }|dk7  r n|dz  } t        |d      }| j                  |      }t	        | d      r| j
                  |_        | j                         D ]R  }|d   }|d   }t        |      }t        t        |      |      dz
  }	||	   }||kD  s;|dk7  sA|j                  ||       T |S )a  
        Return a copy of self with all ngrams removed whose
        count is less or equal to <prune_count>.

        prune_count==-1  # prune all frequencies
        prune_count=0    # prune nothing
        prune_count>0    # prune frequencies below or equal prune_count
        r      r0   r   )
r    reversedmax	__class__r1   r0   r*   r!   minr   )
r   prune_countsr    prune_countr2   r3   r   r4   levelks
             r   prunez_BaseModel.pruneg   s     

#L1 	Kb QJE	
 E1u%4%"nnEO""$ 		0BqEEqEEJEC%u-1A&q/K{"r(9!!%/		0 r   c                     d| _         d| _        d| _        	 t        t        |   |       y # t        $ r}d| _         |d }~ww xY w)NFr   T)
load_errorload_error_msgr   superr   loadIOError)r   filenameer;   s      r   rF   z_BaseModel.load   sI     	*d(2 	"DOG	s   , 	A	>Ac                     | j                  |      }|r1|j                         D ]  \  }}| j                  ||        d| _        |S )z
        Remove word context[-1] where it appears after history context[:-1]
        from the model. If the history is empty all n-grams containing word
        will be removed.
        T)get_remove_context_changesitemsr   r   )r   contextchangesr   r4   s        r   remove_contextz_BaseModel.remove_context   sN     11': ' /u  ./ !DMr   c           	          i }| j                         D ]x  }|d   }|d   }t        t        |            D ]U  }t        t        t        |      |dz               D ]  }|||z
     || dz
     k7  s < t        |      dz
  k(  sO| ||<    x z |S )z}
        Simulate removal of context.
        Returns a dict of affected n-grams and their count changes (negative).
        r   r   )r*   r   r!   r<   )r   rM   rN   r3   r   r4   r&   js           r   rK   z%_BaseModel.get_remove_context_changes   s    
 ""$ 	BqEEqEE 3u:& s3w<156 AQqSzWaRT]2 CL1,,*/	 r   )T)__name__
__module____qualname__r   rC   rD   r   r   r.   r5   rA   rF   rO   rK   __classcell__)r;   s   @r   r   r      s<    HJN$B
!Fr   r   c                       e Zd ZdZd Zy)LanguageModelzp
    Abstract class representing the base class of all models.
    Keep this for access to class constants.
    c                     t               N)NotImplementedError)r   s    r   __init__zLanguageModel.__init__   s    !##r   N)rR   rS   rT   __doc__r[    r   r   rW   rW      s    $r   rW   c                       e Zd Zy)UnigramModelNrR   rS   rT   r]   r   r   r_   r_          r   r_   c                       e Zd Zy)DynamicModelNr`   r]   r   r   rc   rc      ra   r   rc   c                       e Zd Zy)DynamicModelKNNr`   r]   r   r   re   re      ra   r   re   c                       e Zd Zy)CachedDynamicModelNr`   r]   r   r   rg   rg      ra   r   rg   c                     g }g }| D ]4  }||k(  r|r|j                  |       |r|g}!g }$|j                  |       6 t        |      dkD  s
|r|d   |k7  r|j                  |       |S )a  
    Split list of tokens at separator token.

    Doctests:
    # excluding separator
    >>> split_tokens(["<unk>", "word1", "word2", "word3"], "<unk>")
    [['word1', 'word2', 'word3']]
    >>> split_tokens(["word1", "<unk>", "word2", "word3"], "<unk>")
    [['word1'], ['word2', 'word3']]
    >>> split_tokens(["word1", "word2", "word3", "<unk>"], "<unk>")
    [['word1', 'word2', 'word3']]

    # including separator
    >>> split_tokens(["<unk>", "word1", "word2", "word3"], "<unk>", True)
    [['<unk>', 'word1', 'word2', 'word3']]
    >>> split_tokens(["word1", "<unk>", "word2", "word3"], "<unk>", True)
    [['word1'], ['<unk>', 'word2', 'word3']]
    >>> split_tokens(["word1", "word2", "word3", "<unk>"], "<unk>", True)
    [['word1', 'word2', 'word3']]
    r   r   )appendr!   )r   	separatorkeep_separatorr"   r%   r'   s         r   r   r      s    * NM 
(I%%m4!* "  '
( =A-*i7m,r   c                     g }d}|D ]  }| || }|r|j                  |       |dz   }! | |d }|r|j                  |       |S )a$  
    Patition tokens with splits at the given indices.
    split_indices must be sorted in ascending order.

    Doctests:
    >>> test = split_tokens_at

    >>> test(["word0", "word1", "word2"], [])
    [['word0', 'word1', 'word2']]

    >>> test(["word0", "word1", "word2"], [0])
    [['word1', 'word2']]

    >>> test(["word0", "word1", "word2"], [1])
    [['word0'], ['word2']]

    >>> test(["word0", "word1", "word2"], [2])
    [['word0', 'word1']]

    >>> test(["word0", "word1", "word2"], [0, 2])
    [['word1']]

    >>> test(["word0", "word1", "word2"], [0, 1, 2])
    []

    >>> test(["word0", "word1", "word2", "word3", "word4"], [0, 2, 4])
    [['word1'], ['word3']]

    # out of range indices
    >>> test(["word0", "word1", "word2"], [100, 1000])
    [['word0', 'word1', 'word2']]
    r   r   N)ri   )r   split_indicesr"   	remainingr&   r$   s         r   split_tokens_atro      si    B NI 1%!!'*aC		 YZ Gg&r   a-   .*?
           (?:
                 (?:[.;:!?](?:(?=[\s]) | \")) # punctuation
               | (?:\\s*\\n\\s*)+(?=[\\n])    # multiples newlines
               | <s>                          # sentence end mark
           )
         | .+$                                # last sentence fragment
    c                    | j                  dd      }t        j                  |      }g }g }|D ]K  }|j                         }	 |j	                         }|j                         }	t        |      }
|j                         }||
t        |      z
  z  }t        |      }
|j                         }|	|
t        |      z
  z  }	t        j                  dd|      }t        |      }
|j                         }|	|
t        |      z
  z  }	t        |      }
|j                         }||
t        |      z
  z  }|r*t        j                  d|t        j                        s|dz  }|j                  |       |j                  ||	g       N ||fS )z Split text into sentences.  r   z   z
[.;:!?]"?$z <s>)replaceSENTENCE_PATTERNfinditergroupstartendr!   lstriprstripresubsearchUNICODEri   )textdisambiguatefilteredmatches	sentencesspansmatchsentencebeginrx   ls              r   split_sentencesr   7  sm   
 ||D%H ''1G IE '';;=KKMEIIKC HA(HQX&&EHA(H1s8}$$C vveUH5H HA(H1s8}$$CHA(HQX&&E yy"**E&HX&LL%&O''R er   u  
    (                                     # <unk>
      (?:^|(?<=\s))
        \S*(\S)\\2{{3,}}\S*               # char repeated more than 3 times
        | [-]{{3}}                        # dash repeated more than 2 times
      (?=\s|$)
      | :[^\s:@]+?@                       # password in URL
    ) |
    (                                     # <num>
      (?:[-+]?\d+(?:[.,]\d+)*)            # anything numeric looking
      | (?:[.,]\d+)
    ) |
    (                                     # word
      (?:[-]{{0,2}}                       # allow command line options
        [^\W\d]\w*(?:[-'´΄][\w]+)*        # word, not starting with a digit
        [{trailing_characters}'´΄]?)
      | <unk> | <s> | </s> | <num>        # pass through control words
      | <bot:[a-z]*>                      # pass through begin of text merkers
      | (?:^|(?<=\s))
          (?:
            \| {standalone_operators}     # common space delimited operators
          )
        (?=\s|$)
    )
    r   )trailing_charactersstandalone_operators-z
| [-]{1,2}c                    |rt         j                  |       }nt        j                  |       }g }g }|D ]  }|j                         }|d   r4|j	                  |d          |j	                  |j                                L|d   r1|j	                  d       |j	                  |j                                |d   s|j	                  d       |j	                  |j                                 ||fS )N   r8   z<num>r   r   )CONTEXT_PATTERNru   TEXT_PATTERNgroupsri   span)r   
is_contextr   r   r   r   r   s          r   tokenize_sentencer     s    !**84''1FE 
'!9MM&)$LL&AYMM'"LL&AYMM'"LL&
' 5=r   c                 \   g }g }t        |       \  }}t        |      D ]  \  }}t        ||      \  }}	||   d   }
|	D cg c]  }|d   |
z   |d   |
z   g }	}|dkD  r$|j                  d       |j                  |
|
g       |j	                  |       |j	                  |	        ||fS c c}w )a~   Split text into word tokens.
        The result is ready for use in learn_tokens().

        Sentence begins, if detected, are marked with "<s>".
        Numbers are replaced with the number marker <num>.
        Other tokens that could confuse the prediction are
        replaced with the unknown word marker "<unk>".

        Examples, text -> tokens:
            "We saw whales"  -> ["We", "saw", "whales"]
            "We saw whales " -> ["We", "saw", "whales"]
            "Hello there! We saw 5 whales "
                             -> ["Hello", "there", "<s>",
                                 "We", "saw", "<num>", "whales"]
    r   r   r   )r   r   r   ri   r   )r   r   r   r   r   sentence_spansr&   r   tssssbeginss               r   tokenize_textr     s    " FE / 5I~ + 8"8Z8B"1%245QqtF{AaDK(55 q5MM% LL&&)*bR 5= 6s   B)c                    t        | d      \  }}t        j                  d| t        j                  t        j                  z  t        j
                  z        s/|j                  d       t        |       }|j                  ||g       ||fS )zh Split text into word tokens + completion prefix.
        The result is ready for use in predict().
    T)r   u0  
                  ^$                             # empty string?
                | .*[-'´΄\w]$                    # word at the end?
                | (?:^|.*\s)[|]=?$               # recognized operator?
                | .*(\S)\\1{3,}$                 # anything repeated > 3 times?
                r   )r   r{   r   r~   DOTALLVERBOSEri   r!   )r   r   r   tends       r   tokenize_contextr     ss     "$T:MFE88 
 2::bii/

:< 	b4ydD\"5=r   c                    d}t         j                  dk\  rt        }nt        }	 t	        | |d      }|j                  d      }d}|D ]o  }|j                  d      rd}|st        j                  d|      }	|	r*|d	}t        |t        |	j                         d	               }|j                  d
      sn |S  |S # |$ r
}Y d}~yd}~ww xY w)zc
    Read the order from the header of the given file.
    Encoding may be 'utf-8', 'latin-1'.
    N)r   r      
Fz\data\Tzngram (\d+)=\d+r   \)sysversion_infoFileNotFoundErrorrG   read_corpussplit
startswithr{   r}   r:   intr   )
rH   encodingr    ex_classr   exlinesdatalineresults
             r   
read_orderr     s    
 E
6!$8Xr2 JJtED ??:&DYY148F=EE3v}}q'9#:;t$L L)  s   B: :C	C	c                    |r|g}nddg}t        |      D ]{  \  }}	 |&t        j                  | |      j                         }nKd}t        j                  | |      5 }t	        |      D ]  }|j                         }|s n||z  } ddd        |S  S # 1 sw Y   xY w# t        $ r}	|t        |      dz
  k(  r|	Y d}	~	d}	~	ww xY w)z2 Read corpus, encoding may be 'utf-8', 'latin-1'. zutf-8zlatin-1N)r   r   r   )r   codecsopenreadr   readlineUnicodeDecodeErrorr!   )
rH   r   	num_lines	encodingsr&   encr   fterrs
             r   r   r     s     J	i(	9% #	 {{8c:??A[[C8 "A"9- "JJL !		"" 	K%$ K" " " 	C	N1$$		s0   AB"*BB"B	B""	C+CCc                 z    t        | |      }|j                  d      }dD ]  }||vs|j                  |        |S )zk
    Read vocabulary with one word per line.
    Encoding may be 'utf-8', 'latin-1', like read_corpus.
    r   )r   r   z</s>z</num>)r   r   ri   )rH   r   r   
vocabulary	ctrl_words        r   read_vocabularyr     sK    
 x*DD!J7 )	J&i() r   c                     i }| D ]  }|j                  |d      dz   ||<    t        |j                               D cg c]  }|d   |k\  s| }}t        |d d      }|r|d| S |S c c}w )z< Extract the most frequent <max_words> words from <tokens>. r   r   c                     | d   S )Nr   r]   )xs    r   <lambda>z$extract_vocabulary.<locals>.<lambda>4  s
    ! r   T)keyreverseN)getlistrL   sorted)r   	min_count	max_wordsmr   r   rL   s          r   extract_vocabularyr   .  s}    
A uuQ{Q!QWWY=11Q49+<Q=E=5nd;EZi   >s   A)A)c                 N    t        |      }| D cg c]
  }||v r|nd c}S c c}w )Nr   )set)r   r   vr   s       r   filter_tokensr   :  s*    JA.45aAW$555s   "c                    |s| j                   }d}d}t        |      }t        t        |            D ]  }t        ||dz
  z
  d      }t	        ||dz
  z
  |z   t        |            }||| }	t        |	      dk7  sG| j                  |	      }
|
dk(  rt        ||	|
       |
rt        |
d      n
t        d      }||z  }|dz  } |r| |z  nd}	 d|z  }||fS #  d}Y ||fS xY w)Nr   r   r8   infinity)	r    r!   r   r:   r<   get_probabilityprintr   float)r2   r   r    ngram_countentropy
word_countr&   brI   r   p
perplexitys               r   r   r   >  s   KGVJ 3v; 
57A57E!3v;/qu:?%%e,AAvj%*Aq	E*$5AqLG1K
 &0whz!QG'\
 J
Js   C Cc                 H    t        | ||||      \  }}||z
  }|r|dz  |z  S dS )z9 Calculate keystroke savings rate from simulated typing. g      Y@r   )simulate_typing)query_modellearn_modelr   limitprogresstotal_charspressed_keyssaved_keystrokess           r   ksrr   ]  s>     /[)UZ\d eK"\15@e#k1GaGr   c                    d}d}t        |      D ]2  \  }}d}	d}
|
t        |      k  rt        d|	z         \  }}|r|t        |      dz
     nd}|t        |	      t        |      z
  d  }t        j                  d|t        j
                        j                         }| j                  ||      }	 ||v rt        |      t        |      z
  }|dk(  rd}nd}t        |      D ]  }|	||
   z  }	|
dz  }
|dz  } |dz  }|
t        |      k  r|rt        |      \  }}|j                  |       |s ||t        |      ||       5 ||fS )Nr   r   . r   z^([\w]|[-'])*)r   r!   r   r{   r}   r~   rv   predictr   inputr   r   )r   r   r   r   r   r   r   r&   r   	inputlinecursorrM   r   prefixprefix_to_endtarget_wordchoicesadded_charsr@   r   s                       r   r   r   c  s{   KL	* +C
(	s8}$-dY.>?NGU07WS\!^,RF$S^CK%?%@AM))$4mRZZPVVXK!))'59G g%!+.V<!#"#K;' !Xf--	!q !
 AL= s8}$B ,X6MFE$$V, QI\BW+CZ $$r   )contextmanagerc              #   V  K   dd l }dd l}|r|j                          |j                          |j                          |j                         }| r| nd}|j                  d|z         |j	                          d  |j                  d|j                         |z
  dz  z         y d  y w)Nr   timeitz%-15s z	%10.3fms
i  )timegccollectwriteflush)r   outr   r   r   r   s         r   r   r     s~     









IIKq8		(T/"		
		,499;?D"89:
s   B'B)__main__).r   z . za. za. bzsplit_sentences('z'): ztokenize_text('ztokenize_context(')FrY   )NN)r   r   )4
__future__r   r   r   r   r{   r   mathr   pypredict.lmlmr   r   r	   r   rW   r_   rc   re   rg   r   ro   compiler~   r   r   rt   r   tokenize_patternformatr   r   r   r   r   r   r   r   r   r   r   r   r   
contextlibr   stdoutr   rR   ar   r   reprr]   r   r   <module>r     sS  ( B A 
 	    3 3Z Zz$J 0 0 $	:r 		:r 		Z!2!2 		R%:%: 	'R.b 2:: 
BII	bjj	(* 6r 4 rzz*110213 2 5 **RYY.rzz9;
 "**-44031= 5 ? **RYY.rzz9;
.!F""H8
6>H2%j &**  ( z)A QT48M3NOPQ  M4mD6I1JKLM  SdD9I$9O4PQRS r   