Format change using Black
This commit is contained in:
@@ -1,49 +1,66 @@
|
|||||||
|
|
||||||
import cupy as cp
|
import cupy as cp
|
||||||
import numpy as np
|
import numpy as np
|
||||||
|
|
||||||
EINSUM_SYMBOLS_BASE = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
EINSUM_SYMBOLS_BASE = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||||
|
|
||||||
class QiboCircuitToEinsum:
|
|
||||||
def __init__(self, circuit, dtype='complex128'):
|
|
||||||
|
|
||||||
self.backend = cp
|
|
||||||
self.dtype = getattr(self.backend, dtype)
|
|
||||||
|
|
||||||
self.input_tensor_counter = np. zeros((circuit.nqubits,))
|
class QiboCircuitToEinsum:
|
||||||
|
def __init__(self, circuit, dtype="complex128"):
|
||||||
|
self.backend = cp
|
||||||
|
self.dtype = getattr(self.backend, dtype)
|
||||||
|
|
||||||
|
self.input_tensor_counter = np.zeros((circuit.nqubits,))
|
||||||
self.gates = []
|
self.gates = []
|
||||||
for gate in circuit.queue:
|
for gate in circuit.queue:
|
||||||
targets = list(gate.target_qubits)
|
targets = list(gate.target_qubits)
|
||||||
for target in targets:
|
for target in targets:
|
||||||
self.input_tensor_counter[target] = self.input_tensor_counter[target] + 1
|
self.input_tensor_counter[target] = (
|
||||||
|
self.input_tensor_counter[target] + 1
|
||||||
|
)
|
||||||
controls = list(gate.control_qubits)
|
controls = list(gate.control_qubits)
|
||||||
for control in controls:
|
for control in controls:
|
||||||
self.input_tensor_counter[control] = self.input_tensor_counter[control] + 1
|
self.input_tensor_counter[control] = (
|
||||||
|
self.input_tensor_counter[control] + 1
|
||||||
|
)
|
||||||
gate_qubits = controls + targets
|
gate_qubits = controls + targets
|
||||||
self.gates.append((cp.asarray(gate.matrix).reshape((2,) * 2 * len(gate_qubits)), gate_qubits))
|
self.gates.append(
|
||||||
|
(
|
||||||
|
cp.asarray(gate.matrix).reshape((2,) * 2 * len(gate_qubits)),
|
||||||
|
gate_qubits,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
self.qubit_name = [indx for indx, value in enumerate(self.input_tensor_counter) if value > 0]
|
self.qubit_name = [
|
||||||
|
indx for indx, value in enumerate(self.input_tensor_counter) if value > 0
|
||||||
|
]
|
||||||
|
|
||||||
def state_vector(self):
|
def state_vector(self):
|
||||||
|
|
||||||
input_tensor_count = np.count_nonzero(self.input_tensor_counter)
|
input_tensor_count = np.count_nonzero(self.input_tensor_counter)
|
||||||
|
|
||||||
input_operands = self._get_bitstring_tensors('0'*input_tensor_count, self.dtype, backend=self.backend)
|
input_operands = self._get_bitstring_tensors(
|
||||||
|
"0" * input_tensor_count, self.dtype, backend=self.backend
|
||||||
mode_labels, qubits_frontier, next_frontier = self._init_mode_labels_from_qubits(self.qubit_name)
|
)
|
||||||
|
|
||||||
gate_mode_labels, gate_operands = self._parse_gates_to_mode_labels_operands(self.gates,
|
(
|
||||||
qubits_frontier,
|
mode_labels,
|
||||||
next_frontier)
|
qubits_frontier,
|
||||||
|
next_frontier,
|
||||||
|
) = self._init_mode_labels_from_qubits(self.qubit_name)
|
||||||
|
|
||||||
|
gate_mode_labels, gate_operands = self._parse_gates_to_mode_labels_operands(
|
||||||
|
self.gates, qubits_frontier, next_frontier
|
||||||
|
)
|
||||||
|
|
||||||
operands = input_operands + gate_operands
|
operands = input_operands + gate_operands
|
||||||
mode_labels += gate_mode_labels
|
mode_labels += gate_mode_labels
|
||||||
|
|
||||||
expression = self._convert_mode_labels_to_expression(mode_labels, qubits_frontier)
|
expression = self._convert_mode_labels_to_expression(
|
||||||
|
mode_labels, qubits_frontier
|
||||||
|
)
|
||||||
|
|
||||||
return expression, operands
|
return expression, operands
|
||||||
|
|
||||||
def _get_symbol(self,i):
|
def _get_symbol(self, i):
|
||||||
"""
|
"""
|
||||||
Return a Unicode as label for index.
|
Return a Unicode as label for index.
|
||||||
|
|
||||||
@@ -53,33 +70,26 @@ class QiboCircuitToEinsum:
|
|||||||
return EINSUM_SYMBOLS_BASE[i]
|
return EINSUM_SYMBOLS_BASE[i]
|
||||||
return chr(i + 140)
|
return chr(i + 140)
|
||||||
|
|
||||||
def _init_mode_labels_from_qubits(self,qubits):
|
def _init_mode_labels_from_qubits(self, qubits):
|
||||||
|
frontier_dict = {}
|
||||||
frontier_dict ={}
|
|
||||||
n = len(qubits)
|
n = len(qubits)
|
||||||
for x in range(n):
|
for x in range(n):
|
||||||
frontier_dict[qubits[x]]=x
|
frontier_dict[qubits[x]] = x
|
||||||
return [[i] for i in range(n)], frontier_dict, n
|
return [[i] for i in range(n)], frontier_dict, n
|
||||||
|
|
||||||
def _get_bitstring_tensors(self, bitstring, dtype=np.complex128, backend=cp):
|
def _get_bitstring_tensors(self, bitstring, dtype=np.complex128, backend=cp):
|
||||||
|
asarray = backend.asarray # _get_backend_asarray_func(backend)
|
||||||
asarray = backend.asarray #_get_backend_asarray_func(backend)
|
|
||||||
state_0 = asarray([1, 0], dtype=dtype)
|
state_0 = asarray([1, 0], dtype=dtype)
|
||||||
state_1 = asarray([0, 1], dtype=dtype)
|
state_1 = asarray([0, 1], dtype=dtype)
|
||||||
|
|
||||||
basis_map = {'0': state_0,
|
basis_map = {"0": state_0, "1": state_1}
|
||||||
'1': state_1}
|
|
||||||
|
|
||||||
operands = [basis_map[ibit] for ibit in bitstring]
|
operands = [basis_map[ibit] for ibit in bitstring]
|
||||||
return operands
|
return operands
|
||||||
|
|
||||||
def _parse_gates_to_mode_labels_operands(
|
def _parse_gates_to_mode_labels_operands(
|
||||||
self,
|
self, gates, qubits_frontier, next_frontier
|
||||||
gates,
|
|
||||||
qubits_frontier,
|
|
||||||
next_frontier
|
|
||||||
):
|
):
|
||||||
|
|
||||||
mode_labels = []
|
mode_labels = []
|
||||||
operands = []
|
operands = []
|
||||||
|
|
||||||
@@ -92,16 +102,19 @@ class QiboCircuitToEinsum:
|
|||||||
output_mode_labels.append(next_frontier)
|
output_mode_labels.append(next_frontier)
|
||||||
qubits_frontier[q] = next_frontier
|
qubits_frontier[q] = next_frontier
|
||||||
next_frontier += 1
|
next_frontier += 1
|
||||||
mode_labels.append(output_mode_labels+input_mode_labels)
|
mode_labels.append(output_mode_labels + input_mode_labels)
|
||||||
return mode_labels, operands
|
return mode_labels, operands
|
||||||
|
|
||||||
def _convert_mode_labels_to_expression(self,input_mode_labels, output_mode_labels):
|
def _convert_mode_labels_to_expression(self, input_mode_labels, output_mode_labels):
|
||||||
|
|
||||||
out_list = []
|
out_list = []
|
||||||
for key in output_mode_labels:
|
for key in output_mode_labels:
|
||||||
out_list.append(output_mode_labels[key])
|
out_list.append(output_mode_labels[key])
|
||||||
|
|
||||||
input_symbols = [''.join(map(self._get_symbol, idx)) for idx in input_mode_labels]
|
input_symbols = [
|
||||||
expression = ','.join(input_symbols) + '->' + ''.join(map(self._get_symbol, out_list))
|
"".join(map(self._get_symbol, idx)) for idx in input_mode_labels
|
||||||
|
]
|
||||||
|
expression = (
|
||||||
|
",".join(input_symbols) + "->" + "".join(map(self._get_symbol, out_list))
|
||||||
|
)
|
||||||
|
|
||||||
return expression
|
return expression
|
||||||
|
|||||||
@@ -5,39 +5,49 @@ import cupy as cp
|
|||||||
from qibo.models import *
|
from qibo.models import *
|
||||||
from timeit import default_timer as timer
|
from timeit import default_timer as timer
|
||||||
|
|
||||||
def parser():
|
|
||||||
|
|
||||||
|
def parser():
|
||||||
parser = argparse.ArgumentParser()
|
parser = argparse.ArgumentParser()
|
||||||
|
|
||||||
parser.add_argument("--nqubits", default=10, type=int, help="Number of quibits in the circuits.")
|
parser.add_argument(
|
||||||
|
"--nqubits", default=10, type=int, help="Number of quibits in the circuits."
|
||||||
|
)
|
||||||
|
|
||||||
parser.add_argument("--circuit", default="qft", type=str,
|
parser.add_argument(
|
||||||
help="Type of circuit to use. See README for the list of "
|
"--circuit",
|
||||||
"available circuits.")
|
default="qft",
|
||||||
|
type=str,
|
||||||
|
help="Type of circuit to use. See README for the list of "
|
||||||
|
"available circuits.",
|
||||||
|
)
|
||||||
|
|
||||||
parser.add_argument("--precision", default='complex128', type=str,
|
parser.add_argument(
|
||||||
help="Numerical precision of the simulation. "
|
"--precision",
|
||||||
"Choose between 'complex128' and 'complex64'.")
|
default="complex128",
|
||||||
|
type=str,
|
||||||
|
help="Numerical precision of the simulation. "
|
||||||
|
"Choose between 'complex128' and 'complex64'.",
|
||||||
|
)
|
||||||
|
|
||||||
return parser.parse_args()
|
return parser.parse_args()
|
||||||
|
|
||||||
def run_bench(task, label):
|
|
||||||
|
|
||||||
start = timer()
|
def run_bench(task, label):
|
||||||
|
start = timer()
|
||||||
result = task()
|
result = task()
|
||||||
end = timer()
|
end = timer()
|
||||||
circuit_eval_time = end - start
|
circuit_eval_time = end - start
|
||||||
print(f"Simulation time: {label} = {circuit_eval_time}s")
|
print(f"Simulation time: {label} = {circuit_eval_time}s")
|
||||||
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def main(args: argparse.Namespace):
|
|
||||||
|
|
||||||
|
def main(args: argparse.Namespace):
|
||||||
print("Testing for %d nqubits" % (args.nqubits))
|
print("Testing for %d nqubits" % (args.nqubits))
|
||||||
nqubits = args.nqubits
|
nqubits = args.nqubits
|
||||||
circuit_name = args.circuit
|
circuit_name = args.circuit
|
||||||
datatype = args.precision
|
datatype = args.precision
|
||||||
#Create qibo quibit
|
# Create qibo quibit
|
||||||
|
|
||||||
if circuit_name in ("qft", "QFT"):
|
if circuit_name in ("qft", "QFT"):
|
||||||
circuit = QFT(nqubits)
|
circuit = QFT(nqubits)
|
||||||
@@ -48,12 +58,13 @@ def main(args: argparse.Namespace):
|
|||||||
expression, operands = myconvertor.state_vector()
|
expression, operands = myconvertor.state_vector()
|
||||||
|
|
||||||
result_qibo = run_bench(circuit, "Qibo")
|
result_qibo = run_bench(circuit, "Qibo")
|
||||||
sv_cutn = run_bench(lambda:contract(expression, *operands), "cuQuantum cuTensorNet")
|
sv_cutn = run_bench(
|
||||||
|
lambda: contract(expression, *operands), "cuQuantum cuTensorNet"
|
||||||
|
)
|
||||||
|
|
||||||
#print(f"is sv in agreement?", cp.allclose(sv_cutn.flatten(), result_qibo.state(numpy=True)))
|
# print(f"is sv in agreement?", cp.allclose(sv_cutn.flatten(), result_qibo.state(numpy=True)))
|
||||||
assert cp.allclose(sv_cutn.flatten(), result_qibo.state(numpy=True))
|
assert cp.allclose(sv_cutn.flatten(), result_qibo.state(numpy=True))
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
main(parser())
|
main(parser())
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user