Finite state machine

296 views
Skip to first unread message

jorge.cla...@gmail.com

unread,
Jan 20, 2021, 7:46:23 PM1/20/21
to Bonsai Users
Dear all,

From your experience with the latest Bonsai feature set and built-in node capabilities, what is your best approach for modeling a complex finite state machine with Bonsai?





Best regards,

Jorge Cardoso

Gonçalo Lopes

unread,
Feb 7, 2021, 11:29:16 AM2/7/21
to jorge.cla...@gmail.com, Bonsai Users
Hi Jorge,

Here are links to a slide deck and worksheet which discuss this in detail:

In summary:
  • Define all external inputs and outputs to the finite-state machine using Subjects (BehaviorSubject, PublishSubject, as appropriate). For example:
image.png

Here we define Response and Led as two abstract input/output subjects, respectively, to the state machine. The Led subject is defined using the new typed subject declaration, where you can declare a subject source by right-clicking on any operator which you want to use to send outputs, and selecting for example Create Source > BehaviorSubject.
  • Inputs to the state machine can be accessed at any time using SubscribeSubject.
  • Outputs from the state machine can be broadcast at any time using MulticastSubject.
  • A single state can be modelled using the SelectMany operator:
    • The input to SelectMany is the event which triggers the state
    • The workflow inside SelectMany specifies all the behavior of the state (what is running, e.g. playing sounds, starting stimulus, sending messages, etc).
    • The outputs of SelectMany are the triggers of subsequent states. Usually for readability you want to make sure that only a single output is sent from any given state, and that the state is terminated afterwards. Operators such as First, Last, Take(1) or TakeLast(1) can be used for this purpose, followed by the WorkflowOutput operator.
  • Sequential states can be modelled simply as a chain of SelectMany operators: each output signals the exit from one state and starts execution of the next state.
  • Conditional transitions can be modelled using branching together with the Condition node to specify what paths are allowed depending on output. The Merge node should usually be used at the end to ensure all possible paths lead to the end of the trial.
  • Parallel states can be modelled simply by removing conditions from branches: both states will then execute in parallel.
  • Looping over trials can be modelled by using the Repeat operator at the end of the trial structure. This will repeat the trial logic from the beginning when the last event from the current trial is emitted.
  • ITIs or other delays can be modelled as Timer or Delay operators at various points and their duration can be varied by randomizing the duration using the Numerics package.
For example, the following workflow:

image.png

Models a simple reaction time task where a stimulus is presented (StimOn), followed by a Response (with optional timeout). Depending on whether the response is emitted or the timeout elapses, the outcome of that state is variable (true/false). The conditions ensure that either the Reward or Fail state is executed. Whichever one runs, the trial resumes via the Repeat at the end. In this example Sink nodes were used to simplify modelling of point effects such as turning LEDs on/off, but this is optional.

This is the rough outline, but several complications can be added from here. I guess the rest would depend on the specific task you would like to model.

Hope this helps.

--
You received this message because you are subscribed to the Google Groups "Bonsai Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to bonsai-users...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/bonsai-users/c98f2c01-dd8d-41cd-a285-921e1c2c3f5dn%40googlegroups.com.

Jorge Miguel Claro Cardoso

unread,
Feb 21, 2021, 1:57:40 PM2/21/21
to Gonçalo Lopes, Bonsai Users
Hi Gonçalo,

Thank you for the detailed information, I will be testing this framework in the next few days.




All the best,

Jorge Cardoso

On 7 Feb 2021, at 16:29, Gonçalo Lopes <goncal...@gmail.com> wrote:

Hi Jorge,

Here are links to a slide deck and worksheet which discuss this in detail:

In summary:
  • Define all external inputs and outputs to the finite-state machine using Subjects (BehaviorSubject, PublishSubject, as appropriate). For example:
<image.png>

Here we define Response and Led as two abstract input/output subjects, respectively, to the state machine. The Led subject is defined using the new typed subject declaration, where you can declare a subject source by right-clicking on any operator which you want to use to send outputs, and selecting for example Create Source > BehaviorSubject.
  • Inputs to the state machine can be accessed at any time using SubscribeSubject.
  • Outputs from the state machine can be broadcast at any time using MulticastSubject.
  • A single state can be modelled using the SelectMany operator:
    • The input to SelectMany is the event which triggers the state
    • The workflow inside SelectMany specifies all the behavior of the state (what is running, e.g. playing sounds, starting stimulus, sending messages, etc).
    • The outputs of SelectMany are the triggers of subsequent states. Usually for readability you want to make sure that only a single output is sent from any given state, and that the state is terminated afterwards. Operators such as First, Last, Take(1) or TakeLast(1) can be used for this purpose, followed by the WorkflowOutput operator.
  • Sequential states can be modelled simply as a chain of SelectMany operators: each output signals the exit from one state and starts execution of the next state.
  • Conditional transitions can be modelled using branching together with the Condition node to specify what paths are allowed depending on output. The Merge node should usually be used at the end to ensure all possible paths lead to the end of the trial.
  • Parallel states can be modelled simply by removing conditions from branches: both states will then execute in parallel.
  • Looping over trials can be modelled by using the Repeat operator at the end of the trial structure. This will repeat the trial logic from the beginning when the last event from the current trial is emitted.
  • ITIs or other delays can be modelled as Timer or Delay operators at various points and their duration can be varied by randomizing the duration using the Numerics package.
For example, the following workflow:
<image.png>

Models a simple reaction time task where a stimulus is presented (StimOn), followed by a Response (with optional timeout). Depending on whether the response is emitted or the timeout elapses, the outcome of that state is variable (true/false). The conditions ensure that either the Reward or Fail state is executed. Whichever one runs, the trial resumes via the Repeat at the end. In this example Sink nodes were used to simplify modelling of point effects such as turning LEDs on/off, but this is optional.

This is the rough outline, but several complications can be added from here. I guess the rest would depend on the specific task you would like to model.

Hope this helps.
Reply all
Reply to author
Forward
0 new messages