2020-11-29 17:43:20 +01:00
|
|
|
#lang scribble/manual
|
2023-08-08 17:22:03 +02:00
|
|
|
@(require scribble/example racket/sandbox
|
|
|
|
(for-label typed/racket/base
|
2023-08-16 08:23:47 +02:00
|
|
|
(submod "../rs.rkt" typed)
|
2023-08-16 14:01:17 +02:00
|
|
|
"../utils.rkt"
|
2023-08-16 08:23:47 +02:00
|
|
|
"../dynamics.rkt"))
|
2023-08-08 17:22:03 +02:00
|
|
|
|
|
|
|
@(define rs-evaluator
|
|
|
|
(parameterize ([sandbox-output 'string]
|
|
|
|
[sandbox-error-output 'string]
|
|
|
|
[sandbox-memory-limit 500])
|
2023-08-16 14:01:17 +02:00
|
|
|
(make-evaluator 'typed/racket
|
|
|
|
#:requires '((submod "rs.rkt" typed) "utils.rkt"))))
|
2023-08-08 17:22:03 +02:00
|
|
|
|
|
|
|
@(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))
|
2020-11-29 17:43:20 +01:00
|
|
|
|
|
|
|
@title[#:tag "rs"]{dds/rs: Reaction Systems}
|
|
|
|
|
2023-08-08 17:22:03 +02:00
|
|
|
@defmodule[(submod dds/rs typed)]
|
2020-11-29 22:12:01 +01:00
|
|
|
|
|
|
|
This module defines reaction systems and various tools for working with them.
|
|
|
|
|
|
|
|
@section[#:tag "rs-basics"]{Basic definitions}
|
|
|
|
|
2023-08-08 17:22:03 +02:00
|
|
|
@deftype[Species]{
|
|
|
|
|
|
|
|
A synonym of @racket[Symbol].
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2023-08-08 17:40:44 +02:00
|
|
|
@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].
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2023-08-09 11:29:09 +02:00
|
|
|
@deftype[ReactionName]{
|
|
|
|
|
|
|
|
A reaction name is any @racket[Symbol].
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2023-08-08 18:09:24 +02:00
|
|
|
@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))
|
|
|
|
]}
|
|
|
|
|
2023-08-08 18:28:25 +02:00
|
|
|
@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))
|
|
|
|
]}
|
|
|
|
|
2023-08-08 18:34:40 +02:00
|
|
|
@deftype[ReactionSystem]{
|
|
|
|
|
2023-08-09 11:29:09 +02:00
|
|
|
A reaction system is a dictionary mapping @racket[ReactionName]s to
|
|
|
|
@racket[Reaction]s.
|
2023-08-08 18:34:40 +02:00
|
|
|
|
|
|
|
}
|
|
|
|
|
2023-08-09 11:29:09 +02:00
|
|
|
@defproc[(list-enabled [rs ReactionSystem] [s (Setof Species)])
|
|
|
|
(Listof ReactionName)]{
|
2023-08-09 11:15:43 +02:00
|
|
|
|
|
|
|
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))))
|
|
|
|
]}
|
|
|
|
|
2023-08-10 01:07:41 +02:00
|
|
|
@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))
|
|
|
|
]}
|
2023-08-09 11:15:43 +02:00
|
|
|
|
2023-08-10 16:19:58 +02:00
|
|
|
@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)))
|
|
|
|
]}
|
|
|
|
|
2023-08-08 18:34:40 +02:00
|
|
|
|
2020-11-29 22:12:01 +01:00
|
|
|
@section{Org-mode interaction}
|
|
|
|
|
|
|
|
This section contains some useful primitives for
|
|
|
|
@hyperlink["https://orgmode.org/"]{Org-mode} interoperability.
|
|
|
|
|
2023-08-10 16:30:02 +02:00
|
|
|
@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"))
|
|
|
|
]}
|
|
|
|
|
2023-08-10 16:46:32 +02:00
|
|
|
@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")))
|
|
|
|
]}
|
|
|
|
|
2023-08-10 18:05:22 +02:00
|
|
|
@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\"))")
|
|
|
|
]}
|
|
|
|
|
2023-08-11 15:55:09 +02:00
|
|
|
@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\"))")
|
|
|
|
]}
|
|
|
|
|
2023-08-13 21:17:32 +02:00
|
|
|
@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)))
|
|
|
|
]}
|
|
|
|
|
2023-08-14 13:32:27 +02:00
|
|
|
@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))))
|
|
|
|
]}
|
|
|
|
|
2023-08-10 16:30:02 +02:00
|
|
|
|
2020-11-29 22:12:01 +01:00
|
|
|
@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.
|
2023-08-14 14:47:09 +02:00
|
|
|
|
|
|
|
@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].
|
|
|
|
|
|
|
|
}
|
2023-08-16 08:23:47 +02:00
|
|
|
|
|
|
|
@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%].
|
|
|
|
|
|
|
|
}
|
2023-08-16 14:01:17 +02:00
|
|
|
|
|
|
|
@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)))
|
|
|
|
]}
|
2023-08-17 10:26:05 +02:00
|
|
|
|
|
|
|
@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)))
|
|
|
|
]}
|
2023-08-17 17:43:50 +02:00
|
|
|
|
|
|
|
@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))))
|
|
|
|
]}
|
2023-08-19 16:33:57 +02:00
|
|
|
|
|
|
|
@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))
|
|
|
|
]}
|
2023-08-19 16:47:49 +02:00
|
|
|
|
|
|
|
@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))
|
|
|
|
]}
|
2023-08-23 16:37:54 +02:00
|
|
|
|
|
|
|
@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))))
|
|
|
|
]}
|