2020-02-23 12:19:37 +01:00
|
|
|
#lang racket
|
|
|
|
|
|
|
|
;;; dds/generic
|
|
|
|
|
|
|
|
;;; Provides the definition of several generic interfaces for discrete
|
|
|
|
;;; dynamical systems.
|
|
|
|
|
2020-02-23 18:51:57 +01:00
|
|
|
(require racket/generic graph)
|
2020-02-23 12:19:37 +01:00
|
|
|
|
|
|
|
(provide
|
|
|
|
;; Generics
|
|
|
|
gen:dds
|
|
|
|
;; Functions
|
2020-02-23 13:28:51 +01:00
|
|
|
(contract-out [dds-step-one (-> dds? any/c (set/c any/c))]
|
2020-02-23 14:11:38 +01:00
|
|
|
[dds-step-one-annotated (-> dds? any/c (set/c (cons/c any/c any/c)))]
|
2020-02-23 18:51:57 +01:00
|
|
|
[dds-step (-> dds? (set/c any/c #:kind 'dont-care) (set/c any/c))]
|
|
|
|
[dds-build-state-graph (-> dds? (set/c any/c #:kind 'dont-care) graph?)]
|
|
|
|
[dds-build-n-step-state-graph (-> dds? (set/c any/c #:kind 'dont-care) number? graph?)])
|
2020-02-23 12:19:37 +01:00
|
|
|
;; Predicates
|
|
|
|
(contract-out [dds? (-> any/c boolean?)]))
|
|
|
|
|
2020-02-23 13:28:51 +01:00
|
|
|
;;; Given a dds and a set of starting states, produce the set of
|
|
|
|
;;; states reachable in one step. This is a fallback for dds-step.
|
|
|
|
(define (fallback-dds-step dds ss)
|
2020-02-23 13:36:49 +01:00
|
|
|
(apply set-union (for/list ([s ss]) (dds-step-one dds s))))
|
2020-02-23 13:28:51 +01:00
|
|
|
|
2020-02-23 18:51:57 +01:00
|
|
|
;;; Given a dds, a set of starting states, and a range whose length
|
|
|
|
;;; determines the number of steps to run, produces the state graph
|
|
|
|
;;; reachable from the starting steps in this many steps. This is a
|
|
|
|
;;; fallback for dds-build-state-graph and dds-build-n-step-state
|
|
|
|
;;; graph.
|
|
|
|
(define (fallback-dds-build-state-graph dds states step-range)
|
|
|
|
(for/fold ([edges empty]
|
|
|
|
[current-states states]
|
|
|
|
[visited-states states]
|
|
|
|
#:result (directed-graph edges))
|
|
|
|
([i step-range]
|
|
|
|
#:break (set-empty? current-states))
|
|
|
|
(for/fold ([new-edges empty]
|
|
|
|
[new-states (set)]
|
|
|
|
#:result (values
|
|
|
|
(append edges new-edges)
|
|
|
|
(set-subtract new-states visited-states)
|
|
|
|
(set-union current-states visited-states)))
|
|
|
|
([s current-states])
|
|
|
|
(let ([ss-next (dds-step-one dds s)])
|
|
|
|
(values
|
|
|
|
(append new-edges (for/list ([s-next ss-next]) (list s s-next)))
|
|
|
|
(set-union ss-next new-states))))))
|
|
|
|
|
2020-02-23 12:19:37 +01:00
|
|
|
;;; A discrete dynamical system.
|
|
|
|
(define-generics dds
|
2020-02-23 12:21:08 +01:00
|
|
|
;; Given a dds and a state, produce the next states of the dds.
|
2020-02-23 15:05:06 +01:00
|
|
|
;; This method has no fallback.
|
2020-02-23 13:28:51 +01:00
|
|
|
(dds-step-one dds state)
|
2020-02-23 14:11:38 +01:00
|
|
|
;; Given a dds and a state, produce the next states paired with some
|
|
|
|
;; annotation. Typical usage would include including the
|
2020-02-23 15:05:06 +01:00
|
|
|
;; information about the update mode. This method has no fallback.
|
2020-02-23 14:11:38 +01:00
|
|
|
(dds-step-one-annotated dds state)
|
2020-02-23 13:28:51 +01:00
|
|
|
;; Given a dds and a set of starting states, produce the set of
|
|
|
|
;; states reachable in one step. This method falls back to running
|
|
|
|
;; dds-step-one for all states.
|
|
|
|
(dds-step dds states)
|
2020-02-23 18:51:57 +01:00
|
|
|
;; Given a dds and a set of starting states, produces the state
|
|
|
|
;; graph reachable from the starting states. This method falls back
|
|
|
|
;; to exploring the state graph with dds-step-one.
|
|
|
|
(dds-build-state-graph dds states)
|
|
|
|
;; Given a dds, a set of starting states, and a number of steps to
|
|
|
|
;; run, produces the state graph reachable from the starting states
|
|
|
|
;; in this many steps. This method falls back to exploring the
|
|
|
|
;; state graph with dds-step-one.
|
|
|
|
(dds-build-n-step-state-graph dds states nsteps)
|
2020-02-23 13:28:51 +01:00
|
|
|
|
|
|
|
#:defined-predicate dds-implements?
|
|
|
|
#:fallbacks
|
2020-02-23 18:51:57 +01:00
|
|
|
[(define dds-step fallback-dds-step)
|
|
|
|
(define (dds-build-state-graph dds states)
|
|
|
|
;; Run fallback-dds-build-state-graph with an infinite range,
|
|
|
|
;; which will make it stop only when it has explored all the
|
|
|
|
;; state graph.
|
|
|
|
(fallback-dds-build-state-graph dds states (in-naturals)))
|
|
|
|
(define (dds-build-n-step-state-graph dds states nsteps)
|
|
|
|
(fallback-dds-build-state-graph dds states (in-range nsteps)))])
|