From eb831c2ad5ea271a5358915a2340d641e2866631 Mon Sep 17 00:00:00 2001 From: "R. Bernstein" Date: Sun, 20 Oct 2024 20:35:25 -0400 Subject: [PATCH 1/4] Simplify & inference fns moved under mathics.eval (#1140) --- mathics/builtin/arithmetic.py | 2 +- mathics/builtin/numbers/algebra.py | 71 ++++-------------------- mathics/builtin/numeric.py | 7 ++- mathics/{builtin => eval}/inference.py | 33 +++++++---- mathics/eval/numbers/algebra/simplify.py | 63 +++++++++++++++++++++ 5 files changed, 100 insertions(+), 76 deletions(-) rename mathics/{builtin => eval}/inference.py (95%) diff --git a/mathics/builtin/arithmetic.py b/mathics/builtin/arithmetic.py index bd42e7e74..0313ceb94 100644 --- a/mathics/builtin/arithmetic.py +++ b/mathics/builtin/arithmetic.py @@ -10,7 +10,6 @@ import sympy -from mathics.builtin.inference import get_assumptions_list from mathics.builtin.numeric import Abs from mathics.builtin.scoping import dynamic_scoping from mathics.core.atoms import ( @@ -72,6 +71,7 @@ SymbolUndefined, ) from mathics.eval.arithmetic import eval_Sign +from mathics.eval.inference import get_assumptions_list from mathics.eval.nevaluator import eval_N # This tells documentation how to sort this module diff --git a/mathics/builtin/numbers/algebra.py b/mathics/builtin/numbers/algebra.py index 6fb082bcf..51c0a0591 100644 --- a/mathics/builtin/numbers/algebra.py +++ b/mathics/builtin/numbers/algebra.py @@ -17,7 +17,6 @@ import sympy -from mathics.builtin.inference import evaluate_predicate from mathics.builtin.options import options_to_rules from mathics.builtin.scoping import dynamic_scoping from mathics.core.atoms import Integer, Integer0, Integer1, Number, RationalOneHalf @@ -63,7 +62,10 @@ SymbolTable, SymbolTanh, ) -from mathics.eval.numbers.algebra.simplify import default_complexity_function +from mathics.eval.numbers.algebra.simplify import ( + default_complexity_function, + eval_Simplify, +) from mathics.eval.numbers.numbers import cancel, sympy_factor from mathics.eval.parts import walk_parts from mathics.eval.patterns import match @@ -1496,7 +1498,10 @@ def eval_list(self, expr, vars, evaluation): # FullSimplify class Simplify(Builtin): r""" - :WMA link: + :SymPy: + https://docs.sympy.org/latest/modules/simplify + /simplify.html, + :WMA: https://reference.wolfram.com/language/ref/Simplify.html
@@ -1605,65 +1610,9 @@ def eval(self, expr, evaluation, options={}): {"System`$Assumptions": assumptions}, evaluation, ) - return self.do_apply(expr, evaluation, options) - - def do_apply(self, expr, evaluation, options={}): - # Check first if we are dealing with a logic expression... - if expr in (SymbolTrue, SymbolFalse, SymbolList): - return expr - - # ``evaluate_predicate`` tries to reduce expr taking into account - # the assumptions established in ``$Assumptions``. - expr = evaluate_predicate(expr, evaluation) - - # If we get an atom, return it. - if isinstance(expr, Atom): - return expr - - # Now, try to simplify the elements. - # TODO: Consider to move this step inside ``evaluate_predicate``. - # Notice that here we want to pass through the full evaluation process - # to use all the defined rules... - name = self.get_name() - symbol_name = Symbol(name) - elements = [ - Expression(symbol_name, element).evaluate(evaluation) - for element in expr._elements - ] - head = Expression(symbol_name, expr.get_head()).evaluate(evaluation) - expr = Expression(head, *elements) - # At this point, we used all the tools available in Mathics. - # If the expression has a sympy form, try to use it. - # Now, convert the expression to sympy - sympy_expr = expr.to_sympy() - # If the expression cannot be handled by Sympy, just return it. - if sympy_expr is None: - return expr - # Now, try to simplify using sympy - complexity_function = options.get("System`ComplexityFunction", None) - if complexity_function is None or complexity_function is SymbolAutomatic: - - def _default_complexity_function(x): - return default_complexity_function(from_sympy(x)) - - complexity_function = _default_complexity_function - else: - if isinstance(complexity_function, (Expression, Symbol)): - _complexity_function = complexity_function - complexity_function = ( - lambda x: Expression(_complexity_function, from_sympy(x)) - .evaluate(evaluation) - .to_python() - ) - - # At this point, ``complexity_function`` is a function that takes a - # sympy expression and returns an integer. - sympy_result = sympy.simplify(sympy_expr, measure=complexity_function) - - # and bring it back - result = from_sympy(sympy_result).evaluate(evaluation) - return result + symbol_name = Symbol(self.get_name()) + return eval_Simplify(symbol_name, expr, evaluation, options) class FullSimplify(Simplify): diff --git a/mathics/builtin/numeric.py b/mathics/builtin/numeric.py index 1d5a65d32..27f283f69 100644 --- a/mathics/builtin/numeric.py +++ b/mathics/builtin/numeric.py @@ -15,7 +15,6 @@ import sympy -from mathics.builtin.inference import evaluate_predicate from mathics.core.atoms import ( Complex, Integer, @@ -52,6 +51,7 @@ eval_RealSign, eval_Sign, ) +from mathics.eval.inference import evaluate_predicate from mathics.eval.nevaluator import eval_NValues @@ -319,7 +319,10 @@ def eval_N(self, expr, evaluation: Evaluation): class Piecewise(SympyFunction): """ - :WMA link:https://reference.wolfram.com/language/ref/Piecewise.html + :SymPy: + https://docs.sympy.org/latest/modules/functions + /elementary.html#piecewise, + :WMA:https://reference.wolfram.com/language/ref/Piecewise.html
'Piecewise[{{expr1, cond1}, ...}]' diff --git a/mathics/builtin/inference.py b/mathics/eval/inference.py similarity index 95% rename from mathics/builtin/inference.py rename to mathics/eval/inference.py index b34beb384..1f1e10eab 100644 --- a/mathics/builtin/inference.py +++ b/mathics/eval/inference.py @@ -3,8 +3,7 @@ Inference Functions """ -no_doc = "no doc" - +from mathics.core.evaluation import Evaluation from mathics.core.expression import Expression from mathics.core.parser import parse_builtin_rule from mathics.core.parser.util import SystemDefinitions @@ -14,11 +13,21 @@ # TODO: Extend these rules? +no_doc = "no doc" + + +def debug_logical_expr(pref, expr, evaluation: Evaluation): + print( + pref, expr + ) # expr.format(evaluation,"OutputForm").boxes_to_text(evaluation=evaluation)) + + +def null_debug_logical_expr(pref, expr, evaluation: Evaluation): + return + -def debug_logical_expr(pref, expr, evaluation): - pass - # return - # print(pref , expr) #expr.format(evaluation,"OutputForm").boxes_to_text(evaluation=evaluation)) +# Tracing can redefine this to provide trace information +DEBUG_LOGICAL_EXPR = null_debug_logical_expr logical_algebraic_rules_spec = { @@ -105,7 +114,7 @@ def remove_nots_when_unnecesary(pred, evaluation): cc = True while cc: pred, cc = pred.do_apply_rules(remove_not_rules, evaluation) - debug_logical_expr("-> ", pred, evaluation) + DEBUG_LOGICAL_EXPR("-> ", pred, evaluation) if pred is SymbolTrue or pred is SymbolFalse: return pred return pred @@ -362,14 +371,14 @@ def evaluate_predicate(pred, evaluation): *[evaluate_predicate(subp, evaluation) for subp in pred.elements], ) - debug_logical_expr("reducing ", pred, evaluation) + DEBUG_LOGICAL_EXPR("reducing ", pred, evaluation) ensure_logical_algebraic_rules() pred = pred.evaluate(evaluation) - debug_logical_expr("-> ", pred, evaluation) + DEBUG_LOGICAL_EXPR("-> ", pred, evaluation) cc = True while cc: pred, cc = pred.do_apply_rules(logical_algebraic_rules, evaluation) - debug_logical_expr("-> ", pred, evaluation) + DEBUG_LOGICAL_EXPR("-> ", pred, evaluation) if pred is SymbolTrue or pred is SymbolFalse: return pred @@ -378,11 +387,11 @@ def evaluate_predicate(pred, evaluation): return remove_nots_when_unnecesary(pred, evaluation).evaluate(evaluation) if assumption_rules is not None: - debug_logical_expr(" Now, using the assumptions over ", pred, evaluation) + DEBUG_LOGICAL_EXPR(" Now, using the assumptions over ", pred, evaluation) changed = True while changed: pred, changed = pred.do_apply_rules(assumption_rules, evaluation) - debug_logical_expr(" -> ", pred, evaluation) + DEBUG_LOGICAL_EXPR(" -> ", pred, evaluation) pred = remove_nots_when_unnecesary(pred, evaluation).evaluate(evaluation) return pred diff --git a/mathics/eval/numbers/algebra/simplify.py b/mathics/eval/numbers/algebra/simplify.py index 5cf158515..fb2a40e97 100644 --- a/mathics/eval/numbers/algebra/simplify.py +++ b/mathics/eval/numbers/algebra/simplify.py @@ -4,8 +4,14 @@ Algorithms for simplifying expressions and evaluate complexity. """ +from sympy import simplify + from mathics.core.atoms import Number +from mathics.core.convert.sympy import from_sympy from mathics.core.expression import Expression +from mathics.core.symbols import Atom, Symbol, SymbolFalse, SymbolList, SymbolTrue +from mathics.core.systemsymbols import SymbolAutomatic +from mathics.eval.inference import evaluate_predicate def default_complexity_function(expr: Expression) -> int: @@ -24,3 +30,60 @@ def default_complexity_function(expr: Expression) -> int: ) else: return 1 + + +def eval_Simplify(symbol_name: Symbol, expr, evaluation, options: dict): + # Check first if we are dealing with a logic expression... + if expr in (SymbolTrue, SymbolFalse, SymbolList): + return expr + + # ``evaluate_predicate`` tries to reduce expr taking into account + # the assumptions established in ``$Assumptions``. + expr = evaluate_predicate(expr, evaluation) + + # If we get an atom, return it. + if isinstance(expr, Atom): + return expr + + # Now, try to simplify the elements. + # TODO: Consider to move this step inside ``evaluate_predicate``. + # Notice that here we want to pass through the full evaluation process + # to use all the defined rules... + elements = [ + Expression(symbol_name, element).evaluate(evaluation) + for element in expr._elements + ] + head = Expression(symbol_name, expr.get_head()).evaluate(evaluation) + expr = Expression(head, *elements) + + # At this point, we used all the tools available in Mathics. + # If the expression has a sympy form, try to use it. + # Now, convert the expression to sympy + sympy_expr = expr.to_sympy() + # If the expression cannot be handled by Sympy, just return it. + if sympy_expr is None: + return expr + # Now, try to simplify using sympy + complexity_function = options.get("System`ComplexityFunction", None) + if complexity_function is None or complexity_function is SymbolAutomatic: + + def _default_complexity_function(x): + return default_complexity_function(from_sympy(x)) + + complexity_function = _default_complexity_function + else: + if isinstance(complexity_function, (Expression, Symbol)): + _complexity_function = complexity_function + complexity_function = ( + lambda x: Expression(_complexity_function, from_sympy(x)) + .evaluate(evaluation) + .to_python() + ) + + # At this point, ``complexity_function`` is a function that takes a + # sympy expression and returns an integer. + sympy_result = simplify(sympy_expr, measure=complexity_function) + + # and bring it back + result = from_sympy(sympy_result).evaluate(evaluation) + return result From e7ca02646d741cc6dd97579e51f65bba5e3db92b Mon Sep 17 00:00:00 2001 From: "R. Bernstein" Date: Sun, 20 Oct 2024 22:26:17 -0400 Subject: [PATCH 2/4] We can tolerate PyPy now... (#1139) Fixes #661 --------- Co-authored-by: Juan Mauricio Matera --- mathics/builtin/drawing/plot.py | 2 +- mathics/builtin/scipy_utils/integrators.py | 3 +-- mathics/builtin/scipy_utils/optimizers.py | 3 +-- mathics/eval/drawing/plot.py | 3 ++- mathics/eval/nevaluator.py | 2 +- 5 files changed, 6 insertions(+), 7 deletions(-) diff --git a/mathics/builtin/drawing/plot.py b/mathics/builtin/drawing/plot.py index 3069a9cae..e08af31f6 100644 --- a/mathics/builtin/drawing/plot.py +++ b/mathics/builtin/drawing/plot.py @@ -316,7 +316,7 @@ def eval(self, points, evaluation: Evaluation, options: dict): all_points = ( points.value if hasattr(points, "value") and points.value is not None - else eval_N(points, evaluation).to_python() + else eval_N(points, evaluation).to_python() # TODO: force tuple-ness? ) # FIXME: arrange for self to have a .symbolname property or attribute diff --git a/mathics/builtin/scipy_utils/integrators.py b/mathics/builtin/scipy_utils/integrators.py index 82db83667..39b4c078e 100644 --- a/mathics/builtin/scipy_utils/integrators.py +++ b/mathics/builtin/scipy_utils/integrators.py @@ -1,9 +1,8 @@ # -*- coding: utf-8 -*- from mathics.core.builtin import check_requires_list -from mathics.core.util import IS_PYPY -if IS_PYPY or not check_requires_list(["scipy", "numpy"]): +if not check_requires_list(["scipy", "numpy"]): raise ImportError import numpy as np diff --git a/mathics/builtin/scipy_utils/optimizers.py b/mathics/builtin/scipy_utils/optimizers.py index dcc52b47a..fe76eca3c 100644 --- a/mathics/builtin/scipy_utils/optimizers.py +++ b/mathics/builtin/scipy_utils/optimizers.py @@ -5,10 +5,9 @@ from mathics.core.evaluation import Evaluation from mathics.core.expression import Expression from mathics.core.systemsymbols import SymbolAutomatic, SymbolFailed, SymbolInfinity -from mathics.core.util import IS_PYPY from mathics.eval.nevaluator import eval_N -if IS_PYPY or not check_requires_list(["scipy", "numpy"]): +if not check_requires_list(["scipy", "numpy"]): raise ImportError diff --git a/mathics/eval/drawing/plot.py b/mathics/eval/drawing/plot.py index cc279fe40..3d34424c7 100644 --- a/mathics/eval/drawing/plot.py +++ b/mathics/eval/drawing/plot.py @@ -134,7 +134,8 @@ def quiet_f(*args): def eval_ListPlot( - plot_groups: list, + # TODO: plot_groups should be a tuple only? + plot_groups: Union[list, tuple], x_range: list, y_range: list, is_discrete_plot: bool, diff --git a/mathics/eval/nevaluator.py b/mathics/eval/nevaluator.py index 05751dd64..4dbe16674 100644 --- a/mathics/eval/nevaluator.py +++ b/mathics/eval/nevaluator.py @@ -29,7 +29,7 @@ def eval_N( expression: BaseElement, evaluation: Evaluation, prec: BaseElement = SymbolMachinePrecision, -) -> BaseElement: +) -> Optional[BaseElement]: """ Equivalent to Expression(SymbolN, expression).evaluate(evaluation) """ From 712337b4fc7eaa0c50bd0c37ee506406a166dd28 Mon Sep 17 00:00:00 2001 From: Juan Mauricio Matera Date: Mon, 21 Oct 2024 09:38:43 -0300 Subject: [PATCH 3/4] fixing check manifest (#1142) This PR just fixes and reinstall the SYMBOL_MANIFEST consistency check, to avoid erase/ duplicate symbols. --- .github/workflows/consistency-checks.yml | 1 + SYMBOLS_MANIFEST.txt | 30 +++++++++++-- admin-tools/build_and_check_manifest.py | 4 +- mathics/builtin/atomic/strings.py | 8 ++-- mathics/builtin/files_io/filesystem.py | 57 ------------------------ mathics/builtin/numbers/constants.py | 5 +++ 6 files changed, 39 insertions(+), 66 deletions(-) diff --git a/.github/workflows/consistency-checks.yml b/.github/workflows/consistency-checks.yml index ea3742c34..0cbf4dc4c 100644 --- a/.github/workflows/consistency-checks.yml +++ b/.github/workflows/consistency-checks.yml @@ -35,3 +35,4 @@ jobs: - name: Test Mathics Consistency and Style run: | make check-consistency-and-style + make check-builtin-manifest diff --git a/SYMBOLS_MANIFEST.txt b/SYMBOLS_MANIFEST.txt index 43c6e2162..47d30dde6 100644 --- a/SYMBOLS_MANIFEST.txt +++ b/SYMBOLS_MANIFEST.txt @@ -1,4 +1,3 @@ -CombinatoricaOld`BinarySearch HTML`DataImport HTML`FullDataImport HTML`HyperlinksImport @@ -40,6 +39,7 @@ System`$Machine System`$MachineEpsilon System`$MachineName System`$MachinePrecision +System`$MaxLengthIntStringConversion System`$MaxMachineNumber System`$MaxPrecision System`$MinMachineNumber @@ -105,7 +105,6 @@ System`Apart System`Append System`AppendTo System`Apply -System`ApplyLevel System`ArcCos System`ArcCosh System`ArcCot @@ -134,10 +133,12 @@ System`Attributes System`Automatic System`Axes System`Axis +System`Background System`BarChart System`BaseForm System`Begin System`BeginPackage +System`BellB System`BernoulliB System`BernsteinBasis System`BesselI @@ -197,6 +198,7 @@ System`ChartLegends System`ChebyshevT System`ChebyshevU System`Check +System`CheckAbort System`ChessboardDistance System`Chop System`Circle @@ -238,6 +240,7 @@ System`ConditionalExpression System`Cone System`Cone3DBox System`Conjugate +System`ConjugateTranspose System`Constant System`ConstantArray System`ContainsOnly @@ -322,6 +325,8 @@ System`Dispatch System`Divide System`DivideBy System`Divisible +System`DivisorSigma +System`DivisorSum System`Divisors System`Do System`Dodecahedron @@ -355,12 +360,14 @@ System`Erf System`Erfc System`Erosion System`EuclideanDistance +System`EulerE System`EulerGamma System`EulerPhi System`Evaluate System`EvenQ System`ExactNumberQ System`Except +System`Exit System`Exp System`ExpIntegralE System`ExpIntegralEi @@ -526,6 +533,8 @@ System`Integer System`IntegerDigits System`IntegerExponent System`IntegerLength +System`IntegerPart +System`IntegerPartitions System`IntegerQ System`IntegerReverse System`IntegerString @@ -543,6 +552,7 @@ System`InverseGudermannian System`InverseHaversine System`JaccardDissimilarity System`JacobiP +System`JacobiSymbol System`Join System`Joined System`KelvinBei @@ -554,6 +564,7 @@ System`Keys System`Khinchin System`KnownUnitQ System`KroneckerProduct +System`KroneckerSymbol System`Kurtosis System`LABColor System`LCHColor @@ -574,9 +585,9 @@ System`LessEqual System`LetterCharacter System`LetterNumber System`LetterQ -System`LeviCivitaTensor System`Level System`LevelQ +System`LeviCivitaTensor System`LightBlue System`LightBrown System`LightCyan @@ -600,6 +611,7 @@ System`ListLinePlot System`ListLogPlot System`ListPlot System`ListQ +System`ListStepPlot System`Listable System`LoadModule System`Locked @@ -612,6 +624,7 @@ System`LogisticSigmoid System`Longest System`Lookup System`LowerCaseQ +System`LucasL System`MachineNumberQ System`MachinePrecision System`Magenta @@ -619,6 +632,7 @@ System`MakeBoxes System`ManhattanDistance System`MantissaExponent System`Map +System`MapApply System`MapAt System`MapIndexed System`MapThread @@ -642,6 +656,7 @@ System`Medium System`MemberQ System`MemoryAvailable System`MemoryInUse +System`MersennePrimeExponent System`Mesh System`Message System`MessageName @@ -655,6 +670,7 @@ System`Missing System`Mod System`ModularInverse System`Module +System`MoebiusMu System`MorphologicalComponents System`Most System`Multinomial @@ -760,6 +776,7 @@ System`PolyGamma System`Polygon System`Polygon3DBox System`PolygonBox +System`PolygonalNumber System`PolynomialQ System`Position System`Positive @@ -768,6 +785,7 @@ System`Postfix System`Power System`PowerExpand System`PowerMod +System`PowersRepresentations System`PreDecrement System`PreIncrement System`Precedence @@ -793,6 +811,7 @@ System`PseudoInverse System`Purple System`Put System`PutAppend +System`PythonCProfileEvaluation System`PythonForm System`QRDecomposition System`Quantile @@ -827,8 +846,8 @@ System`ReadProtected System`Real System`RealAbs System`RealDigits -System`RealNumberQ System`RealSign +System`RealValuedNumberQ System`Reals System`Reap System`Record @@ -855,6 +874,7 @@ System`ResetDirectory System`Rest System`Return System`Reverse +System`ReverseSort System`Riffle System`Right System`RogersTanimotoDissimilarity @@ -886,6 +906,7 @@ System`Set System`SetAttributes System`SetDelayed System`SetDirectory +System`SetEnvironment System`SetFileDate System`SetOptions System`SetStreamPosition @@ -925,6 +946,7 @@ System`SplitBy System`Sqrt System`SqrtBox System`SquaredEuclideanDistance +System`SquaresR System`StandardDeviation System`StandardForm System`StartOfLine diff --git a/admin-tools/build_and_check_manifest.py b/admin-tools/build_and_check_manifest.py index 9a8400068..2a1c33fdb 100755 --- a/admin-tools/build_and_check_manifest.py +++ b/admin-tools/build_and_check_manifest.py @@ -5,7 +5,7 @@ from mathics.core.builtin import Builtin from mathics.core.load_builtin import ( import_and_load_builtins, - modules, + mathics3_builtins_modules, name_is_builtin_symbol, ) @@ -15,7 +15,7 @@ def generate_available_builtins_names(): msg = "" builtins_by_name = {} - for module in modules: + for module in mathics3_builtins_modules: vars = dir(module) for name in vars: var = name_is_builtin_symbol(module, name) diff --git a/mathics/builtin/atomic/strings.py b/mathics/builtin/atomic/strings.py index 72326d7b7..22291b7ec 100644 --- a/mathics/builtin/atomic/strings.py +++ b/mathics/builtin/atomic/strings.py @@ -411,14 +411,16 @@ class HexadecimalCharacter(Builtin): # This isn't your normal Box class. We'll keep this here rather than # in mathics.builtin.box for now. -class InterpretationBox(PrefixOperator): +# mmatera commenct: This does not even exist in WMA. \! should be associated +# to `ToExpression`, but it was not properly implemented by now... +class InterpretedBox(PrefixOperator): r""" :WMA link: https://reference.wolfram.com/language/ref/InterpretationBox.html
-
'InterpretationBox[$box$]' +
'InterpretedBox[$box$]'
is the ad hoc fullform for \! $box$. just for internal use...
@@ -430,7 +432,7 @@ class InterpretationBox(PrefixOperator): summary_text = "interpret boxes as an expression" def eval(self, boxes, evaluation: Evaluation): - """InterpretationBox[boxes_]""" + """InterpretedBox[boxes_]""" # TODO: the following is a very raw and dummy way to # handle these expressions. # In the first place, this should handle different kind diff --git a/mathics/builtin/files_io/filesystem.py b/mathics/builtin/files_io/filesystem.py index f0faf505e..59a7fea58 100644 --- a/mathics/builtin/files_io/filesystem.py +++ b/mathics/builtin/files_io/filesystem.py @@ -346,63 +346,6 @@ def eval(self, evaluation: Evaluation): return String(result) -class DirectoryName(Builtin): - """ - :WMA link:https://reference.wolfram.com/language/ref/DirectoryName.html - -
-
'DirectoryName["$name$"]' -
extracts the directory name from a filename. -
- - >> DirectoryName["a/b/c"] - = a/b - - >> DirectoryName["a/b/c", 2] - = a - """ - - messages = { - "string": "String expected at position 1 in `1`.", - "intpm": ("Positive machine-sized integer expected at " "position 2 in `1`."), - } - - options = { - "OperatingSystem": "$OperatingSystem", - } - summary_text = "directory part of a filename" - - def eval_with_n(self, name, n, evaluation: Evaluation, options: dict): - "DirectoryName[name_, n_, OptionsPattern[DirectoryName]]" - - if n is None: - expr = to_expression("DirectoryName", name) - py_n = 1 - else: - expr = to_expression("DirectoryName", name, n) - py_n = n.to_python() - - if not (isinstance(py_n, int) and py_n > 0): - evaluation.message("DirectoryName", "intpm", expr) - return - - py_name = name.to_python() - if not (isinstance(py_name, str) and py_name[0] == py_name[-1] == '"'): - evaluation.message("DirectoryName", "string", expr) - return - py_name = py_name[1:-1] - - result = py_name - for i in range(py_n): - (result, tmp) = osp.split(result) - - return String(result) - - def eval(self, name, evaluation: Evaluation, options: dict): - "DirectoryName[name_, OptionsPattern[DirectoryName]]" - return self.eval_with_n(name, None, evaluation, options) - - class DirectoryStack(Builtin): """ :WMA link:https://reference.wolfram.com/language/ref/DirectoryStack.html diff --git a/mathics/builtin/numbers/constants.py b/mathics/builtin/numbers/constants.py index fc9067197..2f4e4a1d6 100644 --- a/mathics/builtin/numbers/constants.py +++ b/mathics/builtin/numbers/constants.py @@ -756,3 +756,8 @@ class Underflow(Builtin): instance = cls(expression=False) val = instance.get_constant() NUMERICAL_CONSTANTS[instance.symbol] = MachineReal(val.value) + +# Remove these variables to prevent errors in the SYMBOL_MANIFEST check. +del cls +del instance +del val From 8c472bd199573f8500813da55a215f4be1e5278b Mon Sep 17 00:00:00 2001 From: "R. Bernstein" Date: Tue, 22 Oct 2024 06:47:11 -0400 Subject: [PATCH 4/4] Romberg is deprecated... (#1131) and will be removed by SciPyi 1.15 --- CHANGES.rst | 1 + mathics/builtin/scipy_utils/integrators.py | 18 +++--------------- test/builtin/numbers/test_nintegrate.py | 4 ++-- test/core/__init__.py | 0 4 files changed, 6 insertions(+), 17 deletions(-) create mode 100644 test/core/__init__.py diff --git a/CHANGES.rst b/CHANGES.rst index 0bedb26bc..41dd4d21c 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -33,6 +33,7 @@ API incompatibility ------------------- * ``Matcher`` now requires an additional ``evaluation`` parameter +* ``Romberg`` removed as an ``NIntegrate[]`` method. It is depcrecated in SciPy and is to be removed by SciPy 1.15. Bugs diff --git a/mathics/builtin/scipy_utils/integrators.py b/mathics/builtin/scipy_utils/integrators.py index 39b4c078e..bca1ec473 100644 --- a/mathics/builtin/scipy_utils/integrators.py +++ b/mathics/builtin/scipy_utils/integrators.py @@ -5,8 +5,6 @@ if not check_requires_list(["scipy", "numpy"]): raise ImportError -import numpy as np - def _scipy_interface(integrator, options_map, mandatory=None, adapt_func=None): """ @@ -24,7 +22,8 @@ def _scipy_proxy_func_filter(fun, a, b, **opts): if native_opt[1]: val = native_opt[1](val) native_opts[native_opt[0]] = val - return adapt_func(integrator(fun, a, b, **native_opts)) + if adapt_func is not None: + return adapt_func(integrator(fun, a, b, **native_opts)) def _scipy_proxy_func(fun, a, b, **opts): native_opts = {} @@ -42,7 +41,7 @@ def _scipy_proxy_func(fun, a, b, **opts): try: - from scipy.integrate import nquad, quad, romberg + from scipy.integrate import nquad, quad except Exception: scipy_nintegrate_methods = {} else: @@ -69,17 +68,6 @@ def _scipy_proxy_func(fun, a, b, **opts): False, ) ), - "Romberg": tuple( - ( - _scipy_interface( - romberg, - {"tol": ("tol", None), "maxrec": ("divmax", None)}, - None, - lambda x: (x, np.nan), - ), - False, - ) - ), } scipy_nintegrate_methods["Automatic"] = scipy_nintegrate_methods["Quadrature"] diff --git a/test/builtin/numbers/test_nintegrate.py b/test/builtin/numbers/test_nintegrate.py index cfe1e2b05..b3d9443a0 100644 --- a/test/builtin/numbers/test_nintegrate.py +++ b/test/builtin/numbers/test_nintegrate.py @@ -13,7 +13,7 @@ from mathics.core.builtin import check_requires_list if check_requires_list(["scipy", "scipy.integrate"]): - methods = ["Automatic", "Romberg", "Internal", "NQuadrature"] + methods = ["Automatic", "Internal", "NQuadrature"] generic_tests_for_nintegrate = [ (r"NIntegrate[x^2, {x,0,1}, {method} ]", r"1/3.", ""), @@ -46,7 +46,7 @@ "1.", None, [ - r"The Method option should be a built-in method name in {`Automatic`, `Internal`, `Simpson`, `NQuadrature`, `Quadrature`, `Romberg`}. Using `Automatic`" + r"The Method option should be a built-in method name in {`Automatic`, `Internal`, `Simpson`, `NQuadrature`, `Quadrature`}. Using `Automatic`" ], ), ], diff --git a/test/core/__init__.py b/test/core/__init__.py new file mode 100644 index 000000000..e69de29bb