feat: 一系列新功能

This commit is contained in:
2026-01-08 00:05:00 +08:00
parent d3dadced85
commit 6d60f95d6a
44 changed files with 1984 additions and 93 deletions

View File

@@ -0,0 +1,5 @@
from .evalizor import Evalizer
from .lict import Lict
from .refvar import RefVar
__all__ = ["Evalizer", "Lict", "RefVar"]

View File

@@ -0,0 +1,33 @@
class Evalizer:
"""几乎无副作用的模板系统
接受环境信息并创建一个模板解析工具, 工具传入参数支持list, dict及其嵌套
副作用问题: 仅存在于 eval 函数
"""
# TODO: 弃用风险极高的 eval
# TODO: 异步/多线程执行避免堵塞
def __init__(self, environment: dict) -> None:
self.env = environment
def __call__(self, anyobj):
return self.travel(anyobj)
def travel(self, anyobj):
if isinstance(anyobj, list):
return list(map(self.travel, anyobj))
elif isinstance(anyobj, dict):
return dict(map(self.travel, anyobj.items()))
elif isinstance(anyobj, tuple):
return tuple(map(self.travel, anyobj))
elif isinstance(anyobj, str):
if anyobj.startswith("eval:"):
return self.eval_with_env(anyobj[5:])
else:
return anyobj
else:
return anyobj
def eval_with_env(self, s: str):
ret = eval(s, globals(), self.env)
return ret

View File

@@ -0,0 +1,149 @@
from collections import UserList
from typing import Any, Iterator
class Lict(UserList): # TODO: 优化同步(惰性同步), 当前性能为 O(n)
""" "列典" 对象
同时兼容字典和列表大多数 API, 两边数据同步的容器
列表数据是 dictobj.items() 的格式
支持根据字典或列表初始化
限制要求:
- 键名一定唯一, 且仅能为字符串
- 值一定是引用对象
- 不使用并发
- 不在乎列表顺序语义(严格按键名字符序排列)和列表索引查找, 因此外部的 sort, index 等功能不可用
- append 的元组中, 表示键名的元素不能重复, 否则会导致覆盖行为
只有在 Python 3.7+ 中, forced_order 行为才能被取消.
"""
def __init__(
self,
initlist: list | None = None,
initdict: dict | None = None,
forced_order=False,
):
self.dicted_data = {}
if initdict != None:
initlist = list(initdict.items())
super().__init__(initlist=initlist)
self.forced_order = forced_order
self._sync_based_on_list()
if self.forced_order:
self.data.sort()
def _sync_based_on_dict(self):
self.data = list(self.dicted_data.items())
if self.forced_order:
self.data.sort()
def _sync_based_on_list(self):
self.dicted_data = {}
for i in self.data:
self.dicted_data[i[0]] = i[1]
def __iter__(self) -> Iterator:
return self.data.__iter__()
def __getitem__(self, i):
if isinstance(i, str):
return self.dicted_data[i]
else:
return super().__getitem__(i)
def get_itemic_unit(self, ident):
return (ident, self.dicted_data[ident])
def __setitem__(self, i, item):
if isinstance(i, str):
self.dicted_data[i] = item
self._sync_based_on_dict()
else:
if item != (item[0], item[1]):
raise NotImplementedError
super().__setitem__(i, item)
self._sync_based_on_list()
def __delitem__(self, i):
if isinstance(i, str):
del self.dicted_data[i]
self._sync_based_on_dict()
else:
super().__delitem__(i)
self._sync_based_on_list()
def __contains__(self, item):
return item in self.data or item in self.keys() or item in self.values()
def append(self, item: Any) -> None:
if item != (item[0], item[1]):
raise NotImplementedError
super().append(item)
self._sync_based_on_list()
if self.forced_order:
self.data.sort()
def append_new(self, item: Any):
if item != (item[0], item[1]):
raise NotImplementedError
if item[0] not in self:
super().append(item)
self._sync_based_on_list()
if self.forced_order:
self.data.sort()
def insert(self, i: int, item: Any) -> None:
if item != (item[0], item[1]): # 确保 item 是遵从限制的元组
raise NotImplementedError
super().insert(i, item)
self._sync_based_on_list()
if self.forced_order:
self.data.sort()
def pop(self, i: int = -1) -> Any:
res = super().pop(i)
self._sync_based_on_list()
return res
def remove(self, item: Any) -> None:
if isinstance(item, str):
item = (item, self.dicted_data[item])
if item != (item[0], item[1]):
raise NotImplementedError
super().remove(item)
self._sync_based_on_list()
if self.forced_order:
self.data.sort()
def clear(self) -> None:
super().clear()
self._sync_based_on_list()
def index(self):
raise NotImplementedError
def extend(self):
raise NotImplementedError
def sort(self):
raise NotImplementedError
def reverse(self):
raise NotImplementedError
def keys(self):
return self.dicted_data.keys()
def values(self):
return self.dicted_data.values()
def items(self):
return self.data
def keys_equal_with(self, other):
return self.key_equality(self, other)
@classmethod
def key_equality(cls, a, b):
return a.keys() == b.keys()

View File

@@ -0,0 +1,241 @@
class RefVar:
def __init__(self, initvalue) -> None:
self.data = initvalue
def __repr__(self) -> str:
return f"RefVar({repr(self.data)})"
def __str__(self) -> str:
return str(self.data)
def __add__(self, other):
if isinstance(other, RefVar):
return RefVar(self.data + other.data)
return RefVar(self.data + other)
def __radd__(self, other):
return RefVar(other + self.data)
def __sub__(self, other):
if isinstance(other, RefVar):
return RefVar(self.data - other.data)
return RefVar(self.data - other)
def __rsub__(self, other):
return RefVar(other - self.data)
def __mul__(self, other):
if isinstance(other, RefVar):
return RefVar(self.data * other.data)
return RefVar(self.data * other)
def __rmul__(self, other):
return RefVar(other * self.data)
def __truediv__(self, other):
if isinstance(other, RefVar):
return RefVar(self.data / other.data)
return RefVar(self.data / other)
def __rtruediv__(self, other):
return RefVar(other / self.data)
def __floordiv__(self, other):
if isinstance(other, RefVar):
return RefVar(self.data // other.data)
return RefVar(self.data // other)
def __rfloordiv__(self, other):
return RefVar(other // self.data)
def __mod__(self, other):
if isinstance(other, RefVar):
return RefVar(self.data % other.data)
return RefVar(self.data % other)
def __rmod__(self, other):
return RefVar(other % self.data)
def __pow__(self, other):
if isinstance(other, RefVar):
return RefVar(self.data**other.data)
return RefVar(self.data**other)
def __rpow__(self, other):
return RefVar(other**self.data)
def __neg__(self):
return RefVar(-self.data)
def __pos__(self):
return RefVar(+self.data)
def __abs__(self):
return RefVar(abs(self.data))
def __eq__(self, other):
if isinstance(other, RefVar):
return self.data == other.data
return self.data == other
def __ne__(self, other):
return not self.__eq__(other)
def __lt__(self, other):
if isinstance(other, RefVar):
return self.data < other.data
return self.data < other
def __le__(self, other):
if isinstance(other, RefVar):
return self.data <= other.data
return self.data <= other
def __gt__(self, other):
if isinstance(other, RefVar):
return self.data > other.data
return self.data > other
def __ge__(self, other):
if isinstance(other, RefVar):
return self.data >= other.data
return self.data >= other
# 位运算
def __and__(self, other):
if isinstance(other, RefVar):
return RefVar(self.data & other.data)
return RefVar(self.data & other)
def __rand__(self, other):
return RefVar(other & self.data)
def __or__(self, other):
if isinstance(other, RefVar):
return RefVar(self.data | other.data)
return RefVar(self.data | other)
def __ror__(self, other):
return RefVar(other | self.data)
def __xor__(self, other):
if isinstance(other, RefVar):
return RefVar(self.data ^ other.data)
return RefVar(self.data ^ other)
def __rxor__(self, other):
return RefVar(other ^ self.data)
def __lshift__(self, other):
if isinstance(other, RefVar):
return RefVar(self.data << other.data)
return RefVar(self.data << other)
def __rlshift__(self, other):
return RefVar(other << self.data)
def __rshift__(self, other):
if isinstance(other, RefVar):
return RefVar(self.data >> other.data)
return RefVar(self.data >> other)
def __rrshift__(self, other):
return RefVar(other >> self.data)
def __invert__(self):
return RefVar(~self.data)
# 类型转换
def __int__(self):
return int(self.data)
def __float__(self):
return float(self.data)
def __bool__(self):
return bool(self.data)
def __complex__(self):
return complex(self.data)
def __bytes__(self):
return bytes(self.data)
def __hash__(self):
return hash(self.data)
# 容器操作(如果底层数据支持)
def __len__(self):
return len(self.data)
def __getitem__(self, key):
return self.data[key]
def __setitem__(self, key, value):
self.data[key] = value
def __delitem__(self, key):
del self.data[key]
def __contains__(self, item):
return item in self.data
def __iter__(self):
return iter(self.data)
def __iadd__(self, other):
if isinstance(other, RefVar):
self.data += other.data
else:
self.data += other
return self
def __isub__(self, other):
if isinstance(other, RefVar):
self.data -= other.data
else:
self.data -= other
return self
def __imul__(self, other):
if isinstance(other, RefVar):
self.data *= other.data
else:
self.data *= other
return self
def __itruediv__(self, other):
if isinstance(other, RefVar):
self.data /= other.data
else:
self.data /= other
return self
def __ifloordiv__(self, other):
if isinstance(other, RefVar):
self.data //= other.data
else:
self.data //= other
return self
def __imod__(self, other):
if isinstance(other, RefVar):
self.data %= other.data
else:
self.data %= other
return self
def __ipow__(self, other):
if isinstance(other, RefVar):
self.data **= other.data
else:
self.data **= other
return self
def __call__(self, *args, **kwargs):
if callable(self.data):
return self.data(*args, **kwargs)
raise TypeError(f"'{type(self.data).__name__}' object is not callable")
def __getattr__(self, name):
return getattr(self.data, name)

View File

@@ -3,8 +3,8 @@ from .electron import Electron
from .nucleon import Nucleon
from .placeholders import (
AtomPlaceholder,
NucleonPlaceholder,
ElectronPlaceholder,
NucleonPlaceholder,
orbital_placeholder,
)

View File

@@ -1,6 +1,5 @@
from typing import TypedDict
from heurams.services.logger import get_logger
from .electron import Electron

View File

@@ -57,6 +57,10 @@ class Electron:
result = self.algodata[self.algo.algo_name]["is_activated"]
return result
def last_modify(self):
result = self.algodata[self.algo.algo_name]["last_modify"]
return result
def get_rating(self):
try:
result = self.algo.get_rating(self.algodata)
@@ -68,6 +72,10 @@ class Electron:
result = self.algo.nextdate(self.algodata)
return result
def lastdate(self) -> int:
result = self.algodata[self.algo.algo_name]["lastdate"]
return result
def revisor(self, quality: int = 5, is_new_activation: bool = False):
"""算法迭代决策机制实现

View File

@@ -1,9 +1,9 @@
from copy import deepcopy
from logging import config
from heurams.services.logger import get_logger
from heurams.utils.evalizor import Evalizer
from heurams.context import config_var
from heurams.services.logger import get_logger
from heurams.kernel.auxiliary.evalizor import Evalizer
logger = get_logger(__name__)

View File

@@ -1,7 +1,8 @@
from heurams.kernel.particles import orbital
from .atom import Atom
from .electron import Electron
from .nucleon import Nucleon
from .atom import Atom
orbital_placeholder = {
"schedule": ["quick_review", "recognition", "final_review"],

View File

@@ -1,12 +1,13 @@
from functools import reduce
import random
import heurams.kernel.puzzles as puz
import heurams.kernel.particles as pt
from heurams.services.logger import get_logger
from functools import reduce
from tabulate import tabulate as tabu
from transitions import Machine
import heurams.kernel.particles as pt
import heurams.kernel.puzzles as puz
from heurams.services.logger import get_logger
from .states import FissionState, PhaserState
logger = get_logger(__name__)

View File

@@ -1,8 +1,9 @@
from click import style
from transitions import Machine
import heurams.kernel.particles as pt
from heurams.kernel.particles.placeholders import AtomPlaceholder
from heurams.services.logger import get_logger
from transitions import Machine
from .procession import Procession
from .states import PhaserState, ProcessionState
@@ -133,9 +134,10 @@ class Phaser(Machine):
return Procession([AtomPlaceholder()], PhaserState.FINISHED)
def __repr__(self, style="pipe", ends="\n"):
from heurams.services.textproc import truncate
from tabulate import tabulate as tabu
from heurams.services.textproc import truncate
lst = [
{
"Type": "Phaser",

View File

@@ -1,7 +1,8 @@
from tabulate import tabulate as tabu
from transitions import Machine
import heurams.kernel.particles as pt
from heurams.services.logger import get_logger
from transitions import Machine
from tabulate import tabulate as tabu
from .fission import Fission
from .states import PhaserState, ProcessionState

View File

@@ -7,7 +7,7 @@ import toml
import heurams.kernel.particles as pt
from ...utils.lict import Lict
from heurams.kernel.auxiliary.lict import Lict
class RepoManifest(TypedDict):
@@ -167,7 +167,7 @@ class Repo:
return 0
@classmethod
def probe_vaild_repos_in_dir(cls, folder: Path):
def probe_valid_repos_in_dir(cls, folder: Path):
lst = list()
for i in folder.iterdir():
if i.is_dir():