Skip to content

Ansaetze#

.. or Ansatzes as preferred by the english community. Anyway, we got various of the most-used Ansaetze implemented in this package. 🚀

You can load them manually by

from qml_essentials.ansaetze import Ansaetze
all_ansaetze = Ansaetze.get_available()

for ansatz in all_ansaetze:
    print(ansatz.__name__)

See the Overview at the end of this document for more details. However, usually you just want reference to them (by name) when instantiating a model. To get an overview of all the available Ansaetze, checkout the references.

Custom Ansatz#

For building the different Ansatzes, we use topology patterns defined in qml_essentials.topologies. You can find a list of all the available topologies in the references as well.

To start implementing your own ansatz, you can inheriting from the Circuit class:

from qml_essentials.ansaetze import Circuit
from qml_essentials.gates import Gates
from qml_essentials.topologies import Topology, Block

class MyHardwareEfficient(Circuit):
    @staticmethod
    def structure():
        return (
            Block(gate=Gates.RY),
            Block(gate=Gates.RZ),
            Block(gate=Gates.RY),
            Block(
                gate=Gates.CX,
                topology=Topology.stairs,
                stride=2,
                mirror=False,
            ),
            Block(
                gate=Gates.CX,
                topology=Topology.stairs,
                stride=2,
                offset=1,
                mirror=False,
            ),
        )
and then pass it to the model:
from qml_essentials.model import Model

model = Model(
    n_qubits=2,
    n_layers=1,
    circuit_type=MyHardwareEfficient,
)

If you don't want to use the provided blocks and topologies, you can build your own Ansatz from scratch but have to implement all the required methods shown in the example below:

import pennylane.numpy as np
from qml_essentials.gates import PulseInformation as pinfo
from typing import Optional

class MyHardwareEfficient(Circuit):
    @staticmethod
    def n_params_per_layer(n_qubits: int) -> int:
        return n_qubits * 3

    @staticmethod
    def n_pulse_params_per_layer(n_qubits: int) -> int:
        n_params_RY = pinfo.num_params("RY")
        n_params_RZ = pinfo.num_params("RZ")
        n_params_CZ = pinfo.num_params("CZ")

        n_pulse_params = (num_params_RY + num_params_RZ) * n_qubits
        n_pulse_params += num_params_CZ * (n_qubits - 1)

        return pulse_params

    @staticmethod
    def get_control_indices(n_qubits: int) -> Optional[np.ndarray]:
        return None

    @staticmethod
    def build(w: np.ndarray, n_qubits: int, **kwargs):
        w_idx = 0
        for q in range(n_qubits):
            Gates.RY(w[w_idx], wires=q, **kwargs)
            w_idx += 1
            Gates.RZ(w[w_idx], wires=q, **kwargs)
            w_idx += 1

        if n_qubits > 1:
            for q in range(n_qubits - 1):
                Gates.CZ(wires=[q, q + 1], **kwargs)

The **kwargs allow both noise simulation and pulse simulation. A custom Circuit should define n_pulse_params_per_layer if it will use pulse simulation at some point, but may be omitted otherwise.

Check out page Usage on how to proceed from here.

Custom Encoding#

On model instantiation, you can choose how your inputs are encoded. The default encoding is "RX" which will result in a single RX rotation per qubit. You can change this behavior, by setting the optional encoding argument to - a string or a list of strings where each is checked agains the Gates class - a callable or a list of callables

A callable must take an input, the wire where it's acting on and an optional noise_params dictionary. Let's look at an example, where we want to encode a two-dimensional input:

from qml_essentials.model import Model
from qml_essentials.gates import Gates

def MyCustomEncoding(w, wires, **kwars):
    Gates.RX(w[0], wires, **kwargs)
    Gates.RY(w[1], wires, **kwargs)

model = Model(
    n_qubits=2,
    n_layers=1,
    circuit_type=MyHardwareEfficient,
    encoding=MyCustomEncoding,
)

model(inputs=[1, 2])

Overview#

This section shows an overview of all the available Ansaetze in our package. Most of the circuits are implemented according to to the original paper by Sim et al.. Note that Circuit 10 deviates from the original implementation!

Oh and in case you need a refresh on the rotational axes and their corresponding states, here is a Bloch sphere 😇 :

Bloch Sphere

4 Qubit Circuits#

No Ansatz#

No Ansatz No Ansatz

Circuit 1#

Circuit 1 Circuit 1

Circuit 2#

Circuit 2 Circuit 2

Circuit 3#

Circuit 3 Circuit 3

Circuit 4#

Circuit 4 Circuit 4

Circuit 5#

Circuit 5 Circuit 5

Circuit 6#

Circuit 6 Circuit 6

Circuit 7#

Circuit 7 Circuit 7

Circuit 8#

Circuit 8 Circuit 8

Circuit 9#

Circuit 9 Circuit 9

Circuit 10#

Circuit 10 Circuit 10

Circuit 13#

Circuit 13 Circuit 13

Circuit 14#

Circuit 14 Circuit 14

Circuit 15#

Circuit 15 Circuit 15

Circuit 16#

Circuit 16 Circuit 16

Circuit 17#

Circuit 17 Circuit 17

Circuit 18#

Circuit 18 Circuit 18

Circuit 19#

Circuit 19 Circuit 19

No Entangling#

No Entangling No Entangling

Strongly Entangling#

Strongly Entangling Strongly Entangling

Hardware Efficient#

Hardware Efficient Hardware Efficient

GHZ#

GHZ GHZ

5 Qubit Circuits#

No Ansatz#

No Ansatz No Ansatz

Circuit 1#

Circuit 1 Circuit 1

Circuit 2#

Circuit 2 Circuit 2

Circuit 3#

Circuit 3 Circuit 3

Circuit 4#

Circuit 4 Circuit 4

Circuit 5#

Circuit 5 Circuit 5

Circuit 6#

Circuit 6 Circuit 6

Circuit 7#

Circuit 7 Circuit 7

Circuit 8#

Circuit 8 Circuit 8

Circuit 9#

Circuit 9 Circuit 9

Circuit 10#

Circuit 10 Circuit 10

Circuit 13#

Circuit 13 Circuit 13

Circuit 14#

Circuit 14 Circuit 14

Circuit 15#

Circuit 15 Circuit 15

Circuit 16#

Circuit 16 Circuit 16

Circuit 17#

Circuit 17 Circuit 17

Circuit 18#

Circuit 18 Circuit 18

Circuit 19#

Circuit 19 Circuit 19

No Entangling#

No Entangling No Entangling

Strongly Entangling#

Strongly Entangling Strongly Entangling

Hardware Efficient#

Hardware Efficient Hardware Efficient

GHZ#

GHZ GHZ

6 Qubit Circuits#

No Ansatz#

No Ansatz No Ansatz

Circuit 1#

Circuit 1 Circuit 1

Circuit 2#

Circuit 2 Circuit 2

Circuit 3#

Circuit 3 Circuit 3

Circuit 4#

Circuit 4 Circuit 4

Circuit 5#

Circuit 5 Circuit 5

Circuit 6#

Circuit 6 Circuit 6

Circuit 7#

Circuit 7 Circuit 7

Circuit 8#

Circuit 8 Circuit 8

Circuit 9#

Circuit 9 Circuit 9

Circuit 10#

Circuit 10 Circuit 10

Circuit 13#

Circuit 13 Circuit 13

Circuit 14#

Circuit 14 Circuit 14

Circuit 15#

Circuit 15 Circuit 15

Circuit 16#

Circuit 16 Circuit 16

Circuit 17#

Circuit 17 Circuit 17

Circuit 18#

Circuit 18 Circuit 18

Circuit 19#

Circuit 19 Circuit 19

No Entangling#

No Entangling No Entangling

Strongly Entangling#

Strongly Entangling Strongly Entangling

Hardware Efficient#

Hardware Efficient Hardware Efficient

GHZ#

GHZ GHZ