def apply(self, f, x, x0, evaluation, options): "FindRoot[f_, {x_, x0_}, OptionsPattern[]]" # First, determine x0 and x x0 = apply_N(x0, evaluation) if not isinstance(x0, Number): evaluation.message("FindRoot", "snum", x0) return x_name = x.get_name() if not x_name: evaluation.message("FindRoot", "sym", x, 2) return # Now, get the explicit form of f, depending of x # keeping x without evaluation (Like inside a "Block[{x},f]) f = dynamic_scoping(lambda ev: f.evaluate(ev), {x_name: None}, evaluation) # If after evaluation, we get an "Equal" expression, # convert it in a function by substracting both # members. Again, ensure the scope in the evaluation if f.get_head_name() == "System`Equal": f = Expression("Plus", f.leaves[0], Expression("Times", Integer(-1), f.leaves[1])) f = dynamic_scoping(lambda ev: f.evaluate(ev), {x_name: None}, evaluation) # Determine the method method = options["System`Method"] if isinstance(method, Symbol): method = method.get_name().split("`")[-1] if method == "Automatic": method = "Newton" elif not isinstance(method, String): method = None evaluation.message("FindRoot", "bdmthd", method, [String(m) for m in self.methods.keys()]) return else: method = method.value # Determine the "jacobian" if method in ("Newton", ) and options["System`Jacobian"].sameQ( Symbol("Automatic")): def diff(evaluation): return Expression("D", f, x).evaluate(evaluation) d = dynamic_scoping(diff, {x_name: None}, evaluation) options["System`Jacobian"] = d method = self.methods.get(method, None) if method is None: evaluation.message("FindRoot", "bdmthd", method, [String(m) for m in self.methods.keys()]) return x0, success = method(f, x0, x, options, evaluation) if not success: return return Expression(SymbolList, Expression(SymbolRule, x, x0))
def apply_iter(self, expr, i, imin, imax, di, evaluation): '%(name)s[expr_, {i_Symbol, imin_, imax_, di_}]' index = imin.evaluate(evaluation).get_real_value() imax = imax.evaluate(evaluation).get_real_value() di = di.evaluate(evaluation).get_real_value() if index is None or imax is None or di is None: if self.throw_iterb: evaluation.message(self.get_name(), 'iterb') return result = [] while index <= imax: evaluation.check_stopped() try: item = dynamic_scoping(expr.evaluate, {i.name: Number.from_mp(index)}, evaluation) result.append(item) except ContinueInterrupt: if self.allow_loopcontrol: pass else: raise except BreakInterrupt: if self.allow_loopcontrol: break else: raise index = add(index, di) return self.get_result(result)
def apply(self, f, x, x0, evaluation): "FindRoot[f_, {x_, x0_}]" x0 = Expression(SymbolN, x0).evaluate(evaluation) if not isinstance(x0, Number): evaluation.message("FindRoot", "snum", x0) return x_name = x.get_name() if not x_name: evaluation.message("FindRoot", "sym", x, 2) return count = 0 def diff(evaluation): return Expression("D", f, x).evaluate(evaluation) d = dynamic_scoping(diff, {x_name: None}, evaluation) def sub(evaluation): d_value = d.evaluate(evaluation) if d_value == Integer(0): return None return Expression( "Times", f, Expression("Power", d_value, Integer(-1)) ).evaluate(evaluation) while count < 100: minus = dynamic_scoping(sub, {x_name: x0}, evaluation) if minus is None: evaluation.message("FindRoot", "dsing", x, x0) return x1 = Expression( "Plus", x0, Expression("Times", Integer(-1), minus) ).evaluate(evaluation) if not isinstance(x1, Number): evaluation.message("FindRoot", "nnum", x, x0) return if x1 == x0: break x0 = Expression(SymbolN, x1).evaluate( evaluation ) # N required due to bug in sympy arithmetic count += 1 else: evaluation.message("FindRoot", "maxiter") return Expression(SymbolList, Expression(SymbolRule, x, x0))
def eval_f(x_value, y_value): value = stored.get((x_value, y_value), False) if value == False: value = dynamic_scoping(f.evaluate, {x: Real(x_value), y: Real(y_value)}, evaluation) value = chop(value).get_real_value() value = float(value) stored[(x_value, y_value)] = value return value
def apply(self, f, x, x0, evaluation): 'FindRoot[f_, {x_, x0_}]' x0 = Expression('N', x0).evaluate(evaluation) if not isinstance(x0, Number): evaluation.message('FindRoot', 'snum', x0) return x_name = x.get_name() if not x_name: evaluation.message('FindRoot', 'sym', x, 2) return count = 0 def diff(evaluation): return Expression('D', f, x).evaluate(evaluation) d = dynamic_scoping(diff, {x_name: None}, evaluation) def sub(evaluation): d_value = d.evaluate(evaluation) if d_value == Integer(0): return None return Expression('Times', f, Expression('Power', d_value, Integer(-1))).evaluate(evaluation) while count < 100: minus = dynamic_scoping(sub, {x_name: x0}, evaluation) if minus is None: evaluation.message('FindRoot', 'dsing', x, x0) return x1 = Expression('Plus', x0, Expression('Times', Integer(-1), minus)).evaluate(evaluation) if not isinstance(x1, Number): evaluation.message('FindRoot', 'nnum', x, x0) return if x1 == x0: break x0 = Expression('N', x1).evaluate( evaluation) # N required due to bug in sympy arithmetic count += 1 else: evaluation.message('FindRoot', 'maxiter') return Expression('List', Expression('Rule', x, x0))
def apply(self, f, x, x0, evaluation): 'FindRoot[f_, {x_, x0_}]' x0 = Expression('N', x0).evaluate(evaluation) if not isinstance(x0, Number): evaluation.message('FindRoot', 'snum', x0) return x_name = x.get_name() if not x_name: evaluation.message('FindRoot', 'sym', x, 2) return count = 0 def diff(evaluation): return Expression('D', f, x).evaluate(evaluation) d = dynamic_scoping(diff, {x_name: None}, evaluation) def sub(evaluation): d_value = d.evaluate(evaluation) if d_value == Integer(0): return None return Expression('Times', f, Expression( 'Power', d_value, Integer(-1))).evaluate(evaluation) while count < 100: minus = dynamic_scoping(sub, {x_name: x0}, evaluation) if minus is None: evaluation.message('FindRoot', 'dsing', x, x0) return x1 = Expression('Plus', x0, Expression( 'Times', Integer(-1), minus)).evaluate(evaluation) if not isinstance(x1, Number): evaluation.message('FindRoot', 'nnum', x, x0) return if x1 == x0: break x0 = Expression('N', x1).evaluate( evaluation) # N required due to bug in sympy arithmetic count += 1 else: evaluation.message('FindRoot', 'maxiter') return Expression('List', Expression('Rule', x, x0))
def eval_f(x_value, y_value): value = stored.get((x_value, y_value), False) if value == False: value = dynamic_scoping(f.evaluate, { x: Real(x_value), y: Real(y_value) }, evaluation) value = chop(value).get_real_value() value = float(value) stored[(x_value, y_value)] = value return value
def apply(self, f, x, x0, evaluation): "FindRoot[f_, {x_, x0_}]" x0 = Expression("N", x0).evaluate(evaluation) if not isinstance(x0, Number): evaluation.message("FindRoot", "snum", x0) return x_name = x.get_name() if not x_name: evaluation.message("FindRoot", "sym", x, 2) return count = 0 def diff(evaluation): return Expression("D", f, x).evaluate(evaluation) d = dynamic_scoping(diff, {x_name: None}, evaluation) def sub(evaluation): d_value = d.evaluate(evaluation) if d_value == Integer(0): return None return Expression("Times", f, Expression("Power", d_value, Integer(-1))).evaluate(evaluation) while count < 100: minus = dynamic_scoping(sub, {x_name: x0}, evaluation) if minus is None: evaluation.message("FindRoot", "dsing", x_name, x0) return x1 = Expression("Plus", x0, Expression("Times", Integer(-1), minus)).evaluate(evaluation) if not isinstance(x1, Number): evaluation.message("FindRoot", "nnum", x_name, x0) return if x1 == x0: break x0 = Expression("N", x1).evaluate(evaluation) # N required due to bug in sympy arithmetic count += 1 else: evaluation.message("FindRoot", "maxiter") return Expression("List", Expression("Rule", x, x0))
def apply_assuming(self, assumptions, expr, evaluation): "Assuming[assumptions_, expr_]" assumptions = assumptions.evaluate(evaluation) if assumptions.is_true(): cond = [] elif assumptions.is_symbol() or not assumptions.has_form("List", None): cond = [assumptions] else: cond = assumptions._leaves cond = tuple(cond) + get_assumptions_list(evaluation) list_cond = Expression("List", *cond) # TODO: reduce the list of predicates return dynamic_scoping(lambda ev: expr.evaluate(ev), {"System`$Assumptions": list_cond}, evaluation)
def apply_iter(self, expr, i, imin, imax, di, evaluation): '%(name)s[expr_, {i_Symbol, imin_, imax_, di_}]' if isinstance(self, SympyFunction) and di.get_int_value() == 1: whole_expr = Expression(self.get_name(), expr, Expression('List', i, imin, imax)) sympy_expr = whole_expr.to_sympy() # apply Together to produce results similar to Mathematica result = sympy.together(sympy_expr) result = from_sympy(result) result = cancel(result) if not result.same(whole_expr): return result index = imin.evaluate(evaluation) imax = imax.evaluate(evaluation) di = di.evaluate(evaluation) result = [] while True: cont = Expression('LessEqual', index, imax).evaluate(evaluation) if cont == Symbol('False'): break if cont != Symbol('True'): if self.throw_iterb: evaluation.message(self.get_name(), 'iterb') return evaluation.check_stopped() try: item = dynamic_scoping(expr.evaluate, {i.name: index}, evaluation) result.append(item) except ContinueInterrupt: if self.allow_loopcontrol: pass else: raise except BreakInterrupt: if self.allow_loopcontrol: break else: raise index = Expression('Plus', index, di).evaluate(evaluation) return self.get_result(result)
def quiet_evaluate(expr, vars, evaluation, expect_list=False): """ Evaluates expr with given dynamic scoping values without producing arithmetic error messages. """ expr = Expression('N', expr) quiet_expr = Expression('Quiet', expr, Expression( 'List', Expression('MessageName', Symbol('Power'), String('infy')))) value = dynamic_scoping(quiet_expr.evaluate, vars, evaluation) if expect_list: if value.has_form('List', None): value = [chop(item).get_real_value() for item in value.leaves] if any(item is None for item in value): return None return value else: return None else: return chop(value).get_real_value()
def apply_iter(self, expr, i, imin, imax, di, evaluation): '%(name)s[expr_, {i_Symbol, imin_, imax_, di_}]' if di.get_int_value() == 1 and isinstance(self, SympyFunction): whole_expr = Expression(self.get_name(), expr, Expression('List', i, imin, imax)) sympy_expr = whole_expr.to_sympy() # apply Together to produce results similar to Mathematica result = sympy.together(sympy_expr) result = from_sympy(result) result = cancel(result) if not result.same(whole_expr): return result index = imin.evaluate(evaluation).get_real_value() imax = imax.evaluate(evaluation).get_real_value() di = di.evaluate(evaluation).get_real_value() if index is None or imax is None or di is None: if self.throw_iterb: evaluation.message(self.get_name(), 'iterb') return result = [] while index <= imax: evaluation.check_stopped() try: item = dynamic_scoping(expr.evaluate, {i.name: Number.from_mp(index)}, evaluation) result.append(item) except ContinueInterrupt: if self.allow_loopcontrol: pass else: raise except BreakInterrupt: if self.allow_loopcontrol: break else: raise index = index + di return self.get_result(result)
def apply_iter(self, expr, i, imin, imax, di, evaluation): '%(name)s[expr_, {i_Symbol, imin_, imax_, di_}]' if di.get_int_value() == 1 and isinstance(self, SageFunction): whole_expr = Expression(self.get_name(), expr, Expression('List', i, imin, imax)) sympy_expr = whole_expr.to_sympy() # apply Together to produce results similar to Mathematica result = sympy.together(sympy_expr) result = from_sympy(result) result = cancel(result) if not result.same(whole_expr): return result index = imin.evaluate(evaluation).get_real_value() imax = imax.evaluate(evaluation).get_real_value() di = di.evaluate(evaluation).get_real_value() if index is None or imax is None or di is None: if self.throw_iterb: evaluation.message(self.get_name(), 'iterb') return result = [] while index <= imax: evaluation.check_stopped() try: item = dynamic_scoping(expr.evaluate, {i.name: Number.from_mp(index)}, evaluation) result.append(item) except ContinueInterrupt: if self.allow_loopcontrol: pass else: raise except BreakInterrupt: if self.allow_loopcontrol: break else: raise index = add(index, di) return self.get_result(result)
def apply_list(self, expr, i, items, evaluation): '%(name)s[expr_, {i_Symbol, {items___}}]' items = items.evaluate(evaluation).get_sequence() result = [] for item in items: evaluation.check_stopped() try: item = dynamic_scoping(expr.evaluate, {i.name: item}, evaluation) result.append(item) except ContinueInterrupt: if self.allow_loopcontrol: pass else: raise except BreakInterrupt: if self.allow_loopcontrol: break else: raise return self.get_result(result)
def find_root_newton(f, x0, x, opts, evaluation) -> (Number, bool): df = opts["System`Jacobian"] maxit = opts["System`MaxIterations"] x_name = x.get_name() if maxit.sameQ(Symbol("Automatic")): maxit = 100 else: maxit = maxit.evaluate(evaluation).get_int_value() def sub(evaluation): d_value = df.evaluate(evaluation) if d_value == Integer(0): return None return Expression( "Times", f, Expression("Power", d_value, Integer(-1)) ).evaluate(evaluation) count = 0 while count < maxit: minus = dynamic_scoping(sub, {x_name: x0}, evaluation) if minus is None: evaluation.message("FindRoot", "dsing", x, x0) return x0, False x1 = Expression("Plus", x0, Expression("Times", Integer(-1), minus)).evaluate( evaluation ) if not isinstance(x1, Number): evaluation.message("FindRoot", "nnum", x, x0) return x0, False # TODO: use Precision goal... if x1 == x0: break x0 = Expression(SymbolN, x1).evaluate( evaluation ) # N required due to bug in sympy arithmetic count += 1 else: evaluation.message("FindRoot", "maxiter") return x0, True
def eval_f(f, x_value): value = dynamic_scoping(f.evaluate, {x: x_value}, evaluation) value = chop(value).get_real_value() return value
def find_root_secant(f, x0, x, opts, evaluation) -> (Number, bool): region = opts.get("$$Region", None) if not type(region) is list: if x0.is_zero: region = (Real(-1), Real(1)) else: xmax = 2 * x0.to_python() xmin = -2 * x0.to_python() if xmin > xmax: region = (Real(xmax), Real(xmin)) else: region = (Real(xmin), Real(xmax)) maxit = opts["System`MaxIterations"] x_name = x.get_name() if maxit.sameQ(Symbol("Automatic")): maxit = 100 else: maxit = maxit.evaluate(evaluation).get_int_value() x0 = from_python(region[0]) x1 = from_python(region[1]) f0 = dynamic_scoping(lambda ev: f.evaluate(evaluation), {x_name: x0}, evaluation) f1 = dynamic_scoping(lambda ev: f.evaluate(evaluation), {x_name: x1}, evaluation) if not isinstance(f0, Number): return x0, False if not isinstance(f1, Number): return x0, False f0 = f0.to_python(n_evaluation=True) f1 = f1.to_python(n_evaluation=True) count = 0 while count < maxit: if f0 == f1: x1 = Expression( "Plus", x0, Expression( "Times", Real(0.75), Expression("Plus", x1, Expression("Times", Integer(-1), x0)), ), ) x1 = x1.evaluate(evaluation) f1 = dynamic_scoping(lambda ev: f.evaluate(evaluation), {x_name: x1}, evaluation) if not isinstance(f1, Number): return x0, False f1 = f1.to_python(n_evaluation=True) continue inv_deltaf = from_python(1.0 / (f1 - f0)) num = Expression( "Plus", Expression("Times", x0, f1), Expression("Times", x1, f0, Integer(-1)), ) x2 = Expression("Times", num, inv_deltaf) x2 = x2.evaluate(evaluation) f2 = dynamic_scoping(lambda ev: f.evaluate(evaluation), {x_name: x2}, evaluation) if not isinstance(f2, Number): return x0, False f2 = f2.to_python(n_evaluation=True) f1, f0 = f2, f1 x1, x0 = x2, x1 if x1 == x0 or abs(f2) == 0: break count = count + 1 else: evaluation.message("FindRoot", "maxiter") return x0, False return x0, True