From cdd2ce776b0f59c6ad50b8c0de5538a3e5063af1 Mon Sep 17 00:00:00 2001 From: Michael Broughton Date: Mon, 12 Jun 2023 13:57:18 -0700 Subject: [PATCH 01/50] Revert "Merge pull request #776 from Sinestro38/master" This reverts commit b4c7ea151275cb75bd75e5c2d35f36abf8679fd8, reversing changes made to 140277d10ca63b541acb481ecaf899f91c846e5b. --- .../core/ops/math_ops/tfq_inner_product.cc | 12 +-- .../ops/math_ops/tfq_inner_product_grad.cc | 4 +- .../core/ops/noise/tfq_noisy_expectation.cc | 28 +++---- .../noise/tfq_noisy_sampled_expectation.cc | 28 +++---- .../core/ops/noise/tfq_noisy_samples.cc | 4 +- tensorflow_quantum/core/ops/parse_context.cc | 83 +++++++------------ .../core/ops/tfq_adj_grad_op.cc | 24 +++--- .../core/ops/tfq_calculate_unitary_op.cc | 4 +- .../core/ops/tfq_ps_decompose_op.cc | 4 +- .../core/ops/tfq_ps_symbol_replace_op.cc | 10 +-- .../ops/tfq_ps_weights_from_symbols_op.cc | 8 +- .../core/ops/tfq_simulate_expectation_op.cc | 8 +- .../core/ops/tfq_simulate_state_op.cc | 8 +- tensorflow_quantum/core/src/adj_util.cc | 10 +-- .../core/src/circuit_parser_qsim.cc | 58 +++++-------- .../core/src/circuit_parser_qsim_test.cc | 7 +- .../core/src/program_resolution.cc | 23 +++-- .../core/src/program_resolution_test.cc | 27 +++--- tensorflow_quantum/core/src/util_qsim.h | 8 +- tensorflow_quantum/core/src/util_qsim_test.cc | 6 +- .../datasets/spin_system_test.py | 3 +- 21 files changed, 163 insertions(+), 204 deletions(-) diff --git a/tensorflow_quantum/core/ops/math_ops/tfq_inner_product.cc b/tensorflow_quantum/core/ops/math_ops/tfq_inner_product.cc index 374aa5b55..74751f9cc 100644 --- a/tensorflow_quantum/core/ops/math_ops/tfq_inner_product.cc +++ b/tensorflow_quantum/core/ops/math_ops/tfq_inner_product.cc @@ -174,7 +174,7 @@ class TfqInnerProductOp : public tensorflow::OpKernel { // Simulate programs one by one. Parallelizing over state vectors // we no longer parallelize over circuits. Each time we encounter a // a larger circuit we will grow the Statevector as necessary. - for (size_t i = 0; i < fused_circuits.size(); i++) { + for (int i = 0; i < fused_circuits.size(); i++) { int nq = num_qubits[i]; if (nq > largest_nq) { // need to switch to larger statespace. @@ -186,10 +186,10 @@ class TfqInnerProductOp : public tensorflow::OpKernel { // the state if there is a possibility that circuit[i] and // circuit[i + 1] produce the same state. ss.SetStateZero(sv); - for (size_t j = 0; j < fused_circuits[i].size(); j++) { + for (int j = 0; j < fused_circuits[i].size(); j++) { qsim::ApplyFusedGate(sim, fused_circuits[i][j], sv); } - for (size_t j = 0; j < other_fused_circuits[i].size(); j++) { + for (int j = 0; j < other_fused_circuits[i].size(); j++) { // (#679) Just ignore empty program if (fused_circuits[i].size() == 0) { (*output_tensor)(i, j) = std::complex(1, 0); @@ -197,7 +197,7 @@ class TfqInnerProductOp : public tensorflow::OpKernel { } ss.SetStateZero(scratch); - for (size_t k = 0; k < other_fused_circuits[i][j].size(); k++) { + for (int k = 0; k < other_fused_circuits[i][j].size(); k++) { qsim::ApplyFusedGate(sim, other_fused_circuits[i][j][k], scratch); } @@ -255,13 +255,13 @@ class TfqInnerProductOp : public tensorflow::OpKernel { // no need to update scratch_state since ComputeExpectation // will take care of things for us. ss.SetStateZero(sv); - for (size_t j = 0; j < fused_circuits[cur_batch_index].size(); j++) { + for (int j = 0; j < fused_circuits[cur_batch_index].size(); j++) { qsim::ApplyFusedGate(sim, fused_circuits[cur_batch_index][j], sv); } } ss.SetStateZero(scratch); - for (size_t k = 0; + for (int k = 0; k < other_fused_circuits[cur_batch_index][cur_internal_index].size(); k++) { diff --git a/tensorflow_quantum/core/ops/math_ops/tfq_inner_product_grad.cc b/tensorflow_quantum/core/ops/math_ops/tfq_inner_product_grad.cc index 534d7fef9..3db493b11 100644 --- a/tensorflow_quantum/core/ops/math_ops/tfq_inner_product_grad.cc +++ b/tensorflow_quantum/core/ops/math_ops/tfq_inner_product_grad.cc @@ -398,13 +398,13 @@ class TfqInnerProductGradOp : public tensorflow::OpKernel { // if applicable compute control qubit mask and control value bits. uint64_t mask = 0; uint64_t cbits = 0; - for (size_t k = 0; k < cur_gate.controlled_by.size(); k++) { + for (int k = 0; k < cur_gate.controlled_by.size(); k++) { uint64_t control_loc = cur_gate.controlled_by[k]; mask |= uint64_t{1} << control_loc; cbits |= ((cur_gate.cmask >> k) & 1) << control_loc; } - for (size_t k = 0; + for (int k = 0; k < gradient_gates[cur_batch_index][l - 1].grad_gates.size(); k++) { // Copy sv_adj onto scratch2 in anticipation of non-unitary diff --git a/tensorflow_quantum/core/ops/noise/tfq_noisy_expectation.cc b/tensorflow_quantum/core/ops/noise/tfq_noisy_expectation.cc index 6f09da68f..c67fa01f7 100644 --- a/tensorflow_quantum/core/ops/noise/tfq_noisy_expectation.cc +++ b/tensorflow_quantum/core/ops/noise/tfq_noisy_expectation.cc @@ -175,8 +175,8 @@ class TfqNoisyExpectationOp : public tensorflow::OpKernel { tensorflow::GuardedPhiloxRandom random_gen; int max_n_shots = 1; - for (size_t i = 0; i < num_samples.size(); i++) { - for (size_t j = 0; j < num_samples[i].size(); j++) { + for (int i = 0; i < num_samples.size(); i++) { + for (int j = 0; j < num_samples[i].size(); j++) { max_n_shots = std::max(max_n_shots, num_samples[i][j]); } } @@ -188,12 +188,12 @@ class TfqNoisyExpectationOp : public tensorflow::OpKernel { // Simulate programs one by one. Parallelizing over state vectors // we no longer parallelize over circuits. Each time we encounter a // a larger circuit we will grow the Statevector as necessary. - for (size_t i = 0; i < ncircuits.size(); i++) { + for (int i = 0; i < ncircuits.size(); i++) { int nq = num_qubits[i]; // (#679) Just ignore empty program if (ncircuits[i].channels.size() == 0) { - for (size_t j = 0; j < pauli_sums[i].size(); j++) { + for (int j = 0; j < pauli_sums[i].size(); j++) { (*output_tensor)(i, j) = -2.0; } continue; @@ -220,7 +220,7 @@ class TfqNoisyExpectationOp : public tensorflow::OpKernel { sv, unused_stats); // Use this trajectory as a source for all expectation calculations. - for (size_t j = 0; j < pauli_sums[i].size(); j++) { + for (int j = 0; j < pauli_sums[i].size(); j++) { if (run_samples[j] >= num_samples[i][j]) { continue; } @@ -232,14 +232,14 @@ class TfqNoisyExpectationOp : public tensorflow::OpKernel { run_samples[j]++; } bool break_loop = true; - for (size_t j = 0; j < num_samples[i].size(); j++) { + for (int j = 0; j < num_samples[i].size(); j++) { if (run_samples[j] < num_samples[i][j]) { break_loop = false; break; } } if (break_loop) { - for (size_t j = 0; j < num_samples[i].size(); j++) { + for (int j = 0; j < num_samples[i].size(); j++) { rolling_sums[j] /= num_samples[i][j]; (*output_tensor)(i, j) = static_cast(rolling_sums[j]); } @@ -280,8 +280,8 @@ class TfqNoisyExpectationOp : public tensorflow::OpKernel { tensorflow::GuardedPhiloxRandom random_gen; int max_n_shots = 1; - for (size_t i = 0; i < num_samples.size(); i++) { - for (size_t j = 0; j < num_samples[i].size(); j++) { + for (int i = 0; i < num_samples.size(); i++) { + for (int j = 0; j < num_samples[i].size(); j++) { max_n_shots = std::max(max_n_shots, num_samples[i][j]); } } @@ -304,13 +304,13 @@ class TfqNoisyExpectationOp : public tensorflow::OpKernel { random_gen.ReserveSamples128(ncircuits.size() * max_n_shots + 1); tensorflow::random::SimplePhilox rand_source(&local_gen); - for (size_t i = 0; i < ncircuits.size(); i++) { + for (int i = 0; i < ncircuits.size(); i++) { int nq = num_qubits[i]; int rep_offset = rep_offsets[start][i]; // (#679) Just ignore empty program if (ncircuits[i].channels.size() == 0) { - for (size_t j = 0; j < pauli_sums[i].size(); j++) { + for (int j = 0; j < pauli_sums[i].size(); j++) { (*output_tensor)(i, j) = -2.0; } continue; @@ -337,7 +337,7 @@ class TfqNoisyExpectationOp : public tensorflow::OpKernel { sim, sv, unused_stats); // Compute expectations across all ops using this trajectory. - for (size_t j = 0; j < pauli_sums[i].size(); j++) { + for (int j = 0; j < pauli_sums[i].size(); j++) { int p_reps = (num_samples[i][j] + num_threads - 1) / num_threads; if (run_samples[j] >= p_reps + rep_offset) { continue; @@ -354,7 +354,7 @@ class TfqNoisyExpectationOp : public tensorflow::OpKernel { // Check if we have run enough trajectories for all ops. bool break_loop = true; - for (size_t j = 0; j < num_samples[i].size(); j++) { + for (int j = 0; j < num_samples[i].size(); j++) { int p_reps = (num_samples[i][j] + num_threads - 1) / num_threads; if (run_samples[j] < p_reps + rep_offset) { break_loop = false; @@ -364,7 +364,7 @@ class TfqNoisyExpectationOp : public tensorflow::OpKernel { if (break_loop) { // Lock writing to this batch index in output_tensor. batch_locks[i].lock(); - for (size_t j = 0; j < num_samples[i].size(); j++) { + for (int j = 0; j < num_samples[i].size(); j++) { rolling_sums[j] /= num_samples[i][j]; (*output_tensor)(i, j) += static_cast(rolling_sums[j]); } diff --git a/tensorflow_quantum/core/ops/noise/tfq_noisy_sampled_expectation.cc b/tensorflow_quantum/core/ops/noise/tfq_noisy_sampled_expectation.cc index 7e1993a7e..aa0c85691 100644 --- a/tensorflow_quantum/core/ops/noise/tfq_noisy_sampled_expectation.cc +++ b/tensorflow_quantum/core/ops/noise/tfq_noisy_sampled_expectation.cc @@ -177,8 +177,8 @@ class TfqNoisySampledExpectationOp : public tensorflow::OpKernel { tensorflow::GuardedPhiloxRandom random_gen; int max_psum_length = 1; int max_n_shots = 1; - for (size_t i = 0; i < pauli_sums.size(); i++) { - for (size_t j = 0; j < pauli_sums[i].size(); j++) { + for (int i = 0; i < pauli_sums.size(); i++) { + for (int j = 0; j < pauli_sums[i].size(); j++) { max_psum_length = std::max(max_psum_length, pauli_sums[i][j].terms().size()); max_n_shots = std::max(max_n_shots, num_samples[i][j]); @@ -192,12 +192,12 @@ class TfqNoisySampledExpectationOp : public tensorflow::OpKernel { // Simulate programs one by one. Parallelizing over state vectors // we no longer parallelize over circuits. Each time we encounter a // a larger circuit we will grow the Statevector as necessary. - for (size_t i = 0; i < ncircuits.size(); i++) { + for (int i = 0; i < ncircuits.size(); i++) { int nq = num_qubits[i]; // (#679) Just ignore empty program if (ncircuits[i].channels.empty()) { - for (size_t j = 0; j < pauli_sums[i].size(); j++) { + for (int j = 0; j < pauli_sums[i].size(); j++) { (*output_tensor)(i, j) = -2.0; } continue; @@ -224,7 +224,7 @@ class TfqNoisySampledExpectationOp : public tensorflow::OpKernel { sv, unused_stats); // Use this trajectory as a source for all expectation calculations. - for (size_t j = 0; j < pauli_sums[i].size(); j++) { + for (int j = 0; j < pauli_sums[i].size(); j++) { if (run_samples[j] >= num_samples[i][j]) { continue; } @@ -236,14 +236,14 @@ class TfqNoisySampledExpectationOp : public tensorflow::OpKernel { run_samples[j]++; } bool break_loop = true; - for (size_t j = 0; j < num_samples[i].size(); j++) { + for (int j = 0; j < num_samples[i].size(); j++) { if (run_samples[j] < num_samples[i][j]) { break_loop = false; break; } } if (break_loop) { - for (size_t j = 0; j < num_samples[i].size(); j++) { + for (int j = 0; j < num_samples[i].size(); j++) { rolling_sums[j] /= num_samples[i][j]; (*output_tensor)(i, j) = static_cast(rolling_sums[j]); } @@ -285,8 +285,8 @@ class TfqNoisySampledExpectationOp : public tensorflow::OpKernel { tensorflow::GuardedPhiloxRandom random_gen; int max_psum_length = 1; int max_n_shots = 1; - for (size_t i = 0; i < pauli_sums.size(); i++) { - for (size_t j = 0; j < pauli_sums[i].size(); j++) { + for (int i = 0; i < pauli_sums.size(); i++) { + for (int j = 0; j < pauli_sums[i].size(); j++) { max_psum_length = std::max(max_psum_length, pauli_sums[i][j].terms().size()); max_n_shots = std::max(max_n_shots, num_samples[i][j]); @@ -310,13 +310,13 @@ class TfqNoisySampledExpectationOp : public tensorflow::OpKernel { auto local_gen = random_gen.ReserveSamples128(num_rand); tensorflow::random::SimplePhilox rand_source(&local_gen); - for (size_t i = 0; i < ncircuits.size(); i++) { + for (int i = 0; i < ncircuits.size(); i++) { int nq = num_qubits[i]; int rep_offset = rep_offsets[start][i]; // (#679) Just ignore empty program if (ncircuits[i].channels.empty()) { - for (size_t j = 0; j < pauli_sums[i].size(); j++) { + for (int j = 0; j < pauli_sums[i].size(); j++) { (*output_tensor)(i, j) = -2.0; } continue; @@ -343,7 +343,7 @@ class TfqNoisySampledExpectationOp : public tensorflow::OpKernel { sim, sv, unused_stats); // Compute expectations across all ops using this trajectory. - for (size_t j = 0; j < pauli_sums[i].size(); j++) { + for (int j = 0; j < pauli_sums[i].size(); j++) { int p_reps = (num_samples[i][j] + num_threads - 1) / num_threads; if (run_samples[j] >= p_reps + rep_offset) { continue; @@ -360,7 +360,7 @@ class TfqNoisySampledExpectationOp : public tensorflow::OpKernel { // Check if we have run enough trajectories for all ops. bool break_loop = true; - for (size_t j = 0; j < num_samples[i].size(); j++) { + for (int j = 0; j < num_samples[i].size(); j++) { int p_reps = (num_samples[i][j] + num_threads - 1) / num_threads; if (run_samples[j] < p_reps + rep_offset) { break_loop = false; @@ -370,7 +370,7 @@ class TfqNoisySampledExpectationOp : public tensorflow::OpKernel { if (break_loop) { // Lock writing to this batch index in output_tensor. batch_locks[i].lock(); - for (size_t j = 0; j < num_samples[i].size(); j++) { + for (int j = 0; j < num_samples[i].size(); j++) { rolling_sums[j] /= num_samples[i][j]; (*output_tensor)(i, j) += static_cast(rolling_sums[j]); } diff --git a/tensorflow_quantum/core/ops/noise/tfq_noisy_samples.cc b/tensorflow_quantum/core/ops/noise/tfq_noisy_samples.cc index 1af738323..341c87910 100644 --- a/tensorflow_quantum/core/ops/noise/tfq_noisy_samples.cc +++ b/tensorflow_quantum/core/ops/noise/tfq_noisy_samples.cc @@ -159,7 +159,7 @@ class TfqNoisySamplesOp : public tensorflow::OpKernel { // Simulate programs one by one. Parallelizing over state vectors // we no longer parallelize over circuits. Each time we encounter a // a larger circuit we will grow the Statevector as nescessary. - for (size_t i = 0; i < ncircuits.size(); i++) { + for (int i = 0; i < ncircuits.size(); i++) { int nq = num_qubits[i]; if (nq > largest_nq) { @@ -252,7 +252,7 @@ class TfqNoisySamplesOp : public tensorflow::OpKernel { auto local_gen = random_gen.ReserveSamples32(needed_random); tensorflow::random::SimplePhilox rand_source(&local_gen); - for (size_t i = 0; i < ncircuits.size(); i++) { + for (int i = 0; i < ncircuits.size(); i++) { int nq = num_qubits[i]; int j = start > 0 ? offset_prefix_sum[start - 1][i] : 0; int needed_samples = offset_prefix_sum[start][i] - j; diff --git a/tensorflow_quantum/core/ops/parse_context.cc b/tensorflow_quantum/core/ops/parse_context.cc index 026c57321..f926d15bb 100644 --- a/tensorflow_quantum/core/ops/parse_context.cc +++ b/tensorflow_quantum/core/ops/parse_context.cc @@ -20,7 +20,6 @@ limitations under the License. #include #include -#include "absl/status/status.h" #include "tensorflow/core/framework/op_kernel.h" #include "tensorflow/core/lib/core/error_codes.pb.h" #include "tensorflow/core/lib/core/status.h" @@ -52,7 +51,7 @@ Status ParseProto(const std::string& text, T* proto) { } return Status( - static_cast(absl::StatusCode::kInvalidArgument), + static_cast(absl::StatusCode::kInvalidArgument), "Unparseable proto: " + text); } @@ -69,7 +68,7 @@ Status ParsePrograms(OpKernelContext* context, const std::string& input_name, if (input->dims() != 1) { // Never parse anything other than a 1d list of circuits. return Status( - static_cast( + static_cast( absl::StatusCode::kInvalidArgument), absl::StrCat("programs must be rank 1. Got rank ", input->dims(), ".")); } @@ -78,13 +77,9 @@ Status ParsePrograms(OpKernelContext* context, const std::string& input_name, const int num_programs = program_strings.dimension(0); programs->assign(num_programs, Program()); - Status parse_status = ::tensorflow::Status(); - auto p_lock = tensorflow::mutex(); - auto DoWork = [&](int start, int end) { for (int i = start; i < end; i++) { - Status local = ParseProto(program_strings(i), &programs->at(i)); - NESTED_FN_STATUS_SYNC(parse_status, local, p_lock); + OP_REQUIRES_OK(context, ParseProto(program_strings(i), &programs->at(i))); } }; @@ -93,7 +88,7 @@ Status ParsePrograms(OpKernelContext* context, const std::string& input_name, context->device()->tensorflow_cpu_worker_threads()->workers->ParallelFor( num_programs, cycle_estimate, DoWork); - return parse_status; + return ::tensorflow::Status(); } Status ParsePrograms2D(OpKernelContext* context, const std::string& input_name, @@ -106,7 +101,7 @@ Status ParsePrograms2D(OpKernelContext* context, const std::string& input_name, if (input->dims() != 2) { // Never parse anything other than a 1d list of circuits. - return Status(static_cast( + return Status(static_cast( absl::StatusCode::kInvalidArgument), absl::StrCat("other_programs must be rank 2. Got rank ", input->dims(), ".")); @@ -117,14 +112,12 @@ Status ParsePrograms2D(OpKernelContext* context, const std::string& input_name, const int num_entries = program_strings.dimension(1); programs->assign(num_programs, std::vector(num_entries, Program())); - Status parse_status = ::tensorflow::Status(); - auto p_lock = tensorflow::mutex(); auto DoWork = [&](int start, int end) { for (int i = start; i < end; i++) { - Status local = + OP_REQUIRES_OK( + context, ParseProto(program_strings(i / num_entries, i % num_entries), - &programs->at(i / num_entries).at(i % num_entries)); - NESTED_FN_STATUS_SYNC(parse_status, local, p_lock); + &programs->at(i / num_entries).at(i % num_entries))); } }; @@ -133,7 +126,7 @@ Status ParsePrograms2D(OpKernelContext* context, const std::string& input_name, context->device()->tensorflow_cpu_worker_threads()->workers->ParallelFor( num_programs * num_entries, cycle_estimate, DoWork); - return parse_status; + return ::tensorflow::Status(); } Status GetProgramsAndProgramsToAppend( @@ -150,7 +143,7 @@ Status GetProgramsAndProgramsToAppend( } if (programs->size() != programs_to_append->size()) { - return Status(static_cast( + return Status(static_cast( absl::StatusCode::kInvalidArgument), "programs and programs_to_append must have matching sizes."); } @@ -178,7 +171,7 @@ Status GetProgramsAndNumQubits( } if (programs->size() != p_sums->size()) { return Status( - static_cast( + static_cast( absl::StatusCode::kInvalidArgument), absl::StrCat("Number of circuits and PauliSums do not match. Got ", programs->size(), " circuits and ", p_sums->size(), @@ -187,22 +180,19 @@ Status GetProgramsAndNumQubits( } // Resolve qubit ID's in parallel. - Status parse_status = ::tensorflow::Status(); - auto p_lock = tensorflow::mutex(); num_qubits->assign(programs->size(), -1); auto DoWork = [&](int start, int end) { for (int i = start; i < end; i++) { Program& program = (*programs)[i]; unsigned int this_num_qubits; - Status local; if (p_sums) { - local = ResolveQubitIds(&program, &this_num_qubits, &(p_sums->at(i)), - swap_endianness); + OP_REQUIRES_OK(context, + ResolveQubitIds(&program, &this_num_qubits, + &(p_sums->at(i)), swap_endianness)); } else { - local = ResolveQubitIds(&program, &this_num_qubits, nullptr, - swap_endianness); + OP_REQUIRES_OK(context, ResolveQubitIds(&program, &this_num_qubits, + nullptr, swap_endianness)); } - NESTED_FN_STATUS_SYNC(parse_status, local, p_lock); (*num_qubits)[i] = this_num_qubits; } }; @@ -212,7 +202,7 @@ Status GetProgramsAndNumQubits( context->device()->tensorflow_cpu_worker_threads()->workers->ParallelFor( num_qubits->size(), cycle_estimate, DoWork); - return parse_status; + return ::tensorflow::Status(); } tensorflow::Status GetProgramsAndNumQubits( @@ -233,7 +223,7 @@ tensorflow::Status GetProgramsAndNumQubits( } if (programs->size() != other_programs->size()) { - return Status(static_cast( + return Status(static_cast( absl::StatusCode::kInvalidArgument), absl::StrCat("programs and other_programs batch dimension", " do not match. Foud: ", programs->size(), @@ -241,16 +231,13 @@ tensorflow::Status GetProgramsAndNumQubits( } // Resolve qubit ID's in parallel. - Status parse_status = ::tensorflow::Status(); - auto p_lock = tensorflow::mutex(); num_qubits->assign(programs->size(), -1); auto DoWork = [&](int start, int end) { for (int i = start; i < end; i++) { Program& program = (*programs)[i]; unsigned int this_num_qubits; - Status local = - ResolveQubitIds(&program, &this_num_qubits, &(*other_programs)[i]); - NESTED_FN_STATUS_SYNC(parse_status, local, p_lock); + OP_REQUIRES_OK(context, ResolveQubitIds(&program, &this_num_qubits, + &(*other_programs)[i])); (*num_qubits)[i] = this_num_qubits; } }; @@ -260,7 +247,7 @@ tensorflow::Status GetProgramsAndNumQubits( context->device()->tensorflow_cpu_worker_threads()->workers->ParallelFor( num_qubits->size(), cycle_estimate, DoWork); - return parse_status; + return ::tensorflow::Status(); } Status GetPauliSums(OpKernelContext* context, @@ -273,7 +260,7 @@ Status GetPauliSums(OpKernelContext* context, } if (input->dims() != 2) { - return Status(static_cast( + return Status(static_cast( absl::StatusCode::kInvalidArgument), absl::StrCat("pauli_sums must be rank 2. Got rank ", input->dims(), ".")); @@ -283,18 +270,12 @@ Status GetPauliSums(OpKernelContext* context, p_sums->assign(sum_specs.dimension(0), std::vector(sum_specs.dimension(1), PauliSum())); const int op_dim = sum_specs.dimension(1); - Status parse_status = ::tensorflow::Status(); - auto p_lock = tensorflow::mutex(); auto DoWork = [&](int start, int end) { for (int ii = start; ii < end; ii++) { const int i = ii / op_dim; const int j = ii % op_dim; PauliSum p; - // We should not stop the whole program, because TFQ cuQuantum ops - // requires running destructors to return cuQuantum handlers, - // and not to fall into segfault. - Status local = ParseProto(sum_specs(i, j), &p); - NESTED_FN_STATUS_SYNC(parse_status, local, p_lock); + OP_REQUIRES_OK(context, ParseProto(sum_specs(i, j), &p)); (*p_sums)[i][j] = p; } }; @@ -304,7 +285,7 @@ Status GetPauliSums(OpKernelContext* context, context->device()->tensorflow_cpu_worker_threads()->workers->ParallelFor( sum_specs.dimension(0) * sum_specs.dimension(1), cycle_estimate, DoWork); - return parse_status; + return ::tensorflow::Status(); } Status GetSymbolMaps(OpKernelContext* context, std::vector* maps) { @@ -316,7 +297,7 @@ Status GetSymbolMaps(OpKernelContext* context, std::vector* maps) { } if (input_names->dims() != 1) { - return Status(static_cast( + return Status(static_cast( absl::StatusCode::kInvalidArgument), absl::StrCat("symbol_names must be rank 1. Got rank ", input_names->dims(), ".")); @@ -329,7 +310,7 @@ Status GetSymbolMaps(OpKernelContext* context, std::vector* maps) { } if (input_values->dims() != 2) { - return Status(static_cast( + return Status(static_cast( absl::StatusCode::kInvalidArgument), absl::StrCat("symbol_values must be rank 2. Got rank ", input_values->dims(), ".")); @@ -339,7 +320,7 @@ Status GetSymbolMaps(OpKernelContext* context, std::vector* maps) { const auto symbol_values = input_values->matrix(); if (symbol_names.dimension(0) != symbol_values.dimension(1)) { - return Status(static_cast( + return Status(static_cast( absl::StatusCode::kInvalidArgument), "Input symbol names and value sizes do not match."); } @@ -375,7 +356,7 @@ tensorflow::Status GetNumSamples( } if (input_num_samples->dims() != 2) { - return Status(static_cast( + return Status(static_cast( absl::StatusCode::kInvalidArgument), absl::StrCat("num_samples must be rank 2. Got rank ", input_num_samples->dims(), ".")); @@ -389,7 +370,7 @@ tensorflow::Status GetNumSamples( for (unsigned int j = 0; j < matrix_num_samples.dimension(1); j++) { const int num_samples = matrix_num_samples(i, j); if (num_samples < 1) { - return Status(static_cast( + return Status(static_cast( absl::StatusCode::kInvalidArgument), "Each element of num_samples must be greater than 0."); } @@ -411,7 +392,7 @@ Status GetIndividualSample(tensorflow::OpKernelContext* context, } if (input_num_samples->dims() != 1) { - return Status(static_cast( + return Status(static_cast( absl::StatusCode::kInvalidArgument), absl::StrCat("num_samples must be rank 1. Got rank ", input_num_samples->dims(), ".")); @@ -420,7 +401,7 @@ Status GetIndividualSample(tensorflow::OpKernelContext* context, const auto vector_num_samples = input_num_samples->vec(); if (vector_num_samples.dimension(0) != 1) { - return Status(static_cast( + return Status(static_cast( absl::StatusCode::kInvalidArgument), absl::StrCat("num_samples must contain 1 element. Got ", vector_num_samples.dimension(0), ".")); @@ -441,7 +422,7 @@ tensorflow::Status GetPrevGrads( } if (input_grads->dims() != 2) { - return Status(static_cast( + return Status(static_cast( absl::StatusCode::kInvalidArgument), absl::StrCat("downstream_grads must be rank 2. Got rank ", input_grads->dims(), ".")); diff --git a/tensorflow_quantum/core/ops/tfq_adj_grad_op.cc b/tensorflow_quantum/core/ops/tfq_adj_grad_op.cc index fe88a5817..e7252baee 100644 --- a/tensorflow_quantum/core/ops/tfq_adj_grad_op.cc +++ b/tensorflow_quantum/core/ops/tfq_adj_grad_op.cc @@ -202,15 +202,15 @@ class TfqAdjointGradientOp : public tensorflow::OpKernel { } ss.SetStateZero(sv); - for (size_t j = 0; j < full_fuse[i].size(); j++) { + for (int j = 0; j < full_fuse[i].size(); j++) { qsim::ApplyFusedGate(sim, full_fuse[i][j], sv); } // sv now contains psi // scratch contains (sum_j paulis_sums[i][j] * downstream_grads[j])|psi> // scratch2 now contains psi as well. - [[maybe_unused]] Status unused = AccumulateOperators( - pauli_sums[i], downstream_grads[i], sim, ss, sv, scratch2, scratch); + Status unused = AccumulateOperators(pauli_sums[i], downstream_grads[i], + sim, ss, sv, scratch2, scratch); for (int j = partial_fused_circuits[i].size() - 1; j >= 0; j--) { for (int k = partial_fused_circuits[i][j].size() - 1; k >= 0; k--) { @@ -231,14 +231,13 @@ class TfqAdjointGradientOp : public tensorflow::OpKernel { // if applicable compute control qubit mask and control value bits. uint64_t mask = 0; uint64_t cbits = 0; - for (size_t k = 0; k < cur_gate.controlled_by.size(); k++) { + for (int k = 0; k < cur_gate.controlled_by.size(); k++) { uint64_t control_loc = cur_gate.controlled_by[k]; mask |= uint64_t{1} << control_loc; cbits |= ((cur_gate.cmask >> k) & 1) << control_loc; } - for (size_t k = 0; k < gradient_gates[i][j - 1].grad_gates.size(); - k++) { + for (int k = 0; k < gradient_gates[i][j - 1].grad_gates.size(); k++) { // Copy sv onto scratch2 in anticipation of non-unitary "gradient // gate". ss.Copy(sv, scratch2); @@ -298,7 +297,7 @@ class TfqAdjointGradientOp : public tensorflow::OpKernel { auto scratch = ss.Create(largest_nq); auto scratch2 = ss.Create(largest_nq); - for (size_t i = 0; i < partial_fused_circuits.size(); i++) { + for (int i = 0; i < partial_fused_circuits.size(); i++) { int nq = num_qubits[i]; if (nq > largest_nq) { @@ -315,15 +314,15 @@ class TfqAdjointGradientOp : public tensorflow::OpKernel { } ss.SetStateZero(sv); - for (size_t j = 0; j < full_fuse[i].size(); j++) { + for (int j = 0; j < full_fuse[i].size(); j++) { qsim::ApplyFusedGate(sim, full_fuse[i][j], sv); } // sv now contains psi // scratch contains (sum_j paulis_sums[i][j] * downstream_grads[j])|psi> // scratch2 now contains psi as well. - [[maybe_unused]] Status unused = AccumulateOperators( - pauli_sums[i], downstream_grads[i], sim, ss, sv, scratch2, scratch); + Status unused = AccumulateOperators(pauli_sums[i], downstream_grads[i], + sim, ss, sv, scratch2, scratch); for (int j = partial_fused_circuits[i].size() - 1; j >= 0; j--) { for (int k = partial_fused_circuits[i][j].size() - 1; k >= 0; k--) { @@ -343,14 +342,13 @@ class TfqAdjointGradientOp : public tensorflow::OpKernel { // if applicable compute control qubit mask and control value bits. uint64_t mask = 0; uint64_t cbits = 0; - for (size_t k = 0; k < cur_gate.controlled_by.size(); k++) { + for (int k = 0; k < cur_gate.controlled_by.size(); k++) { uint64_t control_loc = cur_gate.controlled_by[k]; mask |= uint64_t{1} << control_loc; cbits |= ((cur_gate.cmask >> k) & 1) << control_loc; } - for (size_t k = 0; k < gradient_gates[i][j - 1].grad_gates.size(); - k++) { + for (int k = 0; k < gradient_gates[i][j - 1].grad_gates.size(); k++) { // Copy sv onto scratch2 in anticipation of non-unitary "gradient // gate". ss.Copy(sv, scratch2); diff --git a/tensorflow_quantum/core/ops/tfq_calculate_unitary_op.cc b/tensorflow_quantum/core/ops/tfq_calculate_unitary_op.cc index 4f1f662ca..ace5327e1 100644 --- a/tensorflow_quantum/core/ops/tfq_calculate_unitary_op.cc +++ b/tensorflow_quantum/core/ops/tfq_calculate_unitary_op.cc @@ -116,7 +116,7 @@ class TfqCalculateUnitaryOp : public tensorflow::OpKernel { // Simulate programs one by one. Parallelizing over state vectors // we no longer parallelize over circuits. Each time we encounter a // a larger circuit we will grow the unitary as nescessary. - for (size_t i = 0; i < fused_circuits.size(); i++) { + for (int i = 0; i < fused_circuits.size(); i++) { int nq = num_qubits[i]; UCalculator sim = UCalculator(tfq_for); UnitarySpace us = UnitarySpace(tfq_for); @@ -126,7 +126,7 @@ class TfqCalculateUnitaryOp : public tensorflow::OpKernel { u = us.CreateUnitary(nq); } us.SetIdentity(u); - for (size_t j = 0; j < fused_circuits[i].size(); j++) { + for (int j = 0; j < fused_circuits[i].size(); j++) { qsim::ApplyFusedGate(sim, fused_circuits[i][j], u); } diff --git a/tensorflow_quantum/core/ops/tfq_ps_decompose_op.cc b/tensorflow_quantum/core/ops/tfq_ps_decompose_op.cc index 5c20e546e..669ea6368 100644 --- a/tensorflow_quantum/core/ops/tfq_ps_decompose_op.cc +++ b/tensorflow_quantum/core/ops/tfq_ps_decompose_op.cc @@ -65,11 +65,11 @@ class TfqPsDecomposeOp : public tensorflow::OpKernel { new_program.mutable_language()->set_gate_set("tfq_gate_set"); new_program.mutable_circuit()->set_scheduling_strategy( Circuit::MOMENT_BY_MOMENT); - for (size_t j = 0; j < cur_program.circuit().moments().size(); j++) { + for (int j = 0; j < cur_program.circuit().moments().size(); j++) { Moment cur_moment(cur_program.circuit().moments().at(j)); std::vector temp_moment_list(max_buffer_moments, Moment()); int num_extra_moments = 0; - for (size_t k = 0; k < cur_moment.operations().size(); k++) { + for (int k = 0; k < cur_moment.operations().size(); k++) { Operation cur_op = cur_moment.operations().at(k); auto &cur_op_map = *cur_op.mutable_args(); if (cur_op.gate().id() == "PISP") { diff --git a/tensorflow_quantum/core/ops/tfq_ps_symbol_replace_op.cc b/tensorflow_quantum/core/ops/tfq_ps_symbol_replace_op.cc index 6a38be061..559fbecc9 100644 --- a/tensorflow_quantum/core/ops/tfq_ps_symbol_replace_op.cc +++ b/tensorflow_quantum/core/ops/tfq_ps_symbol_replace_op.cc @@ -89,9 +89,9 @@ class TfqPsSymbolReplaceOp : public tensorflow::OpKernel { std::string symbol_to_replace = symbols(sidx); std::string temp_symbol_holder; Program cur_program = programs.at(pidx); - for (size_t j = 0; j < cur_program.circuit().moments().size(); j++) { + for (int j = 0; j < cur_program.circuit().moments().size(); j++) { Moment cur_moment = cur_program.circuit().moments().at(j); - for (size_t k = 0; k < cur_moment.operations().size(); k++) { + for (int k = 0; k < cur_moment.operations().size(); k++) { Operation cur_op = cur_moment.operations().at(k); for (auto l = cur_op.args().begin(); l != cur_op.args().end(); l++) { @@ -163,12 +163,12 @@ class TfqPsSymbolReplaceOp : public tensorflow::OpKernel { for (int i = start; i < end; i++) { int sidx = i % n_symbols; int pidx = i / n_symbols; - for (size_t j = 0; j < output_programs.at(pidx).at(sidx).size(); j++) { + for (int j = 0; j < output_programs.at(pidx).at(sidx).size(); j++) { output_tensor(pidx, sidx, j) = output_programs.at(pidx).at(sidx).at(j); } - for (size_t j = output_programs.at(pidx).at(sidx).size(); - j < biggest_pad; j++) { + for (int j = output_programs.at(pidx).at(sidx).size(); j < biggest_pad; + j++) { output_tensor(pidx, sidx, j) = empty_program; } } diff --git a/tensorflow_quantum/core/ops/tfq_ps_weights_from_symbols_op.cc b/tensorflow_quantum/core/ops/tfq_ps_weights_from_symbols_op.cc index 65c03a77c..4a027223e 100644 --- a/tensorflow_quantum/core/ops/tfq_ps_weights_from_symbols_op.cc +++ b/tensorflow_quantum/core/ops/tfq_ps_weights_from_symbols_op.cc @@ -82,9 +82,9 @@ class TfqPsWeightsFromSymbolOp : public tensorflow::OpKernel { auto DoWork = [&](int start, int end) { for (int i = start; i < end; i++) { Program cur_program = programs.at(i); - for (size_t j = 0; j < cur_program.circuit().moments().size(); j++) { + for (int j = 0; j < cur_program.circuit().moments().size(); j++) { Moment cur_moment = cur_program.circuit().moments().at(j); - for (size_t k = 0; k < cur_moment.operations().size(); k++) { + for (int k = 0; k < cur_moment.operations().size(); k++) { Operation cur_op = cur_moment.operations().at(k); if (ignored_symbol_set.contains(cur_op.gate().id())) continue; @@ -146,10 +146,10 @@ class TfqPsWeightsFromSymbolOp : public tensorflow::OpKernel { auto DoWork2 = [&](int start, int end) { for (int i = start; i < end; i++) { for (int j = 0; j < n_symbols; j++) { - for (size_t k = 0; k < output_results.at(i).at(j).size(); k++) { + for (int k = 0; k < output_results.at(i).at(j).size(); k++) { output_tensor(i, j, k) = output_results.at(i).at(j).at(k); } - for (size_t k = output_results.at(i).at(j).size(); + for (int k = output_results.at(i).at(j).size(); k < largest_single_symbol; k++) { output_tensor(i, j, k) = 0.0f; } diff --git a/tensorflow_quantum/core/ops/tfq_simulate_expectation_op.cc b/tensorflow_quantum/core/ops/tfq_simulate_expectation_op.cc index 210e9e93f..bca6d2f63 100644 --- a/tensorflow_quantum/core/ops/tfq_simulate_expectation_op.cc +++ b/tensorflow_quantum/core/ops/tfq_simulate_expectation_op.cc @@ -143,7 +143,7 @@ class TfqSimulateExpectationOp : public tensorflow::OpKernel { // Simulate programs one by one. Parallelizing over state vectors // we no longer parallelize over circuits. Each time we encounter a // a larger circuit we will grow the Statevector as necessary. - for (size_t i = 0; i < fused_circuits.size(); i++) { + for (int i = 0; i < fused_circuits.size(); i++) { int nq = num_qubits[i]; if (nq > largest_nq) { @@ -156,10 +156,10 @@ class TfqSimulateExpectationOp : public tensorflow::OpKernel { // the state if there is a possibility that circuit[i] and // circuit[i + 1] produce the same state. ss.SetStateZero(sv); - for (size_t j = 0; j < fused_circuits[i].size(); j++) { + for (int j = 0; j < fused_circuits[i].size(); j++) { qsim::ApplyFusedGate(sim, fused_circuits[i][j], sv); } - for (size_t j = 0; j < pauli_sums[i].size(); j++) { + for (int j = 0; j < pauli_sums[i].size(); j++) { // (#679) Just ignore empty program if (fused_circuits[i].size() == 0) { (*output_tensor)(i, j) = -2.0; @@ -221,7 +221,7 @@ class TfqSimulateExpectationOp : public tensorflow::OpKernel { // no need to update scratch_state since ComputeExpectation // will take care of things for us. ss.SetStateZero(sv); - for (size_t j = 0; j < fused_circuits[cur_batch_index].size(); j++) { + for (int j = 0; j < fused_circuits[cur_batch_index].size(); j++) { qsim::ApplyFusedGate(sim, fused_circuits[cur_batch_index][j], sv); } } diff --git a/tensorflow_quantum/core/ops/tfq_simulate_state_op.cc b/tensorflow_quantum/core/ops/tfq_simulate_state_op.cc index 833deb965..e659800ce 100644 --- a/tensorflow_quantum/core/ops/tfq_simulate_state_op.cc +++ b/tensorflow_quantum/core/ops/tfq_simulate_state_op.cc @@ -135,8 +135,8 @@ class TfqSimulateStateOp : public tensorflow::OpKernel { // Simulate programs one by one. Parallelizing over state vectors // we no longer parallelize over circuits. Each time we encounter a - // a larger circuit we will grow the Statevector as necessary. - for (size_t i = 0; i < fused_circuits.size(); i++) { + // a larger circuit we will grow the Statevector as nescessary. + for (int i = 0; i < fused_circuits.size(); i++) { int nq = num_qubits[i]; if (nq > largest_nq) { @@ -145,7 +145,7 @@ class TfqSimulateStateOp : public tensorflow::OpKernel { sv = ss.Create(largest_nq); } ss.SetStateZero(sv); - for (size_t j = 0; j < fused_circuits[i].size(); j++) { + for (int j = 0; j < fused_circuits[i].size(); j++) { qsim::ApplyFusedGate(sim, fused_circuits[i][j], sv); } @@ -194,7 +194,7 @@ class TfqSimulateStateOp : public tensorflow::OpKernel { sv = ss.Create(largest_nq); } ss.SetStateZero(sv); - for (size_t j = 0; j < fused_circuits[i].size(); j++) { + for (int j = 0; j < fused_circuits[i].size(); j++) { qsim::ApplyFusedGate(sim, fused_circuits[i][j], sv); } diff --git a/tensorflow_quantum/core/src/adj_util.cc b/tensorflow_quantum/core/src/adj_util.cc index e15ff8a8c..ceb76b2c1 100644 --- a/tensorflow_quantum/core/src/adj_util.cc +++ b/tensorflow_quantum/core/src/adj_util.cc @@ -38,7 +38,7 @@ void CreateGradientCircuit( const QsimCircuit& circuit, const std::vector& metadata, std::vector>>* partial_fuses, std::vector* grad_gates) { - for (size_t i = 0; i < metadata.size(); i++) { + for (int i = 0; i < metadata.size(); i++) { if (metadata[i].symbol_values.empty()) { continue; } @@ -78,7 +78,7 @@ void CreateGradientCircuit( // PhasedX else if (circuit.gates[i].kind == qsim::Cirq::GateKind::kPhasedXPowGate) { // Process potentially several symbols. - for (size_t j = 0; j < metadata[i].symbol_values.size(); j++) { + for (int j = 0; j < metadata[i].symbol_values.size(); j++) { if (metadata[i].placeholder_names[j] == GateParamNames::kPhaseExponent) { PopulateGradientPhasedXPhasedExponent( @@ -103,7 +103,7 @@ void CreateGradientCircuit( // Process potentially several symbols. bool swapq = circuit.gates[i].swapped; - for (size_t j = 0; j < metadata[i].symbol_values.size(); j++) { + for (int j = 0; j < metadata[i].symbol_values.size(); j++) { if (metadata[i].placeholder_names[j] == GateParamNames::kTheta) { PopulateGradientFsimTheta( metadata[i].symbol_values[j], i, @@ -128,7 +128,7 @@ void CreateGradientCircuit( qsim::Cirq::GateKind::kPhasedISwapPowGate) { // Process potentially several symbols. bool swapq = circuit.gates[i].swapped; - for (size_t j = 0; j < metadata[i].symbol_values.size(); j++) { + for (int j = 0; j < metadata[i].symbol_values.size(); j++) { if (metadata[i].placeholder_names[j] == GateParamNames::kPhaseExponent) { PopulateGradientPhasedISwapPhasedExponent( @@ -159,7 +159,7 @@ void CreateGradientCircuit( partial_fuses->assign(grad_gates->size() + 1, std::vector>({})); - for (size_t i = 0; i < grad_gates->size(); i++) { + for (int i = 0; i < grad_gates->size(); i++) { right = circuit.gates.begin() + (*grad_gates)[i].index; (*partial_fuses)[i] = fuser.FuseGates(qsim::BasicGateFuser::Parameter(), diff --git a/tensorflow_quantum/core/src/circuit_parser_qsim.cc b/tensorflow_quantum/core/src/circuit_parser_qsim.cc index 8b70ab041..1024d28c7 100644 --- a/tensorflow_quantum/core/src/circuit_parser_qsim.cc +++ b/tensorflow_quantum/core/src/circuit_parser_qsim.cc @@ -27,7 +27,6 @@ limitations under the License. #include "../qsim/lib/gates_cirq.h" #include "../qsim/lib/io.h" #include "absl/container/flat_hash_map.h" -#include "absl/status/status.h" #include "absl/strings/numbers.h" #include "absl/strings/str_split.h" #include "absl/strings/string_view.h" @@ -59,7 +58,7 @@ inline Status ParseProtoArg( // iterator> const auto arg_v = op.args().find(arg_name); if (arg_v == op.args().end()) { - return Status(static_cast( + return Status(static_cast( absl::StatusCode::kInvalidArgument), "Could not find arg: " + arg_name + " in op."); } @@ -72,7 +71,7 @@ inline Status ParseProtoArg( const auto iter = param_map.find(proto_arg.symbol()); if (iter == param_map.end()) { return Status( - static_cast( + static_cast( absl::StatusCode::kInvalidArgument), "Could not find symbol in parameter map: " + proto_arg.symbol()); } @@ -104,7 +103,7 @@ inline Status ParseProtoControls(const Operation& op, absl::StrSplit(control_v_str, ','); if (control_toks.size() != control_v_toks.size()) { - return Status(static_cast( + return Status(static_cast( absl::StatusCode::kInvalidArgument), "Mistmatched number of control qubits and control values."); } @@ -124,7 +123,7 @@ inline Status ParseProtoControls(const Operation& op, for (auto tok : control_v_toks) { valid = absl::SimpleAtoi(tok, &tmp); if (!valid) { - return Status(static_cast( + return Status(static_cast( absl::StatusCode::kInvalidArgument), "Unparseable control value: " + std::string(tok)); } @@ -187,8 +186,7 @@ inline Status TwoConstantGate( const unsigned int num_qubits, const unsigned int time, QsimCircuit* circuit, std::vector* metadata) { unsigned int q0, q1; - [[maybe_unused]] bool unused; - unused = absl::SimpleAtoi(op.qubits(0).id(), &q0); + bool unused = absl::SimpleAtoi(op.qubits(0).id(), &q0); unused = absl::SimpleAtoi(op.qubits(1).id(), &q1); auto gate = create_f(time, num_qubits - q0 - 1, num_qubits - q1 - 1); Status s = OptionalInsertControls(op, num_qubits, &gate); @@ -214,10 +212,9 @@ inline Status SingleEigenGate( const unsigned int num_qubits, const unsigned int time, QsimCircuit* circuit, std::vector* metadata) { unsigned int q0; - + bool unused; float exp, exp_s, gs; Status u; - [[maybe_unused]] bool unused; unused = absl::SimpleAtoi(op.qubits(0).id(), &q0); absl::optional exponent_symbol; @@ -265,9 +262,8 @@ inline Status TwoEigenGate( QsimCircuit* circuit, std::vector* metadata) { unsigned int q0, q1; float exp, exp_s, gs; - + bool unused; Status u; - [[maybe_unused]] bool unused; unused = absl::SimpleAtoi(op.qubits(0).id(), &q0); unused = absl::SimpleAtoi(op.qubits(1).id(), &q1); @@ -405,10 +401,9 @@ inline Status PhasedXGate(const Operation& op, const SymbolMap& param_map, const unsigned int time, QsimCircuit* circuit, std::vector* metadata) { int q0; - + bool unused; float pexp, pexp_s, exp, exp_s, gs; Status u; - [[maybe_unused]] bool unused; unused = absl::SimpleAtoi(op.qubits(0).id(), &q0); absl::optional exponent_symbol; @@ -466,10 +461,9 @@ inline Status FsimGate(const Operation& op, const SymbolMap& param_map, QsimCircuit* circuit, std::vector* metadata) { int q0, q1; - + bool unused; float theta, theta_s, phi, phi_s; Status u; - [[maybe_unused]] bool unused; unused = absl::SimpleAtoi(op.qubits(0).id(), &q0); unused = absl::SimpleAtoi(op.qubits(1).id(), &q1); @@ -524,10 +518,9 @@ inline Status PhasedISwapGate(const Operation& op, const SymbolMap& param_map, const unsigned int time, QsimCircuit* circuit, std::vector* metadata) { int q0, q1; - + bool unused; float pexp, pexp_s, exp, exp_s; Status u; - [[maybe_unused]] bool unused; unused = absl::SimpleAtoi(op.qubits(0).id(), &q0); unused = absl::SimpleAtoi(op.qubits(1).id(), &q1); @@ -602,7 +595,7 @@ tensorflow::Status ParseAppendGate(const Operation& op, auto build_f = func_map.find(op.gate().id()); if (build_f == func_map.end()) { *lookup_succeeded = false; - return Status(static_cast( + return Status(static_cast( absl::StatusCode::kInvalidArgument), absl::StrCat("Could not parse gate id: ", op.gate().id(), ". This is likely because a cirq.Channel was " @@ -617,10 +610,9 @@ inline Status AsymmetricDepolarizingChannel(const Operation& op, const unsigned int time, NoisyQsimCircuit* ncircuit) { int q; - + bool unused; float p_x, p_y, p_z; Status u; - [[maybe_unused]] bool unused; unused = absl::SimpleAtoi(op.qubits(0).id(), &q); u = ParseProtoArg(op, "p_x", {}, &p_x); @@ -640,10 +632,9 @@ inline Status DepolarizingChannel(const Operation& op, const unsigned int time, NoisyQsimCircuit* ncircuit) { int q; - + bool unused; float p; Status u; - [[maybe_unused]] bool unused; unused = absl::SimpleAtoi(op.qubits(0).id(), &q); u = ParseProtoArg(op, "p", {}, &p); @@ -659,10 +650,9 @@ inline Status DepolarizingChannel(const Operation& op, inline Status GADChannel(const Operation& op, const unsigned int num_qubits, const unsigned int time, NoisyQsimCircuit* ncircuit) { int q; - + bool unused; float p, gamma; Status u; - [[maybe_unused]] bool unused; unused = absl::SimpleAtoi(op.qubits(0).id(), &q); u = ParseProtoArg(op, "p", {}, &p); @@ -684,8 +674,7 @@ inline Status ResetChannel(const Operation& op, const unsigned int num_qubits, const unsigned int time, NoisyQsimCircuit* ncircuit) { int q; - - [[maybe_unused]] bool unused; + bool unused; unused = absl::SimpleAtoi(op.qubits(0).id(), &q); auto chan = qsim::Cirq::ResetChannel::Create(time, num_qubits - q - 1); @@ -698,10 +687,9 @@ inline Status AmplitudeDampingChannel(const Operation& op, const unsigned int time, NoisyQsimCircuit* ncircuit) { int q; - + bool unused; float gamma; Status u; - [[maybe_unused]] bool unused; unused = absl::SimpleAtoi(op.qubits(0).id(), &q); u = ParseProtoArg(op, "gamma", {}, &gamma); @@ -719,10 +707,9 @@ inline Status PhaseDampingChannel(const Operation& op, const unsigned int time, NoisyQsimCircuit* ncircuit) { int q; - + bool unused; float gamma; Status u; - [[maybe_unused]] bool unused; unused = absl::SimpleAtoi(op.qubits(0).id(), &q); u = ParseProtoArg(op, "gamma", {}, &gamma); @@ -741,10 +728,9 @@ inline Status PhaseFlipChannel(const Operation& op, const unsigned int time, NoisyQsimCircuit* ncircuit) { int q; - + bool unused; float p; Status u; - [[maybe_unused]] bool unused; unused = absl::SimpleAtoi(op.qubits(0).id(), &q); u = ParseProtoArg(op, "p", {}, &p); @@ -762,10 +748,9 @@ inline Status BitFlipChannel(const Operation& op, const unsigned int num_qubits, const unsigned int time, NoisyQsimCircuit* ncircuit) { int q; - + bool unused; float p; Status u; - [[maybe_unused]] bool unused; unused = absl::SimpleAtoi(op.qubits(0).id(), &q); u = ParseProtoArg(op, "p", {}, &p); @@ -795,7 +780,7 @@ tensorflow::Status ParseAppendChannel(const Operation& op, auto build_f = chan_func_map.find(op.gate().id()); if (build_f == chan_func_map.end()) { - return Status(static_cast( + return Status(static_cast( absl::StatusCode::kInvalidArgument), absl::StrCat("Could not parse channel id: ", op.gate().id())); } @@ -866,8 +851,7 @@ tensorflow::Status QsimCircuitFromProgram( // Convert proto to qsim internal representation. circuit->num_qubits = num_qubits; int time = 0; - [[maybe_unused]] bool unused; - + bool unused; // Special case empty. if (num_qubits <= 0) { return ::tensorflow::Status(); diff --git a/tensorflow_quantum/core/src/circuit_parser_qsim_test.cc b/tensorflow_quantum/core/src/circuit_parser_qsim_test.cc index 811ecd430..e6ea68e80 100644 --- a/tensorflow_quantum/core/src/circuit_parser_qsim_test.cc +++ b/tensorflow_quantum/core/src/circuit_parser_qsim_test.cc @@ -23,7 +23,6 @@ limitations under the License. #include "../qsim/lib/circuit_noisy.h" #include "../qsim/lib/gates_cirq.h" #include "absl/container/flat_hash_map.h" -#include "absl/status/status.h" #include "absl/strings/numbers.h" #include "gtest/gtest.h" #include "tensorflow/core/lib/core/status.h" @@ -65,7 +64,7 @@ Arg MakeControlArg(const std::string& val) { } inline void AssertControlEqual(const QsimGate& a, const QsimGate& b) { - for (size_t i = 0; i < a.controlled_by.size(); i++) { + for (int i = 0; i < a.controlled_by.size(); i++) { ASSERT_EQ(a.controlled_by[i], b.controlled_by[i]); } ASSERT_EQ(a.cmask, b.cmask); @@ -90,14 +89,14 @@ inline void AssertOneQubitEqual(const QsimGate& a, const QsimGate& b) { inline void AssertChannelEqual(const QsimChannel& a, const QsimChannel& b) { ASSERT_EQ(a.size(), b.size()); - for (size_t i = 0; i < a.size(); i++) { + for (int i = 0; i < a.size(); i++) { ASSERT_EQ(a[i].kind, b[i].kind); ASSERT_EQ(a[i].unitary, b[i].unitary); ASSERT_NEAR(a[i].prob, b[i].prob, 1e-5); auto a_k_ops = a[i].ops; auto b_k_ops = b[i].ops; EXPECT_EQ(a_k_ops.size(), b_k_ops.size()); - for (size_t j = 0; j < a_k_ops.size(); j++) { + for (int j = 0; j < a_k_ops.size(); j++) { AssertOneQubitEqual(a_k_ops[j], b_k_ops[j]); } } diff --git a/tensorflow_quantum/core/src/program_resolution.cc b/tensorflow_quantum/core/src/program_resolution.cc index 86e3ab897..0fbda9368 100644 --- a/tensorflow_quantum/core/src/program_resolution.cc +++ b/tensorflow_quantum/core/src/program_resolution.cc @@ -20,7 +20,6 @@ limitations under the License. #include "absl/container/flat_hash_map.h" #include "absl/container/flat_hash_set.h" -#include "absl/status/status.h" #include "absl/strings/str_cat.h" #include "absl/strings/str_join.h" #include "absl/strings/str_split.h" @@ -67,17 +66,17 @@ Status RegisterQubits( } if (splits.size() != 2) { - return Status(static_cast( + return Status(static_cast( absl::StatusCode::kInvalidArgument), absl::StrCat("Unable to parse qubit: ", qb)); } if (!absl::SimpleAtoi(splits[0], &r)) { - return Status(static_cast( + return Status(static_cast( absl::StatusCode::kInvalidArgument), absl::StrCat("Unable to parse qubit: ", qb)); } if (!absl::SimpleAtoi(splits[1], &c)) { - return Status(static_cast( + return Status(static_cast( absl::StatusCode::kInvalidArgument), absl::StrCat("Unable to parse qubit: ", qb)); } @@ -173,7 +172,7 @@ Status ResolveQubitIds(Program* program, unsigned int* num_qubits, const auto result = id_to_index.find(pair.qubit_id()); if (result == id_to_index.end()) { return Status( - static_cast( + static_cast( absl::StatusCode::kInvalidArgument), "Found a Pauli sum operating on qubits not found in circuit."); } @@ -265,7 +264,7 @@ Status ResolveQubitIds(Program* program, unsigned int* num_qubits, visited_qubits.erase(qubit.id()); const auto result = id_to_index.find(qubit.id()); if (result == id_to_index.end()) { - return Status(static_cast( + return Status(static_cast( absl::StatusCode::kInvalidArgument), "A paired circuit contains qubits not found in " "reference circuit."); @@ -288,7 +287,7 @@ Status ResolveQubitIds(Program* program, unsigned int* num_qubits, visited_qubits.erase(id); const auto result = id_to_index.find(id); if (result == id_to_index.end()) { - return Status(static_cast( + return Status(static_cast( absl::StatusCode::kInvalidArgument), "A paired circuit contains qubits not found in " "reference circuit."); @@ -303,7 +302,7 @@ Status ResolveQubitIds(Program* program, unsigned int* num_qubits, } if (!visited_qubits.empty()) { return Status( - static_cast( + static_cast( absl::StatusCode::kInvalidArgument), "A reference circuit contains qubits not found in paired circuit."); } @@ -324,7 +323,7 @@ Status ResolveSymbols( if (iter == param_map.end()) { if (resolve_all) { return Status( - static_cast( + static_cast( absl::StatusCode::kInvalidArgument), "Could not find symbol in parameter map: " + arg.symbol()); } @@ -365,7 +364,7 @@ Status CheckMPSSupported(const Program& program) { const int total_num_qubits = qubits.size() + control_ids.size(); if (total_num_qubits > 2) { return Status( - static_cast( + static_cast( absl::StatusCode::kInvalidArgument), absl::StrCat("1D operations only support 1 and 2 qubit gates. " "Found: ", @@ -373,7 +372,7 @@ Status CheckMPSSupported(const Program& program) { } if (total_num_qubits == 2) { - size_t j = 0; + int j = 0; std::vector qids(2, -1234); for (; j < qubits.size(); j++) { (void)absl::SimpleAtoi(qubits[j].id(), &qids[j]); @@ -384,7 +383,7 @@ Status CheckMPSSupported(const Program& program) { // Are the two qubits not neighbors? if (std::abs((int)qids[0] - (int)qids[1]) > 1) { - return Status(static_cast( + return Status(static_cast( absl::StatusCode::kInvalidArgument), "A program is not in 1D topology. It contains an" " operation with qubits not neighbors each other."); diff --git a/tensorflow_quantum/core/src/program_resolution_test.cc b/tensorflow_quantum/core/src/program_resolution_test.cc index 450d5d1cf..2a4e61151 100644 --- a/tensorflow_quantum/core/src/program_resolution_test.cc +++ b/tensorflow_quantum/core/src/program_resolution_test.cc @@ -20,7 +20,6 @@ limitations under the License. #include #include "absl/container/flat_hash_map.h" -#include "absl/status/status.h" #include "gtest/gtest.h" #include "tensorflow/core/lib/core/status.h" #include "tensorflow_quantum/core/proto/program.pb.h" @@ -236,7 +235,7 @@ TEST(ProgramResolutionTest, ResolveQubitIdsInvalidControlQubit) { .mutable_arg_value() ->set_string_value("junk"); EXPECT_EQ(ResolveQubitIds(&program, &qubit_count), - tensorflow::Status(static_cast( + tensorflow::Status(static_cast( absl::StatusCode::kInvalidArgument), "Unable to parse qubit: junk")); } @@ -253,7 +252,7 @@ TEST(ProgramResolutionTest, ResolveQubitIdsInvalidQubit) { ->mutable_qubits(0) ->set_id("junk"); EXPECT_EQ(ResolveQubitIds(&program, &qubit_count), - tensorflow::Status(static_cast( + tensorflow::Status(static_cast( absl::StatusCode::kInvalidArgument), "Unable to parse qubit: junk")); } @@ -303,7 +302,7 @@ TEST(ProgramResolutionTest, ResolveQubitIdsWithInvalidPauliSum) { EXPECT_EQ(ResolveQubitIds(&program, &qubit_count, &p_sums), tensorflow::Status( - static_cast( + static_cast( absl::StatusCode::kInvalidArgument), "Found a Pauli sum operating on qubits not found in circuit.")); } @@ -377,7 +376,7 @@ TEST(ProgramResolutionTest, ResolveQubitIdsMultiProgramInvalid) { ->set_id("junk"); std::vector others = {other, other}; EXPECT_EQ(ResolveQubitIds(&program, &qubit_count, &others), - tensorflow::Status(static_cast( + tensorflow::Status(static_cast( absl::StatusCode::kInvalidArgument), "Unable to parse qubit: junk")); } @@ -398,7 +397,7 @@ TEST(ProgramResolutionTest, ResolveQubitIdsMultiProgramInvalidControl) { ->set_string_value("junk"); std::vector others = {other, other}; EXPECT_EQ(ResolveQubitIds(&program, &qubit_count, &others), - tensorflow::Status(static_cast( + tensorflow::Status(static_cast( absl::StatusCode::kInvalidArgument), "Unable to parse qubit: junk")); } @@ -419,7 +418,7 @@ TEST(ProgramResolutionTest, ResolveQubitIdsMultiProgramMismatch) { EXPECT_EQ( ResolveQubitIds(&program, &qubit_count, &others), tensorflow::Status( - static_cast( + static_cast( absl::StatusCode::kInvalidArgument), "A paired circuit contains qubits not found in reference circuit.")); } @@ -442,7 +441,7 @@ TEST(ProgramResolutionTest, ResolveQubitIdsMultiProgramMismatchControl) { EXPECT_EQ( ResolveQubitIds(&program, &qubit_count, &others), tensorflow::Status( - static_cast( + static_cast( absl::StatusCode::kInvalidArgument), "A paired circuit contains qubits not found in reference circuit.")); } @@ -463,7 +462,7 @@ TEST(ProgramResolutionTest, ResolveQubitIdsMultiProgramSmaller) { EXPECT_EQ( ResolveQubitIds(&program, &qubit_count, &others), tensorflow::Status( - static_cast( + static_cast( absl::StatusCode::kInvalidArgument), "A reference circuit contains qubits not found in paired circuit.")); } @@ -486,7 +485,7 @@ TEST(ProgramResolutionTest, ResolveQubitIdsMultiProgramSmallerControl) { EXPECT_EQ( ResolveQubitIds(&program, &qubit_count, &others), tensorflow::Status( - static_cast( + static_cast( absl::StatusCode::kInvalidArgument), "A reference circuit contains qubits not found in paired circuit.")); } @@ -547,7 +546,7 @@ TEST(ProgramResolutionTest, ResolveSymbolsStrictPartial) { const absl::flat_hash_map> param_map = { {"v1", {0, 1.0}}}; EXPECT_EQ(ResolveSymbols(param_map, &symbol_program, true), - Status(static_cast( + Status(static_cast( absl::StatusCode::kInvalidArgument), "Could not find symbol in parameter map: v2")); } @@ -587,7 +586,7 @@ TEST(ProgramResolutionTest, CheckQubitsIn1DFailedByOpWithMoreThan2Qubits) { ASSERT_TRUE(google::protobuf::TextFormat::ParseFromString( three_qubit_op_program, &program_with_3qubit_op)); EXPECT_EQ(CheckMPSSupported(program_with_3qubit_op), - Status(static_cast( + Status(static_cast( absl::StatusCode::kInvalidArgument), "1D operations only support 1 and 2 qubit gates. " "Found: 3 qubit gate.")); @@ -599,7 +598,7 @@ TEST(ProgramResolutionTest, ASSERT_TRUE(google::protobuf::TextFormat::ParseFromString( valid_program, &program_with_3qubit_op)); EXPECT_EQ(CheckMPSSupported(program_with_3qubit_op), - Status(static_cast( + Status(static_cast( absl::StatusCode::kInvalidArgument), "1D operations only support 1 and 2 qubit gates. " "Found: 3 qubit gate.")); @@ -610,7 +609,7 @@ TEST(ProgramResolutionTest, CheckQubitsIn1DFailedByNot1DTopology) { ASSERT_TRUE(google::protobuf::TextFormat::ParseFromString( resolved_qubit_program_not_1d, &program_not_1d)); EXPECT_EQ(CheckMPSSupported(program_not_1d), - Status(static_cast( + Status(static_cast( absl::StatusCode::kInvalidArgument), "A program is not in 1D topology. It contains an" " operation with qubits not neighbors each other.")); diff --git a/tensorflow_quantum/core/src/util_qsim.h b/tensorflow_quantum/core/src/util_qsim.h index adf38705e..f08715343 100644 --- a/tensorflow_quantum/core/src/util_qsim.h +++ b/tensorflow_quantum/core/src/util_qsim.h @@ -453,13 +453,13 @@ static void BalanceTrajectory(const std::vector>& num_samples, std::vector rep_limits(num_samples.size(), -1); std::vector height(num_threads, 0); - for (size_t i = 0; i < num_samples.size(); i++) { - for (size_t j = 0; j < num_samples[i].size(); j++) { + for (int i = 0; i < num_samples.size(); i++) { + for (int j = 0; j < num_samples[i].size(); j++) { rep_limits[i] = std::max(rep_limits[i], num_samples[i][j]); } } int prev_max_height = -1; - for (size_t j = 0; j < num_samples.size(); j++) { + for (int j = 0; j < num_samples.size(); j++) { int run_ceiling = ((rep_limits[j] + num_threads - 1) / num_threads); int num_lo = num_threads * run_ceiling - rep_limits[j]; int num_hi = num_threads - num_lo; @@ -498,7 +498,7 @@ static void BalanceTrajectory(const int& num_samples, const int& num_threads, std::vector height(num_threads, 0); int prev_max_height = -1; - for (size_t j = 0; j < (*thread_offsets)[0].size(); j++) { + for (int j = 0; j < (*thread_offsets)[0].size(); j++) { int run_ceiling = ((num_samples + num_threads - 1) / num_threads); int num_lo = num_threads * run_ceiling - num_samples; int num_hi = num_threads - num_lo; diff --git a/tensorflow_quantum/core/src/util_qsim_test.cc b/tensorflow_quantum/core/src/util_qsim_test.cc index 400c16d76..b4f630f3c 100644 --- a/tensorflow_quantum/core/src/util_qsim_test.cc +++ b/tensorflow_quantum/core/src/util_qsim_test.cc @@ -646,13 +646,13 @@ static void AssertWellBalanced(const std::vector>& n_reps, const int& num_threads, const std::vector>& offsets) { auto max_work = std::vector(n_reps.size(), -1); - for (size_t i = 0; i < n_reps.size(); i++) { - for (size_t j = 0; j < n_reps[0].size(); j++) { + for (int i = 0; i < n_reps.size(); i++) { + for (int j = 0; j < n_reps[0].size(); j++) { max_work[i] = std::max(max_work[i], n_reps[i][j]); } } - for (size_t i = 0; i < n_reps.size(); i++) { + for (int i = 0; i < n_reps.size(); i++) { int sum = 0; int prev_local_work = 0; for (int k = 0; k < num_threads; k++) { diff --git a/tensorflow_quantum/datasets/spin_system_test.py b/tensorflow_quantum/datasets/spin_system_test.py index 200120a65..917fd0f73 100644 --- a/tensorflow_quantum/datasets/spin_system_test.py +++ b/tensorflow_quantum/datasets/spin_system_test.py @@ -28,8 +28,7 @@ from tensorflow_quantum.datasets.spin_system import SpinSystemInfo -# TODO(#748): Inherit this class from tf.test.TestCase after fixing the issue. -class TFIChainTest: +class TFIChainTest(tf.test.TestCase): """Testing tfi_chain.""" # pylint: disable=C0103 From 99913bdd11a44304eab8f1c0fb63f58b9ef40f6f Mon Sep 17 00:00:00 2001 From: Michael Broughton Date: Mon, 12 Jun 2023 13:57:39 -0700 Subject: [PATCH 02/50] Revert "remove release notes md" This reverts commit 25313f41e8350ef90153bef0f03c9d576d34b1dd. --- tensorflow_quantum/release.md | 37 +++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 tensorflow_quantum/release.md diff --git a/tensorflow_quantum/release.md b/tensorflow_quantum/release.md new file mode 100644 index 000000000..46d844e7a --- /dev/null +++ b/tensorflow_quantum/release.md @@ -0,0 +1,37 @@ +# Release 0.8.0 +# Breaking Changes +- Build, compilation, and packaging: + - The TensorFlow dependency has been upgraded from 2.7.0 to 2.11.0: + - TensorFlow Quantum is now compiled with `_GLIBCXX_USE_CXX11_ABI=1`. Downstream projects that encounter `std::__cxx11` or `[abi:cxx11]` linker errors will need to adopt this compiler option. See [the GNU C++ Library docs on Dual ABI](https://gcc.gnu.org/onlinedocs/libstdc++/manual/using_dual_abi.html). + - TensorFlow Quantum is now compiled with `-std=c++17`, see [install.md](/docs/install.md) for build instructions. +- Cirq dependency has been upgraded from `0.13.1` to `~=1.0` + - `cirq_google.XMON` was deprecated : https://github.com/quantumlib/Cirq/issues/4856 + - `QuantumEngineSampler` was deprecated : https://github.com/quantumlib/Cirq/issues/5371 + - So, we need [ProcessorSampler() for testing](https://github.com/quantumlib/Cirq/blob/master/cirq-google/cirq_google/engine/processor_sampler_test.py) + - `cirq.CNOT` interface was changed. + - https://quantumai.google/reference/python/cirq/CNOT + - No more control, target argument. + - `cirq.SingleQubitGate` was deprecated. + - For testing, use `cirq.testing.SingleQubitGate` : https://github.com/quantumlib/Cirq/pull/5272/files + - For implementation, use `cirq.Gate`. + +# Major Features and Improvements +- Significant performance improvements by introducing cuQuantum support for circuit execution on Nvidia GPUs: + - TensorFlow Quantum Keras layers can now be executed on GPU by setting the optional arguement `use_cuquantum=True` at layer instantiation. Examples: + - `tfq.layers.Expectation(use_cuquantum=True)` + - `tfq.layers.SampledExpectation(use_cuquantum=True)` (note that cuQuantum runtime is unsupported for any noisy circuit operations + - `tfq.layers.State(use_cuquantum=True)` + - `tfq.layers.Sample(use_cuquantum=True)` + - `tfq.layers.PQC(model_circuit, operators, use_cuquantum=True)` + - `tfq.layers.ControlledPQC(model_circuit, operators, use_cuquantum=True)` + - Important notes: + - CuQuantum execution is currently only supported for source distributions meaning that the user must build TensorFlow Quantum & `tensorFlow-cpu` from source following the instructions in [install.md](/docs/install.md#build-from-source). + - Ensure that the first entry is "N" in the `configure.sh` script at [this step](/docs/install.md#6-build-the-tensorflow-quantum-pip-package) of building. This ensures that you build upon `tensorflow-cpu` as `tensorflow-gpu` is unnecessary for CuQuantum support in TensorFlow Quantum. + - The cuQuantum SDK must be installed locally. See [installation instructions](https://docs.nvidia.com/cuda/cuquantum/custatevec/getting_started.html) for details. As part of the installation process, ensure that the `CUQUANTUM_ROOT` environment variable is set (referred to in the installation instructions). If not set, bazel will attempt to automatically locate the folder containing the cuQuantum installation upon running `configure.sh` at [this step](/docs/install.md#6-build-the-tensorflow-quantum-pip-package). + - Tested on Titan, Ampere and Volta Nvidia GPU architectures. Note that Pascal GPU architectures are not supported, see documentation to [check whether your GPU is compatible with cuQuantum](https://docs.nvidia.com/cuda/cuquantum/getting_started.html#custatevec) + - Quantum concurrency (global context option) should be turned off when `use_cuquantum=True`. This can be done by running: `tfq.python.quantum_context.set_quantum_concurrent_op_mode(False)` + + + +# Thanks to our Contributors +This release contains contributions from many people at Google, Nvidia, as well as: From a413194241cfd00a6cf2965482cf00c1f16dd8ca Mon Sep 17 00:00:00 2001 From: Michael Broughton Date: Mon, 12 Jun 2023 13:57:44 -0700 Subject: [PATCH 03/50] Revert "Merge remote-tracking branch 'forkB/fix_warnings'" This reverts commit d78931498fd4ee6d06ffba9271f2d948827c58fb, reversing changes made to fe3a96e24a3001b76547a36bbe3301f8e5a8a255. --- .bazelversion | 2 +- .github/workflows/ci.yaml | 12 +- .github/workflows/cirq_compatibility.yaml | 3 +- WORKSPACE | 32 +-- .../scripts/benchmark_clifford_circuit.py | 2 +- benchmarks/scripts/benchmark_op_gradients.py | 2 +- .../scripts/benchmark_random_circuit.py | 2 +- benchmarks/scripts/benchmark_util.py | 2 +- benchmarks/scripts/benchmark_util_test.py | 2 +- benchmarks/scripts/flags.py | 2 +- benchmarks/scripts/flags_test.py | 2 +- benchmarks/scripts/models/__init__.py | 2 +- .../scripts/models/random_clifford_circuit.py | 2 +- .../models/random_clifford_circuit_test.py | 2 +- configure.sh | 20 +- docs/_book.yaml | 2 +- docs/_index.yaml | 2 +- docs/install.md | 12 +- release/BUILD | 7 +- release/build_pip_package.sh | 2 +- release/setup.py | 2 +- scripts/benchmark_all.sh | 2 +- scripts/build_docs.py | 2 +- scripts/build_pip_package_test.sh | 2 +- scripts/ci_install.sh | 6 +- scripts/ci_validate_tutorials.sh | 2 +- scripts/format_all.sh | 4 +- scripts/format_check.sh | 4 +- scripts/format_ipynb.py | 2 +- scripts/import_test.py | 2 +- scripts/lint_all.sh | 2 +- scripts/msan_test.sh | 2 +- scripts/run_example.sh | 2 +- scripts/test_all.sh | 2 +- scripts/test_benchmarks.sh | 2 +- scripts/test_tutorials.py | 2 +- tensorflow_quantum/__init__.py | 2 +- tensorflow_quantum/core/__init__.py | 2 +- tensorflow_quantum/core/ops/BUILD | 216 +---------------- tensorflow_quantum/core/ops/__init__.py | 2 +- tensorflow_quantum/core/ops/batch_util.py | 2 +- .../core/ops/batch_util_test.py | 3 +- .../core/ops/circuit_execution_ops.py | 2 +- .../core/ops/circuit_execution_ops_test.py | 3 +- tensorflow_quantum/core/ops/cirq_ops.py | 2 +- tensorflow_quantum/core/ops/cirq_ops_test.py | 3 +- tensorflow_quantum/core/ops/load_module.py | 2 +- .../core/ops/math_ops/__init__.py | 2 +- .../core/ops/math_ops/fidelity_op.py | 2 +- .../core/ops/math_ops/fidelity_op_test.py | 3 +- .../ops/math_ops/inner_product_grad_test.py | 3 +- .../core/ops/math_ops/inner_product_op.py | 2 +- .../ops/math_ops/inner_product_op_test.py | 3 +- .../core/ops/math_ops/simulate_mps.py | 2 +- .../core/ops/math_ops/simulate_mps_test.py | 3 +- tensorflow_quantum/core/ops/noise/__init__.py | 2 +- .../core/ops/noise/noisy_expectation_op.py | 2 +- .../ops/noise/noisy_expectation_op_test.py | 3 +- .../ops/noise/noisy_sampled_expectation_op.py | 2 +- .../noisy_sampled_expectation_op_test.py | 3 +- .../core/ops/noise/noisy_samples_op.py | 2 +- .../core/ops/noise/noisy_samples_op_test.py | 3 +- .../core/ops/tfq_adj_grad_op.py | 2 +- .../core/ops/tfq_adj_grad_op_test.py | 3 +- .../core/ops/tfq_ps_util_ops.py | 2 +- .../core/ops/tfq_ps_util_ops_test.py | 3 +- .../tfq_simulate_expectation_op_cuda.cu.cc | 206 ---------------- ...fq_simulate_expectation_op_cuquantum.cu.cc | 220 ------------------ .../core/ops/tfq_simulate_ops.py | 2 +- .../core/ops/tfq_simulate_ops_cuda.py | 44 ---- .../core/ops/tfq_simulate_ops_cuquantum.py | 44 ---- .../core/ops/tfq_simulate_ops_gpu_test.py | 139 ----------- .../core/ops/tfq_simulate_ops_test.py | 3 +- tensorflow_quantum/core/ops/tfq_unitary_op.py | 2 +- .../core/ops/tfq_unitary_op_test.py | 3 +- .../core/ops/tfq_utility_ops.py | 2 +- .../core/ops/tfq_utility_ops_test.py | 3 +- tensorflow_quantum/core/proto/__init__.py | 2 +- tensorflow_quantum/core/serialize/__init__.py | 2 +- .../core/serialize/op_deserializer_test.py | 1 - .../core/serialize/op_serializer_test.py | 1 - .../serialize/serializable_gate_set_test.py | 1 - .../core/serialize/serializer.py | 2 +- .../core/serialize/serializer_test.py | 5 +- tensorflow_quantum/datasets/__init__.py | 2 +- tensorflow_quantum/datasets/cluster_state.py | 2 +- .../datasets/cluster_state_test.py | 3 +- tensorflow_quantum/datasets/spin_system.py | 2 +- .../datasets/spin_system_test.py | 3 +- tensorflow_quantum/python/__init__.py | 2 +- .../python/differentiators/__init__.py | 2 +- .../python/differentiators/adjoint.py | 2 +- .../python/differentiators/adjoint_test.py | 3 +- .../python/differentiators/differentiator.py | 2 +- .../differentiators/differentiator_test.py | 3 +- .../python/differentiators/gradient_test.py | 3 +- .../differentiators/linear_combination.py | 2 +- .../linear_combination_test.py | 3 +- .../python/differentiators/parameter_shift.py | 2 +- .../differentiators/parameter_shift_test.py | 3 +- .../differentiators/parameter_shift_util.py | 2 +- .../parameter_shift_util_test.py | 3 +- tensorflow_quantum/python/layers/__init__.py | 2 +- .../layers/circuit_construction/__init__.py | 2 +- .../layers/circuit_construction/elementary.py | 2 +- .../circuit_construction/elementary_test.py | 3 +- .../layers/circuit_executors/__init__.py | 2 +- .../layers/circuit_executors/expectation.py | 2 +- .../circuit_executors/expectation_test.py | 3 +- .../layers/circuit_executors/input_checks.py | 2 +- .../circuit_executors/input_checks_test.py | 3 +- .../python/layers/circuit_executors/sample.py | 2 +- .../layers/circuit_executors/sample_test.py | 3 +- .../circuit_executors/sampled_expectation.py | 2 +- .../sampled_expectation_test.py | 3 +- .../python/layers/circuit_executors/state.py | 2 +- .../layers/circuit_executors/state_test.py | 3 +- .../layers/circuit_executors/unitary.py | 2 +- .../layers/circuit_executors/unitary_test.py | 3 +- .../python/layers/high_level/__init__.py | 2 +- .../layers/high_level/controlled_pqc.py | 2 +- .../layers/high_level/controlled_pqc_test.py | 3 +- .../layers/high_level/noisy_controlled_pqc.py | 2 +- .../high_level/noisy_controlled_pqc_test.py | 3 +- .../python/layers/high_level/noisy_pqc.py | 2 +- .../layers/high_level/noisy_pqc_test.py | 3 +- .../python/layers/high_level/pqc.py | 2 +- .../python/layers/high_level/pqc_test.py | 3 +- .../python/optimizers/__init__.py | 2 +- .../python/optimizers/rotosolve_minimizer.py | 2 +- .../optimizers/rotosolve_minimizer_test.py | 3 +- .../python/optimizers/spsa_minimizer.py | 2 +- .../python/optimizers/spsa_minimizer_test.py | 3 +- tensorflow_quantum/python/quantum_context.py | 2 +- .../python/quantum_context_test.py | 3 +- tensorflow_quantum/python/util.py | 2 +- tensorflow_quantum/python/util_test.py | 3 +- 137 files changed, 155 insertions(+), 1096 deletions(-) delete mode 100644 tensorflow_quantum/core/ops/tfq_simulate_expectation_op_cuda.cu.cc delete mode 100644 tensorflow_quantum/core/ops/tfq_simulate_expectation_op_cuquantum.cu.cc delete mode 100644 tensorflow_quantum/core/ops/tfq_simulate_ops_cuda.py delete mode 100644 tensorflow_quantum/core/ops/tfq_simulate_ops_cuquantum.py delete mode 100644 tensorflow_quantum/core/ops/tfq_simulate_ops_gpu_test.py diff --git a/.bazelversion b/.bazelversion index 03f488b07..831446cbd 100644 --- a/.bazelversion +++ b/.bazelversion @@ -1 +1 @@ -5.3.0 +5.1.0 diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 387b7d6a4..7e6f1a21a 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -5,7 +5,7 @@ on: [pull_request] jobs: lint: name: Lint check - runs-on: ubuntu-20.04 + runs-on: ubuntu-18.04 steps: - uses: actions/checkout@v1 - uses: actions/setup-python@v1 @@ -19,7 +19,7 @@ jobs: format: name: Formatting check - runs-on: ubuntu-20.04 + runs-on: ubuntu-18.04 steps: - uses: actions/checkout@v1 @@ -34,7 +34,7 @@ jobs: wheel-build: name: Wheel test - runs-on: ubuntu-20.04 + runs-on: ubuntu-18.04 steps: - uses: actions/checkout@v1 @@ -53,7 +53,7 @@ jobs: bazel-tests: name: Library tests - runs-on: ubuntu-20.04 + runs-on: ubuntu-18.04 needs: [lint, format] steps: @@ -71,7 +71,7 @@ jobs: leak-tests: name: Memory Leak tests - runs-on: ubuntu-20.04 + runs-on: ubuntu-18.04 needs: [lint, format] steps: @@ -89,7 +89,7 @@ jobs: tutorials-test: name: Tutorial tests - runs-on: ubuntu-20.04 + runs-on: ubuntu-18.04 needs: [lint, format, wheel-build] steps: diff --git a/.github/workflows/cirq_compatibility.yaml b/.github/workflows/cirq_compatibility.yaml index ee8e26f94..f5e5b9629 100644 --- a/.github/workflows/cirq_compatibility.yaml +++ b/.github/workflows/cirq_compatibility.yaml @@ -1,4 +1,3 @@ - name: Cirq Compatibility on: @@ -8,7 +7,7 @@ on: jobs: consistency: name: Nightly Compatibility - runs-on: ubuntu-20.04 + runs-on: ubuntu-16.04 steps: - uses: actions/checkout@v1 - uses: actions/setup-python@v1 diff --git a/WORKSPACE b/WORKSPACE index 6a29d598b..b47e25d2f 100644 --- a/WORKSPACE +++ b/WORKSPACE @@ -24,19 +24,11 @@ cc_library( ], ) -# http_archive( -# name = "qsim", -# sha256 = "b9c1eba09a885a938b5e73dfc2e02f5231cf3b01d899415caa24769346a731d5", -# strip_prefix = "qsim-0.13.3", -# urls = ["https://github.com/quantumlib/qsim/archive/refs/tags/v0.13.3.zip"], -# ) - -# TODO: After merging this patch later into qsim mainstream, remove this and uncomment the above. http_archive( name = "qsim", - sha256 = "", - strip_prefix = "qsim-0.15.0-dev20230327_v3", - urls = ["https://github.com/jaeyoo/qsim/archive/refs/tags/v0.15.0+dev20230327_v3.tar.gz"], + sha256 = "b9c1eba09a885a938b5e73dfc2e02f5231cf3b01d899415caa24769346a731d5", + strip_prefix = "qsim-0.13.3", + urls = ["https://github.com/quantumlib/qsim/archive/refs/tags/v0.13.3.zip"], ) http_archive( @@ -81,21 +73,3 @@ bind( actual = "@six_archive//:six", ) -new_local_repository( - name = "cuquantum_libs", - path = "/usr/local/google/home/jaeyoo/workspace/cuquantum-linux-x86_64-22.11.0.13-archive", - build_file_content = """ -cc_library( - name = "custatevec_headers", - srcs = ["include/custatevec.h"], - visibility = ["//visibility:public"], -) - -cc_library( - name = "custatevec", - srcs = ["lib/libcustatevec.so"], - visibility = ["//visibility:public"], -) -""", -) - diff --git a/benchmarks/scripts/benchmark_clifford_circuit.py b/benchmarks/scripts/benchmark_clifford_circuit.py index c71751dbc..643eff790 100644 --- a/benchmarks/scripts/benchmark_clifford_circuit.py +++ b/benchmarks/scripts/benchmark_clifford_circuit.py @@ -11,7 +11,7 @@ # 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. -# ============================================================================= +# ============================================================================== """Benchmark simulators against classically simulatable circuits.""" import os import time diff --git a/benchmarks/scripts/benchmark_op_gradients.py b/benchmarks/scripts/benchmark_op_gradients.py index 687e1b1f6..89b04cfd1 100644 --- a/benchmarks/scripts/benchmark_op_gradients.py +++ b/benchmarks/scripts/benchmark_op_gradients.py @@ -11,7 +11,7 @@ # 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. -# ============================================================================= +# ============================================================================== """Benchmark differentiator methods.""" import os import time diff --git a/benchmarks/scripts/benchmark_random_circuit.py b/benchmarks/scripts/benchmark_random_circuit.py index b265237d7..51d4ccfbf 100644 --- a/benchmarks/scripts/benchmark_random_circuit.py +++ b/benchmarks/scripts/benchmark_random_circuit.py @@ -11,7 +11,7 @@ # 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. -# ============================================================================= +# ============================================================================== """Benchmark simulators against classically intractable 'supremacy' circuits.""" import os import time diff --git a/benchmarks/scripts/benchmark_util.py b/benchmarks/scripts/benchmark_util.py index 87e903ecb..5b4bea2e5 100644 --- a/benchmarks/scripts/benchmark_util.py +++ b/benchmarks/scripts/benchmark_util.py @@ -11,7 +11,7 @@ # 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. -# ============================================================================= +# ============================================================================== """Utility functions for benchmark tools.""" import tensorflow as tf import test_log_pb2 diff --git a/benchmarks/scripts/benchmark_util_test.py b/benchmarks/scripts/benchmark_util_test.py index 951478a19..bece69897 100644 --- a/benchmarks/scripts/benchmark_util_test.py +++ b/benchmarks/scripts/benchmark_util_test.py @@ -11,7 +11,7 @@ # 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. -# ============================================================================= +# ============================================================================== """Tests for utilities related to reading/running benchmarks.""" import os import tempfile diff --git a/benchmarks/scripts/flags.py b/benchmarks/scripts/flags.py index ee173ef28..eaf7e78e2 100644 --- a/benchmarks/scripts/flags.py +++ b/benchmarks/scripts/flags.py @@ -11,7 +11,7 @@ # 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. -# ============================================================================= +# ============================================================================== """Command line flags shared between benchmarks.""" from collections import namedtuple from absl import flags as absl_flags diff --git a/benchmarks/scripts/flags_test.py b/benchmarks/scripts/flags_test.py index c51a2f814..6383809c6 100644 --- a/benchmarks/scripts/flags_test.py +++ b/benchmarks/scripts/flags_test.py @@ -11,7 +11,7 @@ # 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. -# ============================================================================= +# ============================================================================== """Tests for benchmark command line flags.""" import tensorflow as tf diff --git a/benchmarks/scripts/models/__init__.py b/benchmarks/scripts/models/__init__.py index 9d181170d..bf5b48863 100644 --- a/benchmarks/scripts/models/__init__.py +++ b/benchmarks/scripts/models/__init__.py @@ -11,4 +11,4 @@ # 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. -# ============================================================================= \ No newline at end of file +# ============================================================================== \ No newline at end of file diff --git a/benchmarks/scripts/models/random_clifford_circuit.py b/benchmarks/scripts/models/random_clifford_circuit.py index 09012c14e..a08a667b5 100644 --- a/benchmarks/scripts/models/random_clifford_circuit.py +++ b/benchmarks/scripts/models/random_clifford_circuit.py @@ -11,7 +11,7 @@ # 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. -# ============================================================================= +# ============================================================================== from typing import Iterable diff --git a/benchmarks/scripts/models/random_clifford_circuit_test.py b/benchmarks/scripts/models/random_clifford_circuit_test.py index bee8f5464..c6d968ea0 100644 --- a/benchmarks/scripts/models/random_clifford_circuit_test.py +++ b/benchmarks/scripts/models/random_clifford_circuit_test.py @@ -11,7 +11,7 @@ # 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. -# ============================================================================= +# ============================================================================== from absl.testing import parameterized import cirq diff --git a/configure.sh b/configure.sh index 0ca4a0ae4..5efd4212a 100755 --- a/configure.sh +++ b/configure.sh @@ -12,7 +12,7 @@ # 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. -# ============================================================================= +# ============================================================================== PLATFORM="$(uname -s | tr 'A-Z' 'a-z')" function write_to_bazelrc() { @@ -62,11 +62,11 @@ while [[ "$TF_NEED_CUDA" == "" ]]; do done while [[ "$TF_CUDA_VERSION" == "" ]]; do - read -p "Are you building against TensorFlow 2.11(including RCs) or newer?[Y/n] " INPUT + read -p "Are you building against TensorFlow 2.1(including RCs) or newer?[Y/n] " INPUT case $INPUT in - [Yy]* ) echo "Build against TensorFlow 2.11 or newer."; TF_CUDA_VERSION=11;; - [Nn]* ) echo "Build against TensorFlow <2.11."; TF_CUDA_VERSION=10.0;; - "" ) echo "Build against TensorFlow 2.11 or newer."; TF_CUDA_VERSION=11;; + [Yy]* ) echo "Build against TensorFlow 2.1 or newer."; TF_CUDA_VERSION=10.1;; + [Nn]* ) echo "Build against TensorFlow <2.1."; TF_CUDA_VERSION=10.0;; + "" ) echo "Build against TensorFlow 2.1 or newer."; TF_CUDA_VERSION=10.1;; * ) echo "Invalid selection: " $INPUT;; esac done @@ -94,6 +94,10 @@ fi TF_CFLAGS=( $(python -c 'import tensorflow as tf; print(" ".join(tf.sysconfig.get_compile_flags()))') ) TF_LFLAGS="$(python -c 'import tensorflow as tf; print(" ".join(tf.sysconfig.get_link_flags()))')" +write_to_bazelrc "build:cuda --define=using_cuda=true --define=using_cuda_nvcc=true" +if [[ "$PIP_MANYLINUX2010" == "0" ]]; then + write_to_bazelrc "build:cuda --crosstool_top=@local_config_cuda//crosstool:toolchain" +fi write_to_bazelrc "build --experimental_repo_remote_exec" write_to_bazelrc "build --spawn_strategy=standalone" @@ -138,12 +142,8 @@ fi # TODO(yifeif): do not hardcode path if [[ "$TF_NEED_CUDA" == "1" ]]; then - write_to_bazelrc "build:cuda --define=using_cuda=true --define=using_cuda_nvcc=true" - write_to_bazelrc "build:cuda --@local_config_cuda//:enable_cuda" - write_to_bazelrc "build:cuda --crosstool_top=@local_config_cuda//crosstool:toolchain" - write_action_env_to_bazelrc "TF_CUDA_VERSION" ${TF_CUDA_VERSION} - write_action_env_to_bazelrc "TF_CUDNN_VERSION" "8" + write_action_env_to_bazelrc "TF_CUDNN_VERSION" "7" if is_windows; then write_action_env_to_bazelrc "CUDNN_INSTALL_PATH" "C:/Program Files/NVIDIA GPU Computing Toolkit/CUDA/v${TF_CUDA_VERSION}" write_action_env_to_bazelrc "CUDA_TOOLKIT_PATH" "C:/Program Files/NVIDIA GPU Computing Toolkit/CUDA/v${TF_CUDA_VERSION}" diff --git a/docs/_book.yaml b/docs/_book.yaml index 967d8ee7f..47daeba1b 100644 --- a/docs/_book.yaml +++ b/docs/_book.yaml @@ -11,7 +11,7 @@ # 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. -# ============================================================================= +# ============================================================================== upper_tabs: # Tabs left of dropdown menu - include: /_upper_tabs_left.yaml diff --git a/docs/_index.yaml b/docs/_index.yaml index fb1fc5876..e8de0371a 100644 --- a/docs/_index.yaml +++ b/docs/_index.yaml @@ -11,7 +11,7 @@ # 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. -# ============================================================================= +# ============================================================================== book_path: /quantum/_book.yaml project_path: /quantum/_project.yaml description: > diff --git a/docs/install.md b/docs/install.md index 3de77ecf9..5e64d0616 100644 --- a/docs/install.md +++ b/docs/install.md @@ -17,7 +17,7 @@ TensorFlow Quantum is supported on Python 3.7, 3.8, and 3.9 and depends directly ### Requirements * pip 19.0 or later (requires `manylinux2010` support) -* [TensorFlow == 2.11.0](https://www.tensorflow.org/install/pip) +* [TensorFlow == 2.7.0](https://www.tensorflow.org/install/pip) See the [TensorFlow install guide](https://www.tensorflow.org/install/pip) to set up your Python development environment and an (optional) virtual environment. @@ -27,7 +27,7 @@ Upgrade `pip` and install TensorFlow
   pip3 install --upgrade pip
-  pip3 install tensorflow==2.11.0
+  pip3 install tensorflow==2.7.0
 
@@ -84,7 +84,7 @@ As noted in the TensorFlow guide, the Bazel build system will be required. -Our latest source builds use TensorFlow 2.11.0. To ensure compatibility we use `bazel` version 5.3.0. To remove any existing version of Bazel: +Our latest source builds use TensorFlow 2.11.0. To ensure compatibility we use `bazel` version 5.1.0. To remove any existing version of Bazel:
@@ -92,13 +92,13 @@ Our latest source builds use TensorFlow 2.11.0. To ensure compatibility we use `
 
-Download and install `bazel` version 5.3.0: +Download and install `bazel` version 5.1.0:
-  wget https://github.com/bazelbuild/bazel/releases/download/5.3.0/bazel_5.3.0-linux-x86_64.deb
+  wget https://github.com/bazelbuild/bazel/releases/download/5.1.0/bazel_5.1.0-linux-x86_64.deb
 
-  sudo dpkg -i bazel_5.3.0-linux-x86_64.deb
+  sudo dpkg -i bazel_5.1.0-linux-x86_64.deb
 
diff --git a/release/BUILD b/release/BUILD index b588a6c5a..7212cb1d3 100644 --- a/release/BUILD +++ b/release/BUILD @@ -1,5 +1,3 @@ -load("@local_config_cuda//cuda:build_defs.bzl", "if_cuda_is_configured") - licenses(["notice"]) sh_binary( @@ -68,8 +66,5 @@ sh_binary( "//tensorflow_quantum/python:util", "//tensorflow_quantum/python/optimizers:rotosolve_minimizer", "//tensorflow_quantum/python/optimizers:spsa_minimizer", - ] + if_cuda_is_configured([ - "//tensorflow_quantum/core/ops:tfq_simulate_ops_cuda_py", - "//tensorflow_quantum/core/ops:tfq_simulate_ops_cuquantum_py", - ]), + ], ) diff --git a/release/build_pip_package.sh b/release/build_pip_package.sh index 1c423c656..8bed5b909 100755 --- a/release/build_pip_package.sh +++ b/release/build_pip_package.sh @@ -12,7 +12,7 @@ # 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. -# ============================================================================= +# ============================================================================== set -e set -x diff --git a/release/setup.py b/release/setup.py index 7b6037023..b3ff0ded7 100644 --- a/release/setup.py +++ b/release/setup.py @@ -11,7 +11,7 @@ # 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. -# ============================================================================= +# ============================================================================== """TensorFlow Quantum adds qauntum computing primitives to TensorFlow. TensorFlow Quantum is an open source library for high performance batch diff --git a/scripts/benchmark_all.sh b/scripts/benchmark_all.sh index 648d9ebad..cd50209c2 100644 --- a/scripts/benchmark_all.sh +++ b/scripts/benchmark_all.sh @@ -12,7 +12,7 @@ # 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. -# ============================================================================= +# ============================================================================== echo "Testing benchmarks."; 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/...)) exit_code=$? diff --git a/scripts/build_docs.py b/scripts/build_docs.py index 3ad066491..dc47df224 100644 --- a/scripts/build_docs.py +++ b/scripts/build_docs.py @@ -11,7 +11,7 @@ # 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. -# ============================================================================= +# ============================================================================== """Tool to generate external api_docs for tfq.""" from __future__ import absolute_import diff --git a/scripts/build_pip_package_test.sh b/scripts/build_pip_package_test.sh index 144a42cfb..644338b6a 100755 --- a/scripts/build_pip_package_test.sh +++ b/scripts/build_pip_package_test.sh @@ -12,7 +12,7 @@ # 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. -# ============================================================================= +# ============================================================================== pip install -r requirements.txt diff --git a/scripts/ci_install.sh b/scripts/ci_install.sh index 860c02ecc..a0ed81c8c 100755 --- a/scripts/ci_install.sh +++ b/scripts/ci_install.sh @@ -12,8 +12,8 @@ # 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. -# ============================================================================= -wget https://github.com/bazelbuild/bazel/releases/download/5.3.0/bazel_5.3.0-linux-x86_64.deb -sudo dpkg -i bazel_5.3.0-linux-x86_64.deb +# ============================================================================== +wget https://github.com/bazelbuild/bazel/releases/download/5.1.0/bazel_5.1.0-linux-x86_64.deb +sudo dpkg -i bazel_5.1.0-linux-x86_64.deb pip install --upgrade pip setuptools wheel pip install -r requirements.txt \ No newline at end of file diff --git a/scripts/ci_validate_tutorials.sh b/scripts/ci_validate_tutorials.sh index d64361464..e58355faf 100755 --- a/scripts/ci_validate_tutorials.sh +++ b/scripts/ci_validate_tutorials.sh @@ -12,7 +12,7 @@ # 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. -# ============================================================================= +# ============================================================================== # Run the tutorials using the installed pip package pip install jupyter nbclient==0.6.5 jupyter-client==6.1.12 ipython==7.22.0 diff --git a/scripts/format_all.sh b/scripts/format_all.sh index 2a57c0747..0e374a3cc 100755 --- a/scripts/format_all.sh +++ b/scripts/format_all.sh @@ -12,13 +12,13 @@ # 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. -# ============================================================================= +# ============================================================================== echo "Doing python language formatting..." python3 -m yapf --style=google --in-place --recursive ./benchmarks python3 -m yapf --style=google --in-place --recursive ./tensorflow_quantum echo -e "Done! \nDoing notebook formatting..." python3 ./scripts/format_ipynb.py echo -e "Done! \nDoing C++ formatting..." -find tensorflow_quantum/ -iname *.h -o -iname *.cc | xargs clang-format-6.0 -i -style=google +find tensorflow_quantum/ -iname *.h -o -iname *.cc | xargs clang-format -i -style=google echo "Done!" exit 0; diff --git a/scripts/format_check.sh b/scripts/format_check.sh index fb5b21ca1..1d91427e0 100755 --- a/scripts/format_check.sh +++ b/scripts/format_check.sh @@ -12,7 +12,7 @@ # 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. -# ============================================================================= +# ============================================================================== echo "Checking python formatting..."; ################################################################################ @@ -92,7 +92,7 @@ else fi echo "Checking C++ formatting..."; -formatting_outputs=$(find tensorflow_quantum/ -iname *.h -o -iname *.cc | xargs clang-format-6.0 -style=google -output-replacements-xml); +formatting_outputs=$(find tensorflow_quantum/ -iname *.h -o -iname *.cc | xargs clang-format -style=google -output-replacements-xml); CFORMATCHECK=0 while read -r formatting_outputs; do if [ "$formatting_outputs" != "" ] && [ "$formatting_outputs" != "" ] && [ "$formatting_outputs" != "" ] && [ "$formatting_outputs" != " " ]; then diff --git a/scripts/format_ipynb.py b/scripts/format_ipynb.py index 10d2e447f..fac7a8bf1 100644 --- a/scripts/format_ipynb.py +++ b/scripts/format_ipynb.py @@ -11,7 +11,7 @@ # 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. -# ============================================================================= +# ============================================================================== """Format notebook code cells using yapf google style.""" import glob import nbformat diff --git a/scripts/import_test.py b/scripts/import_test.py index ce2c87307..83ec24d2e 100644 --- a/scripts/import_test.py +++ b/scripts/import_test.py @@ -11,7 +11,7 @@ # 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. -# ============================================================================= +# ============================================================================== """Tests to check if importing `tfq` APIs is successful or not.""" import tensorflow_quantum as tfq diff --git a/scripts/lint_all.sh b/scripts/lint_all.sh index 755906981..fb7e1c9a5 100755 --- a/scripts/lint_all.sh +++ b/scripts/lint_all.sh @@ -12,7 +12,7 @@ # 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. -# ============================================================================= +# ============================================================================== echo "Checking for lint in python code..."; linting_outputs=$(pylint --rcfile .pylintrc ./tensorflow_quantum ./examples); exit_code=$? diff --git a/scripts/msan_test.sh b/scripts/msan_test.sh index 398332315..d47e8ccfe 100755 --- a/scripts/msan_test.sh +++ b/scripts/msan_test.sh @@ -12,7 +12,7 @@ # 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. -# ============================================================================= +# ============================================================================== echo "Testing All Bazel cc_tests with msan."; test_outputs=$(bazel test -c opt --cxxopt="-D_GLIBCXX_USE_CXX11_ABI=1" \ --cxxopt="-msse2" --cxxopt="-msse3" --cxxopt="-msse4" \ diff --git a/scripts/run_example.sh b/scripts/run_example.sh index 1fbdd62d7..bb86edc22 100755 --- a/scripts/run_example.sh +++ b/scripts/run_example.sh @@ -12,7 +12,7 @@ # 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. -# ============================================================================= +# ============================================================================== cd .. cp quantum/scripts/import_test.py import_test.py python import_test.py \ No newline at end of file diff --git a/scripts/test_all.sh b/scripts/test_all.sh index 2795e0429..7a9fc7824 100755 --- a/scripts/test_all.sh +++ b/scripts/test_all.sh @@ -12,7 +12,7 @@ # 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. -# ============================================================================= +# ============================================================================== echo "Testing All Bazel py_test and cc_tests."; test_outputs=$(bazel test -c opt --experimental_repo_remote_exec --cxxopt="-D_GLIBCXX_USE_CXX11_ABI=1" --cxxopt="-std=c++17" --cxxopt="-msse2" --cxxopt="-msse3" --cxxopt="-msse4" --notest_keep_going --test_output=errors //tensorflow_quantum/...) exit_code=$? diff --git a/scripts/test_benchmarks.sh b/scripts/test_benchmarks.sh index 281791ec7..07e3adec1 100644 --- a/scripts/test_benchmarks.sh +++ b/scripts/test_benchmarks.sh @@ -12,7 +12,7 @@ # 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. -# ============================================================================= +# ============================================================================== 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)) diff --git a/scripts/test_tutorials.py b/scripts/test_tutorials.py index b4463b90d..1650caf15 100644 --- a/scripts/test_tutorials.py +++ b/scripts/test_tutorials.py @@ -11,7 +11,7 @@ # 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. -# ============================================================================= +# ============================================================================== """Module to ensure all notebooks execute without error by pytesting them.""" import glob import re diff --git a/tensorflow_quantum/__init__.py b/tensorflow_quantum/__init__.py index 44f4ba3ea..7c781f882 100644 --- a/tensorflow_quantum/__init__.py +++ b/tensorflow_quantum/__init__.py @@ -11,7 +11,7 @@ # 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. -# ============================================================================= +# ============================================================================== """Module functions for tensorflow_quantum.*""" # Import basic ops and op getters. diff --git a/tensorflow_quantum/core/__init__.py b/tensorflow_quantum/core/__init__.py index 7e43c4be5..fb24ad4a8 100644 --- a/tensorflow_quantum/core/__init__.py +++ b/tensorflow_quantum/core/__init__.py @@ -11,7 +11,7 @@ # 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. -# ============================================================================= +# ============================================================================== """Imports to tensorflow_quantum.core.* level.""" # Import getters for constructing ops. from tensorflow_quantum.core.ops import (get_expectation_op, diff --git a/tensorflow_quantum/core/ops/BUILD b/tensorflow_quantum/core/ops/BUILD index 84361cef1..8087a8d3b 100644 --- a/tensorflow_quantum/core/ops/BUILD +++ b/tensorflow_quantum/core/ops/BUILD @@ -1,6 +1,4 @@ # load op_wrapper -load("@org_tensorflow//tensorflow:tensorflow.bzl", "tf_gpu_kernel_library", "tf_gen_op_wrapper_py") -load("@local_config_cuda//cuda:build_defs.bzl", "if_cuda_is_configured", "if_cuda") package(default_visibility = ["//visibility:public"]) @@ -14,23 +12,6 @@ config_setting( constraint_values = ["@bazel_tools//platforms:windows"], ) -cc_library( - name = "cuda", - data = [ - "@local_config_cuda//cuda:cudart", - ], - linkopts = select({ - ":windows": [], - "//conditions:default": [ - "-Wl,-rpath,../local_config_cuda/cuda/lib64", - "-Wl,-rpath,../local_config_cuda/cuda/extras/CUPTI/lib64", - ], - }), - deps = [ - "@local_config_cuda//cuda:cudart", - ], -) - py_library( name = "ops", srcs = ["__init__.py"], @@ -49,10 +30,7 @@ py_library( "//tensorflow_quantum/core/ops/math_ops:inner_product_op_py", "//tensorflow_quantum/core/ops/math_ops:fidelity_op_py", "//tensorflow_quantum/core/ops/noise:noisy_expectation_op_py", - ] + if_cuda_is_configured([ - ":tfq_simulate_ops_cuda_py", - ":tfq_simulate_ops_cuquantum_py", - ]), + ], ) cc_binary( @@ -641,198 +619,6 @@ py_test( ], ) -py_library( - name = "tfq_simulate_ops_cuda_py", - srcs = ["tfq_simulate_ops_cuda.py"], - data = [ - ":_tfq_simulate_ops_cuda.so", - ], - srcs_version = "PY3", - deps = [ - # tensorflow framework for wrappers - ":load_module", - ], -) - -py_library( - name = "tfq_simulate_ops_cuquantum_py", - srcs = ["tfq_simulate_ops_cuquantum.py"], - data = [ - ":_tfq_simulate_ops_cuquantum.so", - ], - srcs_version = "PY3", - deps = [ - # tensorflow framework for wrappers - ":load_module", - ], -) - -py_test( - name = "tfq_simulate_ops_gpu_test", - srcs = ["tfq_simulate_ops_gpu_test.py"], - deps = [ - ":tfq_simulate_ops_cuda_py", - ":tfq_simulate_ops_cuquantum_py", - ":tfq_simulate_ops_py", - "//tensorflow_quantum/python:util", - ], - srcs_version = "PY3", -) - -cc_binary( - name = "_tfq_simulate_ops_cuda.so", - srcs = [ - "tfq_simulate_expectation_op_cuda.cu.cc", - ], - linkshared = 1, - features = select({ - ":windows": ["windows_export_all_symbols"], - "//conditions:default": [], - }), - copts = select({ - ":windows": [ - "/D__CLANG_SUPPORT_DYN_ANNOTATION__", - "/D_USE_MATH_DEFINES", - "/DEIGEN_MPL2_ONLY", - "/DEIGEN_MAX_ALIGN_BYTES=64", - "/DEIGEN_HAS_TYPE_TRAITS=0", - "/DTF_USE_SNAPPY", - "/showIncludes", - "/MD", - "/O2", - "/DNDEBUG", - "/w", - "-DWIN32_LEAN_AND_MEAN", - "-DNOGDI", - "/d2ReducedOptimizeHugeFunctions", - "/arch:AVX", - "/std:c++17", - "-DTENSORFLOW_MONOLITHIC_BUILD", - "/DPLATFORM_WINDOWS", - "/DEIGEN_HAS_C99_MATH", - "/DTENSORFLOW_USE_EIGEN_THREADPOOL", - "/DEIGEN_AVOID_STL_ARRAY", - "/Iexternal/gemmlowp", - "/wd4018", - "/wd4577", - "/DNOGDI", - "/UTF_COMPILE_LIBRARY", - ], - "//conditions:default": [ - "-Iexternal/local_cuda/cuda/include", - # "--cuda-gpu-arch=sm_86", - # "-L/usr/local/cuda/lib64", - # "-lcudart_static", - # "-ldl", - # "-lrt", - "-pthread", - "-std=c++17", - "-D_GLIBCXX_USE_CXX11_ABI=1", - "-O3", - "-Iexternal/cuda_headers", - "-DNV_CUDNN_DISABLE_EXCEPTION", - # "-fpermissive", - ], - }) + if_cuda_is_configured(["-DTENSORFLOW_USE_NVCC=1", "-DGOOGLE_CUDA=1", "-x cuda", "-nvcc_options=relaxed-constexpr", "-nvcc_options=ftz=true"]), - deps = [ - # cirq cc proto - "//tensorflow_quantum/core/ops:parse_context", - "//tensorflow_quantum/core/ops:tfq_simulate_utils", - "//tensorflow_quantum/core/proto:pauli_sum_cc_proto", - "//tensorflow_quantum/core/proto:program_cc_proto", - "//tensorflow_quantum/core/src:circuit_parser_qsim", - "//tensorflow_quantum/core/src:util_qsim", - "@eigen//:eigen3", - # "@local_cuda//:cuda_headers" - # tensorflow core framework - # tensorflow core lib - # tensorflow core protos - ] + if_cuda_is_configured([ - ":cuda", - "@local_config_cuda//cuda:cuda_headers", - "@qsim//lib:qsim_cuda_lib", - ]), - # alwayslink=1, -) - -cc_binary( - name = "_tfq_simulate_ops_cuquantum.so", - srcs = [ - "tfq_simulate_expectation_op_cuquantum.cu.cc", - ], - linkshared = 1, - features = select({ - ":windows": ["windows_export_all_symbols"], - "//conditions:default": [], - }), - copts = select({ - ":windows": [ - "/D__CLANG_SUPPORT_DYN_ANNOTATION__", - "/D_USE_MATH_DEFINES", - "/DEIGEN_MPL2_ONLY", - "/DEIGEN_MAX_ALIGN_BYTES=64", - "/DEIGEN_HAS_TYPE_TRAITS=0", - "/DTF_USE_SNAPPY", - "/showIncludes", - "/MD", - "/O2", - "/DNDEBUG", - "/w", - "-DWIN32_LEAN_AND_MEAN", - "-DNOGDI", - "/d2ReducedOptimizeHugeFunctions", - "/arch:AVX", - "/std:c++17", - "-DTENSORFLOW_MONOLITHIC_BUILD", - "/DPLATFORM_WINDOWS", - "/DEIGEN_HAS_C99_MATH", - "/DTENSORFLOW_USE_EIGEN_THREADPOOL", - "/DEIGEN_AVOID_STL_ARRAY", - "/Iexternal/gemmlowp", - "/wd4018", - "/wd4577", - "/DNOGDI", - "/UTF_COMPILE_LIBRARY", - ], - "//conditions:default": [ - "-Iexternal/local_cuda/cuda/include", - # "--cuda-gpu-arch=sm_86", - # "-L/usr/local/cuda/lib64", - # "-lcudart_static", - # "-ldl", - # "-lrt", - "-pthread", - "-std=c++17", - "-D_GLIBCXX_USE_CXX11_ABI=1", - "-O3", - "-Iexternal/cuda_headers", - "-DNV_CUDNN_DISABLE_EXCEPTION", - # "-fpermissive", - ], - }) + if_cuda_is_configured(["-DTENSORFLOW_USE_NVCC=1", "-DGOOGLE_CUDA=1", "-x cuda", "-nvcc_options=relaxed-constexpr", "-nvcc_options=ftz=true"]), - deps = [ - # cirq cc proto - "//tensorflow_quantum/core/ops:parse_context", - "//tensorflow_quantum/core/ops:tfq_simulate_utils", - "//tensorflow_quantum/core/proto:pauli_sum_cc_proto", - "//tensorflow_quantum/core/proto:program_cc_proto", - "//tensorflow_quantum/core/src:circuit_parser_qsim", - "//tensorflow_quantum/core/src:util_qsim", - "@eigen//:eigen3", - # "@local_cuda//:cuda_headers" - # tensorflow core framework - # tensorflow core lib - # tensorflow core protos - ] + if_cuda_is_configured([ - ":cuda", - "@cuquantum_libs//:custatevec", - "@cuquantum_libs//:custatevec_headers", - "@local_config_cuda//cuda:cuda_headers", - "@qsim//lib:qsim_cuquantum_lib", - ]), - # alwayslink=1, -) - py_library( name = "load_module", srcs = ["load_module.py"], diff --git a/tensorflow_quantum/core/ops/__init__.py b/tensorflow_quantum/core/ops/__init__.py index fc687424a..062ea7499 100644 --- a/tensorflow_quantum/core/ops/__init__.py +++ b/tensorflow_quantum/core/ops/__init__.py @@ -11,7 +11,7 @@ # 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. -# ============================================================================= +# ============================================================================== """Module for tfq.core.ops.*""" # Import getters for constructing ops. diff --git a/tensorflow_quantum/core/ops/batch_util.py b/tensorflow_quantum/core/ops/batch_util.py index 7575ffae1..75f148424 100644 --- a/tensorflow_quantum/core/ops/batch_util.py +++ b/tensorflow_quantum/core/ops/batch_util.py @@ -11,7 +11,7 @@ # 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. -# ============================================================================= +# ============================================================================== """A module to for running Cirq objects.""" import collections diff --git a/tensorflow_quantum/core/ops/batch_util_test.py b/tensorflow_quantum/core/ops/batch_util_test.py index 16debfc0c..6b11becd7 100644 --- a/tensorflow_quantum/core/ops/batch_util_test.py +++ b/tensorflow_quantum/core/ops/batch_util_test.py @@ -11,12 +11,11 @@ # 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. -# ============================================================================= +# ============================================================================== """Test parallel Cirq simulations.""" # Remove PYTHONPATH collisions for protobuf. # pylint: disable=wrong-import-position import sys - NEW_PATH = [x for x in sys.path if 'com_google_protobuf' not in x] sys.path = NEW_PATH # pylint: enable=wrong-import-position diff --git a/tensorflow_quantum/core/ops/circuit_execution_ops.py b/tensorflow_quantum/core/ops/circuit_execution_ops.py index b2cc1ce70..1158e98e4 100644 --- a/tensorflow_quantum/core/ops/circuit_execution_ops.py +++ b/tensorflow_quantum/core/ops/circuit_execution_ops.py @@ -11,7 +11,7 @@ # 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. -# ============================================================================= +# ============================================================================== """A module for user-facing generators of tfq ops.""" import enum diff --git a/tensorflow_quantum/core/ops/circuit_execution_ops_test.py b/tensorflow_quantum/core/ops/circuit_execution_ops_test.py index 08e4f5b6f..f94297cdc 100644 --- a/tensorflow_quantum/core/ops/circuit_execution_ops_test.py +++ b/tensorflow_quantum/core/ops/circuit_execution_ops_test.py @@ -11,12 +11,11 @@ # 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. -# ============================================================================= +# ============================================================================== """Module to test consistency between Cirq and TFQ circuit execution ops.""" # Remove PYTHONPATH collisions for protobuf. # pylint: disable=wrong-import-position import sys - NEW_PATH = [x for x in sys.path if 'com_google_protobuf' not in x] sys.path = NEW_PATH # pylint: enable=wrong-import-position diff --git a/tensorflow_quantum/core/ops/cirq_ops.py b/tensorflow_quantum/core/ops/cirq_ops.py index 2c1039ac8..2650e812b 100644 --- a/tensorflow_quantum/core/ops/cirq_ops.py +++ b/tensorflow_quantum/core/ops/cirq_ops.py @@ -11,7 +11,7 @@ # 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. -# ============================================================================= +# ============================================================================== """Generators for ops that call out to cirq simulators from the tf graph.""" import functools import numbers diff --git a/tensorflow_quantum/core/ops/cirq_ops_test.py b/tensorflow_quantum/core/ops/cirq_ops_test.py index 8dc0de4a9..1b54771a9 100644 --- a/tensorflow_quantum/core/ops/cirq_ops_test.py +++ b/tensorflow_quantum/core/ops/cirq_ops_test.py @@ -11,12 +11,11 @@ # 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. -# ============================================================================= +# ============================================================================== """Tests for the cirq simulation ops.""" # Remove PYTHONPATH collisions for protobuf. # pylint: disable=wrong-import-position import sys - NEW_PATH = [x for x in sys.path if 'com_google_protobuf' not in x] sys.path = NEW_PATH # pylint: enable=wrong-import-position diff --git a/tensorflow_quantum/core/ops/load_module.py b/tensorflow_quantum/core/ops/load_module.py index ee4f9b0b6..b5002ad84 100644 --- a/tensorflow_quantum/core/ops/load_module.py +++ b/tensorflow_quantum/core/ops/load_module.py @@ -11,7 +11,7 @@ # 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. -# ============================================================================= +# ============================================================================== """Module to load python op libraries.""" import os diff --git a/tensorflow_quantum/core/ops/math_ops/__init__.py b/tensorflow_quantum/core/ops/math_ops/__init__.py index 9d3b92f64..982e26911 100644 --- a/tensorflow_quantum/core/ops/math_ops/__init__.py +++ b/tensorflow_quantum/core/ops/math_ops/__init__.py @@ -11,7 +11,7 @@ # 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. -# ============================================================================= +# ============================================================================== """Module for tfq.core.ops.math_ops.*""" from tensorflow_quantum.core.ops.math_ops.fidelity_op import fidelity diff --git a/tensorflow_quantum/core/ops/math_ops/fidelity_op.py b/tensorflow_quantum/core/ops/math_ops/fidelity_op.py index ae2908baa..8f2e87e44 100644 --- a/tensorflow_quantum/core/ops/math_ops/fidelity_op.py +++ b/tensorflow_quantum/core/ops/math_ops/fidelity_op.py @@ -11,7 +11,7 @@ # 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. -# ============================================================================= +# ============================================================================== """Module for tfq.math.fidelity op.""" import tensorflow as tf from tensorflow_quantum.core.ops.math_ops import inner_product_op diff --git a/tensorflow_quantum/core/ops/math_ops/fidelity_op_test.py b/tensorflow_quantum/core/ops/math_ops/fidelity_op_test.py index a17011bd3..1ab8031ea 100644 --- a/tensorflow_quantum/core/ops/math_ops/fidelity_op_test.py +++ b/tensorflow_quantum/core/ops/math_ops/fidelity_op_test.py @@ -11,12 +11,11 @@ # 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. -# ============================================================================= +# ============================================================================== """Tests that specifically target tfq_inner_product.""" # Remove PYTHONPATH collisions for protobuf. # pylint: disable=wrong-import-position import sys - NEW_PATH = [x for x in sys.path if 'com_google_protobuf' not in x] sys.path = NEW_PATH # pylint: enable=wrong-import-position diff --git a/tensorflow_quantum/core/ops/math_ops/inner_product_grad_test.py b/tensorflow_quantum/core/ops/math_ops/inner_product_grad_test.py index 513f1eeb0..7fa74ee40 100644 --- a/tensorflow_quantum/core/ops/math_ops/inner_product_grad_test.py +++ b/tensorflow_quantum/core/ops/math_ops/inner_product_grad_test.py @@ -11,12 +11,11 @@ # 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. -# ============================================================================= +# ============================================================================== """Tests that specifically target tfq_inner_product_grad.""" # Remove PYTHONPATH collisions for protobuf. # pylint: disable=wrong-import-position import sys - NEW_PATH = [x for x in sys.path if 'com_google_protobuf' not in x] sys.path = NEW_PATH # pylint: enable=wrong-import-position diff --git a/tensorflow_quantum/core/ops/math_ops/inner_product_op.py b/tensorflow_quantum/core/ops/math_ops/inner_product_op.py index 54e49643e..5d92b7b92 100644 --- a/tensorflow_quantum/core/ops/math_ops/inner_product_op.py +++ b/tensorflow_quantum/core/ops/math_ops/inner_product_op.py @@ -11,7 +11,7 @@ # 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. -# ============================================================================= +# ============================================================================== """Module to register python op gradient.""" import os import tensorflow as tf diff --git a/tensorflow_quantum/core/ops/math_ops/inner_product_op_test.py b/tensorflow_quantum/core/ops/math_ops/inner_product_op_test.py index fb4bbf5c9..ae83857b6 100644 --- a/tensorflow_quantum/core/ops/math_ops/inner_product_op_test.py +++ b/tensorflow_quantum/core/ops/math_ops/inner_product_op_test.py @@ -11,12 +11,11 @@ # 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. -# ============================================================================= +# ============================================================================== """Tests that specifically target tfq_inner_product.""" # Remove PYTHONPATH collisions for protobuf. # pylint: disable=wrong-import-position import sys - NEW_PATH = [x for x in sys.path if 'com_google_protobuf' not in x] sys.path = NEW_PATH # pylint: enable=wrong-import-position diff --git a/tensorflow_quantum/core/ops/math_ops/simulate_mps.py b/tensorflow_quantum/core/ops/math_ops/simulate_mps.py index 41e1fd7c2..812081c05 100644 --- a/tensorflow_quantum/core/ops/math_ops/simulate_mps.py +++ b/tensorflow_quantum/core/ops/math_ops/simulate_mps.py @@ -11,7 +11,7 @@ # 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. -# ============================================================================= +# ============================================================================== """Module to register MPS simulation ops.""" import os import tensorflow as tf diff --git a/tensorflow_quantum/core/ops/math_ops/simulate_mps_test.py b/tensorflow_quantum/core/ops/math_ops/simulate_mps_test.py index 3ed527ed8..ee7317b6a 100644 --- a/tensorflow_quantum/core/ops/math_ops/simulate_mps_test.py +++ b/tensorflow_quantum/core/ops/math_ops/simulate_mps_test.py @@ -11,12 +11,11 @@ # 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. -# ============================================================================= +# ============================================================================== """Tests that specifically target simulate_mps.""" # Remove PYTHONPATH collisions for protobuf. # pylint: disable=wrong-import-position import sys - NEW_PATH = [x for x in sys.path if 'com_google_protobuf' not in x] sys.path = NEW_PATH # pylint: enable=wrong-import-position diff --git a/tensorflow_quantum/core/ops/noise/__init__.py b/tensorflow_quantum/core/ops/noise/__init__.py index d7969cec5..71291d4d2 100644 --- a/tensorflow_quantum/core/ops/noise/__init__.py +++ b/tensorflow_quantum/core/ops/noise/__init__.py @@ -11,7 +11,7 @@ # 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. -# ============================================================================= +# ============================================================================== """Module for tfq.core.ops.noise.*""" from tensorflow_quantum.core.ops.noise.noisy_expectation_op import expectation diff --git a/tensorflow_quantum/core/ops/noise/noisy_expectation_op.py b/tensorflow_quantum/core/ops/noise/noisy_expectation_op.py index 7f801e686..e621988a0 100644 --- a/tensorflow_quantum/core/ops/noise/noisy_expectation_op.py +++ b/tensorflow_quantum/core/ops/noise/noisy_expectation_op.py @@ -11,7 +11,7 @@ # 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. -# ============================================================================= +# ============================================================================== """Module for high performance noisy circuit simulation ops.""" import os import tensorflow as tf diff --git a/tensorflow_quantum/core/ops/noise/noisy_expectation_op_test.py b/tensorflow_quantum/core/ops/noise/noisy_expectation_op_test.py index 5c87bdbfc..1e73500b8 100644 --- a/tensorflow_quantum/core/ops/noise/noisy_expectation_op_test.py +++ b/tensorflow_quantum/core/ops/noise/noisy_expectation_op_test.py @@ -11,12 +11,11 @@ # 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. -# ============================================================================= +# ============================================================================== """Tests that specifically target noisy expectation calculation.""" # Remove PYTHONPATH collisions for protobuf. # pylint: disable=wrong-import-position import sys - NEW_PATH = [x for x in sys.path if 'com_google_protobuf' not in x] sys.path = NEW_PATH # pylint: enable=wrong-import-position diff --git a/tensorflow_quantum/core/ops/noise/noisy_sampled_expectation_op.py b/tensorflow_quantum/core/ops/noise/noisy_sampled_expectation_op.py index 2cc84fd47..1874c8a5e 100644 --- a/tensorflow_quantum/core/ops/noise/noisy_sampled_expectation_op.py +++ b/tensorflow_quantum/core/ops/noise/noisy_sampled_expectation_op.py @@ -11,7 +11,7 @@ # 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. -# ============================================================================= +# ============================================================================== """Module for high performance noisy circuit sampled epxectation ops.""" import os import tensorflow as tf diff --git a/tensorflow_quantum/core/ops/noise/noisy_sampled_expectation_op_test.py b/tensorflow_quantum/core/ops/noise/noisy_sampled_expectation_op_test.py index ea967c93b..35d1cc113 100644 --- a/tensorflow_quantum/core/ops/noise/noisy_sampled_expectation_op_test.py +++ b/tensorflow_quantum/core/ops/noise/noisy_sampled_expectation_op_test.py @@ -11,12 +11,11 @@ # 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. -# ============================================================================= +# ============================================================================== """Tests that specifically target noisy expectation calculation.""" # Remove PYTHONPATH collisions for protobuf. # pylint: disable=wrong-import-position import sys - NEW_PATH = [x for x in sys.path if 'com_google_protobuf' not in x] sys.path = NEW_PATH # pylint: enable=wrong-import-position diff --git a/tensorflow_quantum/core/ops/noise/noisy_samples_op.py b/tensorflow_quantum/core/ops/noise/noisy_samples_op.py index 1e19b19ae..4441d0c04 100644 --- a/tensorflow_quantum/core/ops/noise/noisy_samples_op.py +++ b/tensorflow_quantum/core/ops/noise/noisy_samples_op.py @@ -11,7 +11,7 @@ # 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. -# ============================================================================= +# ============================================================================== """Module for high performance noisy circuit sampling ops""" import os import tensorflow as tf diff --git a/tensorflow_quantum/core/ops/noise/noisy_samples_op_test.py b/tensorflow_quantum/core/ops/noise/noisy_samples_op_test.py index 88b221941..b952e8d40 100644 --- a/tensorflow_quantum/core/ops/noise/noisy_samples_op_test.py +++ b/tensorflow_quantum/core/ops/noise/noisy_samples_op_test.py @@ -11,12 +11,11 @@ # 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. -# ============================================================================= +# ============================================================================== """Tests that specifically target noisy sampling.""" # Remove PYTHONPATH collisions for protobuf. # pylint: disable=wrong-import-position import sys - NEW_PATH = [x for x in sys.path if 'com_google_protobuf' not in x] sys.path = NEW_PATH # pylint: enable=wrong-import-position diff --git a/tensorflow_quantum/core/ops/tfq_adj_grad_op.py b/tensorflow_quantum/core/ops/tfq_adj_grad_op.py index ead1e34d6..04b8ff0fb 100644 --- a/tensorflow_quantum/core/ops/tfq_adj_grad_op.py +++ b/tensorflow_quantum/core/ops/tfq_adj_grad_op.py @@ -11,7 +11,7 @@ # 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. -# ============================================================================= +# ============================================================================== """Module to register python op gradient.""" import tensorflow as tf from tensorflow_quantum.core.ops.load_module import load_module diff --git a/tensorflow_quantum/core/ops/tfq_adj_grad_op_test.py b/tensorflow_quantum/core/ops/tfq_adj_grad_op_test.py index 3acb662c4..388bb163f 100644 --- a/tensorflow_quantum/core/ops/tfq_adj_grad_op_test.py +++ b/tensorflow_quantum/core/ops/tfq_adj_grad_op_test.py @@ -11,12 +11,11 @@ # 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. -# ============================================================================= +# ============================================================================== """Tests that specifically target tfq_unitary_op.""" # Remove PYTHONPATH collisions for protobuf. # pylint: disable=wrong-import-position import sys - NEW_PATH = [x for x in sys.path if 'com_google_protobuf' not in x] sys.path = NEW_PATH # pylint: enable=wrong-import-position diff --git a/tensorflow_quantum/core/ops/tfq_ps_util_ops.py b/tensorflow_quantum/core/ops/tfq_ps_util_ops.py index 5a90eb0b3..ad746d045 100644 --- a/tensorflow_quantum/core/ops/tfq_ps_util_ops.py +++ b/tensorflow_quantum/core/ops/tfq_ps_util_ops.py @@ -11,7 +11,7 @@ # 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. -# ============================================================================= +# ============================================================================== """Expose bindings for ParameterShift C++ ops.""" from tensorflow_quantum.core.ops.load_module import load_module diff --git a/tensorflow_quantum/core/ops/tfq_ps_util_ops_test.py b/tensorflow_quantum/core/ops/tfq_ps_util_ops_test.py index 3ee1b3f61..14bccd9bf 100644 --- a/tensorflow_quantum/core/ops/tfq_ps_util_ops_test.py +++ b/tensorflow_quantum/core/ops/tfq_ps_util_ops_test.py @@ -11,12 +11,11 @@ # 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. -# ============================================================================= +# ============================================================================== """Test for ParameterShift specific C++ ops.""" # Remove PYTHONPATH collisions for protobuf. # pylint: disable=wrong-import-position import sys - NEW_PATH = [x for x in sys.path if 'com_google_protobuf' not in x] sys.path = NEW_PATH # pylint: enable=wrong-import-position diff --git a/tensorflow_quantum/core/ops/tfq_simulate_expectation_op_cuda.cu.cc b/tensorflow_quantum/core/ops/tfq_simulate_expectation_op_cuda.cu.cc deleted file mode 100644 index 20e5bfe8c..000000000 --- a/tensorflow_quantum/core/ops/tfq_simulate_expectation_op_cuda.cu.cc +++ /dev/null @@ -1,206 +0,0 @@ -/* 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. -See the License for the specific language governing permissions and -limitations under the License. -==============================================================================*/ - -#include -#include - -#include - -#include "../qsim/lib/circuit.h" -#include "../qsim/lib/gate_appl.h" -#include "../qsim/lib/gates_cirq.h" -#include "../qsim/lib/gates_qsim.h" -#include "../qsim/lib/seqfor.h" -#include "../qsim/lib/simulator_cuda.h" -#include "../qsim/lib/statespace_cuda.h" -#include "tensorflow/core/framework/op_kernel.h" -#include "tensorflow/core/framework/shape_inference.h" -#include "tensorflow/core/framework/tensor_shape.h" -#include "tensorflow/core/lib/core/error_codes.pb.h" -#include "tensorflow/core/lib/core/status.h" -#include "tensorflow/core/lib/core/threadpool.h" -#include "tensorflow/core/platform/mutex.h" -#include "tensorflow_quantum/core/ops/parse_context.h" -#include "tensorflow_quantum/core/proto/pauli_sum.pb.h" -#include "tensorflow_quantum/core/proto/program.pb.h" -#include "tensorflow_quantum/core/src/util_qsim.h" - -namespace tfq { - -using ::tensorflow::Status; -using ::tfq::proto::PauliSum; -using ::tfq::proto::Program; - -typedef qsim::Cirq::GateCirq QsimGate; -typedef qsim::Circuit QsimCircuit; - -class TfqSimulateExpectationOpCuda : public tensorflow::OpKernel { - public: - explicit TfqSimulateExpectationOpCuda( - tensorflow::OpKernelConstruction* context) - : OpKernel(context) {} - - void Compute(tensorflow::OpKernelContext* context) override { - // TODO (mbbrough): add more dimension checks for other inputs here. - const int num_inputs = context->num_inputs(); - OP_REQUIRES(context, num_inputs == 4, - tensorflow::errors::InvalidArgument(absl::StrCat( - "Expected 4 inputs, got ", num_inputs, " inputs."))); - - // Create the output Tensor. - const int output_dim_batch_size = context->input(0).dim_size(0); - const int output_dim_op_size = context->input(3).dim_size(1); - tensorflow::TensorShape output_shape; - output_shape.AddDim(output_dim_batch_size); - output_shape.AddDim(output_dim_op_size); - - tensorflow::Tensor* output = nullptr; - tensorflow::AllocatorAttributes alloc_attr; - alloc_attr.set_on_host(true); - alloc_attr.set_gpu_compatible(true); - OP_REQUIRES_OK(context, context->allocate_output(0, output_shape, &output, - alloc_attr)); - auto output_tensor = output->matrix(); - // Parse program protos. - std::vector programs; - std::vector num_qubits; - std::vector> pauli_sums; - OP_REQUIRES_OK(context, GetProgramsAndNumQubits(context, &programs, - &num_qubits, &pauli_sums)); - - std::vector maps; - OP_REQUIRES_OK(context, GetSymbolMaps(context, &maps)); - - OP_REQUIRES(context, programs.size() == maps.size(), - tensorflow::errors::InvalidArgument(absl::StrCat( - "Number of circuits and symbol_values do not match. Got ", - programs.size(), " circuits and ", maps.size(), - " symbol values."))); - - // Construct qsim circuits. - std::vector qsim_circuits(programs.size(), QsimCircuit()); - std::vector>> fused_circuits( - programs.size(), std::vector>({})); - - Status parse_status = Status(); - auto p_lock = tensorflow::mutex(); - auto construct_f = [&](int start, int end) { - for (int i = start; i < end; i++) { - Status local = - QsimCircuitFromProgram(programs[i], maps[i], num_qubits[i], - &qsim_circuits[i], &fused_circuits[i]); - NESTED_FN_STATUS_SYNC(parse_status, local, p_lock); - } - }; - - const int num_cycles = 1000; - context->device()->tensorflow_cpu_worker_threads()->workers->ParallelFor( - programs.size(), num_cycles, construct_f); - OP_REQUIRES_OK(context, parse_status); - - int max_num_qubits = 0; - for (const int num : num_qubits) { - max_num_qubits = std::max(max_num_qubits, num); - } - ComputeLarge(num_qubits, fused_circuits, pauli_sums, context, - &output_tensor); - } - - private: - int num_threads_in_sim_; - int block_count_; - - // Define the GPU implementation that launches the CUDA kernel. - void ComputeLarge( - const std::vector& num_qubits, - const std::vector>>& fused_circuits, - const std::vector>& pauli_sums, - tensorflow::OpKernelContext* context, - tensorflow::TTypes::Matrix* output_tensor) { - // Instantiate qsim objects. - using Simulator = qsim::SimulatorCUDA; - using StateSpace = Simulator::StateSpace; - // Begin simulation with default parameters. - int largest_nq = 1; - Simulator sim = Simulator(); - StateSpace ss = StateSpace(StateSpace::Parameter()); - auto sv = ss.Create(largest_nq); - auto scratch = ss.Create(largest_nq); - - // Simulate programs one by one. Parallelizing over state vectors - // we no longer parallelize over circuits. Each time we encounter a - // a larger circuit we will grow the Statevector as necessary. - for (int i = 0; i < fused_circuits.size(); i++) { - int nq = num_qubits[i]; - - if (nq > largest_nq) { - // need to switch to larger statespace. - largest_nq = nq; - sv = ss.Create(largest_nq); - scratch = ss.Create(largest_nq); - } - // TODO: add heuristic here so that we do not always recompute - // the state if there is a possibility that circuit[i] and - // circuit[i + 1] produce the same state. - ss.SetStateZero(sv); - for (int j = 0; j < fused_circuits[i].size(); j++) { - qsim::ApplyFusedGate(sim, fused_circuits[i][j], sv); - } - for (int j = 0; j < pauli_sums[i].size(); j++) { - // (#679) Just ignore empty program - if (fused_circuits[i].size() == 0) { - (*output_tensor)(i, j) = -2.0; - continue; - } - float exp_v = 0.0; - OP_REQUIRES_OK(context, - ComputeExpectationQsim(pauli_sums[i][j], sim, ss, sv, - scratch, &exp_v)); - (*output_tensor)(i, j) = exp_v; - } - } - } -}; - -REGISTER_KERNEL_BUILDER( - Name("TfqSimulateExpectationCuda").Device(tensorflow::DEVICE_CPU), - TfqSimulateExpectationOpCuda); - -REGISTER_OP("TfqSimulateExpectationCuda") - .Input("programs: string") - .Input("symbol_names: string") - .Input("symbol_values: float") - .Input("pauli_sums: string") - .Output("expectations: float") - .SetShapeFn([](tensorflow::shape_inference::InferenceContext* c) { - tensorflow::shape_inference::ShapeHandle programs_shape; - TF_RETURN_IF_ERROR(c->WithRank(c->input(0), 1, &programs_shape)); - - tensorflow::shape_inference::ShapeHandle symbol_names_shape; - TF_RETURN_IF_ERROR(c->WithRank(c->input(1), 1, &symbol_names_shape)); - - tensorflow::shape_inference::ShapeHandle symbol_values_shape; - TF_RETURN_IF_ERROR(c->WithRank(c->input(2), 2, &symbol_values_shape)); - - tensorflow::shape_inference::ShapeHandle pauli_sums_shape; - TF_RETURN_IF_ERROR(c->WithRank(c->input(3), 2, &pauli_sums_shape)); - - tensorflow::shape_inference::DimensionHandle output_rows = - c->Dim(programs_shape, 0); - tensorflow::shape_inference::DimensionHandle output_cols = - c->Dim(pauli_sums_shape, 1); - c->set_output(0, c->Matrix(output_rows, output_cols)); - - return ::tensorflow::Status(); - }); - -} // namespace tfq diff --git a/tensorflow_quantum/core/ops/tfq_simulate_expectation_op_cuquantum.cu.cc b/tensorflow_quantum/core/ops/tfq_simulate_expectation_op_cuquantum.cu.cc deleted file mode 100644 index 6c9f03eb7..000000000 --- a/tensorflow_quantum/core/ops/tfq_simulate_expectation_op_cuquantum.cu.cc +++ /dev/null @@ -1,220 +0,0 @@ -/* 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. -See the License for the specific language governing permissions and -limitations under the License. -==============================================================================*/ - -#include -#include - -#include - -#include "../cuquantum_libs/include/custatevec.h" -#include "../qsim/lib/circuit.h" -#include "../qsim/lib/gate_appl.h" -#include "../qsim/lib/gates_cirq.h" -#include "../qsim/lib/gates_qsim.h" -#include "../qsim/lib/seqfor.h" -#include "../qsim/lib/simulator_custatevec.h" -#include "../qsim/lib/statespace_custatevec.h" -#include "tensorflow/core/framework/op_kernel.h" -#include "tensorflow/core/framework/shape_inference.h" -#include "tensorflow/core/framework/tensor_shape.h" -#include "tensorflow/core/lib/core/error_codes.pb.h" -#include "tensorflow/core/lib/core/status.h" -#include "tensorflow/core/lib/core/threadpool.h" -#include "tensorflow/core/platform/mutex.h" -#include "tensorflow_quantum/core/ops/parse_context.h" -#include "tensorflow_quantum/core/proto/pauli_sum.pb.h" -#include "tensorflow_quantum/core/proto/program.pb.h" -#include "tensorflow_quantum/core/src/util_qsim.h" - -namespace tfq { - -using ::tensorflow::Status; -using ::tfq::proto::PauliSum; -using ::tfq::proto::Program; - -typedef qsim::Cirq::GateCirq QsimGate; -typedef qsim::Circuit QsimCircuit; - -class TfqSimulateExpectationOpCuQuantum : public tensorflow::OpKernel { - public: - explicit TfqSimulateExpectationOpCuQuantum( - tensorflow::OpKernelConstruction* context) - : OpKernel(context) {} - - void Compute(tensorflow::OpKernelContext* context) override { - // TODO (mbbrough): add more dimension checks for other inputs here. - const int num_inputs = context->num_inputs(); - OP_REQUIRES(context, num_inputs == 4, - tensorflow::errors::InvalidArgument(absl::StrCat( - "Expected 4 inputs, got ", num_inputs, " inputs."))); - - // Create the output Tensor. - const int output_dim_batch_size = context->input(0).dim_size(0); - const int output_dim_op_size = context->input(3).dim_size(1); - tensorflow::TensorShape output_shape; - output_shape.AddDim(output_dim_batch_size); - output_shape.AddDim(output_dim_op_size); - - tensorflow::Tensor* output = nullptr; - tensorflow::AllocatorAttributes alloc_attr; - alloc_attr.set_on_host(true); // why?? - alloc_attr.set_gpu_compatible(true); - OP_REQUIRES_OK(context, context->allocate_output(0, output_shape, &output, - alloc_attr)); - auto output_tensor = output->matrix(); - // Parse program protos. - std::vector programs; - std::vector num_qubits; - std::vector> - pauli_sums; // why is this a vector of vectors?? - OP_REQUIRES_OK(context, GetProgramsAndNumQubits(context, &programs, - &num_qubits, &pauli_sums)); - - std::vector maps; - OP_REQUIRES_OK(context, GetSymbolMaps(context, &maps)); - - OP_REQUIRES(context, programs.size() == maps.size(), - tensorflow::errors::InvalidArgument(absl::StrCat( - "Number of circuits and symbol_values do not match. Got ", - programs.size(), " circuits and ", maps.size(), - " symbol values."))); - - // Construct qsim circuits. - std::vector qsim_circuits(programs.size(), QsimCircuit()); - std::vector>> fused_circuits( - programs.size(), std::vector>({})); - - Status parse_status = Status::OK(); - auto p_lock = tensorflow::mutex(); - auto construct_f = [&](int start, int end) { - for (int i = start; i < end; i++) { - Status local = - QsimCircuitFromProgram(programs[i], maps[i], num_qubits[i], - &qsim_circuits[i], &fused_circuits[i]); - NESTED_FN_STATUS_SYNC(parse_status, local, p_lock); - } - }; - - const int num_cycles = 1000; - context->device()->tensorflow_cpu_worker_threads()->workers->ParallelFor( - programs.size(), num_cycles, construct_f); - OP_REQUIRES_OK(context, parse_status); - - int max_num_qubits = 0; - for (const int num : num_qubits) { - max_num_qubits = std::max(max_num_qubits, num); - } - - // create handles for simulator - cublasCreate(&cublas_handle_); - custatevecCreate(&custatevec_handle_); - - ComputeLarge(num_qubits, fused_circuits, pauli_sums, context, - &output_tensor); - - // destroy handles in sync with simulator lifetime - cublasDestroy(cublas_handle_); - custatevecDestroy(custatevec_handle_); - } - - private: - cublasHandle_t cublas_handle_; - custatevecHandle_t custatevec_handle_; - - // Define the GPU implementation that launches the CUDA kernel. - void ComputeLarge( - const std::vector& num_qubits, - const std::vector>>& fused_circuits, - const std::vector>& pauli_sums, - tensorflow::OpKernelContext* context, - tensorflow::TTypes::Matrix* output_tensor) { - // Instantiate qsim objects. - using Simulator = qsim::SimulatorCuStateVec; - using StateSpace = Simulator::StateSpace; - - // Launch the cuda kernel. - // Begin simulation. - int largest_nq = 1; - Simulator sim = Simulator(cublas_handle_, custatevec_handle_); - StateSpace ss = StateSpace(cublas_handle_, custatevec_handle_); - auto sv = ss.Create(largest_nq); - ss.SetStateZero(sv); - auto scratch = ss.Create(largest_nq); - - // Simulate programs one by one. Parallelizing over state vectors - // we no longer parallelize over circuits. Each time we encounter a - // a larger circuit we will grow the Statevector as necessary. - for (int i = 0; i < fused_circuits.size(); i++) { - int nq = num_qubits[i]; - - if (nq > largest_nq) { - // need to switch to larger statespace. - largest_nq = nq; - sv = ss.Create(largest_nq); - scratch = ss.Create(largest_nq); - } - // TODO: add heuristic here so that we do not always recompute - // the state if there is a possibility that circuit[i] and - // circuit[i + 1] produce the same state. - ss.SetStateZero(sv); - for (int j = 0; j < fused_circuits[i].size(); j++) { - qsim::ApplyFusedGate(sim, fused_circuits[i][j], sv); - } - for (int j = 0; j < pauli_sums[i].size(); j++) { - // (#679) Just ignore empty program - if (fused_circuits[i].size() == 0) { - (*output_tensor)(i, j) = -2.0; - continue; - } - float exp_v = 0.0; - OP_REQUIRES_OK(context, - ComputeExpectationQsim(pauli_sums[i][j], sim, ss, sv, - scratch, &exp_v)); - (*output_tensor)(i, j) = exp_v; - } - } - } -}; - -REGISTER_KERNEL_BUILDER( - Name("TfqSimulateExpectationCuquantum").Device(tensorflow::DEVICE_CPU), - TfqSimulateExpectationOpCuQuantum); - -REGISTER_OP("TfqSimulateExpectationCuquantum") - .Input("programs: string") - .Input("symbol_names: string") - .Input("symbol_values: float") - .Input("pauli_sums: string") - .Output("expectations: float") - .SetShapeFn([](tensorflow::shape_inference::InferenceContext* c) { - tensorflow::shape_inference::ShapeHandle programs_shape; - TF_RETURN_IF_ERROR(c->WithRank(c->input(0), 1, &programs_shape)); - - tensorflow::shape_inference::ShapeHandle symbol_names_shape; - TF_RETURN_IF_ERROR(c->WithRank(c->input(1), 1, &symbol_names_shape)); - - tensorflow::shape_inference::ShapeHandle symbol_values_shape; - TF_RETURN_IF_ERROR(c->WithRank(c->input(2), 2, &symbol_values_shape)); - - tensorflow::shape_inference::ShapeHandle pauli_sums_shape; - TF_RETURN_IF_ERROR(c->WithRank(c->input(3), 2, &pauli_sums_shape)); - - tensorflow::shape_inference::DimensionHandle output_rows = - c->Dim(programs_shape, 0); - tensorflow::shape_inference::DimensionHandle output_cols = - c->Dim(pauli_sums_shape, 1); - c->set_output(0, c->Matrix(output_rows, output_cols)); - - return tensorflow::Status::OK(); - }); - -} // namespace tfq diff --git a/tensorflow_quantum/core/ops/tfq_simulate_ops.py b/tensorflow_quantum/core/ops/tfq_simulate_ops.py index a68116c3e..17f1fd6bd 100644 --- a/tensorflow_quantum/core/ops/tfq_simulate_ops.py +++ b/tensorflow_quantum/core/ops/tfq_simulate_ops.py @@ -11,7 +11,7 @@ # 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. -# ============================================================================= +# ============================================================================== """Module to register python op gradient.""" import tensorflow as tf from tensorflow_quantum.core.ops.load_module import load_module diff --git a/tensorflow_quantum/core/ops/tfq_simulate_ops_cuda.py b/tensorflow_quantum/core/ops/tfq_simulate_ops_cuda.py deleted file mode 100644 index d1a2ca4d2..000000000 --- a/tensorflow_quantum/core/ops/tfq_simulate_ops_cuda.py +++ /dev/null @@ -1,44 +0,0 @@ -# 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. -# See the License for the specific language governing permissions and -# limitations under the License. -# ============================================================================= -"""Module to register cuda simulation python op.""" -import tensorflow as tf -from tensorflow_quantum.core.ops.load_module import load_module - -SIM_OP_MODULE = load_module("_tfq_simulate_ops_cuda.so") - - -def tfq_simulate_expectation(programs, symbol_names, symbol_values, pauli_sums): - """Calculates the expectation value of circuits wrt some operator(s). - Args: - programs: `tf.Tensor` of strings with shape [batch_size] containing - the string representations of the circuits to be executed. - symbol_names: `tf.Tensor` of strings with shape [n_params], which - is used to specify the order in which the values in - `symbol_values` should be placed inside of the circuits in - `programs`. - symbol_values: `tf.Tensor` of real numbers with shape - [batch_size, n_params] specifying parameter values to resolve - into the circuits specificed by programs, following the ordering - dictated by `symbol_names`. - pauli_sums: `tf.Tensor` of strings with shape [batch_size, n_ops] - containing the string representation of the operators that will - be used on all of the circuits in the expectation calculations. - Returns: - `tf.Tensor` with shape [batch_size, n_ops] that holds the - expectation value for each circuit with each op applied to it - (after resolving the corresponding parameters in). - """ - return SIM_OP_MODULE.tfq_simulate_expectation_cuda( - programs, symbol_names, tf.cast(symbol_values, tf.float32), pauli_sums) \ No newline at end of file diff --git a/tensorflow_quantum/core/ops/tfq_simulate_ops_cuquantum.py b/tensorflow_quantum/core/ops/tfq_simulate_ops_cuquantum.py deleted file mode 100644 index 785cce16c..000000000 --- a/tensorflow_quantum/core/ops/tfq_simulate_ops_cuquantum.py +++ /dev/null @@ -1,44 +0,0 @@ -# Copyright 2023 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. -# See the License for the specific language governing permissions and -# limitations under the License. -# ============================================================================= -"""Module to register cuQuantum simulation python op.""" -import tensorflow as tf -from tensorflow_quantum.core.ops.load_module import load_module - -SIM_OP_MODULE = load_module("_tfq_simulate_ops_cuquantum.so") - - -def tfq_simulate_expectation(programs, symbol_names, symbol_values, pauli_sums): - """Calculates the expectation value of circuits wrt some operator(s). - Args: - programs: `tf.Tensor` of strings with shape [batch_size] containing - the string representations of the circuits to be executed. - symbol_names: `tf.Tensor` of strings with shape [n_params], which - is used to specify the order in which the values in - `symbol_values` should be placed inside of the circuits in - `programs`. - symbol_values: `tf.Tensor` of real numbers with shape - [batch_size, n_params] specifying parameter values to resolve - into the circuits specificed by programs, following the ordering - dictated by `symbol_names`. - pauli_sums: `tf.Tensor` of strings with shape [batch_size, n_ops] - containing the string representation of the operators that will - be used on all of the circuits in the expectation calculations. - Returns: - `tf.Tensor` with shape [batch_size, n_ops] that holds the - expectation value for each circuit with each op applied to it - (after resolving the corresponding parameters in). - """ - return SIM_OP_MODULE.tfq_simulate_expectation_cuquantum( - programs, symbol_names, tf.cast(symbol_values, tf.float32), pauli_sums) \ No newline at end of file diff --git a/tensorflow_quantum/core/ops/tfq_simulate_ops_gpu_test.py b/tensorflow_quantum/core/ops/tfq_simulate_ops_gpu_test.py deleted file mode 100644 index eb1bc02f6..000000000 --- a/tensorflow_quantum/core/ops/tfq_simulate_ops_gpu_test.py +++ /dev/null @@ -1,139 +0,0 @@ -# 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. -# See the License for the specific language governing permissions and -# limitations under the License. -# ============================================================================= -"""Tests that specifically target tfq_simulate_ops_cu*.""" -import time -import numpy as np -import tensorflow as tf -import cirq - -from tensorflow_quantum.core.ops import tfq_simulate_ops -from tensorflow_quantum.core.ops import tfq_simulate_ops_cuda -from tensorflow_quantum.core.ops import tfq_simulate_ops_cuquantum -from tensorflow_quantum.python import util - - -def measure_average_runtime(fn, tag, num_samples=10): - """ - Measure the average runtime of a function. - - Args: - fn: A function to measure. - tag: A string to print. - num_samples: Number of samples to measure. - - Returns: - A tuple of (average runtime, function result). - """ - avg_time = [] - for _ in range(num_samples): - begin_time = time.time() - result = fn() - duration = time.time() - begin_time - avg_time.append(duration) - avg_time = sum(avg_time) / float(num_samples) - print(f"\n\t{tag} time: {avg_time}\n") - return avg_time, result - - -class SimulateExpectationGpuTest(tf.test.TestCase): - """Tests tfq_simulate_expectation.""" - - def test_simulate_expectation_cpu_vs_cuda(self): - """Make sure that cpu & gpu(cuda) ops have the same results.""" - n_qubits = 20 - batch_size = 5 - symbol_names = ['alpha'] - qubits = cirq.GridQubit.rect(1, n_qubits) - circuit_batch, resolver_batch = \ - util.random_symbol_circuit_resolver_batch( - qubits, symbol_names, batch_size) - - circuit_batch_tensor = util.convert_to_tensor(circuit_batch) - - symbol_values_array = np.array( - [[resolver[symbol] - for symbol in symbol_names] - for resolver in resolver_batch]) - - pauli_sums = util.random_pauli_sums(qubits, 3, batch_size) - pauli_sums_tensor = util.convert_to_tensor([[x] for x in pauli_sums]) - - cpu_avg_time, res_cpu = measure_average_runtime( - lambda: tfq_simulate_ops.tfq_simulate_expectation( - circuit_batch_tensor, symbol_names, - symbol_values_array.astype(np.float64), pauli_sums_tensor), - "CPU", - num_samples=100, - ) - - cuda_avg_time, res_cuda = measure_average_runtime( - lambda: tfq_simulate_ops_cuda.tfq_simulate_expectation( - circuit_batch_tensor, symbol_names, - symbol_values_array.astype(np.float64), pauli_sums_tensor), - "CUDA", - num_samples=100, - ) - - # The result should be the similar within a tolerance. - np.testing.assert_allclose(res_cpu, res_cuda, atol=1e-4) - - # CUDA op should be faster than CPU op. - self.assertGreater(cpu_avg_time, cuda_avg_time) - - def test_simulate_expectation_cpu_vs_cuquantum(self): - """Make sure that cpu & gpu(cuquantum) ops have the same results.""" - n_qubits = 20 - batch_size = 5 - symbol_names = ['alpha'] - qubits = cirq.GridQubit.rect(1, n_qubits) - circuit_batch, resolver_batch = \ - util.random_symbol_circuit_resolver_batch( - qubits, symbol_names, batch_size) - - circuit_batch_tensor = util.convert_to_tensor(circuit_batch) - - symbol_values_array = np.array( - [[resolver[symbol] - for symbol in symbol_names] - for resolver in resolver_batch]) - - pauli_sums = util.random_pauli_sums(qubits, 3, batch_size) - pauli_sums_tensor = util.convert_to_tensor([[x] for x in pauli_sums]) - - cpu_avg_time, res_cpu = measure_average_runtime( - lambda: tfq_simulate_ops.tfq_simulate_expectation( - circuit_batch_tensor, symbol_names, - symbol_values_array.astype(np.float64), pauli_sums_tensor), - "CPU", - num_samples=100, - ) - - cuda_avg_time, res_cuda = measure_average_runtime( - lambda: tfq_simulate_ops_cuquantum.tfq_simulate_expectation( - circuit_batch_tensor, symbol_names, - symbol_values_array.astype(np.float64), pauli_sums_tensor), - "cuQuantum", - num_samples=100, - ) - - # The result should be the similar within a tolerance. - np.testing.assert_allclose(res_cpu, res_cuda, atol=1e-4) - - # cuQuantum op should be faster than CPU op. - self.assertGreater(cpu_avg_time, cuda_avg_time) - - -if __name__ == "__main__": - tf.test.main() diff --git a/tensorflow_quantum/core/ops/tfq_simulate_ops_test.py b/tensorflow_quantum/core/ops/tfq_simulate_ops_test.py index cb1d05f10..4cdbe42e5 100644 --- a/tensorflow_quantum/core/ops/tfq_simulate_ops_test.py +++ b/tensorflow_quantum/core/ops/tfq_simulate_ops_test.py @@ -11,12 +11,11 @@ # 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. -# ============================================================================= +# ============================================================================== """Tests that specifically target tfq_simulate_ops.""" # Remove PYTHONPATH collisions for protobuf. # pylint: disable=wrong-import-position import sys - NEW_PATH = [x for x in sys.path if 'com_google_protobuf' not in x] sys.path = NEW_PATH # pylint: enable=wrong-import-position diff --git a/tensorflow_quantum/core/ops/tfq_unitary_op.py b/tensorflow_quantum/core/ops/tfq_unitary_op.py index 775516896..5db7005db 100644 --- a/tensorflow_quantum/core/ops/tfq_unitary_op.py +++ b/tensorflow_quantum/core/ops/tfq_unitary_op.py @@ -11,7 +11,7 @@ # 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. -# ============================================================================= +# ============================================================================== """Module to register python op gradient.""" import tensorflow as tf from tensorflow_quantum.core.ops import tfq_utility_ops diff --git a/tensorflow_quantum/core/ops/tfq_unitary_op_test.py b/tensorflow_quantum/core/ops/tfq_unitary_op_test.py index 04f8c576a..212094056 100644 --- a/tensorflow_quantum/core/ops/tfq_unitary_op_test.py +++ b/tensorflow_quantum/core/ops/tfq_unitary_op_test.py @@ -11,12 +11,11 @@ # 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. -# ============================================================================= +# ============================================================================== """Tests that specifically target tfq_unitary_op.""" # Remove PYTHONPATH collisions for protobuf. # pylint: disable=wrong-import-position import sys - NEW_PATH = [x for x in sys.path if 'com_google_protobuf' not in x] sys.path = NEW_PATH # pylint: enable=wrong-import-position diff --git a/tensorflow_quantum/core/ops/tfq_utility_ops.py b/tensorflow_quantum/core/ops/tfq_utility_ops.py index 2d0d45def..e560f579c 100644 --- a/tensorflow_quantum/core/ops/tfq_utility_ops.py +++ b/tensorflow_quantum/core/ops/tfq_utility_ops.py @@ -11,7 +11,7 @@ # 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. -# ============================================================================= +# ============================================================================== """Expose bindings for tfq utility ops.""" import tensorflow as tf from tensorflow_quantum.core.ops.load_module import load_module diff --git a/tensorflow_quantum/core/ops/tfq_utility_ops_test.py b/tensorflow_quantum/core/ops/tfq_utility_ops_test.py index 806437176..00c5ff791 100644 --- a/tensorflow_quantum/core/ops/tfq_utility_ops_test.py +++ b/tensorflow_quantum/core/ops/tfq_utility_ops_test.py @@ -11,12 +11,11 @@ # 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. -# ============================================================================= +# ============================================================================== """Tests for tfq utility ops.""" # Remove PYTHONPATH collisions for protobuf. # pylint: disable=wrong-import-position import sys - NEW_PATH = [x for x in sys.path if 'com_google_protobuf' not in x] sys.path = NEW_PATH # pylint: enable=wrong-import-position diff --git a/tensorflow_quantum/core/proto/__init__.py b/tensorflow_quantum/core/proto/__init__.py index be0da7259..bdbbd7a51 100644 --- a/tensorflow_quantum/core/proto/__init__.py +++ b/tensorflow_quantum/core/proto/__init__.py @@ -11,4 +11,4 @@ # 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. -# ============================================================================= +# ============================================================================== diff --git a/tensorflow_quantum/core/serialize/__init__.py b/tensorflow_quantum/core/serialize/__init__.py index eebbe0156..6ee678723 100644 --- a/tensorflow_quantum/core/serialize/__init__.py +++ b/tensorflow_quantum/core/serialize/__init__.py @@ -11,7 +11,7 @@ # 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. -# ============================================================================= +# ============================================================================== """Module for tfq.core.serialize.*""" from tensorflow_quantum.core.serialize.serializer import (serialize_circuit, deserialize_circuit, diff --git a/tensorflow_quantum/core/serialize/op_deserializer_test.py b/tensorflow_quantum/core/serialize/op_deserializer_test.py index 634561d2b..ce1748b65 100644 --- a/tensorflow_quantum/core/serialize/op_deserializer_test.py +++ b/tensorflow_quantum/core/serialize/op_deserializer_test.py @@ -15,7 +15,6 @@ # Remove PYTHONPATH collisions for protobuf. # pylint: disable=wrong-import-position import sys - NEW_PATH = [x for x in sys.path if 'com_google_protobuf' not in x] sys.path = NEW_PATH # pylint: enable=wrong-import-position diff --git a/tensorflow_quantum/core/serialize/op_serializer_test.py b/tensorflow_quantum/core/serialize/op_serializer_test.py index 432dd117f..a485091e7 100644 --- a/tensorflow_quantum/core/serialize/op_serializer_test.py +++ b/tensorflow_quantum/core/serialize/op_serializer_test.py @@ -15,7 +15,6 @@ # Remove PYTHONPATH collisions for protobuf. # pylint: disable=wrong-import-position import sys - NEW_PATH = [x for x in sys.path if 'com_google_protobuf' not in x] sys.path = NEW_PATH # pylint: enable=wrong-import-position diff --git a/tensorflow_quantum/core/serialize/serializable_gate_set_test.py b/tensorflow_quantum/core/serialize/serializable_gate_set_test.py index e8f94b1db..1e6fd9861 100644 --- a/tensorflow_quantum/core/serialize/serializable_gate_set_test.py +++ b/tensorflow_quantum/core/serialize/serializable_gate_set_test.py @@ -15,7 +15,6 @@ # Remove PYTHONPATH collisions for protobuf. # pylint: disable=wrong-import-position import sys - NEW_PATH = [x for x in sys.path if 'com_google_protobuf' not in x] sys.path = NEW_PATH # pylint: enable=wrong-import-position diff --git a/tensorflow_quantum/core/serialize/serializer.py b/tensorflow_quantum/core/serialize/serializer.py index 80ddb6672..73b38ee16 100644 --- a/tensorflow_quantum/core/serialize/serializer.py +++ b/tensorflow_quantum/core/serialize/serializer.py @@ -11,7 +11,7 @@ # 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. -# ============================================================================= +# ============================================================================== """A basic serializer used to serialize/deserialize Cirq circuits for tfq.""" # TODO(pmassey / anyone): determine if this should be kept as globals. import copy diff --git a/tensorflow_quantum/core/serialize/serializer_test.py b/tensorflow_quantum/core/serialize/serializer_test.py index d4e1667e6..a43da0cf0 100644 --- a/tensorflow_quantum/core/serialize/serializer_test.py +++ b/tensorflow_quantum/core/serialize/serializer_test.py @@ -11,12 +11,11 @@ # 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. -# ============================================================================= +# ============================================================================== """Module to test serialization core.""" # Remove PYTHONPATH collisions for protobuf. # pylint: disable=wrong-import-position import sys - NEW_PATH = [x for x in sys.path if 'com_google_protobuf' not in x] sys.path = NEW_PATH # pylint: enable=wrong-import-position @@ -100,7 +99,7 @@ def _build_op_proto(gate_id, arg_names, arg_vals, qubit_ids): if isinstance(arg_vals[i], str) else \ program_pb2.Arg( arg_value=program_pb2.ArgValue( - float_value=np.round(float(arg_vals[i]), 6)))) + float_value=np.round(float(arg_vals[i]), 6)))) \ for i in range(len(arg_vals))}, qubits=[program_pb2.Qubit( id=q_id) for q_id in qubit_ids])]) diff --git a/tensorflow_quantum/datasets/__init__.py b/tensorflow_quantum/datasets/__init__.py index 8ec6a1e5a..de1192fd4 100644 --- a/tensorflow_quantum/datasets/__init__.py +++ b/tensorflow_quantum/datasets/__init__.py @@ -11,7 +11,7 @@ # 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. -# ============================================================================= +# ============================================================================== """Experimental location for interesting quantum datasets.""" # Import to the tensorflow_quantum.datasets.* level.""" from tensorflow_quantum.datasets.cluster_state import excited_cluster_states diff --git a/tensorflow_quantum/datasets/cluster_state.py b/tensorflow_quantum/datasets/cluster_state.py index 59c35997f..2c7f5a909 100644 --- a/tensorflow_quantum/datasets/cluster_state.py +++ b/tensorflow_quantum/datasets/cluster_state.py @@ -11,7 +11,7 @@ # 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. -# ============================================================================= +# ============================================================================== """Toy dataset showing boilerplate code for a cluster state example.""" import numpy as np import cirq diff --git a/tensorflow_quantum/datasets/cluster_state_test.py b/tensorflow_quantum/datasets/cluster_state_test.py index 0b675d145..49e75309d 100644 --- a/tensorflow_quantum/datasets/cluster_state_test.py +++ b/tensorflow_quantum/datasets/cluster_state_test.py @@ -11,12 +11,11 @@ # 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. -# ============================================================================= +# ============================================================================== """Test the cluster state dataset.""" # Remove PYTHONPATH collisions for protobuf. # pylint: disable=wrong-import-position import sys - NEW_PATH = [x for x in sys.path if 'com_google_protobuf' not in x] sys.path = NEW_PATH # pylint: enable=wrong-import-position diff --git a/tensorflow_quantum/datasets/spin_system.py b/tensorflow_quantum/datasets/spin_system.py index 3d53d5eae..4a180a68f 100644 --- a/tensorflow_quantum/datasets/spin_system.py +++ b/tensorflow_quantum/datasets/spin_system.py @@ -11,7 +11,7 @@ # 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. -# ============================================================================= +# ============================================================================== """Quantum datasets for quantum many-body spin systems.""" from collections import namedtuple diff --git a/tensorflow_quantum/datasets/spin_system_test.py b/tensorflow_quantum/datasets/spin_system_test.py index 917fd0f73..3dac53a80 100644 --- a/tensorflow_quantum/datasets/spin_system_test.py +++ b/tensorflow_quantum/datasets/spin_system_test.py @@ -11,12 +11,11 @@ # 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. -# ============================================================================= +# ============================================================================== """Test the spin system dataset""" # Remove PYTHONPATH collisions for protobuf. # pylint: disable=wrong-import-position import sys - NEW_PATH = [x for x in sys.path if 'com_google_protobuf' not in x] sys.path = NEW_PATH # pylint: enable=wrong-import-position diff --git a/tensorflow_quantum/python/__init__.py b/tensorflow_quantum/python/__init__.py index a66da1f02..afc3cd168 100644 --- a/tensorflow_quantum/python/__init__.py +++ b/tensorflow_quantum/python/__init__.py @@ -11,7 +11,7 @@ # 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. -# ============================================================================= +# ============================================================================== """Module definitions for tensorflow_quantum.python.util.*""" from tensorflow_quantum.python.util import ( # Utility functions. diff --git a/tensorflow_quantum/python/differentiators/__init__.py b/tensorflow_quantum/python/differentiators/__init__.py index 8ce0a4889..ab386b22c 100644 --- a/tensorflow_quantum/python/differentiators/__init__.py +++ b/tensorflow_quantum/python/differentiators/__init__.py @@ -11,7 +11,7 @@ # 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. -# ============================================================================= +# ============================================================================== """Module functions for tfq.differentiators.*""" from tensorflow_quantum.python.differentiators.adjoint import ( diff --git a/tensorflow_quantum/python/differentiators/adjoint.py b/tensorflow_quantum/python/differentiators/adjoint.py index 44b8e9da6..95ff5554e 100644 --- a/tensorflow_quantum/python/differentiators/adjoint.py +++ b/tensorflow_quantum/python/differentiators/adjoint.py @@ -11,7 +11,7 @@ # 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. -# ============================================================================= +# ============================================================================== """Compute gradients by combining function values linearly.""" import tensorflow as tf diff --git a/tensorflow_quantum/python/differentiators/adjoint_test.py b/tensorflow_quantum/python/differentiators/adjoint_test.py index 640a87d30..ffbf9173e 100644 --- a/tensorflow_quantum/python/differentiators/adjoint_test.py +++ b/tensorflow_quantum/python/differentiators/adjoint_test.py @@ -11,12 +11,11 @@ # 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. -# ============================================================================= +# ============================================================================== """Tests for the differentiator abstract class.""" # Remove PYTHONPATH collisions for protobuf. # pylint: disable=wrong-import-position import sys - NEW_PATH = [x for x in sys.path if 'com_google_protobuf' not in x] sys.path = NEW_PATH # pylint: enable=wrong-import-position diff --git a/tensorflow_quantum/python/differentiators/differentiator.py b/tensorflow_quantum/python/differentiators/differentiator.py index bb3668a92..4b1d597ed 100644 --- a/tensorflow_quantum/python/differentiators/differentiator.py +++ b/tensorflow_quantum/python/differentiators/differentiator.py @@ -11,7 +11,7 @@ # 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. -# ============================================================================= +# ============================================================================== """Testing consistency in values across differentiation methods.""" import abc import inspect diff --git a/tensorflow_quantum/python/differentiators/differentiator_test.py b/tensorflow_quantum/python/differentiators/differentiator_test.py index b61b2a323..6f21f2e18 100644 --- a/tensorflow_quantum/python/differentiators/differentiator_test.py +++ b/tensorflow_quantum/python/differentiators/differentiator_test.py @@ -11,12 +11,11 @@ # 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. -# ============================================================================= +# ============================================================================== """Tests for the differentiator abstract class.""" # Remove PYTHONPATH collisions for protobuf. # pylint: disable=wrong-import-position import sys - NEW_PATH = [x for x in sys.path if 'com_google_protobuf' not in x] sys.path = NEW_PATH # pylint: enable=wrong-import-position diff --git a/tensorflow_quantum/python/differentiators/gradient_test.py b/tensorflow_quantum/python/differentiators/gradient_test.py index b85506b0d..f666ad801 100644 --- a/tensorflow_quantum/python/differentiators/gradient_test.py +++ b/tensorflow_quantum/python/differentiators/gradient_test.py @@ -11,12 +11,11 @@ # 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. -# ============================================================================= +# ============================================================================== """Testing for gradient calculation consistency in TFQ.""" # Remove PYTHONPATH collisions for protobuf. # pylint: disable=wrong-import-position import sys - NEW_PATH = [x for x in sys.path if 'com_google_protobuf' not in x] sys.path = NEW_PATH # pylint: enable=wrong-import-position diff --git a/tensorflow_quantum/python/differentiators/linear_combination.py b/tensorflow_quantum/python/differentiators/linear_combination.py index cee6959bd..dabbd9e34 100644 --- a/tensorflow_quantum/python/differentiators/linear_combination.py +++ b/tensorflow_quantum/python/differentiators/linear_combination.py @@ -11,7 +11,7 @@ # 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. -# ============================================================================= +# ============================================================================== """Compute gradients by combining function values linearly.""" import numbers diff --git a/tensorflow_quantum/python/differentiators/linear_combination_test.py b/tensorflow_quantum/python/differentiators/linear_combination_test.py index ecb223816..f46b086e4 100644 --- a/tensorflow_quantum/python/differentiators/linear_combination_test.py +++ b/tensorflow_quantum/python/differentiators/linear_combination_test.py @@ -11,12 +11,11 @@ # 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. -# ============================================================================= +# ============================================================================== """Basic tests for the LinearCombinationDifferentiator""" # Remove PYTHONPATH collisions for protobuf. # pylint: disable=wrong-import-position import sys - NEW_PATH = [x for x in sys.path if 'com_google_protobuf' not in x] sys.path = NEW_PATH # pylint: enable=wrong-import-position diff --git a/tensorflow_quantum/python/differentiators/parameter_shift.py b/tensorflow_quantum/python/differentiators/parameter_shift.py index 8a4ef9c3a..bf1631bba 100644 --- a/tensorflow_quantum/python/differentiators/parameter_shift.py +++ b/tensorflow_quantum/python/differentiators/parameter_shift.py @@ -11,7 +11,7 @@ # 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. -# ============================================================================= +# ============================================================================== """Compute analytic gradients by using general parameter-shift rule. """ import tensorflow as tf diff --git a/tensorflow_quantum/python/differentiators/parameter_shift_test.py b/tensorflow_quantum/python/differentiators/parameter_shift_test.py index d40b2257e..5a0846f25 100644 --- a/tensorflow_quantum/python/differentiators/parameter_shift_test.py +++ b/tensorflow_quantum/python/differentiators/parameter_shift_test.py @@ -11,12 +11,11 @@ # 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. -# ============================================================================= +# ============================================================================== """Basic tests for the ParameterShift differentiator""" # Remove PYTHONPATH collisions for protobuf. # pylint: disable=wrong-import-position import sys - NEW_PATH = [x for x in sys.path if 'com_google_protobuf' not in x] sys.path = NEW_PATH # pylint: enable=wrong-import-position diff --git a/tensorflow_quantum/python/differentiators/parameter_shift_util.py b/tensorflow_quantum/python/differentiators/parameter_shift_util.py index 34889c69a..266b3b68e 100644 --- a/tensorflow_quantum/python/differentiators/parameter_shift_util.py +++ b/tensorflow_quantum/python/differentiators/parameter_shift_util.py @@ -11,7 +11,7 @@ # 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. -# ============================================================================= +# ============================================================================== """Util functions for general parameter-shift rule. """ import numpy as np import tensorflow as tf diff --git a/tensorflow_quantum/python/differentiators/parameter_shift_util_test.py b/tensorflow_quantum/python/differentiators/parameter_shift_util_test.py index a8178be6e..8c1083a10 100644 --- a/tensorflow_quantum/python/differentiators/parameter_shift_util_test.py +++ b/tensorflow_quantum/python/differentiators/parameter_shift_util_test.py @@ -11,12 +11,11 @@ # 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. -# ============================================================================= +# ============================================================================== """Basic tests for utility functions for ParameterShift""" # Remove PYTHONPATH collisions for protobuf. # pylint: disable=wrong-import-position import sys - NEW_PATH = [x for x in sys.path if 'com_google_protobuf' not in x] sys.path = NEW_PATH # pylint: enable=wrong-import-position diff --git a/tensorflow_quantum/python/layers/__init__.py b/tensorflow_quantum/python/layers/__init__.py index 3de402f8d..88f2e5dad 100644 --- a/tensorflow_quantum/python/layers/__init__.py +++ b/tensorflow_quantum/python/layers/__init__.py @@ -11,7 +11,7 @@ # 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. -# ============================================================================= +# ============================================================================== """Module definitions for tensorflow_quantum.python.layers.*""" # Utility layers. from tensorflow_quantum.python.layers.circuit_construction import ( diff --git a/tensorflow_quantum/python/layers/circuit_construction/__init__.py b/tensorflow_quantum/python/layers/circuit_construction/__init__.py index 765f26e83..0c5ded5c5 100644 --- a/tensorflow_quantum/python/layers/circuit_construction/__init__.py +++ b/tensorflow_quantum/python/layers/circuit_construction/__init__.py @@ -11,7 +11,7 @@ # 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. -# ============================================================================= +# ============================================================================== """Module for tfq.python.layers.circuit_construction.*""" # pylint: disable=line-too-long diff --git a/tensorflow_quantum/python/layers/circuit_construction/elementary.py b/tensorflow_quantum/python/layers/circuit_construction/elementary.py index 13574c435..66714f800 100644 --- a/tensorflow_quantum/python/layers/circuit_construction/elementary.py +++ b/tensorflow_quantum/python/layers/circuit_construction/elementary.py @@ -11,7 +11,7 @@ # 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. -# ============================================================================= +# ============================================================================== """Elementary layers, such as the AddCircuit layer.""" import numpy as np import tensorflow as tf diff --git a/tensorflow_quantum/python/layers/circuit_construction/elementary_test.py b/tensorflow_quantum/python/layers/circuit_construction/elementary_test.py index 6d07cd2e1..38577dbe9 100644 --- a/tensorflow_quantum/python/layers/circuit_construction/elementary_test.py +++ b/tensorflow_quantum/python/layers/circuit_construction/elementary_test.py @@ -11,12 +11,11 @@ # 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. -# ============================================================================= +# ============================================================================== """Tests for the elementary layers.""" # Remove PYTHONPATH collisions for protobuf. # pylint: disable=wrong-import-position import sys - NEW_PATH = [x for x in sys.path if 'com_google_protobuf' not in x] sys.path = NEW_PATH # pylint: enable=wrong-import-position diff --git a/tensorflow_quantum/python/layers/circuit_executors/__init__.py b/tensorflow_quantum/python/layers/circuit_executors/__init__.py index 0ce744835..74d26d3e0 100644 --- a/tensorflow_quantum/python/layers/circuit_executors/__init__.py +++ b/tensorflow_quantum/python/layers/circuit_executors/__init__.py @@ -11,7 +11,7 @@ # 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. -# ============================================================================= +# ============================================================================== """Module for tfq.python.layers.circuit_executors.*""" # pylint: disable=line-too-long diff --git a/tensorflow_quantum/python/layers/circuit_executors/expectation.py b/tensorflow_quantum/python/layers/circuit_executors/expectation.py index 35d0c1b50..c3b1d913e 100644 --- a/tensorflow_quantum/python/layers/circuit_executors/expectation.py +++ b/tensorflow_quantum/python/layers/circuit_executors/expectation.py @@ -11,7 +11,7 @@ # 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. -# ============================================================================= +# ============================================================================== """A tf.keras.layer that ingests programs and outputs expectation values.""" import numbers diff --git a/tensorflow_quantum/python/layers/circuit_executors/expectation_test.py b/tensorflow_quantum/python/layers/circuit_executors/expectation_test.py index 1ef7b99fc..e4489e763 100644 --- a/tensorflow_quantum/python/layers/circuit_executors/expectation_test.py +++ b/tensorflow_quantum/python/layers/circuit_executors/expectation_test.py @@ -11,12 +11,11 @@ # 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. -# ============================================================================= +# ============================================================================== """Tests for tensorflow_quantum.layers.circuit_executors.expectation.""" # Remove PYTHONPATH collisions for protobuf. # pylint: disable=wrong-import-position import sys - NEW_PATH = [x for x in sys.path if 'com_google_protobuf' not in x] sys.path = NEW_PATH # pylint: enable=wrong-import-position diff --git a/tensorflow_quantum/python/layers/circuit_executors/input_checks.py b/tensorflow_quantum/python/layers/circuit_executors/input_checks.py index 9855b5b74..b73fbde26 100644 --- a/tensorflow_quantum/python/layers/circuit_executors/input_checks.py +++ b/tensorflow_quantum/python/layers/circuit_executors/input_checks.py @@ -11,7 +11,7 @@ # 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. -# ============================================================================= +# ============================================================================== """Input checks common to circuit execution layers.""" import numpy as np import sympy diff --git a/tensorflow_quantum/python/layers/circuit_executors/input_checks_test.py b/tensorflow_quantum/python/layers/circuit_executors/input_checks_test.py index 304b365e1..affbd55d7 100644 --- a/tensorflow_quantum/python/layers/circuit_executors/input_checks_test.py +++ b/tensorflow_quantum/python/layers/circuit_executors/input_checks_test.py @@ -11,12 +11,11 @@ # 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. -# ============================================================================= +# ============================================================================== """Tests for tensorflow_quantum.layers.circuit_executors.input_checks.""" # Remove PYTHONPATH collisions for protobuf. # pylint: disable=wrong-import-position import sys - NEW_PATH = [x for x in sys.path if 'com_google_protobuf' not in x] sys.path = NEW_PATH # pylint: enable=wrong-import-position diff --git a/tensorflow_quantum/python/layers/circuit_executors/sample.py b/tensorflow_quantum/python/layers/circuit_executors/sample.py index 750885c20..616d811bc 100644 --- a/tensorflow_quantum/python/layers/circuit_executors/sample.py +++ b/tensorflow_quantum/python/layers/circuit_executors/sample.py @@ -11,7 +11,7 @@ # 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. -# ============================================================================= +# ============================================================================== """A tf.keras.layer that ingests programs and outputs bitstring samples.""" import numbers diff --git a/tensorflow_quantum/python/layers/circuit_executors/sample_test.py b/tensorflow_quantum/python/layers/circuit_executors/sample_test.py index 7103759b4..b83848132 100644 --- a/tensorflow_quantum/python/layers/circuit_executors/sample_test.py +++ b/tensorflow_quantum/python/layers/circuit_executors/sample_test.py @@ -11,12 +11,11 @@ # 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. -# ============================================================================= +# ============================================================================== """Tests for the sample layer.""" # Remove PYTHONPATH collisions for protobuf. # pylint: disable=wrong-import-position import sys - NEW_PATH = [x for x in sys.path if 'com_google_protobuf' not in x] sys.path = NEW_PATH # pylint: enable=wrong-import-position diff --git a/tensorflow_quantum/python/layers/circuit_executors/sampled_expectation.py b/tensorflow_quantum/python/layers/circuit_executors/sampled_expectation.py index fa434e332..ebc750e59 100644 --- a/tensorflow_quantum/python/layers/circuit_executors/sampled_expectation.py +++ b/tensorflow_quantum/python/layers/circuit_executors/sampled_expectation.py @@ -11,7 +11,7 @@ # 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. -# ============================================================================= +# ============================================================================== """A tf.keras.layer that ingests programs and outputs sampled expectation values .""" import numbers diff --git a/tensorflow_quantum/python/layers/circuit_executors/sampled_expectation_test.py b/tensorflow_quantum/python/layers/circuit_executors/sampled_expectation_test.py index b027cfbe5..4e96a5c49 100644 --- a/tensorflow_quantum/python/layers/circuit_executors/sampled_expectation_test.py +++ b/tensorflow_quantum/python/layers/circuit_executors/sampled_expectation_test.py @@ -11,12 +11,11 @@ # 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. -# ============================================================================= +# ============================================================================== """Tests for tensorflow_quantum.layers.circuit_executors.sampled_expectation.""" # Remove PYTHONPATH collisions for protobuf. # pylint: disable=wrong-import-position import sys - NEW_PATH = [x for x in sys.path if 'com_google_protobuf' not in x] sys.path = NEW_PATH # pylint: enable=wrong-import-position diff --git a/tensorflow_quantum/python/layers/circuit_executors/state.py b/tensorflow_quantum/python/layers/circuit_executors/state.py index f2b213ee1..6f979139a 100644 --- a/tensorflow_quantum/python/layers/circuit_executors/state.py +++ b/tensorflow_quantum/python/layers/circuit_executors/state.py @@ -11,7 +11,7 @@ # 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. -# ============================================================================= +# ============================================================================== """A tf.keras.layer that ingests programs and parameters and outputs a state.""" import tensorflow as tf diff --git a/tensorflow_quantum/python/layers/circuit_executors/state_test.py b/tensorflow_quantum/python/layers/circuit_executors/state_test.py index 8904014b7..8addb0d8f 100644 --- a/tensorflow_quantum/python/layers/circuit_executors/state_test.py +++ b/tensorflow_quantum/python/layers/circuit_executors/state_test.py @@ -11,12 +11,11 @@ # 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. -# ============================================================================= +# ============================================================================== """Tests for tensorflow_quantum.layers.circuit_executors.state.""" # Remove PYTHONPATH collisions for protobuf. # pylint: disable=wrong-import-position import sys - NEW_PATH = [x for x in sys.path if 'com_google_protobuf' not in x] sys.path = NEW_PATH # pylint: enable=wrong-import-position diff --git a/tensorflow_quantum/python/layers/circuit_executors/unitary.py b/tensorflow_quantum/python/layers/circuit_executors/unitary.py index 73bd40c83..34e9385f7 100644 --- a/tensorflow_quantum/python/layers/circuit_executors/unitary.py +++ b/tensorflow_quantum/python/layers/circuit_executors/unitary.py @@ -11,7 +11,7 @@ # 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. -# ============================================================================= +# ============================================================================== """A tf.keras.layer that ingests programs and outputs a unitary.""" import tensorflow as tf diff --git a/tensorflow_quantum/python/layers/circuit_executors/unitary_test.py b/tensorflow_quantum/python/layers/circuit_executors/unitary_test.py index 30a84eecd..7330c807f 100644 --- a/tensorflow_quantum/python/layers/circuit_executors/unitary_test.py +++ b/tensorflow_quantum/python/layers/circuit_executors/unitary_test.py @@ -11,12 +11,11 @@ # 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. -# ============================================================================= +# ============================================================================== """Tests for tensorflow_quantum.layers.circuit_executors.unitary.""" # Remove PYTHONPATH collisions for protobuf. # pylint: disable=wrong-import-position import sys - NEW_PATH = [x for x in sys.path if 'com_google_protobuf' not in x] sys.path = NEW_PATH # pylint: enable=wrong-import-position diff --git a/tensorflow_quantum/python/layers/high_level/__init__.py b/tensorflow_quantum/python/layers/high_level/__init__.py index 19e1a000b..2f7bd6580 100644 --- a/tensorflow_quantum/python/layers/high_level/__init__.py +++ b/tensorflow_quantum/python/layers/high_level/__init__.py @@ -11,7 +11,7 @@ # 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. -# ============================================================================= +# ============================================================================== """Module for tfq.python.layers.high_level.*""" # pylint: disable=line-too-long diff --git a/tensorflow_quantum/python/layers/high_level/controlled_pqc.py b/tensorflow_quantum/python/layers/high_level/controlled_pqc.py index a61b4b50e..588a8aa59 100644 --- a/tensorflow_quantum/python/layers/high_level/controlled_pqc.py +++ b/tensorflow_quantum/python/layers/high_level/controlled_pqc.py @@ -11,7 +11,7 @@ # 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. -# ============================================================================= +# ============================================================================== """Module for tfq.python.layers.high_level.controlled_pqc layer.""" import numbers import numpy as np diff --git a/tensorflow_quantum/python/layers/high_level/controlled_pqc_test.py b/tensorflow_quantum/python/layers/high_level/controlled_pqc_test.py index 11f7e1e59..0d9e76e7e 100644 --- a/tensorflow_quantum/python/layers/high_level/controlled_pqc_test.py +++ b/tensorflow_quantum/python/layers/high_level/controlled_pqc_test.py @@ -11,12 +11,11 @@ # 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. -# ============================================================================= +# ============================================================================== """Test module for tfq.python.layers.high_level.controlled_pqc layer.""" # Remove PYTHONPATH collisions for protobuf. # pylint: disable=wrong-import-position import sys - NEW_PATH = [x for x in sys.path if 'com_google_protobuf' not in x] sys.path = NEW_PATH # pylint: enable=wrong-import-position diff --git a/tensorflow_quantum/python/layers/high_level/noisy_controlled_pqc.py b/tensorflow_quantum/python/layers/high_level/noisy_controlled_pqc.py index 9a3b86eec..f3239e443 100644 --- a/tensorflow_quantum/python/layers/high_level/noisy_controlled_pqc.py +++ b/tensorflow_quantum/python/layers/high_level/noisy_controlled_pqc.py @@ -11,7 +11,7 @@ # 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. -# ============================================================================= +# ============================================================================== """Module for tfq.python.layers.high_level.noisy_controlled_pqc layer.""" import numbers import numpy as np diff --git a/tensorflow_quantum/python/layers/high_level/noisy_controlled_pqc_test.py b/tensorflow_quantum/python/layers/high_level/noisy_controlled_pqc_test.py index 111f2c506..57ecf6cff 100644 --- a/tensorflow_quantum/python/layers/high_level/noisy_controlled_pqc_test.py +++ b/tensorflow_quantum/python/layers/high_level/noisy_controlled_pqc_test.py @@ -11,12 +11,11 @@ # 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. -# ============================================================================= +# ============================================================================== """Test module for tfq.python.layers.high_level.controlled_pqc layer.""" # Remove PYTHONPATH collisions for protobuf. # pylint: disable=wrong-import-position import sys - NEW_PATH = [x for x in sys.path if 'com_google_protobuf' not in x] sys.path = NEW_PATH # pylint: enable=wrong-import-position diff --git a/tensorflow_quantum/python/layers/high_level/noisy_pqc.py b/tensorflow_quantum/python/layers/high_level/noisy_pqc.py index 2c6796231..05cb535e8 100644 --- a/tensorflow_quantum/python/layers/high_level/noisy_pqc.py +++ b/tensorflow_quantum/python/layers/high_level/noisy_pqc.py @@ -11,7 +11,7 @@ # 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. -# ============================================================================= +# ============================================================================== """Module for tfq.python.layers.high_level.noisy_pqc layer.""" import numbers import numpy as np diff --git a/tensorflow_quantum/python/layers/high_level/noisy_pqc_test.py b/tensorflow_quantum/python/layers/high_level/noisy_pqc_test.py index ea56115c0..112838912 100644 --- a/tensorflow_quantum/python/layers/high_level/noisy_pqc_test.py +++ b/tensorflow_quantum/python/layers/high_level/noisy_pqc_test.py @@ -11,12 +11,11 @@ # 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. -# ============================================================================= +# ============================================================================== """Test module for tfq.python.layers.high_level.noisy_pqc layer.""" # Remove PYTHONPATH collisions for protobuf. # pylint: disable=wrong-import-position import sys - NEW_PATH = [x for x in sys.path if 'com_google_protobuf' not in x] sys.path = NEW_PATH # pylint: enable=wrong-import-position diff --git a/tensorflow_quantum/python/layers/high_level/pqc.py b/tensorflow_quantum/python/layers/high_level/pqc.py index 229ded921..e370be294 100644 --- a/tensorflow_quantum/python/layers/high_level/pqc.py +++ b/tensorflow_quantum/python/layers/high_level/pqc.py @@ -11,7 +11,7 @@ # 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. -# ============================================================================= +# ============================================================================== """Module for tfq.python.layers.high_level.pqc layer.""" import numbers import numpy as np diff --git a/tensorflow_quantum/python/layers/high_level/pqc_test.py b/tensorflow_quantum/python/layers/high_level/pqc_test.py index 33b74fedb..e6d831c66 100644 --- a/tensorflow_quantum/python/layers/high_level/pqc_test.py +++ b/tensorflow_quantum/python/layers/high_level/pqc_test.py @@ -11,12 +11,11 @@ # 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. -# ============================================================================= +# ============================================================================== """Test module for tfq.python.layers.high_level.pqc layer.""" # Remove PYTHONPATH collisions for protobuf. # pylint: disable=wrong-import-position import sys - NEW_PATH = [x for x in sys.path if 'com_google_protobuf' not in x] sys.path = NEW_PATH # pylint: enable=wrong-import-position diff --git a/tensorflow_quantum/python/optimizers/__init__.py b/tensorflow_quantum/python/optimizers/__init__.py index 1a1d97d41..d93023205 100755 --- a/tensorflow_quantum/python/optimizers/__init__.py +++ b/tensorflow_quantum/python/optimizers/__init__.py @@ -11,7 +11,7 @@ # 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. -# ============================================================================= +# ============================================================================== """Module definitions for tensorflow_quantum.python.optimizers.*""" # Quantum circuit specific optimizers. diff --git a/tensorflow_quantum/python/optimizers/rotosolve_minimizer.py b/tensorflow_quantum/python/optimizers/rotosolve_minimizer.py index 3376cd20e..5bf23f6a0 100755 --- a/tensorflow_quantum/python/optimizers/rotosolve_minimizer.py +++ b/tensorflow_quantum/python/optimizers/rotosolve_minimizer.py @@ -11,7 +11,7 @@ # 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. -# ============================================================================= +# ============================================================================== """The rotosolve minimization algorithm.""" import numpy as np import tensorflow as tf diff --git a/tensorflow_quantum/python/optimizers/rotosolve_minimizer_test.py b/tensorflow_quantum/python/optimizers/rotosolve_minimizer_test.py index 0687f4ee3..1d3a2965f 100755 --- a/tensorflow_quantum/python/optimizers/rotosolve_minimizer_test.py +++ b/tensorflow_quantum/python/optimizers/rotosolve_minimizer_test.py @@ -11,12 +11,11 @@ # 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. -# ============================================================================= +# ============================================================================== """Test module for tfq.python.optimizers.rotosolve_minimizer optimizer.""" # Remove PYTHONPATH collisions for protobuf. # pylint: disable=wrong-import-position import sys - NEW_PATH = [x for x in sys.path if 'com_google_protobuf' not in x] sys.path = NEW_PATH # pylint: enable=wrong-import-position diff --git a/tensorflow_quantum/python/optimizers/spsa_minimizer.py b/tensorflow_quantum/python/optimizers/spsa_minimizer.py index 10a915ee0..471b46d9e 100644 --- a/tensorflow_quantum/python/optimizers/spsa_minimizer.py +++ b/tensorflow_quantum/python/optimizers/spsa_minimizer.py @@ -11,7 +11,7 @@ # 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. -# ============================================================================= +# ============================================================================== """The SPSA minimization algorithm.""" import tensorflow as tf import numpy as np diff --git a/tensorflow_quantum/python/optimizers/spsa_minimizer_test.py b/tensorflow_quantum/python/optimizers/spsa_minimizer_test.py index 33dcb180e..1de86d86c 100644 --- a/tensorflow_quantum/python/optimizers/spsa_minimizer_test.py +++ b/tensorflow_quantum/python/optimizers/spsa_minimizer_test.py @@ -11,12 +11,11 @@ # 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. -# ============================================================================= +# ============================================================================== """Test module for tfq.python.optimizers.spsa_minimizer optimizer.""" # Remove PYTHONPATH collisions for protobuf. # pylint: disable=wrong-import-position import sys - NEW_PATH = [x for x in sys.path if 'com_google_protobuf' not in x] sys.path = NEW_PATH # pylint: enable=wrong-import-position diff --git a/tensorflow_quantum/python/quantum_context.py b/tensorflow_quantum/python/quantum_context.py index 1a869bdea..44c01cdeb 100644 --- a/tensorflow_quantum/python/quantum_context.py +++ b/tensorflow_quantum/python/quantum_context.py @@ -11,7 +11,7 @@ # 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. -# ============================================================================= +# ============================================================================== """A global singleton object for defining op execution parameters.""" import multiprocessing diff --git a/tensorflow_quantum/python/quantum_context_test.py b/tensorflow_quantum/python/quantum_context_test.py index 7f7a62d58..5b219b1dc 100644 --- a/tensorflow_quantum/python/quantum_context_test.py +++ b/tensorflow_quantum/python/quantum_context_test.py @@ -11,12 +11,11 @@ # 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. -# ============================================================================= +# ============================================================================== """Tests for quantum_context functions.""" # Remove PYTHONPATH collisions for protobuf. # pylint: disable=wrong-import-position import sys - NEW_PATH = [x for x in sys.path if 'com_google_protobuf' not in x] sys.path = NEW_PATH # pylint: enable=wrong-import-position diff --git a/tensorflow_quantum/python/util.py b/tensorflow_quantum/python/util.py index c736a403f..92ebeabee 100644 --- a/tensorflow_quantum/python/util.py +++ b/tensorflow_quantum/python/util.py @@ -11,7 +11,7 @@ # 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. -# ============================================================================= +# ============================================================================== """A collection of helper functions which are useful in places in TFQ.""" import itertools diff --git a/tensorflow_quantum/python/util_test.py b/tensorflow_quantum/python/util_test.py index 0e1159806..3d4e2dd76 100644 --- a/tensorflow_quantum/python/util_test.py +++ b/tensorflow_quantum/python/util_test.py @@ -11,12 +11,11 @@ # 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. -# ============================================================================= +# ============================================================================== """Tests for TFQ utilities.""" # Remove PYTHONPATH collisions for protobuf. # pylint: disable=wrong-import-position import sys - NEW_PATH = [x for x in sys.path if 'com_google_protobuf' not in x] sys.path = NEW_PATH # pylint: enable=wrong-import-position From 97a1818a6b131d0ceef1f3b945bdc62c6a072d55 Mon Sep 17 00:00:00 2001 From: Michael Broughton Date: Mon, 12 Jun 2023 14:00:36 -0700 Subject: [PATCH 04/50] Revert "Merge pull request #772 from Sinestro38/fix_license" This reverts commit 140277d10ca63b541acb481ecaf899f91c846e5b, reversing changes made to 7131f9e4d2d289e51f9705161b29c45159da1921. --- scripts/ci_install.sh | 4 +- .../tfq_simulate_expectation_op_cuda.cu.cc | 207 ++++++++++++++++ ...fq_simulate_expectation_op_cuquantum.cu.cc | 221 ++++++++++++++++++ .../core/ops/tfq_simulate_ops_cuda.py | 45 ++++ .../core/ops/tfq_simulate_ops_cuquantum.py | 45 ++++ .../core/ops/tfq_simulate_ops_gpu_test.py | 133 +++++++++++ 6 files changed, 653 insertions(+), 2 deletions(-) create mode 100644 tensorflow_quantum/core/ops/tfq_simulate_expectation_op_cuda.cu.cc create mode 100644 tensorflow_quantum/core/ops/tfq_simulate_expectation_op_cuquantum.cu.cc create mode 100644 tensorflow_quantum/core/ops/tfq_simulate_ops_cuda.py create mode 100644 tensorflow_quantum/core/ops/tfq_simulate_ops_cuquantum.py create mode 100644 tensorflow_quantum/core/ops/tfq_simulate_ops_gpu_test.py diff --git a/scripts/ci_install.sh b/scripts/ci_install.sh index a0ed81c8c..04e6b3159 100755 --- a/scripts/ci_install.sh +++ b/scripts/ci_install.sh @@ -13,7 +13,7 @@ # See the License for the specific language governing permissions and # limitations under the License. # ============================================================================== -wget https://github.com/bazelbuild/bazel/releases/download/5.1.0/bazel_5.1.0-linux-x86_64.deb -sudo dpkg -i bazel_5.1.0-linux-x86_64.deb +wget https://github.com/bazelbuild/bazel/releases/download/5.3.0/bazel_5.3.0-linux-x86_64.deb +sudo dpkg -i bazel_5.3.0-linux-x86_64.deb pip install --upgrade pip setuptools wheel pip install -r requirements.txt \ No newline at end of file diff --git a/tensorflow_quantum/core/ops/tfq_simulate_expectation_op_cuda.cu.cc b/tensorflow_quantum/core/ops/tfq_simulate_expectation_op_cuda.cu.cc new file mode 100644 index 000000000..271df7f5c --- /dev/null +++ b/tensorflow_quantum/core/ops/tfq_simulate_expectation_op_cuda.cu.cc @@ -0,0 +1,207 @@ +/* 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. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include +#include + +#include + +#include "../qsim/lib/circuit.h" +#include "../qsim/lib/gate_appl.h" +#include "../qsim/lib/gates_cirq.h" +#include "../qsim/lib/gates_qsim.h" +#include "../qsim/lib/seqfor.h" +#include "../qsim/lib/simulator_cuda.h" +#include "../qsim/lib/statespace_cuda.h" +#include "tensorflow/core/framework/op_kernel.h" +#include "tensorflow/core/framework/shape_inference.h" +#include "tensorflow/core/framework/tensor_shape.h" +#include "tensorflow/core/lib/core/error_codes.pb.h" +#include "tensorflow/core/lib/core/status.h" +#include "tensorflow/core/lib/core/threadpool.h" +#include "tensorflow/core/platform/mutex.h" +#include "tensorflow_quantum/core/ops/parse_context.h" +#include "tensorflow_quantum/core/proto/pauli_sum.pb.h" +#include "tensorflow_quantum/core/proto/program.pb.h" +#include "tensorflow_quantum/core/src/util_qsim.h" + +namespace tfq { + +using ::tensorflow::Status; +using ::tfq::proto::PauliSum; +using ::tfq::proto::Program; + +typedef qsim::Cirq::GateCirq QsimGate; +typedef qsim::Circuit QsimCircuit; + + +class TfqSimulateExpectationOpCuda : public tensorflow::OpKernel { + public: + explicit TfqSimulateExpectationOpCuda(tensorflow::OpKernelConstruction* context) + : OpKernel(context) {} + + void Compute(tensorflow::OpKernelContext* context) override { + // TODO (mbbrough): add more dimension checks for other inputs here. + const int num_inputs = context->num_inputs(); + OP_REQUIRES(context, num_inputs == 4, + tensorflow::errors::InvalidArgument(absl::StrCat( + "Expected 4 inputs, got ", num_inputs, " inputs."))); + + // Create the output Tensor. + const int output_dim_batch_size = context->input(0).dim_size(0); + const int output_dim_op_size = context->input(3).dim_size(1); + tensorflow::TensorShape output_shape; + output_shape.AddDim(output_dim_batch_size); + output_shape.AddDim(output_dim_op_size); + + tensorflow::Tensor* output = nullptr; + tensorflow::AllocatorAttributes alloc_attr; + alloc_attr.set_on_host(true); + alloc_attr.set_gpu_compatible(true); + OP_REQUIRES_OK(context, context->allocate_output(0, output_shape, &output, + alloc_attr)); + auto output_tensor = output->matrix(); + // Parse program protos. + std::vector programs; + std::vector num_qubits; + std::vector> pauli_sums; + OP_REQUIRES_OK(context, GetProgramsAndNumQubits(context, &programs, + &num_qubits, &pauli_sums)); + + std::vector maps; + OP_REQUIRES_OK(context, GetSymbolMaps(context, &maps)); + + OP_REQUIRES(context, programs.size() == maps.size(), + tensorflow::errors::InvalidArgument(absl::StrCat( + "Number of circuits and symbol_values do not match. Got ", + programs.size(), " circuits and ", maps.size(), + " symbol values."))); + + // Construct qsim circuits. + std::vector qsim_circuits(programs.size(), QsimCircuit()); + std::vector>> fused_circuits( + programs.size(), std::vector>({})); + + Status parse_status = Status(); + auto p_lock = tensorflow::mutex(); + auto construct_f = [&](int start, int end) { + for (int i = start; i < end; i++) { + Status local = + QsimCircuitFromProgram(programs[i], maps[i], num_qubits[i], + &qsim_circuits[i], &fused_circuits[i]); + NESTED_FN_STATUS_SYNC(parse_status, local, p_lock); + } + }; + + const int num_cycles = 1000; + context->device()->tensorflow_cpu_worker_threads()->workers->ParallelFor( + programs.size(), num_cycles, construct_f); + OP_REQUIRES_OK(context, parse_status); + + int max_num_qubits = 0; + for (const int num : num_qubits) { + max_num_qubits = std::max(max_num_qubits, num); + } + ComputeLarge(num_qubits, fused_circuits, pauli_sums, context, + &output_tensor); + } + + private: + int num_threads_in_sim_; + int block_count_; + + // Define the GPU implementation that launches the CUDA kernel. + void ComputeLarge( + const std::vector& num_qubits, + const std::vector>>& fused_circuits, + const std::vector>& pauli_sums, + tensorflow::OpKernelContext* context, + tensorflow::TTypes::Matrix* output_tensor) { + // Instantiate qsim objects. + using Simulator = qsim::SimulatorCUDA; + using StateSpace = Simulator::StateSpace; + // Begin simulation with default parameters. + int largest_nq = 1; + Simulator sim = Simulator(); + StateSpace ss = StateSpace(StateSpace::Parameter()); + auto sv = ss.Create(largest_nq); + auto scratch = ss.Create(largest_nq); + + // Simulate programs one by one. Parallelizing over state vectors + // we no longer parallelize over circuits. Each time we encounter a + // a larger circuit we will grow the Statevector as necessary. + for (int i = 0; i < fused_circuits.size(); i++) { + int nq = num_qubits[i]; + + if (nq > largest_nq) { + // need to switch to larger statespace. + largest_nq = nq; + sv = ss.Create(largest_nq); + scratch = ss.Create(largest_nq); + } + // TODO: add heuristic here so that we do not always recompute + // the state if there is a possibility that circuit[i] and + // circuit[i + 1] produce the same state. + ss.SetStateZero(sv); + for (int j = 0; j < fused_circuits[i].size(); j++) { + qsim::ApplyFusedGate(sim, fused_circuits[i][j], sv); + } + for (int j = 0; j < pauli_sums[i].size(); j++) { + // (#679) Just ignore empty program + if (fused_circuits[i].size() == 0) { + (*output_tensor)(i, j) = -2.0; + continue; + } + float exp_v = 0.0; + OP_REQUIRES_OK(context, + ComputeExpectationQsim(pauli_sums[i][j], sim, ss, sv, + scratch, &exp_v)); + (*output_tensor)(i, j) = exp_v; + } + } + } + +}; + +REGISTER_KERNEL_BUILDER( + Name("TfqSimulateExpectationCuda").Device(tensorflow::DEVICE_CPU), + TfqSimulateExpectationOpCuda); + +REGISTER_OP("TfqSimulateExpectationCuda") + .Input("programs: string") + .Input("symbol_names: string") + .Input("symbol_values: float") + .Input("pauli_sums: string") + .Output("expectations: float") + .SetShapeFn([](tensorflow::shape_inference::InferenceContext* c) { + tensorflow::shape_inference::ShapeHandle programs_shape; + TF_RETURN_IF_ERROR(c->WithRank(c->input(0), 1, &programs_shape)); + + tensorflow::shape_inference::ShapeHandle symbol_names_shape; + TF_RETURN_IF_ERROR(c->WithRank(c->input(1), 1, &symbol_names_shape)); + + tensorflow::shape_inference::ShapeHandle symbol_values_shape; + TF_RETURN_IF_ERROR(c->WithRank(c->input(2), 2, &symbol_values_shape)); + + tensorflow::shape_inference::ShapeHandle pauli_sums_shape; + TF_RETURN_IF_ERROR(c->WithRank(c->input(3), 2, &pauli_sums_shape)); + + tensorflow::shape_inference::DimensionHandle output_rows = + c->Dim(programs_shape, 0); + tensorflow::shape_inference::DimensionHandle output_cols = + c->Dim(pauli_sums_shape, 1); + c->set_output(0, c->Matrix(output_rows, output_cols)); + + return ::tensorflow::Status(); + }); + +} // namespace tfq diff --git a/tensorflow_quantum/core/ops/tfq_simulate_expectation_op_cuquantum.cu.cc b/tensorflow_quantum/core/ops/tfq_simulate_expectation_op_cuquantum.cu.cc new file mode 100644 index 000000000..c1fb0143a --- /dev/null +++ b/tensorflow_quantum/core/ops/tfq_simulate_expectation_op_cuquantum.cu.cc @@ -0,0 +1,221 @@ +/* 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. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include +#include + +#include + +#include "../cuquantum_libs/include/custatevec.h" +#include "../qsim/lib/circuit.h" +#include "../qsim/lib/gate_appl.h" +#include "../qsim/lib/gates_cirq.h" +#include "../qsim/lib/gates_qsim.h" +#include "../qsim/lib/seqfor.h" +#include "../qsim/lib/simulator_custatevec.h" +#include "../qsim/lib/statespace_custatevec.h" +#include "tensorflow/core/framework/op_kernel.h" +#include "tensorflow/core/framework/shape_inference.h" +#include "tensorflow/core/framework/tensor_shape.h" +#include "tensorflow/core/lib/core/error_codes.pb.h" +#include "tensorflow/core/lib/core/status.h" +#include "tensorflow/core/lib/core/threadpool.h" +#include "tensorflow/core/platform/mutex.h" +#include "tensorflow_quantum/core/ops/parse_context.h" +#include "tensorflow_quantum/core/proto/pauli_sum.pb.h" +#include "tensorflow_quantum/core/proto/program.pb.h" +#include "tensorflow_quantum/core/src/util_qsim.h" + +namespace tfq { + +using ::tensorflow::Status; +using ::tfq::proto::PauliSum; +using ::tfq::proto::Program; + +typedef qsim::Cirq::GateCirq QsimGate; +typedef qsim::Circuit QsimCircuit; + + +class TfqSimulateExpectationOpCuQuantum : public tensorflow::OpKernel { + public: + explicit TfqSimulateExpectationOpCuQuantum(tensorflow::OpKernelConstruction* context) + : OpKernel(context) {} + + void Compute(tensorflow::OpKernelContext* context) override { + + // TODO (mbbrough): add more dimension checks for other inputs here. + const int num_inputs = context->num_inputs(); + OP_REQUIRES(context, num_inputs == 4, + tensorflow::errors::InvalidArgument(absl::StrCat( + "Expected 4 inputs, got ", num_inputs, " inputs."))); + + // Create the output Tensor. + const int output_dim_batch_size = context->input(0).dim_size(0); + const int output_dim_op_size = context->input(3).dim_size(1); + tensorflow::TensorShape output_shape; + output_shape.AddDim(output_dim_batch_size); + output_shape.AddDim(output_dim_op_size); + + tensorflow::Tensor* output = nullptr; + tensorflow::AllocatorAttributes alloc_attr; + alloc_attr.set_on_host(true); // why?? + alloc_attr.set_gpu_compatible(true); + OP_REQUIRES_OK(context, context->allocate_output(0, output_shape, &output, + alloc_attr)); + auto output_tensor = output->matrix(); + // Parse program protos. + std::vector programs; + std::vector num_qubits; + std::vector> pauli_sums; // why is this a vector of vectors?? + OP_REQUIRES_OK(context, GetProgramsAndNumQubits(context, &programs, + &num_qubits, &pauli_sums)); + + std::vector maps; + OP_REQUIRES_OK(context, GetSymbolMaps(context, &maps)); + + OP_REQUIRES(context, programs.size() == maps.size(), + tensorflow::errors::InvalidArgument(absl::StrCat( + "Number of circuits and symbol_values do not match. Got ", + programs.size(), " circuits and ", maps.size(), + " symbol values."))); + + // Construct qsim circuits. + std::vector qsim_circuits(programs.size(), QsimCircuit()); + std::vector>> fused_circuits( + programs.size(), std::vector>({})); + + Status parse_status = Status::OK(); + auto p_lock = tensorflow::mutex(); + auto construct_f = [&](int start, int end) { + for (int i = start; i < end; i++) { + Status local = + QsimCircuitFromProgram(programs[i], maps[i], num_qubits[i], + &qsim_circuits[i], &fused_circuits[i]); + NESTED_FN_STATUS_SYNC(parse_status, local, p_lock); + } + }; + + const int num_cycles = 1000; + context->device()->tensorflow_cpu_worker_threads()->workers->ParallelFor( + programs.size(), num_cycles, construct_f); + OP_REQUIRES_OK(context, parse_status); + + int max_num_qubits = 0; + for (const int num : num_qubits) { + max_num_qubits = std::max(max_num_qubits, num); + } + + // create handles for simulator + cublasCreate(&cublas_handle_); + custatevecCreate(&custatevec_handle_); + + ComputeLarge(num_qubits, fused_circuits, pauli_sums, context, + &output_tensor); + + // destroy handles in sync with simulator lifetime + cublasDestroy(cublas_handle_); + custatevecDestroy(custatevec_handle_); + } + + private: + cublasHandle_t cublas_handle_; + custatevecHandle_t custatevec_handle_; + + // Define the GPU implementation that launches the CUDA kernel. + void ComputeLarge( + const std::vector& num_qubits, + const std::vector>>& fused_circuits, + const std::vector>& pauli_sums, + tensorflow::OpKernelContext* context, + tensorflow::TTypes::Matrix* output_tensor) { + // Instantiate qsim objects. + using Simulator = qsim::SimulatorCuStateVec; + using StateSpace = Simulator::StateSpace; + + + // Launch the cuda kernel. + // Begin simulation. + int largest_nq = 1; + Simulator sim = Simulator(cublas_handle_, custatevec_handle_); + StateSpace ss = StateSpace(cublas_handle_, custatevec_handle_); + auto sv = ss.Create(largest_nq); + ss.SetStateZero(sv); + auto scratch = ss.Create(largest_nq); + + // Simulate programs one by one. Parallelizing over state vectors + // we no longer parallelize over circuits. Each time we encounter a + // a larger circuit we will grow the Statevector as necessary. + for (int i = 0; i < fused_circuits.size(); i++) { + int nq = num_qubits[i]; + + if (nq > largest_nq) { + // need to switch to larger statespace. + largest_nq = nq; + sv = ss.Create(largest_nq); + scratch = ss.Create(largest_nq); + } + // TODO: add heuristic here so that we do not always recompute + // the state if there is a possibility that circuit[i] and + // circuit[i + 1] produce the same state. + ss.SetStateZero(sv); + for (int j = 0; j < fused_circuits[i].size(); j++) { + qsim::ApplyFusedGate(sim, fused_circuits[i][j], sv); + } + for (int j = 0; j < pauli_sums[i].size(); j++) { + // (#679) Just ignore empty program + if (fused_circuits[i].size() == 0) { + (*output_tensor)(i, j) = -2.0; + continue; + } + float exp_v = 0.0; + OP_REQUIRES_OK(context, + ComputeExpectationQsim(pauli_sums[i][j], sim, ss, sv, + scratch, &exp_v)); + (*output_tensor)(i, j) = exp_v; + } + } + } +}; + +REGISTER_KERNEL_BUILDER( + Name("TfqSimulateExpectationCuquantum").Device(tensorflow::DEVICE_CPU), + TfqSimulateExpectationOpCuQuantum); + +REGISTER_OP("TfqSimulateExpectationCuquantum") + .Input("programs: string") + .Input("symbol_names: string") + .Input("symbol_values: float") + .Input("pauli_sums: string") + .Output("expectations: float") + .SetShapeFn([](tensorflow::shape_inference::InferenceContext* c) { + tensorflow::shape_inference::ShapeHandle programs_shape; + TF_RETURN_IF_ERROR(c->WithRank(c->input(0), 1, &programs_shape)); + + tensorflow::shape_inference::ShapeHandle symbol_names_shape; + TF_RETURN_IF_ERROR(c->WithRank(c->input(1), 1, &symbol_names_shape)); + + tensorflow::shape_inference::ShapeHandle symbol_values_shape; + TF_RETURN_IF_ERROR(c->WithRank(c->input(2), 2, &symbol_values_shape)); + + tensorflow::shape_inference::ShapeHandle pauli_sums_shape; + TF_RETURN_IF_ERROR(c->WithRank(c->input(3), 2, &pauli_sums_shape)); + + tensorflow::shape_inference::DimensionHandle output_rows = + c->Dim(programs_shape, 0); + tensorflow::shape_inference::DimensionHandle output_cols = + c->Dim(pauli_sums_shape, 1); + c->set_output(0, c->Matrix(output_rows, output_cols)); + + return tensorflow::Status::OK(); + }); + +} // namespace tfq diff --git a/tensorflow_quantum/core/ops/tfq_simulate_ops_cuda.py b/tensorflow_quantum/core/ops/tfq_simulate_ops_cuda.py new file mode 100644 index 000000000..e6860b028 --- /dev/null +++ b/tensorflow_quantum/core/ops/tfq_simulate_ops_cuda.py @@ -0,0 +1,45 @@ +# 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. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== +"""Module to register cuda simulation python op.""" +import os +import tensorflow as tf +from tensorflow_quantum.core.ops.load_module import load_module + +SIM_OP_MODULE = load_module("_tfq_simulate_ops_cuda.so") + + +def tfq_simulate_expectation(programs, symbol_names, symbol_values, pauli_sums): + """Calculates the expectation value of circuits wrt some operator(s). + Args: + programs: `tf.Tensor` of strings with shape [batch_size] containing + the string representations of the circuits to be executed. + symbol_names: `tf.Tensor` of strings with shape [n_params], which + is used to specify the order in which the values in + `symbol_values` should be placed inside of the circuits in + `programs`. + symbol_values: `tf.Tensor` of real numbers with shape + [batch_size, n_params] specifying parameter values to resolve + into the circuits specificed by programs, following the ordering + dictated by `symbol_names`. + pauli_sums: `tf.Tensor` of strings with shape [batch_size, n_ops] + containing the string representation of the operators that will + be used on all of the circuits in the expectation calculations. + Returns: + `tf.Tensor` with shape [batch_size, n_ops] that holds the + expectation value for each circuit with each op applied to it + (after resolving the corresponding parameters in). + """ + return SIM_OP_MODULE.tfq_simulate_expectation_cuda( + programs, symbol_names, tf.cast(symbol_values, tf.float32), pauli_sums) \ No newline at end of file diff --git a/tensorflow_quantum/core/ops/tfq_simulate_ops_cuquantum.py b/tensorflow_quantum/core/ops/tfq_simulate_ops_cuquantum.py new file mode 100644 index 000000000..127d4f56b --- /dev/null +++ b/tensorflow_quantum/core/ops/tfq_simulate_ops_cuquantum.py @@ -0,0 +1,45 @@ +# Copyright 2023 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. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== +"""Module to register cuQuantum simulation python op.""" +import os +import tensorflow as tf +from tensorflow_quantum.core.ops.load_module import load_module + +SIM_OP_MODULE = load_module("_tfq_simulate_ops_cuquantum.so") + + +def tfq_simulate_expectation(programs, symbol_names, symbol_values, pauli_sums): + """Calculates the expectation value of circuits wrt some operator(s). + Args: + programs: `tf.Tensor` of strings with shape [batch_size] containing + the string representations of the circuits to be executed. + symbol_names: `tf.Tensor` of strings with shape [n_params], which + is used to specify the order in which the values in + `symbol_values` should be placed inside of the circuits in + `programs`. + symbol_values: `tf.Tensor` of real numbers with shape + [batch_size, n_params] specifying parameter values to resolve + into the circuits specificed by programs, following the ordering + dictated by `symbol_names`. + pauli_sums: `tf.Tensor` of strings with shape [batch_size, n_ops] + containing the string representation of the operators that will + be used on all of the circuits in the expectation calculations. + Returns: + `tf.Tensor` with shape [batch_size, n_ops] that holds the + expectation value for each circuit with each op applied to it + (after resolving the corresponding parameters in). + """ + return SIM_OP_MODULE.tfq_simulate_expectation_cuquantum( + programs, symbol_names, tf.cast(symbol_values, tf.float32), pauli_sums) \ No newline at end of file diff --git a/tensorflow_quantum/core/ops/tfq_simulate_ops_gpu_test.py b/tensorflow_quantum/core/ops/tfq_simulate_ops_gpu_test.py new file mode 100644 index 000000000..62517be22 --- /dev/null +++ b/tensorflow_quantum/core/ops/tfq_simulate_ops_gpu_test.py @@ -0,0 +1,133 @@ +# 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. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== +"""Tests that specifically target tfq_simulate_ops_cu*.""" +import os +import time +import numpy as np +from absl.testing import parameterized +import tensorflow as tf +import cirq + +from tensorflow_quantum.core.ops import tfq_simulate_ops +from tensorflow_quantum.core.ops import tfq_simulate_ops_cuda +from tensorflow_quantum.core.ops import tfq_simulate_ops_cuquantum +from tensorflow_quantum.python import util + +def measure_average_runtime(fn, tag, num_samples=10): + avg_time = [] + for _ in range(num_samples): + begin_time = time.time() + result = fn() + duration = time.time() - begin_time + avg_time.append(duration) + avg_time = sum(avg_time) / float(num_samples) + print(f"\n\t{tag} time: {avg_time}\n") + return avg_time, result + + +class SimulateExpectationGpuTest(tf.test.TestCase): + """Tests tfq_simulate_expectation.""" + + def test_simulate_expectation_cpu_vs_cuda(self): + """Make sure that cpu & gpu(cuda) ops have the same results.""" + n_qubits = 20 + batch_size = 5 + symbol_names = ['alpha'] + qubits = cirq.GridQubit.rect(1, n_qubits) + circuit_batch, resolver_batch = \ + util.random_symbol_circuit_resolver_batch( + qubits, symbol_names, batch_size) + + circuit_batch_tensor = util.convert_to_tensor(circuit_batch) + + symbol_values_array = np.array( + [[resolver[symbol] + for symbol in symbol_names] + for resolver in resolver_batch]) + + pauli_sums = util.random_pauli_sums(qubits, 3, batch_size) + pauli_sums_tensor = util.convert_to_tensor([[x] for x in pauli_sums]) + + cpu_avg_time, res_cpu = measure_average_runtime( + lambda: tfq_simulate_ops.tfq_simulate_expectation( + circuit_batch_tensor, + symbol_names, symbol_values_array.astype(np.float64), + pauli_sums_tensor), + "CPU", + num_samples=100, + ) + + cuda_avg_time, res_cuda = measure_average_runtime( + lambda: tfq_simulate_ops_cuda.tfq_simulate_expectation( + circuit_batch_tensor, + symbol_names, symbol_values_array.astype(np.float64), + pauli_sums_tensor), + "CUDA", + num_samples=100, + ) + + # The result should be the similar within a tolerance. + np.testing.assert_allclose(res_cpu, res_cuda, atol=1e-4) + + # CUDA op should be faster than CPU op. + self.assertGreater(cpu_avg_time, cuda_avg_time) + + def test_simulate_expectation_cpu_vs_cuquantum(self): + """Make sure that cpu & gpu(cuquantum) ops have the same results.""" + n_qubits = 20 + batch_size = 5 + symbol_names = ['alpha'] + qubits = cirq.GridQubit.rect(1, n_qubits) + circuit_batch, resolver_batch = \ + util.random_symbol_circuit_resolver_batch( + qubits, symbol_names, batch_size) + + circuit_batch_tensor = util.convert_to_tensor(circuit_batch) + + symbol_values_array = np.array( + [[resolver[symbol] + for symbol in symbol_names] + for resolver in resolver_batch]) + + pauli_sums = util.random_pauli_sums(qubits, 3, batch_size) + pauli_sums_tensor = util.convert_to_tensor([[x] for x in pauli_sums]) + + cpu_avg_time, res_cpu = measure_average_runtime( + lambda: tfq_simulate_ops.tfq_simulate_expectation( + circuit_batch_tensor, + symbol_names, symbol_values_array.astype(np.float64), + pauli_sums_tensor), + "CPU", + num_samples=100, + + ) + + cuda_avg_time, res_cuda = measure_average_runtime( + lambda: tfq_simulate_ops_cuquantum.tfq_simulate_expectation( + circuit_batch_tensor, + symbol_names, symbol_values_array.astype(np.float64), + pauli_sums_tensor), + "cuQuantum", + num_samples=100, + ) + + # The result should be the similar within a tolerance. + np.testing.assert_allclose(res_cpu, res_cuda, atol=1e-4) + + # cuQuantum op should be faster than CPU op. + self.assertGreater(cpu_avg_time, cuda_avg_time) + +if __name__ == "__main__": + tf.test.main() \ No newline at end of file From dde0bcee5cf4e0c39861268041f9f4a5bb7973e8 Mon Sep 17 00:00:00 2001 From: Michael Broughton Date: Mon, 12 Jun 2023 14:08:21 -0700 Subject: [PATCH 05/50] Revert "fix ubuntu version to 20.04" This reverts commit 803622aa2f59983b81086dc07d562aca0c955f2b. --- .github/workflows/ci.yaml | 14 ++++++++------ .github/workflows/cirq_compatibility.yaml | 2 +- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 7e6f1a21a..b37f194e8 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -5,7 +5,7 @@ on: [pull_request] jobs: lint: name: Lint check - runs-on: ubuntu-18.04 + runs-on: ubuntu-latest steps: - uses: actions/checkout@v1 - uses: actions/setup-python@v1 @@ -19,7 +19,7 @@ jobs: format: name: Formatting check - runs-on: ubuntu-18.04 + runs-on: ubuntu-latest steps: - uses: actions/checkout@v1 @@ -27,6 +27,8 @@ jobs: with: python-version: '3.8' architecture: 'x64' + - name: get ubuntu version + run: lsb_release -a - name: Install Format tools run: pip install --upgrade pip setuptools; pip install -r requirements.txt; sudo apt-get install -y clang-format-6.0 - name: Format Check @@ -34,7 +36,7 @@ jobs: wheel-build: name: Wheel test - runs-on: ubuntu-18.04 + runs-on: ubuntu-latest steps: - uses: actions/checkout@v1 @@ -53,7 +55,7 @@ jobs: bazel-tests: name: Library tests - runs-on: ubuntu-18.04 + runs-on: ubuntu-latest needs: [lint, format] steps: @@ -71,7 +73,7 @@ jobs: leak-tests: name: Memory Leak tests - runs-on: ubuntu-18.04 + runs-on: ubuntu-latest needs: [lint, format] steps: @@ -89,7 +91,7 @@ jobs: tutorials-test: name: Tutorial tests - runs-on: ubuntu-18.04 + runs-on: ubuntu-latest needs: [lint, format, wheel-build] steps: diff --git a/.github/workflows/cirq_compatibility.yaml b/.github/workflows/cirq_compatibility.yaml index f5e5b9629..246ff918d 100644 --- a/.github/workflows/cirq_compatibility.yaml +++ b/.github/workflows/cirq_compatibility.yaml @@ -7,7 +7,7 @@ on: jobs: consistency: name: Nightly Compatibility - runs-on: ubuntu-16.04 + runs-on: ubuntu-latest steps: - uses: actions/checkout@v1 - uses: actions/setup-python@v1 From 849c5e006284a4d4109f5c775346bce68b87df85 Mon Sep 17 00:00:00 2001 From: Michael Broughton Date: Mon, 12 Jun 2023 14:08:24 -0700 Subject: [PATCH 06/50] Revert "[debug] get ubuntu version of runner" This reverts commit 8002690bcba9c4bdf28c961f38d2a89cd38f14dc. --- .github/workflows/ci.yaml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index b37f194e8..a004beee3 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -27,8 +27,6 @@ jobs: with: python-version: '3.8' architecture: 'x64' - - name: get ubuntu version - run: lsb_release -a - name: Install Format tools run: pip install --upgrade pip setuptools; pip install -r requirements.txt; sudo apt-get install -y clang-format-6.0 - name: Format Check From e70b9eb7bc3d98ddab1e96e70bdd31768f3dc53f Mon Sep 17 00:00:00 2001 From: Michael Broughton Date: Mon, 12 Jun 2023 14:08:30 -0700 Subject: [PATCH 07/50] Revert "update ubuntu github runner from 18.04 to latest" This reverts commit 471573ae6883f767efe61d20f5fa7a88de60c012. --- .github/workflows/ci.yaml | 12 ++++++------ .github/workflows/cirq_compatibility.yaml | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index a004beee3..7e6f1a21a 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -5,7 +5,7 @@ on: [pull_request] jobs: lint: name: Lint check - runs-on: ubuntu-latest + runs-on: ubuntu-18.04 steps: - uses: actions/checkout@v1 - uses: actions/setup-python@v1 @@ -19,7 +19,7 @@ jobs: format: name: Formatting check - runs-on: ubuntu-latest + runs-on: ubuntu-18.04 steps: - uses: actions/checkout@v1 @@ -34,7 +34,7 @@ jobs: wheel-build: name: Wheel test - runs-on: ubuntu-latest + runs-on: ubuntu-18.04 steps: - uses: actions/checkout@v1 @@ -53,7 +53,7 @@ jobs: bazel-tests: name: Library tests - runs-on: ubuntu-latest + runs-on: ubuntu-18.04 needs: [lint, format] steps: @@ -71,7 +71,7 @@ jobs: leak-tests: name: Memory Leak tests - runs-on: ubuntu-latest + runs-on: ubuntu-18.04 needs: [lint, format] steps: @@ -89,7 +89,7 @@ jobs: tutorials-test: name: Tutorial tests - runs-on: ubuntu-latest + runs-on: ubuntu-18.04 needs: [lint, format, wheel-build] steps: diff --git a/.github/workflows/cirq_compatibility.yaml b/.github/workflows/cirq_compatibility.yaml index 246ff918d..f5e5b9629 100644 --- a/.github/workflows/cirq_compatibility.yaml +++ b/.github/workflows/cirq_compatibility.yaml @@ -7,7 +7,7 @@ on: jobs: consistency: name: Nightly Compatibility - runs-on: ubuntu-latest + runs-on: ubuntu-16.04 steps: - uses: actions/checkout@v1 - uses: actions/setup-python@v1 From 2aac191db7318b9f53d50b002d82b75ac52de5d3 Mon Sep 17 00:00:00 2001 From: Michael Broughton Date: Mon, 12 Jun 2023 14:08:35 -0700 Subject: [PATCH 08/50] Revert "update > to ~" This reverts commit fe3a96e24a3001b76547a36bbe3301f8e5a8a255. --- tensorflow_quantum/release.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tensorflow_quantum/release.md b/tensorflow_quantum/release.md index 46d844e7a..63fcd0a0f 100644 --- a/tensorflow_quantum/release.md +++ b/tensorflow_quantum/release.md @@ -4,7 +4,7 @@ - The TensorFlow dependency has been upgraded from 2.7.0 to 2.11.0: - TensorFlow Quantum is now compiled with `_GLIBCXX_USE_CXX11_ABI=1`. Downstream projects that encounter `std::__cxx11` or `[abi:cxx11]` linker errors will need to adopt this compiler option. See [the GNU C++ Library docs on Dual ABI](https://gcc.gnu.org/onlinedocs/libstdc++/manual/using_dual_abi.html). - TensorFlow Quantum is now compiled with `-std=c++17`, see [install.md](/docs/install.md) for build instructions. -- Cirq dependency has been upgraded from `0.13.1` to `~=1.0` +- Cirq dependency has been upgraded from `0.13.1` to `>=1.0` - `cirq_google.XMON` was deprecated : https://github.com/quantumlib/Cirq/issues/4856 - `QuantumEngineSampler` was deprecated : https://github.com/quantumlib/Cirq/issues/5371 - So, we need [ProcessorSampler() for testing](https://github.com/quantumlib/Cirq/blob/master/cirq-google/cirq_google/engine/processor_sampler_test.py) From 437aa5b21b1293c02b200e4df4da9136cb2a00e4 Mon Sep 17 00:00:00 2001 From: Michael Broughton Date: Mon, 12 Jun 2023 14:08:37 -0700 Subject: [PATCH 09/50] Revert "update cirq dependency news" This reverts commit a44ab2659fde41daf73f1abbcca56aa34d78661d. --- tensorflow_quantum/release.md | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/tensorflow_quantum/release.md b/tensorflow_quantum/release.md index 63fcd0a0f..8abd51297 100644 --- a/tensorflow_quantum/release.md +++ b/tensorflow_quantum/release.md @@ -4,16 +4,6 @@ - The TensorFlow dependency has been upgraded from 2.7.0 to 2.11.0: - TensorFlow Quantum is now compiled with `_GLIBCXX_USE_CXX11_ABI=1`. Downstream projects that encounter `std::__cxx11` or `[abi:cxx11]` linker errors will need to adopt this compiler option. See [the GNU C++ Library docs on Dual ABI](https://gcc.gnu.org/onlinedocs/libstdc++/manual/using_dual_abi.html). - TensorFlow Quantum is now compiled with `-std=c++17`, see [install.md](/docs/install.md) for build instructions. -- Cirq dependency has been upgraded from `0.13.1` to `>=1.0` - - `cirq_google.XMON` was deprecated : https://github.com/quantumlib/Cirq/issues/4856 - - `QuantumEngineSampler` was deprecated : https://github.com/quantumlib/Cirq/issues/5371 - - So, we need [ProcessorSampler() for testing](https://github.com/quantumlib/Cirq/blob/master/cirq-google/cirq_google/engine/processor_sampler_test.py) - - `cirq.CNOT` interface was changed. - - https://quantumai.google/reference/python/cirq/CNOT - - No more control, target argument. - - `cirq.SingleQubitGate` was deprecated. - - For testing, use `cirq.testing.SingleQubitGate` : https://github.com/quantumlib/Cirq/pull/5272/files - - For implementation, use `cirq.Gate`. # Major Features and Improvements - Significant performance improvements by introducing cuQuantum support for circuit execution on Nvidia GPUs: From b84275b827593c939c303c1e9e58539d42be47d1 Mon Sep 17 00:00:00 2001 From: Michael Broughton Date: Mon, 12 Jun 2023 14:08:39 -0700 Subject: [PATCH 10/50] Revert "Update release.md" This reverts commit a7a67c8afc5f977a8347be0a78001c4c9fbd772a. --- tensorflow_quantum/release.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tensorflow_quantum/release.md b/tensorflow_quantum/release.md index 8abd51297..264c00477 100644 --- a/tensorflow_quantum/release.md +++ b/tensorflow_quantum/release.md @@ -17,7 +17,7 @@ - Important notes: - CuQuantum execution is currently only supported for source distributions meaning that the user must build TensorFlow Quantum & `tensorFlow-cpu` from source following the instructions in [install.md](/docs/install.md#build-from-source). - Ensure that the first entry is "N" in the `configure.sh` script at [this step](/docs/install.md#6-build-the-tensorflow-quantum-pip-package) of building. This ensures that you build upon `tensorflow-cpu` as `tensorflow-gpu` is unnecessary for CuQuantum support in TensorFlow Quantum. - - The cuQuantum SDK must be installed locally. See [installation instructions](https://docs.nvidia.com/cuda/cuquantum/custatevec/getting_started.html) for details. As part of the installation process, ensure that the `CUQUANTUM_ROOT` environment variable is set (referred to in the installation instructions). If not set, bazel will attempt to automatically locate the folder containing the cuQuantum installation upon running `configure.sh` at [this step](/docs/install.md#6-build-the-tensorflow-quantum-pip-package). + - The cuQuantum SDK must be installed locally. See [installation instructions](https://docs.nvidia.com/cuda/cuquantum/custatevec/getting_started.html) for details. As part of the installation process, ensure that the `CUQUANTUM_ROOT` environment variable is set (referred to in the installation instructions). If not set, bazel will attempt to locate the folder containing the cuQuantum installation upon running `configure.sh` at [this step](/docs/install.md#6-build-the-tensorflow-quantum-pip-package). - Tested on Titan, Ampere and Volta Nvidia GPU architectures. Note that Pascal GPU architectures are not supported, see documentation to [check whether your GPU is compatible with cuQuantum](https://docs.nvidia.com/cuda/cuquantum/getting_started.html#custatevec) - Quantum concurrency (global context option) should be turned off when `use_cuquantum=True`. This can be done by running: `tfq.python.quantum_context.set_quantum_concurrent_op_mode(False)` From 4d859a047d3276163d26d9d4d1951b0ba827a062 Mon Sep 17 00:00:00 2001 From: Michael Broughton Date: Mon, 12 Jun 2023 14:08:41 -0700 Subject: [PATCH 11/50] Revert "add notes" This reverts commit c7f729a01527bb065bdc5a0e7b1ea43e1330f4ba. --- tensorflow_quantum/release.md | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/tensorflow_quantum/release.md b/tensorflow_quantum/release.md index 264c00477..6d12339a3 100644 --- a/tensorflow_quantum/release.md +++ b/tensorflow_quantum/release.md @@ -6,22 +6,13 @@ - TensorFlow Quantum is now compiled with `-std=c++17`, see [install.md](/docs/install.md) for build instructions. # Major Features and Improvements -- Significant performance improvements by introducing cuQuantum support for circuit execution on Nvidia GPUs: - - TensorFlow Quantum Keras layers can now be executed on GPU by setting the optional arguement `use_cuquantum=True` at layer instantiation. Examples: +- Significant performance improvements by introducing cuQuantum support for circuit execution on GPU: + - TensorFlow Quantum Keras layers can now be executed on GPU by setting `use_cuquantum=True` at layer instantiation. Examples: - `tfq.layers.Expectation(use_cuquantum=True)` - `tfq.layers.SampledExpectation(use_cuquantum=True)` (note that cuQuantum runtime is unsupported for any noisy circuit operations - `tfq.layers.State(use_cuquantum=True)` - `tfq.layers.Sample(use_cuquantum=True)` - - `tfq.layers.PQC(model_circuit, operators, use_cuquantum=True)` - - `tfq.layers.ControlledPQC(model_circuit, operators, use_cuquantum=True)` - - Important notes: - - CuQuantum execution is currently only supported for source distributions meaning that the user must build TensorFlow Quantum & `tensorFlow-cpu` from source following the instructions in [install.md](/docs/install.md#build-from-source). - - Ensure that the first entry is "N" in the `configure.sh` script at [this step](/docs/install.md#6-build-the-tensorflow-quantum-pip-package) of building. This ensures that you build upon `tensorflow-cpu` as `tensorflow-gpu` is unnecessary for CuQuantum support in TensorFlow Quantum. - - The cuQuantum SDK must be installed locally. See [installation instructions](https://docs.nvidia.com/cuda/cuquantum/custatevec/getting_started.html) for details. As part of the installation process, ensure that the `CUQUANTUM_ROOT` environment variable is set (referred to in the installation instructions). If not set, bazel will attempt to locate the folder containing the cuQuantum installation upon running `configure.sh` at [this step](/docs/install.md#6-build-the-tensorflow-quantum-pip-package). - - Tested on Titan, Ampere and Volta Nvidia GPU architectures. Note that Pascal GPU architectures are not supported, see documentation to [check whether your GPU is compatible with cuQuantum](https://docs.nvidia.com/cuda/cuquantum/getting_started.html#custatevec) - - Quantum concurrency (global context option) should be turned off when `use_cuquantum=True`. This can be done by running: `tfq.python.quantum_context.set_quantum_concurrent_op_mode(False)` - - + - `tfq.layers.SimulateSample(use_cuquantum=True)` # Thanks to our Contributors This release contains contributions from many people at Google, Nvidia, as well as: From 5cc5cb3be13f4cc39746e9454248bf1872e6b7bf Mon Sep 17 00:00:00 2001 From: Michael Broughton Date: Mon, 12 Jun 2023 14:08:43 -0700 Subject: [PATCH 12/50] Revert "update version num" This reverts commit f933b6925b7ef673c78dbbb750e0a75e3c70dcd3. --- tensorflow_quantum/release.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tensorflow_quantum/release.md b/tensorflow_quantum/release.md index 6d12339a3..01af81c36 100644 --- a/tensorflow_quantum/release.md +++ b/tensorflow_quantum/release.md @@ -1,4 +1,4 @@ -# Release 0.8.0 +# Release 0.7.0 # Breaking Changes - Build, compilation, and packaging: - The TensorFlow dependency has been upgraded from 2.7.0 to 2.11.0: From 49f4b77c0537e2c914773a08db104f7b77aa5072 Mon Sep 17 00:00:00 2001 From: Michael Broughton Date: Mon, 12 Jun 2023 14:08:45 -0700 Subject: [PATCH 13/50] Revert "Update release.md" This reverts commit c2ab0d5e08af1eed85f97e8ab5794bbbc7c20833. --- tensorflow_quantum/release.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tensorflow_quantum/release.md b/tensorflow_quantum/release.md index 01af81c36..91c5a3331 100644 --- a/tensorflow_quantum/release.md +++ b/tensorflow_quantum/release.md @@ -1,10 +1,4 @@ # Release 0.7.0 -# Breaking Changes -- Build, compilation, and packaging: - - The TensorFlow dependency has been upgraded from 2.7.0 to 2.11.0: - - TensorFlow Quantum is now compiled with `_GLIBCXX_USE_CXX11_ABI=1`. Downstream projects that encounter `std::__cxx11` or `[abi:cxx11]` linker errors will need to adopt this compiler option. See [the GNU C++ Library docs on Dual ABI](https://gcc.gnu.org/onlinedocs/libstdc++/manual/using_dual_abi.html). - - TensorFlow Quantum is now compiled with `-std=c++17`, see [install.md](/docs/install.md) for build instructions. - # Major Features and Improvements - Significant performance improvements by introducing cuQuantum support for circuit execution on GPU: - TensorFlow Quantum Keras layers can now be executed on GPU by setting `use_cuquantum=True` at layer instantiation. Examples: @@ -14,5 +8,11 @@ - `tfq.layers.Sample(use_cuquantum=True)` - `tfq.layers.SimulateSample(use_cuquantum=True)` +- Build, compilation, and packaging: + - The TensorFlow dependency has been upgraded from 2.7.0 to 2.11.0: + - TensorFlow Quantum is now compiled with `_GLIBCXX_USE_CXX11_ABI=1`. Downstream projects that encounter `std::__cxx11` or `[abi:cxx11]` linker errors will need to adopt this compiler option. See [the GNU C++ Library docs on Dual ABI](https://gcc.gnu.org/onlinedocs/libstdc++/manual/using_dual_abi.html). + - TensorFlow Quantum is now compiled with `-std=c++17`, see [install.md](/docs/install.md) for build instructions. + + # Thanks to our Contributors This release contains contributions from many people at Google, Nvidia, as well as: From 5af15c8f35fb5d76baaa5a52221c2938f63dcb53 Mon Sep 17 00:00:00 2001 From: Michael Broughton Date: Mon, 12 Jun 2023 14:08:47 -0700 Subject: [PATCH 14/50] Revert "Create release.md" This reverts commit ac7722ad7da4e529da40e0c2baccdaadf9c2c056. --- tensorflow_quantum/release.md | 18 ------------------ 1 file changed, 18 deletions(-) delete mode 100644 tensorflow_quantum/release.md diff --git a/tensorflow_quantum/release.md b/tensorflow_quantum/release.md deleted file mode 100644 index 91c5a3331..000000000 --- a/tensorflow_quantum/release.md +++ /dev/null @@ -1,18 +0,0 @@ -# Release 0.7.0 -# Major Features and Improvements -- Significant performance improvements by introducing cuQuantum support for circuit execution on GPU: - - TensorFlow Quantum Keras layers can now be executed on GPU by setting `use_cuquantum=True` at layer instantiation. Examples: - - `tfq.layers.Expectation(use_cuquantum=True)` - - `tfq.layers.SampledExpectation(use_cuquantum=True)` (note that cuQuantum runtime is unsupported for any noisy circuit operations - - `tfq.layers.State(use_cuquantum=True)` - - `tfq.layers.Sample(use_cuquantum=True)` - - `tfq.layers.SimulateSample(use_cuquantum=True)` - -- Build, compilation, and packaging: - - The TensorFlow dependency has been upgraded from 2.7.0 to 2.11.0: - - TensorFlow Quantum is now compiled with `_GLIBCXX_USE_CXX11_ABI=1`. Downstream projects that encounter `std::__cxx11` or `[abi:cxx11]` linker errors will need to adopt this compiler option. See [the GNU C++ Library docs on Dual ABI](https://gcc.gnu.org/onlinedocs/libstdc++/manual/using_dual_abi.html). - - TensorFlow Quantum is now compiled with `-std=c++17`, see [install.md](/docs/install.md) for build instructions. - - -# Thanks to our Contributors -This release contains contributions from many people at Google, Nvidia, as well as: From 4a3a9d20f1620ec87c0131791872d97898b3dba7 Mon Sep 17 00:00:00 2001 From: Michael Broughton Date: Mon, 12 Jun 2023 14:09:26 -0700 Subject: [PATCH 15/50] Revert "Merge branch 'master' into master" This reverts commit 7131f9e4d2d289e51f9705161b29c45159da1921, reversing changes made to 2c1e7fa4778475040c149b23e2b2f661007a1f8e. --- configure.sh | 4 +- .../tfq_simulate_expectation_op_cuda.cu.cc | 207 ---------------- ...fq_simulate_expectation_op_cuquantum.cu.cc | 221 ------------------ .../core/ops/tfq_simulate_ops_cuda.py | 45 ---- .../core/ops/tfq_simulate_ops_cuquantum.py | 45 ---- .../core/ops/tfq_simulate_ops_gpu_test.py | 133 ----------- 6 files changed, 2 insertions(+), 653 deletions(-) delete mode 100644 tensorflow_quantum/core/ops/tfq_simulate_expectation_op_cuda.cu.cc delete mode 100644 tensorflow_quantum/core/ops/tfq_simulate_expectation_op_cuquantum.cu.cc delete mode 100644 tensorflow_quantum/core/ops/tfq_simulate_ops_cuda.py delete mode 100644 tensorflow_quantum/core/ops/tfq_simulate_ops_cuquantum.py delete mode 100644 tensorflow_quantum/core/ops/tfq_simulate_ops_gpu_test.py diff --git a/configure.sh b/configure.sh index 5efd4212a..1b0c9c420 100755 --- a/configure.sh +++ b/configure.sh @@ -64,9 +64,9 @@ done while [[ "$TF_CUDA_VERSION" == "" ]]; do read -p "Are you building against TensorFlow 2.1(including RCs) or newer?[Y/n] " INPUT case $INPUT in - [Yy]* ) echo "Build against TensorFlow 2.1 or newer."; TF_CUDA_VERSION=10.1;; + [Yy]* ) echo "Build against TensorFlow 2.1 or newer."; TF_CUDA_VERSION=11;; [Nn]* ) echo "Build against TensorFlow <2.1."; TF_CUDA_VERSION=10.0;; - "" ) echo "Build against TensorFlow 2.1 or newer."; TF_CUDA_VERSION=10.1;; + "" ) echo "Build against TensorFlow 2.1 or newer."; TF_CUDA_VERSION=11;; * ) echo "Invalid selection: " $INPUT;; esac done diff --git a/tensorflow_quantum/core/ops/tfq_simulate_expectation_op_cuda.cu.cc b/tensorflow_quantum/core/ops/tfq_simulate_expectation_op_cuda.cu.cc deleted file mode 100644 index 271df7f5c..000000000 --- a/tensorflow_quantum/core/ops/tfq_simulate_expectation_op_cuda.cu.cc +++ /dev/null @@ -1,207 +0,0 @@ -/* 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. -See the License for the specific language governing permissions and -limitations under the License. -==============================================================================*/ - -#include -#include - -#include - -#include "../qsim/lib/circuit.h" -#include "../qsim/lib/gate_appl.h" -#include "../qsim/lib/gates_cirq.h" -#include "../qsim/lib/gates_qsim.h" -#include "../qsim/lib/seqfor.h" -#include "../qsim/lib/simulator_cuda.h" -#include "../qsim/lib/statespace_cuda.h" -#include "tensorflow/core/framework/op_kernel.h" -#include "tensorflow/core/framework/shape_inference.h" -#include "tensorflow/core/framework/tensor_shape.h" -#include "tensorflow/core/lib/core/error_codes.pb.h" -#include "tensorflow/core/lib/core/status.h" -#include "tensorflow/core/lib/core/threadpool.h" -#include "tensorflow/core/platform/mutex.h" -#include "tensorflow_quantum/core/ops/parse_context.h" -#include "tensorflow_quantum/core/proto/pauli_sum.pb.h" -#include "tensorflow_quantum/core/proto/program.pb.h" -#include "tensorflow_quantum/core/src/util_qsim.h" - -namespace tfq { - -using ::tensorflow::Status; -using ::tfq::proto::PauliSum; -using ::tfq::proto::Program; - -typedef qsim::Cirq::GateCirq QsimGate; -typedef qsim::Circuit QsimCircuit; - - -class TfqSimulateExpectationOpCuda : public tensorflow::OpKernel { - public: - explicit TfqSimulateExpectationOpCuda(tensorflow::OpKernelConstruction* context) - : OpKernel(context) {} - - void Compute(tensorflow::OpKernelContext* context) override { - // TODO (mbbrough): add more dimension checks for other inputs here. - const int num_inputs = context->num_inputs(); - OP_REQUIRES(context, num_inputs == 4, - tensorflow::errors::InvalidArgument(absl::StrCat( - "Expected 4 inputs, got ", num_inputs, " inputs."))); - - // Create the output Tensor. - const int output_dim_batch_size = context->input(0).dim_size(0); - const int output_dim_op_size = context->input(3).dim_size(1); - tensorflow::TensorShape output_shape; - output_shape.AddDim(output_dim_batch_size); - output_shape.AddDim(output_dim_op_size); - - tensorflow::Tensor* output = nullptr; - tensorflow::AllocatorAttributes alloc_attr; - alloc_attr.set_on_host(true); - alloc_attr.set_gpu_compatible(true); - OP_REQUIRES_OK(context, context->allocate_output(0, output_shape, &output, - alloc_attr)); - auto output_tensor = output->matrix(); - // Parse program protos. - std::vector programs; - std::vector num_qubits; - std::vector> pauli_sums; - OP_REQUIRES_OK(context, GetProgramsAndNumQubits(context, &programs, - &num_qubits, &pauli_sums)); - - std::vector maps; - OP_REQUIRES_OK(context, GetSymbolMaps(context, &maps)); - - OP_REQUIRES(context, programs.size() == maps.size(), - tensorflow::errors::InvalidArgument(absl::StrCat( - "Number of circuits and symbol_values do not match. Got ", - programs.size(), " circuits and ", maps.size(), - " symbol values."))); - - // Construct qsim circuits. - std::vector qsim_circuits(programs.size(), QsimCircuit()); - std::vector>> fused_circuits( - programs.size(), std::vector>({})); - - Status parse_status = Status(); - auto p_lock = tensorflow::mutex(); - auto construct_f = [&](int start, int end) { - for (int i = start; i < end; i++) { - Status local = - QsimCircuitFromProgram(programs[i], maps[i], num_qubits[i], - &qsim_circuits[i], &fused_circuits[i]); - NESTED_FN_STATUS_SYNC(parse_status, local, p_lock); - } - }; - - const int num_cycles = 1000; - context->device()->tensorflow_cpu_worker_threads()->workers->ParallelFor( - programs.size(), num_cycles, construct_f); - OP_REQUIRES_OK(context, parse_status); - - int max_num_qubits = 0; - for (const int num : num_qubits) { - max_num_qubits = std::max(max_num_qubits, num); - } - ComputeLarge(num_qubits, fused_circuits, pauli_sums, context, - &output_tensor); - } - - private: - int num_threads_in_sim_; - int block_count_; - - // Define the GPU implementation that launches the CUDA kernel. - void ComputeLarge( - const std::vector& num_qubits, - const std::vector>>& fused_circuits, - const std::vector>& pauli_sums, - tensorflow::OpKernelContext* context, - tensorflow::TTypes::Matrix* output_tensor) { - // Instantiate qsim objects. - using Simulator = qsim::SimulatorCUDA; - using StateSpace = Simulator::StateSpace; - // Begin simulation with default parameters. - int largest_nq = 1; - Simulator sim = Simulator(); - StateSpace ss = StateSpace(StateSpace::Parameter()); - auto sv = ss.Create(largest_nq); - auto scratch = ss.Create(largest_nq); - - // Simulate programs one by one. Parallelizing over state vectors - // we no longer parallelize over circuits. Each time we encounter a - // a larger circuit we will grow the Statevector as necessary. - for (int i = 0; i < fused_circuits.size(); i++) { - int nq = num_qubits[i]; - - if (nq > largest_nq) { - // need to switch to larger statespace. - largest_nq = nq; - sv = ss.Create(largest_nq); - scratch = ss.Create(largest_nq); - } - // TODO: add heuristic here so that we do not always recompute - // the state if there is a possibility that circuit[i] and - // circuit[i + 1] produce the same state. - ss.SetStateZero(sv); - for (int j = 0; j < fused_circuits[i].size(); j++) { - qsim::ApplyFusedGate(sim, fused_circuits[i][j], sv); - } - for (int j = 0; j < pauli_sums[i].size(); j++) { - // (#679) Just ignore empty program - if (fused_circuits[i].size() == 0) { - (*output_tensor)(i, j) = -2.0; - continue; - } - float exp_v = 0.0; - OP_REQUIRES_OK(context, - ComputeExpectationQsim(pauli_sums[i][j], sim, ss, sv, - scratch, &exp_v)); - (*output_tensor)(i, j) = exp_v; - } - } - } - -}; - -REGISTER_KERNEL_BUILDER( - Name("TfqSimulateExpectationCuda").Device(tensorflow::DEVICE_CPU), - TfqSimulateExpectationOpCuda); - -REGISTER_OP("TfqSimulateExpectationCuda") - .Input("programs: string") - .Input("symbol_names: string") - .Input("symbol_values: float") - .Input("pauli_sums: string") - .Output("expectations: float") - .SetShapeFn([](tensorflow::shape_inference::InferenceContext* c) { - tensorflow::shape_inference::ShapeHandle programs_shape; - TF_RETURN_IF_ERROR(c->WithRank(c->input(0), 1, &programs_shape)); - - tensorflow::shape_inference::ShapeHandle symbol_names_shape; - TF_RETURN_IF_ERROR(c->WithRank(c->input(1), 1, &symbol_names_shape)); - - tensorflow::shape_inference::ShapeHandle symbol_values_shape; - TF_RETURN_IF_ERROR(c->WithRank(c->input(2), 2, &symbol_values_shape)); - - tensorflow::shape_inference::ShapeHandle pauli_sums_shape; - TF_RETURN_IF_ERROR(c->WithRank(c->input(3), 2, &pauli_sums_shape)); - - tensorflow::shape_inference::DimensionHandle output_rows = - c->Dim(programs_shape, 0); - tensorflow::shape_inference::DimensionHandle output_cols = - c->Dim(pauli_sums_shape, 1); - c->set_output(0, c->Matrix(output_rows, output_cols)); - - return ::tensorflow::Status(); - }); - -} // namespace tfq diff --git a/tensorflow_quantum/core/ops/tfq_simulate_expectation_op_cuquantum.cu.cc b/tensorflow_quantum/core/ops/tfq_simulate_expectation_op_cuquantum.cu.cc deleted file mode 100644 index c1fb0143a..000000000 --- a/tensorflow_quantum/core/ops/tfq_simulate_expectation_op_cuquantum.cu.cc +++ /dev/null @@ -1,221 +0,0 @@ -/* 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. -See the License for the specific language governing permissions and -limitations under the License. -==============================================================================*/ - -#include -#include - -#include - -#include "../cuquantum_libs/include/custatevec.h" -#include "../qsim/lib/circuit.h" -#include "../qsim/lib/gate_appl.h" -#include "../qsim/lib/gates_cirq.h" -#include "../qsim/lib/gates_qsim.h" -#include "../qsim/lib/seqfor.h" -#include "../qsim/lib/simulator_custatevec.h" -#include "../qsim/lib/statespace_custatevec.h" -#include "tensorflow/core/framework/op_kernel.h" -#include "tensorflow/core/framework/shape_inference.h" -#include "tensorflow/core/framework/tensor_shape.h" -#include "tensorflow/core/lib/core/error_codes.pb.h" -#include "tensorflow/core/lib/core/status.h" -#include "tensorflow/core/lib/core/threadpool.h" -#include "tensorflow/core/platform/mutex.h" -#include "tensorflow_quantum/core/ops/parse_context.h" -#include "tensorflow_quantum/core/proto/pauli_sum.pb.h" -#include "tensorflow_quantum/core/proto/program.pb.h" -#include "tensorflow_quantum/core/src/util_qsim.h" - -namespace tfq { - -using ::tensorflow::Status; -using ::tfq::proto::PauliSum; -using ::tfq::proto::Program; - -typedef qsim::Cirq::GateCirq QsimGate; -typedef qsim::Circuit QsimCircuit; - - -class TfqSimulateExpectationOpCuQuantum : public tensorflow::OpKernel { - public: - explicit TfqSimulateExpectationOpCuQuantum(tensorflow::OpKernelConstruction* context) - : OpKernel(context) {} - - void Compute(tensorflow::OpKernelContext* context) override { - - // TODO (mbbrough): add more dimension checks for other inputs here. - const int num_inputs = context->num_inputs(); - OP_REQUIRES(context, num_inputs == 4, - tensorflow::errors::InvalidArgument(absl::StrCat( - "Expected 4 inputs, got ", num_inputs, " inputs."))); - - // Create the output Tensor. - const int output_dim_batch_size = context->input(0).dim_size(0); - const int output_dim_op_size = context->input(3).dim_size(1); - tensorflow::TensorShape output_shape; - output_shape.AddDim(output_dim_batch_size); - output_shape.AddDim(output_dim_op_size); - - tensorflow::Tensor* output = nullptr; - tensorflow::AllocatorAttributes alloc_attr; - alloc_attr.set_on_host(true); // why?? - alloc_attr.set_gpu_compatible(true); - OP_REQUIRES_OK(context, context->allocate_output(0, output_shape, &output, - alloc_attr)); - auto output_tensor = output->matrix(); - // Parse program protos. - std::vector programs; - std::vector num_qubits; - std::vector> pauli_sums; // why is this a vector of vectors?? - OP_REQUIRES_OK(context, GetProgramsAndNumQubits(context, &programs, - &num_qubits, &pauli_sums)); - - std::vector maps; - OP_REQUIRES_OK(context, GetSymbolMaps(context, &maps)); - - OP_REQUIRES(context, programs.size() == maps.size(), - tensorflow::errors::InvalidArgument(absl::StrCat( - "Number of circuits and symbol_values do not match. Got ", - programs.size(), " circuits and ", maps.size(), - " symbol values."))); - - // Construct qsim circuits. - std::vector qsim_circuits(programs.size(), QsimCircuit()); - std::vector>> fused_circuits( - programs.size(), std::vector>({})); - - Status parse_status = Status::OK(); - auto p_lock = tensorflow::mutex(); - auto construct_f = [&](int start, int end) { - for (int i = start; i < end; i++) { - Status local = - QsimCircuitFromProgram(programs[i], maps[i], num_qubits[i], - &qsim_circuits[i], &fused_circuits[i]); - NESTED_FN_STATUS_SYNC(parse_status, local, p_lock); - } - }; - - const int num_cycles = 1000; - context->device()->tensorflow_cpu_worker_threads()->workers->ParallelFor( - programs.size(), num_cycles, construct_f); - OP_REQUIRES_OK(context, parse_status); - - int max_num_qubits = 0; - for (const int num : num_qubits) { - max_num_qubits = std::max(max_num_qubits, num); - } - - // create handles for simulator - cublasCreate(&cublas_handle_); - custatevecCreate(&custatevec_handle_); - - ComputeLarge(num_qubits, fused_circuits, pauli_sums, context, - &output_tensor); - - // destroy handles in sync with simulator lifetime - cublasDestroy(cublas_handle_); - custatevecDestroy(custatevec_handle_); - } - - private: - cublasHandle_t cublas_handle_; - custatevecHandle_t custatevec_handle_; - - // Define the GPU implementation that launches the CUDA kernel. - void ComputeLarge( - const std::vector& num_qubits, - const std::vector>>& fused_circuits, - const std::vector>& pauli_sums, - tensorflow::OpKernelContext* context, - tensorflow::TTypes::Matrix* output_tensor) { - // Instantiate qsim objects. - using Simulator = qsim::SimulatorCuStateVec; - using StateSpace = Simulator::StateSpace; - - - // Launch the cuda kernel. - // Begin simulation. - int largest_nq = 1; - Simulator sim = Simulator(cublas_handle_, custatevec_handle_); - StateSpace ss = StateSpace(cublas_handle_, custatevec_handle_); - auto sv = ss.Create(largest_nq); - ss.SetStateZero(sv); - auto scratch = ss.Create(largest_nq); - - // Simulate programs one by one. Parallelizing over state vectors - // we no longer parallelize over circuits. Each time we encounter a - // a larger circuit we will grow the Statevector as necessary. - for (int i = 0; i < fused_circuits.size(); i++) { - int nq = num_qubits[i]; - - if (nq > largest_nq) { - // need to switch to larger statespace. - largest_nq = nq; - sv = ss.Create(largest_nq); - scratch = ss.Create(largest_nq); - } - // TODO: add heuristic here so that we do not always recompute - // the state if there is a possibility that circuit[i] and - // circuit[i + 1] produce the same state. - ss.SetStateZero(sv); - for (int j = 0; j < fused_circuits[i].size(); j++) { - qsim::ApplyFusedGate(sim, fused_circuits[i][j], sv); - } - for (int j = 0; j < pauli_sums[i].size(); j++) { - // (#679) Just ignore empty program - if (fused_circuits[i].size() == 0) { - (*output_tensor)(i, j) = -2.0; - continue; - } - float exp_v = 0.0; - OP_REQUIRES_OK(context, - ComputeExpectationQsim(pauli_sums[i][j], sim, ss, sv, - scratch, &exp_v)); - (*output_tensor)(i, j) = exp_v; - } - } - } -}; - -REGISTER_KERNEL_BUILDER( - Name("TfqSimulateExpectationCuquantum").Device(tensorflow::DEVICE_CPU), - TfqSimulateExpectationOpCuQuantum); - -REGISTER_OP("TfqSimulateExpectationCuquantum") - .Input("programs: string") - .Input("symbol_names: string") - .Input("symbol_values: float") - .Input("pauli_sums: string") - .Output("expectations: float") - .SetShapeFn([](tensorflow::shape_inference::InferenceContext* c) { - tensorflow::shape_inference::ShapeHandle programs_shape; - TF_RETURN_IF_ERROR(c->WithRank(c->input(0), 1, &programs_shape)); - - tensorflow::shape_inference::ShapeHandle symbol_names_shape; - TF_RETURN_IF_ERROR(c->WithRank(c->input(1), 1, &symbol_names_shape)); - - tensorflow::shape_inference::ShapeHandle symbol_values_shape; - TF_RETURN_IF_ERROR(c->WithRank(c->input(2), 2, &symbol_values_shape)); - - tensorflow::shape_inference::ShapeHandle pauli_sums_shape; - TF_RETURN_IF_ERROR(c->WithRank(c->input(3), 2, &pauli_sums_shape)); - - tensorflow::shape_inference::DimensionHandle output_rows = - c->Dim(programs_shape, 0); - tensorflow::shape_inference::DimensionHandle output_cols = - c->Dim(pauli_sums_shape, 1); - c->set_output(0, c->Matrix(output_rows, output_cols)); - - return tensorflow::Status::OK(); - }); - -} // namespace tfq diff --git a/tensorflow_quantum/core/ops/tfq_simulate_ops_cuda.py b/tensorflow_quantum/core/ops/tfq_simulate_ops_cuda.py deleted file mode 100644 index e6860b028..000000000 --- a/tensorflow_quantum/core/ops/tfq_simulate_ops_cuda.py +++ /dev/null @@ -1,45 +0,0 @@ -# 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. -# See the License for the specific language governing permissions and -# limitations under the License. -# ============================================================================== -"""Module to register cuda simulation python op.""" -import os -import tensorflow as tf -from tensorflow_quantum.core.ops.load_module import load_module - -SIM_OP_MODULE = load_module("_tfq_simulate_ops_cuda.so") - - -def tfq_simulate_expectation(programs, symbol_names, symbol_values, pauli_sums): - """Calculates the expectation value of circuits wrt some operator(s). - Args: - programs: `tf.Tensor` of strings with shape [batch_size] containing - the string representations of the circuits to be executed. - symbol_names: `tf.Tensor` of strings with shape [n_params], which - is used to specify the order in which the values in - `symbol_values` should be placed inside of the circuits in - `programs`. - symbol_values: `tf.Tensor` of real numbers with shape - [batch_size, n_params] specifying parameter values to resolve - into the circuits specificed by programs, following the ordering - dictated by `symbol_names`. - pauli_sums: `tf.Tensor` of strings with shape [batch_size, n_ops] - containing the string representation of the operators that will - be used on all of the circuits in the expectation calculations. - Returns: - `tf.Tensor` with shape [batch_size, n_ops] that holds the - expectation value for each circuit with each op applied to it - (after resolving the corresponding parameters in). - """ - return SIM_OP_MODULE.tfq_simulate_expectation_cuda( - programs, symbol_names, tf.cast(symbol_values, tf.float32), pauli_sums) \ No newline at end of file diff --git a/tensorflow_quantum/core/ops/tfq_simulate_ops_cuquantum.py b/tensorflow_quantum/core/ops/tfq_simulate_ops_cuquantum.py deleted file mode 100644 index 127d4f56b..000000000 --- a/tensorflow_quantum/core/ops/tfq_simulate_ops_cuquantum.py +++ /dev/null @@ -1,45 +0,0 @@ -# Copyright 2023 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. -# See the License for the specific language governing permissions and -# limitations under the License. -# ============================================================================== -"""Module to register cuQuantum simulation python op.""" -import os -import tensorflow as tf -from tensorflow_quantum.core.ops.load_module import load_module - -SIM_OP_MODULE = load_module("_tfq_simulate_ops_cuquantum.so") - - -def tfq_simulate_expectation(programs, symbol_names, symbol_values, pauli_sums): - """Calculates the expectation value of circuits wrt some operator(s). - Args: - programs: `tf.Tensor` of strings with shape [batch_size] containing - the string representations of the circuits to be executed. - symbol_names: `tf.Tensor` of strings with shape [n_params], which - is used to specify the order in which the values in - `symbol_values` should be placed inside of the circuits in - `programs`. - symbol_values: `tf.Tensor` of real numbers with shape - [batch_size, n_params] specifying parameter values to resolve - into the circuits specificed by programs, following the ordering - dictated by `symbol_names`. - pauli_sums: `tf.Tensor` of strings with shape [batch_size, n_ops] - containing the string representation of the operators that will - be used on all of the circuits in the expectation calculations. - Returns: - `tf.Tensor` with shape [batch_size, n_ops] that holds the - expectation value for each circuit with each op applied to it - (after resolving the corresponding parameters in). - """ - return SIM_OP_MODULE.tfq_simulate_expectation_cuquantum( - programs, symbol_names, tf.cast(symbol_values, tf.float32), pauli_sums) \ No newline at end of file diff --git a/tensorflow_quantum/core/ops/tfq_simulate_ops_gpu_test.py b/tensorflow_quantum/core/ops/tfq_simulate_ops_gpu_test.py deleted file mode 100644 index 62517be22..000000000 --- a/tensorflow_quantum/core/ops/tfq_simulate_ops_gpu_test.py +++ /dev/null @@ -1,133 +0,0 @@ -# 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. -# See the License for the specific language governing permissions and -# limitations under the License. -# ============================================================================== -"""Tests that specifically target tfq_simulate_ops_cu*.""" -import os -import time -import numpy as np -from absl.testing import parameterized -import tensorflow as tf -import cirq - -from tensorflow_quantum.core.ops import tfq_simulate_ops -from tensorflow_quantum.core.ops import tfq_simulate_ops_cuda -from tensorflow_quantum.core.ops import tfq_simulate_ops_cuquantum -from tensorflow_quantum.python import util - -def measure_average_runtime(fn, tag, num_samples=10): - avg_time = [] - for _ in range(num_samples): - begin_time = time.time() - result = fn() - duration = time.time() - begin_time - avg_time.append(duration) - avg_time = sum(avg_time) / float(num_samples) - print(f"\n\t{tag} time: {avg_time}\n") - return avg_time, result - - -class SimulateExpectationGpuTest(tf.test.TestCase): - """Tests tfq_simulate_expectation.""" - - def test_simulate_expectation_cpu_vs_cuda(self): - """Make sure that cpu & gpu(cuda) ops have the same results.""" - n_qubits = 20 - batch_size = 5 - symbol_names = ['alpha'] - qubits = cirq.GridQubit.rect(1, n_qubits) - circuit_batch, resolver_batch = \ - util.random_symbol_circuit_resolver_batch( - qubits, symbol_names, batch_size) - - circuit_batch_tensor = util.convert_to_tensor(circuit_batch) - - symbol_values_array = np.array( - [[resolver[symbol] - for symbol in symbol_names] - for resolver in resolver_batch]) - - pauli_sums = util.random_pauli_sums(qubits, 3, batch_size) - pauli_sums_tensor = util.convert_to_tensor([[x] for x in pauli_sums]) - - cpu_avg_time, res_cpu = measure_average_runtime( - lambda: tfq_simulate_ops.tfq_simulate_expectation( - circuit_batch_tensor, - symbol_names, symbol_values_array.astype(np.float64), - pauli_sums_tensor), - "CPU", - num_samples=100, - ) - - cuda_avg_time, res_cuda = measure_average_runtime( - lambda: tfq_simulate_ops_cuda.tfq_simulate_expectation( - circuit_batch_tensor, - symbol_names, symbol_values_array.astype(np.float64), - pauli_sums_tensor), - "CUDA", - num_samples=100, - ) - - # The result should be the similar within a tolerance. - np.testing.assert_allclose(res_cpu, res_cuda, atol=1e-4) - - # CUDA op should be faster than CPU op. - self.assertGreater(cpu_avg_time, cuda_avg_time) - - def test_simulate_expectation_cpu_vs_cuquantum(self): - """Make sure that cpu & gpu(cuquantum) ops have the same results.""" - n_qubits = 20 - batch_size = 5 - symbol_names = ['alpha'] - qubits = cirq.GridQubit.rect(1, n_qubits) - circuit_batch, resolver_batch = \ - util.random_symbol_circuit_resolver_batch( - qubits, symbol_names, batch_size) - - circuit_batch_tensor = util.convert_to_tensor(circuit_batch) - - symbol_values_array = np.array( - [[resolver[symbol] - for symbol in symbol_names] - for resolver in resolver_batch]) - - pauli_sums = util.random_pauli_sums(qubits, 3, batch_size) - pauli_sums_tensor = util.convert_to_tensor([[x] for x in pauli_sums]) - - cpu_avg_time, res_cpu = measure_average_runtime( - lambda: tfq_simulate_ops.tfq_simulate_expectation( - circuit_batch_tensor, - symbol_names, symbol_values_array.astype(np.float64), - pauli_sums_tensor), - "CPU", - num_samples=100, - - ) - - cuda_avg_time, res_cuda = measure_average_runtime( - lambda: tfq_simulate_ops_cuquantum.tfq_simulate_expectation( - circuit_batch_tensor, - symbol_names, symbol_values_array.astype(np.float64), - pauli_sums_tensor), - "cuQuantum", - num_samples=100, - ) - - # The result should be the similar within a tolerance. - np.testing.assert_allclose(res_cpu, res_cuda, atol=1e-4) - - # cuQuantum op should be faster than CPU op. - self.assertGreater(cpu_avg_time, cuda_avg_time) - -if __name__ == "__main__": - tf.test.main() \ No newline at end of file From 7358b9db72dc027bf0b7673022b209a581d5f8c0 Mon Sep 17 00:00:00 2001 From: Michael Broughton Date: Mon, 12 Jun 2023 14:09:28 -0700 Subject: [PATCH 16/50] Revert "Upgrade bazel version 5.3.0 and fix some typo in tf version (#755)" This reverts commit 2c1e7fa4778475040c149b23e2b2f661007a1f8e. --- configure.sh | 4 ++-- scripts/ci_install.sh | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/configure.sh b/configure.sh index 1b0c9c420..5efd4212a 100755 --- a/configure.sh +++ b/configure.sh @@ -64,9 +64,9 @@ done while [[ "$TF_CUDA_VERSION" == "" ]]; do read -p "Are you building against TensorFlow 2.1(including RCs) or newer?[Y/n] " INPUT case $INPUT in - [Yy]* ) echo "Build against TensorFlow 2.1 or newer."; TF_CUDA_VERSION=11;; + [Yy]* ) echo "Build against TensorFlow 2.1 or newer."; TF_CUDA_VERSION=10.1;; [Nn]* ) echo "Build against TensorFlow <2.1."; TF_CUDA_VERSION=10.0;; - "" ) echo "Build against TensorFlow 2.1 or newer."; TF_CUDA_VERSION=11;; + "" ) echo "Build against TensorFlow 2.1 or newer."; TF_CUDA_VERSION=10.1;; * ) echo "Invalid selection: " $INPUT;; esac done diff --git a/scripts/ci_install.sh b/scripts/ci_install.sh index 04e6b3159..a0ed81c8c 100755 --- a/scripts/ci_install.sh +++ b/scripts/ci_install.sh @@ -13,7 +13,7 @@ # See the License for the specific language governing permissions and # limitations under the License. # ============================================================================== -wget https://github.com/bazelbuild/bazel/releases/download/5.3.0/bazel_5.3.0-linux-x86_64.deb -sudo dpkg -i bazel_5.3.0-linux-x86_64.deb +wget https://github.com/bazelbuild/bazel/releases/download/5.1.0/bazel_5.1.0-linux-x86_64.deb +sudo dpkg -i bazel_5.1.0-linux-x86_64.deb pip install --upgrade pip setuptools wheel pip install -r requirements.txt \ No newline at end of file From 5f5b47438911a41119165a855684376e202af635 Mon Sep 17 00:00:00 2001 From: Michael Broughton Date: Mon, 12 Jun 2023 14:09:38 -0700 Subject: [PATCH 17/50] Revert "Merge pull request #3 from jaeyoo/pavan/remove_compute_small" This reverts commit 79aae25dc5db7c7e1ae2a83c23a0fb88af2d19c4, reversing changes made to 46aa1f0eb43473967f81e14b00a706adefc37482. --- tensorflow_quantum/core/ops/BUILD | 1 + .../tfq_simulate_expectation_op_cuda.cu.cc | 282 +++++++++++++++++ ...fq_simulate_expectation_op_cuquantum.cu.cc | 293 ++++++++++++++++++ .../core/ops/tfq_simulate_ops_gpu_test.py | 128 ++++++++ 4 files changed, 704 insertions(+) create mode 100644 tensorflow_quantum/core/ops/tfq_simulate_expectation_op_cuda.cu.cc create mode 100644 tensorflow_quantum/core/ops/tfq_simulate_expectation_op_cuquantum.cu.cc create mode 100644 tensorflow_quantum/core/ops/tfq_simulate_ops_gpu_test.py diff --git a/tensorflow_quantum/core/ops/BUILD b/tensorflow_quantum/core/ops/BUILD index 8087a8d3b..3983d068b 100644 --- a/tensorflow_quantum/core/ops/BUILD +++ b/tensorflow_quantum/core/ops/BUILD @@ -24,6 +24,7 @@ py_library( ":tfq_adj_grad_op_py", ":tfq_ps_util_ops_py", ":tfq_simulate_ops_py", + ":tfq_simulate_ops_cuda_py", ":tfq_unitary_op_py", ":tfq_utility_ops_py", # test addons diff --git a/tensorflow_quantum/core/ops/tfq_simulate_expectation_op_cuda.cu.cc b/tensorflow_quantum/core/ops/tfq_simulate_expectation_op_cuda.cu.cc new file mode 100644 index 000000000..a7a448bd0 --- /dev/null +++ b/tensorflow_quantum/core/ops/tfq_simulate_expectation_op_cuda.cu.cc @@ -0,0 +1,282 @@ +/* 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. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include +#include + +#include + +#include "../qsim/lib/circuit.h" +#include "../qsim/lib/gate_appl.h" +#include "../qsim/lib/gates_cirq.h" +#include "../qsim/lib/gates_qsim.h" +#include "../qsim/lib/seqfor.h" +#include "../qsim/lib/simulator_cuda.h" +#include "../qsim/lib/statespace_cuda.h" +#include "tensorflow/core/framework/op_kernel.h" +#include "tensorflow/core/framework/shape_inference.h" +#include "tensorflow/core/framework/tensor_shape.h" +#include "tensorflow/core/lib/core/error_codes.pb.h" +#include "tensorflow/core/lib/core/status.h" +#include "tensorflow/core/lib/core/threadpool.h" +#include "tensorflow/core/platform/mutex.h" +#include "tensorflow_quantum/core/ops/parse_context.h" +#include "tensorflow_quantum/core/proto/pauli_sum.pb.h" +#include "tensorflow_quantum/core/proto/program.pb.h" +#include "tensorflow_quantum/core/src/util_qsim.h" + +namespace tfq { + +using ::tensorflow::Status; +using ::tfq::proto::PauliSum; +using ::tfq::proto::Program; + +typedef qsim::Cirq::GateCirq QsimGate; +typedef qsim::Circuit QsimCircuit; + + +class TfqSimulateExpectationOpCuda : public tensorflow::OpKernel { + public: + explicit TfqSimulateExpectationOpCuda(tensorflow::OpKernelConstruction* context) + : OpKernel(context) {} + + void Compute(tensorflow::OpKernelContext* context) override { + // TODO (mbbrough): add more dimension checks for other inputs here. + const int num_inputs = context->num_inputs(); + OP_REQUIRES(context, num_inputs == 4, + tensorflow::errors::InvalidArgument(absl::StrCat( + "Expected 4 inputs, got ", num_inputs, " inputs."))); + + // Create the output Tensor. + const int output_dim_batch_size = context->input(0).dim_size(0); + const int output_dim_op_size = context->input(3).dim_size(1); + tensorflow::TensorShape output_shape; + output_shape.AddDim(output_dim_batch_size); + output_shape.AddDim(output_dim_op_size); + + tensorflow::Tensor* output = nullptr; + tensorflow::AllocatorAttributes alloc_attr; + alloc_attr.set_on_host(true); + alloc_attr.set_gpu_compatible(true); + OP_REQUIRES_OK(context, context->allocate_output(0, output_shape, &output, + alloc_attr)); + auto output_tensor = output->matrix(); + // Parse program protos. + std::vector programs; + std::vector num_qubits; + std::vector> pauli_sums; + OP_REQUIRES_OK(context, GetProgramsAndNumQubits(context, &programs, + &num_qubits, &pauli_sums)); + + std::vector maps; + OP_REQUIRES_OK(context, GetSymbolMaps(context, &maps)); + + OP_REQUIRES(context, programs.size() == maps.size(), + tensorflow::errors::InvalidArgument(absl::StrCat( + "Number of circuits and symbol_values do not match. Got ", + programs.size(), " circuits and ", maps.size(), + " symbol values."))); + + // Construct qsim circuits. + std::vector qsim_circuits(programs.size(), QsimCircuit()); + std::vector>> fused_circuits( + programs.size(), std::vector>({})); + + Status parse_status = Status(); + auto p_lock = tensorflow::mutex(); + auto construct_f = [&](int start, int end) { + for (int i = start; i < end; i++) { + Status local = + QsimCircuitFromProgram(programs[i], maps[i], num_qubits[i], + &qsim_circuits[i], &fused_circuits[i]); + NESTED_FN_STATUS_SYNC(parse_status, local, p_lock); + } + }; + + const int num_cycles = 1000; + context->device()->tensorflow_cpu_worker_threads()->workers->ParallelFor( + programs.size(), num_cycles, construct_f); + OP_REQUIRES_OK(context, parse_status); + + int max_num_qubits = 0; + for (const int num : num_qubits) { + max_num_qubits = std::max(max_num_qubits, num); + } + if (max_num_qubits >= 26 || programs.size() == 1) { + ComputeLarge(num_qubits, fused_circuits, pauli_sums, context, + &output_tensor); + } else { + ComputeSmall(num_qubits, max_num_qubits, fused_circuits, pauli_sums, + context, &output_tensor); + } + } + + private: + int num_threads_in_sim_; + int block_count_; + + // Define the GPU implementation that launches the CUDA kernel. + void ComputeLarge( + const std::vector& num_qubits, + const std::vector>>& fused_circuits, + const std::vector>& pauli_sums, + tensorflow::OpKernelContext* context, + tensorflow::TTypes::Matrix* output_tensor) { + // Instantiate qsim objects. + using Simulator = qsim::SimulatorCUDA; + using StateSpace = Simulator::StateSpace; + // Begin simulation with default parameters. + int largest_nq = 1; + Simulator sim = Simulator(); + StateSpace ss = StateSpace(StateSpace::Parameter()); + auto sv = ss.Create(largest_nq); + auto scratch = ss.Create(largest_nq); + + // Simulate programs one by one. Parallelizing over state vectors + // we no longer parallelize over circuits. Each time we encounter a + // a larger circuit we will grow the Statevector as necessary. + for (int i = 0; i < fused_circuits.size(); i++) { + int nq = num_qubits[i]; + + if (nq > largest_nq) { + // need to switch to larger statespace. + largest_nq = nq; + sv = ss.Create(largest_nq); + scratch = ss.Create(largest_nq); + } + // TODO: add heuristic here so that we do not always recompute + // the state if there is a possibility that circuit[i] and + // circuit[i + 1] produce the same state. + ss.SetStateZero(sv); + for (int j = 0; j < fused_circuits[i].size(); j++) { + qsim::ApplyFusedGate(sim, fused_circuits[i][j], sv); + } + for (int j = 0; j < pauli_sums[i].size(); j++) { + // (#679) Just ignore empty program + if (fused_circuits[i].size() == 0) { + (*output_tensor)(i, j) = -2.0; + continue; + } + float exp_v = 0.0; + OP_REQUIRES_OK(context, + ComputeExpectationQsim(pauli_sums[i][j], sim, ss, sv, + scratch, &exp_v)); + (*output_tensor)(i, j) = exp_v; + } + } + } + + void ComputeSmall( + const std::vector& num_qubits, const int max_num_qubits, + const std::vector>>& fused_circuits, + const std::vector>& pauli_sums, + tensorflow::OpKernelContext* context, + tensorflow::TTypes::Matrix* output_tensor) { + using Simulator = qsim::SimulatorCUDA; + using StateSpace = Simulator::StateSpace; + + StateSpace::Parameter param_default; + const int output_dim_op_size = output_tensor->dimension(1); + + Status compute_status = Status(); + auto c_lock = tensorflow::mutex(); + auto DoWork = [&](int start, int end) { + int old_batch_index = -2; + int cur_batch_index = -1; + int largest_nq = 1; + int cur_op_index; + + // Begin simulation. + auto sim = Simulator(); + auto ss = StateSpace(param_default); + auto sv = ss.Create(largest_nq); + auto scratch = ss.Create(largest_nq); + for (int i = start; i < end; i++) { + cur_batch_index = i / output_dim_op_size; + cur_op_index = i % output_dim_op_size; + + const int nq = num_qubits[cur_batch_index]; + + // (#679) Just ignore empty program + if (fused_circuits[cur_batch_index].size() == 0) { + (*output_tensor)(cur_batch_index, cur_op_index) = -2.0; + continue; + } + + if (cur_batch_index != old_batch_index) { + // We've run into a new state vector we must compute. + // Only compute a new state vector when we have to. + if (nq > largest_nq) { + largest_nq = nq; + sv = ss.Create(largest_nq); + scratch = ss.Create(largest_nq); + } + // no need to update scratch_state since ComputeExpectation + // will take care of things for us. + ss.SetStateZero(sv); + for (int j = 0; j < fused_circuits[cur_batch_index].size(); j++) { + qsim::ApplyFusedGate(sim, fused_circuits[cur_batch_index][j], sv); + } + } + + float exp_v = 0.0; + NESTED_FN_STATUS_SYNC( + compute_status, + ComputeExpectationQsim(pauli_sums[cur_batch_index][cur_op_index], + sim, ss, sv, scratch, &exp_v), + c_lock); + (*output_tensor)(cur_batch_index, cur_op_index) = exp_v; + old_batch_index = cur_batch_index; + } + }; + + const int64_t num_cycles = + 200 * (int64_t(1) << static_cast(max_num_qubits)); + context->device()->tensorflow_cpu_worker_threads()->workers->ParallelFor( + fused_circuits.size() * output_dim_op_size, num_cycles, DoWork); + OP_REQUIRES_OK(context, compute_status); + } +}; + +REGISTER_KERNEL_BUILDER( + Name("TfqSimulateExpectationCuda").Device(tensorflow::DEVICE_CPU), + TfqSimulateExpectationOpCuda); + +REGISTER_OP("TfqSimulateExpectationCuda") + .Input("programs: string") + .Input("symbol_names: string") + .Input("symbol_values: float") + .Input("pauli_sums: string") + .Output("expectations: float") + .SetShapeFn([](tensorflow::shape_inference::InferenceContext* c) { + tensorflow::shape_inference::ShapeHandle programs_shape; + TF_RETURN_IF_ERROR(c->WithRank(c->input(0), 1, &programs_shape)); + + tensorflow::shape_inference::ShapeHandle symbol_names_shape; + TF_RETURN_IF_ERROR(c->WithRank(c->input(1), 1, &symbol_names_shape)); + + tensorflow::shape_inference::ShapeHandle symbol_values_shape; + TF_RETURN_IF_ERROR(c->WithRank(c->input(2), 2, &symbol_values_shape)); + + tensorflow::shape_inference::ShapeHandle pauli_sums_shape; + TF_RETURN_IF_ERROR(c->WithRank(c->input(3), 2, &pauli_sums_shape)); + + tensorflow::shape_inference::DimensionHandle output_rows = + c->Dim(programs_shape, 0); + tensorflow::shape_inference::DimensionHandle output_cols = + c->Dim(pauli_sums_shape, 1); + c->set_output(0, c->Matrix(output_rows, output_cols)); + + return ::tensorflow::Status(); + }); + +} // namespace tfq \ No newline at end of file diff --git a/tensorflow_quantum/core/ops/tfq_simulate_expectation_op_cuquantum.cu.cc b/tensorflow_quantum/core/ops/tfq_simulate_expectation_op_cuquantum.cu.cc new file mode 100644 index 000000000..61ba96d79 --- /dev/null +++ b/tensorflow_quantum/core/ops/tfq_simulate_expectation_op_cuquantum.cu.cc @@ -0,0 +1,293 @@ +/* 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. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include +#include + +#include + +#include "../cuquantum_libs/include/custatevec.h" +#include "../qsim/lib/circuit.h" +#include "../qsim/lib/gate_appl.h" +#include "../qsim/lib/gates_cirq.h" +#include "../qsim/lib/gates_qsim.h" +#include "../qsim/lib/seqfor.h" +#include "../qsim/lib/simulator_custatevec.h" +#include "../qsim/lib/statespace_custatevec.h" +#include "tensorflow/core/framework/op_kernel.h" +#include "tensorflow/core/framework/shape_inference.h" +#include "tensorflow/core/framework/tensor_shape.h" +#include "tensorflow/core/lib/core/error_codes.pb.h" +#include "tensorflow/core/lib/core/status.h" +#include "tensorflow/core/lib/core/threadpool.h" +#include "tensorflow/core/platform/mutex.h" +#include "tensorflow_quantum/core/ops/parse_context.h" +#include "tensorflow_quantum/core/proto/pauli_sum.pb.h" +#include "tensorflow_quantum/core/proto/program.pb.h" +#include "tensorflow_quantum/core/src/util_qsim.h" + +namespace tfq { + +using ::tensorflow::Status; +using ::tfq::proto::PauliSum; +using ::tfq::proto::Program; + +typedef qsim::Cirq::GateCirq QsimGate; +typedef qsim::Circuit QsimCircuit; + + +class TfqSimulateExpectationOpCuQuantum : public tensorflow::OpKernel { + public: + explicit TfqSimulateExpectationOpCuQuantum(tensorflow::OpKernelConstruction* context) + : OpKernel(context) {} + + void Compute(tensorflow::OpKernelContext* context) override { + // TODO (mbbrough): add more dimension checks for other inputs here. + const int num_inputs = context->num_inputs(); + OP_REQUIRES(context, num_inputs == 4, + tensorflow::errors::InvalidArgument(absl::StrCat( + "Expected 4 inputs, got ", num_inputs, " inputs."))); + + // Create the output Tensor. + const int output_dim_batch_size = context->input(0).dim_size(0); + const int output_dim_op_size = context->input(3).dim_size(1); + tensorflow::TensorShape output_shape; + output_shape.AddDim(output_dim_batch_size); + output_shape.AddDim(output_dim_op_size); + + tensorflow::Tensor* output = nullptr; + tensorflow::AllocatorAttributes alloc_attr; + alloc_attr.set_on_host(true); // why?? + alloc_attr.set_gpu_compatible(true); + OP_REQUIRES_OK(context, context->allocate_output(0, output_shape, &output, + alloc_attr)); + auto output_tensor = output->matrix(); + // Parse program protos. + std::vector programs; + std::vector num_qubits; + std::vector> pauli_sums; // why is this a vector of vectors?? + OP_REQUIRES_OK(context, GetProgramsAndNumQubits(context, &programs, + &num_qubits, &pauli_sums)); + + std::vector maps; + OP_REQUIRES_OK(context, GetSymbolMaps(context, &maps)); + + OP_REQUIRES(context, programs.size() == maps.size(), + tensorflow::errors::InvalidArgument(absl::StrCat( + "Number of circuits and symbol_values do not match. Got ", + programs.size(), " circuits and ", maps.size(), + " symbol values."))); + + // Construct qsim circuits. + std::vector qsim_circuits(programs.size(), QsimCircuit()); + std::vector>> fused_circuits( + programs.size(), std::vector>({})); + + Status parse_status = Status::OK(); + auto p_lock = tensorflow::mutex(); + auto construct_f = [&](int start, int end) { + for (int i = start; i < end; i++) { + Status local = + QsimCircuitFromProgram(programs[i], maps[i], num_qubits[i], + &qsim_circuits[i], &fused_circuits[i]); + NESTED_FN_STATUS_SYNC(parse_status, local, p_lock); + } + }; + + const int num_cycles = 1000; + context->device()->tensorflow_cpu_worker_threads()->workers->ParallelFor( + programs.size(), num_cycles, construct_f); + OP_REQUIRES_OK(context, parse_status); + + int max_num_qubits = 0; + for (const int num : num_qubits) { + max_num_qubits = std::max(max_num_qubits, num); + } + + // create handles for simulator + cublasCreate(&cublas_handle_); + custatevecCreate(&custatevec_handle_); + if (max_num_qubits >= 26 || programs.size() == 1) { + ComputeLarge(num_qubits, fused_circuits, pauli_sums, context, + &output_tensor); // HOW TO manage extraWorkspace size? + } else { + ComputeSmall(num_qubits, max_num_qubits, fused_circuits, pauli_sums, + context, &output_tensor); + } + // destroy handles in sync with simulator lifetime + cublasDestroy(cublas_handle_); + custatevecDestroy(custatevec_handle_); + } + + private: + cublasHandle_t cublas_handle_; + custatevecHandle_t custatevec_handle_; + + // Define the GPU implementation that launches the CUDA kernel. + void ComputeLarge( + const std::vector& num_qubits, + const std::vector>>& fused_circuits, + const std::vector>& pauli_sums, + tensorflow::OpKernelContext* context, + tensorflow::TTypes::Matrix* output_tensor) { + // Instantiate qsim objects. + using Simulator = qsim::SimulatorCuStateVec; + using StateSpace = Simulator::StateSpace; + + + // Launch the cuda kernel. + // Begin simulation. + int largest_nq = 1; + Simulator sim = Simulator(cublas_handle_, custatevec_handle_); + StateSpace ss = StateSpace(cublas_handle_, custatevec_handle_); + auto sv = ss.Create(largest_nq); + ss.SetStateZero(sv); + auto scratch = ss.Create(largest_nq); + + // Simulate programs one by one. Parallelizing over state vectors + // we no longer parallelize over circuits. Each time we encounter a + // a larger circuit we will grow the Statevector as necessary. + for (int i = 0; i < fused_circuits.size(); i++) { + int nq = num_qubits[i]; + + if (nq > largest_nq) { + // need to switch to larger statespace. + largest_nq = nq; + sv = ss.Create(largest_nq); + scratch = ss.Create(largest_nq); + } + // TODO: add heuristic here so that we do not always recompute + // the state if there is a possibility that circuit[i] and + // circuit[i + 1] produce the same state. + ss.SetStateZero(sv); + for (int j = 0; j < fused_circuits[i].size(); j++) { + qsim::ApplyFusedGate(sim, fused_circuits[i][j], sv); + } + for (int j = 0; j < pauli_sums[i].size(); j++) { + // (#679) Just ignore empty program + if (fused_circuits[i].size() == 0) { + (*output_tensor)(i, j) = -2.0; + continue; + } + float exp_v = 0.0; + OP_REQUIRES_OK(context, + ComputeExpectationQsim(pauli_sums[i][j], sim, ss, sv, + scratch, &exp_v)); + (*output_tensor)(i, j) = exp_v; + } + } + } + + void ComputeSmall( + const std::vector& num_qubits, const int max_num_qubits, + const std::vector>>& fused_circuits, + const std::vector>& pauli_sums, + tensorflow::OpKernelContext* context, + tensorflow::TTypes::Matrix* output_tensor) { + using Simulator = qsim::SimulatorCuStateVec; + using StateSpace = Simulator::StateSpace; + + const int output_dim_op_size = output_tensor->dimension(1); + + Status compute_status = Status::OK(); + auto c_lock = tensorflow::mutex(); + auto DoWork = [&](int start, int end) { + int old_batch_index = -2; + int cur_batch_index = -1; + int largest_nq = 1; + int cur_op_index; + + // Launch custatevec, begin simulation. + auto sim = Simulator(cublas_handle_, custatevec_handle_); + auto ss = StateSpace(cublas_handle_, custatevec_handle_); + auto sv = ss.Create(largest_nq); + auto scratch = ss.Create(largest_nq); + for (int i = start; i < end; i++) { + cur_batch_index = i / output_dim_op_size; + cur_op_index = i % output_dim_op_size; + + const int nq = num_qubits[cur_batch_index]; + + // (#679) Just ignore empty program + if (fused_circuits[cur_batch_index].size() == 0) { + (*output_tensor)(cur_batch_index, cur_op_index) = -2.0; + continue; + } + + if (cur_batch_index != old_batch_index) { + // We've run into a new state vector we must compute. + // Only compute a new state vector when we have to. + if (nq > largest_nq) { + largest_nq = nq; + sv = ss.Create(largest_nq); + scratch = ss.Create(largest_nq); + } + // no need to update scratch_state since ComputeExpectation + // will take care of things for us. + ss.SetStateZero(sv); + for (int j = 0; j < fused_circuits[cur_batch_index].size(); j++) { + qsim::ApplyFusedGate(sim, fused_circuits[cur_batch_index][j], sv); + } + } + + float exp_v = 0.0; + NESTED_FN_STATUS_SYNC( + compute_status, + ComputeExpectationQsim(pauli_sums[cur_batch_index][cur_op_index], + sim, ss, sv, scratch, &exp_v), + c_lock); + (*output_tensor)(cur_batch_index, cur_op_index) = exp_v; + old_batch_index = cur_batch_index; + } + }; + + const int64_t num_cycles = + 200 * (int64_t(1) << static_cast(max_num_qubits)); + context->device()->tensorflow_cpu_worker_threads()->workers->ParallelFor( + fused_circuits.size() * output_dim_op_size, num_cycles, DoWork); + OP_REQUIRES_OK(context, compute_status); + } +}; + +REGISTER_KERNEL_BUILDER( + Name("TfqSimulateExpectationCuquantum").Device(tensorflow::DEVICE_CPU), + TfqSimulateExpectationOpCuQuantum); + +REGISTER_OP("TfqSimulateExpectationCuquantum") + .Input("programs: string") + .Input("symbol_names: string") + .Input("symbol_values: float") + .Input("pauli_sums: string") + .Output("expectations: float") + .SetShapeFn([](tensorflow::shape_inference::InferenceContext* c) { + tensorflow::shape_inference::ShapeHandle programs_shape; + TF_RETURN_IF_ERROR(c->WithRank(c->input(0), 1, &programs_shape)); + + tensorflow::shape_inference::ShapeHandle symbol_names_shape; + TF_RETURN_IF_ERROR(c->WithRank(c->input(1), 1, &symbol_names_shape)); + + tensorflow::shape_inference::ShapeHandle symbol_values_shape; + TF_RETURN_IF_ERROR(c->WithRank(c->input(2), 2, &symbol_values_shape)); + + tensorflow::shape_inference::ShapeHandle pauli_sums_shape; + TF_RETURN_IF_ERROR(c->WithRank(c->input(3), 2, &pauli_sums_shape)); + + tensorflow::shape_inference::DimensionHandle output_rows = + c->Dim(programs_shape, 0); + tensorflow::shape_inference::DimensionHandle output_cols = + c->Dim(pauli_sums_shape, 1); + c->set_output(0, c->Matrix(output_rows, output_cols)); + + return tensorflow::Status::OK(); + }); + +} // namespace tfq diff --git a/tensorflow_quantum/core/ops/tfq_simulate_ops_gpu_test.py b/tensorflow_quantum/core/ops/tfq_simulate_ops_gpu_test.py new file mode 100644 index 000000000..39571bd2d --- /dev/null +++ b/tensorflow_quantum/core/ops/tfq_simulate_ops_gpu_test.py @@ -0,0 +1,128 @@ +# 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. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== +"""Tests that specifically target tfq_simulate_ops_cu*.""" +import os +import time +import numpy as np +from absl.testing import parameterized +import tensorflow as tf +import cirq + +from tensorflow_quantum.core.ops import tfq_simulate_ops +from tensorflow_quantum.core.ops import tfq_simulate_ops_cuda +from tensorflow_quantum.core.ops import tfq_simulate_ops_cuquantum +from tensorflow_quantum.python import util + +def measure_average_runtime(fn, tag, num_samples=10): + avg_time = [] + for _ in range(num_samples): + begin_time = time.time() + result = fn() + duration = time.time() - begin_time + avg_time.append(duration) + avg_time = sum(avg_time) / float(num_samples) + print(f"\n\t{tag} time: {avg_time}\n") + return avg_time, result + + +class SimulateExpectationGpuTest(tf.test.TestCase): + """Tests tfq_simulate_expectation.""" + + def test_simulate_expectation_cpu_vs_cuda(self): + """Make sure that cpu & gpu(cuda) ops have the same results.""" + n_qubits = 20 + batch_size = 5 + symbol_names = ['alpha'] + qubits = cirq.GridQubit.rect(1, n_qubits) + circuit_batch, resolver_batch = \ + util.random_symbol_circuit_resolver_batch( + qubits, symbol_names, batch_size) + + circuit_batch_tensor = util.convert_to_tensor(circuit_batch) + + symbol_values_array = np.array( + [[resolver[symbol] + for symbol in symbol_names] + for resolver in resolver_batch]) + + pauli_sums = util.random_pauli_sums(qubits, 3, batch_size) + pauli_sums_tensor = util.convert_to_tensor([[x] for x in pauli_sums]) + + cpu_avg_time, res_cpu = measure_average_runtime( + lambda: tfq_simulate_ops.tfq_simulate_expectation( + circuit_batch_tensor, + symbol_names, symbol_values_array.astype(np.float64), + pauli_sums_tensor), + "CPU" + ) + + cuda_avg_time, res_cuda = measure_average_runtime( + lambda: tfq_simulate_ops_cuda.tfq_simulate_expectation( + circuit_batch_tensor, + symbol_names, symbol_values_array.astype(np.float64), + pauli_sums_tensor), + "CUDA" + ) + + # The result should be the similar within a tolerance. + np.testing.assert_allclose(res_cpu, res_cuda, atol=1e-5) + + # CUDA op should be faster than CPU op. + self.assertGreater(cpu_avg_time, cuda_avg_time) + + def test_simulate_expectation_cpu_vs_cuquantum(self): + """Make sure that cpu & gpu(cuquantum) ops have the same results.""" + n_qubits = 20 + batch_size = 5 + symbol_names = ['alpha'] + qubits = cirq.GridQubit.rect(1, n_qubits) + circuit_batch, resolver_batch = \ + util.random_symbol_circuit_resolver_batch( + qubits, symbol_names, batch_size) + + circuit_batch_tensor = util.convert_to_tensor(circuit_batch) + + symbol_values_array = np.array( + [[resolver[symbol] + for symbol in symbol_names] + for resolver in resolver_batch]) + + pauli_sums = util.random_pauli_sums(qubits, 3, batch_size) + pauli_sums_tensor = util.convert_to_tensor([[x] for x in pauli_sums]) + + cpu_avg_time, res_cpu = measure_average_runtime( + lambda: tfq_simulate_ops.tfq_simulate_expectation( + circuit_batch_tensor, + symbol_names, symbol_values_array.astype(np.float64), + pauli_sums_tensor), + "CPU" + ) + + cuda_avg_time, res_cuda = measure_average_runtime( + lambda: tfq_simulate_ops_cuquantum.tfq_simulate_expectation( + circuit_batch_tensor, + symbol_names, symbol_values_array.astype(np.float64), + pauli_sums_tensor), + "cuQuantum" + ) + + # The result should be the similar within a tolerance. + np.testing.assert_allclose(res_cpu, res_cuda, atol=1e-5) + + # cuQuantum op should be faster than CPU op. + self.assertGreater(cpu_avg_time, cuda_avg_time) + +if __name__ == "__main__": + tf.test.main() \ No newline at end of file From 585b47d858ee92aa25805bc5829547ab2df98f81 Mon Sep 17 00:00:00 2001 From: Michael Broughton Date: Mon, 12 Jun 2023 14:10:36 -0700 Subject: [PATCH 18/50] Revert "Fix lint" This reverts commit 20815bc5f5977f189f467d5726f101b82f1498f1. --- .../core/ops/tfq_simulate_expectation_op_cuquantum.cu.cc | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/tensorflow_quantum/core/ops/tfq_simulate_expectation_op_cuquantum.cu.cc b/tensorflow_quantum/core/ops/tfq_simulate_expectation_op_cuquantum.cu.cc index 61ba96d79..c1c65c35a 100644 --- a/tensorflow_quantum/core/ops/tfq_simulate_expectation_op_cuquantum.cu.cc +++ b/tensorflow_quantum/core/ops/tfq_simulate_expectation_op_cuquantum.cu.cc @@ -116,13 +116,7 @@ class TfqSimulateExpectationOpCuQuantum : public tensorflow::OpKernel { // create handles for simulator cublasCreate(&cublas_handle_); custatevecCreate(&custatevec_handle_); - if (max_num_qubits >= 26 || programs.size() == 1) { - ComputeLarge(num_qubits, fused_circuits, pauli_sums, context, - &output_tensor); // HOW TO manage extraWorkspace size? - } else { - ComputeSmall(num_qubits, max_num_qubits, fused_circuits, pauli_sums, - context, &output_tensor); - } + // destroy handles in sync with simulator lifetime cublasDestroy(cublas_handle_); custatevecDestroy(custatevec_handle_); From 7044721bed019edc6da82d6f90e78f5e12bf9231 Mon Sep 17 00:00:00 2001 From: Michael Broughton Date: Mon, 12 Jun 2023 14:11:06 -0700 Subject: [PATCH 19/50] Revert "Fix lint" This reverts commit 47e6aaeefffa7d8ce66ea632998dceb2a15be28c. --- .../core/ops/tfq_simulate_expectation_op_cuda.cu.cc | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/tensorflow_quantum/core/ops/tfq_simulate_expectation_op_cuda.cu.cc b/tensorflow_quantum/core/ops/tfq_simulate_expectation_op_cuda.cu.cc index a7a448bd0..43fa1739f 100644 --- a/tensorflow_quantum/core/ops/tfq_simulate_expectation_op_cuda.cu.cc +++ b/tensorflow_quantum/core/ops/tfq_simulate_expectation_op_cuda.cu.cc @@ -111,6 +111,7 @@ class TfqSimulateExpectationOpCuda : public tensorflow::OpKernel { for (const int num : num_qubits) { max_num_qubits = std::max(max_num_qubits, num); } +<<<<<<< HEAD if (max_num_qubits >= 26 || programs.size() == 1) { ComputeLarge(num_qubits, fused_circuits, pauli_sums, context, &output_tensor); @@ -118,6 +119,12 @@ class TfqSimulateExpectationOpCuda : public tensorflow::OpKernel { ComputeSmall(num_qubits, max_num_qubits, fused_circuits, pauli_sums, context, &output_tensor); } +======= + + ComputeLarge(num_qubits, fused_circuits, pauli_sums, context, + &output_tensor); + +>>>>>>> parent of 47e6aae (Fix lint) } private: From 86b31a2a2920b61708f5594005c678f2a9a53abc Mon Sep 17 00:00:00 2001 From: Michael Broughton Date: Mon, 12 Jun 2023 14:11:08 -0700 Subject: [PATCH 20/50] Revert "Update release/BUILD with `if_cuda_is_configured`" This reverts commit f2cd2552b001004bae0f3d843860e5485b7443a2. --- release/BUILD | 2 ++ 1 file changed, 2 insertions(+) diff --git a/release/BUILD b/release/BUILD index 7212cb1d3..0701b894f 100644 --- a/release/BUILD +++ b/release/BUILD @@ -39,6 +39,8 @@ sh_binary( "//tensorflow_quantum/core/ops:tfq_unitary_op_py", "//tensorflow_quantum/core/ops:tfq_utility_ops_py", "//tensorflow_quantum/core/ops:tfq_simulate_ops_py", + "//tensorflow_quantum/core/ops:tfq_simulate_ops_cuda_py", + "//tensorflow_quantum/core/ops:tfq_simulate_ops_cuquantum_py", "//tensorflow_quantum/core/ops/math_ops:fidelity_op_py", "//tensorflow_quantum/core/ops/math_ops:inner_product_op_py", "//tensorflow_quantum/core/ops/math_ops:simulate_mps_py", From 6f5b7255d3531374cb9db9dbb955422d48f34ca4 Mon Sep 17 00:00:00 2001 From: Michael Broughton Date: Mon, 12 Jun 2023 14:11:55 -0700 Subject: [PATCH 21/50] Revert "add :tfq_simulate_ops_cuquantum_py target to release BUILD" This reverts commit 3e8a9a42d16e1b092d29db1af623c2ff8609baf8. --- release/BUILD | 2 -- 1 file changed, 2 deletions(-) diff --git a/release/BUILD b/release/BUILD index 0701b894f..7212cb1d3 100644 --- a/release/BUILD +++ b/release/BUILD @@ -39,8 +39,6 @@ sh_binary( "//tensorflow_quantum/core/ops:tfq_unitary_op_py", "//tensorflow_quantum/core/ops:tfq_utility_ops_py", "//tensorflow_quantum/core/ops:tfq_simulate_ops_py", - "//tensorflow_quantum/core/ops:tfq_simulate_ops_cuda_py", - "//tensorflow_quantum/core/ops:tfq_simulate_ops_cuquantum_py", "//tensorflow_quantum/core/ops/math_ops:fidelity_op_py", "//tensorflow_quantum/core/ops/math_ops:inner_product_op_py", "//tensorflow_quantum/core/ops/math_ops:simulate_mps_py", From 47818a6427b46e7106070bed19c518e97638a238 Mon Sep 17 00:00:00 2001 From: Michael Broughton Date: Mon, 12 Jun 2023 14:13:13 -0700 Subject: [PATCH 22/50] Revert "remove computeSmall from cuda and cuquantum kernels" This reverts commit 5cb7fa153f694e4ae1d1eb94c69b78e5b0d88e4b. --- .../core/ops/tfq_simulate_expectation_op_cuda.cu.cc | 7 ------- 1 file changed, 7 deletions(-) diff --git a/tensorflow_quantum/core/ops/tfq_simulate_expectation_op_cuda.cu.cc b/tensorflow_quantum/core/ops/tfq_simulate_expectation_op_cuda.cu.cc index 43fa1739f..a7a448bd0 100644 --- a/tensorflow_quantum/core/ops/tfq_simulate_expectation_op_cuda.cu.cc +++ b/tensorflow_quantum/core/ops/tfq_simulate_expectation_op_cuda.cu.cc @@ -111,7 +111,6 @@ class TfqSimulateExpectationOpCuda : public tensorflow::OpKernel { for (const int num : num_qubits) { max_num_qubits = std::max(max_num_qubits, num); } -<<<<<<< HEAD if (max_num_qubits >= 26 || programs.size() == 1) { ComputeLarge(num_qubits, fused_circuits, pauli_sums, context, &output_tensor); @@ -119,12 +118,6 @@ class TfqSimulateExpectationOpCuda : public tensorflow::OpKernel { ComputeSmall(num_qubits, max_num_qubits, fused_circuits, pauli_sums, context, &output_tensor); } -======= - - ComputeLarge(num_qubits, fused_circuits, pauli_sums, context, - &output_tensor); - ->>>>>>> parent of 47e6aae (Fix lint) } private: From 7413a700499d14247047c64cc70948d9516cbd21 Mon Sep 17 00:00:00 2001 From: Michael Broughton Date: Mon, 12 Jun 2023 14:14:35 -0700 Subject: [PATCH 23/50] Revert "Merge pull request #2 from jaeyoo/cuquantum_support" This reverts commit 46aa1f0eb43473967f81e14b00a706adefc37482, reversing changes made to 2a5fd073deecc9c9a07cf2d85e7befb3f3554fcb. --- ..._test.py => tfq_simulate_ops_cuda_test.py} | 46 +------------------ 1 file changed, 2 insertions(+), 44 deletions(-) rename tensorflow_quantum/core/ops/{tfq_simulate_ops_gpu_test.py => tfq_simulate_ops_cuda_test.py} (62%) diff --git a/tensorflow_quantum/core/ops/tfq_simulate_ops_gpu_test.py b/tensorflow_quantum/core/ops/tfq_simulate_ops_cuda_test.py similarity index 62% rename from tensorflow_quantum/core/ops/tfq_simulate_ops_gpu_test.py rename to tensorflow_quantum/core/ops/tfq_simulate_ops_cuda_test.py index 39571bd2d..dce578d30 100644 --- a/tensorflow_quantum/core/ops/tfq_simulate_ops_gpu_test.py +++ b/tensorflow_quantum/core/ops/tfq_simulate_ops_cuda_test.py @@ -12,7 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. # ============================================================================== -"""Tests that specifically target tfq_simulate_ops_cu*.""" +"""Tests that specifically target tfq_simulate_ops_cuda.""" import os import time import numpy as np @@ -22,7 +22,6 @@ from tensorflow_quantum.core.ops import tfq_simulate_ops from tensorflow_quantum.core.ops import tfq_simulate_ops_cuda -from tensorflow_quantum.core.ops import tfq_simulate_ops_cuquantum from tensorflow_quantum.python import util def measure_average_runtime(fn, tag, num_samples=10): @@ -37,7 +36,7 @@ def measure_average_runtime(fn, tag, num_samples=10): return avg_time, result -class SimulateExpectationGpuTest(tf.test.TestCase): +class SimulateExpectationTest(tf.test.TestCase): """Tests tfq_simulate_expectation.""" def test_simulate_expectation_cpu_vs_cuda(self): @@ -82,47 +81,6 @@ def test_simulate_expectation_cpu_vs_cuda(self): # CUDA op should be faster than CPU op. self.assertGreater(cpu_avg_time, cuda_avg_time) - def test_simulate_expectation_cpu_vs_cuquantum(self): - """Make sure that cpu & gpu(cuquantum) ops have the same results.""" - n_qubits = 20 - batch_size = 5 - symbol_names = ['alpha'] - qubits = cirq.GridQubit.rect(1, n_qubits) - circuit_batch, resolver_batch = \ - util.random_symbol_circuit_resolver_batch( - qubits, symbol_names, batch_size) - - circuit_batch_tensor = util.convert_to_tensor(circuit_batch) - - symbol_values_array = np.array( - [[resolver[symbol] - for symbol in symbol_names] - for resolver in resolver_batch]) - - pauli_sums = util.random_pauli_sums(qubits, 3, batch_size) - pauli_sums_tensor = util.convert_to_tensor([[x] for x in pauli_sums]) - - cpu_avg_time, res_cpu = measure_average_runtime( - lambda: tfq_simulate_ops.tfq_simulate_expectation( - circuit_batch_tensor, - symbol_names, symbol_values_array.astype(np.float64), - pauli_sums_tensor), - "CPU" - ) - - cuda_avg_time, res_cuda = measure_average_runtime( - lambda: tfq_simulate_ops_cuquantum.tfq_simulate_expectation( - circuit_batch_tensor, - symbol_names, symbol_values_array.astype(np.float64), - pauli_sums_tensor), - "cuQuantum" - ) - - # The result should be the similar within a tolerance. - np.testing.assert_allclose(res_cpu, res_cuda, atol=1e-5) - - # cuQuantum op should be faster than CPU op. - self.assertGreater(cpu_avg_time, cuda_avg_time) if __name__ == "__main__": tf.test.main() \ No newline at end of file From 303730b7bd5ec68b232eaa89dd7c0d12d736c313 Mon Sep 17 00:00:00 2001 From: Michael Broughton Date: Mon, 12 Jun 2023 14:14:37 -0700 Subject: [PATCH 24/50] Revert "Merge pull request #1 from jaeyoo/cuda_support" This reverts commit 2a5fd073deecc9c9a07cf2d85e7befb3f3554fcb, reversing changes made to b0dd7451567fa1a7ad6f0907320344617892c9ea. --- tensorflow_quantum/core/ops/BUILD | 1 - .../tfq_simulate_expectation_op_cuda.cu.cc | 282 ------------------ .../core/ops/tfq_simulate_ops_cuda_test.py | 86 ------ 3 files changed, 369 deletions(-) delete mode 100644 tensorflow_quantum/core/ops/tfq_simulate_expectation_op_cuda.cu.cc delete mode 100644 tensorflow_quantum/core/ops/tfq_simulate_ops_cuda_test.py diff --git a/tensorflow_quantum/core/ops/BUILD b/tensorflow_quantum/core/ops/BUILD index 3983d068b..8087a8d3b 100644 --- a/tensorflow_quantum/core/ops/BUILD +++ b/tensorflow_quantum/core/ops/BUILD @@ -24,7 +24,6 @@ py_library( ":tfq_adj_grad_op_py", ":tfq_ps_util_ops_py", ":tfq_simulate_ops_py", - ":tfq_simulate_ops_cuda_py", ":tfq_unitary_op_py", ":tfq_utility_ops_py", # test addons diff --git a/tensorflow_quantum/core/ops/tfq_simulate_expectation_op_cuda.cu.cc b/tensorflow_quantum/core/ops/tfq_simulate_expectation_op_cuda.cu.cc deleted file mode 100644 index a7a448bd0..000000000 --- a/tensorflow_quantum/core/ops/tfq_simulate_expectation_op_cuda.cu.cc +++ /dev/null @@ -1,282 +0,0 @@ -/* 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. -See the License for the specific language governing permissions and -limitations under the License. -==============================================================================*/ - -#include -#include - -#include - -#include "../qsim/lib/circuit.h" -#include "../qsim/lib/gate_appl.h" -#include "../qsim/lib/gates_cirq.h" -#include "../qsim/lib/gates_qsim.h" -#include "../qsim/lib/seqfor.h" -#include "../qsim/lib/simulator_cuda.h" -#include "../qsim/lib/statespace_cuda.h" -#include "tensorflow/core/framework/op_kernel.h" -#include "tensorflow/core/framework/shape_inference.h" -#include "tensorflow/core/framework/tensor_shape.h" -#include "tensorflow/core/lib/core/error_codes.pb.h" -#include "tensorflow/core/lib/core/status.h" -#include "tensorflow/core/lib/core/threadpool.h" -#include "tensorflow/core/platform/mutex.h" -#include "tensorflow_quantum/core/ops/parse_context.h" -#include "tensorflow_quantum/core/proto/pauli_sum.pb.h" -#include "tensorflow_quantum/core/proto/program.pb.h" -#include "tensorflow_quantum/core/src/util_qsim.h" - -namespace tfq { - -using ::tensorflow::Status; -using ::tfq::proto::PauliSum; -using ::tfq::proto::Program; - -typedef qsim::Cirq::GateCirq QsimGate; -typedef qsim::Circuit QsimCircuit; - - -class TfqSimulateExpectationOpCuda : public tensorflow::OpKernel { - public: - explicit TfqSimulateExpectationOpCuda(tensorflow::OpKernelConstruction* context) - : OpKernel(context) {} - - void Compute(tensorflow::OpKernelContext* context) override { - // TODO (mbbrough): add more dimension checks for other inputs here. - const int num_inputs = context->num_inputs(); - OP_REQUIRES(context, num_inputs == 4, - tensorflow::errors::InvalidArgument(absl::StrCat( - "Expected 4 inputs, got ", num_inputs, " inputs."))); - - // Create the output Tensor. - const int output_dim_batch_size = context->input(0).dim_size(0); - const int output_dim_op_size = context->input(3).dim_size(1); - tensorflow::TensorShape output_shape; - output_shape.AddDim(output_dim_batch_size); - output_shape.AddDim(output_dim_op_size); - - tensorflow::Tensor* output = nullptr; - tensorflow::AllocatorAttributes alloc_attr; - alloc_attr.set_on_host(true); - alloc_attr.set_gpu_compatible(true); - OP_REQUIRES_OK(context, context->allocate_output(0, output_shape, &output, - alloc_attr)); - auto output_tensor = output->matrix(); - // Parse program protos. - std::vector programs; - std::vector num_qubits; - std::vector> pauli_sums; - OP_REQUIRES_OK(context, GetProgramsAndNumQubits(context, &programs, - &num_qubits, &pauli_sums)); - - std::vector maps; - OP_REQUIRES_OK(context, GetSymbolMaps(context, &maps)); - - OP_REQUIRES(context, programs.size() == maps.size(), - tensorflow::errors::InvalidArgument(absl::StrCat( - "Number of circuits and symbol_values do not match. Got ", - programs.size(), " circuits and ", maps.size(), - " symbol values."))); - - // Construct qsim circuits. - std::vector qsim_circuits(programs.size(), QsimCircuit()); - std::vector>> fused_circuits( - programs.size(), std::vector>({})); - - Status parse_status = Status(); - auto p_lock = tensorflow::mutex(); - auto construct_f = [&](int start, int end) { - for (int i = start; i < end; i++) { - Status local = - QsimCircuitFromProgram(programs[i], maps[i], num_qubits[i], - &qsim_circuits[i], &fused_circuits[i]); - NESTED_FN_STATUS_SYNC(parse_status, local, p_lock); - } - }; - - const int num_cycles = 1000; - context->device()->tensorflow_cpu_worker_threads()->workers->ParallelFor( - programs.size(), num_cycles, construct_f); - OP_REQUIRES_OK(context, parse_status); - - int max_num_qubits = 0; - for (const int num : num_qubits) { - max_num_qubits = std::max(max_num_qubits, num); - } - if (max_num_qubits >= 26 || programs.size() == 1) { - ComputeLarge(num_qubits, fused_circuits, pauli_sums, context, - &output_tensor); - } else { - ComputeSmall(num_qubits, max_num_qubits, fused_circuits, pauli_sums, - context, &output_tensor); - } - } - - private: - int num_threads_in_sim_; - int block_count_; - - // Define the GPU implementation that launches the CUDA kernel. - void ComputeLarge( - const std::vector& num_qubits, - const std::vector>>& fused_circuits, - const std::vector>& pauli_sums, - tensorflow::OpKernelContext* context, - tensorflow::TTypes::Matrix* output_tensor) { - // Instantiate qsim objects. - using Simulator = qsim::SimulatorCUDA; - using StateSpace = Simulator::StateSpace; - // Begin simulation with default parameters. - int largest_nq = 1; - Simulator sim = Simulator(); - StateSpace ss = StateSpace(StateSpace::Parameter()); - auto sv = ss.Create(largest_nq); - auto scratch = ss.Create(largest_nq); - - // Simulate programs one by one. Parallelizing over state vectors - // we no longer parallelize over circuits. Each time we encounter a - // a larger circuit we will grow the Statevector as necessary. - for (int i = 0; i < fused_circuits.size(); i++) { - int nq = num_qubits[i]; - - if (nq > largest_nq) { - // need to switch to larger statespace. - largest_nq = nq; - sv = ss.Create(largest_nq); - scratch = ss.Create(largest_nq); - } - // TODO: add heuristic here so that we do not always recompute - // the state if there is a possibility that circuit[i] and - // circuit[i + 1] produce the same state. - ss.SetStateZero(sv); - for (int j = 0; j < fused_circuits[i].size(); j++) { - qsim::ApplyFusedGate(sim, fused_circuits[i][j], sv); - } - for (int j = 0; j < pauli_sums[i].size(); j++) { - // (#679) Just ignore empty program - if (fused_circuits[i].size() == 0) { - (*output_tensor)(i, j) = -2.0; - continue; - } - float exp_v = 0.0; - OP_REQUIRES_OK(context, - ComputeExpectationQsim(pauli_sums[i][j], sim, ss, sv, - scratch, &exp_v)); - (*output_tensor)(i, j) = exp_v; - } - } - } - - void ComputeSmall( - const std::vector& num_qubits, const int max_num_qubits, - const std::vector>>& fused_circuits, - const std::vector>& pauli_sums, - tensorflow::OpKernelContext* context, - tensorflow::TTypes::Matrix* output_tensor) { - using Simulator = qsim::SimulatorCUDA; - using StateSpace = Simulator::StateSpace; - - StateSpace::Parameter param_default; - const int output_dim_op_size = output_tensor->dimension(1); - - Status compute_status = Status(); - auto c_lock = tensorflow::mutex(); - auto DoWork = [&](int start, int end) { - int old_batch_index = -2; - int cur_batch_index = -1; - int largest_nq = 1; - int cur_op_index; - - // Begin simulation. - auto sim = Simulator(); - auto ss = StateSpace(param_default); - auto sv = ss.Create(largest_nq); - auto scratch = ss.Create(largest_nq); - for (int i = start; i < end; i++) { - cur_batch_index = i / output_dim_op_size; - cur_op_index = i % output_dim_op_size; - - const int nq = num_qubits[cur_batch_index]; - - // (#679) Just ignore empty program - if (fused_circuits[cur_batch_index].size() == 0) { - (*output_tensor)(cur_batch_index, cur_op_index) = -2.0; - continue; - } - - if (cur_batch_index != old_batch_index) { - // We've run into a new state vector we must compute. - // Only compute a new state vector when we have to. - if (nq > largest_nq) { - largest_nq = nq; - sv = ss.Create(largest_nq); - scratch = ss.Create(largest_nq); - } - // no need to update scratch_state since ComputeExpectation - // will take care of things for us. - ss.SetStateZero(sv); - for (int j = 0; j < fused_circuits[cur_batch_index].size(); j++) { - qsim::ApplyFusedGate(sim, fused_circuits[cur_batch_index][j], sv); - } - } - - float exp_v = 0.0; - NESTED_FN_STATUS_SYNC( - compute_status, - ComputeExpectationQsim(pauli_sums[cur_batch_index][cur_op_index], - sim, ss, sv, scratch, &exp_v), - c_lock); - (*output_tensor)(cur_batch_index, cur_op_index) = exp_v; - old_batch_index = cur_batch_index; - } - }; - - const int64_t num_cycles = - 200 * (int64_t(1) << static_cast(max_num_qubits)); - context->device()->tensorflow_cpu_worker_threads()->workers->ParallelFor( - fused_circuits.size() * output_dim_op_size, num_cycles, DoWork); - OP_REQUIRES_OK(context, compute_status); - } -}; - -REGISTER_KERNEL_BUILDER( - Name("TfqSimulateExpectationCuda").Device(tensorflow::DEVICE_CPU), - TfqSimulateExpectationOpCuda); - -REGISTER_OP("TfqSimulateExpectationCuda") - .Input("programs: string") - .Input("symbol_names: string") - .Input("symbol_values: float") - .Input("pauli_sums: string") - .Output("expectations: float") - .SetShapeFn([](tensorflow::shape_inference::InferenceContext* c) { - tensorflow::shape_inference::ShapeHandle programs_shape; - TF_RETURN_IF_ERROR(c->WithRank(c->input(0), 1, &programs_shape)); - - tensorflow::shape_inference::ShapeHandle symbol_names_shape; - TF_RETURN_IF_ERROR(c->WithRank(c->input(1), 1, &symbol_names_shape)); - - tensorflow::shape_inference::ShapeHandle symbol_values_shape; - TF_RETURN_IF_ERROR(c->WithRank(c->input(2), 2, &symbol_values_shape)); - - tensorflow::shape_inference::ShapeHandle pauli_sums_shape; - TF_RETURN_IF_ERROR(c->WithRank(c->input(3), 2, &pauli_sums_shape)); - - tensorflow::shape_inference::DimensionHandle output_rows = - c->Dim(programs_shape, 0); - tensorflow::shape_inference::DimensionHandle output_cols = - c->Dim(pauli_sums_shape, 1); - c->set_output(0, c->Matrix(output_rows, output_cols)); - - return ::tensorflow::Status(); - }); - -} // namespace tfq \ No newline at end of file diff --git a/tensorflow_quantum/core/ops/tfq_simulate_ops_cuda_test.py b/tensorflow_quantum/core/ops/tfq_simulate_ops_cuda_test.py deleted file mode 100644 index dce578d30..000000000 --- a/tensorflow_quantum/core/ops/tfq_simulate_ops_cuda_test.py +++ /dev/null @@ -1,86 +0,0 @@ -# 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. -# See the License for the specific language governing permissions and -# limitations under the License. -# ============================================================================== -"""Tests that specifically target tfq_simulate_ops_cuda.""" -import os -import time -import numpy as np -from absl.testing import parameterized -import tensorflow as tf -import cirq - -from tensorflow_quantum.core.ops import tfq_simulate_ops -from tensorflow_quantum.core.ops import tfq_simulate_ops_cuda -from tensorflow_quantum.python import util - -def measure_average_runtime(fn, tag, num_samples=10): - avg_time = [] - for _ in range(num_samples): - begin_time = time.time() - result = fn() - duration = time.time() - begin_time - avg_time.append(duration) - avg_time = sum(avg_time) / float(num_samples) - print(f"\n\t{tag} time: {avg_time}\n") - return avg_time, result - - -class SimulateExpectationTest(tf.test.TestCase): - """Tests tfq_simulate_expectation.""" - - def test_simulate_expectation_cpu_vs_cuda(self): - """Make sure that cpu & gpu(cuda) ops have the same results.""" - n_qubits = 20 - batch_size = 5 - symbol_names = ['alpha'] - qubits = cirq.GridQubit.rect(1, n_qubits) - circuit_batch, resolver_batch = \ - util.random_symbol_circuit_resolver_batch( - qubits, symbol_names, batch_size) - - circuit_batch_tensor = util.convert_to_tensor(circuit_batch) - - symbol_values_array = np.array( - [[resolver[symbol] - for symbol in symbol_names] - for resolver in resolver_batch]) - - pauli_sums = util.random_pauli_sums(qubits, 3, batch_size) - pauli_sums_tensor = util.convert_to_tensor([[x] for x in pauli_sums]) - - cpu_avg_time, res_cpu = measure_average_runtime( - lambda: tfq_simulate_ops.tfq_simulate_expectation( - circuit_batch_tensor, - symbol_names, symbol_values_array.astype(np.float64), - pauli_sums_tensor), - "CPU" - ) - - cuda_avg_time, res_cuda = measure_average_runtime( - lambda: tfq_simulate_ops_cuda.tfq_simulate_expectation( - circuit_batch_tensor, - symbol_names, symbol_values_array.astype(np.float64), - pauli_sums_tensor), - "CUDA" - ) - - # The result should be the similar within a tolerance. - np.testing.assert_allclose(res_cpu, res_cuda, atol=1e-5) - - # CUDA op should be faster than CPU op. - self.assertGreater(cpu_avg_time, cuda_avg_time) - - -if __name__ == "__main__": - tf.test.main() \ No newline at end of file From 028ee7d61b6be4f0b01b5a7f65f1745249d3458c Mon Sep 17 00:00:00 2001 From: Michael Broughton Date: Mon, 12 Jun 2023 14:14:39 -0700 Subject: [PATCH 25/50] Revert "Merge branch 'master' into cuda_support" This reverts commit f19298ccb5bdcbee27b931f43690cad228420f57, reversing changes made to 4f6290acab99f65733c36aff4f628c1b11ae42a9. --- configure.sh | 1 + release/setup.py | 2 +- requirements.txt | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/configure.sh b/configure.sh index 5efd4212a..e212efeab 100755 --- a/configure.sh +++ b/configure.sh @@ -99,6 +99,7 @@ if [[ "$PIP_MANYLINUX2010" == "0" ]]; then write_to_bazelrc "build:cuda --crosstool_top=@local_config_cuda//crosstool:toolchain" fi + write_to_bazelrc "build --experimental_repo_remote_exec" write_to_bazelrc "build --spawn_strategy=standalone" write_to_bazelrc "build --strategy=Genrule=standalone" diff --git a/release/setup.py b/release/setup.py index b3ff0ded7..24424b613 100644 --- a/release/setup.py +++ b/release/setup.py @@ -53,7 +53,7 @@ def finalize_options(self): REQUIRED_PACKAGES = [ 'cirq-core==0.13.1', 'cirq-google>=0.13.1', 'sympy == 1.8', 'googleapis-common-protos==1.52.0', 'google-api-core==1.21.0', - 'google-auth==1.18.0', 'protobuf==3.19.5' + 'google-auth==1.18.0', 'protobuf==3.19.4' ] # placed as extra to not have required overwrite existing nightly installs if diff --git a/requirements.txt b/requirements.txt index 578179982..ae8700878 100644 --- a/requirements.txt +++ b/requirements.txt @@ -12,4 +12,4 @@ google-api-core==1.21.0 google-auth==1.18.0 google-api-python-client==1.8.0 grpcio==1.34.1 -protobuf==3.19.5 +protobuf==3.19.4 From 6c7ed1d4c6b1f26d1a37ee560af34fbc2136dbfa Mon Sep 17 00:00:00 2001 From: Michael Broughton Date: Mon, 12 Jun 2023 14:15:23 -0700 Subject: [PATCH 26/50] Revert "Add cuQuantum test (but failed at numeric diff test)" This reverts commit f97c496bfd939b2ec5534718618be76274b76e20. --- ...fq_simulate_expectation_op_cuquantum.cu.cc | 14 +-- .../core/ops/tfq_simulate_ops_cuda_test.py | 86 +++++++++++++++++++ 2 files changed, 93 insertions(+), 7 deletions(-) create mode 100644 tensorflow_quantum/core/ops/tfq_simulate_ops_cuda_test.py diff --git a/tensorflow_quantum/core/ops/tfq_simulate_expectation_op_cuquantum.cu.cc b/tensorflow_quantum/core/ops/tfq_simulate_expectation_op_cuquantum.cu.cc index c1c65c35a..94ac3c43e 100644 --- a/tensorflow_quantum/core/ops/tfq_simulate_expectation_op_cuquantum.cu.cc +++ b/tensorflow_quantum/core/ops/tfq_simulate_expectation_op_cuquantum.cu.cc @@ -14,8 +14,8 @@ limitations under the License. #include #include +#include -#include "../cuquantum_libs/include/custatevec.h" #include "../qsim/lib/circuit.h" #include "../qsim/lib/gate_appl.h" #include "../qsim/lib/gates_cirq.h" @@ -48,7 +48,7 @@ typedef qsim::Circuit QsimCircuit; class TfqSimulateExpectationOpCuQuantum : public tensorflow::OpKernel { public: explicit TfqSimulateExpectationOpCuQuantum(tensorflow::OpKernelConstruction* context) - : OpKernel(context) {} + : OpKernel(context) { } void Compute(tensorflow::OpKernelContext* context) override { // TODO (mbbrough): add more dimension checks for other inputs here. @@ -141,7 +141,7 @@ class TfqSimulateExpectationOpCuQuantum : public tensorflow::OpKernel { // Launch the cuda kernel. // Begin simulation. int largest_nq = 1; - Simulator sim = Simulator(cublas_handle_, custatevec_handle_); + Simulator sim = Simulator(custatevec_handle_); StateSpace ss = StateSpace(cublas_handle_, custatevec_handle_); auto sv = ss.Create(largest_nq); ss.SetStateZero(sv); @@ -201,7 +201,7 @@ class TfqSimulateExpectationOpCuQuantum : public tensorflow::OpKernel { int cur_op_index; // Launch custatevec, begin simulation. - auto sim = Simulator(cublas_handle_, custatevec_handle_); + auto sim = Simulator(custatevec_handle_); auto ss = StateSpace(cublas_handle_, custatevec_handle_); auto sv = ss.Create(largest_nq); auto scratch = ss.Create(largest_nq); @@ -253,10 +253,10 @@ class TfqSimulateExpectationOpCuQuantum : public tensorflow::OpKernel { }; REGISTER_KERNEL_BUILDER( - Name("TfqSimulateExpectationCuquantum").Device(tensorflow::DEVICE_CPU), - TfqSimulateExpectationOpCuQuantum); + Name("TfqSimulateExpectationOpCuQuantum").Device(tensorflow::DEVICE_CPU), + TfqSimulateExpectationOpCuQuantumOp); -REGISTER_OP("TfqSimulateExpectationCuquantum") +REGISTER_OP("TfqSimulateExpectationOpCuQuantum") .Input("programs: string") .Input("symbol_names: string") .Input("symbol_values: float") diff --git a/tensorflow_quantum/core/ops/tfq_simulate_ops_cuda_test.py b/tensorflow_quantum/core/ops/tfq_simulate_ops_cuda_test.py new file mode 100644 index 000000000..dce578d30 --- /dev/null +++ b/tensorflow_quantum/core/ops/tfq_simulate_ops_cuda_test.py @@ -0,0 +1,86 @@ +# 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. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== +"""Tests that specifically target tfq_simulate_ops_cuda.""" +import os +import time +import numpy as np +from absl.testing import parameterized +import tensorflow as tf +import cirq + +from tensorflow_quantum.core.ops import tfq_simulate_ops +from tensorflow_quantum.core.ops import tfq_simulate_ops_cuda +from tensorflow_quantum.python import util + +def measure_average_runtime(fn, tag, num_samples=10): + avg_time = [] + for _ in range(num_samples): + begin_time = time.time() + result = fn() + duration = time.time() - begin_time + avg_time.append(duration) + avg_time = sum(avg_time) / float(num_samples) + print(f"\n\t{tag} time: {avg_time}\n") + return avg_time, result + + +class SimulateExpectationTest(tf.test.TestCase): + """Tests tfq_simulate_expectation.""" + + def test_simulate_expectation_cpu_vs_cuda(self): + """Make sure that cpu & gpu(cuda) ops have the same results.""" + n_qubits = 20 + batch_size = 5 + symbol_names = ['alpha'] + qubits = cirq.GridQubit.rect(1, n_qubits) + circuit_batch, resolver_batch = \ + util.random_symbol_circuit_resolver_batch( + qubits, symbol_names, batch_size) + + circuit_batch_tensor = util.convert_to_tensor(circuit_batch) + + symbol_values_array = np.array( + [[resolver[symbol] + for symbol in symbol_names] + for resolver in resolver_batch]) + + pauli_sums = util.random_pauli_sums(qubits, 3, batch_size) + pauli_sums_tensor = util.convert_to_tensor([[x] for x in pauli_sums]) + + cpu_avg_time, res_cpu = measure_average_runtime( + lambda: tfq_simulate_ops.tfq_simulate_expectation( + circuit_batch_tensor, + symbol_names, symbol_values_array.astype(np.float64), + pauli_sums_tensor), + "CPU" + ) + + cuda_avg_time, res_cuda = measure_average_runtime( + lambda: tfq_simulate_ops_cuda.tfq_simulate_expectation( + circuit_batch_tensor, + symbol_names, symbol_values_array.astype(np.float64), + pauli_sums_tensor), + "CUDA" + ) + + # The result should be the similar within a tolerance. + np.testing.assert_allclose(res_cpu, res_cuda, atol=1e-5) + + # CUDA op should be faster than CPU op. + self.assertGreater(cpu_avg_time, cuda_avg_time) + + +if __name__ == "__main__": + tf.test.main() \ No newline at end of file From 5a4a6c7c967faf1a74941d38898502156c327d62 Mon Sep 17 00:00:00 2001 From: Michael Broughton Date: Mon, 12 Jun 2023 14:15:50 -0700 Subject: [PATCH 27/50] Revert "Fix ComputeSmall and enable it." This reverts commit 4f6290acab99f65733c36aff4f628c1b11ae42a9. --- ...fq_simulate_expectation_op_cuquantum.cu.cc | 50 +++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/tensorflow_quantum/core/ops/tfq_simulate_expectation_op_cuquantum.cu.cc b/tensorflow_quantum/core/ops/tfq_simulate_expectation_op_cuquantum.cu.cc index 94ac3c43e..4d3512343 100644 --- a/tensorflow_quantum/core/ops/tfq_simulate_expectation_op_cuquantum.cu.cc +++ b/tensorflow_quantum/core/ops/tfq_simulate_expectation_op_cuquantum.cu.cc @@ -112,6 +112,7 @@ class TfqSimulateExpectationOpCuQuantum : public tensorflow::OpKernel { for (const int num : num_qubits) { max_num_qubits = std::max(max_num_qubits, num); } +<<<<<<< HEAD:tensorflow_quantum/core/ops/tfq_simulate_expectation_op_cuquantum.cu.cc // create handles for simulator cublasCreate(&cublas_handle_); @@ -125,6 +126,21 @@ class TfqSimulateExpectationOpCuQuantum : public tensorflow::OpKernel { private: cublasHandle_t cublas_handle_; custatevecHandle_t custatevec_handle_; +======= + if (max_num_qubits >= 26 || programs.size() == 1 || true) { + ComputeLarge(num_qubits, fused_circuits, pauli_sums, context, + &output_tensor); + } else { + ComputeSmall(num_qubits, max_num_qubits, fused_circuits, pauli_sums, + context, &output_tensor); + } + } + + private: + int num_threads_in_sim_; + int thread_per_block_; + int block_count_; +>>>>>>> parent of 4f6290a (Fix ComputeSmall and enable it.):tensorflow_quantum/core/ops/tfq_simulate_expectation_op_cuda.cu.cc // Define the GPU implementation that launches the CUDA kernel. void ComputeLarge( @@ -136,6 +152,7 @@ class TfqSimulateExpectationOpCuQuantum : public tensorflow::OpKernel { // Instantiate qsim objects. using Simulator = qsim::SimulatorCuStateVec; using StateSpace = Simulator::StateSpace; +<<<<<<< HEAD:tensorflow_quantum/core/ops/tfq_simulate_expectation_op_cuquantum.cu.cc // Launch the cuda kernel. @@ -143,6 +160,26 @@ class TfqSimulateExpectationOpCuQuantum : public tensorflow::OpKernel { int largest_nq = 1; Simulator sim = Simulator(custatevec_handle_); StateSpace ss = StateSpace(cublas_handle_, custatevec_handle_); +======= + // Launch the cuda kernel. These parameters came from: + // 1. min/max num_threads in //third_party/qsim/tests/simulator_cuda_test.cu + // 2. min/max num_threads & dblocks in + // //third_party/qsim/tests/statespace_cuda_test.cu + // //third_party/qsim/lib/statespace_cuda.h:55-64 + // num_dblocks has no explanation. just follow test code 2 or 16. + int block_count = 2; // 2 or 16; + // num_threads = 2**q where q in [5..10] + int thread_per_block = 128; // 32, 64, 128, 256, 512, 1024; + // TFQ GPU + StateSpace::Parameter param_ss; + param_ss.num_threads = thread_per_block; + param_ss.num_dblocks = block_count; + + // Begin simulation. + int largest_nq = 1; + Simulator sim = Simulator(); + StateSpace ss = StateSpace(param_ss); +>>>>>>> parent of 4f6290a (Fix ComputeSmall and enable it.):tensorflow_quantum/core/ops/tfq_simulate_expectation_op_cuda.cu.cc auto sv = ss.Create(largest_nq); ss.SetStateZero(sv); auto scratch = ss.Create(largest_nq); @@ -190,6 +227,13 @@ class TfqSimulateExpectationOpCuQuantum : public tensorflow::OpKernel { using Simulator = qsim::SimulatorCuStateVec; using StateSpace = Simulator::StateSpace; +<<<<<<< HEAD:tensorflow_quantum/core/ops/tfq_simulate_expectation_op_cuquantum.cu.cc +======= + StateSpace::Parameter param_ss; + param_ss.num_threads = thread_per_block_; + param_ss.num_dblocks = block_count_; + +>>>>>>> parent of 4f6290a (Fix ComputeSmall and enable it.):tensorflow_quantum/core/ops/tfq_simulate_expectation_op_cuda.cu.cc const int output_dim_op_size = output_tensor->dimension(1); Status compute_status = Status::OK(); @@ -200,9 +244,15 @@ class TfqSimulateExpectationOpCuQuantum : public tensorflow::OpKernel { int largest_nq = 1; int cur_op_index; +<<<<<<< HEAD:tensorflow_quantum/core/ops/tfq_simulate_expectation_op_cuquantum.cu.cc // Launch custatevec, begin simulation. auto sim = Simulator(custatevec_handle_); auto ss = StateSpace(cublas_handle_, custatevec_handle_); +======= + // Begin simulation. + auto sim = Simulator(); + auto ss = StateSpace(param_ss); +>>>>>>> parent of 4f6290a (Fix ComputeSmall and enable it.):tensorflow_quantum/core/ops/tfq_simulate_expectation_op_cuda.cu.cc auto sv = ss.Create(largest_nq); auto scratch = ss.Create(largest_nq); for (int i = start; i < end; i++) { From 2e08e5f6018b0613e583d71fa811659ad78283a5 Mon Sep 17 00:00:00 2001 From: Michael Broughton Date: Mon, 12 Jun 2023 14:15:53 -0700 Subject: [PATCH 28/50] Revert "Fix tfq_simulate_ops_cuda op test." This reverts commit 66442482a21fc7139fb2cdc69a36fd2f5e9c207f. --- .../core/ops/tfq_simulate_ops_cuda_test.py | 103 +++++++++++++----- 1 file changed, 74 insertions(+), 29 deletions(-) diff --git a/tensorflow_quantum/core/ops/tfq_simulate_ops_cuda_test.py b/tensorflow_quantum/core/ops/tfq_simulate_ops_cuda_test.py index dce578d30..c293fe673 100644 --- a/tensorflow_quantum/core/ops/tfq_simulate_ops_cuda_test.py +++ b/tensorflow_quantum/core/ops/tfq_simulate_ops_cuda_test.py @@ -24,23 +24,18 @@ from tensorflow_quantum.core.ops import tfq_simulate_ops_cuda from tensorflow_quantum.python import util -def measure_average_runtime(fn, tag, num_samples=10): - avg_time = [] - for _ in range(num_samples): - begin_time = time.time() - result = fn() - duration = time.time() - begin_time - avg_time.append(duration) - avg_time = sum(avg_time) / float(num_samples) - print(f"\n\t{tag} time: {avg_time}\n") - return avg_time, result - class SimulateExpectationTest(tf.test.TestCase): """Tests tfq_simulate_expectation.""" - def test_simulate_expectation_cpu_vs_cuda(self): - """Make sure that cpu & gpu(cuda) ops have the same results.""" + def test_simulate_expectation_diff(self): + """Make sure that cpu & gpu ops have the same results.""" + # TF 2 + # gpus = tf.config.list_physical_devices('GPU') + # self.assertLess(len(gpus), 1) + # if len(gpus) < 1: + # self.skipTest("Expected at least 1 GPU but found {} GPUs".format( + # len(gpus))) n_qubits = 20 batch_size = 5 symbol_names = ['alpha'] @@ -59,27 +54,77 @@ def test_simulate_expectation_cpu_vs_cuda(self): pauli_sums = util.random_pauli_sums(qubits, 3, batch_size) pauli_sums_tensor = util.convert_to_tensor([[x] for x in pauli_sums]) - cpu_avg_time, res_cpu = measure_average_runtime( - lambda: tfq_simulate_ops.tfq_simulate_expectation( + cpu_avg_time = [] + for _ in range(10): + cpu_time = time.time() + res_cpu = tfq_simulate_ops.tfq_simulate_expectation( circuit_batch_tensor, symbol_names, symbol_values_array.astype(np.float64), - pauli_sums_tensor), - "CPU" - ) + pauli_sums_tensor) + cpu_time = time.time() - cpu_time + cpu_avg_time.append(cpu_time) + cpu_avg_time = sum(cpu_avg_time) / 10.0 + print("\n\tCPU time: ", cpu_avg_time, "\n") - cuda_avg_time, res_cuda = measure_average_runtime( - lambda: tfq_simulate_ops_cuda.tfq_simulate_expectation( - circuit_batch_tensor, - symbol_names, symbol_values_array.astype(np.float64), - pauli_sums_tensor), - "CUDA" - ) + avg_cpu_with_gpu_time = [] + for _ in range(10): + cpu_with_gpu_time = time.time() + with tf.device("/device:GPU:0"): + res_cpu_with_gpu = tfq_simulate_ops_cuda.tfq_simulate_expectation( + circuit_batch_tensor, + symbol_names, symbol_values_array.astype(np.float64), + pauli_sums_tensor) + cpu_with_gpu_time = time.time() - cpu_with_gpu_time + avg_cpu_with_gpu_time.append(cpu_with_gpu_time) + avg_cpu_with_gpu_time = sum(avg_cpu_with_gpu_time) / 10.0 + + # Both are CPU devices. + self.assertEqual(res_cpu.device, res_cpu_with_gpu.device) + np.testing.assert_allclose(res_cpu, res_cpu_with_gpu) + print("\n\tCPU with GPU device time: ", avg_cpu_with_gpu_time, "\n") + + @tf.function + def cpu_with_gpu_fn(): + with tf.device("/device:GPU:0"): + return tfq_simulate_ops_cuda.tfq_simulate_expectation( + circuit_batch_tensor, + symbol_names, symbol_values_array.astype(np.float64), + pauli_sums_tensor) + + avg_fn_cpu_with_gpu_time = [] + for _ in range(10): + fn_cpu_with_gpu_time = time.time() + res_fn_cpu_with_gpu = cpu_with_gpu_fn() + fn_cpu_with_gpu_time = time.time() - fn_cpu_with_gpu_time + avg_fn_cpu_with_gpu_time.append(fn_cpu_with_gpu_time) + avg_fn_cpu_with_gpu_time = sum(avg_fn_cpu_with_gpu_time) / 10.0 + + # CPU & GPU devices. + self.assertNotEqual(res_cpu.device, res_fn_cpu_with_gpu.device) + np.testing.assert_allclose(res_cpu, res_fn_cpu_with_gpu) + print("\n\ttf.function, CPU with GPU device time: ", + avg_fn_cpu_with_gpu_time, "\n") + + # avg_gpu_time = [] + # for _ in range(10): + # gpu_time = time.time() + # res_gpu = tfq_simulate_ops_gpu_cpu.tfq_simulate_expectation( + # circuit_batch_tensor, + # symbol_names, symbol_values_array.astype(np.float64), + # pauli_sums_tensor) + # gpu_time = time.time() - gpu_time + # avg_gpu_time.append(gpu_time) + # avg_gpu_time = sum(avg_gpu_time) / 10.0 + # print("\n\tGPU version time: ", avg_gpu_time, "\n") - # The result should be the similar within a tolerance. - np.testing.assert_allclose(res_cpu, res_cuda, atol=1e-5) - # CUDA op should be faster than CPU op. - self.assertGreater(cpu_avg_time, cuda_avg_time) + # # This guarantees that both tensors are not in the same devices + # # (e.g. CPU vs GPU) + # # self.assertNotEqual(res.device, res_gpu.device) + # # -> this doesn't work anymore because TFQ op itself is in CPU. + # # only qsim::SimulatorCUDA is in GPU + # np.testing.assert_allclose(res_cpu, res_gpu) + # self.assertGreater(cpu_avg_time, avg_gpu_time) if __name__ == "__main__": From 9374a9560d501aae27e4459721a7e8f5516ca032 Mon Sep 17 00:00:00 2001 From: Michael Broughton Date: Mon, 12 Jun 2023 14:16:50 -0700 Subject: [PATCH 29/50] Revert "Temporarily turn on ComputeLarge always" This reverts commit 23dd880224b209430dfda4c3a88a351c64dce28a. --- .../tfq_simulate_expectation_op_cuquantum.cu.cc | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/tensorflow_quantum/core/ops/tfq_simulate_expectation_op_cuquantum.cu.cc b/tensorflow_quantum/core/ops/tfq_simulate_expectation_op_cuquantum.cu.cc index 4d3512343..1f9e9e168 100644 --- a/tensorflow_quantum/core/ops/tfq_simulate_expectation_op_cuquantum.cu.cc +++ b/tensorflow_quantum/core/ops/tfq_simulate_expectation_op_cuquantum.cu.cc @@ -112,21 +112,7 @@ class TfqSimulateExpectationOpCuQuantum : public tensorflow::OpKernel { for (const int num : num_qubits) { max_num_qubits = std::max(max_num_qubits, num); } -<<<<<<< HEAD:tensorflow_quantum/core/ops/tfq_simulate_expectation_op_cuquantum.cu.cc - - // create handles for simulator - cublasCreate(&cublas_handle_); - custatevecCreate(&custatevec_handle_); - - // destroy handles in sync with simulator lifetime - cublasDestroy(cublas_handle_); - custatevecDestroy(custatevec_handle_); - } - private: - cublasHandle_t cublas_handle_; - custatevecHandle_t custatevec_handle_; -======= if (max_num_qubits >= 26 || programs.size() == 1 || true) { ComputeLarge(num_qubits, fused_circuits, pauli_sums, context, &output_tensor); From 8a6a66a6c66a66b8f44b5f924da0354c9e0bad55 Mon Sep 17 00:00:00 2001 From: Michael Broughton Date: Mon, 12 Jun 2023 14:18:03 -0700 Subject: [PATCH 30/50] Revert "Upgrade TF version from 2.7 to 2.11 (#749)" This reverts commit 20cfde5eb2f6188d35bab1375c98572ae4571b20. --- .bazelversion | 2 +- WORKSPACE | 10 +- benchmarks/README.md | 4 +- configure.sh | 6 +- docs/install.md | 21 +- docs/tutorials/barren_plateaus.ipynb | 29 +- docs/tutorials/gradients.ipynb | 51 +- docs/tutorials/hello_many_worlds.ipynb | 261 +++------ docs/tutorials/mnist.ipynb | 13 +- docs/tutorials/noise.ipynb | 234 ++++---- docs/tutorials/qcnn.ipynb | 203 ++----- docs/tutorials/quantum_data.ipynb | 42 +- .../quantum_reinforcement_learning.ipynb | 25 +- release/setup.py | 6 +- requirements.txt | 6 +- scripts/benchmark_all.sh | 4 +- scripts/build_pip_package_test.sh | 2 +- scripts/ci_install.sh | 4 +- scripts/ci_validate_tutorials.sh | 6 +- scripts/msan_test.sh | 6 +- scripts/test_all.sh | 4 +- scripts/test_benchmarks.sh | 6 +- scripts/test_tutorials.py | 6 +- tensorflow_quantum/core/ops/BUILD | 42 +- tensorflow_quantum/core/ops/cirq_ops_test.py | 2 +- tensorflow_quantum/core/ops/math_ops/BUILD | 6 +- .../core/ops/math_ops/simulate_mps_test.py | 5 +- .../core/ops/math_ops/tfq_inner_product.cc | 4 +- .../ops/math_ops/tfq_inner_product_grad.cc | 4 +- .../math_ops/tfq_simulate_1d_expectation.cc | 6 +- .../tfq_simulate_1d_sampled_expectation.cc | 6 +- .../ops/math_ops/tfq_simulate_1d_samples.cc | 4 +- tensorflow_quantum/core/ops/noise/BUILD | 6 +- .../core/ops/noise/tfq_noisy_expectation.cc | 6 +- .../noise/tfq_noisy_sampled_expectation.cc | 6 +- .../core/ops/noise/tfq_noisy_samples.cc | 4 +- tensorflow_quantum/core/ops/parse_context.cc | 71 +-- .../core/ops/tfq_adj_grad_op.cc | 4 +- .../core/ops/tfq_calculate_unitary_op.cc | 4 +- .../core/ops/tfq_circuit_append_op.cc | 2 +- .../core/ops/tfq_ps_decompose_op.cc | 2 +- .../core/ops/tfq_ps_symbol_replace_op.cc | 2 +- .../ops/tfq_ps_weights_from_symbols_op.cc | 2 +- .../core/ops/tfq_resolve_parameters_op.cc | 4 +- .../core/ops/tfq_simulate_expectation_op.cc | 6 +- .../tfq_simulate_sampled_expectation_op.cc | 6 +- .../core/ops/tfq_simulate_samples_op.cc | 4 +- .../core/ops/tfq_simulate_state_op.cc | 4 +- .../core/ops/tfq_utility_ops_test.py | 2 +- .../core/serialize/op_serializer.py | 2 +- .../core/serialize/op_serializer_test.py | 2 +- tensorflow_quantum/core/src/BUILD | 7 - .../core/src/circuit_parser_qsim.cc | 69 +-- .../core/src/circuit_parser_qsim_test.cc | 113 ++-- .../core/src/program_resolution.cc | 52 +- .../core/src/program_resolution_test.cc | 56 +- tensorflow_quantum/core/src/util_qsim.h | 14 +- tensorflow_quantum/datasets/spin_system.py | 4 +- .../datasets/spin_system_test.py | 3 +- .../sampled_expectation_test.py | 2 +- .../python/optimizers/rotosolve_minimizer.py | 537 +++++++++--------- .../python/optimizers/spsa_minimizer.py | 195 +++---- 62 files changed, 943 insertions(+), 1278 deletions(-) diff --git a/.bazelversion b/.bazelversion index 831446cbd..0b2eb36f5 100644 --- a/.bazelversion +++ b/.bazelversion @@ -1 +1 @@ -5.1.0 +3.7.2 diff --git a/WORKSPACE b/WORKSPACE index b47e25d2f..b70cca65b 100644 --- a/WORKSPACE +++ b/WORKSPACE @@ -3,8 +3,8 @@ load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") -EIGEN_COMMIT = "3bb6a48d8c171cf20b5f8e48bfb4e424fbd4f79e" -EIGEN_SHA256 = "eca9847b3fe6249e0234a342b78f73feec07d29f534e914ba5f920f3e09383a3" +EIGEN_COMMIT = "12e8d57108c50d8a63605c6eb0144c838c128337" +EIGEN_SHA256 = "f689246e342c3955af48d26ce74ac34d21b579a00675c341721a735937919b02" http_archive( @@ -33,10 +33,10 @@ http_archive( http_archive( name = "org_tensorflow", - sha256 = "e52cda3bae45f0ae0fccd4055e9fa29892b414f70e2df94df9a3a10319c75fff", - strip_prefix = "tensorflow-2.11.0", + sha256 = "249b48ddee927801c7a4f8e5442cf1a3c860f6f46b85a2ff7a78b501507dd561", + strip_prefix = "tensorflow-2.7.0", urls = [ - "https://github.com/tensorflow/tensorflow/archive/refs/tags/v2.11.0.zip", + "https://github.com/tensorflow/tensorflow/archive/refs/tags/v2.7.0.zip", ], ) diff --git a/benchmarks/README.md b/benchmarks/README.md index 4e71f8de2..b71bd1b04 100644 --- a/benchmarks/README.md +++ b/benchmarks/README.md @@ -24,7 +24,7 @@ Some notes on benchmark configuration: For example, to benchmark a dense depth-10 Clifford circuit over 5 qubits call: ``` -bazel run -c opt --cxxopt="-D_GLIBCXX_USE_CXX11_ABI=1" --cxxopt="-msse2" \ +bazel run -c opt --cxxopt="-D_GLIBCXX_USE_CXX11_ABI=0" --cxxopt="-msse2" \ --cxxopt="-msse3" --cxxopt="-msse4" \ benchmarks/scripts:benchmark_clifford_circuit -- \ --n_moments 5 --n_qubits 4 \ @@ -39,7 +39,7 @@ benchmarks/scripts/reports/CliffordBenchmarks.benchmark_clifford_circuit_4_5_1 To benchmark the parameter shift differentiation method on a random depth-10 4-qubit circuit with 10 parameters call, where the circuit will be differentiated over 50 trials, each time over a batch of 10 circuits. ``` -bazel run -c opt --cxxopt="-D_GLIBCXX_USE_CXX11_ABI=1" --cxxopt="-msse2" \ +bazel run -c opt --cxxopt="-D_GLIBCXX_USE_CXX11_ABI=0" --cxxopt="-msse2" \ --cxxopt="-msse3" --cxxopt="-msse4" \ benchmarks/scripts:benchmark_op_gradients -- \ --n_moments 10 --n_qubits 4 --n_symbols 10 \ diff --git a/configure.sh b/configure.sh index e212efeab..6ba7a1bc4 100755 --- a/configure.sh +++ b/configure.sh @@ -100,12 +100,12 @@ if [[ "$PIP_MANYLINUX2010" == "0" ]]; then fi -write_to_bazelrc "build --experimental_repo_remote_exec" write_to_bazelrc "build --spawn_strategy=standalone" write_to_bazelrc "build --strategy=Genrule=standalone" +write_to_bazelrc "build --experimental_repo_remote_exec" write_to_bazelrc "build -c opt" -write_to_bazelrc "build --cxxopt=\"-D_GLIBCXX_USE_CXX11_ABI=1\"" -write_to_bazelrc "build --cxxopt=\"-std=c++17\"" +write_to_bazelrc "build --cxxopt=\"-D_GLIBCXX_USE_CXX11_ABI=0\"" +write_to_bazelrc "build --cxxopt=\"-std=c++14\"" if is_windows; then diff --git a/docs/install.md b/docs/install.md index 5e64d0616..8c19034c1 100644 --- a/docs/install.md +++ b/docs/install.md @@ -84,7 +84,7 @@ As noted in the TensorFlow guide, the Bazel build system will be required. -Our latest source builds use TensorFlow 2.11.0. To ensure compatibility we use `bazel` version 5.1.0. To remove any existing version of Bazel: +Our latest source builds use TensorFlow 2.7.0. To ensure compatibility we use `bazel` version 3.7.2. To remove any existing version of Bazel:
@@ -92,13 +92,13 @@ Our latest source builds use TensorFlow 2.11.0. To ensure compatibility we use `
 
-Download and install `bazel` version 5.1.0: +Download and install `bazel` version 3.7.2:
-  wget https://github.com/bazelbuild/bazel/releases/download/5.1.0/bazel_5.1.0-linux-x86_64.deb
+  wget https://github.com/bazelbuild/bazel/releases/download/3.7.2/bazel_3.7.2-linux-x86_64.deb
 
-  sudo dpkg -i bazel_5.1.0-linux-x86_64.deb
+  sudo dpkg -i bazel_3.7.2-linux-x86_64.deb
 
@@ -122,7 +122,7 @@ Finally, confirm installation of the correct `bazel` version: ### 4. Build TensorFlow from source Here we adapt instructions from the TensorFlow [build from source](https://www.tensorflow.org/install/source) -guide, see the link for further details. TensorFlow Quantum is compatible with TensorFlow version 2.11.0. +guide, see the link for further details. TensorFlow Quantum is compatible with TensorFlow version 2.7.0. Download the TensorFlow source code: @@ -131,7 +131,7 @@ Download the
   git clone https://github.com/tensorflow/tensorflow.git
   cd tensorflow
-  git checkout v2.11.0
+  git checkout v2.7.0
 
Be sure the virtual environment you created in step 2 is activated. Then, install the TensorFlow dependencies: @@ -141,8 +141,7 @@ Be sure the virtual environment you created in step 2 is activated. Then, instal pip install -U pip six numpy wheel setuptools mock 'future>=0.17.1' pip install -U keras_applications --no-deps pip install -U keras_preprocessing --no-deps - pip install numpy==1.24.2 - pip install packaging requests + pip install numpy==1.19.5 @@ -154,11 +153,11 @@ Configure the TensorFlow build. When asked for the Python interpreter and librar -Build the TensorFlow package (Since TF v2.8, `_GLIBCXX_USE_CXX11_ABI` is set to 1, and the c++ codes are all compiled with `-std=c++17`): +Build the TensorFlow package:
-  bazel build -c opt --cxxopt="-O3" --cxxopt="-march=native" --cxxopt="-std=c++17" --cxxopt="-D_GLIBCXX_USE_CXX11_ABI=1" //tensorflow/tools/pip_package:build_pip_package
+  bazel build -c opt --cxxopt="-O3" --cxxopt="-march=native" --cxxopt="-D_GLIBCXX_USE_CXX11_ABI=0" //tensorflow/tools/pip_package:build_pip_package
 
@@ -194,7 +193,7 @@ Build the TensorFlow Quantum pip package and install:
   ./configure.sh
-  bazel build -c opt --cxxopt="-O3" --cxxopt="-march=native" --cxxopt="-std=c++17" --cxxopt="-D_GLIBCXX_USE_CXX11_ABI=1" release:build_pip_package
+  bazel build -c opt --cxxopt="-O3" --cxxopt="-march=native" --cxxopt="-D_GLIBCXX_USE_CXX11_ABI=0" release:build_pip_package
   bazel-bin/release/build_pip_package /tmp/tfquantum/
   python3 -m pip install /tmp/tfquantum/name_of_generated_wheel.whl
 
diff --git a/docs/tutorials/barren_plateaus.ipynb b/docs/tutorials/barren_plateaus.ipynb index 3c9176eaa..2447018c9 100644 --- a/docs/tutorials/barren_plateaus.ipynb +++ b/docs/tutorials/barren_plateaus.ipynb @@ -12,7 +12,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 0, "metadata": { "cellView": "form", "colab": {}, @@ -89,7 +89,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 0, "metadata": { "colab": {}, "colab_type": "code", @@ -112,7 +112,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 0, "metadata": { "colab": {}, "colab_type": "code", @@ -125,7 +125,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 0, "metadata": { "colab": {}, "colab_type": "code", @@ -150,7 +150,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 0, "metadata": { "colab": {}, "colab_type": "code", @@ -202,7 +202,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 0, "metadata": { "colab": {}, "colab_type": "code", @@ -278,7 +278,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 0, "metadata": { "colab": {}, "colab_type": "code", @@ -327,7 +327,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 0, "metadata": { "colab": {}, "colab_type": "code", @@ -399,7 +399,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 0, "metadata": { "colab": {}, "colab_type": "code", @@ -455,7 +455,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 0, "metadata": { "colab": {}, "colab_type": "code", @@ -511,15 +511,6 @@ "display_name": "Python 3", "language": "python", "name": "python3" - }, - "language_info": { - "name": "python", - "version": "3.10.9 (main, Dec 7 2022, 13:47:07) [GCC 12.2.0]" - }, - "vscode": { - "interpreter": { - "hash": "916dbcbb3f70747c44a77c7bcd40155683ae19c65e1c03b4aa3499c5328201f1" - } } }, "nbformat": 4, diff --git a/docs/tutorials/gradients.ipynb b/docs/tutorials/gradients.ipynb index 072718bcf..62a7ce103 100644 --- a/docs/tutorials/gradients.ipynb +++ b/docs/tutorials/gradients.ipynb @@ -12,7 +12,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 0, "metadata": { "cellView": "form", "colab": {}, @@ -91,7 +91,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 0, "metadata": { "colab": {}, "colab_type": "code", @@ -114,7 +114,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 0, "metadata": { "colab": {}, "colab_type": "code", @@ -127,7 +127,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 0, "metadata": { "colab": {}, "colab_type": "code", @@ -152,7 +152,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 0, "metadata": { "colab": {}, "colab_type": "code", @@ -187,7 +187,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 0, "metadata": { "colab": {}, "colab_type": "code", @@ -212,7 +212,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 0, "metadata": { "colab": {}, "colab_type": "code", @@ -236,7 +236,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 0, "metadata": { "colab": {}, "colab_type": "code", @@ -269,7 +269,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 0, "metadata": { "colab": {}, "colab_type": "code", @@ -302,7 +302,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 0, "metadata": { "colab": {}, "colab_type": "code", @@ -331,7 +331,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 0, "metadata": { "colab": {}, "colab_type": "code", @@ -361,7 +361,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 0, "metadata": { "colab": {}, "colab_type": "code", @@ -390,7 +390,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 0, "metadata": { "colab": {}, "colab_type": "code", @@ -439,7 +439,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 0, "metadata": { "colab": {}, "colab_type": "code", @@ -494,7 +494,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 0, "metadata": { "colab": {}, "colab_type": "code", @@ -518,7 +518,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 0, "metadata": { "colab": {}, "colab_type": "code", @@ -548,7 +548,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 0, "metadata": { "colab": {}, "colab_type": "code", @@ -577,7 +577,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 0, "metadata": { "colab": {}, "colab_type": "code", @@ -636,7 +636,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 0, "metadata": { "colab": {}, "colab_type": "code", @@ -694,7 +694,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 0, "metadata": { "colab": {}, "colab_type": "code", @@ -750,7 +750,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 0, "metadata": { "colab": {}, "colab_type": "code", @@ -812,15 +812,6 @@ "display_name": "Python 3", "language": "python", "name": "python3" - }, - "language_info": { - "name": "python", - "version": "3.10.9 (main, Dec 7 2022, 13:47:07) [GCC 12.2.0]" - }, - "vscode": { - "interpreter": { - "hash": "916dbcbb3f70747c44a77c7bcd40155683ae19c65e1c03b4aa3499c5328201f1" - } } }, "nbformat": 4, diff --git a/docs/tutorials/hello_many_worlds.ipynb b/docs/tutorials/hello_many_worlds.ipynb index 229136219..f3dd7fe19 100644 --- a/docs/tutorials/hello_many_worlds.ipynb +++ b/docs/tutorials/hello_many_worlds.ipynb @@ -12,15 +12,12 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 0, "metadata": { "cellView": "form", "colab": {}, "colab_type": "code", - "id": "iiQkM5ZgQ8r2", - "vscode": { - "languageId": "python" - } + "id": "iiQkM5ZgQ8r2" }, "outputs": [], "source": [ @@ -92,14 +89,11 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 0, "metadata": { "colab": {}, "colab_type": "code", - "id": "TorxE5tnkvb2", - "vscode": { - "languageId": "python" - } + "id": "TorxE5tnkvb2" }, "outputs": [], "source": [ @@ -118,14 +112,11 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 0, "metadata": { "colab": {}, "colab_type": "code", - "id": "saFHsRDpkvkH", - "vscode": { - "languageId": "python" - } + "id": "saFHsRDpkvkH" }, "outputs": [], "source": [ @@ -134,14 +125,11 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 0, "metadata": { "colab": {}, "colab_type": "code", - "id": "4Ql5PW-ACO0J", - "vscode": { - "languageId": "python" - } + "id": "4Ql5PW-ACO0J" }, "outputs": [], "source": [ @@ -162,14 +150,11 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 0, "metadata": { "colab": {}, "colab_type": "code", - "id": "enZ300Bflq80", - "vscode": { - "languageId": "python" - } + "id": "enZ300Bflq80" }, "outputs": [], "source": [ @@ -212,14 +197,11 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 0, "metadata": { "colab": {}, "colab_type": "code", - "id": "2yQdmhQLCrzQ", - "vscode": { - "languageId": "python" - } + "id": "2yQdmhQLCrzQ" }, "outputs": [], "source": [ @@ -238,14 +220,11 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 0, "metadata": { "colab": {}, "colab_type": "code", - "id": "Ps-pd2mndXs7", - "vscode": { - "languageId": "python" - } + "id": "Ps-pd2mndXs7" }, "outputs": [], "source": [ @@ -272,14 +251,11 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 0, "metadata": { "colab": {}, "colab_type": "code", - "id": "VMq7EayNRyQb", - "vscode": { - "languageId": "python" - } + "id": "VMq7EayNRyQb" }, "outputs": [], "source": [ @@ -301,15 +277,12 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 0, "metadata": { "colab": {}, "colab_type": "code", "id": "hrSnOCi3ehr_", - "scrolled": true, - "vscode": { - "languageId": "python" - } + "scrolled": true }, "outputs": [], "source": [ @@ -322,14 +295,11 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 0, "metadata": { "colab": {}, "colab_type": "code", - "id": "OZ0lWFXv6pII", - "vscode": { - "languageId": "python" - } + "id": "OZ0lWFXv6pII" }, "outputs": [], "source": [ @@ -352,15 +322,12 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 0, "metadata": { "colab": {}, "colab_type": "code", "id": "1gLQjA02mIyy", - "scrolled": true, - "vscode": { - "languageId": "python" - } + "scrolled": true }, "outputs": [], "source": [ @@ -383,14 +350,11 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 0, "metadata": { "colab": {}, "colab_type": "code", - "id": "aX_vEmCKmpQS", - "vscode": { - "languageId": "python" - } + "id": "aX_vEmCKmpQS" }, "outputs": [], "source": [ @@ -417,18 +381,15 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 0, "metadata": { "colab": {}, "colab_type": "code", - "id": "1fsVZhF5lIXp", - "vscode": { - "languageId": "python" - } + "id": "1fsVZhF5lIXp" }, "outputs": [], "source": [ - "batch_vals = np.array(np.random.uniform(0, 2 * np.pi, (5, 2)), dtype=float)" + "batch_vals = np.array(np.random.uniform(0, 2 * np.pi, (5, 2)), dtype=np.float32)" ] }, { @@ -443,14 +404,11 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 0, "metadata": { "colab": {}, "colab_type": "code", - "id": "RsfF53UCJtr9", - "vscode": { - "languageId": "python" - } + "id": "RsfF53UCJtr9" }, "outputs": [], "source": [ @@ -481,14 +439,11 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 0, "metadata": { "colab": {}, "colab_type": "code", - "id": "kGZVdcZ6y9lC", - "vscode": { - "languageId": "python" - } + "id": "kGZVdcZ6y9lC" }, "outputs": [], "source": [ @@ -542,14 +497,11 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 0, "metadata": { "colab": {}, "colab_type": "code", - "id": "N-j7SCl-51-q", - "vscode": { - "languageId": "python" - } + "id": "N-j7SCl-51-q" }, "outputs": [], "source": [ @@ -580,14 +532,11 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 0, "metadata": { "colab": {}, "colab_type": "code", - "id": "1v4CK2jD6pIj", - "vscode": { - "languageId": "python" - } + "id": "1v4CK2jD6pIj" }, "outputs": [], "source": [ @@ -612,14 +561,11 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 0, "metadata": { "colab": {}, "colab_type": "code", - "id": "kZbYRTe16pIm", - "vscode": { - "languageId": "python" - } + "id": "kZbYRTe16pIm" }, "outputs": [], "source": [ @@ -652,14 +598,11 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 0, "metadata": { "colab": {}, "colab_type": "code", - "id": "UfHF8NNE6pIr", - "vscode": { - "languageId": "python" - } + "id": "UfHF8NNE6pIr" }, "outputs": [], "source": [ @@ -687,14 +630,11 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 0, "metadata": { "colab": {}, "colab_type": "code", - "id": "Zvt2YGmZ6pIu", - "vscode": { - "languageId": "python" - } + "id": "Zvt2YGmZ6pIu" }, "outputs": [], "source": [ @@ -719,14 +659,11 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 0, "metadata": { "colab": {}, "colab_type": "code", - "id": "Xs6EMhah6pIz", - "vscode": { - "languageId": "python" - } + "id": "Xs6EMhah6pIz" }, "outputs": [], "source": [ @@ -750,14 +687,11 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 0, "metadata": { "colab": {}, "colab_type": "code", - "id": "ERXNPe4F6pI4", - "vscode": { - "languageId": "python" - } + "id": "ERXNPe4F6pI4" }, "outputs": [], "source": [ @@ -796,14 +730,11 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 0, "metadata": { "colab": {}, "colab_type": "code", - "id": "ciMIJAuH6pJA", - "vscode": { - "languageId": "python" - } + "id": "ciMIJAuH6pJA" }, "outputs": [], "source": [ @@ -839,14 +770,11 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 0, "metadata": { "colab": {}, "colab_type": "code", - "id": "_VYfzHffWo7n", - "vscode": { - "languageId": "python" - } + "id": "_VYfzHffWo7n" }, "outputs": [], "source": [ @@ -873,14 +801,11 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 0, "metadata": { "colab": {}, "colab_type": "code", - "id": "6nk2Yr3e6pJJ", - "vscode": { - "languageId": "python" - } + "id": "6nk2Yr3e6pJJ" }, "outputs": [], "source": [ @@ -909,14 +834,11 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 0, "metadata": { "colab": {}, "colab_type": "code", - "id": "Lwphqvs96pJO", - "vscode": { - "languageId": "python" - } + "id": "Lwphqvs96pJO" }, "outputs": [], "source": [ @@ -935,14 +857,11 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 0, "metadata": { "colab": {}, "colab_type": "code", - "id": "dtPYqbNi8zeZ", - "vscode": { - "languageId": "python" - } + "id": "dtPYqbNi8zeZ" }, "outputs": [], "source": [ @@ -957,14 +876,11 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 0, "metadata": { "colab": {}, "colab_type": "code", - "id": "azE-qV0OaC1o", - "vscode": { - "languageId": "python" - } + "id": "azE-qV0OaC1o" }, "outputs": [], "source": [ @@ -998,14 +914,11 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 0, "metadata": { "colab": {}, "colab_type": "code", - "id": "RoIlb7r7j5SY", - "vscode": { - "languageId": "python" - } + "id": "RoIlb7r7j5SY" }, "outputs": [], "source": [ @@ -1044,14 +957,11 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 0, "metadata": { "colab": {}, "colab_type": "code", - "id": "aYskLTacs8Ku", - "vscode": { - "languageId": "python" - } + "id": "aYskLTacs8Ku" }, "outputs": [], "source": [ @@ -1088,14 +998,11 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 0, "metadata": { "colab": {}, "colab_type": "code", - "id": "hta0G3Nc6pJY", - "vscode": { - "languageId": "python" - } + "id": "hta0G3Nc6pJY" }, "outputs": [], "source": [ @@ -1124,14 +1031,11 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 0, "metadata": { "colab": {}, "colab_type": "code", - "id": "n_aTG4g3-y0F", - "vscode": { - "languageId": "python" - } + "id": "n_aTG4g3-y0F" }, "outputs": [], "source": [ @@ -1154,14 +1058,11 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 0, "metadata": { "colab": {}, "colab_type": "code", - "id": "IMHjiKit6pJg", - "vscode": { - "languageId": "python" - } + "id": "IMHjiKit6pJg" }, "outputs": [], "source": [ @@ -1195,14 +1096,11 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 0, "metadata": { "colab": {}, "colab_type": "code", - "id": "4gw_L3JG0_G0", - "vscode": { - "languageId": "python" - } + "id": "4gw_L3JG0_G0" }, "outputs": [], "source": [ @@ -1230,14 +1128,11 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 0, "metadata": { "colab": {}, "colab_type": "code", - "id": "nFuGA73MAA4p", - "vscode": { - "languageId": "python" - } + "id": "nFuGA73MAA4p" }, "outputs": [], "source": [ @@ -1255,14 +1150,11 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 0, "metadata": { "colab": {}, "colab_type": "code", - "id": "Cf_G-GdturLL", - "vscode": { - "languageId": "python" - } + "id": "Cf_G-GdturLL" }, "outputs": [], "source": [ @@ -1295,14 +1187,11 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 0, "metadata": { "colab": {}, "colab_type": "code", - "id": "uXmH0TQ76pJt", - "vscode": { - "languageId": "python" - } + "id": "uXmH0TQ76pJt" }, "outputs": [], "source": [ diff --git a/docs/tutorials/mnist.ipynb b/docs/tutorials/mnist.ipynb index 91405ed26..b80f2500f 100644 --- a/docs/tutorials/mnist.ipynb +++ b/docs/tutorials/mnist.ipynb @@ -112,7 +112,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 0, "metadata": { "colab": {}, "colab_type": "code", @@ -125,7 +125,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 0, "metadata": { "colab": {}, "colab_type": "code", @@ -1117,15 +1117,6 @@ "display_name": "Python 3", "language": "python", "name": "python3" - }, - "language_info": { - "name": "python", - "version": "3.10.9 (main, Dec 7 2022, 13:47:07) [GCC 12.2.0]" - }, - "vscode": { - "interpreter": { - "hash": "916dbcbb3f70747c44a77c7bcd40155683ae19c65e1c03b4aa3499c5328201f1" - } } }, "nbformat": 4, diff --git a/docs/tutorials/noise.ipynb b/docs/tutorials/noise.ipynb index 0a0ebc290..3d43d17e0 100644 --- a/docs/tutorials/noise.ipynb +++ b/docs/tutorials/noise.ipynb @@ -1,4 +1,29 @@ { + "nbformat": 4, + "nbformat_minor": 0, + "metadata": { + "colab": { + "name": "noise.ipynb", + "provenance": [] + }, + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.8.8" + } + }, "cells": [ { "cell_type": "markdown", @@ -11,12 +36,10 @@ }, { "cell_type": "code", - "execution_count": null, "metadata": { "cellView": "form", "id": "iiQkM5ZgQ8r2" }, - "outputs": [], "source": [ "#@title Licensed under the Apache License, Version 2.0 (the \"License\");\n", "# you may not use this file except in compliance with the License.\n", @@ -29,7 +52,9 @@ "# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n", "# See the License for the specific language governing permissions and\n", "# limitations under the License." - ] + ], + "execution_count": null, + "outputs": [] }, { "cell_type": "markdown", @@ -77,29 +102,29 @@ }, { "cell_type": "code", - "execution_count": null, "metadata": { "id": "J2CRbYRqrLdt" }, - "outputs": [], "source": [ "!pip install tensorflow==2.7.0 tensorflow-quantum==0.7.2" - ] + ], + "execution_count": null, + "outputs": [] }, { "cell_type": "code", - "execution_count": null, "metadata": { "id": "QStNslxBwgte" }, - "outputs": [], "source": [ "!pip install -q git+https://github.com/tensorflow/docs" - ] + ], + "execution_count": null, + "outputs": [] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 0, "metadata": { "colab": {}, "colab_type": "code", @@ -114,11 +139,9 @@ }, { "cell_type": "code", - "execution_count": null, "metadata": { "id": "iRU07S4o8B52" }, - "outputs": [], "source": [ "import random\n", "import cirq\n", @@ -130,7 +153,9 @@ "import matplotlib.pyplot as plt\n", "import tensorflow_docs as tfdocs\n", "import tensorflow_docs.plots" - ] + ], + "execution_count": null, + "outputs": [] }, { "cell_type": "markdown", @@ -161,11 +186,9 @@ }, { "cell_type": "code", - "execution_count": null, "metadata": { "id": "Eu_vpHbfrQKQ" }, - "outputs": [], "source": [ "def x_circuit(qubits):\n", " \"\"\"Produces an X wall circuit on `qubits`.\"\"\"\n", @@ -179,18 +202,20 @@ "my_circuit = x_circuit(my_qubits)\n", "my_noisy_circuit = make_noisy(my_circuit, 0.5)\n", "my_circuit" - ] + ], + "execution_count": null, + "outputs": [] }, { "cell_type": "code", - "execution_count": null, "metadata": { "id": "1B7vmyPm_TQ7" }, - "outputs": [], "source": [ "my_noisy_circuit" - ] + ], + "execution_count": null, + "outputs": [] }, { "cell_type": "markdown", @@ -203,15 +228,15 @@ }, { "cell_type": "code", - "execution_count": null, "metadata": { "id": "0QN9W69U8v_V" }, - "outputs": [], "source": [ "rho = cirq.final_density_matrix(my_circuit)\n", "np.round(rho, 3)" - ] + ], + "execution_count": null, + "outputs": [] }, { "cell_type": "markdown", @@ -224,15 +249,15 @@ }, { "cell_type": "code", - "execution_count": null, "metadata": { "id": "zSD9H8SC9IJ1" }, - "outputs": [], "source": [ "rho = cirq.final_density_matrix(my_noisy_circuit)\n", "np.round(rho, 3)" - ] + ], + "execution_count": null, + "outputs": [] }, { "cell_type": "markdown", @@ -245,11 +270,9 @@ }, { "cell_type": "code", - "execution_count": null, "metadata": { "id": "Z4uj-Zs0AE3n" }, - "outputs": [], "source": [ "\"\"\"Sample from my_noisy_circuit.\"\"\"\n", "def plot_samples(circuit):\n", @@ -262,7 +285,9 @@ " plt.bar([i for i in range(2** len(my_qubits))], freqs, tick_label=['00','01','10','11'])\n", "\n", "plot_samples(my_noisy_circuit)" - ] + ], + "execution_count": null, + "outputs": [] }, { "cell_type": "markdown", @@ -275,15 +300,15 @@ }, { "cell_type": "code", - "execution_count": null, "metadata": { "id": "NRCOhTVpEJzz" }, - "outputs": [], "source": [ "\"\"\"Sample from my_circuit.\"\"\"\n", "plot_samples(my_circuit)" - ] + ], + "execution_count": null, + "outputs": [] }, { "cell_type": "markdown", @@ -296,15 +321,15 @@ }, { "cell_type": "code", - "execution_count": null, "metadata": { "id": "D2Fg-FUdUJQx" }, - "outputs": [], "source": [ "my_really_noisy_circuit = make_noisy(my_circuit, 0.75)\n", "plot_samples(my_really_noisy_circuit)" - ] + ], + "execution_count": null, + "outputs": [] }, { "cell_type": "markdown", @@ -330,23 +355,21 @@ }, { "cell_type": "code", - "execution_count": null, "metadata": { "id": "byVI5nbNQ4_b" }, - "outputs": [], "source": [ "\"\"\"Draw bitstring samples from `my_noisy_circuit`\"\"\"\n", "bitstrings = tfq.layers.Sample(backend='noisy')(my_noisy_circuit, repetitions=1000)" - ] + ], + "execution_count": null, + "outputs": [] }, { "cell_type": "code", - "execution_count": null, "metadata": { "id": "ncl0ruCZrd2s" }, - "outputs": [], "source": [ "numeric_values = np.einsum('ijk,k->ij', bitstrings.to_tensor().numpy(), [1, 2])[0]\n", "freqs, _ = np.histogram(numeric_values, bins=[i+0.01 for i in range(-1,2** len(my_qubits))])\n", @@ -355,7 +378,9 @@ "plt.xlabel('Bitstring')\n", "plt.ylabel('Frequency')\n", "plt.bar([i for i in range(2** len(my_qubits))], freqs, tick_label=['00','01','10','11'])" - ] + ], + "execution_count": null, + "outputs": [] }, { "cell_type": "markdown", @@ -369,15 +394,15 @@ }, { "cell_type": "code", - "execution_count": null, "metadata": { "id": "ep45G-09rfrA" }, - "outputs": [], "source": [ "some_observables = [cirq.X(my_qubits[0]), cirq.Z(my_qubits[0]), 3.0 * cirq.Y(my_qubits[1]) + 1]\n", "some_observables" - ] + ], + "execution_count": null, + "outputs": [] }, { "cell_type": "markdown", @@ -390,17 +415,17 @@ }, { "cell_type": "code", - "execution_count": null, "metadata": { "id": "jL6wJ3LCvNcn" }, - "outputs": [], "source": [ "noiseless_sampled_expectation = tfq.layers.SampledExpectation(backend='noiseless')(\n", " my_circuit, operators=some_observables, repetitions=10000\n", ")\n", "noiseless_sampled_expectation.numpy()" - ] + ], + "execution_count": null, + "outputs": [] }, { "cell_type": "markdown", @@ -413,17 +438,17 @@ }, { "cell_type": "code", - "execution_count": null, "metadata": { "id": "8U4Gm-LGvYqa" }, - "outputs": [], "source": [ "noisy_sampled_expectation = tfq.layers.SampledExpectation(backend='noisy')(\n", " [my_noisy_circuit, my_really_noisy_circuit], operators=some_observables, repetitions=10000\n", ")\n", "noisy_sampled_expectation.numpy()" - ] + ], + "execution_count": null, + "outputs": [] }, { "cell_type": "markdown", @@ -440,31 +465,31 @@ }, { "cell_type": "code", - "execution_count": null, "metadata": { "id": "pGXKlyCywAfj" }, - "outputs": [], "source": [ "noiseless_analytic_expectation = tfq.layers.Expectation(backend='noiseless')(\n", " my_circuit, operators=some_observables\n", ")\n", "noiseless_analytic_expectation.numpy()" - ] + ], + "execution_count": null, + "outputs": [] }, { "cell_type": "code", - "execution_count": null, "metadata": { "id": "6FUkJ7aOyTlI" }, - "outputs": [], "source": [ "noisy_analytic_expectation = tfq.layers.Expectation(backend='noisy')(\n", " [my_noisy_circuit, my_really_noisy_circuit], operators=some_observables, repetitions=10000\n", ")\n", "noisy_analytic_expectation.numpy()" - ] + ], + "execution_count": null, + "outputs": [] }, { "cell_type": "markdown", @@ -485,16 +510,16 @@ }, { "cell_type": "code", - "execution_count": null, "metadata": { "id": "_ZqVLEji2WUx" }, - "outputs": [], "source": [ "qubits = cirq.GridQubit.rect(1, 8)\n", "circuits, labels, pauli_sums, _ = tfq.datasets.xxz_chain(qubits, 'closed')\n", "circuits[0]" - ] + ], + "execution_count": null, + "outputs": [] }, { "cell_type": "markdown", @@ -507,11 +532,9 @@ }, { "cell_type": "code", - "execution_count": null, "metadata": { "id": "zkQofAqqGibQ" }, - "outputs": [], "source": [ "def get_data(qubits, depolarize_p=0.):\n", " \"\"\"Return quantum data circuits and labels in `tf.Tensor` form.\"\"\"\n", @@ -524,7 +547,9 @@ " labels_tensor = tf.convert_to_tensor([x[1] for x in tmp])\n", "\n", " return circuits_tensor, labels_tensor" - ] + ], + "execution_count": null, + "outputs": [] }, { "cell_type": "markdown", @@ -538,11 +563,9 @@ }, { "cell_type": "code", - "execution_count": null, "metadata": { "id": "TwryFaFIG2Ya" }, - "outputs": [], "source": [ "def modelling_circuit(qubits, depth, depolarize_p=0.):\n", " \"\"\"A simple classifier circuit.\"\"\"\n", @@ -567,7 +590,9 @@ " return ret, [op(q) for q in qubits for op in [cirq.X, cirq.Y, cirq.Z]]\n", "\n", "modelling_circuit(qubits, 3)[0]" - ] + ], + "execution_count": null, + "outputs": [] }, { "cell_type": "markdown", @@ -581,11 +606,9 @@ }, { "cell_type": "code", - "execution_count": null, "metadata": { "id": "r09CT5N9DWa_" }, - "outputs": [], "source": [ "def build_keras_model(qubits, depolarize_p=0.):\n", " \"\"\"Prepare a noisy hybrid quantum classical Keras model.\"\"\"\n", @@ -601,7 +624,9 @@ " post_process = tf.keras.layers.Dense(1)(intermediate)\n", "\n", " return tf.keras.Model(inputs=[spin_input], outputs=[post_process])" - ] + ], + "execution_count": null, + "outputs": [] }, { "cell_type": "markdown", @@ -618,11 +643,9 @@ }, { "cell_type": "code", - "execution_count": null, "metadata": { "id": "QAgpq9c-EakW" }, - "outputs": [], "source": [ "training_histories = dict()\n", "depolarize_p = 0.\n", @@ -636,15 +659,15 @@ "\n", "# Show the keras plot of the model\n", "tf.keras.utils.plot_model(phase_classifier, show_shapes=True, dpi=70)" - ] + ], + "execution_count": null, + "outputs": [] }, { "cell_type": "code", - "execution_count": null, "metadata": { "id": "9tKimWRMlVfL" }, - "outputs": [], "source": [ "noiseless_data, noiseless_labels = get_data(qubits, depolarize_p)\n", "training_histories['noiseless'] = phase_classifier.fit(x=noiseless_data,\n", @@ -653,7 +676,9 @@ " epochs=n_epochs,\n", " validation_split=0.15,\n", " verbose=1)" - ] + ], + "execution_count": null, + "outputs": [] }, { "cell_type": "markdown", @@ -666,27 +691,27 @@ }, { "cell_type": "code", - "execution_count": null, "metadata": { "id": "TG87YNUWKKLY" }, - "outputs": [], "source": [ "loss_plotter = tfdocs.plots.HistoryPlotter(metric = 'loss', smoothing_std=10)\n", "loss_plotter.plot(training_histories)" - ] + ], + "execution_count": null, + "outputs": [] }, { "cell_type": "code", - "execution_count": null, "metadata": { "id": "O2ZwM18YUxxm" }, - "outputs": [], "source": [ "acc_plotter = tfdocs.plots.HistoryPlotter(metric = 'accuracy', smoothing_std=10)\n", "acc_plotter.plot(training_histories)" - ] + ], + "execution_count": null, + "outputs": [] }, { "cell_type": "markdown", @@ -700,11 +725,9 @@ }, { "cell_type": "code", - "execution_count": null, "metadata": { "id": "0jy54uWpgwhi" }, - "outputs": [], "source": [ "depolarize_p = 0.001\n", "n_epochs = 50\n", @@ -717,7 +740,9 @@ "\n", "# Show the keras plot of the model\n", "tf.keras.utils.plot_model(noisy_phase_classifier, show_shapes=True, dpi=70)" - ] + ], + "execution_count": null, + "outputs": [] }, { "cell_type": "markdown", @@ -730,11 +755,9 @@ }, { "cell_type": "code", - "execution_count": null, "metadata": { "id": "210cLP5AoClJ" }, - "outputs": [], "source": [ "noisy_data, noisy_labels = get_data(qubits, depolarize_p)\n", "training_histories['noisy'] = noisy_phase_classifier.fit(x=noisy_data,\n", @@ -743,29 +766,31 @@ " epochs=n_epochs,\n", " validation_split=0.15,\n", " verbose=1)" - ] + ], + "execution_count": null, + "outputs": [] }, { "cell_type": "code", - "execution_count": null, "metadata": { "id": "eQ8pknNdohzy" }, - "outputs": [], "source": [ "loss_plotter.plot(training_histories)" - ] + ], + "execution_count": null, + "outputs": [] }, { "cell_type": "code", - "execution_count": null, "metadata": { "id": "nBtgnKWtuWRR" }, - "outputs": [], "source": [ "acc_plotter.plot(training_histories)" - ] + ], + "execution_count": null, + "outputs": [] }, { "cell_type": "markdown", @@ -776,30 +801,5 @@ "Success: The noisy model still managed to train under some mild depolarization noise. Try experimenting with different noise models to see how and when training might fail. Also look out for noisy functionality under `tfq.layers` and `tfq.noise`." ] } - ], - "metadata": { - "colab": { - "name": "noise.ipynb", - "provenance": [] - }, - "kernelspec": { - "display_name": "Python 3", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.8.8" - } - }, - "nbformat": 4, - "nbformat_minor": 0 + ] } diff --git a/docs/tutorials/qcnn.ipynb b/docs/tutorials/qcnn.ipynb index f53182701..f6d851723 100644 --- a/docs/tutorials/qcnn.ipynb +++ b/docs/tutorials/qcnn.ipynb @@ -12,15 +12,12 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 0, "metadata": { "cellView": "form", "colab": {}, "colab_type": "code", - "id": "iiQkM5ZgQ8r2", - "vscode": { - "languageId": "python" - } + "id": "iiQkM5ZgQ8r2" }, "outputs": [], "source": [ @@ -94,14 +91,11 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 0, "metadata": { "colab": {}, "colab_type": "code", - "id": "Aquwcz-0aHqz", - "vscode": { - "languageId": "python" - } + "id": "Aquwcz-0aHqz" }, "outputs": [], "source": [ @@ -120,14 +114,11 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 0, "metadata": { "colab": {}, "colab_type": "code", - "id": "3Pl5PW-ACO9J", - "vscode": { - "languageId": "python" - } + "id": "3Pl5PW-ACO9J" }, "outputs": [], "source": [ @@ -136,14 +127,11 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 0, "metadata": { "colab": {}, "colab_type": "code", - "id": "4Ql5PW-ACO0J", - "vscode": { - "languageId": "python" - } + "id": "4Ql5PW-ACO0J" }, "outputs": [], "source": [ @@ -164,14 +152,11 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 0, "metadata": { "colab": {}, "colab_type": "code", - "id": "QytLEAtoejW5", - "vscode": { - "languageId": "python" - } + "id": "QytLEAtoejW5" }, "outputs": [], "source": [ @@ -216,14 +201,11 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 0, "metadata": { "colab": {}, "colab_type": "code", - "id": "FhNf0G_OPLqZ", - "vscode": { - "languageId": "python" - } + "id": "FhNf0G_OPLqZ" }, "outputs": [], "source": [ @@ -258,14 +240,11 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 0, "metadata": { "colab": {}, "colab_type": "code", - "id": "ImRynsUN4BSG", - "vscode": { - "languageId": "python" - } + "id": "ImRynsUN4BSG" }, "outputs": [], "source": [ @@ -284,14 +263,11 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 0, "metadata": { "colab": {}, "colab_type": "code", - "id": "tfff6dJp39Fg", - "vscode": { - "languageId": "python" - } + "id": "tfff6dJp39Fg" }, "outputs": [], "source": [ @@ -362,14 +338,11 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 0, "metadata": { "colab": {}, "colab_type": "code", - "id": "iUrvTCU1hDgP", - "vscode": { - "languageId": "python" - } + "id": "iUrvTCU1hDgP" }, "outputs": [], "source": [ @@ -407,14 +380,11 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 0, "metadata": { "colab": {}, "colab_type": "code", - "id": "eLJ-JHOihDgT", - "vscode": { - "languageId": "python" - } + "id": "eLJ-JHOihDgT" }, "outputs": [], "source": [ @@ -449,14 +419,11 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 0, "metadata": { "colab": {}, "colab_type": "code", - "id": "qpQwVWKazU8g", - "vscode": { - "languageId": "python" - } + "id": "qpQwVWKazU8g" }, "outputs": [], "source": [ @@ -481,14 +448,11 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 0, "metadata": { "colab": {}, "colab_type": "code", - "id": "9tZt0aAO4r4F", - "vscode": { - "languageId": "python" - } + "id": "9tZt0aAO4r4F" }, "outputs": [], "source": [ @@ -512,14 +476,11 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 0, "metadata": { "colab": {}, "colab_type": "code", - "id": "oNRGOqky2exY", - "vscode": { - "languageId": "python" - } + "id": "oNRGOqky2exY" }, "outputs": [], "source": [ @@ -571,14 +532,11 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 0, "metadata": { "colab": {}, "colab_type": "code", - "id": "T5uhvF-g2rpZ", - "vscode": { - "languageId": "python" - } + "id": "T5uhvF-g2rpZ" }, "outputs": [], "source": [ @@ -597,14 +555,11 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 0, "metadata": { "colab": {}, "colab_type": "code", - "id": "aJTdRrfS2uIo", - "vscode": { - "languageId": "python" - } + "id": "aJTdRrfS2uIo" }, "outputs": [], "source": [ @@ -623,14 +578,11 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 0, "metadata": { "colab": {}, "colab_type": "code", - "id": "DOHRbkvH2xGK", - "vscode": { - "languageId": "python" - } + "id": "DOHRbkvH2xGK" }, "outputs": [], "source": [ @@ -651,14 +603,11 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 0, "metadata": { "colab": {}, "colab_type": "code", - "id": "1Fa19Lzb3wnR", - "vscode": { - "languageId": "python" - } + "id": "1Fa19Lzb3wnR" }, "outputs": [], "source": [ @@ -687,14 +636,11 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 0, "metadata": { "colab": {}, "colab_type": "code", - "id": "Bi6q2nmY3z_U", - "vscode": { - "languageId": "python" - } + "id": "Bi6q2nmY3z_U" }, "outputs": [], "source": [ @@ -716,14 +662,11 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 0, "metadata": { "colab": {}, "colab_type": "code", - "id": "jD3fgcWO4yEU", - "vscode": { - "languageId": "python" - } + "id": "jD3fgcWO4yEU" }, "outputs": [], "source": [ @@ -750,14 +693,11 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 0, "metadata": { "colab": {}, "colab_type": "code", - "id": "pFXow2OX47O5", - "vscode": { - "languageId": "python" - } + "id": "pFXow2OX47O5" }, "outputs": [], "source": [ @@ -781,14 +721,11 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 0, "metadata": { "colab": {}, "colab_type": "code", - "id": "vzEsY6-n5NR0", - "vscode": { - "languageId": "python" - } + "id": "vzEsY6-n5NR0" }, "outputs": [], "source": [ @@ -848,14 +785,11 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 0, "metadata": { "colab": {}, "colab_type": "code", - "id": "_TFkAm1sQZEN", - "vscode": { - "languageId": "python" - } + "id": "_TFkAm1sQZEN" }, "outputs": [], "source": [ @@ -886,14 +820,11 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 0, "metadata": { "colab": {}, "colab_type": "code", - "id": "2tiCJOb5Qzcr", - "vscode": { - "languageId": "python" - } + "id": "2tiCJOb5Qzcr" }, "outputs": [], "source": [ @@ -944,14 +875,11 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 0, "metadata": { "colab": {}, "colab_type": "code", - "id": "Ut-U1hBkQ8Fs", - "vscode": { - "languageId": "python" - } + "id": "Ut-U1hBkQ8Fs" }, "outputs": [], "source": [ @@ -1004,14 +932,11 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 0, "metadata": { "colab": {}, "colab_type": "code", - "id": "EyYw9kYIRCE7", - "vscode": { - "languageId": "python" - } + "id": "EyYw9kYIRCE7" }, "outputs": [], "source": [ @@ -1030,14 +955,11 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 0, "metadata": { "colab": {}, "colab_type": "code", - "id": "yL3jhGiBRJHt", - "vscode": { - "languageId": "python" - } + "id": "yL3jhGiBRJHt" }, "outputs": [], "source": [ @@ -1086,14 +1008,11 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 0, "metadata": { "colab": {}, "colab_type": "code", - "id": "W3TkNVm9RTBj", - "vscode": { - "languageId": "python" - } + "id": "W3TkNVm9RTBj" }, "outputs": [], "source": [ @@ -1146,14 +1065,11 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 0, "metadata": { "colab": {}, "colab_type": "code", - "id": "suRvxcAKRZK6", - "vscode": { - "languageId": "python" - } + "id": "suRvxcAKRZK6" }, "outputs": [], "source": [ @@ -1173,14 +1089,11 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 0, "metadata": { "colab": {}, "colab_type": "code", - "id": "-6NR7yAQRmOU", - "vscode": { - "languageId": "python" - } + "id": "-6NR7yAQRmOU" }, "outputs": [], "source": [ diff --git a/docs/tutorials/quantum_data.ipynb b/docs/tutorials/quantum_data.ipynb index 9e78b9493..58329cd0f 100644 --- a/docs/tutorials/quantum_data.ipynb +++ b/docs/tutorials/quantum_data.ipynb @@ -114,21 +114,21 @@ "!pip install tensorflow==2.7.0 tensorflow-quantum==0.7.2" ] }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": {}, - "colab_type": "code", - "id": "4Ql5PW-ACO0J" - }, - "outputs": [], - "source": [ - "# Update package resources to account for version changes.\n", - "import importlib, pkg_resources\n", - "importlib.reload(pkg_resources)" - ] - }, + { + "cell_type": "code", + "execution_count": 0, + "metadata": { + "colab": {}, + "colab_type": "code", + "id": "4Ql5PW-ACO0J" + }, + "outputs": [], + "source": [ + "# Update package resources to account for version changes.\n", + "import importlib, pkg_resources\n", + "importlib.reload(pkg_resources)" + ] + }, { "cell_type": "code", "execution_count": 3, @@ -285,7 +285,7 @@ }, { "data": { - "image/png": "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", + "image/png": "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\n", "text/plain": [ "
" ] @@ -484,7 +484,9 @@ "outputs": [ { "data": { - "image/svg+xml": "(0, 0): (0, 1): (0, 2): (0, 3): X^0.192X^(11/14)X^0.276X^0.876Y^0.622Y^0.78Y^0.802Y^(5/14)Z^(7/16)Z^(3/11)Z^0.958Z^0.501", + "image/svg+xml": [ + "(0, 0): (0, 1): (0, 2): (0, 3): X^0.192X^(11/14)X^0.276X^0.876Y^0.622Y^0.78Y^0.802Y^(5/14)Z^(7/16)Z^(3/11)Z^0.958Z^0.501" + ], "text/plain": [ "" ] @@ -557,7 +559,9 @@ }, { "data": { - "image/svg+xml": "(0, 0): (0, 1): HHXRz(2.0*ref_0)XHHRx(0.5Ï€)Rx(0.5Ï€)XRz(2.0*ref_0)XRx(-0.5Ï€)Rx(-0.5Ï€)XRz(2.0*ref_0)X", + "image/svg+xml": [ + "(0, 0): (0, 1): HHXRz(2.0*ref_0)XHHRx(0.5Ï€)Rx(0.5Ï€)XRz(2.0*ref_0)XRx(-0.5Ï€)Rx(-0.5Ï€)XRz(2.0*ref_0)X" + ], "text/plain": [ "" ] @@ -1043,7 +1047,7 @@ }, { "data": { - "image/png": "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9evXA+DxeLjpppsYNmwYI0aM4Mknn+THH3/kZN0E7fvvv+eUU06J+BrCjVfPl19+yfjx4xk9ejTTp0+nsLAQgJ9++olRo0YxatQoRo8eTVVVFXv27GHq1KmMGjWKYcOG8fPPPwOQn59PSUkJAG+88QYjRoxg5MiRnH/++VHP0RHo2PI4wciYMElHw1tTAzS0hIVzqZtyclplTBJJe+b2L1ezZnd823gNyUvjfycMbXS7V155haysLOrq6hg3bhwnnXQSl19+OfPnz6d3797s27cPgDvvvJP09HRWrlwJQFlZWaPHLigoYMGCBRiNRiorK/n5558xmUzMmTOHW2+9lY8//pgXXniBbdu28ccff2Aymdi3bx+ZmZn89a9/pbi4mNzcXF599VUuueSSsOcoLi4OO149kydPZuHChSiKwksvvcQDDzzAww8/zEMPPcTTTz/NpEmTqK6uxmaz8cILL3DUUUfxr3/9C4/HQ21tbdCxVq9ezV133cWCBQvIycnxny/SOToCUoRFQ8aESToYWjsib30gQ7J6/ny8FRUkT5pE8sRDKHrwIQCM2dISJpG0JU888QSffvopADt37uSFF15g6tSp/jpTWVlZAMyZM4f33nvPv19mZmajxz799NMx+sIQKioquPDCC9m4cSOKouDyhS3MmTOHq666yu+u1M53/vnn89Zbb3HxxRfz22+/8cYbb4Q9x8KFC8OOV09BQQFnnnkme/bswel0+redNGkSN954I+eeey4zZ86ke/fujBs3jksuuQSXy8XJJ5/MqFGjgo71448/cvrpp5Pjm0Bq54t0jo6AFGHRkDFhkg6Eqqp4qkT9L80SVr9+AzuvuBIA+8iRZF96Kd66ekqeegpTmAumRHKgEYvFKhHMmzePOXPm8Ntvv5GUlMRhhx3GqFGjWLduXczH0JdECK1PlZyc7H/8n//8h8MPP5xPP/2Ubdu2cdhhh0U97sUXX8wJJ5yAzWbj9NNPb1FM2bXXXsuNN97IiSeeyLx587jtttsAuOWWWzjuuOOYNWsWkyZNYvbs2UydOpX58+fz9ddfc9FFF3HjjTdywQUXNPscHQEZExYNGRMm6UCoDgdogfm+mLCq777zr9dqguVeczWD1q5B6eDBuhJJR6aiooLMzEySkpJYt24dCxcupL6+nvnz57N161YAv7ttxowZPP300/59NXdk586dWbt2LV6v129Ri3Subt26ASJjUGPGjBk8//zzuN3uoPPl5eWRl5fHXXfdxcUXXxzxuBMmTAg73kjnfv311/3LN2/ezPDhw/nHP/7BuHHjWLduHdu3b6dz585cfvnlXHbZZSxbtizoWEcccQQffvghpaWlQeeLdI6OgBRhUZAxYZKOhKcyENfi9VnCnDt3+JdZevbwP5aFKiWStuXoo4/G7XYzePBgbrnlFiZMmEBubi4vvPACM2fOZOTIkZx55pkA/Pvf/6asrIxhw4YxcuRI5s6dC8B9993H8ccfz8SJE+natWvEc/3973/nn//8J6NHj/YLLoDLLruMnj17+gPd33nnHf+6c889lx49ejA4Sm/ZSOPVc9ttt3H66aczZswYvxsR4LHHHvMnBJjNZo455hjmzZvHyJEjGT16NO+//z7XX3990LGGDh3Kv/71Lw499FBGjhzJjTfeGPUcHQFF7WACY+zYseqSJUta5VzVP//MzsuvIP+9d7GH+KYlkvZG6csv++O9kg+dSs/nn2fHJZdSs2ABAH1mzcLap+PESkgkiWLt2rVRxYUErrnmGkaPHs2ll17a1kPpUIT7bimKslRV1bHhtpf+iKhogfkdS6hKDjxchYVCgBkM2EeM8MeEuX1mewBLr55tNTyJRNKBGDNmDMnJyR0mw7AjI0VYNAw+l42MCZO0c9y+Gjqdb7mF6p9+wlstsiTdpaWkHX88nW78W9iq+RKJRBLK0qVLGywbP348Dkdw6Zs333yT4cOHt9aw9kukCIuCdtNSPZ42HolE0hBVVan88kssvXr5Y8CsAwZQs2gR3tJSVI8Hz759mLt3w5yX18ajlUgkHZlFixa19RD2S2RgfhT82WO6QEaJpL3gWLuW3X//B9vOPAtPZQUAhuRkDFYral0djo0bwevF0r17G49UIpFIJOGQIiwKmghTpQiTtBPq129g7aDB1K1ajbs0kA5ePW8eIESYYrfhra+n4ssvwWQiJUwrEYlEIpG0PVKERcNkBqQIk7Qfquf+CEDV99/jKS/3L3esFQUeDcnJGJKS8VZXU/nV16RMmYIphuraEolEIml9pAiLgmL2iTCnq41HIpH40ErKKASJMOcOUQ/MkJyMITkJb00N7sJCUmfMaINBSiQSiSQWpAiLgmKW7khJ+0Kr66cYDHgqAnFg3upqUBQMSXYMunYltiGyFpJE0tFJSUlp6yG0GbfddhsPPfRQ3I43ceLEdjEODSnCohCICZOWMEk7wV+zTsFTXo4hNRVTly4AGJKSUAyGIBFm6dOnDQYpkUj2R9z7gUFiga94dXtBirAoyOxISVujejxU//yL3wKmb6FV+fXXGNPTMWVnA/jFl1E3azZYLK03WIlEEhO33HJLUC/I2267jbvuuotp06Zx0EEHMXz4cD7//POYjlVdXR1xvzfeeMPfkuj8888HoLCwkFNOOYWRI0cycuRIFixYwLZt2xg2bJh/v4ceesjfBPuwww7jhhtuYOzYsTz++ON8+eWXjB8/ntGjRzN9+nQKCwv947j44osZPnw4I0aM4OOPP+aVV17hhhtu8B/3xRdf5G9/+1vE1xJuvHpefPFFxo0bx8iRIzn11FOpra0F4MMPP/S3dJo6dSoAq1ev5uCDD2bUqFGMGDGCjRs3AsFWxfvvv5/hw4czcuRIbrnllqjnSBSyTlg0ZHakpI3Z9+qrFD30MN2fe5bUww5D9YqadfXr1uEpK8OYkYHJ1yvNkJYq/vvEmGK1ts2gJZKOxDe3wN6V8T1ml+FwzH0RV5955pnccMMNXH311QB88MEHzJ49m+uuu460tDRKSkqYMGECJ554YqN9Xm02G59++mmD/dasWcNdd93FggULyMnJ8Te7vu666zj00EP59NNP8Xg8VFdX+xuCR8LpdKK1CywrK2PhwoUoisJLL73EAw88wMMPP8ydd95Jeno6K1eu9G9nNpu5++67efDBBzGbzbz66qs8//zzYc+xevXqsOPVM3PmTC6//HJA9NN8+eWXufbaa7njjjuYPXs23bp1o9wXK/vcc89x/fXXc+655+J0OvGE1Pv85ptv+Pzzz1m0aBFJSUn+80U6R6KQIiwK/sB8lxRhkrbBsXkLAB5f+yF/O6LiYgC6/Off/t6Q5i6iga8mwgw2W6uOVSKRxMbo0aMpKipi9+7dFBcXk5mZSZcuXfjb3/7G/PnzMRgM7Nq1i8LCQrr4wg0ioaoqt956a4P9fvzxR04//XR/Q+usrKz/b+/e46qs0oaP/y5gD6AoIioiajCTBiMICIqHJk9RNK9hNoOMWZNUNk1jpj7WlDnJm9qnaWzsYONojQpl42OYM449bz0eUJvyEIykpuYpTDwkIpKoCMJ6/9g3O0AQNdgb4fp+Pn7c97pP19439+ZirXWvBcD69etJT08HwN3dHV9f33qTsKoTc+fl5ZGcnMzx48cpLS0lJMQ+H+3atWtZtmyZYzs/66nsYcOGsXr1asLCwigrK6tzhP264q1q165dTJ8+nTNnzlBcXMydd94JwKBBgxg3bhyjR4/m3nvvBWDAgAHMnj2bvLw87r33Xnr06FHtWGvXriUlJYVWrVpVO19d52gsmoRdgY4TplzOqvnCmr2h4oK9arzE+mvTrU0bPKzR8Ctrvhw1Yd7ezoxUqRvTFWqsGlNSUhIZGRmcOHGC5ORkli5dSn5+PtnZ2dhsNoKDgykpKan3ONe7X1UeHh5UVHw/PV/N/VtX6Wf6xBNPMGXKFBITE9mwYYOj2bIujzzyCC+++CKhoaGkpKRcU1w1jRs3jn/84x9ERkayZMkSNljjI/71r39l69atfPjhh8TExJCdnc19991HXFwcH374IT//+c9ZsGABw4YNu+5zNBbtE3YF39eEacd85Rrmkj0Jq5xCq6JG/wQ3Ly88Kv9itPqLVdaAuWlzpFJNVnJyMsuWLSMjI4OkpCSKioro1KkTNpuNzMxMDh8+fFXHqWu/YcOG8f7771Ng1aJXNrcNHz6c+fPnA1BeXk5RUREBAQGcPHmSgoICLl68yOrVq694vqCgIADS0tIc5fHx8dX6uVXWrsXFxXHkyBHee+89xowZU+dx64q3qrNnzxIYGEhZWRlLly51lB88eJC4uDheeOEFOnbsyJEjRzh06BA//vGPmThxIiNHjmTHjh3VjhUfH8/ixYsdfb4qz1fXORqLJmFXoE9HKlerWQtrLlyotizerbAF2acl8o6OAuy1YwCtb7218QNUSl2XXr16cfbsWYKCgggMDGTs2LFkZWURERFBeno6oaGhV3Wcuvbr1asXzz33HIMHDyYyMpIpU6YA8Nprr5GZmUlERAQxMTHs3r0bm83G888/T79+/YiPj7/iuVNTU0lKSiImJsbRdAj2/lOFhYWODvKZmZmOdaNHj2bQoEGOJsq6Po/a4q1q5syZxMXFMWjQoGoxPvXUU0RERBAeHs7AgQOJjIxk+fLlhIeHExUVxa5du/j1r39d7VgJCQkkJiYSGxtLVFSUY/iJus7RWMRUedrqRhAbG2sqOwg2NmMMe8N+SofHf0vHiROdck6lqjoyYQLFa9fReeYL+CUl8c1DD3Hus82O9T0+/Tce/v6U7NmD5y23IG72v6tK9u3DMyTEUZurlPrenj17CAvTMfScZcSIEUyePJnhLWAKtdp+tkQk2xgTW9v2WhN2BSICNpt2zFdOY0pLObdtGwAXD31N2dFjABSvW893a9ZwPueLattXNj16hYU5EjAAr549NQFTSrnUmTNn6NmzJ97e3i0iAbse2jG/HuLhoR3zldOcfPU1Ti9aRPCKDHJ/8UtHefGGDY5JuqvSzvdKtQw7d+68bOwsT09Ptm7d6qKI6teuXTv27dtXraygoKDWhGzdunX4W2MetiSahNVDkzDlTBetL6zKISlq03PrFvbF9QeoVvullGq+IiIiyMnJcXUYP5i/v3+zeB8NpVG/wUUkQUS+EpEDIvJMLeuniMhuEdkhIutE5KbGjOd62JMw7ZivnMTNPjCjqfK4eE3uvr7OikYppVQjarSaMBFxB94E4oE84HMRWWWM2V1ls+1ArDHmvIj8FngZSL78aK4jNpsOUaGcRsT+d1FF8bnL1vndf//3U2kppZS64TXmN3o/4IAx5hCAiCwDRgKOJMwYk1ll+y3A/Y0Yz3URDw/QjvnKWazxwMqOH7tsVefpzzk7GqWUUo2oMZsjg4AjVZbzrLK6PAz8v0aM5/rYtE+YciKrObLs2OVJmFJKtURLlizhWDP9TmwSbRsicj8QCwyuY/2jwKMA3bt3d2JkIB42TcKUU5R8tc8xJ2R9SVjQ3D9fNnq+UkrVdOnSJTxu8G4MS5YsITw8nC7WFG3NSWPWhB0FulVZ7mqVVSMitwPPAYnGmIu1HcgYs9AYE2uMie3YsWOjBFsXfTpSOUNFSQlfjxxJyRf2qTUu1UjCbN26VVtue9ddtPvFL5wWn1Kq4d1zzz3ExMTQq1cvFi5cCMBHH31Enz59iIyMdAzlUFxcTEpKChEREfTu3ZsVK1YA4OPj4zhWRkYG48aNA+zzHz722GPExcXx9NNPs23bNgYMGEB0dDQDBw7kq6++AuzTFk2dOpXw8HB69+7NG2+8wfr167nnnnscx12zZg2jRo2q8z0sXryYnj170q9fP8aPH8+ECRMcMWRkZDi2q4y1uLiY4cOH06dPHyIiIvjnP/8JQG5uLmFhYYwfP55evXpxxx13cOHCBTIyMsjKymLs2LFERUVx4cIFgoODOXXqFABZWVkMGTIEsI/m/+CDD/Kzn/2Mm266iQ8++ICnn36aiIgIEhISKGuC/bsbMz3+HOghIiHYk69fAfdV3UBEooEFQIIx5mQjxnLd9OlI1VgOjhhB6YGDdHpq6mVJ1sX9BxyvA6ZPx+9XTep5FaWajT9u+yN7T+9t0GOGtg/l9/1+X+92ixYton379ly4cIG+ffsycuRIxo8fz6ZNmwgJCXHMZzhz5kx8fX3ZuXMn8P28jFeSl5fHZ599hru7O9999x2ffPIJHh4erF27lmnTprFixQoWLlxIbm4uOTk5eHh4cPr0afz8/Hj88cfJz8+nY8eOLF68mIceeqjWcxw/fpwZM2aQnZ2Nr68vQ4cOJTo6+opxeXl5sXLlStq2bcupU6fo378/iYmJAOzfv5+///3vvPXWW4wePZoVK1Zw//33M2/ePObMmUNsbK2Dzldz8OBBMjMz2b17NwMGDGDFihW8/PLLjBo1ig8//LBagtkUNFoSZoy5JCITgI8Bd2CRMeZLEXkByDLGrAL+BPgA74sIwDfGmMTGiul62DvmaxKmGlbF+fOUHjgIwMk/zcGjc+c6t3Xz9tKnIpVqhl5//XVWrlwJwJEjR1i4cCG33XYbISEhALRv3x6AtWvXsmzZMsd+V5qDsVJSUhLu1oM+RUVFPPjgg+zfvx8RcdQIrV27lscee8zRXFl5vgceeIB3332XlJQUNm/eTHp6eq3n2Lp1K0OGDKGyhSo5OfmywVlrMsYwbdo0Nm3ahJubG0ePHuXbb78FICQkhKioKABiYmLIzc2t933WdNddd2Gz2YiIiKC8vJyEhATAPs7a9RyvsTXqN7sx5n+A/6lR9nyV17c35vkbgnh5UXGx1NVhqGbm4oED1ZYvnTgBQKt+/fDo2JGSr/YS8NRT5D05ida3/swVISrVIlxNjVVj2LBhA2vXrmXz5s20atWKIUOGEBUVxd69V18rZ1VeAFBSUlJtXevWrR2v//CHPzB06FBWrlxJbm6uo/muLikpKdx99914eXmRlJR0XX3KPDw8qLDGO6yoqKC01P57dOnSpeTn55OdnY3NZiM4ONgRu6enp2N/d3d3Lly4UO+xa77vymO4ublhs9kcn5GbmxuXmmDXIh1uux5ubXyoOHvW1WGoZqSipITc0bU3L96UnkbQK3P4yerV+AweTGjOdmwBnZwcoVKqsRUVFeHn50erVq3Yu3cvW7ZsoaSkhE2bNvH1118DOJoj4+PjefPNNx37VjZHBgQEsGfPHioqKhw1anWdKyjIPjjBkiVLHOXx8fEsWLDAkZxUnq9Lly506dKFWbNmkZKSUudx4+Li2LhxIwUFBZSVlfH+++871gUHB5OdnQ3AqlWrHLVvRUVFdOrUCZvNRmZmJocPH673s2rTpg1nq/wernrsyv5xNypNwurh3qYt5ZqEqQZyPDWVw/eNdXUYSikXS0hI4NKlS4SFhfHMM8/Qv39/OnbsyMKFC7n33nuJjIwkOdn+x9r06dMpLCwkPDycyMhIMjPtQ2y+9NJLjBgxgoEDBxIYGFjnuZ5++mmeffZZoqOjq9UGPfLII3Tv3p3evXsTGRnJe++951g3duxYunXrRlhYWJ3HDQwMJDU1lQEDBjBo0KBq244fP56NGzcSGRnJ5s2bHTVzY8eOJSsri4iICNLT0wkNDa33s6p80KCyY/6MGTN48skniY2NdTS53qjEGOPqGK5JbGysycrKctr5Trz4IkUfrOSWrM+ddk7VPJz//HPEuxU/uqk7ZceOYwvszL5+cdhu6o7YbLj7tKH8zBlKrX4K3RYuwOe221wbtFItwJ49e66YXCiYMGEC0dHRPPzww1e9z5IlS8jKymLevHmNGFnTVtvPlohkG2NqfapAe/vWw71NWyqKizHl5cgNnnEr5yk7eZLDD/waAM9bbuHiV18RbFXVd5o8mbZWZ9GL+/dz6G77syiagCmlmoKYmBhat27NK6+84upQmj1Nwurh1sY+tknFuXO4t23r4mhUU1V+9iwHhgyl4tw5ui9eVG1suYvWmDy5SUkA2KoMOOjeoYNzA1VKqXpU9reqKi4ujosXqw/l+c477xAREeFYHjdunGOsMnV1NAmrh3sbe+JV/t1ZTcJUnS7uP0DFOfuk23m/m4D/bx8DoFVcHOe3bq22bbUkzNfXeUEqpdR12lrje0w1DO2YX4/KmrDywtMujkQ1Zebi949JV5w/z/ltn+MRGEi3+X/BdtP3U215hobi7u/vWBY3Nzx73EzHSU86NV6llFKupzVh9fCwfmGeeGEmIe8vd3E0qqkqLyqqtnzuk0/wGTIEt1atuPnjj6+474//9a/GDE0ppVQTpTVh9fCOisLN1xdTUvugcUpVlJZydNJkALov+hs/Cg4G7B3ylVJKqbpoElYPcXenTfztlJ8pqn9j1eJc2LmL89u+H77EOyaGjpMm0apvX9reeYcLI1NKKdXUaXPkVfBo147yoiKMMdWmiVAt27ktW/hmXAresTGOMjdPT9om3EnbhDtdGJlSSqkbgdaEXQU3X19MaSmmjnmsVMtUsnsPABeyLn+cWymlGoqPj4+rQ2g2Xn31Vc6fP+/qMBw0CbsK7u3aAZD/2uuc27bNtcEolzNlZZxeupRTCxZUK+867w0XRaSUUo2vKU6Afa2aWhKmzZFXwb2tfSyn02lpnE5L45b/ZOPWqpWLo1Kukv+Xv1Aw/6/VyloPHECb2293UURKqet14sUXubhnb4Me0zMslM7TptW5/plnnqFbt2787ne/AyA1NRUPDw8yMzMpLCykrKyMWbNmMXLkyHrPVVxczMiRI2vdLz09nTlz5iAi9O7dm3feeYdvv/2Wxx57jEOHDgEwf/58unTpwogRI9i1axcAc+bMobi4mNTUVIYMGUJUVBT//ve/GTNmDD179mTWrFmUlpbi7+/P0qVLCQgIoLi4mCeeeIKsrCxEhBkzZlBUVMSOHTt49dVXAXjrrbfYvXs3c+fOrfW9zJ49m7S0NDp16kS3bt2IiYlh6tSpDBkyhDlz5hAbG8upU6eIjY0lNzeX3NxcHnjgAc5ZYzTOmzePgQMHsmHDBlJTU+nQoQO7du0iJiaGd999lzfeeINjx44xdOhQOnToQGZmJj4+PhQXFwOQkZHB6tWrWbJkCePGjcPb25vt27dz8uRJFi1aRHp6Ops3byYuLq7aROg/hCZhV8HNp3W15cPjUghZ/t8uika50oWduy5LwAC6L1rkgmiUUjei5ORkJk2a5EjCli9fzscff8zEiRNp27Ytp06don///iQmJtbbD9nLy4uVK1dett/u3buZNWsWn332GR06dOD0aftYlxMnTmTw4MGsXLmS8vJyiouLKSwsvOI5SktLqZyzubCwkC1btiAivP3227z88su88sorzJw5E19fX3bu3OnYzmazMXv2bP70pz9hs9lYvHgxC2q0IFTKzs5m2bJl5OTkcOnSJfr06UNMTEyt21bq1KkTa9aswcvLi/379zNmzBhHnNu3b+fLL7+kS5cuDBo0iE8//ZSJEyfy5z//mczMTDpcxWwlhYWFbN68mVWrVpGYmMinn37K22+/Td++fcnJySEqKqreY9RHk7Cr0HrgQFoPGsS5Tz8F7NPQmPJyijMzKViyBLfWres5gmouyr45Um355vXrqGhCVdtKqWtzpRqrxhIdHc3Jkyc5duwY+fn5+Pn50blzZyZPnsymTZtwc3Pj6NGjfPvtt3Tu3PmKxzLGMG3atMv2W79+PUlJSY5ko3379gCsX7+e9PR0ANzd3fH19a03CUtOTna8zsvLIzk5mePHj1NaWkpISAgAa9euZdmyZY7t/Pz8ABg2bBirV68mLCyMsrKyatMcVfXJJ58watQoWlmtTImJiVeMCaCsrIwJEyaQk5ODu7s7+/btc6zr168fXbt2BSAqKorc3FxuvfXWeo9Z1d13342IEBERQUBAgCP2Xr16kZubq0mYs4gIQa/M4fgfnscrPJz8uXM5s2IFJ56f4djGKzzchREqZ3Fr3ZqOkyfj3t6Piu++qzYFkVJKXa2kpCQyMjI4ceIEycnJLF26lPz8fLKzs7HZbAQHB1NSUlLvca53v6o8PDyoqKhwLNfcv3WVioYnnniCKVOmkJiY6Gj2u5JHHnmEF198kdDQUFJSUq4prtriqxrb3LlzCQgI4IsvvqCiogIvLy/HOk9PT8drd3f3OvuzVa1prPm+K4/h5uZW7Xhubm4N1j9Ok7Cr5N6uHV3feJ2LBw+SP3dutQQs4A/TaT92rAujU0opdSNJTk5m/PjxnDp1io0bN7J8+XI6deqEzWYjMzOTw4cPX9VxioqKat1v2LBhjBo1iilTpuDv78/p06dp3749w4cPZ/78+UyaNMnRHBkQEMDJkycpKCjAx8eH1atXk5CQUOf5goKCAEhLS3OUx8fH8+abbzr6fxUWFuLn50dcXBxHjhzhP//5Dzt27Kjzfdx2222MGzeOZ599lkuXLvGvf/2L3/zmNwAEBweTnZ1Nv379yMjIqBZL165dcXNzIy0tjfLy8no/rzZt2nD27FlHDWFAQAB79uzhlltuYeXKlbRp06beYzQkfTryGnn+5Cf85OOPCF6RQciqf3Lzpo343Xefq8NSSil1A+nVqxdnz54lKCiIwMBAxo4dS1ZWFhEREaSnpxMaGnpVx6lrv169evHcc88xePBgIiMjmTJlCgCvvfYamZmZREREEBMTw+7du7HZbDz//PP069eP+Pj4K547NTWVpKQkYmJiqvWrmj59OoWFhYSHhxMZGUlmZqZj3ejRoxk0aJCjibI2ffr0ITk5mcjISO666y769u3rWDd16lTmz59PdHQ0p06dcpQ//vjjpKWlERkZyd69e6vV2NXl0UcfJSEhgaFDhwLw0ksvMWLECAYOHEhgYGC9+zc0McY4/aQ/RGxsrKnseKeUUkpdqz179hAWFubqMFqMESNGMHnyZIYPH37V+6SmpuLj48PUqVMbMbKGV9vPlohkG2Nia9tea8KUUkop1eDOnDlDz5498fb2vqYErCXRPmFKKaVUE7dz504eeOCBamWenp5s3brVRRHVr127dtWeWAQoKCioNSFbt24d/v7+juX6Ovw3F5qEKaWUUk1cREQEOTk5rg7jB/P3928W76OhaHOkUkqpFudG6w+tmr7r+ZnSJEwppVSL4uXlRUFBgSZiqsEYYygoKKg2VtnV0OZIpZRSLUrXrl3Jy8sjPz/f1aGoZsTLy8sxSv/V0iRMKaVUi2Kz2RzT7SjlStocqZRSSinlApqEKaWUUkq5gCZhSimllFIucMNNWyQi+cDVzWx6/ToAp+rdSjmbXpemSa9L06PXpGnS69L0OOOa3GSM6VjbihsuCXMGEcmqa54n5Tp6XZomvS5Nj16TpkmvS9Pj6muizZFKKaWUUi6gSZhSSimllAtoEla7ha4OQNVKr0vTpNel6dFr0jTpdWl6XHpNtE+YUkoppZQLaE2YUkoppZQLaBJWg4gkiMhXInJARJ5xdTwthYh0E5FMEdktIl+KyJNWeXsRWSMi+63//axyEZHXreu0Q0T6uPYdNG8i4i4i20VktbUcIiJbrc//v0XkR1a5p7V8wFof7NLAmykRaSciGSKyV0T2iMgAvVdcT0QmW99fu0Tk7yLipfeK84nIIhE5KSK7qpRd8/0hIg9a2+8XkQcbI1ZNwqoQEXfgTeAu4KfAGBH5qWujajEuAf9ljPkp0B/4nfXZPwOsM8b0ANZZy2C/Rj2sf48C850fcovyJLCnyvIfgbnGmJuBQuBhq/xhoNAqn2ttpxrea8BHxphQIBL7tdF7xYVEJAiYCMQaY8IBd+BX6L3iCkuAhBpl13R/iEh7YAYQB/QDZlQmbg1Jk7Dq+gEHjDGHjDGlwDJgpItjahGMMceNMf+xXp/F/kslCPvnn2ZtlgbcY70eCaQbuy1AOxEJdG7ULYOIdAX+D/C2tSzAMCDD2qTmdam8XhnAcGt71UBExBe4DfgbgDGm1BhzBr1XmgIPwFtEPIBWwHH0XnE6Y8wm4HSN4mu9P+4E1hhjThtjCoE1XJ7Y/WCahFUXBBypspxnlSknsqrlo4GtQIAx5ri16gQQYL3Wa+U8rwJPAxXWsj9wxhhzyVqu+tk7rou1vsjaXjWcECAfWGw1Eb8tIq3Re8WljDFHgTnAN9iTryIgG71XmoprvT+cct9oEqaaFBHxAVYAk4wx31VdZ+yP8urjvE4kIiOAk8aYbFfHohw8gD7AfGNMNHCO75tWAL1XXMFqqhqJPUnuArSmEWpO1A/XlO4PTcKqOwp0q7Lc1SpTTiAiNuwJ2FJjzAdW8beVTSfW/yetcr1WzjEISBSRXOzN88Ow90dqZzW5QPXP3nFdrPW+QIEzA24B8oA8Y8xWazkDe1Km94pr3Q58bYzJN8aUAR9gv3/0XmkarvX+cMp9o0lYdZ8DPaynWX6EvVPlKhfH1CJYfSH+Buwxxvy5yqpVQOVTKQ8C/6xS/mvryZb+QFGVqmbVQIwxzxpjuhpjgrHfD+uNMWOBTOCX1mY1r0vl9fqltX2T+IuzuTDGnACOiMgtVtFwYDd6r7jaN0B/EWllfZ9VXhe9V5qGa70/PgbuEBE/q5bzDqusQelgrTWIyM+x94FxBxYZY2a7NqKWQURuBT4BdvJ936Np2PuFLQe6A4eB0caY09aX3Dzs1f3ngRRjTJbTA29BRGQIMNUYM0JEfoy9Zqw9sB243xhzUUS8gHew9+k7DfzKGHPIRSE3WyIShf1BiR8Bh4AU7H9U673iQiLyf4Fk7E97bwcewd6PSO8VJxKRvwNDgA7At9ifcvwH13h/iMhD2H8PAcw2xixu8Fg1CVNKKaWUcj5tjlRKKaWUcgFNwpRSSimlXECTMKWUUkopF9AkTCmllFLKBTQJU0oppZRyAU3ClFLNioiUi0hOlX/P1L/XVR87WER2NdTxlFItm0f9myil1A3lgjEmytVBKKVUfbQmTCnVIohIroi8LCI7RWSbiNxslQeLyHoR2SEi60Sku1UeICIrReQL699A61DuIvKWiHwpIv8rIt4ue1NKqRuaJmFKqebGu0ZzZHKVdUXGmAjsI2S/apW9AaQZY3oDS4HXrfLXgY3GmEjsczN+aZX3AN40xvQCzgC/aNR3o5RqtnTEfKVUsyIixcYYn1rKc4FhxphD1mTxJ4wx/iJyCgg0xpRZ5ceNMR1EJB/oaoy5WOUYwcAaY0wPa/n3gM0YM8sJb00p1cxoTZhSqiUxdby+FhervC5H+9Yqpa6TJmFKqZYkucr/m63XnwG/sl6PxT6RPMA64LcAIuIuIr7OClIp1TLoX3BKqebGW0Ryqix/ZIypHKbCT0R2YK/NGmOVPQEsFpGngHwgxSp/ElgoIg9jr/H6LXC8sYNXSrUc2idMKdUiWH3CYo0xp1wdi1JKgTZHKqWUUkq5hNaEKaWUUkq5gNaEKaWUUkq5gCZhSimllFIuoEmYUkoppZQLaBKmlFJKKeUCmoQppZRSSrmAJmFKKaWUUi7w/wHvnB5cNJf+XAAAAABJRU5ErkJggg==", + "image/png": "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9evXA+DxeLjpppsYNmwYI0aM4Mknn+THH3/kZN0E7fvvv+eUU06J+BrCjVfPl19+yfjx4xk9ejTTp0+nsLAQgJ9++olRo0YxatQoRo8eTVVVFXv27GHq1KmMGjWKYcOG8fPPPwOQn59PSUkJAG+88QYjRoxg5MiRnH/++VHP0RHo2PI4wciYMElHw1tTAzS0hIVzqZtyclplTBJJe+b2L1ezZnd823gNyUvjfycMbXS7V155haysLOrq6hg3bhwnnXQSl19+OfPnz6d3797s27cPgDvvvJP09HRWrlwJQFlZWaPHLigoYMGCBRiNRiorK/n5558xmUzMmTOHW2+9lY8//pgXXniBbdu28ccff2Aymdi3bx+ZmZn89a9/pbi4mNzcXF599VUuueSSsOcoLi4OO149kydPZuHChSiKwksvvcQDDzzAww8/zEMPPcTTTz/NpEmTqK6uxmaz8cILL3DUUUfxr3/9C4/HQ21tbdCxVq9ezV133cWCBQvIycnxny/SOToCUoRFQ8aESToYWjsib30gQ7J6/ny8FRUkT5pE8sRDKHrwIQCM2dISJpG0JU888QSffvopADt37uSFF15g6tSp/jpTWVlZAMyZM4f33nvPv19mZmajxz799NMx+sIQKioquPDCC9m4cSOKouDyhS3MmTOHq666yu+u1M53/vnn89Zbb3HxxRfz22+/8cYbb4Q9x8KFC8OOV09BQQFnnnkme/bswel0+redNGkSN954I+eeey4zZ86ke/fujBs3jksuuQSXy8XJJ5/MqFGjgo71448/cvrpp5Pjm0Bq54t0jo6AFGHRkDFhkg6Eqqp4qkT9L80SVr9+AzuvuBIA+8iRZF96Kd66ekqeegpTmAumRHKgEYvFKhHMmzePOXPm8Ntvv5GUlMRhhx3GqFGjWLduXczH0JdECK1PlZyc7H/8n//8h8MPP5xPP/2Ubdu2cdhhh0U97sUXX8wJJ5yAzWbj9NNPb1FM2bXXXsuNN97IiSeeyLx587jtttsAuOWWWzjuuOOYNWsWkyZNYvbs2UydOpX58+fz9ddfc9FFF3HjjTdywQUXNPscHQEZExYNGRMm6UCoDgdogfm+mLCq777zr9dqguVeczWD1q5B6eDBuhJJR6aiooLMzEySkpJYt24dCxcupL6+nvnz57N161YAv7ttxowZPP300/59NXdk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\n", "text/plain": [ "
" ] diff --git a/docs/tutorials/quantum_reinforcement_learning.ipynb b/docs/tutorials/quantum_reinforcement_learning.ipynb index fba0291e6..50298fe8a 100644 --- a/docs/tutorials/quantum_reinforcement_learning.ipynb +++ b/docs/tutorials/quantum_reinforcement_learning.ipynb @@ -177,7 +177,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 0, "metadata": { "colab": {}, "colab_type": "code", @@ -360,7 +360,9 @@ }, { "data": { - "image/svg+xml": "(0, 0): (0, 1): (0, 2): Rx(theta0)Rx(theta3)Rx(theta6)Ry(theta1)Ry(theta4)Ry(theta7)Rz(theta2)Rz(theta5)Rz(theta8)Rx(x0_0)Rx(x0_1)Rx(x0_2)Rx(theta9)Rx(theta12)Rx(theta15)Ry(theta10)Ry(theta13)Ry(theta16)Rz(theta11)Rz(theta14)Rz(theta17)", + "image/svg+xml": [ + "(0, 0): (0, 1): (0, 2): Rx(theta0)Rx(theta3)Rx(theta6)Ry(theta1)Ry(theta4)Ry(theta7)Rz(theta2)Rz(theta5)Rz(theta8)Rx(x0_0)Rx(x0_1)Rx(x0_2)Rx(theta9)Rx(theta12)Rx(theta15)Ry(theta10)Ry(theta13)Ry(theta16)Rz(theta11)Rz(theta14)Rz(theta17)" + ], "text/plain": [ "" ] @@ -589,7 +591,7 @@ "outputs": [ { "data": { - "image/png": "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", + "image/png": "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\n", "text/plain": [ "" ] @@ -906,7 +908,7 @@ "outputs": [ { "data": { - "image/png": "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", + "image/png": "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\n", "text/plain": [ "
" ] @@ -1106,7 +1108,7 @@ "outputs": [ { "data": { - "image/png": "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", + "image/png": "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\n", "text/plain": [ "" ] @@ -1136,7 +1138,7 @@ "outputs": [ { "data": { - "image/png": "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", + "image/png": "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\n", "text/plain": [ "" ] @@ -1201,7 +1203,7 @@ " next_state, reward, done, _ = env.step(action)\n", " \n", " interaction = {'state': state_array, 'action': action, 'next_state': next_state.copy(),\n", - " 'reward': reward, 'done':np.float32(done)}\n", + " 'reward': reward, 'done':float(done)}\n", " \n", " return interaction" ] @@ -1501,7 +1503,7 @@ "outputs": [ { "data": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAAAmQAAAE9CAYAAACleH4eAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADh0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uMy4yLjIsIGh0dHA6Ly9tYXRwbG90bGliLm9yZy+WH4yJAAAgAElEQVR4nOy9d7wsR3UtvHbPzDnn5qSLcrgKIAkQEsgyshBJJotgG3g2/ADzZDC2wQQbkE0wfvh7FtggjI39EAZbZEwQCIQEQigASugq53iF7lW4OZ4woev7o7u6q6qruqt7Zs6ZPmcvfmJmqrurq3v6Tq2z96q1SQgBBoPBYDAYDMbcIZjrATAYDAaDwWAsdDAhYzAYDAaDwZhjMCFjMBgMBoPBmGMwIWMwGAwGg8GYYzAhYzAYDAaDwZhjMCFjMBgMBoPBmGM053oA/WC//fYTRxxxxFwPg8FgMBgMBqMQ69ev3yqEWGvbVmtCdsQRR+CGG26Y62EwGAwGg8FgFIKIHnZt45Qlg8FgMBgMxhyDCRmDwWAwGAzGHIMJGYPBYDAYDMYcgwkZg8FgMBgMxhyDCRmDwWAwGAzGHIMJGYPBYDAYDMYcgwkZg8FgMBgMxhxjqISMiDYQ0W1EdDMR3RC3rSaiS4novvh1VdxORPRZIrqfiG4lomcOc2wMBoPBYDAYo4LZiJC9QAhxohDi5Pjz2QAuE0IcA+Cy+DMAvAzAMfF/bwfwH7MwNgaDwWAwGIw5x1w49b8awPPj9+cDuALAB+P2LwshBIBriWglER0ohHhsDsbIYDAYs44d+9rYuGMKTz9kxVwPZaSwb6aLi29/HCcfvgpH7LfE+7hdUx08tHUfTjx0ZWabEAK/vH8rnnX4Ktzx6G4cvnoxtu1r47gDlw9y6IW4+ZGdOGLNYlzzwDasXTaOk49Yjavv34pFYw0ctnox1iwd1/a/8Tc7cM/je7S2w9csxsYdUxhvBli+qAUAeOqBy/HormnMdHpYt3YJtu5p4/iDlmPr3hk8vmsaTzt48M/YL+/bisXjDRy53xJc88A27JzqYPWSMQghsGOyo+27fKKFlz/9ABARAGD3dAf3b96LZx62CrunO7j7sT2YbHfx3GPWIggoc55Tj1qDhtEOANc/tB0PbNkLADh45SJs2zeD6U7oNf5nHLISxx80u9+/imETMgHgp0QkAHxeCHEegP0VkvU4gP3j9wcDeEQ5dmPcphEyIno7oggaDjvssCEOncFgMGYXv/fvv8KGbZPYcM4r5nooI4WLbnsMH/jOrfido9bg6297tnO/R7ZPoheKhLS9+UvX45ZHduKhf3x5MvFLfO/GTfirb9+S6WO27/1rPvcrjDUDtLsRabjgz38Hb/jP6wBEhOJXZ79Q2/9dX78Jm3ZOVTrXhnNegZf9yy+wZc/MwK/z8rs3463//WsAwNLxJvbOdAuP+el7n4sn778MAPDeb96My+7ejNs+9mL844/vxjeu/w0A4Et/fDJeeOz+yTGX3fUEzjr/BvzNy47Fnz7vqEyfb/vyDdg11cm0++Dslx07rwnZc4QQm4joSQAuJaK71Y1CCBGTNW/EpO48ADj55JNLHctgMBijjA3bJud6CCOJmZis7J7On2hP/+TlAFJSdcsjOwEAQgAGH8PGHdVIzTAgyRgAbN3bTt7biNe+dhd/8MxD8P6XPAUA8KELbsNld2/2PteWPTN9jNSNJ3ZPJ+8lGfvd456En90Vje0ff//peMFTngQAuObBrXjvt27RSNuGbfsAAI/unEYvTO9HM9CVVY/tmo73t/9b2TvTxVtOPRyNIMCXfvUQAOAbb3s21nlEVpdOzG1576GeXQixKX7dTEQXADgFwBMyFUlEBwKQT9ImAIcqhx8StzEYDAZjIUMI9aX84da2uf97XlguyNamotMNsXJxCwesmAAATIw1hjK2srClD2X6FADWLh1Pxrz/8uhVJaIHrVyEB7bsw6M7p3D4mpQ8BSaTzkG3F6IXCqxeMq4R8ANXTCTnHmUMTdRPREuIaJl8D+DFAG4HcCGAt8S7vQXAD+L3FwJ4c7za8tkAdrF+jMFgMBiSolQmZFUPHDJswyoaaacn0GqkU7c/XRkubIRsvJmOs9kgpT0ikTMqIVuxCEAUFVS/L5M4y082ntbuRf2NNQPtHrWa9XD4GmaEbH8AF8R5+yaArwshLiGiXwP4HyI6C8DDAF4f7/9jAC8HcD+ASQBvHeLYGAwGg1ETyPm5Kq2yRshGgKOVHZcQAu1eiDGF3JjauLmCjZBppEh5L4naTKeXtO23bAxARMgWtdKoX+i4H7arlhG38WaAULmRLcvYRhFDI2RCiAcBPMPSvg3AGZZ2AeAvhjUeBoPBYNQP1z24LYmYVI10jQL5sqFsyrIbs5M6RsishEyJkFF8JVv2zOCQVYuSdiEEhBC4/qHtOGXd6twxyP7GmgG6PUWH1uAIGYPBYDAYlfHTOx7H27+yHkeu9be6sGEU9GI2lB1VJyYZo5iCa1oI2VhBylLVkMmIVhgKLSomAPzkjsfxjq/eiH94zdNy2bUaIdPG1hgV2pqP0ftWGQwGg8FAuhLywS3RCrzqGjJLW9VBDRBlx9XpWiJkI8I1GkGWTmgpS2X7eCsbIRPqq6ohEwKPbI+eg4e27kvabdc90+3F/Tcwppx7rCYRsnqMksFgMBgLHgONdDnY3WwuAAitKUv3/oloXdWQDXxU1WAbhytCJgmSJFCAEiETRoSsxNeRpCwbgXY+W/RuFMGEjMFgMBi1wCAjZC70XCryWUIe6UxSllqEbDTIRs9yk8dcov44QqamLOVlh0Inqmq3hPwIoiRk461A043Z9G2jCCZkDAaDwagFqq+ytESiHPvaiMWwYE1Z5pzeSshKnU9Y3w8CNiKri/ptETKLhsyIkGnkTOmbLFeeaMgagbayclRIaxGYkDEYDAZjXsGHbLh2mc0IWRmiCKSEbKyiqF9UTAX6wHbf9JSl/r4RkJGylAMziCN0vVjeuF0RsrqgfiNmMBiMeY5RNTKda5j3pdsLcevGnZn9THIwqilLe4QsbxVhVtRfJkSmRv9s+rV+YOtvzBEhA6LomZqylIeHQqeprvthNYZNNGSNzPnqACZkDAaDMWJgPmaHeV/O/dm9eNW//Qp3PLpLa++ahMzWlyMWNbsRsnJII2SqqN+feIQaISt58gJYI2SN1OC1ZazCHG8G7pSl0leZqF66ylJ36q8L6jdiBoPBqDlu27hLm3RMMB+zw7wvt2/aDQDYvFsvmN1WTEGBchFHk8wNE2WjVHZRf4nzKbdl0BGy4pQlZbbNdELzEAiBjA+Zvj17nge27MXema4SIQtqs7JSBRMyBoPBmEVc/cBWvPLffokv/eoh5z6csrTDvC8uMtLpGoTM2pf92DyiPGiUFfW3+xT1u1YvDgJq35ILjTmc+oHIHNZue2FG8hwpS+X9GZ+6Em/8wrWsIWMwGAyGPx7ZPgkAuPeJPc59mI71h0zKsoQB62xGyGyDyItcdXr9GcP6EJ2qUIOSzTg96bK9AGINWS+bspSlkiTUYd6+aRc+9sM7ree/ZeMuxam/URszWBX1GzGDwWDUGHIOCnJmUg6Q2eF7W9pGhKwMw53zVZZ5thdKSq4KhpqyVPqTvl9qhMz0Ahtv6SlLp6hfeX/9hu25Y5ARt7FmUJtySSqYkDEYDMYsQk6Eed5Io1p7ca7h4hDm/cqK+v2Jz1yvssxDWsty9ET9aqpXkq88HddYwxT1R68CZmrVtcoyx4esGfAqSwaDwWDkQ04veZpjjpDZYRIr1y3sZET9xX1JzKYxrLV0Us7+Vg1ZRduLQXN+lcjKZzsvCjzebBiRTFVDprSWGOdMNwRRRASbltqao476jZjBYDBqDPkXf95kxbAj9MxEZghZiXPMte1FXiqxbUlZjo6GTCFkMSPLG9tYM9BF/fFXZmrIyoyz3Q0x1ghARJyyZDAYDEY+5MTFEbLhQYrfJUrZXvRmkZDZRP05hNAm6i+zzlI9n4votLsh3v7lG3D347u9+wX06Jt8xvMIGZFOSHUfMn3Muel95bydnkjuDYv6GQwGg5ELOd+yhqwYRdEf75RliXMOOnKUB9v3nBegS33IqkV/1CiW6zy3P7oLP73zCXzwu7dV71sSshyyGBDBlkEVQr8vAvmEWu9DJGdk2wsGg8Fg5MInZTkMTvDzu5/A3//wjsF3PESY98E30uWjIXOxtNG2vZCi/v5Tlq57KZvLUj41siejZXkyLoI9hZpXXNwGbUWmQDJwTlkyGAwGIxdhQsjc+wyDEvzv/74B//WrDUPoefbge18yKcsSRbznWkPmI+ofq2gM++dfuzF5X3SZZSWOWp1MD2sXIoMoJ7YX0b+R5FDHOOV2k7DJw8xSTXVA/UbMYDAYNYacCIMcRsZO/XY4bS+M9m6vHj5k1lWWeREyS3HxMsTp1o1pzU935Kna9csI2eFrFifkLH9oZNWQRaJ+oBFfmICwpvdlOlSvdZnuy7YXDAaDwchF6kPm3ofpmB0Z2wvHTfTRkLmIT9dcyjlElC2d1IvHppqslvEh085TsL1srz0h0AgIAZEi6i+KkGU1bSKOkMk/WIr4sak3k6c0jWjrACZkDAaDMYuQcxA79RfDvEWu+7Jh2yTCUCSTcDuzyjJ7jLuWZdlRVkdZ2wuB/FR3GbhWc1Z99nphFNVSh5c3VnObPG0YR8ikqWzRePQIWUok88jgqKI51wNgMBiMhYTQw/Zi0CGyr1778GA7nCO4bsvHf3Qnpjs9NIMoOpMtLl7C9mJWI2TlVlmGIpu+q8o7iohOWUITRbWghdZyI2Qgh6g/ei9TlqEQ1mid7DqzyrKGREyCI2QMBoMxiwg9ImSDxoe/f/usnWuQyK6y1D+rd/CGDduTCJmP275rj1m1vbBG7vItHkwiX/Upcl1n1avv9gSaQaA913l/dJiifnndkc1FqrEUjjGlmn915Wj1+zEK4AgZg8FgDAAbd0zigOUThf5HcgLJ+0t+11QHoRBYtWRsoGOsO/LIinY/C4hcHubcGDZnsKHIasaqRoSchKyq7YUQCAhGypJw68debN3fNIaV5xVCRBGywBICyxkvoGvIAOADL30KTjp0lfc1zDU4QsZgMBh9Yvu+Np7zicvxf350Z+G+PinL5/7T5Tjp45cOanjzBr7RKzNFaRf124+dXduLcinLKCU3mHO7ziNJb2nbi1jDZx63fKKF5ROtzP4EspZIkhqyIElZ5p9X91aLepb48+cfjVOPWlPuQuYQTMgYDAajT+ya6gAArrp3S+G+coJp1FjrMlcw52b1Fqp308dQdhSKi9tO5SKEu6c72LGvPTBCVmStUnb1prrKUiLP2iWbsoxewzDWkAXpOHM1ZFqrGNiih7kApywZDAZjQPCZyn1sLxgRzHuUV+cRUHVFOspwrLk2hnVd44l//1OEAlg81tDaqz5HzghZte4QhiKji8zXkJk+ZOn5QwE0Y2PXovFo9TnDev+74ggZg8FgzCLY0aI68oiVJiHzuMkjkbK0DMJVusm1GKS6D1nRMsty/cmUpTq+vLER9OtPRP1CQMgVm/DwIVP7gKh8P0YBTMgYDAZjQPCZCmQEZDZLJs4XVNaQlRH1z6pTv63NLwqYfK4aIXO4e1T2IRNRhEwdT+EqS/W8clxS1C+d+oVdN0fJdn3sHCFjMBgMRqmU5WzaK9QVGS1Y7t7pTJw9zv9eF6VFB4vsuYoidCbhGLTthcTuqQ7O/u6tmGr3/PqziPrzVoAGRHq6UfEhE1BsL0Q+STRJXY35GBMyBoPB6BdlJgFZ1Wd2J/75Af8ImfF5RCNkVlF/UYRsQCEgZ13Q+O7d/fgefPPXj+Db6x/x6q8nkE1Z5kXIYFshKW0v9FqWruPl/mofbAzLYDAYDC9IJ3jmY+WRd8+0edhgG3bbC8cqyxEV9UtkjGEri/oHq+rvhWEUIVPacs2PjVWWaXHx6LtpqBGynPOqt6tMJHQUwYSMwWAwBgSfSEw30ZAV71xkTTDfka1lmTG+sB6XjZD538fZFfVn24oidNnSSdHnssW0B+3U3wtj3Zcm6nfDFN8ntheGMWwoCqoXQGNkrCFjMBiMhYwyk0AvdoL38bvqzKJrfB2QGyFDSk7MKJM1QuboZ86NYctGyBztRRj0ZfbCSPeljiMvQhb5kOkrJOW4wjAlmALCTh4tHicCTMgYDAZjQaOKRsnnmHav/0LXO/a1++5jVOAb6epHQzabxrC2lY5FRCmjkSJHewFc97KofqgL0sxVHQXlMIzAWGUp74WI/xcoqyjzC66rY2XbCwaDwWDA76/zREPmEaJod/snZHUuwWSSAV8NWZZEZA8cCR8y2yrLkrYXRe3uc7vaq12/TFlSiZRlaIuQhdH3nGrIRMEqS7UPjpAxGAwGA2U1ZMX79kvI5qMGTb0mvXSSYnuROcbSj4N4zHlx8cKUpd0YNldAb8GgV/mGQlRIWarHR6/SGFYV9dtSlvK6Mz5k1S9hzsGEjMFgMPpEFQ2Zj6i/X0JW95Wctvvqc00mES1zG+Z6pV5pH7L486A0ZJWNYWWETKFEhYRMO2+cyo/HJm0vikT9epStPDEdJTAhYzAYjFlEanvhQch6fqacLtgm97pHzVz3jcgdHbFGyBy3YTZJbJni4hLZCFncXpKROTVkpXpJ0QujCJn6JeRzI8pEt4DsKkuBgpSlaZ1RXz7GhIzBYDD6RWJq6TGdlbG9mOkzQmYnZH11OedQx+9LwGzfi/M2zKao33KusosK0ghZWdsLe3smuug5HlnuKPAkZNF+ad+aU79iX1Ek6tcHW2s+NnxCRkQNIrqJiH4Uf15HRNcR0f1E9C0iGovbx+PP98fbjxj22BgMBmMQKDOF9mZRQ2ab3GvOx3IjZBL9pB1n8/7YzlUYIXPM2uVTloO90l4o0GyUS1nqpq7xa0ZDZre9kN+xFmWDYKf+ArwbwF3K508AOFcIcTSAHQDOitvPArAjbj833o/BYDBGHnLC8FlyL0Xjs7HKsmcRqNc9ZekzfB/rBnfKcjZF/dlzFZ3fJeovS0SGYQxrFhcvWmWpXn8q6o/eB3G0TcB+n9QUp9pWXzo2ZEJGRIcAeAWA/4w/E4AXAvhOvMv5AF4Tv391/Bnx9jOozlSXwWAsGJRLWZbRkA0+QlZ3OCNkJVdZujCbt6xKhMycFKuK+gd9nb04qqUSxiqifqkhCygimaGw/6tSFwGkbWx7kYfPAPgAAPmrsgbATiFEN/68EcDB8fuDATwCAPH2XfH+DAaDMeLwn91m0/aia3EerTtFUwmZa/L10ZC57sTci/rzj3GK+ssaw7qehMqrLJGNkBUUF7eL+uV3QMk+1pRlElFTV1myMawVRHQmgM1CiPUD7vftRHQDEd2wZcuWQXbNYDAYlVDKCV4SstlIWc5HUb9rAyFhJ+YEXiZlObu2FxZRv82+X4UjRFbeh6zU7h79xU79qjFsboTMTFmmETIRR8gCosQGw4RIjlPaOELmxGkAXkVEGwB8E1Gq8l8ArCSiZrzPIQA2xe83ATgUAOLtKwBsMzsVQpwnhDhZCHHy2rVrhzh8BoPB8EMqSC7eV514itB3ytJGyGoeIxMDJhLZEwy5fwU2olHkS+uKkJUlIm4NWbUbIFOWvrU1TWPY5H28yjKIfUxCh1N/qB6QeVdPDI2QCSH+RghxiBDiCAB/CODnQog3ArgcwGvj3d4C4Afx+wvjz4i3/1zUXX3KYDAWBKpolHxSY2x7kYVbQ5Yia93Qf/9VEIYCU223l1wVp/5BBYAGbQwbGqL+Igk4gfRalqaGTNbFFPmi/oxTf41DZHPhQ/ZBAO8jovsRacS+GLd/EcCauP19AM6eg7ExGAxGaSSrLD3mgjAhZCZpsKy461PQNJt1GWcLPoTJy4dswITEhk/+5B4c99FLMNnuWrfbvvPSxrAV+Yd3cXHP/kxRv1+ETF8hCUgNWaQFS1OW7lHot0vUWEEGNIt36R9CiCsAXBG/fxDAKZZ9pgG8bjbGw2AwGINEuQiZPWVpm4f75VPzk5DZ29XISD+rLAd5y75740YAwJ7pLhaPZadb6yrLgsFmSidJ24uSY3NdZ9UIYVo6KR5XAVOUlhYSSXHxOEVJFHuVOQaarrLUSV2NA2SzQ8gYDAZjPsNmUlkEU1Rtmwj7TZ9ZjWFrztF8NE4+UR5XP4PU2BVxg0opywFFyAbtQxbGpZOSlGXB/tLSIh1Pen4B6UNGsQ+Z5Xy2lCXqXcuSCRmDwWD0iSoapWyEzEae+iMHXZsxbM2lz+otUS0OlEWWmWvM0yD5tvcD97ksKctCY1j9c1X64TpL1WeuGwo0A0oIYxExytpeiOQ18SGDW9Rv+yMoFKLWETKuZclgMBizCJeoPy8KUBV5/k11RTUNmT8GuZasiBzYzlQcIfPvK/fcnhoyX0RCfP9VlsgYw8p+4r7iVZaiQNTPTv0MBoPBSGBb8eXcN371iZD1m7LsLigNmWI/YmyzR1jsGMYdc6ZHLc3FEbLhpiyrPjKJhqzEKkv1tsjxCCGidD6l12olrq7vtMYhMiZkDAaD0SfKpAHdKUvbvn0NyxptqTtFU68pM/cmjCxDybL9OAmJ3x0KQ4FOgU9ckWu87bkpsp7L+sJWFPU7zlPZhyzUV1kW8aJI1K9Et+S4hNxOcQFye3FxWFKWQtR7lSUTMgaDwegTchLx+uPckbK0rYjs1/bCFiGrk71jmcmVoEfIbJYKGvrUkP3tBbfhmA9d7LVvGb1aWVF/VQw6QiYLgqe1NQsiZKSfSx1PVKg81ZlZo2GWlKXst65gQsZgVMRUu4fP/OzevsvbMOqPVJDssa9xjNmHir5XWdY8QmZPVbmvQC9QXa0fX0LyzV8/UrhPFQ2Zrf5oXp/Vfchc7eZz6ddfT5ZOgl+EjEBO0tyNTWajVZYOUb+UCRhtNeZjTMgYjKr47M/vw2d+dh++s37jXA+FMccoQ3IkETDJ0mz5kNUoQGaFeknmpK9mLE2xd14/9l4GB1ePdt1gfl+DsnVw2l5U1ZAJ3fbCJ0ImAEy2u/jsZfdp6d9otSQlUbS8P1bMeph1dupn2wsGoyJ27GsDqL+NAKN/lDOGjV5nQ9TvawwbhiI24hz9ycxZOolIi5rohMw/Ulj2lkv/rUqwifoLnfr1z0U6NRecpZMq/p6Fiajf06kf0b3+zM/uw3lXPaht6/bC5Hk0yXU6Tv0ViO7d6D/BbnCEjMGoiOlOVKNuUasxxyNhzD38JzE54W3f18Z5Vz3gdO4H+td7WSd3S9ORf/tjvOOr6/s612zBpbGKNGRp6rjo1vUr6pcwV0U+sn0SX7vu4WRMebCL+sudv3LK0vHMFmRMnUhLJ8mWoghZtH3vTLasVKRHk6StIGVpaM9q8DeFE0zIGIyKmO5Ev1wTTMgWPEoZw8YT3r1P7MX//fHduPE3O5x99JuytIr6HRPxT+54or+TzRJedO5V9g2k6or0lXlWTf+AUnbHfOhi3PfEnuTzH553LT50we3YpxCNMucqSwh9+cf//b2nG+ex71flkQvDiDQ1SviQSeJkuzfdMEwWCLhF/VndZk+IyhHDUQATMgajIqbiCNlEi/8ZLXT0Q5w6PbumLOq3P0ZWd2PYYm9RfQ+hvFHvZ16ExUSV7/KWjbuS9zsnpZQhjQKVWWU5rAhZw/iZcpHEKs+cjBKqKUsfUX80DssYQhiifv+UZY35GBMyBqMqZMpyoskRsoWOMqlFc185f1g1ZMOwveirx9lFmbGq5CzSkKn9+JPd2dSE2sYwrILwpsi+qGh3GcgxlxX1A/Z70A1jDRlS537XONXr6PZEcYWAEQYTMgajIqZju4s6CKEZw0WZKcycB/OiKMMwhp3XUHRFGrEoESEbBh8rU8i7yKnf3OybossQshJRuyLI64tSlv61LF3jiAJdlIj6rSln4xWQov76/h4zIWMwKmImjpDxKktGqVWWLjH1EFZZjqIx7A0btuOqe7cMvF9SnN9N3ZHtil2EpN97npyzyJjW0T6slGWzYRIy13NY6vQA0jGrpZOKIFemusYRUPqd5lnC6P5lYa1F/Wx7wWBUhNSQMR9jlCHlmQhHkrrJ7tu/D1l2ydxcP66v/X/XAAA2nPOKgffttr2w7esftSo61sUB8tJyrrMV8cGqhMOMWDlJYoUnRD5mgbLKMvAM97jGIdOfTtsLqw8ZO/UzGAsS00mEjLHgoaTKilAmMtO/7UW2rU6i/jLQSicZk7iNZLhugw8Jbhs3duOOKXzvRt0gWjjea/tUiJBlCX3VlKVfhMzncUlF/fBPWVpWWar6L4qLiwtHztKWsuyGYa1TlhwhYzAqQtpezNcJjuGPco+AS0ydbevfGNYWIavPA1v28lVPN01CVuLe+pDgyZme9vncn90LAHjNiQdr58yzdojGkG0blqg/s8rStWMfov6GIur3XSGrXm4jIITxquOAyEvUr24KQ46QMRgLElOsIWPEkBOGT7QiK8qW7TYNWX/jGtbkPltwR5biLUZERY+WqBGyLPrx4Zrs9KztwvGhTHqwqJalCV/+UTVC5gPZV5Rm9IuQBZZ0rnoMIXbqd4xV9ZyTKHvvRg1MyBiMipBFxTlCxihlDDuL0RKbqL9Ofz+UNW9V3dt7PVVD5p8O9omQdW25YOPYUDEpLbOisexX7i2i99WQ9REha6oRMm9j2LStqeQsU2NYu6hfHqdu64X1XvXOhIzB6BM1mt8YQ0KqXSp+Gsw9konJKvDu7+nKqwFYZ9isIUwfMjVaIgA8vmsaF9yU6rzKrHw04RNd0987yF/xqQqP8aUfDXOVpeMiMhoyjxuS+JBR+i0UEaPEGFa5ooZGyNJ6l9ZFGcmK2nRjLwxrrCBjDRmD0Tfm2kaAMfcoZwxrtsRRFEvQZSilk+bB43rNA9uwdKLpnHyF0KOL51+9AQ9t3YeHt03ipU89EIvGGn3VsnRFLnXdWlpX0ZVJG8Rvh29EqOHrQ2Z+9hiiqiELkpRl/jG2e6MSMopd/11O/YnthdLW7dW7liUTMgajT8yD+Y3RJ8o8A2Uc4vsunaTMumuWjGHbvnatNI+uy3/zl64HABih+mMAACAASURBVJx5woHpvsp1CQiNjF5xz5bMfv1EyPLKDkmCVFQpYLbhqyEzr81n7MkqyxJO/bZxNIyUZZBre5Edb7tX7wgZpywZjH4x97+1jLlGmWfAFPVbtDQSg4yQ1TFyUJXImBEyFfKelHHPN1Hkph/1I5QFG/Z9fAj3rzdsz93ub8Sqf/bV5/k8g6GSsvQlYoGFuGqi/thCIxT5CV/dGFYsHA0ZEQVEtHxYg2Ew6ohR+OuXMbcoE8ly7VnGvNQXoUbI7CWaRjnlXnVoAm5CJu+J+3soPqk7BakcL/R21/5FeF1spOuCt4bMM2VpPsteKUslQiZRxYesaWrIkgiZbZzZ8fXCeV7Lkoi+TkTLiWgJgNsB3ElE7x/+0BgMBqMe6GeVZbpabPApSzVCJieqKhqhuULR0FzRECEcK0yRErWyKzhV+KSdhTI+d3qw+FyF8NWQGUzFd6FBGU2dXBnpM6wkeqi0BRYNWSjs35XqOWfvuX7wiZAdL4TYDeA1AC4GsA7Am4Y6KgajRhjlCY0xOxDGa+6+mZ3cKTSHu4I3ehohkxEy/TyDqt04DJQZmr6vcEbIeknK0t6Pz/3Isy6xkTBz712THXzvxo0Dia17+5AF1SJkPpARQ13UXxQhyz6PZoQtWYdpix4br2m//uMeNfgQshYRtRARsguFEB2waobBSDDC8xljllBqlSVMQiTb++vXBjshM8czP6BeRxQhs7NZmV7rp5ale5WlQsJESpZMkvPub92E9/3PLXhgy16Ps7nPUQZmylL6KGb71z+77DFUpCnL9Jq9V1kq3eurLCPdW7Go3+i3cLSjCx9C9nkAGwAsAXAVER0OYPcwB8Vg1AnzZUJjVEeZZ8Cc38KcFNogU5bu8dj3+c9fPIgjzr4InX7DdH2gqj4zFO4IWbdXFCHz6d/eLpB+jyZBVPH4rmkAwFTb7vhfBr4RIXO/PdMd637ZVZb56IUCr/ncrwAAjSBIz+MZIdNWWZIaIUtF/fnpfH3bvI6QCSE+K4Q4WAjxchHhYQAvmIWxMRi1wCiLohmzg1KPgCNCNYxVllpZGsevvWvs514a1WecdpQJmg0U3VczIqW+d5HRsChC1kfK0vQhk+GaYf5G+BbTJpAWtdoz3bXul11lmT/2vTNpPw0q4UMWv6rEOZOyjMth5f07MLfNy+LiRPS+gmM/PeCxMBi1BNMxRn8pS3fExjUZ3r5pF87811/i4nefjuMOdC987/qkLAsiRaNsI+C66wLQSiepSET9fZzXlcYTig+ZRs4c/QzGGNZ/v4AoeaZ2OyJkWaf+/H7VSFsQIGFavqssuz07IVNF/bYb6ExZju7jWoi8CNmy+L+TAfwZgIPj/94B4JnDHxqDUQ9wgIzRT8oSycTi1smYuOT2xwEAl975BADggS17cc0D2zL7dRSdUELIjNG60oIpUZy7B1y9J089aDme/5S1zu3aCsecCFkq6s+/7jy4fMjMKF3Sp4vAFZ5J9uXe05d/EOlkxRkhM5+PkhEyGaEqGpfcr6No/VRC1mpQXDrJnrJMDH7nUcrSGSETQvw9ABDRVQCeKYTYE3/+GICLZmV0DEYtwIxsoaPcakAzQqa/6tvsHct5S24/41NXAgA2nPMKbT+bMayv8Wdix9Fv3nRAIAJ+76SDddd9p5YrZ5VlkrJ0HOtxue7z6mOwtVdB3pi8I2SgOHoXR8imshGyX9y3Bb/ZNqmfu6BfldhFqyyj91UiZOoxal9WDVkotxn9zseUpYL9AbSVz+24jcFggCNkDOWv9QqC8DxNk4tU2Mrz2NDuZSNk2fEURcjyzzFMqEMjUNZLKydn6VplWSzq94iQ9bnKssy5gMH8yRelLNPPtgjZm754faataIx6ytLfh0yORV00okXIgiBOWdpjuLbi4tGJ8887yvBZZfllANcT0cfi6Nh1AP57mINiMOoE5mOMfki5MF5VuEiDy1NMxe/9+69w0a2PKcfYz+PWkEUbXORjNqCemShr3aBN1cZbp1N/oai/eFx5PmTWffqIxpl9mYd4i/pJ33f3dMdLw1asIXOkLAtF/XHK0kHIGoFMWUb39dDVi/C1P/ntwnHVmI/lR8go+jPsy4gMYU+Pm98qhLhp2ANjMOoCjpAx+tEC5Wm1XBNmI9CPteGm3+zUPrtInLtQdv722YAeIcuamwoHARJCeDj1O87pMa7yTv3VzwUU/Mb41rIkfZVlpycw0w0x0WrkHlfEx6umLOW41e9JLZ3UbEQrNoWIvs+j1i7FaUfvl2xPUurGzRnlRShFyCVkQghBRD8WQjwdwI2zNCYGo1bgWpYMX9Ii555mQMlElPhWldCQ+aYsbcf4RsgkfAppDwvmv61shCyFei/yImRFon6f79JpzaaOQRtP9Whc3vFACVE/siRp93QnIWRuo9yilGVKyAJl5UChhix+da2ybAaRy6z0ITP7c8kE5nUtSwA3EtFvDX0kDEZNwREyhvfEGu+oTjyuv/SjNns/qcu5/8OX1A50aNhcmNOUpZGzNL3UXFnBflZZ9pOy1McgFA2ZqydPDVnObr4RISIkD0GrEb3ZN5N6zLnuVxnbCzVCVgRJsDoOnaPsS8RjkP1+5x2nYtXi1rx06vcR9f82gDcS0cMA9gFyJao4YagjYzBqAuZjDN8oqdyrGRBm4vd5pZNcE38jST/6j9FpDFtw3Kj8wWGL8KijN3VWPUcYq8iHzKuWZYE+zey/H71amf3ykZq2thoBOr0euso9clVkKGV7EVApTZt53qztBUGIUKsRevIRq/HUg1ZgKjYszmjq5mvKMsZLhj4KBqPGYKd+RvLXegG9kRN2sxEAiCeUHJG5U7gsI2QlolcpmdGPGekImfKeCLmrLNX7F+ZpyOL9nLUcPcZVZBUi37usRtRx+iBvvzI+ZEESIYueP/Uedbr5WkIXdk3pETJ5zc2Gn+1FR0lZjjXSvxpkX1JDRsaxLu1lfemYByGLSyWBiJ4EYGLoI2IwGIyaoWykQyUWoQCufmArHovrG6pwkaGgHw1ZRkSWf9ywjGFVV/ucnZK3hAINWahvKNKQTXf8imtb+/BJWWoC/341ZG74BoQCouR+t2Lio+q3Znr2EllFY9y2N3XFaigLB1RyZYNtleVEKz2m1QgiUT9kytJBxjMhsvzxjjIKNWRE9Coiug/AQwCuRFRo/GKP4yaI6HoiuoWI7iAiaTS7joiuI6L7iehbRDQWt4/Hn++Ptx/Rx3UxGLMGDpAxyj4CuoZM4A1fuA4fuuD2zH5uY1hybhdC4NiPZH+iXbYXRaRueITMYx/lPRFZVlm6UpbFqyxnuikBOWXdanz8NU/DqUeusUYqpzs9XHJ7aiGSVwcz0Y2FKelwWKINxqnf2xhWjZDFZChUU5bFaVgbtu6dSd5Hmv6o77FmASGzrLJctWQseS8jZKEQmOn20FL6k0QNyJLdOhvD+oj6Pw7g2QDuFUKsA3AGgGs9jpsB8EIhxDMAnAjgpUT0bACfAHCuEOJoADsAnBXvfxaAHXH7ufF+DMbIg1dZMvxXWUb7tVRCltuvvT1NhWV36IXCGv1xifqLnl/nisI+4UP0TNuLTMpS608/zpXOTQiZco9aDcKbnn04JlqB9W6cc/HdeMdXb8SvN2zHdQ9uw6adU87x2ohCJijpEKS7kEeaS/mQxQ+OTCf2tJRltS962740QqaSq2JClh3D6sUpIZMWGEIAW/e2sd/SMeXY9NnPOPXXl495EbKOEGIbgICIAiHE5YjqW+ZCRNgbf2zF/wkALwTwnbj9fACvid+/Ov6MePsZVGd1HmPBgCNkjNIpS0Vfk0dMiiNklnM4+nI79TtPnzuGfuGTblVJjSyOrW13aMjyVlmGQiAMhVbFIDUzJev1bt4TpZOf2D2N/3XetfjkJfdY+37RuVcmIndVQ9avU7/LTqMMVLm9TFl2PET9uc9nKLB9X1trk9/ReBEhs7SpEbJmnLKcbHexd6aLtcvGtWMX6irLnUS0FMBVAL5GRJsRrbYsBBE1AKwHcDSAzwF4AMBOIYRclrERUcFyxK+PAIAQoktEuwCsAbDV81oYjDkBEzJG+VWW6WSVR0x8a1n6HSN9yPTtaiQpDEUmLTgsUX8VopcfIdNTlq5xd8PIEFVFUu4H9n/Pi1rRVPmDmx/NHV9ZXZrvvc0V9cuxe9SOlM/AmEVD1nausnT3uWuqg14o8K4XHo1DVy/Guv2WJONpFWnILMNdvUSPkBEBm/dEKdG1SxVCRjQvi4v7RMheDWASwHsBXIKIVL3Sp3MhRE8IcSKAQwCcAuDYiuNMQERvJ6IbiOiGLVu2FB/AYAwZzMcY/qmnaEeVWPRcAiPk+ZDlRMgK05zu8dnE6sP6g8NLQ6alLCkr6tc0ZPpxeRqy6Y5dwE6xM7yJRWPRVHnpnU8UDzoZjxqxc4zF8+b67FWUNldXWVpTlhU0ZDJdefSTluL1Jx+qbfMV9atYpaYsY6f+nZPRKk41QhZQXoSsvozMh5D9IYCjhBBdIcT5QojPxilMbwghdgK4HMCpAFYSkYzMHQJgU/x+E4BDASDevgJA5jxCiPOEECcLIU5eu3ZtmWEwGAzGUJDohgpmTrldLRHjmgij/QuiXSUIVHqM3q5OuLaIzbCc+r00ZOoHyo9+ZHzIHES3Z42QyZSlfVyLx3ySSTq0dKpzH09Clhsh89WQZVdZ+qQs80b48LYoWXbA8tSAQT5DvqJ+FauWtJL3zUCnVvspETKAMqW9giRSmHvakYYPITsMwOeJ6CEi+jYRvYuITiw6iIjWEtHK+P0iAC8CcBciYvbaeLe3APhB/P7C+DPi7T8XbPDEqAH4MWXIR2Dznhmcc/HdOTtGL2qErJtDyFxkqFLKMpBD0Leru9uOncuUZZGoX49C6ceViZDJXl0u80X1Hm0QUCOZxj2Pv4Oc4KiGfFG/HwjIpBO7HqL+vN+36zdsR6tBeMahK5M2SXaLUpa2e61GyBpBoJErTUMWi/rf+62b8YlYz9eMzzevCZkQ4u+EEC8EcDyAXwB4PyJdWBEOBHA5Ed0K4NcALhVC/AjABwG8j4juR6QR+2K8/xcBrInb3wfg7LIXw2DMBZiOMVSS8/+ufMC5n24MG6Gbl7J0bMoT9RdpyPL2t5GvYf3BUUXUn2cMq1+3W0MW2SjYbyzBLupfVIWQOciiCv+UZf/fgaohk7YXj+6cwtUPRDLtKhqy9Rt24OkHr9AIqzTcLYqQ2ajkkvE0EhlpyNJ9Fo+l5wgoiuhdcNOmZBHFWELI6svICuOwRPRhAKcBWArgJgB/jYiY5UIIcSuAkyztDyLSk5nt0wBeVzxkBmPEwIxsQeIj378dj++exhfefHJpg8+mZ4TMXVw87s9KyOx9uYxhNWG8ZU4eVoSsLNEjpfRP2of7vStC1rVFyOJug8B+T6sUrA5FSjnU7/HRnVO494nIgMC70kJehMzbh0xx0Y/Dpf9w0V0AgB++8zmVNGTbJ9s47sDlWptMfRausrSMu6WsPm429JSluhCGQHhgi762UB5bXzrmt8ry9wF0AVyEyBj2GiHETP4hDMbCAfuQLUx85dqHk/dltUBayjInQlakB3MZw9qPyR8TEEVseqHAFfdsTtqGVTnJq181ZWmLkDlqWYZCoOciGDYNWfJqj5BV09HZj/mdc35eul9twYKxzVfEHmgRMp0sff/mTXjW4ausx+UuAgmF9scF4B8hs426pZCuppGyVEsx2cncwkhZPhPA7wK4HpEO7DYi+uWwB8Zg1AUsIWP4PgJyYvUV9RfprOwaMvu+LlG/+rkXCnzplw/hrPNv8B5DVZQW9cNSOskVIUMUCTPJAuCKkKW+F7ZRlakZqo6n2IfMs6+cJ8ybgJCqIYvtL2LSNNXp5fiQ6Z83bN2H4z5yCTZs3YduT2iRKyCNkBWusjQGvmJRS7NcaQZ6RFT97nMJWY1jZD4py6cBOB3A8xAZwj4Cj5Qlg7FQwHyM4Z+ytETIHISsEdijNUA6wWfJlXCnOY0xpH3p/W7cMWk916DhJ+rXNWTG3O/2IRPRKstmgzKpS1XUL4tXp6J+OyNzpT/zYNpwWPfx9iFzb/PnY25j2HY3zCm2rp/8ezduxFSnh+/fvAndMHRGyMqI+t962hH4u1c+VdveaKQp1oCgkTWbTkySy3kdIQNwDoDlAD4L4DghxAuEEB8d7rAYjPqAI2QMbz2UJULmSlk2ArsnltJNJuUlRJ4PmX2mUifcXpiNxQxPQ1ZuHwJlUpYwyKTa3A2FlgKT+IeL7sKDWyP9kRTrq8aw1qhjpQhZsajfl+wOYmGFLuoPtHG1u6EzUmueuhPfi1YjiCJkDf07mel5piyVw2wLTlpBoJR60vuypjsXgoZMCHFmbFtxmBCiMwtjYjBqBdaQMUqnLLVVlvajmwG5NUZxszlRh0IUasgyPmQKH7SRr1FJWRJZUpaahkxpj7VwJlmQ+P5Nkf3lRKuByXYPchoPHCnLKhEygeKUpS/ZzbtV5YqL66ssJWa67pSl+TzJMTcDsqaF/TVk6XE2fWND8SEzz2H740KmTuu8yrIwQkZErwRwMyKXfhDRiUR04bAHxmCMMnz++mUsHJROWSqTRtcxEVZKWcJDQ+boy3yftA2puHiVyJs52QqDhKnohiITWTH7yUTIHLUsq4j6fYxh/SNkeVt9Rf3KKstGlkT5ashkir0RELq9MHOPE0JWkLJUh20nWKnthRkZtV2xi3zXCT6rLD+GyKbiCgAQQtxMROuGOCYGY+Th82PLWDgoO7GqxcVdqaJGQE4ylKQsjdkyzNGQJcawOWPthSIz+Q/Lqb90ypKyKUtdQ6Yf1wsFWo6lpbJ1ohVon8kxLteKzTwIIZIokLN0UigSHVtuXwMQ9ROlxMfUd11+zxZcfo+9FGE2hR09lP1GyNQ0pe0agoDSUk/GOWxfq9ynxgEyLw1ZRwixy2jjOYjBkOAQGcMTkiypRMEVKWoG5JzIZbN5qBA53mWOSEpRhGx4xrA+KUtF1A/bKkth3VdAFETIolfTgd9Vy7InRFa/Vjj2FN1Q4EWfvhI/uHmTts+Nv9np9fOhfc/GAWVE/fISGkq0rPjc+vmkhqzRCKxp4SXj0T1VjVzt49HHZoO85xkNWV7KssYqMp8I2R1E9AYADSI6BsBfArh6uMNiMEYbwvGesTDhnbKUEbJA1ZDZw2ABkTP9mE6SZUT9tiNM24vscY5MVt/wcuo39sldZamMM1ll6YqQxRYQ48bKPFmSJzPWUKDVoFJpVtX2Yu90F/dt3ot3f/Nm7+P1vgbwK6OI+okiwp9nuZKeXP8oU+ytOELWML6UT/zBCfjejZtwolJOyTocTdRv30emPTMaMsu+jQUSIXsXgKcCmAHwdQC7ALxnmINiMEYdrCFjqLCllP7yGzfhXy+7z7q/OsG0u+4ImSuK5Juy/OiZx+Okw6KJsY7FxVXYjGHV1Y+m7YVtBaBEpysw3gxSguIh6jdXbLrIXjIGo+xTP8i7U/7FxXWtnOkf5oJ6X9c/vAN7prtJf0D2PqxZOo63PffIwnGpkSzXrvL7y2jIbBGy+b7KkogaAC4SQrwAwIdmZ0gMxuhDzyAwI1vosD0CF97yKADgXWcck7TJyU3VkPVcEbKAELoiGHE/Jn+KVlmmn1uNNAWXzmlGVE15H9lemFG3YWnIPFKWqg8ZsvYILrIoEBFTF+mY6vQw3mxokbHoHHYSHAqBVjOIwhIxGkHW40w/Ri2d5NzNC3n3KtG/FRCgSNSfkpZmgwAP3wR56m17Z/AH/3F1pr2qmL7I9gJItW6m5s22uySGQcnU8ighlyILIXoAQiJaMUvjYTBqARb1M1T4PgPJJKY69edoyIoc3s2toaEhUycnt1N/2tCxkMNh+ZCV7dYm6lfTqZkIWZxmtGGq08NEK0iiNHrKMrt/t5ftq0hTJgoij2WQ93uT1jXNP0dEaNMPtgjfsolsjEbe130zvcw2oDhS6ByPusrSsY9MWfqssmwEgXNbXeCjIduLqFzSpQCSap5CiL8c2qgYjBGHJiBmRrbg4b3KMn5VJxjXCr482ws5+WYMS4VOdPRyM/apSteQ2aJDyvtQ4I3/eR3+5PR1OOO4/a39+aK0Dxmyon49ZakcJ+JVlg5R/3S7h1VLxpLZOyVmZCXXPUu0zRXV0cYe79M3IcvZVmaVpZqitS14WLV4LElJmufOmBDHr76pz8x4UPxstlwaMsvuCWGuMSPzIWTfi/9jMBgxOELGUOFLypNVlo1iUX8zCJwO8bLVJDWmMWwQ6OVn1GPTY9L3nV5oMY5NG6Y6PVzz4DZc8+A2bDjnFdax+cLH30y3vchOxCpJ0J36Bbo9gYmWfXae7PRwYCtI5+4CUb9tNWFhYKiA6JaBem3maX1XFaqrLAFYLUGkDYgKeT9MvzzpWzaIlGWRhswkvzYynIj6a8zIfJz6z5+NgTAYdQVryBi+SPVcSsrSESELckonJSlLi4bMFSHzSVl2e5bSScb2QaEoQnbNA9vwlWsfVlooE0lRiY5uEisjZPbJuRcKTLQUDVncHjhSlr1QZKJzRVqlUAhFQza8lKUvtAgZ6TpGifFm1qpCnnvGqHUp/caqR8hSFGnIXGlaFQtllSWDwTDAHIyhwp+UR/v51LLMXWUZt9vSSOoxamrUZQyrEjjbWNT+bBqzqii6ZWd/79bCPnpaylKNkCEufO2e4sabQSaakifqN3VMJkEzUZQKLoNcQqesnMyDnrKEtc6nTRcnzy0Lsku0e6lBbBWo41V7OO7A5cn7saTmpn79tmttKNdWV/ikLBkMhgHWkDFU+Kcso9emh1N/ELh9yNLzZlOWWnpLSwvFETKzD6Wl08vWwlRTlq7yOlVQFDUyN9v4hsvUVtaydEXIgMgUVhIlUiJHtlF1e1lCVkSAhDLmQYr6TVCyT5Gon7Qoki3VaLsk2asZIevEdi1VU5bq7VSjjT9852mpPq1hj+raOGDAETIGY2GCSdj8xM7JNu7fvLfUMUL4lZcXQuAtX7oegBEhc5AcWVz8c5ffj4//6E5tm7OWpdDbVBLhmqfU/bs9kSGIobE9aR9m1MeyPVkgqFyIJupXjWER17I0okB/8YKjkvfjzcCSsrSnia0RsoLZs8jfzRd5pBKo6EMGyhi6Ru1ZyKHPdPUImSTnZSsYqOOxodkIMnYX5r8wGelTT51GyOrLyJyPFBH9kIgudP03m4NkMEYNQnvP7Gy+4Mx//SV+99NXljrGVv/Rhj0zXTy2axqA7tTvmqwbcemkf/rJPfjiLx/StsnzZVKWJiHz0JCpxKEbZotMq+NrK9t2TXmYWOWgOPqnfzbJE6Bfv2nWbBPi//4zD0nej7caGduLaFzZgUWO9MXCcnP8co88v7I8vON5R2XSqGeecKC2jy/9IOg6KxvRIyKc/79P0drkfZ3u2EX9rpWsfiOK4LqXMmVp3r6UkKkp+fkdIftnAJ8C8BCAKQBfiP/bC+CB4Q+NwRhdsFP//MTGHVOlj+kJd0FvFdv2tpP3mg+ZI2XZDNylemSrzRjW9CFTBevRsVkSJ9HtiYxwXyNsPZW89ZuGK0pZmhEyOeGm9073IUvf3/zITjy2azpDFtQJfKJpE/Xbc5Y9ByE75/efjkUtV81Gezq1DKLhpIT/c294Jt52+pEV+yJNQ2bTfhGA5z15LU45YnXSlor69QiZTGEOIkLmIlGtpvwjwhUhSw+UX3WN+ZhbQyaEuBIAiOhTQoiTlU0/JKIbhj4yBqMmYD42/yCE8E4FhaHfM7Btb2rz3vAR9TeCwlqWRRoyqw9ZyQhZKATufHQ3jly7RNvW7+riwgiZ8dkWISsqjG6SDvXjuGLxoGrIbP3YV1kCf3jKYfjBzY/imge3Zccv0n7LpizPe9Oz8PjuaTy+a1orGL94rJF5LtVySHkgqMaw9tJJSRdKV5LAzzgiZJVF/cp7VxdyjObdC5JrVtssjTWDT6xxCREllJyI1gFYMrwhMRijDy1lyYxs3sGr6HKMnpkndGCrGiFT0kUuK4mxHO2QPJ1NQ6bZXtic+s2+lPednsgQsr3TXbz8s7/AO79+k7atXwP/0hoyy3yrr7LM9mGan2YjZPrKPFcty14oMjYXkqC5FnJqhrolfyROOGQl3nzqEckig+RoyyMhI4eFon4yU3w5+yrv5d8L5irL1IesWspSHYtL95VoyMyUpSU9GRjfZR3hcyffC+AKIrqCiK4EcDm4uDhjgUP3BaovI3t42z7smuxPCzQfMd21l4mxIar/WIxt+9IImRqdcFlJ+GhzzMhLxA31lKWEK3Cg+5CFmVTkVDwR/+yuJzSi2m/R8aJFARkNmUxZKlOu3ke2P1Mnpd6DcasxrNv2Ihtty6bNtPEj9SEr698WJOm3SEdo869Lhu7JQMyUpSTrJx22Ep/9o5OS85l9JhEyc5VlfE0DKZ3k6GIsTlm6yLlG6ixtdYOPMewlRHQMgGPjpruFEDN5xzAY8x4qIasvH8Pz/ukKHLRiAlf/zRlzPZSRwnSnh+UTLa99Q09Rv6ohU7mWq3RSHiFLSidZU5bpZ13UL481+0rfd8NshKytTMTqitD+V1nmb3duViNkWsoyu2teuSNdQ5YSFdt32Q2zrv+S7DoJmdJPWfIqx51EyOLjbWcqQz/UKKNKKNcsGdM600hvoiFzGcNWTVkWi/qTlKVx+xoWMqya3tYVhX+CEdFiAO8H8E4hxC0ADiOiM4c+MgZjhFHnqJiJR+OVf4wUpl4mDz0hvJ4HXUOmRsjKE7I8bZkeIUu1RWnK0iRx6fuORdSvTsRtLWVZ/t+A0AhUuQhZShZSuIxhJdQI2d0ff6k2gY+3ggwRcNWyDK2i/ujVJWoXSMmBSl59CEO6GjKy4ZBHFx37jbc9G5987QnO7WotS9U6wuxX+yyAzXum8elL79X2ac9C6aQi2ws93+aR8wAAIABJREFUZRn3VWk0owGflOV/AWgDODX+vAnAPwxtRAxGDaClLOscImNYYepl8mBGpVyYbKd9tjQNmZ38yXSNDYnthZmyRLa4eBJdcdhemClLM0KmEjLV6qJKgEw9dzEhM9JU8lW5LZqo3zIglSxMtBp6LcdGkOmTyP7vuWsT9RelLFUfMqVLc1XmD/7itOy4k7qMEeS1Wc+lpFtPPWoNXn/yodbx6PuqwvhUOGcTy4dC4OvX/SbTVTcR9VcsnWTRf5lIUpbGPxE5zgUXIQNwlBDikwA6ACCEmES9SSiD0TdY1D+/YXou5SEM/Z4BNW2lr7KskLKEPWUpjAiZeh7ZnXk29fR7Zrq454k9yeeA9JTljn1p2rWK2anupp+/byZAZjH+dNWylDDNT0mbwLMrN3NrWTo0ZK6vSUtZKozCJGRLJ7LKIbMuo7xMe8pSEu3i78OmIVMXMtjE9QKwpu/b/RrDKucqipBljrWQr7StvvTEh5C1iWgR4u+MiI4CwBoyxoKG5kM2h+NgDBbSiNL0XMqDb8pSjeDoTv3VU5ZZk1edYOn1Al0TVXrAeVc9qJHRRkDavdipRMiqRIbVIwbi1F8QcWvl2F5EREKf2F21LG2ETH52pyyFNZK5aEwnZLboUBohiyNERpRTRRn+oUbAVIIrxzDWDLTzynOb+jEgLZ1U1RjWRqZMpBoye8pSb6s0jJGCTy3LjwG4BMChRPQ1AKcBeOswB8VgjDo4QjY/0WwQ2r2yETKRYeU2sqLyLk1D5khZ5k50uaJ+e4QsFfW7NWQmiEibjHcqK3KrrLLUU5b++0ZjiV+N/V58/P54Yvc07n0iW/Iqz/YiIMqK+sn+B1ZPZG0vUg2Z/XtStV/qV7w4Q8iyx2YjZEL7rKIMD1H3VW07Tlm3Gm87fR3Oes6RmfMIAeyYbMNE3xEylZA59klXWertSbRXaZffbb+LTeYSPqssf0pE6wE8G9F9e7cQYuvQR8ZgjDDmg+1FvwWP5yMiEtQrpSGz2V7Ybq0zQub4HiZaeSlL/TVpFzpJsxnDZsfqfg4aBiHbrWrIKtQZLzJyVeHWkOnT95LxJhaNNQpF/YCFkCV9pn3bhhWGFtsLGSFzsIlQ2FfDLhrTp127lYWhIctJWZZBqrMiJWUZvf/QK463HiOE0FLVEmnppP5Tli4NmUvUrz4D3/2zU3HzI7uwKyaNdf5Z81lleZkQYpsQ4iIhxI+EEFuJ6LLZGByDMapQfyDqGiFzOcQvZMjJpZQPmaHbAtxu7xI+UQV3SZ60f1uETG1SU1PJpJeJ5rnHkNGQKZGSquWA0vMWETJ7u3nnosSjnUiZ95kCdZsu5lf7NsdmE/WnESZHylKkvxIq6V5kEG3X8eq2RNRvK3dURjulpQn14219AtHjsmOyg2MPWIaXPHX/pL3dZ+mkwDIWE82CWpYA8KzDV+Os56xLxtzvczmXyCsuPkFEqwHsR0SriGh1/N8RAA6erQEyGCMJYX1bK3CELAupWSmbsjTnANu9VVN8Pt5NptZIhezK5NRRmiw9j80WIGt7oX8+7sDl6TGBkbLUVlkOOWVpfCaTNSUb5P7ZDs37rH6KImSkbXEWYLdoyCZiwmwSNXX86fekErLilKUJ+TzZdi2nIUtToaqoP9On8j4UAjsn21i9ZExbKdwZ6CpL+z5SA5hx6rek39Pvrr6/a3kpyz9F5Mh/EID1SL+j3QD+bcjjYjDqg5r+AJQpD7RQIIsZlxX1m+TClfZK4DGJTjRzCFlyHv1EQugkzYyW+eDQVYuwde8MtuyZQSMgtJV7odpeVCH0KmmqmrI0QaC4BmV2m6nvcmrIjNdQCCg+/lGELEPIgvgcPhGy9EtZ7JGylJCbJJm3RrOU8xUhpZ+qD5ktQpa+FwLYPtnGcQcsx2O7ppL2xKm/YspS/UZdC07Seysc7SmC5LurOJwRgJPaCiH+RQixDsBfCyGOFEKsi/97hhCCCRljQUM43tcJCzlCJoTAR75/O276zQ6tXWpWykTIIg2ZR8rS+Gv+fS96cm6/EzkRMtn/o7um8f5v36K1u4iOy4fM3H/5ohauev8LcNvHXoyACA9s2ZdsU8tsVXl89FWR+ftmNscTbtbMFc6i4K5yR0A0qWcMUZVzP7J9MtEShiJLyOSKRDchQ3KzVZI8YUTI8oiyaWlhFfVXjJCpxrDZ86bohQI7JztYubiFfTMpOZcltQazyjJ/vDYDX1d/8zJlqSAkopXyQ5y+/PMhjonBGHnoxrBzN45+4DIkXQiY6vTwlWsfxus/f43WPpYQshLGsBYfsiINGQH4yzOOwX5Lx539TjTzVlmmb7+9fqN2XhfRcaXj5Gc5MS+faGHRWAPLJlrYboi5+09ZCut7G7K2FymZ0NtLaMjUNFmQpixJaZPnPv2Tl+PtX1kPwB4hk89KnlO/HJJKxheNuaN2Jnx8yMogrZFpGMPmICJkbaxaPIZ97W7Svn1fGxOtAMstPmo+UM/qGsPKxS382fOPwlf/5Le19jT9nu2jzn9n+hCytwkhdsoPQogdAN42vCExGKMPTdRf0xiZa3XfQoAkR2baVk6OM2VWWRaQLwmVYFBOdEIiV0OW0+4iOrZJLBpX9CqJxfJF7glWK1VUKWWpnrecqN8pIaM8Ubg7QqbYkGWOl7q5q+7dAiC6bpM4yQhZXi1LeY3qfSuVsoxf5fH2fSVR9aFreoQw6tOyl9LXzqkOQgGsWjKGM459krbfgSsWVTZizXwXttES4YMvPRZP3n+Z/ViRbavr7zHgR8gapNxxImoAGBvekBiM0cd8iJAtpJTl5698AD+94/Hks+va5QQ6UyJ62Auzqyxt+jz1nLYSNSbM1JY2Tsf4hSVClkR/HKJn+VmO2beoeiUfMuW2Fi3yzRAy+Wqmr3LiRq76k0Akxlc1VdH26HWqrRNym+1FqyBCpq54Vb97M/KZR8oTb62BpSzTY/KKo6stsgbrqsUtfOTM43Hd356RbDtg+YT/yc1zeKQsXbCvNo1e6/p7DPgRsksAfIuIziCiMwB8I25jMBYs1H/znV6ITTunrPtNtrt4zzdvwta9o1fcwmVIOh/xjxffnaSfAHd0MImcdf1/1UOR/ZvcGiFTbrecPPKiI2OGNsenOkQo9MiTj6jfnMD2W+ZOo+Yd53VMGVG/Z6RDtfYw4ao/CcQpS0VTpb7um+lqx1lTlkUaMsBKyEzNVV6EydRF2chnonvzEfUnUUay1oM094vOHb2uWjyGZiPAk5Tn48AVfRAyDx8yF2y3PBH11/gPTR9C9kEAlwP4s/i/ywB8YJiDYjBGHeqP3xd+8RBOO+fnmR9xAPjujZvw/ZsfxbmX3jubw/PCQoqQmXCVK+ol0aJyETKTXNiO133f3NEJCXOiV78u19wbKia1px29BscflFpYuIxhTeJz8MpF1r6XjeuptkqrLEtEljORvryUpaOPjN7MGSHTXyfNCJnFqb8oZQmFqKvPR8uIkPn4eMnHyR4h8yczmu2FQUaNXjMtKxe3Muc7oB9C1ocgzl46yf581wmFhEwIEQL4bwAfEkK8VgjxeSGEv8CCwZiHsE0me6azhGyUsZBtL1ymuKm2bBg+ZOl7H+8pM5Ki6bccbEbVkH381U9zlE7SjzGHqhKyi999evJ++SI9lVlJ1F/i+KzthYtAZFdLpucw9tQiZFlz1CRl2TEJWfY7G4+/H5ennPpdqN9dduWnfezquGTUpx8SA9iF9L71MVcvySqVzGeiKqpGyOyi/vr+rvk49b8KwM2I05REdCIRXTjsgTEYdUPbUoB3lFE1QnbVvVvwH1c8MODRzC6cETKH2D8PPUvK0kb41FRKQgByfoGzEbLiMam2F+Ykl34WmWNUuFJSgyBk6jFFi0pcETIzepMXIcsboywZZDuHGu2e7vSi4uIuUb9LQ6ZcgHyujjtwOY5cuyQzDhcSUX98HbZomktbZ+1PIWG+xrASKxdnCZnLFNcH6n0rrSGzRsii1xrzMa+U5d8BOAXATgAQQtwMYF3RQUR0KBFdTkR3EtEdRPTuuH01EV1KRPfFr6vidiKizxLR/UR0KxE9s/plMRjDhe0ffbtXr8Bx1dJJb/7S9fjEJXcPeDSzCxcZCCtEyHqWCFmRqN8Uk9tg1gjUtWEuUX+qVcsSsnQf8xhtP2WiVBcWrDQJWYXHRz1XWdsVU+eVtMNNRvI4XyMgtGJGbEbKVFG/tP5wpSx9nPp7SdTyqRmz2lwfsnibfF5t56riQyYUX7UiDZmEWRQdqF42CdBJX/kIWXodZludI2Q+BiIdIcQu44H3ueIugL8SQtxIRMsArCeiSwH8MYDLhBDnENHZAM5GpFN7GYBj4v9+G8B/xK8MxsjBJjhu24TgI/zjsFBsL6zpw1AnN/L3rVuBkEVfsX4OWwQutEweefOZOdnpKUv3WJwr8pz2DNH+Hz3z+IxNhLqwYEVMyMabAWa6YbVVlsp9Kv/8kfL/SmtOhCxP6B4QZa5XftqnEDLpSZexvUhWWbrOnV6vfB6IKPOd55ERua0XP492p/4sOXFBXYnoIrgu2FKzfREy5dCyvdgiy6lTf31/13wI2R1E9AZE9hfHAPhLAFcXHSSEeAzAY/H7PUR0F6IamK8G8Px4t/MBXIGIkL0awJdF9FRdS0QriejAuB8GY6Rgj5DVK2XpStupuH/zHnzxlw+h2xP48JnHJ5NynWBLJauEa+9MF8tiqwf5Y95vhMwWfdQiZPHkkTcZmzUCNVG/429i1WrBWfTa8fnVJx6ENYZRrdqH/O5XLR7D47unK9UMVA8p++/FHSFza8jy0vIBUaLTS20vom1TigHqjKOI9lhc2irvPsvrVUmyO5WcRSZClmP34AO1nmlSHD2H5KnH2chgXmH0IqjRvrJeZjYB/0Ixhn0XgKcCmEFkebEbUY1Lb8QFyU8CcB2A/RWS9TgAWT7+YACPKIdtBBcxZ4wobP/my7i7jwJ8UpZv//J6fOP6R/Dt9Rvxhase1LbVpYivjZCpE7WanpLt7ZIaMvOvclv0xxpRiuchcwUjkDU1DbWonn0sqoYsE0lyHJsKxvMnxRXxKju52q7K3x/quctYi6gwyUI07Iopy4bUVMm+ojdqhEwSMpcxrFPUr2gLVWNX8zbnivqN4/vRbAE6acktnWS0uQqID0pDVpbX5a6yrMnvkg0+qywnhRAfEkL8lhDi5Pj9tO8JiGgpgO8CeI8QYrfRt0DJVapE9HYiuoGIbtiyZUuZQxmMoSKPkPW7OmoY8EkZqeM2CUJdUp62SIxKRmcUwpb6kJVfZbnf0jH8xQuOio63nFMlVGaNvmWW8jPmRK8SuryUpdxkq/kIZKNr6f72PiUkaVwav1ZbZZkeU9YHL9HdWTVk9mPyRf1AM4mQ6X2rJL2dEDL9+HEPp35JDtKFFn51GZWNANJ/a3mLQPxE/enYco1hjSZXarJiGcvo2AFEyFTIporS2JGAM2VJRD9EDlkSQryqqHMiaiEiY18TQnwvbn5CpiKJ6EAAm+P2TQAOVQ4/JG4zz3segPMA4OSTT67HjMCYd7D9FVamIPUowCdlKdMy0Xv917fdDSsXFp5NqITsHy++C6995iHatVsJWZmUZRwJGWsEOHTVYgD6vZUaNZVQpSnL6HXpRBPYpffbbJgpS/X7coj6IbTJX0WqNdLb0zqJ+ZOiLOUkn4NqtSzT96UJmYxiZdrtIz945SK88oSD8IHv3GrtLwiUlKURIVNtL2a60XuVlJyybjVedPz+mXYVasn5rhIhKyNgl3uGyvGZfUpwGXmnQiEKInP6Rtc1lhXju44tHyFzt81XDdk/99NxXG7piwDuEkJ8Wtl0IYC3ADgnfv2B0v5OIvomIjH/LtaPMUYVtn/y8oe7Luh5/CmpkjDTOb7dDbHEz9R9TqGmLD9/5YP40S2P4Z9ee0LSpn5vVY1hI5E0JVEHU4DfILtTv5z4llnKFZkRMvV4tzGsQrASi4P88cs/LqiAW8v+JInp1/aitIbMUbORyH6N//aGk3LrgTaI0Eq+r6hN3vK9iu3FTCebsvzXPzopWYHqLp2E5Ieil6SFy5EPLw1ZCUm8WToKcDxL3hGyflKWyulKdkOWsbuMj+sEJyETQlzZZ9+nAXgTgNuI6Oa47W8REbH/IaKzADwM4PXxth8DeDmA+wFMAnhrn+dnMIYG24/YTN0iZB4px3GFhI0bEbK6lF4yNWShEOgo165ul6SnjIYsKp2kRzDUe9OLy+70LClLOREttWnIclOWeaJ+e4RMIiPqTyJk+ZBRGknSXV//+oe344YNO/Cnzzsqe+4BRMgy7fH/TBSRhWiVpbyWaCySbKomzzOWlKU6ltyUZfw+0emBSgnhZd8yxZ4XIfPRTiXWEGG28oDWp/F5GIRMPbZ8yjJ6VVPg89r2gohug51sEiL51wmWbQmEEL+E+9/4GWZDrCf7i7w+GYzRgSVlWTJCduNvduDXD223TlyzAZ+U5XhLiZAZhGymJka4JiGLyJFdQyYnvnIRMgCxjYDkr90wS560lKV8zdGQZYxhPUT9Au70lmviNsmkC12DkLkmvj/4j2sAoPC5Livqd2rIHBGyQkIWpF5vkqDLKPCuqU6yny1lqeqfclOWxncfBPb7/OFXHIeJVgMf/v7t+rXFr4NaZZnorATQTCJKPkTO1T6YlGXZXmz3YT4Yw+alLM+ctVEwGDWD7R+9TdSf99vw+/8eucfMGSHziJCpaUrT0PLvLrwD573pWRmt06jBNOxtBqQZt0pCJoRI0n2lSydB1wepxyfWB1bbi+jVRsjMqIFmDOsYi3oNGULmGn+S4nTsEOPoJy0FAJxw8ApcdOtjlYo4q9dQPkJmT8GSpQ0oJmQNRUMmTWol2VSd+uXzoZVd8iFkWoQsPc62+5+cfiQAZAmZJFAJyXZfTxmn/lCIXEF+tq/hRsiqGsPa2uocIXN+JUKIh+V/AKYBPD3+bypuYzAWLGz/5Osn6i+nITMn4J/fvRnrH94x8HENGmYkLzDShzKCpl5emVWW0vZC9ZhSo489W4Qss8qy2N/Np5ZlKJRtlkgS4HbqL5oUX3T8/vjJe56L15x0cHKusujHh0zCZnthS1m67CgkVGNY+ceJJGi2VZYuAuF06lc84dKUYznyIa8rXWXZn4ZM7in/gIjG6d5vzFj0YKKfCJm+yrLcsbb91ehfXeFTy/L1AK4H8DpEeq/riOi1wx4YgzHK8I2Q+fU1N78grghZLxTYORmVi1EJWTcUGVImy8qMMswyRs2AtGuXKSnVCqOMhuz8qzfg2ge3gaA4q9tSlpbSSTJdtKjlFp+n/SgfXClLpV3O3UUTttPZ34KnHLAs2a+aU38Kn5S5DdmUJVkDOEVkQTWGlWORz/u0bZWlSiCUmTM/Qhb1m353bhNbK+S9HnDpJAhhNVeVkG1m+S4T/Yn6+4+Q6c97/SNkPk79HwLwW0KIzQBARGsB/AzAd4Y5MAZjlGHTXeRpqvImxW4oCn/4hgGXi/n/d9Fd+NKvHsKd/+clWsqyF4aZqMbWGhAyU0MWEGnRQbkYQ13FWCaddvfjewAA6/ZbkqSBOkpnksTaiovLsU14EbLilGVecfH0WENDlhjJ2vf/59c9A7/Zti/5nK7Oq0DI+kpZxq9mu6UN8E1Z6gRaflYJWTtJWabHapYNHk796XFlI2QR8ldZxucrUTopMoaVx2X3k89QqxkA7Z7z12tQaoVBaMjKLG4YVfgQskCSsRjb4Ofwz2DMWwwyQtbpzY2fl2tCvOT2yG3mwpsfxQU3pVaA3VBkrvHRnVPDG+CAYBKyZkOPkEmS2euDLABSy5RNWcpT2UT9KSEr/v79UpZ5GjJ7iipNWdrP+9pnHaJ9tkUBfaEeUtX2wkSzQVb9VPEqy9SBXkZH5UriqU4viaTaSifZ7CNMRMaw5jnL+ZCltSzdUcxyEbJ4bEiLi9v+uJSkxvRpc42vX5RdZZmQL8tYaszHvIjVJUT0EyL6YyL6YwAXAbh4uMNiMEYbdkJWTRNjptRmC+qE2gsF9kxHK8uknuns792mEZdeKDLXuGlHDQiZIepvBIFuDBuTTDnpjTeDauk0SidnldBJ8qRG4JK2+DSulOUVf/18/PPrnqEdA+SsshTZFKSccF0aMtO3rAgyIlRNqzOACJkxTmdZHw8NmZmylJ+nO2FCzuyEzE7OVNhIs0vU70LGhyznOyon6s+vQymfVdN70EQ/KUt9XOX2t4v6o9c6pyx9Sie9H8DnAZwQ/3eeEOIDwx4YgzHKsP1VaZtgfH4b5srPSyVbH/7+7Xj6x36Kbi/EknE7OehZImSqPcCoImN7QbDaXsgI1qKxBtq9sHTqg5CaXZ576b1Ju0xV2kofnXb0GgDATsd9PGK/JUlRb80Y1jGGyGoheu8q0WMem9peODo1kEx8BYzMdv90H7Ly91d9lWg17LGzMilL09JjqtPDeEyS2wWrLF1EKEpZ6tcYWXSUSFkmGjJ7gfN4L+/+VJ1VYAszxeglETKKz2A/R7+1Nc1xld5fGfu8Li5OREcT0WkAIIT4nhDifUKI9wHYQkRzs06fwRgRuHQXYSg0l28fzBkh66UT8XfXb4zaQoGljhV/3VBkvNbq8Ntn8yFTyYDcLiOGE3G5qLK1OtV0lFqcOhTRxKxGJOVE/f6XHIvfPe5JeOlTD3D2K4MUoUboHCnL0M8iQTumZISsEaSTeh5sKU1tJWvOc28je2mETG9vNgK77UXB9TQC1Rg2JmQWI2SbqF+9t877LLJ/tkUrcXOHpe+vrLJ0kbkqPmRC5N8f75TlHEXIbIG704/ZD88+cjXOftmxAxnTXCAvQvYZALst7bvibQwGQ4EQwD//9B487e9+gt3T/pGjqqvN+oXUzahnv+Kezbjq3i3W/XuhyFQjqIOANmN7QbrtxUxiexETsljPVSWlZvtLv6fouiTk59VLxvCfb/ktHLHfEm37kcpnOQlrqxodt13VkCW+XUZ0I/OdxZYdvghs47GOJdumUhSTKKuw9Z36kJkpS3v8Rk1l7rd0zNKfYgzb0536AYWQdWR0Kj1WT1mWEfVTqTRfGiETzvOUEvUr++YEyJLvrkjbWmQt4ouy3diI6eKxJr759lNx1NqlAxnTXCBP1L+/EOI2s1EIcRsRHTG0ETEYNUUoBL4fi+B3T3Ww3MNbCqjux1QGU+0eWg3STFz3zUR/+avL89/x1Rszxx7zpKW4b/Neq6i/DnqNjO2FIuoPSLW9kIQsipB1ugLIzuNOuCbbMBSZaFGeIP7yv34+Vi9JTywjGZpTv7O4ePqdZIuLp/to4xPlVrn5iqdtz4ZsiqKUOYSsRHRyrBlYJ2jJx658//OTtK+KhqohC1P9oMR4HCmd6WVTlurpXGRWLamVjKlA1H/mCQfilc84KNPeC4UzolUmBap+d+l7WyQzjpDF98N1hkFFyMqusxzUYoJRQx4hW5mzbdGgB8Jg1Al5S8WBcj+SsxEhO+6jl+DlTz8A//7GZyVtqht53vzXCAjNuNzQtFkXsgZeuCYxiET90cCXjDVTY1iDkJUlyssnWtbVkqrQ3jUmFeuMaFmaIlSOdwxNKGkyWxHuaCfjGIiSk3r0WkSa8gjZeDPI1ZDZjnVpyJpBkKshO3zNEsvW9LkGssawQFo2LImQOXRjubUsMxGy/PTcv73hmcb+6fgcaxesY3LvE72GIn8c8qsdK/IhG5iGrNr+PmWf6oS8r/gGInqb2UhEfwJg/fCGxGCMPmw/BHnzU97v1mxpyH582+Pa573tlJDlTa7NRhT5qWuEzIwANCidgBeNNVJRf0LIqqUsVy5uWf3EeiIbIbNFbFwgCwFyTURSr2ab4MxVl8n4wnITq6+GzPZIyWPGmkFupQjr4+jUkJE1wFKUGiSi1PbCKJ0ExKlQstey1Pux9y+QjUZSSdsLdZWlM0Lm3Zu6sKMgZWkscnCRvcGtsqwWIavBz08p5EXI3gPgAiJ6I1ICdjKiIP7vDXtgDMYow/ZDUFVP1U/KstsL0RMiSa/Y4CJb+zwXHzQojpD1soSsDj+I5uU3ggDdMEQjIEy0UkKWrrSLRf0lI5crFrWs9hWhEIkm6gMvfQqee8xaHLp6sXe/ScrSw/ZCGsPaJn3XSjkhiqMvWj+WFKoNeSR/rBHkVkOwHSvHb15HtMoye21+on7SztfSarcSWkFgNYZV4SJYoVI6KbkGh87QBXldvTB0a8gszb/4wAsw2e7hJZ+5yhhr9CpEvll1QpwLNGSDSh2Wj5DNz5RlXi3LJ4QQvwPg7wFsiP/7eyHEqUKIx13HMRgLAXlCWKAcOXNN/EIIfPay+3LNV//oC9fiKR++JLd/l3jal5AJIImQZUT9NUgZ2CI53TAyxhxvBrjuwW349g2PKJNQGkUog0VjDSwasxAypeTURLOBpx28olS/toiUa2RRejR/wsr6kLkF43ljKpJ55dlejLeC3Aik7VjnKsvAscqyyPaCbClLPRXZbJDVh8w2rgxE8n9an1V8yHqhcOq1UsPf9FyHrl6MtcvGM/vaygvlOvXPkg9ZaduLeWpN7+NDdrkQ4l/j/34+G4NiMEYdeUJYAFj/8A58d/1GL2Lmmpge3jaJT196L/7sq+udVQB+vaG4uLeLkO2d8assEIqIvPRCkaRvvnLWKTjx0JW18PzJrnAU6PUEWgFhvBXg0V3TeP93bk2iJDKNVXRt5hwy0Wo4ImRKLcKcCezqs1+Iq89+oeU8ehQHcBN+IdJC52kHxj6W8ZX3gaq2ylKNvOTaXliOdY3Q5UNWlAYjSr+PriLcl2k6qTGThCwgwpP3z67gK7fKsqQPWfzaC0V5Qpizr/qM2FOW0WurWUTI/M89SOTV4awz5inPZDCGi6II2bu/eTP+6tu3ePXlSlnKCeuWjbtw7EcuwfqHi8mXDTNdO/GabPtFyMJQpvmzuYuWAAAgAElEQVRSp/4TD12JZRPNWmrIurFXXCOgxHMMQHJ/D10drVkqe23jzcCqIVNTlnmr0g5auQgHrcyul7JGyJwpyzgdlachsxDUshmggKiSD5lsGWs2Sq+yTCNk+mDNCNlfv/jJOP2Y/XLHBkjCpa+yBNI0XSOIyJn89xMQ4dt/+jv4yXueq4/L0b+6wCK9hupO/UWkObOIw7ZPMjZ9nCbMlGXZdG1ZVDaGnWfwqWXJYDAMDFJD5kpZ7jFSijds2I5nHb6qsL+pdk9LnbmKnpdJWTYDQqiI+idajXhS9upiTmESh1s37sRV90Y+cep9+uEtj+LYA5bh6YdEC8zLfp8TrYZmmyDRC0UScaiyKi11xk/b3CnLKD2am7LMFBevNiFWc+pPxeKdnoj9sLLnzrv35t6tZqDpoc484SC884XH5I4NiFOWhoZMjg0zccoyCBQfMsKKxS2sWKwvyHBFvOQCCxWli4sr0dGy0Sg7KU8jS67KDYCasizW4Q0C5f8gGMhpRw4cIWMwKiH7M5YnYs77/XBFCvZO64TJhx587vL7cdxHL8HOyXbS5iJke2e6WGzRPJkQccpSOvVHJWcCBFQPY1jza9k5mZr2qhGtJ3ZP4+gnLVVE9Pn9mpd+1NolDnKRpveqpHhsRqzu4uLRc2IV9eeIz8tOcD4aMltKM4mQGSWLfI5NRP3GWFvxakh1bD4gSo1NVQsOSUKk6F9GsF3dutqFGMAqy/i128sxhnV0Z0vkplFSkfubZBrDcoRsdsCEjMGogCIfsjJwEjIjgpXXvYxW/NNP7gEAbFIWAtg0ZN1eiOlO6G1e22zEPmRK0WXySFuNAvLGqBKybXvbWDbRrFSk+LfXrcZLHOWPekIo5YzKTyRJylLTkNn3lass1dP8zcuOxVFrl+CEeDHBIET9RD4+ZNk2NUIGuKPDVg2ZS9RvlE7yJ2SpUXJXCT/Kscni47L4vCvd7GpX64om+1I5QboaISv97Fh2t9pF5HxPsyXqr5IyB+rxB2EZMCFjMCqgSENWBi6DzAwhy6Sa0s/tXqgV+t6+L4qQXX7PZlx21xNJu3wvay0uX1SsWgiVCNlMt5eQmIDqYQzrCi2+6hkHYZFi5LpnpotlEy3F1iGnS2MiePaRa3IjUD6ifhfSlXHK+XP2N1OQJx22Cpf91fOxOC4abxP1l/WBagRUOBnaUpryEDnRdxw32VrLMnk1NGQNgso+ytzjFYtaOOGQFfjU656RtLUSDRk0UX9ZHzBhTVlWjJDFNi39QvZQpBtMjGETp377zoNbZVlu/7wFCXUGEzIGY0CwiXh9ICNk312/EXc8uitpz6Qsjc6nlJWX7V6IB7fsTT5v2xsRsrf+16/xqUvvTdrPOv8GAKl+bJlHhCwU0cS0cccUvnrtbzChRMjq8IPoinSd+79OzIjwl437RciykY8czZYi6q8ygckghZrGc5Gh1Icsuy2ZVEWW2FfxgSpeZelOWSYli5wRMneILJuyrBYhk/te+M7n4Izj9k/aVFF/sxEoKUtXytARIbOK+stqyKLXvFWWRceqsJN7t6hfpm+HnbIsWzppUERw1MCifgajAuwpy2p9/ezOJ3DAiolkVeaGc14BIBshM7FHIWztbogHt+xLPm/dO5NzXCc5dtXiYkImhECj0cDNj+wEADy6axoAaqshAyLi1QgoY1OxdKLp5QJubsqbH3oh+kpZ2tIzeassncawjqhClXSYz4IOq+2F4QDvcuvPs70wR9o0bC/6LeeT2l4EaDUoudeuVKPrdCL5vxQBEQT5/5tJCJmIbFrKwLa3ZnuRawwbvc6eD1nZ/ZmQMRiMGEU+ZMl+Hn1ddvdmXHb35ky7uQrSPOduJUXZ7oZ4aOu+xC9s2742XLh90+7kh3Tl4uLq2XKVpQkf64NRgG2My+PSReNmhGyilUy8+REyIxWVM6OEfUbIElG/V+kk4axT6DpzKMqPK0pX9xEhk2J6Rx/WWpZkvon7ahii/oKVgUWQz3qDss79Nqxy/Bv68jUPa6WYgOg7KOcbFi9+6AlMNMtGyGykPMvKrX9cGpULXGceVC3L8qWTBnLakQOnLBmMCvDVkPXDV0zbCzOYsHtaJ2Rb9sxgzZIxHLB8Alv3uCNkj+yYTMicT4QMjgm7LrYXtu9A1pI0I2TLJpqphiyPkJU4fximGrJ+RP0qIXPp23o5VhISg/Ahi1ZZ9q8hc0bISqxYbjV024t+SYIU+gdGBNX13a3bbwn+509PtW4zF9QEZC/z5EKqIauQsrS0BQofc/nSASVKJw2IQZTXkBVHsesIJmQMRgX4+pC5fi/MCWfNkv+/vTMPk6Oq+v/39jb7klmSQPYNAgGyEJKwBlnDvgkYFBEQ3EUFX9GfIIi+8iqKIgoCIossAiKgIiAhLAkQkkDIRvaF7JNlMpm1t7q/P6pu1a2tu6q6Z7pn5nyeZ57prr5Vdauruu63zjn3HPtTtjWGzJrgdU+bYQVLpBUkFQXRcAgNVTE0ZRBk8WRaF3NeLGSKS2wcY72juLhTH2s1IWrNG6bGkNnjbKz4iSFTuCGgAlnIQvbBx81ClkgrWlC//TNjELPGkAVLO5CtBKvjA4rWb5EB3m1Ci9O6bikYgs6ydENPe8GYXmgeyPwdTRtV52nbjKnbP3RQlcf2hhjPdo6s59Wp+aDqUgDAiPryLGkvzK5lN/I2y5JiyACQICOIQGQKhDW105ZZLRbW2WVy3TnxVG2NIeuy1JHcLYmuREpBWuGIhhnGDazCJzsOuPa9K6lIFjJvLkunJLKMsV7xhOrostQmM1jv61WlUSmbeSYLmXX2nPH6u6cdYtt/bnnI1P/moH7ntomUgkRK0TPQy+jHZVkeJA9ZKJQ9ftAxU7+YveeQbiLbusKqabOQhSwxZDkLMiOov8RkIctpswDU3wxjDK9+96TsjWEc6772RF6sUcePbcBfr52Ob35mrL7M6V5mtWS6WVwpMWx+IUFGEEFwjLtwdgc5YZ1dJifIXLRpH57+4FO9vI/g4fkb8dA7G/T3siCLpxSk0qpb48ghNWhqjWPXgS7HfXcl0zjgI6hf4dwkyL5zmpoFPdRrLGT2ZRUlzuGzVaW5W8huOG0cKqSEu2meo8vSKYbMpW/xlIK2eApVpfbjc3NRBatl6TzLUhZpzg8o6v/secjc4/6sqBayPLosQ84uy6DiI5fumCx/WTZkL53k3P6EcQ0mq2Iml6U+y9Jln/mLIfPbvm8qMhJkBBEA5xgy9wHIijVDuRxLc8VDC3Dz88uwZV8HGirNFqzH39+sv5ZnUibTClKay/IILQHoyu3OVrKuVBotnUmUx8IodcjUf1BNKWZPG2Y6BuE+ffhLU/EdzQIU6iUWMiES6itimDFadS1VuOTkqi2PGnE2PtJeWMcHefDmnOvbys1lmT2oP5FW0J5IOQpOtwE6UAyZS/xgNtGouyyzZOp3WrdaE5m2WpZSED9jmSdYeCGIyzLj9nIwbcnnzO9PLXt3met2e36WJQX1AyTICCIQmZ4qZdxyNQkBdtHkIZh5SKNjNv0dLV1oqCwxLZNvgFaXpbCQCREnJ4qVES7LmrIoKh0G7mNH16MiZiznHGjTCpHXSFaKXhNDpgCDqkuw+JbTMaqhEoC5hqVMTZmUGDaThcwyjFlFgjyQpRVjW7mkvfBiIUukFLR1pRzPq76u9X3ATP1OgfeywHK69vWEo2H1+3cL6ndaV1x74wZWmpbLecicZgP7JSK5LOXi80GFXiSHWZ/yLt3i7YKSOTGs5QHCpW2+LFVBJpX0RUiQEUQAnGPI7O3cZouJgWvqyAEYVF1iqjcpu7usgkwecHa3xXWrQSKlIKlwRMIhlGtiqrXLTZCpQf3VpVHHWpYhS21A1cKjvpYFWW+xkDnl5SqPatYWS1u11qD62o+FzDo+CCul2L8QU0HGL91lKe3TTQgLl6WjIHM5LkXxLxTdZlmaZoJqn7+4ZBvW7mo17TuqpXBwD+p3d1nedv4EPH7tNH25LHjykZ9KpOQIMWYS7kHdczmJRJMgyzyLwktQv/N69mXivtVTwodqWaqQICOIAHi1kLkNOOLmGg2FEA6FTBYyeR27hcz4ye7vSGJwjTprKpFWkFYUREJML5EjF9GW6Uoq6EikUV4SNlnCBCFmfvKVj6CmLGZq1xssZBzGDVx8z8JleYZD/UlhCclsIbOsYxkg7r1iMn5y3uHqdhTJZRlgIGHaKTe7LJ0H3EQq7SrI3HYdxGWpzrJ0sJBJ1y7nHMm0ghueXoLz7p2n9xsw3HizH3wfx/z8ddt2nMSwmIhRGg3jxHGN+vJIyEglkQ8LmVw6Sa7kENTzmM3tlwnZZelmTQzKtJF1qIiF8bWTR9s+ExZKcV13t/zxu/0+qsdIkBHFw962OJ5c8Gmhu+EJp7HaSZu4FWCWaxvK9fIA6KVaAKChyhxDJt/b2+MpfZZkIqUgmeaqINMGkf1uLstUGomUGm8mxJt5H+a7nSy6rBay3iDIZMEhUocIy8fBtWVY+dMzTe29lU5yn2UJqLM1jxvToG1HGuCClE5ycVk6ibtESkF7PO0SQ2asKxOkuHiIMby2chdG3vxv03J51mRaAbY2q0Xu9RnCemySs+tdXteK00QFQMxc1PqVF5cl07clp0UJapVxc1mecfggXDljRMZ15V1mc1n6dR8OqIhhxU9n4egR9pQdhos92Lb94j8xbN9UZCTIiKLhW099hB/9YxnWSzUZixW3TP1WV6ZbDJm4uUbCDJEwM4kwmUaLhawjbuQi60ik9XxaIu2Fur0QYuEQmjucs/XHk2mkFI5YOORiSbG6LI3Xcl4i1osSw1otZLKrtkSLEzpkkBqbFCgxrMMAIcSzyJ4P5JgYlputT07iY+7q3ZqFzC603Yuf+7f+yKJdfoiyuiw3WH7LRn4r5xg+azsZa91RGdGbvFrIcnBZnj/xYF10ulnIHvjiVNxx4REZtyPv0S1FSHeQyySUIPjdTb5mdxYbVDqJKBpEQexssRLFitMg4hq0LJUmyTSI1Fim+gurF+cc7YkUajUXYjytIJVWENEEVnlJGC0ZXJbJtIKq0ogpaFkQtmQTdxNdjPWWWpZGnq24LsiMW184xPDUdTNw6GA1WaenWpZZYsgAs7BTdBeQ//47pSfgyDwoVbpYk9R1LTFknPse4GQx+KN/LMMxIwdg3KAqU1C/onAs29Zi3reDhcyJbGWZAHVGrHDLC+HgRUC88z+fcZ3wAkilk3II6j9qaA3W7GrFqp2tubkspfPiN6g/FyuS+PrFA9vYxsoMrXPHr4Wsj+oxEmRE8eA2lb8YcZwq7qC93Kb1i6fdEGP6rC4nZOHwmUMb8daa3VAUrmdkr61QBdtf5m1EWSysD3Tl0bDJQlZXEcMvLzkKD8/fiK5kWnNvhnS3jOwytQ5q4wZW4oVvHKcLZoEaQ+ba9aJBzrMlXJbWyQzHjqnXX3txWToVjbYSlgVZN+QhyyTk/bks/Q+IVj0lrnO5j3vbE7jvzfX6+45ESv/asmWAt15XL3zjeFubV79zErY2dwAwJ3PNxrC6cgzL8LmohRlizBxD5uMrYozp11guVjvzLEt/D6rRcAhPXjcdVzy4wPd+xbU/vL4cj14zDUePGOB7G34IUjqpsaoEN5w6rns6VCDIZUkQQXAYq52sRWKAcprZBqg360w37ETacFFOH10PhasxYCJRq4gh27CnHbsOdOkDUnlJxBRDVl0awWmHD0JpNIyuVBrJtIKYNtPNWj6IMeMGOWN0He6/8mgMHVCOicNqTe3UWZbFr8jMMWTqF2+tYSnjKTFshkz91u3IaS+CuIDEOrJAVFxclgJrVQdAsrRZlvMAmfqtxyGOVX4A2XWgC/GUghPHqbF0339uKa57bBGA7DUSrWJ4kuXaA9QyQCL+KRcrlBUhgMMhhrJY9uLiTjAYD1OZHriybkfapVsS3UyIOEa/6LMsGcPMQxozplHJB35LJwHAwv93Gr6QJQavt0GCjCAC4DXthRigrJ8JC1k4zBzL3IyoLwcAVJZEcdTQGnz95DG6cEsrHB0JVajVSTUwOxJp/eZfHjO7LMWTfmk0hK6k5t7U9ltiESdhKYbs+DENNrepoPcUFzeC1uOaUMkYj+QpqN+yjsOAIm9HbCuIq0V3fVqD+i0CQX4fc3AJij7mI6jfvm/1f1oyE3cl1Wt03EDVFfzvpTv0z9yuKYFb7KUbIo1GPq5H+dhMLksf3xFjhhU2m3s2y5b0V24xZI1VJSiJhPCDs8Y7fn7iuAZcNnWor72Krz8fkyS8wEiJACCXJVFEBHlKKhSOMyodLA1p7anWFuyvjRyREHOchfXtU8ahLBbGaYcNxOmHDwIAPDxvo75uu5aotbIkgrsunYibnv0YXcm0LtrKomGThUwXZJEwOjUxJ/ZrtVaEpDQCmca33pQY1uqyzOQyM2LI3I/NetxOY7UY2HmOLkuxLVNQP+yiSFxTE4fWYPa04bZtuKa9CJiHTEZ0rVl6CBBWOvFwIVNXmbmGql/Lq7iG82GxFUemcG6pZenPQlaWB5ell1mWJZEwVv/sLNdtPH7tdN/71Wuv9lCwVu+583cvpEsJIgD6E6RpNiK3CTV3C5kxi8nJFVISDeHsIw8yxfYIAZVWONrjRiyUeAJXuFGHr6IkYornES66kmgY2/Z3Ytv+Tn0Q60iYC4eHGMMFkw4GAJx95EGu30FvSgwrvkYxm9XqppXx5rJ0XsdpWa4uS8BeqohnCMS/dOqwjG4yp6D+IHnIZMT1vEZLAAsYFrLhdQ6CLEtRe78TCoXAdksz4we5UkOQWpYTh9XisIOq9XVzy0NWGPRJKEWaGLavQoKMKBp6Y1C/fCNxru2njiyycGntSuKpD9RUAZGQ8yxLJzemXEJHiKiKkoiprW4hswSti5p8n+5rN9pqQk4M3kKkhBgwblAVNt15DsYOdJ9d1VsSw8pB698/czyiYYZB1aWu7b3lIbOs43AnFcsUzqVEm977LWMtVeTkshRki/ex9l1OC+IVN+vcmp2SINOskdVlEVsRe6ub3GrZEt/XnRcfiTdunJm1P0L05MNlqX8XnOtpZdTl3tZ/8RvHY/roet0qnUv8VaGKaOf6AOEX0mMq5LIkio6eGOM37G7DKb9+C3+7fgamj67PvoIFrg+wDEKeqQO4s+VAHnBufXEFXlyyHYCRGNaKU9yJHkPGzRYy2eUpXldYBNn1J40BAHz26KGYv26vtg91EPvrtdPR2pXEzc8vw7qmNs83YdZLEsMChiv5/IkH4/yJB2dsHaiWpYMtw7C0ccv14p9wyJwZn4O75g5zEwCZMvVHfQ68VuucuM7XNrXpcYqdCfVhJBYOY3BNmcmdab2+Uwo3LRPf18RhtRjtIeWCLsjyoMjEV5Hm3BSjmU0cPffVY01CX04+nGtfeppslSXevOlk7HPJcxgEspCpdJuFjDH2MGOsiTG2XFpWxxj7L2NsrfZ/gLacMcbuYYytY4wtZYxN6a5+EcVPPtwO2XhvgypKXliyLdD6oofyfcRpMDBmWRrL5Mzk4ZBz2gunZcJ9kEpzdCY1C1ksYhrI5BgywX+/e5Ke1uGiyUP1mB4xiB06uApTR9bp63q9OaoxZJ6aFhTFpwXISy1LqzHXafO6IFPkPGT5cVkq3H2wdEp5AchB/XZrlO9M/TYLmSq+2uIp1FeoyYy7pHi9YQPMosRqAbamdBBvvfbLcNvnQZBJpbMyTf6wMnVkHYZJ7llRMcOtwoAXChVXqycydlEIIxsqMGV496bC6I90p8vyEQCzLMtuBjCHcz4OwBztPQCcBWCc9nc9gPu6sV9EkdMTVhen3E5+MGLImG2ZjBFDZnwojzFuaS+cLBaRkDHomGPIJJel9lpeZg1gF65J637FOl4HwRBjmaP+iwQ5MawXgmTqz5yHzL/AsPfJ3B+3TP2A3V0tb8OJYHnILBYuLeA8kVL066tLmzwSDTMcdlC1qb3VQmYNWBfH6jX8SsRD+p2d6UTIw/n3gjgPTilIvFIow5GSxUKWb8hCptJtgoxz/jaAfZbFFwB4VHv9KIALpeWPcZX3AdQyxtyjiYk+jV+RtLOlC6+t2OlrHTGYBS8KYI8JUksnmdEtZNIyefBzC+rPtCylcD1gujQWdowhk0WYVZCJ99ZgY+Hu9DoI9sYYMi8YFjL3NvZM/fbtMymGzAiS9twNE3aXpfvsvWw5vuwxZNyW6NVLf2RE39T8dur+56xqUvsTCWFkgzmw33o+rBUtjDQhXi1k+YwhU//nemkL61pnMp2lZfExqqECAMWQ9TQ9HUM2iHMuktHsBDBIez0EwBap3VZt2Q4Q/Q6/g/xn738XW5s7sfEXZ3u+gRs5vYIpMicLWeY8ZMaH8j0uEmKOs7CcXJZ6glCF6xaFaChkdlk61M+zDtDiqddqpYhqasHrd9hbiov7TXwaJDGsY9qLPMaQWb/rTIH4rkW4xbqW5YGKi1u+0JQuyDgqS80WulgkhBPHNdpEpdP6cp8AHy7LSD5jyIzfWS6IsIGuZBqzpw3HcksZKS8USqg8ff0MrNh+oMcmFZCFTKVgQf2cc84Y833FM8auh+rWxPDh9lw7RO/H731wa3Onvp7XJ32jYLO/fQn01SwWMiu64JM+CnmwkDkF9YsBPqVwfbvWGLSwJqpkq1jUYiETg6m7hcxPUL+npgXFr+AIkhg2W6b+XF2WoZBVkHHbebrh1HEYP7jKFMckIwZXW2JYJffSSUJopdIKSq0u8nAYNeVRrP/fs3HcL+bggslDbNtLpCwWMkXsp+djyMQuc3V/CpdlZyKNuy+fFKwv0g0mH4XTvTKwqhQDD3WfiZxvSI6p9HTai13CFan9b9KWbwNM5cWGastscM4f4JxP5ZxPbWxs7NbOEoUhaFyXWyZrJ/L1FJw1hiydzUIWcplR6W4hSytctyhYY9BE7Fksg4VM9NlqhYvoMWT243DCU/B7EeA38WmwxLAOLktJ2OXssmTMlJuLwy6cS6NhnJUhb5xhIbNbo/yO9W4WskSa21JayA8H7/7wVPxglj2jvJuFzOtpi+XRZWkk9FXff+3kMWioLPG9HSHIOnJwWcrXy9ybTg68nWJFTDAiA5lKTwuylwBcpb2+CsCL0vIvarMtZwBokVybRD8jqEjy432UxU0QnBLDOj1RO8WQyc+D4TDTrVoyjhYyWZCl1UE0ZHF5GkH9xvpeXZa+Z1kiu2uvGPCb+NSTy9JDDJkpU3/OLkvz9eVk9RNVCNxw23WgPGSW9sJim0wrtqS72QqJA+4xZF4Tk+azlqU1qP8Hs8Zj0Y9P870d3WWZCC7IxG9sUHWJq+WzN/PsV47Fn6+aWrB8a8VGt7ksGWNPATgZQANjbCuAnwC4E8AzjLFrAWwGcJnW/GUAZwNYB6ADwNXd1S+i+AnqKlAtZN6mqevupID74rAPsArnNtO7U6Z++d4TZs6zLLMF9acUrouviEPai5hcg8+yLbF/m8sy5M9lKSdQDRex0yFTElUnvCSGteK0dVOmfqlYcxBCIWZ6UOlKKnqtREFVaeb6kALHWpY+9Yy13JcRQ2YXZG7f/UE1pUgpHLtb4w6zLLV1fQb154Mg59+JsjwE9YvDd7KY9wUGVpfi1AxJmvsb3SbIOOezXT461aEtB/CN7uoL0TsQ97+gVqsg8fm5WsiYxWXpOsvSxWUZdqll6TTA6EH9nGvFwe3uSSOo330gE9vJOe2FxbVTrCicI+IrhiyAhcwpU7/JZSmWBRNkYUsMWUc8pSeAra+I4QezxuPiKfbYLBk9hsyyXLUg+gzqt1nIZEHm7aHovR+eitdX7sKXH1tkCzcQ2/Oqo2OR/D0QMElI54IeQ5aLINP+99RsR6KwUKZ+ougIOsD7iSETg1tgQab9F+OSmgLCHndkZOo3lsmDWcQlqN9JpOkWsrRmIRPCytFC5v5ELbbjFtTv1U3kJfi9GPAb1O8lNs4+y9Iphozp+cP0mKiAho4QY/oEFM45OpJpVGqzKUMhhsuOGZZhbWvnue1trqWTUml1JmkyzVES9X6QYsKJNTGsPiu1AC5LUS6pviJzvc1s1JSp22nIUkg9E4aFjARZf4AEGVF0BBVJftyPad2VGNRCZhZakVAIibRis6rotSylAdzksgy7pL1wCuqXYltSimK4LEP2GLJMuaiEeLC7LP0G9fcOCxmHv6BhLxM+vMSQieWyIAvssmRGf7qSCjgHqgLUSHTK5ZsOEtTvYCETDx+lHi1kgDEJxc1l6T1Tf/4E2TlHHoSOS9K4YHLmElvZGFRdinuvmIxjA5RmE/R0TUmisJAgI4qOoHFdfoScaJt7mSZttmOYIZG2Czw9hkwyADAvFrIMVjM17YVhIZPdk2EPFjKxaasVTmzHq2jIV6xNd+O/dJIHl6VtHed2ouRRPl2W7VpheWEh87NFp7ZB8pDZLGQK161cfixk4gEiZRFkfl2W+RRkjPm0OGbg3KNyE3XieyFB1j/om5GCRK8m6CzLIILMOt3eK1YNIidtddqPbCGz5iHLJL5kZMtNMi27LKWcYw6JYa0IwWUdhHWXpZ/SSSh+QeY3MaycYT/TNk3ruMgiplm2xHUQdDJZiBlJVTv0slnBnqed8pDlKsjSioJkSt2wNag/E+KaSyq5zbLMVp2gtyLOOQmy/kHfvIqJXk2PWMi4sFwZ60y547948O0Nnta3xhAJcWTtupGHzFhmzUPm5J7M5MbULWS6y1IWePbEsFbcajXqLkufN//ekPYiWB4y9zaeLWSaZUsIuKADq5ypX1jIKlxqVmaCMWa7dv0KVtEfmZTCkRAWMh8uSyGkktbEsL4z9fdNwSLuUxRD1j8gQUYUHUEHeD+CTAgxWfzta0/g5y9/4ml9sZr4L4SQVUyKiQbyYvnWGmLO1jCnG7DQbWnNPWS4LCULmUvAvoz4yDPMZBUAACAASURBVGrN012WnmtZCuFS3IrMbyZ6L65Y60du21ctW/nI1G/8Ljo0QRbEQsbglPYiiIXM/F6NIROCzL+FzJ4YVv1fCJdlMSFX5CD6Pn3zKi4COOd4edkO2+whIjs94rK0WMj8igprc7fSLc5pL4ybK/ORh0xYsNKahUy0CZssZFoMWYYByi1GKuI37YU+G9FT84LhNxO9t8Sw5g/dtm+dZRl0XA1LLst24bIsCev78IpTUH+QPGTWOMOUwnWXZWnUu4VMXNPW+6RfC1lftSAJC3tfzUNGmKGz3E3M+aQJX3/iQ9z7xrpCd6XX0ZOzLMU6fmPJRGuxvnhCt2becMrUb7WmOD3dO1lcRLO0ll7AqQC5KFuTMag/5CwehXXNbx6y4o8h82cB8lTL0raO8/bDIQauuSwZ818zUiDXsuzQXZZBLGT2/Svcf7/EuZ89Ta0nnDa5LI1r76ihNRm3Ix5krEH94kHJc9WIPprpfczASgDAF44dUeCeED0BCbI88vmH3sctLywHALR0JgEAm/e2u7Zv6UhizI9exry1e3qkf8WEonD8Z9kOR2tY4Ez9PiqFG8WQc5tt2amVRanSZry5zrJ0SQwLeLco6G5RRUFaURytAgO0HEqZEsM2anX5rPv1ayHzkkC1GPBrAfLiirWnvXDfVppzLbVEcNEgx5B1JERQv/8YMsDe9yAxZMJCJq7BVNp5luVL3zwh43bEw4jdQqbtx2fH+poua6gswaY7z8H5E3ObrUn0DkiQ5ZH56/bi8fc3AzAsFIkMLssV21uQVjjunbu2R/pXTPxt0RZ87YkP8fTCLbbPAteyzCEPmV/Xshis41owssia7u6yNJZZB40yjwOrGATTCrTSSU6CTE1CmclC9oNZ43H7+RNw6viB5u3rLlBP3ek9xcV9ZqIXLTOnvbDMssyYh0zdVtAcZIDFZakJshpNfDdW+Sh8zdyKi/uMIdNn5KrXc1pR9IcbP0H9xixLe5/E9r1y/xeOxhs3nux9BYIoMigPWTehC7KU+0Bf3MNY97JjfycAoKm1S18mvo+gFhc/bkdrpn6/FjJra1FH0LoZY5al8YFVv5R6DIIWg6AY/JwsZCLLeKYYsrJYGFcdN9K2XFjVvIoXL7FWxQDn/nJ1eZpl6dlCpj5g+C1wbtuOHNQfV12WwwaU465LJ+KkcQ2et8MA28UbKKjfkktPnmXppZi4oCSsijfrfVI8lPkR0rOOGOy5LUEUIyTIuglxw45nEGQCtxxGfZlMiTKDuiz9WNaEQUysYs0UnhVLc+GytOJUzsl6fE6xYE6YLWSKY6CvsNT5GRT1fmjb82rJMSxJxa3IOLohhszHLEuFcyhK7i7LVFrB7f9cgb/M3wRAdTl/9uihvrbjGNSv+BeL1okkYuYvkNldbkWv96jFxel94jSzkOh/kMuymxBPixktZMU9jnUrmVwSQV2WPWshM7evdCljIzYrD+5Bj08MUGlFcXVZupVF8oKR9sKvhay4L2S/syxFDUo/tSwz5yHLXWCEQ2osmhBjIRZse9FwyG6NCuCyNNdjDZky9ftJ0hqLhBANM90NKwhSzokgejskyLoJcdPzEpvU1wJRvSCsRHISUvEqaIC9H6FjDeb3H0Nmfu9mIXNq79cYJzAEGXd1WQqCCDJhqfN6PYp2Ra7HAguOzGkv7O2dkDP15+SytPQnaN6t0mjYZrUPIhbl5nYLmb++lcciuhvW6JO/uD+C6AuQIOsm4in1iS+TK8z6lN2fEAOa00AW1OLix0JmpLtQB5FcY8gqswiyfFrIUloh53CGqYN+3EaCSCiYhazoBZnPxLCAFvvl48DcNi9n6s/FQiYXFweClwoqiYQQT5qtUUHi2+RvRo0hU/R7nRBkV87wlqqhIhbWZ47q289xEgRB9EYohswDz3+4Fb9/Yx3euHGm5xu7sJBlclnmWt+uN2PkGTKWiZt8T+QhE/sX1gKnWK9M2CxkLi5Lp/ZBj0+vl8k50opiEl0NlSUYVlemvxfX6dXHj/S8/ajfxLAeaj4WA0HSOjCfFjK3OFA17UWwwHkZYYUSBIkRBJwtZH7ztLn1TY4h23TnOZ7XLy+J2ARZWiGXJdH/IEHmge898zEA1doV81gzTRdkGVxh4omyvwT1f/HhDzBt5AB885Rx+mDnNJYHLp3kJw+ZtuMuzVrgPzGsuX22MjZml2WwA4zIFrK02eKy6Men2dr7GRSBvltcPIgYCmWJIbMes5uxUmTqzzUmSs5DBgR3WZZEQvo1L/AbYycjKk3Iecj8uyzDen1OU59IkRH9DHJZ+iCTuLK6obxYyPpbWaW31+zGXa+tAWAMaE7fT9ABPoiFrCupgHPuK6ksYBeS2dxRsoAL6rLUBZDmssx3/T69uLjnGLLekfYiSGkgqwCyYv3ETfCFmZGpP1+JYYHgxbSdY8hy61s4rFrIhJXLT+kkQBVkHXG7yzKXPhFEb4QsZD5IpBTAJQdj0uLyEuLN+jRqWkdr0x/uO+9v2Gt6L1yETiLXi0uvuT2Bzfs6MGlYra/1jP0bbeMpJXDpJEG2p3nFo4XsyS9Pd+2L2UKm5D0tgN9ZlqJV8SeGDRJDls1l6W2WZUhL6Koo+XVZ5tdCllvpITHLsulAHIwB9ZUxX+tXxCLYeaDLtIxclkR/hASZDzJZu6wWFi8Wskyf9SW27+/E5x5437SsK2n/fsQg50VYXfan97C2qc3klvNVXNwqyPxaKz0OyEZzo32mfs4YXe8q7kIhps/aUy1k+R2xhtWVIxYJYVB1qaf2vScxbJAYMn+1LN1Sz4a0tBe5uizVNBzSdgMKqNJoGAe6kvp7cV3m0jchFpta46iviPl3WTrEkCk5ToIgiN4ICTIf+BFkwi1gdQ/85MXlYIzhtvMn+E9G2kvpsMSHAECn9pQufz/i2/Dislzb1AbALG78CDJ5H/FkOrCF7MEvTgWQ3f0sbz7T8WWztIUZk2ZZ5nfAOmRQFdb87CzP7cXuiz+GjPuO0wwxlvdM/bnERIk8ZLmizrI0rtVMCZozIXdl+/5OrGtqw5DaMgys8ibmZdRZlpT2giAohswHiXQG96PFZRmXgvrlmKFH39uMR97dpK6juyz7+o3Hfnxi6r3sshTfk58BXhbJQS1kXUnFdwyZYMrwWpx++KDsFjLpddB9AcbAnEo7Z+rvScR1W+R6TAvq97dO9rQXVgtp92bqDzOW03UjKI2G0ZUy7mPid5CLthfWrW37OzGo2kddTQ01D5nFQqbk1ieC6I2QIPNBpjJIVguJLBTc1pPX2drcgY172nPsYXHilFJCWMhMgkp3WXrfdtxhcPGCPNh2pdI5p73IJqpll6XTQO91rA6HGNJp1UKWKTFsT9BbLGQ8gLUla1C/zUKW2WWZa6Z+xpjZmhzwO7dbyETqHX99k5v/6cqjMbyuHADQHnd/aHWjokSdZWn9jVAeMqK/QS5LH/iKIUvLgiyt12wTrNjegl1aICsDcML/zQXgP1VBb8DpexMxZPIgIzSRnwE+7iDovCCfr65kOsAsS/NAls364ZSH7K/XTteX/fe7M/Hh5uas+9UtZArXi40Xit6SGDbIjL2sechs7Z3bCUtbrsXFwyF7vccglEbDpqB+ce5yEYtnThiMKcMH4Jifv47TDx/ke/2KkggUrlraKrR8fmlyWRL9ELKQ+UAIiy37OnDKr9/EzhZjZpDdQmbc9JwsZOfcMw8PvrOxm3ravTS3J3Dab97Cml2tnto7CzJhIbNbuPxYuuTBJUimfnUb5lmWXtJSiBZiyMg2nskiM82Bkw5pxAnjGvRlYwdW4rJjhmXdrwigTqUVRAvssuwtiWGD5NnKlofMbiF1bhcWLstcU0uEGDoyzNj2Skk0ZH4IykNQPwA0VpVg1R2z8OUTR/let6FSdXPuaYvry1Lp/E9aIYhihwSZD0QQ/l8XbMaG3e34+4db9c+sA7rJZZnMFvBd3AOalbmrm7CuqQ2/f2Odp/ZOgkx2Wf7oH8vwwNvrJZdlMAuZn/xectt4Km3apzUe0AlxysQYm22wNQX1KxxBx5pIiCGZ5jm7wPKBCJQv9utX4dknS1gJMYZMl4E97UWGTP1a2otcXHAsyyQDr5RE1Dxkov+GIAse1C8ojYYDWbUaq1RBtrvVEGStXcms5cgIoq9BV7wPRFC/uLHKg7gsOpKKYnNZZqKvJ4iNOxxfV8II6n9ywacAgPoKNX+Rn/gYWez6s5BJfUkqphiyZJojSyUkyUKmXgvZxiFr2ougYirEmH6tFdqCII652NNeBHEXZkt7YT3mjMXFebA+yFjFXNCvvDSqPoPHUwpKo2H9OArpHmx0sJC1dqVQXRotVJcIoiCQhcwHYiCUawoKZDGQSnOTUMg0GQBwL0C+rqnN9NRYLIh7t3wL/8rji/Dikm2O7Z0shO2JDEH9vmLIDLEb1EJmjSFLWs7Xml2taG5PmJbpAsujhUw+pFzcV5EQ02fJZSou3hMYMWTFrciCxJCFGMsoeqyls9z0dTikZurPh8syH5RE1FhW8Zvc2twBoLAzGhuq1Acx+V53oCuJKrKQEf0MEmQ+EMJKLxljEmHGIL5qZysSUib1eCqNRZv2uSYf7UzIQbbGNk/7zVs45uev48cvLAOg3rA27G7L09EExyqwOOd4dcUu3PD0Esf2Ttn4xTHvbTOEjhFD5qMvqWAWspSioFybaNGVTFssZOYOnHH32zj39/MctyPGWD+lk3KykIUY9neo31mhByxdkBW0F9kJEkOWzUJmj+p3bqa7LHOeZRl4VRPCQrartQvLt7XgnHvU67qQZYrqK0oQYlaXZQpVZCEj+hn0COIDayyULABkK9cl972L2vIoRtSXY8Pudlxy33sAgG+fOs5xu/sk64tTAfO/vv8pfnbhkTj5V3PRnkgXfCZmW9w82yubBdD6vcVTaV2kbW/p1JeL8c+Ppevd9Xv019v3d2Lz3naMqK/Iul5aUWd3dSTS6EoppgHbKb3Atv2dpvUtBjLHAbMkYgRQW0snBU0SGouEsK1Z7UuDzxI1+UZPe1HkPssg1qmsiWEd2jtuR2Tqz7EUUL5SQAgL2dV/WWi6pgtpIQuHGOoqSrCbXJZEP4csZD4QIqJDEyTt2v+mA1146WOzu25/RxKThw0wLVuyZb/jdvd1GIJMuKOsbiDOue7mK4SLqLk9gcvufw9b9nXgQJd63MKC0NqVeTq+VZC1dBilW7oka5tuIfNxfH+Yu15//fj7mzHzV296Wk/hHBUx4b4xuyxbOpP4ztMf4bUVO039kxEWL2EtPXJIDa6YPhw3nzVeb3P2kQcZ7eUcS0rwHEuDqkqxaa/qZqqv9J+EM5/0nuLiQWpZZimd5DUPmZT2IpdM/bmsKyPiNK0PGH4m0gDAlBHqve1EaaZwLgwZUIaNe9pxzSML8caqXWiLpwpuASaInoYEWRYemW+kphDCol3LB9TUGseyrS248z+r8NQHW2zrTh5ea3rflXAO7pcFi2hjtTq1S+u2xnPLR9TalcTybS2+1vnHR9vwwaZ9+N4zS7BTs2qJDN1Wi5mVhGVSgxCmRw2tMS0XQizbrL1sFhkvgjWtcJTH1Bu+tbj4pr3teGHJdlz/+GLXY7NayKpKo/jfi47EV2eO0dtcPGWIrT2gHmdQ99VBNUZpGjG4FgpxCMUcQ6bni/O5Xtbi4h5jyESC2SBxbNbt5IMhA8ocl+9pSzgud2PSsFp88tNZOPUw/3nHnBjdUIH3N+zDG6uacM0jiwAA1WVkISP6FyTIsnDbP1fqrxMpBR992qy7GP+zfCfOu3ceNrhk2J80zCLIssy2BIx0EO0WISAHleca6P/NJz/Cub+fhx0tndkba4i+L9zUjGcWqek+WrUixW3ZLGSWmKzrH18MAPjScSPN7YR7TxsJOedYuGmf7ek92/fo5ftROEdpNITyWBhLt+7HHf8yzvPCjfv0166CTPufaZycPqre1h5QE+AGFWSDZUFWYAtZKFT8FjKhFf0nhvVnIXOrlRliDJ2JNJZu3Z9jAW9rB4JtZ0itIcjka1AkqfaDNdl1LoxusIcZkIWM6G+QIPPBzgNduOiP7+LVFbtMy1fuOGBrO7K+HHUWC0aXh8SOX3l8MRSF20qQ7JUE2Z4cBFlnIo231uwGADyzcCs6Eims3H4AH37arFsT0grH1/66GB9sVMXQ159YjFeW77RtS7gqW+NJ22cybnnYKksieP17J6HG8iQsvIdPfvApLr3/PTy32Gx97HSxNArO+f28rFabVJojEgrh3KMOsp3PBZogqy6N2ISxlUxFq2OREO6+fCLqKmKWGblKYJelbCGrLvCAJY6gmPOQBU18qsaQZRBklvfM5U4aYsD63e040JXK6UEqXxayCimfy08vmKC/7sxD0tlcGNVoF2SFvr4JoqchQeaDzVrsjhWnxKeHHVSNkoj5612zK/sMyVU7W/HMoi02y4wswuTgV79s3mdY815ZsRPfeXoJzr7nHVz8x3cx55Mmdfutcfxn+U5c//giLNnSjJeX7cTSrXYXpxBkfi1kgvJYBGMHVuG28w83LRcWskff3QQA+Mv8TbjusUXYqx13RxZBtrs1jv0dmUWiGlgPnHXEQabl5bEwVu1UKxBUlUZN50EeoL1qkIsmD8XMQxotpZOCxwQNrjEsHIUuLWPEkBWzIFP/FyoxrGyFOpDld5KtP/nm89NHYMmtp+Nbp4zFLecenn2FbkT2JgzUEsUOqS0vVHcIoiDQI0gGrDfdLfvMguzoEQOw2KX+4LRRdSiJBjPp3/z8Mvz4nMNMy9ZL6S6aDgQXZDu0ck+zJgzGKyt24hPJurerVf1MPMkzQBdpToj0C9ljyFwEWYn6/VSWWCxkCkdze0IXsKt2tmLVzlYMrCrBzEMadZdnJna3xTEgQ4yVonBEoyEcMcQcxzaoulQv8t6eSJnE5updrRg/uBqAHNRv3/ZvL5+kZx8H1O9RFi0K53YXlEemjarDZ48eiomW+LtCoMeQFbYbGTGKZ/tbL5PL8p21u3HTsx+blmWKIRMc6Mz8kJCJesuM2vMmHhx4W/d/YYouVGvLY7jxjEMDbytfDB1giK85N85ES2fStIwg+gNkIcuANXh+bZPZwvXUdTMc1zt+bD2+eOxIm4XMD3//0Dxr8/9eWaW/XrHd7iL1iqi/ef4k+w1dWKZEPEmIMazYfgDlsbBtAKgujaA9kUZLZ9IkyNQyMRxLtxozSuMpBZUlEVvaD5EHrNKSFl/hHIs0ofv9Mw/FuUcdhDGNFXhiwadZxdhj10wDkD2OLK2lQpCFEwAcXGu4BPd3JPG/L3+iv5/123f015mMQhdOHoLjxxqzz6xlb9I5zLKsKYvirksn4spjRwZaP58UQ2LY1q4k5nyyC9c8shAHuuyCJ2gMWaag/iv//IEtCN7NdS3v1k+ePCujGyr118tvPxM3uKTQ8cKsIw4yzQAuFh65+hj88pKjUFUaJTFG9EtIkGVgf7t6g7/VYs6/7bzD8eR10xFzEVyNlSUIhxgiOUTxyparg2tK9cGhJBLCB5v2YsmW/Yin0li+rQUffdpsmnm4emcrrnlkIRZvbsa6plb8ed5G/OI/n+DrTyzGD59Xk8xOH1Vn26cYZISlLBRi2LCnDaceNgi/nz3Z1PaMCYMBANuaO01pLxZs3IuH52/E+ffOx7vr9+CHzy/FI+9uQmk0hOtPGo1rTzCKD1dosxyPHFqDK2eMwOvfm4mJw2rx2spduO6xRWAMuOb4Ubj3iim4SXuKH1xdijsvPhJ3Xz7R8XsTs8j2tMXRlUybvkcZRUrO+tvLJ+nLTxlvnjVmnbBhFR9exnnG7Gkv8pXGoJAIkeOh9Ge38bW/fohrH12EN1Y1Ye4q1Zr72HubcObdb+NbT32kz9z1HUMWUs9ZWuFY5uCut+JaXDxP53m0FGNVWRLpE9ePlZMPHYjLjhlW6G4QRMEgQZYBkR9sRH05bjz9EH35l44fhePGqBYQMTtInr1UpgkNxhiW3XZGxn1cffxIAMAJmkVlRL39yVCIHwC45oRR2LKvExf+YT7O1DLIX/THd3H/2+uxYrs6cNw7dx3eWNWES+57F6f95m3c8a+V+NNbG/DyMiMw32mGnpg9uktzicaTaWxt7sQo7Rif/eqx+MrM0fjKSaMxe5p64/xg417MW2skZ73iwQX42b9Vq9IvX1mtpwPZ05ZAZUnEFKtSJlnI7rjwCIwdWIkx0myr2rKo3uYz4wfiS8eNxLNfPRafmzYcF00eauv/pGG1pkLF339uKc763Tv4w9x1OOeedzB/ndrPxZv34eOtLbqV6sLJRnqKK6YNx9XHj8Rt55lF+Fdmjta/mycWbMavXl0NIHNQv4AB2N7Shf+uVCcPpHlwC1kxYdSyLIyFbEdLJ+atkxMDd+EHzy3FrS+uwOpdrfjnx9vxqjYZJZiFjOPeN9bhvHvn6Wli/jB3nWt7P8v9Mri6NHsjgiB6NRRDloFmTZDVlsfwrVPH4emFW9BiiQP53hmH4JtPfoR7Zk/Cgc4Urn5kIWYeYrirqkqj+OSns1RrzyML8e76vab1R9SV4+OfnIGORArH/uINXHr0UNz12hpTm0HVpSiNhjB2YCWuPWEU7ntTTYa6SZpk8MtXVuOXr6zG3ZdPxKvLdyIWCdlit0Y1VKC5I6FbpgQf3nI6LvzDfGxp7sCzi7bgnjlrARhByGO0p/NjRtbhmJGqZU24BEVakMaqEpubcMmW/agujdiCma+cMQKPv7/Z5qoEgHGDqvTXsuWtNBrGbedPMLVdfvuZuOrhD7B4czN+dPZ4fOm4UYiGGaJhpotCALp4uvXF5RhYVYr3NuxFLBwyPY0fN6Ye767fi7JYGD85bwI457hg0hBMvuO/AFTB/Ke3NuDiP87Hds3tW1kS8WQBEbNwb/77UkTDE9GVTOfNclJISrUYSfE74ZzjpmeX4tDBlRhZX4FB1aVIc47Jw2oxf91e/Ont9fj6yWPRlUrjifc34+ufGYv6ihhuevZj7G1LQOEc15wwCseMrMOohgqs3HEAsXAI/162A42VJTjpkEY89cGnCDHg+2eOxyl3vWXqj+zWF9yoxXr5nQBxoDOJpVtbMF/7va7cfgAhxvRryYrb5kd6qBrhhVCI4Y4LJmDswKrsjQmC6JWQIMtAdWkUpx02UM/9NOfGmbacWOcedTBmjK5Hg2Zx+uiW023B5MLKc/flk/Dg2xvw1ZPH4FevrMbfFm3BgIoYasqiqCmL4qNbTkdteRT/WrpDn+kHqJafD/7faYiFQyiNhnHHBRNwy4sr9M8vnzoMe9rimLOqCd/9mzoAvfTN4/HA2xvwr6U79HZXzhiB2dOG6xaNB784FXvb4qiriCESYnhz9W68uXo3BlaVoK4ipvdhxmgjn5ZALtvz7VPH4dunjMUxP38dzZbZjRdPGYpHtNmSgtvPn4AbzzhEH9Bl5ODl2dOG2z6XqSyJ4P4vHI175qzFmRMG6y7kUQ0VthmtB9eUYv3udqzfrbogn7xuOqaONNy2j1w9zVSonDGGARUx/OPrx2He2j16ML8QYzedcQguO2aYJ2G1Qdvn3vYEvvSXhQBgS4nSGxndUIGKWBg/+Psy/GHueny6z3kW8tABZdjR0gWFc7wjWVPfXrsHNWVRk5C/Vbuu6ytiplQvVv48b6Puxj9iSDWaDsTRJG3njguPwC0vLNffN7X6y7MlHnbEQ83//H2pY7vpo+qwYOM+V0vYKeMH4u7X1zh+5pdiiBskCKL7YMWcZTsbU6dO5YsWLSp0NwKxpy2OP85dj5vPGm+LRetKqrUeFa0osdPg/eqKnfjK44txy7mH63FZ2/Z34tevrsbQAWX4nhZz9ae31mN4XTmmjqxDQ2XM1VLw/Wc/xrOLt+J3n5uEMycMRiTEcP9b6zG6sdI1AHjJlv3458fb8f0zD0VpNIz2eAqLNjfjyQWbcc5RB+PDzc249oRRWLnjAA50JnHp1OzxIZ2JNO78zye46riRGF5XjkiA6YjN7Qns70yitiyKv3+4FR9vbcHNZ43HZ371JiYOq8EDV07NOAPTjd2tcZz7+3cQCYXwyndO9Fz8+P0Ne7F8WwvKYmH8e+kOHDmkBt893VmQ9jZ++s+VeFirZiGsspdMGYqLJg/BW2uasHRrixakXYZrjh+Fu15bjZc+3o4TxzVg6IAy7G5N4JIpQzB9dD12t8bx0Dsb8OxiNfHwxKE1+NgSv3X+xINxwtgG/PjF5Th0UBX++PkpGDqgDF1JBYypVtV75qzFD88ej8NvfRVHDa3BtJF1mD19OMY0Vtr678bMX83F5r0dmDVhMOav36Nba2dPG4byWAQXTDoYtWUxHFxbivZE2pZLT8A5x69fW4N4Ko3jxjTgM+MHBvmaCYLoIzDGFnPOpzp+VkyCjDE2C8DvAIQBPMQ5vzNT+94syPJBS0cSlaXe3GbZ6Eqm0ZVMo7a891tu3GjpTCIWDuWUYbylM4myaNh1Qkd/I5FS0KldO3UVMXTE06gpzyxU93ckUBoNuwpSzjn2tCXQWFUCzjmaWuPoSKRRVx7Tt72nLY7q0mjG89DSmURJJBRI+HYkUuBcFKBPIcQY4kkF5SVhRIPmLCEIot/TKwQZYywMYA2A0wFsBbAQwGzO+Uq3dfq7ICMIgiAIoveQSZAV06PeNADrOOcbOOcJAE8DuKDAfSIIgiAIguh2ikmQDQEgFy3cqi0zwRi7njG2iDG2aPfu3T3WOYIgCIIgiO6imASZJzjnD3DOp3LOpzY2Nha6OwRBEARBEDlTTIJsGwB5Gt5QbRlBEARBEESfppgE2UIA4xhjoxhjMQCfA/BSgftEEARBEATR7RRNYljOeYox9k0Ar0JNe/Ew53xFltUIgiAIgiB6PUUjyACAc/4ygJcL3Q+CIAiCIIiepJhclgRBEARBEP0SVC7WgQAABuZJREFUEmQEQRAEQRAFhgQZQRAEQRBEgSma0klBYIztBrC5m3fTAGBPN++DKCx0jvs+dI77PnSO+z594RyP4Jw7JlHt1YKsJ2CMLXKrO0X0Degc933oHPd96Bz3ffr6OSaXJUEQBEEQRIEhQUYQBEEQBFFgSJBl54FCd4Dodugc933oHPd96Bz3ffr0OaYYMoIgCIIgiAJDFjKCIAiCIIgCQ4IsA4yxWYyx1YyxdYyxmwvdHyIYjLFhjLG5jLGVjLEVjLEbtOV1jLH/MsbWav8HaMsZY+we7bwvZYxNKewREF5gjIUZYx8xxv6lvR/FGFugnce/McZi2vIS7f067fORhew34R3GWC1j7DnG2CrG2CeMsWPpd9x3YIx9V7tHL2eMPcUYK+1Pv2MSZC4wxsIA/gDgLACHA5jNGDu8sL0iApICcCPn/HAAMwB8QzuXNwOYwzkfB2CO9h5Qz/k47e96APf1fJeJANwA4BPp/f8BuJtzPhZAM4BrteXXAmjWlt+ttSN6B78D8ArnfDyAiVDPN/2O+wCMsSEAvg1gKuf8CABhAJ9DP/odkyBzZxqAdZzzDZzzBICnAVxQ4D4RAeCc7+Ccf6i9boV6Ex8C9Xw+qjV7FMCF2usLADzGVd4HUMsYO6iHu034gDE2FMA5AB7S3jMApwB4TmtiPb/ivD8H4FStPVHEMMZqAJwE4M8AwDlPcM73g37HfYkIgDLGWARAOYAd6Ee/YxJk7gwBsEV6v1VbRvRiNLP2ZAALAAzinO/QPtoJYJD2ms597+O3AP4HgKK9rwewn3Oe0t7L51A/v9rnLVp7orgZBWA3gL9orumHGGMVoN9xn4Bzvg3AXQA+hSrEWgAsRj/6HZMgI/oNjLFKAH8H8B3O+QH5M65ON6Ypx70Qxti5AJo454sL3ReiW4kAmALgPs75ZADtMNyTAOh33JvRYv8ugCq8DwZQAWBWQTvVw5Agc2cbgGHS+6HaMqIXwhiLQhVjT3DOn9cW7xIuDO1/k7aczn3v4ngA5zPGNkENLTgFaqxRreb6AMznUD+/2uc1APb2ZIeJQGwFsJVzvkB7/xxUgUa/477BaQA2cs53c86TAJ6H+tvuN79jEmTuLAQwTpvhEYMaXPhSgftEBECLK/gzgE8457+RPnoJwFXa66sAvCgt/6I2S2sGgBbJJUIUGZzzH3LOh3LOR0L9nb7BOf88gLkAPqs1s55fcd4/q7Unq0qRwznfCWALY+xQbdGpAFaCfsd9hU8BzGCMlWv3bHF++83vmBLDZoAxdjbU2JQwgIc55z8vcJeIADDGTgDwDoBlMGKMfgQ1juwZAMMBbAZwGed8n3YzuBequbwDwNWc80U93nHCN4yxkwHcxDk/lzE2GqrFrA7ARwC+wDmPM8ZKATwONZZwH4DPcc43FKrPhHcYY5OgTtyIAdgA4GqohgX6HfcBGGO3A7gc6sz4jwB8GWqsWL/4HZMgIwiCIAiCKDDksiQIgiAIgigwJMgIgiAIgiAKDAkygiAIgiCIAkOCjCAIgiAIosCQICMIgiAIgigwJMgIgugzMMbSjLEl0t/N2deybWMqY+wen+tsYow1+N0XQRCEgNJeEATRZ2CMtXHOKwuw300ApnLO9/T0vgmC6BuQhYwgiD6PZsH6JWNsGWPsA8bYWG35pYyx5Yyxjxljb2vLTmaM/Ut7XccYe4ExtpQx9j5j7ChteT1j7DXG2ArG2EMAmLSvL2j7WMIY+xNjLFyAQyYIopdBgowgiL5EmcVlebn0WQvn/Eio2dt/qy27FcCZnPOJAM532N7tAD7inB8FtbrDY9rynwCYxzmfAOAfULPEgzF2GNRM48dzzicBSAP4fH4PkSCIvkgkexOCIIheQ6cmhJx4Svp/t/Z6PoBHGGPPQC1mbOUEAJcAAOf8Dc0yVg3gJAAXa8v/zRhr1tqfCuBoAAvVyj0og1HsmiAIwhUSZARB9Be49TXn/KuMsekAzgGwmDF2dI77YAAe5Zz/MMftEATRzyCXJUEQ/YXLpf/vAQBjbAznfAHn/FYAuwEMs6zzDjSXo1a4fA/n/ACAtwFcoS0/C8AArf0cAJ9ljA3UPqtjjI3otiMiCKLPQBYygiD6EmWMsSXS+1c45yL1xQDG2FIAcQCztWW/YoyNg2rZmgPgYwAzpfVvA/Cwtl4HgKu05bcDeIoxtgLAuwA+BQDO+UrG2I8BvMYYCwFIAvgGgM35PUyCIPoalPaCIIg+D6WlIAii2CGXJUEQBEEQRIEhCxlBEARBEESBIQsZQRAEQRBEgSFBRhAEQRAEUWBIkBEEQRAEQRQYEmQEQRAEQRAFhgQZQRAEQRBEgSFBRhAEQRAEUWD+P4OVq5z/8Mn0AAAAAElFTkSuQmCC", + "image/png": "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\n", "text/plain": [ "
" ] @@ -1567,12 +1569,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.9 (main, Dec 7 2022, 13:47:07) [GCC 12.2.0]" - }, - "vscode": { - "interpreter": { - "hash": "916dbcbb3f70747c44a77c7bcd40155683ae19c65e1c03b4aa3499c5328201f1" - } + "version": "3.8.5" } }, "nbformat": 4, diff --git a/release/setup.py b/release/setup.py index 24424b613..f1a73e717 100644 --- a/release/setup.py +++ b/release/setup.py @@ -53,13 +53,13 @@ def finalize_options(self): REQUIRED_PACKAGES = [ 'cirq-core==0.13.1', 'cirq-google>=0.13.1', 'sympy == 1.8', 'googleapis-common-protos==1.52.0', 'google-api-core==1.21.0', - 'google-auth==1.18.0', 'protobuf==3.19.4' + 'google-auth==1.18.0', 'protobuf==3.17.3' ] # placed as extra to not have required overwrite existing nightly installs if # they exist. -EXTRA_PACKAGES = ['tensorflow == 2.11.0'] -CUR_VERSION = '0.7.3' +EXTRA_PACKAGES = ['tensorflow == 2.7.0'] +CUR_VERSION = '0.7.2' class BinaryDistribution(Distribution): diff --git a/requirements.txt b/requirements.txt index ae8700878..ee7ebc77f 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,15 +1,15 @@ cirq-core==0.13.1 cirq-google==0.13.1 sympy==1.8 -numpy==1.24.2 # TensorFlow can detect if it was built against other versions. +numpy==1.19.5 # TensorFlow can detect if it was built against other versions. nbformat==4.4.0 pylint==2.4.4 yapf==0.28.0 -tensorflow==2.11.0 +tensorflow==2.7.0 # Needed for compatibility with cirq program protos. googleapis-common-protos==1.52.0 google-api-core==1.21.0 google-auth==1.18.0 google-api-python-client==1.8.0 grpcio==1.34.1 -protobuf==3.19.4 +protobuf==3.17.3 diff --git a/scripts/benchmark_all.sh b/scripts/benchmark_all.sh index cd50209c2..9fbf73387 100644 --- a/scripts/benchmark_all.sh +++ b/scripts/benchmark_all.sh @@ -14,7 +14,7 @@ # limitations under the License. # ============================================================================== echo "Testing benchmarks."; -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/...)) +test_outputs=$(bazel test -c opt --cxxopt="-D_GLIBCXX_USE_CXX11_ABI=0" --cxxopt="-msse2" --cxxopt="-msse3" --cxxopt="-msse4" --test_output=errors $(bazel query //benchmarks/...)) exit_code=$? if [ "$exit_code" == "0" ]; then @@ -26,5 +26,5 @@ else fi echo "Running preconfigured benchmarks."; -bazel_run=${bazel run -c opt --cxxopt="-D_GLIBCXX_USE_CXX11_ABI=1" --cxxopt="-msse2" --cxxopt="-msse3" --cxxopt="-msse4"} +bazel_run=${bazel run -c opt --cxxopt="-D_GLIBCXX_USE_CXX11_ABI=0" --cxxopt="-msse2" --cxxopt="-msse3" --cxxopt="-msse4"} bazel_run benchmarks/scripts:benchmark_clifford_circuit -- --op_density 1 --n_moments 10 --n_qubits 4 \ No newline at end of file diff --git a/scripts/build_pip_package_test.sh b/scripts/build_pip_package_test.sh index 644338b6a..1adc7a7e9 100755 --- a/scripts/build_pip_package_test.sh +++ b/scripts/build_pip_package_test.sh @@ -19,7 +19,7 @@ pip install -r requirements.txt # cd tensorflow_quantum echo "Y\n" | ./configure.sh -bazel build -c opt --cxxopt="-D_GLIBCXX_USE_CXX11_ABI=1" --cxxopt="-msse2" --cxxopt="-msse3" --cxxopt="-msse4" release:build_pip_package +bazel build -c opt --cxxopt="-D_GLIBCXX_USE_CXX11_ABI=0" --cxxopt="-msse2" --cxxopt="-msse3" --cxxopt="-msse4" release:build_pip_package rm /tmp/tensorflow_quantum/* || echo ok bazel-bin/release/build_pip_package /tmp/tensorflow_quantum/ pip install -U /tmp/tensorflow_quantum/*.whl diff --git a/scripts/ci_install.sh b/scripts/ci_install.sh index a0ed81c8c..99b3dc45e 100755 --- a/scripts/ci_install.sh +++ b/scripts/ci_install.sh @@ -13,7 +13,7 @@ # See the License for the specific language governing permissions and # limitations under the License. # ============================================================================== -wget https://github.com/bazelbuild/bazel/releases/download/5.1.0/bazel_5.1.0-linux-x86_64.deb -sudo dpkg -i bazel_5.1.0-linux-x86_64.deb +wget https://github.com/bazelbuild/bazel/releases/download/3.7.2/bazel_3.7.2-linux-x86_64.deb +sudo dpkg -i bazel_3.7.2-linux-x86_64.deb pip install --upgrade pip setuptools wheel pip install -r requirements.txt \ No newline at end of file diff --git a/scripts/ci_validate_tutorials.sh b/scripts/ci_validate_tutorials.sh index e58355faf..74c9189a1 100755 --- a/scripts/ci_validate_tutorials.sh +++ b/scripts/ci_validate_tutorials.sh @@ -15,13 +15,11 @@ # ============================================================================== # Run the tutorials using the installed pip package -pip install jupyter nbclient==0.6.5 jupyter-client==6.1.12 ipython==7.22.0 +pip install jupyter nbconvert==6.4.3 jupyter-client==6.1.12 ipython==7.22.0 # Workaround for ipykernel - see https://github.com/ipython/ipykernel/issues/422 pip install ipykernel==5.1.1 # OpenAI Gym pip package needed for the quantum reinforcement learning tutorial -pip install gym==0.24.1 -# seaborn has also numpy dependency, it requires version >= 0.12.0. -pip install seaborn==0.12.0 +pip install gym==0.18.0 # tf_docs pip package needed for noise tutorial. pip install -q git+https://github.com/tensorflow/docs # Leave the quantum directory, otherwise errors may occur diff --git a/scripts/msan_test.sh b/scripts/msan_test.sh index d47e8ccfe..021b2e9c6 100755 --- a/scripts/msan_test.sh +++ b/scripts/msan_test.sh @@ -14,19 +14,19 @@ # limitations under the License. # ============================================================================== echo "Testing All Bazel cc_tests with msan."; -test_outputs=$(bazel test -c opt --cxxopt="-D_GLIBCXX_USE_CXX11_ABI=1" \ +test_outputs=$(bazel test -c opt --cxxopt="-D_GLIBCXX_USE_CXX11_ABI=0" \ --cxxopt="-msse2" --cxxopt="-msse3" --cxxopt="-msse4" \ --cxxopt="-fsanitize=address" --linkopt="-fsanitize=address" \ --cxxopt="-g" --cxxopt="-O0" \ --notest_keep_going --test_output=errors \ //tensorflow_quantum/core/src:all && \ - bazel test -c opt --cxxopt="-D_GLIBCXX_USE_CXX11_ABI=1" \ + bazel test -c opt --cxxopt="-D_GLIBCXX_USE_CXX11_ABI=0" \ --cxxopt="-mavx2" --cxxopt="-mavx" --cxxopt="-mfma" \ --cxxopt="-fsanitize=address" --linkopt="-fsanitize=address" \ --cxxopt="-g" --cxxopt="-O0" \ --notest_keep_going --test_output=errors \ //tensorflow_quantum/core/src:all && \ - bazel test -c opt --cxxopt="-D_GLIBCXX_USE_CXX11_ABI=1" \ + bazel test -c opt --cxxopt="-D_GLIBCXX_USE_CXX11_ABI=0" \ --cxxopt="-fsanitize=address" --linkopt="-fsanitize=address" \ --cxxopt="-g" --cxxopt="-O0" \ --notest_keep_going --test_output=errors \ diff --git a/scripts/test_all.sh b/scripts/test_all.sh index 7a9fc7824..e5513bb12 100755 --- a/scripts/test_all.sh +++ b/scripts/test_all.sh @@ -14,7 +14,7 @@ # limitations under the License. # ============================================================================== echo "Testing All Bazel py_test and cc_tests."; -test_outputs=$(bazel test -c opt --experimental_repo_remote_exec --cxxopt="-D_GLIBCXX_USE_CXX11_ABI=1" --cxxopt="-std=c++17" --cxxopt="-msse2" --cxxopt="-msse3" --cxxopt="-msse4" --notest_keep_going --test_output=errors //tensorflow_quantum/...) +test_outputs=$(bazel test -c opt --experimental_repo_remote_exec --cxxopt="-D_GLIBCXX_USE_CXX11_ABI=0" --cxxopt="-msse2" --cxxopt="-msse3" --cxxopt="-msse4" --notest_keep_going --test_output=errors //tensorflow_quantum/...) exit_code=$? if [ "$exit_code" == "0" ]; then echo "Testing Complete!"; @@ -23,4 +23,4 @@ else echo "Testing failed, please correct errors before proceeding." echo "{$test_outputs}" exit 64; -fi +fi \ No newline at end of file diff --git a/scripts/test_benchmarks.sh b/scripts/test_benchmarks.sh index 07e3adec1..d969a0d29 100644 --- a/scripts/test_benchmarks.sh +++ b/scripts/test_benchmarks.sh @@ -14,10 +14,10 @@ # limitations under the License. # ============================================================================== 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)) +bazel test -c opt --cxxopt="-D_GLIBCXX_USE_CXX11_ABI=0" --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=0" --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) +# bench_outputs=$(bazel run -c opt --cxxopt="-D_GLIBCXX_USE_CXX11_ABI=0" --cxxopt="-msse2" --cxxopt="-msse3" --cxxopt="-msse4" --test_output=errors //benchmarks/scripts:benchmark_clifford_circuit) exit_code=$? if [ "$exit_code" == "0" ]; then echo "Testing Complete!"; diff --git a/scripts/test_tutorials.py b/scripts/test_tutorials.py index 1650caf15..13df27aef 100644 --- a/scripts/test_tutorials.py +++ b/scripts/test_tutorials.py @@ -18,7 +18,7 @@ from absl.testing import parameterized import nbformat -import nbclient +import nbconvert import tensorflow as tf # Must be run from the directory containing `quantum` repo. @@ -46,7 +46,9 @@ def test_notebook(self, path): src = re.sub('n_epochs ?= ?.*', 'n_epochs = 2', src) cell['source'] = src - _ = nbclient.execute(nb, timeout=900, kernel_name="python3") + _ = nbconvert.preprocessors.execute.executenb(nb, + timeout=900, + kernel_name="python3") if __name__ == "__main__": diff --git a/tensorflow_quantum/core/ops/BUILD b/tensorflow_quantum/core/ops/BUILD index 8087a8d3b..8a534229b 100644 --- a/tensorflow_quantum/core/ops/BUILD +++ b/tensorflow_quantum/core/ops/BUILD @@ -55,7 +55,7 @@ cc_binary( "-DNOGDI", "/d2ReducedOptimizeHugeFunctions", "/arch:AVX", - "/std:c++17", + "/std:c++14", "-DTENSORFLOW_MONOLITHIC_BUILD", "/DPLATFORM_WINDOWS", "/DEIGEN_HAS_C99_MATH", @@ -69,8 +69,8 @@ cc_binary( ], "//conditions:default": [ "-pthread", - "-std=c++17", - "-D_GLIBCXX_USE_CXX11_ABI=1", + "-std=c++14", + "-D_GLIBCXX_USE_CXX11_ABI=0", ], }), features = select({ @@ -118,7 +118,7 @@ cc_binary( "-DNOGDI", "/d2ReducedOptimizeHugeFunctions", "/arch:AVX", - "/std:c++17", + "/std:c++14", "-DTENSORFLOW_MONOLITHIC_BUILD", "/DPLATFORM_WINDOWS", "/DEIGEN_HAS_C99_MATH", @@ -132,8 +132,8 @@ cc_binary( ], "//conditions:default": [ "-pthread", - "-std=c++17", - "-D_GLIBCXX_USE_CXX11_ABI=1", + "-std=c++14", + "-D_GLIBCXX_USE_CXX11_ABI=0", ], }), features = select({ @@ -176,7 +176,7 @@ cc_binary( "-DNOGDI", "/d2ReducedOptimizeHugeFunctions", "/arch:AVX", - "/std:c++17", + "/std:c++14", "-DTENSORFLOW_MONOLITHIC_BUILD", "/DPLATFORM_WINDOWS", "/DEIGEN_HAS_C99_MATH", @@ -190,8 +190,8 @@ cc_binary( ], "//conditions:default": [ "-pthread", - "-std=c++17", - "-D_GLIBCXX_USE_CXX11_ABI=1", + "-std=c++14", + "-D_GLIBCXX_USE_CXX11_ABI=0", ], }), features = select({ @@ -242,7 +242,7 @@ cc_binary( "-DNOGDI", "/d2ReducedOptimizeHugeFunctions", "/arch:AVX", - "/std:c++17", + "/std:c++14", "-DTENSORFLOW_MONOLITHIC_BUILD", "/DPLATFORM_WINDOWS", "/DEIGEN_HAS_C99_MATH", @@ -256,8 +256,8 @@ cc_binary( ], "//conditions:default": [ "-pthread", - "-std=c++17", - "-D_GLIBCXX_USE_CXX11_ABI=1", + "-std=c++14", + "-D_GLIBCXX_USE_CXX11_ABI=0", ], }), features = select({ @@ -301,7 +301,7 @@ cc_library( "-DNOGDI", "/d2ReducedOptimizeHugeFunctions", "/arch:AVX", - "/std:c++17", + "/std:c++14", "-DTENSORFLOW_MONOLITHIC_BUILD", "/DPLATFORM_WINDOWS", "/DEIGEN_HAS_C99_MATH", @@ -315,8 +315,8 @@ cc_library( ], "//conditions:default": [ "-pthread", - "-std=c++17", - "-D_GLIBCXX_USE_CXX11_ABI=1", + "-std=c++14", + "-D_GLIBCXX_USE_CXX11_ABI=0", ], }), deps = [ @@ -354,7 +354,7 @@ cc_binary( "-DNOGDI", "/d2ReducedOptimizeHugeFunctions", "/arch:AVX", - "/std:c++17", + "/std:c++14", "-DTENSORFLOW_MONOLITHIC_BUILD", "/DPLATFORM_WINDOWS", "/DEIGEN_HAS_C99_MATH", @@ -368,8 +368,8 @@ cc_binary( ], "//conditions:default": [ "-pthread", - "-std=c++17", - "-D_GLIBCXX_USE_CXX11_ABI=1", + "-std=c++14", + "-D_GLIBCXX_USE_CXX11_ABI=0", ], }), features = select({ @@ -416,7 +416,7 @@ cc_library( "-DNOGDI", "/d2ReducedOptimizeHugeFunctions", "/arch:AVX", - "/std:c++17", + "/std:c++14", "-DTENSORFLOW_MONOLITHIC_BUILD", "/DPLATFORM_WINDOWS", "/DEIGEN_HAS_C99_MATH", @@ -430,8 +430,8 @@ cc_library( ], "//conditions:default": [ "-pthread", - "-std=c++17", - "-D_GLIBCXX_USE_CXX11_ABI=1", + "-std=c++14", + "-D_GLIBCXX_USE_CXX11_ABI=0", ], }), deps = [ diff --git a/tensorflow_quantum/core/ops/cirq_ops_test.py b/tensorflow_quantum/core/ops/cirq_ops_test.py index 1b54771a9..ffbfab1de 100644 --- a/tensorflow_quantum/core/ops/cirq_ops_test.py +++ b/tensorflow_quantum/core/ops/cirq_ops_test.py @@ -457,7 +457,7 @@ def run_sweep(self, program, params, repetitions): 'tfq': np.array([[1] * len(program.all_qubits())] * repetitions, - dtype=int), + dtype=np.int32), }) for param in cirq.to_resolvers(params) ] diff --git a/tensorflow_quantum/core/ops/math_ops/BUILD b/tensorflow_quantum/core/ops/math_ops/BUILD index 6eb8a0320..51bad72fb 100644 --- a/tensorflow_quantum/core/ops/math_ops/BUILD +++ b/tensorflow_quantum/core/ops/math_ops/BUILD @@ -38,7 +38,7 @@ cc_binary( "-DNOGDI", "/d2ReducedOptimizeHugeFunctions", "/arch:AVX", - "/std:c++17", + "/std:c++14", "-DTENSORFLOW_MONOLITHIC_BUILD", "/DPLATFORM_WINDOWS", "/DEIGEN_HAS_C99_MATH", @@ -52,8 +52,8 @@ cc_binary( ], "//conditions:default": [ "-pthread", - "-std=c++17", - "-D_GLIBCXX_USE_CXX11_ABI=1", + "-std=c++14", + "-D_GLIBCXX_USE_CXX11_ABI=0", ], }), features = select({ diff --git a/tensorflow_quantum/core/ops/math_ops/simulate_mps_test.py b/tensorflow_quantum/core/ops/math_ops/simulate_mps_test.py index ee7317b6a..1120b1392 100644 --- a/tensorflow_quantum/core/ops/math_ops/simulate_mps_test.py +++ b/tensorflow_quantum/core/ops/math_ops/simulate_mps_test.py @@ -934,10 +934,7 @@ def test_complex_equality(self): ] for _ in range(batch_size)] symbol_names = [] resolver_batch = [{} for _ in range(batch_size)] - # Because `pauli_sums` has inhomogeneous shape due to the different - # number of terms, `np.ones_like` failed with `pauli_sums`. - puali_sums_len = [[len(x) for x in y] for y in pauli_sums] - num_samples = np.ones_like(puali_sums_len, dtype=int) * 1000 + num_samples = np.ones_like(pauli_sums, dtype=np.int32) * 1000 symbol_values_array = np.array( [[resolver[symbol] diff --git a/tensorflow_quantum/core/ops/math_ops/tfq_inner_product.cc b/tensorflow_quantum/core/ops/math_ops/tfq_inner_product.cc index 74751f9cc..2a66d2919 100644 --- a/tensorflow_quantum/core/ops/math_ops/tfq_inner_product.cc +++ b/tensorflow_quantum/core/ops/math_ops/tfq_inner_product.cc @@ -87,7 +87,7 @@ class TfqInnerProductOp : public tensorflow::OpKernel { std::vector fused_circuits(programs.size(), QsimFusedCircuit({})); - Status parse_status = ::tensorflow::Status(); + Status parse_status = Status::OK(); auto p_lock = tensorflow::mutex(); auto construct_f = [&](int start, int end) { for (int i = start; i < end; i++) { @@ -314,7 +314,7 @@ REGISTER_OP("TfqInnerProduct") c->Dim(other_programs_shape, 1); c->set_output(0, c->Matrix(output_rows, output_cols)); - return ::tensorflow::Status(); + return tensorflow::Status::OK(); }); } // namespace tfq diff --git a/tensorflow_quantum/core/ops/math_ops/tfq_inner_product_grad.cc b/tensorflow_quantum/core/ops/math_ops/tfq_inner_product_grad.cc index 3db493b11..5b29571d2 100644 --- a/tensorflow_quantum/core/ops/math_ops/tfq_inner_product_grad.cc +++ b/tensorflow_quantum/core/ops/math_ops/tfq_inner_product_grad.cc @@ -112,7 +112,7 @@ class TfqInnerProductGradOp : public tensorflow::OpKernel { std::vector> gradient_gates( programs.size(), std::vector({})); - Status parse_status = ::tensorflow::Status(); + Status parse_status = Status::OK(); auto p_lock = tensorflow::mutex(); auto construct_f = [&](int start, int end) { for (int i = start; i < end; i++) { @@ -490,7 +490,7 @@ REGISTER_OP("TfqInnerProductGrad") {output_rows, tensorflow::shape_inference::InferenceContext::kUnknownDim})); - return ::tensorflow::Status(); + return tensorflow::Status::OK(); }); } // namespace tfq diff --git a/tensorflow_quantum/core/ops/math_ops/tfq_simulate_1d_expectation.cc b/tensorflow_quantum/core/ops/math_ops/tfq_simulate_1d_expectation.cc index c00b43a9b..adb1d9bb6 100644 --- a/tensorflow_quantum/core/ops/math_ops/tfq_simulate_1d_expectation.cc +++ b/tensorflow_quantum/core/ops/math_ops/tfq_simulate_1d_expectation.cc @@ -100,7 +100,7 @@ class TfqSimulateMPS1DExpectationOp : public tensorflow::OpKernel { std::vector qsim_circuits(programs.size(), QsimCircuit()); std::vector fused_circuits(programs.size(), QsimFusedCircuit({})); - Status parse_status = ::tensorflow::Status(); + Status parse_status = Status::OK(); auto p_lock = tensorflow::mutex(); auto construct_f = [&](int start, int end) { for (int i = start; i < end; i++) { @@ -153,7 +153,7 @@ class TfqSimulateMPS1DExpectationOp : public tensorflow::OpKernel { const int output_dim_op_size = output_tensor->dimension(1); - Status compute_status = ::tensorflow::Status(); + Status compute_status = Status::OK(); auto c_lock = tensorflow::mutex(); auto DoWork = [&](int start, int end) { int old_batch_index = -2; @@ -247,7 +247,7 @@ REGISTER_OP("TfqSimulateMPS1DExpectation") c->Dim(pauli_sums_shape, 1); c->set_output(0, c->Matrix(output_rows, output_cols)); - return ::tensorflow::Status(); + return tensorflow::Status::OK(); }); } // namespace tfq diff --git a/tensorflow_quantum/core/ops/math_ops/tfq_simulate_1d_sampled_expectation.cc b/tensorflow_quantum/core/ops/math_ops/tfq_simulate_1d_sampled_expectation.cc index ba94e8c72..750531f16 100644 --- a/tensorflow_quantum/core/ops/math_ops/tfq_simulate_1d_sampled_expectation.cc +++ b/tensorflow_quantum/core/ops/math_ops/tfq_simulate_1d_sampled_expectation.cc @@ -113,7 +113,7 @@ class TfqSimulateMPS1DSampledExpectationOp : public tensorflow::OpKernel { std::vector>> fused_circuits( programs.size(), std::vector>({})); - Status parse_status = ::tensorflow::Status(); + Status parse_status = Status::OK(); auto p_lock = tensorflow::mutex(); auto construct_f = [&](int start, int end) { for (int i = start; i < end; i++) { @@ -179,7 +179,7 @@ class TfqSimulateMPS1DSampledExpectationOp : public tensorflow::OpKernel { ->tensorflow_cpu_worker_threads() ->workers->NumThreads(); - Status compute_status = ::tensorflow::Status(); + Status compute_status = Status::OK(); auto c_lock = tensorflow::mutex(); auto DoWork = [&](int start, int end) { int old_batch_index = -2; @@ -291,7 +291,7 @@ REGISTER_OP("TfqSimulateMPS1DSampledExpectation") c->Dim(pauli_sums_shape, 1); c->set_output(0, c->Matrix(output_rows, output_cols)); - return ::tensorflow::Status(); + return tensorflow::Status::OK(); }); } // namespace tfq diff --git a/tensorflow_quantum/core/ops/math_ops/tfq_simulate_1d_samples.cc b/tensorflow_quantum/core/ops/math_ops/tfq_simulate_1d_samples.cc index 608f94689..495e5f8f2 100644 --- a/tensorflow_quantum/core/ops/math_ops/tfq_simulate_1d_samples.cc +++ b/tensorflow_quantum/core/ops/math_ops/tfq_simulate_1d_samples.cc @@ -85,7 +85,7 @@ class TfqSimulateMPS1DSamplesOp : public tensorflow::OpKernel { std::vector>> fused_circuits( programs.size(), std::vector>({})); - Status parse_status = ::tensorflow::Status(); + Status parse_status = Status::OK(); auto p_lock = tensorflow::mutex(); auto construct_f = [&](int start, int end) { for (int i = start; i < end; i++) { @@ -242,7 +242,7 @@ REGISTER_OP("TfqSimulateMPS1DSamples") tensorflow::shape_inference::InferenceContext::kUnknownDim, tensorflow::shape_inference::InferenceContext::kUnknownDim})); - return ::tensorflow::Status(); + return tensorflow::Status::OK(); }); } // namespace tfq diff --git a/tensorflow_quantum/core/ops/noise/BUILD b/tensorflow_quantum/core/ops/noise/BUILD index 3758037e5..a72665780 100644 --- a/tensorflow_quantum/core/ops/noise/BUILD +++ b/tensorflow_quantum/core/ops/noise/BUILD @@ -36,7 +36,7 @@ cc_binary( "-DNOGDI", "/d2ReducedOptimizeHugeFunctions", "/arch:AVX", - "/std:c++17", + "/std:c++14", "-DTENSORFLOW_MONOLITHIC_BUILD", "/DPLATFORM_WINDOWS", "/DEIGEN_HAS_C99_MATH", @@ -50,8 +50,8 @@ cc_binary( ], "//conditions:default": [ "-pthread", - "-std=c++17", - "-D_GLIBCXX_USE_CXX11_ABI=1", + "-std=c++14", + "-D_GLIBCXX_USE_CXX11_ABI=0", ], }), features = select({ diff --git a/tensorflow_quantum/core/ops/noise/tfq_noisy_expectation.cc b/tensorflow_quantum/core/ops/noise/tfq_noisy_expectation.cc index c67fa01f7..430b8d303 100644 --- a/tensorflow_quantum/core/ops/noise/tfq_noisy_expectation.cc +++ b/tensorflow_quantum/core/ops/noise/tfq_noisy_expectation.cc @@ -111,7 +111,7 @@ class TfqNoisyExpectationOp : public tensorflow::OpKernel { std::vector qsim_circuits(programs.size(), NoisyQsimCircuit()); - Status parse_status = ::tensorflow::Status(); + Status parse_status = Status::OK(); auto p_lock = tensorflow::mutex(); auto construct_f = [&](int start, int end) { for (int i = start; i < end; i++) { @@ -287,7 +287,7 @@ class TfqNoisyExpectationOp : public tensorflow::OpKernel { } random_gen.Init(tensorflow::random::New64(), tensorflow::random::New64()); - Status compute_status = ::tensorflow::Status(); + Status compute_status = Status::OK(); auto c_lock = tensorflow::mutex(); auto DoWork = [&](int start, int end) { // Begin simulation. @@ -418,7 +418,7 @@ REGISTER_OP("TfqNoisyExpectation") c->Dim(pauli_sums_shape, 1); c->set_output(0, c->Matrix(output_rows, output_cols)); - return ::tensorflow::Status(); + return tensorflow::Status::OK(); }); } // namespace tfq diff --git a/tensorflow_quantum/core/ops/noise/tfq_noisy_sampled_expectation.cc b/tensorflow_quantum/core/ops/noise/tfq_noisy_sampled_expectation.cc index aa0c85691..c6b66d861 100644 --- a/tensorflow_quantum/core/ops/noise/tfq_noisy_sampled_expectation.cc +++ b/tensorflow_quantum/core/ops/noise/tfq_noisy_sampled_expectation.cc @@ -112,7 +112,7 @@ class TfqNoisySampledExpectationOp : public tensorflow::OpKernel { std::vector qsim_circuits(programs.size(), NoisyQsimCircuit()); - Status parse_status = ::tensorflow::Status(); + Status parse_status = Status::OK(); auto p_lock = tensorflow::mutex(); auto construct_f = [&](int start, int end) { for (int i = start; i < end; i++) { @@ -294,7 +294,7 @@ class TfqNoisySampledExpectationOp : public tensorflow::OpKernel { } random_gen.Init(tensorflow::random::New64(), tensorflow::random::New64()); - Status compute_status = ::tensorflow::Status(); + Status compute_status = Status::OK(); auto c_lock = tensorflow::mutex(); auto DoWork = [&](int start, int end) { // Begin simulation. @@ -424,7 +424,7 @@ REGISTER_OP("TfqNoisySampledExpectation") c->Dim(pauli_sums_shape, 1); c->set_output(0, c->Matrix(output_rows, output_cols)); - return ::tensorflow::Status(); + return tensorflow::Status::OK(); }); } // namespace tfq diff --git a/tensorflow_quantum/core/ops/noise/tfq_noisy_samples.cc b/tensorflow_quantum/core/ops/noise/tfq_noisy_samples.cc index 341c87910..f8a102914 100644 --- a/tensorflow_quantum/core/ops/noise/tfq_noisy_samples.cc +++ b/tensorflow_quantum/core/ops/noise/tfq_noisy_samples.cc @@ -82,7 +82,7 @@ class TfqNoisySamplesOp : public tensorflow::OpKernel { std::vector qsim_circuits(programs.size(), NoisyQsimCircuit()); - Status parse_status = ::tensorflow::Status(); + Status parse_status = Status::OK(); auto p_lock = tensorflow::mutex(); auto construct_f = [&](int start, int end) { for (int i = start; i < end; i++) { @@ -343,7 +343,7 @@ REGISTER_OP("TfqNoisySamples") tensorflow::shape_inference::InferenceContext::kUnknownDim, tensorflow::shape_inference::InferenceContext::kUnknownDim})); - return ::tensorflow::Status(); + return tensorflow::Status::OK(); }); } // namespace tfq diff --git a/tensorflow_quantum/core/ops/parse_context.cc b/tensorflow_quantum/core/ops/parse_context.cc index f926d15bb..dd8f941fc 100644 --- a/tensorflow_quantum/core/ops/parse_context.cc +++ b/tensorflow_quantum/core/ops/parse_context.cc @@ -42,17 +42,16 @@ template Status ParseProto(const std::string& text, T* proto) { // First attempt to parse from the binary representation. if (proto->ParseFromString(text)) { - return ::tensorflow::Status(); + return Status::OK(); } // If that fails, then try to parse from the human readable representation. if (google::protobuf::TextFormat::ParseFromString(text, proto)) { - return ::tensorflow::Status(); + return Status::OK(); } - return Status( - static_cast(absl::StatusCode::kInvalidArgument), - "Unparseable proto: " + text); + return Status(tensorflow::error::INVALID_ARGUMENT, + "Unparseable proto: " + text); } } // namespace @@ -68,8 +67,7 @@ Status ParsePrograms(OpKernelContext* context, const std::string& input_name, if (input->dims() != 1) { // Never parse anything other than a 1d list of circuits. return Status( - static_cast( - absl::StatusCode::kInvalidArgument), + tensorflow::error::INVALID_ARGUMENT, absl::StrCat("programs must be rank 1. Got rank ", input->dims(), ".")); } @@ -88,7 +86,7 @@ Status ParsePrograms(OpKernelContext* context, const std::string& input_name, context->device()->tensorflow_cpu_worker_threads()->workers->ParallelFor( num_programs, cycle_estimate, DoWork); - return ::tensorflow::Status(); + return Status::OK(); } Status ParsePrograms2D(OpKernelContext* context, const std::string& input_name, @@ -101,8 +99,7 @@ Status ParsePrograms2D(OpKernelContext* context, const std::string& input_name, if (input->dims() != 2) { // Never parse anything other than a 1d list of circuits. - return Status(static_cast( - absl::StatusCode::kInvalidArgument), + return Status(tensorflow::error::INVALID_ARGUMENT, absl::StrCat("other_programs must be rank 2. Got rank ", input->dims(), ".")); } @@ -126,7 +123,7 @@ Status ParsePrograms2D(OpKernelContext* context, const std::string& input_name, context->device()->tensorflow_cpu_worker_threads()->workers->ParallelFor( num_programs * num_entries, cycle_estimate, DoWork); - return ::tensorflow::Status(); + return Status::OK(); } Status GetProgramsAndProgramsToAppend( @@ -143,12 +140,11 @@ Status GetProgramsAndProgramsToAppend( } if (programs->size() != programs_to_append->size()) { - return Status(static_cast( - absl::StatusCode::kInvalidArgument), + return Status(tensorflow::error::INVALID_ARGUMENT, "programs and programs_to_append must have matching sizes."); } - return ::tensorflow::Status(); + return Status::OK(); } Status GetProgramsAndNumQubits( @@ -171,8 +167,7 @@ Status GetProgramsAndNumQubits( } if (programs->size() != p_sums->size()) { return Status( - static_cast( - absl::StatusCode::kInvalidArgument), + tensorflow::error::INVALID_ARGUMENT, absl::StrCat("Number of circuits and PauliSums do not match. Got ", programs->size(), " circuits and ", p_sums->size(), " paulisums.")); @@ -202,7 +197,7 @@ Status GetProgramsAndNumQubits( context->device()->tensorflow_cpu_worker_threads()->workers->ParallelFor( num_qubits->size(), cycle_estimate, DoWork); - return ::tensorflow::Status(); + return Status::OK(); } tensorflow::Status GetProgramsAndNumQubits( @@ -223,8 +218,7 @@ tensorflow::Status GetProgramsAndNumQubits( } if (programs->size() != other_programs->size()) { - return Status(static_cast( - absl::StatusCode::kInvalidArgument), + return Status(tensorflow::error::INVALID_ARGUMENT, absl::StrCat("programs and other_programs batch dimension", " do not match. Foud: ", programs->size(), " and ", other_programs->size())); @@ -247,7 +241,7 @@ tensorflow::Status GetProgramsAndNumQubits( context->device()->tensorflow_cpu_worker_threads()->workers->ParallelFor( num_qubits->size(), cycle_estimate, DoWork); - return ::tensorflow::Status(); + return Status::OK(); } Status GetPauliSums(OpKernelContext* context, @@ -260,8 +254,7 @@ Status GetPauliSums(OpKernelContext* context, } if (input->dims() != 2) { - return Status(static_cast( - absl::StatusCode::kInvalidArgument), + return Status(tensorflow::error::INVALID_ARGUMENT, absl::StrCat("pauli_sums must be rank 2. Got rank ", input->dims(), ".")); } @@ -285,7 +278,7 @@ Status GetPauliSums(OpKernelContext* context, context->device()->tensorflow_cpu_worker_threads()->workers->ParallelFor( sum_specs.dimension(0) * sum_specs.dimension(1), cycle_estimate, DoWork); - return ::tensorflow::Status(); + return Status::OK(); } Status GetSymbolMaps(OpKernelContext* context, std::vector* maps) { @@ -297,8 +290,7 @@ Status GetSymbolMaps(OpKernelContext* context, std::vector* maps) { } if (input_names->dims() != 1) { - return Status(static_cast( - absl::StatusCode::kInvalidArgument), + return Status(tensorflow::error::INVALID_ARGUMENT, absl::StrCat("symbol_names must be rank 1. Got rank ", input_names->dims(), ".")); } @@ -310,8 +302,7 @@ Status GetSymbolMaps(OpKernelContext* context, std::vector* maps) { } if (input_values->dims() != 2) { - return Status(static_cast( - absl::StatusCode::kInvalidArgument), + return Status(tensorflow::error::INVALID_ARGUMENT, absl::StrCat("symbol_values must be rank 2. Got rank ", input_values->dims(), ".")); } @@ -320,8 +311,7 @@ Status GetSymbolMaps(OpKernelContext* context, std::vector* maps) { const auto symbol_values = input_values->matrix(); if (symbol_names.dimension(0) != symbol_values.dimension(1)) { - return Status(static_cast( - absl::StatusCode::kInvalidArgument), + return Status(tensorflow::error::INVALID_ARGUMENT, "Input symbol names and value sizes do not match."); } @@ -343,7 +333,7 @@ Status GetSymbolMaps(OpKernelContext* context, std::vector* maps) { context->device()->tensorflow_cpu_worker_threads()->workers->ParallelFor( symbol_values.dimension(0), cycle_estimate, DoWork); - return ::tensorflow::Status(); + return Status::OK(); } tensorflow::Status GetNumSamples( @@ -356,8 +346,7 @@ tensorflow::Status GetNumSamples( } if (input_num_samples->dims() != 2) { - return Status(static_cast( - absl::StatusCode::kInvalidArgument), + return Status(tensorflow::error::INVALID_ARGUMENT, absl::StrCat("num_samples must be rank 2. Got rank ", input_num_samples->dims(), ".")); } @@ -370,8 +359,7 @@ tensorflow::Status GetNumSamples( for (unsigned int j = 0; j < matrix_num_samples.dimension(1); j++) { const int num_samples = matrix_num_samples(i, j); if (num_samples < 1) { - return Status(static_cast( - absl::StatusCode::kInvalidArgument), + return Status(tensorflow::error::INVALID_ARGUMENT, "Each element of num_samples must be greater than 0."); } sub_parsed_num_samples.push_back(num_samples); @@ -379,7 +367,7 @@ tensorflow::Status GetNumSamples( parsed_num_samples->push_back(sub_parsed_num_samples); } - return ::tensorflow::Status(); + return Status::OK(); } // used by tfq_simulate_samples. @@ -392,8 +380,7 @@ Status GetIndividualSample(tensorflow::OpKernelContext* context, } if (input_num_samples->dims() != 1) { - return Status(static_cast( - absl::StatusCode::kInvalidArgument), + return Status(tensorflow::error::INVALID_ARGUMENT, absl::StrCat("num_samples must be rank 1. Got rank ", input_num_samples->dims(), ".")); } @@ -401,14 +388,13 @@ Status GetIndividualSample(tensorflow::OpKernelContext* context, const auto vector_num_samples = input_num_samples->vec(); if (vector_num_samples.dimension(0) != 1) { - return Status(static_cast( - absl::StatusCode::kInvalidArgument), + return Status(tensorflow::error::INVALID_ARGUMENT, absl::StrCat("num_samples must contain 1 element. Got ", vector_num_samples.dimension(0), ".")); } (*n_samples) = vector_num_samples(0); - return ::tensorflow::Status(); + return Status::OK(); } // used by adj_grad_op. @@ -422,8 +408,7 @@ tensorflow::Status GetPrevGrads( } if (input_grads->dims() != 2) { - return Status(static_cast( - absl::StatusCode::kInvalidArgument), + return Status(tensorflow::error::INVALID_ARGUMENT, absl::StrCat("downstream_grads must be rank 2. Got rank ", input_grads->dims(), ".")); } @@ -440,7 +425,7 @@ tensorflow::Status GetPrevGrads( parsed_prev_grads->push_back(sub_parsed_grads); } - return ::tensorflow::Status(); + return Status::OK(); } } // namespace tfq diff --git a/tensorflow_quantum/core/ops/tfq_adj_grad_op.cc b/tensorflow_quantum/core/ops/tfq_adj_grad_op.cc index e7252baee..7625c7962 100644 --- a/tensorflow_quantum/core/ops/tfq_adj_grad_op.cc +++ b/tensorflow_quantum/core/ops/tfq_adj_grad_op.cc @@ -99,7 +99,7 @@ class TfqAdjointGradientOp : public tensorflow::OpKernel { std::vector> gradient_gates( programs.size(), std::vector({})); - Status parse_status = ::tensorflow::Status(); + Status parse_status = Status::OK(); auto p_lock = tensorflow::mutex(); auto construct_f = [&](int start, int end) { for (int i = start; i < end; i++) { @@ -411,7 +411,7 @@ REGISTER_OP("TfqAdjointGradient") c->Dim(symbol_names_shape, 0); c->set_output(0, c->Matrix(output_rows, output_cols)); - return ::tensorflow::Status(); + return tensorflow::Status::OK(); }); } // namespace tfq diff --git a/tensorflow_quantum/core/ops/tfq_calculate_unitary_op.cc b/tensorflow_quantum/core/ops/tfq_calculate_unitary_op.cc index ace5327e1..b06a7faef 100644 --- a/tensorflow_quantum/core/ops/tfq_calculate_unitary_op.cc +++ b/tensorflow_quantum/core/ops/tfq_calculate_unitary_op.cc @@ -68,7 +68,7 @@ class TfqCalculateUnitaryOp : public tensorflow::OpKernel { std::vector>> fused_circuits( programs.size(), std::vector>({})); - Status parse_status = ::tensorflow::Status(); + Status parse_status = Status::OK(); auto p_lock = tensorflow::mutex(); auto construct_f = [&](int start, int end) { for (int i = start; i < end; i++) { @@ -182,7 +182,7 @@ REGISTER_OP("TfqCalculateUnitary") tensorflow::shape_inference::InferenceContext::kUnknownDim, tensorflow::shape_inference::InferenceContext::kUnknownDim})); - return ::tensorflow::Status(); + return tensorflow::Status::OK(); }); } // namespace tfq diff --git a/tensorflow_quantum/core/ops/tfq_circuit_append_op.cc b/tensorflow_quantum/core/ops/tfq_circuit_append_op.cc index 582bd1681..8109ccd56 100644 --- a/tensorflow_quantum/core/ops/tfq_circuit_append_op.cc +++ b/tensorflow_quantum/core/ops/tfq_circuit_append_op.cc @@ -90,7 +90,7 @@ REGISTER_OP("TfqAppendCircuit") c->set_output(0, c->input(0)); - return ::tensorflow::Status(); + return tensorflow::Status::OK(); }); } // namespace tfq diff --git a/tensorflow_quantum/core/ops/tfq_ps_decompose_op.cc b/tensorflow_quantum/core/ops/tfq_ps_decompose_op.cc index 669ea6368..f4355c07c 100644 --- a/tensorflow_quantum/core/ops/tfq_ps_decompose_op.cc +++ b/tensorflow_quantum/core/ops/tfq_ps_decompose_op.cc @@ -326,7 +326,7 @@ REGISTER_OP("TfqPsDecompose") c->set_output(0, c->input(0)); - return ::tensorflow::Status(); + return tensorflow::Status::OK(); }); } // namespace tfq diff --git a/tensorflow_quantum/core/ops/tfq_ps_symbol_replace_op.cc b/tensorflow_quantum/core/ops/tfq_ps_symbol_replace_op.cc index 559fbecc9..3423177b0 100644 --- a/tensorflow_quantum/core/ops/tfq_ps_symbol_replace_op.cc +++ b/tensorflow_quantum/core/ops/tfq_ps_symbol_replace_op.cc @@ -206,7 +206,7 @@ REGISTER_OP("TfqPsSymbolReplace") tensorflow::shape_inference::InferenceContext::kUnknownDim, tensorflow::shape_inference::InferenceContext::kUnknownDim})); - return ::tensorflow::Status(); + return tensorflow::Status::OK(); }); } // namespace tfq diff --git a/tensorflow_quantum/core/ops/tfq_ps_weights_from_symbols_op.cc b/tensorflow_quantum/core/ops/tfq_ps_weights_from_symbols_op.cc index 4a027223e..94aaf6641 100644 --- a/tensorflow_quantum/core/ops/tfq_ps_weights_from_symbols_op.cc +++ b/tensorflow_quantum/core/ops/tfq_ps_weights_from_symbols_op.cc @@ -184,7 +184,7 @@ REGISTER_OP("TfqPsWeightsFromSymbols") tensorflow::shape_inference::InferenceContext::kUnknownDim, tensorflow::shape_inference::InferenceContext::kUnknownDim})); - return ::tensorflow::Status(); + return tensorflow::Status::OK(); }); } // namespace tfq diff --git a/tensorflow_quantum/core/ops/tfq_resolve_parameters_op.cc b/tensorflow_quantum/core/ops/tfq_resolve_parameters_op.cc index 8d7ce06cf..3ef3277d2 100644 --- a/tensorflow_quantum/core/ops/tfq_resolve_parameters_op.cc +++ b/tensorflow_quantum/core/ops/tfq_resolve_parameters_op.cc @@ -59,7 +59,7 @@ class TfqResolveParametersOp : public tensorflow::OpKernel { "Number of circuits and values do not match. Got ", programs.size(), " circuits and ", maps.size(), " values."))); - Status parse_status = ::tensorflow::Status(); + Status parse_status = Status::OK(); auto p_lock = tensorflow::mutex(); auto DoWork = [&](int start, int end) { std::string temp; @@ -100,7 +100,7 @@ REGISTER_OP("TfqResolveParameters") c->set_output(0, c->input(0)); - return ::tensorflow::Status(); + return tensorflow::Status::OK(); }); } // namespace tfq diff --git a/tensorflow_quantum/core/ops/tfq_simulate_expectation_op.cc b/tensorflow_quantum/core/ops/tfq_simulate_expectation_op.cc index bca6d2f63..e8499f482 100644 --- a/tensorflow_quantum/core/ops/tfq_simulate_expectation_op.cc +++ b/tensorflow_quantum/core/ops/tfq_simulate_expectation_op.cc @@ -86,7 +86,7 @@ class TfqSimulateExpectationOp : public tensorflow::OpKernel { std::vector>> fused_circuits( programs.size(), std::vector>({})); - Status parse_status = ::tensorflow::Status(); + Status parse_status = Status::OK(); auto p_lock = tensorflow::mutex(); auto construct_f = [&](int start, int end) { for (int i = start; i < end; i++) { @@ -186,7 +186,7 @@ class TfqSimulateExpectationOp : public tensorflow::OpKernel { const int output_dim_op_size = output_tensor->dimension(1); - Status compute_status = ::tensorflow::Status(); + Status compute_status = Status::OK(); auto c_lock = tensorflow::mutex(); auto DoWork = [&](int start, int end) { int old_batch_index = -2; @@ -274,7 +274,7 @@ REGISTER_OP("TfqSimulateExpectation") c->Dim(pauli_sums_shape, 1); c->set_output(0, c->Matrix(output_rows, output_cols)); - return ::tensorflow::Status(); + return tensorflow::Status::OK(); }); } // namespace tfq diff --git a/tensorflow_quantum/core/ops/tfq_simulate_sampled_expectation_op.cc b/tensorflow_quantum/core/ops/tfq_simulate_sampled_expectation_op.cc index e0ed05a49..0452f2750 100644 --- a/tensorflow_quantum/core/ops/tfq_simulate_sampled_expectation_op.cc +++ b/tensorflow_quantum/core/ops/tfq_simulate_sampled_expectation_op.cc @@ -105,7 +105,7 @@ class TfqSimulateSampledExpectationOp : public tensorflow::OpKernel { std::vector>> fused_circuits( programs.size(), std::vector>({})); - Status parse_status = ::tensorflow::Status(); + Status parse_status = Status::OK(); auto p_lock = tensorflow::mutex(); auto construct_f = [&](int start, int end) { for (int i = start; i < end; i++) { @@ -231,7 +231,7 @@ class TfqSimulateSampledExpectationOp : public tensorflow::OpKernel { ->tensorflow_cpu_worker_threads() ->workers->NumThreads(); - Status compute_status = ::tensorflow::Status(); + Status compute_status = Status::OK(); auto c_lock = tensorflow::mutex(); auto DoWork = [&](int start, int end) { int old_batch_index = -2; @@ -333,7 +333,7 @@ REGISTER_OP("TfqSimulateSampledExpectation") c->Dim(pauli_sums_shape, 1); c->set_output(0, c->Matrix(output_rows, output_cols)); - return ::tensorflow::Status(); + return tensorflow::Status::OK(); }); } // namespace tfq diff --git a/tensorflow_quantum/core/ops/tfq_simulate_samples_op.cc b/tensorflow_quantum/core/ops/tfq_simulate_samples_op.cc index 0e68020e9..f9ea8c4a3 100644 --- a/tensorflow_quantum/core/ops/tfq_simulate_samples_op.cc +++ b/tensorflow_quantum/core/ops/tfq_simulate_samples_op.cc @@ -77,7 +77,7 @@ class TfqSimulateSamplesOp : public tensorflow::OpKernel { std::vector>> fused_circuits( programs.size(), std::vector>({})); - Status parse_status = ::tensorflow::Status(); + Status parse_status = Status::OK(); auto p_lock = tensorflow::mutex(); auto construct_f = [&](int start, int end) { for (int i = start; i < end; i++) { @@ -281,7 +281,7 @@ REGISTER_OP("TfqSimulateSamples") tensorflow::shape_inference::InferenceContext::kUnknownDim, tensorflow::shape_inference::InferenceContext::kUnknownDim})); - return ::tensorflow::Status(); + return tensorflow::Status::OK(); }); } // namespace tfq diff --git a/tensorflow_quantum/core/ops/tfq_simulate_state_op.cc b/tensorflow_quantum/core/ops/tfq_simulate_state_op.cc index e659800ce..6d74f18b0 100644 --- a/tensorflow_quantum/core/ops/tfq_simulate_state_op.cc +++ b/tensorflow_quantum/core/ops/tfq_simulate_state_op.cc @@ -69,7 +69,7 @@ class TfqSimulateStateOp : public tensorflow::OpKernel { std::vector>> fused_circuits( programs.size(), std::vector>({})); - Status parse_status = ::tensorflow::Status(); + Status parse_status = Status::OK(); auto p_lock = tensorflow::mutex(); auto construct_f = [&](int start, int end) { for (int i = start; i < end; i++) { @@ -238,7 +238,7 @@ REGISTER_OP("TfqSimulateState") {c->Dim(programs_shape, 0), tensorflow::shape_inference::InferenceContext::kUnknownDim})); - return ::tensorflow::Status(); + return tensorflow::Status::OK(); }); } // namespace tfq diff --git a/tensorflow_quantum/core/ops/tfq_utility_ops_test.py b/tensorflow_quantum/core/ops/tfq_utility_ops_test.py index 00c5ff791..8eab57ae7 100644 --- a/tensorflow_quantum/core/ops/tfq_utility_ops_test.py +++ b/tensorflow_quantum/core/ops/tfq_utility_ops_test.py @@ -82,7 +82,7 @@ def test_append_input_checking(self): # These tests really just makes sure we can cast output res = tfq_utility_ops.append_circuit([], []) - self.assertDTypeEqual(res.numpy().astype(str), np.dtype(' str: msg.arg_value.string_value = value elif (isinstance(value, (list, tuple, np.ndarray)) and all(isinstance(x, (bool, np.bool_)) for x in value)): - # Some protobuf / numpy combinations do not support bool_, so cast. + # Some protobuf / numpy combinations do not support np.bool_, so cast. msg.arg_value.bool_values.values.extend([bool(x) for x in value]) elif isinstance(value, sympy.Symbol): msg.symbol = str(value.free_symbols.pop()) diff --git a/tensorflow_quantum/core/serialize/op_serializer_test.py b/tensorflow_quantum/core/serialize/op_serializer_test.py index a485091e7..7597d6a47 100644 --- a/tensorflow_quantum/core/serialize/op_serializer_test.py +++ b/tensorflow_quantum/core/serialize/op_serializer_test.py @@ -108,7 +108,7 @@ def get_val(op): } } }), - (List[bool], np.array([True, False], dtype=np.bool_), { + (List[bool], np.array([True, False], dtype=np.bool), { 'arg_value': { 'bool_values': { 'values': [True, False] diff --git a/tensorflow_quantum/core/src/BUILD b/tensorflow_quantum/core/src/BUILD index 5595a5ca2..9e9bf3c17 100644 --- a/tensorflow_quantum/core/src/BUILD +++ b/tensorflow_quantum/core/src/BUILD @@ -21,7 +21,6 @@ cc_library( hdrs = ["adj_util.h"], deps = [ ":circuit_parser_qsim", - "@com_google_absl//absl/status", "@qsim//lib:circuit", "@qsim//lib:fuser", "@qsim//lib:fuser_basic", @@ -39,8 +38,6 @@ cc_test( ":adj_util", ":circuit_parser_qsim", "@com_google_googletest//:gtest_main", - "@com_google_absl//absl/status", - "@local_config_tf//:libtensorflow_framework", "@qsim//lib:gates_cirq", "@qsim//lib:matrix", ], @@ -55,7 +52,6 @@ cc_library( "//tensorflow_quantum/core/proto:program_cc_proto", "//tensorflow_quantum/core/proto:projector_sum_cc_proto", "@com_google_absl//absl/container:flat_hash_map", - "@com_google_absl//absl/status", "@local_config_tf//:libtensorflow_framework", "@local_config_tf//:tf_header_lib", "@qsim//lib:channel", @@ -131,7 +127,6 @@ cc_library( "@com_google_absl//absl/container:flat_hash_map", "@com_google_absl//absl/container:flat_hash_set", "@com_google_absl//absl/strings", - "@com_google_absl//absl/status", "@local_config_tf//:libtensorflow_framework", "@local_config_tf//:tf_header_lib", ], @@ -146,9 +141,7 @@ cc_test( ":program_resolution", "//tensorflow_quantum/core/proto:program_cc_proto", "@com_google_absl//absl/container:flat_hash_map", - "@com_google_absl//absl/status", "@com_google_googletest//:gtest_main", - "@local_config_tf//:libtensorflow_framework", "@local_config_tf//:tf_header_lib", ], ) diff --git a/tensorflow_quantum/core/src/circuit_parser_qsim.cc b/tensorflow_quantum/core/src/circuit_parser_qsim.cc index 1024d28c7..8a7b2d490 100644 --- a/tensorflow_quantum/core/src/circuit_parser_qsim.cc +++ b/tensorflow_quantum/core/src/circuit_parser_qsim.cc @@ -29,7 +29,6 @@ limitations under the License. #include "absl/container/flat_hash_map.h" #include "absl/strings/numbers.h" #include "absl/strings/str_split.h" -#include "absl/strings/string_view.h" #include "absl/types/optional.h" #include "tensorflow/core/lib/core/status.h" #include "tensorflow_quantum/core/proto/pauli_sum.pb.h" @@ -58,8 +57,7 @@ inline Status ParseProtoArg( // iterator> const auto arg_v = op.args().find(arg_name); if (arg_v == op.args().end()) { - return Status(static_cast( - absl::StatusCode::kInvalidArgument), + return Status(tensorflow::error::INVALID_ARGUMENT, "Could not find arg: " + arg_name + " in op."); } // find proto arg field. @@ -71,8 +69,7 @@ inline Status ParseProtoArg( const auto iter = param_map.find(proto_arg.symbol()); if (iter == param_map.end()) { return Status( - static_cast( - absl::StatusCode::kInvalidArgument), + tensorflow::error::INVALID_ARGUMENT, "Could not find symbol in parameter map: " + proto_arg.symbol()); } *result = iter->second.second; @@ -80,7 +77,7 @@ inline Status ParseProtoArg( symbol_used->emplace(iter->first); } } - return ::tensorflow::Status(); + return Status::OK(); } inline Status ParseProtoControls(const Operation& op, @@ -94,7 +91,7 @@ inline Status ParseProtoControls(const Operation& op, if (control_str == "" && control_v_str == "") { // empty default value set in serializer.py - return ::tensorflow::Status(); + return Status::OK(); } std::vector control_toks = @@ -103,12 +100,11 @@ inline Status ParseProtoControls(const Operation& op, absl::StrSplit(control_v_str, ','); if (control_toks.size() != control_v_toks.size()) { - return Status(static_cast( - absl::StatusCode::kInvalidArgument), + return Status(tensorflow::error::INVALID_ARGUMENT, "Mistmatched number of control qubits and control values."); } if (control_toks.empty()) { - return ::tensorflow::Status(); + return Status::OK(); } bool valid; unsigned int tmp; @@ -123,13 +119,12 @@ inline Status ParseProtoControls(const Operation& op, for (auto tok : control_v_toks) { valid = absl::SimpleAtoi(tok, &tmp); if (!valid) { - return Status(static_cast( - absl::StatusCode::kInvalidArgument), + return Status(tensorflow::error::INVALID_ARGUMENT, "Unparseable control value: " + std::string(tok)); } control_values->push_back(tmp); } - return ::tensorflow::Status(); + return Status::OK(); } inline Status OptionalInsertControls(const Operation& op, @@ -143,10 +138,10 @@ inline Status OptionalInsertControls(const Operation& op, return s; } if (control_qubits.empty()) { - return ::tensorflow::Status(); + return Status::OK(); } qsim::MakeControlledGate(control_qubits, control_values, *gate); - return ::tensorflow::Status(); + return Status::OK(); } // series of fixed signature gate builders. @@ -175,7 +170,7 @@ inline Status SingleConstantGate( info.index = circuit->gates.size() - 1; metadata->push_back(info); } - return ::tensorflow::Status(); + return Status::OK(); } // two qubit gate Create(time, q0, q1) @@ -201,7 +196,7 @@ inline Status TwoConstantGate( info.index = circuit->gates.size() - 1; metadata->push_back(info); } - return ::tensorflow::Status(); + return Status::OK(); } // single qubit eigen -> Create(time, q0, exponent, global_shift) @@ -250,7 +245,7 @@ inline Status SingleEigenGate( } metadata->push_back(info); } - return ::tensorflow::Status(); + return Status::OK(); } // two qubit eigen -> Create(time, q0, q1, exp, gs) @@ -301,7 +296,7 @@ inline Status TwoEigenGate( } metadata->push_back(info); } - return ::tensorflow::Status(); + return Status::OK(); } Status IGate(const Operation& op, const SymbolMap& param_map, @@ -452,7 +447,7 @@ inline Status PhasedXGate(const Operation& op, const SymbolMap& param_map, } metadata->push_back(info); } - return ::tensorflow::Status(); + return Status::OK(); } // two qubit fsim -> Create(time, q0, q1, theta, phi) @@ -509,7 +504,7 @@ inline Status FsimGate(const Operation& op, const SymbolMap& param_map, } metadata->push_back(info); } - return ::tensorflow::Status(); + return Status::OK(); } // two qubit phase iswap -> Create(time, q0, q1, pexp, exp) @@ -567,7 +562,7 @@ inline Status PhasedISwapGate(const Operation& op, const SymbolMap& param_map, } metadata->push_back(info); } - return ::tensorflow::Status(); + return Status::OK(); } tensorflow::Status ParseAppendGate(const Operation& op, @@ -595,8 +590,7 @@ tensorflow::Status ParseAppendGate(const Operation& op, auto build_f = func_map.find(op.gate().id()); if (build_f == func_map.end()) { *lookup_succeeded = false; - return Status(static_cast( - absl::StatusCode::kInvalidArgument), + return Status(tensorflow::error::INVALID_ARGUMENT, absl::StrCat("Could not parse gate id: ", op.gate().id(), ". This is likely because a cirq.Channel was " "used in an op that does not support them.")); @@ -624,7 +618,7 @@ inline Status AsymmetricDepolarizingChannel(const Operation& op, auto chan = qsim::Cirq::AsymmetricDepolarizingChannel::Create( time, num_qubits - q - 1, p_x, p_y, p_z); ncircuit->channels.push_back(chan); - return ::tensorflow::Status(); + return Status::OK(); } inline Status DepolarizingChannel(const Operation& op, @@ -644,7 +638,7 @@ inline Status DepolarizingChannel(const Operation& op, auto chan = qsim::Cirq::DepolarizingChannel::Create( time, num_qubits - q - 1, p); ncircuit->channels.push_back(chan); - return ::tensorflow::Status(); + return Status::OK(); } inline Status GADChannel(const Operation& op, const unsigned int num_qubits, @@ -667,7 +661,7 @@ inline Status GADChannel(const Operation& op, const unsigned int num_qubits, auto chan = qsim::Cirq::GeneralizedAmplitudeDampingChannel::Create( time, num_qubits - q - 1, p, gamma); ncircuit->channels.push_back(chan); - return ::tensorflow::Status(); + return Status::OK(); } inline Status ResetChannel(const Operation& op, const unsigned int num_qubits, @@ -679,7 +673,7 @@ inline Status ResetChannel(const Operation& op, const unsigned int num_qubits, auto chan = qsim::Cirq::ResetChannel::Create(time, num_qubits - q - 1); ncircuit->channels.push_back(chan); - return ::tensorflow::Status(); + return Status::OK(); } inline Status AmplitudeDampingChannel(const Operation& op, @@ -699,7 +693,7 @@ inline Status AmplitudeDampingChannel(const Operation& op, auto chan = qsim::Cirq::AmplitudeDampingChannel::Create( time, num_qubits - q - 1, gamma); ncircuit->channels.push_back(chan); - return ::tensorflow::Status(); + return Status::OK(); } inline Status PhaseDampingChannel(const Operation& op, @@ -720,7 +714,7 @@ inline Status PhaseDampingChannel(const Operation& op, auto chan = qsim::Cirq::PhaseDampingChannel::Create( time, num_qubits - q - 1, gamma); ncircuit->channels.push_back(chan); - return ::tensorflow::Status(); + return Status::OK(); } inline Status PhaseFlipChannel(const Operation& op, @@ -741,7 +735,7 @@ inline Status PhaseFlipChannel(const Operation& op, auto chan = qsim::Cirq::PhaseFlipChannel::Create(time, num_qubits - q - 1, p); ncircuit->channels.push_back(chan); - return ::tensorflow::Status(); + return Status::OK(); } inline Status BitFlipChannel(const Operation& op, const unsigned int num_qubits, @@ -761,7 +755,7 @@ inline Status BitFlipChannel(const Operation& op, const unsigned int num_qubits, auto chan = qsim::Cirq::BitFlipChannel::Create(time, num_qubits - q - 1, p); ncircuit->channels.push_back(chan); - return ::tensorflow::Status(); + return Status::OK(); } tensorflow::Status ParseAppendChannel(const Operation& op, @@ -780,8 +774,7 @@ tensorflow::Status ParseAppendChannel(const Operation& op, auto build_f = chan_func_map.find(op.gate().id()); if (build_f == chan_func_map.end()) { - return Status(static_cast( - absl::StatusCode::kInvalidArgument), + return Status(tensorflow::error::INVALID_ARGUMENT, absl::StrCat("Could not parse channel id: ", op.gate().id())); } return build_f->second(op, num_qubits, time, ncircuit); @@ -797,7 +790,7 @@ tensorflow::Status NoisyQsimCircuitFromProgram(const Program& program, // Special case empty. ncircuit->num_qubits = num_qubits; if (num_qubits <= 0) { - return ::tensorflow::Status(); + return Status::OK(); } int time = 0; @@ -841,7 +834,7 @@ tensorflow::Status NoisyQsimCircuitFromProgram(const Program& program, {qsim::gate::Measurement::Create(time, all_qbs)}}}); } - return ::tensorflow::Status(); + return Status::OK(); } tensorflow::Status QsimCircuitFromProgram( @@ -854,7 +847,7 @@ tensorflow::Status QsimCircuitFromProgram( bool unused; // Special case empty. if (num_qubits <= 0) { - return ::tensorflow::Status(); + return Status::OK(); } circuit->gates.reserve(program.circuit().moments_size() * num_qubits); @@ -876,7 +869,7 @@ tensorflow::Status QsimCircuitFromProgram( *fused_circuit = qsim::BasicGateFuser().FuseGates( qsim::BasicGateFuser::Parameter(), circuit->num_qubits, circuit->gates); - return ::tensorflow::Status(); + return Status::OK(); } Status QsimCircuitFromPauliTerm( diff --git a/tensorflow_quantum/core/src/circuit_parser_qsim_test.cc b/tensorflow_quantum/core/src/circuit_parser_qsim_test.cc index e6ea68e80..4cfb40424 100644 --- a/tensorflow_quantum/core/src/circuit_parser_qsim_test.cc +++ b/tensorflow_quantum/core/src/circuit_parser_qsim_test.cc @@ -149,7 +149,7 @@ TEST_P(TwoQubitEigenFixture, TwoEigenGate) { // Test case where we have a placeholder. ASSERT_EQ(QsimCircuitFromProgram(program_proto, symbol_map, 2, &test_circuit, &fused_circuit, &metadata), - ::tensorflow::Status()); + tensorflow::Status::OK()); AssertTwoQubitEqual(test_circuit.gates[0], ref_gate); EXPECT_EQ(metadata[0].index, 0); EXPECT_EQ(metadata[0].symbol_values[0], "placeholder"); @@ -172,7 +172,7 @@ TEST_P(TwoQubitEigenFixture, TwoEigenGate) { // Test case where we have all float values. ASSERT_EQ(QsimCircuitFromProgram(program_proto, symbol_map, 2, &test_circuit, &fused_circuit, &metadata), - ::tensorflow::Status()); + tensorflow::Status::OK()); AssertTwoQubitEqual(test_circuit.gates[0], ref_gate); EXPECT_EQ(metadata[0].index, 0); EXPECT_NEAR(metadata[0].gate_params[0], exp, 1e-5); @@ -191,8 +191,7 @@ TEST_P(TwoQubitEigenFixture, TwoEigenGate) { // Test case where proto arg missing. ASSERT_EQ(QsimCircuitFromProgram(program_proto, symbol_map, 2, &test_circuit, &fused_circuit), - tensorflow::Status(static_cast( - absl::StatusCode::kInvalidArgument), + tensorflow::Status(tensorflow::error::INVALID_ARGUMENT, "Could not find arg: exponent in op.")); test_circuit.gates.clear(); @@ -204,8 +203,7 @@ TEST_P(TwoQubitEigenFixture, TwoEigenGate) { ASSERT_EQ( QsimCircuitFromProgram(program_proto, symbol_map, 2, &test_circuit, &fused_circuit), - tensorflow::Status(static_cast( - absl::StatusCode::kInvalidArgument), + tensorflow::Status(tensorflow::error::INVALID_ARGUMENT, "Could not find symbol in parameter map: alpha")); } @@ -252,7 +250,7 @@ TEST_P(TwoQubitEigenFixture, TwoEigenGateControlled) { // Test case where we have a placeholder. ASSERT_EQ(QsimCircuitFromProgram(program_proto, symbol_map, 4, &test_circuit, &fused_circuit, &metadata), - ::tensorflow::Status()); + tensorflow::Status::OK()); AssertTwoQubitEqual(test_circuit.gates[0], ref_gate); EXPECT_EQ(metadata[0].index, 0); EXPECT_EQ(metadata[0].symbol_values[0], "placeholder"); @@ -321,7 +319,7 @@ TEST_P(SingleQubitEigenFixture, SingleEigenGate) { ASSERT_EQ(QsimCircuitFromProgram(program_proto, symbol_map, 1, &test_circuit, &fused_circuit, &metadata), - ::tensorflow::Status()); + tensorflow::Status::OK()); AssertOneQubitEqual(test_circuit.gates[0], ref_gate); EXPECT_EQ(metadata[0].index, 0); EXPECT_EQ(metadata[0].symbol_values[0], "placeholder"); @@ -344,7 +342,7 @@ TEST_P(SingleQubitEigenFixture, SingleEigenGate) { // Test case where we have all float values. ASSERT_EQ(QsimCircuitFromProgram(program_proto, symbol_map, 1, &test_circuit, &fused_circuit, &metadata), - ::tensorflow::Status()); + tensorflow::Status::OK()); AssertOneQubitEqual(test_circuit.gates[0], ref_gate); EXPECT_EQ(metadata[0].index, 0); EXPECT_NEAR(metadata[0].gate_params[0], exp, 1e-5); @@ -363,8 +361,7 @@ TEST_P(SingleQubitEigenFixture, SingleEigenGate) { // Test case where proto arg missing. ASSERT_EQ(QsimCircuitFromProgram(program_proto, symbol_map, 1, &test_circuit, &fused_circuit), - tensorflow::Status(static_cast( - absl::StatusCode::kInvalidArgument), + tensorflow::Status(tensorflow::error::INVALID_ARGUMENT, "Could not find arg: exponent in op.")); test_circuit.gates.clear(); @@ -376,8 +373,7 @@ TEST_P(SingleQubitEigenFixture, SingleEigenGate) { ASSERT_EQ( QsimCircuitFromProgram(program_proto, symbol_map, 1, &test_circuit, &fused_circuit), - tensorflow::Status(static_cast( - absl::StatusCode::kInvalidArgument), + tensorflow::Status(tensorflow::error::INVALID_ARGUMENT, "Could not find symbol in parameter map: alpha")); } @@ -422,7 +418,7 @@ TEST_P(SingleQubitEigenFixture, SingleEigenGateControlled) { ASSERT_EQ(QsimCircuitFromProgram(program_proto, symbol_map, 3, &test_circuit, &fused_circuit, &metadata), - ::tensorflow::Status()); + tensorflow::Status::OK()); AssertOneQubitEqual(test_circuit.gates[0], ref_gate); EXPECT_EQ(metadata[0].index, 0); EXPECT_EQ(metadata[0].symbol_values[0], "placeholder"); @@ -475,7 +471,7 @@ TEST(QsimCircuitParserTest, SingleConstantGate) { ASSERT_EQ(QsimCircuitFromProgram(program_proto, empty_map, 1, &test_circuit, &fused_circuit, &metadata), - ::tensorflow::Status()); + tensorflow::Status::OK()); AssertOneQubitEqual(test_circuit.gates[0], kv.second); EXPECT_EQ(metadata.size(), 1); EXPECT_EQ(metadata[0].placeholder_names.size(), 0); @@ -515,7 +511,7 @@ TEST(QsimCircuitParserTest, SingleConstantGateControlled) { ASSERT_EQ(QsimCircuitFromProgram(program_proto, empty_map, 3, &test_circuit, &fused_circuit, &metadata), - ::tensorflow::Status()); + tensorflow::Status::OK()); AssertOneQubitEqual(test_circuit.gates[0], kv.second); EXPECT_EQ(metadata.size(), 1); EXPECT_EQ(metadata[0].placeholder_names.size(), 0); @@ -557,7 +553,7 @@ TEST(QsimCircuitParserTest, TwoConstantGate) { ASSERT_EQ(QsimCircuitFromProgram(program_proto, empty_map, 2, &test_circuit, &fused_circuit, &metadata), - ::tensorflow::Status()); + tensorflow::Status::OK()); AssertTwoQubitEqual(test_circuit.gates[0], kv.second); EXPECT_EQ(metadata.size(), 1); EXPECT_EQ(metadata[0].placeholder_names.size(), 0); @@ -600,7 +596,7 @@ TEST(QsimCircuitParserTest, TwoConstantGateControlled) { ASSERT_EQ(QsimCircuitFromProgram(program_proto, empty_map, 4, &test_circuit, &fused_circuit, &metadata), - ::tensorflow::Status()); + tensorflow::Status::OK()); AssertTwoQubitEqual(test_circuit.gates[0], kv.second); EXPECT_EQ(metadata.size(), 1); EXPECT_EQ(metadata[0].placeholder_names.size(), 0); @@ -650,7 +646,7 @@ TEST(QsimCircuitParserTest, FsimGate) { // Test symbol resolution. ASSERT_EQ(QsimCircuitFromProgram(program_proto, symbol_map, 2, &test_circuit, &fused_circuit, &metadata), - ::tensorflow::Status()); + tensorflow::Status::OK()); AssertTwoQubitEqual(test_circuit.gates[0], reference); EXPECT_EQ(metadata.size(), 1); EXPECT_EQ(metadata[0].placeholder_names.size(), 2); @@ -677,7 +673,7 @@ TEST(QsimCircuitParserTest, FsimGate) { // Test float values only. ASSERT_EQ(QsimCircuitFromProgram(program_proto, symbol_map, 2, &test_circuit, &fused_circuit, &metadata), - ::tensorflow::Status()); + tensorflow::Status::OK()); AssertTwoQubitEqual(test_circuit.gates[0], reference); EXPECT_EQ(metadata.size(), 1); EXPECT_EQ(metadata[0].placeholder_names.size(), 0); @@ -695,8 +691,7 @@ TEST(QsimCircuitParserTest, FsimGate) { // Test case where proto arg missing. ASSERT_EQ(QsimCircuitFromProgram(program_proto, symbol_map, 2, &test_circuit, &fused_circuit), - tensorflow::Status(static_cast( - absl::StatusCode::kInvalidArgument), + tensorflow::Status(tensorflow::error::INVALID_ARGUMENT, "Could not find arg: theta in op.")); test_circuit.gates.clear(); @@ -708,8 +703,7 @@ TEST(QsimCircuitParserTest, FsimGate) { ASSERT_EQ( QsimCircuitFromProgram(program_proto, symbol_map, 2, &test_circuit, &fused_circuit), - tensorflow::Status(static_cast( - absl::StatusCode::kInvalidArgument), + tensorflow::Status(tensorflow::error::INVALID_ARGUMENT, "Could not find symbol in parameter map: alpha")); } @@ -755,7 +749,7 @@ TEST(QsimCircuitParserTest, FsimGateControlled) { // Test symbol resolution. ASSERT_EQ(QsimCircuitFromProgram(program_proto, symbol_map, 4, &test_circuit, &fused_circuit, &metadata), - ::tensorflow::Status()); + tensorflow::Status::OK()); AssertTwoQubitEqual(test_circuit.gates[0], reference); EXPECT_EQ(metadata.size(), 1); EXPECT_EQ(metadata[0].placeholder_names.size(), 2); @@ -814,7 +808,7 @@ TEST(QsimCircuitParserTest, PhasedISwap) { // Test symbol resolution. ASSERT_EQ(QsimCircuitFromProgram(program_proto, symbol_map, 2, &test_circuit, &fused_circuit, &metadata), - ::tensorflow::Status()); + tensorflow::Status::OK()); AssertTwoQubitEqual(test_circuit.gates[0], reference); EXPECT_EQ(metadata.size(), 1); EXPECT_EQ(metadata[0].placeholder_names.size(), 2); @@ -841,7 +835,7 @@ TEST(QsimCircuitParserTest, PhasedISwap) { // Test float values only. ASSERT_EQ(QsimCircuitFromProgram(program_proto, symbol_map, 2, &test_circuit, &fused_circuit, &metadata), - ::tensorflow::Status()); + tensorflow::Status::OK()); AssertTwoQubitEqual(test_circuit.gates[0], reference); EXPECT_EQ(metadata.size(), 1); EXPECT_EQ(metadata[0].placeholder_names.size(), 0); @@ -859,8 +853,7 @@ TEST(QsimCircuitParserTest, PhasedISwap) { // Test case where proto arg missing. ASSERT_EQ(QsimCircuitFromProgram(program_proto, symbol_map, 2, &test_circuit, &fused_circuit), - tensorflow::Status(static_cast( - absl::StatusCode::kInvalidArgument), + tensorflow::Status(tensorflow::error::INVALID_ARGUMENT, "Could not find arg: phase_exponent in op.")); test_circuit.gates.clear(); @@ -872,8 +865,7 @@ TEST(QsimCircuitParserTest, PhasedISwap) { ASSERT_EQ( QsimCircuitFromProgram(program_proto, symbol_map, 2, &test_circuit, &fused_circuit), - tensorflow::Status(static_cast( - absl::StatusCode::kInvalidArgument), + tensorflow::Status(tensorflow::error::INVALID_ARGUMENT, "Could not find symbol in parameter map: alpha")); } @@ -921,7 +913,7 @@ TEST(QsimCircuitParserTest, PhasedISwapControlled) { // Test symbol resolution. ASSERT_EQ(QsimCircuitFromProgram(program_proto, symbol_map, 4, &test_circuit, &fused_circuit, &metadata), - ::tensorflow::Status()); + tensorflow::Status::OK()); AssertTwoQubitEqual(test_circuit.gates[0], reference); EXPECT_EQ(metadata.size(), 1); EXPECT_EQ(metadata[0].placeholder_names.size(), 2); @@ -980,7 +972,7 @@ TEST(QsimCircuitParserTest, PhasedXPow) { // Test symbol resolution. ASSERT_EQ(QsimCircuitFromProgram(program_proto, symbol_map, 1, &test_circuit, &fused_circuit, &metadata), - ::tensorflow::Status()); + tensorflow::Status::OK()); AssertOneQubitEqual(test_circuit.gates[0], reference); EXPECT_EQ(metadata.size(), 1); EXPECT_EQ(metadata[0].placeholder_names.size(), 2); @@ -1009,7 +1001,7 @@ TEST(QsimCircuitParserTest, PhasedXPow) { // Test float values only. ASSERT_EQ(QsimCircuitFromProgram(program_proto, symbol_map, 1, &test_circuit, &fused_circuit, &metadata), - ::tensorflow::Status()); + tensorflow::Status::OK()); AssertOneQubitEqual(test_circuit.gates[0], reference); EXPECT_EQ(metadata.size(), 1); EXPECT_EQ(metadata[0].placeholder_names.size(), 0); @@ -1027,8 +1019,7 @@ TEST(QsimCircuitParserTest, PhasedXPow) { // Test case where proto arg missing. ASSERT_EQ(QsimCircuitFromProgram(program_proto, symbol_map, 1, &test_circuit, &fused_circuit), - tensorflow::Status(static_cast( - absl::StatusCode::kInvalidArgument), + tensorflow::Status(tensorflow::error::INVALID_ARGUMENT, "Could not find arg: phase_exponent in op.")); test_circuit.gates.clear(); @@ -1040,8 +1031,7 @@ TEST(QsimCircuitParserTest, PhasedXPow) { ASSERT_EQ( QsimCircuitFromProgram(program_proto, symbol_map, 1, &test_circuit, &fused_circuit), - tensorflow::Status(static_cast( - absl::StatusCode::kInvalidArgument), + tensorflow::Status(tensorflow::error::INVALID_ARGUMENT, "Could not find symbol in parameter map: alpha")); } @@ -1089,7 +1079,7 @@ TEST(QsimCircuitParserTest, PhasedXPowControlled) { // Test symbol resolution. ASSERT_EQ(QsimCircuitFromProgram(program_proto, symbol_map, 3, &test_circuit, &fused_circuit, &metadata), - ::tensorflow::Status()); + tensorflow::Status::OK()); AssertOneQubitEqual(test_circuit.gates[0], reference); EXPECT_EQ(metadata.size(), 1); EXPECT_EQ(metadata[0].placeholder_names.size(), 2); @@ -1134,8 +1124,7 @@ TEST(QsimCircuitParserTest, InvalidControlValues) { ASSERT_EQ(QsimCircuitFromProgram(program_proto, empty_map, 3, &test_circuit, &fused_circuit, &metadata), - tensorflow::Status(static_cast( - absl::StatusCode::kInvalidArgument), + tensorflow::Status(tensorflow::error::INVALID_ARGUMENT, "Unparseable control value: junk")); } @@ -1168,8 +1157,7 @@ TEST(QsimCircuitParserTest, MismatchControlNum) { ASSERT_EQ(QsimCircuitFromProgram(program_proto, empty_map, 3, &test_circuit, &fused_circuit, &metadata), tensorflow::Status( - static_cast( - absl::StatusCode::kInvalidArgument), + tensorflow::error::INVALID_ARGUMENT, "Mistmatched number of control qubits and control values.")); } @@ -1186,7 +1174,7 @@ TEST(QsimCircuitParserTest, EmptyTest) { // Ensure that nothing bad happens with an empty circuit. ASSERT_EQ(QsimCircuitFromProgram(program_proto, empty_map, 2, &test_circuit, &fused_circuit, &metadata), - ::tensorflow::Status()); + tensorflow::Status::OK()); ASSERT_EQ(test_circuit.gates.size(), 0); ASSERT_EQ(fused_circuit.size(), 0); ASSERT_EQ(metadata.size(), 0); @@ -1239,7 +1227,7 @@ TEST(QsimCircuitParserTest, CompoundCircuit) { ASSERT_EQ( NoisyQsimCircuitFromProgram(program_proto, {}, 2, true, &test_circuit), - ::tensorflow::Status()); + tensorflow::Status::OK()); AssertChannelEqual(test_circuit.channels[0], ref_chan); AssertOneQubitEqual(test_circuit.channels[1][0].ops[0], ref_gate); ASSERT_EQ(test_circuit.channels.size(), @@ -1282,7 +1270,7 @@ TEST(QsimCircuitParserTest, AsymmetricDepolarizing) { ASSERT_EQ( NoisyQsimCircuitFromProgram(program_proto, {}, 1, false, &test_circuit), - ::tensorflow::Status()); + tensorflow::Status::OK()); AssertChannelEqual(test_circuit.channels[0], reference); ASSERT_EQ(test_circuit.channels.size(), 1); ASSERT_EQ(test_circuit.num_qubits, 1); @@ -1319,7 +1307,7 @@ TEST(QsimCircuitParserTest, AmplitudeDamping) { ASSERT_EQ( NoisyQsimCircuitFromProgram(program_proto, {}, 1, false, &test_circuit), - ::tensorflow::Status()); + tensorflow::Status::OK()); AssertChannelEqual(test_circuit.channels[0], reference); ASSERT_EQ(test_circuit.channels.size(), 1); ASSERT_EQ(test_circuit.num_qubits, 1); @@ -1355,7 +1343,7 @@ TEST(QsimCircuitParserTest, Depolarizing) { ASSERT_EQ( NoisyQsimCircuitFromProgram(program_proto, {}, 1, false, &test_circuit), - ::tensorflow::Status()); + tensorflow::Status::OK()); AssertChannelEqual(test_circuit.channels[0], reference); ASSERT_EQ(test_circuit.channels.size(), 1); ASSERT_EQ(test_circuit.num_qubits, 1); @@ -1395,7 +1383,7 @@ TEST(QsimCircuitParserTest, GeneralizedAmplitudeDamping) { ASSERT_EQ( NoisyQsimCircuitFromProgram(program_proto, {}, 1, false, &test_circuit), - ::tensorflow::Status()); + tensorflow::Status::OK()); AssertChannelEqual(test_circuit.channels[0], reference); ASSERT_EQ(test_circuit.channels.size(), 1); ASSERT_EQ(test_circuit.num_qubits, 1); @@ -1429,7 +1417,7 @@ TEST(QsimCircuitParserTest, Reset) { ASSERT_EQ( NoisyQsimCircuitFromProgram(program_proto, {}, 1, false, &test_circuit), - ::tensorflow::Status()); + tensorflow::Status::OK()); AssertChannelEqual(test_circuit.channels[0], reference); ASSERT_EQ(test_circuit.channels.size(), 1); ASSERT_EQ(test_circuit.num_qubits, 1); @@ -1465,7 +1453,7 @@ TEST(QsimCircuitParserTest, PhaseDamping) { ASSERT_EQ( NoisyQsimCircuitFromProgram(program_proto, {}, 1, false, &test_circuit), - ::tensorflow::Status()); + tensorflow::Status::OK()); AssertChannelEqual(test_circuit.channels[0], reference); ASSERT_EQ(test_circuit.channels.size(), 1); ASSERT_EQ(test_circuit.num_qubits, 1); @@ -1501,7 +1489,7 @@ TEST(QsimCircuitParserTest, PhaseFlip) { ASSERT_EQ( NoisyQsimCircuitFromProgram(program_proto, {}, 1, false, &test_circuit), - ::tensorflow::Status()); + tensorflow::Status::OK()); AssertChannelEqual(test_circuit.channels[0], reference); ASSERT_EQ(test_circuit.channels.size(), 1); ASSERT_EQ(test_circuit.num_qubits, 1); @@ -1537,7 +1525,7 @@ TEST(QsimCircuitParserTest, BitFlip) { ASSERT_EQ( NoisyQsimCircuitFromProgram(program_proto, {}, 1, false, &test_circuit), - ::tensorflow::Status()); + tensorflow::Status::OK()); AssertChannelEqual(test_circuit.channels[0], reference); ASSERT_EQ(test_circuit.channels.size(), 1); ASSERT_EQ(test_circuit.num_qubits, 1); @@ -1552,7 +1540,7 @@ TEST(QsimCircuitParserTest, NoisyEmpty) { NoisyQsimCircuit test_circuit; ASSERT_EQ( NoisyQsimCircuitFromProgram(program_proto, {}, 0, false, &test_circuit), - ::tensorflow::Status()); + tensorflow::Status::OK()); ASSERT_EQ(test_circuit.channels.size(), 0); ASSERT_EQ(test_circuit.num_qubits, 0); } @@ -1571,8 +1559,7 @@ TEST(QsimCircuitParserTest, NoisyBadProto) { NoisyQsimCircuit test_circuit; ASSERT_EQ( NoisyQsimCircuitFromProgram(program_proto, {}, 1, false, &test_circuit), - tensorflow::Status(static_cast( - absl::StatusCode::kInvalidArgument), + tensorflow::Status(tensorflow::error::INVALID_ARGUMENT, "Could not parse channel id: ABCDEFG")); } @@ -1593,7 +1580,7 @@ TEST(QsimCircuitParserTest, CircuitFromPauliTermPauli) { // Check conversion status = QsimCircuitFromPauliTerm(pauli_proto, 1, &test_circuit, &fused_circuit); - ASSERT_EQ(status, tensorflow::Status()); + ASSERT_EQ(status, tensorflow::Status::OK()); ASSERT_EQ(test_circuit.num_qubits, 1); ASSERT_EQ(test_circuit.gates.size(), 1); AssertOneQubitEqual(test_circuit.gates[0], reference); @@ -1606,7 +1593,7 @@ TEST(QsimCircuitParserTest, CircuitFromPauliTermEmpty) { std::vector> fused_circuit; status = QsimCircuitFromPauliTerm(pauli_proto, 0, &test_circuit, &fused_circuit); - ASSERT_EQ(status, tensorflow::Status()); + ASSERT_EQ(status, tensorflow::Status::OK()); ASSERT_EQ(test_circuit.num_qubits, 0); ASSERT_EQ(test_circuit.gates.size(), 0); } @@ -1628,7 +1615,7 @@ TEST(QsimCircuitParserTest, ZBasisCircuitFromPauliTermPauliX) { // Check conversion status = QsimZBasisCircuitFromPauliTerm(pauli_proto, 1, &test_circuit, &fused_circuit); - ASSERT_EQ(status, tensorflow::Status()); + ASSERT_EQ(status, tensorflow::Status::OK()); ASSERT_EQ(test_circuit.num_qubits, 1); ASSERT_EQ(test_circuit.gates.size(), 1); AssertOneQubitEqual(test_circuit.gates[0], reference); @@ -1651,7 +1638,7 @@ TEST(QsimCircuitParserTest, ZBasisCircuitFromPauliTermPauliY) { // Check conversion status = QsimZBasisCircuitFromPauliTerm(pauli_proto, 1, &test_circuit, &fused_circuit); - ASSERT_EQ(status, tensorflow::Status()); + ASSERT_EQ(status, tensorflow::Status::OK()); ASSERT_EQ(test_circuit.num_qubits, 1); ASSERT_EQ(test_circuit.gates.size(), 1); AssertOneQubitEqual(test_circuit.gates[0], reference); @@ -1673,7 +1660,7 @@ TEST(QsimCircuitParserTest, ZBasisCircuitFromPauliTermPauliZ) { // Check conversion status = QsimZBasisCircuitFromPauliTerm(pauli_proto, 1, &test_circuit, &fused_circuit); - ASSERT_EQ(status, tensorflow::Status()); + ASSERT_EQ(status, tensorflow::Status::OK()); ASSERT_EQ(test_circuit.num_qubits, 1); ASSERT_EQ(test_circuit.gates.size(), 0); } @@ -1700,7 +1687,7 @@ TEST(QsimCircuitParserTest, ZBasisCircuitFromPauliTermPauliCompound) { // Check conversion status = QsimZBasisCircuitFromPauliTerm(pauli_proto, 2, &test_circuit, &fused_circuit); - ASSERT_EQ(status, tensorflow::Status()); + ASSERT_EQ(status, tensorflow::Status::OK()); ASSERT_EQ(test_circuit.num_qubits, 2); ASSERT_EQ(test_circuit.gates.size(), 2); AssertOneQubitEqual(test_circuit.gates[0], reference1); @@ -1714,7 +1701,7 @@ TEST(QsimCircuitParserTest, ZBasisCircuitFromPauliTermEmpty) { std::vector> fused_circuit; status = QsimZBasisCircuitFromPauliTerm(pauli_proto, 0, &test_circuit, &fused_circuit); - ASSERT_EQ(status, tensorflow::Status()); + ASSERT_EQ(status, tensorflow::Status::OK()); ASSERT_EQ(test_circuit.num_qubits, 0); ASSERT_EQ(test_circuit.gates.size(), 0); } diff --git a/tensorflow_quantum/core/src/program_resolution.cc b/tensorflow_quantum/core/src/program_resolution.cc index 0fbda9368..82af94d35 100644 --- a/tensorflow_quantum/core/src/program_resolution.cc +++ b/tensorflow_quantum/core/src/program_resolution.cc @@ -23,7 +23,6 @@ limitations under the License. #include "absl/strings/str_cat.h" #include "absl/strings/str_join.h" #include "absl/strings/str_split.h" -#include "absl/strings/string_view.h" #include "tensorflow/core/lib/core/error_codes.pb.h" #include "tensorflow/core/lib/core/status.h" #include "tensorflow_quantum/core/proto/pauli_sum.pb.h" @@ -47,14 +46,13 @@ inline absl::string_view IntMaxStr() { } Status RegisterQubits( - absl::string_view qb_string, + const std::string& qb_string, absl::flat_hash_set, std::string>>* id_set) { // Inserts qubits found in qb_string into id_set. // Supported GridQubit wire formats and line qubit wire formats. if (qb_string.empty()) { - return ::tensorflow::Status(); // no control-default value specified in - // serializer.py + return Status::OK(); // no control-default value specified in serializer.py } const std::vector qb_list = absl::StrSplit(qb_string, ','); @@ -66,25 +64,22 @@ Status RegisterQubits( } if (splits.size() != 2) { - return Status(static_cast( - absl::StatusCode::kInvalidArgument), + return Status(tensorflow::error::INVALID_ARGUMENT, absl::StrCat("Unable to parse qubit: ", qb)); } if (!absl::SimpleAtoi(splits[0], &r)) { - return Status(static_cast( - absl::StatusCode::kInvalidArgument), + return Status(tensorflow::error::INVALID_ARGUMENT, absl::StrCat("Unable to parse qubit: ", qb)); } if (!absl::SimpleAtoi(splits[1], &c)) { - return Status(static_cast( - absl::StatusCode::kInvalidArgument), + return Status(tensorflow::error::INVALID_ARGUMENT, absl::StrCat("Unable to parse qubit: ", qb)); } auto locs = std::pair, std::string>( std::pair(r, c), std::string(qb)); id_set->insert(locs); } - return ::tensorflow::Status(); + return Status::OK(); } Status ResolveQubitIds(Program* program, unsigned int* num_qubits, @@ -94,7 +89,7 @@ Status ResolveQubitIds(Program* program, unsigned int* num_qubits, // (#679) Just ignore empty program. // Number of qubits in empty programs is zero. *num_qubits = 0; - return ::tensorflow::Status(); + return Status::OK(); } absl::flat_hash_set, std::string>> id_set; @@ -172,8 +167,7 @@ Status ResolveQubitIds(Program* program, unsigned int* num_qubits, const auto result = id_to_index.find(pair.qubit_id()); if (result == id_to_index.end()) { return Status( - static_cast( - absl::StatusCode::kInvalidArgument), + tensorflow::error::INVALID_ARGUMENT, "Found a Pauli sum operating on qubits not found in circuit."); } pair.set_qubit_id(result->second); @@ -182,7 +176,7 @@ Status ResolveQubitIds(Program* program, unsigned int* num_qubits, } } - return ::tensorflow::Status(); + return Status::OK(); } Status ResolveQubitIds(Program* program, unsigned int* num_qubits, @@ -191,7 +185,7 @@ Status ResolveQubitIds(Program* program, unsigned int* num_qubits, // (#679) Just ignore empty program. // Number of qubits in empty programs is zero. *num_qubits = 0; - return ::tensorflow::Status(); + return Status::OK(); } absl::flat_hash_set, std::string>> id_set; @@ -264,8 +258,7 @@ Status ResolveQubitIds(Program* program, unsigned int* num_qubits, visited_qubits.erase(qubit.id()); const auto result = id_to_index.find(qubit.id()); if (result == id_to_index.end()) { - return Status(static_cast( - absl::StatusCode::kInvalidArgument), + return Status(tensorflow::error::INVALID_ARGUMENT, "A paired circuit contains qubits not found in " "reference circuit."); } @@ -287,8 +280,7 @@ Status ResolveQubitIds(Program* program, unsigned int* num_qubits, visited_qubits.erase(id); const auto result = id_to_index.find(id); if (result == id_to_index.end()) { - return Status(static_cast( - absl::StatusCode::kInvalidArgument), + return Status(tensorflow::error::INVALID_ARGUMENT, "A paired circuit contains qubits not found in " "reference circuit."); } @@ -302,13 +294,12 @@ Status ResolveQubitIds(Program* program, unsigned int* num_qubits, } if (!visited_qubits.empty()) { return Status( - static_cast( - absl::StatusCode::kInvalidArgument), + tensorflow::error::INVALID_ARGUMENT, "A reference circuit contains qubits not found in paired circuit."); } } - return ::tensorflow::Status(); + return Status::OK(); } Status ResolveSymbols( @@ -323,8 +314,7 @@ Status ResolveSymbols( if (iter == param_map.end()) { if (resolve_all) { return Status( - static_cast( - absl::StatusCode::kInvalidArgument), + tensorflow::error::INVALID_ARGUMENT, "Could not find symbol in parameter map: " + arg.symbol()); } continue; @@ -335,7 +325,7 @@ Status ResolveSymbols( } } - return ::tensorflow::Status(); + return Status::OK(); } Status CheckMPSSupported(const Program& program) { @@ -344,7 +334,7 @@ Status CheckMPSSupported(const Program& program) { // // Requires: program have qubit ids resolved. if (program.circuit().moments().empty()) { - return ::tensorflow::Status(); + return Status::OK(); } for (auto moment : program.circuit().moments()) { @@ -364,8 +354,7 @@ Status CheckMPSSupported(const Program& program) { const int total_num_qubits = qubits.size() + control_ids.size(); if (total_num_qubits > 2) { return Status( - static_cast( - absl::StatusCode::kInvalidArgument), + tensorflow::error::INVALID_ARGUMENT, absl::StrCat("1D operations only support 1 and 2 qubit gates. " "Found: ", total_num_qubits, " qubit gate.")); @@ -383,8 +372,7 @@ Status CheckMPSSupported(const Program& program) { // Are the two qubits not neighbors? if (std::abs((int)qids[0] - (int)qids[1]) > 1) { - return Status(static_cast( - absl::StatusCode::kInvalidArgument), + return Status(tensorflow::error::INVALID_ARGUMENT, "A program is not in 1D topology. It contains an" " operation with qubits not neighbors each other."); } @@ -392,7 +380,7 @@ Status CheckMPSSupported(const Program& program) { } } - return ::tensorflow::Status(); + return Status::OK(); } } // namespace tfq diff --git a/tensorflow_quantum/core/src/program_resolution_test.cc b/tensorflow_quantum/core/src/program_resolution_test.cc index 2a4e61151..74a200b13 100644 --- a/tensorflow_quantum/core/src/program_resolution_test.cc +++ b/tensorflow_quantum/core/src/program_resolution_test.cc @@ -187,7 +187,7 @@ TEST(ProgramResolutionTest, ResolveQubitIdsValid) { ASSERT_TRUE( google::protobuf::TextFormat::ParseFromString(valid_program, &program)); - EXPECT_EQ(ResolveQubitIds(&program, &qubit_count), Status()); + EXPECT_EQ(ResolveQubitIds(&program, &qubit_count), Status::OK()); EXPECT_EQ(qubit_count, 3); EXPECT_EQ(program.circuit().moments(0).operations(0).qubits(0).id(), "1"); EXPECT_EQ(program.circuit().moments(0).operations(0).qubits(1).id(), "2"); @@ -207,7 +207,7 @@ TEST(ProgramResolutionTest, ResolveQubitIdsValidLine) { ASSERT_TRUE(google::protobuf::TextFormat::ParseFromString(valid_line_program, &program)); - EXPECT_EQ(ResolveQubitIds(&program, &qubit_count), Status()); + EXPECT_EQ(ResolveQubitIds(&program, &qubit_count), Status::OK()); EXPECT_EQ(qubit_count, 3); EXPECT_EQ(program.circuit().moments(0).operations(0).qubits(0).id(), "1"); EXPECT_EQ(program.circuit().moments(0).operations(0).qubits(1).id(), "2"); @@ -235,8 +235,7 @@ TEST(ProgramResolutionTest, ResolveQubitIdsInvalidControlQubit) { .mutable_arg_value() ->set_string_value("junk"); EXPECT_EQ(ResolveQubitIds(&program, &qubit_count), - tensorflow::Status(static_cast( - absl::StatusCode::kInvalidArgument), + tensorflow::Status(tensorflow::error::INVALID_ARGUMENT, "Unable to parse qubit: junk")); } @@ -252,8 +251,7 @@ TEST(ProgramResolutionTest, ResolveQubitIdsInvalidQubit) { ->mutable_qubits(0) ->set_id("junk"); EXPECT_EQ(ResolveQubitIds(&program, &qubit_count), - tensorflow::Status(static_cast( - absl::StatusCode::kInvalidArgument), + tensorflow::Status(tensorflow::error::INVALID_ARGUMENT, "Unable to parse qubit: junk")); } @@ -268,7 +266,7 @@ TEST(ProgramResolutionTest, ResolveQubitIdsWithPauliSum) { google::protobuf::TextFormat::ParseFromString(valid_psum, &p_sum)); std::vector p_sums = {p_sum, p_sum}; - EXPECT_EQ(ResolveQubitIds(&program, &qubit_count, &p_sums), Status()); + EXPECT_EQ(ResolveQubitIds(&program, &qubit_count, &p_sums), Status::OK()); EXPECT_EQ(qubit_count, 3); EXPECT_EQ(program.circuit().moments(0).operations(0).qubits(0).id(), "1"); EXPECT_EQ(program.circuit().moments(0).operations(0).qubits(1).id(), "2"); @@ -302,8 +300,7 @@ TEST(ProgramResolutionTest, ResolveQubitIdsWithInvalidPauliSum) { EXPECT_EQ(ResolveQubitIds(&program, &qubit_count, &p_sums), tensorflow::Status( - static_cast( - absl::StatusCode::kInvalidArgument), + tensorflow::error::INVALID_ARGUMENT, "Found a Pauli sum operating on qubits not found in circuit.")); } @@ -330,7 +327,8 @@ TEST(ProgramResolutionTest, ResolveQubitIdsMultiProgram) { ->set_string_value("0_2"); // turn 0_0 -> 0_2! std::vector other_programs = {other, other}; - EXPECT_EQ(ResolveQubitIds(&program, &qubit_count, &other_programs), Status()); + EXPECT_EQ(ResolveQubitIds(&program, &qubit_count, &other_programs), + Status::OK()); EXPECT_EQ(qubit_count, 3); EXPECT_EQ(program.circuit().moments(0).operations(0).qubits(0).id(), "1"); EXPECT_EQ(program.circuit().moments(0).operations(0).qubits(1).id(), "2"); @@ -376,8 +374,7 @@ TEST(ProgramResolutionTest, ResolveQubitIdsMultiProgramInvalid) { ->set_id("junk"); std::vector others = {other, other}; EXPECT_EQ(ResolveQubitIds(&program, &qubit_count, &others), - tensorflow::Status(static_cast( - absl::StatusCode::kInvalidArgument), + tensorflow::Status(tensorflow::error::INVALID_ARGUMENT, "Unable to parse qubit: junk")); } @@ -397,8 +394,7 @@ TEST(ProgramResolutionTest, ResolveQubitIdsMultiProgramInvalidControl) { ->set_string_value("junk"); std::vector others = {other, other}; EXPECT_EQ(ResolveQubitIds(&program, &qubit_count, &others), - tensorflow::Status(static_cast( - absl::StatusCode::kInvalidArgument), + tensorflow::Status(tensorflow::error::INVALID_ARGUMENT, "Unable to parse qubit: junk")); } @@ -418,8 +414,7 @@ TEST(ProgramResolutionTest, ResolveQubitIdsMultiProgramMismatch) { EXPECT_EQ( ResolveQubitIds(&program, &qubit_count, &others), tensorflow::Status( - static_cast( - absl::StatusCode::kInvalidArgument), + tensorflow::error::INVALID_ARGUMENT, "A paired circuit contains qubits not found in reference circuit.")); } @@ -441,8 +436,7 @@ TEST(ProgramResolutionTest, ResolveQubitIdsMultiProgramMismatchControl) { EXPECT_EQ( ResolveQubitIds(&program, &qubit_count, &others), tensorflow::Status( - static_cast( - absl::StatusCode::kInvalidArgument), + tensorflow::error::INVALID_ARGUMENT, "A paired circuit contains qubits not found in reference circuit.")); } @@ -462,8 +456,7 @@ TEST(ProgramResolutionTest, ResolveQubitIdsMultiProgramSmaller) { EXPECT_EQ( ResolveQubitIds(&program, &qubit_count, &others), tensorflow::Status( - static_cast( - absl::StatusCode::kInvalidArgument), + tensorflow::error::INVALID_ARGUMENT, "A reference circuit contains qubits not found in paired circuit.")); } @@ -485,8 +478,7 @@ TEST(ProgramResolutionTest, ResolveQubitIdsMultiProgramSmallerControl) { EXPECT_EQ( ResolveQubitIds(&program, &qubit_count, &others), tensorflow::Status( - static_cast( - absl::StatusCode::kInvalidArgument), + tensorflow::error::INVALID_ARGUMENT, "A reference circuit contains qubits not found in paired circuit.")); } @@ -496,7 +488,7 @@ TEST(ProgramResolutionTest, ResolveSymbolsPartial) { valid_symbol_program, &symbol_program)); const absl::flat_hash_map> param_map = { {"v1", {0, 1.0}}}; - EXPECT_EQ(ResolveSymbols(param_map, &symbol_program, false), Status()); + EXPECT_EQ(ResolveSymbols(param_map, &symbol_program, false), Status::OK()); EXPECT_EQ(symbol_program.circuit() .moments(0) .operations(0) @@ -520,7 +512,7 @@ TEST(ProgramResolutionTest, ResolveSymbolsFull) { valid_symbol_program, &symbol_program)); const absl::flat_hash_map> param_map = { {"v1", {0, 1.0}}, {"v2", {1, 2.0f}}}; - EXPECT_EQ(ResolveSymbols(param_map, &symbol_program, false), Status()); + EXPECT_EQ(ResolveSymbols(param_map, &symbol_program, false), Status::OK()); EXPECT_EQ(symbol_program.circuit() .moments(0) .operations(0) @@ -546,8 +538,7 @@ TEST(ProgramResolutionTest, ResolveSymbolsStrictPartial) { const absl::flat_hash_map> param_map = { {"v1", {0, 1.0}}}; EXPECT_EQ(ResolveSymbols(param_map, &symbol_program, true), - Status(static_cast( - absl::StatusCode::kInvalidArgument), + Status(tensorflow::error::INVALID_ARGUMENT, "Could not find symbol in parameter map: v2")); } @@ -557,7 +548,7 @@ TEST(ProgramResolutionTest, ResolveSymbolsStrictFull) { valid_symbol_program, &symbol_program)); const absl::flat_hash_map> param_map = { {"v1", {0, 1.0}}, {"v2", {1, 2.0f}}}; - EXPECT_EQ(ResolveSymbols(param_map, &symbol_program, true), Status()); + EXPECT_EQ(ResolveSymbols(param_map, &symbol_program, true), Status::OK()); EXPECT_EQ(symbol_program.circuit() .moments(0) .operations(0) @@ -578,7 +569,7 @@ TEST(ProgramResolutionTest, ResolveSymbolsStrictFull) { TEST(ProgramResolutionTest, CheckMPSSupportedEmpty) { Program empty; - EXPECT_EQ(CheckMPSSupported(empty), Status()); + EXPECT_EQ(CheckMPSSupported(empty), Status::OK()); } TEST(ProgramResolutionTest, CheckQubitsIn1DFailedByOpWithMoreThan2Qubits) { @@ -586,8 +577,7 @@ TEST(ProgramResolutionTest, CheckQubitsIn1DFailedByOpWithMoreThan2Qubits) { ASSERT_TRUE(google::protobuf::TextFormat::ParseFromString( three_qubit_op_program, &program_with_3qubit_op)); EXPECT_EQ(CheckMPSSupported(program_with_3qubit_op), - Status(static_cast( - absl::StatusCode::kInvalidArgument), + Status(tensorflow::error::INVALID_ARGUMENT, "1D operations only support 1 and 2 qubit gates. " "Found: 3 qubit gate.")); } @@ -598,8 +588,7 @@ TEST(ProgramResolutionTest, ASSERT_TRUE(google::protobuf::TextFormat::ParseFromString( valid_program, &program_with_3qubit_op)); EXPECT_EQ(CheckMPSSupported(program_with_3qubit_op), - Status(static_cast( - absl::StatusCode::kInvalidArgument), + Status(tensorflow::error::INVALID_ARGUMENT, "1D operations only support 1 and 2 qubit gates. " "Found: 3 qubit gate.")); } @@ -609,8 +598,7 @@ TEST(ProgramResolutionTest, CheckQubitsIn1DFailedByNot1DTopology) { ASSERT_TRUE(google::protobuf::TextFormat::ParseFromString( resolved_qubit_program_not_1d, &program_not_1d)); EXPECT_EQ(CheckMPSSupported(program_not_1d), - Status(static_cast( - absl::StatusCode::kInvalidArgument), + Status(tensorflow::error::INVALID_ARGUMENT, "A program is not in 1D topology. It contains an" " operation with qubits not neighbors each other.")); } diff --git a/tensorflow_quantum/core/src/util_qsim.h b/tensorflow_quantum/core/src/util_qsim.h index f08715343..94531a884 100644 --- a/tensorflow_quantum/core/src/util_qsim.h +++ b/tensorflow_quantum/core/src/util_qsim.h @@ -148,7 +148,7 @@ tensorflow::Status ComputeExpectationQsim(const tfq::proto::PauliSum& p_sum, bool fuse_paulis = true) { // apply the gates of the pauliterms to a copy of the state vector // and add up expectation value term by term. - tensorflow::Status status = ::tensorflow::Status(); + tensorflow::Status status = tensorflow::Status::OK(); for (const tfq::proto::PauliTerm& term : p_sum.terms()) { // catch identity terms if (term.paulis_size() == 0) { @@ -204,11 +204,11 @@ tensorflow::Status ComputeSampledExpectationQsim( std::uniform_int_distribution<> distrib(1, 1 << 30); if (num_samples == 0) { - return ::tensorflow::Status(); + return tensorflow::Status::OK(); } // apply the gates of the pauliterms to a copy of the state vector // and add up expectation value term by term. - tensorflow::Status status = ::tensorflow::Status(); + tensorflow::Status status = tensorflow::Status::OK(); for (const tfq::proto::PauliTerm& term : p_sum.terms()) { // catch identity terms if (term.paulis_size() == 0) { @@ -288,11 +288,11 @@ tensorflow::Status ComputeMPSSampledExpectationQsim( std::uniform_int_distribution<> distrib(1, 1 << 30); if (num_samples == 0) { - return ::tensorflow::Status(); + return tensorflow::Status::OK(); } // apply the gates of the pauliterms to a copy of the state vector // and add up expectation value term by term. - tensorflow::Status status = ::tensorflow::Status(); + tensorflow::Status status = tensorflow::Status::OK(); for (const tfq::proto::PauliTerm& term : p_sum.terms()) { // catch identity terms if (term.paulis_size() == 0) { @@ -367,7 +367,7 @@ tensorflow::Status AccumulateOperators( // apply the gates of the pauliterms to a copy of the state vector // accumulating results as we go. Effectively doing O|psi> for an arbitrary // O. Result is stored on scratch. - tensorflow::Status status = ::tensorflow::Status(); + tensorflow::Status status = tensorflow::Status::OK(); ss.Copy(source, scratch); ss.SetAllZeros(dest); @@ -424,7 +424,7 @@ tensorflow::Status AccumulateFusedCircuits( const std::vector& coefficients, const std::vector& fused_circuits, const SimT& sim, const StateSpaceT& ss, StateT& scratch, StateT& dest) { - tensorflow::Status status = ::tensorflow::Status(); + tensorflow::Status status = tensorflow::Status::OK(); ss.SetAllZeros(dest); for (std::vector>::size_type i = 0; diff --git a/tensorflow_quantum/datasets/spin_system.py b/tensorflow_quantum/datasets/spin_system.py index 4a180a68f..a9f3170d1 100644 --- a/tensorflow_quantum/datasets/spin_system.py +++ b/tensorflow_quantum/datasets/spin_system.py @@ -280,7 +280,7 @@ def tfi_chain(qubits, boundary_condition="closed", data_dir=None): / np.pi # Parameters are stored as np.float32, but cirq expects np.float64 # See https://github.com/quantumlib/Cirq/issues/3359 - params = params.astype(float) + params = params.astype(np.float) additional_info.append( SpinSystemInfo(g=g, gs=np.load( @@ -517,7 +517,7 @@ def xxz_chain(qubits, boundary_condition="closed", data_dir=None): / np.pi # Parameters are stored as np.float32, but cirq expects np.float64 # See https://github.com/quantumlib/Cirq/issues/3359 - params = params.astype(float) + params = params.astype(np.float) additional_info.append( SpinSystemInfo(g=g, gs=np.load( diff --git a/tensorflow_quantum/datasets/spin_system_test.py b/tensorflow_quantum/datasets/spin_system_test.py index 3dac53a80..dcd35d5c7 100644 --- a/tensorflow_quantum/datasets/spin_system_test.py +++ b/tensorflow_quantum/datasets/spin_system_test.py @@ -224,8 +224,7 @@ def test_param_resolver(self): rtol=1e-3) -# TODO(#748): Inherit this class from tf.test.TestCase after fixing the issue. -class TFIRectangularTest: +class TFIRectangularTest(tf.test.TestCase): """Testing tfi_rectangular.""" # pylint: disable=C0103 diff --git a/tensorflow_quantum/python/layers/circuit_executors/sampled_expectation_test.py b/tensorflow_quantum/python/layers/circuit_executors/sampled_expectation_test.py index 4e96a5c49..2d165b13c 100644 --- a/tensorflow_quantum/python/layers/circuit_executors/sampled_expectation_test.py +++ b/tensorflow_quantum/python/layers/circuit_executors/sampled_expectation_test.py @@ -389,7 +389,7 @@ def test_simple_op_input(self, backend): outputs=[circuit_output]) model.compile( - optimizer=tf.keras.optimizers.Adam(learning_rate=0.2), + optimizer=tf.keras.optimizers.Adam(learning_rate=0.05), loss=tf.keras.losses.mean_squared_error, ) history = model.fit(x=[circuit, ops, n], diff --git a/tensorflow_quantum/python/optimizers/rotosolve_minimizer.py b/tensorflow_quantum/python/optimizers/rotosolve_minimizer.py index 5bf23f6a0..bd1270068 100755 --- a/tensorflow_quantum/python/optimizers/rotosolve_minimizer.py +++ b/tensorflow_quantum/python/optimizers/rotosolve_minimizer.py @@ -1,274 +1,263 @@ -# 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. -# See the License for the specific language governing permissions and -# limitations under the License. -# ============================================================================== -"""The rotosolve minimization algorithm.""" -import numpy as np -import tensorflow as tf - - -def prefer_static_shape(x): - """Return static shape of tensor `x` if available, - - else `tf.shape(x)`. - - Args: - x: `tf.Tensor` (already converted). - Returns: - Numpy array (if static shape is obtainable), else `tf.Tensor`. - """ - return prefer_static_value(tf.shape(x)) - - -def prefer_static_value(x): - """Return static value of tensor `x` if available, else `x`. - - Args: - x: `tf.Tensor` (already converted). - Returns: - Numpy array (if static value is obtainable), else `tf.Tensor`. - """ - static_x = tf.get_static_value(x) - if static_x is not None: - return static_x - return x - - -class RotosolveOptimizerResults(tf.experimental.ExtensionType): - """ExtentionType of Rotosolve Optimizer tf.while_loop() inner state.""" - converged: tf.Tensor - # Scalar boolean tensor indicating whether the minimum - # was found within tolerance. - num_iterations: tf.Tensor - # The number of iterations of the rotosolve update. - num_objective_evaluations: tf.Tensor - # The total number of objective - # evaluations performed. - position: tf.Tensor - # A tensor containing the last argument value found - # during the search. If the search converged, then - # this value is the argmin of the objective function. - # A tensor containing the value of the objective from - # previous iteration - objective_value_prev: tf.Tensor - # Save the evaluated value of the objective function - # from the previous iteration - objective_value: tf.Tensor - # A tensor containing the value of the objective - # function at the `position`. If the search - # converged, then this is the (local) minimum of - # the objective function. - tolerance: tf.Tensor - # Define the stop criteria. Iteration will stop when the - # objective value difference between two iterations is - # smaller than tolerance - solve_param_i: tf.Tensor - - # The parameter index where rotosolve is currently - # modifying. Reserved for internal use. - - def to_dict(self): - """Transforms immutable data to mutable dictionary.""" - return { - "converged": self.converged, - "num_iterations": self.num_iterations, - "num_objective_evaluations": self.num_objective_evaluations, - "position": self.position, - "objective_value": self.objective_value, - "objective_value_prev": self.objective_value_prev, - "tolerance": self.tolerance, - "solve_param_i": self.solve_param_i, - } - - -def _get_initial_state(initial_position, tolerance, expectation_value_function): - """Create RotosolveOptimizerResults with initial state of search.""" - init_args = { - "converged": tf.Variable(False), - "num_iterations": tf.Variable(0), - "num_objective_evaluations": tf.Variable(0), - "position": tf.Variable(initial_position), - "objective_value": expectation_value_function(initial_position), - "objective_value_prev": tf.Variable(0.), - "tolerance": tolerance, - "solve_param_i": tf.Variable(0), - } - return RotosolveOptimizerResults(**init_args) - - -def minimize(expectation_value_function, - initial_position, - tolerance=1e-5, - max_iterations=50, - name=None): - """Applies the rotosolve algorithm. - - The rotosolve algorithm can be used to minimize a linear combination - - of quantum measurement expectation values. See the following paper: - - [arXiv:1903.12166](https://arxiv.org/abs/1903.12166), Ken M. Nakanishi. - [arXiv:1905.09692](https://arxiv.org/abs/1905.09692), Mateusz Ostaszewski. - - Usage: - - Here is an example of optimize a function which consists summation of - a few sinusoids. - - >>> n = 10 # Number of sinusoids - >>> coefficient = tf.random.uniform(shape=[n]) - >>> min_value = -tf.math.reduce_sum(tf.abs(coefficient)) - >>> func = lambda x:tf.math.reduce_sum(tf.sin(x) * coefficient) - >>> # Optimize the function with rotosolve, start with random parameters - >>> result = tfq.optimizers.rotosolve_minimize(func, np.random.random(n)) - >>> result.converged - tf.Tensor(True, shape=(), dtype=bool) - >>> result.objective_value - tf.Tensor(-4.7045116, shape=(), dtype=float32) - - Args: - expectation_value_function: A Python callable that accepts - a point as a real `tf.Tensor` and returns a `tf.Tensor`s - of real dtype containing the value of the function. - The function to be minimized. The input is of shape `[n]`, - where `n` is the size of the trainable parameters. - The return value is a real `tf.Tensor` Scalar (matching shape - `[1]`). This must be a linear combination of quantum - measurement expectation value, otherwise this algorithm cannot - work. - initial_position: Real `tf.Tensor` of shape `[n]`. The starting - point, or points when using batching dimensions, of the search - procedure. At these points the function value and the gradient - norm should be finite. - tolerance: Scalar `tf.Tensor` of real dtype. Specifies the tolerance - for the procedure. If the supremum norm between two iteration - vector is below this number, the algorithm is stopped. - name: (Optional) Python `str`. The name prefixed to the ops created - by this function. If not supplied, the default name 'minimize' - is used. - - Returns: - optimizer_results: A RotosolveOptimizerResults object contains the - result of the optimization process. - """ - - with tf.name_scope(name or 'minimize'): - initial_position = tf.convert_to_tensor(initial_position, - name='initial_position', - dtype='float32') - dtype = initial_position.dtype.base_dtype - tolerance = tf.convert_to_tensor(tolerance, - dtype=dtype, - name='grad_tolerance') - max_iterations = tf.convert_to_tensor(max_iterations, - name='max_iterations') - - def _rotosolve_one_parameter_once(state): - """Rotosolve a single parameter once. - - Args: - state: A RotosolveOptimizerResults object stores the - current state of the minimizer. - - Returns: - states: A list which the first element is the new state - """ - delta_shift = tf.scatter_nd([[state.solve_param_i]], - [tf.constant(np.pi / 2, dtype=dtype)], - prefer_static_shape(state.position)) - - # Evaluate three different point for curve fitting - v_l, v_n, v_r = expectation_value_function( - state.position - delta_shift), \ - state.objective_value, \ - expectation_value_function(state.position + delta_shift) - - # Use the analytical solution to find the optimized position - delta_update = -np.pi / 2 - \ - tf.math.atan2(2 * v_n - v_l - v_r, v_r - v_l) - - delta_update_tensor = tf.scatter_nd( - [[state.solve_param_i]], [delta_update], - prefer_static_shape(state.position)) - - new_position = (tf.math.floormod( - state.position + delta_update_tensor, np.pi * 2)) - next_state_params = state.to_dict() - next_state_params.update({ - "solve_param_i": state.solve_param_i + 1, - "position": new_position, - "objective_value_prev": state.objective_value, - "objective_value": (expectation_value_function(new_position)), - }) - return [RotosolveOptimizerResults(**next_state_params)] - - def _rotosolve_all_parameters_once(state): - """Iterate over all parameters and rotosolve each single - - of them once. - - Args: - state: A RotosolveOptimizerResults object stores the - current state of the minimizer. - - Returns: - states: A list which the first element is the new state - """ - - def _cond_internal(state_cond): - return state_cond.solve_param_i < \ - prefer_static_shape(state_cond.position)[0] - - next_state_params = state.to_dict() - next_state_params.update({ - "num_objective_evaluations": - state.num_objective_evaluations + 1, - }) - - return tf.while_loop( - cond=_cond_internal, - body=_rotosolve_one_parameter_once, - loop_vars=[RotosolveOptimizerResults(**next_state_params)], - parallel_iterations=1, - ) - - # The `state` here is a `RotosolveOptimizerResults` tuple with - # values for the current state of the algorithm computation. - def _cond(state): - """Continue if iterations remain and stopping condition - is not met.""" - return (state.num_iterations < max_iterations) \ - and (not state.converged) - - def _body(state): - """Main optimization loop.""" - pre_state_params = state.to_dict() - pre_state_params.update({"solve_param_i": 0}) - pre_state = RotosolveOptimizerResults(**pre_state_params) - post_state = _rotosolve_all_parameters_once(pre_state)[0] - next_state_params = post_state.to_dict() - next_state_params.update({ - "converged": (tf.abs(post_state.objective_value - - post_state.objective_value_prev) < - post_state.tolerance), - "num_iterations": post_state.num_iterations + 1, - }) - return [RotosolveOptimizerResults(**next_state_params)] - - initial_state = _get_initial_state(initial_position, tolerance, - expectation_value_function) - - return tf.while_loop(cond=_cond, - body=_body, - loop_vars=[initial_state], - parallel_iterations=1)[0] +# 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. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== +"""The rotosolve minimization algorithm""" +import collections +import numpy as np +import tensorflow as tf + + +def prefer_static_shape(x): + """Return static shape of tensor `x` if available, + + else `tf.shape(x)`. + + Args: + x: `tf.Tensor` (already converted). + Returns: + Numpy array (if static shape is obtainable), else `tf.Tensor`. + """ + return prefer_static_value(tf.shape(x)) + + +def prefer_static_value(x): + """Return static value of tensor `x` if available, else `x`. + + Args: + x: `tf.Tensor` (already converted). + Returns: + Numpy array (if static value is obtainable), else `tf.Tensor`. + """ + static_x = tf.get_static_value(x) + if static_x is not None: + return static_x + return x + + +RotosolveOptimizerResults = collections.namedtuple( + 'RotosolveOptimizerResults', + [ + 'converged', + # Scalar boolean tensor indicating whether the minimum + # was found within tolerance. + 'num_iterations', + # The number of iterations of the rotosolve update. + 'num_objective_evaluations', + # The total number of objective + # evaluations performed. + 'position', + # A tensor containing the last argument value found + # during the search. If the search converged, then + # this value is the argmin of the objective function. + # A tensor containing the value of the objective from + # previous iteration + 'objective_value_previous_iteration', + # Save the evaluated value of the objective function + # from the previous iteration + 'objective_value', + # A tensor containing the value of the objective + # function at the `position`. If the search + # converged, then this is the (local) minimum of + # the objective function. + 'tolerance', + # Define the stop criteria. Iteration will stop when the + # objective value difference between two iterations is + # smaller than tolerance + 'solve_param_i', + # The parameter index where rotosolve is currently + # modifying. Reserved for internal use. + ]) + + +def _get_initial_state(initial_position, tolerance, expectation_value_function): + """Create RotosolveOptimizerResults with initial state of search.""" + init_args = { + "converged": tf.Variable(False), + "num_iterations": tf.Variable(0), + "num_objective_evaluations": tf.Variable(0), + "position": tf.Variable(initial_position), + "objective_value": tf.Variable(0.), + "objective_value_previous_iteration": tf.Variable(0.), + "tolerance": tolerance, + "solve_param_i": tf.Variable(0) + } + return RotosolveOptimizerResults(**init_args) + + +def minimize(expectation_value_function, + initial_position, + tolerance=1e-5, + max_iterations=50, + name=None): + """Applies the rotosolve algorithm. + + The rotosolve algorithm can be used to minimize a linear combination + + of quantum measurement expectation values. See the following paper: + + [arXiv:1903.12166](https://arxiv.org/abs/1903.12166), Ken M. Nakanishi. + [arXiv:1905.09692](https://arxiv.org/abs/1905.09692), Mateusz Ostaszewski. + + Usage: + + Here is an example of optimize a function which consists summation of + a few sinusoids. + + >>> n = 10 # Number of sinusoids + >>> coefficient = tf.random.uniform(shape=[n]) + >>> min_value = -tf.math.reduce_sum(tf.abs(coefficient)) + >>> func = lambda x:tf.math.reduce_sum(tf.sin(x) * coefficient) + >>> # Optimize the function with rotosolve, start with random parameters + >>> result = tfq.optimizers.rotosolve_minimize(func, np.random.random(n)) + >>> result.converged + tf.Tensor(True, shape=(), dtype=bool) + >>> result.objective_value + tf.Tensor(-4.7045116, shape=(), dtype=float32) + + Args: + expectation_value_function: A Python callable that accepts + a point as a real `tf.Tensor` and returns a `tf.Tensor`s + of real dtype containing the value of the function. + The function to be minimized. The input is of shape `[n]`, + where `n` is the size of the trainable parameters. + The return value is a real `tf.Tensor` Scalar (matching shape + `[1]`). This must be a linear combination of quantum + measurement expectation value, otherwise this algorithm cannot + work. + initial_position: Real `tf.Tensor` of shape `[n]`. The starting + point, or points when using batching dimensions, of the search + procedure. At these points the function value and the gradient + norm should be finite. + tolerance: Scalar `tf.Tensor` of real dtype. Specifies the tolerance + for the procedure. If the supremum norm between two iteration + vector is below this number, the algorithm is stopped. + name: (Optional) Python `str`. The name prefixed to the ops created + by this function. If not supplied, the default name 'minimize' + is used. + + Returns: + optimizer_results: A RotosolveOptimizerResults object contains the + result of the optimization process. + """ + + with tf.name_scope(name or 'minimize'): + initial_position = tf.convert_to_tensor(initial_position, + name='initial_position', + dtype='float32') + dtype = initial_position.dtype.base_dtype + tolerance = tf.convert_to_tensor(tolerance, + dtype=dtype, + name='grad_tolerance') + max_iterations = tf.convert_to_tensor(max_iterations, + name='max_iterations') + + def _rotosolve_one_parameter_once(state): + """Rotosolve a single parameter once. + + Args: + state: A RotosolveOptimizerResults object stores the + current state of the minimizer. + + Returns: + states: A list which the first element is the new state + """ + delta_shift = tf.scatter_nd([[state.solve_param_i]], + [tf.constant(np.pi / 2, dtype=dtype)], + prefer_static_shape(state.position)) + + # Evaluate three different point for curve fitting + v_l, v_n, v_r = expectation_value_function( + state.position - delta_shift), \ + state.objective_value, \ + expectation_value_function(state.position + delta_shift) + + # Use the analytical solution to find the optimized position + delta_update = -np.pi / 2 - \ + tf.math.atan2(2 * v_n - v_l - v_r, v_r - v_l) + + delta_update_tensor = tf.scatter_nd( + [[state.solve_param_i]], [delta_update], + prefer_static_shape(state.position)) + + state.solve_param_i.assign_add(1) + state.position.assign( + tf.math.floormod(state.position + delta_update_tensor, + np.pi * 2)) + + state.objective_value_previous_iteration.assign( + state.objective_value) + state.objective_value.assign( + expectation_value_function(state.position)) + + return [state] + + def _rotosolve_all_parameters_once(state): + """Iterate over all parameters and rotosolve each single + + of them once. + + Args: + state: A RotosolveOptimizerResults object stores the + current state of the minimizer. + + Returns: + states: A list which the first element is the new state + """ + + def _cond_internal(state_cond): + return state_cond.solve_param_i < \ + prefer_static_shape(state_cond.position)[0] + + state.num_objective_evaluations.assign_add(1) + + return tf.while_loop( + cond=_cond_internal, + body=_rotosolve_one_parameter_once, + loop_vars=[state], + parallel_iterations=1, + ) + + # The `state` here is a `RotosolveOptimizerResults` tuple with + # values for the current state of the algorithm computation. + def _cond(state): + """Continue if iterations remain and stopping condition + is not met.""" + return (state.num_iterations < max_iterations) \ + and (not state.converged) + + def _body(state): + """Main optimization loop.""" + + state.solve_param_i.assign(0) + + _rotosolve_all_parameters_once(state) + + state.num_iterations.assign_add(1) + state.converged.assign( + tf.abs(state.objective_value - + state.objective_value_previous_iteration) < + state.tolerance) + + return [state] + + initial_state = _get_initial_state(initial_position, tolerance, + expectation_value_function) + + initial_state.objective_value.assign( + expectation_value_function(initial_state.position)) + + return tf.while_loop(cond=_cond, + body=_body, + loop_vars=[initial_state], + parallel_iterations=1)[0] diff --git a/tensorflow_quantum/python/optimizers/spsa_minimizer.py b/tensorflow_quantum/python/optimizers/spsa_minimizer.py index 471b46d9e..ecabda275 100644 --- a/tensorflow_quantum/python/optimizers/spsa_minimizer.py +++ b/tensorflow_quantum/python/optimizers/spsa_minimizer.py @@ -12,7 +12,8 @@ # See the License for the specific language governing permissions and # limitations under the License. # ============================================================================== -"""The SPSA minimization algorithm.""" +"""The SPSA minimization algorithm""" +import collections import tensorflow as tf import numpy as np @@ -44,88 +45,69 @@ def prefer_static_value(x): return x -class SPSAOptimizerResults(tf.experimental.ExtensionType): - """ExtentionType of SPSA Optimizer tf.while_loop() inner state.""" - converged: tf.Tensor - # Scalar boolean tensor indicating whether the minimum - # was found within tolerance. - num_iterations: tf.Tensor - # The number of iterations of the SPSA update. - num_objective_evaluations: tf.Tensor - # The total number of objective - # evaluations performed. - position: tf.Tensor - # A tensor containing the last argument value found - # during the search. If the search converged, then - # this value is the argmin of the objective function. - # A tensor containing the value of the objective from - # previous iteration - objective_value_prev: tf.Tensor - # Save the evaluated value of the objective function - # from the previous iteration - objective_value: tf.Tensor - # A tensor containing the value of the objective - # function at the `position`. If the search - # converged, then this is the (local) minimum of - # the objective function. - tolerance: tf.Tensor - # Define the stop criteria. Iteration will stop when the - # objective value difference between two iterations is - # smaller than tolerance - learning_rate: tf.Tensor - # Specifies the learning rate - alpha: tf.Tensor - # Specifies scaling of the learning rate - perturb: tf.Tensor - # Specifies the size of the perturbations - gamma: tf.Tensor - # Specifies scaling of the size of the perturbations - blocking: tf.Tensor - # If true, then the optimizer will only accept updates that improve - # the objective function. - allowed_increase: tf.Tensor - - # Specifies maximum allowable increase in objective function - # (only applies if blocking is true). - - def to_dict(self): - """Transforms immutable data to mutable dictionary.""" - return { - "converged": self.converged, - "num_iterations": self.num_iterations, - "num_objective_evaluations": self.num_objective_evaluations, - "position": self.position, - "objective_value": self.objective_value, - "objective_value_prev": self.objective_value_prev, - "tolerance": self.tolerance, - "learning_rate": self.learning_rate, - "alpha": self.alpha, - "perturb": self.perturb, - "gamma": self.gamma, - "blocking": self.blocking, - "allowed_increase": self.allowed_increase, - } +SPSAOptimizerResults = collections.namedtuple( + 'SPSAOptimizerResults', + [ + 'converged', + # Scalar boolean tensor indicating whether the minimum + # was found within tolerance. + 'num_iterations', + # The number of iterations of the SPSA update. + 'num_objective_evaluations', + # The total number of objective + # evaluations performed. + 'position', + # A tensor containing the last argument value found + # during the search. If the search converged, then + # this value is the argmin of the objective function. + # A tensor containing the value of the objective from + # previous iteration + 'objective_value_previous_iteration', + # Save the evaluated value of the objective function + # from the previous iteration + 'objective_value', + # A tensor containing the value of the objective + # function at the `position`. If the search + # converged, then this is the (local) minimum of + # the objective function. + 'tolerance', + # Define the stop criteria. Iteration will stop when the + # objective value difference between two iterations is + # smaller than tolerance + 'lr', + # Specifies the learning rate + 'alpha', + # Specifies scaling of the learning rate + 'perturb', + # Specifies the size of the perturbations + 'gamma', + # Specifies scaling of the size of the perturbations + 'blocking', + # If true, then the optimizer will only accept updates that improve + # the objective function. + 'allowed_increase' + # Specifies maximum allowable increase in objective function + # (only applies if blocking is true). + ]) def _get_initial_state(initial_position, tolerance, expectation_value_function, - learning_rate, alpha, perturb, gamma, blocking, - allowed_increase): + lr, alpha, perturb, gamma, blocking, allowed_increase): """Create SPSAOptimizerResults with initial state of search.""" init_args = { "converged": tf.Variable(False), "num_iterations": tf.Variable(0), "num_objective_evaluations": tf.Variable(0), "position": tf.Variable(initial_position), - "objective_value": - (tf.cast(expectation_value_function(initial_position), tf.float32)), - "objective_value_prev": tf.Variable(np.inf), + "objective_value": tf.Variable(0.), + "objective_value_previous_iteration": tf.Variable(np.inf), "tolerance": tolerance, - "learning_rate": tf.Variable(learning_rate), + "lr": tf.Variable(lr), "alpha": tf.Variable(alpha), "perturb": tf.Variable(perturb), "gamma": tf.Variable(gamma), "blocking": tf.Variable(blocking), - "allowed_increase": tf.Variable(allowed_increase), + "allowed_increase": tf.Variable(allowed_increase) } return SPSAOptimizerResults(**init_args) @@ -135,7 +117,7 @@ def minimize(expectation_value_function, tolerance=1e-5, max_iterations=200, alpha=0.602, - learning_rate=1.0, + lr=1.0, perturb=1.0, gamma=0.101, blocking=False, @@ -177,8 +159,7 @@ def minimize(expectation_value_function, tolerance: Scalar `tf.Tensor` of real dtype. Specifies the tolerance for the procedure. If the supremum norm between two iteration vector is below this number, the algorithm is stopped. - learning_rate: Scalar `tf.Tensor` of real dtype. - Specifies the learning rate. + lr: Scalar `tf.Tensor` of real dtype. Specifies the learning rate alpha: Scalar `tf.Tensor` of real dtype. Specifies scaling of the learning rate. perturb: Scalar `tf.Tensor` of real dtype. Specifies the size of the @@ -217,9 +198,7 @@ def minimize(expectation_value_function, max_iterations = tf.convert_to_tensor(max_iterations, name='max_iterations') - learning_rate_init = tf.convert_to_tensor(learning_rate, - name='initial_a', - dtype='float32') + lr_init = tf.convert_to_tensor(lr, name='initial_a', dtype='float32') perturb_init = tf.convert_to_tensor(perturb, name='initial_c', dtype='float32') @@ -245,25 +224,19 @@ def _spsa_once(state): state.perturb * delta_shift) gradient_estimate = (v_p - v_m) / (2 * state.perturb) * delta_shift - update = state.learning_rate * gradient_estimate - next_state_params = state.to_dict() - next_state_params.update({ - "num_objective_evaluations": - state.num_objective_evaluations + 2, - }) - - current_obj = tf.cast(expectation_value_function(state.position - - update), - dtype=tf.float32) - if state.objective_value_prev + \ + update = state.lr * gradient_estimate + + state.num_objective_evaluations.assign_add(2) + + current_obj = expectation_value_function(state.position - update) + if state.objective_value_previous_iteration + \ state.allowed_increase >= current_obj or not state.blocking: - next_state_params.update({ - "position": state.position - update, - "objective_value_prev": state.objective_value, - "objective_value": current_obj - }) + state.position.assign(state.position - update) + state.objective_value_previous_iteration.assign( + state.objective_value) + state.objective_value.assign(current_obj) - return [SPSAOptimizerResults(**next_state_params)] + return [state] # The `state` here is a `SPSAOptimizerResults` tuple with # values for the current state of the algorithm computation. @@ -275,33 +248,31 @@ def _cond(state): def _body(state): """Main optimization loop.""" - new_learning_rate = learning_rate_init / ( + new_lr = lr_init / ( (tf.cast(state.num_iterations + 1, tf.float32) + 0.01 * tf.cast(max_iterations, tf.float32))**state.alpha) new_perturb = perturb_init / (tf.cast(state.num_iterations + 1, tf.float32)**state.gamma) - pre_state_params = state.to_dict() - pre_state_params.update({ - "learning_rate": new_learning_rate, - "perturb": new_perturb, - }) - - post_state = _spsa_once(SPSAOptimizerResults(**pre_state_params))[0] - post_state_params = post_state.to_dict() - post_state_params.update({ - "num_iterations": - post_state.num_iterations + 1, - "converged": - (tf.abs(state.objective_value - state.objective_value_prev) - < state.tolerance), - }) - return [SPSAOptimizerResults(**post_state_params)] + state.lr.assign(new_lr) + state.perturb.assign(new_perturb) + + _spsa_once(state) + state.num_iterations.assign_add(1) + state.converged.assign( + tf.abs(state.objective_value - + state.objective_value_previous_iteration) < + state.tolerance) + return [state] initial_state = _get_initial_state(initial_position, tolerance, - expectation_value_function, - learning_rate, alpha, perturb, gamma, - blocking, allowed_increase) + expectation_value_function, lr, + alpha, perturb, gamma, blocking, + allowed_increase) + + initial_state.objective_value.assign( + tf.cast(expectation_value_function(initial_state.position), + tf.float32)) return tf.while_loop(cond=_cond, body=_body, From ce3d14a7c9fb32b83c41fc7608480c1ee1443aff Mon Sep 17 00:00:00 2001 From: Michael Broughton Date: Mon, 12 Jun 2023 14:18:20 -0700 Subject: [PATCH 31/50] Revert "TFQ simulate expectation CUDA op" This reverts commit f063417f4b08c6b430c8822bc9cb8ad8a7819ff9. --- .../core/ops/tfq_simulate_ops_cuda_test.py | 131 ------------------ 1 file changed, 131 deletions(-) delete mode 100644 tensorflow_quantum/core/ops/tfq_simulate_ops_cuda_test.py diff --git a/tensorflow_quantum/core/ops/tfq_simulate_ops_cuda_test.py b/tensorflow_quantum/core/ops/tfq_simulate_ops_cuda_test.py deleted file mode 100644 index c293fe673..000000000 --- a/tensorflow_quantum/core/ops/tfq_simulate_ops_cuda_test.py +++ /dev/null @@ -1,131 +0,0 @@ -# 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. -# See the License for the specific language governing permissions and -# limitations under the License. -# ============================================================================== -"""Tests that specifically target tfq_simulate_ops_cuda.""" -import os -import time -import numpy as np -from absl.testing import parameterized -import tensorflow as tf -import cirq - -from tensorflow_quantum.core.ops import tfq_simulate_ops -from tensorflow_quantum.core.ops import tfq_simulate_ops_cuda -from tensorflow_quantum.python import util - - -class SimulateExpectationTest(tf.test.TestCase): - """Tests tfq_simulate_expectation.""" - - def test_simulate_expectation_diff(self): - """Make sure that cpu & gpu ops have the same results.""" - # TF 2 - # gpus = tf.config.list_physical_devices('GPU') - # self.assertLess(len(gpus), 1) - # if len(gpus) < 1: - # self.skipTest("Expected at least 1 GPU but found {} GPUs".format( - # len(gpus))) - n_qubits = 20 - batch_size = 5 - symbol_names = ['alpha'] - qubits = cirq.GridQubit.rect(1, n_qubits) - circuit_batch, resolver_batch = \ - util.random_symbol_circuit_resolver_batch( - qubits, symbol_names, batch_size) - - circuit_batch_tensor = util.convert_to_tensor(circuit_batch) - - symbol_values_array = np.array( - [[resolver[symbol] - for symbol in symbol_names] - for resolver in resolver_batch]) - - pauli_sums = util.random_pauli_sums(qubits, 3, batch_size) - pauli_sums_tensor = util.convert_to_tensor([[x] for x in pauli_sums]) - - cpu_avg_time = [] - for _ in range(10): - cpu_time = time.time() - res_cpu = tfq_simulate_ops.tfq_simulate_expectation( - circuit_batch_tensor, - symbol_names, symbol_values_array.astype(np.float64), - pauli_sums_tensor) - cpu_time = time.time() - cpu_time - cpu_avg_time.append(cpu_time) - cpu_avg_time = sum(cpu_avg_time) / 10.0 - print("\n\tCPU time: ", cpu_avg_time, "\n") - - avg_cpu_with_gpu_time = [] - for _ in range(10): - cpu_with_gpu_time = time.time() - with tf.device("/device:GPU:0"): - res_cpu_with_gpu = tfq_simulate_ops_cuda.tfq_simulate_expectation( - circuit_batch_tensor, - symbol_names, symbol_values_array.astype(np.float64), - pauli_sums_tensor) - cpu_with_gpu_time = time.time() - cpu_with_gpu_time - avg_cpu_with_gpu_time.append(cpu_with_gpu_time) - avg_cpu_with_gpu_time = sum(avg_cpu_with_gpu_time) / 10.0 - - # Both are CPU devices. - self.assertEqual(res_cpu.device, res_cpu_with_gpu.device) - np.testing.assert_allclose(res_cpu, res_cpu_with_gpu) - print("\n\tCPU with GPU device time: ", avg_cpu_with_gpu_time, "\n") - - @tf.function - def cpu_with_gpu_fn(): - with tf.device("/device:GPU:0"): - return tfq_simulate_ops_cuda.tfq_simulate_expectation( - circuit_batch_tensor, - symbol_names, symbol_values_array.astype(np.float64), - pauli_sums_tensor) - - avg_fn_cpu_with_gpu_time = [] - for _ in range(10): - fn_cpu_with_gpu_time = time.time() - res_fn_cpu_with_gpu = cpu_with_gpu_fn() - fn_cpu_with_gpu_time = time.time() - fn_cpu_with_gpu_time - avg_fn_cpu_with_gpu_time.append(fn_cpu_with_gpu_time) - avg_fn_cpu_with_gpu_time = sum(avg_fn_cpu_with_gpu_time) / 10.0 - - # CPU & GPU devices. - self.assertNotEqual(res_cpu.device, res_fn_cpu_with_gpu.device) - np.testing.assert_allclose(res_cpu, res_fn_cpu_with_gpu) - print("\n\ttf.function, CPU with GPU device time: ", - avg_fn_cpu_with_gpu_time, "\n") - - # avg_gpu_time = [] - # for _ in range(10): - # gpu_time = time.time() - # res_gpu = tfq_simulate_ops_gpu_cpu.tfq_simulate_expectation( - # circuit_batch_tensor, - # symbol_names, symbol_values_array.astype(np.float64), - # pauli_sums_tensor) - # gpu_time = time.time() - gpu_time - # avg_gpu_time.append(gpu_time) - # avg_gpu_time = sum(avg_gpu_time) / 10.0 - # print("\n\tGPU version time: ", avg_gpu_time, "\n") - - - # # This guarantees that both tensors are not in the same devices - # # (e.g. CPU vs GPU) - # # self.assertNotEqual(res.device, res_gpu.device) - # # -> this doesn't work anymore because TFQ op itself is in CPU. - # # only qsim::SimulatorCUDA is in GPU - # np.testing.assert_allclose(res_cpu, res_gpu) - # self.assertGreater(cpu_avg_time, avg_gpu_time) - - -if __name__ == "__main__": - tf.test.main() \ No newline at end of file From 8395581ddfd4062c61e15fee61d1c27a432bce58 Mon Sep 17 00:00:00 2001 From: Michael Broughton Date: Mon, 12 Jun 2023 14:18:49 -0700 Subject: [PATCH 32/50] Revert "Update ci_install bazel version, removed duplicated code lines." This reverts commit 1317edf584cf978a106ecb657faf3d3fdef67402. --- tensorflow_quantum/python/optimizers/spsa_minimizer.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tensorflow_quantum/python/optimizers/spsa_minimizer.py b/tensorflow_quantum/python/optimizers/spsa_minimizer.py index ecabda275..1b40ef00e 100644 --- a/tensorflow_quantum/python/optimizers/spsa_minimizer.py +++ b/tensorflow_quantum/python/optimizers/spsa_minimizer.py @@ -236,7 +236,9 @@ def _spsa_once(state): state.objective_value) state.objective_value.assign(current_obj) - return [state] + return [SPSAOptimizerResults(**next_state_params)] + + return [SPSAOptimizerResults(**next_state_params)] # The `state` here is a `SPSAOptimizerResults` tuple with # values for the current state of the algorithm computation. From 7a80a4682584acf9c67a30cf8af4d269903e4cf8 Mon Sep 17 00:00:00 2001 From: Michael Broughton Date: Mon, 12 Jun 2023 14:20:11 -0700 Subject: [PATCH 33/50] Revert "Fix typo" This reverts commit a765f7ff84e2b7edb19e324b8d6a33171a7d5984. --- scripts/ci_validate_tutorials.sh | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/scripts/ci_validate_tutorials.sh b/scripts/ci_validate_tutorials.sh index 74c9189a1..631d4eed7 100755 --- a/scripts/ci_validate_tutorials.sh +++ b/scripts/ci_validate_tutorials.sh @@ -19,7 +19,9 @@ pip install jupyter nbconvert==6.4.3 jupyter-client==6.1.12 ipython==7.22.0 # Workaround for ipykernel - see https://github.com/ipython/ipykernel/issues/422 pip install ipykernel==5.1.1 # OpenAI Gym pip package needed for the quantum reinforcement learning tutorial -pip install gym==0.18.0 +pip install gym==0.24.1 +# seaborn has also numpy dependency, it requires version >= 0.12.0. +pip install seaborn=0.12.0 # tf_docs pip package needed for noise tutorial. pip install -q git+https://github.com/tensorflow/docs # Leave the quantum directory, otherwise errors may occur From 1e8499e4fce4fcdbf2c0ed5e7e828beae75d3163 Mon Sep 17 00:00:00 2001 From: Michael Broughton Date: Mon, 12 Jun 2023 14:20:13 -0700 Subject: [PATCH 34/50] Revert "Upgrade seaborn version to 0.12.0" This reverts commit 4e7c22dedc2e231d7eab3dd4cd3f0235444e51e0. --- scripts/ci_validate_tutorials.sh | 2 -- 1 file changed, 2 deletions(-) diff --git a/scripts/ci_validate_tutorials.sh b/scripts/ci_validate_tutorials.sh index 631d4eed7..45e97ff79 100755 --- a/scripts/ci_validate_tutorials.sh +++ b/scripts/ci_validate_tutorials.sh @@ -20,8 +20,6 @@ pip install jupyter nbconvert==6.4.3 jupyter-client==6.1.12 ipython==7.22.0 pip install ipykernel==5.1.1 # OpenAI Gym pip package needed for the quantum reinforcement learning tutorial pip install gym==0.24.1 -# seaborn has also numpy dependency, it requires version >= 0.12.0. -pip install seaborn=0.12.0 # tf_docs pip package needed for noise tutorial. pip install -q git+https://github.com/tensorflow/docs # Leave the quantum directory, otherwise errors may occur From d7347c4c99f25a8236433fd620327bd15c5a110f Mon Sep 17 00:00:00 2001 From: Michael Broughton Date: Mon, 12 Jun 2023 14:20:15 -0700 Subject: [PATCH 35/50] Revert "Fix tutorial errors" This reverts commit c185891066ce453dcac56fc19d172bd71150a031. --- docs/tutorials/barren_plateaus.ipynb | 2 +- docs/tutorials/gradients.ipynb | 4 ++-- docs/tutorials/hello_many_worlds.ipynb | 8 ++++---- docs/tutorials/mnist.ipynb | 4 ++-- docs/tutorials/quantum_reinforcement_learning.ipynb | 6 +++--- 5 files changed, 12 insertions(+), 12 deletions(-) diff --git a/docs/tutorials/barren_plateaus.ipynb b/docs/tutorials/barren_plateaus.ipynb index 2447018c9..b35e4f76c 100644 --- a/docs/tutorials/barren_plateaus.ipynb +++ b/docs/tutorials/barren_plateaus.ipynb @@ -297,7 +297,7 @@ " # Prep the inputs as tensors\n", " circuit_tensor = tfq.convert_to_tensor(circuits)\n", " values_tensor = tf.convert_to_tensor(\n", - " np.random.uniform(0, 2 * np.pi, (n_circuits, 1)).astype(np.float32))\n", + " np.random.uniform(0, 2 * np.pi, (n_circuits, 1)).astype(float))\n", "\n", " # Use TensorFlow GradientTape to track gradients.\n", " with tf.GradientTape() as g:\n", diff --git a/docs/tutorials/gradients.ipynb b/docs/tutorials/gradients.ipynb index 62a7ce103..1db3f4bf2 100644 --- a/docs/tutorials/gradients.ipynb +++ b/docs/tutorials/gradients.ipynb @@ -99,7 +99,7 @@ }, "outputs": [], "source": [ - "!pip install tensorflow==2.7.0" + "!pip install tensorflow==2.11.0" ] }, { @@ -122,7 +122,7 @@ }, "outputs": [], "source": [ - "!pip install tensorflow-quantum==0.7.2" + "!pip install tensorflow-quantum==0.7.3" ] }, { diff --git a/docs/tutorials/hello_many_worlds.ipynb b/docs/tutorials/hello_many_worlds.ipynb index f3dd7fe19..98a0e1b15 100644 --- a/docs/tutorials/hello_many_worlds.ipynb +++ b/docs/tutorials/hello_many_worlds.ipynb @@ -739,10 +739,10 @@ "outputs": [], "source": [ "# The command input values to the classical NN.\n", - "commands = np.array([[0], [1]], dtype=np.float32)\n", + "commands = np.array([[0], [1]], dtype=float)\n", "\n", "# The desired Z expectation value at output of quantum circuit.\n", - "expected_outputs = np.array([[1], [-1]], dtype=np.float32)" + "expected_outputs = np.array([[1], [-1]], dtype=float)" ] }, { @@ -1108,10 +1108,10 @@ "operator_data = tfq.convert_to_tensor([[cirq.X(qubit)], [cirq.Z(qubit)]])\n", "\n", "# The command input values to the classical NN.\n", - "commands = np.array([[0], [1]], dtype=np.float32)\n", + "commands = np.array([[0], [1]], dtype=float)\n", "\n", "# The desired expectation value at output of quantum circuit.\n", - "expected_outputs = np.array([[1], [-1]], dtype=np.float32)" + "expected_outputs = np.array([[1], [-1]], dtype=float)" ] }, { diff --git a/docs/tutorials/mnist.ipynb b/docs/tutorials/mnist.ipynb index b80f2500f..baed1eac9 100644 --- a/docs/tutorials/mnist.ipynb +++ b/docs/tutorials/mnist.ipynb @@ -480,8 +480,8 @@ "source": [ "THRESHOLD = 0.5\n", "\n", - "x_train_bin = np.array(x_train_nocon > THRESHOLD, dtype=np.float32)\n", - "x_test_bin = np.array(x_test_small > THRESHOLD, dtype=np.float32)" + "x_train_bin = np.array(x_train_nocon > THRESHOLD, dtype=float)\n", + "x_test_bin = np.array(x_test_small > THRESHOLD, dtype=float)" ] }, { diff --git a/docs/tutorials/quantum_reinforcement_learning.ipynb b/docs/tutorials/quantum_reinforcement_learning.ipynb index 50298fe8a..5a59f4080 100644 --- a/docs/tutorials/quantum_reinforcement_learning.ipynb +++ b/docs/tutorials/quantum_reinforcement_learning.ipynb @@ -864,7 +864,7 @@ " actions = np.concatenate([ep['actions'] for ep in episodes])\n", " rewards = [ep['rewards'] for ep in episodes]\n", " returns = np.concatenate([compute_returns(ep_rwds, gamma) for ep_rwds in rewards])\n", - " returns = np.array(returns, dtype=np.float32)\n", + " returns = np.array(returns, dtype=float)\n", "\n", " id_action_pairs = np.array([[i, a] for i, a in enumerate(actions)])\n", " \n", @@ -1456,9 +1456,9 @@ " training_batch = np.random.choice(replay_memory, size=batch_size)\n", " Q_learning_update(np.asarray([x['state'] for x in training_batch]),\n", " np.asarray([x['action'] for x in training_batch]),\n", - " np.asarray([x['reward'] for x in training_batch], dtype=np.float32),\n", + " np.asarray([x['reward'] for x in training_batch], dtype=float),\n", " np.asarray([x['next_state'] for x in training_batch]),\n", - " np.asarray([x['done'] for x in training_batch], dtype=np.float32),\n", + " np.asarray([x['done'] for x in training_batch], dtype=float),\n", " model, gamma, n_actions)\n", " \n", " # Update target model\n", From 035013bb715ee89848885159272ba8e3bbd8579b Mon Sep 17 00:00:00 2001 From: Michael Broughton Date: Mon, 12 Jun 2023 14:21:13 -0700 Subject: [PATCH 36/50] Revert "Fix tutorial error" This reverts commit c5df061088fc7d69fde7f8f695e0a43fd2a32213. --- docs/tutorials/gradients.ipynb | 6 +++--- scripts/test_tutorials.py | 1 - 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/docs/tutorials/gradients.ipynb b/docs/tutorials/gradients.ipynb index 1db3f4bf2..2ade263a6 100644 --- a/docs/tutorials/gradients.ipynb +++ b/docs/tutorials/gradients.ipynb @@ -99,7 +99,7 @@ }, "outputs": [], "source": [ - "!pip install tensorflow==2.11.0" + "!pip install tensorflow==2.7.0" ] }, { @@ -122,7 +122,7 @@ }, "outputs": [], "source": [ - "!pip install tensorflow-quantum==0.7.3" + "!pip install tensorflow-quantum==0.7.2" ] }, { @@ -370,7 +370,7 @@ "outputs": [], "source": [ "# Make input_points = [batch_size, 1] array.\n", - "input_points = np.linspace(0, 5, 200)[:, np.newaxis].astype(np.float32)\n", + "input_points = np.linspace(0, 5, 200)[:, np.newaxis].astype(float)\n", "exact_outputs = expectation_calculation(my_circuit,\n", " operators=pauli_x,\n", " symbol_names=['alpha'],\n", diff --git a/scripts/test_tutorials.py b/scripts/test_tutorials.py index 13df27aef..7424fe38c 100644 --- a/scripts/test_tutorials.py +++ b/scripts/test_tutorials.py @@ -50,6 +50,5 @@ def test_notebook(self, path): timeout=900, kernel_name="python3") - if __name__ == "__main__": tf.test.main() From ea8536f97eac26ff1d308bcf378bdbc80d3df046 Mon Sep 17 00:00:00 2001 From: Michael Broughton Date: Mon, 12 Jun 2023 14:21:30 -0700 Subject: [PATCH 37/50] Revert "Upgrade the latest gym for notebook tutorial." This reverts commit 9b94ebf2e4ff4cbabacf03bd52eebab4327409f0. --- scripts/ci_validate_tutorials.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/ci_validate_tutorials.sh b/scripts/ci_validate_tutorials.sh index 45e97ff79..74c9189a1 100755 --- a/scripts/ci_validate_tutorials.sh +++ b/scripts/ci_validate_tutorials.sh @@ -19,7 +19,7 @@ pip install jupyter nbconvert==6.4.3 jupyter-client==6.1.12 ipython==7.22.0 # Workaround for ipykernel - see https://github.com/ipython/ipykernel/issues/422 pip install ipykernel==5.1.1 # OpenAI Gym pip package needed for the quantum reinforcement learning tutorial -pip install gym==0.24.1 +pip install gym==0.18.0 # tf_docs pip package needed for noise tutorial. pip install -q git+https://github.com/tensorflow/docs # Leave the quantum directory, otherwise errors may occur From ec60c0f3cadfb1fa66521636514c75c4f401b923 Mon Sep 17 00:00:00 2001 From: Michael Broughton Date: Mon, 12 Jun 2023 14:23:13 -0700 Subject: [PATCH 38/50] Revert "Format optimizers" This reverts commit 39a811d1a2ba8e854f800ba23157a7cc017a8cf4. --- .../python/optimizers/rotosolve_minimizer.py | 527 +++++++++--------- .../python/optimizers/spsa_minimizer.py | 104 ++++ 2 files changed, 368 insertions(+), 263 deletions(-) diff --git a/tensorflow_quantum/python/optimizers/rotosolve_minimizer.py b/tensorflow_quantum/python/optimizers/rotosolve_minimizer.py index bd1270068..65998d929 100755 --- a/tensorflow_quantum/python/optimizers/rotosolve_minimizer.py +++ b/tensorflow_quantum/python/optimizers/rotosolve_minimizer.py @@ -1,263 +1,264 @@ -# 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. -# See the License for the specific language governing permissions and -# limitations under the License. -# ============================================================================== -"""The rotosolve minimization algorithm""" -import collections -import numpy as np -import tensorflow as tf - - -def prefer_static_shape(x): - """Return static shape of tensor `x` if available, - - else `tf.shape(x)`. - - Args: - x: `tf.Tensor` (already converted). - Returns: - Numpy array (if static shape is obtainable), else `tf.Tensor`. - """ - return prefer_static_value(tf.shape(x)) - - -def prefer_static_value(x): - """Return static value of tensor `x` if available, else `x`. - - Args: - x: `tf.Tensor` (already converted). - Returns: - Numpy array (if static value is obtainable), else `tf.Tensor`. - """ - static_x = tf.get_static_value(x) - if static_x is not None: - return static_x - return x - - -RotosolveOptimizerResults = collections.namedtuple( - 'RotosolveOptimizerResults', - [ - 'converged', - # Scalar boolean tensor indicating whether the minimum - # was found within tolerance. - 'num_iterations', - # The number of iterations of the rotosolve update. - 'num_objective_evaluations', - # The total number of objective - # evaluations performed. - 'position', - # A tensor containing the last argument value found - # during the search. If the search converged, then - # this value is the argmin of the objective function. - # A tensor containing the value of the objective from - # previous iteration - 'objective_value_previous_iteration', - # Save the evaluated value of the objective function - # from the previous iteration - 'objective_value', - # A tensor containing the value of the objective - # function at the `position`. If the search - # converged, then this is the (local) minimum of - # the objective function. - 'tolerance', - # Define the stop criteria. Iteration will stop when the - # objective value difference between two iterations is - # smaller than tolerance - 'solve_param_i', - # The parameter index where rotosolve is currently - # modifying. Reserved for internal use. - ]) - - -def _get_initial_state(initial_position, tolerance, expectation_value_function): - """Create RotosolveOptimizerResults with initial state of search.""" - init_args = { - "converged": tf.Variable(False), - "num_iterations": tf.Variable(0), - "num_objective_evaluations": tf.Variable(0), - "position": tf.Variable(initial_position), - "objective_value": tf.Variable(0.), - "objective_value_previous_iteration": tf.Variable(0.), - "tolerance": tolerance, - "solve_param_i": tf.Variable(0) - } - return RotosolveOptimizerResults(**init_args) - - -def minimize(expectation_value_function, - initial_position, - tolerance=1e-5, - max_iterations=50, - name=None): - """Applies the rotosolve algorithm. - - The rotosolve algorithm can be used to minimize a linear combination - - of quantum measurement expectation values. See the following paper: - - [arXiv:1903.12166](https://arxiv.org/abs/1903.12166), Ken M. Nakanishi. - [arXiv:1905.09692](https://arxiv.org/abs/1905.09692), Mateusz Ostaszewski. - - Usage: - - Here is an example of optimize a function which consists summation of - a few sinusoids. - - >>> n = 10 # Number of sinusoids - >>> coefficient = tf.random.uniform(shape=[n]) - >>> min_value = -tf.math.reduce_sum(tf.abs(coefficient)) - >>> func = lambda x:tf.math.reduce_sum(tf.sin(x) * coefficient) - >>> # Optimize the function with rotosolve, start with random parameters - >>> result = tfq.optimizers.rotosolve_minimize(func, np.random.random(n)) - >>> result.converged - tf.Tensor(True, shape=(), dtype=bool) - >>> result.objective_value - tf.Tensor(-4.7045116, shape=(), dtype=float32) - - Args: - expectation_value_function: A Python callable that accepts - a point as a real `tf.Tensor` and returns a `tf.Tensor`s - of real dtype containing the value of the function. - The function to be minimized. The input is of shape `[n]`, - where `n` is the size of the trainable parameters. - The return value is a real `tf.Tensor` Scalar (matching shape - `[1]`). This must be a linear combination of quantum - measurement expectation value, otherwise this algorithm cannot - work. - initial_position: Real `tf.Tensor` of shape `[n]`. The starting - point, or points when using batching dimensions, of the search - procedure. At these points the function value and the gradient - norm should be finite. - tolerance: Scalar `tf.Tensor` of real dtype. Specifies the tolerance - for the procedure. If the supremum norm between two iteration - vector is below this number, the algorithm is stopped. - name: (Optional) Python `str`. The name prefixed to the ops created - by this function. If not supplied, the default name 'minimize' - is used. - - Returns: - optimizer_results: A RotosolveOptimizerResults object contains the - result of the optimization process. - """ - - with tf.name_scope(name or 'minimize'): - initial_position = tf.convert_to_tensor(initial_position, - name='initial_position', - dtype='float32') - dtype = initial_position.dtype.base_dtype - tolerance = tf.convert_to_tensor(tolerance, - dtype=dtype, - name='grad_tolerance') - max_iterations = tf.convert_to_tensor(max_iterations, - name='max_iterations') - - def _rotosolve_one_parameter_once(state): - """Rotosolve a single parameter once. - - Args: - state: A RotosolveOptimizerResults object stores the - current state of the minimizer. - - Returns: - states: A list which the first element is the new state - """ - delta_shift = tf.scatter_nd([[state.solve_param_i]], - [tf.constant(np.pi / 2, dtype=dtype)], - prefer_static_shape(state.position)) - - # Evaluate three different point for curve fitting - v_l, v_n, v_r = expectation_value_function( - state.position - delta_shift), \ - state.objective_value, \ - expectation_value_function(state.position + delta_shift) - - # Use the analytical solution to find the optimized position - delta_update = -np.pi / 2 - \ - tf.math.atan2(2 * v_n - v_l - v_r, v_r - v_l) - - delta_update_tensor = tf.scatter_nd( - [[state.solve_param_i]], [delta_update], - prefer_static_shape(state.position)) - - state.solve_param_i.assign_add(1) - state.position.assign( - tf.math.floormod(state.position + delta_update_tensor, - np.pi * 2)) - - state.objective_value_previous_iteration.assign( - state.objective_value) - state.objective_value.assign( - expectation_value_function(state.position)) - - return [state] - - def _rotosolve_all_parameters_once(state): - """Iterate over all parameters and rotosolve each single - - of them once. - - Args: - state: A RotosolveOptimizerResults object stores the - current state of the minimizer. - - Returns: - states: A list which the first element is the new state - """ - - def _cond_internal(state_cond): - return state_cond.solve_param_i < \ - prefer_static_shape(state_cond.position)[0] - - state.num_objective_evaluations.assign_add(1) - - return tf.while_loop( - cond=_cond_internal, - body=_rotosolve_one_parameter_once, - loop_vars=[state], - parallel_iterations=1, - ) - - # The `state` here is a `RotosolveOptimizerResults` tuple with - # values for the current state of the algorithm computation. - def _cond(state): - """Continue if iterations remain and stopping condition - is not met.""" - return (state.num_iterations < max_iterations) \ - and (not state.converged) - - def _body(state): - """Main optimization loop.""" - - state.solve_param_i.assign(0) - - _rotosolve_all_parameters_once(state) - - state.num_iterations.assign_add(1) - state.converged.assign( - tf.abs(state.objective_value - - state.objective_value_previous_iteration) < - state.tolerance) - - return [state] - - initial_state = _get_initial_state(initial_position, tolerance, - expectation_value_function) - - initial_state.objective_value.assign( - expectation_value_function(initial_state.position)) - - return tf.while_loop(cond=_cond, - body=_body, - loop_vars=[initial_state], - parallel_iterations=1)[0] +<<<<<<< HEAD +# 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. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== +"""The rotosolve minimization algorithm""" +import collections +import numpy as np +import tensorflow as tf + + +def prefer_static_shape(x): + """Return static shape of tensor `x` if available, + + else `tf.shape(x)`. + + Args: + x: `tf.Tensor` (already converted). + Returns: + Numpy array (if static shape is obtainable), else `tf.Tensor`. + """ + return prefer_static_value(tf.shape(x)) + + +def prefer_static_value(x): + """Return static value of tensor `x` if available, else `x`. + + Args: + x: `tf.Tensor` (already converted). + Returns: + Numpy array (if static value is obtainable), else `tf.Tensor`. + """ + static_x = tf.get_static_value(x) + if static_x is not None: + return static_x + return x + + +RotosolveOptimizerResults = collections.namedtuple( + 'RotosolveOptimizerResults', + [ + 'converged', + # Scalar boolean tensor indicating whether the minimum + # was found within tolerance. + 'num_iterations', + # The number of iterations of the rotosolve update. + 'num_objective_evaluations', + # The total number of objective + # evaluations performed. + 'position', + # A tensor containing the last argument value found + # during the search. If the search converged, then + # this value is the argmin of the objective function. + # A tensor containing the value of the objective from + # previous iteration + 'objective_value_previous_iteration', + # Save the evaluated value of the objective function + # from the previous iteration + 'objective_value', + # A tensor containing the value of the objective + # function at the `position`. If the search + # converged, then this is the (local) minimum of + # the objective function. + 'tolerance', + # Define the stop criteria. Iteration will stop when the + # objective value difference between two iterations is + # smaller than tolerance + 'solve_param_i', + # The parameter index where rotosolve is currently + # modifying. Reserved for internal use. + ]) + + +def _get_initial_state(initial_position, tolerance, expectation_value_function): + """Create RotosolveOptimizerResults with initial state of search.""" + init_args = { + "converged": tf.Variable(False), + "num_iterations": tf.Variable(0), + "num_objective_evaluations": tf.Variable(0), + "position": tf.Variable(initial_position), + "objective_value": tf.Variable(0.), + "objective_value_previous_iteration": tf.Variable(0.), + "tolerance": tolerance, + "solve_param_i": tf.Variable(0) + } + return RotosolveOptimizerResults(**init_args) + + +def minimize(expectation_value_function, + initial_position, + tolerance=1e-5, + max_iterations=50, + name=None): + """Applies the rotosolve algorithm. + + The rotosolve algorithm can be used to minimize a linear combination + + of quantum measurement expectation values. See the following paper: + + [arXiv:1903.12166](https://arxiv.org/abs/1903.12166), Ken M. Nakanishi. + [arXiv:1905.09692](https://arxiv.org/abs/1905.09692), Mateusz Ostaszewski. + + Usage: + + Here is an example of optimize a function which consists summation of + a few sinusoids. + + >>> n = 10 # Number of sinusoids + >>> coefficient = tf.random.uniform(shape=[n]) + >>> min_value = -tf.math.reduce_sum(tf.abs(coefficient)) + >>> func = lambda x:tf.math.reduce_sum(tf.sin(x) * coefficient) + >>> # Optimize the function with rotosolve, start with random parameters + >>> result = tfq.optimizers.rotosolve_minimize(func, np.random.random(n)) + >>> result.converged + tf.Tensor(True, shape=(), dtype=bool) + >>> result.objective_value + tf.Tensor(-4.7045116, shape=(), dtype=float32) + + Args: + expectation_value_function: A Python callable that accepts + a point as a real `tf.Tensor` and returns a `tf.Tensor`s + of real dtype containing the value of the function. + The function to be minimized. The input is of shape `[n]`, + where `n` is the size of the trainable parameters. + The return value is a real `tf.Tensor` Scalar (matching shape + `[1]`). This must be a linear combination of quantum + measurement expectation value, otherwise this algorithm cannot + work. + initial_position: Real `tf.Tensor` of shape `[n]`. The starting + point, or points when using batching dimensions, of the search + procedure. At these points the function value and the gradient + norm should be finite. + tolerance: Scalar `tf.Tensor` of real dtype. Specifies the tolerance + for the procedure. If the supremum norm between two iteration + vector is below this number, the algorithm is stopped. + name: (Optional) Python `str`. The name prefixed to the ops created + by this function. If not supplied, the default name 'minimize' + is used. + + Returns: + optimizer_results: A RotosolveOptimizerResults object contains the + result of the optimization process. + """ + + with tf.name_scope(name or 'minimize'): + initial_position = tf.convert_to_tensor(initial_position, + name='initial_position', + dtype='float32') + dtype = initial_position.dtype.base_dtype + tolerance = tf.convert_to_tensor(tolerance, + dtype=dtype, + name='grad_tolerance') + max_iterations = tf.convert_to_tensor(max_iterations, + name='max_iterations') + + def _rotosolve_one_parameter_once(state): + """Rotosolve a single parameter once. + + Args: + state: A RotosolveOptimizerResults object stores the + current state of the minimizer. + + Returns: + states: A list which the first element is the new state + """ + delta_shift = tf.scatter_nd([[state.solve_param_i]], + [tf.constant(np.pi / 2, dtype=dtype)], + prefer_static_shape(state.position)) + + # Evaluate three different point for curve fitting + v_l, v_n, v_r = expectation_value_function( + state.position - delta_shift), \ + state.objective_value, \ + expectation_value_function(state.position + delta_shift) + + # Use the analytical solution to find the optimized position + delta_update = -np.pi / 2 - \ + tf.math.atan2(2 * v_n - v_l - v_r, v_r - v_l) + + delta_update_tensor = tf.scatter_nd( + [[state.solve_param_i]], [delta_update], + prefer_static_shape(state.position)) + + state.solve_param_i.assign_add(1) + state.position.assign( + tf.math.floormod(state.position + delta_update_tensor, + np.pi * 2)) + + state.objective_value_previous_iteration.assign( + state.objective_value) + state.objective_value.assign( + expectation_value_function(state.position)) + + return [state] + + def _rotosolve_all_parameters_once(state): + """Iterate over all parameters and rotosolve each single + + of them once. + + Args: + state: A RotosolveOptimizerResults object stores the + current state of the minimizer. + + Returns: + states: A list which the first element is the new state + """ + + def _cond_internal(state_cond): + return state_cond.solve_param_i < \ + prefer_static_shape(state_cond.position)[0] + + state.num_objective_evaluations.assign_add(1) + + return tf.while_loop( + cond=_cond_internal, + body=_rotosolve_one_parameter_once, + loop_vars=[state], + parallel_iterations=1, + ) + + # The `state` here is a `RotosolveOptimizerResults` tuple with + # values for the current state of the algorithm computation. + def _cond(state): + """Continue if iterations remain and stopping condition + is not met.""" + return (state.num_iterations < max_iterations) \ + and (not state.converged) + + def _body(state): + """Main optimization loop.""" + + state.solve_param_i.assign(0) + + _rotosolve_all_parameters_once(state) + + state.num_iterations.assign_add(1) + state.converged.assign( + tf.abs(state.objective_value - + state.objective_value_previous_iteration) < + state.tolerance) + + return [state] + + initial_state = _get_initial_state(initial_position, tolerance, + expectation_value_function) + + initial_state.objective_value.assign( + expectation_value_function(initial_state.position)) + + return tf.while_loop(cond=_cond, + body=_body, + loop_vars=[initial_state], + parallel_iterations=1)[0] diff --git a/tensorflow_quantum/python/optimizers/spsa_minimizer.py b/tensorflow_quantum/python/optimizers/spsa_minimizer.py index 1b40ef00e..31e753aac 100644 --- a/tensorflow_quantum/python/optimizers/spsa_minimizer.py +++ b/tensorflow_quantum/python/optimizers/spsa_minimizer.py @@ -45,6 +45,7 @@ def prefer_static_value(x): return x +<<<<<<< HEAD SPSAOptimizerResults = collections.namedtuple( 'SPSAOptimizerResults', [ @@ -89,6 +90,80 @@ def prefer_static_value(x): # Specifies maximum allowable increase in objective function # (only applies if blocking is true). ]) +======= +class SPSAOptimizerResults(tf.experimental.ExtensionType): + converged: tf.Tensor + # Scalar boolean tensor indicating whether the minimum + # was found within tolerance. + num_iterations: tf.Tensor + # The number of iterations of the SPSA update. + num_objective_evaluations: tf.Tensor + # The total number of objective + # evaluations performed. + position: tf.Tensor + # A tensor containing the last argument value found + # during the search. If the search converged, then + # this value is the argmin of the objective function. + # A tensor containing the value of the objective from + # previous iteration + objective_value_previous_iteration: tf.Tensor + # Save the evaluated value of the objective function + # from the previous iteration + objective_value: tf.Tensor + # A tensor containing the value of the objective + # function at the `position`. If the search + # converged, then this is the (local) minimum of + # the objective function. + tolerance: tf.Tensor + # Define the stop criteria. Iteration will stop when the + # objective value difference between two iterations is + # smaller than tolerance + lr: tf.Tensor + # Specifies the learning rate + alpha: tf.Tensor + # Specifies scaling of the learning rate + perturb: tf.Tensor + # Specifies the size of the perturbations + gamma: tf.Tensor + # Specifies scaling of the size of the perturbations + blocking: tf.Tensor + # If true, then the optimizer will only accept updates that improve + # the objective function. + allowed_increase: tf.Tensor + + # Specifies maximum allowable increase in objective function + # (only applies if blocking is true). + + def to_dict(self): + return { + "converged": + self.converged, + "num_iterations": + self.num_iterations, + "num_objective_evaluations": + self.num_objective_evaluations, + "position": + self.position, + "objective_value": + self.objective_value, + "objective_value_previous_iteration": + self.objective_value_previous_iteration, + "tolerance": + self.tolerance, + "lr": + self.lr, + "alpha": + self.alpha, + "perturb": + self.perturb, + "gamma": + self.gamma, + "blocking": + self.blocking, + "allowed_increase": + self.allowed_increase, + } +>>>>>>> parent of 39a811d (Format optimizers) def _get_initial_state(initial_position, tolerance, expectation_value_function, @@ -99,7 +174,12 @@ def _get_initial_state(initial_position, tolerance, expectation_value_function, "num_iterations": tf.Variable(0), "num_objective_evaluations": tf.Variable(0), "position": tf.Variable(initial_position), +<<<<<<< HEAD "objective_value": tf.Variable(0.), +======= + "objective_value": + (tf.cast(expectation_value_function(initial_position), tf.float32)), +>>>>>>> parent of 39a811d (Format optimizers) "objective_value_previous_iteration": tf.Variable(np.inf), "tolerance": tolerance, "lr": tf.Variable(lr), @@ -256,6 +336,7 @@ def _body(state): new_perturb = perturb_init / (tf.cast(state.num_iterations + 1, tf.float32)**state.gamma) +<<<<<<< HEAD state.lr.assign(new_lr) state.perturb.assign(new_perturb) @@ -266,15 +347,38 @@ def _body(state): state.objective_value_previous_iteration) < state.tolerance) return [state] +======= + pre_state_params = state.to_dict() + pre_state_params.update({ + "lr": new_lr, + "perturb": new_perturb, + }) + + post_state = _spsa_once(SPSAOptimizerResults(**pre_state_params))[0] + post_state_params = post_state.to_dict() + tf.print("asdf", state.objective_value.dtype, + state.objective_value_previous_iteration.dtype) + post_state_params.update({ + "num_iterations": + post_state.num_iterations + 1, + "converged": (tf.abs(state.objective_value - + state.objective_value_previous_iteration) < + state.tolerance), + }) + return [SPSAOptimizerResults(**post_state_params)] +>>>>>>> parent of 39a811d (Format optimizers) initial_state = _get_initial_state(initial_position, tolerance, expectation_value_function, lr, alpha, perturb, gamma, blocking, allowed_increase) +<<<<<<< HEAD initial_state.objective_value.assign( tf.cast(expectation_value_function(initial_state.position), tf.float32)) +======= +>>>>>>> parent of 39a811d (Format optimizers) return tf.while_loop(cond=_cond, body=_body, From c0be4b0e25a50684a7061f17e893493851fe6f9f Mon Sep 17 00:00:00 2001 From: Michael Broughton Date: Mon, 12 Jun 2023 14:31:04 -0700 Subject: [PATCH 39/50] Revert "Format" This reverts commit a22b98fa4fef34a4df9174e33d2c455b675337c4. --- .../core/src/circuit_parser_qsim.cc | 18 ++++++--- .../core/src/circuit_parser_qsim_test.cc | 39 ++++++++++++------- .../core/src/program_resolution.cc | 30 +++++++++----- 3 files changed, 58 insertions(+), 29 deletions(-) diff --git a/tensorflow_quantum/core/src/circuit_parser_qsim.cc b/tensorflow_quantum/core/src/circuit_parser_qsim.cc index 8a7b2d490..52b0d5fb2 100644 --- a/tensorflow_quantum/core/src/circuit_parser_qsim.cc +++ b/tensorflow_quantum/core/src/circuit_parser_qsim.cc @@ -57,7 +57,8 @@ inline Status ParseProtoArg( // iterator> const auto arg_v = op.args().find(arg_name); if (arg_v == op.args().end()) { - return Status(tensorflow::error::INVALID_ARGUMENT, + return Status(static_cast( + absl::StatusCode::kInvalidArgument), "Could not find arg: " + arg_name + " in op."); } // find proto arg field. @@ -69,7 +70,8 @@ inline Status ParseProtoArg( const auto iter = param_map.find(proto_arg.symbol()); if (iter == param_map.end()) { return Status( - tensorflow::error::INVALID_ARGUMENT, + static_cast( + absl::StatusCode::kInvalidArgument), "Could not find symbol in parameter map: " + proto_arg.symbol()); } *result = iter->second.second; @@ -100,7 +102,8 @@ inline Status ParseProtoControls(const Operation& op, absl::StrSplit(control_v_str, ','); if (control_toks.size() != control_v_toks.size()) { - return Status(tensorflow::error::INVALID_ARGUMENT, + return Status(static_cast( + absl::StatusCode::kInvalidArgument), "Mistmatched number of control qubits and control values."); } if (control_toks.empty()) { @@ -119,7 +122,8 @@ inline Status ParseProtoControls(const Operation& op, for (auto tok : control_v_toks) { valid = absl::SimpleAtoi(tok, &tmp); if (!valid) { - return Status(tensorflow::error::INVALID_ARGUMENT, + return Status(static_cast( + absl::StatusCode::kInvalidArgument), "Unparseable control value: " + std::string(tok)); } control_values->push_back(tmp); @@ -590,7 +594,8 @@ tensorflow::Status ParseAppendGate(const Operation& op, auto build_f = func_map.find(op.gate().id()); if (build_f == func_map.end()) { *lookup_succeeded = false; - return Status(tensorflow::error::INVALID_ARGUMENT, + return Status(static_cast( + absl::StatusCode::kInvalidArgument), absl::StrCat("Could not parse gate id: ", op.gate().id(), ". This is likely because a cirq.Channel was " "used in an op that does not support them.")); @@ -774,7 +779,8 @@ tensorflow::Status ParseAppendChannel(const Operation& op, auto build_f = chan_func_map.find(op.gate().id()); if (build_f == chan_func_map.end()) { - return Status(tensorflow::error::INVALID_ARGUMENT, + return Status(static_cast( + absl::StatusCode::kInvalidArgument), absl::StrCat("Could not parse channel id: ", op.gate().id())); } return build_f->second(op, num_qubits, time, ncircuit); diff --git a/tensorflow_quantum/core/src/circuit_parser_qsim_test.cc b/tensorflow_quantum/core/src/circuit_parser_qsim_test.cc index 4cfb40424..f3bc078e8 100644 --- a/tensorflow_quantum/core/src/circuit_parser_qsim_test.cc +++ b/tensorflow_quantum/core/src/circuit_parser_qsim_test.cc @@ -191,7 +191,8 @@ TEST_P(TwoQubitEigenFixture, TwoEigenGate) { // Test case where proto arg missing. ASSERT_EQ(QsimCircuitFromProgram(program_proto, symbol_map, 2, &test_circuit, &fused_circuit), - tensorflow::Status(tensorflow::error::INVALID_ARGUMENT, + tensorflow::Status(static_cast( + absl::StatusCode::kInvalidArgument), "Could not find arg: exponent in op.")); test_circuit.gates.clear(); @@ -203,7 +204,8 @@ TEST_P(TwoQubitEigenFixture, TwoEigenGate) { ASSERT_EQ( QsimCircuitFromProgram(program_proto, symbol_map, 2, &test_circuit, &fused_circuit), - tensorflow::Status(tensorflow::error::INVALID_ARGUMENT, + tensorflow::Status(static_cast( + absl::StatusCode::kInvalidArgument), "Could not find symbol in parameter map: alpha")); } @@ -361,7 +363,8 @@ TEST_P(SingleQubitEigenFixture, SingleEigenGate) { // Test case where proto arg missing. ASSERT_EQ(QsimCircuitFromProgram(program_proto, symbol_map, 1, &test_circuit, &fused_circuit), - tensorflow::Status(tensorflow::error::INVALID_ARGUMENT, + tensorflow::Status(static_cast( + absl::StatusCode::kInvalidArgument), "Could not find arg: exponent in op.")); test_circuit.gates.clear(); @@ -373,7 +376,8 @@ TEST_P(SingleQubitEigenFixture, SingleEigenGate) { ASSERT_EQ( QsimCircuitFromProgram(program_proto, symbol_map, 1, &test_circuit, &fused_circuit), - tensorflow::Status(tensorflow::error::INVALID_ARGUMENT, + tensorflow::Status(static_cast( + absl::StatusCode::kInvalidArgument), "Could not find symbol in parameter map: alpha")); } @@ -691,7 +695,8 @@ TEST(QsimCircuitParserTest, FsimGate) { // Test case where proto arg missing. ASSERT_EQ(QsimCircuitFromProgram(program_proto, symbol_map, 2, &test_circuit, &fused_circuit), - tensorflow::Status(tensorflow::error::INVALID_ARGUMENT, + tensorflow::Status(static_cast( + absl::StatusCode::kInvalidArgument), "Could not find arg: theta in op.")); test_circuit.gates.clear(); @@ -703,7 +708,8 @@ TEST(QsimCircuitParserTest, FsimGate) { ASSERT_EQ( QsimCircuitFromProgram(program_proto, symbol_map, 2, &test_circuit, &fused_circuit), - tensorflow::Status(tensorflow::error::INVALID_ARGUMENT, + tensorflow::Status(static_cast( + absl::StatusCode::kInvalidArgument), "Could not find symbol in parameter map: alpha")); } @@ -853,7 +859,8 @@ TEST(QsimCircuitParserTest, PhasedISwap) { // Test case where proto arg missing. ASSERT_EQ(QsimCircuitFromProgram(program_proto, symbol_map, 2, &test_circuit, &fused_circuit), - tensorflow::Status(tensorflow::error::INVALID_ARGUMENT, + tensorflow::Status(static_cast( + absl::StatusCode::kInvalidArgument), "Could not find arg: phase_exponent in op.")); test_circuit.gates.clear(); @@ -865,7 +872,8 @@ TEST(QsimCircuitParserTest, PhasedISwap) { ASSERT_EQ( QsimCircuitFromProgram(program_proto, symbol_map, 2, &test_circuit, &fused_circuit), - tensorflow::Status(tensorflow::error::INVALID_ARGUMENT, + tensorflow::Status(static_cast( + absl::StatusCode::kInvalidArgument), "Could not find symbol in parameter map: alpha")); } @@ -1019,7 +1027,8 @@ TEST(QsimCircuitParserTest, PhasedXPow) { // Test case where proto arg missing. ASSERT_EQ(QsimCircuitFromProgram(program_proto, symbol_map, 1, &test_circuit, &fused_circuit), - tensorflow::Status(tensorflow::error::INVALID_ARGUMENT, + tensorflow::Status(static_cast( + absl::StatusCode::kInvalidArgument), "Could not find arg: phase_exponent in op.")); test_circuit.gates.clear(); @@ -1031,7 +1040,8 @@ TEST(QsimCircuitParserTest, PhasedXPow) { ASSERT_EQ( QsimCircuitFromProgram(program_proto, symbol_map, 1, &test_circuit, &fused_circuit), - tensorflow::Status(tensorflow::error::INVALID_ARGUMENT, + tensorflow::Status(static_cast( + absl::StatusCode::kInvalidArgument), "Could not find symbol in parameter map: alpha")); } @@ -1124,7 +1134,8 @@ TEST(QsimCircuitParserTest, InvalidControlValues) { ASSERT_EQ(QsimCircuitFromProgram(program_proto, empty_map, 3, &test_circuit, &fused_circuit, &metadata), - tensorflow::Status(tensorflow::error::INVALID_ARGUMENT, + tensorflow::Status(static_cast( + absl::StatusCode::kInvalidArgument), "Unparseable control value: junk")); } @@ -1157,7 +1168,8 @@ TEST(QsimCircuitParserTest, MismatchControlNum) { ASSERT_EQ(QsimCircuitFromProgram(program_proto, empty_map, 3, &test_circuit, &fused_circuit, &metadata), tensorflow::Status( - tensorflow::error::INVALID_ARGUMENT, + static_cast( + absl::StatusCode::kInvalidArgument), "Mistmatched number of control qubits and control values.")); } @@ -1559,7 +1571,8 @@ TEST(QsimCircuitParserTest, NoisyBadProto) { NoisyQsimCircuit test_circuit; ASSERT_EQ( NoisyQsimCircuitFromProgram(program_proto, {}, 1, false, &test_circuit), - tensorflow::Status(tensorflow::error::INVALID_ARGUMENT, + tensorflow::Status(static_cast( + absl::StatusCode::kInvalidArgument), "Could not parse channel id: ABCDEFG")); } diff --git a/tensorflow_quantum/core/src/program_resolution.cc b/tensorflow_quantum/core/src/program_resolution.cc index 82af94d35..a06b17b97 100644 --- a/tensorflow_quantum/core/src/program_resolution.cc +++ b/tensorflow_quantum/core/src/program_resolution.cc @@ -64,15 +64,18 @@ Status RegisterQubits( } if (splits.size() != 2) { - return Status(tensorflow::error::INVALID_ARGUMENT, + return Status(static_cast( + absl::StatusCode::kInvalidArgument), absl::StrCat("Unable to parse qubit: ", qb)); } if (!absl::SimpleAtoi(splits[0], &r)) { - return Status(tensorflow::error::INVALID_ARGUMENT, + return Status(static_cast( + absl::StatusCode::kInvalidArgument), absl::StrCat("Unable to parse qubit: ", qb)); } if (!absl::SimpleAtoi(splits[1], &c)) { - return Status(tensorflow::error::INVALID_ARGUMENT, + return Status(static_cast( + absl::StatusCode::kInvalidArgument), absl::StrCat("Unable to parse qubit: ", qb)); } auto locs = std::pair, std::string>( @@ -167,7 +170,8 @@ Status ResolveQubitIds(Program* program, unsigned int* num_qubits, const auto result = id_to_index.find(pair.qubit_id()); if (result == id_to_index.end()) { return Status( - tensorflow::error::INVALID_ARGUMENT, + static_cast( + absl::StatusCode::kInvalidArgument), "Found a Pauli sum operating on qubits not found in circuit."); } pair.set_qubit_id(result->second); @@ -258,7 +262,8 @@ Status ResolveQubitIds(Program* program, unsigned int* num_qubits, visited_qubits.erase(qubit.id()); const auto result = id_to_index.find(qubit.id()); if (result == id_to_index.end()) { - return Status(tensorflow::error::INVALID_ARGUMENT, + return Status(static_cast( + absl::StatusCode::kInvalidArgument), "A paired circuit contains qubits not found in " "reference circuit."); } @@ -280,7 +285,8 @@ Status ResolveQubitIds(Program* program, unsigned int* num_qubits, visited_qubits.erase(id); const auto result = id_to_index.find(id); if (result == id_to_index.end()) { - return Status(tensorflow::error::INVALID_ARGUMENT, + return Status(static_cast( + absl::StatusCode::kInvalidArgument), "A paired circuit contains qubits not found in " "reference circuit."); } @@ -294,7 +300,8 @@ Status ResolveQubitIds(Program* program, unsigned int* num_qubits, } if (!visited_qubits.empty()) { return Status( - tensorflow::error::INVALID_ARGUMENT, + static_cast( + absl::StatusCode::kInvalidArgument), "A reference circuit contains qubits not found in paired circuit."); } } @@ -314,7 +321,8 @@ Status ResolveSymbols( if (iter == param_map.end()) { if (resolve_all) { return Status( - tensorflow::error::INVALID_ARGUMENT, + static_cast( + absl::StatusCode::kInvalidArgument), "Could not find symbol in parameter map: " + arg.symbol()); } continue; @@ -354,7 +362,8 @@ Status CheckMPSSupported(const Program& program) { const int total_num_qubits = qubits.size() + control_ids.size(); if (total_num_qubits > 2) { return Status( - tensorflow::error::INVALID_ARGUMENT, + static_cast( + absl::StatusCode::kInvalidArgument), absl::StrCat("1D operations only support 1 and 2 qubit gates. " "Found: ", total_num_qubits, " qubit gate.")); @@ -372,7 +381,8 @@ Status CheckMPSSupported(const Program& program) { // Are the two qubits not neighbors? if (std::abs((int)qids[0] - (int)qids[1]) > 1) { - return Status(tensorflow::error::INVALID_ARGUMENT, + return Status(static_cast( + absl::StatusCode::kInvalidArgument), "A program is not in 1D topology. It contains an" " operation with qubits not neighbors each other."); } From 612dd41038838f714273fc599344203f3bc8b1dd Mon Sep 17 00:00:00 2001 From: Michael Broughton Date: Mon, 12 Jun 2023 14:31:47 -0700 Subject: [PATCH 40/50] Revert "Upgrade to TF v2.11" This reverts commit 26fa2dfda35ab64585d03e20def1dfd42031b123. --- docs/tutorials/barren_plateaus.ipynb | 2 +- docs/tutorials/gradients.ipynb | 2 +- docs/tutorials/hello_many_worlds.ipynb | 8 ++-- docs/tutorials/mnist.ipynb | 4 +- .../quantum_reinforcement_learning.ipynb | 6 +-- .../core/src/circuit_parser_qsim.cc | 18 +++------ .../core/src/circuit_parser_qsim_test.cc | 39 +++++++------------ .../core/src/program_resolution.cc | 30 +++++--------- 8 files changed, 40 insertions(+), 69 deletions(-) diff --git a/docs/tutorials/barren_plateaus.ipynb b/docs/tutorials/barren_plateaus.ipynb index b35e4f76c..2447018c9 100644 --- a/docs/tutorials/barren_plateaus.ipynb +++ b/docs/tutorials/barren_plateaus.ipynb @@ -297,7 +297,7 @@ " # Prep the inputs as tensors\n", " circuit_tensor = tfq.convert_to_tensor(circuits)\n", " values_tensor = tf.convert_to_tensor(\n", - " np.random.uniform(0, 2 * np.pi, (n_circuits, 1)).astype(float))\n", + " np.random.uniform(0, 2 * np.pi, (n_circuits, 1)).astype(np.float32))\n", "\n", " # Use TensorFlow GradientTape to track gradients.\n", " with tf.GradientTape() as g:\n", diff --git a/docs/tutorials/gradients.ipynb b/docs/tutorials/gradients.ipynb index 2ade263a6..62a7ce103 100644 --- a/docs/tutorials/gradients.ipynb +++ b/docs/tutorials/gradients.ipynb @@ -370,7 +370,7 @@ "outputs": [], "source": [ "# Make input_points = [batch_size, 1] array.\n", - "input_points = np.linspace(0, 5, 200)[:, np.newaxis].astype(float)\n", + "input_points = np.linspace(0, 5, 200)[:, np.newaxis].astype(np.float32)\n", "exact_outputs = expectation_calculation(my_circuit,\n", " operators=pauli_x,\n", " symbol_names=['alpha'],\n", diff --git a/docs/tutorials/hello_many_worlds.ipynb b/docs/tutorials/hello_many_worlds.ipynb index 98a0e1b15..f3dd7fe19 100644 --- a/docs/tutorials/hello_many_worlds.ipynb +++ b/docs/tutorials/hello_many_worlds.ipynb @@ -739,10 +739,10 @@ "outputs": [], "source": [ "# The command input values to the classical NN.\n", - "commands = np.array([[0], [1]], dtype=float)\n", + "commands = np.array([[0], [1]], dtype=np.float32)\n", "\n", "# The desired Z expectation value at output of quantum circuit.\n", - "expected_outputs = np.array([[1], [-1]], dtype=float)" + "expected_outputs = np.array([[1], [-1]], dtype=np.float32)" ] }, { @@ -1108,10 +1108,10 @@ "operator_data = tfq.convert_to_tensor([[cirq.X(qubit)], [cirq.Z(qubit)]])\n", "\n", "# The command input values to the classical NN.\n", - "commands = np.array([[0], [1]], dtype=float)\n", + "commands = np.array([[0], [1]], dtype=np.float32)\n", "\n", "# The desired expectation value at output of quantum circuit.\n", - "expected_outputs = np.array([[1], [-1]], dtype=float)" + "expected_outputs = np.array([[1], [-1]], dtype=np.float32)" ] }, { diff --git a/docs/tutorials/mnist.ipynb b/docs/tutorials/mnist.ipynb index baed1eac9..b80f2500f 100644 --- a/docs/tutorials/mnist.ipynb +++ b/docs/tutorials/mnist.ipynb @@ -480,8 +480,8 @@ "source": [ "THRESHOLD = 0.5\n", "\n", - "x_train_bin = np.array(x_train_nocon > THRESHOLD, dtype=float)\n", - "x_test_bin = np.array(x_test_small > THRESHOLD, dtype=float)" + "x_train_bin = np.array(x_train_nocon > THRESHOLD, dtype=np.float32)\n", + "x_test_bin = np.array(x_test_small > THRESHOLD, dtype=np.float32)" ] }, { diff --git a/docs/tutorials/quantum_reinforcement_learning.ipynb b/docs/tutorials/quantum_reinforcement_learning.ipynb index 5a59f4080..50298fe8a 100644 --- a/docs/tutorials/quantum_reinforcement_learning.ipynb +++ b/docs/tutorials/quantum_reinforcement_learning.ipynb @@ -864,7 +864,7 @@ " actions = np.concatenate([ep['actions'] for ep in episodes])\n", " rewards = [ep['rewards'] for ep in episodes]\n", " returns = np.concatenate([compute_returns(ep_rwds, gamma) for ep_rwds in rewards])\n", - " returns = np.array(returns, dtype=float)\n", + " returns = np.array(returns, dtype=np.float32)\n", "\n", " id_action_pairs = np.array([[i, a] for i, a in enumerate(actions)])\n", " \n", @@ -1456,9 +1456,9 @@ " training_batch = np.random.choice(replay_memory, size=batch_size)\n", " Q_learning_update(np.asarray([x['state'] for x in training_batch]),\n", " np.asarray([x['action'] for x in training_batch]),\n", - " np.asarray([x['reward'] for x in training_batch], dtype=float),\n", + " np.asarray([x['reward'] for x in training_batch], dtype=np.float32),\n", " np.asarray([x['next_state'] for x in training_batch]),\n", - " np.asarray([x['done'] for x in training_batch], dtype=float),\n", + " np.asarray([x['done'] for x in training_batch], dtype=np.float32),\n", " model, gamma, n_actions)\n", " \n", " # Update target model\n", diff --git a/tensorflow_quantum/core/src/circuit_parser_qsim.cc b/tensorflow_quantum/core/src/circuit_parser_qsim.cc index 52b0d5fb2..8a7b2d490 100644 --- a/tensorflow_quantum/core/src/circuit_parser_qsim.cc +++ b/tensorflow_quantum/core/src/circuit_parser_qsim.cc @@ -57,8 +57,7 @@ inline Status ParseProtoArg( // iterator> const auto arg_v = op.args().find(arg_name); if (arg_v == op.args().end()) { - return Status(static_cast( - absl::StatusCode::kInvalidArgument), + return Status(tensorflow::error::INVALID_ARGUMENT, "Could not find arg: " + arg_name + " in op."); } // find proto arg field. @@ -70,8 +69,7 @@ inline Status ParseProtoArg( const auto iter = param_map.find(proto_arg.symbol()); if (iter == param_map.end()) { return Status( - static_cast( - absl::StatusCode::kInvalidArgument), + tensorflow::error::INVALID_ARGUMENT, "Could not find symbol in parameter map: " + proto_arg.symbol()); } *result = iter->second.second; @@ -102,8 +100,7 @@ inline Status ParseProtoControls(const Operation& op, absl::StrSplit(control_v_str, ','); if (control_toks.size() != control_v_toks.size()) { - return Status(static_cast( - absl::StatusCode::kInvalidArgument), + return Status(tensorflow::error::INVALID_ARGUMENT, "Mistmatched number of control qubits and control values."); } if (control_toks.empty()) { @@ -122,8 +119,7 @@ inline Status ParseProtoControls(const Operation& op, for (auto tok : control_v_toks) { valid = absl::SimpleAtoi(tok, &tmp); if (!valid) { - return Status(static_cast( - absl::StatusCode::kInvalidArgument), + return Status(tensorflow::error::INVALID_ARGUMENT, "Unparseable control value: " + std::string(tok)); } control_values->push_back(tmp); @@ -594,8 +590,7 @@ tensorflow::Status ParseAppendGate(const Operation& op, auto build_f = func_map.find(op.gate().id()); if (build_f == func_map.end()) { *lookup_succeeded = false; - return Status(static_cast( - absl::StatusCode::kInvalidArgument), + return Status(tensorflow::error::INVALID_ARGUMENT, absl::StrCat("Could not parse gate id: ", op.gate().id(), ". This is likely because a cirq.Channel was " "used in an op that does not support them.")); @@ -779,8 +774,7 @@ tensorflow::Status ParseAppendChannel(const Operation& op, auto build_f = chan_func_map.find(op.gate().id()); if (build_f == chan_func_map.end()) { - return Status(static_cast( - absl::StatusCode::kInvalidArgument), + return Status(tensorflow::error::INVALID_ARGUMENT, absl::StrCat("Could not parse channel id: ", op.gate().id())); } return build_f->second(op, num_qubits, time, ncircuit); diff --git a/tensorflow_quantum/core/src/circuit_parser_qsim_test.cc b/tensorflow_quantum/core/src/circuit_parser_qsim_test.cc index f3bc078e8..4cfb40424 100644 --- a/tensorflow_quantum/core/src/circuit_parser_qsim_test.cc +++ b/tensorflow_quantum/core/src/circuit_parser_qsim_test.cc @@ -191,8 +191,7 @@ TEST_P(TwoQubitEigenFixture, TwoEigenGate) { // Test case where proto arg missing. ASSERT_EQ(QsimCircuitFromProgram(program_proto, symbol_map, 2, &test_circuit, &fused_circuit), - tensorflow::Status(static_cast( - absl::StatusCode::kInvalidArgument), + tensorflow::Status(tensorflow::error::INVALID_ARGUMENT, "Could not find arg: exponent in op.")); test_circuit.gates.clear(); @@ -204,8 +203,7 @@ TEST_P(TwoQubitEigenFixture, TwoEigenGate) { ASSERT_EQ( QsimCircuitFromProgram(program_proto, symbol_map, 2, &test_circuit, &fused_circuit), - tensorflow::Status(static_cast( - absl::StatusCode::kInvalidArgument), + tensorflow::Status(tensorflow::error::INVALID_ARGUMENT, "Could not find symbol in parameter map: alpha")); } @@ -363,8 +361,7 @@ TEST_P(SingleQubitEigenFixture, SingleEigenGate) { // Test case where proto arg missing. ASSERT_EQ(QsimCircuitFromProgram(program_proto, symbol_map, 1, &test_circuit, &fused_circuit), - tensorflow::Status(static_cast( - absl::StatusCode::kInvalidArgument), + tensorflow::Status(tensorflow::error::INVALID_ARGUMENT, "Could not find arg: exponent in op.")); test_circuit.gates.clear(); @@ -376,8 +373,7 @@ TEST_P(SingleQubitEigenFixture, SingleEigenGate) { ASSERT_EQ( QsimCircuitFromProgram(program_proto, symbol_map, 1, &test_circuit, &fused_circuit), - tensorflow::Status(static_cast( - absl::StatusCode::kInvalidArgument), + tensorflow::Status(tensorflow::error::INVALID_ARGUMENT, "Could not find symbol in parameter map: alpha")); } @@ -695,8 +691,7 @@ TEST(QsimCircuitParserTest, FsimGate) { // Test case where proto arg missing. ASSERT_EQ(QsimCircuitFromProgram(program_proto, symbol_map, 2, &test_circuit, &fused_circuit), - tensorflow::Status(static_cast( - absl::StatusCode::kInvalidArgument), + tensorflow::Status(tensorflow::error::INVALID_ARGUMENT, "Could not find arg: theta in op.")); test_circuit.gates.clear(); @@ -708,8 +703,7 @@ TEST(QsimCircuitParserTest, FsimGate) { ASSERT_EQ( QsimCircuitFromProgram(program_proto, symbol_map, 2, &test_circuit, &fused_circuit), - tensorflow::Status(static_cast( - absl::StatusCode::kInvalidArgument), + tensorflow::Status(tensorflow::error::INVALID_ARGUMENT, "Could not find symbol in parameter map: alpha")); } @@ -859,8 +853,7 @@ TEST(QsimCircuitParserTest, PhasedISwap) { // Test case where proto arg missing. ASSERT_EQ(QsimCircuitFromProgram(program_proto, symbol_map, 2, &test_circuit, &fused_circuit), - tensorflow::Status(static_cast( - absl::StatusCode::kInvalidArgument), + tensorflow::Status(tensorflow::error::INVALID_ARGUMENT, "Could not find arg: phase_exponent in op.")); test_circuit.gates.clear(); @@ -872,8 +865,7 @@ TEST(QsimCircuitParserTest, PhasedISwap) { ASSERT_EQ( QsimCircuitFromProgram(program_proto, symbol_map, 2, &test_circuit, &fused_circuit), - tensorflow::Status(static_cast( - absl::StatusCode::kInvalidArgument), + tensorflow::Status(tensorflow::error::INVALID_ARGUMENT, "Could not find symbol in parameter map: alpha")); } @@ -1027,8 +1019,7 @@ TEST(QsimCircuitParserTest, PhasedXPow) { // Test case where proto arg missing. ASSERT_EQ(QsimCircuitFromProgram(program_proto, symbol_map, 1, &test_circuit, &fused_circuit), - tensorflow::Status(static_cast( - absl::StatusCode::kInvalidArgument), + tensorflow::Status(tensorflow::error::INVALID_ARGUMENT, "Could not find arg: phase_exponent in op.")); test_circuit.gates.clear(); @@ -1040,8 +1031,7 @@ TEST(QsimCircuitParserTest, PhasedXPow) { ASSERT_EQ( QsimCircuitFromProgram(program_proto, symbol_map, 1, &test_circuit, &fused_circuit), - tensorflow::Status(static_cast( - absl::StatusCode::kInvalidArgument), + tensorflow::Status(tensorflow::error::INVALID_ARGUMENT, "Could not find symbol in parameter map: alpha")); } @@ -1134,8 +1124,7 @@ TEST(QsimCircuitParserTest, InvalidControlValues) { ASSERT_EQ(QsimCircuitFromProgram(program_proto, empty_map, 3, &test_circuit, &fused_circuit, &metadata), - tensorflow::Status(static_cast( - absl::StatusCode::kInvalidArgument), + tensorflow::Status(tensorflow::error::INVALID_ARGUMENT, "Unparseable control value: junk")); } @@ -1168,8 +1157,7 @@ TEST(QsimCircuitParserTest, MismatchControlNum) { ASSERT_EQ(QsimCircuitFromProgram(program_proto, empty_map, 3, &test_circuit, &fused_circuit, &metadata), tensorflow::Status( - static_cast( - absl::StatusCode::kInvalidArgument), + tensorflow::error::INVALID_ARGUMENT, "Mistmatched number of control qubits and control values.")); } @@ -1571,8 +1559,7 @@ TEST(QsimCircuitParserTest, NoisyBadProto) { NoisyQsimCircuit test_circuit; ASSERT_EQ( NoisyQsimCircuitFromProgram(program_proto, {}, 1, false, &test_circuit), - tensorflow::Status(static_cast( - absl::StatusCode::kInvalidArgument), + tensorflow::Status(tensorflow::error::INVALID_ARGUMENT, "Could not parse channel id: ABCDEFG")); } diff --git a/tensorflow_quantum/core/src/program_resolution.cc b/tensorflow_quantum/core/src/program_resolution.cc index a06b17b97..82af94d35 100644 --- a/tensorflow_quantum/core/src/program_resolution.cc +++ b/tensorflow_quantum/core/src/program_resolution.cc @@ -64,18 +64,15 @@ Status RegisterQubits( } if (splits.size() != 2) { - return Status(static_cast( - absl::StatusCode::kInvalidArgument), + return Status(tensorflow::error::INVALID_ARGUMENT, absl::StrCat("Unable to parse qubit: ", qb)); } if (!absl::SimpleAtoi(splits[0], &r)) { - return Status(static_cast( - absl::StatusCode::kInvalidArgument), + return Status(tensorflow::error::INVALID_ARGUMENT, absl::StrCat("Unable to parse qubit: ", qb)); } if (!absl::SimpleAtoi(splits[1], &c)) { - return Status(static_cast( - absl::StatusCode::kInvalidArgument), + return Status(tensorflow::error::INVALID_ARGUMENT, absl::StrCat("Unable to parse qubit: ", qb)); } auto locs = std::pair, std::string>( @@ -170,8 +167,7 @@ Status ResolveQubitIds(Program* program, unsigned int* num_qubits, const auto result = id_to_index.find(pair.qubit_id()); if (result == id_to_index.end()) { return Status( - static_cast( - absl::StatusCode::kInvalidArgument), + tensorflow::error::INVALID_ARGUMENT, "Found a Pauli sum operating on qubits not found in circuit."); } pair.set_qubit_id(result->second); @@ -262,8 +258,7 @@ Status ResolveQubitIds(Program* program, unsigned int* num_qubits, visited_qubits.erase(qubit.id()); const auto result = id_to_index.find(qubit.id()); if (result == id_to_index.end()) { - return Status(static_cast( - absl::StatusCode::kInvalidArgument), + return Status(tensorflow::error::INVALID_ARGUMENT, "A paired circuit contains qubits not found in " "reference circuit."); } @@ -285,8 +280,7 @@ Status ResolveQubitIds(Program* program, unsigned int* num_qubits, visited_qubits.erase(id); const auto result = id_to_index.find(id); if (result == id_to_index.end()) { - return Status(static_cast( - absl::StatusCode::kInvalidArgument), + return Status(tensorflow::error::INVALID_ARGUMENT, "A paired circuit contains qubits not found in " "reference circuit."); } @@ -300,8 +294,7 @@ Status ResolveQubitIds(Program* program, unsigned int* num_qubits, } if (!visited_qubits.empty()) { return Status( - static_cast( - absl::StatusCode::kInvalidArgument), + tensorflow::error::INVALID_ARGUMENT, "A reference circuit contains qubits not found in paired circuit."); } } @@ -321,8 +314,7 @@ Status ResolveSymbols( if (iter == param_map.end()) { if (resolve_all) { return Status( - static_cast( - absl::StatusCode::kInvalidArgument), + tensorflow::error::INVALID_ARGUMENT, "Could not find symbol in parameter map: " + arg.symbol()); } continue; @@ -362,8 +354,7 @@ Status CheckMPSSupported(const Program& program) { const int total_num_qubits = qubits.size() + control_ids.size(); if (total_num_qubits > 2) { return Status( - static_cast( - absl::StatusCode::kInvalidArgument), + tensorflow::error::INVALID_ARGUMENT, absl::StrCat("1D operations only support 1 and 2 qubit gates. " "Found: ", total_num_qubits, " qubit gate.")); @@ -381,8 +372,7 @@ Status CheckMPSSupported(const Program& program) { // Are the two qubits not neighbors? if (std::abs((int)qids[0] - (int)qids[1]) > 1) { - return Status(static_cast( - absl::StatusCode::kInvalidArgument), + return Status(tensorflow::error::INVALID_ARGUMENT, "A program is not in 1D topology. It contains an" " operation with qubits not neighbors each other."); } From 5ac5dad290aeefbaf66a0f64afa33dac054af137 Mon Sep 17 00:00:00 2001 From: "Jae H. Yoo" <40815393+jaeyoo@users.noreply.github.com> Date: Mon, 20 Mar 2023 13:00:20 -0700 Subject: [PATCH 41/50] Upgrade TF version from 2.7 to 2.11 (#749) * Upgrade bazel version to 5.1.0 for building with TFv2.11.0 * Upgrade to TF v2.11 * Bump up the version of numpy to v1.24.2 * Format * Fix tf.Variable inside tf.while_loop issues inside optimizers * Format optimizers * Upgrade the latest gym for notebook tutorial. * Fix tutorial error * Fix tutorial errors * Upgrade seaborn version to 0.12.0 * Fix typo * Remove debug print * Update ci_install bazel version, removed duplicated code lines. --- .bazelversion | 2 +- WORKSPACE | 10 +- benchmarks/README.md | 4 +- configure.sh | 7 +- docs/install.md | 21 +- docs/tutorials/barren_plateaus.ipynb | 29 +- docs/tutorials/gradients.ipynb | 51 ++-- docs/tutorials/hello_many_worlds.ipynb | 261 +++++++++++++----- docs/tutorials/mnist.ipynb | 13 +- docs/tutorials/noise.ipynb | 234 ++++++++-------- docs/tutorials/qcnn.ipynb | 203 ++++++++++---- docs/tutorials/quantum_data.ipynb | 42 ++- .../quantum_reinforcement_learning.ipynb | 25 +- release/setup.py | 6 +- requirements.txt | 6 +- scripts/benchmark_all.sh | 4 +- scripts/build_pip_package_test.sh | 2 +- scripts/ci_install.sh | 4 +- scripts/ci_validate_tutorials.sh | 6 +- scripts/msan_test.sh | 6 +- scripts/test_all.sh | 4 +- scripts/test_benchmarks.sh | 6 +- scripts/test_tutorials.py | 6 +- tensorflow_quantum/core/ops/BUILD | 42 +-- tensorflow_quantum/core/ops/cirq_ops_test.py | 2 +- tensorflow_quantum/core/ops/math_ops/BUILD | 6 +- .../core/ops/math_ops/simulate_mps_test.py | 5 +- .../core/ops/math_ops/tfq_inner_product.cc | 4 +- .../ops/math_ops/tfq_inner_product_grad.cc | 4 +- .../math_ops/tfq_simulate_1d_expectation.cc | 6 +- .../tfq_simulate_1d_sampled_expectation.cc | 6 +- .../ops/math_ops/tfq_simulate_1d_samples.cc | 4 +- tensorflow_quantum/core/ops/noise/BUILD | 6 +- .../core/ops/noise/tfq_noisy_expectation.cc | 6 +- .../noise/tfq_noisy_sampled_expectation.cc | 6 +- .../core/ops/noise/tfq_noisy_samples.cc | 4 +- tensorflow_quantum/core/ops/parse_context.cc | 71 +++-- .../core/ops/tfq_adj_grad_op.cc | 4 +- .../core/ops/tfq_calculate_unitary_op.cc | 4 +- .../core/ops/tfq_circuit_append_op.cc | 2 +- .../core/ops/tfq_ps_decompose_op.cc | 2 +- .../core/ops/tfq_ps_symbol_replace_op.cc | 2 +- .../ops/tfq_ps_weights_from_symbols_op.cc | 2 +- .../core/ops/tfq_resolve_parameters_op.cc | 4 +- .../core/ops/tfq_simulate_expectation_op.cc | 6 +- .../tfq_simulate_sampled_expectation_op.cc | 6 +- .../core/ops/tfq_simulate_samples_op.cc | 4 +- .../core/ops/tfq_simulate_state_op.cc | 4 +- .../core/ops/tfq_utility_ops_test.py | 2 +- .../core/serialize/op_serializer.py | 2 +- .../core/serialize/op_serializer_test.py | 2 +- tensorflow_quantum/core/src/BUILD | 7 + .../core/src/circuit_parser_qsim.cc | 69 ++--- .../core/src/circuit_parser_qsim_test.cc | 113 ++++---- .../core/src/program_resolution.cc | 52 ++-- .../core/src/program_resolution_test.cc | 56 ++-- tensorflow_quantum/core/src/util_qsim.h | 14 +- tensorflow_quantum/datasets/spin_system.py | 4 +- .../datasets/spin_system_test.py | 3 +- .../sampled_expectation_test.py | 2 +- .../python/optimizers/rotosolve_minimizer.py | 144 +++++----- .../python/optimizers/spsa_minimizer.py | 181 ++++-------- 62 files changed, 1021 insertions(+), 794 deletions(-) diff --git a/.bazelversion b/.bazelversion index 0b2eb36f5..831446cbd 100644 --- a/.bazelversion +++ b/.bazelversion @@ -1 +1 @@ -3.7.2 +5.1.0 diff --git a/WORKSPACE b/WORKSPACE index b70cca65b..b47e25d2f 100644 --- a/WORKSPACE +++ b/WORKSPACE @@ -3,8 +3,8 @@ load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") -EIGEN_COMMIT = "12e8d57108c50d8a63605c6eb0144c838c128337" -EIGEN_SHA256 = "f689246e342c3955af48d26ce74ac34d21b579a00675c341721a735937919b02" +EIGEN_COMMIT = "3bb6a48d8c171cf20b5f8e48bfb4e424fbd4f79e" +EIGEN_SHA256 = "eca9847b3fe6249e0234a342b78f73feec07d29f534e914ba5f920f3e09383a3" http_archive( @@ -33,10 +33,10 @@ http_archive( http_archive( name = "org_tensorflow", - sha256 = "249b48ddee927801c7a4f8e5442cf1a3c860f6f46b85a2ff7a78b501507dd561", - strip_prefix = "tensorflow-2.7.0", + sha256 = "e52cda3bae45f0ae0fccd4055e9fa29892b414f70e2df94df9a3a10319c75fff", + strip_prefix = "tensorflow-2.11.0", urls = [ - "https://github.com/tensorflow/tensorflow/archive/refs/tags/v2.7.0.zip", + "https://github.com/tensorflow/tensorflow/archive/refs/tags/v2.11.0.zip", ], ) diff --git a/benchmarks/README.md b/benchmarks/README.md index b71bd1b04..4e71f8de2 100644 --- a/benchmarks/README.md +++ b/benchmarks/README.md @@ -24,7 +24,7 @@ Some notes on benchmark configuration: For example, to benchmark a dense depth-10 Clifford circuit over 5 qubits call: ``` -bazel run -c opt --cxxopt="-D_GLIBCXX_USE_CXX11_ABI=0" --cxxopt="-msse2" \ +bazel run -c opt --cxxopt="-D_GLIBCXX_USE_CXX11_ABI=1" --cxxopt="-msse2" \ --cxxopt="-msse3" --cxxopt="-msse4" \ benchmarks/scripts:benchmark_clifford_circuit -- \ --n_moments 5 --n_qubits 4 \ @@ -39,7 +39,7 @@ benchmarks/scripts/reports/CliffordBenchmarks.benchmark_clifford_circuit_4_5_1 To benchmark the parameter shift differentiation method on a random depth-10 4-qubit circuit with 10 parameters call, where the circuit will be differentiated over 50 trials, each time over a batch of 10 circuits. ``` -bazel run -c opt --cxxopt="-D_GLIBCXX_USE_CXX11_ABI=0" --cxxopt="-msse2" \ +bazel run -c opt --cxxopt="-D_GLIBCXX_USE_CXX11_ABI=1" --cxxopt="-msse2" \ --cxxopt="-msse3" --cxxopt="-msse4" \ benchmarks/scripts:benchmark_op_gradients -- \ --n_moments 10 --n_qubits 4 --n_symbols 10 \ diff --git a/configure.sh b/configure.sh index 6ba7a1bc4..5efd4212a 100755 --- a/configure.sh +++ b/configure.sh @@ -99,13 +99,12 @@ if [[ "$PIP_MANYLINUX2010" == "0" ]]; then write_to_bazelrc "build:cuda --crosstool_top=@local_config_cuda//crosstool:toolchain" fi - +write_to_bazelrc "build --experimental_repo_remote_exec" write_to_bazelrc "build --spawn_strategy=standalone" write_to_bazelrc "build --strategy=Genrule=standalone" -write_to_bazelrc "build --experimental_repo_remote_exec" write_to_bazelrc "build -c opt" -write_to_bazelrc "build --cxxopt=\"-D_GLIBCXX_USE_CXX11_ABI=0\"" -write_to_bazelrc "build --cxxopt=\"-std=c++14\"" +write_to_bazelrc "build --cxxopt=\"-D_GLIBCXX_USE_CXX11_ABI=1\"" +write_to_bazelrc "build --cxxopt=\"-std=c++17\"" if is_windows; then diff --git a/docs/install.md b/docs/install.md index 8c19034c1..5e64d0616 100644 --- a/docs/install.md +++ b/docs/install.md @@ -84,7 +84,7 @@ As noted in the TensorFlow guide, the Bazel build system will be required. -Our latest source builds use TensorFlow 2.7.0. To ensure compatibility we use `bazel` version 3.7.2. To remove any existing version of Bazel: +Our latest source builds use TensorFlow 2.11.0. To ensure compatibility we use `bazel` version 5.1.0. To remove any existing version of Bazel:
@@ -92,13 +92,13 @@ Our latest source builds use TensorFlow 2.7.0. To ensure compatibility we use `b
 
-Download and install `bazel` version 3.7.2: +Download and install `bazel` version 5.1.0:
-  wget https://github.com/bazelbuild/bazel/releases/download/3.7.2/bazel_3.7.2-linux-x86_64.deb
+  wget https://github.com/bazelbuild/bazel/releases/download/5.1.0/bazel_5.1.0-linux-x86_64.deb
 
-  sudo dpkg -i bazel_3.7.2-linux-x86_64.deb
+  sudo dpkg -i bazel_5.1.0-linux-x86_64.deb
 
@@ -122,7 +122,7 @@ Finally, confirm installation of the correct `bazel` version: ### 4. Build TensorFlow from source Here we adapt instructions from the TensorFlow [build from source](https://www.tensorflow.org/install/source) -guide, see the link for further details. TensorFlow Quantum is compatible with TensorFlow version 2.7.0. +guide, see the link for further details. TensorFlow Quantum is compatible with TensorFlow version 2.11.0. Download the TensorFlow source code: @@ -131,7 +131,7 @@ Download the
   git clone https://github.com/tensorflow/tensorflow.git
   cd tensorflow
-  git checkout v2.7.0
+  git checkout v2.11.0
 
Be sure the virtual environment you created in step 2 is activated. Then, install the TensorFlow dependencies: @@ -141,7 +141,8 @@ Be sure the virtual environment you created in step 2 is activated. Then, instal pip install -U pip six numpy wheel setuptools mock 'future>=0.17.1' pip install -U keras_applications --no-deps pip install -U keras_preprocessing --no-deps - pip install numpy==1.19.5 + pip install numpy==1.24.2 + pip install packaging requests @@ -153,11 +154,11 @@ Configure the TensorFlow build. When asked for the Python interpreter and librar -Build the TensorFlow package: +Build the TensorFlow package (Since TF v2.8, `_GLIBCXX_USE_CXX11_ABI` is set to 1, and the c++ codes are all compiled with `-std=c++17`):
-  bazel build -c opt --cxxopt="-O3" --cxxopt="-march=native" --cxxopt="-D_GLIBCXX_USE_CXX11_ABI=0" //tensorflow/tools/pip_package:build_pip_package
+  bazel build -c opt --cxxopt="-O3" --cxxopt="-march=native" --cxxopt="-std=c++17" --cxxopt="-D_GLIBCXX_USE_CXX11_ABI=1" //tensorflow/tools/pip_package:build_pip_package
 
@@ -193,7 +194,7 @@ Build the TensorFlow Quantum pip package and install:
   ./configure.sh
-  bazel build -c opt --cxxopt="-O3" --cxxopt="-march=native" --cxxopt="-D_GLIBCXX_USE_CXX11_ABI=0" release:build_pip_package
+  bazel build -c opt --cxxopt="-O3" --cxxopt="-march=native" --cxxopt="-std=c++17" --cxxopt="-D_GLIBCXX_USE_CXX11_ABI=1" release:build_pip_package
   bazel-bin/release/build_pip_package /tmp/tfquantum/
   python3 -m pip install /tmp/tfquantum/name_of_generated_wheel.whl
 
diff --git a/docs/tutorials/barren_plateaus.ipynb b/docs/tutorials/barren_plateaus.ipynb index 2447018c9..3c9176eaa 100644 --- a/docs/tutorials/barren_plateaus.ipynb +++ b/docs/tutorials/barren_plateaus.ipynb @@ -12,7 +12,7 @@ }, { "cell_type": "code", - "execution_count": 0, + "execution_count": null, "metadata": { "cellView": "form", "colab": {}, @@ -89,7 +89,7 @@ }, { "cell_type": "code", - "execution_count": 0, + "execution_count": null, "metadata": { "colab": {}, "colab_type": "code", @@ -112,7 +112,7 @@ }, { "cell_type": "code", - "execution_count": 0, + "execution_count": null, "metadata": { "colab": {}, "colab_type": "code", @@ -125,7 +125,7 @@ }, { "cell_type": "code", - "execution_count": 0, + "execution_count": null, "metadata": { "colab": {}, "colab_type": "code", @@ -150,7 +150,7 @@ }, { "cell_type": "code", - "execution_count": 0, + "execution_count": null, "metadata": { "colab": {}, "colab_type": "code", @@ -202,7 +202,7 @@ }, { "cell_type": "code", - "execution_count": 0, + "execution_count": null, "metadata": { "colab": {}, "colab_type": "code", @@ -278,7 +278,7 @@ }, { "cell_type": "code", - "execution_count": 0, + "execution_count": null, "metadata": { "colab": {}, "colab_type": "code", @@ -327,7 +327,7 @@ }, { "cell_type": "code", - "execution_count": 0, + "execution_count": null, "metadata": { "colab": {}, "colab_type": "code", @@ -399,7 +399,7 @@ }, { "cell_type": "code", - "execution_count": 0, + "execution_count": null, "metadata": { "colab": {}, "colab_type": "code", @@ -455,7 +455,7 @@ }, { "cell_type": "code", - "execution_count": 0, + "execution_count": null, "metadata": { "colab": {}, "colab_type": "code", @@ -511,6 +511,15 @@ "display_name": "Python 3", "language": "python", "name": "python3" + }, + "language_info": { + "name": "python", + "version": "3.10.9 (main, Dec 7 2022, 13:47:07) [GCC 12.2.0]" + }, + "vscode": { + "interpreter": { + "hash": "916dbcbb3f70747c44a77c7bcd40155683ae19c65e1c03b4aa3499c5328201f1" + } } }, "nbformat": 4, diff --git a/docs/tutorials/gradients.ipynb b/docs/tutorials/gradients.ipynb index 62a7ce103..072718bcf 100644 --- a/docs/tutorials/gradients.ipynb +++ b/docs/tutorials/gradients.ipynb @@ -12,7 +12,7 @@ }, { "cell_type": "code", - "execution_count": 0, + "execution_count": null, "metadata": { "cellView": "form", "colab": {}, @@ -91,7 +91,7 @@ }, { "cell_type": "code", - "execution_count": 0, + "execution_count": null, "metadata": { "colab": {}, "colab_type": "code", @@ -114,7 +114,7 @@ }, { "cell_type": "code", - "execution_count": 0, + "execution_count": null, "metadata": { "colab": {}, "colab_type": "code", @@ -127,7 +127,7 @@ }, { "cell_type": "code", - "execution_count": 0, + "execution_count": null, "metadata": { "colab": {}, "colab_type": "code", @@ -152,7 +152,7 @@ }, { "cell_type": "code", - "execution_count": 0, + "execution_count": null, "metadata": { "colab": {}, "colab_type": "code", @@ -187,7 +187,7 @@ }, { "cell_type": "code", - "execution_count": 0, + "execution_count": null, "metadata": { "colab": {}, "colab_type": "code", @@ -212,7 +212,7 @@ }, { "cell_type": "code", - "execution_count": 0, + "execution_count": null, "metadata": { "colab": {}, "colab_type": "code", @@ -236,7 +236,7 @@ }, { "cell_type": "code", - "execution_count": 0, + "execution_count": null, "metadata": { "colab": {}, "colab_type": "code", @@ -269,7 +269,7 @@ }, { "cell_type": "code", - "execution_count": 0, + "execution_count": null, "metadata": { "colab": {}, "colab_type": "code", @@ -302,7 +302,7 @@ }, { "cell_type": "code", - "execution_count": 0, + "execution_count": null, "metadata": { "colab": {}, "colab_type": "code", @@ -331,7 +331,7 @@ }, { "cell_type": "code", - "execution_count": 0, + "execution_count": null, "metadata": { "colab": {}, "colab_type": "code", @@ -361,7 +361,7 @@ }, { "cell_type": "code", - "execution_count": 0, + "execution_count": null, "metadata": { "colab": {}, "colab_type": "code", @@ -390,7 +390,7 @@ }, { "cell_type": "code", - "execution_count": 0, + "execution_count": null, "metadata": { "colab": {}, "colab_type": "code", @@ -439,7 +439,7 @@ }, { "cell_type": "code", - "execution_count": 0, + "execution_count": null, "metadata": { "colab": {}, "colab_type": "code", @@ -494,7 +494,7 @@ }, { "cell_type": "code", - "execution_count": 0, + "execution_count": null, "metadata": { "colab": {}, "colab_type": "code", @@ -518,7 +518,7 @@ }, { "cell_type": "code", - "execution_count": 0, + "execution_count": null, "metadata": { "colab": {}, "colab_type": "code", @@ -548,7 +548,7 @@ }, { "cell_type": "code", - "execution_count": 0, + "execution_count": null, "metadata": { "colab": {}, "colab_type": "code", @@ -577,7 +577,7 @@ }, { "cell_type": "code", - "execution_count": 0, + "execution_count": null, "metadata": { "colab": {}, "colab_type": "code", @@ -636,7 +636,7 @@ }, { "cell_type": "code", - "execution_count": 0, + "execution_count": null, "metadata": { "colab": {}, "colab_type": "code", @@ -694,7 +694,7 @@ }, { "cell_type": "code", - "execution_count": 0, + "execution_count": null, "metadata": { "colab": {}, "colab_type": "code", @@ -750,7 +750,7 @@ }, { "cell_type": "code", - "execution_count": 0, + "execution_count": null, "metadata": { "colab": {}, "colab_type": "code", @@ -812,6 +812,15 @@ "display_name": "Python 3", "language": "python", "name": "python3" + }, + "language_info": { + "name": "python", + "version": "3.10.9 (main, Dec 7 2022, 13:47:07) [GCC 12.2.0]" + }, + "vscode": { + "interpreter": { + "hash": "916dbcbb3f70747c44a77c7bcd40155683ae19c65e1c03b4aa3499c5328201f1" + } } }, "nbformat": 4, diff --git a/docs/tutorials/hello_many_worlds.ipynb b/docs/tutorials/hello_many_worlds.ipynb index f3dd7fe19..229136219 100644 --- a/docs/tutorials/hello_many_worlds.ipynb +++ b/docs/tutorials/hello_many_worlds.ipynb @@ -12,12 +12,15 @@ }, { "cell_type": "code", - "execution_count": 0, + "execution_count": null, "metadata": { "cellView": "form", "colab": {}, "colab_type": "code", - "id": "iiQkM5ZgQ8r2" + "id": "iiQkM5ZgQ8r2", + "vscode": { + "languageId": "python" + } }, "outputs": [], "source": [ @@ -89,11 +92,14 @@ }, { "cell_type": "code", - "execution_count": 0, + "execution_count": null, "metadata": { "colab": {}, "colab_type": "code", - "id": "TorxE5tnkvb2" + "id": "TorxE5tnkvb2", + "vscode": { + "languageId": "python" + } }, "outputs": [], "source": [ @@ -112,11 +118,14 @@ }, { "cell_type": "code", - "execution_count": 0, + "execution_count": null, "metadata": { "colab": {}, "colab_type": "code", - "id": "saFHsRDpkvkH" + "id": "saFHsRDpkvkH", + "vscode": { + "languageId": "python" + } }, "outputs": [], "source": [ @@ -125,11 +134,14 @@ }, { "cell_type": "code", - "execution_count": 0, + "execution_count": null, "metadata": { "colab": {}, "colab_type": "code", - "id": "4Ql5PW-ACO0J" + "id": "4Ql5PW-ACO0J", + "vscode": { + "languageId": "python" + } }, "outputs": [], "source": [ @@ -150,11 +162,14 @@ }, { "cell_type": "code", - "execution_count": 0, + "execution_count": null, "metadata": { "colab": {}, "colab_type": "code", - "id": "enZ300Bflq80" + "id": "enZ300Bflq80", + "vscode": { + "languageId": "python" + } }, "outputs": [], "source": [ @@ -197,11 +212,14 @@ }, { "cell_type": "code", - "execution_count": 0, + "execution_count": null, "metadata": { "colab": {}, "colab_type": "code", - "id": "2yQdmhQLCrzQ" + "id": "2yQdmhQLCrzQ", + "vscode": { + "languageId": "python" + } }, "outputs": [], "source": [ @@ -220,11 +238,14 @@ }, { "cell_type": "code", - "execution_count": 0, + "execution_count": null, "metadata": { "colab": {}, "colab_type": "code", - "id": "Ps-pd2mndXs7" + "id": "Ps-pd2mndXs7", + "vscode": { + "languageId": "python" + } }, "outputs": [], "source": [ @@ -251,11 +272,14 @@ }, { "cell_type": "code", - "execution_count": 0, + "execution_count": null, "metadata": { "colab": {}, "colab_type": "code", - "id": "VMq7EayNRyQb" + "id": "VMq7EayNRyQb", + "vscode": { + "languageId": "python" + } }, "outputs": [], "source": [ @@ -277,12 +301,15 @@ }, { "cell_type": "code", - "execution_count": 0, + "execution_count": null, "metadata": { "colab": {}, "colab_type": "code", "id": "hrSnOCi3ehr_", - "scrolled": true + "scrolled": true, + "vscode": { + "languageId": "python" + } }, "outputs": [], "source": [ @@ -295,11 +322,14 @@ }, { "cell_type": "code", - "execution_count": 0, + "execution_count": null, "metadata": { "colab": {}, "colab_type": "code", - "id": "OZ0lWFXv6pII" + "id": "OZ0lWFXv6pII", + "vscode": { + "languageId": "python" + } }, "outputs": [], "source": [ @@ -322,12 +352,15 @@ }, { "cell_type": "code", - "execution_count": 0, + "execution_count": null, "metadata": { "colab": {}, "colab_type": "code", "id": "1gLQjA02mIyy", - "scrolled": true + "scrolled": true, + "vscode": { + "languageId": "python" + } }, "outputs": [], "source": [ @@ -350,11 +383,14 @@ }, { "cell_type": "code", - "execution_count": 0, + "execution_count": null, "metadata": { "colab": {}, "colab_type": "code", - "id": "aX_vEmCKmpQS" + "id": "aX_vEmCKmpQS", + "vscode": { + "languageId": "python" + } }, "outputs": [], "source": [ @@ -381,15 +417,18 @@ }, { "cell_type": "code", - "execution_count": 0, + "execution_count": null, "metadata": { "colab": {}, "colab_type": "code", - "id": "1fsVZhF5lIXp" + "id": "1fsVZhF5lIXp", + "vscode": { + "languageId": "python" + } }, "outputs": [], "source": [ - "batch_vals = np.array(np.random.uniform(0, 2 * np.pi, (5, 2)), dtype=np.float32)" + "batch_vals = np.array(np.random.uniform(0, 2 * np.pi, (5, 2)), dtype=float)" ] }, { @@ -404,11 +443,14 @@ }, { "cell_type": "code", - "execution_count": 0, + "execution_count": null, "metadata": { "colab": {}, "colab_type": "code", - "id": "RsfF53UCJtr9" + "id": "RsfF53UCJtr9", + "vscode": { + "languageId": "python" + } }, "outputs": [], "source": [ @@ -439,11 +481,14 @@ }, { "cell_type": "code", - "execution_count": 0, + "execution_count": null, "metadata": { "colab": {}, "colab_type": "code", - "id": "kGZVdcZ6y9lC" + "id": "kGZVdcZ6y9lC", + "vscode": { + "languageId": "python" + } }, "outputs": [], "source": [ @@ -497,11 +542,14 @@ }, { "cell_type": "code", - "execution_count": 0, + "execution_count": null, "metadata": { "colab": {}, "colab_type": "code", - "id": "N-j7SCl-51-q" + "id": "N-j7SCl-51-q", + "vscode": { + "languageId": "python" + } }, "outputs": [], "source": [ @@ -532,11 +580,14 @@ }, { "cell_type": "code", - "execution_count": 0, + "execution_count": null, "metadata": { "colab": {}, "colab_type": "code", - "id": "1v4CK2jD6pIj" + "id": "1v4CK2jD6pIj", + "vscode": { + "languageId": "python" + } }, "outputs": [], "source": [ @@ -561,11 +612,14 @@ }, { "cell_type": "code", - "execution_count": 0, + "execution_count": null, "metadata": { "colab": {}, "colab_type": "code", - "id": "kZbYRTe16pIm" + "id": "kZbYRTe16pIm", + "vscode": { + "languageId": "python" + } }, "outputs": [], "source": [ @@ -598,11 +652,14 @@ }, { "cell_type": "code", - "execution_count": 0, + "execution_count": null, "metadata": { "colab": {}, "colab_type": "code", - "id": "UfHF8NNE6pIr" + "id": "UfHF8NNE6pIr", + "vscode": { + "languageId": "python" + } }, "outputs": [], "source": [ @@ -630,11 +687,14 @@ }, { "cell_type": "code", - "execution_count": 0, + "execution_count": null, "metadata": { "colab": {}, "colab_type": "code", - "id": "Zvt2YGmZ6pIu" + "id": "Zvt2YGmZ6pIu", + "vscode": { + "languageId": "python" + } }, "outputs": [], "source": [ @@ -659,11 +719,14 @@ }, { "cell_type": "code", - "execution_count": 0, + "execution_count": null, "metadata": { "colab": {}, "colab_type": "code", - "id": "Xs6EMhah6pIz" + "id": "Xs6EMhah6pIz", + "vscode": { + "languageId": "python" + } }, "outputs": [], "source": [ @@ -687,11 +750,14 @@ }, { "cell_type": "code", - "execution_count": 0, + "execution_count": null, "metadata": { "colab": {}, "colab_type": "code", - "id": "ERXNPe4F6pI4" + "id": "ERXNPe4F6pI4", + "vscode": { + "languageId": "python" + } }, "outputs": [], "source": [ @@ -730,11 +796,14 @@ }, { "cell_type": "code", - "execution_count": 0, + "execution_count": null, "metadata": { "colab": {}, "colab_type": "code", - "id": "ciMIJAuH6pJA" + "id": "ciMIJAuH6pJA", + "vscode": { + "languageId": "python" + } }, "outputs": [], "source": [ @@ -770,11 +839,14 @@ }, { "cell_type": "code", - "execution_count": 0, + "execution_count": null, "metadata": { "colab": {}, "colab_type": "code", - "id": "_VYfzHffWo7n" + "id": "_VYfzHffWo7n", + "vscode": { + "languageId": "python" + } }, "outputs": [], "source": [ @@ -801,11 +873,14 @@ }, { "cell_type": "code", - "execution_count": 0, + "execution_count": null, "metadata": { "colab": {}, "colab_type": "code", - "id": "6nk2Yr3e6pJJ" + "id": "6nk2Yr3e6pJJ", + "vscode": { + "languageId": "python" + } }, "outputs": [], "source": [ @@ -834,11 +909,14 @@ }, { "cell_type": "code", - "execution_count": 0, + "execution_count": null, "metadata": { "colab": {}, "colab_type": "code", - "id": "Lwphqvs96pJO" + "id": "Lwphqvs96pJO", + "vscode": { + "languageId": "python" + } }, "outputs": [], "source": [ @@ -857,11 +935,14 @@ }, { "cell_type": "code", - "execution_count": 0, + "execution_count": null, "metadata": { "colab": {}, "colab_type": "code", - "id": "dtPYqbNi8zeZ" + "id": "dtPYqbNi8zeZ", + "vscode": { + "languageId": "python" + } }, "outputs": [], "source": [ @@ -876,11 +957,14 @@ }, { "cell_type": "code", - "execution_count": 0, + "execution_count": null, "metadata": { "colab": {}, "colab_type": "code", - "id": "azE-qV0OaC1o" + "id": "azE-qV0OaC1o", + "vscode": { + "languageId": "python" + } }, "outputs": [], "source": [ @@ -914,11 +998,14 @@ }, { "cell_type": "code", - "execution_count": 0, + "execution_count": null, "metadata": { "colab": {}, "colab_type": "code", - "id": "RoIlb7r7j5SY" + "id": "RoIlb7r7j5SY", + "vscode": { + "languageId": "python" + } }, "outputs": [], "source": [ @@ -957,11 +1044,14 @@ }, { "cell_type": "code", - "execution_count": 0, + "execution_count": null, "metadata": { "colab": {}, "colab_type": "code", - "id": "aYskLTacs8Ku" + "id": "aYskLTacs8Ku", + "vscode": { + "languageId": "python" + } }, "outputs": [], "source": [ @@ -998,11 +1088,14 @@ }, { "cell_type": "code", - "execution_count": 0, + "execution_count": null, "metadata": { "colab": {}, "colab_type": "code", - "id": "hta0G3Nc6pJY" + "id": "hta0G3Nc6pJY", + "vscode": { + "languageId": "python" + } }, "outputs": [], "source": [ @@ -1031,11 +1124,14 @@ }, { "cell_type": "code", - "execution_count": 0, + "execution_count": null, "metadata": { "colab": {}, "colab_type": "code", - "id": "n_aTG4g3-y0F" + "id": "n_aTG4g3-y0F", + "vscode": { + "languageId": "python" + } }, "outputs": [], "source": [ @@ -1058,11 +1154,14 @@ }, { "cell_type": "code", - "execution_count": 0, + "execution_count": null, "metadata": { "colab": {}, "colab_type": "code", - "id": "IMHjiKit6pJg" + "id": "IMHjiKit6pJg", + "vscode": { + "languageId": "python" + } }, "outputs": [], "source": [ @@ -1096,11 +1195,14 @@ }, { "cell_type": "code", - "execution_count": 0, + "execution_count": null, "metadata": { "colab": {}, "colab_type": "code", - "id": "4gw_L3JG0_G0" + "id": "4gw_L3JG0_G0", + "vscode": { + "languageId": "python" + } }, "outputs": [], "source": [ @@ -1128,11 +1230,14 @@ }, { "cell_type": "code", - "execution_count": 0, + "execution_count": null, "metadata": { "colab": {}, "colab_type": "code", - "id": "nFuGA73MAA4p" + "id": "nFuGA73MAA4p", + "vscode": { + "languageId": "python" + } }, "outputs": [], "source": [ @@ -1150,11 +1255,14 @@ }, { "cell_type": "code", - "execution_count": 0, + "execution_count": null, "metadata": { "colab": {}, "colab_type": "code", - "id": "Cf_G-GdturLL" + "id": "Cf_G-GdturLL", + "vscode": { + "languageId": "python" + } }, "outputs": [], "source": [ @@ -1187,11 +1295,14 @@ }, { "cell_type": "code", - "execution_count": 0, + "execution_count": null, "metadata": { "colab": {}, "colab_type": "code", - "id": "uXmH0TQ76pJt" + "id": "uXmH0TQ76pJt", + "vscode": { + "languageId": "python" + } }, "outputs": [], "source": [ diff --git a/docs/tutorials/mnist.ipynb b/docs/tutorials/mnist.ipynb index b80f2500f..91405ed26 100644 --- a/docs/tutorials/mnist.ipynb +++ b/docs/tutorials/mnist.ipynb @@ -112,7 +112,7 @@ }, { "cell_type": "code", - "execution_count": 0, + "execution_count": null, "metadata": { "colab": {}, "colab_type": "code", @@ -125,7 +125,7 @@ }, { "cell_type": "code", - "execution_count": 0, + "execution_count": null, "metadata": { "colab": {}, "colab_type": "code", @@ -1117,6 +1117,15 @@ "display_name": "Python 3", "language": "python", "name": "python3" + }, + "language_info": { + "name": "python", + "version": "3.10.9 (main, Dec 7 2022, 13:47:07) [GCC 12.2.0]" + }, + "vscode": { + "interpreter": { + "hash": "916dbcbb3f70747c44a77c7bcd40155683ae19c65e1c03b4aa3499c5328201f1" + } } }, "nbformat": 4, diff --git a/docs/tutorials/noise.ipynb b/docs/tutorials/noise.ipynb index 3d43d17e0..0a0ebc290 100644 --- a/docs/tutorials/noise.ipynb +++ b/docs/tutorials/noise.ipynb @@ -1,29 +1,4 @@ { - "nbformat": 4, - "nbformat_minor": 0, - "metadata": { - "colab": { - "name": "noise.ipynb", - "provenance": [] - }, - "kernelspec": { - "display_name": "Python 3", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.8.8" - } - }, "cells": [ { "cell_type": "markdown", @@ -36,10 +11,12 @@ }, { "cell_type": "code", + "execution_count": null, "metadata": { "cellView": "form", "id": "iiQkM5ZgQ8r2" }, + "outputs": [], "source": [ "#@title Licensed under the Apache License, Version 2.0 (the \"License\");\n", "# you may not use this file except in compliance with the License.\n", @@ -52,9 +29,7 @@ "# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n", "# See the License for the specific language governing permissions and\n", "# limitations under the License." - ], - "execution_count": null, - "outputs": [] + ] }, { "cell_type": "markdown", @@ -102,29 +77,29 @@ }, { "cell_type": "code", + "execution_count": null, "metadata": { "id": "J2CRbYRqrLdt" }, + "outputs": [], "source": [ "!pip install tensorflow==2.7.0 tensorflow-quantum==0.7.2" - ], - "execution_count": null, - "outputs": [] + ] }, { "cell_type": "code", + "execution_count": null, "metadata": { "id": "QStNslxBwgte" }, + "outputs": [], "source": [ "!pip install -q git+https://github.com/tensorflow/docs" - ], - "execution_count": null, - "outputs": [] + ] }, { "cell_type": "code", - "execution_count": 0, + "execution_count": null, "metadata": { "colab": {}, "colab_type": "code", @@ -139,9 +114,11 @@ }, { "cell_type": "code", + "execution_count": null, "metadata": { "id": "iRU07S4o8B52" }, + "outputs": [], "source": [ "import random\n", "import cirq\n", @@ -153,9 +130,7 @@ "import matplotlib.pyplot as plt\n", "import tensorflow_docs as tfdocs\n", "import tensorflow_docs.plots" - ], - "execution_count": null, - "outputs": [] + ] }, { "cell_type": "markdown", @@ -186,9 +161,11 @@ }, { "cell_type": "code", + "execution_count": null, "metadata": { "id": "Eu_vpHbfrQKQ" }, + "outputs": [], "source": [ "def x_circuit(qubits):\n", " \"\"\"Produces an X wall circuit on `qubits`.\"\"\"\n", @@ -202,20 +179,18 @@ "my_circuit = x_circuit(my_qubits)\n", "my_noisy_circuit = make_noisy(my_circuit, 0.5)\n", "my_circuit" - ], - "execution_count": null, - "outputs": [] + ] }, { "cell_type": "code", + "execution_count": null, "metadata": { "id": "1B7vmyPm_TQ7" }, + "outputs": [], "source": [ "my_noisy_circuit" - ], - "execution_count": null, - "outputs": [] + ] }, { "cell_type": "markdown", @@ -228,15 +203,15 @@ }, { "cell_type": "code", + "execution_count": null, "metadata": { "id": "0QN9W69U8v_V" }, + "outputs": [], "source": [ "rho = cirq.final_density_matrix(my_circuit)\n", "np.round(rho, 3)" - ], - "execution_count": null, - "outputs": [] + ] }, { "cell_type": "markdown", @@ -249,15 +224,15 @@ }, { "cell_type": "code", + "execution_count": null, "metadata": { "id": "zSD9H8SC9IJ1" }, + "outputs": [], "source": [ "rho = cirq.final_density_matrix(my_noisy_circuit)\n", "np.round(rho, 3)" - ], - "execution_count": null, - "outputs": [] + ] }, { "cell_type": "markdown", @@ -270,9 +245,11 @@ }, { "cell_type": "code", + "execution_count": null, "metadata": { "id": "Z4uj-Zs0AE3n" }, + "outputs": [], "source": [ "\"\"\"Sample from my_noisy_circuit.\"\"\"\n", "def plot_samples(circuit):\n", @@ -285,9 +262,7 @@ " plt.bar([i for i in range(2** len(my_qubits))], freqs, tick_label=['00','01','10','11'])\n", "\n", "plot_samples(my_noisy_circuit)" - ], - "execution_count": null, - "outputs": [] + ] }, { "cell_type": "markdown", @@ -300,15 +275,15 @@ }, { "cell_type": "code", + "execution_count": null, "metadata": { "id": "NRCOhTVpEJzz" }, + "outputs": [], "source": [ "\"\"\"Sample from my_circuit.\"\"\"\n", "plot_samples(my_circuit)" - ], - "execution_count": null, - "outputs": [] + ] }, { "cell_type": "markdown", @@ -321,15 +296,15 @@ }, { "cell_type": "code", + "execution_count": null, "metadata": { "id": "D2Fg-FUdUJQx" }, + "outputs": [], "source": [ "my_really_noisy_circuit = make_noisy(my_circuit, 0.75)\n", "plot_samples(my_really_noisy_circuit)" - ], - "execution_count": null, - "outputs": [] + ] }, { "cell_type": "markdown", @@ -355,21 +330,23 @@ }, { "cell_type": "code", + "execution_count": null, "metadata": { "id": "byVI5nbNQ4_b" }, + "outputs": [], "source": [ "\"\"\"Draw bitstring samples from `my_noisy_circuit`\"\"\"\n", "bitstrings = tfq.layers.Sample(backend='noisy')(my_noisy_circuit, repetitions=1000)" - ], - "execution_count": null, - "outputs": [] + ] }, { "cell_type": "code", + "execution_count": null, "metadata": { "id": "ncl0ruCZrd2s" }, + "outputs": [], "source": [ "numeric_values = np.einsum('ijk,k->ij', bitstrings.to_tensor().numpy(), [1, 2])[0]\n", "freqs, _ = np.histogram(numeric_values, bins=[i+0.01 for i in range(-1,2** len(my_qubits))])\n", @@ -378,9 +355,7 @@ "plt.xlabel('Bitstring')\n", "plt.ylabel('Frequency')\n", "plt.bar([i for i in range(2** len(my_qubits))], freqs, tick_label=['00','01','10','11'])" - ], - "execution_count": null, - "outputs": [] + ] }, { "cell_type": "markdown", @@ -394,15 +369,15 @@ }, { "cell_type": "code", + "execution_count": null, "metadata": { "id": "ep45G-09rfrA" }, + "outputs": [], "source": [ "some_observables = [cirq.X(my_qubits[0]), cirq.Z(my_qubits[0]), 3.0 * cirq.Y(my_qubits[1]) + 1]\n", "some_observables" - ], - "execution_count": null, - "outputs": [] + ] }, { "cell_type": "markdown", @@ -415,17 +390,17 @@ }, { "cell_type": "code", + "execution_count": null, "metadata": { "id": "jL6wJ3LCvNcn" }, + "outputs": [], "source": [ "noiseless_sampled_expectation = tfq.layers.SampledExpectation(backend='noiseless')(\n", " my_circuit, operators=some_observables, repetitions=10000\n", ")\n", "noiseless_sampled_expectation.numpy()" - ], - "execution_count": null, - "outputs": [] + ] }, { "cell_type": "markdown", @@ -438,17 +413,17 @@ }, { "cell_type": "code", + "execution_count": null, "metadata": { "id": "8U4Gm-LGvYqa" }, + "outputs": [], "source": [ "noisy_sampled_expectation = tfq.layers.SampledExpectation(backend='noisy')(\n", " [my_noisy_circuit, my_really_noisy_circuit], operators=some_observables, repetitions=10000\n", ")\n", "noisy_sampled_expectation.numpy()" - ], - "execution_count": null, - "outputs": [] + ] }, { "cell_type": "markdown", @@ -465,31 +440,31 @@ }, { "cell_type": "code", + "execution_count": null, "metadata": { "id": "pGXKlyCywAfj" }, + "outputs": [], "source": [ "noiseless_analytic_expectation = tfq.layers.Expectation(backend='noiseless')(\n", " my_circuit, operators=some_observables\n", ")\n", "noiseless_analytic_expectation.numpy()" - ], - "execution_count": null, - "outputs": [] + ] }, { "cell_type": "code", + "execution_count": null, "metadata": { "id": "6FUkJ7aOyTlI" }, + "outputs": [], "source": [ "noisy_analytic_expectation = tfq.layers.Expectation(backend='noisy')(\n", " [my_noisy_circuit, my_really_noisy_circuit], operators=some_observables, repetitions=10000\n", ")\n", "noisy_analytic_expectation.numpy()" - ], - "execution_count": null, - "outputs": [] + ] }, { "cell_type": "markdown", @@ -510,16 +485,16 @@ }, { "cell_type": "code", + "execution_count": null, "metadata": { "id": "_ZqVLEji2WUx" }, + "outputs": [], "source": [ "qubits = cirq.GridQubit.rect(1, 8)\n", "circuits, labels, pauli_sums, _ = tfq.datasets.xxz_chain(qubits, 'closed')\n", "circuits[0]" - ], - "execution_count": null, - "outputs": [] + ] }, { "cell_type": "markdown", @@ -532,9 +507,11 @@ }, { "cell_type": "code", + "execution_count": null, "metadata": { "id": "zkQofAqqGibQ" }, + "outputs": [], "source": [ "def get_data(qubits, depolarize_p=0.):\n", " \"\"\"Return quantum data circuits and labels in `tf.Tensor` form.\"\"\"\n", @@ -547,9 +524,7 @@ " labels_tensor = tf.convert_to_tensor([x[1] for x in tmp])\n", "\n", " return circuits_tensor, labels_tensor" - ], - "execution_count": null, - "outputs": [] + ] }, { "cell_type": "markdown", @@ -563,9 +538,11 @@ }, { "cell_type": "code", + "execution_count": null, "metadata": { "id": "TwryFaFIG2Ya" }, + "outputs": [], "source": [ "def modelling_circuit(qubits, depth, depolarize_p=0.):\n", " \"\"\"A simple classifier circuit.\"\"\"\n", @@ -590,9 +567,7 @@ " return ret, [op(q) for q in qubits for op in [cirq.X, cirq.Y, cirq.Z]]\n", "\n", "modelling_circuit(qubits, 3)[0]" - ], - "execution_count": null, - "outputs": [] + ] }, { "cell_type": "markdown", @@ -606,9 +581,11 @@ }, { "cell_type": "code", + "execution_count": null, "metadata": { "id": "r09CT5N9DWa_" }, + "outputs": [], "source": [ "def build_keras_model(qubits, depolarize_p=0.):\n", " \"\"\"Prepare a noisy hybrid quantum classical Keras model.\"\"\"\n", @@ -624,9 +601,7 @@ " post_process = tf.keras.layers.Dense(1)(intermediate)\n", "\n", " return tf.keras.Model(inputs=[spin_input], outputs=[post_process])" - ], - "execution_count": null, - "outputs": [] + ] }, { "cell_type": "markdown", @@ -643,9 +618,11 @@ }, { "cell_type": "code", + "execution_count": null, "metadata": { "id": "QAgpq9c-EakW" }, + "outputs": [], "source": [ "training_histories = dict()\n", "depolarize_p = 0.\n", @@ -659,15 +636,15 @@ "\n", "# Show the keras plot of the model\n", "tf.keras.utils.plot_model(phase_classifier, show_shapes=True, dpi=70)" - ], - "execution_count": null, - "outputs": [] + ] }, { "cell_type": "code", + "execution_count": null, "metadata": { "id": "9tKimWRMlVfL" }, + "outputs": [], "source": [ "noiseless_data, noiseless_labels = get_data(qubits, depolarize_p)\n", "training_histories['noiseless'] = phase_classifier.fit(x=noiseless_data,\n", @@ -676,9 +653,7 @@ " epochs=n_epochs,\n", " validation_split=0.15,\n", " verbose=1)" - ], - "execution_count": null, - "outputs": [] + ] }, { "cell_type": "markdown", @@ -691,27 +666,27 @@ }, { "cell_type": "code", + "execution_count": null, "metadata": { "id": "TG87YNUWKKLY" }, + "outputs": [], "source": [ "loss_plotter = tfdocs.plots.HistoryPlotter(metric = 'loss', smoothing_std=10)\n", "loss_plotter.plot(training_histories)" - ], - "execution_count": null, - "outputs": [] + ] }, { "cell_type": "code", + "execution_count": null, "metadata": { "id": "O2ZwM18YUxxm" }, + "outputs": [], "source": [ "acc_plotter = tfdocs.plots.HistoryPlotter(metric = 'accuracy', smoothing_std=10)\n", "acc_plotter.plot(training_histories)" - ], - "execution_count": null, - "outputs": [] + ] }, { "cell_type": "markdown", @@ -725,9 +700,11 @@ }, { "cell_type": "code", + "execution_count": null, "metadata": { "id": "0jy54uWpgwhi" }, + "outputs": [], "source": [ "depolarize_p = 0.001\n", "n_epochs = 50\n", @@ -740,9 +717,7 @@ "\n", "# Show the keras plot of the model\n", "tf.keras.utils.plot_model(noisy_phase_classifier, show_shapes=True, dpi=70)" - ], - "execution_count": null, - "outputs": [] + ] }, { "cell_type": "markdown", @@ -755,9 +730,11 @@ }, { "cell_type": "code", + "execution_count": null, "metadata": { "id": "210cLP5AoClJ" }, + "outputs": [], "source": [ "noisy_data, noisy_labels = get_data(qubits, depolarize_p)\n", "training_histories['noisy'] = noisy_phase_classifier.fit(x=noisy_data,\n", @@ -766,31 +743,29 @@ " epochs=n_epochs,\n", " validation_split=0.15,\n", " verbose=1)" - ], - "execution_count": null, - "outputs": [] + ] }, { "cell_type": "code", + "execution_count": null, "metadata": { "id": "eQ8pknNdohzy" }, + "outputs": [], "source": [ "loss_plotter.plot(training_histories)" - ], - "execution_count": null, - "outputs": [] + ] }, { "cell_type": "code", + "execution_count": null, "metadata": { "id": "nBtgnKWtuWRR" }, + "outputs": [], "source": [ "acc_plotter.plot(training_histories)" - ], - "execution_count": null, - "outputs": [] + ] }, { "cell_type": "markdown", @@ -801,5 +776,30 @@ "Success: The noisy model still managed to train under some mild depolarization noise. Try experimenting with different noise models to see how and when training might fail. Also look out for noisy functionality under `tfq.layers` and `tfq.noise`." ] } - ] + ], + "metadata": { + "colab": { + "name": "noise.ipynb", + "provenance": [] + }, + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.8.8" + } + }, + "nbformat": 4, + "nbformat_minor": 0 } diff --git a/docs/tutorials/qcnn.ipynb b/docs/tutorials/qcnn.ipynb index f6d851723..f53182701 100644 --- a/docs/tutorials/qcnn.ipynb +++ b/docs/tutorials/qcnn.ipynb @@ -12,12 +12,15 @@ }, { "cell_type": "code", - "execution_count": 0, + "execution_count": null, "metadata": { "cellView": "form", "colab": {}, "colab_type": "code", - "id": "iiQkM5ZgQ8r2" + "id": "iiQkM5ZgQ8r2", + "vscode": { + "languageId": "python" + } }, "outputs": [], "source": [ @@ -91,11 +94,14 @@ }, { "cell_type": "code", - "execution_count": 0, + "execution_count": null, "metadata": { "colab": {}, "colab_type": "code", - "id": "Aquwcz-0aHqz" + "id": "Aquwcz-0aHqz", + "vscode": { + "languageId": "python" + } }, "outputs": [], "source": [ @@ -114,11 +120,14 @@ }, { "cell_type": "code", - "execution_count": 0, + "execution_count": null, "metadata": { "colab": {}, "colab_type": "code", - "id": "3Pl5PW-ACO9J" + "id": "3Pl5PW-ACO9J", + "vscode": { + "languageId": "python" + } }, "outputs": [], "source": [ @@ -127,11 +136,14 @@ }, { "cell_type": "code", - "execution_count": 0, + "execution_count": null, "metadata": { "colab": {}, "colab_type": "code", - "id": "4Ql5PW-ACO0J" + "id": "4Ql5PW-ACO0J", + "vscode": { + "languageId": "python" + } }, "outputs": [], "source": [ @@ -152,11 +164,14 @@ }, { "cell_type": "code", - "execution_count": 0, + "execution_count": null, "metadata": { "colab": {}, "colab_type": "code", - "id": "QytLEAtoejW5" + "id": "QytLEAtoejW5", + "vscode": { + "languageId": "python" + } }, "outputs": [], "source": [ @@ -201,11 +216,14 @@ }, { "cell_type": "code", - "execution_count": 0, + "execution_count": null, "metadata": { "colab": {}, "colab_type": "code", - "id": "FhNf0G_OPLqZ" + "id": "FhNf0G_OPLqZ", + "vscode": { + "languageId": "python" + } }, "outputs": [], "source": [ @@ -240,11 +258,14 @@ }, { "cell_type": "code", - "execution_count": 0, + "execution_count": null, "metadata": { "colab": {}, "colab_type": "code", - "id": "ImRynsUN4BSG" + "id": "ImRynsUN4BSG", + "vscode": { + "languageId": "python" + } }, "outputs": [], "source": [ @@ -263,11 +284,14 @@ }, { "cell_type": "code", - "execution_count": 0, + "execution_count": null, "metadata": { "colab": {}, "colab_type": "code", - "id": "tfff6dJp39Fg" + "id": "tfff6dJp39Fg", + "vscode": { + "languageId": "python" + } }, "outputs": [], "source": [ @@ -338,11 +362,14 @@ }, { "cell_type": "code", - "execution_count": 0, + "execution_count": null, "metadata": { "colab": {}, "colab_type": "code", - "id": "iUrvTCU1hDgP" + "id": "iUrvTCU1hDgP", + "vscode": { + "languageId": "python" + } }, "outputs": [], "source": [ @@ -380,11 +407,14 @@ }, { "cell_type": "code", - "execution_count": 0, + "execution_count": null, "metadata": { "colab": {}, "colab_type": "code", - "id": "eLJ-JHOihDgT" + "id": "eLJ-JHOihDgT", + "vscode": { + "languageId": "python" + } }, "outputs": [], "source": [ @@ -419,11 +449,14 @@ }, { "cell_type": "code", - "execution_count": 0, + "execution_count": null, "metadata": { "colab": {}, "colab_type": "code", - "id": "qpQwVWKazU8g" + "id": "qpQwVWKazU8g", + "vscode": { + "languageId": "python" + } }, "outputs": [], "source": [ @@ -448,11 +481,14 @@ }, { "cell_type": "code", - "execution_count": 0, + "execution_count": null, "metadata": { "colab": {}, "colab_type": "code", - "id": "9tZt0aAO4r4F" + "id": "9tZt0aAO4r4F", + "vscode": { + "languageId": "python" + } }, "outputs": [], "source": [ @@ -476,11 +512,14 @@ }, { "cell_type": "code", - "execution_count": 0, + "execution_count": null, "metadata": { "colab": {}, "colab_type": "code", - "id": "oNRGOqky2exY" + "id": "oNRGOqky2exY", + "vscode": { + "languageId": "python" + } }, "outputs": [], "source": [ @@ -532,11 +571,14 @@ }, { "cell_type": "code", - "execution_count": 0, + "execution_count": null, "metadata": { "colab": {}, "colab_type": "code", - "id": "T5uhvF-g2rpZ" + "id": "T5uhvF-g2rpZ", + "vscode": { + "languageId": "python" + } }, "outputs": [], "source": [ @@ -555,11 +597,14 @@ }, { "cell_type": "code", - "execution_count": 0, + "execution_count": null, "metadata": { "colab": {}, "colab_type": "code", - "id": "aJTdRrfS2uIo" + "id": "aJTdRrfS2uIo", + "vscode": { + "languageId": "python" + } }, "outputs": [], "source": [ @@ -578,11 +623,14 @@ }, { "cell_type": "code", - "execution_count": 0, + "execution_count": null, "metadata": { "colab": {}, "colab_type": "code", - "id": "DOHRbkvH2xGK" + "id": "DOHRbkvH2xGK", + "vscode": { + "languageId": "python" + } }, "outputs": [], "source": [ @@ -603,11 +651,14 @@ }, { "cell_type": "code", - "execution_count": 0, + "execution_count": null, "metadata": { "colab": {}, "colab_type": "code", - "id": "1Fa19Lzb3wnR" + "id": "1Fa19Lzb3wnR", + "vscode": { + "languageId": "python" + } }, "outputs": [], "source": [ @@ -636,11 +687,14 @@ }, { "cell_type": "code", - "execution_count": 0, + "execution_count": null, "metadata": { "colab": {}, "colab_type": "code", - "id": "Bi6q2nmY3z_U" + "id": "Bi6q2nmY3z_U", + "vscode": { + "languageId": "python" + } }, "outputs": [], "source": [ @@ -662,11 +716,14 @@ }, { "cell_type": "code", - "execution_count": 0, + "execution_count": null, "metadata": { "colab": {}, "colab_type": "code", - "id": "jD3fgcWO4yEU" + "id": "jD3fgcWO4yEU", + "vscode": { + "languageId": "python" + } }, "outputs": [], "source": [ @@ -693,11 +750,14 @@ }, { "cell_type": "code", - "execution_count": 0, + "execution_count": null, "metadata": { "colab": {}, "colab_type": "code", - "id": "pFXow2OX47O5" + "id": "pFXow2OX47O5", + "vscode": { + "languageId": "python" + } }, "outputs": [], "source": [ @@ -721,11 +781,14 @@ }, { "cell_type": "code", - "execution_count": 0, + "execution_count": null, "metadata": { "colab": {}, "colab_type": "code", - "id": "vzEsY6-n5NR0" + "id": "vzEsY6-n5NR0", + "vscode": { + "languageId": "python" + } }, "outputs": [], "source": [ @@ -785,11 +848,14 @@ }, { "cell_type": "code", - "execution_count": 0, + "execution_count": null, "metadata": { "colab": {}, "colab_type": "code", - "id": "_TFkAm1sQZEN" + "id": "_TFkAm1sQZEN", + "vscode": { + "languageId": "python" + } }, "outputs": [], "source": [ @@ -820,11 +886,14 @@ }, { "cell_type": "code", - "execution_count": 0, + "execution_count": null, "metadata": { "colab": {}, "colab_type": "code", - "id": "2tiCJOb5Qzcr" + "id": "2tiCJOb5Qzcr", + "vscode": { + "languageId": "python" + } }, "outputs": [], "source": [ @@ -875,11 +944,14 @@ }, { "cell_type": "code", - "execution_count": 0, + "execution_count": null, "metadata": { "colab": {}, "colab_type": "code", - "id": "Ut-U1hBkQ8Fs" + "id": "Ut-U1hBkQ8Fs", + "vscode": { + "languageId": "python" + } }, "outputs": [], "source": [ @@ -932,11 +1004,14 @@ }, { "cell_type": "code", - "execution_count": 0, + "execution_count": null, "metadata": { "colab": {}, "colab_type": "code", - "id": "EyYw9kYIRCE7" + "id": "EyYw9kYIRCE7", + "vscode": { + "languageId": "python" + } }, "outputs": [], "source": [ @@ -955,11 +1030,14 @@ }, { "cell_type": "code", - "execution_count": 0, + "execution_count": null, "metadata": { "colab": {}, "colab_type": "code", - "id": "yL3jhGiBRJHt" + "id": "yL3jhGiBRJHt", + "vscode": { + "languageId": "python" + } }, "outputs": [], "source": [ @@ -1008,11 +1086,14 @@ }, { "cell_type": "code", - "execution_count": 0, + "execution_count": null, "metadata": { "colab": {}, "colab_type": "code", - "id": "W3TkNVm9RTBj" + "id": "W3TkNVm9RTBj", + "vscode": { + "languageId": "python" + } }, "outputs": [], "source": [ @@ -1065,11 +1146,14 @@ }, { "cell_type": "code", - "execution_count": 0, + "execution_count": null, "metadata": { "colab": {}, "colab_type": "code", - "id": "suRvxcAKRZK6" + "id": "suRvxcAKRZK6", + "vscode": { + "languageId": "python" + } }, "outputs": [], "source": [ @@ -1089,11 +1173,14 @@ }, { "cell_type": "code", - "execution_count": 0, + "execution_count": null, "metadata": { "colab": {}, "colab_type": "code", - "id": "-6NR7yAQRmOU" + "id": "-6NR7yAQRmOU", + "vscode": { + "languageId": "python" + } }, "outputs": [], "source": [ diff --git a/docs/tutorials/quantum_data.ipynb b/docs/tutorials/quantum_data.ipynb index 58329cd0f..9e78b9493 100644 --- a/docs/tutorials/quantum_data.ipynb +++ b/docs/tutorials/quantum_data.ipynb @@ -114,21 +114,21 @@ "!pip install tensorflow==2.7.0 tensorflow-quantum==0.7.2" ] }, - { - "cell_type": "code", - "execution_count": 0, - "metadata": { - "colab": {}, - "colab_type": "code", - "id": "4Ql5PW-ACO0J" - }, - "outputs": [], - "source": [ - "# Update package resources to account for version changes.\n", - "import importlib, pkg_resources\n", - "importlib.reload(pkg_resources)" - ] - }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": {}, + "colab_type": "code", + "id": "4Ql5PW-ACO0J" + }, + "outputs": [], + "source": [ + "# Update package resources to account for version changes.\n", + "import importlib, pkg_resources\n", + "importlib.reload(pkg_resources)" + ] + }, { "cell_type": "code", "execution_count": 3, @@ -285,7 +285,7 @@ }, { "data": { - "image/png": "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\n", + "image/png": "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", "text/plain": [ "
" ] @@ -484,9 +484,7 @@ "outputs": [ { "data": { - "image/svg+xml": [ - "(0, 0): (0, 1): (0, 2): (0, 3): X^0.192X^(11/14)X^0.276X^0.876Y^0.622Y^0.78Y^0.802Y^(5/14)Z^(7/16)Z^(3/11)Z^0.958Z^0.501" - ], + "image/svg+xml": "(0, 0): (0, 1): (0, 2): (0, 3): X^0.192X^(11/14)X^0.276X^0.876Y^0.622Y^0.78Y^0.802Y^(5/14)Z^(7/16)Z^(3/11)Z^0.958Z^0.501", "text/plain": [ "" ] @@ -559,9 +557,7 @@ }, { "data": { - "image/svg+xml": [ - "(0, 0): (0, 1): HHXRz(2.0*ref_0)XHHRx(0.5Ï€)Rx(0.5Ï€)XRz(2.0*ref_0)XRx(-0.5Ï€)Rx(-0.5Ï€)XRz(2.0*ref_0)X" - ], + "image/svg+xml": "(0, 0): (0, 1): HHXRz(2.0*ref_0)XHHRx(0.5Ï€)Rx(0.5Ï€)XRz(2.0*ref_0)XRx(-0.5Ï€)Rx(-0.5Ï€)XRz(2.0*ref_0)X", "text/plain": [ "" ] @@ -1047,7 +1043,7 @@ }, { "data": { - "image/png": "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9evXA+DxeLjpppsYNmwYI0aM4Mknn+THH3/kZN0E7fvvv+eUU06J+BrCjVfPl19+yfjx4xk9ejTTp0+nsLAQgJ9++olRo0YxatQoRo8eTVVVFXv27GHq1KmMGjWKYcOG8fPPPwOQn59PSUkJAG+88QYjRoxg5MiRnH/++VHP0RHo2PI4wciYMElHw1tTAzS0hIVzqZtyclplTBJJe+b2L1ezZnd823gNyUvjfycMbXS7V155haysLOrq6hg3bhwnnXQSl19+OfPnz6d3797s27cPgDvvvJP09HRWrlwJQFlZWaPHLigoYMGCBRiNRiorK/n5558xmUzMmTOHW2+9lY8//pgXXniBbdu28ccff2Aymdi3bx+ZmZn89a9/pbi4mNzcXF599VUuueSSsOcoLi4OO149kydPZuHChSiKwksvvcQDDzzAww8/zEMPPcTTTz/NpEmTqK6uxmaz8cILL3DUUUfxr3/9C4/HQ21tbdCxVq9ezV133cWCBQvIycnxny/SOToCUoRFQ8aESToYWjsib30gQ7J6/ny8FRUkT5pE8sRDKHrwIQCM2dISJpG0JU888QSffvopADt37uSFF15g6tSp/jpTWVlZAMyZM4f33nvPv19mZmajxz799NMx+sIQKioquPDCC9m4cSOKouDyhS3MmTOHq666yu+u1M53/vnn89Zbb3HxxRfz22+/8cYbb4Q9x8KFC8OOV09BQQFnnnkme/bswel0+redNGkSN954I+eeey4zZ86ke/fujBs3jksuuQSXy8XJJ5/MqFGjgo71448/cvrpp5Pjm0Bq54t0jo6AFGHRkDFhkg6Eqqp4qkT9L80SVr9+AzuvuBIA+8iRZF96Kd66ekqeegpTmAumRHKgEYvFKhHMmzePOXPm8Ntvv5GUlMRhhx3GqFGjWLduXczH0JdECK1PlZyc7H/8n//8h8MPP5xPP/2Ubdu2cdhhh0U97sUXX8wJJ5yAzWbj9NNPb1FM2bXXXsuNN97IiSeeyLx587jtttsAuOWWWzjuuOOYNWsWkyZNYvbs2UydOpX58+fz9ddfc9FFF3HjjTdywQUXNPscHQEZExYNGRMm6UCoDgdogfm+mLCq777zr9dqguVeczWD1q5B6eDBuhJJR6aiooLMzEySkpJYt24dCxcupL6+nvnz57N161YAv7ttxowZPP300/59NXdk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\n", + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAmEAAAE9CAYAAABDUbVaAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjMuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/d3fzzAAAACXBIWXMAAAsTAAALEwEAmpwYAAC3PUlEQVR4nOyddZhTV/6H3xvPuCKDDe5WoFCsAtSVurvsVre/drfbtbq7u7srLS0tlLYUirW46yBjjEv0/v44uclNJslkZpIROO/zzDPJ1RO793O+qqiqikQikUgkEomkdTG09QAkEolEIpFIDkSkCJNIJBKJRCJpA6QIk0gkEolEImkDpAiTSCQSiUQiaQOkCJNIJBKJRCJpA6QIk0gkEolEImkDTG09gKaSk5Oj5ufnt/UwJBKJRCKRSBpl6dKlJaqq5oZb1+FEWH5+PkuWLGnrYUgkEolEIpE0iqIo2yOtk+5IiUQikUgkkjZAijCJRCKRSCSSNkCKMIlEIpFIJJI2QIowiUQikUgkkjZAijCJRCKRSCSSNkCKMIlEIpFIJJI2QIowiUQikUgkkjYgYSJMUZRXFEUpUhRlVYT1iqIoTyiKsklRlBWKohyUqLFIJBKJRCKRtDcSaQl7DTg6yvpjgP6+vyuAZxM4FolEIpFIJJJ2RcIq5quqOl9RlPwom5wEvKGqqgosVBQlQ1GUrqqq7knUmCSSROD2eCmqcpBmN1NZ52qwPs1uxmoyUFLtQFUhxWYiyWxEURQMCiiKgsvjxaAoGA1Ki8ejqioOtxdVBZNRweNVsZmNMe/r8aqYjMHzM49XRQEMBgW3xwvQYJv9GbfHi8loCHofWouiqnrcHjXsOovJQJrNzJo9lQAMzUujrNaJxWjAZjbG/Llr1Ls8VNa72LC3mrH5meyrcfrX7SqvY2tJDUPz0qiqd7O1pKb5LypGspMtzBjSGUVp+H67vW5MBnELc3lclNaX+td5vCpeVaXSVUaNs4ayulq6J/dlc+VqimrKAKhzeah2uEi1mqmqd6EoStDrVYB+nVPITLLENFan24vJoFBU5aDO5cFsVCisdODxBj677GQLPbOSqHd5sJiNWIxK2NcWiserYjQo1Djc2MxGjAaFijoXO0prqXN5GmyvKNA5zUbPrCScbi8WU+O/1ap6N2ajQr3L61+WZjdRU++msMpBVpKFZJuJ1bsrsBqN9My2k2ozx/Te1DrdlNW62FtRH/R+JAqjQWFI1zTslsa//8NzhjMwa2DCxxSJtmxb1A3YqXte4FvWQIQpinIFwlpGz549W2VwktbF7fHy8bICzEYDNQ43W0pq2F1ex95KB0O6ptI5zcZPG4rZVFSN26PSPdOO1Wyg3uXFYjTw0OkjGZKXFvbYFXUu3l60nfkbitlX42R4twzKap3s2FeLqoqLm1cVF10V6Jxm5bEzR5ObaqWwsh6z0UBWcsML8b4aJ1e/vYy1eyspr20ovqJhNCgYFYX0JDPpdjObi6u5cmpfbjlmUMzHUFWV5TvLmbeuCIfby7IdZVTWuVlfWBW0XVayhY+uOoQ+uSkNjuFwe5i/oYS3F21nV1kddS4Pu8vryM9JxqAoaLeHvRX1GAwKmUlmtpXWApCfnYTZJ8TG5mdx50lD27Uw21JcTZ3Lw2+bS+mabufPgnK/+I3GhsIqft5YAkCq1USKzcRHf5lItwx7xH20z+bnDSVU1ovvRlmtkzW7Kzl+RFeuPrxf2JvvR0sLWOsTVJuLq9lcXM3OfXVRx5dsMVLj9DR4nJdu47OrJ9EpzRZ1f4CfNxbz5A+bWLu3kqp6NyC+NwFR4sFgLUQx1oHiQXWlg6KC4kQx1ge/dq8VxeAAQDFWY7TtFtuq2us14Cw7GEXxYM5YAqhgrMdgqsTrzMKYtBWvMwfF4AQUOv1Z10AIubwudlTtoFdaL0yKieK6YiqdlY2+ziazN/6HZHMCjhmORJszdiT4+C3kq92xbfe3MX87YEVYzKiq+gLwAsDYsWMTL6MlLcbt8eJwe0m2xvYVe/yHjTz546aw6/7cWQ5Aqs2EghAwaXYz20pq6J5pZ31hFc/M28STZ49ucGObv6GY699bTlmti17ZSfTITOK7NXvxelW6ZtixmIxYTAZqHW7yMuxsLq7m102l3PvNWvrmpvDg7PUc0iebd6+YEHTcjYVVPDV3E79tKaVXdhJ/mz6A7aW19MyyB82+VBU2FlVTVuNkSF4aKVYTW0tqfAJQvBYVlU1F1Xy1YndYEfb71n3UuzwUVznYU1HHsh3leFWV0monK3dVRHxPR/bIIDfFypy1hTz8/QaePqdh2OWL87fw0HcbyE62cHDvLBQFhndLx+H2sr20hr6dUjAaFPp1SkF7a4d3zwDA4xUz5n01Tt79fQc9suz89bB+EcfTEupdHmav3sshfbOp9omELuk2ympdvDh/C5dP7RNVFK3aVcGJT/1CuEl4ssUY1RqRZDGSZDFS6xM3eyrqeXH+Fm47cWiDbb1elWd/2sxz8zZT5XAHHV9RoHtmEg99t4HtpbU8ePpI/36Pz9lISbWDNxduR1Eg2WIixWpiZI90Th/Tg85p1qDzuLxC5BRVqqwpXkdd0ny8Hgt7arcz2NaZyvo6tu1N4tGF26g2/YEBA4v2LqJzUme6JHdhY9lGSupK8bqTUFEwmKpQbQrkQ6qioqoKLtVIukFFUQx4VQ8qXlqC3ZSEgkKtu4Zu3dfh8rgod5ZhVIxYjTZUVNzerbi8Loy2QuymJOrqzajuXnipok96HwxKQORrN87Saidb9qVTX90DvA2vN9kpZgZ1TcVtKCRN6c+oTiNQFFBQ8KoqBkX8B2E96p2TTL3bw4dLCvhoaQFPnjWacb2zgo7p8XqZt76EZ3/aREGZEMk5yRbG5GfSLcNO5zQbigJ2s4lBXVOxGA1sKalme2kdX/25m/6dU1i3t4qtJTVcP60/Zx8cbFy446s1zFrZUEUN756OATFZHJufRbcMO72yk8hKsrBtXw35WckoCmwsqmFTURWbiqr9E4hZ100h1RZ4fz5dXsAbv21ncNc0flxXRO+cZA7pk02v7CQUBeqcXlbtrqBvbgqoKptLavB6Vbqk28nPSeKTZbvYW1HHV9dNwRjm9/PWwu08NXcTB/fOol9uCr1zkrGajQzskkKSObHS4/EfNrBgUyk/3HQogalkgCXb9vHPT1dRVe8ib9zEhI6lMdpShO0Ceuied/ctk3RAymudVNS5qKp3U1zt4PYvVlPr9PD1dVMorKxnWLf0iPu6PV5eW7CNI4d05tLJvdlQWEXXdDuKAoO7pjF3fREDOqcysEsqCuD1QnpSwAz+94/+5IMlBZw+tgeHDgg0qnd5vPz9oxVkp1h589LxUceg54Fv1/HMvMB09bctpUHrPV6VGY/OB8T4vrl+SkzHjcaL87dw96y1FFXWB1ku5q4v4uJXFwdta1AgN9WKxwvnT+jFMcO7cPGri7n5qIFcMqk3RVUOOqdZ/cLiP5+t4v0lO1FVNUhsqKrKx8t20Ss7iVnXTYlZMIfj8jeW8OzczZw/oVfMLopw6Me4o7SWdXsrcXtVXvllK0u2lwVtazEacPpco68t2MbFk/L53wkNhRHA24t24FVhQp8suqbbOWlUHqN7ZlLv8tA5BkvR9tIa7vp6LffOHM4dX67h0+W7+Oexg7CaAoJ7c3E1l72+hK0lNRw+MJejhnZhyoDcIHGoqipXv7OMD5cW8O/jh5BuN1NZ7+LRORsA6JmVxNybDmNb5RaybdmkWlL5cMOH9M3oR6Ytk+2V27GZbDy29DH21uxlQtcJLHJ9Az4tnmXLYnPdGtyqG2sn+GrPd0GvY0vFFgoq95JhzsPrqcKmdicnxY5FsTOkS1e6pWWzs2on+6o91HhKKKoroKiuiJP6nkT31O70Se+DV/Xy9B9P4/Q4md5rOof1OAyzQXzmHtXD5vLN9Ezric1ow6gY6ZXeC5fHRbY9G4B5O+dx7Y/XAnD9Qddz3uDzsJnEZ+DyuCiqK6JbSjcATnr6VzIUM6+ffHDQ65i7rogf1hVy5JAu3P7laiqLazAZFAZ1TaXG4WFrSQ0PnDqCCX2yycuwNctCOzi3Bx/9/h2b9ho5flhn/3KH28NdX63lzYU7AAtg4dsbpjCoS3hLvMaIruL/9YcFlg389zdU1yTTOTlw/GqHm3mrHSQbs3n/ygkc98Qv4r0Ylcf/Thga1ioPMLpb4PGovMDjP3eWc9LTv7Jyh8opowPneer7P6h2WNld6mDGkAE8euYoUppwDeiS3Jlr3lnOzCdWk2438/JFY+memQSIycgni1dzSK8+vHPphEaOFH+m9PHy/UoHiiejwe+7os7FY7PXUVktxoq38d9/ImlLEfYFcI2iKO8B44EKGQ/W8XB7vPy2pZTzX/497Ppxd88BYFCXVCb3y+Ffxw1uYHVYtVu4QE4Ymcf4PtmM75MdtP7c8b2ijuEfRw/igyUFbCysChJhGwqr2FtZz+PHjopZgAFcc0Q/PlxaQPdMO8cO68rds9ZSWu0gO0VYI1YUlPu3vXfm8JiPG40R3cX41uyp9IswVVV59ddt2M1G7pk5DLvZCCgM7JJK75zkoP3X3HG0P56sS3rwRaVbph2n20uN0xN0kf1jZ7n/ZtUSAQZwxdQ+fL+mkJ83lnDs8K5Rty2rcbKhsIqn523mqkP7MLFvDgD//XwVX/65m9cvORiLycDMZxb4rU8ZSWYumdQbi8lAv07CrbpsRxn1Lg+FlfX8uqmUV3/dxhVT+9A1vaFFbOWucib1y+bty4JvCOn22ARjr+xkXrxgLAAnjMzjiz9388eO8qDv6gPfrmNXWR23nziUCw7phcvrot5Tj1e1sql8E1m2LJJMSbgyPsJg68mfu3cwv/hdFhQsJblfCaornSP6X8Qrq17iieVPADCt5zR+2PFDxHF9v/17Dut+GOcMPodady1Tu03FrbpZVvgHl378NOb0P7l1/K2cMeAM/vL1fcxZ0pkqZy6lqgnw8N61hzb629DHXmkc3TtyztWYzmOiHm9Kt8Ck5YgeR/gFGIDZaPYLMIAUq5Fqn0VR4/mfNnPvN+sAeGuh8Indfcowzh7X0x+zuHhbGQf3zmpRjGWqzUy3DDvbQmLfrnt3ObNXF/qf33rsoEYFWCQyksx+96/GNyv3UOP08PFfJjI0L505Nx5Kut1Mbqo1wlGiM7hrGooC20pq/ctWFJRT7XBz9NAuXHFoHw7qmdnk4x47rCs3H1XLq79uY31hFXPXF3P+hF6oqso/Pl7BrvI6bj6qbdx8fXLENWJzcXUDEfbPT1awsaia0T0zuPOkYU26NySChIkwRVHeBQ4DchRFKQD+B5gBVFV9DpgFHAtsAmqBixM1Fknz2VRURbLVFPbGpqoql7y+hPkbihusm33DVH7eWMzjP2ykqt7Nur1VrNtbxWVT+jQQCZqoGZef1eA4sZCVbMFkUCjVBdUCrCwQ5oERPvdZrCRZTMy76TAsJgOLtuwDYO2eKib3FxdBzf0w+4apDOyS2qwxh6JdxNfuqeKwgZ0AmL+xhPkbirnpyAGcMrp71P2j3WyyfPE0ZTXOIBH22fJdWE0Gjh7epaXDp5PvBlEfJkjY6fbyzLxNnDgyj3d/38GLP2/1r+uZZWdi3xy2l9bwxm/bAXj+py3sq3FiMxt54fyxZCSZyc9JbjBLP21M4D35eWMx57/8O0u2lXHCSPFddXu8PDV3E31yU1i1q5IrD+3TotfoVb04PU66plsxZyziX4uf5bXc5+iW0o2HlzzM75VbGTN0GJ8Vv8CSH7tjMVr4bvt3TOk2hZ93/Rx0rOTecPUvz/ifG8yAuZyPd90e5A/QC7AT+pzAOYPPYU/NHgprCpnUbRJZtizSrcE3ETNmJnU7BKW4gpN6/4WzBk5EURSWrxiP1+Hwb3fdtEEx3YBCBVhLMRqMXDv6Wt5f9z690qJPsJItJkqrA+JBVVW/ABvfO4tFW/eRl27jlNHd/MkSJqOBQ/pmhz1eU0m2mIIC390eLz/5rnfnTejJWwt3cLjv99ocUm1mqhzB8aSLtu4jK9nCQT0zAPyTjuZiMRnolGplV3kgtvCz5buxmQ08cPoI0pppuTYYFK4+vB9/Pawv4+/5ga/+3M1543uyeFsZHy4tAOCYOFxbmkPPLGHl0q7Vev7cKe4LV0zp0+YCDBKbHXl2I+tV4OpEnV/SfH7bXIrdYuSZuZv4bk0hAzun8uFfDmnwY/1m1V7mbyjmzLE9GNgllTu+WkOPLDvXHtGfgV2E+/DSyb3ZUlLDQ7PX882qvazdW9lAhO0qr8NsVPw38qaiKArZKRZKqwM3GLfHy8u/bCUnxUIv3w+yKWiWoUFdhcg67+VFzL3pMHrnJLO3QgQih76OlpCeZKZTqpUtxdX+ZZuKxONzGrEENkaGz3VbXuuih0/nqqrKVyv2MH1w52ZfhPVoIjBcFt+jczbw7LzNrNpVwZy1RQBM6pfNoi37KKwUn9mP68TyoXlpzN9QTJXDzf/NGMDk/jkxnV+zDOpvmK8t2MZjczYCkJlk5rwY30dVVSmqLfK7iJYVLsNitPDI0kdYXrScSwZfg63rpxTWwzGfHMMdE+/g9TWvQwqscs2HcthUHohv/HnXz5za/1T21OxhRfEKpvc8is82f4xRsTAoqz+rS1eTVHIdr140iYeWPMTBXQ7myhFXsrRwKRfPFnPTt499m+E5w1EUhWE5w2J6HclWEx5Xmt/yPKBzCsVVgd/IsW10gwS4YsQVXDHiika3S7GagixhWkbmvTOHc/bBPdlRWovJqJBkScytzK6LBQTYXFxDvcvLo2eO5JTR3bnr5JZZwlOspgaWsGXbyzioZ2ZMWZOx0i3Dzi6dICmudtAlzRaX376iKEwf0pl3Fu1g8bYy/6T6s6snBbnrW5NOvhjKworgpJE6p4dd5XWcfXBPjmnEYt9adIjAfEnrUe/ycPaLC4OWrS+sYuYzC5hz46H+ZSsKyvnr28sAuOmogeSmWumWaWdK/5ygC6KiKPTNTeG+U0fwzaq9XPraYjbdfWxQiv+e8nq6pNtalPafnWyltDpgCdtWWsPGomruPHlYi46bkxIQhqt2VdA7J5ndFXUkW4yk2eL780mzm6lxBi7IBWW1JFuMZCa17EKZ6Ysh2Vcr3p/v1xRy4wd/UFXvZlK/2EROY2hZkm5d5Luqqtz+5RpeW7ANwC/A/nv8EC6Z3JsLXvmdosp66l0eVhZUkGYzMW1wZ574QQino4bFLhK0i73DJ8JqHG6/AAO4eFJvekQR48uLlvP7nt+5bPhlvLjyRZ7+42n+d8j/yLRmcsO8G4K2fWH1Y0HP/7vgv0HPfznrFz5Y/4HfpQhwzehryLJlUeuqJcWSwvzfptK/s4Xnjz2Ewx75liGdOzMkewivHPWKf5+xXcZy/UHX0zutNyNyR8T8XmikWI3U6ARMcZWDo4Z25oqpfZmzVkyu2jspNlPQa9jgy/wdlicsGD2zmz7BagpJFiN1OhGmJcIMj5MFJdVmolInwnbuq2VLSQ3njI9vFYBumUlBYRT68Ip4cPHEfN5ZtIPCynpW7qqga7qNUT0y4nb8pmIzG8lKtrC3MliE3f7lakBM9toLUoRJgvh1U0nQ8xcvGMvlbyzxW2U0PlkmfCY9suz+WIWjhka+aabbzYzumcHyHeWU1TqDLgB7KurCujubQnaKhRKdO3JjoRjv6DhcCM4a14P3Fu/0z8j3lNfTNcMe15kq+MoLOAIX/IKyOrpnJrX4PFp6f7lPhN366Ur/7FuLRWspmiVMy5gEMX5NgOWmWimucpBuN3PRxHxAuDBX7arg8Ifmsaeinrx0G8cM68KSbfu4cGI+A5ogEmxmIQK1Gkc7y2qpdrjpkWVn5746LvSdMxxfbP6Cf/3yLwDyUvJ4d927ANz+2+3+bYZkD+GioRfx2abPWLB7AV5XKgazEAQKCkmOqSQbOvHi6eeRbk3nuD7H8cTyJzh/yPkMyx5Gjl2I3RSLcC2N6J7Jsu1lzF1Xws4S+MuU8C6ty4ZfFvN7EEqy1UStTtQXVTkY3zubMb0yGdOr6TFAbUGy1RT0myjxTbRCs0UThd1spEJX+29lQTnJFiO9c1rmItRIs5lZul3ENtrMRuasFbFmM4Z0bmTPppGTYmGfbpJaWu2kVxwFrBZbuaKgnB37aumTm9zIHomnc5rN77UA+PyPXby3eCfdM+2cMbZHlD1bFynCJADMfOZXDu6dHZTCfPKoPGYM6cyFh/Ti3d934vWqfqvSr5tKmNI/h5cuHBvzOS6d3Jtr3llOsW4W5vWqbC+tZWILYzhyUqxBxSM3FlWjKIj06hZy+0lDeW/xTkp8rpydZbVRyyE0lyRL8E1TiLCWn0ezpGk1n7qk2SiucpBmMzVJ6ETDpLkjdZaw3b4YlHH5mYzNz+LZeZvJy7D7v0Od06xBxTHtFiODu6bxzuVNz6bSipJqMWmam/Ph00cxont6UNHSb7d+y+urXycnKYd5O+cFHefWX24Nej4oaxCXDLuEo/OPFm6XntPZWL6Rs55fwrj+Lk4+qBOjsycz+b4F3HTkAPqki7izvJQ8Fp+7GKvRGlZED+qSypd/7ubb1XtJsZo4Y2z0mL/mkKxz5TncHsprXc12+bcVKVYTTo8Xh9uD1WT0W7szI2QIxht7iCVs6Y4yhualx6WoMgAK1Do93P7lGi6elM/tX66hT04yvbLjK2LS7WaqHG5/0dfSGgcHxVGIp/lEmBbveepB8f8+N5UuadYgS9iDs9cDcM3h/WIqXttaSBEmQVVVlu0oZ9mOck4b051ki5Gbjhror13Tr3MqTo+X4moHndNsVNS62FhUzUmj8prk89dceyVVTvAZzX7eVEJRlYPDBzU/uBVEJWq9O3Lnvlo6pVpjqpjcGFaTcD2KivdCNDY3iSAayVYju8sDs+6CsloOzm/5hTIjSSQuaPFAu8vrOGxgLs+ce1DcLkZaCQB9TNge3yz03pnDSbaaeHaeKGGhMX1wZ15fsJ1pgztxzLAu9OvUfEFoNhowGhTq3eKGWeS7+HZJswUJsH31+7h5/s3iia7yyNTuUxmcNZjnVzwfdNwPT/gw5DxmhmQPIcNUSKongxP6jmapr3TG0Lxgq6I+6y+ULr6MrY+WFjCsW1pCitwmW4x+y5H22XdqJQtSvEj2/X5rHD4RVuMgI8nsd38nGn19uJUFFazaVcl/jx8St+NrNRCXbNvnn8jMPKhblD2ah2apqqxzkWY3s6/GSW5K/IRsaGeGvIy2LfsAIulBKyzt9apU1LmYNqgTZ45rP1YwkCJsv0dVVa55dzmbi6r56trJYS/2+qzCLcXVDO+ezsWTevuXdfP9oHaV1+Hxqky870cAJjYxnsgvwnwB9Pp6XC0WYSlW6lweap1ukiwmiqsddEqN34UgJ9VKSbWT0hon1Q53XE35Gkm6TCyt5lq3OFjCjAaFzmk29lTUU1YjXsOkvjlxDWYOZwlb4ctO7ZpuJ9lqYuPdxwTdPEf3zGTZf2ZgjrF1S2PYTAa/O3LDvq0YkzbjNgxnwe4Cvt36LUV1RRTViri0v4/7Ow8sfsC/74icEVwy/JIGIiwSaXaT302ltapKb0Lsnl4M5cQxNkdPstXEdt9NqEgTYXH8TbQGWoJMjcNNlm+ild1KVjAQ7kjtN7l6t/g+x9NV+J/jh3Dlm0tJspp4c+F2JvTJ4urD41/wWBNhFXUuHG4vXhVyY6iP11xaGl4SD6wmg98yvqu8jqp6N9MGh2+B1ZZIEbYfo6oq1767nK9XiPJr6wurGNI1rcGXUJ81s2xHORccEpxFlpUsbhLltU5/XFGq1dTkeCstdqyk2kG9yxNUEDW1hXWqsn2zutJqJ0lZJooqHXHNXuySZqOgvI6d+8RNrWczMi4bI1kXSF1QJs6jFT9sKV3TbeypqGNLiYiV69spvu6O0JiwijoXr/y6FYvR4L+RhrNexNMtYLXWsqTqNa78voIFexaQ1AtO+uLFBtuZDWbOHnQ2jy19DKdXfJ+ndJ+C2WDm2enPkpecx0mfnxT1XPqsPU2MxVpzDAiqXXTXybFlOzYV/RiLfO7Z5taaaiu074dWlLckzgHljWG3mPzuSM2yG0tx31g5amgXJvfL4RdfLO60QYkRCdp3s7zORb3PStycrPFYGdy17ZM+bGYjDncgRhQSc91uKVKE7ccUlNXx1YpA/dvjnviFjCQzx4/oyuEDO1FQVseU/jmc9PSvQfuF1k7R4sSq6t3+C9Ks66c0+WKRZjNhNRnYW1HPluLgAogtvfDk6qxsPbKSKK52xC3oHGBgl1Te+32n3+WZiBuBiAnzzdx8wjhesWddM+ysKCj3J1j0y43vRVKzhLl87khNRF51WN+4nicSe6r34Or+P7Y4YUuEnnE59hxK6kr46pSvMBlMPHb4Y9y58E7OHHgmg7MGAzC52+SYzmcxBQK2myXCdBapeAntUERQuxBhxVXixtvR3JGacNeaPu+uqGNUj9ZLKrCbjTg9XtweL4WV9eSkWOMeT5Tjm0CmWE1cPrVltewioZWpqahz+cs25Mc57kzj4dNHMroZxV/jjdVk8GdL7y4XrzkenoV4I0XYfszLv4ggyXcuH8/XK/bww9oi9lbW89bCHf5K0+EITb/WaslU1rspq9Gyk5o+G1QUhfzsZL5euYeXftna+A5NQG8J83hVSqsdcZ31D+6SRp3L40/zzmjCDTdWkixGapxuUafK5z6KlzWve6adb1ft4ZdNpSRZjHG/GCmKgtGg+G+WmuXlsIG50XZrEUW1RVw15yquHnl1gzISGkf2OpJj+xzLhrINzOw3k03lm8hLET1dpnSfwnenfRd2v7eOfYssW+S4P7OvMjvo3JFN+E6k2U1YjAZumNE/5n2aSrLVRI3Tg9crvk8GRZRy6Ujo68/VuzwUlNUxs5HCxfEkyReTtnxnOe8t3hmUuBQvNHd0PJJwIqF3R24rFS2e4h239fhZo6hzejh1TNsH5QNYzQbqfZYwbVLbNY7ekXghRdh+xMbCKnbsq2Xa4M68tXA7ry3YRlayhYPzs5jYN4e7TxH9FK9/bzmzVu4N2veLayYxLC+dtXsrGdw1uIaKduGprHNRWFlPVrKl2bPBzGQz6321fuKJVoZhX42T0hqHiHmIowjTYsBW764EAjPLeJJkMaGqosyCFjcXqU9cUzlpVB7PztvMl3/u5rCBufHL7tJhNCj+mLDCyvi7biocFRgUA6mWVF5f/ToPLXkIwC/AFNWMqghBpKoKR6bfz/1TZ2AymJjWc5oYT3Js8Twjc0dGXW82GnB5Aq7XJIuxScHiiqKw4e5jYt6+OaRYhYCoc4leil3T7Qn53BOJye/mFgkxqkqrlj/QEnu+XSWul95wHeBbiFbrzJOAY2toISXFVQ72VtbTKdUa92SQk0bFP6GgJdhMRjxeFbfHy+7yOnJTrQ0SCNoD7SdPU9IiVFU0lb709SWU1Ti57YvVTO6Xw5wbDw36sZmNBp45dwwrbzuSW44Z5F8+pGsaBoPSIMMLhG/dYjJQVe+msNLRojR3fTD4x3+JX/d6TShWO9yBTLA4ijCtKXVBWR2KQouaVEci2XfTrHG6Kal2kBnHLLBBXdL8N7Qp/RNjnTIZFH9MmGbJy22B23ZD2Qbm7ZzH8Z8ez67qXZzz9TlMfHci++r38djSx4K2zbHn0Lf2CXp7ruXrE3+mev0dDO80KO4tdzRMRsWfCVpR54pL5fF4ow9qX7Onsl0VqIwVvyXM6+XnjaJdUP8WZNE2Fbvvpq1dU764NjZ3dVPQ+jaGa7ETLzKTzGQkmdlcXE1xlSOhQfntBatWO9AtJrXttTyLFGH7CTv2Bfqrjb7ze9xelcun9oloSUm1mbl0ciADsrFZUZrNxHM/bWbO2kJ/g+nmcNfJwzh9THeOGdaFkb6YrXgUXtTEXY3DHRAAcRVh4vi7yutIs5kTYlHQXkOtw0NJlTPuWXNaP73jRySmXYfRoPhjwlpqMXV5XJz6xalc++O1bK/czqurXmVHlXChH/r+objVQD21wVmDuXX8rdjNJiyOYdz2+UZQzQmtCG8xGvzB4hV1ria5IluLZN/3qajKwdaSmrATrPaOyRCICft42S7G9Mps1aBvzR25vbSGTqnWuNQdDGWQr//sRZPy435sDUVR6N8phU2FPhHWiskNbYVm9XK4PJTUOFs1oaMpSHfkfsIan5tMT2MXK7PRwO0nDo2pCXWqzRyoVt0CcZOXYefB0wOunlnXTYmLWLKYDFiMBqqdAUtYbkr8Znta8+hElaeAQE2kWpeb4mpH3EXYk2ePZnNxTVxdhHrMRoPfpdIUi6lX9bJ231reWvMW03tO55C8Q3hs2WNB27y//v2g56nmVH468ycURfFbu94x/c6CzYHiX0MT2JxXbwmrrG+nIsz3nV26vQxVhSEd2hKmUu1wMbhLaquWGNDckVtLahLWIslkNLDx7mP8lupE0ScnhR/XF+H1qu0icD7RWH0TQIfbS2m1g745bV/FPxxShHVwXv5lKwu3lPL9msKg5TazIabZTrR2Lnr0fRLjaWGK541BK/FQnABLWLKuhEaibrhJfveRh+IqR9x7r2UkWRjTK3E1lvQxYUVV9RHFnqqq/hvp2tK1/PPnf7K5QpQr+WrLV/7tFBRUVH9WI8D1B13PKytf4Z/j/4nZGPw56OM97GZjQoVRcEyYOyEdFFqK5t7+fes+oH31y4sVkzEQE1bn9GCLQ/HlpqC5Iyvr3QmtsdYaxWfTk8yU1zpxe9V265qLJ1oh8dcXbKOgrI5jhrVefbmmIEVYB2ZvRT13frXG/3xQl1TevXwCpTUO+uamxHXGGK8A8USi9ZlbtHUfqTZTXKrla1hMBpHy7PYmrFikZgmrdrjZW1FP1+EdK27DpMsYLKp0NHAHltWXYTFaOOfrc6h2VZNly2LdvnVhjzUwcyBvHPMGq0pWMbrzaG5bcBtVzirOH3I+lwy7BIPS8Kalib50u5nl/5kR51cXjF6EVda5GNK1/QkczXr7x85yUm2mdpkZ1hhGf+kTL3VOD0mtHFitj2Ht0Q7LGzSFJIvRHy6QHcdq+e0VrZ/s8/O3tPFIoiNFWAfF5fFy3suLgpZ9fs0krCZjQvqq6a1K9naYYQLiprOioJzNxTVcfXj861Ol2kw4qp0Jc+dponHnvlqcHi957aDqdFMwGUWJCpfHQ5nlG1KTT0VVVe5ZdA/vrX8PgF5pvdheuR3AX73+prE3+TMdV164kkpnJXaTHbPBzMFdDwbg7sl3N3r+3j53Q9d0m78/ZaIwGwPxb+02JswaiGPsnZPc7iqFx4JJV6Ki1uWJ68QqFuyWgNjvk4B4sNYkWScoE1Fqo70R2lKvvXaL2P8/if0It8fLJ8t3ceLIPG547w9/4c2PrjqEgrK6JvVxbCopVnGTSbWauGxKYgoKtpRkq8nfx29mAhrIau6uliQmREO7SGqfa0ezXJgMBtxelYUFf2LJnc3ssmWUzRvJnB1z/Ntsr9xOz9SedE7uzOK9iwGY2X8mGdYMBmQOACDN0jyrUp7PJZjSwu4LsWAyGnB7RRHPaoebNHv7u5Tq34e0DnrT1SxhtS4PqkobiLDA+9a7ncYUxUqSNfDepVrb36Qh3mjZkQDHDe+a0MSHltAxf5kHEDtKa1EU6JGVxBM/buKJHzYyf0Mx364WdWs+uuoQxuZnMTY/sePQCvv9bcaAVr8QxoqWyZRmM9EnARdMrQVGouIptIvk5mIhwvLaYZxRNIwGhVpPGV9vXgJApbvYL8DunXIvOyp38OyfzzI0eyj/HP9PVpasZGTuSFItqZzUL3qboFjQYuium5a4Aqgawh2pUlkvsjTbsyUMElNSpTXQYqWq6kX9t9a2wuvdn4lKyGktDmRL2JFDO7da0/emsv9/Eh2cqQ/OBUQx1Sd+2AjAvPWiXs5FE/MZmx+5qnc8ueCQfFQVzp3Qs1XO1xy0mX9ehj0hrpdUm4niqsTVm9Euknt9bUXa4409HDWuGq754RpKM3ZS6CmEnYF1pw04jfFdx3N0/tF4VS859hymdp9Kpi2Tqd2nxnUcualWtt13XFyPGQmzz0Kzr0YkgbTHz0ovINqjpS4WNEtYtU/sJrW6JSxwvkSFIbQW+4MobwpWXXmcRHqJWkrH/GUegJz4VKC/Y7XDzeR+Odx24tBWO7/FZEhYX7N4oc3uEtWk+K1Lx/P03E2M752dkONrs/xSX2uo9mpx3F65Ha/qpXe6qDP3R9EfLClcAiHDfWH6i0zIG+8XxAbFwBkDz2jt4SYEs+8Cr9WkS0QHhZZiMCgkWYzUOj3tsphsLGgxYVU+EdbaFc/1N/L2WG29KSTrricHgiVM/3npXZPtjfY7MkkD/jZ9gP9x/84dO0g0EWiNkBMVE5SXYefuU4aTnqAbrnbT3KeJsHZ60T/+0+M58bMTcXgcvLLqFTaVb/Kvs6g54n/tRA7pNqFDBoPHgiYOtCrn7TXoV7N+pLVDS10s+C1hDs0S1rriYX/6/iYFxQh2zO9DUwiyhLVTVyRIS1i7ptYZqAo+vncW103rx6NzNgCt27qjo6DFbNQ6PW08kuaTZDH5x98eZt4frP+ADGsGR+YfSYWjggW7F/jX3TTvJuYVzAPApJjoXfM4drMFh2kjde720cQ3UWidADQRFq9G6/HG4rv5dNTAfK1ifmUbxYTtT+gtYSkd9PvQFDqKJWz//yQ6IPfOWktuqpWjhnbxLztpVLegWVl+TscOEk0E2b4mtTUOdyNbtl+0lHiLydAumi3fufBOAJ4xPcOjyx5lY9lG/zpNgAHkp+djqjPj9qgo7r6kWdvvRS8eaOKgYF8tZqNCVlL7rLvk9vXy7OiWMM0d2VYuemsz22+1J/SWsPZwbUk0euFlMbZf8S5FWDtEKy43ppdoLXH14X05++AeQdt0z5AiLJTRPTMY2DmVfx47qPGN2yma5aI9zPhVVfU//usPf22wfkDmAJ444glWFq9kQNYA/vNhEQ6Xl6r6xLV2ai+YfZXcd5bV0ik18XXJmktFnbAgdbSacxqa27eyru0sYT/dfFirlD1JNLkpVib1y2Zyv9y2HkqroBfOze1h2xp0/G/WfkZ5rdP/+I3fRFHLU0Z3bxCb0F7dH21JstXE7L/FN+OutTG3ExH2Z/GfvLLyFf/zHqk9mN5rOpcOu5RVJau4as5V3Dr+VrqldKNbSjcAjIYS3F4PVfWu/T77SvuctpbU0Cen/cZn1ruEJaxHVscUxUaf2NVakbVFpfde2R27PpiGxWTg7csmtPUwWg2LUZ8dKUWYJAZqHG7unRVo4/Lp8l0cnJ9Fv04NL/LtWdlLmo/2ubaG26WkroTfdv/G0flHU1pfSoWjgudXPE+qJZVPNn7i3+7BQx/k6Pyj/c8ndZvEygtXNjieyaDg9gpL2P6efaWJsJJqJ0cObb8iTKN7B225o1nC9lTUoygkrGWYZP9Db7hoz/fL/ftK2cF447ftvL9EFFka3zuLRVv3MbFfcDmEmaO7UVBe1xbDk7QC2s09UUH5qqriUT2YDCbOm3Ueu6p3cesvt2JQDPTP6M/6svUA9M/sj8vjYlvlNpJNsVkCTAYFl1ul2unusIHgsaI1lgboH2aS1F4Y0T2dFQUVQTWiOhJa7FKdy0NOigVTO85yk7RfpCVM0iibi6u5/1thBZs+uBMXHJLPoq2/M31w56DtHjlzVBuMTtJaaLFG9gRl8zyx/AleWvkSC89ZyK7qXf7lXtXrF2AHdTqIJ6c9SVl9Gff+fi+jO42O6dgmo0JFnQtV7biB4LGid3W0556C71w+wV/otCNiNgTe55yUxNT/k+z/SEuYpFFe+WWr//Fz543BZDSw7s6j20WZAknr4Y8Ja4Y70uVx8cDiB7hgyAX0SAtO5CitK2Vp4VJeWvkSAEd+dGTQ+sndJmMymLj14FvpmtIVED0cn5v+XMznNxoM7PPFNB4o7kho3z0+U6ymDh1UbjAoKAqoauJ6tkr2f2TF/A6Eu7iYulWrALAPG4Ypt3UySVJ01d5NCXZJSdovLcmOXF26mvfWv8e8gnl8f9r3gHA/vrr6VR5d+mjQtpXOSgCOyT+G4/ocx6E9Dm3hyIX1zunrr7m/B+br3ZGd22mh1v0Fk0HB5VHJ2M+tq5LEYTa2z+xlkCKsAXV//knBNdcCkDpjBt2ffKJVzltcKbJ/vrp2cqucT9I+aUlM2NYKYU3dW7OXJXuXUFJXwsI9C/l448dht3/s8MeY1nNa8wcbQnBvuv370tJN11y9o/Zl7CgYfSKso8a1Sdqe9tz5oP06StuIpHHjyP/wQ6wDB+KtqU7ouTYVVVNRK+rf7K2sZ0yvzA7fJFbSMrSehE2xhBXXFrO1Yiubyzf7l108+2Junn+zX4DN7D/Tv+7MgWfy6lGvxlWAQXC7qP3dEqbPNmzPF/j9Aa0wbopVegb2F7wOB9svuJDqn39u8r57/ncbJS++6H9e+OCDFD32WNR9PJWVbDnhRNYOHkL1z7+w9fQzWDtoMBunHsq+d95p8hjiiZxahGBMT8c+PB1jWhqq05XQc01/5CdSrCZW3X4UeyvrGdRFtiI60PEH5keJCVtbupYzvjqDd459h62VW3n2j2cpqC5osJ1RMXL6gNMprivmvxP+S1FtEecOPpfJ3RJjbT2QLGGKopCbag0qaBtvqufPx7lzJ5aevahftxZFUTAkJ2MbMoTapcvw1ossacUo3mvFZMLrqI88ZoMRDAZUt8v33CD2cTpRFAXFZketr8OQnAKoeB0OFEUhecpULD17UPnNt6QdfxwVn3yKt6Ya++jROLduJf2EE1As0UtHVM6aRfKkSRjT0/3LKr76GoD044+Luq+mcVu7b6QkOl6Hg8ovvyT9pJNQzOEnXarXS8Vnn5M6YzqVX8/CU1EBioJzx3Zqf/+dulWryLvnbly7dqO6nCgmE6rLhWKxYExPx5iZSf369YEDut2Uv/++OLbLBarKvpdFPUPFbA58WXycvU60+dt72w84NopuHzsvv9y/3j56NJYewfGzrY38VkdAMZvw1iauFIR28a52uLn9y9UUVtQzuV9Ows4n6RjEEhOmWbceW/YYv+/9PWjd5G6T+WXXLwD8dOZPpFsDN71npz8b7+EGcSCJMICf/354i4+hqip4PKgeD96aGoyZmXgrKlDdbnZecWUcRtlykn79FVNmFpWzZlHx5RfU/rYwaH39+vV0ufXWoGWq1wuqimI04ti6lV03/h+pM6bT7YknwPdad990EwApU6dgTEuLeH6XR8QZJjfTEqa63WA0gteL4mtfoy1THQ68NTUYkpNR6+tR7HbxOaSlic+kOrHekI7MvtffoPSFF/BUV5N+wglht6n9/Xf23HorpS++iHPr1gbr1dpadt3wt2adv+SJJ4OfP/lUg20u8P2vXNdgFdbBg+n2yMP+70Rbsf9fKZuLySR+qAlCq2QN8Oqv24BA70PJgYsW8K3FhJXXl2M0GEm1pLKjcgfZ9mx+KvgJIEiA3Tz2ZsZ3HY/D4+CXXb8wtvPYIAHWGugbBKft5+5IiE/iTNkbb1B4730Y0tLwVlZi6toV9549Me07YMkSDHYb64YO8y/L/stV5F5zTdjtt5x4Es7Nm+n/y88YMzPZcdHF1C5eTN/vZrPtrLPx7NuHPxVRh150hQow8RreJO3II0kaO9a/bM8/b6V26VL6fv8djg3CAlG/YQPFjzxK2dtv0/2pwA3UsWFD0L6haNfK5ljCXHv3sumww4UFzmik/8/z8dbWsmHcweRefx373nxLvG5Jsym6736K7rs/6jbOrVsxJCWhWCx4yssZsGghnrIyNh99jH8bS9++ODdvxjpwIA6d9Sv/ww+xDRkcOJhm7dK+p6HPdfS9dRYAm+85FgwGFEVB9Xj8j9sDUoRFQDGZEyrCquobujqz2qAlh6R94fK4MSZvxG4ZhMvjYsr7UwDok96HLRWip6hRCb75P3LYIxzW/TDMRjMer4cLhlzAuYPPbfWx6y1hB1Jmb9WPc/FUVGDMzMC9dy+mzp2p+OQTPNXVGFNCaogpBjzl5RjTheWn6vs5AEKA5ebi3rMHY24OnuISAHq9+w6OdevYe/sdQYcxJCdjTBFFdPt8MwvV4cC1ezcpkydHnNn3eu1VnDt2YMoRFvduTzyOY/16LD17oljFBLDX22+z/Zxzmvwe7PnPf7H26xt4T3yva+eVV+LesxcA995CSn2xPHtuv92/beG992HO6xrx2P9eJfYfsCudgrebVvnftbcQQLjBgJ2XX4G3Xrhsix8XSVcZp59O+Ycfht0/4+yzsPbv36RzHkgYU9PwVFU2sk0qnqoqbAMGYO7RA9fu3cLVmJ5O92efwVtdg6lTJ2wDB1C/di22YcOo+3MFitmMp6Ic+/BhUY8fjfm3TKOq3h30m2hry1coUoRFQDGZ/LETiaAyTAFF2ZJDsqb+HZJ6fsvyyjoOeisQMKoJMICHD3uYMZ3G+AXajF4z/OuMBiM3j7u59QasoyPXo2oJBX8Nbm5uzsvDtXs3AJb8/KB4KccGEaNi7tEDg92OdeBAnDt2kDRuLNmXXUbRffeTdfFF1K1ciW3wEJJGjyZp9OgGIixHd05r794A2AZFb1xvys0NKrljyszENEH0Euz+2KPse/117COG0/vzzyh56mlMXbtgsCdRs2ABGTNPwVVYSLVPcKafeCK1v/9OyrRpKEYjFZ9/jnP7Dv+xLfn5eMrLce8tBEXBmJ6OqUsX8Hpx7dqFwWoj9WjRCsu5ZUvQvqHk1VSJ11lYi7Oi6d8xJSkJS7c8XHv24i4R4lax27H07ImlZ0+63PY/VKcTU24Ozu07yLroQnb9301Y+/Sh8803Y0jqmH032yvmzoEC5KmHB7v0kw85BICUyZPicq7ume3/s1MSGViaCMaOHasuWbIk4efZdeP/Ub96NX1nfxv3Yy/eto/SaidXvbU0aPl7V0xgQp/sCHtJ9nee+eMZnv0zetzWrJmz6JEqAkl/2vkT1a5qjusTPbC5tfhjZzknP/0rANvuax9jag3WDhoccd2gVStRTAHhsOvmv1P55ZcMWLK4oZUsxnP0evstksaMad5gOyD5t4gA/rcvG88kGTcr6YAoirJUVdWwPvcDc+oaA4o5ce7I05/7zf/4xQvG8sovW/ltS2m77m8liT/bKraRY88hxZLCxrKNUQXYpcMu5bLhl5FiCdy441FgNZ7YfK2WRnZv3Vi01qT4iScpffVVcq68gvSZM9lx8SVB6zPPP5/0k07C2jtfZBeagi+xXe++i04339QkAQYwYNFCFJMJT1UV5i5dWvw6OhIZSWbKa12t0tReImltpAiLhFmkysYbrzfY8tgrO4knzxnNO4t2MLJ7RtzPJ2l/eFUv9/1+H++uexeAf43/F++tew+r0YrD4/Bv1ze9L73Te7O5YjPnDD4nSIC1RwZ0SuWG6f05Z3zPth5Kwih55hkAih97nNqly3BuDtRmyzjzTHKuvMIfc2VIbtj43GCxYOjUqcnn1Uo7hDvm/s60QZ35eFlBUL9OiWR/QYqwCCgJyo6scQYfM8VqIifFynXTZPDngcKDix/0CzCAuxfdDcDFQy9mzZpxzNvxG1NGFvLsMXdjM3Wc4r0Gg8IN0we09TDihqqqqLW1/uuAFtytUaMrNJn/8UfYhw5t1fEdKNx9yjAOG5jL0LzIZSwkko6KFGERSER25Jd/7mZbSQ0A10/rT6rN1K6b/0riT6WzkrfWvhV23Y1jb+Sy1UtwVw/lrD4XdCgBtr9QOWsWu278vybtM3jd2gSNRgIi0/aEkXltPQyJJCFIERaBeFvCvF6Va99d7n/eJzeZk0Z1i9vxJe2TJXuX8I/5/+DmcTezpWILqZaGXRF6p/fmpL4nAeDxippIJkP7qGFzIOHavTusAOt86z/9jxW7HUNSkijwabNhHTiwNYcokUj2M6QIi4BiNkEcY8LK64KPdaCm8x9IlNaVcvHsiwG4eX5w2YgzBpzBBxs+4Pdzf8duCtQ+6pubwtz1xeSmysK9rc2u/7upwbIut/2PzLPOaoPRSCSSAwGpBCIRZ0vYvhpH0PNkKcL2OzxeDx7Vg0Ex8ODiB+md3jvitv+e8G9uOfgWzMbgyvJ/P3oQRwzqxAiZpNHqeMrLGyyTAkwikSQSqQQioJjNoKqoHk9cKuyWVjuDnktL2P7B+n3r6ZvRlzfXvMmPO37kj+I/eH7687yz7p0G2w7OGszafWvJsmWhKEoDAQZgMRmYKGshtSq7/3krFZ9+2tbDkEgkByBSCURAMYkbpOpyxUWEfbJsV9BzKcI6PksLl3LRtxcxo9cMvt/+vX/5lXMaNl5+8ognOazHYbyy6hUm5cWnGrSkZbjLyqj744+wAqzrvfdi6dG9DUYlkUgOJKQSiIBWZDEeLslNRdW8v2Rn0DLpjuyYqKrK8qLlDMsZxtpSkRWnF2Aao3JHUe4oZ1vlNgC/8Lpk2CUNtpW0Dbtu+Bu1ixaFXZdxysmtOxiJRHJAklAloCjK0cDjgBF4SVXV+0LW9wReBzJ829yiquqsRI4pVvwiLA7B+d+s3ON//Pz5Y3h9wTYykxq6oiTtm83lmzn585MBGN9lPIoSOYPxb2P+Rr/Mfry26jXW7lsb1vUoaTtUVQ0SYJ1vvZXCe+5pwxFJJJIDkYSJMEVRjMDTwAygAFisKMoXqqqu0W32b+ADVVWfVRRlCDALyE/UmJqCYva9NXGwhFU53FhNBhbdOo2MJAtHDT2w2o50RP7+09/pld6Lq0ddTXl9Oa+seiWomv2ivYEb+KCsQZwx8Azu+O0ODup0EK8d/ZpfoF130HWtPnZJ43hraoKeG1JT6fXWm2w/7/w2GpFEIjkQSaQl7GBgk6qqWwAURXkPOAnQizAV0MogpwO7EziephEnd+Tu8jo+XlpAstVERpIlHiOTtALfbPsGgBP7nsiTy570P++f2Z97Jt/D6V+ezsXDLub60ddjNBipcdXw/bbvuXnczVEtZJL2gaekJOi5ISWZpLFjST/lFJLGjWujUUkkkgONRIqwboA+EKoAGB+yzW3Ad4qiXAskA9MTOJ4m4Q/Mb4EIW1FQzolP/QpAlzRZ/bw9U++ux+V1kWpJZVnhMv/yYz85Nmi7/0z4D4OyBvHb2b8F9XJMNifzwpEvtNp4JS3DXVoa9Nzo68mYd690SUokktajraPDzwZeU1X1YUVRDgHeVBRlmKqqXv1GiqJcAVwB0LNngpsDb/4RvvkHSpbIcFNdzRdhD323wf/Yq6pRtpS0NefOOpcNZRuY3G0yv+z6JWhdkimJWnctw7KHMbrTaIB230xbEp6qH36g+LHHcGzcFLT8QGyMLZFI2p5EirBdQA/d8+6+ZXouBY4GUFX1N0VRbEAOUKTfSFXVF4AXAMaOHZtYNeN2QskGlCwRkN+SwPxUW+DtlSKs/eLxethQJgRzqAD7vzH/x7lDzsWAoS2GJokzpS++hHPb9gbLpQiTSCRtQSLvLIuB/oqi9FYUxQKcBXwRss0OYBqAoiiDARtQnMAxNY5ZtJBRFA8Aqrv5IqysJlCg1e2VIqy9sb1yO9XOaorrxFfu6lFXk5+WH7TNwKyBmA1mjAYjRkPL68VJ2g7n9u3U/fEH2VddiSEtDWNuDoakJECKMIlE0jYkzBKmqqpbUZRrgNmI8hOvqKq6WlGUO4Alqqp+Afwf8KKiKH9DBOlfpKptbDLSRBhChLUkO7K02onNbKDe5cUjRVi7QlVVjv/0ePpl9PPX8BqSPYQp3aZw18K7eG7Gc2yt2MqoTqPadqCSuFHx5VegKGSceirZl18OwM5LLqV2yRIMdnsje0skEkn8SWhMmK/m16yQZf/VPV4DtK/y4SZfAL3qc0d6vVE2jozXq1Ja4yA/O5l1e6vwShHWbli/bz0mg/jqbyrfxKZyER/UOakzA7MG8u7x7wJIAdbBUb1eSp9/Hkt+PtU//0L1/PkkTRiPuUugREz3p56kdvlyjBkZbTdQiURywNLWgfntD58lDK/PDdkMEba7vI6J9/0IwJhemazbW4VHxoS1C9xeN6d9eVqD5WM7jyU/Pb/1ByRJGI5Nmyh+/AkAFKsVU24uWRdeGLSNMSOD1MMPb4vhSSQSiRRhDdDckR5fPFczRNjTcwOZV/07pTJ7daF0R7YT9tbsDXp+Yt8TObb3sUzq1r4MspKW49iw0f845y9XkXPVVW04GolEImmIFGGhmHyWML87smniqd7l4asVgTZFw7qJWrRShLUdO6t2srJ4JQA7qnYAMCx7GDMHzOT0Aae35dAkCcSxTvT27PHiCySNDy1RKJFIJG2PFGGhmEVMmOL1WcLU2C1hRZX1PP7DRirqAhmVQ7qmA3DM8K7xG6MkJv4o+oMlhUuYu2MuK0pWBK179PBH6ZIs20ftr6iqStWcH0gaN46UKVPaejgSiUQSFinCQtEsYc1wR5741K/sraync5qVTqk2Vu6qoFum3dczUjZwbg1Wl65me8V2ju1zLOd/I/oAdkvpFrRNrj2XTkmd2mJ4klbCXVSEc9s2Ms85p62HIpFIJBGRIiwUgwGMVvBZwtRv/w0bk+HCLxvddW9lPQDpdjNvXnowu8rrMBoUOsuWRa2Cqqqc9dVZABzU+SD/8l3VgRrBFoOF7077DoMii6/uz3gqKgAwdZJiWyKRtF/knSgcZhuKlh25dxVsnd+k3b0qZCRZGJqXnoDBSSKxuXyz//GMj2aE3ea7077zl6eQ7F+oXi8lL76Iu6yM4kcfA8CQKttLSSSS9ou8G4XDZAevAxAVZJuKrAkWP0rqSsix5zRYXuuq5fbfbue0Aadx2XeXMShrEGtK1wRtM77reC4ddilP/fEU/TP6s7d2L1m2rNYauqSVqVnwG8UPP0LZ2+/g3iuyYI2pqW08KolEIomMFGHhMNsCMWFN0FPpdjMVdS6um9Y/MeNqpywtXMru6t2c0PeERrdVVRVFUWI67tdbvuaWn2/h3ePepXd6b15Y8QJnDzqbd9a+Q8+0nszaOotZW0Ut4FABBnD/lPvJtmdzSN4hTXtBkg6Jt64WwC/AAAxShEkkknaMFGHhMCehOIQlDDU2wQCiDMUlk3pz8uhujW+8H3HRtxcB8FPBT1w14ir6ZfYLu90bq9/gwSUPsvjcxdhM0ePk9lTv4ZafbwHg7K/P9i//Zus37KnZE2k3AGb0msH3278n257dhFch6fCEaTEmLWESiaQ9I0VYOIxmUH0NvDVLmKpCFAuOy+Ol2uGOaxakV/Xy2+7fmJg3sYH16OeCn9lbu5ftFdu5cOiF5Cbl4vF68KgeLEYLAAt2LeDBJQ8yMGsgZw08i1GdRrG8aDm90nqRZctiZ9VOPtrwEcf2Ppavt37NX0f+lS+3fEnnpM5M7T4VgC0VW1hVsopZW2extnQtrx79KhvKNrC5fDNH9TqK73d87x/T7G2zKaot4qUjX+LpP57m5H4n0zu9t3/922vfBuCdde9wav9TqXBU8MnGT5jcbTIXz74YgAGZA3B6nAzNGRr2PQkVYO8e9y517joumX0JaZY08tPzeWDqA7i9ze/5KemYeKqqGiyTljCJRNKekSIsHIoBlBA/pKsOLElhN693eTj9ud8AyIxBhBXVFjF3x1zOGHhGkLjaUbmD+xffz8x+M7GZbDy27DHW7VvHbYfcxqkDTsXtdXPPonuoc9fx1Zav/Pu9vuZ1zhx4JuWOclaVrOLrU77m223f+i1Jm8o38fWWr5l1yiwu+OYC7CY7s2bO4thPjgXglVWvAFBaV8oXm78AYMUFKyiuK+asr86izl3nP9dJn53kf/zcn881eG3Li5Yz5q0x/uOaDWZemPECw3OH+7d5dOmjfLbpMzxeDzuqdvBTwU/+dRvKNkR970wGExcOuZCXV73M8JzhDMsZBsAXJ39Bz9SeGA1G/3aSAwstI1KPwWptg5FIJBJJbMg7VTgUA4oWDKZpMUdVRBG2bEcZK3eJG8CQvDT/8k83fsorq15hZv+ZfLLxEz4/+XMMioH7f7+f77Z/R5Y9C6vRSt+Mvryw4gW+2PwFbq+b+QXB2ZjfbvuWRXsXsaZ0Ddsrt4cdw/vr3/c/Xly4mOVFyxtsc+ynQnTVueu4fu71QesyrZl+AQYi0/DcWecGCbDm4PK6eGzZY3RL6cbumt3+5VsrtvofbyrfxLG9j+WOSXfwxuo3eGL5E2yr3NbgWC8d+RIjc0diNVoZ22UsI3NH+tfpLW6SAxNPeXlbD0EikUiahBRh4VAMDd2Rzmqgc9jNN+wNuEH0ZSnuXnQ3Do+DR5Y+Aojg8QpHBd9t/w6AG+fdGNNwFu5Z2KThP7j4wUYtSiuKV9DJ3omiuiIA7ph0B9f+eC1H9jqS77Z/x3Vzr6PWLQKdPznxE55a/hSnDTiNJHMS/TL6Mfm9yQCkW9P59/h/c/P8m0kyJXHt6Gu5f/H9AJzS7xQsRgvvr3+fP4v/BCDDmsHLR73MqV+cGjSem8fdjNVo5aJhF/HEctF0+dbxt3LPonsA+OnMn4IyGyd3m9yk90Sy/6O3hOV/+CGeyoaWMYlEImlPSBEWDsWI3wSmBeY7GsabaKzeXQnAvTOHYzMb/cvTLGkU1xX7n+sDzPum92VzRaCuVTR6pvZkd/Vu3GrDOCcFhQ9P+JDcpFzKHeWc/dXZDQTYlSOuxGww88aaNzih7wn+2KxPTvqEuxbexUGdD+KwHoex/PzlmAwmrvnhGr+L8M5Jd9I/sz+PH/F40DHnnzmfK7+/kv9M+A99M/oyOGswfx/3d3/AfZfkLtwx6Q5cXhe7q3fz866fAbjtkNvom94XgIM6HUS2PZsxncf4y1CYDQF37tmDzvaLMFlaQtIY7t0BS6tt2NCYs3AlEomkrZAiLByKAUXxtSvyW8JqIm6+enclh/S3Mjh/H6tLqshLyWNLxRaK64rpmty1QTB5t5RufHzix8zZMYebfroJIOx2Gh+d+BEltSV+d+I9k++hqLaIcwefi9PrJM0iXKBZtiwybZnUVtcG7X/N6GsAuHLklQAYFSMHdzmYdGs6Dx76oH87LY7q3in3cufCO/lm6zcc3OXgsGPKtGXywQkf+J9rj6ud1eKco8Q5zQYzTxzxBPvq9wW1CvrpzJ9ItaQGiS6NN455w/+aJJJYqV8fmHxIASaRSDoCUoSFQzEAPnektszrhuVvgaMaJlwFQGFNIdM/mo6z9ny65Czg/G8aWrb+PeHfpFvTOW/Wef5lqqpiNBg5Kv8oBmUNIsOaQbI5mdFvjg47HLvJTvfU7v7n+npcNoJLPZTUlfgfD8gcwMcnftzgeDePuznqy0+1pPLA1Ae4f8r9Tb6ZpVhSWHnhyqBlJoOpQa/GaJat0Z0C78P3p30vg+wlYSn/+GPcxSU4Nqwn6+JL8JSWkvPXv5A+89TGd5ZIJJJ2gLy7hUNRUAixhKle+Pxq8dgnwtbuWwuAJe9N9kWoiNArrVeDZXtr90Zd7x8GCtN7TfcNKTYx5PA4/I9bWqahPVgTuiR3aeshSNope/71b//jylnfAJA6fTqW7gdWnT6JRNJxkSIsHAYj+EWYT4io3qBNqpxV7Kjc0WDXp6c9zdU/XO1/3i2lGzWugCtzfNfxnDPonLCnfXra02TbsxmSNYQtFVvom9E3aP38M+fj8SUMROLhQx/mlVWvsLp0tayVJTmgsPTqhXXw4LYehkQikcSMFGHhUAxoJjC/O1INrht23qzz2FKxJWjZKf1OYWr3qSw6ZxEldSWUOcowGUykWlKxGW04PA6en/68v5ZVKFqBVKCBAAMRh9UYR+YfyeDswRz7ybFShEn2W7z19Q2W2UaMaBfWW4lEIokVKcLCoRgg1B25YwEApQYDN8++pIEAA/wWryRzEj3NPelJTwAMioGvTvmKVEtqRAEWT/KS8zi297FcMOSChJ9LImlNvHV1lL3zLslTGpYoMWZktP6AJBKJpAVIERYOxeCPCfMbwH5+GIB301JZvHdx2N1SLZFbpHRODl9jLBEYDUbun3p/q51PIkk0XocDFIWiRx6l7M03ydgeXLTY2r8fGaed1kajk0gkkuYhRVg4FH1MWGDxFrOJFzLSOKjTQdw35T7+2Kryl3cW8e4VY9mnrghyJ0okkvix4eDxmHJyUOwiG9ixRWQim7t3x5idRe/334+2u0QikbRLpAgLh75tEYEYk2U2K6qi8N9qD129Kh8V1YBqYWS3riRZerTNWCWSAwDV4cC1a5c/8L5+hSiD0uPZZ1Ds4duJSSQSSXtHirBwKApanTC9JWydxUKqx0uf1V9SlTuO79eOoXumnSSLfBslktZA9QXkq04nmM1Y+vWTwfgSiaTDYmjrAbRL9NmROhG21mJhkNOJAjz4UxErCiro3ymlTYYokRwoqLofobuoyP/YlJUlBZhEIunQSBEWDoOxQbFWN7DeYmaQ0wmA19fGKNXWsO2ORCKJD3UrV7Fu8BD/c29NDZjFb86QJN2QEomkYyP9aOHQlahQfTFh28xmHAYDgx1ChI01rGer2oU+uf3bapQSyX5P2XvvNliWecYZGNPTsB80pg1GJJFIJPFDirBwKAZQg2PC1lrF7Huw0wXAycYFnGxcgOvwv7fFCCWSAwJDmKB7Y2YmuddcHWZriUQi6VhId2Q4FAOKGuyOXGuxYPN6yXe5gjY1G+VbKJEkCoPdHmaZLcyWEolE0vGQCiIcipHQwPylNiuDnC5pOpRIWhFDUkMRptikCJNIJPsHUoSFQzFA5U7xWFXYYTKxxmplRk1t245LIjnQMDWc9oRzUUokEklHRIqwcCiKKBXms4ZttIh4sDH1jrYbk0RyAKL6spH1SHekRCLZX5AiLBxak21FuCOLjOJ5Z4+7DQclkRx4qI6GIky6IyUSyf6CFGHhUHxviwKoUGQyYlJVsjzeNh2WRHIgUP3rrzg2bQIClrBe776DtX8/sYG+grJEIpF0YKQIC4dPhGkeySKjkRyPJ/yb5fW04sAkkv2fnZdexpbjTwBAdTowZmSQNHo0Xe64A0NqKrYhQxo5gkQikXQMZLJfOPyWMBUVhSKTkU7uCGLL4wRDwwwuiUTScrwOB4rVCkDS6NEMXPx7G49IIpFI4oe0hIVDETFgis8dWW4wkuWJIsIkEklcUEPq8KlOl1+ESSQSyf6GFGHhCIkJqzAaSPdGiAfzuMIvl0gkTcZTXR30XHU4UCyyP6tEItk/kSIsHKI+BSBigMsN0USYtIRJJPHCG0aEGSzSEiaRSPZPpAgLhxaYr4AHhTqDgfRImZHuMLXDPC54bASs/SqBg5RI9g+q589n07TpeB0OPJWVQeu8Tod0R0okkv2WRkWYoignKIpyYIk1f50wFadJ1CTK0FnC5nuGs8vWXzwJ546sKYHy7fD1jYkeqUTS4dl79924du3CvWcP3qqAJWzfO+9Q+9tClDBV8yUSiWR/IBZxdSawUVGUBxRFGZToAbULdDFhzlzxktN0IsyDgYXdL/E9CeeO1OoYKWHWIXycobWOZO0jyYGK76uvqiqeygr/4sI77gSgdvHithiVRCKRJJxGRZiqqucBo4HNwGuKovymKMoViqKkJnx0bYWuTpjTJ77SddmRSVYzx4/OF0+aExO24Am4PQPqfa6X5W+L5xW7mj1kiaSjU/bOu+y67vq2HoZEIpG0GjG5GVVVrQQ+At4DugKnAMsURbk2gWNrO3SWMJdPhCXrLFW9slOwanEq7nqY/a9gAaVtq0SwhC15VfyvKRb/V7wv/pesj8foJZIOSdlbb4Vd3mfWrFYeiUQikbQOscSEnagoyqfAPMAMHKyq6jHASOD/Eju8NkIJxIR5fYLK7g2IMKPRCEaLeLJ5Lvz2FHx1Q2B/VXNdRhBhmjjTxJoWgxYpA1MiORCI4JK39undygORSCSS1iGWiNdTgUdVVZ2vX6iqaq2iKJcmZlhtjE8kKQq4fcLIpgYEksWsE2H1vhgW/Q3E21ijb02E+Y6piT5VtkCSSCQSieRAIRZ35G2Av1eIoih2RVHyAVRV/SHajoqiHK0oynpFUTYpinJLhG3OUBRljaIoqxVFeSf2obcOHp9Q0lvCbGYTGH0FJB1V4r/JKspVPDUONs1peKA1X8Bzk4W1S7OEafFkfktYY+JNIpFIJBLJ/kIslrAPgYm65x7fsnHRdlIUxQg8DcwACoDFiqJ8oarqGt02/YF/ApNUVS1TFKVTE8efGPwxXeD1NehO0lm6LCajEF0ATl9KvdECZduhZAPMusm3v84d+fGlQnR5HPgtYR5fjTHNEiabgUsORCJ47SUSiWR/JxZLmElVVX8KoO+xJYb9DgY2qaq6xbfPe8BJIdtcDjytqmqZ79hFsQ070QjBpShQUy/qgNl0IkxRlIA7UhNhJmvAohXYMvBQqyemegOB/27NEmYIrJNIDjRkdRaJRHKAEosIK1YU5UTtiaIoJwElMezXDdipe17gW6ZnADBAUZRfFUVZqCjK0TEcN/H4Y7VUymvrsXq9wW+UYtC5I3WWsOgHFf+87oAIC7WEyZgwyQFEyYsvsnbQYFRnwzIvg9etbYMRSSQSSesSizvyKuBtRVGeQph2dgIXxPH8/YHDgO7AfEVRhquqWq7fSFGUK4ArAHr27BmnU0dBDVjCQMUemrUVyRIW6k6sLIAFT8JEXSUPryfgpnSHxoRJS5jkwKH0+RcA8JSXh13f+7NPMabuv+UIJRKJJJZirZtVVZ0ADAEGq6o6UVXVTTEcexfQQ/e8u2+ZngLgC1VVXaqqbgU2IERZ6BheUFV1rKqqY3Nzc2M4dQvRuwVVbxgRZmiYHWm0gDdMC6Pv/h2SOekhYkyYtIRJDiBUXwFktb7ev8ycl0feww8BYBs0CHO3UOO5RCKR7D/E1JRNUZTjgKGATfFZcVRVvaOR3RYD/RVF6Y0QX2cB54Rs8xlwNvCqoig5CPfkllgHnzgCgfkKalBmpH+F5o6sKxf/DabwfSQhuKq+qreE+USYQQbmSw48VHfDbOB+P0ZNuJZIJJL9iliKtT6H6B95LcKEczrQq7H9VFV1A9cAs4G1wAeqqq5WFOUOXYzZbKBUUZQ1wFzgZlVVS5v1SuKJPztSRVG92EMD5hUDGH3Zka4a8d/rjlxi4uUZgcded8MSFUpIYP5Xf4P5D7XsNUg6Jh9dCgufbetRtA6uCJMWiUQiOUCIxRI2UVXVEYqirFBV9XZFUR4Gvonl4KqqzgJmhSz7r+6xCtzo+2s3uDxuzARiwmyhljBFZwnTWPMF9D08/AH3/Bl4rHdHun1uGE2EaSJuySvi/9SbmvcCJB2XVR+Jvwl/aeuRSCQSiSTBxJIdqQVs1CqKkge4EP0j91te/jngEVXCBeajCBeioitJUbEDPr+m8YOrUQLzI7kzJZL9DDVMi6LMc0KjFSQSiWT/JhYR9qWiKBnAg8AyYBvQ7irbxxNFVydMUcNlR2ruw5AYrqo9jR/c64lcouKbm4MbgUskHQx3aSlrBw2m4suvom6nOhz+x6bOnRm8bi1d/vufRA9PIpFI2hVRRZiiKAbgB1VVy1VV/RgRCzZI71LcH1F0D1RU7KGlI5QWlPjWizB3SEwYQMn65h9bImljnFu3ArDvjTeClquqSslzz+PYvBkAb42IpUw79hjyP/ygdQcpkUgk7YSoIkxVVS+i9ZD23KGqakXCR9XGGNBEl4qqKuHdkc3F6w4E4LtqYd/W4Er7jRZ9lUjaL55qUTcvtACrt6KC4sceo/wDIbg0EZY8dSrmTu2jW5lEIpG0NrG4I39QFOVURWmJ+adjob3QHXSKUKKiBage8PgC8H99DJ4YBYWrA+vd9eH2khwIhImT6mh4SkVyc6gIc/uW16/fAAREmCE5uRVHJ5FIJO2LWETYlYiG3Q5FUSoVRalSFKUyweNqM1werz8mTEVBIUyx1pbgdQdKU2gWsW0/B9ZrdcckBx6RSpy0YzwVFWw940yc27YB4C4RYsu5dSt777zLv5223LFuHQXXXU/l7NkAGDuqCJt7D/x4V+PbSSQSSRRiqZifqqqqQVVVi6qqab7naa0xuLagzuXxizC71YSi0rBOWEvweoOLtzYYQFng8ZovIltHSjfD7j/iNy5J2xPte9FOqfrhR+pXrKDkWVHbzF0aaCtb9vbb/scVn3wCiBZFVd99R+lzzwMJtoRtmB3o7Rpvfrof5j+YmGNLArjqYd2sxreTSDoosRRrnRrurzUG1xbUOT3+mLCsVIsQYfF0R3qc4KqLMoDywOMPzofVn4bf7smD4IVD4zcuSdvTAUVYKJ59ZUHPVacTT3UNFZ9/Hnb7hImwwtXwzhnwzT8Sc3xJ6/Ddv+C9s6FgaVuPRCJJCLEUa71Z99gGHAwsBY5IyIjamFqnxx8T5lVUFMAWT3fka8dGX18XfBOjujB+55a0jN1/COF72Y/QfUz8j+/peO7IUDxVlShmM6qvGr6nsjJseyKNhImwigLxv3pvYo4vaR1KRAwhLx0BN6yCjB7Rt5dIOhixuCNP0P3NAIYBZY3t11GpcwbckV7wWcJCS1QkcAC/vxD8XPaTbD9s/E78X58g98h+YAnzVlVjHzOG1GOOBoT7UQvCTz91ZoPtEybCaveJ/5vmtO/ae4tfgsI1bT2K9ov++rd7eduNQyJJELEE5odSAAyO90DaC3UuNwafCPMoPhHWmllr3pCq+fGMR5O0EE19J+j70AFFmOoO/r56qyoxpqaQceppgE+E+cpWpM6YQfdn/BVvMHXqhIFaEfcTLyoKRByl3qL8wQXxO368+fr/4LlJbT2K9ktQskrHzx6WSEKJJSbsSUVRnvD9PQX8jKicv19S6/Twh9oXAK/J2nIRNu1/YAjpMzn1Zug5MXhZUk74/UOr8oeyH7iwOgx+DZYoEdbx2lZ5a2uDnnuqqjGkpmHMyBDPKyr8ljBjcjKpRxxB+imnANB39rcojwyEt0+Lz2CKN8CjQ2HBk8EiLNTF317QrDxyohUZ/W9Cvk+S/ZBYLGFLEDFgS4HfgH+oqnpeQkfVhtQ6PXzoOZQNZ8zHa0tBAcwtuemabGBJCl6mGBuKq9BtNBq78Lhqmj82SRORlrBQ1LrgJBNvZSXGgnkYHSImq+Dqa6j5/Xcg4Hrsctv/6PfDHAx2u9hJX6KlJWjxkxu+hdpS3aAiiNutP8O754iM5aYQr4mP29H4NvHE6xGvd9uvrXvelqD/7PaDOnoSSSixBOZ/BNSrqlANiqIYFUVJUlW1tpH9OiRDuqZx38wRdMrvwjaEO9LclN++YggWTmYbmJOhXtdowGBsKK5M9sDj7H5Qukk89nrF3/pZkDNAiLdOOm+wswZs6bBxDuRPArOduFK0DgwmyOkX3+N2RLR6xYm6GUQSC/Fm+wLIGQjJ2S0+lGYJ8zqdqB4P3tpaDDWFmL+6AMgCCJSjSEkR/61WDN26xfd9VNWAmKuvFLFg/kFGsCa/exY4q8FRCfaM2M/ljpLd3BQ8rSzC6spg/dew/Ve4ZXvrnru5BH12UoRJ9j9iqpgP6O/sdmBOhG07PD2ykjjr4J5kJFlQfTFhxkg//v5HNWwzFOp6DGsJMwQuLrYM3346PZzSJfBY9cCf78D758LT4+CZCcHHctbC3lXw9qnw7S0xvcYm8cx4eCoBmYAdkkRbwlpBhHlc8Oox8ObJcTmct7bO97/WH/tltHhR1IZxXg2C8OOZdPLH26J2F0DxOijXiYxIRXC18zfVIuWM0/zT3cqWT83S2pHc3vrPTlrCJPshsYgwm6qq/oqHvscRfGf7F15F3HaNkX77534A/ykOXmYMI8LMIW+XQeeOTPbFghl0H0WqToR5PbBvS/D+t6UHHjuroc6XCVayKdJLCew3777o2ySa1hjDN/8Q57ktHZa+Hr/jJtoSpndH3pYOlbvjf44aXzHVvSvicjjNElbz03y2niKyHw1mb9B/DcOjfeDXxwML4ul+/fM93aBCREYk0aH9Bl1NEFW7lsLDA5o2tki0tiVMq08Yy/v+yFD49p+JHU8seNqxO/LFI+C149t6FJIOTiwirEZRlIO0J4qijAHiZI9v36ioKCqYmmL5CCfCLCEWAMUYmIXbswLLNPQibP4DULIx8vlctYFjGaJ8nNoFbN69kbdJNNo4Ez2GRc8FHn95HZTFy/XSyjFhieiIUFMk/ivNSYxuiFcXE+baLUSjJVV8zr2PCp6gKEbg+//qdtbdYFsaZxWt3ZfemlK8AWb/Cxa9EPg+NkWExVPUt3ZMmNaXVnvfSzfDoudh31ZY8FTgGvHb01BZAAufad3xhUNvLW1vgfm7lsYvnrEj46oXE+t4ZjkfQMQSE3YD8KGiKLsRd6EuwJmJHFR7QVUUIcIau+cefV/AFWiyE1RGzWSNYAnzXVA0gWbQibCc/sHbr/0i8rlLN4E9UzyuKRHxYwYDVBdBUnbguI21SjLZWh5P5qoTf163yPYMFYXROgW0lKq9kNI5YK3S8+5Z8NffWn6ORPewDxUicRJKQVT7hJEhlp9+dFSvl/qVK8XhkpP9WZDWdHGTt6R4MNk9uOuMmJPdgbdP+47qX29dGaTktmQwkdfpRdiLhwvrsZ6y7dB5aOT968rF5MoSEtupUbkbUrs2/fvR2iJMf5P0uOC146BqD/xwJzirYPhp4nc0+9bw+9dXiO9N6KQykcgSFe2f358XE2uTFSb/ra1H0xBnrbj/NSXusxWJpVjrYmAQ8BfgKmCwqqoHRA8JzRLWMCYs5GI74S8wQBSnJCkreJ3Z3lDcKEbo7ev8lNYtsEwjNa/hYIadBiPPbrj8i2vhx7vF46I18Msj4qbxUP9gq0M0EXZ/PrzaSCX/WHjlaHigtzj3j3c0XJ8oEVa2DR4eGOzq0hPvEgWt4Y6ExIgwzRIWGrvYDBwbN+LatYuu99zDwKVLMGaKyYDREnh/3HXie91tou4z0DJ69a+3pZ9RrCIsVICBaIsT7fwPDxJ/IESKnjVfwCODYdMPsY9Vo9XdkTqL38eXCgEGQoCBqLH2xonB++i/6/f1hCdbOT40KDuynVnCJAKn7/fcXi1hLx4O9/dq61FEJJY6YVcDyaqqrlJVdRWQoijKXxM/tLZHiwlr1BIGAcuCZpXSMFkbzhwNRjjyLrh2GWTmi2WqF25cC//Y1tClqR033HKA4rWBx9t+CcSIrf0ysLyxYNzdYUq//fJo9H1AzI7fO1fEo+35I7B81SeBx6oKn/4FNs4Wz0OTGVqKdgNd+WH49XGw+gABUdRaIiyae7m5VPtEmLHl74lnn/ieWXp0B6Dvt9/Q75HLwm5rTdcJIYfvpq+/wW77WRRVjSVY/bdnhMtMY+lrwb+BBgONIRC9aJ2IJXxogBAbz06G108Q3293ncigrC4KCBeN+Q+I//qSGLHS2oH5bt1Nck2YXp4vTROvd9R5cJCvwO0dWeJ90D6zqj3i/W4t2nNMmESgfS6J9hQ0FUc1vHmKSNRpx8RyJb5cVVX/FU9V1TJFUS4H2kHAQGLxW8Ji+fFrwsKeKXoLvuRrrWmyN3RHKgYhqLL7CpEGYrae5rOAacv0JGXFdqG3Zwayt/RiJ5IlTG+d8rjEzbDvEaIB8pzbAutUVaT995se/GP79XFY9xXkDmx43JoSn6tniMjw/PMdsS4OVpggNHEUqc9m3CxKvte96Xvw3iVE0qY50PuwuIiaBmKhqfWrYkGbtTZTADi2bgXA2rs3nkpxYzakpgJgTE/HmBp8Ie41vZi6EgsG/UzG4bNG6V/v1zeK/5Ouh26NWFtm+wLGD7la/P/y+kZG7Tv3tl8ib1KwODiWMM0LW+cHW5N3LYWaYpG9nNJJJDeU7RDrmvP5+y1hrXTzitUSPfpc4V5d9oaYHG6dDzt/D6z/8noYcxEUr4eitcHXpbzR0O2gBocMy7ZfhGUxnItXo7488Fj1CrFstgUmr+Eo3yFEY+ehwlW8d5X4vPJGxTYuSdPQLJSJsNy3hI2zYfOPged7VkDXEW03ngjEcuUwKoqiqKpQIoqiGIE4mzLaJ15fiQpTRg/Y10hwt16EdR8jnnuckS1hGnoR5j9WGBFmzwzMRqNhzxSzdgi2nEUSYfqA5h9uF9XGL5kNrxwVvN2KD+DTK+DYh+DgywPLdywS//VlNUDMul+eITI7bw7J7oxk0WsumqCoKQ6/Xv9+twTtYlOyAZa8LGL33joVDr0FDo9DJlmoeyoR7irtmO468b6ZmvZT3nKMcFsPXrcWb7VPhKWkBjZw1QIKDDkJ1nxGUo6LpJwQcam5v8JZqGL5jjeHmhIRAxWJ318Mfn7uByKWUG/12blIvL5D/yF+t9+uCFjzmpNYoH1vW+vm5Y7BXWRJgc7DwJYGp70KH10slocGoKsqPH1ww/2TO8GNaxq3PlfsjP55hMPrFiVzAG6LItweGx7Y5smxwv1tz4S/b42PtUZa5ELQ3o92ZgkL/ZyenxL9e9NGxCLCvgXeVxTled/zK4FvEjek9oM/O/Ivv8HiV+C7f0fe2KQTYRC4wZjtYE0L3lZ/gdJEmP6GFO7GaM9q6AoJx4r3hUAAESO26AUYf0XDG96f78GnV8JluliWIp/Zdt1XDY9bsVP8DzXtaoIvNMPMVRsoraGfzUL8RZheYD4SJsBaiZMI07vPyrYFPut4mbtDLRWJCNzWfw/u8gXC/7sovPU1hB2XXBJ8KJ8lzJimE2HOGnEjP/01uD0j/IH8lrAwE4NoVpFwxCp+CldFX1/hs2hds0RYWYxmYdF+epz4rCHgnk/pFLAoau9ncwrtaoK4tdw40SxhF80SFizVG5g0DpsJg0+AR4fBhu+Ct3/3rMDjqX+HcZcJq8NnV8GdEVqwReLyHyGte8PlpRuDhVqkem/R0OIP68pEzFtqF3hkiPi+15TAv/dG3z8cH18W3p3b3nHWwD15cMoLMDKOuXV+S1g7E2HxrEOYQGIRYf8ArkAE5QOsQGRI7vf464TFchPvPEz8r9zlW+BT4SabMN1n9YZPfBYk/fEsoop40AUykiUsFjdeaODxNzcL8323sYFlf7wDn/1FPC5eH1i+6XvxvyqMW0+brWs3Hw3NcqHFGmnoL5ihbsJ4uyP1FqPKgjAb6GZEZduEC3Fc+NilsGycAzt+E5YQPZqYbM7NIRyhQjYRbYzCCp/KmDITaxYEMkxVpxNvlc8Spi/C6qwRxYn1F+QTHg92GTqqhIXJFJKwAjD73zD4xNgu6PMfEha3WNgbIsIUI5z6InwULCzJ6huIxTNZhFtOE2EaluSG4qs5n5UmshUDVO4RWdDjr2z6cWIlmgjL7BU+O9poFiEIf7wVvHzjd9BpqLi2jblQiJoRZ4gJV6xC2mQVgjeS+zk0vjZSbN/W+bB5LvSaCP1nBJZvmRe8XeEqYRWv0V2rXHVNzwpf/WnjPX1joWQT7FgQiL9LNNo1+vv/xlmEtdOYsA6SyNGoCFNV1asoyiKgL3AGkAN8nOiBtQe8WkxYLO6skWeJwPCDrwhebrKKeK5Buhmd/nhaxXynzg0TzhKW2qX5Ae1fXCtmmxqaAINAeyQ94dqyaD+w0BuSVvyzaHXk84dmlMXdEtaIFaKuHPauhNzB8O7ZwkI4dKZ47+v2BQrm6qkuEhYPEN0IQlGUgDCNVwXyBpawBGQbhRMLzWjD4yosxFNdhSElBcWo+z6768XEA+D4x4SwGHNRsAjbuyJQ3T6Uih3C6prRs/FB/HinaMETC/qkEY0hJwMhIiw0GUKzWo+7XMRI2TOg5yHBbZGgee5I/2ehCMvSnj/EdSI9jFUoHkT6nLuPE2IzEiPOaCjCVC+c8XpwOR2DUWSKxwuTBToPh0JRBiWiq/r1E8T/Xx4Jdje9ESLQdy1r6JWoKxMxtLb04Lg+rzfytSG9m4g703DWNK9sx7MTxQRy9PmtI2A00a8lbsWL9ip22uu4QogYjKAoygBFUf6nKMo64ElgB4CqqoerqvpUaw2wLVEVVWRHKiaC/N3hfjC2dLhsDvQIiZPQbkh6F6Q+BsTmuyjoLUzhLGG5A6OLl6k3RxdptRFS8H95pOGy+sqGy7Tx7fgNNvosZq66gHgsWBL53KGWsLjHhEVw26V2Fe9LbQk8N1kUn9QyKSt2wpz/wYN9G87cf31ClNkIFZx6VDWQkh0vi1WolTER2XPhBGMMAdteZ/BYHBs34a2s8gflBx1f+3zHXgznf9rwYJEEmEZTXnfp5ti2C5c5q02GNCtxOIuMtk33sfCfIrhpgxDnodbcZlnCfN8fxaCbqCTwZhyuhIBiENetaBPN/Cnif3InmH6beJwzoGE9w0Rw1tuBxzVFkbeLhfkPwGshpXhqSuDBPvDRRcHLf3lYXBsqw4SAhCbM3NujeePRLPiJsHiHw+9CT9D52pv7Lx7WylYgWkToOuAI4HhVVSerqvok0DFeVRwoqSthXfkGFBWUUNHVlMBM7eKmd0EGWcJ8LYj0P4xwYspkjSyyzvkQDvtndDdfpKD1cNSGmSnNfzDwuMhXDkDvggxXf0kj1BKmjXPObQFB1xIiXVSsqSLb7uz3RczJriWBGeu7Z8OCJ8RjzZqn8f1/fOOOkG2pobkPt8yFnx6Ap8fDj3c17zUUb4DfQuY2iQjMDydYv7wB1oaJA9QPpTQ4M7fym2/wVFdh9DXl9uN1t9zdHM0yF2pxCv3smsp1y+GCz8X/8z9ruF6bPIVmOIdmQzYnJkwfmK991olo4r7+W+GCCve+xnItMxjghpWi4LEWPtFpcHzHGPHcuvd58UuBx1rCxOKXg7d/79ymHV+L51z7pfgdbJojXNfa7zhcxnWohbqlN/vP/tI6wf7RrtEtQQvHaO3iw43R0S1hwExgDzBXUZQXFUWZRrtLf0gcL618CRUwNPe3cdmPMO1/ged64aUXZKHmcQh2R57yApzqu9BEEmHdDhLH124MmvVNT20TblaNlcKw+i7EocIu3HmhYbyYZin55VF4+7TYxxWJaCLMmgoDj4Zuo0UwrXbj88fuARtmC1fTulnBs9xomXpbfgq2XM29W1zQ5z/YPNfU52FK7yXEEhbmmDsWiAbxUahZGBwPV792Da4dOzHlhbixvO7wmXGX/QjT/gsT/go9xkcfY7SLeYMEkJrw28VKVh/xfc7qE7BK69FeS6ilqIElzAUVu4JjLBtDE16umoCFNhGf+btnilIyW+eHWRnjBS6jp3DNaeNMb6b1p6lEstBp7m2ttImGPqlo6s2Bx+MjuEn1WbFLX4VPrgj+LeiFS/F6Edwf7vtZvF4Iqc1zo1uEqgpFUpTe+r7q48T0iQ2lKe25moImSlu7+HBjhPscElH2p4VEFGGqqn6mqupZiGr5cxHtizopivKsoihHttL42hRVIfw1Khb/ffcxMEV3gdDvE2QJC3Ph17sjR54p2olA5FpEWmabdmPoO63hNk2yhDUiwiIF43cZHnh8yguBx9WhMWGW+P4YIt209QK35yHif8WOhtvN/qeIm3vvbHFB1AjN6tRTuDJQqDOUcHF2jRFOuCSkREUUS0to8LqOfa8HeibaR47EuX0Hji1bsA0cFLyh1x3+xtl9DEz5Pzj6Xrj0u+AJihYXqRHNPRpLras+h4Vfrg8DOCTGetPa5xKafBHqUve44NEh4cs2RCJcT9NE3sh2L2/5MbTf0dBTWn6sWIiWFBVNsI67PHA9GnC0sIiHo+D34Odp3aBGd/3Td1J4+mB4dGj4z+jpg2HDt/DmyfD7Cw3Xa/x0v8hK/+Od4OWFUWJq44V+0hjP66/m5m7t4sONEc4SlghLcwuJpW1Rjaqq76iqegLQHViOyJjc71GVFljCoqG/sIS6OSByzFQkS1ho3Jk+20dzsejdNuFEmh79Reb4R+HKkBm0FjOmmerTfUHUXUcGtkntHHisufVu2ijaNane2GZlu5bBbenCzffRpYHlX90olt+WDq8cA1/dEH5/qy5eacJfoX9I7bPTXg1+bLIFCoGCKL8R7WIVqdVNuCDwxgj3mcfLvD//IXjQF7/jcUauS/XcJJh7L7x4hGhyDRTc8DfWjx2Ha88eksaPZ9DKFaQeczS4XOB2Yx0wIPgYXndsMX8puu+H1tNNy4ZzO0QhT+0z1tpyvXMmvH9e48c+71P4b5jPxu5rKdZlBMy4s/HjQKCtmDm01l+IaG5qnI2qhi9zkOj4oNB402hFT8PRewr8p0TEyLUG0WLVnp8SeZ3ZFsi+9bggrasoxaJxy87g7f9vA/SbIX7z+iSpcL/xSJ+RVrbj21vgrQgWfu2aGRqiES2xKV7oRVi82vgUrw8U4f79ebirS9TJXKsSzsUbrySqONKkMs+qqpYBL/j+9msUFGEJSwRBrskwJ4lkaYsUa6PdELSbn0Un7LQssz90Aa69DoHNMfa6UwyBOBAQF/H6ClGkVZvN2TOEhUmf0ZaUHXisWcLsmeJmVlcWXoTVlcHyt2DC1SIORYv7KF4n/sZcJKxTS14J7LNjQeSx6y1hiiLS/zfOFsL3+MeCLSZDThJxIas/EWLMXS9cDz/dF/n4Ghd8IWqiOWtg3n0w6+/Qa5Ko2ZaUBWMvafwY4T7bBU/A9NsDGXtb5vn6jka5+YTjR53g8LjE+xJq5cvqC/s2B17vrqWQ0omqb7/1b2Lq3AnFbMacF+htai6cC/NWipuyq14cP5Y2UVrmKQQsYfYs8R1w18NcXWzdpjkilm/Dt4TFZA+Od4rU7smSDMc9DD0nxJ6NNuN26DIM+oVMXEIFclPLlLjrw4cINMWa4KoTVf7HXyWyf+srof90sa5gqSjXkt0veB+DKTDJOvOtxrsThCPeiTXRiCbCotXnMycFPAea9cNkFbF/hWuEB+KIfwdiv1I7i84eWpkejXDxsbGw6XsR57n2C1HfUTGI91qbDO8Kab+sT4Za+ZGo9h/vuDu9CHNUCpHS0qzM0Jhed52YQLnqxG+5/wxY+CyMOqf1G2iHs3q1VhJEE4hTU739kxbFhEUj1BLR+9BAQ++o+0X4wWjL9UHExz0i4pxCXT0gZvfJnRrPNrJnCuuR3qybnCt+wK/4PNK2dFHyAaDTkMB2euFWWyoq6hvN4sLocYcPEv3qRiGCsvqIVP1Qt+jrxwcedxsj2lBEMy/rLWEg3ufu42DidTDkxOCYAYNRdALYvkAUt517D/z8cORj6+lzqPjT+O5fog+i1o+z+8Eim8xVK8ZUXyE+M0uKeE9UNXL82fZfA6JLS7n/116xjyWMFTUaHpe4AdvCiLBwN9bv/wsEBJfBCBSuxpwU+FEYVr4KO3UCpOfE2ERYsq4uWaglrLpQ3Cg1di8L39tUY9BxsOqjxs+pemHoyY1vp8dsD1/HKbQ1j/7i7vUGhKDHJT5bgzGQhAPhM5BDj9MYc26HRc+KpJNPfHXvbt0txKbWNi0UTdQYzKIQa3sn1B05dKa4RujJ7A1lW4OXmaziGpHSRSQtaWT1EX8Ak/9PxMkddKF43nsq/PGu+G5akoWrMpZYvW5jRdJPKJ9cHtkqHtqBQP+5f+yz+se7unto/KQmxFoijvSTKY3CVfCtz1l20dfCu7BrKZz2csNtE0m431JNibjWhd4b2pB21uypfREUExYkgFo4ewid3V34BUy9qfH9GpttazdSsx3GXQpX/hQ+5sxkgyvmNX6+f2wTZny9ezMpM7jVUXKumLWBsCxpla/1NxwI3PwMZiGcnDpLmGY2Ltkg/r93jnBBhavcr3HsgyK1Phqhr91oEvsMOdE3Ft/nkNlb/O81EW5aL2KXwiVMxMLEa4RVTS8anpskqtPf30sEEj/QG+7Ph6/+Jtb/eFfD2BSNcK7Dpw6GRwY1XN4YrjpxYQr32voc3mBRqDVfWf0uPDsR46dn+5cZzSEbuWqbYQnzfVc06+m6r4VYvPR7GHFWw31DyZ8Ufnlo8HivCNs1h9QuMPyMwHN9oLX+ZvfFdeLzvi+k7lmkgqZNEWFrvxD/9Yk89+SJBIFI9D8y+H97J/RamTcKbg0pG6GfwGrfJbdDPL5pvfhdhz22AS78MhBz22863LwR/roALvteCDjNWumIIJpBWNBC6TK8aWEJmpss1v6ezSG0BM5bp4prUksyM0PH2/OQwKRcvz5S6EYi0QtnzQ3/9Di4N0F1+JqJFGFRCLKEBX1RW2gei+UmFY5GXR4+caiPXwln4TDbm1YlWt/SxpYR/COzpIgYnOv+EOf6yy9w7TLhhvtLoMI6uYMC4yndBBt0na80q5jeOhAp6F0/jtxB0fvuxTLbuXZZeEHakir4xz0KZ7wJV4UpJKrvRbj8TXhpBvz8UORj7dssqrrrb9oVO8TzpgbXuuoC7shQZtwBZ79H0YpUqgpEjKHqDp5sGIwq5I3GaA2c12AOGUPFzqZbwjTXXhdf1wktsSF3UMOq6QCDjg9+PvhEuOKnhttd9bNwP/1lgfiMT3i88XE1Bf3vQi98HDor78oPwi+PdFOPJsKqi0RspGY11SzFoTfC0EQYPSc9DX9dCKe+FHmb9kTod8mcFGwBHn2e+FyvmAeXzxUTKIhPD9I0naCN1gUgXFzveF+DmWGniWvM5XNh4rXB2/SaHHisWfT1YuXTq8LXdmsOHleg7ZZGwWLx/8OLYMfC5h03NKwkp39IIVvfd74tqunrY5tDvQbRWhC2MlKERUBREhgT1txeho0Vw9N+yI0JLLM9fK9ALfMJ4ExdDJm+9IQ9M9BHEoTZPjlbtGXS1mf3FY/1M0TN8qG9dn09rZ2/i0DVUPdo15HCvRUOW7oIvs2OUjBywDGR12lk9w1vjj/sFuFGDEf/o8TN7Iw3RGxZKMnZwtrWZZiIF9PTd5qoAt55OPQ9wvf+6axCoa9n7j0iYzNcoO/Wn2DVJyLLrmRjYHl1caCWm37ysOM3EeMSTpyaLDiTR1C6JpWCX7Kg7zTq9gULeMWoQv5kDDrrlyHUElZbGlvMkH4b7Uantf4q3yG+c9bUYBGWP0VYGU9+JvhY9ixhIQnFnilcT52HQt5o8X2JJ/rfkL7kyb7NgVIV+mQV7XdTXyFKGYBIfNETLRnjp/uF2/XP90SJFK00gP6zh4bNyDXSe4r3oNPgpruy24rQa2Wo4Ol/lLjB540WLmJtghHNchUrGT1EDcCqwoYiTB9uYTDBzJfgxCcDy4aeIgTiEf8W15huB4mM4HGXB7YZNjPwWBPfehH257sw757G6xXGQrS+w2s+g1eO8sX5vitiT111IjRDj8cN20ImlqFhJek9gzPxt2pu17YQYboJTej3ZsGTtBekCIuAqqrB2ZGJdEfGPKhGRJhWnypUhIXWyDHZw9f0OuSawOPBOmuDfryhMQCxWtQ0oREuvfutmfDwwOAiiD3Gi6zMS74RzYVD0S62+ZMbrgMYeCzk9Au/LhYOuTp8tXd7Fpz7gbjADjlJVIWPRp9DRYNjEO6O8z8R1sK//CKOf8FncM3iwPb9fIHVQ30XaO09CeeufPNk+OhieHwEPKXLVntpGjwzQQgw/UX9wwuFlSTUTTtMtGWqWSAusOaePeH8T9gxN7hli8GowpCTg34KStcRDccV6/f7YF+fxBGni/89J/hWqOL7oiiBC+mUm+Cir4TwDXV1RwrETzR6K41ehL12XKBURV1ZIHu43CfCXjs+kHjQ85Dg4PholjBNUK/7Ct44MbA81JL657vh9++IVR5DP1vteqNZkUITD7TvUL8ZtBjtmvXWzMZF2IjTRexgl+Ei5MKSLCZq2uQUxMTjON1npe84oLkjQxMBfn1cZCu3FC38Y9INkbd540TRgP2Nk+DNU+DVY4JLZ8y7V3QcKNAlFTh94QfpPYV3IiMkBGCJLw4smsciUbijiDBoNzXDZGB+BBweByb9RSv0wt8SmmsJs/gsGEnZwuJw0IUi20tDyxALtXQc5bOmaJYmsy38jTKcdSyU5BARFqlAayhag2hnbfTtLvtBBPjrLSX5k0Qw+qLnRashCMTBHPNA4IcOIgC+ZEPs44pGuH5wzWnNMeQk4V6N5KbTf7e0i5VmnWtKLMW9PcRNvdxXf+r2jMB3Ro92QUrKhhvX+cflLhYzWGNaGmqYC5Ry7N0NSxNcPtdngVVE7JOrNvaK+cfcL7IPTTYhyExWcRzUwPdFe89yB8Z2zNZE/zsOJ57mPySyZoecJFzI75wuSqHsXRHYxppGkDqKGhPmE2HxsIx0VLTv7vmfCGEUOinsNBj+VRgfq6d2DSpeB9+EVGXK6Blw++qvVZfPo9FwlaQcEWuWoSsTsfpTUcdNX2BWo7JAXAe++pvIPOwyXFjMjw0TsjHrZl8CUDoUr4XTXoHHRwXqpIXrhanhrhcu0wVPCas5iP6Wf98qwku0ZALtdX90ibiv2NKF2x81QkFgxITqx7tEMevOw+AvMfZ8bQn6CX84Y4GzOnzMdCsjRVgEHB4HSXpL2MizRTr43pUtP3gsM/eLZjV0GQw/TdSw8bhF9omiBF8AtPiBUBFmMIgg/Ud8Kc/hZgUgjnXB58HlJULRbo5NRRNv0eqD5U8RVoFw8QNmuwiGDkVfwPbEJ32lJr6CgTG4Ihsj3DiaEyvWZRic/Fzk0hKKAud8IGo2LX9TLAvNak3pIi5+o8+DEWeKFitlW4Vo08bkqBQlOPToax5pGC0iZq3ryKCgbneJCEL21tU1aFMEYEgOI+iMpsBn0GmwyIKKNeZRUQIXR+2mabKJyYRWR2zS9eI7NyzEHXvpHBHTonf3XfVr0zpDtJTGLH5aaRC9FeCjEMupLT3Ywh1LbTh9OECT6IimsBC074vJGj4zD+Lndp56s+g32+dwXzkMXabWof8Q2Y91+4K/75EKauu57HthYdJP8jxOMXkMLeLa53DhEv39RSHUADb/KP5Ub0PXf2ih2L0rRSb0D7eL5/p4UEtqw+tDn8Og01Dxest3iEzUz/4qLHpa/a9vbxGJHVpha3Ny4HX3OUwIQEeI5XDDt4ESM4WrRHJXoktW6GuChZtQSxHWvnF6nKiAookwg1HUe9Iy2lpCLJawcBlfBiOMuywQ3B1aEVhzXelN5RppeYGyFJqVKK27mGVp+3Qd1fgPI9QS1ljA5fGPiToxmqCMJsLOeCP68SJZIyddD3v+DJQSGN3E/nFNobkVl0edHX39gJBCsiar+J6oHiG8QNRQ6zZGZIMNmyliL1K6RK5lNuFqWPh0w+VGSyBDVIenRAgvb1UVrt2BNiqW3r1xbt2KYvPdAA+6kIzNq/Dmjg4+QFbfpomwcGjWXK2MgCVJfOdD6TFO/OnRAvtbi5jdrlcEbqB68g4SNwf979hRKRJUzHbxPpZvFyVl3I5AgU8tDidcaYZotEVwdNxJRM2gCCRlQY8JwqLirhd1Cpe+KtZZU0Xnh2cmwPDTm3ZcrUyGPlFDY8tcIdrzRovJVtdRYtncuxtuu/hFYXWOFhKiL/WinduWIYTZSU+KoHw96T0DIRGqKrbb/qv40yYT5TuEOA2HwQiTr4cf7gh4bMKxdT70PTyxpSL0E5pwhodw738bIEVYBOo99aiKToTFk+bGhPnxXUxDRZgmEKxhRBgELCbaj/avv8F9Ph/+rVHS2vXoK53rxxKJsRcHx01FSsG+YZW46EVDy6jTSkpozLgj+n7xJDQGJd5ocT8GY8BCMuw0cTNe/hak+no1HqHL7pl6E9wZ4maYdH0UERbeXej2Wb88VVW49gqXV+/PPqXowYdwbt2KweZzV5/4BF0barjA9yoWa0AktAv38NMa37atCY1zyRkoJgpa/N7o8+Gkp8TjrqOCSxac+5EoZAnBv+Mf7hB//abD2EtFK61R5wqLht6NmT9FxMjdFjIxGXaaiBkLbTK9vxDOvZ5IzDYRQuGqF99ve5awftnSREzXfxtp8RaNSCET2f3h8h/F431bGq4r3SjKo6z8QGS56mvfbf8NXj068PzbEDeqPRNu0bXLWvgs7FwkkoQ2/wjpuvINitIwLlb7vn3/38CyqpC+l5rgsaQEi7BR5waKhn9wvvj/76LYwmCaQ7TsSAjvJWgDpAiLgNPjTJwIa25MmH9/38U/Un2XiBcq7Qbv+9ib8+XXB5NC02fXobVqNKLFKmjkHSTcdokWQnquXyFM+as+FvFWpzyX2PNpN2R9XFXvqeIz7zREFJsNRS+qhp0mMujqykUV8ItmiaDxT3RZWRHaX2nuSLWuDk+lcCcYUlIwJAlxpbobiYcLbZ/VHC78UpRiyBvd+LZtTejrtKYKa+6uJeJm12NCYN0Fn4kb17I3xHN91me4AOFNcwLZontXNAyDCLWc9pokrBVGs5jQVO+F5yIkrXRULp0jepC2Jia7yBYE8f2+9DuRjayV3GkJRpMon/LJFcJFp6HVXYSGnoej7xOT7O4Hi8mtPqMdRDeUUefBH2+FP2eo1ey8j4VlKzMfSjc3njV77TJRoiha+zDN9WfPDMSnQvDr0nj5yIDnRlFEQe1t88Vk/+TnWjah099rwlnCvrxeLB93eSA5qA2QIiyEvTV7WVa4jAW7F9BbSVAURUstYdr+4RqUQmQT7wVfiFY6mlsvUi/KaDRwVzbxHYrkjowly9JgaHjzSTSZvQLWp4HHNr3XXlPRAv8NJjj6fmEZ0j7vHjE0hz7pafFeTrxOPM+fFFy3p8/hAQuMDufOnbh27MCUm4u7uBiPT5AZrFYMSeIC5q1rpJBkaCP55tB5aPiLdXskdDJlSRbFjdPCVKK3Z4qMvXAiLNLveIuvjEW4ONTQGLnTXhUWtGn/FTF0YWM3O7g7MtT93Bror0vmJDEJDZ2ItoTOQxteh/XFZfVejSEni2xwLeYtUhHaYx8Q19mKncIiWlMSKFERKkasqYHfW7hM51Cy+4q/tG5ictf3iIbu2GGnibpjU/4PntR1lsgZEPjffZzoDawPndm7UgT/Kwbxm8juL87Ve6qI/yvZKM7pcQlLsd4A4PWKmDPt/mKyBRcVD7q/+GL7tN/VhL82/roTiBRhIawuXc0/fhYmXBUwK2HeopbGVrQ0XVcLRtZ896FEckd2HRH8Q2vK67ClByxvmflQtq3pxwAYeZZIu+6ItEZMjd8SZoIJV8W+n9Y6xWwLuMA0TLoL0AWfhd29eu48ADLOOpOSJ5/yZ0oqdjsp06dT8fkXWAc0cvPRLnQtdrd3EEJfZ7jgXz369P1YRNieP8MvT+ksxJ6e1M5wchjXs579IiaslQkSYXGuM6ehhYlo/VuHnBwyhiSR9HLG67Edz5IMp78aeL5xDrx9qm9dnOrDTfsvfHqlsMyFZi5bkgK1/DoNCRT37uK794w+L5CtqeeXR2HObaI80IoPRI00EO21znwruAzPRV8Hlyda91XAxRkOfeP6sRcH+g/bM2HA0eH3aSWkCAthQtcJfHHyF+yp2UPu7u9wL/2k8Z2aSktvUp2HBnrEhSNS9mNLuGlT4PHVi2Hlh/D5X2ny7HrabXDoLXBP10Y3PSDxi7Amfkcu+TZy+QztRqLVqwpD/bp1GLOzsQ0SbhZNhBmsVtJmzCBl6RIMyY2IDM0SFklU7G80WYTpShLos1+jvV95B4kWWIf/S1g3VU/T3b3HPwZf3dC0fSQC/Xsdj7I34dB+t1NvEoIj1JPx9y0tc/HrxX+87g0jzxKegcayC6/4SbRsAzFR+OeuyL+TidcLAZrRU1jRakpEUdVlrzeMfXzzlGBh5a4XSUoXfil+I89OCs461iYg2f1FZuuSV4Q176pfEieuY0SKsBCSzcn0Tu9N7/TeFNl+pzQRBd1aGhMG0S/4iZjx6vvTmSyBOKSmnstgEDOl018XYlI/u5EEbshNfV+N5siV6q0pcNIzIhspAo7167ENHIghRdwA3MUlYDSimMUxGxVgELC4taTlU0ci9MbYmAhLyoJjHhRiVV+mJlSE9Zsu3DWWFJHp++d7Im4lXHzMpd83XtbC32xcWsKajL7MQVNavTUFLaHKkhw+lKSl59WHUMTSzSJWYinvYLKI0jFaMeNIXhoQvwl95xV7pmi+bs8IeE/6HA5jLoSdixvu3+8IyNW5PIvX6sbhE1r2DFHq6ITHhYhsLBmsFZAiLBoGJTj4vSWNTgG/L7ols5poHHpL+FT4aOQOErOvppLvq3k1vgkuMz36jJ72jva5t/jzj+VcmgiLs0svTNkOVVVRXS4MFguuggLsI0dgTNNEWDEGaxMTNzShfqCIsEHHiR50A44RvVBjsTKMv6LhstBOGEfeDZ10gd8TQjpe6IkWJ3jEf0ScTHZ/EXc07b+Rt5WEJ6j1TYJEmCb0zDFMdJpDorIPY6XLsOaXj0nrKrLf+x4BX/8fnP6aEFJDT4m+X+7AYBHWa6IQcof6skXHXNS88SQA2bYoCoqixLe1gea+SFTMzOH/hGvCtLeJxtWLgssdxEpaV7itIrZg8cZICVOE9UBFuyG3QpuP4scfZ/2IkXhra/HW1mJITsaQGhBhir2JNx0tIP9AEWFZfcRvQGuV01yRrgnvrqPE/3BNy5vD1JvgsjnC8vyf4o418Wkv6EWYKVGWMN9vPlEiDxITotKa9DkMrl0ae4HX0MLemflwW3nYpKS2JqGWMEVRjgYeB4zAS6qqhq0qqSjKqcBHwDhVVZckckxNwncjVFVVCLIWB+QbAXf8rRwdmb8ubJiG3d7QPvdWCcz33chbQYSVv/8BAJ7KSmERS0rCmCLcBarT2XRLmGbhbU5rp46MZmlorvjUPvOZL4rimKmhtfgOcK5ZmtiintEIckcmODA/kSLs+hWt202irQmdyNjb3u0YiYSJMEVRjMDTwAygAFisKMoXqqquCdkuFbgeWJSosTQbg1YUVRU34Ja6owxG8NB2DYfbI50Gt/UI2hfNDcxvzqk8Qix5a0Vat2K3Y0gJxGwotibedPwi7ACxhGm09HVrn7nZHohpkQTIacW6gKHoC34mamKkjwlLFBHLluynNBBhGW0yjFhIpBo4GNikquoWVVWdwHvASWG2uxO4H2h/JZ41y0e8XJJ+C5gMkJVEwB8T1gpC3SfCPBW+wqxJSSgmk78umGJrqiXM9/0+4ESYVrevmRZArc5SO75RHLAMPDbwOFHfa39MWAItYQcaWoiARjwTEuJMIq/03QB9p9kC3zI/iqIcBPRQVfXrBI6j2SiaxSpeAdlpefE5jqR1aZPA/MSLMNU3ufBWVgJgsAvxZUgTWU8GW1Njwg5QS5jWFNkaQ7ZYOKb9D27Z2XYuN0lkxl0mEi+gecWtY8EfE9bB47baE11Hwj+2tfUoYqLNsiMVRTEAjwAXxbDtFcAVAD17Rq51FH+ExUpV1RDbVTMtWed/KvpzyRmvJBLe1gvMb2AJS/aJMJ8lzNBkS9gBGhM29BRRkXzsJc3b32CILd1f0vooCsx8Hpa/HcgIjzetERN2IGLPhMvnQk1xW48kKom80u8CdFXi6O5bppEKDAPmKYqyDZgAfKEoSoPCUaqqvqCq6lhVVcfm5raiXzvelrD0bnBQlKq+kvZJqwbmN7NOWHNO5RdhmiVM3AQMvlgwxSpjwmLCYISJ1yY2pkfSdtjS4ZC/Ju43edTdwsqWqOzLA5luB7V+q7smkkgRthjoryhKb0VRLMBZwBfaSlVVK1RVzVFVNV9V1XxgIXBi+8qO9P1PRMFWiSQciaoTFg5NhFUGYsIAf2mKJseEaWnhoW1MJBJJZMZdKkqIyIStA5KEuSNVVXUrinINMBtRouIVVVVXK4pyB7BEVdUvoh+h7Yl7TJhE0hitGZjvQ4sJ08SX3yIWS5V8PXmj4KJZotq7RCKRSBoloTFhqqrOAmaFLAtbtllV1cMSOZbm4YsJ82oiTIqxA5JJN4iG5aNbwZWcYBHmravDtXcv1t69/cs85ZolTIgug124IY1NFWEA+ZNaPkiJRCI5QJD2z2j4zcNSfB3QpOTCWW+3TkJFgkVYwbXXseWYY/2ZkQDusn1AIDBfiwUzJEfp8yaRSCSSFiNFWDRkTJiktUlwsdaaX34Rp3EHguddO3ai2GwYMzJ8YxCTjia7IyUSiUTSJKQIi0LEmLDWyJKTHJi0UkyY6gy0Y3Hu2IE5L0+05iKQNSlFmEQikSQWKcKiosWESUuYpJU4+Erxv+vIxJ7HreuJ5/VizssLeg5ShEkkEkmiabNirR2CUEtYqu9GlZnfJsORHAAMOBJuq0j4aVSXK+i5uWvXwDpfsVXFkqAK4RKJRCIBpAiLjr6BN8DAY+C8j6HP4W03JokkDqhOZ9DznKuuDDzxCEuYYpSGcolEIkkkUoRFQQlt4K0o0G962w1IIokT3traoOfmboG2rqrHF7SfoOQAiUQikQjkVDcavuBoVRZrlexneKqqI65LmSx65Fny81tpNBKJRHJgIi1h0VBC3JESyX6Ct7oq4rrM888j7ZijMbVmn1aJRCI5AJEiLBqhMWESSQfFVViEY+NG/3NPVWQRpiiKFGASiUTSCkgRFoUGMWESSQdl29ln4d69x//cG8UdKZFIJJLWQcaERUORDbwl+wd6AQbgqapso5FIJBKJREOKsGhoFcSlCJPsZ0hLmEQikbQ90h0ZDRkTJtlP8VYLEWbt34+ca69t49FIJBLJgYkUYVGQMWGS/RWPLzsy74EHsA0e3MajkUhaF5fLRUFBAfX19W09FMl+hM1mo3v37pjN5pj3kSIsGpEaeEskHQ1FCfoeeyuFCFOstrYakUTSZhQUFJCamkp+fn5gsi2RtABVVSktLaWgoIDevXvHvJ+MCYuGVqzVK0WYpINjDK5+r1nCDHYpwiQHHvX19WRnZ0sBJokbiqKQnZ3dZOuqFGHR0H6fqnRHSjoGqqriratrsFwxBP/UPeXlYrlNijDJgYkUYJJ405zvlBRhUVCkO1LSwSh+5FHWjz6I6p9/CV4RYglzbtoMgMFub62hSSQSiSQEKcKioZWokIH5kg5C3fLlADh3bA9arhgbNuNOGj8eg7SESSSSOPPaa69xzTXXxO14xx57LOU+631bjiMRyMD8aPiLtbbtMCSSWFFdLvG/3hG8IowISz/55FYYkUQiaUvcbjcmU8e+1c+aNauth5AwpCUsGjImTNLB8Lqc4r8jODg0NCYMwJST3Spjkkgk4Tn55JMZM2YMQ4cO5YUXXgDg22+/5aCDDmLkyJFMmzYNgOrqai6++GKGDx/OiBEj+PjjjwFISUnxH+ujjz7ioosuAuCiiy7iqquuYvz48fz973/n999/55BDDmH06NFMnDiR9evXA+DxeLjpppsYNmwYI0aM4Mknn+THH3/kZN0E7fvvv+eUU06J+BrCjVfPl19+yfjx4xk9ejTTp0+nsLAQgJ9++olRo0YxatQoRo8eTVVVFXv27GHq1KmMGjWKYcOG8fPPPwOQn59PSUkJAG+88QYjRoxg5MiRnH/++VHP0RHo2PI4wciYMElHw1tTAzS0hIVzqZtyclplTBJJe+b2L1ezZnd823gNyUvjfycMbXS7V155haysLOrq6hg3bhwnnXQSl19+OfPnz6d3797s27cPgDvvvJP09HRWrlwJQFlZWaPHLigoYMGCBRiNRiorK/n5558xmUzMmTOHW2+9lY8//pgXXniBbdu28ccff2Aymdi3bx+ZmZn89a9/pbi4mNzcXF599VUuueSSsOcoLi4OO149kydPZuHChSiKwksvvcQDDzzAww8/zEMPPcTTTz/NpEmTqK6uxmaz8cILL3DUUUfxr3/9C4/HQ21tbdCxVq9ezV133cWCBQvIycnxny/SOToCUoRFQ8aESToYWjsib30gQ7J6/ny8FRUkT5pE8sRDKHrwIQCM2dISJpG0JU888QSffvopADt37uSFF15g6tSp/jpTWVlZAMyZM4f33nvPv19mZmajxz799NMx+sIQKioquPDCC9m4cSOKouDyhS3MmTOHq666yu+u1M53/vnn89Zbb3HxxRfz22+/8cYbb4Q9x8KFC8OOV09BQQFnnnkme/bswel0+redNGkSN954I+eeey4zZ86ke/fujBs3jksuuQSXy8XJJ5/MqFGjgo71448/cvrpp5Pjm0Bq54t0jo6AFGHRkDFhkg6Eqqp4qkT9L80SVr9+AzuvuBIA+8iRZF96Kd66ekqeegpTmAumRHKgEYvFKhHMmzePOXPm8Ntvv5GUlMRhhx3GqFGjWLduXczH0JdECK1PlZyc7H/8n//8h8MPP5xPP/2Ubdu2cdhhh0U97sUXX8wJJ5yAzWbj9NNPb1FM2bXXXsuNN97IiSeeyLx587jtttsAuOWWWzjuuOOYNWsWkyZNYvbs2UydOpX58+fz9ddfc9FFF3HjjTdywQUXNPscHQEZExYNGRMm6UCoDgdogfm+mLCq777zr9dqguVeczWD1q5B6eDBuhJJR6aiooLMzEySkpJYt24dCxcupL6+nvnz57N161YAv7ttxowZPP300/59NXdk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", "text/plain": [ "
" ] diff --git a/docs/tutorials/quantum_reinforcement_learning.ipynb b/docs/tutorials/quantum_reinforcement_learning.ipynb index 50298fe8a..fba0291e6 100644 --- a/docs/tutorials/quantum_reinforcement_learning.ipynb +++ b/docs/tutorials/quantum_reinforcement_learning.ipynb @@ -177,7 +177,7 @@ }, { "cell_type": "code", - "execution_count": 0, + "execution_count": null, "metadata": { "colab": {}, "colab_type": "code", @@ -360,9 +360,7 @@ }, { "data": { - "image/svg+xml": [ - "(0, 0): (0, 1): (0, 2): Rx(theta0)Rx(theta3)Rx(theta6)Ry(theta1)Ry(theta4)Ry(theta7)Rz(theta2)Rz(theta5)Rz(theta8)Rx(x0_0)Rx(x0_1)Rx(x0_2)Rx(theta9)Rx(theta12)Rx(theta15)Ry(theta10)Ry(theta13)Ry(theta16)Rz(theta11)Rz(theta14)Rz(theta17)" - ], + "image/svg+xml": "(0, 0): (0, 1): (0, 2): Rx(theta0)Rx(theta3)Rx(theta6)Ry(theta1)Ry(theta4)Ry(theta7)Rz(theta2)Rz(theta5)Rz(theta8)Rx(x0_0)Rx(x0_1)Rx(x0_2)Rx(theta9)Rx(theta12)Rx(theta15)Ry(theta10)Ry(theta13)Ry(theta16)Rz(theta11)Rz(theta14)Rz(theta17)", "text/plain": [ "" ] @@ -591,7 +589,7 @@ "outputs": [ { "data": { - "image/png": "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\n", + "image/png": "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", "text/plain": [ "" ] @@ -908,7 +906,7 @@ "outputs": [ { "data": { - "image/png": "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\n", + "image/png": "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", "text/plain": [ "
" ] @@ -1108,7 +1106,7 @@ "outputs": [ { "data": { - "image/png": "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\n", + "image/png": "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", "text/plain": [ "" ] @@ -1138,7 +1136,7 @@ "outputs": [ { "data": { - "image/png": "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\n", + "image/png": "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", "text/plain": [ "" ] @@ -1203,7 +1201,7 @@ " next_state, reward, done, _ = env.step(action)\n", " \n", " interaction = {'state': state_array, 'action': action, 'next_state': next_state.copy(),\n", - " 'reward': reward, 'done':float(done)}\n", + " 'reward': reward, 'done':np.float32(done)}\n", " \n", " return interaction" ] @@ -1503,7 +1501,7 @@ "outputs": [ { "data": { - "image/png": "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\n", + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAmQAAAE9CAYAAACleH4eAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADh0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uMy4yLjIsIGh0dHA6Ly9tYXRwbG90bGliLm9yZy+WH4yJAAAgAElEQVR4nOy9d7wsR3UtvHbPzDnn5qSLcrgKIAkQEsgyshBJJotgG3g2/ADzZDC2wQQbkE0wfvh7FtggjI39EAZbZEwQCIQEQigASugq53iF7lW4OZ4woev7o7u6q6qruqt7Zs6ZPmcvfmJmqrurq3v6Tq2z96q1SQgBBoPBYDAYDMbcIZjrATAYDAaDwWAsdDAhYzAYDAaDwZhjMCFjMBgMBoPBmGMwIWMwGAwGg8GYYzAhYzAYDAaDwZhjMCFjMBgMBoPBmGM053oA/WC//fYTRxxxxFwPg8FgMBgMBqMQ69ev3yqEWGvbVmtCdsQRR+CGG26Y62EwGAwGg8FgFIKIHnZt45Qlg8FgMBgMxhyDCRmDwWAwGAzGHIMJGYPBYDAYDMYcgwkZg8FgMBgMxhyDCRmDwWAwGAzGHIMJGYPBYDAYDMYcgwkZg8FgMBgMxhxjqISMiDYQ0W1EdDMR3RC3rSaiS4novvh1VdxORPRZIrqfiG4lomcOc2wMBoPBYDAYo4LZiJC9QAhxohDi5Pjz2QAuE0IcA+Cy+DMAvAzAMfF/bwfwH7MwNgaDwWAwGIw5x1w49b8awPPj9+cDuALAB+P2LwshBIBriWglER0ohHhsDsbIYDAYs44d+9rYuGMKTz9kxVwPZaSwb6aLi29/HCcfvgpH7LfE+7hdUx08tHUfTjx0ZWabEAK/vH8rnnX4Ktzx6G4cvnoxtu1r47gDlw9y6IW4+ZGdOGLNYlzzwDasXTaOk49Yjavv34pFYw0ctnox1iwd1/a/8Tc7cM/je7S2w9csxsYdUxhvBli+qAUAeOqBy/HormnMdHpYt3YJtu5p4/iDlmPr3hk8vmsaTzt48M/YL+/bisXjDRy53xJc88A27JzqYPWSMQghsGOyo+27fKKFlz/9ABARAGD3dAf3b96LZx62CrunO7j7sT2YbHfx3GPWIggoc55Tj1qDhtEOANc/tB0PbNkLADh45SJs2zeD6U7oNf5nHLISxx80u9+/imETMgHgp0QkAHxeCHEegP0VkvU4gP3j9wcDeEQ5dmPcphEyIno7oggaDjvssCEOncFgMGYXv/fvv8KGbZPYcM4r5nooI4WLbnsMH/jOrfido9bg6297tnO/R7ZPoheKhLS9+UvX45ZHduKhf3x5MvFLfO/GTfirb9+S6WO27/1rPvcrjDUDtLsRabjgz38Hb/jP6wBEhOJXZ79Q2/9dX78Jm3ZOVTrXhnNegZf9yy+wZc/MwK/z8rs3463//WsAwNLxJvbOdAuP+el7n4sn778MAPDeb96My+7ejNs+9mL844/vxjeu/w0A4Et/fDJeeOz+yTGX3fUEzjr/BvzNy47Fnz7vqEyfb/vyDdg11cm0++Dslx07rwnZc4QQm4joSQAuJaK71Y1CCBGTNW/EpO48ADj55JNLHctgMBijjA3bJud6CCOJmZis7J7On2hP/+TlAFJSdcsjOwEAQgAGH8PGHdVIzTAgyRgAbN3bTt7biNe+dhd/8MxD8P6XPAUA8KELbsNld2/2PteWPTN9jNSNJ3ZPJ+8lGfvd456En90Vje0ff//peMFTngQAuObBrXjvt27RSNuGbfsAAI/unEYvTO9HM9CVVY/tmo73t/9b2TvTxVtOPRyNIMCXfvUQAOAbb3s21nlEVpdOzG1576GeXQixKX7dTEQXADgFwBMyFUlEBwKQT9ImAIcqhx8StzEYDAZjIUMI9aX84da2uf97XlguyNamotMNsXJxCwesmAAATIw1hjK2srClD2X6FADWLh1Pxrz/8uhVJaIHrVyEB7bsw6M7p3D4mpQ8BSaTzkG3F6IXCqxeMq4R8ANXTCTnHmUMTdRPREuIaJl8D+DFAG4HcCGAt8S7vQXAD+L3FwJ4c7za8tkAdrF+jMFgMBiSolQmZFUPHDJswyoaaacn0GqkU7c/XRkubIRsvJmOs9kgpT0ikTMqIVuxCEAUFVS/L5M4y082ntbuRf2NNQPtHrWa9XD4GmaEbH8AF8R5+yaArwshLiGiXwP4HyI6C8DDAF4f7/9jAC8HcD+ASQBvHeLYGAwGg1ETyPm5Kq2yRshGgKOVHZcQAu1eiDGF3JjauLmCjZBppEh5L4naTKeXtO23bAxARMgWtdKoX+i4H7arlhG38WaAULmRLcvYRhFDI2RCiAcBPMPSvg3AGZZ2AeAvhjUeBoPBYNQP1z24LYmYVI10jQL5sqFsyrIbs5M6RsishEyJkFF8JVv2zOCQVYuSdiEEhBC4/qHtOGXd6twxyP7GmgG6PUWH1uAIGYPBYDAYlfHTOx7H27+yHkeu9be6sGEU9GI2lB1VJyYZo5iCa1oI2VhBylLVkMmIVhgKLSomAPzkjsfxjq/eiH94zdNy2bUaIdPG1hgV2pqP0ftWGQwGg8FAuhLywS3RCrzqGjJLW9VBDRBlx9XpWiJkI8I1GkGWTmgpS2X7eCsbIRPqq6ohEwKPbI+eg4e27kvabdc90+3F/Tcwppx7rCYRsnqMksFgMBgLHgONdDnY3WwuAAitKUv3/oloXdWQDXxU1WAbhytCJgmSJFCAEiETRoSsxNeRpCwbgXY+W/RuFMGEjMFgMBi1wCAjZC70XCryWUIe6UxSllqEbDTIRs9yk8dcov44QqamLOVlh0Inqmq3hPwIoiRk461A043Z9G2jCCZkDAaDwagFqq+ytESiHPvaiMWwYE1Z5pzeSshKnU9Y3w8CNiKri/ptETKLhsyIkGnkTOmbLFeeaMgagbayclRIaxGYkDEYDAZjXsGHbLh2mc0IWRmiCKSEbKyiqF9UTAX6wHbf9JSl/r4RkJGylAMziCN0vVjeuF0RsrqgfiNmMBiMeY5RNTKda5j3pdsLcevGnZn9THIwqilLe4QsbxVhVtRfJkSmRv9s+rV+YOtvzBEhA6LomZqylIeHQqeprvthNYZNNGSNzPnqACZkDAaDMWJgPmaHeV/O/dm9eNW//Qp3PLpLa++ahMzWlyMWNbsRsnJII2SqqN+feIQaISt58gJYI2SN1OC1ZazCHG8G7pSl0leZqF66ylJ36q8L6jdiBoPBqDlu27hLm3RMMB+zw7wvt2/aDQDYvFsvmN1WTEGBchFHk8wNE2WjVHZRf4nzKbdl0BGy4pQlZbbNdELzEAiBjA+Zvj17nge27MXema4SIQtqs7JSBRMyBoPBmEVc/cBWvPLffokv/eoh5z6csrTDvC8uMtLpGoTM2pf92DyiPGiUFfW3+xT1u1YvDgJq35ILjTmc+oHIHNZue2FG8hwpS+X9GZ+6Em/8wrWsIWMwGAyGPx7ZPgkAuPeJPc59mI71h0zKsoQB62xGyGyDyItcdXr9GcP6EJ2qUIOSzTg96bK9AGINWS+bspSlkiTUYd6+aRc+9sM7ree/ZeMuxam/URszWBX1GzGDwWDUGHIOCnJmUg6Q2eF7W9pGhKwMw53zVZZ5thdKSq4KhpqyVPqTvl9qhMz0Ahtv6SlLp6hfeX/9hu25Y5ARt7FmUJtySSqYkDEYDMYsQk6Eed5Io1p7ca7h4hDm/cqK+v2Jz1yvssxDWsty9ET9aqpXkq88HddYwxT1R68CZmrVtcoyx4esGfAqSwaDwWDkQ04veZpjjpDZYRIr1y3sZET9xX1JzKYxrLV0Us7+Vg1ZRduLQXN+lcjKZzsvCjzebBiRTFVDprSWGOdMNwRRRASbltqao476jZjBYDBqDPkXf95kxbAj9MxEZghZiXPMte1FXiqxbUlZjo6GTCFkMSPLG9tYM9BF/fFXZmrIyoyz3Q0x1ghARJyyZDAYDEY+5MTFEbLhQYrfJUrZXvRmkZDZRP05hNAm6i+zzlI9n4votLsh3v7lG3D347u9+wX06Jt8xvMIGZFOSHUfMn3Muel95bydnkjuDYv6GQwGg5ELOd+yhqwYRdEf75RliXMOOnKUB9v3nBegS33IqkV/1CiW6zy3P7oLP73zCXzwu7dV71sSshyyGBDBlkEVQr8vAvmEWu9DJGdk2wsGg8Fg5MInZTkMTvDzu5/A3//wjsF3PESY98E30uWjIXOxtNG2vZCi/v5Tlq57KZvLUj41siejZXkyLoI9hZpXXNwGbUWmQDJwTlkyGAwGIxdhQsjc+wyDEvzv/74B//WrDUPoefbge18yKcsSRbznWkPmI+ofq2gM++dfuzF5X3SZZSWOWp1MD2sXIoMoJ7YX0b+R5FDHOOV2k7DJw8xSTXVA/UbMYDAYNYacCIMcRsZO/XY4bS+M9m6vHj5k1lWWeREyS3HxMsTp1o1pzU935Kna9csI2eFrFifkLH9oZNWQRaJ+oBFfmICwpvdlOlSvdZnuy7YXDAaDwchF6kPm3ofpmB0Z2wvHTfTRkLmIT9dcyjlElC2d1IvHppqslvEh085TsL1srz0h0AgIAZEi6i+KkGU1bSKOkMk/WIr4sak3k6c0jWjrACZkDAaDMYuQcxA79RfDvEWu+7Jh2yTCUCSTcDuzyjJ7jLuWZdlRVkdZ2wuB/FR3GbhWc1Z99nphFNVSh5c3VnObPG0YR8ikqWzRePQIWUok88jgqKI51wNgMBiMhYTQw/Zi0CGyr1778GA7nCO4bsvHf3Qnpjs9NIMoOpMtLl7C9mJWI2TlVlmGIpu+q8o7iohOWUITRbWghdZyI2Qgh6g/ei9TlqEQ1mid7DqzyrKGREyCI2QMBoMxiwg9ImSDxoe/f/usnWuQyK6y1D+rd/CGDduTCJmP275rj1m1vbBG7vItHkwiX/Upcl1n1avv9gSaQaA913l/dJiifnndkc1FqrEUjjGlmn915Wj1+zEK4AgZg8FgDAAbd0zigOUThf5HcgLJ+0t+11QHoRBYtWRsoGOsO/LIinY/C4hcHubcGDZnsKHIasaqRoSchKyq7YUQCAhGypJw68debN3fNIaV5xVCRBGywBICyxkvoGvIAOADL30KTjp0lfc1zDU4QsZgMBh9Yvu+Np7zicvxf350Z+G+PinL5/7T5Tjp45cOanjzBr7RKzNFaRf124+dXduLcinLKCU3mHO7ziNJb2nbi1jDZx63fKKF5ROtzP4EspZIkhqyIElZ5p9X91aLepb48+cfjVOPWlPuQuYQTMgYDAajT+ya6gAArrp3S+G+coJp1FjrMlcw52b1Fqp308dQdhSKi9tO5SKEu6c72LGvPTBCVmStUnb1prrKUiLP2iWbsoxewzDWkAXpOHM1ZFqrGNiih7kApywZDAZjQPCZyn1sLxgRzHuUV+cRUHVFOspwrLk2hnVd44l//1OEAlg81tDaqz5HzghZte4QhiKji8zXkJk+ZOn5QwE0Y2PXovFo9TnDev+74ggZg8FgzCLY0aI68oiVJiHzuMkjkbK0DMJVusm1GKS6D1nRMsty/cmUpTq+vLER9OtPRP1CQMgVm/DwIVP7gKh8P0YBTMgYDAZjQPCZCmQEZDZLJs4XVNaQlRH1z6pTv63NLwqYfK4aIXO4e1T2IRNRhEwdT+EqS/W8clxS1C+d+oVdN0fJdn3sHCFjMBgMRqmU5WzaK9QVGS1Y7t7pTJw9zv9eF6VFB4vsuYoidCbhGLTthcTuqQ7O/u6tmGr3/PqziPrzVoAGRHq6UfEhE1BsL0Q+STRJXY35GBMyBoPB6BdlJgFZ1Wd2J/75Af8ImfF5RCNkVlF/UYRsQCEgZ13Q+O7d/fgefPPXj+Db6x/x6q8nkE1Z5kXIYFshKW0v9FqWruPl/mofbAzLYDAYDC9IJ3jmY+WRd8+0edhgG3bbC8cqyxEV9UtkjGEri/oHq+rvhWEUIVPacs2PjVWWaXHx6LtpqBGynPOqt6tMJHQUwYSMwWAwBgSfSEw30ZAV71xkTTDfka1lmTG+sB6XjZD538fZFfVn24oidNnSSdHnssW0B+3U3wtj3Zcm6nfDFN8ntheGMWwoCqoXQGNkrCFjMBiMhYwyk0AvdoL38bvqzKJrfB2QGyFDSk7MKJM1QuboZ86NYctGyBztRRj0ZfbCSPeljiMvQhb5kOkrJOW4wjAlmALCTh4tHicCTMgYDAZjQaOKRsnnmHav/0LXO/a1++5jVOAb6epHQzabxrC2lY5FRCmjkSJHewFc97KofqgL0sxVHQXlMIzAWGUp74WI/xcoqyjzC66rY2XbCwaDwWDA76/zREPmEaJod/snZHUuwWSSAV8NWZZEZA8cCR8y2yrLkrYXRe3uc7vaq12/TFlSiZRlaIuQhdH3nGrIRMEqS7UPjpAxGAwGA2U1ZMX79kvI5qMGTb0mvXSSYnuROcbSj4N4zHlx8cKUpd0YNldAb8GgV/mGQlRIWarHR6/SGFYV9dtSlvK6Mz5k1S9hzsGEjMFgMPpEFQ2Zj6i/X0JW95Wctvvqc00mES1zG+Z6pV5pH7L486A0ZJWNYWWETKFEhYRMO2+cyo/HJm0vikT9epStPDEdJTAhYzAYjFlEanvhQch6fqacLtgm97pHzVz3jcgdHbFGyBy3YTZJbJni4hLZCFncXpKROTVkpXpJ0QujCJn6JeRzI8pEt4DsKkuBgpSlaZ1RXz7GhIzBYDD6RWJq6TGdlbG9mOkzQmYnZH11OedQx+9LwGzfi/M2zKao33KusosK0ghZWdsLe3smuug5HlnuKPAkZNF+ad+aU79iX1Ek6tcHW2s+NnxCRkQNIrqJiH4Uf15HRNcR0f1E9C0iGovbx+PP98fbjxj22BgMBmMQKDOF9mZRQ2ab3GvOx3IjZBL9pB1n8/7YzlUYIXPM2uVTloO90l4o0GyUS1nqpq7xa0ZDZre9kN+xFmWDYKf+ArwbwF3K508AOFcIcTSAHQDOitvPArAjbj833o/BYDBGHnLC8FlyL0Xjs7HKsmcRqNc9ZekzfB/rBnfKcjZF/dlzFZ3fJeovS0SGYQxrFhcvWmWpXn8q6o/eB3G0TcB+n9QUp9pWXzo2ZEJGRIcAeAWA/4w/E4AXAvhOvMv5AF4Tv391/Bnx9jOozlSXwWAsGJRLWZbRkA0+QlZ3OCNkJVdZujCbt6xKhMycFKuK+gd9nb04qqUSxiqifqkhCygimaGw/6tSFwGkbWx7kYfPAPgAAPmrsgbATiFEN/68EcDB8fuDATwCAPH2XfH+DAaDMeLwn91m0/aia3EerTtFUwmZa/L10ZC57sTci/rzj3GK+ssaw7qehMqrLJGNkBUUF7eL+uV3QMk+1pRlElFTV1myMawVRHQmgM1CiPUD7vftRHQDEd2wZcuWQXbNYDAYlVDKCV4SstlIWc5HUb9rAyFhJ+YEXiZlObu2FxZRv82+X4UjRFbeh6zU7h79xU79qjFsboTMTFmmETIRR8gCosQGw4RIjlPaOELmxGkAXkVEGwB8E1Gq8l8ArCSiZrzPIQA2xe83ATgUAOLtKwBsMzsVQpwnhDhZCHHy2rVrhzh8BoPB8EMqSC7eV514itB3ytJGyGoeIxMDJhLZEwy5fwU2olHkS+uKkJUlIm4NWbUbIFOWvrU1TWPY5H28yjKIfUxCh1N/qB6QeVdPDI2QCSH+RghxiBDiCAB/CODnQog3ArgcwGvj3d4C4Afx+wvjz4i3/1zUXX3KYDAWBKpolHxSY2x7kYVbQ5Yia93Qf/9VEIYCU223l1wVp/5BBYAGbQwbGqL+Igk4gfRalqaGTNbFFPmi/oxTf41DZHPhQ/ZBAO8jovsRacS+GLd/EcCauP19AM6eg7ExGAxGaSSrLD3mgjAhZCZpsKy461PQNJt1GWcLPoTJy4dswITEhk/+5B4c99FLMNnuWrfbvvPSxrAV+Yd3cXHP/kxRv1+ETF8hCUgNWaQFS1OW7lHot0vUWEEGNIt36R9CiCsAXBG/fxDAKZZ9pgG8bjbGw2AwGINEuQiZPWVpm4f75VPzk5DZ29XISD+rLAd5y75740YAwJ7pLhaPZadb6yrLgsFmSidJ24uSY3NdZ9UIYVo6KR5XAVOUlhYSSXHxOEVJFHuVOQaarrLUSV2NA2SzQ8gYDAZjPsNmUlkEU1Rtmwj7TZ9ZjWFrztF8NE4+UR5XP4PU2BVxg0opywFFyAbtQxbGpZOSlGXB/tLSIh1Pen4B6UNGsQ+Z5Xy2lCXqXcuSCRmDwWD0iSoapWyEzEae+iMHXZsxbM2lz+otUS0OlEWWmWvM0yD5tvcD97ksKctCY1j9c1X64TpL1WeuGwo0A0oIYxExytpeiOQ18SGDW9Rv+yMoFKLWETKuZclgMBizCJeoPy8KUBV5/k11RTUNmT8GuZasiBzYzlQcIfPvK/fcnhoyX0RCfP9VlsgYw8p+4r7iVZaiQNTPTv0MBoPBSGBb8eXcN371iZD1m7LsLigNmWI/YmyzR1jsGMYdc6ZHLc3FEbLhpiyrPjKJhqzEKkv1tsjxCCGidD6l12olrq7vtMYhMiZkDAaD0SfKpAHdKUvbvn0NyxptqTtFU68pM/cmjCxDybL9OAmJ3x0KQ4FOgU9ckWu87bkpsp7L+sJWFPU7zlPZhyzUV1kW8aJI1K9Et+S4hNxOcQFye3FxWFKWQtR7lSUTMgaDwegTchLx+uPckbK0rYjs1/bCFiGrk71jmcmVoEfIbJYKGvrUkP3tBbfhmA9d7LVvGb1aWVF/VQw6QiYLgqe1NQsiZKSfSx1PVKg81ZlZo2GWlKXst65gQsZgVMRUu4fP/OzevsvbMOqPVJDssa9xjNmHir5XWdY8QmZPVbmvQC9QXa0fX0LyzV8/UrhPFQ2Zrf5oXp/Vfchc7eZz6ddfT5ZOgl+EjEBO0tyNTWajVZYOUb+UCRhtNeZjTMgYjKr47M/vw2d+dh++s37jXA+FMccoQ3IkETDJ0mz5kNUoQGaFeknmpK9mLE2xd14/9l4GB1ePdt1gfl+DsnVw2l5U1ZAJ3fbCJ0ImAEy2u/jsZfdp6d9otSQlUbS8P1bMeph1dupn2wsGoyJ27GsDqL+NAKN/lDOGjV5nQ9TvawwbhiI24hz9ycxZOolIi5rohMw/Ulj2lkv/rUqwifoLnfr1z0U6NRecpZMq/p6Fiajf06kf0b3+zM/uw3lXPaht6/bC5Hk0yXU6Tv0ViO7d6D/BbnCEjMGoiOlOVKNuUasxxyNhzD38JzE54W3f18Z5Vz3gdO4H+td7WSd3S9ORf/tjvOOr6/s612zBpbGKNGRp6rjo1vUr6pcwV0U+sn0SX7vu4WRMebCL+sudv3LK0vHMFmRMnUhLJ8mWoghZtH3vTLasVKRHk6StIGVpaM9q8DeFE0zIGIyKmO5Ev1wTTMgWPEoZw8YT3r1P7MX//fHduPE3O5x99JuytIr6HRPxT+54or+TzRJedO5V9g2k6or0lXlWTf+AUnbHfOhi3PfEnuTzH553LT50we3YpxCNMucqSwh9+cf//b2nG+ex71flkQvDiDQ1SviQSeJkuzfdMEwWCLhF/VndZk+IyhHDUQATMgajIqbiCNlEi/8ZLXT0Q5w6PbumLOq3P0ZWd2PYYm9RfQ+hvFHvZ16ExUSV7/KWjbuS9zsnpZQhjQKVWWU5rAhZw/iZcpHEKs+cjBKqKUsfUX80DssYQhiifv+UZY35GBMyBqMqZMpyoskRsoWOMqlFc185f1g1ZMOwveirx9lFmbGq5CzSkKn9+JPd2dSE2sYwrILwpsi+qGh3GcgxlxX1A/Z70A1jDRlS537XONXr6PZEcYWAEQYTMgajIqZju4s6CKEZw0WZKcycB/OiKMMwhp3XUHRFGrEoESEbBh8rU8i7yKnf3OybossQshJRuyLI64tSlv61LF3jiAJdlIj6rSln4xWQov76/h4zIWMwKmImjpDxKktGqVWWLjH1EFZZjqIx7A0btuOqe7cMvF9SnN9N3ZHtil2EpN97npyzyJjW0T6slGWzYRIy13NY6vQA0jGrpZOKIFemusYRUPqd5lnC6P5lYa1F/Wx7wWBUhNSQMR9jlCHlmQhHkrrJ7tu/D1l2ydxcP66v/X/XAAA2nPOKgffttr2w7esftSo61sUB8tJyrrMV8cGqhMOMWDlJYoUnRD5mgbLKMvAM97jGIdOfTtsLqw8ZO/UzGAsS00mEjLHgoaTKilAmMtO/7UW2rU6i/jLQSicZk7iNZLhugw8Jbhs3duOOKXzvRt0gWjjea/tUiJBlCX3VlKVfhMzncUlF/fBPWVpWWar6L4qLiwtHztKWsuyGYa1TlhwhYzAqQtpezNcJjuGPco+AS0ydbevfGNYWIavPA1v28lVPN01CVuLe+pDgyZme9vncn90LAHjNiQdr58yzdojGkG0blqg/s8rStWMfov6GIur3XSGrXm4jIITxquOAyEvUr24KQ46QMRgLElOsIWPEkBOGT7QiK8qW7TYNWX/jGtbkPltwR5biLUZERY+WqBGyLPrx4Zrs9KztwvGhTHqwqJalCV/+UTVC5gPZV5Rm9IuQBZZ0rnoMIXbqd4xV9ZyTKHvvRg1MyBiMipBFxTlCxihlDDuL0RKbqL9Ofz+UNW9V3dt7PVVD5p8O9omQdW25YOPYUDEpLbOisexX7i2i99WQ9REha6oRMm9j2LStqeQsU2NYu6hfHqdu64X1XvXOhIzB6BM1mt8YQ0KqXSp+Gsw9konJKvDu7+nKqwFYZ9isIUwfMjVaIgA8vmsaF9yU6rzKrHw04RNd0987yF/xqQqP8aUfDXOVpeMiMhoyjxuS+JBR+i0UEaPEGFa5ooZGyNJ6l9ZFGcmK2nRjLwxrrCBjDRmD0Tfm2kaAMfcoZwxrtsRRFEvQZSilk+bB43rNA9uwdKLpnHyF0KOL51+9AQ9t3YeHt03ipU89EIvGGn3VsnRFLnXdWlpX0ZVJG8Rvh29EqOHrQ2Z+9hiiqiELkpRl/jG2e6MSMopd/11O/YnthdLW7dW7liUTMgajT8yD+Y3RJ8o8A2Uc4vsunaTMumuWjGHbvnatNI+uy3/zl64HABih+mMAACAASURBVJx5woHpvsp1CQiNjF5xz5bMfv1EyPLKDkmCVFQpYLbhqyEzr81n7MkqyxJO/bZxNIyUZZBre5Edb7tX7wgZpywZjH4x97+1jLlGmWfAFPVbtDQSg4yQ1TFyUJXImBEyFfKelHHPN1Hkph/1I5QFG/Z9fAj3rzdsz93ub8Sqf/bV5/k8g6GSsvQlYoGFuGqi/thCIxT5CV/dGFYsHA0ZEQVEtHxYg2Ew6ohR+OuXMbcoE8ly7VnGvNQXoUbI7CWaRjnlXnVoAm5CJu+J+3soPqk7BakcL/R21/5FeF1spOuCt4bMM2VpPsteKUslQiZRxYesaWrIkgiZbZzZ8fXCeV7Lkoi+TkTLiWgJgNsB3ElE7x/+0BgMBqMe6GeVZbpabPApSzVCJieqKhqhuULR0FzRECEcK0yRErWyKzhV+KSdhTI+d3qw+FyF8NWQGUzFd6FBGU2dXBnpM6wkeqi0BRYNWSjs35XqOWfvuX7wiZAdL4TYDeA1AC4GsA7Am4Y6KgajRhjlCY0xOxDGa+6+mZ3cKTSHu4I3ehohkxEy/TyDqt04DJQZmr6vcEbIeknK0t6Pz/3Isy6xkTBz712THXzvxo0Dia17+5AF1SJkPpARQ13UXxQhyz6PZoQtWYdpix4br2m//uMeNfgQshYRtRARsguFEB2waobBSDDC8xljllBqlSVMQiTb++vXBjshM8czP6BeRxQhs7NZmV7rp5ale5WlQsJESpZMkvPub92E9/3PLXhgy16Ps7nPUQZmylL6KGb71z+77DFUpCnL9Jq9V1kq3eurLCPdW7Go3+i3cLSjCx9C9nkAGwAsAXAVER0OYPcwB8Vg1AnzZUJjVEeZZ8Cc38KcFNogU5bu8dj3+c9fPIgjzr4InX7DdH2gqj4zFO4IWbdXFCHz6d/eLpB+jyZBVPH4rmkAwFTb7vhfBr4RIXO/PdMd637ZVZb56IUCr/ncrwAAjSBIz+MZIdNWWZIaIUtF/fnpfH3bvI6QCSE+K4Q4WAjxchHhYQAvmIWxMRi1wCiLohmzg1KPgCNCNYxVllpZGsevvWvs514a1WecdpQJmg0U3VczIqW+d5HRsChC1kfK0vQhk+GaYf5G+BbTJpAWtdoz3bXul11lmT/2vTNpPw0q4UMWv6rEOZOyjMth5f07MLfNy+LiRPS+gmM/PeCxMBi1BNMxRn8pS3fExjUZ3r5pF87811/i4nefjuMOdC987/qkLAsiRaNsI+C66wLQSiepSET9fZzXlcYTig+ZRs4c/QzGGNZ/v4AoeaZ2OyJkWaf+/H7VSFsQIGFavqssuz07IVNF/bYb6ExZju7jWoi8CNmy+L+TAfwZgIPj/94B4JnDHxqDUQ9wgIzRT8oSycTi1smYuOT2xwEAl975BADggS17cc0D2zL7dRSdUELIjNG60oIpUZy7B1y9J089aDme/5S1zu3aCsecCFkq6s+/7jy4fMjMKF3Sp4vAFZ5J9uXe05d/EOlkxRkhM5+PkhEyGaEqGpfcr6No/VRC1mpQXDrJnrJMDH7nUcrSGSETQvw9ABDRVQCeKYTYE3/+GICLZmV0DEYtwIxsoaPcakAzQqa/6tvsHct5S24/41NXAgA2nPMKbT+bMayv8Wdix9Fv3nRAIAJ+76SDddd9p5YrZ5VlkrJ0HOtxue7z6mOwtVdB3pi8I2SgOHoXR8imshGyX9y3Bb/ZNqmfu6BfldhFqyyj91UiZOoxal9WDVkotxn9zseUpYL9AbSVz+24jcFggCNkDOWv9QqC8DxNk4tU2Mrz2NDuZSNk2fEURcjyzzFMqEMjUNZLKydn6VplWSzq94iQ9bnKssy5gMH8yRelLNPPtgjZm754faataIx6ytLfh0yORV00okXIgiBOWdpjuLbi4tGJ8887yvBZZfllANcT0cfi6Nh1AP57mINiMOoE5mOMfki5MF5VuEiDy1NMxe/9+69w0a2PKcfYz+PWkEUbXORjNqCemShr3aBN1cZbp1N/oai/eFx5PmTWffqIxpl9mYd4i/pJ33f3dMdLw1asIXOkLAtF/XHK0kHIGoFMWUb39dDVi/C1P/ntwnHVmI/lR8go+jPsy4gMYU+Pm98qhLhp2ANjMOoCjpAx+tEC5Wm1XBNmI9CPteGm3+zUPrtInLtQdv722YAeIcuamwoHARJCeDj1O87pMa7yTv3VzwUU/Mb41rIkfZVlpycw0w0x0WrkHlfEx6umLOW41e9JLZ3UbEQrNoWIvs+j1i7FaUfvl2xPUurGzRnlRShFyCVkQghBRD8WQjwdwI2zNCYGo1bgWpYMX9Ii555mQMlElPhWldCQ+aYsbcf4RsgkfAppDwvmv61shCyFei/yImRFon6f79JpzaaOQRtP9Whc3vFACVE/siRp93QnIWRuo9yilGVKyAJl5UChhix+da2ybAaRy6z0ITP7c8kE5nUtSwA3EtFvDX0kDEZNwREyhvfEGu+oTjyuv/SjNns/qcu5/8OX1A50aNhcmNOUpZGzNL3UXFnBflZZ9pOy1McgFA2ZqydPDVnObr4RISIkD0GrEb3ZN5N6zLnuVxnbCzVCVgRJsDoOnaPsS8RjkP1+5x2nYtXi1rx06vcR9f82gDcS0cMA9gFyJao4YagjYzBqAuZjDN8oqdyrGRBm4vd5pZNcE38jST/6j9FpDFtw3Kj8wWGL8KijN3VWPUcYq8iHzKuWZYE+zey/H71amf3ykZq2thoBOr0euso9clVkKGV7EVApTZt53qztBUGIUKsRevIRq/HUg1ZgKjYszmjq5mvKMsZLhj4KBqPGYKd+RvLXegG9kRN2sxEAiCeUHJG5U7gsI2QlolcpmdGPGekImfKeCLmrLNX7F+ZpyOL9nLUcPcZVZBUi37usRtRx+iBvvzI+ZEESIYueP/Uedbr5WkIXdk3pETJ5zc2Gn+1FR0lZjjXSvxpkX1JDRsaxLu1lfemYByGLSyWBiJ4EYGLoI2IwGIyaoWykQyUWoQCufmArHovrG6pwkaGgHw1ZRkSWf9ywjGFVV/ucnZK3hAINWahvKNKQTXf8imtb+/BJWWoC/341ZG74BoQCouR+t2Lio+q3Znr2EllFY9y2N3XFaigLB1RyZYNtleVEKz2m1QgiUT9kytJBxjMhsvzxjjIKNWRE9Coiug/AQwCuRFRo/GKP4yaI6HoiuoWI7iAiaTS7joiuI6L7iehbRDQWt4/Hn++Ptx/Rx3UxGLMGDpAxyj4CuoZM4A1fuA4fuuD2zH5uY1hybhdC4NiPZH+iXbYXRaRueITMYx/lPRFZVlm6UpbFqyxnuikBOWXdanz8NU/DqUeusUYqpzs9XHJ7aiGSVwcz0Y2FKelwWKINxqnf2xhWjZDFZChUU5bFaVgbtu6dSd5Hmv6o77FmASGzrLJctWQseS8jZKEQmOn20FL6k0QNyJLdOhvD+oj6Pw7g2QDuFUKsA3AGgGs9jpsB8EIhxDMAnAjgpUT0bACfAHCuEOJoADsAnBXvfxaAHXH7ufF+DMbIg1dZMvxXWUb7tVRCltuvvT1NhWV36IXCGv1xifqLnl/nisI+4UP0TNuLTMpS608/zpXOTQiZco9aDcKbnn04JlqB9W6cc/HdeMdXb8SvN2zHdQ9uw6adU87x2ohCJijpEKS7kEeaS/mQxQ+OTCf2tJRltS962740QqaSq2JClh3D6sUpIZMWGEIAW/e2sd/SMeXY9NnPOPXXl495EbKOEGIbgICIAiHE5YjqW+ZCRNgbf2zF/wkALwTwnbj9fACvid+/Ov6MePsZVGd1HmPBgCNkjNIpS0Vfk0dMiiNklnM4+nI79TtPnzuGfuGTblVJjSyOrW13aMjyVlmGQiAMhVbFIDUzJev1bt4TpZOf2D2N/3XetfjkJfdY+37RuVcmIndVQ9avU7/LTqMMVLm9TFl2PET9uc9nKLB9X1trk9/ReBEhs7SpEbJmnLKcbHexd6aLtcvGtWMX6irLnUS0FMBVAL5GRJsRrbYsBBE1AKwHcDSAzwF4AMBOIYRclrERUcFyxK+PAIAQoktEuwCsAbDV81oYjDkBEzJG+VWW6WSVR0x8a1n6HSN9yPTtaiQpDEUmLTgsUX8VopcfIdNTlq5xd8PIEFVFUu4H9n/Pi1rRVPmDmx/NHV9ZXZrvvc0V9cuxe9SOlM/AmEVD1nausnT3uWuqg14o8K4XHo1DVy/Guv2WJONpFWnILMNdvUSPkBEBm/dEKdG1SxVCRjQvi4v7RMheDWASwHsBXIKIVL3Sp3MhRE8IcSKAQwCcAuDYiuNMQERvJ6IbiOiGLVu2FB/AYAwZzMcY/qmnaEeVWPRcAiPk+ZDlRMgK05zu8dnE6sP6g8NLQ6alLCkr6tc0ZPpxeRqy6Y5dwE6xM7yJRWPRVHnpnU8UDzoZjxqxc4zF8+b67FWUNldXWVpTlhU0ZDJdefSTluL1Jx+qbfMV9atYpaYsY6f+nZPRKk41QhZQXoSsvozMh5D9IYCjhBBdIcT5QojPxilMbwghdgK4HMCpAFYSkYzMHQJgU/x+E4BDASDevgJA5jxCiPOEECcLIU5eu3ZtmWEwGAzGUJDohgpmTrldLRHjmgij/QuiXSUIVHqM3q5OuLaIzbCc+r00ZOoHyo9+ZHzIHES3Z42QyZSlfVyLx3ySSTq0dKpzH09Clhsh89WQZVdZ+qQs80b48LYoWXbA8tSAQT5DvqJ+FauWtJL3zUCnVvspETKAMqW9giRSmHvakYYPITsMwOeJ6CEi+jYRvYuITiw6iIjWEtHK+P0iAC8CcBciYvbaeLe3APhB/P7C+DPi7T8XbPDEqAH4MWXIR2Dznhmcc/HdOTtGL2qErJtDyFxkqFLKMpBD0Leru9uOncuUZZGoX49C6ceViZDJXl0u80X1Hm0QUCOZxj2Pv4Oc4KiGfFG/HwjIpBO7HqL+vN+36zdsR6tBeMahK5M2SXaLUpa2e61GyBpBoJErTUMWi/rf+62b8YlYz9eMzzevCZkQ4u+EEC8EcDyAXwB4PyJdWBEOBHA5Ed0K4NcALhVC/AjABwG8j4juR6QR+2K8/xcBrInb3wfg7LIXw2DMBZiOMVSS8/+ufMC5n24MG6Gbl7J0bMoT9RdpyPL2t5GvYf3BUUXUn2cMq1+3W0MW2SjYbyzBLupfVIWQOciiCv+UZf/fgaohk7YXj+6cwtUPRDLtKhqy9Rt24OkHr9AIqzTcLYqQ2ajkkvE0EhlpyNJ9Fo+l5wgoiuhdcNOmZBHFWELI6svICuOwRPRhAKcBWArgJgB/jYiY5UIIcSuAkyztDyLSk5nt0wBeVzxkBmPEwIxsQeIj378dj++exhfefHJpg8+mZ4TMXVw87s9KyOx9uYxhNWG8ZU4eVoSsLNEjpfRP2of7vStC1rVFyOJug8B+T6sUrA5FSjnU7/HRnVO494nIgMC70kJehMzbh0xx0Y/Dpf9w0V0AgB++8zmVNGTbJ9s47sDlWptMfRausrSMu6WsPm429JSluhCGQHhgi762UB5bXzrmt8ry9wF0AVyEyBj2GiHETP4hDMbCAfuQLUx85dqHk/dltUBayjInQlakB3MZw9qPyR8TEEVseqHAFfdsTtqGVTnJq181ZWmLkDlqWYZCoOciGDYNWfJqj5BV09HZj/mdc35eul9twYKxzVfEHmgRMp0sff/mTXjW4ausx+UuAgmF9scF4B8hs426pZCuppGyVEsx2cncwkhZPhPA7wK4HpEO7DYi+uWwB8Zg1AUsIWP4PgJyYvUV9RfprOwaMvu+LlG/+rkXCnzplw/hrPNv8B5DVZQW9cNSOskVIUMUCTPJAuCKkKW+F7ZRlakZqo6n2IfMs6+cJ8ybgJCqIYvtL2LSNNXp5fiQ6Z83bN2H4z5yCTZs3YduT2iRKyCNkBWusjQGvmJRS7NcaQZ6RFT97nMJWY1jZD4py6cBOB3A8xAZwj4Cj5Qlg7FQwHyM4Z+ytETIHISsEdijNUA6wWfJlXCnOY0xpH3p/W7cMWk916DhJ+rXNWTG3O/2IRPRKstmgzKpS1XUL4tXp6J+OyNzpT/zYNpwWPfx9iFzb/PnY25j2HY3zCm2rp/8ezduxFSnh+/fvAndMHRGyMqI+t962hH4u1c+VdveaKQp1oCgkTWbTkySy3kdIQNwDoDlAD4L4DghxAuEEB8d7rAYjPqAI2QMbz2UJULmSlk2ArsnltJNJuUlRJ4PmX2mUifcXpiNxQxPQ1ZuHwJlUpYwyKTa3A2FlgKT+IeL7sKDWyP9kRTrq8aw1qhjpQhZsajfl+wOYmGFLuoPtHG1u6EzUmueuhPfi1YjiCJkDf07mel5piyVw2wLTlpBoJR60vuypjsXgoZMCHFmbFtxmBCiMwtjYjBqBdaQMUqnLLVVlvajmwG5NUZxszlRh0IUasgyPmQKH7SRr1FJWRJZUpaahkxpj7VwJlmQ+P5Nkf3lRKuByXYPchoPHCnLKhEygeKUpS/ZzbtV5YqL66ssJWa67pSl+TzJMTcDsqaF/TVk6XE2fWND8SEzz2H740KmTuu8yrIwQkZErwRwMyKXfhDRiUR04bAHxmCMMnz++mUsHJROWSqTRtcxEVZKWcJDQ+boy3yftA2puHiVyJs52QqDhKnohiITWTH7yUTIHLUsq4j6fYxh/SNkeVt9Rf3KKstGlkT5ashkir0RELq9MHOPE0JWkLJUh20nWKnthRkZtV2xi3zXCT6rLD+GyKbiCgAQQtxMROuGOCYGY+Th82PLWDgoO7GqxcVdqaJGQE4ylKQsjdkyzNGQJcawOWPthSIz+Q/Lqb90ypKyKUtdQ6Yf1wsFWo6lpbJ1ohVon8kxLteKzTwIIZIokLN0UigSHVtuXwMQ9ROlxMfUd11+zxZcfo+9FGE2hR09lP1GyNQ0pe0agoDSUk/GOWxfq9ynxgEyLw1ZRwixy2jjOYjBkOAQGcMTkiypRMEVKWoG5JzIZbN5qBA53mWOSEpRhGx4xrA+KUtF1A/bKkth3VdAFETIolfTgd9Vy7InRFa/Vjj2FN1Q4EWfvhI/uHmTts+Nv9np9fOhfc/GAWVE/fISGkq0rPjc+vmkhqzRCKxp4SXj0T1VjVzt49HHZoO85xkNWV7KssYqMp8I2R1E9AYADSI6BsBfArh6uMNiMEYbwvGesTDhnbKUEbJA1ZDZw2ABkTP9mE6SZUT9tiNM24vscY5MVt/wcuo39sldZamMM1ll6YqQxRYQ48bKPFmSJzPWUKDVoFJpVtX2Yu90F/dt3ot3f/Nm7+P1vgbwK6OI+okiwp9nuZKeXP8oU+ytOELWML6UT/zBCfjejZtwolJOyTocTdRv30emPTMaMsu+jQUSIXsXgKcCmAHwdQC7ALxnmINiMEYdrCFjqLCllP7yGzfhXy+7z7q/OsG0u+4ImSuK5Juy/OiZx+Okw6KJsY7FxVXYjGHV1Y+m7YVtBaBEpysw3gxSguIh6jdXbLrIXjIGo+xTP8i7U/7FxXWtnOkf5oJ6X9c/vAN7prtJf0D2PqxZOo63PffIwnGpkSzXrvL7y2jIbBGy+b7KkogaAC4SQrwAwIdmZ0gMxuhDzyAwI1vosD0CF97yKADgXWcck7TJyU3VkPVcEbKAELoiGHE/Jn+KVlmmn1uNNAWXzmlGVE15H9lemFG3YWnIPFKWqg8ZsvYILrIoEBFTF+mY6vQw3mxokbHoHHYSHAqBVjOIwhIxGkHW40w/Ri2d5NzNC3n3KtG/FRCgSNSfkpZmgwAP3wR56m17Z/AH/3F1pr2qmL7I9gJItW6m5s22uySGQcnU8ighlyILIXoAQiJaMUvjYTBqARb1M1T4PgPJJKY69edoyIoc3s2toaEhUycnt1N/2tCxkMNh+ZCV7dYm6lfTqZkIWZxmtGGq08NEK0iiNHrKMrt/t5ftq0hTJgoij2WQ93uT1jXNP0dEaNMPtgjfsolsjEbe130zvcw2oDhS6ByPusrSsY9MWfqssmwEgXNbXeCjIduLqFzSpQCSap5CiL8c2qgYjBGHJiBmRrbg4b3KMn5VJxjXCr482ws5+WYMS4VOdPRyM/apSteQ2aJDyvtQ4I3/eR3+5PR1OOO4/a39+aK0Dxmyon49ZakcJ+JVlg5R/3S7h1VLxpLZOyVmZCXXPUu0zRXV0cYe79M3IcvZVmaVpZqitS14WLV4LElJmufOmBDHr76pz8x4UPxstlwaMsvuCWGuMSPzIWTfi/9jMBgxOELGUOFLypNVlo1iUX8zCJwO8bLVJDWmMWwQ6OVn1GPTY9L3nV5oMY5NG6Y6PVzz4DZc8+A2bDjnFdax+cLH30y3vchOxCpJ0J36Bbo9gYmWfXae7PRwYCtI5+4CUb9tNWFhYKiA6JaBem3maX1XFaqrLAFYLUGkDYgKeT9MvzzpWzaIlGWRhswkvzYynIj6a8zIfJz6z5+NgTAYdQVryBi+SPVcSsrSESELckonJSlLi4bMFSHzSVl2e5bSScb2QaEoQnbNA9vwlWsfVlooE0lRiY5uEisjZPbJuRcKTLQUDVncHjhSlr1QZKJzRVqlUAhFQza8lKUvtAgZ6TpGifFm1qpCnnvGqHUp/caqR8hSFGnIXGlaFQtllSWDwTDAHIyhwp+UR/v51LLMXWUZt9vSSOoxamrUZQyrEjjbWNT+bBqzqii6ZWd/79bCPnpaylKNkCEufO2e4sabQSaakifqN3VMJkEzUZQKLoNcQqesnMyDnrKEtc6nTRcnzy0Lsku0e6lBbBWo41V7OO7A5cn7saTmpn79tmttKNdWV/ikLBkMhgHWkDFU+Kcso9emh1N/ELh9yNLzZlOWWnpLSwvFETKzD6Wl08vWwlRTlq7yOlVQFDUyN9v4hsvUVtaydEXIgMgUVhIlUiJHtlF1e1lCVkSAhDLmQYr6TVCyT5Gon7Qoki3VaLsk2asZIevEdi1VU5bq7VSjjT9852mpPq1hj+raOGDAETIGY2GCSdj8xM7JNu7fvLfUMUL4lZcXQuAtX7oegBEhc5AcWVz8c5ffj4//6E5tm7OWpdDbVBLhmqfU/bs9kSGIobE9aR9m1MeyPVkgqFyIJupXjWER17I0okB/8YKjkvfjzcCSsrSnia0RsoLZs8jfzRd5pBKo6EMGyhi6Ru1ZyKHPdPUImSTnZSsYqOOxodkIMnYX5r8wGelTT51GyOrLyJyPFBH9kIgudP03m4NkMEYNQnvP7Gy+4Mx//SV+99NXljrGVv/Rhj0zXTy2axqA7tTvmqwbcemkf/rJPfjiLx/StsnzZVKWJiHz0JCpxKEbZotMq+NrK9t2TXmYWOWgOPqnfzbJE6Bfv2nWbBPi//4zD0nej7caGduLaFzZgUWO9MXCcnP8co88v7I8vON5R2XSqGeecKC2jy/9IOg6KxvRIyKc/79P0drkfZ3u2EX9rpWsfiOK4LqXMmVp3r6UkKkp+fkdIftnAJ8C8BCAKQBfiP/bC+CB4Q+NwRhdsFP//MTGHVOlj+kJd0FvFdv2tpP3mg+ZI2XZDNylemSrzRjW9CFTBevRsVkSJ9HtiYxwXyNsPZW89ZuGK0pZmhEyOeGm9073IUvf3/zITjy2azpDFtQJfKJpE/Xbc5Y9ByE75/efjkUtV81Gezq1DKLhpIT/c294Jt52+pEV+yJNQ2bTfhGA5z15LU45YnXSlor69QiZTGEOIkLmIlGtpvwjwhUhSw+UX3WN+ZhbQyaEuBIAiOhTQoiTlU0/JKIbhj4yBqMmYD42/yCE8E4FhaHfM7Btb2rz3vAR9TeCwlqWRRoyqw9ZyQhZKATufHQ3jly7RNvW7+riwgiZ8dkWISsqjG6SDvXjuGLxoGrIbP3YV1kCf3jKYfjBzY/imge3Zccv0n7LpizPe9Oz8PjuaTy+a1orGL94rJF5LtVySHkgqMaw9tJJSRdKV5LAzzgiZJVF/cp7VxdyjObdC5JrVtssjTWDT6xxCREllJyI1gFYMrwhMRijDy1lyYxs3sGr6HKMnpkndGCrGiFT0kUuK4mxHO2QPJ1NQ6bZXtic+s2+lPednsgQsr3TXbz8s7/AO79+k7atXwP/0hoyy3yrr7LM9mGan2YjZPrKPFcty14oMjYXkqC5FnJqhrolfyROOGQl3nzqEckig+RoyyMhI4eFon4yU3w5+yrv5d8L5irL1IesWspSHYtL95VoyMyUpSU9GRjfZR3hcyffC+AKIrqCiK4EcDm4uDhjgUP3BaovI3t42z7smuxPCzQfMd21l4mxIar/WIxt+9IImRqdcFlJ+GhzzMhLxA31lKWEK3Cg+5CFmVTkVDwR/+yuJzSi2m/R8aJFARkNmUxZKlOu3ke2P1Mnpd6DcasxrNv2Ihtty6bNtPEj9SEr698WJOm3SEdo869Lhu7JQMyUpSTrJx22Ep/9o5OS85l9JhEyc5VlfE0DKZ3k6GIsTlm6yLlG6ixtdYOPMewlRHQMgGPjpruFEDN5xzAY8x4qIasvH8Pz/ukKHLRiAlf/zRlzPZSRwnSnh+UTLa99Q09Rv6ohU7mWq3RSHiFLSidZU5bpZ13UL481+0rfd8NshKytTMTqitD+V1nmb3duViNkWsoyu2teuSNdQ5YSFdt32Q2zrv+S7DoJmdJPWfIqx51EyOLjbWcqQz/UKKNKKNcsGdM600hvoiFzGcNWTVkWi/qTlKVx+xoWMqya3tYVhX+CEdFiAO8H8E4hxC0ADiOiM4c+MgZjhFHnqJiJR+OVf4wUpl4mDz0hvJ4HXUOmRsjKE7I8bZkeIUu1RWnK0iRx6fuORdSvTsRtLWVZ/t+A0AhUuQhZShZSuIxhJdQI2d0ff6k2gY+3ggwRcNWyDK2i/ujVJWoXSMmBSl59CEO6GjKy4ZBHFx37jbc9G5987QnO7WotS9U6wuxX+yyAzXum8elL79X2ac9C6aQi2ws93+aR8wAAIABJREFUZRn3VWk0owGflOV/AWgDODX+vAnAPwxtRAxGDaClLOscImNYYepl8mBGpVyYbKd9tjQNmZ38yXSNDYnthZmyRLa4eBJdcdhemClLM0KmEjLV6qJKgEw9dzEhM9JU8lW5LZqo3zIglSxMtBp6LcdGkOmTyP7vuWsT9RelLFUfMqVLc1XmD/7itOy4k7qMEeS1Wc+lpFtPPWoNXn/yodbx6PuqwvhUOGcTy4dC4OvX/SbTVTcR9VcsnWTRf5lIUpbGPxE5zgUXIQNwlBDikwA6ACCEmES9SSiD0TdY1D+/YXou5SEM/Z4BNW2lr7KskLKEPWUpjAiZeh7ZnXk29fR7Zrq454k9yeeA9JTljn1p2rWK2anupp+/byZAZjH+dNWylDDNT0mbwLMrN3NrWTo0ZK6vSUtZKozCJGRLJ7LKIbMuo7xMe8pSEu3i78OmIVMXMtjE9QKwpu/b/RrDKucqipBljrWQr7StvvTEh5C1iWgR4u+MiI4CwBoyxoKG5kM2h+NgDBbSiNL0XMqDb8pSjeDoTv3VU5ZZk1edYOn1Al0TVXrAeVc9qJHRRkDavdipRMiqRIbVIwbi1F8QcWvl2F5EREKf2F21LG2ETH52pyyFNZK5aEwnZLboUBohiyNERpRTRRn+oUbAVIIrxzDWDLTzynOb+jEgLZ1U1RjWRqZMpBoye8pSb6s0jJGCTy3LjwG4BMChRPQ1AKcBeOswB8VgjDo4QjY/0WwQ2r2yETKRYeU2sqLyLk1D5khZ5k50uaJ+e4QsFfW7NWQmiEibjHcqK3KrrLLUU5b++0ZjiV+N/V58/P54Yvc07n0iW/Iqz/YiIMqK+sn+B1ZPZG0vUg2Z/XtStV/qV7w4Q8iyx2YjZEL7rKIMD1H3VW07Tlm3Gm87fR3Oes6RmfMIAeyYbMNE3xEylZA59klXWertSbRXaZffbb+LTeYSPqssf0pE6wE8G9F9e7cQYuvQR8ZgjDDmg+1FvwWP5yMiEtQrpSGz2V7Ybq0zQub4HiZaeSlL/TVpFzpJsxnDZsfqfg4aBiHbrWrIKtQZLzJyVeHWkOnT95LxJhaNNQpF/YCFkCV9pn3bhhWGFtsLGSFzsIlQ2FfDLhrTp127lYWhIctJWZZBqrMiJWUZvf/QK463HiOE0FLVEmnppP5Tli4NmUvUrz4D3/2zU3HzI7uwKyaNdf5Z81lleZkQYpsQ4iIhxI+EEFuJ6LLZGByDMapQfyDqGiFzOcQvZMjJpZQPmaHbAtxu7xI+UQV3SZ60f1uETG1SU1PJpJeJ5rnHkNGQKZGSquWA0vMWETJ7u3nnosSjnUiZ95kCdZsu5lf7NsdmE/WnESZHylKkvxIq6V5kEG3X8eq2RNRvK3dURjulpQn14219AtHjsmOyg2MPWIaXPHX/pL3dZ+mkwDIWE82CWpYA8KzDV+Os56xLxtzvczmXyCsuPkFEqwHsR0SriGh1/N8RAA6erQEyGCMJYX1bK3CELAupWSmbsjTnANu9VVN8Pt5NptZIhezK5NRRmiw9j80WIGt7oX8+7sDl6TGBkbLUVlkOOWVpfCaTNSUb5P7ZDs37rH6KImSkbXEWYLdoyCZiwmwSNXX86fekErLilKUJ+TzZdi2nIUtToaqoP9On8j4UAjsn21i9ZExbKdwZ6CpL+z5SA5hx6rek39Pvrr6/a3kpyz9F5Mh/EID1SL+j3QD+bcjjYjDqg5r+AJQpD7RQIIsZlxX1m+TClfZK4DGJTjRzCFlyHv1EQugkzYyW+eDQVYuwde8MtuyZQSMgtJV7odpeVCH0KmmqmrI0QaC4BmV2m6nvcmrIjNdQCCg+/lGELEPIgvgcPhGy9EtZ7JGylJCbJJm3RrOU8xUhpZ+qD5ktQpa+FwLYPtnGcQcsx2O7ppL2xKm/YspS/UZdC07Seysc7SmC5LurOJwRgJPaCiH+RQixDsBfCyGOFEKsi/97hhCCCRljQUM43tcJCzlCJoTAR75/O276zQ6tXWpWykTIIg2ZR8rS+Gv+fS96cm6/EzkRMtn/o7um8f5v36K1u4iOy4fM3H/5ohauev8LcNvHXoyACA9s2ZdsU8tsVXl89FWR+ftmNscTbtbMFc6i4K5yR0A0qWcMUZVzP7J9MtEShiJLyOSKRDchQ3KzVZI8YUTI8oiyaWlhFfVXjJCpxrDZ86bohQI7JztYubiFfTMpOZcltQazyjJ/vDYDX1d/8zJlqSAkopXyQ5y+/PMhjonBGHnoxrBzN45+4DIkXQiY6vTwlWsfxus/f43WPpYQshLGsBYfsiINGQH4yzOOwX5Lx539TjTzVlmmb7+9fqN2XhfRcaXj5Gc5MS+faGHRWAPLJlrYboi5+09ZCut7G7K2FymZ0NtLaMjUNFmQpixJaZPnPv2Tl+PtX1kPwB4hk89KnlO/HJJKxheNuaN2Jnx8yMogrZFpGMPmICJkbaxaPIZ97W7Svn1fGxOtAMstPmo+UM/qGsPKxS382fOPwlf/5Le19jT9nu2jzn9n+hCytwkhdsoPQogdAN42vCExGKMPTdRf0xiZa3XfQoAkR2baVk6OM2VWWRaQLwmVYFBOdEIiV0OW0+4iOrZJLBpX9CqJxfJF7glWK1VUKWWpnrecqN8pIaM8Ubg7QqbYkGWOl7q5q+7dAiC6bpM4yQhZXi1LeY3qfSuVsoxf5fH2fSVR9aFreoQw6tOyl9LXzqkOQgGsWjKGM459krbfgSsWVTZizXwXttES4YMvPRZP3n+Z/ViRbavr7zHgR8gapNxxImoAGBvekBiM0cd8iJAtpJTl5698AD+94/Hks+va5QQ6UyJ62Auzqyxt+jz1nLYSNSbM1JY2Tsf4hSVClkR/HKJn+VmO2beoeiUfMuW2Fi3yzRAy+Wqmr3LiRq76k0Akxlc1VdH26HWqrRNym+1FqyBCpq54Vb97M/KZR8oTb62BpSzTY/KKo6stsgbrqsUtfOTM43Hd356RbDtg+YT/yc1zeKQsXbCvNo1e6/p7DPgRsksAfIuIziCiMwB8I25jMBYs1H/znV6ITTunrPtNtrt4zzdvwta9o1fcwmVIOh/xjxffnaSfAHd0MImcdf1/1UOR/ZvcGiFTbrecPPKiI2OGNsenOkQo9MiTj6jfnMD2W+ZOo+Yd53VMGVG/Z6RDtfYw4ao/CcQpS0VTpb7um+lqx1lTlkUaMsBKyEzNVV6EydRF2chnonvzEfUnUUay1oM094vOHb2uWjyGZiPAk5Tn48AVfRAyDx8yF2y3PBH11/gPTR9C9kEAlwP4s/i/ywB8YJiDYjBGHeqP3xd+8RBOO+fnmR9xAPjujZvw/ZsfxbmX3jubw/PCQoqQmXCVK+ol0aJyETKTXNiO133f3NEJCXOiV78u19wbKia1px29BscflFpYuIxhTeJz8MpF1r6XjeuptkqrLEtEljORvryUpaOPjN7MGSHTXyfNCJnFqb8oZQmFqKvPR8uIkPn4eMnHyR4h8yczmu2FQUaNXjMtKxe3Muc7oB9C1ocgzl46yf581wmFhEwIEQL4bwAfEkK8VgjxeSGEv8CCwZiHsE0me6azhGyUsZBtL1ymuKm2bBg+ZOl7H+8pM5Ki6bccbEbVkH381U9zlE7SjzGHqhKyi999evJ++SI9lVlJ1F/i+KzthYtAZFdLpucw9tQiZFlz1CRl2TEJWfY7G4+/H5ennPpdqN9dduWnfezquGTUpx8SA9iF9L71MVcvySqVzGeiKqpGyOyi/vr+rvk49b8KwM2I05REdCIRXTjsgTEYdUPbUoB3lFE1QnbVvVvwH1c8MODRzC6cETKH2D8PPUvK0kb41FRKQgByfoGzEbLiMam2F+Ykl34WmWNUuFJSgyBk6jFFi0pcETIzepMXIcsboywZZDuHGu2e7vSi4uIuUb9LQ6ZcgHyujjtwOY5cuyQzDhcSUX98HbZomktbZ+1PIWG+xrASKxdnCZnLFNcH6n0rrSGzRsii1xrzMa+U5d8BOAXATgAQQtwMYF3RQUR0KBFdTkR3EtEdRPTuuH01EV1KRPfFr6vidiKizxLR/UR0KxE9s/plMRjDhe0ffbtXr8Bx1dJJb/7S9fjEJXcPeDSzCxcZCCtEyHqWCFmRqN8Uk9tg1gjUtWEuUX+qVcsSsnQf8xhtP2WiVBcWrDQJWYXHRz1XWdsVU+eVtMNNRvI4XyMgtGJGbEbKVFG/tP5wpSx9nPp7SdTyqRmz2lwfsnibfF5t56riQyYUX7UiDZmEWRQdqF42CdBJX/kIWXodZludI2Q+BiIdIcQu44H3ueIugL8SQtxIRMsArCeiSwH8MYDLhBDnENHZAM5GpFN7GYBj4v9+G8B/xK8MxsjBJjhu24TgI/zjsFBsL6zpw1AnN/L3rVuBkEVfsX4OWwQutEweefOZOdnpKUv3WJwr8pz2DNH+Hz3z+IxNhLqwYEVMyMabAWa6YbVVlsp9Kv/8kfL/SmtOhCxP6B4QZa5XftqnEDLpSZexvUhWWbrOnV6vfB6IKPOd55ERua0XP492p/4sOXFBXYnoIrgu2FKzfREy5dCyvdgiy6lTf31/13wI2R1E9AZE9hfHAPhLAFcXHSSEeAzAY/H7PUR0F6IamK8G8Px4t/MBXIGIkL0awJdF9FRdS0QriejAuB8GY6Rgj5DVK2XpStupuH/zHnzxlw+h2xP48JnHJ5NynWBLJauEa+9MF8tiqwf5Y95vhMwWfdQiZPHkkTcZmzUCNVG/429i1WrBWfTa8fnVJx6ENYZRrdqH/O5XLR7D47unK9UMVA8p++/FHSFza8jy0vIBUaLTS20vom1TigHqjKOI9lhc2irvPsvrVUmyO5WcRSZClmP34AO1nmlSHD2H5KnH2chgXmH0IqjRvrJeZjYB/0Ixhn0XgKcCmEFkebEbUY1Lb8QFyU8CcB2A/RWS9TgAWT7+YACPKIdtBBcxZ4wobP/my7i7jwJ8UpZv//J6fOP6R/Dt9Rvxhase1LbVpYivjZCpE7WanpLt7ZIaMvOvclv0xxpRiuchcwUjkDU1DbWonn0sqoYsE0lyHJsKxvMnxRXxKju52q7K3x/quctYi6gwyUI07Iopy4bUVMm+ojdqhEwSMpcxrFPUr2gLVWNX8zbnivqN4/vRbAE6acktnWS0uQqID0pDVpbX5a6yrMnvkg0+qywnhRAfEkL8lhDi5Pj9tO8JiGgpgO8CeI8QYrfRt0DJVapE9HYiuoGIbtiyZUuZQxmMoSKPkPW7OmoY8EkZqeM2CUJdUp62SIxKRmcUwpb6kJVfZbnf0jH8xQuOio63nFMlVGaNvmWW8jPmRK8SuryUpdxkq/kIZKNr6f72PiUkaVwav1ZbZZkeU9YHL9HdWTVk9mPyRf1AM4mQ6X2rJL2dEDL9+HEPp35JDtKFFn51GZWNANJ/a3mLQPxE/enYco1hjSZXarJiGcvo2AFEyFTIporS2JGAM2VJRD9EDlkSQryqqHMiaiEiY18TQnwvbn5CpiKJ6EAAm+P2TQAOVQ4/JG4zz3segPMA4OSTT67HjMCYd7D9FVamIPUowCdlKdMy0Xv917fdDSsXFp5NqITsHy++C6995iHatVsJWZmUZRwJGWsEOHTVYgD6vZUaNZVQpSnL6HXpRBPYpffbbJgpS/X7coj6IbTJX0WqNdLb0zqJ+ZOiLOUkn4NqtSzT96UJmYxiZdrtIz945SK88oSD8IHv3GrtLwiUlKURIVNtL2a60XuVlJyybjVedPz+mXYVasn5rhIhKyNgl3uGyvGZfUpwGXmnQiEKInP6Rtc1lhXju44tHyFzt81XDdk/99NxXG7piwDuEkJ8Wtl0IYC3ADgnfv2B0v5OIvomIjH/LtaPMUYVtn/y8oe7Luh5/CmpkjDTOb7dDbHEz9R9TqGmLD9/5YP40S2P4Z9ee0LSpn5vVY1hI5E0JVEHU4DfILtTv5z4llnKFZkRMvV4tzGsQrASi4P88cs/LqiAW8v+JInp1/aitIbMUbORyH6N//aGk3LrgTaI0Eq+r6hN3vK9iu3FTCebsvzXPzopWYHqLp2E5Ieil6SFy5EPLw1ZCUm8WToKcDxL3hGyflKWyulKdkOWsbuMj+sEJyETQlzZZ9+nAXgTgNuI6Oa47W8REbH/IaKzADwM4PXxth8DeDmA+wFMAnhrn+dnMIYG24/YTN0iZB4px3GFhI0bEbK6lF4yNWShEOgo165ul6SnjIYsKp2kRzDUe9OLy+70LClLOREttWnIclOWeaJ+e4RMIiPqTyJk+ZBRGknSXV//+oe344YNO/Cnzzsqe+4BRMgy7fH/TBSRhWiVpbyWaCySbKomzzOWlKU6ltyUZfw+0emBSgnhZd8yxZ4XIfPRTiXWEGG28oDWp/F5GIRMPbZ8yjJ6VVPg89r2gohug51sEiL51wmWbQmEEL+E+9/4GWZDrCf7i7w+GYzRgSVlWTJCduNvduDXD223TlyzAZ+U5XhLiZAZhGymJka4JiGLyJFdQyYnvnIRMgCxjYDkr90wS560lKV8zdGQZYxhPUT9Au70lmviNsmkC12DkLkmvj/4j2sAoPC5Livqd2rIHBGyQkIWpF5vkqDLKPCuqU6yny1lqeqfclOWxncfBPb7/OFXHIeJVgMf/v7t+rXFr4NaZZnorATQTCJKPkTO1T6YlGXZXmz3YT4Yw+alLM+ctVEwGDWD7R+9TdSf99vw+/8eucfMGSHziJCpaUrT0PLvLrwD573pWRmt06jBNOxtBqQZt0pCJoRI0n2lSydB1wepxyfWB1bbi+jVRsjMqIFmDOsYi3oNGULmGn+S4nTsEOPoJy0FAJxw8ApcdOtjlYo4q9dQPkJmT8GSpQ0oJmQNRUMmTWol2VSd+uXzoZVd8iFkWoQsPc62+5+cfiQAZAmZJFAJyXZfTxmn/lCIXEF+tq/hRsiqGsPa2uocIXN+JUKIh+V/AKYBPD3+bypuYzAWLGz/5Osn6i+nITMn4J/fvRnrH94x8HENGmYkLzDShzKCpl5emVWW0vZC9ZhSo489W4Qss8qy2N/Np5ZlKJRtlkgS4HbqL5oUX3T8/vjJe56L15x0cHKusujHh0zCZnthS1m67CgkVGNY+ceJJGi2VZYuAuF06lc84dKUYznyIa8rXWXZn4ZM7in/gIjG6d5vzFj0YKKfCJm+yrLcsbb91ehfXeFTy/L1AK4H8DpEeq/riOi1wx4YgzHK8I2Q+fU1N78grghZLxTYORmVi1EJWTcUGVImy8qMMswyRs2AtGuXKSnVCqOMhuz8qzfg2ge3gaA4q9tSlpbSSTJdtKjlFp+n/SgfXClLpV3O3UUTttPZ34KnHLAs2a+aU38Kn5S5DdmUJVkDOEVkQTWGlWORz/u0bZWlSiCUmTM/Qhb1m353bhNbK+S9HnDpJAhhNVeVkG1m+S4T/Yn6+4+Q6c97/SNkPk79HwLwW0KIzQBARGsB/AzAd4Y5MAZjlGHTXeRpqvImxW4oCn/4hgGXi/n/d9Fd+NKvHsKd/+clWsqyF4aZqMbWGhAyU0MWEGnRQbkYQ13FWCaddvfjewAA6/ZbkqSBOkpnksTaiovLsU14EbLilGVecfH0WENDlhjJ2vf/59c9A7/Zti/5nK7Oq0DI+kpZxq9mu6UN8E1Z6gRaflYJWTtJWabHapYNHk796XFlI2QR8ldZxucrUTopMoaVx2X3k89QqxkA7Z7z12tQaoVBaMjKLG4YVfgQskCSsRjb4Ofwz2DMWwwyQtbpzY2fl2tCvOT2yG3mwpsfxQU3pVaA3VBkrvHRnVPDG+CAYBKyZkOPkEmS2euDLABSy5RNWcpT2UT9KSEr/v79UpZ5GjJ7iipNWdrP+9pnHaJ9tkUBfaEeUtX2wkSzQVb9VPEqy9SBXkZH5UriqU4viaTaSifZ7CNMRMaw5jnL+ZCltSzdUcxyEbJ4bEiLi9v+uJSkxvRpc42vX5RdZZmQL8tYaszHvIjVJUT0EyL6YyL6YwAXAbh4uMNiMEYbdkJWTRNjptRmC+qE2gsF9kxHK8uknuns792mEZdeKDLXuGlHDQiZIepvBIFuDBuTTDnpjTeDauk0SidnldBJ8qRG4JK2+DSulOUVf/18/PPrnqEdA+SsshTZFKSccF0aMtO3rAgyIlRNqzOACJkxTmdZHw8NmZmylJ+nO2FCzuyEzE7OVNhIs0vU70LGhyznOyon6s+vQymfVdN70EQ/KUt9XOX2t4v6o9c6pyx9Sie9H8DnAZwQ/3eeEOIDwx4YgzHKsP1VaZtgfH4b5srPSyVbH/7+7Xj6x36Kbi/EknE7OehZImSqPcCoImN7QbDaXsgI1qKxBtq9sHTqg5CaXZ576b1Ju0xV2kofnXb0GgDATsd9PGK/JUlRb80Y1jGGyGoheu8q0WMem9peODo1kEx8BYzMdv90H7Ly91d9lWg17LGzMilL09JjqtPDeEyS2wWrLF1EKEpZ6tcYWXSUSFkmGjJ7gfN4L+/+VJ1VYAszxeglETKKz2A/R7+1Nc1xld5fGfu8Li5OREcT0WkAIIT4nhDifUKI9wHYQkRzs06fwRgRuHQXYSg0l28fzBkh66UT8XfXb4zaQoGljhV/3VBkvNbq8Ntn8yFTyYDcLiOGE3G5qLK1OtV0lFqcOhTRxKxGJOVE/f6XHIvfPe5JeOlTD3D2K4MUoUboHCnL0M8iQTumZISsEaSTeh5sKU1tJWvOc28je2mETG9vNgK77UXB9TQC1Rg2JmQWI2SbqF+9t877LLJ/tkUrcXOHpe+vrLJ0kbkqPmRC5N8f75TlHEXIbIG704/ZD88+cjXOftmxAxnTXCAvQvYZALst7bvibQwGQ4EQwD//9B487e9+gt3T/pGjqqvN+oXUzahnv+Kezbjq3i3W/XuhyFQjqIOANmN7QbrtxUxiexETsljPVSWlZvtLv6fouiTk59VLxvCfb/ktHLHfEm37kcpnOQlrqxodt13VkCW+XUZ0I/OdxZYdvghs47GOJdumUhSTKKuw9Z36kJkpS3v8Rk1l7rd0zNKfYgzb0536AYWQdWR0Kj1WT1mWEfVTqTRfGiETzvOUEvUr++YEyJLvrkjbWmQt4ouy3diI6eKxJr759lNx1NqlAxnTXCBP1L+/EOI2s1EIcRsRHTG0ETEYNUUoBL4fi+B3T3Ww3MNbCqjux1QGU+0eWg3STFz3zUR/+avL89/x1Rszxx7zpKW4b/Neq6i/DnqNjO2FIuoPSLW9kIQsipB1ugLIzuNOuCbbMBSZaFGeIP7yv34+Vi9JTywjGZpTv7O4ePqdZIuLp/to4xPlVrn5iqdtz4ZsiqKUOYSsRHRyrBlYJ2jJx658//OTtK+KhqohC1P9oMR4HCmd6WVTlurpXGRWLamVjKlA1H/mCQfilc84KNPeC4UzolUmBap+d+l7WyQzjpDF98N1hkFFyMqusxzUYoJRQx4hW5mzbdGgB8Jg1Al5S8WBcj+SsxEhO+6jl+DlTz8A//7GZyVtqht53vzXCAjNuNzQtFkXsgZeuCYxiET90cCXjDVTY1iDkJUlyssnWtbVkqrQ3jUmFeuMaFmaIlSOdwxNKGkyWxHuaCfjGIiSk3r0WkSa8gjZeDPI1ZDZjnVpyJpBkKshO3zNEsvW9LkGssawQFo2LImQOXRjubUsMxGy/PTcv73hmcb+6fgcaxesY3LvE72GIn8c8qsdK/IhG5iGrNr+PmWf6oS8r/gGInqb2UhEfwJg/fCGxGCMPmw/BHnzU97v1mxpyH582+Pa573tlJDlTa7NRhT5qWuEzIwANCidgBeNNVJRf0LIqqUsVy5uWf3EeiIbIbNFbFwgCwFyTURSr2ab4MxVl8n4wnITq6+GzPZIyWPGmkFupQjr4+jUkJE1wFKUGiSi1PbCKJ0ExKlQstey1Pux9y+QjUZSSdsLdZWlM0Lm3Zu6sKMgZWkscnCRvcGtsqwWIavBz08p5EXI3gPgAiJ6I1ICdjKiIP7vDXtgDMYow/ZDUFVP1U/KstsL0RMiSa/Y4CJb+zwXHzQojpD1soSsDj+I5uU3ggDdMEQjIEy0UkKWrrSLRf0lI5crFrWs9hWhEIkm6gMvfQqee8xaHLp6sXe/ScrSw/ZCGsPaJn3XSjkhiqMvWj+WFKoNeSR/rBHkVkOwHSvHb15HtMoye21+on7SztfSarcSWkFgNYZV4SJYoVI6KbkGh87QBXldvTB0a8gszb/4wAsw2e7hJZ+5yhhr9CpEvll1QpwLNGSDSh2Wj5DNz5RlXi3LJ4QQvwPg7wFsiP/7eyHEqUKIx13HMRgLAXlCWKAcOXNN/EIIfPay+3LNV//oC9fiKR++JLd/l3jal5AJIImQZUT9NUgZ2CI53TAyxhxvBrjuwW349g2PKJNQGkUog0VjDSwasxAypeTURLOBpx28olS/toiUa2RRejR/wsr6kLkF43ljKpJ55dlejLeC3Aik7VjnKsvAscqyyPaCbClLPRXZbJDVh8w2rgxE8n9an1V8yHqhcOq1UsPf9FyHrl6MtcvGM/vaygvlOvXPkg9ZaduLeWpN7+NDdrkQ4l/j/34+G4NiMEYdeUJYAFj/8A58d/1GL2Lmmpge3jaJT196L/7sq+udVQB+vaG4uLeLkO2d8assEIqIvPRCkaRvvnLWKTjx0JW18PzJrnAU6PUEWgFhvBXg0V3TeP93bk2iJDKNVXRt5hwy0Wo4ImRKLcKcCezqs1+Iq89+oeU8ehQHcBN+IdJC52kHxj6W8ZX3gaq2ylKNvOTaXliOdY3Q5UNWlAYjSr+PriLcl2k6qTGThCwgwpP3z67gK7fKsqQPWfzaC0V5Qpizr/qM2FOW0WurWUTI/M89SOTV4awz5inPZDCGi6II2bu/eTP+6tu3ePXlSlnKCeuWjbtw7EcuwfqHi8mXDTNdO/GabPtFyMJQpvmzuYuWAAAgAElEQVRSp/4TD12JZRPNWmrIurFXXCOgxHMMQHJ/D10drVkqe23jzcCqIVNTlnmr0g5auQgHrcyul7JGyJwpyzgdlachsxDUshmggKiSD5lsGWs2Sq+yTCNk+mDNCNlfv/jJOP2Y/XLHBkjCpa+yBNI0XSOIyJn89xMQ4dt/+jv4yXueq4/L0b+6wCK9hupO/UWkObOIw7ZPMjZ9nCbMlGXZdG1ZVDaGnWfwqWXJYDAMDFJD5kpZ7jFSijds2I5nHb6qsL+pdk9LnbmKnpdJWTYDQqiI+idajXhS9upiTmESh1s37sRV90Y+cep9+uEtj+LYA5bh6YdEC8zLfp8TrYZmmyDRC0UScaiyKi11xk/b3CnLKD2am7LMFBevNiFWc+pPxeKdnoj9sLLnzrv35t6tZqDpoc484SC884XH5I4NiFOWhoZMjg0zccoyCBQfMsKKxS2sWKwvyHBFvOQCCxWli4sr0dGy0Sg7KU8jS67KDYCasizW4Q0C5f8gGMhpRw4cIWMwKiH7M5YnYs77/XBFCvZO64TJhx587vL7cdxHL8HOyXbS5iJke2e6WGzRPJkQccpSOvVHJWcCBFQPY1jza9k5mZr2qhGtJ3ZP4+gnLVVE9Pn9mpd+1NolDnKRpveqpHhsRqzu4uLRc2IV9eeIz8tOcD4aMltKM4mQGSWLfI5NRP3GWFvxakh1bD4gSo1NVQsOSUKk6F9GsF3dutqFGMAqy/i128sxhnV0Z0vkplFSkfubZBrDcoRsdsCEjMGogCIfsjJwEjIjgpXXvYxW/NNP7gEAbFIWAtg0ZN1eiOlO6G1e22zEPmRK0WXySFuNAvLGqBKybXvbWDbRrFSk+LfXrcZLHOWPekIo5YzKTyRJylLTkNn3lass1dP8zcuOxVFrl+CEeDHBIET9RD4+ZNk2NUIGuKPDVg2ZS9RvlE7yJ2SpUXJXCT/Kscni47L4vCvd7GpX64om+1I5QboaISv97Fh2t9pF5HxPsyXqr5IyB+rxB2EZMCFjMCqgSENWBi6DzAwhy6Sa0s/tXqgV+t6+L4qQXX7PZlx21xNJu3wvay0uX1SsWgiVCNlMt5eQmIDqYQzrCi2+6hkHYZFi5LpnpotlEy3F1iGnS2MiePaRa3IjUD6ifhfSlXHK+XP2N1OQJx22Cpf91fOxOC4abxP1l/WBagRUOBnaUpryEDnRdxw32VrLMnk1NGQNgso+ytzjFYtaOOGQFfjU656RtLUSDRk0UX9ZHzBhTVlWjJDFNi39QvZQpBtMjGETp377zoNbZVlu/7wFCXUGEzIGY0CwiXh9ICNk312/EXc8uitpz6Qsjc6nlJWX7V6IB7fsTT5v2xsRsrf+16/xqUvvTdrPOv8GAKl+bJlHhCwU0cS0cccUvnrtbzChRMjq8IPoinSd+79OzIjwl437RciykY8czZYi6q8ygckghZrGc5Gh1Icsuy2ZVEWW2FfxgSpeZelOWSYli5wRMneILJuyrBYhk/te+M7n4Izj9k/aVFF/sxEoKUtXytARIbOK+stqyKLXvFWWRceqsJN7t6hfpm+HnbIsWzppUERw1MCifgajAuwpy2p9/ezOJ3DAiolkVeaGc14BIBshM7FHIWztbogHt+xLPm/dO5NzXCc5dtXiYkImhECj0cDNj+wEADy6axoAaqshAyLi1QgoY1OxdKLp5QJubsqbH3oh+kpZ2tIzeassncawjqhClXSYz4IOq+2F4QDvcuvPs70wR9o0bC/6LeeT2l4EaDUoudeuVKPrdCL5vxQBEQT5/5tJCJmIbFrKwLa3ZnuRawwbvc6eD1nZ/ZmQMRiMGEU+ZMl+Hn1ddvdmXHb35ky7uQrSPOduJUXZ7oZ4aOu+xC9s2742XLh90+7kh3Tl4uLq2XKVpQkf64NRgG2My+PSReNmhGyilUy8+REyIxWVM6OEfUbIElG/V+kk4axT6DpzKMqPK0pX9xEhk2J6Rx/WWpZkvon7ahii/oKVgUWQz3qDss79Nqxy/Bv68jUPa6WYgOg7KOcbFi9+6AlMNMtGyGykPMvKrX9cGpULXGceVC3L8qWTBnLakQOnLBmMCvDVkPXDV0zbCzOYsHtaJ2Rb9sxgzZIxHLB8Alv3uCNkj+yYTMicT4QMjgm7LrYXtu9A1pI0I2TLJpqphiyPkJU4fximGrJ+RP0qIXPp23o5VhISg/Ahi1ZZ9q8hc0bISqxYbjV024t+SYIU+gdGBNX13a3bbwn+509PtW4zF9QEZC/z5EKqIauQsrS0BQofc/nSASVKJw2IQZTXkBVHsesIJmQMRgX4+pC5fi/MCWfNkv+/vTMPk6Oq+v/39jb7klmSQPYNAgGyEJKwBlnDvgkYFBEQ3EUFX9GfIIi+8iqKIgoCIossAiKgIiAhLAkQkkDIRvaF7JNlMpm1t7q/P6pu1a2tu6q6Z7pn5nyeZ57prr5Vdauruu63zjn3HPtTtjWGzJrgdU+bYQVLpBUkFQXRcAgNVTE0ZRBk8WRaF3NeLGSKS2wcY72juLhTH2s1IWrNG6bGkNnjbKz4iSFTuCGgAlnIQvbBx81ClkgrWlC//TNjELPGkAVLO5CtBKvjA4rWb5EB3m1Ci9O6bikYgs6ydENPe8GYXmgeyPwdTRtV52nbjKnbP3RQlcf2hhjPdo6s59Wp+aDqUgDAiPryLGkvzK5lN/I2y5JiyACQICOIQGQKhDW105ZZLRbW2WVy3TnxVG2NIeuy1JHcLYmuREpBWuGIhhnGDazCJzsOuPa9K6lIFjJvLkunJLKMsV7xhOrostQmM1jv61WlUSmbeSYLmXX2nPH6u6cdYtt/bnnI1P/moH7ntomUgkRK0TPQy+jHZVkeJA9ZKJQ9ftAxU7+YveeQbiLbusKqabOQhSwxZDkLMiOov8RkIctpswDU3wxjDK9+96TsjWEc6772RF6sUcePbcBfr52Ob35mrL7M6V5mtWS6WVwpMWx+IUFGEEFwjLtwdgc5YZ1dJifIXLRpH57+4FO9vI/g4fkb8dA7G/T3siCLpxSk0qpb48ghNWhqjWPXgS7HfXcl0zjgI6hf4dwkyL5zmpoFPdRrLGT2ZRUlzuGzVaW5W8huOG0cKqSEu2meo8vSKYbMpW/xlIK2eApVpfbjc3NRBatl6TzLUhZpzg8o6v/secjc4/6sqBayPLosQ84uy6DiI5fumCx/WTZkL53k3P6EcQ0mq2Iml6U+y9Jln/mLIfPbvm8qMhJkBBEA5xgy9wHIijVDuRxLc8VDC3Dz88uwZV8HGirNFqzH39+sv5ZnUibTClKay/IILQHoyu3OVrKuVBotnUmUx8IodcjUf1BNKWZPG2Y6BuE+ffhLU/EdzQIU6iUWMiES6itimDFadS1VuOTkqi2PGnE2PtJeWMcHefDmnOvbys1lmT2oP5FW0J5IOQpOtwE6UAyZS/xgNtGouyyzZOp3WrdaE5m2WpZSED9jmSdYeCGIyzLj9nIwbcnnzO9PLXt3met2e36WJQX1AyTICCIQmZ4qZdxyNQkBdtHkIZh5SKNjNv0dLV1oqCwxLZNvgFaXpbCQCREnJ4qVES7LmrIoKh0G7mNH16MiZiznHGjTCpHXSFaKXhNDpgCDqkuw+JbTMaqhEoC5hqVMTZmUGDaThcwyjFlFgjyQpRVjW7mkvfBiIUukFLR1pRzPq76u9X3ATP1OgfeywHK69vWEo2H1+3cL6ndaV1x74wZWmpbLecicZgP7JSK5LOXi80GFXiSHWZ/yLt3i7YKSOTGs5QHCpW2+LFVBJpX0RUiQEUQAnGPI7O3cZouJgWvqyAEYVF1iqjcpu7usgkwecHa3xXWrQSKlIKlwRMIhlGtiqrXLTZCpQf3VpVHHWpYhS21A1cKjvpYFWW+xkDnl5SqPatYWS1u11qD62o+FzDo+CCul2L8QU0HGL91lKe3TTQgLl6WjIHM5LkXxLxTdZlmaZoJqn7+4ZBvW7mo17TuqpXBwD+p3d1nedv4EPH7tNH25LHjykZ9KpOQIMWYS7kHdczmJRJMgyzyLwktQv/N69mXivtVTwodqWaqQICOIAHi1kLkNOOLmGg2FEA6FTBYyeR27hcz4ye7vSGJwjTprKpFWkFYUREJML5EjF9GW6Uoq6EikUV4SNlnCBCFmfvKVj6CmLGZq1xssZBzGDVx8z8JleYZD/UlhCclsIbOsYxkg7r1iMn5y3uHqdhTJZRlgIGHaKTe7LJ0H3EQq7SrI3HYdxGWpzrJ0sJBJ1y7nHMm0ghueXoLz7p2n9xsw3HizH3wfx/z8ddt2nMSwmIhRGg3jxHGN+vJIyEglkQ8LmVw6Sa7kENTzmM3tlwnZZelmTQzKtJF1qIiF8bWTR9s+ExZKcV13t/zxu/0+qsdIkBHFw962OJ5c8Gmhu+EJp7HaSZu4FWCWaxvK9fIA6KVaAKChyhxDJt/b2+MpfZZkIqUgmeaqINMGkf1uLstUGomUGm8mxJt5H+a7nSy6rBay3iDIZMEhUocIy8fBtWVY+dMzTe29lU5yn2UJqLM1jxvToG1HGuCClE5ycVk6ibtESkF7PO0SQ2asKxOkuHiIMby2chdG3vxv03J51mRaAbY2q0Xu9RnCemySs+tdXteK00QFQMxc1PqVF5cl07clp0UJapVxc1mecfggXDljRMZ15V1mc1n6dR8OqIhhxU9n4egR9pQdhos92Lb94j8xbN9UZCTIiKLhW099hB/9YxnWSzUZixW3TP1WV6ZbDJm4uUbCDJEwM4kwmUaLhawjbuQi60ik9XxaIu2Fur0QYuEQmjucs/XHk2mkFI5YOORiSbG6LI3Xcl4i1osSw1otZLKrtkSLEzpkkBqbFCgxrMMAIcSzyJ4P5JgYlputT07iY+7q3ZqFzC603Yuf+7f+yKJdfoiyuiw3WH7LRn4r5xg+azsZa91RGdGbvFrIcnBZnj/xYF10ulnIHvjiVNxx4REZtyPv0S1FSHeQyySUIPjdTb5mdxYbVDqJKBpEQexssRLFitMg4hq0LJUmyTSI1Fim+gurF+cc7YkUajUXYjytIJVWENEEVnlJGC0ZXJbJtIKq0ogpaFkQtmQTdxNdjPWWWpZGnq24LsiMW184xPDUdTNw6GA1WaenWpZZYsgAs7BTdBeQ//47pSfgyDwoVbpYk9R1LTFknPse4GQx+KN/LMMxIwdg3KAqU1C/onAs29Zi3reDhcyJbGWZAHVGrHDLC+HgRUC88z+fcZ3wAkilk3II6j9qaA3W7GrFqp2tubkspfPiN6g/FyuS+PrFA9vYxsoMrXPHr4Wsj+oxEmRE8eA2lb8YcZwq7qC93Kb1i6fdEGP6rC4nZOHwmUMb8daa3VAUrmdkr61QBdtf5m1EWSysD3Tl0bDJQlZXEcMvLzkKD8/fiK5kWnNvhnS3jOwytQ5q4wZW4oVvHKcLZoEaQ+ba9aJBzrMlXJbWyQzHjqnXX3txWToVjbYSlgVZN+QhyyTk/bks/Q+IVj0lrnO5j3vbE7jvzfX6+45ESv/asmWAt15XL3zjeFubV79zErY2dwAwJ3PNxrC6cgzL8LmohRlizBxD5uMrYozp11guVjvzLEt/D6rRcAhPXjcdVzy4wPd+xbU/vL4cj14zDUePGOB7G34IUjqpsaoEN5w6rns6VCDIZUkQQXAYq52sRWKAcprZBqg360w37ETacFFOH10PhasxYCJRq4gh27CnHbsOdOkDUnlJxBRDVl0awWmHD0JpNIyuVBrJtIKYNtPNWj6IMeMGOWN0He6/8mgMHVCOicNqTe3UWZbFr8jMMWTqF2+tYSnjKTFshkz91u3IaS+CuIDEOrJAVFxclgJrVQdAsrRZlvMAmfqtxyGOVX4A2XWgC/GUghPHqbF0339uKa57bBGA7DUSrWJ4kuXaA9QyQCL+KRcrlBUhgMMhhrJY9uLiTjAYD1OZHriybkfapVsS3UyIOEa/6LMsGcPMQxozplHJB35LJwHAwv93Gr6QJQavt0GCjCAC4DXthRigrJ8JC1k4zBzL3IyoLwcAVJZEcdTQGnz95DG6cEsrHB0JVajVSTUwOxJp/eZfHjO7LMWTfmk0hK6k5t7U9ltiESdhKYbs+DENNrepoPcUFzeC1uOaUMkYj+QpqN+yjsOAIm9HbCuIq0V3fVqD+i0CQX4fc3AJij7mI6jfvm/1f1oyE3cl1Wt03EDVFfzvpTv0z9yuKYFb7KUbIo1GPq5H+dhMLksf3xFjhhU2m3s2y5b0V24xZI1VJSiJhPCDs8Y7fn7iuAZcNnWor72Krz8fkyS8wEiJACCXJVFEBHlKKhSOMyodLA1p7anWFuyvjRyREHOchfXtU8ahLBbGaYcNxOmHDwIAPDxvo75uu5aotbIkgrsunYibnv0YXcm0LtrKomGThUwXZJEwOjUxJ/ZrtVaEpDQCmca33pQY1uqyzOQyM2LI3I/NetxOY7UY2HmOLkuxLVNQP+yiSFxTE4fWYPa04bZtuKa9CJiHTEZ0rVl6CBBWOvFwIVNXmbmGql/Lq7iG82GxFUemcG6pZenPQlaWB5ell1mWJZEwVv/sLNdtPH7tdN/71Wuv9lCwVu+583cvpEsJIgD6E6RpNiK3CTV3C5kxi8nJFVISDeHsIw8yxfYIAZVWONrjRiyUeAJXuFGHr6IkYornES66kmgY2/Z3Ytv+Tn0Q60iYC4eHGMMFkw4GAJx95EGu30FvSgwrvkYxm9XqppXx5rJ0XsdpWa4uS8BeqohnCMS/dOqwjG4yp6D+IHnIZMT1vEZLAAsYFrLhdQ6CLEtRe78TCoXAdksz4we5UkOQWpYTh9XisIOq9XVzy0NWGPRJKEWaGLavQoKMKBp6Y1C/fCNxru2njiyycGntSuKpD9RUAZGQ8yxLJzemXEJHiKiKkoiprW4hswSti5p8n+5rN9pqQk4M3kKkhBgwblAVNt15DsYOdJ9d1VsSw8pB698/czyiYYZB1aWu7b3lIbOs43AnFcsUzqVEm977LWMtVeTkshRki/ex9l1OC+IVN+vcmp2SINOskdVlEVsRe6ub3GrZEt/XnRcfiTdunJm1P0L05MNlqX8XnOtpZdTl3tZ/8RvHY/roet0qnUv8VaGKaOf6AOEX0mMq5LIkio6eGOM37G7DKb9+C3+7fgamj67PvoIFrg+wDEKeqQO4s+VAHnBufXEFXlyyHYCRGNaKU9yJHkPGzRYy2eUpXldYBNn1J40BAHz26KGYv26vtg91EPvrtdPR2pXEzc8vw7qmNs83YdZLEsMChiv5/IkH4/yJB2dsHaiWpYMtw7C0ccv14p9wyJwZn4O75g5zEwCZMvVHfQ68VuucuM7XNrXpcYqdCfVhJBYOY3BNmcmdab2+Uwo3LRPf18RhtRjtIeWCLsjyoMjEV5Hm3BSjmU0cPffVY01CX04+nGtfeppslSXevOlk7HPJcxgEspCpdJuFjDH2MGOsiTG2XFpWxxj7L2NsrfZ/gLacMcbuYYytY4wtZYxN6a5+EcVPPtwO2XhvgypKXliyLdD6oofyfcRpMDBmWRrL5Mzk4ZBz2gunZcJ9kEpzdCY1C1ksYhrI5BgywX+/e5Ke1uGiyUP1mB4xiB06uApTR9bp63q9OaoxZJ6aFhTFpwXISy1LqzHXafO6IFPkPGT5cVkq3H2wdEp5AchB/XZrlO9M/TYLmSq+2uIp1FeoyYy7pHi9YQPMosRqAbamdBBvvfbLcNvnQZBJpbMyTf6wMnVkHYZJ7llRMcOtwoAXChVXqycydlEIIxsqMGV496bC6I90p8vyEQCzLMtuBjCHcz4OwBztPQCcBWCc9nc9gPu6sV9EkdMTVhen3E5+MGLImG2ZjBFDZnwojzFuaS+cLBaRkDHomGPIJJel9lpeZg1gF65J637FOl4HwRBjmaP+iwQ5MawXgmTqz5yHzL/AsPfJ3B+3TP2A3V0tb8OJYHnILBYuLeA8kVL066tLmzwSDTMcdlC1qb3VQmYNWBfH6jX8SsRD+p2d6UTIw/n3gjgPTilIvFIow5GSxUKWb8hCptJtgoxz/jaAfZbFFwB4VHv9KIALpeWPcZX3AdQyxtyjiYk+jV+RtLOlC6+t2OlrHTGYBS8KYI8JUksnmdEtZNIyefBzC+rPtCylcD1gujQWdowhk0WYVZCJ99ZgY+Hu9DoI9sYYMi8YFjL3NvZM/fbtMymGzAiS9twNE3aXpfvsvWw5vuwxZNyW6NVLf2RE39T8dur+56xqUvsTCWFkgzmw33o+rBUtjDQhXi1k+YwhU//nemkL61pnMp2lZfExqqECAMWQ9TQ9HUM2iHMuktHsBDBIez0EwBap3VZt2Q4Q/Q6/g/xn738XW5s7sfEXZ3u+gRs5vYIpMicLWeY8ZMaH8j0uEmKOs7CcXJZ6glCF6xaFaChkdlk61M+zDtDiqddqpYhqasHrd9hbiov7TXwaJDGsY9qLPMaQWb/rTIH4rkW4xbqW5YGKi1u+0JQuyDgqS80WulgkhBPHNdpEpdP6cp8AHy7LSD5jyIzfWS6IsIGuZBqzpw3HcksZKS8USqg8ff0MrNh+oMcmFZCFTKVgQf2cc84Y833FM8auh+rWxPDh9lw7RO/H731wa3Onvp7XJ32jYLO/fQn01SwWMiu64JM+CnmwkDkF9YsBPqVwfbvWGLSwJqpkq1jUYiETg6m7hcxPUL+npgXFr+AIkhg2W6b+XF2WoZBVkHHbebrh1HEYP7jKFMckIwZXW2JYJffSSUJopdIKSq0u8nAYNeVRrP/fs3HcL+bggslDbNtLpCwWMkXsp+djyMQuc3V/CpdlZyKNuy+fFKwv0g0mH4XTvTKwqhQDD3WfiZxvSI6p9HTai13CFan9b9KWbwNM5cWGastscM4f4JxP5ZxPbWxs7NbOEoUhaFyXWyZrJ/L1FJw1hiydzUIWcplR6W4hSytctyhYY9BE7Fksg4VM9NlqhYvoMWT243DCU/B7EeA38WmwxLAOLktJ2OXssmTMlJuLwy6cS6NhnJUhb5xhIbNbo/yO9W4WskSa21JayA8H7/7wVPxglj2jvJuFzOtpi+XRZWkk9FXff+3kMWioLPG9HSHIOnJwWcrXy9ybTg68nWJFTDAiA5lKTwuylwBcpb2+CsCL0vIvarMtZwBokVybRD8jqEjy432UxU0QnBLDOj1RO8WQyc+D4TDTrVoyjhYyWZCl1UE0ZHF5GkH9xvpeXZa+Z1kiu2uvGPCb+NSTy9JDDJkpU3/OLkvz9eVk9RNVCNxw23WgPGSW9sJim0wrtqS72QqJA+4xZF4Tk+azlqU1qP8Hs8Zj0Y9P870d3WWZCC7IxG9sUHWJq+WzN/PsV47Fn6+aWrB8a8VGt7ksGWNPATgZQANjbCuAnwC4E8AzjLFrAWwGcJnW/GUAZwNYB6ADwNXd1S+i+AnqKlAtZN6mqevupID74rAPsArnNtO7U6Z++d4TZs6zLLMF9acUrouviEPai5hcg8+yLbF/m8sy5M9lKSdQDRex0yFTElUnvCSGteK0dVOmfqlYcxBCIWZ6UOlKKnqtREFVaeb6kALHWpY+9Yy13JcRQ2YXZG7f/UE1pUgpHLtb4w6zLLV1fQb154Mg59+JsjwE9YvDd7KY9wUGVpfi1AxJmvsb3SbIOOezXT461aEtB/CN7uoL0TsQ97+gVqsg8fm5WsiYxWXpOsvSxWUZdqll6TTA6EH9nGvFwe3uSSOo330gE9vJOe2FxbVTrCicI+IrhiyAhcwpU7/JZSmWBRNkYUsMWUc8pSeAra+I4QezxuPiKfbYLBk9hsyyXLUg+gzqt1nIZEHm7aHovR+eitdX7sKXH1tkCzcQ2/Oqo2OR/D0QMElI54IeQ5aLINP+99RsR6KwUKZ+ougIOsD7iSETg1tgQab9F+OSmgLCHndkZOo3lsmDWcQlqN9JpOkWsrRmIRPCytFC5v5ELbbjFtTv1U3kJfi9GPAb1O8lNs4+y9Iphozp+cP0mKiAho4QY/oEFM45OpJpVGqzKUMhhsuOGZZhbWvnue1trqWTUml1JmkyzVES9X6QYsKJNTGsPiu1AC5LUS6pviJzvc1s1JSp22nIUkg9E4aFjARZf4AEGVF0BBVJftyPad2VGNRCZhZakVAIibRis6rotSylAdzksgy7pL1wCuqXYltSimK4LEP2GLJMuaiEeLC7LP0G9fcOCxmHv6BhLxM+vMSQieWyIAvssmRGf7qSCjgHqgLUSHTK5ZsOEtTvYCETDx+lHi1kgDEJxc1l6T1Tf/4E2TlHHoSOS9K4YHLmElvZGFRdinuvmIxjA5RmE/R0TUmisJAgI4qOoHFdfoScaJt7mSZttmOYIZG2Czw9hkwyADAvFrIMVjM17YVhIZPdk2EPFjKxaasVTmzHq2jIV6xNd+O/dJIHl6VtHed2ouRRPl2W7VpheWEh87NFp7ZB8pDZLGQK161cfixk4gEiZRFkfl2W+RRkjPm0OGbg3KNyE3XieyFB1j/om5GCRK8m6CzLIILMOt3eK1YNIidtddqPbCGz5iHLJL5kZMtNMi27LKWcYw6JYa0IwWUdhHWXpZ/SSSh+QeY3MaycYT/TNk3ruMgiplm2xHUQdDJZiBlJVTv0slnBnqed8pDlKsjSioJkSt2wNag/E+KaSyq5zbLMVp2gtyLOOQmy/kHfvIqJXk2PWMi4sFwZ60y547948O0Nnta3xhAJcWTtupGHzFhmzUPm5J7M5MbULWS6y1IWePbEsFbcajXqLkufN//ekPYiWB4y9zaeLWSaZUsIuKADq5ypX1jIKlxqVmaCMWa7dv0KVtEfmZTCkRAWMh8uSyGkktbEsL4z9fdNwSLuUxRD1j8gQUYUHUEHeD+CTAgxWfzta0/g5y9/4ml9sZr4L4SQVUyKiQbyYvnWGmLO1jCnG7DQbWnNPWS4LCULmUvAvoz4yDPMZBUAACAASURBVGrN012WnmtZCuFS3IrMbyZ6L65Y60du21ctW/nI1G/8Ljo0QRbEQsbglPYiiIXM/F6NIROCzL+FzJ4YVv1fCJdlMSFX5CD6Pn3zKi4COOd4edkO2+whIjs94rK0WMj8igprc7fSLc5pL4ybK/ORh0xYsNKahUy0CZssZFoMWYYByi1GKuI37YU+G9FT84LhNxO9t8Sw5g/dtm+dZRl0XA1LLst24bIsCev78IpTUH+QPGTWOMOUwnWXZWnUu4VMXNPW+6RfC1lftSAJC3tfzUNGmKGz3E3M+aQJX3/iQ9z7xrpCd6XX0ZOzLMU6fmPJRGuxvnhCt2becMrUb7WmOD3dO1lcRLO0ll7AqQC5KFuTMag/5CwehXXNbx6y4o8h82cB8lTL0raO8/bDIQauuSwZ818zUiDXsuzQXZZBLGT2/Svcf7/EuZ89Ta0nnDa5LI1r76ihNRm3Ix5krEH94kHJc9WIPprpfczASgDAF44dUeCeED0BCbI88vmH3sctLywHALR0JgEAm/e2u7Zv6UhizI9exry1e3qkf8WEonD8Z9kOR2tY4Ez9PiqFG8WQc5tt2amVRanSZry5zrJ0SQwLeLco6G5RRUFaURytAgO0HEqZEsM2anX5rPv1ayHzkkC1GPBrAfLiirWnvXDfVppzLbVEcNEgx5B1JERQv/8YMsDe9yAxZMJCJq7BVNp5luVL3zwh43bEw4jdQqbtx2fH+poua6gswaY7z8H5E3ObrUn0DkiQ5ZH56/bi8fc3AzAsFIkMLssV21uQVjjunbu2R/pXTPxt0RZ87YkP8fTCLbbPAteyzCEPmV/Xshis41owssia7u6yNJZZB40yjwOrGATTCrTSSU6CTE1CmclC9oNZ43H7+RNw6viB5u3rLlBP3ek9xcV9ZqIXLTOnvbDMssyYh0zdVtAcZIDFZakJshpNfDdW+Sh8zdyKi/uMIdNn5KrXc1pR9IcbP0H9xixLe5/E9r1y/xeOxhs3nux9BYIoMigPWTehC7KU+0Bf3MNY97JjfycAoKm1S18mvo+gFhc/bkdrpn6/FjJra1FH0LoZY5al8YFVv5R6DIIWg6AY/JwsZCLLeKYYsrJYGFcdN9K2XFjVvIoXL7FWxQDn/nJ1eZpl6dlCpj5g+C1wbtuOHNQfV12WwwaU465LJ+KkcQ2et8MA28UbKKjfkktPnmXppZi4oCSsijfrfVI8lPkR0rOOGOy5LUEUIyTIuglxw45nEGQCtxxGfZlMiTKDuiz9WNaEQUysYs0UnhVLc+GytOJUzsl6fE6xYE6YLWSKY6CvsNT5GRT1fmjb82rJMSxJxa3IOLohhszHLEuFcyhK7i7LVFrB7f9cgb/M3wRAdTl/9uihvrbjGNSv+BeL1okkYuYvkNldbkWv96jFxel94jSzkOh/kMuymxBPixktZMU9jnUrmVwSQV2WPWshM7evdCljIzYrD+5Bj08MUGlFcXVZupVF8oKR9sKvhay4L2S/syxFDUo/tSwz5yHLXWCEQ2osmhBjIRZse9FwyG6NCuCyNNdjDZky9ftJ0hqLhBANM90NKwhSzokgejskyLoJcdPzEpvU1wJRvSCsRHISUvEqaIC9H6FjDeb3H0Nmfu9mIXNq79cYJzAEGXd1WQqCCDJhqfN6PYp2Ra7HAguOzGkv7O2dkDP15+SytPQnaN6t0mjYZrUPIhbl5nYLmb++lcciuhvW6JO/uD+C6AuQIOsm4in1iS+TK8z6lN2fEAOa00AW1OLix0JmpLtQB5FcY8gqswiyfFrIUloh53CGqYN+3EaCSCiYhazoBZnPxLCAFvvl48DcNi9n6s/FQiYXFweClwoqiYQQT5qtUUHi2+RvRo0hU/R7nRBkV87wlqqhIhbWZ47q289xEgRB9EYohswDz3+4Fb9/Yx3euHGm5xu7sJBlclnmWt+uN2PkGTKWiZt8T+QhE/sX1gKnWK9M2CxkLi5Lp/ZBj0+vl8k50opiEl0NlSUYVlemvxfX6dXHj/S8/ajfxLAeaj4WA0HSOjCfFjK3OFA17UWwwHkZYYUSBIkRBJwtZH7ztLn1TY4h23TnOZ7XLy+J2ARZWiGXJdH/IEHmge898zEA1doV81gzTRdkGVxh4omyvwT1f/HhDzBt5AB885Rx+mDnNJYHLp3kJw+ZtuMuzVrgPzGsuX22MjZml2WwA4zIFrK02eKy6Men2dr7GRSBvltcPIgYCmWJIbMes5uxUmTqzzUmSs5DBgR3WZZEQvo1L/AbYycjKk3Iecj8uyzDen1OU59IkRH9DHJZ+iCTuLK6obxYyPpbWaW31+zGXa+tAWAMaE7fT9ABPoiFrCupgHPuK6ksYBeS2dxRsoAL6rLUBZDmssx3/T69uLjnGLLekfYiSGkgqwCyYv3ETfCFmZGpP1+JYYHgxbSdY8hy61s4rFrIhJXLT+kkQBVkHXG7yzKXPhFEb4QsZD5IpBTAJQdj0uLyEuLN+jRqWkdr0x/uO+9v2Gt6L1yETiLXi0uvuT2Bzfs6MGlYra/1jP0bbeMpJXDpJEG2p3nFo4XsyS9Pd+2L2UKm5D0tgN9ZlqJV8SeGDRJDls1l6W2WZUhL6Koo+XVZ5tdCllvpITHLsulAHIwB9ZUxX+tXxCLYeaDLtIxclkR/hASZDzJZu6wWFi8Wskyf9SW27+/E5x5437SsK2n/fsQg50VYXfan97C2qc3klvNVXNwqyPxaKz0OyEZzo32mfs4YXe8q7kIhps/aUy1k+R2xhtWVIxYJYVB1qaf2vScxbJAYMn+1LN1Sz4a0tBe5uizVNBzSdgMKqNJoGAe6kvp7cV3m0jchFpta46iviPl3WTrEkCk5ToIgiN4ICTIf+BFkwi1gdQ/85MXlYIzhtvMn+E9G2kvpsMSHAECn9pQufz/i2/Dislzb1AbALG78CDJ5H/FkOrCF7MEvTgWQ3f0sbz7T8WWztIUZk2ZZ5nfAOmRQFdb87CzP7cXuiz+GjPuO0wwxlvdM/bnERIk8ZLmizrI0rtVMCZozIXdl+/5OrGtqw5DaMgys8ibmZdRZlpT2giAohswHiXQG96PFZRmXgvrlmKFH39uMR97dpK6juyz7+o3Hfnxi6r3sshTfk58BXhbJQS1kXUnFdwyZYMrwWpx++KDsFjLpddB9AcbAnEo7Z+rvScR1W+R6TAvq97dO9rQXVgtp92bqDzOW03UjKI2G0ZUy7mPid5CLthfWrW37OzGo2kddTQ01D5nFQqbk1ieC6I2QIPNBpjJIVguJLBTc1pPX2drcgY172nPsYXHilFJCWMhMgkp3WXrfdtxhcPGCPNh2pdI5p73IJqpll6XTQO91rA6HGNJp1UKWKTFsT9BbLGQ8gLUla1C/zUKW2WWZa6Z+xpjZmhzwO7dbyETqHX99k5v/6cqjMbyuHADQHnd/aHWjokSdZWn9jVAeMqK/QS5LH/iKIUvLgiyt12wTrNjegl1aICsDcML/zQXgP1VBb8DpexMxZPIgIzSRnwE+7iDovCCfr65kOsAsS/NAls364ZSH7K/XTteX/fe7M/Hh5uas+9UtZArXi40Xit6SGDbIjL2sechs7Z3bCUtbrsXFwyF7vccglEbDpqB+ce5yEYtnThiMKcMH4Jifv47TDx/ke/2KkggUrlraKrR8fmlyWRL9ELKQ+UAIiy37OnDKr9/EzhZjZpDdQmbc9JwsZOfcMw8PvrOxm3ravTS3J3Dab97Cml2tnto7CzJhIbNbuPxYuuTBJUimfnUb5lmWXtJSiBZiyMg2nskiM82Bkw5pxAnjGvRlYwdW4rJjhmXdrwigTqUVRAvssuwtiWGD5NnKlofMbiF1bhcWLstcU0uEGDoyzNj2Skk0ZH4IykNQPwA0VpVg1R2z8OUTR/let6FSdXPuaYvry1Lp/E9aIYhihwSZD0QQ/l8XbMaG3e34+4db9c+sA7rJZZnMFvBd3AOalbmrm7CuqQ2/f2Odp/ZOgkx2Wf7oH8vwwNvrJZdlMAuZn/xectt4Km3apzUe0AlxysQYm22wNQX1KxxBx5pIiCGZ5jm7wPKBCJQv9utX4dknS1gJMYZMl4E97UWGTP1a2otcXHAsyyQDr5RE1Dxkov+GIAse1C8ojYYDWbUaq1RBtrvVEGStXcms5cgIoq9BV7wPRFC/uLHKg7gsOpKKYnNZZqKvJ4iNOxxfV8II6n9ywacAgPoKNX+Rn/gYWez6s5BJfUkqphiyZJojSyUkyUKmXgvZxiFr2ougYirEmH6tFdqCII652NNeBHEXZkt7YT3mjMXFebA+yFjFXNCvvDSqPoPHUwpKo2H9OArpHmx0sJC1dqVQXRotVJcIoiCQhcwHYiCUawoKZDGQSnOTUMg0GQBwL0C+rqnN9NRYLIh7t3wL/8rji/Dikm2O7Z0shO2JDEH9vmLIDLEb1EJmjSFLWs7Xml2taG5PmJbpAsujhUw+pFzcV5EQ02fJZSou3hMYMWTFrciCxJCFGMsoeqyls9z0dTikZurPh8syH5RE1FhW8Zvc2twBoLAzGhuq1Acx+V53oCuJKrKQEf0MEmQ+EMJKLxljEmHGIL5qZysSUib1eCqNRZv2uSYf7UzIQbbGNk/7zVs45uev48cvLAOg3rA27G7L09EExyqwOOd4dcUu3PD0Esf2Ttn4xTHvbTOEjhFD5qMvqWAWspSioFybaNGVTFssZOYOnHH32zj39/MctyPGWD+lk3KykIUY9neo31mhByxdkBW0F9kJEkOWzUJmj+p3bqa7LHOeZRl4VRPCQrartQvLt7XgnHvU67qQZYrqK0oQYlaXZQpVZCEj+hn0COIDayyULABkK9cl972L2vIoRtSXY8Pudlxy33sAgG+fOs5xu/sk64tTAfO/vv8pfnbhkTj5V3PRnkgXfCZmW9w82yubBdD6vcVTaV2kbW/p1JeL8c+Ppevd9Xv019v3d2Lz3naMqK/Iul5aUWd3dSTS6EoppgHbKb3Atv2dpvUtBjLHAbMkYgRQW0snBU0SGouEsK1Z7UuDzxI1+UZPe1HkPssg1qmsiWEd2jtuR2Tqz7EUUL5SQAgL2dV/WWi6pgtpIQuHGOoqSrCbXJZEP4csZD4QIqJDEyTt2v+mA1146WOzu25/RxKThw0wLVuyZb/jdvd1GIJMuKOsbiDOue7mK4SLqLk9gcvufw9b9nXgQJd63MKC0NqVeTq+VZC1dBilW7oka5tuIfNxfH+Yu15//fj7mzHzV296Wk/hHBUx4b4xuyxbOpP4ztMf4bUVO039kxEWL2EtPXJIDa6YPhw3nzVeb3P2kQcZ7eUcS0rwHEuDqkqxaa/qZqqv9J+EM5/0nuLiQWpZZimd5DUPmZT2IpdM/bmsKyPiNK0PGH4m0gDAlBHqve1EaaZwLgwZUIaNe9pxzSML8caqXWiLpwpuASaInoYEWRYemW+kphDCol3LB9TUGseyrS248z+r8NQHW2zrTh5ea3rflXAO7pcFi2hjtTq1S+u2xnPLR9TalcTybS2+1vnHR9vwwaZ9+N4zS7BTs2qJDN1Wi5mVhGVSgxCmRw2tMS0XQizbrL1sFhkvgjWtcJTH1Bu+tbj4pr3teGHJdlz/+GLXY7NayKpKo/jfi47EV2eO0dtcPGWIrT2gHmdQ99VBNUZpGjG4FgpxCMUcQ6bni/O5Xtbi4h5jyESC2SBxbNbt5IMhA8ocl+9pSzgud2PSsFp88tNZOPUw/3nHnBjdUIH3N+zDG6uacM0jiwAA1WVkISP6FyTIsnDbP1fqrxMpBR992qy7GP+zfCfOu3ceNrhk2J80zCLIssy2BIx0EO0WISAHleca6P/NJz/Cub+fhx0tndkba4i+L9zUjGcWqek+WrUixW3ZLGSWmKzrH18MAPjScSPN7YR7TxsJOedYuGmf7ek92/fo5ftROEdpNITyWBhLt+7HHf8yzvPCjfv0166CTPufaZycPqre1h5QE+AGFWSDZUFWYAtZKFT8FjKhFf0nhvVnIXOrlRliDJ2JNJZu3Z9jAW9rB4JtZ0itIcjka1AkqfaDNdl1LoxusIcZkIWM6G+QIPPBzgNduOiP7+LVFbtMy1fuOGBrO7K+HHUWC0aXh8SOX3l8MRSF20qQ7JUE2Z4cBFlnIo231uwGADyzcCs6Eims3H4AH37arFsT0grH1/66GB9sVMXQ159YjFeW77RtS7gqW+NJ22cybnnYKksieP17J6HG8iQsvIdPfvApLr3/PTy32Gx97HSxNArO+f28rFabVJojEgrh3KMOsp3PBZogqy6N2ISxlUxFq2OREO6+fCLqKmKWGblKYJelbCGrLvCAJY6gmPOQBU18qsaQZRBklvfM5U4aYsD63e040JXK6UEqXxayCimfy08vmKC/7sxD0tlcGNVoF2SFvr4JoqchQeaDzVrsjhWnxKeHHVSNkoj5612zK/sMyVU7W/HMoi02y4wswuTgV79s3mdY815ZsRPfeXoJzr7nHVz8x3cx55Mmdfutcfxn+U5c//giLNnSjJeX7cTSrXYXpxBkfi1kgvJYBGMHVuG28w83LRcWskff3QQA+Mv8TbjusUXYqx13RxZBtrs1jv0dmUWiGlgPnHXEQabl5bEwVu1UKxBUlUZN50EeoL1qkIsmD8XMQxotpZOCxwQNrjEsHIUuLWPEkBWzIFP/FyoxrGyFOpDld5KtP/nm89NHYMmtp+Nbp4zFLecenn2FbkT2JgzUEsUOqS0vVHcIoiDQI0gGrDfdLfvMguzoEQOw2KX+4LRRdSiJBjPp3/z8Mvz4nMNMy9ZL6S6aDgQXZDu0ck+zJgzGKyt24hPJurerVf1MPMkzQBdpToj0C9ljyFwEWYn6/VSWWCxkCkdze0IXsKt2tmLVzlYMrCrBzEMadZdnJna3xTEgQ4yVonBEoyEcMcQcxzaoulQv8t6eSJnE5updrRg/uBqAHNRv3/ZvL5+kZx8H1O9RFi0K53YXlEemjarDZ48eiomW+LtCoMeQFbYbGTGKZ/tbL5PL8p21u3HTsx+blmWKIRMc6Mz8kJCJesuM2vMmHhx4W/d/YYouVGvLY7jxjEMDbytfDB1giK85N85ES2fStIwg+gNkIcuANXh+bZPZwvXUdTMc1zt+bD2+eOxIm4XMD3//0Dxr8/9eWaW/XrHd7iL1iqi/ef4k+w1dWKZEPEmIMazYfgDlsbBtAKgujaA9kUZLZ9IkyNQyMRxLtxozSuMpBZUlEVvaD5EHrNKSFl/hHIs0ofv9Mw/FuUcdhDGNFXhiwadZxdhj10wDkD2OLK2lQpCFEwAcXGu4BPd3JPG/L3+iv5/123f015mMQhdOHoLjxxqzz6xlb9I5zLKsKYvirksn4spjRwZaP58UQ2LY1q4k5nyyC9c8shAHuuyCJ2gMWaag/iv//IEtCN7NdS3v1k+ePCujGyr118tvPxM3uKTQ8cKsIw4yzQAuFh65+hj88pKjUFUaJTFG9EtIkGVgf7t6g7/VYs6/7bzD8eR10xFzEVyNlSUIhxgiOUTxyparg2tK9cGhJBLCB5v2YsmW/Yin0li+rQUffdpsmnm4emcrrnlkIRZvbsa6plb8ed5G/OI/n+DrTyzGD59Xk8xOH1Vn26cYZISlLBRi2LCnDaceNgi/nz3Z1PaMCYMBANuaO01pLxZs3IuH52/E+ffOx7vr9+CHzy/FI+9uQmk0hOtPGo1rTzCKD1dosxyPHFqDK2eMwOvfm4mJw2rx2spduO6xRWAMuOb4Ubj3iim4SXuKH1xdijsvPhJ3Xz7R8XsTs8j2tMXRlUybvkcZRUrO+tvLJ+nLTxlvnjVmnbBhFR9exnnG7Gkv8pXGoJAIkeOh9Ge38bW/fohrH12EN1Y1Ye4q1Zr72HubcObdb+NbT32kz9z1HUMWUs9ZWuFY5uCut+JaXDxP53m0FGNVWRLpE9ePlZMPHYjLjhlW6G4QRMEgQZYBkR9sRH05bjz9EH35l44fhePGqBYQMTtInr1UpgkNxhiW3XZGxn1cffxIAMAJmkVlRL39yVCIHwC45oRR2LKvExf+YT7O1DLIX/THd3H/2+uxYrs6cNw7dx3eWNWES+57F6f95m3c8a+V+NNbG/DyMiMw32mGnpg9uktzicaTaWxt7sQo7Rif/eqx+MrM0fjKSaMxe5p64/xg417MW2skZ73iwQX42b9Vq9IvX1mtpwPZ05ZAZUnEFKtSJlnI7rjwCIwdWIkx0myr2rKo3uYz4wfiS8eNxLNfPRafmzYcF00eauv/pGG1pkLF339uKc763Tv4w9x1OOeedzB/ndrPxZv34eOtLbqV6sLJRnqKK6YNx9XHj8Rt55lF+Fdmjta/mycWbMavXl0NIHNQv4AB2N7Shf+uVCcPpHlwC1kxYdSyLIyFbEdLJ+atkxMDd+EHzy3FrS+uwOpdrfjnx9vxqjYZJZiFjOPeN9bhvHvn6Wli/jB3nWt7P8v9Mri6NHsjgiB6NRRDloFmTZDVlsfwrVPH4emFW9BiiQP53hmH4JtPfoR7Zk/Cgc4Urn5kIWYeYrirqkqj+OSns1RrzyML8e76vab1R9SV4+OfnIGORArH/uINXHr0UNz12hpTm0HVpSiNhjB2YCWuPWEU7ntTTYa6SZpk8MtXVuOXr6zG3ZdPxKvLdyIWCdlit0Y1VKC5I6FbpgQf3nI6LvzDfGxp7sCzi7bgnjlrARhByGO0p/NjRtbhmJGqZU24BEVakMaqEpubcMmW/agujdiCma+cMQKPv7/Z5qoEgHGDqvTXsuWtNBrGbedPMLVdfvuZuOrhD7B4czN+dPZ4fOm4UYiGGaJhpotCALp4uvXF5RhYVYr3NuxFLBwyPY0fN6Ye767fi7JYGD85bwI457hg0hBMvuO/AFTB/Ke3NuDiP87Hds3tW1kS8WQBEbNwb/77UkTDE9GVTOfNclJISrUYSfE74ZzjpmeX4tDBlRhZX4FB1aVIc47Jw2oxf91e/Ont9fj6yWPRlUrjifc34+ufGYv6ihhuevZj7G1LQOEc15wwCseMrMOohgqs3HEAsXAI/162A42VJTjpkEY89cGnCDHg+2eOxyl3vWXqj+zWF9yoxXr5nQBxoDOJpVtbMF/7va7cfgAhxvRryYrb5kd6qBrhhVCI4Y4LJmDswKrsjQmC6JWQIMtAdWkUpx02UM/9NOfGmbacWOcedTBmjK5Hg2Zx+uiW023B5MLKc/flk/Dg2xvw1ZPH4FevrMbfFm3BgIoYasqiqCmL4qNbTkdteRT/WrpDn+kHqJafD/7faYiFQyiNhnHHBRNwy4sr9M8vnzoMe9rimLOqCd/9mzoAvfTN4/HA2xvwr6U79HZXzhiB2dOG6xaNB784FXvb4qiriCESYnhz9W68uXo3BlaVoK4ipvdhxmgjn5ZALtvz7VPH4dunjMUxP38dzZbZjRdPGYpHtNmSgtvPn4AbzzhEH9Bl5ODl2dOG2z6XqSyJ4P4vHI175qzFmRMG6y7kUQ0VthmtB9eUYv3udqzfrbogn7xuOqaONNy2j1w9zVSonDGGARUx/OPrx2He2j16ML8QYzedcQguO2aYJ2G1Qdvn3vYEvvSXhQBgS4nSGxndUIGKWBg/+Psy/GHueny6z3kW8tABZdjR0gWFc7wjWVPfXrsHNWVRk5C/Vbuu6ytiplQvVv48b6Puxj9iSDWaDsTRJG3njguPwC0vLNffN7X6y7MlHnbEQ83//H2pY7vpo+qwYOM+V0vYKeMH4u7X1zh+5pdiiBskCKL7YMWcZTsbU6dO5YsWLSp0NwKxpy2OP85dj5vPGm+LRetKqrUeFa0osdPg/eqKnfjK44txy7mH63FZ2/Z34tevrsbQAWX4nhZz9ae31mN4XTmmjqxDQ2XM1VLw/Wc/xrOLt+J3n5uEMycMRiTEcP9b6zG6sdI1AHjJlv3458fb8f0zD0VpNIz2eAqLNjfjyQWbcc5RB+PDzc249oRRWLnjAA50JnHp1OzxIZ2JNO78zye46riRGF5XjkiA6YjN7Qns70yitiyKv3+4FR9vbcHNZ43HZ371JiYOq8EDV07NOAPTjd2tcZz7+3cQCYXwyndO9Fz8+P0Ne7F8WwvKYmH8e+kOHDmkBt893VmQ9jZ++s+VeFirZiGsspdMGYqLJg/BW2uasHRrixakXYZrjh+Fu15bjZc+3o4TxzVg6IAy7G5N4JIpQzB9dD12t8bx0Dsb8OxiNfHwxKE1+NgSv3X+xINxwtgG/PjF5Th0UBX++PkpGDqgDF1JBYypVtV75qzFD88ej8NvfRVHDa3BtJF1mD19OMY0Vtr678bMX83F5r0dmDVhMOav36Nba2dPG4byWAQXTDoYtWUxHFxbivZE2pZLT8A5x69fW4N4Ko3jxjTgM+MHBvmaCYLoIzDGFnPOpzp+VkyCjDE2C8DvAIQBPMQ5vzNT+94syPJBS0cSlaXe3GbZ6Eqm0ZVMo7a891tu3GjpTCIWDuWUYbylM4myaNh1Qkd/I5FS0KldO3UVMXTE06gpzyxU93ckUBoNuwpSzjn2tCXQWFUCzjmaWuPoSKRRVx7Tt72nLY7q0mjG89DSmURJJBRI+HYkUuBcFKBPIcQY4kkF5SVhRIPmLCEIot/TKwQZYywMYA2A0wFsBbAQwGzO+Uq3dfq7ICMIgiAIoveQSZAV06PeNADrOOcbOOcJAE8DuKDAfSIIgiAIguh2ikmQDQEgFy3cqi0zwRi7njG2iDG2aPfu3T3WOYIgCIIgiO6imASZJzjnD3DOp3LOpzY2Nha6OwRBEARBEDlTTIJsGwB5Gt5QbRlBEARBEESfppgE2UIA4xhjoxhjMQCfA/BSgftEEARBEATR7RRNYljOeYox9k0Ar0JNe/Ew53xFltUIgiAIgiB6PUUjyACAc/4ygJcL3Q+CIAiCIIiepJhclgRBEARBEP0SVC7WgQAABuZJREFUEmQEQRAEQRAFhgQZQRAEQRBEgSma0klBYIztBrC5m3fTAGBPN++DKCx0jvs+dI77PnSO+z594RyP4Jw7JlHt1YKsJ2CMLXKrO0X0Degc933oHPd96Bz3ffr6OSaXJUEQBEEQRIEhQUYQBEEQBFFgSJBl54FCd4Dodugc933oHPd96Bz3ffr0OaYYMoIgCIIgiAJDFjKCIAiCIIgCQ4IsA4yxWYyx1YyxdYyxmwvdHyIYjLFhjLG5jLGVjLEVjLEbtOV1jLH/MsbWav8HaMsZY+we7bwvZYxNKewREF5gjIUZYx8xxv6lvR/FGFugnce/McZi2vIS7f067fORhew34R3GWC1j7DnG2CrG2CeMsWPpd9x3YIx9V7tHL2eMPcUYK+1Pv2MSZC4wxsIA/gDgLACHA5jNGDu8sL0iApICcCPn/HAAMwB8QzuXNwOYwzkfB2CO9h5Qz/k47e96APf1fJeJANwA4BPp/f8BuJtzPhZAM4BrteXXAmjWlt+ttSN6B78D8ArnfDyAiVDPN/2O+wCMsSEAvg1gKuf8CABhAJ9DP/odkyBzZxqAdZzzDZzzBICnAVxQ4D4RAeCc7+Ccf6i9boV6Ex8C9Xw+qjV7FMCF2usLADzGVd4HUMsYO6iHu034gDE2FMA5AB7S3jMApwB4TmtiPb/ivD8H4FStPVHEMMZqAJwE4M8AwDlPcM73g37HfYkIgDLGWARAOYAd6Ee/YxJk7gwBsEV6v1VbRvRiNLP2ZAALAAzinO/QPtoJYJD2ms597+O3AP4HgKK9rwewn3Oe0t7L51A/v9rnLVp7orgZBWA3gL9orumHGGMVoN9xn4Bzvg3AXQA+hSrEWgAsRj/6HZMgI/oNjLFKAH8H8B3O+QH5M65ON6Ypx70Qxti5AJo454sL3ReiW4kAmALgPs75ZADtMNyTAOh33JvRYv8ugCq8DwZQAWBWQTvVw5Agc2cbgGHS+6HaMqIXwhiLQhVjT3DOn9cW7xIuDO1/k7aczn3v4ngA5zPGNkENLTgFaqxRreb6AMznUD+/2uc1APb2ZIeJQGwFsJVzvkB7/xxUgUa/477BaQA2cs53c86TAJ6H+tvuN79jEmTuLAQwTpvhEYMaXPhSgftEBECLK/gzgE8457+RPnoJwFXa66sAvCgt/6I2S2sGgBbJJUIUGZzzH3LOh3LOR0L9nb7BOf88gLkAPqs1s55fcd4/q7Unq0qRwznfCWALY+xQbdGpAFaCfsd9hU8BzGCMlWv3bHF++83vmBLDZoAxdjbU2JQwgIc55z8vcJeIADDGTgDwDoBlMGKMfgQ1juwZAMMBbAZwGed8n3YzuBequbwDwNWc80U93nHCN4yxkwHcxDk/lzE2GqrFrA7ARwC+wDmPM8ZKATwONZZwH4DPcc43FKrPhHcYY5OgTtyIAdgA4GqohgX6HfcBGGO3A7gc6sz4jwB8GWqsWL/4HZMgIwiCIAiCKDDksiQIgiAIgigwJMgIgiAIgiAKDAkygiAIgiCIAkOCjCAIgiAIosCQICMIgiAIgigwJMgIgugzMMbSjLEl0t/N2deybWMqY+wen+tsYow1+N0XQRCEgNJeEATRZ2CMtXHOKwuw300ApnLO9/T0vgmC6BuQhYwgiD6PZsH6JWNsGWPsA8bYWG35pYyx5Yyxjxljb2vLTmaM/Ut7XccYe4ExtpQx9j5j7ChteT1j7DXG2ArG2EMAmLSvL2j7WMIY+xNjLFyAQyYIopdBgowgiL5EmcVlebn0WQvn/Eio2dt/qy27FcCZnPOJAM532N7tAD7inB8FtbrDY9rynwCYxzmfAOAfULPEgzF2GNRM48dzzicBSAP4fH4PkSCIvkgkexOCIIheQ6cmhJx4Svp/t/Z6PoBHGGPPQC1mbOUEAJcAAOf8Dc0yVg3gJAAXa8v/zRhr1tqfCuBoAAvVyj0og1HsmiAIwhUSZARB9Be49TXn/KuMsekAzgGwmDF2dI77YAAe5Zz/MMftEATRzyCXJUEQ/YXLpf/vAQBjbAznfAHn/FYAuwEMs6zzDjSXo1a4fA/n/ACAtwFcoS0/C8AArf0cAJ9ljA3UPqtjjI3otiMiCKLPQBYygiD6EmWMsSXS+1c45yL1xQDG2FIAcQCztWW/YoyNg2rZmgPgYwAzpfVvA/Cwtl4HgKu05bcDeIoxtgLAuwA+BQDO+UrG2I8BvMYYCwFIAvgGgM35PUyCIPoalPaCIIg+D6WlIAii2CGXJUEQBEEQRIEhCxlBEARBEESBIQsZQRAEQRBEgSFBRhAEQRAEUWBIkBEEQRAEQRQYEmQEQRAEQRAFhgQZQRAEQRBEgSFBRhAEQRAEUWD+P4OVq5z/8Mn0AAAAAElFTkSuQmCC", "text/plain": [ "
" ] @@ -1569,7 +1567,12 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.8.5" + "version": "3.10.9 (main, Dec 7 2022, 13:47:07) [GCC 12.2.0]" + }, + "vscode": { + "interpreter": { + "hash": "916dbcbb3f70747c44a77c7bcd40155683ae19c65e1c03b4aa3499c5328201f1" + } } }, "nbformat": 4, diff --git a/release/setup.py b/release/setup.py index f1a73e717..24424b613 100644 --- a/release/setup.py +++ b/release/setup.py @@ -53,13 +53,13 @@ def finalize_options(self): REQUIRED_PACKAGES = [ 'cirq-core==0.13.1', 'cirq-google>=0.13.1', 'sympy == 1.8', 'googleapis-common-protos==1.52.0', 'google-api-core==1.21.0', - 'google-auth==1.18.0', 'protobuf==3.17.3' + 'google-auth==1.18.0', 'protobuf==3.19.4' ] # placed as extra to not have required overwrite existing nightly installs if # they exist. -EXTRA_PACKAGES = ['tensorflow == 2.7.0'] -CUR_VERSION = '0.7.2' +EXTRA_PACKAGES = ['tensorflow == 2.11.0'] +CUR_VERSION = '0.7.3' class BinaryDistribution(Distribution): diff --git a/requirements.txt b/requirements.txt index ee7ebc77f..ae8700878 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,15 +1,15 @@ cirq-core==0.13.1 cirq-google==0.13.1 sympy==1.8 -numpy==1.19.5 # TensorFlow can detect if it was built against other versions. +numpy==1.24.2 # TensorFlow can detect if it was built against other versions. nbformat==4.4.0 pylint==2.4.4 yapf==0.28.0 -tensorflow==2.7.0 +tensorflow==2.11.0 # Needed for compatibility with cirq program protos. googleapis-common-protos==1.52.0 google-api-core==1.21.0 google-auth==1.18.0 google-api-python-client==1.8.0 grpcio==1.34.1 -protobuf==3.17.3 +protobuf==3.19.4 diff --git a/scripts/benchmark_all.sh b/scripts/benchmark_all.sh index 9fbf73387..cd50209c2 100644 --- a/scripts/benchmark_all.sh +++ b/scripts/benchmark_all.sh @@ -14,7 +14,7 @@ # limitations under the License. # ============================================================================== echo "Testing benchmarks."; -test_outputs=$(bazel test -c opt --cxxopt="-D_GLIBCXX_USE_CXX11_ABI=0" --cxxopt="-msse2" --cxxopt="-msse3" --cxxopt="-msse4" --test_output=errors $(bazel query //benchmarks/...)) +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/...)) exit_code=$? if [ "$exit_code" == "0" ]; then @@ -26,5 +26,5 @@ else fi echo "Running preconfigured benchmarks."; -bazel_run=${bazel run -c opt --cxxopt="-D_GLIBCXX_USE_CXX11_ABI=0" --cxxopt="-msse2" --cxxopt="-msse3" --cxxopt="-msse4"} +bazel_run=${bazel run -c opt --cxxopt="-D_GLIBCXX_USE_CXX11_ABI=1" --cxxopt="-msse2" --cxxopt="-msse3" --cxxopt="-msse4"} bazel_run benchmarks/scripts:benchmark_clifford_circuit -- --op_density 1 --n_moments 10 --n_qubits 4 \ No newline at end of file diff --git a/scripts/build_pip_package_test.sh b/scripts/build_pip_package_test.sh index 1adc7a7e9..644338b6a 100755 --- a/scripts/build_pip_package_test.sh +++ b/scripts/build_pip_package_test.sh @@ -19,7 +19,7 @@ pip install -r requirements.txt # cd tensorflow_quantum echo "Y\n" | ./configure.sh -bazel build -c opt --cxxopt="-D_GLIBCXX_USE_CXX11_ABI=0" --cxxopt="-msse2" --cxxopt="-msse3" --cxxopt="-msse4" release:build_pip_package +bazel build -c opt --cxxopt="-D_GLIBCXX_USE_CXX11_ABI=1" --cxxopt="-msse2" --cxxopt="-msse3" --cxxopt="-msse4" release:build_pip_package rm /tmp/tensorflow_quantum/* || echo ok bazel-bin/release/build_pip_package /tmp/tensorflow_quantum/ pip install -U /tmp/tensorflow_quantum/*.whl diff --git a/scripts/ci_install.sh b/scripts/ci_install.sh index 99b3dc45e..a0ed81c8c 100755 --- a/scripts/ci_install.sh +++ b/scripts/ci_install.sh @@ -13,7 +13,7 @@ # See the License for the specific language governing permissions and # limitations under the License. # ============================================================================== -wget https://github.com/bazelbuild/bazel/releases/download/3.7.2/bazel_3.7.2-linux-x86_64.deb -sudo dpkg -i bazel_3.7.2-linux-x86_64.deb +wget https://github.com/bazelbuild/bazel/releases/download/5.1.0/bazel_5.1.0-linux-x86_64.deb +sudo dpkg -i bazel_5.1.0-linux-x86_64.deb pip install --upgrade pip setuptools wheel pip install -r requirements.txt \ No newline at end of file diff --git a/scripts/ci_validate_tutorials.sh b/scripts/ci_validate_tutorials.sh index 74c9189a1..e58355faf 100755 --- a/scripts/ci_validate_tutorials.sh +++ b/scripts/ci_validate_tutorials.sh @@ -15,11 +15,13 @@ # ============================================================================== # Run the tutorials using the installed pip package -pip install jupyter nbconvert==6.4.3 jupyter-client==6.1.12 ipython==7.22.0 +pip install jupyter nbclient==0.6.5 jupyter-client==6.1.12 ipython==7.22.0 # Workaround for ipykernel - see https://github.com/ipython/ipykernel/issues/422 pip install ipykernel==5.1.1 # OpenAI Gym pip package needed for the quantum reinforcement learning tutorial -pip install gym==0.18.0 +pip install gym==0.24.1 +# seaborn has also numpy dependency, it requires version >= 0.12.0. +pip install seaborn==0.12.0 # tf_docs pip package needed for noise tutorial. pip install -q git+https://github.com/tensorflow/docs # Leave the quantum directory, otherwise errors may occur diff --git a/scripts/msan_test.sh b/scripts/msan_test.sh index 021b2e9c6..d47e8ccfe 100755 --- a/scripts/msan_test.sh +++ b/scripts/msan_test.sh @@ -14,19 +14,19 @@ # limitations under the License. # ============================================================================== echo "Testing All Bazel cc_tests with msan."; -test_outputs=$(bazel test -c opt --cxxopt="-D_GLIBCXX_USE_CXX11_ABI=0" \ +test_outputs=$(bazel test -c opt --cxxopt="-D_GLIBCXX_USE_CXX11_ABI=1" \ --cxxopt="-msse2" --cxxopt="-msse3" --cxxopt="-msse4" \ --cxxopt="-fsanitize=address" --linkopt="-fsanitize=address" \ --cxxopt="-g" --cxxopt="-O0" \ --notest_keep_going --test_output=errors \ //tensorflow_quantum/core/src:all && \ - bazel test -c opt --cxxopt="-D_GLIBCXX_USE_CXX11_ABI=0" \ + bazel test -c opt --cxxopt="-D_GLIBCXX_USE_CXX11_ABI=1" \ --cxxopt="-mavx2" --cxxopt="-mavx" --cxxopt="-mfma" \ --cxxopt="-fsanitize=address" --linkopt="-fsanitize=address" \ --cxxopt="-g" --cxxopt="-O0" \ --notest_keep_going --test_output=errors \ //tensorflow_quantum/core/src:all && \ - bazel test -c opt --cxxopt="-D_GLIBCXX_USE_CXX11_ABI=0" \ + bazel test -c opt --cxxopt="-D_GLIBCXX_USE_CXX11_ABI=1" \ --cxxopt="-fsanitize=address" --linkopt="-fsanitize=address" \ --cxxopt="-g" --cxxopt="-O0" \ --notest_keep_going --test_output=errors \ diff --git a/scripts/test_all.sh b/scripts/test_all.sh index e5513bb12..7a9fc7824 100755 --- a/scripts/test_all.sh +++ b/scripts/test_all.sh @@ -14,7 +14,7 @@ # limitations under the License. # ============================================================================== echo "Testing All Bazel py_test and cc_tests."; -test_outputs=$(bazel test -c opt --experimental_repo_remote_exec --cxxopt="-D_GLIBCXX_USE_CXX11_ABI=0" --cxxopt="-msse2" --cxxopt="-msse3" --cxxopt="-msse4" --notest_keep_going --test_output=errors //tensorflow_quantum/...) +test_outputs=$(bazel test -c opt --experimental_repo_remote_exec --cxxopt="-D_GLIBCXX_USE_CXX11_ABI=1" --cxxopt="-std=c++17" --cxxopt="-msse2" --cxxopt="-msse3" --cxxopt="-msse4" --notest_keep_going --test_output=errors //tensorflow_quantum/...) exit_code=$? if [ "$exit_code" == "0" ]; then echo "Testing Complete!"; @@ -23,4 +23,4 @@ else echo "Testing failed, please correct errors before proceeding." echo "{$test_outputs}" exit 64; -fi \ No newline at end of file +fi diff --git a/scripts/test_benchmarks.sh b/scripts/test_benchmarks.sh index d969a0d29..07e3adec1 100644 --- a/scripts/test_benchmarks.sh +++ b/scripts/test_benchmarks.sh @@ -14,10 +14,10 @@ # limitations under the License. # ============================================================================== echo "Testing all Benchmarks."; -bazel test -c opt --cxxopt="-D_GLIBCXX_USE_CXX11_ABI=0" --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=0" --cxxopt="-msse2" --cxxopt="-msse3" --cxxopt="-msse4" --test_output=errors $(bazel query //benchmarks/scripts:all)) +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=0" --cxxopt="-msse2" --cxxopt="-msse3" --cxxopt="-msse4" --test_output=errors //benchmarks/scripts:benchmark_clifford_circuit) +# 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!"; diff --git a/scripts/test_tutorials.py b/scripts/test_tutorials.py index 7424fe38c..08a9d85d9 100644 --- a/scripts/test_tutorials.py +++ b/scripts/test_tutorials.py @@ -18,7 +18,7 @@ from absl.testing import parameterized import nbformat -import nbconvert +import nbclient import tensorflow as tf # Must be run from the directory containing `quantum` repo. @@ -46,9 +46,7 @@ def test_notebook(self, path): src = re.sub('n_epochs ?= ?.*', 'n_epochs = 2', src) cell['source'] = src - _ = nbconvert.preprocessors.execute.executenb(nb, - timeout=900, - kernel_name="python3") + _ = nbclient.execute(nb, timeout=900, kernel_name="python3") if __name__ == "__main__": tf.test.main() diff --git a/tensorflow_quantum/core/ops/BUILD b/tensorflow_quantum/core/ops/BUILD index 8a534229b..8087a8d3b 100644 --- a/tensorflow_quantum/core/ops/BUILD +++ b/tensorflow_quantum/core/ops/BUILD @@ -55,7 +55,7 @@ cc_binary( "-DNOGDI", "/d2ReducedOptimizeHugeFunctions", "/arch:AVX", - "/std:c++14", + "/std:c++17", "-DTENSORFLOW_MONOLITHIC_BUILD", "/DPLATFORM_WINDOWS", "/DEIGEN_HAS_C99_MATH", @@ -69,8 +69,8 @@ cc_binary( ], "//conditions:default": [ "-pthread", - "-std=c++14", - "-D_GLIBCXX_USE_CXX11_ABI=0", + "-std=c++17", + "-D_GLIBCXX_USE_CXX11_ABI=1", ], }), features = select({ @@ -118,7 +118,7 @@ cc_binary( "-DNOGDI", "/d2ReducedOptimizeHugeFunctions", "/arch:AVX", - "/std:c++14", + "/std:c++17", "-DTENSORFLOW_MONOLITHIC_BUILD", "/DPLATFORM_WINDOWS", "/DEIGEN_HAS_C99_MATH", @@ -132,8 +132,8 @@ cc_binary( ], "//conditions:default": [ "-pthread", - "-std=c++14", - "-D_GLIBCXX_USE_CXX11_ABI=0", + "-std=c++17", + "-D_GLIBCXX_USE_CXX11_ABI=1", ], }), features = select({ @@ -176,7 +176,7 @@ cc_binary( "-DNOGDI", "/d2ReducedOptimizeHugeFunctions", "/arch:AVX", - "/std:c++14", + "/std:c++17", "-DTENSORFLOW_MONOLITHIC_BUILD", "/DPLATFORM_WINDOWS", "/DEIGEN_HAS_C99_MATH", @@ -190,8 +190,8 @@ cc_binary( ], "//conditions:default": [ "-pthread", - "-std=c++14", - "-D_GLIBCXX_USE_CXX11_ABI=0", + "-std=c++17", + "-D_GLIBCXX_USE_CXX11_ABI=1", ], }), features = select({ @@ -242,7 +242,7 @@ cc_binary( "-DNOGDI", "/d2ReducedOptimizeHugeFunctions", "/arch:AVX", - "/std:c++14", + "/std:c++17", "-DTENSORFLOW_MONOLITHIC_BUILD", "/DPLATFORM_WINDOWS", "/DEIGEN_HAS_C99_MATH", @@ -256,8 +256,8 @@ cc_binary( ], "//conditions:default": [ "-pthread", - "-std=c++14", - "-D_GLIBCXX_USE_CXX11_ABI=0", + "-std=c++17", + "-D_GLIBCXX_USE_CXX11_ABI=1", ], }), features = select({ @@ -301,7 +301,7 @@ cc_library( "-DNOGDI", "/d2ReducedOptimizeHugeFunctions", "/arch:AVX", - "/std:c++14", + "/std:c++17", "-DTENSORFLOW_MONOLITHIC_BUILD", "/DPLATFORM_WINDOWS", "/DEIGEN_HAS_C99_MATH", @@ -315,8 +315,8 @@ cc_library( ], "//conditions:default": [ "-pthread", - "-std=c++14", - "-D_GLIBCXX_USE_CXX11_ABI=0", + "-std=c++17", + "-D_GLIBCXX_USE_CXX11_ABI=1", ], }), deps = [ @@ -354,7 +354,7 @@ cc_binary( "-DNOGDI", "/d2ReducedOptimizeHugeFunctions", "/arch:AVX", - "/std:c++14", + "/std:c++17", "-DTENSORFLOW_MONOLITHIC_BUILD", "/DPLATFORM_WINDOWS", "/DEIGEN_HAS_C99_MATH", @@ -368,8 +368,8 @@ cc_binary( ], "//conditions:default": [ "-pthread", - "-std=c++14", - "-D_GLIBCXX_USE_CXX11_ABI=0", + "-std=c++17", + "-D_GLIBCXX_USE_CXX11_ABI=1", ], }), features = select({ @@ -416,7 +416,7 @@ cc_library( "-DNOGDI", "/d2ReducedOptimizeHugeFunctions", "/arch:AVX", - "/std:c++14", + "/std:c++17", "-DTENSORFLOW_MONOLITHIC_BUILD", "/DPLATFORM_WINDOWS", "/DEIGEN_HAS_C99_MATH", @@ -430,8 +430,8 @@ cc_library( ], "//conditions:default": [ "-pthread", - "-std=c++14", - "-D_GLIBCXX_USE_CXX11_ABI=0", + "-std=c++17", + "-D_GLIBCXX_USE_CXX11_ABI=1", ], }), deps = [ diff --git a/tensorflow_quantum/core/ops/cirq_ops_test.py b/tensorflow_quantum/core/ops/cirq_ops_test.py index ffbfab1de..1b54771a9 100644 --- a/tensorflow_quantum/core/ops/cirq_ops_test.py +++ b/tensorflow_quantum/core/ops/cirq_ops_test.py @@ -457,7 +457,7 @@ def run_sweep(self, program, params, repetitions): 'tfq': np.array([[1] * len(program.all_qubits())] * repetitions, - dtype=np.int32), + dtype=int), }) for param in cirq.to_resolvers(params) ] diff --git a/tensorflow_quantum/core/ops/math_ops/BUILD b/tensorflow_quantum/core/ops/math_ops/BUILD index 51bad72fb..6eb8a0320 100644 --- a/tensorflow_quantum/core/ops/math_ops/BUILD +++ b/tensorflow_quantum/core/ops/math_ops/BUILD @@ -38,7 +38,7 @@ cc_binary( "-DNOGDI", "/d2ReducedOptimizeHugeFunctions", "/arch:AVX", - "/std:c++14", + "/std:c++17", "-DTENSORFLOW_MONOLITHIC_BUILD", "/DPLATFORM_WINDOWS", "/DEIGEN_HAS_C99_MATH", @@ -52,8 +52,8 @@ cc_binary( ], "//conditions:default": [ "-pthread", - "-std=c++14", - "-D_GLIBCXX_USE_CXX11_ABI=0", + "-std=c++17", + "-D_GLIBCXX_USE_CXX11_ABI=1", ], }), features = select({ diff --git a/tensorflow_quantum/core/ops/math_ops/simulate_mps_test.py b/tensorflow_quantum/core/ops/math_ops/simulate_mps_test.py index 1120b1392..ee7317b6a 100644 --- a/tensorflow_quantum/core/ops/math_ops/simulate_mps_test.py +++ b/tensorflow_quantum/core/ops/math_ops/simulate_mps_test.py @@ -934,7 +934,10 @@ def test_complex_equality(self): ] for _ in range(batch_size)] symbol_names = [] resolver_batch = [{} for _ in range(batch_size)] - num_samples = np.ones_like(pauli_sums, dtype=np.int32) * 1000 + # Because `pauli_sums` has inhomogeneous shape due to the different + # number of terms, `np.ones_like` failed with `pauli_sums`. + puali_sums_len = [[len(x) for x in y] for y in pauli_sums] + num_samples = np.ones_like(puali_sums_len, dtype=int) * 1000 symbol_values_array = np.array( [[resolver[symbol] diff --git a/tensorflow_quantum/core/ops/math_ops/tfq_inner_product.cc b/tensorflow_quantum/core/ops/math_ops/tfq_inner_product.cc index 2a66d2919..74751f9cc 100644 --- a/tensorflow_quantum/core/ops/math_ops/tfq_inner_product.cc +++ b/tensorflow_quantum/core/ops/math_ops/tfq_inner_product.cc @@ -87,7 +87,7 @@ class TfqInnerProductOp : public tensorflow::OpKernel { std::vector fused_circuits(programs.size(), QsimFusedCircuit({})); - Status parse_status = Status::OK(); + Status parse_status = ::tensorflow::Status(); auto p_lock = tensorflow::mutex(); auto construct_f = [&](int start, int end) { for (int i = start; i < end; i++) { @@ -314,7 +314,7 @@ REGISTER_OP("TfqInnerProduct") c->Dim(other_programs_shape, 1); c->set_output(0, c->Matrix(output_rows, output_cols)); - return tensorflow::Status::OK(); + return ::tensorflow::Status(); }); } // namespace tfq diff --git a/tensorflow_quantum/core/ops/math_ops/tfq_inner_product_grad.cc b/tensorflow_quantum/core/ops/math_ops/tfq_inner_product_grad.cc index 5b29571d2..3db493b11 100644 --- a/tensorflow_quantum/core/ops/math_ops/tfq_inner_product_grad.cc +++ b/tensorflow_quantum/core/ops/math_ops/tfq_inner_product_grad.cc @@ -112,7 +112,7 @@ class TfqInnerProductGradOp : public tensorflow::OpKernel { std::vector> gradient_gates( programs.size(), std::vector({})); - Status parse_status = Status::OK(); + Status parse_status = ::tensorflow::Status(); auto p_lock = tensorflow::mutex(); auto construct_f = [&](int start, int end) { for (int i = start; i < end; i++) { @@ -490,7 +490,7 @@ REGISTER_OP("TfqInnerProductGrad") {output_rows, tensorflow::shape_inference::InferenceContext::kUnknownDim})); - return tensorflow::Status::OK(); + return ::tensorflow::Status(); }); } // namespace tfq diff --git a/tensorflow_quantum/core/ops/math_ops/tfq_simulate_1d_expectation.cc b/tensorflow_quantum/core/ops/math_ops/tfq_simulate_1d_expectation.cc index adb1d9bb6..c00b43a9b 100644 --- a/tensorflow_quantum/core/ops/math_ops/tfq_simulate_1d_expectation.cc +++ b/tensorflow_quantum/core/ops/math_ops/tfq_simulate_1d_expectation.cc @@ -100,7 +100,7 @@ class TfqSimulateMPS1DExpectationOp : public tensorflow::OpKernel { std::vector qsim_circuits(programs.size(), QsimCircuit()); std::vector fused_circuits(programs.size(), QsimFusedCircuit({})); - Status parse_status = Status::OK(); + Status parse_status = ::tensorflow::Status(); auto p_lock = tensorflow::mutex(); auto construct_f = [&](int start, int end) { for (int i = start; i < end; i++) { @@ -153,7 +153,7 @@ class TfqSimulateMPS1DExpectationOp : public tensorflow::OpKernel { const int output_dim_op_size = output_tensor->dimension(1); - Status compute_status = Status::OK(); + Status compute_status = ::tensorflow::Status(); auto c_lock = tensorflow::mutex(); auto DoWork = [&](int start, int end) { int old_batch_index = -2; @@ -247,7 +247,7 @@ REGISTER_OP("TfqSimulateMPS1DExpectation") c->Dim(pauli_sums_shape, 1); c->set_output(0, c->Matrix(output_rows, output_cols)); - return tensorflow::Status::OK(); + return ::tensorflow::Status(); }); } // namespace tfq diff --git a/tensorflow_quantum/core/ops/math_ops/tfq_simulate_1d_sampled_expectation.cc b/tensorflow_quantum/core/ops/math_ops/tfq_simulate_1d_sampled_expectation.cc index 750531f16..ba94e8c72 100644 --- a/tensorflow_quantum/core/ops/math_ops/tfq_simulate_1d_sampled_expectation.cc +++ b/tensorflow_quantum/core/ops/math_ops/tfq_simulate_1d_sampled_expectation.cc @@ -113,7 +113,7 @@ class TfqSimulateMPS1DSampledExpectationOp : public tensorflow::OpKernel { std::vector>> fused_circuits( programs.size(), std::vector>({})); - Status parse_status = Status::OK(); + Status parse_status = ::tensorflow::Status(); auto p_lock = tensorflow::mutex(); auto construct_f = [&](int start, int end) { for (int i = start; i < end; i++) { @@ -179,7 +179,7 @@ class TfqSimulateMPS1DSampledExpectationOp : public tensorflow::OpKernel { ->tensorflow_cpu_worker_threads() ->workers->NumThreads(); - Status compute_status = Status::OK(); + Status compute_status = ::tensorflow::Status(); auto c_lock = tensorflow::mutex(); auto DoWork = [&](int start, int end) { int old_batch_index = -2; @@ -291,7 +291,7 @@ REGISTER_OP("TfqSimulateMPS1DSampledExpectation") c->Dim(pauli_sums_shape, 1); c->set_output(0, c->Matrix(output_rows, output_cols)); - return tensorflow::Status::OK(); + return ::tensorflow::Status(); }); } // namespace tfq diff --git a/tensorflow_quantum/core/ops/math_ops/tfq_simulate_1d_samples.cc b/tensorflow_quantum/core/ops/math_ops/tfq_simulate_1d_samples.cc index 495e5f8f2..608f94689 100644 --- a/tensorflow_quantum/core/ops/math_ops/tfq_simulate_1d_samples.cc +++ b/tensorflow_quantum/core/ops/math_ops/tfq_simulate_1d_samples.cc @@ -85,7 +85,7 @@ class TfqSimulateMPS1DSamplesOp : public tensorflow::OpKernel { std::vector>> fused_circuits( programs.size(), std::vector>({})); - Status parse_status = Status::OK(); + Status parse_status = ::tensorflow::Status(); auto p_lock = tensorflow::mutex(); auto construct_f = [&](int start, int end) { for (int i = start; i < end; i++) { @@ -242,7 +242,7 @@ REGISTER_OP("TfqSimulateMPS1DSamples") tensorflow::shape_inference::InferenceContext::kUnknownDim, tensorflow::shape_inference::InferenceContext::kUnknownDim})); - return tensorflow::Status::OK(); + return ::tensorflow::Status(); }); } // namespace tfq diff --git a/tensorflow_quantum/core/ops/noise/BUILD b/tensorflow_quantum/core/ops/noise/BUILD index a72665780..3758037e5 100644 --- a/tensorflow_quantum/core/ops/noise/BUILD +++ b/tensorflow_quantum/core/ops/noise/BUILD @@ -36,7 +36,7 @@ cc_binary( "-DNOGDI", "/d2ReducedOptimizeHugeFunctions", "/arch:AVX", - "/std:c++14", + "/std:c++17", "-DTENSORFLOW_MONOLITHIC_BUILD", "/DPLATFORM_WINDOWS", "/DEIGEN_HAS_C99_MATH", @@ -50,8 +50,8 @@ cc_binary( ], "//conditions:default": [ "-pthread", - "-std=c++14", - "-D_GLIBCXX_USE_CXX11_ABI=0", + "-std=c++17", + "-D_GLIBCXX_USE_CXX11_ABI=1", ], }), features = select({ diff --git a/tensorflow_quantum/core/ops/noise/tfq_noisy_expectation.cc b/tensorflow_quantum/core/ops/noise/tfq_noisy_expectation.cc index 430b8d303..c67fa01f7 100644 --- a/tensorflow_quantum/core/ops/noise/tfq_noisy_expectation.cc +++ b/tensorflow_quantum/core/ops/noise/tfq_noisy_expectation.cc @@ -111,7 +111,7 @@ class TfqNoisyExpectationOp : public tensorflow::OpKernel { std::vector qsim_circuits(programs.size(), NoisyQsimCircuit()); - Status parse_status = Status::OK(); + Status parse_status = ::tensorflow::Status(); auto p_lock = tensorflow::mutex(); auto construct_f = [&](int start, int end) { for (int i = start; i < end; i++) { @@ -287,7 +287,7 @@ class TfqNoisyExpectationOp : public tensorflow::OpKernel { } random_gen.Init(tensorflow::random::New64(), tensorflow::random::New64()); - Status compute_status = Status::OK(); + Status compute_status = ::tensorflow::Status(); auto c_lock = tensorflow::mutex(); auto DoWork = [&](int start, int end) { // Begin simulation. @@ -418,7 +418,7 @@ REGISTER_OP("TfqNoisyExpectation") c->Dim(pauli_sums_shape, 1); c->set_output(0, c->Matrix(output_rows, output_cols)); - return tensorflow::Status::OK(); + return ::tensorflow::Status(); }); } // namespace tfq diff --git a/tensorflow_quantum/core/ops/noise/tfq_noisy_sampled_expectation.cc b/tensorflow_quantum/core/ops/noise/tfq_noisy_sampled_expectation.cc index c6b66d861..aa0c85691 100644 --- a/tensorflow_quantum/core/ops/noise/tfq_noisy_sampled_expectation.cc +++ b/tensorflow_quantum/core/ops/noise/tfq_noisy_sampled_expectation.cc @@ -112,7 +112,7 @@ class TfqNoisySampledExpectationOp : public tensorflow::OpKernel { std::vector qsim_circuits(programs.size(), NoisyQsimCircuit()); - Status parse_status = Status::OK(); + Status parse_status = ::tensorflow::Status(); auto p_lock = tensorflow::mutex(); auto construct_f = [&](int start, int end) { for (int i = start; i < end; i++) { @@ -294,7 +294,7 @@ class TfqNoisySampledExpectationOp : public tensorflow::OpKernel { } random_gen.Init(tensorflow::random::New64(), tensorflow::random::New64()); - Status compute_status = Status::OK(); + Status compute_status = ::tensorflow::Status(); auto c_lock = tensorflow::mutex(); auto DoWork = [&](int start, int end) { // Begin simulation. @@ -424,7 +424,7 @@ REGISTER_OP("TfqNoisySampledExpectation") c->Dim(pauli_sums_shape, 1); c->set_output(0, c->Matrix(output_rows, output_cols)); - return tensorflow::Status::OK(); + return ::tensorflow::Status(); }); } // namespace tfq diff --git a/tensorflow_quantum/core/ops/noise/tfq_noisy_samples.cc b/tensorflow_quantum/core/ops/noise/tfq_noisy_samples.cc index f8a102914..341c87910 100644 --- a/tensorflow_quantum/core/ops/noise/tfq_noisy_samples.cc +++ b/tensorflow_quantum/core/ops/noise/tfq_noisy_samples.cc @@ -82,7 +82,7 @@ class TfqNoisySamplesOp : public tensorflow::OpKernel { std::vector qsim_circuits(programs.size(), NoisyQsimCircuit()); - Status parse_status = Status::OK(); + Status parse_status = ::tensorflow::Status(); auto p_lock = tensorflow::mutex(); auto construct_f = [&](int start, int end) { for (int i = start; i < end; i++) { @@ -343,7 +343,7 @@ REGISTER_OP("TfqNoisySamples") tensorflow::shape_inference::InferenceContext::kUnknownDim, tensorflow::shape_inference::InferenceContext::kUnknownDim})); - return tensorflow::Status::OK(); + return ::tensorflow::Status(); }); } // namespace tfq diff --git a/tensorflow_quantum/core/ops/parse_context.cc b/tensorflow_quantum/core/ops/parse_context.cc index dd8f941fc..f926d15bb 100644 --- a/tensorflow_quantum/core/ops/parse_context.cc +++ b/tensorflow_quantum/core/ops/parse_context.cc @@ -42,16 +42,17 @@ template Status ParseProto(const std::string& text, T* proto) { // First attempt to parse from the binary representation. if (proto->ParseFromString(text)) { - return Status::OK(); + return ::tensorflow::Status(); } // If that fails, then try to parse from the human readable representation. if (google::protobuf::TextFormat::ParseFromString(text, proto)) { - return Status::OK(); + return ::tensorflow::Status(); } - return Status(tensorflow::error::INVALID_ARGUMENT, - "Unparseable proto: " + text); + return Status( + static_cast(absl::StatusCode::kInvalidArgument), + "Unparseable proto: " + text); } } // namespace @@ -67,7 +68,8 @@ Status ParsePrograms(OpKernelContext* context, const std::string& input_name, if (input->dims() != 1) { // Never parse anything other than a 1d list of circuits. return Status( - tensorflow::error::INVALID_ARGUMENT, + static_cast( + absl::StatusCode::kInvalidArgument), absl::StrCat("programs must be rank 1. Got rank ", input->dims(), ".")); } @@ -86,7 +88,7 @@ Status ParsePrograms(OpKernelContext* context, const std::string& input_name, context->device()->tensorflow_cpu_worker_threads()->workers->ParallelFor( num_programs, cycle_estimate, DoWork); - return Status::OK(); + return ::tensorflow::Status(); } Status ParsePrograms2D(OpKernelContext* context, const std::string& input_name, @@ -99,7 +101,8 @@ Status ParsePrograms2D(OpKernelContext* context, const std::string& input_name, if (input->dims() != 2) { // Never parse anything other than a 1d list of circuits. - return Status(tensorflow::error::INVALID_ARGUMENT, + return Status(static_cast( + absl::StatusCode::kInvalidArgument), absl::StrCat("other_programs must be rank 2. Got rank ", input->dims(), ".")); } @@ -123,7 +126,7 @@ Status ParsePrograms2D(OpKernelContext* context, const std::string& input_name, context->device()->tensorflow_cpu_worker_threads()->workers->ParallelFor( num_programs * num_entries, cycle_estimate, DoWork); - return Status::OK(); + return ::tensorflow::Status(); } Status GetProgramsAndProgramsToAppend( @@ -140,11 +143,12 @@ Status GetProgramsAndProgramsToAppend( } if (programs->size() != programs_to_append->size()) { - return Status(tensorflow::error::INVALID_ARGUMENT, + return Status(static_cast( + absl::StatusCode::kInvalidArgument), "programs and programs_to_append must have matching sizes."); } - return Status::OK(); + return ::tensorflow::Status(); } Status GetProgramsAndNumQubits( @@ -167,7 +171,8 @@ Status GetProgramsAndNumQubits( } if (programs->size() != p_sums->size()) { return Status( - tensorflow::error::INVALID_ARGUMENT, + static_cast( + absl::StatusCode::kInvalidArgument), absl::StrCat("Number of circuits and PauliSums do not match. Got ", programs->size(), " circuits and ", p_sums->size(), " paulisums.")); @@ -197,7 +202,7 @@ Status GetProgramsAndNumQubits( context->device()->tensorflow_cpu_worker_threads()->workers->ParallelFor( num_qubits->size(), cycle_estimate, DoWork); - return Status::OK(); + return ::tensorflow::Status(); } tensorflow::Status GetProgramsAndNumQubits( @@ -218,7 +223,8 @@ tensorflow::Status GetProgramsAndNumQubits( } if (programs->size() != other_programs->size()) { - return Status(tensorflow::error::INVALID_ARGUMENT, + return Status(static_cast( + absl::StatusCode::kInvalidArgument), absl::StrCat("programs and other_programs batch dimension", " do not match. Foud: ", programs->size(), " and ", other_programs->size())); @@ -241,7 +247,7 @@ tensorflow::Status GetProgramsAndNumQubits( context->device()->tensorflow_cpu_worker_threads()->workers->ParallelFor( num_qubits->size(), cycle_estimate, DoWork); - return Status::OK(); + return ::tensorflow::Status(); } Status GetPauliSums(OpKernelContext* context, @@ -254,7 +260,8 @@ Status GetPauliSums(OpKernelContext* context, } if (input->dims() != 2) { - return Status(tensorflow::error::INVALID_ARGUMENT, + return Status(static_cast( + absl::StatusCode::kInvalidArgument), absl::StrCat("pauli_sums must be rank 2. Got rank ", input->dims(), ".")); } @@ -278,7 +285,7 @@ Status GetPauliSums(OpKernelContext* context, context->device()->tensorflow_cpu_worker_threads()->workers->ParallelFor( sum_specs.dimension(0) * sum_specs.dimension(1), cycle_estimate, DoWork); - return Status::OK(); + return ::tensorflow::Status(); } Status GetSymbolMaps(OpKernelContext* context, std::vector* maps) { @@ -290,7 +297,8 @@ Status GetSymbolMaps(OpKernelContext* context, std::vector* maps) { } if (input_names->dims() != 1) { - return Status(tensorflow::error::INVALID_ARGUMENT, + return Status(static_cast( + absl::StatusCode::kInvalidArgument), absl::StrCat("symbol_names must be rank 1. Got rank ", input_names->dims(), ".")); } @@ -302,7 +310,8 @@ Status GetSymbolMaps(OpKernelContext* context, std::vector* maps) { } if (input_values->dims() != 2) { - return Status(tensorflow::error::INVALID_ARGUMENT, + return Status(static_cast( + absl::StatusCode::kInvalidArgument), absl::StrCat("symbol_values must be rank 2. Got rank ", input_values->dims(), ".")); } @@ -311,7 +320,8 @@ Status GetSymbolMaps(OpKernelContext* context, std::vector* maps) { const auto symbol_values = input_values->matrix(); if (symbol_names.dimension(0) != symbol_values.dimension(1)) { - return Status(tensorflow::error::INVALID_ARGUMENT, + return Status(static_cast( + absl::StatusCode::kInvalidArgument), "Input symbol names and value sizes do not match."); } @@ -333,7 +343,7 @@ Status GetSymbolMaps(OpKernelContext* context, std::vector* maps) { context->device()->tensorflow_cpu_worker_threads()->workers->ParallelFor( symbol_values.dimension(0), cycle_estimate, DoWork); - return Status::OK(); + return ::tensorflow::Status(); } tensorflow::Status GetNumSamples( @@ -346,7 +356,8 @@ tensorflow::Status GetNumSamples( } if (input_num_samples->dims() != 2) { - return Status(tensorflow::error::INVALID_ARGUMENT, + return Status(static_cast( + absl::StatusCode::kInvalidArgument), absl::StrCat("num_samples must be rank 2. Got rank ", input_num_samples->dims(), ".")); } @@ -359,7 +370,8 @@ tensorflow::Status GetNumSamples( for (unsigned int j = 0; j < matrix_num_samples.dimension(1); j++) { const int num_samples = matrix_num_samples(i, j); if (num_samples < 1) { - return Status(tensorflow::error::INVALID_ARGUMENT, + return Status(static_cast( + absl::StatusCode::kInvalidArgument), "Each element of num_samples must be greater than 0."); } sub_parsed_num_samples.push_back(num_samples); @@ -367,7 +379,7 @@ tensorflow::Status GetNumSamples( parsed_num_samples->push_back(sub_parsed_num_samples); } - return Status::OK(); + return ::tensorflow::Status(); } // used by tfq_simulate_samples. @@ -380,7 +392,8 @@ Status GetIndividualSample(tensorflow::OpKernelContext* context, } if (input_num_samples->dims() != 1) { - return Status(tensorflow::error::INVALID_ARGUMENT, + return Status(static_cast( + absl::StatusCode::kInvalidArgument), absl::StrCat("num_samples must be rank 1. Got rank ", input_num_samples->dims(), ".")); } @@ -388,13 +401,14 @@ Status GetIndividualSample(tensorflow::OpKernelContext* context, const auto vector_num_samples = input_num_samples->vec(); if (vector_num_samples.dimension(0) != 1) { - return Status(tensorflow::error::INVALID_ARGUMENT, + return Status(static_cast( + absl::StatusCode::kInvalidArgument), absl::StrCat("num_samples must contain 1 element. Got ", vector_num_samples.dimension(0), ".")); } (*n_samples) = vector_num_samples(0); - return Status::OK(); + return ::tensorflow::Status(); } // used by adj_grad_op. @@ -408,7 +422,8 @@ tensorflow::Status GetPrevGrads( } if (input_grads->dims() != 2) { - return Status(tensorflow::error::INVALID_ARGUMENT, + return Status(static_cast( + absl::StatusCode::kInvalidArgument), absl::StrCat("downstream_grads must be rank 2. Got rank ", input_grads->dims(), ".")); } @@ -425,7 +440,7 @@ tensorflow::Status GetPrevGrads( parsed_prev_grads->push_back(sub_parsed_grads); } - return Status::OK(); + return ::tensorflow::Status(); } } // namespace tfq diff --git a/tensorflow_quantum/core/ops/tfq_adj_grad_op.cc b/tensorflow_quantum/core/ops/tfq_adj_grad_op.cc index 7625c7962..e7252baee 100644 --- a/tensorflow_quantum/core/ops/tfq_adj_grad_op.cc +++ b/tensorflow_quantum/core/ops/tfq_adj_grad_op.cc @@ -99,7 +99,7 @@ class TfqAdjointGradientOp : public tensorflow::OpKernel { std::vector> gradient_gates( programs.size(), std::vector({})); - Status parse_status = Status::OK(); + Status parse_status = ::tensorflow::Status(); auto p_lock = tensorflow::mutex(); auto construct_f = [&](int start, int end) { for (int i = start; i < end; i++) { @@ -411,7 +411,7 @@ REGISTER_OP("TfqAdjointGradient") c->Dim(symbol_names_shape, 0); c->set_output(0, c->Matrix(output_rows, output_cols)); - return tensorflow::Status::OK(); + return ::tensorflow::Status(); }); } // namespace tfq diff --git a/tensorflow_quantum/core/ops/tfq_calculate_unitary_op.cc b/tensorflow_quantum/core/ops/tfq_calculate_unitary_op.cc index b06a7faef..ace5327e1 100644 --- a/tensorflow_quantum/core/ops/tfq_calculate_unitary_op.cc +++ b/tensorflow_quantum/core/ops/tfq_calculate_unitary_op.cc @@ -68,7 +68,7 @@ class TfqCalculateUnitaryOp : public tensorflow::OpKernel { std::vector>> fused_circuits( programs.size(), std::vector>({})); - Status parse_status = Status::OK(); + Status parse_status = ::tensorflow::Status(); auto p_lock = tensorflow::mutex(); auto construct_f = [&](int start, int end) { for (int i = start; i < end; i++) { @@ -182,7 +182,7 @@ REGISTER_OP("TfqCalculateUnitary") tensorflow::shape_inference::InferenceContext::kUnknownDim, tensorflow::shape_inference::InferenceContext::kUnknownDim})); - return tensorflow::Status::OK(); + return ::tensorflow::Status(); }); } // namespace tfq diff --git a/tensorflow_quantum/core/ops/tfq_circuit_append_op.cc b/tensorflow_quantum/core/ops/tfq_circuit_append_op.cc index 8109ccd56..582bd1681 100644 --- a/tensorflow_quantum/core/ops/tfq_circuit_append_op.cc +++ b/tensorflow_quantum/core/ops/tfq_circuit_append_op.cc @@ -90,7 +90,7 @@ REGISTER_OP("TfqAppendCircuit") c->set_output(0, c->input(0)); - return tensorflow::Status::OK(); + return ::tensorflow::Status(); }); } // namespace tfq diff --git a/tensorflow_quantum/core/ops/tfq_ps_decompose_op.cc b/tensorflow_quantum/core/ops/tfq_ps_decompose_op.cc index f4355c07c..669ea6368 100644 --- a/tensorflow_quantum/core/ops/tfq_ps_decompose_op.cc +++ b/tensorflow_quantum/core/ops/tfq_ps_decompose_op.cc @@ -326,7 +326,7 @@ REGISTER_OP("TfqPsDecompose") c->set_output(0, c->input(0)); - return tensorflow::Status::OK(); + return ::tensorflow::Status(); }); } // namespace tfq diff --git a/tensorflow_quantum/core/ops/tfq_ps_symbol_replace_op.cc b/tensorflow_quantum/core/ops/tfq_ps_symbol_replace_op.cc index 3423177b0..559fbecc9 100644 --- a/tensorflow_quantum/core/ops/tfq_ps_symbol_replace_op.cc +++ b/tensorflow_quantum/core/ops/tfq_ps_symbol_replace_op.cc @@ -206,7 +206,7 @@ REGISTER_OP("TfqPsSymbolReplace") tensorflow::shape_inference::InferenceContext::kUnknownDim, tensorflow::shape_inference::InferenceContext::kUnknownDim})); - return tensorflow::Status::OK(); + return ::tensorflow::Status(); }); } // namespace tfq diff --git a/tensorflow_quantum/core/ops/tfq_ps_weights_from_symbols_op.cc b/tensorflow_quantum/core/ops/tfq_ps_weights_from_symbols_op.cc index 94aaf6641..4a027223e 100644 --- a/tensorflow_quantum/core/ops/tfq_ps_weights_from_symbols_op.cc +++ b/tensorflow_quantum/core/ops/tfq_ps_weights_from_symbols_op.cc @@ -184,7 +184,7 @@ REGISTER_OP("TfqPsWeightsFromSymbols") tensorflow::shape_inference::InferenceContext::kUnknownDim, tensorflow::shape_inference::InferenceContext::kUnknownDim})); - return tensorflow::Status::OK(); + return ::tensorflow::Status(); }); } // namespace tfq diff --git a/tensorflow_quantum/core/ops/tfq_resolve_parameters_op.cc b/tensorflow_quantum/core/ops/tfq_resolve_parameters_op.cc index 3ef3277d2..8d7ce06cf 100644 --- a/tensorflow_quantum/core/ops/tfq_resolve_parameters_op.cc +++ b/tensorflow_quantum/core/ops/tfq_resolve_parameters_op.cc @@ -59,7 +59,7 @@ class TfqResolveParametersOp : public tensorflow::OpKernel { "Number of circuits and values do not match. Got ", programs.size(), " circuits and ", maps.size(), " values."))); - Status parse_status = Status::OK(); + Status parse_status = ::tensorflow::Status(); auto p_lock = tensorflow::mutex(); auto DoWork = [&](int start, int end) { std::string temp; @@ -100,7 +100,7 @@ REGISTER_OP("TfqResolveParameters") c->set_output(0, c->input(0)); - return tensorflow::Status::OK(); + return ::tensorflow::Status(); }); } // namespace tfq diff --git a/tensorflow_quantum/core/ops/tfq_simulate_expectation_op.cc b/tensorflow_quantum/core/ops/tfq_simulate_expectation_op.cc index e8499f482..bca6d2f63 100644 --- a/tensorflow_quantum/core/ops/tfq_simulate_expectation_op.cc +++ b/tensorflow_quantum/core/ops/tfq_simulate_expectation_op.cc @@ -86,7 +86,7 @@ class TfqSimulateExpectationOp : public tensorflow::OpKernel { std::vector>> fused_circuits( programs.size(), std::vector>({})); - Status parse_status = Status::OK(); + Status parse_status = ::tensorflow::Status(); auto p_lock = tensorflow::mutex(); auto construct_f = [&](int start, int end) { for (int i = start; i < end; i++) { @@ -186,7 +186,7 @@ class TfqSimulateExpectationOp : public tensorflow::OpKernel { const int output_dim_op_size = output_tensor->dimension(1); - Status compute_status = Status::OK(); + Status compute_status = ::tensorflow::Status(); auto c_lock = tensorflow::mutex(); auto DoWork = [&](int start, int end) { int old_batch_index = -2; @@ -274,7 +274,7 @@ REGISTER_OP("TfqSimulateExpectation") c->Dim(pauli_sums_shape, 1); c->set_output(0, c->Matrix(output_rows, output_cols)); - return tensorflow::Status::OK(); + return ::tensorflow::Status(); }); } // namespace tfq diff --git a/tensorflow_quantum/core/ops/tfq_simulate_sampled_expectation_op.cc b/tensorflow_quantum/core/ops/tfq_simulate_sampled_expectation_op.cc index 0452f2750..e0ed05a49 100644 --- a/tensorflow_quantum/core/ops/tfq_simulate_sampled_expectation_op.cc +++ b/tensorflow_quantum/core/ops/tfq_simulate_sampled_expectation_op.cc @@ -105,7 +105,7 @@ class TfqSimulateSampledExpectationOp : public tensorflow::OpKernel { std::vector>> fused_circuits( programs.size(), std::vector>({})); - Status parse_status = Status::OK(); + Status parse_status = ::tensorflow::Status(); auto p_lock = tensorflow::mutex(); auto construct_f = [&](int start, int end) { for (int i = start; i < end; i++) { @@ -231,7 +231,7 @@ class TfqSimulateSampledExpectationOp : public tensorflow::OpKernel { ->tensorflow_cpu_worker_threads() ->workers->NumThreads(); - Status compute_status = Status::OK(); + Status compute_status = ::tensorflow::Status(); auto c_lock = tensorflow::mutex(); auto DoWork = [&](int start, int end) { int old_batch_index = -2; @@ -333,7 +333,7 @@ REGISTER_OP("TfqSimulateSampledExpectation") c->Dim(pauli_sums_shape, 1); c->set_output(0, c->Matrix(output_rows, output_cols)); - return tensorflow::Status::OK(); + return ::tensorflow::Status(); }); } // namespace tfq diff --git a/tensorflow_quantum/core/ops/tfq_simulate_samples_op.cc b/tensorflow_quantum/core/ops/tfq_simulate_samples_op.cc index f9ea8c4a3..0e68020e9 100644 --- a/tensorflow_quantum/core/ops/tfq_simulate_samples_op.cc +++ b/tensorflow_quantum/core/ops/tfq_simulate_samples_op.cc @@ -77,7 +77,7 @@ class TfqSimulateSamplesOp : public tensorflow::OpKernel { std::vector>> fused_circuits( programs.size(), std::vector>({})); - Status parse_status = Status::OK(); + Status parse_status = ::tensorflow::Status(); auto p_lock = tensorflow::mutex(); auto construct_f = [&](int start, int end) { for (int i = start; i < end; i++) { @@ -281,7 +281,7 @@ REGISTER_OP("TfqSimulateSamples") tensorflow::shape_inference::InferenceContext::kUnknownDim, tensorflow::shape_inference::InferenceContext::kUnknownDim})); - return tensorflow::Status::OK(); + return ::tensorflow::Status(); }); } // namespace tfq diff --git a/tensorflow_quantum/core/ops/tfq_simulate_state_op.cc b/tensorflow_quantum/core/ops/tfq_simulate_state_op.cc index 6d74f18b0..e659800ce 100644 --- a/tensorflow_quantum/core/ops/tfq_simulate_state_op.cc +++ b/tensorflow_quantum/core/ops/tfq_simulate_state_op.cc @@ -69,7 +69,7 @@ class TfqSimulateStateOp : public tensorflow::OpKernel { std::vector>> fused_circuits( programs.size(), std::vector>({})); - Status parse_status = Status::OK(); + Status parse_status = ::tensorflow::Status(); auto p_lock = tensorflow::mutex(); auto construct_f = [&](int start, int end) { for (int i = start; i < end; i++) { @@ -238,7 +238,7 @@ REGISTER_OP("TfqSimulateState") {c->Dim(programs_shape, 0), tensorflow::shape_inference::InferenceContext::kUnknownDim})); - return tensorflow::Status::OK(); + return ::tensorflow::Status(); }); } // namespace tfq diff --git a/tensorflow_quantum/core/ops/tfq_utility_ops_test.py b/tensorflow_quantum/core/ops/tfq_utility_ops_test.py index 8eab57ae7..00c5ff791 100644 --- a/tensorflow_quantum/core/ops/tfq_utility_ops_test.py +++ b/tensorflow_quantum/core/ops/tfq_utility_ops_test.py @@ -82,7 +82,7 @@ def test_append_input_checking(self): # These tests really just makes sure we can cast output res = tfq_utility_ops.append_circuit([], []) - self.assertDTypeEqual(res.numpy().astype(np.str), np.dtype(' str: msg.arg_value.string_value = value elif (isinstance(value, (list, tuple, np.ndarray)) and all(isinstance(x, (bool, np.bool_)) for x in value)): - # Some protobuf / numpy combinations do not support np.bool_, so cast. + # Some protobuf / numpy combinations do not support bool_, so cast. msg.arg_value.bool_values.values.extend([bool(x) for x in value]) elif isinstance(value, sympy.Symbol): msg.symbol = str(value.free_symbols.pop()) diff --git a/tensorflow_quantum/core/serialize/op_serializer_test.py b/tensorflow_quantum/core/serialize/op_serializer_test.py index 7597d6a47..a485091e7 100644 --- a/tensorflow_quantum/core/serialize/op_serializer_test.py +++ b/tensorflow_quantum/core/serialize/op_serializer_test.py @@ -108,7 +108,7 @@ def get_val(op): } } }), - (List[bool], np.array([True, False], dtype=np.bool), { + (List[bool], np.array([True, False], dtype=np.bool_), { 'arg_value': { 'bool_values': { 'values': [True, False] diff --git a/tensorflow_quantum/core/src/BUILD b/tensorflow_quantum/core/src/BUILD index 9e9bf3c17..5595a5ca2 100644 --- a/tensorflow_quantum/core/src/BUILD +++ b/tensorflow_quantum/core/src/BUILD @@ -21,6 +21,7 @@ cc_library( hdrs = ["adj_util.h"], deps = [ ":circuit_parser_qsim", + "@com_google_absl//absl/status", "@qsim//lib:circuit", "@qsim//lib:fuser", "@qsim//lib:fuser_basic", @@ -38,6 +39,8 @@ cc_test( ":adj_util", ":circuit_parser_qsim", "@com_google_googletest//:gtest_main", + "@com_google_absl//absl/status", + "@local_config_tf//:libtensorflow_framework", "@qsim//lib:gates_cirq", "@qsim//lib:matrix", ], @@ -52,6 +55,7 @@ cc_library( "//tensorflow_quantum/core/proto:program_cc_proto", "//tensorflow_quantum/core/proto:projector_sum_cc_proto", "@com_google_absl//absl/container:flat_hash_map", + "@com_google_absl//absl/status", "@local_config_tf//:libtensorflow_framework", "@local_config_tf//:tf_header_lib", "@qsim//lib:channel", @@ -127,6 +131,7 @@ cc_library( "@com_google_absl//absl/container:flat_hash_map", "@com_google_absl//absl/container:flat_hash_set", "@com_google_absl//absl/strings", + "@com_google_absl//absl/status", "@local_config_tf//:libtensorflow_framework", "@local_config_tf//:tf_header_lib", ], @@ -141,7 +146,9 @@ cc_test( ":program_resolution", "//tensorflow_quantum/core/proto:program_cc_proto", "@com_google_absl//absl/container:flat_hash_map", + "@com_google_absl//absl/status", "@com_google_googletest//:gtest_main", + "@local_config_tf//:libtensorflow_framework", "@local_config_tf//:tf_header_lib", ], ) diff --git a/tensorflow_quantum/core/src/circuit_parser_qsim.cc b/tensorflow_quantum/core/src/circuit_parser_qsim.cc index 8a7b2d490..1024d28c7 100644 --- a/tensorflow_quantum/core/src/circuit_parser_qsim.cc +++ b/tensorflow_quantum/core/src/circuit_parser_qsim.cc @@ -29,6 +29,7 @@ limitations under the License. #include "absl/container/flat_hash_map.h" #include "absl/strings/numbers.h" #include "absl/strings/str_split.h" +#include "absl/strings/string_view.h" #include "absl/types/optional.h" #include "tensorflow/core/lib/core/status.h" #include "tensorflow_quantum/core/proto/pauli_sum.pb.h" @@ -57,7 +58,8 @@ inline Status ParseProtoArg( // iterator> const auto arg_v = op.args().find(arg_name); if (arg_v == op.args().end()) { - return Status(tensorflow::error::INVALID_ARGUMENT, + return Status(static_cast( + absl::StatusCode::kInvalidArgument), "Could not find arg: " + arg_name + " in op."); } // find proto arg field. @@ -69,7 +71,8 @@ inline Status ParseProtoArg( const auto iter = param_map.find(proto_arg.symbol()); if (iter == param_map.end()) { return Status( - tensorflow::error::INVALID_ARGUMENT, + static_cast( + absl::StatusCode::kInvalidArgument), "Could not find symbol in parameter map: " + proto_arg.symbol()); } *result = iter->second.second; @@ -77,7 +80,7 @@ inline Status ParseProtoArg( symbol_used->emplace(iter->first); } } - return Status::OK(); + return ::tensorflow::Status(); } inline Status ParseProtoControls(const Operation& op, @@ -91,7 +94,7 @@ inline Status ParseProtoControls(const Operation& op, if (control_str == "" && control_v_str == "") { // empty default value set in serializer.py - return Status::OK(); + return ::tensorflow::Status(); } std::vector control_toks = @@ -100,11 +103,12 @@ inline Status ParseProtoControls(const Operation& op, absl::StrSplit(control_v_str, ','); if (control_toks.size() != control_v_toks.size()) { - return Status(tensorflow::error::INVALID_ARGUMENT, + return Status(static_cast( + absl::StatusCode::kInvalidArgument), "Mistmatched number of control qubits and control values."); } if (control_toks.empty()) { - return Status::OK(); + return ::tensorflow::Status(); } bool valid; unsigned int tmp; @@ -119,12 +123,13 @@ inline Status ParseProtoControls(const Operation& op, for (auto tok : control_v_toks) { valid = absl::SimpleAtoi(tok, &tmp); if (!valid) { - return Status(tensorflow::error::INVALID_ARGUMENT, + return Status(static_cast( + absl::StatusCode::kInvalidArgument), "Unparseable control value: " + std::string(tok)); } control_values->push_back(tmp); } - return Status::OK(); + return ::tensorflow::Status(); } inline Status OptionalInsertControls(const Operation& op, @@ -138,10 +143,10 @@ inline Status OptionalInsertControls(const Operation& op, return s; } if (control_qubits.empty()) { - return Status::OK(); + return ::tensorflow::Status(); } qsim::MakeControlledGate(control_qubits, control_values, *gate); - return Status::OK(); + return ::tensorflow::Status(); } // series of fixed signature gate builders. @@ -170,7 +175,7 @@ inline Status SingleConstantGate( info.index = circuit->gates.size() - 1; metadata->push_back(info); } - return Status::OK(); + return ::tensorflow::Status(); } // two qubit gate Create(time, q0, q1) @@ -196,7 +201,7 @@ inline Status TwoConstantGate( info.index = circuit->gates.size() - 1; metadata->push_back(info); } - return Status::OK(); + return ::tensorflow::Status(); } // single qubit eigen -> Create(time, q0, exponent, global_shift) @@ -245,7 +250,7 @@ inline Status SingleEigenGate( } metadata->push_back(info); } - return Status::OK(); + return ::tensorflow::Status(); } // two qubit eigen -> Create(time, q0, q1, exp, gs) @@ -296,7 +301,7 @@ inline Status TwoEigenGate( } metadata->push_back(info); } - return Status::OK(); + return ::tensorflow::Status(); } Status IGate(const Operation& op, const SymbolMap& param_map, @@ -447,7 +452,7 @@ inline Status PhasedXGate(const Operation& op, const SymbolMap& param_map, } metadata->push_back(info); } - return Status::OK(); + return ::tensorflow::Status(); } // two qubit fsim -> Create(time, q0, q1, theta, phi) @@ -504,7 +509,7 @@ inline Status FsimGate(const Operation& op, const SymbolMap& param_map, } metadata->push_back(info); } - return Status::OK(); + return ::tensorflow::Status(); } // two qubit phase iswap -> Create(time, q0, q1, pexp, exp) @@ -562,7 +567,7 @@ inline Status PhasedISwapGate(const Operation& op, const SymbolMap& param_map, } metadata->push_back(info); } - return Status::OK(); + return ::tensorflow::Status(); } tensorflow::Status ParseAppendGate(const Operation& op, @@ -590,7 +595,8 @@ tensorflow::Status ParseAppendGate(const Operation& op, auto build_f = func_map.find(op.gate().id()); if (build_f == func_map.end()) { *lookup_succeeded = false; - return Status(tensorflow::error::INVALID_ARGUMENT, + return Status(static_cast( + absl::StatusCode::kInvalidArgument), absl::StrCat("Could not parse gate id: ", op.gate().id(), ". This is likely because a cirq.Channel was " "used in an op that does not support them.")); @@ -618,7 +624,7 @@ inline Status AsymmetricDepolarizingChannel(const Operation& op, auto chan = qsim::Cirq::AsymmetricDepolarizingChannel::Create( time, num_qubits - q - 1, p_x, p_y, p_z); ncircuit->channels.push_back(chan); - return Status::OK(); + return ::tensorflow::Status(); } inline Status DepolarizingChannel(const Operation& op, @@ -638,7 +644,7 @@ inline Status DepolarizingChannel(const Operation& op, auto chan = qsim::Cirq::DepolarizingChannel::Create( time, num_qubits - q - 1, p); ncircuit->channels.push_back(chan); - return Status::OK(); + return ::tensorflow::Status(); } inline Status GADChannel(const Operation& op, const unsigned int num_qubits, @@ -661,7 +667,7 @@ inline Status GADChannel(const Operation& op, const unsigned int num_qubits, auto chan = qsim::Cirq::GeneralizedAmplitudeDampingChannel::Create( time, num_qubits - q - 1, p, gamma); ncircuit->channels.push_back(chan); - return Status::OK(); + return ::tensorflow::Status(); } inline Status ResetChannel(const Operation& op, const unsigned int num_qubits, @@ -673,7 +679,7 @@ inline Status ResetChannel(const Operation& op, const unsigned int num_qubits, auto chan = qsim::Cirq::ResetChannel::Create(time, num_qubits - q - 1); ncircuit->channels.push_back(chan); - return Status::OK(); + return ::tensorflow::Status(); } inline Status AmplitudeDampingChannel(const Operation& op, @@ -693,7 +699,7 @@ inline Status AmplitudeDampingChannel(const Operation& op, auto chan = qsim::Cirq::AmplitudeDampingChannel::Create( time, num_qubits - q - 1, gamma); ncircuit->channels.push_back(chan); - return Status::OK(); + return ::tensorflow::Status(); } inline Status PhaseDampingChannel(const Operation& op, @@ -714,7 +720,7 @@ inline Status PhaseDampingChannel(const Operation& op, auto chan = qsim::Cirq::PhaseDampingChannel::Create( time, num_qubits - q - 1, gamma); ncircuit->channels.push_back(chan); - return Status::OK(); + return ::tensorflow::Status(); } inline Status PhaseFlipChannel(const Operation& op, @@ -735,7 +741,7 @@ inline Status PhaseFlipChannel(const Operation& op, auto chan = qsim::Cirq::PhaseFlipChannel::Create(time, num_qubits - q - 1, p); ncircuit->channels.push_back(chan); - return Status::OK(); + return ::tensorflow::Status(); } inline Status BitFlipChannel(const Operation& op, const unsigned int num_qubits, @@ -755,7 +761,7 @@ inline Status BitFlipChannel(const Operation& op, const unsigned int num_qubits, auto chan = qsim::Cirq::BitFlipChannel::Create(time, num_qubits - q - 1, p); ncircuit->channels.push_back(chan); - return Status::OK(); + return ::tensorflow::Status(); } tensorflow::Status ParseAppendChannel(const Operation& op, @@ -774,7 +780,8 @@ tensorflow::Status ParseAppendChannel(const Operation& op, auto build_f = chan_func_map.find(op.gate().id()); if (build_f == chan_func_map.end()) { - return Status(tensorflow::error::INVALID_ARGUMENT, + return Status(static_cast( + absl::StatusCode::kInvalidArgument), absl::StrCat("Could not parse channel id: ", op.gate().id())); } return build_f->second(op, num_qubits, time, ncircuit); @@ -790,7 +797,7 @@ tensorflow::Status NoisyQsimCircuitFromProgram(const Program& program, // Special case empty. ncircuit->num_qubits = num_qubits; if (num_qubits <= 0) { - return Status::OK(); + return ::tensorflow::Status(); } int time = 0; @@ -834,7 +841,7 @@ tensorflow::Status NoisyQsimCircuitFromProgram(const Program& program, {qsim::gate::Measurement::Create(time, all_qbs)}}}); } - return Status::OK(); + return ::tensorflow::Status(); } tensorflow::Status QsimCircuitFromProgram( @@ -847,7 +854,7 @@ tensorflow::Status QsimCircuitFromProgram( bool unused; // Special case empty. if (num_qubits <= 0) { - return Status::OK(); + return ::tensorflow::Status(); } circuit->gates.reserve(program.circuit().moments_size() * num_qubits); @@ -869,7 +876,7 @@ tensorflow::Status QsimCircuitFromProgram( *fused_circuit = qsim::BasicGateFuser().FuseGates( qsim::BasicGateFuser::Parameter(), circuit->num_qubits, circuit->gates); - return Status::OK(); + return ::tensorflow::Status(); } Status QsimCircuitFromPauliTerm( diff --git a/tensorflow_quantum/core/src/circuit_parser_qsim_test.cc b/tensorflow_quantum/core/src/circuit_parser_qsim_test.cc index 4cfb40424..e6ea68e80 100644 --- a/tensorflow_quantum/core/src/circuit_parser_qsim_test.cc +++ b/tensorflow_quantum/core/src/circuit_parser_qsim_test.cc @@ -149,7 +149,7 @@ TEST_P(TwoQubitEigenFixture, TwoEigenGate) { // Test case where we have a placeholder. ASSERT_EQ(QsimCircuitFromProgram(program_proto, symbol_map, 2, &test_circuit, &fused_circuit, &metadata), - tensorflow::Status::OK()); + ::tensorflow::Status()); AssertTwoQubitEqual(test_circuit.gates[0], ref_gate); EXPECT_EQ(metadata[0].index, 0); EXPECT_EQ(metadata[0].symbol_values[0], "placeholder"); @@ -172,7 +172,7 @@ TEST_P(TwoQubitEigenFixture, TwoEigenGate) { // Test case where we have all float values. ASSERT_EQ(QsimCircuitFromProgram(program_proto, symbol_map, 2, &test_circuit, &fused_circuit, &metadata), - tensorflow::Status::OK()); + ::tensorflow::Status()); AssertTwoQubitEqual(test_circuit.gates[0], ref_gate); EXPECT_EQ(metadata[0].index, 0); EXPECT_NEAR(metadata[0].gate_params[0], exp, 1e-5); @@ -191,7 +191,8 @@ TEST_P(TwoQubitEigenFixture, TwoEigenGate) { // Test case where proto arg missing. ASSERT_EQ(QsimCircuitFromProgram(program_proto, symbol_map, 2, &test_circuit, &fused_circuit), - tensorflow::Status(tensorflow::error::INVALID_ARGUMENT, + tensorflow::Status(static_cast( + absl::StatusCode::kInvalidArgument), "Could not find arg: exponent in op.")); test_circuit.gates.clear(); @@ -203,7 +204,8 @@ TEST_P(TwoQubitEigenFixture, TwoEigenGate) { ASSERT_EQ( QsimCircuitFromProgram(program_proto, symbol_map, 2, &test_circuit, &fused_circuit), - tensorflow::Status(tensorflow::error::INVALID_ARGUMENT, + tensorflow::Status(static_cast( + absl::StatusCode::kInvalidArgument), "Could not find symbol in parameter map: alpha")); } @@ -250,7 +252,7 @@ TEST_P(TwoQubitEigenFixture, TwoEigenGateControlled) { // Test case where we have a placeholder. ASSERT_EQ(QsimCircuitFromProgram(program_proto, symbol_map, 4, &test_circuit, &fused_circuit, &metadata), - tensorflow::Status::OK()); + ::tensorflow::Status()); AssertTwoQubitEqual(test_circuit.gates[0], ref_gate); EXPECT_EQ(metadata[0].index, 0); EXPECT_EQ(metadata[0].symbol_values[0], "placeholder"); @@ -319,7 +321,7 @@ TEST_P(SingleQubitEigenFixture, SingleEigenGate) { ASSERT_EQ(QsimCircuitFromProgram(program_proto, symbol_map, 1, &test_circuit, &fused_circuit, &metadata), - tensorflow::Status::OK()); + ::tensorflow::Status()); AssertOneQubitEqual(test_circuit.gates[0], ref_gate); EXPECT_EQ(metadata[0].index, 0); EXPECT_EQ(metadata[0].symbol_values[0], "placeholder"); @@ -342,7 +344,7 @@ TEST_P(SingleQubitEigenFixture, SingleEigenGate) { // Test case where we have all float values. ASSERT_EQ(QsimCircuitFromProgram(program_proto, symbol_map, 1, &test_circuit, &fused_circuit, &metadata), - tensorflow::Status::OK()); + ::tensorflow::Status()); AssertOneQubitEqual(test_circuit.gates[0], ref_gate); EXPECT_EQ(metadata[0].index, 0); EXPECT_NEAR(metadata[0].gate_params[0], exp, 1e-5); @@ -361,7 +363,8 @@ TEST_P(SingleQubitEigenFixture, SingleEigenGate) { // Test case where proto arg missing. ASSERT_EQ(QsimCircuitFromProgram(program_proto, symbol_map, 1, &test_circuit, &fused_circuit), - tensorflow::Status(tensorflow::error::INVALID_ARGUMENT, + tensorflow::Status(static_cast( + absl::StatusCode::kInvalidArgument), "Could not find arg: exponent in op.")); test_circuit.gates.clear(); @@ -373,7 +376,8 @@ TEST_P(SingleQubitEigenFixture, SingleEigenGate) { ASSERT_EQ( QsimCircuitFromProgram(program_proto, symbol_map, 1, &test_circuit, &fused_circuit), - tensorflow::Status(tensorflow::error::INVALID_ARGUMENT, + tensorflow::Status(static_cast( + absl::StatusCode::kInvalidArgument), "Could not find symbol in parameter map: alpha")); } @@ -418,7 +422,7 @@ TEST_P(SingleQubitEigenFixture, SingleEigenGateControlled) { ASSERT_EQ(QsimCircuitFromProgram(program_proto, symbol_map, 3, &test_circuit, &fused_circuit, &metadata), - tensorflow::Status::OK()); + ::tensorflow::Status()); AssertOneQubitEqual(test_circuit.gates[0], ref_gate); EXPECT_EQ(metadata[0].index, 0); EXPECT_EQ(metadata[0].symbol_values[0], "placeholder"); @@ -471,7 +475,7 @@ TEST(QsimCircuitParserTest, SingleConstantGate) { ASSERT_EQ(QsimCircuitFromProgram(program_proto, empty_map, 1, &test_circuit, &fused_circuit, &metadata), - tensorflow::Status::OK()); + ::tensorflow::Status()); AssertOneQubitEqual(test_circuit.gates[0], kv.second); EXPECT_EQ(metadata.size(), 1); EXPECT_EQ(metadata[0].placeholder_names.size(), 0); @@ -511,7 +515,7 @@ TEST(QsimCircuitParserTest, SingleConstantGateControlled) { ASSERT_EQ(QsimCircuitFromProgram(program_proto, empty_map, 3, &test_circuit, &fused_circuit, &metadata), - tensorflow::Status::OK()); + ::tensorflow::Status()); AssertOneQubitEqual(test_circuit.gates[0], kv.second); EXPECT_EQ(metadata.size(), 1); EXPECT_EQ(metadata[0].placeholder_names.size(), 0); @@ -553,7 +557,7 @@ TEST(QsimCircuitParserTest, TwoConstantGate) { ASSERT_EQ(QsimCircuitFromProgram(program_proto, empty_map, 2, &test_circuit, &fused_circuit, &metadata), - tensorflow::Status::OK()); + ::tensorflow::Status()); AssertTwoQubitEqual(test_circuit.gates[0], kv.second); EXPECT_EQ(metadata.size(), 1); EXPECT_EQ(metadata[0].placeholder_names.size(), 0); @@ -596,7 +600,7 @@ TEST(QsimCircuitParserTest, TwoConstantGateControlled) { ASSERT_EQ(QsimCircuitFromProgram(program_proto, empty_map, 4, &test_circuit, &fused_circuit, &metadata), - tensorflow::Status::OK()); + ::tensorflow::Status()); AssertTwoQubitEqual(test_circuit.gates[0], kv.second); EXPECT_EQ(metadata.size(), 1); EXPECT_EQ(metadata[0].placeholder_names.size(), 0); @@ -646,7 +650,7 @@ TEST(QsimCircuitParserTest, FsimGate) { // Test symbol resolution. ASSERT_EQ(QsimCircuitFromProgram(program_proto, symbol_map, 2, &test_circuit, &fused_circuit, &metadata), - tensorflow::Status::OK()); + ::tensorflow::Status()); AssertTwoQubitEqual(test_circuit.gates[0], reference); EXPECT_EQ(metadata.size(), 1); EXPECT_EQ(metadata[0].placeholder_names.size(), 2); @@ -673,7 +677,7 @@ TEST(QsimCircuitParserTest, FsimGate) { // Test float values only. ASSERT_EQ(QsimCircuitFromProgram(program_proto, symbol_map, 2, &test_circuit, &fused_circuit, &metadata), - tensorflow::Status::OK()); + ::tensorflow::Status()); AssertTwoQubitEqual(test_circuit.gates[0], reference); EXPECT_EQ(metadata.size(), 1); EXPECT_EQ(metadata[0].placeholder_names.size(), 0); @@ -691,7 +695,8 @@ TEST(QsimCircuitParserTest, FsimGate) { // Test case where proto arg missing. ASSERT_EQ(QsimCircuitFromProgram(program_proto, symbol_map, 2, &test_circuit, &fused_circuit), - tensorflow::Status(tensorflow::error::INVALID_ARGUMENT, + tensorflow::Status(static_cast( + absl::StatusCode::kInvalidArgument), "Could not find arg: theta in op.")); test_circuit.gates.clear(); @@ -703,7 +708,8 @@ TEST(QsimCircuitParserTest, FsimGate) { ASSERT_EQ( QsimCircuitFromProgram(program_proto, symbol_map, 2, &test_circuit, &fused_circuit), - tensorflow::Status(tensorflow::error::INVALID_ARGUMENT, + tensorflow::Status(static_cast( + absl::StatusCode::kInvalidArgument), "Could not find symbol in parameter map: alpha")); } @@ -749,7 +755,7 @@ TEST(QsimCircuitParserTest, FsimGateControlled) { // Test symbol resolution. ASSERT_EQ(QsimCircuitFromProgram(program_proto, symbol_map, 4, &test_circuit, &fused_circuit, &metadata), - tensorflow::Status::OK()); + ::tensorflow::Status()); AssertTwoQubitEqual(test_circuit.gates[0], reference); EXPECT_EQ(metadata.size(), 1); EXPECT_EQ(metadata[0].placeholder_names.size(), 2); @@ -808,7 +814,7 @@ TEST(QsimCircuitParserTest, PhasedISwap) { // Test symbol resolution. ASSERT_EQ(QsimCircuitFromProgram(program_proto, symbol_map, 2, &test_circuit, &fused_circuit, &metadata), - tensorflow::Status::OK()); + ::tensorflow::Status()); AssertTwoQubitEqual(test_circuit.gates[0], reference); EXPECT_EQ(metadata.size(), 1); EXPECT_EQ(metadata[0].placeholder_names.size(), 2); @@ -835,7 +841,7 @@ TEST(QsimCircuitParserTest, PhasedISwap) { // Test float values only. ASSERT_EQ(QsimCircuitFromProgram(program_proto, symbol_map, 2, &test_circuit, &fused_circuit, &metadata), - tensorflow::Status::OK()); + ::tensorflow::Status()); AssertTwoQubitEqual(test_circuit.gates[0], reference); EXPECT_EQ(metadata.size(), 1); EXPECT_EQ(metadata[0].placeholder_names.size(), 0); @@ -853,7 +859,8 @@ TEST(QsimCircuitParserTest, PhasedISwap) { // Test case where proto arg missing. ASSERT_EQ(QsimCircuitFromProgram(program_proto, symbol_map, 2, &test_circuit, &fused_circuit), - tensorflow::Status(tensorflow::error::INVALID_ARGUMENT, + tensorflow::Status(static_cast( + absl::StatusCode::kInvalidArgument), "Could not find arg: phase_exponent in op.")); test_circuit.gates.clear(); @@ -865,7 +872,8 @@ TEST(QsimCircuitParserTest, PhasedISwap) { ASSERT_EQ( QsimCircuitFromProgram(program_proto, symbol_map, 2, &test_circuit, &fused_circuit), - tensorflow::Status(tensorflow::error::INVALID_ARGUMENT, + tensorflow::Status(static_cast( + absl::StatusCode::kInvalidArgument), "Could not find symbol in parameter map: alpha")); } @@ -913,7 +921,7 @@ TEST(QsimCircuitParserTest, PhasedISwapControlled) { // Test symbol resolution. ASSERT_EQ(QsimCircuitFromProgram(program_proto, symbol_map, 4, &test_circuit, &fused_circuit, &metadata), - tensorflow::Status::OK()); + ::tensorflow::Status()); AssertTwoQubitEqual(test_circuit.gates[0], reference); EXPECT_EQ(metadata.size(), 1); EXPECT_EQ(metadata[0].placeholder_names.size(), 2); @@ -972,7 +980,7 @@ TEST(QsimCircuitParserTest, PhasedXPow) { // Test symbol resolution. ASSERT_EQ(QsimCircuitFromProgram(program_proto, symbol_map, 1, &test_circuit, &fused_circuit, &metadata), - tensorflow::Status::OK()); + ::tensorflow::Status()); AssertOneQubitEqual(test_circuit.gates[0], reference); EXPECT_EQ(metadata.size(), 1); EXPECT_EQ(metadata[0].placeholder_names.size(), 2); @@ -1001,7 +1009,7 @@ TEST(QsimCircuitParserTest, PhasedXPow) { // Test float values only. ASSERT_EQ(QsimCircuitFromProgram(program_proto, symbol_map, 1, &test_circuit, &fused_circuit, &metadata), - tensorflow::Status::OK()); + ::tensorflow::Status()); AssertOneQubitEqual(test_circuit.gates[0], reference); EXPECT_EQ(metadata.size(), 1); EXPECT_EQ(metadata[0].placeholder_names.size(), 0); @@ -1019,7 +1027,8 @@ TEST(QsimCircuitParserTest, PhasedXPow) { // Test case where proto arg missing. ASSERT_EQ(QsimCircuitFromProgram(program_proto, symbol_map, 1, &test_circuit, &fused_circuit), - tensorflow::Status(tensorflow::error::INVALID_ARGUMENT, + tensorflow::Status(static_cast( + absl::StatusCode::kInvalidArgument), "Could not find arg: phase_exponent in op.")); test_circuit.gates.clear(); @@ -1031,7 +1040,8 @@ TEST(QsimCircuitParserTest, PhasedXPow) { ASSERT_EQ( QsimCircuitFromProgram(program_proto, symbol_map, 1, &test_circuit, &fused_circuit), - tensorflow::Status(tensorflow::error::INVALID_ARGUMENT, + tensorflow::Status(static_cast( + absl::StatusCode::kInvalidArgument), "Could not find symbol in parameter map: alpha")); } @@ -1079,7 +1089,7 @@ TEST(QsimCircuitParserTest, PhasedXPowControlled) { // Test symbol resolution. ASSERT_EQ(QsimCircuitFromProgram(program_proto, symbol_map, 3, &test_circuit, &fused_circuit, &metadata), - tensorflow::Status::OK()); + ::tensorflow::Status()); AssertOneQubitEqual(test_circuit.gates[0], reference); EXPECT_EQ(metadata.size(), 1); EXPECT_EQ(metadata[0].placeholder_names.size(), 2); @@ -1124,7 +1134,8 @@ TEST(QsimCircuitParserTest, InvalidControlValues) { ASSERT_EQ(QsimCircuitFromProgram(program_proto, empty_map, 3, &test_circuit, &fused_circuit, &metadata), - tensorflow::Status(tensorflow::error::INVALID_ARGUMENT, + tensorflow::Status(static_cast( + absl::StatusCode::kInvalidArgument), "Unparseable control value: junk")); } @@ -1157,7 +1168,8 @@ TEST(QsimCircuitParserTest, MismatchControlNum) { ASSERT_EQ(QsimCircuitFromProgram(program_proto, empty_map, 3, &test_circuit, &fused_circuit, &metadata), tensorflow::Status( - tensorflow::error::INVALID_ARGUMENT, + static_cast( + absl::StatusCode::kInvalidArgument), "Mistmatched number of control qubits and control values.")); } @@ -1174,7 +1186,7 @@ TEST(QsimCircuitParserTest, EmptyTest) { // Ensure that nothing bad happens with an empty circuit. ASSERT_EQ(QsimCircuitFromProgram(program_proto, empty_map, 2, &test_circuit, &fused_circuit, &metadata), - tensorflow::Status::OK()); + ::tensorflow::Status()); ASSERT_EQ(test_circuit.gates.size(), 0); ASSERT_EQ(fused_circuit.size(), 0); ASSERT_EQ(metadata.size(), 0); @@ -1227,7 +1239,7 @@ TEST(QsimCircuitParserTest, CompoundCircuit) { ASSERT_EQ( NoisyQsimCircuitFromProgram(program_proto, {}, 2, true, &test_circuit), - tensorflow::Status::OK()); + ::tensorflow::Status()); AssertChannelEqual(test_circuit.channels[0], ref_chan); AssertOneQubitEqual(test_circuit.channels[1][0].ops[0], ref_gate); ASSERT_EQ(test_circuit.channels.size(), @@ -1270,7 +1282,7 @@ TEST(QsimCircuitParserTest, AsymmetricDepolarizing) { ASSERT_EQ( NoisyQsimCircuitFromProgram(program_proto, {}, 1, false, &test_circuit), - tensorflow::Status::OK()); + ::tensorflow::Status()); AssertChannelEqual(test_circuit.channels[0], reference); ASSERT_EQ(test_circuit.channels.size(), 1); ASSERT_EQ(test_circuit.num_qubits, 1); @@ -1307,7 +1319,7 @@ TEST(QsimCircuitParserTest, AmplitudeDamping) { ASSERT_EQ( NoisyQsimCircuitFromProgram(program_proto, {}, 1, false, &test_circuit), - tensorflow::Status::OK()); + ::tensorflow::Status()); AssertChannelEqual(test_circuit.channels[0], reference); ASSERT_EQ(test_circuit.channels.size(), 1); ASSERT_EQ(test_circuit.num_qubits, 1); @@ -1343,7 +1355,7 @@ TEST(QsimCircuitParserTest, Depolarizing) { ASSERT_EQ( NoisyQsimCircuitFromProgram(program_proto, {}, 1, false, &test_circuit), - tensorflow::Status::OK()); + ::tensorflow::Status()); AssertChannelEqual(test_circuit.channels[0], reference); ASSERT_EQ(test_circuit.channels.size(), 1); ASSERT_EQ(test_circuit.num_qubits, 1); @@ -1383,7 +1395,7 @@ TEST(QsimCircuitParserTest, GeneralizedAmplitudeDamping) { ASSERT_EQ( NoisyQsimCircuitFromProgram(program_proto, {}, 1, false, &test_circuit), - tensorflow::Status::OK()); + ::tensorflow::Status()); AssertChannelEqual(test_circuit.channels[0], reference); ASSERT_EQ(test_circuit.channels.size(), 1); ASSERT_EQ(test_circuit.num_qubits, 1); @@ -1417,7 +1429,7 @@ TEST(QsimCircuitParserTest, Reset) { ASSERT_EQ( NoisyQsimCircuitFromProgram(program_proto, {}, 1, false, &test_circuit), - tensorflow::Status::OK()); + ::tensorflow::Status()); AssertChannelEqual(test_circuit.channels[0], reference); ASSERT_EQ(test_circuit.channels.size(), 1); ASSERT_EQ(test_circuit.num_qubits, 1); @@ -1453,7 +1465,7 @@ TEST(QsimCircuitParserTest, PhaseDamping) { ASSERT_EQ( NoisyQsimCircuitFromProgram(program_proto, {}, 1, false, &test_circuit), - tensorflow::Status::OK()); + ::tensorflow::Status()); AssertChannelEqual(test_circuit.channels[0], reference); ASSERT_EQ(test_circuit.channels.size(), 1); ASSERT_EQ(test_circuit.num_qubits, 1); @@ -1489,7 +1501,7 @@ TEST(QsimCircuitParserTest, PhaseFlip) { ASSERT_EQ( NoisyQsimCircuitFromProgram(program_proto, {}, 1, false, &test_circuit), - tensorflow::Status::OK()); + ::tensorflow::Status()); AssertChannelEqual(test_circuit.channels[0], reference); ASSERT_EQ(test_circuit.channels.size(), 1); ASSERT_EQ(test_circuit.num_qubits, 1); @@ -1525,7 +1537,7 @@ TEST(QsimCircuitParserTest, BitFlip) { ASSERT_EQ( NoisyQsimCircuitFromProgram(program_proto, {}, 1, false, &test_circuit), - tensorflow::Status::OK()); + ::tensorflow::Status()); AssertChannelEqual(test_circuit.channels[0], reference); ASSERT_EQ(test_circuit.channels.size(), 1); ASSERT_EQ(test_circuit.num_qubits, 1); @@ -1540,7 +1552,7 @@ TEST(QsimCircuitParserTest, NoisyEmpty) { NoisyQsimCircuit test_circuit; ASSERT_EQ( NoisyQsimCircuitFromProgram(program_proto, {}, 0, false, &test_circuit), - tensorflow::Status::OK()); + ::tensorflow::Status()); ASSERT_EQ(test_circuit.channels.size(), 0); ASSERT_EQ(test_circuit.num_qubits, 0); } @@ -1559,7 +1571,8 @@ TEST(QsimCircuitParserTest, NoisyBadProto) { NoisyQsimCircuit test_circuit; ASSERT_EQ( NoisyQsimCircuitFromProgram(program_proto, {}, 1, false, &test_circuit), - tensorflow::Status(tensorflow::error::INVALID_ARGUMENT, + tensorflow::Status(static_cast( + absl::StatusCode::kInvalidArgument), "Could not parse channel id: ABCDEFG")); } @@ -1580,7 +1593,7 @@ TEST(QsimCircuitParserTest, CircuitFromPauliTermPauli) { // Check conversion status = QsimCircuitFromPauliTerm(pauli_proto, 1, &test_circuit, &fused_circuit); - ASSERT_EQ(status, tensorflow::Status::OK()); + ASSERT_EQ(status, tensorflow::Status()); ASSERT_EQ(test_circuit.num_qubits, 1); ASSERT_EQ(test_circuit.gates.size(), 1); AssertOneQubitEqual(test_circuit.gates[0], reference); @@ -1593,7 +1606,7 @@ TEST(QsimCircuitParserTest, CircuitFromPauliTermEmpty) { std::vector> fused_circuit; status = QsimCircuitFromPauliTerm(pauli_proto, 0, &test_circuit, &fused_circuit); - ASSERT_EQ(status, tensorflow::Status::OK()); + ASSERT_EQ(status, tensorflow::Status()); ASSERT_EQ(test_circuit.num_qubits, 0); ASSERT_EQ(test_circuit.gates.size(), 0); } @@ -1615,7 +1628,7 @@ TEST(QsimCircuitParserTest, ZBasisCircuitFromPauliTermPauliX) { // Check conversion status = QsimZBasisCircuitFromPauliTerm(pauli_proto, 1, &test_circuit, &fused_circuit); - ASSERT_EQ(status, tensorflow::Status::OK()); + ASSERT_EQ(status, tensorflow::Status()); ASSERT_EQ(test_circuit.num_qubits, 1); ASSERT_EQ(test_circuit.gates.size(), 1); AssertOneQubitEqual(test_circuit.gates[0], reference); @@ -1638,7 +1651,7 @@ TEST(QsimCircuitParserTest, ZBasisCircuitFromPauliTermPauliY) { // Check conversion status = QsimZBasisCircuitFromPauliTerm(pauli_proto, 1, &test_circuit, &fused_circuit); - ASSERT_EQ(status, tensorflow::Status::OK()); + ASSERT_EQ(status, tensorflow::Status()); ASSERT_EQ(test_circuit.num_qubits, 1); ASSERT_EQ(test_circuit.gates.size(), 1); AssertOneQubitEqual(test_circuit.gates[0], reference); @@ -1660,7 +1673,7 @@ TEST(QsimCircuitParserTest, ZBasisCircuitFromPauliTermPauliZ) { // Check conversion status = QsimZBasisCircuitFromPauliTerm(pauli_proto, 1, &test_circuit, &fused_circuit); - ASSERT_EQ(status, tensorflow::Status::OK()); + ASSERT_EQ(status, tensorflow::Status()); ASSERT_EQ(test_circuit.num_qubits, 1); ASSERT_EQ(test_circuit.gates.size(), 0); } @@ -1687,7 +1700,7 @@ TEST(QsimCircuitParserTest, ZBasisCircuitFromPauliTermPauliCompound) { // Check conversion status = QsimZBasisCircuitFromPauliTerm(pauli_proto, 2, &test_circuit, &fused_circuit); - ASSERT_EQ(status, tensorflow::Status::OK()); + ASSERT_EQ(status, tensorflow::Status()); ASSERT_EQ(test_circuit.num_qubits, 2); ASSERT_EQ(test_circuit.gates.size(), 2); AssertOneQubitEqual(test_circuit.gates[0], reference1); @@ -1701,7 +1714,7 @@ TEST(QsimCircuitParserTest, ZBasisCircuitFromPauliTermEmpty) { std::vector> fused_circuit; status = QsimZBasisCircuitFromPauliTerm(pauli_proto, 0, &test_circuit, &fused_circuit); - ASSERT_EQ(status, tensorflow::Status::OK()); + ASSERT_EQ(status, tensorflow::Status()); ASSERT_EQ(test_circuit.num_qubits, 0); ASSERT_EQ(test_circuit.gates.size(), 0); } diff --git a/tensorflow_quantum/core/src/program_resolution.cc b/tensorflow_quantum/core/src/program_resolution.cc index 82af94d35..0fbda9368 100644 --- a/tensorflow_quantum/core/src/program_resolution.cc +++ b/tensorflow_quantum/core/src/program_resolution.cc @@ -23,6 +23,7 @@ limitations under the License. #include "absl/strings/str_cat.h" #include "absl/strings/str_join.h" #include "absl/strings/str_split.h" +#include "absl/strings/string_view.h" #include "tensorflow/core/lib/core/error_codes.pb.h" #include "tensorflow/core/lib/core/status.h" #include "tensorflow_quantum/core/proto/pauli_sum.pb.h" @@ -46,13 +47,14 @@ inline absl::string_view IntMaxStr() { } Status RegisterQubits( - const std::string& qb_string, + absl::string_view qb_string, absl::flat_hash_set, std::string>>* id_set) { // Inserts qubits found in qb_string into id_set. // Supported GridQubit wire formats and line qubit wire formats. if (qb_string.empty()) { - return Status::OK(); // no control-default value specified in serializer.py + return ::tensorflow::Status(); // no control-default value specified in + // serializer.py } const std::vector qb_list = absl::StrSplit(qb_string, ','); @@ -64,22 +66,25 @@ Status RegisterQubits( } if (splits.size() != 2) { - return Status(tensorflow::error::INVALID_ARGUMENT, + return Status(static_cast( + absl::StatusCode::kInvalidArgument), absl::StrCat("Unable to parse qubit: ", qb)); } if (!absl::SimpleAtoi(splits[0], &r)) { - return Status(tensorflow::error::INVALID_ARGUMENT, + return Status(static_cast( + absl::StatusCode::kInvalidArgument), absl::StrCat("Unable to parse qubit: ", qb)); } if (!absl::SimpleAtoi(splits[1], &c)) { - return Status(tensorflow::error::INVALID_ARGUMENT, + return Status(static_cast( + absl::StatusCode::kInvalidArgument), absl::StrCat("Unable to parse qubit: ", qb)); } auto locs = std::pair, std::string>( std::pair(r, c), std::string(qb)); id_set->insert(locs); } - return Status::OK(); + return ::tensorflow::Status(); } Status ResolveQubitIds(Program* program, unsigned int* num_qubits, @@ -89,7 +94,7 @@ Status ResolveQubitIds(Program* program, unsigned int* num_qubits, // (#679) Just ignore empty program. // Number of qubits in empty programs is zero. *num_qubits = 0; - return Status::OK(); + return ::tensorflow::Status(); } absl::flat_hash_set, std::string>> id_set; @@ -167,7 +172,8 @@ Status ResolveQubitIds(Program* program, unsigned int* num_qubits, const auto result = id_to_index.find(pair.qubit_id()); if (result == id_to_index.end()) { return Status( - tensorflow::error::INVALID_ARGUMENT, + static_cast( + absl::StatusCode::kInvalidArgument), "Found a Pauli sum operating on qubits not found in circuit."); } pair.set_qubit_id(result->second); @@ -176,7 +182,7 @@ Status ResolveQubitIds(Program* program, unsigned int* num_qubits, } } - return Status::OK(); + return ::tensorflow::Status(); } Status ResolveQubitIds(Program* program, unsigned int* num_qubits, @@ -185,7 +191,7 @@ Status ResolveQubitIds(Program* program, unsigned int* num_qubits, // (#679) Just ignore empty program. // Number of qubits in empty programs is zero. *num_qubits = 0; - return Status::OK(); + return ::tensorflow::Status(); } absl::flat_hash_set, std::string>> id_set; @@ -258,7 +264,8 @@ Status ResolveQubitIds(Program* program, unsigned int* num_qubits, visited_qubits.erase(qubit.id()); const auto result = id_to_index.find(qubit.id()); if (result == id_to_index.end()) { - return Status(tensorflow::error::INVALID_ARGUMENT, + return Status(static_cast( + absl::StatusCode::kInvalidArgument), "A paired circuit contains qubits not found in " "reference circuit."); } @@ -280,7 +287,8 @@ Status ResolveQubitIds(Program* program, unsigned int* num_qubits, visited_qubits.erase(id); const auto result = id_to_index.find(id); if (result == id_to_index.end()) { - return Status(tensorflow::error::INVALID_ARGUMENT, + return Status(static_cast( + absl::StatusCode::kInvalidArgument), "A paired circuit contains qubits not found in " "reference circuit."); } @@ -294,12 +302,13 @@ Status ResolveQubitIds(Program* program, unsigned int* num_qubits, } if (!visited_qubits.empty()) { return Status( - tensorflow::error::INVALID_ARGUMENT, + static_cast( + absl::StatusCode::kInvalidArgument), "A reference circuit contains qubits not found in paired circuit."); } } - return Status::OK(); + return ::tensorflow::Status(); } Status ResolveSymbols( @@ -314,7 +323,8 @@ Status ResolveSymbols( if (iter == param_map.end()) { if (resolve_all) { return Status( - tensorflow::error::INVALID_ARGUMENT, + static_cast( + absl::StatusCode::kInvalidArgument), "Could not find symbol in parameter map: " + arg.symbol()); } continue; @@ -325,7 +335,7 @@ Status ResolveSymbols( } } - return Status::OK(); + return ::tensorflow::Status(); } Status CheckMPSSupported(const Program& program) { @@ -334,7 +344,7 @@ Status CheckMPSSupported(const Program& program) { // // Requires: program have qubit ids resolved. if (program.circuit().moments().empty()) { - return Status::OK(); + return ::tensorflow::Status(); } for (auto moment : program.circuit().moments()) { @@ -354,7 +364,8 @@ Status CheckMPSSupported(const Program& program) { const int total_num_qubits = qubits.size() + control_ids.size(); if (total_num_qubits > 2) { return Status( - tensorflow::error::INVALID_ARGUMENT, + static_cast( + absl::StatusCode::kInvalidArgument), absl::StrCat("1D operations only support 1 and 2 qubit gates. " "Found: ", total_num_qubits, " qubit gate.")); @@ -372,7 +383,8 @@ Status CheckMPSSupported(const Program& program) { // Are the two qubits not neighbors? if (std::abs((int)qids[0] - (int)qids[1]) > 1) { - return Status(tensorflow::error::INVALID_ARGUMENT, + return Status(static_cast( + absl::StatusCode::kInvalidArgument), "A program is not in 1D topology. It contains an" " operation with qubits not neighbors each other."); } @@ -380,7 +392,7 @@ Status CheckMPSSupported(const Program& program) { } } - return Status::OK(); + return ::tensorflow::Status(); } } // namespace tfq diff --git a/tensorflow_quantum/core/src/program_resolution_test.cc b/tensorflow_quantum/core/src/program_resolution_test.cc index 74a200b13..2a4e61151 100644 --- a/tensorflow_quantum/core/src/program_resolution_test.cc +++ b/tensorflow_quantum/core/src/program_resolution_test.cc @@ -187,7 +187,7 @@ TEST(ProgramResolutionTest, ResolveQubitIdsValid) { ASSERT_TRUE( google::protobuf::TextFormat::ParseFromString(valid_program, &program)); - EXPECT_EQ(ResolveQubitIds(&program, &qubit_count), Status::OK()); + EXPECT_EQ(ResolveQubitIds(&program, &qubit_count), Status()); EXPECT_EQ(qubit_count, 3); EXPECT_EQ(program.circuit().moments(0).operations(0).qubits(0).id(), "1"); EXPECT_EQ(program.circuit().moments(0).operations(0).qubits(1).id(), "2"); @@ -207,7 +207,7 @@ TEST(ProgramResolutionTest, ResolveQubitIdsValidLine) { ASSERT_TRUE(google::protobuf::TextFormat::ParseFromString(valid_line_program, &program)); - EXPECT_EQ(ResolveQubitIds(&program, &qubit_count), Status::OK()); + EXPECT_EQ(ResolveQubitIds(&program, &qubit_count), Status()); EXPECT_EQ(qubit_count, 3); EXPECT_EQ(program.circuit().moments(0).operations(0).qubits(0).id(), "1"); EXPECT_EQ(program.circuit().moments(0).operations(0).qubits(1).id(), "2"); @@ -235,7 +235,8 @@ TEST(ProgramResolutionTest, ResolveQubitIdsInvalidControlQubit) { .mutable_arg_value() ->set_string_value("junk"); EXPECT_EQ(ResolveQubitIds(&program, &qubit_count), - tensorflow::Status(tensorflow::error::INVALID_ARGUMENT, + tensorflow::Status(static_cast( + absl::StatusCode::kInvalidArgument), "Unable to parse qubit: junk")); } @@ -251,7 +252,8 @@ TEST(ProgramResolutionTest, ResolveQubitIdsInvalidQubit) { ->mutable_qubits(0) ->set_id("junk"); EXPECT_EQ(ResolveQubitIds(&program, &qubit_count), - tensorflow::Status(tensorflow::error::INVALID_ARGUMENT, + tensorflow::Status(static_cast( + absl::StatusCode::kInvalidArgument), "Unable to parse qubit: junk")); } @@ -266,7 +268,7 @@ TEST(ProgramResolutionTest, ResolveQubitIdsWithPauliSum) { google::protobuf::TextFormat::ParseFromString(valid_psum, &p_sum)); std::vector p_sums = {p_sum, p_sum}; - EXPECT_EQ(ResolveQubitIds(&program, &qubit_count, &p_sums), Status::OK()); + EXPECT_EQ(ResolveQubitIds(&program, &qubit_count, &p_sums), Status()); EXPECT_EQ(qubit_count, 3); EXPECT_EQ(program.circuit().moments(0).operations(0).qubits(0).id(), "1"); EXPECT_EQ(program.circuit().moments(0).operations(0).qubits(1).id(), "2"); @@ -300,7 +302,8 @@ TEST(ProgramResolutionTest, ResolveQubitIdsWithInvalidPauliSum) { EXPECT_EQ(ResolveQubitIds(&program, &qubit_count, &p_sums), tensorflow::Status( - tensorflow::error::INVALID_ARGUMENT, + static_cast( + absl::StatusCode::kInvalidArgument), "Found a Pauli sum operating on qubits not found in circuit.")); } @@ -327,8 +330,7 @@ TEST(ProgramResolutionTest, ResolveQubitIdsMultiProgram) { ->set_string_value("0_2"); // turn 0_0 -> 0_2! std::vector other_programs = {other, other}; - EXPECT_EQ(ResolveQubitIds(&program, &qubit_count, &other_programs), - Status::OK()); + EXPECT_EQ(ResolveQubitIds(&program, &qubit_count, &other_programs), Status()); EXPECT_EQ(qubit_count, 3); EXPECT_EQ(program.circuit().moments(0).operations(0).qubits(0).id(), "1"); EXPECT_EQ(program.circuit().moments(0).operations(0).qubits(1).id(), "2"); @@ -374,7 +376,8 @@ TEST(ProgramResolutionTest, ResolveQubitIdsMultiProgramInvalid) { ->set_id("junk"); std::vector others = {other, other}; EXPECT_EQ(ResolveQubitIds(&program, &qubit_count, &others), - tensorflow::Status(tensorflow::error::INVALID_ARGUMENT, + tensorflow::Status(static_cast( + absl::StatusCode::kInvalidArgument), "Unable to parse qubit: junk")); } @@ -394,7 +397,8 @@ TEST(ProgramResolutionTest, ResolveQubitIdsMultiProgramInvalidControl) { ->set_string_value("junk"); std::vector others = {other, other}; EXPECT_EQ(ResolveQubitIds(&program, &qubit_count, &others), - tensorflow::Status(tensorflow::error::INVALID_ARGUMENT, + tensorflow::Status(static_cast( + absl::StatusCode::kInvalidArgument), "Unable to parse qubit: junk")); } @@ -414,7 +418,8 @@ TEST(ProgramResolutionTest, ResolveQubitIdsMultiProgramMismatch) { EXPECT_EQ( ResolveQubitIds(&program, &qubit_count, &others), tensorflow::Status( - tensorflow::error::INVALID_ARGUMENT, + static_cast( + absl::StatusCode::kInvalidArgument), "A paired circuit contains qubits not found in reference circuit.")); } @@ -436,7 +441,8 @@ TEST(ProgramResolutionTest, ResolveQubitIdsMultiProgramMismatchControl) { EXPECT_EQ( ResolveQubitIds(&program, &qubit_count, &others), tensorflow::Status( - tensorflow::error::INVALID_ARGUMENT, + static_cast( + absl::StatusCode::kInvalidArgument), "A paired circuit contains qubits not found in reference circuit.")); } @@ -456,7 +462,8 @@ TEST(ProgramResolutionTest, ResolveQubitIdsMultiProgramSmaller) { EXPECT_EQ( ResolveQubitIds(&program, &qubit_count, &others), tensorflow::Status( - tensorflow::error::INVALID_ARGUMENT, + static_cast( + absl::StatusCode::kInvalidArgument), "A reference circuit contains qubits not found in paired circuit.")); } @@ -478,7 +485,8 @@ TEST(ProgramResolutionTest, ResolveQubitIdsMultiProgramSmallerControl) { EXPECT_EQ( ResolveQubitIds(&program, &qubit_count, &others), tensorflow::Status( - tensorflow::error::INVALID_ARGUMENT, + static_cast( + absl::StatusCode::kInvalidArgument), "A reference circuit contains qubits not found in paired circuit.")); } @@ -488,7 +496,7 @@ TEST(ProgramResolutionTest, ResolveSymbolsPartial) { valid_symbol_program, &symbol_program)); const absl::flat_hash_map> param_map = { {"v1", {0, 1.0}}}; - EXPECT_EQ(ResolveSymbols(param_map, &symbol_program, false), Status::OK()); + EXPECT_EQ(ResolveSymbols(param_map, &symbol_program, false), Status()); EXPECT_EQ(symbol_program.circuit() .moments(0) .operations(0) @@ -512,7 +520,7 @@ TEST(ProgramResolutionTest, ResolveSymbolsFull) { valid_symbol_program, &symbol_program)); const absl::flat_hash_map> param_map = { {"v1", {0, 1.0}}, {"v2", {1, 2.0f}}}; - EXPECT_EQ(ResolveSymbols(param_map, &symbol_program, false), Status::OK()); + EXPECT_EQ(ResolveSymbols(param_map, &symbol_program, false), Status()); EXPECT_EQ(symbol_program.circuit() .moments(0) .operations(0) @@ -538,7 +546,8 @@ TEST(ProgramResolutionTest, ResolveSymbolsStrictPartial) { const absl::flat_hash_map> param_map = { {"v1", {0, 1.0}}}; EXPECT_EQ(ResolveSymbols(param_map, &symbol_program, true), - Status(tensorflow::error::INVALID_ARGUMENT, + Status(static_cast( + absl::StatusCode::kInvalidArgument), "Could not find symbol in parameter map: v2")); } @@ -548,7 +557,7 @@ TEST(ProgramResolutionTest, ResolveSymbolsStrictFull) { valid_symbol_program, &symbol_program)); const absl::flat_hash_map> param_map = { {"v1", {0, 1.0}}, {"v2", {1, 2.0f}}}; - EXPECT_EQ(ResolveSymbols(param_map, &symbol_program, true), Status::OK()); + EXPECT_EQ(ResolveSymbols(param_map, &symbol_program, true), Status()); EXPECT_EQ(symbol_program.circuit() .moments(0) .operations(0) @@ -569,7 +578,7 @@ TEST(ProgramResolutionTest, ResolveSymbolsStrictFull) { TEST(ProgramResolutionTest, CheckMPSSupportedEmpty) { Program empty; - EXPECT_EQ(CheckMPSSupported(empty), Status::OK()); + EXPECT_EQ(CheckMPSSupported(empty), Status()); } TEST(ProgramResolutionTest, CheckQubitsIn1DFailedByOpWithMoreThan2Qubits) { @@ -577,7 +586,8 @@ TEST(ProgramResolutionTest, CheckQubitsIn1DFailedByOpWithMoreThan2Qubits) { ASSERT_TRUE(google::protobuf::TextFormat::ParseFromString( three_qubit_op_program, &program_with_3qubit_op)); EXPECT_EQ(CheckMPSSupported(program_with_3qubit_op), - Status(tensorflow::error::INVALID_ARGUMENT, + Status(static_cast( + absl::StatusCode::kInvalidArgument), "1D operations only support 1 and 2 qubit gates. " "Found: 3 qubit gate.")); } @@ -588,7 +598,8 @@ TEST(ProgramResolutionTest, ASSERT_TRUE(google::protobuf::TextFormat::ParseFromString( valid_program, &program_with_3qubit_op)); EXPECT_EQ(CheckMPSSupported(program_with_3qubit_op), - Status(tensorflow::error::INVALID_ARGUMENT, + Status(static_cast( + absl::StatusCode::kInvalidArgument), "1D operations only support 1 and 2 qubit gates. " "Found: 3 qubit gate.")); } @@ -598,7 +609,8 @@ TEST(ProgramResolutionTest, CheckQubitsIn1DFailedByNot1DTopology) { ASSERT_TRUE(google::protobuf::TextFormat::ParseFromString( resolved_qubit_program_not_1d, &program_not_1d)); EXPECT_EQ(CheckMPSSupported(program_not_1d), - Status(tensorflow::error::INVALID_ARGUMENT, + Status(static_cast( + absl::StatusCode::kInvalidArgument), "A program is not in 1D topology. It contains an" " operation with qubits not neighbors each other.")); } diff --git a/tensorflow_quantum/core/src/util_qsim.h b/tensorflow_quantum/core/src/util_qsim.h index 94531a884..f08715343 100644 --- a/tensorflow_quantum/core/src/util_qsim.h +++ b/tensorflow_quantum/core/src/util_qsim.h @@ -148,7 +148,7 @@ tensorflow::Status ComputeExpectationQsim(const tfq::proto::PauliSum& p_sum, bool fuse_paulis = true) { // apply the gates of the pauliterms to a copy of the state vector // and add up expectation value term by term. - tensorflow::Status status = tensorflow::Status::OK(); + tensorflow::Status status = ::tensorflow::Status(); for (const tfq::proto::PauliTerm& term : p_sum.terms()) { // catch identity terms if (term.paulis_size() == 0) { @@ -204,11 +204,11 @@ tensorflow::Status ComputeSampledExpectationQsim( std::uniform_int_distribution<> distrib(1, 1 << 30); if (num_samples == 0) { - return tensorflow::Status::OK(); + return ::tensorflow::Status(); } // apply the gates of the pauliterms to a copy of the state vector // and add up expectation value term by term. - tensorflow::Status status = tensorflow::Status::OK(); + tensorflow::Status status = ::tensorflow::Status(); for (const tfq::proto::PauliTerm& term : p_sum.terms()) { // catch identity terms if (term.paulis_size() == 0) { @@ -288,11 +288,11 @@ tensorflow::Status ComputeMPSSampledExpectationQsim( std::uniform_int_distribution<> distrib(1, 1 << 30); if (num_samples == 0) { - return tensorflow::Status::OK(); + return ::tensorflow::Status(); } // apply the gates of the pauliterms to a copy of the state vector // and add up expectation value term by term. - tensorflow::Status status = tensorflow::Status::OK(); + tensorflow::Status status = ::tensorflow::Status(); for (const tfq::proto::PauliTerm& term : p_sum.terms()) { // catch identity terms if (term.paulis_size() == 0) { @@ -367,7 +367,7 @@ tensorflow::Status AccumulateOperators( // apply the gates of the pauliterms to a copy of the state vector // accumulating results as we go. Effectively doing O|psi> for an arbitrary // O. Result is stored on scratch. - tensorflow::Status status = tensorflow::Status::OK(); + tensorflow::Status status = ::tensorflow::Status(); ss.Copy(source, scratch); ss.SetAllZeros(dest); @@ -424,7 +424,7 @@ tensorflow::Status AccumulateFusedCircuits( const std::vector& coefficients, const std::vector& fused_circuits, const SimT& sim, const StateSpaceT& ss, StateT& scratch, StateT& dest) { - tensorflow::Status status = tensorflow::Status::OK(); + tensorflow::Status status = ::tensorflow::Status(); ss.SetAllZeros(dest); for (std::vector>::size_type i = 0; diff --git a/tensorflow_quantum/datasets/spin_system.py b/tensorflow_quantum/datasets/spin_system.py index a9f3170d1..4a180a68f 100644 --- a/tensorflow_quantum/datasets/spin_system.py +++ b/tensorflow_quantum/datasets/spin_system.py @@ -280,7 +280,7 @@ def tfi_chain(qubits, boundary_condition="closed", data_dir=None): / np.pi # Parameters are stored as np.float32, but cirq expects np.float64 # See https://github.com/quantumlib/Cirq/issues/3359 - params = params.astype(np.float) + params = params.astype(float) additional_info.append( SpinSystemInfo(g=g, gs=np.load( @@ -517,7 +517,7 @@ def xxz_chain(qubits, boundary_condition="closed", data_dir=None): / np.pi # Parameters are stored as np.float32, but cirq expects np.float64 # See https://github.com/quantumlib/Cirq/issues/3359 - params = params.astype(np.float) + params = params.astype(float) additional_info.append( SpinSystemInfo(g=g, gs=np.load( diff --git a/tensorflow_quantum/datasets/spin_system_test.py b/tensorflow_quantum/datasets/spin_system_test.py index dcd35d5c7..3dac53a80 100644 --- a/tensorflow_quantum/datasets/spin_system_test.py +++ b/tensorflow_quantum/datasets/spin_system_test.py @@ -224,7 +224,8 @@ def test_param_resolver(self): rtol=1e-3) -class TFIRectangularTest(tf.test.TestCase): +# TODO(#748): Inherit this class from tf.test.TestCase after fixing the issue. +class TFIRectangularTest: """Testing tfi_rectangular.""" # pylint: disable=C0103 diff --git a/tensorflow_quantum/python/layers/circuit_executors/sampled_expectation_test.py b/tensorflow_quantum/python/layers/circuit_executors/sampled_expectation_test.py index 2d165b13c..4e96a5c49 100644 --- a/tensorflow_quantum/python/layers/circuit_executors/sampled_expectation_test.py +++ b/tensorflow_quantum/python/layers/circuit_executors/sampled_expectation_test.py @@ -389,7 +389,7 @@ def test_simple_op_input(self, backend): outputs=[circuit_output]) model.compile( - optimizer=tf.keras.optimizers.Adam(learning_rate=0.05), + optimizer=tf.keras.optimizers.Adam(learning_rate=0.2), loss=tf.keras.losses.mean_squared_error, ) history = model.fit(x=[circuit, ops, n], diff --git a/tensorflow_quantum/python/optimizers/rotosolve_minimizer.py b/tensorflow_quantum/python/optimizers/rotosolve_minimizer.py index 65998d929..5bf23f6a0 100755 --- a/tensorflow_quantum/python/optimizers/rotosolve_minimizer.py +++ b/tensorflow_quantum/python/optimizers/rotosolve_minimizer.py @@ -1,4 +1,3 @@ -<<<<<<< HEAD # Copyright 2020 The TensorFlow Quantum Authors. All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -13,8 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. # ============================================================================== -"""The rotosolve minimization algorithm""" -import collections +"""The rotosolve minimization algorithm.""" import numpy as np import tensorflow as tf @@ -46,39 +44,51 @@ def prefer_static_value(x): return x -RotosolveOptimizerResults = collections.namedtuple( - 'RotosolveOptimizerResults', - [ - 'converged', - # Scalar boolean tensor indicating whether the minimum - # was found within tolerance. - 'num_iterations', - # The number of iterations of the rotosolve update. - 'num_objective_evaluations', - # The total number of objective - # evaluations performed. - 'position', - # A tensor containing the last argument value found - # during the search. If the search converged, then - # this value is the argmin of the objective function. - # A tensor containing the value of the objective from - # previous iteration - 'objective_value_previous_iteration', - # Save the evaluated value of the objective function - # from the previous iteration - 'objective_value', - # A tensor containing the value of the objective - # function at the `position`. If the search - # converged, then this is the (local) minimum of - # the objective function. - 'tolerance', - # Define the stop criteria. Iteration will stop when the - # objective value difference between two iterations is - # smaller than tolerance - 'solve_param_i', - # The parameter index where rotosolve is currently - # modifying. Reserved for internal use. - ]) +class RotosolveOptimizerResults(tf.experimental.ExtensionType): + """ExtentionType of Rotosolve Optimizer tf.while_loop() inner state.""" + converged: tf.Tensor + # Scalar boolean tensor indicating whether the minimum + # was found within tolerance. + num_iterations: tf.Tensor + # The number of iterations of the rotosolve update. + num_objective_evaluations: tf.Tensor + # The total number of objective + # evaluations performed. + position: tf.Tensor + # A tensor containing the last argument value found + # during the search. If the search converged, then + # this value is the argmin of the objective function. + # A tensor containing the value of the objective from + # previous iteration + objective_value_prev: tf.Tensor + # Save the evaluated value of the objective function + # from the previous iteration + objective_value: tf.Tensor + # A tensor containing the value of the objective + # function at the `position`. If the search + # converged, then this is the (local) minimum of + # the objective function. + tolerance: tf.Tensor + # Define the stop criteria. Iteration will stop when the + # objective value difference between two iterations is + # smaller than tolerance + solve_param_i: tf.Tensor + + # The parameter index where rotosolve is currently + # modifying. Reserved for internal use. + + def to_dict(self): + """Transforms immutable data to mutable dictionary.""" + return { + "converged": self.converged, + "num_iterations": self.num_iterations, + "num_objective_evaluations": self.num_objective_evaluations, + "position": self.position, + "objective_value": self.objective_value, + "objective_value_prev": self.objective_value_prev, + "tolerance": self.tolerance, + "solve_param_i": self.solve_param_i, + } def _get_initial_state(initial_position, tolerance, expectation_value_function): @@ -88,10 +98,10 @@ def _get_initial_state(initial_position, tolerance, expectation_value_function): "num_iterations": tf.Variable(0), "num_objective_evaluations": tf.Variable(0), "position": tf.Variable(initial_position), - "objective_value": tf.Variable(0.), - "objective_value_previous_iteration": tf.Variable(0.), + "objective_value": expectation_value_function(initial_position), + "objective_value_prev": tf.Variable(0.), "tolerance": tolerance, - "solve_param_i": tf.Variable(0) + "solve_param_i": tf.Variable(0), } return RotosolveOptimizerResults(**init_args) @@ -191,17 +201,16 @@ def _rotosolve_one_parameter_once(state): [[state.solve_param_i]], [delta_update], prefer_static_shape(state.position)) - state.solve_param_i.assign_add(1) - state.position.assign( - tf.math.floormod(state.position + delta_update_tensor, - np.pi * 2)) - - state.objective_value_previous_iteration.assign( - state.objective_value) - state.objective_value.assign( - expectation_value_function(state.position)) - - return [state] + new_position = (tf.math.floormod( + state.position + delta_update_tensor, np.pi * 2)) + next_state_params = state.to_dict() + next_state_params.update({ + "solve_param_i": state.solve_param_i + 1, + "position": new_position, + "objective_value_prev": state.objective_value, + "objective_value": (expectation_value_function(new_position)), + }) + return [RotosolveOptimizerResults(**next_state_params)] def _rotosolve_all_parameters_once(state): """Iterate over all parameters and rotosolve each single @@ -220,12 +229,16 @@ def _cond_internal(state_cond): return state_cond.solve_param_i < \ prefer_static_shape(state_cond.position)[0] - state.num_objective_evaluations.assign_add(1) + next_state_params = state.to_dict() + next_state_params.update({ + "num_objective_evaluations": + state.num_objective_evaluations + 1, + }) return tf.while_loop( cond=_cond_internal, body=_rotosolve_one_parameter_once, - loop_vars=[state], + loop_vars=[RotosolveOptimizerResults(**next_state_params)], parallel_iterations=1, ) @@ -239,25 +252,22 @@ def _cond(state): def _body(state): """Main optimization loop.""" - - state.solve_param_i.assign(0) - - _rotosolve_all_parameters_once(state) - - state.num_iterations.assign_add(1) - state.converged.assign( - tf.abs(state.objective_value - - state.objective_value_previous_iteration) < - state.tolerance) - - return [state] + pre_state_params = state.to_dict() + pre_state_params.update({"solve_param_i": 0}) + pre_state = RotosolveOptimizerResults(**pre_state_params) + post_state = _rotosolve_all_parameters_once(pre_state)[0] + next_state_params = post_state.to_dict() + next_state_params.update({ + "converged": (tf.abs(post_state.objective_value - + post_state.objective_value_prev) < + post_state.tolerance), + "num_iterations": post_state.num_iterations + 1, + }) + return [RotosolveOptimizerResults(**next_state_params)] initial_state = _get_initial_state(initial_position, tolerance, expectation_value_function) - initial_state.objective_value.assign( - expectation_value_function(initial_state.position)) - return tf.while_loop(cond=_cond, body=_body, loop_vars=[initial_state], diff --git a/tensorflow_quantum/python/optimizers/spsa_minimizer.py b/tensorflow_quantum/python/optimizers/spsa_minimizer.py index 31e753aac..471b46d9e 100644 --- a/tensorflow_quantum/python/optimizers/spsa_minimizer.py +++ b/tensorflow_quantum/python/optimizers/spsa_minimizer.py @@ -12,8 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. # ============================================================================== -"""The SPSA minimization algorithm""" -import collections +"""The SPSA minimization algorithm.""" import tensorflow as tf import numpy as np @@ -45,53 +44,8 @@ def prefer_static_value(x): return x -<<<<<<< HEAD -SPSAOptimizerResults = collections.namedtuple( - 'SPSAOptimizerResults', - [ - 'converged', - # Scalar boolean tensor indicating whether the minimum - # was found within tolerance. - 'num_iterations', - # The number of iterations of the SPSA update. - 'num_objective_evaluations', - # The total number of objective - # evaluations performed. - 'position', - # A tensor containing the last argument value found - # during the search. If the search converged, then - # this value is the argmin of the objective function. - # A tensor containing the value of the objective from - # previous iteration - 'objective_value_previous_iteration', - # Save the evaluated value of the objective function - # from the previous iteration - 'objective_value', - # A tensor containing the value of the objective - # function at the `position`. If the search - # converged, then this is the (local) minimum of - # the objective function. - 'tolerance', - # Define the stop criteria. Iteration will stop when the - # objective value difference between two iterations is - # smaller than tolerance - 'lr', - # Specifies the learning rate - 'alpha', - # Specifies scaling of the learning rate - 'perturb', - # Specifies the size of the perturbations - 'gamma', - # Specifies scaling of the size of the perturbations - 'blocking', - # If true, then the optimizer will only accept updates that improve - # the objective function. - 'allowed_increase' - # Specifies maximum allowable increase in objective function - # (only applies if blocking is true). - ]) -======= class SPSAOptimizerResults(tf.experimental.ExtensionType): + """ExtentionType of SPSA Optimizer tf.while_loop() inner state.""" converged: tf.Tensor # Scalar boolean tensor indicating whether the minimum # was found within tolerance. @@ -106,7 +60,7 @@ class SPSAOptimizerResults(tf.experimental.ExtensionType): # this value is the argmin of the objective function. # A tensor containing the value of the objective from # previous iteration - objective_value_previous_iteration: tf.Tensor + objective_value_prev: tf.Tensor # Save the evaluated value of the objective function # from the previous iteration objective_value: tf.Tensor @@ -118,7 +72,7 @@ class SPSAOptimizerResults(tf.experimental.ExtensionType): # Define the stop criteria. Iteration will stop when the # objective value difference between two iterations is # smaller than tolerance - lr: tf.Tensor + learning_rate: tf.Tensor # Specifies the learning rate alpha: tf.Tensor # Specifies scaling of the learning rate @@ -135,59 +89,43 @@ class SPSAOptimizerResults(tf.experimental.ExtensionType): # (only applies if blocking is true). def to_dict(self): + """Transforms immutable data to mutable dictionary.""" return { - "converged": - self.converged, - "num_iterations": - self.num_iterations, - "num_objective_evaluations": - self.num_objective_evaluations, - "position": - self.position, - "objective_value": - self.objective_value, - "objective_value_previous_iteration": - self.objective_value_previous_iteration, - "tolerance": - self.tolerance, - "lr": - self.lr, - "alpha": - self.alpha, - "perturb": - self.perturb, - "gamma": - self.gamma, - "blocking": - self.blocking, - "allowed_increase": - self.allowed_increase, + "converged": self.converged, + "num_iterations": self.num_iterations, + "num_objective_evaluations": self.num_objective_evaluations, + "position": self.position, + "objective_value": self.objective_value, + "objective_value_prev": self.objective_value_prev, + "tolerance": self.tolerance, + "learning_rate": self.learning_rate, + "alpha": self.alpha, + "perturb": self.perturb, + "gamma": self.gamma, + "blocking": self.blocking, + "allowed_increase": self.allowed_increase, } ->>>>>>> parent of 39a811d (Format optimizers) def _get_initial_state(initial_position, tolerance, expectation_value_function, - lr, alpha, perturb, gamma, blocking, allowed_increase): + learning_rate, alpha, perturb, gamma, blocking, + allowed_increase): """Create SPSAOptimizerResults with initial state of search.""" init_args = { "converged": tf.Variable(False), "num_iterations": tf.Variable(0), "num_objective_evaluations": tf.Variable(0), "position": tf.Variable(initial_position), -<<<<<<< HEAD - "objective_value": tf.Variable(0.), -======= "objective_value": (tf.cast(expectation_value_function(initial_position), tf.float32)), ->>>>>>> parent of 39a811d (Format optimizers) - "objective_value_previous_iteration": tf.Variable(np.inf), + "objective_value_prev": tf.Variable(np.inf), "tolerance": tolerance, - "lr": tf.Variable(lr), + "learning_rate": tf.Variable(learning_rate), "alpha": tf.Variable(alpha), "perturb": tf.Variable(perturb), "gamma": tf.Variable(gamma), "blocking": tf.Variable(blocking), - "allowed_increase": tf.Variable(allowed_increase) + "allowed_increase": tf.Variable(allowed_increase), } return SPSAOptimizerResults(**init_args) @@ -197,7 +135,7 @@ def minimize(expectation_value_function, tolerance=1e-5, max_iterations=200, alpha=0.602, - lr=1.0, + learning_rate=1.0, perturb=1.0, gamma=0.101, blocking=False, @@ -239,7 +177,8 @@ def minimize(expectation_value_function, tolerance: Scalar `tf.Tensor` of real dtype. Specifies the tolerance for the procedure. If the supremum norm between two iteration vector is below this number, the algorithm is stopped. - lr: Scalar `tf.Tensor` of real dtype. Specifies the learning rate + learning_rate: Scalar `tf.Tensor` of real dtype. + Specifies the learning rate. alpha: Scalar `tf.Tensor` of real dtype. Specifies scaling of the learning rate. perturb: Scalar `tf.Tensor` of real dtype. Specifies the size of the @@ -278,7 +217,9 @@ def minimize(expectation_value_function, max_iterations = tf.convert_to_tensor(max_iterations, name='max_iterations') - lr_init = tf.convert_to_tensor(lr, name='initial_a', dtype='float32') + learning_rate_init = tf.convert_to_tensor(learning_rate, + name='initial_a', + dtype='float32') perturb_init = tf.convert_to_tensor(perturb, name='initial_c', dtype='float32') @@ -304,19 +245,23 @@ def _spsa_once(state): state.perturb * delta_shift) gradient_estimate = (v_p - v_m) / (2 * state.perturb) * delta_shift - update = state.lr * gradient_estimate - - state.num_objective_evaluations.assign_add(2) + update = state.learning_rate * gradient_estimate + next_state_params = state.to_dict() + next_state_params.update({ + "num_objective_evaluations": + state.num_objective_evaluations + 2, + }) - current_obj = expectation_value_function(state.position - update) - if state.objective_value_previous_iteration + \ + current_obj = tf.cast(expectation_value_function(state.position - + update), + dtype=tf.float32) + if state.objective_value_prev + \ state.allowed_increase >= current_obj or not state.blocking: - state.position.assign(state.position - update) - state.objective_value_previous_iteration.assign( - state.objective_value) - state.objective_value.assign(current_obj) - - return [SPSAOptimizerResults(**next_state_params)] + next_state_params.update({ + "position": state.position - update, + "objective_value_prev": state.objective_value, + "objective_value": current_obj + }) return [SPSAOptimizerResults(**next_state_params)] @@ -330,55 +275,33 @@ def _cond(state): def _body(state): """Main optimization loop.""" - new_lr = lr_init / ( + new_learning_rate = learning_rate_init / ( (tf.cast(state.num_iterations + 1, tf.float32) + 0.01 * tf.cast(max_iterations, tf.float32))**state.alpha) new_perturb = perturb_init / (tf.cast(state.num_iterations + 1, tf.float32)**state.gamma) -<<<<<<< HEAD - state.lr.assign(new_lr) - state.perturb.assign(new_perturb) - - _spsa_once(state) - state.num_iterations.assign_add(1) - state.converged.assign( - tf.abs(state.objective_value - - state.objective_value_previous_iteration) < - state.tolerance) - return [state] -======= pre_state_params = state.to_dict() pre_state_params.update({ - "lr": new_lr, + "learning_rate": new_learning_rate, "perturb": new_perturb, }) post_state = _spsa_once(SPSAOptimizerResults(**pre_state_params))[0] post_state_params = post_state.to_dict() - tf.print("asdf", state.objective_value.dtype, - state.objective_value_previous_iteration.dtype) post_state_params.update({ "num_iterations": post_state.num_iterations + 1, - "converged": (tf.abs(state.objective_value - - state.objective_value_previous_iteration) < - state.tolerance), + "converged": + (tf.abs(state.objective_value - state.objective_value_prev) + < state.tolerance), }) return [SPSAOptimizerResults(**post_state_params)] ->>>>>>> parent of 39a811d (Format optimizers) initial_state = _get_initial_state(initial_position, tolerance, - expectation_value_function, lr, - alpha, perturb, gamma, blocking, - allowed_increase) -<<<<<<< HEAD - - initial_state.objective_value.assign( - tf.cast(expectation_value_function(initial_state.position), - tf.float32)) -======= ->>>>>>> parent of 39a811d (Format optimizers) + expectation_value_function, + learning_rate, alpha, perturb, gamma, + blocking, allowed_increase) return tf.while_loop(cond=_cond, body=_body, From e76bf5d75b42c7bf260e2317b732c1f4c12eb89c Mon Sep 17 00:00:00 2001 From: "Jae H. Yoo" <40815393+jaeyoo@users.noreply.github.com> Date: Tue, 28 Mar 2023 15:22:24 -0700 Subject: [PATCH 42/50] Upgrade bazel version 5.3.0 and fix some typo in tf version (#755) --- .bazelversion | 2 +- configure.sh | 14 +++++++------- docs/install.md | 12 ++++++------ scripts/ci_install.sh | 4 ++-- 4 files changed, 16 insertions(+), 16 deletions(-) diff --git a/.bazelversion b/.bazelversion index 831446cbd..03f488b07 100644 --- a/.bazelversion +++ b/.bazelversion @@ -1 +1 @@ -5.1.0 +5.3.0 diff --git a/configure.sh b/configure.sh index 5efd4212a..ff42047fe 100755 --- a/configure.sh +++ b/configure.sh @@ -64,9 +64,9 @@ done while [[ "$TF_CUDA_VERSION" == "" ]]; do read -p "Are you building against TensorFlow 2.1(including RCs) or newer?[Y/n] " INPUT case $INPUT in - [Yy]* ) echo "Build against TensorFlow 2.1 or newer."; TF_CUDA_VERSION=10.1;; + [Yy]* ) echo "Build against TensorFlow 2.1 or newer."; TF_CUDA_VERSION=11;; [Nn]* ) echo "Build against TensorFlow <2.1."; TF_CUDA_VERSION=10.0;; - "" ) echo "Build against TensorFlow 2.1 or newer."; TF_CUDA_VERSION=10.1;; + "" ) echo "Build against TensorFlow 2.1 or newer."; TF_CUDA_VERSION=11;; * ) echo "Invalid selection: " $INPUT;; esac done @@ -94,10 +94,6 @@ fi TF_CFLAGS=( $(python -c 'import tensorflow as tf; print(" ".join(tf.sysconfig.get_compile_flags()))') ) TF_LFLAGS="$(python -c 'import tensorflow as tf; print(" ".join(tf.sysconfig.get_link_flags()))')" -write_to_bazelrc "build:cuda --define=using_cuda=true --define=using_cuda_nvcc=true" -if [[ "$PIP_MANYLINUX2010" == "0" ]]; then - write_to_bazelrc "build:cuda --crosstool_top=@local_config_cuda//crosstool:toolchain" -fi write_to_bazelrc "build --experimental_repo_remote_exec" write_to_bazelrc "build --spawn_strategy=standalone" @@ -142,8 +138,12 @@ fi # TODO(yifeif): do not hardcode path if [[ "$TF_NEED_CUDA" == "1" ]]; then + write_to_bazelrc "build:cuda --define=using_cuda=true --define=using_cuda_nvcc=true" + write_to_bazelrc "build:cuda --@local_config_cuda//:enable_cuda" + write_to_bazelrc "build:cuda --crosstool_top=@local_config_cuda//crosstool:toolchain" + write_action_env_to_bazelrc "TF_CUDA_VERSION" ${TF_CUDA_VERSION} - write_action_env_to_bazelrc "TF_CUDNN_VERSION" "7" + write_action_env_to_bazelrc "TF_CUDNN_VERSION" "8" if is_windows; then write_action_env_to_bazelrc "CUDNN_INSTALL_PATH" "C:/Program Files/NVIDIA GPU Computing Toolkit/CUDA/v${TF_CUDA_VERSION}" write_action_env_to_bazelrc "CUDA_TOOLKIT_PATH" "C:/Program Files/NVIDIA GPU Computing Toolkit/CUDA/v${TF_CUDA_VERSION}" diff --git a/docs/install.md b/docs/install.md index 5e64d0616..3de77ecf9 100644 --- a/docs/install.md +++ b/docs/install.md @@ -17,7 +17,7 @@ TensorFlow Quantum is supported on Python 3.7, 3.8, and 3.9 and depends directly ### Requirements * pip 19.0 or later (requires `manylinux2010` support) -* [TensorFlow == 2.7.0](https://www.tensorflow.org/install/pip) +* [TensorFlow == 2.11.0](https://www.tensorflow.org/install/pip) See the [TensorFlow install guide](https://www.tensorflow.org/install/pip) to set up your Python development environment and an (optional) virtual environment. @@ -27,7 +27,7 @@ Upgrade `pip` and install TensorFlow
   pip3 install --upgrade pip
-  pip3 install tensorflow==2.7.0
+  pip3 install tensorflow==2.11.0
 
@@ -84,7 +84,7 @@ As noted in the TensorFlow guide, the Bazel build system will be required. -Our latest source builds use TensorFlow 2.11.0. To ensure compatibility we use `bazel` version 5.1.0. To remove any existing version of Bazel: +Our latest source builds use TensorFlow 2.11.0. To ensure compatibility we use `bazel` version 5.3.0. To remove any existing version of Bazel:
@@ -92,13 +92,13 @@ Our latest source builds use TensorFlow 2.11.0. To ensure compatibility we use `
 
-Download and install `bazel` version 5.1.0: +Download and install `bazel` version 5.3.0:
-  wget https://github.com/bazelbuild/bazel/releases/download/5.1.0/bazel_5.1.0-linux-x86_64.deb
+  wget https://github.com/bazelbuild/bazel/releases/download/5.3.0/bazel_5.3.0-linux-x86_64.deb
 
-  sudo dpkg -i bazel_5.1.0-linux-x86_64.deb
+  sudo dpkg -i bazel_5.3.0-linux-x86_64.deb
 
diff --git a/scripts/ci_install.sh b/scripts/ci_install.sh index a0ed81c8c..04e6b3159 100755 --- a/scripts/ci_install.sh +++ b/scripts/ci_install.sh @@ -13,7 +13,7 @@ # See the License for the specific language governing permissions and # limitations under the License. # ============================================================================== -wget https://github.com/bazelbuild/bazel/releases/download/5.1.0/bazel_5.1.0-linux-x86_64.deb -sudo dpkg -i bazel_5.1.0-linux-x86_64.deb +wget https://github.com/bazelbuild/bazel/releases/download/5.3.0/bazel_5.3.0-linux-x86_64.deb +sudo dpkg -i bazel_5.3.0-linux-x86_64.deb pip install --upgrade pip setuptools wheel pip install -r requirements.txt \ No newline at end of file From 1e092a7aee243d9cc114c6893b20bd4f8363435f Mon Sep 17 00:00:00 2001 From: Michael Broughton Date: Tue, 13 Jun 2023 13:48:44 -0700 Subject: [PATCH 43/50] fix compatability issues. --- .github/workflows/ci.yaml | 12 +- ...fq_simulate_expectation_op_cuquantum.cu.cc | 323 ------------------ .../differentiators/linear_combination.py | 3 +- 3 files changed, 8 insertions(+), 330 deletions(-) delete mode 100644 tensorflow_quantum/core/ops/tfq_simulate_expectation_op_cuquantum.cu.cc diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 7e6f1a21a..387b7d6a4 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -5,7 +5,7 @@ on: [pull_request] jobs: lint: name: Lint check - runs-on: ubuntu-18.04 + runs-on: ubuntu-20.04 steps: - uses: actions/checkout@v1 - uses: actions/setup-python@v1 @@ -19,7 +19,7 @@ jobs: format: name: Formatting check - runs-on: ubuntu-18.04 + runs-on: ubuntu-20.04 steps: - uses: actions/checkout@v1 @@ -34,7 +34,7 @@ jobs: wheel-build: name: Wheel test - runs-on: ubuntu-18.04 + runs-on: ubuntu-20.04 steps: - uses: actions/checkout@v1 @@ -53,7 +53,7 @@ jobs: bazel-tests: name: Library tests - runs-on: ubuntu-18.04 + runs-on: ubuntu-20.04 needs: [lint, format] steps: @@ -71,7 +71,7 @@ jobs: leak-tests: name: Memory Leak tests - runs-on: ubuntu-18.04 + runs-on: ubuntu-20.04 needs: [lint, format] steps: @@ -89,7 +89,7 @@ jobs: tutorials-test: name: Tutorial tests - runs-on: ubuntu-18.04 + runs-on: ubuntu-20.04 needs: [lint, format, wheel-build] steps: diff --git a/tensorflow_quantum/core/ops/tfq_simulate_expectation_op_cuquantum.cu.cc b/tensorflow_quantum/core/ops/tfq_simulate_expectation_op_cuquantum.cu.cc deleted file mode 100644 index 1f9e9e168..000000000 --- a/tensorflow_quantum/core/ops/tfq_simulate_expectation_op_cuquantum.cu.cc +++ /dev/null @@ -1,323 +0,0 @@ -/* 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. -See the License for the specific language governing permissions and -limitations under the License. -==============================================================================*/ - -#include -#include - -#include -#include - -#include "../qsim/lib/circuit.h" -#include "../qsim/lib/gate_appl.h" -#include "../qsim/lib/gates_cirq.h" -#include "../qsim/lib/gates_qsim.h" -#include "../qsim/lib/seqfor.h" -#include "../qsim/lib/simulator_custatevec.h" -#include "../qsim/lib/statespace_custatevec.h" -#include "tensorflow/core/framework/op_kernel.h" -#include "tensorflow/core/framework/shape_inference.h" -#include "tensorflow/core/framework/tensor_shape.h" -#include "tensorflow/core/lib/core/error_codes.pb.h" -#include "tensorflow/core/lib/core/status.h" -#include "tensorflow/core/lib/core/threadpool.h" -#include "tensorflow/core/platform/mutex.h" -#include "tensorflow_quantum/core/ops/parse_context.h" -#include "tensorflow_quantum/core/proto/pauli_sum.pb.h" -#include "tensorflow_quantum/core/proto/program.pb.h" -#include "tensorflow_quantum/core/src/util_qsim.h" - -namespace tfq { - -using ::tensorflow::Status; -using ::tfq::proto::PauliSum; -using ::tfq::proto::Program; - -typedef qsim::Cirq::GateCirq QsimGate; -typedef qsim::Circuit QsimCircuit; - - -class TfqSimulateExpectationOpCuQuantum : public tensorflow::OpKernel { - public: - explicit TfqSimulateExpectationOpCuQuantum(tensorflow::OpKernelConstruction* context) - : OpKernel(context) { } - - void Compute(tensorflow::OpKernelContext* context) override { - // TODO (mbbrough): add more dimension checks for other inputs here. - const int num_inputs = context->num_inputs(); - OP_REQUIRES(context, num_inputs == 4, - tensorflow::errors::InvalidArgument(absl::StrCat( - "Expected 4 inputs, got ", num_inputs, " inputs."))); - - // Create the output Tensor. - const int output_dim_batch_size = context->input(0).dim_size(0); - const int output_dim_op_size = context->input(3).dim_size(1); - tensorflow::TensorShape output_shape; - output_shape.AddDim(output_dim_batch_size); - output_shape.AddDim(output_dim_op_size); - - tensorflow::Tensor* output = nullptr; - tensorflow::AllocatorAttributes alloc_attr; - alloc_attr.set_on_host(true); // why?? - alloc_attr.set_gpu_compatible(true); - OP_REQUIRES_OK(context, context->allocate_output(0, output_shape, &output, - alloc_attr)); - auto output_tensor = output->matrix(); - // Parse program protos. - std::vector programs; - std::vector num_qubits; - std::vector> pauli_sums; // why is this a vector of vectors?? - OP_REQUIRES_OK(context, GetProgramsAndNumQubits(context, &programs, - &num_qubits, &pauli_sums)); - - std::vector maps; - OP_REQUIRES_OK(context, GetSymbolMaps(context, &maps)); - - OP_REQUIRES(context, programs.size() == maps.size(), - tensorflow::errors::InvalidArgument(absl::StrCat( - "Number of circuits and symbol_values do not match. Got ", - programs.size(), " circuits and ", maps.size(), - " symbol values."))); - - // Construct qsim circuits. - std::vector qsim_circuits(programs.size(), QsimCircuit()); - std::vector>> fused_circuits( - programs.size(), std::vector>({})); - - Status parse_status = Status::OK(); - auto p_lock = tensorflow::mutex(); - auto construct_f = [&](int start, int end) { - for (int i = start; i < end; i++) { - Status local = - QsimCircuitFromProgram(programs[i], maps[i], num_qubits[i], - &qsim_circuits[i], &fused_circuits[i]); - NESTED_FN_STATUS_SYNC(parse_status, local, p_lock); - } - }; - - const int num_cycles = 1000; - context->device()->tensorflow_cpu_worker_threads()->workers->ParallelFor( - programs.size(), num_cycles, construct_f); - OP_REQUIRES_OK(context, parse_status); - - int max_num_qubits = 0; - for (const int num : num_qubits) { - max_num_qubits = std::max(max_num_qubits, num); - } - - if (max_num_qubits >= 26 || programs.size() == 1 || true) { - ComputeLarge(num_qubits, fused_circuits, pauli_sums, context, - &output_tensor); - } else { - ComputeSmall(num_qubits, max_num_qubits, fused_circuits, pauli_sums, - context, &output_tensor); - } - } - - private: - int num_threads_in_sim_; - int thread_per_block_; - int block_count_; ->>>>>>> parent of 4f6290a (Fix ComputeSmall and enable it.):tensorflow_quantum/core/ops/tfq_simulate_expectation_op_cuda.cu.cc - - // Define the GPU implementation that launches the CUDA kernel. - void ComputeLarge( - const std::vector& num_qubits, - const std::vector>>& fused_circuits, - const std::vector>& pauli_sums, - tensorflow::OpKernelContext* context, - tensorflow::TTypes::Matrix* output_tensor) { - // Instantiate qsim objects. - using Simulator = qsim::SimulatorCuStateVec; - using StateSpace = Simulator::StateSpace; -<<<<<<< HEAD:tensorflow_quantum/core/ops/tfq_simulate_expectation_op_cuquantum.cu.cc - - - // Launch the cuda kernel. - // Begin simulation. - int largest_nq = 1; - Simulator sim = Simulator(custatevec_handle_); - StateSpace ss = StateSpace(cublas_handle_, custatevec_handle_); -======= - // Launch the cuda kernel. These parameters came from: - // 1. min/max num_threads in //third_party/qsim/tests/simulator_cuda_test.cu - // 2. min/max num_threads & dblocks in - // //third_party/qsim/tests/statespace_cuda_test.cu - // //third_party/qsim/lib/statespace_cuda.h:55-64 - // num_dblocks has no explanation. just follow test code 2 or 16. - int block_count = 2; // 2 or 16; - // num_threads = 2**q where q in [5..10] - int thread_per_block = 128; // 32, 64, 128, 256, 512, 1024; - // TFQ GPU - StateSpace::Parameter param_ss; - param_ss.num_threads = thread_per_block; - param_ss.num_dblocks = block_count; - - // Begin simulation. - int largest_nq = 1; - Simulator sim = Simulator(); - StateSpace ss = StateSpace(param_ss); ->>>>>>> parent of 4f6290a (Fix ComputeSmall and enable it.):tensorflow_quantum/core/ops/tfq_simulate_expectation_op_cuda.cu.cc - auto sv = ss.Create(largest_nq); - ss.SetStateZero(sv); - auto scratch = ss.Create(largest_nq); - - // Simulate programs one by one. Parallelizing over state vectors - // we no longer parallelize over circuits. Each time we encounter a - // a larger circuit we will grow the Statevector as necessary. - for (int i = 0; i < fused_circuits.size(); i++) { - int nq = num_qubits[i]; - - if (nq > largest_nq) { - // need to switch to larger statespace. - largest_nq = nq; - sv = ss.Create(largest_nq); - scratch = ss.Create(largest_nq); - } - // TODO: add heuristic here so that we do not always recompute - // the state if there is a possibility that circuit[i] and - // circuit[i + 1] produce the same state. - ss.SetStateZero(sv); - for (int j = 0; j < fused_circuits[i].size(); j++) { - qsim::ApplyFusedGate(sim, fused_circuits[i][j], sv); - } - for (int j = 0; j < pauli_sums[i].size(); j++) { - // (#679) Just ignore empty program - if (fused_circuits[i].size() == 0) { - (*output_tensor)(i, j) = -2.0; - continue; - } - float exp_v = 0.0; - OP_REQUIRES_OK(context, - ComputeExpectationQsim(pauli_sums[i][j], sim, ss, sv, - scratch, &exp_v)); - (*output_tensor)(i, j) = exp_v; - } - } - } - - void ComputeSmall( - const std::vector& num_qubits, const int max_num_qubits, - const std::vector>>& fused_circuits, - const std::vector>& pauli_sums, - tensorflow::OpKernelContext* context, - tensorflow::TTypes::Matrix* output_tensor) { - using Simulator = qsim::SimulatorCuStateVec; - using StateSpace = Simulator::StateSpace; - -<<<<<<< HEAD:tensorflow_quantum/core/ops/tfq_simulate_expectation_op_cuquantum.cu.cc -======= - StateSpace::Parameter param_ss; - param_ss.num_threads = thread_per_block_; - param_ss.num_dblocks = block_count_; - ->>>>>>> parent of 4f6290a (Fix ComputeSmall and enable it.):tensorflow_quantum/core/ops/tfq_simulate_expectation_op_cuda.cu.cc - const int output_dim_op_size = output_tensor->dimension(1); - - Status compute_status = Status::OK(); - auto c_lock = tensorflow::mutex(); - auto DoWork = [&](int start, int end) { - int old_batch_index = -2; - int cur_batch_index = -1; - int largest_nq = 1; - int cur_op_index; - -<<<<<<< HEAD:tensorflow_quantum/core/ops/tfq_simulate_expectation_op_cuquantum.cu.cc - // Launch custatevec, begin simulation. - auto sim = Simulator(custatevec_handle_); - auto ss = StateSpace(cublas_handle_, custatevec_handle_); -======= - // Begin simulation. - auto sim = Simulator(); - auto ss = StateSpace(param_ss); ->>>>>>> parent of 4f6290a (Fix ComputeSmall and enable it.):tensorflow_quantum/core/ops/tfq_simulate_expectation_op_cuda.cu.cc - auto sv = ss.Create(largest_nq); - auto scratch = ss.Create(largest_nq); - for (int i = start; i < end; i++) { - cur_batch_index = i / output_dim_op_size; - cur_op_index = i % output_dim_op_size; - - const int nq = num_qubits[cur_batch_index]; - - // (#679) Just ignore empty program - if (fused_circuits[cur_batch_index].size() == 0) { - (*output_tensor)(cur_batch_index, cur_op_index) = -2.0; - continue; - } - - if (cur_batch_index != old_batch_index) { - // We've run into a new state vector we must compute. - // Only compute a new state vector when we have to. - if (nq > largest_nq) { - largest_nq = nq; - sv = ss.Create(largest_nq); - scratch = ss.Create(largest_nq); - } - // no need to update scratch_state since ComputeExpectation - // will take care of things for us. - ss.SetStateZero(sv); - for (int j = 0; j < fused_circuits[cur_batch_index].size(); j++) { - qsim::ApplyFusedGate(sim, fused_circuits[cur_batch_index][j], sv); - } - } - - float exp_v = 0.0; - NESTED_FN_STATUS_SYNC( - compute_status, - ComputeExpectationQsim(pauli_sums[cur_batch_index][cur_op_index], - sim, ss, sv, scratch, &exp_v), - c_lock); - (*output_tensor)(cur_batch_index, cur_op_index) = exp_v; - old_batch_index = cur_batch_index; - } - }; - - const int64_t num_cycles = - 200 * (int64_t(1) << static_cast(max_num_qubits)); - context->device()->tensorflow_cpu_worker_threads()->workers->ParallelFor( - fused_circuits.size() * output_dim_op_size, num_cycles, DoWork); - OP_REQUIRES_OK(context, compute_status); - } -}; - -REGISTER_KERNEL_BUILDER( - Name("TfqSimulateExpectationOpCuQuantum").Device(tensorflow::DEVICE_CPU), - TfqSimulateExpectationOpCuQuantumOp); - -REGISTER_OP("TfqSimulateExpectationOpCuQuantum") - .Input("programs: string") - .Input("symbol_names: string") - .Input("symbol_values: float") - .Input("pauli_sums: string") - .Output("expectations: float") - .SetShapeFn([](tensorflow::shape_inference::InferenceContext* c) { - tensorflow::shape_inference::ShapeHandle programs_shape; - TF_RETURN_IF_ERROR(c->WithRank(c->input(0), 1, &programs_shape)); - - tensorflow::shape_inference::ShapeHandle symbol_names_shape; - TF_RETURN_IF_ERROR(c->WithRank(c->input(1), 1, &symbol_names_shape)); - - tensorflow::shape_inference::ShapeHandle symbol_values_shape; - TF_RETURN_IF_ERROR(c->WithRank(c->input(2), 2, &symbol_values_shape)); - - tensorflow::shape_inference::ShapeHandle pauli_sums_shape; - TF_RETURN_IF_ERROR(c->WithRank(c->input(3), 2, &pauli_sums_shape)); - - tensorflow::shape_inference::DimensionHandle output_rows = - c->Dim(programs_shape, 0); - tensorflow::shape_inference::DimensionHandle output_cols = - c->Dim(pauli_sums_shape, 1); - c->set_output(0, c->Matrix(output_rows, output_cols)); - - return tensorflow::Status::OK(); - }); - -} // namespace tfq diff --git a/tensorflow_quantum/python/differentiators/linear_combination.py b/tensorflow_quantum/python/differentiators/linear_combination.py index dabbd9e34..aae72d8ae 100644 --- a/tensorflow_quantum/python/differentiators/linear_combination.py +++ b/tensorflow_quantum/python/differentiators/linear_combination.py @@ -305,8 +305,9 @@ def __init__(self, error_order=2, grid_spacing=0.001): np.arange(1, error_order / 2 + 1) ]) weights = [] - n = error_order / 2 + n = int(error_order / 2) for k in grid_points_to_eval: + k = int(k) numerator = (-1)**(k + 1) * np.math.factorial(n)**2 denom = k * np.math.factorial(n - k) * np.math.factorial(n + k) weights.append(numerator / (denom * grid_spacing)) From 08ea1080d77d0b1eb8a3207bc3e849bbaff3cb25 Mon Sep 17 00:00:00 2001 From: Michael Broughton Date: Tue, 13 Jun 2023 14:28:29 -0700 Subject: [PATCH 44/50] re-trigger kokoro --- .github/workflows/ci.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 387b7d6a4..72d8c04c7 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -2,6 +2,7 @@ name: Continuous Integration on: [pull_request] + jobs: lint: name: Lint check From 03fb5a608d45371241aaf8f91324e4f326e6572d Mon Sep 17 00:00:00 2001 From: Michael Broughton Date: Tue, 13 Jun 2023 14:47:33 -0700 Subject: [PATCH 45/50] re-trigger kokoro --- .github/workflows/ci.yaml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 72d8c04c7..387b7d6a4 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -2,7 +2,6 @@ name: Continuous Integration on: [pull_request] - jobs: lint: name: Lint check From 96c601099a516941200d9b9477cc3522fe42abb5 Mon Sep 17 00:00:00 2001 From: Michael Broughton Date: Tue, 13 Jun 2023 15:07:44 -0700 Subject: [PATCH 46/50] re-trigger kokoro --- .github/workflows/ci.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 387b7d6a4..72d8c04c7 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -2,6 +2,7 @@ name: Continuous Integration on: [pull_request] + jobs: lint: name: Lint check From 218bc6a9ce9ae4762b32645ed6330bfa34fff23d Mon Sep 17 00:00:00 2001 From: Michael Broughton Date: Tue, 13 Jun 2023 15:37:31 -0700 Subject: [PATCH 47/50] re-trigger kokoro --- .github/workflows/ci.yaml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 72d8c04c7..387b7d6a4 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -2,7 +2,6 @@ name: Continuous Integration on: [pull_request] - jobs: lint: name: Lint check From 34fc627721c2df7c17de4fcdb5a750ffc51ffc7b Mon Sep 17 00:00:00 2001 From: Michael Broughton Date: Tue, 13 Jun 2023 16:08:43 -0700 Subject: [PATCH 48/50] re-trigger kokoro --- .github/workflows/ci.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 387b7d6a4..72d8c04c7 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -2,6 +2,7 @@ name: Continuous Integration on: [pull_request] + jobs: lint: name: Lint check From 84b957c38a8f605f9d6897e6da04b4c2818c4346 Mon Sep 17 00:00:00 2001 From: Michael Broughton Date: Fri, 30 Jun 2023 13:44:00 -0700 Subject: [PATCH 49/50] Lower tolerances. --- tensorflow_quantum/core/ops/math_ops/simulate_mps_test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tensorflow_quantum/core/ops/math_ops/simulate_mps_test.py b/tensorflow_quantum/core/ops/math_ops/simulate_mps_test.py index ee7317b6a..114706d64 100644 --- a/tensorflow_quantum/core/ops/math_ops/simulate_mps_test.py +++ b/tensorflow_quantum/core/ops/math_ops/simulate_mps_test.py @@ -359,7 +359,7 @@ def test_complex_equality(self): symbol_values_array, util.convert_to_tensor(pauli_sums), bond_dim=32) - self.assertAllClose(mps_result, cirq_result, atol=1e-5) + self.assertAllClose(mps_result, cirq_result, atol=1e-4) def test_correctness_empty(self): """Tests the mps op with empty circuits.""" From 54df2d722a122431779a119256e9bd81eedc6eac Mon Sep 17 00:00:00 2001 From: Michael Broughton Date: Fri, 30 Jun 2023 13:54:33 -0700 Subject: [PATCH 50/50] Bump CI python version. --- .github/workflows/ci.yaml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 72d8c04c7..43f043e98 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -11,7 +11,7 @@ jobs: - uses: actions/checkout@v1 - uses: actions/setup-python@v1 with: - python-version: '3.8' + python-version: '3.9' architecture: 'x64' - name: Install Lint tools run: pip install --upgrade pip setuptools; pip install -r requirements.txt; @@ -26,7 +26,7 @@ jobs: - uses: actions/checkout@v1 - uses: actions/setup-python@v1 with: - python-version: '3.8' + python-version: '3.9' architecture: 'x64' - name: Install Format tools run: pip install --upgrade pip setuptools; pip install -r requirements.txt; sudo apt-get install -y clang-format-6.0 @@ -41,7 +41,7 @@ jobs: - uses: actions/checkout@v1 - uses: actions/setup-python@v1 with: - python-version: '3.8' + python-version: '3.9' architecture: 'x64' - name: Install Bazel on CI run: ./scripts/ci_install.sh @@ -61,7 +61,7 @@ jobs: - uses: actions/checkout@v1 - uses: actions/setup-python@v1 with: - python-version: '3.8' + python-version: '3.9' architecture: 'x64' - name: Install Bazel on CI run: ./scripts/ci_install.sh @@ -79,7 +79,7 @@ jobs: - uses: actions/checkout@v1 - uses: actions/setup-python@v1 with: - python-version: '3.8' + python-version: '3.9' architecture: 'x64' - name: Install Bazel on CI run: ./scripts/ci_install.sh @@ -97,7 +97,7 @@ jobs: - uses: actions/checkout@v1 - uses: actions/setup-python@v1 with: - python-version: '3.8' + python-version: '3.9' architecture: 'x64' - name: Install notebook dependencies run: pip install --upgrade pip seaborn==0.10.0