\chapter{Key Types}

\section{Alphabetically}

\subsection{A}

\begin{code}
type Assertion = (Term, SideCond)                                    --VarData
\end{code}

\begin{code}
data AtmSideCond                                                    --SideCond
 = SD  GenVar VarSet -- Disjoint
 | SS  GenVar VarSet -- Superset (covers)
 | SP  GenVar        -- Pre
pattern Disjoint gv vs = SD  gv vs  --  vs `intersect`  gv = {}
pattern Covers   gv vs = SS  gv vs  --  vs `supersetof` gv
pattern IsPre    gv    = SP  gv     --  gv is pre-condition
\end{code}

\subsection{B}

\begin{code}
type BVS = Set GenVar
\end{code}

\subsection{C}

\begin{code}
type CalcStep                                                         --Proofs
  = ( Justification  -- step justification
    , Assertion )         -- previous term
\end{code}

\begin{code}
type Calculation                                                      --Proofs
  = ( Term -- end (or current) term
    , [ CalcStep ] )  -- calculation steps, in proof order
\end{code}

\begin{code}
type Candidate = Term
\end{code}

\begin{code}
type CBVS = BVS
\end{code}

\newpage
\subsection{E}

\begin{code}
pattern EVal t k           =  K (E t) k                                  --AST
pattern EVar t v          <-  V (E t) v
pattern ECons t n ts       =  C (E t) n ts
pattern EBind t n vs tm   <-  B (E t) n vs tm
pattern ELam t n vl tm    <-  L (E t) n vl tm
pattern ESub t tm s        =  S (E t) tm s
pattern EIter t na ni lvs  =  I (E t) na ni lvs
pattern E2 t n t1 t2       =  C (E t) n [t1,t2]                          --AST
\end{code}

\subsection{G}

\begin{code}
data GenVar                                                        --Variables
 = GV Variable -- regular variable
 | GL ListVar  -- variable denoting a list of variables
pattern StdVar v = GV v
pattern LstVar lv = GL lv
type VarList = [GenVar]
type VarSet = Set GenVar
\end{code}

\begin{code}
data GroupSpec                                                          --Laws
  = Assoc LeftRight
  | Gather LeftRight Int
  | Split Int
\end{code}

\subsection{H}

\begin{code}
data HowUsed                                                          --Proofs
  = ByMatch MatchClass  -- replace focus with binding(match)
  | ByInstantiation     -- replace focus=true with binding(law)
\end{code}

\subsection{I}

\begin{code}
data Identifier = Id String Int                                    -- LexBase
pattern Identifier nm u <- Id nm u
\end{code}

\newpage
\subsection{J}

\begin{code}
data Justification                                                    --Proofs
  = UseLaw             -- used a law
      HowUsed              -- how law was used in proof step
      String               -- law name
      Binding              -- binding from law variables to goal components
      [Int]                -- zipper descent arguments
  | Substitute         -- performed a substitution
      [Int]                -- zipper descent arguments
  | NormQuant          -- performed a quantifier normalisation
      [Int]                -- zipper descent arguments
  | NestSimp           -- simplified nested quantifiers
      [Int]                -- zipper descent arguments
  | Switch             -- switched focus at sequent level
      SeqFocus             -- focus before switch -- needed to reverse this.
      SeqFocus             -- focus after switch
  | CloneH Int         --  Cloned hypothesis i
  | Flatten Identifier -- flattened use of associative operator
  | Associate          -- grouped use of an associative operator
      Identifier           -- operator
      GroupSpec            -- grouping details.
\end{code}

\subsection{L}

\begin{code}
type Law = (NmdAssertion,Provenance)                                    --Laws
\end{code}

\begin{code}
data Laws'                                                          --Sequents
  = CLaws' { -- currently focussed on conjecture component
      hyp0  :: Theory -- hypothesis theory
    , whichC :: LeftRight -- which term is in the focus
    , otherC :: Term  -- the term not in the focus
    }
  | HLaws' { -- currently focussed on hypothesis component
      hname     :: String -- hyp. theory name
    , hknown    :: VarTable
    , hbefore   :: [Law] -- hyp. laws before focus (reversed)
    , fhName    :: String -- focus hypothesis name
    , fhSC      :: SideCond -- focus hypothesis sc (usually true)
    , fhProv    :: Provenance -- focus hypothesis provenance (?)
    , hOriginal :: Term -- the original form of the focus hypothesis
    , hafter    :: [Law] -- hyp. laws after focus
    , cleft0    :: Term -- left conjecture
    , cright0   :: Term -- right conjecture
    }
\end{code}

\begin{code}
data LeftRight = Lft | Rght                                             --Laws
\end{code}

\begin{code}
data LogicSig                                                           --Laws
  = LogicSig
     { theTrue  :: Term
     , theFalse :: Term
     , theEqv   :: Identifier
     , theImp   :: Identifier
     , theAnd   :: Identifier
     , theOr    :: Identifier
     }
\end{code}

\begin{code}
data LstVarBind                                                      --Binding
 = BL  VarList
 | BS  VarSet
 | BX  [LVarOrTerm]
pattern BindList vl      =  BL vl
pattern BindSet  vs      =  BS vs
pattern BindTLVs tlvs    =  BX tlvs
\end{code}

\begin{code}
type ListVarBinding = M.Map ListVarKey LstVarBind
\end{code}

\begin{code}
type ListVarKey = (Identifier,VarClass,[Identifier],[Identifier])
\end{code}

\begin{code}
data LiveProof                                                    --LiveProofs
  = LP {
      conjThName :: String -- conjecture theory name
    , conjName :: String -- conjecture name
    , conjecture :: Assertion -- assertion being proven
    , conjSC :: SideCond -- side condition
    , strategy :: String -- strategy
    , mtchCtxts :: [MatchContext] -- current matching contexts
    , focus :: SeqZip  -- current sub-term of interest
    , fPath :: [Int] -- current term zipper descent arguments
    , matches :: Matches -- current matches
    , stepsSoFar :: [CalcStep]  -- calculation steps so far, most recent first
    }
\end{code}

\begin{code}
type LiveProofs = Map (String,String) LiveProof                   --LiveProofs
\end{code}

\begin{code}
data LstVarMatchRole -- ListVar Matching Roles                       --VarData
 = KL VarList        -- Known Variable-List, all of which are themselves known
      [Variable]     -- full expansion
      Int            -- length of full expansion
 | KS VarSet         -- Known Variable-Set, all of which are themselves known
      (Set Variable) -- full expansion
      Int            -- size of full expansion
 | AL                -- Abstract Known Variable-List
 | AS                -- Abstract Known Variable-Set
 | UL                -- Unknown List-Variable
pattern KnownVarList vl vars len  =  KL vl vars len
pattern KnownVarSet  vs vars siz  =  KS vs vars siz
pattern AbstractList              =  AL
pattern AbstractSet               =  AS
pattern UnknownListVar            =  UL
\end{code}

\begin{code}
type LVarSub = Set (ListVar,ListVar) -- target/replacement              --AST
\end{code}

\subsection{M}

\begin{code}                                                      --LiveProofs
data Match
 = MT { mName  ::  String     -- assertion name
      , mAsn   ::  Assertion  -- matched assertion
      , mClass ::  MatchClass -- match class
      , mBind  ::  Binding    -- resulting binding
      , mLocSC ::  SideCond   -- goal side-condition local update
      , mLawSC ::  SideCond   -- law side-condition mapped to goal
      , mRepl  ::  Term       -- replacement term
      }
\end{code}

\begin{code}
data MatchClass                                                       --Proofs
  = MA       -- match all of law, with replacement 'true'
  | ME [Int] -- match subpart of 'equiv' chain
  | MIA      -- match implication antecedent A, replacement A /\ C
  | MIC      -- match implication consequent C, replacement A \/ C
  -- MEV should be last, so these matches rank low by default
  | MEV Int  -- match PredVar at given position
pattern MatchAll       = MA
pattern MatchEqv is    = ME is
pattern MatchAnte      = MIA
pattern MatchCnsq      = MIC
pattern MatchEqvVar i  = MEV i
\end{code}

\begin{code}
type MatchContext                                                 --LiveProofs
  = ( String       -- Theory Name
    , [Law]        -- all laws of this theory
    , [VarTable] ) -- all known variables here, and in dependencies
\end{code}

\subsection{N}

\begin{code}
type NmdAssertion = (String,Assertion)                                  --Laws
\end{code}

\subsection{P}

\begin{code}
type Pattern = Term                                                 --Matching
\end{code}

\begin{code}
type PBVS = BVS
\end{code}

\begin{code}
type Proof                                                            --Proofs
  = ( String -- assertion name
    , Assertion
    , String -- Strategy
    , Calculation -- Simple calculational proofs for now
    )
\end{code}

\begin{code}
data Provenance                                                         --Laws
  = Axiom          --  considered as `self-evidently` True
  | Proven String  --  demonstrated by (named) proof
  | Assumed        --  conjecture asserted w/o proof
\end{code}

\begin{code}
pattern PVal k             =  K P k                                      --AST
pattern PVar v            <-  V P v
pattern PCons n ts         =  C P n ts
pattern PBind n vs tm     <-  B P n vs tm
pattern PLam n vl tm      <-  L P n vl tm
pattern PSub tm s          =  S P tm s
pattern PIter na ni lvs    =  I P na ni lvs
pattern P2   n t1 t2       =  C P n [t1,t2]
\end{code}

\subsection{S}

\begin{code}
data SeqFocus = CLeft | CRight | Hyp Int                              --Proofs
\end{code}

\begin{code}
data Sequent                                                        --Sequents
  = Sequent {
     ante :: [Theory] -- antecedent theory context
   , hyp :: Theory -- the goal hypotheses -- we can "go" here
   , sc :: SideCond -- of the conjecture being proven.
   , cleft :: Term -- never 'true' to begin with.
   , cright :: Term -- often 'true' from the start.
   }
\end{code}

\begin{code}
data Sequent'                                                       --Sequents
  = Sequent' {
      ante0 :: [Theory] -- context theories
    , sc0       :: SideCond -- sequent side-condition
    , laws'     :: Laws'
    }
\end{code}

\begin{code}
type SeqZip = (TermZip, Sequent')                                   --Sequents
\end{code}

\begin{code}
type SideCond = ( [AtmSideCond]  -- all must be true                 --VarData
                , VarSet )       -- must be fresh
\end{code}

\begin{code}
type Subscript = String                                            --Variables
\end{code}

\begin{code}
data Substn --  pair-sets below are unique in fst part                  --AST
  = SN TermSub LVarSub
\end{code}

\subsection{T}

\begin{code}
data Term                                                                --AST
 = K TermKind Value                    -- Value
 | V TermKind Variable                 -- Variable
 | C TermKind Identifier [Term]        -- Constructor
 | B TermKind Identifier VarSet Term   -- Binder (unordered)
 | L TermKind Identifier VarList Term  -- Binder (ordered)
 | X Identifier Term                   -- Closure (always a predicate)
 | S TermKind Term Substn              -- Substitution
 | I TermKind                          -- Iterator
     Identifier  -- top grouping constructor
     Identifier  -- component constructor, with arity a
     [ListVar]   -- list-variables, same length as component arity
 | ET Type                              -- Embedded TypeVar
pattern Val  tk k          =   K tk k
pattern Var  tk v          <-  V tk v
pattern Cons tk n ts       =   C tk n ts
pattern Bnd  tk n vs tm    <-  B tk n vs tm
pattern Lam  tk n vl tm    <-  L tk n vl tm
pattern Cls     n    tm    =   X n tm
pattern Sub  tk tm s       =   S tk tm s
pattern Iter tk na ni lvs  =   I tk na ni lvs
pattern Typ  typ           =   ET typ
\end{code}

\newpage
\begin{code}
data Term'                                                        --TermZipper
  = Cons'   TermKind Identifier [Term] -- terms before focus, reversed
                                [Term] -- terms after focus
  | Bnd'   TermKind Identifier VarSet
  | Lam'    TermKind Identifier VarList
  | Cls'             Identifier
  | Sub'    TermKind Substn
  | Substn' TermKind Term LVarSub TermSubL  -- subst-pairs before, reversed
                                  Variable -- focus target variable
                                  TermSubL  -- subst-pairs after focus
\end{code}

\begin{code}
data TermKind                                                            --AST
 = P -- predicate
 | E Type -- expression (with type annotation)
\end{code}

\begin{code}
type TermSub = Set (Variable,Term) -- target/replacememt                --AST
\end{code}

\begin{code}
type TermSubL = [(Variable, Term)]                              --TermZipper
\end{code}

\begin{code}
type TermZip = (Term,[Term'])                                    --TermZipper
\end{code}

\begin{code}
data Theories
  = Theories { tmap :: TheoryMap
             , sdag :: SDAG String }
\end{code}

\begin{code}
data Theory                                                         --Theories
  = Theory {
      thName   :: String
    , thDeps   :: [String]
    , known    :: VarTable
    , subable  :: SubAbilityMap
    , laws     :: [Law]
    , proofs   :: [Proof]
    , conjs    :: [NmdAssertion]
    }
\end{code}

\begin{code}
type TheoryMap = Map String Theory                                  --Theories
\end{code}

\begin{code}
data Token                                                         -- LexBase
 = TA String
 | TI Identifier
pattern ArbTok s = TA s
pattern IdTok i = TI i
\end{code}

\begin{code}
type Txt = String                                                        --AST
\end{code}

\begin{code}
data Type -- most general types first                                   --AST
 = T  -- arbitrary type
 | TV Identifier -- type variable
 | TC Identifier [Type] -- type constructor, applied
 | TA Identifier [(Identifier,[Type])] -- algebraic data type
 | TF Type Type -- function type
 | TG Identifier -- given type
pattern ArbType = T
pattern TypeVar i  = TV i
pattern TypeApp i ts = TC i ts
pattern DataType i fs = TA i fs
pattern FunType tf ta = TF tf ta
pattern GivenType i = TG i
\end{code}

\subsection{V}

\begin{code}
data Value                                                               --AST
 = VB Bool
 | VI Integer
 | VT Txt
pattern Boolean b  =  VB b
pattern Integer i  =  VI i
pattern Txt     t  =  VT t
\end{code}

\begin{code}
data VarBind = BI Identifier | BV Variable | BT Term                 --Binding
pattern BindVar  v  =  BV v
pattern BindTerm t  =  BT t
\end{code}

\begin{code}
type VarBinding = M.Map (Identifier,VarClass) VarBind                --Binding
\end{code}

\begin{code}
data VarClass                                                     --Variables
  = VO -- Observation
  | VE -- Expression
  | VP -- Predicate
pattern ObsV  = VO
pattern ExprV = VE
pattern PredV = VP
\end{code}

\begin{code}
newtype Variable  = VR (Identifier, VarClass, VarWhen)            --Variables
\end{code}

\begin{code}
data VarMatchRole -- Variable Matching Role                          --VarData
  =  KC Term     -- Known Constant
  |  KV Type     -- Known Variable
  |  KG          -- Generic Variable
  |  KI Variable -- Instance Variable ! variable must be known as generic
  |  UV          -- Unknown Variable
pattern KnownConst trm = KC trm
pattern KnownVar typ   = KV typ
pattern GenericVar     = KG
pattern InstanceVar v  = KI v
pattern UnknownVar     = UV
\end{code}

\begin{code}
data VarWhen -- Variable role                                      --Variables
  = WS            --  Static
  | WB            --  Before (pre)
  | WD Subscript  --  During (intermediate)
  | WA            --  After (post)
  | WT            --  Textual
pattern Static    =  WS
pattern Before    =  WB
pattern During n  =  WD n
pattern After     =  WA
pattern Textual   =  WT
\end{code}

% ==========================================================================
\section{By Module}

\subsection{LexBase}

\begin{code}
data Identifier = Id String Int                                    -- LexBase
pattern Identifier nm u <- Id nm u
\end{code}

\begin{code}
data Token                                                         -- LexBase
 = TA String
 | TI Identifier
pattern ArbTok s = TA s
pattern IdTok i = TI i
\end{code}

\subsection{Variables}

\begin{code}
data VarClass                                                     --Variables
  = VO -- Observation
  | VE -- Expression
  | VP -- Predicate
pattern ObsV  = VO
pattern ExprV = VE
pattern PredV = VP
\end{code}

\begin{code}
type Subscript = String                                           --Variables
\end{code}

\begin{code}
data VarWhen -- Variable role                                     --Variables
  = WS            --  Static
  | WB            --  Before (pre)
  | WD Subscript  --  During (intermediate)
  | WA            --  After (post)
  | WT            --  Textual
pattern Static    =  WS
pattern Before    =  WB
pattern During n  =  WD n
pattern After     =  WA
pattern Textual   =  WT
\end{code}

\begin{code}
newtype Variable  = VR (Identifier, VarClass, VarWhen)            --Variables
\end{code}

\begin{code}
data GenVar                                                        --Variables
 = GV Variable -- regular variable
 | GL ListVar  -- variable denoting a list of variables
pattern StdVar v = GV v
pattern LstVar lv = GL lv
type VarList = [GenVar]
type VarSet = Set GenVar
\end{code}

\subsection{AST}

\begin{code}
type TermSub = Set (Variable,Term) -- target/replacememt                --AST
type LVarSub = Set (ListVar,ListVar) -- target/replacement
data Substn --  pair-sets below are unique in fst part
  = SN TermSub LVarSub
\end{code}

\newpage
\begin{code}
data Type -- most general types first                                   --AST
 = T  -- arbitrary type
 | TV Identifier -- type variable
 | TC Identifier [Type] -- type constructor, applied
 | TA Identifier [(Identifier,[Type])] -- algebraic data type
 | TF Type Type -- function type
 | TG Identifier -- given type
pattern ArbType = T
pattern TypeVar i  = TV i
pattern TypeApp i ts = TC i ts
pattern DataType i fs = TA i fs
pattern FunType tf ta = TF tf ta
pattern GivenType i = TG i
\end{code}

\begin{code}
type Txt = String                                                        --AST
data Value
 = VB Bool
 | VI Integer
 | VT Txt
pattern Boolean b  =  VB b
pattern Integer i  =  VI i
pattern Txt     t  =  VT t
\end{code}

\begin{code}
data TermKind                                                            --AST
 = P -- predicate
 | E Type -- expression (with type annotation)
\end{code}

\begin{code}
data Term                                                                --AST
 = K TermKind Value                    -- Value
 | V TermKind Variable                 -- Variable
 | C TermKind Identifier [Term]        -- Constructor
 | B TermKind Identifier VarSet Term   -- Binder (unordered)
 | L TermKind Identifier VarList Term  -- Binder (ordered)
 | X Identifier Term                   -- Closure (always a predicate)
 | S TermKind Term Substn              -- Substitution
 | I TermKind                          -- Iterator
     Identifier  -- top grouping constructor
     Identifier  -- component constructor, with arity a
     [ListVar]   -- list-variables, same length as component arity
 | ET Type                              -- Embedded TypeVar
pattern Val  tk k          =   K tk k
pattern Var  tk v          <-  V tk v
pattern Cons tk n ts       =   C tk n ts
pattern Bnd  tk n vs tm    <-  B tk n vs tm
pattern Lam  tk n vl tm    <-  L tk n vl tm
pattern Cls     n    tm    =   X n tm
pattern Sub  tk tm s       =   S tk tm s
pattern Iter tk na ni lvs  =   I tk na ni lvs
pattern Typ  typ           =   ET typ
\end{code}

\begin{code}
pattern EVal t k           =  K (E t) k                                  --AST
pattern EVar t v          <-  V (E t) v
pattern ECons t n ts       =  C (E t) n ts
pattern EBind t n vs tm   <-  B (E t) n vs tm
pattern ELam t n vl tm    <-  L (E t) n vl tm
pattern ESub t tm s        =  S (E t) tm s
pattern EIter t na ni lvs  =  I (E t) na ni lvs
\end{code}

\newpage
\begin{code}
pattern PVal k             =  K P k                                      --AST
pattern PVar v            <-  V P v
pattern PCons n ts         =  C P n ts
pattern PBind n vs tm     <-  B P n vs tm
pattern PLam n vl tm      <-  L P n vl tm
pattern PSub tm s          =  S P tm s
pattern PIter na ni lvs    =  I P na ni lvs
\end{code}

\begin{code}
pattern E2 t n t1 t2  = C (E t) n [t1,t2]                                --AST
pattern P2   n t1 t2  = C P     n [t1,t2]
\end{code}

\subsection{VarData}

\begin{code}
data VarMatchRole -- Variable Matching Role                          --VarData
  =  KC Term     -- Known Constant
  |  KV Type     -- Known Variable
  |  KG          -- Generic Variable
  |  KI Variable -- Instance Variable ! variable must be known as generic
  |  UV          -- Unknown Variable
pattern KnownConst trm = KC trm
pattern KnownVar typ   = KV typ
pattern GenericVar     = KG
pattern InstanceVar v  = KI v
pattern UnknownVar     = UV
\end{code}

\begin{code}
data LstVarMatchRole -- ListVar Matching Roles                       --VarData
 = KL VarList        -- Known Variable-List, all of which are themselves known
      [Variable]     -- full expansion
      Int            -- length of full expansion
 | KS VarSet         -- Known Variable-Set, all of which are themselves known
      (Set Variable) -- full expansion
      Int            -- size of full expansion
 | AL                -- Abstract Known Variable-List
 | AS                -- Abstract Known Variable-Set
 | UL                -- Unknown List-Variable
pattern KnownVarList vl vars len  =  KL vl vars len
pattern KnownVarSet  vs vars siz  =  KS vs vars siz
pattern AbstractList              =  AL
pattern AbstractSet               =  AS
pattern UnknownListVar            =  UL
\end{code}

\subsection{SideCond}

\begin{code}
data AtmSideCond                                                    --SideCond
 = SD  GenVar VarSet -- Disjoint
 | SS  GenVar VarSet -- Superset (covers)
 | SP  GenVar        -- Pre
pattern Disjoint gv vs = SD  gv vs  --  vs `intersect`  gv = {}
pattern Covers   gv vs = SS  gv vs  --  vs `supersetof` gv
pattern IsPre    gv    = SP  gv     --  gv is pre-condition
\end{code}

\begin{code}
type SideCond = ( [AtmSideCond]  -- all must be true                 --VarData
                , VarSet )       -- must be fresh
\end{code}

\begin{code}
type Assertion = (Term, SideCond)                                    --VarData
\end{code}

\subsection{Laws}

\begin{code}
data LogicSig                                                           --Laws
  = LogicSig
     { theTrue  :: Term
     , theFalse :: Term
     , theEqv   :: Identifier
     , theImp   :: Identifier
     , theAnd   :: Identifier
     , theOr    :: Identifier
     }
\end{code}

\begin{code}
data LeftRight = Lft | Rght                                             --Laws

data GroupSpec                                                          --Laws
  = Assoc LeftRight
  | Gather LeftRight Int
  | Split Int
\end{code}

\begin{code}
type NmdAssertion = (String,Assertion)                                  --Laws
\end{code}

\begin{code}
data Provenance                                                         --Laws
  = Axiom          --  considered as `self-evidently` True
  | Proven String  --  demonstrated by (named) proof
  | Assumed        --  conjecture asserted w/o proof
\end{code}

\begin{code}
type Law = (NmdAssertion,Provenance)                                    --Laws
\end{code}

\subsection{Binding}

\begin{code}
data VarBind = BI Identifier | BV Variable | BT Term                 --Binding
pattern BindVar  v  =  BV v
pattern BindTerm t  =  BT t
type VarBinding = M.Map (Identifier,VarClass) VarBind
\end{code}

\begin{code}
data LstVarBind                                                      --Binding
 = BL  VarList
 | BS  VarSet
 | BX  [LVarOrTerm]
pattern BindList vl      =  BL vl
pattern BindSet  vs      =  BS vs
pattern BindTLVs tlvs    =  BX tlvs
type ListVarKey = (Identifier,VarClass,[Identifier],[Identifier])
type ListVarBinding = M.Map ListVarKey LstVarBind
\end{code}

\subsection{Matching}

\begin{code}
type Pattern = Term                                                 --Matching
type Candidate = Term
type BVS = Set GenVar
type PBVS = BVS
type CBVS = BVS
\end{code}

\subsection{TermZipper}

\begin{code}
type TermSubL = [(Variable, Term)]                              --TermZipper
\end{code}

\begin{code}
data Term'                                                        --TermZipper
  = Cons'   TermKind Identifier [Term] -- terms before focus, reversed
                                [Term] -- terms after focus
  | Bnd'   TermKind Identifier VarSet
  | Lam'    TermKind Identifier VarList
  | Cls'             Identifier
  | Sub'    TermKind Substn
  | Substn' TermKind Term LVarSub TermSubL  -- subst-pairs before, reversed
                                  Variable -- focus target variable
                                  TermSubL  -- subst-pairs after focus
\end{code}

\begin{code}
type TermZip = (Term,[Term'])                                    --TermZipper
\end{code}

\subsection{Proofs}

\begin{code}
data MatchClass                                                       --Proofs
  = MA       -- match all of law, with replacement 'true'
  | ME [Int] -- match subpart of 'equiv' chain
  | MIA      -- match implication antecedent A, replacement A /\ C
  | MIC      -- match implication consequent C, replacement A \/ C
  -- MEV should be last, so these matches rank low by default
  | MEV Int  -- match PredVar at given position
pattern MatchAll       = MA
pattern MatchEqv is    = ME is
pattern MatchAnte      = MIA
pattern MatchCnsq      = MIC
pattern MatchEqvVar i  = MEV i
\end{code}

\begin{code}
data HowUsed                                                          --Proofs
  = ByMatch MatchClass  -- replace focus with binding(match)
  | ByInstantiation     -- replace focus=true with binding(law)
\end{code}

\begin{code}
data SeqFocus = CLeft | CRight | Hyp Int                              --Proofs
\end{code}

\begin{code}
data Justification                                                    --Proofs
  = UseLaw             -- used a law
      HowUsed              -- how law was used in proof step
      String               -- law name
      Binding              -- binding from law variables to goal components
      [Int]                -- zipper descent arguments
  | Substitute         -- performed a substitution
      [Int]                -- zipper descent arguments
  | NormQuant          -- performed a quantifier normalisation
      [Int]                -- zipper descent arguments
  | NestSimp           -- simplified nested quantifiers
      [Int]                -- zipper descent arguments
  | Switch             -- switched focus at sequent level
      SeqFocus             -- focus before switch -- needed to reverse this.
      SeqFocus             -- focus after switch
  | CloneH Int         --  Cloned hypothesis i
  | Flatten Identifier -- flattened use of associative operator
  | Associate          -- grouped use of an associative operator
      Identifier           -- operator
      GroupSpec            -- grouping details.
\end{code}

\begin{code}
type CalcStep                                                         --Proofs
  = ( Justification  -- step justification
    , Assertion )         -- previous term
\end{code}

\begin{code}
type Calculation                                                      --Proofs
  = ( Term -- end (or current) term
    , [ CalcStep ] )  -- calculation steps, in proof order
\end{code}

\begin{code}
type Proof                                                            --Proofs
  = ( String -- assertion name
    , Assertion
    , String -- Strategy
    , Calculation -- Simple calculational proofs for now
    )
\end{code}

\subsection{Theories}

\begin{code}
data Theory                                                         --Theories
  = Theory {
      thName   :: String
    , thDeps   :: [String]
    , known    :: VarTable
    , subable  :: SubAbilityMap
    , laws     :: [Law]
    , proofs   :: [Proof]
    , conjs    :: [NmdAssertion]
    }
\end{code}

\begin{code}
type TheoryMap = Map String Theory                                  --Theories
data Theories
  = Theories { tmap :: TheoryMap
             , sdag :: SDAG String }
\end{code}

\subsection{Sequents}

\begin{code}
data Sequent                                                        --Sequents
  = Sequent {
     ante :: [Theory] -- antecedent theory context
   , hyp :: Theory -- the goal hypotheses -- we can "go" here
   , sc :: SideCond -- of the conjecture being proven.
   , cleft :: Term -- never 'true' to begin with.
   , cright :: Term -- often 'true' from the start.
   }
\end{code}

\newpage
\begin{code}
data Laws'                                                          --Sequents
  = CLaws' { -- currently focussed on conjecture component
      hyp0  :: Theory -- hypothesis theory
    , whichC :: LeftRight -- which term is in the focus
    , otherC :: Term  -- the term not in the focus
    }
  | HLaws' { -- currently focussed on hypothesis component
      hname     :: String -- hyp. theory name
    , hknown    :: VarTable
    , hbefore   :: [Law] -- hyp. laws before focus (reversed)
    , fhName    :: String -- focus hypothesis name
    , fhSC      :: SideCond -- focus hypothesis sc (usually true)
    , fhProv    :: Provenance -- focus hypothesis provenance (?)
    , hOriginal :: Term -- the original form of the focus hypothesis
    , hafter    :: [Law] -- hyp. laws after focus
    , cleft0    :: Term -- left conjecture
    , cright0   :: Term -- right conjecture
    }
\end{code}

\begin{code}
data Sequent'                                                       --Sequents
  = Sequent' {
      ante0 :: [Theory] -- context theories
    , sc0       :: SideCond -- sequent side-condition
    , laws'     :: Laws'
    }
\end{code}

\begin{code}
type SeqZip = (TermZip, Sequent')                                   --Sequents
\end{code}

\subsection{LiveProofs}

\begin{code}                                                      --LiveProofs
data Match
 = MT { mName  ::  String     -- assertion name
      , mAsn   ::  Assertion  -- matched assertion
      , mClass ::  MatchClass -- match class
      , mBind  ::  Binding    -- resulting binding
      , mLocSC ::  SideCond   -- goal side-condition local update
      , mLawSC ::  SideCond   -- law side-condition mapped to goal
      , mRepl  ::  Term       -- replacement term
      }
\end{code}

\begin{code}
type MatchContext                                                 --LiveProofs
  = ( String       -- Theory Name
    , [Law]        -- all laws of this theory
    , [VarTable] ) -- all known variables here, and in dependencies
\end{code}

\begin{code}
data LiveProof                                                    --LiveProofs
  = LP {
      conjThName :: String -- conjecture theory name
    , conjName :: String -- conjecture name
    , conjecture :: Assertion -- assertion being proven
    , conjSC :: SideCond -- side condition
    , strategy :: String -- strategy
    , mtchCtxts :: [MatchContext] -- current matching contexts
    , focus :: SeqZip  -- current sub-term of interest
    , fPath :: [Int] -- current term zipper descent arguments
    , matches :: Matches -- current matches
    , stepsSoFar :: [CalcStep]  -- calculation steps so far, most recent first
    }
\end{code}

\begin{code}
type LiveProofs = Map (String,String) LiveProof                   --LiveProofs
\end{code}


\documentclass[../main]{subfiles}
\pagestyle{fancy}

\begin{document}

\chapter{Notation}
\thispagestyle{fancy}

\setlength{\parindent}{18pt}
\begin{onehalfspacing}

  We will denote the class of ordinals by $\on$. For $X,Y$ sets we denote by ${^X}Y$ the set of all functions from $X$ to $Y$. For an infinite cardinal $\kappa$, we let $H_\kappa$ be the set of sets $X$ such that the cardinality of the transitive closure of $X$ is strictly less than $\kappa$. $\zf^-$ will denote $\zf$ with the Collection scheme but without the Power Set axiom, following the results of \cite{ZFwithoutPowerSet}. We write \gbc\ for G\"odel-Bernays class theory with the Axiom of Choice, and \gb\ for \gbc\ without the Axiom of Choice. The symbol $\contr$ will denote a contradiction and $\p(X)$ denotes the power set of $X$. We will sometimes denote elementary embeddings $\pi\colon(\M,\in)\to(\N,\in)$ by simply $\pi\colon\M\to\N$. Generally, $\alpha,\beta,\gamma,\zeta$ will denote ordinals and $\kappa,\lambda,\theta,\delta$ cardinals. We will always assume elementary embeddings to be non-trivial unless otherwise stated, meaning that the elementary embedding in question is not the identity. We will sometimes abuse notation and denote a generic extension $V[g]$ by simply $V^{\mathbb P}$, where $g\subset\mathbb P$ is $V$-generic.

\end{onehalfspacing}
\setlength{\parindent}{0pt}

\end{document}


\section{Evaluation}\label{sec:refinedhaskell:evaluation}

Our goal is to build a practical and effective
SMT \& refinement type-based verifier for Haskell.
%
We have shown that lazy evaluation requires the
verifier to reason about divergence; we have proposed
an approach for implicitly reasoning about divergence
by eagerly proving termination, thereby optimizing
the precision of the verifier.
%
Next, we describe an experimental evaluation of our
approach that uses \toolname to prove termination
on the already verified libraries from Chapter~\ref{chapter:tool}.
%
Our evaluation seeks to determine whether our approach is
%
\emph{suitable} for a lazy language (\ie do most Haskell functions terminate?),
\emph{precise}  enough to  capture the termination reasons (\ie is \toolname able to prove that most functions terminate?),
\emph{usable}   without placing an unreasonably high burden on the user in the form of explicit termination annotations, and
\emph{effective}  enough to  enable the verification of functional correctness properties.
%

%%\spara{Implementation} \toolname takes as input:
%%%
%%(1)~A Haskell \emph{source} file,
%%%
%%(2)~Refinement type \emph{specifications},
%%    including refined datatype definitions,
%%    measures, predicate and type aliases,
%%    and function signatures, and
%%%
%%(3)~Predicate fragments called \emph{qualifiers}
%%    which are used to infer refinement types using
%%    the abstract interpretation framework of Liquid
%%    Typing~\cite{LiquidPLDI08}.
%%%
%%The verifier returns as output, \textsc{Safe} or \textsc{Unsafe},
%%depending on whether the code meets the specifications or not,
%%and, importantly for debugging the code (or specification!)
%%the inferred types for all sub-expressions.

\spara{Benchmarks}
As benchmarks, we used the following famous Haskell libraries:
%
\texttt{GHC.List} and \texttt{Data.List}, which implement many standard
list operations,
\texttt{Data.Set.Splay}, which implements an splay functional set,
\texttt{Data.Map.Base}, which implements a functional
map,
\libvectoralgos,
which includes a suite of ``imperative'' % (\ie monadic)
array-based sorting algorithms,
\bytestring, a library for manipulating byte arrays, and
\libtext, a library for high-performance Unicode text processing.
%
%%These benchmarks represent a wide spectrum of idiomatic
%%Haskell code: the first three are widely used libraries
%%based on recursive data structures, the fourth and fifth
%%perform subtle, low-level arithmetic manipulation of array
%%indices and pointers, and the last is a rich, high-level
%%library with sophisticated application-specific invariants,
%%well outside the scope of Haskell's expressive type system.
%%Thus, this suite provides a diverse and challenging test-bed
%%for evaluating \toolname.
The verification of functional correctness on our benchmarks
is already discussed in~\S~\ref{sec:realworld:evaluation}.
%
Here we focus only on the extra proof obligations
required to reason about function termination.

\input{text/refinedhaskell/results}

\spara{Results}
Table~\ref{table:realworldhaskell:results} summarizes our experiments, which
covered 39 modules totaling 10,209 non-comment lines of
source code. % and 1,652 lines of specifications.
%
The results were collected on a machine with an Intel Xeon
X5600 and 32GB of RAM~(no benchmark required more than 1GB).
%
Timing data was for runs that performed full
verification of safety and functional correctness
properties in addition to termination. %; we only discuss the latter here.

\begin{itemize}
  \item{\emph{Suitable:}} Our approach of eagerly proving termination is in
    fact, \emph{highly} suitable: of the % a total of 1,539 functions, including
    504 recursive functions, only 12 functions were \emph{actually}
    non-terminating (\ie non-inductive).
    That is, 97.6\% of recursive functions
    % (or 99.1\% of all functions)
    are inductively defined.

  \item{\emph{Precise:}} Our approach is extremely precise, as refinements
    provide auxiliary invariants and extensibility that is crucial for
    proving termination. We successfully \emph{prove} that 96.0\% of
    recursive functions % (or 98.6\% of all functions)
    terminate.
    % (Of the 8 that we fail on, 1 terminates for reasons not fully clear to us!)

  \item{\emph{Usable:}} Our approach is highly usable and only places a
    modest annotation burden on the user. The default metric, namely the first
    parameter with an associated size measure, suffices to automatically
    prove 65.7\% of recursive functions terminating. Thus, only 34.3\% require
    explicit termination metric, totaling about 1.7 witnesses (about 1 line
    each) per 100 lines of code.

  \item{\emph{Effective:}} Our approach is extremely effective at improving the
    precision of the overall verifier (by allowing the VC to use facts
    about binders that provably reduce to values).
    % As shown in the \textbf{Err} column in Table~\ref{table:results},
    Without the termination optimization, \ie by only using information
    for matched-binders (thus in WHNF), \toolname reports 1,395
    unique functional correctness warnings -- about 1 per 7 lines.
    With termination information, this number goes to zero.
\end{itemize}

\begin{comment}

Next, we present a qualitative overview of how to prove termination
properties using \toolname.
\subsection{Proving Termination with Refinements}
\label{sec:proving-termination-with-refinements}
{

% 1. Nats
% 2. structural recursion on Lists
% 3. auxiliary invariants that need ghost variables or termination
% expressions, e.g. list merge
% 4. Bytestring
\ES{Assuming we have already outlined the approach with sized types
  encoded via refinements in the overview.}

Let us begin with one of the simplest recursive functions, the
fibonacci function.
%
\begin{code}
  fib  :: Nat -> Int
  fib 0 = 1
  fib 1 = 1
  fib n = fib (n-1) + fib (n-2)
\end{code}
%
Recall that we have simply defined @Nat@ as @{v:Int | v>=0}@. In
this case, the argument @n@ can itself be used as the termination
metric. The precondition ensures that @n@ will be non-negative, \ie
@n@ is \emph{well-founded}, and \toolname knows from the type of
@(-)@ that @n-1@ and @n-2@ are both strictly less than @n@, therefore
@fib@ \emph{must} terminate.

Not all recursive functions on @Nat@s have such simple termination
metrics, one famous example is the Ackermann function.
%
\begin{code}
  ack m n
    | m == 0    = n + 1
    | n == 0    = ack (m-1) 1
    | otherwise = ack (m-1) (ack m (n-1))
\end{code}
%
Neither @m@ nor @n@ can be shown to decrease in each recursive call,
however @ack@ can still be proven terminating because \emph{either}
@m@ decreases \emph{or} @m@ remains the same and @n@ decreases. In
other words, the pair @(m,n)@ strictly decreases according to a
well-founded \emph{lexicographic} ordering. We express lexicographic
termination in \toolname using \emph{termination expressions}, which
take the form @x :: t / e@ where @e@ is a list of \toolname
expressions that should be used to prove termination. In the case of
@ack@ the expressions will simply be references to the parameters @m@
and @n@
%
\begin{code}
  ack :: m:Nat -> n:Nat -> Nat / [m,n]
\end{code}
%
encoding the requirement that @(m,n)@ is a lexicographically
decreasing pair.

\spara{Measuring the Size of Structures}
Many functions are structurally recursive and can be proven
terminating by showing that they always recur on a \emph{substructure}.
Consider the function @map@ defined over the standard list type.
%
\begin{code}
  map f []     = []
  map f (x:xs) = f x : map f xs
\end{code}
%
In @map@, the recursive call is made with a ``smaller'' input.
We formalize the notion of size with \emph{measures}.
%
\begin{code}
  measure len :: [a] -> Nat
  len []     = 0
  len (x:xs) = 1 + len xs
\end{code}
%
With the above definition,
the @measure@ strengthens the type of the data constructors to:
%
\begin{code}
  []  :: {v: [a] | len v = 0}
  (:) :: x:a -> xs:[a]
      -> {v:[a] | len v = 1 + len xs}
\end{code}
%
where @len@ is simply an uninterpreted function in the SMT
logic~\cite{LiquidPLDI09}. With the strengthened data constructors,
\toolname happily proves that @map@ is always called recursively with
smaller inputs\footnote{\toolname defaults to the second parameter
  here for proving termination because it has no notion of the size of
  a function.}, and that the input size is bounded below by 0,
therefore it must terminate.
\spara{Expressing Termination}
Sometimes, the decreasing metric cannot be associated with a single
parameter or lexicographically ordered sequence of parameters, but is
instead an auxiliary value that is a \emph{function} of the
parameters.
%
For example, here is the @union@ function from the splay-tree-based
set library
%
\begin{code}
  union Leaf         t = t
  union (Node x a b) t = Node x taa tbb
    where
      taa          = union ta a
      tbb          = union tb b
      (ta, _, tb)  = split x t
\end{code}
%
which uses the following datatype:
%
\begin{code}
  data Splay a = Leaf
               | Node a (Splay a) (Splay a)
\end{code}
%
Here, as the recursive call ``swaps'' the parameters, \ie the first
(resp. second) argument of the recursive call is computed from the
second (resp. first) parameter, neither parameter provably decreases,
nor do they form a lexicographically-ordered pair.
%
However, on closer inspection it turns out that the \emph{sum}
of the sizes of the trees strictly decreases, as @split@ has type
%
\begin{code}
  a -> t:Splay a -> (SplayL a t, SplayL a t)
\end{code}
%
where the output type uses the alias
%
\begin{code}
  type SplayL a T
    = {v:Splay a | size v <= size T}
\end{code}
%
and @size@ is a \emph{measure} akin to @len@.
%
\begin{code}
  measure size     :: Splay a -> Nat
  size Leaf         = 0
  size (Node v l r) = 1 + size l + size r
\end{code}
%
We already know how to express this type of termination metric using
our handy termination expressions, so we give @union@ the following type:
%
\begin{code}
  union :: Ord a => x:Splay a -> y:Splay a
        -> Splay a / [size x + size y]
\end{code}

% For example, here is the standard @merge@ function from the eponymous sorting
% procedure:
% %
% \begin{code}
%     merge xs@(x:xs') ys@(y:ys')
%       | x < y     = x : merge xs' ys
%       | otherwise = y : merge xs  ys'
% \end{code}
% %
% neither parameter provably decreases in both calls, but the \emph{sum}
% of the sizes of the parameters strictly decreases.

% In these cases, we can reuse our termination expression syntax from
% above, but with a more complex expression.
% %
% \begin{code}
%     merge :: xs:[a] -> ys:[a] -> [a]
%           / [len xs + len ys]
% \end{code}
% %
% This is equivalent to rewriting @merge@ to take a \emph{ghost}
% parameter that acts as a termination witness, \eg
% %
% \begin{code}
%     merge :: xs:[a] -> ys:[a]
%           -> {v:Nat | v = len xs + len ys}
%           -> [a]
% \end{code}
% %
% except that with the termination expression, one need not modify the
% actual code! Now, \toolname verifies that in each recursive call the
% expression @len xs + len ys@ is strictly smaller, thereby proving that
% @merge@ terminates.

\spara{Pointer-based Termination}
For our last example we will look at the \bytestring
library. \bytestring is an interesting target for our termination
experiments because proving termination of \bytestring functions often
requires reasoning about the length of the memory segment that a
pointer points to.

A (strict) @ByteString@ is a triple of a @pay@load pointer,
an @off@set into the memory buffer referred to by the pointer
(at which the string actually ``begins'') and a @len@gth
corresponding to the number of bytes in the string, which is
the size of the buffer \emph{after} the @off@set, that
corresponds to the string.
%
We define a measure for the \emph{size} of
a @ForeignPtr@'s buffer, and use it to define
the key invariants as a refined datatype
%
\begin{code}
  measure fplen  :: ForeignPtr a -> Nat
  data ByteString = PS
   { pay :: ForeignPtr Word8
   , off :: {v:Nat | v       <= fplen pay}
   , len :: {v:Nat | off + v <= fplen pay}
   }
\end{code}
%
\ES{can probably kill this para about invariants if we need space}
The definition states that
the offset is a @Nat@ no bigger than the size of
the @payload@'s buffer, and that
the sum of the @off@set and non-negative @len@gth
is no more than the size of the payload buffer.
Finally, we encode a @ByteString@'s size as a measure.
%
\begin{code}
  measure blen   :: ByteString -> Nat
  blen (PS p o l) = l
\end{code}

Consider the function @findIndex@, which searches through a
@ByteString@ for a @Word8@ that satisfies some predicate @p@.

\begin{code}
  findIndex p (PS x s l) = inlinePerformIO $
    withForeignPtr x $ \f ->
      go l (f `plusPtr` s) 0
  where
    go :: ptr:_ -> n:_ -> _ / [l - n]
    go ptr n
      | n >= l    = return Nothing
      | otherwise = do
          w <- peek ptr
          if p w
            then return (Just n)
            else go (ptr `plusPtr` 1) (n+1)
\end{code}

The bulk of the work is done by the recursive inner function @go@,
which repeatedly increments @ptr@ until it finds an appropriate byte
or it reaches the end of the valid memory region. We use @l - n@ as
the termination metric for @go@, which denotes the number of bytes
remaining in the valid memory region.

\spara{Nested Data}
For our final example, consider @group@, which
splits a string like @"aart"@ into the list
@["aa","r","t"]@.
% , \ie a list of
% (a)~non-empty @ByteString@s whose
% (b)~total length equals that of the input.
% To specify these requirements, we define a measure for
% the total length of strings in a list and use it to
% write an alias for a list of \emph{non-empty} strings
% whose total length equals that of another string:

% \begin{code}
% measure blens :: [ByteString] -> Int
% blens ([])     = 0
% blens (x:xs)   = blen x + blens xs

% type ByteStringNE
%   = {v:ByteString | blen v > 0}
% type ByteStringsEq B
%   = {v:[ByteStringNE] | blens v = blen b}
% \end{code}
%
% \toolname uses the above to verify that
%
\begin{code}
  group xs
    | null xs   = []
    | otherwise = (y `cons` ys) : group zs
    where
      x         = unsafeHead xs
      xs'       = unsafeTail xs
      (ys, zs)  = spanByte x xs'
\end{code}
%
This example illustrates why refinements are critical for
proving termination. \toolname determines that @unsafeTail@
returns a \emph{shorter} @ByteString@ than its input, and that
each element returned by @spanByte@ is no longer than the
input, concluding that @zs@ is smaller than @xs@, and hence
checking the body under the termination-weakened environment.

\ES{figure out why things break when we change spanByte to use term exprs}

Let's also look at @spanByte@, which splits strings into a pair, to
see how \toolname infers its crucial type:
%
\begin{code}
  spanByte c ps@(PS x s l)
    = inlinePerformIO $ withForeignPtr x $
        \p -> go (p `plusPtr` s) 0
    where
      go :: p:_ -> i:_ -> _ / [l - i]
      go p i
        | i >= l    = return (ps, empty)
        | otherwise = do
            c' <- peekByteOff p i
            if c /= c'
            then let b1 = unsafeTake i ps
                     b2 = unsafeDrop i ps
                 in  return (b1, b2)
            else go p (i+1)
\end{code}
%
Here again, the work is all done by the inner recursive function @go@,
which uses the same termination metric as above. \toolname can
infer that both @ByteString@s in the pair are no longer than @ps@
through a case analysis. In the base case, @blen ps <= blen ps@ and
@blen empty <= blen ps@ both hold trivially, and in the recursive case
@blen b1 <= blen ps@ and @blen b2 <= blen ps@ both hold because
\toolname infers that @unsafeTake@ and @unsafeDrop@ both
return shorter strings. Thus, both @ByteString@s returned by
@spanByte@ are at most as long as its input @xs'@, which is
\emph{strictly} shorter than the input to @group@; therefore @group@
is only called recursively on smaller inputs and it must terminate!

So the bright side is that, although sound and precise refinements in
a lazy language incurs the additional burden of termination proofs,
refinements make proving termination easy!

\end{comment}

%%% Local Variables:
%%% mode: latex
%%% TeX-master: "main"
%%% End:


\section{Implementation}
\label{sec:implementation}

The RZ implementation consists of several sequential passes.

After the initial parsing, a \emph{type reconstruction} phase checks
that the input is well-typed%
\iflong
\ (and checks for well-formedness to the
extent that it is easily decidable)%
\fi
, and if successful produces an
annotated result with all variables explicitly tagged with types. The
type checking phase uses a system of dependent types, with limited
subtyping (implicit coercions) for sum types and subset types.
\iflong
The
details are fairly standard, so are omitted here. One non-obvious
consequence of the realizability translation, however, is that the
subset types with logically equivalent predicates, e.g.,
$\isubset{\ix}{\iS}{\iand{\ipp_1(\ix)}{\ipp_2(\ix)}}$ and
$\isubset{\ix}{\iS}{\iand{\ipp_2(\ix)}{\ipp_1(\ix)}}$ are isomorphic
but not equal in general. An
explicit coercion is required to go from one type to the other,
because subset values will be pairs containing realizers for
$\iand{\ipp_1(\ix)}{\ipp_2(\ix)}$ and
$\iand{\ipp_2(\ix)}{\ipp_1(\ix)}$, and these realizers have
potentially different types $|\ipp_1(\ix)| * |\ipp_2(\ix)|$ and
$|\ipp_2(\ix)| * |\ipp_1(\ix)|$ respectively.
\fi % \iflong

Next the realizability translation is performed as described in
Section~\ref{sec:translation}, producing interface code. The
flexibility of the full input language (e.g., $n$-ary sum types and
dependent product types) makes the translation code fairly involved,
and so it is performed in a ``naive'' fashion whenever possible. The
immediate result of the translation is not easily readable.

Thus, up to four more passes simplify the output before it is displayed to
the user. A \emph{thinning} pass removes all references to trivial
realizers produced by stable formulas.
\iflong
For example, direct translation
of the $\mathtt{free}$ axiom in the output for Kuratowski-finite sets,
see Figure~\ref{fig:kuratowski} and Section~\ref{sec:finite-sets},
yields a value specification for $\mathtt{free}$ of type
%
\begin{equation*}
  (\f{A.a} \to \f{S.s}) \to
  (\f{fin} \to \f{S.s}) * (\ounit * (\f{A.a} \to
  \ounit) *
  (\f{fin} \to \f{fin} \to \ounit))
\end{equation*}
%
where $\ounit$ is the unit (terminal) type classifying the trivial
realizer. Thinning replaces this by the isomorphic type
%
\begin{equation*}
  (\f{A.a} \to \f{S.s}) \to \f{fin} \to \f{S.s}
\end{equation*}
%
and appropriately modifies references to $\f{free}$ in the assertions to account for this change in type.

\fi % \iflong
%
An \emph{optimization} pass applies an ad-hoc collection of
basic logical and term simplifications in order to make the output more readable.
\iflong
Logical simplifications include applications of truth table rules
($\iand{\itrue}{\ip}$ becomes $\ip$), detection of syntactically
identical premises and conclusions
($\iimply{\ip_1}{\iand{\ip_1}{\ip_2}}$ becomes
$\iimply{\ip_1}{\ip_2}$), and optimization of other common patterns we have
seen arise
($\iforall{\ix}{\is}{\iimply{(\iequal{\ix}{\ie})}{\ipp(\ix)}}$ becomes
$\ipp(\ie)$).
\fi % \iflong
Some redundancy may remain, but in practice the optimization pass
helps significantly.

Finally, the user can specify two optional steps occur.
RZ can perform a \emph{phase-splitting} pass~\cite{harper+:popl90}.
This is an experimental implementation of an transformation that can replace a functor (a relatively heavyweight language construct) by
parameterized types and/or polymorphic values.
\iflong
The idea is that although
functors map modules containing types and terms to other modules containing types
and terms, constraints on the programming language ensure that output types
depend only on input types (and not input terms).  Thus, we can split each
functor into a mapping from input types to output types, and then a separate
(polymorphic) term mapping input types and terms to an output term.
See Section~\ref{sec:finite-sets} for an example.
\fi

The other optional transformation is a \emph{hoisting} pass which
moves obligations in the output to top-level positions.  Obligations
appear in the output inside assertions, at the point where an uncheckable property was needed.
Moving these obligations to the top-level
make it easier to see exactly what one is obliged to verify, and can
sometimes make them easier to read, at the cost of losing information about
why the obligation was required at all.
\iflong
See
Section~\ref{sec:exampl-with-oblig} for an example of hoisting.
\fi % \iflong

%%% Local Variables:
%%% mode: latex
%%% TeX-master: "cie"
%%% End:


\chapter{Sample Session} \label{appx:example}

The following is an example session with \caps{\PROGRAM}. Text following
the \caps{\PROGRAM} prompt (\verb|ALG>|) is supplied by the user. The
program response (if any) is shown directly below the equation or
command. Comments on the example are in {\em italics}.

\newenvironment{comments} {\em}{}

\verb|ALG>| \cmd{LIST VARS}
\begin{verbatim}
Database:  /User/me/testing/input_databse.e

SAMPLE DATABASE FOR ALGEBRA

Number of coordinates per node       =     2
Number of nodes                      =   644
Number of elements                   =   480
Number of element blocks             =     1

Number of node sets                  =     0
Number of side sets                  =     0

Code:  MISCPROG  version  1.0       on  12/23/85  at  10:21:59
\end{verbatim}

\verb|ALG>| \cmd{LIST STEPS}
\begin{verbatim}
Number of time steps = 21
   Minimum time =  0.00
   Maximum time = 10.00
\end{verbatim}

\newpage
\verb|ALG>| \cmd{SHOW TMAX}
\vspace{-\medskipamount}
\begin{verbatim}
Select all times from 0.0 to 10.0
   Number of selected times = 21
\end{verbatim}
\verb|ALG>| \cmd{TMAX 5.0}
\vspace{-\medskipamount}
\begin{verbatim}
Select all times from 0.0 to 5.0
   Number of selected times = 11
\end{verbatim}
\verb|ALG>| \cmd{NINTV 5}
\vspace{-\medskipamount}
\begin{verbatim}
Select times 0.0 to 5.0 in 5 intervals with delta offset
   Number of selected times = 5
\end{verbatim}

\begin{comments}
These commands select up to 5 time steps between 0.0 and 5.0 starting at
an offset (1.0) from 0.0. The steps with the times nearest 1.0, 2.0,
3.0, 4.0, and 5.0 are selected. The equations are evaluated and the
results written to the output database only for the selected steps.
\end{comments}

\verb|ALG>| \cmd{LIST NAMES}
\begin{verbatim}
Coordinate names: R Z

Variables Names:
   Global:   RESIDUAL  ENERGY    NORM      L2NORM
   Nodal:    DISPLR    DISPLZ    VELR      VELZ      ACCELR    ACCELZ
   Element:  SIGR      SIGZ      SIGT      TAURZ     EPSR      EPST
             EPSRZ
\end{verbatim}

\verb|ALG>| \cmd{SAVE NODAL}

\begin{comments}
All the input database nodal variables (\cmd{DISPLR}, \cmd{DISPLZ}, \ldots,
\cmd{ACCELZ}) will be written unchanged to the output database (unless
they are assigned a value or listed in a \cmd{DELETE} command).
\end{comments}

\newpage
\verb|ALG>|
\cmd{VONMISES = (1.0$/$SQRT(2.0)) $*$ TMAG(SIGR,SIGZ,SIGT,TAURZ,0,0)} \\
\verb|ALG>|
\cmd{EFFSTR = SQRT(1.5) $*$ 5.79E-3 $*$ VONMISES$**$4 $*$
EXP(-12.0$/$300.0$*$1.987)} \\
\verb|ALG>|
\cmd{PRESS = (SIGR $+$ SIGZ $+$ SIGT) $/$ 3.0} \\
\verb|ALG>|
\cmd{PRESS100 = (SIGR\$100 + SIGZ\$100 + SIGT\$100) $/$ 3.0} \\
\verb|ALG>|
\cmd{PHI = EFFSTR $-$ 0.023 $-$ PRESS $*$ (4.43E$-$8 $-$ 3.7E$-$15 $*$
PRESS)} \\
\verb|ALG>|
\cmd{ALPHA = SIGR\$56} \\
\verb|ALG>|
\cmd{BETA = ALPHA $+$ 1.414}

\begin{comments}
Assign element variables \cmd{VONMISES}, \cmd{EFFSTR}, \cmd{PRESS}, and
\cmd{PHI} and global variables \cmd{PRESS100}, \cmd{ALPHA}, and
\cmd{BETA}. Note that the \cmd{PRESS100} equation could be replaced by
``\cmd{PRESS100 = PRESS\$100}''.
\end{comments}

\verb|ALG>| \cmd{DELETE ALPHA}

\begin{comments}
\cmd{ALPHA} (assigned in the equation ``\cmd{ALPHA = SIGR\$56}'' above)
becomes a temporary variable and will not be written to the output
database.
\end{comments}

\verb|ALG>| \cmd{BAD = (A + 1)) + SIN (1,2)}
\vspace{-\medskipamount}
\begin{verbatim}
*** Expected 1 parameter(s) for function SIN, found 2
*** Parenthesis do not balance
*** "A" is not a database variable
    Equation ignored
\end{verbatim}

\begin{comments}
This equation contains several errors. Each error is flagged and the
equation is ignored.
\end{comments}

\verb|ALG>| \cmd{END}

\begin{comments}
No further user input is accepted and the equation evaluation
begins.
\end{comments}


%
% Chapter 1
%
\chapter {Introduction}

Algorithms designed for quantum computers have the potential to solve some problems that cannot be efficiently solved by algorithms designed for classical computers. However, estimating how much resources are needed to execute a quantum algorithm that outperforms a classical one is a difficult task. There are many quantum programming languages and tools built around them such as Q\#\cite{QSharp_Svore_2018}, Qiskit\cite{Qiskit_2021} and Cirq\cite{Cirq_2021} that allow execution of quantum algorithms on simulators but out-of-the-box options to estimate resources are limited to the logical level or not existent.

\section{The Purpose of This Thesis}

This thesis aims to estimate the resources required at the physical level to run Shor's semiprime integer factorization algorithm for trapped-ion and superconducting quantum hardware platforms. To do this, we will extend the simulators infrastructure built around Q\# to calculate the maximum number of physical qubits, the total number of physical gates, and the maximum runtime required to execute a particular quantum algorithm.

Furthermore, we will also analyze the effects of errors introduced by the physical gates, analyze the feasibility of obtaining reliable results without implementing fault-tolerance, and estimate the cost of running the algorithm using error-corrected qubits and fault-tolerant gates.

In order to make this thesis more accesible to people from different backgrounds, we dedicate the next few chapters to provide a brief overview of the basics of quantum computing, quantum error correction, and Shor's semiprime integer factorization algorithm.


\section{Introduction}
\begin{frame}{\insertsec}
	\begin{itemize}
    \item Nowadays Machine Learning it's widely used
    \item Medical images can be obtained using MRI, PET or CT scans but are underused
    \item Different methods have appeared to analyze these data for image classification,
    object detection, segmentation...
    \item Deep learning models aim to be able to unlock the full potential of medical imaging
  \end{itemize}
\end{frame}

\subsection{Survival Analysis}
\begin{frame}{\insertsubsec}
  Survival analysis models usually have:
  \begin{itemize}
    \item Baseline data \( x \)
    \item Event \( E \in \{0, 1\} \)
    \item Time \( T \)
  \end{itemize}

  Casting the survival problem as a ranking is a way of dealing with censored data.
  \vspace{.3cm}
  \begin{columns}
    \begin{column}{.5\textwidth}
      \begin{figure}
        \centering
        \input{drawings/graph_no_censored.tikz.tex}
        \caption{Uncensored data}
      \end{figure}
    \end{column}
    \begin{column}{.5\textwidth}
      \begin{figure}
        \centering
        \input{drawings/graph_censored.tikz.tex}
        \caption{Censored data}
      \end{figure}
    \end{column}
  \end{columns}

\end{frame}


\section{Abstract}
This article describes an attempt to reproduce key findings of a study of murine hippocampal oscillations published in 2007 \cite{hentschke_muscarinic_2007}. Being a submission to the 'Ten Years Reproducibility Challenge', it focuses on the process of reviving the Matlab code underlying the analyses, particularly the neuronal signal processing toolbox created for the study and its follow-ups.

\section{Introduction}
\subsection{Neuroscientific background}
\label{subsec:background}
Neuronal activity in mammalian central nervous systems is often oscillatory. Intensity, frequency, and other characteristics of the oscillations are closely associated with behavior and arousal state. As this association suggests a functional role of oscillations, they have been studied extensively. One of the most conspicuous cases of behavior-dependent oscillatory neuronal activity occurs in hippocampus, a brain region pivotal for navigation and memory formation: prominent rhythms exist in the theta (4-12 Hz) and gamma (30-90 Hz) bands.
Interestingly, the oscillations are coupled in a nonlinear fashion: the magnitude of gamma oscillations varies cyclically at theta frequency \cite{soltesz_low-_1993} (Fig.~\ref{fig:hip_oscill}). Such phase-amplitude coupling (PAC), also termed 'nesting' of oscillations, has been postulated to be important for memory formation and retrieval \cite{lisman_storage_1995, hyafil_neural_2015}.

A large body of research has shown that both theta and gamma rhythms depend on the neuromodulator acetylcholine, but before our study \cite{hentschke_muscarinic_2007} it had not been clear whether and how their PAC would change with cholinergic signalling. As a first step towards shedding light on this, we performed experiments on mice with extracellular multielectrode arrays implanted into area CA1 of hippocampus. Each extracellular electrode picked up local field potentials (LFPs) -- tiny, local, time-dependent changes in the electrical potential relative to a distant reference point (Fig.~\ref{fig:hip_oscill}B). The mice were behaviorally scored and the LFPs recorded for periods of ca.\ 90 min, including administration of a blocker of muscarinic cholinergic receptors 30 min into the experiments.

\subsection{Code base and scope of reproduction}
The code presented here consists of two major parts. One is a toolbox of bespoke data crunching routines which performed classical time and frequency domain analyses. These were geared towards revealing spatial and temporal relations between signals from the different recording electrodes (crosscorrelations, coherence, etc.), with a focus on within-site phase-amplitude coupling. The 'main' function of this toolbox -- termed 'rmouse' -- integrated behavioral scoring data, partitioned the computational results according to the animals' behavior, and created summary figures for each recording (Fig.~\ref{fig:rmouse_workingstyle}). Also included were numerous post-processing routines with specific jobs like aggregation of data.

The other part of the code consisted of project-specific routines for statistical analyses of the data, and for the generation of publication-style plots.

The major focus here is on getting the toolbox and associated post-processing code to run with a Matlab version as recent as possible. Moreover, I attempted to reproduce those figures of the original study which conveyed the key finding of the paper, namely a reduction of PAC in the presence of muscarinic blockers (Fig.~\ref{fig:repro}).

\subsection{Expectations and results in a nutshell}
As Matlab code is generally quite backwards compatible, I was optimistic about overall success. The optimism was justified in terms of a general repeatability of the analysis; both toolbox and post-processing code could be brought into a functional state, and figures be created from the newly computed analysis results. However, data could only be retrieved for three of the five experimental animals of the original study, so the figures shown here are not exact reproductions, but must rather be seen as proofs of concept.

\begin{figure}
	\centering
	\includegraphics[width=0.9\textwidth]{figures/figures_tenYears_01.png}
	\caption{Theta and gamma oscillations, two prominent hippocampal oscillations under investigation in the original study. A, sketch of a section of rodent hippocampus and the location of the multielectrode recording arrays (orange circles). Shown are also two pyramidal cells with their basal dendrites in \textit{stratum oriens} and apical dendrites in \textit{strata radiatum} and \textit{lacunosum-moleculare}. B, wide-band local field potential data (top trace), and filtered versions (center and bottom, respectively) of a short stretch of oscillatory activity in the hippocampus of a mouse exploring its surroundings. Note how troughs of the slower theta oscillation (4-12 Hz) coincide with peaks in the envelope of the faster gamma oscillations (30-90 Hz).}
	\label{fig:hip_oscill}
\end{figure}

\subsection{Computational context}
% Describe the computational context: Which hardware was used to run the code? Which software infrastructure? Which constraints existed on software development? Which technical choices (language, libraries, ...) were made? Were reproducibility and/or re-usability important criteria?
% About the original source code: Was it published? Was it archived somewhere? Was there a license for it?

I developed the largest part of the code during a postdoctoral stay 2003-2005 in the laboratory of Robert A. Pearce (University of Wisconsin at Madison). The core of the analysis strategy had been devised by Matthew I. Banks (also UW Madison), who had also implemented a first version in a spreadsheet-cum-script language (Origin). Due to limitations inherent in the language it was decided to implement and extend the analysis in a more versatile language. Matlab was the natural way to go, as it was (and still is) the standard programming environment in many electrophysiology laboratories, and I had used it extensively before. In our original study \cite{hentschke_muscarinic_2007}, Matlab versions 6.5 - 7.4 (R13 - R2007a) were used. For later projects, the code has been continuously adapted to Matlab versions up to 7.9 (R2009b), after which it lay dormant. Various Matlab toolboxes were required: most importantly, the Signal Processing Toolbox; depending on the exact post-processing routines, the Curve Fitting and Statistics Toolboxes were also required.

A pivotal issue for the project, and in general for any data-focused undertaking, was the import of raw data. The time series data existed in a proprietary format, the Axon Binary Format (ABF), in which each data point is stored as a 16-bit integer. A function for efficiently importing data of this format into Matlab did not exist. Although the software package provided by the vendor (former Axon Instruments, now Molecular Devices) allowed an export of the data into text format, this was not considered practical (tedium involved in manual conversion, inflation of data size). Hence, I wrote a routine for importing raw data in this format into Matlab and submitted it to the MathWorks Central File Exchange \cite{hentschke_abfload_nodate}. Initially considered a spin-off of minor importance, this routine and its upgrade \cite{collman_fcollmanabfload_nodate} found a widespread distribution in the neuroscience community, and also sparked implementations in other languages \cite{caldwell_abfload_nodate, harden_swhardenpyabf_nodate}. An ironic twist is that the more fail-safe way of implementing a data importing routine for the windows operating system, namely code employing Molecular Devices' dynamic link library (DLL), would have made sense at the project's start in 2003, but has since the introduction of 64-bit versions of Matlab been rendered impractical by the limitation of this DLL to 32 bit (confirmed via an exchange with Molecular Devices Customer Support in December 2019). Readers further interested in this topic may want to consult the "Unofficial Guide to the ABF File Format" by Scott Harden \cite{harden_scott_w_unofficial_nodate}.

As all code was written in pure Matlab, and data import had been solved within Matlab, there were no extraneous dependency issues.

Although reproducibility of the study results was not an imminent concern to me back then, reusability of the code had definitely been an important design aspect early on. Series of experiments with a similar setup were in the pipeline, and given the limited term of my stay it was clear that the code would also be used by my colleagues \cite{perouansky_amnesic_2007, hentschke_altered_2009, balakrishnan_midazolam_2014}. Therefore, I wrote a manual with illustrations, with the intent of providing sufficient information for lab members familiar with the scientific background to find their way through the code. I also commented the code prolifically, especially the scripts calling the toolbox functions. The source code has never been properly archived or published, except for the data importing routine (until the reproducibility challenge came along) for two reasons: first, I considered it too specialized and tailor-made to be of much use for other groups. Second, making the toolbox open access would have required making it more user-friendly and extending the documentation substantially. Absent an academic reward system for such efforts not only for myself but also the hosting lab, I considered the necessary investment of time inappropriate.

I developed the code without any kind of version control worth the term, and left it 'as is' on my then machine in the laboratory. The toolbox's core code was in one dedicated directory, but auxiliary code was scattered throughout my Matlab code base, which of course also contained a great deal of unrelated code. I never saw the necessity of properly packaging the code: it would not be published, and almost all auxiliary functions employed by the toolbox were quite general and therefore also part of other (and future) programming projects. So, my justification for this practice was to avoid redundancy and the usual problems associated with maintaining multiple copies of code.

Towards the end of my stay in the laboratory, I simply mirrored my Matlab directory on other users' machines to get the toolbox to run there. After I left, I developed it further and adapted it to the needs of the subsequent projects, which went on for quite a while.

Hardware was an issue, albeit an uncritical one. The analyses were run on 32-bit Windows PCs with 4 GB of RAM and not-too-bad Intel Pentium processors available at the time (more precise specs are not known anymore). The electrophysiological signals were sampled at ca. 1000 Hz from up to 16 channels and typically lasted for 30 minutes; the resulting individual raw data files occupied less than 100 Mb on disk. Their size in RAM, after conversion from 16-bit integers to the default 64-bit floating type in Matlab, posed no critical challenge. However, the code also implemented the creation of surrogate time series. Dealing with these, as well as multiple filtered copies of the data in RAM in parallel required some thought-through strategies and juggling with computer resources, and was taxing for the CPU. Yet, even full-blown analyses of the whole data set were accomplished overnight.

\section{Retrieval of the software}
% Was it easy to find a copy of your source code?
% Was it easy to locate and setup the dependencies?
% Provide a list of all dependencies (libraries but also tools such as compilers).

Retrieval of the source code was easy; in fact, most of it did not have to be retrieved. As code files are ridiculously small even by the standards of the mid-2000s, I generally leave them on the hard disks of the computers in my hands. The hard part was figuring out the organization of the code files. There were the toolbox folder, still in my Matlab code base, and the folder containing code files for generating the publication figures. Localizing both required just a few minutes. I was also aware that several auxiliary functions, including the data-importing function, were outside the toolbox folder but inside my Matlab code base. However, I forgot that back then I placed scripts defining analysis parameters for each individual data file in yet a different location: namely, in the root folder for the raw data, as well as the subfolders therein. Only after I tried to run the first analysis step did I realize this.

\section{Execution}
% Describe what you did in order to run the software today.
% • Did you succeed in running the software in a modern computational environment? Or did you have to search for old versions of tools and libraries?
% • Describe the computational environment of the reproduction: hardware, operating system, compiler versions etc.
% • Did you have to modify the software in order to make it run today?
% • Were the original instructions that came with the software sufficient, or did you have to modify or extend them?
% • How close were the results you got to the originally published ones? Include the replicated data table and figure, as we do in other ReScience articles.
% If you had to make any modifications to the software or to the instructions that were supplied with it, try to describe which competence another researcher would need in order to do the same work. Would a general familiarity with your programming language and environment have been sufficient?

Reproduction was performed on a PC with Windows 7 and Matlab R2020a with the Signal Processing, Statistics and Machine Learning, and Parallel Computing Toolboxes installed. The PC had 32 GB of RAM, ample space on both hard disk and solid state drive, an Intel Core i7-4770K CPU with four physical cores, and an nvidida GeForce GTX1060 graphics card.

Reproducing data analysis including selected figure panels of the original paper required several processing steps.
I started with the first step -- processing the raw data -- by trying to locate the scripts which defined the analysis parameters for each individual file to be processed. After finding only one, I read the manual, and realized that both the majority of the data and data-specific scripts were missing, contrary to my first cursory impression when entering the challenge. Thanks to the efforts of a former colleague (acknowledgements) I was able to retrieve six complete sets of data and data-specific scripts from three of five experimental animals used in the original study. With these available, I finally remembered how the toolbox was supposed to work.

Before actually trying to run it, I assembled all code files I could identify at this stage as belonging to the project into a directory structure such that submitting the code to a repository would be possible. Next, I ran a dependency analysis on the main function of the toolbox and could identify a number of additional code files that were missing. After copying these to the project directory, I excluded my general Matlab code base from the path. Then, I tried in earnest to start number crunching. It took me about three hours to get the analyses to run on three experiments (two data files each). The adjustments required were, in order of severity:

\begin{enumerate}
	\item Retrieval of functions that were still missing from my general Matlab code base (about two dozen of files).
	\item 'Downgrading' auxiliary functions which had been in my general code base and together with it had evolved over time to the point of being incompatible with the toolbox.
	\item Updating code to be compatible with the recent version of Matlab.
\end{enumerate}

I was shocked to learn how many of the required functions I had to retrieve from my '\_legacy' folder. Had I not exerted caution in getting rid of code and instead deleted them, I would have spent hours on end to recapitulate what they were supposed to do, and possibly given up. A pleasant confirmation of expectations was the little effort I had to spend adapting the code to the most recent Matlab version. Essentially, all I had to do was write a wrapper for function \texttt{diag}, which did not accept cell arrays as inputs anymore. Surprisingly, graphics, including one very simple GUI, worked without hiccups; thanks to a major revision of graphics in R2014b, it also produced more aesthetically pleasing figures.

Moreover, with little effort, it was possible to run number crunching in an embarassingly parallel way using \texttt{parfeval}. This, as well as moving the data to a solid state drive, cut down processing time from a baseline of 152 min to a very agreeable 66 min (three experimental subjects, two recordings each, 100 instances of surrogate data generation each). Although exact numbers are impossible to come by, my estimate is that the combination of recent software and more modern (certainly not recent) hardware sped up the computations by a factor of at least eight. Yet more speedup would have required fundamental re-coding of the toolbox.

\begin{figure}
	\centering
	\includegraphics[width=0.9\textwidth]{figures/example_summaryFig_rmouse.jpg}
	\caption{Example of a summary figure produced by the rmouse toolbox from one of the analyzed data files. These summary figures were meant to provide a quick overview of the data and a glimpse at the computed quantities. The top panel and pie chart on the left illustrate the temporal sequence and proportions of time spent in various behavioural states, respectively, and also quantify recording periods unsuitable for analysis. Examples of data segments considered artifacts are depicted on the left, below the pie chart. All other panels show the results of spectral and time domain analyses.}
	\label{fig:rmouse_workingstyle}
\end{figure}

The next task was aggregating the data from the different experiments, and (re-)producing selected figure panels of the original study. Numerous scripts for various visualizations of the results existed; as these were not strictly documented and kept up to date, a trial-and-error period of identifying key pieces of code responsible for producing the plots ensued. Apart from this, and on top of adjustments similar to those required for the toolbox, I expected two additional problems here. First, the original code made use of the Curve Fitting Toolbox, which was not at my disposition now. Second, code producing 'Christmas Tree' plots -- adorned horizontal bar plots often featuring a coniferous shape (Fig.~\ref{fig:repro}) -- featured low-level graphics commands. Due to substantial changes of Matlab graphics in the interim, I knew that this code would have to be modified.
Both challenges proved surmountable. For the simple fits of 1D data, I used function \texttt{fitnlm}, and refurbished the affected code accordingly. The function producing the horizontal bar plots could also be updated without major pains. Following these fixes, key findings of the original study could be reproduced, albeit only with said partial data (Fig.~\ref{fig:repro}). All other figure panels featuring above-mentioned horizontal bar plots could be reproduced with the same data base by  changing the name of a target variable in a script and adapting the curve-fitting code (data not shown).

\begin{figure}
	\centering
	\includegraphics[width=0.9\textwidth]{figures/figures_tenYears_02.png}
	\caption{Reproduction of key findings. A, exemplary power spectral densities of the wide-band LFP ('raw') and of the gamma envelope of the LFP recorded at the hippocampal fissure. The light shaded area corresponds to the power of the gamma envelope in the theta range; the gray area represents the power of the gamma oscillations. This graph corresponds to Figure 5B in the original paper. B, laminar profile of the power of the gamma envelope in the theta band for immobile and exploring  animals (three of five from which data could be retrieved). The vertical position of the bars illustrates the location of the recording sites underlying the data. Gray, control; black, with the muscarinic blocker atropine. Error bars are standard deviations. Dotted lines are exponential fits to the data. This graph corresponds to Figure 5C in the original paper. C, laminar profile of the crosscorrelation between theta and the gamma envelope. Same conventions as in B apply. Dotted lines are polynomial fits (order 2) to the data. This graph corresponds to Figure 7A in the original paper. D, artistic rendering of theta oscillations, illustrating their highly dynamic nature. Time runs horizontally from left to right. Each set of concentric rings represents a theta peak (green) or trough (orange) detected on each of the 16 electrodes spanning hippocampus (and a trifle of the surrounding tissue). The more rings in a set, the stronger the normalized peak or trough amplitude (as amplitudes differ strongly between the layers, they were normalized for each recording electrode separately). The orientation of recording sites is as in the sketch in B (topmost row corresponds to \textit{stratum oriens/alveus}). On average, there is a phase lag of almost half a theta period between the layers harboring the apical and basal dendrites of the pyramidal cells, but individual theta 'beats' are very variable. The increase of such variability in the presence of atropine (data not shown) is a major cause of the deteriorated coordination between theta and gamma (as shown in C). Modeled after Figure 9A in the original paper.}
	\label{fig:repro}
\end{figure}

\section{Conclusion and personal evaluation}
During my last years in academia, I focused increasingly on professional programming, and eventually left academia in 2019 to work as a Data Scientist. Having along the way picked up at least a modicum of formal software education, my opinion on my original source code is mixed.

On the positive side, I commented the code heavily, particularly the scripts which other users of the code were to use. Later on, I also spent a considerable amount of time on the documentation. A crude form of logging was implemented. Moreover, I had a knack for making code run fast, and consider some aspects of the implementation valid even today.

However, a few of my past code design choices strike me as odd now, to say the least. First and foremost, this is above-mentioned liberal dispersal of code files across my entire code base, and the placement of scripts defining parameters in data directories. The cascades of scripts required for running analyses with the toolbox required immersion into the code, and could have been replaced by a more user-friendly graphical user interface. For post-processing, there had been a proliferation of poorly documented and partly redundant helper or plotting functions. Over time, 13 (thirteen) variants of a 'combine\_X'-function had accumulated, the job of which was to assemble the results of the computations by the toolbox. Moreover, I would have compartmentalized the toolbox code much more. Finally, for a toolbox of this scope, more time should have been devoted to the documentation. All things considered, I believe that resurrecting the code would have been very arduous for anyone else, even a Matlab expert, due to a dearth of documentation.

Yet, I view these deficiencies in context. As a scientist-cum-programmer, one also has the science to do, not to mention actually making sense of the analysis results and writing papers about them. As mentioned before, spending a large amount of time on the documentation would have been hard to justify. Moreover, like many of my former colleagues, I was a self-taught programmer essentially without formal computer science education, so most of my design choices were not based on traded wisdom, but self-accrued, patchy knowledge.

My former self was certainly not alone in this position, as academia in general seems to be a fertile ground for 'organically home-grown' code that may or may not be 'good enough' to publish \cite{barnes_publish_2010}. It is heartening to see that programming scientists are increasingly given a hand in producing reproducible and efficient code \cite{wilson_good_2017}.

\section{Acknowledgements}
I owe profound thanks to Claudia Holt, Section of Experimental Anesthesiology, University Hospital of Tübingen, who unearthed the data for this study. Many thanks also go to Matthew I. Banks for discussions of the manuscript, and to Robert A. Pearce for consenting to the publication of the code.