Mathics3 / mathics-core

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.
https://mathics.org
Other
780 stars 45 forks source link

`MatchQ[1 + 2 x, (a_. + b_. x_Symbol)]` incorrectly failing #1172

Open rocky opened 3 hours ago

rocky commented 3 hours ago

Description

MatchQ[1 + 2 x, (a_. + b_. x_Symbol)] returns False when it should return True.

How to Reproduce

$ mathics
In[1]:= MatchQ[1 + 2 x, (a_. + b_. x_Symbol)]
Out[1]= False (* Wrong *)

In[2]:= MatchQ[0 + 2 x, (a_. + b_. x_Symbol)]
Out[2]= True (* Correct *)

In[2]:= MatchQ[1 + x, (a_. + x_Symbol)]
Out[2]= True (* Also Correct *)

Additional context

This comes from trying to get Rubi working. The function in that, which is failing is called Default[]

aravindh-krishnamoorthy commented 3 hours ago

The issue (for now) is mainly with matching patterns that have a dot like a_. + b_. x_Symbol above. Here, the dot means that the pattern matches not just an expression of type a + b x but also 1 + x, b x, x, and so on. The function Default[] is a Wolfram Language function, which informs the pattern matcher on what the "default" values for a and b are, when omitted. So, x is internally matched to a_. + b_. x_Symbol as Plus[Default[Plus, 1], Times[Default[Times, 1], x] where Default[Plus, 1] = 0 is the default argument (additive identity) for Plus, and similarly 1 for Times.

I started very recently with Mathics, so there may be errors in the analysis below.

From what I gather, the problem seems to be that when matching 1 + 2 x to a_. + b_. x_Symbol, in line 465, https://github.com/Mathics3/mathics-core/blob/bf6a8c0153170b1350f7ed00792eaa4ac801813a/mathics/core/pattern.py#L462-L467 the exception StopGenerator_ExpressionPattern_match is raised WITHOUT a full match.

The exception is raised because the condition candidates < match_count[0] is met: https://github.com/Mathics3/mathics-core/blob/bf6a8c0153170b1350f7ed00792eaa4ac801813a/mathics/core/pattern.py#L830-L831

However, inspecting the pattern at this point reveals that:

(Pdb) unmatched_elements
(<Integer: 1>, <Expression: <Symbol: System`Times>[<Integer: 2>, <Symbol: Global`x>]>)
(Pdb) element
<ExpressionPattern: System`Times[System`Optional[System`Pattern[Global`b, System`Blank[]]], System`Pattern[Global`x, System`Blank[System`Symbol]]]>

I'd expect a match here between the second tuple element and the expression pattern.

However, for 0 + 2 x, unlike for 1 + 2 x, basic_match_expression(self, expression, parms) does not match, but instead, the match is performed in https://github.com/Mathics3/mathics-core/blob/bf6a8c0153170b1350f7ed00792eaa4ac801813a/mathics/core/pattern.py#L468-L469. So, that seems to be a different case.

I'll try to debug a bit more tomorrow.