% -*- TeX-master: t; TeX-PDF-mode: t -*-

\documentclass[11pt]{article}
\usepackage{ifthen}
\usepackage{alltt}
% \usepackage{indentfirst}
\usepackage{latexsym}
\usepackage{graphicx}
\usepackage{gdefs}
% \usepackage{logdef}
\usepackage{amsmath}
\usepackage{amssymb}
\usepackage{setspace}
\usepackage{rotating}
\usepackage{longtable}
\usepackage{hhline}
% \usepackage{refs}
\usepackage{changebar}
\usepackage{array}
\usepackage{wrapfig}
\usepackage[small,compact]{titlesec}
\usepackage{color} % For the \warn command.
\newcommand{\warn}[1]{\textbf{\color{red} [#1] }}

\usepackage{enumitem}
\setlist{nosep,leftmargin=\parindent}

\setlength{\topmargin}{0.0in}
\setlength{\headheight}{0.0in}
\setlength{\headsep}{0.0in}
\setlength{\textwidth}{6.5in}
\setlength{\oddsidemargin}{0.0in}
\setlength{\evensidemargin}{0.0in}
\setlength{\textheight}{9.0in}

\setcounter{topnumber}{5}
\def\topfraction{0.99}
\def\textfraction{0.05}
\def\floatpagefraction{0.9}
\setcounter{bottomnumber}{5}
\def\bottomfraction{0.99}
\setcounter{totalnumber}{10}
\def\dbltopfraction{0.99}
\def\dblfloatpagefraction{0.8}
\setcounter{dbltopnumber}{5}

\setlength{\marginparwidth}{.95in}
\let\oldmarginpar\marginpar
\renewcommand\marginpar[1]{\-\oldmarginpar[\raggedleft\footnotesize #1]%
{\raggedright\footnotesize #1}}

\let\oldthebibliography=\thebibliography
  \let\endoldthebibliography=\endthebibliography
  \renewenvironment{thebibliography}[1]{%
    \begin{oldthebibliography}{#1}%
      \setlength{\parskip}{0ex}%
      \setlength{\itemsep}{0ex}%
  }%
  {%
    \end{oldthebibliography}%
  }

\newcommand{\Paths}{\textit{Paths}}
\newcommand{\Id}{\textit{Id}}
\newcommand{\Var}{\textit{Var}}
\newcommand{\NULL}{\textit{NULL}}
\newcommand{\nullVar}{\textit{null}}
\newcommand{\head}{\textit{head}}
\newcommand{\temp}{\textit{temp}}
\newcommand{\malloc}{\textit{malloc}}
\newcommand{\mallocThree}{\textit{malloc\$3}}


\DeclareMathOperator{\combine}{\oplus}
\DeclareMathOperator*{\Combine}{\bigoplus}
\renewcommand{\int}{\textit{int}}
\newcommand{\pe}{\textit{pe}}
\newcommand{\pgen}{\textit{pgen}}
\newcommand{\cogen}{\textit{cogen}}
\newcommand{\lsem}{\lbrack\!\lbrack}
\newcommand{\rsem}{\rbrack\!\rbrack}
\newcommand{\sem}[1]{\lsem #1 \rsem}

\renewcommand{\exp}{\textit{exp}}
\newcommand{\nonterminal}{\textit{nonterminal}}
\newcommand{\terminal}{\textit{terminal}}
\newcommand{\childNum}{\textit{childNum}}
\newcommand{\Operator}{\textit{Operator}}
\newcommand{\Arity}{\textit{Arity}}
\newcommand{\PlusExp}{\textit{PlusExp}}
\newcommand{\TimesExp}{\textit{TimesExp}}
\newcommand{\IntExp}{\textit{IntExp}}
\newcommand{\Variable}{\textit{Variable}}
\newcommand{\natNum}{\textit{natNum}}
\newcommand{\ident}{\textit{ident}}


\title{Problems: Regular Trees}
\date{}

\sloppy

\begin{document}           % End of preamble and beginning of text.

\maketitle


\begin{enumerate}

\item

\noindent
A \emph{non-deterministic, bottom-up, finite-state tree automaton}
(which will be abbreviated as FSTA) is a formalism for
recognizing (or ``accepting'') members of a language of trees.
An FSTA $A = (Q, Q^F, \Sigma, \delta)$ has
a set of \emph{states} $Q$, a set of final states $Q^F \subseteq Q$,
a \emph{ranked alphabet} $\Sigma$, and a transition
relation $\delta$.

A ranked alphabet means that each symbol has an \emph{arity},
which indicates how many children it has.  We will denote, e.g.,
a binary (arity-2) symbol $\textit{foo}$ by $\textit{foo}^2$.
Thus, if $T_1$ and $T_2$ are two trees,
$\textit{foo}^2(T_1,T_2)$ is another tree; it has the symbol
$\textit{foo}^2$ at its root.

The transition relation $\delta$ consists of rules of the form
\[
  q(f^n) \leftarrow f^n(q_1, \ldots, q_n),
\]
where $q, q_1, \ldots, q_n \in Q$ and $f^n$ is an $n$-ary symbol.
We allow $A$ to be non-deterministic; that is,
one can have multiple result states (i.e., left-hand-side states)
for a given combination of symbol and child states:
\[
  \begin{array}{rcl}
     q(f^n) & \leftarrow & f^n(q_1, \ldots, q_n) \\
    q'(f^n) & \leftarrow & f^n(q_1, \ldots, q_n)
  \end{array}
\]

An FSTA $A$ accepts a language of trees $L(A)$.
For a given tree $T$, $T$ is accepted or rejected depending
on the outcome of the possible \emph{runs} of $A$ over $T$.
A run labels each leaf of $T$ with a state, and then moves upward
to successively label each node of $T$ with a state, using
the rules of $\delta$.
That is, if we have the rule
\[
  q(f^n) \leftarrow f^n(q_1, \ldots, q_n)
\]
in $\delta$ and there is a subtree $S$ whose root symbol is $f^n$
and whose $n$ children are labeled with $q_1, \ldots, q_n$,
respectively, then the root of $S$ can be labeled with $q$.

An \emph{accepting run} is one that labels the root of the tree
with a state in $Q^f$.  Because we allow $A$ to be non-deterministic,
only \emph{one} of the possible runs of $A$ over $T$ needs
to be an accepting run for $T$ to be \emph{accepted}
(i.e., for $T \in L(A)$ to hold).

An FSTA has no initial state, but the rules for 0-ary symbols
cause certain states to act as initial states at a tree's
various leaves.
For instance, suppose that we have the rule
\[
  q_{17}(a^0) \leftarrow a^0()
\]
Then if $T$ has any instance of $a^0$ as a leaf, that leaf
can be labeled with $q_{17}$, and serves as one of the
``initial'' states for runs of $A$ over $T$.
Note that we are permitted to have multiple rules for
a 0-ary symbol:
\[
  \begin{array}{rcl}
    q_{15}(a^0) & \leftarrow & a^0() \\
    q_{17}(a^0) & \leftarrow & a^0()
  \end{array}
\]

\newcommand{\plus}{\textit{plus}}
\newcommand{\float}{\textrm{float}}
\newcommand{\err}{\textrm{error}}

\noindent
{\bf Example}.
Consider the FSTA $A_{\textit{exp}}$ defined as follows:
\begin{eqnarray*}
\lefteqn{A_{\textit{exp}} = ( \{ q_\int, q_\float, q_\err \}, \{ q_\int, q_\float \}, \{ \plus^2, a^0, m^0, x^0 \}, } \\
  &&
  \begin{array}{l}
    \left\{\begin{array}{cc}
      \begin{array}{rcl}
        q_\int(a^0) & \leftarrow & a^0() \\
        q_\int(m^0) & \leftarrow & m^0() \\
        q_\float(m^0) & \leftarrow & m^0() \\
        q_\float(x^0) & \leftarrow & x^0() \\
        q_\int(\plus^2) & \leftarrow & \plus^2(q_\int, q_\int) \\
        q_\float(\plus^2) & \leftarrow & \plus^2(q_\float, q_\float) \\
        q_\err(\plus^2) & \leftarrow & \plus^2(q_\int, q_\float)
      \end{array}
      &
      \begin{array}{rcl}
        q_\err(\plus^2) & \leftarrow & \plus^2(q_\float, q_\int) \\
        q_\err(\plus^2) & \leftarrow & \plus^2(q_\err, q_\int) \\
        q_\err(\plus^2) & \leftarrow & \plus^2(q_\err, q_\float) \\
        q_\err(\plus^2) & \leftarrow & \plus^2(q_\int, q_\err) \\
        q_\err(\plus^2) & \leftarrow & \plus^2(q_\float, q_\err) \\
        q_\err(\plus^2) & \leftarrow & \plus^2(q_\err, q_\err) \\
      \end{array}
    \end{array}\right\}
  \end{array}
).
\end{eqnarray*}
Let $T_1$ and $T_2$ be two trees defined as follows:
\[
\begin{array}{rcl}
  T_1 & = & \plus^2(\plus^2(m^0(), a^0()), a^0()) \\
  T_2 & = & \plus^2(\plus^2(a^0(), b^0()), x^0())
\end{array}
\]
Note that there is both an accepting run for $T_1$, namely,
\[
\begin{array}{rcl}
  &             & \plus^2(\plus^2(m^0(), a^0()), a^0()) \\
  & \Rightarrow & \plus^2(\plus^2(q_\int(m^0), q_\int(a^0)), q_\int(a^0)) \\
  & \Rightarrow & \plus^2(q_\int(\plus^2(m^0(), a^0())), q_\int(a^0)) \\
  & \Rightarrow & q_\int(\plus^2(\plus^2(m^0(), a^0()), a^0())) \\
\end{array}
\]
and a non-accepting run for $T_1$,
\[
\begin{array}{rcl}
  &             & \plus^2(\plus^2(m^0(), a^0()), a^0()) \\
  & \Rightarrow & \plus^2(\plus^2(q_\float(m^0), q_\int(a^0)), q_\int(a^0)) \\
  & \Rightarrow & \plus^2(q_\err(\plus^2(m^0(), a^0())), q_\int(a^0)) \\
  & \Rightarrow & q_\err(\plus^2(\plus^2(m^0(), a^0()), a^0())) \\
\end{array}
\]
In contrast, there is only a non-accepting run for $T_2$, namely,
\[
\begin{array}{rcl}
  &             & \plus^2(\plus^2(a^0(), b^0()), x^0()) \\
  & \Rightarrow & \plus^2(\plus^2(q_\int(a^0), q_\int(b^0)), q_\float(x^0)) \\
  & \Rightarrow & \plus^2(q_\int(\plus^2(a^0(), b^0())), q_\float(x^0)) \\
  & \Rightarrow & q_\err(\plus^2(\plus^2(a^0(), b^0()), x^0)) \\
\end{array}
\]
Consequently, $T_1 \in L(A_{\textit{exp}})$ but $T_2 \not\in L(A_{\textit{exp}})$.
$\Box$

Abbreviations:
\begin{itemize}
  \item
    You may drop superscripts on alphabet symbols.
  \item
    Although we wrote out all of the possible transitions involving
    $q_\err$, it would have been convenient to treat $q_\err$ as a
    ``stuck'' state---in which case, in the set of rules for
    $A_{\textit{exp}}$ we would have omitted the last two rules in the
    first column and all the rules in the second column.  Such rules would
    be implicit: an occurrence of $q_\err$ in any child of an arity-$k$
    symbol results in the symbol being labeled with $q_\err$.
\end{itemize}

\medskip
\noindent
{\bf Part (a)}

\noindent
Explain how ordinary non-deterministic finite-state (string)
automata are a degenerate case of FSTAs.

\newpage
We now describe ideas needed for Parts (b), (c), and (d).

FSTAs are useful in dataflow-analysis and model-checking
problems because they can be used to describe the matched
call-and-return structure of paths in multi-procedure programs.
Parts (b) and (c) concern how to define an FSTA to specify
a tree-language that captures the matched paths specific
to a particular program, namely, the one shown below.
(The ``if(*)'' denotes a non-deterministic branch.)

\medskip
\noindent
\qquad\qquad\qquad\qquad
\begin{tabular}{c}
  \begin{tabular}{l@{\hspace{9.0ex}}l}
    \begin{tabular}{l}
      void foo() \{ \\
      \quad n1: x1 = 0; \\
      \quad n2: x2 = 1; \\
      \quad n3: bar(); \\
      \quad n4: ; \\
      \}
    \end{tabular}
    &
    \begin{tabular}{l}
      void bar() \{ \\
      \quad n5: if (*) \{ \\
      \quad\quad $~~~~~~~$x1 = x1 + x2; \\
      \quad\quad n6: bar(); \\
      \quad\quad n7: x2 = x2+1; \\
      \quad \} \\
      \quad n8: ; \\
      \}
    \end{tabular}
  \end{tabular}
  \\
  \\
  \begin{tabular}{c}
    \includegraphics[width=6cm]{figures/FooBar.eps}
  \end{tabular}
\end{tabular}

\medskip
The FSTA you will define should accept a language, each
tree of which represents a properly matched path
from $n_1$ to $n_4$. For each properly matched path $\rho$
from $n_1$ to $n_4$, the FSTA should accept a tree
that represents $\rho$.  The FSTA should reject trees that either
(i) do not represent a path, or (ii) represent a path
that violates matched call-and-return structure in the graph given
above.

The alphabet $\Sigma$ consists of three kinds of symbols:
\begin{enumerate}
  \item
    Nine 0-ary symbols for the nine edges in the graph given above:
    \[
      \{ e^0_{{n_1}\rightarrow{n_2}}, e^0_{{n_2}\rightarrow{n_3}}, e^0_{{n_3}\rightarrow{n_5}},
          e^0_{{n_5}\rightarrow{n_8}}, e^0_{{n_5}\rightarrow{n_6}}, e^0_{{n_6}\rightarrow{n_5}},
          e^0_{{n_7}\rightarrow{n_8}}, e^0_{{n_8}\rightarrow{n_7}}, e^0_{{n_8}\rightarrow{n_4}}
       \}.
     \]
  \item
    Sixty-four binary symbols for possible start/end positions in a sub-path:
    \[
      \{ p^2_{{n_i}\rightarrow{n_j}} \mid 1 \leq i,j \leq 8 \}.
    \]
  \item
    Sixty-four ternary symbols for subtrees that represent
    possible matched call-and-return sub-paths:
    $\{ c^3_{{n_i}\rightarrow{n_j}} \mid 1 \leq i,j \leq 8 \}$.
    (The symbols are ternary so that the three children
    can represent a call-edge from caller-to-callee,
    an edge or a matched path from the entry node to the exit node
    of the callee, and a return-edge from callee-to-caller.)
\end{enumerate}

\medskip
\noindent
{\bf Part (b)}

\noindent
The idea is that the frontier of each tree (i.e., its sequence of
leaves in left-to-right order) represents a candidate path.
Draw the three trees that represent the following paths:
\begin{enumerate}
  \item
    $[n1 \rightarrow n2, n2 \rightarrow n3, n3 \rightarrow n5, n5 \rightarrow n8, n8 \rightarrow n4]$
  \item
    $[n1 \rightarrow n2, n2 \rightarrow n3, n3 \rightarrow n5, n5 \rightarrow n6, n6 \rightarrow n5, n5 \rightarrow n6, n6 \rightarrow n5, n5 \rightarrow n8, n8 \rightarrow n7, n7 \rightarrow n8, n8 \rightarrow n7, n7 \rightarrow n8, n8 \rightarrow n4]$
  \item
    $[n1 \rightarrow n2, n2 \rightarrow n3, n3 \rightarrow n5, n5 \rightarrow n8, n8 \rightarrow n7]$
\end{enumerate}
(Note: the first two trees should be accepted by the FSTA that
you will define in Part (c); the third tree should be rejected
by the FSTA from Part (c).)

\medskip
\noindent
{\bf Part (c)}

\noindent
The alphabet $\Sigma$ of the FSTA has been defined above.
The set of states $Q$ of the FSTA consists of a stuck
state, $q_\err$, together with 64 states that are
indexed by a pair of node names:
$Q = \{q_\err\} \cup \{ q_{{n_i}\rightarrow{n_j}} \mid 1 \leq i,j \leq 8 \}$.
The set of final states is defined as follows:
$Q^F = \{ q_{{n_1}\rightarrow{n_4}} \}$.

Using $Q$, $Q^F$, and $\Sigma$ as defined above, \emph{sketch}
the definition
of an FSTA that accepts the language of trees that represent
all properly matched paths from $n_1$ to $n_4$.
The intention is that state $q_{{n_i}\rightarrow{n_j}}$ only arises in
a run when there exists a matched path from $n_i$ to $n_j$.

{\bf Note}: There are 65 different states and 137 alphabet symbols.
We do not expect you to write out the full transition relation;
however, it should be clear from your answer what the essential
features are and what the intended pattern is.

Explain why your FSTA accepts the first two trees from your
answer to Part (b), and why it rejects the third tree from
Part (b).

\medskip
\noindent
{\bf Part (d)}

\noindent
Given an FSTA $A = (Q, \Sigma, \delta, q^0, Q^F)$, give
an algorithm for determining whether $L(A) = \emptyset$.

% \noindent
% \medskip
% \noindent
% {\bf Part (e)}
% 
% \noindent
% Given two FSTAs $A_1 = (Q_1, \Sigma_1, \delta_1, q^0_1, Q^F_1)$
% and $A_2 = (Q_2, \Sigma_2, \delta_2, q^0_2, Q^F_2)$,
% give the definition of an FSTA that accepts
% $L(A_1) \cap L(A_2)$.

\newpage

\item

\noindent
A {\em regular tree grammar} is a formalism for
specifying languages of trees.  For instance,
the following grammar $G$
\[
\begin{array}{rcl}
  \exp & ::= & \PlusExp(\exp, \exp) \\
       &  |  & \TimesExp(\exp, \exp) \\
       &  |  & \IntExp(\natNum) \\
       &  |  & \Variable(\ident)
\end{array}
\]
where $\natNum = \{0, 1, 2, \ldots \}$ and $\ident$
is some finite or infinite set of allowable identifiers
(e.g., $\{ A, B, \ldots, X, Y, Z \}$),
defines a language $L(G)$ of trees (or terms).
$L(G)$ includes the trees
\[
\begin{array}{l}
  \Variable(A), \Variable(B), \ldots, \Variable(Z), \\
  \IntExp(0), \IntExp(1), \ldots, \\
  \PlusExp(\Variable(A), \IntExp(0)), \PlusExp(\Variable(B), \IntExp(0)), \ldots, \\
  \TimesExp(\Variable(A), \IntExp(0)), \TimesExp(\Variable(B), \IntExp(0)), \ldots, \\
  \PlusExp(\IntExp(0),\Variable(A)), \PlusExp(\IntExp(0),\Variable(B)), \ldots, \\
  \TimesExp(\IntExp(0),\Variable(A)), \TimesExp(\IntExp(0),\Variable(B)), \ldots,
\end{array}
\]

Let us now introduce some terminology:
$\exp$, $\natNum$, and $\ident$ are called \emph{nonterminals} (or \emph{types});
$\PlusExp$, $\TimesExp$, $\IntExp$, and $\Variable$ are called \emph{operators}.
It is useful to consider $0, 1, 2, \ldots$ as nullary operators
of type $\natNum$ (in which case we might write them as
$0(), 1(), 2(), \ldots$) and $A, B, \ldots, X, Y, Z$ as
nullary operators of type $\ident$ (in which case we might write them as
A(), B(), \ldots, X(), Y(), Z()).
Hence, with this notation one of the trees in $L(G)$ is
$\PlusExp(\Variable(A()), \IntExp(0()))$.

Note that each operator has a fixed \emph{arity} that specifies
the number of children that it has.  For instance, the arities of
some of the operators of $G$ are as follows:
\[
\begin{array}{|l|l|}
  \hline
  \Operator & \Arity \\
  \hline
  \PlusExp & 2 \\
  \TimesExp & 2 \\
  \IntExp & 1 \\
  \Variable & 1 \\
  0 & 0 \\
  1 & 0 \\
  2 & 0 \\
  \vdots & \vdots \\
  A & 0 \\
  B & 0 \\
  \vdots & \vdots \\
  Z & 0 \\
  \hline
\end{array}
\]
Let the children of an arity-$k$ operator be numbered
$1, \ldots, k$.

A \emph{path} in a tree can be described by a string
over an alphabet of (compound) symbols of the form
\[
  (\nonterminal::\Operator.\childNum)
\]
(By convention, if $\Operator$ is a nullary operator,
$\childNum$ is 0.)
For instance, the set of root-to-leaf paths in the tree
$\PlusExp(\Variable(A()), \IntExp(0()))$ is
\[
\left\{
\begin{array}{l}
  (\exp::\PlusExp.1)(\exp::\Variable.1)(\ident::A.0), \\
  (\exp::\PlusExp.2)(\exp::\IntExp.1)(\natNum::0.0)
\end{array}
\right\}.
\]

\medskip

\noindent
{\bf Part (a)}

\noindent
Describe how to create an ordinary finite-state automaton that accepts
the language of root-to-leaf paths in given a regular tree grammar
$H$.  That is, given a regular tree grammar $H$, your construction
should produce the automaton $A_H$ that accepts
\[
  \{ p \mid p~\text{is a root-to-leaf path in some tree T}~\in L(H) \}.
\]

\medskip

\noindent
{\bf Part (b)}

\noindent
Give the automaton that would be produced by your construction for
the regular tree grammar $G$
\[
\begin{array}{rcl}
  \exp & ::= & \PlusExp(\exp, \exp) \\
       &  |  & \TimesExp(\exp, \exp) \\
       &  |  & \IntExp(\natNum) \\
       &  |  & \Variable(\ident)
\end{array}
\]

\medskip

\noindent
{\bf Part (c)}

\noindent
Regular tree grammars are related to context-free grammars in the
following way:
Suppose that you normalize a context-free grammar $F$
by introducing additional nonterminals so that terminal symbols
only appear in leaf productions of the form
$\nonterminal \rightarrow \terminal$;
then, by introducing an operator symbol for each production
(and treating each terminal symbol as a nullary operator),
one has a regular tree grammar whose language is the set of
parse trees for the context-free grammar $F$.

\medskip

A context-free grammar can have two kinds of useless nonterminals:
\[
\begin{array}{ll}
  \text{Useless 1}: & \text{nonterminal $n$ is useless if there is no derivation $root \rightarrow^* \alpha~n~\beta$} \\
  \text{Useless 2}: & \text{nonterminal $n$ is useless if there is no finite parse tree derivable from $n$}
\end{array}
\]

Describe \emph{two} algorithms, both working on finite automata
of the kind described earlier for the language of root-to-leaf paths
of a regular tree grammar:

\medskip

\noindent
{\bf Part (c.i)}
The algorithm for this part returns
the set of nonterminals that are useless because of reason ``Useless 1''.

\medskip

\noindent
{\bf Part (c.ii)}
The algorithm for this part returns
the set of nonterminals that are useless because of reason ``Useless 2''.
(For this part, you may assume that all ``Useless 1'' nonterminals were
removed from the context-free grammar before the automaton was constructed.)

\medskip

\noindent
{\bf Part (d)}

\noindent
Give an example of a \emph{context-free grammar} that has both kinds of useless
nonterminals, and illustrate the two algorithms on it.

\end{enumerate}


\end{document}
