def eval(self, e): if e.ty != LIMIT: return e bd = e.body subst_poly = bd.replace_trig(Var(e.var), e.lim).to_poly() if subst_poly.T != poly.UNKNOWN: return e inf_part, zero_part, const_part = [], [], [] bd_poly = bd.to_poly() if len(bd_poly) != 1: raise NotImplementedError m = bd_poly[0] factors = m.factors for i, j in factors: mono = poly.Polynomial([poly.Monomial(1, ((i, j),))]) norm_m = expr.from_poly(mono) subst_m = norm_m.replace_trig(Var(e.var), e.lim).to_poly() if subst_m.T == poly.ZERO: zero_part.append((Const(1) / norm_m).normalize()) elif subst_m.T in (poly.POS_INF, poly.NEG_INF): inf_part.append(norm_m) elif subst_m.T == poly.NON_ZERO: const_part.append(norm_m) else: raise NotImplementedError(str(mono)) assert inf_part and zero_part inf_expr = functools.reduce(operator.mul, inf_part[1:], inf_part[0]) zero_expr = functools.reduce(operator.mul, zero_part[1:], zero_part[0]) nm_trace = [inf_expr] denom_trace = [zero_expr] while True: nm, denom = nm_trace[-1], denom_trace[-1] nm_deriv, denom_deriv = expr.deriv(e.var, nm), expr.deriv(e.var, denom) nm_subst, denom_subst = nm_deriv.replace_trig(Var(e.var), e.lim), denom_deriv.replace_trig(Var(e.var), e.lim) nm_poly, denom_poly = nm_subst.to_poly(), denom_subst.to_poly() if nm_poly.T in (poly.POS_INF, poly.NEG_INF) and denom_poly.T in (poly.POS_INF, poly.NEG_INF): continue elif nm_poly.T in (poly.ZERO, poly.NON_ZERO) and denom_poly.T in (poly.POS_INF, poly.NEG_INF): return Const(0) elif nm_poly.T in (poly.POS_INF, poly.NEG_INF) and denom_poly.T in (poly.ZERO, poly.NON_ZERO): return expr.from_poly(nm_poly) elif nm_poly.T == poly.NON_ZERO and denom_poly.T == poly.NON_ZERO: return (nm_subst / denom_subst).normalize() else: raise NotImplementedError
def eval(self, e): """ Parameters: e: Expr, the integral on which to perform substitution. Returns: The new integral e', and stores in self.f the parameter used to specify the substitution. """ if isinstance(e, str): e = parser.parse_expr(e) var_name = parser.parse_expr(self.var_name) var_subst = self.var_subst dfx = expr.deriv(e.var, var_subst) body = holpy_style(sympy_style(e.body/dfx)) body_subst = body.replace_trig(var_subst, var_name) if body_subst == body: body_subst = body.replace_trig(var_subst, var_name) lower = var_subst.subst(e.var, e.lower).normalize() upper = var_subst.subst(e.var, e.upper).normalize() if parser.parse_expr(e.var) not in body_subst.findVar(): # Substitution is able to clear all x in original integrand # print('Substitution: case 1') self.f = body_subst if sympy_style(lower) <= sympy_style(upper): return Integral(self.var_name, lower, upper, body_subst).normalize() else: return Integral(self.var_name, upper, lower, Op("-", body_subst)).normalize() else: # Substitution is unable to clear x, need to solve for x # print('Substitution: case 2') gu = solvers.solve(expr.sympy_style(var_subst - var_name), expr.sympy_style(e.var)) if gu == []: # sympy can't solve the equation return e gu = gu[-1] if isinstance(gu, list) else gu gu = expr.holpy_style(gu) c = e.body.replace_trig(parser.parse_expr(e.var), gu) new_problem_body = (e.body.replace_trig(parser.parse_expr(e.var), gu)*expr.deriv(str(var_name), gu)) lower = holpy_style(sympy_style(var_subst).subs(sympy_style(e.var), sympy_style(e.lower))) upper = holpy_style(sympy_style(var_subst).subs(sympy_style(e.var), sympy_style(e.upper))) self.f = new_problem_body if sympy_style(lower) < sympy_style(upper): return Integral(self.var_name, lower, upper, new_problem_body).normalize() else: return Integral(self.var_name, upper, lower, Op("-", new_problem_body)).normalize()
def eval(self, e): if isinstance(e, str): e = parser.parse_expr(e) if e.ty != expr.INTEGRAL: return e e.body = e.body.normalize() du = expr.deriv(e.var, self.u) dv = expr.deriv(e.var, self.v) udv = (self.u * dv).normalize() if udv == e.body: return expr.EvalAt(e.var, e.lower, e.upper, (self.u * self.v).normalize()) - \ expr.Integral(e.var, e.lower, e.upper, (self.v * du).normalize()) else: print("%s != %s" % (str(udv), str(e.body))) raise NotImplementedError("%s != %s" % (str(udv), str(e.body)))
def eval(self, e): if isinstance(e, str): e = parser.parse_expr(e) if e.ty == expr.DERIV: return expr.deriv(e.var, e.body) else: return e
def eval(self, e): if isinstance(e, str): e = parser.parse_expr(e) subst_deriv = expr.deriv(self.var_name, self.var_subst) #dx = d(x(u)) = x'(u) *du new_e_body = e.body.replace_trig(expr.holpy_style(str(e.var)), self.var_subst) #replace all x with x(u) new_e_body = expr.Op("*", new_e_body, subst_deriv) # g(x) = g(x(u)) * x'(u) lower = solvers.solve(expr.sympy_style(self.var_subst - e.lower))[0] upper = solvers.solve(expr.sympy_style(self.var_subst - e.upper))[0] return expr.Integral(self.var_name, expr.holpy_style(lower), expr.holpy_style(upper), new_e_body)
def testDeriv(self): test_data = [ ("1", "0"), ("x", "1"), ("2 * x", "2"), ("x ^ 2", "2 * x"), ("x * y", "y"), ("1 / x", "-1 / x ^ 2"), ("3 * x + 1", "3"), ("x + pi / 3", "1"), ("2 * x + pi / 3", "2"), ("sin(x)", "cos(x)"), ("sin(x^2)", "2 * x * cos(x ^ 2)"), ("cos(x)", "-sin(x)"), ("log(x)", "x ^ -1"), ("x * log(x)", "1 + log(x)"), ("exp(x)", "exp(x)"), ("exp(x^2)", "2 * x * exp(x ^ 2)"), ] for s, s2 in test_data: s = parse_expr(s) self.assertEqual(str(expr.deriv("x", s)), s2)