Skip to content

quast_decisiontree.algorithms.ansatze

quast_decisiontree.algorithms.ansatze

Qrisp-compatible VQE ansatz definitions and registry.

Overview

An ansatz function is a callable with signature::

def ansatz_function(qv: QuantumVariable, params: np.ndarray) -> None

It applies one layer of a parameterized unitary to the quantum variable qv in-place. The VQE driver calls it depth times with successive slices of the full parameter vector.

An ansatz factory returns a tuple (ansatz_function, num_params) where num_params is the number of variational parameters consumed per layer.

Registering Custom Ansatze

To add your own ansatz, create a Python module and call :func:register_ansatz at module level:

.. code-block:: python

# File: my_project/custom_ansatze.py

from quast_decisiontree.algorithms.ansatze import register_ansatz


def _build_my_ansatz(num_qubits, **kwargs):
    num_params = num_qubits

    def my_ansatz(qv, params):
        from qrisp import ry, cx

        for i in range(len(qv)):
            ry(params[i], qv[i])
        for i in range(len(qv) - 1):
            cx(qv[i], qv[i + 1])

    return my_ansatz, num_params


register_ansatz(
    name="MyCustom",
    description="My custom ansatz with RY rotations and linear CNOT",
    factory=_build_my_ansatz,
)

Then reference the module in the YAML config:

.. code-block:: yaml

QrispAnsatzNode:
  children: ["SelectOptimizerNode"]
  ansatz_modules:
    - "my_project.custom_ansatze"

Factory Contract

A factory callable must:

  1. Accept num_qubits as the first positional-or-keyword argument.
  2. Accept arbitrary **kwargs (forward-compatible with future arguments).
  3. Return a tuple (ansatz_function, num_params).
  4. Perform Qrisp imports inside the factory body (not at module level).

The returned ansatz_function(qv, params) must consume exactly num_params entries from params (a 1-D NumPy array or list of floats).

logger module-attribute

logger = logging.getLogger('dt_logger')

AnsatzFactory module-attribute

AnsatzFactory = Callable[..., tuple[Callable, int]]

ANSATZ_REGISTRY module-attribute

ANSATZ_REGISTRY = {}

SINGLE_GATE_MAP module-attribute

SINGLE_GATE_MAP = {
    "rx": rx,
    "ry": ry,
    "rz": rz,
    "p": p,
    "h": h,
    "x": x,
    "y": y,
    "z": z,
    "s": s,
    "t": t,
}

TWO_GATE_MAP module-attribute

TWO_GATE_MAP = {
    "cx": cx,
    "cy": cy,
    "cz": cz,
    "swap": swap,
    "crx": _crx,
    "cry": _cry,
    "crz": crz,
    "cp": cp,
}

PARAMETERIZED_SINGLE_GATES module-attribute

PARAMETERIZED_SINGLE_GATES = frozenset(
    {"rx", "ry", "rz", "p"}
)

PARAMETERIZED_TWO_GATES module-attribute

PARAMETERIZED_TWO_GATES = frozenset(
    {"crx", "cry", "crz", "cp"}
)

AVAILABLE_SINGLE_GATES module-attribute

AVAILABLE_SINGLE_GATES = frozenset(
    {"rx", "ry", "rz", "p", "h", "x", "y", "z", "s", "t"}
)

AVAILABLE_TWO_GATES module-attribute

AVAILABLE_TWO_GATES = frozenset(
    {"cx", "cy", "cz", "crx", "cry", "crz", "cp", "swap"}
)

VALID_ENTANGLEMENTS module-attribute

VALID_ENTANGLEMENTS = (
    "linear",
    "circular",
    "full",
    "blocks",
)

register_ansatz

register_ansatz(
    name, description, factory, hyperparams=None
)

Register an ansatz factory in the global registry.

Parameters

name : str User-facing name (used in YAML configs and interactive queries). description : str One-line description shown during ansatz selection. factory : callable A callable(num_qubits, **kwargs) returning (ansatz_function, num_params). hyperparams : list of HyperParam, optional Additional hyperparameters beyond num_qubits that the factory accepts. Used by the node to query the user interactively.

Source code in src/quast_decisiontree/algorithms/ansatze.py
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
def register_ansatz(
    name: str,
    description: str,
    factory: AnsatzFactory,
    hyperparams: list | None = None,
) -> None:
    """Register an ansatz factory in the global registry.

    Parameters
    ----------
    name : str
        User-facing name (used in YAML configs and interactive queries).
    description : str
        One-line description shown during ansatz selection.
    factory : callable
        A callable(num_qubits, **kwargs) returning (ansatz_function, num_params).
    hyperparams : list of HyperParam, optional
        Additional hyperparameters beyond ``num_qubits`` that the factory
        accepts. Used by the node to query the user interactively.
    """
    if name in ANSATZ_REGISTRY:
        logger.warning("Overwriting existing ansatz %r in registry.", name)
    ANSATZ_REGISTRY[name] = {
        "description": description,
        "factory": factory,
        "hyperparams": hyperparams or [],
    }

get_ansatz

get_ansatz(name, **kwargs)

Retrieve and build an ansatz by name.

Parameters

name : str Registered ansatz name. **kwargs Passed to the factory (must include num_qubits).

Returns

tuple of (callable, int) (ansatz_function, num_params) where ansatz_function has signature (qv, params) -> None.

Raises

ValueError If the name is not found in the registry.

Source code in src/quast_decisiontree/algorithms/ansatze.py
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
def get_ansatz(name: str, **kwargs) -> tuple[Callable, int]:
    """Retrieve and build an ansatz by name.

    Parameters
    ----------
    name : str
        Registered ansatz name.
    **kwargs
        Passed to the factory (must include ``num_qubits``).

    Returns
    -------
    tuple of (callable, int)
        (ansatz_function, num_params) where ansatz_function has signature
        ``(qv, params) -> None``.

    Raises
    ------
    ValueError
        If the name is not found in the registry.
    """
    if name not in ANSATZ_REGISTRY:
        available = ", ".join(sorted(ANSATZ_REGISTRY.keys()))
        raise ValueError(f"Unknown ansatz {name!r}. Available: {available}")
    return ANSATZ_REGISTRY[name]["factory"](**kwargs)

get_registry_descriptions

get_registry_descriptions()

Return {name: description} for all registered ansatze.

Source code in src/quast_decisiontree/algorithms/ansatze.py
198
199
200
def get_registry_descriptions() -> dict[str, str]:
    """Return {name: description} for all registered ansatze."""
    return {name: entry["description"] for name, entry in ANSATZ_REGISTRY.items()}

get_ansatz_hyperparams

get_ansatz_hyperparams(name)

Return the list of extra HyperParam instances for a registered ansatz.

Parameters

name : str Registered ansatz name.

Returns

list of HyperParam Extra hyperparameters (may be empty).

Raises

ValueError If the name is not found in the registry.

Source code in src/quast_decisiontree/algorithms/ansatze.py
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
def get_ansatz_hyperparams(name: str) -> list:
    """Return the list of extra HyperParam instances for a registered ansatz.

    Parameters
    ----------
    name : str
        Registered ansatz name.

    Returns
    -------
    list of HyperParam
        Extra hyperparameters (may be empty).

    Raises
    ------
    ValueError
        If the name is not found in the registry.
    """
    if name not in ANSATZ_REGISTRY:
        available = ", ".join(sorted(ANSATZ_REGISTRY.keys()))
        raise ValueError(f"Unknown ansatz {name!r}. Available: {available}")
    return ANSATZ_REGISTRY[name]["hyperparams"]

load_ansatz_modules

load_ansatz_modules(module_paths)

Import one or more modules so they can register additional ansatze.

Each module is expected to call :func:register_ansatz at import time.

Parameters

module_paths : sequence of str Fully qualified Python module paths.

Source code in src/quast_decisiontree/algorithms/ansatze.py
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
def load_ansatz_modules(module_paths: Sequence[str]) -> None:
    """Import one or more modules so they can register additional ansatze.

    Each module is expected to call :func:`register_ansatz` at import time.

    Parameters
    ----------
    module_paths : sequence of str
        Fully qualified Python module paths.
    """
    import importlib

    for module_path in module_paths:
        logger.info("Loading external ansatz module: %s", module_path)
        importlib.import_module(module_path)