feat: 改进对象系统

This commit is contained in:
2026-01-01 20:18:18 +08:00
parent 94839c6369
commit 9b32a01a10
39 changed files with 682 additions and 180 deletions

View File

@@ -1,18 +1,18 @@
# [调试] 将更改保存到文件 # [调试] 将更改保存到文件
#persist_to_file = 1 persist_to_file = 1
# [调试] 覆写时间, 设为 -1 以禁用 # [调试] 覆写时间, 设为 -1 以禁用
#daystamp_override = -1 daystamp_override = -1
#timestamp_override = -1 timestamp_override = -1
# [调试] 一键通过 # [调试] 一键通过
#quick_pass = 1 quick_pass = 1
# 对于每个项目的默认新记忆原子数量 # 对于每个项目的默认新记忆原子数量
#scheduled_num = 8 scheduled_num = 8
# UTC 时间戳修正 仅用于 UNIX 日时间戳的生成修正, 单位为秒 # UTC 时间戳修正 仅用于 UNIX 日时间戳的生成修正, 单位为秒
#timezone_offset = +28800 # 中国标准时间 (UTC+8) timezone_offset = +28800 # 中国标准时间 (UTC+8)
[interface] [interface]

366
examples/repo.ipynb Normal file
View File

@@ -0,0 +1,366 @@
{
"cells": [
{
"cell_type": "markdown",
"id": "51b89355",
"metadata": {},
"source": [
"# 演练场\n",
"此笔记本将带你了解 repomgr 与 particles 对象相关操作"
]
},
{
"cell_type": "markdown",
"id": "f5c49014",
"metadata": {},
"source": [
"# 从一个例子开始\n",
"## 了解文件结构\n",
"了解一下文件结构"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "a5ed9864",
"metadata": {},
"outputs": [],
"source": [
"!tree # 了解文件结构"
]
},
{
"cell_type": "markdown",
"id": "4e10922b",
"metadata": {},
"source": [
"如果你先前运行了单元格, 请运行下面一格清理."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "9777730e",
"metadata": {},
"outputs": [],
"source": [
"!rm -rf test_new_repo\n",
"!rm -rf heurams.log*"
]
},
{
"cell_type": "markdown",
"id": "058c098f",
"metadata": {},
"source": [
"## 导入模块\n",
"导入所需模块, 你会看到欢迎信息, 标示了库所使用的配置. \n",
"HeurAMS 在基础设施也使用配置文件实现隐式的依赖注入. "
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "bf1b00c8",
"metadata": {},
"outputs": [],
"source": [
"import heurams.kernel.repolib as repolib # 这是 RepoLib 子模块, 用于管理和结构化 repo(中文含义: 仓库) 数据结构与本地文件间的联系\n",
"import heurams.kernel.particles as pt # 这是 Particles(中文含义: 粒子) 子模块, 用于运行时的记忆管理操作\n",
"from pathlib import Path # 这是 Python 的 Pathlib 模块, 用于表示文件路径, 在整个项目中, 都使用此模块表示路径"
]
},
{
"cell_type": "markdown",
"id": "ea1f68bb",
"metadata": {},
"source": [
"## 运行时检查\n",
"如你所见, repo 在文件系统内存储为一个文件夹. \n",
"因此在载入之前, 首先要检查这是否是一个合乎标准的 repo 文件夹. "
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "897b62d7",
"metadata": {},
"outputs": [],
"source": [
"is_vaild = repolib.Repo.check_repodir(Path(\"./test_repo\"))\n",
"print(f\"这是一个 {'合规' if is_vaild else '不合规'} 的 repo!\")"
]
},
{
"cell_type": "markdown",
"id": "24a19991",
"metadata": {},
"source": [
"## 加载仓库\n",
"接下来, 正式加载 repo."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "708ae7e4",
"metadata": {},
"outputs": [],
"source": [
"test_repo = repolib.Repo.create_from_repodir(Path(\"./test_repo\"))"
]
},
{
"cell_type": "markdown",
"id": "474f8eb7",
"metadata": {},
"source": [
"## 导出为字典\n",
"作为一个数据容器, repo 相应地建立了导入和导出的功能. \n",
"我们刚刚从本地文件夹导入了一个 repo. \n",
"现在试试导出为一个字典."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "a11115fb",
"metadata": {},
"outputs": [],
"source": [
"test_repo_dic = test_repo.export_to_single_dict()\n",
"from pprint import pprint\n",
"pprint(test_repo_dic)"
]
},
{
"cell_type": "markdown",
"id": "35a2e06f",
"metadata": {},
"source": [
"## 持久化与部分保存\n",
"如你所见, 所有内容被结构化地输出了! \n",
"\n",
"现在写回到文件夹! \n",
"\n",
"我们注意到, 并非所有的内容都要被修改. \n",
"我们可以只保存接受修改的一部分, 默认情况下, 是迭代的记忆数据(algodata). \n",
"这就是为什么我们一般不使用单个 json 或 toml 来存储 repo.\n",
"\n",
"persist_to_repodir 接受两个可选参数: \n",
"- save_list: 默认为 [\"algodata\"], 是要持久化的数据.\n",
"- source: 默认为原目录, 你也可以手动指定为其他文件夹(通过 Path)\n",
"\n",
"现在做一些演练, 我们将创建一个位于 test_new_repo 的\"克隆\", 此时我们!\n",
"除非文件夹已经存在, Repo 对象将会为你自动创建新文件夹."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "05eeaacc",
"metadata": {},
"outputs": [],
"source": [
"test_repo.persist_to_repodir(save_list=[\"schedule\", \"payload\", \"manifest\", \"typedef\", \"algodata\"], source=Path(\"test_new_repo\"))\n",
"!tree"
]
},
{
"cell_type": "markdown",
"id": "059d7bdf",
"metadata": {},
"source": [
"如你所见, test_new_repo 已被生成!"
]
},
{
"cell_type": "markdown",
"id": "4ef8925c",
"metadata": {},
"source": [
"# 数据结构\n",
"现在讲解 repo 的数据结构"
]
},
{
"cell_type": "markdown",
"id": "c19fed95",
"metadata": {},
"source": [
"## Lict 对象\n",
"Lict 对象集成了部分列表和字典的功能, 数据在这两种风格的 API 间都可用, 且修改是同步的. \n",
"Lict 默认情况下不会保存序列顺序, 而是在列表形式下, 自动按索引字符序排布, 详情请参阅源代码. \n",
"现在导入并初始化一个 Lict 对象:"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "7e88bd7c",
"metadata": {},
"outputs": [],
"source": [
"from heurams.utils.lict import Lict\n",
"lct = Lict() # 空的\n",
"lct = Lict(initlist=[(\"name\", \"tom\"), (\"age\", 12), (\"enemy\", \"jerry\")]) # 基于列表\n",
"print(lct)\n",
"lct = Lict(initdict={\"name\": \"tom\", \"age\": 12, \"enemy\": \"jerry\"}) # 基于字典\n",
"print(lct)\n"
]
},
{
"cell_type": "markdown",
"id": "4d760bf9",
"metadata": {},
"source": [
"### 输出形式\n",
"lct 的\"官方\"输出形式是列表形式\n",
"你也可以选择输出字典形式"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "248f6cba",
"metadata": {},
"outputs": [],
"source": [
"print(lct.dicted_data)"
]
},
{
"cell_type": "markdown",
"id": "29dce184",
"metadata": {},
"source": [
"### dicted_data 属性与修改方式\n",
"dicted_data 属性是一个字典, 它自动同步来自 Lict 对象操作的修改.\n",
"一个注意事项: 不要直接修改 dicted_data, 这将不会触发同步 hook.\n",
"如果你一定要这样做, 请在完事后手动运行同步 hook.\n",
"推荐的修改方式是直接把 lct 当作一个字典"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "a0eb07a7",
"metadata": {},
"outputs": [],
"source": [
"# 由于 jupyter 的环境处理, 请不要重复运行此单元格, 如果想再看一遍, 请重启 jupyter 后再全部运行\n",
"\n",
"# 错误的方式\n",
"lct.dicted_data[\"type\"] = \"cat\"\n",
"print(lct) # 将不会同步修改\n",
"\n",
"# 不推荐, 但可用的方式\n",
"lct.dicted_data[\"type\"] = \"cat\"\n",
"lct._sync_based_on_dict()\n",
"print(lct)\n",
"\n",
"# 推荐方式\n",
"lct['is_human'] = False\n",
"print(lct)"
]
},
{
"cell_type": "markdown",
"id": "2337d113",
"metadata": {},
"source": [
"### data 属性与修改方式\n",
"data 属性是一个列表, 它自动同步来自 Lict 对象操作的修改.\n",
"一个注意事项: 不要直接修改 data, 这将不会触发同步 hook, 并且可能破坏排序.\n",
"如果你一定要这样做, 请在完事后手动运行同步 hook 和 sort, 此处不演示.\n",
"推荐的修改方式是直接把 lct 当作一个列表, 且避免使用索引修改"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "0ab442d4",
"metadata": {},
"outputs": [],
"source": [
"# 由于 jupyter 的环境处理, 请不要重复运行此单元格, 如果想再看一遍, 请重启 jupyter 后再全部运行\n",
"\n",
"# 唯一推荐方式\n",
"lct.append(('enemy_2', 'spike'))\n",
"print(lct.dicted_data)"
]
},
{
"cell_type": "markdown",
"id": "a3383f59",
"metadata": {},
"source": [
"### 多面手\n",
"Lict 有一些很酷的功能\n",
"详情请看源文件\n",
"此处是一些例子"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "f3ca752f",
"metadata": {},
"outputs": [],
"source": [
"lct = Lict(initdict={'age': 12, 'enemy': 'jerry', 'is_human': False, 'name': 'tom', 'type': 'cat', 'enemy_2': 'spike'})\n",
"print(lct)\n",
"print(lct.dicted_data)\n",
"print(\"------\")\n",
"for i in lct:\n",
" print(i)\n",
"print(len(lct))\n",
"while len(lct) > 0:\n",
" print(lct.pop())\n",
" print(lct)\n",
"lct = Lict(initdict={'age': 12, 'enemy': 'jerry', 'is_human': False, 'name': 'tom', 'type': 'cat', 'enemy_2': 'spike'})\n",
"..."
]
},
{
"cell_type": "markdown",
"id": "2d6d3483",
"metadata": {},
"source": [
"关爱环境 从你我做起"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "773bf99c",
"metadata": {},
"outputs": [],
"source": [
"!rm -rf test_new_repo\n",
"!rm -rf heurams.log*"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.13.11"
}
},
"nbformat": 4,
"nbformat_minor": 5
}

View File

@@ -0,0 +1 @@
{}

View File

@@ -0,0 +1,3 @@
title = "测试单元: 过秦论"
author = "__heurams__"
desc = "高考古诗文: 过秦论"

View File

@@ -0,0 +1,11 @@
["秦孝公据崤函之固, 拥雍州之地,"]
note = []
content = "秦孝公/据/崤函/之固/, 拥/雍州/之地,/"
translation = "秦孝公占据着崤山和函谷关的险固地势,拥有雍州的土地,"
keyword_note = {"据"="占据", "崤函"="崤山和函谷关", "雍州"="古代九州之一"}
["君臣固守以窥周室,"]
note = []
content = "君臣/固守/以窥/周室,/"
translation = "君臣牢固地守卫着,借以窥视周王室的权力,"
keyword_note = {"窥"="窥视"}

View File

@@ -0,0 +1,5 @@
schedule = ["quick_review", "recognition", "final_review"]
[phases]
quick_review = [["FillBlank", "1.0"], ["SelectMeaning", "0.5"], ["Recognition", "1.0"]]
recognition = [["Recognition", "1.0"]]
final_review = [["FillBlank", "0.7"], ["SelectMeaning", "0.7"], ["Recognition", "1.0"]]

View File

@@ -0,0 +1,19 @@
["古文句"]
[annotation]
note = "笔记"
keyword_note = "关键词翻译"
translation = "语句翻译"
delimiter = "分隔符"
content = "内容"
tts_text = "文本转语音文本"
["common"]
delimiter = "/"
tts_text = "eval:payload['content'].replace('/', '')"
["puzzles"] # 谜题定义
# 我们称 "Recognition" 为 recognition 谜题的 alia
"Recognition" = { __origin__ = "recognition", __hint__ = "", primary = "eval:payload['content']", secondary = ["eval:payload['keyword_note']", "eval:payload['note']"], top_dim = ["eval:payload['translation']"] }
"SelectMeaning" = { __origin__ = "mcq", __hint__ = "eval:payload['content']", primary = "eval:payload['content']", mapping = "eval:payload['keyword_note']", jammer = "eval:list(payload['keyword_note'].values())", max_riddles_num = "eval:default['mcq']['max_riddles_num']", prefix = "选择正确项: " }
"FillBlank" = { __origin__ = "cloze", __hint__ = "", text = "eval:payload['content']", delimiter = "eval:metadata['formation']['delimiter']", min_denominator = "eval:default['cloze']['min_denominator']"}

View File

@@ -0,0 +1,61 @@
# [调试] 将更改保存到文件
persist_to_file = 1
# [调试] 覆写时间, 设为 -1 以禁用
daystamp_override = -1
timestamp_override = -1
# [调试] 一键通过
quick_pass = 1
# 对于每个项目的默认新记忆原子数量
scheduled_num = 8
# UTC 时间戳修正 仅用于 UNIX 日时间戳的生成修正, 单位为秒
timezone_offset = +28800 # 中国标准时间 (UTC+8)
[interface]
[interface.memorizor]
autovoice = true # 自动语音播放, 仅限于 recognition 组件
[algorithm]
default = "SM-2" # 主要算法; 可选项: SM-2, SM-15M, FSRS
[puzzles] # 谜题默认配置
[puzzles.mcq]
max_riddles_num = 2
[puzzles.cloze]
min_denominator = 3
[paths] # 相对于配置文件的 ".." (即工作目录) 而言 或绝对路径
nucleon_dir = "./data/nucleon"
electron_dir = "./data/electron"
global_dir = "./data/global" # 全局数据路径, SM-15 等算法需要
orbital_dir = "./data/orbital"
cache_dir = "./data/cache"
template_dir = "./data/template"
[services] # 定义服务到提供者的映射
audio = "playsound" # 可选项: playsound(通用), termux(仅用于支持 Android Termux), mpg123(TODO)
tts = "edgetts" # 可选项: edgetts
llm = "openai" # 可选项: openai
sync = "webdav" # 可选项: 留空, webdav
[providers.tts.edgetts] # EdgeTTS 设置
voice = "zh-CN-XiaoxiaoNeural" # 可选项: zh-CN-YunjianNeural (男声), zh-CN-XiaoxiaoNeural (女声)
[providers.llm.openai] # 与 OpenAI 相容的语言模型接口服务设置
url = ""
key = ""
[providers.sync.webdav] # WebDAV 同步设置
url = ""
username = ""
password = ""
remote_path = "/heurams/"
verify_ssl = true
[sync]

View File

@@ -6,8 +6,8 @@ from heurams.services.logger import get_logger
from .screens.about import AboutScreen from .screens.about import AboutScreen
from .screens.dashboard import DashboardScreen from .screens.dashboard import DashboardScreen
from .screens.repocreator import NucleonCreatorScreen
from .screens.precache import PrecachingScreen from .screens.precache import PrecachingScreen
from .screens.repocreator import NucleonCreatorScreen
from .screens.synctool import SyncScreen from .screens.synctool import SyncScreen
logger = get_logger(__name__) logger = get_logger(__name__)

View File

@@ -7,8 +7,8 @@ from heurams.services.logger import get_logger
from .screens.about import AboutScreen from .screens.about import AboutScreen
from .screens.dashboard import DashboardScreen from .screens.dashboard import DashboardScreen
from .screens.repocreator import NucleonCreatorScreen
from .screens.precache import PrecachingScreen from .screens.precache import PrecachingScreen
from .screens.repocreator import NucleonCreatorScreen
logger = get_logger(__name__) logger = get_logger(__name__)

View File

@@ -1,5 +1,5 @@
"""关于界面 """关于界面"""
"""
from textual.app import ComposeResult from textual.app import ComposeResult
from textual.containers import ScrollableContainer from textual.containers import ScrollableContainer
from textual.screen import Screen from textual.screen import Screen

View File

@@ -1,5 +1,5 @@
"""仪表盘界面 """仪表盘界面"""
"""
import pathlib import pathlib
from textual.app import ComposeResult from textual.app import ComposeResult
@@ -62,7 +62,8 @@ class DashboardScreen(Screen):
Returns: Returns:
dict: 包含显示文本的字典,键为行号 dict: 包含显示文本的字典,键为行号
""" """
from heurams.kernel.repository.particle_loader import load_electron, load_nucleon from heurams.kernel.repository.particle_loader import (load_electron,
load_nucleon)
result = {} result = {}
filestem = pathlib.Path(filename).stem filestem = pathlib.Path(filename).stem

View File

@@ -1,2 +1 @@
"""笔记界面 """笔记界面"""
"""

View File

@@ -1,2 +1 @@
"""整体式记忆工作界面 """整体式记忆工作界面"""
"""

View File

@@ -1,5 +1,5 @@
"""队列式记忆工作界面 """队列式记忆工作界面"""
"""
from enum import Enum, auto from enum import Enum, auto
from textual.app import ComposeResult from textual.app import ComposeResult
@@ -8,8 +8,8 @@ from textual.reactive import reactive
from textual.screen import Screen from textual.screen import Screen
from textual.widgets import Button, Footer, Header, Label, Static from textual.widgets import Button, Footer, Header, Label, Static
import heurams.kernel.particles as pt
import heurams.kernel.evaluators as pz import heurams.kernel.evaluators as pz
import heurams.kernel.particles as pt
from heurams.context import config_var from heurams.context import config_var
from heurams.kernel.reactor import * from heurams.kernel.reactor import *
from heurams.services.logger import get_logger from heurams.services.logger import get_logger

View File

@@ -1,5 +1,5 @@
"""缓存工具界面 """缓存工具界面"""
"""
import pathlib import pathlib
from textual.app import ComposeResult from textual.app import ComposeResult

View File

@@ -1,5 +1,5 @@
"""记忆准备界面 """记忆准备界面"""
"""
from textual.app import ComposeResult from textual.app import ComposeResult
from textual.containers import ScrollableContainer from textual.containers import ScrollableContainer
from textual.reactive import reactive from textual.reactive import reactive

View File

@@ -1,2 +1 @@
""""前进电台" 界面 """ "前进电台" 界面"""
"""

View File

@@ -1,5 +1,5 @@
"""仓库创建向导界面 """仓库创建向导界面"""
"""
from pathlib import Path from pathlib import Path
import toml import toml

View File

@@ -1,5 +1,5 @@
"""同步工具界面 """同步工具界面"""
"""
import pathlib import pathlib
import time import time

View File

@@ -4,8 +4,8 @@ import random
from typing import TypedDict from typing import TypedDict
import heurams.interface.widgets as pzw import heurams.interface.widgets as pzw
import heurams.kernel.particles as pt
import heurams.kernel.evaluators as pz import heurams.kernel.evaluators as pz
import heurams.kernel.particles as pt
staging = {} # 细粒度缓存区, 是 ident -> quality 的封装 staging = {} # 细粒度缓存区, 是 ident -> quality 的封装

View File

@@ -7,8 +7,8 @@ from textual.message import Message
from textual.widget import Widget from textual.widget import Widget
from textual.widgets import Button, Label from textual.widgets import Button, Label
import heurams.kernel.particles as pt
import heurams.kernel.evaluators as pz import heurams.kernel.evaluators as pz
import heurams.kernel.particles as pt
from heurams.services.logger import get_logger from heurams.services.logger import get_logger
from .base_puzzle_widget import BasePuzzleWidget from .base_puzzle_widget import BasePuzzleWidget

View File

@@ -5,8 +5,8 @@ from textual.containers import Container, ScrollableContainer
from textual.widget import Widget from textual.widget import Widget
from textual.widgets import Button, Label from textual.widgets import Button, Label
import heurams.kernel.particles as pt
import heurams.kernel.evaluators as pz import heurams.kernel.evaluators as pz
import heurams.kernel.particles as pt
from heurams.services.hasher import hash from heurams.services.hasher import hash
from heurams.services.logger import get_logger from heurams.services.logger import get_logger

View File

@@ -1,8 +1,8 @@
from heurams.services.logger import get_logger from heurams.services.logger import get_logger
from .base import BaseAlgorithm
from .sm2 import SM2Algorithm from .sm2 import SM2Algorithm
from .sm15m import SM15MAlgorithm from .sm15m import SM15MAlgorithm
from .base import BaseAlgorithm
logger = get_logger(__name__) logger = get_logger(__name__)

View File

@@ -75,4 +75,3 @@ class BaseAlgorithm:
return 1 return 1
except: except:
return 0 return 0

View File

@@ -6,6 +6,7 @@ from .base import BaseEvaluator
logger = get_logger(__name__) logger = get_logger(__name__)
class GuessEvaluator(BaseEvaluator): class GuessEvaluator(BaseEvaluator):
def __init__(self): def __init__(self):
super().__init__() super().__init__()

View File

@@ -5,7 +5,6 @@ from typing import TypedDict
import toml import toml
from heurams.context import config_var
from heurams.services.logger import get_logger from heurams.services.logger import get_logger
from .electron import Electron from .electron import Electron
@@ -19,11 +18,13 @@ class AtomRegister_runtime(TypedDict):
min_rate: int # 最低评分 min_rate: int # 最低评分
new_activation: bool # 新激活 new_activation: bool # 新激活
class AtomRegister(TypedDict): class AtomRegister(TypedDict):
nucleon: Nucleon nucleon: Nucleon
electron: Electron electron: Electron
runtime: AtomRegister_runtime runtime: AtomRegister_runtime
class Atom: class Atom:
""" """
统一处理一系列对象的所有信息与持久化: 统一处理一系列对象的所有信息与持久化:
@@ -39,10 +40,10 @@ class Atom:
"new_activation": False, "new_activation": False,
} }
def __init__(self, nucleon_obj = None, electron_obj = None, orbital_obj = None): def __init__(self, nucleon_obj=None, electron_obj=None, orbital_obj=None):
self.ident = nucleon_obj["ident"] # type: ignore self.ident = nucleon_obj["ident"] # type: ignore
self.registry: AtomRegister = { # type: ignore self.registry: AtomRegister = { # type: ignore
"ident": nucleon_obj["ident"], # type: ignore "ident": nucleon_obj["ident"], # type: ignore
"nucleon": nucleon_obj, "nucleon": nucleon_obj,
"electron": electron_obj, "electron": electron_obj,
"orbital": orbital_obj, "orbital": orbital_obj,
@@ -53,7 +54,7 @@ class Atom:
self.registry["runtime"]["new_activation"] = True self.registry["runtime"]["new_activation"] = True
def init_runtime(self): def init_runtime(self):
self.registry['runtime'] = AtomRegister_runtime(**self.default_runtime) self.registry["runtime"] = AtomRegister_runtime(**self.default_runtime)
def minimize(self, rating): def minimize(self, rating):
"""效果等同于 self.registry['runtime']['min_rate'] = min(rating, self.registry['runtime']['min_rate']) """效果等同于 self.registry['runtime']['min_rate'] = min(rating, self.registry['runtime']['min_rate'])

View File

@@ -1,12 +1,14 @@
from copy import deepcopy
from typing import TypedDict from typing import TypedDict
import heurams.kernel.algorithms as algolib
import heurams.services.timer as timer import heurams.services.timer as timer
from heurams.context import config_var
from heurams.kernel.algorithms import algorithms from heurams.kernel.algorithms import algorithms
from heurams.services.logger import get_logger from heurams.services.logger import get_logger
import heurams.kernel.algorithms as algolib
from copy import deepcopy
logger = get_logger(__name__) logger = get_logger(__name__)
class Electron: class Electron:
"""电子: 单算法支持的记忆数据包装""" """电子: 单算法支持的记忆数据包装"""

View File

@@ -1,17 +1,17 @@
from heurams.services.logger import get_logger
from copy import deepcopy from copy import deepcopy
from heurams.services.logger import get_logger
from heurams.utils.evalizor import Evalizer from heurams.utils.evalizor import Evalizer
logger = get_logger(__name__) logger = get_logger(__name__)
class Nucleon: class Nucleon:
"""原子核: 带有运行时隔离的模板化只读材料元数据容器 """原子核: 带有运行时隔离的模板化只读材料元数据容器"""
"""
def __init__(self, ident, payload, common): def __init__(self, ident, payload, common):
self.ident = ident self.ident = ident
env = { env = {"payload": payload}
"payload": payload
}
self.evalizer = Evalizer(environment=env) self.evalizer = Evalizer(environment=env)
self.data = self.evalizer(deepcopy((payload | common))) self.data = self.evalizer(deepcopy((payload | common)))
@@ -48,5 +48,5 @@ class Nucleon:
_data = nucleonic_data _data = nucleonic_data
payload = _data[1][0] payload = _data[1][0]
common = _data[1][1] common = _data[1][1]
ident = _data[0] #TODO:实现eval ident = _data[0] # TODO:实现eval
return Nucleon(ident, payload, common) return Nucleon(ident, payload, common)

View File

@@ -1,14 +1,16 @@
from heurams.utils.lict import Lict
from heurams.utils.evalizor import Evalizer from heurams.utils.evalizor import Evalizer
from heurams.utils.lict import Lict
class Orbital():
class Orbital:
@classmethod @classmethod
def create_orbital(cls, schedule: list, phase_def: dict): def create_orbital(cls, schedule: list, phase_def: dict):
phase_def = Lict(initdict=phase_def) # type: ignore phase_def = Lict(initdict=phase_def) # type: ignore
orbital = Lict() orbital = Lict()
for i in schedule: for i in schedule:
orbital[i] = Lict(phase_def[i]) orbital[i] = Lict(phase_def[i])
return orbital return orbital
@classmethod @classmethod
def create_orbital_on_orbitic_data(cls, orbitic_data): def create_orbital_on_orbitic_data(cls, orbitic_data):
return cls.create_orbital(orbitic_data["schedule"], orbitic_data["phases"]) return cls.create_orbital(orbitic_data["schedule"], orbitic_data["phases"])

View File

@@ -1,7 +1,7 @@
import random import random
import heurams.kernel.particles as pt
import heurams.kernel.evaluators as puz import heurams.kernel.evaluators as puz
import heurams.kernel.particles as pt
from heurams.services.logger import get_logger from heurams.services.logger import get_logger
from .states import PhaserState from .states import PhaserState

View File

@@ -1,5 +1,5 @@
from ...utils.lict import Lict from ...utils.lict import Lict
def merge(x: Lict, y: Lict): def merge(x: Lict, y: Lict):
return Lict(list(x.values()) + list(y.values())) return Lict(list(x.values()) + list(y.values()))

View File

@@ -1,3 +1,3 @@
class Navi(): class Navi:
def __init__(self, init) -> None: def __init__(self, init) -> None:
pass pass

View File

@@ -1,11 +1,15 @@
import json
from functools import reduce from functools import reduce
from pathlib import Path from pathlib import Path
import heurams.kernel.particles as pt
import toml import toml
import json
import heurams.kernel.particles as pt
from ...utils.lict import Lict from ...utils.lict import Lict
class Repo():
class Repo:
file_mapping = { file_mapping = {
"schedule": "schedule.toml", "schedule": "schedule.toml",
"payload": "payload.toml", "payload": "payload.toml",
@@ -24,13 +28,21 @@ class Repo():
default_save_list = ["algodata"] default_save_list = ["algodata"]
def __init__(self, schedule: dict, payload: Lict, manifest: dict, typedef: dict, algodata: Lict, source = None) -> None: def __init__(
self,
schedule: dict,
payload: Lict,
manifest: dict,
typedef: dict,
algodata: Lict,
source=None,
) -> None:
self.schedule: dict = schedule self.schedule: dict = schedule
self.manifest: dict = manifest self.manifest: dict = manifest
self.typedef: dict = typedef self.typedef: dict = typedef
self.payload: Lict = payload self.payload: Lict = payload
self.algodata: Lict = algodata self.algodata: Lict = algodata
self.source: Path | None = source # 若存在, 指向 repo 所在 dir self.source: Path | None = source # 若存在, 指向 repo 所在 dir
self.database = { self.database = {
"schedule": self.schedule, "schedule": self.schedule,
"payload": self.payload, "payload": self.payload,
@@ -42,35 +54,43 @@ class Repo():
self.generate_particles_data() self.generate_particles_data()
def generate_particles_data(self): def generate_particles_data(self):
self.nucleonic_data_lict = Lict(initlist=list(map(self._attach(self.typedef), self.payload)))
self.nucleonic_data_lict = Lict(
initlist=list(map(
self._nucleonic_proc,
self.payload))
)
self.electronic_data_lict = self.algodata self.electronic_data_lict = self.algodata
self.orbitic_data = self.schedule self.orbitic_data = self.schedule
@staticmethod def _nucleonic_proc(self, unit):
def _attach(value): ident = unit[0]
def inner(x): common = self.typedef["common"]
return (x, value) return (ident, (unit[1], common))
return inner
@staticmethod @staticmethod
def _merge(value): def _merge(value):
def inner(x): def inner(x):
return map(x, value) return (x, value)
return inner return inner
def __len__(self): def __len__(self):
return len(self.payload) return len(self.payload)
def persist_to_repodir(self, save_list: list | None = None, source: Path | None= None): def persist_to_repodir(
self, save_list: list | None = None, source: Path | None = None
):
if save_list == None: if save_list == None:
save_list = self.default_save_list save_list = self.default_save_list
if self.source != None and source == None: if self.source != None and source == None:
source = self.source source = self.source
if source == None: if source == None:
raise FileNotFoundError("不存在仓库到文件的映射") raise FileNotFoundError("不存在仓库到文件的映射")
source.mkdir(parents=True, exist_ok=False)
for keyname in save_list: for keyname in save_list:
filename = self.file_mapping[keyname] filename = self.file_mapping[keyname]
with open(source / filename, 'w') as f: with open(source / filename, "w") as f:
try: try:
dict_data = self.database[keyname].dicted_data dict_data = self.database[keyname].dicted_data
except: except:
@@ -86,14 +106,14 @@ class Repo():
return self.database return self.database
@classmethod @classmethod
def create_new_repo(cls, source = None): def create_new_repo(cls, source=None):
default_database = { default_database = {
"schedule": {}, "schedule": {},
"payload": Lict([]), "payload": Lict([]),
"algodata": Lict([]), "algodata": Lict([]),
"manifest": {}, "manifest": {},
"typedef": {}, "typedef": {},
"source": source "source": source,
} }
return Repo(**default_database) return Repo(**default_database)

View File

@@ -1,9 +1,10 @@
class Evalizer(): class Evalizer:
"""几乎无副作用的模板系统 """几乎无副作用的模板系统
接受环境信息并创建一个模板解析工具, 工具传入参数支持list, dict及其嵌套 接受环境信息并创建一个模板解析工具, 工具传入参数支持list, dict及其嵌套
副作用问题: 仅存在于 eval 函数 副作用问题: 仅存在于 eval 函数
""" """
# TODO: 弃用风险极高的 eval # TODO: 弃用风险极高的 eval
# 理论上已经限制了全局函数 但eval仍有风险 # 理论上已经限制了全局函数 但eval仍有风险
# TODO: 异步/多线程执行避免堵塞 # TODO: 异步/多线程执行避免堵塞

View File

@@ -1,9 +1,9 @@
from collections import UserList from collections import UserList
from typing import Any, Iterator from typing import Any, Iterator
class Lict(UserList): #TODO: 优化同步(惰性同步), 当前性能为 O(n)
""""列典" 对象 class Lict(UserList): # TODO: 优化同步(惰性同步), 当前性能为 O(n)
""" "列典" 对象
同时兼容字典和列表大多数 API, 两边数据同步的容器 同时兼容字典和列表大多数 API, 两边数据同步的容器
列表数据是 dictobj.items() 的格式 列表数据是 dictobj.items() 的格式
@@ -17,7 +17,13 @@ class Lict(UserList): #TODO: 优化同步(惰性同步), 当前性能为 O(n)
只有在 Python 3.7+ 中, forced_order 行为才能被取消. 只有在 Python 3.7+ 中, forced_order 行为才能被取消.
""" """
def __init__(self, initlist: list | None = None, initdict: dict | None = None, forced_order = True):
def __init__(
self,
initlist: list | None = None,
initdict: dict | None = None,
forced_order=True,
):
self.dicted_data = {} self.dicted_data = {}
if initdict != None: if initdict != None:
initlist = list(initdict.items()) initlist = list(initdict.items())
@@ -65,19 +71,23 @@ class Lict(UserList): #TODO: 优化同步(惰性同步), 当前性能为 O(n)
self._sync_based_on_list() self._sync_based_on_list()
def __contains__(self, item): def __contains__(self, item):
return (item in self.data or item in self.keys() or item in self.values()) return item in self.data or item in self.keys() or item in self.values()
def append(self, item: Any) -> None: def append(self, item: Any) -> None:
if item != (item[0], item[1]): if item != (item[0], item[1]):
raise NotImplementedError raise NotImplementedError
super().append(item) super().append(item)
self._sync_based_on_list() self._sync_based_on_list()
if self.forced_order:
self.data.sort()
def insert(self, i: int, item: Any) -> None: def insert(self, i: int, item: Any) -> None:
if item != (item[0], item[1]): # 确保 item 是遵从限制的元组 if item != (item[0], item[1]): # 确保 item 是遵从限制的元组
raise NotImplementedError raise NotImplementedError
super().insert(i, item) super().insert(i, item)
self._sync_based_on_list() self._sync_based_on_list()
if self.forced_order:
self.data.sort()
def pop(self, i: int = -1) -> Any: def pop(self, i: int = -1) -> Any:
res = super().pop(i) res = super().pop(i)
@@ -91,6 +101,8 @@ class Lict(UserList): #TODO: 优化同步(惰性同步), 当前性能为 O(n)
raise NotImplementedError raise NotImplementedError
super().remove(item) super().remove(item)
self._sync_based_on_list() self._sync_based_on_list()
if self.forced_order:
self.data.sort()
def clear(self) -> None: def clear(self) -> None:
super().clear() super().clear()

View File

@@ -58,11 +58,11 @@ class RefVar:
def __pow__(self, other): def __pow__(self, other):
if isinstance(other, RefVar): if isinstance(other, RefVar):
return RefVar(self.data ** other.data) return RefVar(self.data**other.data)
return RefVar(self.data ** other) return RefVar(self.data**other)
def __rpow__(self, other): def __rpow__(self, other):
return RefVar(other ** self.data) return RefVar(other**self.data)
def __neg__(self): def __neg__(self):
return RefVar(-self.data) return RefVar(-self.data)