Spaces:
Running
Running
admin
commited on
Commit
·
30e9073
0
Parent(s):
Initial commit
Browse files- .gitattributes +35 -0
- .gitignore +10 -0
- README.md +12 -0
- app.py +221 -0
- output_util.py +14 -0
- requirements.txt +3 -0
- sgntools.py +34 -0
- solution.py +132 -0
- solutions/e.py +68 -0
- solutions/eq.py +179 -0
- solutions/pi.py +136 -0
- solutions/pin.py +188 -0
.gitattributes
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
*.7z filter=lfs diff=lfs merge=lfs -text
|
| 2 |
+
*.arrow filter=lfs diff=lfs merge=lfs -text
|
| 3 |
+
*.bin filter=lfs diff=lfs merge=lfs -text
|
| 4 |
+
*.bz2 filter=lfs diff=lfs merge=lfs -text
|
| 5 |
+
*.ckpt filter=lfs diff=lfs merge=lfs -text
|
| 6 |
+
*.ftz filter=lfs diff=lfs merge=lfs -text
|
| 7 |
+
*.gz filter=lfs diff=lfs merge=lfs -text
|
| 8 |
+
*.h5 filter=lfs diff=lfs merge=lfs -text
|
| 9 |
+
*.joblib filter=lfs diff=lfs merge=lfs -text
|
| 10 |
+
*.lfs.* filter=lfs diff=lfs merge=lfs -text
|
| 11 |
+
*.mlmodel filter=lfs diff=lfs merge=lfs -text
|
| 12 |
+
*.model filter=lfs diff=lfs merge=lfs -text
|
| 13 |
+
*.msgpack filter=lfs diff=lfs merge=lfs -text
|
| 14 |
+
*.npy filter=lfs diff=lfs merge=lfs -text
|
| 15 |
+
*.npz filter=lfs diff=lfs merge=lfs -text
|
| 16 |
+
*.onnx filter=lfs diff=lfs merge=lfs -text
|
| 17 |
+
*.ot filter=lfs diff=lfs merge=lfs -text
|
| 18 |
+
*.parquet filter=lfs diff=lfs merge=lfs -text
|
| 19 |
+
*.pb filter=lfs diff=lfs merge=lfs -text
|
| 20 |
+
*.pickle filter=lfs diff=lfs merge=lfs -text
|
| 21 |
+
*.pkl filter=lfs diff=lfs merge=lfs -text
|
| 22 |
+
*.pt filter=lfs diff=lfs merge=lfs -text
|
| 23 |
+
*.pth filter=lfs diff=lfs merge=lfs -text
|
| 24 |
+
*.rar filter=lfs diff=lfs merge=lfs -text
|
| 25 |
+
*.safetensors filter=lfs diff=lfs merge=lfs -text
|
| 26 |
+
saved_model/**/* filter=lfs diff=lfs merge=lfs -text
|
| 27 |
+
*.tar.* filter=lfs diff=lfs merge=lfs -text
|
| 28 |
+
*.tar filter=lfs diff=lfs merge=lfs -text
|
| 29 |
+
*.tflite filter=lfs diff=lfs merge=lfs -text
|
| 30 |
+
*.tgz filter=lfs diff=lfs merge=lfs -text
|
| 31 |
+
*.wasm filter=lfs diff=lfs merge=lfs -text
|
| 32 |
+
*.xz filter=lfs diff=lfs merge=lfs -text
|
| 33 |
+
*.zip filter=lfs diff=lfs merge=lfs -text
|
| 34 |
+
*.zst filter=lfs diff=lfs merge=lfs -text
|
| 35 |
+
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
.gitignore
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
.idea/
|
| 2 |
+
.vscode/
|
| 3 |
+
workdir/mathjax-full/
|
| 4 |
+
workdir/res.html
|
| 5 |
+
workdir/pre/mma2sympy_input.txt
|
| 6 |
+
workdir/pre/mma2sympy_output.py
|
| 7 |
+
pre.nb
|
| 8 |
+
*__pycache__*
|
| 9 |
+
test.*
|
| 10 |
+
rename.sh
|
README.md
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
title: Note that * QED
|
| 3 |
+
emoji: 🤓
|
| 4 |
+
colorFrom: indigo
|
| 5 |
+
colorTo: green
|
| 6 |
+
sdk: gradio
|
| 7 |
+
sdk_version: 5.22.0
|
| 8 |
+
app_file: app.py
|
| 9 |
+
pinned: false
|
| 10 |
+
license: mit
|
| 11 |
+
short_description: Compare sizes by 'Note that' proof
|
| 12 |
+
---
|
app.py
ADDED
|
@@ -0,0 +1,221 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import os
|
| 2 |
+
import gradio as gr
|
| 3 |
+
from solution import solutions
|
| 4 |
+
from sympy.core.numbers import Rational
|
| 5 |
+
|
| 6 |
+
EN_US = os.getenv("LANG") != "zh_CN.UTF-8"
|
| 7 |
+
ZH2EN = {
|
| 8 |
+
"# “注意到”证明法比较大小": "# Compare sizes by 'Note that' proof",
|
| 9 |
+
"比较 e^(m/n) 与 u/v 大小": "Compare e^(m/n) and u/v",
|
| 10 |
+
"分母不能为 0": "The denominator cannot be 0",
|
| 11 |
+
"比较 π^n 与 p/q 大小": "Compare π^n and p/q",
|
| 12 |
+
"比较 e 与 p/q 大小": "Compare e and p/q",
|
| 13 |
+
"比较 π 与 p/q 大小": "Compare π and p/q",
|
| 14 |
+
"#### 证明结果": "#### Proof result",
|
| 15 |
+
"注意到": "Note that",
|
| 16 |
+
"状态栏": "Status",
|
| 17 |
+
"证毕!": "QED",
|
| 18 |
+
}
|
| 19 |
+
|
| 20 |
+
|
| 21 |
+
def _L(zh_txt: str):
|
| 22 |
+
return ZH2EN[zh_txt] if EN_US else zh_txt
|
| 23 |
+
|
| 24 |
+
|
| 25 |
+
def generate_md(args_dict, name):
|
| 26 |
+
ans_latex = solutions[name](**args_dict).get_latex_ans()
|
| 27 |
+
return f"{_L('注意到')} $${ans_latex}$$ {_L('证毕!')}"
|
| 28 |
+
|
| 29 |
+
|
| 30 |
+
def float_to_fraction(x):
|
| 31 |
+
x_str = "{0:.10f}".format(x).rstrip("0").rstrip(".") # 移除小数点后的无效零
|
| 32 |
+
|
| 33 |
+
# 检查是否为整数
|
| 34 |
+
if "." not in x_str:
|
| 35 |
+
return Rational(x_str), Rational(1)
|
| 36 |
+
|
| 37 |
+
# 分割整数部分和小数部分
|
| 38 |
+
integer_part, decimal_part = x_str.split(".")
|
| 39 |
+
decimal_digits = len(decimal_part)
|
| 40 |
+
|
| 41 |
+
# 构造分子和分母
|
| 42 |
+
numerator = int(integer_part + decimal_part)
|
| 43 |
+
denominator = 10**decimal_digits
|
| 44 |
+
|
| 45 |
+
# 简化分数
|
| 46 |
+
gcd_value = 1
|
| 47 |
+
a = numerator
|
| 48 |
+
b = denominator
|
| 49 |
+
while b != 0:
|
| 50 |
+
a, b = b, a % b
|
| 51 |
+
gcd_value = a
|
| 52 |
+
|
| 53 |
+
p = Rational(numerator // gcd_value)
|
| 54 |
+
q = Rational(denominator // gcd_value)
|
| 55 |
+
return p, q
|
| 56 |
+
|
| 57 |
+
|
| 58 |
+
def infer_pi(p, q):
|
| 59 |
+
status = "Success"
|
| 60 |
+
proof = None
|
| 61 |
+
try:
|
| 62 |
+
if q == 0:
|
| 63 |
+
raise ValueError(_L("分母不能为 0"))
|
| 64 |
+
|
| 65 |
+
p, q = float_to_fraction(p / q)
|
| 66 |
+
args_dict = {"p": p, "q": q}
|
| 67 |
+
proof = generate_md(args_dict, "π")
|
| 68 |
+
|
| 69 |
+
except Exception as e:
|
| 70 |
+
status = f"{e}"
|
| 71 |
+
|
| 72 |
+
return status, proof
|
| 73 |
+
|
| 74 |
+
|
| 75 |
+
def infer_e(p, q):
|
| 76 |
+
status = "Success"
|
| 77 |
+
proof = None
|
| 78 |
+
try:
|
| 79 |
+
if q == 0:
|
| 80 |
+
raise ValueError(_L("分母不能为 0"))
|
| 81 |
+
|
| 82 |
+
p, q = float_to_fraction(p / q)
|
| 83 |
+
args_dict = {"p": p, "q": q}
|
| 84 |
+
proof = generate_md(args_dict, "e")
|
| 85 |
+
|
| 86 |
+
except Exception as e:
|
| 87 |
+
status = f"{e}"
|
| 88 |
+
|
| 89 |
+
return status, proof
|
| 90 |
+
|
| 91 |
+
|
| 92 |
+
def infer_eq(q1, q2, u, v):
|
| 93 |
+
status = "Success"
|
| 94 |
+
proof = None
|
| 95 |
+
try:
|
| 96 |
+
if q2 == 0 or v == 0:
|
| 97 |
+
raise ValueError(_L("分母不能为 0"))
|
| 98 |
+
|
| 99 |
+
q1, q2 = float_to_fraction(q1 / q2)
|
| 100 |
+
u, v = float_to_fraction(u / v)
|
| 101 |
+
args_dict = {"q1": q1, "q2": q2, "u": u, "v": v}
|
| 102 |
+
proof = generate_md(args_dict, "e^q")
|
| 103 |
+
|
| 104 |
+
except Exception as e:
|
| 105 |
+
status = f"{e}"
|
| 106 |
+
|
| 107 |
+
return status, proof
|
| 108 |
+
|
| 109 |
+
|
| 110 |
+
def infer_pin(n: int, p, q):
|
| 111 |
+
status = "Success"
|
| 112 |
+
proof = None
|
| 113 |
+
try:
|
| 114 |
+
if q == 0:
|
| 115 |
+
raise ValueError(_L("分母不能为 0"))
|
| 116 |
+
|
| 117 |
+
p, q = float_to_fraction(p / q)
|
| 118 |
+
args_dict = {"n": n, "p": p, "q": q}
|
| 119 |
+
proof = generate_md(args_dict, "π^n")
|
| 120 |
+
|
| 121 |
+
except Exception as e:
|
| 122 |
+
status = f"{e}"
|
| 123 |
+
|
| 124 |
+
return status, proof
|
| 125 |
+
|
| 126 |
+
|
| 127 |
+
if __name__ == "__main__":
|
| 128 |
+
os.chdir(os.path.dirname(__file__))
|
| 129 |
+
for file_name in os.listdir("solutions"):
|
| 130 |
+
if not file_name.endswith(".py"):
|
| 131 |
+
continue
|
| 132 |
+
|
| 133 |
+
__import__(f"solutions.{file_name[:-3]}")
|
| 134 |
+
|
| 135 |
+
with gr.Blocks() as demo:
|
| 136 |
+
gr.Markdown(_L("# “注意到”证明法比较大小"))
|
| 137 |
+
with gr.Tabs():
|
| 138 |
+
with gr.TabItem("π"):
|
| 139 |
+
gr.Interface(
|
| 140 |
+
fn=infer_pi,
|
| 141 |
+
inputs=[
|
| 142 |
+
gr.Number(label="p", value=314),
|
| 143 |
+
gr.Number(label="q", value=100),
|
| 144 |
+
],
|
| 145 |
+
outputs=[
|
| 146 |
+
gr.Textbox(label=_L("状态栏"), show_copy_button=True),
|
| 147 |
+
gr.Markdown(
|
| 148 |
+
value=_L("#### 证明结果"),
|
| 149 |
+
show_copy_button=True,
|
| 150 |
+
container=True,
|
| 151 |
+
min_height=122,
|
| 152 |
+
),
|
| 153 |
+
],
|
| 154 |
+
title=_L("比较 π 与 p/q 大小"),
|
| 155 |
+
flagging_mode="never",
|
| 156 |
+
)
|
| 157 |
+
|
| 158 |
+
with gr.TabItem("e"):
|
| 159 |
+
gr.Interface(
|
| 160 |
+
fn=infer_e,
|
| 161 |
+
inputs=[
|
| 162 |
+
gr.Number(label="p", value=2718),
|
| 163 |
+
gr.Number(label="q", value=1000),
|
| 164 |
+
],
|
| 165 |
+
outputs=[
|
| 166 |
+
gr.Textbox(label=_L("状态栏"), show_copy_button=True),
|
| 167 |
+
gr.Markdown(
|
| 168 |
+
value=_L("#### 证明结果"),
|
| 169 |
+
show_copy_button=True,
|
| 170 |
+
container=True,
|
| 171 |
+
min_height=122,
|
| 172 |
+
),
|
| 173 |
+
],
|
| 174 |
+
title=_L("比较 e 与 p/q 大小"),
|
| 175 |
+
flagging_mode="never",
|
| 176 |
+
)
|
| 177 |
+
|
| 178 |
+
with gr.TabItem("e^q"):
|
| 179 |
+
gr.Interface(
|
| 180 |
+
fn=infer_eq,
|
| 181 |
+
inputs=[
|
| 182 |
+
gr.Number(label="m", value=3),
|
| 183 |
+
gr.Number(label="n", value=4),
|
| 184 |
+
gr.Number(label="u", value=2117),
|
| 185 |
+
gr.Number(label="v", value=1000),
|
| 186 |
+
],
|
| 187 |
+
outputs=[
|
| 188 |
+
gr.Textbox(label=_L("状态栏"), show_copy_button=True),
|
| 189 |
+
gr.Markdown(
|
| 190 |
+
value=_L("#### 证明结果"),
|
| 191 |
+
show_copy_button=True,
|
| 192 |
+
container=True,
|
| 193 |
+
min_height=122,
|
| 194 |
+
),
|
| 195 |
+
],
|
| 196 |
+
title=_L("比较 e^(m/n) 与 u/v 大小"),
|
| 197 |
+
flagging_mode="never",
|
| 198 |
+
)
|
| 199 |
+
|
| 200 |
+
with gr.TabItem("π^n"):
|
| 201 |
+
gr.Interface(
|
| 202 |
+
fn=infer_pin,
|
| 203 |
+
inputs=[
|
| 204 |
+
gr.Number(label="n", value=3, step=1),
|
| 205 |
+
gr.Number(label="p", value=31),
|
| 206 |
+
gr.Number(label="q", value=1),
|
| 207 |
+
],
|
| 208 |
+
outputs=[
|
| 209 |
+
gr.Textbox(label=_L("状态栏"), show_copy_button=True),
|
| 210 |
+
gr.Markdown(
|
| 211 |
+
value=_L("#### 证明结果"),
|
| 212 |
+
show_copy_button=True,
|
| 213 |
+
container=True,
|
| 214 |
+
min_height=122,
|
| 215 |
+
),
|
| 216 |
+
],
|
| 217 |
+
title=_L("比较 π^n 与 p/q 大小"),
|
| 218 |
+
flagging_mode="never",
|
| 219 |
+
)
|
| 220 |
+
|
| 221 |
+
demo.launch()
|
output_util.py
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from sympy import latex
|
| 2 |
+
|
| 3 |
+
|
| 4 |
+
def to_latex(expr, is_coeff=False):
|
| 5 |
+
return "" if is_coeff and expr == 1 else f"{{{latex(expr)}}}"
|
| 6 |
+
|
| 7 |
+
|
| 8 |
+
def to_latexes(*args, is_coeff=False):
|
| 9 |
+
return [to_latex(i, is_coeff=is_coeff) for i in args]
|
| 10 |
+
|
| 11 |
+
|
| 12 |
+
sign2cmp = {1: ">", -1: "<"}
|
| 13 |
+
|
| 14 |
+
sign2cmp_inv = {1: "<", -1: ">"}
|
requirements.txt
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
sympy~=1.12
|
| 2 |
+
pywebview~=5.3.2
|
| 3 |
+
ttkbootstrap~=1.10.1
|
sgntools.py
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
def sgns(*args):
|
| 2 |
+
for i in args:
|
| 3 |
+
if i < 0:
|
| 4 |
+
break
|
| 5 |
+
else:
|
| 6 |
+
return 1
|
| 7 |
+
|
| 8 |
+
for i in args:
|
| 9 |
+
if i > 0:
|
| 10 |
+
break
|
| 11 |
+
else:
|
| 12 |
+
return -1
|
| 13 |
+
|
| 14 |
+
return 0
|
| 15 |
+
|
| 16 |
+
|
| 17 |
+
def sq_func_sgn(a, b, c):
|
| 18 |
+
r"""
|
| 19 |
+
let f(x) = a+bx+cx^2, x \in [0, 1]
|
| 20 |
+
:return: f(x)>=0? 1; f(x)<=0? -1; 0
|
| 21 |
+
"""
|
| 22 |
+
f0 = a
|
| 23 |
+
f1 = a + b + c
|
| 24 |
+
fm = 0
|
| 25 |
+
if c != 0:
|
| 26 |
+
x_m = -b / (2 * c)
|
| 27 |
+
if 0 <= x_m <= 1:
|
| 28 |
+
fm = a + b * x_m + c * x_m**2
|
| 29 |
+
|
| 30 |
+
return sgns(f0, f1, fm)
|
| 31 |
+
|
| 32 |
+
|
| 33 |
+
def lin_func_sgn(a, b):
|
| 34 |
+
return sgns(a, a + b)
|
solution.py
ADDED
|
@@ -0,0 +1,132 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from typing import Iterable, Callable
|
| 2 |
+
from sympy import Eq, Expr, Symbol, linsolve, simplify, latex
|
| 3 |
+
|
| 4 |
+
|
| 5 |
+
class CannotCalculate(Exception):
|
| 6 |
+
pass
|
| 7 |
+
|
| 8 |
+
|
| 9 |
+
class BadInput(Exception):
|
| 10 |
+
pass
|
| 11 |
+
|
| 12 |
+
|
| 13 |
+
CONSTANT_TERM_KEY = "constant_term"
|
| 14 |
+
|
| 15 |
+
|
| 16 |
+
class GetIntegrate:
|
| 17 |
+
integrate_result_classes: dict[str, Expr | None]
|
| 18 |
+
|
| 19 |
+
def integrate_and_separate(
|
| 20 |
+
self, integrate_formula: Expr, integrate_args: tuple
|
| 21 |
+
) -> dict[str, Expr]:
|
| 22 |
+
"""
|
| 23 |
+
解积分,分离各项
|
| 24 |
+
"""
|
| 25 |
+
raise NotImplementedError(
|
| 26 |
+
"该函数已弃用,请使用 GetIntegrateFromData 类。如果想要使用它预处理,见 pre/old_solution.py"
|
| 27 |
+
)
|
| 28 |
+
|
| 29 |
+
def get_integrate_args(self, try_arg):
|
| 30 |
+
"""
|
| 31 |
+
:return: integrand_function, (independent_variable, lower_limit, upper_limit)
|
| 32 |
+
被积函数, (自变量, 下限, 上限)
|
| 33 |
+
"""
|
| 34 |
+
raise NotImplementedError()
|
| 35 |
+
|
| 36 |
+
def tries(self, try_arg):
|
| 37 |
+
"""
|
| 38 |
+
:return: {term_name: coefficient_of_the_term}
|
| 39 |
+
{该项的名称: 该项系数}
|
| 40 |
+
"""
|
| 41 |
+
return self.integrate_and_separate(*self.get_integrate_args(try_arg))
|
| 42 |
+
|
| 43 |
+
def get_latex(self, try_arg, subs):
|
| 44 |
+
expr, args = self.get_integrate_args(try_arg)
|
| 45 |
+
expr = simplify(expr).subs(subs)
|
| 46 |
+
sym, low, high = args
|
| 47 |
+
return r"\int_{%s}^{%s} {%s} \mathrm{d} {%s}" % (
|
| 48 |
+
low,
|
| 49 |
+
high,
|
| 50 |
+
latex(simplify(expr)),
|
| 51 |
+
sym,
|
| 52 |
+
)
|
| 53 |
+
|
| 54 |
+
|
| 55 |
+
class GetIntegrateFromData(GetIntegrate):
|
| 56 |
+
data: dict[object, dict[str, Expr]]
|
| 57 |
+
|
| 58 |
+
def tries(self, try_arg):
|
| 59 |
+
return self.data[try_arg]
|
| 60 |
+
|
| 61 |
+
|
| 62 |
+
class Solution:
|
| 63 |
+
get_integrate: GetIntegrate
|
| 64 |
+
# gui: Pattern
|
| 65 |
+
|
| 66 |
+
get_tries_args: Callable[[], Iterable[Expr]]
|
| 67 |
+
"""
|
| 68 |
+
Generate try_arg for each trial
|
| 69 |
+
生成每一次尝试的 try_arg
|
| 70 |
+
"""
|
| 71 |
+
|
| 72 |
+
symbols: tuple[Symbol, ...]
|
| 73 |
+
"""
|
| 74 |
+
The undetermined variable to solve.
|
| 75 |
+
要求的待定系数
|
| 76 |
+
"""
|
| 77 |
+
|
| 78 |
+
integrate_result_classes_eq: dict[str, Expr]
|
| 79 |
+
"""
|
| 80 |
+
{term_name: coefficient}
|
| 81 |
+
The value to which each term's coefficient is equal.
|
| 82 |
+
每个项系数分别要等于的值
|
| 83 |
+
"""
|
| 84 |
+
|
| 85 |
+
check_sgn: Callable
|
| 86 |
+
"""
|
| 87 |
+
Input: unpacked solution of undetermined variables;
|
| 88 |
+
Output: 0 (cannot determine), 1 or -1 (can determine; 1 and -1 are interchangeable for greater or less than).
|
| 89 |
+
Module sgntools provides lin_func_sgn and sq_func_sgn. Call help() for further details.
|
| 90 |
+
|
| 91 |
+
输入:解包的待定系数的值列表;
|
| 92 |
+
输出: 0(无法确定), 1或-1(可以确定, 1和-1哪个代表大于、哪个代表小于, 是可以互换的)
|
| 93 |
+
sgntools 模块提供了 lin_func_sgn 和 sq_func_sgn 函数,详见 help()
|
| 94 |
+
"""
|
| 95 |
+
# check_sgn: Callable[?, 1 | 0 | -1]
|
| 96 |
+
|
| 97 |
+
def get_symbols(self, separate_result):
|
| 98 |
+
"""凑积分结果系数"""
|
| 99 |
+
system = [
|
| 100 |
+
Eq(int_term, self.integrate_result_classes_eq[key])
|
| 101 |
+
for key, int_term in separate_result.items()
|
| 102 |
+
]
|
| 103 |
+
print(f"{system=}")
|
| 104 |
+
return linsolve(system, *self.symbols)
|
| 105 |
+
|
| 106 |
+
def try_times(self) -> tuple[Expr, dict, int] | tuple[None, None, None]:
|
| 107 |
+
for try_arg in self.get_tries_args():
|
| 108 |
+
separate = self.get_integrate.tries(try_arg)
|
| 109 |
+
for symbol_solution in self.get_symbols(separate):
|
| 110 |
+
if sgn := self.check_sgn(*symbol_solution):
|
| 111 |
+
return try_arg, dict(zip(self.symbols, symbol_solution)), sgn
|
| 112 |
+
|
| 113 |
+
return None, None, None
|
| 114 |
+
|
| 115 |
+
def get_latex_ans(self):
|
| 116 |
+
"""
|
| 117 |
+
:return: None if it can't be solved; Otherwise, LaTeX (without "$$")
|
| 118 |
+
"""
|
| 119 |
+
raise NotImplementedError()
|
| 120 |
+
|
| 121 |
+
|
| 122 |
+
# 插件注册(历史遗留问题)
|
| 123 |
+
solutions = {}
|
| 124 |
+
solution_sort = []
|
| 125 |
+
|
| 126 |
+
|
| 127 |
+
def register(name, solution, top=False):
|
| 128 |
+
solutions[name] = solution
|
| 129 |
+
if top:
|
| 130 |
+
solution_sort.insert(0, name)
|
| 131 |
+
else:
|
| 132 |
+
solution_sort.append(name)
|
solutions/e.py
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from sympy import *
|
| 2 |
+
from sympy.abc import a, b, x
|
| 3 |
+
from output_util import to_latex, sign2cmp
|
| 4 |
+
from sgntools import lin_func_sgn
|
| 5 |
+
from solution import *
|
| 6 |
+
|
| 7 |
+
_data = {
|
| 8 |
+
1: {"constant_term": 3 * a - 8 * b, "e_term": -a + 3 * b},
|
| 9 |
+
2: {"constant_term": -38 * a + 174 * b, "e_term": 14 * a - 64 * b},
|
| 10 |
+
3: {"constant_term": 1158 * a - 7584 * b, "e_term": -426 * a + 2790 * b},
|
| 11 |
+
4: {"constant_term": -65304 * a + 557400 * b, "e_term": 24024 * a - 205056 * b},
|
| 12 |
+
5: {
|
| 13 |
+
"constant_term": 5900520 * a - 62118720 * b,
|
| 14 |
+
"e_term": -2170680 * a + 22852200 * b,
|
| 15 |
+
},
|
| 16 |
+
6: {
|
| 17 |
+
"constant_term": -780827760 * a + 9778048560 * b,
|
| 18 |
+
"e_term": 287250480 * a - 3597143040 * b,
|
| 19 |
+
},
|
| 20 |
+
}
|
| 21 |
+
|
| 22 |
+
|
| 23 |
+
class EIntegrate(GetIntegrateFromData):
|
| 24 |
+
# sympy 算力不够,以下由 MMA 算出
|
| 25 |
+
data = _data
|
| 26 |
+
|
| 27 |
+
def get_integrate_args(self, n):
|
| 28 |
+
return x**n * (1 - x) ** n * (a + b * x) * exp(x), (x, 0, 1)
|
| 29 |
+
|
| 30 |
+
|
| 31 |
+
class ESolution(Solution):
|
| 32 |
+
def __init__(self, p, q):
|
| 33 |
+
self.p = p
|
| 34 |
+
self.q = q
|
| 35 |
+
if self.q == 0:
|
| 36 |
+
raise BadInput()
|
| 37 |
+
|
| 38 |
+
self.get_integrate = EIntegrate()
|
| 39 |
+
self.symbols = (a, b)
|
| 40 |
+
|
| 41 |
+
self.integrate_result_classes_eq = {
|
| 42 |
+
"e_term": q,
|
| 43 |
+
CONSTANT_TERM_KEY: -p,
|
| 44 |
+
}
|
| 45 |
+
# check
|
| 46 |
+
self.check_sgn = lin_func_sgn
|
| 47 |
+
|
| 48 |
+
@staticmethod
|
| 49 |
+
def get_tries_args():
|
| 50 |
+
return EIntegrate.data.keys()
|
| 51 |
+
|
| 52 |
+
def get_latex_ans(self):
|
| 53 |
+
try_arg, symbol_val, sgn = self.try_times()
|
| 54 |
+
print(f"{(try_arg, symbol_val, sgn)=}")
|
| 55 |
+
if try_arg is None:
|
| 56 |
+
return None
|
| 57 |
+
|
| 58 |
+
p = to_latex(self.p)
|
| 59 |
+
q = to_latex(self.q, is_coeff=True)
|
| 60 |
+
I = self.get_integrate.get_latex(try_arg, symbol_val)
|
| 61 |
+
return rf"{q}e-{p} = {I} {sign2cmp[sgn]} 0"
|
| 62 |
+
|
| 63 |
+
|
| 64 |
+
register("e", ESolution)
|
| 65 |
+
|
| 66 |
+
|
| 67 |
+
if __name__ == "__main__":
|
| 68 |
+
print(ESolution(25, 9))
|
solutions/eq.py
ADDED
|
@@ -0,0 +1,179 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from sympy import *
|
| 2 |
+
from sympy.abc import *
|
| 3 |
+
from output_util import to_latex, sign2cmp, to_latexes
|
| 4 |
+
from sgntools import lin_func_sgn
|
| 5 |
+
from solution import *
|
| 6 |
+
|
| 7 |
+
_data = {
|
| 8 |
+
(1,): {
|
| 9 |
+
"constant_term": a / q**2 + 2 * a / q**3 - 2 * b / q**3 - 6 * b / q**4,
|
| 10 |
+
"eq_term": a / q**2 - 2 * a / q**3 + b / q**2 - 4 * b / q**3 + 6 * b / q**4,
|
| 11 |
+
},
|
| 12 |
+
(2,): {
|
| 13 |
+
"constant_term": -2 * a / q**3
|
| 14 |
+
- 12 * a / q**4
|
| 15 |
+
- 24 * a / q**5
|
| 16 |
+
+ 6 * b / q**4
|
| 17 |
+
+ 48 * b / q**5
|
| 18 |
+
+ 120 * b / q**6,
|
| 19 |
+
"eq_term": 2 * a / q**3
|
| 20 |
+
- 12 * a / q**4
|
| 21 |
+
+ 24 * a / q**5
|
| 22 |
+
+ 2 * b / q**3
|
| 23 |
+
- 18 * b / q**4
|
| 24 |
+
+ 72 * b / q**5
|
| 25 |
+
- 120 * b / q**6,
|
| 26 |
+
},
|
| 27 |
+
(3,): {
|
| 28 |
+
"constant_term": 6 * a / q**4
|
| 29 |
+
+ 72 * a / q**5
|
| 30 |
+
+ 360 * a / q**6
|
| 31 |
+
+ 720 * a / q**7
|
| 32 |
+
- 24 * b / q**5
|
| 33 |
+
- 360 * b / q**6
|
| 34 |
+
- 2160 * b / q**7
|
| 35 |
+
- 5040 * b / q**8,
|
| 36 |
+
"eq_term": 6 * a / q**4
|
| 37 |
+
- 72 * a / q**5
|
| 38 |
+
+ 360 * a / q**6
|
| 39 |
+
- 720 * a / q**7
|
| 40 |
+
+ 6 * b / q**4
|
| 41 |
+
- 96 * b / q**5
|
| 42 |
+
+ 720 * b / q**6
|
| 43 |
+
- 2880 * b / q**7
|
| 44 |
+
+ 5040 * b / q**8,
|
| 45 |
+
},
|
| 46 |
+
(4,): {
|
| 47 |
+
"constant_term": -24 * a / q**5
|
| 48 |
+
- 480 * a / q**6
|
| 49 |
+
- 4320 * a / q**7
|
| 50 |
+
- 20160 * a / q**8
|
| 51 |
+
- 40320 * a / q**9
|
| 52 |
+
+ 120 * b / q**6
|
| 53 |
+
+ 2880 * b / q**7
|
| 54 |
+
+ 30240 * b / q**8
|
| 55 |
+
+ 161280 * b / q**9
|
| 56 |
+
+ 362880 * b / q**10,
|
| 57 |
+
"eq_term": 24 * a / q**5
|
| 58 |
+
- 480 * a / q**6
|
| 59 |
+
+ 4320 * a / q**7
|
| 60 |
+
- 20160 * a / q**8
|
| 61 |
+
+ 40320 * a / q**9
|
| 62 |
+
+ 24 * b / q**5
|
| 63 |
+
- 600 * b / q**6
|
| 64 |
+
+ 7200 * b / q**7
|
| 65 |
+
- 50400 * b / q**8
|
| 66 |
+
+ 201600 * b / q**9
|
| 67 |
+
- 362880 * b / q**10,
|
| 68 |
+
},
|
| 69 |
+
(5,): {
|
| 70 |
+
"constant_term": 120 * a / q**6
|
| 71 |
+
+ 3600 * a / q**7
|
| 72 |
+
+ 50400 * a / q**8
|
| 73 |
+
+ 403200 * a / q**9
|
| 74 |
+
+ 1814400 * a / q**10
|
| 75 |
+
+ 3628800 * a / q**11
|
| 76 |
+
- 720 * b / q**7
|
| 77 |
+
- 25200 * b / q**8
|
| 78 |
+
- 403200 * b / q**9
|
| 79 |
+
- 3628800 * b / q**10
|
| 80 |
+
- 18144000 * b / q**11
|
| 81 |
+
- 39916800 * b / q**12,
|
| 82 |
+
"eq_term": 120 * a / q**6
|
| 83 |
+
- 3600 * a / q**7
|
| 84 |
+
+ 50400 * a / q**8
|
| 85 |
+
- 403200 * a / q**9
|
| 86 |
+
+ 1814400 * a / q**10
|
| 87 |
+
- 3628800 * a / q**11
|
| 88 |
+
+ 120 * b / q**6
|
| 89 |
+
- 4320 * b / q**7
|
| 90 |
+
+ 75600 * b / q**8
|
| 91 |
+
- 806400 * b / q**9
|
| 92 |
+
+ 5443200 * b / q**10
|
| 93 |
+
- 21772800 * b / q**11
|
| 94 |
+
+ 39916800 * b / q**12,
|
| 95 |
+
},
|
| 96 |
+
(6,): {
|
| 97 |
+
"constant_term": -720 * a / q**7
|
| 98 |
+
- 30240 * a / q**8
|
| 99 |
+
- 604800 * a / q**9
|
| 100 |
+
- 7257600 * a / q**10
|
| 101 |
+
- 54432000 * a / q**11
|
| 102 |
+
- 239500800 * a / q**12
|
| 103 |
+
- 479001600 * a / q**13
|
| 104 |
+
+ 5040 * b / q**8
|
| 105 |
+
+ 241920 * b / q**9
|
| 106 |
+
+ 5443200 * b / q**10
|
| 107 |
+
+ 72576000 * b / q**11
|
| 108 |
+
+ 598752000 * b / q**12
|
| 109 |
+
+ 2874009600 * b / q**13
|
| 110 |
+
+ 6227020800 * b / q**14,
|
| 111 |
+
"eq_term": 720 * a / q**7
|
| 112 |
+
- 30240 * a / q**8
|
| 113 |
+
+ 604800 * a / q**9
|
| 114 |
+
- 7257600 * a / q**10
|
| 115 |
+
+ 54432000 * a / q**11
|
| 116 |
+
- 239500800 * a / q**12
|
| 117 |
+
+ 479001600 * a / q**13
|
| 118 |
+
+ 720 * b / q**7
|
| 119 |
+
- 35280 * b / q**8
|
| 120 |
+
+ 846720 * b / q**9
|
| 121 |
+
- 12700800 * b / q**10
|
| 122 |
+
+ 127008000 * b / q**11
|
| 123 |
+
- 838252800 * b / q**12
|
| 124 |
+
+ 3353011200 * b / q**13
|
| 125 |
+
- 6227020800 * b / q**14,
|
| 126 |
+
},
|
| 127 |
+
}
|
| 128 |
+
|
| 129 |
+
|
| 130 |
+
class EQIntegrate(GetIntegrateFromData):
|
| 131 |
+
data = _data
|
| 132 |
+
|
| 133 |
+
def get_integrate_args(self, try_arg):
|
| 134 |
+
n, q = try_arg
|
| 135 |
+
return x**n * (1 - x) ** n * (a + b * x) * e ** (q * x), (x, 0, 1)
|
| 136 |
+
|
| 137 |
+
def tries(self, try_arg):
|
| 138 |
+
n, q_value = try_arg
|
| 139 |
+
return {key: expr.subs(q, q_value) for key, expr in self.data[(n,)].items()}
|
| 140 |
+
|
| 141 |
+
|
| 142 |
+
class EQSolution(Solution):
|
| 143 |
+
def __init__(self, q1, q2, u, v):
|
| 144 |
+
if q2 == 0 or v == 0:
|
| 145 |
+
raise BadInput()
|
| 146 |
+
|
| 147 |
+
self.q = q1 / q2 # 输入都是 Rational 类型的,可以不损失精度相除
|
| 148 |
+
self.u = u
|
| 149 |
+
self.v = v
|
| 150 |
+
self.get_integrate = EQIntegrate()
|
| 151 |
+
self.symbols = (a, b)
|
| 152 |
+
self.integrate_result_classes_eq = {
|
| 153 |
+
"eq_term": v,
|
| 154 |
+
CONSTANT_TERM_KEY: -u,
|
| 155 |
+
}
|
| 156 |
+
# check
|
| 157 |
+
self.check_sgn = lin_func_sgn
|
| 158 |
+
|
| 159 |
+
def get_tries_args(self):
|
| 160 |
+
for (n,) in EQIntegrate.data.keys():
|
| 161 |
+
yield n, self.q
|
| 162 |
+
|
| 163 |
+
def get_latex_ans(self):
|
| 164 |
+
try_arg, symbol_val, sgn = self.try_times()
|
| 165 |
+
print(f"{(try_arg, symbol_val, sgn)=}")
|
| 166 |
+
if try_arg is None:
|
| 167 |
+
return None
|
| 168 |
+
|
| 169 |
+
u, q = to_latexes(self.u, self.q)
|
| 170 |
+
v = to_latex(self.v, is_coeff=True)
|
| 171 |
+
I = self.get_integrate.get_latex(try_arg, symbol_val)
|
| 172 |
+
return rf"{v}e^{q}-{u} = {I} {sign2cmp[sgn]} 0"
|
| 173 |
+
|
| 174 |
+
|
| 175 |
+
register("e^q", EQSolution)
|
| 176 |
+
|
| 177 |
+
|
| 178 |
+
if __name__ == "__main__":
|
| 179 |
+
print(EQSolution(Rational(2), 1, 7, 1).get_latex_ans())
|
solutions/pi.py
ADDED
|
@@ -0,0 +1,136 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from sympy.abc import a, b, c, x
|
| 2 |
+
from output_util import to_latex, sign2cmp
|
| 3 |
+
from sgntools import sq_func_sgn
|
| 4 |
+
from solution import *
|
| 5 |
+
|
| 6 |
+
|
| 7 |
+
class PiIntegrate(GetIntegrateFromData):
|
| 8 |
+
# sympy 算力不够,以下由 MMA 算出
|
| 9 |
+
# PiIF[n_] :=
|
| 10 |
+
# Collect[ Collect[
|
| 11 |
+
# PowerExpand[ Expand[
|
| 12 |
+
# Integrate[x^n*(1 - x)^n*(a + b x + c x^2)/(x^2 + 1),
|
| 13 |
+
# {x, 0, 1}]
|
| 14 |
+
# ]],
|
| 15 |
+
# Log[2]], Pi]
|
| 16 |
+
data = {
|
| 17 |
+
1: {
|
| 18 |
+
"pi_term": (a - b - c) / 4,
|
| 19 |
+
"log2_term": (a + b - c) / 2,
|
| 20 |
+
CONSTANT_TERM_KEY: -a + b / 2 + 7 * c / 6,
|
| 21 |
+
},
|
| 22 |
+
2: {
|
| 23 |
+
"pi_term": -b / 2,
|
| 24 |
+
"log2_term": a - c,
|
| 25 |
+
CONSTANT_TERM_KEY: (-2 * a / 3 + 19 * b / 12 + 7 * c / 10),
|
| 26 |
+
},
|
| 27 |
+
3: {
|
| 28 |
+
"pi_term": (-a - b + c) / 2,
|
| 29 |
+
"log2_term": a - b - c,
|
| 30 |
+
CONSTANT_TERM_KEY: 53 * a / 60 + 34 * b / 15 - 92 * c / 105,
|
| 31 |
+
},
|
| 32 |
+
4: {
|
| 33 |
+
"pi_term": -a + c,
|
| 34 |
+
"log2_term": 2 * b,
|
| 35 |
+
CONSTANT_TERM_KEY: 22 * a / 7 + 233 * b / 168 - 1979 * c / 630,
|
| 36 |
+
},
|
| 37 |
+
5: {
|
| 38 |
+
"pi_term": -a + b + c,
|
| 39 |
+
"log2_term": 2 * (-a - b + c),
|
| 40 |
+
CONSTANT_TERM_KEY: 11411 * a / 2520 - 4423 * b / 2520 - 41837 * c / 9240,
|
| 41 |
+
},
|
| 42 |
+
6: {
|
| 43 |
+
"pi_term": 2 * b,
|
| 44 |
+
"log2_term": -4 * a + 4 * c,
|
| 45 |
+
CONSTANT_TERM_KEY: (38429 * a) / 13860
|
| 46 |
+
- (174169 * b) / 27720
|
| 47 |
+
- (35683 * c) / 12870,
|
| 48 |
+
},
|
| 49 |
+
7: {
|
| 50 |
+
"pi_term": 2 * (a + b - c),
|
| 51 |
+
"log2_term": 4 * (-a + b + c),
|
| 52 |
+
CONSTANT_TERM_KEY: -((421691 * a) / 120120)
|
| 53 |
+
- (407917 * b) / 45045
|
| 54 |
+
+ (31627 * c) / 9009,
|
| 55 |
+
},
|
| 56 |
+
8: {
|
| 57 |
+
"pi_term": 4 * (a - c),
|
| 58 |
+
"log2_term": 8 * b,
|
| 59 |
+
CONSTANT_TERM_KEY: -(188684 * a) / 15015
|
| 60 |
+
- (1332173 * b) / 240240
|
| 61 |
+
+ (3849155 * c) / 306306,
|
| 62 |
+
},
|
| 63 |
+
9: {
|
| 64 |
+
"pi_term": 4 * (a - b - c),
|
| 65 |
+
"log2_term": 8 * (-c + a + b),
|
| 66 |
+
CONSTANT_TERM_KEY: -((17069771 * a) / 942480)
|
| 67 |
+
+ (86025349 * b) / 12252240
|
| 68 |
+
+ (4216233689 * c) / 232792560,
|
| 69 |
+
},
|
| 70 |
+
10: {
|
| 71 |
+
"pi_term": -8 * b,
|
| 72 |
+
"log2_term": 16 * (a - c),
|
| 73 |
+
CONSTANT_TERM_KEY: -((1290876029 * a) / 116396280)
|
| 74 |
+
+ (325039733 * b) / 12932920
|
| 75 |
+
+ (117352369 * c) / 10581480,
|
| 76 |
+
},
|
| 77 |
+
11: {
|
| 78 |
+
"pi_term": 8 * (-a - b + c),
|
| 79 |
+
"log2_term": 16 * (a - b - c),
|
| 80 |
+
CONSTANT_TERM_KEY: (817240769 * a) / 58198140
|
| 81 |
+
+ (4216233641 * b) / 116396280
|
| 82 |
+
- (37593075209 * c) / 2677114440,
|
| 83 |
+
},
|
| 84 |
+
12: {
|
| 85 |
+
"pi_term": -16 * a + 16 * c,
|
| 86 |
+
"log2_term": -32 * b,
|
| 87 |
+
CONSTANT_TERM_KEY: (431302721 * a) / 8580495
|
| 88 |
+
+ (9135430531 * b) / 411863760
|
| 89 |
+
- (5902037233 * c) / 117417300,
|
| 90 |
+
},
|
| 91 |
+
}
|
| 92 |
+
|
| 93 |
+
def get_integrate_args(self, n):
|
| 94 |
+
return x**n * (1 - x) ** n * (a + b * x + c * x**2) / (1 + x**2), (x, 0, 1)
|
| 95 |
+
|
| 96 |
+
|
| 97 |
+
class PiSolution(Solution):
|
| 98 |
+
def __init__(self, p, q):
|
| 99 |
+
self.p = p
|
| 100 |
+
self.q = q
|
| 101 |
+
if self.q == 0:
|
| 102 |
+
raise BadInput()
|
| 103 |
+
|
| 104 |
+
self.get_integrate = PiIntegrate()
|
| 105 |
+
self.symbols = (a, b, c)
|
| 106 |
+
self.integrate_result_classes_eq = {
|
| 107 |
+
"pi_term": q,
|
| 108 |
+
"log2_term": 0,
|
| 109 |
+
CONSTANT_TERM_KEY: -p,
|
| 110 |
+
}
|
| 111 |
+
# check
|
| 112 |
+
self.check_sgn = sq_func_sgn
|
| 113 |
+
|
| 114 |
+
@staticmethod
|
| 115 |
+
def get_tries_args():
|
| 116 |
+
return PiIntegrate.data.keys()
|
| 117 |
+
|
| 118 |
+
def get_latex_ans(self):
|
| 119 |
+
try_arg, symbol_val, sgn = self.try_times()
|
| 120 |
+
print(f"{(try_arg, symbol_val, sgn)=}")
|
| 121 |
+
if try_arg is None:
|
| 122 |
+
return None
|
| 123 |
+
|
| 124 |
+
p = to_latex(self.p)
|
| 125 |
+
q = to_latex(self.q, is_coeff=True)
|
| 126 |
+
I = self.get_integrate.get_latex(try_arg, symbol_val)
|
| 127 |
+
return rf"{q}\pi-{p} = {I} {sign2cmp[sgn]} 0"
|
| 128 |
+
|
| 129 |
+
|
| 130 |
+
register("π", PiSolution, top=True)
|
| 131 |
+
|
| 132 |
+
if __name__ == "__main__":
|
| 133 |
+
while True:
|
| 134 |
+
p = int(input(">>> "))
|
| 135 |
+
q = int(input(" / "))
|
| 136 |
+
print(PiSolution(p, q).get_latex_ans())
|
solutions/pin.py
ADDED
|
@@ -0,0 +1,188 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from sympy import *
|
| 2 |
+
from sympy.abc import a, b, x
|
| 3 |
+
from output_util import to_latex, sign2cmp, to_latexes
|
| 4 |
+
from sgntools import lin_func_sgn
|
| 5 |
+
from solution import *
|
| 6 |
+
|
| 7 |
+
_data = {
|
| 8 |
+
(1, 2): {"constant_term": a - 2 * b / 3, "pin_term": -a / 4 + b / 4},
|
| 9 |
+
(1, 4): {"constant_term": -2 * a / 3 + 13 * b / 15, "pin_term": a / 4 - b / 4},
|
| 10 |
+
(1, 6): {"constant_term": 13 * a / 15 - 76 * b / 105, "pin_term": -a / 4 + b / 4},
|
| 11 |
+
(1, 8): {"constant_term": -76 * a / 105 + 263 * b / 315, "pin_term": a / 4 - b / 4},
|
| 12 |
+
(1, 10): {
|
| 13 |
+
"constant_term": 263 * a / 315 - 2578 * b / 3465,
|
| 14 |
+
"pin_term": -a / 4 + b / 4,
|
| 15 |
+
},
|
| 16 |
+
(1, 12): {
|
| 17 |
+
"constant_term": -2578 * a / 3465 + 36979 * b / 45045,
|
| 18 |
+
"pin_term": a / 4 - b / 4,
|
| 19 |
+
},
|
| 20 |
+
(2, 3): {"constant_term": a / 4 - 3 * b / 16, "pin_term": -a / 48 + b / 48},
|
| 21 |
+
(2, 5): {"constant_term": -3 * a / 16 + 31 * b / 144, "pin_term": a / 48 - b / 48},
|
| 22 |
+
(2, 7): {
|
| 23 |
+
"constant_term": 31 * a / 144 - 115 * b / 576,
|
| 24 |
+
"pin_term": -a / 48 + b / 48,
|
| 25 |
+
},
|
| 26 |
+
(2, 9): {
|
| 27 |
+
"constant_term": -115 * a / 576 + 3019 * b / 14400,
|
| 28 |
+
"pin_term": a / 48 - b / 48,
|
| 29 |
+
},
|
| 30 |
+
(2, 11): {
|
| 31 |
+
"constant_term": 3019 * a / 14400 - 973 * b / 4800,
|
| 32 |
+
"pin_term": -a / 48 + b / 48,
|
| 33 |
+
},
|
| 34 |
+
(2, 13): {
|
| 35 |
+
"constant_term": -973 * a / 4800 + 48877 * b / 235200,
|
| 36 |
+
"pin_term": a / 48 - b / 48,
|
| 37 |
+
},
|
| 38 |
+
(3, 2): {"constant_term": 2 * a - 52 * b / 27, "pin_term": -a / 16 + b / 16},
|
| 39 |
+
(3, 4): {
|
| 40 |
+
"constant_term": -52 * a / 27 + 6554 * b / 3375,
|
| 41 |
+
"pin_term": a / 16 - b / 16,
|
| 42 |
+
},
|
| 43 |
+
(3, 6): {
|
| 44 |
+
"constant_term": 6554 * a / 3375 - 2241272 * b / 1157625,
|
| 45 |
+
"pin_term": -a / 16 + b / 16,
|
| 46 |
+
},
|
| 47 |
+
(3, 8): {
|
| 48 |
+
"constant_term": -2241272 * a / 1157625 + 60600094 * b / 31255875,
|
| 49 |
+
"pin_term": a / 16 - b / 16,
|
| 50 |
+
},
|
| 51 |
+
(3, 10): {
|
| 52 |
+
"constant_term": 60600094 * a / 31255875 - 80596213364 * b / 41601569625,
|
| 53 |
+
"pin_term": -a / 16 + b / 16,
|
| 54 |
+
},
|
| 55 |
+
(3, 12): {
|
| 56 |
+
"constant_term": -80596213364 * a / 41601569625
|
| 57 |
+
+ 177153083899958 * b / 91398648466125,
|
| 58 |
+
"pin_term": a / 16 - b / 16,
|
| 59 |
+
},
|
| 60 |
+
(4, 3): {
|
| 61 |
+
"constant_term": 3 * a / 8 - 45 * b / 128,
|
| 62 |
+
"pin_term": -7 * a / 1920 + 7 * b / 1920,
|
| 63 |
+
},
|
| 64 |
+
(4, 5): {
|
| 65 |
+
"constant_term": -45 * a / 128 + 1231 * b / 3456,
|
| 66 |
+
"pin_term": 7 * a / 1920 - 7 * b / 1920,
|
| 67 |
+
},
|
| 68 |
+
(4, 7): {
|
| 69 |
+
"constant_term": 1231 * a / 3456 - 19615 * b / 55296,
|
| 70 |
+
"pin_term": -7 * a / 1920 + 7 * b / 1920,
|
| 71 |
+
},
|
| 72 |
+
(4, 9): {
|
| 73 |
+
"constant_term": -19615 * a / 55296 + 12280111 * b / 34560000,
|
| 74 |
+
"pin_term": 7 * a / 1920 - 7 * b / 1920,
|
| 75 |
+
},
|
| 76 |
+
(4, 11): {
|
| 77 |
+
"constant_term": 12280111 * a / 34560000 - 4090037 * b / 11520000,
|
| 78 |
+
"pin_term": -7 * a / 1920 + 7 * b / 1920,
|
| 79 |
+
},
|
| 80 |
+
(4, 13): {
|
| 81 |
+
"constant_term": -4090037 * a / 11520000 + 9824498837 * b / 27659520000,
|
| 82 |
+
"pin_term": 7 * a / 1920 - 7 * b / 1920,
|
| 83 |
+
},
|
| 84 |
+
(5, 2): {
|
| 85 |
+
"constant_term": 24 * a - 1936 * b / 81,
|
| 86 |
+
"pin_term": -5 * a / 64 + 5 * b / 64,
|
| 87 |
+
},
|
| 88 |
+
(5, 4): {
|
| 89 |
+
"constant_term": -1936 * a / 81 + 6051944 * b / 253125,
|
| 90 |
+
"pin_term": 5 * a / 64 - 5 * b / 64,
|
| 91 |
+
},
|
| 92 |
+
(5, 6): {
|
| 93 |
+
"constant_term": 6051944 * a / 253125 - 101708947808 * b / 4254271875,
|
| 94 |
+
"pin_term": -5 * a / 64 + 5 * b / 64,
|
| 95 |
+
},
|
| 96 |
+
(5, 8): {
|
| 97 |
+
"constant_term": -101708947808 * a / 4254271875
|
| 98 |
+
+ 24715694492344 * b / 1033788065625,
|
| 99 |
+
"pin_term": 5 * a / 64 - 5 * b / 64,
|
| 100 |
+
},
|
| 101 |
+
(5, 10): {
|
| 102 |
+
"constant_term": 24715694492344 * a / 1033788065625
|
| 103 |
+
- 3980462502772918544 * b / 166492601756971875,
|
| 104 |
+
"pin_term": -5 * a / 64 + 5 * b / 64,
|
| 105 |
+
},
|
| 106 |
+
(5, 12): {
|
| 107 |
+
"constant_term": -3980462502772918544 * a / 166492601756971875
|
| 108 |
+
+ 1477921859864507412282392 * b / 61817537584151358384375,
|
| 109 |
+
"pin_term": 5 * a / 64 - 5 * b / 64,
|
| 110 |
+
},
|
| 111 |
+
(6, 3): {
|
| 112 |
+
"constant_term": 15 * a / 8 - 945 * b / 512,
|
| 113 |
+
"pin_term": -31 * a / 16128 + 31 * b / 16128,
|
| 114 |
+
},
|
| 115 |
+
(6, 5): {
|
| 116 |
+
"constant_term": -945 * a / 512 + 229955 * b / 124416,
|
| 117 |
+
"pin_term": 31 * a / 16128 - 31 * b / 16128,
|
| 118 |
+
},
|
| 119 |
+
(6, 7): {
|
| 120 |
+
"constant_term": 229955 * a / 124416 - 14713475 * b / 7962624,
|
| 121 |
+
"pin_term": -31 * a / 16128 + 31 * b / 16128,
|
| 122 |
+
},
|
| 123 |
+
(6, 9): {
|
| 124 |
+
"constant_term": -14713475 * a / 7962624 + 45982595359 * b / 24883200000,
|
| 125 |
+
"pin_term": 31 * a / 16128 - 31 * b / 16128,
|
| 126 |
+
},
|
| 127 |
+
(6, 11): {
|
| 128 |
+
"constant_term": 45982595359 * a / 24883200000 - 5109066151 * b / 2764800000,
|
| 129 |
+
"pin_term": -31 * a / 16128 + 31 * b / 16128,
|
| 130 |
+
},
|
| 131 |
+
(6, 13): {
|
| 132 |
+
"constant_term": -5109066151 * a / 2764800000
|
| 133 |
+
+ 601081707598999 * b / 325275955200000,
|
| 134 |
+
"pin_term": 31 * a / 16128 - 31 * b / 16128,
|
| 135 |
+
},
|
| 136 |
+
}
|
| 137 |
+
|
| 138 |
+
|
| 139 |
+
class PiNIntegrate(GetIntegrateFromData):
|
| 140 |
+
data = _data
|
| 141 |
+
|
| 142 |
+
def get_integrate_args(self, args):
|
| 143 |
+
n, m = args
|
| 144 |
+
return x**m * (a + b * x**2) * (log(1 / x)) ** (n - 1) / (1 + x**2), (x, 0, 1)
|
| 145 |
+
|
| 146 |
+
|
| 147 |
+
class PiNSolution(Solution):
|
| 148 |
+
def __init__(self, n, p, q):
|
| 149 |
+
if n < 0:
|
| 150 |
+
n = -n
|
| 151 |
+
p, q = q, p
|
| 152 |
+
self.n = n
|
| 153 |
+
self.p = p
|
| 154 |
+
self.q = q
|
| 155 |
+
if self.q == 0:
|
| 156 |
+
raise BadInput()
|
| 157 |
+
|
| 158 |
+
self.get_integrate = PiNIntegrate()
|
| 159 |
+
self.symbols = (a, b)
|
| 160 |
+
self.integrate_result_classes_eq = {
|
| 161 |
+
"pin_term": q,
|
| 162 |
+
CONSTANT_TERM_KEY: -p,
|
| 163 |
+
}
|
| 164 |
+
# check
|
| 165 |
+
self.check_sgn = lin_func_sgn
|
| 166 |
+
|
| 167 |
+
def get_tries_args(self):
|
| 168 |
+
for n, m in PiNIntegrate.data.keys():
|
| 169 |
+
if n == self.n:
|
| 170 |
+
yield n, m
|
| 171 |
+
|
| 172 |
+
def get_latex_ans(self):
|
| 173 |
+
try_arg, symbol_val, sgn = self.try_times()
|
| 174 |
+
print(f"{(try_arg, symbol_val, sgn)=}")
|
| 175 |
+
if try_arg is None:
|
| 176 |
+
return None
|
| 177 |
+
|
| 178 |
+
p, n = to_latexes(self.p, self.n)
|
| 179 |
+
q = to_latex(self.q, is_coeff=True)
|
| 180 |
+
I = self.get_integrate.get_latex(try_arg, symbol_val)
|
| 181 |
+
return rf"{q}\pi^{n}-{p} = {I} {sign2cmp[sgn]} 0"
|
| 182 |
+
|
| 183 |
+
|
| 184 |
+
register("π^n", PiNSolution)
|
| 185 |
+
|
| 186 |
+
|
| 187 |
+
if __name__ == "__main__":
|
| 188 |
+
print(PiNSolution(3, 31, 1).get_latex_ans())
|