def get_paper_part_frac(degree):
from ..partialfrac import thetas_alphas_to_expr_complex
from sympy import Float, I
# Values above are negative what we expect. It also only includes one of
# each complex conjugate, which is fine so long as we pass in the positive
# imaginary parts for the thetas.
thetas = [-Float(r) + Float(i)*I for r, i in
zip(part_frac_coeffs[degree]['thetas']['real'],
part_frac_coeffs[degree]['thetas']['imaginary'])]
alphas = [-Float(r) + Float(i)*I for r, i in
zip(part_frac_coeffs[degree]['alphas']['real'],
part_frac_coeffs[degree]['alphas']['imaginary'])]
[alpha0] = [Float(r) + Float(i)*I for r, i in
zip(part_frac_coeffs[degree]['alpha0']['real'],
part_frac_coeffs[degree]['alpha0']['imaginary'])]
return thetas_alphas_to_expr_complex(thetas, alphas, alpha0)
python类I的实例源码
def get_paper_thetas_alphas(degree):
from sympy import Float, I
thetas = [-Float(r) + Float(i)*I for r, i in
zip(part_frac_coeffs[degree]['thetas']['real'],
part_frac_coeffs[degree]['thetas']['imaginary'])]
thetas = thetas + [i.conjugate() for i in thetas]
alphas = [-Float(r) + Float(i)*I for r, i in
zip(part_frac_coeffs[degree]['alphas']['real'],
part_frac_coeffs[degree]['alphas']['imaginary'])]
alphas = alphas + [i.conjugate() for i in alphas]
[alpha0] = [Float(r) + Float(i)*I for r, i in
zip(part_frac_coeffs[degree]['alpha0']['real'],
part_frac_coeffs[degree]['alpha0']['imaginary'])]
return thetas, alphas, alpha0
def test_prudnikov_misc():
assert can_do([1, (3 + I)/2, (3 - I)/2], [S(3)/2, 2])
assert can_do([S.Half, a - 1], [S(3)/2, a + 1], lowerplane=True)
assert can_do([], [b + 1])
assert can_do([a], [a - 1, b + 1])
assert can_do([a], [a - S.Half, 2*a])
assert can_do([a], [a - S.Half, 2*a + 1])
assert can_do([a], [a - S.Half, 2*a - 1])
assert can_do([a], [a + S.Half, 2*a])
assert can_do([a], [a + S.Half, 2*a + 1])
assert can_do([a], [a + S.Half, 2*a - 1])
assert can_do([S.Half], [b, 2 - b])
assert can_do([S.Half], [b, 3 - b])
assert can_do([1], [2, b])
assert can_do([a, a + S.Half], [2*a, b, 2*a - b + 1])
assert can_do([a, a + S.Half], [S.Half, 2*a, 2*a + S.Half])
assert can_do([a], [a + 1], lowerplane=True) # lowergamma
def test_use():
assert use(0, expand) == 0
f = (x + y)**2*x + 1
assert use(f, expand, level=0) == x**3 + 2*x**2*y + x*y**2 + + 1
assert use(f, expand, level=1) == x**3 + 2*x**2*y + x*y**2 + + 1
assert use(f, expand, level=2) == 1 + x*(2*x*y + x**2 + y**2)
assert use(f, expand, level=3) == (x + y)**2*x + 1
f = (x**2 + 1)**2 - 1
kwargs = {'gaussian': True}
assert use(f, factor, level=0, kwargs=kwargs) == x**2*(x**2 + 2)
assert use(f, factor, level=1, kwargs=kwargs) == (x + I)**2*(x - I)**2 - 1
assert use(f, factor, level=2, kwargs=kwargs) == (x + I)**2*(x - I)**2 - 1
assert use(f, factor, level=3, kwargs=kwargs) == (x**2 + 1)**2 - 1
def as_real_imag(self, deep=True, **hints):
"""
returns a tuple represeting a complex numbers
Examples
========
>>> from sympy import I
>>> (7 + 9*I).as_real_imag()
(7, 9)
>>> ((1 + I)/(1 - I)).as_real_imag()
(0, 1)
>>> ((1 + 2*I)*(1 + 3*I)).as_real_imag()
(-5, 5)
"""
sargs, terms = self.args, []
re_part, im_part = [], []
for term in sargs:
re, im = term.as_real_imag(deep=deep)
re_part.append(re)
im_part.append(im)
return (self.func(*re_part), self.func(*im_part))
def test_pow_eval():
# XXX Pow does not fully support conversion of negative numbers
# to their complex equivalent
assert sqrt(-1) == I
assert sqrt(-4) == 2*I
assert sqrt( 4) == 2
assert (8)**Rational(1, 3) == 2
assert (-8)**Rational(1, 3) == 2*((-1)**Rational(1, 3))
assert sqrt(-2) == I*sqrt(2)
assert (-1)**Rational(1, 3) != I
assert (-10)**Rational(1, 3) != I*((10)**Rational(1, 3))
assert (-2)**Rational(1, 4) != (2)**Rational(1, 4)
assert 64**Rational(1, 3) == 4
assert 64**Rational(2, 3) == 16
assert 24/sqrt(64) == 3
assert (-27)**Rational(1, 3) == 3*(-1)**Rational(1, 3)
assert (cos(2) / tan(2))**2 == (cos(2) / tan(2))**2
def test_p():
assert Px.hilbert_space == L2(Interval(S.NegativeInfinity, S.Infinity))
assert qapply(Px*PxKet(px)) == px*PxKet(px)
assert PxKet(px).dual_class() == PxBra
assert PxBra(x).dual_class() == PxKet
assert (Dagger(PxKet(py))*PxKet(px)).doit() == DiracDelta(px - py)
assert (XBra(x)*PxKet(px)).doit() == \
exp(I*x*px/hbar)/sqrt(2*pi*hbar)
assert represent(PxKet(px)) == DiracDelta(px - px_1)
rep_x = represent(PxOp(), basis=XOp)
assert rep_x == -hbar*I*DiracDelta(x_1 - x_2)*DifferentialOperator(x_1)
assert rep_x == represent(PxOp(), basis=XOp())
assert rep_x == represent(PxOp(), basis=XKet)
assert rep_x == represent(PxOp(), basis=XKet())
assert represent(PxOp()*XKet(), basis=XKet) == \
-hbar*I*DiracDelta(x - x_2)*DifferentialOperator(x)
assert represent(XBra("y")*PxOp()*XKet(), basis=XKet) == \
-hbar*I*DiracDelta(x - y)*DifferentialOperator(x)
def test_scalars():
x = symbols('x', complex=True)
assert Dagger(x) == conjugate(x)
assert Dagger(I*x) == -I*conjugate(x)
i = symbols('i', real=True)
assert Dagger(i) == i
p = symbols('p')
assert isinstance(Dagger(p), adjoint)
i = Integer(3)
assert Dagger(i) == i
A = symbols('A', commutative=False)
assert Dagger(A).is_commutative is False
def test_quantum_fourier():
assert QFT(0, 3).decompose() == \
SwapGate(0, 2)*HadamardGate(0)*CGate((0,), PhaseGate(1)) * \
HadamardGate(1)*CGate((0,), TGate(2))*CGate((1,), PhaseGate(2)) * \
HadamardGate(2)
assert IQFT(0, 3).decompose() == \
HadamardGate(2)*CGate((1,), RkGate(2, -2))*CGate((0,), RkGate(2, -3)) * \
HadamardGate(1)*CGate((0,), RkGate(1, -2))*HadamardGate(0)*SwapGate(0, 2)
assert represent(QFT(0, 3), nqubits=3) == \
Matrix([[exp(2*pi*I/8)**(i*j % 8)/sqrt(8) for i in range(8)] for j in range(8)])
assert QFT(0, 4).decompose() # non-trivial decomposition
assert qapply(QFT(0, 3).decompose()*Qubit(0, 0, 0)).expand() == qapply(
HadamardGate(0)*HadamardGate(1)*HadamardGate(2)*Qubit(0, 0, 0)
).expand()
def test_Pauli():
#this and the following test are testing both Pauli and Dirac matrices
#and also that the general Matrix class works correctly in a real world
#situation
sigma1 = msigma(1)
sigma2 = msigma(2)
sigma3 = msigma(3)
assert sigma1 == sigma1
assert sigma1 != sigma2
# sigma*I -> I*sigma (see #354)
assert sigma1*sigma2 == sigma3*I
assert sigma3*sigma1 == sigma2*I
assert sigma2*sigma3 == sigma1*I
assert sigma1*sigma1 == eye(2)
assert sigma2*sigma2 == eye(2)
assert sigma3*sigma3 == eye(2)
assert sigma1*2*sigma1 == 2*eye(2)
assert sigma1*sigma3*sigma1 == -sigma3
def test_Znm():
# http://en.wikipedia.org/wiki/Solid_harmonics#List_of_lowest_functions
th, ph = Symbol("theta", real=True), Symbol("phi", real=True)
from sympy.abc import n,m
assert Znm(0, 0, th, ph) == Ynm(0, 0, th, ph)
assert Znm(1, -1, th, ph) == (-sqrt(2)*I*(Ynm(1, 1, th, ph)
- exp(-2*I*ph)*Ynm(1, 1, th, ph))/2)
assert Znm(1, 0, th, ph) == Ynm(1, 0, th, ph)
assert Znm(1, 1, th, ph) == (sqrt(2)*(Ynm(1, 1, th, ph)
+ exp(-2*I*ph)*Ynm(1, 1, th, ph))/2)
assert Znm(0, 0, th, ph).expand(func=True) == 1/(2*sqrt(pi))
assert Znm(1, -1, th, ph).expand(func=True) == (sqrt(3)*I*sqrt(-cos(th)**2 + 1)*exp(I*ph)/(4*sqrt(pi))
- sqrt(3)*I*sqrt(-cos(th)**2 + 1)*exp(-I*ph)/(4*sqrt(pi)))
assert Znm(1, 0, th, ph).expand(func=True) == sqrt(3)*cos(th)/(2*sqrt(pi))
assert Znm(1, 1, th, ph).expand(func=True) == (-sqrt(3)*sqrt(-cos(th)**2 + 1)*exp(I*ph)/(4*sqrt(pi))
- sqrt(3)*sqrt(-cos(th)**2 + 1)*exp(-I*ph)/(4*sqrt(pi)))
assert Znm(2, -1, th, ph).expand(func=True) == (sqrt(15)*I*sqrt(-cos(th)**2 + 1)*exp(I*ph)*cos(th)/(4*sqrt(pi))
- sqrt(15)*I*sqrt(-cos(th)**2 + 1)*exp(-I*ph)*cos(th)/(4*sqrt(pi)))
assert Znm(2, 0, th, ph).expand(func=True) == 3*sqrt(5)*cos(th)**2/(4*sqrt(pi)) - sqrt(5)/(4*sqrt(pi))
assert Znm(2, 1, th, ph).expand(func=True) == (-sqrt(15)*sqrt(-cos(th)**2 + 1)*exp(I*ph)*cos(th)/(4*sqrt(pi))
- sqrt(15)*sqrt(-cos(th)**2 + 1)*exp(-I*ph)*cos(th)/(4*sqrt(pi)))
def _eval_expand_func(self, **hints):
from sympy import log, expand_mul, Dummy, exp_polar, I
s, z = self.args
if s == 1:
return -log(1 + exp_polar(-I*pi)*z)
if s.is_Integer and s <= 0:
u = Dummy('u')
start = u/(1 - u)
for _ in range(-s):
start = u*start.diff(u)
return expand_mul(start).subs(u, z)
return polylog(s, z)
###############################################################################
###################### HURWITZ GENERALIZED ZETA FUNCTION ######################
###############################################################################
def fdiff(self, argindex=4):
if argindex == 1:
# Diff wrt n
raise ArgumentIndexError(self, argindex)
elif argindex == 2:
# Diff wrt m
raise ArgumentIndexError(self, argindex)
elif argindex == 3:
# Diff wrt theta
n, m, theta, phi = self.args
return (m * C.cot(theta) * Ynm(n, m, theta, phi) +
sqrt((n - m)*(n + m + 1)) * C.exp(-I*phi) * Ynm(n, m + 1, theta, phi))
elif argindex == 4:
# Diff wrt phi
n, m, theta, phi = self.args
return I * m * Ynm(n, m, theta, phi)
else:
raise ArgumentIndexError(self, argindex)
def test_root():
from sympy.abc import x, y, z
n = Symbol('n', 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)
def _fourier_transform(f, x, k, a, b, name, simplify=True):
"""
Compute a general Fourier-type transform
F(k) = a int_-oo^oo exp(b*I*x*k) f(x) dx.
For suitable choice of a and b, this reduces to the standard Fourier
and inverse Fourier transforms.
"""
from sympy import exp, I, oo
F = integrate(a*f*exp(b*I*x*k), (x, -oo, oo))
if not F.has(Integral):
return _simplify(F, simplify), True
if not F.is_Piecewise:
raise IntegralTransformError(name, f, 'could not compute integral')
F, cond = F.args[0]
if F.has(Integral):
raise IntegralTransformError(name, f, 'integral in unexpected form')
return _simplify(F, simplify), cond
def test_special_denom():
# TODO: add more tests here
DE = DifferentialExtension(extension={'D': [Poly(1, x), Poly(t, t)]})
assert special_denom(Poly(1, t), Poly(t**2, t), Poly(1, t), Poly(t**2 - 1, t),
Poly(t, t), DE) == \
(Poly(1, t), Poly(t**2 - 1, t), Poly(t**2 - 1, t), Poly(t, t))
# assert special_denom(Poly(1, t), Poly(2*x, t), Poly((1 + 2*x)*t, t), DE) == 1
# issue 3940
# Note, this isn't a very good test, because the denominator is just 1,
# but at least it tests the exp cancellation case
DE = DifferentialExtension(extension={'D': [Poly(1, x), Poly(-2*x*t0, t0),
Poly(I*k*t1, t1)]})
DE.decrement_level()
assert special_denom(Poly(1, t0), Poly(I*k, t0), Poly(1, t0), Poly(t0, t0),
Poly(1, t0), DE) == \
(Poly(1, t0), Poly(I*k, t0), Poly(t0, t0), Poly(1, t0))
def test_prudnikov_misc():
assert can_do([1, (3 + I)/2, (3 - I)/2], [S(3)/2, 2])
assert can_do([S.Half, a - 1], [S(3)/2, a + 1], lowerplane=True)
assert can_do([], [b + 1])
assert can_do([a], [a - 1, b + 1])
assert can_do([a], [a - S.Half, 2*a])
assert can_do([a], [a - S.Half, 2*a + 1])
assert can_do([a], [a - S.Half, 2*a - 1])
assert can_do([a], [a + S.Half, 2*a])
assert can_do([a], [a + S.Half, 2*a + 1])
assert can_do([a], [a + S.Half, 2*a - 1])
assert can_do([S.Half], [b, 2 - b])
assert can_do([S.Half], [b, 3 - b])
assert can_do([1], [2, b])
assert can_do([a, a + S.Half], [2*a, b, 2*a - b + 1])
assert can_do([a, a + S.Half], [S.Half, 2*a, 2*a + S.Half])
assert can_do([a], [a + 1], lowerplane=True) # lowergamma
def test_use():
assert use(0, expand) == 0
f = (x + y)**2*x + 1
assert use(f, expand, level=0) == x**3 + 2*x**2*y + x*y**2 + + 1
assert use(f, expand, level=1) == x**3 + 2*x**2*y + x*y**2 + + 1
assert use(f, expand, level=2) == 1 + x*(2*x*y + x**2 + y**2)
assert use(f, expand, level=3) == (x + y)**2*x + 1
f = (x**2 + 1)**2 - 1
kwargs = {'gaussian': True}
assert use(f, factor, level=0, kwargs=kwargs) == x**2*(x**2 + 2)
assert use(f, factor, level=1, kwargs=kwargs) == (x + I)**2*(x - I)**2 - 1
assert use(f, factor, level=2, kwargs=kwargs) == (x + I)**2*(x - I)**2 - 1
assert use(f, factor, level=3, kwargs=kwargs) == (x**2 + 1)**2 - 1
def as_real_imag(self, deep=True, **hints):
"""
returns a tuple representing a complex number
Examples
========
>>> from sympy import I
>>> (7 + 9*I).as_real_imag()
(7, 9)
>>> ((1 + I)/(1 - I)).as_real_imag()
(0, 1)
>>> ((1 + 2*I)*(1 + 3*I)).as_real_imag()
(-5, 5)
"""
sargs, terms = self.args, []
re_part, im_part = [], []
for term in sargs:
re, im = term.as_real_imag(deep=deep)
re_part.append(re)
im_part.append(im)
return (self.func(*re_part), self.func(*im_part))
def test_issue_4149():
assert (3 + I).is_complex
assert (3 + I).is_imaginary is False
assert (3*I + S.Pi*I).is_imaginary
# as Zero.is_imaginary is False, see issue 7649
y = Symbol('y', real=True)
assert (3*I + S.Pi*I + y*I).is_imaginary is None
p = Symbol('p', positive=True)
assert (3*I + S.Pi*I + p*I).is_imaginary
n = Symbol('n', negative=True)
assert (-3*I - S.Pi*I + n*I).is_imaginary
i = Symbol('i', imaginary=True)
assert ([(i**a).is_imaginary for a in range(4)] ==
[False, True, False, True])
# tests from the PR #7887:
e = S("-sqrt(3)*I/2 + 0.866025403784439*I")
assert e.is_real is False
assert e.is_imaginary
def test_pow_eval():
# XXX Pow does not fully support conversion of negative numbers
# to their complex equivalent
assert sqrt(-1) == I
assert sqrt(-4) == 2*I
assert sqrt( 4) == 2
assert (8)**Rational(1, 3) == 2
assert (-8)**Rational(1, 3) == 2*((-1)**Rational(1, 3))
assert sqrt(-2) == I*sqrt(2)
assert (-1)**Rational(1, 3) != I
assert (-10)**Rational(1, 3) != I*((10)**Rational(1, 3))
assert (-2)**Rational(1, 4) != (2)**Rational(1, 4)
assert 64**Rational(1, 3) == 4
assert 64**Rational(2, 3) == 16
assert 24/sqrt(64) == 3
assert (-27)**Rational(1, 3) == 3*(-1)**Rational(1, 3)
assert (cos(2) / tan(2))**2 == (cos(2) / tan(2))**2
def test_p():
assert Px.hilbert_space == L2(Interval(S.NegativeInfinity, S.Infinity))
assert qapply(Px*PxKet(px)) == px*PxKet(px)
assert PxKet(px).dual_class() == PxBra
assert PxBra(x).dual_class() == PxKet
assert (Dagger(PxKet(py))*PxKet(px)).doit() == DiracDelta(px - py)
assert (XBra(x)*PxKet(px)).doit() == \
exp(I*x*px/hbar)/sqrt(2*pi*hbar)
assert represent(PxKet(px)) == DiracDelta(px - px_1)
rep_x = represent(PxOp(), basis=XOp)
assert rep_x == -hbar*I*DiracDelta(x_1 - x_2)*DifferentialOperator(x_1)
assert rep_x == represent(PxOp(), basis=XOp())
assert rep_x == represent(PxOp(), basis=XKet)
assert rep_x == represent(PxOp(), basis=XKet())
assert represent(PxOp()*XKet(), basis=XKet) == \
-hbar*I*DiracDelta(x - x_2)*DifferentialOperator(x)
assert represent(XBra("y")*PxOp()*XKet(), basis=XKet) == \
-hbar*I*DiracDelta(x - y)*DifferentialOperator(x)
def test_expressions():
assert residue(1/(x + 1), x, 0) == 0
assert residue(1/(x + 1), x, -1) == 1
assert residue(1/(x**2 + 1), x, -1) == 0
assert residue(1/(x**2 + 1), x, I) == -I/2
assert residue(1/(x**2 + 1), x, -I) == I/2
assert residue(1/(x**4 + 1), x, 0) == 0
def test_expressions_failing():
assert residue(1/(x**4 + 1), x, exp(I*pi/4)) == -(S(1)/4 + I/4)/sqrt(2)
n = Symbol('n', integer=True, positive=True)
assert residue(exp(z)/(z - pi*I/4*a)**n, z, I*pi*a) == \
exp(I*pi*a/4)/factorial(n - 1)
assert residue(1/(x**2 + a**2)**2, x, a*I) == -I/4/a**3
def test_issue_5654():
assert residue(1/(x**2 + a**2)**2, x, a*I) == -I/(4*a**3)
def test_branch_bug():
assert hyperexpand(hyper((-S(1)/3, S(1)/2), (S(2)/3, S(3)/2), -z)) == \
-z**S('1/3')*lowergamma(exp_polar(I*pi)/3, z)/5 \
+ sqrt(pi)*erf(sqrt(z))/(5*sqrt(z))
assert hyperexpand(meijerg([S(7)/6, 1], [], [S(2)/3], [S(1)/6, 0], z)) == \
2*z**S('2/3')*(2*sqrt(pi)*erf(sqrt(z))/sqrt(z) - 2*lowergamma(
S(2)/3, z)/z**S('2/3'))*gamma(S(2)/3)/gamma(S(5)/3)
def randcplx(offset=-1):
""" Polys is not good with real coefficients. """
return _randrat() + I*_randrat() + I*(1 + offset)
def can_do_meijer(a1, a2, b1, b2, numeric=True):
"""
This helper function tries to hyperexpand() the meijer g-function
corresponding to the parameters a1, a2, b1, b2.
It returns False if this expansion still contains g-functions.
If numeric is True, it also tests the so-obtained formula numerically
(at random values) and returns False if the test fails.
Else it returns True.
"""
from sympy import unpolarify, expand
r = hyperexpand(meijerg(a1, a2, b1, b2, z))
if r.has(meijerg):
return False
# NOTE hyperexpand() returns a truly branched function, whereas numerical
# evaluation only works on the main branch. Since we are evaluating on
# the main branch, this should not be a problem, but expressions like
# exp_polar(I*pi/2*x)**a are evaluated incorrectly. We thus have to get
# rid of them. The expand heuristically does this...
r = unpolarify(expand(r, force=True, power_base=True, power_exp=False,
mul=False, log=False, multinomial=False, basic=False))
if not numeric:
return True
repl = {}
for n, a in enumerate(meijerg(a1, a2, b1, b2, z).free_symbols - set([z])):
repl[a] = randcplx(n)
return tn(meijerg(a1, a2, b1, b2, z).subs(repl), r.subs(repl), z)
def test_meijerg():
# carefully set up the parameters.
# NOTE: this used to fail sometimes. I believe it is fixed, but if you
# hit an inexplicable test failure here, please let me know the seed.
a1, a2 = map(lambda n: randcplx() - 5*I - n*I, range(2))
b1, b2 = map(lambda n: randcplx() + 5*I + n*I, range(2))
b3, b4, b5, a3, a4, a5 = map(lambda n: randcplx(), range(6))
g = meijerg([a1], [a3, a4], [b1], [b3, b4], z)
assert ReduceOrder.meijer_minus(3, 4) is None
assert ReduceOrder.meijer_plus(4, 3) is None
g2 = meijerg([a1, a2], [a3, a4], [b1], [b3, b4, a2], z)
assert tn(ReduceOrder.meijer_plus(a2, a2).apply(g, op), g2, z)
g2 = meijerg([a1, a2], [a3, a4], [b1], [b3, b4, a2 + 1], z)
assert tn(ReduceOrder.meijer_plus(a2, a2 + 1).apply(g, op), g2, z)
g2 = meijerg([a1, a2 - 1], [a3, a4], [b1], [b3, b4, a2 + 2], z)
assert tn(ReduceOrder.meijer_plus(a2 - 1, a2 + 2).apply(g, op), g2, z)
g2 = meijerg([a1], [a3, a4, b2 - 1], [b1, b2 + 2], [b3, b4], z)
assert tn(ReduceOrder.meijer_minus(
b2 + 2, b2 - 1).apply(g, op), g2, z, tol=1e-6)
# test several-step reduction
an = [a1, a2]
bq = [b3, b4, a2 + 1]
ap = [a3, a4, b2 - 1]
bm = [b1, b2 + 1]
niq, ops = reduce_order_meijer(G_Function(an, ap, bm, bq))
assert niq.an == (a1,)
assert set(niq.ap) == set([a3, a4])
assert niq.bm == (b1,)
assert set(niq.bq) == set([b3, b4])
assert tn(apply_operators(g, ops, op), meijerg(an, ap, bm, bq, z), z)
def _combine_inverse(lhs, rhs):
"""
Returns lhs - rhs, but treats arguments like symbols, so things like
oo - oo return 0, instead of a nan.
"""
from sympy import oo, I, expand_mul
if lhs == oo and rhs == oo or lhs == oo*I and rhs == oo*I:
return S.Zero
return expand_mul(lhs - rhs)