Wednesday, June 20, 2012

Welcome to the Major Leagues

I'm not the only person to have recognized that the skill sets for doing embedded development are the same as for developing for large distributed systems and multicore/multiprocessor architectures. And I'm sure I'm not the only one to have built a career on that common skill set based on dealing with concurrency and parallelism (and understanding why those are two different things), frequently working close to bare metal, developing scalable solutions, worrying about real-time and emergent behavior, and needing to understand what goes on under the hood.

But despite having spent decades on and off doing it, when I'm asked to define embedded development, I'm at a bit of a loss. Ask this question in an internet forum, and you will be surprised to find that there is no real consensus even among those who describe themselves as embedded developers.

Part of this is because the hardware target for which an embedded developer writes software ranges from a tiny inexpensive low-power eight-bit microcontrollers (which in fact may not even be independent chips themselves but cores implemented inside of another chip like an FPGA or some other surface-mounted device) with kilobytes of memory to a thirty-two-bit microprocessor with multiple cores and megabytes or even gigabytes of memory. The developer may code in assembler, C, C++, Java, or even scripting languages like Python and Perl. The underlying software platform that runs on the so-called embedded system ranges from none (remarkably, it is not uncommon to have no OS-like layer at all), to a simple task scheduler like FreeRTOS or even home grown, to a large commercial RTOS like VxWorks, to a full blown multi-user GNU/Linux or even Windows operating system.

This uncertainty about how to describe what we do for a living to our friends, children, spouses, and even colleagues is just going to get worse.

Yesterday I successfully built the entire Android "Ice Cream Sandwich" (a.k.a. ICS) software stack for my ODROID-A4 platform as part of my Conestoga project. It took awhile. I'm used to that, having built other Android releases like "Frozen Yogurt" and "Gingerbread" for the BeagleBoard as part of Contraption. While I was watching the build process scroll along in a window, I began to idly wonder just how big this software distribution was. So in another window I unloosed some of my favorite commands like find, wc, and awk.

ICS consists of 25,410 files ending in .java containing 5,325,103 lines of what is presumably Java code. It also includes 62,861 files ending in .cpp, .c, .hpp, or .h, containing 13,225,200 lines of presumed C or C++ code. This is just the Android stack. The same statistics for the Linux kernel and the U-Boot boot loader would make these numbers significantly larger.

To be fair, the ICS counts include some stuff that may not run on the Android target itself. Much of the code that does run on the target is what we would normally associate with the standard underlying C and C++ libraries on any other system. And one of the reasons not to count the Linux and U-Boot code bases is that they each contain vast amounts of code for targets completely unrelated to Android or the ODROID-A4 target. But even so, those are still big numbers, and developers working in the lower levels of Android close to bare metal may still end up indexing and searching all those unrelated files because there is no easy way to exclude them.

So just a naive census of the Android ICS code base for the ODROID-A4 yields 18,550,303 lines of code in 88,271 source files.

Surprised? Do you think those numbers are too big or too small? The answer may depend on whether or not you see Android as an embedded system. The A4 runs on a battery, connects wirelessly to a network, fits in my shirt pocket, and has tightly integrated hardware components. Any embedded developer would be completely at home perusing its circuit board. But it implements a complex user-facing graphical user interface and a bunch of applications. So desktop developers see a lot of stuff they recognize as well.

For sure these are pretty naive numbers. And I would be the first to say that lines of code is a kind of useless metric of just about anything. But if you are a developer tasked with working in this code base, then part of your job may be to reverse engineer portions of this code to understand it and to integrate with it, which means you'll be indexing, searching through, and reading this code, whether it's blank lines, comments, or the implementation of a cryptographic hash function.

What does this mean? I'm not sure. But I do believe that product and project managers who are looking at using Android, whether it's for a small embedded device or a large complex system, may need to recalibrate the mental models they carry around in their heads regarding the complexity of the tasks they are asking developers to take on. If you spend most of your time in the embedded world, or if you don't but you see shirt-pocket-sized mobile wireless devices as embedded systems, then the idea of a code base of more than eighteen million lines of code might seem surprising, not to mention a little daunting.

It's not as bad as I may make it sound. The Android APIs are well documented (albeit a moving target with each new release), and tools like the Android SDK and its Eclipse plug-in are very good.

But Android is not Minor League.

Tuesday, June 19, 2012

ODROID-A4, Mac OS X, USB, ADB

The latest Digital Aggregates project to show up on my radar screen uses the ODROID-A4, an Android reference and development platform from Hardkernel for mobile devices based on the Samsung Exynos family of processors. The A4 uses an Exynos 4210 system-on-a-chip that features dual one gigahertz ARM Cortex-A9 cores, has one gigabyte of memory, and a microSD card slot for its persistent storage. As you can see in the photograph below, the A4 is a handheld battery-powered mobile device the size of a largish smartphone or a smallish tablet. (I believe it's form factor is the same as the Samsung Galaxy S Android smartphone.)

This project is code-named Conestoga. This project is so new, there's no web page for it yet.

(Update 2012-07-06: the Conestoga web page exists now and has a link to the tarball for what I'm working on. Warning: it's definitely a work in progress.)

Here's a photograph of the A4 on my development bench fixture. Clockwise from top: amplified speakers (because my ears are old), blue HDMI cable to an external display (because my eyes are old), the ODROID-A4 and an unconnected accessory I/O board just above it, the debug board with TTA20 debug cable, USB cable, and DB9 serial cable, and a powered USB hub.

ODROID-A4: Bench Fixture

I'm no stranger to Android, having previously worked with several different releases of it on a couple of BeagleBoards for my Contraption project in which I ran a GNU software stack along side the Android software stack on a common Linux kernel. I'm a big believer in working as high as you can on the abstraction ladder even on embedded systems, which makes frameworks like Android of interest in me in a broader context than just mobile devices like smartphones and tablets.

But I blew nearly half a day trying to get the USB-based Android Debug Bridge (adb) to recognize the A4 on my Mac Mini desktop system running OS X 10.6.8.

I found some useful background on the web on Stack Overflow, Intohand, and this discussion on Goggle Code. As usual, software development is a team effort, even when you've never met any of the other team members.

What finally worked for me was two-fold.


  1. I used a separate powered USB hub (visible in the photograph above) instead of connecting the A4 to the hub built into the Cinema Display on my Mac Mini (no clue why, but that's what worked for others too).
  2. I did not use a USB cable to the mini-USB port on the debug board, connecting only the USB-to-TTA20 debug cable and a DB9 serial cable. The TTA20 port on the debug board provides USB access for the Android Debug Bridge. The DB9 port provides console access with a root shell.


To be clear, here's a photograph of both of the A4 and the debug board on the left with all three cables connected, which did not work.

ODROID-A4: Console, USB, and TTA20

Here's a photograph of just the debug cable and the serial cable, which did work.

ODROID-A4: Console and TTA20

Here's a screen snapshot of how the device enumerates on OS X.

ODROID-A4 USB Enumeration on Mac OS X

And here's the results of asking the Android Debug Bridge to list all the visible devices.

$ adb devices
List of devices attached
BABABEEFBABABEEF device

Here's hoping this saves others some time.

Update (2012-06-03)

While adb on the Mac works just fine, I've had no consistent success getting fastboot, the interface that allows you to communicate with the U-Boot boot loader over USB, to work on the Mac. Web perusal has led me to believe this is a common issue with later versions of Mac OS X. (I'm running 10.6.8 a.k.a. "Snow Leopard".)

After blowing an entire day trying various strategies including enabling USB debugging on OS X and writing my own OS X codeless kernel extension, I finally gave up and attached the A4 to my Ubuntu server (which, for unrelated reasons, I had recently moved from the vast subterranean catacombs to my office on the second floor of the Palatial Overclock Estate), where within an hour or two everything worked just fine.

The weird part is that fastboot devices on the Mac actually worked once out of dozens of tries. What I saw logged by the USB stack in OS X smells like some kind of race condition.

For now I'm sticking with Ubuntu for platform work on the A4, and will return to the Mac (which now entails just a cable swap at the powered USB hub) when and if I do application development in Java on the A4 using the Eclipse Android plug-in.

Sunday, June 10, 2012

Going Gentle Into That Good Night

My master's thesis was published in 1983. The text of the digital version was written using a word processing program called WordStar that ran on a microcomputer using a Motorola 6800 processor running the CP/M operating system and stored on eight-inch floppy disks. The source code for my software that I was writing about was stored on eight-inch floppies in RT-11 format and ran on a Digital Equipment Corporation PDP-11 running the RSX-11M operating system. I'm pretty sure none of that exists now.

If you absolutely had to recover that digital information, it would require tens or even hundreds of thousands of dollars, in terms of hardware, software, and time, if it could be done at all. You'd have to find eight-inch floppy drives, devise a way to hook them up to some modern computer, track down the description of the CP/M and RT-11 file system formats and the WordStar and RSX-11M file formats, implement both their documented behavior and the undocumented behavior, pray that the floppies were still readable nearly thirty years later, and hope that I didn't use some compression and/or encryption algorithm that was in vogue at the time.

The effort would be made somewhat more complicated by the fact that I threw away those eight-inch floppy disks years ago. But I do have a hardcopy of my thesis, which includes the text and the complete source listings, printed on acid free paper, and hardbound. If this tome were to survive fires, floods, and the inevitable collapse of civilization, it would likely still be readable a thousand years from now. If anyone cared. Which is highly unlikely.

So it is with preservation of digital information. While I can actually read an original book by Galileo, and make out the icons on a shard of four thousand year old Greek pottery, digital data are ephemeral. My enormous collection of motion picture and television soundtrack music on compact disk, about two thousand of them, has a shelf life. Estimates range from 100 years to as few as two years. And what are my chances of buying a new CD player twenty years from now? Let's ask the people who invested in eight-track tapes, cassette tapes, or any number of other media technologies that have gone by the wayside. It is a similar story for DVDs, nine-track magnetic tape, flash memory, and anything else that stores bits magnetically, optically, or electronically.

What's worse, it's not just the physical bits, it's what the bits mean: encryption, compression, application file format, operating system file system format, all have something to do with how the ones and zeros are interpreted. So the problem just gets exponentially complicated, because information about all that stuff is stored digitally too. How much of it do you need to read the digital copy of my thesis? All of it. 

The general consensus is that there are two approaches to solving the long-term digital preservation problem: migration and emulation.

Migration is the act of more or less continually copying all archived digital information to the latest and greatest formats and technologies. This can work. Sorta. I once worked at a place that had to purchase every single used tape drive of the discontinued model they were using in order to keep enough working for long enough so that they could move their enormous tape archive containing the sole copies of historical climate data and archived output from climate simulations to a format and technology that might buy them another decade before panic sat in again. When you do this you hope you can get the migration competed before the new technology is obsolete.

Emulation is building a system using new technology that acts like old technology. This is non-trivial, for the reasons stated above: the documentation you need, if it exists at all, is also stored digitally. And there's the matter of the physical media and the devices to read it. This approach is the reason I was once tasked with writing UNIX code that grokked files stored in a variety of IBM VM/370 file formats. My software, which I designed by reverse engineering the original VM/370 system software written in IBM assembler, was used to access hundreds of thousands of files. Successfully, I'm told.

Barry Karafin, formerly the head of Bell Labs, once observed that most high technologies have a half-life of about five years. Some technologies, like C and TCP/IP, have done better. But for most of it, there is no long term. The need to migrate or emulate is, like adaptive maintenance, a continuous on-going process that never ends.

The definitive work on this topic in my opinion is

Jeff Rothenberg, "Ensuring the Longevity of Digital Documents", Scientific American, vol. 272, no. 1, January 1995

a digital copy of which, so far, can be found here, providing its still readable and you have software that understands Adobe's Portable Document Format. Just today I read another article on this topic written more recently

David Anderson, "Historical Reflections: The Future of the Past", Communications of the ACM, vol. 55, no. 5, May 2012

that I also recommend, and which, at least for now, can be found here. If the links are broken, or your browser can't render the text, well, then, welcome to the information age.

This is serious stuff. I'm not kidding. The value of information often can only be ascertained in hindsight once its historical context is known. We are contemporaneously the worst judges of the value of the data that we produce. We can still read the original letters John Adams wrote to his wife. But the chances that two hundred years from now anything that any of us may have written, important or not, will still exist and be readable are vanishingly slim.

Friday, June 08, 2012

The Prisoner's Dilemma, the Fermi Paradox, and War Games

I have enough life experience and self-knowledge to recognize when I'm being totally intellectually obsessive on some topic. And for sure, when I start to quote myself I've reached some critical threshold of narcissism. But never the less, here are some footnotes that I added to a recent blog article (which was only peripherally on this topic) that I'm reposting here because I'm so enamored with these ideas.

"The prisoner's dilemma also applies to the Fermi Paradox, which frames the contradiction between the statistical likelihood of technological extraterrestrial civilizations with the fact that so far there is no evidence of such. The dominant but sub-optimal strategy is for each civilization to try to wipe out all the others before someone does it to them. I'm voting for weaponized von Neumann machines. It's interesting (to me anyway) that John von Neumann, the inventor of game theory, also invented the idea of self-replicating automata. I'd like to think that weaponized von Neumann machines of extraterrestrial origin are the untold backstory to books and movies about the zombie apocalypse. Or of the Borg race from the Star Trek universe. The central theme, in my opinion, of the Borg story arc in Star Trek is that the Borg applied the dominant strategy of betrayal to the prisoner's dilemma while the members of the United Federation of Planets chose the cooperative optimal strategy."

"The WOPR U.S. automated defense computer learns the inefficiency of nuclear war by playing tic-tac-toe in the movie WarGames. But a much better game, and one that likely actually came from nuclear strategists, would be to have it play a repeated prisoner's dilemma game where it would learn the benefit of cooperation over betrayal. On the other hand, this is exactly the plot of the movie Colossus: The Forbin Project, and that didn't turn out so well due to what economists would call an externality."

Let's all hope I get over this once I've finished reading Dixit and Nalebuff''s book Thinking Strategically.

Wednesday, June 06, 2012

Making Something From Nothing

Here's the latest on my homebrew solar-powered Arduino-based remote sensor platform.

Solar + Battery Powered Arduino with Zigbee

The basic parts manifest, clockwise from top left, includes a solar battery charger regulator, an Arduino Uno board with an XBee radio shield and a Xbee Series 1 radio module, a 12V gel cell rechargeable lead-acid battery, and a solar panel designed to recharge 12V batteries. I bought the regulator and solar panel at my local Harbor Freight hardware store in Westminster Colorado. I purchased the Arduino, Xbee radio shield, and Xbee radios over the web from SparkFun Electronics in nearby Boulder Colorado (who are very nice folks, BTW). I also bought some miscellaneous parts and connectors at my local Radio Shack at the Colorado Mills outlet mall in Lakewood Colorado (who know me quite well by now, and have been known to whip out a multimeter when I have a question).

Parts Manifest

Everything except the solar panel fits nicely into a five dollar plastic box I bought at the local Office Depot office supply store in Wheat Ridge Colorado. The box isn't intended to be water tight, just to keep the worst of the elements off the electrical bits.

Inside the Box

Here's a closeup of what gets stuffed into the box. The battery, purchased at my local Interstate Battery store in Arvada Colorado, is the largest and heaviest item, and the most expensive single component as well. What would I do without my Brother thermal label maker?

Slot

I used my Dremel tool to cut a tiny slot in the plastic box through which I feed the cable to the solar panel. I also used the Dremel to drill holes in the bottom of the box, which has a bit of a lip around its bottom, so if any moisture does seep into the box it might have a chance of draining out. No air vents though, so we'll see if things get too warm. The box itself will sit in the shade of the roof over my rear deck.

Closed Up

With the lid on you can see that the slot for the cable is conveniently protected by the lip of the lid.

Remote Sensor Platform: Instrument and Power Pod

I sat what I am now calling the "Instrument Pod" on a table on my back deck just to make it less likely that I won't trip over it or kick it over. You can easily see the LEDs on the Arduino, the Xbee shield, and the regulator through the transparent plastic.

Remote Sensor Platform: Solar Panel

The solar panel sits on a couple of zinc-coated nails on the conveniently angled open lattice portion of the south-facing roof over my back deck where it's not shaded by any of the nearby trees. It's pretty secure but can be easily lifted off the nails with a little jiggling. Did I mention that Colorado gets more sunny days than any other state in the U.S.? Sorry, California. I have no idea how weather proof this solar panel is, the instruction sheet wasn't helpful in this regard.

Remote Sensor Platform: Installation

Stepping back a little bit, here's what it all looks like: solar panel above, instrument pod below. I've since moved the table a little further back under the roof to the left where it's more consistently shaded.

Remote Sensor Platform: Logging

The test software on the Arduino logs how long it's been running since it's last reset. If the board loses power, the application will restart automatically if and when power is restored. It's talking over a wireless serial channel using the Zigbee (IEEE 802.15.4) protocol to a similar tiny little radio hooked up to my Mac desktop in my office on the second floor. I use the Mac screen utility with a little script that prepends a timestamp to each line it receives from the instrument pod, and logs it all to a file.

My goal at this phase is to see whether I can get enough sunlight to run the Arduino and keep a small battery charged during the day, and to run the Arduino on battery power at night. I'm guessing I'll need a larger solar panel (or at least use this as an excuse to buy one) but this is a cost effective way to get some empirical data.

The ever helpful folks at Office Depot asked me what I was going to store in the plastic box. When I explained it was a microcontroller, radio, battery, and solar charge regulator, they backed away slowly. I get similar strange looks from most (but not all) of the handymen and women my local Lowes hardware store when I explain that "I'm making something from nothing".

Tuesday, June 05, 2012

The Developer's Dilemma

The police arrest you and your buddy. They place you in separate interrogation rooms. They suspect you both of a crime but don't have enough evidence to convict you. The cop questioning you offers you a deal: you rat out your accomplish and you get a reduced sentence. Of course, you know another cop is making the same offer to your buddy. If only one of you confesses, the stool pigeon is charged with a misdemeanor and goes free while the other guy is sentenced to a full year in the big house. If you both confess, you'll each do six months. If neither of you confesses, the best they can do on the evidence they have is charge you both with a lesser crime for which you'll each do one month.

This scenario is familiar to anyone to watches crime shows on television, reads police procedurals, or sees pretty much any movie by Martin Scorsese. It is also an example of one of the fundamental games of game theory called the prisoner's dilemma. As the police well know, the dominant strategy is for you to confess: it's the strategy that has the best outcome for you without having to depend on what the other guy does or doesn't do. It allows you to be indifferent to his strategy.

But that doesn't mean it's the best outcome, period. It is also unfortunately the dominant strategy for your buddy. If you both confess, you'll both do six months. It would be far better if both of you kept your mouths shut. The dominant strategy is inefficient because it motivates you both to achieve a sub-optimal outcome. But to do better requires cooperation and trust in your accomplice. This is tough because, as they say, there is no honor among thieves. The prisoner's dilemma is one of the reasons for omert├á, the Mafia's code of silence: it alters the payout for both parties to make it more likely that they will not betray one another. The stool pigeon's life isn't worth a plug nickel.

The prisoner's dilemma is widely discussed because it occurs so frequently in real life. The classic example is the nuclear arms race. The dominant strategy for each adversary is to launch a pre-emptive nuclear strike. But if both follow their dominant strategies, to say the outcome is sub-optimal is putting it mildly. Game theory played an important role in framing the strategy of nuclear deterrence for the United States and, one must assume, the Soviet Union. It is probably no coincidence that Merrill Flood and Melvin Dresher of the RAND Corporation first formally framed the prisoner's dilemma the year after the Soviets detonated their first atomic bomb. [1]

There are lots of other real life example. Like the one you may find yourself in right now as a software developer. Don't think so? Consider this: the company you work for probably has a fixed raise or bonus pool to distribute amongst you and your peers. Every dollar the person next to you gets is one dollar you won't get. There are only so many slots into which people may be promoted. Every slot filled with someone else is a slot that is no longer available to you. Many companies use a strategy of forced ranking, where a manager must rank a certain percentage of his employees into the lowest rating tier for use when the layoffs inevitably occur. Someone has to go in that tier no matter that their actual performance in absolute terms may be. This is called a zero-sum game: everyone's gain is balanced by someone else's loss. [2] Like it or not, your employer's human resources polices force you to compete with the developer sitting across from you. Your dominant strategy is to betray him.

But that's not the optimal strategy. Even though your company's incentive program is tragically designed to motivate you to do otherwise, both you and your fellow developer will do better if you cooperate and work together. Your joint efforts will produce a product that will be more successful, the customers will be happier, and your employer will make more money. All this because you chose to cooperate instead of compete, and despite the fact that your company is telling you to act otherwise.

I spent several years working in an organization in which our director thought competition is good (his exact words) and encouraged it among the various groups under his management. This, despite the fact that each group played a different role, and to succeed we all had to work together to support one another. Treating his groups like interchangeable commodities drove tremendous dysfunction into that organization, and highly politicized the work environment. As a manager I spent most of my time trying to shield my troops from this while attempting to get my peer managers to actually fulfill their official responsibilities. I don't miss it. Later I worked in an organization that used forced ranking. It was interesting to watch developers attempt to game the system, occasionally by screwing one another. I don't miss that, either.

How does one escape from the prisoner's dilemma? Much of game theory is about techniques and strategies to encourage cooperation among the players. Robert Axelrod of the University of Michigan held a prisoner's dilemma competition: entries were computer programs that played against one another for multiple rounds, deciding in each round whether to defect (betray or confess), or cooperate (stay silent). The winning algorithm was tit-for-tat: the program always began by cooperating; if its opponent defected, the program defected in the next round, but immediately returned to cooperating in the following round. [3]

Avinash Dixit and Barry Nalebuff illustrate the problem with this strategy: when it plays against itself, and its opponent defects just once, it falls into a perpetual pattern of alternating defection with cooperation. How can its opponent defect just once? Because in real-life, honest mistakes happen, due to misunderstandings and miscommunication. A better strategy, according to Dixit and Nalebuff, is to base your decision on both short-term and long-term memory of your opponent's past decisions, a version of which Scott Stevens has called tit-for-two-tats.

But regardless of the specifics, Stevens points out that tit-for-tat-like strategies that perform well in the repeated prisoner's dilemma game all have four characteristics:


  1. They are nice: they always begin by trusting.
  2. They are provokable: they always punish by betraying if they themselves are betrayed.
  3. They are forgiving: even though betrayed, they can eventually return to cooperating.
  4. They are straightforward: their strategy is rational, transparent, and easily understood.


I first became interested in game theory back in the 1990s when I was working on very large real-time distributed telecommunications systems. The game trees (for sequential games) and game tables (for simultaneous games) from game theory gave me a more structured way to think about error detection and recovery, particularly with regards to communication channels to other systems. I was surprised to find, when I started looking at incentive programs for software developers, that game theory played a key role there as well. Game theory is a topic that once you begin to read about it, you see it everywhere. It is a social science that studies strategic decision making. And the games that it studies permeate our lives.

Once I realized that I was routinely caught in a developer's dilemma, the tit-for-tat strategies gave me a useful approach to deal with it. Studying game theory has led me to be nicer, more provokable, more forgiving (that was the hard one, for me), and more straightforward. I'm not exaggerating when I say it's made me a better person.

Footnotes

[1] The prisoner's dilemma also applies to the Fermi Paradox, which frames the contradiction between the statistical likelihood of technological extraterrestrial civilizations with the fact that so far there is no evidence of such. The dominant but sub-optimal strategy is for each civilization to try to wipe out all the others before someone does it to them. I'm voting for weaponized von Neumann machines. It's interesting (to me anyway) that John von Neumann, the inventor of game theory, also invented the idea of self-replicating automata. I'd like to think that weaponized von Neumann machines of extraterrestrial origin are the untold backstory to books and movies about the zombie apocalypse. Or of the Borg race from the Star Trek universe. The central theme, in my opinion, of the Borg story arc in Star Trek is that the Borg applied the dominant strategy of betrayal to the prisoner's dilemma while the members of the United Federation of Planets chose the cooperative optimal strategy.

[2] Strictly speaking, forced ranking isn't zero-sum. For a game to be zero-sum, not only does every win have to be offset by a loss of equal value, but there must be no way for all players to come out ahead. But if all employees who are ranked relative to one another could enter into an enforceable collective agreement in which they each agreed to work less hard, their forced ranking relative to one another would remain unchanged while they each applied the absolute minimum amount of effort necessary to keep their jobs. While it is hard to believe that this is what their employer intended, it is in fact the most efficient outcome for the forced ranking game.

[3] The WOPR U.S. automated defense computer learns the inefficiency of nuclear war by playing tic-tac-toe in the movie WarGames. But a much better game, and one that likely actually came from nuclear strategists, would be to have it play a repeated prisoner's dilemma game where it would learn the benefit of cooperation over betrayal. On the other hand, this is exactly the plot of the movie Colossus: The Forbin Project, and that didn't turn out so well due to what economists would call an externality.

Sources

Wikipedia, Game theory, 2012

Wikipedia, Prisoner's dilemma, 2012

Wikipedia, Fermi paradox, 2012

Avinash K. Dixit and Barry J. Nalebuff, The Art of Strategy, W. W. Norton,  2008

Scott P. Stevens, Games People Play, The Teaching Company, 2008

Robert D. Austin, Measuring and Managing Performance in Organizations, Dorset House, 1996

Avinash K. Dixit and Barry J. Nalebuff, Thinking Strategically, W. W. Norton, 1991

Lawrence Lasker et al., WarGames, MGM, 1983

James Bridges, D. F. Jones, Colossus: The Forbin Project, Universal Pictures, 1970