Skip to content

HW-aware Synthesis of MCX

This example shows that implementation of multiple control-x (MCX) logic, using the Classiq synthesis engine, yields different circuit results for different quantum hardware.

The fictitious hardware created here demonstrates how to insert your own custom-designed machine. For comparison, create two types of hardware with cx, u basis gates. The difference between them manifests in the connectivity map: one has linear connectivity while the other has all-to-all connectivity.

from classiq import (
    CX,
    Constraints,
    CustomHardwareSettings,
    H,
    OptimizationParameter,
    Output,
    Preferences,
    QArray,
    QBit,
    X,
    allocate,
    control,
    create_model,
    qfunc,
    set_constraints,
    set_preferences,
    show,
    synthesize,
    write_qmod,
)

# define MCX quantum function


@qfunc
def my_mcx(cntrl: QArray[QBit], target: QBit) -> None:
    control(cntrl, lambda: X(target))


# define the MCX parameters within the quantum 'main' function
@qfunc
def main(cntrl: Output[QArray[QBit]], target: Output[QBit]) -> None:
    allocate(15, cntrl)
    allocate(1, target)
    my_mcx(cntrl, target)


# build a model
model = create_model(main)

# define the hardware parameters
max_width = 18

linear_connectivity = [[qubit, qubit + 1] for qubit in range(max_width - 1)]

preferences_linear = Preferences(
    custom_hardware_settings=CustomHardwareSettings(
        basis_gates=["cx", "u"],
        connectivity_map=linear_connectivity,
    ),
    random_seed=-1,
)
preferences_all_to_all = Preferences(
    custom_hardware_settings=CustomHardwareSettings(basis_gates=["cx", "u"]),
    random_seed=-1,
)

# define synthesis engine constraints

constraints = Constraints(optimization_parameter="depth", max_width=max_width)

# define models with different preferences
model = set_constraints(model, constraints)

model_linear = set_preferences(model, preferences_linear)
model_all_to_all = set_preferences(model, preferences_all_to_all)

# write models to files

write_qmod(model_linear, "hardware_aware_mcx_linear")
write_qmod(model_all_to_all, "hardware_aware_mcx_all_to_all")


# synthesize to create quantum programs and view circuits:
qprog_linear = synthesize(model_linear)
show(qprog_linear)

qprog_all_to_all = synthesize(model_all_to_all)
show(qprog_all_to_all)
Opening: https://platform.classiq.io/circuit/49c8fa89-91ad-4802-ae00-2fba8f3257e7?version=0.41.0.dev39%2B79c8fd0855


Opening: https://platform.classiq.io/circuit/14a11412-f9e4-4779-ac98-339dccc1efe3?version=0.41.0.dev39%2B79c8fd0855

Comparison of the two circuits shows that applying MCx using different connectivity maps yields different implementation.

Using "all-to-all" connectivity, the synthesis engine chooses as the best implementation a recourse based on "Maslov2015" [1] that was written on the Classiq platform. Using that, the manufactured circuit has 18 qubits; i.e., it uses two auxiliary qubits. The total depth of the circuit is 936.

When using linear connectivity, the best implementation chosen by the synthesis engine is, in fact, different: an algorithm developed by Classiq, which is better suited for this map. Here, the manufactured circuit uses 17 qubits with only one auxiliary and has a depth of 1257 gates.

References

[1]: Maslov, D., 2016. Advantages of using relative-phase Toffoli gates with an application to multiple control Toffoli optimization. Physical Review A, 93(2), p.022311.