qat-core: Core data structures and Abstract classes

Abstract classes

Following classes may be used to define new Plugins or QPUs.

class qat.plugins.AbstractPlugin

Abstract interface of a Plugin.

abstract compile(batch, specs)

Compiles a Batch into another Batch according to some hardware specs

do_post_processing()

Returns True iff the results need to be aggregated/post processed via the plugin.

serve(port, host_ip='localhost', server_type=None)

Runs the plugin inside a server

Parameters
  • port (int) – the port on which to listen

  • host_ip (str) – the url on which to publish the API. Optional. Defaults to ‘localhost’.

  • server_type (str, optional) –

    type of server. The different types of server are:

    • ”simple”: single-thread server, accepts one connection at a time (default server type)

    • ”threaded”: multi-thread server, each connection starts a new thread

    • ”pool”: multi-thread server, each connection runs in a thread, with a maximum of 10 running threads

    • ”fork”: multi-process server, each connection runs in a new process

wrapper_post_process(results)

Call post process function and wrap the result in a PostProcessResult object

class qat.core.qpu.QPUHandler

Abstract class describing the mininmal QPU interface.

The minimal interface is the implementation of the submit_job method:

This method should return a Result structure corresponding to the execution of a Job.

serve(port, host_ip='localhost', server_type=None)

Runs the QPU inside a server

Parameters
  • port (int) – the port on which to listen

  • host_ip (str) – the url on which to publish the API. Optional. Defaults to ‘localhost’.

  • server_type (str, optional) –

    type of server. The different types of server are:

    • ”simple”: single-thread server, accepts one connection at a time (default server type)

    • ”threaded”: multi-thread server, each connection starts a new thread

    • ”pool”: multi-thread server, each connection runs in a thread, with a maximum of 10 running threads

    • ”fork”: multi-process server, each connection runs in a new process

submit(batch: qat.core.wrappers.batch.Batch, meta_data: Optional[dict] = None) → qat.core.wrappers.result.BatchResult

Executes a batch of jobs and returns the corresponding list of Results.

Parameters

batch (Batch) – a batch of jobs. If a single job is provided, the job is embedded into a Batch, executed, and the first result is returned.

Returns

a batch result

Return type

(BatchResult)

abstract submit_job(job: qat.core.wrappers.job.Job) → qat.core.wrappers.result.Result

Returns a Result structure corresponding to the execution of a Job.

Note

Notice that the job can be assumed to be already compiled/optimized.

This is the end of the pipe!

Parameters

job (Job) – the job to execute

Returns

a result

Return type

(Result)

Remote interfaces

QPUs and Plugins can be used in client/server mode. Any Plugin or QPU, once constructed, can be published via their serve method (see right above).

Once published, a client can connect and interact with them via one of the two following classes:

class qat.core.qpu.RemoteQPU

RemoteQPUs are built from a port and an ip address. They behave similarly to a local QPU Handler but also allow adjunction of local Plugins. The information flow inside a RemoteQPU is comparable to the information flow inside a QPUHandler:

  • when compiling a batch the batch goes through all the local plugins and is sent to the connection. The resulting batch is then returned to the user

  • when submitting, the batch is compiled using the local plugins and then forwarded through the connection. The results are then post

    processed by the local Plugins.

Parameters
  • port (optional, int) – the port to connect to

  • ip (optional, str) – the IP address to connect to

  • plugins (list<qat.plugins.AbstractPlugins>) – a list of plugins. Optional. Defaults to None.

  • connection (optional Thrift connection) – for internal use

class qat.core.plugins.RemotePlugin

RemotePlugins are built from a port and an ip address.

Parameters
  • port (optional, int) – a port to connect to

  • ip (optional, str) – the IP address to connect to

  • connection (optional, Thrift connection) – for internal use

Batch and Job

Following are used to send a circuit or a set of circuit to a plugin or to a QPU. The circuit is then compiled or executed. The Job class is used to send a single Circuit to a QPU whereas the Batch class is used to send several Circuit objects at the same time.

class qat.core.Job

A high level wrapper for the Job thrift class.

Instance attributes:
  • circuit (Circuit): circuit to execute

  • schedule (Schedule): schedule to execute

  • type (ProcessingType): type of Job

  • observable (Observable, optional): the observable (required if job type is of type 1, i.e observable sampling)

  • qubits (list<int>, optional): measured qubits

  • nbshots (int): number of required shots: if 0, do maximal number of shots

  • aggregate_data (bool): contract corresponding result object

  • amp_threshold (float, optional): amplitude values under this threshold are considered null

dump(fname)

Dumps the job in a binary file.

Parameters

fname (str) – the file name

classmethod from_thrift(tobject)

Builds a Job from a thrift job

get_variables()

Returns the set of all variables appearing in the job

classmethod load(fname)

Loads the Job from a binary file.

Parameters

fname (str) – the file name

Returns

Job

property psi_0

Initial state

Processing types for jobs are defined via an enum class:

class qat.comm.shared.ttypes.ProcessingType

Different types of processings of the final quantum state.

Possible values:
  • SAMPLE=0: sampling in the computational basis

  • OBSERVABLE=1: observable sampling

class qat.core.Batch

Simple higher level wrapper for the serializable Batch class.

Instance attributes:
  • jobs (list<Job>): jobs composing the batch

  • meta_data (dict<str, str>): meta data

dump(fname)

Dumps the Batch inside a file in binary format.

Parameters

fname (str) – the file name

classmethod from_thrift(tobject)

Builds a Batch object from a thrift batch

get_variables()

Returns the of all variables appearing in the Batch.

static load(fname)

Loads a Batch from a file.

Parameters

fname (str) – the file name

Returns

Batch

Observables

class qat.core.Observable

Class describing an observable (i.e some Hermitian operator) over the Hilbert space spanned by a list of qbits.

The observable is stored as a sum of Terms, each composed of a Pauli operator and a real coefficient.

The purpose of this class is mainly to efficiently automatize the sampling of this observable on the final state obtained after a computation.

Construction:

An Observable object can be constructed in various ways:

using a matrix representation:

using a list of Term:

Parameters
  • nqbits (int) – number of qubits

  • matrix (np.array, optional) – the matrix representing the observable. Defaults to None.

  • pauli_terms (list<Term>, optional) – the list of products of Pauli operators representing the observable. Defaults to None.

  • constant_coeff (float) – a constant additive term

terms

the list of products of Pauli operators representing the observable.

Type

list<Term>

nbqbits

the number of qbits on which the observable acts

Type

int

constant_coeff

a constant additive term

Type

float

class qat.core.Term

Class describing a term in the Pauli basis of an observable. It basically consists in a pair (coeffcient, pauli operator).

This class supports Thrift serialization and can be transmitted directly to the to_job method of a circuit object.

Term are constructed as follows:

from qat.core import Term

term = Term(1., # Coefficient of the term
            "XXY", # tensor of operators X, X, and Y
            [1, 4, 7]) # over qubits 1, 4, and 7
Parameters
  • coefficient (float) – the coefficient in front of the term

  • pauli_op (str) – the Pauli operator specified as a string containing I, X, Y, and Z characters.

  • qbits (list<int>) – the list of concerned qubits

coeff

the coefficient in front of the term

Type

float

op

the Pauli operator specified as a string containing I, X, Y, and Z characters.

Type

str

qbits

the list of concerned qubits

Type

list<int>

Results

A result is composed of several samples or, is an observable is measured, of a scalar. The result data structure is Result

class qat.core.Result

Simple higher level wrapper for the serializable Result class.

Parameters
  • result (ThriftResult, optional) – result

  • lsb_first (bool, optional) – whether to use convention with least significant bit first. Defaults to False.

  • nbqbits (int, optional) – number of qubits, required if lsb_first is False. Defaults to None.

Instance attributes:
  • raw_data (list<Sample>, optional): the raw data sampling, if requested

  • value (float, optional): scalar output

  • value_data (map<str, float>, optional): Informationon the scalar output (deviation, etc)

  • meta_data (map<str, str>): any information the QPU might want to transmit to the user (logs, resource usage, etc)

  • has_statevector (bool): set to True iff the .statevector attribute is non-empty

  • statevector: a low level description of the result. Usually contains a numpy array describing either a state vector or a probability distribution. Not always set.

add_sample(state, amplitude=None, probability=None, err=None, intermediate_measurements=None)

Add sample to result. If required, reverts bit order.

Parameters
  • state (int) – the index of the state in comput. basis

  • amplitude (complex, optional) – a complex number for the amplitude

  • probability (float, optional) – the probability

  • err (float, optional) – the error on the probability estimate

  • intermediate_measurements (IntermediateMeasurements, optional) – the intermediate measures

dump(fname)

Dumps the Result inside a file in binary format.

Parameters

fname (str) – the file name

classmethod from_thrift(tobject)

Builds a Result object from a thrift object

static load(fname)

Loads a Result from a file.

Parameters

fname (str) – the file name

Returns

Result

property value

Scalar output - complex number

property values

Scalar output - complex number

wrap_samples(qreg_list)

Wraps the samples using a list of quantum registers Also serializes the underlying statevector object, if any

class qat.core.wrappers.result.Sample

Simple higher-level wrapper for the serializable Sample class.

Parameters

qregs (QRegister) – quantum register

Instance attributes:
  • state (State): the measured state

  • probability (float, optional): the probability of the state (infinite number of shots/samples, for simulators only), or frequency of the state (finite number of shots)

  • amplitude (complex, optional): optionally (for simulators), the amplitude of the state

  • intermediate_measurements (IntermediateMeasurement): list of intermediate measurements

  • err (float, optional): optionally, the sampling error: if the number of samples is finite, it is the estimate of the standard error on the mean \(\varepsilon_{k}\equiv\sqrt{\langle\left(p_{k}-f_{k}\right)^{2}\rangle}\), where \(p_k\) is the true probability of obtaining state \(|k\rangle\) and \(f_k\) its estimate. if the number samples is infinite (simulator only), it is the error bar on the computed probability (for approximate simulators only, like stochastic simulators)

property amplitude

Returns the amplitude of the Sample (wrapped in a Python complex number)

classmethod from_thrift(tobject)

Builds a Sample object from a thrift object

set_qreg(qregs)

Sets the quantum register information for pretty display and cast of states

property state

Gets the state of the sample. The state may be wrapped in a State object

class qat.core.wrappers.result.State

Class representing a ‘classical’ state

Its __str__ method is overloaded to possibly take a QRegister type as format argument.

Parameters
  • int_msb_value (int) – the state (integer, msb format)

  • qregs (list<QRegister>, optional) – a list of QRegister to use for formatting purposes.

property bitstring

Returns a bitstring representation of the state

property int

Returns a msb representation of the state

property lsb_int

Returns a lsb reprensentation of the state

property value

Casts the state into a classical value using the information from the quantum registers

class qat.comm.shared.ttypes.IntermediateMeasurement

Data structure representing outcome of an intermediate measurement.

- cbits

list<bool> the list of classical bits resulting from the measurement

- gate_pos

int the position of the measurement in the circuit

- probability

optional, float, the probability of this precise measurement outcome

class qat.core.BatchResult

Simple higher level wrapper for the serializable BatchResult class.

Parameters

kwargs (keyword arguments) – accepted arguments are results (a list of Result objects) and meta_data (a (str, str) map).

Instance attributes:
  • results (list<Result>): list of results

  • meta_data (dict<str, str>): meta data

append(value)

Add a result in the list of results

Parameters

value (Result) –

dump(fname)

Dumps the BatchResult inside a file in binary format.

Parameters

fname (str) – the file name

extend(values)

Add several results in the list of results

Parameters

values (list<Result>) –

classmethod from_thrift(tobject)

Builds a BatchResult object from a thrift object

static load(fname)

Loads a BatchResult from a file

Parameters

fname (str) – the file name

Returns

BatchResult

Circuits

Here is the basic interface of the circuit class. For more information on the various attributes the circuit object, please refer to Exceptions. For instance, one can easily concatenate two Circuit objects (as long as they have the same number of qubits):

cat_circuit = circuit1 + circuit2

Tensorial composition is implemented via an overloading of the __mult__ operator:

kron_circuit = circuit1 * circuit2

Among the other useful methods, we can find:

  • the direct generation of a Job object from a circuit using various parameters:

    job = circuit.to_job(job_type="SAMPLE", nbshots=1024, qubits=[0, 3, 7])
    
  • (de)serialization of a circuit:

    circuit.dump("my_circuit.circ")
    circuit = Circuit.load("my_circuit.circ")
    
  • binding of an abstract variable:

    new_circuit = circuit(theta=0.34)
    # or, equivalently
    new_circuit = circuit.bind_variables({theta: 0.34})
    
class qat.core.Circuit

Simple higher level wrapper for the serializable Circuit class.

This wrapper provides high-level manipulation routines such as variable binding or iteration.

Circuits are usually built using the .to_circ method of the Program class, and are not designed to be built by hand.

The simplest way to explore the content of a circuit is to use the .iterate_simple method that provides a user friendly sequence of instructions:

from qat.lang.AQASM import *
prog = Program()
cbits = prog.calloc(4)
qbits = prog.qalloc(4)
for qb in qbits:
    H(qb)
RX(prog.new_var(float, "a")).ctrl(3)(qbits)
CNOT(qbits[0], qbits[1])
prog.measure(qbits[1])
prog.reset([qbits[3]], [cbits[2]])

circuit = prog.to_circ()

for op in circuit.iterate_simple():
    print(op)
('H', [], [0])
('H', [], [1])
('H', [], [2])
('H', [], [3])
('C-C-C-RX', [<qat.core.variables.Variable object at 0x1473fdf4c5c0>], [0, 1, 2, 3])
('CNOT', [], [0, 1])
('MEASURE', [1], [1])
('RESET', [3], [2])
bind_variable(v_name, v_value, gate_set=None)

Bind variable v_name with value v_value. Returns a fresh circuit. If binding the variable result in a gate becoming fully defined, its matrix will be regenerated using the default gate set of pyAQASM (or using a custom gate set).

..warning:

For performances reasons, this method does not fully copy the circuit. In particular, modifying some portions of the resulting circuit will have a side effect of the initial circuit. To avoid this behavior, feel free to deepcopy the circuit beforehand.

Parameters
  • v_name (str) – the variable name

  • v_value (any) – the value

  • gate_set (optional, GateSet) – a gate set to use to generate the matrices for freshly bound gates

Returns

a quantum circuit

Return type

Circuit

bind_variables(v_dictionary, gate_set=None, **kwargs)

Iterates bind_variable() over a dictionary of (names, values).

Parameters
  • v_dictionary (map<str,any>) – the variable names/values dictionary

  • gate_set (optional, GateSet) – a gate set to use to generate the matrices for freshly bound gates. If not None, the current gate set will be updated and used to fill the matrices

Returns

a quantum circuit.

Return type

Circuit

dump(fname)

Dumps the circuit in a binary file (.circ)

Parameters

fname (str) – the file name

static empty(nbqbits)

Generates an empty circuit

Parameters

nbqbits (int) – the number of qbits of the circuit

Returns

an empty circuit

Return type

Circuit

fill_matrices(gate_set, submatrices_only=True, include_default_gate_set=False)

Attaches matrices to gates according to the matrix generators in gate_set.

Parameters
  • gate_set (GateSet) – a gate set specifying the matrix generators of the gates present in the circuit. Note that if some gate has no corresponding entry in the gate set or its signature has no matrix generator, no matrix will be attached to its definition.

  • submatrices_only (bool) –

    If set to True, only subgate will receive matrices. Default to True.

  • include_default_gate_set (bool) – if set to True, the native gate set of pyAQASM will be included. Default to False.

classmethod from_thrift(tobject)

Builds a Circuit from a thrift circuit

property gate_set

The gate set used to generate the circuit

get_variables()

Returns the set of variables appearing in the circuit

insert_gate(position, gate, qbits, **kwargs)

Inserts a pyAQASM gate inside the circuit.

Parameters
  • position (int) – index where to insert the gate

  • gate (Gate) – a pyAQASM gate (or routine)

  • qbits (list<int>) – a list of integers

  • kwargs (dict) – all the keyword arguments are fed to the linker

iterate_simple(depth=None)

Iterates over the instructions of the circuit in a user friendly way.

The iterator yields tuples with explicit content. Each tuples starts with a keyword or a gate name, followed by the arguments of the instruction.

E.g, a measure of qubits 0 and 1 stored in cbits 2 and 3 would yield:

("MEASURE", [0, 1], [2, 3])
classmethod load(fname)

Loads a circuit from a binary (.circ) file.

Parameters

fname (str) – the file name

Returns

a circuit

Return type

Circuit

remove_locks()

Remove all lock/release placeholders of the circuit.

to_job(job_type='SAMPLE', qubits=None, nbshots=0, aggregate_data=True, amp_threshold=9.094947017729282e-13, **kwargs)

Generates a Job containing the circuit and some post processing information.

Parameters
  • job_type (str) – possible values are “SAMPLE” for computational basis sampling of some qubits, or “OBS” for observable evaluation (see qat.core.Observable for more information about this mode).

  • qubits (optional, list<int>, list<QRegister>) – the list of qubits to measure (in “SAMPLE” mode). If some quantum register is passed instead, all the qubits of the register will be measured. Moreover, if the register was “typed” (see qat.lang.AQASM.Program.qalloc() for more information), the results will be cast into the register type. Defaults to None, meaning all qubits are to be measured.

  • nbshots (optional, int) – The number of shots to perform. Defaults to zero. If set to zero, the convention is that the QPU should do its best: a quantum processor will use the largest amount of shot authorized by its configuration, while a simulator will try to output all the possible states constained in the final distribution, together with their probabilities (and possible amplitudes).

  • aggregate_data (optional, bool) – if set to True, and nbshots is not zero, the samples will be aggregated and their probability field will be used to store their observed frequencies of apparition. Defaults to True.

  • amp_threshold (optional, double) – amplitude threshold under which states are not returned in the result structure. Useful to prune states that are unlikely to be measured out of the returned samples. Defaults to 1/2^40.

Keyword Arguments

observable (Observable) – see Observable. Used for the “OBS” mode only).

Displaying circuits

Circuits could be displayed is a notebook or inside a terminal. To display a circuit in a terminal, you can use the function qat.core.console.display()

qat.core.console.display(circuit, max_depth=0, circuit_name=None, batchmode=False)

Displays a circuit on the terminal using ASCII art. By default, calls to sub-circuits are not inlined when displaying. You can display the content of a sub-circuit by increasing the maximal depth of inlining.

from qat.core.console import display
from qat.lang.AQASM import Program
from qat.lang.AQASM.qftarith import add

# Define circuit
prog = Program()
qbits = prog.qalloc(5)
prog.apply(add(3, 2), qbits)
circ = prog.to_circ()

# Display circuit
display(circ)

# Display implementation of "add"
display(circ, max_depth=1)

# Display full circuit
display(circ, max_depth=None)
Parameters
  • circuit (Circuit) – displayed circuit

  • max_depth (int, optional) – maximal depth of inlining (None is maximal)

  • circuit_name (str, optional) – name of the circuit

  • batchmode (bool, optional) – if this variable is set to True, this function will not wait for user input

Warning

Only GATETYPE operators can be visualized in a terminal. An exception is raised if your circuit contains measures, gates controlled classically, logic operators, …

The %qatdisplay magic can be used to display a circuit in a notebook or in an IPython terminal.

If myQLM Python magics has not been installed, please refer to the magic installation page to install this magic command

%qatdisplay circuit

Hardware specifications

Hardware specifications are described by a the class HardwareSpecs

class qat.core.HardwareSpecs

Simple higher level wrapper for the serializable HardwareSpecs class.

Instance attributes:
  • nbqbits (int): number of qubits

  • topology (Topology): topology

  • gateset (GateSet): the gate set of the hardware

  • description (str): description of the hardware

as_graph()

Returns a networkx.Graph object corresponding to the topology. This function calls the method to_nx() of the class Topology

from qat.devices import RIGETTI_ASPEN

# Cast the device into a networkx graph
nx_graph = RIGETTI_ASPEN.as_graph()
Returns

graph describing the topology of this hardware specs

Return type

networkx.Graph

as_quameleon()

Returns a QuameleonPlugin instance enforcing the device’s connectivity for easy inclusion in a QLM stack

from qat.devices import RIGETTI_ASPEN
from qat.qpus import get_default_qpu

# Create a stack
stack = RIGETTI_ASPEN.as_quameleon() | get_default_qpu()
print(stack)
QuameleonPlugin | PyLinalg
Returns

Quameleon plugin

Return type

QuameleonPlugin

dump(fname)

Dumps the HardwareSpecs inside a file in binary format.

Parameters

fname (str) – the file name

classmethod from_thrift(tobject)

Builds a HardwareSpecs object from a thrift object

static load(fname)

Loads a HardwareSpecs from a file.

Parameters

fname (str) – the file name

Returns

HardwareSpecs

property nbqbits

Number of qubits composing the hardware

property topology

Topology of the hardware

class qat.core.Topology

Simple higher-level wrapper for the serializable Topology class.

Parameters
  • topology (ThriftTopology, optional) – serializable object describing the topology

  • is_directed (bool, optional) – set the topology directed or undirected (used if your topology is Custom). If your topology is undirected, any qubit of a pair is either a control or a target qubit, otherwise, only one qubit of the pair is the control qubit. The topology is, by default, undirected

  • type (TopologyType, optional) – type of the topology (All to All, LNN or Custom)

  • graph (dict<int, list<int>>, optional) – graph describing the topology (required iff the topology is Custom). Any key of this dictionary corresponds to the index of a control qubit and each linked value corresponds to indexes of qubits which can be target of this control qubit

add_edge(qb1, qb2)

Update connectivity between qubits. The topology will be set to CUSTOM (if needed). Use this method if a two qubits gate can be applied between qubits of indexes qb1 and qb2

Note

If your topology is directed, the first argument is the control qubit.

Parameters
  • qb1 (int) – index of the first qubit

  • qb2 (int) – index of the second qubit

dump(fname)

Dumps the Toplogy inside a file in binary format.

Parameters

fname (str) – the file name

static from_nx(nx_graph, vmap=None)

Builds a Topology object from a networkx Graph

Parameters
  • nx_graph (networkx.Graph) – a networkx Graph

  • vmap (optional, dict) – if set, the dictionary is update with a map that maps graph nodes to qubit indexes

classmethod from_thrift(tobject, init_none=False)

Builds a Topology object from a thrift topology object

static load(fname)

Loads a Topology from a file.

Parameters

fname (str) – the file name

Returns

Topology

to_nx()

Cast the Topology object into a networkx graph.

Returns

a networkx graph

Return type

nx.Graph

class qat.core.TopologyType

This class is a enumeration describing the type of a Topology. Currently, there are three types of topologies:

All To All (ALL_TO_ALL)

This type describes topologies for which two-qubit gates can be applied on any pair of qubits

from qat.core import Topology, TopologyType

all_to_all = Topology(type=TopologyType.ALL_TO_ALL)

Linear (LNN)

This type describes topologies for which two-qubit gates can only be applied on qubits having consecutive indexes (i.e. a two-qubit gate can only be applied on the qubits of indexes \(i\) and \(i \pm 1\))

from qat.core import Topology, TopologyType

lnn = Topology(type=TopologyType.LNN)

Custom (CUSTOM)

This type describes a custom topology. Objects of type Topology having a custom topology type must have a graph

from qat.core import Topology, TopologyType

# Init topology
custom = Topology(type=TopologyType.CUSTOM)

# Graph definition
custom.add_edge(0, 1)
custom.add_edge(0, 2)

Gate set and gate signatures

These classes are core classes hidden behind qat.lang.AQASM.gates.AbstractGate class.

class qat.core.gate_set.GateSignature

GateSignatures describe gate constructors. They are defined via a constructor name and a list of argument types.

Parameters
  • name (str) – the name of the gate

  • arg_types (list<type>) – a list of python types describing the types of the arguments. Supported types are: int, float, str, np.matrix, np.ndarray, list.

  • arity (int, optional) – the arity of the gate is known in advance

  • matrix_generator (func, optional) – a function that generates the gates matrix when provided with a set of parameters

  • circuit_generator (func, optional) – a function that generates a Circuit implementing the gate when provided with a set of parameters

get_circuit(*args)

Generates a circuit corresponding to a set of parameters.

Parameters

*args (list<Any>) – a list of parameters

get_matrix(*args)

Returns the matrix corresponding to a set of parameters.

Parameters

*args (list<Any>) – a list of parameters

set_circuit_generator(gen)

Sets the circuit generator.

Parameters

gen (fun) – a function that generates a Circuit given the appropriate parameters

set_matrix_generator(gen)

Sets the matrix generator.

Parameters

gen (fun) – a function that generates a numpy matrix given the appropriate parameters

class qat.core.gate_set.GateSet

Gate sets represent collections of GateSignature.

Parameters

dictio (dict) – a (str, GateSignature) dictionary

add_signature(signa)

Adds a new GateSignature in the GateSet. If the signature redefines a gate, a GateSyntaxRedefinition is raised.

Parameters

signa (GateSignature) – a gate signature

union(new_gate_set)

Compute the union of the gate set with another gate set

Parameters

new_gate_set (GateSet) – another gate set

Returns

the union of both gate sets

Return type

GateSet

class qat.core.gate_set.GateSyntaxRedefinition

Exception raised when a GateSyntax is redefined in a GateSet

Variables and expressions

When defining variational circuit, pyAQASM provides its own way to declare variables (via the qat.lang.AQASM.Program.new_var() method). However, it is possible to turn most parts of a Job into a parametrized quantity using qat.core.Variable objects.

class qat.core.Variable

Class for typed variables. Variables can be used in any python arithmetic expression to build an ArithExpression object.

Parameters
  • name (str) – the variable name

  • var_type (type) – the variable type. Default to float.

Note

For now, the var_type argument is simply ignored.

Warning

Variable with names that can be cast to numerical values are forbidden:

get_variables()

Returns a singleton containing the name of the variable .

to_thrift()

Generates a thrift RPN version of the expression. This is used to store the expression in a serializable format.

from qat.core import Variable
a, b = Variable("a"), Variable("b")
expr = a + b
print(expr)
print(expr.to_thrift())
(a + b)
+ a b
class qat.core.variables.ArithExpression

Class to represent arbitrary arithmetic expressions.

This class is not designed to be instantiated by hand. Expressions are constructed by calling a Symbol object on one or several variables.

Additionally, expressions (and variables) have their numeric operator overloaded (i.e +, -, etc).

from qat.core.variables import cos, Variable

a = Variable("a")
print(type(cos))
expr = cos(a)
print(type(expr))
<class 'qat.core.variables.Symbol'>
<class 'qat.core.variables.ArithExpression'>
Parameters
  • symbol (Symbol) – the symbol labeling the node

  • children (list) – the list of children of the node. These could be variables, expressions, or constants

static from_string(thrift_string, var_dic=None)

Builds an arithmetic expression out of a RPN string.

Effectively the inverse of the to_thrift method.

from qat.core.variables import ArithExpression

expr = ArithExpression.from_string("+ a b")
print(expr)
(a + b)
Parameters
  • thrift_string (str) – a RPN string

  • var_dic (optional, dict) – a dictionary of variables as found in a Circuit

get_variables()

Returns the set of variables appearing inside the expression.

Returns

a set of variable indexes

Return type

set<int>

pretty_print(depth=0)

Pretty prints the expression for debugging (mostly)

to_thrift()

Generates a thrift RPN version of the expression.

See Variable method with the same name.

Returns

a string representation

Return type

str

It is possible to extend the set of symbols supported by this abstract expression mecanics by extending the list of a symbols with a new qat.core.variables.Symbol. The only constraint is that the new symbols should have a fixed arity that is known in advance.

class qat.core.variables.Symbol

A simple structure to describe labels in the AST of an arithmetic expression.

A symbol requires:
  • a token representing the symbo

  • a proper python function that implements the symbol for numerical values

  • an arity (i.e a number of arguments)

For instance, the cos symbol of this module is declared as follows:

from qat.core.variables import Symbol
import numpy as np
cos = Symbol("cos", np.cos, 1)
print(cos)
print(type(cos))
print(cos(np.pi))
cos
<class 'qat.core.variables.Symbol'>
-1.0

Its __call__ operator is overloaded in order to behave as the underlying function for numeric values and to build an ArithExpression when called on abstract expressions or variables.

Parameters
  • token (str) – the token corresponding to the symbol

  • evaluator (callable) – the proper function underlying the symbol (i.e the semantic)

  • arity (int) – the expected arguments of the symbol

  • infix (bool) – If set to True, the symbol will be displayed in infix format (only allowed when arity=2). Defaults to False.

  • pretty_token (optional, str) – If set, the pretty token will be used when displaying the symbol.

Defined symbols can be accessed via the ALL_SYMBOLS module variable:

from qat.core.variables import ALL_SYMBOLS

for token, symbol in ALL_SYMBOLS.items():
    print(token, symbol.evaluator, symbol.arity)
+ <cyfunction <lambda> at 0x14989d942430> 2
* <cyfunction <lambda> at 0x14989d9424f8> 2
- <cyfunction <lambda> at 0x14989d9425c0> 2
UMINUS <cyfunction <lambda> at 0x14989d942688> 1
/ <cyfunction <lambda> at 0x14989d942750> 2
** <cyfunction <lambda> at 0x14989d942818> 2
cos <ufunc 'cos'> 1
sin <ufunc 'sin'> 1
exp <ufunc 'exp'> 1
sqrt <ufunc 'sqrt'> 1
heaviside <cyfunction <lambda> at 0x14989d9428e0> 3

For instance, the following piece of code adds a new symbol that represents the min between two numeric values.

from qat.core.variables import Variable, Symbol, ALL_SYMBOLS

# token will "min"
# underlying function is the standard `min`
# it has arity 2
# it is not an infix operator
my_min = Symbol("min", min, 2, infix=False)

# This step is necessary if we want to be able to bind variables in expressions containing min
ALL_SYMBOLS["min"] = my_min

a, b = Variable("a"), Variable("b")

expr = my_min(a, b)
print(expr)
print(expr(a=3))
print(expr(a=3, b=4))
min(a,b)
min(3,b)
3

Various methods and tools

qat.core.formula_eval.evaluate(formula_str, tab)

Evaluate a logical formula stored in prefix format inside a string.

Parameters
  • formula_str (str) – a string

  • tab (list<bool>) – a list of values of the cbits

Returns

bool

qat.core.circuit_builder.matrix_util.get_predef_generator()

Returns a map of all the matrices of constant gates in the default gate set

qat.core.circuit_builder.matrix_util.get_param_generator()

Returns a map containing the 4 default parametrized gates generators

qat.core.circuit_builder.matrix_util.default_gate_set()

Generates a fresh default gate set

Plugins & Junctions

class qat.plugins.Junction

Junctions are elements of a stack that allow for iterations inside a QLM stack. They implement the standard QPU interface (submit, submit_job, etc), but can be seen as some kind of iterative plugin that delegates execution of jobs to the lower part of the stack.

Junctions can be composed via the pipe operator to be included saemlessly into QLM stacks.

Parameters

collective (bool, optional) – if set to True, the .run method will receive the full batch. If set to False, .run will receive the jobs one by one. Defaults to False.

execute(qlm_object)

Executes a new Job or Batch back using the lower part of the stack.

Parameters

qlm_object (Job or Batch) – the qlm object to transmit down the stack

Returns

a Result structure corresponding to the transmitted Job or Batch

Return type

BatchResult or Result

abstract run(initial_object, meta_data)

This function will be called upon the reception of a fresh abstract QLM object (e.g a Job or a Batch depending the Junction configuration)

Warning

This is an abstract method with no default implementation. You should build your own junction by inheriting from this class and implementing your own .run method.

Parameters
  • qlm_object (Job or Batch) – the initial abstract QLM object. The type depends on the constructor parameter collective: if set to True, a Batch will be provided. If False, a Job.

  • meta_data (dict) – the meta data of the initial batch. This is helpful to transmit arguments from the client to the Junction

Returns

this method should return a Result or BatchResult depending on the collective constructor parameter

Return type

Result, BatchResult

class qat.plugins.Optimizer

A particulized Junction that provides a higher level, QLM independant interface to perform variational optimization.

Instead of providing a .execute method, it provides a .evaluate method that takes a map of <variablename, value> and returns a float.

The administrative burden on binding the variables of the abstract job and fetching the result’s value is done by the class itself, under the hood.

Parameters
  • collective (optional, bool) – see Junction class constructor arguments

  • **binding_kwargs (dict) – a collection of arguments passed to the variable binding method of the job. E.g gate set, matrix generation parameters, etc.

evaluate(values)

Bind variables into the abstract job/batch, execute the job/batch and return the “value” field of the returned Result object or the sum of the result values if a BatchResult is returned.

Parameters

values (dict) – a dictionary of values (str, float)

Returns

a floating point number or a complex, depending on the structure of the Job

Return type

float or complex

abstract optimize(var_names)

This function will be called upon the reception of a fresh abstract QLM object (e.g a Job or a Batch depending the Junction configuration).

Upon reception of a fresh QLM object (Job, Batch), the object is stored in the self.job attribute, and this method is called with as single argument the list of all the variables appearing inside the object.

Warning

This is an abstract method with no default implementation. You should build your own optimizer by inheriting from this class and implementing your own .optimize method.

Parameters

var_names (list) – the list of variables to optimize upon

Returns

this method should return a triplet of values with:

  • the optimal value found (this will correspond to the .value field in the final result object)

  • the optimal values of the parameters (these will be stored in the meta_data using the “parameters” key in the final result object)

  • any additional information (these will be also stored in the meta_data field using the “optimizer_data” key)

Return type

(float, list/np.ndarray, object)