parityos_addons

class parityos_addons.interfaces.CirqExporter(parameter_map: Mapping[str, object] = None, qubit_map: Mapping[Qubit, NamedQubit] = None)

Tool to convert ParityOS circuits to Cirq circuits.

Instantiate the CirqExporter with a qubit map and a parameter map. Then use the to_cirq method to convert ParityOS circuits to Cirq circuits.

EXAMPLE:

qubit_map = {Qubit(i): cirq.NamedQubit(str(i)) for i in range(10)} parameter_map = {‘theta’: sympy.Symbol(‘theta’), ‘gamma’: sympy.Symbol(‘gamma’)} cirq_exporter = CirqExporter(qubit_map, parameter_map) cirq_circuit = cirq_exporter.to_cirq(parityos_circuit)

__init__(parameter_map: Mapping[str, object] = None, qubit_map: Mapping[Qubit, NamedQubit] = None)

Converts the circuit to a cirq circuit.

Parameters:
  • parameter_map – a mapping of the form {parameter_name: parameter_value}, where the parameter_name is a string that is used as a parameter_name in the ParityOS circuit, and parameter_value is a number like object (int, float, numpy float or a Sympy symbol are all valid). Optional. If not given, then an empty dictionary is used instead.

  • qubit_map – a mapping of the form {ParityOS_qubit: cirq_qubit}, where cirq_qubit is a Cirq NamedQubit instance. Optional. If not given, then ParityOS Qubits are automatically converted into cirq.NamedQubit instances with the same label.

gate_to_cirq(gate: Gate) GateOperation

Converts a gate to a Cirq gate operation.

Parameters:

gate – a ParityOS gate instance.

Returns:

a Cirq gate operation.

to_cirq(circuit: Gate | Circuit) Circuit

Converts the circuit to a Cirq circuit.

Parameters:

circuit – a ParityOS circuit of quantum gates.

Returns:

a Cirq circuit.

class parityos_addons.interfaces.QiskitExporter(parameter_map: Mapping[str, object] = None, qubit_map: Mapping[Qubit, int] = None, qubits: Iterable[Qubit] = None)

Tool to convert ParityOS circuits to Qiskit quantum circuits.

Instantiate the QiskitExporter with a qubit map and a parameter map. Then use the to_qiskit method to convert a ParityOS circuit to Qiskit quantum circuit.

EXAMPLE:

from qisc import Parameter parameter_map = {‘theta’: Parameter(‘$theta$’), ‘gamma’: Parameter(‘$gamma$’)} qiskit_exporter = QiskitExporter(parameter_map) qiskit_circuit = qiskit_exporter.to_qiskit(parityos_circuit)

__init__(parameter_map: Mapping[str, object] = None, qubit_map: Mapping[Qubit, int] = None, qubits: Iterable[Qubit] = None)

Converts the circuit to a Qiskit circuit.

Parameters:
  • parameter_map – a mapping of the form {parameter_name: parameter_value}, where the parameter_name is a string that is used as a parameter_name in the ParityOS circuit, and parameter_value is a number like object (int, float, numpy float or a Qiskit Parameter object are all valid). Optional. If not given, then an empty dictionary is used instead.

  • qubit_map – a mapping of the form {ParityOS_qubit: qubit_index}, where qubit_index is the integer index of the qubit in the Qiskit qubit register. Optional.

  • qubits – an iterable of ParityOS qubits. This is used to generate a qubit_map where each qubit is mapped onto its index in the sequence. Optional. Either a qubit_map or a qubits iterable must be given.

append_qiskit_gate(qiskit_circuit: <module 'qiskit.circuit' from '/usr/local/lib/python3.11/site-packages/qiskit/circuit/__init__.py'>, gate: ~parityos.base.gates.Gate)

Creates a qiskit gate corresponding to the ParityOS Gate instance and appends it to the qiskit circuit. :param qiskit_circuit: the qiskit circuit to which we want to append the gate :param gate: the ParityOS Gate that is appended to the circuit

to_qiskit(circuit: Gate | Circuit) QuantumCircuit

Converts the circuit to a Qiskit quantum circuit.

Parameters:

circuit – a ParityOS circuit of quantum gates.

Returns:

a Qiskit QuantumCircuit object.

parityos_addons.qaoa.generate_qaoa(parityos_output: ParityOSOutput, unitary_pattern: str) tuple[Circuit, dict[str, tuple[float, float]]]

Generates a QAOA quantum circuit and a dictionary with parameter bounds. The QAOA quantum circuit is composed of several unitary propagators, related to the problem Hamiltonian, driver terms and Parity constraints. The parameter bounds dictionary maps the parameter names used in the quantum circuit onto a (lower bound, upper bound) tuple of floats for each classical QAOA parameter in the QAOA circuit.

Parameters:
  • parityos_output (ParityOSOutput) –

    The compiler output as an object of ParityOSOutput, containing information about the compiled problem and the raw constraint circuit, as defined in the response schema. Assumptions:

    1. the device has only 2-body connections;

    2. the interaction coefficients are explicit numbers, not strings.

  • unitary_pattern (str) –

    the pattern of unitaries to use in each repetition. Should be a string with the following characters:

    • Z: the problem Hamiltonian

    • X: the driver Hamiltonian

    • C: the constraint Hamiltonian

    The string is expressed in time order, from left to right.

Example:

To create a ParityOS QAOA circuit of order p=3, create the circuit from a ParityOSOutput object with a unitary_pattern of order 3: qaoa_circuit, parameter_bounds = generate_qaoa(parityos_output, ‘XCZXCZXCZ’)

class parityos_addons.spin_hamiltonians.SpinZ(label: str | int | tuple[int, ...] | Qubit)

Represents a classical Ising spin value (+1 or -1) or the Z-eigenvalue of a Pauli Z operator.

parityos_addons.spin_hamiltonians.spinz_to_hamiltonian(expr: Add | Mul) ProblemRepresentation

Convert an expression containing sums of products of SpinZ objects into a ParityOS problem representation.

Parameters:

expr – an expression containing sums of products of SpinZ objects

Returns:

a ProblemRepresentation object

parityos_addons.spin_hamiltonians.untie_spinz_product(product: Mul) tuple[frozenset[Qubit], object]

Split a product of SpinZ and other factors into a pure product of SpinZ object and the product of all the remaining factors.

Parameters:

product – A product of SpinZ objects and other Sympy objects or numbers

Returns:

a tuple where the first item is the product of SpinZ objects and the second item is the product of all the other factors in the term

parityos_addons.benchmarking.benchmark_compiler_runs(client: CompilerClient, compiler_runs: Collection[CompilerRun], calculate_circuit_statistics: bool = True) DataFrame

Calculates statistics from the CompilerRun instances, by requesting the corresponding ParityOSOutputs.

Parameters:
  • client – CompilerClient which should send requests to get the corresponding ParityOSOutputs

  • compiler_runs – Collection of CompilerRun instances

  • calculate_circuit_statistics – indicates if circuit statistics should be added

Returns:

pd.DataFrame containing benchmark results

parityos_addons.benchmarking.benchmark_parityos_outputs(parityos_outputs: Collection[ParityOSOutput], calculate_circuit_statistics: bool = True) DataFrame

Calculates statistics from the ParityOSOutput instances

Parameters:
  • parityos_outputs – Collection of ParityOSOutput instances

  • calculate_circuit_statistics – indicates if circuit statistics should be added

Returns:

pd.DataFrame containing benchmark results

class parityos_addons.analog_computation.Observable(interactions: Sequence[PauliOp], coefficients: Sequence)

Representation of an Observable as a sum of PauliOps multiplied by corresponding coefficients.

__init__(interactions: Sequence[PauliOp], coefficients: Sequence)
Parameters:
  • interactions – the PauliOps that should be multiplied by the corresponding coefficients and summed up together in order to obtain the Observable.

  • coefficients – The coefficients in the Observable, in a sequence that aligns with the interactions sequence.

Example:

observable = Observable(
    [PauliOp([X(Qubit(1))]), PauliOp([Y(Qubit(1)), Y(Qubit(2))])],
    (0.5, -0.8),
)
evaluate(configuration: Mapping[Qubit, int]) float

Evaluates the expectation value of the Observable in specific Z eigenstates with eigenvalues +1 or -1 given by the configuration.

Parameters:

configuration – a mapping of the qubits onto their Z eigenvalue +1 or -1.

Returns:

the corresponding expectation value

classmethod from_json(data)

Constructs an Observable object from JSON data.

Parameters:

data – a JSON-like dictionary with 'interactions', 'coefficients' fields

Returns:

an Observable object

classmethod from_nx_graph(graph: networkx.Graph)
Parameters:

graph – A graph representing an optimization problem; nodes are interpreted as binary variables, and edges between them are interpreted as Z interaction terms between them (with strength given by the weight data on each edge).

Returns:

the Observable associated with the given graph

classmethod from_terms(terms: Iterator[tuple[PauliOp, float]] | Sequence[tuple[PauliOp, float]]) Observable

Creates an Observable from given terms. :param terms: sequence or iterator of (PauliOp, coefficient) tuples. :return: Observable.

property qubits: Set[Qubit]
Returns:

set of the Qubits which appear in the Observable.

tensor(other: Observable) Observable

Return the tensor product observable selfother. self and other must not share common qubit labels. Note: Alternatively, the syntax observable1 ^ observable2 can be used to compute the tensor product between two observables

Parameters:

other – Other observable to compute the tensor product with

Returns:

tensor product observable selfother. If observables share common qubits a ParityOsAnalogComputationException is raised.

property terms: Iterator[tuple[PauliOp, float]]

A property that returns an Iterator of all (interaction, coefficient) pairs.

Returns:

an Iterator for the (interaction, coefficient) pairs

to_json()

Converts the Observable object to json.

Returns:

the Observable object in json-serializable format

class parityos_addons.analog_computation.ParitySchedule(output: ParityOSOutput, interactions_coefficient: Expr = t, constraints_coefficient: Expr = t, driver_coefficient: Expr = 1.0 - t, time_parameter: Symbol = t, duration: float = 1.0)

A standard annealing Schedule for the Parity Architecture. In contrast to the Schedule class ParitySchedule knows the names of its terms: interactions_term, constraints_term, driver_term. The ParitySchedule corresponds to:

ParitySchedule = interactions_term + constraints_term + driver_term

where terms consists of an Observable and a time dependent coefficient.

__init__(output: ParityOSOutput, interactions_coefficient: Expr = t, constraints_coefficient: Expr = t, driver_coefficient: Expr = 1.0 - t, time_parameter: Symbol = t, duration: float = 1.0)

Creates ParitySchedule from ParityOSOutput and related coefficients. :param output: ParityOSOutput to transform into a Schedule :param interactions_coefficient: sympy.Expr for the interactions term :param constraints_coefficient: sympy.Expr for the constraints term :param driver_coefficient: sympy.Expr for the driver term :param time_parameter: sympy.Symbol for the time parameter :param duration: float :return: ParitySchedule

property constraints_coefficient: Expr

Coefficient of the constraints term

property constraints_schedule: Schedule

Schedule for the constraints

property driver_coefficient: Expr

Coefficient of the driver term

property driver_schedule: Schedule

Schedule for the driver

property duration: float

Duration of the schedule

property interactions_coefficient: Expr

Coefficient of the interactions term

property interactions_schedule: Schedule

Schedule for the interactions

property qubits: list[Qubit]

Obtain a sorted list of all qubits in this Schedule instance.

property schedule: Schedule

Returns the full corresponding Schedule

property time_parameter: Symbol

Time parameter as sympy.Symbol

class parityos_addons.analog_computation.PauliOp(pauli_gates: Collection[X | Y | Z] = frozenset({}))

Representation of multi-qubit Pauli operators that consist of a tensor product of Pauli gates (X, Y, Z).

__init__(pauli_gates: Collection[X | Y | Z] = frozenset({}))

The case when pauli_gates is None corresponds to the Identity operator. Each Pauli gate should be applied to a unique qubit.

commutes_with(other)
Returns true if self commutes with other, otherwise false. Here, we are applying the rule

“Two Pauli strings commute iff they do not commute on an even number of indices.”

Parameters:

other – another PauliOp

Returns:

True or False, indicating whether self and other commute.

evaluate(configuration: Mapping[Qubit, int]) int

Evaluates the expectation value of the PauliOp operator in specific Z eigenstates with eigenvalues +1 or -1 given by the configuration.

Parameters:

configuration – a mapping of the qubits onto their Z eigenvalue +1 or -1.

Returns:

the corresponding expectation value, which is either +1 or -1 or 0

classmethod from_json(data: list) PauliOp

Initializes the PauliOp class from json

Parameters:

data – PauliOp in json format

Returns:

A PauliOp instance

property qubits: Set[Qubit]

Set of Qubits which appear in the PauliOp.

to_json() str | int | float | bool | None | dict[str, str | int | float | bool | None | dict[str, JSONType] | list[JSONType]] | list[str | int | float | bool | None | dict[str, JSONType] | list[JSONType]]

Converts the PauliOp to json

Returns:

the PauliOp in json format

class parityos_addons.analog_computation.Schedule(terms: list[ScheduleTerm], time_parameter: Symbol, duration: float = 1.0)

Representation of a Schedule defined as a sum of ScheduleTerms.

Parameters:
  • terms – list of ScheduleTerms.

  • time_parameter – sympy.Symbol representing the time parameter.

  • duration – duration of the Schedule.

Example:

>>> observable_1 = Observable(
>>>     [PauliOp([X(Qubit(1))]), PauliOp([Y(Qubit(1)), Y(Qubit(2))])], [0.5, -0.8],
>>> )
>>> observable_2 = Observable([PauliOp([Z(Qubit(1))])], [1])

>>> time = sympy.Symbol("t")
>>> coefficient_1 = 3.1 * time
>>> coefficient_2 = time + 4

>>> term_1 = ScheduleTerm(observable_1, coefficient_1)
>>> term_2 = ScheduleTerm(observable_2, coefficient_2)
>>> schedule = Schedule([term_1, term_2], time)
__init__(terms: list[ScheduleTerm], time_parameter: Symbol, duration: float = 1.0) None
add_term(term: ScheduleTerm) Self

Creates a new Schedule by adding an (observable, coefficient) pair. :param term: an (observable, coefficient) pair. :return: new Schedule

property coefficients: list[Expr]
Returns:

list of coefficients.

classmethod compose(schedules: Iterable[Self]) Self

Compose a Schedule by combining all ScheduleTerm`s of a sequence of `Schedule`s. For that the `time_parameter and duration must be identical in all `Schedule`s.

classmethod from_json(data: dict) Self

Constructs a Schedule object from JSON data.

Parameters:

data – a JSON-like dictionary with 'terms', 'time_parameter', 'duration' fields.

Returns:

a Schedule object.

property observables: list[Observable]
Returns:

list of Observables.

property parameters: set
Returns:

set of the parameters that are in the list of coefficients

property qubits: list[Qubit]

Obtain a sorted list of all qubits in this Schedule instance.

subs_parameters(*args) Self

Substitutes parameters and returns a new Schedule. Passes the args to the Sympy’s subs methods. From Sympy docstrings:

:param args:args is either:
  • two arguments, e.g. foo.subs(old, new)

  • one iterable argument, e.g. foo.subs(iterable). The iterable may be
    o an iterable container with (old, new) pairs. In this case the

    replacements are processed in the order given with successive patterns possibly affecting replacements already made.

    o a dict or set whose key/value items correspond to old/new pairs.

    In this case the old/new pairs will be sorted by op count and in case of a tie, by number of args and the default_sort_key. The resulting sorted list is then processed as an iterable container (see previous).

Returns:

a new Schedule

to_json() dict

Converts the Schedule to json.

Returns:

the Schedule in json-serializable format

class parityos_addons.analog_computation.ScheduleTerm(observable: Observable, coefficient: Expr)

ScheduleTerm = coefficient * observable, where :param observable: Observable instance. :param coefficient: sympy.Expr representing a parameterized (or constant) coefficient.

__init__(observable: Observable, coefficient: Expr) None
classmethod from_json(data) ScheduleTerm

Constructs a ScheduleTerm object from JSON data.

Parameters:

data – a JSON-like dictionary with the corresponding fields.

Returns:

a ScheduleTerm object.

property parameters: set
Returns:

the parameters of the ScheduleTerm.

subs_parameters(args) ScheduleTerm

Substitutes parameters and returns a new Schedule.

Passes the args to the Sympy’s subs methods. From Sympy’s docstrings: :param args:args is either:

  • two arguments, e.g. foo.subs(old, new)

  • one iterable argument, e.g. foo.subs(iterable). The iterable may be
    o an iterable container with (old, new) pairs. In this case the

    replacements are processed in the order given with successive patterns possibly affecting replacements already made.

    o a dict or set whose key/value items correspond to old/new pairs.

    In this case the old/new pairs will be sorted by op count and in case of a tie, by number of args and the default_sort_key. The resulting sorted list is then processed as an iterable container (see previous).

Returns:

a new Schedule.

to_json() dict

Converts the ScheduleTerm to json.

Returns:

the ScheduleTerm in json-serializable format.

parityos_addons.analog_computation.observable_from_problem(problem_representation: ProblemRepresentation, constraint_strength: float = 1.0) Observable

Creates an Observable from ProblemRepresentation that contains both interactions and constraints.

Parameters:
  • problem_representation – a ProblemRepresentation instance.

  • constraint_strength – the absolute value to multiply to constraint.value(s) in order to obtain the coefficients for the observable defined by constraints. ProblemRepresentation is assumed to be a minimization problem.

Returns:

Observable.

parityos_addons.analog_computation.observable_from_problem_constraints(problem_representation: ProblemRepresentation, constraint_strength: float = 1.0) Observable

Creates an Observable only from the constraints of the ProblemRepresentation.

Parameters:
  • problem_representation – a ProblemRepresentation instance.

  • constraint_strength – the absolute value to multiply to constraint.value(s) in order to obtain the coefficients for the observable defined by constraints. ProblemRepresentation is assumed to be a minimization problem.

Returns:

Observable.

parityos_addons.analog_computation.observable_from_problem_interactions(problem_representation: ProblemRepresentation) Observable

Creates an Observable only from interactions of the ProblemRepresentation.

Parameters:

problem_representation – a ProblemRepresentation instance.

Returns:

Observable.

parityos_addons.analog_computation.standard_driver_observable_for_qubits(qubits: Sequence[Qubit] | set[Qubit]) Observable

Creates a standard driver (-sum(X)) observable for qubits. :param qubits: :return: a driver Observable