<?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>Functional Lens &#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>on Mathematics and Computation</description>
	<lastBuildDate>Mon, 26 Dec 2011 21:15:37 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.1.2</generator>
		<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 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 POPL&#8217;08 drove [...]]]></description>
			<content:encoded><![CDATA[<p>I 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 &#8216;s example of a parser to recognize the language <img src='http://s.wordpress.com/latex.php?latex=0%5En%201%5En&#038;bg=ffffff&#038;fg=000000&#038;s=0' 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 [...]]]></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>
	</channel>
</rss>

