GitLab

accessible_worlds.aw_vocabulary

  1from collections import Counter
  2from pathlib import Path
  3
  4import numpy as np
  5
  6from .aw_utils import (
  7    safe_save, 
  8    load_json, 
  9    synonyms_wsd,
 10    get_word_forms
 11)
 12
 13class AwVocabulary :
 14
 15    def __init__( 
 16        self,
 17        core_things_and_concepts : dict[str,list[str]],
 18        moral_concepts : dict[str,list[str]],
 19        word_counter : Counter | None = None,
 20        core_integration_counter  : Counter | None = None,
 21        moral_integration_counter : Counter | None = None,
 22        all_core_word_forms : set[str] | None = None,
 23        vocab_word_forms : dict[str, list[str] ] | None = None,
 24        all_vocab_word_forms : set[str] | None = None,
 25        vocab_names : set[str] | None = None ) :
 26
 27        self.core_things_and_concepts = core_things_and_concepts
 28        self.moral_concepts = moral_concepts
 29
 30        if word_counter is None :
 31            self.word_counter = Counter()
 32        else :
 33            self.word_counter = word_counter
 34
 35        if core_integration_counter is None :
 36            self.core_integration_counter = Counter( {
 37                integration : 0
 38                for _, category in self.core_things_and_concepts.items() for integration in category
 39            } )
 40        else :
 41            self.core_integration_counter = core_integration_counter
 42
 43        if moral_integration_counter is None :
 44            self.moral_integration_counter = Counter( {
 45                integration : 0
 46                for _, category in self.moral_concepts.items() for integration in category
 47            } )
 48        else :
 49            self.moral_integration_counter = moral_integration_counter
 50
 51        if all_core_word_forms is None :
 52            all_words = set()
 53            for element in list( self.core_integration_counter.keys() ) + list( self.moral_integration_counter.keys() ) :
 54                all_words.update( element.split() )
 55
 56            word_forms = get_word_forms( all_words )
 57            self.all_core_word_forms = set( [ w for _, forms in word_forms.items() for w in forms ] )
 58        else :
 59            self.all_core_word_forms = all_core_word_forms
 60
 61        if all_vocab_word_forms is None :
 62            self.all_vocab_word_forms = set()
 63        else :
 64            self.all_vocab_word_forms = all_vocab_word_forms
 65
 66        if vocab_word_forms is None :
 67            self.vocab_word_forms = dict()
 68        else :
 69            self.vocab_word_forms = vocab_word_forms
 70
 71        if vocab_names is None :
 72            self.vocab_names = set() 
 73        else :
 74            self.vocab_names = vocab_names
 75
 76    @classmethod
 77    def from_file( 
 78        cls, 
 79        filepath : str | Path ) :
 80
 81        data = load_json( filepath )
 82        return cls(
 83            core_things_and_concepts=data['core_things_and_concepts'],
 84            moral_concepts=data[ 'moral_concepts' ],
 85            word_counter=Counter( data['word_counter'] ),
 86            core_integration_counter=Counter( data['core_integration_counter'] ),
 87            moral_integration_counter=Counter( data['moral_integration_counter'] ), 
 88            all_core_word_forms=set( data['all_core_word_forms'] ),
 89            vocab_word_forms=data['vocab_word_forms'],
 90            all_vocab_word_forms=set( data['all_vocab_word_forms'] ),
 91            vocab_names=set(data['vocab_names'])
 92        )
 93
 94    def to_file( self, filepath : str | Path ) : 
 95        
 96        data =  {
 97            "core_things_and_concepts" : self.core_things_and_concepts,
 98            "moral_concepts" : self.moral_concepts,
 99            "word_counter" : self.word_counter,
100            "core_integration_counter" : self.core_integration_counter,
101            "moral_integration_counter" : self.moral_integration_counter,
102            "all_core_word_forms"  : list( self.all_core_word_forms ),
103            "all_vocab_word_forms" : list( self.all_vocab_word_forms ),
104            "vocab_word_forms" : self.vocab_word_forms,
105            "vocab_names" : list( self.vocab_names )
106        }
107
108        safe_save( 
109            data=data, 
110            filepath=filepath )
111
112    def update_words( self, words ) :
113
114        self.word_counter.update( words )
115        new_words = list( set( [ w for w in words if not w in self.vocab_word_forms ] ) )
116        new_word_forms = get_word_forms( new_words )
117        self.vocab_word_forms.update( { w : list(forms) for w, forms in new_word_forms.items() } )
118        all_new_forms = [ wf for w, forms in new_word_forms.items() for wf in forms ]
119        self.all_vocab_word_forms.update( all_new_forms )
120
121        self.vocab_names.update( [ word for word in words if word and word[0].isupper() ] )
122
123    def update_core_integrations( self, integrations : list[str] ) :
124        self.core_integration_counter.update( integrations )
125
126    def update_moral_integrations( self, integrations : list[str] ) :
127        self.moral_integration_counter.update( integrations )
128
129    def sample_least_gounded( self, min_k : int, max_k : int, np_rng ) -> list[str] :
130
131        # no boosting single characters, contraction tokens, or names
132        filtered_counts = {k: v for k, v in self.word_counter.items() if ( len(k) > 1 and "'" not in k and k[0].islower() ) }
133
134        if not filtered_counts :
135            return []
136        
137        counts = np.array( list( filtered_counts.values() ), dtype=float )
138        counts = np.where( counts==0, 1.0, counts )
139        probs = ( 1.0 / counts**2 )
140        probs = probs / np.sum( probs )
141
142        k = min( np_rng.integers( min_k, max_k+1 ), len( self.word_counter ) )
143
144        return np_rng.choice(  
145            list( filtered_counts.keys() ), 
146            size=k, 
147            replace=False, 
148            p=probs ).tolist()
149
150    def _sample_integrations( self, counter : Counter, np_rng, min_k : int, max_k : int ) -> list[str] :
151        
152        k = min( len( counter ), np_rng.integers( min_k, max_k+1 ) )
153        chosen = []
154        min_count = min( counter.values() )
155        min_items = [ str(key) for key, count in counter.items()  if count == min_count ]
156        
157        while len( chosen ) < k :
158
159            if len( min_items ) >= k :
160                chosen += np_rng.choice( min_items, size=k, replace=False ).tolist()
161                break
162            else :
163                chosen += min_items 
164                k -= len( min_items )
165                min_count = min( [ val for val in counter.values() if val > min_count ] )
166                min_items = [ key for key, count in counter.items()  if count == min_count ]
167
168        return chosen
169
170    def sample_core_integrations( 
171        self, 
172        np_rng, 
173        min_k : int, 
174        max_k : int,
175        min_extra_creature_integrations : int,
176        max_extra_creature_integrations : int ) -> list[str] :
177
178        core_integrations = self._sample_integrations( 
179            self.core_integration_counter, 
180            np_rng, 
181            min_k=min_k, 
182            max_k=max_k 
183        )
184
185        n_extra_creature_integrations = np_rng.integers( 
186            min_extra_creature_integrations, 
187            max_extra_creature_integrations+1 
188        )
189
190        if max_extra_creature_integrations > 0 :
191            
192            extra_creature_integrations = np_rng.choice(  
193                self.core_things_and_concepts[ 'representative creatures' ],
194                size=n_extra_creature_integrations,
195                replace=False
196            ).tolist()
197
198            core_integrations = list( set( core_integrations + extra_creature_integrations ) )
199
200        return core_integrations 
201
202    def sample_moral_integrations( self, np_rng, min_k : int, max_k : int ) -> list[str] :
203        return self._sample_integrations( self.moral_integration_counter, np_rng, min_k=min_k, max_k=max_k )
204
205    def synonyms( self, word, context : str ) -> list[str] :
206        all_synonyms = synonyms_wsd( word, context )
207        return [ s for s in all_synonyms if s in self.word_counter ]
208
209    def get_word_counts( self, words : list[str] ) -> dict[str, int] : 
210        return {
211            word: self.word_counter.get( word, 0 )
212            for word in set( words )
213        }
214
215    def get_words( self ) -> list[str] : 
216        return list( self.word_counter.keys() ) 
217
218    def get_names( self ) -> set[str] : 
219        return self.vocab_names
220
221    def size( self ) -> int :
222        return len( self.word_counter )
223
224    def has_word( self, word : str ) -> bool : 
225        return word in self.word_counter
226
227    def is_core_word( self, word : str ) -> bool : 
228        return ( 
229            word in self.core_integration_counter or 
230            word in self.moral_integration_counter
231        )
232
233    def is_form_of_core_word( self, word : str ) -> bool : 
234        return word in self.all_core_word_forms
235
236    def is_form_of_vocab_word( self, word : str ) -> bool : 
237        return word in self.all_vocab_word_forms
class AwVocabulary:
 14class AwVocabulary :
 15
 16    def __init__( 
 17        self,
 18        core_things_and_concepts : dict[str,list[str]],
 19        moral_concepts : dict[str,list[str]],
 20        word_counter : Counter | None = None,
 21        core_integration_counter  : Counter | None = None,
 22        moral_integration_counter : Counter | None = None,
 23        all_core_word_forms : set[str] | None = None,
 24        vocab_word_forms : dict[str, list[str] ] | None = None,
 25        all_vocab_word_forms : set[str] | None = None,
 26        vocab_names : set[str] | None = None ) :
 27
 28        self.core_things_and_concepts = core_things_and_concepts
 29        self.moral_concepts = moral_concepts
 30
 31        if word_counter is None :
 32            self.word_counter = Counter()
 33        else :
 34            self.word_counter = word_counter
 35
 36        if core_integration_counter is None :
 37            self.core_integration_counter = Counter( {
 38                integration : 0
 39                for _, category in self.core_things_and_concepts.items() for integration in category
 40            } )
 41        else :
 42            self.core_integration_counter = core_integration_counter
 43
 44        if moral_integration_counter is None :
 45            self.moral_integration_counter = Counter( {
 46                integration : 0
 47                for _, category in self.moral_concepts.items() for integration in category
 48            } )
 49        else :
 50            self.moral_integration_counter = moral_integration_counter
 51
 52        if all_core_word_forms is None :
 53            all_words = set()
 54            for element in list( self.core_integration_counter.keys() ) + list( self.moral_integration_counter.keys() ) :
 55                all_words.update( element.split() )
 56
 57            word_forms = get_word_forms( all_words )
 58            self.all_core_word_forms = set( [ w for _, forms in word_forms.items() for w in forms ] )
 59        else :
 60            self.all_core_word_forms = all_core_word_forms
 61
 62        if all_vocab_word_forms is None :
 63            self.all_vocab_word_forms = set()
 64        else :
 65            self.all_vocab_word_forms = all_vocab_word_forms
 66
 67        if vocab_word_forms is None :
 68            self.vocab_word_forms = dict()
 69        else :
 70            self.vocab_word_forms = vocab_word_forms
 71
 72        if vocab_names is None :
 73            self.vocab_names = set() 
 74        else :
 75            self.vocab_names = vocab_names
 76
 77    @classmethod
 78    def from_file( 
 79        cls, 
 80        filepath : str | Path ) :
 81
 82        data = load_json( filepath )
 83        return cls(
 84            core_things_and_concepts=data['core_things_and_concepts'],
 85            moral_concepts=data[ 'moral_concepts' ],
 86            word_counter=Counter( data['word_counter'] ),
 87            core_integration_counter=Counter( data['core_integration_counter'] ),
 88            moral_integration_counter=Counter( data['moral_integration_counter'] ), 
 89            all_core_word_forms=set( data['all_core_word_forms'] ),
 90            vocab_word_forms=data['vocab_word_forms'],
 91            all_vocab_word_forms=set( data['all_vocab_word_forms'] ),
 92            vocab_names=set(data['vocab_names'])
 93        )
 94
 95    def to_file( self, filepath : str | Path ) : 
 96        
 97        data =  {
 98            "core_things_and_concepts" : self.core_things_and_concepts,
 99            "moral_concepts" : self.moral_concepts,
100            "word_counter" : self.word_counter,
101            "core_integration_counter" : self.core_integration_counter,
102            "moral_integration_counter" : self.moral_integration_counter,
103            "all_core_word_forms"  : list( self.all_core_word_forms ),
104            "all_vocab_word_forms" : list( self.all_vocab_word_forms ),
105            "vocab_word_forms" : self.vocab_word_forms,
106            "vocab_names" : list( self.vocab_names )
107        }
108
109        safe_save( 
110            data=data, 
111            filepath=filepath )
112
113    def update_words( self, words ) :
114
115        self.word_counter.update( words )
116        new_words = list( set( [ w for w in words if not w in self.vocab_word_forms ] ) )
117        new_word_forms = get_word_forms( new_words )
118        self.vocab_word_forms.update( { w : list(forms) for w, forms in new_word_forms.items() } )
119        all_new_forms = [ wf for w, forms in new_word_forms.items() for wf in forms ]
120        self.all_vocab_word_forms.update( all_new_forms )
121
122        self.vocab_names.update( [ word for word in words if word and word[0].isupper() ] )
123
124    def update_core_integrations( self, integrations : list[str] ) :
125        self.core_integration_counter.update( integrations )
126
127    def update_moral_integrations( self, integrations : list[str] ) :
128        self.moral_integration_counter.update( integrations )
129
130    def sample_least_gounded( self, min_k : int, max_k : int, np_rng ) -> list[str] :
131
132        # no boosting single characters, contraction tokens, or names
133        filtered_counts = {k: v for k, v in self.word_counter.items() if ( len(k) > 1 and "'" not in k and k[0].islower() ) }
134
135        if not filtered_counts :
136            return []
137        
138        counts = np.array( list( filtered_counts.values() ), dtype=float )
139        counts = np.where( counts==0, 1.0, counts )
140        probs = ( 1.0 / counts**2 )
141        probs = probs / np.sum( probs )
142
143        k = min( np_rng.integers( min_k, max_k+1 ), len( self.word_counter ) )
144
145        return np_rng.choice(  
146            list( filtered_counts.keys() ), 
147            size=k, 
148            replace=False, 
149            p=probs ).tolist()
150
151    def _sample_integrations( self, counter : Counter, np_rng, min_k : int, max_k : int ) -> list[str] :
152        
153        k = min( len( counter ), np_rng.integers( min_k, max_k+1 ) )
154        chosen = []
155        min_count = min( counter.values() )
156        min_items = [ str(key) for key, count in counter.items()  if count == min_count ]
157        
158        while len( chosen ) < k :
159
160            if len( min_items ) >= k :
161                chosen += np_rng.choice( min_items, size=k, replace=False ).tolist()
162                break
163            else :
164                chosen += min_items 
165                k -= len( min_items )
166                min_count = min( [ val for val in counter.values() if val > min_count ] )
167                min_items = [ key for key, count in counter.items()  if count == min_count ]
168
169        return chosen
170
171    def sample_core_integrations( 
172        self, 
173        np_rng, 
174        min_k : int, 
175        max_k : int,
176        min_extra_creature_integrations : int,
177        max_extra_creature_integrations : int ) -> list[str] :
178
179        core_integrations = self._sample_integrations( 
180            self.core_integration_counter, 
181            np_rng, 
182            min_k=min_k, 
183            max_k=max_k 
184        )
185
186        n_extra_creature_integrations = np_rng.integers( 
187            min_extra_creature_integrations, 
188            max_extra_creature_integrations+1 
189        )
190
191        if max_extra_creature_integrations > 0 :
192            
193            extra_creature_integrations = np_rng.choice(  
194                self.core_things_and_concepts[ 'representative creatures' ],
195                size=n_extra_creature_integrations,
196                replace=False
197            ).tolist()
198
199            core_integrations = list( set( core_integrations + extra_creature_integrations ) )
200
201        return core_integrations 
202
203    def sample_moral_integrations( self, np_rng, min_k : int, max_k : int ) -> list[str] :
204        return self._sample_integrations( self.moral_integration_counter, np_rng, min_k=min_k, max_k=max_k )
205
206    def synonyms( self, word, context : str ) -> list[str] :
207        all_synonyms = synonyms_wsd( word, context )
208        return [ s for s in all_synonyms if s in self.word_counter ]
209
210    def get_word_counts( self, words : list[str] ) -> dict[str, int] : 
211        return {
212            word: self.word_counter.get( word, 0 )
213            for word in set( words )
214        }
215
216    def get_words( self ) -> list[str] : 
217        return list( self.word_counter.keys() ) 
218
219    def get_names( self ) -> set[str] : 
220        return self.vocab_names
221
222    def size( self ) -> int :
223        return len( self.word_counter )
224
225    def has_word( self, word : str ) -> bool : 
226        return word in self.word_counter
227
228    def is_core_word( self, word : str ) -> bool : 
229        return ( 
230            word in self.core_integration_counter or 
231            word in self.moral_integration_counter
232        )
233
234    def is_form_of_core_word( self, word : str ) -> bool : 
235        return word in self.all_core_word_forms
236
237    def is_form_of_vocab_word( self, word : str ) -> bool : 
238        return word in self.all_vocab_word_forms
AwVocabulary( core_things_and_concepts: dict[str, list[str]], moral_concepts: dict[str, list[str]], word_counter: collections.Counter | None = None, core_integration_counter: collections.Counter | None = None, moral_integration_counter: collections.Counter | None = None, all_core_word_forms: set[str] | None = None, vocab_word_forms: dict[str, list[str]] | None = None, all_vocab_word_forms: set[str] | None = None, vocab_names: set[str] | None = None)
16    def __init__( 
17        self,
18        core_things_and_concepts : dict[str,list[str]],
19        moral_concepts : dict[str,list[str]],
20        word_counter : Counter | None = None,
21        core_integration_counter  : Counter | None = None,
22        moral_integration_counter : Counter | None = None,
23        all_core_word_forms : set[str] | None = None,
24        vocab_word_forms : dict[str, list[str] ] | None = None,
25        all_vocab_word_forms : set[str] | None = None,
26        vocab_names : set[str] | None = None ) :
27
28        self.core_things_and_concepts = core_things_and_concepts
29        self.moral_concepts = moral_concepts
30
31        if word_counter is None :
32            self.word_counter = Counter()
33        else :
34            self.word_counter = word_counter
35
36        if core_integration_counter is None :
37            self.core_integration_counter = Counter( {
38                integration : 0
39                for _, category in self.core_things_and_concepts.items() for integration in category
40            } )
41        else :
42            self.core_integration_counter = core_integration_counter
43
44        if moral_integration_counter is None :
45            self.moral_integration_counter = Counter( {
46                integration : 0
47                for _, category in self.moral_concepts.items() for integration in category
48            } )
49        else :
50            self.moral_integration_counter = moral_integration_counter
51
52        if all_core_word_forms is None :
53            all_words = set()
54            for element in list( self.core_integration_counter.keys() ) + list( self.moral_integration_counter.keys() ) :
55                all_words.update( element.split() )
56
57            word_forms = get_word_forms( all_words )
58            self.all_core_word_forms = set( [ w for _, forms in word_forms.items() for w in forms ] )
59        else :
60            self.all_core_word_forms = all_core_word_forms
61
62        if all_vocab_word_forms is None :
63            self.all_vocab_word_forms = set()
64        else :
65            self.all_vocab_word_forms = all_vocab_word_forms
66
67        if vocab_word_forms is None :
68            self.vocab_word_forms = dict()
69        else :
70            self.vocab_word_forms = vocab_word_forms
71
72        if vocab_names is None :
73            self.vocab_names = set() 
74        else :
75            self.vocab_names = vocab_names
core_things_and_concepts
moral_concepts
@classmethod
def from_file(cls, filepath: str | pathlib.Path):
77    @classmethod
78    def from_file( 
79        cls, 
80        filepath : str | Path ) :
81
82        data = load_json( filepath )
83        return cls(
84            core_things_and_concepts=data['core_things_and_concepts'],
85            moral_concepts=data[ 'moral_concepts' ],
86            word_counter=Counter( data['word_counter'] ),
87            core_integration_counter=Counter( data['core_integration_counter'] ),
88            moral_integration_counter=Counter( data['moral_integration_counter'] ), 
89            all_core_word_forms=set( data['all_core_word_forms'] ),
90            vocab_word_forms=data['vocab_word_forms'],
91            all_vocab_word_forms=set( data['all_vocab_word_forms'] ),
92            vocab_names=set(data['vocab_names'])
93        )
def to_file(self, filepath: str | pathlib.Path):
 95    def to_file( self, filepath : str | Path ) : 
 96        
 97        data =  {
 98            "core_things_and_concepts" : self.core_things_and_concepts,
 99            "moral_concepts" : self.moral_concepts,
100            "word_counter" : self.word_counter,
101            "core_integration_counter" : self.core_integration_counter,
102            "moral_integration_counter" : self.moral_integration_counter,
103            "all_core_word_forms"  : list( self.all_core_word_forms ),
104            "all_vocab_word_forms" : list( self.all_vocab_word_forms ),
105            "vocab_word_forms" : self.vocab_word_forms,
106            "vocab_names" : list( self.vocab_names )
107        }
108
109        safe_save( 
110            data=data, 
111            filepath=filepath )
def update_words(self, words):
113    def update_words( self, words ) :
114
115        self.word_counter.update( words )
116        new_words = list( set( [ w for w in words if not w in self.vocab_word_forms ] ) )
117        new_word_forms = get_word_forms( new_words )
118        self.vocab_word_forms.update( { w : list(forms) for w, forms in new_word_forms.items() } )
119        all_new_forms = [ wf for w, forms in new_word_forms.items() for wf in forms ]
120        self.all_vocab_word_forms.update( all_new_forms )
121
122        self.vocab_names.update( [ word for word in words if word and word[0].isupper() ] )
def update_core_integrations(self, integrations: list[str]):
124    def update_core_integrations( self, integrations : list[str] ) :
125        self.core_integration_counter.update( integrations )
def update_moral_integrations(self, integrations: list[str]):
127    def update_moral_integrations( self, integrations : list[str] ) :
128        self.moral_integration_counter.update( integrations )
def sample_least_gounded(self, min_k: int, max_k: int, np_rng) -> list[str]:
130    def sample_least_gounded( self, min_k : int, max_k : int, np_rng ) -> list[str] :
131
132        # no boosting single characters, contraction tokens, or names
133        filtered_counts = {k: v for k, v in self.word_counter.items() if ( len(k) > 1 and "'" not in k and k[0].islower() ) }
134
135        if not filtered_counts :
136            return []
137        
138        counts = np.array( list( filtered_counts.values() ), dtype=float )
139        counts = np.where( counts==0, 1.0, counts )
140        probs = ( 1.0 / counts**2 )
141        probs = probs / np.sum( probs )
142
143        k = min( np_rng.integers( min_k, max_k+1 ), len( self.word_counter ) )
144
145        return np_rng.choice(  
146            list( filtered_counts.keys() ), 
147            size=k, 
148            replace=False, 
149            p=probs ).tolist()
def sample_core_integrations( self, np_rng, min_k: int, max_k: int, min_extra_creature_integrations: int, max_extra_creature_integrations: int) -> list[str]:
171    def sample_core_integrations( 
172        self, 
173        np_rng, 
174        min_k : int, 
175        max_k : int,
176        min_extra_creature_integrations : int,
177        max_extra_creature_integrations : int ) -> list[str] :
178
179        core_integrations = self._sample_integrations( 
180            self.core_integration_counter, 
181            np_rng, 
182            min_k=min_k, 
183            max_k=max_k 
184        )
185
186        n_extra_creature_integrations = np_rng.integers( 
187            min_extra_creature_integrations, 
188            max_extra_creature_integrations+1 
189        )
190
191        if max_extra_creature_integrations > 0 :
192            
193            extra_creature_integrations = np_rng.choice(  
194                self.core_things_and_concepts[ 'representative creatures' ],
195                size=n_extra_creature_integrations,
196                replace=False
197            ).tolist()
198
199            core_integrations = list( set( core_integrations + extra_creature_integrations ) )
200
201        return core_integrations 
def sample_moral_integrations(self, np_rng, min_k: int, max_k: int) -> list[str]:
203    def sample_moral_integrations( self, np_rng, min_k : int, max_k : int ) -> list[str] :
204        return self._sample_integrations( self.moral_integration_counter, np_rng, min_k=min_k, max_k=max_k )
def synonyms(self, word, context: str) -> list[str]:
206    def synonyms( self, word, context : str ) -> list[str] :
207        all_synonyms = synonyms_wsd( word, context )
208        return [ s for s in all_synonyms if s in self.word_counter ]
def get_word_counts(self, words: list[str]) -> dict[str, int]:
210    def get_word_counts( self, words : list[str] ) -> dict[str, int] : 
211        return {
212            word: self.word_counter.get( word, 0 )
213            for word in set( words )
214        }
def get_words(self) -> list[str]:
216    def get_words( self ) -> list[str] : 
217        return list( self.word_counter.keys() ) 
def get_names(self) -> set[str]:
219    def get_names( self ) -> set[str] : 
220        return self.vocab_names
def size(self) -> int:
222    def size( self ) -> int :
223        return len( self.word_counter )
def has_word(self, word: str) -> bool:
225    def has_word( self, word : str ) -> bool : 
226        return word in self.word_counter
def is_core_word(self, word: str) -> bool:
228    def is_core_word( self, word : str ) -> bool : 
229        return ( 
230            word in self.core_integration_counter or 
231            word in self.moral_integration_counter
232        )
def is_form_of_core_word(self, word: str) -> bool:
234    def is_form_of_core_word( self, word : str ) -> bool : 
235        return word in self.all_core_word_forms
def is_form_of_vocab_word(self, word: str) -> bool:
237    def is_form_of_vocab_word( self, word : str ) -> bool : 
238        return word in self.all_vocab_word_forms