#lang racket ;;; dds/generic ;;; Provides the definition of several generic interfaces for discrete ;;; dynamical systems. (require racket/generic graph) (provide ;; Generics gen:dds ;; Functions (contract-out [dds-step-one (-> dds? any/c (set/c any/c))] [dds-step-one-annotated (-> dds? any/c (set/c (cons/c any/c any/c)))] [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?)]) ;; Predicates (contract-out [dds? (-> any/c boolean?)])) ;;; 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) (apply set-union (for/list ([s ss]) (dds-step-one dds s)))) ;;; 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)))))) ;;; A discrete dynamical system. (define-generics dds ;; Given a dds and a state, produce the next states of the dds. ;; This method has no fallback. (dds-step-one dds state) ;; Given a dds and a state, produce the next states paired with some ;; annotation. Typical usage would include including the ;; information about the update mode. This method has no fallback. (dds-step-one-annotated dds state) ;; 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) ;; 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) #:defined-predicate dds-implements? #:fallbacks [(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)))])