def init(self, expr): super(PatternObject, self).init(expr) if self.arg_counts is not None: if len(expr.leaves) not in self.arg_counts: self.error_args(len(expr.leaves), *self.arg_counts) self.expr = expr self.head = Pattern.create(expr.head) self.leaves = [Pattern.create(leaf) for leaf in expr.leaves]
def apply(self, expr, patterns, f, evaluation): 'Reap[expr_, {patterns___}, f_]' patterns = patterns.get_sequence() sown = [(Pattern.create(pattern), []) for pattern in patterns] def listener(e, tag): result = False for pattern, items in sown: if pattern.does_match(tag, evaluation): for item in items: if item[0].same(tag): item[1].append(e) break else: items.append((tag, [e])) result = True return result evaluation.add_listener('sow', listener) try: result = expr.evaluate(evaluation) items = [] for pattern, tags in sown: list = Expression('List') for tag, elements in tags: list.leaves.append( Expression(f, tag, Expression('List', *elements))) items.append(list) return Expression('List', result, Expression('List', *items)) finally: evaluation.remove_listener('sow', listener)
def apply(self, expr, pattern, test, evaluation): 'ArrayQ[expr_, pattern_, test_]' pattern = Pattern.create(pattern) dims = [len(expr.get_leaves())] # to ensure an atom is not an array def check(level, expr): if not expr.has_form('List', None): test_expr = Expression(test, expr) if test_expr.evaluate(evaluation) != Symbol('True'): return False level_dim = None else: level_dim = len(expr.leaves) if len(dims) > level: if dims[level] != level_dim: return False else: dims.append(level_dim) if level_dim is not None: for leaf in expr.leaves: if not check(level + 1, leaf): return False return True if not check(0, expr): return Symbol('False') depth = len(dims) - 1 # None doesn't count if not pattern.does_match(Integer(depth), evaluation): return Symbol('False') return Symbol('True')
def apply(self, expr, patterns, f, evaluation): 'Reap[expr_, {patterns___}, f_]' patterns = patterns.get_sequence() sown = [(Pattern.create(pattern), []) for pattern in patterns] def listener(e, tag): result = False for pattern, items in sown: if pattern.does_match(tag, evaluation): for item in items: if item[0].same(tag): item[1].append(e) break else: items.append((tag, [e])) result = True return result evaluation.add_listener('sow', listener) try: result = expr.evaluate(evaluation) items = [] for pattern, tags in sown: list = Expression('List') for tag, elements in tags: list.leaves.append(Expression(f, tag, Expression('List', *elements))) items.append(list) return Expression('List', result, Expression('List', *items)) finally: evaluation.remove_listener('sow', listener)
def apply(self, f, x, evaluation): 'D[f_, x_?NotListQ]' if f == x: return Integer(1) elif not f.is_atom() and len(f.leaves) == 1 and f.leaves[0] == x: return Expression( Expression(Expression('Derivative', Integer(1)), f.head), x) elif not f.is_atom() and len(f.leaves) == 1: g = f.leaves[0] return Expression( 'Times', Expression('D', Expression(f.head, g), g), Expression('D', g, x)) elif not f.is_atom() and len(f.leaves) > 1: def summand(leaf, index): if leaf.same(x): result = Expression(Expression( Expression( 'Derivative', *([Integer(0)] * (index) + [Integer(1)] + [Integer(0)] * (len(f.leaves) - index - 1))), f.head), *f.leaves) else: result = Expression('D', f, leaf) return Expression('Times', result, Expression('D', leaf, x)) x_pattern = Pattern.create(x) result = Expression( 'Plus', *[ summand(leaf, index) for index, leaf in enumerate(f.leaves) if not leaf.is_free(x_pattern, evaluation)]) if len(result.leaves) == 1: return result.leaves[0] else: return result
def apply(self, expr, form, evaluation): "FreeQ[expr_, form_]" form = Pattern.create(form) if expr.is_free(form, evaluation): return Symbol("True") else: return Symbol("False")
def apply(self, expr, form, evaluation): 'FreeQ[expr_, form_]' form = Pattern.create(form) if expr.is_free(form, evaluation): return Symbol('True') else: return Symbol('False')
def apply(self, expr, form, evaluation): 'FreeQ[expr_, form_]' """def is_free(sub): for vars, rest in form.match(sub, {}, evaluation, fully=False): return False if sub.is_atom(): return True else: return is_free(sub.head) and all(is_free(leaf) for leaf in sub.leaves)""" form = Pattern.create(form) if expr.is_free(form, evaluation): return Symbol('True') else: return Symbol('False')
def apply(self, eqs, vars, evaluation): 'Solve[eqs_, vars_]' vars_original = vars head_name = vars.get_head_name() if head_name == 'System`List': vars = vars.leaves else: vars = [vars] for var in vars: if ((var.is_atom() and not var.is_symbol()) or # noqa head_name in ('System`Plus', 'System`Times', 'System`Power') or 'System`Constant' in var.get_attributes(evaluation.definitions)): evaluation.message('Solve', 'ivar', vars_original) return eqs_original = eqs if eqs.get_head_name() in ('System`List', 'System`And'): eqs = eqs.leaves else: eqs = [eqs] sympy_eqs = [] sympy_denoms = [] for eq in eqs: symbol_name = eq.get_name() if symbol_name == 'System`True': pass elif symbol_name == 'System`False': return Expression('List') elif not eq.has_form('Equal', 2): return evaluation.message('Solve', 'eqf', eqs_original) else: left, right = eq.leaves left = left.to_sympy() right = right.to_sympy() if left is None or right is None: return eq = left - right eq = sympy.together(eq) eq = sympy.cancel(eq) sympy_eqs.append(eq) numer, denom = eq.as_numer_denom() sympy_denoms.append(denom) vars_sympy = [var.to_sympy() for var in vars] if None in vars_sympy: return # delete unused variables to avoid SymPy's # PolynomialError: Not a zero-dimensional system # in e.g. Solve[x^2==1&&z^2==-1,{x,y,z}] all_vars = vars[:] all_vars_sympy = vars_sympy[:] vars = [] vars_sympy = [] for var, var_sympy in zip(all_vars, all_vars_sympy): pattern = Pattern.create(var) if not eqs_original.is_free(pattern, evaluation): vars.append(var) vars_sympy.append(var_sympy) def transform_dict(sols): if not sols: yield sols for var, sol in six.iteritems(sols): rest = sols.copy() del rest[var] rest = transform_dict(rest) if not isinstance(sol, (tuple, list)): sol = [sol] if not sol: for r in rest: yield r else: for r in rest: for item in sol: new_sols = r.copy() new_sols[var] = item yield new_sols break def transform_solution(sol): if not isinstance(sol, dict): if not isinstance(sol, (list, tuple)): sol = [sol] sol = dict(list(zip(vars_sympy, sol))) return transform_dict(sol) if not sympy_eqs: sympy_eqs = True elif len(sympy_eqs) == 1: sympy_eqs = sympy_eqs[0] try: if isinstance(sympy_eqs, bool): result = sympy_eqs else: result = sympy.solve(sympy_eqs, vars_sympy) if not isinstance(result, list): result = [result] if (isinstance(result, list) and len(result) == 1 and result[0] is True): return Expression('List', Expression('List')) if result == [None]: return Expression('List') results = [] for sol in result: results.extend(transform_solution(sol)) result = results if any(sol and any(var not in sol for var in all_vars_sympy) for sol in result): evaluation.message('Solve', 'svars') # Filter out results for which denominator is 0 # (SymPy should actually do that itself, but it doesn't!) result = [sol for sol in result if all( sympy.simplify(denom.subs(sol)) != 0 for denom in sympy_denoms)] return Expression('List', *(Expression( 'List', *(Expression('Rule', var, from_sympy(sol[var_sympy])) for var, var_sympy in zip(vars, vars_sympy) if var_sympy in sol) ) for sol in result)) except sympy.PolynomialError: # raised for e.g. Solve[x^2==1&&z^2==-1,{x,y,z}] when not deleting # unused variables beforehand pass except NotImplementedError: pass except TypeError as exc: if str(exc).startswith("expected Symbol, Function or Derivative"): evaluation.message('Solve', 'ivar', vars_original)
def apply(self, f, x, evaluation): "D[f_, x_?NotListQ]" x_pattern = Pattern.create(x) if f.is_free(x_pattern, evaluation): return IntegerZero elif f == x: return Integer1 elif f.is_atom(): # Shouldn't happen 1 / 0 return # So, this is not an atom... head = f.get_head() if head == SymbolPlus: terms = [ Expression("D", term, x) for term in f.leaves if not term.is_free(x_pattern, evaluation) ] if len(terms) == 0: return IntegerZero return Expression(SymbolPlus, *terms) elif head == SymbolTimes: terms = [] for i, factor in enumerate(f.leaves): if factor.is_free(x_pattern, evaluation): continue factors = [leaf for j, leaf in enumerate(f.leaves) if j != i] factors.append(Expression("D", factor, x)) terms.append(Expression(SymbolTimes, *factors)) if len(terms) != 0: return Expression(SymbolPlus, *terms) else: return IntegerZero elif head == SymbolPower and len(f.leaves) == 2: base, exp = f.leaves terms = [] if not base.is_free(x_pattern, evaluation): terms.append( Expression( SymbolTimes, exp, Expression( SymbolPower, base, Expression(SymbolPlus, exp, IntegerMinusOne), ), Expression("D", base, x), )) if not exp.is_free(x_pattern, evaluation): if base.is_atom() and base.get_name() == "System`E": terms.append( Expression(SymbolTimes, f, Expression("D", exp, x))) else: terms.append( Expression( SymbolTimes, f, Expression("Log", base), Expression("D", exp, x), )) if len(terms) == 0: return IntegerZero elif len(terms) == 1: return terms[0] else: return Expression(SymbolPlus, *terms) elif len(f.leaves) == 1: if f.leaves[0] == x: return Expression( Expression(Expression("Derivative", Integer(1)), f.head), x) else: g = f.leaves[0] return Expression( SymbolTimes, Expression("D", Expression(f.head, g), g), Expression("D", g, x), ) else: # many leaves def summand(leaf, index): result = Expression( Expression( Expression( "Derivative", *([IntegerZero] * (index) + [Integer1] + [IntegerZero] * (len(f.leaves) - index - 1))), f.head, ), *f.leaves) if leaf.sameQ(x): return result else: return Expression("Times", result, Expression("D", leaf, x)) result = [ summand(leaf, index) for index, leaf in enumerate(f.leaves) if not leaf.is_free(x_pattern, evaluation) ] if len(result) == 1: return result[0] elif len(result) == 0: return IntegerZero else: return Expression("Plus", *result)
def apply(self, f, xs, evaluation, options): "Integrate[f_, xs__, OptionsPattern[]]" self.patpow0 = Pattern.create( Expression("Power", Integer0, Expression("Blank"))) assuming = options["System`Assumptions"].evaluate(evaluation) f_sympy = f.to_sympy() if f_sympy is None or isinstance(f_sympy, SympyExpression): return xs = xs.get_sequence() vars = [] prec = None for x in xs: if x.has_form("List", 3): x, a, b = x.leaves prec_a = a.get_precision() prec_b = b.get_precision() if prec_a is not None and prec_b is not None: prec_new = min(prec_a, prec_b) if prec is None or prec_new < prec: prec = prec_new a = a.to_sympy() b = b.to_sympy() if a is None or b is None: return else: a = b = None if not x.get_name(): evaluation.message("Integrate", "ilim") return x = x.to_sympy() if x is None: return if a is None or b is None: vars.append(x) else: vars.append((x, a, b)) try: result = sympy.integrate(f_sympy, *vars) except sympy.PolynomialError: return except ValueError: # e.g. ValueError: can't raise polynomial to a negative power return except NotImplementedError: # e.g. NotImplementedError: Result depends on the sign of # -sign(_Mathics_User_j)*sign(_Mathics_User_w) return if prec is not None and isinstance(result, sympy.Integral): # TODO MaxExtaPrecision -> maxn result = result.evalf(dps(prec)) else: result = from_sympy(result) # If the result is defined as a Piecewise expression, # use ConditionalExpression. # This does not work now because the form sympy returns the values if result.get_head_name() == "System`Piecewise": cases = result._leaves[0]._leaves if len(result._leaves) == 1: if cases[-1]._leaves[1].is_true(): default = cases[-1]._leaves[0] cases = result._leaves[0]._leaves[:-1] else: default = SymbolUndefined else: cases = result._leaves[0]._leaves default = result._leaves[1] if default.has_form("Integrate", None): if default._leaves[0] == f: default = SymbolUndefined simplified_cases = [] for case in cases: # TODO: if something like 0^n or 1/expr appears, # put the condition n!=0 or expr!=0 accordingly in the list of # conditions... cond = Expression("Simplify", case._leaves[1], assuming).evaluate(evaluation) resif = Expression("Simplify", case._leaves[0], assuming).evaluate(evaluation) if cond.is_true(): return resif if resif.has_form("ConditionalExpression", 2): cond = Expression("And", resif._leaves[1], cond) cond = Expression("Simplify", cond, assuming).evaluate(evaluation) resif = resif._leaves[0] simplified_cases.append(Expression(SymbolList, resif, cond)) cases = simplified_cases if default == SymbolUndefined and len(cases) == 1: cases = cases[0] result = Expression("ConditionalExpression", *(cases._leaves)) else: result = Expression(result._head, cases, default) else: result = Expression("Simplify", result, assuming).evaluate(evaluation) return result
def apply(self, eqs, vars, evaluation): 'Solve[eqs_, vars_]' vars_original = vars head_name = vars.get_head_name() if head_name == 'List': vars = vars.leaves else: vars = [vars] for var in vars: if (var.is_atom() and not var.is_symbol()) or head_name in ('Plus', 'Times', 'Power'): evaluation.message('Solve', 'ivar', vars_original) return eqs_original = eqs if eqs.get_head_name() in ('List', 'And'): eqs = eqs.leaves else: eqs = [eqs] sympy_eqs = [] sympy_denoms = [] for eq in eqs: symbol_name = eq.get_name() if symbol_name == 'True': #return Expression('List', Expression('List')) pass elif symbol_name == 'False': return Expression('List') elif not eq.has_form('Equal', 2): return evaluation.message('Solve', 'eqf', eqs_original) else: left, right = eq.leaves left = left.to_sympy() right = right.to_sympy() #vars_sympy = [var.to_sympy() for var in vars] eq = left - right eq = sympy.together(eq) eq = sympy.cancel(eq) sympy_eqs.append(eq) numer, denom = eq.as_numer_denom() sympy_denoms.append(denom) #eqs = actual_eqs #left, right = eq.leaves vars_sympy = [var.to_sympy() for var in vars] # delete unused variables to avoid SymPy's # PolynomialError: Not a zero-dimensional system # in e.g. Solve[x^2==1&&z^2==-1,{x,y,z}] all_vars = vars[:] all_vars_sympy = vars_sympy[:] #for index, var in enumerate(all_vars): # if eqs_original.is_free(var, evaluation): vars = [] vars_sympy = [] for var, var_sympy in zip(all_vars, all_vars_sympy): pattern = Pattern.create(var) if not eqs_original.is_free(pattern, evaluation): vars.append(var) vars_sympy.append(var_sympy) def transform_dict(sols): #print "Transform %s" % sols if not sols: yield sols for var, sol in sols.iteritems(): rest = sols.copy() del rest[var] rest = transform_dict(rest) if not isinstance(sol, (tuple, list)): #print "Convert %s (type %s)" % (sol, type(sol)) sol = [sol] if not sol: for r in rest: #print "Yield %s" % r yield r else: for r in rest: for item in sol: #print "Yield %s with new %s" % (r, item) new_sols = r.copy() new_sols[var] = item yield new_sols break def transform_solution(sol): #if isinstance(sol, (list, tuple)): if not isinstance(sol, dict): if not isinstance(sol, (list, tuple)): sol = [sol] sol = dict(zip(vars_sympy, sol)) #return sol return transform_dict(sol) if not sympy_eqs: sympy_eqs = True elif len(sympy_eqs) == 1: sympy_eqs = sympy_eqs[0] #eq = left - right #eq = sympy.together(eq) #eq = sympy.cancel(eq) # otherwise Solve[f''[x]==0,x] for f[x_]:=4 x / (x ^ 2 + 3 x + 5) takes forever try: #print sympy_eqs result = sympy.solve(sympy_eqs, vars_sympy) #print result if not isinstance(result, list): result = [result] if result == [True]: return Expression('List', Expression('List')) if result == [None]: return Expression('List') #print result #result = [transform_solution(sol) for sol in result] results = [] for sol in result: results.extend(transform_solution(sol)) result = results #print result if any(sol and any(var not in sol for var in all_vars_sympy) for sol in result): evaluation.message('Solve', 'svars') #numer, denom = eq.as_numer_denom() #for sol in result: # sol_denom = denom.subs({var_sympy: sol}) result = [ sol for sol in result if all( sympy.simplify(denom.subs(sol)) != 0 for denom in sympy_denoms) ] # filter out results for which denominator is 0 # (SymPy should actually do that itself, but it doesn't!) return Expression( 'List', *(Expression( 'List', *(Expression('Rule', var, from_sympy(sol[var_sympy])) for var, var_sympy in zip(vars, vars_sympy) if var_sympy in sol)) for sol in result)) #except TypeError: #evaluation.message('Solve', 'ivar', vars_original) #raise except sympy.PolynomialError: # raised for e.g. Solve[x^2==1&&z^2==-1,{x,y,z}] when not deleting unused variables beforehand pass except NotImplementedError: pass
def apply(self, eqs, vars, evaluation): 'Solve[eqs_, vars_]' vars_original = vars head_name = vars.get_head_name() if head_name == 'System`List': vars = vars.leaves else: vars = [vars] for var in vars: if ((var.is_atom() and not var.is_symbol()) or # noqa head_name in ('System`Plus', 'System`Times', 'System`Power') or 'System`Constant' in var.get_attributes(evaluation.definitions)): evaluation.message('Solve', 'ivar', vars_original) return eqs_original = eqs if eqs.get_head_name() in ('System`List', 'System`And'): eqs = eqs.leaves else: eqs = [eqs] sympy_eqs = [] sympy_denoms = [] for eq in eqs: symbol_name = eq.get_name() if symbol_name == 'System`True': pass elif symbol_name == 'System`False': return Expression('List') elif not eq.has_form('Equal', 2): return evaluation.message('Solve', 'eqf', eqs_original) else: left, right = eq.leaves left = left.to_sympy() right = right.to_sympy() eq = left - right eq = sympy.together(eq) eq = sympy.cancel(eq) sympy_eqs.append(eq) numer, denom = eq.as_numer_denom() sympy_denoms.append(denom) vars_sympy = [var.to_sympy() for var in vars] # delete unused variables to avoid SymPy's # PolynomialError: Not a zero-dimensional system # in e.g. Solve[x^2==1&&z^2==-1,{x,y,z}] all_vars = vars[:] all_vars_sympy = vars_sympy[:] vars = [] vars_sympy = [] for var, var_sympy in zip(all_vars, all_vars_sympy): pattern = Pattern.create(var) if not eqs_original.is_free(pattern, evaluation): vars.append(var) vars_sympy.append(var_sympy) def transform_dict(sols): if not sols: yield sols for var, sol in six.iteritems(sols): rest = sols.copy() del rest[var] rest = transform_dict(rest) if not isinstance(sol, (tuple, list)): sol = [sol] if not sol: for r in rest: yield r else: for r in rest: for item in sol: new_sols = r.copy() new_sols[var] = item yield new_sols break def transform_solution(sol): if not isinstance(sol, dict): if not isinstance(sol, (list, tuple)): sol = [sol] sol = dict(list(zip(vars_sympy, sol))) return transform_dict(sol) if not sympy_eqs: sympy_eqs = True elif len(sympy_eqs) == 1: sympy_eqs = sympy_eqs[0] try: if isinstance(sympy_eqs, bool): result = sympy_eqs else: result = sympy.solve(sympy_eqs, vars_sympy) if not isinstance(result, list): result = [result] if (isinstance(result, list) and len(result) == 1 and result[0] is True): return Expression('List', Expression('List')) if result == [None]: return Expression('List') results = [] for sol in result: results.extend(transform_solution(sol)) result = results if any(sol and any(var not in sol for var in all_vars_sympy) for sol in result): evaluation.message('Solve', 'svars') # Filter out results for which denominator is 0 # (SymPy should actually do that itself, but it doesn't!) result = [sol for sol in result if all( sympy.simplify(denom.subs(sol)) != 0 for denom in sympy_denoms)] return Expression('List', *(Expression( 'List', *(Expression('Rule', var, from_sympy(sol[var_sympy])) for var, var_sympy in zip(vars, vars_sympy) if var_sympy in sol) ) for sol in result)) except sympy.PolynomialError: # raised for e.g. Solve[x^2==1&&z^2==-1,{x,y,z}] when not deleting # unused variables beforehand pass except NotImplementedError: pass except TypeError as exc: if str(exc).startswith("expected Symbol, Function or Derivative"): evaluation.message('Solve', 'ivar', vars_original)
def apply(self, eqs, vars, evaluation): 'Solve[eqs_, vars_]' vars_original = vars head_name = vars.get_head_name() if head_name == 'List': vars = vars.leaves else: vars = [vars] for var in vars: if (var.is_atom() and not var.is_symbol()) or head_name in ('Plus', 'Times', 'Power'): evaluation.message('Solve', 'ivar', vars_original) return eqs_original = eqs if eqs.get_head_name() in ('List', 'And'): eqs = eqs.leaves else: eqs = [eqs] sympy_eqs = [] sympy_denoms = [] for eq in eqs: symbol_name = eq.get_name() if symbol_name == 'True': #return Expression('List', Expression('List')) pass elif symbol_name == 'False': return Expression('List') elif not eq.has_form('Equal', 2): return evaluation.message('Solve', 'eqf', eqs_original) else: left, right = eq.leaves left = left.to_sympy() right = right.to_sympy() #vars_sympy = [var.to_sympy() for var in vars] eq = left - right eq = sympy.together(eq) eq = sympy.cancel(eq) sympy_eqs.append(eq) numer, denom = eq.as_numer_denom() sympy_denoms.append(denom) #eqs = actual_eqs #left, right = eq.leaves vars_sympy = [var.to_sympy() for var in vars] # delete unused variables to avoid SymPy's # PolynomialError: Not a zero-dimensional system # in e.g. Solve[x^2==1&&z^2==-1,{x,y,z}] all_vars = vars[:] all_vars_sympy = vars_sympy[:] #for index, var in enumerate(all_vars): # if eqs_original.is_free(var, evaluation): vars = [] vars_sympy = [] for var, var_sympy in zip(all_vars, all_vars_sympy): pattern = Pattern.create(var) if not eqs_original.is_free(pattern, evaluation): vars.append(var) vars_sympy.append(var_sympy) def transform_dict(sols): #print "Transform %s" % sols if not sols: yield sols for var, sol in sols.iteritems(): rest = sols.copy() del rest[var] rest = transform_dict(rest) if not isinstance(sol, (tuple, list)): #print "Convert %s (type %s)" % (sol, type(sol)) sol = [sol] if not sol: for r in rest: #print "Yield %s" % r yield r else: for r in rest: for item in sol: #print "Yield %s with new %s" % (r, item) new_sols = r.copy() new_sols[var] = item yield new_sols break def transform_solution(sol): #if isinstance(sol, (list, tuple)): if not isinstance(sol, dict): if not isinstance(sol, (list, tuple)): sol = [sol] sol = dict(zip(vars_sympy, sol)) #return sol return transform_dict(sol) if not sympy_eqs: sympy_eqs = True elif len(sympy_eqs) == 1: sympy_eqs = sympy_eqs[0] #eq = left - right #eq = sympy.together(eq) #eq = sympy.cancel(eq) # otherwise Solve[f''[x]==0,x] for f[x_]:=4 x / (x ^ 2 + 3 x + 5) takes forever try: #print sympy_eqs result = sympy.solve(sympy_eqs, vars_sympy) #print result if not isinstance(result, list): result = [result] if result == [True]: return Expression('List', Expression('List')) if result == [None]: return Expression('List') #print result #result = [transform_solution(sol) for sol in result] results = [] for sol in result: results.extend(transform_solution(sol)) result = results #print result if any(sol and any(var not in sol for var in all_vars_sympy) for sol in result): evaluation.message('Solve', 'svars') #numer, denom = eq.as_numer_denom() #for sol in result: # sol_denom = denom.subs({var_sympy: sol}) result = [sol for sol in result if all(sympy.simplify(denom.subs(sol)) != 0 for denom in sympy_denoms)] # filter out results for which denominator is 0 # (SymPy should actually do that itself, but it doesn't!) return Expression('List', *(Expression('List', *(Expression('Rule', var, from_sympy(sol[var_sympy])) for var, var_sympy in zip(vars, vars_sympy) if var_sympy in sol)) for sol in result)) #except TypeError: #evaluation.message('Solve', 'ivar', vars_original) #raise except sympy.PolynomialError: # raised for e.g. Solve[x^2==1&&z^2==-1,{x,y,z}] when not deleting unused variables beforehand pass except NotImplementedError: pass