File size: 4,273 Bytes
5c5cb4d
 
2f94119
 
5c5cb4d
 
 
 
2f94119
3e7998b
2f94119
5c5cb4d
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3e7998b
 
 
5c5cb4d
 
3e7998b
5c5cb4d
 
 
 
 
 
f09d15a
3e7998b
5c5cb4d
 
 
 
3e7998b
5c5cb4d
3e7998b
 
 
5c5cb4d
 
 
 
8a4e70b
5c5cb4d
 
 
2f94119
5c5cb4d
3e7998b
5c5cb4d
8a4e70b
f09d15a
 
5c5cb4d
3e7998b
 
 
5c5cb4d
 
 
3e7998b
 
5c5cb4d
 
3e7998b
 
2f94119
5c5cb4d
3e7998b
5c5cb4d
 
 
 
 
 
3e7998b
5c5cb4d
f09d15a
2f94119
 
5c5cb4d
f09d15a
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119

import re
import gradio as gr
import sympy as sp
from sympy.parsing.sympy_parser import (
    parse_expr, standard_transformations,
    implicit_multiplication_application, convert_xor
)

TITLE = "LanguageBridge — Math Fast Agent (SymPy)"

# ---------- 輸入正規化:隱式乘法 / ^→** / 全形→半形 / √→sqrt ----------
def normalize_ascii(s: str) -> str:
    table = str.maketrans({
        '(':'(', ')':')', ',':',', ';':';', ':':':',
        '=':'=', '-':'-', '+':'+', '*':'*', '/':'/', '。':'.',
        '×':'*', '√':'sqrt'
    })
    return s.translate(table)

def auto_insert_stars(s: str) -> str:
    # 3x -> 3*x; x(x+1) -> x*(x+1);(x+1)x -> (x+1)*x; 2sqrt(x) -> 2*sqrt(x)
    s = re.sub(r'(\d)([A-Za-z])', r'\1*\2', s)
    s = re.sub(r'([A-Za-z0-9_])\(', r'\1*(', s)
    s = re.sub(r'\)([A-Za-z0-9_])', r')*\1', s)
    s = re.sub(r'(\d)\s*sqrt', r'\1*sqrt', s)
    return s

def preprocess(expr: str) -> str:
    s = (expr or "").strip()
    s = normalize_ascii(s)
    s = s.replace("^", "**")        # 2^3 -> 2**3
    s = auto_insert_stars(s)        # 隱式乘法 → 顯式
    return s

# 支援隱式乘法與 ^ 解析
TRANS = standard_transformations + (implicit_multiplication_application, convert_xor)

def to_sympy_expr(s: str):
    s = preprocess(s)
    return parse_expr(s, transformations=TRANS)

def to_sympy_eq(s: str):
    s = preprocess(s)
    if "=" not in s:
        raise ValueError("等式缺少 '='")
    L, R = s.split("=", 1)
    return sp.Eq(parse_expr(L, transformations=TRANS),
                 parse_expr(R, transformations=TRANS))

# ---------------- 主邏輯(保留原介面與輸出格式) ----------------
def solve_math(q: str):
    q = (q or "").strip()
    if not q:
        return "請輸入算式或方程,例如:2x+3=11;sin(x)^2 + cos(x)^2;factor(x^2-9)"

    try:
        # 多題/聯立:分號 ; 或換行 \n 分隔
        parts = [s.strip() for seg in q.split(";") for s in seg.split("\n")]
        parts = [p for p in parts if p]

        # 若任一行含 '=',啟用「解方程(可聯立)」模式
        if any("=" in p for p in parts):
            eqs, syms = [], set()
            for s in parts:
                if "=" in s:
                    e = to_sympy_eq(s)
                    eqs.append(e)
                    syms |= e.free_symbols | e.rhs.free_symbols
            if not syms:
                syms = {sp.symbols("x")}
            sol = sp.solve(eqs, list(syms), dict=True)
            if not sol:
                return "無解或需要更多條件。"
            return "\n".join(
                f"解 {i}: " + ", ".join([f\"{k} = {sp.simplify(v)}\" for k, v in d.items()])
                for i, d in enumerate(sol, 1)
            )

        # 否則視為單一表達式:簡化 / 因式 / 微分 / 積分
        expr = to_sympy_expr(q)
        out = []
        try:
            out.append(f"簡化:{sp.simplify(expr)}")
        except Exception:
            out.append(f"簡化:{expr}")
        try:
            fact = sp.factor(expr)
            if fact != expr:
                out.append(f"因式分解:{fact}")
        except Exception:
            pass
        try:
            x = next(iter(expr.free_symbols)) if expr.free_symbols else sp.symbols("x")
            out.append(f"對 {x} 微分:{sp.diff(expr, x)}")
            out.append(f"對 {x} 積分:{sp.integrate(expr, x)}")
        except Exception:
            pass
        return "\n".join(out) if out else f"結果:{expr}"

    except Exception as e:
        return f"解析失敗:{e}"

# ---------------- 介面 ----------------
with gr.Blocks(title=TITLE) as demo:
    gr.Markdown(
        "## " + TITLE + "\\n"
        "貼上算式(可多行 / 用分號 `;` 分隔)。\\n\\n"
        "**可直接輸入隱式乘法:** `3x`、`2(x+1)`、`(x)(x+1)`、`2sqrt(x)`;"
        "也可用 `x^2`(自動轉為 `x**2`),`√(x)`(自動轉為 `sqrt(x)`)。"
    )
    q = gr.Textbox(lines=6, label="題目 / 算式(可含聯立方程)")
    out = gr.Textbox(lines=12, label="輸出")
    gr.Button("送出 🚀").click(fn=solve_math, inputs=q, outputs=out)

if __name__ == "__main__":
    # Space 環境不需要 share
    demo.launch()