diff --git a/Development/AIseedGrant/AIseed.bib b/Development/AIseedGrant/AIseed.bib new file mode 100644 index 0000000..e9f14a7 --- /dev/null +++ b/Development/AIseedGrant/AIseed.bib @@ -0,0 +1,118 @@ +@article{MALIAR202176, + title = {Deep learning for solving dynamic economic models.}, + journal = {Journal of Monetary Economics}, + volume = {122}, + pages = {76-101}, + year = {2021}, + issn = {0304-3932}, + doi = {https://doi.org/10.1016/j.jmoneco.2021.07.004}, + url = {https://www.sciencedirect.com/science/article/pii/S0304393221000799}, + author = {Lilia Maliar and Serguei Maliar and Pablo Winant}, + keywords = {Artificial intelligence, Machine learning, Deep learning, Neural network, Stochastic gradient, Dynamic models, Model reduction, Dynamic programming, Bellman equation, Euler equation, Value functio}, + abstract = {We introduce a unified deep learning method that solves dynamic economic models by casting them into nonlinear regression equations. We derive such equations for three fundamental objects of economic dynamics – lifetime reward functions, Bellman equations and Euler equations. We estimate the decision functions on simulated data using a stochastic gradient descent method. We introduce an all-in-one integration operator that facilitates approximation of high-dimensional integrals. We use neural networks to perform model reduction and to handle multicollinearity. Our deep learning method is tractable in large-scale problems, e.g., Krusell and Smith (1998). We provide a TensorFlow code that accommodates a variety of applications.} +} + +@article{KrusellSmith, + author = {Krusell, Per and Smith, Jr., Anthony A.}, + title = {Income and Wealth Heterogeneity in the Macroeconomy}, + journal = {Journal of Political Economy}, + volume = {106}, + number = {5}, + pages = {867-896}, + year = {1998}, + doi = {10.1086/250034}, + abstract = { How do movements in the distribution of income and wealth affect the macroeconomy? We analyze this question using a calibrated version of the stochastic growth model with partially uninsurable idiosyncratic risk and movements in aggregate productivity. Our main finding is that, in the stationary stochastic equilibrium, the behavior of the macroeconomic aggregates can be almost perfectly described using only the mean of the wealth distribution. This result is robust to substantial changes in both parameter values and model specification. Our benchmark model, whose only difference from the representative‐agent framework is the existence of uninsurable idiosyncratic risk, displays far less cross‐sectional dispersion and skewness in wealth than U.S. data. However, an extension that relies on a small amount of heterogeneity in thrift does succeed in replicating the key features of the wealth data. Furthermore, this extension features aggregate time series that depart significantly from permanent income behavior. } +} + +@article{cAndCwithStickyE, + Author = {Carroll, Christopher D. and Crawley, Edmund and Slacalek, Jiri and Tokuoka, Kiichi and White, Matthew N.}, + Title = {Sticky Expectations and Consumption Dynamics}, + Journal = {American Economic Journal: Macroeconomics}, + Volume = {12}, + Number = {3}, + Year = {2020}, + Month = {July}, + Pages = {40–76}, + DOI = {10.1257/mac.20180286}, + URL = {https://www.aeaweb.org/articles?id=10.1257/mac.20180286} +} + +@periodical{JEDCspecial, + editor = {Den Haan, Wouter}, + year = {2010}, + title = {Journal of Economic Dynamics and Control}, + issuetitle = {Computational Suite of Models with Heterogeneous Agents: Incomplete Markets and Aggregate Uncertainty}, + volume = {34}, + number = {1}, + url = {https://www.sciencedirect.com/journal/journal-of-economic-dynamics-and-control/vol/34/issue/1}, +} + +@article{FiveGuys, + author = {Ahn, SeHyoun and Kaplan, Greg and Moll, Benjamin and Winberry, Thomas and Wolf, Christian}, + title = {When Inequality Matters for Macro and Macro Matters for Inequality}, + journal = {NBER Macroeconomics Annual}, + volume = {32}, + number = {}, + pages = {1-75}, + year = {2018}, + doi = {10.1086/696046}, + , + abstract = { We develop an efficient and easy to use computational method for solving a wide class of general equilibrium heterogeneous agent models with aggregate shocks together with an open source suite of codes that implement our algorithms in an easy to use toolbox. Our method extends standard linearization techniques and is designed to work in cases when inequality matters for the dynamics of macroeconomic aggregates. We present two applications that analyze a two asset incomplete markets model parameterized to match the distribution of income, wealth, and marginal propensities to consume. First, we show that our model is consistent with two key features of aggregate consumption dynamics that are difficult to match with representative agent models: (1) the sensitivity of aggregate consumption to predictable changes in aggregate income, and (2) the relative smoothness of aggregate consumption. Second, we extend the model to feature capital-skill complementarity and show how factor-specific productivity shocks shape dynamics of income and consumption inequality. } +} + +@misc{Reiter2010, + number = {258}, + address = {Wien}, + title = {Approximate and Almost-Exact Aggregation in Dynamic Stochastic Heterogeneous-Agent Models}, + year = {2010}, + series = {Economics Series}, + publisher = {Institut f{\"u}r H{\"o}here Studien}, + editor = {Robert M. Kunst and Walter Fisher and Klaus Ritzberger}, + month = {October}, + keywords = {'Heterogeneous agents' 'Aggregation' 'Model reduction'}, + isbn = {1605-7996}, + author = {Reiter, Michael}, + url = {https://irihs.ihs.ac.at/id/eprint/2021/}, + abstract = {Abstract: The paper presents a new method to solve DSGE models with a great number of heterogeneous agents. Using tools from systems and control theory, it is shown how to reduce the dimension of the state and the policy vector so that the reduced model approximates the original model with high precision. The method is illustrated with a stochastic growth model with incomplete markets similar to Krusell and Smith (1998), and with a model of heterogeneous firms with state-dependent pricing. For versions of those models that are nonlinear in individual variables, but linearized in aggregate variables, approximations with 50 to 200 state variables deliver solutions that are precise up to machine precision. The paper also shows how to reduce the state vector even further, with a very small reduction in precision.;} +} + +@article{CarrollEGM, + title = {The method of endogenous gridpoints for solving dynamic stochastic optimization problems}, + journal = {Economics Letters}, + volume = {91}, + number = {3}, + pages = {312-320}, + year = {2006}, + issn = {0165-1765}, + doi = {https://doi.org/10.1016/j.econlet.2005.09.013}, + url = {https://www.sciencedirect.com/science/article/pii/S0165176505003368}, + author = {Christopher D. Carroll}, + keywords = {Dynamic optimization, Precautionary saving, Stochastic growth model, Endogenous gridpoints, Liquidity constraints}, + abstract = {This paper introduces a solution method for numerical dynamic stochastic optimization problems that avoids rootfinding operations. The idea is applicable to many microeconomic and macroeconomic problems, including life cycle, buffer-stock, and stochastic growth problems. Software is provided.} +} + +@article{CarrollBuffer, + author = {Carroll, Christopher D.}, + title = "{Buffer-Stock Saving and the Life Cycle/Permanent Income Hypothesis*}", + journal = {The Quarterly Journal of Economics}, + volume = {112}, + number = {1}, + pages = {1-55}, + year = {1997}, + month = {02}, + abstract = "{This paper argues that the typical household's saving is better described by a “buffer-stock” version than by the traditional version of the Life Cycle/Permanent Income Hypothesis (LC/PIH) model. Buffer-stock behavior emerges if consumers with important income uncertainty are sufficiently impatient. In the traditional model, consumption growth is determined solely by tastes. In contrast, buffer-stock consumers set average consumption growth equal to average labor income growth, regardless of tastes. The model can explain three empirical puzzles: the “consumption/income parallel” documented by Carroll and Summers; the “consumption/income divergence” first documented in the 1930s; and the stability of the household age/wealth profile over time despite the unpredictability of idiosyncratic wealth changes.}", + issn = {0033-5533}, + doi = {10.1162/003355397555109}, + url = {https://doi.org/10.1162/003355397555109}, + eprint = {https://academic.oup.com/qje/article-pdf/112/1/1/5291627/112-1-1.pdf}, +} + +@InProceedings{HARK, + author = { {C}hristopher {D}. {C}arroll and {A}lexander {M}. {K}aufman and {J}acqueline {L}. {K}azil and {N}athan {M}. {P}almer and {M}atthew {N}. {W}hite }, + title = { {T}he {E}con-{A}{R}{K} and {H}{A}{R}{K}: {O}pen {S}ource {T}ools for {C}omputational {E}conomics }, + booktitle = { {P}roceedings of the 17th {P}ython in {S}cience {C}onference }, + pages = { 25 - 30 }, + year = { 2018 }, + editor = { {F}atih {A}kici and {D}avid {L}ippa and {D}illon {N}iederhut and {M} {P}acer }, + doi = { 10.25080/Majora-4af1f417-004 } +} diff --git a/Development/AIseedGrant/AIseedGrant.pdf b/Development/AIseedGrant/AIseedGrant.pdf new file mode 100644 index 0000000..d83f4b6 Binary files /dev/null and b/Development/AIseedGrant/AIseedGrant.pdf differ diff --git a/Development/AIseedGrant/AIseedGrant.tex b/Development/AIseedGrant/AIseedGrant.tex new file mode 100644 index 0000000..380cb7e --- /dev/null +++ b/Development/AIseedGrant/AIseedGrant.tex @@ -0,0 +1,98 @@ + + \documentclass[11pt,pdftex,letterpaper]{article} + \usepackage{setspace} + \usepackage[dvips,]{graphicx} %draft option suppresses graphics dvi display +% \usepackage{lscape} +% \usepackage{latexsym} +% \usepackage{endnotes} +% \usepackage{epsfig} + \usepackage{amsmath} +% \singlespace + \setlength{\textwidth}{6.5in} + \setlength{\textheight}{9in} + \addtolength{\topmargin}{-\topmargin} + \setlength{\oddsidemargin}{0in} + \setlength{\evensidemargin}{0in} + \addtolength{\headsep}{-\headsep} + \addtolength{\topskip}{-\topskip} + \addtolength{\headheight}{-\headheight} + \setcounter{secnumdepth}{2} +% \renewcommand{\thesection}{\arabic{section}} + % \renewcommand{\footnote}{\endnote} + \newtheorem{proposition}{Proposition} + \newtheorem{definition}{Definition} + \newtheorem{lemma}{lemma} + \newtheorem{corollary}{Corollary} + \newtheorem{assumption}{Assumption} + \newcommand{\Prob}{\operatorname{Prob}} + \clubpenalty 5000 + \widowpenalty 5000 + \renewcommand{\baselinestretch}{1.20} + \usepackage{amsmath} + \usepackage{amsthm} + \usepackage{amsfonts} + \usepackage{amssymb} + \usepackage{bbm} + \usepackage{natbib} + \newcommand{\N}{\mathbb{N}} + \newcommand{\R}{\mathbb{R}} + \newcommand{\E}{\mathbb{E}} + \newcommand{\der}[2]{\frac{\text{d}#1}{\text{d}#2}} + \newcommand{\pd}[2]{\frac{\partial#1}{\partial#2}} + +\begin{document} +\thispagestyle{empty} + +\begin{center} + \textbf{Proposal for AI-Informed Discovery and Inquiry Seed Grant 2025 \\ September 30, 2024} +\end{center} + +\vspace{1.5cm} + +\noindent \textbf{Project Title:} A Deeper Dive on Deep-Learning Solution Methods for Heterogeneous Agents Macroeconomic Models + +\vspace{1.5cm} + +\noindent \textbf{Principal Investigator:} Professor Christopher D. Carroll (\texttt{ccarroll@jhu.edu}), Department of Economics, Krieger School of Arts and Sciences + +\newpage +\setcounter{page}{1} + +\begin{center} + \textbf{Proposal Narrative} +\end{center} + +\noindent \textbf{Background:} A central assumption in economic modeling is that agents (decision-makers) have \textit{rational expectations} about future events. That is, while they do not know future states with certainty, they have accurate \textit{beliefs} about the \textit{distribution of events} that could occur, conditional on all information available to them in the present. Combined with the equally fundamental assumption of \textit{rational behavior}-- that each agent chooses their action (e.g.\ how much to spend on consumption vs save for the future) to optimize their preferences in some way-- the rational expectations assumption provides discipline to economic models. These assumptions ``pin down'' model predictions by restricting behavior and beliefs to be ``correct'' within the context of the model: there are infinite ways to be wrong and only one way to be right. While there is plenty of research on models of non-rational expectations (including by me in \cite{cAndCwithStickyE}) and evidence showing that human behavior \textit{cannot} be rationalized in some experimental contexts, these principles remain the standard core of modern economic theory. + +For decades, macroeconomists typically worked with \textit{representative agent} models, in which all households are agglomerated into a single \textit{representative consumer}, who is employed by the unitary \textit{representative firm}, etc. Such a reductive approach was justified by a widely held belief that heterogeneity among households or firms was of second or third order importance for aggregate, macroeconomic outcomes, as well as the practical consideration that modeling rational expectations about future outcomes is only feasible if present and future states can be represented by a reasonable number of variables. Over the past 25 years or so, the importance of the heterogeneity of household states (e.g.\ the distribution of wealth) has been taken more seriously by macroeconomists, nicely summarized in \cite{FiveGuys}. + +Properly solving a heterogeneous agents macroeconomic model is a daunting challenge, conceptually and computationally. Future prices depend on the future behavior of many agents (in the limit, a continuum), each of whose action depends on both their particular idiosyncratic circumstances and the entire distribution of states of their peers-- everyone has to know where everyone else is and predict what they're going to do. The canonical approach to this problem was presented in \cite{KrusellSmith}, who reduced households' information set to a small set of statistical moments about the full distribution (ultimately, just the mean) and showed that the value of further information was of little consequence to individual welfare nor aggregate dynamics. Subsequent work demonstrated that this result was not universal and critically depended on the simplifying assumptions, and explored other methods for reducing the complexity of the state space while preserving solution accuracy (see e.g. \cite{Reiter2010}). Variations on the original model used by Krusell \& Smith have remained the benchmark for exploring and discussing these topics, including in a special issue of the Journal of Economic Dynamics and Control (\cite{JEDCspecial}). + +More recently, researchers have begun to explore how deep-learning and neural-network approaches can be used to solve heterogeneous agents macroeconomic models. In particular, \cite{MALIAR202176} present a unified framework for solving such models using deep learning methods. Prior work usually divides the Krusell-Smith model into two complementary parts: 1) how agents should \textit{behave} conditional on the current state and their understanding of aggregate dynamics; and 2) how the macroeconomic state \textit{dynamically evolves} given how individual agents behave. This paper instead solves both parts together, casting the \textit{entire model} into a form usable by a neural network (or other functional approximator), and showing that three related approaches to representing the model all yield comparable results. As usual, the benchmark model is based on \cite{KrusellSmith}, and the authors briefly explore how their deep-learning solution systematically deviates from that produced by the traditional moment-based method. Based on their analysis, the authors conclude that incorporating more neurons in the second hidden layer (representing aggregate dynamics) is effective in improving solution accuracy, but including more moments of the state distribution is not. They explain that this is because the moments are \textit{exogenously chosen} pieces of information that \textit{aren't valuable} to agents when choosing their action, whereas the neural-network approach \textit{endogenously} finds the aggregate information that is relevant to individuals. + +\vspace{0.25cm} + +\noindent \textbf{Area of Investigation:} I believe that this last point is ripe for a deeper exploration, and that I am well equipped to conduct this work with an AI-Informed Seed Grant. \cite{MALIAR202176} report model solution times ranging from 9 minutes to 12 hours (on an ordinary laptop) depending on how many agents are tracked in the population for their method (1 to 1000). From personal experience with their variation of the Krusell-Smith model, I know that the traditional (moment-based) method takes only a few minutes to solve on ordinary hardware. The (approximately one page) discussion of this topic in the published paper does not provide any insight into the \textit{economic magnitude} of the improvement in solution accuracy that is attained by spending orders of magnitude more computational time, nor provides such a comparison time for readers who are less familiar. As a basic threshold matter, I would conduct a more thorough exploration and report of the trade-off between computation time and solution accuracy, using standard measures for the field. As you might guess, economists are interested in \textit{what's gained} when additional resources are spent. + +Beyond that straightforward analysis, the AI-Informed Seed Grant would be used to investigate a hybrid approach that lies between the traditional moment-based method from \cite{KrusellSmith} and the unified approach in \cite{MALIAR202176} that passes the entire model as a problem for the neural network to solve. Returning to the framing in the Background portion of this narrative, solving for \textit{rational behavior} conditional on beliefs is a well understood problem in computational economics; there are many ``secrets'' and ``tricks'' that have developed over time for efficiently solving such problems. Under the ``unified'' approach in \cite{MALIAR202176}, decades of specialized know-how about solving consumption-saving problems is thrown out and the neural network is left to its own devices, unguided by economic theory about its task. In contrast, representing \textit{rational expectations} when the state space is high dimensional is \textit{not nearly} as well understood or developed. Given a long history of the states and actions of millions of agents, an economist would have some \textit{informed guesses} about how best to summarize the dynamic properties of this information, but they wouldn't necessarily be very good. To wit, Per Krusell and Tony Smith thought that the second and third moments of the wealth distribution would be relevant, but they were wrong. Parsing large datasets for the important ``hidden'' features is \textit{exactly} what deep learning methods excel at. + +\vspace{0.25cm} + +\noindent \textbf{Project Goals, Methods, and Impact:} The main task for the AI-Informed Seed Grant would be to investigate and report on a hybrid method in which the \textit{microeconomic} problem (rational behavior conditional on beliefs about aggregate dynamics) is solved by human-coded methods, drawing on decades of specialized knowledge, while the \textit{macroeconomic} component (characterizing aggregate dynamics from individual behavior) would be conducted by neural network. I believe this approach would best apply machine learning to the aspect of heterogeneous agents macroeconomics for which it is best suited, maximizing its efficiency in the solution method. + +Moreover, the field would greatly benefit from a proper \textit{interpretation} of the neural network's solution. That is, if the second moment of the wealth distribution \textit{isn't} relevant, but the neural network found information of the same dimensionality that \textit{is} relevant, then \textit{what is that information}? \cite{MALIAR202176} are silent on this critical question, the answer to which would inform further development of both economic theory and computational methods. That is, if we have a better idea of \textit{what to look for} based on the neural network's solution to one model, these insights can be applied to other models \textit{whether or not} a neural network is used to solve them. + +I am particularly well suited for this task for several reasons. First, and with appropriate humility, I am one of the leading theorists on consumption-saving models (\cite{CarrollBuffer}), as well as the developer of foundational methods for their efficient solution (\cite{CarrollEGM}). Second, I am the PI for Econ-ARK (\texttt{http://www.econ-ark.org}), a project that produces open source software for solving heterogeneous agents models (the \texttt{HARK} Python package). Econ-ARK's developers are currently working on a modeling language that will allow for much greater cross-compatibility of solution methods, including machine-learning toolkits. Being able to demonstrate a proof-of-concept by connecting \texttt{HARK}'s hand-coded microeconomic solvers to a neural network that can efficiently characterize the relevant macroeconomic dynamics would make Econ-ARK \textit{significantly} more attractive to other funders. This project is currently funded by a generous corporate sponsorship from T.\ Rowe Price, and has previously received a large grant from the Sloan Foundation, to whom we are applying for a second grant. + +\nocite{HARK} + +Third, I have recently been installed as the president of the Society for Computational Economics (SCE), taking over from Lilia Maliar (of \cite{MALIAR202176}). Tying these last two together into the fourth and final reason: this summer Econ-ARK employed the Maliars' son Marc, who actually helped them write the TensorFlow code for that paper. Developing the hybrid method that I have outlined here is eminently feasible for me because I already am the PI for an expertly developed microeconomic solution codebase \textit{and} direct access to the authors and programmers for the seminal paper that I seek to improve upon. The tools are there, and the AI-Informed Seed Grant would provide the means for me to put them together. + +\newpage + +\begin{singlespace} + \bibliographystyle{mnwteststyle} + \bibliography{AIseed} +\end{singlespace} + +\end{document} \ No newline at end of file diff --git a/Development/AIseedGrant/mnwteststyle.bst b/Development/AIseedGrant/mnwteststyle.bst new file mode 100644 index 0000000..4cddfcc --- /dev/null +++ b/Development/AIseedGrant/mnwteststyle.bst @@ -0,0 +1,1590 @@ +%% +%% This is file `mnwteststyle.bst', +%% generated with the docstrip utility. +%% +%% The original source files were: +%% +%% merlin.mbs (with options: `ay,nat,seq-labc,nm-rev,jnrlst,mcite,mct-1,mct-x3,nmft,nmft-sc,keyxyr,blkyear,dt-beg,yr-par,note-yr,tit-qq,bt-qq,atit-u,volp-sp,num-xser,ser-vol,isbn,pp,abr,ednx,mth-bare,xedn,nfss,') +%% ---------------------------------------- +%% *** This is my first attempt at a bst for my dissertation. *** +%% +%% Copyright 1994-2011 Patrick W Daly + % =============================================================== + % IMPORTANT NOTICE: + % This bibliographic style (bst) file has been generated from one or + % more master bibliographic style (mbs) files, listed above. + % + % This generated file can be redistributed and/or modified under the terms + % of the LaTeX Project Public License Distributed from CTAN + % archives in directory macros/latex/base/lppl.txt; either + % version 1 of the License, or any later version. + % =============================================================== + % Name and version information of the main mbs file: + % \ProvidesFile{merlin.mbs}[2011/11/18 4.33 (PWD, AO, DPC)] + % For use with BibTeX version 0.99a or later + %------------------------------------------------------------------- + % This bibliography style file is intended for texts in ENGLISH + % This is an author-year citation style bibliography. As such, it is + % non-standard LaTeX, and requires a special package file to function properly. + % Such a package is natbib.sty by Patrick W. Daly + % The form of the \bibitem entries is + % \bibitem[Jones et al.(1990)]{key}... + % \bibitem[Jones et al.(1990)Jones, Baker, and Smith]{key}... + % The essential feature is that the label (the part in brackets) consists + % of the author names, as they should appear in the citation, with the year + % in parentheses following. There must be no space before the opening + % parenthesis! + % With natbib v5.3, a full list of authors may also follow the year. + % In natbib.sty, it is possible to define the type of enclosures that is + % really wanted (brackets or parentheses), but in either case, there must + % be parentheses in the label. + % The \cite command functions as follows: + % \citet{key} ==>> Jones et al. (1990) + % \citet*{key} ==>> Jones, Baker, and Smith (1990) + % \citep{key} ==>> (Jones et al., 1990) + % \citep*{key} ==>> (Jones, Baker, and Smith, 1990) + % \citep[chap. 2]{key} ==>> (Jones et al., 1990, chap. 2) + % \citep[e.g.][]{key} ==>> (e.g. Jones et al., 1990) + % \citep[e.g.][p. 32]{key} ==>> (e.g. Jones et al., 1990, p. 32) + % \citeauthor{key} ==>> Jones et al. + % \citeauthor*{key} ==>> Jones, Baker, and Smith + % \citeyear{key} ==>> 1990 + %--------------------------------------------------------------------- + +ENTRY + { address + author + booktitle + chapter + edition + editor + eid + howpublished + institution + isbn + journal + key + month + note + number + organization + pages + publisher + school + series + title + type + volume + year + } + {} + { label extra.label sort.label short.list } +INTEGERS { output.state before.all mid.sentence after.sentence after.block } +FUNCTION {init.state.consts} +{ #0 'before.all := + #1 'mid.sentence := + #2 'after.sentence := + #3 'after.block := +} +STRINGS { s t} +FUNCTION {output.nonnull} +{ 's := + output.state mid.sentence = + { ", " * write$ } + { output.state after.block = + { add.period$ write$ + newline$ + "\newblock " write$ + } + { output.state before.all = + 'write$ + { add.period$ " " * write$ } + if$ + } + if$ + mid.sentence 'output.state := + } + if$ + s +} +FUNCTION {output} +{ duplicate$ empty$ + 'pop$ + 'output.nonnull + if$ +} +FUNCTION {output.check} +{ 't := + duplicate$ empty$ + { pop$ "empty " t * " in " * cite$ * warning$ } + 'output.nonnull + if$ +} +FUNCTION {fin.entry} +{ add.period$ + write$ + newline$ +} + +FUNCTION {new.block} +{ output.state before.all = + 'skip$ + { after.block 'output.state := } + if$ +} +FUNCTION {new.sentence} +{ output.state after.block = + 'skip$ + { output.state before.all = + 'skip$ + { after.sentence 'output.state := } + if$ + } + if$ +} +FUNCTION {add.blank} +{ " " * before.all 'output.state := +} + +FUNCTION {date.block} +{ + new.block +} + +FUNCTION {not} +{ { #0 } + { #1 } + if$ +} +FUNCTION {and} +{ 'skip$ + { pop$ #0 } + if$ +} +FUNCTION {or} +{ { pop$ #1 } + 'skip$ + if$ +} +FUNCTION {non.stop} +{ duplicate$ + "}" * add.period$ + #-1 #1 substring$ "." = +} + +STRINGS {z} + +FUNCTION {remove.dots} +{ 'z := + "" + { z empty$ not } + { z #1 #2 substring$ + duplicate$ "\." = + { z #3 global.max$ substring$ 'z := * } + { pop$ + z #1 #1 substring$ + z #2 global.max$ substring$ 'z := + duplicate$ "." = 'pop$ + { * } + if$ + } + if$ + } + while$ +} +FUNCTION {new.block.checkb} +{ empty$ + swap$ empty$ + and + 'skip$ + 'new.block + if$ +} +FUNCTION {field.or.null} +{ duplicate$ empty$ + { pop$ "" } + 'skip$ + if$ +} +FUNCTION {emphasize} +{ duplicate$ empty$ + { pop$ "" } + { "\emph{" swap$ * "}" * } + if$ +} +FUNCTION {scaps} +{ duplicate$ empty$ + { pop$ "" } + { "\textsc{" swap$ * "}" * } + if$ +} +FUNCTION {bib.name.font} +{ scaps } +FUNCTION {bib.fname.font} +{ bib.name.font } +FUNCTION {tie.or.space.prefix} +{ duplicate$ text.length$ #3 < + { "~" } + { " " } + if$ + swap$ +} + +FUNCTION {capitalize} +{ "u" change.case$ "t" change.case$ } + +FUNCTION {space.word} +{ " " swap$ * " " * } + % Here are the language-specific definitions for explicit words. + % Each function has a name bbl.xxx where xxx is the English word. + % The language selected here is ENGLISH +FUNCTION {bbl.and} +{ "and"} + +FUNCTION {bbl.etal} +{ "et~al." } + +FUNCTION {bbl.editors} +{ "editors" } + +FUNCTION {bbl.editor} +{ "editor" } + +FUNCTION {bbl.edby} +{ "edited by" } + +FUNCTION {bbl.edition} +{ "ed." } + +FUNCTION {bbl.volume} +{ "vol." } + +FUNCTION {bbl.of} +{ "of" } + +FUNCTION {bbl.number} +{ "no." } + +FUNCTION {bbl.nr} +{ "no." } + +FUNCTION {bbl.in} +{ "in" } + +FUNCTION {bbl.pages} +{ "pp." } + +FUNCTION {bbl.page} +{ "p." } + +FUNCTION {bbl.chapter} +{ "chap." } + +FUNCTION {bbl.techrep} +{ "Tech. Rep." } + +FUNCTION {bbl.mthesis} +{ "Master's thesis" } + +FUNCTION {bbl.phdthesis} +{ "Ph.D. thesis" } + +MACRO {jan} {"Jan."} + +MACRO {feb} {"Feb."} + +MACRO {mar} {"Mar."} + +MACRO {apr} {"Apr."} + +MACRO {may} {"May"} + +MACRO {jun} {"Jun."} + +MACRO {jul} {"Jul."} + +MACRO {aug} {"Aug."} + +MACRO {sep} {"Sep."} + +MACRO {oct} {"Oct."} + +MACRO {nov} {"Nov."} + +MACRO {dec} {"Dec."} + +MACRO {acmcs} {"ACM Computing Surveys"} + +MACRO {acta} {"Acta Informatica"} + +MACRO {cacm} {"Communications of the ACM"} + +MACRO {ibmjrd} {"IBM Journal of Research and Development"} + +MACRO {ibmsj} {"IBM Systems Journal"} + +MACRO {ieeese} {"IEEE Transactions on Software Engineering"} + +MACRO {ieeetc} {"IEEE Transactions on Computers"} + +MACRO {ieeetcad} + {"IEEE Transactions on Computer-Aided Design of Integrated Circuits"} + +MACRO {ipl} {"Information Processing Letters"} + +MACRO {jacm} {"Journal of the ACM"} + +MACRO {jcss} {"Journal of Computer and System Sciences"} + +MACRO {scp} {"Science of Computer Programming"} + +MACRO {sicomp} {"SIAM Journal on Computing"} + +MACRO {tocs} {"ACM Transactions on Computer Systems"} + +MACRO {tods} {"ACM Transactions on Database Systems"} + +MACRO {tog} {"ACM Transactions on Graphics"} + +MACRO {toms} {"ACM Transactions on Mathematical Software"} + +MACRO {toois} {"ACM Transactions on Office Information Systems"} + +MACRO {toplas} {"ACM Transactions on Programming Languages and Systems"} + +MACRO {tcs} {"Theoretical Computer Science"} +FUNCTION {bibinfo.check} +{ swap$ + duplicate$ missing$ + { + pop$ pop$ + "" + } + { duplicate$ empty$ + { + swap$ pop$ + } + { swap$ + pop$ + } + if$ + } + if$ +} +FUNCTION {bibinfo.warn} +{ swap$ + duplicate$ missing$ + { + swap$ "missing " swap$ * " in " * cite$ * warning$ pop$ + "" + } + { duplicate$ empty$ + { + swap$ "empty " swap$ * " in " * cite$ * warning$ + } + { swap$ + pop$ + } + if$ + } + if$ +} +INTEGERS { nameptr namesleft numnames } + + +STRINGS { bibinfo} + +FUNCTION {format.names} +{ 'bibinfo := + duplicate$ empty$ 'skip$ { + 's := + "" 't := + #1 'nameptr := + s num.names$ 'numnames := + numnames 'namesleft := + { namesleft #0 > } + { s nameptr + "{vv~}{ll}{, f.}{, jj}" + format.name$ + bibinfo bibinfo.check + 't := + nameptr #1 > + { + namesleft #1 > + { ", " * t * } + { + s nameptr "{ll}" format.name$ duplicate$ "others" = + { 't := } + { pop$ } + if$ + numnames #2 > + { "," * } + 'skip$ + if$ + t "others" = + { + " " * bbl.etal * + bib.name.font + } + { + bbl.and + space.word * t * + } + if$ + } + if$ + } + 't + if$ + nameptr #1 + 'nameptr := + namesleft #1 - 'namesleft := + } + while$ + t "others" = + 'skip$ + { bib.name.font } + if$ + } if$ +} +FUNCTION {format.names.ed} +{ + 'bibinfo := + duplicate$ empty$ 'skip$ { + 's := + "" 't := + #1 'nameptr := + s num.names$ 'numnames := + numnames 'namesleft := + { namesleft #0 > } + { s nameptr + "{f.~}{vv~}{ll}{, jj}" + format.name$ + bibinfo bibinfo.check + 't := + nameptr #1 > + { + namesleft #1 > + { ", " * t * } + { + s nameptr "{ll}" format.name$ duplicate$ "others" = + { 't := } + { pop$ } + if$ + numnames #2 > + { "," * } + 'skip$ + if$ + t "others" = + { + + " " * bbl.etal * + } + { + bbl.and + space.word * t * + } + if$ + } + if$ + } + 't + if$ + nameptr #1 + 'nameptr := + namesleft #1 - 'namesleft := + } + while$ + } if$ +} +FUNCTION {format.key} +{ empty$ + { key field.or.null } + { "" } + if$ +} + +FUNCTION {format.authors} +{ author "author" format.names +} +FUNCTION {get.bbl.editor} +{ editor num.names$ #1 > 'bbl.editors 'bbl.editor if$ } + +FUNCTION {format.editors} +{ editor "editor" format.names duplicate$ empty$ 'skip$ + { + "," * + " " * + get.bbl.editor + * + } + if$ +} +FUNCTION {format.isbn} +{ isbn "isbn" bibinfo.check + duplicate$ empty$ 'skip$ + { + new.block + "ISBN " swap$ * + } + if$ +} + +FUNCTION {format.note} +{ + note empty$ + { "" } + { note #1 #1 substring$ + duplicate$ "{" = + 'skip$ + { output.state mid.sentence = + { "l" } + { "u" } + if$ + change.case$ + } + if$ + note #2 global.max$ substring$ * "note" bibinfo.check + } + if$ +} + +FUNCTION {format.title} +{ title + "title" bibinfo.check + duplicate$ empty$ 'skip$ + { + "\enquote{" swap$ * + add.period$ "}" * + } + if$ +} +FUNCTION {end.quote.btitle} +{ booktitle empty$ + 'skip$ + { before.all 'output.state := } + if$ +} +FUNCTION {format.full.names} +{'s := + "" 't := + #1 'nameptr := + s num.names$ 'numnames := + numnames 'namesleft := + { namesleft #0 > } + { s nameptr + "{vv~}{ll}" format.name$ + 't := + nameptr #1 > + { + namesleft #1 > + { ", " * t * } + { + s nameptr "{ll}" format.name$ duplicate$ "others" = + { 't := } + { pop$ } + if$ + t "others" = + { + " " * bbl.etal * + } + { + numnames #2 > + { "," * } + 'skip$ + if$ + bbl.and + space.word * t * + } + if$ + } + if$ + } + 't + if$ + nameptr #1 + 'nameptr := + namesleft #1 - 'namesleft := + } + while$ +} + +FUNCTION {author.editor.key.full} +{ author empty$ + { editor empty$ + { key empty$ + { cite$ #1 #3 substring$ } + 'key + if$ + } + { editor format.full.names } + if$ + } + { author format.full.names } + if$ +} + +FUNCTION {author.key.full} +{ author empty$ + { key empty$ + { cite$ #1 #3 substring$ } + 'key + if$ + } + { author format.full.names } + if$ +} + +FUNCTION {editor.key.full} +{ editor empty$ + { key empty$ + { cite$ #1 #3 substring$ } + 'key + if$ + } + { editor format.full.names } + if$ +} + +FUNCTION {make.full.names} +{ type$ "book" = + type$ "inbook" = + or + 'author.editor.key.full + { type$ "proceedings" = + 'editor.key.full + 'author.key.full + if$ + } + if$ +} + +FUNCTION {output.bibitem} +{ newline$ + "\bibitem[{" write$ + label write$ + ")" make.full.names duplicate$ short.list = + { pop$ } + { * } + if$ + "}]{" * write$ + cite$ write$ + "}" write$ + newline$ + "" + before.all 'output.state := +} + +FUNCTION {n.dashify} +{ + 't := + "" + { t empty$ not } + { t #1 #1 substring$ "-" = + { t #1 #2 substring$ "--" = not + { "--" * + t #2 global.max$ substring$ 't := + } + { { t #1 #1 substring$ "-" = } + { "-" * + t #2 global.max$ substring$ 't := + } + while$ + } + if$ + } + { t #1 #1 substring$ * + t #2 global.max$ substring$ 't := + } + if$ + } + while$ +} + +FUNCTION {word.in} +{ bbl.in capitalize + " " * } + +FUNCTION {format.date} +{ year "year" bibinfo.check duplicate$ empty$ + { + } + 'skip$ + if$ + extra.label * + before.all 'output.state := + " (" swap$ * ")" * +} +FUNCTION {format.btitle} +{ title "title" bibinfo.check + duplicate$ empty$ 'skip$ + { + emphasize + } + if$ +} +FUNCTION {either.or.check} +{ empty$ + 'pop$ + { "can't use both " swap$ * " fields in " * cite$ * warning$ } + if$ +} +FUNCTION {format.bvolume} +{ volume empty$ + { "" } + { bbl.volume volume tie.or.space.prefix + "volume" bibinfo.check * * + series "series" bibinfo.check + duplicate$ empty$ 'pop$ + { emphasize ", " * swap$ * } + if$ + "volume and number" number either.or.check + } + if$ +} +FUNCTION {format.number.series} +{ volume empty$ + { number empty$ + { series field.or.null } + { series empty$ + { number "number" bibinfo.check } + { output.state mid.sentence = + { bbl.number } + { bbl.number capitalize } + if$ + number tie.or.space.prefix "number" bibinfo.check * * + bbl.in space.word * + series "series" bibinfo.check * + } + if$ + } + if$ + } + { "" } + if$ +} + +FUNCTION {format.edition} +{ edition duplicate$ empty$ 'skip$ + { + output.state mid.sentence = + { "l" } + { "t" } + if$ change.case$ + "edition" bibinfo.check + " " * bbl.edition * + } + if$ +} +INTEGERS { multiresult } +FUNCTION {multi.page.check} +{ 't := + #0 'multiresult := + { multiresult not + t empty$ not + and + } + { t #1 #1 substring$ + duplicate$ "-" = + swap$ duplicate$ "," = + swap$ "+" = + or or + { #1 'multiresult := } + { t #2 global.max$ substring$ 't := } + if$ + } + while$ + multiresult +} +FUNCTION {format.pages} +{ pages duplicate$ empty$ 'skip$ + { duplicate$ multi.page.check + { + bbl.pages swap$ + n.dashify + } + { + bbl.page swap$ + } + if$ + tie.or.space.prefix + "pages" bibinfo.check + * * + } + if$ +} +FUNCTION {format.journal.pages} +{ pages duplicate$ empty$ 'pop$ + { swap$ duplicate$ empty$ + { pop$ pop$ format.pages } + { + ": " * + swap$ + n.dashify + "pages" bibinfo.check + * + } + if$ + } + if$ +} +FUNCTION {format.journal.eid} +{ eid "eid" bibinfo.check + duplicate$ empty$ 'pop$ + { swap$ duplicate$ empty$ 'skip$ + { + ": " * + } + if$ + swap$ * + } + if$ +} +FUNCTION {format.vol.num.pages} +{ volume field.or.null + duplicate$ empty$ 'skip$ + { + "volume" bibinfo.check + } + if$ + number "number" bibinfo.check duplicate$ empty$ 'skip$ + { + swap$ duplicate$ empty$ + { "there's a number but no volume in " cite$ * warning$ } + 'skip$ + if$ + swap$ + "(" swap$ * ")" * + } + if$ * + eid empty$ + { format.journal.pages } + { format.journal.eid } + if$ +} + +FUNCTION {format.chapter.pages} +{ chapter empty$ + 'format.pages + { type empty$ + { bbl.chapter } + { type "l" change.case$ + "type" bibinfo.check + } + if$ + chapter tie.or.space.prefix + "chapter" bibinfo.check + * * + pages empty$ + 'skip$ + { ", " * format.pages * } + if$ + } + if$ +} + +FUNCTION {bt.enquote} +{ duplicate$ empty$ 'skip$ + { "\enquote{" swap$ * + non.stop + { ",} " * } + { "}, " * } + if$ + } + if$ +} +FUNCTION {format.booktitle} +{ + booktitle "booktitle" bibinfo.check + bt.enquote +} +FUNCTION {format.in.ed.booktitle} +{ format.booktitle duplicate$ empty$ 'skip$ + { + editor "editor" format.names.ed duplicate$ empty$ 'pop$ + { + "," * + " " * + get.bbl.editor + ", " * + * swap$ + * } + if$ + word.in swap$ * + } + if$ +} +FUNCTION {format.thesis.type} +{ type duplicate$ empty$ + 'pop$ + { swap$ pop$ + "t" change.case$ "type" bibinfo.check + } + if$ +} +FUNCTION {format.tr.number} +{ number "number" bibinfo.check + type duplicate$ empty$ + { pop$ bbl.techrep } + 'skip$ + if$ + "type" bibinfo.check + swap$ duplicate$ empty$ + { pop$ "t" change.case$ } + { tie.or.space.prefix * * } + if$ +} +FUNCTION {format.article.crossref} +{ + word.in + " \cite{" * crossref * "}" * +} +FUNCTION {format.book.crossref} +{ volume duplicate$ empty$ + { "empty volume in " cite$ * "'s crossref of " * crossref * warning$ + pop$ word.in + } + { bbl.volume + capitalize + swap$ tie.or.space.prefix "volume" bibinfo.check * * bbl.of space.word * + } + if$ + " \cite{" * crossref * "}" * +} +FUNCTION {format.incoll.inproc.crossref} +{ + word.in + " \cite{" * crossref * "}" * +} +FUNCTION {format.org.or.pub} +{ 't := + "" + address empty$ t empty$ and + 'skip$ + { + t empty$ + { address "address" bibinfo.check * + } + { t * + address empty$ + 'skip$ + { ", " * address "address" bibinfo.check * } + if$ + } + if$ + } + if$ +} +FUNCTION {format.publisher.address} +{ publisher "publisher" bibinfo.warn format.org.or.pub +} + +FUNCTION {format.organization.address} +{ organization "organization" bibinfo.check format.org.or.pub +} + +FUNCTION {article} +{ output.bibitem + format.authors "author" output.check + author format.key output + format.date "year" output.check + date.block + format.title "title" output.check + new.block + crossref missing$ + { + journal + "journal" bibinfo.check + emphasize + "journal" output.check + format.vol.num.pages output + } + { format.article.crossref output.nonnull + format.pages output + } + if$ + new.block + format.note output + fin.entry +} +FUNCTION {book} +{ output.bibitem + author empty$ + { format.editors "author and editor" output.check + editor format.key output + } + { format.authors output.nonnull + crossref missing$ + { "author and editor" editor either.or.check } + 'skip$ + if$ + } + if$ + format.date "year" output.check + date.block + format.btitle "title" output.check + crossref missing$ + { format.bvolume output + new.block + format.number.series output + new.sentence + format.publisher.address output + } + { + new.block + format.book.crossref output.nonnull + } + if$ + format.edition output + format.isbn output + new.block + format.note output + fin.entry +} +FUNCTION {booklet} +{ output.bibitem + format.authors output + author format.key output + format.date "year" output.check + date.block + format.title "title" output.check + new.block + howpublished "howpublished" bibinfo.check output + address "address" bibinfo.check output + format.isbn output + new.block + format.note output + fin.entry +} + +FUNCTION {inbook} +{ output.bibitem + author empty$ + { format.editors "author and editor" output.check + editor format.key output + } + { format.authors output.nonnull + crossref missing$ + { "author and editor" editor either.or.check } + 'skip$ + if$ + } + if$ + format.date "year" output.check + date.block + format.btitle "title" output.check + crossref missing$ + { + format.bvolume output + format.chapter.pages "chapter and pages" output.check + new.block + format.number.series output + new.sentence + format.publisher.address output + } + { + format.chapter.pages "chapter and pages" output.check + new.block + format.book.crossref output.nonnull + } + if$ + format.edition output + crossref missing$ + { format.isbn output } + 'skip$ + if$ + new.block + format.note output + fin.entry +} + +FUNCTION {incollection} +{ output.bibitem + format.authors "author" output.check + author format.key output + format.date "year" output.check + date.block + format.title "title" output.check + new.block + crossref missing$ + { format.in.ed.booktitle "booktitle" output.check + end.quote.btitle + format.bvolume output + format.number.series output + format.chapter.pages output + new.sentence + format.publisher.address output + format.edition output + format.isbn output + } + { format.incoll.inproc.crossref output.nonnull + format.chapter.pages output + } + if$ + new.block + format.note output + fin.entry +} +FUNCTION {inproceedings} +{ output.bibitem + format.authors "author" output.check + author format.key output + format.date "year" output.check + date.block + format.title "title" output.check + new.block + crossref missing$ + { format.in.ed.booktitle "booktitle" output.check + end.quote.btitle + format.bvolume output + format.number.series output + format.pages output + new.sentence + publisher empty$ + { format.organization.address output } + { organization "organization" bibinfo.check output + format.publisher.address output + } + if$ + format.isbn output + } + { format.incoll.inproc.crossref output.nonnull + format.pages output + } + if$ + new.block + format.note output + fin.entry +} +FUNCTION {conference} { inproceedings } +FUNCTION {manual} +{ output.bibitem + format.authors output + author format.key output + format.date "year" output.check + date.block + format.btitle "title" output.check + organization address new.block.checkb + organization "organization" bibinfo.check output + address "address" bibinfo.check output + format.edition output + new.block + format.note output + fin.entry +} + +FUNCTION {mastersthesis} +{ output.bibitem + format.authors "author" output.check + author format.key output + format.date "year" output.check + date.block + format.btitle + "title" output.check + new.block + bbl.mthesis format.thesis.type output.nonnull + school "school" bibinfo.warn output + address "address" bibinfo.check output + new.block + format.note output + fin.entry +} + +FUNCTION {misc} +{ output.bibitem + format.authors output + author format.key output + format.date "year" output.check + date.block + format.title output + new.block + howpublished "howpublished" bibinfo.check output + new.block + format.note output + fin.entry +} +FUNCTION {phdthesis} +{ output.bibitem + format.authors "author" output.check + author format.key output + format.date "year" output.check + date.block + format.btitle + "title" output.check + new.block + bbl.phdthesis format.thesis.type output.nonnull + school "school" bibinfo.warn output + address "address" bibinfo.check output + new.block + format.note output + fin.entry +} + +FUNCTION {proceedings} +{ output.bibitem + format.editors output + editor format.key output + format.date "year" output.check + date.block + format.btitle "title" output.check + format.bvolume output + format.number.series output + new.sentence + publisher empty$ + { format.organization.address output } + { organization "organization" bibinfo.check output + format.publisher.address output + } + if$ + format.isbn output + new.block + format.note output + fin.entry +} + +FUNCTION {techreport} +{ output.bibitem + format.authors "author" output.check + author format.key output + format.date "year" output.check + date.block + format.title + "title" output.check + new.block + format.tr.number output.nonnull + institution "institution" bibinfo.warn output + address "address" bibinfo.check output + new.block + format.note output + fin.entry +} + +FUNCTION {unpublished} +{ output.bibitem + format.authors "author" output.check + author format.key output + format.date "year" output.check + date.block + format.title "title" output.check + new.block + format.note "note" output.check + fin.entry +} + +FUNCTION {default.type} { misc } +READ +FUNCTION {sortify} +{ purify$ + "l" change.case$ +} +INTEGERS { len } +FUNCTION {chop.word} +{ 's := + 'len := + s #1 len substring$ = + { s len #1 + global.max$ substring$ } + 's + if$ +} +FUNCTION {format.lab.names} +{'s := + "" 't := + #1 'nameptr := + s num.names$ 'numnames := + numnames 'namesleft := + { namesleft #0 > } + { s nameptr + "{vv~}{ll}" format.name$ + 't := + nameptr #1 > + { + nameptr #2 = + numnames #3 > and + { "others" 't := + #1 'namesleft := } + 'skip$ + if$ + namesleft #1 > + { ", " * t * } + { + s nameptr "{ll}" format.name$ duplicate$ "others" = + { 't := } + { pop$ } + if$ + t "others" = + { + " " * bbl.etal * + } + { + numnames #2 > + { "," * } + 'skip$ + if$ + bbl.and + space.word * t * + } + if$ + } + if$ + } + 't + if$ + nameptr #1 + 'nameptr := + namesleft #1 - 'namesleft := + } + while$ +} + +FUNCTION {author.key.label} +{ author empty$ + { key empty$ + { cite$ #1 #3 substring$ } + 'key + if$ + } + { author format.lab.names } + if$ +} + +FUNCTION {author.editor.key.label} +{ author empty$ + { editor empty$ + { key empty$ + { cite$ #1 #3 substring$ } + 'key + if$ + } + { editor format.lab.names } + if$ + } + { author format.lab.names } + if$ +} + +FUNCTION {editor.key.label} +{ editor empty$ + { key empty$ + { cite$ #1 #3 substring$ } + 'key + if$ + } + { editor format.lab.names } + if$ +} + +FUNCTION {calc.short.authors} +{ type$ "book" = + type$ "inbook" = + or + 'author.editor.key.label + { type$ "proceedings" = + 'editor.key.label + 'author.key.label + if$ + } + if$ + 'short.list := +} + +FUNCTION {calc.label} +{ calc.short.authors + short.list + "(" + * + year duplicate$ empty$ + short.list key field.or.null = or + { pop$ "" } + 'skip$ + if$ + * + 'label := +} + +FUNCTION {sort.format.names} +{ 's := + #1 'nameptr := + "" + s num.names$ 'numnames := + numnames 'namesleft := + { namesleft #0 > } + { s nameptr + "{vv{ } }{ll{ }}{ f{ }}{ jj{ }}" + format.name$ 't := + nameptr #1 > + { + " " * + namesleft #1 = t "others" = and + { "zzzzz" 't := } + 'skip$ + if$ + numnames #2 > nameptr #2 = and + { "zz" * year field.or.null * " " * + #1 'namesleft := + } + { t sortify * } + if$ + } + { t sortify * } + if$ + nameptr #1 + 'nameptr := + namesleft #1 - 'namesleft := + } + while$ +} + +FUNCTION {sort.format.title} +{ 't := + "A " #2 + "An " #3 + "The " #4 t chop.word + chop.word + chop.word + sortify + #1 global.max$ substring$ +} +FUNCTION {author.sort} +{ author empty$ + { key empty$ + { "to sort, need author or key in " cite$ * warning$ + "" + } + { key sortify } + if$ + } + { author sort.format.names } + if$ +} +FUNCTION {author.editor.sort} +{ author empty$ + { editor empty$ + { key empty$ + { "to sort, need author, editor, or key in " cite$ * warning$ + "" + } + { key sortify } + if$ + } + { editor sort.format.names } + if$ + } + { author sort.format.names } + if$ +} +FUNCTION {editor.sort} +{ editor empty$ + { key empty$ + { "to sort, need editor or key in " cite$ * warning$ + "" + } + { key sortify } + if$ + } + { editor sort.format.names } + if$ +} +FUNCTION {presort} +{ calc.label + label sortify + " " + * + type$ "book" = + type$ "inbook" = + or + 'author.editor.sort + { type$ "proceedings" = + 'editor.sort + 'author.sort + if$ + } + if$ + #1 entry.max$ substring$ + 'sort.label := + sort.label + * + #1 entry.max$ substring$ + 'sort.key$ := +} + +ITERATE {presort} +SORT +STRINGS { last.label next.extra } +INTEGERS { last.extra.num last.extra.num.extended last.extra.num.blank number.label } +FUNCTION {initialize.extra.label.stuff} +{ #0 int.to.chr$ 'last.label := + "" 'next.extra := + #0 'last.extra.num := + "a" chr.to.int$ #1 - 'last.extra.num.blank := + last.extra.num.blank 'last.extra.num.extended := + #0 'number.label := +} +FUNCTION {forward.pass} +{ last.label label = + { last.extra.num #1 + 'last.extra.num := + last.extra.num "z" chr.to.int$ > + { "a" chr.to.int$ 'last.extra.num := + last.extra.num.extended #1 + 'last.extra.num.extended := + } + 'skip$ + if$ + last.extra.num.extended last.extra.num.blank > + { last.extra.num.extended int.to.chr$ + last.extra.num int.to.chr$ + * 'extra.label := } + { last.extra.num int.to.chr$ 'extra.label := } + if$ + } + { "a" chr.to.int$ 'last.extra.num := + "" 'extra.label := + label 'last.label := + } + if$ + number.label #1 + 'number.label := +} +FUNCTION {reverse.pass} +{ next.extra "b" = + { "a" 'extra.label := } + 'skip$ + if$ + extra.label 'next.extra := + extra.label + duplicate$ empty$ + 'skip$ + { "{\natexlab{" swap$ * "}}" * } + if$ + 'extra.label := + label extra.label * 'label := +} +EXECUTE {initialize.extra.label.stuff} +ITERATE {forward.pass} +REVERSE {reverse.pass} +FUNCTION {bib.sort.order} +{ sort.label + " " + * + year field.or.null sortify + * + #1 entry.max$ substring$ + 'sort.key$ := +} +ITERATE {bib.sort.order} +SORT +FUNCTION {begin.bib} +{ preamble$ empty$ + 'skip$ + { preamble$ write$ newline$ } + if$ + "\begin{thebibliography}{" number.label int.to.str$ * "}" * + write$ newline$ + "\newcommand{\enquote}[1]{``#1''}" + write$ newline$ + "\providecommand{\natexlab}[1]{#1}" + write$ newline$ +} +EXECUTE {begin.bib} +EXECUTE {init.state.consts} +ITERATE {call.type$} +FUNCTION {end.bib} +{ newline$ + "\end{thebibliography}" write$ newline$ +} +EXECUTE {end.bib} +%% End of customized bst file +%% +%% End of file `mnwteststyle.bst'.