11use pyo3:: prelude:: * ;
22use std:: collections:: { HashMap , HashSet } ;
3+ use std:: hash:: Hash ;
4+ use std:: collections:: hash_map:: Entry ;
35
46/// Formats the sum of two numbers as string.
57#[ pyfunction]
68fn sum_as_string ( a : usize , b : usize ) -> PyResult < String > {
79 Ok ( ( a + b) . to_string ( ) )
810}
911
12+ fn increment_and_remove_if_zero < T : std:: cmp:: Eq + Hash , N : std:: ops:: AddAssign + std:: cmp:: PartialEq < usize > > ( map : & mut HashMap < T , N > , key : T , amount : N ) -> ( ) {
13+ match map. entry ( key) {
14+ Entry :: Occupied ( mut entry) => {
15+ // add
16+ * entry. get_mut ( ) += amount;
17+
18+ // if the value becomes 0 as a result remove.
19+ if * entry. get ( ) == 0 {
20+ entry. remove ( ) ;
21+ }
22+ }
23+ Entry :: Vacant ( entry) => {
24+ if amount != 0 {
25+ entry. insert ( amount) ;
26+ }
27+ }
28+ }
29+ }
30+
31+ fn decrement_or_remove < T : std:: cmp:: Eq + Hash > ( map : & mut HashMap < T , usize > , key : T , amount : usize ) -> ( ) {
32+ match map. entry ( key) {
33+ Entry :: Occupied ( mut entry) => {
34+ // add
35+ * entry. get_mut ( ) -= amount;
36+
37+ // if the value becomes 0 as a result remove.
38+ if * entry. get ( ) == 0 {
39+ entry. remove ( ) ;
40+ }
41+ }
42+ Entry :: Vacant ( _) => { }
43+ }
44+ }
45+
1046// borrows:
1147// tok_to_count: hashmap
1248fn get_pairs (
1349 tok_to_count : & HashMap < Vec < Vec < u8 > > , usize > ,
1450) -> (
1551 HashMap < ( Vec < u8 > , Vec < u8 > ) , usize > ,
16- HashMap < ( Vec < u8 > , Vec < u8 > ) , HashSet < Vec < u8 > > > ,
52+ HashMap < ( Vec < u8 > , Vec < u8 > ) , HashSet < Vec < Vec < u8 > > > > ,
1753) {
1854 let mut pair_to_count: HashMap < ( Vec < u8 > , Vec < u8 > ) , usize > = HashMap :: new ( ) ;
19- let mut pair_to_toks: HashMap < ( Vec < u8 > , Vec < u8 > ) , HashSet < Vec < u8 > > > = HashMap :: new ( ) ;
55+ let mut pair_to_toks: HashMap < ( Vec < u8 > , Vec < u8 > ) , HashSet < Vec < Vec < u8 > > > > = HashMap :: new ( ) ;
2056
2157 for ( tok, count) in tok_to_count {
2258 // not big enough for a pair.
2359 if tok. len ( ) < 2 {
2460 continue ;
2561 }
2662 for i in 0 ..( tok. len ( ) - 1 ) {
27- let pair = ( tok[ i] , tok[ i+1 ] ) ;
63+ let pair = ( tok[ i] . clone ( ) , tok[ i+1 ] . clone ( ) ) ;
2864
2965 match pair_to_count. entry ( pair. clone ( ) ) {
3066 std:: collections:: hash_map:: Entry :: Occupied ( mut e) => {
@@ -38,7 +74,7 @@ fn get_pairs(
3874 pair_to_toks
3975 . entry ( pair. clone ( ) )
4076 . or_insert ( HashSet :: new ( ) )
41- . insert ( tok) ;
77+ . insert ( tok. clone ( ) ) ;
4278 }
4379 }
4480
@@ -48,10 +84,10 @@ fn get_pairs(
4884/// we take a map from vector of bytes and a max vocab size.
4985/// and we return?
5086#[ pyfunction]
51- fn merge ( tok_to_count : HashMap < Vec < Vec < u8 > > , usize > , max : usize ) -> PyResult < Vec < ( Vec < u8 > , Vec < u8 > ) > > {
87+ fn merge ( mut tok_to_count : HashMap < Vec < Vec < u8 > > , usize > , max : usize ) -> PyResult < Vec < ( Vec < u8 > , Vec < u8 > ) > > {
5288 let mut max_pairs = vec ! [ ( vec![ 0 ; 0 ] , vec![ 0 ; 0 ] ) ; max] ;
5389 let ( mut pair_to_count, mut pair_to_toks) = get_pairs ( & tok_to_count) ;
54- let max_heap =
90+ // TODO: maintain heap of max-pairs, instead of finding the max_pair on every loop.
5591
5692 while max_pairs. len ( ) < max {
5793 let max_pair_opt = max_pairs. iter ( )
@@ -63,13 +99,14 @@ fn merge(tok_to_count: HashMap<Vec<Vec<u8>>, usize>, max: usize) -> PyResult<Vec
6399 max_pairs. push ( max_pair. clone ( ) ) ;
64100 // ---------------- EFFICIENTLY UPDATE ----------------
65101 let max_pair_to_toks = & pair_to_toks[ & max_pair] ;
102+
66103 // for every tok that contains max_pair
67104 for tok in max_pair_to_toks. clone ( ) {
68105 let tok_count = tok_to_count[ & tok. clone ( ) ] ;
69106
70- // for every pair
107+ // for every pair in tok
71108 for i in 0 ..tok. len ( ) - 1 {
72- let pair = ( vec ! [ tok[ i] ] , vec ! [ tok[ i+1 ] ] ) ;
109+ let pair = ( tok[ i] . clone ( ) , tok[ i+1 ] . clone ( ) ) ;
73110
74111 match pair_to_toks. entry ( pair. clone ( ) ) {
75112 std:: collections:: hash_map:: Entry :: Occupied ( mut e) => {
@@ -96,14 +133,62 @@ fn merge(tok_to_count: HashMap<Vec<Vec<u8>>, usize>, max: usize) -> PyResult<Vec
96133 std:: collections:: hash_map:: Entry :: Vacant ( _) => { }
97134 }
98135 }
99- let new_tok: Vec < u8 > = Vec :: new ( ) ;
136+
137+ // construct new_tok
138+ let mut new_tok: Vec < Vec < u8 > > = Vec :: new ( ) ;
139+
100140 let mut i = 0 ;
141+
101142 while i < tok. len ( ) {
102- if i < tok. len ( ) - 1 && ( tok[ i] , tok[ i+1 ] ) == max_pair {
103- new_tok. append ( tok[ i] + tok[ i+1 ] ) ;
143+ if i < tok. len ( ) - 1 && ( tok[ i] . clone ( ) , tok[ i+1 ] . clone ( ) ) == max_pair {
144+ let new_vocab = [ & tok[ i] [ ..] , & tok[ i+1 ] [ ..] ] . concat ( ) ;
145+ new_tok. push ( new_vocab) ;
146+ i += 2 ;
147+ } else {
148+ new_tok. push ( tok[ i] . clone ( ) ) ;
149+ i += 1
150+ }
151+ }
152+
153+ // increment new_tok count by tok_count
154+ * tok_to_count. entry ( new_tok. clone ( ) ) . or_insert ( 0 ) += tok_count;
155+
156+ // decrement tok count by tok_count
157+ // if tok_count is zero -> remove tok entry all together.
158+ decrement_or_remove ( & mut tok_to_count, tok. clone ( ) , tok_count) ;
159+
160+ // for every pair in new_tok
161+ for i in 0 ..new_tok. clone ( ) . len ( ) - 1 {
162+ let pair = ( tok[ i] . clone ( ) , tok[ i+1 ] . clone ( ) ) ;
163+
164+ match pair_to_toks. entry ( pair. clone ( ) ) {
165+ std:: collections:: hash_map:: Entry :: Occupied ( mut e) => {
166+ let set = e. get_mut ( ) ;
167+
168+ // remove from pair's toks.
169+ set. insert ( new_tok. clone ( ) ) ;
170+ }
171+ std:: collections:: hash_map:: Entry :: Vacant ( _) => { }
172+ }
173+
174+ match pair_to_count. entry ( pair. clone ( ) ) {
175+ std:: collections:: hash_map:: Entry :: Occupied ( mut e) => {
176+ * e. get_mut ( ) -= tok_count; // remove tok_count from pair count.
177+
178+ // if pair's count is zero.
179+ if * e. get ( ) == 0 {
180+ // remove pair's pair_to_count entry
181+ e. remove ( ) ;
182+
183+ // TODO: also remove the pair's pair_to_toks entry
184+ }
185+ }
186+ std:: collections:: hash_map:: Entry :: Vacant ( _) => { }
104187 }
105188 }
106189 }
190+
191+
107192
108193 // ---------------- EFFICIENTLY UPDATE ----------------
109194 }
0 commit comments