SaashaJoshi / piQture

piQture: A quantum machine learning library for image processing.
https://saashajoshi.github.io/piQture/
Apache License 2.0
20 stars 10 forks source link

Add quantum convolutional neural network (QCNN) #6

Closed SaashaJoshi closed 9 months ago

SaashaJoshi commented 10 months ago

The QCNN structure consists of 4 layers: data embedding, convolutional layer, pooling layer, and fully connected layer, followed by measurement and training.

- [ ] Data encoding integration (separate PR) - [ ] Training integration (separate PR)

SaashaJoshi commented 10 months ago

Currently, the pooling layer considers two adjacent qubits and applies a dynamic circuit. It measures one of the qubits and a controlled phase gate on the other. However, as given in the reference paper, this measurement can also be performed on two adjacent qubits. Two qubits are measured, and corresponding controlled phase gates are applied to the qubit.

https://github.com/SaashaJoshi/quantum-image-processing/blob/2d21202f013546b7894bbbc90f368ae9ab2f87d6/quantum_image_processing/models/neural_networks/convolutional/qcnn.py#L121-L123

This flexibility in the number of qubits to be measured is yet to be implemented. This feature (perhaps) corresponds to the size of strides in a classical pooling layer.

SaashaJoshi commented 9 months ago

The decision to make in-place changes to the circuit while applying different layers is made because dynamic circuits (if_test, or if_else), used in Pooling layers, cannot be composed with any other circuit in the current version of Qiskit. These instructions are applied with a context manager and cannot be applied when clbits outside the enclosing circuit are referred.

Refer: Raises CircuitError

SaashaJoshi commented 9 months ago

The EstimatorQNN doesn't allow measurements. Therefore, the current QuantumPoolingLayer cannot be applied with the estimator primitive. One alternative could be to change the way the pooling layer is built, i.e. without using the dynamic circuits and (perhaps) using some operator to replicate the results of a controlled-phase shift. Else, searching into the primitives could help find a way around this.

SaashaJoshi commented 9 months ago

Searching into primitives - primitives currently do not support dynamic circuits. In order to apply these mid-circuit measurements, a simple backend.run() should be used. However, this does not support a runtime behaviour (i.e. a cyclic run of the circuit on the hardware without facing the queue more than once). Refer: How do Qiskit Runtime primitives differ from backend.run?