class_docstr: The Agent class, the highest-level API that wraps together processes for action, perception, and learning under active inference.
  
  The basic usage is as follows:
  
  >>> my_agent = Agent(A = A, B = C, <more_params>)
  >>> observation = env.step(initial_action)
  >>> qs = my_agent.infer_states(observation)
  >>> q_pi, G = my_agent.infer_policies()
  >>> next_action = my_agent.sample_action()
  >>> next_observation = env.step(next_action)
  
  This represents one timestep of an active inference process. Wrapping this step in a loop with an ``Env()`` class that returns
  observations and takes actions as inputs, would entail a dynamic agent-environment interaction.
class_docstr_tok: ["The","Agent","class",",","the","highest-level","API","that","wraps","together","processes","for","action",",","perception",",","and","learning","under","active","inference",".","The","basic","usage","is","as","follows",":",">",">",">","my_agent","=","Agent","(","A","=","A",",","B","=","C",",","<","more_params",">",")",">",">",">","observation","=","env.step","(","initial_action",")",">",">",">","qs","=","my_agent.infer_states","(","observation",")",">",">",">","q_pi",",","G","=","my_agent.infer_policies","(",")",">",">",">","next_action","=","my_agent.sample_action","(",")",">",">",">","next_observation","=","env.step","(","next_action",")","This","represents","one","timestep","of","an","active","inference","process",".","Wrapping","this","step","in","a","loop","with","an","``","Env","(",")","``","class","that","returns","observations","and","takes","actions","as","inputs",",","would","entail","a","dynamic","agent-environment","interaction","."]
docstr: Update approximate posterior over hidden states by solving variational inference problem, given an observation.
  
  Parameters
  ----------
  observation: ``list`` or ``tuple`` of ints
      The observation input. Each entry ``observation[m]`` stores the index of the discrete
      observation for modality ``m``.
  
  Returns
  ---------
  qs: ``numpy.ndarray`` of dtype object
      Posterior beliefs over hidden states. Depending on the inference algorithm chosen, the resulting ``qs`` variable will have additional sub-structure to reflect whether
      beliefs are additionally conditioned on timepoint and policy.
      For example, in case the ``self.inference_algo == 'MMP' `` indexing structure is policy->timepoint-->factor, so that 
      ``qs[p_idx][t_idx][f_idx]`` refers to beliefs about marginal factor ``f_idx`` expected under policy ``p_idx`` 
      at timepoint ``t_idx``.
docstr_tok: ["Update","approximate","posterior","over","hidden","states","by","solving","variational","inference","problem",",","given","an","observation",".","Parameters","--","--","--","--","--","observation",":","``","list","``","or","``","tuple","``","of","ints","The","observation","input",".","Each","entry","``","observation","[","m","]","``","stores","the","index","of","the","discrete","observation","for","modality","``","m","``",".","Returns","--","--","--","--","-","qs",":","``","numpy.ndarray","``","of","dtype","object","Posterior","beliefs","over","hidden","states",".","Depending","on","the","inference","algorithm","chosen",",","the","resulting","``","qs","``","variable","will","have","additional","sub-structure","to","reflect","whether","beliefs","are","additionally","conditioned","on","timepoint","and","policy",".","For","example",",","in","case","the","``","self.inference_algo","==","'MMP","'","``","indexing","structure","is","policy-",">","timepoint","--",">","factor",",","so","that","``","qs","[","p_idx","]","[","t_idx","]","[","f_idx","]","``","refers","to","beliefs","about","marginal","factor","``","f_idx","``","expected","under","policy","``","p_idx","``","at","timepoint","``","t_idx","``","."]
code: def infer_states(self, observation, distr_obs=False):
      """
      Update approximate posterior over hidden states by solving variational inference problem, given an observation.
  
      Parameters
      ----------
      observation: ``list`` or ``tuple`` of ints
          The observation input. Each entry ``observation[m]`` stores the index of the discrete
          observation for modality ``m``.
  
      Returns
      ---------
      qs: ``numpy.ndarray`` of dtype object
          Posterior beliefs over hidden states. Depending on the inference algorithm chosen, the resulting ``qs`` variable will have additional sub-structure to reflect whether
          beliefs are additionally conditioned on timepoint and policy.
          For example, in case the ``self.inference_algo == 'MMP' `` indexing structure is policy->timepoint-->factor, so that
          ``qs[p_idx][t_idx][f_idx]`` refers to beliefs about marginal factor ``f_idx`` expected under policy ``p_idx``
          at timepoint ``t_idx``.
      """
  
      observation = tuple(observation) if not distr_obs else observation
  
      if not hasattr(self, "qs"):
          self.reset()
  
      if self.inference_algo == "VANILLA":
          if self.action is not None:
              empirical_prior = control.get_expected_states(
                  self.qs, self.B, self.action.reshape(1, -1)  # type: ignore
              )[0]
          else:
              empirical_prior = self.D
          qs = inference.update_posterior_states(
              self.A,
              observation,
              empirical_prior,
              **self.inference_params,
          )
      elif self.inference_algo == "MMP":
          self.prev_obs.append(observation)
          if len(self.prev_obs) > self.inference_horizon:
              latest_obs = self.prev_obs[-self.inference_horizon :]
              latest_actions = self.prev_actions[
                  -(self.inference_horizon - 1) :
              ]
          else:
              latest_obs = self.prev_obs
              latest_actions = self.prev_actions
  
          qs, F = inference.update_posterior_states_full(
              self.A,
              self.B,
              latest_obs,
              self.policies,
              latest_actions,
              prior=self.latest_belief,
              policy_sep_prior=self.edge_handling_params[
                  "policy_sep_prior"
              ],
              **self.inference_params,
          )
  
          self.F = F  # variational free energy of each policy
  
      if hasattr(self, "qs_hist"):
          self.qs_hist.append(qs)
      self.qs = qs
  
      return qs
  
imports: import warnings
  import numpy
  from pymdp import inference, control, learning
  from pymdp import utils, maths
  import copy
label_desc: Use image node_id 11 for calling the Agent obj's underlying member method code with example usage: obj.infer_states(observation, distr_obs) and returns: qs