Explore the intersection between software and mathematics. Michael L Perry takes you on a journey through the history of computing, information theory, cryptography, distributed systems, and everywhere else that math has influenced technology. Not only will you dive into math papers, but you'll also learn valuable programming techniques that you can apply in any language.Code Erat Demonstrandum
QED 19: Dependency Tracking24/10/2016 Duration: 17min
The number of degrees of freedom in a system is equal to its number of unknowns minus its number of equations. That is also equal to the number of independent variables in the system. Dependent variables do not contribute degrees of freedom. However, by taking advantage of determinism, we can compute at run time the set of independent variables upon which a dependent variable depends. This gives libraries like Update Controls, Assisticant, and Knockout the ability to figure out when to update the view with extreme efficiency. Both C# and Java have enumerables. These are interfaces understood by the looping constructs of the language itself. Unfortunately, it is unsafe to modify a collection while using an iterator. But immutable data types hold the key, and should be the preferred way of managing collections. Prime numbers are the building blocks of all natural numbers. Godel used them to prove his Incompleteness Theorem. There are many mind-blowing facts that we know about prime numbers, such as the general
Q.E.D. 18: Paxos19/09/2016 Duration: 16min
Leslie Lamport wrote a paper describing the Paxos algorithm in plain English. This is an algorithm that guarantees that a distributed system reaches consensus on the value of an attribute. Lamport claims that the algorithm can be derived from the problem statement, which would imply that it is the only algorithm that can achieve these results. Indeed, many of the distributed systems that we use today are based at least in part on Paxos. Linq not only introduced the ability to query a database directly from C#. It also introduced a set of language features that were useful in their own right. Lambda expressions did not exist in C# prior to 3.0, but now they are preferred to their predecessor, anonymous delegates. Extension methods were added to the language specifically to make Linq work, but nevertheless provide an entirely new form of expressiveness. Linq works because its parts were designed to compose. This is not quite so true of language features that came later, like async and primary constructors. Ferm
QED 17: Pythagoras27/08/2016 Duration: 16min
The Pythagoreans were a cult of Greek mathematicians that believed that all things were composed of large enough integers. Their leader, Pythagoras, is best known for the proof that the square of the hypotenuse of a right triangle is equal to the sum of the squares of the two sides. Unfortunately, this theorem leads to the conclusion that some numbers cannot be expressed as the ratio of large enough integers, and so proof destroyed their beliefs. Monads are an extremely useful category of type. Whereas Applicatives let us build pipelines of single values, Monads support forking within that pipeline. They provide a "bind" method that joins a function returning another Monad to the end of the pipeline, and then flattens out the result. We can use this to build queries, to eliminate null reference exceptions, and even to execute asynchronous code without nested callbacks. Event Sourcing, popularized by Greg Young, is the practice of storing the events that have occurred in a system, instead of the current state
QED 16: Elements15/08/2016 Duration: 17min
Euclid's Elements takes a disciplined, formal approach to proving assertions based only on simple axiomatic statements. While most of these axioms are elegant, one of them is more complex and wordy. It seems as if it should be provable from the others. Several mathematicians have tried, but eventually they found a surprising result. Beware when proving your own assertions that you don't make the mistake of assuming something that seems obvious. Category theory isn't as complex as you might be lead to believe. A category is nothing more than a contract that sets rules on how a type is to behave. Functors, despite having a weird name, are just types that can map functions into a different space. The List type is an example of a functor, because it can transform a function on its elements into a function on lists. And Applicatives are just wrapper types. They are especially useful for building pipelines. CQRS, Command Query Responsibility Segregation, is a pattern that applies the Single Responsibility Principle
QED 15: The Y Combinator16/07/2016 Duration: 19min
The Lambda Calculus uses simple replacement to compute expressions. However, it does not define a way to replace a parameter of a function with the function itself. That would seem to make it impossible to write recursive functions. However, with a clever bit of self-application, we can define a function that makes any other function recursive. This is the Y-Combinator. Claude Shannon told us that it was important to keep equivocation high in order to make a cypher difficult to crack. In the second half of his paper, he tells us how to do that. We need to diffuse the message, and we need to confuse the key. Doing these two things will destroy the statistical patterns of the message so that the only possible attack is brute force. The Two Generals problem has no solution. But does that mean that we cannot guarantee that a distributed system will reach consensus? Not at all. By applying two simplifying assumptions, we reduce the problem to one that can be solved with a very simple protocol. This durable messagi
QED 14: Equivocation02/07/2016 Duration: 16min
Claude Shannon followed up one incredibly important paper with a second of even greater significance. In Communication Theory of Secrecy Systems, he analyzes cryptosystems based on the probabilities of certain plaintext messages given an intercepted cyphertext. Understanding this form of analysis will help us to design more effective systems. The Lambda Calculus computes using nothing but symbol replacement. If we are going to run programs like a computer, we need to express conditional branches. We can represent the value "true" as a function λa.λb.a. In other words, the function that returns the first of two arguments. Similarly, the value "false" is represented by the function λa.λb.b. To create a conditional "if-else" statement, capture two branches and then apply the third argument to select between them: λa.λb.λc.c a b. Suppose that you needed to reach an agreement among several people by passing messages. Now suppose that some of those people could not be trusted. Under what conditions could you find a
QED 13: The First Program18/06/2016 Duration: 19min
in a translation of a paper on the Analytical Engine, Ada Lovelace improved upon L. F. Menambrea's work by applying rigor to the calculations that he performed. But then she took things one iteration further. In fact, she took things n iterations further. She wrote the first computer program, using the backtracking feature of the Analytical Engine to perform loops. The Lambda Calculus contains only functions. Evaluating a function is merely rewriting it to replace its parameter with its argument. How then can we represent something like numbers in a language with no primitives? We do it by writing a function that calls another function a certain number of times. The function that calls it once is the number 1. The function that calls it 100 times is the number 100. Alonzo Church demonstrated that these "Church Numerals" could be operated upon by other functions to calculate any computable number. We gain a great deal of confidence in our code if we can reason about the value of variables. What better way to k
QED 12: Difference Engine20/07/2015 Duration: 17min
The Difference Engine was a mechanical computer that could calculate tables of numbers based on polynomials. The amazing thing is, though, that it could only add. How then could it accomplish this feat? By the method of differences! Charles Babbage never constructed his Difference Engine, but we've made a couple from his designs. Lambda Calculus is also a method of computation based on really simple rules. In this case, they are alpha-conversion, beta-conversion, and eta-conversion. These serious-sounding transforms are actually pretty simple. Let's first learn what they are, and then see how they relate to C#. Speaking of C#, Malachi asks a question about C# constructors. As you may know, I am of the opinion that constructor parameters should represent only immutable fields. How, then, does one initialize a mutable field in such a way that you can guarantee that it is set? In other words, write a method on the class that can only be called after the object is initialized.
QED 11: The Lambda Calculus26/03/2015 Duration: 17min
Alonzo Church invented The Lambda Calculus as a simple set of rules that, when applied correctly, could compute anything that you could do with a pencil and paper. But all it is is simple replacement. Learn the basics of lambda expressions so that we can build on this theory of computation. As we celebrate pi day in the States (where we put the month in the wrong place -- 3/14/15), let's see how we go about computing the digits of pi. We'll start out with a simple geometric method, and progress through more modern techniques, until we arive at a truly surprising and remarkable formula. When John von Neumann created Game Theory, he showed how it can sometimes find an optamal strategy. But there's one game for which it fails completely. Find out why The Prisoner's Dilemma is such a tricky problem, and how a fair algorithm was found to be the best possible solution.
QED 10: The Two Generals Problem09/03/2015 Duration: 13min
Listener Richard Allen writes to ask about proving enough of a program correct to constrain the number of tests that must be written. I respond that you need both tests and proof. Otherwise, how could you know that the specification is what you intended? Two generals wish to reach consensus by sending messengers through enemy territory. How can this be achieved? You can prove, in fact, that it cannot. This has important rammifications on the design of distributed systems. To prove that prerequisites are satisfied before calling a method, you can use a factory method. By chaining these factory methods together, you can prove that an entire sequence of events must take place in the correct order. This makes a fluend API not only more readable, but also more provable.
QED 9: The CAP Theorem12/01/2015 Duration: 14min
In 2000, Eric Brewer presented the CAP Conjecture to the Symposium on Principles of Distributed Computing. This states that a distributed system cannot simultaneously guarantee consistency, availability, and partition tolerance. It can, however, guarantee two of the three. It makes little sense to talk about guaranteeing consistency and availability while sacrificing partition tolerance. Network partitions are going to occur, so we must choose whether we are going to give up consistency or availability when that happens. Mathematical induction is a style of proof whereby you prove the base case (typically N = 1), and then you prove the inductive step (that if it's true for N, it's true for N+1). In programming, mathematical induction is used when writing recursive functions. First, implement the function for the base case. Then, assuming that the function works for smaller cases, reuse it to implement the function for larger ones. Constructors can be used to prove that one thing happens before another, and fu
Q.E.D. 8: Constructability28/12/2014 Duration: 15min
Knowing that a directed graph is acyclic is useful. If you construct directed graphs in a certain way, then you can prove that they have no cycles. Design systems to produce constructable graphs, and you can take advantage of all of the theorems known to be true of DAGs. Alan Turing proved that there could not be a general procedure to determine whether an expression in first order predicate calculus is satisfyable. This extends Godel's Incompleteness Theorem by asserting not only that there are some true statements that cannot be proven, but also that there is no way to decide whether a statement in general even has a proof. In the process of constructing this proof, Alan Turing defined the Universal Machine, which can perform any mechanical computation. This is the genesis of the computers that we use today. Leslie Lamport finishes off his paper on Time, Clocks, and the Order of Events in a Distributed System by showing how to synchronize physical clocks. This is useful to avoid anomalies caused by communic
QED 7: Topological Ordering14/12/2014 Duration: 15min
In a directed acyclic graph, we can use reachability to determine a partial order. But sometimes we want a total ordering of the nodes to accomplish some result. There are usually many possible total orderings that satisfy the partial ordering. Topological sorting algorithms can help us discover them, whether we want just one, or all possible orderings. Unit tests can only cover one scenario. Mathematical proof, while it generalizes to many scenarios, is not always feasible. Thankfully, we have tools that will search the input space to help us find problems in our code. Parameterized unit tests come in two flavors: generitive tests and exploratory tests. Generitive testing tools, like Quick Check and Test.Check, try random inputs. Exploratory testsing tools, like Pex and Code Digger, discover scenarios that cover as many branches in the code as possible. These tools are a good addition to the other two, helping us fill that gap. Leslie Lamport used logical clocks in a distributed system to solve the mutual ex
Partial Order03/12/2014 Duration: 14min
A fully ordered set is one in which we can tell for any two members which one comes before the other. Think integers. A partially ordered set, however, only gives us an answer for some pairs of nodes. A directed acyclic graph defines a partial order over its nodes. Find out how to compute this partial order, and some of the ways in which it can be applied. The number of degrees of freedom in a system of equations is equal to the number of unknowns minus the number of equations. We can add unknowns, as long as we also add the same number of equations, without changing the behavior of the system. Then we can rewrite the equations, again without changing behavior, to solve for some of those unknowns in terms of others. Doing so, we divide the system into independent and dependent variables. The number of degrees of freedom is equal to the number of independent variables. In 1978, Leslie Lamport wrote "Time, Clocks, and the Ordering of Events in a Distributed System". In this paper, he constructs a clock that giv
Q.E.D. 5: Fields and Properties26/10/2014 Duration: 16min
The number of degrees of freedom in a solution should match the number in the problem. If you have extra degrees of freedom, then you have to write extra code to keep them in sync. This opens the door for bugs. To count the degrees of freedom in a solution, count the mutable fields and the auto properties. These constructs introduce one degree of freedom for each instance of the object. Kurt Godel proved that first order predicate calculus is complete. Any true statement can be proven from axioms. However, he also proved that more complex systems are incomplete. No matter how many axioms you introduce, there will be true statements that you cannot prove. See how he did it, and how that eventually lead to the invention of the comupter. Many of the data structures that we use are directed graphs. Relational databases have foriegn keys, which are directional edges between two records. Build systems have dependencies, which are directional edges between projects. Some of these systems not only directed, but
Q. E. D. 4: Factories28/09/2014 Duration: 16min
In the .NET Socket API, if you call methods in the wrong order, the Socket class will throw an exception. Wouldn't it be better if it guided you into the pit of success at compile time? One pattern from the Gang of Four book holds the key to proving that prerequisites happen first. You can compute how many degrees of freedom are in a problem. This tells you how many decisions you can make, or how many values it takes to describe the current state. Knowing this will tell you some interesting things about the solution to that problem. Daan Leijen explores the balance between type constraints, which make it possible to prove interesting assertions about values, and generalizations, which make it easy to express types. Finding this balance is sometimes a hard problem, leading some to abandon statically typed languages for dynamically typed ones. In Extensible Records with Scoped Labels, Daan shows us how we can take on some of the power of dynamic typing -- extension -- without giving up type inference.
QED 3: First or Default16/09/2014 Duration: 15min
FirstOrDefault is an extension method used in Linq. It is often used incorrectly, leading to exceptions or ignored data. Learn techniques for accessing members of a Linq expression without the possibility of errors. "Theorem" and "theory" sound similar, but they mean completely different things. Learn the difference, and how a theorem can be part of a theory. Continuing with Claude E. Shannon's "The Mathematical Theory of Communication", we learn how to model random noise within a channel. How does this noise effect the bandwidth of the channel? How can we achieve any desired confidence in the message received, shy of certainty? The math tells us how.
QED 2: Code Contracts08/09/2014 Duration: 18min
Code Contracts let you express predicates in C# code. This Visual Studio plug in and associated library checks your assertions. It can perform tests at run time, and even prove the predicates at compile time. Leonhard Euler solved the Seven Bridges problem. In so doing, he established graph theory, one of the foundations of computer science. Reason through his proof, and discover how many bridges it will take to solve the problem. Claude E. Shannon defined Information Theory in "A Mathematical Theory of Communication". Review the first part of his paper, where he analyzes the capacity of a noiseless channel. Then find out how we can transmit faster than that capacity will allow, given information about the language.
QED 1: Predicates01/09/2014 Duration: 23min
Apply the principles of predicate calculus to creating reliable software. Use a technique inspired by algebra to confidently change the structure of code without breaking it. And learn how the father of game theory paved the way to the digital computers that we use today. Explore the intersection between software and mathematics.