Giter Site home page Giter Site logo

simonegasperini / qiskit-symb Goto Github PK

View Code? Open in Web Editor NEW
22.0 1.0 2.0 326 KB

Python package for symbolic quantum computation in Qiskit

Home Page: https://pypi.org/project/qiskit-symb/

License: Apache License 2.0

Python 100.00%
qiskit quantum-computing symbolic-computation sympy

qiskit-symb's Introduction


Qiskit DemoDays presentation $\rightarrow$ ๐Ÿ”—link, password: Demoday20230615 (15th June 2023)

Jupyter notebook demo $\rightarrow$ ๐Ÿ”—link (15th June 2023)

Qiskit Medium blog $\rightarrow$ ๐Ÿ”—link (28th June 2023)


Table of contents

Introduction

The qiskit-symb package is meant to be a Python tool to enable the symbolic evaluation of parametric quantum states and operators defined in Qiskit by parameterized quantum circuits.

A Parameterized Quantum Circuit (PQC) is a quantum circuit where we have at least one free parameter (e.g. a rotation angle $\theta$). PQCs are particularly relevant in Quantum Machine Learning (QML) models, where the values of these parameters can be learned during training to reach the desired output.

In particular, qiskit-symb can be used to create a symbolic representation of a parametric quantum statevector, density matrix, or unitary operator directly from the Qiskit quantum circuit. This has been achieved through the re-implementation of some basic classes defined in the qiskit/quantum_info/ module by using sympy as a backend for symbolic expressions manipulation.

Installation

User-mode

pip install qiskit-symb

โš ๏ธ The package requires qiskit>=1. See the official Migration guides if you are used to a prevoius Qiskit version.

Dev-mode

git clone https://github.com/SimoneGasperini/qiskit-symb.git
cd qiskit-symb
pip install -e .

Usage examples

Sympify a Qiskit circuit

Let's get started on how to use qiskit-symb to get the symbolic representation of a given Qiskit circuit. In particular, in this first basic example, we consider the following quantum circuit:

from qiskit import QuantumCircuit
from qiskit.circuit import Parameter, ParameterVector

y = Parameter('y')
p = ParameterVector('p', length=2)

pqc = QuantumCircuit(2)
pqc.ry(y, 0)
pqc.cx(0, 1)
pqc.u(0, *p, 1)

pqc.draw('mpl')

To get the sympy representation of the unitary matrix corresponding to the parameterized circuit, we just have to create the symbolic Operator instance and call the to_sympy() method:

from qiskit_symb.quantum_info import Operator

op = Operator(pqc)
op.to_sympy()
$$\left[\begin{matrix}\cos{\left(\frac{y}{2} \right)} & - \sin{\left(\frac{y}{2} \right)} & 0 & 0\\0 & 0 & \sin{\left(\frac{y}{2} \right)} & \cos{\left(\frac{y}{2} \right)}\\0 & 0 & e^{i \left(p[0] + p[1]\right)} \cos{\left(\frac{y}{2} \right)} & - e^{i \left(p[0] + p[1]\right)} \sin{\left(\frac{y}{2} \right)}\\e^{i \left(p[0] + p[1]\right)} \sin{\left(\frac{y}{2} \right)} & e^{i \left(p[0] + p[1]\right)} \cos{\left(\frac{y}{2} \right)} & 0 & 0\end{matrix}\right]$$

If you want then to assign a value to some specific parameter, you can use the subs(<dict>) method passing a dictionary that maps each parameter to the desired corresponding value:

new_op = op.subs({p: [-1, 2]})
new_op.to_sympy()
$$\left[\begin{matrix}\cos{\left(\frac{y}{2} \right)} & - \sin{\left(\frac{y}{2} \right)} & 0 & 0\\0 & 0 & \sin{\left(\frac{y}{2} \right)} & \cos{\left(\frac{y}{2} \right)}\\0 & 0 & e^{i} \cos{\left(\frac{y}{2} \right)} & - e^{i} \sin{\left(\frac{y}{2} \right)}\\e^{i} \sin{\left(\frac{y}{2} \right)} & e^{i} \cos{\left(\frac{y}{2} \right)} & 0 & 0\end{matrix}\right]$$

Lambdify a Qiskit circuit

Given a Qiskit circuit, qiskit-symb also allows to generate a Python lambda function with actual arguments matching the Qiskit unbound parameters. Let's consider the following example starting from a ZZFeatureMap circuit, commonly used as a data embedding ansatz in QML applications:

from qiskit.circuit.library import ZZFeatureMap

pqc = ZZFeatureMap(feature_dimension=3, reps=1)
pqc.draw('mpl')

To get the Python function representing the final parameteric statevector, we just have to create the symbolic Statevector instance and call the to_lambda() method:

from qiskit_symb.quantum_info import Statevector

pqc = pqc.decompose()
statevec = Statevector(pqc).to_lambda()

We can now call the lambda-generated function statevec passing the x values we want to assign to each parameter. The returned object will be a numpy 2D-array (with shape=(8,1) in this case) representing the final output statevector psi.

x = [1.24, 2.27, 0.29]
psi = statevec(*x)

This feature can be useful when, given a Qiskit PQC, we want to run it multiple times with different parameters values. Indeed, we can perform a single symbolic evalutation and then call the lambda generated function as many times as needed, passing different values of the parameters at each iteration.

Contributors


Simone Gasperini

qiskit-symb's People

Contributors

sbrandhsn avatar simonegasperini avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar

qiskit-symb's Issues

Symbolic evaluation of `CUGate` raises an unexpected `TypeError`

There is an issue when one tries to use the package and the circuit contains controlled unitaries. For instance the circuit

from qiskit.circuit import QuantumRegister, ClassicalRegister, QuantumCircuit, Parameter
import numpy as np

st0 = Parameter("st0")
st1 = Parameter("st1")

def u1red_cr_overrot(alpha, theta):
    qreg_q = QuantumRegister(2, "q")
    creg_c = ClassicalRegister(2, "c")
    circuit = QuantumCircuit(qreg_q, creg_c)
    circuit.u(1.570796326794897, -2.9755113931440857, 4.71238898038469 + st1, qreg_q[1])
    circuit.u(1.8942714348583476, -4.71238898038469, 0.0 + st0, qreg_q[0])
    circuit.cu(np.pi / 2, np.pi / 2, -np.pi / 2, 0, qreg_q[1], qreg_q[0])
    return qreg_q, creg_c, circuit

raises no problem when one draws it:

phin = 0.0
theta = np.pi / 8.0

qreg_q, creg_c, circuit = u1red_cr_overrot(phin, theta)
circuit.draw("mpl")

But if one tries to get its Statevector form

from qiskit_symb.quantum_info import Statevector

statevec = Statevector(circuit)

it raises the following error message:

TypeError: CUGate.__init__() got multiple values for argument 'ctrl_qubits'

Note that this also happens if one wants to obtain its Operator form:

from qiskit_symb.quantum_info import Operator

op = Operator(circuit)

FidelityStatevectorKernel

Hello,

I am testing qiskit-symb with FidelityStatevectorKernel, but encounter the following error: 'Statevector' object has no attribute 'data'

from qiskit_symb.quantum_info import Statevector
quantum_kernel = FidelityStatevectorKernel(feature_map=..., statevector_type=Statevector)

Add support for general unparameterized unitary gates

Unitary gates help represent arbitrary unparameterized blocks acting on some number of qubits. They are particularly useful during circuit transpilation passes. It is straightforward to support them in qiskit-symb, and I've verified it works as expected. Here is the relevant gate class:

r"""Symbolic unitary gate module"""

from sympy.matrices import Matrix
from ...gate import Gate


class UnitaryGate(Gate):
    r"""Symbolic unitary gate class"""

    def __init__(self, mat, qubits):
        """todo"""
        super().__init__(
            name='unitary',
            num_qubits=len(qubits),
            params=[],
            qubits=qubits
        )
        self.mat = mat

    def __sympy__(self):
        """todo"""
        return Matrix(self.mat)

P.S. Awesome work with everything Simone! Your package has been very helpful and easy to use!

Missing docstrings to build online documentation

Most of the classes, methods, and functions defined in the /src and /tests directories need a proper docstring written in same style/format used in the official qiskit repository.

Then, it will be possible to set up a continuous documentation workflow based on Sphinx to build the online documentation.

Symbolic evaluation algorithm can be optimized for parallel gates

Consider the two circuits in the picture below: in both cases, we have a $CNOT$ gate and an $H$ gate acting in parallel. However, while in the first circuit (left) they are represented in a single "layer", in the second circuit (right) the drawing function moves the $H$ gate in a second "layer".

circs

Since the qiskit-symb algorithm is based on circuit.draw(output='text').nodes to get the circuit layout before performing the needed linear algebra (see method QuantumBase._get_circ_data), the way the second circuit is unfolded is not optimal because gates acting in parallel are split in two different "layers". In particular:

$$ \mathrm{circ_1} = H \otimes (I \otimes |0\rangle \langle0| + X \otimes |1\rangle \langle1|) $$

$$ \mathrm{circ_2} = (I \otimes H \otimes I) \cdot (I \otimes I \otimes |0\rangle \langle0| + X \otimes I \otimes |1\rangle \langle1|) $$

The goal is to implement the optimal algorithm to unfold any given circuit to always have its minimal number of "layers". For example, in this case, the second circuit should be represented in the following equivalent form:

$$ \mathrm{circ_2} = I \otimes H \otimes |0\rangle \langle0| + X \otimes H \otimes |1\rangle \langle1| $$

`XXMinusYYGate`, `XXPlusYYGate` and `DCXGate` are not supported

The following Qiskit gates are not supported and have to be implemented from scratch:

As shown in the code below, trying to use qiskit-symb on a circuit containing one of these gates raises a NotImplementedError. At the moment, the best workaround is to decompose the circuit just before its symbolic evaluation.

from qiskit.circuit import QuantumCircuit, Parameter
from qiskit.circuit.library import XXMinusYYGate
from qiskit_symb import Operator

qc = QuantumCircuit(2)
theta = Parameter('theta')
gate = XXMinusYYGate(theta)
qc.append(gate, [0, 1])

#qc = qc.decompose()
op = Operator(qc)

To successfully implement a gate acting on $N$ qubits in qiskit-symb, the first step is to find its mathematical representation as a linear combination of tensor products between $N$ complex 2 $\times$ 2 matrices (see here for further details and suggestions).

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.