Giter Club home page Giter Club logo

mathics3 / mathics-core Goto Github PK

View Code? Open in Web Editor NEW
715.0 14.0 40.0 27.21 MB

An open-source Mathematica. This repository contains the Python modules for WL Built-in functions, variables, core primitives, e.g. Symbol, a parser to create Expressions, and an evaluator to execute them.

Home Page: https://mathics.org

License: Other

Makefile 0.15% Shell 0.13% Perl 0.29% Python 86.20% Mathematica 9.00% HTML 3.88% TeX 0.34%
computer-algebra-system mathematica wolfram-language

mathics-core's Introduction

Welcome to Mathics Core!

Pypi Installs Latest Version Supported Python Versions

Packaging status

Mathics is a general-purpose computer algebra system (CAS).

However this repository contains just the Python modules for WL Built-in functions, variables, core primitives, e.g. Symbol, a parser to create Expressions, and an evaluator to execute them.

The home page for Mathics is https://mathics.org where you will find a list of screenshots and components making up the system.

Installing

Installing locally, requires a number of dependencies and OS package dependencies.

See the Installing Mathics for instructions on installing Mathics3.

Running:

Mathics3, the core library comes with a very simple command-line program called mathics:

$ mathics

Mathics 5.0.3dev0
on CPython 3.8.12 (heads/v2.3.4.1_release:4a6b4d3504, Jun  3 2022, 15:46:12)
using SymPy 1.10.1, mpmath 1.2.1, numpy 1.23.1, cython 0.29.30

Copyright (C) 2011-2022 The Mathics Team.
This program comes with ABSOLUTELY NO WARRANTY.
This is free software, and you are welcome to redistribute it
under certain conditions.
See the documentation for the full license.

Quit by evaluating Quit[] or by pressing CONTROL-D.

In[1]:=

Type mathics --help for options that can be provided.

For a more featureful frontend, see mathicsscript.

For a Django front-end based web front-end see https://pypi.org/project/Mathics-Django/.

Contributing

Please feel encouraged to contribute to Mathics! Create your own fork, make the desired changes, commit, and make a pull request.

License

Mathics is released under the GNU General Public License Version 3 (GPL3).

mathics-core's People

Contributors

azhao12345 avatar bnjones avatar bth8 avatar davide125 avatar freshwater avatar garkgarcia avatar gitant avatar hengruo avatar hrueter avatar jaycech3n avatar kalsofar avatar kejcao avatar lanyjie avatar larionvn avatar li-xiang-ideal avatar lieblb avatar mego avatar mmatera avatar mrshu avatar poeschko avatar poke1024 avatar proxy-sander avatar rebcabin avatar rocky avatar skirpichev avatar sn6uv avatar suhr avatar teaalltr avatar tiagocavalcante avatar wolfv avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

mathics-core's Issues

Unevaluated

In #58 I tried to fix this issue:

In WMA

In[1]:= F[a, Unevaluated[a]]
Out[1]:=F[a, Unevaluated[a]]

In Mathics

In[1]:= F[a, Unevaluated[a]]
Out[1]:=F[Unevaluated[a], Unevaluated[a]]

This happens because as now Symbols are singletons, the old mechanism of setting a property does not work anymore. In #58, I tried to fix this using a table. However, this does not work in general, if F has the attributes Orderless or Flat, because the order is lost.

Overflow in computation with large integers

This example is from the mathematica docs:
https://reference.wolfram.com/language/tutorial/DiophantineReduce.html

This calculation produces a large integer and then numerical evaluation overflows somehow:

In[1]:= poly = x^100000 + 1234 x^77777 - 2121 x^12345 + 7890 x^999 - x^11
Out[1]:= -x ^ 11 + 7890 x ^ 999 - 2121 x ^ 12345 + 1234 x ^ 77777 + x ^ 100000

In[2]:= freeterm = poly /. x -> 1234567;
Out[2]:= None

In[3]:= N[freeterm]
General::ovfl: Overflow occurred in computation.

Also displaying freeterm is very slow.

By contrast with SymPy (not sure if SymPy is actually involved here):

In [1]: poly = x**100000 + 1234* x**77777 - 2121* x**12345 + 7890* x**999 - x**11

In [2]: freeterm = poly.subs(x, 1234567)

In [3]: N(freeterm)
Out[3]: 2.92690499812734e+609151

Crash when matching blank followed by brackets

Observed behavior

Mathics crashes when matching against a pattern consisting of a blank followed by square brackets

In[1]:= g[i] /. _[i] :> a

Expected behavior as in Mathematica

In[1]:= g[i] /. _[i] :> a
Out[1]= a

Possible Work-around

Prefixing the underscore works as expected: g[i] /. v_[i] :> a

Setup

Linux Mint 20.3
Mathics 4.0.0 on CPython 3.8.10 (default, Nov 26 2021, 20:14:08) using SymPy 1.8, mpmath 1.2.1, numpy 1.17.4

Does Mathics `Unequal[]` equal WL `Unequal[]`?

In going over the docs something I noticed. In Mathics Unequal[] == True

We also write For any expression x and y, Unequal[x, y] == Not[Equal[x, y]] And when there are zero or one parameter, our behavior is not inconsistent.

But is this correct? That is, in the degenerate situations Unequal[x] == Equal[x] ?

Fails to NIntegrate where removable singularities are present

I am trying to NIntegrate the function Sin[x]/x between -1 and 1. It has a removable singularity at x = 0. However, mathics shows General::ovfl: Overflow occurred in computation.
However, the numerical integral works when I try to integrate from -0.5 to 1 (i.e., when the absolute value of the limits are not equal).
I am using the AUR package in Manjaro.

$ mathics

Mathics 4.0.0
on CPython 3.9.7 (default, Aug 31 2021, 13:28:12) 
using SymPy 1.9, mpmath 1.2.1, numpy 1.21.2, cython 0.29.24

Copyright (C) 2011-2021 The Mathics Team.
This program comes with ABSOLUTELY NO WARRANTY.
This is free software, and you are welcome to redistribute it
under certain conditions.
See the documentation for the full license.

Quit by evaluating Quit[] or by pressing CONTROL-D.

In[1]:= NIntegrate[Sin[x]/x,{x,-1,1}]
General::ovfl: Overflow occurred in computation.
Out[1]= Overflow[]

In[2]:= NIntegrate[Sin[x]/x,{x,-0.5,1}]
Out[2]= 1.43919

In[3]:= NIntegrate[Sin[x]/x,{x,-Infinity,Infinity}]
General::ovfl: Overflow occurred in computation.
Out[3]= Overflow[]

Bug in Clear[]?

A mentioned in #193 (comment), we might have a bug in Clear[]

In WMA:

In[1]:={a+b, Unprotect[Plus];Plus=Q;p+q, Clear[Plus]; r+s} 
Out[1]={Q[a, b], Q[p, q], r + s}`

In Mathics, the output is:

Out[1]= {a + b, Q[p, q], r + s}

OrderedQ implementation different from Wolfram Language

Observed behavior

In[1]:= OrderedQ[{2,1}]
Out[1]= OrderedQ[{2,1}]

Expected behavior

In[1]:= OrderedQ[{2,1}]
Out[1]= False

Background

In WL OrderedQ takes a list of elements as input. Instead Mathics implementation of OrderedQ expects two arguments, whose order is checked against each other.

Setup

Linux Mint 20.3
Mathics 4.0.0 on CPython 3.8.10 (default, Nov 26 2021, 20:14:08) using SymPy 1.8, mpmath 1.2.1, numpy 1.17.4

Possible Fix

I rewrote the OrderedQ class to obtain the behavior expected from above. However this still compares only the first two elements in the list, where Mathematica would check all of them.

class OrderedQ(Builtin):

class OrderedQ(Builtin):
    """
    <dl>
    <dt>'OrderedQ[{$a$, $b$}]'
        <dd>is 'True' if $a$ sorts before $b$ according to canonical
        ordering.
    </dl>

    >> OrderedQ[{a, b}]
     = True
    >> OrderedQ[{b, a}]
     = False
    """

    def apply(self, expr, evaluation):
        "OrderedQ[expr_]"

        if expr.leaves[0] <= expr.leaves[1]:
            return SymbolTrue
        else:
            return SymbolFalse

ScriptCommandLine compatibility with WMA

From #67 it becomes apparent that the behavior of ScriptCommandLine in Mathics differs from WMA in the sense that the first element of the list in WMA is the script filename instead of the first paramenter.

Derivative of integrals

D[Integrate[f[u,x],{u,a[x],b[x]},x] or D[NIntegrate[f[u,x],{u,a[x],b[x]},x] are not currently evaluated, while
Integrate[D[f[u,x],x],{u,a[x],b[x]}] produces Indeterminate.

``ClearAll`` fails to clear the attributes in builtin symbols

ClearAll[symb] is supposed to set the default value for the attributes of symb. However, this fails when it is done over a builtin symbol. For example

In[1]:= Unprotect[Plus]; Plus=Q; ClearAll[Plus]; Attributes[Plus]

returns {} instead of {Flat, Listable, NumericFunction, OneIdentity, Orderless, Protected}.
Moreover, for some reason, ClearAll[All] does not completely reset the Definition to its built-in state.

failure of Nintegrate for Debye function

Attached is an example. When run under wolframscript:
wolframscript -file t.wls 210 0.0325 55.85
410.8394779818933
Under mathics:
mathics t.wls 210 0.0325 55.85
Part::partw: Part 2 of {} does not exist.
Part::partw: Part 3 of {} does not exist.
Part::partw: Part 4 of {} does not exist.
Part::partw: Part 2 of {}
...
FindRoot::nnum: The function value is not a number at TD = 500..
ReplaceAll::reps: FindRoot[msA - const phi[t / TD] / (t / TD) / (M TD), {TD, 500.}] is not a valid replacement rule.
TD /. FindRoot[msA - const phi[t / TD] / (t / TD) / (M TD), {TD, 500.}]

Ron Cohen
t.wls.zip

add Diagonal

This returns a list of the diagonal entries in a square matrix.

Expressions with undefined variables are slow

Expressions with undefined variables are 16x slower than the equivalents defined variables.

In[1]:= x=1
Out[1]= 1

In[2]:= Print[Timing[x+1+1.4+2]]; Print[Timing[y+1+1.4+2]]; Print[Timing[1+1.4+2+x]]; Print[Timing[1+1.4+2+y]]
{0.000742186, 5.4}
{0.0123144, 4.4 + y}
{0.000772454, 5.4}
{0.0121675, 4.4 + y}
Out[2]= None

One way to fix it is to have a hash table (python dict) with the numeric variables (in the future we can expand it to have a hash table for each type of value).

If the variable isn't there and we are expecting a numeric value we stop searching for the variable in other hash tables (currently we just have the huge definitions).

To we have an order of magnitude of the performance improvement here is the time with a hardcoded y:

In[1]:= Timing[1+1.4+2+y]
Out[1]= {0.00349792, 4.4 + y}

And by hardcoded I mean:

- items = items.numerify(evaluation).get_sequence()
+ items = [Integer(1), Real(1.4), Integer(2), Symbol("y")]

The hardcoded sum is almost 3.5x (71%) faster.

SameQ for PrecisionReal

When SameQ is applied to two PrecisionReal numbers that differs in a quantity under the precision, WMA returs True, while Mathics returns False. The issue does not affect to Equal. For example, in WMA,

In[1]:= a=N[2/9,3]; b=0.22222`5; {a,b,a==b, a===b}

returns

Out[1]= {0.222,0.22222,True, True}

while in Mathics,

Out[1]:=  {0.222,0.22222,True, False}

This issue comes up when we try to implement low-level tests (see for example #145), and seems to be related to how the comparison operator is implemented in mpf.

A similar issue comes up if we evaluate a-b. In WMA,

In[2]:={a-b, Precision[a-b]}

results in

Out[2]={0.`, 0.}

while in Mathics,

Out[2]={0.0000153, 3.}

A possible fix would be to check the precision in PrecisionReal.sameQ and in the constructors of Real and PrecisionReal..

Reference to non-existing file?

This issue is something I found just by reading the code. In examples/symbolic_logic/gries_schneider/GS1.m, there is a command to "<<GS0.m", which (according to the prose), brings into existence the symbol "expect" for the internal test framework.

I'm not equipped to run the examples now (on my iPad), but I don't see how they could run. I'll upload a copy of GS0.m from my archives later, if it would be helfpul to do.

Cannot Plot with mathics and mathicsscript

Hi,
I'm not able to plot anything with mathics and mathicsscript.
e.g.

In[1]:= Plot[Sin[x], {x, 0, \[Pi]}]
Out[1]:= System`Graphics

Using Mathics-Django, plotting works.
Is this a common issue or did I need some additional dependency?
Thank you in advance.

Improve SphericalBessel? rules for reach faster its fixed point

Certain expressions like SphericalBesselJ are implemented as native WL rules. Depending of how we write these rules, we need several steps before reaching a fixed point in the evaluation. For example,

SphericalBesselJ[n_,x_]

is internally defined as

SphericalBesselJ[n_, z_]->Sqrt[Pi / 2] / Sqrt[z] BesselJ[n + 0.5, z]

but, after evaluation, we get

Sqrt[Pi] Sqrt[2] BesselJ[0.5 + n_, x_] / (2 Sqrt[x_])

The output of TraceEvaluation[SphericalBesselJ[n, z]] is detailed below. However, it is more or less evident that a lot of computation could be saved by defining a more suitable rule. Notice also that such a better rule could depend on the context (for example, if BesselJ is called with numeric arguments, the best rule could be different.

TraceEvaluation[SphericalBesselJ[n,x]]

produces

    Evaluating: System`SphericalBesselJ[Global`n, Global`x]
      Evaluating: System`SphericalBesselJ
      Evaluating: Global`n
      Evaluating: Global`x
    -> System`Times[System`Sqrt[System`Times[System`Pi, System`Power[2, -1]]], System`Power[System`Sqrt[Global`x], -1], System`BesselJ[System`Plus[Global`n, 0.5], Global`x]]
      Evaluating: System`Times
      Evaluating: System`Sqrt[System`Times[System`Pi, System`Power[2, -1]]]
        Evaluating: System`Sqrt
        Evaluating: System`Times[System`Pi, System`Power[2, -1]]
          Evaluating: System`Times
          Evaluating: System`Pi
          Evaluating: System`Power[2, -1]
            Evaluating: System`Power
          -> 1/2
      -> System`Power[System`Times[1/2, System`Pi], System`Times[1, System`Power[2, -1]]]
        Evaluating: System`Power
        Evaluating: System`Times[1/2, System`Pi]
        Evaluating: System`Times[1, System`Power[2, -1]]
          Evaluating: System`Times
          Evaluating: System`Power[2, -1]
            Evaluating: System`Power
          -> 1/2
        -> 1/2
        Evaluating: System`Power[System`Pi, 1/2]
          Evaluating: System`Power
          Evaluating: System`Pi
          Evaluating: System`Pi
        Evaluating: System`Power[2, 1/2]
          Evaluating: System`Power
      -> System`Times[1/2, System`Power[System`Pi, 1/2], System`Power[2, 1/2]]
        Evaluating: System`Times
        Evaluating: System`Power[System`Pi, 1/2]
        Evaluating: System`Power[2, 1/2]
      Evaluating: System`Power[System`Sqrt[Global`x], -1]
        Evaluating: System`Power
        Evaluating: System`Sqrt[Global`x]
          Evaluating: System`Sqrt
          Evaluating: Global`x
        -> System`Power[Global`x, System`Times[1, System`Power[2, -1]]]
          Evaluating: System`Power
          Evaluating: Global`x
          Evaluating: System`Times[1, System`Power[2, -1]]
            Evaluating: System`Times
            Evaluating: System`Power[2, -1]
              Evaluating: System`Power
            -> 1/2
          -> 1/2
          Evaluating: Global`x
        Evaluating: Global`x
      -> System`Power[Global`x, -1/2]
        Evaluating: System`Power
        Evaluating: Global`x
        Evaluating: Global`x
      Evaluating: System`BesselJ[System`Plus[Global`n, 0.5], Global`x]
        Evaluating: System`BesselJ
        Evaluating: System`Plus[Global`n, 0.5]
          Evaluating: System`Plus
          Evaluating: Global`n
          Evaluating: System`N[Global`n, 15]
            Evaluating: System`N
            Evaluating: Global`n
            Evaluating: System`$MinPrecision
            -> 0
            Evaluating: System`N[0]
              Evaluating: System`N
            -> System`N[0, System`MachinePrecision]
              Evaluating: System`N
              Evaluating: System`MachinePrecision
            -> 0.0
            Evaluating: System`$MaxPrecision
            -> System`Infinity
            Evaluating: System`Infinity
            -> System`DirectedInfinity[1]
            Evaluating: System`DirectedInfinity[1]
              Evaluating: System`DirectedInfinity
              Evaluating: System`Unequal[System`N[System`Abs[1]], 1]
                Evaluating: System`Unequal
                Evaluating: System`N[System`Abs[1]]
                  Evaluating: System`N
                  Evaluating: System`Abs[1]
                    Evaluating: System`Abs
                  -> 1
                -> System`N[1, System`MachinePrecision]
                  Evaluating: System`N
                  Evaluating: System`MachinePrecision
                -> 1.0
                Evaluating: System`Function[System`Not[System`ExactNumberQ[System`Slot[1]]]][1.0]
                  Evaluating: System`Function[System`Not[System`ExactNumberQ[System`Slot[1]]]]
                    Evaluating: System`Function
                -> System`Not[System`ExactNumberQ[1.0]]
                  Evaluating: System`Not
                  Evaluating: System`ExactNumberQ[1.0]
                    Evaluating: System`ExactNumberQ
                  -> System`False
                    Evaluating: System`False
                -> System`True
                  Evaluating: System`True
                Evaluating: System`Function[System`Not[System`ExactNumberQ[System`Slot[1]]]][1]
                  Evaluating: System`Function[System`Not[System`ExactNumberQ[System`Slot[1]]]]
                    Evaluating: System`Function
                -> System`Not[System`ExactNumberQ[1]]
                  Evaluating: System`Not
                  Evaluating: System`ExactNumberQ[1]
                    Evaluating: System`ExactNumberQ
                  -> System`True
                    Evaluating: System`True
                -> System`False
                  Evaluating: System`False
                Evaluating: System`Function[System`Not[System`ExactNumberQ[System`Slot[1]]]][1.0]
                  Evaluating: System`Function[System`Not[System`ExactNumberQ[System`Slot[1]]]]
                    Evaluating: System`Function
                -> System`Not[System`ExactNumberQ[1.0]]
                  Evaluating: System`Not
                  Evaluating: System`ExactNumberQ[1.0]
                    Evaluating: System`ExactNumberQ
                  -> System`False
                    Evaluating: System`False
                -> System`True
                  Evaluating: System`True
                Evaluating: System`ExactNumberQ[1.0]
                  Evaluating: System`ExactNumberQ
                -> System`False
                  Evaluating: System`False
                Evaluating: System`ExactNumberQ[1]
                  Evaluating: System`ExactNumberQ
                -> System`True
                  Evaluating: System`True
                Evaluating: System`$MaxExtraPrecision
              -> System`False
                Evaluating: System`False
            Evaluating: System`N[15]
              Evaluating: System`N
            -> System`N[15, System`MachinePrecision]
              Evaluating: System`N
              Evaluating: System`MachinePrecision
            -> 15.0
          -> Global`n
            Evaluating: Global`n
        Evaluating: Global`x
        Evaluating: System`Plus[0.5, Global`n]
          Evaluating: System`Plus
          Evaluating: Global`n
          Evaluating: System`N[Global`n, 15]
            Evaluating: System`N
            Evaluating: Global`n
            Evaluating: System`$MinPrecision
            -> 0
            Evaluating: System`N[0]
              Evaluating: System`N
            -> System`N[0, System`MachinePrecision]
              Evaluating: System`N
              Evaluating: System`MachinePrecision
            -> 0.0
            Evaluating: System`$MaxPrecision
            -> System`Infinity
            Evaluating: System`Infinity
            -> System`DirectedInfinity[1]
            Evaluating: System`DirectedInfinity[1]
              Evaluating: System`DirectedInfinity
              Evaluating: System`Unequal[System`N[System`Abs[1]], 1]
                Evaluating: System`Unequal
                Evaluating: System`N[System`Abs[1]]
                  Evaluating: System`N
                  Evaluating: System`Abs[1]
                    Evaluating: System`Abs
                  -> 1
                -> System`N[1, System`MachinePrecision]
                  Evaluating: System`N
                  Evaluating: System`MachinePrecision
                -> 1.0
                Evaluating: System`Function[System`Not[System`ExactNumberQ[System`Slot[1]]]][1.0]
                  Evaluating: System`Function[System`Not[System`ExactNumberQ[System`Slot[1]]]]
                    Evaluating: System`Function
                -> System`Not[System`ExactNumberQ[1.0]]
                  Evaluating: System`Not
                  Evaluating: System`ExactNumberQ[1.0]
                    Evaluating: System`ExactNumberQ
                  -> System`False
                    Evaluating: System`False
                -> System`True
                  Evaluating: System`True
                Evaluating: System`Function[System`Not[System`ExactNumberQ[System`Slot[1]]]][1]
                  Evaluating: System`Function[System`Not[System`ExactNumberQ[System`Slot[1]]]]
                    Evaluating: System`Function
                -> System`Not[System`ExactNumberQ[1]]
                  Evaluating: System`Not
                  Evaluating: System`ExactNumberQ[1]
                    Evaluating: System`ExactNumberQ
                  -> System`True
                    Evaluating: System`True
                -> System`False
                  Evaluating: System`False
                Evaluating: System`Function[System`Not[System`ExactNumberQ[System`Slot[1]]]][1.0]
                  Evaluating: System`Function[System`Not[System`ExactNumberQ[System`Slot[1]]]]
                    Evaluating: System`Function
                -> System`Not[System`ExactNumberQ[1.0]]
                  Evaluating: System`Not
                  Evaluating: System`ExactNumberQ[1.0]
                    Evaluating: System`ExactNumberQ
                  -> System`False
                    Evaluating: System`False
                -> System`True
                  Evaluating: System`True
                Evaluating: System`ExactNumberQ[1.0]
                  Evaluating: System`ExactNumberQ
                -> System`False
                  Evaluating: System`False
                Evaluating: System`ExactNumberQ[1]
                  Evaluating: System`ExactNumberQ
                -> System`True
                  Evaluating: System`True
                Evaluating: System`$MaxExtraPrecision
              -> System`False
                Evaluating: System`False
            Evaluating: System`N[15]
              Evaluating: System`N
            -> System`N[15, System`MachinePrecision]
              Evaluating: System`N
              Evaluating: System`MachinePrecision
            -> 15.0
          -> Global`n
            Evaluating: Global`n
        Evaluating: Global`x
Sqrt[Pi] Sqrt[2] BesselJ[0.5 + n, x] / (2 Sqrt[x])

On aarch64 architecture, test_timeconstrained1from test_datentime.py fails

When building mathics-core for openSUSE Tumbleweed, on the aarch64 architecture, the following test from version 4.0.0 fails (however, everything passes on x86_64 and i586). Any help resolving this would be appreciated.

[ 1876s] ____________________________ test_timeconstrained1 _____________________________
[ 1876s] 
[ 1876s]     def test_timeconstrained1():
[ 1876s]         #
[ 1876s]         str_expr1 = "a=1.; TimeConstrained[Do[Pause[.1];a=a+1,{1000}],1]"
[ 1876s]         result = evaluate(str_expr1)
[ 1876s]         str_expected = "$Aborted"
[ 1876s]         expected = evaluate(str_expected)
[ 1876s]         assert result == expected
[ 1876s]         time.sleep(1)
[ 1876s] >       assert evaluate("a").to_python() == 10
[ 1876s] E       assert 9.0 == 10
[ 1876s] E         +9.0
[ 1876s] E         -10
[ 1876s] 
[ 1876s] test_datentime.py:28: AssertionError

Thanks for your app.

Normal does not work

Normal[Series[f[x],{x,0,1}]]

gives

Normal[f[0] + f'[0] x + O[x] ^ 2]

instead of

f[0] + f'[0] x

Mathics crashes while applaying substitution rule

Observed behavior

Mathics crashes from this input

In[1]:= a == d b + d c /. a_ x_ + a_ y_ -> a (x + y)

Expected behavior as in Mathematica

In[1]:= a == d b + d c /. a_ x_ + a_ y_ -> a (x + y)
Out[1]= a == (b + c) d

Temporary Work-around

I can use a == d b + d c // Simplify, but I want more control over the substitution rules.

Setup

Linux Mint 20.3
Mathics 4.0.0 on CPython 3.8.10 (default, Nov 26 2021, 20:14:08) using SymPy 1.8, mpmath 1.2.1, numpy 1.17.4

``N[F[Pi],prec,Method->method]`` does evaluates to ``F[N[Pi,prec,Method->method]]``

The use of the Method option for numeric evaluation breaks the behavior or N, that should propagate to its leaves.
For example, N[F[Pi],10] does evaluates to F[N[Pi,10]] produces the (TraceEvaluation):

    Evaluating: System`N[Global`F[System`Pi], 10]
      Evaluating: System`N
      Evaluating: Global`F[System`Pi]
        Evaluating: Global`F
        Evaluating: System`Pi
           [...]
      Evaluating: System`N[10]
         [...]
      -> 10.0
      Evaluating: System`N[Global`F, 10]
        [...]
      -> Global`F
      Evaluating: System`N[System`Pi, 10]
        [...]
      -> 3.141592654
    -> Global`F[3.141592654]
      Evaluating: Global`F
F[3.141592654]

But, N[F[Pi],10, Method->"numpy"] does evaluates to F[N[Pi,10]] produces (TraceEvaluation):

Evaluating: System`N[Global`F[System`Pi], 10, System`Rule[System`Method, "numpy"]]
  Evaluating: System`N
  Evaluating: Global`F[System`Pi]
    Evaluating: Global`F
    Evaluating: System`Pi
  Evaluating: System`Rule[System`Method, "numpy"]
    Evaluating: System`Rule
    Evaluating: System`Method

N[F[Pi], 10, Method -> numpy]



Assignment of N makes Mathics crash

Assignments such as N = 1 make Mathics crash because lhs has no attribute leaves (file mathics/builtin/assignments/internals.py, line 399)

I don't know if it be better to add an hasattr, as below, or a try-catch.
Obviously it could be useful call the rejected_because_protected function.

def process_assign_n(self, lhs, rhs, evaluation, tags, upset):    
    lhs, condition = unroll_conditions(lhs)    
    lhs, rhs = unroll_patterns(lhs, rhs, evaluation)    
    defs = evaluation.definitions    
                              
    if hasattr(lhs, "leaves"):                 # <--- here
        if len(lhs.leaves) not in (1, 2):    
            evaluation.message_args("N", len(lhs.leaves), 1, 2)    
            raise AssignmentException(lhs, None)    
        if len(lhs.leaves) == 1:    
            nprec = SymbolMachinePrecision    
        else:                 
            nprec = lhs.leaves[1]        
        focus = lhs.leaves[0]    
        lhs = Expression(SymbolN, focus, nprec)    
        tags = process_tags_and_upset_dont_allow_custom(    
            tags, upset, self, lhs, focus, evaluation    
        )                     
        count = 0             
        lhs, rhs = process_rhs_conditions(lhs, rhs, condition, evaluation)      
        rule = Rule(lhs, rhs)    
        for tag in tags:      
            if rejected_because_protected(self, lhs, tag, evaluation):    
                continue      
            count += 1        
            defs.add_nvalue(tag, rule)    
        return count > 0 

Session without builtins not working

Some things you try to evaluate in a session without builtins aren't working.

e.g.:

>>> from mathics.session import MathicsSession
>>> session = MathicsSession(add_builtin=False)
>>> session.evaluate("x")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/src/app/mathics-core/mathics/session.py", line 65, in evaluate
    expr = parse(self.definitions, MathicsSingleLineFeeder(str_expression))
  File "/usr/src/app/mathics-core/mathics/core/parser/util.py", line 21, in parse
    return parse_returning_code(definitions, feeder)[0]
  File "/usr/src/app/mathics-core/mathics/core/parser/util.py", line 34, in parse_returning_code
    return convert(ast, definitions), source_code
  File "/usr/src/app/mathics-core/mathics/core/parser/convert.py", line 165, in convert
    result = self.do_convert(node)
  File "/usr/src/app/mathics-core/mathics/core/parser/convert.py", line 171, in do_convert
    return getattr(self, "_make_" + result[0])(*result[1:])
  File "/usr/src/app/mathics-core/mathics/core/parser/convert.py", line 177, in _make_Lookup
    value = self.definitions.lookup_name(s)
  File "/usr/src/app/mathics-core/mathics/core/definitions.py", line 383, in lookup_name
    current_context = self.get_current_context()
  File "/usr/src/app/mathics-core/mathics/core/definitions.py", line 256, in get_current_context
    context = context_rule.replace.get_string_value()
AttributeError: 'NoneType' object has no attribute 'replace'

MessageName Symbol::usage not working

Symbol::usage returns nothing, while ?Symbol works correctly.

Example:
In[1]:= ?Diagonal
Return a list with the diagonal elements of a given matrix
Out[1]:= Null

In[2]:= Diagonal::usage
Out[2]:= Diagonal::usage

Unwanted spaces

When I run mathics and say 2x+3 I get these lines:

In[1]:= 2x+3
Out[1]= 3 + 2 x

if I go to def format_outputform in mathics/builtin/arithfns/basic.py and change op to be Dot Operator I get these lines:

In[1]:= 2x+3
Out[1]= 3 + 2 ⋅ x

I expected to get 3 + 2⋅x but after result = self.create_expression(SymbolMakeBoxes, expr, form).evaluate(evaluation) (that was line 308 in mathics/core/element.py) that result contains ["2", " ⋅ ", "x"]] with unwanted spaces around dot operator. If only I could somehow prevent that and get ["2", "⋅", "x"]] in result (spaces around Plus Sign " + " in result are totally fine)

False condition in Simplify crashes

It seems that Mathics completely bombs out for this input:

In[1]:= Simplify[Sin[Pi*x], False]
Traceback (most recent call last):
...
  File "/home/oscar/current/sympy/mathics-core/mathics/builtin/inference.py", line 274, in get_assumption_rules_dispatch
    evaluation.message("Inconsistent assumptions")
TypeError: message() missing 1 required positional argument: 'tag'

I'm not using up to date master as I don't have a proper dev environment set up but that's this line:

if val_consistent_assumptions is SymbolFalse:
evaluation.message("Inconsistent assumptions")

Looks like a missing tag argument as indicated by the error message.

Review and document walk_levels and walk_parts

Looking at the problem about "singletonize" symbols, I hit these two functions that are not documented, and seems to be important in things relating to handling list and in general, nested expressions. In particular, walk_levels uses Expression.position objects which are also not documented and seem to be related to the caching expression mechanism.

Mathics crashes during Factor

Observed behavior

Mathics crashes from this input

In[1]:= a == d b + d c // Factor

Expected behavior as in Mathematica

In[1]:= a == d b + d c // Factor
Out[1]= a == (b + c) d

Setup

Linux Mint 20.3
Mathics 4.1.0.dev0 on CPython 3.8.10 (default, Nov 26 2021, 20:14:08) using SymPy 1.8, mpmath 1.2.1, numpy 1.17.4

Failed inversion of matrix with expression elements

Observed behavior

Mathics crashes after evaluating the following input for a few minutes

In[1]:= Inverse[{{g[0, 0], g[0, 1]}, {g[0, 1], g[1, 1]}}]

Expected behavior

In[1]:= Inverse[{{g[0, 0], g[0, 1]}, {g[0, 1], g[1, 1]}}]
Out[1]= {{g[1, 1] / (g[0, 0] g[1, 1] - g[0, 1] ^ 2), -g[0, 1] / (g[0, 0] g[1, 1] - g[0, 1] ^ 2)}, {-g[0, 1] / (g[0, 0] g[1, 1] - g[0, 1] ^ 2), g[0, 0] / (g[0, 0] g[1, 1] - g[0, 1] ^ 2)}}

Background

The program fails within SymPy, which seems to have problems dealing with SympyExpression elements. So I don't know if this is a bug in SymPy or if Mathics must provide a different input to the SymPy API.

The following cases work as expected.
Triangular matrix:
In[1]:= Inverse[{{g[0,0], g[0,1]}, {0, g[1,1]}}]
Inverting a matrix of symbols:
In[1]:= Inverse[{{g00, g01}, {g01, g11}}]

Setup

Linux Mint 20.3
Mathics 4.0.0 on CPython 3.8.10 (default, Nov 26 2021, 20:14:08) using SymPy 1.8, mpmath 1.2.1, numpy 1.17.4

Traceback

Traceback (most recent call last):
  File "/usr/local/bin/mathics", line 8, in <module>
    sys.exit(main())
  File "/usr/local/lib/python3.8/dist-packages/mathics/main.py", line 402, in main
    result = evaluation.evaluate(query, timeout=settings.TIMEOUT)
  File "/usr/local/lib/python3.8/dist-packages/mathics/core/evaluation.py", line 361, in evaluate
    result = run_with_timeout_and_stack(evaluate, timeout, self)
  File "/usr/local/lib/python3.8/dist-packages/mathics/core/evaluation.py", line 118, in run_with_timeout_and_stack
    return request()
  File "/usr/local/lib/python3.8/dist-packages/mathics/core/evaluation.py", line 332, in evaluate
    self.last_eval = query.evaluate(self)
  File "/usr/local/lib/python3.8/dist-packages/mathics/core/expression.py", line 1315, in evaluate
    expr, reevaluate = expr.evaluate_next(evaluation)
  File "/usr/local/lib/python3.8/dist-packages/mathics/core/expression.py", line 1449, in evaluate_next
    result = rule.apply(new, evaluation, fully=False)
  File "/usr/local/lib/python3.8/dist-packages/mathics/core/rules.py", line 67, in apply
    self.pattern.match(yield_match, expression, {}, evaluation, fully=fully)
  File "/usr/local/lib/python3.8/dist-packages/mathics/core/pattern.py", line 291, in match
    self.head.match(yield_head, expression.get_head(), vars, evaluation)
  File "/usr/local/lib/python3.8/dist-packages/mathics/core/pattern.py", line 159, in match
    yield_func(vars, None)
  File "/usr/local/lib/python3.8/dist-packages/mathics/core/pattern.py", line 281, in yield_head
    self.get_pre_choices(
  File "/usr/local/lib/python3.8/dist-packages/mathics/core/pattern.py", line 429, in get_pre_choices
    yield_func(vars)
  File "/usr/local/lib/python3.8/dist-packages/mathics/core/pattern.py", line 258, in yield_choice
    self.match_leaf(
  File "/usr/local/lib/python3.8/dist-packages/mathics/core/pattern.py", line 655, in match_leaf
    self.get_wrappings(
  File "/usr/local/lib/python3.8/dist-packages/mathics/core/pattern.py", line 456, in get_wrappings
    yield_func(items[0])
  File "/usr/local/lib/python3.8/dist-packages/mathics/core/pattern.py", line 643, in yield_wrapping
    leaf.match(
  File "/usr/local/lib/python3.8/dist-packages/mathics/builtin/patterns.py", line 852, in match
    self.pattern.match(yield_func, expression, new_vars, evaluation)
  File "/usr/local/lib/python3.8/dist-packages/mathics/builtin/patterns.py", line 1050, in match
    yield_func(vars, None)
  File "/usr/local/lib/python3.8/dist-packages/mathics/core/pattern.py", line 640, in match_yield
    yield_func(new_vars, items_rest)
  File "/usr/local/lib/python3.8/dist-packages/mathics/core/rules.py", line 42, in yield_match
    new_expression = self.do_replace(expression, vars, options, evaluation)
  File "/usr/local/lib/python3.8/dist-packages/mathics/core/rules.py", line 131, in do_replace
    return self.function(evaluation=evaluation, **vars_noctx)
  File "/usr/local/lib/python3.8/dist-packages/mathics/builtin/numbers/linalg.py", line 209, in apply
    inv = matrix.inv()
  File "/usr/local/lib/python3.8/dist-packages/sympy/matrices/matrices.py", line 2199, in inv
    return _inv(self, method=method, iszerofunc=iszerofunc,
  File "/usr/local/lib/python3.8/dist-packages/sympy/matrices/inverse.py", line 459, in _inv
    rv = M.inverse_GE(iszerofunc=iszerofunc)
  File "/usr/local/lib/python3.8/dist-packages/sympy/matrices/matrices.py", line 2184, in inverse_GE
    return _inv_GE(self, iszerofunc=iszerofunc)
  File "/usr/local/lib/python3.8/dist-packages/sympy/matrices/inverse.py", line 242, in _inv_GE
    red = big.rref(iszerofunc=iszerofunc, simplify=True)[0]
  File "/usr/local/lib/python3.8/dist-packages/sympy/matrices/matrices.py", line 170, in rref
    return _rref(self, iszerofunc=iszerofunc, simplify=simplify,
  File "/usr/local/lib/python3.8/dist-packages/sympy/matrices/reductions.py", line 305, in _rref
    mat, pivot_cols, _ = _row_reduce(M, iszerofunc, simpfunc,
  File "/usr/local/lib/python3.8/dist-packages/sympy/matrices/reductions.py", line 127, in _row_reduce
    mat, pivot_cols, swaps = _row_reduce_list(list(M), M.rows, M.cols, M.one,
  File "/usr/local/lib/python3.8/dist-packages/sympy/matrices/reductions.py", line 68, in _row_reduce_list
    assumed_nonzero, newly_determined = _find_reasonable_pivot(
  File "/usr/local/lib/python3.8/dist-packages/sympy/matrices/determinant.py", line 104, in _find_reasonable_pivot
    if x.equals(S.Zero):
  File "/usr/local/lib/python3.8/dist-packages/sympy/core/expr.py", line 751, in equals
    constant = diff.is_constant(simplify=False, failing_number=True)
  File "/usr/local/lib/python3.8/dist-packages/sympy/core/expr.py", line 674, in is_constant
    if b is not None and b is not S.NaN and b.equals(a) is False:
  File "/usr/local/lib/python3.8/dist-packages/sympy/core/expr.py", line 751, in equals
    constant = diff.is_constant(simplify=False, failing_number=True)
  File "/usr/local/lib/python3.8/dist-packages/sympy/core/expr.py", line 674, in is_constant
    if b is not None and b is not S.NaN and b.equals(a) is False:
  File "/usr/local/lib/python3.8/dist-packages/sympy/core/expr.py", line 751, in equals
    constant = diff.is_constant(simplify=False, failing_number=True)
  File "/usr/local/lib/python3.8/dist-packages/sympy/core/expr.py", line 674, in is_constant
    if b is not None and b is not S.NaN and b.equals(a) is False:
  File "/usr/local/lib/python3.8/dist-packages/sympy/core/expr.py", line 751, in equals
    constant = diff.is_constant(simplify=False, failing_number=True)
  File "/usr/local/lib/python3.8/dist-packages/sympy/core/expr.py", line 674, in is_constant
    if b is not None and b is not S.NaN and b.equals(a) is False:
  File "/usr/local/lib/python3.8/dist-packages/sympy/core/expr.py", line 751, in equals
    constant = diff.is_constant(simplify=False, failing_number=True)
  File "/usr/local/lib/python3.8/dist-packages/sympy/core/expr.py", line 674, in is_constant
    if b is not None and b is not S.NaN and b.equals(a) is False:
  File "/usr/local/lib/python3.8/dist-packages/sympy/core/expr.py", line 751, in equals
    constant = diff.is_constant(simplify=False, failing_number=True)
  File "/usr/local/lib/python3.8/dist-packages/sympy/core/expr.py", line 674, in is_constant
    if b is not None and b is not S.NaN and b.equals(a) is False:
  File "/usr/local/lib/python3.8/dist-packages/sympy/core/expr.py", line 751, in equals
    constant = diff.is_constant(simplify=False, failing_number=True)
  File "/usr/local/lib/python3.8/dist-packages/sympy/core/expr.py", line 674, in is_constant
    if b is not None and b is not S.NaN and b.equals(a) is False:
  File "/usr/local/lib/python3.8/dist-packages/sympy/core/expr.py", line 751, in equals
    constant = diff.is_constant(simplify=False, failing_number=True)
  File "/usr/local/lib/python3.8/dist-packages/sympy/core/expr.py", line 674, in is_constant
    if b is not None and b is not S.NaN and b.equals(a) is False:
  File "/usr/local/lib/python3.8/dist-packages/sympy/core/expr.py", line 741, in equals
    diff = factor_terms(simplify(self - other), radical=True)
  File "/usr/local/lib/python3.8/dist-packages/sympy/simplify/simplify.py", line 722, in simplify
    short = shorter(powsimp(expr, combine='exp', deep=True), powsimp(expr), expr)
  File "/usr/local/lib/python3.8/dist-packages/sympy/simplify/powsimp.py", line 116, in powsimp
    expr = expr.func(*[recurse(w) for w in expr.args])
  File "/usr/local/lib/python3.8/dist-packages/sympy/simplify/powsimp.py", line 116, in <listcomp>
    expr = expr.func(*[recurse(w) for w in expr.args])
  File "/usr/local/lib/python3.8/dist-packages/sympy/simplify/powsimp.py", line 107, in recurse
    return powsimp(arg, _deep, _combine, _force, _measure)
  File "/usr/local/lib/python3.8/dist-packages/sympy/simplify/powsimp.py", line 116, in powsimp
    expr = expr.func(*[recurse(w) for w in expr.args])
  File "/usr/local/lib/python3.8/dist-packages/sympy/simplify/powsimp.py", line 116, in <listcomp>
    expr = expr.func(*[recurse(w) for w in expr.args])
  File "/usr/local/lib/python3.8/dist-packages/sympy/simplify/powsimp.py", line 107, in recurse
    return powsimp(arg, _deep, _combine, _force, _measure)
  File "/usr/local/lib/python3.8/dist-packages/sympy/simplify/powsimp.py", line 116, in powsimp
    expr = expr.func(*[recurse(w) for w in expr.args])
  File "/usr/local/lib/python3.8/dist-packages/mathics/core/convert.py", line 65, in __new__
    return SympyExpression(self.expr)
AttributeError: 'SympyExpression' object has no attribute 'expr'

Handling Overflow in subexpressions

In WMA, overflow in an element of an expression does not abort the evaluation:

In[1]:= {q, Gamma[10*^20]}

General::ovfl: Overflow occurred in computation.

Out[1]= {q, Overflow[]} 

In Mathics, on the other hand, the raised exception is caught at the top level in the evaluation

In[1]:= {q, Gamma[10*^20]}

General::ovfl: Overflow occurred in computation.

Out[1]= Overflow[]

Sparse Identity Matrix

The following one line code mimics the sparse identity matrix generation in mathematica -

SparseArray[Table[{i,i}->1, {i,1,N}]]

But I am not sure about the best way to implement this in mathics with the following function call -

id = IdentityMatrix[N, SparseArray]

I would be happy to implement this if I get some hint.

First with empty list crashes mathics

Demo:

In[4]:= First[{}]
Traceback (most recent call last):
...
  File "/home/oscar/current/sympy/mathics-core/mathics/builtin/list/eol.py", line 434, in apply
    return expr.leaves[0]
IndexError: tuple index out of range

I guess there should be a handler for the case where the list is empty.

Is it possible to halt and restart the mathics kernel from the web-ui?

Hello! I was kicking the tires on the mathics web-ui the other day when I unwisely set a very large computation into motion. I couldn't figure out how to halt the kernel without killing the webserver. Is there a way to halt the kernel from the web-ui?

If there is a better place to ask this question, then please let me know.

batch use of mathics

mathematica has the instruction

AppendTo[$Echo,"stdout"]

which allows to run programs in batch mode i.e.

math< inputfile > outputfile

This does not work with mathics. Is there any way to obtain the same result
i.e. of seeing the input lines in the outputfile? It would be very useful.

Expression evaluating to False

Observed behavior

In[1]:= g[2] == g[3]
Out[1]= False

Expected behavior

In[1]:= g[2] == g[3]
Out[1]= g[2] == g[3]

Background

In WL expression equations evaluating to False return the expression itself. Only the identity operator === should return False for expression equations. (For numerical evaluations also == can return False.)

Setup

Linux Mint 20.3
Mathics 4.0.0 on CPython 3.8.10 (default, Nov 26 2021, 20:14:08) using SymPy 1.8, mpmath 1.2.1, numpy 1.17.4

Possible Fix

Fix expr_equal in

returning None instead of tst fixes the behavior above.

Crash during FullSimplify

Observed behavior

Mathics crashes from the following input

In[1]:= a[x] + e f / (2 d) + c[x] // FullSimplify

Expected behavior

In[1]:= a[x] + e f / (2 d) + c[x] // FullSimplify
Out[1]= e f / (2 d) + a[x] + c[x]

Background

I tried to find a more minimal example, but reducing the input further eliminates the failure.

Curiously the following order of input works

In[1]:= a[x] + e f / (d) + c[x] // FullSimplify
Out[1]= e f / d + a[x] + c[x]

In[2]:= a[x] + e f / (2 d) + c[x] // FullSimplify
Out[2]= e f / (2 d) + a[x] + c[x]

Setup

Linux Mint 20.3
Mathics 4.0.0 on CPython 3.8.10 (default, Nov 26 2021, 20:14:08) using SymPy 1.8, mpmath 1.2.1, numpy 1.17.4

Traceback

Traceback (most recent call last):
  File "/usr/local/bin/mathics", line 8, in <module>
    sys.exit(main())
  File "/usr/local/lib/python3.8/dist-packages/mathics/main.py", line 402, in main
    result = evaluation.evaluate(query, timeout=settings.TIMEOUT)
  File "/usr/local/lib/python3.8/dist-packages/mathics/core/evaluation.py", line 361, in evaluate
    result = run_with_timeout_and_stack(evaluate, timeout, self)
  File "/usr/local/lib/python3.8/dist-packages/mathics/core/evaluation.py", line 118, in run_with_timeout_and_stack
    return request()
  File "/usr/local/lib/python3.8/dist-packages/mathics/core/evaluation.py", line 332, in evaluate
    self.last_eval = query.evaluate(self)
  File "/usr/local/lib/python3.8/dist-packages/mathics/core/expression.py", line 1315, in evaluate
    expr, reevaluate = expr.evaluate_next(evaluation)
  File "/usr/local/lib/python3.8/dist-packages/mathics/core/expression.py", line 1449, in evaluate_next
    result = rule.apply(new, evaluation, fully=False)
  File "/usr/local/lib/python3.8/dist-packages/mathics/core/rules.py", line 67, in apply
    self.pattern.match(yield_match, expression, {}, evaluation, fully=fully)
  File "/usr/local/lib/python3.8/dist-packages/mathics/core/pattern.py", line 291, in match
    self.head.match(yield_head, expression.get_head(), vars, evaluation)
  File "/usr/local/lib/python3.8/dist-packages/mathics/core/pattern.py", line 159, in match
    yield_func(vars, None)
  File "/usr/local/lib/python3.8/dist-packages/mathics/core/pattern.py", line 281, in yield_head
    self.get_pre_choices(
  File "/usr/local/lib/python3.8/dist-packages/mathics/core/pattern.py", line 429, in get_pre_choices
    yield_func(vars)
  File "/usr/local/lib/python3.8/dist-packages/mathics/core/pattern.py", line 258, in yield_choice
    self.match_leaf(
  File "/usr/local/lib/python3.8/dist-packages/mathics/core/pattern.py", line 655, in match_leaf
    self.get_wrappings(
  File "/usr/local/lib/python3.8/dist-packages/mathics/core/pattern.py", line 456, in get_wrappings
    yield_func(items[0])
  File "/usr/local/lib/python3.8/dist-packages/mathics/core/pattern.py", line 643, in yield_wrapping
    leaf.match(
  File "/usr/local/lib/python3.8/dist-packages/mathics/builtin/patterns.py", line 852, in match
    self.pattern.match(yield_func, expression, new_vars, evaluation)
  File "/usr/local/lib/python3.8/dist-packages/mathics/builtin/patterns.py", line 1050, in match
    yield_func(vars, None)
  File "/usr/local/lib/python3.8/dist-packages/mathics/core/pattern.py", line 640, in match_yield
    yield_func(new_vars, items_rest)
  File "/usr/local/lib/python3.8/dist-packages/mathics/core/rules.py", line 42, in yield_match
    new_expression = self.do_replace(expression, vars, options, evaluation)
  File "/usr/local/lib/python3.8/dist-packages/mathics/core/rules.py", line 131, in do_replace
    return self.function(evaluation=evaluation, **vars_noctx)
  File "/usr/local/lib/python3.8/dist-packages/mathics/builtin/numbers/algebra.py", line 424, in apply
    sympy_result = sympy.simplify(sympy_expr)
  File "/usr/local/lib/python3.8/dist-packages/sympy/simplify/simplify.py", line 757, in simplify
    return done(expr)
  File "/usr/local/lib/python3.8/dist-packages/sympy/simplify/simplify.py", line 576, in done
    rv = e.doit() if doit else e
  File "/usr/local/lib/python3.8/dist-packages/sympy/core/operations.py", line 432, in doit
    terms = [term.doit(**hints) for term in self.args]
  File "/usr/local/lib/python3.8/dist-packages/sympy/core/operations.py", line 432, in <listcomp>
    terms = [term.doit(**hints) for term in self.args]
  File "/usr/local/lib/python3.8/dist-packages/sympy/core/basic.py", line 1668, in doit
    return self.func(*terms)
  File "/usr/local/lib/python3.8/dist-packages/mathics/core/convert.py", line 65, in __new__
    return SympyExpression(self.expr)
AttributeError: 'SympyExpression' object has no attribute 'expr'

Support Polyhedra in Asymptote

Currently in mathicsscript (or dmathicsscript):

In[1]:= Graphics3D[Octahedron[{{0,0,0}, {1,1,1}}, 2]]
Traceback (most recent call last):
...

 File "/tmp/Mathics3/mathics-core/mathics/format/asy.py", line 349, in graphics_elements
    format_fn = lookup_method(element, "asy")
  File "/tmp/Mathics3/mathics-core/mathics/core/formatter.py", line 87, in lookup_method
    f"Can't find formatter {format_fn.__name__} for {type(self).__name__}"
AttributeError: 'NoneType' object has no attribute '__name__'

We probably could and should put a try/except in asy.py around line 349.

However better would be to support Polyhedra like Octahedron in asymptote.

To this end, I see https://github.com/pivaldi/asymptote-packages

@pivaldi Are there any limitations to using inside of this project Mathics ?

If not, any suggestions for how to incorporate here or in the docker image.

More generally, we could really use someone who knows Asymptote better to improve our asymptote code generation which you can examples rendered see here while or in the full PDF.

Expression Refactor Todo list

  • Turn some BaseElement into @attribute get_attributes Same thing for get_elements, get_head, etc?
  • Move is_inexect out of BaseElement
  • Move get_float_value() out of BaseElement
  • Move do_format and format is out of BaseElement

Polynomial root fails to evaluate under N

Here it seems that N can compute the complex roots but not the real one:

In[40]:= Solve[x^5 + 2*x + 1 == 0, x]
Out[40]:= {{x -> Root[#1 ^ 5 + 2 #1 + 1&, 1]}, {x -> Root[#1 ^ 5 + 2 #1 + 1&, 2]}, {x -> Root[#1 ^ 5 + 2 #1 + 1&, 3]}, {x -> Root[#1 ^ 5 + 2 #1 + 1&, 4]}, {x -> Root[#1 ^ 5 + 2 #1 + 1&, 5]}}

In[41]:= N[%]
Out[41]:= {{x -> -0.701874 - 0.879697 I}, {x -> -0.701874 + 0.879697 I}, {x -> 0.945068 - 0.854518 I}, {x -> 0.945068 + 0.854518 I}, {x -> Root[#1 ^ 5 + 2 #1 + 1&, 5]}}

In[44]:= N[Root[#1 ^ 5 + 2 #1 + 1&, 5]]
Out[44]:= Root[#1 ^ 5 + 2 #1 + 1&, 5]

I'm not sure why since SymPy can compute this:

In [1]: solve(x**5 + 2*x + 1, x)
Out[1]: 
⎡       ⎛ 5             ⎞         ⎛ 5             ⎞         ⎛ 5             ⎞         ⎛ 5CRootOfx  + 2x + 1, 0⎠, CRootOfx  + 2x + 1, 1⎠, CRootOfx  + 2x + 1, 2⎠, CRootOfx  + 2x + 1

   ⎞         ⎛ 5             ⎞⎤
, 3⎠, CRootOfx  + 2x + 1, 4⎠⎦

In [2]: [r.n() for r in _]
Out[2]: 
[-0.486389035934543, -0.701873568855862 - 0.879697197929824, -0.701873568855862 + 0.8796971979298
24, 0.945068086823133 - 0.854517514439046, 0.945068086823133 + 0.854517514439046]

In [3]: RootOf(x**5 + 2*x + 1, 0).n()
Out[3]: -0.486389035934543

Oh, actually maybe this is what's going on:

In[45]:= N[Root[#1 ^ 5 + 2 #1 + 1&, 0]]
Root::iidx: Argument 0 at position 2 is out of bounds
Out[45]:= -0.486389

SymPy numbers the roots 0 through 4 where I guess Mathematica numbers them 1 though 5. Somewhere there needs to be a -1.

Remove duplication of precedence in `mathics/core/parser/operators.py`

Mathics scannner is now getting close to complete in recording operator precedence. If information is lacking, it should be added to mathics-scanner. For example, we may need to add information about prefix-ops, postfix ops, left binary ops, etc.

This should be used instead of mathics/core/parser/operators.py and that removed or reduced.

Note that one gentle way to do this is to first start out with mathics-scanner, and then merge in information that is currently in this file. And this is also a way to tell whether things are fully done: if the set difference of what is in operators.py minus the scanner tables is not empty, we need to add more.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.