THE AUDITORY MODELING TOOLBOX

Applies to version: 1.6.0

View the help

Go to function

frambi_simulate
Simulate a single trial of interactions between agent and environment

Program code:

function [response, varargout] = frambi_simulate(agent, environment, options) 
%frambi_simulate Simulate a single trial of interactions between agent and environment
%   Usage: [response, logs] = frambi_simulate(agent, environment, options)
%
%   Input parameters:
%     agent      : Structure representing the FrAMBI agent. See the general description of 
%                  FrAMBI for more details. See EXP_BARUMERLI2024 for an example. 
%
%     environment: Structure representing the FrAMBI environment. See the general description 
%                  of FrAMBI for more details. See EXP_BARUMERLI2024 for an example. 
%
%     options    : Structure representing the FrAMBI options. It needs to contain
%                  the structure sample with the following fields:
% 
%                  - initialization*: Flag, if true the states of the agent 
%                    and environment will be initialized by calling 
%                    the functions defined in agent.model.initialize and
%                    environment.model.initialize.
%
%                  - validation*: Flag, if true the states of the agent 
%                    and environment will be validated by calling 
%                    FRAMBI_VALIDATE.
%
%                  - simulate*: Structure controlling the simulation with the
%                    field cycles_max describing the maximum number of 
%                    perception-action cycles in order to obtain a response
%                    of the single trial. 
% 
%   Output parameters:
%     response    : Response simulated by the agent. Depending on the 
%                   function defined in agent.model.respond, it can be a 
%                   scalar, vector, or matrix. 
%                   
%     logs  : Cell array documenting the internal states and decisions
%             in each cycle, useful for debugging and detailed analysis.
%             Each row of logs contains information about a single 
%             perception-action cycle with the following
%             fields: 
%
%             - agent*: Structure containing the state of the agent.
%
%             - environment*: Structure containing the state of the environment. 
%
%             The last row of logs contains the field response, which 
%             stores the response as returned by the function
%             agent.model.respond. 
%
%
%   FRAMBI_SIMULATE(..) simulates a single behavioral trial in an experiment
%   described as perception-action cycles. To this end, the interaction between 
%   the agent and the environment is simulated by iterating over the 
%   following sequence:
%
%   - Execute: Defined in environment.model.execute, the environment 
%     creates signals to be obeserved by the agent. 
%
%   - Observe: Defined in agent.model.observe, the agent observes the 
%     environment and creates features for the inference of the environment's hidden states. 
%
%   - Infer: Defined in agent.model.infer, the agent creates beliefs by 
%     infering the environment's hidden states. 
%
%   - Act: Defined in agent.model.act, the agent acts on the environment
%     based on the infered beliefs.
%
%   - Conclude: Defined in environment.model.conclude, the environment 
%     concludes whether to end or continue the trial. 
%
%   This simulates the mechanisms present in a single behavioral trial. 
%
%   With the trial being finished, FRAMBI_SIMULATE(..) 
%   obtains a response from the agent as defined in agent.model.respond.
%   
% 
%   See also: frambi_plot frambi_disp frambi_estimate exp_barumerli2024
%
%   References:
%     R. Barumerli and P. Majdak. FrAMBI: A Software Framework for Auditory
%     Modeling Based on Bayesian Inference. under review at Neuroinformatics,
%     2024.
%     
%
%   Url: http://amtoolbox.org/amt-1.6.0/doc/frambi/frambi_simulate.php


%   #Author: Roberto Barumerli (2023): Original implementation. 
%   #Author: Roberto Barumerli (2024): Integration in the AMT.
%   #Author: Michael Mihocic (2024): Documentation fixed. 
%   #Author: Piotr Majdak (2024): Adaptations for the AMT 1.6.

% This file is licensed unter the GNU General Public License (GPL) either 
% version 3 of the license, or any later version as published by the Free Software 
% Foundation. Details of the GPLv3 can be found in the AMT directory "licences" and 
% at <https://www.gnu.org/licenses/gpl-3.0.html>. 
% You can redistribute this file and/or modify it under the terms of the GPLv3. 
% This file is distributed without any warranty; without even the implied warranty 
% of merchantability or fitness for a particular purpose. 

% This is core of the framework.
%
% In this file, the scaffolding to run the experiment
% where agent and environment interact. 
% 
% The idea is based on two structures one for the agent and one for the
% environment. Each structure contains the state and the functions to update
% such state. The separation in two structures in important since the agent
% does not have access directly to the environment generative model.
% Instead the agent contains its internal model which is updated after the 
% interaction with the environment. 
% 
% 2022-12-06 first upload
% 2022-12-13 terminology updated

    % initalize agent and environment states
    if options.initialization
        agent.state = agent.model.initialize(agent.state);
        environment.state = environment.model.initialize(environment.state);
    end
    
    % validate agent and environemnt structures
    if options.validation
        agent.state = frambi_validate(agent.state);
        environment.state = frambi_validate(environment.state);
    end

    % check if logs are required; if not disable feature to increase speed 
    logging = nargout > 1; 

    if logging    
        logs = cell(options.simulate.cycles_max, 1);
%         logs{1, 1} = {environment.state, agent.state};
          logs{1}.agent = agent.state;
          logs{1}.environment = environment.state;          
    end

    % initalize stopping conditions
    stop = false;
    ii = 1;

    while ~stop && ~agent.state.terminate && (ii - 1 < options.simulate.cycles_max)
        % -1.a- execute - (e.g. generate binaural sound)
        %               - output is volatile (the agent uses a model to
        %               keep track of it)
        %               - the environment knows about the agent (e.g. position)
        environment.state = environment.model.execute(environment.state, agent.state.action, options);

        % -2- observation (e.g compute features and generate likelihood)
        agent.state.observation = agent.model.observe(environment.state.output, agent.state, options);
		
        % -3- perform inference with internal model (e.g. compute posterior)
        agent.state.beliefs = agent.model.infer(agent.state, options);

        % -4- decide the next action (e.g. rotate the head)
        agent.state.action = agent.model.act(agent.state, options);

        % -5- terminate loop checking the environment
        stop = environment.model.conclude(environment.state, options);

        % -6- log everything
        if logging
%             logs{ii, 1} = {agent.state, environment.state};
            logs{ii}.agent = agent.state;
            logs{ii}.environment = environment.state;
        end

        % move forward the counter
        ii = ii + 1;
    end

    % -6- additional response mechanisms (e.g. response noise)
    response = agent.model.respond(agent.state, options);

    if logging
        logs{ii-1}.response = response;
        logs = logs(1:max(1,ii-1),1); % remove empty logs
        varargout{1} = logs; 
    end
end