pycopancore.private._expressions module¶
Created on Mar 20, 2017.
@author: heitzig
- class _DotConstruct(start, attribute_sequence, *args, aggregation=None, argument=None, **assumptions)[source]¶
Bases:
AtomicExprA _DotConstruct represents a syntactical construct with dots, starting with an entity-type or process taxon class, followed by zero or more ReferenceVariables or SetVariables or aggregation keywords such as sum, and ending in either an attribute, e.g. SocialSystem.sum.cells.population or an aggregation keyword without evaluation, e.g. SocialSystem.world.sum, or an aggregation keyword with evaluation, e.g. SocialSystem.world.sum(some expression).
- __call__(*args, **kwargs)[source]¶
calling is only allowed if we are an aggregation without argument yet, and results in adding an argument
- __getattr__(name)[source]¶
accessing an attribute of a _DotConstruct basically returns a new _DotConstruct that is extended by the name of this attribute, giving special treatment to aggregations
- _aggregation = None¶
- _argset = ()¶
- _argument = None¶
- _attribute_sequence = None¶
- _broadcast(values)[source]¶
broadcast a list of values from entities at an intermediate level to their “offspring” entities at the final level
- _can_be_target = None¶
- _explicit_class_assumptions = {}¶
- _initialized = None¶
- _iterable = False¶
- _prop_handler = {'extended_negative': <function Expr._eval_is_extended_negative>, 'extended_positive': <function Expr._eval_is_extended_positive>}¶
- _start = None¶
- args = ()¶
- property branchings¶
return the list of branching lens at SetReferences, to be used in aggregation and broadcasting
- property cardinalities¶
return the list of level cardinalities at SetReferences, to be used in aggregation and broadcasting
- default_assumptions = {}¶
- eval(instances=None)[source]¶
gets referenced attribute values and performs aggregations where necessary.
- is_Add = False¶
- is_constant(*args, **kwargs)[source]¶
Return True if self is constant, False if not, or None if the constancy could not be determined conclusively.
Explanation¶
If an expression has no free symbols then it is a constant. If there are free symbols it is possible that the expression is a constant, perhaps (but not necessarily) zero. To test such expressions, a few strategies are tried:
1) numerical evaluation at two random points. If two such evaluations give two different values and the values have a precision greater than 1 then self is not constant. If the evaluations agree or could not be obtained with any precision, no decision is made. The numerical testing is done only if
wrtis different than the free symbols.2) differentiation with respect to variables in ‘wrt’ (or all free symbols if omitted) to see if the expression is constant or not. This will not always lead to an expression that is zero even though an expression is constant (see added test in test_expr.py). If all derivatives are zero then self is constant with respect to the given symbols.
3) finding out zeros of denominator expression with free_symbols. It will not be constant if there are zeros. It gives more negative answers for expression that are not constant.
If neither evaluation nor differentiation can prove the expression is constant, None is returned unless two numerical values happened to be the same and the flag
failing_numberis True – in that case the numerical value will be returned.If flag simplify=False is passed, self will not be simplified; the default is True since self should be simplified before testing.
Examples
>>> from sympy import cos, sin, Sum, S, pi >>> from sympy.abc import a, n, x, y >>> x.is_constant() False >>> S(2).is_constant() True >>> Sum(x, (x, 1, 10)).is_constant() True >>> Sum(x, (x, 1, n)).is_constant() False >>> Sum(x, (x, 1, n)).is_constant(y) True >>> Sum(x, (x, 1, n)).is_constant(n) False >>> Sum(x, (x, 1, n)).is_constant(x) True >>> eq = a*cos(x)**2 + a*sin(x)**2 - a >>> eq.is_constant() True >>> eq.subs({x: pi, a: 2}) == eq.subs({x: pi, a: 3}) == 0 True
>>> (0**x).is_constant() False >>> x.is_constant() False >>> (x**x).is_constant() False >>> one = cos(x)**2 + sin(x)**2 >>> one.is_constant() True >>> ((one - 1)**(x + 1)).is_constant() in (True, False) # could be 0 or 1 True
- is_float = False¶
- match(*args, **kwargs)[source]¶
Pattern matching.
Wild symbols match all.
Return
Nonewhen expression (self) does not match with pattern. Otherwise return a dictionary such that:pattern.xreplace(self.match(pattern)) == self
Examples
>>> from sympy import Wild, Sum >>> from sympy.abc import x, y >>> p = Wild("p") >>> q = Wild("q") >>> r = Wild("r") >>> e = (x+y)**(x+y) >>> e.match(p**p) {p_: x + y} >>> e.match(p**q) {p_: x + y, q_: x + y} >>> e = (2*x)**2 >>> e.match(p*q**r) {p_: 4, q_: x, r_: 2} >>> (p*q**r).xreplace(e.match(p*q**r)) 4*x**2
Since match is purely structural expressions that are equivalent up to bound symbols will not match:
>>> print(Sum(x, (x, 1, 2)).match(Sum(y, (y, 1, p)))) None
An expression with bound symbols can be matched if the pattern uses a distinct
Wildfor each bound symbol:>>> Sum(x, (x, 1, 2)).match(Sum(q, (q, 1, p))) {p_: 2, q_: x}
The
oldflag will give the old-style pattern matching where expressions and patterns are essentially solved to give the match. Both of the following give None unlessold=True:>>> (x - 2).match(p - x, old=True) {p_: 2*x - 2} >>> (2/x).match(p*x, old=True) {p_: 2/x**2}
See also
matchespattern.matches(expr) is the same as expr.match(pattern)
xreplaceexact structural replacement
replacestructural replacement with pattern matching
Wildsymbolic placeholders for expressions in pattern matching
- property owning_class¶
return the class owning the _DotConstruct
- precedence = 1000¶
- property target_class¶
return the class owning the target attribute
- property target_instances¶
return the list of instances owning the referenced attributes, may contain instances more than once due to broadcasting
- property target_variable¶
return the Variable object representing the target attribute