[PDF Download] Functional data structures in r: advanced statistical programming in r thomas mailund

Page 1


Visit to download the full and correct content document: https://textbookfull.com/product/functional-data-structures-in-r-advanced-statistical-pr ogramming-in-r-thomas-mailund/

More products digital (pdf, epub, mobi) instant download maybe you interests ...

Functional Data Structures in R: Advanced Statistical Programming in R Mailund

https://textbookfull.com/product/functional-data-structures-in-radvanced-statistical-programming-in-r-mailund/

Functional Programming in R: Advanced Statistical Programming for Data Science, Analysis and Finance 1st Edition Thomas Mailund

https://textbookfull.com/product/functional-programming-in-radvanced-statistical-programming-for-data-science-analysis-andfinance-1st-edition-thomas-mailund/

Domain Specific Languages in R Advanced Statistical Programming 1st Edition Thomas Mailund

https://textbookfull.com/product/domain-specific-languages-in-radvanced-statistical-programming-1st-edition-thomas-mailund/

Domain Specific Languages in R Advanced Statistical Programming 1st Edition Thomas Mailund

https://textbookfull.com/product/domain-specific-languages-in-radvanced-statistical-programming-1st-edition-thomas-mailund-2/

Metaprogramming in R: Advanced Statistical Programming for Data Science, Analysis and Finance 1st Edition

Thomas Mailund

https://textbookfull.com/product/metaprogramming-in-r-advancedstatistical-programming-for-data-science-analysis-andfinance-1st-edition-thomas-mailund/

Advanced Object-Oriented Programming in R: Statistical Programming for Data Science, Analysis and Finance 1st Edition Thomas Mailund

https://textbookfull.com/product/advanced-object-orientedprogramming-in-r-statistical-programming-for-data-scienceanalysis-and-finance-1st-edition-thomas-mailund/

Beginning Data Science in R: Data Analysis, Visualization, and Modelling for the Data Scientist 1st Edition Thomas Mailund

https://textbookfull.com/product/beginning-data-science-in-rdata-analysis-visualization-and-modelling-for-the-datascientist-1st-edition-thomas-mailund/

Pointers in C Programming A Modern Approach to Memory Management Recursive Data Structures Strings and Arrays

Thomas Mailund

https://textbookfull.com/product/pointers-in-c-programming-amodern-approach-to-memory-management-recursive-data-structuresstrings-and-arrays-thomas-mailund/

Advanced R Statistical Programming and Data Models: Analysis, Machine Learning, and Visualization 1st Edition Matt Wiley

https://textbookfull.com/product/advanced-r-statisticalprogramming-and-data-models-analysis-machine-learning-andvisualization-1st-edition-matt-wiley/

Functional Data Structures in R

Advanced Statistical Programming in R

Thomas Mailund

Functional Data Structures in R Advanced Statistical Programming in

R

Thomas Mailund

Functional Data Structures in R: Advanced Statistical Programming in R

ISBN-13 (pbk): 978-1-4842-3143-2

https://doi.org/10.1007/978-1-4842-3144-9

Library of Congress Control Number: 2017960831

Copyright © 2017 by Thomas Mailund

ISBN-13 (electronic): 978-1-4842-3144-9

This work is subject to copyright. All rights are reserved by the Publisher, whether the whole or part of the material is concerned, specifically the rights of translation, reprinting, reuse of illustrations, recitation, broadcasting, reproduction on microfilms or in any other physical way, and transmission or information storage and retrieval, electronic adaptation, computer software, or by similar or dissimilar methodology now known or hereafter developed.

Trademarked names, logos, and images may appear in this book. Rather than use a trademark symbol with every occurrence of a trademarked name, logo, or image we use the names, logos, and images only in an editorial fashion and to the benefit of the trademark owner, with no intention of infringement of the trademark.

The use in this publication of trade names, trademarks, service marks, and similar terms, even if they are not identified as such, is not to be taken as an expression of opinion as to whether or not they are subject to proprietary rights.

While the advice and information in this book are believed to be true and accurate at the date of publication, neither the authors nor the editors nor the publisher can accept any legal responsibility for any errors or omissions that may be made. The publisher makes no warranty, express or implied, with respect to the material contained herein.

Cover image by Freepik (www.freepik.com)

Managing Director: Welmoed Spahr

Editorial Director: Todd Green

Acquisitions Editor: Steve Anglin

Development Editor: Matthew Moodie

Technical Reviewer: Karthik Ramasubramanian

Coordinating Editor: Mark Powers

Copy Editor: Corbin P Collins

Distributed to the book trade worldwide by Springer Science+Business Media New York, 233 Spring Street, 6th Floor, New York, NY 10013. Phone 1-800-SPRINGER, fax (201) 348-4505, e-mail orders-ny@springer-sbm.com, or visit www.springeronline.com. Apress Media, LLC is a California LLC and the sole member (owner) is Springer Science + Business Media Finance Inc (SSBM Finance Inc). SSBM Finance Inc is a Delaware corporation.

For information on translations, please e-mail rights@apress.com, or visit www.apress.com/ rights-permissions.

Apress titles may be purchased in bulk for academic, corporate, or promotional use. eBook versions and licenses are also available for most titles. For more information, reference our Print and eBook Bulk Sales web page at www.apress.com/bulk-sales.

Any source code or other supplementary material referenced by the author in this book is available to readers on GitHub via the book's product page, located at www.apress.com/ 9781484231432. For more detailed information, please visit www.apress.com/source-code.

Printed on acid-free paper

Table of ConTenTs

Conclusions

Bibliography

About the Author

Thomas Mailund is an associate professor in bioinformatics at Aarhus University, Denmark. He has a background in math and computer science. For the last decade, his main focus has been on genetics and evolutionary studies, particularly comparative genomics, speciation, and gene flow between emerging species. He has published Beginning Data Science in R, Functional Programming in R, and Metaprogramming in R with Apress, as well as other books.

About the Technical Reviewer

Karthik Ramasubramanian works for one of the largest and fastest-growing technology unicorns in India, Hike Messenger, where he brings the best of business analytics and data science experience to his role. In his seven years of research and industry experience, he has worked on cross-industry data science problems in retail, e-commerce, and technology, developing and prototyping data-driven solutions. In his previous role at Snapdeal, one of the largest e-commerce retailers in India, he was leading core statistical modeling initiatives for customer growth and pricing analytics. Prior to Snapdeal, he was part of the central database team, managing the data warehouses for global business applications of Reckitt Benckiser (RB). He has vast experience working with scalable machine learning solutions for industry, including sophisticated graph network and self-learning neural networks. He has a master’s degree in theoretical computer science from PSG College of Technology, Anna University, and is a certified big data professional. He is passionate about teaching and mentoring future data scientists through different online and public forums. He enjoys writing poems in his leisure time and is an avid traveler.

Introduction

This book gives an introduction to functional data structures. Many traditional data structures rely on the structures being mutable. We can update search trees, change links in linked lists, and rearrange values in a vector. In functional languages, and as a general rule in the R programming language, data is not mutable. You cannot alter existing data. The techniques used to modify data structures to give us efficient building blocks for algorithmic programming cannot be used.

There are workarounds for this. R is not a pure functional language, and we can change variable-value bindings by modifying environments. We can exploit this to emulate pointers and implement traditional data structures this way; or we can abandon pure R programming and implement data structures in C/C++ with some wrapper code so we can use them in our R programs. Both solutions allow us to use traditional data structures, but the former gives us very untraditional R code, and the latter has no use for those not familiar with other languages than R.

The good news, though, is that we don’t have to reject R when implementing data structures if we are willing to abandon the traditional data structures instead. There are data structures that we can manipulate by building new versions of them rather than modifying them. These data structures, so-called functional data structures, are different from the traditional data structures you might know, but they are worth knowing if you plan to do serious algorithmic programming in a functional language such as R.

There are not necessarily drop-in replacements for all the data structures you are used to, at least not with the same runtime performance for their operations, but there are likely to be implementations for most

abstract data structures you regularly use. In cases where you might have to lose a bit of efficiency by using a functional data structures instead of a traditional one, however, you have to consider whether the extra speed is worth the extra time you have to spend implementing a data structure in exotic R or in an entirely different language.

There is always a trade-off when it comes to speed. How much programming time is a speed-up worth? If you are programming in R, chances are you value programmer-time over computer-time. R is a highlevel language and relatively slow compared to most other languages. There is a price to providing higher levels of expressiveness. You accept this when you choose to work with R. You might have to make the same choice when it comes to selecting a functional data structure over a traditional one, or you might conclude that you really do need the extra speed and choose to spend more time programming to save time when doing an analysis. Only you can make the right choice based on your situation. You need to find out the available choices to enable you to work data structures when you cannot modify them. InTroduCTIon

CHAPTER 1 Introduction

This book gives an introduction to functional data structures. Many traditional data structures rely on the structures being mutable. We can update search trees, change links in linked lists, and rearrange values in a vector. In functional languages, and as a general rule in the R programming language, data is not mutable. You cannot alter existing data. The techniques used to modify data structures to give us efficient building blocks for algorithmic programming cannot be used.

There are workarounds for this. R is not a pure functional language, and we can change variable-value bindings by modifying environments. We can exploit this to emulate pointers and implement traditional data structures this way; or we can abandon pure R programming and implement data structures in C/C++ with some wrapper code so we can use them in our R programs. Both solutions allow us to use traditional data structures, but the former gives us very untraditional R code, and the latter has no use for those not familiar with other languages than R.

The good news, however, is that we don’t have to reject R when implementing data structures if we are willing to abandon the traditional data structures instead. There are data structures we can manipulate by building new versions of them rather than modifying them. These data structures, so-called functional data structures, are different from the traditional data structures you might know, but they are worth knowing if you plan to do serious algorithmic programming in a functional language such as R.

© Thomas Mailund 2017

T. Mailund, Functional Data Structures in R, https://doi.org/10.1007/978-1-4842-3144-9_1

There are not necessarily drop-in replacements for all the data structures you are used to, at least not with the same runtime performance for their operations—but there are likely to be implementations for most abstract data structures you regularly use. In cases where you might have to lose a bit of efficiency by using a functional data structure instead of a traditional one, you have to consider whether the extra speed is worth the extra time you have to spend implementing a data structure in exotic R or in an entirely different language. There is always a trade-off when it comes to speed. How much programming time is a speed-up worth? If you are programming in R, the chances are that you value programmer time over computer time. R is a high-level language that is relatively slow compared to most other languages. There is a price to providing higher levels of expressiveness. You accept this when you choose to work with R. You might have to make the same choice when it comes to selecting a functional data structure over a traditional one, or you might conclude that you really do need the extra speed and choose to spend more time programming to save time when doing an analysis. Only you can make the right choice based on your situation. You need to find out the available choices to enable you to work data structures when you cannot modify them. Chapter 1 IntroduCtIon

CHAPTER 2 Abstract Data Structures

Before we get started with the actual data structures, we need to get some terminologies and notations in place. We need to agree on what an abstract data structure is—in contrast to a concrete one—and we need to agree on how to reason with runtime complexity in an abstract way.

If you are at all familiar with algorithms and data structures, you can skim quickly through this chapter. There won’t be any theory you are not already familiar with. Do at least skim through it, though, just to make sure we agree on the notation I will use in the remainder of the book.

If you are not familiar with the material in this chapter, I urge you to find a text book on algorithms and read it. The material I cover in this chapter should suffice for the theory we will need in this book, but there is a lot more to data structures and complexity than I can possibly cover in a single chapter. Most good textbooks on algorithms will teach you a lot more, so if this book is of interest, you should not find any difficulties in continuing your studies.

© Thomas Mailund 2017

T. Mailund, Functional Data Structures in R, https://doi.org/10.1007/978-1-4842-3144-9_2

Structure on Data

As the name implies, data structures have something to do with structured data. By data, we can just think of elements from some arbitrary set. There might be some more structure to the data than the individual data points, and when there is we keep that in mind and will probably want to exploit that somehow. However, in the most general terms, we just have some large set of data points.

So, a simple example of working with data would be imagining we have this set of possible values—say, all possible names of students at a university—and I am interested in a subset—for example, the students that are taking one of my classes. A class would be a subset of students, and I could represent it as the subset of student names. When I get an email from a student, I might be interested in figuring out if it is from one of my students, and in that case, in which class. So, already we have some structure on the data. Different classes are different subsets of student names. We also have an operation we would like to be able to perform on these classes: checking membership.

There might be some inherent structure to the data we work with, which could be properties such as lexicographical orders on names—it enables us to sort student names, for example. Other structure we add on top of this. We add structure by defining classes as subsets of student names. There is even a third level of structure: how we represent the classes on our computer.

The first level of structure—inherent in the data we work with—is not something we have much control over. We might be able to exploit it in various ways, but otherwise, it is just there. When it comes to designing algorithms and data structures, this structure is often simple information; if there is order in our data, we can sort it, for example. Different algorithms and different data structures make various assumptions about the underlying data, but most general algorithms and data structures make few assumptions. When I make assumptions in this book, I will make those assumptions explicit. Chapter 2 abstraCt Data struCtures

The second level of structure—the structure we add on top of the universe of possible data points—is information in addition to what just exists out there in the wild; this can be something as simple as defining classes as subsets of student names. It is structure we add to data for a purpose, of course. We want to manipulate this structure and use it to answer questions while we evaluate our programs. When it comes to algorithmic theory, what we are mainly interested in at this level is which operations are possible on the data. If we represent classes as sets of student names, we are interested in testing membership to a set. To construct the classes, we might also want to be able to add elements to an existing set. That might be all we are interested in, or we might also want to be able to remove elements from a set, get the intersection or union of two sets, or do any other operation on sets.

What we can do with data in a program is largely defined by the operations we can do on structured data; how we implement the operations is less important. That might affect the efficiency of the operations and thus the program, but when it comes to what is possible to program and what is not—or what is easy to program and what is hard, at least—it is the possible operations that are important.

Because it is the operations we can do on data, and now how we represent the data—the third level of structure we have—that is most important, we distinguish between the possible operations and how they are implemented. We define abstract data structures by the operations we can do and call different implementations of them concrete data structures. Abstract data structures are defined by which operations we can do on data; concrete data structures, by how we represent the data and implement these operations. Chapter 2 abstraCt

Abstract Data Structures in R

If we define abstract data structures by the operations they provide, it is natural to represent them in R by a set of generic functions. In this book, I will use the S3 object system for this.1

Let’s say we want a data structure that represents sets, and we need two operations on it: we want to be able to insert elements into the set, and we want to be able to check if an element is found in the set. The generic interface for such a data structure could look like this:

insert <- function(set, elem) UseMethod("insert") member <- function(set, elem) UseMethod("member")

Using generic functions, we can replace one implementation with another with little hassle. We just need one place to specify which concrete implementation we will use for an object we will otherwise only access through the abstract interface. Each implementation we write will have one function for constructing an empty data structure. This empty structure sets the class for the concrete implementation, and from here on we can access the data structure through generic functions. We can write a simple list-based implementation of the set data structure like this:

empty_list_set <- function() { structure(c(), class = "list_set") }

insert.list_set <- function(set, elem) { structure(c(elem, set), class = "list_set") }

1If you are unfamiliar with generic functions and the S3 system, you can check out my book Advanced Object-Oriented Programming in R book (Apress, 2017), where I explain all this. Chapter 2 abstraCt

member.list_set <- function(set, elem) { elem %in% set }

The empty_list_set function is how we create our first set of the concrete type. When we insert elements into a set, we also get the right type back, but we shouldn’t call insert.list_set directly. We should just use insert and let the generic function mechanism pick the right implementation. If we make sure to make the only point where we refer to the concrete implementation be the creation of the empty set, then we make it easier to replace one implementation with another:

s <- empty_list_set() member(s, 1) ## [1] FALSE

s <- insert(s, 1) member(s, 1) ## [1] TRUE

When we implement data structures in R, there are a few rules of thumb we should follow, and some are more important than others. Using a single “empty data structure” constructor and otherwise generic interfaces is one such rule. It isn’t essential, but it does make it easier to work with abstract interfaces.

More important is this rule: keep modifying and querying a data structure as separate functions. Take an operation such as popping the top element of a stack. You might think of this as a function that removes the first element of a stack and then returns the element to you. There is nothing wrong with accessing a stack this way in most languages, but in functional languages, it is much better to split this into two different operations: one for getting the top element and another for removing it from the stack. Chapter 2 abstraCt Data

The reason for this is simple: our functions can’t have side effects. If a “pop” function takes a stack as an argument, it cannot modify this stack. It can give you the top element of the stack, and it can give you a new stack where the top element is removed, but it cannot give you the top element and then modify the stack as a side effect. Whenever we want to modify a data structure, what we have to do in a functional language, is to create a new structure instead. And we need to return this new structure to the caller. Instead of wrapping query answers and new (or “modified”) data structures in lists so we can return multiple values, it is much easier to keep the two operations separate.

Another rule of thumb for interfaces that I will stick to in this book, with one exception, is that I will always have my functions take the data structure as the first argument. This isn’t something absolutely necessary, but it fits the convention for generic functions, so it makes it easier to work with abstract interfaces, and even when a function is not abstract—when I need some helper functions—remembering that the first argument is always the data structure is easier. The one exception to this rule is the construction of linked lists, where tradition is to have a construction function, cons, that takes an element as its first argument and a list as its second argument and construct a new list where the element is put at the head of the list. This construction is too much of a tradition for me to mess with, and I won’t write a generic function of it, so it doesn’t come into conflict with how we handle polymorphism.

Other than that, there isn’t much more language mechanics to creating abstract data structures. All operations we define on an abstract data structure have some intended semantics to them, but we cannot enforce this through the language; we just have to make sure that the operations we implement actually do what they are supposed to do. Chapter 2 abstraCt Data struCtures

Chapter 2 abstraCt Data struCtures

Implementing Concrete Data Structures in R

When it comes to concrete implementations of data structures, there are a few techniques we need in order to translate the data structure designs into R code. In particular, we need to be able to represent what are essentially pointers, and we need to be able to represent empty data structures. Different programming languages will have different approaches to these two issues. Some allow the definition of recursive data types that naturally handle empty data structures and pointers, others have unique values that always represent “empty,” and some have static type systems to help. We are programming in R, though, so we have to make it work here.

For efficient data structures in functional programming, we need recursive data types, which essentially boils down to representing pointers. R doesn’t have pointers, so we need a workaround. That workaround is using lists to define data structures and using named elements in lists as our pointers.

Consider one of the simplest data structures known to man: the linked list. If you are not familiar with linked lists, you can read about them in the next chapter, where I consider them in some detail. In short, linked lists consist of a head—an element we store in the list—and a tail—another list, one item shorter. It is a recursive definition that we can write like this:

LIST = EMPTY | CONS(HEAD, LIST)

Here EMPTY is a special symbol representing the empty list, and CONS—a traditional name for this, from the Lisp programming language—a symbol that constructs a list from a HEAD element and a tail that is another LIST. The definition is recursive—it defines LIST in terms of a tail that is also a LIST—and this in principle allows lists to be infinitely long. In practice, a list will eventually end up at EMPTY.

Chapter 2 abstraCt Data struCtures

We can construct linked lists in R using R’s built-in list data structure. That structure is not a linked list; it is a fixed-size collection of elements that are possibly named. We exploit named elements to build pointers. We can implement the CONS construction like this:

linked_list_cons <- function(head, tail) { structure(list(head = head, tail = tail), class = "linked_list_set") }

We just construct a list with two elements, head and tail. These will be references to other objects—head to the element we store in the list, and tail to the rest of the list—so we are in effect using them as pointers. We then add a class to the list to make linked lists work as an implementation of an abstract data structure.

Using classes and generic functions to implement polymorphic abstract data structures leads us to the second issue we need to deal with in R. We need to be able to represent empty lists. The natural choice for an empty list would be NULL, which represents “nothing” for the built-in list objects, but we can’t get polymorphism to work with NULL. We can’t give NULL a class. We could, of course, still work with NULL as the empty list and just have classes for non-empty lists, but this clashes with our desire to have the empty data structures being the one point where we decide concrete data structures instead of just accessing them through an abstract interface. If we didn’t give empty data structures a type, we would need to use concrete update functions instead. That could make switching between different implementations cumbersome. We really do want to have empty data structures with classes.

The trick is to use a sentinel object to represent empty structures. Sentinel objects have the same structure as non-empty data structure objects—which has the added benefit of making some implementations easier to write—but they are recognized as representing “empty.” We construct a sentinel as we would any other object, but we remember it

Chapter 2 abstraCt Data struCtures

for future reference. When we create an empty data structure, we always return the same sentinel object, and we have a function for checking emptiness that examines whether its input is identical to the sentinel object. For linked lists, this sentinel trick would look like this: linked_list_nil <- linked_list_cons(NA, NULL) empty_linked_list_set <- function() linked_list_nil is_empty.linked_list_set <- function(x) identical(x, linked_list_nil)

The is_empty function is a generic function that we will use for all data structures.

The identical test isn’t perfect. It will consider any list element containing NA as the last item in a list as the sentinel. Because we don’t expect anyone to store NA in a linked list—it makes sense to have missing data in a lot of analysis, but rarely does it make sense to store it in data structures—it will have to do.

Using a sentinel for empty data structures can also occasionally be useful for more than dispatching on generic functions. Sometimes, we actually want to use sentinels as proper objects, because it simplifies certain functions. In those cases, we can end up with associating meta-data with “empty” sentinel objects. We will see examples of this when we implement red-black search trees. If we do this, then checking for emptiness using identical will not work. If we modify a sentinel to change metainformation, it will no longer be identical to the reference empty object. In those cases, we will use other approaches to testing for emptiness.

Asymptotic Running Time

Although the operations we define in the interface of an abstract data type determine how we can use these in our programs, the efficiency of our programs depends on how efficient the data structure operations are.

Chapter 2 abstraCt Data struCtures

Because of this, we often consider the time efficiency part of the interface of a data structure—if not part of the abstract data structure, we very much care about it when we have to pick concrete implementations of data structures for our algorithms.

When it comes to algorithmic performance, the end goal is always to reduce wall time—the actual time we have to wait for a program to finish. But this depends on many factors that cannot necessarily know about when we design our algorithms. The computer the code will run on might not be available to us when we develop our software, and both its memory and CPU capabilities are likely to affect the running time significantly. The running time is also likely to depend intimately on the data we will run the algorithm on. If we want to know exactly how long it will take to analyze a particular set of data, we have to run the algorithm on this data. Once we have done this, we know exactly how long it took to analyze the data, but by then it is too late to explore different solutions to do the analysis faster.

Because we cannot practically evaluate the efficiency of our algorithms and data structures by measuring the running time on the actual data we want to analyze, we use different techniques to judge the quality of various possible solutions to our problems.

One such technique is the use of asymptotic complexity, also known as big-O notation. Simply put, we abstract away some details of the running time of different algorithms or data structure operations and classify their runtime complexity according to upper bounds known up to a constant.

First, we reduce our data to its size. We might have a set with n elements, or a string of length n. Although our data structures and algorithms might use very different actual wall time to work on different data of the same size, we care only about the number n and not the details of the data. Of course, data of the same size is not all equal, so when we reduce all our information about it to a single size, we have to be a little careful about what we mean when we talk about the algorithmic complexity of a problem. Here, we usually use one of two approaches: we speak of the worst-case or the average/expected complexity. The worst-case

runtime complexity of an algorithm is the longest running time we can expect from it on any data of size n. The expected runtime complexity of an algorithm is the mean running time for data of size n, assuming some distribution over the possible data.

Second, we do not consider the actual running time for data of size n—where we would need to know exactly how many operations of different kinds would be executed by an algorithm, and how long each kind of operation takes to execute. We just count the number of operations and consider them equal. This gives us some function of n that tells us how many operations an algorithm or operation will execute, but not how long each operation takes. We don’t care about the details when comparing most algorithms because we only care about asymptotic behavior when doing most of our algorithmic analysis.

By asymptotic behavior, I mean the behavior of functions when the input numbers grow large. A function f (n) is an asymptotic upper bound for another function g (n) if there exists some number N such that g (n) ≤ f (n) whenever n > N. We write this in big-O notation as g (n) ∈ O( f (n)) or g(n) = O( f (n)) (the choice of notation is a little arbitrary and depends on which textbook or reference you use).

The rationale behind using asymptotic complexity is that we can use it to reason about how algorithms will perform when we give them larger data sets. If we need to process data with millions of data points, we might be about to get a feeling for their running time through experiments with tens or hundreds of data points, and we might conclude that one algorithm outperforms another in this range. But that does not necessarily reflect how the two algorithms will compare for much larger data. If one algorithm is asymptotically faster than another, it will eventually outperform the other—we just have to get to the point where n gets large enough.

A third abstraction we often use is to not be too concerned with getting the exact number of operations as a function of n correct. We just want an upper bound. The big-O notation allows us to say that an algorithm Chapter 2 abstraCt

Chapter 2 abstraCt Data struCtures

runs in any big-O complexity that is an upper bound for the actual runtime complexity. We want to get this upper bound as exact as we can, to properly evaluate different choices of algorithms, but if we have upper and lower bounds for various algorithms, we can still compare them. Even if the bounds are not tight, if we can see that the upper bound of one algorithm is better than the lower bound of another, we can reason about the asymptotic running time of solutions based on the two.

To see the asymptotic reasoning in action, consider the set implementation we wrote earlier:

empty_list_set <- function() { structure(c(), class = "list_set") }

insert.list_set <- function(set, elem) { structure(c(elem, set), class = "list_set") }

member.list_set <- function(set, elem) { elem %in% set }

It represents the set as a vector, and when we add elements to the set, we simply concatenate the new element to the front of the existing set. Vectors, in R, are represented as contiguous memory, so when we construct new vectors this way, we need to allocate a block of memory to contain the new vector, copy the first element into the first position, and then copy the entire old vector into the remaining positions of the new vector. Inserting an element into a set of size n, with this implementation, will take time O(n)—we need to insert n+1 set elements into newly allocated blocks of memory. Growing a set from size 0 to size n by repeatedly inserting elements will take time O(n2).

The membership test, elem %in% set, runs through the vector until it either sees the value elem or reaches the end of the vector. The best case

Chapter 2 abstraCt Data struCtures

would be to see elem at the beginning of the vector, but if we consider worst-case complexity, this is another O(n) runtime operation.

As an alternative implementation, consider linked lists. We insert elements in the list using the cons operation, and we check membership by comparing elem with the head of the list. If the two are equal, the set contains the element. If not, we check whether elem is found in the rest of the list. In a pure functional language, we would use recursion for this search, but here I have just implemented it using a while loop:

insert.linked_list_set <- function(set, elem) { linked_list_cons(elem, set) }

member.linked_list_set <- function(set, elem) { while (!is_empty(set)) { if (set$head == elem) return(TRUE) set <- set$tail } return(FALSE) }

The insert operation in this implementation takes constant time. We create a new list node and set the head and tail in it, but unlike the vector implementation, we do not copy anything. For the linked list, inserting elements is an O(1) operation. The membership check, though, still runs in O(n) because we still do a linear search.

Experimental Evaluation of Algorithms

Analyzing the asymptotic performance of algorithms and data structures is the only practical approach to designing programs that work on very large data, but it cannot stand alone when it comes to writing efficient code. Some experimental validation is also needed. We should always

Chapter 2 abstraCt Data struCtures

perform experiments with implementations to 1) be informed about the performance constants hidden beneath the big-O notation, and 2) to validate that the performance is as we expect it to be.

For the first point, remember that just because two algorithms are in the same big-O category—say, both are in O(n2)—that doesn’t mean they have the same wall-time performance. It means that both algorithms are asymptotically bounded by some function c⋅n2 where c is a constant. Even if both are running in quadratic time, so that the upper bound is actually tight, they could be bounded by functions with very different constants. They may have the same asymptotic complexity, but in practice, one could be much faster than the other. By experimenting with the algorithms, we can get a feeling, at least, for how the algorithms perform in practice.

Experimentation also helps us when we have analyzed the worst case asymptotic performance of algorithms, but where the data we actually want to process is different from the worst possible data. If we can create samples of data that resemble the actual data we want to analyze, we can get a feeling for how close it is to the worst case, and perhaps find that an algorithm with worse worst case performance actually has better average case performance.

As for point number two for why we want to experiment with algorithms, it is very easy to write code with a different runtime complexity than we expected, either because of simple bugs or because we are programming in R, a very high-level language, where language constructions potentially hide complex operations. Assigning to a vector, for example, is not a simple constant time operation if more than one variable refers to the vector. Assignment to vector elements potentially involves copying the entire vector. Sometimes it is a constant time operation; sometimes it is a linear time operation. We can deduce what it will be by carefully reading the code, but it is human to err, so it makes sense always to validate that we have the expected complexity by running experiments.

Chapter 2 abstraCt Data struCtures

In this book, I will use the microbenchmark package to run performance experiments. This package lets us run a number of executions of the same operation and get the time it takes back in nanoseconds. I don’t need that fine a resolution, but it is nice to be able to get a list of time measurements. I collect the results in a tibble data frame from which I can summarize the results and plot them later. The code I use for my experiments is as follows:

library(tibble)

library(microbenchmark)

get_performance_n <- function( algo , n , setup , evaluate , times , ...) {

config <- setup(n)

benchmarks <- microbenchmark(evaluate(n, config), times = times)

tibble(algo = algo, n = n, time = benchmarks$time / 1e9) # time in sec }

get_performance <- function( algo , ns , setup , evaluate , times = 10 , ...) {

f <- function(n)

get_performance_n(algo, n, setup, evaluate, times = times, ...)

results <- Map(f, ns) do.call('rbind', results) }

The performance experiment functions let me specify a function for setting up an experiment and another for running the experiment. If I want to evaluate the time it takes to construct a set of the numbers from one up to n, I can use the setup function to choose the implementation—based on their respective empty structures—and I can construct the sets in the evaluate function:

setup <- function(empty) function(n) empty evaluate <- function(n, empty) { set <- empty elements <- sample(1:n) for (elm in elements) { set <- insert(set, elm) } }

ns <- seq(1000, 5000, by = 500)

performance <- rbind( get_performance("list()", ns, setup(empty_list_set()), evaluate), get_performance("linked list", ns, setup(empty_linked_list_set()), evaluate) )

I permute the elements I insert in the sets to avoid any systematic bias in how the data is added to the sets. There isn’t any with the two implementations we have here, but for many data structures there are, so

Chapter 2 abstraCt Data str uCtures

this is a way of getting an average case complexity instead of a best-case or worst-case performance.

Running the performance measuring code with these two functions and the two set implementations, I get the results I have plotted in Figure 2-1: library(ggplot2)

ggplot(performance, aes(x = n, y = time, colour = algo)) + geom_jitter() + geom_smooth(method = "loess", span = 2, se = FALSE) + scale_colour_grey("Data structure", end = 0.5) + xlab(quote(n)) + ylab("Time (sec)") + theme_minimal()

In this figure, we can see what we expected from the asymptotic runtime analysis. The two approaches are not that different for small sets, but as the size of the data grows, the list implementation takes relatively longer to construct a set than the linked list implementation.

Figure 2-1. Direct comparison of the two set construction implementations

Another random document with no related content on Scribd:

administer such an oath, but must send for a magistrate competent for the purpose. Unfortunately for him, the impeachment of Judge Pickering was a precedent directly opposed to this doctrine. He was compelled to submit while the Senate unwillingly took the forms of a court.

Giles’s view of impeachment, which was the same with that of Randolph, had the advantage of being clear and consistent. The opposite extreme, afterward pressed by Luther Martin and his associate counsel for the defence, restricted impeachment to misdemeanors indictable at law,—a conclusion not to be resisted if the words of the Constitution were to be understood in a legal sense. Such a rule would have made impeachment worthless for many cases where it was likely to be most needed; for comparatively few violations of official duty, however fatal to the State, could be brought within this definition. Giles might have quoted Madison in support of the broader view; and if Madison did not understand the Constitution, any other Virginian might be excused for error. So far back as the year 1789, when Congress began to discuss the President’s powers, Madison said: “I contend that the wanton removal of meritorious officers would subject him to impeachment and removal from his own high trust.” Such a misdemeanor was certainly not indictable, and could not technically be brought within the words of the Constitution; it was impeachable only on Giles’s theory.

The Senate became confused between these two views, and never knew on what theory it acted. Giles failed to take from its proceedings the character of a court of justice; but though calling itself a court of justice, it would not follow strict rules of law. The result was a nondescript court, neither legal nor political, making law and voting misdemeanors for itself as it went, and stumbling from one inconsistency to another.

The managers added to the confusion. They put forward no steady theory of their own as to the nature of impeachment; possibly differing in opinion, they intentionally allotted different lines of argument to each. In opening the case, Feb. 20, 1805, one of the managers, George W. Campbell of Tennessee, took the ground that “misdemeanor” in the Constitution need imply no criminality.

“Impeachment,” said he, “according to the meaning of the Constitution, may fairly be considered a kind of inquest into the conduct of an officer merely as it regards his office.... It is more in the nature of a civil investigation than of a criminal prosecution.” Such seemed to be the theory of the managers and of the House; for although the articles of impeachment reported by Randolph in March, 1804, had in each case alleged acts which were inspired by an evil intent to oppress the victim or to excite odium against the Government, and were at least misdemeanors in the sense of misbehavior, Randolph at the last moment slipped into the indictment two new articles, one of which alleged no evil intent at all, while both alleged, at worst, errors in law such as every judge in the United States had committed. Article V. charged that Chase had issued a capias against Callender, when the law of Virginia required a summons to appear at the next court. Article VI. charged that he had, “with intent to oppress,” held Callender for trial at once, contrary to the law of Virginia. Every judge on the Supreme Bench had ruled that United States courts were not bound to follow the processes of the State courts; Chief-Justice Marshall himself, as Giles threatened, must be the first victim if such an offence were a misdemeanor in constitutional law.

That a judge was impeachable for a mistake in declaring the law seemed therefore to be settled, so far as the House and its managers could decide the point. Judge Chase’s counsel assumed that this principle, which had been so publicly proclaimed, was seriously meant; and one after another dwelt on the extravagance of the doctrine that a civil officer should be punished for mere error of judgment. In reply, Joseph H. Nicholson, Randolph’s closest ally, repudiated the theory on which he had himself acted in Pickering’s case, and which Giles, Randolph, and Campbell pressed; he even denied having heard such ground taken as that an impeachment was a mere inquest of office:—

“For myself, I am free to declare that I heard no such position taken If declarations of this kind have been made, in the name of the managers I here disclaim them We do contend that this is a criminal prosecution for offences committed in the discharge of high official duties, and we now support it, not merely for the purpose of

removing an individual from office, but in order that the punishment inflicted on him may deter others from pursuing the baneful example which has been set them ”

The impeachment, then, was a criminal prosecution, and the Senate was a criminal court; yet no offence was charged which the law considered a misdemeanor, while error of judgment, with no imputed ill-intent, was alleged as a crime.

Staggering under this load of inconsistencies, uncertain what line of argument to pursue, and ignorant whether the Senate would be ruled by existing law or invent a system of law of its own, the managers, Feb. 9, 1805, appeared in the Senate chamber to open their case and produce their witnesses. Upon the popular imagination of the day the impeachment of Warren Hastings had taken deep hold. Barely ten years had passed since the House of Lords rendered its judgment in that famous case; and men’s minds were still full of associations with Westminster Hall. The impeachment of Judge Chase was a cold and colorless performance beside the melodramatic splendor of Hastings’s trial; but in the infinite possibilities of American democracy, the questions to be decided in the Senate chamber had a weight for future ages beyond any that were then settled in the House of Lords. Whether Judge Chase should be removed from the bench was a trifling matter; whether Chief-Justice Marshall and the Supreme Court should hold their power and principles against this combination of State-rights conservatives and Pennsylvania democrats was a subject for grave reflection. Men who did not see that the tide of political innovation had long since turned, and that the French revolution was no longer raging, were consumed with anxiety for the fate of Chase, and not wholly without reason; for had Marshall been a man of less calm and certain judgment, a single mistake by him might easily have prostrated the judiciary at the feet of partisans.

By order of the Vice-President the Senate chamber was arranged in accordance with his ideas of what suited so grave an occasion. His own chair stood, like that of the chief-justice in the court-room, against the wall, and on its right and left crimson benches extended like the seats of associate judges, to accommodate the thirty-four

senators, who were all present. In front of the Vice-President, on the right, a box was assigned to the managers; on the left, a similar box was occupied by Justice Chase and his counsel. The rest of the floor was given to members of the House, foreign ministers, and other official persons. Behind these a new gallery was erected especially for ladies, and at each end of this temporary gallery boxes were reserved for the wives and families of public officers. The upper and permanent gallery was public. The arrangement was a mimic reproduction of the famous scene in Westminster Hall; and the little society of Washington went to the spectacle with the same interest and passion which had brought the larger society of London to hear the orations of Sheridan and Burke.

Before this audience Justice Chase at last appeared with his array of counsel at his side,—Luther Martin, Robert Goodloe Harper, Charles Lee, Philip Barton Key, and Joseph Hopkinson. In such a contest weakness of numbers was one element of strength; for the mere numbers of Congressmen served only to rouse sympathy for the accused. The contest was unequal in another sense, for the intellectual power of the House was quite unable on the field of law to cope with the half-dozen picked and trained champions who stood at the bar. Justice Chase alone was a better lawyer than any in Congress; Luther Martin could easily deal with the whole box of managers; Harper and Lee were not only lawyers, but politicians; and young Hopkinson’s genius was beyond his years.

In the managers’ box stood no lawyer of corresponding weight. John Randolph, who looked upon the impeachment as his personal act, was not only ignorant of law, but could not work by legal methods. Joseph H. Nicholson and Cæsar A. Rodney were more formidable; but neither of them would have outweighed any single member of Chase’s counsel. The four remaining managers, all Southern men, added little to the strength of their associates. John Boyle of Kentucky lived to become chief-justice of that State, and was made district judge of the United States by a President who was one of the Federalist senators warmly opposed to the impeachment. George Washington Campbell of Tennessee lived to be a senator, Secretary of the Treasury, and minister to Russia. Peter Early of

Georgia became a judge on the Supreme Bench of his own State. Christopher Clark of Virginia was chosen only at the last moment to take the place of Roger Nelson of Maryland, who retired. None of them rose much above the average level of Congress; and Chase’s counsel grappled with them so closely, and shut them within a field so narrow, that no genius could have found room to move. From the moment that the legal and criminal character of impeachment was conceded, Chase’s counsel dragged them hither and thither at will.

Feb. 9, 1805, the case was opened by John Randolph. Randolph claimed to have drawn all the articles of impeachment with his own hand. If any one understood their character, it was he; and the respondent’s counsel naturally listened with interest for Randolph’s explanation or theory of impeachment, and for the connection he should establish between his theory and his charges. These charges were numerous, but fell under few heads. Of the eight articles which Randolph presented, the first concerned the judge’s conduct at the trial of John Fries for treason in Philadelphia in 1800; the five following articles alleged a number of offences committed during the trial of James Thompson Callender for libel at Richmond in that year; Article VII. charged as a misdemeanor the judge’s refusal, in the same year, to dismiss the grand jury in Delaware before indicting a seditious printer; finally, Article VIII. complained of the judge’s harangue to the grand jury at Baltimore in May, 1803, which it characterized as “highly indecent, extrajudicial, and tending to prostitute the high judicial character with which he was invested to the low purpose of an electioneering partisan.”

Serious as some of these charges certainly were,—for in the case of Callender, even more than in that of Fries, Chase’s temper had led him to strain, if not to violate, the law,—none of the articles alleged an offence known to the statute-books or the common law; and Randolph’s first task was to show that they could be made the subject of impeachment, that they were high crimes and misdemeanors in the sense of the Constitution, or that in some sense they were impeachable. Instead of arguing this point, he contented himself by declaring the theory of the defence to be monstrous. His speech touched the articles, one by one, adding little

to their force, but piling one mistake on another in its assertions of fact and assumptions of law.

Ten days passed in taking evidence before the field was cleared and the discussion began. Then, Feb. 20, 1805, Early and Campbell led for the managers in arguments which followed more or less closely in Randolph’s steps, inferring criminality in the accused from the manifest tenor of his acts. Campbell ventured to add that he was not obliged to prove the accused to have committed any crime known to the law,—it was enough that he had transgressed the line of official duty with corrupt motives; but this timid incursion into the field of the Constitution was supported by no attempt at argument. “I lay it down as a settled rule of decision,” said he, “that when a man violates a law or commits a manifest breach of his duty, an evil intent or corrupt motive must be presumed to have actuated his conduct.”

Joseph Hopkinson opened for the defence. Friends and enemies joined in applauding the vigor of this young man’s attack. The whole effort of Chase’s counsel was to drive the impeachers within the limits of law, and compel them to submit to the restrictions of legal methods. Hopkinson struck into the heart of the question. He maintained that under the Constitution no judge could be lawfully impeached or removed from office for any act or offence for which he could not be indicted; “misdemeanor,” he argued, was a technical term well understood and defined, which meant the violation of a public law, and which, when occurring in a legal instrument like the Constitution, must be given its legal meaning. After stating this proposition with irresistible force, he dealt with Article I. of the impeachment, which covered the case of Fries, and shook it to pieces with skill very unlike the treatment of Early and Campbell. Barton Key next rose, and dealt with Articles II., III., and IV., covering part of Callender’s case; he was followed by Charles Lee, who succeeded in breaking down Randolph’s interpolated Articles V. and VI. Then Luther Martin appeared on the scene, and the audience felt that the managers were helpless in his hands.

This extraordinary man—“unprincipled and impudent Federalist bulldog,” as Jefferson called him—revelled in the pleasure of a fight with democrats. The bar of Maryland felt a curious mixture of pride

and shame in owning that his genius and vices were equally remarkable. Rough and coarse in manner and expression, verbose, often ungrammatical, commonly more or less drunk, passionate, vituperative, gross, he still had a mastery of legal principles and a memory that overbalanced his faults, an audacity and humor that conquered ill-will. In the practice of his profession he had learned to curb his passions until his ample knowledge had time to give the utmost weight to his assaults. His argument at Chase’s trial was the climax of his career; but such an argument cannot be condensed in a paragraph. Its length and variety defied analysis within the limits of a page, though its force made other efforts seem unsubstantial.

Martin covered the same ground that his associates had taken before him, dwelling earnestly on the contention that an impeachable offence must be also indictable. Harper followed, concluding the argument for the defence, and seeming to go beyond his associates in narrowing the field of impeachment; for he argued that it was a criminal prosecution, which must be founded on some wilful violation of a known law of the land,—a line of reasoning which could end only in requiring the violation of an Act of Congress. This theory did not necessarily clash with that of Martin. No hesitation or inconsistency was shown on the side of the defence; every resource of the profession was used with energy and skill.

The managers then put forward their best pleaders; for they had need of all their strength. Nicholson began by disavowing the idea that impeachment was a mere inquest of office; this impeachment was, he said, a criminal prosecution intended not merely to remove, but to punish, the offender. On the other hand, he maintained that since judges held their commissions during good behavior, and could be removed only by impeachment, the Constitution must have intended that any act of misbehavior should be considered a misdemeanor. He showed the absurdities which would rise from construing the Constitution in a legal sense. His argument, though vigorous and earnest, and offering the advantages of a plausible compromise between two extreme and impracticable doctrines, yet evidently strained the language of the Constitution and disregarded law. As Nicholson himself said, he discarded legal usage: “In my

judgment the Constitution of the United States ought to be expounded upon its own principles, and foreign aid ought never to be called in. Our Constitution was fashioned after none other in the known world; and if we understand the language in which it is written, we require no assistance in giving it a true exposition.” He wanted a construction “purely and entirely American.” In the mouth of a strict constructionist this substitution of the will of Congress for the settled rules of law had as strange a sound as Luther Martin could have wished, and offered another example of the instinct, so striking in the Louisiana debate, which not even Nicholson, Randolph, or Jefferson himself could always resist.

Rodney, the same day, followed Nicholson; and as though not satisfied with his colleague’s theory, did what Nicholson, in the name of all the managers, had a few hours before expressly disclaimed,— he adopted and pressed Giles’s theory of impeachment with all the precision of language he could command. Nicholson seemed content to assume impeachment as limited to “treason, bribery, or other high crimes and misdemeanors;” but in his view misbehavior might be construed as a misdemeanor in a “purely and entirely American” sense. Rodney was not satisfied with this argument, and insisted that the Constitution imposed no limit on impeachment.

“Is there a word in the whole sentence,” he asked, “which expresses an idea, or from which any fair inference can be drawn, that no person shall be impeached but for ‘treason, bribery, or other high crimes and misdemeanors?’... From the most cursory and transient view of this passage I submit with due deference that it must appear very manifest that there are other cases than those here specified for which an impeachment will lie and is the proper remedy.”

The judges held their offices during good behavior; the instant a judge should behave ill his office became forfeited. To ascertain the fact “officially, or rather judicially,” impeachment was provided; the authority of the Senate was therefore coextensive with the complaint.

Rodney stated this principle broadly, but did not rest upon it; on the contrary, he accepted the respondent’s challenge, and undertook to show that Chase had been guilty of crimes and misdemeanors in the technical sense of the term. Probably he was wise in choosing

this alternative; for no one could doubt that his constitutional doctrine was one into which Chase’s counsel were sedulously trying to drive him. If Rodney was right, the Senate was not a court of justice, and should discard judicial forms. Giles had seen this consequence of the argument, and had acted upon it, until beaten by its inevitable inconsistencies; at least sixteen senators were willing to accept the principle, and to make of impeachment an “official, or rather judicial,” inquest of office. Judge Chase’s counsel knew also that some halfdozen Republican senators feared to allow a partisan majority in the Senate to decide, after the fact, that such or such a judicial opinion had forfeited the judge’s seat on the bench. This practice could end only in making the Senate, like the House of Lords, a court of last appeal. Giles threatened to impeach Marshall and the whole Supreme Court on Rodney’s theory; and such a threat was as alarming to Dr. Mitchill of New York, or Senator Bradley of Vermont, as it was to Pickering and Tracy.

When Rodney finished, the theory of impeachment was more perplexed than ever, and but one chance remained to clear it. All the respondent’s counsel had spoken in their turn; all the managers had expounded their theories: John Randolph was to close. Randolph was an invalid, overwhelmed by work and excitement, nervous, irritable, and not to be controlled. When he appeared in the box, Feb. 27, 1805, he was unprepared; and as he spoke, he not only made his usual long pauses for recollection, but continually complained of having lost his notes, of his weakness, want of ability, and physical as well as moral incompetence. Such expressions in the mouths of other men might have passed for rhetoric; but Randolph’s speech showed that he meant all he said. He too undertook to answer the argument of Luther Martin, Harper, and Hopkinson on the nature of impeachment; but he answered without understanding it,—calling it “almost too absurd for argument,” “a monstrous pretension,” “a miserable quibble,” but advancing no theory of his own, and supporting neither Campbell’s, Nicholson’s, nor Rodney’s opinion. After a number of arguments which were in no sense answers, he said he would no longer worry the good sense of the Court by combating such a claim,—a claim which the best lawyers in America

affirmed to be sound, and the two ablest of the managers had exhausted themselves in refuting.

Randolph’s closing speech was overcharged with vituperation and with misstatements of fact and law, but was chiefly remarkable on account of the strange and almost irrational behavior of the speaker. Randolph’s tall, thin figure, his penetrating eyes and shrill voice, were familiar to the society of Washington, and his violence of manner in the House only a short time before, in denouncing Granger and the Yazoo men, had prepared his audience for some eccentric outburst; but no one expected to see him, “with much distortion of face and contortion of body, tears, groans, and sobs,” break down in the middle of his self-appointed task, and congratulate the Senate that this was “the last day of my sufferings and of yours.”[143]

The next day the Senate debated the form of its final judgment. [144] Bayard moved that the question should be put: “Is Samuel Chase guilty or not guilty of a high crime or misdemeanor as charged in the article just read?” The point was vital; for if this form should be adopted, the Senate returned to the ground it had deserted in the case of Judge Pickering, and every senator would be obliged to assert that Chase’s acts were crimes. At this crisis Giles abandoned the extreme impeachers. He made a speech repeating his old argument, and insisting that the House might impeach and the Senate convict not only for other than indictable offences, but for other than high crimes and misdemeanors; yet since in the present case the charges were avowedly for high crimes and misdemeanors, he was willing to take the question as Bayard proposed it, protesting meanwhile against its establishment as a precedent. Bayard’s Resolution was adopted March 1, a few moments before the hour of half-past twelve, which had been appointed for pronouncing judgment.

The Senate chamber was crowded with spectators when VicePresident Burr took the chair and directed the secretary to read the first article of impeachment. Every member of the Senate answered to his name. Tracy of Connecticut, prostrated by recent illness, was

brought on a couch and supported to his seat, where his pale face added to the serious effect of the scene. The first article, which concerned the trial of Fries, was that on which Randolph had founded the impeachment, and on which the managers had thrown perhaps the greatest weight. As the roll was called, Senator Bradley of Vermont, first of the Republican members, startled the audience by saying “Not Guilty.” Gaillard of South Carolina, and, to the astonishment of every one, Giles, the most ardent of impeachers, repeated the same verdict. These three defections decided the result; but they were only the beginning. Jackson of Georgia, another hot impeacher, came next; then Dr. Mitchill, Samuel Smith of Maryland, and in quick succession all the three Smiths of New York, Ohio, and Vermont. A majority of the Senate declared against the article, and the overthrow of the impeachers was beyond expectation complete.

On the second article the acquittal was still more emphatic; but on the third the impeachers rallied,—Giles, Jackson, and Samuel Smith returned to their party, and for the first time a majority appeared for conviction. Yet even with this support, the impeachers were far from obtaining the required twenty-three votes; the five recalcitrant Northern democrats stood firm; Gaillard was not to be moved, and Stone of North Carolina joined him:—the impeachers could muster but eighteen votes. They did no better on the fourth article. On the fifth,—Randolph’s interpolated charge, which alleged no evil intent,—every member of the Senate voted “Not Guilty;” on the sixth, which was little more than a repetition of the fifth, only four senators could be found to condemn, and on the seventh, only ten. One chance of conviction remained, the eighth article, which covered the judge’s charge to the grand jury at Baltimore in 1803. There lay the true cause of impeachment; yet this charge had been least pressed and least defended. The impeachers brought out their whole strength in its support; Giles, Jackson, Samuel Smith, and Stone united in pronouncing the judge guilty: but the five Northern democrats and Gaillard held out to the last, and the managers saw themselves deserted by nearly one fourth of the Republican senators. Nineteen voices were the utmost that could be induced to sustain impeachment.

The sensation was naturally intense; and yet the overwhelming nature of the defeat would have warranted an excitement still greater. No one understood better the meaning of Chase’s acquittal than John Randolph, whose authority it overthrew. His anger showed itself in an act which at first alarmed and then amused his enemies. Hurrying from the Senate chamber to the House, he offered a Resolution for submitting to the States an amendment to the Constitution: “The judges of the Supreme and all other courts of the United States shall be removed by the President on the joint address of both Houses of Congress.” His friend Nicholson, as though still angrier than Randolph, moved another amendment,—that the legislature of any State might, whenever it thought proper, recall a senator and vacate his seat. These resolutions were by a party vote referred to the next Congress.

Randolph threatened in vain; the rod was no longer in his hands. His overthrow before the Senate was the smallest of his failures. The Northern democrats talked of him with disgust; and Senator Cocke of Tennessee, who had voted “Guilty” on every article of impeachment except the fifth, told his Federalist colleagues in the Senate that Randolph’s vanity, ambition, insolence, and dishonesty, not only in the impeachment but in other matters, were such as to make the acquittal no subject for regret.[145] Madison did not attempt to hide his amusement at Randolph’s defeat. Jefferson held himself studiously aloof. To Jefferson and men of his class Randolph seems to have alluded, in a letter written a few weeks later, as “whimsicals,” who “advocated the leading measures of their party until they were nearly ripe for execution, when they hung back, condemned the step after it was taken, and on most occasions affected a glorious neutrality.”[146] Even Giles turned hostile. He not only yielded to the enemies of Randolph in regard to the form of vote to be taken on the impeachment, and fairly joined them in the vote on the first article, but he also aided in offering Randolph a rebuke on another point connected with the impeachment.

In the middle of the trial, February 15, Randolph reported to the House, and the House quickly passed, a Bill appropriating five thousand dollars for the payment of the witnesses summoned by the

managers. When this Bill came before the Senate, Bayard moved to amend it by extending its provisions to the witnesses summoned by Judge Chase. The point was delicate; for if the Senate was a court, and impeachment a criminal procedure, this court should follow the rules that guided other judicial bodies; and every one knew that no court in America or in Christendom obliged the State, as a prosecutor, to pay the witnesses of the accused. After the acquittal, such a rule was either equivalent to telling the House that its charges against Chase were frivolous and should never have been presented, or it suggested that the trial had been an official inquiry into the conduct of an officer, and not a criminal procedure at law. The Republicans might properly reject the first assumption, the Federalists ought to resist the second; yet when Bayard’s amendment came to a vote, it was unanimously adopted.[147] The House disagreed; the Senate insisted, and Giles led the Senate, affirming that he had drawn the form of summons, and that this form made no distinction between the witnesses for one party and the other. The argument was not decisive, for the court records showed at once by whom each witness was called; but Giles’s reasoning satisfied the Senate, and led to his appointment, March 3, with Bradley, an enemy of impeachment, as conferrees to meet Randolph, Nicholson, and Early on the part of the House. They disagreed; and Randolph, with his friends, felt that Giles and the Senate had inflicted on them a grievous insult. The Report of the conference committee was received by the House at about seven o’clock on the evening of March 3, when the Eighth Congress was drawing its last breath. Randolph, who reported the disagreement, moved that the House adhere; and having thus destroyed the Bill, he next moved that the Clerk of the House should be directed to pay the witnesses, or any other expense certified by the managers, from the contingent fund. He would have carried his point, although it violated every financial profession of the Republican party, but that the House was thin, and the Federalists, by refusing to vote, prevented a quorum. At half-past nine o’clock on Sunday night, the 3d of March, 1805, the Eighth Congress came to an end in a scene of total confusion and factiousness.

The failure of Chase’s impeachment was a blow to the Republican party from which it never wholly recovered. Chief-Justice Marshall at length was safe; he might henceforward at his leisure fix the principles of Constitutional law. Jefferson resigned himself for the moment to Randolph’s overthrow; but the momentary consolations passed away, and a life-long disappointment remained. Fifteen years later his regret was strongly expressed:—

“The Judiciary of the United States,” mourned the old ex-President, [148] “is the subtle corps of sappers and miners constantly working underground to undermine the foundations of our confederated fabric They are construing our Constitution from a co-ordination of a general and special government to a general and supreme one alone.... Having found from experience that impeachment is an impracticable thing, a mere scarecrow, they consider themselves secure for life; they skulk from responsibility; ... an opinion is huddled up in conclave, perhaps by a majority of one, delivered as if unanimous, and with the silent acquiescence of lazy or timid associates, by a crafty chief-judge who sophisticates the law to his mind by the turn of his own reasoning.”

The acquittal of Chase proved that impeachment was a scarecrow; but its effect on impeachment as a principle of law was less evident. No point was decided. The theory of Giles, Randolph, and Rodney was still intact, for it was not avowedly applied to the case. The theory of Judge Chase’s counsel—that an impeachable offence must be also indictable, or even a violation of some known statute of the United States—was overthrown neither by the argument nor by the judgment. So far as Constitutional law was concerned, President Jefferson himself might still be impeached, according to the dictum of Madison, for the arbitrary removal of a useful tide-waiter, and Chief-Justice Marshall might be driven from the bench, as Giles wished, for declaring the Constitution to be above the authority of a statute; but although the acquittal of Chase decided no point of law except his innocence of high crimes or misdemeanors, as charged in the indictment, it proved impeachment to be “an impracticable thing” for partisan purposes, and it decided the permanence of those lines of Constitutional development which were a reflection of the common law. Henceforward the legal profession had its own way in expounding the principles and

expanding the powers of the central government through the Judiciary.

CHAPTER XI.

T Louisiana treaty, signed in May, 1803, was followed by two years of diplomatic activity. The necessary secrecy of diplomacy gave to every President the power to involve the country without its knowledge in dangers which could not be afterward escaped, and the Republican party neither invented nor suggested means by which this old evil of irresponsible politics could be cured; but of all Presidents, none used these arbitrary powers with more freedom and secrecy than Jefferson. His ideas of Presidential authority in foreign affairs were little short of royal. He loved the sense of power and the freedom from oversight which diplomacy gave, and thought with reason that as his knowledge of Europe was greater than that of other Americans, so he should be left to carry out his policy undisturbed.

Jefferson’s overmastering passion was to obtain West Florida. To this end two paths seemed open. If he chose to conciliate, Yrujo was still ready to aid; and Spain stood in such danger between England and France that Godoy could not afford to throw the United States into the hands of either. If Jefferson wished the friendship of Spain, he had every reason to feel sure that the Prince of Peace would act in the same spirit in which he had negotiated the treaty of 1795 and restored the right of deposit in 1802. In this case Florida must be let alone until Spain should be willing to cede, or the United States be ready for war.

On the other hand, the President might alienate Spain and grasp at Florida. Livingston and Monroe warmly urged this policy, and were in fact its authors. Livingston’s advice would by itself have had no great weight with Jefferson or Madison, but they believed strongly in Monroe; and when he made Livingston’s idea his own, he gave it weight. Monroe had been sent abroad to buy Florida; he had bought Louisiana. From the Potomac to the Mississippi, every Southern man expected and required that by peace or war Florida should be annexed to the Union; and the annexation of Louisiana made that of

Florida seem easy Neither Monroe, Madison, nor Jefferson could resist the impulse to seize it.

Livingston’s plan has been described. He did not assert that Spain had intended to retrocede Florida to France, or that France had claimed it as included in the retrocession. He knew the contrary; and tried in vain to find some one willing to say that the country to the Perdido ought to be included in the purchase. He made much of Marbois’s cautious encouragement and Talleyrand’s transparent manœuvres; but he was forced at last to maintain that Spain had retroceded West Florida to France without knowing it, that France had sold it to the United States without suspecting it, that the United States had bought it without paying for it, and that neither France nor Spain, although the original contracting parties, were competent to decide the meaning of their own contract. Believing that Bonaparte was pledged to support the United States in their effort to obtain West Florida, Livingston was anxious only to push Spain to the utmost. Talleyrand allowed him to indulge in these dreams. “I have obtained from him,” wrote Livingston to Madison,[149] “a positive promise that this government shall aid any negotiation that shall be set on foot” for the purchase of East Florida; while as for Florida west of the Perdido, “the moment is so favorable for taking possession of that country, that I hope it has not been neglected, even though a little force should be necessary to effect it. Your minister must find the means to justify it.”

When the letters written by Livingston and Monroe in May, 1803, reached Washington, they were carefully studied by the President, fully understood, and a policy quickly settled. When Jefferson wrote to Senator Breckenridge his ideas on the unconstitutionality of the purchase, he spoke with equal clearness on the course he meant to pursue toward Spain in order to obtain Florida:[150]

“We have some claims to extend on the sea-coast westwardly to the Rio Norte or Bravo, and, better, to go eastwardly to the Rio Perdido, between Mobile and Pensacola, the ancient boundary of Louisiana. These claims will be a subject of negotiation with Spain; and if as soon as she is at war we push them strongly with one hand,

holding out a price with the other, we shall certainly obtain the Floridas, and all in good time.”

This was not Livingston’s plan, but something quite distinct from it. Livingston and Monroe wanted the President to seize West Florida, and negotiate for East Florida. Jefferson preferred to negotiate for West Florida and to leave East Florida alone for the time.

Madison had already instructed[151] the minister at Madrid that the Floridas were not included in the treaty, “being, it appears, still held by Spain,” and that the negotiation for their purchase would be conducted by Monroe at Madrid. Instructions of the same date were instantly sent to Monroe,[152] urging him to pursue the negotiation for Florida, although owing to the large drain made on the Treasury, and to the “manifest course of events,” the government was not disposed to make sacrifices for the sake of obtaining that country. “Your inquiries may also be directed,” wrote Madison, “to the question whether any, and how much, of what passes for West Florida be fairly included in the territory ceded to us by France.”

The idea that West Florida could be claimed as a part of the Louisiana purchase was a turning-point in the second Administration of Jefferson. Originating in Minister Livingston’s mind, it passed from him to Monroe; and in a few weeks the President declared the claim substantial.[153] As the summer of 1803 closed, Jefferson’s plan became clear He meant to push this claim, in connection with other claims, and to wait the moment when Spain should be dragged into the war between France and England.

These other claims were of various degrees of merit, and involved France as well as Spain. During the quasi war between the United States and France, before Jefferson came into power, American commerce in Spanish waters suffered severely from two causes. The first consisted in captures made by Spanish cruisers, and condemnations decided in Spanish courts; the second was due to captures made by French cruisers, and condemned by French consuls in Spanish ports, or by courts of appeal in France, without regard to the rights or dignity of Spain. With much trouble, in August,

1802, at the time when Europe and America were waiting for the end of Leclerc’s struggle with the negroes and fevers of St. Domingo, Pinckney succeeded in persuading the Prince of Peace to let the claims for Spanish depredations go before a commission for settlement; but Godoy obstinately refused to recognize the claims for French depredations, taking the ground that Spain was in no way responsible for them, had never in any way profited by them, and had no power at the time they occurred to prevent them; that France, and France alone, had committed the offence, and should pay for it.

Pinckney resisted this reasoning as energetically as possible; but when Cevallos offered to sign a convention covering the Spanish depredations, and reserving the Franco-Spanish claims for future discussion, Pinckney properly decided to accept an offer which secured for his fellow-citizens five or ten millions of money, and which left the other claim still open.[154] The convention of Aug. 11, 1802, was sent to the Senate Jan. 11, 1803, in the excitement that followed Morales’s withdrawal of the entrepôt at New Orleans. The Senate deferred action until the last moment of the session; and then, March 3, 1803, after Nicholson and Randolph had appeared at the bar to impeach Judge Pickering, Pinckney’s claims convention was taken up, and the nine Federalists were allowed to defeat it by the absence of Republican senators. The majority reconsidered the vote and postponed the whole subject till the next session. Thus, owing to the action of Federalist senators, when Jefferson in the following summer, after buying Louisiana, looked about for the means of buying Florida, he found these classes of claims, aggregating as he supposed between five and ten million dollars, ready to his hand. Monroe was promptly ordered to insist upon treating both classes alike, and setting both of them against the proposed purchase of Florida. “On the subject of these claims you will hold a strong language,” said Madison.[155]

A third class of claims could be made useful for the same purpose. Damages had been sustained by individuals in the violation of their right of deposit at New Orleans in the autumn of 1802.

“A distinction, however, is to be made,” wrote Madison, “between the positive and specific damages sustained by individuals and the

Turn static files into dynamic content formats.

Create a flipbook
Issuu converts static files into: digital portfolios, online yearbooks, online catalogs, digital photo albums and more. Sign up and create your flipbook.