Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions benchmarks/scripts/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,19 @@ licenses(["notice"])
# Export for the PIP package.
exports_files(["__init__.py"])

py_library(
name = "benchmark_flags",
srcs = ["flags.py"],
)

py_test(
name = "benchmark_clifford_circuit",
srcs = ["benchmark_clifford_circuit.py"],
python_version = "PY3",
deps = [
":benchmark_flags",
":benchmark_util",
"//benchmarks/scripts/models:random_clifford_circuit",
"//tensorflow_quantum/core/ops:tfq_simulate_ops_py",
"//tensorflow_quantum/core/serialize:serializer",
"@local_config_tf//:test_log_pb2",
Expand All @@ -35,6 +43,8 @@ py_test(
srcs = ["benchmark_random_circuit.py"],
python_version = "PY3",
deps = [
":benchmark_flags",
":benchmark_util",
"//tensorflow_quantum/core/ops:tfq_simulate_ops_py",
"//tensorflow_quantum/core/serialize:serializer",
"@local_config_tf//:test_log_pb2",
Expand All @@ -46,6 +56,8 @@ py_test(
srcs = ["benchmark_op_gradients.py"],
python_version = "PY3",
deps = [
":benchmark_flags",
":benchmark_util",
"//tensorflow_quantum/core/ops:batch_util",
"//tensorflow_quantum/core/ops:cirq_ops",
"//tensorflow_quantum/core/ops:tfq_simulate_ops_py",
Expand Down
8 changes: 4 additions & 4 deletions benchmarks/scripts/benchmark_op_gradients.py
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ def setup(self):
for resolver in resolver_batch],
dtype=np.float32)

self.symbol_names = symbol_names
self.symbol_names_tensor = tf.convert_to_tensor(symbol_names)
self.symbol_values_tensor = tf.convert_to_tensor(symbol_values_array)
self.programs = util.convert_to_tensor(circuit_batch)
self.psums = util.convert_to_tensor([psums])
Expand All @@ -140,15 +140,15 @@ def _benchmark_tfq_differentiator(self, differentiator, params):
analytic_op=tfq_simulate_ops.tfq_simulate_expectation)

for _ in range(params.n_burn):
op(self.programs, self.symbol_names, self.symbol_values_tensor,
self.psums)
op(self.programs, self.symbol_names_tensor,
self.symbol_values_tensor, self.psums)

deltas = [None] * params.n_runs
for i in range(params.n_runs):
start = time.perf_counter()
with tf.GradientTape() as g:
g.watch(self.symbol_values_tensor)
expectations = op(self.programs, self.symbol_names,
expectations = op(self.programs, self.symbol_names_tensor,
self.symbol_values_tensor, self.psums)
g.gradient(expectations, self.symbol_values_tensor)
deltas[i] = time.perf_counter() - start
Expand Down
90 changes: 87 additions & 3 deletions benchmarks/scripts/benchmark_random_circuit.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,14 @@
# ==============================================================================
"""Benchmark simulators against classically intractable 'supremacy' circuits."""
import os
import random
import time
from typing import Iterable, Sequence, TypeVar, cast

import numpy as np
from absl.testing import parameterized
import cirq
import tensorflow as tf
import numpy as np

from tensorflow_quantum.core.ops import tfq_simulate_ops
from tensorflow_quantum.core.serialize.serializer import serialize_circuit
Expand All @@ -32,14 +34,96 @@
TEST_PARAMS_1 = flags.test_flags(n_rows=3, n_cols=5, n_moments=5)
TEST_PARAMS_2 = flags.test_flags(n_rows=4, n_cols=4, n_moments=20)

T = TypeVar('T')


def _choice(rand_gen: float, sequence: Sequence[T]) -> T:
"""Choose a pseudo-random element from a non-empty sequence."""
return sequence[int(rand_gen * len(sequence))]


def _make_cz_layer(qubits: Iterable[cirq.GridQubit], layer_index: int):
"""Yield a CZ interaction pattern for the given layer index."""
offset = layer_index % 8
for q in qubits:
for q2 in [
cirq.GridQubit(q.row + 1, q.col),
cirq.GridQubit(q.row, q.col + 1)
]:
if q2 in qubits and ((q.row + q.col + offset) % 2 == 0):
yield cirq.CZ(q, q2)


def _add_cz_layer(layer_index: int, circuit: cirq.Circuit) -> int:
"""Add the next non-empty CZ layer and return the updated layer index."""
cz_layer = None
while not cz_layer:
qubits = cast(Iterable[cirq.GridQubit], circuit.all_qubits())
cz_layer = list(_make_cz_layer(qubits, layer_index))
layer_index += 1

circuit.append(cz_layer, strategy=cirq.InsertStrategy.NEW_THEN_INLINE)
return layer_index


def generate_boixo_2018_beyond_classical_v2_grid(n_rows: int, n_cols: int,
cz_depth: int,
seed: int) -> cirq.Circuit:
"""Local copy of ReCirq's v2 beyond-classical grid circuit generator.

Source reference:
https://github.com/quantumlib/ReCirq/blob/main/recirq/beyond_classical/google_v2_beyond_classical.py

Note:
We intentionally keep this local copy to avoid introducing broader
dependency migration. A future cleanup can switch to direct
ReCirq dependency once repository constraints are aligned.
"""
qubits = [
cirq.GridQubit(i, j) for i in range(n_rows) for j in range(n_cols)
]
non_diagonal_gates = [cirq.X**(1 / 2), cirq.Y**(1 / 2)]
rand_gen = random.Random(seed).random

circuit = cirq.Circuit()
circuit.append(cirq.H(qubit) for qubit in qubits)

layer_index = 0
if cz_depth:
layer_index = _add_cz_layer(layer_index, circuit)
for qubit in qubits:
if not circuit.operation_at(qubit, 1):
circuit.append(cirq.T(qubit),
strategy=cirq.InsertStrategy.EARLIEST)

for moment_index in range(2, cz_depth + 1):
layer_index = _add_cz_layer(layer_index, circuit)
for qubit in qubits:
if not circuit.operation_at(qubit, moment_index):
last_op = circuit.operation_at(qubit, moment_index - 1)
if last_op:
gate = cast(cirq.GateOperation, last_op).gate
if gate == cirq.CZ:
circuit.append(_choice(rand_gen(),
non_diagonal_gates).on(qubit),
strategy=cirq.InsertStrategy.EARLIEST)
elif gate != cirq.T:
circuit.append(cirq.T(qubit),
strategy=cirq.InsertStrategy.EARLIEST)

circuit.append([cirq.H(qubit) for qubit in qubits],
strategy=cirq.InsertStrategy.NEW_THEN_INLINE)
return circuit


def make_random_circuit(n_rows, n_cols, depth):
"""Generate a random unparameterized circuit of fixed depth."""
return cirq.experiments.generate_boixo_2018_supremacy_circuits_v2_grid(
circuit = generate_boixo_2018_beyond_classical_v2_grid(
n_rows=n_rows,
n_cols=n_cols,
cz_depth=depth - 2, # Account for beginning/ending Hadamard layers
cz_depth=max(0, depth - 2), # Account for initial/final Hadamards.
seed=SEED)
return cirq.Circuit(circuit[:depth])


class RandomCircuitBenchmarksTest(tf.test.TestCase, parameterized.TestCase):
Expand Down
3 changes: 1 addition & 2 deletions benchmarks/scripts/models/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,9 @@ licenses(["notice"])
# Export for the PIP package.
exports_files(["__init__.py"])

py_binary(
py_library(
name = "random_clifford_circuit",
srcs = ["random_clifford_circuit.py"],
python_version = "PY3",
)

py_test(
Expand Down
12 changes: 4 additions & 8 deletions scripts/test_benchmarks.sh
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
#!/bin/bash
# Copyright 2020 The TensorFlow Quantum Authors. All Rights Reserved.
#
#
# 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.
Expand All @@ -15,15 +15,11 @@
# ==============================================================================
echo "Testing all Benchmarks.";
bazel test -c opt --cxxopt="-D_GLIBCXX_USE_CXX11_ABI=1" --cxxopt="-msse2" --cxxopt="-msse3" --cxxopt="-msse4" --test_output=errors $(bazel query //benchmarks/scripts:all)
# test_outputs=$(bazel test -c opt --cxxopt="-D_GLIBCXX_USE_CXX11_ABI=1" --cxxopt="-msse2" --cxxopt="-msse3" --cxxopt="-msse4" --test_output=errors $(bazel query //benchmarks/scripts:all))
bench_outputs=$()
# bench_outputs=$(bazel run -c opt --cxxopt="-D_GLIBCXX_USE_CXX11_ABI=1" --cxxopt="-msse2" --cxxopt="-msse3" --cxxopt="-msse4" --test_output=errors //benchmarks/scripts:benchmark_clifford_circuit)
exit_code=$?
if [ "$exit_code" == "0" ]; then
echo "Testing Complete!";
exit 0;
else
echo "Testing failed, please correct errors before proceeding."
echo "{$test_outputs}"
exit 64;
fi
fi
Loading