def test_nocache(clear_imports, monkeypatch): """Regression tests with DIOFANT_USE_CACHE=False. """ monkeypatch.setenv('DIOFANT_USE_CACHE', 'False') from diofant.core.cache import CACHE from diofant.core.symbol import Symbol from diofant.functions import sin, sqrt # test that we don't use cache assert CACHE == [] x = Symbol('x') assert CACHE == [] # issue sympy/sympy#8840 expr = (1 + x) * x # not raises # issue sympy/sympy#9413 (2 * x).is_complex # not raises # see commit c459d18 sin(x + x) # see commit 53dd1eb mx = -Symbol('x', negative=False) assert mx.is_positive is not True px = 2 * Symbol('x', positive=False) assert px.is_positive is not True # see commit 2eaaba2 s = 1 / sqrt(x**2) y = Symbol('y') result = s.subs(sqrt(x**2), y) assert result == 1 / y
def __new__(cls, name, index, system, pretty_str, latex_str): name = str(name) pretty_str = str(pretty_str) latex_str = str(latex_str) from diofant.vector.coordsysrect import CoordSysCartesian obj = super(BaseScalar, cls).__new__(cls, name) if not isinstance(system, CoordSysCartesian): raise TypeError("system should be a CoordSysCartesian") if index not in range(0, 3): raise ValueError("Invalid index specified.") # The _id is used for equating purposes, and for hashing obj._id = (index, system) obj._name = name obj._pretty_form = pretty_str obj._latex_form = latex_str obj._system = system # Change the args for the object obj._args = tuple([ Symbol(name), Integer(index), system, Symbol(pretty_str), Symbol(latex_str) ]) return obj
def test_root(): from diofant.abc import x n = Symbol('n', integer=True) k = Symbol('k', integer=True) assert root(2, 2) == sqrt(2) assert root(2, 1) == 2 assert root(2, 3) == 2**Rational(1, 3) assert root(2, 3) == cbrt(2) assert root(2, -5) == 2**Rational(4, 5) / 2 assert root(-2, 1) == -2 assert root(-2, 2) == sqrt(2) * I assert root(-2, 1) == -2 assert root(x, 2) == sqrt(x) assert root(x, 1) == x assert root(x, 3) == x**Rational(1, 3) assert root(x, 3) == cbrt(x) assert root(x, -5) == x**Rational(-1, 5) assert root(x, n) == x**(1 / n) assert root(x, -n) == x**(-1 / n) assert root(x, n, k) == x**(1 / n) * (-1)**(2 * k / n)
def test_core_symbol(): # make the Symbol a unique name that doesn't class with any other # testing variable in this file since after this test the symbol # having the same name will be cached as noncommutative for c in (Dummy, Dummy("x", commutative=False), Symbol, Symbol("_sympyissue_6229", commutative=False), Wild, Wild("x")): check(c)
def test_issue_8413(): x = Symbol('x', extended_real=True) # we can't evaluate in general because non-reals are not # comparable: Min(floor(3.2 + I), 3.2 + I) -> ValueError assert Min(floor(x), x) == floor(x) assert Min(ceiling(x), x) == x assert Max(floor(x), x) == x assert Max(ceiling(x), x) == ceiling(x)
def doprint(self, expr, assign_to=None): """ Print the expression as code. Parameters ---------- expr : Expression The expression to be printed. assign_to : Symbol, MatrixSymbol, or string (optional) If provided, the printed code will set the expression to a variable with name ``assign_to``. """ from diofant.matrices.expressions.matexpr import MatrixSymbol if isinstance(assign_to, str): if expr.is_Matrix: assign_to = MatrixSymbol(assign_to, *expr.shape) else: assign_to = Symbol(assign_to) elif not isinstance(assign_to, (Basic, type(None))): raise TypeError("{0} cannot assign to object of type {1}".format( type(self).__name__, type(assign_to))) if assign_to: expr = Assignment(assign_to, expr) else: # _sympify is not enough b/c it errors on iterables expr = sympify(expr) # keep a set of expressions that are not strictly translatable to Code # and number constants that must be declared and initialized self._not_supported = set() self._number_symbols = set() lines = self._print(expr).splitlines() # format the output if self._settings["human"]: frontlines = [] if len(self._not_supported) > 0: frontlines.append(self._get_comment( "Not supported in {0}:".format(self.language))) for expr in sorted(self._not_supported, key=str): frontlines.append(self._get_comment(type(expr).__name__)) for name, value in sorted(self._number_symbols, key=str): frontlines.append(self._declare_number_const(name, value)) lines = frontlines + lines lines = self._format_code(lines) result = "\n".join(lines) else: lines = self._format_code(lines) result = (self._number_symbols, self._not_supported, "\n".join(lines)) del self._not_supported del self._number_symbols return result
def _roots_quartic_euler(p, q, r, a): """ Descartes-Euler solution of the quartic equation Parameters ========== p, q, r: coefficients of ``x**4 + p*x**2 + q*x + r`` a: shift of the roots Notes ===== This is a helper function for ``roots_quartic``. Look for solutions of the form :: ``x1 = sqrt(R) - sqrt(A + B*sqrt(R))`` ``x2 = -sqrt(R) - sqrt(A - B*sqrt(R))`` ``x3 = -sqrt(R) + sqrt(A - B*sqrt(R))`` ``x4 = sqrt(R) + sqrt(A + B*sqrt(R))`` To satisfy the quartic equation one must have ``p = -2*(R + A); q = -4*B*R; r = (R - A)**2 - B**2*R`` so that ``R`` must satisfy the Descartes-Euler resolvent equation ``64*R**3 + 32*p*R**2 + (4*p**2 - 16*r)*R - q**2 = 0`` If the resolvent does not have a rational solution, return None; in that case it is likely that the Ferrari method gives a simpler solution. Examples ======== >>> from diofant import Rational, Integer >>> p, q, r = -Rational(64, 5), -Rational(512, 125), -Rational(1024, 3125) >>> _roots_quartic_euler(p, q, r, Integer(0))[0] -sqrt(32*sqrt(5)/125 + 16/5) + 4*sqrt(5)/5 """ # solve the resolvent equation x = Symbol('x') eq = 64*x**3 + 32*p*x**2 + (4*p**2 - 16*r)*x - q**2 xsols = list(roots(Poly(eq, x), cubics=False).keys()) xsols = [sol for sol in xsols if sol.is_rational] if not xsols: return R = max(xsols) c1 = sqrt(R) B = -q*c1/(4*R) A = -R - p/2 c2 = sqrt(A + B) c3 = sqrt(A - B) return [c1 - c2 - a, -c1 - c3 - a, -c1 + c3 - a, c1 + c2 - a]
def test_nocache(clear_imports, monkeypatch): """Regression tests with DIOFANT_USE_CACHE=False. """ monkeypatch.setenv('DIOFANT_USE_CACHE', 'False') from diofant.core.cache import CACHE from diofant.core.symbol import Symbol from diofant.functions import sin, sqrt, exp, sinh # test that we don't use cache assert CACHE == [] x = Symbol('x') assert CACHE == [] # issue sympy/sympy#8840 (1 + x)*x # not raises # issue sympy/sympy#9413 (2*x).is_complex # not raises # see commit c459d18 sin(x + x) # not raises # see commit 53dd1eb mx = -Symbol('x', negative=False) assert mx.is_positive is not True px = 2*Symbol('x', positive=False) assert px.is_positive is not True # see commit 2eaaba2 s = 1/sqrt(x**2) y = Symbol('y') result = s.subs(sqrt(x**2), y) assert result == 1/y # problem from https://groups.google.com/forum/#!topic/sympy/LkTMQKC_BOw # see commit c459d18 a = Symbol('a', positive=True) f = exp(x*(-a - 1)) g = sinh(x) f*g # not raises
def test_real_root(): assert real_root(-8, 3) == -2 assert real_root(-16, 4) == root(-16, 4) r = root(-7, 4) assert real_root(r) == r r1 = root(-1, 3) r2 = r1**2 r3 = root(-1, 4) assert real_root(r1 + r2 + r3) == -1 + r2 + r3 assert real_root(root(-2, 3)) == -root(2, 3) assert real_root(-8., 3) == -2 x = Symbol('x') n = Symbol('n') g = real_root(x, n) assert g.subs(dict(x=-8, n=3)) == -2 assert g.subs(dict(x=8, n=3)) == 2 # give principle root if there is no real root -- if this is not desired # then maybe a Root class is needed to raise an error instead assert g.subs(dict(x=I, n=3)) == cbrt(I) assert g.subs(dict(x=-8, n=2)) == sqrt(-8) assert g.subs(dict(x=I, n=2)) == sqrt(I)
from itertools import permutations import pytest from diofant.combinatorics.permutations import (Cycle, Permutation, _af_parity, _af_rmul, _af_rmuln) from diofant.core.symbol import Symbol __all__ = () rmul = Permutation.rmul a = Symbol('a', integer=True) def test_Permutation(): # don't auto fill 0 pytest.raises(ValueError, lambda: Permutation([1])) p = Permutation([0, 1, 2, 3]) # call as bijective assert [p(i) for i in range(p.size)] == list(p) # call as operator assert p(list(range(p.size))) == list(p) # call as function assert list(p(1, 2)) == [0, 2, 1, 3] # conversion to list assert list(p) == list(range(4)) assert Permutation(size=4) == Permutation(3) assert Permutation(Permutation(3), size=5) == Permutation(4) # cycle form with size assert Permutation([[1, 2]], size=4) == Permutation([[1, 2], [0], [3]]) # random generation
def rsolve_poly(coeffs, f, n, **hints): """ Given linear recurrence operator `\operatorname{L}` of order `k` with polynomial coefficients and inhomogeneous equation `\operatorname{L} y = f`, where `f` is a polynomial, we seek for all polynomial solutions over field `K` of characteristic zero. The algorithm performs two basic steps: (1) Compute degree `N` of the general polynomial solution. (2) Find all polynomials of degree `N` or less of `\operatorname{L} y = f`. There are two methods for computing the polynomial solutions. If the degree bound is relatively small, i.e. it's smaller than or equal to the order of the recurrence, then naive method of undetermined coefficients is being used. This gives system of algebraic equations with `N+1` unknowns. In the other case, the algorithm performs transformation of the initial equation to an equivalent one, for which the system of algebraic equations has only `r` indeterminates. This method is quite sophisticated (in comparison with the naive one) and was invented together by Abramov, Bronstein and Petkovšek. It is possible to generalize the algorithm implemented here to the case of linear q-difference and differential equations. Lets say that we would like to compute `m`-th Bernoulli polynomial up to a constant. For this we can use `b(n+1) - b(n) = m n^{m-1}` recurrence, which has solution `b(n) = B_m + C`. For example: >>> from diofant import Symbol, rsolve_poly >>> n = Symbol('n', integer=True) >>> rsolve_poly([-1, 1], 4*n**3, n) C0 + n**4 - 2*n**3 + n**2 References ========== .. [1] S. A. Abramov, M. Bronstein and M. Petkovšek, On polynomial solutions of linear operator equations, in: T. Levelt, ed., Proc. ISSAC '95, ACM Press, New York, 1995, 290-296. .. [2] M. Petkovšek, Hypergeometric solutions of linear recurrences with polynomial coefficients, J. Symbolic Computation, 14 (1992), 243-264. .. [3] M. Petkovšek, H. S. Wilf, D. Zeilberger, A = B, 1996. """ f = sympify(f) if not f.is_polynomial(n): return homogeneous = f.is_zero r = len(coeffs) - 1 coeffs = [Poly(coeff, n) for coeff in coeffs] g = gcd_list(coeffs + [f], n, polys=True) if not g.is_ground: coeffs = [quo(c, g, n, polys=False) for c in coeffs] f = quo(f, g, n, polys=False) polys = [Poly(0, n)] * (r + 1) terms = [(S.Zero, S.NegativeInfinity)] * (r + 1) for i in range(0, r + 1): for j in range(i, r + 1): polys[i] += coeffs[j] * binomial(j, i) if not polys[i].is_zero: (exp, ), coeff = polys[i].LT() terms[i] = (coeff, exp) d = b = terms[0][1] for i in range(1, r + 1): if terms[i][1] > d: d = terms[i][1] if terms[i][1] - i > b: b = terms[i][1] - i d, b = int(d), int(b) x = Dummy('x') degree_poly = S.Zero for i in range(0, r + 1): if terms[i][1] - i == b: degree_poly += terms[i][0] * FallingFactorial(x, i) nni_roots = list( roots(degree_poly, x, filter='Z', predicate=lambda r: r >= 0).keys()) if nni_roots: N = [max(nni_roots)] else: N = [] if homogeneous: N += [-b - 1] else: N += [f.as_poly(n).degree() - b, -b - 1] N = int(max(N)) if N < 0: if homogeneous: if hints.get('symbols', False): return S.Zero, [] else: return S.Zero else: return if N <= r: C = [] y = E = S.Zero for i in range(0, N + 1): C.append(Symbol('C' + str(i))) y += C[i] * n**i for i in range(0, r + 1): E += coeffs[i].as_expr() * y.subs(n, n + i) solutions = solve_undetermined_coeffs(E - f, C, n) if solutions is not None: C = [c for c in C if (c not in solutions)] result = y.subs(solutions) else: return # TBD else: A = r U = N + A + b + 1 nni_roots = list( roots(polys[r], filter='Z', predicate=lambda r: r >= 0).keys()) if nni_roots != []: a = max(nni_roots) + 1 else: a = S.Zero def _zero_vector(k): return [S.Zero] * k def _one_vector(k): return [S.One] * k def _delta(p, k): B = S.One D = p.subs(n, a + k) for i in range(1, k + 1): B *= -Rational(k - i + 1, i) D += B * p.subs(n, a + k - i) return D alpha = {} for i in range(-A, d + 1): I = _one_vector(d + 1) for k in range(1, d + 1): I[k] = I[k - 1] * (x + i - k + 1) / k alpha[i] = S.Zero for j in range(0, A + 1): for k in range(0, d + 1): B = binomial(k, i + j) D = _delta(polys[j].as_expr(), k) alpha[i] += I[k] * B * D V = Matrix(U, A, lambda i, j: int(i == j)) if homogeneous: for i in range(A, U): v = _zero_vector(A) for k in range(1, A + b + 1): if i - k < 0: break B = alpha[k - A].subs(x, i - k) for j in range(0, A): v[j] += B * V[i - k, j] denom = alpha[-A].subs(x, i) for j in range(0, A): V[i, j] = -v[j] / denom else: G = _zero_vector(U) for i in range(A, U): v = _zero_vector(A) g = S.Zero for k in range(1, A + b + 1): if i - k < 0: break B = alpha[k - A].subs(x, i - k) for j in range(0, A): v[j] += B * V[i - k, j] g += B * G[i - k] denom = alpha[-A].subs(x, i) for j in range(0, A): V[i, j] = -v[j] / denom G[i] = (_delta(f, i - A) - g) / denom P, Q = _one_vector(U), _zero_vector(A) for i in range(1, U): P[i] = (P[i - 1] * (n - a - i + 1) / i).expand() for i in range(0, A): Q[i] = Add(*[(v * p).expand() for v, p in zip(V[:, i], P)]) if not homogeneous: h = Add(*[(g * p).expand() for g, p in zip(G, P)]) C = [Symbol('C' + str(i)) for i in range(0, A)] def g(i): return Add(*[c * _delta(q, i) for c, q in zip(C, Q)]) if homogeneous: E = [g(i) for i in range(N + 1, U)] else: E = [g(i) + _delta(h, i) for i in range(N + 1, U)] if E != []: solutions = solve(E, *C) if not solutions: if homogeneous: if hints.get('symbols', False): return S.Zero, [] else: return S.Zero else: return else: solutions = {} if homogeneous: result = S.Zero else: result = h for c, q in list(zip(C, Q)): if c in solutions: s = solutions[c] * q C.remove(c) else: s = c * q result += s.expand() if hints.get('symbols', False): return result, C else: return result
def roots_quintic(f): """ Calulate exact roots of a solvable quintic """ result = [] coeff_5, coeff_4, p, q, r, s = f.all_coeffs() # Eqn must be of the form x^5 + px^3 + qx^2 + rx + s if coeff_4: return result if coeff_5 != 1: l = [p/coeff_5, q/coeff_5, r/coeff_5, s/coeff_5] if not all(coeff.is_Rational for coeff in l): return result f = Poly(f/coeff_5) quintic = PolyQuintic(f) # Eqn standardized. Algo for solving starts here if not f.is_irreducible: return result f20 = quintic.f20 # Check if f20 has linear factors over domain Z if f20.is_irreducible: return result # Now, we know that f is solvable for _factor in f20.factor_list()[1]: if _factor[0].is_linear: theta = _factor[0].root(0) break d = discriminant(f) delta = sqrt(d) # zeta = a fifth root of unity zeta1, zeta2, zeta3, zeta4 = quintic.zeta T = quintic.T(theta, d) tol = Float(1e-10) alpha = T[1] + T[2]*delta alpha_bar = T[1] - T[2]*delta beta = T[3] + T[4]*delta beta_bar = T[3] - T[4]*delta disc = alpha**2 - 4*beta disc_bar = alpha_bar**2 - 4*beta_bar l0 = quintic.l0(theta) l1 = _quintic_simplify((-alpha + sqrt(disc)) / Integer(2)) l4 = _quintic_simplify((-alpha - sqrt(disc)) / Integer(2)) l2 = _quintic_simplify((-alpha_bar + sqrt(disc_bar)) / Integer(2)) l3 = _quintic_simplify((-alpha_bar - sqrt(disc_bar)) / Integer(2)) order = quintic.order(theta, d) test = (order*delta.n()) - ( (l1.n() - l4.n())*(l2.n() - l3.n()) ) # Comparing floats if not comp(test, 0, tol): l2, l3 = l3, l2 # Now we have correct order of l's R1 = l0 + l1*zeta1 + l2*zeta2 + l3*zeta3 + l4*zeta4 R2 = l0 + l3*zeta1 + l1*zeta2 + l4*zeta3 + l2*zeta4 R3 = l0 + l2*zeta1 + l4*zeta2 + l1*zeta3 + l3*zeta4 R4 = l0 + l4*zeta1 + l3*zeta2 + l2*zeta3 + l1*zeta4 Res = [None, [None]*5, [None]*5, [None]*5, [None]*5] Res_n = [None, [None]*5, [None]*5, [None]*5, [None]*5] sol = Symbol('sol') # Simplifying improves performace a lot for exact expressions R1 = _quintic_simplify(R1) R2 = _quintic_simplify(R2) R3 = _quintic_simplify(R3) R4 = _quintic_simplify(R4) # Solve imported here. Causing problems if imported as 'solve' # and hence the changed name from diofant.solvers.solvers import solve as _solve a, b = symbols('a b', cls=Dummy) _sol = _solve( sol**5 - a - I*b, sol) for i in range(5): _sol[i] = factor(_sol[i]) R1 = R1.as_real_imag() R2 = R2.as_real_imag() R3 = R3.as_real_imag() R4 = R4.as_real_imag() for i, root in enumerate(_sol): Res[1][i] = _quintic_simplify(root.subs({ a: R1[0], b: R1[1] })) Res[2][i] = _quintic_simplify(root.subs({ a: R2[0], b: R2[1] })) Res[3][i] = _quintic_simplify(root.subs({ a: R3[0], b: R3[1] })) Res[4][i] = _quintic_simplify(root.subs({ a: R4[0], b: R4[1] })) for i in range(1, 5): for j in range(5): Res_n[i][j] = Res[i][j].n() Res[i][j] = _quintic_simplify(Res[i][j]) r1 = Res[1][0] r1_n = Res_n[1][0] for i in range(5): if comp(im(r1_n*Res_n[4][i]), 0, tol): r4 = Res[4][i] break u, v = quintic.uv(theta, d) sqrt5 = math.sqrt(5) # Now we have various Res values. Each will be a list of five # values. We have to pick one r value from those five for each Res u, v = quintic.uv(theta, d) testplus = (u + v*delta*sqrt(5)).n() testminus = (u - v*delta*sqrt(5)).n() # Evaluated numbers suffixed with _n # We will use evaluated numbers for calculation. Much faster. r4_n = r4.n() r2 = r3 = None for i in range(5): r2temp_n = Res_n[2][i] for j in range(5): # Again storing away the exact number and using # evaluated numbers in computations r3temp_n = Res_n[3][j] if (comp(r1_n*r2temp_n**2 + r4_n*r3temp_n**2 - testplus, 0, tol) and comp(r3temp_n*r1_n**2 + r2temp_n*r4_n**2 - testminus, 0, tol)): r2 = Res[2][i] r3 = Res[3][j] break if r2: break # Now, we have r's so we can get roots x1 = (r1 + r2 + r3 + r4)/5 x2 = (r1*zeta4 + r2*zeta3 + r3*zeta2 + r4*zeta1)/5 x3 = (r1*zeta3 + r2*zeta1 + r3*zeta4 + r4*zeta2)/5 x4 = (r1*zeta2 + r2*zeta4 + r3*zeta1 + r4*zeta3)/5 x5 = (r1*zeta1 + r2*zeta2 + r3*zeta3 + r4*zeta4)/5 result = [x1, x2, x3, x4, x5] # Now check if solutions are distinct saw = set() for r in result: r = r.n(2) if r in saw: # Roots were identical. Abort, return [] # and fall back to usual solve return [] saw.add(r) return result
def test_Min(): from diofant.abc import x, y, z n = Symbol('n', negative=True) n_ = Symbol('n_', negative=True) nn = Symbol('nn', nonnegative=True) nn_ = Symbol('nn_', nonnegative=True) p = Symbol('p', positive=True) p_ = Symbol('p_', positive=True) np = Symbol('np', nonpositive=True) np_ = Symbol('np_', nonpositive=True) assert Min(5, 4) == 4 assert Min(-oo, -oo) == -oo assert Min(-oo, n) == -oo assert Min(n, -oo) == -oo assert Min(-oo, np) == -oo assert Min(np, -oo) == -oo assert Min(-oo, 0) == -oo assert Min(0, -oo) == -oo assert Min(-oo, nn) == -oo assert Min(nn, -oo) == -oo assert Min(-oo, p) == -oo assert Min(p, -oo) == -oo assert Min(-oo, oo) == -oo assert Min(oo, -oo) == -oo assert Min(n, n) == n assert Min(n, np) == Min(n, np) assert Min(np, n) == Min(np, n) assert Min(n, 0) == n assert Min(0, n) == n assert Min(n, nn) == n assert Min(nn, n) == n assert Min(n, p) == n assert Min(p, n) == n assert Min(n, oo) == n assert Min(oo, n) == n assert Min(np, np) == np assert Min(np, 0) == np assert Min(0, np) == np assert Min(np, nn) == np assert Min(nn, np) == np assert Min(np, p) == np assert Min(p, np) == np assert Min(np, oo) == np assert Min(oo, np) == np assert Min(0, 0) == 0 assert Min(0, nn) == 0 assert Min(nn, 0) == 0 assert Min(0, p) == 0 assert Min(p, 0) == 0 assert Min(0, oo) == 0 assert Min(oo, 0) == 0 assert Min(nn, nn) == nn assert Min(nn, p) == Min(nn, p) assert Min(p, nn) == Min(p, nn) assert Min(nn, oo) == nn assert Min(oo, nn) == nn assert Min(p, p) == p assert Min(p, oo) == p assert Min(oo, p) == p assert Min(oo, oo) == oo assert Min(n, n_).func is Min assert Min(nn, nn_).func is Min assert Min(np, np_).func is Min assert Min(p, p_).func is Min # lists pytest.raises(ValueError, lambda: Min()) assert Min(x, y) == Min(y, x) assert Min(x, y, z) == Min(z, y, x) assert Min(x, Min(y, z)) == Min(z, y, x) assert Min(x, Max(y, -oo)) == Min(x, y) assert Min(p, oo, n, p, p, p_) == n assert Min(p_, n_, p) == n_ assert Min(n, oo, -7, p, p, 2) == Min(n, -7) assert Min(2, x, p, n, oo, n_, p, 2, -2, -2) == Min(-2, x, n, n_) assert Min(0, x, 1, y) == Min(0, x, y) assert Min(1000, 100, -100, x, p, n) == Min(n, x, -100) assert Min(cos(x), sin(x)) == Min(cos(x), sin(x)) assert Min(cos(x), sin(x)).subs(x, 1) == cos(1) assert Min(cos(x), sin(x)).subs(x, Rational(1, 2)) == sin(Rational(1, 2)) pytest.raises(ValueError, lambda: Min(cos(x), sin(x)).subs(x, I)) pytest.raises(ValueError, lambda: Min(I)) pytest.raises(ValueError, lambda: Min(I, x)) pytest.raises(ValueError, lambda: Min(S.ComplexInfinity, x)) assert Min(1, x).diff(x) == Heaviside(1 - x) assert Min(x, 1).diff(x) == Heaviside(1 - x) assert Min(0, -x, 1 - 2*x).diff(x) == -Heaviside(x + Min(0, -2*x + 1)) \ - 2*Heaviside(2*x + Min(0, -x) - 1) a, b = Symbol('a', extended_real=True), Symbol('b', extended_real=True) # a and b are both real, Min(a, b) should be real assert Min(a, b).is_extended_real # issue 7619 f = Function('f') assert Min(1, 2 * Min(f(1), 2)) # doesn't fail # issue 7233 e = Min(0, x) assert e.evalf == e.n assert e.n().args == (0, x)
def test_Max(): from diofant.abc import x, y, z n = Symbol('n', negative=True) n_ = Symbol('n_', negative=True) nn = Symbol('nn', nonnegative=True) nn_ = Symbol('nn_', nonnegative=True) p = Symbol('p', positive=True) p_ = Symbol('p_', positive=True) np = Symbol('np', nonpositive=True) np_ = Symbol('np_', nonpositive=True) r = Symbol('r', extended_real=True) assert Max(5, 4) == 5 # lists pytest.raises(ValueError, lambda: Max()) assert Max(x, y) == Max(y, x) assert Max(x, y, z) == Max(z, y, x) assert Max(x, Max(y, z)) == Max(z, y, x) assert Max(x, Min(y, oo)) == Max(x, y) assert Max(n, -oo, n_, p, 2) == Max(p, 2) assert Max(n, -oo, n_, p) == p assert Max(2, x, p, n, -oo, S.NegativeInfinity, n_, p, 2) == Max(2, x, p) assert Max(0, x, 1, y) == Max(1, x, y) assert Max(r, r + 1, r - 1) == 1 + r assert Max(1000, 100, -100, x, p, n) == Max(p, x, 1000) assert Max(cos(x), sin(x)) == Max(sin(x), cos(x)) assert Max(cos(x), sin(x)).subs(x, 1) == sin(1) assert Max(cos(x), sin(x)).subs(x, Rational(1, 2)) == cos(Rational(1, 2)) pytest.raises(ValueError, lambda: Max(cos(x), sin(x)).subs(x, I)) pytest.raises(ValueError, lambda: Max(I)) pytest.raises(ValueError, lambda: Max(I, x)) pytest.raises(ValueError, lambda: Max(S.ComplexInfinity, 1)) # interesting: # Max(n, -oo, n_, p, 2) == Max(p, 2) # True # Max(n, -oo, n_, p, 1000) == Max(p, 1000) # False assert Max(1, x).diff(x) == Heaviside(x - 1) assert Max(x, 1).diff(x) == Heaviside(x - 1) assert Max(x**2, 1 + x, 1).diff(x) == \ 2*x*Heaviside(x**2 - Max(1, x + 1)) \ + Heaviside(x - Max(1, x**2) + 1) a, b = Symbol('a', extended_real=True), Symbol('b', extended_real=True) # a and b are both real, Max(a, b) should be real assert Max(a, b).is_extended_real # issue 7233 e = Max(0, x) assert e.evalf == e.n assert e.n().args == (0, x)
def symarray(prefix, shape, **kwargs): # pragma: no cover """Create a numpy ndarray of symbols (as an object array). The created symbols are named ``prefix_i1_i2_``... You should thus provide a non-empty prefix if you want your symbols to be unique for different output arrays, as Diofant symbols with identical names are the same object. Parameters ---------- prefix : string A prefix prepended to the name of every symbol. shape : int or tuple Shape of the created array. If an int, the array is one-dimensional; for more than one dimension the shape must be a tuple. \*\*kwargs : dict keyword arguments passed on to Symbol Examples -------- These doctests require numpy. >>> from diofant import symarray >>> symarray('', 3) [_0 _1 _2] If you want multiple symarrays to contain distinct symbols, you *must* provide unique prefixes: >>> a = symarray('', 3) >>> b = symarray('', 3) >>> a[0] == b[0] True >>> a = symarray('a', 3) >>> b = symarray('b', 3) >>> a[0] == b[0] False Creating symarrays with a prefix: >>> symarray('a', 3) [a_0 a_1 a_2] For more than one dimension, the shape must be given as a tuple: >>> symarray('a', (2, 3)) [[a_0_0 a_0_1 a_0_2] [a_1_0 a_1_1 a_1_2]] >>> symarray('a', (2, 3, 2)) [[[a_0_0_0 a_0_0_1] [a_0_1_0 a_0_1_1] [a_0_2_0 a_0_2_1]] <BLANKLINE> [[a_1_0_0 a_1_0_1] [a_1_1_0 a_1_1_1] [a_1_2_0 a_1_2_1]]] For setting assumptions of the underlying Symbols: >>> [s.is_real for s in symarray('a', 2, real=True)] [True, True] """ from numpy import empty, ndindex arr = empty(shape, dtype=object) for index in ndindex(shape): arr[index] = Symbol('%s_%s' % (prefix, '_'.join(map(str, index))), **kwargs) return arr