dds/scribblings/rs.scrbl

374 lines
10 KiB
Racket

#lang scribble/manual
@(require scribble/example racket/sandbox
(for-label typed/racket/base
"../rs.rkt"
"../utils.rkt"
"../dynamics.rkt"))
@(define rs-evaluator
(parameterize ([sandbox-output 'string]
[sandbox-error-output 'string]
[sandbox-memory-limit 500])
(make-evaluator 'typed/racket
#:requires '("rs.rkt" "utils.rkt"))))
@(define-syntax-rule (ex . args)
(examples #:eval rs-evaluator . args))
@(define-syntax-rule (deftypeform . args)
(defform #:kind "type" . args))
@(define-syntax-rule (deftype . args)
(defidform #:kind "type" . args))
@title[#:tag "rs"]{dds/rs: Reaction Systems}
@defmodule[dds/rs]
This module defines reaction systems and various tools for working with them.
@section[#:tag "rs-basics"]{Basic definitions}
@deftype[Species]{
A synonym of @racket[Symbol].
}
@defstruct*[reaction ([reactants (Setof Species)]
[inhibitors (Setof Species)]
[products (Setof Species)])]{
A reaction is a triple of sets, giving the reactants, the inhibitors,
and the products, respectively.
}
@deftype[Reaction]{
The type of the instances of @racket[reaction].
}
@deftype[ReactionName]{
A reaction name is any @racket[Symbol].
}
@defproc[(make-reaction [r (Listof Reaction)]
[i (Listof Reaction)]
[p (Listof Reaction)])
Reaction]{
A shortcut for constructing @racket[Reaction]s using list syntax
instead of set syntax.
@ex[
(make-reaction '(a b) '(c d) '(e f))
]}
@defproc[(enabled? [r Reaction] [s (Setof Species)]) Boolean]{
A @racket[Reaction] is enabled on a set of species if all of its
reactants are in the set and none of its inhibitors are.
@ex[
(enabled? (make-reaction '(a b) '(c d) '())
(set 'a 'b 'e))
(enabled? (make-reaction '(a b) '(c d) '())
(set 'a 'b 'c))
(enabled? (make-reaction '(a b) '(c d) '())
(set 'b 'e))
]}
@deftype[ReactionSystem]{
A reaction system is a dictionary mapping @racket[ReactionName]s to
@racket[Reaction]s.
}
@defproc[(list-enabled [rs ReactionSystem] [s (Setof Species)])
(Listof ReactionName)]{
Returns the list of the names of reactions of @racket[rs] enabled on
@racket[s].
@ex[
(let ([rs (hash 'a (make-reaction '(x) '(y) '(z))
'b (make-reaction '(x y) '() '(z)))])
(values (list-enabled rs (set 'x 'y))
(list-enabled rs (set 'x))))
]}
@defproc[(union-products [rs ReactionSystem] [as (Listof ReactionName)])
(Setof Species)]{
Returns the union of the product sets of the given reactions listed in
@racket[as] in @racket[rs]. If no reactions are supplied, returns the
empty set.
@ex[
(union-products (hash 'a (make-reaction '(x) '(y) '(z))
'b (make-reaction '(x y) '() '(z)))
'(a b))
]}
@defproc[(apply-rs [rs ReactionSystem] [s (Setof Species)])
(Setof Species)]{
Applies the reaction system @racket[rs] to @racket[s].
@ex[
(let ([rs (hash 'a (make-reaction '(x) '(y) '(z))
'b (make-reaction '(x y) '() '(z)))])
(apply-rs rs (set 'x)))
]}
@section{Org-mode interaction}
This section contains some useful primitives for
@hyperlink["https://orgmode.org/"]{Org-mode} interoperability.
@defproc[(str-triple->reaction [lst (List String String String)]) Reaction]{
Converts a triple of strings to a reaction.
@ex[
(str-triple->reaction '("a b" "c d" "e f"))
]}
@defproc[(ht-str-triples->rs [ht (HashTable ReactionName (List String String String))])
ReactionSystem]{
Converts a hash table mapping reaction names to triples of strings to
a reaction system.
@ex[
(ht-str-triples->rs (hash 'a (list "x y" "" "k i")
'b (list "" "x y" "t j")))
]}
@defproc[(read-org-rs [str String]) ReactionSystem]{
Reads a reaction system from an Org-mode style string.
@ex[
(read-org-rs "((\"a\" \"x t\" \"y\" \"z\") (\"b\" \"x\" \"q\" \"z\"))")
]}
@defproc[(read-context-sequence [str String]) (Listof (Setof Species))]{
Reads a context sequence (a list of sets of species) from a string
containing a list, which may be produced by Org-mode.
@ex[
(read-context-sequence "((\"x y\") (\"z\") (\"\") (\"t\"))")
]}
@defproc[(reaction->str-triple [r Reaction]) (Listof String)]{
Converts a reaction to a triple of strings.
@ex[
(reaction->str-triple (make-reaction '(x y) '(z t) '(k i)))
]}
@defproc[(rs->ht-str-triples [rs ReactionSystem])
(HashTable ReactionName (Listof String))]{
Converts a reaction system to a hash table mapping
@racket[ReactionNames]s to triples of strings.
@ex[
(rs->ht-str-triples (hash 'a (make-reaction '(x) '(y) '(z))
'b (make-reaction '(x y) '() '(z))))
]}
@section{Dynamics of reaction systems}
The dynamics of reaction systems is typically defined as @emph{interaction
processes}. An interactive process of a reaction system is a sequence of
states driven by a sequence of contexts in the following way. The reaction
system starts with the initial context. Then, at every step, the result of
applying the reaction system is merged with the next element of the context
sequence, and the reaction system is then applied to the result of the union.
If the sequence of contexts is empty, the reaction system cannot evolve.
@defstruct*[state ([result (Setof Species)]
[rest-contexts (Listof (Setof Species))])]{
A state of a reaction system is a set of species representing the
result of the application of the reactions from the previous steps
(the field @racket[result]), plus the rest of the context sequence
(the field @racket[rest-contexts]).
The length of @racket[rest-contexts] dictates for how many steps the
reaction system will be run. If it is empty, no more reactions will
be applied.
}
@deftype[State]{
The type of the instances of @racket[state].
}
@defclass[dynamics% dds% ()]{
A model of dynamics of a @racket[ReactionSystem].
@defconstructor[([rs ReactionSystem])]{
Constructs a model of dynamics for @racket[rs].
}
@defmethod[(step/annotated [s State]) (Listof (Pairof (Listof ReactionName) State))]{
Runs the @racket[ReactionSystem] stored in this class on the given
state and produces a list containing one pair, indicated the reactions
enabled on @racket[s] and the @racket[State] resulting after applying
these reactions.
@ex[
(let* ([rs (hash 'a (make-reaction '(x) '(y) '(z))
'b (make-reaction '(x y) '() '(x)))]
[dyn (new dynamics% [rs rs])]
[s0 (state (set 'x 'y)
(list (set) (set) (set 'x)))])
(send dyn step/annotated s0))
]}
}
@deftype[Dynamics%]{
The type of an instance of @racket[dynamics%].
}
@defproc[(build-interactive-process-graph [rs ReactionSystem]
[contexts (Listof (Setof Species))])
Graph]{
Builds the state graph of the reaction system @racket[rs] driven by
the context sequence @racket[contexts].
This function directly calls @method[dds% build-state-graph/annotated]
under the hood, and is actually a light interface on top of
that function.
@ex[
(let ([rs (hash 'a (make-reaction '(x) '(y) '(z))
'b (make-reaction '(x y) '() '(x)))]
[ctx : (Listof (Setof Species)) (list (set) (set) (set 'x))])
(dotit (build-interactive-process-graph rs ctx)))
]}
@defproc[(build-interactive-process-graph/simple-states
[rs ReactionSystem]
[contexts (Listof (Setof Species))])
Graph]{
Builds the state graph of the reaction system @racket[rs] driven by
the context sequence @racket[contexts], like
@racket[build-interactive-process-graph], but omits the context
sequences from the states.
@bold{Note:} If the reaction system visits the same set of species
multiple times, all these visits will be conflated into a single node
in the resulting graph. The number or the order of visits will not be
reflected in any way.
@ex[
(let ([rs (hash 'a (make-reaction '(x) '(y) '(z))
'b (make-reaction '(x y) '() '(x)))]
[ctx : (Listof (Setof Species)) (list (set) (set) (set 'x))])
(dotit (build-interactive-process-graph/simple-states rs ctx)))
]}
@defproc[(pretty-print-state-graph/simple-states [sgr Graph]) Graph]{
Pretty prints the node and edge labels in a reaction system
state graph with simple states.
Simple states, as opposed to @racket[State], do not include the
remaining context sequence.
See @racket[build-interactive-process-graph/simple-states] for further
explanations and examples.
@ex[
(let ([rs (hash 'a (make-reaction '(x) '(y) '(z))
'b (make-reaction '(x y) '() '(x)))]
[ctx : (Listof (Setof Species)) (list (set) (set) (set 'x))])
(dotit (pretty-print-state-graph/simple-states
(build-interactive-process-graph/simple-states rs ctx))))
]}
@defproc[(build-interactive-process [rs ReactionSystem]
[ctx (Listof (Setof Species))])
(Listof (Pairof (Setof Species) (Setof Species)))]{
Builds the interactive process driven by the given context sequence.
The output is a list of pairs of lists in which the first element is
the current context and the second element is the result of the
application of reactions to the previous state. The interactive
process stops one step after the end of the context sequence, to show
the effect of the last context.
@ex[
(let ([rs (hash 'a (make-reaction '(x) '(y) '(z))
'b (make-reaction '(x y) '() '(x)))]
[ctx : (Listof (Setof Species)) (list (set) (set) (set 'x))])
(build-interactive-process rs ctx))
]}
@defproc[(build-interactive-process/org
[rs ReactionSystem]
[ctx (Listof (Setof Species))])
(Listof (Listof (Setof Species)))]{
Like @racket[build-interactive-process], but the type of a line of the
output is @racket[(Listof (Setof Species))] instead of @racket[(Pairof
(Setof Species) (Setof Species))].
This function may be more practical for outputting directly to an
Org-mode table.
@ex[
(let ([rs (hash 'a (make-reaction '(x) '(y) '(z))
'b (make-reaction '(x y) '() '(x)))]
[ctx : (Listof (Setof Species)) (list (set) (set) (set 'x))])
(build-interactive-process/org rs ctx))
]}
@defproc[(pretty-print-state [st State]) String]{
Pretty prints the context sequence and the current result of
@racket[st].
@ex[
(pretty-print-state (state (set 'x 'y) (list (set 'z) (set) (set 'x))))
]}
@defproc[(pretty-print-state-graph [sgr Graph]) Graph]{
Pretty prints the state graph of a reaction system.
Note that we need to keep the full context sequence in the name of
each state to avoid confusion between the states at different steps of
the evolution.
@ex[
(let ([rs (hash 'a (make-reaction '(x) '(y) '(z))
'b (make-reaction '(x y) '() '(x)))]
[ctx : (Listof (Setof Species)) (list (set) (set) (set 'x))])
(dotit (pretty-print-state-graph (build-interactive-process-graph rs ctx))))
]}