diff --git a/src/heurams/kernel/algorithms/__init__.py b/src/heurams/kernel/algorithms/__init__.py new file mode 100644 index 0000000..86c6f3e --- /dev/null +++ b/src/heurams/kernel/algorithms/__init__.py @@ -0,0 +1,33 @@ +from typing import Dict, Any, Callable, TypedDict + +class AlgorithmConfig(TypedDict): + algo_name: str + defaults: Dict[str, Any] + revisor: Callable[[dict, int, bool], None] + +_algorithms: Dict[str, AlgorithmConfig] = {} + +def register_algorithm(algo_name: str, defaults: Dict[str, Any], revisor: Callable): + _algorithms[algo_name] = { + 'algo_name': algo_name, + 'defaults': defaults, + 'revisor': revisor + } + +def get_algorithm(algo_name: str) -> AlgorithmConfig: + if algo_name not in _algorithms: + raise ValueError(f"算法 {algo_name}' 未找到, 可用值: {list_algorithms()}") + return _algorithms[algo_name] + +def list_algorithms() -> list[str]: + return list(_algorithms.keys()) + +# 导入注册 +from . import supermemo2 +register_algorithm( + algo_name=supermemo2.algo_name, + defaults=supermemo2.defaults, + revisor=supermemo2.revisor +) + +__all__ = ['get_algorithm', 'list_algorithms', 'register_algorithm', 'AlgorithmConfig'] \ No newline at end of file diff --git a/src/heurams/kernel/algorithms/fsrs.devel.py b/src/heurams/kernel/algorithms/fsrs.devel.py new file mode 100644 index 0000000..e69de29 diff --git a/src/heurams/kernel/algorithms/supermemo2.py b/src/heurams/kernel/algorithms/supermemo2.py new file mode 100644 index 0000000..3bf5093 --- /dev/null +++ b/src/heurams/kernel/algorithms/supermemo2.py @@ -0,0 +1,66 @@ +import heurams.services.timer as timer +from typing import TypedDict + +algo_name = "supermemo2" + +class AlgodataDict(TypedDict): + efactor: float + real_rept: int + rept: int + interval: int + last_date: int + next_date: int + is_activated: int + last_modify: float + +defaults = { + 'efactor': 2.5, + 'real_rept': 0, + 'rept': 0, + 'interval': 0, + 'last_date': 0, + 'next_date': 0, + 'is_activated': 0, + 'last_modify': timer.get_timestamp() +} + +def revisor(algodata: dict, feedback: int = 5, is_new_activation: bool = False): + """SM-2 算法迭代决策机制实现 + 根据 quality(0 ~ 5) 进行参数迭代最佳间隔 + quality 由主程序评估 + + Args: + quality (int): 记忆保留率量化参数 + """ + if feedback == -1: + return + + algodata[algo_name]['efactor'] = algodata[algo_name]['efactor'] + ( + 0.1 - (5 - feedback) * (0.08 + (5 - feedback) * 0.02) + ) + algodata[algo_name]['efactor'] = max(1.3, algodata[algo_name]['efactor']) + + if feedback < 3: + algodata[algo_name]['rept'] = 0 + algodata[algo_name]['interval'] = 0 + else: + algodata[algo_name]['rept'] += 1 + + algodata[algo_name]['real_rept'] += 1 + + if is_new_activation: + algodata[algo_name]['rept'] = 0 + algodata[algo_name]['efactor'] = 2.5 + + if algodata[algo_name]['rept'] == 0: + algodata[algo_name]['interval'] = 1 + elif algodata[algo_name]['rept'] == 1: + algodata[algo_name]['interval'] = 6 + else: + algodata[algo_name]['interval'] = round( + algodata[algo_name]['interval'] * algodata[algo_name]['efactor'] + ) + + algodata[algo_name]['last_date'] = timer.get_daystamp() + algodata[algo_name]['next_date'] = timer.get_daystamp() + algodata[algo_name]['interval'] + algodata[algo_name]['last_modify'] = timer.get_timestamp() \ No newline at end of file diff --git a/src/heurams/kernel/particles/atom.py b/src/heurams/kernel/particles/atom.py index 5483f6a..4eedf0a 100644 --- a/src/heurams/kernel/particles/atom.py +++ b/src/heurams/kernel/particles/atom.py @@ -1,10 +1,22 @@ from .electron import Electron from .nucleon import Nucleon +from typing import TypedDict import pathlib import typing import toml import json +class AtomRegister(TypedDict): + nucleon: Nucleon + nucleon_path: pathlib.Path + nucleon_fmt: str + electron: Electron + electron_path: pathlib.Path + electron_fmt: str + orbital: dict + orbital_path: pathlib.Path + orbital_fmt: str + class Atom(): """ 统一处理一系列对象的所有信息与持久化: @@ -14,9 +26,11 @@ class Atom(): 以及关联路径 """ + + def __init__(self, ident = ""): self.ident = ident - self.register = { + self.register: AtomRegister = { # type: ignore "nucleon": None, "nucleon_path": None, "nucleon_fmt": "toml", @@ -49,6 +63,17 @@ class Atom(): raise KeyError("不受支持的持久化格式") else: raise TypeError("对未初始化的路径对象操作") + + def __getitem__(self, key): + if key in self.register: + return self.register[key] + raise KeyError(f"不支持的键: {key}") + + def __setitem__(self, key, value): + if key in self.register: + self.register[key] = value + else: + raise KeyError(f"不支持的键: {key}") @staticmethod def placeholder(): diff --git a/src/heurams/kernel/particles/electron.py b/src/heurams/kernel/particles/electron.py index b51e350..45ea2de 100644 --- a/src/heurams/kernel/particles/electron.py +++ b/src/heurams/kernel/particles/electron.py @@ -1,49 +1,40 @@ import heurams.services.timer as timer from heurams.context import config_var +from heurams.kernel.algorithms import get_algorithm class Electron: """电子: 记忆分析元数据及算法""" - algo = "SM-2" - def __init__(self, ident: str, algodata: dict = {}): + def __init__(self, ident: str, algodata: dict = {}, algo: str = "supermemo2"): """初始化电子对象 (记忆数据) Args: ident: 算法的唯一标识符, 用于区分不同的算法实例, 使用 algodata[ident] 获取 algodata: 算法数据字典, 包含算法的各项参数和设置 + algo: 使用的算法模块标识 """ self.algodata = algodata self.ident = ident + self.algo = algo + + algorithm_config = get_algorithm(self.algo) + if self.algo not in self.algodata.keys(): self.algodata[self.algo] = {} - if algodata[self.algo] == {}: - self._default_init() + if not self.algodata[self.algo]: + self._default_init(algorithm_config['defaults']) - def _default_init(self): - """默认初始化包装 - """ - defaults = { - 'efactor': 2.5, # 易度系数, 越大越简单, 最大为5 - 'real_rept': 0, # (实际)重复次数 - 'rept': 0, # (有效)重复次数 - 'interval': 0, # 最佳间隔 - 'last_date': 0, # 上一次复习的时间戳 - 'next_date': 0, # 将要复习的时间戳 - 'is_activated': 0, # 激活状态 - # *NOTE: 此处"时间戳"是以天为单位的整数, 即 UNIX 时间戳除以一天的秒数取整 - 'last_modify': timer.get_timestamp() # 最后修改时间戳(此处是UNIX时间戳) - } - self.algodata[self.algo] = defaults + def _default_init(self, defaults: dict): + """默认初始化包装""" + self.algodata[self.algo] = defaults.copy() def activate(self): - """激活此电子 - """ + """激活此电子""" self.algodata[self.algo]['is_activated'] = 1 self.algodata[self.algo]['last_modify'] = timer.get_timestamp() def modify(self, var: str, value): - """修改 algodata[algo] 中子字典数据 - """ + """修改 algodata[algo] 中子字典数据""" if var in self.algodata[self.algo]: self.algodata[self.algo][var] = value self.algodata[self.algo]['last_modify'] = timer.get_timestamp() @@ -51,52 +42,20 @@ class Electron: print(f"警告: '{var}' 非已知元数据字段") def revisor(self, quality: int = 5, is_new_activation: bool = False): - """SM-2 算法迭代决策机制实现 - 根据 quality(0 ~ 5) 进行参数迭代最佳间隔 - quality 由主程序评估 - + """算法迭代决策机制实现 + Args: - quality (int): 记忆保留率量化参数 + quality (int): 记忆保留率量化参数 (0-5) + is_new_activation (bool): 是否为初次激活 """ - print(f"REVISOR: {quality}, {is_new_activation}") - if quality == -1: - return -1 - - self.algodata[self.algo]['efactor'] = self.algodata[self.algo]['efactor'] + ( - 0.1 - (5 - quality) * (0.08 + (5 - quality) * 0.02) - ) - self.algodata[self.algo]['efactor'] = max(1.3, self.algodata[self.algo]['efactor']) - - if quality < 3: - # 若保留率低于 3,重置重复次数 - self.algodata[self.algo]['rept'] = 0 - self.algodata[self.algo]['interval'] = 0 # 设为0,以便下面重新计算 I(1) - else: - self.algodata[self.algo]['rept'] += 1 - - self.algodata[self.algo]['real_rept'] += 1 - - if is_new_activation: # 初次激活 - self.algodata[self.algo]['rept'] = 0 - self.algodata[self.algo]['efactor'] = 2.5 - - if self.algodata[self.algo]['rept'] == 0: # 刚被重置或初次激活后复习 - self.algodata[self.algo]['interval'] = 1 # I(1) - elif self.algodata[self.algo]['rept'] == 1: - self.algodata[self.algo]['interval'] = 6 # I(2) 经验公式 - else: - self.algodata[self.algo]['interval'] = round( - self.algodata[self.algo]['interval'] * self.algodata[self.algo]['efactor'] - ) - - self.algodata[self.algo]['last_date'] = timer.get_daystamp() - self.algodata[self.algo]['next_date'] = timer.get_daystamp() + self.algodata[self.algo]['interval'] - self.algodata[self.algo]['last_modify'] = timer.get_timestamp() + algorithm_config = get_algorithm(self.algo) + algorithm_config['revisor'](self.algodata, quality, is_new_activation) def __str__(self): return ( f"记忆单元预览 \n" f"标识符: '{self.ident}' \n" + f"算法: {self.algo} \n" f"易度系数: {self.algodata[self.algo]['efactor']:.2f} \n" f"已经重复的次数: {self.algodata[self.algo]['rept']} \n" f"下次间隔: {self.algodata[self.algo]['interval']} 天 \n" @@ -126,12 +85,10 @@ class Electron: self.algodata[self.algo]['last_modify'] = timer.get_timestamp() def __len__(self): - """仅返回当前算法的配置数量 - """ + """仅返回当前算法的配置数量""" return len(self.algodata[self.algo]) @staticmethod def placeholder(): - """生成一个电子占位符 - """ - return Electron("电子对象样例内容", {}) + """生成一个电子占位符""" + return Electron("电子对象样例内容", {}) \ No newline at end of file diff --git a/src/heurams/kernel/puzzles/selection.py b/src/heurams/kernel/puzzles/mcq.py similarity index 100% rename from src/heurams/kernel/puzzles/selection.py rename to src/heurams/kernel/puzzles/mcq.py diff --git a/src/heurams/kernel/reactor/reactor.py b/src/heurams/kernel/reactor/core.py similarity index 85% rename from src/heurams/kernel/reactor/reactor.py rename to src/heurams/kernel/reactor/core.py index 75cc82c..ac5b409 100644 --- a/src/heurams/kernel/reactor/reactor.py +++ b/src/heurams/kernel/reactor/core.py @@ -5,7 +5,38 @@ import heurams.services.timer as timer from typing import Tuple from .apparatus import Apparatus -class Reactor(): +class Core(): + """堆芯: 记忆流程核心状态机""" + def __init__(self, atoms: list, stage = ""): + self.atoms = atoms + self.queue = atoms.copy() + self.current_atom = atoms[0] + self.cursor = 0 + + def forward(self, step = 1): + self.cursor += step + try: + self.current_atom = self.queue[self.cursor] + return 1 # 成功 + except IndexError: + return 0 + + def append(self, atom): + self.queue.append(self.current_atom) + + def __len__(self): + return (len(self.queue) - self.cursor) + + def is_empty(self): + return len(self.queue) + +class Fission(): + """裂变器: 单原子调度展开器""" + def __init__(self, atom: pt.Atom): + self.atom = atom + atom.register["orbital"] + +class Reactork(): """反应堆对象, 处理和分配一次文件记忆流程的资源与策略""" def __init__(self, nucleon_file: pt.NucleonUnion, electron_file: pt.ElectronUnion, screen, tasked_num): # 导入原子对象 diff --git a/src/heurams/kernel/reactor/rounds.py b/src/heurams/kernel/reactor/rounds.py deleted file mode 100644 index 39e0db0..0000000 --- a/src/heurams/kernel/reactor/rounds.py +++ /dev/null @@ -1 +0,0 @@ -# 轮次编排 \ No newline at end of file diff --git a/src/heurams/kernel/reactor/rtk.py b/src/heurams/kernel/reactor/rtk.py deleted file mode 100644 index 8d5d270..0000000 --- a/src/heurams/kernel/reactor/rtk.py +++ /dev/null @@ -1,11 +0,0 @@ -# 核心流程状态机 - -import heurams.kernel.particles as pt -import heurams.services.timer as timer -from typing import Tuple -from .apparatus import Apparatus - -class Reactor(): - def __init__(self, atoms): - # atoms 是原子列表 - \ No newline at end of file