benrbray / prosemirror-math

Schema and plugins for "first-class" math support in ProseMirror!
https://benrbray.com/prosemirror-math/
MIT License
243 stars 35 forks source link

Specialized Support for Arrays #15

Open bohrium opened 3 years ago

bohrium commented 3 years ago

One of the most annoying-times-frequency things among my latex experiences is making 2d grids by describing them using 1d text. Such grids include matrices, commutative diagrams, tables, multi-line derivations whose terms are aligned, and more. It'd be neat to provide a special "array mode" for parsing and editing text of the form

A & B & C & D & E \\  
A & B & C & D & E \\  
A & B & C & D & E \\  
A & B & C & D & E

This is the syntax for the latex body in each of all four examples above. The cells(' latex expressions) will typically all differ in length, creating a headache (do we spend time inserting white-space to align the columns, maintaining this alignment when we modify the cells? or do we ignore alignment issues in the source code and just count in our head when editing each row?)

It would be nice if when one's cursor enters a latex block of the above form, the cells in the latex block automatically align (wrt the ampersands and line-break symbols). If I correctly understand the spirit of prosemirror-math, one wants to avoid having popup dialog boxes or editors separate from the text. So perhaps the alignment could be as simple as inserting appropriate whitespace when the block is "active"!

benrbray commented 3 years ago

I agree, this is a common pain point for me as well, and I've been mulling over solutions in my head for a while. Getting the workflow right is tricky, but I'm happy to discuss possibilities. Although the examples you listed share a common syntax, I think they appear in quite different contexts and will need to be handled differently. We will also be limited by the commands supported by KaTeX / MathJax.

A x = \begin{bmatrix}
   a_{11} & a_{12} \\
   a_{21} & a_{22}
\end{bmatrix}
\begin{bmatrix}
    x_1 \\ x_2
\end{bmatrix}
\begin{aligned}
\EE_{q(x)}\left[  (x-\mu_A)^T \Sigma_A^{-1} (x-\mu_A) \right]
&= \EE\left[
        \trace\left( (x-\mu_A)^T \Sigma_A^{-1} (x-\mu_A) \right)
    \right] 
    & \text{(trace of scalar)} \\
&= \EE\left[
        \trace\left( \Sigma_A^{-1} (x-\mu_A) (x-\mu_A)^T \right)
    \right]
    & \text{(cyclicity)}\\
&= \trace\left( \EE\left[
        \Sigma_A^{-1} (x-\mu_A) (x-\mu_A)^T
    \right] \right)
    &\text{(linearity)}\\
&= \trace\left( \Sigma_A^{-1} \EE\left[
        (x-\mu_A) (x-\mu_A)^T
    \right] \right) 
    &\text{(linearity)}\\
&= \trace\left( \Sigma_A^{-1} \left[
        \Sigma_B + (\mu_B - \mu_A)(\mu_B - \mu_A)^T
    \right] \right)
    &\text{(eqn\;\ref{eqn:gauss-quadratic-form})} \\
&= \trace\left( \Sigma_A^{-1} \Sigma_B \right)
    + (\mu_B - \mu_A)^T \Sigma_A^{-1} (\mu_B - \mu_A)
    &\text{(cyclicity; linearity)}
\end{aligned}
bohrium commented 3 years ago

Cool! Your points about differences in context implying differences in handling make a lot of sense to me. I'll mull over.

Quick comments:

quiver seems to generate tikz blocks, but katex does not support tikz's environments (I think). It seems they support the amscd "CD" environment (CD stands for commutative diagram), which is a very bare bones package that can express perhaps 80% of the simple diagrams a math student might draw and that can render them correctly perhaps 80% of the time.

matrices as sub-expressions : the general design problem is as you mention tricky, so I'll discuss the much easier case where I'm allowed to overfit to my own tastes :smile:. I would feel happy if the example given is auto formatted to look like

A x =
\begin{bmatrix}                                                                 
    loremipsum & 1      \\                                                      
    0          & moocow                                                         
\end{bmatrix}                                                                   
\begin{bmatrix}                                                                 
    whole       \\                                                              
    two-percent                                                                 
\end{bmatrix} 

However, I can imagine folks and cases that favor a more compact style such as:

A x = \begin{bmatrix} loremipsum & 1      \\                                    
                      0          & moocow \end{bmatrix} \begin{bmatrix} whole \\ two-percent \end{bmatrix}

Here, only the "hard-to-parse" first matrix is formatted in an aligned way. I don't see how to approximate this latter style programatically --- or whether to so attempt would be useful.

multiline derivations: i bet the following two rules are common to many personal styles:

For example, both hold in the example you showed (for for the two values of k, we have c=0 and then c=4). So perhaps something good here be to insert spaces according to this "weak rule" rather than insisting on a canonical form. Thus, the formatter would not override extra newlines and extra indentation provided by the user.

Here's a simple example of what it would love to see when modifying a multiline derivation. Say we start with

\begin{align}
    a                                                                           
    &= \left(                                                                   
           itwasthebestoftimes                                                  
       \right)                                                                  
       moo   & \left\langle                                                     
                   itwastheworstoftimes                                         
               \right\rangle& woah                                              
        & true \\                                                               
    &= \left(                                                                   
           itwastheageofwisdom                                                  
       \right)                                                                  
       cow   & \left(                                                           
                   itwastheageoffoolishness                                     
               \right)_0    & woah \\                                           
        & true \\                                                               
    &                                &                                          
                            & woah                                              
        & true                                                                  
\end{align}

Upon replacing "cow" by "iamafundamoomentallygoodcow", we see

\begin{align}                                                                   
    a                                                                           
    &= \left(                                                                   
           itwasthebestoftimes                                                  
       \right)                                                                  
       moo                           & \left\langle                             
                                           itwastheworstoftimes                 
                                       \right\rangle& woah                      
        & true \\                                                               
    &= \left(                                                                   
           itwastheageofwisdom                                                  
       \right)                                                                  
       iamafundamoomentallygoodcow   & \left(                                   
                                           itwastheageoffoolishness             
                                       \right)_0    & woah \\                   
        & true \\                                                               
    &                                &                                          
                                                    & woah                      
        & true                                                                  
\end{align}

Then, upon replacing the "\rangle" by ")", we see

\begin{align}
    a                                                                           
    &= \left(                                                                   
           itwasthebestoftimes                                                  
       \right)                                                                  
       moo                           & \left\langle                             
                                           itwastheworstoftimes                 
                                       \right)  & woah                          
        & true \\                                                               
    &= \left(                                                                   
           itwastheageofwisdom                                                  
       \right)                                                                  
       iamafundamoomentallygoodcow   & \left(                                   
                                           itwastheageoffoolishness             
                                       \right)_0& woah \\                       
        & true \\                                                               
    &                                &                                          
                                                & woah                          
        & true                                                                  
\end{align}
bohrium commented 3 years ago

As for diagrams, here are what some that come to mind. They go from most to least common and from least to most complex. From the implementation standpoint they are similar: each is a combination of basic parts. But from the usability standpoint each might say something different about what interfaces best aid mathematical writing.

lifting diagram

\begin{tikzcd}
                               & P \arrow[d, "g"] \arrow[ld, "l"', dotted] \\
X \arrow[r, "\pi"', two heads] & Y                                        
\end{tikzcd}

see this link

causal model

\begin{tikzcd}
                                                                 & \substack{\text{sensor}\\ \text{placement}} \arrow[rd] \arrow[rrd] &                                                     &                                              \\
\substack{\text{attentive}\\ \text{nurse}} \arrow[ru] \arrow[rd] &                                                                    & \substack{\text{sensor}\\ \text{reading}} \arrow[r] & \substack{\text{guessed}\\ \text{heartrate}} \\
                                                                 & \substack{\text{true}\\ \text{heartrate}} \arrow[ru]               &                                                     &                                             
\end{tikzcd}

see this link

naturality

\begin{tikzcd}
                                     & a \arrow[ldd, no head, dotted] \arrow[rd, no head, dotted] \arrow[rr] &               & b \arrow[rd, no head, dotted] \arrow[dd, no head, dotted] &    \\
                                     &                                                                       & Ga \arrow[rr] &                                                           & Gb \\
Fa \arrow[rrr] \arrow[rru, "\eta_a"] &                                                                       &               & Fb \arrow[ru, "\eta_b"]                                   &   
\end{tikzcd}

see this link

finite-state automaton

\begin{tikzcd}
\to q_0 \arrow[r, "a"] \arrow["b", loop, distance=2em, in=235, out=305] & q_1 \arrow[r, "a"] \arrow[l, "b"', bend left=49] & q_2 \arrow[r, "a"] \arrow[ll, "b"', bend left=49] & \boxed{q_3} \arrow["{a,b}", loop, distance=2em, in=235, out=305]
\end{tikzcd}

see this link

bohrium commented 3 years ago

Let me know if any of these ideas sounds like a good starting point that I might try to implement!

benrbray commented 3 years ago

I think we agree on the rough ux, so I'm happy to continue the feedback loop with you if you start on a prototype! Some things to ponder: