Probabilistic automata
This commit is contained in:
parent
061ea0e0d3
commit
a86ec8b064
9 changed files with 271 additions and 0 deletions
10
probabilistic/README.md
Normal file
10
probabilistic/README.md
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
Probabilistic models
|
||||||
|
====================
|
||||||
|
|
||||||
|
With the weighted automata semantics (i.e. weighted outputs and no state
|
||||||
|
labels). I have implemented:
|
||||||
|
|
||||||
|
* Gridworld 1 and 2 from Tappler et al 2019.
|
||||||
|
Note: This is note the same semantics, so I had to convert it a little
|
||||||
|
bit. It is comparable (but smaller).
|
||||||
|
|
2
probabilistic/Setup.hs
Normal file
2
probabilistic/Setup.hs
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
import Distribution.Simple
|
||||||
|
main = defaultMain
|
15
probabilistic/app/Main.hs
Normal file
15
probabilistic/app/Main.hs
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
module Main where
|
||||||
|
|
||||||
|
import PA
|
||||||
|
import Grid
|
||||||
|
import Output
|
||||||
|
|
||||||
|
main :: IO ()
|
||||||
|
main = do
|
||||||
|
writeFile "example.dot" (dotShow example)
|
||||||
|
writeFile "example.pa" (denseShow example)
|
||||||
|
writeFile "grid1.dot" (dotShow firstPA)
|
||||||
|
writeFile "grid1.pa" (denseShow firstPA)
|
||||||
|
writeFile "grid2.dot" (dotShow secondPA)
|
||||||
|
writeFile "grid2.pa" (denseShow secondPA)
|
||||||
|
|
BIN
probabilistic/examplePA.zip
Normal file
BIN
probabilistic/examplePA.zip
Normal file
Binary file not shown.
27
probabilistic/probabilistic.cabal
Normal file
27
probabilistic/probabilistic.cabal
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
cabal-version: 2.2
|
||||||
|
name: probabilistic
|
||||||
|
version: 0.1.0.0
|
||||||
|
author: Joshua Moerman
|
||||||
|
maintainer: joshua@cs.rwth-aachen.de
|
||||||
|
build-type: Simple
|
||||||
|
|
||||||
|
common stuff
|
||||||
|
default-language: Haskell2010
|
||||||
|
build-depends:
|
||||||
|
base >=4.14 && <4.15,
|
||||||
|
containers
|
||||||
|
|
||||||
|
library pag
|
||||||
|
import: stuff
|
||||||
|
hs-source-dirs: src
|
||||||
|
exposed-modules:
|
||||||
|
Grid,
|
||||||
|
PA,
|
||||||
|
Prob,
|
||||||
|
Output
|
||||||
|
|
||||||
|
executable probabilistic
|
||||||
|
import: stuff
|
||||||
|
hs-source-dirs: app
|
||||||
|
main-is: Main.hs
|
||||||
|
build-depends: pag
|
100
probabilistic/src/Grid.hs
Normal file
100
probabilistic/src/Grid.hs
Normal file
|
@ -0,0 +1,100 @@
|
||||||
|
{-# language TypeSynonymInstances #-}
|
||||||
|
{-# language FlexibleInstances #-}
|
||||||
|
|
||||||
|
module Grid where
|
||||||
|
|
||||||
|
import PA
|
||||||
|
import Prob
|
||||||
|
import Output
|
||||||
|
|
||||||
|
type Alph = Char
|
||||||
|
|
||||||
|
alph :: [Alph]
|
||||||
|
alph = "NESW"
|
||||||
|
|
||||||
|
-- word data with sizes
|
||||||
|
type World = ([[Char]], Int, Int)
|
||||||
|
|
||||||
|
first :: [[Char]]
|
||||||
|
first =
|
||||||
|
[ "CCCMW"
|
||||||
|
, "WWWCM"
|
||||||
|
, "SMGCG"
|
||||||
|
, "MGCMW"
|
||||||
|
, "GSMGW"
|
||||||
|
]
|
||||||
|
|
||||||
|
firstW :: World
|
||||||
|
firstW = (first, length (head first), length first)
|
||||||
|
|
||||||
|
second :: [[Char]]
|
||||||
|
second =
|
||||||
|
[ "CCMCCGMS"
|
||||||
|
, "CGWWGMCG"
|
||||||
|
, "CMSGMCGW"
|
||||||
|
, "SCCCCGSC"
|
||||||
|
, "MWCCGSMC"
|
||||||
|
, "GSMGWWGM"
|
||||||
|
]
|
||||||
|
|
||||||
|
secondW :: World
|
||||||
|
secondW = (second, length (head second), length second)
|
||||||
|
|
||||||
|
-- either a valid position or a wall
|
||||||
|
type State = Either () (Int, Int)
|
||||||
|
|
||||||
|
instance StateShow State where
|
||||||
|
sshow (Left ()) = "W"
|
||||||
|
sshow (Right (c, r)) = "p" <> show c <> "x" <> show r
|
||||||
|
|
||||||
|
delta :: World -> State -> Alph -> V State
|
||||||
|
delta (grid, w, h) (Left ()) _ = []
|
||||||
|
delta (grid, w, h) (Right (c, r)) i =
|
||||||
|
let currCell = grid !! r !! c
|
||||||
|
filterValid (c', r') =
|
||||||
|
if 0 <= c' && c' < w && 0 <= r' && r' < h
|
||||||
|
then case grid !! r' !! c' of
|
||||||
|
'W' -> Left ()
|
||||||
|
cel -> Right (c', r')
|
||||||
|
else Left ()
|
||||||
|
probs =
|
||||||
|
case currCell of
|
||||||
|
'C' -> fmap (0.25 *) [0, 1, 0] -- concrete
|
||||||
|
'M' -> fmap (0.25 *) [0.1, 0.8, 0.1] -- mud
|
||||||
|
'G' -> fmap (0.25 *) [0.2, 0.6, 0.2] -- grass
|
||||||
|
'S' -> fmap (0.25 *) [0.3, 0.4, 0.3] -- sand
|
||||||
|
nextCoords =
|
||||||
|
case i of
|
||||||
|
'N' -> [(c-1, r-1), (c, r-1), (c+1, r-1)]
|
||||||
|
'E' -> [(c+1, r-1), (c+1, r), (c+1, r+1)]
|
||||||
|
'S' -> [(c-1, r+1), (c, r+1), (c+1, r+1)]
|
||||||
|
'W' -> [(c-1, r-1), (c-1, r), (c-1, r+1)]
|
||||||
|
in vector (zip (fmap filterValid nextCoords) probs)
|
||||||
|
|
||||||
|
ini :: V State
|
||||||
|
ini = dirac (Right (0, 0))
|
||||||
|
|
||||||
|
acc :: State -> Prob
|
||||||
|
acc (Left _) = 1
|
||||||
|
acc (Right _) = 0
|
||||||
|
|
||||||
|
ss :: World -> [State]
|
||||||
|
ss (grid, w, h) = Left () : fmap Right goodCells
|
||||||
|
where
|
||||||
|
allCells = (,) <$> [0..w-1] <*> [0..h-1]
|
||||||
|
goodCells = filter (\(c, r) -> grid !! r !! c /= 'W') allCells
|
||||||
|
|
||||||
|
toPA :: World -> PA State Alph
|
||||||
|
toPA world = PA
|
||||||
|
{ states = ss world
|
||||||
|
, alphabet = alph
|
||||||
|
, initialState = ini
|
||||||
|
, acceptance = acc
|
||||||
|
, transitions = delta world
|
||||||
|
}
|
||||||
|
|
||||||
|
firstPA :: PA State Alph
|
||||||
|
firstPA = toPA firstW
|
||||||
|
|
||||||
|
secondPA :: PA State Alph
|
||||||
|
secondPA = toPA secondW
|
60
probabilistic/src/Output.hs
Normal file
60
probabilistic/src/Output.hs
Normal file
|
@ -0,0 +1,60 @@
|
||||||
|
{-# language PartialTypeSignatures #-}
|
||||||
|
{-# language TupleSections #-}
|
||||||
|
{-# language DerivingVia #-}
|
||||||
|
{-# language StandaloneDeriving #-}
|
||||||
|
{-# language TypeSynonymInstances #-}
|
||||||
|
{-# language FlexibleInstances #-}
|
||||||
|
|
||||||
|
module Output where
|
||||||
|
|
||||||
|
import PA
|
||||||
|
import Prob (Prob)
|
||||||
|
import Data.List (intercalate)
|
||||||
|
import qualified Data.Map as Map
|
||||||
|
import Text.Printf
|
||||||
|
|
||||||
|
probShow :: Prob -> String
|
||||||
|
probShow p = printf "%f" (fromRational p :: Double)
|
||||||
|
|
||||||
|
-- Printing the PA
|
||||||
|
class StateShow x where
|
||||||
|
sshow :: x -> String
|
||||||
|
class InputShow i where
|
||||||
|
ishow :: i -> String
|
||||||
|
|
||||||
|
instance StateShow String where sshow str = str
|
||||||
|
instance InputShow String where ishow str = str
|
||||||
|
instance StateShow Char where sshow c = [c]
|
||||||
|
instance InputShow Char where ishow c = [c]
|
||||||
|
|
||||||
|
newtype DefaultShow x = DS { unDS :: x }
|
||||||
|
instance (Show x) => StateShow (DefaultShow x) where sshow (DS x) = "s" <> show x
|
||||||
|
instance (Show i) => InputShow (DefaultShow i) where ishow (DS i) = "i" <> show i
|
||||||
|
|
||||||
|
deriving via DefaultShow Int instance StateShow Int
|
||||||
|
deriving via DefaultShow Int instance InputShow Int
|
||||||
|
|
||||||
|
dotShow :: (StateShow s, InputShow i) => PA s i -> String
|
||||||
|
dotShow pa =
|
||||||
|
"digraph pa {\n"
|
||||||
|
<> concatMap (\s -> " " <> sshow s <> " [label=\"" <> probShow (acceptance pa s) <> "\"]\n") (states pa)
|
||||||
|
<> concatMap (\(s, p) -> " _init -> " <> sshow s <> " [probability=\"" <> probShow p <> "\"]\n") (initialState pa)
|
||||||
|
<> concatMap (\(s, i, (t, p)) -> " " <> sshow s <> " -> " <> sshow t <> " [label=\"" <> ishow i <> "\" probability=\"" <> probShow p <> "\"]\n") allTrans
|
||||||
|
<> "}\n"
|
||||||
|
where
|
||||||
|
allTrans = concatMap (\(s, i) -> fmap (s,i,) (transitions pa s i)) $ (,) <$> states pa <*> alphabet pa
|
||||||
|
|
||||||
|
|
||||||
|
denseShow :: (StateShow s, InputShow i, Ord s) => PA s i -> String
|
||||||
|
denseShow pa =
|
||||||
|
"states = [" <> intercalate ", " (fmap sshow (states pa)) <> "]\n"
|
||||||
|
<> "alphabet = [" <> intercalate ", " (fmap ishow (alphabet pa)) <> "]\n"
|
||||||
|
<> "initial = [" <> intercalate ", " (fmap (\s -> probShow (Map.findWithDefault 0 s iMap)) (states pa)) <> "]\n"
|
||||||
|
<> "final = " <> showV (probShow . acceptance pa) (states pa) <> "\n"
|
||||||
|
<> intercalate "\n" (fmap (\a -> "trans_" <> ishow a <> " = " <> showM (matrixFor a)) (alphabet pa))
|
||||||
|
<> "\n"
|
||||||
|
where
|
||||||
|
iMap = Map.fromList (initialState pa)
|
||||||
|
matrixFor i = [[ Map.findWithDefault 0 c row | c <- states pa] | r <- states pa, let row = Map.fromList (transitions pa r i)]
|
||||||
|
showM (firstR:restR) = "[" <> showV probShow firstR <> ",\n " <> intercalate ",\n " (fmap (showV probShow) restR) <> "]"
|
||||||
|
showV f l = "[" <> intercalate ", " (fmap f l) <> "]"
|
35
probabilistic/src/PA.hs
Normal file
35
probabilistic/src/PA.hs
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
{-# language PartialTypeSignatures #-}
|
||||||
|
{-# language TupleSections #-}
|
||||||
|
{-# language DerivingVia #-}
|
||||||
|
{-# language StandaloneDeriving #-}
|
||||||
|
{-# language TypeSynonymInstances #-}
|
||||||
|
{-# language FlexibleInstances #-}
|
||||||
|
|
||||||
|
module PA where
|
||||||
|
|
||||||
|
import Prob
|
||||||
|
|
||||||
|
-- Probabilistic Automata
|
||||||
|
data PA s i = PA
|
||||||
|
{ states :: [s]
|
||||||
|
, alphabet :: [i]
|
||||||
|
, initialState :: V s
|
||||||
|
, acceptance :: s -> Prob
|
||||||
|
, transitions :: s -> i -> V s }
|
||||||
|
|
||||||
|
example :: PA Int Char
|
||||||
|
example = PA
|
||||||
|
{ states = [0, 1, 2]
|
||||||
|
, alphabet = ['a']
|
||||||
|
, initialState = vector [(0, 1)]
|
||||||
|
, acceptance = \n ->
|
||||||
|
case n of
|
||||||
|
0 -> 0
|
||||||
|
1 -> 0.1
|
||||||
|
n -> 1
|
||||||
|
, transitions = \n c ->
|
||||||
|
case n of
|
||||||
|
0 -> vector [(1, 0.5), (0, 0.5)]
|
||||||
|
1 -> vector [(2, 0.9)]
|
||||||
|
n -> []
|
||||||
|
}
|
22
probabilistic/src/Prob.hs
Normal file
22
probabilistic/src/Prob.hs
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
{-# language TupleSections #-}
|
||||||
|
|
||||||
|
module Prob where
|
||||||
|
|
||||||
|
import qualified Data.Map as Map
|
||||||
|
|
||||||
|
-- Probability Distributions
|
||||||
|
type Prob = Rational
|
||||||
|
type V s = [(s, Prob)]
|
||||||
|
|
||||||
|
-- sums up duplicates
|
||||||
|
vector :: (Ord s) => [(s, Prob)] -> V s
|
||||||
|
vector = Map.toList . Map.filter (> 0) . Map.fromListWith (+)
|
||||||
|
|
||||||
|
-- point distribution
|
||||||
|
dirac :: a -> V a
|
||||||
|
dirac x = [(x, 1)]
|
||||||
|
|
||||||
|
-- uniform distribution
|
||||||
|
unif :: (Ord a) => [a] -> V a
|
||||||
|
unif l = vector (fmap (,p) l)
|
||||||
|
where p = 1 / fromIntegral (length l)
|
Loading…
Add table
Reference in a new issue