<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-6958126065976802292</id><updated>2011-12-04T23:03:00.898-08:00</updated><category term='divide conquer algorithm parallel'/><category term='dead code ocean'/><category term='transitivity-utils transitive closure graph reachability dietz agrawal'/><category term='scala stackoverflow case-classes traits equals'/><category term='active'/><category term='memory-measurer data-structures footprint java'/><category term='state machine'/><category term='t-mobile nexus-s customer support'/><category term='rapidshare infinite compression md5'/><category term='trendy programming bug'/><category term='scala actors fork join'/><category term='scala actors'/><category term='linear congruential random number generator maximal period'/><category term='passive'/><category term='liskov matchmaker photo'/><category term='API-design call-stack'/><category term='james gosling'/><category term='int overflow underflow average'/><category term='java.lang.Object synchronization cas cache sharing padding'/><category term='transitivity-utils transitive relation'/><category term='iterator'/><category term='consistent hashing hashtables sorting counting sort bigtable'/><category term='JComboBox'/><category term='GFS bandwidth google filesystem replicas'/><category term='enumerate directed acyclic graphs'/><category term='PhantomReference java finalization'/><category term='java puzzler'/><category term='trampoline python yield generator'/><category term='java random contention'/><category term='google collections recursive union'/><category term='java dsl xml'/><category term='pet projects java jbenchy flexigraph memory-measurer'/><category term='Matrix chain order CLRS dynamic programming'/><title type='text'>Code-o-matic</title><subtitle type='html'>The programming blog of Dimitris Andreou</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://code-o-matic.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6958126065976802292/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://code-o-matic.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Dimitris Andreou</name><uri>https://profiles.google.com/116229150468867889128</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-l6gGcDEXxqI/AAAAAAAAAAI/AAAAAAAABq0/x5Wy-h5G81Y/s512-c/photo.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>35</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-6958126065976802292.post-4817655722294762075</id><published>2011-08-11T19:56:00.001-07:00</published><updated>2011-08-11T19:56:41.931-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='java.lang.Object synchronization cas cache sharing padding'/><title type='text'>Few words on false sharing of cache lines</title><content type='html'>&lt;span class="Apple-style-span" style="background-color: white; font-family: Arial, sans-serif; font-size: 13px; line-height: 18px;"&gt;Spent some quality time reading the native code behind java.lang.Object, particularly checking how synchronization is implemented (really complicated code, and critically important for the whole platform as you can imagine)﻿.&lt;br /&gt;&lt;br /&gt;It is implemented like this (ton of details left out): of the 8 bytes of the object, 4 of them, if the object is used as a lock, are interpreted as a pointer to some ObjectMonitor, basically a queue of waiting threads. The implied CAS operation associated with entering or exiting a synchronized block is targetted (unless I misread it), to a word _inside_ the bytes of the Object, not the linked structure. This basically means that if you have an "locks" Object[8] array (initialized with "new Object()" in a loop), and you grab lock[3] from one thread, and lock[7] from another, these are likely to interfere with one another (CASes on the same cache line, one succeeding may spuriously cause the other to fail and retry). ReentrantLock is less&amp;nbsp;susceptible&amp;nbsp;to this problem, since it weighs at 40 bytes instead of 8, but still. All of this is fixable through padding.&lt;br /&gt;&lt;br /&gt;This is not to imply that only CAS operations on nearby locations are a problem; even plain writes/reads of nearby memory locations from different threads will cause false cache sharing and increased cache coherency traffic.&amp;nbsp;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6958126065976802292-4817655722294762075?l=code-o-matic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://code-o-matic.blogspot.com/feeds/4817655722294762075/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://code-o-matic.blogspot.com/2011/08/few-words-on-false-sharing-of-cache.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6958126065976802292/posts/default/4817655722294762075'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6958126065976802292/posts/default/4817655722294762075'/><link rel='alternate' type='text/html' href='http://code-o-matic.blogspot.com/2011/08/few-words-on-false-sharing-of-cache.html' title='Few words on false sharing of cache lines'/><author><name>Dimitris Andreou</name><uri>https://profiles.google.com/116229150468867889128</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-l6gGcDEXxqI/AAAAAAAAAAI/AAAAAAAABq0/x5Wy-h5G81Y/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6958126065976802292.post-6327767302971943988</id><published>2011-03-28T14:02:00.000-07:00</published><updated>2011-03-28T14:02:01.793-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='james gosling'/><title type='text'>James Gosling at Google!</title><content type='html'>Woohoo! James just joined Google!! Finally!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6958126065976802292-6327767302971943988?l=code-o-matic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://code-o-matic.blogspot.com/feeds/6327767302971943988/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://code-o-matic.blogspot.com/2011/03/james-gosling-at-google.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6958126065976802292/posts/default/6327767302971943988'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6958126065976802292/posts/default/6327767302971943988'/><link rel='alternate' type='text/html' href='http://code-o-matic.blogspot.com/2011/03/james-gosling-at-google.html' title='James Gosling at Google!'/><author><name>Dimitris Andreou</name><uri>https://profiles.google.com/116229150468867889128</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-l6gGcDEXxqI/AAAAAAAAAAI/AAAAAAAABq0/x5Wy-h5G81Y/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6958126065976802292.post-395348791025200658</id><published>2011-01-18T00:13:00.000-08:00</published><updated>2011-02-02T09:12:14.810-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='active'/><category scheme='http://www.blogger.com/atom/ns#' term='API-design call-stack'/><category scheme='http://www.blogger.com/atom/ns#' term='trampoline python yield generator'/><category scheme='http://www.blogger.com/atom/ns#' term='iterator'/><category scheme='http://www.blogger.com/atom/ns#' term='state machine'/><category scheme='http://www.blogger.com/atom/ns#' term='scala actors'/><category scheme='http://www.blogger.com/atom/ns#' term='passive'/><title type='text'>A note on API Design - call-stack as the source of a pervasive duality</title><content type='html'>I'll talk about few simple, often overlooked, yet pervasive and important, aspects of API design. They come by many names and many forms; if you have written code of any length, you have already faced at some level what I'm going to discuss. Long story short: almost any non-trivial API can be meaningfully designed in two, in some sense dual ways. Don't pick randomly. If your library is popular and frequently used, this matter has profound importance: chances are that users will press for an implementation of the dual, no matter which way you chose to offer - not always realizing that what they asked for is already implemented, just turned "inside out". If you don't realize this duality, you risk mindlessly duplicating lots of things, without realizing it, increasing the entropy of your library.&lt;br /&gt;&lt;br /&gt;So my bet is that if you are doing API design, you are probably interested. (&lt;b&gt;Edit:&lt;/b&gt; if you want to understand actors, you might also be interested!)&lt;br /&gt;&lt;br /&gt;This is certainly not just a theoretical issue. Some well known manifestations of the phenomenon in the real world:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;The introduction of &lt;a href="http://stax.codehaus.org/Home"&gt;StAX&lt;/a&gt;, while &lt;a href="http://sax.sourceforge.net/"&gt;SAX&lt;/a&gt; was there&lt;/li&gt;&lt;li&gt;The many requests (or cries) for having Collection#forEach() kind of methods, to complement the #iterator()-based approach (&lt;a href="http://gafter.blogspot.com/2007/07/internal-versus-external-iterators.html"&gt;related post by Neal Gafter&lt;/a&gt;)&lt;/li&gt;&lt;li&gt;Scala collections, which offer both iteration styles (passing a callback, or getting an iterator)&lt;/li&gt;&lt;li&gt;Servlets (which are callbacks) vs &lt;a href="http://rifers.org/"&gt;RIFE&lt;/a&gt; framework (recall their motto, "do scanf() over the web?" - they perceived that in this way the brought the "simplicity of console applications programming to the web".)&lt;/li&gt;&lt;li&gt;Callbacks, continuations, python's nifty "yield" (generators), trampolines, all come from the some place as well.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;And that place is the good old call-stack.&lt;br /&gt;&lt;br /&gt;Some (very) basic concepts up-front, to make sure we are on the same page. By "API", we usually refer to the layer through which user code and library code communicates. In Java, that is methods and the types they are defined in. Communication between these two parties (in either direction) typically happens by invoking methods: user code invoking library code, or the inverse (after the user code hands some callbacks to the library code, of course, since the library doesn't know its users). Method invocation occurs in a thread. The caller's stackframe issues the invocation to the callee, which pushes the callee's stackframe on the call-stack. Since it is a stack, the caller's stackframe (i.e., local variables + program counter) outlives the one of the callee. Trivial fact, but not trivial consequences.&lt;br /&gt;&lt;br /&gt;Now, consider any two state machines that need to work together. When you are using an iterator, you are interacting with a state machine. When you pass callbacks to a parser, you interact with a state machine. Your program is a state machine, anything you invoke is also one - but we will concern ourselves with non-trivial state machines - even a pure function is a state machine, but it has only a single, unchanging state.&lt;br /&gt;&lt;br /&gt;Since we are talking about API design, say one state machine is provided as a "library", and the other is "user code", communicating through some API (I only need to address the case of *two* state-machines; for more, you can recursively apply the same arguments). To make it concrete, lets use as an example these very simple state machines:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;A state machine that remembers/reports the maximum element it has seen&lt;/li&gt;&lt;li&gt;A state machine that produces a set of elements&lt;/li&gt;&lt;/ul&gt;And we want to combine them together so we compute the maximum element of a set.&lt;br /&gt;&lt;br /&gt;In a single thread's call-stack, one of these must be deeper in the stack than the other, thus there are only two different configurations to arrange this interaction. One must play the role of the caller (for lack of a better name, I'll call this role &lt;b&gt;active&lt;/b&gt;, because it is the one that initiates the invocations to the second), the other must play the role of the callee (&lt;b&gt;passive&lt;/b&gt;&amp;nbsp;- it reacts to invocations by the active one). The messaging works as follows: The caller (active) passes a message by &lt;i&gt;invoking&lt;/i&gt;, the callee (passive) answers by &lt;i&gt;returning&lt;/i&gt; (and it has to return, if the computation ever halts).&lt;br /&gt;&lt;br /&gt;Lets see the two arrangements of the the aforementioned state machines, in very simplified code:&lt;br /&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;b&gt;//library - active&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;static int findMax(Iterator&lt;integer&gt; integers) {&lt;/integer&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp;int max = Integer.MIN_VALUE; &lt;b&gt;// &amp;lt;-- call-stack encoded state&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp;while (integers.hasNext()) {&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;max = Math.max(max, integers.next());&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp;}&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp;return max;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;b&gt;//user code - passive&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;class ValuesFromAnArray implements Iterator&lt;integer&gt; {&lt;/integer&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp;private final int[] array;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp;private int position; //heap-encoded state&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp;ValuesFromAnArray(int[] array) {&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;this.array = array;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp;}&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;b&gt;// API layer between library and user code&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;b&gt;&lt;/b&gt;&amp;nbsp;&amp;nbsp;public Integer next() {&amp;nbsp;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;if (!hasNext()) throw new NoSuchElementException();&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;return array[position++];&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;b&gt;// API layer between library and user code&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;b&gt;&lt;/b&gt;&amp;nbsp;&amp;nbsp;public boolean hasNext() {&amp;nbsp;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;return position &amp;lt; array.length;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp;}&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;}&lt;/span&gt;&lt;br /&gt;(I don't concern myself with trivialities like how to wrap the Iterator into an Iterable).&lt;br /&gt;&lt;br /&gt;Here, the library is active. The user code returns a value, and updates its state (which must be stored in the heap) so next time it will return the next value. The active library has an easier job - it only uses a local var for its state, and it doesn't have to explicitly store where it was (so it can come back to it) before calling the user code, since it implicitly uses the &lt;i&gt;program counter&lt;/i&gt; to store that information. (And if you think about it, if you have a method and you have 8 independent positions, like nested if's of depth equal to 3, and you enter one of them, you effectively use the program counter to encode &lt;i&gt;3 bits of information&lt;/i&gt;. To turn this into a heap-based state machine, be sure to remember to encode those three bits in the heap as well!) The passive user code is basically a simplistic iterator (and iterators are a fine example of constructs designed to be passive).&lt;br /&gt;&lt;br /&gt;The other option is this:&lt;br /&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;b&gt;//user code - active&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;int[] array = ...;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;MaxFinder m = new MaxFinder();&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;for (int value : array) {&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp;m.seeValue(value);&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;int max = m.max();&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;b&gt;//library - passive&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;class MaxFinder {&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp;private int max = Integer.MIN_VALUE; &lt;b&gt;//heap-encoded state&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;b&gt;// API layer between user code and library&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;b&gt;&lt;/b&gt;&amp;nbsp;&amp;nbsp;void seeValue(int value) {&amp;nbsp;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;max = Math.max(max, value);&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp;}&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;b&gt;// API layer between user code and library&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp;int max() {&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;return max;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp;}&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;In this case, the user code is active and the library is passive. Again, the passive one is forced to encode its state in the heap.&lt;br /&gt;&lt;br /&gt;Both work. All we did is a simple mechanical transformation to go from the one to the other. The question for the library designer:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Which option to offer? (Or offer both??)&lt;/li&gt;&lt;/ul&gt;That's not so trivial. Lets try to compare:&lt;br /&gt;&lt;br /&gt;&lt;b&gt;1. Syntax:&lt;/b&gt; There is no doubt that having the option to encode your state in the call-stack is a big &lt;i&gt;syntactic&lt;/i&gt;&amp;nbsp;win (big, but only syntactic). Not so much because of local vars, but because of the program counter: All those nifty for-loops, nested if statements and what not, look so ugly when encoded in the heap. For example, here is some active user code:&lt;br /&gt;&lt;br /&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;MaxFinder maxFinder = new MaxFinder();&lt;/span&gt;&lt;/div&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;for (int i = 0; i &amp;lt; 10; i++) {&lt;/span&gt;&lt;/div&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp;for (int j = 0; j &amp;lt; 5; j++) {&lt;/span&gt;&lt;/div&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;maxFinder.seeValue(someComplicatedFunction(i, j));&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp;}&lt;/span&gt;&lt;/div&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;}&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;br /&gt;&lt;/span&gt;Easy. Lets see what happens if we try to transform this into passive user code:&lt;br /&gt;&lt;br /&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;return new AbstractIterator&lt;integer&gt;() { //Guava's AbstractIterator for convenience&lt;/integer&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp;int i = 0;&lt;/span&gt;&lt;/div&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp;int j = 0;&lt;/span&gt;&lt;/div&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp;protected Integer computeNext() {&lt;/span&gt;&lt;/div&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;try {&lt;/span&gt;&lt;/div&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp;return (i &amp;lt; 5) ? someComplicatedFunction(i, j) : endOfData();&lt;/span&gt;&lt;/div&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;} finally {&lt;/span&gt;&lt;/div&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp;j++;&lt;/span&gt;&lt;/div&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp;if (j &amp;gt;= 5) {&lt;/span&gt;&lt;/div&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; i++;&lt;/span&gt;&lt;/div&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; j = 0;&lt;/span&gt;&lt;/div&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp;}&lt;/span&gt;&lt;/div&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;}&lt;/span&gt;&lt;/div&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp;}&lt;/span&gt;&lt;/div&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;Ouch - that's like we took a shotgun and splattered the previous code into pieces. Of course, I'm biased: after having read countless for-loops, I tend to understand them more easily and think them simpler, compared to the individual pieces of them scattered here and there. "It's just syntax", in the end (mind you, the difference could be a lot worse though).&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;2. Composability&lt;/b&gt;: Now this is not aesthetics any more, but it's a more serious question between "works" or "doesn't work". If you offer your library as active, you force the user code to be passive. If the user code is already written, and is active, &lt;i&gt;then it simply can't work with the active library&lt;/i&gt;. It is precisely this user that will complain to you about your library and/or ask you to offer a passive counterpart in addition to the active you already offered. One of the two parties must agree to use &lt;i&gt;return&lt;/i&gt;&amp;nbsp;to send a message back, instead of recursively invoking a method. If neither is passive, the result will be infinite recursion. &lt;i&gt;An active participant requires control of the call-stack for the duration of the coordination&lt;/i&gt; (corollary, two actives can only work together if each one has its own call-stack - see "trampoline" below). But if you offer your library as passive, &lt;i&gt;you don't preclude any option for the user&lt;/i&gt; (it can be either active or passive), and thus this is the most flexible.&amp;nbsp;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;To exemplify the last point, (this is an adaptation from &lt;a href="http://gafter.blogspot.com/2007/07/internal-versus-external-iterators.html/"&gt;Gafter's post&lt;/a&gt;) suppose we have two lists and we want to test whether they are equal. If we can produce iterators (i.e., passive state machines), it is easy:&lt;br /&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;//&lt;b&gt;PassiveList offers #iterator()&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;boolean areEqual(PassiveList list1, PassiveList list2) {&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp;if (list1.size() != list2.size()) return false;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp;Iterator i1 = list1.&lt;b&gt;iterator()&lt;/b&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp;Iterator i2 = list2.&lt;b&gt;iterator()&lt;/b&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp;while (i1.&lt;b&gt;hasNext()&lt;/b&gt;) {&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;if (i1.&lt;b&gt;next()&lt;/b&gt; != &lt;b&gt;i2.next()&lt;/b&gt;) return false;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp;}&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp;return true;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;If one of the lists was active (had a #forEach() operation instead of giving an iterator), it is still implementable, let the active control the passive:&lt;br /&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;b&gt;//ActiveList offers #forEach(ElementHandler)&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;boolean areEqual(ActiveList activeList, PassiveList passiveList) {&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp;if (activeList.size() != passiveList.size()) return false;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp;final Iterator iterator = passiveList.&lt;b&gt;iterator()&lt;/b&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp;final boolean[] equal = { true };&amp;nbsp;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp;activeList.&lt;b&gt;forEach(new ElementHandler() {&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;b&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;public void process(Object e)&lt;/b&gt; {&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp;if (e != iterator.&lt;b&gt;next()&lt;/b&gt;) equal[0] = false;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;} //don't nitpick about not breaking early!&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp;});&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp;return equal[0];&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;But in principle, it's not possible to implement the following method, without spawning a second thread (again, see trampoline, below), :&lt;br /&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;//both are active!&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;boolean areEqual(ActiveList list1, ActiveList list2);&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;3) Exceptions: &lt;/b&gt;Another (Java-specific) way that the two option differ is &lt;i&gt;checked exceptions&lt;/i&gt;, unfortunately. If you create an active library, you have to anticipate your passive user code may require to throw checked exceptions - so creating the API (implemented by user code) without knowing the checked exceptions beforehand is problematic and ugly (this have to somehow be reflected in the API signatures, and generified exceptions are not for the weak-hearted), whereas if you let the user code take the active position, it is oh-too-easy for the user code to wrap the whole thing in a try/catch or add a throws clause in the enclosing method (the enclosing method is of not offered by your library and is no concern to you - if it is not &lt;i&gt;your &lt;/i&gt;code that throws checked exceptions, you don't have to worry about them, and this is good). &lt;span class="Apple-style-span" style="font-size: xx-small;"&gt;Oh well. Just another reason we all should be doing scala, eventually. Lets quickly hide this under the carpet for now.&lt;/span&gt;&amp;nbsp;Credit for noting this important caveat goes to Chris Povirk.&lt;br /&gt;&lt;br /&gt;So where these considerations leave us? My rules of thumb (not entirely contradiction-free):&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;&lt;i&gt;Let the more complicated participant have the active position&lt;/i&gt;; that piece of code will benefit the most by having its stackframe available for encoding its state.&amp;nbsp;&lt;/li&gt;&lt;li&gt;If you provide a library, &lt;i&gt;offer it as passive&lt;/i&gt; - so you leave all options open for the user.&lt;br /&gt;&lt;br /&gt;But what to do if you anticipate *the library* to be the more complicated participant? Do you choose to make it active and force user code to be passive? What if you are wrong in your estimation? It's a tough call. But in the end, if you are forced to offer your library also as active, at least place that version near the passive one, so it's apparent that these two perform the same function, and so the users have to look for this functionality at a single place, not two.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;If though the library is supposed to offer parallelization to the user, there is no option: you &lt;b&gt;have&lt;/b&gt;&amp;nbsp;to make it active, because parallelization boils down to controlling how to invoke user's code. (See &lt;a href="http://gee.cs.oswego.edu/dl/jsr166/dist/extra166ydocs/extra166y/ParallelArray.html"&gt;ParallelArray&lt;/a&gt;'s active operations. This also offers a passive iterator, but it would be folly to use it)&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;That was the meat of this post. I mentioned trampolines above, so in the remaining part, I'll touch upon that.&lt;br /&gt;&lt;br /&gt;Python generators are, indeed, beautiful. You write an &lt;i&gt;active&lt;/i&gt; piece of code, and some python (alas, very inefficient) piece of magic transforms it into a &lt;i&gt;passive&lt;/i&gt; construct (iterator) out of that (which, recall, can be used with another active counterpart). Thus, you get the best of both worlds: &lt;b&gt;both&lt;/b&gt;&amp;nbsp;parties (e.g. producer and consumer, here) can be active!&lt;br /&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;b&gt;//producer - active!&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;Iterator&lt;integer&gt; iterator = magicTrampoline(new AbstractProducer&lt;integer&gt;() {&lt;/integer&gt;&lt;/integer&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp;public void run() {&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;for (int i = 0; i &amp;lt; 10; i++) {&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp;for (int j = 0; j &amp;lt; 5; j++) {&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;produce(complicatedFunction(i, j));&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp;}&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;}&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp;}&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;};&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;b&gt;//consumer - active!&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;while (iterator.hasNext())&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp;consume(iterator.next());&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;This is certainly the best option for code readability. The cost is, we need an extra thread (more precisely, we need an extra call-stack). "Trampoline" is the common name of the port of this to Java. I wanted to link to some implementation here, but couldn't readily find a nice one. I'll just sketch the implementation anyway: the idea is that you let the producer run on a separate (from the consumer) thread. Thus message-passing between producer and consumer do not happen in the same call-stack, but via another means, say via a BlockingQueue (the producer puts, the consumer takes). So, the producer doesn't have to destroy its stackframe(s) after producing an element, but it can safely hold on to it (remember that this was not possible in the single-thread scenario, with message passing via the call-stack, that would lead to infinite recursion).&lt;br /&gt;&lt;br /&gt;&lt;b&gt;--EDIT&lt;/b&gt;&lt;br /&gt;&lt;b&gt;&lt;/b&gt;Sure I can find an implementation of the above - &lt;a href="http://www.google.com/search?sourceid=chrome&amp;amp;ie=UTF-8&amp;amp;q=scala+actors"&gt;scala actors&lt;/a&gt;! The actors interact in an active (of course!) fashion, and this is possible because they communicate by &lt;i&gt;exchanging messages, &lt;/i&gt;not&lt;i&gt; invocations&lt;/i&gt;, thus no party needs to play the passive role. (Of course, underneath there is the good old BlockingQueue and the trampoline mechanics mentioned above. ) And yet, even in scala actors, there are the so called reactive actors - these don't hold on to their thread (and their call-stack), thus are not as wasteful as the regular actors, but, as per the discussion above, they are passive. This is the way one can tie actors in this discussion, and understand these through a different perspective.&lt;br /&gt;&lt;b&gt;--/EDIT&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Since the cost for this is very high (not just the second thread itself, but the frequent blockings/context switches), it is not to be recommended in Java, unless we someday get much more lightweight threads, like those in Erlang. (And I can certainly imagine the joy of Erlang programmers, who can always readily use their call-stack to encode their complex state machines, instead of jumping through hops just so they do not introduce another thread.)&lt;br /&gt;&lt;br /&gt;(Another way to achieve this would be via continuations - which Java doesn't support natively.)&lt;br /&gt;&lt;br /&gt;And a departing story:&amp;nbsp;4 years ago, I played with these ideas in the context of implementing complex gesture detection for a graph editor, amongst other graph related tasks. Use-case: implement drag and drop for nodes (a common task). This is what my experimental code looked like - quite elegant:&lt;br /&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;b&gt;//active pattern detection!&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;Event firstEvent = awaitEvent();&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;if (firstEvent.isMouseDown()) {&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp;Event nextEvent;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp;while ((nextEvent = awaitEvent()).isMouseDrag()) {&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;continue;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp;}&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp;if (nextEvent.isMouseUp()) {&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;//drag and drop is complete!&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp;}&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;} else {&amp;nbsp;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp;...&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;If you have read all the way to here (phew!), you can probably imagine how "fun" (ugh) would be transforming the pattern detection to a passive, say, MouseListener/MouseMotionListener (and translating those if's and else's and while's...). Be my guest and try (I'm kidding - just don't). This is the source of my first rule of thumb: it was via such, sufficiently complicated state machines that I observed how much the code can be simplified just through the act of making it active.&lt;br /&gt;&lt;br /&gt;To better understand the last example and how it's relevant, note that Swing itself is an active state machine - remember, it owns&amp;nbsp;the event-dispatching thread, thus user code is forced into the passive role. (Which is also consistent with my first rule of thumb: swing, the most complex machinery, taking up the active, more convenient role).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6958126065976802292-395348791025200658?l=code-o-matic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://code-o-matic.blogspot.com/feeds/395348791025200658/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://code-o-matic.blogspot.com/2011/01/note-on-api-design-call-stack-as-source.html#comment-form' title='8 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6958126065976802292/posts/default/395348791025200658'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6958126065976802292/posts/default/395348791025200658'/><link rel='alternate' type='text/html' href='http://code-o-matic.blogspot.com/2011/01/note-on-api-design-call-stack-as-source.html' title='A note on API Design - call-stack as the source of a pervasive duality'/><author><name>Dimitris Andreou</name><uri>https://profiles.google.com/116229150468867889128</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-l6gGcDEXxqI/AAAAAAAAAAI/AAAAAAAABq0/x5Wy-h5G81Y/s512-c/photo.jpg'/></author><thr:total>8</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6958126065976802292.post-1116802042100381142</id><published>2010-12-29T21:32:00.000-08:00</published><updated>2010-12-29T21:35:45.125-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='t-mobile nexus-s customer support'/><title type='text'>An unhappy T-Mobile customer</title><content type='html'>I don't usually post things like this, but I'll get out of my way for this one. T-Mobile. I'm a customer for three days now, and I'm already deeply disappointed.&lt;br /&gt;&lt;br /&gt;So here is the story. I went to a T-Mobile store to activate an account. I already had my Nexus S and an unactivated T-Mobile simm card. I gave them my ssn, and opted for an unlimited data plan (plus 500 minutes of talk and unlimited messaging). So two days ago (it's 12/29/10 today) the 3G connectivity worked as advertized. You can see my recent activity too, as I can see it from the my.t-mobile site, where I can manage my account. See? There are ~4mb of downloads on 12/27. It worked.&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/_H1UVegJ_stI/TRwOp4mGEhI/AAAAAAAAANw/Oev1eyF69RA/s1600/Screenshot.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="268" src="http://4.bp.blogspot.com/_H1UVegJ_stI/TRwOp4mGEhI/AAAAAAAAANw/Oev1eyF69RA/s640/Screenshot.png" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;When I try to access a webpage from my mobile (turning wifi off, of course), I get redirected to a very cute page, of which I can't make a screenshot, but here is the text of it:&lt;br /&gt;&lt;br /&gt;[url: &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;http://m.web2.go.com/upsell/?msisdn=etc&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: Arial, Helvetica, sans-serif;"&gt; - the URL itself is...peculiar. What are they trying to upsell to me?&lt;/span&gt;]&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;span class="Apple-style-span"&gt;Subscription Required&lt;/span&gt;&lt;/blockquote&gt;&lt;blockquote&gt;Your are not currently subscribed to a data plan. Click here to view plans and get the entire web - right on your phone!&lt;/blockquote&gt;Also note the typo ("Your are not..."), yes, it looks professionally done. Anyway, my issue is that is claims I have no data plan, while actually I have an unlimited one. Thanks T-Mobile for messing with my account. It was certainly more fun driving back to google from an unknown place with no driving navigation, it did spice up my day, and I'm grateful for that.&lt;br /&gt;&lt;br /&gt;Next weirdness, and this is really, &lt;i&gt;really&lt;/i&gt;&amp;nbsp;weird, in the &lt;i&gt;what were they frikking thinking???? &lt;/i&gt;kind of sense. In the process of trying to get online help through chat from a T-Mobile agent, I went to the my.t-mobile page again, to copy and paste my services, to make a point that &lt;i style="font-weight: bold;"&gt;I do pay for an unlimited data plan thankyouverymuch&lt;/i&gt;. So this is the page I got:&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/_H1UVegJ_stI/TRwT1x4dCcI/AAAAAAAAAN0/7oFDSa-fgOk/s1600/Screenshot-1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="369" src="http://2.bp.blogspot.com/_H1UVegJ_stI/TRwT1x4dCcI/AAAAAAAAAN0/7oFDSa-fgOk/s640/Screenshot-1.png" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;Note two things: "&lt;b&gt;Unlimited Web"&lt;/b&gt;, &lt;i&gt;and &lt;/i&gt;that only "minutes" services are listed below. I tried to copy-paste this whole text to the T-Mobile agent. &lt;b style="font-style: italic;"&gt;To my huge amazement, the pasted text did not match what you read above!!! &lt;/b&gt;Here is the copied/pasted of that same page:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;b&gt;Even More Plus™ 500 Talk + Unlimited Text + Unlimited Web&lt;/b&gt;&lt;/blockquote&gt;&lt;blockquote&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;500 Whenever minutes&lt;/blockquote&gt;&lt;blockquote&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;Unlimited Weekend Minutes&lt;/blockquote&gt;&lt;blockquote&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;Unlimited Weeknight Minutes&lt;/blockquote&gt;&lt;blockquote&gt;&lt;br /&gt;&lt;/blockquote&gt;&lt;blockquote&gt;&lt;b&gt;Plan on this line&lt;/b&gt;&lt;/blockquote&gt;&lt;blockquote&gt;&lt;b&gt;We're sorry. Some of your plans and services information is currently unavailable. Please try again later.&lt;/b&gt;&lt;/blockquote&gt;&lt;br /&gt;Wow, T-Mobile! Thanks for using invisible font to inform me that my plan is currently unavailable! Gee, who in their right minds want to read about problems? Lets just hide it!!! Problem solved! Well, not quite.&lt;br /&gt;&lt;br /&gt;So, I'm basically forced to visit their store again, tomorrow. An hour of my life to the drain, and lets see if they can fix whatever the problem is.&lt;br /&gt;&lt;br /&gt;In the bottom below, I paste (hopefully no new text will be revealed in this one!) the transcript from the agent that tried to "help" me. Basically I got zero help and zero explanation for anything, apart from the always helpful suggestion to remove my battery for 30 seconds and try again. At least there was an excuse: he couldn't verify my SSN number. This is pretty fascinating by itself, because later I called another T-Mobile agent, where that agent confessed that my SSN number was missing from my account, for whatever reason. Nevertheless, the first agent asked for the last digits of my SSN, and pretended to "try" to verify it (i.e., check if these matched an...altogether missing SSN number!). "I do apologize that is not the last 4 digits of your ssn listed on your account" was the precise response.&lt;br /&gt;&lt;br /&gt;I then specifically asked for what the problem could be, because obviously it couldn't be a typo - &lt;i&gt;and he never mentioned that there was no SSN at all!! &lt;/i&gt;Also, all my offers to identify me with a variety of other ways - digits from my credit card, my bank account number, my routing number, were futile, since apparently they only use (the missing in this case!) SSN number! Not even a passport number or an id or whatever. It's kind of ironic that the first time I went to their store, I had to leave and come back with my passport, &lt;i&gt;because my SSN was not enough.&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;I wonder: Is there any wireless network provider in the US with decent customer support? Or decent services that &lt;i&gt;don't need&lt;/i&gt;&amp;nbsp;decent customer support, which would be ideal -&amp;nbsp;I'm open to suggestions (just as long as my nexus s is compatible).&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Customer Chat&lt;br /&gt;Chat Transcript&lt;br /&gt;Please wait while we find an agent to assist you...&lt;br /&gt;You are currently at position number 3 in the queue.&lt;br /&gt;All agents are currently busy. Please stand by.&lt;br /&gt;You are currently at position number 1 in the queue.&lt;br /&gt;An agent will be with you in a moment. Thank you for your patience.&lt;br /&gt;You are currently at position number 1 in the queue.&lt;br /&gt;The next available Agent will be with you in a moment.&lt;br /&gt;You are currently at position number 1 in the queue.&lt;br /&gt;You have been connected to ^Gavin H.&lt;br /&gt;&lt;b&gt;Dimitrios Andreou:&lt;/b&gt; When I try to access a webpage from my nexus s (I have an unlimited data plan, supposedly), I get redirected to http://m.web2go.com/upsell?msisdn=etc, which contains the following text: " Subscription Required Your (sic) are not currently subscribed to a data plan. Click here to view plans and get the entire web - right from your phone! " This doesn't make any sense. What is the cause of this? At least 2 days earlier my 3g connection was working properly.&lt;br /&gt;&lt;b&gt;^Gavin H:&lt;/b&gt; &amp;nbsp;Hi Dimitrios , welcome to T-Mobile live Chat. I’m ^Gavin and I will be happy to assist you. Please give me a moment to review your question.&lt;br /&gt;&lt;b&gt;^Gavin H:&lt;/b&gt; &amp;nbsp;thank you for holding Dimitrios, I can certainly understand why you contacted us about this today. I would love to assist you&lt;br /&gt;with this today.&lt;br /&gt;&lt;b&gt;Dimitrios Andreou: &lt;/b&gt;&amp;nbsp;Hi Gavin, hopefully you'll be able to help indeed :)&lt;br /&gt;&lt;b&gt;^Gavin H:&lt;/b&gt; &amp;nbsp;Please bear with me for 2 to 3 minutes while I look over this issue for you.&lt;br /&gt;&lt;b&gt;Dimitrios Andreou:&lt;/b&gt; &amp;nbsp;sure&lt;br /&gt;&lt;b&gt;^Gavin H:&lt;/b&gt; &amp;nbsp;Can you verify the the last 4 digits of your ssn for me please.&lt;br /&gt;&lt;b&gt;Dimitrios Andreou:&lt;/b&gt;&amp;nbsp;&amp;nbsp;****&lt;br /&gt;&lt;b&gt;^Gavin H:&lt;/b&gt; &amp;nbsp;I do apologize that is not the last 4 digits of your ssn listed on your account.&lt;br /&gt;&lt;b&gt;Dimitrios Andreou:&lt;/b&gt; &amp;nbsp;huh? let me check again&lt;br /&gt;&lt;b&gt;Dimitrios Andreou:&lt;/b&gt; &amp;nbsp;no, these are certainly the last 4 digits of my ssn&lt;br /&gt;&lt;b&gt;^Gavin H:&lt;/b&gt; &amp;nbsp;I do apologize that is not the ssn listed n your account.&lt;br /&gt;&lt;b&gt;Dimitrios Andreou:&lt;/b&gt; &amp;nbsp;so how can we fix that?&lt;br /&gt;&lt;b&gt;^Gavin H:&lt;/b&gt; &amp;nbsp;I can help you with basic troubleshooting today but I would not be able to make any account changes today.&lt;br /&gt;&lt;b&gt;Dimitrios Andreou:&lt;/b&gt; &amp;nbsp;I'd like to know what's the problem with my account's ssn record then&lt;br /&gt;&lt;b&gt;Dimitrios Andreou:&lt;/b&gt; &amp;nbsp;also, I'm sure you can identify me via other means, e.g. I could give you the last 4 digits of my credit card&lt;br /&gt;&lt;b&gt;Dimitrios Andreou:&lt;/b&gt; &amp;nbsp;or account number, or routing number&lt;br /&gt;&lt;b&gt;^Gavin H:&lt;/b&gt; &amp;nbsp;Unfortuanately only the ssn is listed on your account that can verify you.&lt;br /&gt;&lt;b&gt;Dimitrios Andreou:&lt;/b&gt; &amp;nbsp;this doesn't make sense. You are not giving me any explanation. This can't possibly just be a typo (I activated my account two or three days ago, giving my ssn as the authorities provided it to me)&lt;br /&gt;&lt;b&gt;Dimitrios Andreou: &lt;/b&gt;&amp;nbsp;in any case, this is irrelevant to my problem. How do you explain that while I have unlimited data plan, I get redirected to the page I mentioned in my original question?&lt;br /&gt;&lt;b&gt;^Gavin H:&lt;/b&gt; &amp;nbsp;When did you add your data plan.&lt;br /&gt;&lt;b&gt;Dimitrios Andreou:&lt;/b&gt; &amp;nbsp;two or three days ago, when I activated my account with t-mobile&lt;br /&gt;&lt;b&gt;^Gavin H:&lt;/b&gt; &amp;nbsp;This issue sounds like it is a account provisioning probelm and I can not check to see if your account is setup correctly if your account is not verified.&lt;br /&gt;&lt;b&gt;^Gavin H:&lt;/b&gt; &amp;nbsp;are you able to make calls?&lt;br /&gt;&lt;b&gt;Dimitrios Andreou: &lt;/b&gt;&amp;nbsp;yes, I am&lt;br /&gt;&lt;b&gt;Dimitrios Andreou:&lt;/b&gt; &amp;nbsp;can you help me understand what "account provisioning problem" might mean?&lt;br /&gt;&lt;b&gt;^Gavin H:&lt;/b&gt; &amp;nbsp;That there could be something that is incorrect on your account or has not been added to your account.&lt;br /&gt;&lt;b&gt;Dimitrios Andreou: &lt;/b&gt;&amp;nbsp;also, 3g connectivity worked two days ago&lt;br /&gt;&lt;b&gt;Dimitrios Andreou:&lt;/b&gt; &amp;nbsp;so what changed since then?&lt;br /&gt;&lt;b&gt;^Gavin H:&lt;/b&gt; &amp;nbsp;I would be unable to tell if there has been any account changes until your account is verified. Can you turn your phone off and remive the battery for 30 seconds for me please then turn your phone back on for me please.&lt;br /&gt;&lt;b&gt;Dimitrios Andreou:&lt;/b&gt; &amp;nbsp;(If you are able to see, you can check that my "Recent Use" page has around 4mb of downloads on 12/27, but nothing more recently than that)&lt;br /&gt;&lt;b&gt;Dimitrios Andreou:&lt;/b&gt; &amp;nbsp;ok&lt;br /&gt;&lt;b&gt;^Gavin H: &lt;/b&gt;&amp;nbsp;Let me know when you are back at the main screen of the phone.&lt;br /&gt;&lt;b&gt;Dimitrios Andreou:&lt;/b&gt; &amp;nbsp;back in the main screen (opened a browser, same redirection happens)&lt;br /&gt;&lt;b&gt;Dimitrios Andreou: &lt;/b&gt;&amp;nbsp;can I definitely make sure what my data plan is, through the my.t-mobile site?&lt;br /&gt;&lt;b&gt;^Gavin H:&lt;/b&gt; &amp;nbsp;Okay, I would advise you to go to your local T-Mobile store location and show 2 forms of id to change your ssn on your account. This will enable us to access your account to see if there is a account probelm.&lt;br /&gt;&lt;b&gt;Dimitrios Andreou:&lt;/b&gt; &amp;nbsp;Ok, I go to "Manage -&amp;gt; Plans &amp;amp; Services, and I get this:&lt;br /&gt;&lt;b&gt;Dimitrios Andreou:&lt;/b&gt; &amp;nbsp;Dimitrios's plan Change plan&lt;br /&gt;&lt;br /&gt;Even More Plus™ 500 Talk + Unlimited Text + Unlimited Web&lt;br /&gt;500 Whenever minutes&lt;br /&gt;Unlimited Weekend Minutes&lt;br /&gt;Unlimited Weeknight Minutes&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Plan on this line&lt;br /&gt;&lt;br /&gt;We're sorry. Some of your plans and services information is currently unavailable. Please try again later.&lt;br /&gt;&lt;br /&gt;Services on Dimitrios's line&lt;br /&gt;&lt;br /&gt;In addition to the shared plan and services on this account (detailed above), this line also has the following services:&lt;br /&gt;There are no additional services active on this line in your account.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Dimitrios Andreou:&lt;/b&gt; &amp;nbsp;can you explain that? Or I have to go to the store again?&lt;br /&gt;&lt;b&gt;Dimitrios Andreou:&lt;/b&gt; &amp;nbsp;huh, this is very weird&lt;br /&gt;&lt;b&gt;^Gavin H:&lt;/b&gt; &amp;nbsp;We are uanle to access your account without you giving us the correct ssn on your account. You can change your ssn by going to your local T-Mobile retail store and showing them 2 forms of id to verify who you are. This will enable us to access your account to see if there is a account probelm&lt;br /&gt;&lt;b&gt;Dimitrios Andreou:&lt;/b&gt; &amp;nbsp;Gavin, will you spend a minute seeing what I get? This is truly very weird. See this text: "We're sorry. Some of your plans and services information is currently unavailable. Please try again later."&lt;br /&gt;&lt;b&gt;Dimitrios Andreou:&lt;/b&gt; &amp;nbsp;What is weird about it is that it is invisible in the my.t-mobile page, it was only revealed when I copied/pasted it!&lt;br /&gt;&lt;b&gt;Dimitrios Andreou:&lt;/b&gt; &amp;nbsp;no explanation for that either?&lt;br /&gt;&lt;b&gt;^Gavin H:&lt;/b&gt; &amp;nbsp;This could be a account error on are end if you would like to check to see if ther are other steps you can try to get your data service back you can contact samsung to troubleshoot your phone.&lt;br /&gt;&lt;b&gt;Dimitrios Andreou:&lt;/b&gt; &amp;nbsp;ok. you can't help me, I guess. I'll publish this, and go to the store tomorrow.&lt;br /&gt;&lt;b&gt;Dimitrios Andreou:&lt;/b&gt; &amp;nbsp;thanks for your time&lt;br /&gt;&lt;b&gt;^Gavin H:&lt;/b&gt; &amp;nbsp;Is there anything else we can assist you with today?&lt;br /&gt;&lt;b&gt;Dimitrios Andreou:&lt;/b&gt; &amp;nbsp;nop&lt;br /&gt;&lt;b&gt;^Gavin H:&lt;/b&gt; &amp;nbsp;Thank you for contacting T-Mobile Chat, have a great day!&lt;br /&gt;&lt;b&gt;Dimitrios Andreou:&lt;/b&gt; &amp;nbsp;goodbye&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6958126065976802292-1116802042100381142?l=code-o-matic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://code-o-matic.blogspot.com/feeds/1116802042100381142/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://code-o-matic.blogspot.com/2010/12/unhappy-t-mobile-customer.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6958126065976802292/posts/default/1116802042100381142'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6958126065976802292/posts/default/1116802042100381142'/><link rel='alternate' type='text/html' href='http://code-o-matic.blogspot.com/2010/12/unhappy-t-mobile-customer.html' title='An unhappy T-Mobile customer'/><author><name>Dimitris Andreou</name><uri>https://profiles.google.com/116229150468867889128</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-l6gGcDEXxqI/AAAAAAAAAAI/AAAAAAAABq0/x5Wy-h5G81Y/s512-c/photo.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_H1UVegJ_stI/TRwOp4mGEhI/AAAAAAAAANw/Oev1eyF69RA/s72-c/Screenshot.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6958126065976802292.post-3599912072659369247</id><published>2010-12-12T23:19:00.000-08:00</published><updated>2011-01-07T13:33:24.658-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='linear congruential random number generator maximal period'/><title type='text'>How long is the period of random numbers created by java.util.Random?</title><content type='html'>&lt;span class="Apple-style-span" style="font-family: Arial, Helvetica, sans-serif;"&gt;The answer is, &lt;i&gt;pretty darn long!&lt;/i&gt;&amp;nbsp;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: Arial, Helvetica, sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: Arial, Helvetica, sans-serif;"&gt;I feel a bit cheated for not knowning, while I had several times seen the code the years before.&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: Arial, Helvetica, sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: Arial, Helvetica, sans-serif;"&gt;So it uses a good old linear congruential generator:&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: Arial, Helvetica, sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: Arial, Helvetica, sans-serif;"&gt;x = A * x + C&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: Arial, Helvetica, sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: Arial, Helvetica, sans-serif;"&gt;So, java.util.Random uses these two constants (A and C respectively):&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;private final static long multiplier = 0x5DEECE66DL;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;private final static long addend = 0xBL;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: Arial, Helvetica, sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: Arial, Helvetica, sans-serif;"&gt;Quite appropriate to place two "random" numbers in the Random class, right? Only these are not &lt;i&gt;entirely&amp;nbsp;&lt;/i&gt;random...&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: Arial, Helvetica, sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: Arial, Helvetica, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;0x5DEECE66DL&lt;/span&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;% 8 == 5&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: Arial, Helvetica, sans-serif;"&gt;and&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: Arial, Helvetica, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;0xBL &lt;/span&gt;is an odd.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: Arial, Helvetica, sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;span class="Apple-style-span" style="font-family: Arial, Helvetica, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-family: Arial, Helvetica, sans-serif;"&gt;So what?&amp;nbsp;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: Arial, Helvetica, sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: Arial, Helvetica, sans-serif;"&gt;It turns out, when these exact conditions are satisfied, the defined period is &lt;i&gt;maximal&lt;/i&gt;, so the generated period (x is long) is 2^64. This piece of magic is documented &lt;a href="http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.34.1024"&gt;here, page 9&lt;/a&gt;. The "why" of it is beyond me.&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: Arial, Helvetica, sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: Arial, Helvetica, sans-serif;"&gt;If any ninja mathematician comes across this post, please leave some explanation if you can.&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: Arial, Helvetica, sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: Arial, Helvetica, sans-serif;"&gt;&lt;b&gt;EDIT: &lt;/b&gt;oops. I overlooked that java.util.Random uses a mask to only reduce itself to 48 bits, instead of 64, so correspondingly the period is 2^48 instead of 2^64; apparently in an attempt to increase the quality of the generated numbers. In any case, if you need longer period, the technique described here will do the trick.&lt;/span&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6958126065976802292-3599912072659369247?l=code-o-matic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://code-o-matic.blogspot.com/feeds/3599912072659369247/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://code-o-matic.blogspot.com/2010/12/how-long-is-period-of-random-numbers.html#comment-form' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6958126065976802292/posts/default/3599912072659369247'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6958126065976802292/posts/default/3599912072659369247'/><link rel='alternate' type='text/html' href='http://code-o-matic.blogspot.com/2010/12/how-long-is-period-of-random-numbers.html' title='How long is the period of random numbers created by java.util.Random?'/><author><name>Dimitris Andreou</name><uri>https://profiles.google.com/116229150468867889128</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-l6gGcDEXxqI/AAAAAAAAAAI/AAAAAAAABq0/x5Wy-h5G81Y/s512-c/photo.jpg'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6958126065976802292.post-7161821533477288443</id><published>2010-12-12T18:24:00.000-08:00</published><updated>2010-12-12T18:26:00.926-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='consistent hashing hashtables sorting counting sort bigtable'/><title type='text'>Juggling consistent hashing, hashtables, and good old sorting</title><content type='html'>&lt;a href="http://en.wikipedia.org/wiki/Consistent_hashing"&gt;Consistent hashing&lt;/a&gt;&amp;nbsp;can be summarized in one sentence: it is a hashtable with variant-length buckets.&lt;br /&gt;&lt;br /&gt;You have a line segment (that's the key space). Breaking it to N equal parts (the buckets) means it is very easy (O(1)) to compute which part contains a given point. But if you increase or decrease N, all parts change (and shrink or grow respectively). Only the first and the last part have one of its ends unaffected, but the rest have both their ends moved.&lt;br /&gt;&lt;br /&gt;Now consider breaking it in N parts, but not of necessarily the same length. Now it is easier to change the number of parts. Do you want more parts? Break one in two pieces. Want fewer parts? Merge two parts sitting next to each other. All other parts remain firm in their place, unaffected. But now finding which part contains a given point gets more complicated (O(logN) if you keep the parts sorted, say in a red-black tree).&lt;br /&gt;&lt;br /&gt;Hashtables themselves can be summarized in an interesting way: it is &lt;b&gt;sorting&lt;/b&gt;...by hash (it doesn't matter if the original key space is not totally ordered - &lt;i&gt;the hashes are&lt;/i&gt;).&amp;nbsp;But if it is sorting, where the logN factor in the complexity of hashtable operations? Well, there isn't one: hashes are small natural numbers (bounded by the hashtable size, which is O(N) of the elements in it). And what do you think of when you want to sort small natural numbers? &lt;a href="http://en.wikipedia.org/wiki/Counting_sort"&gt;Counting sort&lt;/a&gt;.&amp;nbsp;(Caveat: hash functions do not just aim to map a large key space into a sequence of natural numbers, that's only part of the story. They also aim to approximate a random permutation of the original space, which is separately useful - to try to load balance the buckets when the incoming distribution is not uniform. In consistent hashing, we sacrifice the first role of hash functions, but we keep this latter one).&lt;br /&gt;&lt;br /&gt;Trying to compress the discussion above:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Hashtables are really counting sort&lt;/li&gt;&lt;ul&gt;&lt;li&gt;(Yes, data structures &lt;i&gt;are&lt;/i&gt; algorithms)&lt;/li&gt;&lt;li&gt;An &lt;i&gt;equal&lt;/i&gt; piece of the (approximately permuted) key space is mapped to each bucket&lt;/li&gt;&lt;ul&gt;&lt;li&gt;Easy to find the corresponding bucket for a key (++)&lt;/li&gt;&lt;li&gt;Changing the number of buckets affects the mapped spaces of all buckets (--)&lt;/li&gt;&lt;/ul&gt;&lt;/ul&gt;&lt;li&gt;Consistent hashing differs in the following way:&lt;/li&gt;&lt;ul&gt;&lt;li&gt;&amp;nbsp;A &lt;i&gt;variable &lt;/i&gt;piece&amp;nbsp;the (approximately permuted) key space is mapped to each bucket&lt;/li&gt;&lt;ul&gt;&lt;li&gt;Harder to find the corresponding bucket for a key (--)&lt;/li&gt;&lt;li&gt;Easy to split or merge buckets, without affecting any other buckets (++)&lt;/li&gt;&lt;/ul&gt;&lt;/ul&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;Bonus section: &lt;a href="http://en.wikipedia.org/wiki/BigTable"&gt;Bigtables&lt;/a&gt;&amp;nbsp;(and the good old Bigtable paper &lt;a href="http://static.googleusercontent.com/external_content/untrusted_dlcp/labs.google.com/en/us/papers/bigtable-osdi06.pdf"&gt;here&lt;/a&gt;). In Bigtable, The rows are primarily sorted by row key. The tablets (think buckets) are variable length, so that overloaded tablets can be split, without touching the huge amount of data that potentially reside in the same bigtable. (One can help load balancing the tablets by -did you guess it?- sorting by hash first...). So, here you go. The rows are &lt;i&gt;sorted&lt;/i&gt;. Yet it can still rightfully be described as consistent &lt;i&gt;hashing&lt;/i&gt;. Confused yet? Well, at least I tried. :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6958126065976802292-7161821533477288443?l=code-o-matic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://code-o-matic.blogspot.com/feeds/7161821533477288443/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://code-o-matic.blogspot.com/2010/12/juggling-consistent-hashing-hashtables.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6958126065976802292/posts/default/7161821533477288443'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6958126065976802292/posts/default/7161821533477288443'/><link rel='alternate' type='text/html' href='http://code-o-matic.blogspot.com/2010/12/juggling-consistent-hashing-hashtables.html' title='Juggling consistent hashing, hashtables, and good old sorting'/><author><name>Dimitris Andreou</name><uri>https://profiles.google.com/116229150468867889128</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-l6gGcDEXxqI/AAAAAAAAAAI/AAAAAAAABq0/x5Wy-h5G81Y/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6958126065976802292.post-3019942861520900937</id><published>2010-10-20T02:47:00.000-07:00</published><updated>2010-10-20T02:50:45.645-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='memory-measurer data-structures footprint java'/><title type='text'>Memory cost (per entry) for various Java data structures</title><content type='html'>Have you seen this?&amp;nbsp;&lt;a href="http://code.google.com/p/memory-measurer/wiki/ElementCostInDataStructures"&gt;http://code.google.com/p/memory-measurer/wiki/ElementCostInDataStructures&lt;/a&gt;&lt;br /&gt;It shows the memory cost &lt;i&gt;per each entry&lt;/i&gt;&amp;nbsp;for various common and not-so-common Java data structures. For example, have you wondered when you put() an entry to a HashMap, how much memory footprint you create, &lt;i&gt;apart&lt;/i&gt;&amp;nbsp;from the space occupied by your key and your value (i.e. only by internal artifacts introduced by HashMap itself)? There are the answers to such questions.&lt;br /&gt;&lt;br /&gt;It also exemplifies the utility of my &lt;a href="http://code.google.com/p/memory-measurer/"&gt;memory measuring tool&lt;/a&gt;, which I recently redesigned to decouple object exploration from measuring the memory usage (bytes) of objects, so I can use the same exploration to derive more qualitative statistics, like number of objects in a object graph, number of references, and number of primitives (which would directly reflect memory usage if it weren't for effects of alignment).&lt;br /&gt;&lt;br /&gt;If you are designing data structures in Java, it would be silly not to use this tool. Seriously. (Profilers can be used to somewhat the same effect, but why fire it up and click buttons till you get where you want and take numbers and calculate by yourself, when you can do it more precisely with very simple code).&lt;br /&gt;&lt;br /&gt;Future work: do the same for the immutable &lt;a href="http://guava-libraries.googlecode.com/"&gt;Guava&lt;/a&gt; collections.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6958126065976802292-3019942861520900937?l=code-o-matic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://code-o-matic.blogspot.com/feeds/3019942861520900937/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://code-o-matic.blogspot.com/2010/10/memory-cost-per-entry-for-various-java.html#comment-form' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6958126065976802292/posts/default/3019942861520900937'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6958126065976802292/posts/default/3019942861520900937'/><link rel='alternate' type='text/html' href='http://code-o-matic.blogspot.com/2010/10/memory-cost-per-entry-for-various-java.html' title='Memory cost (per entry) for various Java data structures'/><author><name>Dimitris Andreou</name><uri>https://profiles.google.com/116229150468867889128</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-l6gGcDEXxqI/AAAAAAAAAAI/AAAAAAAABq0/x5Wy-h5G81Y/s512-c/photo.jpg'/></author><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6958126065976802292.post-2854160661273445261</id><published>2010-07-29T18:42:00.000-07:00</published><updated>2010-10-19T17:26:24.472-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='transitivity-utils transitive closure graph reachability dietz agrawal'/><title type='text'>Graph reachability, transitive closures, and a nasty historical accident in the pre-google era</title><content type='html'>&lt;div class="separator" style="clear: both; text-align: left;"&gt;Last few days I'm feeling a bit like an archaeologist. It's probably a great story to explain to a newcomer just what's the importance of the internet, coupled with a great search engine. But I digress.&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;What follows is a pretty long post, covering a lot of ground in the graph reachability problem and transitive closures, enumerating various naive solutions (i.e., the ones you are likely to see used), then moving to much more promising approaches.&lt;br /&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;b&gt;&lt;span class="Apple-style-span"&gt;&lt;span class="Apple-style-span" style="font-size: x-large;"&gt;Introduction&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;Lets say you have a directed graph, &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;G = (V, E)&lt;/span&gt;, and you want to know &lt;i&gt;real fast&lt;/i&gt;&amp;nbsp;whether you can reach some node from some other, in other words whether there is a directed path &lt;b&gt;u --&amp;gt; v&lt;/b&gt;, for any nodes &lt;b&gt;u&lt;/b&gt; and &lt;b&gt;v&lt;/b&gt;. (Take a moment to convince yourself that this is a trivial problem if the graph is undirected). Before we continue, lets stop and think where this might be useful. Consider a (really silly) class hierarchy (we also call it an ontology):&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/_H1UVegJ_stI/TFGwW5JvIUI/AAAAAAAAAJM/EvOAzm3Da6U/s1600/class_hierarchy.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="241" src="http://2.bp.blogspot.com/_H1UVegJ_stI/TFGwW5JvIUI/AAAAAAAAAJM/EvOAzm3Da6U/s640/class_hierarchy.png" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Testing whether there is a directed path between two nodes in a class hierarchy is equivalent to asking "is this class a subclass of another?". That's basically what the &lt;b&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;instanceof&lt;/span&gt; &lt;/b&gt;Java operator does (if we only consider classes, then subtyping in Java forms a tree - single inheritance, remember? - but if we add interfaces in the mix, we get a DAG, but thankfully, never a cycle).&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Lets formally denote such a query by a function&amp;nbsp;&lt;b&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;existsPath: V x V --&amp;gt; {1, 0}&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;&lt;span class="Apple-style-span" style="font-weight: normal;"&gt;.&lt;/span&gt;&lt;/span&gt;&amp;nbsp;&lt;/b&gt;It takes an ordered pair of nodes, and returns whether there is a path from the first to the second. Now, lets make sure that having such an &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;existsPath&lt;/span&gt; function is, in fact, &lt;b&gt;the &lt;a href="http://en.wikipedia.org/wiki/Characteristic_function"&gt;characteristic function&lt;/a&gt; of the&amp;nbsp;&lt;a href="http://en.wikipedia.org/wiki/Transitive_closure"&gt;transitive closure&lt;/a&gt;&lt;/b&gt; of the graph, that is, given any edge, we can apply this function to it to test whether it belongs to the transitive closure or not, i.e., whether it is one of the following edges:&lt;br /&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/_H1UVegJ_stI/TFHE2p0lclI/AAAAAAAAAJU/DaXI5y1mdb0/s1600/class_hierarchy_tr.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;&lt;img border="0" height="241" src="http://3.bp.blogspot.com/_H1UVegJ_stI/TFHE2p0lclI/AAAAAAAAAJU/DaXI5y1mdb0/s640/class_hierarchy_tr.png" width="640" /&gt;&lt;/span&gt;&lt;/a&gt;&lt;/div&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;When we talk about transitive closure, though, we mean something &lt;i&gt;more&lt;/i&gt; than merely being able to answer graph reachability queries - we also imply that we possess a function &lt;b&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;successorSet: V --&amp;gt; Powerset(V)&lt;/span&gt;&lt;/b&gt;. i.e., that we can find all ancestors of a node, instead of checking if a &lt;b&gt;particular&lt;/b&gt; node is an ancestor of it or not.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;By the way, the above explanation is exactly the reason why in &lt;a href="http://code.google.com/p/flexigraph/"&gt;Flexigraph&lt;/a&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;&amp;nbsp;I define the interfaces (sorry, but blogger doesn't play very nicely with source code):&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;table id="src_table_0" style="-webkit-border-horizontal-spacing: 2px; -webkit-border-vertical-spacing: 2px; border-collapse: collapse; font-family: monospace; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; white-space: pre;"&gt;&lt;tbody style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;&lt;tr id="sl_svn2_10" style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;&lt;td class="source" style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 4px; padding-right: 0px; padding-top: 0px; vertical-align: top; white-space: pre-wrap;"&gt;&lt;span class="kwd" style="color: #000088;"&gt;public&lt;/span&gt;&lt;span class="pln" style="color: black;"&gt; interface &lt;/span&gt;&lt;span class="typ" style="color: #660066;"&gt;PathFinder&lt;/span&gt;&lt;span class="pln" style="color: black;"&gt; &lt;/span&gt;&lt;span class="pun" style="color: #666600;"&gt;{&lt;/span&gt;&lt;span class="pln" style="color: black;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr id="sl_svn2_19" style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;&lt;td class="source" style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 4px; padding-right: 0px; padding-top: 0px; vertical-align: top; white-space: pre-wrap;"&gt;&lt;span class="pln" style="color: black;"&gt;&amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span class="kwd" style="color: #000088;"&gt;boolean&lt;/span&gt;&lt;span class="pln" style="color: black;"&gt; pathExists&lt;/span&gt;&lt;span class="pun" style="color: #666600;"&gt;(&lt;/span&gt;&lt;span class="typ" style="color: #660066;"&gt;Node&lt;/span&gt;&lt;span class="pln" style="color: black;"&gt; n1&lt;/span&gt;&lt;span class="pun" style="color: #666600;"&gt;,&lt;/span&gt;&lt;span class="pln" style="color: black;"&gt; &lt;/span&gt;&lt;span class="typ" style="color: #660066;"&gt;Node&lt;/span&gt;&lt;span class="pln" style="color: black;"&gt; n2&lt;/span&gt;&lt;span class="pun" style="color: #666600;"&gt;);&lt;/span&gt;&lt;span class="pln" style="color: black;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr id="sl_svn2_20" style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;&lt;td class="source" style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 4px; padding-right: 0px; padding-top: 0px; vertical-align: top; white-space: pre-wrap;"&gt;&lt;span class="pun" style="color: #666600;"&gt;}&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;br /&gt;&lt;table id="src_table_0" style="-webkit-border-horizontal-spacing: 2px; -webkit-border-vertical-spacing: 2px; border-collapse: collapse; font-family: monospace; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; white-space: pre;"&gt;&lt;tbody style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;&lt;tr id="sl_svn2_12" style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;&lt;td class="source" style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 4px; padding-right: 0px; padding-top: 0px; vertical-align: top; white-space: pre-wrap;"&gt;&lt;span class="kwd" style="color: #000088;"&gt;public&lt;/span&gt;&lt;span class="pln" style="color: black;"&gt; interface &lt;/span&gt;&lt;span class="typ" style="color: #660066;"&gt;Closure&lt;/span&gt;&lt;span class="pln" style="color: black;"&gt; &lt;/span&gt;&lt;span class="kwd" style="color: #000088;"&gt;extends&lt;/span&gt;&lt;span class="pln" style="color: black;"&gt; &lt;/span&gt;&lt;span class="typ" style="color: #660066;"&gt;PathFinder&lt;/span&gt;&lt;span class="pln" style="color: black;"&gt; &lt;/span&gt;&lt;span class="pun" style="color: #666600;"&gt;{&lt;/span&gt;&lt;span class="pln" style="color: black;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr id="sl_svn2_19" style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;&lt;td class="source" style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 4px; padding-right: 0px; padding-top: 0px; vertical-align: top; white-space: pre-wrap;"&gt;&lt;span class="pln" style="color: black;"&gt;&amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span class="typ" style="color: #660066;"&gt;SuccessorSet&lt;/span&gt;&lt;span class="pln" style="color: black;"&gt; successorsOf&lt;/span&gt;&lt;span class="pun" style="color: #666600;"&gt;(&lt;/span&gt;&lt;span class="typ" style="color: #660066;"&gt;Node&lt;/span&gt;&lt;span class="pln" style="color: black;"&gt; node&lt;/span&gt;&lt;span class="pun" style="color: #666600;"&gt;);&lt;/span&gt;&lt;span class="pln" style="color: black;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr id="sl_svn2_20" style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;&lt;td class="source" style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 4px; padding-right: 0px; padding-top: 0px; vertical-align: top; white-space: pre-wrap;"&gt;&lt;span class="pun" style="color: #666600;"&gt;}&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;br /&gt;"&lt;span class="Apple-style-span" style="-webkit-border-horizontal-spacing: 2px; -webkit-border-vertical-spacing: 2px; border-collapse: collapse; font-family: monospace; white-space: pre-wrap;"&gt;&lt;span class="typ" style="color: #660066;"&gt;Closure&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="-webkit-border-horizontal-spacing: 2px; -webkit-border-vertical-spacing: 2px; border-collapse: collapse; font-family: monospace; white-space: pre-wrap;"&gt;&lt;span class="pln" style="color: black;"&gt; &lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="-webkit-border-horizontal-spacing: 2px; -webkit-border-vertical-spacing: 2px; border-collapse: collapse; font-family: monospace; white-space: pre-wrap;"&gt;&lt;span class="kwd" style="color: #000088;"&gt;extends&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="-webkit-border-horizontal-spacing: 2px; -webkit-border-vertical-spacing: 2px; border-collapse: collapse; font-family: monospace; white-space: pre-wrap;"&gt;&lt;span class="pln" style="color: black;"&gt; &lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="-webkit-border-horizontal-spacing: 2px; -webkit-border-vertical-spacing: 2px; border-collapse: collapse; font-family: monospace; white-space: pre-wrap;"&gt;&lt;span class="typ" style="color: #660066;"&gt;PathFinder&lt;/span&gt;&lt;/span&gt;" is basically a theorem expressed in code, that &lt;b&gt;any transitive closure representation is also a graph reachability representation&lt;/b&gt;. That's the precise relation between these two concepts - I'm not aware of any Java graph library that gets these right. Continuing the self-plug, if you need to work with transitive closures/reductions, you might find the whole &lt;a href="http://code.google.com/p/flexigraph/source/browse/trunk/src/gr/forth/ics/graph/algo/transitivity/"&gt;transitivity package&lt;/a&gt; interesting - compare this, for example, with &lt;a href="http://www.jgrapht.org/javadoc/org/jgrapht/alg/TransitiveClosure.html"&gt;JGraphT support&lt;/a&gt;, or &lt;a href="http://www.yworks.com/products/yfiles/doc/api/y/algo/Transitivity.html"&gt;yWorks support&lt;/a&gt;: a sad state of affairs. But I digress again.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;span class="Apple-style-span" style="font-size: x-large;"&gt;Supporting graph reachability queries&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Ok, lets concentrate now on actually implementing support for graph reachability queries. These are the most important questions to ask before we start:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;b&gt;How much memory are we willing to spend?&lt;/b&gt;&lt;/li&gt;&lt;li&gt;&lt;b&gt;Is the graph static? Or update operation are supported (and which)?&lt;/b&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;Lets explore the design space based on some typical answers to the above questions.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Bit-matrix:&amp;nbsp;&lt;/b&gt;The fastest reachability test is offered by the bit-matrix method: make a |V| x |V| matrix, and store in each cell whether there is a path from the row-node to the column-node. This actually&amp;nbsp;&lt;i&gt;materializes&lt;/i&gt;&amp;nbsp;the transitive closure, in the sense that we explicitly (rather than implicitly, to some degree) represent it&amp;nbsp;(and we already argued that representing the transitive closure also implies support for graph reachability queries).&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/_H1UVegJ_stI/TFHKGOElLVI/AAAAAAAAAJc/soW0wmMsD00/s1600/bitmap.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="136" src="http://1.bp.blogspot.com/_H1UVegJ_stI/TFHKGOElLVI/AAAAAAAAAJc/soW0wmMsD00/s400/bitmap.PNG" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Of course, this has some obvious shortcomings. Firstly, it uses &lt;b&gt;O(|V| ^ 2)&lt;/b&gt; memory - but this is not as bad as it looks, and it would probably be a good solution for you &lt;b&gt;if your graph is static&lt;/b&gt;. Which leads us to the second problem - &lt;b&gt;it is terrible if you expect to frequently update your graph&lt;/b&gt;.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Adjacency-list graph representation: &lt;/b&gt;another way of representing the transitive closure is to just create an &lt;a href="http://en.wikipedia.org/wiki/Adjacency_list"&gt;adjacency-list&lt;/a&gt; graph with all the edges of the transitive closure in it. In the example, that would mean to create a graph to represent the second image. (This is what JGraphT and yWorks offer - it's the simplest to implement). This has numerous disadvantages. First, this is a costly representation - such a representation is good for &lt;i&gt;sparse&lt;/i&gt;&amp;nbsp;graphs, but it is very easy for a sparse graph to have a &lt;i&gt;dense&lt;/i&gt;&amp;nbsp;transitive closure (consider a single path). Worse, if you represent each edge with an actual "Edge" object, then you are quite probably end up with a representation even costlier than the naive bitmap method - &lt;b&gt;compare using a single bit to encode an edge vs using at least 12 bytes &lt;/b&gt;(at least, but typically quite more than that), i.e. &lt;b&gt;96bits. &lt;/b&gt;Also, this representation &lt;b&gt;doesn't even offer fast reachability test&lt;/b&gt;&amp;nbsp;- testing whether two nodes are connected depends on the minimum degree of those nodes, and this degree can be large in a dense graph. All in all, this representation is the lest likely to be the best for a given application.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Agrawal et al: &lt;/b&gt;Now, lets see the approach in a very influential paper published in 1989:&amp;nbsp;&lt;span class="Apple-style-span" style="-webkit-border-horizontal-spacing: 2px; -webkit-border-vertical-spacing: 2px; font-family: Arial, Verdana, sans-serif;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="Apple-style-span" style="-webkit-border-horizontal-spacing: 2px; -webkit-border-vertical-spacing: 2px; font-family: Arial, Verdana, sans-serif;"&gt;&lt;a href="https://docs.google.com/viewer?url=http%3A%2F%2Fsites.google.com%2Fsite%2Fjimandreou%2Fvarious%2FAgrawal-EfficientManagementofTransitiveRelationshipsinLargeDataandKnowledgeBases.pdf%3Fattredirects%3D0%26d%3D1"&gt;Efficient Management of Transitive Relationships in Large Data and Knowledge Bases&lt;/a&gt;. Lets see a figure from this paper, starting from the simple case of supporting reachability queries &lt;b&gt;in a tree&lt;/b&gt;:&amp;nbsp;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="-webkit-border-horizontal-spacing: 2px; -webkit-border-vertical-spacing: 2px; font-family: Arial, Verdana, sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/_H1UVegJ_stI/TFHQuF1eiAI/AAAAAAAAAJk/YoQlAcxrB1o/s1600/agrawal.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="312" src="http://2.bp.blogspot.com/_H1UVegJ_stI/TFHQuF1eiAI/AAAAAAAAAJk/YoQlAcxrB1o/s640/agrawal.PNG" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;span class="Apple-style-span" style="-webkit-border-horizontal-spacing: 2px; -webkit-border-vertical-spacing: 2px; font-family: Arial, Verdana, sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: Arial, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="-webkit-border-horizontal-spacing: 2px; -webkit-border-vertical-spacing: 2px;"&gt;(Don't be confused by the edge directions, they just happened to drew them the other way around). Each node is labelled with a pair of integers - think of each pair as an interval in the X-axis. The &lt;i&gt;second&lt;/i&gt;&amp;nbsp;number is the post-order index of that node in the tree, while the first number is equal to &lt;i&gt;the minimum &lt;a href="http://en.wikipedia.org/wiki/Tree_traversal"&gt;post-order&lt;/a&gt; index of any descendant&lt;/i&gt;&amp;nbsp;of that node.&amp;nbsp;Lets quickly visualize those pairs as intervals:&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: Arial, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="-webkit-border-horizontal-spacing: 2px; -webkit-border-vertical-spacing: 2px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/_H1UVegJ_stI/TFHTlA5K4jI/AAAAAAAAAJs/_Ep_HxIWV6M/s1600/agrawal2.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="320" src="http://2.bp.blogspot.com/_H1UVegJ_stI/TFHTlA5K4jI/AAAAAAAAAJs/_Ep_HxIWV6M/s320/agrawal2.PNG" width="212" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;span class="Apple-style-span" style="font-family: Arial, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="-webkit-border-horizontal-spacing: 2px; -webkit-border-vertical-spacing: 2px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: Arial, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="-webkit-border-horizontal-spacing: 2px; -webkit-border-vertical-spacing: 2px;"&gt;As you can see, the interval of each node &lt;i&gt;subsumes&lt;/i&gt;&amp;nbsp;(&lt;i&gt;is a proper superset of&lt;/i&gt;) the intervals of &lt;i&gt;exactly&lt;/i&gt;&amp;nbsp;its descendants. Thus, we can quickly test whether "&lt;b&gt;e&lt;/b&gt;&amp;nbsp;&lt;b&gt;is a descendant of&lt;/b&gt; &lt;b&gt;b&lt;/b&gt;" by asking "&lt;b&gt;is &lt;i&gt;3&lt;/i&gt; contained in the interval [1, 4]?&lt;/b&gt;", in &lt;b&gt;O(1) &lt;/b&gt;time.&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: Arial, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="-webkit-border-horizontal-spacing: 2px; -webkit-border-vertical-spacing: 2px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: Arial, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="-webkit-border-horizontal-spacing: 2px; -webkit-border-vertical-spacing: 2px;"&gt;Quick check: does it easily support graph updates? &lt;b&gt;No!&lt;/b&gt;&amp;nbsp;Inserting a new leaf under node &lt;b&gt;g&lt;/b&gt;&amp;nbsp;would require changing the numbers of &lt;b&gt;g&amp;nbsp;and everything on its right &lt;/b&gt;(that is, &lt;b&gt;&lt;i&gt;all&lt;span class="Apple-style-span" style="font-weight: normal;"&gt;&amp;nbsp;&lt;span class="Apple-style-span" style="font-style: normal;"&gt;the nodes of the graph!).&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/i&gt;&lt;/b&gt;And we are still only discussing about trees. Lets see how this generalizes for acyclic graphs (this can be similarly generalized to general graphs, but I won't elaborate on that here). Again, a figure from the paper:&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: Arial, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="-webkit-border-horizontal-spacing: 2px; -webkit-border-vertical-spacing: 2px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/_H1UVegJ_stI/TFHZw4csuEI/AAAAAAAAAJ0/msdB0NzoblI/s1600/agrawal3.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="288" src="http://3.bp.blogspot.com/_H1UVegJ_stI/TFHZw4csuEI/AAAAAAAAAJ0/msdB0NzoblI/s640/agrawal3.PNG" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;span class="Apple-style-span" style="font-family: Arial, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="-webkit-border-horizontal-spacing: 2px; -webkit-border-vertical-spacing: 2px;"&gt;Note that some non-tree edges have been added, particularly &lt;b&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;d&amp;nbsp;--&amp;gt; b&lt;/span&gt; &lt;/b&gt;(the rest of the inserted are actually redundant, yes, they could have used a better example). Also note that now &lt;b&gt;d &lt;/b&gt;is represented by&amp;nbsp;&lt;b&gt;two&lt;/b&gt;&amp;nbsp;intervals, [6,7] and [1,4]. The same invariants are observed as above - the interval &lt;i&gt;set&lt;/i&gt;&amp;nbsp;of each node &lt;i&gt;subsumes&lt;/i&gt;&amp;nbsp;any interval of &lt;i&gt;exactly&lt;/i&gt;&amp;nbsp;its descendants. Basically, we start with a tree (forest) of the graph, label it as previously, and then process all non-tree edges, by &lt;b&gt;propagating&lt;/b&gt;&amp;nbsp;all the intervals of the descendant to &lt;b&gt;all&lt;/b&gt;&amp;nbsp;its ancestors via that edge.&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: Arial, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="-webkit-border-horizontal-spacing: 2px; -webkit-border-vertical-spacing: 2px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: Arial, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="-webkit-border-horizontal-spacing: 2px; -webkit-border-vertical-spacing: 2px;"&gt;Second check: how does this cope with graph updates? &lt;b&gt;Much worse! &lt;/b&gt;If, for example, we have to change the interval of &lt;b&gt;g&lt;/b&gt;, we now must &lt;b&gt;search potentially the whole graph&lt;/b&gt;&amp;nbsp;and track &lt;i&gt;where&lt;/i&gt;&amp;nbsp;its interval might have been propagated, fixing all those occurrences with the new interval of &lt;b&gt;g&lt;/b&gt;. Well, this sucks big time.&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: Arial, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="-webkit-border-horizontal-spacing: 2px; -webkit-border-vertical-spacing: 2px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: Arial, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="-webkit-border-horizontal-spacing: 2px; -webkit-border-vertical-spacing: 2px;"&gt;Now, lets try to justify the "historical accident" that the title promises.&amp;nbsp;&lt;b&gt;What if I told you that this problem was already solved 7 years earlier than Agrawal reintroduced it? &lt;/b&gt;More importantly, &lt;b&gt;what if I told you that &lt;span class="Apple-style-span" style="font-weight: normal;"&gt;(apparently!)&amp;nbsp;&lt;/span&gt;&lt;i&gt;hardly anyone noticed&lt;/i&gt;&amp;nbsp;this since then? &lt;/b&gt;It's hard to believe. For example, here is a technical report published recently, in 2006:&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="-webkit-border-horizontal-spacing: 2px; -webkit-border-vertical-spacing: 2px; font-family: Arial, Verdana, sans-serif;"&gt;&lt;a href="http://www.blogger.com/goog_804827837"&gt;Preuveneers, Berbers - Prime Numbers Considered Useful&lt;/a&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="-webkit-border-horizontal-spacing: 2px; -webkit-border-vertical-spacing: 2px; font-family: Arial, Verdana, sans-serif;"&gt;&lt;a href="https://docs.google.com/viewer?url=http%3A%2F%2Fsites.google.com%2Fsite%2Fjimandreou%2Fvarious%2FPreuveneers%252CBerbers-PrimeNumbersConsideredUseful%25282006%2529.pdf%3Fattredirects%3D0%26d%3D1"&gt;&amp;nbsp;&lt;/a&gt;. Don't bother reading all those 50 pages - here is a relevant quote (shortly after having presented the Agrawal et al method - emphasis mine):&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: Arial, Verdana, sans-serif;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: Arial, Verdana, sans-serif;"&gt;&lt;blockquote&gt;In the previous section several encoding algorithms for eﬃcient subsumption&amp;nbsp;or subtype testing were discussed. As previously outlined, &lt;b&gt;the major concern&amp;nbsp;is support for eﬃcient incremental and conﬂict-free encoding&lt;/b&gt;. While most algorithms provide a way to encode new classes without re-encoding the whole&amp;nbsp;hierarchy, &lt;b&gt;they often &amp;nbsp;require going through the hierarchy to ﬁnd and modify any&amp;nbsp;&lt;/b&gt;&lt;b&gt;conﬂicting codes&lt;/b&gt;. The &lt;b&gt;&lt;i&gt;only&lt;/i&gt;&lt;/b&gt; algorithm that does not suﬀer from this issue is the&amp;nbsp;&lt;b&gt;&lt;i&gt;binary matrix&lt;/i&gt;&lt;/b&gt; method, but this method is the most expensive one with respect&amp;nbsp;to the encoding length as no compaction of the representation is achieved.&lt;/blockquote&gt;&lt;/span&gt;This statement is the authors' motivation for design a new approach (a not too practical dare I say, requiring expensive computations on very large integers). They didn't know the solution.&lt;br /&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: Arial, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Times New Roman';"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="-webkit-border-horizontal-spacing: 2px; -webkit-border-vertical-spacing: 2px; font-family: Arial, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Times New Roman';"&gt;&lt;span class="Apple-style-span" style="-webkit-border-horizontal-spacing: 0px; -webkit-border-vertical-spacing: 0px;"&gt;Here is another example, published in 2004.&lt;/span&gt;&lt;/span&gt;&lt;a href="https://docs.google.com/viewer?url=http%3A%2F%2Fsites.google.com%2Fsite%2Fjimandreou%2Fvarious%2FChristophides-OptimizingTaxonomicSemanticWebQueriesUsingLabelingSchemes.pdf%3Fattredirects%3D0%26d%3D1"&gt;Christophides - Optimizing Taxonomic Semantic Web Queries Using Labeling Schemes&lt;/a&gt;. &lt;/span&gt;This is a great informative paper surveying at depth a number of different graph reachability schemes, with a focus on databases. Christophides, actually, is my former supervisor, Professor at the University of Crete, and a good friend. Unfortunately, even though this paper actually cites the paper that contains the key idea, they also didn't know the solution (this I know first-hand).&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: Arial, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="-webkit-border-horizontal-spacing: 2px; -webkit-border-vertical-spacing: 2px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: Arial, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="-webkit-border-horizontal-spacing: 2px; -webkit-border-vertical-spacing: 2px;"&gt;Yet another example, published in 1999:&amp;nbsp;&lt;a href="https://docs.google.com/viewer?url=http%3A%2F%2Fsites.google.com%2Fsite%2Fjimandreou%2Fvarious%2FBommel%252CBeck-IncrementalEncodingofMultipleInheritanceHierarchies%25281999%2529.pdf%3Fattredirects%3D0%26d%3D1"&gt;Bommel, Beck - Incremental Encoding of Multiple Inheritance Hierarchies&lt;/a&gt;. Again, they didn't know the solution, so they ended up creating a more complicated, less-than-ideal work-around (see for yourself).&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: Arial, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="-webkit-border-horizontal-spacing: 2px; -webkit-border-vertical-spacing: 2px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: Arial, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="-webkit-border-horizontal-spacing: 2px; -webkit-border-vertical-spacing: 2px;"&gt;I don't even dare to look into all&amp;nbsp;&lt;a href="http://scholar.google.co.uk/scholar?cites=17382624612013631960&amp;amp;as_sdt=2005&amp;amp;sciodt=2000&amp;amp;hl=en"&gt;~250 papers that cite Agrawal's work&lt;/a&gt;.&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: Arial, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="-webkit-border-horizontal-spacing: 2px; -webkit-border-vertical-spacing: 2px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="-webkit-border-horizontal-spacing: 2px; -webkit-border-vertical-spacing: 2px; font-family: Arial, Verdana, sans-serif;"&gt;This is rather embarrassing. Before continuing, this kind of regression would have been highly unlikely if there was an efficient way (e.g. &lt;a href="http://scholar.google.com/"&gt;google scholar&lt;/a&gt; :) ) to search for relevant research. Here goes the obligatory &lt;a href="http://en.wikipedia.org/wiki/Memex"&gt;memex&lt;/a&gt; link.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="-webkit-border-horizontal-spacing: 2px; -webkit-border-vertical-spacing: 2px; font-family: Arial, Verdana, sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="-webkit-border-horizontal-spacing: 2px; -webkit-border-vertical-spacing: 2px; font-family: Arial, Verdana, sans-serif;"&gt;That being said, lets finally turn our attention to the mysterious solution that was missed by seemingly everyone.&amp;nbsp;&lt;/span&gt;&lt;span class="Apple-style-span" style="-webkit-border-horizontal-spacing: 2px; -webkit-border-vertical-spacing: 2px; font-family: Arial, Verdana, sans-serif;"&gt;&lt;a href="https://docs.google.com/viewer?url=http%3A%2F%2Fsites.google.com%2Fsite%2Fjimandreou%2Fvarious%2FDietz-Maintainingorderinalinkedlist.pdf%3Fattredirects%3D0%26d%3D1"&gt;Dietz - Maintaining order in a linked list&lt;/a&gt;. This paper was published much earlier - in 1982, a year special to me since that's when I was born. &lt;/span&gt;&lt;span class="Apple-style-span" style="-webkit-border-horizontal-spacing: 2px; -webkit-border-vertical-spacing: 2px; font-family: Arial, Verdana, sans-serif;"&gt;Dietz introduces the (lets call it so) &lt;i&gt;order maintainance structure&lt;/i&gt;, defined by this interface:&lt;/span&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: Arial, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="-webkit-border-horizontal-spacing: 2px; -webkit-border-vertical-spacing: 2px;"&gt;&lt;b&gt;Insert(x, y)&lt;/b&gt;&lt;br /&gt;Inserts element x right afterwards element y.&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: Arial, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="-webkit-border-horizontal-spacing: 2px; -webkit-border-vertical-spacing: 2px;"&gt;&lt;b&gt;Delete(x) &amp;nbsp;&lt;/b&gt;(Obvious)&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: Arial, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="-webkit-border-horizontal-spacing: 2px; -webkit-border-vertical-spacing: 2px;"&gt;&lt;b&gt;Order(x, y)&amp;nbsp;&lt;/b&gt;&lt;br /&gt;Returns whether x &lt;i&gt;precedes&lt;/i&gt; y.&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="-webkit-border-horizontal-spacing: 2px; -webkit-border-vertical-spacing: 2px; font-family: Arial, Verdana, sans-serif;"&gt;So this is basically similar to a linked list, with the addition that we can ask (in constant time!) whether a particular list node precedes another. The actual data structure proposed to fulfil this interface has been superseded by Dietz and Sleator in &lt;a href="https://docs.google.com/viewer?url=http%3A%2F%2Fsites.google.com%2Fsite%2Fjimandreou%2Fvarious%2FDietz%252CSleator-TwoAlgorithmsforMaintainingOrderinaList%25281988%2529.pdf%3Fattredirects%3D0%26d%3D1"&gt;Two Algorithms for Maintaining Order in a List (1988)&lt;/a&gt;, and then recently by Bender et al in&amp;nbsp;&lt;a href="https://docs.google.com/viewer?url=http%3A%2F%2Fsites.google.com%2Fsite%2Fjimandreou%2Fvarious%2FBender-DataStructuresforMaintainingSetPartitions%25282003%2529.pdf%3Fattredirects%3D0%26d%3D1"&gt;Two Simplified Algorithms for Maintaining Order in a List&lt;/a&gt;. &lt;i&gt;These structures offer amortized O(1) time complexity for all these operations&lt;/i&gt;&lt;b&gt; &lt;/b&gt;(there are also versions offering O(1) worst case, but they are significantly more complex to implement, and likely to be slower in practice). &lt;a href="http://code.google.com/p/transitivity-utils/source/browse/trunk/src/edu/bath/transitivityutils/OrderList.java"&gt;Here is my implementation of Bender's structure&lt;/a&gt;.&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="-webkit-border-horizontal-spacing: 2px; -webkit-border-vertical-spacing: 2px; font-family: Arial, Verdana, sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="-webkit-border-horizontal-spacing: 2px; -webkit-border-vertical-spacing: 2px; font-family: Arial, Verdana, sans-serif;"&gt;So how can this structure solve the incremental updates problem? Lets see Dietz' solution of the case of trees. Lets draw another tree.&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="-webkit-border-horizontal-spacing: 2px; -webkit-border-vertical-spacing: 2px; font-family: Arial, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="-webkit-border-horizontal-spacing: 0px; -webkit-border-vertical-spacing: 0px; font-family: 'Times New Roman';"&gt;&lt;a href="http://3.bp.blogspot.com/_H1UVegJ_stI/TFIgM4onX0I/AAAAAAAAAKM/h2HI0SIcU5c/s1600/class_hierarchy3.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="282" src="http://3.bp.blogspot.com/_H1UVegJ_stI/TFIgM4onX0I/AAAAAAAAAKM/h2HI0SIcU5c/s640/class_hierarchy3.png" width="640" /&gt;&lt;/a&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;/div&gt;&lt;span class="Apple-style-span" style="-webkit-border-horizontal-spacing: 2px; -webkit-border-vertical-spacing: 2px; font-family: Arial, Verdana, sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="-webkit-border-horizontal-spacing: 2px; -webkit-border-vertical-spacing: 2px; font-family: Arial, Verdana, sans-serif;"&gt;Okay, so this is the same tree, and I have labelled the nodes with intervals, with one catch - the intervals do not comprise integers, but symbolic names. What's the deal, you say? Here's the deal!&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="-webkit-border-horizontal-spacing: 2px; -webkit-border-vertical-spacing: 2px; font-family: Arial, Verdana, sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/_H1UVegJ_stI/TFIiDgPbRoI/AAAAAAAAAKU/q3eVy-UFrqI/s1600/list.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="84" src="http://2.bp.blogspot.com/_H1UVegJ_stI/TFIiDgPbRoI/AAAAAAAAAKU/q3eVy-UFrqI/s640/list.png" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;span class="Apple-style-span" style="-webkit-border-horizontal-spacing: 2px; -webkit-border-vertical-spacing: 2px; font-family: Arial, Verdana, sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;/div&gt;&lt;span class="Apple-style-span" style="font-family: Arial, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="-webkit-border-horizontal-spacing: 2px; -webkit-border-vertical-spacing: 2px;"&gt;That's it! The colors are there so you can easily match-up the respective nodes. This is a linked list, or more precisely, the order-maintainance list. Any two nodes in it define an interval. For example, [Pet_pre, Pet_post] interval (green in the picture) contain both Cat's and Dog's nodes - precisely because it is an ancestor of both! &lt;b&gt;Note that, internally, these list nodes &lt;i&gt;do&lt;/i&gt;&amp;nbsp;in fact contain integers that observe the total order &lt;/b&gt;(e.g., are monotonically increasing from left to right)&lt;b&gt;&amp;nbsp;so we can test in O(1) whether a node precedes another&lt;/b&gt;. This is quite a simple structure, and there are very good algorithms for inserting a node in it - if there is no space between the integers of the adjacent nodes, an appropriate region of this list is renumbered.&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: Arial, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="-webkit-border-horizontal-spacing: 2px; -webkit-border-vertical-spacing: 2px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: Arial, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="-webkit-border-horizontal-spacing: 2px; -webkit-border-vertical-spacing: 2px;"&gt;&lt;b&gt;&lt;span class="Apple-style-span" style="-webkit-border-horizontal-spacing: 0px; -webkit-border-vertical-spacing: 0px; font-family: 'Times New Roman'; font-weight: normal;"&gt;&lt;span class="Apple-style-span" style="font-family: Arial, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="-webkit-border-horizontal-spacing: 2px; -webkit-border-vertical-spacing: 2px;"&gt;&lt;b&gt;Update:&amp;nbsp;&lt;/b&gt;probably it's obvious, but better be specific. So how do we add a descendant? Lets say we want to add a graph node&amp;nbsp;&lt;b&gt;X&lt;/b&gt;&amp;nbsp;that is a subclass of Pet. We simply create two list nodes, X_pre, X_post, and insert them right&amp;nbsp;&lt;i&gt;before&lt;/i&gt;&amp;nbsp;Pet_post. That would result in a chain&amp;nbsp;&lt;b&gt;&lt;span class="Apple-style-span" style="color: #cc0000;"&gt;Pet_pre&lt;/span&gt;&lt;/b&gt;&amp;nbsp;--&amp;gt; [whatever nodes were already here]&lt;whatever here="" previously="" was=""&gt;&amp;nbsp;--&amp;gt;&amp;nbsp;&lt;b&gt;&lt;span class="Apple-style-span" style="color: blue;"&gt;X_pre&lt;/span&gt;&lt;/b&gt;&amp;nbsp;--&amp;gt;&amp;nbsp;&lt;b&gt;&lt;span class="Apple-style-span" style="color: blue;"&gt;X_post&lt;/span&gt;&lt;/b&gt;&amp;nbsp;--&amp;gt;&amp;nbsp;&lt;b&gt;&lt;span class="Apple-style-span" style="color: red;"&gt;Pet_post&lt;/span&gt;&lt;/b&gt;.&amp;nbsp;&lt;/whatever&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="-webkit-border-horizontal-spacing: 0px; -webkit-border-vertical-spacing: 0px; font-family: 'Times New Roman'; font-weight: normal;"&gt;&lt;span class="Apple-style-span" style="-webkit-border-horizontal-spacing: 2px; -webkit-border-vertical-spacing: 2px; font-family: Arial, Verdana, sans-serif;"&gt;Or we could add these right&amp;nbsp;&lt;i&gt;after&lt;/i&gt;&amp;nbsp;Pet_pre, it's equivalent really. (As a coincidence, both Dietz and I chose the first alternative, to insert child_pre and child_post right&amp;nbsp;&lt;i&gt;before&amp;nbsp;&lt;/i&gt;parent_post. I had a reason for this actually, there is a tiny difference because I'm using Integer.MIN_VALUE as a sentinel value, but that would be way too much details for this post). Of course, to insert a node, say B, between two others, say A and C, we have to find an integer between label(A) and label(C), i.e. to make sure that we have label(A) &amp;lt; label(B) &amp;lt; label(C), without affecting any existing label relation. If label(A) = label(C) + 1 (i.e., consecutive, no space between them for a new node), we have some nodes to&amp;nbsp;&lt;i&gt;make&lt;/i&gt;&amp;nbsp;space at the place of insertion. Compare with Dietz' Figure 4.1, in the "Maintaining order in a linked list" paper.&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: Arial, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="-webkit-border-horizontal-spacing: 2px; -webkit-border-vertical-spacing: 2px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: Arial, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="-webkit-border-horizontal-spacing: 2px; -webkit-border-vertical-spacing: 2px;"&gt;While this might not seem such a big win for the case of trees, it is absolutely necessary in the case of graphs. This is what Agrawal et al missed! &lt;b&gt;Instead of using integers directly, they should have used nodes of an order-maintainance structure.&lt;/b&gt;&amp;nbsp;Why? Because when an interval does not have space to accommodate a new descendant, instead of widening the interval and then &lt;b&gt;scanning the whole graph to find appearances of those integers to fix them, we instead make only local changes in the order maintainance structure in O(1), &lt;i&gt;without even touching the graph&lt;/i&gt;!&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: Arial, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="-webkit-border-horizontal-spacing: 2px; -webkit-border-vertical-spacing: 2px; line-height: 28px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: Arial, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="-webkit-border-horizontal-spacing: 2px; -webkit-border-vertical-spacing: 2px;"&gt;You can visualize the difference in the following example.&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/_H1UVegJ_stI/TFInLcgPtnI/AAAAAAAAAKc/hhqlMM1SGYA/s1600/class_hierarchy5.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="500" src="http://1.bp.blogspot.com/_H1UVegJ_stI/TFInLcgPtnI/AAAAAAAAAKc/hhqlMM1SGYA/s640/class_hierarchy5.png" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;span class="Apple-style-span" style="font-family: Arial, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="-webkit-border-horizontal-spacing: 2px; -webkit-border-vertical-spacing: 2px;"&gt;The segmented edges are non-tree edges, so they propagate upwards the intervals, thus, the &lt;b&gt;H&lt;/b&gt;&amp;nbsp;node ends up having 3 distinct intervals. Now, if instead of nodes such as E_pre and E_post, we had numbers, what would have happened if we wanted to add a descendant under &lt;b&gt;E&lt;/b&gt;&amp;nbsp;but it had no space in its interval? We would fix the boundaries of E's interval, and we would have to search the graph to see where the old boundaries have been propagated (i.e. in nodes &lt;b&gt;F &lt;/b&gt;and &lt;b&gt;H&lt;/b&gt;). With the order maintainance structure, &lt;b&gt;this is not needed&lt;/b&gt;. We locally renumber whichever node is required, and we do it &lt;b&gt;once - we only renumber E_pre and E_post once, and due to sharing, wherever those have been propagated is insignificant, all positions are automatically fixed too! &lt;span class="Apple-style-span" style="font-weight: normal;"&gt;Contrast this to having to visit &lt;/span&gt;F, G&lt;span class="Apple-style-span" style="font-weight: normal;"&gt;&amp;nbsp;and &lt;/span&gt;H&lt;span class="Apple-style-span" style="font-weight: normal;"&gt;, find &lt;/span&gt;E_pre&lt;span class="Apple-style-span" style="font-weight: normal;"&gt;, &lt;/span&gt;E_post&lt;span class="Apple-style-span" style="font-weight: normal;"&gt; in their intervals, and fix them in all places. Let alone if we had to renumber a series of intervals, and hunt the propagations of all of them in the graph.&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: Arial, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="-webkit-border-horizontal-spacing: 2px; -webkit-border-vertical-spacing: 2px;"&gt;&lt;b&gt;&lt;br /&gt;&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: Arial, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="-webkit-border-horizontal-spacing: 2px; -webkit-border-vertical-spacing: 2px;"&gt;Just for completeness, this is what the order maintainance list would look like, in the last example:&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: Arial, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="-webkit-border-horizontal-spacing: 2px; -webkit-border-vertical-spacing: 2px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: Arial, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="-webkit-border-horizontal-spacing: 2px; -webkit-border-vertical-spacing: 2px;"&gt;A_pre --&amp;gt; B_pre --&amp;gt; C_pre --&amp;gt; D_pre --&amp;gt; &lt;b&gt;E_pre&lt;/b&gt; --&amp;gt; &lt;b&gt;E_post &lt;/b&gt;--&amp;gt; D_post --&amp;gt; F_pre --&amp;gt; F_post --&amp;gt; C_post --&amp;gt; G_pre --&amp;gt; G_post --&amp;gt; B_post --&amp;gt; H_pre --&amp;gt; H_post --&amp;gt; A_post.&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: Arial, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="-webkit-border-horizontal-spacing: 2px; -webkit-border-vertical-spacing: 2px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: Arial, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="-webkit-border-horizontal-spacing: 2px; -webkit-border-vertical-spacing: 2px;"&gt;In this structure we perform the renumbering, not in the graph! Particularly, in some (typically small) region that contains the two nodes inside which we want to insert something.&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: Arial, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="-webkit-border-horizontal-spacing: 2px; -webkit-border-vertical-spacing: 2px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: Arial, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="-webkit-border-horizontal-spacing: 2px; -webkit-border-vertical-spacing: 2px;"&gt;So, there you go. This is the trick I (&lt;b&gt;re&lt;/b&gt;)discovered on some Friday of last March, and ended up coding &amp;nbsp;&lt;a href="http://code.google.com/p/transitivity-utils"&gt;http://code.google.com/p/transitivity-utils&lt;/a&gt; in the following weekend, which implements all of the above and more, so you don't have to. It is hard to believe that this went unnoticed for 20 years - and even harder to believe that the solution was there all along,&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="-webkit-border-horizontal-spacing: 2px; -webkit-border-vertical-spacing: 2px; font-family: Arial, Verdana, sans-serif; line-height: 28px;"&gt;&amp;nbsp;waiting for someone to make the connection.&amp;nbsp;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="-webkit-border-horizontal-spacing: 2px; -webkit-border-vertical-spacing: 2px; font-family: Arial, Verdana, sans-serif; line-height: 28px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="-webkit-border-horizontal-spacing: 2px; -webkit-border-vertical-spacing: 2px; font-family: Arial, Verdana, sans-serif; line-height: 28px;"&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="-webkit-border-horizontal-spacing: 2px; -webkit-border-vertical-spacing: 2px; font-family: Arial, Verdana, sans-serif; line-height: 28px;"&gt;Now that's something to ponder about. Oh, and thanks, Dietz. You did your best.&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: Arial, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="-webkit-border-horizontal-spacing: 2px; -webkit-border-vertical-spacing: 2px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: Arial, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="-webkit-border-horizontal-spacing: 2px; -webkit-border-vertical-spacing: 2px;"&gt;If you managed to read all the way down to here, my thanks for your patience. That was way too long a post, but hopefully, you also earned something out of it. I regard this a very interesting story, and wish I was a better storyteller than this, but here you go.&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6958126065976802292-2854160661273445261?l=code-o-matic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://code-o-matic.blogspot.com/feeds/2854160661273445261/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://code-o-matic.blogspot.com/2010/07/graph-reachability-transitive-closures.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6958126065976802292/posts/default/2854160661273445261'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6958126065976802292/posts/default/2854160661273445261'/><link rel='alternate' type='text/html' href='http://code-o-matic.blogspot.com/2010/07/graph-reachability-transitive-closures.html' title='Graph reachability, transitive closures, and a nasty historical accident in the pre-google era'/><author><name>Dimitris Andreou</name><uri>https://profiles.google.com/116229150468867889128</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-l6gGcDEXxqI/AAAAAAAAAAI/AAAAAAAABq0/x5Wy-h5G81Y/s512-c/photo.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_H1UVegJ_stI/TFGwW5JvIUI/AAAAAAAAAJM/EvOAzm3Da6U/s72-c/class_hierarchy.png' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6958126065976802292.post-1102299473855718106</id><published>2010-07-25T12:13:00.000-07:00</published><updated>2010-07-25T16:54:47.166-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='GFS bandwidth google filesystem replicas'/><title type='text'>Google File System - the 'bandwidth' problem</title><content type='html'>I am reading the very interesting &lt;a href="https://docs.google.com/viewer?url=http%3A%2F%2Fstatic.googleusercontent.com%2Fexternal_content%2Funtrusted_dlcp%2Flabs.google.com%2Fen%2F%2Fpapers%2Fgfs-sosp2003.pdf"&gt;Google File System&lt;/a&gt; paper. It describes the situation back in 2003, not sure how much things have changed since then. Before moving to the subject of this post, lets sum up some interesting points of that paper first (only based on my certainly incomplete understanding).&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;GFS clearly favors &lt;b&gt;appending&lt;/b&gt; to files than &lt;b&gt;random access&lt;/b&gt; writing. If all mutations of a file are appends, sequential readers (readers that scan the whole of the file - which represents the vast majority of cases) have also extra consistency guarantees: in the face of concurrent modifications, the only "bad" thing that they may see is the file ending prematurely. But everything up to that point is guaranteed to be well defined and consistent.&lt;/li&gt;&lt;li&gt;A GFS file can be used as an excellent producer-consumer queue! Multiple producers may append ("record append") to the file, with no need for extra synchronization/distributed locking. This is a weaker form of append - the client &lt;b&gt;does not choose &lt;/b&gt;where the data end up to, &lt;b&gt;the primary replica server of that file chooses this&lt;/b&gt;, and the clients get a guarantee that the update with occur &lt;b&gt;at least once&lt;/b&gt;&amp;nbsp;(well, not exactly once, but one can work-around this by uniquely naming the records, if they aren't already named so). This seems much simpler and better than either having to establish distributed locking protocols between producers, or letting them choose the offset in the file where their append should take place, and trying to resolve potential (and possibly very frequent) collisions.&lt;/li&gt;&lt;li&gt;Automatic &lt;b&gt;garbage collection&lt;/b&gt; of orphaned chunks (file pieces) is implemented.&lt;/li&gt;&lt;li&gt;&lt;b&gt;There are quite weak concurrency guarantees&lt;/b&gt; &lt;b&gt;for writers that write &lt;i&gt;lots&lt;/i&gt; of data&lt;/b&gt;. The writer client needs to break up the data into acceptably small pieces, and each piece is written atomically - but if there are multiple writers doing the same, the final result is undefined, it could contain random fragments of the data of each writer.&lt;/li&gt;&lt;li&gt;&lt;b&gt;File metadata updates are atomic&lt;/b&gt;. This is particularly nice, consider the following case: a writer writes to a file, and &lt;b&gt;after&amp;nbsp;&lt;/b&gt;&amp;nbsp;it's done writing, it &lt;b&gt;atomically &lt;/b&gt;renames the file to a name which can then publish to readers. This is the analog of doing a &lt;b&gt;compare-and-swap &lt;/b&gt;(CAS) in a shared memory multiprocessor (SMP), which, importantly, is the base of most &lt;b&gt;lock-free algorithms&lt;/b&gt;. In particular, the writer that writes to a file (unknown to others) is like a thread doing thread-local computation, and only announce the result in the end via an atomic pointer update (&lt;b&gt;atomically&lt;/b&gt; update a root pointer, if nobody has already changed it, or in GFS, if nobody has created the intended filename first).&lt;/li&gt;&lt;/ul&gt;&lt;div&gt;Now, on to the piece that found curious enough to make a post about. A couple of key points:&lt;/div&gt;&lt;div&gt;&lt;ul&gt;&lt;li&gt;&lt;b&gt;When a client wants to write, it can pick whatever replica&lt;/b&gt;&amp;nbsp;to initiate this action (presumably the replica closer to it - and in Google's case, they can infer the "closeness" of two nodes by inspecting their IPs).&amp;nbsp;&lt;/li&gt;&lt;li&gt;&lt;b&gt;The data must be stored &lt;/b&gt;(temporarily)&lt;b&gt;&amp;nbsp;to all replicas before the client notifies the &lt;/b&gt;(designated) &lt;b&gt;primary replica that the write should be committed.&amp;nbsp;&lt;/b&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;This leads to the problem: &lt;b&gt;How to move client's data to be written, to all replicas?&lt;/b&gt;&amp;nbsp;Google's answer is &lt;b&gt;through a chain (hamiltonian path) through all replicas, &lt;/b&gt;starting at the replica that was contacted by the client. This is preferred over e.g. a dissemination tree, so as to bound the requirements of out-bandwidth of &amp;nbsp;replicas - perhaps the best dissemination could be a star-like tree, but too much burden would be placed on the central node, and so on).&amp;nbsp;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Here is a picture taken from the aforementioned paper. Note the thick arrows, they show the chain that data goes through, from the client and to all replicas.&amp;nbsp;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/_H1UVegJ_stI/TEx3S0xdOpI/AAAAAAAAAIk/BP8Os0O5TA0/s1600/Write+Control+and+Data+Flow.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="362" src="http://3.bp.blogspot.com/_H1UVegJ_stI/TEx3S0xdOpI/AAAAAAAAAIk/BP8Os0O5TA0/s400/Write+Control+and+Data+Flow.png" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;But how do we choose the next replica in the chain?&lt;/b&gt;&amp;nbsp;I.e., why we send the data from Replica A to the Primary Replica and then to Replica B, rather than the other way around? Google is using a &lt;b&gt;simple, greedy rule: pick the replica &lt;/b&gt;(that hasn't seen the data yet)&lt;b&gt; that is closest to the current one.&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;&lt;br /&gt;&lt;/b&gt;&lt;/div&gt;&lt;div&gt;This looks like the well (ok, perhaps not so well) known graph theoretic problem, the&amp;nbsp;&lt;a href="http://en.wikipedia.org/wiki/Graph_bandwidth"&gt;Bandwidth Problem&lt;/a&gt;. That is, we have a graph, and we want to create some linear order of the nodes, so that we minimize the total edge distances (e.g. if we put nodes side-by-side, the edges between them would have very low distance/cost). It's NP-Hard.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;To visualize the bandwidth problem, I'm stealing a picture from the excellent Skiena's book, the &lt;a href="http://www.amazon.com/exec/obidos/ASIN/1848000693/thealgorithmrepo"&gt;Algorithm Design Manual&lt;/a&gt;, which I highly recommend. (I guess a free ad here should worth stealing a small picture :-/ ). (By the way, &lt;a href="https://docs.google.com/viewer?url=http%3A%2F%2Fsites.google.com%2Fsite%2Fjimandreou%2Fvarious%2FCopingwiththeNP-HardnessoftheGraphBandwidthProblem.pdf"&gt;here is an excellent treatment of the problem&lt;/a&gt;&amp;nbsp;by&amp;nbsp;Uriel Feige, very conveniently containing approximation algorithms and heuristics).&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/_H1UVegJ_stI/TEx_vls1V0I/AAAAAAAAAIs/Elu8DzNDSAk/s1600/bandwidth.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="161" src="http://2.bp.blogspot.com/_H1UVegJ_stI/TEx_vls1V0I/AAAAAAAAAIs/Elu8DzNDSAk/s400/bandwidth.png" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Well, almost, but not &lt;i&gt;exactly&lt;/i&gt; the same problem. The subtle difference is that in the Bandwidth Problem, we seek to minimize the distance/cost sum of &lt;b&gt;all&lt;/b&gt;&amp;nbsp;edges, while in the case of GFS, we only need to minimize the length of a single (any) Hamiltonian path (the picture just shows an easy case, where apart from a single path there are no more edges in the graph).&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Ok, so I don't know yet how to state this problem. (While reading the paper, I thought it was the same problem, thus the title of this post). Let me do something else for now - lets try to be create an example that &lt;b&gt;maximizes the cost for GFS' heuristic&lt;/b&gt;. Here is what I came up with (click to see larger size):&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/_H1UVegJ_stI/TEyFDcb7MQI/AAAAAAAAAI0/nR4ciTk4rsI/s1600/bandwidth.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="77" src="http://3.bp.blogspot.com/_H1UVegJ_stI/TEyFDcb7MQI/AAAAAAAAAI0/nR4ciTk4rsI/s400/bandwidth.png" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I think that's the worst case scenario. The client chooses the replica in the middle, then we go to the right 1 step (because the one at the left is at distance 2), then we go to the left 3 steps (because the one at the right is at distance 4), and so on, going back and forth, with a total distance travelled = &lt;b&gt;1 + 3 + 7 + 15 = (2^1 - 1) + (2^2 - 1) + (2^3 - 1) + (2^4 - 1) = (2^5 - 1)&lt;/b&gt; &lt;b&gt;&lt;span class="Apple-style-span" style="font-weight: normal;"&gt;=&lt;/span&gt; 31&lt;/b&gt;, or more generally,&amp;nbsp;exactly&lt;b&gt;&amp;nbsp;2^N - 1!&lt;/b&gt;&amp;nbsp;(Of course, don't hold your breath on ever seeing such a topology in an actual GFS cluster!) The optimal solution here would be to go immediately to a boundary replica, either farthest left or right (choose the one closest), and then linearly visit the rest. That would yield a cost of&lt;b&gt; (1 + 4) + (1 + 2 + 4 + 8)&amp;nbsp;= 20, &lt;/b&gt;(1 + 4 to go to the farthest right replica, and then going all the way to the left)&amp;nbsp;or more generally, exactly&amp;nbsp;&lt;b&gt;2^(N - 1) + 2^(N - 3) &lt;/b&gt;(it's fun to work this formula out!).&amp;nbsp;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Now, &lt;b&gt;how much worse is Google's heuristic than the optimal solution?&amp;nbsp;&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;&lt;br /&gt;&lt;/b&gt;&lt;/div&gt;&lt;div&gt;It turns out, (if we assume that I did find the worst case scenario)&lt;b&gt;,&amp;nbsp;&lt;i&gt;Google's solution is at most a factor of 8/5 (= 1.6) of the optimal solution!&lt;/i&gt;&lt;span class="Apple-style-span" style="font-size: x-large;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;&lt;span class="Apple-style-span" style="font-weight: normal;"&gt;(Well, sure enough. To compare 2^N to 2^(N-1) + 2^(N-3), divide everything by 2^N, so we have 1 compared to 1/2 + 1/8, or 5/8).&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-weight: normal;"&gt;Wow! That's extremely good for something as simple! I didn't expect to find such an exact result - one can also&amp;nbsp;&lt;b&gt;&lt;span class="Apple-style-span" style="font-weight: normal;"&gt;compute this easily&lt;/span&gt;&lt;/b&gt;&amp;nbsp;via&amp;nbsp;&lt;a href="http://www.wolframalpha.com/input/?i=lim+((2^n+-+1)+/+((2^(n+-+1)+%2B+2^(n+-+3)))+as+n-%3Einfinity"&gt;WolframAlpha&lt;/a&gt;,&amp;nbsp;which is &lt;i&gt;way&lt;/i&gt;&amp;nbsp;too cool in this kind of problems.&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;&lt;span class="Apple-style-span" style="font-weight: normal;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div&gt;Nice, nice, nice. I thought I would be find something ludicrously bad (in a completely unrealistic scenario), but it turns out, that's just 1.6 times the optimal solution at most!&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;/sheer happy - we haz it :)&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;span class="Apple-style-span" style="font-size: x-large;"&gt;Addendum:&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-size: x-large;"&gt;&lt;b&gt;&lt;br /&gt;&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;Ah, the art of creating good corner case examples. It turns out the above is not the worst case, there is a worse than that, and quite simpler too (I had thought about this earlier, but for some reason I decided that forcing the algorithm to continually go back and forth would be the most expensive).&lt;br /&gt;&lt;br /&gt;Consider this example (again, click to see in full size):&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/_H1UVegJ_stI/TEzMRPVWqTI/AAAAAAAAAI8/ECQEpOcqFH4/s1600/bandwidth.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="112" src="http://1.bp.blogspot.com/_H1UVegJ_stI/TEzMRPVWqTI/AAAAAAAAAI8/ECQEpOcqFH4/s400/bandwidth.png" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;Each adjacent replica pair is separated by unit distance, while the last two are separated by two. We can make the path arbitrarily long, easily forcing the algorithm to choose a path which is a factor of &lt;b&gt;2 - ε &lt;/b&gt;longer than the optimal. And this is to be further restrained: I'm only considering geometric graphs, i.e. graphs where the &lt;a href="http://en.wikipedia.org/wiki/Triangle_inequality"&gt;triangle inequality&lt;/a&gt; holds. &lt;b&gt;I have next to no idea whether actual network topologies resemble geometric graphs&lt;/b&gt;, and certainly one could construct much worse examples in graphs where the notion of distance is completely arbitrary (but distances in a network topology certainly isn't an arbitrary function).&amp;nbsp;It's too late in the night to worry about that, so lets stop here hoping I'm still making some sense. :)&lt;br /&gt;&lt;br /&gt;By the way, I recently bought &lt;a href="http://www.amazon.com/Approximation-Algorithms-Vijay-V-Vazirani/dp/3540653678"&gt;Vazirani's Approximate Algorithms&lt;/a&gt; book. Neat, refreshing read, and highly recommended.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6958126065976802292-1102299473855718106?l=code-o-matic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://code-o-matic.blogspot.com/feeds/1102299473855718106/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://code-o-matic.blogspot.com/2010/07/google-file-system-bandwidth-problem.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6958126065976802292/posts/default/1102299473855718106'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6958126065976802292/posts/default/1102299473855718106'/><link rel='alternate' type='text/html' href='http://code-o-matic.blogspot.com/2010/07/google-file-system-bandwidth-problem.html' title='Google File System - the &apos;bandwidth&apos; problem'/><author><name>Dimitris Andreou</name><uri>https://profiles.google.com/116229150468867889128</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-l6gGcDEXxqI/AAAAAAAAAAI/AAAAAAAABq0/x5Wy-h5G81Y/s512-c/photo.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_H1UVegJ_stI/TEx3S0xdOpI/AAAAAAAAAIk/BP8Os0O5TA0/s72-c/Write+Control+and+Data+Flow.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6958126065976802292.post-346323483784502928</id><published>2010-06-21T07:02:00.000-07:00</published><updated>2010-06-21T07:02:30.536-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='pet projects java jbenchy flexigraph memory-measurer'/><title type='text'>My oldies but goldies pet projects</title><content type='html'>Finally! I took the time to upload some of my old pet projects on google code. Briefly:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://code.google.com/p/flexigraph/"&gt;Flexigraph&lt;/a&gt;: a life-saver of a graph library. :) Packed with several unique features, but I have no time to comment them. Especially the Traverser API scoffs at all other java graph libraries of today (and this is several years old by now).&lt;/li&gt;&lt;li&gt;&lt;a href="http://code.google.com/p/jbenchy/"&gt;JBenchy&lt;/a&gt;: (my friends know this by the imaginative name "aggregator"). This is another life-saver if you are in the business of doing benchmarks/experiments and want a systematic way to store and analyze your collected points. Leverages the sheer expressive and analytical power of SQL GROUP BY statements, yet it hides all SQL from you so you can concentrate on your benchmark itself. It can also create nice diagrams for you, if you need some help with visualization.&lt;/li&gt;&lt;li&gt;&lt;a href="http://code.google.com/p/memory-measurer/"&gt;MemoryMeasurer&lt;/a&gt;: Another uncharacteristically exotic name for a project! This little gem can compute the memory footprint of an arbitrary object graph / data structure. Did you ever wonder how much space does a default HashMap takes? Or an ArrayList of 5 HashMaps? Or whatever? Well, this is the tool for you. Also note that you can use it with JBenchy to create benchmarks for data structures, if this happens to be your thing. Oh, by the way, a new HashMap() takes 120 bytes, in case you &lt;i&gt;did&lt;/i&gt;&amp;nbsp;wonder.&lt;/li&gt;&lt;/ul&gt;&lt;div&gt;Good! All my pets in line, with a new home. Enjoy :)&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6958126065976802292-346323483784502928?l=code-o-matic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://code-o-matic.blogspot.com/feeds/346323483784502928/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://code-o-matic.blogspot.com/2010/06/my-oldies-but-goldies-pet-projects.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6958126065976802292/posts/default/346323483784502928'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6958126065976802292/posts/default/346323483784502928'/><link rel='alternate' type='text/html' href='http://code-o-matic.blogspot.com/2010/06/my-oldies-but-goldies-pet-projects.html' title='My oldies but goldies pet projects'/><author><name>Dimitris Andreou</name><uri>https://profiles.google.com/116229150468867889128</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-l6gGcDEXxqI/AAAAAAAAAAI/AAAAAAAABq0/x5Wy-h5G81Y/s512-c/photo.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6958126065976802292.post-51266849516727688</id><published>2010-05-06T09:30:00.000-07:00</published><updated>2010-05-06T10:06:58.248-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='divide conquer algorithm parallel'/><title type='text'>Motivating Divide and Conquer paradigm</title><content type='html'>Just the other day I went in my old University, met former teachers and collaborators... fun!&lt;br /&gt;&lt;br /&gt;I also attended a lecture on algorithms. The topic: Divide and Conquer.&lt;br /&gt;&lt;br /&gt;The professor presented a very simple example to make the technique apparent. The problem? Find the minimum element of a list. Instead of doing the usual (in pseudocode):&lt;br /&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;result = +oo;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;foreach e in list {&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp;result = min(e, result)&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The divide 'n conquer approach would be:&lt;br /&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;function min(list) &amp;nbsp;{&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp;if (list.size == 1) return array[0]&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp;else {&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;k = list.length / 2&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;return min(&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp;findMin(list.subList(1, k)),&amp;nbsp;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp;findMin(list.subList(k+1, list.size)))&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp;}&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;One could ask, "what's the point". In this example, this doesn't sound important at all. A student with good practical experience with programming would readily recognize that the latter, sophisticated approach is likely to perform worse than the straight-forward iteration. Indeed, a student there asked, "do we gain any gain in time complexity by following the latter approach in this example?". Unfortunately, the answer was no, both &lt;span class="Apple-style-span" style="font-family: inherit;"&gt;versions are O(n), so the exercise "is" pointless.&amp;nbsp;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;Quite some years after the period when I was an undergraduate student, and reflecting on that experience, that was my main gripe with how Computer Science was being taught. Without proper motivation! The student must somehow "guess" by him/herself the importance of the covered topics. An example dialogue that could ensue between students: "-Hey, what did you learn today? -Nothing much, something called 'divide and conquer', it's just a way to create complicated solutions when simple and as good solutions already exist".&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;Since I was attending, I thought I should intervene and give the very, very, very imporant motivation for learning this algorithm design paradigm. The reason is the all-too-known fact that CPUs have stopped getting faster, and they only become more numerous. This can be easily recognized, but it also has a tremendous implication in how we design software. Even for this simplistic problem, the first method of computing the minimum element is &lt;b&gt;doomed&lt;/b&gt;. It may not fail tomorrow, it might not fail next year or the year after, but it's doomed nevertheless. Imagine you have a billion elements of which to find the minimum. Also imagine your run-of-the-mill computer has hundreds of processing cores (by the way, we should stop calling them CPUs/&lt;b&gt;Central&lt;/b&gt; Processing Units, how "central" is something you have hundreds of?).&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;Here is the expression that the first method is trying to evaluate:&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/_H1UVegJ_stI/S-LtBpC4bDI/AAAAAAAAAHQ/pNjyXTTM_b8/s1600/iterated.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="400" src="http://3.bp.blogspot.com/_H1UVegJ_stI/S-LtBpC4bDI/AAAAAAAAAHQ/pNjyXTTM_b8/s400/iterated.png" width="282" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;I.e., you first find the minimum of the first two elements, then you find the minimum of that and the third element, then the minimum of that and the fourth element, etc, etc. The point is, the &lt;b&gt;Kth&lt;/b&gt;&amp;nbsp;call (K&amp;gt;1) to min() always must wait first for the result of the &lt;b&gt;(K-1)th &lt;/b&gt;call of min() to become available. Each min() invocation takes (say) a unit of time, so the final computation cannot consume less that K time units, no matter whether you have a single core or thousands of them. The so called "critical path" (the longest path of things that must happen sequentially) as is also apparent in the diagram, has length K. Bad.&lt;br /&gt;&lt;br /&gt;This is what happens with divide and conquer instead:&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/_H1UVegJ_stI/S-LtYmS2oKI/AAAAAAAAAHY/6jZFs1KBXhI/s1600/divide_conquer.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="240" src="http://1.bp.blogspot.com/_H1UVegJ_stI/S-LtYmS2oKI/AAAAAAAAAHY/6jZFs1KBXhI/s400/divide_conquer.png" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;Still, the root depends to two other min() invocations, and must wait for them before evaluating itself. But those two are not dependent on each other, &lt;b&gt;they may run in parallel. &lt;/b&gt;The critical path here has length only logK. Thus, divide and conquer can solve this problem in &lt;b&gt;O(logN) &lt;/b&gt;instead of &lt;b&gt;O(N)&lt;/b&gt;. Without leaving your excess of processing cores to sit (and waste energy) idly.&lt;br /&gt;&lt;br /&gt;As I explained to the student, this epitomizes programming of the future. Of course that's a hyperbole, but hyperboles are useful to drive a point home. And it is certainly better than present something dry to the student, without any hint of its importance - that's the recipy to make him/her &lt;b&gt;not &lt;/b&gt;pay attention, and soon forget about this weird, exotic thingy.&lt;br /&gt;&lt;br /&gt;That's all for now! Oh, and if you want to actually implement algorithms like this, and you code in Java, the &lt;a href="http://gee.cs.oswego.edu/dl/concurrency-interest/index.html"&gt;fork/join framework&lt;/a&gt; is something you'll definitely want to learn.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6958126065976802292-51266849516727688?l=code-o-matic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://code-o-matic.blogspot.com/feeds/51266849516727688/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://code-o-matic.blogspot.com/2010/05/motivating-divide-and-conquer-paradigm.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6958126065976802292/posts/default/51266849516727688'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6958126065976802292/posts/default/51266849516727688'/><link rel='alternate' type='text/html' href='http://code-o-matic.blogspot.com/2010/05/motivating-divide-and-conquer-paradigm.html' title='Motivating Divide and Conquer paradigm'/><author><name>Dimitris Andreou</name><uri>https://profiles.google.com/116229150468867889128</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-l6gGcDEXxqI/AAAAAAAAAAI/AAAAAAAABq0/x5Wy-h5G81Y/s512-c/photo.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_H1UVegJ_stI/S-LtBpC4bDI/AAAAAAAAAHQ/pNjyXTTM_b8/s72-c/iterated.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6958126065976802292.post-3330693274269645311</id><published>2010-04-13T17:02:00.000-07:00</published><updated>2010-04-13T17:02:03.752-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Matrix chain order CLRS dynamic programming'/><title type='text'>My solution to Matrix-Chain-Order problem (Chapter 15 of CLRS)</title><content type='html'>&lt;span class="Apple-style-span" style="font-family: Arial, Helvetica, sans-serif;"&gt;For practice, I tried solving the problem "Matrix-Chain-Order" that appears on section 15.2 of &lt;/span&gt;&lt;a href="http://mitpress.mit.edu/catalog/item/default.asp?tid=8570&amp;amp;ttype=2"&gt;&lt;span class="Apple-style-span" style="font-family: Arial, Helvetica, sans-serif;"&gt;Introduction to Algorithms&lt;/span&gt;&lt;/a&gt;&lt;span class="Apple-style-span" style="font-family: Arial, Helvetica, sans-serif;"&gt;&amp;nbsp;(that's the chapter on Dynamic Programming). In short, one gets a list of (compatible) matrices, A1, A2, A3... An, and the problem is to compute the optimal order for creating their product.&amp;nbsp;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: Arial, Helvetica, sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: Arial, Helvetica, sans-serif;"&gt;I liked my solution, so I'm posting this just for the record. This should be helpful if one is reading that section and looks for a Java implementation of that problem (in order to compare with his own solution of course :)). To make it tougher, I tried it writing this first on paper, then in my IDE, to see how many errors would slip in the paper version. There were two: a single off-by-one error in the inner loop (damn!), and that I forgot some components of the cost of a particular multiplication expression.&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: Arial, Helvetica, sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: Arial, Helvetica, sans-serif;"&gt;It creates optimal multiplication expressions of increasing width. Initially width == 1, and we just have the leaves, the matrixes themselves. Next, we find the optimal expressions of width == 2, but there is only one order to multiple 2 arrays, so nothing special happens. After that, things get more interesting, since we get to create various possible trees for each sequence of matrixes, and retain the best.&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: Arial, Helvetica, sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: Arial, Helvetica, sans-serif;"&gt;Amazingly, it is exactly one year (to the day!) ago that I posted a same exercise in tree building (enumerating binary trees, also via dynamic programming):&amp;nbsp;&lt;span class="Apple-style-span" style="font-family: 'Times New Roman';"&gt;&lt;a href="http://code-o-matic.blogspot.com/2009/04/wonderful-programming-exercise.html"&gt;http://code-o-matic.blogspot.com/2009/04/wonderful-programming-exercise.html&lt;/a&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: Arial, Helvetica, sans-serif;"&gt;I think I need more diversity :)&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: Arial, Helvetica, sans-serif;"&gt;Anyway. The main method is this:&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;public static void main(String[] args) {&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;Op op = matrixChainOrder(Arrays.asList(&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;new Matrix(30, 35),&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;new Matrix(35, 15),&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;new Matrix(15, 5),&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;new Matrix(5, 10),&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;new Matrix(10, 20),&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;new Matrix(20, 25)));&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;System.out.println(op);&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;System.out.println("Cost: " + op.cost());&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;}&lt;/span&gt;&lt;br /&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;And it prints:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;(([30 X 35] * ([35 X 15] * [15 X 5])) * (([5 X 10] * [10 X 20]) * [20 X 25]))&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;Cost: 15125&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;(This mimicks the example and solution of the book, but it also creates the expression of the multiplication, easy to pretty-print and ready to be computed).&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The full code:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;import java.util.*;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;public class Matrixes {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;public static void main(String[] args) {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;Op op = matrixChainOrder(Arrays.asList(&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;new Matrix(30, 35),&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;new Matrix(35, 15),&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;new Matrix(15, 5),&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;new Matrix(5, 10),&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;new Matrix(10, 20),&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;new Matrix(20, 25)));&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;System.out.println(op);&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;System.out.println("Cost: " + op.cost());&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;}&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;static Op matrixChainOrder(List&lt;matrix&gt; matrixes) {&lt;/matrix&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;Map&lt;interval, op=""&gt; optima = new HashMap&lt;interval, op=""&gt;();&lt;/interval,&gt;&lt;/interval,&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;for (int i = 0; i &amp;lt; matrixes.size(); i++) {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;optima.put(new Interval(i, i), new Leaf(matrixes.get(i)));&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;}&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;for (int width = 1; width &amp;lt; matrixes.size(); width++) {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;for (int offset = 0; offset &amp;lt; matrixes.size() - width; offset++) {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;Op best = DUMMY;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;for (int cut = 0; cut &amp;lt; width; cut++) {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;Op left = optima.get(new Interval(offset, offset + cut));&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;Op right = optima.get(new Interval(offset + cut + 1, offset + width));&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;Op mul = new Mul(left, right);&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;if (mul.cost() &amp;lt; best.cost()) {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;best = mul;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;}&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;}&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;optima.put(new Interval(offset, offset + width), best);&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;}&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;}&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;return optima.get(new Interval(0, matrixes.size() - 1));&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;}&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;private static final Op DUMMY = new Op() {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;public int cost() { return Integer.MAX_VALUE; }&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;public Matrix compute() { throw new AssertionError(); }&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;public int rows() { throw new AssertionError(); }&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;public int columns() { throw new AssertionError(); }&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;};&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;private static class Interval {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;final int begin;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;final int end;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;Interval(int begin, int end) { this.begin = begin; this.end = end; }&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;public boolean equals(Object o) {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;if (!(o instanceof Interval)) return false;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;Interval that = (Interval)o;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;return this.begin == that.begin &amp;amp;&amp;amp; this.end == that.end;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;}&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;public int hashCode() { return 31 * begin * (17 + end * 31); }&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;public String toString() { return "[" + begin + ".." + end + "]"; }&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;}&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;}&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;class Matrix {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;final int rows; final int columns;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;Matrix(int rows, int columns) { this.rows = rows; this.columns = columns; }&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;int rows() { return rows; }&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;int columns() { return columns; }&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;public String toString() { return "[" + rows + " X " + columns + "]"; }&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;}&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;interface Op {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;int cost();&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;Matrix compute();&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;int rows();&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;int columns();&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;}&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;class Leaf implements Op {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;final Matrix matrix;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;Leaf(Matrix matrix) { this.matrix = matrix; }&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;public int cost() { return 0; }&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;public Matrix compute() { return matrix; }&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;public int rows() { return matrix.rows(); }&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;public int columns() { return matrix.columns(); }&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;public String toString() { return matrix.toString(); }&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;}&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;class Mul implements Op {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;final Op left;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;final Op right;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;Mul(Op left, Op right) {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;this.left = left; this.right = right;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;}&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;public int rows() {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;return left.rows();&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;}&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;public int columns() {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;return right.columns();&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;}&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;public int cost() {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;return left.rows() * left.columns() * right.columns() + left.cost() + right.cost();&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;}&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;public Matrix compute() { throw new UnsupportedOperationException("later"); }&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;public String toString() { return "(" + left + " * " + right + ")"; }&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6958126065976802292-3330693274269645311?l=code-o-matic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://code-o-matic.blogspot.com/feeds/3330693274269645311/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://code-o-matic.blogspot.com/2010/04/my-solution-to-matrix-chain-order.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6958126065976802292/posts/default/3330693274269645311'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6958126065976802292/posts/default/3330693274269645311'/><link rel='alternate' type='text/html' href='http://code-o-matic.blogspot.com/2010/04/my-solution-to-matrix-chain-order.html' title='My solution to Matrix-Chain-Order problem (Chapter 15 of CLRS)'/><author><name>Dimitris Andreou</name><uri>https://profiles.google.com/116229150468867889128</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-l6gGcDEXxqI/AAAAAAAAAAI/AAAAAAAABq0/x5Wy-h5G81Y/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6958126065976802292.post-2622037635740802305</id><published>2010-03-15T15:34:00.000-07:00</published><updated>2010-03-26T03:41:23.670-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='transitivity-utils transitive relation'/><title type='text'>Announcing transitivity utilities project</title><content type='html'>Check out my new project: &lt;a href="http://code.google.com/p/transitivity-utils/"&gt;http://code.google.com/p/transitivity-utils/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;This is the recycled message I sent about this at the guava mailing list:&lt;br /&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;--------&lt;/div&gt;I have implemented some new data structures that may be of interest to someone. It is about maintaining transitive relations efficiently, both in terms of memory and time complexity. Internally it uses interval-encoding for elements, which for example can handle reachability queries in trees in just O(1) time and O(1) memory per element. It's not good for graphs that are close to full bipartite graphs - then memory degenerates to O(N) per element and O(logN) for testing reachability.&lt;br /&gt;&lt;br /&gt;&lt;div&gt;Historically, the motivation for this line of research has been encoding inheritance relations in knowledge bases. (For a more familiar example, this can be used to directly implement the instanceof operator of Java, but I don't suggest that!).&lt;br /&gt;&lt;br /&gt;The central type amounts to:&lt;br /&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;TransitiveRelation {&lt;br /&gt;&amp;nbsp;&amp;nbsp; void relate(E subject, E object);&lt;br /&gt;&amp;nbsp;&amp;nbsp; boolean areRelated(E subject, E object);&lt;br /&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;This should be considered for any algorithm that relies on reachability queries.&lt;br /&gt;&lt;br /&gt;I regard the API rather stable (except for I might need better names here and there).&lt;br /&gt;----&lt;br /&gt;&amp;nbsp;Boy, the effort it takes.&lt;br /&gt;&lt;br /&gt;Long story short, I believe I've found the sweetest spot in the design space for this problem. It contains magic sauce found nowhere else. The gist of the underlying solution is so (deceptively?!) simple that it's hard not to ask: "how could &lt;i&gt;that &lt;/i&gt;be overlooked for 20 years?". The details will wait for a future post (but the source is there already).&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6958126065976802292-2622037635740802305?l=code-o-matic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://code-o-matic.blogspot.com/feeds/2622037635740802305/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://code-o-matic.blogspot.com/2010/03/announcing-transitivity-utilities.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6958126065976802292/posts/default/2622037635740802305'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6958126065976802292/posts/default/2622037635740802305'/><link rel='alternate' type='text/html' href='http://code-o-matic.blogspot.com/2010/03/announcing-transitivity-utilities.html' title='Announcing transitivity utilities project'/><author><name>Dimitris Andreou</name><uri>https://profiles.google.com/116229150468867889128</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-l6gGcDEXxqI/AAAAAAAAAAI/AAAAAAAABq0/x5Wy-h5G81Y/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6958126065976802292.post-8232886377840393925</id><published>2010-02-19T04:42:00.000-08:00</published><updated>2010-02-19T05:26:44.753-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='int overflow underflow average'/><title type='text'>Find the average between two ints (facing possible overflows/underflows)</title><content type='html'>How do you compute the average between two ints in Java?&lt;br /&gt;&lt;br /&gt;How about...&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;(x + y) / 2&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Well, that doesn't work when (x + y) can overflow, and in fact this buggy implementation was lurking in the binary-search and mergesort implementations of JDK till recent years. (Obligatory Josh Bloch link:&amp;nbsp;&lt;a href="http://googleresearch.blogspot.com/2006/06/extra-extra-read-all-about-it-nearly.html"&gt;http://googleresearch.blogspot.com/2006/06/extra-extra-read-all-about-it-nearly.html&lt;/a&gt;)&lt;br /&gt;&lt;br /&gt;It's an interesting puzzle for you to meditate and try out yourself - it looks simple, but it's not. I have yet to find a simple solution that works without assumptions on x, y - just any ints.&lt;br /&gt;&lt;br /&gt;Blochs first solution is this:&lt;br /&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;x + (y&amp;nbsp;- x) / 2&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;I.e. starting with x&amp;nbsp;and adding half the distance to &lt;b&gt;y&lt;/b&gt;. Only that this assumes that x,y &amp;gt; 0, otherwise y-x can itself overflow!&lt;br /&gt;&lt;br /&gt;The second solution:&lt;br /&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;(x + y) &amp;gt;&amp;gt;&amp;gt; 1&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Pretty nifty. If (x + y) &lt;i&gt;does&lt;/i&gt;&amp;nbsp;overflow, the high bit of the number (which determines the sign) will become one, i.e. negative, but &amp;gt;&amp;gt;&amp;gt; 1 will do the division and put a zero there. But what if (x + y) underflows (x, y are big negative numbers)? Oops.&lt;br /&gt;&lt;br /&gt;So neither solution works for all cases.&lt;br /&gt;&lt;br /&gt;Still working out a solution. In my case, I only need that &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;average(x, y) != x &amp;amp;&amp;amp; average(x, y) != y&lt;/span&gt;, &amp;nbsp;when x and y are not consecutive ints. Any helping hand appreciated :)&lt;br /&gt;&lt;br /&gt;My current solution:&lt;br /&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;static int avg(int x, int y) {&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;return diffSign(x, y) ? (x + y) / 2 :&amp;nbsp;x + (y - x) / 2;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;static boolean diffSign(int x, int y) {&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;return (x ^ y) &amp;lt; 0;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;i&gt;diffSign&lt;/i&gt;&amp;nbsp;returns true iff x and y do not have the same sign. In that case only, (x + y) is safe. Otherwise, (y - x) is safe, so I go for that option.&amp;nbsp;This solution works for corner cases (like Integer.MIN_VALUE) too.&amp;nbsp;Well, I don't think I can get it any simpler (assuming it's really correct). Can you?&lt;br /&gt;&lt;br /&gt;-edit-&lt;br /&gt;It turns out there is a much more elegant solution, which is provably correct, &lt;a href="http://docs.google.com/viewer?url=http://joyofprogramming.com/Docs_ColumnArticles/26-JoP-Feb-09.pdf"&gt;found here&lt;/a&gt;.&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;static int avg(int x, int y) {&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp;return (x &amp;amp; y) + (x ^ y) / 2;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Wow!..&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6958126065976802292-8232886377840393925?l=code-o-matic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://code-o-matic.blogspot.com/feeds/8232886377840393925/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://code-o-matic.blogspot.com/2010/02/find-average-between-two-ints-facing.html#comment-form' title='7 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6958126065976802292/posts/default/8232886377840393925'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6958126065976802292/posts/default/8232886377840393925'/><link rel='alternate' type='text/html' href='http://code-o-matic.blogspot.com/2010/02/find-average-between-two-ints-facing.html' title='Find the average between two ints (facing possible overflows/underflows)'/><author><name>Dimitris Andreou</name><uri>https://profiles.google.com/116229150468867889128</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-l6gGcDEXxqI/AAAAAAAAAAI/AAAAAAAABq0/x5Wy-h5G81Y/s512-c/photo.jpg'/></author><thr:total>7</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6958126065976802292.post-2319093588174208768</id><published>2010-01-13T14:47:00.000-08:00</published><updated>2010-01-13T14:47:35.731-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='scala stackoverflow case-classes traits equals'/><title type='text'>Traits defining equals, combined with case classes</title><content type='html'>I just contributed a &lt;a href="http://stackoverflow.com/questions/1332574/common-programming-mistakes-for-scala-developers-to-avoid/2060849#2060849"&gt;"common programming mistake for Scala developers"&lt;/a&gt;, in the relevant &lt;a href="http://stackoverflow.com/questions/1332574/common-programming-mistakes-for-scala-developers-to-avoid"&gt;thread&lt;/a&gt; over at &lt;a href="http://stackoverflow.com/"&gt;stackoverflow&lt;/a&gt;&amp;nbsp;(which seems to be turning into a mania, given I contributed quite valuable time myself without really thinking about it). It describes a pitfall from the interplay of case classes, traits and equality defined in the latter - by no means this can be really a "common" mistake, but it is not obvious enough so some help to keep it uncommon doesn't hurt.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6958126065976802292-2319093588174208768?l=code-o-matic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://code-o-matic.blogspot.com/feeds/2319093588174208768/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://code-o-matic.blogspot.com/2010/01/traits-defining-equals-combined-with.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6958126065976802292/posts/default/2319093588174208768'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6958126065976802292/posts/default/2319093588174208768'/><link rel='alternate' type='text/html' href='http://code-o-matic.blogspot.com/2010/01/traits-defining-equals-combined-with.html' title='Traits defining equals, combined with case classes'/><author><name>Dimitris Andreou</name><uri>https://profiles.google.com/116229150468867889128</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-l6gGcDEXxqI/AAAAAAAAAAI/AAAAAAAABq0/x5Wy-h5G81Y/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6958126065976802292.post-3843631383346774341</id><published>2010-01-08T14:46:00.000-08:00</published><updated>2010-01-11T00:06:59.208-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='scala actors fork join'/><title type='text'>Thoughts on Actors</title><content type='html'>&lt;a href="http://old.nabble.com/Guidelines-for-applying-Akka-in-practical-solutions-td27077976.html"&gt;This discussion&lt;/a&gt;&amp;nbsp;(started today) on the scala mailing list relates to understanding the usefulness of &lt;a href="http://akkasource.org/"&gt;Akka&lt;/a&gt;, and more generally, &lt;a href="http://www.scala-lang.org/node/242"&gt;actors&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Somebody suggested comparing using actors to using locks directly. The following are my comments, intially meant as a response, but I ended summarizing many of my current concerns/questions regarding the actor programming model.&lt;br /&gt;&lt;br /&gt;This contrast between actors and low-level concurrent programming (e.g. locks) is misleading. It's not like that there are actors, then a huge void, and then locks, where we get to choose an extreme. There are tons of things in-between. For example, message passing in a single VM is trivial to implement on top of &lt;a href="http://java.sun.com/javase/6/docs/api/java/util/concurrent/BlockingQueue.html"&gt;BlockingQueues &lt;/a&gt;(or, soon, &lt;a href="http://gee.cs.oswego.edu/dl/jsr166/dist/jsr166ydocs/jsr166y/TransferQueue.html"&gt;TransferQueues&lt;/a&gt;). There already exists the &lt;a href="http://java.sun.com/javase/6/docs/api/java/util/concurrent/Executor.html"&gt;executor&lt;/a&gt;&amp;nbsp;framework, and the &lt;a href="http://gee.cs.oswego.edu/dl/papers/fj.pdf"&gt;fork/join framework&lt;/a&gt;, to provide thread pools and fine-grained parallelism.&lt;br /&gt;&lt;br /&gt;My take is that actors provide a simplified, more elegant programming model than using the underlying tools directly. At their core, typical actors are a Runnable accompanied with a BlockingQueue (mailbox), while reactors are event listeners. A strong point of actors, as the&amp;nbsp;&lt;a href="http://lamp.epfl.ch/~phaller/doc/haller07coord.pdf"&gt;Haller/Odersky&lt;/a&gt; paper shows, is that they unify thread-based and event-based models - one can use and combine either under the same framework. This programming model is still young and requires exploration to find its best use cases and fully appreciate it. As much as anything, this too needs an "Effective Actors" type of book. It is easy to go wrong too, especially for beginners trying to wrap their heads around MPI-like programming. Deadlocks are still possible (actors waiting forever for messages that will not come), race conditions are still possible (an actor giving up on waiting a reply, right before the actual reply arrives), it's not like the usual suspects of concurrent programming have magically vanished. &lt;b&gt;(Edit&lt;/b&gt;: Probably I'm wrong to classify the last case as a race condition, it's likely just a data race, following the nomeclature of &lt;a href="http://www.javaconcurrencyinpractice.com/"&gt;JCiP&lt;/a&gt;&lt;b&gt;)&lt;/b&gt;.&lt;br /&gt;&lt;br /&gt;Moreover, the simplification has its cost too - it's not easy, at least for me, to reason about performance implications. For example, assuming scala actors that depend on &lt;a href="https://lampsvn.epfl.ch/trac/scala/browser/scala/trunk/src/actors/scala/actors/scheduler/ForkJoinScheduler.scala"&gt;ForkJoinScheduler&lt;/a&gt;&amp;nbsp;(i.e. using the fork/join framework), this quotation from the javadocs of &lt;a href="http://gee.cs.oswego.edu/dl/jsr166/dist/jsr166ydocs/jsr166y/ForkJoinPool.html"&gt;ForkJoinPool &lt;/a&gt;is interesting:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;A ForkJoinPool may be constructed with a given parallelism level (target pool size), which it attempts to maintain by dynamically adding, suspending, or resuming threads, even if some tasks are waiting to join others. However, no such adjustments are performed in the face of blocked IO or other unmanaged synchronization.&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;This leads to some obvious questions which I can't answer easily at all:&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;What are the (performance) implications of using (blocking) IO in actors? (I haven't seen similar warnings given to actors users).&lt;/li&gt;&lt;li&gt;Noting that tasks are never joined, all receive() blocking calls fall under "unmanaged synchronization" as per the javadoc, so what are the implications of this fact?&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;So, simplification also seems to come at the cost of hiding possible important optimizations, like having a thread that needs to block in order to&amp;nbsp;&lt;a href="http://gee.cs.oswego.edu/dl/jsr166/dist/jsr166ydocs/jsr166y/ForkJoinTask.html#join()"&gt;join()&lt;/a&gt;&amp;nbsp;subtasks, to go and execute other tasks while waiting (via &lt;a href="http://gee.cs.oswego.edu/dl/jsr166/dist/jsr166ydocs/jsr166y/ForkJoinTask.html#helpJoin()"&gt;helpJoin()&lt;/a&gt;).&lt;br /&gt;&lt;br /&gt;I'm not sure what the conclusion should be. Hopefully in 3-4 years collective experience will be substantial and we will better understand how these shiny new tools are best used, and when the underlying concurrency utilities should be used instead. Personally, as of now, while I am eager to experiment with actors, I feel more at home with more low-level tools, so I can more easily reason about the performance characteristics of my code. Hopefully someone will submit to the task of writing a good scala actors book - current books are OK, but Scala is new, so they are devoted to Scala mostly, and perhaps have a chapter on actors, which is too little to go anywhere beyond the very basics.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6958126065976802292-3843631383346774341?l=code-o-matic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://code-o-matic.blogspot.com/feeds/3843631383346774341/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://code-o-matic.blogspot.com/2010/01/thoughts-on-actors.html#comment-form' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6958126065976802292/posts/default/3843631383346774341'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6958126065976802292/posts/default/3843631383346774341'/><link rel='alternate' type='text/html' href='http://code-o-matic.blogspot.com/2010/01/thoughts-on-actors.html' title='Thoughts on Actors'/><author><name>Dimitris Andreou</name><uri>https://profiles.google.com/116229150468867889128</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-l6gGcDEXxqI/AAAAAAAAAAI/AAAAAAAABq0/x5Wy-h5G81Y/s512-c/photo.jpg'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6958126065976802292.post-606164091816636881</id><published>2009-12-26T04:35:00.000-08:00</published><updated>2010-01-06T18:22:08.320-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='liskov matchmaker photo'/><title type='text'>Barbara Liskov talk and vintage photo</title><content type='html'>&lt;div style="text-align: left;"&gt;Few days earlier I was happy to see this talk given by Barbara Liskov:&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;a href="http://www.infoq.com/presentations/liskov-power-of-abstraction"&gt;http://www.infoq.com/presentations/liskov-power-of-abstraction&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Few days earlier I submitted a paper to &lt;a href="http://www.eswc2010.org/"&gt;ESWC10&lt;/a&gt;  (&lt;a href="http://sites.google.com/site/jimandreou/publications"&gt; found here &lt;/a&gt;, titled "Flexible Ranking and Matchmaking for Semantic Service Discovery"), which happened to include a reference to Liskov and her well known substitution principle (the bottom side of the 3rd page). &lt;br /&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;It was not a big deal, just "common sense" reiterated. As you will notice from the talk above, though, at the 70ies this kind of "common sense" we take for granted today, was debatable and unclear then -- just as debatable was whether the &lt;i&gt;goto &lt;/i&gt;statement was evil or not!&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;One thing that impressed me most in that talk was a photo that Barbara shared with the audience, from the 70ies. I had never saw her young!&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/_H1UVegJ_stI/SzYGimYMlbI/AAAAAAAAADk/qHb2q6oKC3k/s1600-h/barbara_liskov.jpg" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"&gt;&lt;img alt="" border="0" id="BLOGGER_PHOTO_ID_5419526393074324914" src="http://3.bp.blogspot.com/_H1UVegJ_stI/SzYGimYMlbI/AAAAAAAAADk/qHb2q6oKC3k/s400/barbara_liskov.jpg" style="cursor: pointer; display: block; height: 223px; margin-bottom: 10px; margin-left: auto; margin-right: auto; margin-top: 0px; text-align: center; width: 400px;" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: center;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;I will leave the photo uncommented - it speaks for itself. -edit: well, I commented it after all, see below :)&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6958126065976802292-606164091816636881?l=code-o-matic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://code-o-matic.blogspot.com/feeds/606164091816636881/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://code-o-matic.blogspot.com/2009/12/barbara-liskov-talk-and-vintage-photo.html#comment-form' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6958126065976802292/posts/default/606164091816636881'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6958126065976802292/posts/default/606164091816636881'/><link rel='alternate' type='text/html' href='http://code-o-matic.blogspot.com/2009/12/barbara-liskov-talk-and-vintage-photo.html' title='Barbara Liskov talk and vintage photo'/><author><name>Dimitris Andreou</name><uri>https://profiles.google.com/116229150468867889128</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-l6gGcDEXxqI/AAAAAAAAAAI/AAAAAAAABq0/x5Wy-h5G81Y/s512-c/photo.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_H1UVegJ_stI/SzYGimYMlbI/AAAAAAAAADk/qHb2q6oKC3k/s72-c/barbara_liskov.jpg' height='72' width='72'/><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6958126065976802292.post-8021817201143799104</id><published>2009-10-20T12:30:00.001-07:00</published><updated>2009-10-20T12:53:52.203-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='google collections recursive union'/><title type='text'>Beware of recursive set union building!</title><content type='html'>The excellent &lt;a href="http://code.google.com/p/google-collections/"&gt;Google collections&lt;/a&gt; library spoils many of us, but that doesn't mean we can afford not being alert using it! &lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Observe how easy it is, for example, to create the (live) union of two sets: &lt;a href="http://google-collections.googlecode.com/svn/trunk/javadoc/com/google/common/collect/Sets.html#union(java.util.Set, java.util.Set)"&gt;Sets.union(setA, setB)&lt;/a&gt;.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;One might be tempted to write code like the following, to make the union of all sets in "S":&lt;/div&gt;&lt;pre&gt;&lt;br /&gt;Set&amp;lt;E&gt; union = Collections.emptySet();&lt;br /&gt; for (Set&amp;lt;E&gt; someSet : S) {&lt;br /&gt;   union = Sets.union(someSet, union)&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;Wow! This build the union in just O(|S|) time! Sure enough, accessing the elements of the union is a different issue, but how slow could it be? (Note that we do pass the smallest union as first argument, in agreement with what javadocs suggest).&lt;br /&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Well, it turns out, this is quite slow. Iterating over the elements of the union take O(N|S|), which for really small sets can be up to O(N^2), where N is the number of all elements of the union. In comparison, creating a single HashSet and calling addAll() to add each set in S to that, takes only O(N) time.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;To understand the issue, consider the algorithm for computing the elements of the union of sets A and B:&lt;/div&gt;&lt;pre&gt;&lt;br /&gt;report all elements in A&lt;br /&gt;for all items x in A&lt;br /&gt; if !b.contains(x)&lt;br /&gt;   report x&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Now consider this union: &lt;b&gt;union(A, union(B, union(C, D)))&lt;/b&gt;, graphically shown below.&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_H1UVegJ_stI/St4TIKv6h-I/AAAAAAAAABM/2MCWJQRuhiQ/s1600-h/tree.png"&gt;&lt;br /&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 180px; height: 270px;" src="http://3.bp.blogspot.com/_H1UVegJ_stI/St4TIKv6h-I/AAAAAAAAABM/2MCWJQRuhiQ/s320/tree.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5394770434681636834" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;div&gt;This is how the union's iterator would report its elements:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;1) Iterate and report all elements of A&lt;/div&gt;&lt;div&gt;2) Iterate elements of B, if they are not in A, report them&lt;/div&gt;&lt;div&gt;3) Iterate elements in C, if they are not in B, then if they are not in A, report them&lt;/div&gt;&lt;div&gt;4) Iterate elements in D, if they are not in C, then if they are not in B, then if they are not in A, report them&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;See the pattern there? Well, that's it. Just resist the temptation to make a recursive union, that's all. (I haven't looked the matter deeply, but I think this shouldn't be affecting recursive intersection or recursive difference).&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;So, in this case, creating a big HashSet and dumping all elements in it is the way to go. It is a bit of a pity that a HashSet is really a HashMap in disguise, i.e. horribly wasteful (compared to what a genuine HashSet implementation should be), but that's life in Java :)&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Till next time,&lt;/div&gt;&lt;div&gt;Bye bye!&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6958126065976802292-8021817201143799104?l=code-o-matic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://code-o-matic.blogspot.com/feeds/8021817201143799104/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://code-o-matic.blogspot.com/2009/10/beware-of-recursive-set-union-building.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6958126065976802292/posts/default/8021817201143799104'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6958126065976802292/posts/default/8021817201143799104'/><link rel='alternate' type='text/html' href='http://code-o-matic.blogspot.com/2009/10/beware-of-recursive-set-union-building.html' title='Beware of recursive set union building!'/><author><name>Dimitris Andreou</name><uri>https://profiles.google.com/116229150468867889128</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-l6gGcDEXxqI/AAAAAAAAAAI/AAAAAAAABq0/x5Wy-h5G81Y/s512-c/photo.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_H1UVegJ_stI/St4TIKv6h-I/AAAAAAAAABM/2MCWJQRuhiQ/s72-c/tree.png' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6958126065976802292.post-4181973929443854359</id><published>2009-10-08T19:18:00.001-07:00</published><updated>2009-10-08T19:23:41.838-07:00</updated><title type='text'>Using JConsole to monitor...JConsole</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_H1UVegJ_stI/Ss6d9R8pfZI/AAAAAAAAABE/s5zpK-s0wkw/s1600-h/jconsole.JPG"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 266px;" src="http://3.bp.blogspot.com/_H1UVegJ_stI/Ss6d9R8pfZI/AAAAAAAAABE/s5zpK-s0wkw/s320/jconsole.JPG" border="0" alt="" id="BLOGGER_PHOTO_ID_5390419480124423570" /&gt;&lt;/a&gt;&lt;br /&gt;I was in the mood for some recursive monitoring, so I fired up a JConsole process and ordered it to monitor itself. I managed to make it show the stack trace of the thread that had the task to show the stack trace of the thread that had the....... you get the idea :)&lt;br /&gt;&lt;br /&gt;&lt;div&gt;For what it worths, here is the stack trace:&lt;/div&gt;&lt;div&gt;&lt;pre&gt;&lt;br /&gt;sun.tools.jconsole.Worker.add(Worker.java:56)&lt;br /&gt;sun.tools.jconsole.Tab.workerAdd(Tab.java:73)&lt;br /&gt;  - locked sun.tools.jconsole.ThreadTab@c829e3&lt;br /&gt;sun.tools.jconsole.ThreadTab.valueChanged(ThreadTab.java:316)&lt;br /&gt;javax.swing.JList.fireSelectionValueChanged(JList.java:1765)&lt;br /&gt;javax.swing.JList$ListSelectionHandler.valueChanged(JList.java:1779)&lt;br /&gt;javax.swing.DefaultListSelectionModel.fireValueChanged(DefaultListSelectionModel.java:167)&lt;br /&gt;javax.swing.DefaultListSelectionModel.fireValueChanged(DefaultListSelectionModel.java:137)&lt;br /&gt;javax.swing.DefaultListSelectionModel.setValueIsAdjusting(DefaultListSelectionModel.java:668)&lt;br /&gt;javax.swing.JList.setValueIsAdjusting(JList.java:2110)&lt;br /&gt;javax.swing.plaf.basic.BasicListUI$Handler.mouseReleased(BasicListUI.java:2788)&lt;br /&gt;java.awt.AWTEventMulticaster.mouseReleased(AWTEventMulticaster.java:273)&lt;br /&gt;java.awt.Component.processMouseEvent(Component.java:6263)&lt;br /&gt;javax.swing.JComponent.processMouseEvent(JComponent.java:3267)&lt;br /&gt;java.awt.Component.processEvent(Component.java:6028)&lt;br /&gt;&lt;/pre&gt;&lt;pre&gt;I'm monitoring a process that should take about 2 hours, so yes, I do have a lot of time in my hands :)&lt;/pre&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6958126065976802292-4181973929443854359?l=code-o-matic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://code-o-matic.blogspot.com/feeds/4181973929443854359/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://code-o-matic.blogspot.com/2009/10/using-jconsole-to-monitorjconsole.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6958126065976802292/posts/default/4181973929443854359'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6958126065976802292/posts/default/4181973929443854359'/><link rel='alternate' type='text/html' href='http://code-o-matic.blogspot.com/2009/10/using-jconsole-to-monitorjconsole.html' title='Using JConsole to monitor...JConsole'/><author><name>Dimitris Andreou</name><uri>https://profiles.google.com/116229150468867889128</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-l6gGcDEXxqI/AAAAAAAAAAI/AAAAAAAABq0/x5Wy-h5G81Y/s512-c/photo.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_H1UVegJ_stI/Ss6d9R8pfZI/AAAAAAAAABE/s5zpK-s0wkw/s72-c/jconsole.JPG' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6958126065976802292.post-5255617788070569423</id><published>2009-09-18T14:29:00.000-07:00</published><updated>2009-09-18T14:41:31.306-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='rapidshare infinite compression md5'/><title type='text'>Rapidshare can compress any file to just 16 bytes!!!</title><content type='html'>Or so it &lt;a href="http://rapidshare.com/privacypolicy.html"&gt;claims&lt;/a&gt;:&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"   style="  ;font-family:arial, sans-serif;font-size:13px;"&gt;&lt;blockquote&gt;there is a program which calculates the MD5 checksum for each file immediately after the upload. &lt;b&gt;The MD5 checksum is a 16 bytes value&lt;/b&gt; which is alsways the same when calculated for the same file. This value is stored in connection with the file. If you upload and distribute an illegal file, we will &lt;b&gt;delete the file&lt;/b&gt; upon notification and &lt;b&gt;a&lt;/b&gt;&lt;b&gt;dd the MD5 checksum to a blacklist&lt;/b&gt;&lt;b&gt;, so the same file cannot be uploaded again&lt;/b&gt;.&lt;/blockquote&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"   style="font-family:arial, sans-serif;font-size:100%;"&gt;&lt;span class="Apple-style-span"  style="font-size:13px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"   style="font-family:arial, sans-serif;font-size:100%;"&gt;&lt;span class="Apple-style-span"  style="font-size:13px;"&gt;(Emphasis mine).&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"   style="font-family:arial, sans-serif;font-size:100%;"&gt;&lt;span class="Apple-style-span"  style="font-size:13px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"   style="font-family:arial, sans-serif;font-size:100%;"&gt;&lt;span class="Apple-style-span"  style="font-size:13px;"&gt;Now, I really, really, &lt;i&gt;really&lt;/i&gt; want to see their blacklist implementation, since obviously it holds the key to the dark art of &lt;span class="Apple-style-span" style="font-style: italic; "&gt;infinite compression, &lt;span class="Apple-style-span" style="font-style: normal;"&gt;which is&lt;/span&gt;&lt;span class="Apple-style-span" style="font-style: normal; "&gt; the Holy Grail Of Computer Science, the Universe, and Everything. Yes, the notorious Holy Grail that nobody wants to touch because &lt;a href="http://matt.might.net/articles/why-infinite-or-guaranteed-file-compression-is-impossible/"&gt;apparently it's the favorite pooping place&lt;/a&gt; for some very special pigeons...&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6958126065976802292-5255617788070569423?l=code-o-matic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://code-o-matic.blogspot.com/feeds/5255617788070569423/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://code-o-matic.blogspot.com/2009/09/rapidshare-can-compress-any-file-to.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6958126065976802292/posts/default/5255617788070569423'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6958126065976802292/posts/default/5255617788070569423'/><link rel='alternate' type='text/html' href='http://code-o-matic.blogspot.com/2009/09/rapidshare-can-compress-any-file-to.html' title='Rapidshare can compress any file to just 16 bytes!!!'/><author><name>Dimitris Andreou</name><uri>https://profiles.google.com/116229150468867889128</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-l6gGcDEXxqI/AAAAAAAAAAI/AAAAAAAABq0/x5Wy-h5G81Y/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6958126065976802292.post-8191706481313007573</id><published>2009-09-14T12:35:00.000-07:00</published><updated>2009-10-04T09:36:00.365-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='JComboBox'/><title type='text'>JComboBox pure craziness</title><content type='html'>Someone asked me why his ItemListener, attached to a JComboBox, was getting &lt;b&gt;two&lt;/b&gt; events when he selected something on it. Weird.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"&gt;I looked up JComboBox' javadocs, just to be sured, and....&lt;/span&gt;&lt;a href="http://java.sun.com/j2se/1.5.0/docs/api/javax/swing/JComboBox.html#addItemListener(java.awt.event.ItemListener)"&gt;this is what I found&lt;/a&gt;&lt;span class="Apple-style-span"&gt;:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style=" ;font-family:'times new roman';"&gt;&lt;/span&gt;&lt;/div&gt;&lt;blockquote&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style=" ;font-family:'times new roman';"&gt;Adds an &lt;code&gt;ItemListener&lt;/code&gt;.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style=" ;font-family:'times new roman';"&gt;&lt;p&gt;&lt;code&gt;aListener&lt;/code&gt; will receive one &lt;b&gt;or two&lt;/b&gt; &lt;code&gt;ItemEvent&lt;/code&gt;s when the selected item changes.&lt;/p&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/blockquote&gt;&lt;div&gt;I understand Swing is a huge framework and it has its rough edges...but this? It certainly looks like someone couldn't fix this strange behavior, and desided to make it a documented &lt;i&gt;feature&lt;/i&gt; instead. Way to go!&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style=" ;font-family:'times new roman';"&gt;&lt;p&gt;&lt;/p&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6958126065976802292-8191706481313007573?l=code-o-matic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://code-o-matic.blogspot.com/feeds/8191706481313007573/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://code-o-matic.blogspot.com/2009/09/jcombobox-pure-craziness.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6958126065976802292/posts/default/8191706481313007573'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6958126065976802292/posts/default/8191706481313007573'/><link rel='alternate' type='text/html' href='http://code-o-matic.blogspot.com/2009/09/jcombobox-pure-craziness.html' title='JComboBox pure craziness'/><author><name>Dimitris Andreou</name><uri>https://profiles.google.com/116229150468867889128</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-l6gGcDEXxqI/AAAAAAAAAAI/AAAAAAAABq0/x5Wy-h5G81Y/s512-c/photo.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6958126065976802292.post-625707788678081025</id><published>2009-09-03T05:11:00.000-07:00</published><updated>2009-09-03T05:16:28.816-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='dead code ocean'/><title type='text'>Where does dead code go to?</title><content type='html'>Have you ever wondered what happens to a piece of code you delete? I like to imagine that, after many years, it ends up somewhere around here:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://en.wikipedia.org/wiki/Great_Pacific_Garbage_Patch"&gt;http://en.wikipedia.org/wiki/Great_Pacific_Garbage_Patch&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;div&gt;Floating in the middle of the ocean for ever. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;What is &lt;i&gt;your&lt;/i&gt; theory about the after-life of dead code? Or you would be the skeptic that would argue that there is only cold nothingness for code that didn't make it into the eternal haven of a repository?&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6958126065976802292-625707788678081025?l=code-o-matic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://code-o-matic.blogspot.com/feeds/625707788678081025/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://code-o-matic.blogspot.com/2009/09/where-does-dead-code-go-to.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6958126065976802292/posts/default/625707788678081025'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6958126065976802292/posts/default/625707788678081025'/><link rel='alternate' type='text/html' href='http://code-o-matic.blogspot.com/2009/09/where-does-dead-code-go-to.html' title='Where does dead code go to?'/><author><name>Dimitris Andreou</name><uri>https://profiles.google.com/116229150468867889128</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-l6gGcDEXxqI/AAAAAAAAAAI/AAAAAAAABq0/x5Wy-h5G81Y/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6958126065976802292.post-9158338834418149924</id><published>2009-07-29T17:35:00.000-07:00</published><updated>2009-10-23T02:11:47.903-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='enumerate directed acyclic graphs'/><title type='text'>The best way to enumerated directed acyclic graphs</title><content type='html'>&lt;div style="text-align: center;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_H1UVegJ_stI/SnavV440eoI/AAAAAAAAAA8/EpqG9UWnoeo/s1600-h/numbered_matrix.PNG"&gt;&lt;/a&gt;&lt;div style="text-align: center;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_H1UVegJ_stI/SnDnyIn3LjI/AAAAAAAAAA0/Aruav3DzKIM/s1600-h/matrix.png"&gt;&lt;/a&gt;&lt;div&gt;Here is a tricky problem for the algorithmically oriented people to ponder about: "enumerate all directed acyclic graphs (DAGs) of a given size &lt;i&gt;n&lt;/i&gt;".&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I'll describe the process I followed in tackling this problem (the result is rather fascinating), but if you find this challenging enough, it would be good to stop reading for a while and see if you can solve it (hopefully in a good way).&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;First, some background. "Are you nuts? Enumerating &lt;i&gt;graphs&lt;/i&gt;? You'll get huge numbers of them almost immediately!". Well, true. For example, &lt;a href="http://www.research.att.com/%7Enjas/sequences/A000088"&gt;here is the arithmetic sequence&lt;/a&gt; that shows just how many distinct (non-isomorphic) general graphs there are. It gets out of hand really quickly. Well, some background. I'm trying to develop an algorithm that takes as input a DAG, but it's quite hard to analyze and/or compare it with existing algorithms. So I'm interested in exhausting all possible inputs up to a certain size and count the logical steps of the algorithm for each problem instance, which can offer me useful feedback on the algorithm design, or show me which graphs produce the worst behavior of the algorithm, for which graphs the algorithm performs better than other algorithms, and so on.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Now, on to business. Upon some research, it seems there is no known sequence defining the number of unique DAGs per node count out there. The closest I found is the number of &lt;a href="http://www.research.att.com/%7Enjas/sequences/A000112"&gt;partially ordered sets&lt;/a&gt;.  A partially ordered set is also a DAG, with the further restriction that its &lt;a href="http://en.wikipedia.org/wiki/Transitive_reduction"&gt;transitive reduction&lt;/a&gt; is &lt;b&gt;itself &lt;/b&gt;(i.e. no redundant edges exist). Since there are many DAGs which yield the same transitively reduced DAG, it is obvious that this sequence is a strictly lower bound on the number of DAGs.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;My first approach was rather brave, but futile nevertheless. I started about defining the sole graph of size 1 (no self loops), which is just a node. Then iteratively I increased the size &lt;b&gt;&lt;i&gt;N&lt;/i&gt; &lt;/b&gt;of generated graphs. At the iteration, the &lt;b&gt;&lt;i&gt;N&lt;/i&gt;&lt;/b&gt;&lt;i&gt;th&lt;/i&gt; node of the graphs is created and combined with all graphs of size &lt;b&gt;N-1&lt;/b&gt; in every possible way. How many ways are there? We are only allowed to connect the new node &lt;b&gt;to&lt;/b&gt; the older nodes (not the other way around), so we only generated DAGs, so there are &lt;b&gt;N-1&lt;/b&gt; possible edges to add. The power set of this is &lt;b&gt;2^(N-1)&lt;/b&gt;, and this is every possible way that a given graph with &lt;b&gt;N-1&lt;/b&gt; size can be extended with a new node.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;This produced DAGs of count 2^0 (1 node), 2^1 (2 nodes)&lt;/div&gt;&lt;div&gt;&lt;ul&gt;&lt;li&gt;&lt;b&gt;2^0 = 1&lt;/b&gt;(one node)&lt;/li&gt;&lt;li&gt;&lt;b&gt;2^1 = 2 &lt;/b&gt;(two nodes)&lt;/li&gt;&lt;li&gt;&lt;b&gt;2^3 = 8&lt;/b&gt; (three nodes)&lt;/li&gt;&lt;li&gt;&lt;b&gt;2^6 = 64&lt;/b&gt; (four nodes)&lt;/li&gt;&lt;li&gt;&lt;b&gt;2^10 = 1024&lt;/b&gt; (five nodes)&lt;/li&gt;&lt;li&gt;&lt;b&gt;2^15 = 32768&lt;/b&gt; (six nodes)&lt;/li&gt;&lt;li&gt;&lt;b&gt;2^21 = 2097152&lt;/b&gt; ( seven nodes)&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div&gt;The next milestone was 2^28 (268435456) graphs, but I ran out of memory. :) But storing more than two million graphs of 7 nodes and up to 21 nodes is a formidable task. I managed to pack all those graphs in about 120mb of RAM, meaning less than &lt;b&gt;60 bytes for each graph, &lt;/b&gt;which for a adjacency lists implementation, is pretty impressive. (But adjacency matrix where each possible edge represented as single bits would be the most economical representation). This is possible because each graph of size &lt;b&gt;N&lt;/b&gt; shared the &lt;b&gt;N-1&lt;/b&gt; nodes of it, along with their adjacency lists, with the previous graph of size &lt;b&gt;N-1&lt;/b&gt; that it extended, so the cost of each graph is more or less the cost of the final node and its list.  (This is the kind of stuff where &lt;a href="http://en.wikipedia.org/wiki/Persistent_data_structure"&gt;persistent data structures&lt;/a&gt; really excel, but in Javaland the reusable implementations are few and far between - did I mention yet you should check out &lt;a href="http://www.scala-lang.org/"&gt;Scala&lt;/a&gt;?)&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Then, I talked with &lt;a href="http://www.cs.bath.ac.uk/%7Emjb/"&gt;Martin&lt;/a&gt;, a collegue/Phd student at the Univ. of Bath, who mostly works on NP-hard problems, and apart from a long discussion on "why one earth &lt;i&gt;do&lt;/i&gt; you want to have a freak of nature like this one???" and other related sub-discussions, he suggested enumerating &lt;i&gt;all undirected general &lt;/i&gt;&lt;i&gt;graphs&lt;/i&gt; (not directed, not acyclic: this is what is offered) by &lt;a href="http://cs.anu.edu.au/%7Ebdm/nauty/"&gt;nauty&lt;/a&gt;, and then produce all DAGs from each graph. Quite a huge amount of work: 2^(n(n-1)) number of graphs, multiplied by the number of DAGs created from each (which can be up to 2^(n-1)(n-2) / 2). But most importantly, he mentioned that nauty enumerates the graphs without having to store the smaller ones, which made me challenge my approach of generating the DAGs.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;From there, it only took few seconds to bump on the correct solution, which is very simple. See the following table:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="color: rgb(0, 0, 238);"&gt;&lt;img src="http://2.bp.blogspot.com/_H1UVegJ_stI/SnDnyIn3LjI/AAAAAAAAAA0/Aruav3DzKIM/s320/matrix.png" alt="" id="BLOGGER_PHOTO_ID_5364042004692414002" style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 320px; height: 294px;" border="0" /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;This table is meant to be a graph's adjacency matrix. The rows, as well as the columns, represent the graph's nodes. Each cell can be &lt;b&gt;0&lt;/b&gt; or &lt;b&gt;1&lt;/b&gt;, to denote if there is a node from the row-node to the column-node, respectively. Note that the nodes of the matrix are actually in topological order (which &lt;span style="font-weight: bold;"&gt;is&lt;/span&gt; defined in DAGs) - a node/row is only allowed to connect to nodes after/up of it, not before/down of it - thus this matrix, the gray area are edges that if were allowed, they would violate the defined topological order.  Only the white cells can contain 1, but the can also contain 0 of course. So what do we have here? For a DAG of &lt;b&gt;n&lt;/b&gt; nodes, we have this nxn matrix, and (n-1)(n-2)/2 cells which can independently vary between 0 or 1. The solution from here is easy: &lt;b&gt;Just arrange these cells as bits in a bit string, i.e. a binary number, start with zero, and increment it by one at each step, till the number consists of only 1's.&lt;/b&gt; Constant storage space, just a number of (n-1)(n-2)/2 bits! And a trivial way to enumerate the dags, transform the enumeration problem to the problem of...adding 1 to a binary number. All it takes is decoding the number into the respective DAG. Isn't this elegant? :)&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;To sum up, this procedure creates 2^((n-1)(n-2) / 2) DAGs, in equal number of iterations. Which in contrary to the suggested method, has half the exponent, i.e. for n = 10, the last method would yield 2^45 steps/DAGs, while using nauty would create 2^90 &lt;b&gt;general &lt;/b&gt;graphs, where each graph would be subsequently transformed to many, many DAGs.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;Addendum: &lt;/b&gt;The above description leaves a tricky part uncommented. We saw how to generate all DAGs with &lt;i&gt;n &lt;/i&gt;nodes, i.e. :&lt;br /&gt;&lt;br /&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;int currentGraph = 1 &lt;&lt; (n - 1) * (n - 2) / 2 ;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;while (currentGraph &gt;= 0) {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;  currentGraph--; //represents a DAG!&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;But how to interpret these numbers as graphs? We have to be able to answer, for all graphs, whether there is an edge (i --&gt; j), i.e. connecting node &lt;i&gt;i&lt;/i&gt;&lt;i&gt; &lt;/i&gt;to node &lt;i&gt;j&lt;/i&gt;. Here is the implementation of this test, by &lt;a href="http://www.csd.uoc.gr/%7Evuzukid/"&gt;Nelly Vouzoukidou&lt;/a&gt;, a graduate cs student at Univ. of Crete:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;boolean hasEdge(int graph, int i, int j) {&lt;br /&gt;  return i &gt; j &amp;&amp; isSet(graph, i * (i - 1)  / 2 + j)&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;//just checks whether a given bit of a number is set&lt;br /&gt;boolean isSet(int number, int bit) {&lt;br /&gt;  return number &amp; (1 &amp;lt;&amp;lt; bit) &amp; number != 0;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;div&gt;You can see the second picture to understand the bits layout that this formula represents. There is a nice geometric interpretation of it too: "i * (i - 1) / 2" is the surface of the triangle above the selected row. To that, we add "j" to go to the desired cell, since at every row, each cell represents the next bit of its left cell.&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="color: rgb(0, 0, 238);font-family:Georgia;" &gt;&lt;img src="http://4.bp.blogspot.com/_H1UVegJ_stI/SnavV440eoI/AAAAAAAAAA8/EpqG9UWnoeo/s320/numbered_matrix.PNG" alt="" id="BLOGGER_PHOTO_ID_5365668796641344130" style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 320px; height: 294px;" border="0" /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;If you found this interesting, you might want to check out &lt;a href="http://code-o-matic.blogspot.com/2009/04/wonderful-programming-exercise.html"&gt;an older post about enumerating all binary trees&lt;/a&gt;, where also an amusing solution is produced.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6958126065976802292-9158338834418149924?l=code-o-matic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://code-o-matic.blogspot.com/feeds/9158338834418149924/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://code-o-matic.blogspot.com/2009/07/best-way-to-enumerated-directed-acyclic.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6958126065976802292/posts/default/9158338834418149924'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6958126065976802292/posts/default/9158338834418149924'/><link rel='alternate' type='text/html' href='http://code-o-matic.blogspot.com/2009/07/best-way-to-enumerated-directed-acyclic.html' title='The best way to enumerated directed acyclic graphs'/><author><name>Dimitris Andreou</name><uri>https://profiles.google.com/116229150468867889128</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-l6gGcDEXxqI/AAAAAAAAAAI/AAAAAAAABq0/x5Wy-h5G81Y/s512-c/photo.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_H1UVegJ_stI/SnDnyIn3LjI/AAAAAAAAAA0/Aruav3DzKIM/s72-c/matrix.png' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6958126065976802292.post-6249954668975375547</id><published>2009-07-06T13:56:00.001-07:00</published><updated>2009-07-06T14:04:31.656-07:00</updated><title type='text'>This is how real men do garbage collection!</title><content type='html'>I was quite fascinated today seeing the way the famous JDK figure Martin Bucholtz does garbage collection. Anyone believing he takes garbage more seriously than that?&lt;div&gt;&lt;br /&gt;&lt;/div&gt;Enjoy:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;private static final Runtime rt = Runtime.getRuntime();&lt;br /&gt;static void gcTillYouDrop() {&lt;br /&gt;    rt.gc();&lt;br /&gt;    rt.runFinalization();&lt;br /&gt;    final CountDownLatch latch = new CountDownLatch(1);&lt;br /&gt;    new Object() {&lt;br /&gt;      protected void finalize() {&lt;br /&gt;        latch.countDown();&lt;br /&gt;      }&lt;br /&gt;    };&lt;br /&gt;    rt.gc();&lt;br /&gt;    try {&lt;br /&gt;      latch.await();&lt;br /&gt;    }&lt;br /&gt;    catch(InterruptedException ie){&lt;br /&gt;      throw new Error(ie);&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;"Hyper-paranoid" indeed, in the words of &lt;a href="http://smallwig.blogspot.com/"&gt;Kevin&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6958126065976802292-6249954668975375547?l=code-o-matic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://code-o-matic.blogspot.com/feeds/6249954668975375547/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://code-o-matic.blogspot.com/2009/07/this-is-how-real-men-do-garbage.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6958126065976802292/posts/default/6249954668975375547'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6958126065976802292/posts/default/6249954668975375547'/><link rel='alternate' type='text/html' href='http://code-o-matic.blogspot.com/2009/07/this-is-how-real-men-do-garbage.html' title='This is how real men do garbage collection!'/><author><name>Dimitris Andreou</name><uri>https://profiles.google.com/116229150468867889128</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-l6gGcDEXxqI/AAAAAAAAAAI/AAAAAAAABq0/x5Wy-h5G81Y/s512-c/photo.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6958126065976802292.post-5707507985714915839</id><published>2009-06-18T10:26:00.001-07:00</published><updated>2009-06-18T10:29:23.424-07:00</updated><title type='text'>Funniest Java Interface</title><content type='html'>&lt;pre&gt;interface sun.net.www.http.&lt;b&gt;Hurryable&lt;/b&gt; {&lt;br /&gt; boolean &lt;b&gt;hurry&lt;/b&gt;();&lt;br /&gt;}&lt;/pre&gt;&lt;pre&gt;&lt;br /&gt;&lt;/pre&gt;&lt;pre&gt;&lt;b&gt;&lt;span class="Apple-style-span" style="font-size: large;"&gt;:-)&lt;/span&gt;&lt;/b&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6958126065976802292-5707507985714915839?l=code-o-matic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://code-o-matic.blogspot.com/feeds/5707507985714915839/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://code-o-matic.blogspot.com/2009/06/funniest-java-interface.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6958126065976802292/posts/default/5707507985714915839'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6958126065976802292/posts/default/5707507985714915839'/><link rel='alternate' type='text/html' href='http://code-o-matic.blogspot.com/2009/06/funniest-java-interface.html' title='Funniest Java Interface'/><author><name>Dimitris Andreou</name><uri>https://profiles.google.com/116229150468867889128</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-l6gGcDEXxqI/AAAAAAAAAAI/AAAAAAAABq0/x5Wy-h5G81Y/s512-c/photo.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6958126065976802292.post-2489932150481780534</id><published>2009-06-16T03:31:00.000-07:00</published><updated>2009-06-16T03:55:31.489-07:00</updated><title type='text'>Funny ConcurrentModificationException while playing with Google's Multimap</title><content type='html'>(Disclaimer: Google's Multimap surely work fine and as advertised - this post describes a potentially confusing code interaction which can result in unintuitive ConcurrentModificationExceptions)&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;First, lets create a multimap:&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"   style="font-family:-webkit-monospace;font-size:100%;"&gt;&lt;span class="Apple-style-span"  style=" white-space: pre;font-size:13px;"&gt;&lt;span class="Apple-style-span"   style="font-family:Georgia;font-size:130%;"&gt;&lt;span class="Apple-style-span"  style=" white-space: normal;font-size:16px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;pre&gt;Multimap multimap = HashMultimap.create();&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Put somehow some values to it:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;pre&gt;putSomeValues(multimap);&lt;/pre&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Now lets iterate its key set, and potentially filter some elements of each key's collection:&lt;/div&gt;&lt;div&gt;&lt;pre&gt;for (Key key : multimap.keySet()) {&lt;br /&gt;  Collection values = multimap.get(key);&lt;br /&gt;&lt;br /&gt;  ...&lt;br /&gt;  if (something) {&lt;br /&gt;    Value someValue = ...;&lt;br /&gt;    values.remove(someValue);&lt;br /&gt;  }&lt;br /&gt;}&lt;/pre&gt;&lt;/div&gt;&lt;div&gt;(We could iterate its entries() as well, which is supposedly faster, but for now, I won't bother).&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;This seems safe. I iterate the keys, and don't perform any structural modification in the multimap, I might only make a collection inside it shorter.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Well, no. It can blow if "values" becomes empty, since then the multimap will remove the respective entry from the map (this is a very desirable behavior, to be sure), thus structurally modifying the map, thus ConcurrentModificationException when the iterator will try to fetch the next key.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;This may be quite nasty if only rarely the "values" collection goes empty and triggers this behavior, so it's good to know. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;My solution is this:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;pre&gt;Iterator keyIterator = multimap.keySet().iterator();&lt;br /&gt;while (keyIterator.hasNext()) {&lt;br /&gt;Key key = keyIterator.next();&lt;br /&gt;Collection values = multimap.get(key);&lt;br /&gt;&lt;br /&gt;...&lt;br /&gt;if (something) {&lt;br /&gt;  Value someValue = ...;&lt;br /&gt;  if (values.size() == 1 &amp;amp;&amp;amp; values.contains(someValue)) {&lt;br /&gt;    keyIterator.remove();&lt;br /&gt;    continue; //this is not really needed&lt;br /&gt;  }&lt;br /&gt;  values.remove(someValue);&lt;br /&gt;}&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div&gt;Quite simpler would be to simply change this:&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;for (Key key : multimap.keySet()) {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;To this:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;for (Key key : Lists.newArrayList(multimap.keySet())) {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;If you don't mind creating a copy of the entire key set up-front.&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6958126065976802292-2489932150481780534?l=code-o-matic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://code-o-matic.blogspot.com/feeds/2489932150481780534/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://code-o-matic.blogspot.com/2009/06/funny-concurrentmodificationexception.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6958126065976802292/posts/default/2489932150481780534'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6958126065976802292/posts/default/2489932150481780534'/><link rel='alternate' type='text/html' href='http://code-o-matic.blogspot.com/2009/06/funny-concurrentmodificationexception.html' title='Funny ConcurrentModificationException while playing with Google&apos;s Multimap'/><author><name>Dimitris Andreou</name><uri>https://profiles.google.com/116229150468867889128</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-l6gGcDEXxqI/AAAAAAAAAAI/AAAAAAAABq0/x5Wy-h5G81Y/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6958126065976802292.post-865906772202205187</id><published>2009-05-12T03:04:00.001-07:00</published><updated>2009-05-12T03:27:47.691-07:00</updated><title type='text'>Double-checked locking idiom, sweet in Scala!</title><content type='html'>In Java, this is what you have to write when you want a lazily, thread-safe constructed value, which isn't static (otherwise you would use &lt;span class="Apple-style-span" style="font-family: 'times new roman'; "&gt;&lt;a href="http://en.wikipedia.org/wiki/Initialization_on_demand_holder_idiom"&gt;Initialization On Demand Holder&lt;/a&gt; idiom).&lt;/span&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'times new roman';"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'courier new';"&gt;private volatile Object field;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'courier new';"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'courier new';"&gt;public Object get() {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'courier new';"&gt;  Object o = field;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'courier new';"&gt;  if (o == null) {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'courier new';"&gt;    synchronize(this) {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'courier new';"&gt;       o = field = create();&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'courier new';"&gt;    }&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'courier new';"&gt;  }&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'courier new';"&gt;  return o;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'courier new';"&gt;}&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'courier new';"&gt;private Object create() { ... }&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'courier new';"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'courier new';"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'courier new';"&gt;Over, and over again, as many times as you need it. Or you could make a light abstraction over it, like this:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'courier new';"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'courier new';"&gt;public class LazyHolder&lt;t&gt; {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'courier new';"&gt;  private volatile T field;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'courier new';"&gt;  &lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'courier new';"&gt;  public T get() {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'courier new';"&gt;    T o = field;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'courier new';"&gt;    if (o == null) {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'courier new';"&gt;      synchronize(this) {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'courier new';"&gt;         o = field = create();&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'courier new';"&gt;      }&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'courier new';"&gt;    }&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'courier new';"&gt;    return o;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'courier new';"&gt;  }&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'courier new';"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'courier new';"&gt;  protected abstract T create();&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'courier new';"&gt;}&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'courier new';"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'courier new';"&gt;So the user would have to do this:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'courier new';"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'courier new';"&gt;private final LazyHolder&lt;t&gt; holder = new LazyHolder&lt;t&gt;() {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'courier new';"&gt;  protected T create() { ... }&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'courier new';"&gt;};&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'courier new';"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'courier new';"&gt;A very tiny caveat here (in both versions): if your computation happens to return null, the computation will be repeated the next time, since we used null as an indicator of missing initialization.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'courier new';"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'courier new';"&gt;Enough about Java. How would you go about doing this in Scala?&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'courier new';"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'courier new';"&gt;Turns out, it is supported directly by the compiler, so you only have to write this:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'courier new';"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'courier new';"&gt;&lt;span class="Apple-style-span" style="font-weight: bold;"&gt;lazy val myLazyField = create();&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'courier new';"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'courier new';"&gt;&lt;span class="Apple-style-span" style="font-style: italic;"&gt;This is all it takes&lt;/span&gt;! It's thread-safe, it's computed only the first time if it's needed, and amazingly easy.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'courier new';"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'courier new';"&gt;This is translated to a variant of the double-checked locking idiom. I decompiled a lazy val declaration and this is what I got:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'courier new';"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'courier new';"&gt;&lt;div&gt;   public volatile int bitmap$0;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;   private Object myLazyField;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;   public String myLazyField() {&lt;/div&gt;&lt;div&gt;        if((bitmap$0 &amp;amp; 1) == 0)&lt;/div&gt;&lt;div&gt;        {&lt;/div&gt;&lt;div&gt;            synchronized(this)&lt;/div&gt;&lt;div&gt;            {&lt;/div&gt;&lt;div&gt;                if((bitmap$0 &amp;amp; 1) == 0)&lt;/div&gt;&lt;div&gt;                {&lt;/div&gt;&lt;div&gt;                    myLazyField = ...&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space:pre"&gt;  &lt;/span&gt;    bitmap$0 = bitmap$0 | 1;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;                }&lt;/div&gt;&lt;div&gt;            }&lt;br /&gt;&lt;/div&gt;&lt;div&gt;        }&lt;/div&gt;&lt;div&gt;        return myLazyField;&lt;/div&gt;&lt;div&gt;    }&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Note the bitmap field, which can support the lazy initialization of up to 32 fields (even if some are initialized merely to null).&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Nice and easy!&lt;/div&gt;&lt;/div&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6958126065976802292-865906772202205187?l=code-o-matic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://code-o-matic.blogspot.com/feeds/865906772202205187/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://code-o-matic.blogspot.com/2009/05/double-checked-locking-idiom-sweet-in.html#comment-form' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6958126065976802292/posts/default/865906772202205187'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6958126065976802292/posts/default/865906772202205187'/><link rel='alternate' type='text/html' href='http://code-o-matic.blogspot.com/2009/05/double-checked-locking-idiom-sweet-in.html' title='Double-checked locking idiom, sweet in Scala!'/><author><name>Dimitris Andreou</name><uri>https://profiles.google.com/116229150468867889128</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-l6gGcDEXxqI/AAAAAAAAAAI/AAAAAAAABq0/x5Wy-h5G81Y/s512-c/photo.jpg'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6958126065976802292.post-7628260451124990079</id><published>2009-04-14T12:53:00.000-07:00</published><updated>2009-04-15T06:10:45.994-07:00</updated><title type='text'>A Wonderful Programming Exercise</title><content type='html'>&lt;blockquote&gt;&lt;/blockquote&gt;&lt;span class="Apple-style-span"  style=" ;font-family:'Times New Roman';"&gt;&lt;div style="border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 3px; padding-right: 3px; padding-bottom: 3px; padding-left: 3px; width: auto; font: normal normal normal 100%/normal Georgia, serif; text-align: left; "&gt;Yesterday, while reading the famous and excellent &lt;a href="http://www.amazon.com/Introduction-Algorithms-Thomas-H-Cormen/dp/0262032937"&gt;Introduction to Algorithms&lt;/a&gt; ("CLRS") book, I bumped on a seemingly innocuous problem on Appendix B (page 1092). The problem statement reads:&lt;/div&gt;&lt;div style="border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 3px; padding-right: 3px; padding-bottom: 3px; padding-left: 3px; width: auto; font: normal normal normal 100%/normal Georgia, serif; text-align: left; "&gt;&lt;div style="border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 3px; padding-right: 3px; padding-bottom: 3px; padding-left: 3px; width: auto; font: normal normal normal 100%/normal Georgia, serif; text-align: left; "&gt;&lt;blockquote&gt;&lt;div style="border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 3px; padding-right: 3px; padding-bottom: 3px; padding-left: 3px; width: auto; font: normal normal normal 100%/normal Georgia, serif; text-align: left; "&gt;Show that by removing a single edge, we can partition the vertices of any n-vertex&lt;/div&gt;&lt;div style="border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 3px; padding-right: 3px; padding-bottom: 3px; padding-left: 3px; width: auto; font: normal normal normal 100%/normal Georgia, serif; text-align: left; "&gt;binary tree into two sets A and B such that |A| &lt;= 3n/4 and |B| &lt;= 3n/4.&lt;/div&gt;&lt;/blockquote&gt;&lt;div style="border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 3px; padding-right: 3px; padding-bottom: 3px; padding-left: 3px; width: auto; font: normal normal normal 100%/normal Georgia, serif; text-align: left; "&gt;My first reaction was, "wow". If you are like me, you tend to consider binary trees as something very, very basic. Something a computer-science student gets to learn and love by second semester, and then move on to more fancy and complex stuff. Yet, this is the first time I came across to this very peculiar property of binary trees (even in the form of an exercise), which states that "you can always split any binary tree by removing some edge and have both components less or equal to 3/4 of the initial size, and equivalently greater or equal to 1/2 of the initial size". Why nature specially picked 3/4 and 1/4? I don't know.  (You may google it, I did, and didn't find the answer/proof).&lt;/div&gt;&lt;div style="border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 3px; padding-right: 3px; padding-bottom: 3px; padding-left: 3px; width: auto; font: normal normal normal 100%/normal Georgia, serif; text-align: left; "&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 3px; padding-right: 3px; padding-bottom: 3px; padding-left: 3px; width: auto; font: normal normal normal 100%/normal Georgia, serif; text-align: left; "&gt;Here is a simple image of a binary tree, courtesy of Wikipedia: &lt;img src="http://upload.wikimedia.org/wikipedia/commons/f/f7/Binary_tree.svg" alt="A binary tree picture"&gt;&lt;/div&gt;&lt;div style="border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 3px; padding-right: 3px; padding-bottom: 3px; padding-left: 3px; width: auto; font: normal normal normal 100%/normal Georgia, serif; text-align: left; "&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 3px; padding-right: 3px; padding-bottom: 3px; padding-left: 3px; width: auto; font: normal normal normal 100%/normal Georgia, serif; text-align: left; "&gt;Anyway, on to the point. My problem was that I couldn't even find a binary tree which I could not cut more evenly than 3/4 and 1/4 (because, the exercise implies that there &lt;span class="Apple-style-span" style="font-weight: bold;"&gt;are &lt;/span&gt;some binary trees that you cannot reduce the greater split component any less than 3/4). So how am I supposed to build some basic intuition to be guided to a formal proof? I didn't fancy drawing and redrawing lots of trees, trying to find the "right" example. So, being a programmer, that's where I thought I could use some help from the computer in front of me: why not let the computer find the example and show it to me?&lt;/div&gt;&lt;div style="border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 3px; padding-right: 3px; padding-bottom: 3px; padding-left: 3px; width: auto; font: normal normal normal 100%/normal Georgia, serif; text-align: left; "&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 3px; padding-right: 3px; padding-bottom: 3px; padding-left: 3px; width: auto; font: normal normal normal 100%/normal Georgia, serif; text-align: left; "&gt;So this was my new problem statement: &lt;span class="Apple-style-span" style="font-weight: bold;"&gt;enumerate *all* binary trees of a given size N&lt;/span&gt;. How about trying this problem yourself and leaving a comment with your solution? (I would be quite interested in a nice solution in Scala by the way).&lt;/div&gt;&lt;div style="border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 3px; padding-right: 3px; padding-bottom: 3px; padding-left: 3px; width: auto; font: normal normal normal 100%/normal Georgia, serif; text-align: left; "&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 3px; padding-right: 3px; padding-bottom: 3px; padding-left: 3px; width: auto; font: normal normal normal 100%/normal Georgia, serif; text-align: left; "&gt;Assuming you now go to your favorite editor and see if you can hack this, let me describe here what happened on my side. My first attempt was ugly. Real ugly. I felt bad doing it, even bad about myself as a programmer. "A real programmer would be able to hack through it in few minutes". Well, mine was ugly, and I didn't even finish it, perhaps it couldn't work that way at all. For history, I tried building all trees in a top-down fashion (by the way, some months ago I was curious about "how many binary trees are there with a given size", and did that top-down approach to find out how many, but that was a simpler problem, and I ended up rediscovering the &lt;a href="http://en.wikipedia.org/wiki/Catalan_number"&gt;Catalan numbers&lt;/a&gt;).&lt;/div&gt;&lt;div style="border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 3px; padding-right: 3px; padding-bottom: 3px; padding-left: 3px; width: auto; font: normal normal normal 100%/normal Georgia, serif; text-align: left; "&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 3px; padding-right: 3px; padding-bottom: 3px; padding-left: 3px; width: auto; font: normal normal normal 100%/normal Georgia, serif; text-align: left; "&gt;I gave up, did not bother with it for another few hours, and then it hit me: why not build the trees bottom-up? In a dynamic programming fashion. Knowing &lt;span class="Apple-style-span" style="font-weight: bold;"&gt;all&lt;/span&gt; trees of size (N-1), one can pretty easily find the trees with size N. &lt;/div&gt;&lt;div style="border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 3px; padding-right: 3px; padding-bottom: 3px; padding-left: 3px; width: auto; font: normal normal normal 100%/normal Georgia, serif; text-align: left; "&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 3px; padding-right: 3px; padding-bottom: 3px; padding-left: 3px; width: auto; font: normal normal normal 100%/normal Georgia, serif; text-align: left; "&gt;&lt;br /&gt;&lt;br /&gt;Enough description, lets have some code:&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="java"&gt;&lt;br /&gt;public class Main {&lt;br /&gt;public static void main(String[] args) {&lt;br /&gt;    int count = 0;&lt;br /&gt;&lt;br /&gt;    for (Node tree : TreeEnumerator.findTrees(5)) {&lt;br /&gt;        System.out.println(tree);&lt;br /&gt;        count++;&lt;br /&gt;    }&lt;br /&gt;    System.out.println(count);&lt;br /&gt;}&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;class TreeEnumerator {&lt;br /&gt;public static Collection&amp;lt;Node&amp;gt; findTrees(int n) {&lt;br /&gt;    List&amp;lt;Collection&amp;lt;Node&amp;gt;&amp;gt; knownTrees = new ArrayList&amp;lt;Collection&amp;lt;Node&amp;gt;&amp;gt;(n);&lt;br /&gt;    knownTrees.add(Collections.&amp;lt;Node&amp;gt;singleton(Nil.instance));&lt;br /&gt;    knownTrees.add(Collections.&amp;lt;Node&amp;gt;singleton(new InternalNode(Nil.instance, Nil.instance)));&lt;br /&gt;    for (int i = 2; i &amp;lt;= n; i++) {&lt;br /&gt;        final int kids = i - 1;&lt;br /&gt;        Collection&amp;lt;Node&amp;gt; trees = new LinkedList&amp;lt;Node&amp;gt;();&lt;br /&gt;        for (int leftKids = kids; leftKids &amp;gt;= 0; leftKids--) {&lt;br /&gt;            int rightKids = kids - leftKids;&lt;br /&gt;            Collection&amp;lt;Node&amp;gt; leftTrees = knownTrees.get(leftKids);&lt;br /&gt;            Collection&amp;lt;Node&amp;gt; rightTrees = knownTrees.get(rightKids);&lt;br /&gt;            for (Node left : leftTrees) {&lt;br /&gt;                for (Node right : rightTrees) {&lt;br /&gt;                    trees.add(new InternalNode(left, right));&lt;br /&gt;                }&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;        knownTrees.add(trees);&lt;br /&gt;    }&lt;br /&gt;    return knownTrees.get(n);&lt;br /&gt;}&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;interface Node {&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;class Nil implements Node {&lt;br /&gt;static final Nil instance = new Nil();&lt;br /&gt;&lt;br /&gt;private Nil() { }&lt;br /&gt;&lt;br /&gt;@Override&lt;br /&gt;public String toString() {&lt;br /&gt;    return ".";&lt;br /&gt;}&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;class InternalNode implements Node {&lt;br /&gt;final Node left, right;&lt;br /&gt;&lt;br /&gt;InternalNode(Node left, Node right) {&lt;br /&gt;    this.left = left;&lt;br /&gt;    this.right = right;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;@Override&lt;br /&gt;public String toString() {&lt;br /&gt;    return "(" + left + right + ")";&lt;br /&gt;}&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div style="border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 3px; padding-right: 3px; padding-bottom: 3px; padding-left: 3px; width: auto; font: normal normal normal 100%/normal Georgia, serif; text-align: left; "&gt;I was very, very happy with the end result and the easiness that new trees are generated, always reusing some existing lower-rank tree. I suppose one might only appreciate this if he had already tried and realized how easily a "simple" problem, thought just a little bit wrongly, may end up in something so complicated and unmanageable - then one really appreciates simplicity! This algorithm is very efficient (probably optimal), and only creates as many nodes as trees (of size N or less), no more. Also noteworthy is that no tree copying takes place anywhere, only tree &lt;span class="Apple-style-span" style="font-style: italic;"&gt;sharing&lt;/span&gt;. (This is facilitated by the fact that nodes do &lt;span class="Apple-style-span" style="font-weight: bold;"&gt;not&lt;/span&gt; ren eference their parents).&lt;/div&gt;&lt;div style="border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 3px; padding-right: 3px; padding-bottom: 3px; padding-left: 3px; width: auto; font: normal normal normal 100%/normal Georgia, serif; text-align: left; "&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 3px; padding-right: 3px; padding-bottom: 3px; padding-left: 3px; width: auto; font: normal normal normal 100%/normal Georgia, serif; text-align: left; "&gt;All this is nice, but this is not the complete solution. We still have to find &lt;span class="Apple-style-span" style="font-weight: bold;"&gt;which&lt;/span&gt; tree of those cannot be broken more evenly than 1/4 and 3/4. An obvious approach is to take every tree, and break it in every place possible, and keep the most even cut of those, and check whether it is 3/4. But then, how would one actually &lt;span class="Apple-style-span" style="font-weight: bold;"&gt;cut&lt;/span&gt; the trees? Nulling references in nodes? But that would destroy all other trees sharing those nodes! Node copying? It would seem that we should after all fall back to copying every tree, then try all breaks, so the original trees are kept intact.&lt;/div&gt;&lt;div style="border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 3px; padding-right: 3px; padding-bottom: 3px; padding-left: 3px; width: auto; font: normal normal normal 100%/normal Georgia, serif; text-align: left; "&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 3px; padding-right: 3px; padding-bottom: 3px; padding-left: 3px; width: auto; font: normal normal normal 100%/normal Georgia, serif; text-align: left; "&gt;Since this gets quite a big post, I'm not going to show the code of my solution, just sketch it. It is just a simple neat trick really. You don't have to actually &lt;span class="Apple-style-span" style="font-style: italic;"&gt;break&lt;/span&gt; the tree! Just define a recursive "int count()" method on Node, and for every tree, do a couple of actions:&lt;/div&gt;&lt;div style="border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 3px; padding-right: 3px; padding-bottom: 3px; padding-left: 3px; width: auto; font: normal normal normal 100%/normal Georgia, serif; text-align: left; "&gt;&lt;ul&gt;&lt;li&gt;Perform count() on the root, store it to "treeSize"&lt;/li&gt;&lt;li&gt;Perform count() on every other node, store it to "subTreeSize"&lt;/li&gt;&lt;/ul&gt;&lt;div&gt;Then you automatically have the sizes of the two components "assuming" they were actually disconnected (while they are not; they are still the same tree). "subTreeSize" is the size of the tree component below the point we would cut it. "treeSize - subTreeSize" is the size of everything else, i.e. the second component. Voila!&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Hopefully you would find this interesting enough and tried it out before reading this. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Cheers!&lt;/div&gt;&lt;/div&gt;&lt;div style="border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 3px; padding-right: 3px; padding-bottom: 3px; padding-left: 3px; width: auto; font: normal normal normal 100%/normal Georgia, serif; text-align: left; "&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 3px; padding-right: 3px; padding-bottom: 3px; padding-left: 3px; width: auto; font: normal normal normal 100%/normal Georgia, serif; text-align: left; "&gt;PS: This blog post is a kind offer from the CoCo coffee-bar (wifi-enabled), located on Cowley St., at the beautiful city of Oxford. &lt;/div&gt;&lt;div style="border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 3px; padding-right: 3px; padding-bottom: 3px; padding-left: 3px; width: auto; font: normal normal normal 100%/normal Georgia, serif; text-align: left; "&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 3px; padding-right: 3px; padding-bottom: 3px; padding-left: 3px; width: auto; font: normal normal normal 100%/normal Georgia, serif; text-align: left; "&gt;PS2: SyntaxHighlighter just won't work for me. :-( Sorry. I am no CSS expert, and would need something pre-integrated in the blogging software.&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6958126065976802292-7628260451124990079?l=code-o-matic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://code-o-matic.blogspot.com/feeds/7628260451124990079/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://code-o-matic.blogspot.com/2009/04/wonderful-programming-exercise.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6958126065976802292/posts/default/7628260451124990079'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6958126065976802292/posts/default/7628260451124990079'/><link rel='alternate' type='text/html' href='http://code-o-matic.blogspot.com/2009/04/wonderful-programming-exercise.html' title='A Wonderful Programming Exercise'/><author><name>Dimitris Andreou</name><uri>https://profiles.google.com/116229150468867889128</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-l6gGcDEXxqI/AAAAAAAAAAI/AAAAAAAABq0/x5Wy-h5G81Y/s512-c/photo.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6958126065976802292.post-749194404324345885</id><published>2009-02-17T08:26:00.000-08:00</published><updated>2010-03-10T02:04:54.098-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='java puzzler'/><title type='text'>Crazy Java Puzzler</title><content type='html'>&lt;div&gt;Here is a puzzle for you. As the title promises, yes, it's quite crazy. It is assumed that you already are a die-hard Java programmer that knows the language better than the skin of his very palm. Ok, maybe not that much, but anyway.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;As a little history, I had posted this on the &lt;a href="http://www.jhug.gr/"&gt;Hellenic (i.e. Greek) Java User Group&lt;/a&gt;, which used to have an online forum, now defunct (too bad). So if you happen to be on those few who happened to see the solution there, just restrain yourself, I don't want any stinkin' spoilers!&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Enough of intro. Here is the code:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;pre class="java" name="code"&gt;interface id {&lt;br /&gt;  &amp;lt;id&amp;gt; Void read(List&amp;lt;id&amp;gt; list);&lt;br /&gt;  &amp;lt;id&amp;gt; Void read(List&amp;lt;id&amp;gt; list);&lt;br /&gt;  &amp;lt;id&amp;gt; Void read(List&amp;lt;id&amp;gt;... list); //*&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-weight: bold;"&gt;The puzzle&lt;/span&gt;: &lt;span class="Apple-style-span" style="font-style: italic;"&gt;What is the shortest edit &lt;/span&gt;(measured in inserted/deleted characters)&lt;span class="Apple-style-span" style="font-style: italic;"&gt; that makes this program compilable? (While keeping the read methods overloaded).&lt;/span&gt;&lt;br /&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;(We're not talking any kind of cheat like compiling with some arbitrary compiler, just the plain Java compiler. &lt;span class="Apple-style-span" style="font-weight: bold;"&gt;Oh, and commenting out lines of code is the wrong answer too&lt;/span&gt;).&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The problem, obviously, is that the two methods produce a name clash.Well, it's all yours! Hit it hard! Can you nail it?&lt;br /&gt;&lt;br /&gt;* [10-Mar-10] As Sureth below points, a solution would be appending "[]" to a list, a 2-character ending. Indeed. Sloppy of me. That basically ruins the fun, so I have to this third overloading to avoid [] and varargs solutions. Now (hopefully) only the intended solution is there, hopefully in not too artificial a puzzle. Oh, by the way, trying this problem is not a waste of time: it reveals a deeper knowledge about the java platform and gives a new (for those unaware of it) technique that can be used in API design. It's already the "magic sauce" of the nice API of a popular testing-related framework.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6958126065976802292-749194404324345885?l=code-o-matic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://code-o-matic.blogspot.com/feeds/749194404324345885/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://code-o-matic.blogspot.com/2009/02/crazy-java-puzzler.html#comment-form' title='9 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6958126065976802292/posts/default/749194404324345885'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6958126065976802292/posts/default/749194404324345885'/><link rel='alternate' type='text/html' href='http://code-o-matic.blogspot.com/2009/02/crazy-java-puzzler.html' title='Crazy Java Puzzler'/><author><name>Dimitris Andreou</name><uri>https://profiles.google.com/116229150468867889128</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-l6gGcDEXxqI/AAAAAAAAAAI/AAAAAAAABq0/x5Wy-h5G81Y/s512-c/photo.jpg'/></author><thr:total>9</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6958126065976802292.post-3754014018337751741</id><published>2009-02-09T00:13:00.000-08:00</published><updated>2009-02-12T08:49:20.986-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='trendy programming bug'/><title type='text'>Tales from the Trendy Programmer(TM)'s life, Part Two</title><content type='html'>&lt;div&gt;&lt;div&gt;My previous blog was about the curious "trendy programmer" syndrome, which manifested itself with mad "dsl"-like monsters. Since I see a pattern there, let me continue the, umm, trend, by showing another instance of trendy programming. This time, using the always trendy ThreadLocal.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Yep, lets admit it. Casually using ThreadLocal here and there makes you look trendy and cool. If you want to be trendy and cool, just do ThreadLocals.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Here is my story. Few months ago, we had been chasing a few strange bugs in some concurrent data-access (JDBC) code. We found them by using some &lt;a href="http://www.csd.uoc.gr/%7Eandreou/monitoringtools.html"&gt;quite handy tools I created&lt;/a&gt;, which were based on a mini interceptor framework. By intercepting JDBC, I went ahead and coded two tools. One which could locate unreleased java.sql.Connection (and pinpoint where in the code they were created), which helped us find unreleased connections left over by the code. And another one which showed the executed transactions, where started in code, where they were finished, and what SQL they contained. (As it turned out, the transactions were really messed up. For example, at some point the coded needed to lock a table, and did so, but some times it seemed that "the lock didn't work", a problem which the other programmer was seeking to pinpoint for weeks. I run the tool once, only to see that the lock was performed...in autoCommit mode. Eek).&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Now, to be able to intercept the real JDBC driver and persuade it to do our thing, I had to use some ThreadLocal, I admit. My guess is that it looked cool and trendy, where I wish it didn't.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;After that, I turned to other tasks than help debugging that project. I had a small idea what was happening to the other project, though. For what I knew, there seemed to be another important bug lingering somewhere. Nobody knew the cause, but I rested assured that the one assigned to it would handle it.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;And then came &lt;span class="Apple-style-span" style="font-style: italic;"&gt;the meeting&lt;/span&gt;. There was something intense in the air. Rumors said that somehow the mystery bug was fixed, and the programmer who did it would even show us the solution to it. He looked confident and happy, so it must have been something good. Cool.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;This went along these lines, in the aforementioned happy and confident tone: "The bug is fixed! The solution I applied to fix this was introducing a &lt;span class="Apple-style-span" style="font-style: italic;"&gt;ThreadLocal&lt;/span&gt; variable. Let me elaborate on what a ThreadLocal is, for those (poor souls) who don't know what it is". Blah blah blah. I was confused and skeptical. Moments later, he describes the test that previously failed due to the bug, which after the fix was passing. I was even more confused. So, I ask a simple question.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;-" Your test... how many threads does it use?"&lt;/div&gt;&lt;div&gt;-" Oh... well... just one".&lt;/div&gt;&lt;div&gt;-".................(is this really happening?).......hmm... you &lt;span class="Apple-style-span" style="font-style: italic;"&gt;do&lt;/span&gt; know that with a single thread, all variables are "thread-local" by definition, don't you?"&lt;/div&gt;&lt;div&gt;-(blank stare)&lt;/div&gt;&lt;div&gt;-(oh uh, I was afraid of that)&lt;/div&gt;&lt;div&gt;-(me, continuing) "And transforming an already thread-local variable to a thread-local...doesn't really have &lt;span class="Apple-style-span" style="font-style: italic;"&gt;any&lt;/span&gt; effect at all, like &lt;span class="Apple-style-span" style="font-style: italic;"&gt;fixing a bug&lt;/span&gt;"&lt;/div&gt;&lt;div&gt;-(incomprehensible attempts to explanation...and then:) "oh, I made it static too."&lt;/div&gt;&lt;div&gt;-(even more confused) "I really don't believe that's what fixed it"&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I spent the next few moments thinking what the consequences of making that variable static were. Which is that a single thread couldn't now use two objects of those together, while previously it could. But that wasn't our usage pattern, so we can just say "okayyy" for the moment and continue.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;So, amazingly, the guy &lt;span class="Apple-style-span" style="font-style: italic;"&gt;didn't actually know&lt;/span&gt; how he fixed the bug (he didn't tell the real fix in the meeting, I had to look it up in the commit logs). Or more likely, he &lt;span class="Apple-style-span" style="font-style: italic;"&gt;did&lt;/span&gt; know the fix, but was something dull and not-cool-enough that he wanted to present a &lt;span class="Apple-style-span" style="font-style: italic;"&gt;ThreadLocal solution&lt;/span&gt; instead. Now that's reverse engineering to a trendy programmer's mind.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Afterwards, I talked with him again. He admitted that ThreadLocal was &lt;span class="Apple-style-span" style="font-style: italic;"&gt;not&lt;/span&gt; the actual fix. (Thankfully - but why all that crap at the meeting? Anyway). &lt;span class="Apple-style-span" style="font-style: italic;"&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;- What's the point of introducing a single thread local variable in a class with a sea of plain variables?&lt;/div&gt;&lt;div&gt;- I just wanted &lt;span class="Apple-style-span" style="font-style: italic;"&gt;my &lt;/span&gt;code change to be thread-safe. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Great. We now have 2 or 3 "thread-safe" lines of code, which don't do anything by themselves, in a sea of 10,000s not-thread-safe code.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;And mind you, this kind of stuff is only going to get worse and worse in time, as more and more programmers find out that concurrent programming looks &lt;span class="Apple-style-span" style="font-style: italic;"&gt;trendy&lt;/span&gt;. Oh, I don't want to even think about that. Beware of the trendy programming!&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6958126065976802292-3754014018337751741?l=code-o-matic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://code-o-matic.blogspot.com/feeds/3754014018337751741/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://code-o-matic.blogspot.com/2009/02/tales-from-trendy-programmertms-life_09.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6958126065976802292/posts/default/3754014018337751741'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6958126065976802292/posts/default/3754014018337751741'/><link rel='alternate' type='text/html' href='http://code-o-matic.blogspot.com/2009/02/tales-from-trendy-programmertms-life_09.html' title='Tales from the Trendy Programmer(TM)&apos;s life, Part Two'/><author><name>Dimitris Andreou</name><uri>https://profiles.google.com/116229150468867889128</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-l6gGcDEXxqI/AAAAAAAAAAI/AAAAAAAABq0/x5Wy-h5G81Y/s512-c/photo.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6958126065976802292.post-1617688953040104689</id><published>2009-02-06T15:40:00.000-08:00</published><updated>2009-02-09T00:53:37.405-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='trendy programming bug'/><title type='text'>Tales from the Trendy Programmer(TM)'s life</title><content type='html'>Oh, the crave to be "trendy". The desire to be "cool", "fashionable", the urge to do old things the "new" way, the "shiny" way. Oh, the hell that opens when these thoughts emerge in the confused mind of a colleague.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;And what is more trendy these days than writing a DSL? Surely, everyone talks about their pet DSLs, and they keep coming from everywhere. Heck, even &lt;a href="http://code-o-matic.blogspot.com/2009/01/dsl-to-output-valid-xml-in-java.html"&gt;I blogged on one&lt;/a&gt;.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;What follows is the most ugly, complicated, and overwhelming solution I've seen in a while, to a problem as ... well, you'll see for yourself. I cannot otherwise explain the situation, other than the programmer trying so hard to be just a little bit more &lt;span class="Apple-style-span" style="font-style: italic;"&gt;trendy&lt;/span&gt;, at the cost of embracing sheer stupifying programmatic blindness and abandoning any kind of common sense.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Here is the amazingly complicated problem, in all its glory:&lt;/div&gt;&lt;div&gt;&lt;ul&gt;&lt;li&gt;&lt;span class="Apple-style-span" style="font-weight: bold;"&gt;Test a service (&lt;/span&gt;which takes a collection of files as input&lt;span class="Apple-style-span" style="font-weight: bold;"&gt;) using several interesting combinations of files (&lt;/span&gt;to see if the service can cope with each combination)&lt;/li&gt;&lt;/ul&gt;&lt;div&gt;My modest solution would be something like:&lt;/div&gt;&lt;/div&gt;&lt;pre name="code" class="java"&gt;&lt;br /&gt;final Document plainDocument = ...;&lt;br /&gt;final Document spicyDocument = ...;&lt;br /&gt;...&lt;br /&gt;final Document funnyDocument = ...;&lt;br /&gt;final Document specialDocument = ...;&lt;br /&gt;&lt;br /&gt;void testFirstInterestingCombination() {&lt;br /&gt;  service.call(plainDocument, spicyDocument);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;void testSecondInterestingCombination() {&lt;br /&gt;  service.call(specialDocument, plainDocument,&lt;br /&gt;        funnyDocument);&lt;br /&gt;}&lt;br /&gt;...//other tests that just pass interesting sets of documents&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;div&gt;But hey, if I did that, what would I be doing for the rest of the day? Just sit around and get bored? Surely there &lt;span class="Apple-style-span" style="font-style: italic;"&gt;has&lt;/span&gt; to be a better way! And here it is:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;pre name="code" class="java"&gt;&lt;br /&gt;interface DocumentCombinationBuilder {&lt;br /&gt;   DocumentCombinationBuilder plainDocument();&lt;br /&gt;   DocumentCombinationBuilder spicyDocument();&lt;br /&gt;   DocumentCombinationBuilder specialDocument();&lt;br /&gt;   ExtraDocumentCombinationBuilder extraDocuments();&lt;br /&gt;&lt;br /&gt;   Set&amp;lt;Document&amp;gt; getDocuments();&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;interface ExtraDocumentCombinationBuilder {&lt;br /&gt;   ExtraDocumentCombinationBuilder funnyDocument();&lt;br /&gt;   ExtraDocumentCombinationBuilder seriousDocument();&lt;br /&gt;   ExtraDocumentCombinationBuilder indifferentDocument();&lt;br /&gt;   Set&amp;lt;Document&amp;gt; getDocuments();&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;div&gt;&lt;/div&gt;For the love of Zeus, I'll just omit the 200-line implementation of the above, and skip directly to the test code that actually uses the above unlucky screen real estate, so to speak:&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="java"&gt;&lt;br /&gt;public void testFirstInterestingCombination() {&lt;br /&gt;   Set&amp;lt;Document&amp;gt; documents = new ExtraDocumentCombinationBuilder()&lt;br /&gt;       .plainDocument().specialDocument().getDocuments();&lt;br /&gt;   service.call(documents);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public void testSecondInterestingCombination() {&lt;br /&gt;   Set&amp;lt;Document&amp;gt; documents = new ExtraDocumentCombinationBuilder()&lt;br /&gt;       .specialDocument().plainDocument()&lt;br /&gt;       .extraDocuments().funnyDocument()&lt;br /&gt;       .getDocuments();&lt;br /&gt;   service.call(documents);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;...//more tests&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Isn't that just cute? This guy managed to uninvent method parameter passing! Which is, to be fair, just plain boring.&lt;br /&gt;&lt;br /&gt;Now, what's the best way to create an arbitrary collection of integers from one to ten? Would you just be dull and old-fashioned with something like "newSet(6, 7, 3, 2, 5)"? Hell no! Be popular with girls simply by being trendy:&lt;/div&gt;&lt;div&gt;&lt;pre name="code" class="java"&gt;&lt;br /&gt;new SetBuilder().six().seven().three().two().five().buildSet(); //the joy!&lt;br /&gt;&lt;/pre&gt;Perhaps I Should quit &lt;a href="http://thedailyworsethanfailure.com/"&gt;the daily WTF&lt;/a&gt;?&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6958126065976802292-1617688953040104689?l=code-o-matic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://code-o-matic.blogspot.com/feeds/1617688953040104689/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://code-o-matic.blogspot.com/2009/02/tales-from-trendy-programmertms-life.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6958126065976802292/posts/default/1617688953040104689'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6958126065976802292/posts/default/1617688953040104689'/><link rel='alternate' type='text/html' href='http://code-o-matic.blogspot.com/2009/02/tales-from-trendy-programmertms-life.html' title='Tales from the Trendy Programmer(TM)&apos;s life'/><author><name>Dimitris Andreou</name><uri>https://profiles.google.com/116229150468867889128</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-l6gGcDEXxqI/AAAAAAAAAAI/AAAAAAAABq0/x5Wy-h5G81Y/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6958126065976802292.post-4476891579636008204</id><published>2009-01-24T04:37:00.001-08:00</published><updated>2009-01-27T13:04:50.135-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='java dsl xml'/><title type='text'>A DSL to output XML, in Java</title><content type='html'>Yesterday, I had to output some simple XML in Java. I couldn't find any decent way of doing this out there. Writing with SAX sucks, and DOM didn't look much better either. I just println'ed the thing out and went on my way.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Today I revisited the problem. I wanted to easily express the XML tree structure and evaluate it as something, a String for instance. I came up with a neat solution heavily based on generics.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Here is a usage example of it:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"   style="  white-space: pre; font-family:-webkit-monospace;font-size:13px;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;pre name="code" class="java"&gt;XmlBuilder xmlBuilder = new XmlBuilder();&lt;br /&gt;String s = Xml.newDocument(new XmlBuilder())&lt;br /&gt;.kid("start")&lt;br /&gt;.kid("kid")&lt;br /&gt;  .kid("subkid").attr("key", "value")&lt;br /&gt;  .close()&lt;br /&gt;.close()&lt;br /&gt;.close();&lt;br /&gt;&lt;br /&gt;System.out.println(s);&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;Note that calling close() sometimes returns a node (that can also close()), but the last time returns directly a String!&lt;br /&gt;&lt;br /&gt;This is the output:&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="java"&gt;&lt;br /&gt;&amp;lt;?xml version="1.0"?&amp;gt;&lt;br /&gt;&amp;lt;root&amp;gt;&lt;br /&gt;&amp;lt;child&amp;gt;&lt;br /&gt;  &amp;lt;sub_child key="value"&amp;gt;&lt;br /&gt;  &amp;lt;/sub_child&amp;gt;&lt;br /&gt;&amp;lt;/child&amp;gt;&lt;br /&gt;&amp;lt;/root&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;div&gt;Here is the simplified crux of the idea:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="java"&gt;&lt;br /&gt;public class Node&amp;lt;T&amp;gt; {&lt;br /&gt;private final String name;&lt;br /&gt;private final T returnValue;&lt;br /&gt;private final XmlHandler handler;&lt;br /&gt;&lt;br /&gt;Node(String name, T returnValue, XmlHandler handler) {&lt;br /&gt;  this.name = name;&lt;br /&gt;  this.returnValue = returnValue;&lt;br /&gt;  this.handler = handler;&lt;br /&gt;}&lt;br /&gt;//...&lt;br /&gt;&lt;br /&gt;Node&amp;lt;Node&amp;lt;T&amp;gt;&amp;gt; child(String label) {&lt;br /&gt;  return new Node&amp;lt;Node&amp;lt;T&amp;gt;&amp;gt;(label, this, handler);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;T close() {&lt;br /&gt;  //...&lt;br /&gt;  handler.endNode(name);&lt;br /&gt;  return returnValue;&lt;br /&gt;}&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;The magic part is methods child() and close(). Node&amp;lt;T&amp;gt; means "when close() is called, return T". Imagine we want to output an XML as a string. We want the root node to be of type Node&amp;lt;String&amp;gt;, so when that closes, we get a String back. Right. Now pay attention to method to the child() method. It returns a Node&amp;lt;Node&amp;lt;T&amp;gt;&amp;gt;, meaning "here is a node that when it closes, you return back to this node" (and we give "this" as a returnValue of the new node).&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;This means that the compiler can figure out the nesting level of each Node. The root Node is just Node&amp;lt;String&amp;gt;. All children of that are of type Node&amp;lt;Node&amp;lt;String&amp;gt;&amp;gt;. Children of those children are Node&amp;lt;Node&amp;lt;Node&amp;lt;String&amp;gt;&amp;gt;&amp;gt;, and so on. When a close() is invoked, a nesting goes away, like pealing an onion kind of way, till we get back to the result we want.&lt;/div&gt;&lt;div&gt;&lt;t&gt;&lt;string&gt;&lt;div&gt;&lt;br /&gt;&lt;div&gt;&lt;div&gt;XmlBuilder is similar to ContentHandler, but simplified. Here it is:&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="java"&gt;&lt;br /&gt;public interface XmlHandler&amp;lt;T&amp;gt; {&lt;br /&gt;void startNode(String name, Map attributes);&lt;br /&gt;void endNode(String name);&lt;br /&gt;&lt;br /&gt;T result();&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The above library can be used with any implementation of XmlHandler - producing a String is only a viable use-case. One could easily create a DOM as well, simply by creating another XmlHandler implementation. XmlBuilder in the example above is XmlHandler&lt;string&gt;, and this is why the root node is of type Node&lt;string&gt;. We could implement an XmlHandler&lt;whatever&gt; and get back the root node as Node&lt;whatever&gt;.&lt;/whatever&gt;&lt;/whatever&gt;&lt;/string&gt;&lt;/string&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;To conclude, this is a nice DSL for expressing XML trees, combined with an abstract handler to process the tree. A point to highlight is that this modelling allows the compiler to know the nesting of each node, so it knows how many consequtive "close()" I can call for example. I must call the right amound of close() to get back to the result I want, or else a type error will occur.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Still, this kind of type-safety doesn't automatically translate to valid XML, because the user could store a node somewhere and close it twice - we would only find that at runtime.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;All in all, that was a good exercise in Java generics. I would give the complete source if there was an easy way to attach it here, but I guess the margin is too narrow. :-)&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/string&gt;&lt;/t&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;script type="text/javascript"&gt;&lt;br /&gt;var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");&lt;br /&gt;document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));&lt;/script&gt;&lt;br /&gt;&lt;script type="text/javascript"&gt;&lt;br /&gt;var pageTracker = _gat._getTracker("UA-3504642-2");&lt;br /&gt;pageTracker._initData();&lt;br /&gt;pageTracker._trackPageview();&lt;/script&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6958126065976802292-4476891579636008204?l=code-o-matic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://code-o-matic.blogspot.com/feeds/4476891579636008204/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://code-o-matic.blogspot.com/2009/01/dsl-to-output-valid-xml-in-java.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6958126065976802292/posts/default/4476891579636008204'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6958126065976802292/posts/default/4476891579636008204'/><link rel='alternate' type='text/html' href='http://code-o-matic.blogspot.com/2009/01/dsl-to-output-valid-xml-in-java.html' title='A DSL to output XML, in Java'/><author><name>Dimitris Andreou</name><uri>https://profiles.google.com/116229150468867889128</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-l6gGcDEXxqI/AAAAAAAAAAI/AAAAAAAABq0/x5Wy-h5G81Y/s512-c/photo.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6958126065976802292.post-3340396218691989515</id><published>2009-01-20T15:35:00.000-08:00</published><updated>2009-02-09T00:54:06.581-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='PhantomReference java finalization'/><title type='text'>The Subtleties of PhantomReference and finalization</title><content type='html'>&lt;span class="Apple-style-span"  style=" ;font-family:'Times New Roman';"&gt;&lt;div style="text-align: justify;border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 3px; padding-right: 3px; padding-bottom: 3px; padding-left: 3px; width: auto; font: normal normal normal 100%/normal Georgia, serif; "&gt;&lt;span&gt;&lt;span&gt;A common misconception regarding PhantomReference is that it is designed to "fix" the dead object resurrection problem that finalizers have. For example, this &lt;a href="http://weblogs.java.net/blog/enicholas/archive/2006/05/understanding_w.html"&gt;old java.net blog&lt;/a&gt; says about phantom references:&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;span&gt;&lt;div style="text-align: justify;"&gt;&lt;/div&gt;&lt;blockquote&gt;&lt;div style="text-align: justify;"&gt;PhantomReferences avoid a fundamental problem with finalization: finalize() methods can "resurrect" objects by creating new strong references to them. So what, you say? Well, the problem is that an object which overrides finalize() must now be determined to be garbage in at least two separate garbage collection cycles in order to be collected.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;/div&gt;&lt;/blockquote&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Well, yeah. Except for the fact that even PhantomReference can let their referred objects be resurrected. This is even how it can be done:&lt;br /&gt;&lt;/div&gt;&lt;span&gt;&lt;div style="text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;pre name="code" class="java"&gt;Reference ref = referenceQueue.remove();&lt;br /&gt;//ref is our PhantomReference instance&lt;br /&gt;Field f = Reference.class.getDeclaredField("referent");&lt;br /&gt;f.setAccessible(true);&lt;br /&gt;System.out.println("I see dead objects! --&gt; " + f.get(ref));&lt;br /&gt;//This is obviously a very bad practice&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Yes, unreachable objects are really referenced from the Reference#referent field, seemingly strongly, but no, the garbage collector makes an exception for that particular field. This fact also contradicts what the previous blog declares:&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;blockquote&gt;PhantomReferences are enqueued only when the object is physically removed from memory.&lt;/blockquote&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Which is not true, as we just saw. Javadocs also say:&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;/div&gt;&lt;blockquote&gt;&lt;div style="text-align: justify;"&gt;Phantom references are most often used for scheduling &lt;span class="Apple-style-span" style="font-weight: bold;"&gt;pre&lt;/span&gt;-mortem cleanup&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;/div&gt;&lt;/blockquote&gt;&lt;div style="text-align: justify;"&gt;So if PhantomReference was not meant to fix the resurrection problem (which indeed is serious, as pointedly proven by Lazarus, Jesus and many others), what is it useful &lt;span class="Apple-style-span" style="font-style: italic;"&gt;for&lt;/span&gt;?&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;The main advantage of using a PhantomReference over finalize() is that finalize() is called by a garbage-collector thread, meaning it introduces concurrency even in a single-threaded program, with all the potential issues (like correctly synchronizing shared state). With a PhantomReference, &lt;span class="Apple-style-span" style="font-weight: bold; "&gt;you&lt;/span&gt; choose the thread that dequeues references from your queue (in a single-threaded program, that thread could periodically do this job).&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;What about using WeakReference? It seems to also fit the bill for pre-mortem clean-up. The difference lies in when exactly the reference is enqueued. A PhantomReference is enqueued &lt;span class="Apple-style-span" style="font-weight: bold;"&gt;after&lt;/span&gt; finalization of the object. A WeakReference is enqueued &lt;span class="Apple-style-span" style="font-weight: bold;"&gt;before&lt;/span&gt;. This doesn't matter for objects with no non-trivial finalize() method.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;And how exactly are you supposed to clean-up a dead object you don't even know? (PhantomReference's get() method always returns null). Well, you &lt;span class="Apple-style-span" style="font-weight: bold;"&gt;should&lt;/span&gt; store as much state as needed to perform the clean-up. If cleaning up an object means &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;null&lt;/span&gt;ing an element of a global array, then you have to keep track of the element index, for example. This can be easily done by extending the PhantomReference and adding the fields you want, and then create PhantomReference instances from that subclass.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Now lets talk about even darker corners than these.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Lets say that it is even darker relating finalization than this. If you are about to write a clean-up hook for an object (by finalize() or with a [Weak|Phantom]Reference), and you happen to call a method on it while there is &lt;span class="Apple-style-span" style="font-weight: bold;"&gt;it is strongly-referenced only from the thread stack&lt;/span&gt; (i.e. a local variable), &lt;span class="Apple-style-span" style="font-weight: bold;"&gt;and you happen to invoke a method to that object, bad things can happen&lt;/span&gt;.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;This is very unfortunate. For performance reasons, the VM is permitted if it can to reuse the register that holds the object reference, thus making the object unreachable. So, during the method invocation on an object, &lt;span class="Apple-style-span" style="font-weight: bold;"&gt;finalization might be executed concurrently&lt;/span&gt;, leading to unpredictable results (finalize() could modify state that is needed by the other method execution). This should be extremely rare though. Currently, this can be fixed by:&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span class="Apple-style-span"   style="  white-space: pre;font-family:-webkit-monospace;font-size:13px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="java"&gt;Object method() {&lt;br /&gt; //do work here&lt;br /&gt; synchronized (this) { }&lt;br /&gt; return result;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="java"&gt;public void finalize() {&lt;br /&gt;synchronized (this) { }&lt;br /&gt;//do work here&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;div style="text-align: justify;"&gt;This will only affect you if you have an object referenced only from the thread stack &lt;span class="Apple-style-span" style="font-weight: bold;"&gt;and &lt;/span&gt;either one holds:&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;ul&gt;&lt;li&gt;it has a non-trivial finalize() method&lt;/li&gt;&lt;li&gt;there is a [Weak|Soft|PhantomReference] to it, enlisted to a ReferenceQueue, and there is &lt;span class="Apple-style-span" style="font-weight: bold;"&gt;a different&lt;/span&gt; thread that dequeues references from ReferenceQueue&lt;/li&gt;&lt;/ul&gt;&lt;div&gt;To conclude, the safest clean-up for objects is to have a ReferenceQueue and a PhantomReference, and you use the same thread that uses the object to do the clean-up. (If this the clean-up is performed from another thread, synchronization will probably be needed, and the above issue might be relevant).&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;You may check these &lt;a href="http://gceclub.sun.com.cn/java_one_online/2005/TS-3281/ts-3281.pdf"&gt;JavaOne slides&lt;/a&gt; too.&lt;/div&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;script type="text/javascript"&gt;&lt;br /&gt;var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");&lt;br /&gt;document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));&lt;br /&gt;&lt;/script&gt;&lt;br /&gt;&lt;script type="text/javascript"&gt;&lt;br /&gt;try {&lt;br /&gt;var pageTracker = _gat._getTracker("UA-3504642-2");&lt;br /&gt;pageTracker._trackPageview();&lt;br /&gt;} catch(err) {}&lt;/script&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6958126065976802292-3340396218691989515?l=code-o-matic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://code-o-matic.blogspot.com/feeds/3340396218691989515/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://code-o-matic.blogspot.com/2009/01/subtleties-of-phantomreference-and.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6958126065976802292/posts/default/3340396218691989515'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6958126065976802292/posts/default/3340396218691989515'/><link rel='alternate' type='text/html' href='http://code-o-matic.blogspot.com/2009/01/subtleties-of-phantomreference-and.html' title='The Subtleties of PhantomReference and finalization'/><author><name>Dimitris Andreou</name><uri>https://profiles.google.com/116229150468867889128</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-l6gGcDEXxqI/AAAAAAAAAAI/AAAAAAAABq0/x5Wy-h5G81Y/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6958126065976802292.post-6123558680817380950</id><published>2009-01-18T00:15:00.000-08:00</published><updated>2009-01-24T17:55:43.678-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='java random contention'/><title type='text'>Beware of hidden contention of Math.random()</title><content type='html'>&lt;div style="text-align: justify;"&gt;Did you know that Math.random() uses a single &lt;a href="http://java.sun.com/j2se/1.5.0/docs/api/java/util/Random.html"&gt;java.util.Random&lt;/a&gt; instance, which itself is thread-safe*? What this means is that if you have a benchmark with multiple threads that are supposed to run in parallel, and all of them constantly generate random numbers through Math.random(), they will all compete for its lock and can deteriorate into running serially.&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;So, beware of this pitfall. It is preferrable to share instead a ThreadLocal&lt;random&gt;, as for example in:&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;static final ThreadLocal&lt;random&gt; localRandom = new ThreadLocal&lt;random&gt;() {&lt;/div&gt;&lt;div style="text-align: justify;"&gt;    @Override protected Random initialValue() {&lt;/div&gt;&lt;div style="text-align: justify;"&gt;        return new Random();&lt;/div&gt;&lt;div style="text-align: justify;"&gt;    }&lt;/div&gt;&lt;div style="text-align: justify;"&gt;};&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;...&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Random random = localRandom.get();&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;This is already quite a common practice when using &lt;a href="http://java.sun.com/j2se/1.5.0/docs/api/java/text/SimpleDateFormat.html"&gt;SimpleDateFormat&lt;/a&gt; in web applications, where it is more efficient to have a separate instance per thread rather than have all threads contend for a single instance (which tends to be quite computationally intensive).&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;A better alternative is slated for inclusion in Java 7: &lt;a href="http://gee.cs.oswego.edu/dl/jsr166/dist/jsr166ydocs/jsr166y/ThreadLocalRandom.html"&gt;ThreadLocalRandom&lt;/a&gt;. This is like a thread local Random, only it is not thread-safe, so some unnecessary overhead is avoided. There is a slight inconvenience that you can't control the initial seed - I could be wrong though (the javadoc says that setSeed throws UnsupportedOperationException, but the implementation seems to be that exactly one call of this method is allowed).&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;* Using volatile reads and compare-and-swaps, which makes it lock-free&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;script type="text/javascript"&gt;&lt;br /&gt;var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");&lt;br /&gt;document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));&lt;br /&gt;&lt;/script&gt;&lt;br /&gt;&lt;script type="text/javascript"&gt;&lt;br /&gt;try {&lt;br /&gt;var pageTracker = _gat._getTracker("UA-3504642-2");&lt;br /&gt;pageTracker._trackPageview();&lt;br /&gt;} catch(err) {}&lt;/script&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6958126065976802292-6123558680817380950?l=code-o-matic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://code-o-matic.blogspot.com/feeds/6123558680817380950/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://code-o-matic.blogspot.com/2009/01/beware-of-hidden-contention-of.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6958126065976802292/posts/default/6123558680817380950'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6958126065976802292/posts/default/6123558680817380950'/><link rel='alternate' type='text/html' href='http://code-o-matic.blogspot.com/2009/01/beware-of-hidden-contention-of.html' title='Beware of hidden contention of Math.random()'/><author><name>Dimitris Andreou</name><uri>https://profiles.google.com/116229150468867889128</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-l6gGcDEXxqI/AAAAAAAAAAI/AAAAAAAABq0/x5Wy-h5G81Y/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6958126065976802292.post-8019740091724811642</id><published>2009-01-12T04:24:00.000-08:00</published><updated>2009-01-24T17:55:56.442-08:00</updated><title type='text'>Comments on "Is Java Obsolete?"</title><content type='html'>&lt;div style="text-align: justify;"&gt;Today I read this blog: &lt;a href="http://californickation.blogspot.com/2009/01/is-java-obsolete.html"&gt;Is Java obsolete? &lt;/a&gt;(spoiler alert: Scala inside)&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Apart from the title which used to be an attention-grabbing (along with "java is dead") but not really any more, I am in a quite similar situation as that author.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;To begin with, I'm a Java programmer. I've invested (literally) thousand hours of my own time in it the past few years, eagerly learning its ins and outs, and also use it for a day job. I can't attain the same level of productiveness using anything else, without spending (much) much time learning it.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Now, on with the post. It's about someone starting &lt;a href="http://www.scala-lang.org/"&gt;http://www.scala-lang.org/&lt;/a&gt;. And doing it, feels (like me) that poor Java-the-language misses so much power (no closures, no FP...). (By the way here is how I picked up Scala: by reading a &lt;a href="http://www.scala-lang.org/docu/files/ScalaOverview.pdf"&gt;paper/overview&lt;/a&gt; on it, watching &lt;a href="http://www.parleys.com/display/PARLEYS/Home#title=The%20Challenge%20of%20Scalable%20Languages;talk=18317398;slide=1"&gt;a talk by Martin Odersky&lt;/a&gt;, and I'm currently reading &lt;a href="http://www.artima.com/shop/programming_in_scala"&gt;Programming in Scala&lt;/a&gt;).&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;I played a bit with various scripting languages. I quite like Ruby/Python, but when I found out what performance implications those pertain, I grew very skeptical (see for example &lt;a href="http://www.python.org/doc/essays/list2str/"&gt;this performance essay of Guido&lt;/a&gt; and amaze). What I saw was performance characteristics (i.e. "slow"), not in the fixable sense Java was in its start, but not fixable, due to language design itself. So I decided I needed something else (and thankfully, Scala was there all along). &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Previously, I also explored some other Java-friendly alternatives, like Groovy. In the words of an anonymous commentator of the above blog: "you might want to have a look at the Groovy language, instead of Scala". Now that's a motivation, heh. Anyway. My experience with groovy was not so good. I looked at it more than a year ago, and the compiler pretty much sucked - I couldn't understand any of the syntax errors. I had the intention of learning it, to at least be able to use it in small-scale scripting tasks, on the console. But that proved futile: it was so easy getting wrong, that I really had to grok most of the groovy language to be able to use it, and that just wouldn't pay off for small-scale scripting tasks. For large-scale, just forget about it. This quote from groovy's main page nicely summarizes the reason: &lt;/div&gt;&lt;div&gt;&lt;ul&gt;&lt;li&gt;&lt;span class="Apple-style-span"  style="font-size:medium;"&gt;You will not get compile errors like you would in Java for using undefined members or passing arguments of the wrong type. See Runtime vs Compile time, Static vs Dynamic.&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div&gt;So, I found the comment's last part "... instead of Scala" quite hilarious. Maybe "complementary", but "instead"? Anyway, I don't want to go there just yet.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;I remember actually settling for BeanShell, since it was much easier to use. Less powerful, true, but not so cumbersome - easy to put to actual work.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;But those are things of the past. I'm quite happy to be able to have both 1) a very powerful oo-functional language, and 2) a very powerful type systems. Types, after all, is the natural currency of Java (as nicely said by crazy bob lee). I tend to view types as language extentions, i.e. "things you can do if you reach here". It's like having the author of a library there with you, giving you advice and direction all the time, whereas in dynamic languages all you have is a string soup where you have to attain the skill of choosing the right string to do the job (and while being at it, write a test proving you picked the right string).&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;To sum up, I can't picture groovy, or any dynamically typed languages replacing java anytime soon. I also don't see scala replacing java anytime soon, either. But I like the ability to enjoy more powerful programming in scala, while the rest of the world can keep using plain java, and all be peaceful and well. &lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Enough rambling from me, on with actual work :)&lt;/div&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;script type="text/javascript"&gt;&lt;br /&gt;var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");&lt;br /&gt;document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));&lt;br /&gt;&lt;/script&gt;&lt;br /&gt;&lt;script type="text/javascript"&gt;&lt;br /&gt;try {&lt;br /&gt;var pageTracker = _gat._getTracker("UA-3504642-2");&lt;br /&gt;pageTracker._trackPageview();&lt;br /&gt;} catch(err) {}&lt;/script&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6958126065976802292-8019740091724811642?l=code-o-matic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://code-o-matic.blogspot.com/feeds/8019740091724811642/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://code-o-matic.blogspot.com/2009/01/today-i-read-this-blog-is-java-obsolete.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6958126065976802292/posts/default/8019740091724811642'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6958126065976802292/posts/default/8019740091724811642'/><link rel='alternate' type='text/html' href='http://code-o-matic.blogspot.com/2009/01/today-i-read-this-blog-is-java-obsolete.html' title='Comments on &quot;Is Java Obsolete?&quot;'/><author><name>Dimitris Andreou</name><uri>https://profiles.google.com/116229150468867889128</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-l6gGcDEXxqI/AAAAAAAAAAI/AAAAAAAABq0/x5Wy-h5G81Y/s512-c/photo.jpg'/></author><thr:total>2</thr:total></entry></feed>
