Spaces:
Paused
Paused
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."
|