<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Mathematical Pamphlet &#187; Reading</title>
	<atom:link href="http://www.kennknowles.com/blog/category/reading/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.kennknowles.com/blog</link>
	<description>computational and digestible</description>
	<lastBuildDate>Thu, 29 May 2008 01:38:46 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>What is defunctionalization?</title>
		<link>http://www.kennknowles.com/blog/2008/05/24/what-is-defunctionalization/</link>
		<comments>http://www.kennknowles.com/blog/2008/05/24/what-is-defunctionalization/#comments</comments>
		<pubDate>Sat, 24 May 2008 21:57:15 +0000</pubDate>
		<dc:creator>Kenn</dc:creator>
				<category><![CDATA[Haskell]]></category>
		<category><![CDATA[Mathematics]]></category>
		<category><![CDATA[Reading]]></category>
		<category><![CDATA[church encoding]]></category>
		<category><![CDATA[continuations]]></category>
		<category><![CDATA[defunctionalization]]></category>
		<category><![CDATA[operational semantics]]></category>

		<guid isPermaLink="false">http://www.kennknowles.com/blog/2008/05/24/what-is-defunctionalization/</guid>
		<description><![CDATA[I recently gave a little demonstration entitled &#8220;What is Defunctionalization?&#8221; for UCSC TWIGS (the acronym, stolen from a similar seminar in the the U. Mass. math department, stands for The &#8220;What Is &#8230; ?&#8221; Graduate Seminar).  The inspiration for this talk was just to present what I&#8217;d learned after Conor McBride&#8217;s brilliant presentation at [...]]]></description>
			<content:encoded><![CDATA[<p>I recently gave a little demonstration entitled &#8220;What is Defunctionalization?&#8221; for <a href="http://slang.soe.ucsc.edu/wiki/doku.php?id=twigs#spring08">UCSC TWIGS</a> (the acronym, stolen from a <a href="http://www.math.umass.edu/~hajir/twigsf03.html">similar seminar</a> in the the U. Mass. math department, stands for <strong>T</strong>he &#8220;<strong>W</strong>hat <strong>I</strong>s &#8230; ?&#8221; <strong>G</strong>raduate <strong>S</strong>eminar).  The inspiration for this talk was just to present what I&#8217;d learned after Conor McBride&#8217;s brilliant presentation at POPL&#8217;08 drove me to put the words &#8220;Olivier Danvy defunctionalize continuation&#8221; into Google.</p>

<p>I coded the simplest examples from</p>

<ul>
<li><a href="http://www.brics.dk/RS/01/23/">Defunctionalization at work</a>. O Danvy, LR Nielsen.  PPDP 2001.</li>
</ul>

<p>in literate Haskell for the audience, and also showed off QuickCheck a little to make sure the translation was correct (finding one error, if I recall).</p>

<p><center><img src='http://www.kennknowles.com/blog/wp-content/uploads/2008/05/nolambda-med.png' alt='nolambda-med.png' /></center></p>

<p>This blog post is a merging of my talk outline and new stuff that came up live.  Try loading it up in GHCi or Haskell-mode and running the examples and QuickCheck properties.
<span id="more-62"></span></p>

<pre>
> {-# LANGUAGE RankNTypes #-}

> import Prelude hiding (reverse)
> import Control.Monad
> import Control.Monad.Cont
> import Test.QuickCheck
</pre>

<p>Broadly, defunctionalization is transforming a program to eliminate higher-order functions.  Rather than focus on its use for compilation (see this H Cejtin, S Jagannathan, S Weeks <a href="http://mlton.org/pages/References/attachments/CejtinEtAl00.pdf">paper on MLTon</a>)
or analyses (see <a href="http://www-users.cs.york.ac.uk/~ndm/firstify/">Firstify</a> from N Mitchell and C Runciman). I wanted to emphasize its use in understanding your own program, along the lines of Wand&#8217;s <a href="http://www.diku.dk/undervisning/2005e/224/papers/Wand80.pdf">Continuation-Based Program Transformation Strategies</a> (JACM 1980).</p>

<p>Here is the first example from Danvy.</p>

<pre>
> aux1 :: (Int -> Int) -> Int
> aux1 f = f 1 + f 10
>
> main1 x y b = (aux1 (\z -> x + z)) * 
>               (aux1 (\z -> if b then y + z else y - z))
</pre>

<p>Defunctionalization replaces all the first-class functions with an explicit data structure <code>Lam1</code> and a global <code>apply1</code> function, essentially embedding a mini-interpreter for just those lambda terms occurring in the program.</p>

<pre>
> data Lam1 = Lam1A Int      -- (Lam1A x)   ~ (\z -> x + z)
>           | Lam1B Int Bool -- (Lam1B y b) ~ (\z -> if b then y + z else y - z)
>
> apply1 :: Lam1 -> Int -> Int
> apply1 (Lam1A x)   z = x + z
> apply1 (Lam1B y b) z = if b then y + z else y - z
>
> aux1defun :: Lam1 -> Int
> aux1defun f = (apply1 f 1) + (apply1 f 10)
>
> main1defun x y b = (aux1defun (Lam1A x)) *
>                    (aux1defun (Lam1B y b))
</pre>

<p>Is it correct?  Ask quickcheck:</p>

<pre>
> prop1 x y b = (main1 x y b == main1defun x y b)

*Main> quickCheck prop1
+++ OK, passed 100 tests.
</pre>

<p>Next example: flattening a binary tree</p>

<pre>
> data BinaryTree a = Leaf a
>                   | Node (BinaryTree a) (BinaryTree a)
</pre>

<p>First, there is the straightforward, inefficient version of flatten</p>

<pre>
> flatten (Leaf x) = [x]
> flatten (Node t1 t2) = (flatten t1) ++ (flatten t2)
</pre>

<p>We can represent our output with <a href="http://www.cse.unsw.edu.au/~dons/dlist.html">difference lists</a> offering O(1) append.</p>

<pre>
> flatten' t = walk t []
>   where walk (Leaf x)     = (x:)
>         walk (Node t1 t2) = (walk t1) . (walk t2)
</pre>

<p>And now that we&#8217;ve introduced a bunch of first-class functions, let&#8217;s see what happens when we defunctionalize them.</p>

<pre>
> data LamBTree a = LamBTreeA a -- (x:)
>                 | LamBTreeB (LamBTree a) (LamBTree a) -- (u . v)
>
> applyBTree (LamBTreeA x)   l = x:l
> applyBTree (LamBTreeB u v) l = applyBTree u (applyBTree v l)
>
> flatten_defun t = applyBTree (walk t) []
>   where walk (Leaf x)     = LamBTreeA x
>         walk (Node t1 t2) = LamBTreeB (walk t1) (walk t2)
</pre>

<p>Note how <code>LamBTree</code> looks just like the definition of <code>BinaryTree</code>, because it is a catamorphism, hence a hylomorphism, i.e. a recursive function with a call tree that looks like a <code>BinaryTree</code> or whatever structure you are hylo&#8217;ing over.  (See <a href="http://www.fing.edu.uy/inco/cursos/proggen/Articulos/sorting.ps.gz">Sorting morphisms</a> for a beautiful examples of using this to understand your program (L Augusteijn.  AFP 1998)).  So <code>walk</code> is pretty much the identity function on trees, and then <code>applyBTree</code> is a flatten function with an accumulating parameter.  Ignoring the intermediate structure, then we see defunctionalization as a way to derive accumulating parameters.</p>

<pre>
> prop_flatten :: BinaryTree Int -> Bool
> prop_flatten t = (flatten_defun t == flatten t)

*Main> quickCheck prop_flatten
OK, passed 100 tests
</pre>

<h2>Defunctionalization as an inverse to church encoding</h2>

<p>This was possibly my favorite part of Danvy&#8217;s paper, but I unfortunately had to elide it from my talk as being slightly
too esoteric for the mixed crowd.</p>

<p>Let us suppose that tuples were not built in to Haskell but we needed to make them ourselves.  The data type and destructors
would look like this:</p>

<pre>
> data MyPair a b = P a b 
>                 deriving (Eq,Show)
>
> myPair x y    = P x y
> myFst (P x y) = x
> mySnd (P x y) = y
</pre>

<p>And we can ask Quickcheck to test extensionality.</p>

<pre>
> prop_pair :: MyPair Int Int -> Bool
> prop_pair p = (p == myPair (myFst p) (mySnd p))

*Main> quickCheck prop_pair
+++ OK, passed 100 tests.
</pre>

<p>So, if you recall whatever lambda-calculus course you may have taken,
we can represent them with only functions.  I like having rank-N
type available for this.</p>

<pre>
> type ChurchPair a b = (forall c . a -> b -> (a -> b -> c) -> c)

> churchPair x y = (\operation -> operation x y)
> churchFst  p   = p (\x y -> x)
> churchSnd  p   = p (\x y -> y)
</pre>

<p>Rather than make an <code>Arbitrary</code> instance, I&#8217;ll settle for reduction
rules in this case.</p>

<pre>
> prop_churchPair :: Int -> Int -> Bool
> prop_churchPair x y = (x == churchFst (churchPair x y)) &#038;&#038;
>                       (y == churchSnd (churchPair x y))

*Main> quickCheck prop_churchPair
+++ OK, passed 100 tests.
</pre>

<p>But now I&#8217;ve introduced a bunch of higher-order functions, so we just <em>have to</em> see how they defunctionalize!</p>

<pre>
> data LamSelector = LamFst | LamSnd
> applySelector (LamFst) x y = x
> applySelector (LamSnd) x y = y
>
> data LamPair a b = LamPair a b
> applyPair (LamPair x y) operation = applySelector operation x y
>
> defunPair x y = (LamPair x y)
> defunFst  p   = applyPair p LamFst
> defunSnd  p   = applyPair p LamSnd
</pre>

<p>You can see that this just reproduces the original, modulo inlining!</p>

<p>Now let&#8217;s church-encode <code>BinaryTree</code> as its own fold (or catamorphism, if you like).  So we have something to defunctionalize, let&#8217;s write <code>churchDepth</code> to calculate the depth of the tree.</p>

<pre>
> type ChurchTree a = forall c. (a -> c) -> (c -> c -> c) -> c

> churchLeaf x     = \onLeaf onNode -> onLeaf x
> churchNode t1 t2 = \onLeaf onNode -> onNode (t1 onLeaf onNode) (t2 onLeaf onNode)
>
> churchFold onLeaf onNode t = t onLeaf onNode

> churchDepth t = t (\x -> 0) (\d1 d2 -> 1 + (d1 `max` d2))
</pre>

<p>Acknowledging that the church encoding is just the fold, we can defunctionalize the fold over any functor to recover the data type. Anyhow&#8230;</p>

<pre>
> data LamLeaf = LamLeaf -- onLeaf
> applyLeaf LamLeaf x = 0
>
> data LamNode = LamNode -- onNode
> applyNode LamNode d1 d2 = 1 + (d1 `max` d2)
>
> data LamTree a = LamTreeLeaf a   -- churchLeaf
>                | LamTreeNode (LamTree a) (LamTree a) -- churchNode
>
> applyTree (LamTreeLeaf x)     onLeaf onNode = applyLeaf onLeaf x
> applyTree (LamTreeNode t1 t2) onLeaf onNode = 
>   applyNode onNode (applyTree t1 onLeaf onNode)
>                    (applyTree t2 onLeaf onNode)
> depth_defun t = applyTree t LamLeaf LamNode
</pre>

<p><code>applyTree</code> is just fold over a tree, as promised, and we&#8217;ve recovered the tree data structure.</p>

<h2>Defunctionalize your continuation</h2>

<p>Suppose you have a first-order (boring!) program.  You can&#8217;t have any fun until you find a way to introduce some first-class functions.  A classic way to introduce a gratuitous number is to convert your code into continuation-passing
style.  Let&#8217;s try it.</p>

<p>This is Danvy&#8217;s &#8217;s example of a parser to recognize the language <img src='http://www.kennknowles.com/blog/wp-content/latex/125/1252bec4b069e275d345986b87ae7665-ffffff000000.png' alt='0^n 1^n' title='0^n 1^n' class='latex' />. It is written with an auxiliary function in the <code>Maybe</code> monad to simulate throwing an exception as soon as we can reject the string.</p>

<pre>
> recognize :: [Int] -> Bool
> recognize xs = case walk xs of Just [] -> True
>                                _       -> False 
>   where 
>     walk :: [Int] -> Maybe [Int]
>     walk (0:xs') = do remaining <- walk xs'
>                       case remaining of (1:ys) -> Just ys
>                                         _      -> Nothing
>     walk xs = Just xs -- otherwise
</pre>

<p>The audience insisted that I test this, because it <em>is</em> a bit of a weird way to write a trivial function.</p>

<pre>
> prop_recognize1 n = recognize (take n (repeat 0) ++ take n (repeat 1))
> prop_recognize2 m n = (m >= 0 &#038;&#038; n >= 1 &#038;&#038; m /= n) 
>    ==> (not (recognize (take m (repeat 0) ++ take n (repeat 1))))

*Main> quickCheck prop_recognize1
+++ OK, passed 100 tests.
*Main> quickCheck prop_recognize2
+++ OK, passed 100 tests.
</pre>

<p>Now if we CPS it, we no longer need the <code>Maybe</code> because we can just discard the continuation and return <code>False</code>.</p>

<pre>
> recognize' :: [Int] -> Bool
> recognize' xs = walk xs (\xs' -> [] == xs')
>   where
>     walk :: [Int] -> ([Int] -> Bool) -> Bool
>     walk (0:xs') k = walk xs' (\rem -> case rem of (1:ys) -> k ys
>                                                    _      -> False)
>     walk xs      k = k xs -- otherwise
</pre>

<p>And defunctionalizing it</p>

<pre>
> data Continuation = ContToplevel     -- (\xs' -> null xs')
>                   | ContRecurse Continuation -- (\remaining -> ... )
>
> applyCont ContToplevel    l = (l==[])
> applyCont (ContRecurse k) l = case l of (1:ys) -> applyCont k ys
>                                         _      -> False
>
> recognize'' xs = walk xs ContToplevel
>   where
>     walk (0:xs') k = walk xs' (ContRecurse k)
>     walk xs      k = applyCont k xs
</pre>

<p>But now we can look and see that the continuation data structure is just implementing natural numbers, so we replace it by an Int.</p>

<pre>
> applyNumCont 0 []     = True
> applyNumCont k (1:xs) = applyNumCont (k-1) xs
> applyNumCont _ _      = False

> recognize_final xs = walk xs 0
>   where walk (0:xs') k = walk xs' (k+1)
>         walk xs      k = k xs
</pre>

<p>We get the program we should have written in the first place.</p>

<p>I didn&#8217;t get to the rest of this in my talk, and anyhow it is most interesting to people who play with operational semantics a lot.  This last bit is from Danvy&#8217;s paper <a href="http://www.cs.bham.ac.uk/~hxt/cw04/danvy.pdf">On Evaluation Contexts, Continuations, and The Rest of Computation</a> from the continuation workshop in 2004.</p>

<p>We have a simple arithmetic language, and two ways of giving it a semantics:  We can either <code>reduce</code> the expression a single small step, using <code>reduceAllTheWay</code> to normalize it, or we can <code>eval</code> the expression directly to a result.</p>

<pre>
> data Exp = Value Int
>          | Add Exp Exp
>
> reduce :: Exp -> Exp
> reduce (Add (Value v1) (Value v2)) = Value (v1 + v2)
> reduce (Add (Value v1) e2        ) = Add (Value v1) (reduce e2)
> reduce (Add e1         e2        ) = Add (reduce e1) e2
>
> reduceAllTheWay :: Exp -> Int
> reduceAllTheWay (Value v) = v
> reduceAllTheWay e = reduceAllTheWay (reduce e)
>
> eval :: Exp -> Int
> eval (Value v)   = v
> eval (Add e1 e2) = (eval e1) + (eval e2)
</pre>

<p>Now we CPS both of them</p>

<pre>
> reduceCPS :: Exp -> (Exp -> a) -> a
> reduceCPS (Add (Value v1) (Value v2)) k = k (Value (v1 + v2))
> reduceCPS (Add (Value v1) e2        ) k = reduceCPS e2 (\e -> k (Add (Value v1) e))
> reduceCPS (Add e1         e2        ) k = reduceCPS e1 (\e -> k (Add e e2))
>
> reduceAllTheWayCPS :: Exp -> (Int -> a) -> a
> reduceAllTheWayCPS (Value v) k = k v
> reduceAllTheWayCPS e         k = reduceCPS e (flip reduceAllTheWayCPS k)

> evalCPS :: Exp -> (Int -> a) -> a
> evalCPS (Value v)   k = k v
> evalCPS (Add e1 e2) k = evalCPS e1 (\v1 -> evalCPS e2 (\v2 -> k (v1 + v2)))
</pre>

<p>CPS code is easier to read when I write it like this</p>

<pre>
> evalCPS' :: Exp -> (Int -> a) -> a
> evalCPS' (Value v)   k = k v
> evalCPS' (Add e1 e2) k = evalCPS e1 (\v1 ->
>                          evalCPS e2 (\v2 ->
>                          k (v1+v2)  ))
</pre>

<p>and I might as well admit that Haskell already has this in the bag</p>

<pre>
> evalCPS'' :: Exp -> Cont a Int
> evalCPS'' (Value v)   = return v
> evalCPS'' (Add e1 e2) = do v1 <- evalCPS'' e1
>                            v2 <- evalCPS'' e2
>                            return (v1 + v2)
</pre>

<p>Now we defunctionalize both semantics</p>

<pre>
> data ContReduce = ContReduce  -- (flip reduceAllTheWay)
>                 | ContAddV1 Exp ContReduce -- (\e -> Add (Value v1) e)
>                 | ContAddE2 ContReduce Exp -- (\e -> Add e e2)
>
> applyContReduce :: ContReduce -> Exp -> Exp
> applyContReduce ContReduce e = e
> applyContReduce (ContAddV1 v1 k) e = applyContReduce k (Add v1 e)
> applyContReduce (ContAddE2 k e2) e = applyContReduce k (Add e e2)
>
> reduceCPSdefun :: Exp -> ContReduce -> Exp
> reduceCPSdefun (Add (Value v1) (Value v2)) k = applyContReduce k (Value (v1 + v2))
> reduceCPSdefun (Add (Value v1) e2        ) k = reduceCPSdefun e2 (ContAddV1 (Value v1) k)
> reduceCPSdefun (Add e1         e2        ) k = reduceCPSdefun e1 (ContAddE2 k e2)
</pre>

<p>The data type <code>ContReduce</code> is the now-common notion of an &#8220;evaluation context&#8221; which some researchers prefer because it separates the important rules about how terms are reduced from the rules that just tell you where in a term reduction happens.</p>

<p>Next&#8230;</p>

<pre>
> data ContEval = ContEval -- toplevel
>               | ContE1 ContEval Exp
>               | ContE2 Int ContEval
>
> applyContEval :: ContEval -> Int -> Int
> applyContEval (ContEval) v = v
> applyContEval (ContE1 k e2) v1 = evalCPSdefun e2 (ContE2 v1 k) 
> applyContEval (ContE2 v1 k) v2 = applyContEval k (v1 + v2)
>
> evalCPSdefun (Value v)   k = applyContEval k v
> evalCPSdefun (Add e1 e2) k = evalCPSdefun e1 (ContE1 k e2)
</pre>

<p>Hey it looks like almost the same thing!  The difference is in how we interpret the data structure.  In the previous case, <code>applyContReduce</code> just used it for navigation.  In this case, <code>applyContEval</code> calls back into <code>evalCPSdefun</code> to keep the evaluation rolling.</p>

<p>If, like myself, you liked this because you feel there is important and interesting structure underlying operational semantics that is
hidden by its many superficial forms, then you&#8217;ll probably like this additional reading:</p>

<ul>
<li><a href="http://www.cs.nott.ac.uk/~gmh/bib.html#modular">Modularity and implementation of mathematical operational semantics</a>.  M Jaskelioff, N Ghani, G Hutton.  MSFP 2008.</li>
<li><a href="http://www.cs.nott.ac.uk/~gmh/bib.html#semantics">Fold and unfold for program semantics</a>.  G Hutton.  ICFP 1998.</li>
</ul>

<p>And I leave you with my hidden instances of arbitrary&#8230;</p>

<pre>
> instance Arbitrary a => Arbitrary (BinaryTree a) where
>   arbitrary = oneof [liftM Leaf arbitrary, liftM2 Node arbitrary arbitrary]

> instance (Arbitrary a, Arbitrary b) => Arbitrary (MyPair a b) where
>   arbitrary = liftM2 myPair arbitrary arbitrary
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.kennknowles.com/blog/2008/05/24/what-is-defunctionalization/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>CTL Model Checking in Haskell:  A Classic Algorithm Explained as Memoization</title>
		<link>http://www.kennknowles.com/blog/2008/05/07/ctl-model-checking-in-haskell-a-classic-algorithm-explained-as-memoization/</link>
		<comments>http://www.kennknowles.com/blog/2008/05/07/ctl-model-checking-in-haskell-a-classic-algorithm-explained-as-memoization/#comments</comments>
		<pubDate>Wed, 07 May 2008 09:13:46 +0000</pubDate>
		<dc:creator>Kenn</dc:creator>
				<category><![CDATA[Haskell]]></category>
		<category><![CDATA[Mathematics]]></category>
		<category><![CDATA[Reading]]></category>
		<category><![CDATA[memoization]]></category>
		<category><![CDATA[model checking]]></category>
		<category><![CDATA[monads]]></category>
		<category><![CDATA[open recursion]]></category>

		<guid isPermaLink="false">http://www.kennknowles.com/blog/2008/05/07/ctl-model-checking-in-haskell-a-classic-algorithm-explained-as-memoization/</guid>
		<description><![CDATA[As an exercise, since my reading group was discussing model checking this week, I implemented the classic model checker for CTL specifications from the 1986 paper


Automatic Verification of Concurrent Systems Using Temporal Logic Specifications by EM Clarke, EM Emerson, AP Sistla.


The &#8220;efficient algorithm&#8221; presented in the paper is, upon reflection, merely a memoized traversal of [...]]]></description>
			<content:encoded><![CDATA[<p>As an exercise, since my reading group was discussing model checking this week, I implemented the classic model checker for CTL specifications from the 1986 paper</p>

<ul>
<li><a href="http://research.microsoft.com/users/qadeer/cse599f/papers/clarke-toplas.pdf">Automatic Verification of Concurrent Systems Using Temporal Logic Specifications</a> by EM Clarke, EM Emerson, AP Sistla.</li>
</ul>

<p>The &#8220;efficient algorithm&#8221; presented in the paper is, upon reflection, merely a memoized traversal of the state machine,
so I combined it with a modified version of</p>

<ul>
<li><a href="http://www.cs.utexas.edu/~wcook/Drafts/2006/MemoMixins.pdf">Monadic Memoization Mixins</a> by D Brown, WR Cook</li>
</ul>

<p>which actually eliminated an auxilliary function from the algorithm, yielding an efficiently-executable 20-line Haskell specification of the meaning of CTL (which is probably clearer than my English prose explanation, and certainly more fun to play with).</p>

<p><a href='http://www.kennknowles.com/blog/wp-content/uploads/2008/05/redyellowgreen.png' title='redyellowgreen.png'><img src='http://www.kennknowles.com/blog/wp-content/uploads/2008/05/redyellowgreen.png' alt='redyellowgreen.png' /></a></p>

<p>This post is, as usual, literate Haskell.  Load it up in GHCi, Haskell-mode, or compile it with <code>ghc --make</code> and try it out.  Maybe you can convince my state space exploration not to terminate <img src='http://www.kennknowles.com/blog/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> 
<span id="more-58"></span></p>

<pre>
> {-# LANGUAGE TypeOperators,ScopedTypeVariables,PatternSignatures #-}

> import qualified Data.Map as M
> import qualified Data.Set as S
> import Data.List
> import Control.Monad 
> import Control.Monad.State hiding (fix)
</pre>

<h2>Memoization Mixins</h2>

<p>Here is the easy example from the Brown-Cook paper, before getting on to model checking.</p>

<p>To enable functional mixins, we write our functions using open recursion.  Instead of a function of type <code>a -&gt; b</code> 
we write one of type <code>Gen (a -&gt; b)</code> and then later &#8220;tie the knot&#8221; with <code>fix</code> (reproduced here for reference)</p>

<pre>
> type Gen a = (a -> a)

> fix :: Gen a -> a
> fix f = f (fix f)
</pre>

<p>The classic example they start with is calculating the nth fibonacci number, but don&#8217;t stop reading just because this example is simple!  It is just to illustrate the technique.</p>

<pre>
> fib :: Int -> Int
> fib 0     = 0
> fib 1     = 1
> fib (n+2) = fib n + fib (n+1)
</pre>

<p>By the time you get to <code>fib 30</code> it takes a dozen or seconds to return
on my poor old computer.  Rewrittin in open recursion as</p>

<pre>
> gFib :: Gen (Int -> Int)
> gFib recurse 0     = 0
> gFib recurse 1     = 1
> gFib recurse (n+2) = recurse n + recurse (n+1)

> fib' = fix gFib
</pre>

<p>This <code>fib'</code> has essentially the same performance, up to constant factors: slow.</p>

<p>To enable us to store the memoization table in something like a <code>State</code>, we parameterize over an underlying monad.  A beautiful technique in its own right, if you ask me.  I agree with the authors that open recursion and monadification are important and powerful enough to deserve language support; you probably will think <code>gmFib</code> below looks a bit crufty.</p>

<pre>
> gmFib :: Monad m => Gen (Int -> m Int)
> gmFib recurse 0     = return 0
> gmFib recurse 1     = return 1
> gmFib recurse (n+2) = do a <- recurse n
>                          b <- recurse (n+1)
>                          return (a + b)
</pre>

<p>And now we can mix in <code>memoize</code></p>

<pre>
> type Memoized a b = State (M.Map a b)

> memoize :: Ord a => Gen (a -> Memoized a b b)
> memoize self x = do memo <- check x
>                     case memo of
>                       Just y  -> return y
>                       Nothing -> do y <- self x
>                                     store x y
>                                     return y

> check :: Ord a => a -> Memoized a b (Maybe b)
> check x = do memotable <- get
>              return (M.lookup x memotable)

> store :: Ord a => a -> b -> Memoized a b ()
> store x y = do memotable <- get
>                put (M.insert x y memotable)
</pre>

<p>Here&#8217;s the final fib, which returns instantly up to at least <code>10000</code>.</p>

<pre>
> fib'' n = evalState (fix (gmFib . memoize) n) M.empty
</pre>

<h2>Computation Tree Logic (CTL)</h2>

<p>The language for which Clarke et al give a graph-based algorithm is called CTL; nowadays people are interested in a bunch of variants like CTL* and ACTL.  I&#8217;m not a model-checking researcher so I don&#8217;t really know the subtleties of their differences.  CTL is
a logic for specifying certain restricted kinds of predicates over the possible traces of a state machine, for today a finite state machine.</p>

<p>Let&#8217;s just look at the Haskell definition:</p>

<pre>
> data CTL p = TT | FF
>            | Atomic p
>            | Not (CTL p)
>            | And (CTL p) (CTL p)
>            | AllSucc  (CTL p)
>            | ExSucc   (CTL p)
>            | AllUntil (CTL p) (CTL p)
>            | ExUntil  (CTL p) (CTL p)
>              deriving (Eq,Ord)
</pre>

<p>Some of these are simply your usual logic</p>

<ul>
<li><code>TT</code> holds of any state</li>
<li><code>FF</code> never holds</li>
<li><code>Atomic p</code> is some atomic proposition over a state, like inequality over program variables, etc.</li>
<li><code>Not</code> and <code>And</code> have their expected meanings</li>
</ul>

<p>The successor constructions let you talk about &#8220;the next&#8221; state:</p>

<ul>
<li><code>AllSucc f</code> (respectively <code>ExSucc</code>) holds of a state <code>s</code> when the formula <code>f</code> holds for all (respectively some) successor states.</li>
</ul>

<p>The interesting ones though, are &#8220;Always Until&#8221; and &#8220;Exists Until&#8221;:</p>

<ul>
<li><code>AllUntil f1 f2</code> holds of a state <code>s</code> when for <em>all</em> prefixes of any trace starting at <code>s</code> you eventually reach a state satisfying <code>f2</code>, and everywhere along the way <code>f1</code> holds.</li>
<li><code>ExUntil</code> is the existential version of that.</li>
</ul>

<p>We can then define some more predicates like &#8220;forever in the future&#8221; and &#8220;eventually&#8221;</p>

<pre>
> allFuture f = AllUntil TT f
> existsFuture f = ExUntil TT f

> allGlobal f = Not(existsFuture(Not f))
> existsGlobal f = Not(allFuture(Not f))
</pre>

<p>Now, to apply a formula to a state machine, first I need the state machine.
I&#8217;ll just represent it by its successor function.</p>

<pre>
> type Succ st = st -> [st]
</pre>

<p>And we need some interpretation of atomic formulas as predicates over states</p>

<pre>
> type Interp p st = p -> st -> Bool
</pre>

<p>And since I&#8217;m using a monadified form of computation, I will lift a bunch
of operations into monads to make everything readable.</p>

<pre>
> andThen,orElse :: Monad m => m Bool -> m Bool -> m Bool
> andThen = liftM2 (&#038;&#038;) 
> orElse  =  liftM2 (||) 

> notM :: Monad m => m Bool -> m Bool
> notM = liftM not

> anyM,allM :: Monad m => (s -> m Bool) -> [s] -> m Bool
> allM f = liftM and . mapM f
> anyM f = liftM or  . mapM f
</pre>

<h2>The Model-Checking Algorithm</h2>

<p>In the Clarke et al paper, the algorithm is expressed by induction on the formula <code>f</code> you want to check:  First, label your state-space graph with all the atomic formula that hold at each state.  Then, label with each the compound formula of height two that holds.  Etc, etc, you are guaranteed that the graph is already labeled with each subformula by the time it becomes necessary.</p>

<p>Like dynamic programming, this is simply a complicated way of expressing memoization.  In fact, they even use a depth-first search helper function that is completely eliminated by expressing it as a memoized function.  This code is considerably shorter and, I think, clearer than the pseudocode in the paper, modulo the overhead of &#8220;mixing in&#8221; and &#8220;tying the knot&#8221;.</p>

<p>Today we have fancy algorithms involving BDDs and abstraction, so I&#8217;m not claiming anything <em>useful</em> except pedagogically.  I do wonder, though, if this code gains something through laziness.  It certainly traverses the state space fewer times (but I&#8217;m sure an implementation of their algorithm would do similar optimizations).</p>

<pre>
> checkCTL :: forall p st . (Ord p, Ord st) => 
>                           Interp p st -> Succ st -> st -> CTL p -> Bool
> checkCTL interp succ init f = 
>    evalState (fix (gCheckCTL . cyclicMemoize2 False) f init) M.empty
>  where 
>    gCheckCTL :: Monad m => Gen (CTL p -> st -> m Bool)
>    gCheckCTL recurse f s = checkFormula f
>      where checkFormula TT           = return True
>            checkFormula FF           = return False
>            checkFormula (Atomic p)   = return (interp p s)
>            checkFormula (Not f1)     = notM (recurse f1 s)
>            checkFormula (And f1 f2)  = recurse f1 s `andThen` recurse f2 s
>            checkFormula (AllSucc f1) = allM (recurse f1) (succ s)
>            checkFormula (ExSucc f1)  = anyM (recurse f1) (succ s)

>            checkFormula (AllUntil f1 f2) = recurse f2 s `orElse` 
>                            (recurse f1 s `andThen` allM (recurse f) (succ s))

>            checkFormula (ExUntil f1 f2)  = recurse f2 s `orElse` 
>                            (recurse f1 s `andThen` anyM (recurse f) (succ s))
</pre>

<p>You may also notice that I cheated a little, perhaps.  I have used <code>cyclicMemoize2</code> instead of <code>memoize</code>:</p>

<pre>
> cyclicMemoize2 :: (Ord a, Ord b) => c -> Gen (a -> b -> Memoized (a,b) c c)
> cyclicMemoize2 backEdge self x y = do memo <- check (x,y)
>                                       case memo of
>                                          Just z  -> return z
>                                          Nothing -> do store (x,y) backEdge
>                                                        z <- self x y
>                                                        store (x,y) z
>                                                        return z
</pre>

<p>One reason is simply that I need a curry/uncurry wrapper for my two argument monadified function.
The deeper thing is that <code>cyclicMemoize2 False</code> inserts a fake memoization entry while a computation
is progressing.  If there is ever a &#8220;back edge&#8221; in the search, it will return this dummy entry.
For CTL, the auxilliary depth-first search used in the paper for <code>AllUntil</code> returns <code>False</code> in these 
cases, so I seed the memo table accordingly.  This is because by the time you have recursed
around a cycle, that means that the <code>f2</code> you are searching for did not occur on the cycle, so it
never will.</p>

<p>To play with it, I&#8217;ve only made a couple of examples involving stop lights (of occasionally curious colors).  I&#8217;d love more, and you&#8217;ll undoubtedly find
bugs if you actually run something significant.</p>

<pre>
> ex1interp p s = (p == s)

> ex1succ "Red"    = ["Green"]
> ex1succ "Green"  = ["Yellow"]
> ex1succ "Yellow" = ["Red"]

> ex2succ "Red"    = ["Green"]
> ex2succ "Green"  = ["Yellow", "Orange"]
> ex2succ "Orange" = ["Red"]
> ex2succ "Yellow" = ["Red"]
</pre>

<p>But it looks kind of OK,</p>

<pre>
*Main> let ch2 = checkCTL ex1interp ex2succ
*Main> let ch1 = checkCTL ex1interp ex1succ
*Main> ch1 "Red" (existsFuture (Atomic "Red"))
True
*Main> ch1 "Red" (existsFuture (Atomic "Blue"))
False
*Main> ch2 "Green" (ExUntil TT (Atomic "Red"))
True
*Main> ch2 "Green" (ExUntil (Atomic "Green") (Atomic "Orange"))
True
*Main> ch1 "Green" (Not (AllUntil (Not (Atomic "Yellow")) (Atomic "Red")))
True
*Main> ch1 "Green" (Not (ExUntil (Not (Atomic "Yellow")) (Atomic "Red")))
True
*Main> ch2 "Green" (Not (ExUntil (Not (Atomic "Yellow")) (Atomic "Red")))
False
</pre>

<p>Quite fun!</p>

<p><a href='http://www.kennknowles.com/blog/wp-content/uploads/2008/05/redyelloworangegreen.png' title='redyelloworangegreen.png'><img src='http://www.kennknowles.com/blog/wp-content/uploads/2008/05/redyelloworangegreen.png' alt='redyelloworangegreen.png' /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.kennknowles.com/blog/2008/05/07/ctl-model-checking-in-haskell-a-classic-algorithm-explained-as-memoization/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Reading Cluster: Recreational Mathematics</title>
		<link>http://www.kennknowles.com/blog/2007/12/29/reading-cluster-recreational-mathematics/</link>
		<comments>http://www.kennknowles.com/blog/2007/12/29/reading-cluster-recreational-mathematics/#comments</comments>
		<pubDate>Sat, 29 Dec 2007 23:51:54 +0000</pubDate>
		<dc:creator>Kenn</dc:creator>
				<category><![CDATA[Mathematics]]></category>
		<category><![CDATA[Reading]]></category>
		<category><![CDATA[math]]></category>
		<category><![CDATA[recreation]]></category>

		<guid isPermaLink="false">http://www.kennknowles.com/blog/2007/12/29/reading-cluster-recreational-mathematics/</guid>
		<description><![CDATA[I read a lot, perhaps to the
detriment of my eventual graduation plans.  Recently, I&#8217;ve been enjoying books of
&#8220;recreational mathematics.&#8221;  This
is a combined review of all such books I&#8217;ve read recently.


You might wonder what I mean by &#8220;recreational mathematics&#8221; since
clearly all math is fun   . Well, I&#8217;m talking about math that is
intended [...]]]></description>
			<content:encoded><![CDATA[<p>I <a href="http://kennknowles.com/reading/">read a lot</a>, perhaps to the
detriment of my eventual graduation plans.  Recently, I&#8217;ve been enjoying books of
&#8220;recreational mathematics.&#8221;  This
is a combined review of all such books I&#8217;ve read recently.
<span id="more-38"></span></p>

<p>You might wonder what I mean by &#8220;recreational mathematics&#8221; since
clearly all math is fun <img src='http://www.kennknowles.com/blog/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' />  . Well, I&#8217;m talking about math that is
intended to be fun before being instructive.  It usually mixes in a
bit of history and description of famous math personalities for added
interest, and has much much MUCH more motivation than your average
math textbook; I find that this helps me immensely in remembering the
math.  However, I am <em>not</em> talking about books <em>only</em> about the
people, places, and times of mathematics.  All the books in this
review have, to some degree, real and rigorous mathematical content.
But none of them are a &#8220;pure&#8221; exposition of consequences from axioms.
It&#8217;ll be plenty clear if you take the time to find and read some of these
wonderful books.</p>

<hr />

<h3><em>Journey Through Genius</em> by William Dunham</h3>

<p>If you read just one book, read <em>Journey Through Genius</em>.  It hits many
mathematicians and topics, and is a great overview.  </p>

<p>Each chapter is centered on one &#8220;great&#8221; theorem, but is arranged
beautifully such that the theorem is merely the peak of the story arc.
For example, the first chapter on Hippocrates&#8217; quadrature of the
<a href="http://mathworld.wolfram.com/Lune.html">lune</a> gives 17 pages to
classical constructive geometry, discussing the disconnect between
&#8220;number&#8221; and &#8220;length&#8221; and showing the quadrature of various polygons.
The proof of the great theorem is then about one full page.  After the
main result, an epilogue eases you out with a discussion of some
following results, in this example about 7 pages, finishing with the
impossibility of squaring the circle with straightedge and compass.</p>

<p>Perhaps my favorite thing about the book is that it really feels like
it is about math, and the artistry with which great theorems are
proved.  People, places, and the passage of time appropriately spice
up the story; reading Newton or Euler&#8217;s work doesn&#8217;t seem like a
disjoint concern from that of Archimedes, but rather like a change of
camera angle in a (highly metaphorical) movie.</p>

<p><em>Journey through Genius</em> ends with Cantor&#8217;s theorem, so don&#8217;t expect to
gain new appreciation for modern abstract nonsense &#8211; I suspect it will
be a <em>long</em> time before a recreational math book tries to tackle what
they teach in grad school today.</p>

<hr />

<h3><em>Yearning for the Impossible</em> by John Stillwell</h3>

<p>This book is definitely my second favorite next to <em>Journey Through
Genius</em>.  Most books are themed by mathematical content or a famous
mathematician, or deliver a historical overview, but this one manages
to truly have an <em>emotional</em> theme just as implied by the title.  I
literally felt the suspense of wondering what would be discovered next
as the mathematicians in the book are practically <em>forced</em> to discover
irrational numbers, complex numbers, projective geometry,
infinitesimals, hyperbolic space, quaternions, prime ideals, and
uncountability.</p>

<p>The treatment of prime ideals especially struck me, since I&#8217;ve never
seen an ounce of motivation elsewhere, and certainly nothing as
down-to-earth as providing unique factorization for Gaussian
integers. I&#8217;m sure more sophisticated uses abound, since they bother
teaching it in the first quarter of Algebra, but since I study
programming languages my grad math experience is somewhat ad hoc&#8230; I
learn math for kicks, and count on motivation and formalism to be
presented together, which is very uncouth in modern math culture!
Anyhow, I sure wish I had read this book years ago.</p>

<hr />

<h3><em>Four Colors Suffice</em> by Robin Wilson</h3>

<p>This one I just got for Christmas, and makes it to number
three in my list because it treats a different sort of problem that
has a <em>very different</em> sort of proof.  The subject, of course, is the
<a href="http://en.wikipedia.org/wiki/Four_color_theorem">Four Color Theorem</a>.
In order to create an entire book for the history of this theorem,
Wilson adopts the interesting approach of describing many false starts and
negative results &#8211; of course, they really do form a major part of the
story, and the eventual correct proof relies on the techniques of an
early incorrect proof.  Also nice are the numerous primary source
documents, such as the first document where DeMorgan communicates the
problem to Hamilton, and where Story says (translating into modern
Santa Cruz English) &#8220;Dude, this problem is gnarly!&#8221;  I hadn&#8217;t realized
that this problem moved through such prestigious hands as DeMorgan,
Hamilton, Peirce, Euler, Cayley, and Kempe (apologies to the other
names who will simply have to wait 100 years to achieve proper
prestige &#8211; I visited the Boston museum of science recently and they
have this wall with a chronology of math where pre-1900 there are
perhaps 1-4 famous people alive at a time and post-1900 it explodes to
fill the entire wall vertically, so I can&#8217;t be expected to remember
them all <img src='http://www.kennknowles.com/blog/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' />  )</p>

<p>Anyhow, as the book progresses, results build up &#8211; but not results
that aid the proof, rather they are results that prove how <em>large</em> any
counterexample must be, and how <em>many</em> special cases must be
considered.  And then there is the moment where over a thousand cases
are checked by computer algorithm, with the expected reactionary
backlash against such a proof.  Amusingly, the proof starts with a ton
of tedious work <em>by hand</em> yet it is the computer part that people
didn&#8217;t trust!  <a href="http://www.math.gatech.edu/~thomas/FC/fourcolor.html">Subsequent
work</a> automates
the first part of the proof so now a computer can replay the proof at
home in a short while.  Especially in the context of mechanizing the
metatheory for programming languages, this is an interesting issue.</p>

<hr />

<h3><em>Euler: Master of us All</em> by William Dunham</h3>

<p>This book has a very similar feel to Journey Through Genius, but is
focused entirely on Euler.  The same good intro/climax/epilogue format
is followed for each chapter, and the same wonderful style that is
distinctly Dunham.  Added to that, Euler&#8217;s math is truly artistic; I
feel like yelling &#8220;BAM!&#8221; at the end of each proof.  I absolutely loved
this one too, but don&#8217;t read it right after Journey Through Genius or
the tone will be getting old.</p>

<p>There is much discussion of rigor issues with Euler&#8217;s approach, which
are certainly valid in the absolute sense that he was working with
terms and notations that weren&#8217;t clearly defined.  But in my opinion it
isn&#8217;t reasonable to retroactively apply rigorous reinventions of
terminology.</p>

<hr />

<h3><em>Imagining Numbers</em> by Barry Mazur</h3>

<p>This one was a gift that got me started on this train of books.  It is
OK, but in retrospect not as good as the others, and complex numbers
make a prominent appearance in many of these books, particularly
<em>Yearning for the Impossible</em>.  On the upside, it is short and nice, and
has poetic and philosophical interludes, making it a unique
experience.</p>

<hr />

<h3><em>Fearless Symmetry</em> by Avner Ash and Robert Gross</h3>

<p>I read this because it had a catchy title <img src='http://www.kennknowles.com/blog/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' />  . I recall it was pretty
good, and had content and motivation I hadn&#8217;t seen before, since I
haven&#8217;t yet had time to reach Galois theory in my sampling of math
courses.  It has been a while since I read it, and it has been
returned to the library, so I can&#8217;t say anything terribly specific
about its content or presentation, but I certainly recommend reading or
re-reading it to anyone engaged in group theory or Galois theory in
particular.  The more of it you already know, the quicker you will
blaze through it anyhow.  Apropos a comment I made in the review of
Journey Through Genius, this book is probably the closest to actually
touching abstract and somewhat difficult modern topics.</p>

<hr />

<h3><em>The Pea and the Sun</em> by Leonard Wapner</h3>

<p>This one is all about the Banach-Tarski &#8220;paradox&#8221; so it has a natural
advantage because of the curiosity of the subject matter.
Unfortunately, it doesn&#8217;t really take advantage of it.  Before getting
to the main theorem, it develops many analogous smaller versions of
the paradox to get the reader situated, and I found it rather
dragging.  Simpler versions of the paradox do make great party tricks,
if you know them well enough to deliver the proof quickly and with
flare, and if you go to the kind of parties that I do&#8230;</p>

<hr />

<h3><em>Unknown Quantity</em> by John Derbyshire</h3>

<p>This one is really popular and well-reviewed, so I&#8217;m almost afraid to
say it was my least favorite of all I&#8217;ve read.  It was just too heavy
on the history, and not exciting enough to keep my interest.  The book is also quite long, while I like knowledge in bite sized
chunks&#8230; I&#8217;ll stick to <em>mathematical pamphlets</em>!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.kennknowles.com/blog/2007/12/29/reading-cluster-recreational-mathematics/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
