From af9c92b5e5b17a012fafd67b9cea389b57b77986 Mon Sep 17 00:00:00 2001 From: Michael Broughton Date: Tue, 12 Jan 2021 00:13:52 -0800 Subject: [PATCH 01/11] W.I.P Final plumbing of multi-qubit gates. --- .../core/ops/circuit_execution_ops_test.py | 2 +- .../core/ops/tfq_adj_grad_op.cc | 29 +++++-- .../core/ops/tfq_simulate_ops_test.py | 2 +- .../core/ops/tfq_utility_ops_test.py | 18 +++- .../core/serialize/serializer.py | 18 ++-- .../python/differentiators/gradient_test.py | 2 +- tensorflow_quantum/python/util.py | 87 +++++++++++++++---- tensorflow_quantum/python/util_test.py | 13 --- 8 files changed, 121 insertions(+), 50 deletions(-) diff --git a/tensorflow_quantum/core/ops/circuit_execution_ops_test.py b/tensorflow_quantum/core/ops/circuit_execution_ops_test.py index 46a738613..88e57b693 100644 --- a/tensorflow_quantum/core/ops/circuit_execution_ops_test.py +++ b/tensorflow_quantum/core/ops/circuit_execution_ops_test.py @@ -233,7 +233,7 @@ def test_simulate_state_no_symbols(self, op_and_sim, n_qubits): util.kwargs_cartesian_product( **{ 'op_and_sim': [(op, sim) - for (op, sim) in zip(STATE_OPS, SIMS)], + for (op, sim) in list(zip(STATE_OPS, SIMS))[:1]], 'n_qubits': [3, 7], 'symbol_names': [['a'], ['a', 'b'], ['a', 'b', 'c', 'd', 'e']] diff --git a/tensorflow_quantum/core/ops/tfq_adj_grad_op.cc b/tensorflow_quantum/core/ops/tfq_adj_grad_op.cc index bc4c74972..02003eef7 100644 --- a/tensorflow_quantum/core/ops/tfq_adj_grad_op.cc +++ b/tensorflow_quantum/core/ops/tfq_adj_grad_op.cc @@ -144,15 +144,15 @@ class TfqAdjointGradientOp : public tensorflow::OpKernel { // ... // This method creates 3 big state vectors per thread so reducing size // here slightly. - if (max_num_qubits >= 25 || programs.size() == 1) { + /*if (max_num_qubits >= 25 || programs.size() == 1) { ComputeLarge(num_qubits, qsim_circuits, maps, full_fuse, partial_fused_circuits, pauli_sums, gradient_gates, downstream_grads, context, &output_tensor); - } else { + } else {*/ ComputeSmall(num_qubits, max_num_qubits, qsim_circuits, maps, full_fuse, partial_fused_circuits, pauli_sums, gradient_gates, downstream_grads, context, &output_tensor); - } + //} } private: @@ -219,12 +219,29 @@ class TfqAdjointGradientOp : public tensorflow::OpKernel { } // Hit a parameterized gate. - ApplyGateDagger( - sim, qsim_circuits[i].gates[gradient_gates[i][j - 1].index], sv); + // todo fix this copy. + auto cur_gate = qsim_circuits[i].gates[gradient_gates[i][j - 1].index]; + ApplyGateDagger(sim, cur_gate, sv); + + StateSpace::MeasurementResult mr; + mr.mask = 0; + mr.bits = 0; + for(int l =0; l len(qubits)): + # skip adding gates in small case. + continue + locs = tuple(random.sample(qubits, n_qubits)) + if isinstance(op, cirq.IdentityGate): + circuit[:i] += op.on(*locs) + continue + full_gate = (op**np.random.random()).on(*locs) + if np.random.random() < 0.5: + # Add a control to this gate. + full_gate = _apply_random_control(full_gate, qubits) + + circuit[:i] += full_gate + + return_circuits.append(circuit) return_resolvers.append(cirq.ParamResolver({})) return return_circuits, return_resolvers @@ -317,6 +366,9 @@ def kwargs_cartesian_product(**kwargs): def _symbols_in_op(op): """Returns the set of symbols in a parameterized gate.""" + if isinstance(op, cirq.ControlledOperation): + op = op.gate + if isinstance(op, cirq.EigenGate): return op.exponent.free_symbols @@ -357,7 +409,10 @@ def get_circuit_symbols(circuit): for moment in circuit: for op in moment: if cirq.is_parameterized(op): - all_symbols |= _symbols_in_op(op.gate) + sub_op = op + if isinstance(op, cirq.ControlledOperation): + sub_op = op.sub_operation + all_symbols |= _symbols_in_op(sub_op.gate) return [str(x) for x in all_symbols] diff --git a/tensorflow_quantum/python/util_test.py b/tensorflow_quantum/python/util_test.py index db8af817e..e6783e5be 100644 --- a/tensorflow_quantum/python/util_test.py +++ b/tensorflow_quantum/python/util_test.py @@ -208,19 +208,6 @@ def test_get_circuit_symbols_all(self): self.assertListEqual(sorted(extracted_symbols), sorted(expected_symbols)) - def test_get_circuit_symbols_error(self): - """Ensure that errors are reported when using unsupported ops.""" - # TODO(mbbrough): remove this test once we reach complete parity - # with cirq in terms of parametrized gate support. - qubits = cirq.GridQubit.rect(1, 2) - symbol = sympy.Symbol("u") - op = cirq.ZPowGate(exponent=symbol).on(qubits[0]).controlled_by( - qubits[1]) - bad_circuit = cirq.Circuit(op) - with self.assertRaisesRegex( - ValueError, expected_regex="tfq.util.get_supported_gates"): - util.get_circuit_symbols(bad_circuit) - class ExponentialUtilFunctionsTest(tf.test.TestCase): """Test that Exponential utility functions work.""" From 6bb8545e3936b2b55aba7f717a66ca0942547e4a Mon Sep 17 00:00:00 2001 From: Michael Broughton Date: Tue, 12 Jan 2021 11:52:31 -0800 Subject: [PATCH 02/11] fix in-moment ordering for control gates. --- .../core/ops/circuit_execution_ops_test.py | 2 +- .../core/ops/tfq_adj_grad_op.cc | 35 +++++++++++++------ .../core/ops/tfq_utility_ops_test.py | 6 ++-- .../core/serialize/serializer.py | 13 +++---- tensorflow_quantum/python/util.py | 3 -- 5 files changed, 35 insertions(+), 24 deletions(-) diff --git a/tensorflow_quantum/core/ops/circuit_execution_ops_test.py b/tensorflow_quantum/core/ops/circuit_execution_ops_test.py index 88e57b693..46a738613 100644 --- a/tensorflow_quantum/core/ops/circuit_execution_ops_test.py +++ b/tensorflow_quantum/core/ops/circuit_execution_ops_test.py @@ -233,7 +233,7 @@ def test_simulate_state_no_symbols(self, op_and_sim, n_qubits): util.kwargs_cartesian_product( **{ 'op_and_sim': [(op, sim) - for (op, sim) in list(zip(STATE_OPS, SIMS))[:1]], + for (op, sim) in zip(STATE_OPS, SIMS)], 'n_qubits': [3, 7], 'symbol_names': [['a'], ['a', 'b'], ['a', 'b', 'c', 'd', 'e']] diff --git a/tensorflow_quantum/core/ops/tfq_adj_grad_op.cc b/tensorflow_quantum/core/ops/tfq_adj_grad_op.cc index 02003eef7..9ee7e2fab 100644 --- a/tensorflow_quantum/core/ops/tfq_adj_grad_op.cc +++ b/tensorflow_quantum/core/ops/tfq_adj_grad_op.cc @@ -144,15 +144,15 @@ class TfqAdjointGradientOp : public tensorflow::OpKernel { // ... // This method creates 3 big state vectors per thread so reducing size // here slightly. - /*if (max_num_qubits >= 25 || programs.size() == 1) { + if (max_num_qubits >= 25 || programs.size() == 1) { ComputeLarge(num_qubits, qsim_circuits, maps, full_fuse, partial_fused_circuits, pauli_sums, gradient_gates, downstream_grads, context, &output_tensor); - } else {*/ + } else { ComputeSmall(num_qubits, max_num_qubits, qsim_circuits, maps, full_fuse, partial_fused_circuits, pauli_sums, gradient_gates, downstream_grads, context, &output_tensor); - //} + } } private: @@ -256,9 +256,7 @@ class TfqAdjointGradientOp : public tensorflow::OpKernel { (*output_tensor)(i, loc) += ss.RealInnerProduct(scratch2, scratch) + ss.RealInnerProduct(scratch, scratch2); } - ApplyGateDagger( - sim, cur_gate, - scratch); + ApplyGateDagger(sim, cur_gate, scratch); } } }; @@ -332,12 +330,29 @@ class TfqAdjointGradientOp : public tensorflow::OpKernel { } // Hit a parameterized gate. - ApplyGateDagger( - sim, qsim_circuits[i].gates[gradient_gates[i][j - 1].index], sv); + // todo fix this copy. + auto cur_gate = qsim_circuits[i].gates[gradient_gates[i][j - 1].index]; + ApplyGateDagger(sim, cur_gate, sv); + + StateSpace::MeasurementResult mr; + mr.mask = 0; + mr.bits = 0; + for(int l =0; l Date: Fri, 22 Jan 2021 15:11:48 -0800 Subject: [PATCH 03/11] Format and 0.7.0 merge. --- tensorflow_quantum/core/ops/tfq_adj_grad_op.cc | 11 ++++++----- tensorflow_quantum/core/ops/tfq_simulate_ops_test.py | 4 ++-- tensorflow_quantum/core/ops/tfq_utility_ops_test.py | 2 +- tensorflow_quantum/core/serialize/serializer.py | 3 ++- tensorflow_quantum/python/util.py | 8 ++++---- 5 files changed, 15 insertions(+), 13 deletions(-) diff --git a/tensorflow_quantum/core/ops/tfq_adj_grad_op.cc b/tensorflow_quantum/core/ops/tfq_adj_grad_op.cc index 9ee7e2fab..7deea5f36 100644 --- a/tensorflow_quantum/core/ops/tfq_adj_grad_op.cc +++ b/tensorflow_quantum/core/ops/tfq_adj_grad_op.cc @@ -220,13 +220,14 @@ class TfqAdjointGradientOp : public tensorflow::OpKernel { // Hit a parameterized gate. // todo fix this copy. - auto cur_gate = qsim_circuits[i].gates[gradient_gates[i][j - 1].index]; + auto cur_gate = + qsim_circuits[i].gates[gradient_gates[i][j - 1].index]; ApplyGateDagger(sim, cur_gate, sv); StateSpace::MeasurementResult mr; mr.mask = 0; mr.bits = 0; - for(int l =0; l len(qubits)): + if (n_qubits > len(qubits)): # skip adding gates in small case. continue locs = tuple(random.sample(qubits, n_qubits)) From 53a9b2aace80db53105a874f65749b64545c640d Mon Sep 17 00:00:00 2001 From: Michael Broughton Date: Fri, 22 Jan 2021 15:30:14 -0800 Subject: [PATCH 04/11] format. --- tensorflow_quantum/python/util.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tensorflow_quantum/python/util.py b/tensorflow_quantum/python/util.py index 1b99c644f..72038e58a 100644 --- a/tensorflow_quantum/python/util.py +++ b/tensorflow_quantum/python/util.py @@ -96,10 +96,10 @@ def random_symbol_circuit(qubits, if isinstance(op, cirq.IdentityGate): circuit[:i] += op.on(*locs) continue - full_gate = (op**( - (np.random.random() if include_scalars else 1.0) * - sympy.Symbol(random_symbols[location % len(random_symbols)]))).on( - *locs) + working_symbol = sympy.Symbol(random_symbols[location % + len(random_symbols)]) + working_scalar = np.random.random() if include_scalars else 1.0 + full_gate = (op**(working_scalar * working_symbol)).on(*locs) if np.random.random() < 0.5: # Add a control to this gate. full_gate = _apply_random_control(full_gate, qubits) From ac262f64fa1f5a2832153b8ab4d4d8bffdcb3eb1 Mon Sep 17 00:00:00 2001 From: Michael Broughton Date: Fri, 22 Jan 2021 15:34:45 -0800 Subject: [PATCH 05/11] missed format on simulate_ops_test. --- tensorflow_quantum/core/ops/tfq_simulate_ops_test.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tensorflow_quantum/core/ops/tfq_simulate_ops_test.py b/tensorflow_quantum/core/ops/tfq_simulate_ops_test.py index e81604624..ae4addb58 100644 --- a/tensorflow_quantum/core/ops/tfq_simulate_ops_test.py +++ b/tensorflow_quantum/core/ops/tfq_simulate_ops_test.py @@ -453,8 +453,8 @@ def test_sampling_output_padding(self, all_n_qubits, n_samples): this_expected_output[:, :max(all_n_qubits) - n_qubits] = -2 expected_outputs.append(this_expected_output) circuits.append( - cirq.Circuit(*cirq.X.on_each( - *cirq.GridQubit.rect(1, n_qubits)))) + cirq.Circuit( + *cirq.X.on_each(*cirq.GridQubit.rect(1, n_qubits)))) results = op(util.convert_to_tensor(circuits), [], [[]] * len(circuits), [n_samples]).numpy() self.assertAllClose(expected_outputs, results) From 274954e2a89a611698112eee58c70f5a5a25e60f Mon Sep 17 00:00:00 2001 From: Michael Broughton Date: Tue, 26 Jan 2021 13:08:43 -0800 Subject: [PATCH 06/11] upgraded to working qsim. --- WORKSPACE | 6 +-- .../core/ops/tfq_adj_grad_op.cc | 38 +++++++++---------- tensorflow_quantum/python/util.py | 10 ++++- 3 files changed, 31 insertions(+), 23 deletions(-) diff --git a/WORKSPACE b/WORKSPACE index bc2b6edf6..ff69268a4 100644 --- a/WORKSPACE +++ b/WORKSPACE @@ -67,9 +67,9 @@ http_archive( http_archive( name = "qsim", - sha256 = "c257c9958e7b55e85161e3d39c1d8c85148f45c82f86c69712cf815728f52faf", - strip_prefix = "qsim-0.7.0", - urls = ["https://github.com/quantumlib/qsim/archive/v0.7.0.zip"], + sha256 = "e2853379bde52d6277f9be4b80f54d32b3b27f7242a6c561cb34fb12d823b80e", + strip_prefix = "qsim-0.7.1-dev-20210126", + urls = ["https://github.com/quantumlib/qsim/archive/v0.7.1-dev+20210126.zip"], ) # Added for crosstool in tensorflow. diff --git a/tensorflow_quantum/core/ops/tfq_adj_grad_op.cc b/tensorflow_quantum/core/ops/tfq_adj_grad_op.cc index 7deea5f36..2d952fa47 100644 --- a/tensorflow_quantum/core/ops/tfq_adj_grad_op.cc +++ b/tensorflow_quantum/core/ops/tfq_adj_grad_op.cc @@ -219,29 +219,29 @@ class TfqAdjointGradientOp : public tensorflow::OpKernel { } // Hit a parameterized gate. - // todo fix this copy. auto cur_gate = qsim_circuits[i].gates[gradient_gates[i][j - 1].index]; + ApplyGateDagger(sim, cur_gate, sv); - StateSpace::MeasurementResult mr; - mr.mask = 0; - mr.bits = 0; - for (int l = 0; l < cur_gate.controlled_by.size(); l++) { - auto control_loc = cur_gate.controlled_by[l]; - mr.mask |= (uint64_t{1} << control_loc); - mr.bits |= (cur_gate.cmask & (1 << l)) << control_loc; + // if applicable compute control qubit mask and control value bits. + uint64_t mask = 0; + uint64_t cbits = 0; + 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 (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); - if (cur_gate.controlled_by.size()) { + if (!cur_gate.controlled_by.empty()) { // Gradient of controlled gattes puts zeros on diagonal which is // the same as collapsing the state and then applying the // non-controlled version of the gradient gate. - ss.Collapse(mr, scratch2); + ss.BulkSetAmpl(scratch2, mask, cbits, 0, 0, true); } qsim::ApplyGate(sim, gradient_gates[i][j - 1].grad_gates[k], scratch2); @@ -335,24 +335,24 @@ class TfqAdjointGradientOp : public tensorflow::OpKernel { auto cur_gate = qsim_circuits[i].gates[gradient_gates[i][j - 1].index]; ApplyGateDagger(sim, cur_gate, sv); - StateSpace::MeasurementResult mr; - mr.mask = 0; - mr.bits = 0; - for (int l = 0; l < cur_gate.controlled_by.size(); l++) { - auto control_loc = cur_gate.controlled_by[l]; - mr.mask |= (uint64_t{1} << control_loc); - mr.bits |= (cur_gate.cmask & (1 << l)) << control_loc; + // if applicable compute control qubit mask and control value bits. + uint64_t mask = 0; + uint64_t cbits = 0; + 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 (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); - if (cur_gate.controlled_by.size()) { + if (!cur_gate.controlled_by.empty()) { // Gradient of controlled gattes puts zeros on diagonal which is // the same as collapsing the state and then applying the // non-controlled version of the gradient gate. - ss.Collapse(mr, scratch2); + ss.BulkSetAmpl(scratch2, mask, cbits, 0, 0, true); } qsim::ApplyGate(sim, gradient_gates[i][j - 1].grad_gates[k], scratch2); diff --git a/tensorflow_quantum/python/util.py b/tensorflow_quantum/python/util.py index 72038e58a..deeeb15df 100644 --- a/tensorflow_quantum/python/util.py +++ b/tensorflow_quantum/python/util.py @@ -26,7 +26,15 @@ def get_supported_gates(): - """A helper to get the gates supported by tfq.""" + """A helper to get the gates supported by tfq. + + Returns a dictionary mapping from supported gate types + to the number of qubits each gate operates on. + + Any of these gates used in conjuction with the + `controll_by` function for multi qubit control are also + supported. + """ supported_gates = serializer.SERIALIZER.supported_gate_types() gate_arity_mapping_dict = dict() for gate in supported_gates: From 1ee556fb1e441105a7e62436ca8f083ca27dc506 Mon Sep 17 00:00:00 2001 From: Michael Broughton Date: Tue, 26 Jan 2021 13:13:43 -0800 Subject: [PATCH 07/11] format. --- tensorflow_quantum/core/ops/tfq_adj_grad_op.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tensorflow_quantum/core/ops/tfq_adj_grad_op.cc b/tensorflow_quantum/core/ops/tfq_adj_grad_op.cc index 2d952fa47..d2c5782f6 100644 --- a/tensorflow_quantum/core/ops/tfq_adj_grad_op.cc +++ b/tensorflow_quantum/core/ops/tfq_adj_grad_op.cc @@ -227,7 +227,7 @@ class TfqAdjointGradientOp : public tensorflow::OpKernel { // if applicable compute control qubit mask and control value bits. uint64_t mask = 0; uint64_t cbits = 0; - for (int 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; @@ -338,7 +338,7 @@ class TfqAdjointGradientOp : public tensorflow::OpKernel { // if applicable compute control qubit mask and control value bits. uint64_t mask = 0; uint64_t cbits = 0; - for (int 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; From 4d1c66eec1e4c891d58fd13f4f276069dc8ef0a9 Mon Sep 17 00:00:00 2001 From: Michael Broughton Date: Tue, 26 Jan 2021 15:47:17 -0800 Subject: [PATCH 08/11] Support muliple control values and fix bug in decompose. --- tensorflow_quantum/core/ops/tfq_ps_decompose_op.cc | 14 +++++++------- .../python/differentiators/gradient_test.py | 4 ++-- tensorflow_quantum/python/util.py | 3 ++- 3 files changed, 11 insertions(+), 10 deletions(-) diff --git a/tensorflow_quantum/core/ops/tfq_ps_decompose_op.cc b/tensorflow_quantum/core/ops/tfq_ps_decompose_op.cc index cb3c01674..bbfa23537 100644 --- a/tensorflow_quantum/core/ops/tfq_ps_decompose_op.cc +++ b/tensorflow_quantum/core/ops/tfq_ps_decompose_op.cc @@ -55,7 +55,7 @@ class TfqPsDecomposeOp : public tensorflow::OpKernel { 0, context->input(0).shape(), &output)); auto output_tensor = output->flat(); - const int max_buffer_moments = 3; + const int max_buffer_moments = 5; auto DoWork = [&](int start, int end) { for (int i = start; i < end; i++) { @@ -79,21 +79,21 @@ class TfqPsDecomposeOp : public tensorflow::OpKernel { phase_exponent.arg_case() == Arg::ArgCase::kSymbol) { // Decompose cirq.PhasedISwapPowGate only if it is // parameterized. - num_extra_moments = 3; + num_extra_moments = 5; Operation new_op; new_op = getOpForPISP(cur_op, 0, 0); cur_moment.mutable_operations()->at(k) = new_op; new_op = getOpForPISP(cur_op, 1, 1); - *cur_moment.add_operations() = new_op; - new_op = getOpForISP(cur_op, "XXP", exponent.symbol()); *temp_moment_list[0].add_operations() = new_op; - new_op = getOpForISP(cur_op, "YYP", exponent.symbol()); + new_op = getOpForISP(cur_op, "XXP", exponent.symbol()); *temp_moment_list[1].add_operations() = new_op; - new_op = getOpForPISP(cur_op, 1, 0); + new_op = getOpForISP(cur_op, "YYP", exponent.symbol()); *temp_moment_list[2].add_operations() = new_op; + new_op = getOpForPISP(cur_op, 1, 0); + *temp_moment_list[3].add_operations() = new_op; new_op = getOpForPISP(cur_op, 0, 1); - *temp_moment_list[2].add_operations() = new_op; + *temp_moment_list[4].add_operations() = new_op; } } else if (cur_op.gate().id() == "ISP") { auto exponent = cur_op_map.at("exponent"); diff --git a/tensorflow_quantum/python/differentiators/gradient_test.py b/tensorflow_quantum/python/differentiators/gradient_test.py index 5bfcfe3ee..92e91ab66 100644 --- a/tensorflow_quantum/python/differentiators/gradient_test.py +++ b/tensorflow_quantum/python/differentiators/gradient_test.py @@ -151,14 +151,14 @@ def exact_grad(theta): **{ 'differentiator': ANALYTIC_DIFFS, 'op': ANALYTIC_OPS, - 'n_qubits': [5], + 'n_qubits': [10], 'n_programs': [3], 'n_ops': [3], 'symbol_names': [['a', 'b']] })) + [{ 'differentiator': adjoint.Adjoint(), 'op': circuit_execution_ops.get_expectation_op(), - 'n_qubits': 5, + 'n_qubits': 10, 'n_programs': 5, 'n_ops': 3, 'symbol_names': ['a', 'b'] diff --git a/tensorflow_quantum/python/util.py b/tensorflow_quantum/python/util.py index deeeb15df..87c4ea032 100644 --- a/tensorflow_quantum/python/util.py +++ b/tensorflow_quantum/python/util.py @@ -77,7 +77,8 @@ def _apply_random_control(gate, all_qubits): # No open qubits to control. Return unmodified gate. return gate control_locs = random.sample(open_qubits, n_open) - return gate.controlled_by(*control_locs) + control_values = random.choices([0, 1], k=n_open) + return gate.controlled_by(*control_locs, control_values=control_values) def random_symbol_circuit(qubits, From 8f8907de2e57d9a4535577e0ec23c4ab2cd7bdb2 Mon Sep 17 00:00:00 2001 From: Michael Broughton Date: Tue, 26 Jan 2021 19:15:37 -0800 Subject: [PATCH 09/11] loosened padding test atol. --- tensorflow_quantum/core/ops/cirq_ops_test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tensorflow_quantum/core/ops/cirq_ops_test.py b/tensorflow_quantum/core/ops/cirq_ops_test.py index 31dcdb27e..77569bf5f 100644 --- a/tensorflow_quantum/core/ops/cirq_ops_test.py +++ b/tensorflow_quantum/core/ops/cirq_ops_test.py @@ -296,7 +296,7 @@ def test_simulate_state_output_padding(self, op_and_sim, all_n_qubits): 'Simulator returned unknown type of result.' + str(type(result))) - self.assertAllClose(tfq_results, manual_padded_results) + self.assertAllClose(tfq_results, manual_padded_results, atol=1e-5) def test_state_empty_circuit(self): """Test empty circuits""" From 33818c044300b7cbfa8195076f307214d9a4bb6f Mon Sep 17 00:00:00 2001 From: Michael Broughton Date: Tue, 26 Jan 2021 22:08:29 -0800 Subject: [PATCH 10/11] Loosen inner product atol. --- tensorflow_quantum/core/ops/math_ops/inner_product_op_test.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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 b9a62c116..e63b08354 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 @@ -250,7 +250,7 @@ def test_correctness_with_symbols(self, n_qubits, batch_size, internal_wf = cirq.final_state_vector(other_batch[i][j]) out_arr[i][j] = np.vdot(final_wf, internal_wf) - self.assertAllClose(out, out_arr) + self.assertAllClose(out, out_arr, atol=1e-5) @parameterized.parameters([ { @@ -297,7 +297,7 @@ def test_correctness_without_symbols(self, n_qubits, batch_size, internal_wf = cirq.final_state_vector(other_batch[i][j]) out_arr[i][j] = np.vdot(final_wf, internal_wf) - self.assertAllClose(out, out_arr) + self.assertAllClose(out, out_arr, atol=1e-5) def test_correctness_empty(self): """Test the inner product between two empty circuits.""" From f00a4a643806a3a1db3b420575bfeb028ddc48fc Mon Sep 17 00:00:00 2001 From: Michael Broughton Date: Tue, 26 Jan 2021 22:16:14 -0800 Subject: [PATCH 11/11] backed off gradient test runtime. --- tensorflow_quantum/python/differentiators/gradient_test.py | 2 +- tensorflow_quantum/python/util.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tensorflow_quantum/python/differentiators/gradient_test.py b/tensorflow_quantum/python/differentiators/gradient_test.py index 92e91ab66..06306bb8d 100644 --- a/tensorflow_quantum/python/differentiators/gradient_test.py +++ b/tensorflow_quantum/python/differentiators/gradient_test.py @@ -151,7 +151,7 @@ def exact_grad(theta): **{ 'differentiator': ANALYTIC_DIFFS, 'op': ANALYTIC_OPS, - 'n_qubits': [10], + 'n_qubits': [5], 'n_programs': [3], 'n_ops': [3], 'symbol_names': [['a', 'b']] diff --git a/tensorflow_quantum/python/util.py b/tensorflow_quantum/python/util.py index 87c4ea032..3b64f7ce1 100644 --- a/tensorflow_quantum/python/util.py +++ b/tensorflow_quantum/python/util.py @@ -32,7 +32,7 @@ def get_supported_gates(): to the number of qubits each gate operates on. Any of these gates used in conjuction with the - `controll_by` function for multi qubit control are also + `controlled_by` function for multi qubit control are also supported. """ supported_gates = serializer.SERIALIZER.supported_gate_types()