-
Notifications
You must be signed in to change notification settings - Fork 263
misc: General reductions in lines of code #3031
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
76c4bd6
e03a32f
305c6b5
194002b
06b49de
f75d3d6
422277d
4d844ce
e2105ac
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,4 +1,5 @@ | ||
| from collections import ChainMap | ||
| from contextlib import suppress | ||
| from functools import cached_property, singledispatch | ||
| from itertools import product | ||
|
|
||
|
|
@@ -28,16 +29,8 @@ | |
| from devito.types.basic import AbstractFunction, Indexed | ||
|
|
||
| __all__ = [ | ||
| 'Conj', | ||
| 'DiffDerivative', | ||
| 'Differentiable', | ||
| 'EvalDerivative', | ||
| 'Imag', | ||
| 'IndexDerivative', | ||
| 'IndexDerivativeProperty', | ||
| 'LocalSum', | ||
| 'Real', | ||
| 'Weights', | ||
| 'Conj', 'DiffDerivative', 'Differentiable', 'EvalDerivative', 'Imag', | ||
| 'IndexDerivative', 'IndexDerivativeProperty', 'LocalSum', 'Real', 'Weights', | ||
| ] | ||
|
|
||
|
|
||
|
|
@@ -88,10 +81,7 @@ def grid(self): | |
| grids = {g.root for g in grids} | ||
| if len(grids) > 1: | ||
| warning("Expression contains multiple grids, returning first found") | ||
| try: | ||
| return grids.pop() | ||
| except KeyError: | ||
| return None | ||
| return grids.pop() if grids else None | ||
|
|
||
| @cached_property | ||
| def dtype(self): | ||
|
|
@@ -154,12 +144,10 @@ def _fd(self): | |
| # Filter out all args with fd order too high | ||
| fd_args = [] | ||
| for f in self._args_diff: | ||
| try: | ||
| with suppress(AttributeError): | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yes |
||
| if f.space_order <= self.space_order and \ | ||
| (not f.is_TimeDependent or f.time_order <= self.time_order): | ||
| fd_args.append(f) | ||
| except AttributeError: | ||
| pass | ||
| return dict(ChainMap(*[getattr(i, '_fd', {}) for i in fd_args])) | ||
|
|
||
| @cached_property | ||
|
|
@@ -168,10 +156,7 @@ def _symbolic_functions(self): | |
|
|
||
| @cached_property | ||
| def function(self): | ||
| if len(self._functions) == 1: | ||
| return set(self._functions).pop() | ||
| else: | ||
| return None | ||
| return set(self._functions).pop() if len(self._functions) == 1 else None | ||
|
|
||
| @cached_property | ||
| def _uses_symbolic_coefficients(self): | ||
|
|
@@ -198,10 +183,8 @@ def _subs(self, old, new, **hints): | |
| return self | ||
| args = list(self.args) | ||
| for i, arg in enumerate(args): | ||
| try: | ||
| with suppress(AttributeError): | ||
| args[i] = arg._subs(old, new, **hints) | ||
| except AttributeError: | ||
| continue | ||
| return self.func(*args, evaluate=False) | ||
|
|
||
| @property | ||
|
|
@@ -290,10 +273,7 @@ def __rfloordiv__(self, other): | |
| return floor(other / self) | ||
|
|
||
| def _inv(self, ref, safe=False): | ||
| if safe: | ||
| return SafeInv(self, ref or self) | ||
| else: | ||
| return 1 / self | ||
| return SafeInv(self, ref or self) if safe else 1 / self | ||
|
|
||
| def __mod__(self, other): | ||
| return Mod(self, other) | ||
|
|
@@ -468,9 +448,8 @@ def has(self, *pattern): | |
| """ | ||
| for p in pattern: | ||
| # Following sympy convention, return True if any is found | ||
| if isinstance(p, type) \ | ||
| and issubclass(p, sympy.Symbol) \ | ||
| and any(isinstance(i, p) for i in self.free_symbols): | ||
| if (isinstance(p, type) and issubclass(p, sympy.Symbol) and | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Todo: revert |
||
| any(isinstance(i, p) for i in self.free_symbols)): | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is less readable |
||
| # Symbols (and subclasses) are the leaves of an expression, and they | ||
| # are promptly available via `free_symbols`. So this is super quick | ||
| return True | ||
|
|
@@ -500,8 +479,7 @@ def deep_priority(expr): | |
| generic value, so `mu*tau_xx` reports .75 rather than `tau_xx`'s 2.1. | ||
| """ | ||
| prio = getattr(expr, '_fd_priority', 0) | ||
| return max([prio] + [deep_priority(i) | ||
| for i in getattr(expr, '_args_diff', ())]) | ||
| return max([prio] + [deep_priority(i) for i in getattr(expr, '_args_diff', ())]) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @FabioLuporini doesn't like |
||
|
|
||
|
|
||
| def highest_priority(diff_op, candidates=None): | ||
|
|
@@ -656,14 +634,12 @@ def __new__(cls, *args, **kwargs): | |
| # which would destroy `EvalDerivative`s if present. So here we perform | ||
| # a similar thing, but cautiously construct an evaluated Add, which | ||
| # will preserve the integrity of `EvalDerivative`s, if any | ||
| try: | ||
| with suppress(AttributeError, ValueError): | ||
| a, b = args | ||
| if a.is_Rational: | ||
| r, b = b.as_coeff_Mul() | ||
| if r is sympy.S.One and type(b) is Add: | ||
| return Add(*[_keep_coeff(a, bi) for bi in b.args], evaluate=False) | ||
| except (AttributeError, ValueError): | ||
| pass | ||
|
|
||
| return super().__new__(cls, *args, **kwargs) | ||
|
|
||
|
|
@@ -686,9 +662,8 @@ def _gather_for_diff(self): | |
| derivs, other = split(self.args, lambda a: isinstance(a, sympy.Derivative)) | ||
| if len(derivs) == 0: | ||
| return self._eval_at(highest_priority(self)) | ||
| else: | ||
| other = self.func(*other)._eval_at(highest_priority(self)) | ||
| return self.func(other, *derivs) | ||
| other = self.func(*other)._eval_at(highest_priority(self)) | ||
| return self.func(other, *derivs) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I despise multiple returns and consider them the definition of spaghetti code. I'd much rather you consolidate and return once |
||
|
|
||
| @classmethod | ||
| def _off_func(cls, a, func): | ||
|
|
@@ -777,8 +752,7 @@ def _eval_at(self, func, interp_mode='direct', **kwargs): | |
| if dim in func.indices_ref.getters}) | ||
| else: | ||
| source = a.indices_ref | ||
| new_factors.append(interp_at(a, source, block_indices, | ||
| self.interp_order)) | ||
| new_factors.append(interp_at(a, source, block_indices, self.interp_order)) | ||
|
|
||
| # Final I from block's location to func | ||
| return interp_at(self.func(*new_factors), block_indices, | ||
|
|
@@ -836,8 +810,7 @@ class RealComplexPart(ComplexPart): | |
|
|
||
| @cached_property | ||
| def dtype(self): | ||
| dtype = extract_dtype(self) | ||
| return dtype(0).real.__class__ | ||
| return extract_dtype(self)(0).real.__class__ | ||
|
|
||
|
|
||
| class Real(RealComplexPart): | ||
|
|
@@ -899,11 +872,8 @@ def __new__(cls, expr, dimensions, **kwargs): | |
| return obj | ||
|
|
||
| def __repr__(self): | ||
| return "{}({}, ({}))".format( | ||
| self.__class__.__name__, | ||
| self.expr, | ||
| ', '.join(d.name for d in self.dimensions) | ||
| ) | ||
| dims = ', '.join(d.name for d in self.dimensions) | ||
| return f"{self.__class__.__name__}({self.expr}, ({dims}))" | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is this actually the correct repr, as in is the second argument actually a tuple? |
||
|
|
||
| __str__ = __repr__ | ||
|
|
||
|
|
@@ -1109,17 +1079,14 @@ def _xreplace(self, rule): | |
| return rule[self], True | ||
| elif not rule: | ||
| return self, False | ||
| else: | ||
| try: | ||
| weights, flags = zip( | ||
| *[i._xreplace(rule) for i in self.weights], strict=True | ||
| ) | ||
| if any(flags): | ||
| return self.func(initvalue=weights, function=None), True | ||
| except AttributeError: | ||
| # `float` weights | ||
| pass | ||
| return super()._xreplace(rule) | ||
| try: | ||
| weights, flags = zip(*[i._xreplace(rule) for i in self.weights], strict=True) | ||
| if any(flags): | ||
| return self.func(initvalue=weights, function=None), True | ||
| except AttributeError: | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should use contextlib.suppress also see comment about multiple returns |
||
| # `float` weights | ||
| pass | ||
| return super()._xreplace(rule) | ||
|
|
||
| @cached_property | ||
| def _npweights(self): | ||
|
|
@@ -1136,8 +1103,7 @@ def value(self, idx): | |
| v = self._npweights[idx] | ||
| if v.is_Number or v.is_Indexed: | ||
| return sympy.sympify(v) | ||
| else: | ||
| return self[idx] | ||
| return self[idx] | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🤮 |
||
|
|
||
|
|
||
| class IndexDerivativeProperty(Tag): | ||
|
|
@@ -1196,8 +1162,7 @@ def compare(self, other): | |
| return (self.weights.compare(other.weights) or | ||
| self.base.compare(other.base) or | ||
| (p1 > p2) - (p1 < p2)) | ||
| else: | ||
| return super().compare(other) | ||
| return super().compare(other) | ||
|
|
||
| @cached_property | ||
| def base(self): | ||
|
|
@@ -1250,8 +1215,7 @@ def _subs(self, old, new, **hints): | |
| # may fail to identify the sub-expression to be replaced (note: if | ||
| # `a/b/c` are atoms or Indexeds, it's generally fine) | ||
|
|
||
| if not old.is_Mul or \ | ||
| old is not self.base: | ||
| if not old.is_Mul or old is not self.base: | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You could even use De Morgan's law... |
||
| return super()._subs(old, new, **hints) | ||
|
|
||
| return self._rebuild(new * self.weights) | ||
|
|
@@ -1300,7 +1264,6 @@ def __new__(cls, *args, base=None, **kwargs): | |
| # story: a zero-order derivative whose weights collapse to one is | ||
| # the identity, so it comes back as the sum it was applied to. | ||
| assert len(args) <= 1 | ||
| return obj | ||
|
|
||
| return obj | ||
|
|
||
|
|
@@ -1339,8 +1302,7 @@ class diffify: | |
|
|
||
| def __new__(cls, obj): | ||
| args = [diffify._doit(i) for i in obj.args] | ||
| obj = diffify._doit(obj, args) | ||
| return obj | ||
| return diffify._doit(obj, args) | ||
|
|
||
| def _doit(obj, args=None): | ||
| cls = diffify._cls(obj) | ||
|
|
@@ -1401,8 +1363,7 @@ def _diff2sympy(obj): | |
|
|
||
| # Handle special objects | ||
| if isinstance(obj, DiffDerivative): | ||
| return IndexDerivative(*args, obj.mapper, | ||
| deriv_order=obj.deriv_order, | ||
| return IndexDerivative(*args, obj.mapper, deriv_order=obj.deriv_order, | ||
| properties=obj.properties), True | ||
|
|
||
| # Handle generic objects such as arithmetic operations | ||
|
|
@@ -1421,8 +1382,7 @@ def _diff2sympy(obj): | |
| # In case of indices using other Function, evaluate | ||
| # may not be a supported argument. | ||
| return obj.func(*args), True | ||
| else: | ||
| return obj, False | ||
| return obj, False | ||
|
|
||
| return _diff2sympy(expr)[0] | ||
|
|
||
|
|
@@ -1460,8 +1420,7 @@ def _(expr, x0, **kwargs): | |
| def test0(a): | ||
| return all(a.indices[d] is i for d, i in x0.items() if d in a.dimensions) | ||
|
|
||
| oa, ia = split(expr._args_diff, | ||
| lambda a: isinstance(a, sympy.Derivative) or test0(a)) | ||
| oa, ia = split(expr._args_diff, lambda a: isinstance(a, sympy.Derivative) or test0(a)) | ||
| oa = oa + tuple(a for a in expr.args if a not in expr._args_diff) | ||
|
|
||
| # Interpolate the necessary args | ||
|
|
@@ -1476,8 +1435,7 @@ def test0(a): | |
| def _(expr, x0, **kwargs): | ||
| if expr.args: | ||
| return expr.func(*[interp_for_fd(i, x0, **kwargs) for i in expr.args]) | ||
| else: | ||
| return expr | ||
| return expr | ||
|
Comment on lines
1436
to
+1438
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Okay, now I've seen enough of this! and removes the multiple returns |
||
|
|
||
|
|
||
| @interp_for_fd.register(AbstractFunction) | ||
|
|
@@ -1486,5 +1444,4 @@ def _(expr, x0, **kwargs): | |
| and expr.indices.get(d, v) is not v} | ||
| if x0_expr: | ||
| return expr.subs({expr.indices[d]: v for d, v in x0_expr.items()}) | ||
| else: | ||
| return expr | ||
| return expr | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No