admin
upl base
cc646d3
raw
history blame
4.44 kB
from typing import Iterable, Callable
from sympy import Eq, linsolve, simplify, latex, Expr, Symbol
class CannotCalculate(Exception):
pass
class BadInput(Exception):
pass
CONSTANT_TERM_KEY = "constant_term"
class GetIntegrate:
integrate_result_classes: dict[str, Expr | None]
def integrate_and_separate(
self, integrate_formula: Expr, integrate_args: tuple
) -> dict[str, Expr]:
"""
解积分,分离各项
"""
raise NotImplementedError(
"该函数已弃用,请使用 GetIntegrateFromData 类。如果想要使用它预处理,见 pre/old_solution.py"
)
# # 解积分
# res = integrate(integrate_formula, integrate_args)
# res = expand(expand(res))
# print(f'integrate[0,1] {integrate_formula}={res}')
#
# # 分离各项
# di = {}
# exprs = []
# for key, expr in self.integrate_result_classes.items():
# if key == CONSTANT_TERM_KEY:
# continue
# exprs.append(expr)
# di[key] = res.coeff(expr)
#
# constant_term, _ = res.as_independent(*exprs)
# return {**di, CONSTANT_TERM_KEY: constant_term}
def get_integrate_args(self, try_arg):
"""
:return: integrand_function, (independent_variable, lower_limit, upper_limit)
被积函数, (自变量, 下限, 上限)
"""
raise NotImplementedError()
def tries(self, try_arg):
"""
:return: {term_name: coefficient_of_the_term}
{该项的名称: 该项系数}
"""
return self.integrate_and_separate(*self.get_integrate_args(try_arg))
def get_latex(self, try_arg, subs):
expr, args = self.get_integrate_args(try_arg)
expr = simplify(expr).subs(subs)
sym, low, high = args
return r"\int_{%s}^{%s} {%s} \mathrm{d} {%s}" % (
low,
high,
latex(simplify(expr)),
sym,
)
class GetIntegrateFromData(GetIntegrate):
data: dict[object, dict[str, Expr]]
def tries(self, try_arg):
return self.data[try_arg]
class Solution:
get_integrate: GetIntegrate
# gui: Pattern
get_tries_args: Callable[[], Iterable[Expr]]
"""
Generate try_arg for each trial
生成每一次尝试的 try_arg
"""
symbols: tuple[Symbol, ...]
"""
The undetermined variable to solve.
要求的待定系数
"""
integrate_result_classes_eq: dict[str, Expr]
"""
{term_name: coefficient}
The value to which each term's coefficient is equal.
每个项系数分别要等于的值
"""
check_sgn: Callable
"""
Input: unpacked solution of undetermined variables;
Output: 0 (cannot determine), 1 or -1 (can determine; 1 and -1 are interchangeable for greater or less than).
Module sgntools provides lin_func_sgn and sq_func_sgn. Call help() for further details.
输入:解包的待定系数的值列表;
输出: 0(无法确定), 1或-1(可以确定, 1和-1哪个代表大于、哪个代表小于, 是可以互换的)
sgntools 模块提供了 lin_func_sgn 和 sq_func_sgn 函数,详见 help()
"""
# check_sgn: Callable[?, 1 | 0 | -1]
def get_symbols(self, separate_result):
"""凑积分结果系数"""
system = [
Eq(int_term, self.integrate_result_classes_eq[key])
for key, int_term in separate_result.items()
]
print(f"{system=}")
return linsolve(system, *self.symbols)
def try_times(self) -> tuple[Expr, dict, int] | tuple[None, None, None]:
for try_arg in self.get_tries_args():
separate = self.get_integrate.tries(try_arg)
for symbol_solution in self.get_symbols(separate):
if sgn := self.check_sgn(*symbol_solution):
return try_arg, dict(zip(self.symbols, symbol_solution)), sgn
return None, None, None
def get_latex_ans(self):
"""
:return: None if it can't be solved; Otherwise, LaTeX (without "$$")
"""
raise NotImplementedError()
# 插件注册(历史遗留问题)
solutions = {}
solution_sort = []
def register(name, solution, top=False):
solutions[name] = solution
if top:
solution_sort.insert(0, name)
else:
solution_sort.append(name)