\documentclass[./\jobname.tex]{subfiles}
\begin{document}

\chapter{Experimental Design}
This chapter gives an overview on how the subsequent experiments are conducted. An integral part of solver comparison is to define a testbed that holds example problems with a known analytical solution. Further, a quality measurement must be defined that compares the numerical to the analytical solution. Since the memory consumption and the solving time is of interest, a robust method to measure these characteristics is needed. The baseline for all experiments is the \gls{fem} solver NGSolve (\cite{schoberl_ngsolvengsolve_2020}).

\section{Testbed}
\label{chap:testbed_description}
The testbed is a collection of multiple two-dimensional scalar \gls{pde}s that are analytically solved such that $u_{ext}(\mathbf{x}): \mathbb{R}^2 \rightarrow \mathbb{R}$ is a solution to the underlying PDE. These can be used to demonstrate the correct implementation of a solver. The testbed can also be used to compare the performance of the classical \gls{fem} solver (NGSolve) with the \gls{ci} solver. The equations and graphs are displayed in the appendix \ref{chap:testbed}. The equations used here are a mixture of different testbeds. Specifically, the equations \gls{pde} 2 and \gls{pde} 3 are picked from the testbed in \cite{chaquet_using_2019}. These problems were also used by \cite{tsoulos_solving_2006} and \cite{panagant_solving_2014}. Preliminary tests have shown that the equations used in these papers are rather simple to approximate. Thus, more complicate equations are added to test the solvability over a wider variety of functions. The more complex equations are taken from the National Institute of Standards and Technology (NIST) website (\cite{mitchell_nist_2018}) that provides benchmarking problems for \gls{fem} solvers with adaptive mesh refinement methods. The other equations 0A, 0B and 8 are specially created to show different properties of the solver.

\textbf{PDE 0A: Gauss Kernel} \\
\underline{Equation Reference:} \eqref{eq:pde0a} \\
\underline{Characteristics:} sum of 5 \gls{gak}, thus can be approximated arbitrarily close; is designed to show convergence towards analytical solution; \\
\underline{Difficulty:} not especially difficult; \\
\underline{Boundary:} function value of solution; \\

\textbf{PDE 0B: Gauss Sine Kernel} \\
\underline{Equation Reference:} \eqref{eq:pde0b} \\
\underline{Characteristics:} can be approximated arbitrarily close by 3 \gls{gsk}; 3 kernels are used to keep the minimal necessary dimension of the representation similar to \gls{pde} 0A;\\
\underline{Difficulty:} the contrast between a dominant wave with a steep gradient in the middle and small waves with little influence on the boundary; simple approximations lay the focus on the middle, while good approximations also match the small waves; \\
\underline{Boundary:} function value of solution; \\

\textbf{PDE 1: Polynomial 2D} \\
\underline{Equation Reference:} \eqref{eq:pde1} \\
\underline{Characteristics:} polynomial of order 20 \\
\underline{Difficulty:} global structure similar to a \gls{gak}; thus, it is simple to approximate; \\
\underline{Boundary:} homogeneous boundary condition; \\
\underline{Reference:} \cite{mitchell_nist_2018}; \\

\textbf{PDE 2: Chaquet PDE 1} \\
\underline{Equation Reference:} \eqref{eq:pde2} \\
\underline{Characteristics:} compare the performance to other solvers; \\
\underline{Difficulty:} rather simple; slight curvature and no steep gradient; \\
\underline{Boundary:} function value on boundary; \\
\underline{Reference:} \cite{chaquet_using_2019}, \cite{chaquet_solving_2012}, \cite{tsoulos_solving_2006}, \cite{sobester_genetic_2008}, \cite{panagant_solving_2014};\\

\textbf{PDE 3: Chaquet PDE 3} \\
\underline{Equation Reference:} \eqref{eq:pde3} \\
\underline{Characteristics:} compare the performance to other solvers; polynomial of order 2; \\
\underline{Difficulty:} well behaved, no steep gradient; \\
\underline{Boundary:} function value on boundary; \\
\underline{Reference:} \cite{chaquet_using_2019}, \cite{chaquet_solving_2012}, \cite{tsoulos_solving_2006}, \cite{panagant_solving_2014}; \\

\textbf{PDE 4: Sine Bump 2D} \\
\underline{Equation Reference:} \eqref{eq:pde4} \\
\underline{Characteristics:} this \gls{pde} is used in both, the work of \cite{chaquet_using_2019} and  \cite{mitchell_nist_2018} with slightly different boundary condition; preliminary tests have shown that the \cite{chaquet_using_2019} \gls{pde} is easier to solve, thus this formulation is disregarded;\\
\underline{Difficulty:} sharp boundary condition on the corners of $\Omega$; \\
\underline{Boundary:} homogeneous boundary condition; \\
\underline{Reference:} \cite{mitchell_nist_2018};\\

\textbf{PDE 5: Arctan Circular Wave Front} \\
\underline{Equation Reference:} \eqref{eq:pde5} \\
\underline{Characteristics:} quarter section of slightly shifted arctan; \\
\underline{Difficulty:} transition from the flat plateaus to the steep gradient of the circular wave front; preliminary tests have shown that this problem is especially hard; \\
\underline{Boundary:} function value on boundary; \\
\underline{Reference:} \cite{mitchell_nist_2018}; \\

\textbf{PDE 6: Peak 2D} \\
\underline{Equation Reference:} \eqref{eq:pde6} \\
\underline{Characteristics:} solution is a single but sharp Gaussian ``peak'' at $(0.5, 0.5)$; \\
\underline{Difficulty:} large negative exponent in e-function results in a steep gradient and small region of interest; \\
\underline{Boundary:} function value on boundary; \\
\underline{Reference:} \cite{mitchell_nist_2018}; \\

\textbf{PDE 7: Boundary Line Singularity} \\
\underline{Equation Reference:} \eqref{eq:pde7} \\
\underline{Characteristics:} the solution to this problem is a root function that is only defined on $x \in \mathbb{R}^{+}$; \\
\underline{Difficulty:} line singularity on boundary with increasing gradient; \\
\underline{Boundary:} function value with singularity on boundary $x_0 = 0$; \\
\underline{Reference:} \cite{mitchell_nist_2018}; \\

\textbf{PDE 8: Interior Point Singularity} \\
\underline{Equation Reference:} \eqref{eq:pde8} \\
\underline{Characteristics:} root function; a singularity within the domain; \\
\underline{Difficulty:} not defined at $(0.5, 0.5)$ which results in numerical inaccuracies; \\
\underline{Boundary:} function value on boundary; \\

\textbf{PDE 9: Arctan Wave Front Homogeneous Boundary Conditions 2D} \\
\underline{Equation Reference:} \eqref{eq:pde9} \\
\underline{Characteristics:} arctan oscillation diagonal to the domain;  \\
\underline{Difficulty:} steep gradient on the transition between wave peak and trough; sharp corners on the boundary; \\
\underline{Boundary:} homogeneous boundary condition; \\
\underline{Reference:} \cite{mitchell_nist_2018}; \\

\section{Software Architecture}
\label{chap:software_architecutre}

To simplify the preparation, execution and evaluation of the experiments, a comprehensive software architecture is defined. The \gls{uml} class diagram can be seen in the appendix \ref{chap:appendix_software_architecture}. The limited class diagram, without any methods and attributes is shown in the figure \ref{fig:uml_class_small} below. The architecture is organised in four main segments.

\large \underline{\textbf{Optimisation Algorithm}} \\
The \inlinecode{IOptAlgoBase} interface must be implemented by every \inlinecode{OptAlgo} class to ensure the compatibility with \inlinecode{CiPdeBase} class of the testbed. A nice side-effect is that it reduces the number of user-defined parameters. An optimisation algorithm of this class must only take an initial guess (e.g. the starting population) as well as two stopping criteria: the maximum number of function evaluation or a minimum error to reach. Also a fitness function (i.e. the function to be optimised) must be provided. Four lists of the same length are returned: the optimum-guess, the function value, the crossover probability and the scale factor per each generation. The actual implementation of the algorithm is not predefined.

\large \underline{\textbf{Kernels}} \\
As described in chapter \ref{chap:candidate_rep}, a candidate solution is defined as a sum of \gls{rbf}. In order to test different candidate representations, different classes must be implemented. Again, to ensure compatibility with the \inlinecode{CiPdeBase} class, all representations must implement the \inlinecode{IKernelBase} interface. This assures that all classes have a method that can calculate the solution as well as the first and the second order derivatives. Here, only two kernels are implemented. A typical Gauss kernel as described in chapter \ref{chap:gauss_kernel} and a so called Gauss Sine kernel shown in chapter \ref{chap:gsin_kernel}.

\large \underline{\textbf{Testbed}} \\
The testbed holds the 11 differential equations used in all experiments. The testbed is abstracted in such a way that an experiment is as simple as creating an \gls{pde} object and calling its solve method. All testbed classes must implement the \inlinecode{ITestbenchBase} interface. This ensures the minimal functionality of every subsequent class. Currently two classes implement this interface, the \inlinecode{FemPdeBase} and the \inlinecode{CiPdeBase}. These are the base classes that provide the specific attributes and methods needed for the \gls{fem} solver and the \gls{ci} solver. The actual \gls{pde} problems are implemented in the classes \inlinecode{FemPdeN} or \inlinecode{CiPdeN} which inherit from the \inlinecode{FemPdeBase} and the \inlinecode{CiPdeBase}, respectively. The number \textit{N} in their name is representative for all different testbench problems and every \gls{pde} has its own class. Since all \gls{pde} classes have the same methods/attributes and only differ in their implementation and name, they do not have to be displayed separately. Therefore, they are symbolised together by a ``stacked notation'' used in the class diagram. Some methods in these classes must be overridden and adapted to the current \gls{pde} problem, which is indicated by the $\land$ character.

\large \underline{\textbf{Post Processing}} \\
Although the post processing block is not actually a class, it is still represented in this diagram. This module provides functions that take \inlinecode{FemPdeN} or \inlinecode{CiPdeN} objects and perform actions with them. The methods are used in the experiments chapters to interpret the results. A detailed description of the implementation is given in the appendix \ref{chap:apendix_post_proc}.

\begin{figure}[H]
	\centering
	\noindent\adjustbox{max width=\linewidth}{\includegraphics[width=1\textwidth]{../../code/uml_diag/testbench_uml_class_small.pdf}
	}
	\unterschrift{This reduced \gls{uml} class diagram gives an overview of the testbed design and its interfaces and classes.}{}{}
	\label{fig:uml_class_small}
\end{figure}

\section{Performance Metric}
\label{chap:metric}
In order to scientifically compare the results produced by the different solvers, some metrics are necessary. Three important solver-properties are measured: the execution time, the memory usage and the quality of the numerical solution. The following chapters describe the measurement process in greater detail.

\subsection{Solving Time}
\label{chap:metric_time}
The solving time is measured within the \inlinecode{solve()} method of either class. The time module of the \cite{python_standard_library_time_2020} is used to interact with the system clock. The resolution, that the time module can access, depends on the system it is running on. Specifically, on the machine used in all further experiments, \inlinecode{time.time()} returns a 24 byte float that represents the time passed since 1st of January 1970. Usually, consecutive calls of this function return increasing values - changing the system time could interfere with the correctness of this value.\\

As the execution time of a program depends on many other factors, such as the current system load, the CPU temperature and the process scheduler, it is necessary to view it as a random variable. Thus, multiple replications have to be done before trying to interpret the results. To make for a fair comparison, the same machine with a similar work-load must be used.  The replications are not done within the \inlinecode{solve()} function and must be applied during the experiment. To reduce the random effects and prevent possible outlier, the Python garbage collector is switched off during the time measurement. For a step-by-step description, the pseudocode is shown in the appendix \ref{chap:solve_function}.

\subsection{Memory Usage}
\label{chap:metric_mem}
Similar to the solving time measurement, the memory usage is determined within the \inlinecode{solve()} method. The \textit{psutil} module (\cite{rodola_psutil_2020}) provides the functionality to read the amount of memory attached to a process at a given time. The function call \inlinecode{process.memory_info()} returns an object with multiple attributes about the current state of the process. Of special interest is the \gls{vms} field. This includes the \gls{rss}, the memory that is currently held within the main memory, and the memory that is currently swapped out to the hard drive.

Without assuming anything about the inner workings of the process, the memory usage is also a random variable. Thus, similar to the time measurement, replications have to be performed. The same pseudocode as for the time measurement (appendix \ref{chap:solve_function}) also applies here. To remove outliers, it is helpful to create and solve one testbed object before recording the experiment. This sets up the necessary references to libraries and modules. Thus they are not mingled into the actual experiments. This should be done for both, the \gls{fem} and the \gls{ci} solver.

\subsection{Quality Measurement}
\label{chap:metric_quality}
Although the fitness function is the criterion that is optimised, it is not applicable as an objective quality measure. As \cite{chaquet_using_2019} describe, it depends on multiple factors:
\begin{itemize}
	\item user-defined parameters $\xi$ and $\phi$
	\item the formulation of the \gls{pde}
	\item number of collocation points used
	\item number of kernels used
\end{itemize}
Thus, \cite{chaquet_using_2019} define a new quality measurement based on the \gls{rmse} over the collocation points as seen in equation \eqref{eq:rmse_chaquet}.
\begin{equation}
\label{eq:rmse_chaquet}
RMSE^2 = \frac{\sum_{i=1, \mathbf{x}_i \in C}^{n_C} \left|\left| u(\mathbf{x}_i) - u_{ext}(\mathbf{x}_i) \right|\right|^2 + \sum_{j=1, \mathbf{x}_j \in B}^{n_B} \left|\left| u(\mathbf{x}_j) - u_{ext}(\mathbf{x}_j) \right|\right|^2}{(n_C + n_B)}
\end{equation}
This quality criterion has three inherent issues. At first, it firmly depends on the number of collocation points used. In an algorithm that uses self-adaptive collocation points, where the distribution of the points depends on random variables, subsequent measures of similar solutions could result in different quality values. Especially in solutions with high condition numbers, the \gls{rmse} measurement would be rendered useless since a small deviation of the point results in a large difference of the function value.

Further with the \gls{rmse}, the quality is only measured on the collocation points and not in between. However, a good solution fits not only these discrete points, but the whole domain. This is called an aliasing error. An approximation can fit the points, without correctly representing the space between them. This is shown in the following figure \ref{fig:aliasing error}.

\begin{figure}[H]
	\centering
	\noindent\adjustbox{max width=0.8\linewidth}{
		\includegraphics[width=\textwidth]{../img/pdf/aliasing_error.pdf}
	}
	\unterschrift{Aliasing Error: sharp inaccuracies in between collocation points}{}{}
	\label{fig:aliasing error}
\end{figure}

Finally, the \gls{fem} method doesn't use collocation points, so this quality measurement could not be calculated. A good quality measurement tool only uses the numerical and analytical solution, independently of the solving method.

This leads to the quality measurement formulation used in this thesis: the L2 norm defined for functions as denoted in equation \eqref{eq:quality_measurement}. This actually measures the distance between the analytical solution and the numerical approximation.
\begin{equation}
\label{eq:quality_measurement}
\left|\left|u_{ext} - u_{apx}\right|\right| = \sqrt{\int_{\Omega} (u_{ext}(\mathbf{x}) - u_{apx}(\mathbf{x}))^2 dx}
\end{equation}
Although this integral is numerically evaluated, the discretisation is much finer than the resolution of the collocation points used in the fitness function - thus also taking the areas between these points into account.

\section{Baseline: NGSolve}
\label{chap:fem_baseline_results}
As mentioned above, the NGSolve framework (\cite{schoberl_ngsolvengsolve_2020}) is used as the baseline for all experiments. NGSolve is a state of the art \gls{fem} solver that is in part developed and maintained by numerous well-known institutes such as the Vienna University of Technology, the University of Göttingen and the Portland State University. This chapter describes the results obtained by running NGSolve on the testbed. The metrics from chapter \ref{chap:metric} are applied.

\subsection{Setup}
At first the \gls{pde}s must be transformed into their corresponding weak form. As all testbed problems are Poisson equations and only differ in their algebraic sign and inhomogeneous part, the weak form is similar for all problems. Referring to equation \eqref{eq: weak form}, the terms $\vec{b} = 0$ and $c = 0$, thus these parts vanish. The matrix $A$ is either $\begin{bsmallmatrix} 1 & 0 \\ 0 & 1 \end{bsmallmatrix}$ or with a negative sign $\begin{bsmallmatrix} -1 & 0 \\ 0 & -1 \end{bsmallmatrix}$ as only the non-mixed second order derivatives occur in the equations. This results in the weak form as presented in equation \eqref{eq: weak form testbed}, where f is the inhomogeneous part of the \gls{pde}.
\begin{equation}
\label{eq: weak form testbed}
\int_{\Omega} \nabla u^T \nabla v dV = \int_{\Omega} f v dV
\end{equation}

To enhance the performance of NGSolve, static condensation is turned on. Further, a multigrid preconditioner is used. All problems are approximated by second order polynomials. The automatic mesh refinement is performed until a maximum of $5 \cdot 10^4$ \gls{dof} is reached. To properly interpret the results, 20 replications for each problem are performed. This is only needed for time and memory usage, the solution itself is not a random variable. To further reduce memory usage, the GUI of NGSolve is switched off.

\subsection{Result}
With the parameters described above, the following results are produced. The solving time as well as the memory usage are displayed in the boxplots \ref{fig:_fem_time_boxplot} and \ref{fig:_fem_mem_boxplot}, respectively. These datasets provide a reference point for the performance of the \gls{ci} solver. In general, the solving time ranges from 2.5 to 5.0 seconds at about 50 to 80 Mbyte of memory. Only problem 3 stands out as a notable exception. To keep the diagram within a readable scale, this \gls{pde} is omitted and plotted in a separate figure.

Table \ref{tab:fem_sol_quality} presents the achieved distances between the exact and the approximated solutions. On \gls{pde} 3 the best numerical quality is achieved.

The problem \gls{pde} 7 only needs around 2.5 seconds to be solved. A reason could be that the solution only depends on one variable and the derivative with respect to y evaluate to zero $\frac{\partial u}{\partial y} = 0$ and thus vanishes. This does not effect the memory usage, since all $5 \cdot 10^4$ \gls{dof} must be created to terminate.

\begin{table}[h]
	\centering
	\noindent\adjustbox{max width=\linewidth}{
		\begin{tabular}{|c|c|}

			\hline
			\rowcolor[HTML]{\farbeTabA}

			Problem PDE & L2 Norm \\ \hline

			0A & $2.967 \cdot 10^{-5}$ \\ \hline
			0B & $1.071 \cdot 10^{-5}$ \\ \hline
			1  & $8.004 \cdot 10^{-7}$ \\ \hline
			2  & $3.501 \cdot 10^{-8}$ \\ \hline
			3  & $1.680 \cdot 10^{-9}$ \\ \hline
			4  & $4.764 \cdot 10^{-7}$ \\ \hline
			5  & $6.057 \cdot 10^{-6}$ \\ \hline
			6  & $1.908 \cdot 10^{-7}$ \\ \hline
			7  & $5.203 \cdot 10^{-5}$ \\ \hline
			8  & $3.237 \cdot 10^{-7}$ \\ \hline
			9  & $2.366 \cdot 10^{-7}$ \\ \hline

		\end{tabular}
	}
	\unterschrift{These are the results obtained by the \gls{fem} solver in terms of distance to the analytical solution. The solver achieves the smallest deviation in PDE 3.}{}{}
	\label{tab:fem_sol_quality}
\end{table}

\begin{figure}[H]
	\centering
	\noindent\adjustbox{max width=0.66\linewidth}{
		\includegraphics[width=\textwidth]{../../code/experiments/_experiment_fem_base/time_boxplot_pde_0a_0b_1_2_4_5_6_7_8_9.pdf}
	}
	\unterschrift{Boxplot: time (in seconds) needed to solve the testbed \gls{pde} (without \gls{pde}3)}{}{}
	\label{fig:_fem_time_boxplot}
\end{figure}

\begin{figure}[H]
	\centering
	\noindent\adjustbox{max width=0.66\linewidth}{
		\includegraphics[width=\textwidth]{../../code/experiments/_experiment_fem_base/mem_boxplot_pde_0a_0b_1_2_4_5_6_7_8_9.pdf}
	}
	\unterschrift{Boxplot: memory (in Mbyte) needed to solve the testbed \gls{pde} (without \gls{pde}3)}{}{}
	\label{fig:_fem_mem_boxplot}
\end{figure}

The following figures \ref{fig:_fem_time_boxplot_pde3} and \ref{fig:_fem_mem_boxplot_pde3} show the boxplot of the time and memory consumption for the testbed \gls{pde} 3 with $5 \cdot 10^4$ \gls{dof}. Compared to the other equations, this problem takes longer to solve while also needing more memory: somewhere around 65.2 seconds at about 130 Mbyte. One possible explanation for that is the fundamental structure of the \gls{pde}. As described in equation \eqref{eq:sol3}, the exact solution to this problem is a polynomial of second order. This can be approximated perfectly by the \gls{fem} solver, since it also uses second order polynomials as basis functions. The mesh-refinement step takes more iterations to produce the $5 \cdot 10^4$ \gls{dof} as compared to the other testbed problems. In fact, since the numerical errors per finite element accumulate, more \gls{dof} should result in a larger approximation error. Figure \ref{fig:_dof_sweep_pde3} shows the performance metrics at different \gls{dof} budgets. The plot supports this hypothesis that less \gls{dof} take less time and memory to solve the \gls{pde} and still end up with a better quality.

\begin{figure}[H]
	\centering
	\noindent\adjustbox{max width=0.7\linewidth}{
		\includegraphics[width=\textwidth]{../../code/experiments/_experiment_fem_base/pde3_ndof.pdf}
	}
	\unterschrift{\gls{pde} 3 performance metrics at different \gls{dof} budgets.}{}{}
	\label{fig:_dof_sweep_pde3}
\end{figure}

\begin{figure}[H]
	\centering
	\begin{subfigure}[b]{0.5\linewidth}
		\centering
		\includegraphics[width=1\textwidth]{../../code/experiments/_experiment_fem_base/time_boxplot_pde_3.pdf}
		\caption{Boxplot: time to solve testbed \gls{pde}3 at $5\cdot 10^4$ \gls{dof}.}
		\label{fig:_fem_time_boxplot_pde3}
	\end{subfigure}%
	%
	\begin{subfigure}[b]{0.5\linewidth}
		\centering
		\includegraphics[width=1\textwidth]{../../code/experiments/_experiment_fem_base/mem_boxplot_pde_3.pdf}
		\caption{Boxplot: memory to solve testbed \gls{pde}3 at $5\cdot 10^4$ \gls{dof}.}
		\label{fig:_fem_mem_boxplot_pde3}
	\end{subfigure}%
	\unterschrift{Comparison of time and memory effort on \gls{pde} 3 at $5 \cdot 10^4$ \gls{dof}.}{}{}%
	\label{}
\end{figure}

\section{Default CI Parameter}
\label{chap:default_ci_param}
Typically, the performance of heuristic optimisation algorithms can be adjusted to specific testbed problems by tuning its parameters. For all further experiments the JADE algorithm, as described with pseudocode \ref{algo: jade}, is used. Similarly, the reported \gls{ci} solver has many parameters that could be adapted. However, adjusting every parameter in order to find the best combination is not an option, since that would take an extensive amount of computation time. Some parameters that might not have a great effect on the performance can be predefined. These values are determined by preliminary tests. If not stated otherwise, the following parameters from table \ref{tab:ci_parameter} are used in the subsequent experiments.

\begin{table}[h]
	\centering
	\noindent\adjustbox{max width=\linewidth}{
		\begin{tabular}{|c|c|c|}

			\hline
			\rowcolor[HTML]{\farbeTabA}

			Parameter & JADE & \multilinecell{\gls{cma_es} \\ (\cite{chaquet_using_2019})} \\ \hline

			$\varphi$ & 100 & 300 \\ \hline
			$\kappa$  & 1   & 3   \\ \hline
			population size & $2 \cdot dim$ & $\frac{3}{2}(4 + \lfloor 3 \cdot ln(dim) \rfloor)$ \\ \hline
			min error & 0   & - \\ \hline
			p & 0.3 & - \\ \hline
			c & 0.5 & - \\ \hline
			replication & 20 & 50 \\ \hline
			\multilinecell{nb \\ nc \\~\\ } & \multilinecell{40 \\ 81 \\ \hline 121 = 11x11}  & \multilinecell{100 equally spaced \\ points over the domain} \\ \hline
			initialisation & $\vec{u_{apx}} \in \mathcal{N}(0,1)$ & \multilinecell{$\omega_i \in \mathcal{U}[-0.01, 0.01]$ \\ $\gamma_i \in \mathcal{U}(0,1]$ \\ $c_{ik} \in \mathcal{U}[2\Omega]$}  \\ \hline

		\end{tabular}
	}
	\unterschrift{These predefined parameters are used for the following numerical experiments. }{}{}
	\label{tab:ci_parameter}
\end{table}

The parameters $\varphi$ and $\kappa$ are used in the fitness function (equation \eqref{eq:fit_func}) for changing the relative importance of the boundary and the interior. \cite{chaquet_using_2019} take similar values. However, preliminary tests have shown, that the current values perform slightly better on the present testbed. Figure \ref{fig:collocation_weight} shows the values of $\xi$ and $\varphi$. It further describes how the weighting factor emphasises the areas closer to the boundary.

\begin{figure}[h]
	\centering
	\noindent\adjustbox{max width=0.8\linewidth}{
		\includegraphics[width=\textwidth]{../img/pdf/collocation_weight.pdf}
	}
	\unterschrift{Weighting factor $\varphi$ and $\xi$ on every collocation point}{}{}
	\label{fig:collocation_weight}
\end{figure}

The population size used by \cite{chaquet_using_2019} is based on the original formulation of the \gls{cma_es}. However, they observed a better convergence when scaling the recommended population size by three. Typically, \gls{de} uses larger population sizes. \cite{mallipeddi_empirical_2008} describe an empirical study on choosing this parameter. They discuss the trade-off between premature convergence and computational effort. The results suggest that population sizes of $2\cdot dim$ are more likely to stagnate, but also converge faster. Since time is a critical resource for the \gls{ci}-solver, this population size is chosen.

The termination condition for \gls{de} is either a maximum number of function evaluation, or a minimal function value to reach. Since the fitness function (equation \eqref{eq:fit_func}) has its optimum at 0, this value is used as the termination condition. A helpful side-effect is that it ensures the same amount of function evaluation in every run, without early termination. This prevents outliers in the time and memory measurement.

The parameters p and c are specific to JADE (algorithm \ref{algo: jade}). The mutation operator \inlinecode{mutationCurrentToPBest1} uses p to select the best individuals and c weights the parameter adaption mechanism. For all experiments these values are set at $p=0.3$ and $c=0.5$.

To account for the statistical influence, every setup is reevaluated by 20 replications where each replication starts with independent initial guesses.

The \gls{fem} solver terminates after it surpasses $5 \cdot 10^4$ \gls{dof}. The whole number of collocation points ($n_B + n_C$) is the equivalent for the \gls{ci} solver. Typically, fewer collocation points are used, since the evaluation time of the fitness function scales poorly with more points. \cite{chaquet_using_2019} use 100 equally spaced collocation points over the domain to solve the \gls{pde}. Here, 121 points are created, as seen in figure \ref{fig:collocation_points}.

\begin{figure}[h]
	\centering
	\noindent\adjustbox{max width=0.6\linewidth}{
		\includegraphics[width=\textwidth]{../img/pdf/testbed_small_domain.pdf}
	}
	\unterschrift{Collocation points used in the testbed. For the \gls{pde}s 0A and 0B with the larger domain, the lower limits $x_0$L and $x_1$L are replaced with -2 and the upper limits $x_0$U and $x_1$U are replaced with 2. The points are still equally spaced.}{}{}
	\label{fig:collocation_points}
\end{figure}

The initialisation is done by a standard normal distribution. This means that every value in the $\mathbf{p_{apx}}$ vector is drawn from a normal distribution. On the contrary, \cite{chaquet_using_2019} initialise the values specifically tailored to each parameter of the kernel. This process assumes a priori information about the solution. In the typical application, this knowledge is not available and thus it should not be used.

\section{Hardware Infrastructure}
\label{chap:hardware_setup}

To increase the experimental throughput, two machines are used: a personal computer (machine 1) and a server in the cloud (machine 2). It is important that any time or memory usage comparisons must be performed between experiments on the same machine. In the experiments chapter it is separately denoted which comparisons are allowed. The following table \ref{tab:machines} shows the properties of both machines. It is important to note that these information are only a reference point. This is probably not enough to actually recreate the exact time or memory data presented in this work.

\begin{table}[h]
	\centering
	\noindent\adjustbox{max width=\linewidth}{
		\begin{tabular}{|c|c|c|}

			\hline
			\rowcolor[HTML]{\farbeTabA}

			Property & Machine 1 & Machine 2 \\ \hline

			Operating System & Windows 10 Home 1909 18363.900 & CentOS Linux release 7.3.1611 \\ \hline
			Python & Anaconda version 2019.03 & Anaconda version 2020.02 \\ \hline
			Processor & Intel Core i7-4790K CPU @ 4.00GHz & Intel Xeon CPU E5-2630 v3 @ 2.40GHz \\ \hline
			Cores & 4 Cores + 4 logical & 32 Cores \\ \hline

		\end{tabular}
	}
	\unterschrift{Comparison of the machines used for the experiments.}{}{}
	\label{tab:machines}
\end{table}

Due to the Python incompatibilities, NGSolve can only be installed on machine 1. Thus, any time or memory usage comparisons between the \gls{ci} solver and the \gls{fem} solver must be conducted on machine 1.

\end{document}


\subsubsection{\stid{6.02} LLNL ATDM: MFEM}

\paragraph{Overview}

The MFEM library
\cite{MFEM} is focused on providing high-performance mathematical algorithms
and finite element discretizations to next-gen high-order ECP/ATDM
applications. A main component of these efforts is the development of
ATDM-specific physics enhancements in the finite element algorithms in
MFEM and the MFEM-based BLAST Arbitrary Lagrangian-Eulerian (ALE)
code \cite{BLAST}, in order to provide efficient discretization
components for LLNL's ATDM efforts, including the MARBL application
(ECP's LLNLApp).

A second main task in the project is the development of unique unstructured
adaptive mesh refinement (AMR) algorithms in MFEM, that focus on generality,
parallel scalability, and ease of integration in unstructured mesh
applications. The new AMR capabilities can benefit a variety of ECP apps that
use unstructured meshes, as well as many other applications in industry and the
SciDAC program.

Another aspect of the work is the preparation of the MFEM finite element library
and related codes for exascale platforms by using mathematical algorithms and
software implementations that exploit increasing on-node concurrency targeting
multiple complex architectures (e.g. GPUs). This part of the project is
synergistic with and leverages efforts from the ECP CEED co-design center.

MFEM is an open-source finite element library with ~3000 downloads/year from 70+
countries. It is freely available at \url{mfem.org}, on GitHub
at \url{github.com/mfem}, where the MFEM community includes more than 165
members), as well as via Spack and OpenHPC. The application outreach and the
integration in the ECP ecosystem is further facilitated by MFEM's participation
in ECP's xSDK project.

\paragraph{Key Challenges}

The key challenges addressed by the LLNL ATDM Mathematical Libraries project are:

\noindent
{\bf \em Robust high-order finite element methods for ALE compressible flow.}
While high-order methods offer significant advantages in terms of HPC performance,
their application to complicated ALE problems requires careful considerations to
control oscillations and ensure accuracy.

\begin{figure}[htb]
\centering
\includegraphics[width=\textwidth]{projects/2.3.6-NNSA/2.3.6.02-LLNL-ATDM/mfem-amr}
\caption{\label{fig:mfem-amr}AMR implementation in MFEM allows many applications to benefit from non-conforming adaptivity, without significant changes in their codes.}
\end{figure}

\noindent
{\bf \em Scalable algorithms for unstructured adaptive mesh refinement.}
Adaptive mesh refinement is a common way to increasing application efficiency
in problems with localized features. While block-structured AMR has been
well-studied, applying AMR in unstructured settings is challenging, especially
in terms of derefinement, anisotropic refinement, parallel rebalance and
scalability.

\noindent
{\bf \em GPU porting of finite element codes.}
Due to the relatively high complexity of the finite element machinery, MFEM,
BLAST and related codes use object-oriented C++ design that allows generality
and flexibility, but poses challenges in terms of porting to GPU architectures.
Finding the right balance between generality and performance in the GPU context
is an important challenge for many finite element-based codes that remains
outstanding in the current software and programming model environment.

\paragraph{Solution Strategy}

The MFEM team has performed and documented a lot of research in
high-performance mathematical algorithms and finite element discretizations
of interest to ATDM applications
\cite{BLAST18,BLASTFCT18,BLASTFCT17,BLAST16,BLAST14,BLAST13,BLAST12,BLAST11}.
Our work has demonstrated that the high-order finite element approach can
successfully handle coupled multi-material ALE, radiation-diffusion and MHD.
We have also shown how high-order methods can be adapted for monotonicity
(positivity preservation), handling of artificial viscosity (shock capturing),
sub-zonal physics via closure models, etc.

To enable many applications to take advantage of unstructured mesh adaptivity,
the MFEM team is developing AMR algorithms at library level, targeting both
{\em conforming} local refinement on simplex meshes and {\em non-conforming}
refinement for quad/hex meshes. Our approach is fairly general, allowing for
any high-order finite element space, H1, H(curl), H(div), on any high-order
curved mesh in 2D and 3D, arbitrary order hanging nodes, anisotropic refinement,
derifenement and parallel load balancing.
An important feature of our library approach is that it is independent of
the physics, and thus easy to incorporate in apps, see Figure \ref{fig:mfem-amr}.

As part of the efforts in the ECP co-design Center for Efficient Exascale
Discretizations (CEED), the MFEM team is also developing mathematical algorithms
and software implementations for finite element methods that exploit increasingq
on-node concurrency targeting multiple complex architectures (e.g. GPUs). This
work includes the libCEED low-level API library, the Laghos miniapp, and several
other efforts available through CEED.

To reach its many customers and partners in NNSA, DOE Office of Science,
academia and industry, the MFEM team delivers regular releases on GitHub
(e.g. mfem-3.3 in 2017, mfem-3.4 in 2018, mfem-4.0 in 2019) that include
detailed documentation and many example codes.  Code quality is ensured
by smoke tests with Travis CI on Linux, Mac, Windows and nightly
regression testing at LLNL.

\paragraph{Recent Progress}

\begin{figure}[tb]
\centering
\includegraphics[width=.4\textwidth]{projects/2.3.6-NNSA/2.3.6.02-LLNL-ATDM/HO-LO}
\includegraphics[width=.4\textwidth]{projects/2.3.6-NNSA/2.3.6.02-LLNL-ATDM/mfem-gpu}
\caption{The MFEM team has developed High-Order $\protect\leftrightarrow$ Low-Order Transformations and GPU support for many linear algebra and finite element operations}
\end{figure}

Selected recent highlights:
\begin{itemize}
\item
Developed ALE discretization methods that support {\it completely lossless}
high order to low order transformations, and vice versa.
\item
Delivered MFEM 4.0 release, with initial GPU support for many linear
algebra and finite elementn operations.
\item
Developed a new formulation for discretizing problems with 1D spherical symmetry
in BLAST. Extended BLAST to the 3T-model (separate equations for the electron
and ion internal energies). Added support for changing masses during the
Lagrangian phase.
\item
Completed the delivery of discretization support for the FY18 MARBL ATDM L2
milestone, including new 3T radiation-diffusion algorithms, and a simulation
capability for problems with spherical and cylindrical symmetry via weight
adjustments.
%With this and other support from the MFEM team, the MARBL team
%successfully defended its ATDM L2 milestone.
\item
Worked on high-order ALE algorithms in BLAST: developed remap step for density
component masses, various code improvements and bugs fixes related to L2
milestone.
%% \item
%% MFEM version 3.4 was released with many new features including: significantly
%% improved non-conforming unstructured AMR scalability; integration with PUMI;
%% block nonlinear operators and variable order NURBS; Conduit mesh blueprint
%% support; general high-order-to-low-order refined field transfer; new specialized
%% time integrators and 12 new examples and miniapps.
%% \item
%% Implemented an initial draft of MFEM’s ``engine'' interface extension to support
%% GPUs and other accelerators. Performed tests with the new ``engine'' extension
%% on Sierra. Explored its use in the Laghos miniapp and BLAST.
%% \item
%% Improvements in AMR interpolation matrix for better construction of
%% communication groups and performance monitoring in the Laghos miniapp.
%% \item
%% Several AMR improvements, including better local conforming tetrahedral
%% refinement (collaborating with a GitHub user), fix for boundary coefficient
%% projection, and general communication groups on for non-conforming AMR
%% supporting the AMR integration in BLAST.
%% \item
%% With summer student made progress on matrix-free algorithms for high-order field
%% monotonicity, targeting performance improvements in the remap phase of
%% MARBL/BLAST.
%% \item
%% GLVis version 3.4 was released with several new features including: 10 new color
%% palettes, better multi-screen window manager support, capability to show element
%% and vertex numbering in 2D, use of X.509 certificates in secure sockets, and a
%% new CMake build system.
%% \item
%% Developed a new version of the hogtess high order experimental visualization
%% tool based on modern OpenGL 4.3 compute shaders that does correct cutting of
%% high order meshes in 3D.
\end{itemize}

\paragraph{Next Steps}

The MFEM team will next demonstrate the use of our HO/LO mappings on
general unstructured meshes in ATDM application at scale.  This includes
new discretization enhancements and new algorithms for ALE multi-physics
applications, in particular in support of the MARBL appliaction's L2
milestone, especially with respect to the transition to exascale
hardware.  We will have MFEM running on early access machines as soon as
they become available, and will support production runs on exascale platforms.


This appendix presents the complete type system of Typed Lua.

\section{Subtyping rules}

\noindent

\mylabel{S-LITERAL}
\[
\senv \vdash L \subtype L
\]

\mylabel{S-FALSE}
\[
\senv \vdash \False \subtype \Boolean
\]

\mylabel{S-TRUE}
\[
\senv \vdash \True \subtype \Boolean
\]

\mylabel{S-STRING}
\[
\senv \vdash {\it string} \subtype \String
\]

\mylabel{S-INT1}
\[
\senv \vdash {\it int} \subtype \Integer
\]

\mylabel{S-INT2}
\[
\senv \vdash {\it int} \subtype \Number
\]

\mylabel{S-FLOAT}
\[
\senv \vdash {\it float} \subtype \Number
\]

\mylabel{S-BASE}
\[
\senv \vdash B \subtype B
\]

\mylabel{S-INTEGER}
\[
\senv \vdash \Integer \subtype \Number
\]

\mylabel{S-NIL}
\[
\senv \vdash \Nil \subtype \Nil
\]

\mylabel{S-VALUE}
\[
\senv \vdash F \subtype \Value
\]

\mylabel{S-ANY}
\[
\senv \vdash \Any \subtype \Any
\]

\mylabel{S-SELF}
\[
\senv \vdash \Self \subtype \Self
\]

\mylabel{S-UNION1}
\[
\dfrac{\senv \vdash F_{1} \subtype F \;\;\;
       \senv \vdash F_{2} \subtype F}
      {\senv \vdash F_{1} \cup F_{2} \subtype F}
\]

\mylabel{S-UNION2}
\[
\dfrac{\senv \vdash F \subtype F_{1}}
      {\senv \vdash F \subtype F_{1} \cup F_{2}}
\]

\mylabel{S-UNION3}
\[
\dfrac{\senv \vdash F \subtype F_{2}}
      {\senv \vdash F \subtype F_{1} \cup F_{2}}
\]

\mylabel{S-FUNCTION}
\[
\dfrac{\senv \vdash S_{3} \subtype S_{1} \;\;\;
       \senv \vdash S_{2} \subtype S_{4}}
      {\senv \vdash S_{1} \rightarrow S_{2} \subtype S_{3} \rightarrow S_{4}}
\]

\mylabel{S-PAIR}
\[
\dfrac{\senv \vdash F_{1} \subtype F_{2} \;\;\;
       \senv \vdash P_{1} \subtype P_{2}}
      {\senv \vdash F_{1} \times P_{1} \subtype F_{2} \times P_{2}}
\]

\mylabel{S-VARARG1}
\[
\dfrac{\senv \vdash F_{1} \cup \Nil \subtype F_{2} \cup \Nil}
      {\senv \vdash F_{1}{*} \subtype F_{2}{*}}
\]

\mylabel{S-VARARG2}
\[
\dfrac{\senv \vdash F_{1} \cup \Nil \subtype F_{2} \;\;\;
       \senv \vdash F_{1}{*} \subtype P_{2}}
      {\senv \vdash F_{1}{*} \subtype F_{2} \times P_{2}}
\]

\mylabel{S-VARARG3}
\[
\dfrac{\senv \vdash F_{1} \subtype F_{2} \cup \Nil \;\;\;
       \senv \vdash P_{1} \subtype F_{2}{*}}
      {\senv \vdash F_{1} \times P_{1} \subtype F_{2}{*}}
\]

\mylabel{S-UNION4}
\[
\dfrac{\senv \vdash S_{1} \subtype S \;\;\;
       \senv \vdash S_{2} \subtype S}
      {\senv \vdash S_{1} \sqcup S_{2} \subtype S}
\]

\mylabel{S-UNION5}
\[
\dfrac{\senv \vdash S \subtype S_{1}}
      {\senv \vdash S \subtype S_{1} \sqcup S_{2}}
\]

\mylabel{S-UNION6}
\[
\dfrac{\senv \vdash S \subtype S_{2}}
      {\senv \vdash S \subtype S_{1} \sqcup S_{2}}
\]

\mylabel{S-TABLE1}
\[
\dfrac{\forall i \; \exists j \;\;\;
       \senv \vdash F_{j} \subtype F_{i}' \;\;\;
       \senv \vdash F_{i}' \subtype F_{j} \;\;\;
       \senv \vdash V_{j} \subtype_{c} V_{i}'}
      {\senv \vdash \{\overline{F{:}V}\}_{fixed|closed} \subtype
                    \{\overline{F'{:}V'}\}_{closed}}
\]

\mylabel{S-TABLE2}
\[
\dfrac{\begin{array}{c}
       \forall i \; \forall j \;\;\;
       \senv \vdash F_{i} \subtype F_{j}' \to \senv \vdash V_{i} \subtype_{u} V_{j}'\\
       \forall j \; \nexists i \;\;\;
       \senv \vdash F_{i} \subtype F_{j}' \to \senv \vdash \Nil \subtype_{o} V_{j}'
       \end{array}}
      {\senv \vdash \{\overline{F{:}V}\}_{unique} \subtype
                    \{\overline{F'{:}V'}\}_{closed}}
\]

\mylabel{S-TABLE3}
\[
\dfrac{\begin{array}{c}
       \forall i \; \exists j \;\;\;
       \senv \vdash F_{i} \subtype F_{j}' \land \senv \vdash V_{i} \subtype_{u} V_{j}' \\
       \forall j \; \nexists i \;\;\;
       \senv \vdash F_{i} \subtype F_{j}' \to \senv \vdash \Nil \subtype_{o} V_{j}'
       \end{array}}
      {\senv \vdash \{\overline{F{:}V}\}_{unique} \subtype
                    \{\overline{F'{:}V'}\}_{unique|open|fixed}}
\]

\mylabel{S-TABLE4}
\[
\dfrac{\begin{array}{c}
       \forall i \; \forall j \;\;\;
       \senv \vdash F_{i} \subtype F_{j}' \to \senv \vdash V_{i} \subtype_{c} V_{j}' \\
       \forall j \; \nexists i \;\;\;
       \senv \vdash F_{i} \subtype F_{j}' \to \senv \vdash \Nil \subtype_{o} V_{j}'
       \end{array}}
      {\senv \vdash \{\overline{F{:}V}\}_{open} \subtype
                    \{\overline{F'{:}V'}\}_{closed}}
\]

\mylabel{S-TABLE5}
\[
\dfrac{\begin{array}{c}
       \forall i \; \exists j \;\;\;
       \senv \vdash F_{i} \subtype F_{j}' \land \senv \vdash V_{i} \subtype_{c} V_{j}' \\
       \forall j \; \nexists i \;\;\;
       \senv \vdash F_{i} \subtype F_{j}' \to \senv \vdash \Nil \subtype_{o} V_{j}'
       \end{array}}
      {\senv \vdash \{\overline{F{:}V}\}_{open} \subtype
                    \{\overline{F'{:}V'}\}_{open|fixed}}
\]

\mylabel{S-TABLE6}
\[
\dfrac{\begin{array}{c}
       \forall i \; \exists j \;\;\;
       \senv \vdash F_{i} \subtype F_{j}' \;\;\;
       \senv \vdash F_{j}' \subtype F_{i} \;\;\;
       \senv \vdash V_{i} \subtype_{c} V_{j}' \\
       \forall j \; \exists i \;\;\;
       \senv \vdash F_{i} \subtype F_{j}' \;\;\;
       \senv \vdash F_{j}' \subtype F_{i} \;\;\;
       \senv \vdash V_{i} \subtype_{c} V_{j}' \\
       \end{array}}
      {\senv \vdash \{\overline{F{:}V}\}_{fixed} \subtype
                    \{\overline{F'{:}V'}\}_{fixed}}
\]

\mylabel{S-FIELD1}
\[
\dfrac{\senv \vdash F_{1} \subtype F_{2} \;\;\;
       \senv \vdash F_{2} \subtype F_{1}}
      {\senv \vdash F_{1} \subtype_{c} F_{2}}
\]

\mylabel{S-FIELD2}
\[
\dfrac{\senv \vdash F_{1} \subtype F_{2}}
      {\senv \vdash \Const \; F_{1} \subtype_{c} \Const \; F_{2}}
\]

\mylabel{S-FIELD3}
\[
\dfrac{\senv \vdash F_{1} \subtype F_{2}}
      {\senv \vdash F_{1} \subtype_{c} \Const \; F_{2}}
\]

\mylabel{S-FIELD4}
\[
\dfrac{\senv \vdash F_{1} \subtype F_{2}}
      {\senv \vdash F_{1} \subtype_{u} F_{2}}
\]

\mylabel{S-FIELD5}
\[
\dfrac{\senv \vdash F_{1} \subtype F_{2}}
      {\senv \vdash \Const \; F_{1} \subtype_{u} \Const \; F_{2}}
\]

\mylabel{S-FIELD6}
\[
\dfrac{\senv \vdash F_{1} \subtype F_{2}}
      {\senv \vdash \Const \; F_{1} \subtype_{u} F_{2}}
\]

\mylabel{S-FIELD7}
\[
\dfrac{\senv \vdash F_{1} \subtype F_{2}}
      {\senv \vdash F_{1} \subtype_{u} \Const \; F_{2}}
\]

\mylabel{S-FIELD8}
\[
\dfrac{\senv \vdash \Nil \subtype F}
      {\senv \vdash \Nil \subtype_{o} F}
\]

\mylabel{S-FIELD9}
\[
\dfrac{\senv \vdash \Nil \subtype F}
      {\senv \vdash \Nil \subtype_{o} \Const \; F}
\]

\mylabel{S-AMBER}
\[
\dfrac{\senv[x_{1} \subtype x_{2}] \vdash F_{1} \subtype F_{2}}
      {\senv \vdash \mu x_{1}.F_{1} \subtype \mu x_{2}.F_{2}}
\]

\mylabel{S-ASSUMPTION}
\[
\dfrac{x_{1} \subtype x_{2} \in \senv}
      {\senv \vdash x_{1} \subtype x_{2}}
\]

\mylabel{S-UNFOLDR}
\[
\dfrac{\senv \vdash F_{1} \subtype [x \mapsto \mu x.F_{2}]F_{2}}
      {\senv \vdash F_{1} \subtype \mu x.F_{2}}
\]

\mylabel{S-UNFOLDL}
\[
\dfrac{\senv \vdash [x \mapsto \mu x.F_{1}]F_{1} \subtype F_{2}}
      {\senv \vdash \mu x.F_{1} \subtype F_{2}}
\]

\mylabel{S-EXPRESSION}
\[
\senv \vdash T \subtype T
\]

\mylabel{S-PAIR2}
\[
\dfrac{\senv \vdash T_{1} \subtype T_{2} \;\;\;
       \senv \vdash E_{1} \subtype E_{2}}
      {\senv \vdash T_{1} \times E_{1} \subtype T_{2} \times E_{2}}
\]

\mylabel{S-VARARG4}
\[
\dfrac{\senv \vdash T_{1} \cup \Nil \subtype T_{2} \cup \Nil}
      {\senv \vdash T_{1}{*} \subtype T_{2}{*}}
\]

\mylabel{S-VARARG5}
\[
\dfrac{\senv \vdash T_{1} \cup \Nil \subtype T_{2} \;\;\;
       \senv \vdash T_{1}{*} \subtype E_{2}}
      {\senv \vdash T_{1}{*} \subtype T_{2} \times E_{2}}
\]

\mylabel{S-VARARG6}
\[
\dfrac{\senv \vdash T_{1} \subtype T_{2} \cup \Nil \;\;\;
       \senv \vdash E_{1} \subtype T_{2}{*}}
      {\senv \vdash T_{1} \times E_{1} \subtype T_{2}{*}}
\]

\mylabel{C-ANY1}
\[
\senv \vdash F \lesssim \Any
\]

\mylabel{C-ANY2}
\[
\senv \vdash \Any \lesssim F
\]

\section{Typing rules}

\noindent

\mylabel{T-SKIP}
\[
\env_{1}, \penv \vdash \mathbf{skip}, \env_{1}
\]

\mylabel{T-SEQ}
\[
\dfrac{\env_{1}, \penv \vdash s_{1}, \env_{2} \;\;\;
       \env_{2}, \penv \vdash s_{2}, \env_{3}}
      {\env_{1}, \penv \vdash s_{1} \; ; \; s_{2}, \env_{3}}
\]

\mylabel{T-ASSIGNMENT}
\[
\dfrac{\env_{1}, \penv \vdash el:S_{1}, \env_{2} \;\;\;
       \env_{2}, \penv \vdash \overline{l}:S_{2}, \env_{3} \;\;\;
       S_{1} \lesssim S_{2}}
      {\env_{1}, \penv \vdash \overline{l} = el,\env_{3}}
\]

\mylabel{T-METHOD1}
\[
\dfrac{\begin{array}{c}
       \env_{1}(id_{1}) = F_{s} \;\;\;
       F_{s} = \{\overline{F{:}V}\}_{unique} \\
       \env_{1}, \penv \vdash id_{2} : L, \env_{2} \;\;\;
       \nexists i \in 1..n \; L \lesssim F_{i} \;\;\;
       n = |\overline{F{:}V}| \\
       closeall(\env_{1})[self \mapsto \Self, \overline{id \mapsto F}, \self \mapsto F_{s}],
       \penv[\ret \mapsto S] \vdash s, \env_{3}\\
       F_{o} = \{\overline{F{:}V}, L{:}\Const \; \Self \times F_{1} \times ... \times F_{n} \times \Nil{*} \rightarrow S\}_{unique}\\
       \env_{4} = openset(\env_{1}[id_{1} \mapsto F_{o}], frv(\mathbf{fun} \; (\overline{id{:}T}){:}S \; s)) \\
       \env_{5} = closeset(\env_{4}, fav(\mathbf{fun} \; (\overline{id{:}T}){:}S \; s))
       \end{array}}
      {\begin{array}{c}
       \env_{1}, \penv \vdash \mathbf{fun} \; id_{1}{:}id_{2} \; (\overline{id{:}F}){:}S \; s, \env_{5}\\
       \end{array}}
\]

\mylabel{T-METHOD2}
\[
\dfrac{\begin{array}{c}
       \env_{1}(id_{1}) = F_{s} \;\;\;
       F_{s} = \{\overline{F{:}V}\}_{open} \\
       \env_{1}, \penv \vdash id_{2} : L, \env_{2} \;\;\;
       \nexists i \in 1..n \; L \lesssim F_{i} \;\;\;
       n = |\overline{F{:}V}| \\
       closeall(\env_{1})[self \mapsto \Self, \overline{id \mapsto F}, \self \mapsto F_{s}],
       \penv[\ret \mapsto S] \vdash s, \env_{3}\\
       F_{o} = \{\overline{F{:}V}, L{:}\Const \; \Self \times F_{1} \times ... \times F_{n} \times \Nil{*} \rightarrow S\}_{open}\\
       \env_{4} = openset(\env_{1}[id_{1} \mapsto F_{o}], frv(\mathbf{fun} \; (\overline{id{:}T}){:}S \; s)) \\
       \env_{5} = closeset(\env_{4}, fav(\mathbf{fun} \; (\overline{id{:}T}){:}S \; s))
       \end{array}}
      {\begin{array}{c}
       \env_{1}, \penv \vdash \mathbf{fun} \; id_{1}{:}id_{2} \; (\overline{id{:}F}){:}S \; s, \env_{5}\\
       \end{array}}
\]

\mylabel{T-METHOD3}
\[
\dfrac{\begin{array}{c}
       \env_{1}(id_{1}) = F_{s} \;\;\;
       F_{s} = \{\overline{F{:}V}\}_{unique} \\
       \env_{1}, \penv \vdash id_{2} : L, \env_{2} \;\;\;
       \nexists i \in 1..n \; L \lesssim F_{i} \;\;\;
       n = |\overline{F{:}V}| \\
       closeall(\env_{1})[self \mapsto \Self, \overline{id \mapsto F}, {...} \mapsto F, \self \mapsto F_{s}],
       \penv[\ret \mapsto S] \vdash s, \env_{3}\\
       F_{o} = \{\overline{F{:}V}, L{:}\Const \; \Self \times F_{1} \times ... \times F_{n} \times F{*} \rightarrow S\}_{unique}\\
       \env_{4} = openset(\env_{1}[id_{1} \mapsto F_{o}], frv(\mathbf{fun} \; (\overline{id{:}T}){:}S \; s)) \\
       \env_{5} = closeset(\env_{4}, fav(\mathbf{fun} \; (\overline{id{:}T}){:}S \; s))
       \end{array}}
      {\begin{array}{c}
       \env_{1}, \penv \vdash \mathbf{fun} \; id_{1}{:}id_{2} \; (\overline{id{:}F},{...}{:}F){:}S \; s, \env_{5}\\
       \end{array}}
\]

\mylabel{T-METHOD4}
\[
\dfrac{\begin{array}{c}
       \env_{1}(id_{1}) = F_{s} \;\;\;
       F_{s} = \{\overline{F{:}V}\}_{open} \\
       \env_{1}, \penv \vdash id_{2} : L, \env_{2} \;\;\;
       \nexists i \in 1..n \; L \lesssim F_{i} \;\;\;
       n = |\overline{F{:}V}| \\
       closeall(\env_{1})[self \mapsto \Self, \overline{id \mapsto F}, {...} \mapsto F, \self \mapsto F_{s}],
       \penv[\ret \mapsto S] \vdash s, \env_{3}\\
       F_{o} = \{\overline{F{:}V}, L{:}\Const \; \Self \times F_{1} \times ... \times F_{n} \times F{*} \rightarrow S\}_{open}\\
       \env_{4} = openset(\env_{1}[id_{1} \mapsto F_{o}], frv(\mathbf{fun} \; (\overline{id{:}T}){:}S \; s)) \\
       \env_{5} = closeset(\env_{4}, fav(\mathbf{fun} \; (\overline{id{:}T}){:}S \; s))
       \end{array}}
      {\begin{array}{c}
       \env_{1}, \penv \vdash \mathbf{fun} \; id_{1}{:}id_{2} \; (\overline{id{:}F},{...}{:}F){:}S \; s, \env_{5}\\
       \end{array}}
\]

\mylabel{T-METHOD5}
\[
\dfrac{\begin{array}{c}
       \env_{1}(id_{1}) = F_{s} \;\;\;
       F_{s} = \{\overline{F{:}V}\}_{unique} \;\;\;
       \env_{1}, \penv \vdash id_{2} : L, \env_{2} \;\;\;
       n = |\overline{F{:}V}| \\
       \exists i \in 1..n \; L \subtype F_{i} \wedge F_{i} \subtype L \wedge
       \Const \; \Self \times F_{1} \times ... \times F_{n} \times \Nil{*} \rightarrow S \subtype V_{i} \\
       closeall(\env_{1})[self \mapsto \Self, \overline{id \mapsto F}, \self \mapsto F_{s}],
       \penv[\ret \mapsto S] \vdash s, \env_{3}\\
       V_{i} \mapsto \Const \; \Self \times F_{1} \times ... \times F_{n} \times \Nil{*} \rightarrow S\\
       \env_{4} = openset(\env_{1}[id_{1} \mapsto F_{s}], frv(\mathbf{fun} \; (\overline{id{:}T}){:}S \; s)) \\
       \env_{5} = closeset(\env_{4}, fav(\mathbf{fun} \; (\overline{id{:}T}){:}S \; s))
       \end{array}}
      {\begin{array}{c}
       \env_{1}, \penv \vdash \mathbf{fun} \; id_{1}{:}id_{2} \; (\overline{id{:}F}){:}S \; s, \env_{5}\\
       \end{array}}
\]

\mylabel{T-METHOD6}
\[
\dfrac{\begin{array}{c}
       \env_{1}(id_{1}) = F_{s} \;\;\;
       F_{s} = \{\overline{F{:}V}\}_{open} \;\;\;
       \env_{1}, \penv \vdash id_{2} : L, \env_{2} \;\;\;
       n = |\overline{F{:}V}| \\
       \exists i \in 1..n \; L \subtype F_{i} \wedge F_{i} \subtype L \wedge
       \Const \; \Self \times F_{1} \times ... \times F_{n} \times \Nil{*} \rightarrow S \subtype V_{i} \\
       closeall(\env_{1})[self \mapsto \Self, \overline{id \mapsto F}, \self \mapsto F_{s}],
       \penv[\ret \mapsto S] \vdash s, \env_{3}\\
       V_{i} \mapsto \Const \; \Self \times F_{1} \times ... \times F_{n} \times \Nil{*} \rightarrow S\\
       \env_{4} = openset(\env_{1}[id_{1} \mapsto F_{s}], frv(\mathbf{fun} \; (\overline{id{:}T}){:}S \; s)) \\
       \env_{5} = closeset(\env_{4}, fav(\mathbf{fun} \; (\overline{id{:}T}){:}S \; s))
       \end{array}}
      {\begin{array}{c}
       \env_{1}, \penv \vdash \mathbf{fun} \; id_{1}{:}id_{2} \; (\overline{id{:}F}){:}S \; s, \env_{5}\\
       \end{array}}
\]

\mylabel{T-METHOD7}
\[
\dfrac{\begin{array}{c}
       \env_{1}(id_{1}) = F_{s} \;\;\;
       F_{s} = \{\overline{F{:}V}\}_{unique} \;\;\;
       \env_{1}, \penv \vdash id_{2} : L, \env_{2} \;\;\;
       n = |\overline{F{:}V}| \\
       \exists i \in 1..n \; L \subtype F_{i} \wedge F_{i} \subtype L \wedge
       \Const \; \Self \times F_{1} \times ... \times F_{n} \times F{*} \rightarrow S \subtype V_{i} \\
       closeall(\env_{1})[self \mapsto \Self, \overline{id \mapsto F}, {...} \mapsto F, \self \mapsto F_{s}],
       \penv[\ret \mapsto S] \vdash s, \env_{3}\\
       V_{i} \mapsto \Const \; \Self \times F_{1} \times ... \times F_{n} \times F{*} \rightarrow S\\
       \env_{4} = openset(\env_{1}[id_{1} \mapsto F_{s}], frv(\mathbf{fun} \; (\overline{id{:}T}){:}S \; s)) \\
       \env_{5} = closeset(\env_{4}, fav(\mathbf{fun} \; (\overline{id{:}T}){:}S \; s))
       \end{array}}
      {\begin{array}{c}
       \env_{1}, \penv \vdash \mathbf{fun} \; id_{1}{:}id_{2} \; (\overline{id{:}F},{...}{:}F){:}S \; s, \env_{5}\\
       \end{array}}
\]

\mylabel{T-METHOD8}
\[
\dfrac{\begin{array}{c}
       \env_{1}(id_{1}) = F_{s} \;\;\;
       F_{s} = \{\overline{F{:}V}\}_{open} \;\;\;
       \env_{1}, \penv \vdash id_{2} : L, \env_{2} \;\;\;
       n = |\overline{F{:}V}| \\
       \exists i \in 1..n \; L \subtype F_{i} \wedge F_{i} \subtype L \wedge
       \Const \; \Self \times F_{1} \times ... \times F_{n} \times F{*} \rightarrow S \subtype V_{i} \\
       closeall(\env_{1})[self \mapsto \Self, \overline{id \mapsto F}, {...} \mapsto F, \self \mapsto F_{s}],
       \penv[\ret \mapsto S] \vdash s, \env_{3}\\
       V_{i} \mapsto \Const \; \Self \times F_{1} \times ... \times F_{n} \times F{*} \rightarrow S\\
       \env_{4} = openset(\env_{1}[id_{1} \mapsto F_{s}], frv(\mathbf{fun} \; (\overline{id{:}T}){:}S \; s)) \\
       \env_{5} = closeset(\env_{4}, fav(\mathbf{fun} \; (\overline{id{:}T}){:}S \; s))
       \end{array}}
      {\begin{array}{c}
       \env_{1}, \penv \vdash \mathbf{fun} \; id_{1}{:}id_{2} \; (\overline{id{:}F},{...}{:}F){:}S \; s, \env_{5}\\
       \end{array}}
\]

\mylabel{T-WHILE1}
\[
\dfrac{\begin{array}{c}
       \env_{1}, \penv \vdash e:F, \env_{2} \;\;\;
       closeall(\env_{2}), \penv \vdash s, \env_{3}\\
       \env_{4} = closeset(\env_{2}, fav(s)) \\
       \env_{5} = openset(\env_{4},frv(s))
       \end{array}}
      {\env_{1}, \penv \vdash \mathbf{while} \; e \; \mathbf{do} \; s,\env_{5}}
\]

\mylabel{T-WHILE2}
\[
\dfrac{\begin{array}{c}
       \env_{1}(id) = F\\
       closeall(\env_{1}[id \mapsto \phi(F, filter(F, \Nil))]), \penv \vdash s, \env_{2}\\
       \env_{3} = openset(\env_{1}[id \mapsto F], frv(s))\\
       \env_{4} = closeset(\env_{3}, fav(s))
       \end{array}}
      {\env_{1}, \penv \vdash \mathbf{while} \; id \; \mathbf{do} \; s,\env_{4}}
\]

\mylabel{T-IF1}
\[
\dfrac{\begin{array}{c}
       \env_{1}, \penv \vdash e:T, \env_{2} \;\;\;
       \env_{2}, \penv \vdash s_{1}:\env_{3} \;\;\;
       \env_{2}, \penv \vdash s_{2}:\env_{4} \;\;\;
       \env_{5} = join(\env_{3}, \env_{4})
       \end{array}}
      {\env_{1} \vdash \mathbf{if} \; e \; \mathbf{then} \; s_{1} \; \mathbf{else} \; s_{2}, \env_{5}}
\]

\mylabel{T-IF2}
\[
\dfrac{\begin{array}{c}
       \env_{1}(id) = F \;\;\;
       F_{t} = fot(F, \Nil) \;\;\;
       F_{e} = fit(F, \Nil) \\
       \env_{1}[id \mapsto \phi(F,F_{t})], \penv \vdash s_{1}, \env_{2}\\
       \env_{1}[id \mapsto \phi(F,F_{e})], \penv \vdash s_{2}, \env_{3}\\
       \env_{4} = join(\env_{2}, \env_{3})
      \end{array}}
      {\env_{1}, \penv \vdash \mathbf{if} \; id \; \mathbf{then} \; s_{1} \; \mathbf{else} \; s_{2}, \env_{4}[id \mapsto F]}
\]

\mylabel{T-IF3}
\[
\dfrac{\begin{array}{c}
       \env_{1}(id) = F \;\;\;
       F_{t} = fot(F, \Nil) \;\;\;
       F_{e} = fit(F, \Nil) \\
       F_{e} = \Void \;\;\;
       \env_{1}[id \mapsto \phi(F,F_{t})], \penv \vdash s_{1}, \env_{2}
      \end{array}}
      {\env_{1}, \penv \vdash \mathbf{if} \; id \; \mathbf{then} \; s_{1} \; \mathbf{else} \; s_{2}, \env_{2}[id \mapsto F]}
\]

\mylabel{T-IF4}
\[
\dfrac{\begin{array}{c}
       \env_{1}(id) = F \;\;\;
       F_{t} = fot(F, \Nil) \;\;\;
       F_{e} = fit(F, \Nil) \\
       F_{t} = \Void \;\;\;
       \env_{1}[id \mapsto \phi(F,F_{e})], \penv \vdash s_{2}, \env_{2}
      \end{array}}
      {\env_{1}, \penv \vdash \mathbf{if} \; id \; \mathbf{then} \; s_{1} \; \mathbf{else} \; s_{2}, \env_{2}[id \mapsto F]}
\]

\mylabel{T-IF5}
\[
\dfrac{\begin{array}{c}
       \env_{1}(id) = \pi_{i}^{x} \\
       S_{t} = fopt(\penv(x), \Nil, i) \;\;\;
       S_{e} = fipt(\penv(x), \Nil, i) \\
       \env_{1}, \penv[x \mapsto S_{t}] \vdash s_{1}, \env_{2}\\
       \env_{1}, \penv[x \mapsto S_{e}] \vdash s_{2}, \env_{3}\\
       \env_{4} = join(\env_{2}, \env_{3})
      \end{array}}
      {\env_{1}, \penv \vdash \mathbf{if} \; id \; \mathbf{then} \; s_{1} \; \mathbf{else} \; s_{2}, \env_{4}}
\]

\mylabel{T-IF6}
\[
\dfrac{\begin{array}{c}
       \env_{1}(id) = \pi_{i}^{x} \\
       S_{t} = fopt(\penv(x), \Nil, i) \\
       fit(proj(\penv(x), i), \Nil) = \Void \\
       \env_{1}, \penv[x \mapsto S_{t}] \vdash s_{1}, \env_{2}
      \end{array}}
      {\env_{1}, \penv \vdash \mathbf{if} \; id \; \mathbf{then} \; s_{1} \; \mathbf{else} \; s_{2}, \env_{2}}
\]

\mylabel{T-IF7}
\[
\dfrac{\begin{array}{c}
       \env_{1}(id) = \pi_{i}^{x} \\
       S_{e} = fipt(\penv(x), \Nil, i) \\
       fot(proj(\penv(x), i), \Nil) = \Void \\
       \env_{1}, \penv[x \mapsto S_{e}] \vdash s_{2}, \env_{2}
      \end{array}}
      {\env_{1}, \penv \vdash \mathbf{if} \; id \; \mathbf{then} \; s_{1} \; \mathbf{else} \; s_{2}, \env_{2}}
\]

\mylabel{T-IF8}
\[
\dfrac{\begin{array}{c}
       \env_{1}(id) = \phi(F_{1},F_{2}) \;\;\;
       F_{t} = fit(F_{2}, \String) \;\;\;
       F_{e} = fot(F_{2}, \String) \\
       \env_{1}[id \mapsto \phi(F_{1},F_{t})], \penv \vdash s_{1}, \env_{2}\\
       \env_{1}[id \mapsto \phi(F_{1},F_{e})], \penv \vdash s_{2}, \env_{3}\\
       \env_{4} = join(\env_{2}, \env_{3})
      \end{array}}
      {\env_{1}, \penv \vdash \mathbf{if} \; type(id) == ``string" \; \mathbf{then} \; s_{1} \; \mathbf{else} \; s_{2}, \env_{4}[id \mapsto F_{1}]}
\]

\mylabel{T-IF9}
\[
\dfrac{\begin{array}{c}
       \env_{1}(id) = \phi(F_{1},F_{2}) \;\;\;
       F_{t} = fit(F_{2}, \String) \;\;\;
       F_{e} = fot(F_{2}, \String) \\
       F_{t} = \Void \;\;\;
       \env_{1}[id \mapsto \phi(F_{1},F_{e})], \penv \vdash s_{2}, \env_{2}
      \end{array}}
      {\env_{1}, \penv \vdash \mathbf{if} \; type(id) == ``string" \; \mathbf{then} \; s_{1} \; \mathbf{else} \; s_{2}, \env_{2}[id \mapsto F_{1}]}
\]

\mylabel{T-IF10}
\[
\dfrac{\begin{array}{c}
       \env_{1}(id) = \phi(F_{1},F_{2}) \;\;\;
       F_{t} = fit(F_{2}, \String) \;\;\;
       F_{e} = fot(F_{2}, \String) \\
       F_{e} = \Void \;\;\;
       \env_{1}[id \mapsto \phi(F_{1},F_{t})], \penv \vdash s_{1}, \env_{2}
      \end{array}}
      {\env_{1}, \penv \vdash \mathbf{if} \; type(id) == ``string" \; \mathbf{then} \; s_{1} \; \mathbf{else} \; s_{2}, \env_{2}[id \mapsto F_{1}]}
\]

\mylabel{T-LOCAL1}
\[
\dfrac{\begin{array}{c}
       \env_{1}, \penv \vdash el:S, \env_{2} \\
       S \lesssim F_{1} \times ... \times F_{n} \times \Value{*} \;\;\;
       n = |\;\overline{id{:}F}\;| \\
       \env_{2}[\overline{id \mapsto F}], \penv \vdash s, \env_{3}
       \end{array}}
      {\env_{1}, \penv \vdash \mathbf{local} \; \overline{id{:}F} = el \; \mathbf{in} \; s, (\env_{3} - \{\overline{id}\})[\overline{id \mapsto \env_{2}(id)]}}
\]

\mylabel{T-LOCAL2}
\[
\dfrac{\begin{array}{c}
       \env_{1}, \penv \vdash el:E, \env_{2}, (x,S) \\
       \env_{3} = \env_{2}[id_{1} \mapsto infer(E,1), ..., id_{n} \mapsto infer(E,n)] \\
       \env_{3}, \penv[x \mapsto S] \vdash s, \env_{4} \;\;\;
       n = |\;\overline{id}\;|
       \end{array}}
      {\env_{1}, \penv \vdash \mathbf{local} \; \overline{id} = el \; \mathbf{in} \; s, (\env_{4} - \{\overline{id}\})[\overline{id \mapsto \env_{2}(id)]}}
\]

\mylabel{T-LOCALREC}
\[
\dfrac{\env_{1}[id \mapsto F], \penv \vdash e:F_{1}, \env_{2} \;\;\;
       F_{1} \lesssim F \;\;\;
       \env_{2}, \penv \vdash s, \env_{3}}
      {\env_{1}, \penv \vdash \mathbf{rec} \; id{:}F = e \; \mathbf{in} \; s, (\env_{3} - \{id\})[\overline{id \mapsto \env_{2}(id)]}}
\]

\mylabel{T-RETURN}
\[
\dfrac{\env_{1} \vdash el:S_{1}, \env_{2} \;\;\;
       \penv(\ret) = S_{2} \;\;\;
       S_{1} \lesssim S_{2}}
      {\env_{1} \vdash \mathbf{return} \; el, \env_{2}}
\]

\mylabel{T-STMAPPLY1}
\[
\dfrac{\env_{1}, \penv \vdash e(el):S, \env_{2}}
      {\env_{1}, \penv \vdash \lfloor e(el) \rfloor_{0},\env_{2}}
\]

\mylabel{T-STMINVOKE1}
\[
\dfrac{\env_{1}, \penv \vdash e{:}n(el):S, \env_{2}}
      {\env_{1}, \penv \vdash \lfloor e{:}n(el) \rfloor_{0}, \env_{2}}
\]

\mylabel{T-NIL}
\[
\env_{1}, \penv \vdash \mathbf{nil}:\Nil, \env_{1}
\]

\mylabel{T-FALSE}
\[
\env_{1}, \penv \vdash \mathbf{false}:\False, \env_{1}
\]

\mylabel{T-TRUE}
\[
\env_{1}, \penv \vdash \mathbf{true}:\True, \env_{1}
\]

\mylabel{T-INT}
\[
\env_{1}, \penv \vdash {\it int}:{\it int}, \env_{1}
\]

\mylabel{T-FLOAT}
\[
\env_{1}, \penv \vdash {\it float}:{\it float}, \env_{1}
\]

\mylabel{T-STR}
\[
\env_{1}, \penv \vdash {\it string}:{\it string}, \env_{1}
\]

\mylabel{T-IDREAD1}
\[
\dfrac{\env_{1}(id) = F}
      {\env_{1}, \penv \vdash id:close(F), \env_{1}[id \mapsto open(F)]}
\]

\mylabel{T-IDREAD2}
\[
\dfrac{\env_{1}(id) = F}
      {\env_{1}, \penv \vdash id:fix(F), \env_{1}[id \mapsto fix(F)]}
\]

\mylabel{T-IDREAD3}
\[
\dfrac{\env_{1}(id) = \phi(F_{1},F_{2})}
      {\env_{1}, \penv \vdash id:F_{2}, \env_{1}}
\]

\mylabel{T-IDREAD4}
\[
\dfrac{\env_{1}(id) = \pi_{i}^{x}}
      {\env_{1}, \penv \vdash id:proj(\penv(x), i), \env_{1}}
\]

\mylabel{T-INDEXREAD1}
\[
\dfrac{\begin{array}{c}
       \env_{1}(id) = \{\overline{F{:}V}\} \;\;\;
       \env_{1}, \penv \vdash e_{2}:F, \env_{2} \;\;\;
       \exists i \in 1{..}n \; F \lesssim F_{i} \;\;\;
       n = |\overline{F{:}V}|
       \end{array}}
      {\env_{1}, \penv \vdash id[e_{2}]:rconst(V_{i}), \env_{2}}
\]

\mylabel{T-INDEXREAD2}
\[
\dfrac{\begin{array}{c}
       \env_{1}, \penv \vdash e_{1}:\{\overline{F{:}V}\}, \env_{2} \;\;\;
       \env_{2}, \penv \vdash e_{2}:F, \env_{3} \;\;\;
       \exists i \in 1{..}n \; F \lesssim F_{i} \;\;\;
       n = |\overline{F{:}V}|
       \end{array}}
      {\env_{1}, \penv \vdash e_{1}[e_{2}]:rconst(V_{i}), \env_{3}}
\]

\mylabel{T-INDEXREAD3}
\[
\dfrac{\env_{1}, \penv \vdash e_{1}:\Any, \env_{2} \;\;\;
       \env_{2}, \penv \vdash e_{2}:F, \env_{3}}
      {\env_{1}, \penv \vdash e_{1}[e_{2}]:\Any, \env_{3}}
\]

\mylabel{T-COERCE1}
\[
\dfrac{\env_{1}(id) \subtype F \;\;\; tag(F,closed)}
      {\env_{1}, \penv \vdash {<}F{>} \; id:F, \env_{1}[id \mapsto reopen(F)]}
\]

\mylabel{T-COERCE2}
\[
\dfrac{\env_{1}(id) \subtype F \;\;\; tag(F,fixed)}
      {\env_{1}, \penv \vdash {<}F{>} \; id:F, \env_{1}[id \mapsto F]}
\]

\mylabel{T-FUNCTION1}
\[
\dfrac{\begin{array}{c}
       closeall(\env_{1})[\overline{id \mapsto F}], \penv[\ret \mapsto S] \vdash s, \env_{2} \\
       \env_{3} = openset(\env_{1}, frv(\mathbf{fun} \; (\overline{id{:}F}){:}S \; s)) \\
       \env_{4} = closeset(\env_{3}, fav(\mathbf{fun} \; (\overline{id{:}F}){:}S \; s))
       \end{array}}
      {\env_{1}, \penv \vdash \mathbf{fun} \; (\overline{id{:}F}){:}S \; s:F_{1} \times ... \times F_{n} \times \Nil{*} \rightarrow S, \env_{4}}
\]

\mylabel{T-FUNCTION2}
\[
\dfrac{\begin{array}{c}
       closeall(\env_{1})[\overline{id \mapsto F}, {...} \mapsto F], \penv[\ret \mapsto S] \vdash s, \env_{2} \\
       \env_{3} = openset(\env_{1}, frv(\mathbf{fun} \; (\overline{id{:}F}){:}S \; s)) \\
       \env_{4} = closeset(\env_{3}, fav(\mathbf{fun} \; (\overline{id{:}F}){:}S \; s))
       \end{array}}
      {\env_{1}, \penv \vdash \mathbf{fun} \; (\overline{id{:}F},{...}{:}F){:}S \; s:F_{1} \times ... \times F_{n} \times F{*} \rightarrow S, \env_{4}}
\]

\mylabel{T-CONSTRUCTOR1}
\[
\dfrac{\begin{array}{c}
       \env_{1}, \penv \vdash ([e_{1}] = e_{2})_{i}:(F_{i},V_{i}), \env_{i+1} \;\;\;
       T = \{F_{1}{:}V_{1}, ..., F_{n}{:}V_{n}\}_{unique} \\
       wf(T) \;\;\;
       n = |\;\overline{[e_{1}] = e_{2}}\;| \;\;\;
       \env_{f} = merge(\env_{1}, ..., \env_{n+1})
       \end{array}}
      {\env_{1}, \penv \vdash \{\;\overline{[e_{1}] = e_{2}}\;\}:T, \env_{f}}
\]

\mylabel{T-CONSTRUCTOR2}
\[
\dfrac{\begin{array}{c}
       \env_{1}, \penv \vdash ([e_{1}] = e_{2})_{i}:(F_{i},V_{i}), \env_{i+1} \\
       \env_{1}, \penv \vdash me : F_{n+1} \times ... \times F_{n+m} \times F_{n+m+1}{*}, \env_{n+2}\\
       T = \{F_{1}{:}V_{1}, ..., F_{n}{:}V_{n}, 1{:}F_{n+1}, ..., m{:}F_{n+m}, \Integer{:}F_{n+m+1} \cup \Nil\}_{unique}\\
       wf(T) \;\;\;
       n = |\;\overline{[e_{1}] = e_{2}}\;| \;\;\;
       \env_{f} = merge(\env_{1}, ..., \env_{n+2})
       \end{array}}
      {\env_{1}, \penv \vdash \{\;\overline{[e_{1}] = e_{2}}\;\}:T, \env_{f}}
\]

\mylabel{T-FIELD}\\
\[
\dfrac{\env_{1}, \penv \vdash e_{2}:V, \env_{2} \;\;\;
       \env_{2}, \penv \vdash e_{1}:F, \env_{3}}
      {\env_{1}, \penv \vdash [e_{1}] = e_{2}: (F,vt(F,V)), \env_{3}}
\]

\mylabel{T-ARITH1}
\[
\dfrac{\env_{1}, \penv \vdash e_{1}:F_{1}, \env_{2} \;\;\;
       \env_{2}, \penv \vdash e_{2}:F_{2}, \env_{3} \;\;\;
       F_{1} \subtype \Integer \;\;\;
       F_{2} \subtype \Integer}
      {\env_{1}, \penv \vdash e_{1} + e_{2}:\Integer, \env_{3}}
\]

\mylabel{T-ARITH2}
\[
\dfrac{\env_{1}, \penv \vdash e_{1}:F_{1}, \env_{2} \;\;\;
       \env_{2}, \penv \vdash e_{2}:F_{2}, \env_{3} \;\;\;
       F_{1} \subtype \Integer \;\;\;
       F_{2} \subtype \Number}
      {\env_{1}, \penv \vdash e_{1} + e_{2}:\Number, \env_{3}}
\]

\mylabel{T-ARITH3}
\[
\dfrac{\env_{1}, \penv \vdash e_{1}:F_{1}, \env_{2} \;\;\;
       \env_{2}, \penv \vdash e_{2}:F_{2}, \env_{3} \;\;\;
       F_{1} \subtype \Number \;\;\;
       F_{2} \subtype \Integer}
      {\env_{1}, \penv \vdash e_{1} + e_{2}:\Number, \env_{3}}
\]

\mylabel{T-ARITH4}
\[
\dfrac{\env_{1}, \penv \vdash e_{1}:F_{1}, \env_{2} \;\;\;
       \env_{2}, \penv \vdash e_{2}:F_{2}, \env_{3} \;\;\;
       F_{1} \subtype \Number \;\;\;
       F_{2} \subtype \Number}
      {\env_{1}, \penv \vdash e_{1} + e_{2}:\Number, \env_{3}}
\]

\mylabel{T-ARITH5}
\[
\dfrac{\env_{1}, \penv \vdash e_{1}:\Any, \env_{2} \;\;\;
       \env_{2}, \penv \vdash e_{2}:F, \env_{3}}
      {\env_{1}, \penv \vdash e_{1} + e_{2}:\Any, \env_{3}}
\]

\mylabel{T-ARITH6}
\[
\dfrac{\env_{1}, \penv \vdash e_{1}:F, \env_{2} \;\;\;
       \env_{2}, \penv \vdash e_{2}:\Any, \env_{3}}
      {\env_{1}, \penv \vdash e_{1} + e_{2}:\Any, \env_{3}}
\]

\mylabel{T-CONCAT1}
\[
\dfrac{\env_{1}, \penv \vdash e_{1}:F_{1}, \env_{2} \;\;\;
       \env_{2}, \penv \vdash e_{2}:F_{2}, \env_{3} \;\;\;
       F_{1} \subtype \String \;\;\;
       F_{2} \subtype \String}
      {\env_{1}, \penv \vdash e_{1} \; {..} \; e_{2}:\String, \env_{3}}
\]

\mylabel{T-CONCAT2}
\[
\dfrac{\env_{1}, \penv \vdash e_{1}:\Any, \env_{2} \;\;\;
       \env_{2}, \penv \vdash e_{2}:F, \env_{3}}
      {\env_{1}, \penv \vdash e_{1} \; {..} \; e_{2}:\Any, \env_{3}}
\]

\mylabel{T-CONCAT3}
\[
\dfrac{\env_{1}, \penv \vdash e_{1}:F, \env_{2} \;\;\;
       \env_{2}, \penv \vdash e_{2}:\Any, \env_{3}}
      {\env_{1}, \penv \vdash e_{1} \; {..} \; e_{2}:\Any, \env_{3}}
\]

\mylabel{T-EQUAL}
\[
\dfrac{\env_{1}, \penv \vdash e_{1}:F_{1}, \env_{2} \;\;\;
       \env_{2}, \penv \vdash e_{2}:F_{2}, \env_{3}}
      {\env_{1}, \penv \vdash e_{1} == e_{2}:\Boolean, \env_{3}}
\]

\mylabel{T-ORDER1}
\[
\dfrac{\env_{1}, \penv \vdash e_{1}:F_{1}, \env_{2} \;\;\;
       \env_{2}, \penv \vdash e_{2}:F_{2}, \env_{3} \;\;\;
       F_{1} \subtype \Number \;\;\;
       F_{2} \subtype \Number}
      {\env, \penv \vdash e_{1} < e_{2}:\Boolean, \env_{3}}
\]

\mylabel{T-ORDER2}
\[
\dfrac{\env_{1}, \penv \vdash e_{1}:F_{1}, \env_{2} \;\;\;
       \env_{2}, \penv \vdash e_{2}:F_{2}, \env_{3} \;\;\;
       F_{1} \subtype \String \;\;\;
       F_{2} \subtype \String}
      {\env_{1}, \penv \vdash e_{1} < e_{2}:\Boolean}
\]

\mylabel{T-ORDER3}
\[
\dfrac{\env_{1}, \penv \vdash e_{1}:\Any, \env_{2} \;\;\;
       \env_{2}, \penv \vdash e_{2}:F, \env_{3}}
      {\env_{1}, \penv \vdash e_{1} < e_{2}:\Any, \env_{3}}
\]

\mylabel{T-ORDER4}
\[
\dfrac{\env_{1}, \penv \vdash e_{1}:F, \env_{2} \;\;\;
       \env_{2}, \penv \vdash e_{2}:\Any, \env_{3}}
      {\env_{1}, \penv \vdash e_{1} < e_{2}:\Any, \env_{3}}
\]

\mylabel{T-BITWISE1}
\[
\dfrac{\env_{1}, \penv \vdash e_{1}:F_{1}, \env_{2} \;\;\;
       \env_{2}, \penv \vdash e_{2}:F_{2}, \env_{3} \;\;\;
       F_{1} \subtype \Integer \;\;\;
       F_{2} \subtype \Integer}
      {\env_{1}, \penv \vdash e_{1} \;\&\; e_{2}:\Integer, \env_{3}}
\]

\mylabel{T-BITWISE2}
\[
\dfrac{\env_{1}, \penv \vdash e_{1}:\Any, \env_{2} \;\;\;
       \env_{2}, \penv \vdash e_{2}:F, \env_{3}}
      {\env_{1}, \penv \vdash e_{1} \;\&\; e_{2}:\Any, \env_{3}}
\]

\mylabel{T-BITWISE3}
\[
\dfrac{\env_{1}, \penv \vdash e_{1}:F, \env_{2} \;\;\;
       \env_{2}, \penv \vdash e_{2}:\Any, \env_{3}}
      {\env_{1}, \penv \vdash e_{1} \;\&\; e_{2}:\Any, \env_{3}}
\]

\mylabel{T-AND1}
\[
\dfrac{\env_{1}, \penv \vdash e_{1}:\Nil, \env_{2}}
      {\env_{1}, \penv \vdash e_{1} \; \mathbf{and} \; e_{2}:\Nil, \env_{2}}
\]

\mylabel{T-AND2}
\[
\dfrac{\env_{1}, \penv \vdash e_{1}:\False, \env_{2}}
      {\env_{1}, \penv \vdash e_{1} \; \mathbf{and} \; e_{2}:\False, \env_{2}}
\]

\mylabel{T-AND3}
\[
\dfrac{\env_{1}, \penv \vdash e_{1}:\Nil \cup \False, \env_{2}}
      {\env_{1}, \penv \vdash e_{1} \; \mathbf{and} \; e_{2}:\Nil \cup \False, \env_{2}}
\]

\mylabel{T-AND4}
\[
\dfrac{\env_{1}, \penv \vdash e_{1}:F_{1}, \env_{2} \;\;\;
       \env_{2}, \penv \vdash e_{2}:F_{2}, \env_{3} \;\;\;
       \Nil \not\lesssim F_{1} \;\;\;
       \False \not\lesssim F_{1}}
      {\env_{1}, \penv \vdash e_{1} \; \mathbf{and} \; e_{2}:F_{2}, \env_{3}}
\]

\mylabel{T-AND5}
\[
\dfrac{\env_{1}, \penv \vdash e_{1}:F_{1}, \env_{2} \;\;\;
       \env_{2}, \penv \vdash e_{2}:F_{2}, \env_{3}}
      {\env_{1}, \penv \vdash e_{1} \; \mathbf{and} \; e_{2}:F_{1} \cup F_{2}, \env_{3}}
\]

\mylabel{T-OR1}
\[
\dfrac{\env_{1}, \penv \vdash e_{1}:F, \env_{2} \;\;\;
       \Nil \not\lesssim F \;\;\;
       \False \not\lesssim F}
      {\env_{1}, \penv \vdash e_{1} \; \mathbf{or} \; e_{2}:F, \env_{2}}
\]

\mylabel{T-OR2}
\[
\dfrac{\env_{1}, \penv \vdash e_{1}:\Nil, \env_{2} \;\;\;
       \env_{2}, \penv \vdash e_{2}:F, \env_{3}}
      {\env_{1}, \penv \vdash e_{1} \; \mathbf{or} \; e_{2}:F, \env_{3}}
\]

\mylabel{T-OR3}
\[
\dfrac{\env_{1}, \penv \vdash e_{1}:\False, \env_{2} \;\;\;
       \env_{2}, \penv \vdash e_{2}:F, \env_{3}}
      {\env_{1}, \penv \vdash e_{1} \; \mathbf{or} \; e_{2}:F, \env_{3}}
\]

\mylabel{T-OR4}
\[
\dfrac{\env_{1}, \penv \vdash e_{1}:\Nil \cup \False, \env_{2} \;\;\;
       \env_{2}, \penv \vdash e_{2}:F, \env_{3}}
      {\env_{1}, \penv \vdash e_{1} \; \mathbf{or} \; e_{2}:F, \env_{3}}
\]

\mylabel{T-OR5}
\[
\dfrac{\env_{1}, \penv \vdash e_{1}:F_{1}, \env_{2} \;\;\;
       \env_{2}, \penv \vdash e_{2}:F_{2}, \env_{3}}
      {\env_{1}, \penv \vdash e_{1} \; \mathbf{or} \; e_{2}:filter(filter(F_{1}, \Nil), \False) \cup F_{2}, \env_{3}}
\]

\mylabel{T-NOT1}
\[
\dfrac{\env_{1}, \penv \vdash e:\Nil, \env_{2}}
      {\env_{1}, \penv \vdash \mathbf{not} \; e:\True, \env_{2}}
\]

\mylabel{T-NOT2}
\[
\dfrac{\env_{1}, \penv \vdash e:\False, \env_{2}}
      {\env_{1}, \penv \vdash \mathbf{not} \; e:\True, \env_{2}}
\]

\mylabel{T-NOT3}
\[
\dfrac{\env_{1}, \penv \vdash e:\Nil \cup \False, \env_{2}}
      {\env_{1}, \penv \vdash \mathbf{not} \; e:\True, \env_{2}}
\]

\mylabel{T-NOT4}
\[
\dfrac{\env_{1}, \penv \vdash e:F \;\;\;
       \Nil \not\lesssim F \;\;\;
       \False \not\lesssim F}
      {\env_{1}, \penv \vdash \mathbf{not} \; e:\False, \env_{2}}
\]

\mylabel{T-NOT5}
\[
\dfrac{\env_{1}, \penv \vdash e:F, \env_{2}}
      {\env_{1}, \penv \vdash \mathbf{not} \; e:\Boolean, \env_{2}}
\]

\mylabel{T-LEN1}
\[
\dfrac{\env_{1}, \penv \vdash e:F, \env_{2} \;\;\;
       F \subtype \String}
      {\env_{1}, \penv \vdash \# \; e:\Integer, \env_{2}}
\]

\mylabel{T-LEN2}
\[
\dfrac{\env_{1}, \penv \vdash e:F, \env_{2} \;\;\;
       F \subtype \{\}_{closed}}
      {\env_{1}, \penv \vdash \# \; e:\Integer, \env_{2}}
\]

\mylabel{T-LEN3}
\[
\dfrac{\env_{1}, \penv \vdash e:\Any, \env_{2}}
      {\env_{1}, \penv \vdash \# \; e:\Any, \env_{2}}
\]

\mylabel{T-EXPAPPLY1}
\[
\dfrac{\env_{1}, \penv \vdash e(el):S, \env_{2}}
      {\env_{1}, \penv \vdash \lfloor e(el) \rfloor_{1}:proj(S,1), \env_{2}}
\]

\mylabel{T-EXPINVOKE1}
\[
\dfrac{\env_{1}, \penv \vdash e{:}n(el):S, \env_{2}}
      {\env_{1}, \penv \vdash \lfloor e{:}n(el) \rfloor_{1}:proj(S,1), \env_{2}}
\]

\mylabel{T-EXPDOTS}
\[
\dfrac{\env_{1}, \penv \vdash {...}:F{*}, \env_{2}}
      {\env_{1}, \penv \vdash \lfloor {...} \rfloor_{1}:F \cup \Nil, \env_{2}}
\]

\mylabel{T-IDWRITE1}
\[
\dfrac{\env_{1}(id) = F}
      {\env_{1}, \penv \vdash id_{l}:F, \env_{1}}
\]

\mylabel{T-IDWRITE2}
\[
\dfrac{\env_{1}(id) = \phi(F_{1},F_{2})}
      {\env_{1}, \penv \vdash id_{l}:F_{1}, \env_{1}[id \mapsto F_{1}]}
\]

\mylabel{T-INDEXWRITE1}
\[
\dfrac{\begin{array}{c}
       \env_{1}, \penv \vdash e_{1}:\{\overline{F{:}V}\}, \env_{2} \\
       \env_{2}, \penv \vdash e_{2}:F, \env_{3} \;\;\;
       \exists i \in 1{..}n \; F \lesssim F_{i} \wedge \neg const(V_{i}) \;\;\;
       n = |\overline{F{:}V}|
       \end{array}}
      {\env_{1}, \penv \vdash e_{1}[e_{2}]_{l}:V_{i}, \env_{3}}
\]

\mylabel{T-INDEXWRITE2}
\[
\dfrac{\env_{1}, \penv \vdash e_{1}:\Any, \env_{2} \;\;\;
       \env_{2}, \penv \vdash e_{2}:F, \env_{3}}
      {\env_{1}, \penv \vdash e_{1}[e_{2}]_{l}:\Any, \env_{3}}
\]

\mylabel{T-REFINE1}
\[
\dfrac{\begin{array}{c}
       \env_{1}(id) = \{\overline{F{:}V}\}_{unique}\\
       \env_{1}, \penv \vdash e:F_{new}, \env_{2} \;\;\;
       \nexists i \in 1..n \; F_{new} \lesssim F_{i} \;\;\;
       V_{new} = vt(F_{new},V) \;\;\; n = |\overline{F{:}V}|
       \end{array}}
      {\env_{1}, \penv \vdash id[e] {<}V{>}:V_{new}, \env_{2}[id \mapsto \{\overline{F{:}V}, F_{new}{:}V_{new}\}_{unique}]}
\]

\mylabel{T-REFINE2}
\[
\dfrac{\begin{array}{c}
       \env_{1}(id) = \{\overline{F{:}V}\}_{open}\\
       \env_{1}, \penv \vdash e:F_{new}, \env_{2} \;\;\;
       \nexists i \in 1..n \; F_{new} \lesssim F_{i} \;\;\;
       V_{new} = vt(F_{new},V) \;\;\; n = |\overline{F{:}V}|
       \end{array}}
      {\env_{1}, \penv \vdash id[e] {<}V{>}:V_{new}, \env_{2}[id \mapsto \{\overline{F{:}V}, F_{new}{:}V_{new}\}_{open}]}
\]

\mylabel{T-LHSLIST}
\[
\dfrac{\env_{1}, \penv \vdash l_{i}:F_{i}, \env_{i+1} \;\;\;
       \env_{f} = merge(\env_{1}, ..., \env_{n+1}) \;\;\;
       n = |\;\overline{l}\;|}
      {\env_{1}, \penv \vdash \overline{l}:F_{1} \times ... \times F_{n} \times \Value{*}, \env_{f}}
\]

\mylabel{T-EXPLIST1}
\[
\dfrac{\env_{1}, \penv \vdash e_{i}:F_{i}, \env_{i+1} \;\;\;
       \env_{f} = merge(\env_{1}, ..., \env_{n+1}) \;\;\;
       n = |\;\overline{e}\;|}
      {\env_{1}, \penv \vdash \overline{e}:F_{1} \times ... \times F_{n} \times \Nil{*}, \env_{f}}
\]

\mylabel{T-EXPLIST2}
\[
\dfrac{\begin{array}{c}
       \env_{1}, \penv \vdash e_{i}:F_{i}, \env_{i+1} \;\;\;
       \env_{1}, \penv \vdash me:F_{n+1} \times ... \times F_{n+m} \times F_{n+m+1}{*}, \env_{n+2}\\
       \env_{f} = merge(\env_{1}, ..., \env_{n+2}) \;\;\;
       n = |\;\overline{e}\;|
       \end{array}}
      {\env_{1}, \penv \vdash \overline{e},me:F_{1} \times ... \times F_{n+m} \times F_{n+m+1}{*}, \env_{f}}
\]

\mylabel{T-EXPLIST3}
\[
\dfrac{\begin{array}{c}
       \env_{1}, \penv \vdash e_{i}:F_{i}, \env_{i+1} \;\;\;
       \env_{1}, \penv \vdash me:S, \env_{n+2}\\
       S = F_{n+1} \times ... \times F_{n+m} \times \Nil{*} \sqcup F_{n+1}' \times ... \times F_{n+m}' \times \Nil{*} \\
       \env_{f} = merge(\env_{1}, ..., \env_{n+2}) \;\;\;
       n = |\;\overline{e}\;|
       \end{array}}
      {\env_{1}, \penv \vdash \overline{e},me:F_{1} \times ... \times F_{n} \times \pi_{1}^{x} \times ... \times \pi_{m}^{x} \times \Nil{*}, \env_{f}, (x,S)}
\]

\mylabel{T-APPLY1}
\[
\dfrac{\env_{1}, \penv \vdash e:S_{1} \rightarrow S_{2}, \env_{2} \;\;\;
       \env_{2}, \penv \vdash el:S_{3}, \env_{3} \;\;\;
       S_{3} \lesssim S_{1}}
      {\env_{1}, \penv \vdash e(el):S_{2}, \env_{3}}
\]

\mylabel{T-APPLY2}
\[
\dfrac{\env_{1}, \penv \vdash e:\Any, \env_{2} \;\;\;
       \env_{2}, \penv \vdash el:S, \env_{3}}
      {\env_{1}, \penv \vdash e_{1}(el):\Any{*}, \env_{3}}
\]

\mylabel{T-INVOKE1}
\[
\dfrac{\begin{array}{c}
       \env_{1}, \penv \vdash e:F, \env_{2}\\
       \env_{2}[\sigma \mapsto F], \penv \vdash e[id]:\Const \; S_{1} \rightarrow S_{2}, \env_{3}\\
       \env_{3}[\sigma \mapsto F], \penv \vdash el:S_{3}, \env_{4} \;\;\;
       F \times S_{3} \lesssim [\Self \mapsto F]S_{1}
       \end{array}}
      {\env_{1}, \penv \vdash e{:}id(el):[\Self \mapsto F]S_{2}, \env_{4}}
\]

\mylabel{T-INVOKE2}
\[
\dfrac{\env_{1}, \penv \vdash e:\Any, \env_{2} \;\;\;
       \env_{2}, \penv \vdash el:S, \env_{3}}
      {\env_{1}, \penv \vdash e{:}id(el):\Any{*}, \env_{3}}
\]

\mylabel{T-DOTS}
\[
\dfrac{\env_{1}({...}) = F}
      {\env_{1}, \penv \vdash {...}:F{*}, \env_{1}}
\]

\mylabel{T-SELF}
\[
\dfrac{\env_{1}, \penv \vdash e:\Self, \env_{2} \;\;\;
       \env_{2}(\self) = F}
      {\env_{1}, \penv \vdash e:F, \env_{2}}
\]

\mylabel{T-SETMETATABLE1}
\[
\dfrac{\env_{1}(id) = \Self}
      {\env_{1}, \penv \vdash setmetatable(\{\}, \{[``\string_\string_index"] = id\}):\Self, \env_{1}}
\]

\mylabel{T-SETMETATABLE2}
\[
\dfrac{\env_{1}(id) = \{F_{1}{:}V_{1}, ..., F_{n}{:}V_{n}\}_{fixed}}
      {\env_{1}, \penv \vdash setmetatable(\{\}, \{[``\string_\string_index"] = id\}):\{F_{1}{:}V_{1}, ..., F_{n}{:}V_{n}\}_{open}, \env_{1}}
\]

\mylabel{T-SETMETATABLE3}
\[
\dfrac{\env_{1}, \penv \vdash e : T, \env_{2} \;\;\;
       T = \{F_{1}{:}V_{1}, ..., F_{n}{:}V_{n}\}_{closed} \;\;\;
       \env_{1}(id) = \Self \;\;\; \env_{1}(\sigma) \subtype T}
      {\env_{1}, \penv \vdash setmetatable(e, \{[``\string_\string_index"] = id\}):\Self, \env_{2}[\sigma \mapsto T]}
\]

\mylabel{T-UNFOLD}
\[
\dfrac{\env_{1}, \penv \vdash e:\mu x.F, \env_{2}}
      {\env_{1}, \penv \vdash e:[x \mapsto \mu x.F]F, \env_{2}}
\]

\mylabel{T-FOLD}
\[
\dfrac{\env_{1}, \penv \vdash e:[x \mapsto \mu x.F]F, \env_{2}}
      {\env_{1}, \penv \vdash e:\mu x.F, \env_{2}}
\]

\mylabel{T-TERNARY}
\[
\dfrac{\env_{1}, \penv \vdash e_{1}:F_{1}, \env_{2} \;\;\;
       \env_{2}, \penv \vdash e_{2}:F_{2}, \env_{3} \;\;\;
       \env_{3}, \penv \vdash e_{3}:F_{2}, \env_{4}}
      {\env_{1}, \penv \vdash e_{1} \; \mathbf{and} \; e_{2} \; \mathbf{or} \; e_{3}:F_{2}, \env_{4}}
\]

\section{Auxiliary functions}

\noindent

\begin{align*}
wf(\{\overline{F:V}\}_{unique|open|fixed|closed}) & = \forall i \; ((\nexists j \; i \not= j \,\wedge\, F_{i} \lesssim F_{j}) \,\wedge\, wf(V_{i}) \,\wedge\\
& \;\;\;\; \lnot tag(V_{i},unique) \,\wedge\, \lnot tag(V_{i},open))\\
wf({\bf const}\; F) & = wf(F) \\
wf(F_1 \cup F_2) & = wf(F_1) \,\wedge\, wf(F_2) \\
wf(\mu x.F) & = wf(F) \\
wf(S_1 \rightarrow S_2) & = wf(S_1) \,\wedge\, wf(S_2) \\
wf(S_1 \sqcup S_2) & = wf(S_1) \,\wedge\, wf(S_2)\\
wf(F{*}) & = wf(F) \\
wf(F \times P) & = wf(F) \,\wedge\,wf(P)\\
wf(F) & = \top \;\;\;\mathrm{for\; all\; other\; cases}
\end{align*}

\begin{align*}
tag(F_1 \cup F_2, t) & = tag(F_1, t) \,\vee\, tag(F_2,t) \\
tag(\{\overline{F{:}V}\}_{t}, t) & = \top\\
tag(\{\overline{F{:}V}\}_{t_{1}}, t_{2}) & = \bot\\
tag(F, t) & = \bot
\end{align*}

\begin{align*}
vt(L, V) & = fix(V) \\
vt(F_1, F_2) & = nil(fix(F_2))\\
vt(F_1, {\bf const}\;F_2) & = {\bf const}\;nil(fix(F_2))
\end{align*}

\begin{align*}
nil(T) & = \left\{
\begin{array}{ll}
T & \text{if $\Nil \lesssim T$} \\
T \cup \Nil & \text{otherwise}
\end{array} \right.
\end{align*}

\begin{align*}
fix(F_{1} \cup F_{2}) & = fix(F_{1}) \cup fix(F_{2})\\
fix(\{\overline{F{:}V}\}_{unique|open}) & = \{\overline{F{:}V}\}_{fixed} \\
fix(F) & = F
\end{align*}

\begin{align*}
close(F_{1} \cup F_{2}) & = close(F_{1}) \cup close(F_{2})\\
close(\{\overline{F{:}V}\}_{unique|open}) & = \{\overline{F{:}V}\}_{closed} \\
close(F) & = F
\end{align*}

\begin{align*}
open(F_{1} \cup F_{2}) & = open(F_{1}) \cup open(F_{2})\\
open(\{\overline{F{:}V}\}_{unique}) & = \{\overline{F{:}V}\}_{open} \\
open(F) & = F
\end{align*}

\begin{align*}
reopen(\{\overline{F:V}\}_{closed}) & = \{\overline{F:V}\}_{open}\\
reopen(F) & = F
\end{align*}

\begin{align*}
rconst({\bf const}\;F) & = F\\
rconst(F) & = F
\end{align*}

\begin{align*}
const({\bf const}\;F) & = \top\\
const(F) & = \bot
\end{align*}

\begin{align*}
proj(S_1 \sqcup S_2, i) & = proj(S_1, i) \cup proj(S_2, i) \\
proj(F{*}, i) & = nil(F) \\
proj(F \times P, 1) & = F \\
proj(F \times P, i) & = proj(P, i-1)\\
proj(E{*}, i) & = nil(E) \\
proj(T \times E, 1) & = T \\
proj(T \times E, i) & = proj(E, i-1)
\end{align*}

\begin{align*}
infer(T_{1} \times ... \times T_{n}{*}, i) & = \left\{
\begin{array}{ll}
general(T_{i}) & \text{if $i < n$}\\
general(nil(T_{n})) & \text{if $i >= n$}
\end{array} \right.
\end{align*}

\begin{align*}
general(\False) & = \Boolean\\
general(\True) & = \Boolean\\
general({\it int}) & = \Integer\\
general({\it float}) & = \Number\\
general({\it string}) & = \String\\
general(F_{1} \cup F_{2}) & = general(F_{1}) \cup general(F_{2})\\
general(S_{1} \rightarrow S_{2}) & = general2(S_{1}) \rightarrow general2(S_{2})\\
general(\{F_{1}{:}V_{1}, ..., F_{n}{:}V_{n}\}_{tag}) & = \{F_{1}{:}general(V_{1}), ..., F_{n}{:}general(V_{n})\}_{tag}\\
general(\mu x.F) & = \mu x.general(F)\\
general(T) & = T
\end{align*}

\begin{align*}
general2(F{*}) & = general(F){*}\\
general2(F \times P) & = general(F) \times general2(P)\\
general2(S_{1} \sqcup S_{2}) & = general2(S_{1}) \sqcup general2(S_{2})
\end{align*}

\begin{align*}
closeall(\env[id_{1} \mapsto T_{1}, ..., id_{n} \mapsto T_{n}]) & = \env[id_{1} \mapsto close(T_{1}), ..., id_{n} \mapsto close(T_{n})]
\end{align*}

\begin{align*}
closeset(\env, \{id_{1}, ..., id_{n}\}) & = \env[id_{1} \mapsto close(\env(id_{1})), ..., id_{n} \mapsto close(\env(id_{n}))]
\end{align*}

\begin{align*}
openset(\env, \{id_{1}, ..., id_{n}\}) & = \env[id_{1} \mapsto open(\env(id_{1})), ..., id_{n} \mapsto open(\env(id_{n}))]
\end{align*}

\begin{align*}
merge(\overline{\env}) & = reduce(\overline{\env}, merge2)\\
merge2(\env_1,\env_2) & = \{\overline{(id,merget(\env_1(id),\env_2(id))}\}\\
merget(T_1, T_2) & = T_1 \;\;\; \mathrm{if\;} T_2 \lesssim T_1\\
merget(T_1, T_2) & = T_2 \;\;\; \mathrm{if\;} T_1 \lesssim T_2\\
& \;\;\;\;\; \mathrm{the\;next\;case\;applies\;if} \\
& \;\;\;\;\; \overline{V^l \lesssim_u V_r \,\vee\, V^r \lesssim_u V_l}\\
& \;\;\;\;\; \mathrm{and\;the\;right\; side\; is\;}wf\\
merget(\{\overline{F:V^l},\overline{F^{\prime}:V^\prime}\}_{unique},\\
\{\overline{F:V^r},\overline{F^{\prime\prime}:V^{\prime\prime}}\}_{unique}) & =
\{\overline{F:sup_u(V^l,V^r)},\\
& \;\;\;\;\;\; \overline{F^\prime:V^\prime},\\
& \;\;\;\;\;\; \overline{F^{\prime\prime}:V^{\prime\prime}}\}_{unique}\\
& \;\;\;\;\; \mathrm{the\;next\;case\;applies\;if} \\
& \;\;\;\;\; \overline{V^l \lesssim_c V_r \,\vee\, V^r \lesssim_c V_l}\\
& \;\;\;\;\; \mathrm{and\;the\;right\; side\; is\;}wf\\
merget(\{\overline{F:V^l},\overline{F^{\prime}:V^{\prime}}\}_{unique|open},\\
\{\overline{F:V^r},\overline{F^{\prime\prime}:V^{\prime\prime}}\}_{unique|open}) & =
\{\overline{F:sup_c(V^l,V^r)},\\
& \;\;\;\;\;\; \overline{F^\prime:V^\prime},\\
& \;\;\;\;\;\; \overline{F^{\prime\prime}:V^{\prime\prime}}\}_{open}\\
merget(T_1, T_2) & = \bot \;\;\; \mathrm{otherwise}
\end{align*}

\begin{align*}
sup_u(V_1, V_2) & = V_2 \;\;\; \mathrm{if}\; V_1 \lesssim_u V_2\\
sup_u(V_1, V_2) & = V_1 \;\;\; \mathrm{if}\; V_2 \lesssim_u V_1
\end{align*}

\begin{align*}
sup_c(V_1, V_2) & = V_2 \;\;\; \mathrm{if}\; V_1 \lesssim_c V_2\\
sup_c(V_1, V_2) & = V_1 \;\;\; \mathrm{if}\; V_2 \lesssim_c V_1
\end{align*}

\begin{align*}
join(\env_1,\env_2) & = \{\overline{(id,joint(\env_1(id),\env_2(id))}\}\\
joint(T_1, T_2) & = T_1 \;\;\; \mathrm{if\;} T_2 \lesssim T_1\\
joint(T_1, T_2) & = T_2 \;\;\; \mathrm{if\;} T_1 \lesssim T_2\\
& \;\;\;\;\; \mathrm{the\;next\;case\;applies\;if}\; \\
& \;\;\;\;\; \overline{V^l \lesssim_u V_r \,\vee\, V^r \lesssim_u V_l}\\
& \;\;\;\;\; \mathrm{and\;the\;right\; side\; is\;}wf\\
joint(\{\overline{F:V^l},\overline{F^{\prime}:V^{\prime}}\}_{unique},
\{\overline{F:V^r},\overline{F^{\prime\prime}:V^{\prime\prime}}\}_{unique}) & =
\{\overline{F:sup_u(V^l,V^r)},\\
& \;\;\;\;\;\; \overline{F^\prime:nil(V^\prime)},\\
& \;\;\;\;\;\; \overline{F^{\prime\prime}:nil(V^{\prime\prime})}\}_{unique}\\
joint(T_1, T_2) & = \bot \;\;\; \mathrm{otherwise}
\end{align*}

\begin{align*}
filter(F_{1} \cup F_{2}, F_{1}) & = filter(F_{2}, F_{1})\\
filter(F_{1} \cup F_{2}, F_{2}) & = filter(F_{1}, F_{2})\\
filter(F_{1} \cup F_{2}, F_{3}) & = filter(F_{1}, F_{3}) \cup filter(F_{2}, F_{3})\\
filter(F_{1}, F_{2}) & = F_{1}
\end{align*}

\begin{align*}
fopt(P_1 \sqcup P_2, F, i) & = P_2 & \mathrm{if} \; fot(proj(P_1, i),F) = {\bf void} \\
fopt(P_1 \sqcup P_2, F, i) & = P_1 & \mathrm{if} \; fot(proj(P_2, i),F) = {\bf void} \\
fopt(P_1 \sqcup P_2, F, i) & = P_1 \sqcup P_2 & \mathrm{otherwise}\\
fopt(P \sqcup S, F, i) & = fopt(S,F,i) & \mathrm{if} \; fot(proj(P, i),F) = {\bf void} \\
fopt(P \sqcup S, F, i) & = P \sqcup fopt(S,F,i) & \mathrm{otherwise}\\
fopt(S \sqcup P_2, F, i) & = fopt(S,F,i) & \mathrm{if} \; fot(proj(P, i),F) = {\bf void} \\
fopt(S \sqcup P, F, i) & = fopt(S,F,i) \sqcup P & \mathrm{otherwise}\\
fopt(S_1 \sqcup S_2, F, i) & = fopt(S_1,F,i) \sqcup fopt(S_2,F,i)
\end{align*}

\begin{align*}
fot(F_1 \cup F_2,F_3) & = fot(F_1,F_3) & \mathrm{if}\;fot(F_2,F_3) = {\bf void}\\
fot(F_1 \cup F_2,F_3) & = fot(F_2,F_3) & \mathrm{if}\;fot(F_1,F_3) = {\bf void}\\
fot(F_1 \cup F_2,F_3) & = fot(F_1,F_3) \cup fot(F_2,F_3) & \mathrm{otherwise}\\
fot(F_1,F_2) & = {\bf void} & \mathrm{if} \; F_1 \subtype F_2 \; \mathrm{and} \; F_2 \subtype F_1\\
fot(F_1,F_2) & = F_1 & \mathrm{otherwise}
\end{align*}

\begin{align*}
fipt(P_1 \sqcup P_2, F, i) & = P_2 & \mathrm{if} \; fit(proj(P_1, i),F) = {\bf void} \\
fipt(P_1 \sqcup P_2, F, i) & = P_1 & \mathrm{if} \; fit(proj(P_2, i),F) = {\bf void} \\
fipt(P_1 \sqcup P_2, F, i) & = P_1 \sqcup P_2 & \mathrm{otherwise}\\
fipt(P \sqcup S, F, i) & = fipt(S,F,i) & \mathrm{if} \; fit(proj(P, i),F) = {\bf void} \\
fipt(P \sqcup S, F, i) & = P \sqcup fipt(S,F,i) & \mathrm{otherwise}\\
fipt(S \sqcup P_2, F, i) & = fipt(S,F,i) & \mathrm{if} \; fit(proj(P, i),F) = {\bf void} \\
fipt(S \sqcup P, F, i) & = fipt(S,F,i) \sqcup P & \mathrm{otherwise}\\
fipt(S_1 \sqcup S_2, F, i) & = fipt(S_1,F,i) \sqcup fipt(S_2,F,i)
\end{align*}

\begin{align*}
fit(F_1 \cup F_2,F_3) & = fit(F_1,F_3) & \mathrm{if}\;fit(F_2,F_3) = {\bf void}\\
fit(F_1 \cup F_2,F_3) & = fit(F_2,F_3) & \mathrm{if}\;fit(F_1,F_3) = {\bf void}\\
fit(F_1 \cup F_2,F_3) & = fit(F_1,F_3) \cup fit(F_2,F_3) & \mathrm{otherwise}\\
fit(F_1,F_2) & = F_1 & \mathrm{if} \; F_1 \subtype F_2 \; \mathrm{and} \; F_2 \subtype F_1\\
fit(F_1,F_2) & = {\bf void} & \mathrm{otherwise}
\end{align*}