489 lines
15 KiB
Racket
489 lines
15 KiB
Racket
#lang scribble/manual
|
|
@(require scribble/example racket/sandbox
|
|
(for-label typed/racket/base
|
|
(submod "../tbn.rkt" typed)
|
|
"../networks.rkt"
|
|
"../utils.rkt"
|
|
"../functions.rkt"
|
|
"../dynamics.rkt"))
|
|
|
|
@(define tbn-evaluator
|
|
(parameterize ([sandbox-output 'string]
|
|
[sandbox-error-output 'string]
|
|
[sandbox-memory-limit 500])
|
|
(make-evaluator 'typed/racket #:requires '((submod "tbn.rkt" typed)))))
|
|
|
|
@(define-syntax-rule (ex . args)
|
|
(examples #:eval tbn-evaluator . args))
|
|
|
|
@(define-syntax-rule (deftypeform . args)
|
|
(defform #:kind "type" . args))
|
|
|
|
@(define-syntax-rule (deftype . args)
|
|
(defidform #:kind "type" . args))
|
|
|
|
@title[#:tag "tbn"]{dds/tbn: Threshold and Sign Boolean Networks (TBN and SBN)}
|
|
|
|
@defmodule[(submod dds/tbn typed)]
|
|
|
|
@section{TBFs and states}
|
|
|
|
This module defines threshold Boolean networks (TBN), as well as sign
|
|
Boolean networks (SBN). The update functions in such networks are
|
|
respectively @seclink["tbf" #:doc '(lib
|
|
"dds/scribblings/dds.scrbl")]{threshold Boolean functions} and sign
|
|
Boolean functions.
|
|
|
|
@defproc[(apply-tbf-to-state [a-tbf TBF] [st (State (U Zero One))])
|
|
(U Zero One)]{
|
|
|
|
Applies a TBF to a state.
|
|
|
|
The values of the variables of the state are ordered by
|
|
@racket[hash-map] and fed to the TBF in order. The number of the
|
|
inputs of the TBF must match the number of variables in the state.
|
|
|
|
@ex[
|
|
(require "functions.rkt")
|
|
(apply-tbf-to-state (tbf #(1 1) 1) (hash 'x1 0 'x2 1))
|
|
]}
|
|
|
|
@defstruct*[tbf/state ([weights (VariableMapping Real)]
|
|
[threshold Real])]{
|
|
|
|
A state TBF is a @racket[TBF] with named inputs. A state TBF can be
|
|
applied to states in an unambiguous ways.
|
|
|
|
}
|
|
|
|
@deftype[TBF/State]{
|
|
|
|
The type of the instances of @racket[tbf/state].
|
|
|
|
}
|
|
|
|
@deftogether[(@defproc[(tbf/state-w [tbfs TBF/State]) (VariableMapping Real)]
|
|
@defproc[(tbf/state-θ [tbfs TBF/State]) Real])]{
|
|
|
|
Shorter synonyms for field accessors of @racket[tbf/state].
|
|
|
|
@ex[
|
|
(let ([tbfs (tbf/state (hash 'a 1 'b 1) 1)])
|
|
(values (tbf/state-w tbfs)
|
|
(tbf/state-θ tbfs)))
|
|
]}
|
|
|
|
@defproc[(make-tbf/state [pairs (Listof (Pairof Variable Real))]
|
|
[threshold Real])
|
|
TBF/State]{
|
|
|
|
Makes a @racket[TBF/State] from a list of pairs of names of variables
|
|
and weights, as well as a threshold.
|
|
|
|
@ex[
|
|
(make-tbf/state '((x1 . 1) (x2 . 1)) 1)
|
|
]}
|
|
|
|
@defproc[(sbf/state? [tbfs TBF/State]) Boolean]{
|
|
|
|
A state sign Boolean function (SBF) is a @racket[TBF/State] whose
|
|
threshold is 0.
|
|
|
|
@ex[
|
|
(sbf/state? (tbf/state (hash 'a -1 'b 1) 0))
|
|
(sbf/state? (tbf/state (hash 'a -1 'b 1) 1))
|
|
]}
|
|
|
|
@defproc[(apply-tbf/state [tbfs TBF/State]
|
|
[st (State (U Zero One))])
|
|
(U Zero One)]{
|
|
|
|
Applies a @racket[TBF/State] to its inputs given by the state
|
|
@racket[st].
|
|
|
|
Applying a TBF consists in multiplying the weights by the
|
|
corresponding inputs and comparing the sum of the products to
|
|
the threshold.
|
|
|
|
This function is similar to @racket[apply-tbf], but because it applies
|
|
a @racket[TBF/State] to a @racket[(State (U Zero One))], it avoids
|
|
potential mismatches between weights and the corresponding
|
|
input values.
|
|
|
|
@ex[
|
|
(apply-tbf/state (tbf/state (hash 'a 2 'b -2) 1)
|
|
(hash 'a 1 'b 0 'c 1))
|
|
]}
|
|
|
|
@section{Reading and printing TBFs and SBFs}
|
|
|
|
@defproc[(lists+vars->tbfs/state [vars (Listof Variable)]
|
|
[lsts (Listof (Listof Real))])
|
|
(Listof TBF/State)]{
|
|
|
|
Reads a list of @racket[TBF/State] from a list of list of
|
|
@racket[Real]s.
|
|
|
|
The last element of each list is taken to be the threshold of the
|
|
TBFs, and the rest of the elements are taken to be the weights.
|
|
|
|
@ex[
|
|
(lists+vars->tbfs/state '(x y) '((1 2 3) (1 1 2)))
|
|
]}
|
|
|
|
@defproc[(lists+headers->tbfs/state [lsts+headers (Pairof (Listof Variable) (Listof (Listof Real)))])
|
|
(Listof TBF/State)]{
|
|
|
|
Like @racket[lists+vars->tbfs/state], but the names of the variables
|
|
are taken from the first line of @racket[lsts+headers].
|
|
|
|
All the lines in @racket[lsts+headers] are assumed to be of the same
|
|
lenght, which means in particular that the last element of the first
|
|
line (the threshold column) is discarded.
|
|
|
|
@ex[
|
|
(lists+headers->tbfs/state '((x y f) (1 2 3) (1 1 2)))
|
|
]}
|
|
|
|
@defproc[(lists->tbfs/state [lsts (Listof (Liostf Real))])
|
|
(Listof TBF/State)]{
|
|
|
|
Like @racket[lists+vars->tbfs/state], but the names of the variables
|
|
are generated as @tt{xi}, where @italic{i} is the index of the
|
|
variable, starting from 0.
|
|
|
|
@ex[
|
|
(lists->tbfs/state '((1 2 3) (1 1 2)))
|
|
]}
|
|
|
|
@defproc[(lists->tbfs/state/opt-headers
|
|
[lsts (Listof (Listof (U Variable Real)))]
|
|
[#:headers hdr Boolean])
|
|
(Listof TBF/State)]{
|
|
|
|
This function allows selecting between @racket[lists->tbfs/state] and
|
|
@racket[lists+headers->tbfs/state] based on the value of @racket[hdr].
|
|
If @racket[hdr] is @racket[#f], then @racket[lists->tbfs/state] is
|
|
applied to @racket[lsts], otherwise @racket[lists+headers->tbfs/state]
|
|
is applied.
|
|
|
|
@ex[
|
|
(lists->tbfs/state/opt-headers '((1 2 3) (1 1 2)) #:headers #f)
|
|
(lists->tbfs/state/opt-headers '((x y f) (1 2 3) (1 1 2)) #:headers #t)
|
|
]}
|
|
|
|
@deftogether[(@defproc[(lists+vars->sbfs/state [vars (Listof Variable)]
|
|
[lsts (Listof (Listof Real))])
|
|
(Listof TBF/State)]
|
|
@defproc[(lists+headers->sbfs/state
|
|
[lsts (Pairof (Listof Variable) (Listof (Listof Real)))])
|
|
(Listof TBF/State)]
|
|
@defproc[(lists->sbfs/state [lsts (Listof (Listof Real))])
|
|
(Listof TBF/State)])]{
|
|
|
|
Like the corresponding TBF-related functions, but which create SBFs.
|
|
In other words, the input lists are treated as lists of weights, and
|
|
the thresholds are set to 0.
|
|
|
|
@ex[
|
|
(lists+vars->sbfs/state '(x y) '((1 2) (1 1)))
|
|
(lists+headers->sbfs/state '((x y) (1 2) (1 1)))
|
|
(lists->sbfs/state '((1 2) (1 1)))
|
|
]}
|
|
|
|
@defproc[(read-org-tbfs/state [str String]) (Listof TBF/State)]{
|
|
|
|
Reads a list of @racket[TBF/State] from an Org-mode string containing
|
|
a sexp, containing a list of lists of numbers. As in
|
|
@racket[lists->tbfs/state], the last element of each list is taken to
|
|
be the threshold of the TBF, and the rest of the elements are taken to
|
|
be the weights.
|
|
|
|
Similarly to @racket[lists->tbfs/state], the names of the variables
|
|
are generated as @tt{xi}, where @italic{i} is the index of the
|
|
variable, starting from 0.
|
|
|
|
@ex[
|
|
(read-org-tbfs/state "((1 2 3) (1 1 2))")
|
|
]}
|
|
|
|
@defproc[(read-org-tbfs/state+headers [str String]) (Listof TBF/State)]{
|
|
|
|
Like @racket[read-org-tbfs/state], but the first list in @racket[str]
|
|
is taken to contain the names of the variables, similarly to
|
|
@racket[lists+headers->tbfs/state].
|
|
|
|
@ex[
|
|
(read-org-tbfs/state+headers "((a b f) (1 2 3) (1 1 2))")
|
|
]}
|
|
|
|
@defproc[(tbfs/state->lists [tbfs (Listof TBF/State)]) (Listof (Listof Real))]{
|
|
|
|
Given a list of @racket[TBF/State], produces a sexp that Org-mode can
|
|
interpret as a table.
|
|
|
|
All @racket[TBF/State] in the list must have the same inputs.
|
|
The function does not check this property.
|
|
|
|
@ex[
|
|
(tbfs/state->lists (list (tbf/state (hash 'a 1 'b 2) 3)
|
|
(tbf/state (hash 'a -2 'b 1) 1)))
|
|
]}
|
|
|
|
@defproc[(tbfs/state->lists+headers [tbfs (Listof TBF/State)])
|
|
(Pairof (Listof Variable) (Listof (Listof Real)))]{
|
|
|
|
Like @racket[tbfs/state->lists+headers], but the first list of the
|
|
result is the list of input names of the first @racket[TBF/State] in
|
|
@racket[tbfs]. The last element of this first list is @racket['θ] and
|
|
corresponds to the column giving the thresholds of the TBFs.
|
|
|
|
@ex[
|
|
(tbfs/state->lists+headers
|
|
(list (tbf/state (hash 'a 1 'b 2) 3)
|
|
(tbf/state (hash 'a -2 'b 1) 1)))
|
|
]}
|
|
|
|
@defproc[(sbfs/state->lists [sbfs (Listof TBF/State)])
|
|
(Listof (Listof Real))]{
|
|
|
|
Like @racket[tbfs/state->lists], but the thresholds are omitted.
|
|
|
|
@ex[
|
|
(sbfs/state->lists (list (tbf/state (hash 'a 1 'b 2) 0)
|
|
(tbf/state (hash 'a -2 'b 1) 0)))
|
|
]
|
|
|
|
Note that this function just drops the threshold, without checking
|
|
whether it is actually 0:
|
|
|
|
@ex[
|
|
(sbfs/state->lists (list (tbf/state (hash 'a 1 'b 2) 3)))
|
|
]}
|
|
|
|
@defproc[(sbfs/state->lists+headers [sbfs (Listof TBF/State)])
|
|
(Pairof (Listof Variable) (Listof (Listof Real)))]{
|
|
|
|
Like @racket[sbfs/state->lists], but also shows the names of the
|
|
variables as column headers.
|
|
|
|
@ex[
|
|
(sbfs/state->lists+headers (list (tbf/state (hash 'a 1 'b 2) 0)
|
|
(tbf/state (hash 'a -2 'b 1) 0)))
|
|
]}
|
|
|
|
@section{Tabulating TBFs and SBFs}
|
|
|
|
@defproc[(tabulate-tbfs/state [tbfs (Listof TBF/State)]) (Listof (Listof Real))]{
|
|
|
|
Tabulates a list of @racket[TBF/State].
|
|
|
|
As in the case of @racket[tbf-tabulate*], the result is a list of
|
|
lists giving the truth tables of the given TBFs. The first elements
|
|
of each row give the values of the inputs, while the last elements
|
|
give the values of each function corresponding to the input.
|
|
|
|
All the TBFs must have exactly the same inputs. This function does
|
|
not check this property.
|
|
|
|
@ex[
|
|
(tabulate-tbfs/state
|
|
(list (tbf/state (hash 'a 1 'b 2) 2)
|
|
(tbf/state (hash 'a -2 'b 2) 1)))
|
|
]}
|
|
|
|
@defproc[(tabulate-tbfs/state+headers [tbfs (Listof TBF/State)])
|
|
(Pairof (Listof Variable)
|
|
(Listof (Listof Real)))]{
|
|
|
|
Like @racket[tabulate-tbfs/state], but the first list of the result is
|
|
a gives the names of the variables appearing in the inputs of
|
|
@racket[(car tbfs)], followed by function names. The function names
|
|
are generated as @tt{fi}, where @tt{i} is the number of the TBF in
|
|
the list.
|
|
|
|
@ex[
|
|
(tabulate-tbfs/state+headers
|
|
(list (tbf/state (hash 'a 1 'b 2) 2)
|
|
(tbf/state (hash 'a -2 'b 2) 1)))
|
|
]}
|
|
|
|
@deftogether[(@defproc[(tabulate-tbf/state [tbf TBF/State])
|
|
(Listof (Listof Real))]
|
|
@defproc[(tabulate-tbf/state+headers [tbf TBF/State])
|
|
(Pairof (Listof Variable) (Listof (Listof Real)))])]{
|
|
|
|
Like @racket[tabulate-tbfs/state] and
|
|
@racket[tabulate-tbfs/state+headers], but only tabulate single TBFs.
|
|
|
|
@ex[
|
|
(tabulate-tbf/state (tbf/state (hash 'a 1 'b 2) 2))
|
|
(tabulate-tbf/state+headers (tbf/state (hash 'a 1 'b 2) 2))
|
|
]}
|
|
|
|
@section{TBNs and SBNs}
|
|
|
|
@deftype[TBN]{
|
|
|
|
The type of a TBN, i.e. a mapping assigning to each variable
|
|
a @racket[TBF/State].
|
|
|
|
}
|
|
|
|
@defproc[(sbn? [tbn TBN]) Boolean]{
|
|
|
|
A SBN is a @racket[TBN] in which all @racket[TBF/State]s satisfy
|
|
@racket[sbf/state?].
|
|
|
|
All functions in @racket[tbn] must only reference variables appearing
|
|
in the network. This function does not check this condition.
|
|
|
|
@ex[
|
|
(let ([f1 (tbf/state (hash 'a -1 'b 1) 0)]
|
|
[f2 (tbf/state (hash 'a -1 'b 1) 1)])
|
|
(values (sbn? (hash 'a f1 'b f1))
|
|
(sbn? (hash 'a f1 'b f2))))
|
|
]}
|
|
|
|
@defproc[(tbn->network [tbn TBN]) (Network (U Zero One))]{
|
|
|
|
Constructs a @racket[Network] out of the given @racket[tbn].
|
|
|
|
@ex[
|
|
(require (only-in "networks.rkt" update))
|
|
(let* ([tbn-form (hash 'a (tbf/state (hash 'a -1 'b 1) 0)
|
|
'b (tbf/state (hash 'a -1 'b 1) 1))]
|
|
[tbn (tbn->network tbn-form)]
|
|
[s (hash 'a 0 'b 1)])
|
|
(update tbn s '(a b)))
|
|
]}
|
|
|
|
@defproc[(parse-org-tbn [tab (Listof (Listof (U Symbol Real)))]
|
|
[#:headers headers Boolean #t]
|
|
[#:func-names func-names Boolean #t])
|
|
TBN]{
|
|
|
|
Reads a TBN from a list of lists of numbers or symbols, which may
|
|
represent an Org-mode table. As in @racket[lists->tbfs/state], the
|
|
last element of each list is taken to be the threshold of the TBF, and
|
|
the rest of the elements are taken to be the weights.
|
|
|
|
If @racket[headers] is @racket[#t], the names of the variables to
|
|
appear as the inputs of the TBF are taken from the first list.
|
|
The last element of this list (corresponding to the column giving the
|
|
threshold) is discarded. If @racket[headers] is @racket[#f], the
|
|
names of the variables are generated as @tt{xi}, where @tt{i} is
|
|
the index of the variable.
|
|
|
|
If @racket[func-names] is @racket[#t], the first element in every row
|
|
except the first one are taken to be the name of the variable to which
|
|
the TBF should be associated. If @racket[func-names] is @racket[#f],
|
|
the functions are assigned to variables in lexicographic order.
|
|
|
|
@racket[func-names] cannot be @racket[#t] if @racket[headers] is
|
|
@racket[#f]. The function does not check this condition.
|
|
|
|
This is a helper function for @racket[read-org-tbn] and
|
|
@racket[read-org-sbn].
|
|
|
|
@ex[
|
|
(parse-org-tbn '((1 2 3) (3 2 1)) #:headers #f #:func-names #f)
|
|
(parse-org-tbn '((a b θ) (1 2 3) (3 2 1)) #:headers #t #:func-names #f)
|
|
(parse-org-tbn '((dummy a b θ) (b 3 2 1) (a 1 2 3)) #:headers #t #:func-names #t)
|
|
]}
|
|
|
|
@defproc[(read-org-tbn [str String]
|
|
[#:headers headers Boolean #t]
|
|
[#:func-names func-names Boolean #t])
|
|
TBN]{
|
|
|
|
Reads a TBN from an string containing a sexp, containing a list of
|
|
lists of numbers and possibly symbols. This string may be produced by
|
|
Org-mode.
|
|
|
|
As in @racket[lists->tbfs/state], the last element of each list is
|
|
taken to be the threshold of the TBFs, and the rest of the elements
|
|
are taken to be the weights.
|
|
|
|
As in @racket[parse-org-tbn], if @racket[headers] is @racket[#t], the
|
|
names of the variables to appear as the inputs of the TBF are taken
|
|
from the first list. The last element of this list is discarded.
|
|
If @racket[headers] is @racket[#f], the names of the variables are
|
|
generated as @tt{xi}, where @tt{i} is the index of the variable.
|
|
|
|
If @racket[func-names] is @racket[#t], the first element in every row
|
|
except the first one, are taken to be the name of the variable to
|
|
which the TBF should be associated. If @racket[func-names] is
|
|
@racket[#f], the functions are assigned to variables in
|
|
alphabetical order.
|
|
|
|
As in @racket[parse-org-tbn], @racket[func-names] cannot be
|
|
@racket[#t] if @racket[headers] is @racket[#f]. The function does not
|
|
check this condition.
|
|
|
|
@ex[
|
|
(read-org-tbn "((\"-\" \"x\" \"y\" \"θ\") (\"y\" -1 0 -1) (\"x\" 0 -1 -1))")
|
|
]}
|
|
|
|
@defproc[(read-org-sbn [str String]
|
|
[#:headers headers Boolean #t]
|
|
[#:func-names func-names Boolean #t])
|
|
TBN]{
|
|
|
|
Like @racket[read-org-tbn], but reads an SBN from the input string,
|
|
i.e. all the numbers are taken to be the weights, and the threshold is
|
|
set to 0.
|
|
|
|
@ex[
|
|
(read-org-sbn "((\"-\" \"x\" \"y\") (\"y\" -1 0) (\"x\" 0 -1))")
|
|
]}
|
|
|
|
@defproc[(build-tbn-state-graph [tbn TBN]) Graph]{
|
|
|
|
Builds the state graph of a @racket[TBN].
|
|
|
|
This function constructs a @racket[(Network (U Zero One))] from
|
|
@racket[tbn], then builds the state graph of its synchronous dynamics,
|
|
and pretty-prints the node labels.
|
|
|
|
@ex[
|
|
(require (only-in "utils.rkt" dotit))
|
|
(dotit (build-tbn-state-graph
|
|
(hash 'a (tbf/state (hash 'a -1 'b 1) 0)
|
|
'b (tbf/state (hash 'a -1 'b 1) 1))))
|
|
]}
|
|
|
|
@defproc[(normalized-tbn? [tbn TBN]) Boolean]{
|
|
|
|
Checks whether @racket[tbn] is normalized: whether all of the
|
|
functions have the same inputs, and whether these inputs are exactly
|
|
the variables of @racket[tbn].
|
|
|
|
@ex[
|
|
(normalized-tbn?
|
|
(hash 'x (tbf/state (hash 'x 0 'y -1) -1)
|
|
'y (tbf/state (hash 'x -1 'y 0) -1)))
|
|
(normalized-tbn?
|
|
(hash 'x (tbf/state (hash 'x 0 ) -1)
|
|
'y (tbf/state (hash 'y 0) -1)))
|
|
]}
|
|
|
|
@section{Miscellaneous utilities}
|
|
|
|
@defproc[(group-truth-table-by-nai [tt (Listof (Listof Integer))])
|
|
(Listof (Listof (Listof Integer)))]{
|
|
|
|
Given the truth table @racket[tt] of a Boolean function, groups the
|
|
lines by the @italic{N}umber of @italic{A}ctivated @italic{I}nputs—the
|
|
number of inputs which are 1 in the input vector.
|
|
|
|
@ex[
|
|
(group-truth-table-by-nai '((0 0 0 1)
|
|
(0 0 1 1)
|
|
(0 1 0 0)
|
|
(0 1 1 1)
|
|
(1 0 0 0)
|
|
(1 0 1 0)
|
|
(1 1 0 1)
|
|
(1 1 1 0)))
|
|
]}
|