def test_deltasummation_mul_x_kd(): assert ds(x*KD(i, j), (j, 1, 3)) == \ Piecewise((x, And(Integer(1) <= i, i <= 3)), (0, True)) assert ds(x * KD(i, j), (j, 1, 1)) == Piecewise((x, Eq(i, 1)), (0, True)) assert ds(x * KD(i, j), (j, 2, 2)) == Piecewise((x, Eq(i, 2)), (0, True)) assert ds(x * KD(i, j), (j, 3, 3)) == Piecewise((x, Eq(i, 3)), (0, True)) assert ds(x*KD(i, j), (j, 1, k)) == \ Piecewise((x, And(Integer(1) <= i, i <= k)), (0, True)) assert ds(x*KD(i, j), (j, k, 3)) == \ Piecewise((x, And(k <= i, i <= 3)), (0, True)) assert ds(x*KD(i, j), (j, k, l)) == \ Piecewise((x, And(k <= i, i <= l)), (0, True))
def test_deltasummation_basic_symbolic(): assert ds(KD(i, j), (j, 1, 3)) == \ Piecewise((1, And(Integer(1) <= i, i <= 3)), (0, True)) assert ds(KD(i, j), (j, 1, 1)) == Piecewise((1, Eq(i, 1)), (0, True)) assert ds(KD(i, j), (j, 2, 2)) == Piecewise((1, Eq(i, 2)), (0, True)) assert ds(KD(i, j), (j, 3, 3)) == Piecewise((1, Eq(i, 3)), (0, True)) assert ds(KD(i, j), (j, 1, k)) == \ Piecewise((1, And(Integer(1) <= i, i <= k)), (0, True)) assert ds(KD(i, j), (j, k, 3)) == \ Piecewise((1, And(k <= i, i <= 3)), (0, True)) assert ds(KD(i, j), (j, k, l)) == \ Piecewise((1, And(k <= i, i <= l)), (0, True))
def test_autowrap_dummy(): # Uses DummyWrapper to test that codegen works as expected f = autowrap(x + y, backend='dummy') assert f() == str(x + y) assert f.args == "x, y" assert f.returns == "nameless" f = autowrap(Eq(z, x + y), backend='dummy') assert f() == str(x + y) assert f.args == "x, y" assert f.returns == "z" f = autowrap(Eq(z, x + y + z), backend='dummy') assert f() == str(x + y + z) assert f.args == "x, y, z" assert f.returns == "z"
def test_deltasummation_mul_x_add_y_kd(): assert ds(x*(y + KD(i, j)), (j, 1, 3)) == \ Piecewise((3*x*y + x, And(Integer(1) <= i, i <= 3)), (3*x*y, True)) assert ds(x*(y + KD(i, j)), (j, 1, 1)) == \ Piecewise((x*y + x, Eq(i, 1)), (x*y, True)) assert ds(x*(y + KD(i, j)), (j, 2, 2)) == \ Piecewise((x*y + x, Eq(i, 2)), (x*y, True)) assert ds(x*(y + KD(i, j)), (j, 3, 3)) == \ Piecewise((x*y + x, Eq(i, 3)), (x*y, True)) assert ds(x*(y + KD(i, j)), (j, 1, k)) == \ Piecewise((k*x*y + x, And(Integer(1) <= i, i <= k)), (k*x*y, True)) assert ds(x*(y + KD(i, j)), (j, k, 3)) == \ Piecewise(((4 - k)*x*y + x, And(k <= i, i <= 3)), ((4 - k)*x*y, True)) assert ds(x * (y + KD(i, j)), (j, k, l)) == Piecewise( ((l - k + 1) * x * y + x, And(k <= i, i <= l)), ((l - k + 1) * x * y, True))
def test_m_loops(): # Note: an Octave programmer would probably vectorize this across one or # more dimensions. Also, size(A) would be used rather than passing in m # and n. Perhaps users would expect us to vectorize automatically here? # Or is it possible to represent such things using IndexedBase? from diofant.tensor import IndexedBase, Idx from diofant import symbols n, m = symbols('n m', integer=True) A = IndexedBase('A') x = IndexedBase('x') y = IndexedBase('y') i = Idx('i', m) j = Idx('j', n) result, = codegen(('mat_vec_mult', Eq(y[i], A[i, j] * x[j])), "Octave", header=False, empty=False) source = result[1] expected = ('function y = mat_vec_mult(A, m, n, x)\n' ' for i = 1:m\n' ' y(i) = 0;\n' ' end\n' ' for i = 1:m\n' ' for j = 1:n\n' ' y(i) = %(rhs)s + y(i);\n' ' end\n' ' end\n' 'end\n') assert (source == expected % { 'rhs': 'A(%s, %s).*x(j)' % (i, j) } or source == expected % { 'rhs': 'x(j).*A(%s, %s)' % (i, j) })
def test_m_tensor_loops_multiple_contractions(): # see comments in previous test about vectorizing from diofant.tensor import IndexedBase, Idx from diofant import symbols n, m, o, p = symbols('n m o p', integer=True) A = IndexedBase('A') B = IndexedBase('B') y = IndexedBase('y') i = Idx('i', m) j = Idx('j', n) k = Idx('k', o) l = Idx('l', p) result, = codegen(('tensorthing', Eq(y[i], B[j, k, l] * A[i, j, k, l])), "Octave", header=False, empty=False) source = result[1] expected = ('function y = tensorthing(A, B, m, n, o, p)\n' ' for i = 1:m\n' ' y(i) = 0;\n' ' end\n' ' for i = 1:m\n' ' for j = 1:n\n' ' for k = 1:o\n' ' for l = 1:p\n' ' y(i) = y(i) + B(j, k, l).*A(i, j, k, l);\n' ' end\n' ' end\n' ' end\n' ' end\n' 'end\n') assert source == expected
def test_autowrap_args(): x, y, z = symbols('x y z') pytest.raises(CodeGenArgumentListError, lambda: autowrap(Eq(z, x + y), backend='dummy', args=(x,))) f = autowrap(Eq(z, x + y), backend='dummy', args=(y, x)) assert f() == str(x + y) assert f.args == "y, x" assert f.returns == "z" pytest.raises(CodeGenArgumentListError, lambda: autowrap(Eq(z, x + y + z), backend='dummy', args=(x, y))) f = autowrap(Eq(z, x + y + z), backend='dummy', args=(y, x, z)) assert f() == str(x + y + z) assert f.args == "y, x, z" assert f.returns == "z"
def test_ccode_Indexed_without_looking_for_contraction(): len_y = 5 y = IndexedBase('y', shape=(len_y, )) x = IndexedBase('x', shape=(len_y, )) Dy = IndexedBase('Dy', shape=(len_y - 1, )) i = Idx('i', len_y - 1) e = Eq(Dy[i], (y[i + 1] - y[i]) / (x[i + 1] - x[i])) code0 = ccode(e.rhs, assign_to=e.lhs, contract=False) assert code0 == 'Dy[i] = (y[%s] - y[i])/(x[%s] - x[i]);' % (i + 1, i + 1)
def test_minimize_linear(): assert minimize([ -2 * x - 3 * y - 2 * z, 2 * x + y + z <= 4, x + 2 * y + z <= 7, z <= 5, x >= 0, y >= 0, z >= 0 ], x, y, z) == (-11, { x: 0, y: 3, z: 1 }) assert minimize([ -2 * x - 3 * y - 2 * z, 2 * x + y + z <= 4, x + 2 * y + z <= 7, z <= 5, x >= 0, y >= 0, z >= 0 ], x, y, z) == (-11, { x: 0, y: 3, z: 1 }) assert minimize([ -2 * x - 3 * y - 2 * z, 2 * x + y + z <= 4, x + 2 * y + z < 7, z <= 5, x >= 0, y >= 0, z >= 0 ], x, y, z) is None assert minimize([ -2 * x - 3 * y - 4 * z, 3 * x + 2 * y + z <= 10, 2 * x + 5 * y + 3 * z <= 15, x >= 0, y >= 0, z >= 0 ], x, y, z) == (-20, { x: 0, y: 0, z: 5 }) assert maximize([ 12 * x + 40 * y, x + y <= 15, x + 3 * y <= 36, x <= 10, x >= 0, y >= 0 ], x, y) == (480, { x: 0, y: 12 }) assert minimize([ -2 * x - 3 * y - 4 * z, Eq(3 * x + 2 * y + z, 10), Eq(2 * x + 5 * y + 3 * z, 15), x >= 0, y >= 0, z >= 0 ], x, y, z) == (Rational(-130, 7), { x: Rational(15, 7), y: 0, z: Rational(25, 7) })
def test_deltasummation_mul_add_x_kd_add_y_kd(): assert ds((x + KD(i, k)) * (y + KD(i, j)), (j, 1, 3)) == piecewise_fold( Piecewise((KD(i, k) + x, And(Integer(1) <= i, i <= 3)), (0, True)) + 3 * (KD(i, k) + x) * y) assert ds((x + KD(i, k)) * (y + KD(i, j)), (j, 1, 1)) == piecewise_fold( Piecewise((KD(i, k) + x, Eq(i, 1)), (0, True)) + (KD(i, k) + x) * y) assert ds((x + KD(i, k)) * (y + KD(i, j)), (j, 2, 2)) == piecewise_fold( Piecewise((KD(i, k) + x, Eq(i, 2)), (0, True)) + (KD(i, k) + x) * y) assert ds((x + KD(i, k)) * (y + KD(i, j)), (j, 3, 3)) == piecewise_fold( Piecewise((KD(i, k) + x, Eq(i, 3)), (0, True)) + (KD(i, k) + x) * y) assert ds((x + KD(i, k)) * (y + KD(i, j)), (j, 1, k)) == piecewise_fold( Piecewise((KD(i, k) + x, And(Integer(1) <= i, i <= k)), (0, True)) + k * (KD(i, k) + x) * y) assert ds((x + KD(i, k)) * (y + KD(i, j)), (j, k, 3)) == piecewise_fold( Piecewise((KD(i, k) + x, And(k <= i, i <= 3)), (0, True)) + (4 - k) * (KD(i, k) + x) * y) assert ds((x + KD(i, k)) * (y + KD(i, j)), (j, k, l)) == piecewise_fold( Piecewise((KD(i, k) + x, And(k <= i, i <= l)), (0, True)) + (l - k + 1) * (KD(i, k) + x) * y)
def test_minimize_linear_2(): assert minimize([ 2 * x + 3 * y - z, 1 <= x + y + z, x + y + z <= 2, 1 <= x - y + z, x - y + z <= 2, Eq(x - y - z, 3) ], x, y, z) == (3, { x: 2, y: -S.Half, z: -S.Half })
def test_trigintegrate_odd(): assert trigintegrate(Rational(1), x) == x assert trigintegrate(x, x) is None assert trigintegrate(x**2, x) is None assert trigintegrate(sin(x), x) == -cos(x) assert trigintegrate(cos(x), x) == sin(x) assert trigintegrate(sin(3 * x), x) == -cos(3 * x) / 3 assert trigintegrate(cos(3 * x), x) == sin(3 * x) / 3 y = Symbol('y') assert trigintegrate(sin(y*x), x) == \ Piecewise((0, Eq(y, 0)), (-cos(y*x)/y, True)) assert trigintegrate(cos(y*x), x) == \ Piecewise((x, Eq(y, 0)), (sin(y*x)/y, True)) assert trigintegrate(sin(y*x)**2, x) == \ Piecewise((0, Eq(y, 0)), ((x*y/2 - sin(x*y)*cos(x*y)/2)/y, True)) assert trigintegrate(sin(y*x)*cos(y*x), x) == \ Piecewise((0, Eq(y, 0)), (sin(x*y)**2/(2*y), True)) assert trigintegrate(cos(y*x)**2, x) == \ Piecewise((x, Eq(y, 0)), ((x*y/2 + sin(x*y)*cos(x*y)/2)/y, True)) y = Symbol('y', positive=True) # TODO: remove conds='none' below. For this to work we would have to rule # out (e.g. by trying solve) the condition y = 0, incompatible with # y.is_positive being True. assert trigintegrate(sin(y * x), x, conds='none') == -cos(y * x) / y assert trigintegrate(cos(y * x), x, conds='none') == sin(y * x) / y assert trigintegrate(sin(x) * cos(x), x) == sin(x)**2 / 2 assert trigintegrate(sin(x) * cos(x)**2, x) == -cos(x)**3 / 3 assert trigintegrate(sin(x)**2 * cos(x), x) == sin(x)**3 / 3 # check if it selects right function to substitute, # so the result is kept simple assert trigintegrate(sin(x)**7 * cos(x), x) == sin(x)**8 / 8 assert trigintegrate(sin(x) * cos(x)**7, x) == -cos(x)**8 / 8 assert trigintegrate(sin(x)**7 * cos(x)**3, x) == \ -sin(x)**10/10 + sin(x)**8/8 assert trigintegrate(sin(x)**3 * cos(x)**7, x) == \ cos(x)**10/10 - cos(x)**8/8
def test_cython_wrapper_inoutarg(): code_gen = CythonCodeWrapper(CCodeGen()) routine = make_routine("test", Eq(z, x + y + z)) source = get_string(code_gen.dump_pyx, [routine]) expected = ("cdef extern from 'file.h':\n" " void test(double x, double y, double *z)\n" "\n" "def test_c(double x, double y, double z):\n" "\n" " test(x, y, &z)\n" " return z") assert source == expected
def test_deltasummation_mul_add_x_y_add_kd_kd(): assert ds((x + y) * (KD(i, k) + KD(j, k)), (k, 1, 3)) == piecewise_fold( Piecewise((x + y, And(Integer(1) <= i, i <= 3)), (0, True)) + Piecewise((x + y, And(Integer(1) <= j, j <= 3)), (0, True))) assert ds((x + y) * (KD(i, k) + KD(j, k)), (k, 1, 1)) == piecewise_fold( Piecewise((x + y, Eq(i, 1)), (0, True)) + Piecewise((x + y, Eq(j, 1)), (0, True))) assert ds((x + y) * (KD(i, k) + KD(j, k)), (k, 2, 2)) == piecewise_fold( Piecewise((x + y, Eq(i, 2)), (0, True)) + Piecewise((x + y, Eq(j, 2)), (0, True))) assert ds((x + y) * (KD(i, k) + KD(j, k)), (k, 3, 3)) == piecewise_fold( Piecewise((x + y, Eq(i, 3)), (0, True)) + Piecewise((x + y, Eq(j, 3)), (0, True))) assert ds((x + y) * (KD(i, k) + KD(j, k)), (k, 1, l)) == piecewise_fold( Piecewise((x + y, And(Integer(1) <= i, i <= l)), (0, True)) + Piecewise((x + y, And(Integer(1) <= j, j <= l)), (0, True))) assert ds((x + y) * (KD(i, k) + KD(j, k)), (k, l, 3)) == piecewise_fold( Piecewise((x + y, And(l <= i, i <= 3)), (0, True)) + Piecewise((x + y, And(l <= j, j <= 3)), (0, True))) assert ds((x + y) * (KD(i, k) + KD(j, k)), (k, l, m)) == piecewise_fold( Piecewise((x + y, And(l <= i, i <= m)), (0, True)) + Piecewise((x + y, And(l <= j, j <= m)), (0, True)))
def test_diofantissue_469(): A = MatrixSymbol("A", n, n) B = MatrixSymbol("B", n, n) expr = Eq(A, B) assert simplify(expr) == expr
def test_Relational(): assert mcode(Eq(x, y)) == 'x == y' assert mcode(Ne(x, y/(1 + y**2))) == 'x != y/(y^2 + 1)' assert mcode(Le(0, x**2)) == '0 <= x^2' assert mcode(Gt(pi, 3, evaluate=False)) == 'Pi > 3'
def test_rewrite_as_Piecewise(): x, y = symbols('x, y', real=True) assert (Max(x, y).rewrite(Piecewise) == x * Piecewise( (1, x - y > 0), (Rational(1, 2), Eq(x - y, 0)), (0, true)) + y * Piecewise((1, -x + y > 0), (Rational(1, 2), Eq(-x + y, 0)), (0, true)))
def trigintegrate(f, x, conds='piecewise'): """Integrate f = Mul(trig) over x >>> from diofant import Symbol, sin, cos, tan, sec, csc, cot >>> from diofant.integrals.trigonometry import trigintegrate >>> from diofant.abc import x >>> trigintegrate(sin(x)*cos(x), x) sin(x)**2/2 >>> trigintegrate(sin(x)**2, x) x/2 - sin(x)*cos(x)/2 >>> trigintegrate(tan(x)*sec(x), x) 1/cos(x) >>> trigintegrate(sin(x)*tan(x), x) -log(sin(x) - 1)/2 + log(sin(x) + 1)/2 - sin(x) http://en.wikibooks.org/wiki/Calculus/Integration_techniques See Also ======== diofant.integrals.integrals.Integral.doit diofant.integrals.integrals.Integral """ from diofant.integrals.integrals import integrate pat, a, n, m = _pat_sincos(x) f = f.rewrite('sincos') M = f.match(pat) if M is None: return n, m = M[n], M[m] if n is S.Zero and m is S.Zero: return x zz = x if n is S.Zero else S.Zero a = M[a] if n.is_odd or m.is_odd: u = _u n_, m_ = n.is_odd, m.is_odd # take smallest n or m -- to choose simplest substitution if n_ and m_: n_ = n_ and (n < m) # NB: careful here, one of the m_ = m_ and not (n < m) # conditions *must* be true # n m u=C (n-1)/2 m # S(x) * C(x) dx --> -(1-u^2) * u du if n_: ff = -(1 - u**2)**((n - 1) / 2) * u**m uu = cos(a * x) # n m u=S n (m-1)/2 # S(x) * C(x) dx --> u * (1-u^2) du elif m_: ff = u**n * (1 - u**2)**((m - 1) / 2) uu = sin(a * x) fi = integrate(ff, u) # XXX cyclic deps fx = fi.subs(u, uu) if conds == 'piecewise': return Piecewise((zz, Eq(a, 0)), (fx / a, True)) return fx / a # n & m are both even # # 2k 2m 2l 2l # we transform S (x) * C (x) into terms with only S (x) or C (x) # # example: # 100 4 100 2 2 100 4 2 # S (x) * C (x) = S (x) * (1-S (x)) = S (x) * (1 + S (x) - 2*S (x)) # # 104 102 100 # = S (x) - 2*S (x) + S (x) # 2k # then S is integrated with recursive formula # take largest n or m -- to choose simplest substitution n_ = (abs(n) > abs(m)) m_ = (abs(m) > abs(n)) res = S.Zero if n_: # 2k 2 k i 2i # C = (1 - S ) = sum(i, (-) * B(k, i) * S ) if m > 0: for i in range(0, m // 2 + 1): res += ((-1)**i * binomial(m // 2, i) * _sin_pow_integrate(n + 2 * i, x)) elif m == 0: res = _sin_pow_integrate(n, x) else: # m < 0 , |n| > |m| # / # | # | m n # | cos (x) sin (x) dx = # | # | # / # / # | # -1 m+1 n-1 n - 1 | m+2 n-2 # ________ cos (x) sin (x) + _______ | cos (x) sin (x) dx # | # m + 1 m + 1 | # / res = (Rational(-1, m + 1) * cos(x)**(m + 1) * sin(x)**(n - 1) + Rational(n - 1, m + 1) * trigintegrate(cos(x)**(m + 2) * sin(x)**(n - 2), x)) elif m_: # 2k 2 k i 2i # S = (1 - C ) = sum(i, (-) * B(k, i) * C ) if n > 0: # / / # | | # | m n | -m n # | cos (x)*sin (x) dx or | cos (x) * sin (x) dx # | | # / / # # |m| > |n| ; m, n >0 ; m, n belong to Z - {0} # n 2 # sin (x) term is expanded here in terms of cos (x), # and then integrated. # for i in range(0, n // 2 + 1): res += ((-1)**i * binomial(n // 2, i) * _cos_pow_integrate(m + 2 * i, x)) elif n == 0: # / # | # | 1 # | _ _ _ # | m # | cos (x) # / # res = _cos_pow_integrate(m, x) else: # n < 0 , |m| > |n| # / # | # | m n # | cos (x) sin (x) dx = # | # | # / # / # | # 1 m-1 n+1 m - 1 | m-2 n+2 # _______ cos (x) sin (x) + _______ | cos (x) sin (x) dx # | # n + 1 n + 1 | # / res = (Rational(1, n + 1) * cos(x)**(m - 1) * sin(x)**(n + 1) + Rational(m - 1, n + 1) * trigintegrate(cos(x)**(m - 2) * sin(x)**(n + 2), x)) else: if m == n: # Substitute sin(2x)/2 for sin(x)cos(x) and then Integrate. res = integrate((Rational(1, 2) * sin(2 * x))**m, x) elif (m == -n): if n < 0: # Same as the scheme described above. # the function argument to integrate in the end will # be 1 , this cannot be integrated by trigintegrate. # Hence use diofant.integrals.integrate. res = (Rational(1, n + 1) * cos(x)**(m - 1) * sin(x)**(n + 1) + Rational(m - 1, n + 1) * integrate(cos(x)**(m - 2) * sin(x)**(n + 2), x)) else: res = ( Rational(-1, m + 1) * cos(x)**(m + 1) * sin(x)**(n - 1) + Rational(n - 1, m + 1) * integrate(cos(x)**(m + 2) * sin(x)**(n - 2), x)) if conds == 'piecewise': return Piecewise((zz, Eq(a, 0)), (res.subs(x, a * x) / a, True)) return res.subs(x, a * x) / a
def test_minimize_linear(): assert minimize([ -2 * x - 3 * y - 2 * z, 2 * x + y + z <= 4, x + 2 * y + z <= 7, z <= 5, x >= 0, y >= 0, z >= 0 ], x, y, z) == (-11, { x: 0, y: 3, z: 1 }) assert minimize([ -2 * x - 3 * y - 2 * z, 2 * x + y + z <= 4, x + 2 * y + z <= 7, z <= 5, x >= 0, y >= 0, z >= 0 ], x, y, z) == (-11, { x: 0, y: 3, z: 1 }) assert minimize([ -2 * x - 3 * y - 2 * z, 2 * x + y + z <= 4, x + 2 * y + z < 7, z <= 5, x >= 0, y >= 0, z >= 0 ], x, y, z) is None assert minimize([ -2 * x - 3 * y - 4 * z, 3 * x + 2 * y + z <= 10, 2 * x + 5 * y + 3 * z <= 15, x >= 0, y >= 0, z >= 0 ], x, y, z) == (-20, { x: 0, y: 0, z: 5 }) assert maximize([ 12 * x + 40 * y, x + y <= 15, x + 3 * y <= 36, x <= 10, x >= 0, y >= 0 ], x, y) == (480, { x: 0, y: 12 }) assert minimize([ -2 * x - 3 * y - 4 * z, Eq(3 * x + 2 * y + z, 10), Eq(2 * x + 5 * y + 3 * z, 15), x >= 0, y >= 0, z >= 0 ], x, y, z) == (Rational(-130, 7), { x: Rational(15, 7), y: 0, z: Rational(25, 7) }) assert maximize([2 * x + y, y - x <= 1, x - 2 * y <= 2, x >= 0, y >= 0], x, y) == (oo, { x: nan, y: nan }) assert minimize([ 2 * x + 3 * y - z, 1 <= x + y + z, x + y + z <= 2, 1 <= x - y + z, x - y + z <= 2, Eq(x - y - z, 3) ], x, y, z) == (3, { x: 2, y: Rational(-1, 2), z: Rational(-1, 2) }) x1, x2, x3, x4, x5 = symbols('x1:6') assert minimize([ -2 * x1 + 4 * x2 + 7 * x3 + x4 + 5 * x5, Eq(-x1 + x2 + 2 * x3 + x4 + 2 * x5, 7), Eq(-x1 + 2 * x2 + 3 * x3 + x4 + x5, 6), Eq(-x1 + x2 + x3 + 2 * x4 + x5, 4), x2 >= 0, x3 >= 0, x4 >= 0, x5 >= 0 ], x1, x2, x3, x4, x5) == (19, { x1: -1, x2: 0, x3: 1, x4: 0, x5: 2 }) assert minimize([ -x - y, x + 2 * y <= 8, 3 * x + 2 * y <= 12, x + 3 * y >= 6, x >= 0, y >= 0 ], x, y) == (-5, { x: 2, y: 3 }) pytest.raises( InfeasibleProblem, lambda: minimize([ -x - y, x + 2 * y <= 8, 3 * x + 2 * y <= 12, x + 3 * y >= 13, x >= 0, y >= 0 ], x, y)) pytest.raises( InfeasibleProblem, lambda: minimize([ -x - y, x + 2 * y <= 8, 3 * x + 2 * y <= 12, x + 3 * y >= 13, x >= 0, y >= 0 ], x, y)) assert minimize([-x - y, 2 * x + y >= 4, Eq(x + 2 * y, 6), x >= 0, y >= 0], x, y) == (-6, { x: 6, y: 0 }) assert minimize([ 6 * x + 3 * y, x + y >= 1, 2 * x - y >= 1, 3 * y <= 2, x >= 0, y >= 0 ], x, y) == (5, { x: Rational(2, 3), y: Rational(1, 3) })