def _print_Function(self, expr): if str(expr.func) in self.arrays: return f'{expr.func}[{expr.args[0]}]' if str(expr.func) == 'int_floor': return '((%s) / (%s))' % (self._print( expr.args[0]), self._print(expr.args[1])) return super()._print_Function(expr)
def __new__(cls, name=None, dtype=DEFAULT_SYMBOL_TYPE, **assumptions): if name is None: # Set name dynamically name = "sym_" + str(symbol.s_currentsymbol) symbol.s_currentsymbol += 1 elif name.startswith('__DACE'): raise NameError('Symbols cannot start with __DACE') elif not dtypes.validate_name(name): raise NameError('Invalid symbol name "%s"' % name) if not isinstance(dtype, dtypes.typeclass): raise TypeError('dtype must be a DaCe type, got %s' % str(dtype)) if 'integer' in assumptions or 'int' not in str(dtype): # Using __xnew__ as the regular __new__ is cached, which leads # to modifying different references of symbols with the same name. self = sympy.Symbol.__xnew__(cls, name, **assumptions) else: self = sympy.Symbol.__xnew__(cls, name, integer=True, **assumptions) self.dtype = dtype self._constraints = [] self.value = None return self
def symtype(expr): """ Returns the inferred symbol type from a symbolic expression. """ stypes = [s.dtype for s in symlist(expr).values()] if len(stypes) == 0: return DEFAULT_SYMBOL_TYPE elif _checkEqualIvo(stypes): return stypes[0] else: raise TypeError( 'Cannot infer symbolic type from expression "%s"' ' with symbols [%s]' % (str(expr), ', '.join( [str(s) + ": " + str(s.dtype) for s in symlist(expr)])))
def safe_replace(mapping: Dict[Union[SymbolicType, str], Union[SymbolicType, str]], replace_callback: Callable[[Dict[str, str]], None], value_as_string: bool = False) -> None: """ Safely replaces symbolic expressions that may clash with each other via a two-step replacement. For example, the mapping ``{M: N, N: M}`` would be translated to replacing ``{N, M} -> __dacesym_{N, M}`` followed by ``__dacesym{N, M} -> {M, N}``. :param mapping: The replacement dictionary. :param replace_callback: A callable function that receives a replacement dictionary and performs the replacement (can be unsafe). :param value_as_string: Replacement values are replaced as strings rather than symbols. """ # First, filter out direct (to constants) and degenerate (N -> N) replacements repl = {} invrepl = {} for k, v in mapping.items(): # Degenerate if str(k) == str(v): continue # Not symbolic try: if not value_as_string: v = pystr_to_symbolic(v) except (TypeError, ValueError, AttributeError, sympy.SympifyError): repl[k] = v continue # Constant try: float(v) repl[k] = v continue except (TypeError, ValueError, AttributeError): pass # Otherwise, symbolic replacement repl[k] = f'__dacesym_{k}' invrepl[f'__dacesym_{k}'] = v if len(repl) == 0: return # Make the two-step replacement replace_callback(repl) if len(invrepl) == 0: return replace_callback(invrepl)
def free_symbols_and_functions(expr: Union[SymbolicType, str]) -> Set[str]: if isinstance(expr, str): if dtypes.validate_name(expr): return {expr} expr = pystr_to_symbolic(expr) if not isinstance(expr, sympy.Basic): return set() result = {str(k) for k in expr.free_symbols} for atom in swalk(expr): if (is_sympy_userfunction(atom) and str(atom.func) not in _builtin_userfunctions): result.add(str(atom.func)) return result
def check_constraints(self, value): fail = None for constraint in self.constraints: try: eval_cons = constraint.subs({self: value}) if not eval_cons: fail = constraint break except (AttributeError, TypeError, ValueError): raise RuntimeError( 'Cannot validate constraint %s for symbol %s' % (str(constraint), self.name)) if fail is not None: raise RuntimeError( 'Value %s invalidates constraint %s for symbol %s' % (str(value), str(fail), self.name))
def contains_sympy_functions(expr): """ Returns True if expression contains Sympy functions. """ if is_sympy_userfunction(expr): if str(expr.func) in _builtin_userfunctions: return False return True for arg in expr.args: if contains_sympy_functions(arg): return True return False
def _spickle(obj): return str(obj), { s.name: (s.dtype, s._assumptions) for s in symlist(obj).values() }
def _print_Float(self, expr): if int(expr) == expr: return str(int(expr)) return super()._print_Float(expr)
def symbol_name_or_value(val): """ Returns the symbol name if symbol, otherwise the value as a string. """ if isinstance(val, symbol): return val.name return str(val)
def __str__(self): if self.expr != self.approx: return str(self.expr) + " (~" + str(self.approx) + ")" else: return str(self.expr)
def _spickle(obj): return str(obj)