Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enclosing parentheses should be equivalent to <mfenced></mfenced> tags #3208

Open
xrjunque opened this issue Mar 26, 2024 · 10 comments
Open
Labels
Expected Behavior This is how MathJax works

Comments

@xrjunque
Copy link

xrjunque commented Mar 26, 2024

To whom it may concern:

Latex code

\begin{equation} {(\tfrac{1}{2})^n} \end{equation}

translated by MathJax into MathML gives the following MathML code which is XML valid code, but should not as MathML code:

<math xmlns="http://www.w3.org/1998/Math/MathML" display="block">
  <mstyle displaystyle="true" scriptlevel="0">
    <mrow class="MJX-TeXAtom-ORD">
      <mrow class="MJX-TeXAtom-ORD">
        <mo stretchy="false">(</mo>
        <mstyle displaystyle="false" scriptlevel="0">
          <mfrac>
            <mn>1</mn>
            <mn>2</mn>
          </mfrac>
        </mstyle>
        <msup>
          <mo stretchy="false">)</mo>
          <mi>n</mi>
        </msup>
        <mo stretchy="false">]</mo>
      </mrow>
    </mrow>
  </mstyle>
</math>

This is, if we replace the enclosing parentheses by a <mfenced> tag (which should give an equivalent valid math expression), it results an invalid XML code:

<math xmlns="http://www.w3.org/1998/Math/MathML" display="block">
  <mstyle displaystyle="true" scriptlevel="0">
    <mrow class="MJX-TeXAtom-ORD">
      <mrow class="MJX-TeXAtom-ORD">
        <mfenced>
        <mstyle displaystyle="false" scriptlevel="0">
          <mfrac>
            <mn>1</mn>
            <mn>2</mn>
          </mfrac>
        </mstyle>
        <msup>
          </mfenced>
          <mi>n</mi>
        </msup>
        </mo stretchy="false">]</mo>
      </mrow>
    </mrow>
  </mstyle>
</math>

The reason is because the position of the closing </mfenced> or <mo strechy="false">)</mo> should be before the <msup> tag:

<math xmlns="http://www.w3.org/1998/Math/MathML" display="block">
  <mstyle displaystyle="true" scriptlevel="0">
    <mrow class="MJX-TeXAtom-ORD">
      <mrow class="MJX-TeXAtom-ORD">
        <mfenced>
          <mstyle displaystyle="false" scriptlevel="0">
            <mfrac>
              <mn>1</mn>
              <mn>2</mn>
            </mfrac>
          </mstyle>
        </mfenced>
        <msup>
          <mi>n</mi>
        </msup>
        </mo stretchy="false">]</mo>
      </mrow>
    </mrow>
  </mstyle>
</math>

Thanks beforehand for your interest.

Xavier Junqué i de Fortuny

@dpvc
Copy link
Member

dpvc commented Mar 26, 2024

MathJax's output is designed to produce a result that is as close to TeX's output as is it can. The output from TeX is

latex

while MathJax produces

mjx

so both produce equivalent results. TeX does not match the two parentheses and they do not stretch to fit the size of the fraction, and the placement of the superscript is based on the close parenthesis, not the size of the fraction. In the expression (\tfrac{1}{2})^n, the superscript is on the ), which is just a separate symbol, not associated with the preceding ( in any way.

To get the effect of <mfenced>, you would need to use \left(...\right), which does pair these two parentheses, and will allow them to stretch. For example, \left(\tfrac{1}{2}\right)^n allows the parentheses to stretch and places the superscript in relation to the stretched size:

mjx2

That produces

<math xmlns="http://www.w3.org/1998/Math/MathML" display="block">
  <mstyle mathsize="1.73em">
    <msup>
      <mrow data-mjx-texclass="INNER">
        <mo data-mjx-texclass="OPEN">(</mo>
        <mstyle displaystyle="false" scriptlevel="0">
          <mfrac>
            <mn>1</mn>
            <mn>2</mn>
          </mfrac>
        </mstyle>
        <mo data-mjx-texclass="CLOSE">)</mo>
      </mrow>
      <mi>n</mi>
    </msup>
  </mstyle>
</math>

as its MathML, which is equivalent to what I think you meant to propose as

<math xmlns="http://www.w3.org/1998/Math/MathML" display="block">
  <mstyle mathsize="1.73em">
    <msup>
      <mfenced>
        <mstyle displaystyle="false" scriptlevel="0">
          <mfrac>
            <mn>1</mn>
            <mn>2</mn>
          </mfrac>
        </mstyle>
      </mfenced>
      <mi>n</mi>
    </msup>
  </mstyle>
</math>

though your third example is identical to your second one, other than indentation (and both are invalid MathML due to the msup having only one child).

It would also be possible in your original LaTeX to use the braces to group the parentheses and put the superscript after that to get a similar effect:

\begin{equation} {(\tfrac{1}{2})}^n \end{equation}

Here, the superscript is for the complete expression (\tfrac{1}{2}), so will be positioned with respect to the height of the expression as a whole; that is, it will be positioned higher since the fraction is larger than the parenthesis. Note, however, that the parentheses will still not stretch. For that, you must use \left...\right.

Your MathML examples don't actually correspond to your LaTeX, due to the <mo stretchy="false">]</mo> while there is no ] in the original LaTeX. I assume you copied the MathML from a different LaTeX expression accidentally.

Finally, the mfenced tag is deprecated, and the <mrow><mo>(</mo>...<mo>)</mo></mrow> construction is the recommended one (which is what MathJax is using for \left(...\right)).

So the upshot is, MathJax's rendering of your LaTeX expression is correct (meaning that it matches the actual LaTeX output), and the generated MathML is correct for producing that result. Your modification of the MathML to include an mfenced element changes the underlying structure of the expression, and produces invalid MathML, as you point out, but that is not MathJax's fault, as you were the one making the change. If you are going to modify the MathML in this way, you would need to move the <msup> to before the <mfenced> yourself. Asking MathJax to put the <msup> earlier would mean MathJax would not produce the proper LaTeX output for the given LaTeX input.

@dpvc dpvc transferred this issue from mathjax/MathJax-docs Mar 26, 2024
@dpvc dpvc added the Expected Behavior This is how MathJax works label Mar 26, 2024
@xrjunque
Copy link
Author

xrjunque commented Mar 26, 2024

I think you have my first edition. Sorry, I did edit my comment about 15 minutes later than the first, where there is no ] and the second example is an invalid MathML, while the third example is a valid one.

I can understand that MathJax does its best to translate LaTex but, if we assume parentheses positions as XML tags have a meaning of opening tag for <mo stretchy="false">(</mo> and closing tag for <mo stretchy="false">)</mo> other than decorative, as I see it, they should have a role equivalent to that of deprecated <mfenced> </mfenced>. In this case, the MathML construct is not XML valid -captured in my second example.

Perhaps another tag, other than parentheses, could do the purpose? Or restore <mfenced> roll indicating matching parentheses in a math expression whereas having a XML valid construct?

An extract of https://www.w3.org/TR/mathml4/#presm_scrlim
«Because presentation elements should be used to describe the abstract notational structure of expressions, it is important that the base expression in all scripting elements (i.e. the first argument expression) should be the entire expression that is being scripted, not just the trailing character. For example, (x+y)^2 should be written as:

<msup>
  <mrow>
    <mo> ( </mo>
    <mrow>
      <mi> x </mi>
      <mo> + </mo>
      <mi> y </mi>
    </mrow>
    <mo> ) </mo>
  </mrow>
  <mn> 2 </mn>
</msup>

»

@dpvc
Copy link
Member

dpvc commented Mar 26, 2024

I think you have my first edition. Sorry, I did edit my comment about 15 minutes later than the first, where there is no ] and the second example is an invalid MathML, while the third example is a valid one.

It looks like we may have been editing at the same time, so perhaps I did end up modifying an earlier version. The edit history shows you made two edited versions, and they all include the ] and neither they nor the original have a valid third example. Your edited version seems to be

<math xmlns="http://www.w3.org/1998/Math/MathML" display="block">
  <mstyle displaystyle="true" scriptlevel="0">
    <mrow class="MJX-TeXAtom-ORD">
      <mrow class="MJX-TeXAtom-ORD">
        <mfenced>
          <mstyle displaystyle="false" scriptlevel="0">
            <mfrac>
              <mn>1</mn>
              <mn>2</mn>
            </mfrac>
          </mstyle>
        </mfenced>
        <msup>
          <mi>n</mi>
        </msup>
      </mrow>
    </mrow>
  </mstyle>
</math>

but this is not valid MathML, as I point out above. The <msup> is invalid because it requires two children, not one. You would need the <msup> open tag to be before the <mfenced> open tag. That is, the <mfenced>...</mfenced> would have to be the first child of the <msup> and the <mi>n</mi> be the second, as in

<math xmlns="http://www.w3.org/1998/Math/MathML" display="block">
  <mstyle displaystyle="true" scriptlevel="0">
    <msup>
      <mfenced>
        <mstyle displaystyle="false" scriptlevel="0">
          <mfrac>
            <mn>1</mn>
            <mn>2</mn>
          </mfrac>
        </mstyle>
      </mfenced>
      <mi>n</mi>
    </msup>
  </mstyle>
</math>

as I suggested above.

if we assume parentheses positions as XML tags have a meaning of opening tag for <mo stretchy="false">(</mo> and closing tag for <mo stretchy="false">)</mo>

That is not a valid assumption. For example, some people use )0,1( to mean the open interval from 0 to 1, so ) is an open delimiter and ( is a close delimiter. LaTeX makes very limited semantic assumptions about the meaning of the symbols, in general, and certainly doesn't pair symbols as you are requesting. You must do that explicitly yourself, using \left and \right` which enforces the pairing. That is the mechanism that TeX provides for doing such pairing, and for MathJax to do anything else would be counter to what LaTeX does.

other than decorative, as I see it, they should have a role equivalent to that of deprecated <mfenced> </mfenced>

Unfortunately, that's not how LaTeX works, and the difference is not just decorative. In LaTeX, parentheses entered individually do not stretch and are not paired, while those entered with \left and \right do stretch and are paired. MathJax has to handle these symbols in the same way LaTeX does: parentheses given by <mo stretchy="false"> will not stretch and are not paired, while <mfenced> would have parentheses that do pair and that are paired, though the recommended encoding, as you yourself point out, would be <mrow><mo>(</mo>...<mo>)</mo></mrow>, which is what MathJax produces for \left(...\right). You are asking MathJax to make semantic interpretations of the expression that are not being done by LaTeX, and that will end up producing different output from what LaTeX would produce. LaTeX has ways to produce the MathML you are looking for, but you do have to use them if that's the MathML you want to produce.

In this case, the MathML construct is not XML valid -captured in my second example.

Yes, that is invalid MathML, not because of the <mfenced> but because of the <msup>. But that is not MathML that MathJax produces, so I'm not sure why you are complaining about it. That is your own editing of the MathML, and you have corrupted it by doing so. That is not MathJax's fault, nor something MathJax has any way to fix for you.

[From the MathML specification] For example, (x+y)^2 should be written as:

<msup>
  <mrow>
    <mo> ( </mo>
    <mrow>
      <mi> x </mi>
      <mo> + </mo>
      <mi> y </mi>
    </mrow>
    <mo> ) </mo>
  </mrow>
  <mn> 2 </mn>
</msup>

Yes, that's right, and the way you would write that expression in LaTeX is {(x+y)}^2, not (x+y)^2. The former means raise the entire (x+y) to the power of 2, whereas the second (in LaTeX) means raise the ) to the power 2, since LaTeX does no parentheses pairing in this case. The output from MathJa for {(x+y)}^2 is

<msup>
  <mrow data-mjx-texclass="ORD">
    <mo stretchy="false">(</mo>
    <mi>x</mi>
    <mo>+</mo>
    <mi>y</mi>
    <mo stretchy="false">)</mo>
  </mrow>
  <mn>2</mn>
</msup>

which is in line with the example from the specification, missing only the redundant inner mrow. I do not see why that have included that, but if you want an extra mrow, you could use { ( {x+y} ) }^2 to achieve that.

As you can see, you can control MathJax's MathML production by proper use of braces to indication the grouping that you intend. Because LaTeX is not semantic, If you want to create more semantically meaningful MathML, you need to be more careful about how your LaTeX is constructed, as you are the one to impose the semantics, not LaTeX (and so, not MathJax's LaTeX input jax).

@xrjunque
Copy link
Author

xrjunque commented Mar 26, 2024 via email

@dpvc
Copy link
Member

dpvc commented Mar 26, 2024

Turning back to the sample I gave; it is an equation:

\begin{equation} {(\tfrac{1}{2})^n} \end{equation}

Actually, despite the equation environment, it is not an equation, since it has no equal sign (an equation is two expressions with an equal sign between them). This is an expression, and so is ]3,4[. You can certainly use the latter in an equation, as in

\begin{equation} ]0,1[ \cup [1,2[ = ]0,2[ \end{equation}

A naïve pairing of "open" brackets with "close" ones will be totally wrong, here.

In any case, since MathJax is trying to reproduce LaTeX input and output (not some computer algebra system results), the generated MathML is not going to be changed, since that would produce results different from LaTeX.

@xrjunque
Copy link
Author

xrjunque commented Mar 26, 2024 via email

@dpvc
Copy link
Member

dpvc commented Mar 26, 2024

Certainly,
\begin{equation} ]0,1[ \cup [1,2[ = ]0,2[ \end{equation}
is not an equation in spite of being labeled as "equation".

Certainly this is an equation, because it is an equality between two mathematical objects: it says that the open interval from 0 to 1 when union with the half-open interval from 1 (inclusive) to 2 (exclusive) is equal to the open interval from 0 to 2. That is an equality between two expressions and so it is an equation, by definition.

On the other hand {(\tfrac{1}{2})^n} is not an equation, as it is not an equality between two expressions. It is a single expression, therefore, not an equation.

But none of that matters, as matching parentheses or brackets is not something that LaTeX does except when something like \left and \right are used. It doesn't matter if it is an equation or just an expression, as there is no way for LaTeX or MathJax to know what delimiters are supposed to be matched without your being more explicit about in your original LaTeX notation. That's just how LaTeX works, and wishing it did something else is not going to change that.

@xrjunque
Copy link
Author

xrjunque commented Mar 26, 2024 via email

@dpvc
Copy link
Member

dpvc commented Mar 27, 2024

There are plenty of LaTex examples out there (math expressions or equations) not considering the use of \left and \right [or braces] -as you pointed- and the result is a poor or bad translation into MathML.

TeX was developed in the late 1970s as a means of producing high quality printed documents that include mathematics. That means its main focus was getting the symbols onto the page in the right locations, so its input language does not enforce any semantic meaning to the underlying symbols (the reader does that when he or she reads the page). It was not meant as an interchange language, and is not structured to carry the mathematical meaning of the symbols it presents.

Presentation MathML is also meant mostly for displaying mathematics, not giving it meaning, though its tags do help give it some semantics, and certainly more than TeX does. Because TeX does not carry semantic meaning, trying to add that semantics to the MathML output means moving beyond what was in the original TeX, and that means guessing what the original semantics should be. While that can be done in some cases, there are always going to be TeX expressions were that guesswork gets it wrong. MathJax's mission is to reproduce TeX output's for any given input, not to produce the most semantically meaningful representation of the underlying mathematics (which may or may not render the same as TeX would). A MathML expression that reproduces the desired TeX output is not a "poor" or "bad" translation when that is the goal. You have a different goal, which is fine, but it is not MathJax's mission to produce the output you are looking for.

If LaTex can't express itself with rigor, LaTex coder has to supply this lack with extra work.

Yes, that's correct. Writing semantically meaningful LaTeX is possible, but it does take extra care to do so. Because TeX and LaTeX input isn't required to be meaningful, trying to impose meaning onto it would only work sometimes.

MathJax does have a semantic-enrichment extension that tries to determine meaning for the expressions it processes. It will, for example, convert (x+y)^2 from

  <mo stretchy="false">(</mo>
  <mi>x</mi>
  <mo>+</mo>
  <mi>y</mi>
  <msup>
    <mo stretchy="false">)</mo>
    <mn>2</mn>
  </msup>

to

  <msup>
    <mrow>
      <mo stretchy="false">(</mo>
      <mrow>
        <mi>x</mi>
        <mo>+</mo>
        <mi>y</mi>
      </mrow>
      <mo stretchy="false">)</mo>
    </mrow>
    <mn>2</mn>
  </msup>

but the heuristics for this are "standard" meanings of the symbols, and so will fail in circumstances where they are not used in that standard way. For example, it will badly misinterpret the interval notation in my previous comments. But perhaps that would do what you are looking for.

@xrjunque
Copy link
Author

xrjunque commented Mar 27, 2024 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Expected Behavior This is how MathJax works
Projects
None yet
Development

No branches or pull requests

2 participants