Synchronous Models of Language

Extracted source text ยท arXiv cmp-lg/9605032

\documentstyle[aclap,lingmacros]{article}

\newcommand{\secref}[1]{Section~\ref{#1}}
\newcommand{\figref}[1]{Figure~\ref{#1}}

\newcommand{\veps}{\varepsilon}
\newcommand{\epsfree}{--$\varepsilon$}
\newcommand{\perm}[1]{\mbox{${\sf Perm}({#1})$}}


\newcommand{\csg}{{\rm CSG}}
\newcommand{\tag}{{\rm TAG}}
\newcommand{\cfg}{{\rm CFG}}
\newcommand{\slig}{\mbox{\rm MLIG}}
\newcommand{\oldslig}{\mbox{\rm \{\}-LIG}}
\newcommand{\stlig}{\mbox{\rm []-LIG}}
\newcommand{\lig}{\mbox{\rm []-LIG}}
\newcommand{\spda}{\mbox{\rm \{\}-PDA}}
\newcommand{\uvg}{{\rm UVG}}
\newcommand{\ud}{{\rm UVG-DL}}
\newcommand{\uvd}{{\rm UVG-DL}}
\newcommand{\uds}{{\rm UVG-DL$_{\rm strict}$}}
\newcommand{\uvdi}{{\rm UVG-DL-$\Delta$}}
\newcommand{\uvilex}{{\rm UVG-DL-$\Delta_{\rm Lex}$}}
\newcommand{\uvlex}{{\rm UVG-DL$_{\rm Lex}$}}
\newcommand{\qfr}{\mbox{$_{\rm fR}^q$}}
\newcommand{\vtag}{\mbox{\rm V-TAG}}
\newcommand{\vtagd}{\mbox{\rm V-TAG-$\Delta$}}
\newcommand{\vtaglex}{{\rm V-TAG-$\Delta_{\rm Lex}$}}
\newcommand{\ibp}{{\rm \{\}-BEPDA}}



\newcommand{\vii}{\mbox{${\cal V}^{(f)}$}}
\newcommand{\bii}{\mbox{${\cal B}^{(f)}$}}
\newcommand{\lmax}[1]{\mbox{$L_M({#1})$}}
\newcommand{\langg}{\mbox{$Q_{f}$}}

\newcommand{\longderiv}[1]{\mbox{$\:{\Longrightarrow_{#1}}\:$}}
\newcommand{\longderivi}[2]{\mbox{$\:\stackrel{\!\!\!\!\!#1}%
                        {\Longrightarrow_{#2}}\:$}}

%\newcommand{\comment}[1]{}
%\newcommand{\myspace}{\hspace{1em}}
%  \newcommand{\myspaces}{\;\;\;\;\;}

\newcommand{\size}[1]{\mbox{$\mid \! {#1} \! \mid$}}
\newcommand{\mycount}[1]{\mbox{$\#({#1})$}}
\newcommand{\mycounta}[2]{\mbox{$\#_{#1}({#2})$}}
\newcommand{\bigo}[1]{\mbox{$O({#1})$}}
\newcommand{\bigt}[1]{\mbox{${\mit\Theta}({#1})$}}
\newcommand{\proof}{\noindent {\em Proof.\hspace{1em}}}
%\newcommand{\olproof}{{\em Outline of the proof.\hspace{1em}}}
\newcommand{\olproof}{\noindent{\bf Proof (outline).\hspace{1em}}}
\newcommand{\closeproof}{\mbox{\hspace{1em}\rule{.45em}{.45em}}}
\newcommand{\closeproofns}{\mbox{\rule{.45em}{.45em}}}
%\newcommand{\closeexa}{\mbox{\hspace{1em}\fbox{\rule{.45em}{.45em}}}}
%\newcommand{\closeexans}{\mbox{\fbox{\rule{.45em}{.45em}}}}
\newcommand{\closeexa}{\mbox{\hspace{1em}$\Box$}}
\newcommand{\closeexans}{\mbox{$\Box$}}

\newcommand{\subs}[2]{\mbox{$_{#1}w_{#2}$}}
\newcommand{\mand}{\;\mbox{\rm and}\;}

\newcommand{\nonterm}{V_{{\rm N}}}
\newcommand{\myterm}{V_{{\rm T}}}
\newcommand{\myind}{V_{{\rm I}}}
\newcommand{\myinds}{V_{{\rm [I]}}}  %^{{\rm[]}}}
\newcommand{\myindm}{V_{{\rm \{I\}}}}    %^{{\rm\{\}}}}
\newcommand{\gvar}{\mbox{$(\nonterm \cup \myterm)^{\ast}$}}
\newcommand{\ggvar}{\mbox{$((\nonterm \myind^{\ast}) \cup
\myterm)^{\ast}$}}
\newcommand{\ggmvar}{\mbox{$((\nonterm {\cal M}(\myind)) \cup
\myterm)^{\ast}$}}
\newcommand{\nonmyterm}{\mbox{$(\nonterm \cup \myterm)$}}
\newcommand{\deri}{\mbox{$\:\stackrel{\!\!\!\!*}{\Longrightarrow}\:$}}
\newcommand{\deriG}{\mbox{$\:\stackrel{\!\!\!\!*}{\Longrightarrow_G}\:$}}
\newcommand{\deria}[1]{\mbox{$\:\stackrel{\!\!\!#1}{\Longrightarrow}\:$}}
\newcommand{\sderia}[1]{\mbox{$\:\stackrel{\!\!\!#1}{\Longrightarrow}\:$}}
\newcommand{\deriaa}[2]{\mbox{$\:{\stackrel{\!\!\!#1}\Longrightarrow}_{#2}\:$}}
\newcommand{\lderiv}[1]{\mbox{$\:{\stackrel{\!\!\!*}\Longrightarrow}_{#1}\:$}}
\newcommand{\deriv}[1]{\mbox{$\:{\Longrightarrow_{#1}}\:$}}
\newcommand{\derivi}[2]{\mbox{$\:\stackrel{\!\!\!\!\!\!\!#1}%
                        {\Rightarrow_{#2}}\:$}}
\newcommand{\derivii}[2]{\mbox{$\:\stackrel{\!\!\!\!\!\!\!#1}%
                        {\Rightarrow_{#2}}\:$}}


\newcommand{\vds}{\mbox{$\:\:\:\raisebox{.45em}{{$\scriptstyle *$}}\hspace{-.62em}{\vdash}\:$}}
\newcommand{\vda}[1]{\mbox{$\:\:\:\raisebox{.45em}{{$\scriptstyle
#1$}}\hspace{-.62em}{\vdash}\:$}}
\newcommand{\vdm}[1]{\mbox{${\vdash_{\!\!\!\!{\mit {\scriptscriptstyle
M}}}}\:$}}
\newcommand{\vdsm}[1]{\mbox{$\:\:\:\raisebox{.45em}{{$\scriptstyle *$}}\hspace{-.62em}{\vdash_{\!\!\!\!{\mit {\scriptscriptstyle M}}}}\:$}}
\newcommand{\vdsa}[1]{\mbox{$\:\:\:\raisebox{.45em}{{$\scriptstyle
*$}}\hspace{-.62em}{\vdash_{\!\!\!\!{\mit {\scriptscriptstyle #1}}}}\:$}}
\newcommand{\vdaa}[2]{\mbox{$\:\:\:\raisebox{.48em}{{$\scriptstyle
#1$}}\hspace{-.62em}{\vdash_{\!\!\!\!{\mit {\scriptscriptstyle #2}}}}\:$}}
\newcommand{\vdaal}[2]{\mbox{$\:\:\:\raisebox{.57em}{{$\scriptstyle
#1$}}\hspace{-.85em}{\vdash_{\!\!\!\!{\mit {\scriptscriptstyle #2}}}}\:$}}
\newcommand{\vdaall}[2]{\mbox{$\:\:\:\raisebox{.57em}{{$\scriptstyle
#1$}}\hspace{-1.9em}{\vdash_{\!\!\!\!{\mit {\scriptscriptstyle #2}}}}\:$}}
\newcommand{\vdaaa}[3]{\mbox{$\:\:\:\raisebox{.57em}{{$\scriptstyle
#1$}}\hspace{-#3em}{\vdash_{\!\!\!\!{\mit {\scriptscriptstyle #2}}}}\:$}}



\newcommand{\bos}{\hspace{.25em}\raisebox{-.25em}{\rule{.1203em}{1em}\hspace{-.1203em}\rule[.95em]{.4em}{.1203em}\hspace{-.4em}\rule{.4em}{.1203em}\hspace{.2em}}}


\newcommand{\bee}{\mbox{${\cal B}^{(r,f)}$}}
\newcommand{\lang}{\mbox{$L_{r,f}$}}


\newcommand{\dom}[2]{\mbox{\sf dom$_{#1}(#2)$}}
\newcommand{\doms}[1]{\mbox{\sf dom$_{#1}$}}
\newcommand{\domsi}{\mbox{\sf dom}}




\newcommand{\mymid}{\,\mid\,}

\newcommand{\sca}{{\rm USCG}}
\newcommand{\lsca}{{\rm LUSCG}}
\newcommand{\lscaof}[2]{\mbox{${#1}$-\lsca$({#2})$}}
\newcommand{\lcfrs}{{\rm LCFRS}}
\newcommand{\lcfrsof}[2]{\mbox{${#1}$-\lcfrs$({#2})$}}
\newcommand{\mcfg}{{\rm MCFG}}
\newcommand{\mcfgof}[2]{\mbox{${#1}$-\mcfg$({#2})$}}



\newcommand{\cf}[1]{\mbox{${\rm der}({#1})$}}
\newcommand{\yt}[2]{\mbox{$yT_{\rm #1}({\rm #2})$}}



\newcommand{\msize}[1]{\mbox{$\parallel \!\! {#1} \!\! \parallel$}}
\newcommand{\rhs}[1]{\mbox{${\sf rhs}({#1})$}}
\newcommand{\lhs}[1]{\mbox{${\sf lhs}({#1})$}}
\newcommand{\vdate}[2]{\mbox{$\odot_{#1}^{#2}$}}
\newcommand{\cvector}[2]{\mbox{$\gamma_{#1}^{#2}$}}
\newcommand{\ivector}[1]{\mbox{$\gamma_{#1}$}}
\newcommand{\vvector}[3]{\mbox{$\gamma_{#1}^{(#2,#3)}$}}


\newcommand{\countl}[1]{\mbox{\sc count-$#1$}}
\newcommand{\mixl}[1]{\mbox{\sc mix-}#1}
\newcommand{\ints}{\mbox{\sf N}}




\newtheorem{definition}{Definition}
\newtheorem{theorem}{Theorem}
\newtheorem{lemma}[theorem]{Lemma}
\newtheorem{prop}{Proposition}
\newtheorem{coro}[theorem]{Corollary}
\newtheorem{conj}[theorem]{Conjecture}



\newcounter{exacount}
\setcounter{exacount}{0}
\newcommand{\example}{\noindent \refstepcounter{exacount}{\sc Example
\theexacount}}%\newline}
\newcommand{\examplel}[1]{\noindent \refstepcounter{exacount}{\sc Example
\theexacount}\label{#1}} 
\newcommand{\examplecont}[1]{\noindent{\sc Example~\ref{#1}}\newline} 



\newcommand{\scrl}{\mbox{$\cal L$}}
\newcommand{\scrlof}[1]{\mbox{\rm $\cal L$(#1)}}
\newcommand{\scrla}[1]{\mbox{\rm $\cal L$(#1)}}
\newcommand{\scrlra}[1]{\mbox{\rm $\cal L_R$(#1)}}
\newcommand{\scrlla}[1]{\mbox{\rm $\cal L_L$(#1)}}

\newcommand{\multis}[1]{\mbox{$\cal M$}(#1)}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\newcommand{\srel}{\synch}   %% synchronization relation
\newcommand{\Srel}{\Sigma}   %% Synchronization relation

\newcommand{\heir}{heir}   %% Synchronization relation


\newcommand{\sep}{\,\mid\,}
\newcommand{\de}{\mbox{$\rightarrow$}}
\newcommand{\e}{\mbox{$\varepsilon$}}


\newcommand{\dlvect}{D}

\newcommand{\domain}{\mbox{${\it dom}$}}
\newcommand{\range}{\mbox{${\it rg}$}}

\newcommand{\penum}{\mbox{$\Pi$}}
\newcommand{\rhsenum}{\mbox{$\Gamma$}}
%\newcommand{\dlinks}{\mbox{$\lambda$}}
\newcommand{\dlinks}[1]{\mbox{\sf dom$_{#1}$}}
%\newcommand{\slinks}{\mbox{$\sigma$}}

\newcommand{\dlinksp}[1]{\mbox{\sf dl$_{#1}$}}
\newcommand{\dlinkspi}{\mbox{\sf dl}}


\newcommand{\synch}{\mbox{$\sigma$}}

\newcommand{\uvgd}{\mbox{{\rm UVG-DL}}}
\newcommand{\suvgd}{\mbox{{\rm SynchUVG-DL}}}
\newcommand{\suvd}{\mbox{{\rm SynchUVG-DL}}}
\newcommand{\nlstag}{\mbox{{\rm nlSynchTAG}}}
\newcommand{\stag}{\mbox{{\rm SynchTAG}}}




\renewcommand{\labelenumi}{\rm{(\roman{enumi})}}
\renewcommand{\labelenumii}{\rm{(\alph{enumii})}}

\newtheorem{algorithm}{Algorithm}





\newcommand{\out}{\mbox{${\it out}$}}






\include{psfig}



\newcommand{\namecite}[1]{\cite{#1}}


% this set of commands is meant to solve the
% problem where figures get pushed to the end by
% changing the parameters of how much space on a
% page the figures can take up
% 
\setcounter{bottomnumber}{50}
\setcounter{topnumber}{50}
\setcounter{dbltopnumber}{50}
\renewcommand{\bottomfraction}{1}
\renewcommand{\topfraction}{1}
\renewcommand{\dbltopfraction}{1}
\setcounter{totalnumber}{50}
\renewcommand{\textfraction}{0}
\renewcommand{\floatpagefraction}{0.5}


\title{\vspace{-1in}{\small In {\em Proceedings of the 34th Meeting of the Association for Computational Linguistics (ACL'96)}}\\
Synchronous Models of Language}


\author{Owen Rambow \\
CoGenTex, Inc.                       \\
840 Hanshaw Road, Suite 11           \\
Ithaca, NY 14850-1589                \\
{\tt owen@cogentex.com}\And
       Giorgio Satta \\
        	Dipartimento di Elettronica ed Informatica \\ 
        	Universit\`{a} di Padova \\
        	via Gradenigo, 6/A \\
        	I-35131 Padova,	Italy \\
	{\tt satta@dei.unipd.it}}


\begin{document}


\maketitle
\vspace{-0.5in}
\begin{abstract}
In synchronous rewriting, the productions of two rewriting systems are
paired and applied synchronously in the derivation of a pair of strings.
We present a new synchronous rewriting system and argue that it can handle
certain phenomena that are not covered by existing synchronous systems.  We
also prove some interesting formal/computational properties of our system.
\end{abstract}


\section{Introduction}

Much of theoretical linguistics can be formulated in a very natural manner
as stating correspondences (translations) between layers of representation;
for example, related interface layers LF and PF in GB and Minimalism
\cite{chomsky:1993}, semantic and syntactic information in HPSG
\cite{pollard/sag:1994}, or the different structures such as c-structure
and f-structure in LFG \cite{bresnan/kaplan:1982}.  Similarly, many
problems in natural language processing, in particular parsing and
generation, can be expressed as transductions, which are calculations of
such correspondences.  There is therefore a great need for formal models of
corresponding levels of representation, and for corresponding algorithms
for transduction.

Several different transduction systems have been used in the past by the
computational and theoretical linguistics communities.  These systems have
been borrowed from translation theory, a subfield of formal language
theory, or have been originally (and sometimes redundantly) developed.
{\em Finite state transducers} (for an overview, see, e.g.,
\cite{aho/ullman:1972}) provide translations between regular languages.
These devices have been popular in computational morphology and
computational phonology since the early eighties
\cite{koskenniemi:1983,kaplan/kay:1994}, and more recently in parsing as
well (see, e.g., \cite{gross:1989a,pereira:1991,roche:1993}).  {\em
Pushdown transducers} and {\em syntax directed translation schemata} (SDTS)
\cite{aho/ullman:1969a} translate between context-free languages and are
therefore more powerful than finite state transducers.  Pushdown
transducers are a standard model for parsing, and have also been used
(usually implicitly) in speech understanding.  Recently, variants of SDTS
have been proposed as models for simultaneously bracketing parallel
corpora~\cite{wu:1995}.  Synchronization of tree adjoining grammars (TAGs)
\cite{shieber/schabes:1990a,shieber:1994} are even more powerful than the
previous formalisms, and have been applied in machine translation
\cite{ASJ:1990,egedi/palmer:1994,harbusch/poller:1994,prigent:1994},
natural language generation \cite{shieber/schabes:1991}, and theoretical
syntax \cite{abeille:1994a}.  The common underlying idea in all of these
formalisms is to combine two generative devices through a pairing of their
productions (or, in the case of the corresponding automata, of their
transitions) in such a way that right-hand side nonterminal symbols in the
paired productions are {\em linked}.  The processes of derivation proceed
synchronously in the two devices by applying the paired grammar rules only
to linked nonterminals introduced previously in the derivation.  The fact
that the above systems all reflect the same translation technique has not
always been recognized in the computational linguistics literature.
Following~\namecite{shieber/schabes:1990a} we will refer to the general
approach as {\em synchronous rewriting}.  While synchronous systems are
becoming more and more popular, surprisingly little is known about the
formal characteristics of these systems (with the exception of the
finite-state devices).


In this paper, we argue that existing synchronous systems cannot handle, in
a computationally attractive way, a standard problem in syntax/semantics
translation, namely quantifier scoping.  We propose a new system that
provides a synchronization between two unordered vector grammars with
dominance links (\uvd) \namecite{rambow:1994c}.  The type of
synchronization is closely based on a previously proposed model, which we
will call ``local'' synchronization.  We argue that this synchronous system
can deal with quantifier scoping in the desired way.  The proposed system
has the {\em weak language preservation property}, that is, the defined
synchronization mechanism does not alter the weak generative capacity of
the formalism being synchronized.  Furthermore, the {\em tree-to-forest
translation\/} problem for our system can be solved in polynomial time;
that is, given a derivation tree obtained according to one of the
synchronized grammars, we can construct the forest of all the translated
derivation trees in the other grammar, using a polynomial amount of time.

The structure of this paper is as follows.  In \secref{sec-qr}, we
introduce quantifier raising and review two types of synchronization and
mention some new formal results.  We introduce our new synchronous system
in~\secref{sec-def}, and present our formal results and outline the proof
techniques in \secref{sec-proofs}.



\section{Types of Synchronization}

\label{sec-qr}

\subsection{Quantifier Raising}

We start by presenting an example which is based on transfer between a
syntactic representation and a ``semantic'' representation of the scoping
of quantified NPs.  It is generally assumed that in English (and many other
languages), quantified arguments of a verb can (in appropriate contexts)
take scope in any possible order, and that this generalization extends to
cases of embedded clauses \cite{may:1985}.\footnote{We explicitly exclude
from our analysis cases of quantified NPs embedded in NPs, and do not, of
course, propose to develop a serious linguistic theory of quantifier
scoping.}  For example, sentence (\ref{sent-exa}) can have four possible
interpretations (of the six possible orderings of the quantifiers, two
pairs are logically equivalent), two of which are shown in
(\ref{sec-scopes}).

\enumsentence{\label{sec-exa}\label{sent-exa}
Every man thinks some official said some Norwegian arrived}

\eenumsentence{\label{sec-scopes}\label{sent-scopes}
\item
$\forall x$, $x$ a man, $\exists y$, $y$ an official, $\exists z$, $z$ a
Norwegian, $x$ thinks $y$ said $z$ arrived
\item
$\exists z$, $z$ a Norwegian, $\exists y$, $y$ an official, $\forall x$,
$x$ a man, $x$ thinks $y$ said $z$ arrived }

We give a simplified syntactic representation for (\ref{sent-exa}) in
\figref{fig-exa}, and a simplified semantic representation for
(\ref{sec-scopes}b) in \figref{fig-scopes}.  



\begin{figure}[htb]
\centerline{
\psfig{figure=syntax.eps,scale=67}
}
\caption{Syntactic representation for (1)}
\label{fig-exa}\label{fig-syntax}
\end{figure}



\begin{figure}[htb]
\centerline{
\psfig{figure=semantics.eps,scale=67}
}
\caption{Semantic representation for (2b)}
\label{fig-scopes}\label{fig-semantics}
\end{figure}



\subsection{Non-Local Synchronization}

We will first discuss a type of synchronization proposed by
\namecite{shieber/schabes:1990a}, based on TAG.  We will refer to this
system as {\em non-local synchronous TAG} (\nlstag).  The synchronization
is non-local in the sense that once links are introduced during a
derivation by a synchronized pair of grammar rules, they need not continue
to impinge on the nodes that introduced them: the links may be reassigned
to a newly introduced nonterminal when an original node is rewritten.  We
will refer to this mechanism as {\em link inheritance}.  To illustrate, we
will give as an example an analysis of the quantifier-raising example
introduced above, extending in a natural manner an example given by Shieber
and Schabes.

\begin{figure}[htb]
\centerline{
\psfig{figure=nlstag-gram-small.eps,scale=57}
}
\caption{Elementary structures in nlSynchTAG}
\label{fig-nl-elems}
\end{figure}

\begin{figure}[tb]
\centerline{
\psfig{figure=nlstag-der2-small.eps,scale=57}}
\centerline{
\psfig{figure=nlstag-der3-small.eps,scale=57}}
\caption{Non-local derivation  in nlSynchTAG}
\label{fig-nl-der1}
\end{figure}



The elementary structures are shown in \figref{fig-nl-elems} (we only give
one NP --- the others are similar).  The nominal arguments in the syntax
are associated with pairs of trees in the semantics, and are linked to two
nodes, the quantifier and the variable.  The derivation proceeds as
illustrated in Figure~\ref{fig-nl-der1}, finally yielding the two
structures in \figref{fig-syntax} and \figref{fig-scopes}.  Note that some
of the links originating with the NP nodes are inherited during the
derivation.  By changing the order in which we add the nominal arguments at
the end of the derivation, we can obtain all quantifier scopes in the
semantics.

The problem with non-local synchronization is that the weak language
preservation property does not hold.  \namecite{shieber:1994} shows that
not all {\nlstag} left-projection languages can be generated by TAGs.  As a
new result, in~\cite{rambow/satta:1996a} we show that the recognition of
some fixed left-projection languages of a {\nlstag} is NP-complete.  Our
reduction crucially relies on link inheritance.  This makes {\nlstag}
unattractive for applications in theoretical or computational linguistics.



\subsection{Local Synchronous Systems}

In contrast with non-local synchronization, in local synchronization there
is no inheritance of synchronization links.  This is enforced by requiring
that the links establish a bijection between nonterminals in the two
synchronously derived sentential forms, that is, each nonterminal must be
involved in exactly one link.  In this way, once a nonterminal is rewritten
through the application of a pair of rules to two linked nonterminals, no
additional link remains to be transferred to the newly introduced
nonterminals.  As a consequence of this, the derivation structures in the
left and right grammars are always isomorphic (up to ordering and labeling
of nodes).

\begin{figure}[htb]
\parbox{\columnwidth}{
{\bf Grammar}:\newline
\begin{small}
\begin{tabular}{ll}
S\framebox{{\tiny 1}} $\rightarrow$ NP\framebox{\tiny 2}
{\em likes} NP\framebox{\tiny 3} & S\framebox{\tiny 1}
$\rightarrow$ NP\framebox{\tiny 3} {\em pla{\^\i}t {\`a}}
NP\framebox{\tiny 2}\\
NP\framebox{\tiny  4} $\rightarrow$ {\em John} & NP\framebox{\tiny  4} $\rightarrow$ {\em Jean} \\
NP\framebox{\tiny  5} $\rightarrow$ {\em the white} N\framebox{\tiny  6} & NP\framebox{\tiny  5} $\rightarrow$ {\em la} N\framebox{\tiny  6} {\em
blanche} \\
N\framebox{\tiny 7} $\rightarrow$ {\em house} & N\framebox{\tiny 7} $\rightarrow$ {\em maison}
\end{tabular}
\end{small}
{\bf Derivation}:\newline
\begin{small}
(S\framebox{\tiny 0}, S\framebox{\tiny 0}) \\
\rule{.3cm}{0cm}$\Longrightarrow$(NP\framebox{\tiny 2} {\em likes} NP\framebox{\tiny 3}, NP\framebox{\tiny 3} {\em pla{\^\i}t {\`a}} NP\framebox{\tiny 2})\\
\rule{.3cm}{0cm}$\Longrightarrow$(NP\framebox{\tiny 2} {\em likes the white} N\framebox{\tiny 6}, {\em la} N\framebox{\tiny 6} {\em blanche pla{\^\i}t {\`a}} NP\framebox{\tiny 2})\\ 
\rule{.3cm}{0cm}$\deri$({\em John likes the white house}, {\em \rule{3mm}{0mm}la maison blanche pla{\^\i}t {\`a}
Jean}) 
\end{small}
}
\caption{Sample SDTS and derivation}
\label{fig-sdts}
\end{figure}



The canonical example of local synchronization is SDTS
\cite{aho/ullman:1969a}, in which two context-free grammars are
synchronized.  We give an example of an SDTS and a derivation in
\figref{fig-sdts}.  The links are indicated as boxed numbers to the right
of the nonterminal to which they apply.  \cite{shieber:1994} defines the
tree-rewriting version of SDTS, which we will call {\em synchronous TAG}
(\stag), and argues that {\stag} does not have the formal problems of
{\nlstag} (though \cite{shieber:1994} studies the translation problem
making the unappealing assumption that each tree in the input grammar is
associated with only one output grammar tree).

However, {\stag} cannot derive all possible scope orderings, because of the
locality restriction.  This can be shown by adapting the proof technique in
\cite{BRN:1992-short}.  In the following section, we will present a
synchronous system which has local synchronization's formal advantages, but
handles the scoping data.




\section{Extended Local Synchronization}

\label{sec-def}

In this section, we propose a new synchronous system, which is based on
local synchronization of unordered vector grammars with dominance links
(\uvd)~\cite{rambow:1994c}.  The presentations will be informal for reasons
of space; we refer to~\cite{rambow/satta:1996a} for details.  In \uvd ,
several context-free string rewriting rules are grouped into sets, called
{\em vectors}.  In a derivation, all or no rules from a given instance of a
vector must be used.  Put differently, all productions from a given vector
must be used the same number of times.  They can be applied in any order
and need not be applied simultaneously or one right after the other.  In
addition, \uvd\/ has {\em dominance links}.  An occurrence of a nonterminal
$A$ in the right-hand side of a rule $p$ can be linked to the left-hand
nonterminal of another rule $p'$ in the same vector.  This dominance link
will act as a constraint on derivations: if $p$ is used in a derivation,
then $p'$ must be used subsequently in the subderivation that starts with
the occurrence of $A$ introduced by $p$.  A {\uvd} is {\em lexicalized} iff
at least one production in every vector contains a terminal symbol.
Henceforth, all \uvd s mentioned in this paper will implicitly be assumed
to be lexicalized.  The derivation structure of a {\uvd} is just the
derivation structure of the same derivation in the underlying context-free
grammar (the CFG obtained by forming the union of all vectors).  We give an
example of a {\uvd} in \figref{fig-uvd-gram}, in which the dotted lines
represent the dominance links.  A sample derivation is in
\figref{fig-uvd-der}.

\begin{figure}[htb]
\centerline{
\psfig{figure=sem-gram.eps,scale=67}}
\caption{A UVG-DL for deriving semantic representations such as (2)}
\label{fig-uvd-gram}
\end{figure}

Our proposal for the synchronization of two UVG-DL uses the notion of
locality in synchronization, but with respect to entire vectors, not
individual productions in these vectors.  This approach, as we will see,
gives us both the desired empirical coverage and acceptable computational
and formal results.  We suppose that in each vector $v$ of a {\uvd} there
is exactly one privileged element, which we call the {\em synchronous
production} of $v$.  All other elements of $v$ are referred to as {\em
asynchronous productions}.  In Figures~\ref{fig-uvd-gram}
and~\ref{fig-uvd-der}, the synchronous productions are designated by a
bold-italic left-hand side symbol.  Furthermore, in the right-hand side of
each asynchronous production of $v$ we identify a single nonterminal,
called the {\em heir}.

In a {\em synchronous UVG-DL} (SynchUVG-DL), vectors from one \uvd\/ are
synchronized with vectors from another \uvd .  Two vectors are synchronized
by specifying a bijective synchronization mapping (as in local
synchronization) between the non-heir right-hand side occurrences of
nonterminals in the productions of the two vectors.  A nonterminal on which
a synchronization link impinges is referred to as a {\em synchronous
nonterminal}.  A sample {\suvd} grammar is shown in \figref{fig-suvd-gram}.


Informally speaking, during a SynchUVG-DL derivation, the two synchronous
productions in a pair of synchronized vectors must be applied at the same
time and must rewrite linked occurrences of nonterminals previously
introduced.  The asynchronous productions of the two synchronized grammars
are not subject to the synchronization requirement, and they can be applied
at any time and independently of the other grammar (but of course subject
to the grammar-specific dominance links).  Any synchronous links that
impinge on a nonterminal rewritten by an asynchronous production are
transferred to the heir of the asynchronous production.  (A production may
introduce a synchronous nonterminal whose counterpart in the other grammar
has not yet been introduced.  In this case, the link remains ``pending''.)
Thus, while in SynchUVG-DL there is link inheritance as in non-local
synchronization, link inheritance is only possible with those productions
that themselves are not subject to the synchronization requirement.

The locality of synchronization in SynchUVG-DL becomes clear when we
consider a new structure which we introduce here, called the {\em vector
derivation tree}.  Consider two synchronized \uvd derivations in a
SynchUVG-DL.  The vector derivation tree for either component derivation is
obtained as follows.  Each instance of a vector used in the derivation is
represented as a single node (which we label with that vector's lexeme).  A
node representing a vector $v_1$ is immediately dominated by the node
representing the vector $v_2$ which introduced the synchronization link
that the synchronous production of $v_1$ rewrites.  Unlike the standard
derivation tree for \uvd , the vector derivation tree clearly shows how the
vectors (rather than the component rules of the vectors) were combined
during the derivation.  The vector derivation tree for the derivation in
\figref{fig-uvd-der} is shown in \figref{fig-uvd-vecder}.


\begin{figure}[htb]
\centerline{
\psfig{figure=derivation.eps,scale=67}
}
\caption{Derivation of (2b) in a UVG-DL}
\label{fig-uvd-der}
\end{figure}



\begin{figure}[htb]
\centerline{
\psfig{figure=vector-deriv.eps,scale=67}
}
\caption{Vector derivation tree for derivation of (2b)}
\label{fig-uvd-vecder}
\end{figure}



It should be clear that the vector derivation trees for two
synchronized derivations are isomorphic, reflecting the fact that our
definition of SynchUVG-DL is local with respect to vectors (though not
with respect to productions, since the derivation trees of two
synchronized UVG-DL derivations need not be isomorphic).  The vector
derivation tree can be seen as representing an ``outline'' for the
derivation.  Such a view is attractive from a linguistic perspective:
if each vector represents a lexeme and its projection (where the
synchronous production is the basis of the lexical projection that the
vector represents), then the vector derivation tree is in fact the
dependency tree of the sentence (representing direct relations between
lexemes such as grammatical function).  In this respect, the vector
derivation tree of \uvd\/ is like the derivation tree of tree
adjoining grammar and of D-tree grammars (DTG)~\cite{RVW:1995a}, which is
not surprising, since all three formalisms share the same extended domain
of locality.  Furthermore, the vector derivation tree of SynchUVG-DL shares
with the the derivation tree of DTG the property that it reflects
linguistic dependency uniformly; however, while the definition of DTG was
motivated precisely from considerations of dependency, the vector
derivation tree is merely a by-product of our definition of SynchUVG-DL,
which was motivated from the desire to have a computationally tractable
model of synchronization more powerful than SynchTAG.%
\footnote{We do not discuss modifiers in this
paper for lack of space.}

\begin{figure}[tb]
\centerline{
\psfig{figure=suvd-gram-small.eps,scale=57}
}
\caption{{\suvd} grammar for quantifier scope disambiguation}
\label{fig-suvd-gram}
\end{figure}


\begin{figure}[htb]
\centerline{
\psfig{figure=suvd-der-1-2.eps,scale=57}
}
\caption{{\suvd} derivation, steps 1 and 2}
\label{fig-suvd-der2}
\end{figure}

\begin{figure}[hbt]
\centerline{
\psfig{figure=suvd-der3-small.eps,scale=57}
}
\caption{{\suvd} derivation, step 3}
\label{fig-suvd-der3}
\end{figure}



We briefly discuss a sample derivation.  We start with the two start
symbols, which are linked.  We then apply an asynchronous production from
the semantic grammar.  In \figref{fig-suvd-der2} (top) we see how the link is
inherited by the heir nonterminal of the applied production.  This step is
repeated with two more asynchronous productions, yielding
\figref{fig-suvd-der2} (bottom).  We now apply productions for the bodies of the
clauses, but stop short before the two synchronous productions for the {\em
arrive} clause, yielding \figref{fig-suvd-der3}.  We see the asynchronous
production of the syntactic {\em arrive} vector has not only inherited the
link to its heir nonterminal, but has introduced a link of its own.  Since
the semantic end of the link has not been introduced yet, the links remains
pending.  We then finish the derivation to obtain the
two trees in \figref{fig-syntax} and \figref{fig-semantics}, with no
synchronization or dominance links left.


\section{Formal results}

\label{sec-proofs}

\begin{theorem}
$\suvgd$ has the language preservation property. 
\end{theorem}

\olproof Let $G_s$ be a $\suvgd$, $G'$ and $G''$ its left and right $\uvgd$
components, respectively.  We construct a $\uvgd$ $G$ generating the
left-projection language of $G_s$.  $G$ uses all the nonterminal symbols of
$G'$ and $G''$, and some compound nonterminals of the form $[A,B]$, $A$ and
$B$ nonterminals of $G'$ and $G''$, respectively.  $G$ simulates $G_s$
derivations by intermixing symbols of $G'$ and symbols of $G''$, and
without generating any of the terminal symbols of $G''$.  Most important,
each pair of linked nonterminals generated by $G_s$ is represented by $G$
using a compound symbol.  This enforces the requirement of simultaneous
application of synchronous productions to linked nonterminals.

Each vector $v$ of $G$ is constructed from a pair of synchronous vectors
$(v',v'')$ of $G_s$ as follows.  First, all instances of nonterminals in
$v''$ are replaced by $\veps$.  Furthermore, for any instance $B$ of a
right-hand side nonterminal of $v''$ linked to a right-hand side
nonterminal $A$ of $v'$, $B$ is replaced by $\veps$ and $A$ by $[A,B]$.
Then the two synchronous productions in $v'$ and $v''$ are composed into a
single production in $v$, by composing the two left-hand sides in a
compound symbol and by concatenating the two right-hand sides.  Finally, to
simulate link inheritance in derivations of $G_s$, each asynchronous
production in $v'$ and $v''$ is transferred to $v$, either without any
change, or by composing with some nonterminal $C$ both its left-hand side
and the heir nonterminal in its right-hand side.  Note that there are
finitely many choices for the last step, and each choice gives a different
vector in $G$, simulating the application of $v'$ and $v''$ to a set of
(occurrences of) nonterminals in a particular link configuration in a
sentential form of $G_s$.~\closeproof

We now introduce a representation for sets of derivation trees in a $\uvgd$
$G$.  A {\em parse tree\/} in $G$ is an ordered tree representing a
derivation in $G$ and encoding at each node the production $p$ used to
start the corresponding subderivation and the multiset of productions $f$
used in that subderivation.  A {\em parse forest\/} in $G$ is a directed
acyclic graph which is ordered and bipartite.  (We use ideas originally
developed in~\cite{lang:1991} for the context-free case.)  Nodes of the
graph are of two different types, called {\em and-nodes\/} and {\em
or-nodes}, respectively, and each directed arc connects nodes of different
types.  A parse forest in $G$ represents a set $T$ of parse trees in $G$ if
the following holds.  When starting at a root node and walking through the
graph, if we follow exactly one of the outgoing arcs at each or-node, and
all of the outgoing arcs at each and-node, we obtain a tree in $T$ modulo
the removal of the or-nodes.
Furthermore, every tree in $T$ can be obtained in this way. 


\begin{lemma}
Let $G$ be a $\uvgd$ and let $q \geq 1$ be a natural number. 
The parse forest representing the set 
of all parse trees in $G$ with no more than 
$q$ vectors can be constructed in an amount of time 
bounded by a polynomial function of $q$.~\closeproof
\label{l:qforest}
\end{lemma}

Let $G_s$ be a $\suvgd$, $G'$ and $G''$ its left and
right $\uvgd$ components, respectively. 
For a parse tree $\tau$ in $G'$, we denote as 
$T(\tau)$ the set of all parse trees in $G''$ 
that are synchronous with $\tau$ according to $G_s$. 
The {\em parse-to-forest translation\/} problem for $G_s$ 
takes as input a parse tree $\tau$ in $G'$ and gives as output 
a parse forest representation for $T(\tau)$. 
If $G_s$ is lexicalized, such a parse forest has size bounded 
by a polynomial function of $\size{\tau}$, despite the fact that 
the size of $T(\tau)$ can be exponentially larger than the size
of $\tau$.  In fact, we have a stronger result. 

\begin{theorem}
The parse-to-forest translation problem for a lexicalized $\/\suvgd$ 
can be computed in polynomial time. 
\label{t:trans} 
\end{theorem} 

\olproof Let $G_s$ be a $\suvgd$ with $G'$ and $G''$ its left and right
$\uvgd$ components, respectively.  Let $\tau$ be a parse tree in $G'$ and
$\pi$ be the parse forest representing $T(\tau)$.  The construction of
$\pi$ consists of two stages.

In the first stage, we construct the vector derivation tree $\gamma$
associated with~$\tau$.  Let $q$ be the number of nodes of $\gamma$.  We
also construct a parse forest $\pi_q$ representing the set of all parse
trees in $G''$ with no more than $q$ vectors.  This stage takes polynomial
time in the size of $\tau$, since $\gamma$ can be constructed from $\tau$
in linear time and $\pi_q$ can be constructed as in Lemma~\ref{l:qforest}.

In the second stage, we remove from $\pi_q$ all the parse trees not in
$\pi$. This completes the construction, since the set of parse trees
represented by $\pi$ is included in the set of parse trees represented by
$\pi_q$.  Let $n_r$ and $\Gamma$ be the root node and the set of all nodes
of $\gamma$, respectively.  For $n \in \Gamma$, $\out(n)$ denotes the set
of all children of $n$.  We call {\em family\/} the set $\{n_r\}$ and any
nonempty subset of $\out(n)$, $n \in \Gamma$.  The main idea is to
associate a set of families ${\cal F}_n$ to each node $n$ of $\pi_q$, such
that the following condition is satisfied.  A family $F$ belongs to ${\cal
F}_n$ if and only if at least one subderivation in $G''$ represented at $n$
induces a forest of vector derivation trees whose root nodes are all and
only the nodes in $F$.  Each ${\cal F}_n$ can easily be computed visiting
$\pi_q$ in a bottom-up fashion.  Crucially, we ``block'' a node of $\pi_q$
if we fail in the construction of ${\cal F}_n$.  We claim that each set
${\cal F}_n$ has size bounded by the number of nodes in $\gamma$. This can
be shown using the fact that all derivation trees represented at a node of
$\pi_q$ employ the same multiset of productions of $G''$.  From the above
claim, it follows that $\pi_q$ can be processed in time polynomial in the
size of $\tau$.  Finally, we obtain $\pi$ simply by removing from $\pi_q$
all nodes that have been blocked.~\closeproof









\section{Conclusion}

We have presented {\suvd}, a synchronous system which has restricted
formal power, is computationally tractable, and which handles the
quantifier-raising data.  In addition, {\suvd} can be used for modeling the
syntax of languages with syntactic constructions which have been argued to
be beyond the formal power of TAG, such as scrambling in German and many
other languages \cite{rambow:1994c} or {\em wh}-movement in Kashmiri
\cite{RVW:1995a}.  {\suvd} can be used to synchronize a syntactic grammar
for these languages either with a semantic grammar, or with the syntactic
grammar of another language for machine translation applications.  However,
{\suvd} cannot handle the list of cases listed in \cite{shieber:1994}.
These pose a problem for {\suvd} for the same reason that they pose a
problem for other local synchronous systems: the (syntactic) dependency
structures represented by the two derivations are different.  These cases
remain an open research issue.

\section*{Acknowledgments}


Parts of the present research were done while Rambow was supported by the
North Atlantic Treaty Organization under a Grant awarded in 1993, while at
TALANA, Universit{\'e} Paris 7, and while Satta was visiting the Center for
Language and Speech Processing, Johns Hopkins University, Baltimore, MD.



\begin{thebibliography}{}

\bibitem[\protect\citename{Abeill\'{e}}1994]{abeille:1994a}
Abeill\'{e}, Anne.
\newblock 1994.
\newblock Syntax or semantics? {Handling} nonlocal dependencies with {MCTAGs}
  or {Synchronous} {TAGs}.
\newblock {\em Computational Intelligence}, 10(4):471--485.

\bibitem[\protect\citename{Abeill\'{e}, Schabes, and Joshi}1990]{ASJ:1990}
Abeill\'{e}, Anne, Yves Schabes, and Aravind Joshi.
\newblock 1990.
\newblock Using lexicalized {TAGs} for machine translation.
\newblock In {\em Proceedings of the 13th International Conference on
  Computational Linguistics (COLING'90)}, Helsinki. COLING-90.

\bibitem[\protect\citename{Aho and Ullman}1969]{aho/ullman:1969a}
Aho, A.~V. and J.~D. Ullman.
\newblock 1969.
\newblock Syntax directed translations and the pushdown assembler.
\newblock {\em J. Comput. Syst. Sci.}, 3(1):37--56.

\bibitem[\protect\citename{Aho and Ullman}1972]{aho/ullman:1972}
Aho, A.~V. and J.~D. Ullman.
\newblock 1972.
\newblock {\em The Theory of Parsing, Translation, and Compiling}.
\newblock Prentice Hall, Englewood Cliffs, NJ.

\bibitem[\protect\citename{Becker, Rambow, and Niv}1992]{BRN:1992-short}
Becker, Tilman, Owen Rambow, and Michael Niv.
\newblock 1992.
\newblock The derivational generative power, or, scrambling is beyond {LCFRS}.
\newblock Technical Report IRCS-92-38, Institute for Research in Cognitive
  Science, University of Pennsylvania.

\bibitem[\protect\citename{Bresnan and Kaplan}1982]{bresnan/kaplan:1982}
Bresnan, J. and R.~Kaplan.
\newblock 1982.
\newblock Lexical-functional grammar: A formal system for grammatical
  representation.
\newblock In J.~Bresnan, editor, {\em The Mental Representation of Grammatical
  Relations}. {MIT} {P}ress.

\bibitem[\protect\citename{Chomsky}1993]{chomsky:1993}
Chomsky, Noam.
\newblock 1993.
\newblock A minimalist program for linguistic theory.
\newblock In Kenneth Hale and Samuel~J. Keyser, editors, {\em The View from
  {B}uilding 20}. {MIT} {P}ress, Cambridge, Mass., pages 1--52.

\bibitem[\protect\citename{Egedi and Palmer}1994]{egedi/palmer:1994}
Egedi, Dana and Martha Palmer.
\newblock 1994.
\newblock Constraining lexical selection across languages using {TAG}.
\newblock In {\em 3$^e$ Colloque International sur les Grammaires d'Arbres
  Adjoints (TAG+3)}, Rapport Technique TALANA-RT-94-01. Universit{\'e} Paris 7.

\bibitem[\protect\citename{Gross}1989]{gross:1989a}
Gross, Maurice.
\newblock 1989.
\newblock The use of {Finite}-{State} {Automata} in the lexical representation
  of natural language.
\newblock In M.~Gross and D.~Perrin, editors, {\em Electronic Dictionaries and
  Automata in Computational Linguistics}. Springer.

\bibitem[\protect\citename{Harbusch and Poller}1994]{harbusch/poller:1994}
Harbusch, Karin and Peter Poller.
\newblock 1994.
\newblock Structural rewriting with synchronous rewriting systems.
\newblock In {\em 3$^e$ Colloque International sur les Grammaires d'Arbres
  Adjoints (TAG+3)}, Rapport Technique TALANA-RT-94-01. Universit{\'e} Paris 7.

\bibitem[\protect\citename{Kaplan and Kay}1994]{kaplan/kay:1994}
Kaplan, Ronald~M. and Martin Kay.
\newblock 1994.
\newblock Regular models of phonological rule systems.
\newblock {\em Computational Linguistics}, 20(3):331--378.

\bibitem[\protect\citename{Koskenniemi}1983]{koskenniemi:1983}
Koskenniemi, Kimmo.
\newblock 1983.
\newblock Two-level morphology: A general computational model for word-form
  recognition and production.
\newblock Technical Report~11, Department of General Linguistics, University of
  Helsinki.

\bibitem[\protect\citename{Lang}1991]{lang:1991}
Lang, B.
\newblock 1991.
\newblock Towards a uniform formal framework for parsing.
\newblock In M.~Tomita, editor, {\em Current Issues in Parsing technology}.
  Kluwer Academic Publishers, chapter~11, pages 153--171.

\bibitem[\protect\citename{May}1985]{may:1985}
May, Robert.
\newblock 1985.
\newblock {\em Logical Form: Its structure and Derivation}.
\newblock {MIT} {P}ress, Cambridge, Mass.

\bibitem[\protect\citename{Pereira}1991]{pereira:1991}
Pereira, Fernando.
\newblock 1991.
\newblock Finite-state approximation of phrase structure grammars.
\newblock In {\em 29th Meeting of the Association for Computational Linguistics
  (ACL'91)}, Berkeley, California. ACL.

\bibitem[\protect\citename{Pollard and Sag}1994]{pollard/sag:1994}
Pollard, Carl and Ivan Sag.
\newblock 1994.
\newblock {\em Head-Driven Phrase Structure Grammar}.
\newblock University of Chicago Press, Chicago.

\bibitem[\protect\citename{Prigent}1994]{prigent:1994}
Prigent, Gilles.
\newblock 1994.
\newblock Synchronous tags and machine translation.
\newblock In {\em 3$^e$ Colloque International sur les Grammaires d'Arbres
  Adjoints (TAG+3)}, Rapport Technique TALANA-RT-94-01. Universit{\'e} Paris 7.

\bibitem[\protect\citename{Rambow}1994]{rambow:1994c}
Rambow, Owen.
\newblock 1994.
\newblock Multiset-valued linear index grammars.
\newblock In {\em 32nd Meeting of the Association for Computational Linguistics
  (ACL'94)}. ACL.

\bibitem[\protect\citename{Rambow and Satta}1996]{rambow/satta:1996a}
Rambow, Owen and Giorgio Satta.
\newblock 1996.
\newblock Synchronous models of language.
\newblock Manuscript under preparation.

\bibitem[\protect\citename{Rambow, Vijay-Shanker, and Weir}1995]{RVW:1995a}
Rambow, Owen, K.~Vijay-Shanker, and David Weir.
\newblock 1995.
\newblock {D}-{Tree} {Grammars}.
\newblock In {\em 33rd Meeting of the Association for Computational Linguistics
  (ACL'95)}. ACL.

\bibitem[\protect\citename{Roche}1993]{roche:1993}
Roche, Emmanuel.
\newblock 1993.
\newblock {\em Analyse syntaxique transformationelle du fran{\c c}ais par
  transducteur et lexique-grammaire}.
\newblock {Ph.D.} thesis, Universit{\'e} Raris 7, Paris, France.

\bibitem[\protect\citename{Shieber and Schabes}1990]{shieber/schabes:1990a}
Shieber, Stuart and Yves Schabes.
\newblock 1990.
\newblock Synchronous tree adjoining grammars.
\newblock In {\em Proceedings of the 13th International Conference on
  Computational Linguistics}, Helsinki.

\bibitem[\protect\citename{Shieber and Schabes}1991]{shieber/schabes:1991}
Shieber, Stuart and Yves Schabes.
\newblock 1991.
\newblock Generation and synchronous tree adjoining grammars.
\newblock {\em Computational Intelligence}, 4(7):220--228.

\bibitem[\protect\citename{Shieber}1994]{shieber:1994}
Shieber, Stuart~B.
\newblock 1994.
\newblock Restricting the weak generative capacity of {Synchronous} {Tree}
  {Adjoining} {Grammar}.
\newblock {\em Computational Intelligence}, 10(4):371--385.

\bibitem[\protect\citename{Wu}1995]{wu:1995}
Wu, Dekai.
\newblock 1995.
\newblock An algorithm for simultaneously bracketing parallel texts by aligning
  words.
\newblock In {\em 33rd Meeting of the Association for Computational Linguistics
  (ACL'95)}. ACL.

\end{thebibliography}


\end{document}




% Psfig/TeX 
\def\PsfigVersion{1.9}
% dvips version
%
% All psfig/tex software, documentation, and related files
% in this distribution of psfig/tex are 
% Copyright 1987, 1988, 1991 Trevor J. Darrell
%
% Permission is granted for use and non-profit distribution of psfig/tex 
% providing that this notice is clearly maintained. The right to
% distribute any portion of psfig/tex for profit or as part of any commercial
% product is specifically reserved for the author(s) of that portion.
%
% *** Feel free to make local modifications of psfig as you wish,
% *** but DO NOT post any changed or modified versions of ``psfig''
% *** directly to the net. Send them to me and I'll try to incorporate
% *** them into future versions. If you want to take the psfig code 
% *** and make a new program (subject to the copyright above), distribute it, 
% *** (and maintain it) that's fine, just don't call it psfig.
%
% Bugs and improvements to trevor@media.mit.edu.
%
% Thanks to Greg Hager (GDH) and Ned Batchelder for their contributions
% to the original version of this project.
%
% Modified by J. Daniel Smith on 9 October 1990 to accept the
% %%BoundingBox: comment with or without a space after the colon.  Stole
% file reading code from Tom Rokicki's EPSF.TEX file (see below).
%
% More modifications by J. Daniel Smith on 29 March 1991 to allow the
% the included PostScript figure to be rotated.  The amount of
% rotation is specified by the "angle=" parameter of the \psfig command.
%
% Modified by Robert Russell on June 25, 1991 to allow users to specify
% .ps filenames which don't yet exist, provided they explicitly provide
% boundingbox information via the \psfig command. Note: This will only work
% if the "file=" parameter follows all four "bb???=" parameters in the
% command. This is due to the order in which psfig interprets these params.
%
%  3 Jul 1991   JDS     check if file already read in once
%  4 Sep 1991   JDS     fixed incorrect computation of rotated
%                       bounding box
% 25 Sep 1991   GVR     expanded synopsis of \psfig
% 14 Oct 1991   JDS     \fbox code from LaTeX so \psdraft works with TeX
%                       changed \typeout to \ps@typeout
% 17 Oct 1991   JDS     added \psscalefirst and \psrotatefirst
%

% From: gvr@cs.brown.edu (George V. Reilly)
%
% \psdraft      draws an outline box, but doesn't include the figure
%               in the DVI file.  Useful for previewing.
%
% \psfull       includes the figure in the DVI file (default).
%
% \psscalefirst width= or height= specifies the size of the figure
%               before rotation.
% \psrotatefirst (default) width= or height= specifies the size of the
%                figure after rotation.  Asymetric figures will
%                appear to shrink.
%
% \psfigurepath#1       sets the path to search for the figure
%
% \psfig
% usage: \psfig{file=, figure=, scale=, height=, width=,
%                       bbllx=, bblly=, bburx=, bbury=,
%                       rheight=, rwidth=, clip=, angle=, silent=}
%
%       "file" is the filename.  If no path name is specified and the
%               file is not found in the current directory,
%               it will be looked for in directory \psfigurepath.
%       "figure" is a synonym for "file".
%       If "scale" is specified, the figure is scaled by the (integer)
%               percentage.  scale is a convenient way to
%               specify identical width & height simultaneously.
%               It overwrites the height and width options.
%                       same size
%                       \psfig{figure=foo.ps,scale=100} 
%                       half the size 
%                       \psfig{figure=foo.ps,scale=50} 
%                       double size 
%                       \psfig{figure=foo.ps,scale=200} 
%       By default, the width and height of the figure are taken from
%               the BoundingBox of the figure.
%       If "width" is specified, the figure is scaled so that it has
%               the specified width.  Its height changes proportionately.
%       If "height" is specified, the figure is scaled so that it has
%               the specified height.  Its width changes proportionately.
%       If both "width" and "height" are specified, the figure is scaled
%               anamorphically.
%       "bbllx", "bblly", "bburx", and "bbury" control the PostScript
%               BoundingBox.  If these four values are specified
%               *before* the "file" option, the PSFIG will not try to
%               open the PostScript file.
%       "rheight" and "rwidth" are the reserved height and width
%               of the figure, i.e., how big TeX actually thinks
%               the figure is.  They default to "width" and "height".
%       The "clip" option ensures that no portion of the figure will
%               appear outside its BoundingBox.  "clip=" is a switch and
%               takes no value, but the `=' must be present.
%       The "angle" option specifies the angle of rotation (degrees, ccw).
%       The "silent" option makes \psfig work silently.
%

% check to see if macros already loaded in (maybe some other file says
% "\input psfig") ...
\ifx\undefined\psfig\else\endinput\fi

%
% from a suggestion by eijkhout@csrd.uiuc.edu to allow
% loading as a style file. Changed to avoid problems
% with amstex per suggestion by jbence@math.ucla.edu

\let\LaTeXAtSign=\@
\let\@=\relax
\edef\psfigRestoreAt{\catcode`\@=\number\catcode`@\relax}
%\edef\psfigRestoreAt{\catcode`@=\number\catcode`@\relax}
\catcode`\@=11\relax
\newwrite\@unused
\def\ps@typeout#1{{\let\protect\string\immediate\write\@unused{#1}}}
\ps@typeout{psfig/tex \PsfigVersion}

%% Here's how you define your figure path.  Should be set up with null
%% default and a user useable definition.

\def\figurepath{./}
\def\psfigurepath#1{\edef\figurepath{#1}}

%
% @psdo control structure -- similar to Latex @for.
% I redefined these with different names so that psfig can
% be used with TeX as well as LaTeX, and so that it will not 
% be vunerable to future changes in LaTeX's internal
% control structure,
%
\def\@nnil{\@nil}
\def\@empty{}
\def\@psdonoop#1\@@#2#3{}
\def\@psdo#1:=#2\do#3{\edef\@psdotmp{#2}\ifx\@psdotmp\@empty \else
    \expandafter\@psdoloop#2,\@nil,\@nil\@@#1{#3}\fi}
\def\@psdoloop#1,#2,#3\@@#4#5{\def#4{#1}\ifx #4\@nnil \else
       #5\def#4{#2}\ifx #4\@nnil \else#5\@ipsdoloop #3\@@#4{#5}\fi\fi}
\def\@ipsdoloop#1,#2\@@#3#4{\def#3{#1}\ifx #3\@nnil 
       \let\@nextwhile=\@psdonoop \else
      #4\relax\let\@nextwhile=\@ipsdoloop\fi\@nextwhile#2\@@#3{#4}}
\def\@tpsdo#1:=#2\do#3{\xdef\@psdotmp{#2}\ifx\@psdotmp\@empty \else
    \@tpsdoloop#2\@nil\@nil\@@#1{#3}\fi}
\def\@tpsdoloop#1#2\@@#3#4{\def#3{#1}\ifx #3\@nnil 
       \let\@nextwhile=\@psdonoop \else
      #4\relax\let\@nextwhile=\@tpsdoloop\fi\@nextwhile#2\@@#3{#4}}
% 
% \fbox is defined in latex.tex; so if \fbox is undefined, assume that
% we are not in LaTeX.
% Perhaps this could be done better???
\ifx\undefined\fbox
% \fbox code from modified slightly from LaTeX
\newdimen\fboxrule
\newdimen\fboxsep
\newdimen\ps@tempdima
\newbox\ps@tempboxa
\fboxsep = 3pt
\fboxrule = .4pt
\long\def\fbox#1{\leavevmode\setbox\ps@tempboxa\hbox{#1}\ps@tempdima\fboxrule
    \advance\ps@tempdima \fboxsep \advance\ps@tempdima \dp\ps@tempboxa
   \hbox{\lower \ps@tempdima\hbox
  {\vbox{\hrule height \fboxrule
          \hbox{\vrule width \fboxrule \hskip\fboxsep
          \vbox{\vskip\fboxsep \box\ps@tempboxa\vskip\fboxsep}\hskip 
                 \fboxsep\vrule width \fboxrule}
                 \hrule height \fboxrule}}}}
\fi
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% file reading stuff from epsf.tex
%   EPSF.TEX macro file:
%   Written by Tomas Rokicki of Radical Eye Software, 29 Mar 1989.
%   Revised by Don Knuth, 3 Jan 1990.
%   Revised by Tomas Rokicki to accept bounding boxes with no
%      space after the colon, 18 Jul 1990.
%   Portions modified/removed for use in PSFIG package by
%      J. Daniel Smith, 9 October 1990.
%
\newread\ps@stream
\newif\ifnot@eof       % continue looking for the bounding box?
\newif\if@noisy        % report what you're making?
\newif\if@atend        % %%BoundingBox: has (at end) specification
\newif\if@psfile       % does this look like a PostScript file?
%
% PostScript files should start with `%!'
%
{\catcode`\%=12\global\gdef\epsf@start{%!}}
\def\epsf@PS{PS}
%
\def\epsf@getbb#1{%
%
%   The first thing we need to do is to open the
%   PostScript file, if possible.
%
\openin\ps@stream=#1
\ifeof\ps@stream\ps@typeout{Error, File #1 not found}\else
%
%   Okay, we got it. Now we'll scan lines until we find one that doesn't
%   start with %. We're looking for the bounding box comment.
%
   {\not@eoftrue \chardef\other=12
    \def\do##1{\catcode`##1=\other}\dospecials \catcode`\ =10
    \loop
       \if@psfile
          \read\ps@stream to \epsf@fileline
       \else{
          \obeyspaces
          \read\ps@stream to \epsf@tmp\global\let\epsf@fileline\epsf@tmp}
       \fi
       \ifeof\ps@stream\not@eoffalse\else
%
%   Check the first line for `%!'.  Issue a warning message if its not
%   there, since the file might not be a PostScript file.
%
       \if@psfile\else
       \expandafter\epsf@test\epsf@fileline:. \\%
       \fi
%
%   We check to see if the first character is a % sign;
%   if so, we look further and stop only if the line begins with
%   `%%BoundingBox:' and the `(atend)' specification was not found.
%   That is, the only way to stop is when the end of file is reached,
%   or a `%%BoundingBox: llx lly urx ury' line is found.
%
          \expandafter\epsf@aux\epsf@fileline:. \\%
       \fi
   \ifnot@eof\repeat
   }\closein\ps@stream\fi}%
%
% This tests if the file we are reading looks like a PostScript file.
%
\long\def\epsf@test#1#2#3:#4\\{\def\epsf@testit{#1#2}
                        \ifx\epsf@testit\epsf@start\else
\ps@typeout{Warning! File does not start with `\epsf@start'.  It may not be a PostScript file.}
                        \fi
                        \@psfiletrue} % don't test after 1st line
%
%   We still need to define the tricky \epsf@aux macro. This requires
%   a couple of magic constants for comparison purposes.
%
{\catcode`\%=12\global\let\epsf@percent=%\global\def\epsf@bblit{%BoundingBox}}
%
%
%   So we're ready to check for `%BoundingBox:' and to grab the
%   values if they are found.  We continue searching if `(at end)'
%   was found after the `%BoundingBox:'.
%
\long\def\epsf@aux#1#2:#3\\{\ifx#1\epsf@percent
   \def\epsf@testit{#2}\ifx\epsf@testit\epsf@bblit
        \@atendfalse
        \epsf@atend #3 . \\%
        \if@atend       
           \if@verbose{
                \ps@typeout{psfig: found `(atend)'; continuing search}
           }\fi
        \else
        \epsf@grab #3 . . . \\%
        \not@eoffalse
        \global\no@bbfalse
        \fi
   \fi\fi}%
%
%   Here we grab the values and stuff them in the appropriate definitions.
%
\def\epsf@grab #1 #2 #3 #4 #5\\{%
   \global\def\epsf@llx{#1}\ifx\epsf@llx\empty
      \epsf@grab #2 #3 #4 #5 .\\\else
   \global\def\epsf@lly{#2}%
   \global\def\epsf@urx{#3}\global\def\epsf@ury{#4}\fi}%
%
% Determine if the stuff following the %%BoundingBox is `(atend)'
% J. Daniel Smith.  Copied from \epsf@grab above.
%
\def\epsf@atendlit{(atend)} 
\def\epsf@atend #1 #2 #3\\{%
   \def\epsf@tmp{#1}\ifx\epsf@tmp\empty
      \epsf@atend #2 #3 .\\\else
   \ifx\epsf@tmp\epsf@atendlit\@atendtrue\fi\fi}


% End of file reading stuff from epsf.tex
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% trigonometry stuff from "trig.tex"
\chardef\psletter = 11 % won't conflict with \begin{letter} now...
\chardef\other = 12

\newif \ifdebug %%% turn me on to see TeX hard at work ...
\newif\ifc@mpute %%% don't need to compute some values
\c@mputetrue % but assume that we do

\let\then = \relax
\def\r@dian{pt }
\let\r@dians = \r@dian
\let\dimensionless@nit = \r@dian
\let\dimensionless@nits = \dimensionless@nit
\def\internal@nit{sp }
\let\internal@nits = \internal@nit
\newif\ifstillc@nverging
\def \Mess@ge #1{\ifdebug \then \message {#1} \fi}

{ %%% Things that need abnormal catcodes %%%
        \catcode `\@ = \psletter
        \gdef \nodimen {\expandafter \n@dimen \the \dimen}
        \gdef \term #1 #2 #3%
               {\edef \t@ {\the #1}%%% freeze parameter 1 (count, by value)
                \edef \t@@ {\expandafter \n@dimen \the #2\r@dian}%
                                   %%% freeze parameter 2 (dimen, by value)
                \t@rm {\t@} {\t@@} {#3}%
               }
        \gdef \t@rm #1 #2 #3%
               {{%
                \count 0 = 0
                \dimen 0 = 1 \dimensionless@nit
                \dimen 2 = #2\relax
                \Mess@ge {Calculating term #1 of \nodimen 2}%
                \loop
                \ifnum  \count 0 < #1
                \then   \advance \count 0 by 1
                        \Mess@ge {Iteration \the \count 0 \space}%
                        \Multiply \dimen 0 by {\dimen 2}%
                        \Mess@ge {After multiplication, term = \nodimen 0}%
                        \Divide \dimen 0 by {\count 0}%
                        \Mess@ge {After division, term = \nodimen 0}%
                \repeat
                \Mess@ge {Final value for term #1 of 
                                \nodimen 2 \space is \nodimen 0}%
                \xdef \Term {#3 = \nodimen 0 \r@dians}%
                \aftergroup \Term
               }}
        \catcode `\p = \other
        \catcode `\t = \other
        \gdef \n@dimen #1pt{#1} %%% throw away the ``pt''
}

\def \Divide #1by #2{\divide #1 by #2} %%% just a synonym

\def \Multiply #1by #2%%% allows division of a dimen by a dimen
       {{%%% should really freeze parameter 2 (dimen, passed by value)
        \count 0 = #1\relax
        \count 2 = #2\relax
        \count 4 = 65536
        \Mess@ge {Before scaling, count 0 = \the \count 0 \space and
                        count 2 = \the \count 2}%
        \ifnum  \count 0 > 32767 %%% do our best to avoid overflow
        \then   \divide \count 0 by 4
                \divide \count 4 by 4
        \else   \ifnum  \count 0 < -32767
                \then   \divide \count 0 by 4
                        \divide \count 4 by 4
                \else
                \fi
        \fi
        \ifnum  \count 2 > 32767 %%% while retaining reasonable accuracy
        \then   \divide \count 2 by 4
                \divide \count 4 by 4
        \else   \ifnum  \count 2 < -32767
                \then   \divide \count 2 by 4
                        \divide \count 4 by 4
                \else
                \fi
        \fi
        \multiply \count 0 by \count 2
        \divide \count 0 by \count 4
        \xdef \product {#1 = \the \count 0 \internal@nits}%
        \aftergroup \product
       }}

\def\r@duce{\ifdim\dimen0 > 90\r@dian \then   % sin(x+90) = sin(180-x)
                \multiply\dimen0 by -1
                \advance\dimen0 by 180\r@dian
                \r@duce
            \else \ifdim\dimen0 < -90\r@dian \then  % sin(-x) = sin(360+x)
                \advance\dimen0 by 360\r@dian
                \r@duce
                \fi
            \fi}

\def\Sine#1%
       {{%
        \dimen 0 = #1 \r@dian
        \r@duce
        \ifdim\dimen0 = -90\r@dian \then
           \dimen4 = -1\r@dian
           \c@mputefalse
        \fi
        \ifdim\dimen0 = 90\r@dian \then
           \dimen4 = 1\r@dian
           \c@mputefalse
        \fi
        \ifdim\dimen0 = 0\r@dian \then
           \dimen4 = 0\r@dian
           \c@mputefalse
        \fi
%
        \ifc@mpute \then
                % convert degrees to radians
                \divide\dimen0 by 180
                \dimen0=3.141592654\dimen0
%
                \dimen 2 = 3.1415926535897963\r@dian %%% a well-known constant
                \divide\dimen 2 by 2 %%% we only deal with -pi/2 : pi/2
                \Mess@ge {Sin: calculating Sin of \nodimen 0}%
                \count 0 = 1 %%% see power-series expansion for sine
                \dimen 2 = 1 \r@dian %%% ditto
                \dimen 4 = 0 \r@dian %%% ditto
                \loop
                        \ifnum  \dimen 2 = 0 %%% then we've done
                        \then   \stillc@nvergingfalse 
                        \else   \stillc@nvergingtrue
                        \fi
                        \ifstillc@nverging %%% then calculate next term
                        \then   \term {\count 0} {\dimen 0} {\dimen 2}%
                                \advance \count 0 by 2
                                \count 2 = \count 0
                                \divide \count 2 by 2
                                \ifodd  \count 2 %%% signs alternate
                                \then   \advance \dimen 4 by \dimen 2
                                \else   \advance \dimen 4 by -\dimen 2
                                \fi
                \repeat
        \fi             
                        \xdef \sine {\nodimen 4}%
       }}

% Now the Cosine can be calculated easily by calling \Sine
\def\Cosine#1{\ifx\sine\UnDefined\edef\Savesine{\relax}\else
                             \edef\Savesine{\sine}\fi
        {\dimen0=#1\r@dian\advance\dimen0 by 90\r@dian
         \Sine{\nodimen 0}
         \xdef\cosine{\sine}
         \xdef\sine{\Savesine}}}              
% end of trig stuff
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\def\psdraft{
        \def\@psdraft{0}
        %\ps@typeout{draft level now is \@psdraft \space . }
}
\def\psfull{
        \def\@psdraft{100}
        %\ps@typeout{draft level now is \@psdraft \space . }
}

\psfull

\newif\if@scalefirst
\def\psscalefirst{\@scalefirsttrue}
\def\psrotatefirst{\@scalefirstfalse}
\psrotatefirst

\newif\if@draftbox
\def\psnodraftbox{
        \@draftboxfalse
}
\def\psdraftbox{
        \@draftboxtrue
}
\@draftboxtrue

\newif\if@prologfile
\newif\if@postlogfile
\def\pssilent{
        \@noisyfalse
}
\def\psnoisy{
        \@noisytrue
}
\psnoisy
%%% These are for the option list.
%%% A specification of the form a = b maps to calling \@p@@sa{b}
\newif\if@bbllx
\newif\if@bblly
\newif\if@bburx
\newif\if@bbury
\newif\if@height
\newif\if@width
\newif\if@scale
\newif\if@rheight
\newif\if@rwidth
\newif\if@angle
\newif\if@clip
\newif\if@verbose
\def\@p@@sclip#1{\@cliptrue}


\newif\if@decmpr

%%% GDH 7/26/87 -- changed so that it first looks in the local directory,
%%% then in a specified global directory for the ps file.
%%% RPR 6/25/91 -- changed so that it defaults to user-supplied name if
%%% boundingbox info is specified, assuming graphic will be created by
%%% print time.
%%% TJD 10/19/91 -- added bbfile vs. file distinction, and @decmpr flag

\def\@p@@sfigure#1{\def\@p@sfile{null}\def\@p@sbbfile{null}
                \openin1=#1.bb
                \ifeof1\closein1
                        \openin1=\figurepath#1.bb
                        \ifeof1\closein1
                                \openin1=#1
                                \ifeof1\closein1%
                                       \openin1=\figurepath#1
                                        \ifeof1
                                           \ps@typeout{Error, File #1 not found}
                                                \if@bbllx\if@bblly
                                                \if@bburx\if@bbury
                                                        \def\@p@sfile{#1}%
                                                        \def\@p@sbbfile{#1}%
                                                        \@decmprfalse
                                                \fi\fi\fi\fi
                                        \else\closein1
                                                \def\@p@sfile{\figurepath#1}%
                                                \def\@p@sbbfile{\figurepath#1}%
                                                \@decmprfalse
                                        \fi%
                                \else\closein1%
                                        \def\@p@sfile{#1}
                                        \def\@p@sbbfile{#1}
                                        \@decmprfalse
                                \fi
                        \else
                                \def\@p@sfile{\figurepath#1}
                                \def\@p@sbbfile{\figurepath#1.bb}
                                \@decmprtrue
                        \fi
                \else
                        \def\@p@sfile{#1}
                        \def\@p@sbbfile{#1.bb}
                        \@decmprtrue
                \fi}

\def\@p@@sfile#1{\@p@@sfigure{#1}}

\def\@p@@sbbllx#1{
                %\ps@typeout{bbllx is #1}
                \@bbllxtrue
                \dimen100=#1
                \edef\@p@sbbllx{\number\dimen100}
}
\def\@p@@sbblly#1{
                %\ps@typeout{bblly is #1}
                \@bbllytrue
                \dimen100=#1
                \edef\@p@sbblly{\number\dimen100}
}
\def\@p@@sbburx#1{
                %\ps@typeout{bburx is #1}
                \@bburxtrue
                \dimen100=#1
                \edef\@p@sbburx{\number\dimen100}
}
\def\@p@@sbbury#1{
                %\ps@typeout{bbury is #1}
                \@bburytrue
                \dimen100=#1
                \edef\@p@sbbury{\number\dimen100}
}
\def\@p@@sscale#1{
                \@scaletrue
                \count255=#1
                \edef\@p@sscale{\number\count255}
                %\typeout{Scale is \@p@sscale}
}
\def\@p@@sheight#1{
                \@heighttrue
                \dimen100=#1
                \edef\@p@sheight{\number\dimen100}
                %\ps@typeout{Height is \@p@sheight}
}
\def\@p@@swidth#1{
                %\ps@typeout{Width is #1}
                \@widthtrue
                \dimen100=#1
                \edef\@p@swidth{\number\dimen100}
}
\def\@p@@srheight#1{
                %\ps@typeout{Reserved height is #1}
                \@rheighttrue
                \dimen100=#1
                \edef\@p@srheight{\number\dimen100}
}
\def\@p@@srwidth#1{
                %\ps@typeout{Reserved width is #1}
                \@rwidthtrue
                \dimen100=#1
                \edef\@p@srwidth{\number\dimen100}
}
\def\@p@@sangle#1{
                %\ps@typeout{Rotation is #1}
                \@angletrue
%               \dimen100=#1
                \edef\@p@sangle{#1} %\number\dimen100}
}
\def\@p@@ssilent#1{ 
                \@verbosefalse
}
\def\@p@@sprolog#1{\@prologfiletrue\def\@prologfileval{#1}}
\def\@p@@spostlog#1{\@postlogfiletrue\def\@postlogfileval{#1}}
\def\@cs@name#1{\csname #1\endcsname}
\def\@setparms#1=#2,{\@cs@name{@p@@s#1}{#2}}
%
% initialize the defaults (size the size of the figure)
%
\def\ps@init@parms{
                \@bbllxfalse \@bbllyfalse
                \@bburxfalse \@bburyfalse
                \@heightfalse \@widthfalse
                \@scalefalse
                \@rheightfalse \@rwidthfalse
                \def\@p@sbbllx{}\def\@p@sbblly{}
                \def\@p@sbburx{}\def\@p@sbbury{}
                \def\@p@sheight{}\def\@p@swidth{}
                \def\@p@sscale{}
                \def\@p@srheight{}\def\@p@srwidth{}
                \def\@p@sangle{0}
                \def\@p@sfile{} \def\@p@sbbfile{}
                \def\@p@scost{10}
                \def\@sc{}
                \@prologfilefalse
                \@postlogfilefalse
                \@clipfalse
                \if@noisy
                        \@verbosetrue
                \else
                        \@verbosefalse
                \fi
}
%
% Go through the options setting things up.
%
\def\parse@ps@parms#1{
                \@psdo\@psfiga:=#1\do
                   {\expandafter\@setparms\@psfiga,}}
%
% Compute bb height and width
%
\newif\ifno@bb
\def\bb@missing{
        \if@verbose{
                \ps@typeout{psfig: searching \@p@sbbfile \space  for bounding box}
        }\fi
        \no@bbtrue
        \epsf@getbb{\@p@sbbfile}
        \ifno@bb \else \bb@cull\epsf@llx\epsf@lly\epsf@urx\epsf@ury\fi
}       
\def\bb@cull#1#2#3#4{
        \dimen100=#1 bp\edef\@p@sbbllx{\number\dimen100}
        \dimen100=#2 bp\edef\@p@sbblly{\number\dimen100}
        \dimen100=#3 bp\edef\@p@sbburx{\number\dimen100}
        \dimen100=#4 bp\edef\@p@sbbury{\number\dimen100}
        \no@bbfalse
}
% rotate point (#1,#2) about (0,0).
% The sine and cosine of the angle are already stored in \sine and
% \cosine.  The result is placed in (\p@intvaluex, \p@intvaluey).
\newdimen\p@intvaluex
\newdimen\p@intvaluey
\def\rotate@#1#2{{\dimen0=#1 sp\dimen1=#2 sp
%               calculate x' = x \cos\theta - y \sin\theta
                  \global\p@intvaluex=\cosine\dimen0
                  \dimen3=\sine\dimen1
                  \global\advance\p@intvaluex by -\dimen3
%               calculate y' = x \sin\theta + y \cos\theta
                  \global\p@intvaluey=\sine\dimen0
                  \dimen3=\cosine\dimen1
                  \global\advance\p@intvaluey by \dimen3
                  }}
\def\compute@bb{
                \no@bbfalse
                \if@bbllx \else \no@bbtrue \fi
                \if@bblly \else \no@bbtrue \fi
                \if@bburx \else \no@bbtrue \fi
                \if@bbury \else \no@bbtrue \fi
                \ifno@bb \bb@missing \fi
                \ifno@bb \ps@typeout{FATAL ERROR: no bb supplied or found}
                        \no-bb-error
                \fi
                %
%\ps@typeout{BB: \@p@sbbllx, \@p@sbblly, \@p@sbburx, \@p@sbbury} 
%
% store height/width of original (unrotated) bounding box
                \count203=\@p@sbburx
                \count204=\@p@sbbury
                \advance\count203 by -\@p@sbbllx
                \advance\count204 by -\@p@sbblly
                \edef\ps@bbw{\number\count203}
                \edef\ps@bbh{\number\count204}
                %\ps@typeout{ psbbh = \ps@bbh, psbbw = \ps@bbw }
                \if@angle 
                        \Sine{\@p@sangle}\Cosine{\@p@sangle}
                        {\dimen100=\maxdimen\xdef\r@p@sbbllx{\number\dimen100}
                                            \xdef\r@p@sbblly{\number\dimen100}
                                            \xdef\r@p@sbburx{-\number\dimen100}
                                            \xdef\r@p@sbbury{-\number\dimen100}}
%
% Need to rotate all four points and take the X-Y extremes of the new
% points as the new bounding box.
                        \def\minmaxtest{
                           \ifnum\number\p@intvaluex<\r@p@sbbllx
                              \xdef\r@p@sbbllx{\number\p@intvaluex}\fi
                           \ifnum\number\p@intvaluex>\r@p@sbburx
                              \xdef\r@p@sbburx{\number\p@intvaluex}\fi
                           \ifnum\number\p@intvaluey<\r@p@sbblly
                              \xdef\r@p@sbblly{\number\p@intvaluey}\fi
                           \ifnum\number\p@intvaluey>\r@p@sbbury
                              \xdef\r@p@sbbury{\number\p@intvaluey}\fi
                           }
%                       lower left
                        \rotate@{\@p@sbbllx}{\@p@sbblly}
                        \minmaxtest
%                       upper left
                        \rotate@{\@p@sbbllx}{\@p@sbbury}
                        \minmaxtest
%                       lower right
                        \rotate@{\@p@sbburx}{\@p@sbblly}
                        \minmaxtest
%                       upper right
                        \rotate@{\@p@sbburx}{\@p@sbbury}
                        \minmaxtest
                        \edef\@p@sbbllx{\r@p@sbbllx}\edef\@p@sbblly{\r@p@sbblly}
                        \edef\@p@sbburx{\r@p@sbburx}\edef\@p@sbbury{\r@p@sbbury}
%\ps@typeout{rotated BB: \r@p@sbbllx, \r@p@sbblly, \r@p@sbburx, \r@p@sbbury}
                \fi
                \count203=\@p@sbburx
                \count204=\@p@sbbury
                \advance\count203 by -\@p@sbbllx
                \advance\count204 by -\@p@sbblly
                \edef\@bbw{\number\count203}
                \edef\@bbh{\number\count204}
                %\ps@typeout{ bbh = \@bbh, bbw = \@bbw }
}
%
% \in@hundreds performs #1 * (#2 / #3) correct to the hundreds,
%       then leaves the result in @result
%
\def\in@hundreds#1#2#3{\count240=#2 \count241=#3
                     \count100=\count240        % 100 is first digit #2/#3
                     \divide\count100 by \count241
                     \count101=\count100
                     \multiply\count101 by \count241
                     \advance\count240 by -\count101
                     \multiply\count240 by 10
                     \count101=\count240        %101 is second digit of #2/#3
                     \divide\count101 by \count241
                     \count102=\count101
                     \multiply\count102 by \count241
                     \advance\count240 by -\count102
                     \multiply\count240 by 10
                     \count102=\count240        % 102 is the third digit
                     \divide\count102 by \count241
                     \count200=#1\count205=0
                     \count201=\count200
                        \multiply\count201 by \count100
                        \advance\count205 by \count201
                     \count201=\count200
                        \divide\count201 by 10
                        \multiply\count201 by \count101
                        \advance\count205 by \count201
                        %
                     \count201=\count200
                        \divide\count201 by 100
                        \multiply\count201 by \count102
                        \advance\count205 by \count201
                        %
                     \edef\@result{\number\count205}
}
\def\compute@wfromh{
                % computing : width = height * (bbw / bbh)
                \in@hundreds{\@p@sheight}{\@bbw}{\@bbh}
                %\ps@typeout{ \@p@sheight * \@bbw / \@bbh, = \@result }
                \edef\@p@swidth{\@result}
                %\ps@typeout{w from h: width is \@p@swidth}
}
\def\compute@hfromw{
                % computing : height = width * (bbh / bbw)
                \in@hundreds{\@p@swidth}{\@bbh}{\@bbw}
                %\ps@typeout{ \@p@swidth * \@bbh / \@bbw = \@result }
                \edef\@p@sheight{\@result}
                %\ps@typeout{h from w : height is \@p@sheight}
}
%% yves
\def\compute@wfroms{
                %\typeout{computewfroms: scale is \@p@sscale}   
                % computing : width = scale * (bbw / 100)
                \in@hundreds{\@p@sscale}{\@bbw}{100}
                %\typeout{ \@p@sscale * \@bbw / 100, = \@result }
                \edef\@p@swidth{\@result}
                %\typeout{w from s: width is \@p@swidth}
}
\def\compute@hfroms{
                %\typeout{computehfroms: scale is \@p@sscale}   
                % computing : height = scale * (bbh / 100)
                \in@hundreds{\@p@sscale}{\@bbh}{100}
                %\typeout{ \@p@sscale * \@bbh / 100 = \@result }
                \edef\@p@sheight{\@result}
                %\typeout{h from s : height is \@p@sheight}
}
\def\compute@handw{
                \if@scale
%                       \edef\@p@sheight{\@bbh}
%                       \edef\@p@swidth{\@bbw}
                        \compute@wfroms
                        \compute@hfroms
                \else
                        \if@height 
                                \if@width
                                \else
                                        \compute@wfromh
                                \fi     
                        \else 
                                \if@width
                                        \compute@hfromw
                                \else
                                        \edef\@p@sheight{\@bbh}
                                        \edef\@p@swidth{\@bbw}
                                \fi
                        \fi
                \fi
}
%% finish
\def\compute@resv{
                \if@rheight \else \edef\@p@srheight{\@p@sheight} \fi
                \if@rwidth \else \edef\@p@srwidth{\@p@swidth} \fi
                %\ps@typeout{rheight = \@p@srheight, rwidth = \@p@srwidth}
}
%               
% Compute any missing values
\def\compute@sizes{
        \compute@bb
        \if@scalefirst\if@angle
% at this point the bounding box has been adjsuted correctly for
% rotation.  PSFIG does all of its scaling using \@bbh and \@bbw.  If
% a width= or height= was specified along with \psscalefirst, then the
% width=/height= value needs to be adjusted to match the new (rotated)
% bounding box size (specifed in \@bbw and \@bbh).
%    \ps@bbw       width=
%    -------  =  ---------- 
%    \@bbw       new width=
% so `new width=' = (width= * \@bbw) / \ps@bbw; where \ps@bbw is the
% width of the original (unrotated) bounding box.
        \if@width
           \in@hundreds{\@p@swidth}{\@bbw}{\ps@bbw}
           \edef\@p@swidth{\@result}
        \fi
        \if@height
           \in@hundreds{\@p@sheight}{\@bbh}{\ps@bbh}
           \edef\@p@sheight{\@result}
        \fi
        \fi\fi
        \compute@handw
        \compute@resv}

%
% \psfig
% usage : \psfig{file=, height=, width=, bbllx=, bblly=, bburx=, bbury=,
%                       rheight=, rwidth=, clip=}
%
% "clip=" is a switch and takes no value, but the `=' must be present.
\def\psfig#1{\vbox {
        % do a zero width hard space so that a single
        % \psfig in a centering enviornment will behave nicely
        %{\setbox0=\hbox{\ }\ \hskip-\wd0}
        %
        \ps@init@parms
        \parse@ps@parms{#1}
        \compute@sizes
        %
        \ifnum\@p@scost<\@psdraft{
                %
                \special{ps::[begin]    \@p@swidth \space \@p@sheight \space
                                \@p@sbbllx \space \@p@sbblly \space
                                \@p@sbburx \space \@p@sbbury \space
                                startTexFig \space }
                \if@angle
                        \special {ps:: \@p@sangle \space rotate \space} 
                \fi
                \if@clip{
                        \if@verbose{
                                \ps@typeout{(clip)}
                        }\fi
                        \special{ps:: doclip \space }
                }\fi
                \if@prologfile
                    \special{ps: plotfile \@prologfileval \space } \fi
                \if@decmpr{
                        \if@verbose{
                                \ps@typeout{psfig: including \@p@sfile.Z \space }
                        }\fi
                        \special{ps: plotfile "`zcat \@p@sfile.Z" \space }
                }\else{
                        \if@verbose{
                                \ps@typeout{psfig: including \@p@sfile \space }
                        }\fi
                        \special{ps: plotfile \@p@sfile \space }
                }\fi
                \if@postlogfile
                    \special{ps: plotfile \@postlogfileval \space } \fi
                \special{ps::[end] endTexFig \space }
                % Create the vbox to reserve the space for the figure.
                \vbox to \@p@srheight sp{
                % 1/92 TJD Changed from "true sp" to "sp" for magnification.
                        \hbox to \@p@srwidth sp{
                                \hss
                        }
                \vss
                }
        }\else{
                % draft figure, just reserve the space and print the
                % path name.
                \if@draftbox{           
                        % Verbose draft: print file name in box
                        \hbox{\frame{\vbox to \@p@srheight sp{
                        \vss
                        \hbox to \@p@srwidth sp{ \hss \@p@sfile \hss }
                        \vss
                        }}}
                }\else{
                        % Non-verbose draft
                        \vbox to \@p@srheight sp{
                        \vss
                        \hbox to \@p@srwidth sp{\hss}
                        \vss
                        }
                }\fi    



        }\fi
}}
\psfigRestoreAt
\let\@=\LaTeXAtSign