I’m attempting to mannequin the proof of Immerman–Szelepcsényi Theorem with Haskell because it closely makes use of non-determinism. A proof of what the purpose of that is could be discovered right here.

```
{-# LANGUAGE FlexibleContexts #-}
import Management.Monad
import Management.Monad.State
kind NonDet a = [a]
kind NonDetState s a = StateT s [] a
kind Vertex = Int
-- signify the graph as an adjacency listing
-- or equivalently, a nondeterministic computation
-- that returns the subsequent vertex given the present
getNextVertex :: Vertex -> NonDet Vertex
getNextVertex = undefined
-- is there a path from `supply` to `goal` in `certain` steps
guessPath :: Int -> Vertex -> Vertex -> NonDetState Vertex ()
guessPath certain supply goal = do
put supply
nonDeterministicWalk certain
the place
nonDeterministicWalk certain = do
guard (certain >= 0)
v <- get
if v == goal
then return ()
else do
w <- raise $ getNextVertex v
put w
nonDeterministicWalk (certain - 1)
-- when you knew the variety of vertices reachable from the supply
-- use that to certify that concentrate on shouldn't be reachable
certifyUnreachAux :: [Vertex] -> Int -> Vertex -> Vertex -> NonDetState Int ()
certifyUnreachAux vertices c supply goal = do
put 0
forM_ vertices $ v -> do
-- guess whether or not the vertex v is reachable or not
guess <- raise [True, False]
if (not guess || v == goal)
-- if the vertex v shouldn't be reachable or is the goal
-- then simply transfer on to the subsequent one
then return ()
else do
-- in any other case confirm that the vertex is certainly reachable
guessPath (size vertices) supply v
counter <- get
put (counter + 1)
counter <- get
guard (counter == c)
return ()
-- work out the variety of vertices reachable from supply
-- in `steps` steps
countReachable :: [Vertex] -> Int -> Vertex -> NonDet Int
countReachable vertices steps supply = do
if steps <= 0
then return 1
else do
previouslyReachable <- countReachable vertices (steps - 1) supply
evalStateT (countReachableInduct vertices previouslyReachable steps supply) (0, 0, False)
-- determining what number of vertices are reachable in (i+1) steps
-- given the variety of vertices reachable in i steps
countReachableInduct :: [Vertex] -> Int -> Int -> Vertex -> NonDetState (Int, Int, Bool) Int
countReachableInduct vertices previouslyReachable steps supply = do
-- initialize the counters to 0
put (0, 0, False)
forM_ vertices $ v -> do
-- set the primary counter to 0
-- and unset the flag that claims you could have
-- checked that v is a neighbor of u or u itself
(previousCount, currentCount, b) <- get
put (0, currentCount, False)
forM_ vertices $ u -> do
-- guess if u reachable from the supply in (steps - 1) steps
guess <- raise [True, False]
if not guess
-- if not, then we will transfer forward to the subsequent u
then return ()
else do
-- since we guessed that u is reachable,
-- we must always confirm it
raise $ evalStateT (guessPath (steps - 1) supply u) 0
(previousCount, currentCount, b) <- get
put ((previousCount + 1), currentCount, b)
if (u == v)
then do
(previousCount, currentCount, _) <- get
put (previousCount, currentCount, True)
else do
neighbor <- raise $ getNextVertex u
if (u == neighbor)
then do
(previousCount, currentCount, _) <- get
put (previousCount, currentCount, True)
else
-- if v is neither u nor a neighbor of u,
-- we simply transfer to the second iteration
return ()
guard (previousCount == previouslyReachable)
(previousCount, currentCount, b) <- get
-- if v was at most distance 1 from u, which
-- we verfied to be a vertex reachable in
-- (steps - 1) steps, then v is reachable
-- in steps steps
put (previousCount, (currentCount + if b then 1 else 0), b)
(_, currentCount, _) <- get
return currentCount
-- lastly put all of the strategies collectively and present that
-- goal is unreachable from supply
certifyUnreach :: [Vertex] -> Vertex -> Vertex -> NonDet ()
certifyUnreach vertices supply goal = do
c <- countReachable vertices (size vertices) supply
evalStateT (certifyUnreachAux vertices c supply goal) 0
```

I would like normal feedback on how I might enhance coding type. One specific factor is the awkward use of `get`

and `put`

to get the three counters however replace one in all them. I want to understand how this may be achieved extra elegantly with lenses.