docstr: Tests the refactored (Categorical-less) versions of `get_expected_states` and `get_expected_obs` together
docstr_tok: ["Tests","the","refactored","(","Categorical-less",")","versions","of","`","get_expected_states","`","and","`","get_expected_obs","`","together"]
code: def test_get_expected_states_and_obs(self):
      """
      Tests the refactored (Categorical-less) versions of `get_expected_states` and `get_expected_obs` together
      """
  
      """Test with single observation modality, single hidden state factor and single timestep"""
  
      num_obs = [3]
      num_states = [3]
      num_controls = [3]
  
      qs = utils.obj_array_uniform(num_states)
      A = utils.random_A_matrix(num_obs, num_states)
      B = utils.random_B_matrix(num_states, num_controls)
  
      policies = control.construct_policies(
          num_states, num_controls, policy_len=1
      )
  
      factor_idx = 0
      modality_idx = 0
      t_idx = 0
  
      for idx, policy in enumerate(policies):
          qs_pi = control.get_expected_states(qs, B, policy)
  
          # validation qs_pi
          qs_pi_valid = B[factor_idx][
              :, :, policies[idx][t_idx, factor_idx]
          ].dot(qs[factor_idx])
  
          self.assertTrue(
              (qs_pi[t_idx][factor_idx] == qs_pi_valid).all()
          )
  
          qo_pi = control.get_expected_obs(qs_pi, A)
  
          # validation qo_pi
          qo_pi_valid = maths.spm_dot(
              A[modality_idx], utils.to_obj_array(qs_pi_valid)
          )
  
          self.assertTrue(
              (qo_pi[t_idx][modality_idx] == qo_pi_valid).all()
          )
  
      """Test with multiple observation modalities, multiple hidden state factors and single timestep"""
  
      num_obs = [3, 3]
      num_states = [3, 3]
      num_controls = [3, 2]
  
      num_factors = len(num_states)
      num_modalities = len(num_obs)
  
      qs = utils.obj_array_uniform(num_states)
      A = utils.random_A_matrix(num_obs, num_states)
      B = utils.random_B_matrix(num_states, num_controls)
  
      policies = control.construct_policies(
          num_states, num_controls, policy_len=1
      )
  
      t_idx = 0
  
      for idx, policy in enumerate(policies):
          qs_pi = control.get_expected_states(qs, B, policy)
  
          for factor_idx in range(num_factors):
              # validation qs_pi
              qs_pi_valid = B[factor_idx][
                  :, :, policies[idx][t_idx, factor_idx]
              ].dot(qs[factor_idx])
              self.assertTrue(
                  (qs_pi[t_idx][factor_idx] == qs_pi_valid).all()
              )
  
          qo_pi = control.get_expected_obs(qs_pi, A)
  
          for modality_idx in range(num_modalities):
              # validation qo_pi
              qo_pi_valid = maths.spm_dot(A[modality_idx], qs_pi[t_idx])
              self.assertTrue(
                  (qo_pi[t_idx][modality_idx] == qo_pi_valid).all()
              )
  
      """Test with multiple observation modalities, multiple hidden state factors and multiple timesteps"""
  
      num_obs = [3, 3]
      num_states = [3, 3]
      num_controls = [3, 2]
  
      num_factors = len(num_states)
      num_modalities = len(num_obs)
  
      qs = utils.obj_array_uniform(num_states)
      A = utils.random_A_matrix(num_obs, num_states)
      B = utils.random_B_matrix(num_states, num_controls)
  
      policies = control.construct_policies(
          num_states, num_controls, policy_len=3
      )
  
      for idx, policy in enumerate(policies):
          qs_pi = control.get_expected_states(qs, B, policy)
  
          for t_idx in range(3):
              for factor_idx in range(num_factors):
                  # validation qs_pi
                  if t_idx == 0:
                      qs_pi_valid = B[factor_idx][
                          :, :, policies[idx][t_idx, factor_idx]
                      ].dot(qs[factor_idx])
                  else:
                      qs_pi_valid = B[factor_idx][
                          :, :, policies[idx][t_idx, factor_idx]
                      ].dot(qs_pi[t_idx - 1][factor_idx])
  
                  self.assertTrue(
                      (qs_pi[t_idx][factor_idx] == qs_pi_valid).all()
                  )
  
          qo_pi = control.get_expected_obs(qs_pi, A)
  
          for t_idx in range(3):
              for modality_idx in range(num_modalities):
                  # validation qo_pi
                  qo_pi_valid = maths.spm_dot(
                      A[modality_idx], qs_pi[t_idx]
                  )
                  self.assertTrue(
                      (qo_pi[t_idx][modality_idx] == qo_pi_valid).all()
                  )
  
imports: import os
  import unittest
  import numpy
  from pymdp import utils, maths
  from pymdp import control
label_desc: Use image node_id 2 for calling the TestControl obj's underlying member method code with example usage: obj.test_get_expected_states_and_obs() without return types