\section{Classification System}\seclabel{class} \index{classification} A \dfn{classification} is a user-defined abstraction that describes (``classifies'') arbitrary data. Classifications can be used as predicates, generating functions, and can be composed into more complex classifications. Nearly all conditions in \tame{} are specified using classifications. \index{first-order logic!sentence} \index{classification!coupling} All classifications represent \dfn{first-order sentences}---% that is, they contain no \dfn{free variables}. Intuitively, this means that all variables within a~classification are \dfn{tightly coupled} to the classification itself. This limitation is mitigated through use of the template system. \begin{axiom}[Classification Introduction]\axmlabel{class-intro} \todo{Symbol in place of $=$ here ($\equiv$ not appropriate).} \begin{alignat}{3} &\xml{}\label{eq:xml-classify} \\ &\quad \MFam{M^0}jJkK &&\VFam{v^0}jJ &&\quad s^0 \nonumber\\[-4mm] &\quad \quad\vdots &&\quad\vdots &&\quad \vdots \nonumber\\ &\quad \MFam{M^l}jJkK &&\VFam{v^m}jJ &&\quad s^n \nonumber\\[-3mm] &\xml{} % NB: This -50mu needs adjustment if you change the alignment above! &&\mspace{-50mu}= \Classify^c_\gamma\left(\odot,M,v,s\right), \nonumber \end{alignat} \noindent where \begin{align} J &\subset\Int \neq\emptyset, \\ \forall{j\in J}\Big(K_j &\subset\Int \neq\emptyset\Big), \\ \forall{k}\Big(M^k &: J \rightarrow K_{j\in J} \rightarrow \Bool\Big), \label{eq:class-matrix} \\ \forall{k}\Big(v^k &: J \rightarrow \Bool\Big), \\ \forall{k}\Big(s^k &\in\Bool\Big), \\ \alpha &\in\Set{\epsilon,\, \texttt{any="true"}}, \label{eq:xml-any-domain} \end{align} \noindent and the monoid~$\odot$ is defined as \begin{equation}\label{eq:classify-rel} \odot = \begin{cases} \Monoid\Bool\land\true &\alpha = \epsilon,\\ \Monoid\Bool\lor\false &\alpha = \texttt{any="true"}. \end{cases} \end{equation} \end{axiom} % This TODO was the initial motivation for this paper! \todo{Emphasize index sets, both relationships and nonempty.} We use a $4$-tuple $\Classify\left(\odot,M,v,s\right)$ to represent a $\odot_1$-classification (a classification with the binary operation $\land$ or~$\lor$) consisting of a combination of matrix~($M$), vector~($v$), and scalar~($s$) matches, rendered above in columns.\footnote{% The symbol~$\odot$ was chosen since the binary operation for a monoid is~$\bullet$ (see \secref{monoids}) and~$\odot$ looks vaguely like~$(\bullet)$, representing a portion of the monoid triple.} A $\land$-classification is pronounced ``conjunctive classification'', and $\lor$ ``disjunctive''.\footnote{% Conjunctive and disjunctive classifications used to be referred to, respectively, as \dfn{universal} and \dfn{existential}, referring to fact that $\forall\Set{a_0,\ldots,a_n}(a) \equiv a_0\land\ldots\land a_n$, and similarly for $\exists$. This terminology has changed since all classifications are in fact existential over their matches' index sets, and so the terminology would otherwise lead to confusion.} The variables~$c$ and~$\gamma$ are required in~\tame{} but are both optional in our notation~$\Classify^c_\gamma$, and can be used to identify the two different data representations of the classification.\footnote{% \xpath{classify/@yields} is optional in the grammar of \tame{}, but the compiler will generate one for us if one is not provided. As such, we will for simplicity consider it to be required here.} $\alpha$~serves as a placeholder for an optional \xml{any="true"}, with $\emptystr$~representing the empty string in~\eqref{eq:xml-any-domain}. Note the wildcard variable matching \xmlattr{desc}---% its purpose is only to provide documentation. \begin{corollary}[$\odot$ Commutative Monoid]\corlabel{odot-monoid} $\odot$ is a commutative monoid in \axmref{class-intro}. \end{corollary} \begin{proof} By \axmref{class-intro}, $\odot$ must be a monoid. Assume $\alpha=\epsilon$. Then, $\odot = \Monoid\Bool\land\true$, which is proved by \lemref{monoid-land}. Next, assume $\alpha=\texttt{any="true"}$. Then, $\odot = \Monoid\Bool\lor\false$, which is proved by \lemref{monoid-land}. \end{proof} \index{classification!commutativity} \index{compiler!classification commutativity} While \axmref{class-intro} seems to imply an ordering to matches, users of the language are free to specify matches in any order and the compiler will rearrange matches as it sees fit. This is due to the commutativity of~$\odot$ as proved by \corref{odot-monoid}, and not only affords great ease of use to users of~\tame{}, but also great flexibility to compiler writers. For notational convenience, we will let \begin{align} \odot^\land &= \Monoid\Bool\land\true, \\ \odot^\lor &= \Monoid\Bool\lor\false. \end{align} \def\cpredmatseq{{M^0_j}_k \bullet\cdots\bullet {M^l_j}_k} \def\cpredvecseq{v^0_j\bullet\cdots\bullet v^m_j} \def\cpredscalarseq{s^0\bullet\cdots\bullet s^n} \begin{axiom}[Classification-Predicate Equivalence]\axmlabel{class-pred} Let $\Classify^c_\gamma\left(\Monoid\Bool\bullet e,M,v,s\right)$ be a classification by~\axmref{class-intro}. We then have the first-order sentence \begin{equation*} c \equiv {} \Exists{j\in J}{\Exists{k\in K_j}\cpredmatseq\bullet\cpredvecseq} \bullet\cpredscalarseq. \end{equation*} \end{axiom} \begin{axiom}[Classification Yield]\axmlabel{class-yield} Let $\Classify^c_\gamma\left(\Monoid\Bool\bullet e,M,v,s\right)$ be a classification by~\axmref{class-intro}. Then, \begin{align} r &= \begin{cases} 2 &M\neq\emptyset, \\ 1 &M=\emptyset \land v\neq\emptyset, \\ 0 &M\union v = \emptyset, \end{cases} \\ \exists{j\in J}\Big(\exists{k\in K_j}\Big( \Gamma^2_{j_k} &= \cpredmatseq\bullet\cpredvecseq\bullet\cpredscalarseq \Big)\Big), \\ % \exists{j\in J}\Big( \Gamma^1_j &= \cpredvecseq\bullet\cpredscalarseq \Big), \\ % \Gamma^0 &= \cpredscalarseq. \\ % \gamma &= \Gamma^r. \end{align} \end{axiom} \begin{theorem}[Classification Composition]\thmlabel{class-compose} Classifications may be composed to create more complex classifications using the classification yield~$\gamma$ as in~\axmref{class-yield}. This interpretation is equivalent to \axmref{class-pred} by \begin{equation} c \equiv \Exists{j\in J}{ \Exists{k\in K_j}{\Gamma^2_{j_k}} \bullet \Gamma^1_j } \bullet \Gamma^0. \end{equation} \end{theorem} \def\eejJ{\equiv \exists{j\in J}\Big(} \begin{proof} Expanding each~$\Gamma$ in \axmref{class-yield}, we have \begin{alignat*}{3} c &\eejJ\Exists{k\in K_j}{\Gamma^2_{j_k}} \bullet \Gamma^1_j \Big) \bullet \Gamma^0 &&\text{by \axmref{class-yield}} \\ % &\eejJ\exists{k\in K_j}\Big( \cpredmatseq \bullet \cpredvecseq \bullet \cpredscalarseq \Big) \\ &\hphantom{\eejJ}\;\cpredvecseq \bullet \cpredscalarseq \Big) \bullet \cpredscalarseq, \\ % &\eejJ\exists{k\in K_j}\Big(\cpredmatseq\Big) \bullet \cpredvecseq \bullet \cpredscalarseq \\ &\hphantom{\eejJ}\;\cpredvecseq \bullet \cpredscalarseq \Big) \bullet \cpredscalarseq, &&\text{by \dfnref{quant-conn}} \\ % &\eejJ\exists{k\in K_j}\Big(\cpredmatseq\Big) &&\text{by \dfnref{prop-taut}} \\ &\hphantom{\eejJ}\;\cpredvecseq \bullet \cpredscalarseq \Big) \bullet \cpredscalarseq, \\ % &\eejJ\exists{k\in K_j}\Big(\cpredmatseq\Big) &&\text{by \dfnref{quant-conn}} \\ &\hphantom{\eejJ}\;\cpredvecseq\Big) \bullet \cpredscalarseq \bullet \cpredscalarseq, \\ % &\eejJ\exists{k\in K_j}\Big(\cpredmatseq\Big) &&\text{by \dfnref{prop-taut}} \\ &\hphantom{\eejJ}\;\cpredvecseq\Big) \bullet \cpredscalarseq. \tag*{\qedhere} \\ \end{alignat*} \end{proof} \begin{lemma}[Classification Predicate Vacuity]\lemlabel{class-pred-vacu} Let $\Classify^c_\gamma\left(\Monoid\Bool\bullet e,\emptyset,\emptyset,\emptyset\right)$ be a classification by~\axmref{class-intro}. $\odot$ is a monoid by \corref{odot-monoid}. Then $c \equiv \gamma \equiv e$. \end{lemma} \begin{proof} First consider $c$. \begin{alignat}{3} c &\equiv \Exists{j\in J}{\Exists{k}{e}\bullet e} \bullet e \qquad&&\text{by \dfnref{monoid-seq}} \label{p:cri-c} \\ &\equiv \Exists{j\in J}{e \bullet e} \bullet e &&\text{by \dfnref{quant-elim}} \\ &\equiv \Exists{j\in J}{e} \bullet e &&\text{by \ref{eq:monoid-identity}} \\ &\equiv e \bullet e &&\text{by \dfnref{quant-elim}} \\ &\equiv e. &&\text{by \ref{eq:monoid-identity}} \end{alignat} For $\gamma$, we have $r=0$ by \axmref{class-yield}, and so by similar steps as~$c$, $\gamma=\Gamma^r=e$. Therefore $c\equiv e$. \end{proof} \begin{figure}[h]\label{fig:always-never} \begin{alignat*}{3} \begin{aligned} \xml{} \end{aligned} \quad&=\quad \Classify^\texttt{always}_\texttt{alwaysTrue} &&\left(\odot^\land,\emptyset,\emptyset,\emptyset\right). \\ % \begin{aligned} \xml{} \end{aligned} \quad&=\quad \Classify^\texttt{never}_\texttt{neverTrue} &&\left(\odot^\lor,\emptyset,\emptyset,\emptyset\right). \end{alignat*} \caption{\tameclass{always} and \tameclass{never} from package \tamepkg{core/base}.} \end{figure} Figure~\ref{fig:always-never} demonstrates \lemref{class-pred-vacu} in the definitions of the classifications \tameclass{always} and \tameclass{never}. These classifications are typically referenced directly for clarity rather than creating other vacuous classifications, encapsulating \lemref{class-pred-vacu}. \begin{theorem}[Classification Rank Independence]\thmlabel{class-rank-indep} Let $\odot=\Monoid\Bool\bullet e$. Then, \begin{equation} \Classify_\gamma\left(\odot,M,v,s\right) \equiv \Classify\left( \odot, \Classify_{\gamma'''}\left(\odot,M,\emptyset,\emptyset\right), \Classify_{\gamma''}\left(\odot,\emptyset,v,\emptyset\right), \Classify_{\gamma'}\left(\odot,\emptyset,\emptyset,s\right) \right). \end{equation} \end{theorem} \begin{proof} First, by \axmref{class-yield}, observe these special cases following from \lemref{class-pred-vacu}: \begin{alignat}{3} \Gamma'''^2 &= \cpredmatseq, \qquad&&\text{assuming $v\union s=\emptyset$} \\ \Gamma''^1 &= \cpredvecseq, &&\text{assuming $M\union s=\emptyset$}\\ \Gamma'^0 &= \cpredscalarseq. &&\text{assuming $M\union v=\emptyset$} \end{alignat} By \thmref{class-compose}, we must prove \begin{align} \Exists{j\in J}{ \Exists{k\in K_j}{\cpredmatseq} \bullet \cpredvecseq } \bullet \cpredscalarseq \nonumber\\ \equiv c \equiv \Exists{j\in J}{ \Exists{k\in K_j}{\gamma'''_{j_k}} \bullet \gamma''_j } \bullet \gamma'. \label{eq:rank-indep-goal} \end{align} By \axmref{class-yield}, we have $r'''=2$, $r''=1$, and $r'=0$, and so $\gamma'''=\Gamma'''^2$, $\gamma''=\Gamma''^1$, and $\gamma'=\Gamma'^0$. By substituting these values in~\ref{eq:rank-indep-goal}, the theorem is proved. \end{proof} \begin{corollary}[Classification As Proposition] Classifications with $M\union v=\emptyset$ or with constant index sets can be represented by propositional logic (that is---without first-order logic). \end{corollary} \begin{proof} Assume $M\union v=\emptyset$. By \thmref{class-rank-indep}, \begin{align*} c &\equiv \cpredscalarseq, \end{align*} \noindent which is a propositional formula. Similarly, if we define our index set~$J$ to be constant (such that it is known at compile-time)\footnote{% Alternatively, we could set an upper bound for~$J$, always expand into that upper bound, and then let undefined values of $v^m_j$ be~$e$.}, we are then able to eliminate existential quantification over~$J$ as follows: Then, \begin{align}\label{eq:prop-vec} c &\equiv \Exists{j\in J}{\cpredvecseq}, \nonumber\\ &\equiv \left(v^0_0\bullet\cdots\bullet v^m_0\right) \lor\cdots\lor \left(v^0_{|J|-1}\bullet\cdots\bullet v^m_{|J|-1}\right), \end{align} \noindent which is a propositional formula. Similarly, for matrices, \begin{align} c &\equiv \Exists{j\in J}{\Exists{k\in K_j}{\cpredmatseq}}, \nonumber\\ &\equiv \Exists{j\in J}{ \left({M^0_j}_0\bullet\cdots\bullet{M^0_j}_{|K_j|-1}\right) \lor\cdots\lor \left({M^l_j}_0\bullet\cdots\bullet{M^l_j}_{|K_j|-1}\right) }, \end{align} \noindent and then proceed as in~\ref{eq:prop-vec}. \end{proof} \INCOMPLETE{The classification definitions are incomplete!} These definitions may also be used as a form of pattern matching to look up a corresponding variable. For example, if we have $\Classify^\texttt{foo}$ and want to know its \xmlattr{yields}, we can write~$\Classify^\texttt{foo}_\gamma$ to bind the \xmlattr{yields} to~$\gamma$.\footnote{% This is conceptually like a symbol table lookup in the compiler.} \mremark{Note that these illustrate \emph{scalar} values only.} Consider the following classification $\Classify^\texttt{cost-exceeded}$. Let~\tameparam{cost} be a scalar parameter. \index{classification!classify@\xmlnode{classify}} \begin{lstlisting} \end{lstlisting} \noindent is then equivalent to the proposition \begin{equation*} \tameclass{cost-exceeded} \equiv \tameparam{cost} > 100.00. \end{equation*} \index{classification!domain} A classification is either \true or~\false. Let $\tameparam{cost}=150.00$. Then, \begin{align*} \tameclass{cost-exceeded} & \equiv \tameparam{cost} > 100.00 \\ & \equiv 150.00 > 100.00 \\ & \equiv \true. \end{align*} Each \xmlnode{match} of a classification is a~\dfn{predicate}. Multiple predicates are by default joined by conjunction: \begin{lstlisting} \end{lstlisting} \noindent is equivalent to the proposition \begin{equation*} \tameclass{pool-hazard} \equiv \tameparam{diving\_board} \land \tameparam{pool\_depth\_ft} < 8. \end{equation*} \subsection{Matches} \todo{Non-scalar values.} \begin{definition}[Match Equality] \begin{equation*} \xml{} \equiv x = y. \end{equation*} \end{definition} \begin{definition}[Match Equality Short Form] \begin{equation*} \xml{} \equiv \xml{}. \end{equation*} \end{definition} \begin{definition}[Match Equality Long Form] \begin{alignat*}{2} \xml{} &\equiv {}&&\xml{} \\ & &&\quad \xml{} \\ & &&\quad\quad \xml{} \\ & &&\quad \xml{} \\ & &&\xml{} \\ &\equiv {}&&\xml{}. \end{alignat*} \end{definition} \begin{definition}[Match Membership Equivalence] When $T$ is a type defined with \xmlnode{typedef}, \begin{equation*} \xml{} \equiv x \in T. \end{equation*} \end{definition}