

from typing import Any




def 			UpperCAmelCase__				(			_A      : list	,      _A      : list	,      _A      : dict	,      _A      : dict	,      _A      : dict	,      ):





  '''simple docstring'''







  _validation(
      _A	,      _A	,      _A	,      _A	,      _A	,      )
  # Creates data structures and fill initial step
  a__  ={}
  a__  ={}
  for state in states_space:
    a__  =observations_space[0]
    a__  =(
        initial_probabilities[state] * emission_probabilities[state][observation]
    )
    a__  =None

  # Fills the data structure with the probabilities of
  # different transitions and pointers to previous states
  for o in range(1	,      len(_A							)							):
    a__  =observations_space[o]
    a__  =observations_space[o - 1]
    for state in states_space:
      # Calculates the argmax for probability function
      a__  =''''''
      a__  =-1
      for k_state in states_space:
        a__  =(
            probabilities[(k_state, prior_observation)]
            * transition_probabilities[k_state][state]
            * emission_probabilities[state][observation]
        )
        if probability > max_probability:
          a__  =probability
          a__  =k_state

            # Update probabilities and pointers dicts
      a__  =(
          probabilities[(arg_max, prior_observation)]
          * transition_probabilities[arg_max][state]
          * emission_probabilities[state][observation]
      )

      a__  =arg_max

    # The final observation
  a__  =observations_space[len(_A							) - 1]

  # argmax for given final observation
  a__  =''''''
  a__  =-1
  for k_state in states_space:
    a__  =probabilities[(k_state, final_observation)]
    if probability > max_probability:
      a__  =probability
      a__  =k_state
  a__  =arg_max

  # Process pointers backwards
  a__  =last_state
  a__  =[]
  for o in range(len(_A							) - 1	,      -1	,      -1							):
    result.append(_A							)
    a__  =pointers[previous, observations_space[o]]
  result.reverse()

  return result




def 			UpperCAmelCase__				(			_A      : Any	,      _A      : Any	,      _A      : Any	,      _A      : Any	,      _A      : Any	,      ):





  '''simple docstring'''







  _validate_not_empty(
      _A	,      _A	,      _A	,      _A	,      _A	,      )
  _validate_lists(_A	,      _A							)
  _validate_dicts(
      _A	,      _A	,      _A							)




def 			UpperCAmelCase__				(			_A      : Any	,      _A      : Any	,      _A      : Any	,      _A      : Any	,      _A      : Any	,      ):





  '''simple docstring'''







  if not all(
      [
          observations_space,
          states_space,
          initial_probabilities,
          transition_probabilities,
          emission_probabilities,
      ]							):
    raise ValueError('''There\'s an empty parameter'''							)




def 			UpperCAmelCase__				(			_A      : Any	,      _A      : Any							):





  '''simple docstring'''







  _validate_list(_A	,      '''observations_space'''							)
  _validate_list(_A	,      '''states_space'''							)




def 			UpperCAmelCase__				(			_A      : Any	,      _A      : str							):





  '''simple docstring'''







  if not isinstance(_object	,      _A							):
    a__  =F"""{var_name} must be a list"""
    raise ValueError(_A							)
  else:
    for x in _object:
      if not isinstance(_A	,      _A							):
        a__  =F"""{var_name} must be a list of strings"""
        raise ValueError(_A							)




def 			UpperCAmelCase__				(			_A      : Any	,      _A      : Any	,      _A      : Any	,      ):





  '''simple docstring'''







  _validate_dict(_A	,      '''initial_probabilities'''	,      _A							)
  _validate_nested_dict(_A	,      '''transition_probabilities'''							)
  _validate_nested_dict(_A	,      '''emission_probabilities'''							)




def 			UpperCAmelCase__				(			_A      : Any	,      _A      : str							):





  '''simple docstring'''







  _validate_dict(_object	,      _A	,      _A							)
  for x in _object.values():
    _validate_dict(_A	,      _A	,      _A	,      _A							)




def 			UpperCAmelCase__				(			_A      : Any	,      _A      : str	,      _A      : type	,      _A      : bool = False							):





  '''simple docstring'''







  if not isinstance(_object	,      _A							):
    a__  =F"""{var_name} must be a dict"""
    raise ValueError(_A							)
  if not all(isinstance(_A	,      _A							) for x in _object							):
    a__  =F"""{var_name} all keys must be strings"""
    raise ValueError(_A							)
  if not all(isinstance(_A	,      _A							) for x in _object.values()							):
    a__  ='''nested dictionary ''' if nested else ''''''
    a__  =F"""{var_name} {nested_text}all values must be {value_type.__name__}"""
    raise ValueError(_A							)


if __name__ == "__main__":
       from doctest import testmod

       testmod()



from __future__ import annotations




def 			UpperCAmelCase__				(			_A      : float	,      _A      : float	,      _A      : float	,      ):





  '''simple docstring'''







  if (electron_conc, hole_conc, intrinsic_conc).count(0							) != 1:
    raise ValueError('''You cannot supply more or less than 2 values'''							)
  elif electron_conc < 0:
    raise ValueError('''Electron concentration cannot be negative in a semiconductor'''							)
  elif hole_conc < 0:
    raise ValueError('''Hole concentration cannot be negative in a semiconductor'''							)
  elif intrinsic_conc < 0:
    raise ValueError(
        '''Intrinsic concentration cannot be negative in a semiconductor'''							)
  elif electron_conc == 0:
    return (
        "electron_conc",
        intrinsic_conc**2 / hole_conc,
    )
  elif hole_conc == 0:
    return (
        "hole_conc",
        intrinsic_conc**2 / electron_conc,
    )
  elif intrinsic_conc == 0:
    return (
        "intrinsic_conc",
        (electron_conc * hole_conc) ** 0.5,
    )
  else:
    return (-1, -1)


if __name__ == "__main__":
       import doctest

       doctest.testmod()
