Supported resources

This section lists the scheduler resource types currently supported by OpenQL.

Roughly speaking, resources control whether two (or more) quantum gates may execute in parallel, and under what conditions. The most obvious one is that two quantum gates operating on the same qubit physically cannot be executed at the same time, but quantum chips typically have more subtle constraints as well. For example, execution of an X gate on one qubit may require generation of a particular waveform by a waveform generator shared between a number of qubits; in this case, it might be possible to do an X gate on another qubit in parallel, but not a Y gate.

Resources are of course used by the (resource-constrained) scheduler, but other passes may also make use of them. For example, the mapper uses them in its heuristic routing algorithm to try to overlap swaps with the rest of the circuit as much as possible, in such a way that resource constraints are not violated.

Resource specification

Resources are specified using the "resources" section of the platform configuration file. Two flavors are supported for its contents: one for compatibility with older platform configuration files, and one extended structure. The extended structure has the following syntax.

"resources": {
    "architecture": <optional string, default "">,
    "dnu": <optional list of strings, default []>,
    "resources": {
        "<name>": {
            "type": "<type>",
            "config": {
                <optional configuration>
            }
        }
        ...
    }
}

The optional "architecture" key may be used to make shorthands for architecture- specific resources, normally prefixed with "arch.<architecture>.". If it’s not specified or an empty string, the architecture is derived from the "eqasm_compiler" key.

The optional "dnu" key may be used to specify a list of do-not-use resource types (experimental, deprecated, or any other resource that’s considered unfit for “production” use) that you explicitly want to use, including the “dnu” namespace they are defined in. Once specified, you’ll be able to use the resource type without the "dnu" namespace element. For example, if you would include "dnu.whatever" in the list, the resource type "whatever" may be used to add the resource.

The "resources" subkey specifies the actual resource list. This consists of a map from unique resource names matching [a-zA-Z0-9_\-]+ to a resource configuration. The configuration object must have a "type" key, which must identify a resource type that OpenQL knows about; the type names are listed in the sections below. The "config" key is optional, and is used to pass type-specific configuration data to the resource. If not specified, an empty JSON object will be passed to the resource instead.

If the "resources" subkey is not present, the old structure is used instead. This has the following, simpler form:

"resources": {
    "<type>": {
        <configuration>
    },
    ...
}

This is limited to one resource per type alias. The names for the resources are inferred, and the architecture namespace is in this case always based upon the contents of the "eqasm_compiler" key.

Instrument resource

Type names: Instrument.

This resource models an instrument or group of instruments that is needed to apply a certain kind of quantum gate, with the constraint that the instrument is shared between a number of qubits/edges, and can only perform one function at a time. That is, two gates that share an instrument can be parallelized if and only if they use the same instrument function. By default, parallel gates requiring the same instrument also need to start at the same time and have the same duration, but this can be disabled.

The instrument function is configurable for each particular gate based on one or more custom keys in the instruction set definition of the platform configuration file. It’s also possible to specify that there is only a single function (i.e., all gates requiring access to the instrument can be parallelized, but only if they start at the same time and have the same duration), or to specify that all functions are mutually exclusive (in which case gates using the same instrument can never be parallelized).

The instrument(s) affected by the gate, if any, are selected based on the qubit operands of the gate and upon whether the gate matches a set of predicates. Like the instrument function selection, the predicates are based on custom keys in the instruction definition in the platform configuration file. A different set of predicates can be provided based on the number of qubit operands of the gate.

Configuration structure

The shared instrument resource is configured using the following JSON structure.

{
    "predicate": {
        "<gate-key>": ["<value>", ...],
        ...
    },
    "predicate_1q": ...,
    "predicate_2q": ...,
    "predicate_nq": ...,
    "function": [
        "<gate-key>",
        ...
    ],
    "allow_overlap": [true, false],
    "instruments": [
        {
            "name": "<optional instrument name>",
            "qubit":     [<qubits>],
            "edge":      [<edges>],
            "1q_qubit":  [<qubits>],
            "2q_qubit0": [<qubits>],
            "2q_qubit1": [<qubits>],
            "nq_qubit0": [<qubits>],
            "nq_qubit1": [<qubits>],
            "nq_qubitn": [<qubits>]
        }
    ]
}

All sections except "instruments" are optional. Unrecognized sections throw an error.

Predicates

The predicate section must be a map of string-string or string-list(string) key-value pairs, representing (custom) keys and values in the instruction set definition section for the incoming gate that must be matched. An incoming gate matches the predicate if and only if:

  • its instruction set definition object has values for all keys specified;

  • these keys all map to strings; and

  • the string values match (one of) the specified value(s) for each key.

For example, if an instruction definition looks like this:

"x": {
    "duration": 40,
    "type": "mw",
    "instr": "x"
}

the following predicate configuration will match it:

"predicate": {
    "type": "mw"
}

but will reject a gate defined like this:

"cnot": {
    "duration": 80,
    "type": "flux",
    "instr": "cnot"
}

because its "type" is "flux".

Note

It will also silently reject gates which don’t have the "type" key, so beware of typos!

Should you want to match both types, but not any other type, you could do

"predicate": {
    "type": ["mw", "flux"]
}

Different predicates can be specified for single-, two-, and more-than-two-qubit gates. Both the common predicate and the size-specific predicate must match.

Instrument function selection

The function section can be one of three things:

  • a list of gate keys as specified in the structure above, in which case the selected function is the combination of the (string) values of these keys in the gate definition;

  • an empty list or unspecified, in which case function matching is disabled, always allowing two gates to execute in parallel (but still requiring them to start and end simultaneously); or

  • the string "exclusive", in which case exclusive access is modelled, i.e. matching gates can never execute in parallel.

For example, say that an x gate requires a different instrument function than an y gate, i.e. they cannot be done in parallel, but multiple x gates on different qubits can be parallelized (idem for y), you might use:

"function": [
    "instr"
]

for gates defined as follows:

"x": {
    "duration": 40,
    "type": "mw",
    "instr": "x"
},
"y": {
    "duration": 40,
    "type": "mw",
    "instr": "y"
}

In some cases, it is not necessary for parallel operations requiring the same instrument function to actually start at the same time. For example, an instrument resource modelling qubit detuning would have two states, one indicating that the qubit is detuned, and one indicating that it is not, but as long as it is in one of these states, it doesn’t matter when gates requiring it start and end. This behavior can be specified with the "allow_overlap" option. If specified, it must be a boolean, defaulting to false.

Note

It makes little sense to combine "allow_overlap" with an empty "function" section, because this would disable all constraints on parallelism.

Instrument definition

A single instrument resource can define multiple independent instruments with the same behavior, distinguished by which qubits or edges they’re connected to. This is done using the instruments section. It consists of a list of objects, where each object represents an instrument. The contents of the object define its connectivity, by way of predicates on the qubit operand list of the incoming gates.

  • For single-qubit gates, the instrument is used if and only if the single qubit operand is in the "1q_qubit" or "qubit" list.

  • For two-qubit gates, the instrument is used if any of the following is true:

    • either qubit is in the "qubit" list;

    • the first qubit operand is in the "2q_qubit0" list;

    • the second qubit operand is in the "2q_qubit1" list; or

    • the edge index (from the topology section of the platform) corresponding to the qubit operand pair is in the "edge" list.

  • For three-or-more-qubit gates, the instrument is used if any of the following is true:

    • any of the qubit operands is in the "qubit" list;

    • the first qubit operand is in the "nq_qubit0" list;

    • the second qubit operand is in the "nq_qubit1" list; or

    • any of the remaining qubit operands are in the "nq_qubitn" list.

For example, an instrument defined as follows:

"instruments": [
    {
        "name": "qubit-2",
        "1q_qubit": [2],
        "edge": [1, 9]
    }
]

will be used by single-qubit gates acting on qubit 2, and by two-qubit gates acting on edge 1 or 9 (as defined in the topology section of the platform configuration file). Of course the gate also has to match the gate predicates defined for this resource for it to be considered. When a gate matches all of the above, the instrument function as defined in the function section will (need to) be reserved for this instrument for the duration of that gate, and thus the gate will be postponed if a conflicting reservation already exists.

QWG example

In CC-light, single-qubit rotation gates (instructions with "type": "mw") are controlled by QWGs. Each QWG controls a particular set of qubits. It can control multiple qubits at a time, but only when they perform the same gate (configured using "cc_light_instr") and start at the same time. There are three QWGs, the first of which is connected to qubits 0 and 1, the second one to qubits 2, 3, and 4, and the third to qubits 5 and 6.

This can be modelled with the following configuration:

{
    "predicate": { "type": "mw" },
    "function": [ "cc_light_instr" ],
    "instruments": [
        {
            "name": "QWG0",
            "qubit": [0, 1]
        },
        {
            "name": "QWG1",
            "qubit": [2, 3, 4]
        },
        {
            "name": "QWG2",
            "qubit": [5, 6]
        }
    ]
}

Before resources were generalized, QWGs were modelled with a specific resource type. Its configuration structure instead looked like this for the same thing:

{
    "count": 3,
    "connection_map": {
        "0" : [0, 1],
        "1" : [2, 3, 4],
        "2" : [5, 6]
    }
}

For backward compatibility, this structure is desugared to the complete structure when the instrument resource is constructed using arch.cc_light.qwgs.

Measurement unit example

In CC-light, single-qubit measurements (instructions with "type": "readout") are controlled by measurement units. Each one controls a private set of qubits. A measurement unit can control multiple qubits at the same time, but only when they start at the same time. There were two measurement units, the first of which being connected to qubits 0, 2, 4, 5, and 6, and the second to qubits 1 and 4.

This can be modelled with the following configuration:

{
    "predicate": { "type": "readout" },
    "instruments": [
        {
            "name": "MEAS0",
            "qubit": [0, 2, 4, 5, 6]
        },
        {
            "name": "MEAS1",
            "qubit": [1, 4]
        }
    ]
}

Before resources were generalized, this was modelled with a specific resource type. Its configuration structure instead looked like this for the same thing:

{
    "count": 2,
    "connection_map": {
        "0" : [0, 2, 3, 5, 6],
        "1" : [1, 4]
    }
}

For backward compatibility, this structure is desugared to the complete structure when the instrument resource is constructed using arch.cc_light.meas_units.

Qubit detuning example

In CC-light, two-qubit flux gates ("type": "flux") for particular edges require a third qubit to be detuned (also known as parked). This moves the qubit out of the way frequency-wise to prevent it from being affected by the flux gate as well. However, doing so prevents single-qubit microwave quantum gates ("type": "mw") from using the detuned qubit (and vice versa). Specifically:

  • a two-qubit gate operating on qubits 0 and 2 detunes qubit 3;

  • a two-qubit gate operating on qubits 0 and 3 detunes qubit 2;

  • a two-qubit gate operating on qubits 1 and 3 detunes qubit 4;

  • a two-qubit gate operating on qubits 1 and 4 detunes qubit 3;

  • a two-qubit gate operating on qubits 3 and 5 detunes qubit 6; and

  • a two-qubit gate operating on qubits 3 and 6 detunes qubit 5.

This can be modelled with the following configuration:

{
    "predicate_1q": { "type": "mw" },
    "predicate_2q": { "type": "flux" },
    "function": [ "type" ],
    "allow_overlap": true,
    "instruments": [
        {
            "name": "qubit-2",
            "1q_qubit": [2],
            "edge": [1, 9]
        },
        {
            "name": "qubit-3",
            "1q_qubit": [3],
            "edge": [0, 3, 8, 11]
        },
        {
            "name": "qubit-4",
            "1q_qubit": [4],
            "edge": [2, 10]
        },
        {
            "name": "qubit-5",
            "1q_qubit": [5],
            "edge": [6, 14]
        },
        {
            "name": "qubit-6",
            "1q_qubit": [6],
            "edge": [5, 13]
        }
    ]
}

Before resources were generalized, this was modelled with a specific resource type. Its configuration structure instead looked like this for the same thing:

{
    "count": 7,
    "connection_map": {
        "0": [3],
        "1": [2],
        "2": [4],
        "3": [3],
        "4": [],
        "5": [6],
        "6": [5],
        "7": [],
        "8": [3],
        "9": [2],
        "10": [4],
        "11": [3],
        "12": [],
        "13": [6],
        "14": [5],
        "15": []
    }
}

To be specific, the connection map mapped each edge index to a list of qubits detuned by doing a flux gate on that edge. For backward compatibility, this structure is desugared to the complete structure when the instrument resource is constructed using arch.cc_light.detuned_qubits.

Mutably-exclusive edge example

The above qubit detuning has additional implications for two-qubit gates. Specifically, the following edges are mutably exclusive:

  • q0-q2 (edge 0 and 8) is mutually-exclusive with q1-q3 (edge 2 and 10);

  • q0-q3 (edge 1 and 9) is mutually-exclusive with q1-q4 (edge 3 and 11);

  • q2-q5 (edge 4 and 12) is mutually-exclusive with q3-q6 (edge 6 and 14); and

  • q3-q5 (edge 5 and 13) is mutually-exclusive with q4-q6 (edge 7 and 15).

{
    "predicate": { "type": "flux" },
    "function": "exclusive",
    "instruments": [
        {
            "name": "edge-0_2-1_3",
            "edge": [0, 2, 8, 10]
        },
        {
            "name": "edge-0_3-1_4",
            "edge": [1, 3, 9, 11]
        },
        {
            "name": "edge-2_5-3_6",
            "edge": [4, 6, 12, 14]
        },
        {
            "name": "edge-3_5-4_6",
            "edge": [5, 7, 13, 15]
        }
    ]
}

Before resources were generalized, this was modelled with a specific resource type. Its configuration structure instead looked like this for the same thing:

{
    "count": 16,
    "connection_map": {
        "0": [2, 10],
        "1": [3, 11],
        "2": [0, 8],
        "3": [1, 9],
        "4": [6, 14],
        "5": [7, 15],
        "6": [4, 12],
        "7": [5, 13],
        "8": [2, 10],
        "9": [3, 11],
        "10": [0, 8],
        "11": [1, 9],
        "12": [6, 14],
        "13": [7, 15],
        "14": [4, 12],
        "15": [5, 13]
    }
}

Here, the keys and values in "connection_map" specify edge indices, where usage of the edge in key indicates that the edge indices it maps to can no longer be used. Note that the i+8 edge is not in the second list because it maps to the inversed-direction edge, which is already excluded by mutual exclusion of the qubits themselves. For backward compatibility, this structure is desugared to the complete structure when the instrument resource is constructed using arch.cc_light.edges.

Multi-core channel resource

Type names: InterCoreChannel.

This resource models inter-core communication with limited connectivity between cores. This is modelled as follows.

Each core has a limited number of channels, with which it can connect to other cores. The connectivity between the channels of each core is assumed to be fully connected, but the number of channels per core can be adjusted. Gates matching the predicate (if any) use one of the available core/channel pairs for each core that they use (communication) qubits of. The core is of course determined by the qubit index, but the channel is undefined; the resource will use the first available channel.

The resource is configured using the following structure.

{
    "predicate": {
        "<gate-key>": ["<value>", ...],
        ...
    },
    "predicate_1q": ...,
    "predicate_2q": ...,
    "predicate_nq": ...,
    "inter_core_required": <boolean, default true>,
    "communication_qubit_only": <boolean, default false>,
    "num_channels": <number of channels per core, default 1>
}

Note that the number of cores and communication qubits per core are configured in the topology section of the platform JSON configuration data. These settings are not repeated here.

The predicate section must be a map of string-string or string-list(string) key-value pairs, representing (custom) keys and values in the instruction set definition section for the incoming gate that must be matched. An incoming gate matches the predicate if and only if:

  • its instruction set definition object has values for all keys specified;

  • these keys all map to strings; and

  • the string values match (one of) the specified value(s) for each key.

Different predicates can be specified for single-, two-, and more-than-two-qubit gates. Both the common predicate and the size-specific predicate must match.

Furthermore, gates can be predicated based on whether they actually use qubits from multiple cores. This is controlled by "inter_core_required". When set or unspecified, a gate must operate on qubits belonging to at least two different cores to match the predicate. Otherwise, this is not required. That is, a gate matching the other predicates that uses only qubits from one core would still use channel resources for that core. This is mostly for compatibility with the original channel resource, which didn’t check for this.

The "communication_qubit_only" flag controls whether all qubits of a gate use communication channel resources, or whether only qubits marked as communication qubits are considered.

Finally, the "num_channels" key specifies how many independent channels each core has. The default and minimum value is 1.

Qubit resource

Type names: Qubit or arch.cc_light.qubits.

This resource ensures that a qubit is only ever in use by one gate at a time.

Note

It assumes that a gate with a qubit operand actually uses this operand for its entire duration, so it may be overly pessimistic.

This resource does not have any JSON configuration options. Historically it had a “count” key specifying the number of qubits, but this is now taken from the platform’s qubit count. Any JSON options that are passed anyway are silently ignored.

CC-light channels resource

Type names: arch.cc_light.channels.

Compatibility wrapper for the CC-light channels resource. This does exactly the same thing as the InterCoreChannel resource, but accepts the following configuration structure:

{
    "count": <number of channels>
}

This structure is converted to the following for use with the InterCoreChannel resource:

{
    "predicate": { "type": "extern" },
    "inter_core_required": false,
    "communication_qubit_only": false,
    "num_channels": <taken from "count">
}

CC-light detuned_qubits resource

Type names: arch.cc_light.detuned_qubits.

Compatibility wrapper for the CC-light detuned qubit resource. This is the same resource type as Instrument, but accepting a different JSON configuration structure for backward compatibility. Refer to the documentation of the Instrument resource for more information; everything is explained there.

CC-light edges resource

Type names: arch.cc_light.edges.

Compatibility wrapper for the CC-light edge resource. This is the same resource type as Instrument, but accepting a different JSON configuration structure for backward compatibility. Refer to the documentation of the Instrument resource for more information; everything is explained there.

CC-light meas_units resource

Type names: arch.cc_light.meas_units.

Compatibility wrapper for the CC-light measurement unit resource. This is the same resource type as Instrument, but accepting a different JSON configuration structure for backward compatibility. Refer to the documentation of the Instrument resource for more information; everything is explained there.

CC-light qwgs resource

Type names: arch.cc_light.qwgs.

Compatibility wrapper for the CC-light QWG resource. This is the same resource type as Instrument, but accepting a different JSON configuration structure for backward compatibility. Refer to the documentation of the Instrument resource for more information; everything is explained there.