Technical Documents

Demonstrating the Power of Markdown with Pandoc

Authors: Gabriel Nützi, The Community

Date: 2. December 2020

Location: Zürich, Switzerland

Abstract

This is a setup demonstrating the power and use of markdown for technical documents by using a fully automated conversion sequence with gradle and of course pandoc.”

Acknowledgement

Acknowledgements go to the authors of this setup.

$$ \newcommand{\vvec}[1]{\mathbf{#1}} \newcommand{\mat}[1]{\mathbf{#1}} \newcommand{\cs}[1]{\mathrm{#1}} \newcommand{\rp}[1]{{_\cs{#1}}} \newcommand{\csT}[2]{\mat{A}_{\mathrm{#1#2}}} \newcommand{\genT}[2]{\mat{T}_{\mathrm{#1#2}}} \newcommand{\affcsT}[2]{\mat{H}_{\mathrm{#1#2}}} \newcommand{\affcsTdx}[2]{\mat{H}_{\mathrm{#1#2}}^{\transp}} \newcommand{\basevec}[2]{\vvec{e}_{\mathrm{#1}}^{\cs{#2}}} \newcommand{\homArr}[1]{\left[\begin{array}{c}#1 \\ 1 \end{array}\right]} \newcommand{\homArrTr}[1]{\left[\begin{array}{c}#1 && 1 \end{array}\right]} \newcommand{\homMat}[2]{\left[\begin{array}{cc}#1 & #2 \\ \vvec{0} & 1 \end{array}\right]} \newcommand{\arr}[2]{\left[\begin{array}{#1}#2\end{array}\right]} \newcommand{\transp}{\top} \newcommand{\rot}[2]{\mat{R}_\mathrm{#1#2}} \newcommand{\norm}[1]{\|#1\|} \newcommand{\mdet}[1]{\det(#1)} \newcommand{\set}[1]{\mathcal{#1}} \newcommand{\prox}[1]{\mathbf{prox}_{\set{C}}} \DeclareMathOperator*{\argmin}{argmin} \newcommand{\ncone}[1]{\mathcal{N}_{\set{#1}}} \newcommand{\indf}[1]{I_{\set{#1}}} $$

1 Intro

Read the Readme.md for futher information.

2 Samples

2.1 Konvexe Probleme

In diesem Abschnitt geht es darum ein besseres Verständnis zu geben über Algorithmen und Konzepte welche zum Beispiel bei der \(2\)d-/\(3\)d-Kollisionsdetektion oder in Optimierungs-Algorithmen genutzt werden. Die Erklärungen sind eine stärkere und vereinfachte Zusammenfassung aus [1, Ch. 6]. Dieses Kapitel möchte nicht mathematisch abschliessend sein, sondern lediglich (nach der Ansicht des Autors) ein paar wichtige Grundkonzepte vermitteln, welche einen wunderbaren Einstieg in dieses Thema geben. Die erwähnten Konzepte sind in der generellsten Form der konvexen Analysis zu finden und können sehr wohl als die wichtigsten Standbeine verinnerlicht werden. Auf Beweise wird bewusst verzichtet. Es wird versucht die mathematischen Definitionen anschaulich zu erklären.

Das Vorhandensein eines konvexen Optimierungsproblems oder auch einer konvexen Menge beim Lösen eines Problems in \(3\)D, oder auch mehr Dimensionen, erlaubt es, auf eine Fülle von mathematisch sehr etablierten Definitionen und Konzepte aus der konvexen Analysis zurückzugreifen. Diese schon fast 50-jährige Theorie ist sehr fundiert und ein abgeschlossenes Untergebiet in der Mathematik.

Die konvexe Analysis ist ein Grenzgebiet von Geometrie, Analysis und Funktionalanalysis, das sich mit den Eigenschaften konvexer Mengen und konvexer Funktionen befaßt und Anwendungen sowohl in der reinen Mathematik besitzt (von Existenzsätzen in der Theorie der Differential- und Integralgleichungen bis zum Gitterpunktsatz von Minkowski in der Zahlentheorie) als auch in Bereichen wie der mathematischen Ökonomie und den Ingenieurswissenschaften, wo man es oft mit Optimierungs- und Gleichgewichtsproblemen zu tun hat. Als einschlägige Referenz auf diesem Gebiet sei hier mal das Standardwerk [2] gegeben.

2.1.1 Konvexe Menge

Eine Menge \(\set{C} \subseteq V\), also ein Teilmenge eines Vektorraums \(V\), wird konvex genannt, falls und nur falls \[\begin{align} \lambda \vvec{a} + (1-\lambda) \vvec{b} \in \set{C} \quad \forall \vvec{a},\vvec{b} \in \set{C}, \ \lambda \in [0,1] \ . \end{align}\] gilt.

Das heisst alle Punkte auf einer geraden Linie zwischen zwei beliebigen Punkten aus der Menge \(\set{C}\) müssen auch in dieser Menge liegen damit es konvex ist. Stellt man sich eine Banane vor oder eine Oberfläche eines \(3\)d-Würfels, dann erfüllen diese Mengen das Kriterium nicht. Ein ausgefülltes \(2\)d-Rechteck , ein gefüllter \(3\)d-Würfel oder eine gefüllte Kugel jedoch schon. Eine konvexe Menge ist eine Teilmenge eines Vektorraums. Ein Beispiel ist der euklidische Raum \(\mathbb{E}^3\) in \(3\)D.

Man interessiert sich nun zum Beispiel für die Projektion eines Punktes \(\vvec{x}\) auf ein konvexe Menge \(\set{C}\). Die Projektion sollte so sein, dass der Abstand zwischen dem Punkt \(\vvec{x}\) und dem projezierten Punkt \(\vvec{y} \in \set{C}\) minimal ist.

Der Abstand wird über eine Metrik \(d(\vvec{x},\vvec{y}) \geq 0\) definiert - die Distanzfunktion. Der euklidische Vektorraum \(\mathbb{E}^3\) ist ein Vektorraum mit einer Metrik und ist daher ein metrischer Raum. Das Standard-Skalarprodukt \(\vvec{x}^\transp \vvec{y}\) im euklidischen Raum \(\mathbb{E}^3\) induziert direkt die Standardnorm \(\norm{\vvec{x}}_2 := \sqrt{\vvec{x}^\transp \vvec{x}} \geq 0\). Diese wiederum induziert direkt die Metrik \[\begin{align} d(\vvec{x},\vvec{y}) := \norm{\vvec{x} - \vvec{y}}_2. \end{align}\]

Wir können somit über die Metrik \(d(\vvec{x},\vvec{y})\) die Länge zwischen zwei Vektoren \(\vvec{x},\vvec{y} \in \mathbb{E}^3\) berechnen.

2.1.2 Proximaler Punkt

Mit der Metrik, also unserem Lineal zum Messen von Distanzen, lässt sich nun die Projektion \(\prox{C}(\vvec{p})\) eines Punktes \(\vvec{p}\) mit minimaler Distanz auf eine konvexe Menge \(\set{C}\) relativ leicht definieren zu \[\begin{align} \prox{C}(\vvec{p}) := \underset{\vvec{x} \ \in \ \set{C}}{\argmin} \norm{\vvec{x} - \vvec{p}}_2. \end{align}\]

Das heisst \(\prox{C}(\vvec{p})\) minimiert den Punkt \(\vvec{x}\) in der Menge \(\set{C}\) so, dass sein Abstand zu \(\vvec{p}\) minimal ist.

2.1.3 Normalkegel

Eines der wichtigsten Konzept der konvexen Analysis ist die des Normalkegels. Wie der Name schon sagt, handelt es sich um einen Kegel welcher durch Normalenvektoren auf der Oberfläche einer konvexen Menge aufgespannt wird. Wir geben hier direkt die Definition und sehen im Anschluss wie sich dieser Kegel visualisiert:

Ein Normalkegel \(\ncone{C}\) auf ein konvexes Set \(\set{C}\) im Punkt \(\vvec{x} \in \set{C}\) ist definert als \[\begin{align} \ncone{C}(\vvec{x}) := \left\{ \vvec{y} \ | \ \vvec{y}^\transp(\vvec{x}^* - \vvec{x}) \leq 0, \quad \forall \vvec{x}^* \in \set{C} \right\} \end{align}\]

Das ist nun ein wenig kryptisch, heisst jedoch nichts anderes als folgendes: Der Normalkegel \(\ncone{C}(\vvec{x})\) besteht aus allen Vektoren (das wäre \(\vvec{y}\)) ausgehend von \(\vvec{x}\) welche mit allen Vektoren welche vom Punkt \(\vvec{x}\) in die Menge \(\set{C}\) zeigen (das wäre \(\vvec{x}^* - \vvec{x}\)), einen stumpfen Winkel bilden (das wäre das Skalatprodukt mit \(\leq 0\)). Der Ursprung der Menge \(\ncone{C}(\vvec{x})\) ist im Punkt \(\vvec{x}\).

Die Abbildung 1 visualisiert für eine konvexe Menge \(\set{C}\) die verschiedenen Normalkegel.

Figure 1: Normalkegel an die Punkte \vvec{x}, \vvec{y} und \vvec{z}. Der Normalkegel an einen innerhalb der Menge \set{C} liegenden Punkt \vvec{z} degeneriert zum \vvec{0}-Vektor. Der Vektor \vvec{v} ist in der Menge des Normalkegels an \vvec{x}.

2.1.4 Zusammenhang von Normalkegel und Proximaler Punkt

Man fragt sich natürlich nun: Was bringen uns diese mathematische Definitionen?

Es stellt sich heraus, dass es einen Zusammenhang gibt zwischen \(\prox{C}\) und \(\ncone{C}\) welcher extremst nützlich ist und heute im Feld der konvexen Optimierung, beim Machine-Learning, in der Starrkörper-Mechanik (Starrkörper-Simulationen und Physics-Engines in Games) oder auch in der Kollisionsdetektion (GJK Algorithmus) durch projektive Iterationen direkte Anwendung findet.

Der Zusammenhang ist wie folgt: \[\begin{align} \vvec{y} \in \ncone{C}(\vvec{x}) \quad \Leftrightarrow \quad \vvec{x} = \prox{C}(\vvec{x} + \vvec{y}) \label{eq:prox-to-ncone} \end{align}\]

Das heisst, eine Normalkegel-Inklusion (die Relation \(\vvec{a} \in \set{B}\) wird Mengen-Inklusion genannt) ist direkt an eine implizite projektive Gleichung gekoppelt.

Damit lässt sich nun ein interessanter wichtiget Fakt ableiten. Aus der Visualisierung 1 entnehmen wir, dass \(\vvec{p}-\vvec{x}\) in der Menge \(\ncone{C}(\vvec{x})\) liegt, also lässt sich schreiben \[\begin{align} \vvec{p}-\vvec{x} \in \ncone{C}(\vvec{x}). \end{align}\]

Dies lässt sich mit obiger Beziehung direkt zu \[\begin{align} \vvec{x} &= \prox{C}(\vvec{x} + \vvec{p} - \vvec{x}) \\ &= \prox{C}(\vvec{p}). \end{align}\] umschreiben. Aus dem erkennen wir, dass der Ursprung des Normalkegels, worin ein beliebiger Punkt \(\vvec{p}\) liegt, direkt der proximale Punkt ist zu \(\vvec{p}\).

Müssten wir nun eine Projektionsfunktion auf ein \(2\)d-Dreieck herleiten, würden wir folgendes Bild malen:

Figure 2: Normalkegel an die Punkte \vvec{a}, \vvec{b} und \vvec{c} eines Dreiecks.

Das heisst es gibt genau 3 nicht triviale Normalkegel und 3 einfachere Normalkegel (bestehend lediglich aus den Normalen auf die Seitenflächen). Eine Projektionsfunktion auf ein Dreieck muss diese 6 Bereiche beachten und ist so auch optimal und richtig implementiert.

2.1.5 Zusammenhang von Normalkegel und Konvexer Optimierung

Um hier mathematisch nicht in einen Exzess zu geraten, wird hier nur eine abgespeckte Erklärung gegeben. Für mehr Informationen sei auf [1, Ch. 6] verwiesen und die darin enthaltenen Referenzen.

Betrachte man folgendes allgemeine restriktierte konvexe Optimierungsproblem: \[\begin{align} \vvec{x}^* = \underset{\vvec{x} \ \in \ \set{C}}{\argmin} f(\vvec{x}), \label{eq:convexproblem} \end{align}\] wobei die Funktion \(f(\vvec{x}) \in \mathbb{R}\) strikt konvex und differenzierbar (man stelle sich den oberen Teil eines Weinglases vor, wobei \(\vvec{x} \in \mathbb{R}^2\)) ist und die minimierenden Punkte \(\vvec{x}\) auf eine konvexe Menge \(\set{C}\) restriktiert sind. Der minimierende Punkt ist hier mit \(\vvec{x}^*\) bezeichnet. Es gibt nur einen solchen globalen minimierenden Punkt

Dann kann man das Problem in ein freies konvexes Programm umschreiben indem man die Einschränkung \(\vvec{x} \in \set{C}\) mit einer Bestrafungsfunktion \(\indf{C}(\vvec{x})\) ersetzt \[\begin{align} \vvec{x}^* = \underset{\vvec{x}}{\argmin} f(\vvec{x}) + \indf{C}(\vvec{x}). \end{align}\]

Die Bestrafungsfunktion \(\indf{C}(\vvec{x})\) liefert \(0\) falls \(\vvec{x} \in \set{C}\) und sonst \(+\infty\). Diese Funktion wird Indikatorfunktion genannt.

Die Frage ist nun wie kriegen wir eine Bedingung an den optimalen (minimierenden) Punkt \(\vvec{x}^*\). Das geht ziemlich analog zu der Bedindung für Minima/Maxima einer differenzierbaren Funktionen \(f\) : \[\begin{align} \vvec{0} = \frac{df}{d\vvec{x}}(\vvec{x}^*) \label{eq:optimality-difffunc} \end{align}\] was konkret heisst, dass der Nullvektor \(\vvec{0}\) gleich dem Gradient \(\frac{df}{d\vvec{x}}\) ist an der optimalen Stelle \(\vvec{x}^*\).

Da wir aber bei unserem Problem \(\eqref{eq:convexproblem}\) diese unstetige, nicht-differenzierbare Bestrafungsfunktion \(\indf{C}\) eingebaut haben, ist dies nicht direkt mit der normalen Differentiation zu machen. Man braucht in der konvexen Analysis eine verallgemeinerte Ableitung - das Subdifferential, welches nicht mehr nur einfache Steigungen (d.h. die Steigung für \(1\)-dimensionale Funktionen \(f(x)\) oder allgemeiner der Gradient für \(n\)-dimensionale Funktionen \(f(\vvec{x})\)) zurück geben kann sondern auch ganze Mengen von solchen Steigungen. Das heisst, das Subdifferential an einem Punkt ist eine Menge aller Gradienten an diesen Punkt der Funktion. Das heisst direkt, dass eine Gleicheit zu \(\vvec{0}\) wie in \(\eqref{eq:optimality-difffunc}\) nicht mehr richtig wäre und hier eine Mengen-Inklusion \(\vvec{0} \in \dots\) stehen muss.

Anstatt \(\frac{d}{d\vvec{x}}\indf{C}\) nehmen wir einfach das Subdifferential \(\partial_{\vvec{x}} \indf{C}\) und die Bedingung \(\eqref{eq:optimality-difffunc}\) wird dann zu \[\begin{align} \label{eq:optimality-strict-convex} \vvec{0} \in \frac{df}{d\vvec{x}}(\vvec{x}^*) + \partial_{\vvec{x}} \indf{C}(\vvec{x}^*) \end{align}\]

Nur was machen wir nun mit dieser mengenwertigen Relation?

Da man zeigen kann, dass das Subdifferential, also die mengenwertige Ableitung, der Indikatorfunktion \(\partial_{\vvec{x}} \indf{C}(\vvec{x})\) genau dem Normalkegel \(\ncone{C}(\vvec{x})\) entspricht, können wir die obige Inklusion so schreiben: \[\begin{align} \vvec{0} \in \frac{df}{d\vvec{x}}(\vvec{x}^*) + \ncone{C}(\vvec{x}^*) \quad \Leftrightarrow \quad -\frac{df}{d\vvec{x}}(\vvec{x}^*) \in \ncone{C}(\vvec{x}^*) \label{eq:optimality-strict-convex-2} \end{align}\]

Das bringt uns nicht viel mehr ausser einer visuellen Erkenntnis durch folgende Visualisierung:

Figure 3: Konvexes Optimierungs Problem innerhalb der Menge \set{C} auf einer 2d-Funktion f(\vvec{x}) \in \mathbb{R}. Der negative Gradient liegt im Optimum \vvec{x}^* genau innerhalb des Normalkegels an \vvec{x}^*.

Mit der Beziehung zwischen proximalem Punkt und Normalkegel \(\eqref{eq:prox-to-ncone}\) kriegen wir daraus direkt eine implizite Projektionsgleichung für den optimalen Punkt \(\vvec{x}^*\): \[\begin{align} -\frac{df}{d\vvec{x}}(\vvec{x}^*) \in \ncone{C}(\vvec{x}^*) \quad \Leftrightarrow \quad \vvec{x}^* = \prox{C}(\vvec{x}^* - \frac{df}{d\vvec{x}}(\vvec{x}^*)), \end{align}\] welche man iterative lösen kann, was zum Gradienten-Projektionsverfahren führt (Gradient Projection Algorithm).

2.2 Code Sample

Some inline code int a; a += "asd"

class LogicNode
{
public:
    EG_DEFINE_TYPES();

    using InputSockets  = std::vector<LogicSocketInputBase*>;
    using OutputSockets = std::vector<LogicSocketOutputBase*>;

public:
    //! The basic constructor of a node.
    LogicNode(NodeId id = nodeIdInvalid)
        : m_id(id)
    {}

    LogicNode(const LogicNode&) = default;
    LogicNode(LogicNode&&)      = default;

    virtual ~LogicNode() = default;

    //! The init function.
    virtual void init() = 0;

    //! The reset function.
    virtual void reset() = 0;

    //! The main compute function of this execution node.
    virtual void compute() = 0;

public:
    NodeId id() const { return m_id; }
    void setId(NodeId id) { m_id = id; }

protected:
    //! Registers input sockets for this node.
    template<typename... Sockets>
    void registerInputs(std::tuple<Sockets...>& sockets)
    {
        m_inputs = tupleUtil::toPointers<
            [](auto*... p) { return InputSockets{p...}; }>(sockets);
    }

    //! Registers output sockets for this node.
    template<typename... Sockets>
    void registerOutputs(std::tuple<Sockets...>& sockets)
    {
        m_outputs = tupleUtil::toPointers<
            [](auto*... p) { return OutputSockets{p...}; }>(sockets);
    }

public:
    //! Get the list of input sockets.
    const InputSockets& getInputs() const { return m_inputs; }
    InputSockets& getInputs() { return m_inputs; }

    //! Get the list of output sockets.
    const OutputSockets& getOutputs() const { return m_outputs; }
    OutputSockets& getOutputs() { return m_outputs; }

    //! Get the input socket at index `index`.
    const LogicSocketInputBase* input(SocketIndex index) const
    {
        EG_THROW_IF(index >= m_inputs.size(), "Wrong index");
        return m_inputs[index];
    }

    //! Get the input socket at index `index`.
    LogicSocketInputBase* input(SocketIndex index)
    {
        EG_THROW_IF(index >= m_inputs.size(), "Wrong index");
        return m_inputs[index];
    }

    //! Get the output socket at index `index`.
    const LogicSocketOutputBase* output(SocketIndex index) const
    {
        EG_THROW_IF(index >= m_outputs.size(), "Wrong index");
        return m_outputs[index];
    }

    //! Get the output socket at index `index`.
    LogicSocketOutputBase* output(SocketIndex index)
    {
        EG_THROW_IF(index >= m_outputs.size(), "Wrong index");
        return m_outputs[index];
    }

protected:
    NodeId m_id;              //!< The id of the node.
    InputSockets m_inputs;    //!< The input sockets.
    OutputSockets m_outputs;  //!< The output sockets.
};

A normal code block without syntax highlighting:

Some special text here.

2.3 PDF Include Sample

You can also include PDFs directly by: Selecting pages works only in latex output.

2.4 Questionaire Sample

Personal

How hard is Markdown?

Which features would you like to have which Markdown does currently not support?



2.5 Tables

2.5.1 HTML Table

Table by included .html file.
Fruits asd Vegetables Constraints Properties
Pre Zuccini ripe long
First
  1. Lorem ipsum.
  2. Aliquam tinc.
Definition 1
\(\int_0^1{x^2} := \frac{1}{3}\)
Definition 2
\(x^2\) is a squared variable
Second
  • Lorem ipsum.
  • Mauris eu.
  1. Lorem sit.
  2. Dapibus.
  1. Aliquam risus.
  2. Auctor neque.

2.5.2 Markdown Tables

2.5.2.1 Multline Table

Here’s a multiline table without a header.
First row 12.0 Example of a row that spans multiple lines.
Second row 5.0 Here’s another one.

2.5.2.2 Grid Table

Sample grid table.
Fruit Price Advantages
Bananas $1.34
  • built-in wrapper
  • bright color
Oranges $2.10
  • cures scurvy
  • tasty
  • Link chap. 2.5.2

2.5.2.3 RST-Style Table

This is a RST-style table which is converted by filters/pandoc-list-table.lua

Sample Table
Key Name Italic Code
A This is some random text to demonstrate line breaks across cells. And it should happen. *italic* `code`
B This is some random text to demonstrate line breaks across cells. And it should happen. ``code``

References

[1]
G. Nützi, Non-smooth granular rigid body dynamics with applications to chute flows, PhD thesis, ETH Zurich; ETH Zürich, Zürich, 2016.
[2]
R. T. Rockafellar, Convex analysis. Princeton: Princeton University Press, 2015 [Online]. Available: https://www.degruyter.com/view/title/516543