code: def core_act(
      self,
      *,
      states,
      internals,
      auxiliaries,
      parallel,
      deterministic,
      independent,
  ):
      zero_float = tf_util.constant(value=0.0, dtype="float")
  
      # On-policy policy/baseline horizon (TODO: retrieve from buffer!)
      assertions = list()
      if self.config.create_tf_assertions:
          zero = tf_util.constant(value=0, dtype="int")
          past_horizon = tf.math.maximum(
              x=self.policy.past_horizon(on_policy=True),
              y=self.baseline.past_horizon(on_policy=True),
          )
          assertions.append(
              tf.debugging.assert_equal(
                  x=past_horizon,
                  y=zero,
                  message="Policy/baseline on-policy horizon currently not supported.",
              )
          )
          if not independent:
              false = tf_util.constant(value=False, dtype="bool")
              assertions.append(
                  tf.debugging.assert_equal(
                      x=deterministic,
                      y=false,
                      message="Invalid combination deterministic and not independent.",
                  )
              )
  
      # Variable noise
      if len(self.policy.trainable_variables) > 0 and (
          (
              not independent
              and not self.variable_noise.is_constant(value=0.0)
          )
          or (independent and self.variable_noise.final_value() != 0.0)
      ):
          if independent:
              variable_noise = tf_util.constant(
                  value=self.variable_noise.final_value(),
                  dtype=self.variable_noise.spec.type,
              )
          else:
              variable_noise = self.variable_noise.value()
  
          def no_variable_noise():
              return [
                  tf.zeros_like(input=var)
                  for var in self.policy.trainable_variables
              ]
  
          def apply_variable_noise():
              variable_noise_tensors = list()
              for variable in self.policy.trainable_variables:
                  noise = tf.random.normal(
                      shape=tf_util.shape(x=variable),
                      mean=0.0,
                      stddev=variable_noise,
                      dtype=self.variable_noise.spec.tf_type(),
                  )
                  if variable.dtype != tf_util.get_dtype(type="float"):
                      noise = tf.cast(x=noise, dtype=variable.dtype)
                  assignment = variable.assign_add(
                      delta=noise, read_value=False
                  )
                  with tf.control_dependencies(
                      control_inputs=(assignment,)
                  ):
                      variable_noise_tensors.append(
                          tf_util.identity(input=noise)
                      )
              return variable_noise_tensors
  
          variable_noise_tensors = tf.cond(
              pred=tf.math.logical_or(
                  x=deterministic,
                  y=tf.math.equal(x=variable_noise, y=zero_float),
              ),
              true_fn=no_variable_noise,
              false_fn=apply_variable_noise,
          )
  
      else:
          variable_noise_tensors = list()
  
      with tf.control_dependencies(
          control_inputs=(variable_noise_tensors + assertions)
      ):
          dependencies = list()
  
          # State preprocessing (after variable noise)
          for name in self.states_spec:
              if name in self.state_preprocessing:
                  states[name] = self.state_preprocessing[name].apply(
                      x=states[name],
                      deterministic=deterministic,
                      independent=independent,
                  )
  
          # Policy act (after variable noise)
          batch_size = tf_util.cast(
              x=tf.shape(input=states.value())[0], dtype="int"
          )
          starts = tf.range(
              batch_size, dtype=tf_util.get_dtype(type="int")
          )
          lengths = tf_util.ones(
              shape=tf.expand_dims(input=batch_size, axis=0),
              dtype="int",
          )
          horizons = tf.stack(values=(starts, lengths), axis=1)
          next_internals = TensorDict()
          actions, next_internals["policy"] = self.policy.act(
              states=states,
              horizons=horizons,
              internals=internals["policy"],
              auxiliaries=auxiliaries,
              deterministic=deterministic,
              independent=independent,
          )
          if isinstance(actions, tf.Tensor):
              dependencies.append(actions)
          else:
              dependencies.extend(actions.flatten())
  
          # Baseline internals (after variable noise)
          # TODO: shouldn't be required for independent-act
          if (
              self.separate_baseline
              and len(self.internals_spec["baseline"]) > 0
          ):
              next_internals["baseline"] = self.baseline.next_internals(
                  states=states,
                  horizons=horizons,
                  internals=internals["baseline"],
                  actions=actions,
                  deterministic=deterministic,
                  independent=independent,
              )
          else:
              next_internals["baseline"] = TensorDict()
          dependencies.extend(next_internals.flatten())
  
      # Reverse variable noise (after policy act)
      if len(variable_noise_tensors) > 0:
          with tf.control_dependencies(control_inputs=dependencies):
              dependencies = list()
  
              def apply_variable_noise():
                  assignments = list()
                  for var, noise in zip(
                      self.policy.trainable_variables,
                      variable_noise_tensors,
                  ):
                      assignments.append(
                          var.assign_sub(delta=noise, read_value=False)
                      )
                  return tf.group(*assignments)
  
              dependencies.append(
                  tf.cond(
                      pred=tf.math.equal(
                          x=variable_noise, y=zero_float
                      ),
                      true_fn=tf.no_op,
                      false_fn=apply_variable_noise,
                  )
              )
  
      # Exploration
      if (
          not independent
          and (
              isinstance(self.exploration, dict)
              or not self.exploration.is_constant(value=0.0)
          )
      ) or (
          independent
          and (
              isinstance(self.exploration, dict)
              or self.exploration.final_value() != 0.0
          )
      ):
          # Global exploration
          if not isinstance(self.exploration, dict):
              # exploration_fns = dict()
              if not independent and not self.exploration.is_constant(
                  value=0.0
              ):
                  exploration = self.exploration.value()
              elif (
                  independent and self.exploration.final_value() != 0.0
              ):
                  exploration = tf_util.constant(
                      value=self.exploration.final_value(),
                      dtype=self.exploration.spec.type,
                  )
              else:
                  assert False
  
          float_dtype = tf_util.get_dtype(type="float")
          for name, spec, action in self.actions_spec.zip_items(
              actions
          ):
              # Per-action exploration
              if isinstance(self.exploration, dict):
                  if name not in self.exploration:
                      continue
                  elif not independent and not self.exploration[
                      name
                  ].is_constant(value=0.0):
                      exploration = self.exploration.value()
                  elif (
                      independent
                      and self.exploration[name].final_value() != 0.0
                  ):
                      exploration = tf_util.constant(
                          value=self.exploration[name].final_value(),
                          dtype=self.exploration[name].spec.type,
                      )
                  else:
                      continue
  
              # Apply exploration
              if spec.type == "bool":
                  # Bool action: if uniform[0, 1] < exploration, then uniform[True, False]
  
                  def apply_exploration():
                      shape = tf_util.cast(
                          x=tf.shape(input=action), dtype="int"
                      )
                      half = tf_util.constant(value=0.5, dtype="float")
                      random_action = (
                          tf.random.uniform(
                              shape=shape, dtype=float_dtype
                          )
                          < half
                      )
                      is_random = (
                          tf.random.uniform(
                              shape=shape, dtype=float_dtype
                          )
                          < exploration
                      )
                      return tf.where(
                          condition=is_random, x=random_action, y=action
                      )
  
              elif spec.type == "int" and spec.num_values is not None:
                  if self.config.enable_int_action_masking:
                      # Masked action: if uniform[0, 1] < exploration, then uniform[unmasked]
                      # (Similar code as for RandomModel.core_act)
  
                      def apply_exploration():
                          shape = tf_util.cast(
                              x=tf.shape(input=action), dtype="int"
                          )
                          mask = auxiliaries[name]["mask"]
                          choices = tf_util.constant(
                              value=list(range(spec.num_values)),
                              dtype=spec.type,
                              shape=(
                                  tuple(1 for _ in spec.shape)
                                  + (1, spec.num_values)
                              ),
                          )
                          one = tf_util.constant(
                              value=1, dtype="int", shape=(1,)
                          )
                          multiples = tf.concat(
                              values=(shape, one), axis=0
                          )
                          choices = tf.tile(
                              input=choices, multiples=multiples
                          )
                          choices = tf.boolean_mask(
                              tensor=choices, mask=mask
                          )
                          num_valid = tf.math.count_nonzero(
                              input=mask, axis=(spec.rank + 1)
                          )
                          num_valid = tf.reshape(
                              tensor=num_valid, shape=(-1,)
                          )
                          masked_offset = tf.math.cumsum(
                              x=num_valid, axis=0, exclusive=True
                          )
                          uniform = tf.random.uniform(
                              shape=shape, dtype=float_dtype
                          )
                          uniform = tf.reshape(
                              tensor=uniform, shape=(-1,)
                          )
                          num_valid = tf_util.cast(
                              x=num_valid, dtype="float"
                          )
                          random_offset = tf.dtypes.cast(
                              x=(uniform * num_valid),
                              dtype=tf.dtypes.int64,
                          )
                          random_action = tf.gather(
                              params=choices,
                              indices=(masked_offset + random_offset),
                          )
                          random_action = tf.reshape(
                              tensor=random_action, shape=shape
                          )
                          is_random = tf.random.uniform(
                              shape=shape, dtype=float_dtype
                          )
                          is_random = is_random < exploration
                          return tf.where(
                              condition=is_random,
                              x=random_action,
                              y=action,
                          )
  
                  else:
                      # Int action: if uniform[0, 1] < exploration, then uniform[num_values]
  
                      def apply_exploration():
                          shape = tf_util.cast(
                              x=tf.shape(input=action), dtype="int"
                          )
                          random_action = tf.random.uniform(
                              shape=shape,
                              maxval=spec.num_values,
                              dtype=spec.tf_type(),
                          )
                          is_random = tf.random.uniform(
                              shape=shape, dtype=float_dtype
                          )
                          is_random = is_random < exploration
                          return tf.where(
                              condition=is_random,
                              x=random_action,
                              y=action,
                          )
  
              else:
                  # Int/float action: action + normal[0, exploration]
  
                  def apply_exploration():
                      shape = tf_util.cast(
                          x=tf.shape(input=action), dtype="int"
                      )
                      noise = tf.random.normal(
                          shape=shape, dtype=spec.tf_type()
                      )
                      x = action + noise * exploration
  
                      # Clip action if left-/right-bounded
                      if spec.min_value is not None:
                          x = tf.math.maximum(x=x, y=spec.min_value)
                      if spec.max_value is not None:
                          x = tf.math.minimum(x=x, y=spec.max_value)
                      return x
  
              # if isinstance(self.exploration, dict):
              # Per-action exploration
              actions[name] = tf.cond(
                  pred=tf.math.logical_or(
                      x=deterministic,
                      y=tf.math.equal(x=exploration, y=zero_float),
                  ),
                  true_fn=(lambda: action),
                  false_fn=apply_exploration,
              )
  
              # else:
              #     exploration_fns[name] = apply_exploration
  
          # if not isinstance(self.exploration, dict):
          #     # Global exploration
  
          #     def apply_exploration():
          #         for name in self.actions_spec:
          #             actions[name] = exploration_fns[name]()
          #         return actions
  
          #     actions = tf.cond(
          #         pred=tf.math.equal(x=exploration, y=zero_float),
          #         true_fn=(lambda: actions), false_fn=apply_exploration
          #     )
  
      # Update states/internals/auxiliaries/actions buffers
      if not independent:
          assignments = list()
          buffer_index = tf.gather(
              params=self.buffer_index, indices=parallel
          )
          if self.circular_buffer:
              buffer_index = tf.math.mod(
                  x=buffer_index, y=self.buffer_capacity
              )
          indices = tf.stack(values=(parallel, buffer_index), axis=1)
          for name, buffer, state in self.states_buffer.zip_items(
              states
          ):
              value = tf.tensor_scatter_nd_update(
                  tensor=buffer, indices=indices, updates=state
              )
              assignments.append(buffer.assign(value=value))
              # assignments.append(buffer.scatter_nd_update(indices=indices, updates=state))
          for name, buffer, internal in self.internals_buffer.zip_items(
              internals
          ):  # not next_*
              value = tf.tensor_scatter_nd_update(
                  tensor=buffer, indices=indices, updates=internal
              )
              assignments.append(buffer.assign(value=value))
              # assignments.append(buffer.scatter_nd_update(indices=indices, updates=internal))
          for (
              name,
              buffer,
              auxiliary,
          ) in self.auxiliaries_buffer.zip_items(auxiliaries):
              value = tf.tensor_scatter_nd_update(
                  tensor=buffer, indices=indices, updates=auxiliary
              )
              assignments.append(buffer.assign(value=value))
              # assignments.append(buffer.scatter_nd_update(indices=indices, updates=auxiliary))
          for name, buffer, action in self.actions_buffer.zip_items(
              actions
          ):
              value = tf.tensor_scatter_nd_update(
                  tensor=buffer, indices=indices, updates=action
              )
              assignments.append(buffer.assign(value=value))
              # assignments.append(buffer.scatter_nd_update(indices=indices, updates=action))
  
          # Increment buffer index (after buffer assignments)
          with tf.control_dependencies(control_inputs=assignments):
              ones = tf_util.ones(
                  shape=tf.expand_dims(input=batch_size, axis=0),
                  dtype="int",
              )
              indices = tf.expand_dims(input=parallel, axis=1)
              value = tf.tensor_scatter_nd_add(
                  tensor=self.buffer_index,
                  indices=indices,
                  updates=ones,
              )
              dependencies.append(self.buffer_index.assign(value=value))
              # sparse_delta = tf.IndexedSlices(values=ones, indices=parallel)
              # dependencies.append(self.buffer_index.scatter_add(sparse_delta=sparse_delta))
  
      with tf.control_dependencies(control_inputs=dependencies):
          actions = actions.fmap(
              function=(
                  lambda name, x: tf_util.identity(input=x, name=name)
              ),
              with_names=True,
          )
          next_internals = next_internals.fmap(
              function=(
                  lambda name, x: tf_util.identity(input=x, name=name)
              ),
              with_names=True,
          )
          return actions, next_internals
  
imports: import logging
  import tensorflow
  from tensorforce import TensorforceError
  from tensorforce.core import ModuleDict, memory_modules, optimizer_modules, parameter_modules, SignatureDict, TensorDict, TensorSpec, TensorsSpec, tf_function, tf_util, VariableDict
  from tensorforce.core.models import Model
  from tensorforce.core.networks import Preprocessor
  from tensorforce.core.objectives import objective_modules
  from tensorforce.core.policies import policy_modules, StochasticPolicy
label_desc: Use image node_id 12 for calling the TensorforceModel obj's underlying member method code with example usage: obj.core_act() and returns: actions,  next_internals, unknown, variable_noise_tensors, tf, tf, x, tf, tf