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
@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
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