Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • ghc/nofib
  • sgraf812/nofib
  • Abhiroop/nofib
  • ggreif/nofib
  • phadej/nofib
  • AndreasK/nofib
  • takenobu-hs/nofib
  • hsyl20/nofib
  • trac-matthewbauer/nofib
  • bgamari/nofib
  • trac-vdukhovni/nofib
  • cptwunderlich/nofib
  • alinab/nofib
  • teo/nofib
14 results
Show changes
Commits on Source (15)
......@@ -8,6 +8,8 @@ cachegrind.out.*
cachegrind.out.summary
perf.data
perf.data.*
dist-newstyle/
.ghc.environment.*
# Specific generated files
nofib-analyse/nofib-analyse
......@@ -107,6 +109,7 @@ spectral/constraints/constraints
spectral/cryptarithm1/cryptarithm1
spectral/cryptarithm2/cryptarithm2
spectral/cse/cse
spectral/dom-lt/dom-lt
spectral/eliza/eliza
spectral/exact-reals/exact-reals
spectral/expert/expert
......
variables:
DOCKER_REV: 2b69e99de97bd5bf1fbdbf45852231c3dcb602b6
validate:
image: ghcci/x86_64-linux-deb9:0.2
image: "registry.gitlab.haskell.org/ghc/ci-images/x86_64-linux-deb9:$DOCKER_REV"
tags:
- x86_64-linux
before_script:
- git clean -xdf
- sudo apt install -y time
- ghc --version
- cabal --version
script:
- make clean
- |
cabal update
cabal install regex-compat html
- cabal update
- make boot mode=fast
- "make mode=fast NoFibRuns=1 2>&1 | tee log"
- "nofib-analyse/nofib-analyse log"
......
......@@ -12,33 +12,26 @@ pick `$(which ghc)` or whatever the `HC` environment variable is set to.
Additional information can also be found on
[NoFib's wiki page](https://ghc.haskell.org/trac/ghc/wiki/Building/RunningNoFib).
## Package Depedencies
Please make sure you have the following packages installed for your
system GHC:
* html
* regex-compat (will install: mtl, regex-base, regex-posix)
There's also a `easy.sh` helper script, which as name implies, is
automated and easy way to run `nofib`.
See the section at the end of README for its usage.
## Using
<details>
<summary>Git symlink support for Windows machines</summary>
NoFib uses a few symlinks here and there to share code between benchmarks.
Git for Windows has symlinks support for some time now, but
[it may not be enabled by default](https://stackoverflow.com/a/42137273/388010).
You will notice strange `make boot` failures if it's not enabled for you.
Make sure you follow the instructions in the link to enable symlink support,
possibly as simple as through `git config core.symlinks true` or cloning with
`git clone -c core.symlinks=true <URL>`.
</details>
Install the [package dependencies](#package-dependencies):
```
$ cabal install html regex-compat
```
Install [`cabal-install-2.4`](https://www.haskell.org/cabal/download.html) or later.
Then, to run the tests, execute:
......@@ -60,8 +53,11 @@ $ make boot
$ make EXTRA_HC_OPTS="-fllvm"
```
**Note:** to get all the results, you have to `clean` and `boot` between
separate `nofib` runs.
To compare the results of multiple runs, save the output in a logfile
and use the program in `../utils/nofib-analyse`, for example:
and use the program in `./nofib-analyse/nofib-analyse`, for example:
```
...
......@@ -115,6 +111,19 @@ This is the default of its `-i` option, which is of course incompatible with
`mode=fast`. In that case, you should just set `-i` as appropriate, even
deactivate it with `-i 0`.
## Boot vs. benchmarked GHC
The `nofib-analyse` utility is compiled with `BOOT_HC` compiler,
which may be different then the GHC under the benchmark.
You can control which GHC you benchmark with `HC` variable
```
$ make clean
$ make boot HC=ghc-head
$ make HC=ghc-head 2>&1 | tee nofib-log-ghc-head
```
## Configuration
There are some options you might want to tweak; search for nofib in
......@@ -148,11 +157,51 @@ If you add a benchmark try to set the problem sizes for
fast/normal/slow reasonably. [Modes](#modes) lists the recommended brackets for
each mode.
### Benchmark Categories
So you have a benchmark to submit but don't know in which subfolder to put it? Here's some
advice on the intended semantics of each category.
#### Single threaded benchmarks
These are run when you just type `make`. Their semantics is explained in
[the Nofib paper](https://link.springer.com/chapter/10.1007%2F978-1-4471-3215-8_17)
(You can find a .ps online, thanks to @bgamari. Alternatively grep for
'Spectral' in docs/paper/paper.verb).
- `imaginary`: Mostly toy benchmarks, solving puzzles like n-queens.
- `spectral`: Algorithmic kernels, like FFT. If you want to add a benchmark of a
library, this most certainly the place to put it.
- `real`: Actual applications, with a command-line interface and all. Because of
the large dependency footprint of today's applications, these have become
rather aged.
- `shootout`: Benchmarks from
[the benchmarks game](https://benchmarksgame-team.pages.debian.net/benchmarksgame/),
formerly known as "language shootout".
Most of the benchmarks are quite old and aren't really written in way one would
write high-performance Haskell code today (e.g., use of `String`, lists,
redefining own list combinators that don't take part in list fusion, rare use of
strictness annotations or unboxed data), so new benchmarks for the `real` and
`spectral` in brackets in particular are always welcome!
#### Other categories
Other than the default single-threaded categories above, there are the
following (SG: I'm guessing here, have never run them):
- `gc`: Run by `make -C gc` (though you'll probably have to edit the Makefile to
your specific config). Select benchmarks from `spectral` and `real`, plus a
few more (Careful, these have not been touched by #15999/!5, see the next
subsection). Testdrives different GC configs, apparently.
- `smp`: Microbenchmarks for the `-threaded` runtime, measuring scheduler
performance on concurrent and STM-heavy code.
### Stability wrt. GC paramerisations
Additionally, pay attention that your benchmarks are stable wrt. different
Additionally, pay attention that your benchmarks are stable wrt. different
GC paramerisations, so that small changes in allocation don't lead to big,
unexplicable jumps in performance. See Trac #15999 for details. Also make sure
unexplicable jumps in performance. See #15999 for details. Also make sure
that you run the benchmark with the default GC settings, as enlarging Gen 0 or
Gen 1 heaps just amplifies the problem.
......@@ -162,6 +211,23 @@ working set grows and shrinks (e.g. is approximately constant) over the whole
run of the benchmark. You can ensure this by iterating your main logic $n times
(how often depends on your program, but in the ball park of 100-1000).
You can test stability by plotting productivity curves for your `fast` settings
with the `prod.py` script attached to Trac #15999.
with the `prod.py` script attached to #15999.
If in doubt, ask Sebastian Graf for help.
## easy.sh
```
./easy.sh - easy nofib
Usage: ./easy.sh [ -m mode ] /path/to/baseline/ghc /path/to/new/ghc"
GHC paths can point to the root of the GHC repository,
if it's build with Hadrian.
Available options:
-m MODE nofib mode: fast norm slow
This script caches the results using the sha256 of ghc executable.
Remove these files, if you want to rerun the benchmark.
```
#!/bin/sh
echo '\033]0;NOFIB: starting...\007'
# Settings
#######################################################################
mode=norm
# "Library" part
#######################################################################
show_usage () {
cat <<EOF
./easy.sh - easy nofib
Usage: ./easy.sh [ -m mode ] /path/to/baseline/ghc /path/to/new/ghc"
GHC paths can point to the root of the GHC repository,
if it's build with Hadrian.
Available options:
-m MODE nofib mode: fast norm slow
This script caches the results using the sha256 of ghc executable.
Remove these files, if you want to rerun the benchmark.
EOF
}
hashoffile () {
shasum -a 256 $1 | awk '{ print $1 }'
}
# getopt
#######################################################################
while getopts 'm:' flag; do
case $flag in
m)
case $OPTARG in
slow)
mode=$OPTARG
;;
norm)
mode=$OPTARG
;;
fast)
mode=$OPTARG
;;
*)
echo "Unknown mode: $OPTARG"
show_usage
exit 1
;;
esac
;;
?) show_usage
;;
esac
done
shift $((OPTIND - 1))
if [ $# -ne 2 ]; then
echo "Expected two arguments: ghc executables or roots of source repositories"
show_usage
exit 1
fi
OLD_HC=$1
NEW_HC=$2
# Set up
#######################################################################
# Arguments can point to GHC repository roots
if [ -d $OLD_HC -a -f "$OLD_HC/_build/stage1/bin/ghc" ]; then
OLD_HC="$OLD_HC/_build/stage1/bin/ghc"
fi
if [ -d $NEW_HC -a -f "$NEW_HC/_build/stage1/bin/ghc" ]; then
NEW_HC="$NEW_HC/_build/stage1/bin/ghc"
fi
# Check we have executables
if [ ! -f $NEW_HC -a -x $OLD_HC ]; then
echo "$OLD_HC is not an executable"
exit 1
fi
if [ ! -f $NEW_HC -a -x $NEW_HC ]; then
echo "$NEW_HC is not an executable"
exit 1
fi
# Info before we get going
#######################################################################
echo "Running nofib (mode=$mode) with $OLD_HC and $NEW_HC"
echo "Running nofib (mode=$mode) with $OLD_HC and $NEW_HC" | sed 's/./-/g'
sleep 2
# Run nofib
#######################################################################
# Run with old ghc
echo '\033]0;NOFIB: old\007'
OLD_HASH=$(hashoffile $OLD_HC)
OLD_OUTPUT=result-$OLD_HASH-$mode.txt
if [ -f $OLD_OUTPUT ]; then
echo "$OLD_OUTPUT exists; not re-running."
else
echo '\033]0;NOFIB: old, cleaning...\007'
make clean
echo '\033]0;NOFIB: old, booting...\007'
make boot mode=$mode HC=$OLD_HC
echo '\033]0;NOFIB: old, benchmarking...\007'
make mode=$mode HC=$OLD_HC 2>&1 | tee $OLD_OUTPUT
fi
# Run with new ghc
echo '\033]0;NOFIB: new\007'
NEW_HASH=$(hashoffile $NEW_HC)
NEW_OUTPUT=result-$NEW_HASH-$mode.txt
if [ -f $NEW_OUTPUT ]; then
echo "$NEW_OUTPUT exists; not re-running."
else
echo '\033]0;NOFIB: new, cleaning...\007'
make clean
echo '\033]0;NOFIB: new, booting...\007'
make boot mode=$mode HC=$NEW_HC
echo '\033]0;NOFIB: new, benchmarking...\007'
make mode=$mode HC=$NEW_HC 2>&1 | tee $NEW_OUTPUT
fi
# Done
#######################################################################
echo '\033]0;NOFIB: done\007'
# Analyse
./nofib-analyse/nofib-analyse $OLD_OUTPUT $NEW_OUTPUT > report.txt
# Show report
less report.txt
......@@ -37,7 +37,6 @@ STDIN_FILE = $(wildcard $(NOFIB_PROG).stdin)
endif
endif
# Bogosity needed here to cope with .exe suffix for strip & size files.
# (shouldn't have to be our problem.)
ifneq "$(HC_FAIL)" "YES"
......
......@@ -4,7 +4,8 @@ include $(TOP)/mk/boilerplate.mk
PROG = nofib-analyse
$(PROG): *.hs
$(BOOT_HC) -O -cpp --make Main -o $(PROG)
cabal v2-build -w $(BOOT_HC)
cp $$(cabal v2-exec -w $(BOOT_HC) -- which $(PROG)) $(PROG)
all :: $(PROG)
......@@ -16,8 +17,7 @@ boot :: $(PROG)
.PHONY: mostlyclean clean distclean maintainer-clean
mostlyclean::
rm -f CmdLine.hi GenUtils.hi Main.hi Slurp.hi
rm -f CmdLine.o GenUtils.o Main.o Slurp.o
rm -rf dist-newstyle dist .ghc.environment.*
clean:: mostlyclean
rm -f $(PROG)
......
-- project file for "boot" utilities
packages: .
cabal-version: 2.4
name: nofib-analyse
version: 0
executable nofib-analyse
default-language: Haskell2010
main-is: Main.hs
other-modules:
CmdLine
GenUtils
Slurp
build-depends:
, array
, base
, containers
, regex-compat
......@@ -3,7 +3,7 @@ include $(TOP)/mk/boilerplate.mk
# TODO(michalt): Re-enable `secretary` (requires `random`)
SUBDIRS = ansi atom awards banner boyer boyer2 calendar cichelli circsim \
clausify constraints cryptarithm1 cryptarithm2 cse eliza expert \
clausify constraints cryptarithm1 cryptarithm2 cse dom-lt eliza expert \
exact-reals fft2 fibheaps fish gcd hartel integer knights lambda \
last-piece lcss life mandel mandel2 mate minimax multiplier para \
power pretty primetest puzzle rewrite scc simple sorting sphere \
......
{-# LANGUAGE RankNTypes, BangPatterns, FlexibleContexts, Strict #-}
{- |
Module : Data.Graph.Dom
Copyright : (c) Matt Morrow 2009
License : BSD3
The Lengauer-Tarjan graph dominators algorithm.
\[1\] Lengauer, Tarjan,
/A Fast Algorithm for Finding Dominators in a Flowgraph/, 1979.
\[2\] Muchnick,
/Advanced Compiler Design and Implementation/, 1997.
\[3\] Brisk, Sarrafzadeh,
/Interference Graphs for Procedures in Static Single/
/Information Form are Interval Graphs/, 2007.
Taken from the dom-lt package.
-}
module Dom (
Node,Path,Edge
,Graph,Rooted
,idom,ipdom
,domTree,pdomTree
,dom,pdom
,pddfs,rpddfs
,fromAdj,fromEdges
,toAdj,toEdges
,asTree,asGraph
,parents,ancestors
) where
import Data.Monoid(Monoid(..))
import Data.Bifunctor
import Data.Tuple (swap)
import Data.Tree
import Data.List
import Data.IntMap(IntMap)
import Data.IntSet(IntSet)
import qualified Data.IntMap.Strict as IM
import qualified Data.IntSet as IS
import Control.Monad
import Control.Monad.ST.Strict
import Data.Array.ST
import Data.Array.Base
(unsafeNewArray_
,unsafeWrite,unsafeRead)
-----------------------------------------------------------------------------
type Node = Int
type Path = [Node]
type Edge = (Node,Node)
type Graph = IntMap IntSet
type Rooted = (Node, Graph)
-----------------------------------------------------------------------------
-- | /Dominators/.
-- Complexity as for @idom@
dom :: Rooted -> [(Node, Path)]
dom = ancestors . domTree
-- | /Post-dominators/.
-- Complexity as for @idom@.
pdom :: Rooted -> [(Node, Path)]
pdom = ancestors . pdomTree
-- | /Dominator tree/.
-- Complexity as for @idom@.
domTree :: Rooted -> Tree Node
domTree a@(r,_) =
let is = filter ((/=r).fst) (idom a)
tg = fromEdges (fmap swap is)
in asTree (r,tg)
-- | /Post-dominator tree/.
-- Complexity as for @idom@.
pdomTree :: Rooted -> Tree Node
pdomTree a@(r,_) =
let is = filter ((/=r).fst) (ipdom a)
tg = fromEdges (fmap swap is)
in asTree (r,tg)
-- | /Immediate dominators/.
-- /O(|E|*alpha(|E|,|V|))/, where /alpha(m,n)/ is
-- \"a functional inverse of Ackermann's function\".
--
-- This Complexity bound assumes /O(1)/ indexing. Since we're
-- using @IntMap@, it has an additional /lg |V|/ factor
-- somewhere in there. I'm not sure where.
idom :: Rooted -> [(Node,Node)]
idom rg = runST (evalS idomM =<< initEnv (pruneReach rg))
-- | /Immediate post-dominators/.
-- Complexity as for @idom@.
ipdom :: Rooted -> [(Node,Node)]
ipdom rg = runST (evalS idomM =<< initEnv (pruneReach (second predG rg)))
-----------------------------------------------------------------------------
-- | /Post-dominated depth-first search/.
pddfs :: Rooted -> [Node]
pddfs = reverse . rpddfs
-- | /Reverse post-dominated depth-first search/.
rpddfs :: Rooted -> [Node]
rpddfs = concat . levels . pdomTree
-----------------------------------------------------------------------------
type Dom s a = S s (Env s) a
type NodeSet = IntSet
type NodeMap a = IntMap a
data Env s = Env
{succE :: !Graph
,predE :: !Graph
,bucketE :: !Graph
,dfsE :: {-# UNPACK #-}!Int
,zeroE :: {-# UNPACK #-}!Node
,rootE :: {-# UNPACK #-}!Node
,labelE :: {-# UNPACK #-}!(Arr s Node)
,parentE :: {-# UNPACK #-}!(Arr s Node)
,ancestorE :: {-# UNPACK #-}!(Arr s Node)
,childE :: {-# UNPACK #-}!(Arr s Node)
,ndfsE :: {-# UNPACK #-}!(Arr s Node)
,dfnE :: {-# UNPACK #-}!(Arr s Int)
,sdnoE :: {-# UNPACK #-}!(Arr s Int)
,sizeE :: {-# UNPACK #-}!(Arr s Int)
,domE :: {-# UNPACK #-}!(Arr s Node)
,rnE :: {-# UNPACK #-}!(Arr s Node)}
-----------------------------------------------------------------------------
idomM :: Dom s [(Node,Node)]
idomM = do
dfsDom =<< rootM
n <- gets dfsE
forM_ [n,n-1..1] (\i-> do
w <- ndfsM i
sw <- sdnoM w
ps <- predsM w
forM_ ps (\v-> do
u <- eval v
su <- sdnoM u
when (su < sw)
(store sdnoE w su))
z <- ndfsM =<< sdnoM w
modify(\e->e{bucketE=IM.adjust
(w`IS.insert`)
z (bucketE e)})
pw <- parentM w
link pw w
bps <- bucketM pw
forM_ bps (\v-> do
u <- eval v
su <- sdnoM u
sv <- sdnoM v
let dv = case su < sv of
True-> u
False-> pw
store domE v dv))
forM_ [1..n] (\i-> do
w <- ndfsM i
j <- sdnoM w
z <- ndfsM j
dw <- domM w
when (dw /= z)
(do ddw <- domM dw
store domE w ddw))
fromEnv
-----------------------------------------------------------------------------
eval :: Node -> Dom s Node
eval v = do
n0 <- zeroM
a <- ancestorM v
case a==n0 of
True-> labelM v
False-> do
compress v
a <- ancestorM v
l <- labelM v
la <- labelM a
sl <- sdnoM l
sla <- sdnoM la
case sl <= sla of
True-> return l
False-> return la
compress :: Node -> Dom s ()
compress v = do
n0 <- zeroM
a <- ancestorM v
aa <- ancestorM a
when (aa /= n0) (do
compress a
a <- ancestorM v
aa <- ancestorM a
l <- labelM v
la <- labelM a
sl <- sdnoM l
sla <- sdnoM la
when (sla < sl)
(store labelE v la)
store ancestorE v aa)
-----------------------------------------------------------------------------
link :: Node -> Node -> Dom s ()
link v w = do
n0 <- zeroM
lw <- labelM w
slw <- sdnoM lw
let balance s = do
c <- childM s
lc <- labelM c
slc <- sdnoM lc
case slw < slc of
False-> return s
True-> do
zs <- sizeM s
zc <- sizeM c
cc <- childM c
zcc <- sizeM cc
case 2*zc <= zs+zcc of
True-> do
store ancestorE c s
store childE s cc
balance s
False-> do
store sizeE c zs
store ancestorE s c
balance c
s <- balance w
lw <- labelM w
zw <- sizeM w
store labelE s lw
store sizeE v . (+zw) =<< sizeM v
let follow s = do
when (s /= n0) (do
store ancestorE s v
follow =<< childM s)
zv <- sizeM v
follow =<< case zv < 2*zw of
False-> return s
True-> do
cv <- childM v
store childE v s
return cv
-----------------------------------------------------------------------------
dfsDom :: Node -> Dom s ()
dfsDom i = do
_ <- go i
n0 <- zeroM
r <- rootM
store parentE r n0
where go i = do
n <- nextM
store dfnE i n
store sdnoE i n
store ndfsE n i
store labelE i i
ss <- succsM i
forM_ ss (\j-> do
s <- sdnoM j
case s==0 of
False-> return()
True-> do
store parentE j i
go j)
-----------------------------------------------------------------------------
initEnv :: Rooted -> ST s (Env s)
initEnv (r0,g0) = do
let (g,rnmap) = renum 1 g0
pred = predG g
r = rnmap IM.! r0
n = IM.size g
ns = [0..n]
m = n+1
let bucket = IM.fromList
(zip ns (repeat mempty))
rna <- newI m
writes rna (fmap swap
(IM.toList rnmap))
doms <- newI m
sdno <- newI m
size <- newI m
parent <- newI m
ancestor <- newI m
child <- newI m
label <- newI m
ndfs <- newI m
dfn <- newI m
forM_ [0..n] (doms.=0)
forM_ [0..n] (sdno.=0)
forM_ [1..n] (size.=1)
forM_ [0..n] (ancestor.=0)
forM_ [0..n] (child.=0)
(doms.=r) r
(size.=0) 0
(label.=0) 0
return (Env
{rnE = rna
,dfsE = 0
,zeroE = 0
,rootE = r
,labelE = label
,parentE = parent
,ancestorE = ancestor
,childE = child
,ndfsE = ndfs
,dfnE = dfn
,sdnoE = sdno
,sizeE = size
,succE = g
,predE = pred
,bucketE = bucket
,domE = doms})
fromEnv :: Dom s [(Node,Node)]
fromEnv = do
dom <- gets domE
rn <- gets rnE
-- r <- gets rootE
(_,n) <- st (getBounds dom)
forM [1..n] (\i-> do
j <- st(rn!:i)
d <- st(dom!:i)
k <- st(rn!:d)
return (j,k))
-----------------------------------------------------------------------------
zeroM :: Dom s Node
zeroM = gets zeroE
domM :: Node -> Dom s Node
domM = fetch domE
rootM :: Dom s Node
rootM = gets rootE
succsM :: Node -> Dom s [Node]
succsM i = gets (IS.toList . (!i) . succE)
predsM :: Node -> Dom s [Node]
predsM i = gets (IS.toList . (!i) . predE)
bucketM :: Node -> Dom s [Node]
bucketM i = gets (IS.toList . (!i) . bucketE)
sizeM :: Node -> Dom s Int
sizeM = fetch sizeE
sdnoM :: Node -> Dom s Int
sdnoM = fetch sdnoE
-- dfnM :: Node -> Dom s Int
-- dfnM = fetch dfnE
ndfsM :: Int -> Dom s Node
ndfsM = fetch ndfsE
childM :: Node -> Dom s Node
childM = fetch childE
ancestorM :: Node -> Dom s Node
ancestorM = fetch ancestorE
parentM :: Node -> Dom s Node
parentM = fetch parentE
labelM :: Node -> Dom s Node
labelM = fetch labelE
nextM :: Dom s Int
nextM = do
n <- gets dfsE
let n' = n+1
modify(\e->e{dfsE=n'})
return n'
-----------------------------------------------------------------------------
type A = STUArray
type Arr s a = A s Int a
infixl 9 !:
infixr 2 .=
(.=) :: (MArray (A s) a (ST s))
=> Arr s a -> a -> Int -> ST s ()
(v .= x) i = unsafeWrite v i x
(!:) :: (MArray (A s) a (ST s))
=> A s Int a -> Int -> ST s a
a !: i = do
o <- unsafeRead a i
return $! o
new :: (MArray (A s) a (ST s))
=> Int -> ST s (Arr s a)
new n = unsafeNewArray_ (0,n-1)
newI :: Int -> ST s (Arr s Int)
newI = new
-- newD :: Int -> ST s (Arr s Double)
-- newD = new
-- dump :: (MArray (A s) a (ST s)) => Arr s a -> ST s [a]
-- dump a = do
-- (m,n) <- getBounds a
-- forM [m..n] (\i -> a!:i)
writes :: (MArray (A s) a (ST s))
=> Arr s a -> [(Int,a)] -> ST s ()
writes a xs = forM_ xs (\(i,x) -> (a.=x) i)
-- arr :: (MArray (A s) a (ST s)) => [a] -> ST s (Arr s a)
-- arr xs = do
-- let n = length xs
-- a <- new n
-- go a n 0 xs
-- return a
-- where go _ _ _ [] = return ()
-- go a n i (x:xs)
-- | i <= n = (a.=x) i >> go a n (i+1) xs
-- | otherwise = return ()
-----------------------------------------------------------------------------
(!) :: Monoid a => IntMap a -> Int -> a
(!) g n = maybe mempty id (IM.lookup n g)
fromAdj :: [(Node, [Node])] -> Graph
fromAdj = IM.fromList . fmap (second IS.fromList)
fromEdges :: [Edge] -> Graph
fromEdges = collectI IS.union fst (IS.singleton . snd)
toAdj :: Graph -> [(Node, [Node])]
toAdj = fmap (second IS.toList) . IM.toList
toEdges :: Graph -> [Edge]
toEdges = concatMap (uncurry (fmap . (,))) . toAdj
predG :: Graph -> Graph
predG g = IM.unionWith IS.union (go g) g0
where g0 = fmap (const mempty) g
f :: IntMap IntSet -> Int -> IntSet -> IntMap IntSet
f m i a = foldl' (\m p -> IM.insertWith mappend p
(IS.singleton i) m)
m
(IS.toList a)
go :: IntMap IntSet -> IntMap IntSet
go = flip IM.foldlWithKey' mempty f
pruneReach :: Rooted -> Rooted
pruneReach (r,g) = (r,g2)
where is = reachable
(maybe mempty id
. flip IM.lookup g) $ r
g2 = IM.fromList
. fmap (second (IS.filter (`IS.member`is)))
. filter ((`IS.member`is) . fst)
. IM.toList $ g
tip :: Tree a -> (a, [Tree a])
tip (Node a ts) = (a, ts)
parents :: Tree a -> [(a, a)]
parents (Node i xs) = p i xs
++ concatMap parents xs
where p i = fmap (flip (,) i . rootLabel)
ancestors :: Tree a -> [(a, [a])]
ancestors = go []
where go acc (Node i xs)
= let acc' = i:acc
in p acc' xs ++ concatMap (go acc') xs
p is = fmap (flip (,) is . rootLabel)
asGraph :: Tree Node -> Rooted
asGraph t@(Node a _) = let g = go t in (a, fromAdj g)
where go (Node a ts) = let as = (fst . unzip . fmap tip) ts
in (a, as) : concatMap go ts
asTree :: Rooted -> Tree Node
asTree (r,g) = let go a = Node a (fmap go ((IS.toList . f) a))
f = (g !)
in go r
reachable :: (Node -> NodeSet) -> (Node -> NodeSet)
reachable f a = go (IS.singleton a) a
where go seen a = let s = f a
as = IS.toList (s `IS.difference` seen)
in foldl' go (s `IS.union` seen) as
collectI :: (c -> c -> c)
-> (a -> Int) -> (a -> c) -> [a] -> IntMap c
collectI (<>) f g
= foldl' (\m a -> IM.insertWith (<>)
(f a)
(g a) m) mempty
-- collect :: (Ord b) => (c -> c -> c)
-- -> (a -> b) -> (a -> c) -> [a] -> Map b c
-- collect (<>) f g
-- = foldl' (\m a -> SM.insertWith (<>)
-- (f a)
-- (g a) m) mempty
-- (renamed, old -> new)
renum :: Int -> Graph -> (Graph, NodeMap Node)
renum from = (\(_,m,g)->(g,m))
. IM.foldlWithKey'
f (from,mempty,mempty)
where
f :: (Int, NodeMap Node, IntMap IntSet) -> Node -> IntSet
-> (Int, NodeMap Node, IntMap IntSet)
f (!n,!env,!new) i ss =
let (j,n2,env2) = go n env i
(n3,env3,ss2) = IS.fold
(\k (!n,!env,!new)->
case go n env k of
(l,n2,env2)-> (n2,env2,l `IS.insert` new))
(n2,env2,mempty) ss
new2 = IM.insertWith IS.union j ss2 new
in (n3,env3,new2)
go :: Int
-> NodeMap Node
-> Node
-> (Node,Int,NodeMap Node)
go !n !env i =
case IM.lookup i env of
Just j -> (j,n,env)
Nothing -> (n,n+1,IM.insert i n env)
-----------------------------------------------------------------------------
newtype S z s a = S {unS :: forall o. (a -> s -> ST z o) -> s -> ST z o}
instance Functor (S z s) where
fmap f (S g) = S (\k -> g (k . f))
instance Monad (S z s) where
return = pure
S g >>= f = S (\k -> g (\a -> unS (f a) k))
instance Applicative (S z s) where
pure a = S (\k -> k a)
(<*>) = ap
-- get :: S z s s
-- get = S (\k s -> k s s)
gets :: (s -> a) -> S z s a
gets f = S (\k s -> k (f s) s)
-- set :: s -> S z s ()
-- set s = S (\k _ -> k () s)
modify :: (s -> s) -> S z s ()
modify f = S (\k -> k () . f)
-- runS :: S z s a -> s -> ST z (a, s)
-- runS (S g) = g (\a s -> return (a,s))
evalS :: S z s a -> s -> ST z a
evalS (S g) = g ((return .) . const)
-- execS :: S z s a -> s -> ST z s
-- execS (S g) = g ((return .) . flip const)
st :: ST z a -> S z s a
st m = S (\k s-> do
a <- m
k a s)
store :: (MArray (A z) a (ST z))
=> (s -> Arr z a) -> Int -> a -> S z s ()
store f i x = do
a <- gets f
st ((a.=x) i)
fetch :: (MArray (A z) a (ST z))
=> (s -> Arr z a) -> Int -> S z s a
fetch f i = do
a <- gets f
st (a!:i)
-----------------------------------------------------------------------------
-- g0 = fromAdj
-- [(1,[2,3])
-- ,(2,[3])
-- ,(3,[4])
-- ,(4,[3,5,6])
-- ,(5,[7])
-- ,(6,[7])
-- ,(7,[4,8])
-- ,(8,[3,9,10])
-- ,(9,[1])
-- ,(10,[7])]
-- g1 = fromAdj
-- [(0,[1])
-- ,(1,[2,3])
-- ,(2,[7])
-- ,(3,[4])
-- ,(4,[5,6])
-- ,(5,[7])
-- ,(6,[4])
-- ,(7,[])]
-----------------------------------------------------------------------------
{-# OPTIONS_GHC -fno-full-laziness #-}
module Main where
import System.Environment
import Data.Bifunctor
import Dom
import Control.Monad
import Data.Traversable
-- Take a filename as input.
-- Each line is expected to be a graph of the form (root, [(vertex, [successors])])
-- Compute the dominators for each line.
main :: IO ()
main = do
[inputFile,repetitions] <- getArgs
let repetitions' = read repetitions
sgraphs <- map (second fromAdj . read) . lines <$> readFile inputFile :: IO [Rooted]
let s = flip map [0..repetitions'] $ (\i -> sum (map (\g -> i + doGraph g) sgraphs)) :: [Int]
print $ sum s
doGraph :: Rooted -> Int
doGraph g = length . idom $ g
\ No newline at end of file
TOP = ../..
include $(TOP)/mk/boilerplate.mk
include $(TOP)/mk/target.mk
# The core (Dom.hs) is taken from the dom-lt package.
# Compute dominators over a graph
# Graphs are real examples for control flow graphs produced by GHC.
# First parameter controls input file, second parameter controls repetitions.
# We do more iterations here for stability over different GC parameterisations
# and to shift compute time away from read/graph creation.
FAST_OPTS = ghc-examples.in 50
NORM_OPTS = ghc-examples.in 400
SLOW_OPTS = ghc-examples.in 1800
# We require containers.
HC_OPTS += -package containers
133008
83076683
2238783
(44,[(462,[211]),(211,[212]),(212,[213]),(213,[214]),(214,[286]),(286,[216,217]),(421,[218,219]),(289,[431]),(431,[221,222]),(389,[223,224]),(434,[225,226]),(292,[227]),(383,[228,229]),(436,[230,231]),(295,[232]),(377,[233,234]),(438,[235,236]),(298,[237]),(371,[238,239]),(440,[240,241]),(301,[242]),(365,[243,244]),(442,[245,246]),(304,[247]),(359,[248,249]),(444,[250,251]),(307,[252]),(353,[253,254]),(446,[255,256]),(310,[257]),(347,[258,259]),(448,[260,261]),(313,[262]),(341,[263,264]),(316,[457]),(457,[266,267]),(317,[459]),(459,[269,270]),(463,[271,272]),(464,[463]),(282,[274,275]),(283,[282]),(274,[277]),(275,[278,279]),(44,[280,281]),(280,[]),(281,[282,283]),(216,[284,285]),(217,[286]),(221,[287,288]),(222,[289]),(225,[290,291]),(226,[292]),(230,[293,294]),(231,[295]),(235,[296,297]),(236,[298]),(240,[299,300]),(241,[301]),(245,[302,303]),(246,[304]),(250,[305,306]),(251,[307]),(255,[308,309]),(256,[310]),(260,[311,312]),(261,[313]),(266,[314,315]),(267,[316]),(269,[]),(270,[317]),(460,[318,319]),(318,[320]),(314,[460]),(315,[]),(458,[322,323]),(322,[324]),(472,[458]),(455,[326,327]),(326,[328]),(470,[455]),(453,[330,331]),(330,[332]),(468,[453]),(451,[334,335]),(334,[336]),(466,[451]),(311,[338]),(342,[341]),(263,[449]),(264,[341]),(343,[]),(312,[342,343]),(308,[344]),(348,[347]),(258,[448]),(259,[347]),(349,[]),(309,[348,349]),(305,[350]),(354,[353]),(253,[446]),(254,[353]),(355,[]),(306,[354,355]),(302,[356]),(360,[359]),(248,[444]),(249,[359]),(361,[]),(303,[360,361]),(299,[362]),(366,[365]),(243,[442]),(244,[365]),(367,[]),(300,[366,367]),(296,[368]),(372,[371]),(238,[440]),(239,[371]),(373,[]),(297,[372,373]),(293,[374]),(378,[377]),(233,[438]),(234,[377]),(379,[]),(294,[378,379]),(290,[380]),(384,[383]),(228,[436]),(229,[383]),(385,[]),(291,[384,385]),(287,[386]),(390,[389]),(223,[434]),(224,[389]),(391,[]),(288,[390,391]),(465,[396,393]),(396,[394,395]),(393,[396]),(404,[402,398]),(405,[404]),(402,[406,401]),(398,[402]),(406,[403]),(394,[404,405]),(401,[406]),(408,[416]),(271,[408]),(272,[409,410]),(409,[411,412]),(410,[463]),(415,[416]),(411,[415]),(417,[416]),(412,[417]),(284,[418]),(422,[421]),(218,[461]),(219,[421]),(423,[]),(285,[422,423]),(277,[429]),(427,[425]),(425,[429]),(278,[427]),(430,[428]),(428,[429]),(279,[430]),(395,[431]),(403,[465]),(386,[434]),(227,[434]),(380,[436]),(232,[436]),(374,[438]),(237,[438]),(368,[440]),(242,[440]),(362,[442]),(247,[442]),(356,[444]),(252,[444]),(350,[446]),(257,[446]),(344,[448]),(262,[448]),(338,[449]),(335,[467]),(336,[451]),(331,[469]),(332,[453]),(327,[471]),(328,[455]),(473,[457]),(323,[457]),(324,[458]),(319,[459]),(320,[460]),(418,[461]),(429,[462]),(461,[463,464]),(416,[465]),(449,[466,467]),(467,[468,469]),(469,[470,471]),(471,[472,473])])
(3,[(41,[28,29]),(51,[30,31]),(40,[51]),(3,[38,34]),(38,[]),(34,[35,36]),(35,[41]),(36,[38]),(28,[51,40]),(29,[41]),(45,[46]),(46,[43,44]),(30,[45]),(43,[]),(44,[46]),(31,[47,48]),(47,[49,50]),(48,[51]),(55,[56]),(56,[53,54]),(49,[55]),(53,[]),(54,[56]),(60,[61]),(61,[58,59]),(50,[60]),(58,[]),(59,[61])])
(2,[(87,[44,38]),(88,[87]),(2,[40,41]),(44,[47,43]),(38,[44]),(47,[50,46]),(43,[47]),(50,[53,49]),(46,[50]),(53,[56,52]),(49,[53]),(56,[59,55]),(52,[56]),(59,[62,58]),(55,[59]),(62,[65,61]),(58,[62]),(65,[68,64]),(61,[65]),(68,[71,67]),(64,[68]),(71,[74,70]),(67,[71]),(74,[77,73]),(70,[74]),(77,[80,76]),(73,[77]),(80,[83,79]),(76,[80]),(83,[89,82]),(79,[83]),(89,[84,85]),(82,[89]),(40,[]),(41,[87,88]),(84,[]),(85,[89])])
(19,[(89,[41,42]),(66,[43]),(43,[44,45]),(78,[46,47]),(72,[78]),(77,[52,50]),(52,[51]),(50,[52]),(51,[53]),(53,[90]),(81,[91]),(91,[56,57]),(90,[62,59]),(62,[60,61]),(59,[62]),(86,[63,64]),(83,[86]),(41,[66]),(42,[]),(19,[89,68]),(68,[]),(70,[69]),(44,[70]),(45,[78,72]),(74,[73]),(46,[74]),(47,[75,76]),(75,[77]),(76,[78]),(80,[79]),(56,[80]),(57,[81]),(60,[86,83]),(85,[84]),(63,[85]),(64,[86]),(79,[89]),(73,[89]),(69,[89]),(84,[90]),(61,[91])])
(0,[(0,[165,166]),(165,[]),(166,[331]),(331,[168,169]),(173,[170]),(168,[171,172]),(169,[173]),(177,[333]),(329,[177,176]),(176,[177]),(318,[178,179]),(343,[180,181]),(185,[182]),(180,[183,184]),(181,[185]),(198,[186,187]),(186,[188]),(187,[189]),(199,[190,191]),(190,[192]),(191,[193]),(337,[194,195]),(197,[337]),(194,[197]),(195,[198,199]),(336,[200,201]),(200,[202]),(201,[203]),(210,[336]),(342,[205,206]),(205,[207]),(206,[208]),(211,[342]),(183,[210,211]),(184,[]),(178,[343]),(352,[213,214]),(218,[215]),(213,[216,217]),(214,[218]),(231,[219,220]),(219,[221]),(220,[222]),(232,[223,224]),(223,[225]),(224,[226]),(346,[227,228]),(230,[346]),(227,[230]),(228,[231,232]),(345,[233,234]),(233,[235]),(234,[236]),(243,[345]),(351,[238,239]),(238,[240]),(239,[241]),(244,[351]),(216,[243,244]),(217,[]),(179,[352]),(319,[246,247]),(361,[248,249]),(253,[250]),(248,[251,252]),(249,[253]),(266,[254,255]),(254,[256]),(255,[257]),(267,[258,259]),(258,[260]),(259,[261]),(355,[262,263]),(265,[355]),(262,[265]),(263,[266,267]),(354,[268,269]),(268,[270]),(269,[271]),(278,[354]),(360,[273,274]),(273,[275]),(274,[276]),(279,[360]),(251,[278,279]),(252,[]),(246,[361]),(370,[281,282]),(286,[283]),(281,[284,285]),(282,[286]),(299,[287,288]),(287,[289]),(288,[290]),(300,[291,292]),(291,[293]),(292,[294]),(364,[295,296]),(298,[364]),(295,[298]),(296,[299,300]),(363,[301,302]),(301,[303]),(302,[304]),(311,[363]),(369,[306,307]),(306,[308]),(307,[309]),(312,[369]),(284,[311,312]),(285,[]),(247,[370]),(334,[314,315]),(317,[316]),(314,[317]),(315,[318,319]),(333,[320,321]),(320,[322]),(321,[334]),(332,[324,325]),(324,[326]),(325,[331]),(330,[332]),(171,[329,330]),(172,[]),(170,[331]),(326,[332]),(322,[333]),(316,[334]),(182,[343]),(202,[336]),(203,[337]),(188,[343]),(189,[343]),(192,[343]),(193,[343]),(207,[342]),(208,[343]),(215,[352]),(235,[345]),(236,[346]),(221,[352]),(222,[352]),(225,[352]),(226,[352]),(240,[351]),(241,[352]),(250,[361]),(270,[354]),(271,[355]),(256,[361]),(257,[361]),(260,[361]),(261,[361]),(275,[360]),(276,[361]),(283,[370]),(303,[363]),(304,[364]),(289,[370]),(290,[370]),(293,[370]),(294,[370]),(308,[369]),(309,[370])])
(13,[(70,[47,48]),(69,[49]),(49,[50,51]),(71,[52,53]),(72,[71]),(73,[55,56]),(74,[73]),(77,[101]),(101,[59,60]),(104,[61]),(61,[102]),(102,[63,64]),(78,[65]),(13,[66,67]),(66,[]),(67,[70]),(47,[69]),(48,[70]),(50,[]),(51,[71,72]),(52,[73,74]),(59,[75,76]),(60,[77]),(63,[]),(64,[78]),(80,[103]),(86,[80]),(82,[103]),(84,[82]),(92,[83]),(87,[84,92]),(75,[86,87]),(89,[103]),(94,[89]),(91,[103]),(93,[91]),(95,[92,93]),(76,[94,95]),(100,[96,97]),(96,[100]),(97,[101]),(55,[100]),(56,[101]),(53,[]),(65,[102]),(83,[103]),(103,[104])])
(9,[(47,[27,28]),(46,[29]),(29,[30,31]),(48,[32,33]),(49,[48]),(52,[35,36]),(54,[37,38]),(56,[39,40]),(58,[41,42]),(9,[43,44]),(43,[]),(44,[47]),(27,[46]),(28,[47]),(30,[]),(31,[48,49]),(57,[]),(32,[52]),(35,[54]),(36,[52]),(37,[56]),(38,[54]),(39,[58]),(40,[56]),(41,[57]),(42,[58]),(33,[])])
(32,[(395,[754]),(396,[395]),(652,[348,491]),(713,[350,351]),(406,[352]),(718,[353,354]),(430,[718]),(766,[356,357]),(767,[766]),(462,[722]),(463,[462]),(722,[361,362]),(471,[363]),(703,[364,730]),(772,[366,367]),(773,[772]),(542,[369,370]),(543,[542]),(546,[731]),(547,[546]),(731,[374,375]),(555,[376]),(397,[377]),(768,[378,379]),(770,[461]),(771,[770]),(461,[382,383]),(776,[384,385]),(777,[776]),(778,[545]),(779,[778]),(545,[389,390]),(32,[391,392]),(391,[]),(392,[393,805]),(393,[395,396]),(378,[]),(379,[397]),(715,[398,399]),(402,[400]),(403,[715]),(398,[402,403]),(350,[404,405]),(351,[406]),(404,[712]),(405,[408]),(712,[413,410]),(413,[411,412]),(410,[413]),(714,[414]),(418,[715]),(420,[418,417]),(417,[418]),(411,[714,420]),(424,[715]),(425,[424,423]),(423,[424]),(412,[425,426]),(457,[713]),(353,[428,429]),(354,[430]),(428,[716]),(429,[432]),(721,[768,434]),(436,[721]),(434,[436,437]),(716,[442,439]),(442,[440,441]),(439,[442]),(719,[443]),(447,[444]),(449,[447,446]),(446,[447]),(440,[719,449]),(453,[450]),(454,[453,452]),(452,[453]),(441,[454,455]),(458,[721]),(769,[457,458]),(356,[459]),(382,[710]),(383,[461]),(475,[462,463]),(468,[464]),(734,[465,466]),(465,[467]),(466,[468]),(361,[469,470]),(362,[471]),(469,[722]),(470,[734]),(476,[735]),(357,[475,476]),(488,[477,491]),(480,[488]),(477,[480,481]),(709,[482,483]),(487,[484]),(482,[485,486]),(483,[487]),(485,[488]),(503,[709]),(706,[490,491]),(493,[706]),(490,[493,494]),(705,[495,496]),(500,[705]),(495,[498,499]),(496,[500]),(498,[501]),(504,[706]),(348,[503,504]),(384,[]),(385,[776]),(511,[513,507]),(512,[511]),(513,[509,510]),(774,[511,512]),(507,[513]),(740,[514,515]),(514,[516]),(741,[517,518]),(520,[741]),(523,[520,521]),(524,[741]),(517,[523,524]),(527,[740]),(528,[741]),(509,[527,528]),(736,[529,530]),(529,[531]),(536,[737]),(737,[533,534]),(538,[736,536]),(539,[737]),(533,[538,539]),(510,[737]),(366,[544]),(367,[542,543]),(389,[544]),(390,[545]),(369,[546,547]),(552,[548]),(743,[549,550]),(549,[558]),(550,[552]),(374,[553,554]),(375,[555]),(553,[731]),(554,[743]),(370,[558]),(564,[566,560]),(565,[564]),(566,[562,563]),(364,[564,565]),(560,[566]),(578,[567,568]),(570,[578]),(567,[570,571]),(729,[572,573]),(577,[574]),(572,[575,576]),(573,[577]),(575,[578]),(562,[729]),(725,[580,581]),(583,[725]),(580,[583,584]),(724,[585,586]),(590,[724]),(585,[588,589]),(586,[590]),(588,[591]),(563,[725]),(754,[593,594]),(784,[595]),(609,[596]),(607,[597]),(765,[598,599]),(606,[604,601]),(604,[608,603]),(601,[604]),(608,[670]),(598,[606]),(599,[607]),(603,[608]),(785,[609,765]),(786,[762]),(805,[]),(638,[612,613]),(612,[614,615]),(618,[758]),(614,[638,618]),(615,[619]),(761,[758]),(788,[621,622]),(789,[788]),(757,[624,625]),(624,[626,627]),(629,[628]),(626,[629,630]),(627,[631]),(625,[632]),(621,[757,634]),(622,[635]),(782,[636,637]),(636,[638,761]),(637,[763]),(783,[641]),(643,[752]),(798,[643]),(780,[644]),(804,[]),(751,[645,764]),(645,[647]),(650,[751]),(651,[649]),(593,[650,651]),(594,[652]),(670,[653,654]),(697,[655,656]),(792,[662,658]),(793,[792]),(662,[660,661]),(658,[662]),(794,[663]),(673,[664]),(671,[669,666]),(669,[672,668]),(666,[669]),(672,[670]),(674,[671]),(668,[672]),(795,[673,674]),(796,[675]),(660,[676,677]),(688,[678,679]),(678,[680,681]),(684,[687]),(680,[688,684]),(681,[685]),(679,[748]),(689,[687]),(676,[688,689]),(677,[690]),(661,[748]),(693,[692]),(800,[693]),(790,[745]),(653,[697,696]),(696,[697]),(701,[698,699]),(698,[701]),(655,[701]),(656,[744]),(654,[703]),(494,[705]),(499,[705]),(501,[706]),(484,[709]),(486,[709]),(481,[709]),(459,[710]),(352,[713]),(414,[712]),(400,[713]),(426,[714]),(408,[715]),(443,[716]),(444,[721]),(437,[718]),(455,[719]),(450,[721]),(432,[721]),(363,[722]),(584,[724]),(589,[724]),(591,[725]),(807,[730]),(574,[729]),(576,[729]),(571,[729]),(806,[730]),(376,[731]),(377,[768]),(810,[768]),(464,[734]),(467,[735]),(530,[736]),(531,[737]),(809,[775]),(521,[740]),(515,[740]),(516,[741]),(808,[775]),(548,[743]),(699,[744]),(692,[745]),(690,[748]),(685,[748]),(675,[748]),(664,[754]),(663,[754]),(647,[751]),(644,[752]),(595,[754]),(596,[754]),(619,[762]),(613,[762]),(630,[757]),(628,[758]),(631,[762]),(632,[762]),(802,[761]),(635,[762]),(641,[763]),(649,[764]),(597,[765]),(491,[766,767]),(710,[768,769]),(735,[770,771]),(730,[772,773]),(544,[774,775]),(775,[776,777]),(558,[778,779]),(764,[780,781]),(752,[782,783]),(762,[784,785]),(758,[786,787]),(763,[788,789]),(744,[790,791]),(745,[792,793]),(748,[794,795]),(687,[796,797]),(781,[798,804]),(791,[800,801]),(634,[802]),(787,[805]),(801,[804]),(797,[805]),(568,[806]),(581,[807]),(518,[808]),(534,[809]),(399,[810])])
(21,[(117,[119]),(119,[86,87]),(118,[91,89]),(91,[179]),(89,[91]),(185,[97,93]),(191,[94]),(192,[131]),(97,[136]),(93,[97]),(136,[98,99]),(135,[138]),(138,[101,102]),(137,[140]),(140,[104,105]),(139,[142]),(142,[107,108]),(141,[144]),(144,[110,111]),(143,[146]),(146,[113,114]),(21,[115,116]),(115,[]),(116,[117]),(86,[118]),(87,[119]),(148,[120,121]),(147,[]),(94,[183]),(127,[123]),(184,[124,125]),(124,[126]),(125,[127]),(183,[184,129]),(131,[185]),(133,[131]),(134,[132]),(129,[133,134]),(98,[135]),(99,[136]),(101,[137]),(102,[138]),(104,[139]),(105,[140]),(107,[141]),(108,[142]),(110,[143]),(111,[144]),(113,[148]),(114,[146]),(120,[147]),(121,[148]),(156,[149,150]),(187,[176,152]),(149,[153]),(150,[172]),(176,[155]),(189,[156]),(153,[157]),(157,[165,159]),(165,[160,161]),(159,[165]),(160,[163,164]),(161,[165]),(170,[166,167]),(173,[170]),(166,[169]),(167,[170]),(172,[171]),(174,[172]),(163,[173,174]),(164,[187]),(152,[176]),(179,[177,178]),(180,[179]),(177,[180,182]),(178,[182]),(132,[183]),(123,[184]),(126,[185]),(171,[187]),(169,[187]),(155,[190]),(182,[189,190]),(190,[191,192])])
(16,[(84,[56,57]),(83,[58]),(58,[59,60]),(85,[61,62]),(86,[85]),(113,[64]),(114,[113]),(64,[66]),(66,[70,68]),(70,[93]),(68,[70]),(93,[71,72]),(92,[77,74]),(77,[75,98]),(74,[77]),(101,[78,79]),(16,[80,81]),(80,[]),(81,[84]),(56,[83]),(57,[84]),(59,[]),(60,[85,86]),(102,[107,88]),(103,[102]),(107,[90,91]),(71,[92]),(72,[93]),(78,[]),(79,[101]),(96,[99]),(75,[96]),(99,[97,98]),(100,[99]),(97,[100]),(98,[101]),(61,[102,103]),(88,[107]),(90,[129,106]),(91,[107]),(128,[112,109]),(112,[110,111]),(109,[112]),(110,[113,114]),(120,[124,116]),(121,[120]),(124,[118,119]),(111,[120,121]),(116,[124]),(118,[128]),(119,[124]),(129,[125,126]),(106,[129]),(125,[128]),(126,[129]),(62,[])])
(2,[(37,[28,29]),(34,[37]),(2,[31,32]),(31,[]),(32,[37,34]),(28,[35,36]),(29,[37]),(62,[38,39]),(43,[40]),(38,[41,42]),(39,[43]),(48,[44,45]),(44,[48]),(45,[47]),(50,[48]),(51,[49]),(41,[50,51]),(42,[]),(55,[52,56]),(52,[55]),(57,[55]),(58,[56]),(35,[57,58]),(36,[]),(40,[62]),(47,[62]),(49,[62]),(56,[62])])
(2,[(311,[314,308]),(312,[]),(2,[309,310]),(309,[]),(310,[311,312]),(314,[313]),(308,[314]),(313,[319,316]),(319,[317,318]),(316,[319]),(641,[320]),(320,[325,322]),(325,[323,324]),(322,[325]),(674,[326]),(328,[327]),(711,[]),(334,[328,329]),(335,[330]),(336,[331,332]),(331,[336]),(332,[334,335]),(675,[336]),(338,[339]),(349,[338]),(676,[339]),(346,[342,341]),(347,[342]),(348,[343,344]),(343,[348]),(344,[346,347]),(350,[348]),(364,[349,350]),(362,[351]),(353,[352]),(359,[353,354]),(360,[355]),(361,[356,357]),(356,[361]),(357,[359,360]),(363,[361]),(365,[362,363]),(323,[364,365]),(324,[]),(672,[641]),(647,[367]),(367,[372,369]),(372,[370,371]),(369,[372]),(677,[373]),(375,[374]),(381,[375,376]),(382,[377]),(383,[378,379]),(378,[383]),(379,[381,382]),(678,[383]),(385,[386]),(396,[385]),(679,[386]),(393,[389,388]),(394,[389]),(395,[390,391]),(390,[395]),(391,[393,394]),(397,[395]),(411,[396,397]),(409,[398]),(400,[399]),(406,[400,401]),(407,[402]),(408,[403,404]),(403,[408]),(404,[406,407]),(410,[408]),(412,[409,410]),(370,[411,412]),(371,[]),(414,[647]),(466,[414,415]),(653,[416]),(416,[421,418]),(421,[419,420]),(418,[421]),(680,[422]),(424,[423]),(430,[424,425]),(431,[426]),(432,[427,428]),(427,[432]),(428,[430,431]),(681,[432]),(434,[435]),(445,[434]),(682,[435]),(442,[438,437]),(443,[438]),(444,[439,440]),(439,[444]),(440,[442,443]),(446,[444]),(460,[445,446]),(458,[447]),(449,[448]),(455,[449,450]),(456,[451]),(457,[452,453]),(452,[457]),(453,[455,456]),(459,[457]),(461,[458,459]),(419,[460,461]),(420,[]),(467,[653]),(468,[463,464]),(463,[468]),(464,[466,467]),(673,[468]),(470,[471]),(481,[470]),(683,[471]),(478,[711,474]),(479,[474]),(480,[475,476]),(475,[480]),(476,[478,479]),(482,[480]),(634,[481,482]),(659,[483]),(483,[488,485]),(488,[486,487]),(485,[488]),(684,[489]),(491,[490]),(497,[491,492]),(498,[493]),(499,[494,495]),(494,[499]),(495,[497,498]),(685,[499]),(501,[502]),(512,[501]),(686,[502]),(509,[505,504]),(510,[505]),(511,[506,507]),(506,[511]),(507,[509,510]),(513,[511]),(527,[512,513]),(525,[514]),(516,[515]),(522,[516,517]),(523,[518]),(524,[519,520]),(519,[524]),(520,[522,523]),(526,[524]),(528,[525,526]),(486,[527,528]),(487,[]),(632,[659]),(665,[530]),(530,[535,532]),(535,[533,534]),(532,[535]),(687,[536]),(538,[537]),(544,[538,539]),(545,[540]),(546,[541,542]),(541,[546]),(542,[544,545]),(688,[546]),(548,[549]),(559,[548]),(689,[549]),(556,[552,551]),(557,[552]),(558,[553,554]),(553,[558]),(554,[556,557]),(560,[558]),(574,[559,560]),(572,[561]),(563,[562]),(569,[563,564]),(570,[565]),(571,[566,567]),(566,[571]),(567,[569,570]),(573,[571]),(575,[572,573]),(533,[574,575]),(534,[]),(578,[665]),(629,[711,578]),(671,[579]),(579,[584,581]),(584,[582,583]),(581,[584]),(690,[585]),(587,[586]),(593,[587,588]),(594,[589]),(595,[590,591]),(590,[595]),(591,[593,594]),(691,[595]),(597,[598]),(608,[597]),(692,[598]),(605,[601,600]),(606,[601]),(607,[602,603]),(602,[607]),(603,[605,606]),(609,[607]),(623,[608,609]),(621,[610]),(612,[611]),(618,[612,613]),(619,[614]),(620,[615,616]),(615,[620]),(616,[618,619]),(622,[620]),(624,[621,622]),(582,[623,624]),(583,[]),(630,[671]),(631,[626,627]),(626,[631]),(627,[629,630]),(633,[631]),(635,[632,633]),(317,[634,635]),(318,[]),(355,[641]),(352,[641]),(351,[641]),(330,[641]),(327,[641]),(326,[641]),(402,[647]),(399,[647]),(398,[647]),(377,[647]),(374,[647]),(373,[647]),(451,[653]),(448,[653]),(447,[653]),(426,[653]),(423,[653]),(422,[653]),(518,[659]),(515,[659]),(514,[659]),(493,[659]),(490,[659]),(489,[659]),(565,[665]),(562,[665]),(561,[665]),(540,[665]),(537,[665]),(536,[665]),(614,[671]),(611,[671]),(610,[671]),(589,[671]),(586,[671]),(585,[671]),(471,[672,673]),(339,[674,675]),(342,[676]),(386,[677,678]),(389,[679]),(435,[680,681]),(438,[682]),(474,[683]),(502,[684,685]),(505,[686]),(549,[687,688]),(552,[689]),(598,[690,691]),(601,[692]),(341,[711]),(329,[711]),(354,[711]),(415,[711]),(388,[711]),(376,[711]),(401,[711]),(437,[711]),(425,[711]),(450,[711]),(504,[711]),(492,[711]),(517,[711]),(551,[711]),(539,[711]),(564,[711]),(600,[711]),(588,[711]),(613,[711])])
(101,[(621,[299,287]),(622,[621]),(623,[289,290]),(624,[623]),(450,[292,293]),(458,[294,295]),(452,[458]),(299,[297,686]),(287,[299]),(459,[300,301]),(460,[459]),(461,[307,304]),(307,[467,306]),(304,[307]),(467,[308,309]),(306,[467]),(447,[311,685]),(448,[447]),(616,[314,315,316,317,318,319]),(444,[616]),(577,[321,322]),(574,[323,324]),(571,[325,326]),(625,[327,328]),(471,[329,330]),(472,[471]),(473,[332,333]),(474,[473]),(479,[335,336]),(476,[479]),(489,[338,339]),(486,[489]),(494,[341,342]),(491,[494]),(495,[344,345]),(496,[495]),(497,[347,685]),(498,[497]),(499,[350,351]),(500,[499]),(501,[353,354]),(502,[501]),(503,[356,357]),(504,[503]),(505,[359,360]),(506,[505]),(507,[362,363]),(508,[507]),(509,[365,366]),(510,[509]),(511,[368,369]),(512,[511]),(513,[371,372]),(514,[513]),(515,[374,375]),(516,[515]),(517,[377,378]),(518,[517]),(519,[380,381]),(520,[519]),(521,[383,384]),(522,[521]),(523,[386,387]),(524,[523]),(525,[389,390]),(526,[525]),(527,[392,393]),(528,[527]),(529,[395,396]),(530,[529]),(531,[398,399]),(532,[531]),(533,[401,402]),(534,[533]),(535,[404,405]),(536,[535]),(541,[407,408]),(538,[541]),(546,[410,411]),(543,[546]),(551,[413,414]),(548,[551]),(555,[416,654]),(556,[555]),(557,[419,420]),(558,[557]),(563,[422,654]),(560,[563]),(568,[425,654]),(565,[568]),(580,[428]),(619,[429,430]),(587,[431,652]),(588,[587]),(589,[434,435]),(590,[589]),(591,[437,652]),(592,[591]),(593,[620]),(620,[441,442]),(311,[616,444]),(101,[445,446]),(445,[]),(446,[447,448]),(449,[]),(289,[449]),(290,[450]),(292,[458,452]),(627,[]),(294,[453,454]),(453,[]),(454,[458]),(628,[456,457]),(456,[]),(457,[458]),(293,[]),(297,[459,460]),(300,[461]),(308,[462,463]),(462,[]),(463,[467]),(309,[465,466]),(465,[]),(466,[467]),(314,[577]),(321,[574]),(323,[571]),(327,[471,472]),(329,[473,474]),(633,[479,476]),(335,[477,478]),(477,[]),(478,[479]),(484,[480,685]),(631,[484,483]),(483,[484]),(480,[]),(637,[489,486]),(338,[487,488]),(487,[]),(488,[489]),(635,[494,491]),(341,[492,493]),(492,[]),(493,[494]),(643,[495,496]),(344,[497,498]),(347,[499,500]),(350,[501,502]),(353,[503,504]),(356,[505,506]),(359,[507,508]),(362,[509,510]),(365,[511,512]),(368,[513,514]),(371,[515,516]),(374,[517,518]),(377,[519,520]),(380,[521,522]),(383,[523,524]),(386,[525,526]),(389,[527,528]),(392,[529,530]),(395,[531,532]),(398,[533,534]),(401,[535,536]),(404,[541,538]),(407,[539,540]),(539,[]),(540,[541]),(645,[546,543]),(410,[544,545]),(544,[]),(545,[546]),(641,[551,548]),(413,[549,550]),(549,[]),(550,[551]),(328,[552,553]),(552,[]),(553,[625]),(325,[555,556]),(416,[557,558]),(419,[563,560]),(422,[561,562]),(561,[]),(562,[563]),(647,[568,565]),(425,[566,567]),(566,[]),(567,[568]),(326,[569,570]),(569,[]),(570,[571]),(324,[572,573]),(572,[]),(573,[574]),(322,[575,576]),(575,[]),(576,[577]),(626,[619,579]),(429,[]),(430,[580]),(583,[619,582]),(579,[583]),(586,[619,585]),(582,[586]),(315,[587,588]),(431,[589,590]),(434,[591,592]),(441,[]),(442,[593]),(608,[598,595]),(598,[596,597]),(595,[598]),(603,[599,600]),(596,[603,602]),(602,[603]),(599,[608]),(609,[605,606]),(610,[609]),(605,[608]),(437,[609,610]),(316,[611,612]),(611,[]),(612,[616]),(317,[614,617]),(614,[]),(617,[616]),(318,[617,618]),(618,[]),(428,[619]),(597,[620]),(685,[621,622]),(686,[623,624]),(654,[625]),(652,[626]),(295,[627,628]),(332,[629,630]),(629,[631,632]),(632,[633,634]),(630,[635,636]),(636,[637,638]),(333,[639,640]),(639,[641,642]),(642,[643,644]),(384,[645,646]),(420,[647,648]),(319,[685]),(435,[652]),(606,[652]),(600,[652]),(585,[685]),(648,[654]),(330,[685]),(634,[685]),(336,[685]),(638,[685]),(339,[685]),(342,[685]),(640,[685]),(644,[685]),(345,[685]),(351,[685]),(354,[685]),(357,[685]),(360,[685]),(363,[685]),(366,[685]),(369,[685]),(372,[685]),(375,[685]),(378,[685]),(381,[685]),(646,[685]),(411,[685]),(387,[685]),(390,[685]),(393,[685]),(396,[685]),(399,[685]),(402,[685]),(405,[685]),(408,[685]),(414,[685]),(301,[686])])
(23,[(581,[269,270]),(582,[581]),(315,[272,273]),(316,[315]),(317,[275,276]),(318,[317]),(323,[278,279]),(320,[323]),(328,[281,282]),(325,[328]),(449,[284,285,286,287,288,289,290]),(450,[449]),(477,[292,293]),(478,[477]),(483,[295,296]),(480,[483]),(553,[298,299]),(554,[553]),(559,[301,302]),(556,[559]),(311,[304,575]),(312,[311]),(304,[573,308]),(23,[309,310]),(309,[]),(310,[311,312]),(579,[313,567]),(585,[315,316]),(587,[317,318]),(591,[323,320]),(278,[]),(279,[321,322]),(321,[]),(322,[323]),(592,[328,325]),(281,[]),(282,[326,327]),(326,[]),(327,[328]),(275,[]),(333,[329,330]),(588,[333,332]),(332,[333]),(597,[]),(344,[334,335]),(598,[344,337]),(337,[344]),(599,[]),(334,[339,340]),(339,[]),(340,[344]),(600,[342,343]),(342,[]),(343,[344]),(329,[]),(349,[345,346]),(589,[349,348]),(348,[349]),(601,[]),(357,[350,351]),(602,[357,353]),(353,[357]),(350,[]),(351,[355,356]),(355,[]),(356,[357]),(345,[]),(425,[358,613]),(583,[360,416]),(584,[362,363]),(368,[364,365]),(362,[368,367]),(367,[368]),(373,[369,370]),(364,[373,372]),(372,[373]),(369,[]),(370,[]),(378,[374,375]),(365,[378,377]),(377,[378]),(383,[379,380]),(374,[383,382]),(382,[383]),(379,[]),(380,[]),(388,[384,385]),(375,[388,387]),(387,[388]),(393,[389,390]),(384,[393,392]),(392,[393]),(603,[]),(401,[394,395]),(604,[401,397]),(397,[401]),(394,[]),(395,[399,400]),(399,[]),(400,[401]),(389,[]),(406,[402,403]),(385,[406,405]),(405,[406]),(402,[]),(403,[]),(363,[407,408]),(407,[]),(408,[584]),(414,[410,416]),(360,[414,413]),(413,[414]),(422,[415,416]),(410,[422,418]),(418,[422]),(415,[420,421]),(420,[]),(421,[422]),(590,[425,424]),(424,[425]),(430,[426,427]),(358,[430,429]),(429,[430]),(435,[431,613]),(426,[435,434]),(434,[435]),(440,[436,613]),(431,[440,439]),(439,[440]),(448,[441,613]),(436,[448,444]),(444,[448]),(441,[446,447]),(446,[]),(447,[448]),(586,[449,450]),(455,[451,452]),(284,[455,454]),(454,[455]),(451,[]),(452,[]),(460,[456,457]),(285,[460,459]),(459,[460]),(468,[461,462]),(605,[468,464]),(464,[468]),(461,[]),(462,[466,467]),(466,[]),(467,[468]),(476,[469,470]),(606,[476,472]),(472,[476]),(469,[]),(470,[474,475]),(474,[]),(475,[476]),(456,[]),(286,[477,478]),(593,[]),(594,[483,480]),(295,[]),(296,[481,482]),(481,[]),(482,[483]),(292,[]),(488,[484,485]),(287,[488,487]),(487,[488]),(607,[]),(496,[489,490]),(608,[496,492]),(492,[496]),(489,[]),(490,[494,495]),(494,[]),(495,[496]),(484,[]),(501,[497,498]),(288,[501,500]),(500,[501]),(609,[]),(509,[502,503]),(610,[509,505]),(505,[509]),(502,[]),(503,[507,508]),(507,[]),(508,[509]),(497,[]),(514,[510,511]),(289,[514,513]),(513,[514]),(519,[515,516]),(510,[519,518]),(518,[519]),(515,[]),(516,[]),(524,[520,521]),(511,[524,523]),(523,[524]),(529,[525,526]),(520,[529,528]),(528,[529]),(525,[]),(526,[]),(534,[530,531]),(521,[534,533]),(533,[534]),(539,[535,536]),(530,[539,538]),(538,[539]),(535,[]),(536,[]),(544,[540,541]),(531,[544,543]),(543,[544]),(611,[]),(552,[545,546]),(612,[552,548]),(548,[552]),(545,[]),(546,[550,551]),(550,[]),(551,[552]),(540,[]),(290,[553,554]),(595,[]),(596,[559,556]),(301,[]),(302,[557,558]),(557,[]),(558,[559]),(298,[]),(269,[]),(580,[579]),(565,[561,567]),(313,[565,564]),(564,[565]),(570,[566,567]),(561,[570,569]),(569,[570]),(566,[]),(573,[571,575]),(308,[573]),(578,[574,575]),(571,[578,577]),(577,[578]),(574,[]),(575,[579,580]),(567,[581,582]),(613,[583]),(416,[584]),(270,[585,586]),(272,[587,588]),(273,[589,590]),(276,[591,592]),(293,[593,594]),(299,[595,596]),(330,[597,598]),(335,[599,600]),(346,[601,602]),(390,[603,604]),(457,[605,606]),(485,[607,608]),(498,[609,610]),(541,[611,612]),(427,[613])])
(9,[(134,[73,70]),(73,[71,72]),(70,[73]),(129,[74,75]),(137,[76,77]),(138,[78,79]),(135,[80,81]),(139,[82,83]),(140,[84,85]),(9,[134,87]),(87,[]),(123,[]),(89,[]),(76,[123,89]),(92,[90,91]),(77,[92]),(143,[]),(97,[93,94]),(90,[97,96]),(96,[97]),(93,[]),(94,[]),(147,[]),(99,[]),(78,[123,99]),(102,[100,101]),(79,[102]),(146,[]),(107,[103,104]),(100,[107,106]),(106,[107]),(103,[]),(104,[]),(109,[]),(80,[123,109]),(112,[110,111]),(81,[112]),(148,[]),(117,[113,114]),(110,[117,116]),(116,[117]),(113,[]),(114,[]),(119,[]),(82,[123,119]),(122,[120,121]),(83,[122]),(149,[]),(120,[]),(150,[]),(124,[]),(84,[123,124]),(85,[129]),(141,[]),(74,[126,130]),(126,[128]),(130,[129]),(142,[130,131]),(131,[132]),(132,[134]),(128,[134]),(71,[135,136]),(136,[137,138]),(72,[139,140]),(75,[141,142]),(91,[143,147]),(101,[147,146]),(111,[147,148]),(121,[149,150])])
(12,[(173,[144,145,146,147,148,149,150,151,152,153]),(174,[173]),(144,[]),(145,[]),(146,[195,156]),(147,[216,158]),(148,[237,160]),(149,[258,162]),(150,[279,164]),(151,[300,166]),(152,[321,168]),(153,[342,170]),(12,[171,172]),(171,[]),(172,[173,174]),(192,[179,176]),(179,[324,178]),(176,[179]),(324,[]),(188,[180,181]),(178,[188,183]),(183,[188]),(180,[192]),(181,[186,187]),(186,[]),(187,[188]),(195,[189,190]),(156,[195]),(189,[192]),(190,[193,194]),(193,[]),(194,[195]),(213,[200,197]),(200,[324,199]),(197,[200]),(209,[201,202]),(199,[209,204]),(204,[209]),(201,[213]),(202,[207,208]),(207,[]),(208,[209]),(216,[210,211]),(158,[216]),(210,[213]),(211,[214,215]),(214,[]),(215,[216]),(234,[221,218]),(221,[324,220]),(218,[221]),(230,[222,223]),(220,[230,225]),(225,[230]),(222,[234]),(223,[228,229]),(228,[]),(229,[230]),(237,[231,232]),(160,[237]),(231,[234]),(232,[235,236]),(235,[]),(236,[237]),(255,[242,239]),(242,[324,241]),(239,[242]),(251,[243,244]),(241,[251,246]),(246,[251]),(243,[255]),(244,[249,250]),(249,[]),(250,[251]),(258,[252,253]),(162,[258]),(252,[255]),(253,[256,257]),(256,[]),(257,[258]),(276,[263,260]),(263,[324,262]),(260,[263]),(272,[264,265]),(262,[272,267]),(267,[272]),(264,[276]),(265,[270,271]),(270,[]),(271,[272]),(279,[273,274]),(164,[279]),(273,[276]),(274,[277,278]),(277,[]),(278,[279]),(297,[284,281]),(284,[324,283]),(281,[284]),(293,[285,286]),(283,[293,288]),(288,[293]),(285,[297]),(286,[291,292]),(291,[]),(292,[293]),(300,[294,295]),(166,[300]),(294,[297]),(295,[298,299]),(298,[]),(299,[300]),(318,[305,302]),(305,[324,304]),(302,[305]),(314,[306,307]),(304,[314,309]),(309,[314]),(306,[318]),(307,[312,313]),(312,[]),(313,[314]),(321,[315,316]),(168,[321]),(315,[318]),(316,[319,320]),(319,[]),(320,[321]),(339,[326,323]),(326,[324,325]),(323,[326]),(335,[327,328]),(325,[335,330]),(330,[335]),(327,[339]),(328,[333,334]),(333,[]),(334,[335]),(342,[336,337]),(170,[342]),(336,[339]),(337,[340,341]),(340,[]),(341,[342])])
(12,[(70,[37,38,39,40,41,42,43,44,45,46]),(71,[70]),(37,[74,49]),(38,[77,51]),(39,[80,53]),(40,[83,55]),(41,[86,57]),(42,[89,59]),(43,[92,61]),(44,[95,63]),(45,[98,65]),(46,[101,67]),(12,[68,69]),(68,[]),(69,[70,71]),(74,[99,100]),(49,[74]),(99,[]),(100,[]),(77,[99,100]),(51,[77]),(80,[99,100]),(53,[80]),(83,[99,100]),(55,[83]),(86,[99,100]),(57,[86]),(89,[99,100]),(59,[89]),(92,[99,100]),(61,[92]),(95,[99,100]),(63,[95]),(98,[99,100]),(65,[98]),(101,[99,100]),(67,[101])])
\ No newline at end of file