6

I want to display a proof tree in the style of a natural deduction within a web page. I will get the data from a JSON file.

Whats the best way to display something like this? Is it possible only with css? Or is there a library that can do something like this? Rendering as an image is not possible, because eventually it should be interactive. I should also mention that this tree can get fairly large.

Example: proof tree

Update: A better example of what the end result should look like: enter image description here

schlicht
  • 4,735
  • 1
  • 13
  • 23

4 Answers4

3

The easiest solution would be mathjax which is a latex javascript renderer. And there are quite a few other similar rendering options out there.

Alternatively you could also look at MathML, which is the w3c standard for writing mathematical equations. Sadly, right now, the support for it is quite lacking as can be seen here, but long term it's going to be a great solution. Additionally the previously mentioned MathJax can be used as a MathML shim in browsers that do not support MathML yet.

The only concern with the MathJax shim is going to be that when you make it interactive it's going to interact differently with your code in browsers which do and do not support MathML, but despite that I would personally advice MathML except if you're already bound into LaTeX.

Based on your update I am not sure whether that can be expressed in MathML or LaTeX and I fear the only thing you could do is draw it on a canvas or set it up in a SVG if you need the interactivity later on. But I can warn you already know that that's not going to be a simple thing to do if you aren't used to it.


To add interactivity to Mathjax:

  1. Use MathML as input
  2. Use HTML/CSS as output
  3. Disable the MathJax context menu by adding showMathMenu:false to your core MathJax config
  4. Include id's in your MathML markup (literally <mo id="someid"> for example)
  5. Use for example jQuery to bind to the id after MathJax has finished (i.e. $("#someid").on("mousemove",function(){...}))

A fully working demo can be found here, move over the equal sign to trigger an alert.

David Mulder
  • 26,123
  • 9
  • 51
  • 114
  • I tested MathML with MathJax. At first it looked good, but I don't see a way to make it interactive (tooltips, links, etc.). – schlicht May 02 '13 at 10:12
  • Edited the answer with an explanation how interactivity can be added to MathJax output. Once you figure it out it's fairly simple (though it took awhile to figure out). – David Mulder May 02 '13 at 11:01
  • The demo works only in chrome for me(and only sometimes), maybe a problem with the synchronisation between your code and MathJax? I shall try MathJax once more. I also have a working demo with tables, but its with tables. Thanks! – schlicht May 02 '13 at 12:46
  • Updated the demo code with a version which will work cross browser. Just cleaned up a bunch of stuff and now I am not relying on some odd jQuery construction at least (`.on` is *supposed* to work like `.live` but apparently this doesn't work in IE). – David Mulder May 03 '13 at 10:37
  • 2
    @schlicht Mathjax can render LaTeX `\begin{array} \end{array}` arrays, and with some carefully placed `\hline`s, some reasonable looking proof trees can be rendered. It's also possible to use `\frac` and some math font size commands (e.g., `\displaystyle`) to keep the text from automatically shrinking. The biggest problem, however, seems to be that MathJax doesn't support the vertical alignment that the array environments provide, so you get stuck with things being a bit higher than they should be. – Joshua Taylor Jun 13 '13 at 02:10
  • 3
    @schlicht For instance, try the MathJax code `$$ \frac{\frac{\displaystyle \frac{P \land Q}{P} \qquad \frac{P \land Q}{Q}}{\displaystyle Q \land P} \qquad Q \land P \to R}{R}$$` in the demo editor at http://www.mathjax.org/demos/ . For another example using the `\frac` technique, I have a proof tree in [this answer](http://math.stackexchange.com/a/375585/72995) on math.stackexchange – Joshua Taylor Jun 13 '13 at 02:17
  • @Joshua Thanks, the shrinking frac was one of the problems I had with the frac solution. But overall I will stick with the html table solution since its the simplest one. – schlicht Jun 14 '13 at 08:21
3

I came across the same thing recently, and I managed to write some CSS which gives quite good results I think. Here's a sample html skeleton:

<div class="proof">
    <div class="prems">
        <div class="proof">
            <div class="prems">
                <div class="proof">
                    <div class="prems">
                        <div class="proof">
                            <div class="concl">
                                <div class="concl-left"></div>
                                <div class="concl-center">bla</div>
                                <div class="concl-right"></div>
                            </div>
                        </div>
                        <div class="inter-proof"></div>
                        <div class="proof">
                            <div class="concl">
                                <div class="concl-left"></div>
                                <div class="concl-center">bla</div>
                                <div class="concl-right"></div>
                            </div>
                        </div>
                    </div>
                    <div class="concl">
                        <div class="concl-left"></div>
                        <div class="concl-center">bla</div>
                        <div class="concl-right"></div>
                    </div>
                </div>
                        <div class="inter-proof"></div>
                <div class="proof">
                    <div class="concl">
                        <div class="concl-left"></div>
                        <div class="concl-center">bla</div>
                        <div class="concl-right"></div>
                    </div>
                </div>
            </div>
            <div class="concl">
                <div class="concl-left"></div>
                <div class="concl-center">bla</div>
                <div class="concl-right"></div>
            </div>
        </div>
    </div>
    <div class="concl">
        <div class="concl-left"></div>
        <div class="concl-center">blabla</div>
        <div class="concl-right"></div>
    </div>
</div>

and here's the CSS:

.proof
{
    display: inline-flex;
    flex-direction: column;
}
.prems
{
    display: inline-flex;
    flex-wrap: nowrap;
    align-items: flex-end;
}
.inter-proof
{
    border-bottom: 1px solid black;
    width: 1em;
}
.concl
{
    display: inline-flex;
    margin-top: -1px;
}
.concl-left
{
    flex-grow: 1;
}
.concl-center
{
    border-top: 1px solid black;
}
.concl-right
{
    flex-grow: 1;
}
.prems > .proof:not(:first-child) > .concl > .concl-left
{
    border-bottom: 1px solid black;
}
.prems > .proof > .concl > .concl-center
{
    border-bottom: 1px solid black;
}
.prems > .proof:not(:last-child) > .concl > .concl-right
{
    border-bottom: 1px solid black;
}

see it live here. I only tried with firefox, and it may need some tweaks for other browsers.

CSSproof
  • 31
  • 1
1

So after much fiddling with css, I used tables to get a satisfactory result. Since the layout is indeed part of the semantics, I think its acceptable in this case.

A small example would look like this:

<table>
    <tr>
        <td>
        </td>
        <td class="rulename" rowspan="2"><div class="rulename">add</div></td></tr>
    <tr><td class="conc">conclusion</td></tr>
</table>

And the css:

td {
 text-align:center;
 height: 1em;
 vertical-align:bottom;
}
td.conc {
 border-top: solid 1px;
}
div.rulename {
 margin-top:-2em;
}

Bigger demo

schlicht
  • 4,735
  • 1
  • 13
  • 23
  • Hello, I am very interested by your solution, but your post is so concise that it is very difficult to understand how you build a natural deduction or a sequent derivation to publish it via mathjax on the web. A detailed tutorial would be very welcome! Many thanks in advance if you can help. – Joseph Vidal-Rosset Dec 15 '19 at 06:01
  • Hey, you can take a look at the demo. If i remember correctly its just plain HTML and CSS, no js or mathjax. I'm no longer (7 years ago) involved in this kind of work, so I don't have anything else to offer. – schlicht Jun 24 '20 at 11:39
0

I gave it a try (for this) and here are the codes (using just plain css and javascript). It just draws raw strings like this image (so no LaTeX... but I also want to accomplish this and currently trying ).

The starting point was something like below.

<style>
  #proof-tree {
      padding: 50px;
      overflow-x: scroll;
  }
  .node {
      display: inline-block;
      white-space: nowrap;
      margin: 0 2em;
      text-align: center;
  }
  .bar {
      width: 100%;
      height: 1px;
      background: black;
      position: relative;
  }
  .rule {
      position: absolute;
      bottom: -0.5em;
      right: -3em;
  }
</style>

<div id="proof-tree">
  <div class="node">
    <div class="antecedents">
      <div class="node">
    <div class="antecedents">
      <div class="node">
        <div class="antecedents"></div>
        <div class="bar"><div class="rule">rule1</div></div>
        <div class="consequent">foo1</div>
      </div>
      <div class="node">
        <div class="antecedents"></div>
        <div class="bar"><div class="rule">rule2</div></div>
        <div class="consequent">hoo2</div>
      </div>
    </div>
    <div class="bar"><div class="rule">rule3</div></div>
    <div class="consequent">foo3</div>
      </div>
      <div class="node">
    <div class="antecedents"></div>
    <div class="bar"><div class="rule">rule4</div></div>
    <div class="consequent">foo5</div>
      </div>
    </div>
    <div class="bar"><div class="rule">rule6</div></div>
    <div class="consequent">foo6</div>
  </div>
</div>

It displays like this.

However, in this way, the lower bars tend to be too long and I couldn't get satisfied with it. Therefore, I wrote some javascript to get the position of nodes and minimize the length of the bar. I do NOT think this is the smartest idea at all. It is obviously dirty... but I hope this could be any help to someone (like me).

Also, please let me know if you/someone have any additional info.

Jin SANO
  • 1
  • 2