def product_mul(self, other, method=0): """Helper function for Product simplification""" from diofant.concrete.products import Product if type(self) == type(other): if method == 0: if self.limits == other.limits: return Product(self.function * other.function, *self.limits) elif method == 1: if simplify(self.function - other.function) == 0: if len(self.limits) == len(other.limits) == 1: i = self.limits[0][0] x1 = self.limits[0][1] y1 = self.limits[0][2] j = other.limits[0][0] x2 = other.limits[0][1] y2 = other.limits[0][2] if i == j: if x2 == y1 + 1: return Product(self.function, (i, x1, y2)) elif x1 == y2 + 1: return Product(self.function, (i, x2, y1)) return Mul(self, other)
def test_log_product(): i, j = symbols('i,j', positive=True, integer=True) x, y = symbols('x,y', positive=True) assert simplify(log(Product(x**i, (i, 1, n)))) == Sum(i*log(x), (i, 1, n)) assert simplify(log(Product(x**i*y**j, (i, 1, n), (j, 1, m)))) == \ log(Product(x**i*y**j, (i, 1, n), (j, 1, m))) expr = log(Product(-2, (n, 0, 4))) assert simplify(expr) == expr
def test_wallis_product(): # Wallis product, given in two different forms to ensure that Product # can factor simple rational expressions A = Product(4 * n**2 / (4 * n**2 - 1), (n, 1, b)) B = Product((2 * n) * (2 * n) / (2 * n - 1) / (2 * n + 1), (n, 1, b)) half = Rational(1, 2) R = pi / 2 * factorial(b)**2 / factorial(b - half) / factorial(b + half) assert simplify(A.doit()) == R assert simplify(B.doit()) == R
def test_conjugate_transpose(): p = Product(x**k, (k, 1, 3)) assert p.adjoint().doit() == p.doit().adjoint() assert p.conjugate().doit() == p.doit().conjugate() assert p.transpose().doit() == p.doit().transpose() A, B = symbols("A B", commutative=False) p = Product(A * B**k, (k, 1, 3)) assert p.adjoint().doit() == p.doit().adjoint() assert p.conjugate().doit() == p.doit().conjugate() assert p.transpose().doit() == p.doit().transpose()
def test__eval_product(): # issue sympy/sympy#4809 a = Function('a') assert product(2 * a(i), (i, 1, n)) == 2**n * Product(a(i), (i, 1, n)) # issue sympy/sympy#4810 assert product(2**i, (i, 1, n)) == 2**(n / 2 + n**2 / 2) assert (product( (i - 1) * (i**6 + i - 1), (i, n, m)) == rf(n - 1, m - n + 1) * product(i**6 + i - 1, (i, n, m))) assert (product(log(i)**2 * cos(i)**3, (i, n, m)) == Product(log(i)**2 * cos(i)**3, (i, n, m)))
def test__eval_product(): from diofant.abc import i, n # issue 4809 a = Function('a') assert product(2 * a(i), (i, 1, n)) == 2**n * Product(a(i), (i, 1, n)) # issue 4810 assert product(2**i, (i, 1, n)) == 2**(n / 2 + n**2 / 2)
def test_distribution_over_equality(): f = Function('f') assert Product(Eq(x * 2, f(x)), (x, 1, 3)).doit() == Eq(48, f(1) * f(2) * f(3)) assert Sum(Eq(f(x), x**2), (x, 0, y)) == \ Eq(Sum(f(x), (x, 0, y)), Sum(x**2, (x, 0, y)))
def test_the_product(l, n, m): # Productmand s = i**3 # First product a = l b = n - 1 S1 = Product(s, (i, a, b)).doit() # Second product a = l b = m - 1 S2 = Product(s, (i, a, b)).doit() # Third product a = m b = n - 1 S3 = Product(s, (i, a, b)).doit() # Test if S1 = S2 * S3 as required assert simplify(S1 / (S2 * S3)) == 1
def test_simple_products(): assert product(2, (k, a, n)) == 2**(n - a + 1) assert product(k, (k, 1, n)) == factorial(n) assert product(k**3, (k, 1, n)) == factorial(n)**3 assert product(k + 1, (k, 0, n - 1)) == factorial(n) assert product(k + 1, (k, a, n - 1)) == rf(1 + a, n - a) assert product(cos(k), (k, 0, 5)) == cos(1) * cos(2) * cos(3) * cos(4) * cos(5) assert product(cos(k), (k, 3, 5)) == cos(3) * cos(4) * cos(5) assert product(cos(k), (k, 1, Rational(5, 2))) != cos(1) * cos(2) assert isinstance(product(k**k, (k, 1, n)), Product) assert Product(x**k, (k, 1, n)).variables == [k] pytest.raises(ValueError, lambda: Product(n)) pytest.raises(ValueError, lambda: Product(n * k)) pytest.raises(ValueError, lambda: Product(n, k)) pytest.raises(ValueError, lambda: Product(n, k, 1)) pytest.raises(ValueError, lambda: Product(n, k, 1, 10)) pytest.raises(ValueError, lambda: Product(n, (k, 1))) assert product(1, (n, 1, oo)) == 1 # issue 8301 assert product(2, (n, 1, oo)) == oo assert product(-1, (n, 1, oo)).func is Product
def test_multiple_products(): assert product(x, (n, 1, k), (k, 1, m)) == x**(m**2 / 2 + m / 2) assert product(f(n), (n, 1, m), (m, 1, k)) == Product(f(n), (n, 1, m), (m, 1, k)).doit() assert Product(f(n), (m, 1, k), (n, 1, k)).doit() == \ Product(Product(f(n), (m, 1, k)), (n, 1, k)).doit() == \ product(f(n), (m, 1, k), (n, 1, k)) == \ product(product(f(n), (m, 1, k)), (n, 1, k)) == \ Product(f(n)**k, (n, 1, k)) assert Product(x, (x, 1, k), (k, 1, n)).doit() == Product(factorial(k), (k, 1, n)) assert Product(x**k, (n, 1, k), (k, 1, m)).variables == [n, k]
def test_the_product(m, n): # g g = i**3 + 2 * i**2 - 3 * i # f = Delta g f = simplify(g.subs(i, i + 1) / g) # The product a = m b = n - 1 P = Product(f, (i, a, b)).doit() # Test if Product_{m <= i < n} f(i) = g(n) / g(m) assert simplify(P / (g.subs(i, n) / g.subs(i, m))) == 1
def test_is_number(): # is number should not rely on evaluation or assumptions, # it should be equivalent to `not foo.free_symbols` assert Sum(1, (x, 1, 1)).is_number is True assert Sum(1, (x, 1, x)).is_number is False assert Sum(0, (x, y, z)).is_number is False assert Sum(x, (y, 1, 2)).is_number is False assert Sum(x, (y, 1, 1)).is_number is False assert Sum(x, (x, 1, 2)).is_number is True assert Sum(x * y, (x, 1, 2), (y, 1, 3)).is_number is True assert Product(2, (x, 1, 1)).is_number is True assert Product(2, (x, 1, y)).is_number is False assert Product(0, (x, y, z)).is_number is False assert Product(1, (x, y, z)).is_number is False assert Product(x, (y, 1, x)).is_number is False assert Product(x, (y, 1, 2)).is_number is False assert Product(x, (y, 1, 1)).is_number is False assert Product(x, (x, 1, 2)).is_number is True
def test_free_symbols(): for func in [Sum, Product]: assert func(1, (x, 1, 2)).free_symbols == set() assert func(0, (x, 1, y)).free_symbols == {y} assert func(2, (x, 1, y)).free_symbols == {y} assert func(x, (x, 1, 2)).free_symbols == set() assert func(x, (x, 1, y)).free_symbols == {y} assert func(x, (y, 1, y)).free_symbols == {x, y} assert func(x, (y, 1, 2)).free_symbols == {x} assert func(x, (y, 1, 1)).free_symbols == {x} assert func(x, (y, 1, z)).free_symbols == {x, z} assert func(x, (x, 1, y), (y, 1, 2)).free_symbols == set() assert func(x, (x, 1, y), (y, 1, z)).free_symbols == {z} assert func(x, (x, 1, y), (y, 1, y)).free_symbols == {y} assert func(x, (y, 1, y), (y, 1, z)).free_symbols == {x, z} assert Sum(1, (x, 1, y)).free_symbols == {y} # free_symbols answers whether the object *as written* has free symbols, # not whether the evaluated expression has free symbols assert Product(1, (x, 1, y)).free_symbols == {y}
def test_evalf_product(): assert Product(n, (n, 1, 10)).evalf() == 3628800. assert Product(1 - 1 / (4 * n**2), (n, 1, oo)).evalf(5) == 0.63662 assert Product(n, (n, -1, 3)).evalf() == 0
def test_change_index(): b, y, c, d, z = symbols('b, y, c, d, z', integer=True) assert Product(x, (x, a, b)).change_index(x, x + 1, y) == \ Product(y - 1, (y, a + 1, b + 1)) assert Product(x**2, (x, a, b)).change_index(x, x - 1) == \ Product((x + 1)**2, (x, a - 1, b - 1)) assert Product(x**2, (x, a, b)).change_index(x, -x, y) == \ Product((-y)**2, (y, -b, -a)) assert Product(x, (x, a, b)).change_index(x, -x - 1) == \ Product(-x - 1, (x, - b - 1, -a - 1)) assert Product(x*y, (x, a, b), (y, c, d)).change_index(x, x - 1, z) == \ Product((z + 1)*y, (z, a - 1, b - 1), (y, c, d)) p = Product(x, (x, 1, 5)) pytest.raises(ValueError, lambda: p.change_index(x, x**2, y)) pytest.raises(ValueError, lambda: p.change_index(x, 2 * x, y))
def test_karr_convention(): i = Symbol('i', integer=True) k = Symbol('k', integer=True) j = Symbol('j', integer=True) # A simple example with a concrete factors and symbolic limits. # The normal product: m = k and n = k + j and therefore m < n: m = k n = k + j a = m b = n - 1 S1 = Product(i**2, (i, a, b)).doit() # The reversed product: m = k + j and n = k and therefore m > n: m = k + j n = k a = m b = n - 1 S2 = Product(i**2, (i, a, b)).doit() assert simplify(S1 * S2) == 1 # Test the empty product: m = k and n = k and therefore m = n: m = k n = k a = m b = n - 1 Sz = Product(i**2, (i, a, b)).doit() assert Sz == 1 # Another example this time with an unspecified factor and # numeric limits. (We can not do both tests in the same example.) f = Function('f') # The normal product with m < n: m = 2 n = 11 a = m b = n - 1 S1 = Product(f(i), (i, a, b)).doit() # The reversed product with m > n: m = 11 n = 2 a = m b = n - 1 S2 = Product(f(i), (i, a, b)).doit() assert simplify(S1 * S2) == 1 # Test the empty product with m = n: m = 5 n = 5 a = m b = n - 1 Sz = Product(f(i), (i, a, b)).doit() assert Sz == 1
def test_Product_doit(): assert Product(n * Integral(a**2), (n, 1, 3)).doit() == 2 * a**9 / 9 assert Product(n*Integral(a**2), (n, 1, 3)).doit(deep=False) == \ 6*Integral(a**2)**3 assert product(n * Integral(a**2), (n, 1, 3)) == 6 * Integral(a**2)**3
def _eval_rewrite_as_Product(self, n): from diofant import Product if n.is_nonnegative and n.is_integer: i = Dummy('i', integer=True) return Product(i, (i, 1, n))
def test_simple_products(): assert Product(nan, (x, 1, 3)) is nan assert product(nan, (x, 1, 3)) is nan assert Product(x, (n, a, a)).doit() == x assert Product(x, (x, a, a)).doit() == a assert Product(x, (y, 1, a)).doit() == x**a lo, hi = 1, 2 s1 = Product(n, (n, lo, hi)) s2 = Product(n, (n, hi, lo)) assert s1 != s2 # This IS correct according to Karr product convention assert s1.doit() == 2 assert s2.doit() == 1 lo, hi = x, x + 1 s1 = Product(n, (n, lo, hi)) s2 = Product(n, (n, hi, lo)) s3 = 1 / Product(n, (n, hi + 1, lo - 1)) assert s1 != s2 # This IS correct according to Karr product convention assert s1.doit() == x * (x + 1) assert s2.doit() == 1 assert s3.doit() == x * (x + 1) assert Product(Integral(2*x, (x, 1, y)) + 2*x, (x, 1, 2)).doit() == \ (y**2 + 1)*(y**2 + 3) assert product(2, (n, a, b)) == 2**(b - a + 1) assert product(n, (n, 1, b)) == factorial(b) assert product(n**3, (n, 1, b)) == factorial(b)**3 assert product(3**(2 + n), (n, a, b)) \ == 3**(2*(1 - a + b) + b/2 + (b**2)/2 + a/2 - (a**2)/2) assert product(cos(n), (n, 3, 5)) == cos(3) * cos(4) * cos(5) assert product(cos(n), (n, x, x + 2)) == cos(x) * cos(x + 1) * cos(x + 2) assert isinstance(product(cos(n), (n, x, x + Rational(1, 2))), Product) # If Product managed to evaluate this one, it most likely got it wrong! assert isinstance(Product(n**n, (n, 1, b)), Product)
def test_rewrite_Sum(): assert Product(1 - S.Half**2/k**2, (k, 1, oo)).rewrite(Sum) == \ exp(Sum(log(1 - 1/(4*k**2)), (k, 1, oo)))
def test_concrete(): for c in (Product, Product(x, (x, 2, 4)), Sum, Sum(x, (x, 2, 4))): check(c)
def test_reorder_limit(): x, y, a, b, c, d = symbols('x, y, a, b, c, d', integer=True) pytest.raises( ReorderError, lambda: Product(x**2, (x, a, b), (y, x, d)).reorder_limit(1, 0))
def test_reverse_order(): x, y, a, b, c, d = symbols('x, y, a, b, c, d', integer=True) assert Product(x, (x, 0, 3)).reverse_order(0) == Product(1 / x, (x, 4, -1)) assert Product(x*y, (x, 1, 5), (y, 0, 6)).reverse_order(0, 1) == \ Product(x*y, (x, 6, 0), (y, 7, -1)) assert Product(x, (x, 1, 2)).reverse_order(0) == Product(1 / x, (x, 3, 0)) assert Product(x, (x, 1, 3)).reverse_order(0) == Product(1 / x, (x, 4, 0)) assert Product(x, (x, 1, a)).reverse_order(0) == Product( 1 / x, (x, a + 1, 0)) assert Product(x, (x, a, 5)).reverse_order(0) == Product( 1 / x, (x, 6, a - 1)) assert Product(x, (x, a + 1, a + 5)).reverse_order(0) == \ Product(1/x, (x, a + 6, a)) assert Product(x, (x, a + 1, a + 2)).reverse_order(0) == \ Product(1/x, (x, a + 3, a)) assert Product(x, (x, a + 1, a + 1)).reverse_order(0) == \ Product(1/x, (x, a + 2, a)) assert Product(x, (x, a, b)).reverse_order(0) == Product( 1 / x, (x, b + 1, a - 1)) assert Product(x, (x, a, b)).reverse_order(x) == Product( 1 / x, (x, b + 1, a - 1)) assert Product(x*y, (x, a, b), (y, 2, 5)).reverse_order(x, 1) == \ Product(x*y, (x, b + 1, a - 1), (y, 6, 1)) assert Product(x*y, (x, a, b), (y, 2, 5)).reverse_order(y, x) == \ Product(x*y, (x, b + 1, a - 1), (y, 6, 1))
def test_karr_convention(): # Test the Karr product convention that we want to hold. # See his paper "Summation in Finite Terms" for a detailed # reasoning why we really want exactly this definition. # The convention is described for sums on page 309 and # essentially in section 1.4, definition 3. For products # we can find in analogy: # # \prod_{m <= i < n} f(i) 'has the obvious meaning' for m < n # \prod_{m <= i < n} f(i) = 0 for m = n # \prod_{m <= i < n} f(i) = 1 / \prod_{n <= i < m} f(i) for m > n # # It is important to note that he defines all products with # the upper limit being *exclusive*. # In contrast, diofant and the usual mathematical notation has: # # prod_{i = a}^b f(i) = f(a) * f(a+1) * ... * f(b-1) * f(b) # # with the upper limit *inclusive*. So translating between # the two we find that: # # \prod_{m <= i < n} f(i) = \prod_{i = m}^{n-1} f(i) # # where we intentionally used two different ways to typeset the # products and its limits. i = Symbol("i", integer=True) k = Symbol("k", integer=True) j = Symbol("j", integer=True) # A simple example with a concrete factors and symbolic limits. # The normal product: m = k and n = k + j and therefore m < n: m = k n = k + j a = m b = n - 1 S1 = Product(i**2, (i, a, b)).doit() # The reversed product: m = k + j and n = k and therefore m > n: m = k + j n = k a = m b = n - 1 S2 = Product(i**2, (i, a, b)).doit() assert simplify(S1 * S2) == 1 # Test the empty product: m = k and n = k and therefore m = n: m = k n = k a = m b = n - 1 Sz = Product(i**2, (i, a, b)).doit() assert Sz == 1 # Another example this time with an unspecified factor and # numeric limits. (We can not do both tests in the same example.) f = Function("f") # The normal product with m < n: m = 2 n = 11 a = m b = n - 1 S1 = Product(f(i), (i, a, b)).doit() # The reversed product with m > n: m = 11 n = 2 a = m b = n - 1 S2 = Product(f(i), (i, a, b)).doit() assert simplify(S1 * S2) == 1 # Test the empty product with m = n: m = 5 n = 5 a = m b = n - 1 Sz = Product(f(i), (i, a, b)).doit() assert Sz == 1
def test_infinite_product(): # issue 5737 assert isinstance(Product(2**(1 / factorial(n)), (n, 0, oo)), Product)
def test_simplify(): y, t, b, c = symbols('y, t, b, c', integer=True) assert simplify(Product(x*y, (x, n, m), (y, a, k)) * Product(y, (x, n, m), (y, a, k))) == \ Product(x*y**2, (x, n, m), (y, a, k)) assert simplify(3 * y * Product(x, (x, n, m)) * Product(x, (x, m + 1, a))) \ == 3 * y * Product(x, (x, n, a)) assert simplify(Product(x, (x, k + 1, a)) * Product(x, (x, n, k))) == \ Product(x, (x, n, a)) assert simplify(Product(x, (x, k + 1, a)) * Product(x + 1, (x, n, k))) == \ Product(x, (x, k + 1, a)) * Product(x + 1, (x, n, k)) assert simplify(Product(x, (t, a, b)) * Product(y, (t, a, b)) * Product(x, (t, b+1, c))) == Product(x*y, (t, a, b)) * \ Product(x, (t, b+1, c)) assert simplify(Product(x, (t, a, b)) * Product(x, (t, b+1, c)) * Product(y, (t, a, b))) == Product(x*y, (t, a, b)) * \ Product(x, (t, b+1, c))
def test_evalf_product(): assert Product(n, (n, 1, 10)).evalf() == 3628800. assert Product(1 - S.Half**2/n**2, (n, 1, oo)).evalf(5) == 0.63662 assert Product(n, (n, -1, 3)).evalf() == 0
def test_index(): p = Product(x, (x, 1, 3), (x, 1, 4)) pytest.raises(ValueError, lambda: p.index(x))
def test_Product(): assert precedence(Product(x, (x, y, y + 1))) == PRECEDENCE['Atom']
def test_reorder(): b, y, c, d, z = symbols('b, y, c, d, z', integer=True) assert Product(x*y, (x, a, b), (y, c, d)).reorder((0, 1)) == \ Product(x*y, (y, c, d), (x, a, b)) assert Product(x, (x, a, b), (x, c, d)).reorder((0, 1)) == \ Product(x, (x, c, d), (x, a, b)) assert Product(x * y + z, (x, a, b), (z, m, n), (y, c, d)).reorder( (2, 0), (0, 1)) == Product(x * y + z, (z, m, n), (y, c, d), (x, a, b)) assert Product(x*y*z, (x, a, b), (y, c, d), (z, m, n)).reorder( (0, 1), (1, 2), (0, 2)) == \ Product(x*y*z, (x, a, b), (z, m, n), (y, c, d)) assert Product(x*y*z, (x, a, b), (y, c, d), (z, m, n)).reorder( (x, y), (y, z), (x, z)) == \ Product(x*y*z, (x, a, b), (z, m, n), (y, c, d)) assert Product(x*y, (x, a, b), (y, c, d)).reorder((x, 1)) == \ Product(x*y, (y, c, d), (x, a, b)) assert Product(x*y, (x, a, b), (y, c, d)).reorder((y, x)) == \ Product(x*y, (y, c, d), (x, a, b)) pytest.raises(ValueError, lambda: Product(x * y, (x, a, b), (y, c, d)).reorder((x, )))