Vrrm Development

2009/03/03

Unbounded Graphs2

Filed under: Technical — whpearson @ 12:42 am
Tags:

Just a quicky, I found a function that returns nice breadth first orderings of the graphs.

gIterate2 :: (b -> [b]) -> [b] -> [[b]]
gIterate2 f xs = iterate (concat. map f) xs

You can even avoid cycles by making the Data type a tuple with a set and then using a function like the following

take 4 $ gIterate2 (\(x,y) -> if member x y then [] else ((x+1), insert x y):[(x-1, insert x y )]) [(1, empty)]

This gets a list of all the nodes 4 iterations away from the original. It does have some limitations compared to the way I did it yesterday in that it can’t return a different type (due to the use of iterate). You can get around this somewhat by using a tuple again with a dummy return value placed in.

Edit from here for added value.

Now that isn’t very pretty lets define a function noRepeat that you can apply to any function a -> [a] to filter out repeats

noRepeat :: (Ord t) => (t -> [a]) -> (t, Set t) -> [(a, Set t)]
noRepeat f (x,y) = if member x y then [] else zip (f x) (repeat (insert x y))

The basic type is (a -> [a]) -> b -> [b]

Let us call this a function transformer. Now the basic output from that is pretty ugly

take 5 $ gIterate2 (noRepeat (\x -> (x+1):[(x-1)])) [(1, empty)]

[[(1,fromList [])],[(2,fromList [1]),(0,fromList [1])],[(3,fromList [1,2]),(1,fromList [1,2]),(1,fromList [0,1]),(-1,fromList [0,1])],[(4,fromList [1,2,3]),(2,fromList [1,2,3]),(0,fromList [-1,0,1]),(-2,fromList [-1,0,1])],[(5,fromList [1,2,3,4]),(3,fromList [1,2,3,4]),(-1,fromList [-2,-1,0,1]),(-3,fromList [-2,-1,0,1])]]

So what can we do? Well if we map (map fst) on it we can get back just the list of nodes. We’ll call the fst the “detransformer” of noRepeat.

So lets create a data type

data TransTriple m a b = Dere {getInit :: a -> b, getTransform :: (a-> m a) -> (b -> m b), getDetrans:: b -> a}

This defines a way to initialise the change, a way to transform the step function given normally and a way to get back to the original value.

gtransformIter pair f xs = Prelude.map (Prelude.map (getDetrans pair)) $ gIterate2 (getTransform pair$ f) (Prelude.map (getInit pair) xs)

We define a new function to take all of these and apply them properly to gIterate2.

a `comp` b = Dere (\x -> getInit a $ getInit b$ x ) (\x -> getTransform a $ getTransform b$ x ) (\x -> getDetrans b $ getDetrans a $ x)

Why do we do this? So we can compose them together. `comp` acts as (.) but for all the functions in the right order. It is not very pretty at the moment.

So let us define a couple of transformer triples.

noRepeat f (x,y) = if member x y then [] else zip (f x) (repeat (insert x y))

stopWhen cond f x = if cond x then [] else f x

noRepeatTriple = Dere (\x -> (x, empty)) (noRepeat) fst

notFiveTriple = Dere id (stopWhen(==5)) id

So you can now call something like

gtransformIter (noRepeatTriple `comp` notFiveTriple) (\x -> (x+1):[(x-1)]) [1]

And it spit out a pure list of numbers, ignoring any branches that get to 5 or any that start to cycle.

I’ll try and do a simple game search next time using this framework.

Advertisement

Leave a Comment »

No comments yet.

RSS feed for comments on this post. TrackBack URI

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Connecting to %s

Theme: Rubric. Blog at WordPress.com.

Follow

Get every new post delivered to your Inbox.