class_docstr: Tests for calling a TransformProgram on a batch of quantum tapes.
docstr: Test postprocessing functions applied in reverse order.
docstr_tok: ["Test","postprocessing","functions","applied","in","reverse","order","."]
code: def test_chain_two_postprocessings(self):
      """Test postprocessing functions applied in reverse order."""
  
      def add_one(results):
          return results[0] + 1.0
  
      def scale_two(results):
          return results[0] * 2.0
  
      def transform_add(tape: qml.tape.QuantumTape):
          """A valid transform."""
          return (tape,), add_one
  
      def transform_mul(tape: qml.tape.QuantumTape):
          return (tape,), scale_two
  
      container1 = TransformContainer(transform_add)
      container2 = TransformContainer(transform_mul)
      prog = TransformProgram((container1, container2))
  
      tape0 = qml.tape.QuantumScript(
          [], [qml.expval(qml.PauliZ(0))], shots=100
      )
      batch = (tape0,)
      new_batch, fn = prog(batch)
  
      assert len(new_batch) == 1
      assert new_batch[0] is tape0
  
      assert fn.func is _apply_postprocessing_stack
      assert fn.args == tuple()
      assert len(fn.keywords["postprocessing_stack"]) == 2
  
      postprocessing0 = fn.keywords["postprocessing_stack"][0]
      assert postprocessing0.func is _batch_postprocessing
      assert postprocessing0.args == tuple()
      assert postprocessing0.keywords["individual_fns"] == [
          add_one,
      ]
      assert postprocessing0.keywords["slices"] == [slice(0, 1)]
  
      postprocessing1 = fn.keywords["postprocessing_stack"][1]
      assert postprocessing1.func is _batch_postprocessing
      assert postprocessing1.args == tuple()
      assert postprocessing1.keywords["individual_fns"] == [
          scale_two,
      ]
      assert postprocessing1.keywords["slices"] == [slice(0, 1)]
  
      results = (1.0,)
      expected = (3.0,)  # 2.0 * 1.0 + 1.0
      assert fn(results) == expected
  
      # Test reverse direction
  
      prog_reverse = TransformProgram((container2, container1))
      new_batch, fn = prog_reverse(batch)
  
      assert len(new_batch) == 1
      assert new_batch[0] is tape0
  
      assert fn.func is _apply_postprocessing_stack
      assert fn.args == tuple()
      assert len(fn.keywords["postprocessing_stack"]) == 2
  
      postprocessing0 = fn.keywords["postprocessing_stack"][0]
      assert postprocessing0.func is _batch_postprocessing
      assert postprocessing0.args == tuple()
      assert postprocessing0.keywords["individual_fns"] == [
          scale_two,
      ]
      assert postprocessing0.keywords["slices"] == [slice(0, 1)]
  
      postprocessing1 = fn.keywords["postprocessing_stack"][1]
      assert postprocessing1.func is _batch_postprocessing
      assert postprocessing1.args == tuple()
      assert postprocessing1.keywords["individual_fns"] == [
          add_one,
      ]
      assert postprocessing1.keywords["slices"] == [slice(0, 1)]
  
      results = (1.0,)
      expected = (4.0,)  # (1.0 + 1.0) * 2.0
      assert fn(results) == expected
  
imports: from typing import Sequence, Callable
  import pytest
  import pennylane
  from pennylane.tape import QuantumScript
  from pennylane.transforms.core import transform, TransformProgram, TransformError, TransformContainer
  from pennylane.transforms.core.transform_program import _batch_postprocessing, _apply_postprocessing_stack, null_postprocessing
  from pennylane.typing import ResultBatch, Result
label_desc: Use image node_id 3 for calling the TestTransformProgramCall obj's underlying member method code with example usage: obj.test_chain_two_postprocessings() and returns: unknown, unknown, tape,  add_one, tape,  scale_two