def __init__(self, x_func: str, y_func: str, z_func: str, t_range: tuple, param=PARAM) -> None: """ Create a 3d curve with r(t) = (x(t), y(t), z(t)) parametrization. :params x_func, y_func, z_func: must depend on param (default: t) :param t_range: variability range for parameter :param param: string that represents the functions' parameter """ assert len(t_range) == 2, 't_range must have len = 2' assert all(isinstance(elem, (float, int)) for elem in t_range), 't_range parameters must be numbers' self._t = symbols(param) self._t_lower = float(t_range[0]) self._t_upper = float(t_range[1]) self._x_func = parse_expr(x_func) self._y_func = parse_expr(y_func) self._z_func = parse_expr(z_func) # create vectorized functions for x, y, z self._x = lambdify(self._t, self._x_func, 'numpy') self._y = lambdify(self._t, self._y_func, 'numpy') self._z = lambdify(self._t, self._z_func, 'numpy') mpl.rcParams['legend.fontsize'] = 10 fig = plt.figure() self._ax = fig.gca(projection='3d')
def eval_expr(expr,variables,container,name): vals={} for k in container: vals[k.name]=k.x vals["S"+k.name]=k.Sx #x = expr.evalf(subs=vals) f=lambdify(tuple(vals.keys()),expr,"numpy") x = f(**vals) #little workaround leer=sy.Symbol("leer") f=0*leer for k in variables: f=f+ (sy.diff(expr,k))**2*sy.Symbol("S"+k.__str__())**2 f=sy.sqrt(f) #print "Formel:" #print ur"\begin*{equation}" #print sy.latex(expr) #print ur"\end{equation}" #print "Fehler" #print ur"\begin*{equation}" #sy.pprint(f) #print ur"\end{equation}" gf = lambdify(tuple(vals.keys()),f,"numpy") Sx = gf(**vals) return (Groesse(name,x.dimensionality.string,x.magnitude,Sx.magnitude),expr,f)
def calculate_y(expr01, x, y, terminals, add_coef=True, x_test=None, y_test=None, filter_warning=True, inter_add=True, inner_add=False, vector_add=False, out_add=False, flat_add=False, np_maps=None, classification=False): if filter_warning: warnings.filterwarnings("ignore") try: if add_coef: pre_y, expr01 = try_add_coef(expr01, x, y, terminals, filter_warning=filter_warning, inter_add=inter_add, inner_add=inner_add, vector_add=vector_add, out_add=out_add, flat_add=flat_add, np_maps=np_maps, classification=classification) else: func0 = utilities.lambdify(terminals, expr01, modules=[np_maps, "numpy"]) pre_y = func0(*x) if classification: pre_y = cla(pre_y) if x_test is not None and y_test is not None: func0 = utilities.lambdify(terminals, expr01, modules=[np_maps, "numpy"]) pre_y = func0(*x_test) if classification: pre_y = cla(pre_y) pre_y = pre_y.ravel() assert y_test.shape == pre_y.shape pre_y = check_array(pre_y, ensure_2d=False) else: pre_y = pre_y.ravel() assert y.shape == pre_y.shape pre_y = check_array(pre_y, ensure_2d=False) except (DataConversionWarning, TypeError, AssertionError, ValueError, AttributeError, KeyError, ZeroDivisionError): pre_y = None return pre_y, expr01
def get_transformation_function(segments, fixed_endpoint=None, fixed_basepoint=None, use_dict=True): if fixed_endpoint: coordinate_labels = [] else: coordinate_labels = ['x','y','z'] if fixed_basepoint: inverse_coordinate_labels = [] else: inverse_coordinate_labels = ['base_x','base_y','base_z'] trans_mat, inv_trans_mat, var_names = get_sympy_reduction(segments, fixed_endpoint, fixed_basepoint, coordinate_labels, inverse_coordinate_labels) # Bake into a lambda func base_func = lambdify(flatten((coordinate_labels, var_names)), trans_mat) base_inv_func = lambdify(flatten((inverse_coordinate_labels, var_names)), inv_trans_mat) if use_dict: if fixed_endpoint: func = lambda var_dict: base_func(*flatten([var_dict[var_name] for var_name in var_names])).A else: func = lambda coords, var_dict: base_func(*flatten((coords, [var_dict[var_name] for var_name in var_names]))).A if fixed_basepoint: inv_func = lambda var_dict: base_inv_func(*flatten([var_dict[var_name] for var_name in var_names])).A else: inv_func = lambda coords, var_dict: base_inv_func(*flatten((coords, [var_dict[var_name] for var_name in var_names]))).A else: if fixed_endpoint: func = lambda var_vals: base_func(*flatten(var_vals)).A else: func = lambda coords, var_vals: base_func(*flatten((coords, var_vals))).A if fixed_basepoint: inv_func = lambda var_vals: base_inv_func(*flatten(var_vals)).A else: inv_func = lambda coords, var_vals: base_inv_func(*flatten((coords, var_vals))).A return func, inv_func
def _eval_evalf(self, prec): """Evaluate this complex root to the given precision. """ with workprec(prec): g = self.poly.gen if not g.is_Symbol: d = Dummy('x') func = lambdify(d, self.expr.subs(g, d)) else: func = lambdify(g, self.expr) interval = self._get_interval() if not self.is_real: # For complex intervals, we need to keep refining until the # imaginary interval is disjunct with other roots, that is, # until both ends get refined. ay = interval.ay by = interval.by while interval.ay == ay or interval.by == by: interval = interval.refine() while True: if self.is_real: x0 = mpf(str(interval.center)) else: x0 = mpc(*map(str, interval.center)) try: root = findroot(func, x0, verify=False) # If the (real or complex) root is not in the 'interval', # then keep refining the interval. This happens if findroot # accidentally finds a different root outside of this # interval because our initial estimate 'x0' was not close # enough. if self.is_real: a = mpf(str(interval.a)) b = mpf(str(interval.b)) if a == b: root = a break if not (a < root < b): raise ValueError("Root not in the interval.") else: ax = mpf(str(interval.ax)) bx = mpf(str(interval.bx)) ay = mpf(str(interval.ay)) by = mpf(str(interval.by)) if ax == bx and ay == by: root = ax + S.ImaginaryUnit * by break if not (ax < root.real < bx and ay < root.imag < by): raise ValueError("Root not in the interval.") except ValueError: interval = interval.refine() continue else: break return Float._new(root.real._mpf_, prec) + I * Float._new(root.imag._mpf_, prec)
def _eval_evalf(self, prec): """Evaluate this complex root to the given precision. """ with workprec(prec): g = self.poly.gen if not g.is_Symbol: d = Dummy('x') func = lambdify(d, self.expr.subs(g, d)) else: func = lambdify(g, self.expr) interval = self._get_interval() if not self.is_real: # For complex intervals, we need to keep refining until the # imaginary interval is disjunct with other roots, that is, # until both ends get refined. ay = interval.ay by = interval.by while interval.ay == ay or interval.by == by: interval = interval.refine() while True: if self.is_real: x0 = mpf(str(interval.center)) else: x0 = mpc(*map(str, interval.center)) try: root = findroot(func, x0, verify=False) # If the (real or complex) root is not in the 'interval', # then keep refining the interval. This happens if findroot # accidentally finds a different root outside of this # interval because our initial estimate 'x0' was not close # enough. if self.is_real: a = mpf(str(interval.a)) b = mpf(str(interval.b)) if a == b: root = a break if not (a < root < b): raise ValueError("Root not in the interval.") else: ax = mpf(str(interval.ax)) bx = mpf(str(interval.bx)) ay = mpf(str(interval.ay)) by = mpf(str(interval.by)) if ax == bx and ay == by: root = ax + S.ImaginaryUnit*by break if not (ax < root.real < bx and ay < root.imag < by): raise ValueError("Root not in the interval.") except ValueError: interval = interval.refine() continue else: break return Float._new(root.real._mpf_, prec) + I*Float._new(root.imag._mpf_, prec)
def forces_from_energies(T, U, q, dq): H = lambda a, b: T(a, b) + U(a, b) L = lambda a, b: T(a, b) - U(a, b) F_sym = sp.diff(L(q, dq), q) - sp.diff(L(q, dq), dq, q) * dq F = lambdify((q, dq), F_sym, "numpy") M_sym = sp.diff(L(q, dq), dq, 2) M = lambdify((q, dq), M_sym, "numpy") return F, M, H, L, F_sym, M_sym
def ML_deriv(): """ m_M_pairs[1,i]=M_t y=m_t x=M_t """ #Python differentiation========================================================================== expr = (-y * (0.5 + (0.5) * tanh( ((y - m) / t))) + x * ln(-(0.5 + (0.5) * tanh(((y - m) / t))))) diff_T = diff(expr, t) diff_m = diff(expr, m) #print diff_T #print diff_m #================================================================================================ #suming over t for T ==================================================================================== diff_T_sum = np.zeros(shape=(1)) T_pydiff_sum = np.zeros(shape=(1)) for i in range(0, (n_pairs)): T_pydiff_ML = 0.5 * m_M_pairs[1, i] * (-m + m_M_pairs[0, i]) * (-tanh( (-m + m_M_pairs[0, i]) / t)**2 + 1) / (t**2 * (-0.5 * tanh( (-m + m_M_pairs[0, i]) / t) - 0.5)) + 0.5 * m_M_pairs[0, i] * ( -m + m_M_pairs[0, i]) * (-tanh( (-m + m_M_pairs[0, i]) / t)**2 + 1) / t**2 T_pydiff_sum = np.append(T_pydiff_sum, T_pydiff_ML) global T_pydif_ML_func T_pydif_ML_func = np.sum(T_pydiff_sum[:, ]) T_pydif_ML_func = lambdify((m, t), T_pydif_ML_func, "numpy") #=================================================================================================== #suming over t for m* ==================================================================================== diff_m_sum = np.zeros(shape=(1)) m_pydiff_sum = np.zeros(shape=(1)) for i in range(0, (n_pairs)): m_pydiff_ML = 0.5 * m_M_pairs[1, i] * (-tanh( (-m + m_M_pairs[0, i]) / t)**2 + 1) / (t * (-0.5 * tanh( (-m + m_M_pairs[0, i]) / t) - 0.5)) + 0.5 * m_M_pairs[0, i] * ( -tanh((-m + m_M_pairs[0, i]) / t)**2 + 1) / t m_pydiff_sum = np.append(m_pydiff_sum, m_pydiff_ML) global m_pydif_ML_func #test equation======================================= equ = x**2 + x**y + 25 m_pydif_ML_func = np.sum(m_pydiff_sum[:, ]) m_pydif_ML_func = lambdify((m, t), m_pydif_ML_func, "numpy")
def accepted(self): expr = parse_expr(self.fEdit.text()) f = lambdify(x, expr) df = lambdify(x, expr.diff(x)) N = 1 delta = float(self.deltaEdit.text()) x0 = float(self.xEdit.text()) x1 = x0-f(x0)/df(x0) while not closeEnaught(x0, x1, delta): x0 = x1 x1 = x0-f(x0)/df(x0) N += 1 self.listWidget.addItem("x = " + str(x1) + ", N = " + str(N))
def graphicalButtonClicked(self): color1 = None if self.f1colorBox.currentIndex() == 0: color1 = 'r' elif self.f1colorBox.currentIndex() == 1: color1 = 'b' elif self.f1colorBox.currentIndex() == 2: color1 = 'g' elif self.f1colorBox.currentIndex() == 3: color1 = 'y' elif self.f1colorBox.currentIndex() == 4: color1 = 'm' elif self.f1colorBox.currentIndex() == 5: color1 = 'c' color2 = None if self.f2colorBox.currentIndex() == 0: color2 = 'r' elif self.f2colorBox.currentIndex() == 1: color2 = 'b' elif self.f2colorBox.currentIndex() == 2: color2 = 'g' elif self.f2colorBox.currentIndex() == 3: color2 = 'y' elif self.f2colorBox.currentIndex() == 4: color2 = 'm' elif self.f2colorBox.currentIndex() == 5: color2 = 'c' expr1 = parse_expr(self.f1Edit.text()) expr2 = parse_expr(self.f2Edit.text()) f1 = lambdify(x, expr1, 'numpy') f2 = lambdify(x, expr2, 'numpy') try: minX = float(self.minxEdit.text()) maxX = float(self.maxxEdit.text()) except: QMessageBox.warning(self, "Warning", "Min and max values error type.") return if minX <= maxX: x1 = np.linspace(minX, maxX, (maxX-minX)*1000) self.plotW.figure.clf() self.plotW.plot(x1, f1(x1), color1) self.plotW.plot(x1, f2(x1), color2) else: QMessageBox.warning(self, "Warning", "Min value must be smaller than max value")
def ML_deriv(): """ m_M_pairs[1,i]=M_t y=m_t x=M_t #Python differentiation========================================================================== """ #================================================================================================ """ #suming over t for T ==================================================================================== diff_T_sum = np.zeros(shape=(1)) T_pydiff_sum = np.zeros(shape=(1)) for i in range(0,(n_pairs)): T_pydiff_ML = 0.5*m_M_pairs[1,i]*(-m + m_M_pairs[0,i])*(-tanh((-m + m_M_pairs[0,i])/t)**2 + 1)/(t**2*(-0.5*tanh((-m + m_M_pairs[0,i])/t) - 0.5)) + 0.5*m_M_pairs[0,i]*(-m + m_M_pairs[0,i])*(-tanh((-m + m_M_pairs[0,i])/t)**2 + 1)/t**2 T_pydiff_sum = np.append(T_pydiff_sum,T_pydiff_ML) global T_pydif_ML_func T_pydif_ML_func = np.sum(T_pydiff_sum[:,]) T_pydif_ML_func=lambdify((m,t),T_pydif_ML_func,"numpy") #=================================================================================================== #suming over t for m* ==================================================================================== diff_m_sum = np.zeros(shape=(1)) m_pydiff_sum = np.zeros(shape=(1)) for i in range(0,(n_pairs)): m_pydiff_ML = 0.5*m_M_pairs[1,i]*(-tanh((-m + m_M_pairs[0,i])/t)**2 + 1)/(t*(-0.5*tanh((-m + m_M_pairs[0,i])/t) - 0.5)) + 0.5*m_M_pairs[0,i]*(-tanh((-m + m_M_pairs[0,i])/t)**2 + 1)/t m_pydiff_sum = np.append(m_pydiff_sum,m_pydiff_ML) global m_pydif_ML_func m_pydif_ML_func = np.sum(m_pydiff_sum[:,]) m_pydif_ML_func=lambdify((m,t),m_pydif_ML_func,"numpy") """ expr = ((x - 4)**2 + (y - 4)**2 + 25) diff_x = diff(expr, x) diff_y = diff(expr, y) print diff_x print diff_y global x_equ_func, y_equ_func x_equ_func = lambdify((x, y), diff_x, "numpy") y_equ_func = lambdify((x, y), diff_y, "numpy")
def d2V_func(lat, V, field_var): "Calculate the masses of the fields in terms of the field values:" field_list = lat.field_list from sympy import diff, Symbol, var, simplify, sympify, S, evalf from sympy.utilities import lambdify from sympy.core.sympify import SympifyError C_coeff = V.C_coeff D_coeff = V.D_coeff V_string = V.V try: d2V = diff(sympify(V_string),field_var,2) except SympifyError: print "Could not parse expression." "Replacement list C_i->C_coeff[i], D_i->D_coeff[i]:" rep_list = {} for i in xrange(len(C_coeff)): rep_list.update({'C'+str(i+1):C_coeff[i]}) for i in xrange(len(D_coeff)): rep_list.update({'D'+str(i+1):D_coeff[i]}) d2V_func = lambdify(field_list,d2V.subs(rep_list)) return d2V_func
def val(self) -> float: """ :return: value of your variable """ args = tuple(self._story.free_symbols) return lambdify(args, self._story, 'numpy')(*(DictSymVar[sym]._value for sym in args))
def SIMethod(self): self.x0 = float(self.x0EditSI.text()) self.eps = float(self.epsEditSI.text()) self.fexpr = parse_expr(self.fEditSI.text()) self.phiexpr = parse_expr(self.phiEditSI.text()) self.f = lambdify(x, self.fexpr) self.phi = lambdify(x, self.phiexpr) self.x1 = 0 self.N = 0 while True: self.x1 = self.phi(self.x0) self.N += 1 if closeEnaught(self.x1, self.x0, self.eps) or self.f(self.x1) == 0: self.listWidget.addItem("x = "+str(self.x1)+", N = "+str(self.N)) break self.x0 = self.x1
def d2V_func(lat, V, field_var): "Calculate the masses of the fields in terms of the field values:" field_list = lat.field_list from sympy import diff, Symbol, var, simplify, sympify, S, evalf from sympy.utilities import lambdify from sympy.core.sympify import SympifyError C_coeff = V.C_coeff D_coeff = V.D_coeff V_string = V.V try: d2V = diff(sympify(V_string), field_var, 2) except SympifyError: print "Could not parse expression." "Replacement list C_i->C_coeff[i], D_i->D_coeff[i]:" rep_list = {} for i in xrange(len(C_coeff)): rep_list.update({'C' + str(i + 1): C_coeff[i]}) for i in xrange(len(D_coeff)): rep_list.update({'D' + str(i + 1): D_coeff[i]}) d2V_func = lambdify(field_list, d2V.subs(rep_list)) return d2V_func
def eval_rational(self, tol): """ Returns a Rational approximation to ``self`` with the tolerance ``tol``. This method uses bisection, which is very robust and it will always converge. The returned Rational instance will be at most 'tol' from the exact root. The following example first obtains Rational approximation to 1e-7 accuracy for all roots of the 4-th order Legendre polynomial, and then evaluates it to 5 decimal digits (so all digits will be correct including rounding): >>> from sympy import S, legendre_poly, Symbol >>> x = Symbol("x") >>> p = legendre_poly(4, x, polys=True) >>> roots = [r.eval_rational(S(1)/10**7) for r in p.real_roots()] >>> roots = [str(r.n(5)) for r in roots] >>> roots ['-0.86114', '-0.33998', '0.33998', '0.86114'] """ if not self.is_real: raise NotImplementedError( "eval_rational() only works for real polynomials so far") func = lambdify(self.poly.gen, self.expr) interval = self._get_interval() a = Rational(str(interval.a)) b = Rational(str(interval.b)) # This is needed due to the bug #3364: a, b = min(a, b), max(a, b) return bisect(func, a, b, tol)
def get_coef(f, c, d): n = 4 y = Symbol('y') deriv = diff(f(y), y, y, y, y, y) func = lambdify(y, -abs(deriv)) max_deriv = -minimize(func, [np.mean([c, d])], bounds=[(c, d)]).fun[0] return max_deriv / factorial(n + 1)
def isolate(alg, eps=None, fast=False): """Give a rational isolating interval for an algebraic number. """ alg = sympify(alg) if alg.is_Rational: return (alg, alg) elif not ask(Q.real(alg)): raise NotImplementedError( "complex algebraic numbers are not supported") func = lambdify((), alg, modules="mpmath", printer=IntervalPrinter()) poly = minpoly(alg, polys=True) intervals = poly.intervals(sqf=True) dps, done = mp.dps, False try: while not done: alg = func() for a, b in intervals: if a <= alg.a and alg.b <= b: done = True break else: mp.dps *= 2 finally: mp.dps = dps if eps is not None: a, b = poly.refine_root(a, b, eps=eps, fast=fast) return (a, b)
def _eval_evalf(self, prec): """Evaluate this complex root to the given precision. """ _prec, mp.prec = mp.prec, prec try: func = lambdify(self.poly.gen, self.expr) interval = self._get_interval() refined = False while True: if self.is_real: x0 = mpf(str(interval.center)) else: x0 = mpc(*map(str, interval.center)) try: root = findroot(func, x0) except ValueError: interval = interval.refine() refined = True continue else: if refined: self._set_interval(interval) break finally: mp.prec = _prec return Float._new(root.real._mpf_, prec) + I*Float._new(root.imag._mpf_, prec)
def isolate(alg, eps=None, fast=False): """Give a rational isolating interval for an algebraic number. """ alg = sympify(alg) if alg.is_Rational: return (alg, alg) elif not alg.is_real: raise NotImplementedError( "complex algebraic numbers are not supported") func = lambdify((), alg, modules="mpmath", printer=IntervalPrinter()) poly = minpoly(alg, polys=True) intervals = poly.intervals(sqf=True) dps, done = mp.dps, False try: while not done: alg = func() for a, b in intervals: if a <= alg.a and alg.b <= b: done = True break else: mp.dps *= 2 finally: mp.dps = dps if eps is not None: a, b = poly.refine_root(a, b, eps=eps, fast=fast) return (a, b)
def computeStabilityFunction(self, A,b,c, bSympy=True): """ returns the stability function R(z) of the Runge-Kutta methods defined by A,b,c """ s = np.size(b) if bSympy: # use symbolic computations to improve speed (effective for low number of stages) s = b.size # nombre d'étages A = sp.Matrix( A ) b = sp.Matrix( b ) c = sp.Matrix( c ) z = sp.Symbol("z") I = sp.Matrix(np.eye(s)) e = sp.Matrix(np.ones((s,))) M_up = I -z*A + z*e*b.T M_down = I-z*A Rsym = M_up.det()/M_down.det() # polynôme R = lambdify((z,),Rsym) # version numérique else: # no symbolic computations e=np.ones((s,)) # Rlbda = lambda z: 1+z*np.dot(b, np.linalg.inv(np.eye(s)-z*A).dot(e)) def Rlbda(z): try: return 1+z*np.dot(b, np.linalg.inv(np.eye(s)-z*A).dot(e)) except np.linalg.LinAlgError: # singular matrix return np.nan R=np.vectorize(Rlbda) Rsym=None return R, Rsym
def eval_rational(self, tol): """ Return a Rational approximation to ``self`` with the tolerance ``tol``. This method uses bisection, which is very robust and it will always converge. The returned Rational instance will be at most 'tol' from the exact root. The following example first obtains Rational approximation to 1e-7 accuracy for all roots of the 4-th order Legendre polynomial, and then evaluates it to 5 decimal digits (so all digits will be correct including rounding): >>> from sympy import S, legendre_poly, Symbol >>> x = Symbol("x") >>> p = legendre_poly(4, x, polys=True) >>> roots = [r.eval_rational(S(1)/10**7) for r in p.real_roots()] >>> roots = [str(r.n(5)) for r in roots] >>> roots ['-0.86114', '-0.33998', '0.33998', '0.86114'] """ if not self.is_real: raise NotImplementedError( "eval_rational() only works for real polynomials so far") func = lambdify(self.poly.gen, self.expr) interval = self._get_interval() a = Rational(str(interval.a)) b = Rational(str(interval.b)) return bisect(func, a, b, tol)
def calcualte_dim(expr01, terminals, dim_list, dim_maps=None): """ Parameters ---------- expr01: Expr sympy expression. terminals: list of sympy.Symbol features and constants dim_list: list of Dim dims of features and constants dim_maps: Callable user dim_maps Returns ------- Dim: dimension dim_score is target dim or not """ terminals = [str(i) for i in terminals] if not dim_maps: dim_maps = dim_map() func0 = utilities.lambdify(terminals, expr01, modules=[dim_maps]) try: dim_ = func0(*dim_list) except (ValueError, TypeError, ZeroDivisionError, NameError): dim_ = dnan if isinstance(dim_, (float, int)): dim_ = dless if not isinstance(dim_, Dim): dim_ = dnan return dim_
def get_transformation_function(segments, fixed_endpoint=None, fixed_basepoint=None, use_dict=True): if fixed_endpoint: coordinate_labels = [] else: coordinate_labels = ['x', 'y', 'z'] if fixed_basepoint: inverse_coordinate_labels = [] else: inverse_coordinate_labels = ['base_x', 'base_y', 'base_z'] trans_mat, inv_trans_mat, var_names = get_sympy_reduction( segments, fixed_endpoint, fixed_basepoint, coordinate_labels, inverse_coordinate_labels) # Bake into a lambda func base_func = lambdify(flatten((coordinate_labels, var_names)), trans_mat) base_inv_func = lambdify(flatten((inverse_coordinate_labels, var_names)), inv_trans_mat) if use_dict: if fixed_endpoint: func = lambda var_dict: base_func(*flatten( [var_dict[var_name] for var_name in var_names])).A else: func = lambda coords, var_dict: base_func(*flatten( (coords, [var_dict[var_name] for var_name in var_names]))).A if fixed_basepoint: inv_func = lambda var_dict: base_inv_func(*flatten( [var_dict[var_name] for var_name in var_names])).A else: inv_func = lambda coords, var_dict: base_inv_func(*flatten( (coords, [var_dict[var_name] for var_name in var_names]))).A else: if fixed_endpoint: func = lambda var_vals: base_func(*flatten(var_vals)).A else: func = lambda coords, var_vals: base_func(*flatten( (coords, var_vals))).A if fixed_basepoint: inv_func = lambda var_vals: base_inv_func(*flatten(var_vals)).A else: inv_func = lambda coords, var_vals: base_inv_func(*flatten( (coords, var_vals))).A return func, inv_func
def solve(self, iterations=10, until=None, threshold=0.001, debuglist=None): """ Runs the solver. The solver will try to find a solution until one of the conditions is reached: (1) the iterations limit is reached In this case a SolutionNotFoundError will be raised. (2) the until condition returns True Arguments: iterations: The number of iterations to run until a solution is reached. (Default: 10) until: This is a function that determines whether or not a solution is reached. (Default: residual error) This takes two parameters, the previous solution vector and the current solution vector. threshold: If using the default end condition, this is the threshold that the residuals must be less than. Raises: SolutionNotFoundError: """ # pylint: disable=invalid-name self._validate_equations() current = self._get_context() if len(self.solutions) == 0: self._update_solutions({k.name: v for k, v in current.items()}) # do we need to update the function lambdas? This is needed # if the number of variables/parameters/equations change. if self._need_function_update: arg_list = [x for x in current.keys()] for i in xrange(len(arg_list)): if isinstance(arg_list[i], Symbol): arg_list[i]._index = i private_funcs = {x[2].__name__: x[1] for x in _RT_FUNCS} for var in self.variables.values(): var.equation.func = lambdify(arg_list, var.equation.expr, private_funcs) self._need_function_update = False solution = _run_solver(self.equations, self.variables, current, max_iterations=iterations, until=until, threshold=threshold, debuglist=debuglist) soln = {k.name: v for k, v in solution.items()} self._update_solutions(soln)
def _eval_evalf(self, prec): """Evaluate this complex root to the given precision. """ _prec, mp.prec = mp.prec, prec try: func = lambdify(self.poly.gen, self.expr) interval = self._get_interval() if not self.is_real: # For complex intervals, we need to keep refining until the # imaginary interval is disjunct with other roots, that is, # until both ends get refined. ay = interval.ay by = interval.by while interval.ay == ay or interval.by == by: interval = interval.refine() while True: if self.is_real: x0 = mpf(str(interval.center)) else: x0 = mpc(*map(str, interval.center)) try: root = findroot(func, x0) # If the (real or complex) root is not in the 'interval', # then keep refining the interval. This happens if findroot # accidentally finds a different root outside of this # interval because our initial estimate 'x0' was not close # enough. if self.is_real: a = mpf(str(interval.a)) b = mpf(str(interval.b)) # This is needed due to the bug #3364: a, b = min(a, b), max(a, b) if not (a < root < b): raise ValueError("Root not in the interval.") else: ax = mpf(str(interval.ax)) bx = mpf(str(interval.bx)) ay = mpf(str(interval.ay)) by = mpf(str(interval.by)) # This is needed due to the bug #3364: ax, bx = min(ax, bx), max(ax, bx) ay, by = min(ay, by), max(ay, by) if not (ax < root.real < bx and ay < root.imag < by): raise ValueError("Root not in the interval.") except ValueError: interval = interval.refine() continue else: break finally: mp.prec = _prec return Float._new(root.real._mpf_, prec) + I * Float._new(root.imag._mpf_, prec)
def get_expected_val_scm(self, idx, act_scm, symb, input_values): from sympy.stats import E, variance a = sympy.symbols('a') new_fun=implemented_function('scm_'+str(idx), lambda inp: act_scm.subs((symb[i], Normal(symb[i], inp[i][0], inp[i][1])) for i in range(0, len(inp)))) lam_f=lambdify(a, new_fun(a)) erg=lam_f(input_values) E=E(erg) V=variance(erg) return E, V
def __init__(self, name, params, equation): self._name = name expr = sympy_parser.parse_expr( equation, transformations=sympy_parser.standard_transformations + (sympy_parser.convert_xor, ), evaluate=False) expr = expr.subs(params) self._f = lambdify(expr.free_symbols, expr)
def f_min(y,mi,mx,stp): """ y - form of analytical function mi - plot and analyze in interval starting from this value mx - plot and alalyze in interval ending with this value stp- stepsize on the x axis. (with a little imagination it can be considered as resolution """ fd=[];d={} t=np.arange(mi,mx,stp) ly=lambdify(x,y) dy=y.diff() ldy=lambdify(x,dy) print 'Analitical function: ',y print 'first derivative: ',dy for i in np.arange(mi,mx,stp): # searhing where the first derivative is zero OR NEAR ZERO! # /technically the same way can be done with lambdify if -0.01 < dy.subs(x,i).evalf() < 0.01: yy=y.subs(x,i).evalf() print 'local extreme at (x,y): (%s, %s)' %(i,yy) d[yy]=i ix=max(d.keys()) ixmin=min(d.keys()) iy=d.get(ix) iymin=d.get(ixmin) print ' ' print 'Global minimum at (x,y): (%s, %s) ' %(iymin,ixmin) print 'Global maximum at (x,y): (%s, %s) ' %(iy,ix) plt.figure('minimi') o1=[];o2=[] for ii in np.arange(mi,mx,stp): o1.append(ly(ii)) o2.append(ldy(ii)) # the plot option below # plt.plot(t,ly(np.arange(mi,mx,stp))) plt.plot(t,o1) # plt.plot(t,ldy(np.arange(mi,mx,stp))) plt.plot(t,o2) plt.plot(iy,ix,'ro',iymin,ixmin,'bo') plt.legend(['y= %s'%y,'dy= %s' %dy, 'extreme point global max','extreme point global min']) plt.show()
def _eval_evalf(self, prec): """Evaluate this complex root to the given precision. """ _prec, mp.prec = mp.prec, prec try: func = lambdify(self.poly.gen, self.expr) interval = self._get_interval() if not self.is_real: # For complex intervals, we need to keep refining until the # imaginary interval is disjunct with other roots, that is, # until both ends get refined. ay = interval.ay by = interval.by while interval.ay == ay or interval.by == by: interval = interval.refine() while True: if self.is_real: x0 = mpf(str(interval.center)) else: x0 = mpc(*map(str, interval.center)) try: root = findroot(func, x0) # If the (real or complex) root is not in the 'interval', # then keep refining the interval. This happens if findroot # accidentally finds a different root outside of this # interval because our initial estimate 'x0' was not close # enough. if self.is_real: a = mpf(str(interval.a)) b = mpf(str(interval.b)) # This is needed due to the bug #3364: a, b = min(a, b), max(a, b) if not (a < root < b): raise ValueError("Root not in the interval.") else: ax = mpf(str(interval.ax)) bx = mpf(str(interval.bx)) ay = mpf(str(interval.ay)) by = mpf(str(interval.by)) # This is needed due to the bug #3364: ax, bx = min(ax, bx), max(ax, bx) ay, by = min(ay, by), max(ay, by) if not (ax < root.real < bx and ay < root.imag < by): raise ValueError("Root not in the interval.") except ValueError: interval = interval.refine() continue else: break finally: mp.prec = _prec return Float._new(root.real._mpf_, prec) + I*Float._new(root.imag._mpf_, prec)
def makefunc(expr, mathmodule = "numpy", dummify=False, **kwargs): symbols = list(expr.atoms(sp.Symbol)) symbols.sort(key=str) func = lambdify(symbols, expr, mathmodule, dummify=dummify, **kwargs) func.kw = symbols func.expr = expr func.kwstr = map(lambda x: x.name, symbols) func.dictcall = types.MethodType(dictcall, func) func.__doc__ = str(expr) return func
def get_coef(f, c, d): y = Symbol('y') # Дифференцируем 5 раз deriv = diff(f(y), y, y, y, y, y) # Получаем функцию из объекта библиотеки sympy deriv_func = lambdify(y, -abs(deriv)) # Минимизируем отрицательную производную, задав начальную точку и интервал поиска max_deriv = -minimize(deriv_func, [np.mean([c, d])], bounds=[(c, d) ]).fun[0] return max_deriv / factorial(n)
def bezierCurve(Points): bx = round(3 * (Points[1][0] - Points[0][0]), 2) cx = round(3 * (Points[2][0] - Points[1][0]) - bx, 2) dx = round(Points[3][0] - Points[0][0] - bx - cx, 2) by = round(3 * (Points[1][1] - Points[0][1]), 2) cy = round(3 * (Points[2][1] - Points[1][1]) - by, 2) dy = round(Points[3][1] - Points[0][1] - by - cy, 2) x = lambda t: Points[0][0] + bx * t + cx * t**2 + dx * t**3 y = lambda t: Points[0][1] + by * t + cy * t**2 + dy * t**3 xExpr = sympify( str(Points[0][0]) + "+" + str(bx) + "*t" + "+" + str(cx) + "*t**2" + "+" + str(dx) + "*t**3") yExpr = sympify( str(Points[0][1]) + "+" + str(by) + "*t" + "+" + str(cy) + "*t**2" + "+" + str(dy) + "*t**3") tSymbol = symbols('t') dxdt = lambdify(tSymbol, diff(xExpr, tSymbol), "math") dydt = lambdify(tSymbol, diff(yExpr, tSymbol), "math") return (x, y), (dxdt, dydt)
def _construct(self, zet): if not isinstance(zet, AbstractSet): zet = as_abstract(zet) var = zet.variables expr = zet.expr func = lambdify(var, expr) if len(var) == 1: return bitmap(func, self.voxels) else: return bitmap(lambda v: func(*v), self.voxels)
def derivative(f, order): if order < 0: return ValueError if order == 0: return f x = Symbol('x') deriv = diff(f(x), x) for i in range(1, order): deriv = sy.diff(deriv, x) return lambdify(x, deriv)
def chisquared_num(self, y, sig, x, param): """ Calculate the numerical value of chi squared for a model given parameter values. :param y: Array of measured values (floats). :param sig: Array of measurement uncertainties (floats). :param x: Array containing numeric values of the independent variable. :param param: List containing numeric values of the model parameters. :return: Numerical value of chi squared. """ chi = self.chisquared(y, sig, x) chi_func = lambdify(self.model_param, chi) return chi_func(*param)
def __init__(self, function, lower_bound, upper_bound, segments=1000): self.segments = segments self.a_coef = np.empty(segments, dtype=float) self.b_coef = np.empty(segments, dtype=float) self.shift_coef = (upper_bound - lower_bound) / 2 / np.pi x, n = sp.symbols('x n') a = lambdify( (x, n), sp.integrate(function(x) * sp.cos(n * x / self.shift_coef), x)) b = lambdify( (x, n), sp.integrate(function(x) * sp.sin(n * x / self.shift_coef), x)) def get_coef(I, n, a, b): return I(b, n) - I(a, n) self.a_coef[0] = get_coef(a, 0, lower_bound, upper_bound) for k in range(1, segments): self.a_coef[k] = get_coef(a, k, lower_bound, upper_bound) self.b_coef[k] = get_coef(b, k, lower_bound, upper_bound)
def compute_singular_points(self): if self.singular_manifolds is None: self.singular_manifolds = sp.solve(self.gq_sym, self.q_sym, self.r_sym) fncs = [] for singular_manifold in self.singular_manifolds: fncs.append(lambdify(self.r_sym, singular_manifold[0], "numpy")) return fncs
def eofhtb(): import sympy from sympy import Matrix import numpy as np import scipy # H_e, convection; K_e, conduction; C_e, specific heat h=120 #convection T_a=25 #ambient temperature [C] k=200 #thermal conductivity [W/m*C] rho=1 #density P=10e-3 #perimeter [m] L=1e-2 #length per element A=6e-6 #section area [m^2] C_p=2.42e6 #specific heat [W/m**3*C] sympy.var('x') N=Matrix([[1-x], [x]]) #shape function B=Matrix([-1,1]) #temperature-gradient function f_e=Matrix([1,1]) #elementwise heat flux f_e= (h*P*L*T_a/2)*f_e #elementwise heat flux #initialize C_e, H_e, K_e C_ee= N*np.transpose(N) H_ee= N*np.transpose(N) K_ee= B*np.transpose(B) x1,x2=(0,1) from sympy.utilities import lambdify from mpmath import quad C_e=scipy.zeros(C_ee.shape, dtype=float) H_e=scipy.zeros(H_ee.shape, dtype=float) K_e=scipy.zeros(K_ee.shape, dtype=float) #Numerical integration for (i,j), expr1 in scipy.ndenumerate(H_ee): H_e[i,j] = quad(lambdify((x),expr1,'math'),(x1,x2)) H_e[i,j] = h*P*L*H_e[i,j] C_e[i,j] = rho*C_p*L*A*quad(lambdify((x),expr1,'math'),(x1,x2)) for (i,j), expr2 in scipy.ndenumerate(K_ee): K_e[i,j] = quad(lambdify((x),expr2,'math'),(x1,x2)) K_e[i,j] = ((A*k)/L)*K_e[i,j] #Compute total stiffness (Conduction+Convection) K_e_total=H_e+K_e return (H_e,K_e,C_e,K_e_total,f_e);
def beta(self, y, sig, x, param): """ Calculate half the negative gradient of chi squared. Might be on the chopping block. :param y: Array of measured values (floats). :param sig: Array of measurement uncertainties (floats). :param x: Array containing numeric values of the independent variable. :param param: List containing numeric values of the model parameters. :return: Array containing the negative of half the numeric gradient. """ c = self.chisq_grad(y, sig, x) d = lambdify(self.model_param, c) return -1 / 2 * sp.asarray(d(*param))
def RelaxMethod(self): self.x0 = float(self.phiEditSI.text()) self.a = self.x0 self.b = float(self.x0EditSI.text()) self.eps = float(self.epsEditSI.text()) self.fexpr = parse_expr(self.fEditSI.text()) self.f = lambdify(x, self.fexpr) xarg = np.linspace(self.a, self.b, np.abs(self.b-self.a)*1000) dfexpr = self.fexpr.diff(x) df = lambdify(x, dfexpr, 'numpy') dfa = np.fabs(df(xarg)) M1 = np.max(dfa) m1 = np.min(dfa) tau = 2/(M1+m1) ro0 = (M1-m1)/(M1+m1) self.N = (np.floor(np.log((self.eps*(1-ro0))/(self.b-self.a))/np.log(ro0))+1).astype(np.int64) x1 = self.x0 + tau * self.f(self.x0) self.x0 = x1 for i in range(self.N-1): x1 = self.x0 + tau * self.f(self.x0) self.x0 = x1 self.listWidget.addItem("x = "+str(x1)+", N = "+str(self.N))
def accepted(self): self.N = 0 expr = parse_expr(self.fEdit.text()) f = lambdify(x, expr) # # a, b, eps = float(self.aEdit.text()), float(self.bEdit.text()), float(self.epsEdit.text()) if a and b and eps and f: if self.bisRButton.isChecked(): self.halfIntervalMethod(f, a, b, eps) else: self.chordMeth(f, a, b, eps)
def calculate_y_unpack(expr01, x, terminals, classification=False): try: func0 = utilities.lambdify(terminals, expr01) pre_y = func0(*x) if classification: pre_y = cla(pre_y) pre_y = pre_y.ravel() pre_y = check_array(pre_y, ensure_2d=False) except (DataConversionWarning, AssertionError, ValueError, AttributeError, KeyError, ZeroDivisionError): pre_y = None return pre_y
def analyticalButtonClicked(self): self.derTableWidget.clear() self.tableWidget.clear() self.tableWidget.setRowCount(0) self.derTableWidget.setColumnCount(0) expr = parse_expr(self.fEdit.text()) f = lambdify(x, expr, 'numpy') diff = expr.diff(x) diffroots = solve(diff, x) diffroots.insert(0, float("-inf")) diffroots.append(float("inf")) colPosition = self.derTableWidget.columnCount() self.derTableWidget.setRowCount(2) self.derTableWidget.insertColumn(colPosition) self.derTableWidget.setItem(0, colPosition, QTableWidgetItem("DerInterval")) self.derTableWidget.setItem(1, colPosition, QTableWidgetItem("Sign f(x)")) for i in range(len(diffroots)): colPosition = self.derTableWidget.columnCount() self.derTableWidget.insertColumn(colPosition) self.derTableWidget.setItem(0, colPosition, QTableWidgetItem(("%f"%(diffroots[i])))) self.derTableWidget.setItem(1, colPosition, QTableWidgetItem(str(sign(f(diffroots[i]))))) xspace = np.linspace(int(diffroots[1]-100), int(diffroots[len(diffroots)-2]+100), int(diffroots[len(diffroots)-2]-diffroots[1]+201)) #TODO: to end work with long table and algorithm with step dct = {} for i in xspace: dct[i] = sign(f(i)) self.tableWidget.setColumnCount(2) rowCount = self.tableWidget.rowCount() self.tableWidget.insertRow(rowCount) self.tableWidget.setItem(rowCount, 0, QTableWidgetItem("x")) self.tableWidget.setItem(rowCount, 1, QTableWidgetItem("Sign f(x)")) keylist = [] keylist = dct.keys() for key in sorted(keylist): rowCount = self.tableWidget.rowCount() self.tableWidget.insertRow(rowCount) self.tableWidget.setItem(rowCount, 0, QTableWidgetItem("%f" %key)) self.tableWidget.setItem(rowCount, 1, QTableWidgetItem(dct[key])) self.derEdit.setText(str(diff)) intervals = '' keylist = sorted(keylist) for i in range(len(keylist)-1): if (dct[keylist[i]] == '-' and dct[keylist[i+1]] == '+') or (dct[keylist[i]] == '+' and dct[keylist[i+1]] == '-'): intervals =( "%s%s" %(intervals, makeinterval(keylist[i], keylist[i+1], f))) elif (dct[keylist[i]] == '0'): intervals = ('%s{%f} and' % (intervals, keylist[i])) self.rootIntervalEdit.setText(intervals)
def index_post(name = None): if(request.method == 'POST'): default_asot = "343.822718 + x*1.8291" adlib_size_of_time = str(request.form.get('adlib_eq', default_asot, type=str)) if adlib_size_of_time == "": adlib_size_of_time = default_asot sim_len = int(request.form.get('sim_len', 80, type=int)) restr_len = int(request.form.get('restr_len', 50, type=int)) restr = float(request.form.get('restr', 9, type=float)) / 100 market_price = float(request.form.get('market_price', 2.89, type=float)) feed_cost = float(request.form.get('feed_cost', 0.25, type=float)) fac_cost = float(request.form.get('fac_cost', 0.35, type=float)) int_rate = float(request.form.get('int_rate', 7.5, type=float)) / 100 adlib_size_of_time += "-y" adlib_size_of_time = parse_expr(adlib_size_of_time) TIME = Symbol("x") SIZE = Symbol("y") # print solve(adlib_size_of_time, SIZE) # print solve(adlib_size_of_time, TIME) get_adlib_size = lambdify(TIME, solve(adlib_size_of_time, SIZE)[0]) get_adlib_time = lambdify(SIZE, solve(adlib_size_of_time, TIME)[0]) sim = simulation.Simulation(sim_len, restr_len, restr) sim.eqs.get_adlib_size = get_adlib_size sim.eqs.get_adlib_time = get_adlib_time sim.feed_cost = feed_cost sim.facility_cost = fac_cost sim.market_price = market_price sim.discount = int_rate sim.run_complete() graph_url = get_graph_url(sim) print "plot url: ", graph_url return render_template("output.html", ploturl = graph_url)
def alpha(self, y, sig, x, param): """ Returns a numeric expression for the Hessian matrix of chi squared. Note: The second derivatives are excluded and this expression only contains the product of first derivatives. See Numerical Recipes page 800-801 (Press, 1987) for more details. :param y: Array of measured values (floats). :param sig: Array of measurement uncertainties (floats). :param x: Array containing numeric values of the independent variable. :param param: List containing numeric values of the model parameters. :return: Array containing half of the numeric hessian. """ c = self.chisq_hessian(y, sig, x) d = lambdify(self.model_param, c) return 1 / 2 * sp.asarray(d(*param))
def interpolate_species_gamma(self, sp, deriv=False): if (sp.name == 'H2_1') or (sp.name == 'H2_2'): expr_gammaH2 = self.species_gamma(species_registry['H2_1'], temp=True, name=False) if deriv is True: expr_dgammaH2_dT = sympy.diff(expr_gammaH2, 'T') f_dgammaH2_dT = lambdify('T', expr_dgammaH2_dT) dgammaH2_dT = f_dgammaH2_dT(self.T) _i1 = np.isnan(dgammaH2_dT) dgammaH2_dT[_i1] = 0.0 return dgammaH2_dT else: f_gammaH2 = lambdify('T', expr_gammaH2) gammaH2_T = f_gammaH2(self.T) _i1 = np.isnan(gammaH2_T) gammaH2_T[_i1] = 7. / 5. return gammaH2_T else: print('Provide your gamma function for {}'.format(sp.name)) raise RuntimeError
def _f(variables, expression): if not expression or expression == "None": return None elif callable(expression): return expression else: if len(variables) == 1 and "|" in variables[0] and Symbol is not None: expression = sympify(expression) present_variables = expression.free_symbols for preferred in map(Symbol, variables[0].split("|")): if preferred in present_variables: present_variables.remove(preferred) preferred = (preferred,) break else: preferred = () variables = *preferred, *(str(v) + "=0" for v in present_variables) return lambdify(variables, expression)
def isolate(alg, eps=None, fast=False): """Give a rational isolating interval for an algebraic number. """ alg = sympify(alg) if alg.is_Rational: return (alg, alg) elif not ask(Q.real(alg)): raise NotImplementedError("complex algebraic numbers are not supported") from sympy.printing.lambdarepr import LambdaPrinter class IntervalPrinter(LambdaPrinter): """Use ``lambda`` printer but print numbers as ``mpi`` intervals. """ def _print_Integer(self, expr): return "mpi('%s')" % super(IntervalPrinter, self)._print_Integer(expr) def _print_Rational(self, expr): return "mpi('%s')" % super(IntervalPrinter, self)._print_Rational(expr) func = lambdify((), alg, modules="mpmath", printer=IntervalPrinter()) poly = minpoly(alg, polys=True) intervals = poly.intervals(sqf=True) dps, done = mp.dps, False try: while not done: alg = func() for a, b in intervals: if a <= alg.a and alg.b <= b: done = True break else: mp.dps *= 2 finally: mp.dps = dps if eps is not None: a, b = poly.refine_root(a, b, eps=eps, fast=fast) return (a, b)
def _eval_evalf(self, prec): """Evaluate this complex root to the given precision. """ _prec, mp.prec = mp.prec, prec try: func = lambdify(self.poly.gen, self.expr) interval, refined = self._get_interval(), False while True: if self.is_real: x0 = mpf(str(interval.center)) else: re, im = interval.center re = mpf(str(re)) im = mpf(str(im)) x0 = mpc(re, im) try: root = findroot(func, x0) except ValueError: interval = interval.refine() refined = True continue else: if refined: self._set_interval(interval) if self.is_conjugate: root = root.conjugate() break finally: mp.prec = _prec return Real._new(root.real._mpf_, prec) + I*Real._new(root.imag._mpf_, prec)
def _lambdify(self, expr): """ Creates a lambdified expression with the appropriate args """ return lambdify(self._arg_list, expr, self._private_funcs)
z = w**3 e_z = expand(z) print e_z rp = re(e_z) print rp ip = im(e_z) print ip # We will plot the surface defined by # [re((u+I*v)**3), im((u+I*v)**3, u] # so the height is the real part of the cubed root. from sympy.utilities import lambdify s = "[" + str(rp) + "," + str(ip) + "," + str(u) + "]" import numpy f = lambdify((u,v),s,numpy) print f(3,2) # If matplotlib is installed, then we can plot surfaces # with the visualization module of the package sympy.mpmath. # We use splot to plot the surface given in parametric form # by f as f(u,v) = x, y, z, for u and v in [-1,+1] # from sympy.mpmath import splot # splot(f,[-1,1],[-1,1]) # We sample the surface for u and v ranging in [-1,+1] # where u is the real part of z^(1/3) and v the imaginary part of z^(1/3). # The plot shows the real part as the height and uses the color # as the imaginary part. # The order of the enumeration of the sample points goes first with v
def _eval_evalf(self, prec): """Evaluate this complex root to the given precision. """ with workprec(prec): g = self.poly.gen if not g.is_Symbol: d = Dummy('x') func = lambdify(d, self.expr.subs(g, d)) else: func = lambdify(g, self.expr) interval = self._get_interval() if not self.is_real: # For complex intervals, we need to keep refining until the # imaginary interval is disjunct with other roots, that is, # until both ends get refined. ay = interval.ay by = interval.by while interval.ay == ay or interval.by == by: interval = interval.refine() while True: if self.is_real: a = mpf(str(interval.a)) b = mpf(str(interval.b)) if a == b: root = a break x0 = mpf(str(interval.center)) else: ax = mpf(str(interval.ax)) bx = mpf(str(interval.bx)) ay = mpf(str(interval.ay)) by = mpf(str(interval.by)) if ax == bx and ay == by: # the sign of the imaginary part will be assigned # according to the desired index using the fact that # roots are sorted with negative imag parts coming # before positive (and all imag roots coming after real # roots) deg = self.poly.degree() i = self.index # a positive attribute after creation if (deg - i) % 2: if ay < 0: ay = -ay else: if ay > 0: ay = -ay root = mpc(ax, ay) break x0 = mpc(*map(str, interval.center)) try: root = findroot(func, x0) # If the (real or complex) root is not in the 'interval', # then keep refining the interval. This happens if findroot # accidentally finds a different root outside of this # interval because our initial estimate 'x0' was not close # enough. It is also possible that the secant method will # get trapped by a max/min in the interval; the root # verification by findroot will raise a ValueError in this # case and the interval will then be tightened -- and # eventually the root will be found. # # It is also possible that findroot will not have any # successful iterations to process (in which case it # will fail to initialize a variable that is tested # after the iterations and raise an UnboundLocalError). if self.is_real: if (a <= root <= b): break elif (ax <= root.real <= bx and ay <= root.imag <= by): break except (UnboundLocalError, ValueError): pass interval = interval.refine() return (Float._new(root.real._mpf_, prec) + I*Float._new(root.imag._mpf_, prec))
def compile(self): """Generates the equations of motion for the simulation and generates a numeric function that will serve as the ode for ode45""" # First, we generate a "system position", "system velocity", # and "system acceleration" vector, which contain all the # information on each object's location and rotation. # At the same time, we generate a "system mass" matrix which # is diagonal and serves to keep track of the corresponding # mass (or moment of inertia) for each term in the system # position vector. self.r, self.v, self.a = [], [], [] self.M = []; self.dM = [] for bod in self.bods: self.r.extend(list(bod.r)) self.v.extend(list(bod.v)) self.a.extend(list(bod.a)) self.M.extend([bod.m]*len(bod.r)) self.dM.extend([s.diff(bod.m,t)]*len(bod.r)) try: self.r.append(bod.ang) self.v.append(bod.omega) self.a.append(bod.alpha) self.M.append(bod.I) self.dM.append(s.diff(bod.I,t)) except AttributeError: pass self.r = s.Matrix(self.r) self.v = s.Matrix(self.v) self.a = s.Matrix(self.a) M = s.Matrix([[0]*len(self.r)]*len(self.r)) dM = s.Matrix([[0]*len(self.r)]*len(self.r)) for i,m in enumerate(self.M): M[i,i] = m dM[i,i] = dM[i] self.M = M self.dM = dM # Next, we generate the free directions of motion. One free # direction of motion exists for each degree of freedom, and # is found by taking the partial derivative of self.r with # respect to that degree of freedom. self.dirs = s.Matrix([[0]*len(self.r)]*len(self.basis)) for i,var in enumerate(self.basis): direction = s.Matrix([s.diff(component, var) for component in self.r]) self.dirs[i,:] = direction.transpose() # Now we compile all the forces and moments into a "system # force vector", and calculate the system's potential energy. self.F = [] self.U = 0 for potential in self.potentials: if potential[0] == Potential2D: self.U += potential[1] for bod in self.bods: for force in self.forces: if force[0] == Force2D: bod.forces.append(force[0](*[arg(bod) for arg in force[1:]])) else: bod.forces.append(force[0](bod,*force[1:])) F = s.Matrix([0]*len(bod.r) + [0]) for force in bod.forces: F += force bod.U = 0 for potential in self.potentials: if potential[0] != Potential2D: bod.U += potential[0](bod,potential[1]) self.U += potential[0](bod,potential[1]) try: I = bod.I except AttributeError: #Make force a vector of length 2 if bod is a point mass F = s.Matrix(F[0:2]) self.F.extend(list(F)) self.F = s.Matrix(self.F) # Now, we generate the equations of motion. This is a cross between # Lagrange's equations for the conservative forces and my # own special sauce for the nonconservative forces. # Now we write F=d(mv)/dt in our new coordinate system LHS is the # F part, RHS is the d(mv) part. ULHS = s.Matrix([s.diff(self.U, q) for q in self.basis]) NLHS = s.simplify(self.dirs * self.F) LHS = NLHS - ULHS RHS = s.simplify(self.dirs * (self.M * self.a + self.dM * self.v)) # And put it into Vec = Mat*Diffs + Vec form self.dds = s.Matrix(self.ddbasis) self.RHMat = s.Matrix([[0]*len(self.basis)]*len(self.basis)) for i, ddvar in enumerate(self.ddbasis): collected = [component.expand().collect(ddvar) for component in RHS] coeffs = [component.coeff(ddvar) for component in collected] remainder = [coll - coeff*ddvar for coll, coeff in zip(collected, coeffs)] RHS = s.simplify(s.Matrix(remainder)) self.RHMat[i,:] = s.Matrix([s.simplify(coeff) for coeff in coeffs]).transpose() # Now we simplify it to LHS = RHMat * dds. This is our # final equation of motion self.LHS = LHS - RHS # # Now we generate the numeric ode function # input_vars = [t] + self.basis + self.dbasis divider = len(self.basis) #between basis and dbasis #the replacement is done to avoid problems with backslashes newvars = s.symbols(['x_'+str(i) for i in range(0,len(input_vars))]) #the flipping of the replacement variables is to avoid problems with #variables being replaced before their derivatives # Generate a numeric version of RHMat and LHS nRHMat = lambdify(newvars, self.RHMat.subs(zip(input_vars[::-1],newvars[::-1])), modules='numpy') nLHS = lambdify(newvars, self.LHS.subs(zip(input_vars[::-1],newvars[::-1])), modules='numpy') # And at the same time we generate numeric r & v functions self.nr = lambdify(newvars, self.r.subs(zip(input_vars[::-1],newvars[::-1])), modules='numpy') self.nv = lambdify(newvars, self.v.subs(zip(input_vars[::-1],newvars[::-1])), modules='numpy') self.nM = lambdify(newvars, self.M.subs(zip(input_vars[::-1],newvars[::-1])), modules='numpy') self.nU = [] for bod in self.bods: if bod.U == 0: def zilch(*args): return 0 nU = zilch else: nU = lambdify(newvars, bod.U.subs(zip(input_vars[::-1],newvars[::-1])), modules='numpy') self.nU.append(nU) def odes(t,y): ddvs = n.linalg.inv(nRHMat(t,*y)) * nLHS(t,*y) return n.hstack((y[divider:],n.ravel(ddvs))) self.odes = odes
# ### Cobb-Douglas example # In[99]: # Declare all symbols used in the equation and solve for y x, y, U,a= sm.symbols("x y U a") u = "x**a * y**(1-a)" u= parse_expr(u) yexp= sm.solve(u-U,y)[0] yexp # In[63]: y1 = lambdify([U,x,a],yexp) # now it takes number input in the order U, x, and a. y1(10,1,.5) # In[101]: # interactive plot, based on http://matplotlib.org/examples/widgets/slider_demo.html # Set plot of IC fig,ax =plt.subplots() a0=.5 u_grid = np.arange(10,25,5) xdom = np.arange(.5,30,.0001) l,= plt.plot(xdom,y1(u_grid[1],xdom,a0),lw=2,color='black') plt.ylim(0,100)
init_vprinting() #Create dictionaries for the values for the values zero_speed_dict = dict(zip(speeds, zeros(len(speeds)))) torque_dict = dict(zip([l_ankle_torque], [0])) forcing_matrix = kane.forcing forcing_matrix = simplify(forcing_matrix) forcing_matrix = simplify(forcing_matrix.subs(zero_speed_dict).subs(parameter_dict).subs(torque_dict)) forcing_solved = solve(forcing_matrix, [l_hip_torque, r_hip_torque, sin(theta1)]) lam_l = lambdify((theta1, theta2, theta3), forcing_solved[l_hip_torque]) lam_r = lambdify((theta1, theta2, theta3), forcing_solved[r_hip_torque]) lam_f = lambdify((theta1, theta2, theta3), forcing_matrix[0]) x = -0.5 y = 0 z = -3.15 X = [] Y = [] Z = [] answer_vector = [] trim = [] threshold = 0.01
# front wheel/ground contact point pQ = pFs.locatenew('Q', rF*F_z) # N.z component of vector to pQ from pP # this is our configuration constraint f = simplify(pQ.pos_from(pP) & N.z) print("f = {}\n".format(msprint(f))) # calculate the derivative of f for use with Newton-Raphson df = f.diff(theta) print("df/dθ = {}\n".format(msprint(df))) # constraint function for zero steer/lean configuration and # using the benchmark parameters f0 = lambdify(theta, f.subs({phi: 0, delta: 0}).subs(benchmark_parameters)) df0 = lambdify(theta, df.subs({phi: 0, delta: 0}).subs(benchmark_parameters)) print("verifying constraint equations are correct") print("for zero steer/lean, pitch should be pi/10") findroot(f0, 0.3, solver="newton", tol=1e-8, verbose=True, df=df0) # convert to moore parameters c_sym = symbols('x[1] pitch x[2] m_rr m_rf m_d1 m_d3 m_d2') c_sym_dict = dict(zip([phi, theta, delta, rR, rF, cR, cF, ls], c_sym)) fc = ccode(f.subs(c_sym_dict)) dfc = ccode(df.subs(c_sym_dict)) cpp_math = { 'cos': 'std::cos',
def eval_approx(self, n): """Evaluate this complex root to the given precision. This uses secant method and root bounds are used to both generate an initial guess and to check that the root returned is valid. If ever the method converges outside the root bounds, the bounds will be made smaller and updated. """ prec = dps_to_prec(n) with workprec(prec): g = self.poly.gen if not g.is_Symbol: d = Dummy('x') if self.is_imaginary: d *= I func = lambdify(d, self.expr.subs(g, d)) else: expr = self.expr if self.is_imaginary: expr = self.expr.subs(g, I*g) func = lambdify(g, expr) interval = self._get_interval() while True: if self.is_real: a = mpf(str(interval.a)) b = mpf(str(interval.b)) if a == b: root = a break x0 = mpf(str(interval.center)) x1 = x0 + mpf(str(interval.dx))/4 elif self.is_imaginary: a = mpf(str(interval.ay)) b = mpf(str(interval.by)) if a == b: root = mpc(mpf('0'), a) break x0 = mpf(str(interval.center[1])) x1 = x0 + mpf(str(interval.dy))/4 else: ax = mpf(str(interval.ax)) bx = mpf(str(interval.bx)) ay = mpf(str(interval.ay)) by = mpf(str(interval.by)) if ax == bx and ay == by: root = mpc(ax, ay) break x0 = mpc(*map(str, interval.center)) x1 = x0 + mpc(*map(str, (interval.dx, interval.dy)))/4 try: # without a tolerance, this will return when (to within # the given precision) x_i == x_{i-1} root = findroot(func, (x0, x1)) # If the (real or complex) root is not in the 'interval', # then keep refining the interval. This happens if findroot # accidentally finds a different root outside of this # interval because our initial estimate 'x0' was not close # enough. It is also possible that the secant method will # get trapped by a max/min in the interval; the root # verification by findroot will raise a ValueError in this # case and the interval will then be tightened -- and # eventually the root will be found. # # It is also possible that findroot will not have any # successful iterations to process (in which case it # will fail to initialize a variable that is tested # after the iterations and raise an UnboundLocalError). if self.is_real or self.is_imaginary: if not bool(root.imag) == self.is_real and ( a <= root <= b): if self.is_imaginary: root = mpc(mpf('0'), root.real) break elif (ax <= root.real <= bx and ay <= root.imag <= by): break except (UnboundLocalError, ValueError): pass interval = interval.refine() # update the interval so we at least (for this precision or # less) don't have much work to do to recompute the root self._set_interval(interval) return (Float._new(root.real._mpf_, prec) + I*Float._new(root.imag._mpf_, prec))