def test_mul(self): # Bivariate times univariate. x = Variable('x') y = Variable('y') c0 = ChebyshevVector({x: 5, y: 3}) c1 = ChebyshevVector({x: 2}) p = c0 * c1 self.assertEqual(len(p), 2) self.assertEqual(p[ChebyshevVector({x: 7, y: 3})], 1 / 2) self.assertEqual(p[ChebyshevVector({x: 3, y: 3})], 1 / 2) # Bivariate times bivariate. c1 = ChebyshevVector({x: 8, y: 1}) p = c0 * c1 self.assertEqual(len(p), 4) self.assertEqual(p[ChebyshevVector({x: 13, y: 4})], 1 / 4) self.assertEqual(p[ChebyshevVector({x: 13, y: 2})], 1 / 4) self.assertEqual(p[ChebyshevVector({x: 3, y: 4})], 1 / 4) self.assertEqual(p[ChebyshevVector({x: 3, y: 2})], 1 / 4) # With zero power. c1 = ChebyshevVector({x: 5, y: 1}) p = c0 * c1 self.assertEqual(len(p), 4) self.assertEqual(p[ChebyshevVector({x: 10, y: 4})], 1 / 4) self.assertEqual(p[ChebyshevVector({x: 10, y: 2})], 1 / 4) self.assertEqual(p[ChebyshevVector({y: 4})], 1 / 4) self.assertEqual(p[ChebyshevVector({y: 2})], 1 / 4) # Multiplication by wrong type. c = ChebyshevVector({x: 3, y: 4}) m = MonomialVector({x: 5, y: 2}) with self.assertRaises(TypeError): c * m
def test_is_odd_is_even(self): for Vector in Vectors: # Even. x = Variable('x') y = Variable('y') v0 = Vector({x: 4, y: 2}) v1 = Vector({x: 1, y: 1}) p = Polynomial({v0: 2.5, v1: 3}) self.assertTrue(p.is_even()) self.assertFalse(p.is_odd()) # Not even nor odd. v0[y] += 1 self.assertFalse(p.is_odd()) self.assertFalse(p.is_even()) # Odd. v1[y] += 1 self.assertTrue(p.is_odd()) self.assertFalse(p.is_even()) # Degree 0. v = Vector({}) p = Polynomial({v: 1}) self.assertTrue(p.is_even()) self.assertFalse(p.is_odd()) # Empty polynomial is 0, hence even. p = Polynomial({}) self.assertTrue(p.is_even()) self.assertFalse(p.is_odd())
def test_derivative_jacobian(self): for Vector in Vectors: # Derivative. x = Variable('x') y = Variable('y') z = Variable('z') m0 = Vector({x: 4, y: 1}) m1 = Vector({x: 5, y: 2}) p = Polynomial({m0: 2.5, m1: -3}) px = m0.derivative(x) * 2.5 + m1.derivative(x) * (-3) py = m0.derivative(y) * 2.5 + m1.derivative(y) * (-3) pz = Polynomial({}) self.assertEqual(p.derivative(x), px) self.assertEqual(p.derivative(y), py) self.assertEqual(p.derivative(z), pz) # Jacobian. for pi, qi in zip(p.jacobian([z, x, y]), np.array([pz, px, py])): self.assertEqual(pi, qi) # Differentiation of zero polynomial must return a polynomial. p = Polynomial({}) px = p.derivative(x) self.assertEqual(px, 0) self.assertTrue(isinstance(px, Polynomial))
def test_substitute(self): for Vector in Vectors: # Partial evaluation. x = Variable('x') y = Variable('y') z = Variable('z') v0 = Vector({x: 1, y: 2}) v1 = Vector({x: 3, z: 5}) p = Polynomial({v0: 3.5, v1: .5}) eval_dict = {x: 2, y: .3} p_eval = v0.substitute(eval_dict) * 3.5 + v1.substitute( eval_dict) * .5 self.assertAlmostEqual(p.substitute(eval_dict), p_eval) # Complete evaluation. eval_dict[z] = -3.12 p_eval = v0.substitute(eval_dict) * 3.5 + v1.substitute( eval_dict) * .5 self.assertAlmostEqual(p.substitute(eval_dict), p_eval) # Cancellation. eval_dict = {x: 0} p_eval = Polynomial({}) self.assertAlmostEqual(p.substitute(eval_dict), p_eval) # Must always return a polynomial. p = Polynomial({}).substitute({x: 3}) self.assertAlmostEqual(p, Polynomial({})) self.assertTrue(isinstance(p, Polynomial))
def test_substitute(self): # Partial evaluation. x = Variable('x') y = Variable('y') z = Variable('z') power_dict = {x: 5, y: 2, z: 3} m = ChebyshevVector(power_dict) x_eval = {x: -2.1, y: 1.5} m_eval = ChebyshevVector({z: 3}) c_eval = 16 * (-2.1)**5 - 20 * (-2.1)**3 + 5 * (-2.1) c_eval *= 2 * 1.5**2 - 1 p = Polynomial({m_eval: c_eval}) self.assertAlmostEqual(m.substitute(x_eval), p) # Complete evaluation. x_eval[z] = 5 m_eval = ChebyshevVector({}) c_eval *= 4 * 5**3 - 3 * 5 p = Polynomial({m_eval: c_eval}) self.assertAlmostEqual(m.substitute(x_eval), p) # Cancellation. x_eval = {z: 0} p = Polynomial({}) self.assertAlmostEqual(m.substitute(x_eval), p)
def test_eq_ne(self): for Vector in Vectors: # Comparisons with different lengths. x = Variable('x') y = Variable('y') v0 = Vector({x: 4, y: 1}) v1 = Vector({x: 5, y: 2}) v2 = Vector({x: 6}) p1 = Polynomial({v0: 5, v1: 2.5, v2: 3}) p2 = Polynomial({v1: 2.5, v0: 5, v2: 3}) p3 = Polynomial({v0: 5, v2: 3}) p4 = Polynomial({v0: 5, v1: 0, v2: 3}) self.assertTrue(p1 == p2) self.assertTrue(p1 != p3) self.assertTrue(p2 != p3) self.assertTrue(p3 == p4) # Comparison to 0. self.assertFalse(p1 == 0) self.assertTrue(p1 != 0) p = Polynomial({}) self.assertTrue(p == 0) self.assertFalse(p != 0) # Comparison with different vector type. m = MonomialVector({x: 4, y: 1}) c = ChebyshevVector({x: 4, y: 1}) pm = Polynomial({m: 1}) pc = Polynomial({c: 1}) self.assertTrue(pm != pc)
def test_init(self): # Empty initialization. v = BasisVector({}) self.assertEqual(v.power_dict, {}) # Simple initialization. x = Variable('x') y = Variable('y') power_dict = {x: 5, y: 2} v = BasisVector(power_dict) self.assertEqual(v.power_dict, power_dict) # Removes zeros. z = Variable('z') power_dict[z] = 0 v = BasisVector(power_dict) self.assertEqual(v.power_dict, {x: 5, y: 2}) # Non-variable variable. with self.assertRaises(TypeError): BasisVector({x: 5, 'y': 2}) with self.assertRaises(TypeError): BasisVector({x: 5, 4: 2}) # Non-integer power. power_dict[z] = 3.33 with self.assertRaises(ValueError): BasisVector(power_dict)
def test_len(self): v = BasisVector({}) self.assertEqual(len(v), 0) x = Variable('x') y = Variable('y') v = BasisVector({x: 5, y: 2}) self.assertEqual(len(v), 2)
def test_iter(self): x = Variable('x') y = Variable('y') power_dict = {x: 5, y: 2} vector = BasisVector(power_dict) for v, p in vector: self.assertEqual(p, power_dict[v]) self.assertEqual(set(vector.variables()), set(power_dict)) self.assertEqual(set(vector.powers()), set(power_dict.values()))
def test_len(self): for Vector in Vectors: x = Variable('x') y = Variable('y') v0 = Vector({x: 4, y: 1}) v1 = Vector({x: 5, y: 2}) v2 = Vector({x: 6}) p = Polynomial({v0: 5, v1: 2.5, v2: 3}) self.assertEqual(len(p), 3)
def test_abs(self): for Vector in Vectors: x = Variable('x') y = Variable('y') v0 = Vector({x: 1, y: 3}) v1 = Vector({x: 2, y: 2}) v2 = Vector({x: 4, y: 1}) p = Polynomial({v0: 1 / 3, v1: -5.2, v2: .22233}) p_abs = Polynomial({v0: 1 / 3, v1: 5.2, v2: .22233}) self.assertEqual(abs(p), p_abs)
def test_repr(self): x = Variable('x') x3 = Variable('x', 3) v = BasisVector({x: 5, x3: 2}) self.assertEqual(v.__repr__(), '(x,5)(x_{3},2)') self.assertEqual(v._repr_latex_(), '$(x,5)(x_{3},2)$') # 1 if all the powers are zero. v = BasisVector({}) self.assertEqual(v.__repr__(), '1') self.assertEqual(v._repr_latex_(), '$1$')
def test_repr(self): for Vector in Vectors: # Only + signs. x = Variable('x') y = Variable('y') v0 = Vector({x: 4, y: 1}) v1 = Vector({x: 5, y: 2}) p = Polynomial({v0: 2.5, v1: 3}) r = '2.5' + v0.__repr__() + '+3' + v1.__repr__() self.assertEqual(p.__repr__(), r) self.assertEqual(p._repr_latex_(), '$' + r + '$') # With - signs. p = Polynomial({v0: 2.5, v1: -3}) r = '2.5' + v0.__repr__() + '-3' + v1.__repr__() self.assertEqual(p.__repr__(), r) self.assertEqual(p._repr_latex_(), '$' + r + '$') p = Polynomial({v0: -2.5, v1: 3}) r = '-2.5' + v0.__repr__() + '+3' + v1.__repr__() self.assertEqual(p.__repr__(), r) self.assertEqual(p._repr_latex_(), '$' + r + '$') # 0 if all the coefficients are 0. p = Polynomial({}) self.assertEqual(p.__repr__(), '0') self.assertEqual(p._repr_latex_(), '$0$') # Suppress 1 coefficients. p = Polynomial({v0: 2.5, v1: 1}) r = '2.5' + v0.__repr__() + '+' + v1.__repr__() self.assertEqual(p.__repr__(), r) self.assertEqual(p._repr_latex_(), '$' + r + '$') p = Polynomial({v0: 1, v1: 3.44}) r = v0.__repr__() + '+3.44' + v1.__repr__() self.assertEqual(p.__repr__(), r) self.assertEqual(p._repr_latex_(), '$' + r + '$') # Vector equal to one. v2 = Vector({}) p = Polynomial({v2: 5.33, v0: 2, v1: 3}) r = '5.33+2' + v0.__repr__() + '+3' + v1.__repr__() self.assertEqual(p.__repr__(), r) self.assertEqual(p._repr_latex_(), '$' + r + '$') # Just represent - if coefficient is -1. w0 = Vector({x: 1}) w1 = Vector({y: 1}) p = Polynomial({w0: 1, w1: -1}) r = w0.__repr__() + '-' + w1.__repr__() self.assertEqual(p.__repr__(), r) self.assertEqual(p._repr_latex_(), '$' + r + '$')
def test_call(self): x = Variable('x') y = Variable('y') z = Variable('z') power_dict = {x: 5, y: 2, z: 3} m = ChebyshevVector(power_dict) x_eval = {x: -2.1, y: 1.5, z: 5} value = 16 * (-2.1)**5 - 20 * (-2.1)**3 + 5 * (-2.1) value *= 2 * 1.5**2 - 1 value *= 4 * 5**3 - 3 * 5 self.assertAlmostEqual(m(x_eval), value)
def test_eq_ne(self): x = Variable('x') y = Variable('y') z = Variable('z') v1 = BasisVector({x: 5, y: 2, z: 3}) v2 = BasisVector({y: 2, x: 5, z: 3}) v3 = BasisVector({x: 5, z: 3}) v4 = BasisVector({x: 5, y: 0, z: 3}) self.assertTrue(v1 == v2) self.assertTrue(v1 != v3) self.assertTrue(v2 != v3) self.assertTrue(v3 == v4)
def test_radd(self): for Vector in Vectors: x = Variable('x') y = Variable('y') v0 = Vector({x: 4, y: 1}) v1 = Vector({x: 5, y: 2}) p = Polynomial({v0: 2.5, v1: 3}) self.assertEqual(p, 0 + p) with self.assertRaises(TypeError): 2 + p with self.assertRaises(TypeError): 'a' + p
def test_repr(self): # Variable without index. x = Variable('x') self.assertEqual(x.__repr__(), 'x') self.assertEqual(x._repr_latex_(), '$x$') # Variable with index. x1 = Variable('x', 1) x11 = Variable('x', 11) self.assertEqual(x1.__repr__(), 'x_{1}') self.assertEqual(x1._repr_latex_(), '$x_{1}$') self.assertEqual(x11.__repr__(), 'x_{11}') self.assertEqual(x11._repr_latex_(), '$x_{11}$')
def test_call(self): for Vector in Vectors: # Partial evaluation. x = Variable('x') y = Variable('y') z = Variable('z') v0 = Vector({x: 1, y: 2}) v1 = Vector({x: 3, z: 5}) p = Polynomial({v0: 3.5, v1: .5}) eval_dict = {x: 2, y: .3, z: -3.12} value = v0(eval_dict) * 3.5 + v1(eval_dict) * .5 self.assertAlmostEqual(p(eval_dict), value)
def test_round(self): for Vector in Vectors: x = Variable('x') y = Variable('y') v0 = Vector({x: 1, y: 3}) v1 = Vector({x: 2, y: 2}) v2 = Vector({x: 4, y: 1}) p = Polynomial({v0: 1 / 3, v1: -5.2, v2: .22233}) p0 = Polynomial({v1: -5}) self.assertEqual(round(p), p0) p1 = Polynomial({v0: .3, v1: -5.2, v2: .2}) self.assertEqual(round(p, 1), p1) p4 = Polynomial({v0: .3333, v1: -5.2, v2: .2223}) self.assertEqual(round(p, 4), p4)
def test_iter(self): for Vector in Vectors: x = Variable('x') y = Variable('y') z = Variable('z') v0 = Vector({x: 4, y: 1}) v1 = Vector({x: 5, z: 2}) v2 = Vector({x: 6}) coef_dict = {v0: 5, v1: 2.5, v2: 3} p = Polynomial(coef_dict) for v, c in p: self.assertEqual(c, coef_dict[v]) self.assertEqual(set(p.vectors()), set(coef_dict)) self.assertEqual(set(p.coefficients()), set(coef_dict.values())) self.assertEqual(set(p.variables()), set([x, y, z]))
def test_in_monomial_basis(self): # Zero polynomial. p = Polynomial({}) p_mon = p.in_monomial_basis() self.assertEqual(p_mon, p) self.assertTrue(isinstance(p_mon, Polynomial)) # Non-zero polynomial. x = Variable('x') y = Variable('y') z = Variable('z') m0 = ChebyshevVector({x: 4, y: 3}) m1 = ChebyshevVector({x: 1, z: 3}) p = Polynomial({m0: 4, m1: 3}) p_mon = m0.in_monomial_basis() * 4 + m1.in_monomial_basis() * 3 self.assertEqual(p.in_monomial_basis(), p_mon)
def test_getter_setter(self): for Vector in Vectors: # Getter. x = Variable('x') y = Variable('y') v0 = Vector({x: 4, y: 1}) v1 = Vector({x: 5, y: 2}) v2 = Vector({x: 5, y: 12}) p = Polynomial({v0: 2, v1: 3.22}) self.assertEqual(p[v0], 2) self.assertEqual(p[v1], 3.22) self.assertEqual(p[v2], 0) self.assertEqual(len(p), 2) # Setter. p[v0] = 1.11 p[v2] = 6 self.assertEqual(p[v0], 1.11) self.assertEqual(p[v1], 3.22) self.assertEqual(p[v2], 6) self.assertEqual(len(p), 3) # Delete instead of setting to zero. p[v2] = 0 self.assertEqual(p[v2], 0) self.assertEqual(len(p), 2) # Do not set if zero. p[v2] = 0 self.assertEqual(p[v2], 0) # Non-vector in the vectors. with self.assertRaises(TypeError): p[2] = 5 with self.assertRaises(TypeError): p[x] = 5 # Vector of different types. m = MonomialVector({x: 4, y: 1}) c = ChebyshevVector({x: 4, y: 2}) p = Polynomial({m: 2.1}) with self.assertRaises(TypeError): p[c] = 5
def test_integral_definite_integral(self): for Vector in Vectors: # Indefinite. x = Variable('x') y = Variable('y') z = Variable('z') m0 = Vector({x: 4, y: 1}) m1 = Vector({x: 5, y: 2}) p = Polynomial({m0: 2.5, m1: -3}) px = m0.integral(x) * 2.5 + m1.integral(x) * (-3) py = m0.integral(y) * 2.5 + m1.integral(y) * (-3) pz = m0.integral(z) * 2.5 + m1.integral(z) * (-3) self.assertEqual(p.integral(x), px) self.assertEqual(p.integral(y), py) self.assertEqual(p.integral(z), pz) # Definite. lbs = [-3, -2, 2.12] ubs = [-1, 4, 5] px = px.substitute({x: -1}) - px.substitute({x: -3}) self.assertEqual(p.definite_integral([x], lbs[:1], ubs[:1]), px) pxy = px.integral(y) pxy = pxy.substitute({y: 4}) - pxy.substitute({y: -2}) self.assertEqual(p.definite_integral([x, y], lbs[:2], ubs[:2]), pxy) pxyz = pxy.integral(z) pxyz = pxyz.substitute({z: 5}) - pxyz.substitute({z: 2.12}) self.assertEqual(p.definite_integral([x, y, z], lbs, ubs), pxyz) # Definite wrong lengths. with self.assertRaises(ValueError): p.definite_integral([x, y], lbs, ubs) with self.assertRaises(ValueError): p.definite_integral([x, y, z], lbs[:2], ubs) with self.assertRaises(ValueError): p.definite_integral([x, y, z], lbs, ubs[:2]) # Integration of zero polynomial must return a polynomial. p = Polynomial({}) px = p.integral(x) self.assertEqual(px, 0) self.assertTrue(isinstance(px, Polynomial))
def test_add_iadd_sub_isub(self): for Vector in Vectors: # Addition. x = Variable('x') y = Variable('y') v0 = Vector({x: 4, y: 1}) v1 = Vector({x: 5, y: 2}) v2 = Vector({x: 6}) p0 = Polynomial({v1: 2.5, v2: 3}) p1 = Polynomial({v1: 2, v0: 3.33}) p01 = Polynomial({v0: 3.33, v1: 4.5, v2: 3}) self.assertEqual(p0 + p1, p01) with self.assertRaises(TypeError): p0 + 2 with self.assertRaises(TypeError): p0 + 'a' # Iterative addition. p0 += p1 self.assertEqual(p0, p01) with self.assertRaises(TypeError): p0 += 2 with self.assertRaises(TypeError): p0 += 'a' # Subtraction. p0 = Polynomial({v1: 2.5, v2: 3}) p1 = Polynomial({v1: 2, v0: 3.33}) p01 = Polynomial({v0: -3.33, v1: .5, v2: 3}) self.assertEqual(p0 - p1, p01) with self.assertRaises(TypeError): p0 - 2 with self.assertRaises(TypeError): p0 - 'a' # Iterative subtraction. p0 -= p1 self.assertEqual(p0, p01) with self.assertRaises(TypeError): p0 -= 2 with self.assertRaises(TypeError): p0 -= 'a'
def test_in_monomial_basis(self): # Zero-dimensional. m = ChebyshevVector({}) p = Polynomial({MonomialVector({}): 1}) self.assertEqual(m.in_monomial_basis(), p) # One-dimensional. x = Variable('x') m = ChebyshevVector({x: 9}) p = Polynomial({ MonomialVector({x: 1}): 9, MonomialVector({x: 3}): -120, MonomialVector({x: 5}): 432, MonomialVector({x: 7}): -576, MonomialVector({x: 9}): 256, }) self.assertEqual(m.in_monomial_basis(), p) # Two-dimensional. y = Variable('y') m = ChebyshevVector({x: 4, y: 3}) p = Polynomial({ MonomialVector({y: 1}): -3, MonomialVector({y: 3}): 4, MonomialVector({ x: 2, y: 1 }): 24, MonomialVector({ x: 2, y: 3 }): -32, MonomialVector({ x: 4, y: 1 }): -24, MonomialVector({ x: 4, y: 3 }): 32, }) self.assertEqual(m.in_monomial_basis(), p)
def test_init(self): # Variable without index. x = Variable('x') self.assertEqual(x.name, 'x') self.assertEqual(x.index, 0) # Variable with index. x1 = Variable('x', 1) self.assertEqual(x1.name, 'x') self.assertEqual(x1.index, 1) # Wrong initializations. with self.assertRaises(TypeError): Variable(5) with self.assertRaises(ValueError): Variable('x', .5) with self.assertRaises(ValueError): Variable('x', -1)
def test_getter_setter(self): # Getter. x = Variable('x') y = Variable('y') z = Variable('z') v = BasisVector({x: 5, y: 2}) self.assertEqual(v[x], 5) self.assertEqual(v[y], 2) self.assertEqual(v[z], 0) self.assertEqual(len(v), 2) with self.assertRaises(TypeError): v['a'] # Setter. v[x] = 12 v[z] = 6 self.assertEqual(v[x], 12) self.assertEqual(v[y], 2) self.assertEqual(v[z], 6) self.assertEqual(len(v), 3) # Delete instead of setting to zero. v[z] = 0 self.assertEqual(v[z], 0) self.assertEqual(len(v), 2) # Do not set if zero. v[z] = 0 self.assertEqual(v[z], 0) # Non-variable variable. with self.assertRaises(TypeError): v['z'] = 5 with self.assertRaises(TypeError): v[4] = 5 # Non-integer power. with self.assertRaises(ValueError): v[z] = 1.5 with self.assertRaises(ValueError): v[z] = -2
def test_pow(self): for Vector in Vectors: x = Variable('x') y = Variable('y') v0 = Vector({x: 1, y: 3}) v1 = Vector({x: 2, y: 2}) p = Polynomial({v0: 3, v1: 5}) p0 = Polynomial({Vector({}): 1}) self.assertEqual(p**0, p0) p_pow = Polynomial({v0: 3, v1: 5}) for i in range(1, 5): self.assertEqual(p**i, p_pow) p_pow *= p # 0 ** 0 is undefined. p = Polynomial({}) with self.assertRaises(ValueError): p**0
def test_pos_neg(self): for Vector in Vectors: x = Variable('x') y = Variable('y') v0 = Vector({x: 1, y: 3}) v1 = Vector({x: 2, y: 2}) v2 = Vector({x: 4, y: 1}) p = Polynomial({v0: 1 / 3, v1: -5.2, v2: .22}) q = Polynomial({v0: -1 / 3, v1: 5.2, v2: -.22}) p_pos = +p p_neg = -p self.assertEqual(p_pos, p) self.assertEqual(p_neg, q) # Positive and negative must return a copy. p_pos[v0] = 3 p_neg[v0] = 3 self.assertTrue(p_pos != p) self.assertTrue(p_neg != q)
def test_mul_imul_rmul(self): for Vector in Vectors: # Multiplication by scalar. x = Variable('x') y = Variable('y') v0 = Vector({x: 4, y: 1}) v1 = Vector({x: 5, y: 2}) v2 = Vector({x: 6}) p = Polynomial({v1: 2.5, v2: 3}) p6 = Polynomial({v1: 15, v2: 18}) self.assertEqual(p * 6, p6) self.assertEqual(6 * p, p6) p0 = Polynomial({}) self.assertEqual(p * 0, p0) self.assertEqual(0 * p, p0) # Iterative multiplication by scalar. p *= 6 self.assertEqual(p, p6) # Multiplication by polynomial. p0 = Polynomial({v0: 3.1, v1: 5.5}) p1 = Polynomial({v0: -2, v2: 2.9}) p01 = (v0 * v0) * 3.1 * (-2) + \ (v0 * v2) * 3.1 * 2.9 + \ (v1 * v0) * 5.5 * (-2) + \ (v1 * v2) * 5.5 * 2.9 self.assertEqual(p0 * p1, p01) # Iterative multiplication by polynomial. p0 *= p1 self.assertEqual(p0, p01) # Multiplication by zero polynomial must return a polynomial. q = Polynomial({}) p0q = p0 * q self.assertEqual(p0q, 0) self.assertTrue(isinstance(p0q, Polynomial))