\documentstyle[11pt]{article}
\newenvironment{gex}{\left[\begin{array}{c|c}}{\end{array}\right]}
\newcommand{\gc}[1]{\mbox{\boldmath$#1$}}
\newcommand{\true}{{\rm T}}
\newcommand{\false}{{\rm F}}
\newcommand{\E}{{\rm E}}
\newcommand{\GE}{{\rm GE}}
\newcommand{\gscheme}{{\rm gscheme}}
\newcommand{\sign}{{\rm sign}}
\begin{document}
\title{Guarded Expressions in Practice\thanks{This text is essentially
    the Technical Report MIP-9702 of the Universit\"at Passau, Germany,
    a revised version of which has appeared in the Proceedings of the
    ISSAC 97. Some few references to former websites for distributing
    Guardian and Redlog have been removed.}}
\author{Andreas Dolzmann\\
  {\tt andreas@dolzmann.de} \and
  Thomas Sturm\\
  Departamento de Matem\'aticas, Estad\'istica y Computaci\'on\\
  Universidad de Cantabria, Santander, Spain\\
  \texttt{sturmt@unican.es, sturm@redlog.eu}}
\date{}
\maketitle
%
\begin{abstract}
Computer algebra systems typically drop some degenerate cases when
evaluating expressions, e.g., $x/x$ becomes $1$ dropping the case
$x=0$. We claim that it is feasible in practice to compute also the
degenerate cases yielding {\em guarded expressions}. We work over real
closed fields but our ideas about handling guarded expression can be
easily transferred to other situations. Using formulas as guards
provides a powerful tool for heuristically reducing the combinatorial
explosion of cases: equivalent, redundant, tautological, and
contradictive cases can be detected by simplification and quantifier
elimination. Our approach allows to simplify the expressions on the
basis of simplification knowledge on the logical side. The method
described in this paper is implemented in the {\sc reduce} package
{\sc guardian}.
\end{abstract}
%
\section{Introduction}
It is meanwhile a well-known fact that evaluations obtained with the
interactive use of computer algebra systems ({\sc cas}) are not
entirely correct in general. Typically, some degenerate cases are
dropped. Consider for instance the evaluation
$$
\frac{x^2}{x}=x,
$$
which is correct only if $x\neq0$.
The problem here is that {\sc cas} consider variables to be
transcendental elements. The user, in contrast, has in mind variables
in the sense of logic. In other words: The user does not think of
rational functions but of terms.

Next consider the valid expression
$$
\frac{\sqrt{x}+\sqrt{-x}}{x}.
$$
It is meaningless over the reals. {\sc Cas} often offer no choice than
to interprete surds over the complex numbers even if they distinguish
between a {\em real} and a {\em complex} mode.

Corless and Jeffrey~\cite{CorlessJeffrey:92} have examined the
behavior of a number of {\sc cas} with such input data. They come to
the conclusion that simultaneous computation of all cases is exemplary
but not feasible due to the combinatorial explosion of cases to be
considered. Therefore, they suggest to ignore the degenerate cases but
to provide the assumptions to the user on request. We claim, in
contrast, that it is in fact feasible to compute all possible cases.

Our setting is as follows: Expressions are evaluated to {\em guarded
expressions} consisting of possibly several conventional expressions
guarded by quantifier-free formulas. For the above examples, we would
obtain
$$
\begin{gex}
\gc{x\neq0}&\gc{x}
\end{gex},\quad
\begin{gex}
\gc{\false}&\gc{\frac{\sqrt{x}+\sqrt{-x}}{x}}
\end{gex}.
$$
As the second example illustrates, we are working in ordered fields,
more precisely in real closed fields. The handling of guarded
expressions as described in this paper can, however, be easily
transferred to other situations.

Our approach can also deal with redundant guarded expressions, such as
$$
\begin{gex}
\gc{\true} & \gc{|x|-x}\\
x\geq0 & 0\\
x<0 & -2x
\end{gex}
$$
which leads to algebraic simplification techniques based on logical
simplification as proposed by Davenport and
Faure \cite{DavenportFaure:94}.

We use {\em formulas} over the language of ordered rings as guards.
This provides powerful tools for heuristically reducing the
combinatorial explosion of cases: equivalent, redundant, tautological,
and contradictive cases can be detected by {\em
simplification}~\cite{DolzmannSturm:95} and {\em quantifier
elimination}~\cite{Tarski:48,Collins:75,Weispfenning:88,LoosWeispfenning:93,Weispfenning:96,Weispfenning:94}.
In certain situations, we will allow the formulas also to contain
extra functions such as $\sqrt{\cdot}$ or $|\cdot|$. Then we take care
that there is no quantifier elimination applied.

Simultaneous computation of several cases concerning certain
expressions being zero or not has been extensively investigated as
{\em dynamic
evaluation}~\cite{GomezDiaz:93,DuvalReynaud:94,DuvalReynaud:94a,
BroadberryGomezDiazWatt:95}. It has also been extended to real closed
fields~\cite{DuvalGonzalesVega:93}. The idea behind the development of
these methods is of a more theoretical nature than to overcome the
problems with the interactive usage of {\sc cas} sketched above: one
wishes to compute in algebraic (or real) extension fields of the
rationals. Guarded expressions occur naturally when solving problems
parametrically. Consider, e.g., the {\em Gr\"obner systems} used
during the computation of {\em comprehensive Gr\"obner bases}
\cite{Weispfenning:92}.

The algorithms described in this paper are implemented in the {\sc
reduce} package {\sc guardian}. It is based on the {\sc
reduce}~\cite{HearnFitch:95,Melenk:95} package {\sc
redlog}~\cite{DolzmannSturm:96,DolzmannSturm:96a} implementing a
formula data type with corresponding algorithms, in particular
including simplification and quantifier elimination.
% Both {\sc guardian} and {\sc redlog} are available on the {\sc
%   www}.\footnote{{\tt http://www.fmi.uni-passau.de/\~{}redlog/}}

\section{An outline of our method}
\subsection{Guarded expressions}
A {\em guarded expression} is a scheme
$$
\begin{gex}
\gc{\gamma_0} & \gc{t_0}\\
\gamma_1 & t_1\\
\vdots&\vdots\\
\gamma_n& t_n
\end{gex}
$$
where each $\gamma_i$ is a quantifier-free formula, the {\em guard},
and each $t_i$ is an associated {\em conventional expression}. The
idea is that some $t_i$ is a valid interpretation iff $\gamma_i$
holds. Each pair $(\gamma_i,t_i)$ is called a {\em case}.

The first case $(\gamma_0,t_0)$ is the {\em generic} case: $t_0$ is
the expression the system would compute without our package, and
$\gamma_0$ is the corresponding guard.

The guards $\gamma_i$ need neither exclude one another, nor do we
require that they form a complete case distinction. We shall, however,
assume that all cases covered by a guarded expression are already
covered by the generic case; in other words:
\begin{equation}
\bigwedge_{i=1}^n(\gamma_i\longrightarrow\gamma_0).\label{gencoversall}
\end{equation}

Consider the following evaluation of $|x|$ to a guarded expression:
$$
\begin{gex}
\gc{\true} & \gc{|x|}\\
x\geq0 & x\\
x<0 & -x
\end{gex}.
$$
Here the non-generic cases already cover the whole domain. The
generic case is in some way {\em redundant}. It is just present for
keeping track of the system's default behavior. Formally we have
\begin{equation}
\Bigl(\bigvee_{i=1}^n\gamma_i\Bigr)\longleftrightarrow\gamma_0.
\label{formalredund}
\end{equation}
As an example for a non-redundant, i.e., {\em necessary} generic case
we have the evaluation of the reciprocal $\frac{1}{x}$:
$$
\begin{gex}
\gc{x\neq0}& \gc{\frac{1}{x}}
\end{gex}.
$$

In every guarded expression, the generic case is explicitly marked as
either necessary or redundant. The corresponding tag is inherited
during the evaluation process. Unfortunately it can happen that
guarded expressions satisfy~(\ref{formalredund}) without being tagged
redundant, e.g., specialization of
$$
\begin{gex}
\gc{\true}&\gc{\sin x}\\
x=0&0
\end{gex}
$$
to $x=0$ if the system cannot evaluate $\sin(0)$. This does not happen
if one claims for necessary generic cases to have, as the reciprocal
above, no alternative cases at all. Else, in the sequel ``redundant
generic case'' has to be read as ``tagged redundant.''

With guarded expressions, the evaluation splits into two independent
parts: {\em Algebraic evaluation} and a subsequent {\em
simplification} of the guarded expression obtained.
%
\subsection{Guarding schemes}
In the introduction we have seen that certain operators introduce case
distinctions. For this, with each operator $f$ there is a {\em
guarding scheme} associated providing information on how to map
$f(t_1,\ldots,t_m)$ to a guarded expression provided that one does not
have to care for the argument expressions $t_1$, \dots,~$t_m$. In the
easiest case, this is a rewrite rule
$$
f(a_1,\ldots,a_m)\to G(a_1,\ldots,a_m).
$$
The actual terms $t_1$, \dots,~$t_m$ are simply substituted for the
formal symbols $a_1$, \dots,~$a_m$ into the generic guarded expression
$G(a_1,\ldots,a_m)$. We give some examples:
\begin{eqnarray}
\frac{a_1}{a_2} & \to &
\begin{gex}
\gc{a_2\neq 0} & \gc{\frac{a_1}{a_2}}
\end{gex}\nonumber\\
\sqrt{a_1} & \to &
\begin{gex}
\gc{a_1\geq 0} & \gc{\sqrt{a_1}}
\end{gex}\nonumber\\
\sign(a_1) & \to &
\begin{gex}
\gc{\true} & \gc{\sign(a_1)}\\
a_1>0 & 1\\
a_1=0 & 0\\
a_1<0 & -1
\end{gex}\nonumber\\
|a_1| & \to &
\begin{gex}
\gc{\true} & \gc{|a_1|}\\
a_1\geq0 & a_1\\
a_1<0 & -a_1
\end{gex}\label{absrewrite}
\end{eqnarray}

For functions of arbitrary arity, e.g., $\min$ or $\max$, we formally
assume infinitely many operators of the same name. Technically, we
associate a procedure parameterized with the number of arguments $m$
that generates the corresponding rewrite rule. As ${\tt
min\_scheme(2)}$ we obtain, e.g.,
\begin{eqnarray}
\min(a_1,a_2) & \to &
\begin{gex}
\gc{\true} & \gc{\min(a_1,a_2)}\\
a_1\leq a_2 & a_1\\
a_2\leq a_1 & a_2
\end{gex}\label{binminscheme},
\end{eqnarray}
while for higher arities there are more case distinctions necessary.

For later complexity analysis, we state the concept of a guarding
scheme formally: a guarding scheme for an $m$-ary operator $f$ is a
map
$$
\gscheme_f: \E^m \to \GE
$$
where $\E$ is the set of expressions, and $\GE$ is the set of guarded
expressions. This allows to split $f(t_1,\ldots,t_m)$ in dependence
on the form of the parameter expressions $t_1$, \dots,~$t_m$.
%
\subsection{Algebraic evaluation}\label{algeval}
\subsubsection{Evaluating conventional expressions}
The evaluation of conventional expressions into guarded expressions is
performed recursively: Constants $c$ evaluate to
$$
\begin{gex}
\gc{\true} & \gc{c}
\end{gex}.
$$
For the evaluation
of $f(e_1,\ldots,e_m)$ the argument expressions $e_1$, \ldots, $e_m$
are recursively evaluated to guarded expressions
\begin{equation}
e_i'=\begin{gex}
\gc{\gamma_{i0}} & \gc{t_{i0}}\\
\gamma_{i1} & t_{i1}\\
\vdots & \vdots\\
\gamma_{in_i} & t_{in_i}\end{gex}\quad\mbox{for}\quad 1\leq i\leq m.
\label{eprimes}
\end{equation}

Then the operator $f$ is ``moved inside'' the $e_i'$ by combining all
cases, technically a simultaneous Cartesian product computation of
both the sets of guards and the sets of terms:
\begin{equation}
\Gamma=\prod_{i=1}^m\{\gamma_{i0},\ldots,\gamma_{in_i}\},\quad
T=\prod_{i=1}^m\{t_{i0},\ldots,t_{in_i}\}.
\label{cartprod}
\end{equation}
This leads to the intermediate result
\begin{equation}
\begin{gex}
\gc{\gamma_{10}\land\dots\land\gamma_{m0}}&
\gc{f(t_{10},\dots,t_{m0})}\\
\vdots&\vdots\\
\gamma_{1n_1}\land\dots\land\gamma_{m0}&
f(t_{1n_1},\dots,t_{m0})\\
\vdots&\vdots\\
\gamma_{1n_1}\land\dots\land\gamma_{mn_m}&
f(t_{1n_1},\dots,t_{mn_m})
\end{gex}.
\label{intermediate}
\end{equation}
The new generic case is exactly the combination of the generic cases
of the $e_i'$. It is redundant if at least one of these combined cases
is redundant.

Next, all non-generic cases containing at least one {\em redundant}
generic constituent $\gamma_{i0}$ in their guard are deleted. The
reason for this is that generic cases are only used to keep track of
the system default behavior. All other cases get the status of a
non-generic case even if they contain necessary generic constituents
in their guard.

At this point, we apply the guarding scheme of $f$ to all remaining
expressions $f(t_{1i_1},\ldots,t_{mi_m})$ in the
form~(\ref{intermediate}) yielding a nested guarded expression
\begin{equation}
\begin{gex}
\gc{\Gamma_0} &
\begin{gex}
\gc{\delta_{00}} & \gc{u_{00}}\\ \vdots & \vdots \\ \delta_{0k_0} & u_{0k_0}
\end{gex}\\
\vdots & \vdots\\
\Gamma_N &
\begin{gex}
\gc{\delta_{N0}} & \gc{u_{N0}}\\ \vdots & \vdots \\ \delta_{Nk_N} & u_{Nk_N}
\end{gex}
\end{gex},\label{nestedge}
\end{equation}
which can be straightforwardly resolved to a guarded expression
$$
\begin{gex}
\gc{\Gamma_0\land\delta_{00}} & \gc{u_{00}}\\
\vdots & \vdots\\
\Gamma_0\land\delta_{0k_0} & u_{0k_0}\\
\vdots & \vdots\\
\Gamma_N\land\delta_{N0} & u_{N0}\\
\vdots & \vdots\\
\Gamma_N\land\delta_{Nk_N} & u_{Nk_N}
\end{gex}.
$$
This form is treated analogously to the form~(\ref{intermediate}): The
new generic case $(\Gamma_0\land\delta_{00},u_{00})$ is redundant if
at least one of $\bigl(\Gamma_0,f(t_{10},\dots,t_{m0})\bigr)$ and
$(\delta_{00},u_{00})$ is redundant. Among the non-generic cases all
those containing redundant generic constituents in their guard are
deleted, and all those containing necessary generic constituents in
their guard get the status of an ordinary non-generic case.

Finally the standard evaluator of the system---{\tt reval} in the case
of {\sc reduce}---is applied to all contained expressions, which
completes the algebraic part of the evaluation.
%
\subsubsection{Evaluating guarded expressions}
The previous section was concerned with the evaluation of pure
conventional expressions into guarded expressions. Our system
currently combines both conventional and guarded expressions. We are
thus faced with the problem of treating guarded subexpressions during
evaluation.

When there is a {\em guarded} subexpression $e_i$ detected during
evaluation, all contained expressions are recursively evaluated to
guarded expressions yielding a nested guarded expression of the
form~(\ref{nestedge}). This is resolved as described above yielding
the evaluation subresult $e_i'$.

As a special case, this explains how guarded expressions are
(re)evaluated to guarded expressions.
%
\subsection{Example}
We describe the evaluation of the expression $\min(x,|x|)$. The first
argument $e_1=x$ evaluates recursively to
\begin{equation}
e_1'=\begin{gex} \gc{\true} & \gc{x} \end{gex}
\label{evalx}
\end{equation}
with a necessary generic case. The nested $x$ inside $e_2=|x|$ evaluates
to the same form~(\ref{evalx}). For obtaining $e_2'$, we apply the
guarding scheme~(\ref{absrewrite}) of the absolute value to the only
term of~(\ref{evalx}) yielding
$$
\begin{gex} \gc{\true} & \begin{gex}
\gc{\true} & \gc{|x|}\\
x\geq 0 & x\\
x<0 & -x
\end{gex}
\end{gex},
$$
where the inner generic case is redundant. This form is resolved to
$$
e_2'=\begin{gex}
\gc{\true\land\true} & \gc{|x|}\\
\true\land x\geq 0 & x\\
\true\land x<0 & -x
\end{gex}
$$
with a redundant generic case. The next step is the combination of
cases by Cartesian product computation. We obtain
$$
\begin{gex}
\gc{\true\land(\true\land\true)} & \gc{\min(x,|x|)}\\
\true\land(\true\land x\geq0) & \min(x,x)\\
\true\land(\true\land x<0) & \min(x,-x)
\end{gex},
$$
which corresponds to~(\ref{intermediate}) above. For the outer $\min$,
we apply the guarding scheme~(\ref{binminscheme}) to all terms
yielding the nested guarded expression
$$
\begin{gex}
\gc{\true\land(\true\land\true)} & \begin{gex}
\gc{\true} & \gc{\min(x,|x|)}\\
x\leq |x| & x\\
|x|\leq x & |x|
\end{gex}\\
\true\land(\true\land x\geq0) & \begin{gex}
\gc{\true} & \gc{\min(x,x)}\\
x\leq x & x\\
x\leq x & x
\end{gex}\\
\true\land(\true\land x<0) & \begin{gex}
\gc{\true} & \gc{\min(x,-x)}\\
x\leq -x & x\\
-x\leq x & -x
\end{gex}
\end{gex},
$$
which is in turn resolved to
$$
\begin{gex}
\gc{(\true\land(\true\land\true))\land\true} & \gc{\min(x,|x|)}\\
(\true\land(\true\land\true))\land x\leq |x| & x\\
(\true\land(\true\land\true))\land |x|\leq x & |x|\\
(\true\land(\true\land x\geq0))\land\true & \min(x,x)\\
(\true\land(\true\land x\geq0))\land x\leq x & x\\
(\true\land(\true\land x\geq0))\land x\leq x & x\\
(\true\land(\true\land x<0))\land\true & \min(x,-x)\\
(\true\land(\true\land x<0))\land x\leq -x & x\\
(\true\land(\true\land x<0))\land -x\leq x & -x
\end{gex}.
$$
From this, we delete the two non-generic cases obtained by combination
with the redundant generic case of the $\min$. The final result of the
algebraic evaluation step is the following:
\begin{equation}
\begin{gex}
\gc{(\true\land(\true\land\true))\land\true} & \gc{\min(x,|x|)}\\
(\true\land(\true\land\true))\land x\leq |x| & x\\
(\true\land(\true\land\true))\land |x|\leq x & |x|\\
(\true\land(\true\land x\geq0))\land x\leq x & x\\
(\true\land(\true\land x\geq0))\land x\leq x & x\\
(\true\land(\true\land x<0))\land x\leq -x & x\\
(\true\land(\true\land x<0))\land -x\leq x & -x
\end{gex}.\label{example}
\end{equation}
\subsection{Worst-case complexity}
Our measure of complexity $|G|$ for guarded expressions $G$ is the
number of contained cases:
$$
\left|\begin{gex}
\gc{\gamma_0} & \gc{t_0}\\
\gamma_1 & t_1\\
\vdots&\vdots\\
\gamma_n& t_n
\end{gex}\right|=n+1.
$$

As in Section~\ref{algeval}, consider an $m$-ary operator $f$,
guarded expression arguments $e_1'$, \dots,~$e_m'$ as in
equation~(\ref{eprimes}), and the Cartesian product $T$ as in
equation~(\ref{cartprod}). Then
\begin{eqnarray*}
\lefteqn{
|f(e_1',\ldots,e_m')| \leq  \sum_{(t_1,\dots,t_m)\in
T}|\gscheme_f(t_1,\dots,t_m)|}\\
& &{}\leq  \max_{(t_1,\ldots,t_m)\in
T}|\gscheme_f(t_1,\ldots,t_m)|\cdot \#T\\
& & {}=  \max_{(t_1,\ldots,t_m)\in
T}|\gscheme_f(t_1,\ldots,t_m)|\cdot \prod_{j=1}^m|e_j'|\\
& & {}\leq  \max_{(t_1,\ldots,t_m)\in
T}|\gscheme_f(t_1,\ldots,t_m)|\cdot\bigl(\max_{1\leq j\leq m}|e_j'|\bigr)^m.
\end{eqnarray*}

In the important special case that the guarding scheme of $f$ is a
rewrite rule $f(a_1,\ldots,a_m)\to G$, the above complexity
estimation simplifies to
$$
|f(e_1',\ldots,e_m')| \leq  |G|\cdot \prod_{j=1}^m|e_j'| \leq  |G|\cdot
\bigl(\max_{1\leq j\leq m}|e_j'|\bigr)^m.
$$
In other words: $|G|$ plays the role of a factor, which, however,
depends on $f$, and $|f(e_1',\ldots,e_m')|$ is polynomial in the size
of the $e_i$ but exponential in the arity of $f$.

%
\subsection{Simplification}
In view of the increasing size of the guarded expressions coming into
existence with subsequent computations, it is indispensable to apply
simplification strategies. There are two different algorithms involved
in the simplification of guarded expressions:
\begin{enumerate}
\item
A {\em formula simplifier} mapping quantifier-free formulas to
equivalent simpler ones.
\item
Effective {\em quantifier elimination} for real closed fields
over the language of ordered rings.
\end{enumerate}

It is not relevant, which simplifier and which quantifier elimination
procedure is actually used. We use the formula simplifier described
in~\cite{DolzmannSturm:95}. Our quantifier elimination uses test point
methods developed by
Weispfenning~\cite{Weispfenning:88,LoosWeispfenning:93,Weispfenning:96}.
It is restricted to formulas obeying certain degree restrictions
wrt.~the quantified variables. As an alternative, {\sc redlog}
provides an interface to Hong's {\sc qepcad} quantifier elimination
package \cite{Hong:93}. Compared to the simplification, the
quantifier elimination is more time consuming. It can be turned off by
a {\em switch}.

The following simplification steps are applied in the given order:
%
\paragraph{Contraction of cases} This is restricted to the
non-generic cases of the considered guarded expression. We contract
different cases containing the same terms:
$$
\begin{gex}
\gc{\gamma_0}&\gc{t_0}\\
\vdots & \vdots\\
\gamma_i & t_i\\
\vdots & \vdots\\
\gamma_j & t_i\\
\vdots & \vdots
\end{gex}\quad\mbox{becomes}\quad
\begin{gex}
\gc{\gamma_0}&\gc{t_0}\\
\vdots & \vdots\\
\gamma_i\lor\gamma_j & t_i\\
\vdots & \vdots\\
\end{gex}.
$$
\paragraph{Simplification of the guards} The simplifier is applied to
all guards replacing them by simplified equivalents. Since our
simplifier maps $\gamma\lor\gamma$ to $\gamma$, this together with the
contraction of cases takes care for the deletion of duplicate cases.

\paragraph{Keep one tautological case} If the guard of some
non-generic case becomes ``$\true$,'' we delete all other non-generic
cases. Else, if quantifier elimination is turned on, we try to detect
a tautology by eliminating the universal closures
$\underline\forall\gamma$ of the guards $\gamma$. This quantifier
elimination is also applied to the guards of generic cases. These are,
in case of success, simply replaced by ``$\true$'' without deleting
the case.

\paragraph{Remove contradictive cases} A non-generic case is  deleted if
its guard has become ``$\false$.'' If quantifier elimination is turned
on, we try to detect further contradictive cases by eliminating the
existential closure $\underline\exists\gamma$ for each guard $\gamma$.
This quantifier elimination is also applied to generic cases. In case
of success they are not deleted but their guards are replaced by
``$\false$.'' Our assumption (\ref{gencoversall}) allows then to
delete all non-generic cases.

\subsection{Example revisited}
We turn back to the form~(\ref{example}) of our example $\min(x,|x|)$.
Contraction of cases with subsequent simplification automatically
yields
$$
\begin{gex}
\gc{\true} & \gc{\min(x,|x|)}\\
\true & x\\
|x|-x\leq 0 & |x|\\
\false & -x
\end{gex},
$$
of which only the tautological non-generic case survives:
\begin{equation}
\begin{gex}
\gc{\true} & \gc{\min(x,|x|)}\\
\true & x
\end{gex}.\label{minabs}
\end{equation}

\subsection{Output modes}
An {\em output mode} determines which part of the information
contained in the guarded expressions is provided to the user. {\sc
Guardian} knows the following output modes:

\paragraph{Matrix} Output matrices in the style used throughout this
paper. We have already seen that these can become very large in
general.
\paragraph{Generic case} Output only the generic case.
\paragraph{Generic term} Output only the generic term. Thus the output
is exactly the same as without the guardian package. If the condition
of the generic case becomes ``$\false$,'' a {\em warning} ``{\tt
contradictive situation}'' is given. The computation can, however, be
continued.\bigskip

Note that output modes are restrictions concerning only the output;
internally the system still computes with the complete guarded
expressions.
%
\subsection{A smart mode}\label{smartmode}
Consider the evaluation result~(\ref{minabs}) of $\min(x,|x|)$. The
{\em generic term} output mode would output $\min(x,|x|)$, although
more precise information could be given, namely $x$. The problem is
caused by the fact that generic cases are used to keep track of the
system's default behavior. In this section we will describe an
optional {\em smart mode} with a different notion of {\em generic
case}. To begin with, we show why the problem can not be overcome by a
``smart output mode.''

Assume that there is an output mode which outputs $x$
for~(\ref{minabs}). As the next computation involving~(\ref{minabs})
consider division by $y$. This would result in
$$
\begin{gex}
\gc{y\neq0} & \gc{\frac{\min(x,|x|)}{y}}\\
y\neq0 & \frac{x}{y}
\end{gex}.
$$
Again, there are identic conditions for the generic case and some
non-generic case, and, again, the term belonging to the latter is
simpler. Our mode would output $\frac{x}{y}$. Next, we apply the
absolute value once more yielding
$$
\begin{gex}
\gc{y\neq 0} & \gc{\frac{|\min(x,|x|)|}{|y|}}\\
xy\geq0 \land y\neq0 & \frac{x}{y}\\
xy<0 \land y\neq0 & \frac{-x}{y}
\end{gex}.
$$
Here, the condition of the generic case differs from all other
conditions. We thus have to output the generic term. For the user, the
evaluation of $|\frac{x}{y}|$ results in $\frac{|\min(x,|x|)|}{|y|}$.

The smart mode can turn a non-generic case into a necessary generic
one dropping the original generic case and all other non-generic
cases. Consider, e.g.,~(\ref{minabs}), where the conditions are equal,
and the non-generic term is ``simpler.''

In fact, the relevant relationship between the conditions is that the
generic condition {\em implies} the non-generic one. In other words:
Some non-generic condition is not more restrictive than the generic
condition, and thus covers the whole domain of the guarded expression.
Note that from the implication and~(\ref{gencoversall}) we may
conclude that the cases are even equivalent.

Implication is heuristically checked by simplification. If this fails,
quantifier elimination provides a decision procedure. Note that our
test point methods are incomplete in this regard due to the degree
restrictions. Also it cannot be applied straightforwardly to guards
containing operators that do not belong to the language of ordered
rings.

Whenever we happen to detect a relevant implication, we actually turn
the corresponding non-generic case into the generic one. From our
motivation of non-generic cases, we may expect that non-generic
expressions are generally more convenient than generic ones.
%
\section{Examples}\label{examples}
We give the results for the following computations as they are printed
in the output mode {\em matrix} providing the full information on the
computation result. The reader can derive himself what the output in
the mode {\em generic case} or {\em generic term} would be.
\begin{itemize}
\item Smart mode or not:
$$
\frac{1}{x^2+2x+1}=\begin{gex}
\gc{x+1\neq0}& \gc{\frac{1}{x^2+2x+1}}
		   \end{gex}.
$$
The simplifier recognizes that the denominator is a square.
\item Smart mode or not:
$$
\frac{1}{x^2+2x+2}=\begin{gex}
\gc{\true}& \gc{\frac{1}{x^2+2x+2}}
		   \end{gex}.
$$
Quantifier elimination recognizes the positive definiteness of the
denominator.
\item Smart mode:
$$
|x|-\sqrt{x}=\begin{gex}
\gc{x\geq 0} & \gc{-\sqrt{x}+x}
	     \end{gex}.
$$
The square root allows to forget about the negative branch of the
absolute value.
\item Smart mode:
$$
|x^2+2x+1|=\begin{gex}
\gc{\true}&\gc{x^2+2x+1}
	   \end{gex}.
$$
The simplifier recognizes the positive semidefiniteness of
the argument. {\sc Reduce} itself recognizes squares within absolute values
only in very special cases such as $|x^2|$.
\item Smart mode:
$$
\min\bigl(x,\max(x,y)\bigr)=\begin{gex}
\gc{\true}&\gc{x}
		  \end{gex}.
$$
Note that {\sc reduce} does not know any rules about nested minima and
maxima.
\item
Smart mode:
$$
\min\bigl(\sign(x),-1\bigr)=\begin{gex}
\gc{\true}&\gc{-1}
		  \end{gex}.
$$
\item Smart mode or not:
$$
|x|-x=\begin{gex}
\gc{\true}&\gc{|x|-x}\\
x\geq0&0\\
x<0&-2x
      \end{gex}.
$$
This example is taken from~\cite{DavenportFaure:94}.
\item
Smart mode or not:
$$
\sqrt{1+x^2\relax y^2\relax
(x^2+y^2-3)}={}
\begin{gex}\gc{\true}&\gc{\sqrt{x^4\relax y^2 +
x^2\relax y^4 - 3\relax x^2\relax y^2 + 1}}\end{gex}
$$
The {\em Motzkin polynomial} is recognized to be positive semidefinite
by quantifier elimination.
\end{itemize}
The evaluation time for the last example is 119\,ms on a {\sc sun
sparc-4}. This illustrates that efficiency is no problem with such
interactive examples.
\section{Outlook}
This section describes possible extensions of the {\sc guardian}. The
extensions proposed in Section~\ref{simplification} on simplification
of terms and Section~\ref{background} on a background theory are clear
from a theoretical point of view but not yet implemented.
Section~\ref{integration} collects some ideas on the application of
our ideas to the {\sc reduce} integrator. In this field, there is some
more theoretical work necessary.
%
\subsection{Simplification of terms}\label{simplification}
Consider the expression $\sign(x)x-|x|$. It evaluates to the following
guarded expression:
$$
\begin{gex}
\gc{\true} & \gc{-|x|+\sign(x)x}\\
x\neq 0 & 0\\
x=0 & -x
\end{gex}.
$$
This suggests to substitute $-x$ by $0$ in the third case, which would
in turn allow to contract the two non-generic cases yielding
$$
\begin{gex}
\gc{\true} & \gc{-|x|+\sign(x)x}\\
\true & 0\end{gex}.
$$
In smart mode second case would then become the only generic case.

Generally, one would proceed as follows: If the guard is a conjunction
containing as toplevel equations
$$
t_1=0,\quad \dots,\quad t_k=0,
$$
reduce the corresponding expression modulo the set of univariate
linear polynomials among $t_1$, \dots,~$t_k$.

A more general approach would reduce the expression modulo a Gr\"obner
basis of all the $t_1$, \dots,~$t_k$. This leads, however, to larger
expressions in general.

One can also imagine to make use of non-conjunctive guards in the
following way:
\begin{enumerate}
\item Compute a {\sc dnf} of the guard.
\item Split the case into several cases corresponding to the
conjunctions in the {\sc dnf}.
\item Simplify the terms.
\item Apply the standard simplification procedure to the resulting
guarded expression. Note that it includes {\em contraction of cases}.
\end{enumerate}
According to experiences with similar ideas in the ``Gr\"obner
simplifier'' described in~\cite{DolzmannSturm:95}, this should work
well.
%
\subsection{Background theory}\label{background}
In practice one often computes with quantities guaranteed to lie in a
certain range. For instance, when computing an electrical resistance,
one knows in advance that it will not be negative. For such cases one
would like to have some facility to provide external information to
the system. This can then be used to reduce the complexity of the
guarded expressions.

One would provide a function {\tt assert($\varphi$)}, which asserts
the formula {\tt $\varphi$} to hold. Successive applications of {\tt
assert} establish a {\em background theory}, which is a set of
formulas considered conjunctively. The information contained in the
background theory can be used with the guarded expression computation.
The user must, however, not rely on all the background information to
be actually used.

Technically, denote by $\Phi$ the (conjunctive) background theory. For
the {\em simplification of the guards}, we can make use of the fact
that our simplifier is designed to simplify wrt.~a theory,
cf.~\cite{DolzmannSturm:95}. For proving that some guard $\gamma$ is
{\em tautological}, we try to prove
$$\underline{\forall}(\Phi\longrightarrow\gamma)$$ instead of
$\underline{\forall}\gamma$. Similarly, for proving that $\gamma$ is
{\em contradictive}, we try to disprove
$$\underline{\exists}(\Phi\land\gamma).$$ Instead of proving
$\underline{\forall}(\gamma_1\longrightarrow\gamma_2)$ in smart mode, we try to
prove
$$\underline{\forall}\bigl((\Phi\land\gamma_1)\longrightarrow\gamma_2\bigr).$$

Independently, one can imagine to use a background theory for reducing
the {\em output} with the {\em matrix} output mode. For this, one
simplifies each guard wrt.~the theory at the output stage treating
contradictions and tautologies appropriately. Using the theory for
replacing all cases by one at output stage in a smart mode manner
leads once more to the problem of expressions or even guarded
expressions ``mysteriously'' getting more complicated. Applying the
theory only at the output stage makes it possible to implement a
procedure {\tt unassert($\varphi$)} in a reasonable way.
%
\subsection{Integration}\label{integration}
{\sc Cas} integrators make ``mistakes'' similar to those we have
examined. Consider, e.g., the typical result
$$
\int x^a\,dx=\frac{1}{a+1}x^{a+1}.
$$
It does not cover the case $a=-1$, for which one wishes to obtain
$$
\int x^{-1}\,dx=\ln x.
$$
This problem can also be solved by using guarded expressions for
integration results.

Within the framework of this paper, we would have to associate a
guarding scheme to the integrator {\tt int}. It is not hard to see
that this cannot be done in a reasonable way without putting as much
knowledge into the scheme as into the integrator itself. Thus for
treating integration, one has to modify the integrator to provide
guarded expressions.

Next, we have to clarify what the guarded expression for the above
integral would look like. Since we know that the integral is defined
for all interpretations of the variables, our
assumption~(\ref{gencoversall}) implies that the generic condition be
``$\true$.'' We obtain the guarded expression
$$
\begin{gex}
\gc{\true}& \gc{\int x^a\,dx}\\
a\neq-1& \frac{1}{a+1}x^{a+1}\\
a=-1 & \ln x
\end{gex}.
$$
Note that the redundant generic case does not model the system's
current behavior.
%
\subsection{Combining algebra with logic}
Our method, in the described form, uses an already implemented
algebraic evaluator. In the previous section, we have seen that this
point of view is not sufficient for treating integration
appropriately.

Also our approach runs into trouble with built-in knowledge such as
\begin{eqnarray}
\sqrt{x^2}&=&|x|\label{sqrtrule},\\
\sign(|x|)&=&1\label{signrule}.
\end{eqnarray}
Equation~(\ref{sqrtrule}) introduces an absolute value operator within
a non-generic term without making a case distinction.
Equation~(\ref{signrule}) is wrong when not considering $x$
transcendental. In contrast to the situation with reciprocals, our
technique cannot be used to avoid this ``mistake.'' We obtain
$$
\sign(|x|)=\begin{gex}
\gc{\true} & \gc{1}\\
x\neq0 & 1\\
x=0 & 0
	   \end{gex}
$$
yielding two different answers for $x=0$.

We have already seen in the example Section~\ref{examples} that the
implementation of knowledge such as~(\ref{sqrtrule})
and~(\ref{signrule}) is usually quite {\it ad hoc}, and can be mostly
covered by using guarded expressions. This obesrvation gives rise to
the following question: When designing a new {\sc cas} based on guarded
expressions, how should the knowledge be distributed between the
algebraic side and the logic side?
%
\section{Conclusions}
Guarded expressions can be used to overcome well-known problems with
interpreting expressions as terms. We have explained in detail how to
compute with guarded expressions including several simplification
techniques. Moreover we gain algebraic simplification power from the
logical simplifications. Numerous examples illustrate the power of our
simplification methods. The largest part of our ideas is efficiently
implemented, and the software is published. The outlook on background
theories and on the treatment of integration by guarded expressions
points on interesting future extensions.
\nocite{Bradford:92}

\begin{thebibliography}{10}

\bibitem{Bradford:92}
{Bradford, R.}
\newblock Algebraic simplification of multiple valued functions.
\newblock In {\em Design and Implementation of Symbolic Computation Systems\/}
  (1992), J.~Fitch, Ed., vol.~721 of {\em Lecture Notes in Computer Science},
  Springer-Verlag, pp.~13--21.
\newblock Proceedings of the DISCO 92.

\bibitem{BroadberryGomezDiazWatt:95}
{Broadberry, P., G\'omez-D\'{\i}az, T., and Watt, S.}
\newblock On the implementation of dynamic evaluation.
\newblock In {\em Proceedings of the International Symposium on Symbolic and
  Algebraic Manipulation (ISSAC 95)\/} (New York, N.Y., 1995), A.~Levelt, Ed.,
  ACM Press, pp.~77--89.

\bibitem{Collins:75}
{Collins, G.~E.}
\newblock Quantifier elimination for the elementary theory of real closed
  fields by cylindrical algebraic decomposition.
\newblock In {\em Automata Theory and Formal Languages. 2nd GI Conference\/}
  (Berlin, Heidelberg, New York, May 1975), H.~Brakhage, Ed., vol.~33 of {\em
  Lecture Notes in Computer Science}, Gesellschaft f\"ur Informatik,
  Springer-Verlag, pp.~134--183.

\bibitem{CorlessJeffrey:92}
{Corless, R.~M., and Jeffrey, D.~J.}
\newblock Well \dots it isn't quite that simple.
\newblock {\em ACM SIGSAM Bulletin 26}, 3 (Aug. 1992), 2--6.
\newblock Feature.

\bibitem{DavenportFaure:94}
{Davenport, J.~H., and Faure, C.}
\newblock The ``unknown'' in computer algebra.
\newblock {\em Programmirovanie 1}, 1 (1994).

\bibitem{DolzmannSturm:95}
{Dolzmann, A., and Sturm, T.}
\newblock Simplification of quan\-ti\-fier-free formulas over ordered fields.
\newblock Technical Report MIP-9517, FMI, Universit\"at Passau, D-94030 Passau,
  Germany, Oct. 1995.
\newblock To appear in the Journal of Symbolic Computation.

\bibitem{DolzmannSturm:96}
{Dolzmann, A., and Sturm, T.}
\newblock Redlog---computer algebra meets computer logic.
\newblock Technical Report MIP-9603, FMI, Universit\"at Passau, D-94030 Passau,
  Germany, Feb. 1996.

\bibitem{DolzmannSturm:96a}
{Dolzmann, A., and Sturm, T.}
\newblock Redlog user manual.
\newblock Technical Report MIP-9616, FMI, Universit\"at Passau, D-94030 Passau,
  Germany, Oct. 1996.
\newblock Edition 1.0 for Version 1.0.

\bibitem{DuvalGonzalesVega:93}
{Duval, D., and Gonz\'ales-Vega, L.}
\newblock Dynamic evaluation and real closure.
\newblock In {\em Proceedings of the IMACS Symposium on Symbolic Computation\/}
  (1993).

\bibitem{DuvalReynaud:94}
{Duval, D., and Reynaud, J.-C.}
\newblock Sketches and computation {I}: Basic definitions and static
  evaluation.
\newblock {\em Mathematical Structures in Computer Science 4}, 2 (1994),
  185--238.

\bibitem{DuvalReynaud:94a}
{Duval, D., and Reynaud, J.-C.}
\newblock Sketches and computation {II}: Dynamic evaluation and applications.
\newblock {\em Mathematical Structures in Computer Science 4}, 2 (1994),
  239--271.

\bibitem{GomezDiaz:93}
{G\'omez-D\'{\i}az, T.}
\newblock Examples of using dynamic constructible closure.
\newblock In {\em Proceedings of the IMACS Symposium on Symbolic Computation\/}
  (1993).

\bibitem{HearnFitch:95}
{Hearn, A.~C., and Fitch, J.~P.}
\newblock {\em Reduce User's Manual for Version~3.6}.
\newblock RAND, Santa Monica, CA 90407-2138, July 1995.
\newblock RAND Publication CP78.

\bibitem{Hong:93}
{Hong, H., Collins, G.~E., Johnson, J.~R., and Encarnacion, M.~J.}
\newblock {QEPCAD} interactive version 12.
\newblock Kindly communicated to us by Hoon Hong, Sept. 1993.

\bibitem{LoosWeispfenning:93}
{Loos, R., and Weispfenning, V.}
\newblock Applying linear quantifier elimination.
\newblock {\em The Computer Journal 36}, 5 (1993), 450--462.
\newblock Special issue on computational quantifier elimination.

\bibitem{Melenk:95}
{Melenk, H.}
\newblock Reduce symbolic mode primer.
\newblock In {\em REDUCE 3.6 User's Guide for UNIX}. Konrad-Zuse-Institut,
  Berlin, 1995.

\bibitem{Tarski:48}
{Tarski, A.}
\newblock A decision method for elementary algebra and geometry.
\newblock Tech. rep., University of California, 1948.
\newblock Second edn., rev. 1951.

\bibitem{Weispfenning:88}
{Weispfenning, V.}
\newblock The complexity of linear problems in fields.
\newblock {\em Journal of Symbolic Computation 5}, 1 (Feb. 1988), 3--27.

\bibitem{Weispfenning:92}
{Weispfenning, V.}
\newblock Comprehensive {G}r\"obner bases.
\newblock {\em Journal of Symbolic Computation 14\/} (July 1992), 1--29.

\bibitem{Weispfenning:94}
{Weispfenning, V.}
\newblock Quantifier elimination for real algebra---the cubic case.
\newblock In {\em Proceedings of the International Symposium on Symbolic and
  Algebraic Computation in Oxford\/} (New York, July 1994), ACM Press,
  pp.~258--263.

\bibitem{Weispfenning:96}
{Weispfenning, V.}
\newblock Quantifier elimination for real algebra---the quadratic case and
  beyond.
\newblock To appear in AAECC.

\end{thebibliography}
\end{document}


\chapter*{Conclusion}
\addcontentsline{toc}{chapter}{Conclusion}

In this thesis we have researched possible variations of agglomerative hierarchical clustering algorithms (section~\ref{sec01:hca}) and selected the variant that promised high GPU utilization and low memory requirements (section~\ref{sec03:impl}). Then, we have implemented the Mahalanobis-average hierarchical clustering accelerated on a single GPU (section~\ref{sec03:gmhc}). Finally, we have performed several experiments to measure the properties of the resulting implementation (chapter~\ref{sec04:res}).

The resulting application is implemented within CUDA framework, which should make it useful for scientific computing where CUDA is a de-facto standard. The implementation uses the Centroid Mahalanobis distance (see def.~\ref{def01:cmd}) as the dissimilarity measure, and it can cluster datasets from single-points or with a help of apriori clusters. We have tested the implementation on single-point datasets with sizes from 40K to 800K points and apriori datasets with sizes from 1M to 5M points. Due to the big time and memory requirements of the CPU implementation, datasets were down-sampled. For single-point datasets, the speedup was 60-times for 4K points and 5000-times for 40K. For apriori datasets, the speedup was 8-times for 1M points and 20-times for 2M points. We have also tested the clustering performance of different apriori cluster size and count ratios. We have discovered that clustering time increases faster with higher apriori cluster count than with higher apriori cluster size.

Regarding the comparison of clustering results, the clusterings differed for sin\-gle-point datasets due to the slightly different dissimilarity measures. On the other hand, in case of more frequently used apriori clusters, the clusterings were practically the same.

\subsection*{Future work}

Although the implementation in this thesis is useful and provides good results, there are many minor improvements that can be added.
The main concern of the future work is to implement the remainder of the functionalities of the current MHCA algorithm.

Most importantly, the dissimilarity measure that can provide better clustering of small clusters can be implemented. We can transform a covariance matrix of  these clusters to make it regular. Then it can be properly inverted and used in the Mahalanobis distance formula.

Next, a covariance matrix can be normalized by dividing each element by its discriminant. When used in the distance formula, this transformation outputs the combination of the Mahalanobis and Euclidean distance. The determinant can be computed as a side product of the Cholesky decomposition that can be used to compute the inverse of a covariance matrix.

Although we do not expect it to provide any substantial improvement on reasonable datasets, the work can be further expanded by implementing the Full Mahalanobis distance (see def.~\ref{def01:fmd}). It can cover the cases when CMD does not provide precise dissimilarity measure which can lead to a better clustering results. Naturally, it would come for the price of~a~greater overall time complexity.


\section{Preparing VASP-files before starting ENVISIoN}
Before visualizations can be made of input data from VASP, the user have to make sure that VASP-files are made in correct format. This applies to a couple main files in VASP that the user has specified before their VASP-run and also after their VASP-run. The restrictions on the formating of VASP-files are a byproduct of the fact that ENVISIoN has a couple limitations in it's parsing of VASP-files. These limitations are by no way intentional and they are born from theoretical sources and from the time-restrictive nature of the project development itself.
\subsection{Preparing for bandstructure visualization}

Before deciding to do any visualization of bandstructures at all, be sure that the VASP-files OUTCAR and KPOINTS are available in the VASP-directory you wish to visualize from. Bandstructure visualization can only be made for eight types of brillouin zones if the user wishes to do so. Namely the following: Primitive Cubic (CUB), Body-Centered Cubic (BCC), Face-Centered Cubic (FCC), Primitive Tetragonal (TET), Primitive Hexagonal (HEX), Primitive Orthorhombic (ORC), Primitive Triclinic type 1a/2a (TRI1a/TRI2a) and Primitive Triclinic type 1b/2b (TRI1b/TRI2b). These brillouin zones have fixed symmetry k-points and are specified in an article by Wahyu Setyawan and Stefano Curtarolo \cite{k-points}.

If the user wish to visualize the bandstructure of any other type of brillouin zone, the parser for bandstructures will be unable to interpret the data from VASP.

Another requirement for a successful visualization of the bandstructure of a brillouin zone type is to format the KPOINTS-file in a specific way such as is illustrated in figure \ref{fig:VASP_band} below. Observe how every two coordinates represents a line between two high-symmetry points as chosen by the $"$line$"$ in the third row, and how each of these pair of coordinates are separated by a blank row for aesthetical reasons. The parser can only handle reciprocal high-symmetry points so make sure that the fourth line in the KPOINTS-file has the word $"$reciprocal$"$ written with no indentation, as shown in the figure.

\begin{figure}[H]
    \centering
    \includegraphics[scale = 0.53]{images/usermanual_band_TET.png}
    \caption{KPOINTS-file for bandstructure calculation of a TET brillouin zone.}
    \label{fig:VASP_band}
\end{figure}

\subsection{Preparing for fermi-surface visualization}

Make sure that a KPOINTS-file and a EIGENVAL-file is present in the VASP-directory you want to input in ENVISIoN.

When choosing to visualize fermi-surfaces, make sure that you use the format shown in figure \ref{fig:VASP_fermisurface} for the KPOINTS-file. During visualization of the fermi-surface of a crystal, we want a very big mesh of k-points and an optimal mesh is 10x10x10. Hence make sure that you the fourth row in KPOINTS is at least 10 on each position, as shown in the figure. A very important thing to also note is that the user has to supply the second row with only the a zero, as shown in the figure, as it will force VASP to generate a mesh in the size specified on the fourth row of the file during a VASP-run.

\begin{figure}[H]
    \centering
    \includegraphics[scale = 0.55]{images/usermanual_fermisurface.png}
    \caption{KPOINTS-file for fermi-surface visualization.}
    \label{fig:VASP_fermisurface}
\end{figure}

Another, very important, thing to note is that the fermi-surface visualization requires the flag ISYM in the INCAR-file of VASP to be set to the value -1 before a VASP-run. If ISYM is not set to -1, the parser for Fermi-surface will not be able to extrapolate the k-points that are given by VASP, since they are symmetric. If you strive to improve your visualization of the fermi-surface of a crystal, simply increase each integer on the fourth row on the figure above from 10 and above. Observe that the fifth row must have zeroes in order to generate a mesh centered in a origin of the Monkhorst-Pack, without any shifts from this origin. This is for the sake of avoiding errors in the VASP-run.

\subsection{Preparing for unitcell visualization}
\label{section_unit}

Make sure that the VASP-files POTCAR and POSCAR are available in your VASP-directory before you decide to visualize the unitcell.

For the unitcell visualization, it is very important how you have written the POTCAR-file in relation to the POSCAR-file. Say you have a crystal structure made of three atomic species and you want to do a VASP-run of it. You will first have to find the POTCAR-files for each atomic species, which is supplied by VASP itself. Then you concat them in order to create a single POTCAR-file which represent all atomic species in a single file. Now the dangerous and very common mistake to do in this case is that you concat the separate atomic species POTCARs in an order that does not consist with the order written in the POSCAR-file. This can lead to wrong conclusions of your VASP-calculations. Figure \ref{fig:VASP_unit} examplifies the correct way of concatting POTCARs.

\begin{figure}[H]
    \centering
    \includegraphics[scale = 0.48]{images/usermanual_unit_TET.png}
    \caption{In this example with the crystal TiO2, the POSCAR-file has Oxygen written as the first atomic species (red box) and hence the common POTCAR has the pseudopotentials of Oxygen atoms concat first and the pseudopotentials of titanium atoms second.}
    \label{fig:VASP_unit}
\end{figure}

To successfully visualize the unitcell, the user has to make sure that there is no indentation in the row where the user specifies if the atomic positions are given in direct or cartesian coordinates in the POSCAR-file. There is also a requirement that all values in the POSCAR-file, besides the row which supplies the number of atoms per atomic species (which are given in integer form), are given in decimal form (float form). Figure \ref{fig:VASP_unit_1} below shows the correct format of POSCAR in the example with Rutile. Notice how the order of the atomic positions are consistent with the order of the atomic species, which is emphasized by the red box for the O-atom positions and the blue box for the Ti-atom positions.

\begin{figure}[H]
    \centering
    \includegraphics[scale = 0.50]{images/usermanual_unit_TET_2.png}
    \caption{Example of the correct format of POSCAR-file with the crystal TiO2.}
    \label{fig:VASP_unit_1}
\end{figure}

\subsection{Preparing for DOS visualization}

Make sure that the VASP-files POTCAR, POSCAR, INCAR and DOSCAR are available in your VASP-directory before you decide to visualize the density of states. \\

To ensure an error-free visualization of DOS, follow the directions mentioned in the section \emph{\nameref{section_unit}}, since unitcell data is acquired simultaneously with DOS data with the VASP parser for DOS visualization.

\subsection{Preparing for electron density visualization}

Make sure that the VASP-files POTCAR, POSCAR and CHG are available in your VASP-directory before you decide to visualize the electron density. In the VASP-file INCAR, make sure that LCHARG flag is not set to False, in order to force VASP to write into the CHG-file during the VASP-run. Also make sure that ISYM flag in the VASP-file INCAR is not set to -1 before a VASP-run, which is done for the fermi-surface visualization, as this can cause a wrong visualization of the electron density.\\

To ensure an error-free visualization of electron density, follow the directions mentioned in the section \emph{\nameref{section_unit}}, since unitcell data is acquired simultaneously with electron density data with the VASP parser for electron density visualization.


\documentclass[12pt]{cdblatex}
\usepackage{fancyhdr}
\usepackage{footer}

\begin{document}

% ============================================================================================
\section*{Example 15 Verifying the BSSN equations}

\CdbSetup{action=hide}

\begin{cadabra}
   {a,b,c,d,e,f,i,j,k,l,m,n,o,p,q,r,s,u#}::Indices(position=independent,values={t,x,y,z}).
   {t,x,y,z}::Coordinate.

   \partial{#}::PartialDerivative.
   D{#}::Derivative.
   DBar{#}::Derivative.

   g_{a b}::Symmetric.
   g^{a b}::Symmetric.
   g_{a}^{b}::KroneckerDelta.
   g^{a}_{b}::KroneckerDelta.

   gBar_{a b}::Symmetric.
   gBar^{a b}::Symmetric.
   gBar_{a}^{b}::KroneckerDelta.
   gBar^{a}_{b}::KroneckerDelta.

   def check (objA,objB):

       tmp := @(objA) - @(objB).

       distribute     (tmp)
       sort_product   (tmp)
       rename_dummies (tmp)
       canonicalise   (tmp)

       return tmp

   import cdblib

   # ---------------------------------------------
   check000A = cdblib.get ('check000','expected/example-15.json')
   check001A = cdblib.get ('check001','expected/example-15.json')

   # ---------------------------------------------
   check000B = cdblib.get ('check000','output/example-15.json')
   check001B = cdblib.get ('check001','output/example-15.json')

   # ---------------------------------------------
   diff000 = check (check000A,check000B)   # cdb (ex-15.diff000,diff000)
   diff001 = check (check001A,check001B)   # cdb (ex-15.diff001,diff001)

\end{cadabra}

% \clearpage

\begin{dgroup*}
   \Dmath*{\cdb*{ex-15.diff000}}
   \Dmath*{\cdb*{ex-15.diff001}}
\end{dgroup*}

\end{document}


\section{Algorithms}
\label{sec:appendix-algorithms}

Complementing the information presented in Section \ref{sec:algorithms}, Table \ref{table:algorithms}
gives a complete overview of all algorithms.

\begin{table*}[t]
    \centering
    {\scriptsize
        \begin{tabular}{r | c c c | c c | c c c c c c | c c c c | c c | c}
            & \rot{Reference} & \rot{Year} & \rot{Citations} & \rot{Categorization} & \rot{Implementation} & \rot{GRAY} & \rot{RGB} & \rot{Lab} & \rot{Luv} & \rot{HSV} & \rot{YCrCb} & \rot{\#Parameters} & \rot{\#Superpixels} & \rot{\#Iterations} & \rot{Compactness} & \rot{Depth} & \rot{Edges} & \\\hline
           \W & \cite{Meyer:1992} & 1992 & 234 & watershed & C/C++ & -- & \bcheckmark & \checkmark & \checkmark & \checkmark & \checkmark & 1 & \checkmark & -- & -- & -- & -- & \ref{plot:w}\\
           \EAMS & \cite{ComaniciuMeer:2002} & 2002 & 9631 & density & MatLab/C & -- & \bcheckmark & -- & \checkmark & -- & -- & 2 & -- & -- & -- & -- & \checkmark & \ref{plot:eams}\\
           \NC & \cite{RenMalik:2003} & 2003 & 996 & graph & MatLab/C & -- & \bcheckmark & -- & -- & -- & -- & 3 & \checkmark & -- & -- & -- & -- & \ref{plot:nc}\\
           \FH & \cite{FelzenswalbHuttenlocher:2004} & 2004 & 4144 & graph & C/C++ & -- & \bcheckmark & -- & -- & -- & -- & 3 & -- & -- & -- & -- & -- & \ref{plot:fh}\\
           \reFH & \multicolumn{3}{c|}{\dittostraight} & \multicolumn{1}{c}{\dittostraight} & C/C++ & -- & \bcheckmark & -- & -- & -- & -- & 3 & -- & -- & -- & -- & -- & \ref{plot:refh}\\
           \RW & \cite{GradyFunkaLea:2004,Grady:2006} & 2004 & 189 + 1587 & graph & MatLab/C & -- & \bcheckmark & -- & -- & -- & -- & 2 & \checkmark & -- & -- & -- & -- & \ref{plot:rw}\\
           \QS & \cite{VedaldiSoatto:2008} & 2008 & 376 & density & MatLab/C & -- & \checkmark & \bcheckmark & -- & -- & -- & 3 & -- & -- & -- & -- & -- & \ref{plot:qs}\\
           \PF & \cite{DruckerMacCormick:2009} & 2009 & 18 & path & Java & -- & \bcheckmark & -- & -- & -- & -- & 2 & \checkmark & -- & -- & -- & -- & \ref{plot:pf}\\
           \TP & \cite{LevinshteinStereKutulakosFleetDickinsonSiddiqi:2009} & 2009 & 559 & contour evolution & MatLab/C & -- & \bcheckmark & -- & -- & -- & -- & 4 & \checkmark & -- & -- & -- & -- & \ref{plot:tp}\\
           \CIS & \cite{VekslerBoykovMehrani:2010} & 2010 & 223 & graph & C/C++ & \bcheckmark & \checkmark & -- & -- & -- & -- & 4 & \checkmark & \checkmark & -- & -- & -- & \ref{plot:cis}\\
           \SLIC & \cite{AchantaShajiSmithLucchiFuaSuesstrunk:2010,AchantaShajiSmithLucchiFuaSuesstrunk:2012} & 2010 & 438 + 1843 & clustering & C/C++ & -- & \checkmark & \bcheckmark & -- & -- & -- & 4 & \checkmark & \checkmark & \checkmark & -- & -- & \ref{plot:slic}\\
           \vlSLIC & \multicolumn{3}{c|}{\dittostraight} & \multicolumn{1}{c}{\dittostraight} & C/C++ & -- & \bcheckmark & -- & -- & -- & -- & 4 & \checkmark & \checkmark & \checkmark & -- & -- & \ref{plot:vlslic}\\
           \CRS & \cite{MesterConradGuevara:2011,ConradMertzMester:2013} & 2011 & 14 + 4 & energy optimization & C/C++ & \checkmark & \checkmark & -- & -- & -- & \bcheckmark & 4 & \checkmark & \checkmark & \checkmark & -- & -- & \ref{plot:crs}\\
           \ERS & \cite{LiuTuzelRamalingamChellappa:2011} & 2011 & 216 & graph & C/C++ & -- & \bcheckmark & -- & -- & -- & -- & 3 & \checkmark & -- & -- & -- & -- & \ref{plot:ers}\\
           \PB & \cite{ZhangHartleyMashfordBurn:2011} & 2011 & 36 & graph & C/C++ & -- & \bcheckmark & -- & -- & -- & -- & 3 & \checkmark & -- & -- & -- & -- & \ref{plot:pb}\\
           \DASP & \cite{WeikersdorferGossowBeetz:2012} & 2012 & 22 & clustering & C/C++ & -- & \bcheckmark & -- & -- & -- & -- & 5 & \checkmark & \checkmark & \checkmark & -- & \checkmark & \ref{plot:dasp}\\
           \SEEDS & \cite{VanDenBerghBoixRoigCapitaniVanGool:2012} & 2012 & 98 & energy optimization & C/C++ & -- & \checkmark & \bcheckmark & -- & \checkmark & -- & 6 & \checkmark & \checkmark & -- & -- & -- & \ref{plot:seeds}\\
           \reSEEDS & \multicolumn{3}{c|}{\dittostraight} & \multicolumn{1}{c}{\dittostraight} & C/C++ & -- & \bcheckmark & \checkmark &  -- & \checkmark & -- & 6 & \checkmark & \checkmark & \checkmark & -- & -- & \ref{plot:reseeds}\\
           \TPS & \cite{DaiTangHuazhaFuXiaochunCao:2012,HuazhuFuXiaochunCaoDaiTangYahongHanDongXu:2014} & 2012 & 8 + 1 & path & MatLab/C & -- & \bcheckmark & -- & -- & -- & -- & 4 & \checkmark & -- & -- & -- & \checkmark & \ref{plot:tps}\\
           \VC & \cite{WangWang:2012} & 2012 & 36 & clustering & C/C++ & -- & \checkmark & \bcheckmark & -- & -- & -- & 6 & \checkmark & -- & \checkmark & -- & -- & \ref{plot:vc}\\
           \CCS & \cite{TasliCiglaGeversAlatan:2013,TasliCiglaAlatan:2015} & 2013 & 6 + 4 & energy optimization & C/C++ & -- & \checkmark & \bcheckmark & -- & -- & -- & 3 & \checkmark & \checkmark & \checkmark & -- & -- & \ref{plot:ccs}\\
           \VCCS & \cite{PaponAbramovSchoelerWoergoetter:2013} & 2013 & 87 & clustering & C/C++ & -- & \bcheckmark & -- & -- & -- & -- & 4 & -- & -- & \checkmark & \checkmark & -- & \ref{plot:vccs}\\
           \CW & \cite{NeubertProtzel:2014} & 2014 & 11 & watershed & C/C++ & -- & \bcheckmark & -- & -- & -- & -- & 2 & \checkmark & -- & \checkmark & -- & -- & \ref{plot:cw}\\
           \ERGC & \cite{BuyssensGardinRuan:2014,BuyssensToutainElmoatazLezoray:2014} & 2014 & 2 + 1 & contour evolution & C/C++ & -- & \checkmark & \bcheckmark & -- & -- & -- & 3 & \checkmark & -- & \checkmark & -- & -- & \ref{plot:ergc}\\
           %\LRW & \cite{ShenDuWangLi:2014} & 2014 & 18 & graph & MatLab/C & -- & \checkmark & \bcheckmark & -- & -- & -- & 5 & \checkmark & \checkmark & -- & -- & -- & \ref{plot:lrw}\\
           \MSS & \cite{BenesovaKottman:2014} & 2014 & 4 & watershed & C/C++ & -- & \bcheckmark & -- & -- & -- & -- & 5 & \checkmark & -- & -- & -- & -- & \ref{plot:mss}\\
           \preSLIC & \cite{NeubertProtzel:2014} & 2014 & 11 & clustering & C/C++ & -- & \checkmark & \bcheckmark & -- & -- & -- & 4 & \checkmark & \checkmark & \checkmark & -- & -- & \ref{plot:preslic}\\
           \WP & \cite{MachairasDecenciereWalter:2014,MachairesFaesselCardenasPenaChabardesWalterDecenciere:2015} & 2014 & 5 + 8 & watershed & Python & -- & \bcheckmark & -- & -- & -- & -- & 2 & \checkmark & -- & \checkmark & -- & -- & \ref{plot:wp}\\
           \ETPS & \cite{YaoBobenFidlerUrtasun:2015} & 2015 & 6 & energy optimization & C/C++ & -- & \bcheckmark & -- & -- & -- & -- & 5 & \checkmark & \checkmark & \checkmark & -- & -- & \ref{plot:etps}\\
           \LSC & \cite{LiChen:2015} & 2015 & 2 & clustering & C/C++ & -- & \checkmark & \bcheckmark & -- & -- & -- & 4 & \checkmark & \checkmark & \checkmark & -- & -- & \ref{plot:lsc}\\
           \POISE & \cite{HumayunLiRehg:2015} & 2015 & 3 & graph & MatLab/C & -- & \bcheckmark & -- & -- & -- & -- & 5 & \checkmark & -- & -- & -- & \checkmark & \ref{plot:poise}\\
           \SEAW & \cite{StrassburgGrzeszickRothackerFink:2015} & 2015 & 0 & wavelet & MatLab/C & -- & \bcheckmark & -- & -- & -- & -- & 3 & -- & -- & -- & -- & -- & \ref{plot:seaw}
        \end{tabular}
    }
    \caption{List of evaluated superpixel algorithms. First of all we present the
    used acronym (in parts consistent with \cite{AchantaShajiSmithLucchiFuaSuesstrunk:2012}
    and \cite{NeubertProtzel:2012}), the corresponding publication, the year of
    publication and the number of Google Scholar citations as of October 13, 2016.
    We present a coarse categorization which is discussed in Section \ref{sec:algorithms}.
    We additionally present implementation details such as the programming language,
    supported color spaces and provided parameters. The color space used for evaluation is marked by a square.
    \textbf{Best viewed in color.}}
    \label{table:algorithms}
\end{table*}


\documentclass{tufte-handout}
\usepackage{amsmath}
\usepackage[utf8]{inputenc}
\usepackage{mathpazo}
\usepackage{booktabs}
\usepackage{microtype}

\usepackage{tikz}

\pagestyle{empty}

\title{Spanning USA Report}
\author{Alice Cooper and Bob Marley}

\begin{document}
  \maketitle

  \section{Results}

  The following table summarizes our results:\sidenote{Correct the right hand column}

  \bigskip\noindent
  \begin{tabular}{lr}
    \toprule
    Input file & MST total weight \\ \midrule
    USA-highway-miles.txt	 & 17535 \\
    tinyEWG-alpha.txt & 321 \\ \bottomrule
  \end{tabular}

  \bigskip
  The MST we found in tinyEWG-alpha.txt can be drawn like this:\sidenote{Draw the tree, by hand if you want to.
  The planar coordinates of the vertex play no role.}

  \medskip
  \begin{tikzpicture}[
      scale = .5,
      every node/.style = {
        circle, draw, black, inner sep = 1pt, font = \small},
      every path/.style = {gray}
      ]
    \node (A) at (3,1) {A}; % 0
    \node (B) at (2.2,3.8) {B}; % 1
    \node (C) at (5.1,1.8) {C}; % 2
    \node (D) at (4.7,3.8) {D}; % 3
    \node (E) at (0,0) {E}; % 4
    \node (F) at (0,3) {F}; % 5
    \node (G) at (7,0) {G}; % 6
    \node (H) at (2,2) {H}; % 7
    \draw (E)--(F);
    \draw (E)--(H);
    \draw (F)--(H);
    \draw (A)--(H);
    \draw (B)--(F);
    \draw (A)--(E);
    \draw (C)--(D);
    \draw (B)--(H);
    \draw (A)--(C);
    \draw (B)--(C);
    \draw (B)--(D);
    \draw (C)--(H);
    \draw (G)--(C);
    \draw (D)--(G);
    \draw (G)--(A);
    \draw (G)--(E);
    \begin{scope}[every path/.style={ultra thick}]
      \draw(E)--(F);
      \draw(G)--(A);
      \draw(G)--(E);
      \draw(G)--(C);
      \draw(G)--(D);
      \draw(F)--(H);
      \draw(F)--(B);
    \end{scope}
  \end{tikzpicture}

  \section{Implementation details}

  We implemented the algorithm of [$\ldots$], using [$\ldots$].%
  \sidenote{%
    Explain what you did.
    Prim?
    Kruskal?
    Which priority queue?
    How did you check connectivity?
    Be very brief.
    Three sentences are a lot.}
  The total running time for implementation is $O(n^3+\log^2 m)$.\sidenote{%
  Replace as necessary.
  Use $n$ for the number of vertices,
    $m$ for the number of edges in the input graph.}

\end{document}


\documentclass[12pt]{article}
\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}
\usepackage[USenglish]{babel}
\usepackage{a4wide}
\usepackage{relsize}
\usepackage{placeins}
\usepackage{rotating}
\usepackage{mathtools}
\usepackage{lmodern}
\usepackage{color}
\usepackage{url}
\usepackage{hyperref}

\title{\textbf{Multi-Camera Self-Calibration}\\{\large Technical report}}
\author{Wojciech Szęszoł\thanks{\textit{e-mail}:\texttt{ciechowoj@gmail.com}}}
\date{Wrocław, \today}

\include{haste}

\begin{document}

\maketitle

\thispagestyle{empty}
\newpage

\section{Introduction}

There are many applications for multi-camera systems in the computer industry. Motion capture studios use multiple cameras for tracking special markers. Multiple
cameras are used to track the position headsets in emerging VR technology. The systems of
cameras are becoming indispensable piece of modern technology.

The majority of such systems require some kind of calibration before being
ready to provide target functionality. Calibration is the process of
estimating position and orientation of cameras with respect to each other
and to surrounding environment and sometimes the parameters of cameras itself.

There are multiple ways to do the calibration. One way is to exploit the
geometrical relationships between inputs from the cameras itself. This report
describes a simplified implementation of algorithm presented in "A Convenient
Multi-Camera  Self-Calibration for Virtual Environments" paper by Svoboda et al.
\cite{svoboda05}.

The algorithm uses correspondence and position of points seen from different
cameras of the system. The points are created by waving some bright object
(like modified laser pointer or diffuse LED diode). The bright object will be
called a pointer in the rest of this report. A full version of the algorithm is
very robust, it is immune for measurement noise and significant amount of
occlusions (the pointer doesn't have to be visible from all cameras at once).

Images of the pointer seen from different cameras can be easily matched to each
other (if cameras are synchronized, the images seen at the same frame are the
matching ones). It is relatively easy to detect the pointer position on the
image from the camera as it has very high intensity in comparison to the
environment.

\section{Algorithm Outline}

The 3D positions of the pointer across different time moments (on different frames
from the camera  capture) forms a point cloud. The pixel locations of the points
from the point cloud will be  called image projections. Let $q_i^j$ be the
image projection of i-th point from j-th  camera. The image projection has form
$q_i^j = \begin{bmatrix} x_i^j & y_i^j & 1 \end{bmatrix}^T$, where $x_i^j$ and
$y_i^j$ are  pixel coordinates in the system, which has the origin at the center of
the image and which has x and y axes pointing left and up respectively. We can
arrange all such image projections in a   matrix $W$ called measurement matrix.
Some of the fields in the measurement matrix may be empty due to occlusions (a
point can be invisible from the given camera, occluded by some other object or the
procedure that localized the bright spot on the image may fail and not report
any location). Equation~\ref{eq:w1} shows the measurement matrix with some
elements missing (marked as $\times$).

\nmatheq {
    \label{eq:w1}
    W =
    \begin{bmatrix}
        x_0^0  & x_1^0  & x_2^0  & x_3^0  & x_4^0  & x_5^0  & x_6^0  & \hdots & x_n^0 \\
        y_0^0  & y_1^0  & y_2^0  & y_3^0  & y_4^0  & y_5^0  & y_6^0  & \hdots & y_n^0 \\
        1      & 1      & 1      & 1      & 1      & 1      & 1      & \hdots & 1 \\
        x_0^1  & x_1^1  & x_2^1  & \times & x_4^1  & x_5^1  & \times & \hdots & x_n^1 \\
        y_0^1  & y_1^1  & y_2^1  & \times & y_4^1  & y_5^1  & \times & \hdots & y_n^1 \\
        1      & 1      & 1      & \times & 1      & 1      & \times & \hdots & 1 \\
        \vdots & \vdots & \vdots & \vdots & \vdots & \vdots & \vdots &        & \vdots \\
        x_0^m  & x_1^m  & \times & x_3^m  & x_4^m  & x_5^m  & x_6^m  & \hdots & x_n^m \\
        y_0^m  & y_1^m  & \times & y_3^m  & y_4^m  & y_5^m  & y_6^m  & \hdots & y_n^m \\
        1      & 1      & \times & 1      & 1      & 1      & 1      & \hdots & 1 \\
    \end{bmatrix}
}

Lets consider a single point $Q_i$ and a camera matrix $P^j$. Equation
\ref{eq:projection} defines a rescaled image projection of the point $Q_i$ for
the camera $P^j$.

\nmatheq {
    \label{eq:projection}
    \lambda_i^j q_i^j =
    \begin{bmatrix}
        \lambda_i^j x_i^j \\
        \lambda_i^j y_i^j \\
        \lambda_i^j
    \end{bmatrix}
    = P_j Q_i
}

The factors $\lambda_i^j$ are called projective depths. The image projections in
the measurement matrix, that comes as the input of the algorithm have the projective
depths divided out. The measurement matrix $\hat{W}$ with known projective
depths will be called a rescaled measurement matrix. The rescaled measurement
matrix has rank four, if no noise is present. If the projective depths were
known and there was no holes in the rescaled measurement matrix, it could be
factorized into the set of camera matrices $\hat{P}$ and the set of point locations
$\hat{Q}$.  However, the factorization would be only up to some projective
transformation. An additional  Euclidean stratification step is needed to
recover $P$ and $Q$ in the Euclidean space. Equation ~\ref{eq:w2} presents factorization of the rescaled measurement matrix.

\nmatheq {
    \label{eq:w2}
    \hat{W} &= \hat{P}\hat{Q} = \\
    \begin{bmatrix}
        \lambda_0^0 x_0^0  & \lambda_1^0 x_1^0  & \lambda_2^0 x_2^0  & \lambda_3^0 x_3^0  & \hdots & \lambda_n^0 x_n^0 \\
        \lambda_0^0 y_0^0  & \lambda_1^0 y_1^0  & \lambda_2^0 y_2^0  & \lambda_3^0 y_3^0  & \hdots & \lambda_n^0 y_n^0 \\
        \lambda_0^0        & \lambda_1^0        & \lambda_2^0        & \lambda_3^0        & \hdots & \lambda_n^0   \\
        \lambda_0^1 x_0^1  & \lambda_1^1 x_1^1  & \lambda_2^1 x_2^1  & \lambda_3^1 x_3^1  & \hdots & \lambda_n^1 x_n^1 \\
        \lambda_0^1 y_0^1  & \lambda_1^1 y_1^1  & \lambda_2^1 y_2^1  & \lambda_3^1 y_3^1  & \hdots & \lambda_n^1 y_n^1 \\
        \lambda_0^1        & \lambda_1^1        & \lambda_2^1        & \lambda_3^1        & \hdots & \lambda_n^1   \\
        \vdots             & \vdots             & \vdots             & \vdots             &        & \vdots \\
        \lambda_0^m x_0^m  & \lambda_1^m x_1^m  & \lambda_2^m x_2^m  & \lambda_3^m x_3^m  & \hdots & \lambda_n^m x_n^m \\
        \lambda_0^m y_0^m  & \lambda_1^m y_1^m  & \lambda_2^m y_2^m  & \lambda_3^m y_3^m  & \hdots & \lambda_n^m y_n^m \\
        \lambda_0^m        & \lambda_1^m        & \lambda_2^m        & \lambda_3^m        & \hdots & \lambda_n^m   \\
    \end{bmatrix}
    &=
    \begin{bmatrix}
        \hat{P}^0 \\
        \hat{P}^1 \\
        \vdots \\
        \hat{P}^m \\
    \end{bmatrix}
    \cdot
    \begin{bmatrix}
        \hat{Q_0} & \hat{Q_1} & \hat{Q_2} & \hat{Q}_3 & \hdots & \hat{Q_n} \\
    \end{bmatrix}
}

If the real world locations of some (at least three which are not co-linear)
points $Q_i$ are known, recovered structures can be aligned with real world
frame of reference (otherwise the scale, rotation and translation of recovered
structures are completely arbitrary). The outline of the algorithm is (each step will be described in the subsequent sections):

\begin{enumerate}
\item Fill gaps in measurement matrix.
\item Recover projective depths.
\item Factorize rescaled measurement matrix.
\item Perform Euclidean stratification.
\item Align recovered structures with real world frame of reference.
\end{enumerate}

The steps 1. and 2. have to be done together, as explained in the next section,
they need to be repeated several times to recover the rescaled measurement matrix from
the partial measurement matrix.

\section{Filling the gaps}
\subsection{Recovering projective depths}

Before trying to fill missing elements, the projective depths of known points
need to be computed. Observe, that any column and any triple of rows associated
with some camera matrix  $P_j$ of the rescaled measurement matrix can be
multiplied with nonzero scalar without changing the information the rescaled
measurement matrix contains (e.g. the camera parameters or the point
locations). The multiplication of a column is canceled by the fact that point
locations are in homogeneous coordinates and $w$ component accommodates the
scaling. Camera matrices can accommodate the scaling in similar manner. That
means projective depths can be fixed for single triple of rows and the rest of
the depths can be calculated with respect to that fixed row. To compute
projective depths of some other row $k$ with respect to the fixed one $j$, the
fundamental matrix $F^{jk}$ and the left epipole $e^{jk}$ need to be computed
\cite{sturm96}. It can be done with the eight point algorithm \cite{hartley95}
(there are   also seven and five point variations \cite{stewenius06}, however
my implementation uses only    the simplest, eight point one), then the
projective depths can be computed according to equation:

\nmatheq {
    \lambda_i^k = \frac{(e^{jk} \times q_i^k) \cdot (F^{jk} q_i^j)}{\norm{e^{jk} \times q_i^k}^2} \lambda_i^j
}

The function that does the above is called \code{recover\_projective\_depths}, it
takes two $3 \times n$ matrices \code{A} and \code{B}. It assumes that
projective depths in \code{A} are known and returns a new matrix that is copy of
\code{B} with projective depths filled in. The fundamental matrix and the left
epipole are computed with functions \code{fundamental\_matrix} and
\code{left\_epipole} respectively. For numerical stability
\code{fundamental\_matrix} normalizes the image projections. There is also
another function \code{recover\_all\_projective\_depths} takes a $3m \times n$
matrix and computes all projective depths.

\subsection{Filling missing elements}

A property of the rescaled measurement matrix that allows to recover its unknown
elements is that in noise free conditions it has rank 4. That means its column
space is four dimensional. If the basis $\mathcal{B}$ of that space is known,
every other column can be expressed as linear combination of the vectors from
that basis. The only condition is the column with missing elements are required
to have at least four elements known (as the linear combination coefficients
have to be computed first). In practice, four elements means at least two image
projections. First four element tuples $A_t$ of columns are sampled from the
rescaled measurement matrix. It is not guaranteed that any of them spans the
basis $\mathcal{B}$. However, the intersection of the subspaces spanned by them
should span $\mathcal{B}$. That is given set $\mathcal{B}_t$ of linear subspaces
generated by tuples of columns $A_t$, $\mathcal{B}$ can be computed as
$\mathcal{B} = \bigcap_{t \in T} \! \mathcal{B}_t = (Span_{t \in T}
\mathcal{B}_t^\bot)^\bot$.  However, the tuples $A_t$ may lack some of their
elements. In \cite{svoboda04} a way to extend incomplete tuples $A_t$ to
extended tuples $B_t$, that can take part in further processing was shown. A
tuple $B_t$ can be created from $A_t$ by replacing all of the unknown elements
with $0$ and adding some extra columns for the incomplete ones. For  every
column that doesn't have a projective depth, the extra column with zeros and
known  image projections should be added. If a column doesn't contain given
point at all, a triple of columns with the standard basis spanning the
dimensions of the unknown point should be added. Equation~\ref{eq:extendAt}
illustrates it.

\nmatheq {
    \label{eq:extendAt}
    A_t &=
    \begin{bmatrix}
        \lambda_1^1 q_1^1 & \lambda_2^1 q_2^1 & \times            & \lambda_4^1 q_4^1 \\
        \lambda_1^2 q_1^2 & \lambda_2^2 q_2^2 & \lambda_3^2 q_3^2 & \lambda_4^2 q_4^2 \\
        ? q_1^3           & \lambda_2^3 q_2^3 & \lambda_3^3 q_3^3 & \lambda_4^3 q_4^3 \\
        \vdots            & \vdots            & \vdots            & \vdots            \\
        \lambda_1^m q_1^m & \lambda_2^m q_2^m & \lambda_3^m q_3^m & \lambda_4^m q_4^m \\
    \end{bmatrix}
    \rarrow \\
    B_t &=
    \begin{bmatrix}
        \lambda_1^1 q_1^1 & 0      &\lambda_2^1 q_2^1 & 0                 & \begin{bmatrix} 1 \\ 0 \\ 0 \end{bmatrix} & \begin{bmatrix} 0 \\ 1 \\ 0 \end{bmatrix} & \begin{bmatrix} 0 \\ 0 \\ 1 \end{bmatrix} & \lambda_4^1 q_4^1 \\
        \lambda_1^2 q_1^2 & 0      &\lambda_2^2 q_2^2 & \lambda_3^2 q_3^2 & 0                                         & 0                                         & 0                                         & \lambda_4^2 q_4^2 \\
        0                 & q_1^3  &\lambda_2^3 q_2^3 & \lambda_3^3 q_3^3 & 0                                         & 0                                         & 0                                         & \lambda_4^3 q_4^3 \\
        \vdots            & \vdots &\vdots            & \vdots            & \vdots                                    & \vdots                                    & \vdots                                    & \vdots            \\
        \lambda_1^m q_1^m & 0      &\lambda_2^m q_2^m & \lambda_3^m q_3^m & 0                                         & 0                                         & 0                                         & \lambda_4^m q_4^m \\
    \end{bmatrix}
}

The generators $B_t^\bot$ of $\mathcal{B}_t^\bot$ can be computed by taking SVD
of $B_t$: $[u, s, v] = svd(B_t)$. The generators are equal to $u[:, d:]$
(the indexing operator $[]$ uses the Python convention), where $d$ is dimension of
$\mathcal{B}_t$, which is number of nonzero entries in $s$. To compute $(Span_{t
\in T} \mathcal{B}_t^\bot)^\bot$, one needs to take $[u, s, v] = svd([B_1^\bot
B_2^\bot \dots B_t^\bot])$ and $(Span_{t \in T} \mathcal{B}_t^\bot)^\bot$ is
equal to $u[:, -4:]$. The detailed description how to recover the column space
can be found in \cite{jacobs99} and \cite{svoboda04}. The function that computes
the rank four column space in the associated program is called
\code{rank\_four\_column\_space}. It takes the rescaled measurement matrix, and
returns a new matrix with four columns that are basis for its column space.

\subsection{Iterative approach}

To recover all of the missing image projections, the
steps just described needs to be applied iteratively. At first the triple of
rows that has the greatest number of elements filled is found, lets call it the
fixed triple. Then all triples that have at least eight elements known in common
with the fixed triple are gathered (the restriction imposed by the eight point
algorithm). Then the sub-matrix from all of the collected triples is created and
the projective depths for known projections are estimated. The next step is to
compute the basis of column space and use it to fill the missing elements. The
process is repeated until all the gaps are filled. The function responsible for
the process is \code{reconstruct\_missing\_data}. It takes a measurement matrix
\code{W} and returns its copy with gaps filled and the projective depths
computed.

\section{Factorization of Measurement Matrix}

Having the projective depths
recovered, rescaled measurement matrix $W$ can be factorized to set of camera
matrices $\hat{P}$ and point positions $\hat{Q}$. The factorization can only by
done up to some unknown projective transformation, but this issue will be fixed
in the next step. As rescaled measurement matrix is rank 4 matrix, it can be
factorized with SVD. However, before factorization it should be balanced to
provide better stability of SVD (\cite{sturm96}). To balance the matrix, columns
are rescaled, so that $\forall_{1 \leq i \leq n} \sum_{j=1}^m \left( (\lambda
_i^j x_i^j)^2 + (\lambda _i^j y_i^j)^2 + (\lambda _i^j)^2 \right)~=~1$ and
triples of rows are rescaled, so that $\forall_{1 \leq j \leq m} \sum_{i=0}^n
\left( (\lambda _i^j x_i^j)^2 + (\lambda _i^j y_i^j)^2 + (\lambda _i^j)^2
\right) = 1$. The~balancing is done with \code{balance\_measurement\_matrix}
function. In (\cite{sturm96}) it is suggested to repeat balancing until the
measurement matrix  changes, however in my implementation number of balancing
steps is fixed to some constant.

After balancing, the matrix can be factorized with SVD. Equation~\ref{eq:rank4}
illustrates it. As factorization of $s$ can be arbitrary, it is factorized by
taking square root. The factorization is a part of the
\code{factor\_measurement\_matrix} procedure.

\nmatheq {
    \label{eq:rank4}
    u, s, v &= svd(\hat{W}) \\
    \hat{P} &= u[:, :4] \cdot \sqrt{s} \\
    \hat{Q} &= \sqrt{s} \cdot v[:4, :] \\
}

\section{Euclidean Stratification}

The matrices $\hat{P}$ and $\hat{Q}$ are recovered up to some unknown projective
transformation. An arbitrary projective transformation matrix $HH^{-1}$ can be inserted
in-between $\hat{P}$ and $\hat{Q}$ and factorization still will be correct.

\nmatheq{
    W = \hat{P}HH^{-1}\hat{Q} = PQ
}

To upgrade the projective factorization to the Euclidean one, the constraints on
the rescaled measurement matrix $W$ and the camera matrix $P$ needs to be
imposed. The first set of constraints puts the origin of the coordinate system
to the centroid of yet unknown points. The  second constraints uses properties
of the camera matrices (an orthogonality of rotation matrix   axes). The
constraints give a raise to set of equations, which if solved gives a matrix
that   changes recovered structures to Euclidean ones. The details can be found
in \cite{svoboda05}   and \cite{han00}. At the end of the document, the
equations~\ref{eq:b},~\ref{eq:Q} and  ~\ref{eq:vertical} for $b$ and $Q$ for
single camera matrix are given for reference (the   notation from
\cite{svoboda05} is used). They can be extended to full system by stacking them
together. The function \code{factor\_measurement\_matrix} solves the equations
and returns   stratified matrix.

\section{Fixing Camera Matrices}

As the triples of rows associated with given cameras can be multiplied by any
nonzero scalar, there is ambiguity in recovered cameras. The z-axis of the
camera may be reversed. To fix that a simple heuristic is used. The number of
points visible in front of camera and in the back of it is counted and if the
number of points visible at the rear side of camera is greater that at  the
front, the z-axis is reversed. \code{resolve\_camera\_ambiguity} function is
intended for  that purpose.

\section{Alignment with World}

To align recovered structures with the real world frame of reference the
positions of at least three point in real world that are not lying on the same line
are needed. In the face of noise additional locations will improve the accuracy
though. A system of linear equations can be created and solved with SVD to
compute a matrix that transforms the structures to the world coordinate system.
In my implementation \code{find\_frame\_of\_reference} is the function which
does that.

\newpage

\section{Dissecting the Camera Matrix}

After successful factorization, to recover intrinsic and extrinsic camera
parameters, the camera matrices needs to be factorized out. The function that
does the job is called \code{decompose}, it takes a camera matrix and returns
tuple $(K, R, T)$ with the matrix of intrinsic parameters, the rotation and the translation
vector. First the $P$ matrix is factorized with the RQ algorithm $\bar{K},
\bar{R} = rq(P[:3, :3])$. This factorization is slightly ambiguous and following
steps \cite{simek12} are carried out to fix it (the fixed matrices will be called $\bar{K}'$~and~$\bar{R}'$):

\begin{enumerate}
\item If $\bar{K}_{00}$ is negative multiply both the first column of $\bar{K}$ and first row
of $\bar{R}$ by $-1$.
\item If $\bar{K}_{11}$ is negative multiply both the second column of $\bar{K}$ and second row
of $\bar{R}$ by $-1$.
\item If $\bar{K}_{22}$ is positive (cameras from my implementation has reversed z-axis)
multiply both the third column of $\bar{K}$ and third row of $\bar{R}$ by $-1$.
\item If determinant of $\bar{R}$ is negative multiply the whole matrix by $-1$.
\end{enumerate}

Then translation is computed as $T = (\bar{K}' \cdot (-\bar{R}'))^{-1} \cdot
P[:3, 3]$. The  last thing is to remove scaling from $\bar{K}$: $K =
\dfrac{\bar{K}''}{\bar{K}'[2,2]}$.

\section{Experiments}

Several experiments were conducted, on two test scenes, including one with real
data. Figure~\ref{fig:artificial} presents the artificial scene. It consist of
10 cameras, the test points were randomly drawn from inside of the sphere. The
points were transformed with the camera matrices, to obtain their pixels
positions in the coordinate systems of the respective cameras. Then random noise was
added to each of the pixel positions. Given a pixel position $p = (p_x, p_y)$, the
new pixel position $p' = (p_x', p_y')$ with the noise added is $p_x' = p_x + (2
\cdot \xi - 1) \cdot \varepsilon$, where $\xi$ is a standard uniform random
variable ($\xi \in [0, 1)$), and $\varepsilon$ controls an amount of the noise added (the
same~for~$y$).

\begin{figure}[!ht]
\centering
\includegraphics[scale=0.5]{artificial.png}
\caption{The arrangement of the cameras in artificial scene.}
\label{fig:artificial}
\end{figure}

In a part of the tests, some of the pixel positions were erased to test if my
implementation can handle the occlusions. The results are summarized in the
table~\ref{tab:artificial}. The RMS error refers to the random mean square root
error between the reference and recovered camera positions. To compute the error, the camera positions were interpreted as a flat array (see numpy's \code{ravel}). The "missing" column
contains the fraction of the pixel positions erased.

\begin{table}[!ht]
\centering
\begin{tabular}{|l|r|r|r|r|r|r|}
\hline
\multicolumn{1}{|c}{ \bfseries name} &
\multicolumn{1}{|c}{ \bfseries cameras} &
\multicolumn{1}{|c}{ \bfseries points} &
\multicolumn{1}{|c}{ \bfseries missing} &
\multicolumn{1}{|c}{ \bfseries noise ($\varepsilon$)} &
\multicolumn{1}{|c|}{\bfseries RMS error } \\ \hline
\code{testset\_m\_0\_0\_e\_0\_0}      & 10 & 100 & 0.0 & 0.0       & 0.00283 \\ \hline
\code{testset\_m\_0\_1\_e\_0\_0}      & 10 & 100 & 0.1 & 0.0       & 0.00287 \\ \hline
\code{testset\_m\_0\_2\_e\_0\_0}      & 10 & 100 & 0.2 & 0.0       & 0.00275 \\ \hline
\code{testset\_m\_0\_4\_e\_0\_0}      & 10 & 100 & 0.4 & 0.0       & 0.01573 \\ \hline
\code{testset\_m\_0\_8\_e\_0\_0}      & 10 & 100 & 0.8 & 0.0     & not converge \\ \hline
\code{testset\_m\_0\_0\_e\_0\_1}      & 10 & 100 & 0.0 & $10^{-1}$ & 896.504 \\ \hline
\code{testset\_m\_0\_0\_e\_0\_01}     & 10 & 100 & 0.0 & $10^{-2}$ & 15.8931 \\ \hline
\code{testset\_m\_0\_0\_e\_0\_001}    & 10 & 100 & 0.0 & $10^{-3}$ & 19.7910 \\ \hline
\code{testset\_m\_0\_0\_e\_0\_0001}   & 10 & 100 & 0.0 & $10^{-4}$ & 0.04995 \\ \hline
\code{testset\_m\_0\_0\_e\_0\_00001}  & 10 & 100 & 0.0 & $10^{-5}$ & 0.00319 \\ \hline
\code{testset\_m\_0\_1\_e\_0\_001}  & 10 & 100 & 0.1 & $10^{-3}$   & 549.828 \\ \hline
\code{testset\_m\_0\_1\_e\_0\_0001}  & 10 & 100 & 0.1 & $10^{-4}$  & 9.78033 \\ \hline
\end{tabular}
\caption{A summary of the tests carried out with the artificial scene.}
\label{tab:artificial}
\end{table}

% data/testset_m_0_0_e_0_0.csv :  0.00283474054273
% data/testset_m_0_1_e_0_0.csv :  0.00287687828883
% data/testset_m_0_2_e_0_0.csv :  0.002753317657
% data/testset_m_0_4_e_0_0.csv :  0.0157395386403
% data/testset_m_0_0_e_0_1.csv :  896.504346513
% data/testset_m_0_0_e_0_01.csv :  15.8931605235
% data/testset_m_0_0_e_0_001.csv :  19.7910311311
% data/testset_m_0_0_e_0_0001.csv :  0.0499547559616
% data/testset_m_0_0_e_0_00001.csv :  0.00319775979851
% data/testset_m_0_1_e_0_001.csv :  549.828117517
% data/testset_m_0_1_e_0_0001.csv :  9.78033946821

The real data was captured with web and mobile phone cameras. The cameras used
were Nokia Lumia 620 (1280x720), Nokia Lumia 820 (1280x720), Huawei P8 Lite
(1088x1280), Motorola MB860 (1920x1080), Asus K56CB (640x480), Microsoft HD 3000
(640x480), 4WORLD Z200 (640x480) (the values int the parentheses are resolutions).
However, the capture from Motorola had to be discarded due to problems with
synchronization (it was skipping and adding extra frames at random places) and
the capture from Lumia 640 had to be discarded as well (due to lighting conditions). The points were generated by
tracking a bright diffuse white LED. The moment of the LED switching on was used to
synchronize the captures from all of the cameras. A checkerboard with known dimensions was used to capture the frame of reference of the scene. A special tool was written to
extract the pixel positions of the pointer (the source code is in \texttt{sync.py}). Figure~\ref{fig:real} shows the arrangement of cameras on the real scene.

\begin{figure}[ht]
\centering
\includegraphics[scale=0.5]{real.png}
\caption{The arrangement of the cameras in real scene.}
\label{fig:real}
\end{figure}

Table~\ref{tab:positions} compares the real positions of the cameras (obtained with a tape measure, with $10cm$ accuracy) with the recovered ones. Table~\ref{tab:real} summarizes the experiment with real scene, a few tests with different degree of missing points were conducted. The "missing" column contains the number of missing pixel positions.

\begin{table}[ht]
\centering
\begin{tabular}{|l|c|c|c|}
\hline
\multicolumn{1}{|c}{\bfseries Camera} &
\multicolumn{1}{|c}{\bfseries Real positions} &
\multicolumn{1}{|c|}{\bfseries Estimated position} \\ \hline
 1 & [16.4, 12.0, -8.2] & [16.4, 8.3, -1.7] \\ \hline
 2 & [18.5, 10.0, -2.8] & [13.5, 7.1, -4.7] \\ \hline
 3 & [5.0, 4.8, -14.7] & [4.6, 3.8, -11.2] \\ \hline
 4 & [16.0, 10.6, 12.4] & [18.2, 9.2,  13.0] \\ \hline
 5 & [-6.3, 10.6, -13.8] & [-2.9, 9.0, -12.2] \\ \hline
\end{tabular}
\caption{The real and recovered camera positions.}
\label{tab:positions}
\end{table}

\begin{table}[!ht]
\centering
\begin{tabular}{|l|r|r|r|r|r|r|}
\hline
\multicolumn{1}{|c}{ \bfseries name} &
\multicolumn{1}{|c}{ \bfseries cameras} &
\multicolumn{1}{|c}{ \bfseries points} &
\multicolumn{1}{|c}{ \bfseries missing} &
\multicolumn{1}{|c|}{\bfseries RMS error } \\ \hline
\code{dataset1}      & 5  & 132 & 0  & 2.92276 \\ \hline
\code{dataset2}      & 5  & 253 & 10 & 3.44128 \\ \hline
\code{dataset3}      & 5  & 263 & 14 & 5.55154 \\ \hline
\code{dataset4}      & 5  & 282 & 21 & 3.40607 \\ \hline
\end{tabular}
\caption{A summary of the tests carried out with the real scene.}
\label{tab:real}
\end{table}

% data/dataset1.csv :  2.92276712426
% data/dataset2.csv :  3.44128694798
% data/dataset3.csv :  5.55154646563
% data/dataset4.csv :  3.40607167903

\begin{figure}[ht]
\centering
\includegraphics[scale=0.4]{sync.png}
\caption{A screen-shot from the \texttt{sync.py} tool, which was used to synchronize the videos and capture the positions of the pointer (the view from discarded cameras is included).}
\end{figure}

\begin{figure}[ht]
\centering
\includegraphics[scale=0.097]{stick.jpg}
\caption{A photo of the "stick" that was used as the pointer.}
\end{figure}

\section{Conclusions}

Implemented algorithm turned out to be quite sensitive to noise. It gives almost
exact results for precise data, but the robustness of the implemented algorithm
quickly diminishes as the error increases. It could have been expected, as some
steps of original implementation \cite{svoboda05} were skipped. The major
problem is the lack of any iterative refinement of the intermediate results (e.g.
optimizing projective structure with Bundle Adjustment, before factorization).
My implementation has not means to handle outliers (the points in real world
experiments were manually selected). The methods applied to sample the columns for
the estimation of the column space basis and to choose the order of computation
of fundamental matrices are very naive in comparison to the ones presented in
the paper. However, as it was experimentally proven, it is robust enough to
recover an approximate structure and motion from the real-world data.

\FloatBarrier

\bibliographystyle{alpha}
\bibliography{main}

The associated code can be found under the following link \url{https://github.com/ciechowoj/calibration} .

\newpage

\section{Equations for Euclidean stratification}

\nmatheq {
    \label{eq:b}
    \begin{dcases}
        (P_z^j)^T b \cdot \frac{T_x^j}{T_z^j} - (P_x^j)^T b &= 0 \\
        (P_z^j)^T b \cdot \frac{T_y^j}{T_z^j} - (P_y^j)^T b &= 0 \\
    \end{dcases} \\
    \begin{dcases}
        P_{z0}^j \frac{T_x^j}{T_z^j} b_x +
        P_{z1}^j \frac{T_x^j}{T_z^j} b_y +
        P_{z2}^j \frac{T_x^j}{T_z^j} b_z +
        P_{z3}^j \frac{T_x^j}{T_z^j} b_w -
        P_{x0}^j b_x +
        P_{x1}^j b_y +
        P_{x2}^j b_z +
        P_{x3}^j b_w &= 0 \\
        P_{z0}^j \frac{T_y^j}{T_z^j} b_x +
        P_{z1}^j \frac{T_y^j}{T_z^j} b_y +
        P_{z2}^j \frac{T_y^j}{T_z^j} b_z +
        P_{z3}^j \frac{T_y^j}{T_z^j} b_w -
        P_{y0}^j b_x +
        P_{y1}^j b_y +
        P_{y2}^j b_z +
        P_{y3}^j b_w &= 0 \\
    \end{dcases} \\
    \begin{dcases}
        \left( P_{z0}^j \frac{T_x^j}{T_z^j} - P_{x0}^j \right) b_x +
        \left( P_{z1}^j \frac{T_x^j}{T_z^j} - P_{x1}^j \right) b_y +
        \left( P_{z2}^j \frac{T_x^j}{T_z^j} - P_{x2}^j \right) b_z +
        \left( P_{z3}^j \frac{T_x^j}{T_z^j} - P_{x3}^j \right) b_w = 0 \\
        \left( P_{z0}^j \frac{T_y^j}{T_z^j} - P_{y0}^j \right) b_x +
        \left( P_{z1}^j \frac{T_y^j}{T_z^j} - P_{y1}^j \right) b_y +
        \left( P_{z2}^j \frac{T_y^j}{T_z^j} - P_{y2}^j \right) b_z +
        \left( P_{z3}^j \frac{T_y^j}{T_z^j} - P_{y3}^j \right) b_w = 0
    \end{dcases} \\
    \begin{bmatrix}
        P_{z0}^j \frac{T_x^j}{T_z^j} - P_{x0}^j & P_{z1}^j\frac{T_x^j}{T_z^j} - P_{x1}^j & P_{z2}^j\frac{T_x^j}{T_z^j} - P_{x2}^j & P_{z3}^j \frac{T_x^j}{T_z^j} - P_{x3}^j \\
        P_{z0}^j \frac{T_y^j}{T_z^j} - P_{y0}^j & P_{z1}^j\frac{T_y^j}{T_z^j} - P_{y1}^j & P_{z2}^j\frac{T_y^j}{T_z^j} - P_{y2}^j & P_{z3}^j \frac{T_y^j}{T_z^j} - P_{y3}^j \\
   \end{bmatrix}
    \cdot
    \begin{bmatrix} b_x \\ b_y \\ b_z \\ b_w \end{bmatrix} = 0
}

\nmatheq {
    \label{eq:Q}
    Q =
    \begin{bmatrix}
        q_{00} & q_{01} & q_{02} & q_{03} \\
        q_{01} & q_{11} & q_{12} & q_{13} \\
        q_{02} & q_{12} & q_{22} & q_{23} \\
        q_{03} & q_{13} & q_{23} & q_{33}
    \end{bmatrix}
}

\newpage

\center \begin{rotate}{270}
\smatheq {
    \begin{bmatrix}
    P_{x0}^{2} - P_{y0}^{2} & 2 P_{x0} P_{x1} - 2 P_{y0} P_{y1} & 2 P_{x0} P_{x2} - 2 P_{y0} P_{y2} & 2 P_{x0} P_{x3} - 2 P_{y0} P_{y3} & P_{x1}^{2} - P_{y1}^{2} & 2 P_{x1} P_{x2} - 2 P_{y1} P_{y2} & 2 P_{x1} P_{x3} - 2 P_{y1} P_{y3} & P_{x2}^{2} - P_{y2}^{2} & 2 P_{x2} P_{x3} - 2 P_{y2} P_{y3} & P_{x3}^{2} - P_{y3}^{2}\\
    P_{x0} P_{y0} & P_{x0} P_{y1} + P_{x1} P_{y0} & P_{x0} P_{y2} + P_{x2} P_{y0} & P_{x0} P_{y3} + P_{x3} P_{y0} & P_{x1} P_{y1} & P_{x1} P_{y2} + P_{x2} P_{y1} & P_{x1} P_{y3} + P_{x3} P_{y1} & P_{x2} P_{y2} & P_{x2} P_{y3} + P_{x3} P_{y2} & P_{x3} P_{y3}\\
    P_{y0} P_{z0} & P_{y0} P_{z1} + P_{y1} P_{z0} & P_{y0} P_{z2} + P_{y2} P_{z0} & P_{y0} P_{z3} + P_{y3} P_{z0} & P_{y1} P_{z1} & P_{y1} P_{z2} + P_{y2} P_{z1} & P_{y1} P_{z3} + P_{y3} P_{z1} & P_{y2} P_{z2} & P_{y2} P_{z3} + P_{y3} P_{z2} & P_{y3} P_{z3}\\
    P_{x0} P_{z0} & P_{x0} P_{z1} + P_{x1} P_{z0} & P_{x0} P_{z2} + P_{x2} P_{z0} & P_{x0} P_{z3} + P_{x3} P_{z0} & P_{x1} P_{z1} & P_{x1} P_{z2} + P_{x2} P_{z1} & P_{x1} P_{z3} + P_{x3} P_{z1} & P_{x2} P_{z2} & P_{x2} P_{z3} + P_{x3} P_{z2} & P_{x3} P_{z3}\\
    P_{z0}^{2} & 2 P_{z0} P_{z1} & 2 P_{z0} P_{z2} & 2 P_{z0} P_{z3} & P_{z1}^{2} & 2 P_{z1} P_{z2} & 2 P_{z1} P_{z3} & P_{z2}^{2} & 2 P_{z2} P_{z3} & P_{z3}^{2}\\
    \end{bmatrix} \cdot
    \begin{bmatrix}
        q_{00}\\q_{01}\\q_{02}\\q_{03}\\q_{11}\\q_{12}\\q_{13}\\q_{22}\\q_{23}\\q_{33}\\
    \end{bmatrix}
    =
    \begin{bmatrix}
        0 \\ 0 \\ 0 \\ 0 \\ 1
    \end{bmatrix}
    }
\end{rotate}

\end{document}