def clean_sh(sh):
"""Turns symbolic solid harmonic functions into string representations
to be using in generating basis functions.
Args
sh (OrderedDict): Output from exatomic.algorithms.basis.solid_harmonics
Returns
clean (OrderedDict): cleaned strings
"""
_replace = {'x': '{x}', 'y': '{y}', 'z': '{z}', ' - ': ' -'}
_repatrn = re.compile('|'.join(_replace.keys()))
clean = OrderedDict()
for key, sym in sh.items():
if isinstance(sym, (Mul, Add)):
string = str(sym.expand()).replace(' + ', ' ')#.replace(' - ', ' -')
string = _repatrn.sub(lambda x: _replace[x.group(0)], string)
clean[key] = [pre + '*' for pre in string.split()]
else: clean[key] = ['']
return clean
python类Add()的实例源码
def test_unify_iter():
expr = Add(1, 2, 3, evaluate=False)
a, b, c = map(Symbol, 'abc')
pattern = Add(a, c, evaluate=False)
assert is_associative(deconstruct(pattern))
assert is_commutative(deconstruct(pattern))
result = list(unify(expr, pattern, {}, (a, c)))
expected = [{a: 1, c: Add(2, 3, evaluate=False)},
{a: 1, c: Add(3, 2, evaluate=False)},
{a: 2, c: Add(1, 3, evaluate=False)},
{a: 2, c: Add(3, 1, evaluate=False)},
{a: 3, c: Add(1, 2, evaluate=False)},
{a: 3, c: Add(2, 1, evaluate=False)},
{a: Add(1, 2, evaluate=False), c: 3},
{a: Add(2, 1, evaluate=False), c: 3},
{a: Add(1, 3, evaluate=False), c: 2},
{a: Add(3, 1, evaluate=False), c: 2},
{a: Add(2, 3, evaluate=False), c: 1},
{a: Add(3, 2, evaluate=False), c: 1}]
assert iterdicteq(result, expected)
def _normal_ordered_form_terms(expr, independent=False, recursive_limit=10,
_recursive_depth=0):
"""
Helper function for normal_ordered_form: loop through each term in an
addition expression and call _normal_ordered_form_factor to perform the
factor to an normally ordered expression.
"""
new_terms = []
for term in expr.args:
if isinstance(term, Mul):
new_term = _normal_ordered_form_factor(
term, recursive_limit=recursive_limit,
_recursive_depth=_recursive_depth, independent=independent)
new_terms.append(new_term)
else:
new_terms.append(term)
return Add(*new_terms)
def _eval_expand_tensorproduct(self, **hints):
"""Distribute TensorProducts across addition."""
args = self.args
add_args = []
stop = False
for i in range(len(args)):
if isinstance(args[i], Add):
for aa in args[i].args:
tp = TensorProduct(*args[:i] + (aa,) + args[i + 1:])
if isinstance(tp, TensorProduct):
tp = tp._eval_expand_tensorproduct()
add_args.append(tp)
break
if add_args:
return Add(*add_args)
else:
return self
def _needs_function_brackets(self, expr):
"""
Returns True if the expression needs to be wrapped in brackets when
passed as an argument to a function, False otherwise. This is a more
liberal version of _needs_brackets, in that many expressions which need
to be wrapped in brackets when added/subtracted/raised to a power do
not need them when passed to a function. Such an example is a*b.
"""
if not self._needs_brackets(expr):
return False
else:
# Muls of the form a*b*c... can be folded
if expr.is_Mul and not self._mul_is_clean(expr):
return True
# Pows which don't need brackets can be folded
elif expr.is_Pow and not self._pow_is_clean(expr):
return True
# Add and Function always need brackets
elif expr.is_Add or expr.is_Function:
return True
else:
return False
def _print_Sum(self, expr):
if len(expr.limits) == 1:
tex = r"\sum_{%s=%s}^{%s} " % \
tuple([ self._print(i) for i in expr.limits[0] ])
else:
def _format_ineq(l):
return r"%s \leq %s \leq %s" % \
tuple([self._print(s) for s in (l[1], l[0], l[2])])
tex = r"\sum_{\substack{%s}} " % \
str.join('\\\\', [ _format_ineq(l) for l in expr.limits ])
if isinstance(expr.function, Add):
tex += r"\left(%s\right)" % self._print(expr.function)
else:
tex += self._print(expr.function)
return tex
def expr(self):
"""
Process the expression, by returning a sympy expression
"""
if DEBUG:
print("> ArithmeticExpression ")
ret = self.op[0].expr
for operation, operand in zip(self.op[1::2], self.op[2::2]):
if operation == '+':
ret = Add(ret, operand.expr)
else:
a = Mul(-1, operand.expr)
ret = Add(ret, a)
return ret
def doit(self, **hints):
expr = self.args[0]
condition = self._condition
if not expr.has(RandomSymbol):
return expr
if isinstance(expr, Add):
return Add(*[Expectation(a, condition=condition).doit() for a in expr.args])
elif isinstance(expr, Mul):
rv = []
nonrv = []
for a in expr.args:
if isinstance(a, RandomSymbol) or a.has(RandomSymbol):
rv.append(a)
else:
nonrv.append(a)
return Mul(*nonrv)*Expectation(Mul(*rv), condition=condition)
return self
def doit(self, **hints):
arg1 = self.args[0]
arg2 = self.args[1]
condition = self._condition
if arg1 == arg2:
return Variance(arg1, condition).doit()
if not arg1.has(RandomSymbol):
return S.Zero
if not arg2.has(RandomSymbol):
return S.Zero
arg1, arg2 = sorted([arg1, arg2], key=default_sort_key)
if isinstance(arg1, RandomSymbol) and isinstance(arg2, RandomSymbol):
return Covariance(arg1, arg2, condition)
coeff_rv_list1 = self._expand_single_argument(arg1.expand())
coeff_rv_list2 = self._expand_single_argument(arg2.expand())
addends = [a*b*Covariance(*sorted([r1, r2], key=default_sort_key), condition=condition)
for (a, r1) in coeff_rv_list1 for (b, r2) in coeff_rv_list2]
return Add(*addends)
def _expand_single_argument(cls, expr):
# return (coefficient, random_symbol) pairs:
if isinstance(expr, RandomSymbol):
return [(S.One, expr)]
elif isinstance(expr, Add):
outval = []
for a in expr.args:
if isinstance(a, Mul):
outval.append(cls._get_mul_nonrv_rv_tuple(a))
elif isinstance(a, RandomSymbol):
outval.append((S.One, a))
return outval
elif isinstance(expr, Mul):
return [cls._get_mul_nonrv_rv_tuple(expr)]
elif expr.has(RandomSymbol):
return [(S.One, expr)]
def test_unify_iter():
expr = Add(1, 2, 3, evaluate=False)
a, b, c = map(Symbol, 'abc')
pattern = Add(a, c, evaluate=False)
assert is_associative(deconstruct(pattern))
assert is_commutative(deconstruct(pattern))
result = list(unify(expr, pattern, {}, (a, c)))
expected = [{a: 1, c: Add(2, 3, evaluate=False)},
{a: 1, c: Add(3, 2, evaluate=False)},
{a: 2, c: Add(1, 3, evaluate=False)},
{a: 2, c: Add(3, 1, evaluate=False)},
{a: 3, c: Add(1, 2, evaluate=False)},
{a: 3, c: Add(2, 1, evaluate=False)},
{a: Add(1, 2, evaluate=False), c: 3},
{a: Add(2, 1, evaluate=False), c: 3},
{a: Add(1, 3, evaluate=False), c: 2},
{a: Add(3, 1, evaluate=False), c: 2},
{a: Add(2, 3, evaluate=False), c: 1},
{a: Add(3, 2, evaluate=False), c: 1}]
assert iterdicteq(result, expected)
def _normal_ordered_form_terms(expr, independent=False, recursive_limit=10,
_recursive_depth=0):
"""
Helper function for normal_ordered_form: loop through each term in an
addition expression and call _normal_ordered_form_factor to perform the
factor to an normally ordered expression.
"""
new_terms = []
for term in expr.args:
if isinstance(term, Mul):
new_term = _normal_ordered_form_factor(
term, recursive_limit=recursive_limit,
_recursive_depth=_recursive_depth, independent=independent)
new_terms.append(new_term)
else:
new_terms.append(term)
return Add(*new_terms)
def _normal_order_terms(expr, recursive_limit=10, _recursive_depth=0):
"""
Helper function for normal_order: look through each term in an addition
expression and call _normal_order_factor to perform the normal ordering
on the factors.
"""
new_terms = []
for term in expr.args:
if isinstance(term, Mul):
new_term = _normal_order_factor(term,
recursive_limit=recursive_limit,
_recursive_depth=_recursive_depth)
new_terms.append(new_term)
else:
new_terms.append(term)
return Add(*new_terms)
def _eval_expand_tensorproduct(self, **hints):
"""Distribute TensorProducts across addition."""
args = self.args
add_args = []
stop = False
for i in range(len(args)):
if isinstance(args[i], Add):
for aa in args[i].args:
tp = TensorProduct(*args[:i] + (aa,) + args[i + 1:])
if isinstance(tp, TensorProduct):
tp = tp._eval_expand_tensorproduct()
add_args.append(tp)
break
if add_args:
return Add(*add_args)
else:
return self
def _needs_function_brackets(self, expr):
"""
Returns True if the expression needs to be wrapped in brackets when
passed as an argument to a function, False otherwise. This is a more
liberal version of _needs_brackets, in that many expressions which need
to be wrapped in brackets when added/subtracted/raised to a power do
not need them when passed to a function. Such an example is a*b.
"""
if not self._needs_brackets(expr):
return False
else:
# Muls of the form a*b*c... can be folded
if expr.is_Mul and not self._mul_is_clean(expr):
return True
# Pows which don't need brackets can be folded
elif expr.is_Pow and not self._pow_is_clean(expr):
return True
# Add and Function always need brackets
elif expr.is_Add or expr.is_Function:
return True
else:
return False
def _print_Sum(self, expr):
if len(expr.limits) == 1:
tex = r"\sum_{%s=%s}^{%s} " % \
tuple([ self._print(i) for i in expr.limits[0] ])
else:
def _format_ineq(l):
return r"%s \leq %s \leq %s" % \
tuple([self._print(s) for s in (l[1], l[0], l[2])])
tex = r"\sum_{\substack{%s}} " % \
str.join('\\\\', [ _format_ineq(l) for l in expr.limits ])
if isinstance(expr.function, Add):
tex += r"\left(%s\right)" % self._print(expr.function)
else:
tex += self._print(expr.function)
return tex
def _print_Product(self, expr):
if len(expr.limits) == 1:
tex = r"\prod_{%s=%s}^{%s} " % \
tuple([ self._print(i) for i in expr.limits[0] ])
else:
def _format_ineq(l):
return r"%s \leq %s \leq %s" % \
tuple([self._print(s) for s in (l[1], l[0], l[2])])
tex = r"\prod_{\substack{%s}} " % \
str.join('\\\\', [ _format_ineq(l) for l in expr.limits ])
if isinstance(expr.function, Add):
tex += r"\left(%s\right)" % self._print(expr.function)
else:
tex += self._print(expr.function)
return tex
def freeze_expression(expr):
"""
Reconstruct ``expr`` turning all :class:`sympy.Mul` and :class:`sympy.Add`
into, respectively, :class:`devito.Mul` and :class:`devito.Add`.
"""
if expr.is_Atom or expr.is_Indexed:
return expr
elif expr.is_Add:
rebuilt_args = [freeze_expression(e) for e in expr.args]
return Add(*rebuilt_args, evaluate=False)
elif expr.is_Mul:
rebuilt_args = [freeze_expression(e) for e in expr.args]
return Mul(*rebuilt_args, evaluate=False)
elif expr.is_Equality:
rebuilt_args = [freeze_expression(e) for e in expr.args]
return Eq(*rebuilt_args, evaluate=False)
else:
return expr.func(*[freeze_expression(e) for e in expr.args])
def add_reaction_constraints(model, reactions, Constraint):
"""
Add the stoichiometric coefficients as constraints.
Parameters
----------
model : optlang.Model
The transposed stoichiometric matrix representation.
reactions : iterable
Container of `cobra.Reaction` instances.
Constraint : optlang.Constraint
The constraint class for the specific interface.
"""
for rxn in reactions:
expression = sympy.Add(
*[coefficient * model.variables[metabolite.id]
for (metabolite, coefficient) in rxn.metabolites.items()])
constraint = Constraint(expression, lb=0, ub=0, name=rxn.id)
model.add(constraint)
def car2sph(sh, cart):
"""
Turns symbolic solid harmonic functions into a dictionary of
arrays containing cartesian to spherical transformation matrices.
Args
sh (OrderedDict): the result of solid_harmonics(l_tot)
cart (dict): dictionary of l, cartesian l, m, n ordering
"""
keys, conv = {}, {}
prevL, mscnt = 0, 0
for L in cart:
for idx, (l, m, n) in enumerate(cart[L]):
key = ''
if l: key += 'x'
if l > 1: key += str(l)
if m: key += 'y'
if m > 1: key += str(m)
if n: key += 'z'
if n > 1: key += str(n)
keys[key] = idx
# TODO: six compatibility
for key, sym in sh.items():
L = key[0]
mscnt = mscnt if prevL == L else 0
conv.setdefault(L, np.zeros((cart_lml_count[L],
spher_lml_count[L]),
dtype=np.float64))
if isinstance(sym, (Mul, Add)):
string = (str(sym.expand())
.replace(' + ', ' ')
.replace(' - ', ' -'))
for chnk in string.split():
pre, exp = chnk.split('*', 1)
if L == 1: conv[L] = np.array(cart[L])
else: conv[L][keys[exp.replace('*', '')], mscnt] = float(pre)
prevL = L
mscnt += 1
conv[0] = np.array([[1]])
return conv
def _print_Add(self, expr):
if not (self._settings['use_autoeye'] or self._settings['py_solve']):
return super()._print_Add(expr)
prec = precedence(expr)
num_terms = [i for i in expr.args if i.is_number]
rest_terms = [i for i in expr.args if i not in num_terms]
if len(rest_terms) > 1:
rest = super()._print_Add(Add(*rest_terms))
elif len(rest_terms) == 1:
rest = self._print(rest_terms[0])
else:
if self._settings['py_solve']:
return super()._print_Add(expr)
rest = ''
if len(num_terms) > 1:
num = self.__class__({**self._settings, 'use_autoeye': False})._print_Add(Add(*num_terms))
elif len(num_terms) == 1:
num = self.__class__({**self._settings, 'use_autoeye': False})._print(num_terms[0])
else:
num = ''
if rest and num:
if self._settings['py_solve']:
return "diag_add(%s, %s)" % (self._print(rest_terms[0]), self._print(Add(*num_terms)))
return self.parenthesize(rest + ' + autoeye(%s)' % num, prec)
elif rest:
return self.parenthesize(rest, prec)
else:
if self._settings['use_autoeye']:
# No need to parenthesize
return 'autoeye(%s)' % num
else:
return self.parenthesize(num, prec)
def create_expression(n):
if n not in coeffs:
raise ValueError("Don't have coefficients for {}".format(n))
from sympy import Float, Add
p = coeffs[n]['p']
q = coeffs[n]['q']
# Don't use Poly here, it loses precision
num = Add(*[Float(p[i])*t**i for i in range(n+1)])
den = Add(*[Float(q[i])*t**i for i in range(n+1)])
return num/den
def test_deconstruct():
expr = Basic(1, 2, 3)
expected = Compound(Basic, (1, 2, 3))
assert deconstruct(expr) == expected
assert deconstruct(1) == 1
assert deconstruct(x) == x
assert deconstruct(x, variables=(x,)) == Variable(x)
assert deconstruct(Add(1, x, evaluate=False)) == Compound(Add, (1, x))
assert deconstruct(Add(1, x, evaluate=False), variables=(x,)) == \
Compound(Add, (1, Variable(x)))
def test_unify_commutative():
expr = Add(1, 2, 3, evaluate=False)
a, b, c = map(Symbol, 'abc')
pattern = Add(a, b, c, evaluate=False)
result = tuple(unify(expr, pattern, {}, (a, b, c)))
expected = ({a: 1, b: 2, c: 3},
{a: 1, b: 3, c: 2},
{a: 2, b: 1, c: 3},
{a: 2, b: 3, c: 1},
{a: 3, b: 1, c: 2},
{a: 3, b: 2, c: 1})
assert iterdicteq(result, expected)
def qubit_to_matrix(qubit, format='sympy'):
"""Coverts an Add/Mul of Qubit objects into it's matrix representation
This function is the inverse of ``matrix_to_qubit`` and is a shorthand
for ``represent(qubit)``.
"""
return represent(qubit, format=format)
#-----------------------------------------------------------------------------
# Measurement
#-----------------------------------------------------------------------------
def normal_order(expr, recursive_limit=10, _recursive_depth=0):
"""Normal order an expression with bosonic or fermionic operators. Note
that this normal order is not equivalent to the original expression, but
the creation and annihilation operators in each term in expr is reordered
so that the expression becomes normal ordered.
Parameters
==========
expr : expression
The expression to normal order.
recursive_limit : int (default 10)
The number of allowed recursive applications of the function.
Examples
========
>>> from sympy.physics.quantum import Dagger
>>> from sympy.physics.quantum.boson import BosonOp
>>> from sympy.physics.quantum.operatorordering import normal_order
>>> a = BosonOp("a")
>>> normal_order(a * Dagger(a))
Dagger(a)*a
"""
if _recursive_depth > recursive_limit:
warn.warning("Warning: too many recursions, aborting")
return expr
if isinstance(expr, Add):
return _normal_order_terms(expr, recursive_limit=recursive_limit,
_recursive_depth=_recursive_depth)
elif isinstance(expr, Mul):
return _normal_order_factor(expr, recursive_limit=recursive_limit,
_recursive_depth=_recursive_depth)
else:
return expr
def _sympystr(self, printer, *args):
from sympy.printing.str import sstr
length = len(self.args)
s = ''
for i in range(length):
if isinstance(self.args[i], (Add, Pow, Mul)):
s = s + '('
s = s + sstr(self.args[i])
if isinstance(self.args[i], (Add, Pow, Mul)):
s = s + ')'
if i != length - 1:
s = s + 'x'
return s
def _latex(self, printer, *args):
if (_combined_printing and
(all([isinstance(arg, Ket) for arg in self.args]) or
all([isinstance(arg, Bra) for arg in self.args]))):
def _label_wrap(label, nlabels):
return label if nlabels == 1 else r"\left\{%s\right\}" % label
s = r", ".join([_label_wrap(arg._print_label_latex(printer, *args),
len(arg.args)) for arg in self.args])
return r"{%s%s%s}" % (self.args[0].lbracket_latex, s,
self.args[0].rbracket_latex)
length = len(self.args)
s = ''
for i in range(length):
if isinstance(self.args[i], (Add, Mul)):
s = s + '\\left('
# The extra {} brackets are needed to get matplotlib's latex
# rendered to render this properly.
s = s + '{' + printer._print(self.args[i], *args) + '}'
if isinstance(self.args[i], (Add, Mul)):
s = s + '\\right)'
if i != length - 1:
s = s + '\\otimes '
return s
def _latex(self, printer=None):
ar = self.args # just to shorten things
if len(ar) == 0:
return str(0)
ol = [] # output list, to be concatenated to a string
mlp = VectorLatexPrinter()
for i, v in enumerate(ar):
# if the coef of the dyadic is 1, we skip the 1
if ar[i][0] == 1:
ol.append(' + ' + mlp.doprint(ar[i][1]) + r"\otimes " +
mlp.doprint(ar[i][2]))
# if the coef of the dyadic is -1, we skip the 1
elif ar[i][0] == -1:
ol.append(' - ' +
mlp.doprint(ar[i][1]) +
r"\otimes " +
mlp.doprint(ar[i][2]))
# If the coefficient of the dyadic is not 1 or -1,
# we might wrap it in parentheses, for readability.
elif ar[i][0] != 0:
arg_str = mlp.doprint(ar[i][0])
if isinstance(ar[i][0], Add):
arg_str = '(%s)' % arg_str
if arg_str.startswith('-'):
arg_str = arg_str[1:]
str_start = ' - '
else:
str_start = ' + '
ol.append(str_start + arg_str + mlp.doprint(ar[i][1]) +
r"\otimes " + mlp.doprint(ar[i][2]))
outstr = ''.join(ol)
if outstr.startswith(' + '):
outstr = outstr[3:]
elif outstr.startswith(' '):
outstr = outstr[1:]
return outstr
def __str__(self, printer=None):
"""Printing method. """
ar = self.args # just to shorten things
if len(ar) == 0:
return str(0)
ol = [] # output list, to be concatenated to a string
for i, v in enumerate(ar):
# if the coef of the dyadic is 1, we skip the 1
if ar[i][0] == 1:
ol.append(' + (' + str(ar[i][1]) + '|' + str(ar[i][2]) + ')')
# if the coef of the dyadic is -1, we skip the 1
elif ar[i][0] == -1:
ol.append(' - (' + str(ar[i][1]) + '|' + str(ar[i][2]) + ')')
# If the coefficient of the dyadic is not 1 or -1,
# we might wrap it in parentheses, for readability.
elif ar[i][0] != 0:
arg_str = VectorStrPrinter().doprint(ar[i][0])
if isinstance(ar[i][0], Add):
arg_str = "(%s)" % arg_str
if arg_str[0] == '-':
arg_str = arg_str[1:]
str_start = ' - '
else:
str_start = ' + '
ol.append(str_start + arg_str + '*(' + str(ar[i][1]) +
'|' + str(ar[i][2]) + ')')
outstr = ''.join(ol)
if outstr.startswith(' + '):
outstr = outstr[3:]
elif outstr.startswith(' '):
outstr = outstr[1:]
return outstr