Skip to content

Commit

Permalink
Merge branch 'master' into tfmem
Browse files Browse the repository at this point in the history
  • Loading branch information
stavros11 committed Mar 31, 2021
2 parents 71dc2f6 + 6642e00 commit 4041aa5
Show file tree
Hide file tree
Showing 12 changed files with 160 additions and 153 deletions.
4 changes: 2 additions & 2 deletions examples/qPDF/qPDF.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@
"source": [
"# import requirements\n",
"import numpy as np\n",
"from qibo.hep import qPDF\n",
"from qibo.models.hep import qPDF\n",
"\n",
"# our setup\n",
"ansatz = 'Weighted'\n",
Expand Down Expand Up @@ -348,4 +348,4 @@
},
"nbformat": 4,
"nbformat_minor": 4
}
}
4 changes: 2 additions & 2 deletions examples/variational_classifier/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ Code at: [https://github.com/Quantum-TII/qibo/tree/master/examples/variational_c

## Problem overview

We want to perform a supervised classification task with a [variational quantum classifer](https://arxiv.org/abs/2001.03622). The classifier is trained to minimize a local loss function given by the quadratic deviation of the classifier's predictions from the actual labels of the examples in the training set. A variational quantum circuit is employed to perform the classification.
We want to perform a supervised classification task with a [variational quantum classifer](https://arxiv.org/abs/1802.06002). The classifier is trained to minimize a local loss function given by the quadratic deviation of the classifier's predictions from the actual labels of the examples in the training set. A variational quantum circuit is employed to perform the classification.

## Implementing the solution

Expand Down Expand Up @@ -42,4 +42,4 @@ Note that nclases must be 3 and cannot be changed in this example, because we ar

## Results

The classification accuracy for the training and test sets is found to be around 70% and 67%, respectively.
The classification accuracy for the training and test sets is found to be around 70% and 73%, respectively.
2 changes: 1 addition & 1 deletion examples/variational_classifier/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ def main(nclasses, nqubits, nlayers, nshots, training, RxRzRx, method):
np.save('data/optimal_angles_rxrzrx_{}q_{}l.npy'.format(nqubits,nlayers), optimal_angles)

# We define our test set (both kets and labels)
data_test = np.concatenate((data[35:49], data[85:99], data[135:149]))
data_test = np.concatenate((data[35:50], data[85:100], data[135:150]))
labels_test = [[1,1]]*15 + [[1,-1]]*15 + [[-1,1]]*15

# We run an accuracy check for the training and the test sets
Expand Down
2 changes: 1 addition & 1 deletion src/qibo/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,5 @@
from qibo.backends import get_backend, get_precision, get_device
from qibo.backends import numpy_matrices as matrices
from qibo.backends import K
from qibo import callbacks, evolution, gates, hamiltonians, models
from qibo import callbacks, gates, hamiltonians, models
from qibo import parallel, optimizers, solvers
1 change: 0 additions & 1 deletion src/qibo/hep/__init__.py

This file was deleted.

4 changes: 4 additions & 0 deletions src/qibo/models/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
from qibo.models.circuit import Circuit, QFT
from qibo.models.evolution import StateEvolution, AdiabaticEvolution
from qibo.models.variational import VQE, QAOA
from qibo.models import hep
138 changes: 138 additions & 0 deletions src/qibo/models/circuit.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
import math
from qibo.config import raise_error
from qibo.core.circuit import Circuit as StateCircuit
from typing import Dict, Optional


class Circuit(StateCircuit):
""""""

@classmethod
def _constructor(cls, *args, **kwargs):
if kwargs["density_matrix"]:
if kwargs["accelerators"] is not None:
raise_error(NotImplementedError,
"Distributed circuits are not implemented for "
"density matrices.")
from qibo.core.circuit import DensityMatrixCircuit as circuit_cls
kwargs = {}
elif kwargs["accelerators"] is None:
circuit_cls = StateCircuit
kwargs = {}
else:
try:
from qibo.tensorflow.distcircuit import DistributedCircuit
except ModuleNotFoundError: # pragma: no cover
# CI installs all required libraries by default
raise_error(ModuleNotFoundError,
"Cannot create distributed circuit because some "
"required libraries are missing.")
circuit_cls = DistributedCircuit
kwargs.pop("density_matrix")
return circuit_cls, args, kwargs

def __new__(cls, nqubits: int,
accelerators: Optional[Dict[str, int]] = None,
memory_device: str = "/CPU:0",
density_matrix: bool = False):
circuit_cls, args, kwargs = cls._constructor(
nqubits, accelerators=accelerators,
memory_device=memory_device,
density_matrix=density_matrix
)
return circuit_cls(*args, **kwargs)

@classmethod
def from_qasm(cls, qasm_code: str,
accelerators: Optional[Dict[str, int]] = None,
memory_device: str = "/CPU:0",
density_matrix: bool = False):
circuit_cls, args, kwargs = cls._constructor(
qasm_code, accelerators=accelerators,
memory_device=memory_device,
density_matrix=density_matrix
)
return circuit_cls.from_qasm(*args, **kwargs)


def QFT(nqubits: int, with_swaps: bool = True,
accelerators: Optional[Dict[str, int]] = None,
memory_device: str = "/CPU:0") -> Circuit:
"""Creates a circuit that implements the Quantum Fourier Transform.
Args:
nqubits (int): Number of qubits in the circuit.
with_swaps (bool): Use SWAP gates at the end of the circuit so that the
qubit order in the final state is the same as the initial state.
accelerators (dict): Accelerator device dictionary in order to use a
distributed circuit
If ``None`` a simple (non-distributed) circuit will be used.
memory_device (str): Device to use for memory in case a distributed circuit
is used. Ignored for non-distributed circuits.
Returns:
A qibo.models.Circuit that implements the Quantum Fourier Transform.
Example:
::
import numpy as np
from qibo.models import QFT
nqubits = 6
c = QFT(nqubits)
# Random normalized initial state vector
init_state = np.random.random(2 ** nqubits) + 1j * np.random.random(2 ** nqubits)
init_state = init_state / np.sqrt((np.abs(init_state)**2).sum())
# Execute the circuit
final_state = c(init_state)
"""
if accelerators is not None:
if not with_swaps:
raise_error(NotImplementedError, "Distributed QFT is only implemented "
"with SWAPs.")
return _DistributedQFT(nqubits, accelerators, memory_device)

from qibo import gates

circuit = Circuit(nqubits)
for i1 in range(nqubits):
circuit.add(gates.H(i1))
for i2 in range(i1 + 1, nqubits):
theta = math.pi / 2 ** (i2 - i1)
circuit.add(gates.CU1(i2, i1, theta))

if with_swaps:
for i in range(nqubits // 2):
circuit.add(gates.SWAP(i, nqubits - i - 1))

return circuit


def _DistributedQFT(nqubits: int,
accelerators: Optional[Dict[str, int]] = None,
memory_device: str = "/CPU:0"):
"""QFT with the order of gates optimized for reduced multi-device communication."""
from qibo import gates

circuit = Circuit(nqubits, accelerators, memory_device)
icrit = nqubits // 2 + nqubits % 2
if accelerators is not None:
circuit.global_qubits = range(circuit.nlocal, nqubits) # pylint: disable=E1101
if icrit < circuit.nglobal: # pylint: disable=E1101
raise_error(NotImplementedError, "Cannot implement QFT for {} qubits "
"using {} global qubits."
"".format(nqubits, circuit.nglobal)) # pylint: disable=E1101

for i1 in range(nqubits):
if i1 < icrit:
i1eff = i1
else:
i1eff = nqubits - i1 - 1
circuit.add(gates.SWAP(i1, i1eff))

circuit.add(gates.H(i1eff))
for i2 in range(i1 + 1, nqubits):
theta = math.pi / 2 ** (i2 - i1)
circuit.add(gates.CU1(i2, i1eff, theta))

return circuit
File renamed without changes.
7 changes: 4 additions & 3 deletions src/qibo/hep/qpdf.py → src/qibo/models/hep.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from qibo import models, gates, K
from qibo import gates, K
from qibo.hamiltonians import Hamiltonian, matrices
from qibo.models.circuit import Circuit
from qibo.config import raise_error


Expand Down Expand Up @@ -128,7 +129,7 @@ def ansatz_Fourier(layers, qubits=1):
Returns:
The circuit, the rotation function and the total number of parameters.
"""
circuit = models.Circuit(qubits)
circuit = Circuit(qubits)
for l in range(layers - 1):
for q in range(qubits):
for _ in range(2):
Expand Down Expand Up @@ -205,7 +206,7 @@ def ansatz_Weighted(layers, qubits=1):
The circuit, the rotation function and the total number of
parameters.
"""
circuit = models.Circuit(qubits)
circuit = Circuit(qubits)
for _ in range(layers - 1):
for q in range(qubits):
circuit.add(gates.RY(q, theta=0))
Expand Down
143 changes: 3 additions & 140 deletions src/qibo/models.py → src/qibo/models/variational.py
Original file line number Diff line number Diff line change
@@ -1,144 +1,7 @@
import math
from qibo import get_backend
from qibo.config import raise_error
from qibo.core.circuit import Circuit as StateCircuit
from qibo.core.circuit import DensityMatrixCircuit
from qibo.evolution import StateEvolution, AdiabaticEvolution
from typing import Dict, Optional


class Circuit(StateCircuit):
""""""

@classmethod
def _constructor(cls, *args, **kwargs):
if kwargs["density_matrix"]:
if kwargs["accelerators"] is not None:
raise_error(NotImplementedError,
"Distributed circuits are not implemented for "
"density matrices.")
circuit_cls = DensityMatrixCircuit
kwargs = {}
elif kwargs["accelerators"] is None:
circuit_cls = StateCircuit
kwargs = {}
else:
try:
from qibo.tensorflow.distcircuit import DistributedCircuit
except ModuleNotFoundError: # pragma: no cover
# CI installs all required libraries by default
raise_error(ModuleNotFoundError,
"Cannot create distributed circuit because some "
"required libraries are missing.")
circuit_cls = DistributedCircuit
kwargs.pop("density_matrix")
return circuit_cls, args, kwargs

def __new__(cls, nqubits: int,
accelerators: Optional[Dict[str, int]] = None,
memory_device: str = "/CPU:0",
density_matrix: bool = False):
circuit_cls, args, kwargs = cls._constructor(
nqubits, accelerators=accelerators,
memory_device=memory_device,
density_matrix=density_matrix
)
return circuit_cls(*args, **kwargs)

@classmethod
def from_qasm(cls, qasm_code: str,
accelerators: Optional[Dict[str, int]] = None,
memory_device: str = "/CPU:0",
density_matrix: bool = False):
circuit_cls, args, kwargs = cls._constructor(
qasm_code, accelerators=accelerators,
memory_device=memory_device,
density_matrix=density_matrix
)
return circuit_cls.from_qasm(*args, **kwargs)


def QFT(nqubits: int, with_swaps: bool = True,
accelerators: Optional[Dict[str, int]] = None,
memory_device: str = "/CPU:0") -> Circuit:
"""Creates a circuit that implements the Quantum Fourier Transform.
Args:
nqubits (int): Number of qubits in the circuit.
with_swaps (bool): Use SWAP gates at the end of the circuit so that the
qubit order in the final state is the same as the initial state.
accelerators (dict): Accelerator device dictionary in order to use a
distributed circuit
If ``None`` a simple (non-distributed) circuit will be used.
memory_device (str): Device to use for memory in case a distributed circuit
is used. Ignored for non-distributed circuits.
Returns:
A qibo.models.Circuit that implements the Quantum Fourier Transform.
Example:
::
import numpy as np
from qibo.models import QFT
nqubits = 6
c = QFT(nqubits)
# Random normalized initial state vector
init_state = np.random.random(2 ** nqubits) + 1j * np.random.random(2 ** nqubits)
init_state = init_state / np.sqrt((np.abs(init_state)**2).sum())
# Execute the circuit
final_state = c(init_state)
"""
if accelerators is not None:
if not with_swaps:
raise_error(NotImplementedError, "Distributed QFT is only implemented "
"with SWAPs.")
return _DistributedQFT(nqubits, accelerators, memory_device)

from qibo import gates

circuit = Circuit(nqubits)
for i1 in range(nqubits):
circuit.add(gates.H(i1))
for i2 in range(i1 + 1, nqubits):
theta = math.pi / 2 ** (i2 - i1)
circuit.add(gates.CU1(i2, i1, theta))

if with_swaps:
for i in range(nqubits // 2):
circuit.add(gates.SWAP(i, nqubits - i - 1))

return circuit


def _DistributedQFT(nqubits: int,
accelerators: Optional[Dict[str, int]] = None,
memory_device: str = "/CPU:0"):
"""QFT with the order of gates optimized for reduced multi-device communication."""
from qibo import gates

circuit = Circuit(nqubits, accelerators, memory_device)
icrit = nqubits // 2 + nqubits % 2
if accelerators is not None:
circuit.global_qubits = range(circuit.nlocal, nqubits) # pylint: disable=E1101
if icrit < circuit.nglobal: # pylint: disable=E1101
raise_error(NotImplementedError, "Cannot implement QFT for {} qubits "
"using {} global qubits."
"".format(nqubits, circuit.nglobal)) # pylint: disable=E1101

for i1 in range(nqubits):
if i1 < icrit:
i1eff = i1
else:
i1eff = nqubits - i1 - 1
circuit.add(gates.SWAP(i1, i1eff))

circuit.add(gates.H(i1eff))
for i2 in range(i1 + 1, nqubits):
theta = math.pi / 2 ** (i2 - i1)
circuit.add(gates.CU1(i2, i1eff, theta))

return circuit
from qibo.core.circuit import Circuit
from qibo.models.evolution import StateEvolution


class VQE(object):
Expand Down Expand Up @@ -373,7 +236,7 @@ def get_initial_state(self, state=None):

if state is None:
return self.state_cls.plus_state(self.nqubits).tensor
return StateCircuit.get_initial_state(self, state)
return Circuit.get_initial_state(self, state)

def minimize(self, initial_p, initial_state=None, method='Powell',
jac=None, hess=None, hessp=None, bounds=None, constraints=(),
Expand Down
2 changes: 1 addition & 1 deletion src/qibo/tests/test_hep.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"""
import numpy as np
import pytest
from qibo.hep import qPDF
from qibo.models.hep import qPDF


test_names = "ansatz,layers,nqubits,multi_output,output"
Expand Down
Loading

0 comments on commit 4041aa5

Please sign in to comment.