Move markov nodes to be single strings

Separating strings by spaces is more memory-friendly than using tuples.

Signed-off-by: Alek Ratzloff <alekratz@gmail.com>
This commit is contained in:
2022-05-27 18:41:17 -07:00
parent b4857e3b4a
commit cc30df8706

View File

@@ -21,7 +21,7 @@ def chain_inner_default() -> defaultdict[str | None, int]:
return defaultdict(int) return defaultdict(int)
def chain_default() -> defaultdict[tuple[str, ...], defaultdict[str | None, int]]: def chain_default() -> defaultdict[str, defaultdict[str | None, int]]:
return defaultdict(chain_inner_default) return defaultdict(chain_inner_default)
@@ -51,11 +51,11 @@ class Chain:
return return
self.__load() self.__load()
for fragment in windows(parts + [None], self.order + 1): for fragment in windows(parts + [None], self.order + 1):
head = tuple(fragment[0:-1]) head = fragment[0:-1]
tail = fragment[-1] tail = fragment[-1]
self.__cache[head][tail] += 1 self.__cache[" ".join(head)][tail] += 1
def get(self, key: tuple[str, ...]) -> dict[str | None, int]: def get(self, key: str) -> dict[str | None, int]:
self.__last_access = asyncio.get_running_loop().time() self.__last_access = asyncio.get_running_loop().time()
if self.__cache: if self.__cache:
if key in self.__cache: if key in self.__cache:
@@ -67,7 +67,7 @@ class Chain:
self.__load() self.__load()
return self.__cache[key] return self.__cache[key]
def set(self, key: tuple[str, ...], value: Mapping[str | None, int]): def set(self, key: str, value: Mapping[str | None, int]):
self.__last_access = asyncio.get_running_loop().time() self.__last_access = asyncio.get_running_loop().time()
if not self.__cache: if not self.__cache:
# Attempt the cache before writing to it # Attempt the cache before writing to it
@@ -85,7 +85,7 @@ class Chain:
self.__cache = defaultdict( self.__cache = defaultdict(
chain_inner_default, chain_inner_default,
{ {
tuple(key.split(" ")): defaultdict( key: defaultdict(
int, int,
{ {
(None if not word else word): weight (None if not word else word): weight
@@ -107,7 +107,7 @@ class Chain:
with open(self.path, "w") as fp: with open(self.path, "w") as fp:
json.dump( json.dump(
{ {
" ".join(key): { key: {
("" if word is None else word): weight ("" if word is None else word): weight
for word, weight in value.items() for word, weight in value.items()
} }
@@ -131,17 +131,16 @@ class Chain:
words: List[str] = [] words: List[str] = []
node = random.choice(list(self.__cache.keys())) node = random.choice(list(self.__cache.keys())).split(" ")
words += node words += node
next: str | None = self.choose_next(node) next: str | None = self.choose_next(" ".join(node))
while next: while next:
words += [next] words += [next]
node = (*node[1:], next) node = [*node[1:], next]
next = self.choose_next(node) next = self.choose_next(" ".join(node))
return " ".join(words) return " ".join(words)
def choose_next(self, head: tuple[str, ...]) -> str | None: def choose_next(self, head: str) -> str | None:
self.__load() self.__load()
choices = self.__cache[head] choices = self.__cache[head]
words = list(choices.keys()) words = list(choices.keys())