def test_idiff(): # the use of idiff in ellipse also provides coverage circ = x**2 + y**2 - 4 ans = -3*x*(x**2 + y**2)/y**5 assert ans == idiff(circ, y, x, 3).simplify() assert ans == idiff(circ, [y], x, 3).simplify() assert idiff(circ, y, x, 3).simplify() == ans explicit = 12*x/sqrt(-x**2 + 4)**5 assert ans.subs(y, solve(circ, y)[0]).equals(explicit) assert True in [sol.diff(x, 3).equals(explicit) for sol in solve(circ, y)] assert idiff(x + t + y, [y, t], x) == -Derivative(t, x) - 1
def parameter_value(self, other, t): """Return the parameter corresponding to the given point. Evaluating an arbitrary point of the entity at this parameter value will return the given point. Examples ======== >>> from sympy import Line, Point >>> from sympy.abc import t >>> a = Point(0, 0) >>> b = Point(2, 2) >>> Line(a, b).parameter_value((1, 1), t) {t: 1/2} >>> Line(a, b).arbitrary_point(t).subs(_) Point2D(1, 1) """ from sympy.geometry.point import Point from sympy.core.symbol import Dummy from sympy.solvers.solvers import solve if not isinstance(other, GeometryEntity): other = Point(other, dim=self.ambient_dimension) if not isinstance(other, Point): raise ValueError("other must be a point") T = Dummy('t', real=True) sol = solve(self.arbitrary_point(T) - other, T, dict=True) if not sol: raise ValueError("Given point is not on %s" % func_name(self)) return {t: sol[0][T]}
def test_issue_8235(): assert reduce_inequalities(x**2 - 1 < 0) == \ And(S(-1) < x, x < S(1)) assert reduce_inequalities(x**2 - 1 <= 0) == \ And(S(-1) <= x, x <= 1) assert reduce_inequalities(x**2 - 1 > 0) == \ Or(And(-oo < x, x < -1), And(x < oo, S(1) < x)) assert reduce_inequalities(x**2 - 1 >= 0) == \ Or(And(-oo < x, x <= S(-1)), And(S(1) <= x, x < oo)) eq = x**8 + x - 9 # we want CRootOf solns here sol = solve(eq >= 0) tru = Or(And(rootof(eq, 1) <= x, x < oo), And(-oo < x, x <= rootof(eq, 0))) assert sol == tru # recast vanilla as real assert solve(sqrt((-x + 1)**2) < 1) == And(S(0) < x, x < 2)
def test_idiff(): x = Symbol('x', real=True) y = Symbol('y', real=True) t = Symbol('t', real=True) f = Function('f') g = Function('g') # the use of idiff in ellipse also provides coverage circ = x**2 + y**2 - 4 ans = -3*x*(x**2 + y**2)/y**5 assert ans == idiff(circ, y, x, 3).simplify() assert ans == idiff(circ, [y], x, 3).simplify() assert idiff(circ, y, x, 3).simplify() == ans explicit = 12*x/sqrt(-x**2 + 4)**5 assert ans.subs(y, solve(circ, y)[0]).equals(explicit) assert True in [sol.diff(x, 3).equals(explicit) for sol in solve(circ, y)] assert idiff(x + t + y, [y, t], x) == -Derivative(t, x) - 1 assert idiff(f(x) * exp(f(x)) - x * exp(x), f(x), x) == (x + 1) * exp(x - f(x))/(f(x) + 1) assert idiff(f(x) - y * exp(x), [f(x), y], x) == (y + Derivative(y, x)) * exp(x) assert idiff(f(x) - y * exp(x), [y, f(x)], x) == -y + exp(-x) * Derivative(f(x), x) assert idiff(f(x) - g(x), [f(x), g(x)], x) == Derivative(g(x), x)
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 test_issue_8235(): x = Symbol('x', real=True) assert reduce_inequalities(x**2 - 1 < 0) == \ And(S(-1) < x, x < S(1)) assert reduce_inequalities(x**2 - 1 <= 0) == \ And(S(-1) <= x, x <= 1) assert reduce_inequalities(x**2 - 1 > 0) == \ Or(And(-oo < x, x < -1), And(x < oo, S(1) < x)) assert reduce_inequalities(x**2 - 1 >= 0) == \ Or(And(-oo < x, x <= S(-1)), And(S(1) <= x, x < oo)) eq = x**8 + x**2 - 9 sol = solve(eq >= 0) known_sol = Or(And(-oo < x, RootOf(x**8 + x**2 - 9, 1) <= x, x < oo), \ And(-oo < x, x < oo, x <= RootOf(x**8 + x**2 - 9, 0))) assert sol == known_sol
def _lambert(eq, x): """ Given an expression assumed to be in the form ``F(X, a..f) = a*log(b*X + c) + d*X + f = 0`` where X = g(x) and x = g^-1(X), return the Lambert solution if possible: ``x = g^-1(-c/b + (a/d)*W(d/(a*b)*exp(c*d/a/b)*exp(-f/a)))``. """ eq = _mexpand(expand_log(eq)) mainlog = _mostfunc(eq, log, x) if not mainlog: return [] # violated assumptions other = eq.subs(mainlog, 0) if (-other).func is log: eq = (eq - other).subs(mainlog, mainlog.args[0]) mainlog = mainlog.args[0] if mainlog.func is not log: return [] # violated assumptions other = -(-other).args[0] eq += other if not x in other.free_symbols: return [] # violated assumptions d, f, X2 = _linab(other, x) logterm = collect(eq - other, mainlog) a = logterm.as_coefficient(mainlog) if a is None or x in a.free_symbols: return [] # violated assumptions logarg = mainlog.args[0] b, c, X1 = _linab(logarg, x) if X1 != X2: return [] # violated assumptions u = Dummy('rhs') sol = [] # check only real solutions: for k in [-1, 0]: l = LambertW(d/(a*b)*exp(c*d/a/b)*exp(-f/a), k) # if W's arg is between -1/e and 0 there is # a -1 branch real solution, too. if k and not l.is_real: continue rhs = -c/b + (a/d)*l solns = solve(X1 - u, x) for i, tmp in enumerate(solns): solns[i] = tmp.subs(u, rhs) sol.append(solns[i]) return sol
def solve_univariate_inequality(expr, gen, assume=True, relational=True): """Solves a real univariate inequality. Examples ======== >>> from sympy.solvers.inequalities import solve_univariate_inequality >>> from sympy.core.symbol import Symbol >>> x = Symbol('x', real=True) >>> solve_univariate_inequality(x**2 >= 4, x) Or(And(-oo < x, x <= -2), And(2 <= x, x < oo)) >>> solve_univariate_inequality(x**2 >= 4, x, relational=False) (-oo, -2] U [2, oo) """ # Implementation for continous functions from sympy.solvers.solvers import solve solns = solve(expr.lhs - expr.rhs, gen, assume=assume) oo = S.Infinity start = -oo sol_sets = [S.EmptySet] for x in sorted(s for s in solns if s.is_real): end = x if simplify(expr.subs(gen, (start + end)/2 if start != -oo else end - 1)): sol_sets.append(Interval(start, end, True, True)) if simplify(expr.subs(gen, x)): sol_sets.append(FiniteSet(x)) start = end end = oo if simplify(expr.subs(gen, start + 1)): sol_sets.append(Interval(start, end, True, True)) rv = Union(*sol_sets) return rv if not relational else rv.as_relational(gen)
def _integrate(field=None): irreducibles = set() for poly in reducibles: for z in poly.atoms(Symbol): if z in V: break else: continue irreducibles |= set(root_factors(poly, z, filter=field)) log_coeffs, log_part = [], [] B = _symbols('B', len(irreducibles)) for i, poly in enumerate(irreducibles): if poly.has(*V): log_coeffs.append(B[i]) log_part.append(log_coeffs[-1] * log(poly)) coeffs = poly_coeffs + log_coeffs candidate = poly_part/poly_denom + Add(*log_part) h = F - _derivation(candidate) / denom numer = h.as_numer_denom()[0].expand(force=True) equations = defaultdict(lambda: S.Zero) for term in Add.make_args(numer): coeff, dependent = term.as_independent(*V) equations[dependent] += coeff solution = solve(equations.values(), *coeffs) return (solution, candidate, coeffs) if solution else None
def pde_1st_linear_variable_coeff(eq, func, order, match, solvefun): r""" Solves a first order linear partial differential equation with variable coefficients. The general form of this partial differential equation is .. math:: a(x, y) \frac{df(x, y)}{dx} + a(x, y) \frac{df(x, y)}{dy} + c(x, y) f(x, y) - G(x, y) where `a(x, y)`, `b(x, y)`, `c(x, y)` and `G(x, y)` are arbitrary functions in `x` and `y`. This PDE is converted into an ODE by making the following transformation. 1] `\xi` as `x` 2] `\eta` as the constant in the solution to the differential equation `\frac{dy}{dx} = -\frac{b}{a}` Making the following substitutions reduces it to the linear ODE .. math:: a(\xi, \eta)\frac{du}{d\xi} + c(\xi, \eta)u - d(\xi, \eta) = 0 which can be solved using dsolve. The general form of this PDE is:: >>> from sympy.solvers.pde import pdsolve >>> from sympy.abc import x, y >>> from sympy import Function, pprint >>> a, b, c, G, f= [Function(i) for i in ['a', 'b', 'c', 'G', 'f']] >>> u = f(x,y) >>> ux = u.diff(x) >>> uy = u.diff(y) >>> genform = a(x, y)*u + b(x, y)*ux + c(x, y)*uy - G(x,y) >>> pprint(genform) d d -G(x, y) + a(x, y)*f(x, y) + b(x, y)*--(f(x, y)) + c(x, y)*--(f(x, y)) dx dy Examples ======== >>> from sympy.solvers.pde import pdsolve >>> from sympy import Function, diff, pprint, exp >>> from sympy.abc import x,y >>> f = Function('f') >>> eq = x*(u.diff(x)) - y*(u.diff(y)) + y**2*u - y**2 >>> pdsolve(eq) f(x, y) == F(x*y)*exp(y**2/2) + 1 References ========== - Viktor Grigoryan, "Partial Differential Equations" Math 124A - Fall 2010, pp.7 """ from sympy.integrals.integrals import integrate from sympy.solvers.ode import dsolve xi, eta = symbols("xi eta") f = func.func x = func.args[0] y = func.args[1] b = match[match['b']] c = match[match['c']] d = match[match['d']] e = -match[match['e']] if not d: # To deal with cases like b*ux = e or c*uy = e if not (b and c): if c: try: tsol = integrate(e/c, y) except NotImplementedError: raise NotImplementedError("Unable to find a solution" " due to inability of integrate") else: return Eq(f(x,y), solvefun(x) + tsol) if b: try: tsol = integrate(e/b, x) except NotImplementedError: raise NotImplementedError("Unable to find a solution" " due to inability of integrate") else: return Eq(f(x,y), solvefun(y) + tsol) if not c: # To deal with cases when c is 0, a simpler method is used. # The PDE reduces to b*(u.diff(x)) + d*u = e, which is a linear ODE in x plode = f(x).diff(x)*b + d*f(x) - e sol = dsolve(plode, f(x)) syms = sol.free_symbols - plode.free_symbols - set([x, y]) rhs = _simplify_variable_coeff(sol.rhs, syms, solvefun, y) return Eq(f(x, y), rhs) if not b: # To deal with cases when b is 0, a simpler method is used. # The PDE reduces to c*(u.diff(y)) + d*u = e, which is a linear ODE in y plode = f(y).diff(y)*c + d*f(y) - e sol = dsolve(plode, f(y)) syms = sol.free_symbols - plode.free_symbols - set([x, y]) rhs = _simplify_variable_coeff(sol.rhs, syms, solvefun, x) return Eq(f(x, y), rhs) dummy = Function('d') h = (c/b).subs(y, dummy(x)) sol = dsolve(dummy(x).diff(x) - h, dummy(x)) if isinstance(sol, list): sol = sol[0] solsym = sol.free_symbols - h.free_symbols - set([x, y]) if len(solsym) == 1: solsym = solsym.pop() etat = (solve(sol, solsym)[0]).subs(dummy(x), y) ysub = solve(eta - etat, y)[0] deq = (b*(f(x).diff(x)) + d*f(x) - e).subs(y, ysub) final = (dsolve(deq, f(x), hint='1st_linear')).rhs if isinstance(final, list): final = final[0] finsyms = final.free_symbols - deq.free_symbols - set([x, y]) rhs = _simplify_variable_coeff(final, finsyms, solvefun, etat) return Eq(f(x, y), rhs) else: raise NotImplementedError("Cannot solve the partial differential equation due" " to inability of constantsimp")
def test_issue_10047(): # this must remain an inequality, not True, since if x # is not real the inequality is invalid assert solve(sin(x) < 2) == (x <= oo)
def checkpdesol(pde, sol, func=None, solve_for_func=True): """ Checks if the given solution satisfies the partial differential equation. pde is the partial differential equation which can be given in the form of an equation or an expression. sol is the solution for which the pde is to be checked. This can also be given in an equation or an expression form. If the function is not provided, the helper function _preprocess from deutils is used to identify the function. If a sequence of solutions is passed, the same sort of container will be used to return the result for each solution. The following methods are currently being implemented to check if the solution satisfies the PDE: 1. Directly substitute the solution in the PDE and check. If the solution hasn't been solved for f, then it will solve for f provided solve_for_func hasn't been set to False. If the solution satisfies the PDE, then a tuple (True, 0) is returned. Otherwise a tuple (False, expr) where expr is the value obtained after substituting the solution in the PDE. However if a known solution returns False, it may be due to the inability of doit() to simplify it to zero. Examples ======== >>> from sympy import Function, symbols, diff >>> from sympy.solvers.pde import checkpdesol, pdsolve >>> x, y = symbols('x y') >>> f = Function('f') >>> eq = 2*f(x,y) + 3*f(x,y).diff(x) + 4*f(x,y).diff(y) >>> sol = pdsolve(eq) >>> assert checkpdesol(eq, sol)[0] >>> eq = x*f(x,y) + f(x,y).diff(x) >>> checkpdesol(eq, sol) (False, (x*F(4*x - 3*y) - 6*F(4*x - 3*y)/25 + 4*Subs(Derivative(F(_xi_1), _xi_1), (_xi_1,), (4*x - 3*y,)))*exp(-6*x/25 - 8*y/25)) """ # Converting the pde into an equation if not isinstance(pde, Equality): pde = Eq(pde, 0) # If no function is given, try finding the function present. if func is None: try: _, func = _preprocess(pde.lhs) except ValueError: funcs = [s.atoms(AppliedUndef) for s in ( sol if is_sequence(sol, set) else [sol])] funcs = reduce(set.union, funcs, set()) if len(funcs) != 1: raise ValueError( 'must pass func arg to checkpdesol for this case.') func = funcs.pop() # If the given solution is in the form of a list or a set # then return a list or set of tuples. if is_sequence(sol, set): return type(sol)(map(lambda i: checkpdesol(pde, i, solve_for_func=solve_for_func), sol)) # Convert solution into an equation if not isinstance(sol, Equality): sol = Eq(func, sol) # Try solving for the function if solve_for_func and not (sol.lhs == func and not sol.rhs.has(func)) and not \ (sol.rhs == func and not sol.lhs.has(func)): try: solved = solve(sol, func) if not solved: raise NotImplementedError except NotImplementedError: pass else: if len(solved) == 1: result = checkpdesol(pde, Eq(func, solved[0]), order=order, solve_for_func=False) else: result = checkpdesol(pde, [Eq(func, t) for t in solved], order=order, solve_for_func=False) # The first method includes direct substitution of the solution in # the PDE and simplifying. pde = pde.lhs - pde.rhs if sol.lhs == func: s = pde.subs(func, sol.rhs).doit() elif sol.rhs == func: s = pde.subs(func, sol.lhs).doit() if s: ss = simplify(s) if ss: return False, ss else: return True, 0 else: return True, 0
def test_sub_qdot(): # This test solves exercises 8.12, 8.17 from Kane 1985 and defines # some velocities in terms of q, qdot. ## --- Declare symbols --- q1, q2, q3 = dynamicsymbols('q1:4') q1d, q2d, q3d = dynamicsymbols('q1:4', level=1) u1, u2, u3 = dynamicsymbols('u1:4') u_prime, R, M, g, e, f, theta = symbols('u\' R, M, g, e, f, theta') a, b, mA, mB, IA, J, K, t = symbols('a b mA mB IA J K t') IA22, IA23, IA33 = symbols('IA22 IA23 IA33') Q1, Q2, Q3 = symbols('Q1 Q2 Q3') # --- Reference Frames --- F = ReferenceFrame('F') P = F.orientnew('P', 'axis', [-theta, F.y]) A = P.orientnew('A', 'axis', [q1, P.x]) A.set_ang_vel(F, u1 * A.x + u3 * A.z) # define frames for wheels B = A.orientnew('B', 'axis', [q2, A.z]) C = A.orientnew('C', 'axis', [q3, A.z]) ## --- define points D, S*, Q on frame A and their velocities --- pD = Point('D') pD.set_vel(A, 0) # u3 will not change v_D_F since wheels are still assumed to roll w/o slip pD.set_vel(F, u2 * A.y) pS_star = pD.locatenew('S*', e * A.y) pQ = pD.locatenew('Q', f * A.y - R * A.x) # masscenters of bodies A, B, C pA_star = pD.locatenew('A*', a * A.y) pB_star = pD.locatenew('B*', b * A.z) pC_star = pD.locatenew('C*', -b * A.z) for p in [pS_star, pQ, pA_star, pB_star, pC_star]: p.v2pt_theory(pD, F, A) # points of B, C touching the plane P pB_hat = pB_star.locatenew('B^', -R * A.x) pC_hat = pC_star.locatenew('C^', -R * A.x) pB_hat.v2pt_theory(pB_star, F, B) pC_hat.v2pt_theory(pC_star, F, C) # --- relate qdot, u --- # the velocities of B^, C^ are zero since B, C are assumed to roll w/o slip kde = [dot(p.vel(F), A.y) for p in [pB_hat, pC_hat]] kde += [u1 - q1d] kde_map = solve(kde, [q1d, q2d, q3d]) for k, v in list(kde_map.items()): kde_map[k.diff(t)] = v.diff(t) # inertias of bodies A, B, C # IA22, IA23, IA33 are not specified in the problem statement, but are # necessary to define an inertia object. Although the values of # IA22, IA23, IA33 are not known in terms of the variables given in the # problem statement, they do not appear in the general inertia terms. inertia_A = inertia(A, IA, IA22, IA33, 0, IA23, 0) inertia_B = inertia(B, K, K, J) inertia_C = inertia(C, K, K, J) # define the rigid bodies A, B, C rbA = RigidBody('rbA', pA_star, A, mA, (inertia_A, pA_star)) rbB = RigidBody('rbB', pB_star, B, mB, (inertia_B, pB_star)) rbC = RigidBody('rbC', pC_star, C, mB, (inertia_C, pC_star)) ## --- use kanes method --- km = KanesMethod(F, [q1, q2, q3], [u1, u2], kd_eqs=kde, u_auxiliary=[u3]) forces = [(pS_star, -M * g * F.x), (pQ, Q1 * A.x + Q2 * A.y + Q3 * A.z)] bodies = [rbA, rbB, rbC] # Q2 = -u_prime * u2 * Q1 / sqrt(u2**2 + f**2 * u1**2) # -u_prime * R * u2 / sqrt(u2**2 + f**2 * u1**2) = R / Q1 * Q2 fr_expected = Matrix([ f * Q3 + M * g * e * sin(theta) * cos(q1), Q2 + M * g * sin(theta) * sin(q1), e * M * g * cos(theta) - Q1 * f - Q2 * R ]) #Q1 * (f - u_prime * R * u2 / sqrt(u2**2 + f**2 * u1**2)))]) fr_star_expected = Matrix([ -(IA + 2 * J * b**2 / R**2 + 2 * K + mA * a**2 + 2 * mB * b**2) * u1.diff(t) - mA * a * u1 * u2, -(mA + 2 * mB + 2 * J / R**2) * u2.diff(t) + mA * a * u1**2, 0 ]) fr, fr_star = km.kanes_equations(bodies, forces) assert (fr.expand() == fr_expected.expand()) assert ((fr_star_expected - trigsimp(fr_star)).expand() == zeros(3, 1))
def _solve_undetermined_coefficients(eq, func, order, match, trialset): r""" Helper function for the method of undetermined coefficients. See the :py:meth:`~sympy.solvers.ode.single.NthLinearConstantCoeffUndeterminedCoefficients` docstring for more information on this method. The parameter ``trialset`` is the set of trial functions as returned by ``_undetermined_coefficients_match()['trialset']``. The parameter ``match`` should be a dictionary that has the following keys: ``list`` A list of solutions to the homogeneous equation. ``sol`` The general solution. """ r = match coeffs = numbered_symbols('a', cls=Dummy) coefflist = [] gensols = r['list'] gsol = r['sol'] f = func.func x = func.args[0] if len(gensols) != order: raise NotImplementedError( "Cannot find " + str(order) + " solutions to the homogeneous equation necessary to apply" + " undetermined coefficients to " + str(eq) + " (number of terms != order)") trialfunc = 0 for i in trialset: c = next(coeffs) coefflist.append(c) trialfunc += c * i eqs = sub_func_doit(eq, f(x), trialfunc) coeffsdict = dict(list(zip(trialset, [0] * (len(trialset) + 1)))) eqs = _mexpand(eqs) for i in Add.make_args(eqs): s = separatevars(i, dict=True, symbols=[x]) if coeffsdict.get(s[x]): coeffsdict[s[x]] += s['coeff'] else: coeffsdict[s[x]] = s['coeff'] coeffvals = solve(list(coeffsdict.values()), coefflist) if not coeffvals: raise NotImplementedError("Could not solve `%s` using the " "method of undetermined coefficients " "(unable to solve for coefficients)." % eq) psol = trialfunc.subs(coeffvals) return Eq(f(x), gsol.rhs + psol)
def transform(self, x, u): r""" Performs a change of variables from `x` to `u` using the relationship given by `x` and `u` which will define the transformations `f` and `F` (which are inverses of each other) as follows: 1) If `x` is a Symbol (which is a variable of integration) then `u` will be interpreted as some function, f(u), with inverse F(u). This, in effect, just makes the substitution of x with f(x). 2) If `u` is a Symbol then `x` will be interpreted as some function, F(x), with inverse f(u). This is commonly referred to as u-substitution. Once f and F have been identified, the transformation is made as follows: .. math:: \int_a^b x \mathrm{d}x \rightarrow \int_{F(a)}^{F(b)} f(x) \frac{\mathrm{d}}{\mathrm{d}x} where `F(x)` is the inverse of `f(x)` and the limits and integrand have been corrected so as to retain the same value after integration. Notes ===== The mappings, F(x) or f(u), must lead to a unique integral. Linear or rational linear expression, `2*x`, `1/x` and `sqrt(x)`, will always work; quadratic expressions like `x**2 - 1` are acceptable as long as the resulting integrand does not depend on the sign of the solutions (see examples). The integral will be returned unchanged if `x` is not a variable of integration. `x` must be (or contain) only one of of the integration variables. If `u` has more than one free symbol then it should be sent as a tuple (`u`, `uvar`) where `uvar` identifies which variable is replacing the integration variable. XXX can it contain another integration variable? Examples ======== >>> from sympy.abc import a, b, c, d, x, u, y >>> from sympy import Integral, S, cos, sqrt >>> i = Integral(x*cos(x**2 - 1), (x, 0, 1)) transform can change the variable of integration >>> i.transform(x, u) Integral(u*cos(u**2 - 1), (u, 0, 1)) transform can perform u-substitution as long as a unique integrand is obtained: >>> i.transform(x**2 - 1, u) Integral(cos(u)/2, (u, -1, 0)) This attempt fails because x = +/-sqrt(u + 1) and the sign does not cancel out of the integrand: >>> Integral(cos(x**2 - 1), (x, 0, 1)).transform(x**2 - 1, u) Traceback (most recent call last): ... ValueError: The mapping between F(x) and f(u) did not give a unique integrand. transform can do a substitution. Here, the previous result is transformed back into the original expression using "u-substitution": >>> ui = _ >>> _.transform(sqrt(u + 1), x) == i True We can accomplish the same with a regular substitution: >>> ui.transform(u, x**2 - 1) == i True If the `x` does not contain a symbol of integration then the integral will be returned unchanged. Integral `i` does not have an integration variable `a` so no change is made: >>> i.transform(a, x) == i True When `u` has more than one free symbol the symbol that is replacing `x` must be identified by passing `u` as a tuple: >>> Integral(x, (x, 0, 1)).transform(x, (u + a, u)) Integral(a + u, (u, -a, -a + 1)) >>> Integral(x, (x, 0, 1)).transform(x, (u + a, a)) Integral(a + u, (a, -u, -u + 1)) See Also ======== variables : Lists the integration variables as_dummy : Replace integration variables with dummy ones """ d = Dummy('d') xfree = x.free_symbols.intersection(self.variables) if len(xfree) > 1: raise ValueError( 'F(x) can only contain one of: %s' % self.variables) xvar = xfree.pop() if xfree else d if xvar not in self.variables: return self u = sympify(u) if isinstance(u, Expr): ufree = u.free_symbols if len(ufree) != 1: raise ValueError(filldedent(''' When f(u) has more than one free symbol, the one replacing x must be identified: pass f(u) as (f(u), u)''')) uvar = ufree.pop() else: u, uvar = u if uvar not in u.free_symbols: raise ValueError(filldedent(''' Expecting a tuple (expr, symbol) where symbol identified a free symbol in expr, but symbol is not in expr's free symbols.''')) if not isinstance(uvar, Symbol): raise ValueError(filldedent(''' Expecting a tuple (expr, symbol) but didn't get a symbol; got %s''' % uvar)) if x.is_Symbol and u.is_Symbol: return self.xreplace({x: u}) if not x.is_Symbol and not u.is_Symbol: raise ValueError('either x or u must be a symbol') if uvar == xvar: return self.transform(x, (u.subs(uvar, d), d)).xreplace({d: uvar}) if uvar in self.limits: raise ValueError(filldedent(''' u must contain the same variable as in x or a variable that is not already an integration variable''')) if not x.is_Symbol: F = [x.subs(xvar, d)] soln = solve(u - x, xvar, check=False) if not soln: raise ValueError('no solution for solve(F(x) - f(u), x)') f = [fi.subs(uvar, d) for fi in soln] else: f = [u.subs(uvar, d)] pdiff, reps = posify(u - x) puvar = uvar.subs([(v, k) for k, v in reps.items()]) soln = [s.subs(reps) for s in solve(pdiff, puvar)] if not soln: raise ValueError('no solution for solve(F(x) - f(u), u)') F = [fi.subs(xvar, d) for fi in soln] newfuncs = set([(self.function.subs(xvar, fi)*fi.diff(d) ).subs(d, uvar) for fi in f]) if len(newfuncs) > 1: raise ValueError(filldedent(''' The mapping between F(x) and f(u) did not give a unique integrand.''')) newfunc = newfuncs.pop() def _calc_limit_1(F, a, b): """ replace d with a, using subs if possible, otherwise limit where sign of b is considered """ wok = F.subs(d, a) if wok is S.NaN or wok.is_finite is False and a.is_finite: return limit(sign(b)*F, d, a) return wok def _calc_limit(a, b): """ replace d with a, using subs if possible, otherwise limit where sign of b is considered """ avals = list(set([_calc_limit_1(Fi, a, b) for Fi in F])) if len(avals) > 1: raise ValueError(filldedent(''' The mapping between F(x) and f(u) did not give a unique limit.''')) return avals[0] newlimits = [] for xab in self.limits: sym = xab[0] if sym == xvar: if len(xab) == 3: a, b = xab[1:] a, b = _calc_limit(a, b), _calc_limit(b, a) if a - b > 0: a, b = b, a newfunc = -newfunc newlimits.append((uvar, a, b)) elif len(xab) == 2: a = _calc_limit(xab[1], 1) newlimits.append((uvar, a)) else: newlimits.append(uvar) else: newlimits.append(xab) return self.func(newfunc, *newlimits)
def crack_rsa(n, phi_n): x = Symbol('x') f = x ** 2 - (n + 1 - phi_n) * x + n return solve(f)
def pde_1st_linear_constant_coeff(eq, func, order, match, solvefun): r""" Solves a first order linear partial differential equation with constant coefficients. The general form of this partial differential equation is .. math:: a \frac{\partial f(x,y)}{\partial x} + b \frac{\partial f(x,y)}{\partial y} + c f(x,y) = G(x,y) where `a`, `b` and `c` are constants and `G(x, y)` can be an arbitrary function in `x` and `y`. The general solution of the PDE is: .. math:: f(x, y) = \left. \left[F(\eta) + \frac{1}{a^2 + b^2} \int\limits^{a x + b y} G\left(\frac{a \xi + b \eta}{a^2 + b^2}, \frac{- a \eta + b \xi}{a^2 + b^2} \right) e^{\frac{c \xi}{a^2 + b^2}}\, d\xi\right] e^{- \frac{c \xi}{a^2 + b^2}} \right|_{\substack{\eta=- a y + b x\\ \xi=a x + b y }}\, , where `F(\eta)` is an arbitrary single-valued function. The solution can be found in SymPy with ``pdsolve``:: >>> from sympy.solvers import pdsolve >>> from sympy.abc import x, y, a, b, c >>> from sympy import Function, pprint >>> f = Function('f') >>> G = Function('G') >>> u = f(x,y) >>> ux = u.diff(x) >>> uy = u.diff(y) >>> genform = a*ux + b*uy + c*u - G(x,y) >>> pprint(genform) d d a*--(f(x, y)) + b*--(f(x, y)) + c*f(x, y) - G(x, y) dx dy >>> pprint(pdsolve(genform, hint='1st_linear_constant_coeff_Integral')) // a*x + b*y \ || / | || | | || | c*xi | || | ------- | || | 2 2 | || | /a*xi + b*eta -a*eta + b*xi\ a + b | || | G|------------, -------------|*e d(xi)| || | | 2 2 2 2 | | || | \ a + b a + b / | || | | || / | || | f(x, y) = ||F(eta) + -------------------------------------------------------|* || 2 2 | \\ a + b / <BLANKLINE> \| || || || || || || || || -c*xi || -------|| 2 2|| a + b || e || || /|eta=-a*y + b*x, xi=a*x + b*y Examples ======== >>> from sympy.solvers.pde import pdsolve >>> from sympy import Function, diff, pprint, exp >>> from sympy.abc import x,y >>> f = Function('f') >>> eq = -2*f(x,y).diff(x) + 4*f(x,y).diff(y) + 5*f(x,y) - exp(x + 3*y) >>> pdsolve(eq) Eq(f(x, y), (F(4*x + 2*y) + exp(x/2 + 4*y)/15)*exp(x/2 - y)) References ========== - Viktor Grigoryan, "Partial Differential Equations" Math 124A - Fall 2010, pp.7 """ # TODO : For now homogeneous first order linear PDE's having # two variables are implemented. Once there is support for # solving systems of ODE's, this can be extended to n variables. xi, eta = symbols("xi eta") f = func.func x = func.args[0] y = func.args[1] b = match[match['b']] c = match[match['c']] d = match[match['d']] e = -match[match['e']] expterm = exp(-S(d)/(b**2 + c**2)*xi) functerm = solvefun(eta) solvedict = solve((b*x + c*y - xi, c*x - b*y - eta), x, y) # Integral should remain as it is in terms of xi, # doit() should be done in _handle_Integral. genterm = (1/S(b**2 + c**2))*Integral( (1/expterm*e).subs(solvedict), (xi, b*x + c*y)) return Eq(f(x,y), Subs(expterm*(functerm + genterm), (eta, xi), (c*x - b*y, b*x + c*y)))
def _contains(self, other): from sympy.matrices import Matrix from sympy.solvers.solveset import solveset, linsolve from sympy.solvers.solvers import solve from sympy.utilities.iterables import is_sequence, cartes L = self.lamda if is_sequence(other) != is_sequence(L.expr): return False elif is_sequence(other) and len(L.expr) != len(other): return False if self._is_multivariate(): if not is_sequence(L.expr): # exprs -> (numer, denom) and check again # XXX this is a bad idea -- make the user # remap self to desired form return other.as_numer_denom() in self.func( Lambda(L.signature, L.expr.as_numer_denom()), self.base_set) eqs = [expr - val for val, expr in zip(other, L.expr)] variables = L.variables free = set(variables) if all(i.is_number for i in list(Matrix(eqs).jacobian(variables))): solns = list( linsolve([e - val for e, val in zip(L.expr, other)], variables)) else: try: syms = [e.free_symbols & free for e in eqs] solns = {} for i, (e, s, v) in enumerate(zip(eqs, syms, other)): if not s: if e != v: return S.false solns[vars[i]] = [v] continue elif len(s) == 1: sy = s.pop() sol = solveset(e, sy) if sol is S.EmptySet: return S.false elif isinstance(sol, FiniteSet): solns[sy] = list(sol) else: raise NotImplementedError else: # if there is more than 1 symbol from # variables in expr than this is a # coupled system raise NotImplementedError solns = cartes(*[solns[s] for s in variables]) except NotImplementedError: solns = solve([e - val for e, val in zip(L.expr, other)], variables, set=True) if solns: _v, solns = solns # watch for infinite solutions like solving # for x, y and getting (x, 0), (0, y), (0, 0) solns = [ i for i in solns if not any(s in i for s in variables) ] if not solns: return False else: # not sure if [] means no solution or # couldn't find one return else: x = L.variables[0] if isinstance(L.expr, Expr): # scalar -> scalar mapping solnsSet = solveset(L.expr - other, x) if solnsSet.is_FiniteSet: solns = list(solnsSet) else: msgset = solnsSet else: # scalar -> vector # note: it is not necessary for components of other # to be in the corresponding base set unless the # computed component is always in the corresponding # domain. e.g. 1/2 is in imageset(x, x/2, Integers) # while it cannot be in imageset(x, x + 2, Integers). # So when the base set is comprised of integers or reals # perhaps a pre-check could be done to see if the computed # values are still in the set. dom = self.base_set for e, o in zip(L.expr, other): dom = dom.intersection(solveset(e - o, x, domain=dom)) if dom.is_empty: # there is no solution in common return False return fuzzy_not(dom.is_empty) for soln in solns: try: if soln in self.base_set: return True except TypeError: return return S.false
def test_issue_10268(): assert solve(log(x) < 1000) == And(-oo < x, x < exp(1000))
def infer(q,a,cutoff,VERBOSE): training = [] wps = open(q).readlines() answs = open(a).readlines() problematic = open('somethingWrongProblems','a') ar = [0,0] sr = [0,0] mr = [0,0] dr = [0,0] right = 0 guesses = 0 ad = [] wrong = [] multiops = 0 multiopsright = 0 replacements = {' two ':' 2 '," three ":' 3 ',' four ':' 4 ',' five ':' 5 ',' six ':' 6 ',' seven ':' 7 ',' eight ':' 8 ',' nine ':' 9 ',' ten ':' 10 ',' eleven ':' 11 ', ' twice ':' 2 '} for k in range(len(wps)): if VERBOSE: for i in range(len(wps)): print(i,wps[i]) k = int(input()) print(k) problem = wps[k].lower() #First preprocessing, tokenize slightly problem = problem.strip().split(" ") for i,x in enumerate(problem): if len(x)==0:continue if x[-1] in [',','.','?']: problem[i] = x[:-1]+" "+x[-1] problem = ' '.join(problem) problem = " " + problem + " " print(problem) for r in replacements: problem = problem.replace(r,replacements[r]) story = nlp.parse(problem) sets = makesets.makesets(story['sentences']) #REMOVE DUPS THIS IS BAD: i = 0 while i < len(sets): x = sets[i] dups = [y for y in sets if y[1].num == x[1].num] if len(dups)>1: for x in dups[1:]: sets.remove(x) i+=1 print("Sets detected: ") for x in sets: x[1].details() numlist = [(cleannum(v.num),v) for k,v in sets] numlist = [x for x in numlist if x[0]!=''] if VERBOSE: for z,v in numlist: v.details() input() allnumbs = {str(k):v for k,v in numlist} objs = {k:(0,v) for k,v in numlist} constraints = [] for i in range(len(numlist)): if numlist[i][0][-1] == "*": if i==0:continue constraints.append(numlist[i-1][0]+" * "+numlist[i][0][:-1]) numlist[i] = (''.join([x for x in numlist[i][0] if x not in ['*','/']]),numlist[i][1]) numlist[i][1].num = numlist[i][0] elif numlist[i][0][0] == "*": if i==0:continue numlist[i] = (''.join([x for x in numlist[i][0] if x not in ['*','/']]),numlist[i][1]) tmp = numlist[i-1] numlist[i-1]=numlist[i] numlist[i]=tmp constraints.append(numlist[i-1][0]+" * "+numlist[i][0][1:]) elif numlist[i][0][-1] == "/": if i==0:continue constraints.append(" / "+numlist[i][0][:-1]) numlist[i] = (''.join([x for x in numlist[i][0] if x not in ['*','/']]),numlist[i][1]) objs = {k:(0,v) for k,v in numlist} if len(objs)<2: wrong.append(k) continue if 'x' not in objs: wrong.append(k) continue integerproblem = all([float(x[0]).is_integer() for x in numlist if x[0]!='x']) multi = False if len(objs)>3: multiops+=1 multi = True if VERBOSE: print(objs,numlist,[v.num for k,v in sets]) #print(allnumbs) state = [] #print(numlist) #for e in allnumbs.items(): #print(numlist) numidxlist = [x[0] for x in numlist] ST = StringTemplate(numidxlist, inf=True) scores = [] equalsmatch = [] contmatch = [] for j,eq in enumerate(ST.equations): #print(j,eq.toString()) good = False ''' if len(constraints)==0: good = True else: for constraint in constraints: if constraint in eq.toString(): good = True if not good: scores.append(-0.2) continue ''' thisscore = [] #print(eq.toString()) #determine score for this eq l,r = [x.strip().split(' ') for x in eq.toString().split('=')] #print(l,r) if len(r)>1 and len(l)>1: scores.append(-0.2); equalsmatch.append('x'); contmatch.append('x') continue if len(r)>1: compound = r target = l[0] else: #print(constraints) compound = l target = r[0] target = (target,objs[target]) #find innermost parens? while len(compound)>1: if "(" in compound: rpidx = (len(compound) - 1) - compound[::-1].index('(') lpidx = rpidx+compound[rpidx:].index(")") subeq = compound[rpidx+1:lpidx] substr = "("+''.join(subeq)+")" compound = compound[:rpidx]+[substr]+compound[lpidx+1:] else: subeq = compound[0:3] substr = "("+''.join(subeq)+")" compound = [substr]+compound[3:] if substr in objs: pute = objs[substr] #print(pute[0],pute[1].num) else: p,op,e = subeq #print(p,op,e) p = objs[p][1] e = objs[e][1] op = op.strip() pute = compute(p,op,e,target,problem) #print("OPERATION SELECTED: ",op) #p.details() #e.details() #print(substr,pute[1].num) objs[substr]=pute if pute == -1: exit() score,c = pute thisscore.append(score) if target[1][1].entity == c.entity: #thisscore.append(-0.2) equalsmatch.append(1) else: equalsmatch.append(0) if target[1][1].container != c.container: contmatch.append(1) else: contmatch.append(0) scores.append(sum(thisscore)) #print(compound) m = np.argmax(scores) #print(scores[m],ST.equations[m].toString()) srt = sorted([(x,i) for i,x in enumerate(scores)],reverse=True) print('\n Top scoring 3 equations: ') for x,i in srt[:3]: print(x,ST.equations[i].toString()) ''' try: if target.ent=='dozen': guess = solve('('+numlist[0].num+'/12)'+"-"+target.num,'x')[0] print(numlist[0].num+"/12="+target.num) else: guess = solve(numlist[0].num+"-"+target.num,'x')[0] print(numlist[0].num+"="+target.num) ''' eqidxs = [y[0] for y in sorted(enumerate(scores),key=lambda x:x[1],reverse=True)] seen = [] tright = 0 for i in eqidxs[:cutoff]: eq = ST.equations[i].toString() ogeq = ST.equations[i].toString() if equalsmatch[i]=='x': continue #eq = eq.replace("=",'-') splitEquation = eq.split('=') eq = splitEquation[0] + '- (' + splitEquation[1] + ')' #print(scores[i], eq) try: guess = solve(eq,'x')[0] except: continue if guess not in seen: seen.append(guess) else: continue # in a "check for complex number" try statement :/ try: if guess < 0: pass except: continue answ = float(answs[k]) vec = [] #build training vector if guess == answ: vec.append(1) else: vec.append(0) vec.append(int(float(guess)<0)) vec.append(int(integerproblem)) vec.append(int(ogeq.index("=")==1)) vec.append(int(eq.split(" ")[-1]==x)) vec.append(equalsmatch[i]) vec.append(contmatch[i]) vec.append(int(guess.is_integer)) #lexical items vec.append(int("at first " in problem)) vec.append(int("start " in problem)) vec.append(int(" now " in problem)) vec.append(int(" total " in problem)) vec.append(int(" equally " in problem)) vec.append(int(" equal " in problem)) training.append(vec) f = open("data/single.global.data",'w') for v in training: f.write(str(v[0])+" ") for i,j in enumerate(v[1:]): f.write(str(i+1)+":"+str(j)+" ") f.write("\n")
def test_issue_10047(): assert solve(sin(x) < 2) == And(-oo < x, x < oo)
def solve_univariate_inequality(expr, gen, relational=True): """Solves a real univariate inequality. Examples ======== >>> from sympy.solvers.inequalities import solve_univariate_inequality >>> from sympy.core.symbol import Symbol >>> x = Symbol('x', real=True) >>> solve_univariate_inequality(x**2 >= 4, x) Or(And(-oo < x, x <= -2), And(2 <= x, x < oo)) >>> solve_univariate_inequality(x**2 >= 4, x, relational=False) (-oo, -2] U [2, oo) """ from sympy.solvers.solvers import solve, denoms e = expr.lhs - expr.rhs parts = n, d = e.as_numer_denom() if all(i.is_polynomial(gen) for i in parts): solns = solve(n, gen, check=False) singularities = solve(d, gen, check=False) else: solns = solve(e, gen, check=False) singularities = [] for d in denoms(e): singularities.extend(solve(d, gen)) include_x = expr.func(0, 0) def valid(x): v = e.subs(gen, x) r = expr.func(v, 0) if r in (S.true, S.false): return r if v.is_real is False: return S.false else: v = v.n(2) if v.is_comparable: return expr.func(v, 0) return S.false start = S.NegativeInfinity sol_sets = [S.EmptySet] try: reals = _nsort(set(solns + singularities), separated=True)[0] except NotImplementedError: raise NotImplementedError('sorting of these roots is not supported') for x in reals: end = x if valid((start + end)/2 if start != S.NegativeInfinity else end - 1): sol_sets.append(Interval(start, end, True, True)) if x in singularities: singularities.remove(x) elif include_x: sol_sets.append(FiniteSet(x)) start = end end = S.Infinity if valid(start + 1): sol_sets.append(Interval(start, end, True, True)) rv = Union(*sol_sets) return rv if not relational else rv.as_relational(gen)
def ratint_ratpart(f, g, x): """ Horowitz-Ostrogradsky algorithm. Explanation =========== Given a field K and polynomials f and g in K[x], such that f and g are coprime and deg(f) < deg(g), returns fractions A and B in K(x), such that f/g = A' + B and B has square-free denominator. Examples ======== >>> from sympy.integrals.rationaltools import ratint_ratpart >>> from sympy.abc import x, y >>> from sympy import Poly >>> ratint_ratpart(Poly(1, x, domain='ZZ'), ... Poly(x + 1, x, domain='ZZ'), x) (0, 1/(x + 1)) >>> ratint_ratpart(Poly(1, x, domain='EX'), ... Poly(x**2 + y**2, x, domain='EX'), x) (0, 1/(x**2 + y**2)) >>> ratint_ratpart(Poly(36, x, domain='ZZ'), ... Poly(x**5 - 2*x**4 - 2*x**3 + 4*x**2 + x - 2, x, domain='ZZ'), x) ((12*x + 6)/(x**2 - 1), 12/(x**2 - x - 2)) See Also ======== ratint, ratint_logpart """ from sympy.solvers.solvers import solve f = Poly(f, x) g = Poly(g, x) u, v, _ = g.cofactors(g.diff()) n = u.degree() m = v.degree() A_coeffs = [Dummy('a' + str(n - i)) for i in range(0, n)] B_coeffs = [Dummy('b' + str(m - i)) for i in range(0, m)] C_coeffs = A_coeffs + B_coeffs A = Poly(A_coeffs, x, domain=ZZ[C_coeffs]) B = Poly(B_coeffs, x, domain=ZZ[C_coeffs]) H = f - A.diff() * v + A * (u.diff() * v).quo(u) - B * u result = solve(H.coeffs(), C_coeffs) A = A.as_expr().subs(result) B = B.as_expr().subs(result) rat_part = cancel(A / u.as_expr(), x) log_part = cancel(B / v.as_expr(), x) return rat_part, log_part
def _lambert(eq, x, domain=S.Complexes): """ Given an expression assumed to be in the form ``F(X, a..f) = a*log(b*X + c) + d*X + f = 0`` where X = g(x) and x = g^-1(X), return the Lambert solution, ``x = g^-1(-c/b + (a/d)*W(d/(a*b)*exp(c*d/a/b)*exp(-f/a)))``. """ eq = _mexpand(expand_log(eq)) mainlog = _mostfunc(eq, log, x) if not mainlog: return [] # violated assumptions other = eq.subs(mainlog, 0) if isinstance(-other, log): eq = (eq - other).subs(mainlog, mainlog.args[0]) mainlog = mainlog.args[0] if not isinstance(mainlog, log): return [] # violated assumptions other = -(-other).args[0] eq += other if not x in other.free_symbols: return [] # violated assumptions d, f, X2 = _linab(other, x) logterm = collect(eq - other, mainlog) a = logterm.as_coefficient(mainlog) if a is None or x in a.free_symbols: return [] # violated assumptions logarg = mainlog.args[0] b, c, X1 = _linab(logarg, x) if X1 != X2: return [] # violated assumptions # invert the generator X1 so we have x(u) u = Dummy('rhs') xusolns = solve(X1 - u, x, domain=domain) # There are infinitely many branches for LambertW # but only branches for k = -1 and 0 might be real. The k = 0 # branch is real and the k = -1 branch is real if the LambertW argumen # in in range [-1/e, 0]. Since `solve` does not return infinite # solutions we will only include the -1 branch if it tests as real. # Otherwise, inclusion of any LambertW in the solution indicates to # the user that there are imaginary solutions corresponding to # different k values. lambert_real_branches = [-1, 0] sol = [] # solution of the given Lambert equation is like # sol = -c/b + (a/d)*LambertW(arg, k), # where arg = d/(a*b)*exp((c*d-b*f)/a/b) and k in lambert_real_branches. # Instead of considering the single arg, `d/(a*b)*exp((c*d-b*f)/a/b)`, # the individual `p` roots obtained when writing `exp((c*d-b*f)/a/b)` # as `exp(A/p) = exp(A)**(1/p)`, where `p` is an Integer, are used. # calculating args for LambertW num, den = ((c * d - b * f) / a / b).as_numer_denom() p, den = den.as_coeff_Mul() e = exp(num / den) t = Dummy('t') real = None if p == 1: t = e args = [d / (a * b) * t] elif domain.is_real: ind_ls = [d / (a * b) * t for t in roots(t**p - e, t).keys()] args = [] j = -1 for i in ind_ls: j += 1 if not isinstance(i, int): if not i.has(I): args.append(ind_ls[j]) real = True elif isinstance(i, int): args.append(ind_ls[j]) else: args = [d / (a * b) * t for t in roots(t**p - e, t).keys()] if len(args) == 0: return S.EmptySet # calculating solutions from args for arg in args: if not len(list(eq.atoms(Symbol, Dummy))) > 1: if not domain.is_subset(S.Reals) and ( re(arg) < -1 / E or arg.has(I)) and (not LambertW(arg).is_real) and (not real): integer = Symbol('integer', integer=True) rhs = -c / b + (a / d) * LambertW(arg, integer) for xu in xusolns: sol.append(xu.subs(u, rhs)) else: if -1 / E <= re(arg) < 0 and LambertW(arg).is_real: for k in lambert_real_branches: w = LambertW(arg, k) rhs = -c / b + (a / d) * w for xu in xusolns: sol.append(xu.subs(u, rhs)) elif re(arg) >= 0 and LambertW(arg).is_real: w = LambertW(arg) rhs = -c / b + (a / d) * w for xu in xusolns: sol.append(xu.subs(u, rhs)) elif re(arg) < -1 / E: return S.EmptySet elif (arg.has(Symbol)) and not arg.has(Dummy): if (list(arg.atoms(Symbol))[0]).is_negative and (list( arg.atoms(Symbol))[0]).is_real and domain.is_subset( S.Reals): for k in lambert_real_branches: w = LambertW(arg, k) rhs = -c / b + (a / d) * w if rhs.has(I) or w.has(I): continue for xu in xusolns: sol.append(xu.subs(u, rhs)) if (list(arg.atoms(Symbol))[0]).is_positive and (list( arg.atoms(Symbol))[0]).is_real and domain.is_subset( S.Reals): w = LambertW(arg) rhs = -c / b + (a / d) * w if rhs.has(I) or w.has(I): continue for xu in xusolns: sol.append(xu.subs(u, rhs)) if (list(arg.atoms(Symbol))[0]).is_negative and (list( arg.atoms(Symbol))[0]).is_real and not domain.is_subset( S.Reals): integer = Symbol('integer', integer=True) rhs = -c / b + (a / d) * LambertW(arg, integer) for xu in xusolns: sol.append(xu.subs(u, rhs)) elif domain.is_subset(S.Reals): for k in lambert_real_branches: w = LambertW(arg, k) rhs = -c / b + (a / d) * w if rhs.has(I) or w.has(I): continue for xu in xusolns: sol.append(xu.subs(u, rhs)) elif domain.is_subset(S.Complexes): integer = Symbol('integer', integer=True) rhs = -c / b + (a / d) * LambertW(arg, integer) for xu in xusolns: sol.append(xu.subs(u, rhs)) else: if not domain.is_subset( S.Reals) and (not LambertW(arg).is_real) and (not real): integer = Symbol('integer', integer=True) rhs = Lambda(integer, -c / b + (a / d) * LambertW(arg, integer)) for xu in xusolns: sol.append(xu.subs(u, rhs)) else: w = LambertW(arg) rhs = -c / b + (a / d) * w for xu in xusolns: sol.append(xu.subs(u, rhs)) return list(set(sol))
def solve_prob3(n, phi, sigma): return solve(get_function(get_coefficients(n, phi, sigma)))
def test_aux_dep(): # This test is about rolling disc dynamics, comparing the results found # with KanesMethod to those found when deriving the equations "manually" # with SymPy. # The terms Fr, Fr*, and Fr*_steady are all compared between the two # methods. Here, Fr*_steady refers to the generalized inertia forces for an # equilibrium configuration. # Note: comparing to the test of test_rolling_disc() in test_kane.py, this # test also tests auxiliary speeds and configuration and motion constraints #, seen in the generalized dependent coordinates q[3], and depend speeds # u[3], u[4] and u[5]. # First, manual derivation of Fr, Fr_star, Fr_star_steady. # Symbols for time and constant parameters. # Symbols for contact forces: Fx, Fy, Fz. t, r, m, g, I, J = symbols('t r m g I J') Fx, Fy, Fz = symbols('Fx Fy Fz') # Configuration variables and their time derivatives: # q[0] -- yaw # q[1] -- lean # q[2] -- spin # q[3] -- dot(-r*B.z, A.z) -- distance from ground plane to disc center in # A.z direction # Generalized speeds and their time derivatives: # u[0] -- disc angular velocity component, disc fixed x direction # u[1] -- disc angular velocity component, disc fixed y direction # u[2] -- disc angular velocity component, disc fixed z direction # u[3] -- disc velocity component, A.x direction # u[4] -- disc velocity component, A.y direction # u[5] -- disc velocity component, A.z direction # Auxiliary generalized speeds: # ua[0] -- contact point auxiliary generalized speed, A.x direction # ua[1] -- contact point auxiliary generalized speed, A.y direction # ua[2] -- contact point auxiliary generalized speed, A.z direction q = dynamicsymbols('q:4') qd = [qi.diff(t) for qi in q] u = dynamicsymbols('u:6') ud = [ui.diff(t) for ui in u] ud_zero = dict(zip(ud, [0.] * len(ud))) ua = dynamicsymbols('ua:3') ua_zero = dict(zip(ua, [0.] * len(ua))) # noqa:F841 # Reference frames: # Yaw intermediate frame: A. # Lean intermediate frame: B. # Disc fixed frame: C. N = ReferenceFrame('N') A = N.orientnew('A', 'Axis', [q[0], N.z]) B = A.orientnew('B', 'Axis', [q[1], A.x]) C = B.orientnew('C', 'Axis', [q[2], B.y]) # Angular velocity and angular acceleration of disc fixed frame # u[0], u[1] and u[2] are generalized independent speeds. C.set_ang_vel(N, u[0] * B.x + u[1] * B.y + u[2] * B.z) C.set_ang_acc( N, C.ang_vel_in(N).diff(t, B) + cross(B.ang_vel_in(N), C.ang_vel_in(N))) # Velocity and acceleration of points: # Disc-ground contact point: P. # Center of disc: O, defined from point P with depend coordinate: q[3] # u[3], u[4] and u[5] are generalized dependent speeds. P = Point('P') P.set_vel(N, ua[0] * A.x + ua[1] * A.y + ua[2] * A.z) O = P.locatenew('O', q[3] * A.z + r * sin(q[1]) * A.y) O.set_vel(N, u[3] * A.x + u[4] * A.y + u[5] * A.z) O.set_acc(N, O.vel(N).diff(t, A) + cross(A.ang_vel_in(N), O.vel(N))) # Kinematic differential equations: # Two equalities: one is w_c_n_qd = C.ang_vel_in(N) in three coordinates # directions of B, for qd0, qd1 and qd2. # the other is v_o_n_qd = O.vel(N) in A.z direction for qd3. # Then, solve for dq/dt's in terms of u's: qd_kd. w_c_n_qd = qd[0] * A.z + qd[1] * B.x + qd[2] * B.y v_o_n_qd = O.pos_from(P).diff(t, A) + cross(A.ang_vel_in(N), O.pos_from(P)) kindiffs = Matrix([dot(w_c_n_qd - C.ang_vel_in(N), uv) for uv in B] + [dot(v_o_n_qd - O.vel(N), A.z)]) qd_kd = solve(kindiffs, qd) # noqa:F841 # Values of generalized speeds during a steady turn for later substitution # into the Fr_star_steady. steady_conditions = solve(kindiffs.subs({qd[1]: 0, qd[3]: 0}), u) steady_conditions.update({qd[1]: 0, qd[3]: 0}) # Partial angular velocities and velocities. partial_w_C = [C.ang_vel_in(N).diff(ui, N) for ui in u + ua] partial_v_O = [O.vel(N).diff(ui, N) for ui in u + ua] partial_v_P = [P.vel(N).diff(ui, N) for ui in u + ua] # Configuration constraint: f_c, the projection of radius r in A.z direction # is q[3]. # Velocity constraints: f_v, for u3, u4 and u5. # Acceleration constraints: f_a. f_c = Matrix([dot(-r * B.z, A.z) - q[3]]) f_v = Matrix([ dot(O.vel(N) - (P.vel(N) + cross(C.ang_vel_in(N), O.pos_from(P))), ai).expand() for ai in A ]) v_o_n = cross(C.ang_vel_in(N), O.pos_from(P)) a_o_n = v_o_n.diff(t, A) + cross(A.ang_vel_in(N), v_o_n) f_a = Matrix([dot(O.acc(N) - a_o_n, ai) for ai in A]) # noqa:F841 # Solve for constraint equations in the form of # u_dependent = A_rs * [u_i; u_aux]. # First, obtain constraint coefficient matrix: M_v * [u; ua] = 0; # Second, taking u[0], u[1], u[2] as independent, # taking u[3], u[4], u[5] as dependent, # rearranging the matrix of M_v to be A_rs for u_dependent. # Third, u_aux ==0 for u_dep, and resulting dictionary of u_dep_dict. M_v = zeros(3, 9) for i in range(3): for j, ui in enumerate(u + ua): M_v[i, j] = f_v[i].diff(ui) M_v_i = M_v[:, :3] M_v_d = M_v[:, 3:6] M_v_aux = M_v[:, 6:] M_v_i_aux = M_v_i.row_join(M_v_aux) A_rs = -M_v_d.inv() * M_v_i_aux u_dep = A_rs[:, :3] * Matrix(u[:3]) u_dep_dict = dict(zip(u[3:], u_dep)) # Active forces: F_O acting on point O; F_P acting on point P. # Generalized active forces (unconstrained): Fr_u = F_point * pv_point. F_O = m * g * A.z F_P = Fx * A.x + Fy * A.y + Fz * A.z Fr_u = Matrix([ dot(F_O, pv_o) + dot(F_P, pv_p) for pv_o, pv_p in zip(partial_v_O, partial_v_P) ]) # Inertia force: R_star_O. # Inertia of disc: I_C_O, where J is a inertia component about principal axis. # Inertia torque: T_star_C. # Generalized inertia forces (unconstrained): Fr_star_u. R_star_O = -m * O.acc(N) I_C_O = inertia(B, I, J, I) T_star_C = -(dot(I_C_O, C.ang_acc_in(N)) \ + cross(C.ang_vel_in(N), dot(I_C_O, C.ang_vel_in(N)))) Fr_star_u = Matrix([ dot(R_star_O, pv) + dot(T_star_C, pav) for pv, pav in zip(partial_v_O, partial_w_C) ]) # Form nonholonomic Fr: Fr_c, and nonholonomic Fr_star: Fr_star_c. # Also, nonholonomic Fr_star in steady turning condition: Fr_star_steady. Fr_c = Fr_u[:3, :].col_join(Fr_u[6:, :]) + A_rs.T * Fr_u[3:6, :] Fr_star_c = Fr_star_u[:3, :].col_join(Fr_star_u[6:, :])\ + A_rs.T * Fr_star_u[3:6, :] Fr_star_steady = Fr_star_c.subs(ud_zero).subs(u_dep_dict)\ .subs(steady_conditions).subs({q[3]: -r*cos(q[1])}).expand() # Second, using KaneMethod in mechanics for fr, frstar and frstar_steady. # Rigid Bodies: disc, with inertia I_C_O. iner_tuple = (I_C_O, O) disc = RigidBody('disc', O, C, m, iner_tuple) bodyList = [disc] # Generalized forces: Gravity: F_o; Auxiliary forces: F_p. F_o = (O, F_O) F_p = (P, F_P) forceList = [F_o, F_p] # KanesMethod. kane = KanesMethod(N, q_ind=q[:3], u_ind=u[:3], kd_eqs=kindiffs, q_dependent=q[3:], configuration_constraints=f_c, u_dependent=u[3:], velocity_constraints=f_v, u_auxiliary=ua) # fr, frstar, frstar_steady and kdd(kinematic differential equations). (fr, frstar) = kane.kanes_equations(bodyList, forceList) frstar_steady = frstar.subs(ud_zero).subs(u_dep_dict).subs(steady_conditions)\ .subs({q[3]: -r*cos(q[1])}).expand() kdd = kane.kindiffdict() assert Matrix(Fr_c).expand() == fr.expand() assert Matrix(Fr_star_c.subs(kdd)).expand() == frstar.expand() assert (simplify(Matrix(Fr_star_steady).expand()) == simplify( frstar_steady.expand())) syms_in_forcing = find_dynamicsymbols(kane.forcing) for qdi in qd: assert qdi not in syms_in_forcing
def infer(q,a,VERBOSE): wps = open(q).readlines() answs = open(a).readlines() problematic = open('somethingWrongProblems','a') ar = [0,0] sr = [0,0] mr = [0,0] dr = [0,0] replacements = {' two ':' 2 '," three ":' 3 ',' four ':' 4 ',' five ':' 5 ',' six ':' 6 ',' seven ':' 7 ',' eight ':' 8 ',' nine ':' 9 ',' ten ':' 10 ',' eleven ':' 11 ', ' twice ':' 2 '} right = 0 guesses = 0 ad = [] wrong = [] multiops = 0 multiopsright = 0 replacements = {' two ':' 2 '," three ":' 3 ',' four ':' 4 ',' five ':' 5 ',' six ':' 6 ',' seven ':' 7 ',' eight ':' 8 ',' nine ':' 9 ',' ten ':' 10 ',' eleven ':' 11 ', ' twice ':' 2 '} for k in range(len(wps)): if VERBOSE: for i in range(len(wps)): print(i,wps[i]) k = int(input()) print(k) problem = wps[k].lower() #First preprocessing, tokenize slightly problem = problem.strip().split(" ") for i,x in enumerate(problem): if len(x)==0:continue if x[-1] in [',','.','?']: problem[i] = x[:-1]+" "+x[-1] problem = ' '.join(problem) problem = " " + problem + " " print(problem) for r in replacements: problem = problem.replace(r,replacements[r]) story = nlp.parse(problem) sets = makesets.makesets(story['sentences']) #REMOVE DUPS THIS IS BAD: i = 0 while i < len(sets): x = sets[i] dups = [y for y in sets if y[1].num == x[1].num] if len(dups)>1: for x in dups[1:]: sets.remove(x) i+=1 print("Sets detected: ") for x in sets: x[1].details() numlist = [(cleannum(v.num),v) for k,v in sets] numlist = [x for x in numlist if x[0]!=''] if VERBOSE: for z,v in numlist: v.details() input() allnumbs = {str(k):v for k,v in numlist} objs = {k:(0,v) for k,v in numlist} constraints = [] for i in range(len(numlist)): if numlist[i][0][-1] == "*": if i==0:continue constraints.append(numlist[i-1][0]+" * "+numlist[i][0][:-1]) numlist[i] = (''.join([x for x in numlist[i][0] if x not in ['*','/']]),numlist[i][1]) numlist[i][1].num = numlist[i][0] elif numlist[i][0][0] == "*": if i==0:continue numlist[i] = (''.join([x for x in numlist[i][0] if x not in ['*','/']]),numlist[i][1]) tmp = numlist[i-1] numlist[i-1]=numlist[i] numlist[i]=tmp constraints.append(numlist[i-1][0]+" * "+numlist[i][0][1:]) elif numlist[i][0][-1] == "/": if i==0:continue constraints.append(" / "+numlist[i][0][:-1]) numlist[i] = (''.join([x for x in numlist[i][0] if x not in ['*','/']]),numlist[i][1]) objs = {k:(0,v) for k,v in numlist} if len(objs)<2: wrong.append(k) continue if 'x' not in objs: wrong.append(k) continue integerproblem = all([float(x[0]).is_integer() for x in numlist if x[0]!='x']) multi = False if len(objs)>3: multiops+=1 multi = True if VERBOSE: print(objs,numlist,[v.num for k,v in sets]) #print(allnumbs) state = [] #print(numlist) #for e in allnumbs.items(): #print(numlist) numidxlist = [x[0] for x in numlist] ST = StringTemplate(numidxlist, inf=True) scores = [] for j,eq in enumerate(ST.equations): #print(j,eq.toString()) good = False if len(constraints)==0: good = True else: for constraint in constraints: if constraint in eq.toString(): good = True if not good: scores.append(-0.2) continue thisscore = [] #print(eq.toString()) #determine score for this eq l,r = [x.strip().split(' ') for x in eq.toString().split('=')] #print(l,r) if len(r)>1 and len(l)>1: scores.append(-0.2);continue if len(r)>1: compound = r target = l[0] else: #print(constraints) compound = l target = r[0] target = (target,objs[target]) #find innermost parens? while len(compound)>1: if "(" in compound: rpidx = (len(compound) - 1) - compound[::-1].index('(') lpidx = rpidx+compound[rpidx:].index(")") subeq = compound[rpidx+1:lpidx] substr = "("+''.join(subeq)+")" compound = compound[:rpidx]+[substr]+compound[lpidx+1:] else: subeq = compound[0:3] substr = "("+''.join(subeq)+")" compound = [substr]+compound[3:] if substr in objs: pute = objs[substr] #print(pute[0],pute[1].num) else: p,op,e = subeq #print(p,op,e) p = objs[p][1] e = objs[e][1] op = op.strip() pute = compute(p,op,e,target,problem) #print("OPERATION SELECTED: ",op) #p.details() #e.details() #print(substr,pute[1].num) objs[substr]=pute if pute == -1: exit() score,c = pute thisscore.append(score) if target[1][1].entity != c.entity: thisscore.append(-0.2) #print("WAT",thisscore,c.ent,c.num) scores.append(sum(thisscore)) #print(compound) m = np.argmax(scores) #print(scores[m],ST.equations[m].toString()) srt = sorted([(x,i) for i,x in enumerate(scores)],reverse=True) print('\n Top scoring 3 equations: ') for x,i in srt[:3]: print(x,ST.equations[i].toString()) ''' try: if target.ent=='dozen': guess = solve('('+numlist[0].num+'/12)'+"-"+target.num,'x')[0] print(numlist[0].num+"/12="+target.num) else: guess = solve(numlist[0].num+"-"+target.num,'x')[0] print(numlist[0].num+"="+target.num) ''' eqidxs = [y[0] for y in sorted(enumerate(scores),key=lambda x:x[1],reverse=True)] eqnidsx = [x[1] for x in srt] seen = [] tright = 0 for i in eqidxs: if len(seen)>=1:break eq = ST.equations[i].toString() #eq = eq.replace("=",'-') splitEquation = eq.split('=') eq = splitEquation[0] + '- (' + splitEquation[1] + ')' #print(scores[i], eq) try: guess = solve(eq,'x')[0] except: guess = -1 # This is the non-negative constraint # wrapped in a "check for complex number" try statement :/ try: if guess < 0: continue except: continue #this is a constraint agianst fractional answers when the problem is integers if not guess.is_integer: if integerproblem: continue if guess not in seen: seen.append(guess) else: continue answ = float(answs[k]) ops = [x for x in ST.equations[i].toString() if x in ['+','-','*','/']] if guess == answ: print("\nCORRECT") tright=1 ar[0] += ops.count('+') sr[0] += ops.count('-') mr[0] += ops.count('*') dr[0] += ops.count('/') else: print("\nINCORRECT") ar[1] += ops.count('+') sr[1] += ops.count('-') mr[1] += ops.count('*') dr[1] += ops.count('/') print("Guessed Equation : ",ST.equations[i].toString() ) print("Guess : ",guess,"\nTrue Answer :", answ, '\n\n') guesses += len(seen) if tright==1: if multi: multiopsright += 1 right +=1 else: wrong.append(k) #break if VERBOSE: input() continue print(right,guesses) print(multiops,multiopsright) print(ar,sr,mr,dr)
def deltasummation(f, limit, no_piecewise=False): """ Handle summations containing a KroneckerDelta. Explanation =========== The idea for summation is the following: - If we are dealing with a KroneckerDelta expression, i.e. KroneckerDelta(g(x), j), we try to simplify it. If we could simplify it, then we sum the resulting expression. We already know we can sum a simplified expression, because only simple KroneckerDelta expressions are involved. If we couldn't simplify it, there are two cases: 1) The expression is a simple expression: we return the summation, taking care if we are dealing with a Derivative or with a proper KroneckerDelta. 2) The expression is not simple (i.e. KroneckerDelta(cos(x))): we can do nothing at all. - If the expr is a multiplication expr having a KroneckerDelta term: First we expand it. If the expansion did work, then we try to sum the expansion. If not, we try to extract a simple KroneckerDelta term, then we have two cases: 1) We have a simple KroneckerDelta term, so we return the summation. 2) We didn't have a simple term, but we do have an expression with simplified KroneckerDelta terms, so we sum this expression. Examples ======== >>> from sympy import oo, symbols >>> from sympy.abc import k >>> i, j = symbols('i, j', integer=True, finite=True) >>> from sympy.concrete.delta import deltasummation >>> from sympy import KroneckerDelta >>> deltasummation(KroneckerDelta(i, k), (k, -oo, oo)) 1 >>> deltasummation(KroneckerDelta(i, k), (k, 0, oo)) Piecewise((1, i >= 0), (0, True)) >>> deltasummation(KroneckerDelta(i, k), (k, 1, 3)) Piecewise((1, (i >= 1) & (i <= 3)), (0, True)) >>> deltasummation(k*KroneckerDelta(i, j)*KroneckerDelta(j, k), (k, -oo, oo)) j*KroneckerDelta(i, j) >>> deltasummation(j*KroneckerDelta(i, j), (j, -oo, oo)) i >>> deltasummation(i*KroneckerDelta(i, j), (i, -oo, oo)) j See Also ======== deltaproduct sympy.functions.special.tensor_functions.KroneckerDelta sympy.concrete.sums.summation """ if ((limit[2] - limit[1]) < 0) == True: return S.Zero if not f.has(KroneckerDelta): return summation(f, limit) x = limit[0] g = _expand_delta(f, x) if g.is_Add: return piecewise_fold( g.func(*[deltasummation(h, limit, no_piecewise) for h in g.args])) # try to extract a simple KroneckerDelta term delta, expr = _extract_delta(g, x) if (delta is not None) and (delta.delta_range is not None): dinf, dsup = delta.delta_range if (limit[1] - dinf <= 0) == True and (limit[2] - dsup >= 0) == True: no_piecewise = True if not delta: return summation(f, limit) solns = solve(delta.args[0] - delta.args[1], x) if len(solns) == 0: return S.Zero elif len(solns) != 1: return Sum(f, limit) value = solns[0] if no_piecewise: return expr.subs(x, value) return Piecewise( (expr.subs(x, value), Interval(*limit[1:3]).as_relational(value)), (S.Zero, True))
def test_non_central_inertia(): # This tests that the calculation of Fr* does not depend the point # about which the inertia of a rigid body is defined. This test solves # exercises 8.12, 8.17 from Kane 1985. # Declare symbols q1, q2, q3 = dynamicsymbols('q1:4') q1d, q2d, q3d = dynamicsymbols('q1:4', level=1) u1, u2, u3, u4, u5 = dynamicsymbols('u1:6') u_prime, R, M, g, e, f, theta = symbols('u\' R, M, g, e, f, theta') a, b, mA, mB, IA, J, K, t = symbols('a b mA mB IA J K t') Q1, Q2, Q3 = symbols('Q1, Q2 Q3') IA22, IA23, IA33 = symbols('IA22 IA23 IA33') # Reference Frames F = ReferenceFrame('F') P = F.orientnew('P', 'axis', [-theta, F.y]) A = P.orientnew('A', 'axis', [q1, P.x]) A.set_ang_vel(F, u1 * A.x + u3 * A.z) # define frames for wheels B = A.orientnew('B', 'axis', [q2, A.z]) C = A.orientnew('C', 'axis', [q3, A.z]) B.set_ang_vel(A, u4 * A.z) C.set_ang_vel(A, u5 * A.z) # define points D, S*, Q on frame A and their velocities pD = Point('D') pD.set_vel(A, 0) # u3 will not change v_D_F since wheels are still assumed to roll without slip. pD.set_vel(F, u2 * A.y) pS_star = pD.locatenew('S*', e * A.y) pQ = pD.locatenew('Q', f * A.y - R * A.x) for p in [pS_star, pQ]: p.v2pt_theory(pD, F, A) # masscenters of bodies A, B, C pA_star = pD.locatenew('A*', a * A.y) pB_star = pD.locatenew('B*', b * A.z) pC_star = pD.locatenew('C*', -b * A.z) for p in [pA_star, pB_star, pC_star]: p.v2pt_theory(pD, F, A) # points of B, C touching the plane P pB_hat = pB_star.locatenew('B^', -R * A.x) pC_hat = pC_star.locatenew('C^', -R * A.x) pB_hat.v2pt_theory(pB_star, F, B) pC_hat.v2pt_theory(pC_star, F, C) # the velocities of B^, C^ are zero since B, C are assumed to roll without slip kde = [q1d - u1, q2d - u4, q3d - u5] vc = [dot(p.vel(F), A.y) for p in [pB_hat, pC_hat]] # inertias of bodies A, B, C # IA22, IA23, IA33 are not specified in the problem statement, but are # necessary to define an inertia object. Although the values of # IA22, IA23, IA33 are not known in terms of the variables given in the # problem statement, they do not appear in the general inertia terms. inertia_A = inertia(A, IA, IA22, IA33, 0, IA23, 0) inertia_B = inertia(B, K, K, J) inertia_C = inertia(C, K, K, J) # define the rigid bodies A, B, C rbA = RigidBody('rbA', pA_star, A, mA, (inertia_A, pA_star)) rbB = RigidBody('rbB', pB_star, B, mB, (inertia_B, pB_star)) rbC = RigidBody('rbC', pC_star, C, mB, (inertia_C, pC_star)) km = KanesMethod(F, q_ind=[q1, q2, q3], u_ind=[u1, u2], kd_eqs=kde, u_dependent=[u4, u5], velocity_constraints=vc, u_auxiliary=[u3]) forces = [(pS_star, -M * g * F.x), (pQ, Q1 * A.x + Q2 * A.y + Q3 * A.z)] bodies = [rbA, rbB, rbC] fr, fr_star = km.kanes_equations(bodies, forces) vc_map = solve(vc, [u4, u5]) # KanesMethod returns the negative of Fr, Fr* as defined in Kane1985. fr_star_expected = Matrix([ -(IA + 2 * J * b**2 / R**2 + 2 * K + mA * a**2 + 2 * mB * b**2) * u1.diff(t) - mA * a * u1 * u2, -(mA + 2 * mB + 2 * J / R**2) * u2.diff(t) + mA * a * u1**2, 0 ]) t = trigsimp(fr_star.subs(vc_map).subs({u3: 0})).doit().expand() assert ((fr_star_expected - t).expand() == zeros(3, 1)) # define inertias of rigid bodies A, B, C about point D # I_S/O = I_S/S* + I_S*/O bodies2 = [] for rb, I_star in zip([rbA, rbB, rbC], [inertia_A, inertia_B, inertia_C]): I = I_star + inertia_of_point_mass(rb.mass, rb.masscenter.pos_from(pD), rb.frame) bodies2.append(RigidBody('', rb.masscenter, rb.frame, rb.mass, (I, pD))) fr2, fr_star2 = km.kanes_equations(bodies2, forces) t = trigsimp(fr_star2.subs(vc_map).subs({u3: 0})).doit() assert (fr_star_expected - t).expand() == zeros(3, 1)
def infer(q, a, VERBOSE): wps = q #open(q).readlines() answs = a #open(a).readlines() problematic = open('somethingWrongProblems', 'a') ar = [0, 0] sr = [0, 0] mr = [0, 0] dr = [0, 0] replacements = { ' two ': ' 2 ', " three ": ' 3 ', ' four ': ' 4 ', ' five ': ' 5 ', ' six ': ' 6 ', ' seven ': ' 7 ', ' eight ': ' 8 ', ' nine ': ' 9 ', ' ten ': ' 10 ', ' eleven ': ' 11 ', ' twice ': ' 2 ' } right = 0 guesses = 0 ad = [] wrong = [] multiops = 0 multiopsright = 0 replacements = { ' two ': ' 2 ', " three ": ' 3 ', ' four ': ' 4 ', ' five ': ' 5 ', ' six ': ' 6 ', ' seven ': ' 7 ', ' eight ': ' 8 ', ' nine ': ' 9 ', ' ten ': ' 10 ', ' eleven ': ' 11 ', ' twice ': ' 2 ' } for k in range(len(wps)): if VERBOSE: for i in range(len(wps)): print(i, wps[i]) k = int(input()) print(k) problem = wps[k].lower() ret = local_score.score(problem) if ret == -1: wrong.append(k) continue equations, scores, equalsmatch, contmatch, integerproblem, failurerate, fivescores = ret m = np.argmax(scores) #print(scores[m],ST.equations[m].toString()) srt = sorted([(x, i) for i, x in enumerate(scores)], reverse=True) print('\n Top scoring 3 equations: ') for x, i in srt[:3]: print(x, equations[i].toString()) eqidxs = [ y[0] for y in sorted( enumerate(scores), key=lambda x: x[1], reverse=True) ] eqnidsx = [x[1] for x in srt] seen = [] tright = 0 globallyadjusted = [] locally = [] answ = float(answs[k]) for i in eqidxs: eq = equations[i].toString() ogeq = equations[i].toString() #eq = eq.replace("=",'-') splitEquation = eq.split('=') eq = splitEquation[0] + '- (' + splitEquation[1] + ')' #print(scores[i], eq) try: guess = solve(eq, 'x')[0] except: continue # This is the non-negative constraint # wrapped in a "check for complex number" try statement :/ try: if guess < 0: continue except: continue if not guess.is_integer: try: int(guess) except: if integerproblem: print("Integer problem") continue #this is a constraint agianst fractional answers when the problem is integers if guess not in seen: seen.append(guess) else: continue ops = [ x for x in equations[i].toString() if x in ['+', '-', '*', '/'] ] vec = [] if equalsmatch[i] == 'x': equalsmatch[i] = 0 #continue contmatch[i] = 0 failurerate[i] = 1 #build training vector vec = vectorize_eqn.vec(scores[i], guess, ogeq.strip().split(" "), integerproblem, equalsmatch[i], contmatch[i], problem, failurerate[i], fivescores[i]) #print(vec) op_label, op_acc, op_val = svm_predict([-1], [vec], globalm, '-q -b 1') op_val = op_val[0][0] locally.append((scores[i], i, guess)) globallyadjusted.append((op_val * scores[i], i, guess)) #globallyadjusted.append(((0.5*op_val)+scores[i],i,guess)) srt = sorted(globallyadjusted, reverse=True) print("top 3 globally adjusted:") for s, i, guess in srt[:3]: print("score : ", s) print("eq : ", equations[i].toString()) print("guess : ", guess) srt2 = sorted(locally, reverse=True) if srt2[0][0] > 0.9: srt = srt2 if len(srt) == 0: guess = -1 score = 0 i = 0 else: score, i, guess = srt[0] if guess == answ or guess / 100 == answ or answ / 100 == guess: print("\nCORRECT") tright = 1 else: print("\nINCORRECT") print("Guessed Equation : ", equations[i].toString()) print("Guess : ", guess, "\nTrue Answer :", answ, '\n\n') guesses += 1 if tright == 1: if multi: multiopsright += 1 right += 1 else: wrong.append(k) #break if VERBOSE: input() continue print(right, guesses)
def solve_univariate_inequality(expr, gen, relational=True): """Solves a real univariate inequality. Examples ======== >>> from sympy.solvers.inequalities import solve_univariate_inequality >>> from sympy.core.symbol import Symbol >>> x = Symbol('x', real=True) >>> solve_univariate_inequality(x**2 >= 4, x) Or(And(-oo < x, x <= -2), And(2 <= x, x < oo)) >>> solve_univariate_inequality(x**2 >= 4, x, relational=False) (-oo, -2] U [2, oo) """ from sympy.solvers.solvers import solve, denoms e = expr.lhs - expr.rhs parts = n, d = e.as_numer_denom() if all(i.is_polynomial(gen) for i in parts): solns = solve(n, gen, check=False) singularities = solve(d, gen, check=False) else: solns = solve(e, gen, check=False) singularities = [] for d in denoms(e): singularities.extend(solve(d, gen)) include_x = expr.func(0, 0) def valid(x): v = e.subs(gen, x) try: r = expr.func(v, 0) except TypeError: r = S.false if r in (S.true, S.false): return r if v.is_real is False: return S.false else: v = v.n(2) if v.is_comparable: return expr.func(v, 0) return S.false start = S.NegativeInfinity sol_sets = [S.EmptySet] try: reals = _nsort(set(solns + singularities), separated=True)[0] except NotImplementedError: raise NotImplementedError('sorting of these roots is not supported') for x in reals: end = x if end in [S.NegativeInfinity, S.Infinity]: if valid(S(0)): sol_sets.append(Interval(start, S.Infinity, True, True)) break if valid((start + end)/2 if start != S.NegativeInfinity else end - 1): sol_sets.append(Interval(start, end, True, True)) if x in singularities: singularities.remove(x) elif include_x: sol_sets.append(FiniteSet(x)) start = end end = S.Infinity if valid(start + 1): sol_sets.append(Interval(start, end, True, True)) rv = Union(*sol_sets) return rv if not relational else rv.as_relational(gen)
def test_slow_general_univariate(): r = RootOf(x**5 - x**2 + 1, 0) assert solve(sqrt(x) + 1/root(x, 3) > 1) == \ Or(And(S(0) < x, x < r**6), And(r**6 < x, x < oo))
def idiff(eq, y, x, n=1): """Return ``dy/dx`` assuming that ``eq == 0``. Parameters ========== y : the dependent variable or a list of dependent variables (with y first) x : the variable that the derivative is being taken with respect to n : the order of the derivative (default is 1) Examples ======== >>> from sympy.abc import x, y, a >>> from sympy.geometry.util import idiff >>> circ = x**2 + y**2 - 4 >>> idiff(circ, y, x) -x/y >>> idiff(circ, y, x, 2).simplify() (-x**2 - y**2)/y**3 Here, ``a`` is assumed to be independent of ``x``: >>> idiff(x + a + y, y, x) -1 Now the x-dependence of ``a`` is made explicit by listing ``a`` after ``y`` in a list. >>> idiff(x + a + y, [y, a], x) -Derivative(a, x) - 1 See Also ======== sympy.core.function.Derivative: represents unevaluated derivatives sympy.core.function.diff: explicitly differentiates wrt symbols """ if is_sequence(y): dep = set(y) y = y[0] elif isinstance(y, Symbol): dep = {y} elif isinstance(y, Function): pass else: raise ValueError( "expecting x-dependent symbol(s) or function(s) but got: %s" % y) f = { s: Function(s.name)(x) for s in eq.free_symbols if s != x and s in dep } if isinstance(y, Symbol): dydx = Function(y.name)(x).diff(x) else: dydx = y.diff(x) eq = eq.subs(f) derivs = {} for i in range(n): yp = solve(eq.diff(x), dydx)[0].subs(derivs) if i == n - 1: return yp.subs([(v, k) for k, v in f.items()]) derivs[dydx] = yp eq = dydx - yp dydx = dydx.diff(x)
def _lambert(eq, x): """ Given an expression assumed to be in the form ``F(X, a..f) = a*log(b*X + c) + d*X + f = 0`` where X = g(x) and x = g^-1(X), return the Lambert solution, ``x = g^-1(-c/b + (a/d)*W(d/(a*b)*exp(c*d/a/b)*exp(-f/a)))``. """ eq = _mexpand(expand_log(eq)) mainlog = _mostfunc(eq, log, x) if not mainlog: return [] # violated assumptions other = eq.subs(mainlog, 0) if isinstance(-other, log): eq = (eq - other).subs(mainlog, mainlog.args[0]) mainlog = mainlog.args[0] if not isinstance(mainlog, log): return [] # violated assumptions other = -(-other).args[0] eq += other if x not in other.free_symbols: return [] # violated assumptions d, f, X2 = _linab(other, x) logterm = collect(eq - other, mainlog) a = logterm.as_coefficient(mainlog) if a is None or x in a.free_symbols: return [] # violated assumptions logarg = mainlog.args[0] b, c, X1 = _linab(logarg, x) if X1 != X2: return [] # violated assumptions # invert the generator X1 so we have x(u) u = Dummy('rhs') xusolns = solve(X1 - u, x) # There are infinitely many branches for LambertW # but only branches for k = -1 and 0 might be real. The k = 0 # branch is real and the k = -1 branch is real if the LambertW argumen # in in range [-1/e, 0]. Since `solve` does not return infinite # solutions we will only include the -1 branch if it tests as real. # Otherwise, inclusion of any LambertW in the solution indicates to # the user that there are imaginary solutions corresponding to # different k values. lambert_real_branches = [-1, 0] sol = [] # solution of the given Lambert equation is like # sol = -c/b + (a/d)*LambertW(arg, k), # where arg = d/(a*b)*exp((c*d-b*f)/a/b) and k in lambert_real_branches. # Instead of considering the single arg, `d/(a*b)*exp((c*d-b*f)/a/b)`, # the individual `p` roots obtained when writing `exp((c*d-b*f)/a/b)` # as `exp(A/p) = exp(A)**(1/p)`, where `p` is an Integer, are used. # calculating args for LambertW num, den = ((c * d - b * f) / a / b).as_numer_denom() p, den = den.as_coeff_Mul() e = exp(num / den) t = Dummy('t') args = [d / (a * b) * t for t in roots(t**p - e, t).keys()] # calculating solutions from args for arg in args: for k in lambert_real_branches: w = LambertW(arg, k) if k and not w.is_real: continue rhs = -c / b + (a / d) * w for xu in xusolns: sol.append(xu.subs(u, rhs)) return sol
guess = solve(numlist[0].num+"-"+target.num,'x')[0] print(numlist[0].num+"="+target.num) ''' eqidxs = [y[0] for y in sorted(enumerate(scores),key=lambda x:x[1],reverse=True)] eqnidsx = [x[1] for x in srt] seen = [] tright = 0 for i in eqidxs: if len(seen)>=1:break eq = ST.equations[i].toString() #eq = eq.replace("=",'-') splitEquation = eq.split('=') eq = splitEquation[0] + '- (' + splitEquation[1] + ')' #print(scores[i], eq) try: guess = solve(eq,'x')[0] except: guess = -1 # This is the non-negative constraint if guess < 0: continue #this is a constraint agianst fractional answers when the problem is integers if not guess.is_integer: if integerproblem: continue if guess not in seen: seen.append(guess) else: continue
def pde_1st_linear_constant_coeff(eq, func, order, match, solvefun): r""" Solves a first order linear partial differential equation with constant coefficients. The general form of this partial differential equation is .. math:: a \frac{\partial f(x,y)}{\partial x} + b \frac{\partial f(x,y)}{\partial y} + c f(x,y) = G(x,y) where `a`, `b` and `c` are constants and `G(x, y)` can be an arbitrary function in `x` and `y`. The general solution of the PDE is: .. math:: f(x, y) = \left. \left[F(\eta) + \frac{1}{a^2 + b^2} \int\limits^{a x + b y} G\left(\frac{a \xi + b \eta}{a^2 + b^2}, \frac{- a \eta + b \xi}{a^2 + b^2} \right) e^{\frac{c \xi}{a^2 + b^2}}\, d\xi\right] e^{- \frac{c \xi}{a^2 + b^2}} \right|_{\substack{\eta=- a y + b x\\ \xi=a x + b y }}\, , where `F(\eta)` is an arbitrary single-valued function. The solution can be found in SymPy with ``pdsolve``:: >>> from sympy.solvers import pdsolve >>> from sympy.abc import x, y, a, b, c >>> from sympy import Function, pprint >>> f = Function('f') >>> G = Function('G') >>> u = f(x,y) >>> ux = u.diff(x) >>> uy = u.diff(y) >>> genform = a*ux + b*uy + c*u - G(x,y) >>> pprint(genform) d d a*--(f(x, y)) + b*--(f(x, y)) + c*f(x, y) - G(x, y) dx dy >>> pprint(pdsolve(genform, hint='1st_linear_constant_coeff_Integral')) // a*x + b*y \ || / | || | | || | c*xi | || | ------- | || | 2 2 | || | /a*xi + b*eta -a*eta + b*xi\ a + b | || | G|------------, -------------|*e d(xi)| || | | 2 2 2 2 | | || | \ a + b a + b / | || | | || / | || | f(x, y) = ||F(eta) + -------------------------------------------------------|* || 2 2 | \\ a + b / <BLANKLINE> \| || || || || || || || || -c*xi || -------|| 2 2|| a + b || e || || /|eta=-a*y + b*x, xi=a*x + b*y Examples ======== >>> from sympy.solvers.pde import pdsolve >>> from sympy import Function, pprint, exp >>> from sympy.abc import x,y >>> f = Function('f') >>> eq = -2*f(x,y).diff(x) + 4*f(x,y).diff(y) + 5*f(x,y) - exp(x + 3*y) >>> pdsolve(eq) Eq(f(x, y), (F(4*x + 2*y)*exp(x/2) + exp(x + 4*y)/15)*exp(-y)) References ========== - Viktor Grigoryan, "Partial Differential Equations" Math 124A - Fall 2010, pp.7 """ # TODO : For now homogeneous first order linear PDE's having # two variables are implemented. Once there is support for # solving systems of ODE's, this can be extended to n variables. xi, eta = symbols("xi eta") f = func.func x = func.args[0] y = func.args[1] b = match[match['b']] c = match[match['c']] d = match[match['d']] e = -match[match['e']] expterm = exp(-S(d) / (b**2 + c**2) * xi) functerm = solvefun(eta) solvedict = solve((b * x + c * y - xi, c * x - b * y - eta), x, y) # Integral should remain as it is in terms of xi, # doit() should be done in _handle_Integral. genterm = (1 / S(b**2 + c**2)) * Integral( (1 / expterm * e).subs(solvedict), (xi, b * x + c * y)) return Eq( f(x, y), Subs(expterm * (functerm + genterm), (eta, xi), (c * x - b * y, b * x + c * y)))
def _contains(self, other): from sympy.matrices import Matrix from sympy.solvers.solveset import solveset, linsolve from sympy.solvers.solvers import solve from sympy.utilities.iterables import is_sequence, iterable, cartes L = self.lamda if is_sequence(other): if not is_sequence(L.expr): return S.false if len(L.expr) != len(other): raise ValueError(filldedent(''' Dimensions of other and output of Lambda are different.''')) elif iterable(other): raise ValueError(filldedent(''' `other` should be an ordered object like a Tuple.''')) solns = None if self._is_multivariate(): if not is_sequence(L.expr): # exprs -> (numer, denom) and check again # XXX this is a bad idea -- make the user # remap self to desired form return other.as_numer_denom() in self.func( Lambda(L.variables, L.expr.as_numer_denom()), self.base_set) eqs = [expr - val for val, expr in zip(other, L.expr)] variables = L.variables free = set(variables) if all(i.is_number for i in list(Matrix(eqs).jacobian(variables))): solns = list(linsolve([e - val for e, val in zip(L.expr, other)], variables)) else: try: syms = [e.free_symbols & free for e in eqs] solns = {} for i, (e, s, v) in enumerate(zip(eqs, syms, other)): if not s: if e != v: return S.false solns[vars[i]] = [v] continue elif len(s) == 1: sy = s.pop() sol = solveset(e, sy) if sol is S.EmptySet: return S.false elif isinstance(sol, FiniteSet): solns[sy] = list(sol) else: raise NotImplementedError else: # if there is more than 1 symbol from # variables in expr than this is a # coupled system raise NotImplementedError solns = cartes(*[solns[s] for s in variables]) except NotImplementedError: solns = solve([e - val for e, val in zip(L.expr, other)], variables, set=True) if solns: _v, solns = solns # watch for infinite solutions like solving # for x, y and getting (x, 0), (0, y), (0, 0) solns = [i for i in solns if not any( s in i for s in variables)] else: x = L.variables[0] if isinstance(L.expr, Expr): # scalar -> scalar mapping solnsSet = solveset(L.expr - other, x) if solnsSet.is_FiniteSet: solns = list(solnsSet) else: msgset = solnsSet else: # scalar -> vector for e, o in zip(L.expr, other): solns = solveset(e - o, x) if solns is S.EmptySet: return S.false for soln in solns: try: if soln in self.base_set: break # check next pair except TypeError: if self.base_set.contains(soln.evalf()): break else: return S.false # never broke so there was no True return S.true if solns is None: raise NotImplementedError(filldedent(''' Determining whether %s contains %s has not been implemented.''' % (msgset, other))) for soln in solns: try: if soln in self.base_set: return S.true except TypeError: return self.base_set.contains(soln.evalf()) return S.false
def canonical_odes(eqs, funcs, t): r""" Function that solves for highest order derivatives in a system Explanation =========== This function inputs a system of ODEs and based on the system, the dependent variables and their highest order, returns the system in the following form: .. math:: X'(t) = A(t) X(t) + b(t) Here, $X(t)$ is the vector of dependent variables of lower order, $A(t)$ is the coefficient matrix, $b(t)$ is the non-homogeneous term and $X'(t)$ is the vector of dependent variables in their respective highest order. We use the term canonical form to imply the system of ODEs which is of the above form. If the system passed has a non-linear term with multiple solutions, then a list of systems is returned in its canonical form. Parameters ========== eqs : List List of the ODEs funcs : List List of dependent variables t : Symbol Independent variable Examples ======== >>> from sympy import symbols, Function, Eq, Derivative >>> from sympy.solvers.ode.systems import canonical_odes >>> f, g = symbols("f g", cls=Function) >>> x, y = symbols("x y") >>> funcs = [f(x), g(x)] >>> eqs = [Eq(f(x).diff(x) - 7*f(x), 12*g(x)), Eq(g(x).diff(x) + g(x), 20*f(x))] >>> canonical_eqs = canonical_odes(eqs, funcs, x) >>> canonical_eqs [[Eq(Derivative(f(x), x), 7*f(x) + 12*g(x)), Eq(Derivative(g(x), x), 20*f(x) - g(x))]] >>> system = [Eq(Derivative(f(x), x)**2 - 2*Derivative(f(x), x) + 1, 4), Eq(-y*f(x) + Derivative(g(x), x), 0)] >>> canonical_system = canonical_odes(system, funcs, x) >>> canonical_system [[Eq(Derivative(f(x), x), -1), Eq(Derivative(g(x), x), y*f(x))], [Eq(Derivative(f(x), x), 3), Eq(Derivative(g(x), x), y*f(x))]] Returns ======= List """ from sympy.solvers.solvers import solve order = _get_func_order(eqs, funcs) canon_eqs = solve(eqs, *[func.diff(t, order[func]) for func in funcs], dict=True) systems = [] for eq in canon_eqs: system = [ Eq(func.diff(t, order[func]), eq[func.diff(t, order[func])]) for func in funcs ] systems.append(system) return systems
''' -----------Converting equation (1) to a system of linear ----------- -----------equations, comparing the coefficients of the ----------- -----------polynomials in both sides of the equation (1) ----------- ''' EQ=[Eq(LHS_matrix[i,j],expand(RHS_matrix[i,j])) for i,j in product(range(LHS_matrix.rows),range(LHS_matrix.cols)) ] eq=[] for equation in EQ: RHS=poly((equation).rhs,s).all_coeffs() #simplify necessary ? LHS=poly((equation).lhs,s).all_coeffs() if len(RHS)>len(LHS): # we add zero for each missing coefficient (greater than the degree of LHS) LHS=(len(RHS)-len(LHS))*[0] + LHS eq=eq+[Eq(LHS[i],RHS[i]) for i in range(len(RHS))] SOL=solve(eq,a+c) # the coefficients of Λ and C #----------substitute the solution in the matrices---------------- C=C.subs(SOL) #substitute(SOL) Lamda=Lamda.subs(SOL) #substitute(SOL) Js=(Ds+Cs*Ys+Lamda*(B0)); # for output compatibility E=eye(A0.cols) if do_test==True: test_result=test(As,Bs,Cs,Ds,Us,sI_A,Js,Ys,B0,C0,C,Psi,Lamda) else: test_result= 'not done' return (E,A0,B0,C,Js,test_result)
def test_slow_general_univariate(): r = rootof(x**5 - x**2 + 1, 0) assert solve(sqrt(x) + 1/root(x, 3) > 1) == \ Or(And(S(0) < x, x < r**6), And(r**6 < x, x < oo))
def solve_univariate_inequality(expr, gen, relational=True): """Solves a real univariate inequality. Examples ======== >>> from sympy.solvers.inequalities import solve_univariate_inequality >>> from sympy.core.symbol import Symbol >>> x = Symbol('x') >>> solve_univariate_inequality(x**2 >= 4, x) Or(And(-oo < x, x <= -2), And(2 <= x, x < oo)) >>> solve_univariate_inequality(x**2 >= 4, x, relational=False) (-oo, -2] U [2, oo) """ from sympy.solvers.solvers import solve, denoms # This keeps the function independent of the assumptions about `gen`. # `solveset` makes sure this function is called only when the domain is # real. d = Dummy(real=True) expr = expr.subs(gen, d) _gen = gen gen = d if expr is S.true: rv = S.Reals elif expr is S.false: rv = S.EmptySet else: e = expr.lhs - expr.rhs parts = n, d = e.as_numer_denom() if all(i.is_polynomial(gen) for i in parts): solns = solve(n, gen, check=False) singularities = solve(d, gen, check=False) else: solns = solve(e, gen, check=False) singularities = [] for d in denoms(e): singularities.extend(solve(d, gen)) include_x = expr.func(0, 0) def valid(x): v = e.subs(gen, x) try: r = expr.func(v, 0) except TypeError: r = S.false if r in (S.true, S.false): return r if v.is_real is False: return S.false else: v = v.n(2) if v.is_comparable: return expr.func(v, 0) return S.false start = S.NegativeInfinity sol_sets = [S.EmptySet] try: reals = _nsort(set(solns + singularities), separated=True)[0] except NotImplementedError: raise NotImplementedError('sorting of these roots is not supported') for x in reals: end = x if end in [S.NegativeInfinity, S.Infinity]: if valid(S(0)): sol_sets.append(Interval(start, S.Infinity, True, True)) break pt = ((start + end)/2 if start is not S.NegativeInfinity else (end/2 if end.is_positive else (2*end if end.is_negative else end - 1))) if valid(pt): sol_sets.append(Interval(start, end, True, True)) if x in singularities: singularities.remove(x) elif include_x: sol_sets.append(FiniteSet(x)) start = end end = S.Infinity # in case start == -oo then there were no solutions so we just # check a point between -oo and oo (e.g. 0) else pick a point # past the last solution (which is start after the end of the # for-loop above pt = (0 if start is S.NegativeInfinity else (start/2 if start.is_negative else (2*start if start.is_positive else start + 1))) if valid(pt): sol_sets.append(Interval(start, end, True, True)) rv = Union(*sol_sets).subs(gen, _gen) return rv if not relational else rv.as_relational(_gen)
def test_issue_10268(): assert solve(log(x) < 1000) == And(S(0) < x, x < exp(1000))
def pde_1st_linear_constant_coeff(eq, func, order, match, solvefun): r""" Solves a first order linear partial differential equation with constant coefficients. The general form of this partial differential equation is .. math:: a \frac{df(x,y)}{dx} + b \frac{df(x,y)}{dy} + c f(x,y) = G(x,y) where `a`, `b` and `c` are constants and `G(x, y)` can be an arbitrary function in `x` and `y`. The general solution of the PDE is:: >>> from sympy.solvers import pdsolve >>> from sympy.abc import x, y, a, b, c >>> from sympy import Function, pprint >>> f = Function('f') >>> G = Function('G') >>> u = f(x,y) >>> ux = u.diff(x) >>> uy = u.diff(y) >>> genform = a*u + b*ux + c*uy - G(x,y) >>> pprint(genform) d d a*f(x, y) + b*--(f(x, y)) + c*--(f(x, y)) - G(x, y) dx dy >>> pprint(pdsolve(genform, hint='1st_linear_constant_coeff_Integral')) // b*x + c*y \ || / | || | | || | a*xi | || | ------- | || | 2 2 | || | /b*xi + c*eta -b*eta + c*xi\ b + c | || | G|------------, -------------|*e d(xi)| || | | 2 2 2 2 | | || | \ b + c b + c / | || | | || / | || | f(x, y) = ||F(eta) + -------------------------------------------------------|* || 2 2 | \\ b + c / <BLANKLINE> \| || || || || || || || || -a*xi || -------|| 2 2|| b + c || e || || /|eta=-b*y + c*x, xi=b*x + c*y Examples ======== >>> from sympy.solvers.pde import pdsolve >>> from sympy import Function, diff, pprint, exp >>> from sympy.abc import x,y >>> f = Function('f') >>> eq = -2*f(x,y).diff(x) + 4*f(x,y).diff(y) + 5*f(x,y) - exp(x + 3*y) >>> pdsolve(eq) f(x, y) == (F(4*x + 2*y) + exp(x/2 + 4*y)/15)*exp(x/2 - y) References ========== - Viktor Grigoryan, "Partial Differential Equations" Math 124A - Fall 2010, pp.7 """ # TODO : For now homogeneous first order linear PDE's having # two variables are implemented. Once there is support for # solving systems of ODE's, this can be extended to n variables. xi, eta = symbols("xi eta") f = func.func x = func.args[0] y = func.args[1] b = match[match['b']] c = match[match['c']] d = match[match['d']] e = -match[match['e']] expterm = exp(-S(d)/(b**2 + c**2)*xi) functerm = solvefun(eta) solvedict = solve((b*x + c*y - xi, c*x - b*y - eta), x, y) # Integral should remain as it is in terms of xi, # doit() should be done in _handle_Integral. genterm = (1/S(b**2 + c**2))*C.Integral( (1/expterm*e).subs(solvedict), (xi, b*x + c*y)) return Eq(f(x,y), Subs(expterm*(functerm + genterm), (eta, xi), (c*x - b*y, b*x + c*y)))
def transform(self, x, u, inverse=False): r""" Performs a change of variables from `x` to `u` using the relationship given by `x` and `u` which will define the transformations `f` and `F` (which are inverses of each other) as follows: 1) If `x` is a Symbol (which is a variable of integration) then `u` will be interpreted as some function, f(u), with inverse F(u). This, in effect, just makes the substitution of x with f(x). 2) If `u` is a Symbol then `x` will be interpreted as some function, F(x), with inverse f(u). This is commonly referred to as u-substitution. The `inverse` option will reverse `x` and `u`. It is a deprecated option since `x` and `u` can just be passed in reverse order. Once f and F have been identified, the transformation is made as follows: .. math:: \int_a^b x \mathrm{d}x \rightarrow \int_{F(a)}^{F(b)} f(x) \frac{\mathrm{d}}{\mathrm{d}x} where `F(x)` is the inverse of `f(x)` and the limits and integrand have been corrected so as to retain the same value after integration. Notes ===== The mappings, F(x) or f(u), must lead to a unique integral. Linear or rational linear expression, `2*x`, `1/x` and `sqrt(x)`, will always work; quadratic expressions like `x**2 - 1` are acceptable as long as the resulting integrand does not depend on the sign of the solutions (see examples). The integral will be returned unchanged if `x` is not a variable of integration. `x` must be (or contain) only one of of the integration variables. If `u` has more than one free symbol then it should be sent as a tuple (`u`, `uvar`) where `uvar` identifies which variable is replacing the integration variable. XXX can it contain another integration variable? Examples ======== >>> from sympy.abc import a, b, c, d, x, u, y >>> from sympy import Integral, S, cos, sqrt >>> i = Integral(x*cos(x**2 - 1), (x, 0, 1)) transform can change the variable of integration >>> i.transform(x, u) Integral(u*cos(u**2 - 1), (u, 0, 1)) transform can perform u-substitution as long as a unique integrand is obtained: >>> i.transform(x**2 - 1, u) Integral(cos(u)/2, (u, -1, 0)) This attempt fails because x = +/-sqrt(u + 1) and the sign does not cancel out of the integrand: >>> Integral(cos(x**2 - 1), (x, 0, 1)).transform(x**2 - 1, u) Traceback (most recent call last): ... ValueError: The mapping between F(x) and f(u) did not give a unique integrand. transform can do a substitution. Here, the previous result is transformed back into the original expression using "u-substitution": >>> ui = _ >>> _.transform(sqrt(u + 1), x) == i True We can accomplish the same with a regular substitution: >>> ui.transform(u, x**2 - 1) == i True If the `x` does not contain a symbol of integration then the integral will be returned unchanged. Integral `i` does not have an integration variable `a` so no change is made: >>> i.transform(a, x) == i True When `u` has more than one free symbol the symbol that is replacing `x` must be identified by passing `u` as a tuple: >>> Integral(x, (x, 0, 1)).transform(x, (u + a, u)) Integral(a + u, (u, -a, -a + 1)) >>> Integral(x, (x, 0, 1)).transform(x, (u + a, a)) Integral(a + u, (a, -u, -u + 1)) See Also ======== variables : Lists the integration variables as_dummy : Replace integration variables with dummy ones """ if inverse: # when this is removed, update the docstring from sympy.utilities.exceptions import SymPyDeprecationWarning SymPyDeprecationWarning( feature="transform(x, f(x), inverse=True)", useinstead="transform(f(x), x)", issue=3380, deprecated_since_version="0.7.2", ).warn() # in the old style x and u contained the same variable so # don't worry about using the old-style feature with the # new style input...but it will still work: # i.transform(x, u).transform(x, u, inverse=True) -> i x, u = u, x d = Dummy('d') xfree = x.free_symbols.intersection(self.variables) if len(xfree) > 1: raise ValueError( 'F(x) can only contain one of: %s' % self.variables) xvar = xfree.pop() if xfree else d if xvar not in self.variables: return self u = sympify(u) if isinstance(u, Expr): ufree = u.free_symbols if len(ufree) != 1: raise ValueError(filldedent(''' When f(u) has more than one free symbol, the one replacing x must be identified: pass f(u) as (f(u), u)''')) uvar = ufree.pop() else: u, uvar = u if uvar not in u.free_symbols: raise ValueError(filldedent(''' Expecting a tuple (expr, symbol) where symbol identified a free symbol in expr, but symbol is not in expr's free symbols.''')) if not isinstance(uvar, Symbol): raise ValueError(filldedent(''' Expecting a tuple (expr, symbol) but didn't get a symbol; got %s''' % uvar)) if x.is_Symbol and u.is_Symbol: return self.xreplace({x: u}) if not x.is_Symbol and not u.is_Symbol: raise ValueError('either x or u must be a symbol') if uvar == xvar: return self.transform(x, u.subs(uvar, d)).xreplace({d: uvar}) if uvar in self.limits: raise ValueError(filldedent(''' u must contain the same variable as in x or a variable that is not already an integration variable''')) if not x.is_Symbol: F = [x.subs(xvar, d)] soln = solve(u - x, xvar, check=False) if not soln: raise ValueError('no solution for solve(F(x) - f(u), x)') f = [fi.subs(uvar, d) for fi in soln] else: f = [u.subs(uvar, d)] pdiff, reps = posify(u - x) puvar = uvar.subs([(v, k) for k, v in reps.items()]) soln = [s.subs(reps) for s in solve(pdiff, puvar)] if not soln: raise ValueError('no solution for solve(F(x) - f(u), u)') F = [fi.subs(xvar, d) for fi in soln] newfuncs = set([(self.function.subs(xvar, fi)*fi.diff(d) ).subs(d, uvar) for fi in f]) if len(newfuncs) > 1: raise ValueError(filldedent(''' The mapping between F(x) and f(u) did not give a unique integrand.''')) newfunc = newfuncs.pop() def _calc_limit_1(F, a, b): """ replace d with a, using subs if possible, otherwise limit where sign of b is considered """ wok = F.subs(d, a) if wok is S.NaN or wok.is_bounded is False and a.is_bounded: return limit(sign(b)*F, d, a) return wok def _calc_limit(a, b): """ replace d with a, using subs if possible, otherwise limit where sign of b is considered """ avals = list(set([_calc_limit_1(Fi, a, b) for Fi in F])) if len(avals) > 1: raise ValueError(filldedent(''' The mapping between F(x) and f(u) did not give a unique limit.''')) return avals[0] newlimits = [] for xab in self.limits: sym = xab[0] if sym == xvar: if len(xab) == 3: a, b = xab[1:] a, b = _calc_limit(a, b), _calc_limit(b, a) if a > b: a, b = b, a newfunc = -newfunc newlimits.append((uvar, a, b)) elif len(xab) == 2: a = _calc_limit(xab[1], 1) newlimits.append((uvar, a)) else: newlimits.append(uvar) else: newlimits.append(xab) return self.func(newfunc, *newlimits)
def heurisch_wrapper(f, x, rewrite=False, hints=None, mappings=None, retries=3, degree_offset=0, unnecessary_permutations=None, _try_heurisch=None): """ A wrapper around the heurisch integration algorithm. Explanation =========== This method takes the result from heurisch and checks for poles in the denominator. For each of these poles, the integral is reevaluated, and the final integration result is given in terms of a Piecewise. Examples ======== >>> from sympy.core import symbols >>> from sympy.functions import cos >>> from sympy.integrals.heurisch import heurisch, heurisch_wrapper >>> n, x = symbols('n x') >>> heurisch(cos(n*x), x) sin(n*x)/n >>> heurisch_wrapper(cos(n*x), x) Piecewise((sin(n*x)/n, Ne(n, 0)), (x, True)) See Also ======== heurisch """ from sympy.solvers.solvers import solve, denoms f = sympify(f) if x not in f.free_symbols: return f*x res = heurisch(f, x, rewrite, hints, mappings, retries, degree_offset, unnecessary_permutations, _try_heurisch) if not isinstance(res, Basic): return res # We consider each denominator in the expression, and try to find # cases where one or more symbolic denominator might be zero. The # conditions for these cases are stored in the list slns. slns = [] for d in denoms(res): try: slns += solve(d, dict=True, exclude=(x,)) except NotImplementedError: pass if not slns: return res slns = list(uniq(slns)) # Remove the solutions corresponding to poles in the original expression. slns0 = [] for d in denoms(f): try: slns0 += solve(d, dict=True, exclude=(x,)) except NotImplementedError: pass slns = [s for s in slns if s not in slns0] if not slns: return res if len(slns) > 1: eqs = [] for sub_dict in slns: eqs.extend([Eq(key, value) for key, value in sub_dict.items()]) slns = solve(eqs, dict=True, exclude=(x,)) + slns # For each case listed in the list slns, we reevaluate the integral. pairs = [] for sub_dict in slns: expr = heurisch(f.subs(sub_dict), x, rewrite, hints, mappings, retries, degree_offset, unnecessary_permutations, _try_heurisch) cond = And(*[Eq(key, value) for key, value in sub_dict.items()]) generic = Or(*[Ne(key, value) for key, value in sub_dict.items()]) if expr is None: expr = integrate(f.subs(sub_dict),x) pairs.append((expr, cond)) # If there is one condition, put the generic case first. Otherwise, # doing so may lead to longer Piecewise formulas if len(pairs) == 1: pairs = [(heurisch(f, x, rewrite, hints, mappings, retries, degree_offset, unnecessary_permutations, _try_heurisch), generic), (pairs[0][0], True)] else: pairs.append((heurisch(f, x, rewrite, hints, mappings, retries, degree_offset, unnecessary_permutations, _try_heurisch), True)) return Piecewise(*pairs)
def solve_univariate_inequality(expr, gen, relational=True): """Solves a real univariate inequality. Examples ======== >>> from sympy.solvers.inequalities import solve_univariate_inequality >>> from sympy.core.symbol import Symbol >>> x = Symbol('x') >>> solve_univariate_inequality(x**2 >= 4, x) Or(And(-oo < x, x <= -2), And(2 <= x, x < oo)) >>> solve_univariate_inequality(x**2 >= 4, x, relational=False) (-oo, -2] U [2, oo) """ from sympy.solvers.solvers import solve, denoms # This keeps the function independent of the assumptions about `gen`. # `solveset` makes sure this function is called only when the domain is # real. d = Dummy(real=True) expr = expr.subs(gen, d) _gen = gen gen = d if expr is S.true: rv = S.Reals elif expr is S.false: rv = S.EmptySet else: e = expr.lhs - expr.rhs parts = n, d = e.as_numer_denom() if all(i.is_polynomial(gen) for i in parts): solns = solve(n, gen, check=False) singularities = solve(d, gen, check=False) else: solns = solve(e, gen, check=False) singularities = [] for d in denoms(e): singularities.extend(solve(d, gen)) include_x = expr.func(0, 0) def valid(x): v = e.subs(gen, x) try: r = expr.func(v, 0) except TypeError: r = S.false if r in (S.true, S.false): return r if v.is_real is False: return S.false else: v = v.n(2) if v.is_comparable: return expr.func(v, 0) return S.false start = S.NegativeInfinity sol_sets = [S.EmptySet] try: reals = _nsort(set(solns + singularities), separated=True)[0] except NotImplementedError: raise NotImplementedError( 'sorting of these roots is not supported') for x in reals: end = x if end in [S.NegativeInfinity, S.Infinity]: if valid(S(0)): sol_sets.append(Interval(start, S.Infinity, True, True)) break if valid((start + end) / 2 if start != S.NegativeInfinity else end - 1): sol_sets.append(Interval(start, end, True, True)) if x in singularities: singularities.remove(x) elif include_x: sol_sets.append(FiniteSet(x)) start = end end = S.Infinity if valid(start + 1): sol_sets.append(Interval(start, end, True, True)) rv = Union(*sol_sets).subs(gen, _gen) return rv if not relational else rv.as_relational(_gen)
def checkpdesol(pde, sol, func=None, solve_for_func=True): """ Checks if the given solution satisfies the partial differential equation. pde is the partial differential equation which can be given in the form of an equation or an expression. sol is the solution for which the pde is to be checked. This can also be given in an equation or an expression form. If the function is not provided, the helper function _preprocess from deutils is used to identify the function. If a sequence of solutions is passed, the same sort of container will be used to return the result for each solution. The following methods are currently being implemented to check if the solution satisfies the PDE: 1. Directly substitute the solution in the PDE and check. If the solution hasn't been solved for f, then it will solve for f provided solve_for_func hasn't been set to False. If the solution satisfies the PDE, then a tuple (True, 0) is returned. Otherwise a tuple (False, expr) where expr is the value obtained after substituting the solution in the PDE. However if a known solution returns False, it may be due to the inability of doit() to simplify it to zero. Examples ======== >>> from sympy import Function, symbols, diff >>> from sympy.solvers.pde import checkpdesol, pdsolve >>> x, y = symbols('x y') >>> f = Function('f') >>> eq = 2*f(x,y) + 3*f(x,y).diff(x) + 4*f(x,y).diff(y) >>> sol = pdsolve(eq) >>> assert checkpdesol(eq, sol)[0] >>> eq = x*f(x,y) + f(x,y).diff(x) >>> checkpdesol(eq, sol) (False, (x*F(4*x - 3*y) - 6*F(4*x - 3*y)/25 + 4*Subs(Derivative(F(_xi_1), _xi_1), (_xi_1,), (4*x - 3*y,)))*exp(-6*x/25 - 8*y/25)) """ # Converting the pde into an equation if not isinstance(pde, Equality): pde = Eq(pde, 0) # If no function is given, try finding the function present. if func is None: try: _, func = _preprocess(pde.lhs) except ValueError: funcs = [ s.atoms(AppliedUndef) for s in (sol if is_sequence(sol, set) else [sol]) ] funcs = set().union(funcs) if len(funcs) != 1: raise ValueError( 'must pass func arg to checkpdesol for this case.') func = funcs.pop() # If the given solution is in the form of a list or a set # then return a list or set of tuples. if is_sequence(sol, set): return type(sol)([ checkpdesol(pde, i, func=func, solve_for_func=solve_for_func) for i in sol ]) # Convert solution into an equation if not isinstance(sol, Equality): sol = Eq(func, sol) elif sol.rhs == func: sol = sol.reversed # Try solving for the function solved = sol.lhs == func and not sol.rhs.has(func) if solve_for_func and not solved: solved = solve(sol, func) if solved: if len(solved) == 1: return checkpdesol(pde, Eq(func, solved[0]), func=func, solve_for_func=False) else: return checkpdesol(pde, [Eq(func, t) for t in solved], func=func, solve_for_func=False) # try direct substitution of the solution into the PDE and simplify if sol.lhs == func: pde = pde.lhs - pde.rhs s = simplify(pde.subs(func, sol.rhs).doit()) return s is S.Zero, s raise NotImplementedError( filldedent(''' Unable to test if %s is a solution to %s.''' % (sol, pde)))
def pde_1st_linear_constant_coeff(eq, func, order, match, solvefun): r""" Solves a first order linear partial differential equation with constant coefficients. The general form of this partial differential equation is .. math:: a \frac{df(x,y)}{dx} + b \frac{df(x,y)}{dy} + c f(x,y) = G(x,y) where `a`, `b` and `c` are constants and `G(x, y)` can be an arbitrary function in `x` and `y`. The general solution of the PDE is:: >>> from sympy.solvers import pdsolve >>> from sympy.abc import x, y, a, b, c >>> from sympy import Function, pprint >>> f = Function('f') >>> G = Function('G') >>> u = f(x,y) >>> ux = u.diff(x) >>> uy = u.diff(y) >>> genform = a*u + b*ux + c*uy - G(x,y) >>> pprint(genform) d d a*f(x, y) + b*--(f(x, y)) + c*--(f(x, y)) - G(x, y) dx dy >>> pprint(pdsolve(genform, hint='1st_linear_constant_coeff_Integral')) // b*x + c*y \ || / | || | | || | a*xi | || | ------- | || | 2 2 | || | /b*xi + c*eta -b*eta + c*xi\ b + c | || | G|------------, -------------|*e d(xi)| || | | 2 2 2 2 | | || | \ b + c b + c / | || | | || / | || | f(x, y) = ||F(eta) + -------------------------------------------------------|* || 2 2 | \\ b + c / <BLANKLINE> \| || || || || || || || || -a*xi || -------|| 2 2|| b + c || e || || /|eta=-b*y + c*x, xi=b*x + c*y Examples ======== >>> from sympy.solvers.pde import pdsolve >>> from sympy import Function, diff, pprint, exp >>> from sympy.abc import x,y >>> f = Function('f') >>> eq = -2*f(x,y).diff(x) + 4*f(x,y).diff(y) + 5*f(x,y) - exp(x + 3*y) >>> pdsolve(eq) Eq(f(x, y), (F(4*x + 2*y) + exp(x/2 + 4*y)/15)*exp(x/2 - y)) References ========== - Viktor Grigoryan, "Partial Differential Equations" Math 124A - Fall 2010, pp.7 """ # TODO : For now homogeneous first order linear PDE's having # two variables are implemented. Once there is support for # solving systems of ODE's, this can be extended to n variables. xi, eta = symbols("xi eta") f = func.func x = func.args[0] y = func.args[1] b = match[match['b']] c = match[match['c']] d = match[match['d']] e = -match[match['e']] expterm = exp(-S(d) / (b**2 + c**2) * xi) functerm = solvefun(eta) solvedict = solve((b * x + c * y - xi, c * x - b * y - eta), x, y) # Integral should remain as it is in terms of xi, # doit() should be done in _handle_Integral. genterm = (1 / S(b**2 + c**2)) * Integral( (1 / expterm * e).subs(solvedict), (xi, b * x + c * y)) return Eq( f(x, y), Subs(expterm * (functerm + genterm), (eta, xi), (c * x - b * y, b * x + c * y)))
def pde_1st_linear_variable_coeff(eq, func, order, match, solvefun): r""" Solves a first order linear partial differential equation with variable coefficients. The general form of this partial differential equation is .. math:: a(x, y) \frac{df(x, y)}{dx} + a(x, y) \frac{df(x, y)}{dy} + c(x, y) f(x, y) - G(x, y) where `a(x, y)`, `b(x, y)`, `c(x, y)` and `G(x, y)` are arbitrary functions in `x` and `y`. This PDE is converted into an ODE by making the following transformation. 1] `\xi` as `x` 2] `\eta` as the constant in the solution to the differential equation `\frac{dy}{dx} = -\frac{b}{a}` Making the following substitutions reduces it to the linear ODE .. math:: a(\xi, \eta)\frac{du}{d\xi} + c(\xi, \eta)u - d(\xi, \eta) = 0 which can be solved using dsolve. The general form of this PDE is:: >>> from sympy.solvers.pde import pdsolve >>> from sympy.abc import x, y >>> from sympy import Function, pprint >>> a, b, c, G, f= [Function(i) for i in ['a', 'b', 'c', 'G', 'f']] >>> u = f(x,y) >>> ux = u.diff(x) >>> uy = u.diff(y) >>> genform = a(x, y)*u + b(x, y)*ux + c(x, y)*uy - G(x,y) >>> pprint(genform) d d -G(x, y) + a(x, y)*f(x, y) + b(x, y)*--(f(x, y)) + c(x, y)*--(f(x, y)) dx dy Examples ======== >>> from sympy.solvers.pde import pdsolve >>> from sympy import Function, diff, pprint, exp >>> from sympy.abc import x,y >>> f = Function('f') >>> eq = x*(u.diff(x)) - y*(u.diff(y)) + y**2*u - y**2 >>> pdsolve(eq) Eq(f(x, y), F(x*y)*exp(y**2/2) + 1) References ========== - Viktor Grigoryan, "Partial Differential Equations" Math 124A - Fall 2010, pp.7 """ from sympy.integrals.integrals import integrate from sympy.solvers.ode import dsolve xi, eta = symbols("xi eta") f = func.func x = func.args[0] y = func.args[1] b = match[match['b']] c = match[match['c']] d = match[match['d']] e = -match[match['e']] if not d: # To deal with cases like b*ux = e or c*uy = e if not (b and c): if c: try: tsol = integrate(e / c, y) except NotImplementedError: raise NotImplementedError("Unable to find a solution" " due to inability of integrate") else: return Eq(f(x, y), solvefun(x) + tsol) if b: try: tsol = integrate(e / b, x) except NotImplementedError: raise NotImplementedError("Unable to find a solution" " due to inability of integrate") else: return Eq(f(x, y), solvefun(y) + tsol) if not c: # To deal with cases when c is 0, a simpler method is used. # The PDE reduces to b*(u.diff(x)) + d*u = e, which is a linear ODE in x plode = f(x).diff(x) * b + d * f(x) - e sol = dsolve(plode, f(x)) syms = sol.free_symbols - plode.free_symbols - {x, y} rhs = _simplify_variable_coeff(sol.rhs, syms, solvefun, y) return Eq(f(x, y), rhs) if not b: # To deal with cases when b is 0, a simpler method is used. # The PDE reduces to c*(u.diff(y)) + d*u = e, which is a linear ODE in y plode = f(y).diff(y) * c + d * f(y) - e sol = dsolve(plode, f(y)) syms = sol.free_symbols - plode.free_symbols - {x, y} rhs = _simplify_variable_coeff(sol.rhs, syms, solvefun, x) return Eq(f(x, y), rhs) dummy = Function('d') h = (c / b).subs(y, dummy(x)) sol = dsolve(dummy(x).diff(x) - h, dummy(x)) if isinstance(sol, list): sol = sol[0] solsym = sol.free_symbols - h.free_symbols - {x, y} if len(solsym) == 1: solsym = solsym.pop() etat = (solve(sol, solsym)[0]).subs(dummy(x), y) ysub = solve(eta - etat, y)[0] deq = (b * (f(x).diff(x)) + d * f(x) - e).subs(y, ysub) final = (dsolve(deq, f(x), hint='1st_linear')).rhs if isinstance(final, list): final = final[0] finsyms = final.free_symbols - deq.free_symbols - {x, y} rhs = _simplify_variable_coeff(final, finsyms, solvefun, etat) return Eq(f(x, y), rhs) else: raise NotImplementedError( "Cannot solve the partial differential equation due" " to inability of constantsimp")
def heurisch_wrapper(f, x, rewrite=False, hints=None, mappings=None, retries=3, degree_offset=0, unnecessary_permutations=None): """ A wrapper around the heurisch integration algorithm. This method takes the result from heurisch and checks for poles in the denominator. For each of these poles, the integral is reevaluated, and the final integration result is given in terms of a Piecewise. Examples ======== >>> from sympy.core import symbols >>> from sympy.functions import cos >>> from sympy.integrals.heurisch import heurisch, heurisch_wrapper >>> n, x = symbols('n x') >>> heurisch(cos(n*x), x) sin(n*x)/n >>> heurisch_wrapper(cos(n*x), x) Piecewise((x, n == 0), (sin(n*x)/n, True)) See Also ======== heurisch """ f = sympify(f) if x not in f.free_symbols: return f*x res = heurisch(f, x, rewrite, hints, mappings, retries, degree_offset, unnecessary_permutations) if not isinstance(res, Basic): return res # We consider each denominator in the expression, and try to find # cases where one or more symbolic denominator might be zero. The # conditions for these cases are stored in the list slns. slns = [] for d in denoms(res): try: slns += solve(d, dict=True, exclude=(x,)) except NotImplementedError: pass if not slns: return res slns = list(uniq(slns)) # Remove the solutions corresponding to poles in the original expression. slns0 = [] for d in denoms(f): try: slns0 += solve(d, dict=True, exclude=(x,)) except NotImplementedError: pass slns = [s for s in slns if s not in slns0] if not slns: return res if len(slns) > 1: eqs = [] for sub_dict in slns: eqs.extend([Eq(key, value) for key, value in sub_dict.items()]) slns = solve(eqs, dict=True, exclude=(x,)) + slns # For each case listed in the list slns, we reevaluate the integral. pairs = [] for sub_dict in slns: expr = heurisch(f.subs(sub_dict), x, rewrite, hints, mappings, retries, degree_offset, unnecessary_permutations) cond = And(*[Eq(key, value) for key, value in sub_dict.items()]) pairs.append((expr, cond)) pairs.append((heurisch(f, x, rewrite, hints, mappings, retries, degree_offset, unnecessary_permutations), True)) return Piecewise(*pairs)
def test_issue_8783(): x = Symbol('x') assert solve(x > -oo) == And(-oo < x, x < oo) assert solve(x < oo) == And(-oo < x, x < oo) assert solve(x > oo) == False assert solve(x < -oo) == False