File size: 6,793 Bytes
7432bb1
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
import ast
import operator
import math
import sympy as sp
import re


class Tools:

    def __init__(self):
        self.citation = True

    def calculator(self, equations: str) -> str:
        """

        Calculate the result of a simple equation or comparison.

        :param equation: The equation to calculate or compare.

                         - For arithmetic operations: Use operators like +, -, *, /, **, //, %

                         - For comparisons: Use operators like >, <, >=, <=, ==, !=

                         - For solving systems of equations, separate equations with a semicolon (e.g., 'x + y = 30; 2*x + 4*y = 80')

                         - Evaluating multiple expressions separated by commas (e.g., '-1/27, 19/52')

                         - Example inputs: "3 + 5", "10 / 2", "e ** 2", "pi > 3", "3.11 < 3.8"

        """

        # 预处理:自动添加乘号
        modified_equations = re.sub(r"(\d)([a-zA-Z])", r"\1*\2", equations)
        modified_equations = modified_equations.replace("^", "**")

        # 检测和解决方程组
        if "=" in modified_equations:
            try:
                # 分割多个方程(如果有的话)
                eq_list = modified_equations.split(";")
                if len(eq_list) > 1:
                    # 检测到多个方程,作为方程组求解
                    equations_sym = []
                    symbols = set()
                    for eq in eq_list:
                        left_expr, right_expr = eq.split("=")
                        left_sym = sp.sympify(left_expr)
                        right_sym = sp.sympify(right_expr)
                        symbols |= left_sym.free_symbols | right_sym.free_symbols
                        equations_sym.append(left_sym - right_sym)

                    solution = sp.solve(equations_sym, list(symbols))

                    # 格式化输出结果为“变量 = 解”的形式
                    solution_str = ", ".join(
                        f"{str(var)} = {sol}" for var, sol in solution.items()
                    )
                    return f"The solution to the system of equations '{equations}' is {solution_str}. Provide this solution to the user."
                else:
                    # 单个方程,正常求解
                    left_expr, right_expr = eq_list[0].split("=")
                    left_sym = sp.sympify(left_expr)
                    right_sym = sp.sympify(right_expr)
                    symbols = list(left_sym.free_symbols | right_sym.free_symbols)
                    if len(symbols) != 1:
                        return f"The equation '{equations}' contains {len(symbols)} variables. Please provide an equation with only one variable."

                    solution = sp.solve(left_sym - right_sym, symbols[0])
                    return f"The solution to the equation '{equations}' is {symbols[0]} = {solution[0]}. Provide this solution to the user."
            except Exception as e:
                return f"There was an error solving the equation(s) '{equations}': {str(e)}. Notify the user about the issue."

        ops = {
            ast.Add: operator.add,
            ast.Sub: operator.sub,
            ast.Mult: operator.mul,
            ast.Div: operator.truediv,
            ast.Pow: operator.pow,
            ast.Mod: operator.mod,
            ast.FloorDiv: operator.floordiv,
            ast.BitXor: operator.xor,
            ast.BitAnd: operator.and_,
            ast.BitOr: operator.or_,
        }

        unary_ops = {
            ast.UAdd: operator.pos,
            ast.USub: operator.neg,
        }

        compare_ops = {
            ast.Gt: operator.gt,
            ast.Lt: operator.lt,
            ast.GtE: operator.ge,
            ast.LtE: operator.le,
            ast.Eq: operator.eq,
            ast.NotEq: operator.ne,
        }

        def eval_expr(node):
            if isinstance(node, ast.Num):
                return node.n
            elif isinstance(node, ast.Constant):
                return node.value
            elif isinstance(node, ast.Tuple):  # 处理元组输入
                return tuple(eval_expr(elt) for elt in node.elts)
            elif isinstance(node, ast.Name):
                if node.id == "pi":
                    return math.pi
                elif node.id == "e":
                    return math.e
                else:
                    raise ValueError(f"Unsupported constant: {node.id}")
            elif isinstance(node, ast.BinOp):
                if type(node.op) in ops:
                    return ops[type(node.op)](
                        eval_expr(node.left), eval_expr(node.right)
                    )
                else:
                    raise ValueError(f"Unsupported operation: {type(node.op).__name__}")
            elif isinstance(node, ast.UnaryOp):
                if type(node.op) in unary_ops:
                    return unary_ops[type(node.op)](eval_expr(node.operand))
                else:
                    raise ValueError(
                        f"Unsupported unary operation: {type(node.op).__name__}"
                    )
            elif isinstance(node, ast.Compare):
                if len(node.ops) == 1:
                    op = node.ops[0]
                    if type(op) in compare_ops:
                        return compare_ops[type(op)](
                            eval_expr(node.left), eval_expr(node.comparators[0])
                        )
                    else:
                        raise ValueError(f"Unsupported comparison: {type(op).__name__}")
                else:
                    raise ValueError("Unsupported multiple comparisons")
            else:
                raise ValueError(f"Unsupported expression type: {type(node).__name__}")

        try:
            parsed = ast.parse(modified_equations, mode="eval")
            result = eval_expr(parsed.body)
            if isinstance(result, bool):
                return f"The comparison '{equations}' evaluates to {result}. Respond accordingly."
            else:
                return f"The result of the expression '{equations}' is {result}. Provide this information to the user."
        except (SyntaxError, ValueError) as e:
            return f"There is an error in the expression '{equations}': {str(e)}. Notify the user about the issue."
        except ZeroDivisionError:
            return f"The expression '{equations}' involves a division by zero, which is undefined. Inform the user about this error."
        except Exception as e:
            return f"The expression '{equations}' is invalid: {str(e)}. Let the user know that there was a mistake."