def tf_update_batch(self, loss_per_instance):
<EOL>mask = tf.not_equal(<EOL>x=self.batch_indices,<EOL>y=tf.zeros(shape=tf.shape(input=self.batch_indices), dtype=tf.int32)<EOL>)<EOL>priority_indices = tf.reshape(tensor=tf.where(condition=mask), shape=[-<NUM_LIT:1>])<EOL>sampled_buffer_batch = self.tf_retrieve_indices(<EOL>buffer_elements=self.last_batch_buffer_elems,<EOL>priority_indices=priority_indices<EOL>)<EOL>states = sampled_buffer_batch['<STR_LIT>']<EOL>internals = sampled_buffer_batch['<STR_LIT>']<EOL>actions = sampled_buffer_batch['<STR_LIT>']<EOL>terminal = sampled_buffer_batch['<STR_LIT>']<EOL>reward = sampled_buffer_batch['<STR_LIT>']<EOL>priorities = loss_per_instance ** self.prioritization_weight<EOL>assignments = list()<EOL>memory_end_index = self.memory_index + self.last_batch_buffer_elems<EOL>memory_insert_indices = tf.range(<EOL>start=self.memory_index,<EOL>limit=memory_end_index<EOL>) % self.capacity<EOL>for name in sorted(states):<EOL><INDENT>assignments.append(tf.scatter_update(<EOL>ref=self.states_memory[name],<EOL>indices=memory_insert_indices,<EOL>updates=states[name][<NUM_LIT:0>:self.last_batch_buffer_elems])<EOL>)<EOL><DEDENT>for name in sorted(internals):<EOL><INDENT>assignments.append(tf.scatter_update(<EOL>ref=self.internals_buffer[name],<EOL>indices=memory_insert_indices,<EOL>updates=internals[name][<NUM_LIT:0>:self.last_batch_buffer_elems]<EOL>))<EOL><DEDENT>assignments.append(tf.scatter_update(<EOL>ref=self.priorities,<EOL>indices=memory_insert_indices,<EOL>updates=priorities[<NUM_LIT:0>:self.last_batch_buffer_elems]<EOL>))<EOL>assignments.append(tf.scatter_update(<EOL>ref=self.terminal_memory,<EOL>indices=memory_insert_indices,<EOL>updates=terminal[<NUM_LIT:0>:self.last_batch_buffer_elems])<EOL>)<EOL>assignments.append(tf.scatter_update(<EOL>ref=self.reward_memory,<EOL>indices=memory_insert_indices,<EOL>updates=reward[<NUM_LIT:0>:self.last_batch_buffer_elems])<EOL>)<EOL>for name in sorted(actions):<EOL><INDENT>assignments.append(tf.scatter_update(<EOL>ref=self.actions_memory[name],<EOL>indices=memory_insert_indices,<EOL>updates=actions[name][<NUM_LIT:0>:self.last_batch_buffer_elems]<EOL>))<EOL><DEDENT>main_memory_priorities = priorities[self.last_batch_buffer_elems:]<EOL>main_memory_priorities = main_memory_priorities[<NUM_LIT:0>:tf.shape(priority_indices)[<NUM_LIT:0>]]<EOL>assignments.append(tf.scatter_update(<EOL>ref=self.priorities,<EOL>indices=priority_indices,<EOL>updates=main_memory_priorities<EOL>))<EOL>with tf.control_dependencies(control_inputs=assignments):<EOL><INDENT>assignments = list()<EOL>sorted_priorities, sorted_indices = tf.nn.top_k(<EOL>input=self.priorities,<EOL>k=self.capacity,<EOL>sorted=True<EOL>)<EOL>assignments.append(tf.assign(ref=self.priorities, value=sorted_priorities))<EOL>assignments.append(tf.scatter_update(<EOL>ref=self.terminal_memory,<EOL>indices=sorted_indices,<EOL>updates=self.terminal_memory<EOL>))<EOL>for name in sorted(self.states_memory):<EOL><INDENT>assignments.append(tf.scatter_update(<EOL>ref=self.states_memory[name],<EOL>indices=sorted_indices,<EOL>updates=self.states_memory[name]<EOL>))<EOL><DEDENT>for name in sorted(self.actions_memory):<EOL><INDENT>assignments.append(tf.scatter_update(<EOL>ref=self.actions_memory[name],<EOL>indices=sorted_indices,<EOL>updates=self.actions_memory[name]<EOL>))<EOL><DEDENT>for name in sorted(self.internals_memory):<EOL><INDENT>assignments.append(tf.scatter_update(<EOL>ref=self.internals_memory[name],<EOL>indices=sorted_indices,<EOL>updates=self.internals_memory[name]<EOL>))<EOL><DEDENT>assignments.append(tf.scatter_update(<EOL>ref=self.reward_memory,<EOL>indices=sorted_indices,<EOL>updates=self.reward_memory<EOL>))<EOL><DEDENT>with tf.control_dependencies(control_inputs=assignments):<EOL><INDENT>assignments = list()<EOL>assignments.append(tf.assign_sub(ref=self.buffer_index, value=self.last_batch_buffer_elems))<EOL>total_inserted_elements = self.memory_size + self.last_batch_buffer_elems<EOL>assignments.append(tf.assign(<EOL>ref=self.memory_size,<EOL>value=tf.minimum(x=total_inserted_elements, y=self.capacity))<EOL>)<EOL>assignments.append(tf.assign(ref=self.memory_index, value=memory_end_index))<EOL>assignments.append(tf.assign(<EOL>ref=self.batch_indices,<EOL>value=tf.zeros(shape=tf.shape(self.batch_indices), dtype=tf.int32)<EOL>))<EOL><DEDENT>with tf.control_dependencies(control_inputs=assignments):<EOL><INDENT>return tf.no_op()<EOL><DEDENT>
Updates priority memory by performing the following steps:

1. Use saved indices from prior retrieval to reconstruct the batch
elements which will have their priorities updated.
2. Compute priorities for these elements.
3. Insert buffer elements to memory, potentially overwriting existing elements.
4. Update priorities of existing memory elements
5. Resort memory.
6. Update buffer insertion index.

Note that this implementation could be made more efficient by maintaining
a sorted version via sum trees.

:param loss_per_instance: Losses from recent batch to perform priority update