class_docstr: General linear interferometer, an array of beamsplitters and phase shifters.
  
  For :math:`M` wires, the general interferometer is specified by
  providing :math:`M(M-1)/2` transmittivity angles :math:`\theta` and the same number of
  phase angles :math:`\phi`, as well as :math:`M-1` additional rotation
  parameters :math:`\varphi`.
  
  By specifying the keyword argument ``mesh``, the scheme used to implement the interferometer
  may be adjusted:
  
  * ``mesh='rectangular'`` (default): uses the scheme described in
    `Clements et al. <https://dx.doi.org/10.1364/OPTICA.3.001460>`__, resulting in a *rectangular* array of
    :math:`M(M-1)/2` beamsplitters arranged in :math:`M` slices and ordered from left
    to right and top to bottom in each slice. The first beamsplitter acts on
    wires :math:`0` and :math:`1`:
  
    .. figure:: ../../_static/clements.png
        :align: center
        :width: 30%
        :target: javascript:void(0);
  
  
  * ``mesh='triangular'``: uses the scheme described in `Reck et al. <https://dx.doi.org/10.1103/PhysRevLett.73.58>`__,
    resulting in a *triangular* array of :math:`M(M-1)/2` beamsplitters arranged in
    :math:`2M-3` slices and ordered from left to right and top to bottom. The
    first and fourth beamsplitters act on wires :math:`M-1` and :math:`M`, the second
    on :math:`M-2` and :math:`M-1`, and the third on :math:`M-3` and :math:`M-2`, and
    so on.
  
    .. figure:: ../../_static/reck.png
        :align: center
        :width: 30%
        :target: javascript:void(0);
  
  In both schemes, the network of :class:`~pennylane.ops.Beamsplitter` operations is followed by
  :math:`M` local :class:`~pennylane.ops.Rotation` Operations.
  
  The rectangular decomposition is generally advantageous, as it has a lower
  circuit depth (:math:`M` vs :math:`2M-3`) and optical depth than the triangular
  decomposition, resulting in reduced optical loss.
  
  This is an example of a 4-mode interferometer with beamsplitters :math:`B` and rotations :math:`R`,
  using ``mesh='rectangular'``:
  
  .. figure:: ../../_static/layer_interferometer.png
      :align: center
      :width: 60%
      :target: javascript:void(0);
  
  .. note::
  
      The decomposition as formulated in `Clements et al. <https://dx.doi.org/10.1364/OPTICA.3.001460>`__ uses a different
      convention for a beamsplitter :math:`T(\theta, \phi)` than PennyLane, namely:
  
      .. math:: T(\theta, \phi) = BS(\theta, 0) R(\phi)
  
      For the universality of the decomposition, the used convention is irrelevant, but
      for a given set of angles the resulting interferometers will be different.
  
      If an interferometer consistent with the convention from `Clements et al. <https://dx.doi.org/10.1364/OPTICA.3.001460>`__
      is needed, the optional keyword argument ``beamsplitter='clements'`` can be specified. This
      will result in each :class:`~pennylane.ops.Beamsplitter` being preceded by a :class:`~pennylane.ops.Rotation` and
      thus increase the number of elementary operations in the circuit.
  
  Args:
      theta (tensor_like): size :math:`(M(M-1)/2,)` tensor of transmittivity angles :math:`\theta`
      phi (tensor_like): size :math:`(M(M-1)/2,)` tensor of phase angles :math:`\phi`
      varphi (tensor_like): size :math:`(M,)` tensor of rotation angles :math:`\varphi`
      wires (Iterable or Wires): Wires that the template acts on. Accepts an iterable of numbers or strings, or
          a Wires object.
      mesh (string): the type of mesh to use
      beamsplitter (str): if ``clements``, the beamsplitter convention from
        Clements et al. 2016 (https://dx.doi.org/10.1364/OPTICA.3.001460) is used; if ``pennylane``, the
        beamsplitter is implemented via PennyLane's ``Beamsplitter`` operation.
  
  Raises:
      ValueError: if inputs do not have the correct format
  
  Example:
  
      The template requires :math:`3` sets of parameters. The ``mesh`` and ``beamsplitter`` keyword arguments are optional and
      have ``'rectangular'`` and ``'pennylane'`` as default values.
  
      .. code-block:: python
  
          dev = qml.device('default.gaussian', wires=4)
  
          @qml.qnode(dev)
          def circuit(params):
              qml.Interferometer(*params, wires=range(4))
              return qml.expval(qml.Identity(0))
  
          shapes = [[6, ], [6, ], [4, ]]
          params = []
          for shape in shapes:
              params.append(np.random.random(shape))
  
      Using these random parameters, the resulting circuit is:
  
      >>> print(qml.draw(circuit, expansion_strategy="device")(params))
      0: ─╭BS(0.97,0.09)────────────────╭BS(0.89,0.33)──R(0.83)────────────────┤  <I>
      1: ─╰BS(0.97,0.09)─╭BS(0.94,0.05)─╰BS(0.89,0.33)─╭BS(0.92,0.27)──R(0.36)─┤
      2: ─╭BS(0.78,0.20)─╰BS(0.94,0.05)─╭BS(0.60,0.39)─╰BS(0.92,0.27)──R(0.28)─┤
      3: ─╰BS(0.78,0.20)────────────────╰BS(0.60,0.39)──R(0.54)────────────────┤
  
      Using different values for optional arguments:
  
      .. code-block:: python
  
          @qml.qnode(dev)
          def circuit(params):
              qml.Interferometer(*params, wires=range(4), mesh='triangular', beamsplitter='clements')
              return qml.expval(qml.Identity(0))
  
          shapes = [[6, ], [6, ], [4, ]]
          params = []
          for shape in shapes:
              params.append(np.random.random(shape))
  
          print(qml.draw(circuit, expansion_strategy="device")(params))
  
      .. code-block::
  
          0: ──R(0.71)───────────────────────────────╭BS(0.07,0.00)──R(0.36)──────────────────────────────
          1: ──R(0.82)────────────────╭BS(0.80,0.00)─╰BS(0.07,0.00)──R(0.77)───────╭BS(0.77,0.00)──R(0.12)
          2: ──R(0.01)─╭BS(0.14,0.00)─╰BS(0.80,0.00)──R(0.73)───────╭BS(0.99,0.00)─╰BS(0.77,0.00)──R(0.07)
          3: ──────────╰BS(0.14,0.00)───────────────────────────────╰BS(0.99,0.00)────────────────────────
  
          ──────────────────────────┤  <I>
          ──────────────────────────┤
          ──╭BS(0.20,0.00)──R(0.86)─┤
          ──╰BS(0.20,0.00)──R(0.62)─┤
docstr: Returns a list of shapes for the 3 parameter tensors.
  
  Args:
      n_wires (int): number of wires
  
  Returns:
      list[tuple[int]]: list of shapes
docstr_tok: ["Returns","a","list","of","shapes","for","the","3","parameter","tensors",".","Args",":","n_wires","(","int",")",":","number","of","wires","Returns",":","list","[","tuple","[","int","]","]",":","list","of","shapes"]
code: def shape(n_wires):
      r"""Returns a list of shapes for the 3 parameter tensors.
  
      Args:
          n_wires (int): number of wires
  
      Returns:
          list[tuple[int]]: list of shapes
      """
      shape_theta_phi = n_wires * (n_wires - 1) // 2
  
      shapes = [(shape_theta_phi,)] * 2 + [(n_wires,)]
  
      return shapes
  
file_path: pennylane/pennylane/templates/subroutines/interferometer.py
imports: from itertools import product
  import pennylane
  from pennylane.ops import Beamsplitter, Rotation
  from pennylane.wires import Wires
  from pennylane.operation import CVOperation, AnyWires
label_desc: Use image node_id 3 for calling the Interferometer obj's underlying member method code with example usage: obj.shape(n_wires) and returns: shapes