def time_invariant(self, expr=None): """ Check if ``expr`` is time invariant. ``expr`` may be an expression ``e`` explicitly tracked by the FlowGraph or even a generic subexpression of ``e``. If no ``expr`` is provided, then time invariance of the entire FlowGraph is assessed. """ if expr is None: return all(self.time_invariant(v) for v in self.values()) if any(q_timedimension(i) for i in expr.free_symbols): return False queue = [expr.rhs if expr.is_Equality else expr] seen = set() while queue: item = queue.pop() temporaries = set() for i in retrieve_terminals(item): if i in seen: # Already inspected, nothing more can be inferred continue elif any( isinstance(j, Dimension) and j.is_Time for j in i.free_symbols): # Definitely not time-invariant return False elif i in self: # Go on with the search temporaries.add(i) elif isinstance(i, Dimension): # Go on with the search, as /i/ is not a time dimension pass elif not i.base.function.is_TensorFunction: # It didn't come from the outside and it's not in self, so # cannot determine if time-invariant; assume time-varying return False seen.add(i) queue.extend([self[i].rhs for i in temporaries]) return True
def time_invariant(self, expr=None): """ Check if ``expr`` is time invariant. ``expr`` may be an expression ``e`` explicitly tracked by the FlowGraph or even a generic subexpression of ``e``. If no ``expr`` is provided, then time invariance of the entire FlowGraph is assessed. """ if expr is None: return all(self.time_invariant(v) for v in self.values()) if any(q_timedimension(i) for i in expr.free_symbols): return False queue = [expr.rhs if expr.is_Equality else expr] seen = set() while queue: item = queue.pop() nodes = set() for i in retrieve_terminals(item): if i in seen: # Already inspected, nothing more can be inferred continue elif any(isinstance(j, Dimension) and j.is_Time for j in i.free_symbols): # Definitely not time-invariant return False elif i in self: # Go on with the search nodes.add(i) elif isinstance(i, Dimension): # Go on with the search, as /i/ is not a time dimension pass elif not i.function.is_DiscreteFunction: # It didn't come from the outside and it's not in self, so # cannot determine if time-invariant; assume time-varying return False seen.add(i) queue.extend([self[i].rhs for i in nodes]) return True