refactor: 开始翻新状态机

This commit is contained in:
2026-04-21 12:52:30 +08:00
parent bcdfddce10
commit 9dd6733063
19 changed files with 111 additions and 135 deletions

View File

@@ -3,9 +3,9 @@
Reactor 是 HeurAMS 的记忆流程状态机模块, 和界面 (interface) 的实现是解耦的, 以便后期与其他框架的适配.\
得益于 Pickle, 状态机模块支持快照!
## Phaser - 全局阶段控制器
## Router - 全局阶段控制器
在一次队列记忆流程中, Phaser 代表记忆流程本身.
在一次队列记忆流程中, Router 代表记忆流程本身.
### 属性
@@ -25,7 +25,7 @@ Reactor 是 HeurAMS 的记忆流程状态机模块, 和界面 (interface) 的实
在初始化 Procession 时, 每个 Procession 被赋予一个不重复的状态属性 作为"阶段状态"属性, 以此标识 Procession 的阶段属性, 因为每个 Procession 管理一个阶段下的复习进程.
你可以用 state 属性获取 Phaser 的当前状态.
你可以用 state 属性获取 Router 的当前状态.
#### Procession 属性
@@ -34,26 +34,26 @@ Reactor 是 HeurAMS 的记忆流程状态机模块, 和界面 (interface) 的实
### 初始化
Phaser 接受一个存储 Atom 对象的列表, 作为组织记忆流程的材料\
Router 接受一个存储 Atom 对象的列表, 作为组织记忆流程的材料\
在内部, 根据是否激活将其分为 new_atoms 与 old_atoms.\
因此, 如果你传入的列表中有算法上"无所事事"的 Atom, 流程会对其进行"加强复习"
由此创建 Procession.
### 直接输出呈现形式
Phaser 的 __repr__ 定义了此对象"官方的显示"用作直观的调试.\
Router 的 __repr__ 定义了此对象"官方的显示"用作直观的调试.\
其以 ascii 表格形式输出, 格式也符合 markdown 表格规范, 你可以直接复制到 markdown.\
示例:
```text
| Type | State | Processions | Current Procession |
|:-------|:--------|:-----------------------|:---------------------|
| Phaser | unsure | ['新记忆', '总体复习'] | 新记忆 |
| Type | State | Processions | Current Procession |
| :----- | :----- | :--------------------- | :----------------- |
| Router | unsure | ['新记忆', '总体复习'] | 新记忆 |
```
| Type | State | Processions | Current Procession |
|:-------|:--------|:-----------------------|:---------------------|
| Phaser | unsure | ['新记忆', '总体复习'] | 新记忆 |
| Type | State | Processions | Current Procession |
| :----- | :----- | :--------------------- | :----------------- |
| Router | unsure | ['新记忆', '总体复习'] | 新记忆 |
### 方法
@@ -85,29 +85,29 @@ Phaser 的 __repr__ 定义了此对象"官方的显示"用作直观的调试.\
- cursor: 指针, 是当前原子在 atoms 列表中的索引
- phase: "阶段属性"
> 注意区分 "Phaser" 和 "Phase", 其中 "Phase" 表示 "Phaser State".
> 注意区分 "Router" 和 "Phase", 其中 "Phase" 表示 "Router State".
- name\_: 阶段的命名
- state: 当前状态属性
### 初始化
接受一个 atoms 列表与 phase_state (PhaserState Enum 类型)对象
接受一个 atoms 列表与 phase_state (RouterState Enum 类型)对象
### 直接输出呈现形式
Phaser, 但显示数据有所不同\
Phaser 不同, Procession 显示队列会对过长的 atom.ident 进行缩略(末尾 `>` 符号)
Router, 但显示数据有所不同\
Router 不同, Procession 显示队列会对过长的 atom.ident 进行缩略(末尾 `>` 符号)
```text
| Type | Name | State | Progress | Queue | Current Atom |
|:-----------|:-------|:--------|:-----------|:-----------------------|:------------------------------|
| Procession | 新记忆 | active | 1 / 2 | ['秦孝公>', '君臣固>'] | 秦孝公据崤函之固, 拥雍州之地, |
| Type | Name | State | Progress | Queue | Current Atom |
| :--------- | :----- | :----- | :------- | :--------------------- | :---------------------------- |
| Procession | 新记忆 | active | 1 / 2 | ['秦孝公>', '君臣固>'] | 秦孝公据崤函之固, 拥雍州之地, |
```
| Type | Name | State | Progress | Queue | Current Atom |
|:-----------|:-------|:--------|:-----------|:-----------------------|:------------------------------|
| Procession | 新记忆 | active | 1 / 2 | ['秦孝公>', '君臣固>'] | 秦孝公据崤函之固, 拥雍州之地, |
| Type | Name | State | Progress | Queue | Current Atom |
| :--------- | :----- | :----- | :------- | :--------------------- | :---------------------------- |
| Procession | 新记忆 | active | 1 / 2 | ['秦孝公>', '君臣固>'] | 秦孝公据崤函之固, 拥雍州之地, |
### 方法
@@ -142,11 +142,11 @@ Phaser 的 __repr__ 定义了此对象"官方的显示"用作直观的调试.\
判断是否为空队列(传入原子列表对象是空列表的队列)
#### get_fission(self)
#### get_expander(self)
获取当前原子的 Fission 对象, 用于单原子调度展开
获取当前原子的 Expander 对象, 用于单原子调度展开
## Fission - 单原子调度控制器
## Expander - 单原子调度控制器
### 属性

View File

@@ -1,8 +1,8 @@
from heurams.services.logger import get_logger
from .fission import Fission
from .phaser import Phaser
from .expander import Expander
from .router import Router
from .procession import Procession
from .states import PhaserState, ProcessionState
from .states import RouterState, ProcessionState
__all__ = ["PhaserState", "ProcessionState", "Procession", "Fission", "Phaser"]
__all__ = ["RouterState", "ProcessionState", "Procession", "Expander", "Router"]

View File

@@ -8,39 +8,39 @@ import heurams.kernel.particles as pt
import heurams.kernel.puzzles as puz
from heurams.services.logger import get_logger
from .states import FissionState, PhaserState
from .states import ExpanderState, RouterState
logger = get_logger(__name__)
class Fission(Machine):
class Expander(Machine):
"""单原子调度展开器"""
def __init__(self, atom: pt.Atom, phase=PhaserState.RECOGNITION):
def __init__(self, atom: pt.Atom, phase=RouterState.RECOGNITION):
self.phase = phase
self.cursor = 0
self.atom = atom
self.current_puzzle_inf: dict
# phase 为 PhaserState 枚举实例, 需要获取其value
# phase 为 RouterState 枚举实例, 需要获取其value
phase_value = phase.value
states = [
{"name": FissionState.EXAMMODE.value},
{"name": FissionState.RETRONLY.value},
{"name": ExpanderState.EXAMMODE.value},
{"name": ExpanderState.RETRONLY.value},
]
transitions = [
{
"trigger": "finish",
"source": FissionState.EXAMMODE.value,
"dest": FissionState.RETRONLY.value,
"source": ExpanderState.EXAMMODE.value,
"dest": ExpanderState.RETRONLY.value,
},
]
if phase == PhaserState.FINISHED:
if phase == RouterState.FINISHED:
Machine.__init__(
self,
states=states,
transitions=transitions,
initial=FissionState.EXAMMODE.value,
initial=ExpanderState.EXAMMODE.value,
)
return
orbital_schedule = atom.registry["orbital"]["phases"][phase_value] # type: ignore
@@ -81,7 +81,7 @@ class Fission(Machine):
self,
states=states,
transitions=transitions,
initial=FissionState.EXAMMODE.value,
initial=ExpanderState.EXAMMODE.value,
)
def get_puzzles_inf(self):
@@ -118,7 +118,7 @@ class Fission(Machine):
dic = [
{
"Type": "Fission",
"Type": "Expander",
"Atom": truncate(self.atom.ident),
"State": self.state,
"Progress": f"{self.cursor + 1} / {len(self.puzzles_inf)}",

View File

@@ -4,8 +4,8 @@ from transitions import Machine
import heurams.kernel.particles as pt
from heurams.services.logger import get_logger
from .fission import Fission
from .states import PhaserState, ProcessionState
from .expander import Expander
from .states import RouterState, ProcessionState
logger = get_logger(__name__)
@@ -13,7 +13,7 @@ logger = get_logger(__name__)
class Procession(Machine):
"""队列: 标识单次记忆流程"""
def __init__(self, atoms: list, phase_state: PhaserState, name_: str = ""):
def __init__(self, atoms: list, phase_state: RouterState, name_: str = ""):
logger.debug(
"Procession.__init__: 原子数量=%d, phase=%s, name='%s'",
len(atoms),
@@ -113,8 +113,8 @@ class Procession(Machine):
logger.debug("Procession.is_empty: %s", empty)
return empty
def get_fission(self):
return Fission(atom=self.current_atom, phase=self.phase) # type: ignore
def get_expander(self):
return Expander(atom=self.current_atom, phase=self.phase) # type: ignore
def __repr__(self, style="pipe", ends="\n"):
from heurams.services.textproc import truncate

View File

@@ -5,16 +5,16 @@ from heurams.kernel.particles.placeholders import AtomPlaceholder
from heurams.services.logger import get_logger
from .procession import Procession
from .states import PhaserState, ProcessionState
from .states import RouterState, ProcessionState
logger = get_logger(__name__)
class Phaser(Machine):
class Router(Machine):
"""全局调度阶段管理器"""
def __init__(self, atoms: list[pt.Atom]) -> None:
logger.debug("Phaser.__init__: 原子数量=%d", len(atoms))
logger.debug("Router.__init__: 原子数量=%d", len(atoms))
self.atoms = atoms
new_atoms = list()
@@ -32,50 +32,50 @@ class Phaser(Machine):
# TODO: 改进为基于配置文件的可选复习阶段
if len(old_atoms):
self.processions.append(
Procession(old_atoms, PhaserState.QUICK_REVIEW, "初始复习")
Procession(old_atoms, RouterState.QUICK_REVIEW, "初始复习")
)
logger.debug("创建初始复习 Procession")
if len(new_atoms):
self.processions.append(
Procession(new_atoms, PhaserState.RECOGNITION, "新记忆")
Procession(new_atoms, RouterState.RECOGNITION, "新记忆")
)
logger.debug("创建新记忆 Procession")
self.processions.append(Procession(atoms, PhaserState.FINAL_REVIEW, "总体复习"))
self.processions.append(Procession(atoms, RouterState.FINAL_REVIEW, "总体复习"))
logger.debug("创建总体复习 Procession")
logger.debug("Phaser 初始化完成, processions 数量=%d", len(self.processions))
logger.debug("Router 初始化完成, processions 数量=%d", len(self.processions))
# 设置transitions状态机
states = [
{"name": PhaserState.UNSURE.value, "on_enter": "on_unsure"},
{"name": PhaserState.QUICK_REVIEW.value, "on_enter": "on_quick_review"},
{"name": PhaserState.RECOGNITION.value, "on_enter": "on_recognition"},
{"name": PhaserState.FINAL_REVIEW.value, "on_enter": "on_final_review"},
{"name": PhaserState.FINISHED.value, "on_enter": "on_finished"},
{"name": RouterState.UNSURE.value, "on_enter": "on_unsure"},
{"name": RouterState.QUICK_REVIEW.value, "on_enter": "on_quick_review"},
{"name": RouterState.RECOGNITION.value, "on_enter": "on_recognition"},
{"name": RouterState.FINAL_REVIEW.value, "on_enter": "on_final_review"},
{"name": RouterState.FINISHED.value, "on_enter": "on_finished"},
]
transitions = [
{"trigger": "to_unsure", "source": "*", "dest": PhaserState.UNSURE.value},
{"trigger": "to_unsure", "source": "*", "dest": RouterState.UNSURE.value},
{
"trigger": "to_quick_review",
"source": "*",
"dest": PhaserState.QUICK_REVIEW.value,
"dest": RouterState.QUICK_REVIEW.value,
},
{
"trigger": "to_recognition",
"source": "*",
"dest": PhaserState.RECOGNITION.value,
"dest": RouterState.RECOGNITION.value,
},
{
"trigger": "to_final_review",
"source": "*",
"dest": PhaserState.FINAL_REVIEW.value,
"dest": RouterState.FINAL_REVIEW.value,
},
{
"trigger": "to_finished",
"source": "*",
"dest": PhaserState.FINISHED.value,
"dest": RouterState.FINISHED.value,
},
]
@@ -83,45 +83,45 @@ class Phaser(Machine):
self,
states=states,
transitions=transitions,
initial=PhaserState.UNSURE.value,
initial=RouterState.UNSURE.value,
)
self.to_unsure()
def on_unsure(self):
"""进入UNSURE状态时的回调"""
logger.debug("Phaser 进入 UNSURE 状态")
logger.debug("Router 进入 UNSURE 状态")
def on_quick_review(self):
"""进入QUICK_REVIEW状态时的回调"""
logger.debug("Phaser 进入 QUICK_REVIEW 状态")
logger.debug("Router 进入 QUICK_REVIEW 状态")
def on_recognition(self):
"""进入RECOGNITION状态时的回调"""
logger.debug("Phaser 进入 RECOGNITION 状态")
logger.debug("Router 进入 RECOGNITION 状态")
def on_final_review(self):
"""进入FINAL_REVIEW状态时的回调"""
logger.debug("Phaser 进入 FINAL_REVIEW 状态")
logger.debug("Router 进入 FINAL_REVIEW 状态")
def on_finished(self):
"""进入FINISHED状态时的回调"""
for i in self.atoms:
i.lock(1)
i.revise()
logger.debug("Phaser 进入 FINISHED 状态")
logger.debug("Router 进入 FINISHED 状态")
def current_procession(self):
logger.debug("Phaser.current_procession 被调用")
logger.debug("Router.current_procession 被调用")
for i in self.processions:
i: Procession
if i.state != ProcessionState.FINISHED.value:
# if i.phase == PhaserState.UNSURE: 此判断是不必要的 因为没有这种 Procession
if i.phase == PhaserState.QUICK_REVIEW:
# if i.phase == RouterState.UNSURE: 此判断是不必要的 因为没有这种 Procession
if i.phase == RouterState.QUICK_REVIEW:
self.to_quick_review()
elif i.phase == PhaserState.RECOGNITION:
elif i.phase == RouterState.RECOGNITION:
self.to_recognition()
elif i.phase == PhaserState.FINAL_REVIEW:
elif i.phase == RouterState.FINAL_REVIEW:
self.to_final_review()
logger.debug("找到未完成的 Procession: phase=%s", i.phase)
@@ -130,7 +130,7 @@ class Phaser(Machine):
# 所有Procession都已完成
self.to_finished()
logger.debug("所有 Procession 已完成, 状态设置为 FINISHED")
return Procession([AtomPlaceholder()], PhaserState.FINISHED)
return Procession([AtomPlaceholder()], RouterState.FINISHED)
def __repr__(self, style="pipe", ends="\n"):
from tabulate import tabulate as tabu
@@ -139,7 +139,7 @@ class Phaser(Machine):
lst = [
{
"Type": "Phaser",
"Type": "Router",
"State": self.state,
"Processions": list(map(lambda f: (f.name_), self.processions)),
"Current Procession": "None" if not self.current_procession() else self.current_procession().name_, # type: ignore

View File

@@ -5,7 +5,7 @@ from heurams.services.logger import get_logger
logger = get_logger(__name__)
class PhaserState(Enum):
class RouterState(Enum):
UNSURE = "unsure"
QUICK_REVIEW = "quick_review"
RECOGNITION = "recognition"
@@ -18,7 +18,7 @@ class ProcessionState(Enum):
FINISHED = "finished"
class FissionState(Enum):
class ExpanderState(Enum):
EXAMMODE = "exammode"
RETRONLY = "retronly"