<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:openSearch="http://a9.com/-/spec/opensearch/1.1/" xmlns:georss="http://www.georss.org/georss" xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr="http://purl.org/syndication/thread/1.0" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" gd:etag="W/&quot;Ak8MRn8yfSp7ImA9WhRUE04.&quot;"><id>tag:blogger.com,1999:blog-5829875</id><updated>2012-01-23T17:14:47.195Z</updated><category term="quote" /><category term="meta" /><category term="graphs" /><category term="puzzle" /><category term="research" /><category term="learning" /><category term="opinion" /><category term="teaching" /><category term="presentation" /><category term="random" /><category term="coding" /><title>Theory and Practice</title><subtitle type="html" /><link rel="http://schemas.google.com/g/2005#feed" type="application/atom+xml" href="http://rgrig.blogspot.com/feeds/posts/default" /><link rel="alternate" type="text/html" href="http://rgrig.blogspot.com/" /><link rel="next" type="application/atom+xml" href="http://www.blogger.com/feeds/5829875/posts/default?start-index=26&amp;max-results=25&amp;redirect=false&amp;v=2" /><author><name>Radu Grigore</name><uri>https://profiles.google.com/101644137139656854756</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh4.googleusercontent.com/-qUUZcf9ulqQ/AAAAAAAAAAI/AAAAAAAADnE/AVKMToUdkMQ/s512-c/photo.jpg" /></author><generator version="7.00" uri="http://www.blogger.com">Blogger</generator><openSearch:totalResults>228</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://feeds.feedburner.com/RgrigsBlog" /><feedburner:info uri="rgrigsblog" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><link rel="license" type="text/html" href="http://creativecommons.org/licenses/by-nc/3.0/" /><entry gd:etag="W/&quot;CUcFQnwyeCp7ImA9WhRSFkw.&quot;"><id>tag:blogger.com,1999:blog-5829875.post-7852094618864459383</id><published>2011-11-16T22:52:00.001Z</published><updated>2011-11-18T10:43:33.290Z</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-11-18T10:43:33.290Z</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="graphs" /><category scheme="http://www.blogger.com/atom/ns#" term="research" /><category scheme="http://www.blogger.com/atom/ns#" term="learning" /><category scheme="http://www.blogger.com/atom/ns#" term="presentation" /><title>Squaregraphs</title><content type="html">&lt;p&gt;&lt;i&gt;On Tuesday, Donald Knuth gave a talk about &lt;a href="http://en.wikipedia.org/wiki/Squaregraph"&gt;squaregraphs&lt;/a&gt;. I'm summarizing here what I learned, and I'm including the open problems that Knuth mentioned.&lt;/i&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;p&gt;Squaregraphs are plannar graphs. When you draw a graph in a plane, each of its cycles partition the plane into two regions, one  bounded and one unbounded. When the bounded region is empty (that is, no edge and no vertex is drawn in it), the cycle is called a &lt;i&gt;bounded face&lt;/i&gt;; when the unbounded region is empty, the cycle is called an &lt;i&gt;unbounded face&lt;/i&gt;. By definition, all bounded faces of a squaregraph are 4-cycles. There is one more condition. A vertex is &lt;i&gt;interior&lt;/i&gt; if it does not belong to the unbounded face. All interior vertices must have degree $\ge4$. Here is an example, a gear graph.&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/-j8vFDI4cqTU/TsRS_WwP43I/AAAAAAAAEmE/A6dolRTGuZM/s1600/gear.png" /&gt;&lt;/div&gt;&lt;p&gt;Knuth told us about many properties that are implied by this definition, usually without proof. I enjoy such talks. First, they give you a hawk's eye view of a subject; second, they make you think about the proofs. Some proofs are easy and some escape you during the talk and even days afterwards, but at least you get an idea of what is easy and what is not. What bothers me is that at no point did I feel the need to invoke the last property, that interior vertices have at least 4 neighbours.&lt;br /&gt;
&lt;p&gt;But let's focus on what I &lt;i&gt;did&lt;/i&gt; learn, rather than what I did not understand.&lt;br /&gt;
&lt;p&gt;While on the bus, before the talk, Rasmus and I looked at the Wikipedia article on squaregraphs, which is very dense, and tried to make sense of it. I think it helped both of us to follow the presentation better. One of the last things Rasmus said was: "Squaregraphs ought to have an inductive definition." And, lo and behold, we found out what that definition is during the talk. Every squaregraph can be built by starting with a 4-cycle and repeatedly adding new faces, subject to the degree constraint: take a simple path of length 1, 2, or 3 that is part of the unbounded face and make a new 4-cycle by adding, respectively, 3, 2, or 1 new edges (drawn in the former unbounded face, that is, towards the outside).&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;img border="0" height="56" width="400" src="http://1.bp.blogspot.com/-rzvAttPzq4g/TsVHtFIFM-I/AAAAAAAAEmo/wtvXKzhKQ1s/s1600/edge.png" /&gt;&lt;/div&gt;&lt;p&gt;Open problem: Is it possible, using this inductive definition, to construct squaregraphs that look like Mona Lisa when viewed from afar?&lt;br /&gt;
&lt;p&gt;By the way, a frog can jump from an edge to an opposite edge across a bounded face, obviously. Here is a picture with all possible frog expeditions on an 8-gear.&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;img border="0" height="123" width="123" src="http://1.bp.blogspot.com/-CX0pHPZsbto/TsU3t7Q-DMI/AAAAAAAAEmc/KYMXFKFqYBU/s1600/gear2.png" /&gt;&lt;/div&gt;Each expedition, depicted above with a curved green line, is a set of edges that cut the graph into two disconnected parts. We give vertices on one side a bit $0$ and vertices on the other side a bit $1$. If we do this for each expedition then each vertex gets as many bits as there are expeditions. To put some order on these bits we name the expeditions $0$, $1$, $\ldots\,$, $n-1$, so each vertex gets an $n$-bit string. In our example, there are 8 green lines so each vertex will get an 8-bit string.&lt;br /&gt;
&lt;p&gt;These bitstrings are interesting because the shortest distance between two vertices equals the &lt;a href="http://en.wikipedia.org/wiki/Hamming_distance"&gt;Hamming distance&lt;/a&gt; between the bitstrings of the vertices. We say that we found an isometric embedding of squaregraphs into an $n$-dimensional hypercube. In $n$ dimensions, squaregraphs look squarish.&lt;br /&gt;
&lt;p&gt;Another interesting property of squaregraphs is that they are median graphs. A median graph is one in which all three vertices $x$, $y$, and $z$ have a median vertex $\langle xyz\rangle$ that is on some shortest path between $x$ and $y$, on some shortest path between $y$ and $z$, and on some shortest path between $z$ and $x$. An example is the integer grid, with vertices $(m_x,m_y)$ for all integers $m_x$ and $m_y$, and edges between vertices $m$ and $n$ when $|m_x-n_x|+|m_y-n_y|=1$. The $x$-coordinate of $\langle mnp\rangle$ is the median of the array $[m_x,n_x,p_x]$, hence the name (I guess). It turns out that you can also isometrically embed median graphs in $n$-dimensional hypercubes. That is, you can label vertices with bitstrings such that travelling an edge flips exactly one bit.&lt;br /&gt;
&lt;p&gt;A subset of the $n$-dimensional hypercube is a median graph exactly when the selected coordinates are the models of a 2-CNF formula. Knuth said that an open problem would be to find a nice condition to impose on 2-CNF formulas such that their models correspond to squaregraphs.&lt;br /&gt;
&lt;p&gt;Notice that on squaregraphs we have a notion of a line (the green equivalence classes above) and also of turning left or right. This means that we can define a knight's move on the bounded faces of a squaregraph. How can we generalize various problems that are usually done on chessboards to squaregraphs? For example, can one define something like &lt;a href="http://en.wikipedia.org/wiki/Rook_polynomial"&gt;rook polynomials&lt;/a&gt; for squaregraphs?&lt;br /&gt;
&lt;p&gt;Finally, is there a 3D generalization of squaregraphs?&lt;br /&gt;
&lt;p&gt;For more information, Knuth recommended a paper by &lt;a href="http://arxiv.org/abs/0905.4537"&gt;Bandelt, Chepoi, and Eppstein&lt;/a&gt;, which is also recommended by Wikipedia. It's quite long, though. Knuth also showed us &lt;a href="http://11011110.livejournal.com/223622.html"&gt;some nice pictures of squaregraphs on Eppstein's blog&lt;/a&gt;. Of this blog he said: "It is one of the best blogs in computer science. I do not read it, for otherwise I would not do anything else."&lt;br /&gt;
&lt;p&gt;[&lt;i&gt;Thanks to &lt;a href="http://www.eecs.qmul.ac.uk/~rusmus/"&gt;Rasmus&lt;/a&gt; for finding several mistakes in a previous version.&lt;/i&gt;]&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5829875-7852094618864459383?l=rgrig.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/RgrigsBlog/~4/915GoEDzEcU" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://rgrig.blogspot.com/feeds/7852094618864459383/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://rgrig.blogspot.com/2011/11/squaregraphs.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5829875/posts/default/7852094618864459383?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5829875/posts/default/7852094618864459383?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/RgrigsBlog/~3/915GoEDzEcU/squaregraphs.html" title="Squaregraphs" /><author><name>Radu Grigore</name><uri>https://profiles.google.com/101644137139656854756</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh4.googleusercontent.com/-qUUZcf9ulqQ/AAAAAAAAAAI/AAAAAAAADnE/AVKMToUdkMQ/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://3.bp.blogspot.com/-j8vFDI4cqTU/TsRS_WwP43I/AAAAAAAAEmE/A6dolRTGuZM/s72-c/gear.png" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://rgrig.blogspot.com/2011/11/squaregraphs.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DEEBQH4yeSp7ImA9WhRSEEo.&quot;"><id>tag:blogger.com,1999:blog-5829875.post-5497970554410524171</id><published>2011-11-10T17:26:00.000Z</published><updated>2011-11-12T05:44:11.091Z</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-11-12T05:44:11.091Z</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="research" /><category scheme="http://www.blogger.com/atom/ns#" term="learning" /><title>Automata on Infinite Alphabets</title><content type="html">&lt;p&gt;&lt;i&gt;There are several ways of extending the standard definitions of automata to infinite alphabets. Here I try to explain why the trivial extension (just use the same definitions) is not satisfactory and present a couple of alternatives.&lt;/i&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;p&gt;The usual definitions go like this. Given is a finite set $\Sigma$. We say that $\Sigma$ is an &lt;i&gt;alphabet&lt;/i&gt; and its elements are &lt;i&gt;letters&lt;/i&gt;. &lt;i&gt;Words&lt;/i&gt; are strings of letters, &lt;i&gt;languages&lt;/i&gt; are sets of words. A &lt;i&gt;finite automaton&lt;/i&gt; is a finite digraph whose arcs are labelled by letters, has a distinguished &lt;i&gt;initial&lt;/i&gt; vertex, and has some vertices marked as being &lt;i&gt;accepting&lt;/i&gt;. Each (finite) automaton determines a language, namely the set of those words obtained by concatenating the labels of a walk from the initial vertex to some accepting vertex. A language that can be described by a finite automaton is said to be &lt;i&gt;regular&lt;/i&gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;p&gt;Why restrict $\Sigma$ to be finite? What could possibly cause problems if we allow it to be bigger? Isn't the generalization straightforward?&lt;br /&gt;
&lt;br /&gt;
&lt;p&gt;Yes and no.&lt;br /&gt;
&lt;br /&gt;
&lt;p&gt;Yes, we could simply remove the restriction on $\Sigma$ and keep the same definitions. However, that would lead to situations that intuitively just don't feel right. For example, is the language $L=\{\,abc \mid c\in\{a,b\}\,\}$ regular? With the definitions above $L$ is regular exactly when $\Sigma$ is finite. There is something unpleasant about a language suddenly becoming non-regular, although its (declarative) definition does not change.&lt;br /&gt;
&lt;br /&gt;
&lt;p&gt;Recall the standard model for (finite) automata: a transition function $\delta:X\times\Sigma\to X$, where $X=V$ is the (finite) set of vertices, an accepting function $\alpha:V\to2$, and the initial function $\iota:1\to X$. There are at least three ways of extending the standard model: finite-memory automata aka register automata (&lt;a href="http://scholar.google.co.uk/scholar?q=finite+memory+automata"&gt;Francez and Kaminski, 1994&lt;/a&gt;), pebble automata, and data automata. All three are surveyed by &lt;a href="http://scholar.google.co.uk/scholar?hl=en&amp;q=automata+and+logics+for+words+and+trees+over+an+infinite+alphabet"&gt;Segoufin (2006)&lt;/a&gt;. Thinking back of the language $L$, the intuitive reason why it cannot be recognized by a finite automaton is that we cannot easily remember the letters we saw. So the natural thing to try is to add a (finite) memory to the automaton. This suggests distinguishing between the (not necessarily finite) set of states $X$ and the finite set of vertices $V$. For example, we could take $X=V\times\Sigma^k$ for some $k$. The automaton has $k$ &lt;i&gt;registers&lt;/i&gt;. However, now the automaton is too powerful. For example, take $V$ to be the singleton set $1$, and $\Sigma$ to be the set of natural numbers $\mathbb{N}$, and $k$ to be $1$. Then $\delta$ could be essentially any function $\mathbb{N}\times\mathbb{N}\to\mathbb{N}$. We did not even require it to be computable! The class of languages recognized by such a device is clearly too big to be called "regular". This is why extra restrictions on $\delta$ are needed. Francez and Kaminski (1994) essentially required that all that $\delta$ can do with letters is (1) store them in registers and (2) compare them for equality.&lt;br /&gt;
&lt;br /&gt;
&lt;p&gt;Finally, &lt;a href="http://scholar.google.co.uk/scholar?hl=en&amp;q=automata+with+group+actions"&gt;Bojanczyk et al (2011)&lt;/a&gt; give what I think is a very cute extension of the standard model of (finite) automata.&lt;br /&gt;
&lt;br /&gt;
&lt;p&gt;&lt;span style="background:#ffff99"&gt;&lt;br /&gt;
Their model is still a triple $(\delta, \alpha, \iota)$ of functions with the types as given above. However, the extra restrictions are much more principled. Now $X$ and $\Sigma$ are required to be $G$-Sets (for some group $G$), and all the three functions are required to be invariant. (These concepts are explained in &lt;a href="http://rgrig.blogspot.com/2011/11/group-actions.html"&gt;my previous post on group actions&lt;/a&gt;.) A language is now &lt;i&gt;$G$-regular&lt;/i&gt; when it is recognized by an automaton for which both $X$ and $\Sigma$ have a finite number of orbits.&lt;/span&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5829875-5497970554410524171?l=rgrig.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/RgrigsBlog/~4/hSJk-jvTyj8" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://rgrig.blogspot.com/feeds/5497970554410524171/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://rgrig.blogspot.com/2011/11/automata-on-infinite-alphabets.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5829875/posts/default/5497970554410524171?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5829875/posts/default/5497970554410524171?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/RgrigsBlog/~3/hSJk-jvTyj8/automata-on-infinite-alphabets.html" title="Automata on Infinite Alphabets" /><author><name>Radu Grigore</name><uri>https://profiles.google.com/101644137139656854756</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh4.googleusercontent.com/-qUUZcf9ulqQ/AAAAAAAAAAI/AAAAAAAADnE/AVKMToUdkMQ/s512-c/photo.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://rgrig.blogspot.com/2011/11/automata-on-infinite-alphabets.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C0YMQ3o7eSp7ImA9WhRTF0o.&quot;"><id>tag:blogger.com,1999:blog-5829875.post-6792066322112919571</id><published>2011-11-07T19:29:00.000Z</published><updated>2011-11-08T16:53:02.401Z</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-11-08T16:53:02.401Z</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="research" /><category scheme="http://www.blogger.com/atom/ns#" term="learning" /><title>Group Actions</title><content type="html">&lt;p&gt;&lt;i&gt;The theory of finite automata works with finite alphabets. The article &lt;a href="http://scholar.google.co.uk/scholar?q=automata+with+group+actions"&gt;Automata with Group Actions&lt;/a&gt; by Bojanczyk et al. is one recent attempt to extend the theory to infinite alphabets. To do so, the authors use a basic notion from group theory, namely group action. Here I review the facts about group actions that are necessary to understand Bojanczyk's article.&lt;/i&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;p&gt;Recall that a &lt;i&gt;group&lt;/i&gt; is a set $G$ together with a binary operation that has an identity, is associative, and each element has an inverse:&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;$1 \pi=\pi 1$, for all $\pi \in G$&lt;br /&gt;
&lt;li&gt;$(\pi\sigma)\tau=\pi(\sigma\tau)$, for all $\pi,\sigma,\tau\in G$, and&lt;br /&gt;
&lt;li&gt;there exist a $\pi^{-1}\in G$ such that $\pi\pi^{-1}=\pi^{-1}\pi=1$, for all $\pi\in G$&lt;br /&gt;
&lt;/ul&gt;&lt;p&gt;The typical example of a group is the set of permutations of some set $X$. Its elements have the type $X \to X$. The identity is the identity function. The binary operation is function composition, which is always associative. Each permutation has an inverse almost by definition. (Permutations &lt;i&gt;are&lt;/i&gt; those functions that have inverses.) This group is sometimes denoted $\mathrm{Sym}(X)$ and is called &lt;i&gt;the symmetric group of $X$&lt;/i&gt;.  &lt;p&gt;Recall also that a function $f : G \to H$ is called a &lt;i&gt;homomorphism&lt;/i&gt; when $f(\pi\sigma)=f(\pi)f(\sigma)$ for all $\pi,\sigma \in G$. We say that $f$ &lt;i&gt;preserves the group operation&lt;/i&gt;. In particular, $f(1)=1$ or, more precisely, $f(1_G)=1_H$. In words, homomorphisms map the identity of one group to the identity of the other. This is easy to prove, and makes a nice exercise.  &lt;p&gt;&lt;span style="background:#ffff99"&gt;A &lt;i&gt;group action&lt;/i&gt; is a homomorphism from $G$ to $\mathrm{Sym}(X)$. The set $X$ is called a &lt;i&gt;$G$-Set&lt;/i&gt;.&lt;/span&gt;  &lt;p&gt;The simplest group action is the &lt;i&gt;trivial action&lt;/i&gt;, which maps all elements of $G$ to the identity permutation of $X$,  &lt;p&gt;I know of two reasons why group actions are an interesting concept. First, they let you think of elements of a group $G$ as symmetries of a set $X$ and therefore they partition the set $X$ into equivalence classes. You change the group $G$, you change which elements of $X$ are "essentially the same." Second, once you have group actions for $X$ and $Y$ you also have group actions for $X \times Y$ and $X+Y$ and $X^*$. So group actions build up nicely.  &lt;p&gt;The picture I have in my mind when I talk about G-Sets is a bunch of points (the elements of $X$) with a bunch of arcs between them. Each arc is labelled by an element of $G$. When we look at all arcs labelled by $\pi$ (where $\pi \in G$) we get the picture of a permutation on $X$. That is, a bunch of (disjoint) cycles. When we look at the arcs labelled by $1_G$ we see a loop on each point. In general, we see $|G|$ arcs getting out of each point. This picture has a few more properties. If there is an arc from $x$ to $y$ and one from $y$ to $z$, then there is an arc from $x$ to $z$. In other words, the digraph I'm describing is transitively closed. Proving this property makes another nice exercise. In yet other words, for all $x$ and $y$ either there is an arc from $x$ to $y$ or there is no path from $x$ to $y$. The (strongly) connected components of this graph are the equivalence classes that $G$ determines on $X$. The equivalence class of an element $x \in X$ is called its &lt;i&gt;orbit&lt;/i&gt;. Another property of this graph (the &lt;a href="http://rgrig.blogspot.com/2005/04/counting-colorful-objects-part-1.html"&gt;Burnside lemma&lt;/a&gt;) is that the points in each orbit have exactly $|G|$ loops in total. (Well, I admit: This is not quite the standard formulation.)  &lt;p&gt;To discuss how group actions build up it's useful to finally introduce some (common) notation. We write $x \cdot \pi = y$ when the permutation associated with $\pi \in G$ maps $x \in X$ to $y \in Y$. So, in a way, the dot $\cdot$ represents the (still nameless) group action. Typically, we use the following. &lt;ul&gt;&lt;li&gt;$(x,y) \cdot \pi = (x \cdot \pi, y \cdot \pi)$&lt;br /&gt;
&lt;li&gt;$[x_0,\ldots,x_{n-1}]\cdot \pi = [x_0\cdot\pi,\ldots,x_{n-1}\cdot\pi]$&lt;br /&gt;
&lt;/ul&gt;&lt;p&gt;&lt;span style="background:#ffff99"&gt;A subset $Z$ of $X$ is said to be &lt;i&gt;invariant&lt;/i&gt; (or &lt;i&gt;equivariant&lt;/i&gt;) when it is a union of orbits. Equivalently, $Z$ is said to be invariant when each $\pi \in G$ permutes its elements, that is $Z \cdot \pi = Z$.&lt;/span&gt; (The graph picture is very handy to figure out why these two definitions are equivalent.)  &lt;p&gt;Now suppose that the $G$-Set is $X \times Y$ and we are given a function $f : X \to Y$. We say that $f$ is invariant when the subset $\{\,(x,f(x))\mid x\in X\,\}$ is invariant. In other words, when $$f(x \cdot \pi) = f(x) \cdot \pi$$ for all $x \in X$ and $\pi \in G$. Invariant functions are closed under composition. $G$-&lt;b&gt;Set&lt;/b&gt; is the category of $G$-Sets with the arrows being invariant functions.  &lt;p&gt;How is this at all relevant to finite automata over infinite alphabets? Well, very roughly, a &lt;i&gt;finite&lt;/i&gt; automaton over infinite alphabets is one that cannot distinguish between symmetric traces. For example, an automaton might say that "given two iterators $\alpha$ and $\beta$ on a collection $\gamma$, it is illegal to use $\alpha$ to modify $\gamma$ and &lt;i&gt;then&lt;/i&gt; continue to use $\beta$." The exact values $\alpha$, $\beta$, and $\gamma$ are irrelevant, so if a trace with some values is accepted, then so are all traces obtained by pointwise permuting the values in the trace. I realize this is rather unclear, but I plan to talk about it in a future post.  &lt;p&gt;In the meantime, there are two other nice references on group actions that I know of: &lt;a href="http://en.wikipedia.org/wiki/Group_action"&gt;Wikipedia&lt;/a&gt; and &lt;a href="http://gowers.wordpress.com/2011/11/06/group-actions-i/"&gt;a recent post on Gower's blog&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5829875-6792066322112919571?l=rgrig.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/RgrigsBlog/~4/ijipGDoXJyo" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://rgrig.blogspot.com/feeds/6792066322112919571/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://rgrig.blogspot.com/2011/11/group-actions.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5829875/posts/default/6792066322112919571?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5829875/posts/default/6792066322112919571?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/RgrigsBlog/~3/ijipGDoXJyo/group-actions.html" title="Group Actions" /><author><name>Radu Grigore</name><uri>https://profiles.google.com/101644137139656854756</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh4.googleusercontent.com/-qUUZcf9ulqQ/AAAAAAAAAAI/AAAAAAAADnE/AVKMToUdkMQ/s512-c/photo.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://rgrig.blogspot.com/2011/11/group-actions.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CkcBRnc-fyp7ImA9WhdVEUo.&quot;"><id>tag:blogger.com,1999:blog-5829875.post-4272147386478257482</id><published>2011-09-16T11:47:00.001+01:00</published><updated>2011-09-16T11:47:37.957+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-09-16T11:47:37.957+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="opinion" /><title>Education, Sport, Entertainment</title><content type="html">The summer Olympic Games are less than a year away.&amp;nbsp;In those Games, athletes compete in numerous events, all physical. I saw the term Olympiad used also for non-physical contests, like the International Olympiad in Informatics. I wondered when did people start to refer to&amp;nbsp;intellectual&amp;nbsp;contests as Olympiads, so I tried Wikipedia and … did not find an answer. Instead, I did find out that 'Olympiad'&amp;nbsp;means 'a period of four years.' Strictly speaking, it is erroneous to say 'Olympiad' for the event itself, especially if the event is annual.&lt;br /&gt;
&lt;br /&gt;
Let's move on from etymology to a more interesting issue: What do these events have in common? Both are contests whose participants demonstrate skill levels that seem super-human. For a normal person, just watching the performances can be inspiring and motivating. I believe that this last similarity is key, because it is what makes the events &lt;i&gt;good&lt;/i&gt;.&lt;br /&gt;
&lt;br /&gt;
Let me explain.&lt;br /&gt;
&lt;br /&gt;
If two people say that 'X is good,' they may, nevertheless,disagree. For example, if two people say that Natalie Portman is good, they may mean different things. One may mean she is a good actress but not a particularly good scientist; another may mean she is a good scientist but not a particularly good actress.&amp;nbsp;It is therefore important to say what I mean by good. Briefly, &lt;i&gt;something that benefits humankind&lt;/i&gt;.&lt;br /&gt;
&lt;br /&gt;
So, what exactly is good about the Games? It can't be the extra pollution caused by&amp;nbsp;hordes&amp;nbsp;of people flying to London. It can't be the overcrowded tubes, which will make my life miserable. Could it be the entertainment it provides to so many people? It could, if only it were less expensive. I'm sure there are &lt;a href="http://en.wikipedia.org/wiki/The_Inbetweeners"&gt;cheaper forms of entertainment&lt;/a&gt;, such as watching &lt;a href="http://www.youtube.com/watch?v=txqiwrbYGrs"&gt;silly videos on YouTube&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
So what is it?&lt;br /&gt;
&lt;br /&gt;
Every performance, such as a movie, a dance, or a football game, makes people feel good while watching. More importantly, some performances have a lasting effect. Some movies haunt you for a long time and make you think about certain aspects of life. Beckham and Hagi inspired a whole generation to &lt;i&gt;play&lt;/i&gt; football (in UK and Romania, respectively). That is one healthier generation than it could have been. Yes, the effects of one particular performance on one particular individual are small, but the effects add up.&lt;br /&gt;
&lt;br /&gt;
In my mind, by far the most important contributions to society of the Olympic Games are the following.&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;promoting exercise and hence a healthier life-style&lt;/li&gt;
&lt;li&gt;promoting fair-play&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
Identifying elites? A means to an end.&amp;nbsp;The skills that awe us are not even the skills most useful to society. Schumacher is a good driver, but do we really think it would be good for society if all drivers would have his skills? The bus driver who takes children to school for 40 years &lt;i&gt;without any accident&lt;/i&gt; is less awe&amp;nbsp;inspiring, but his skills definitely benefit the lives of the many children he transports. Yes, there is &lt;i&gt;some&lt;/i&gt; correlation between the two skills.&lt;br /&gt;
&lt;br /&gt;
And so it is with intellectual contests.&lt;br /&gt;
&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5829875-4272147386478257482?l=rgrig.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/RgrigsBlog/~4/2SFJ_VAKSvo" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://rgrig.blogspot.com/feeds/4272147386478257482/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://rgrig.blogspot.com/2011/09/education-sport-entertainment.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5829875/posts/default/4272147386478257482?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5829875/posts/default/4272147386478257482?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/RgrigsBlog/~3/2SFJ_VAKSvo/education-sport-entertainment.html" title="Education, Sport, Entertainment" /><author><name>Radu Grigore</name><uri>https://profiles.google.com/101644137139656854756</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh4.googleusercontent.com/-qUUZcf9ulqQ/AAAAAAAAAAI/AAAAAAAADnE/AVKMToUdkMQ/s512-c/photo.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://rgrig.blogspot.com/2011/09/education-sport-entertainment.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C0MAQ3s9eip7ImA9WhdQF0w.&quot;"><id>tag:blogger.com,1999:blog-5829875.post-350732006479329734</id><published>2011-08-18T00:17:00.001+01:00</published><updated>2011-08-19T00:50:42.562+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-08-19T00:50:42.562+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="coding" /><title>Putting Formulas in Normal Form</title><content type="html">&lt;p&gt;&lt;i&gt;What would be a beautiful description for conversion to DNF?&lt;/i&gt;

&lt;p&gt;The problem of converting a formula to
&lt;a href="http://en.wikipedia.org/wiki/Disjunctive_normal_form"&gt;DNF&lt;/a&gt;
is easy to explain:
Given a boolean formula, write it as a disjunction of conjunctions.
For example, $(x \lor y) \land z$ may be rewritten, by distributivity,
as $(x \land z) \lor (y \land z)$. The mechanism is also easy to describe:
Push $\lnot$ down by
&lt;a href="http://en.wikipedia.org/wiki/De_Morgan's_laws"&gt;de Morgan&lt;/a&gt;, then
pull $\lor$ above $\land$ by
&lt;a href="http://en.wikipedia.org/wiki/Boolean_algebra_(structure)#Definition"&gt;
distributivity&lt;/a&gt;.

&lt;p&gt;How to turn this description into an algorithm?

&lt;p&gt;I know a nice algorithm for the first half. Expressed in OCaml, it goes
like this: We want a function with the type &lt;code&gt;f1-&amp;gt;f2&lt;/code&gt;, where

&lt;pre class="prettyprint lang-ml"&gt;
type f1 = [`Var of string | `Not of f1 | `And of f1 list | `Or of f1 list]
type f2 = [`Pos of string | `Neg of string | `And of f2 list | `Or of f2 list]
&lt;/pre&gt;

&lt;p&gt;The trick is to keep around a &lt;i&gt;parity&lt;/i&gt;.

&lt;pre class="prettyprint lang-ml"&gt;
let rec pnd (p : bool) : f1 -&amp;gt; f2 = function
  | `Var x -&amp;gt; if p then `Pos x else `Neg x
  | `Not f -&amp;gt; pnd (not p) f
  | `And fs -&amp;gt;
      let fs = List.map (pnd p) fs in
      if p then `And fs else `Or fs
  | `Or fs -&amp;gt;
      let fs = List.map (pnd p) fs in
      if p then `Or fs else `And fs
&lt;/pre&gt;

&lt;p&gt;This algorithm I use when I do boolean manipulations on paper. So I like it.
The code is nice, rather than beautiful, because it has some repetition.

&lt;p&gt;What would be a similarly nice solution for the second half&amp;mdash;applying
distributivity? Expressed in OCaml, we want a function with the type
&lt;code&gt;f2-&amp;gt;dnf&lt;/code&gt;, where

&lt;pre class="prettyprint lang-ml"&gt;
type dnf = [`Pos of string | `Neg of string] list list
&lt;/pre&gt;

&lt;p&gt;Of course, I'm interested in solutions in &lt;i&gt;any&lt;/i&gt; language.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5829875-350732006479329734?l=rgrig.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/RgrigsBlog/~4/YY1Fzhp2IOw" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://rgrig.blogspot.com/feeds/350732006479329734/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://rgrig.blogspot.com/2011/08/putting-formulas-in-normal-form.html#comment-form" title="5 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5829875/posts/default/350732006479329734?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5829875/posts/default/350732006479329734?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/RgrigsBlog/~3/YY1Fzhp2IOw/putting-formulas-in-normal-form.html" title="Putting Formulas in Normal Form" /><author><name>Radu Grigore</name><uri>https://profiles.google.com/101644137139656854756</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh4.googleusercontent.com/-qUUZcf9ulqQ/AAAAAAAAAAI/AAAAAAAADnE/AVKMToUdkMQ/s512-c/photo.jpg" /></author><thr:total>5</thr:total><feedburner:origLink>http://rgrig.blogspot.com/2011/08/putting-formulas-in-normal-form.html</feedburner:origLink></entry><entry gd:etag="W/&quot;Dk8MRXwzeyp7ImA9WhdQFU0.&quot;"><id>tag:blogger.com,1999:blog-5829875.post-4082522451702813471</id><published>2011-08-16T15:23:00.001+01:00</published><updated>2011-08-16T15:28:04.283+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-08-16T15:28:04.283+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="coding" /><title>Loops and Side-effects</title><content type="html">&lt;p&gt;&lt;i&gt;TeX has a better looping construct.&lt;/i&gt;

&lt;p&gt;I designed a small Java-like language for some experiments. I think it is a good idea to be able to say &amp;quot;this piece of code has no side-effects.&amp;quot; (If you saw how I write C/++, you'd probably be surprised by what I just said.) There are various ways of isolating side-effects. My requirements were that (1)&amp;nbsp;it must look much like Java and (2)&amp;nbsp;there should be some way to contain side-effects. So I simply banned side-effects from &lt;i&gt;expressions&lt;/i&gt;.

&lt;p&gt;Then I proceeded to translate the following Java code.

&lt;pre class="prettyprint"&gt;
while (i.hasNext()) {
  Object o = i.next();
  // bla
}
&lt;/pre&gt;

&lt;p&gt;Method calls, however, possibly have side-effects so I could not use them in expressions. A method call is a &lt;i&gt;statement&lt;/i&gt; in my toy language.

&lt;pre class="prettyprint"&gt;
while (true) {
  boolean c = i.hasNext();
  if (!c) break;
  Object o = i.next();
  // bla
}
&lt;/pre&gt;

&lt;p&gt;This loop reminded me of &lt;tt&gt;\loop ... \if ... \repeat&lt;/tt&gt; in $\TeX$. The keywords &lt;tt&gt;loop&lt;/tt&gt; and &lt;tt&gt;repeat&lt;/tt&gt;, however, are rather un-Java-like-esque. So I decided to say &lt;code class=prettyprint&gt;do {...} while (...) {...}&lt;/code&gt;. This way, the normal &lt;code class=prettyprint&gt;do&lt;/code&gt;-loop and the &lt;code class=prettyprint&gt;while&lt;/code&gt;-loop are special cases obtained by omitting one of the bodies.

&lt;pre class=prettyprint&gt;
do boolean c = i.hasNext()
while (c) {
  Object o = i.next();
  // bla
}
&lt;/pre&gt;

&lt;p&gt;Note that in Java (and C/++) one has the &lt;i&gt;illusion&lt;/i&gt; that loops test their condition at the beginning (&lt;code class=prettyprint&gt;while&lt;/code&gt;) or at the end (&lt;code class=prettyprint&gt;do&lt;/code&gt;) but never in the middle. This is not true, because expressions may have side-effects.

&lt;p&gt;If languages would have &lt;code class=prettyprint&gt;do-while&lt;/code&gt;-loops, then I'd probably &lt;code class=prettyprint&gt;break&lt;/code&gt; far less often.

&lt;p&gt;I decided to write this post after seeing another &lt;a href="http://blog.frama-c.com/index.php?post/2011/08/14/begin-while-repeat"&gt;post about how to write a &lt;i&gt;similar&lt;/i&gt; kind of loop in OCaml&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5829875-4082522451702813471?l=rgrig.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/RgrigsBlog/~4/0V5uRy013R4" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://rgrig.blogspot.com/feeds/4082522451702813471/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://rgrig.blogspot.com/2011/08/loops-and-side-effects.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5829875/posts/default/4082522451702813471?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5829875/posts/default/4082522451702813471?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/RgrigsBlog/~3/0V5uRy013R4/loops-and-side-effects.html" title="Loops and Side-effects" /><author><name>Radu Grigore</name><uri>https://profiles.google.com/101644137139656854756</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh4.googleusercontent.com/-qUUZcf9ulqQ/AAAAAAAAAAI/AAAAAAAADnE/AVKMToUdkMQ/s512-c/photo.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://rgrig.blogspot.com/2011/08/loops-and-side-effects.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DkAMRHc6cSp7ImA9WhZbGEo.&quot;"><id>tag:blogger.com,1999:blog-5829875.post-3195768190507377853</id><published>2011-06-24T01:19:00.000+01:00</published><updated>2011-06-24T01:19:45.919+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-06-24T01:19:45.919+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="research" /><category scheme="http://www.blogger.com/atom/ns#" term="learning" /><title>In Praise of Algebra</title><content type="html">&lt;p&gt;&lt;i&gt;Yesterday was Turing's 99th birthday. By coincidence, we had a treat at Queen Mary &amp;mdash; a talk by C.A.R.&amp;nbsp;Hoare. This is a very brief summary of what was said.&lt;/i&gt;

&lt;p&gt;Consider an algebra whose variables range over (possibly non-deterministic) programs:
&lt;ul&gt;
&lt;li&gt;$p;q$ denotes the sequential composition of $p$ and $q$
&lt;li&gt;$p*q$ denotes the parallel composition of $p$ and $q$
&lt;/ul&gt;
and
&lt;ul&gt;
&lt;li&gt;$p \le q$ means that all possible executions of $p$ are also possible executions of $q$
&lt;/ul&gt;

&lt;p&gt;Several obvious properties follow from our intuition of what programs are, so we choose to make them axioms.
&lt;ol&gt;
&lt;li&gt;$*$ is commutative: $p*q=q*p$
&lt;li&gt;$*$ and $;$ are associative: $(p\circ q)\circ r = p\circ(q\circ r)$, where $\circ$ stands for $*$ or $;$
&lt;li&gt;$\le$ is a &lt;a href="http://en.wikipedia.org/wiki/Partial_order#Formal_definition"&gt;partial order&lt;/a&gt;
&lt;li&gt;$*$ and $;$ are monotonic: if $p\le p'$ and $q\le q'$, then $p\circ q\le p'\circ q'$ 
&lt;li&gt;the exchange law: $(p*q);(r*s) \le (p;r)*(q;s)$
&lt;li&gt;the empty program $\varepsilon$ is an identity for both $*$ and $;$
&lt;/ol&gt;

&lt;p&gt;Now it is possible to &lt;i&gt;define&lt;/i&gt; Hoare triples as follows.
$$\{p\}\,q\,\{r\} \;\;=\;\; p;q \le r$$
The fun begins: Several axioms of Hoare triples follow from the algebra. For example, the rule of consequence
$$p'\le p\quad\text{and}\quad\{p\}\,q\,\{r\}\quad\text{and}\quad r\le r'\qquad\text{imply}\qquad \{p'\}\,q\,\{r'\}$$
is true because
$$
\begin{align}
&amp;\{p'\}\,q\,\{r'\}\\
=&amp; p';q \le r'\\
\Leftarrow&amp; p';q \le r \land r \le r' \\
\Leftarrow&amp; p' \le p \land p;q \le r \land r \le r' \\
=&amp; p' \le p \land \{p\}\,q\,\{r\} \land r \le r'
\end{align}
$$

&lt;p&gt;By symmetry, there are other triples one might wish to define.
$$\begin{align}
&amp;p\le q;r \\
&amp;p;q\ge r \\
&amp;p\ge q;r
\end{align}$$
It turns out that two of these lead to laws associated with Plotkin triples (reduction in structural operational semantics) and, respectively, Dijkstra triples (`going backwards'). The other triple is new.

&lt;p&gt;In summary, this algebra acts as a meeting point for various approaches to defining semantics for languages.

&lt;p&gt;To see what are the consequences of the exchange law, how weakening the axioms allows various useful models, and a lot more see: &lt;a href="http://www.eecs.qmul.ac.uk/~rusmus/articles/LocalityBimonoid.pdf"&gt;C.A.R.&amp;nbsp;Hoare, A.&amp;nbsp;Hussain, B.&amp;nbsp;Moller, P.W.&amp;nbsp;O'Hearn, R.L.&amp;nbsp;Petersen, Struth, &lt;i&gt;On Locality and the Exchange Law for Concurrent Processes&lt;/i&gt;&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5829875-3195768190507377853?l=rgrig.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/RgrigsBlog/~4/kj_PCFQEFNc" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://rgrig.blogspot.com/feeds/3195768190507377853/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://rgrig.blogspot.com/2011/06/in-praise-of-algebra.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5829875/posts/default/3195768190507377853?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5829875/posts/default/3195768190507377853?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/RgrigsBlog/~3/kj_PCFQEFNc/in-praise-of-algebra.html" title="In Praise of Algebra" /><author><name>Radu Grigore</name><uri>https://profiles.google.com/101644137139656854756</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh4.googleusercontent.com/-qUUZcf9ulqQ/AAAAAAAAAAI/AAAAAAAADnE/AVKMToUdkMQ/s512-c/photo.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://rgrig.blogspot.com/2011/06/in-praise-of-algebra.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DkQFQnc-cCp7ImA9WhZREEQ.&quot;"><id>tag:blogger.com,1999:blog-5829875.post-5079639623736881152</id><published>2011-04-01T11:39:00.005+01:00</published><updated>2011-04-06T13:51:53.958+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-04-06T13:51:53.958+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="random" /><category scheme="http://www.blogger.com/atom/ns#" term="coding" /><title>Some Random Code Metrics</title><content type="html">&lt;p&gt;&lt;i&gt;How compressible is source code? What is the average size of a file? The answers to these and other useless questions are born from too much caffeine.&lt;/i&gt;

&lt;p&gt;&lt;b&gt;The projects:&lt;/b&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="http://ant.apache.org/"&gt;Ant&lt;/a&gt;: A build system used by many Java projects, which is itself written in Java.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.python.org/getit/"&gt;CPython&lt;/a&gt;: The reference Python implementation, written in C.&lt;/li&gt;
&lt;li&gt;&lt;a href=""&gt;Frama-C&lt;/a&gt;: Analyzers of C programs, written themselves mostly in OCaml.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://code.google.com/p/freeboogie/"&gt;FreeBoogie&lt;/a&gt;: A project of mine written in Java.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.haskell.org/ghc/"&gt;GHC&lt;/a&gt;: The most used Haskell compiler, written in Haskell.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.jedit.org/"&gt;jEdit&lt;/a&gt;: A nice source code editor, written in Java.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://kernel.org/"&gt;Linux&lt;/a&gt;: An operating system macro-kernel, written in C.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://caml.inria.fr/"&gt;OCaml&lt;/a&gt;: Compiler, standard library, and related tools for the language OCaml, written in OCaml.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www-cs-faculty.stanford.edu/~uno/sgb.html"&gt;SGB&lt;/a&gt;: A library for handling graphs and a few example algorithms written by Knuth in CWEB.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;b&gt;Methodology.&lt;/b&gt; Get the repo, spend $\le 1$&amp;nbsp;min choosing a subset of files that look like &amp;quot;the source&amp;quot;, run a few quick commands in the shell, don't check the results. That's so you know how much you can trust what follows. Nevertheless, it's likely I got the orders of magnitude right.

&lt;p&gt;&lt;b&gt;Project size contest.&lt;/b&gt; The most common measure for a project's size is the number of lines of code. This comes with plenty of caveats. In any case, if we define &amp;quot;lines of code&amp;quot; to be &amp;quot;number of '\n' characters in the files that Radu happened to choose as the 'source'&amp;quot; then here are the results:

&lt;ol&gt;
&lt;li&gt;Linux: 9.1 million&lt;/li&gt;
&lt;li&gt;GHC: 460 thousand&lt;/li&gt;
&lt;li&gt;CPython: 450 thousand&lt;/li&gt;
&lt;li&gt;OCaml: 260 thousand&lt;/li&gt;
&lt;li&gt;Ant: 200 thousand&lt;/li&gt;
&lt;li&gt;jEdit: 160 thousand&lt;/li&gt;
&lt;li&gt;Frama-C: 126 thousand&lt;/li&gt;
&lt;li&gt;SGB: 19 thousand&lt;/li&gt;
&lt;li&gt;FreeBoogie: 8 thousand&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;There's an alternative measure that I like much better and that is not used much: the compressed size of the source code. Why do I like it? Because it should make a good proxy for the information content in the source code. For example, it doesn't matter much if coders use space indentation or tab indentation, long lines or short line, etc. There are plenty of caveats here too. For example, it is likely that the true information content (say, Kolmogorov complexity) is much lower, and that would be apparent if compressers would exploit the structure of the language in which the code is written.

&lt;p&gt;Anyway, here is the bzip2 size of the projects.

&lt;ol&gt;
&lt;li&gt;Linux: 45 MB&lt;/li&gt;
&lt;li&gt;GHC: 4.3 MB&lt;/li&gt;
&lt;li&gt;CPython: 2.0 MB&lt;/li&gt;
&lt;li&gt;OCaml: 1.2 MB&lt;/li&gt;
&lt;li&gt;Ant: 930 kB&lt;/li&gt;
&lt;li&gt;Frama-C: 735 kB&lt;/li&gt;
&lt;li&gt;jEdit: 690 kB&lt;/li&gt;
&lt;li&gt;SGB: 190 kB&lt;/li&gt;
&lt;li&gt;FreeBoogie: 50 kB&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;b&gt;File size contest.&lt;/b&gt; All these projects are broken up into files, which roughly correspond to modules or abstraction boundaries. The idea is that you should be able to focus on the internals of one file at a time without needing to know too much about the other files. And that is true of the compiler too, not only of you. Or, at least, that's one way to look at it.

&lt;p&gt;So, lines per file contest:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;CPython: 860&lt;/li&gt;
&lt;li&gt;Linux: 680&lt;/li&gt;
&lt;li&gt;SGB: 580&lt;/li&gt;
&lt;li&gt;OCaml: 330&lt;/li&gt;
&lt;li&gt;jEdit: 330&lt;/li&gt;
&lt;li&gt;Frama-C. 300&lt;/li&gt;
&lt;li&gt;GHC: 280&lt;/li&gt;
&lt;li&gt;Ant: 260&lt;/li&gt;
&lt;li&gt;FreeBoogie: 140&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;And compressed bytes per file contest:

&lt;ol&gt;
&lt;li&gt;SGB: 5900 B&lt;/li&gt;
&lt;li&gt;CPython: 3700 B&lt;/li&gt;
&lt;li&gt;Linux: 3300 B&lt;/li&gt;
&lt;li&gt;GHC: 2600 B&lt;/li&gt;
&lt;li&gt;Frama-C: 1700 B&lt;/li&gt;
&lt;li&gt;OCaml: 1500 B&lt;/li&gt;
&lt;li&gt;jEdit: 1400 B&lt;/li&gt;
&lt;li&gt;Ant: 1200 B&lt;/li&gt;
&lt;li&gt;FreeBoogie: 780 B&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;b&gt;Information density.&lt;/b&gt; So, which project should I read if I want to get most per byte? And which one can be read on the bus without missing much? Well, here's information per character (where information is &amp;quot;measured&amp;quot; as earlier: compressed size, so these are basically inverses of compression ratios).

&lt;ol&gt;
&lt;li&gt;SGB: 0.25&lt;/li&gt;
&lt;li&gt;GHC: 0.21&lt;/li&gt;
&lt;li&gt;FreeBoogie: 0.19&lt;/li&gt;
&lt;li&gt;Linux: 0.18&lt;/li&gt;
&lt;li&gt;Frama-C: 0.16&lt;/li&gt;
&lt;li&gt;jEdit: 0.16&lt;/li&gt;
&lt;li&gt;CPython: 0.15&lt;/li&gt;
&lt;li&gt;OCaml: 0.14&lt;/li&gt;
&lt;li&gt;Ant: 0.14&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Looks like GHC is almost as incompressible as the code Knuth writes.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5829875-5079639623736881152?l=rgrig.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/RgrigsBlog/~4/kC5lBTwj1oo" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://rgrig.blogspot.com/feeds/5079639623736881152/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://rgrig.blogspot.com/2011/04/some-random-code-metrics.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5829875/posts/default/5079639623736881152?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5829875/posts/default/5079639623736881152?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/RgrigsBlog/~3/kC5lBTwj1oo/some-random-code-metrics.html" title="Some Random Code Metrics" /><author><name>Radu Grigore</name><uri>https://profiles.google.com/101644137139656854756</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh4.googleusercontent.com/-qUUZcf9ulqQ/AAAAAAAAAAI/AAAAAAAADnE/AVKMToUdkMQ/s512-c/photo.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://rgrig.blogspot.com/2011/04/some-random-code-metrics.html</feedburner:origLink></entry><entry gd:etag="W/&quot;D0YASXs-fip7ImA9Wx9bEEk.&quot;"><id>tag:blogger.com,1999:blog-5829875.post-757661385680405673</id><published>2011-02-18T16:05:00.001Z</published><updated>2011-02-18T16:05:48.556Z</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-02-18T16:05:48.556Z</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="random" /><title>People and Conferences ≥2000</title><content type="html">&lt;a href="http://www.wordle.net/show/wrdl/3174701/tacas%3E%3D2010" 
          title="Wordle: tacas&amp;gt;=2010"&gt;&lt;img
          src="http://www.wordle.net/thumb/wrdl/3174701/tacas%3E%3D2010"
          alt="Wordle: tacas&amp;gt;=2010"
          style="padding:4px;border:1px solid #ddd"&gt;&lt;/a&gt;
    &lt;a href="http://www.wordle.net/show/wrdl/3174866/aaai2000" 
          title="Wordle: aaai2000"&gt;&lt;img
          src="http://www.wordle.net/thumb/wrdl/3174866/aaai2000"
          alt="Wordle: aaai2000"
          style="padding:4px;border:1px solid #ddd"&gt;&lt;/a&gt;
        &lt;a href="http://www.wordle.net/show/wrdl/3174900/cav2000" 
          title="Wordle: cav2000"&gt;&lt;img
          src="http://www.wordle.net/thumb/wrdl/3174900/cav2000"
          alt="Wordle: cav2000"
          style="padding:4px;border:1px solid #ddd"&gt;&lt;/a&gt;
&lt;a href="http://www.wordle.net/show/wrdl/3174943/ijcai2000" 
          title="Wordle: ijcai2000"&gt;&lt;img
          src="http://www.wordle.net/thumb/wrdl/3174943/ijcai2000"
          alt="Wordle: ijcai2000"
          style="padding:4px;border:1px solid #ddd"&gt;&lt;/a&gt;
&lt;a href="http://www.wordle.net/show/wrdl/3174999/lics2000" 
          title="Wordle: lics2000"&gt;&lt;img
          src="http://www.wordle.net/thumb/wrdl/3174999/lics2000"
          alt="Wordle: lics2000"
          style="padding:4px;border:1px solid #ddd"&gt;&lt;/a&gt;
 &lt;a href="http://www.wordle.net/show/wrdl/3175061/icalp2000" 
          title="Wordle: icalp2000"&gt;&lt;img
          src="http://www.wordle.net/thumb/wrdl/3175061/icalp2000"
          alt="Wordle: icalp2000"
          style="padding:4px;border:1px solid #ddd"&gt;&lt;/a&gt;
&lt;a href="http://www.wordle.net/show/wrdl/3175075/cade2000" 
          title="Wordle: cade2000"&gt;&lt;img
          src="http://www.wordle.net/thumb/wrdl/3175075/cade2000"
          alt="Wordle: cade2000"
          style="padding:4px;border:1px solid #ddd"&gt;&lt;/a&gt;
&lt;a href="http://www.wordle.net/show/wrdl/3175089/oopsla2000" 
          title="Wordle: oopsla2000"&gt;&lt;img
          src="http://www.wordle.net/thumb/wrdl/3175089/oopsla2000"
          alt="Wordle: oopsla2000"
          style="padding:4px;border:1px solid #ddd"&gt;&lt;/a&gt;
&lt;a href="http://www.wordle.net/show/wrdl/3175101/fse2000" 
          title="Wordle: fse2000"&gt;&lt;img
          src="http://www.wordle.net/thumb/wrdl/3175101/fse2000"
          alt="Wordle: fse2000"
          style="padding:4px;border:1px solid #ddd"&gt;&lt;/a&gt;
&lt;a href="http://www.wordle.net/show/wrdl/3175124/focs2000" 
          title="Wordle: focs2000"&gt;&lt;img
          src="http://www.wordle.net/thumb/wrdl/3175124/focs2000"
          alt="Wordle: focs2000"
          style="padding:4px;border:1px solid #ddd"&gt;&lt;/a&gt;
&lt;a href="http://www.wordle.net/show/wrdl/3175144/popl2000" 
          title="Wordle: popl2000"&gt;&lt;img
          src="http://www.wordle.net/thumb/wrdl/3175144/popl2000"
          alt="Wordle: popl2000"
          style="padding:4px;border:1px solid #ddd"&gt;&lt;/a&gt;
&lt;a href="http://www.wordle.net/show/wrdl/3175159/soda2000" 
          title="Wordle: soda2000"&gt;&lt;img
          src="http://www.wordle.net/thumb/wrdl/3175159/soda2000"
          alt="Wordle: soda2000"
          style="padding:4px;border:1px solid #ddd"&gt;&lt;/a&gt;
&lt;a href="http://www.wordle.net/show/wrdl/3175171/icse2000" 
          title="Wordle: icse2000"&gt;&lt;img
          src="http://www.wordle.net/thumb/wrdl/3175171/icse2000"
          alt="Wordle: icse2000"
          style="padding:4px;border:1px solid #ddd"&gt;&lt;/a&gt;
&lt;a href="http://www.wordle.net/show/wrdl/3175187/aosd2000" 
          title="Wordle: aosd2000"&gt;&lt;img
          src="http://www.wordle.net/thumb/wrdl/3175187/aosd2000"
          alt="Wordle: aosd2000"
          style="padding:4px;border:1px solid #ddd"&gt;&lt;/a&gt;
&lt;a href="http://www.wordle.net/show/wrdl/3175211/esop2000" 
          title="Wordle: esop2000"&gt;&lt;img
          src="http://www.wordle.net/thumb/wrdl/3175211/esop2000"
          alt="Wordle: esop2000"
          style="padding:4px;border:1px solid #ddd"&gt;&lt;/a&gt;
&lt;a href="http://www.wordle.net/show/wrdl/3175225/pldi2000" 
          title="Wordle: pldi2000"&gt;&lt;img
          src="http://www.wordle.net/thumb/wrdl/3175225/pldi2000"
          alt="Wordle: pldi2000"
          style="padding:4px;border:1px solid #ddd"&gt;&lt;/a&gt;
&lt;a href="http://www.wordle.net/show/wrdl/3175235/stoc2000" 
          title="Wordle: stoc2000"&gt;&lt;img
          src="http://www.wordle.net/thumb/wrdl/3175235/stoc2000"
          alt="Wordle: stoc2000"
          style="padding:4px;border:1px solid #ddd"&gt;&lt;/a&gt;
&lt;a href="http://www.wordle.net/show/wrdl/3175247/ecoop2000" 
          title="Wordle: ecoop2000"&gt;&lt;img
          src="http://www.wordle.net/thumb/wrdl/3175247/ecoop2000"
          alt="Wordle: ecoop2000"
          style="padding:4px;border:1px solid #ddd"&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5829875-757661385680405673?l=rgrig.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/RgrigsBlog/~4/igs6Jspsb0s" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://rgrig.blogspot.com/feeds/757661385680405673/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://rgrig.blogspot.com/2011/02/people-and-conferences.html#comment-form" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5829875/posts/default/757661385680405673?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5829875/posts/default/757661385680405673?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/RgrigsBlog/~3/igs6Jspsb0s/people-and-conferences.html" title="People and Conferences &amp;ge;2000" /><author><name>Radu Grigore</name><uri>https://profiles.google.com/101644137139656854756</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh4.googleusercontent.com/-qUUZcf9ulqQ/AAAAAAAAAAI/AAAAAAAADnE/AVKMToUdkMQ/s512-c/photo.jpg" /></author><thr:total>1</thr:total><feedburner:origLink>http://rgrig.blogspot.com/2011/02/people-and-conferences.html</feedburner:origLink></entry><entry gd:etag="W/&quot;A0cNRHY9fyp7ImA9Wx9REkg.&quot;"><id>tag:blogger.com,1999:blog-5829875.post-734295761465629938</id><published>2010-12-13T16:51:00.000Z</published><updated>2010-12-13T16:51:35.867Z</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-12-13T16:51:35.867Z</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="research" /><title>A Small jStar Demo</title><content type="html">&lt;object width="640" height="505"&gt;&lt;param name="movie" value="http://www.youtube.com/v/Sapg5Kfwqe0?fs=1&amp;amp;hl=en_GB&amp;amp;hd=1&amp;amp;color1=0x006699&amp;amp;color2=0x54abd6"&gt;&lt;/param&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;/param&gt;&lt;param name="allowscriptaccess" value="always"&gt;&lt;/param&gt;&lt;embed src="http://www.youtube.com/v/Sapg5Kfwqe0?fs=1&amp;amp;hl=en_GB&amp;amp;hd=1&amp;amp;color1=0x006699&amp;amp;color2=0x54abd6" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="640" height="505"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5829875-734295761465629938?l=rgrig.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/RgrigsBlog/~4/1mu1A2hajw0" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://rgrig.blogspot.com/feeds/734295761465629938/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://rgrig.blogspot.com/2010/12/small-jstar-demo.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5829875/posts/default/734295761465629938?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5829875/posts/default/734295761465629938?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/RgrigsBlog/~3/1mu1A2hajw0/small-jstar-demo.html" title="A Small jStar Demo" /><author><name>Radu Grigore</name><uri>https://profiles.google.com/101644137139656854756</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh4.googleusercontent.com/-qUUZcf9ulqQ/AAAAAAAAAAI/AAAAAAAADnE/AVKMToUdkMQ/s512-c/photo.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://rgrig.blogspot.com/2010/12/small-jstar-demo.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DEUHRXs_fCp7ImA9Wx9SFkU.&quot;"><id>tag:blogger.com,1999:blog-5829875.post-5954282594063417055</id><published>2010-12-07T01:43:00.000Z</published><updated>2010-12-07T01:43:54.544Z</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-12-07T01:43:54.544Z</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="opinion" /><title>Old and New</title><content type="html">&lt;p&gt;&lt;i&gt;This is an unusual post&amp;mdash;imprecise, written late in the night, with no apparent purpose, and no apparent question. As I said, it is unusual. Not for the web, but for this blog.&lt;/i&gt;


&lt;p&gt;All else being equal, and sometimes even when all things are not equal, some
prefer old over new and others prefer new over old. Suppose you may choose
between reusing a piece of code and writing it yourself. Suppose further that
you have no objective reason to believe one option is better than the other.
It is not clear that reusing old code will ensure you will have fewer bugs to
fix in the future, since, obviously, you are an awesome programmer. (After all,
you are reading this blog and recommending it to others. Nah. Forget that.  I'm
drunk. Really.) Back to the subject: You are awesome. I'd like to meet you.
No. That was not the subject. Oh, right! So it's not clear that the old code
you may reuse has very few bugs. There is also no obvious reason why you should
be able to write more efficient code. That may be the case if your problem is a
specialization of a general problem solved by the existing code. But that is
not the case. Your problem is just as general as the existing library was
designed to handle. But, wait! The library is there. Surely it must be quicker
to just use it? No, it is not clear. Apparently you must coerce your build
system through some hoops in order to accommodate the existing code. And you do
need to write a &amp;quot;little&amp;quot; glue code. Just how little is
&amp;quot;little&amp;quot; is hard to say. In short, as I said, you really have no idea
of what would be better: to reuse or to write from scratch?

&lt;p&gt;Yet, in spite of all I wrote above, I bet you &lt;i&gt;know&lt;/i&gt; what is the right
thing to do. You feel like telling me, like it is obvious.  However, I am
willing to bet that all your arguments have a counterfactual or philosophical
flavor.  Depending on who you are, you may feel like telling me that reusing
code is the right thing to do, because it surely cannot be right for humans to
keep reinventing wheels. We need to focus on the new stuff, right?  &amp;quot;No.
No.  No.&amp;quot; yells the other reader. It is much better to write the code
yourself.  In the long run, your purpose is to become a better programmer, and
not writing the code yourself means giving up a great learning experience.

&lt;p&gt;The point is that most people either prefer the old, or prefer the new&amp;mdash;very few are indifferent. I
happen to be in the former camp, but this is beside the point. I wonder if
psychologists know what I am talking about.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5829875-5954282594063417055?l=rgrig.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/RgrigsBlog/~4/3xUngdObu1w" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://rgrig.blogspot.com/feeds/5954282594063417055/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://rgrig.blogspot.com/2010/12/old-and-new.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5829875/posts/default/5954282594063417055?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5829875/posts/default/5954282594063417055?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/RgrigsBlog/~3/3xUngdObu1w/old-and-new.html" title="Old and New" /><author><name>Radu Grigore</name><uri>https://profiles.google.com/101644137139656854756</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh4.googleusercontent.com/-qUUZcf9ulqQ/AAAAAAAAAAI/AAAAAAAADnE/AVKMToUdkMQ/s512-c/photo.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://rgrig.blogspot.com/2010/12/old-and-new.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CEEASHk8eSp7ImA9Wx9SE0Q.&quot;"><id>tag:blogger.com,1999:blog-5829875.post-3523092535540829345</id><published>2010-12-03T16:10:00.000Z</published><updated>2010-12-03T16:10:49.771Z</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-12-03T16:10:49.771Z</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="coding" /><title>More OCaml Pretty-Printing</title><content type="html">&lt;p&gt;&lt;i&gt;How to print expressions with binary operators using as few
parentheses as possible. In this post, we avoid parentheses that are
rendered unnecessary by precedence rules.&lt;/i&gt;&lt;/p&gt;

&lt;p&gt;Consider the following type.

&lt;pre class="prettyprint lang-ml"&gt;
type op = Plus | Times
type expr = Op of op * expr list | I of int
&lt;/pre&gt;

&lt;p&gt;And here is a value:

&lt;pre class="prettyprint lang-ml"&gt;
let v = Op (Plus, [I 3; Op (Times, [I 5; I 7; Op (Plus, [I 4; I 2])]); I 2])
&lt;/pre&gt;

&lt;p&gt;If we don't care about how many parentheses are printed, we'd write

&lt;pre class="prettyprint lang-ml"&gt;
open Format

let op2s = function Plus -&amp;gt; '+' | Times -&amp;gt; '*'

let rec pp_list sep pp ppf = function
  | [] -&amp;gt; ()
  | [x] -&amp;gt; fprintf ppf "%a" pp x
  | x::xs -&amp;gt; fprintf ppf "%a%c%a" pp x sep (pp_list sep pp) xs

let rec pp ppf = function
  | Op (o, es) -&amp;gt; fprintf ppf "@[(%a)@]@," (pp_list (op2s o) pp) es
  | I x -&amp;gt; fprintf ppf "%d@," x

let _ = pp std_formatter v
&lt;/pre&gt;

&lt;p&gt;The rule for precedence is simple: It's safe to strip parentheses in
$(A \circ B) \bullet C$ if and only if $\circ$ has higher precedence than
$\bullet$. It would be nice to isolate the code that decides whether
parentheses are needed. We begin by removing grouping concerns from 
&lt;code class="prettyprint lang-ml"&gt;pp&lt;/code&gt;.

&lt;pre class="prettyprint lang-ml"&gt;
let pp r ppf = function
  | Op (o, es) -&amp;gt; pp_list (op2s o) r ppf es
  | I x -&amp;gt; fprintf ppf "%d" x
&lt;/pre&gt;

&lt;p&gt;We can recover parentheses everywhere with a simple 
&lt;a href="http://en.wikipedia.org/wiki/Fixed_point_combinator"&gt;Y-like
combinator&lt;/a&gt;.

&lt;pre class="prettyprint lang-ml"&gt;
let rec y1 f ppf x = fprintf ppf "@[(%a)@]@," (f (y1 f)) x
let pp1 = y1 pp
let _ = pp1 std_formatter v
&lt;/pre&gt;

&lt;p&gt;Now &lt;code class="prettyprint lang-ml"&gt;pp1&lt;/code&gt; does (almost) the
same as the initial &lt;code class="prettyprint lang-ml"&gt;pp&lt;/code&gt;,
the big difference being that we isolated the code that handles grouping.
Because of this, implementing a policy based on operator precedences is
simply a matter of defining another combinator.

&lt;pre class="prettyprint lang-ml"&gt;
let precedence = function 
  | Op (Plus, _::_::_) -&amp;gt; 1
  | Op (Times, _::_::_) -&amp;gt; 2
  | _ -&amp;gt; 0

let rec y2 up f ppf x =
  let down = precedence x in
  let lp, rp = 
    if down &amp;lt;= up &amp;amp;&amp;amp; up &amp;lt;&amp;gt; 0 &amp;amp;&amp;amp; down &amp;lt;&amp;gt; 0 then ("(", ")") else ("","") in
  fprintf ppf "@[%s%a%s@]@," lp (f (y2 down f)) x rp

let pp2 = y2 0 pp

let _ = pp2 std_formatter v
&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5829875-3523092535540829345?l=rgrig.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/RgrigsBlog/~4/JrBCKy0TdrY" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://rgrig.blogspot.com/feeds/3523092535540829345/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://rgrig.blogspot.com/2010/12/more-ocaml-pretty-printing.html#comment-form" title="3 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5829875/posts/default/3523092535540829345?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5829875/posts/default/3523092535540829345?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/RgrigsBlog/~3/JrBCKy0TdrY/more-ocaml-pretty-printing.html" title="More OCaml Pretty-Printing" /><author><name>Radu Grigore</name><uri>https://profiles.google.com/101644137139656854756</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh4.googleusercontent.com/-qUUZcf9ulqQ/AAAAAAAAAAI/AAAAAAAADnE/AVKMToUdkMQ/s512-c/photo.jpg" /></author><thr:total>3</thr:total><feedburner:origLink>http://rgrig.blogspot.com/2010/12/more-ocaml-pretty-printing.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C0YASH0_cSp7ImA9Wx5WF0o.&quot;"><id>tag:blogger.com,1999:blog-5829875.post-5785239707216058610</id><published>2010-09-29T15:39:00.000+01:00</published><updated>2010-09-29T15:39:09.349+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-09-29T15:39:09.349+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="random" /><title>Mini Me</title><content type="html">&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://3.bp.blogspot.com/_byUC16gzOKM/TKNPUrbBLhI/AAAAAAAACHI/7Cr25T25P4g/s1600/mini_me.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/_byUC16gzOKM/TKNPUrbBLhI/AAAAAAAACHI/7Cr25T25P4g/s1600/mini_me.jpg" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5829875-5785239707216058610?l=rgrig.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/RgrigsBlog/~4/3hz-NZohbHM" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://rgrig.blogspot.com/feeds/5785239707216058610/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://rgrig.blogspot.com/2010/09/mini-me.html#comment-form" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5829875/posts/default/5785239707216058610?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5829875/posts/default/5785239707216058610?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/RgrigsBlog/~3/3hz-NZohbHM/mini-me.html" title="Mini Me" /><author><name>Radu Grigore</name><uri>https://profiles.google.com/101644137139656854756</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh4.googleusercontent.com/-qUUZcf9ulqQ/AAAAAAAAAAI/AAAAAAAADnE/AVKMToUdkMQ/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://3.bp.blogspot.com/_byUC16gzOKM/TKNPUrbBLhI/AAAAAAAACHI/7Cr25T25P4g/s72-c/mini_me.jpg" height="72" width="72" /><thr:total>1</thr:total><feedburner:origLink>http://rgrig.blogspot.com/2010/09/mini-me.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CkMDRXY6eSp7ImA9Wx5WF0o.&quot;"><id>tag:blogger.com,1999:blog-5829875.post-3100789763564751576</id><published>2010-09-29T15:10:00.003+01:00</published><updated>2010-09-29T15:27:54.811+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-09-29T15:27:54.811+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="puzzle" /><category scheme="http://www.blogger.com/atom/ns#" term="learning" /><title>Expected Size of a Set</title><content type="html">&lt;p&gt;&lt;i&gt;You insert $a_1$, $a_2$, $\ldots$, $a_n$ into an initially empty set data structure $S$. What is the size $s$ of $S$ at the end?&lt;/i&gt;

&lt;p&gt;Say that each $a_k$ is taken from $1.\,.\&gt;m$ and all $m^n$ sequences are equally likely. If $n=0$ then $s=0$; if $n\to\infty$ then $s\to m$; and a quick and dirty simulator shows that if $n=m$ then $s\approx0.63m$. The number $c(n,k,l)$ of sequences of length $n$ that have exactly $k$ unique elements taken from $1.\,.\&gt;l$ satisfies $$c(n,k,l)=c(n,k,l-1)+\sum_{q&gt;0} {n \choose q} c(n-q,k-1,l-1).$$ This gives a way to compute $s$ exactly for $m=n &lt; 100$, and it seems that indeed $s/n$ approaches $\approx0.63$ from above as $n$ grows.

&lt;p&gt;Do you know a formula for $0.63$? For $s(m=n)$? For $s(m,n)$? (I don't.)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5829875-3100789763564751576?l=rgrig.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/RgrigsBlog/~4/ZisezLrd3J0" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://rgrig.blogspot.com/feeds/3100789763564751576/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://rgrig.blogspot.com/2010/09/expected-size-of-set.html#comment-form" title="6 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5829875/posts/default/3100789763564751576?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5829875/posts/default/3100789763564751576?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/RgrigsBlog/~3/ZisezLrd3J0/expected-size-of-set.html" title="Expected Size of a Set" /><author><name>Radu Grigore</name><uri>https://profiles.google.com/101644137139656854756</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh4.googleusercontent.com/-qUUZcf9ulqQ/AAAAAAAAAAI/AAAAAAAADnE/AVKMToUdkMQ/s512-c/photo.jpg" /></author><thr:total>6</thr:total><feedburner:origLink>http://rgrig.blogspot.com/2010/09/expected-size-of-set.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DU4GR34_eSp7ImA9Wx5XFUo.&quot;"><id>tag:blogger.com,1999:blog-5829875.post-8781409725767615304</id><published>2010-09-15T17:41:00.003+01:00</published><updated>2010-09-15T20:12:06.041+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-09-15T20:12:06.041+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="coding" /><title>A Certain Type of Pretty-Printing in OCAML</title><content type="html">&lt;p&gt;&lt;i&gt;You want to print 
&lt;code class="prettyprint lang-ml"&gt;Node(Leaf, [{ra=1;rb="a"};{ra=2;rb="b"}], Node(Leaf, [{ra=3;rb=["foo";"bar"]}], Leaf))&lt;/code&gt;
as &lt;tt&gt;"1 * a * 2 * b * 3 * foo * bar"&lt;/tt&gt;. How do you do it?&lt;/i&gt;

&lt;p&gt;Let us begin with the simpler problem of printing a star-separated
list of integers.

&lt;pre class="prettyprint lang-ml"&gt;
open Format
let simple_print = function -&amp;gt;
  | [] -&amp;gt; ()
  | [x] -&amp;gt; printf "%d" x
  | x :: xs -&amp;gt; printf "%d@ * "; simple_print xs
&lt;/pre&gt;

&lt;p&gt;Since there is one less star than there are integers, the last integer in
the list is treated in a special way. Of course, we may want to also print
lists of strings in this way; or we may want to use some other separator than a
star; or we may want to use a different formatter.

&lt;pre class="prettyprint lang-ml"&gt;
let better_print separator pp ppf = function -&amp;gt;
  | [] -&amp;gt; ()
  | [x] -&amp;gt; fprintf ppf "%a" pp x
  | x::xs -&amp;gt; 
      fprintf ppf "%a@ %s " pp x separator; 
      better_print separator pp ppf xs
let pp_string ppf x = fprintf ppf "%s" x
let pp_int ppf x = fprintf ppf "%d" x
better_print "||" pp_string std_formatter ["foo"; "bar"]
&lt;/pre&gt;

&lt;p&gt;Now comes the interesting part. Suppose that what we really want to print
are the primitive values that hang in a complicated tree of nested data
structures like lists, variants, records, sets, and so on. For example, the
value mentioned in the summary has type &lt;code class="prettyprint lang-ml"&gt;t&lt;/code&gt;.

&lt;pre class="prettyprint lang-ml"&gt;
type r = { ra : int; rb : string list }
type t = Leaf | Node of t * r list * t
let v =
  Node
    (Leaf,
    [{ra=1;rb=["a"]};{ra=2;rb=["b"]}],
    Node
      (Leaf,
      [{ra=3;rb=["foo";"bar"]}],
      Leaf))
&lt;/pre&gt;

&lt;p&gt;We'll probably have a pretty-printing function &lt;code
  class="prettyprint lang-ml"&gt;pp_r&lt;/code&gt; for type &lt;code class="prettyprint lang-ml"&gt;r&lt;/code&gt;
  and a pretty-printing function &lt;code class="prettyprint lang-ml"&gt;pp_t&lt;/code&gt; for type
  &lt;code class="prettyprint lang-ml"&gt;t&lt;/code&gt;. Let's think about the latter.  For &lt;code
  class="prettyprint lang-ml"&gt;Node(left,data,right)&lt;/code&gt; we'd be tempted to say
  "print left, print star, print data, print star, print right." Of course,
  &lt;code class="prettyprint lang-ml"&gt;left&lt;/code&gt; might be a leaf, in which case we
  should omit the first "print star." Or perhaps, the list &lt;code
  class="prettyprint lang-ml"&gt;data&lt;/code&gt; is empty, in which case we should omit
  &lt;i&gt;one&lt;/i&gt; of the two "print star"s. In a more complicated scenario &lt;code
  class="prettyprint lang-ml"&gt;data&lt;/code&gt; might be a list of sets and, although the
  list is not empty, all of its sets may be. In order to figure whether this is
  the case we'd need to traverse the whole list. Or perhaps we have a record
  with $n$ fields. After printing the first $k$ fields we should print a star
  when one of the first $k$ fields is nonempty and one of the last $n-k$ fields
  is nonempty. So we'd better start by asking &lt;i&gt;once&lt;/i&gt; in the beginning each
  field if it is empty: Otherwise we may end up asking each field $\sim n$
  times and we know that checking emptiness may take linear time.  (It would be
  pretty stupid for pretty-printing of a big structure with few leafs to take
  quadratic time.) Or perhaps, &amp;hellip;

&lt;p&gt;OK. That's a nightmare, so let's try to take a step back. We want:

&lt;ul&gt;
  &lt;li&gt;a way to traverse the data structure,
  &lt;li&gt;a way to print each possible leaf, and
  &lt;li&gt;a way to know when we get to a leaf whether it is the first (or last).
&lt;/ul&gt;

&lt;p&gt;That's easy! It sounds like what we want is a fold.  Well, almost, because
when we hit a string leaf we need to call one function and when we hit an
integer leaf we need to call another. So it is a specialized fold but,
nevertheless, our implementation may look very similar to what we'd do for a
fold.

&lt;pre class="prettyprint lang-ml"&gt;
let pp_string' ppf first x = 
  if not first then fprintf ppf "@ * "; pp_string ppf x; false
let pp_int' ppf first x =
  if not first then fprintf ppf "@ * "; pp_int ppf x; false
let pp_r ppf first {ra=ra; rb=rb} =
  let first = pp_int' ppf first ra in
  List.fold_left pp_string' first rb
let pp_t ppf first = function
  | Leaf -&amp;gt; first
  | Node (left, data, right) -&amp;gt;
      let first = pp_t ppf first left in
      let first = List.fold_left (pp_r ppf) first data in
      pp_t ppf first right
let pp_r' ppf = pp_r ppf false
let pp_t' ppf = pp_t ppf false
&lt;/pre&gt;

&lt;p&gt;This works and is already much nicer than the previous option. However,
There are still problems.

&lt;ul&gt;
  &lt;li&gt;The functions &lt;code class="prettyprint lang-ml"&gt;pp_string'&lt;/code&gt; and
    &lt;code class="prettyprint lang-ml"&gt;pp_int'&lt;/code&gt; are obtained from
    their unprimed counterparts in a very systematic way, so we shouldn't
    write the same code once for each leaf type.
  &lt;li&gt;Similarly for &lt;code class="prettyprint lang-ml"&gt;pp_r'&lt;/code&gt; and
    &lt;code class="prettyprint lang-ml"&gt;pp_t'&lt;/code&gt;.
  &lt;li&gt;Note that for lists we used &lt;code class="prettyprint lang-ml"&gt;List.fold_left&lt;/code&gt;
    so for the type &lt;code class="prettyprint lang-ml"&gt;t&lt;/code&gt; we should be able to
    do something similar: Implement a generic fold, and then use it.
  &lt;li&gt;The star is hardcoded. What if we want a different separator?
&lt;/ul&gt;

&lt;p&gt;So let's see how can we encode the recipe for obtaining 
&lt;code class="prettyprint lang-ml"&gt;pp_string'&lt;/code&gt; and
&lt;code class="prettyprint lang-ml"&gt;pp_int'&lt;/code&gt;. We may be tempted to try the
following.

&lt;pre class="prettyprint lang-ml"&gt;
let pp_sep separator pp = 
  fun ppf first x -&amp;gt; if not first then fprintf ppf "@ %s " separator; false
&lt;/pre&gt;

&lt;p&gt;Yay: We also solved the problem with the star being hard-coded! What
we can do is to add a (first) parameter &lt;code class="prettyprint lang-ml"&gt;pp&lt;/code&gt; to
&lt;code class="prettyprint lang-ml"&gt;pp_r&lt;/code&gt; and
&lt;code class="prettyprint lang-ml"&gt;pp_t&lt;/code&gt;. Then we redefine the primed
versions.

&lt;pre class="prettyprint lang-ml"&gt;
let pp_r' separator ppf = pp_r (pp_primitive separator) ppf false
let pp_r' separator ppf = pp_r (pp_primitive separator) ppf false
&lt;/pre&gt;

&lt;p&gt;We then replace calls to &lt;code class="prettyprint lang-ml"&gt;pp_int'&lt;/code&gt;
by &lt;code class="prettyprint lang-ml"&gt;pp pp_int&lt;/code&gt;. Everything's sweet, right?
Well, &amp;hellip; no, this doesn't typecheck. The reason is in 
&lt;a href="http://caml.inria.fr/resources/doc/faq/core.en.html#polymorphic-arguments"&gt;OCAML's FAQ&lt;/a&gt;.
You may want to try these modifications to convince yourself that they
indeed do not work. Anyway, the workaround is in OCAML's FAQ. So here's
how to do it.

&lt;pre class="prettyprint lang-ml"&gt;
open Format

(* example data structures *)
type r = { ra : int; rb : string list }
type t = Leaf | Node of t * r list * t

(* a value to test with *)
let v =
  Node
    (Leaf,
    [{ra=1;rb=["a"]};{ra=2;rb=["b"]}],
    Node
      (Leaf,
      [{ra=3;rb=["foo";"bar"]}],
      Leaf))

(* how to print 'leafs' *)
let pp_string ppf x = fprintf ppf "%s" x
let pp_int ppf x = fprintf ppf "%d" x

(* a recipe for making leaf printing foldable *)
type sep_wrapper = { 
  primitive : 'a. (formatter-&amp;gt;'a-&amp;gt;unit)-&amp;gt;formatter-&amp;gt;bool-&amp;gt;'a-&amp;gt;bool
}
let pp_sep separator = {
  primitive = fun pp ppf first x -&amp;gt; 
    if not first then fprintf ppf "@ %s " separator; pp ppf x; false
}

(* folds for our homogeous data structures *)
let rec fold_t f s = function
  | Leaf -&amp;gt; s
  | Node (l, xs, r) -&amp;gt; fold_t f (List.fold_left f (fold_t f s l) xs) r

(* pretty printing workers, used mostly internally *)
let pp_r pp ppf first {ra=ra; rb=rb} =
  let first = pp.primitive pp_int ppf first ra in
  List.fold_left (pp.primitive pp_string ppf) first rb
let pp_t pp ppf = 
  fold_t (pp_r pp ppf)

(* pretty printing for the typical user *)
let pp_whole pp = 
  fun separator ppf x -&gt; ignore (pp (pp_sep separator) ppf true x)
let pp_r' = pp_whole pp_r
let pp_t' = pp_whole pp_t

(* a small test *)
let _ =
  printf "@[%a@." (pp_t' "*") v
&lt;/pre&gt;

&lt;p&gt;Note that the strategy of implementing a general fold and then use it
does not work for type &lt;code class="prettyprint lang-ml"&gt;r&lt;/code&gt; because it holds
two kinds of leafs (integers and strings). Also note that what I called leafs (or leaves, whatever) do &lt;b&gt;not&lt;/b&gt; need to be OCAML primitive types.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5829875-8781409725767615304?l=rgrig.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/RgrigsBlog/~4/kksSD14jBJg" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://rgrig.blogspot.com/feeds/8781409725767615304/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://rgrig.blogspot.com/2010/09/certain-type-of-pretty-printing-in.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5829875/posts/default/8781409725767615304?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5829875/posts/default/8781409725767615304?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/RgrigsBlog/~3/kksSD14jBJg/certain-type-of-pretty-printing-in.html" title="A Certain Type of Pretty-Printing in OCAML" /><author><name>Radu Grigore</name><uri>https://profiles.google.com/101644137139656854756</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh4.googleusercontent.com/-qUUZcf9ulqQ/AAAAAAAAAAI/AAAAAAAADnE/AVKMToUdkMQ/s512-c/photo.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://rgrig.blogspot.com/2010/09/certain-type-of-pretty-printing-in.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DU8ASHk4eyp7ImA9Wx5XFUo.&quot;"><id>tag:blogger.com,1999:blog-5829875.post-8363890621797713205</id><published>2010-07-16T21:43:00.002+01:00</published><updated>2010-09-15T20:10:49.733+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-09-15T20:10:49.733+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="random" /><title>Picasaweb Cameras</title><content type="html">Which photo cameras make cool pictures?&lt;br /&gt;
&lt;br /&gt;
I took a sample of 100 &lt;a href="http://picasaweb.google.co.uk/lh/featured?feat=featured_all"&gt;featured pictures from Picasa&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;59 Canon&lt;/li&gt;
&lt;li&gt;23 Nikon&lt;/li&gt;
&lt;li&gt;18 others&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
Out of the Canon pictures, 27 where taken by &lt;a href="http://www.google.com/search?q=eos+5d+mark+II"&gt;EOS 5D Mark II&lt;/a&gt;, 8 where taken by various flavors of &lt;a href="http://www.google.com/search?q=eos+digital+rebel"&gt;EOS DIGITAL REBEL&lt;/a&gt;, and 24 by other Canons.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5829875-8363890621797713205?l=rgrig.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/RgrigsBlog/~4/36lxyT7R9P0" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://rgrig.blogspot.com/feeds/8363890621797713205/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://rgrig.blogspot.com/2010/07/picasaweb-cameras.html#comment-form" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5829875/posts/default/8363890621797713205?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5829875/posts/default/8363890621797713205?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/RgrigsBlog/~3/36lxyT7R9P0/picasaweb-cameras.html" title="Picasaweb Cameras" /><author><name>Radu Grigore</name><uri>https://profiles.google.com/101644137139656854756</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh4.googleusercontent.com/-qUUZcf9ulqQ/AAAAAAAAAAI/AAAAAAAADnE/AVKMToUdkMQ/s512-c/photo.jpg" /></author><thr:total>2</thr:total><feedburner:origLink>http://rgrig.blogspot.com/2010/07/picasaweb-cameras.html</feedburner:origLink></entry><entry gd:etag="W/&quot;D0AFRHs4fSp7ImA9WxFaEU8.&quot;"><id>tag:blogger.com,1999:blog-5829875.post-2629092895678119800</id><published>2010-07-14T16:08:00.003+01:00</published><updated>2010-07-14T17:41:55.535+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-07-14T17:41:55.535+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="puzzle" /><title>Solitaire</title><content type="html">&lt;!--CUT DEF section 1 --&gt;&lt;P&gt;
&lt;I&gt;Yet another &amp;#X201C;Is this NP-complete?&amp;#X201D; question. The problem
is of a kind that I 
&lt;/I&gt;&lt;A HREF="http://rgrig.blogspot.com/2005/08/topcoder-games.html"&gt;&lt;I&gt;discussed before&lt;/I&gt;&lt;/A&gt;&lt;I&gt;.&lt;/I&gt;&lt;/P&gt;&lt;P&gt;In the game &lt;A HREF="http://www.google.com/search?q=solitaire"&gt;Solitaire&lt;/A&gt; you
sometimes visualize the state you want to achieve and regard the necessary
intermediate moves as chore. A friend wondered how to reach the goal with a
minimum number of key presses. (He plays on a Blackberry with no mouse.) Let us
look at a simplified example.
&lt;/P&gt;&lt;TABLE CLASS="display dcenter"&gt;&lt;TR VALIGN="middle"&gt;&lt;TD CLASS="dcell"&gt;
&amp;#XA0;&amp;#XA0;&amp;#XA0;&amp;#XA0;&amp;#XA0;

&lt;/TD&gt;&lt;TD CLASS="dcell"&gt;&lt;TABLE CELLSPACING=6 CELLPADDING=0&gt;&lt;TR&gt;&lt;TD ALIGN=right NOWRAP&gt;&amp;nbsp;&lt;/TD&gt;&lt;TD ALIGN=left NOWRAP&gt;
&amp;#X25A1;,1,&amp;#X25A1;,&amp;#X25A1;,4,3,&amp;#X25A1;,2,5&lt;/TD&gt;&lt;TD ALIGN=right NOWRAP&gt;&amp;nbsp;&lt;/TD&gt;&lt;TD ALIGN=left NOWRAP&gt;&amp;nbsp;&lt;/TD&gt;&lt;TD ALIGN=right NOWRAP&gt;&amp;nbsp;&lt;/TD&gt;&lt;TD ALIGN=left NOWRAP&gt;&amp;nbsp;&lt;/TD&gt;&lt;TD ALIGN=right NOWRAP&gt;&amp;nbsp;&lt;/TD&gt;&lt;TD ALIGN=left NOWRAP&gt;&amp;nbsp;&lt;/TD&gt;&lt;TD ALIGN=right NOWRAP&gt;&amp;nbsp;&lt;/TD&gt;&lt;TD ALIGN=left NOWRAP&gt;&amp;nbsp;&lt;/TD&gt;&lt;TD ALIGN=right NOWRAP&gt;&amp;#XA0;&amp;#XA0;&amp;#XA0;&amp;#XA0;(1)&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;&lt;TD ALIGN=right NOWRAP&gt;&amp;nbsp;&lt;/TD&gt;&lt;TD ALIGN=left NOWRAP&gt;&amp;#X219D;
&amp;#X25A1;,1,&amp;#X25A1;,&amp;#X25A1;,4,23,&amp;#X25A1;,&amp;#X25A1;,5&lt;/TD&gt;&lt;TD ALIGN=right NOWRAP&gt;&amp;nbsp;&lt;/TD&gt;&lt;TD ALIGN=left NOWRAP&gt;&amp;nbsp;&lt;/TD&gt;&lt;TD ALIGN=right NOWRAP&gt;&amp;nbsp;&lt;/TD&gt;&lt;TD ALIGN=left NOWRAP&gt;&amp;nbsp;&lt;/TD&gt;&lt;TD ALIGN=right NOWRAP&gt;&amp;nbsp;&lt;/TD&gt;&lt;TD ALIGN=left NOWRAP&gt;&amp;nbsp;&lt;/TD&gt;&lt;TD ALIGN=right NOWRAP&gt;&amp;nbsp;&lt;/TD&gt;&lt;TD ALIGN=left NOWRAP&gt;&amp;nbsp;&lt;/TD&gt;&lt;TD ALIGN=right NOWRAP&gt;&amp;#XA0;&amp;#XA0;&amp;#XA0;&amp;#XA0;(2)&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;&lt;TD ALIGN=right NOWRAP&gt;&amp;nbsp;&lt;/TD&gt;&lt;TD ALIGN=left NOWRAP&gt;&amp;#X219D;
&amp;#X25A1;,1,&amp;#X25A1;,&amp;#X25A1;,234,&amp;#X25A1;,&amp;#X25A1;,&amp;#X25A1;,5&lt;/TD&gt;&lt;TD ALIGN=right NOWRAP&gt;&amp;nbsp;&lt;/TD&gt;&lt;TD ALIGN=left NOWRAP&gt;&amp;nbsp;&lt;/TD&gt;&lt;TD ALIGN=right NOWRAP&gt;&amp;nbsp;&lt;/TD&gt;&lt;TD ALIGN=left NOWRAP&gt;&amp;nbsp;&lt;/TD&gt;&lt;TD ALIGN=right NOWRAP&gt;&amp;nbsp;&lt;/TD&gt;&lt;TD ALIGN=left NOWRAP&gt;&amp;nbsp;&lt;/TD&gt;&lt;TD ALIGN=right NOWRAP&gt;&amp;nbsp;&lt;/TD&gt;&lt;TD ALIGN=left NOWRAP&gt;&amp;nbsp;&lt;/TD&gt;&lt;TD ALIGN=right NOWRAP&gt;&amp;#XA0;&amp;#XA0;&amp;#XA0;&amp;#XA0;(3)&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;&lt;TD ALIGN=right NOWRAP&gt;&amp;nbsp;&lt;/TD&gt;&lt;TD ALIGN=left NOWRAP&gt;&amp;#X219D;
&amp;#X25A1;,&amp;#X25A1;,&amp;#X25A1;,&amp;#X25A1;,1234,&amp;#X25A1;,&amp;#X25A1;,&amp;#X25A1;,5&lt;/TD&gt;&lt;TD ALIGN=right NOWRAP&gt;&amp;nbsp;&lt;/TD&gt;&lt;TD ALIGN=left NOWRAP&gt;&amp;nbsp;&lt;/TD&gt;&lt;TD ALIGN=right NOWRAP&gt;&amp;nbsp;&lt;/TD&gt;&lt;TD ALIGN=left NOWRAP&gt;&amp;nbsp;&lt;/TD&gt;&lt;TD ALIGN=right NOWRAP&gt;&amp;nbsp;&lt;/TD&gt;&lt;TD ALIGN=left NOWRAP&gt;&amp;nbsp;&lt;/TD&gt;&lt;TD ALIGN=right NOWRAP&gt;&amp;nbsp;&lt;/TD&gt;&lt;TD ALIGN=left NOWRAP&gt;&amp;nbsp;&lt;/TD&gt;&lt;TD ALIGN=right NOWRAP&gt;&amp;#XA0;&amp;#XA0;&amp;#XA0;&amp;#XA0;(4)&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;&lt;TD ALIGN=right NOWRAP&gt;&amp;nbsp;&lt;/TD&gt;&lt;TD ALIGN=left NOWRAP&gt;&amp;#X219D;
&amp;#X25A1;,&amp;#X25A1;,&amp;#X25A1;,&amp;#X25A1;,&amp;#X25A1;,&amp;#X25A1;,&amp;#X25A1;,&amp;#X25A1;,12345
&lt;/TD&gt;&lt;TD ALIGN=right NOWRAP&gt;&amp;nbsp;&lt;/TD&gt;&lt;TD ALIGN=left NOWRAP&gt;&amp;nbsp;&lt;/TD&gt;&lt;TD ALIGN=right NOWRAP&gt;&amp;nbsp;&lt;/TD&gt;&lt;TD ALIGN=left NOWRAP&gt;&amp;nbsp;&lt;/TD&gt;&lt;TD ALIGN=right NOWRAP&gt;&amp;nbsp;&lt;/TD&gt;&lt;TD ALIGN=left NOWRAP&gt;&amp;nbsp;&lt;/TD&gt;&lt;TD ALIGN=right NOWRAP&gt;&amp;nbsp;&lt;/TD&gt;&lt;TD ALIGN=left NOWRAP&gt;&amp;nbsp;&lt;/TD&gt;&lt;TD ALIGN=right NOWRAP&gt;&amp;#XA0;&amp;#XA0;&amp;#XA0;&amp;#XA0;(5)&lt;/TD&gt;&lt;/TR&gt;
&lt;/TABLE&gt;&lt;/TD&gt;&lt;/TR&gt;
&lt;/TABLE&gt;&lt;P&gt;
In this example there are 9&amp;#XA0;slots into which cards 1&amp;#X2013;to&amp;#X2013;5 are placed.
In a &lt;EM&gt;valid state&lt;/EM&gt;, each slot contains a contiguous sequence of cards,
possibly empty&amp;#XA0;(&amp;#X25A1;). Each &lt;EM&gt;move&lt;/EM&gt; consists of transporting a contiguous
sequence of cards from one slot to another. (Take a moment to convince yourself
that a valid state is reached only if the &lt;EM&gt;whole&lt;/EM&gt; sequence of a slot is
transported.) The &lt;EM&gt;cost&lt;/EM&gt; of a move is the distance between the source and
the target slots (and is independent of the size of the transported sequence).
In the example above there are 4&amp;#XA0;moves with a total cost of 2+1+3+4=10. The
&lt;EM&gt;goal&lt;/EM&gt; is to put all the cards in one slot.&lt;/P&gt;&lt;P&gt;This problem has a &lt;A HREF="http://www.google.com/search?q=dynamic+programming"&gt;dynamic programming&lt;/A&gt; solution, which works on a different representation
of the states.
&lt;/P&gt;&lt;TABLE CLASS="display dcenter"&gt;&lt;TR VALIGN="middle"&gt;&lt;TD CLASS="dcell"&gt;
&amp;#XA0;&amp;#XA0;&amp;#XA0;&amp;#XA0;&amp;#XA0;

&lt;/TD&gt;&lt;TD CLASS="dcell"&gt;&lt;TABLE CELLSPACING=6 CELLPADDING=0&gt;&lt;TR&gt;&lt;TD ALIGN=right NOWRAP&gt;&amp;nbsp;&lt;/TD&gt;&lt;TD ALIGN=left NOWRAP&gt;
2,8,6,5,9&lt;/TD&gt;&lt;TD ALIGN=right NOWRAP&gt;&amp;nbsp;&lt;/TD&gt;&lt;TD ALIGN=left NOWRAP&gt;&amp;nbsp;&lt;/TD&gt;&lt;TD ALIGN=right NOWRAP&gt;&amp;nbsp;&lt;/TD&gt;&lt;TD ALIGN=left NOWRAP&gt;&amp;nbsp;&lt;/TD&gt;&lt;TD ALIGN=right NOWRAP&gt;&amp;nbsp;&lt;/TD&gt;&lt;TD ALIGN=left NOWRAP&gt;&amp;nbsp;&lt;/TD&gt;&lt;TD ALIGN=right NOWRAP&gt;&amp;nbsp;&lt;/TD&gt;&lt;TD ALIGN=left NOWRAP&gt;&amp;nbsp;&lt;/TD&gt;&lt;TD ALIGN=right NOWRAP&gt;&amp;#XA0;&amp;#XA0;&amp;#XA0;&amp;#XA0;(6)&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;&lt;TD ALIGN=right NOWRAP&gt;&amp;nbsp;&lt;/TD&gt;&lt;TD ALIGN=left NOWRAP&gt;&amp;#X219D;
2,6,5,9&lt;/TD&gt;&lt;TD ALIGN=right NOWRAP&gt;&amp;nbsp;&lt;/TD&gt;&lt;TD ALIGN=left NOWRAP&gt;&amp;nbsp;&lt;/TD&gt;&lt;TD ALIGN=right NOWRAP&gt;&amp;nbsp;&lt;/TD&gt;&lt;TD ALIGN=left NOWRAP&gt;&amp;nbsp;&lt;/TD&gt;&lt;TD ALIGN=right NOWRAP&gt;&amp;nbsp;&lt;/TD&gt;&lt;TD ALIGN=left NOWRAP&gt;&amp;nbsp;&lt;/TD&gt;&lt;TD ALIGN=right NOWRAP&gt;&amp;nbsp;&lt;/TD&gt;&lt;TD ALIGN=left NOWRAP&gt;&amp;nbsp;&lt;/TD&gt;&lt;TD ALIGN=right NOWRAP&gt;&amp;#XA0;&amp;#XA0;&amp;#XA0;&amp;#XA0;(7)&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;&lt;TD ALIGN=right NOWRAP&gt;&amp;nbsp;&lt;/TD&gt;&lt;TD ALIGN=left NOWRAP&gt;&amp;#X219D;
2,5,9&lt;/TD&gt;&lt;TD ALIGN=right NOWRAP&gt;&amp;nbsp;&lt;/TD&gt;&lt;TD ALIGN=left NOWRAP&gt;&amp;nbsp;&lt;/TD&gt;&lt;TD ALIGN=right NOWRAP&gt;&amp;nbsp;&lt;/TD&gt;&lt;TD ALIGN=left NOWRAP&gt;&amp;nbsp;&lt;/TD&gt;&lt;TD ALIGN=right NOWRAP&gt;&amp;nbsp;&lt;/TD&gt;&lt;TD ALIGN=left NOWRAP&gt;&amp;nbsp;&lt;/TD&gt;&lt;TD ALIGN=right NOWRAP&gt;&amp;nbsp;&lt;/TD&gt;&lt;TD ALIGN=left NOWRAP&gt;&amp;nbsp;&lt;/TD&gt;&lt;TD ALIGN=right NOWRAP&gt;&amp;#XA0;&amp;#XA0;&amp;#XA0;&amp;#XA0;(8)&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;&lt;TD ALIGN=right NOWRAP&gt;&amp;nbsp;&lt;/TD&gt;&lt;TD ALIGN=left NOWRAP&gt;&amp;#X219D;
5,9&amp;#XA0;&lt;/TD&gt;&lt;TD ALIGN=right NOWRAP&gt;&amp;nbsp;&lt;/TD&gt;&lt;TD ALIGN=left NOWRAP&gt;&amp;nbsp;&lt;/TD&gt;&lt;TD ALIGN=right NOWRAP&gt;&amp;nbsp;&lt;/TD&gt;&lt;TD ALIGN=left NOWRAP&gt;&amp;nbsp;&lt;/TD&gt;&lt;TD ALIGN=right NOWRAP&gt;&amp;nbsp;&lt;/TD&gt;&lt;TD ALIGN=left NOWRAP&gt;&amp;nbsp;&lt;/TD&gt;&lt;TD ALIGN=right NOWRAP&gt;&amp;nbsp;&lt;/TD&gt;&lt;TD ALIGN=left NOWRAP&gt;&amp;nbsp;&lt;/TD&gt;&lt;TD ALIGN=right NOWRAP&gt;&amp;#XA0;&amp;#XA0;&amp;#XA0;&amp;#XA0;(9)&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;&lt;TD ALIGN=right NOWRAP&gt;&amp;nbsp;&lt;/TD&gt;&lt;TD ALIGN=left NOWRAP&gt;&amp;#X219D;
9
&lt;/TD&gt;&lt;TD ALIGN=right NOWRAP&gt;&amp;nbsp;&lt;/TD&gt;&lt;TD ALIGN=left NOWRAP&gt;&amp;nbsp;&lt;/TD&gt;&lt;TD ALIGN=right NOWRAP&gt;&amp;nbsp;&lt;/TD&gt;&lt;TD ALIGN=left NOWRAP&gt;&amp;nbsp;&lt;/TD&gt;&lt;TD ALIGN=right NOWRAP&gt;&amp;nbsp;&lt;/TD&gt;&lt;TD ALIGN=left NOWRAP&gt;&amp;nbsp;&lt;/TD&gt;&lt;TD ALIGN=right NOWRAP&gt;&amp;nbsp;&lt;/TD&gt;&lt;TD ALIGN=left NOWRAP&gt;&amp;nbsp;&lt;/TD&gt;&lt;TD ALIGN=right NOWRAP&gt;&amp;#XA0;&amp;#XA0;&amp;#XA0;&amp;#XA0;(10)&lt;/TD&gt;&lt;/TR&gt;
&lt;/TABLE&gt;&lt;/TD&gt;&lt;/TR&gt;
&lt;/TABLE&gt;&lt;P&gt;
The first state tells us that card&amp;#XA0;1 is in slot&amp;#XA0;2, card&amp;#XA0;2 in slot&amp;#XA0;8, card&amp;#XA0;3 in
slot&amp;#XA0;6, and so on; the last state tells us that all cards are in slot&amp;#XA0;9. In
general, a state tells us in which slots there are cards, and does so in
increasing order of cards&amp;#X2019; values. With this representation a move consists
of crossing out a number. The cost of a move is the absolute difference between
the crossed out number and the following number. (The last number in a state
cannot be crossed out.) With &lt;I&gt;n&lt;/I&gt;&amp;#XA0;cards there are 2&lt;SUP&gt;&lt;I&gt;n&lt;/I&gt;&amp;#X2212;1&lt;/SUP&gt; possible states.
For each state there are &amp;lt;&lt;I&gt;n&lt;/I&gt; possible moves. Therefore, if each possible
state and each possible move is examined at most once, then this algorithm
works in &lt;I&gt;O&lt;/I&gt;(&lt;I&gt;n&lt;/I&gt;2&lt;SUP&gt;&lt;I&gt;n&lt;/I&gt;&lt;/SUP&gt;)&amp;#XA0;steps.&lt;/P&gt;&lt;P&gt;Note that there are (&lt;I&gt;n&lt;/I&gt;&amp;#X2212;1)! sequences of moves that attain the goal. A
similar reduction (from&amp;#XA0;&lt;I&gt;n&lt;/I&gt;! to around&amp;#XA0;&lt;I&gt;n&lt;/I&gt;2&lt;SUP&gt;&lt;I&gt;n&lt;/I&gt;&lt;/SUP&gt;) appears when one moves from a brute
force solution to a dynamic programming solution of the Hamiltonian cycle
problem. In general, it is often possible to look at all subsets when it
seems that looking at all permutations is necessary.&lt;/P&gt;&lt;P&gt;&lt;I&gt;Questions:&lt;/I&gt; Can you do better? Is this problem NP-complete?&lt;/P&gt;&lt;!--CUT END --&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5829875-2629092895678119800?l=rgrig.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/RgrigsBlog/~4/fmGhYLZ1sNQ" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://rgrig.blogspot.com/feeds/2629092895678119800/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://rgrig.blogspot.com/2010/07/solitaire.html#comment-form" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5829875/posts/default/2629092895678119800?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5829875/posts/default/2629092895678119800?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/RgrigsBlog/~3/fmGhYLZ1sNQ/solitaire.html" title="Solitaire" /><author><name>Radu Grigore</name><uri>https://profiles.google.com/101644137139656854756</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh4.googleusercontent.com/-qUUZcf9ulqQ/AAAAAAAAAAI/AAAAAAAADnE/AVKMToUdkMQ/s512-c/photo.jpg" /></author><thr:total>1</thr:total><feedburner:origLink>http://rgrig.blogspot.com/2010/07/solitaire.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CkYFQ30zeip7ImA9WxFbGUk.&quot;"><id>tag:blogger.com,1999:blog-5829875.post-3802239172289301481</id><published>2010-07-12T14:08:00.000+01:00</published><updated>2010-07-12T14:08:32.382+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-07-12T14:08:32.382+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="learning" /><title>Mathematical Logic 1</title><content type="html">&lt;p&gt;&lt;i&gt;Motivation by analogy.&lt;/i&gt;&lt;/p&gt;
&lt;!--CUT DEF section 1 --&gt;&lt;P&gt;Logic studies reasoning.
Many people that are not familiar with logic are able to think (reasonably).
For example, many children find the explanation &amp;#X201C;because I say so&amp;#X201D; less satisfying than &amp;#X201C;if you do not solve your homework then you will not receive a high grade, therefore you will receive a high grade only if you solve your homework.&amp;#X201D;
A child may not agree that a high grade is a worthy goal, but the point is that the second explanation is somehow more satisfying.
Some hidden mechanisms are at work, mechanisms that are transfered to children by training.
Children learn how to reason mostly by imitation.
I believe it is a very bad idea to teach a child how to reason by exposing him to logic, for that would be akin teaching a child how to walk by exposing him to the laws of mechanics, or teaching a child how to sing by exposing him to music theory, or teaching a child how to speak by exposing him to the rules of grammar.
It is preposterous to try to teach a child how to speak by explaining the rules of grammar, because language is necessary in order to communicate the rules of grammar.
Such circularity exists in the case of logic too.
One cannot learn logic, unless one already knows how to reason.&lt;/P&gt;&lt;P&gt;Are then mechanics, music theory, grammar, and logic useless?
Although mechanics does not help people to walk, it does help them to build cars; although grammar does not help people to speak, it does help them to communicate effectively.
Mechanics is useful because cars are useful; grammar is useful because the ability to communicate is useful.
Note that people built carts before understanding the laws of mechanics and they probably built engines before understanding the laws of thermodynamics.
However, cars are &lt;EM&gt;better&lt;/EM&gt; because we understand the laws of mechanics.
Similarly, people may communicate without knowing grammar.
However, people communicate &lt;EM&gt;better&lt;/EM&gt; if they follow the rules of grammar.&lt;/P&gt;&lt;P&gt;Logic enriches the way people think. 
A logician immediately parses the sentence &amp;#X201C;if you do not solve your homework then you will not receive a high grade, therefore you will receive a high grade only if you solve your homework&amp;#X201D; as &amp;#X201C;(&lt;EM&gt;if&lt;/EM&gt; (you do &lt;EM&gt;not&lt;/EM&gt; solve your homework) &lt;EM&gt;then&lt;/EM&gt; (you will &lt;EM&gt;not&lt;/EM&gt; receive a high grade), &lt;EM&gt;therefore&lt;/EM&gt; ((you will receive a high grade) &lt;EM&gt;only if&lt;/EM&gt; (you solve your homework))&amp;#X201D;.
Certain &lt;EM&gt;logical connectives&lt;/EM&gt; (like &lt;EM&gt;if&lt;/EM&gt;&amp;#X2026;&lt;EM&gt;then&lt;/EM&gt;, &lt;EM&gt;not&lt;/EM&gt;, &lt;EM&gt;therefore&lt;/EM&gt;, &lt;EM&gt;only if&lt;/EM&gt;) are emphasized, because logic cares more about how statements are chained together into an argument, rather than what those statements mean.
In fact, when being careful about what they say (or hear), logicians will likely translate on the fly that statement into a symbolic form that makes it easier to visualize the structure: &amp;#X201C;(&amp;#XAC; &lt;I&gt;p&lt;/I&gt; &amp;#X21D2; &amp;#XAC; &lt;I&gt;q&lt;/I&gt;) &amp;#X21D2; (&lt;I&gt;q&lt;/I&gt; &amp;#X21D2; &lt;I&gt;p&lt;/I&gt;), where &lt;I&gt;p&lt;/I&gt;&amp;#XA0;stands for &amp;#X2018;you solve your homework&amp;#X2019; and &lt;I&gt;q&lt;/I&gt;&amp;#XA0;stands for &amp;#X2018;you will receive a high grade&amp;#X2019;&amp;#X201D;.
Here, logical connectives are represented by some standard symbols (&amp;#XAC;&amp;#XA0;and&amp;#XA0;&amp;#X21D2;) and the rest is hidden behind letters (&lt;I&gt;p&lt;/I&gt;&amp;#XA0;and&amp;#XA0;&lt;I&gt;q&lt;/I&gt;).&lt;/P&gt;&lt;!--CUT END --&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5829875-3802239172289301481?l=rgrig.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/RgrigsBlog/~4/dVmdOa6z9MM" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://rgrig.blogspot.com/feeds/3802239172289301481/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://rgrig.blogspot.com/2010/07/mathematical-logic-1.html#comment-form" title="5 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5829875/posts/default/3802239172289301481?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5829875/posts/default/3802239172289301481?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/RgrigsBlog/~3/dVmdOa6z9MM/mathematical-logic-1.html" title="Mathematical Logic 1" /><author><name>Radu Grigore</name><uri>https://profiles.google.com/101644137139656854756</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh4.googleusercontent.com/-qUUZcf9ulqQ/AAAAAAAAAAI/AAAAAAAADnE/AVKMToUdkMQ/s512-c/photo.jpg" /></author><thr:total>5</thr:total><feedburner:origLink>http://rgrig.blogspot.com/2010/07/mathematical-logic-1.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CEEEQX06fSp7ImA9WxFWFUU.&quot;"><id>tag:blogger.com,1999:blog-5829875.post-6612345237072046023</id><published>2010-06-03T17:30:00.000+01:00</published><updated>2010-06-03T17:30:00.315+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-06-03T17:30:00.315+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="learning" /><category scheme="http://www.blogger.com/atom/ns#" term="coding" /><title>Are these BDDs the same?</title><content type="html">&lt;i&gt;This is exercise 7.1.4-12 in TAoCP. It is easy, but somehow I liked
the solution.&lt;/i&gt;

&lt;p&gt;A BDD (&lt;b&gt;b&lt;/b&gt;inary &lt;b&gt;d&lt;/b&gt;ecision &lt;b&gt;d&lt;/b&gt;iagram) is a data structure
that encodes boolean functions. Each node has a &lt;i&gt;variable&lt;/i&gt; and two
children, &lt;i&gt;low&lt;/i&gt; and &lt;i&gt;high&lt;/i&gt;. To make it concrete, let's pick a
C-language structure.&lt;/p&gt;

&lt;pre class="prettyprint"&gt;
struct dd_node {
  int V; // variable, at least 1 and at most N
  int L, H; // indexes in nodes
};
struct dd_node nodes[nodes_size];
&lt;/pre&gt;

&lt;p&gt;A valid BDD representation obeys a few constraints.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;span class="prettyprint"&gt;nodes[k].L!=nodes[k].H&lt;/span&gt; 
  for &lt;span class="prettyprint"&gt;k&amp;ge;2&lt;/span&gt;&lt;/li&gt;

  &lt;li&gt;&lt;span class="prettyprint"&gt;nodes[k].L==nodes[k].H==k&lt;/span&gt;
  for &lt;span class="prettyprint"&gt;k&amp;lt;2&lt;/span&gt;&lt;/li&gt;

  &lt;li&gt;&lt;span class="prettyprint"&gt;nodes[nodes[k].X].V&amp;gt;nodes[k].V&lt;/span&gt;
  for &lt;span class="prettyprint"&gt;k&amp;ge;2&lt;/span&gt; and X either L or R&lt;/li&gt;

  &lt;li&gt;&lt;span class="prettyprint"&gt;nodes[k]==nodes[kk]&lt;/span&gt; implies
  &lt;span class="prettyprint"&gt;k==kk&lt;/span&gt;&lt;/li&gt;

  &lt;li&gt;For all &lt;span class="prettyprint"&gt;2&amp;le;k&amp;lt;nodes_size&lt;/span&gt;
  there is a &lt;span class="prettyprint"&gt;kk&lt;/span&gt; such that
  &lt;span class="prettyprint"&gt;nodes[kk].L==k || nodes[kk].R==k&lt;/span&gt;.
&lt;/ol&gt;

&lt;p&gt;Each such node basically encodes a &lt;span class="prettyprint"&gt;(!v?l:h)&lt;/span&gt;
expression. For example, if &lt;span class="prettyprint"&gt;value[V]&lt;/span&gt; is the
value of variable &lt;span class="prettyprint"&gt;V&lt;/span&gt; then the represented
boolean function is evaluated by &lt;span class="prettyprint"&gt;
eval(value, nodes_size-1)&lt;/span&gt;.&lt;/p&gt;

&lt;pre class="prettyprint"&gt;
int eval(int* value, int k) {
  if (k &amp;lt; 2) return k;
  return !value[nodes[k].V]? eval(value, nodes[k].L) : eval(value, nodes[k].H);
}
&lt;/pre&gt;

&lt;p&gt;Here comes the problem. Suppose you are given two BDDs,
&lt;span class="prettyprint"&gt;nodes1&lt;/span&gt; of size &lt;span class="prettyprint"&gt;s1&lt;/span&gt;
and
&lt;span class="prettyprint"&gt;nodes2&lt;/span&gt; of size &lt;span class="prettyprint"&gt;s2&lt;/span&gt;.
Design an algorithm to decide if they represent the same boolean function.
And, by the way, do not use a stack, not even the call stack.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5829875-6612345237072046023?l=rgrig.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/RgrigsBlog/~4/ctldJgCznnE" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://rgrig.blogspot.com/feeds/6612345237072046023/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://rgrig.blogspot.com/2010/06/are-these-bdds-same.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5829875/posts/default/6612345237072046023?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5829875/posts/default/6612345237072046023?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/RgrigsBlog/~3/ctldJgCznnE/are-these-bdds-same.html" title="Are these BDDs the same?" /><author><name>Radu Grigore</name><uri>https://profiles.google.com/101644137139656854756</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh4.googleusercontent.com/-qUUZcf9ulqQ/AAAAAAAAAAI/AAAAAAAADnE/AVKMToUdkMQ/s512-c/photo.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://rgrig.blogspot.com/2010/06/are-these-bdds-same.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CkENR3k5eCp7ImA9WxFSE0k.&quot;"><id>tag:blogger.com,1999:blog-5829875.post-6381312996293651070</id><published>2010-04-15T15:09:00.002+01:00</published><updated>2010-04-15T15:11:36.720+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-04-15T15:11:36.720+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="research" /><title>Thesis and Move to London</title><content type="html">&lt;p&gt;&lt;i&gt;I submitted my thesis and I joined Queen Mary, University of London.&lt;/i&gt;&lt;/p&gt;

&lt;p&gt;
On 26th of March I submitted my 
&lt;a href="http://rgrig.appspot.com/static/papers/rgrig_submitted_thesis.pdf"&gt;
PhD thesis&lt;/a&gt;. I tried to make it easy to understand without much
background knowledge. If you read (parts of) it, then please
consider sending me feedback, as I can make corrections for the
final version.&lt;/p&gt;

&lt;p&gt;Now I work in Queen Mary, University of London in the &lt;a href="http://www.dcs.qmul.ac.uk/research/logic/"&gt;Theory Group&lt;/a&gt;,
on the &lt;a href="http://www.jstarverifier.org/"&gt;jStar&lt;/a&gt; project.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5829875-6381312996293651070?l=rgrig.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/RgrigsBlog/~4/EB3SLhbCqGw" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://rgrig.blogspot.com/feeds/6381312996293651070/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://rgrig.blogspot.com/2010/04/thesis-and-move-to-london.html#comment-form" title="3 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5829875/posts/default/6381312996293651070?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5829875/posts/default/6381312996293651070?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/RgrigsBlog/~3/EB3SLhbCqGw/thesis-and-move-to-london.html" title="Thesis and Move to London" /><author><name>Radu Grigore</name><uri>https://profiles.google.com/101644137139656854756</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh4.googleusercontent.com/-qUUZcf9ulqQ/AAAAAAAAAAI/AAAAAAAADnE/AVKMToUdkMQ/s512-c/photo.jpg" /></author><thr:total>3</thr:total><feedburner:origLink>http://rgrig.blogspot.com/2010/04/thesis-and-move-to-london.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DUQASHo4fip7ImA9WxBbGUQ.&quot;"><id>tag:blogger.com,1999:blog-5829875.post-8868624955999932266</id><published>2010-03-19T11:15:00.000Z</published><updated>2010-03-19T11:15:49.436Z</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-03-19T11:15:49.436Z</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="opinion" /><category scheme="http://www.blogger.com/atom/ns#" term="teaching" /><title>Adding is in Nature’s definition</title><content type="html">&lt;p&gt;&lt;i&gt;Below is one of the funniest and at the same time saddest course descriptions I ever saw.&lt;/i&gt;&lt;/p&gt;

&lt;p&gt;As an undergrad, I took a course of &lt;a href="http://bip.golana.pub.ro/~tudor/"&gt;Tudor Niculiu&lt;/a&gt;. I believe the course was supposed to be on OOP, but the lectures gave us some sort of introduction to philosophy. Luckily, there was no exam&amp;mdash;we just had to write a small C++ program. Then we had to print the program (poor trees!) and go to an oral examination where the lecturer wanted to see, apparently, if we have &lt;i&gt;any&lt;/i&gt; idea about how the program works.&lt;/p&gt;

&lt;p&gt;A colleague once told me that &amp;quot;Niculiu used to be normal, but then he had an accident that affected his brain.&amp;quot; If that's true, then it is quite sad. In any case, I have trouble understanding how someone who describes his course as follows is allowed to teach in what is supposed to be one of the best colleges in Romania.&lt;/p&gt;

&lt;p&gt;Algorithms and Data Structures:&lt;/p&gt;

&lt;blockquote&gt;
Adding is in Nature’s definition. However, the inverse operation, subtraction, needs negative numbers. We close mathematically the Nature to an integer that opens the physics for recognizing the limits of the Reason - electrons, in the meanwhile, attracting marvelous engineering solutions for different technologies. Electronics is among the most advanced engineering sciences; therefore, it has to be practiced by the most conscient human beings. Recurrent addition is multiplication, a most important parameter for the Nature. Mathematics closes the integers to the multiplication inverse, defining the rational numbers. These are not more than the naturals, but we can do many useful things with the Reason, from strategy to computer. So "what else do we need?" say too many, forgetting that the limits of the, so-called, pure Reason are caused by the fact that it bounds itself to close the Adaptability to discrete/ sequential operations. Thanks God, neither mathematicians, nor physicists accept all-happiness. They discover in three ways - order, algebra, analysis - which assisted all of them to think together, the power of continuum and that of the patience. In this context, “mathematicians and physicists” means the theorem, natural laws, or even new approach discoverers, and more, the engineers that understand the essential of mathematics and of physics.&lt;/blockquote&gt;

&lt;p&gt;To his credit, in the first part there's a glimmer of the (nice!) axiomatic way of defining numbers.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5829875-8868624955999932266?l=rgrig.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/RgrigsBlog/~4/EtfhHLhrRRU" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://rgrig.blogspot.com/feeds/8868624955999932266/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://rgrig.blogspot.com/2010/03/adding-is-in-natures-definition.html#comment-form" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5829875/posts/default/8868624955999932266?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5829875/posts/default/8868624955999932266?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/RgrigsBlog/~3/EtfhHLhrRRU/adding-is-in-natures-definition.html" title="Adding is in Nature’s definition" /><author><name>Radu Grigore</name><uri>https://profiles.google.com/101644137139656854756</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh4.googleusercontent.com/-qUUZcf9ulqQ/AAAAAAAAAAI/AAAAAAAADnE/AVKMToUdkMQ/s512-c/photo.jpg" /></author><thr:total>2</thr:total><feedburner:origLink>http://rgrig.blogspot.com/2010/03/adding-is-in-natures-definition.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DUQDRn0zfyp7ImA9WxBbGEg.&quot;"><id>tag:blogger.com,1999:blog-5829875.post-8026315953613734605</id><published>2010-03-17T20:10:00.001Z</published><updated>2010-03-17T20:22:57.387Z</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-03-17T20:22:57.387Z</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="puzzle" /><title>Typesetting Inequalities</title><content type="html">&lt;P&gt;&lt;I&gt;These are two puzzles I arrived at while working on my
PhD thesis. I know the answers but not because I derived them. I
think both puzzles are quite hard. Have fun!&lt;/I&gt;&lt;/P&gt;&lt;P&gt;&lt;B&gt;Typesetting.&lt;/B&gt; As you know from a previous post,
&lt;A HREF="http://rgrig.blogspot.com/2010/03/tex-text-files.html"&gt;ViM
doesn&amp;#X2019;t handle paragraph reformatting&lt;/A&gt; very well in L&lt;sup&gt;A&lt;/sup&gt;T&lt;sub&gt;E&lt;/sub&gt;X, so I
wrote a small tool. Given word lengths &lt;I&gt;l&lt;/I&gt;&lt;SUB&gt;1&lt;/SUB&gt;,&amp;#XA0;&lt;I&gt;l&lt;/I&gt;&lt;SUB&gt;2&lt;/SUB&gt;, &amp;#X2026;,&amp;#XA0;&lt;I&gt;l&lt;/I&gt;&lt;SUB&gt;&lt;I&gt;n&lt;/I&gt;&lt;/SUB&gt;
we want to insert line breaks such that (1)&amp;#XA0;no line is longer
than&amp;#XA0;&lt;I&gt;l&lt;/I&gt; and (2)&amp;#XA0;the shortest line is as long as possible. Here&amp;#X2019;s
the challenge: do it in &lt;I&gt;O&lt;/I&gt;(&lt;I&gt;n&lt;/I&gt;)&amp;#XA0;time.&lt;/P&gt;&lt;P&gt;&lt;B&gt;Inequality.&lt;/B&gt; Show that the following inequality has no
solution in non-negative reals (or integers if you prefer).&lt;/p&gt;

&lt;img border="0" height="43" src="http://4.bp.blogspot.com/_byUC16gzOKM/S6E2t8eJNpI/AAAAAAAAB9A/svkvpSX8Wmo/s640/puzzle000.png" width="640" /&gt;

&lt;p&gt;
PS: I know the answers because of 
&lt;a href="http://11011110.livejournal.com/"&gt;11011110&lt;/a&gt;
and, respectively,
&lt;a href="http://geomblog.blogspot.com/"&gt;geomblog&lt;/a&gt;.
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5829875-8026315953613734605?l=rgrig.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/RgrigsBlog/~4/coIyJXwdR-Q" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://rgrig.blogspot.com/feeds/8026315953613734605/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://rgrig.blogspot.com/2010/03/typesetting-inequalities.html#comment-form" title="3 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5829875/posts/default/8026315953613734605?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5829875/posts/default/8026315953613734605?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/RgrigsBlog/~3/coIyJXwdR-Q/typesetting-inequalities.html" title="Typesetting Inequalities" /><author><name>Radu Grigore</name><uri>https://profiles.google.com/101644137139656854756</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh4.googleusercontent.com/-qUUZcf9ulqQ/AAAAAAAAAAI/AAAAAAAADnE/AVKMToUdkMQ/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://4.bp.blogspot.com/_byUC16gzOKM/S6E2t8eJNpI/AAAAAAAAB9A/svkvpSX8Wmo/s72-c/puzzle000.png" height="72" width="72" /><thr:total>3</thr:total><feedburner:origLink>http://rgrig.blogspot.com/2010/03/typesetting-inequalities.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DEUNRnY7fSp7ImA9WhdTEEk.&quot;"><id>tag:blogger.com,1999:blog-5829875.post-1451409261250427425</id><published>2010-03-02T17:29:00.002Z</published><updated>2011-07-07T14:44:57.805+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-07-07T14:44:57.805+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="presentation" /><title>TeX text files</title><content type="html">&lt;p&gt;&lt;i&gt;Questions for those who use LaTeX by editing text files (as opposed to those who use a WYSIWYG editor like LyX).&lt;/i&gt;&lt;/p&gt;

&lt;p&gt;
Do you use the line wrapping feature in your editor and keep each paragraph on one line or do you usually put paragraphs on multiple lines? If the latter is true then how do you maintain the lines so they aren't too long or too short? Manually or automatically? If automatically, then do you use a program like &lt;tt&gt;par&lt;/tt&gt;, a feature of your editor, or something else? If you use &lt;tt&gt;par&lt;/tt&gt;, then how do you keep it from messing things like &lt;tt&gt;\begin {equation}&amp;hellip;\end{equation}&lt;/tt&gt; and &lt;tt&gt;\begin {verbatim}&amp;hellip;\end{verbatim}&lt;/tt&gt;? (The latter is in a paragraph of its own, but the former usually not.)&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5829875-1451409261250427425?l=rgrig.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/RgrigsBlog/~4/g2p3BU21cW8" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://rgrig.blogspot.com/feeds/1451409261250427425/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://rgrig.blogspot.com/2010/03/tex-text-files.html#comment-form" title="10 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5829875/posts/default/1451409261250427425?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5829875/posts/default/1451409261250427425?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/RgrigsBlog/~3/g2p3BU21cW8/tex-text-files.html" title="TeX text files" /><author><name>Radu Grigore</name><uri>https://profiles.google.com/101644137139656854756</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh4.googleusercontent.com/-qUUZcf9ulqQ/AAAAAAAAAAI/AAAAAAAADnE/AVKMToUdkMQ/s512-c/photo.jpg" /></author><thr:total>10</thr:total><feedburner:origLink>http://rgrig.blogspot.com/2010/03/tex-text-files.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CUQGQnY-eip7ImA9WxBWGEk.&quot;"><id>tag:blogger.com,1999:blog-5829875.post-8706017486071129682</id><published>2010-02-10T19:35:00.002Z</published><updated>2010-02-10T23:08:43.852Z</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-02-10T23:08:43.852Z</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="research" /><title>Graph Clustering and Answer Set Programming</title><content type="html">&lt;p&gt;&lt;i&gt;A short summary of two articles I read on the bus.&lt;/i&gt;&lt;/p&gt;


&lt;p&gt;&lt;b&gt;Cut-clustering&lt;/b&gt;. &lt;a
href="http://scholar.google.com/scholar?cluster=13364084414547474651"&gt;
Flake, Tarjan, and Tsioutsiouliklis&lt;/a&gt; published in 2004
an algorithm for clustering graphs. I always enjoy reading
articles co-authored by Tarjan because they are so clear and
so light on notation. The algorithm acts on undirected graphs.
First, a special node is connected to all other nodes thru edges
of cost &amp;alpha;, a parameter. Initially all nodes are their own
cluster, but clusters will be merged as nodes are processed.
To heuristically speed up the runtime, nodes are processed in
decreasing order of their &amp;quot;connectivity&amp;quot;, which is the
sum of costs on adjacent edges. Processing one node consists of
finding a minimum cut between it and the special node; for all
nodes on the same side of the cut as the node being processed
(1) we mark them as touched and (2) we merge their clusters.
Touched nodes are not processed further. (It doesn't hurt but it's
faster not to process them.) That's it.&lt;/p&gt;

&lt;p&gt;The article discusses why this works and what properties the
resulting clustering has. In short, by making &amp;alpha; bigger you
get smaller clusters, but there is no fine control on the number
and size of clusters. On the bright side, the &amp;quot;quality&amp;quot;
of the clusters is good. Also, by varying &amp;alpha; the resulting
clustering is hierarchical.&lt;/p&gt;

&lt;p&gt;The authors present three case studies:
the graph of citations for papers in &lt;a
href="http://citeseer.ist.psu.edu/"&gt;CiteSeer&lt;/a&gt;, websites close
to &lt;a href="http://www.dmoz.org/"&gt;dmoz&lt;/a&gt;, and something about
websites discussing 9/11. The CiteSeer results are interesting.
Here are the top level clusters:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;61837 paper on image, learning, problem, linear, algorithm
  &lt;ul&gt;
  &lt;li&gt;36986 papers on learning, image, neural, recognition, knowledge&lt;/li&gt;
  &lt;li&gt;8179 papers on numerical, equations, linear, matrix, nonlinear&lt;/li&gt;
  &lt;li&gt;3650 papers on wavelets, coding, transform&lt;/li&gt;
  &lt;li&gt;2386 papers on constraint satisfaction&lt;/li&gt;
  &lt;li&gt;2377 papers on bayesian, monte carlo, markov&lt;/li&gt;
  &lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;34353 papers on parallel, memory, distributed, execution, processors&lt;/li&gt;
&lt;li&gt;20593 papers on network, service, internet, security, traffic&lt;/li&gt;
&lt;li&gt;15415 papers on logic programming, software, language, semantics&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It would be interesting to compare experimentally this approach with
something like &lt;a href="http://en.wikipedia.org/wiki/K-means_clustering"&gt;
&lt;i&gt;k&lt;/i&gt;-means&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Answer set programming&lt;/b&gt;.
In 2002, &lt;a href="http://scholar.google.com/scholar?cluster=2093849466635299524"&gt;
Lifschitz&lt;/a&gt; wrote a nice introduction to answer set programming. I shall
summarize only the basics. A program that finds a big clique in
a graph looks like this:
&lt;/p&gt;

&lt;pre&gt;
const j = 3.
vertex(0..5).  % there are six vertices and here are the edges...
edge(0,1). edge(1,2). edge(2,0). edge(3,4). edge(4.5). edge(5,3). edge(4,0). edge(2,5).

j {in(X) : vertex(X)}. % we want at least 3 vertices ``in'' the clique
joined(X,Y) :- edge(X,Y).
joined(X,Y) :- edge(Y,X).
:- in(X), in(Y), X!=Y, vertex(X), vertex(Y), not joined(X,Y).
  % if X and Y are not joined, then they can't be two distinct selected vertices
&lt;/pre&gt;

&lt;p&gt;&lt;a href="http://www.tcs.hut.fi/Software/smodels/"&gt;SMODELS&lt;/a&gt; 
runs the above program. Beware, you need to change the sources to
compile it with a modern GCC.&lt;/p&gt;

&lt;p&gt;The theory behind it goes as follow. There is a set &lt;i&gt;S&lt;/i&gt;
of literals, which come in pairs, the positive literal &lt;i&gt;l&lt;/i&gt;
and the negative literal -&lt;i&gt;l&lt;/i&gt;. Even if above we used some syntactic
sugar, the program is essentially a set of rules of the form:
&lt;/p&gt;

&lt;center&gt;
&lt;i&gt;A&lt;/i&gt;, &lt;b&gt;not&lt;/b&gt; &lt;i&gt;B&lt;/i&gt;, :- &lt;i&gt;C&lt;/i&gt;, &lt;b&gt;not&lt;/b&gt; &lt;i&gt;D&lt;/i&gt;
&lt;/center&gt;

&lt;p&gt;where &lt;i&gt;A&lt;/i&gt;, &lt;i&gt;B&lt;/i&gt;, &lt;i&gt;C&lt;/i&gt;, and &lt;i&gt;D&lt;/i&gt; are sets of
literals. The set &lt;i&gt;X&lt;/i&gt; is an answer set for such a program
when&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;it is consistent (it does not contain both &lt;i&gt;l&lt;/i&gt; and -&lt;i&gt;l&lt;/i&gt;) &lt;b&gt;and&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;it is an answer set for the reduct program&lt;/i&gt;
&lt;/ul&gt;

&lt;p&gt;The reduct program is obtained
by keeping only the rules for which &lt;i&gt;X&lt;/i&gt;&amp;supe;&lt;i&gt;B&lt;/i&gt; and
&lt;i&gt;X&lt;/i&gt;&amp;cap;&lt;i&gt;D&lt;/i&gt;=&amp;empty; and by removing the &lt;b&gt;not&lt;/b&gt; parts
of the kept rules. The set &lt;i&gt;X&lt;/i&gt; is an answer set for a &lt;b&gt;not&lt;/b&gt;-free
program when
&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;i&gt;X&lt;/i&gt; is closed under the program &lt;b&gt;and&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;i&gt;X&lt;/i&gt; is a minimal (with respect to set inclusion)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Finally, a set &lt;i&gt;X&lt;/i&gt; is closed under a (&lt;b&gt;not&lt;/b&gt;-free) program
when for each rule&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;i&gt;C&lt;/i&gt;&amp;nsub;&lt;i&gt;X&lt;/i&gt; &lt;b&gt;or&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;i&gt;A&lt;/i&gt;&amp;sube;&lt;i&gt;X&lt;/i&gt;
&lt;/ul&gt;

&lt;p&gt;A nice exercise would be to find an encoding of SAT in answer set
programming. (Lifschitz has a solution.) The converse is the subject
of a paper by 
&lt;a href="http://scholar.google.com/scholar?cluster=3915378472339293156"&gt;
Fangzhen Lin and Yuting Zhao&lt;/a&gt;
from 2002 (but published in 2004).&lt;/p&gt;

&lt;p&gt;&lt;b&gt;update 1&lt;/b&gt;: when &amp;alpha; is bigger the clusters are &lt;i&gt;smaller&lt;/i&gt;.&lt;br/&gt;
&lt;b&gt;update 2&lt;/b&gt;: fixed the problem pointed out by Mikolas in the first comment.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5829875-8706017486071129682?l=rgrig.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/RgrigsBlog/~4/1ZnhRLZfa2o" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://rgrig.blogspot.com/feeds/8706017486071129682/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://rgrig.blogspot.com/2010/02/graph-clustering-and-answer-set.html#comment-form" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5829875/posts/default/8706017486071129682?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5829875/posts/default/8706017486071129682?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/RgrigsBlog/~3/1ZnhRLZfa2o/graph-clustering-and-answer-set.html" title="Graph Clustering and Answer Set Programming" /><author><name>Radu Grigore</name><uri>https://profiles.google.com/101644137139656854756</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh4.googleusercontent.com/-qUUZcf9ulqQ/AAAAAAAAAAI/AAAAAAAADnE/AVKMToUdkMQ/s512-c/photo.jpg" /></author><thr:total>2</thr:total><feedburner:origLink>http://rgrig.blogspot.com/2010/02/graph-clustering-and-answer-set.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DUIDRnkzfip7ImA9WxBSFko.&quot;"><id>tag:blogger.com,1999:blog-5829875.post-6405980314739567662</id><published>2009-12-24T17:59:00.002Z</published><updated>2009-12-24T17:59:37.786Z</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-12-24T17:59:37.786Z</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="random" /><title>Green Tree</title><content type="html">&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://4.bp.blogspot.com/_byUC16gzOKM/SzOr_JMy7QI/AAAAAAAAB4g/sSU0_1FZFQA/s1600-h/xmas.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://4.bp.blogspot.com/_byUC16gzOKM/SzOr_JMy7QI/AAAAAAAAB4g/sSU0_1FZFQA/s640/xmas.png" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;/div&gt;
&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5829875-6405980314739567662?l=rgrig.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/RgrigsBlog/~4/aoEJPcxvQCE" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://rgrig.blogspot.com/feeds/6405980314739567662/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://rgrig.blogspot.com/2009/12/green-tree.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5829875/posts/default/6405980314739567662?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5829875/posts/default/6405980314739567662?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/RgrigsBlog/~3/aoEJPcxvQCE/green-tree.html" title="Green Tree" /><author><name>Radu Grigore</name><uri>https://profiles.google.com/101644137139656854756</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh4.googleusercontent.com/-qUUZcf9ulqQ/AAAAAAAAAAI/AAAAAAAADnE/AVKMToUdkMQ/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://4.bp.blogspot.com/_byUC16gzOKM/SzOr_JMy7QI/AAAAAAAAB4g/sSU0_1FZFQA/s72-c/xmas.png" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://rgrig.blogspot.com/2009/12/green-tree.html</feedburner:origLink></entry></feed>

