|
- # Copyright 2021 Huawei Technologies Co., Ltd
- #
- # Licensed under the Apache License, Version 2.0 (the "License");
- # you may not use this file except in compliance with the License.
- # You may obtain a copy of the License at
- #
- # http://www.apache.org/licenses/LICENSE-2.0
- #
- # Unless required by applicable law or agreed to in writing, software
- # distributed under the License is distributed on an "AS IS" BASIS,
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- # See the License for the specific language governing permissions and
- # limitations under the License.
- # ============================================================================
- """Benchmakr for gradient calculation of tensorflow quantum."""
- import time
- import numpy as np
- import tensorflow as tf
- from _parse_args import parser
- args = parser.parse_args()
- tf.config.threading.set_intra_op_parallelism_threads(args.omp_num_threads)
- import tensorflow_quantum as tfq
- import cirq
- import sympy
- import tqdm
-
-
- def convert_to_circuit(image):
- """Encode truncated classical image into quantum datapoint."""
- values = np.ndarray.flatten(image)
- qubits = cirq.GridQubit.rect(4, 4)
- circuit = cirq.Circuit()
- for i, value in enumerate(values):
- if value:
- circuit.append(cirq.X(qubits[i]))
- return circuit
-
-
- class CircuitLayerBuilder():
- """CircuitLayerBuilder"""
- def __init__(self, data_qubits, readout):
- self.data_qubits = data_qubits
- self.readout = readout
-
- def add_layer(self, circuit, gate, prefix):
- for i, qubit in enumerate(self.data_qubits):
- symbol = sympy.Symbol(prefix + '-' + str(i))
- circuit.append(gate(qubit, self.readout)**symbol)
-
-
- def create_quantum_model():
- """Create a QNN model circuit and readout operation to go along with it."""
- data_qubits = cirq.GridQubit.rect(4, 4) # a 4x4 grid.
- readout = cirq.GridQubit(-1, -1) # a single qubit at [-1,-1]
- circuit = cirq.Circuit()
-
- # Prepare the readout qubit.
- circuit.append(cirq.X(readout))
- circuit.append(cirq.H(readout))
-
- builder = CircuitLayerBuilder(data_qubits=data_qubits, readout=readout)
-
- # Then add layers (experiment by adding more).
- builder.add_layer(circuit, cirq.XX, "xx1")
- builder.add_layer(circuit, cirq.ZZ, "zz1")
-
- # Finally, prepare the readout qubit.
- circuit.append(cirq.H(readout))
-
- return circuit, cirq.Z(readout)
-
-
- n_qubits = 17
- data = np.load('./mnist_resize.npz')
- x_train_bin, y_train_nocon, x_test_bin, y_test = data['arr_0'], data[
- 'arr_1'], data['arr_2'], data['arr_3']
- x_train_circ = [convert_to_circuit(x) for x in x_train_bin]
- x_test_circ = [convert_to_circuit(x) for x in x_test_bin]
-
- model_circuit, model_readout = create_quantum_model()
- names = sorted(list(model_circuit._parameter_names_()))
- init = np.random.random(len(names))[None, :].astype(np.float32)
- values_tensor = tf.convert_to_tensor(init)
- for c in x_train_circ:
- c.append(model_circuit)
-
- expectation_calculation = tfq.layers.Expectation(
- differentiator=tfq.differentiators.Adjoint())
-
- t0 = time.time()
- eval_time = []
- for circuit in tqdm.tqdm(x_train_circ[:args.num_sampling]):
- eval_time.append(time.time())
- with tf.GradientTape() as g:
- g.watch(values_tensor)
- exact_outputs = expectation_calculation(model_circuit,
- operators=model_readout,
- symbol_names=names,
- symbol_values=values_tensor)
- g.gradient(exact_outputs, values_tensor)
- eval_time[-1] = time.time() - eval_time[-1]
- eval_time = np.sort(eval_time[1:])
- t1 = time.time()
- print("Eval grad mean time:{}".format(eval_time[1:-1].mean()))
- print("Total time:{}".format(t1 - t0))
|