def test_calculate_adj_grad_simple_case_single(self): """Make sure the adjoint gradient works on a one symbol for all gate.""" n_qubits = 2 batch_size = 1 symbol_names = ['alpha', 'beta', 'gamma'] qubits = cirq.GridQubit.rect(1, n_qubits) circuit_batch, resolver_batch = \ [cirq.Circuit(cirq.X(qubits[0]) ** sympy.Symbol('alpha'), cirq.Y(qubits[1]) ** sympy.Symbol('alpha'), cirq.CNOT(qubits[0], qubits[1]), cirq.FSimGate( -0.56, sympy.Symbol('alpha'))(qubits[0], qubits[1])) ], [{'alpha': 0.123, 'beta': 0.456, 'gamma': 0.789}] op_batch = [[cirq.Z(qubits[0]), cirq.X(qubits[1])] for _ in range(batch_size)] symbol_values_array = np.array( [[resolver[symbol] for symbol in symbol_names] for resolver in resolver_batch]) prev_grads = tf.ones([batch_size, len(op_batch[0])]) out = tfq_adj_grad_op.tfq_adj_grad( util.convert_to_tensor(circuit_batch), tf.convert_to_tensor(symbol_names), tf.convert_to_tensor(symbol_values_array), util.convert_to_tensor(op_batch), prev_grads) self.assertAllClose(out, np.array([[1.2993, 0, 0]]), atol=1e-3)
def test_calculate_adj_grad_empty(self): """Verify that the empty case is handled gracefully.""" out = tfq_adj_grad_op.tfq_adj_grad( util.convert_to_tensor([cirq.Circuit()]), tf.convert_to_tensor([], dtype=tf.dtypes.string), tf.convert_to_tensor([[]]), tf.convert_to_tensor([[]], dtype=tf.dtypes.string), tf.convert_to_tensor([[]])) self.assertShapeEqual(np.zeros((1, 0)), out)
def test_calculate_adj_grad_no_circuit(self): """Verify that the no circuit case is handled gracefully.""" out = tfq_adj_grad_op.tfq_adj_grad( tf.raw_ops.Empty(shape=(0, ), dtype=tf.string), tf.raw_ops.Empty(shape=(0, ), dtype=tf.string), tf.raw_ops.Empty(shape=(0, 0), dtype=tf.float32), tf.raw_ops.Empty(shape=(0, 0), dtype=tf.string), tf.raw_ops.Empty(shape=(0, 0), dtype=tf.float32), ) self.assertShapeEqual(np.zeros((0, 0)), out)
def test_adj_grad_inputs(self): """Make sure that the expectation op fails gracefully on bad inputs.""" n_qubits = 5 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) 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) upstream_grads = np.ones((batch_size, len(symbol_names))) with self.assertRaisesRegex(tf.errors.InvalidArgumentError, 'programs must be rank 1'): # Circuit tensor has too many dimensions. tfq_adj_grad_op.tfq_adj_grad( util.convert_to_tensor([circuit_batch]), symbol_names, tf.convert_to_tensor(symbol_values_array), util.convert_to_tensor([[x] for x in pauli_sums]), tf.convert_to_tensor(upstream_grads)) with self.assertRaisesRegex(tf.errors.InvalidArgumentError, 'symbol_names must be rank 1.'): # symbol_names tensor has too many dimensions. tfq_adj_grad_op.tfq_adj_grad( util.convert_to_tensor(circuit_batch), np.array([symbol_names]), tf.convert_to_tensor(symbol_values_array), util.convert_to_tensor([[x] for x in pauli_sums]), tf.convert_to_tensor(upstream_grads)) with self.assertRaisesRegex(tf.errors.InvalidArgumentError, 'symbol_values must be rank 2.'): # symbol_values_array tensor has too many dimensions. tfq_adj_grad_op.tfq_adj_grad( util.convert_to_tensor(circuit_batch), symbol_names, tf.convert_to_tensor(np.array([symbol_values_array])), util.convert_to_tensor([[x] for x in pauli_sums]), tf.convert_to_tensor(upstream_grads)) with self.assertRaisesRegex(tf.errors.InvalidArgumentError, 'symbol_values must be rank 2.'): # symbol_values_array tensor has too few dimensions. tfq_adj_grad_op.tfq_adj_grad( util.convert_to_tensor(circuit_batch), symbol_names, tf.convert_to_tensor(symbol_values_array[0]), util.convert_to_tensor([[x] for x in pauli_sums]), tf.convert_to_tensor(upstream_grads)) with self.assertRaisesRegex(tf.errors.InvalidArgumentError, 'pauli_sums must be rank 2.'): # pauli_sums tensor has too few dimensions. tfq_adj_grad_op.tfq_adj_grad( util.convert_to_tensor(circuit_batch), symbol_names, tf.convert_to_tensor(symbol_values_array), util.convert_to_tensor([x for x in pauli_sums]), tf.convert_to_tensor(upstream_grads)) with self.assertRaisesRegex(tf.errors.InvalidArgumentError, 'pauli_sums must be rank 2.'): # pauli_sums tensor has too many dimensions. tfq_adj_grad_op.tfq_adj_grad( util.convert_to_tensor(circuit_batch), symbol_names, tf.convert_to_tensor(symbol_values_array), util.convert_to_tensor([[[x]] for x in pauli_sums]), tf.convert_to_tensor(upstream_grads)) with self.assertRaisesRegex(tf.errors.InvalidArgumentError, 'Unparseable proto'): # circuit tensor has the right type but invalid values. tfq_adj_grad_op.tfq_adj_grad( ['junk'] * batch_size, symbol_names, tf.convert_to_tensor(symbol_values_array), util.convert_to_tensor([[x] for x in pauli_sums]), tf.convert_to_tensor(upstream_grads)) with self.assertRaisesRegex(tf.errors.InvalidArgumentError, 'Could not find symbol in parameter map'): # symbol_names tensor has the right type but invalid values. tfq_adj_grad_op.tfq_adj_grad( util.convert_to_tensor(circuit_batch), ['junk'], tf.convert_to_tensor(symbol_values_array), util.convert_to_tensor([[x] for x in pauli_sums]), tf.convert_to_tensor(upstream_grads)) with self.assertRaisesRegex(tf.errors.InvalidArgumentError, 'qubits not found in circuit'): # pauli_sums tensor has the right type but invalid values. new_qubits = [cirq.GridQubit(5, 5), cirq.GridQubit(9, 9)] new_pauli_sums = util.random_pauli_sums(new_qubits, 2, batch_size) tfq_adj_grad_op.tfq_adj_grad( util.convert_to_tensor(circuit_batch), symbol_names, tf.convert_to_tensor(symbol_values_array), util.convert_to_tensor([[x] for x in new_pauli_sums]), tf.convert_to_tensor(upstream_grads)) with self.assertRaisesRegex(tf.errors.InvalidArgumentError, 'Unparseable proto'): # pauli_sums tensor has the right type but invalid values 2. tfq_adj_grad_op.tfq_adj_grad( util.convert_to_tensor(circuit_batch), symbol_names, tf.convert_to_tensor(symbol_values_array), [['junk']] * batch_size, tf.convert_to_tensor(upstream_grads)) with self.assertRaisesRegex(TypeError, 'Cannot convert'): # circuits tensor has the wrong type. tfq_adj_grad_op.tfq_adj_grad( [1.0] * batch_size, symbol_names, tf.convert_to_tensor(symbol_values_array), util.convert_to_tensor([[x] for x in pauli_sums]), tf.convert_to_tensor(upstream_grads)) with self.assertRaisesRegex(TypeError, 'Cannot convert'): # symbol_names tensor has the wrong type. tfq_adj_grad_op.tfq_adj_grad( util.convert_to_tensor(circuit_batch), [0.1234], tf.convert_to_tensor(symbol_values_array), util.convert_to_tensor([[x] for x in pauli_sums]), tf.convert_to_tensor(upstream_grads)) with self.assertRaisesRegex(tf.errors.UnimplementedError, ''): # symbol_values tensor has the wrong type. tfq_adj_grad_op.tfq_adj_grad( util.convert_to_tensor(circuit_batch), symbol_names, [['junk']] * batch_size, util.convert_to_tensor([[x] for x in pauli_sums]), tf.convert_to_tensor(upstream_grads)) with self.assertRaisesRegex(TypeError, 'Cannot convert'): # pauli_sums tensor has the wrong type. tfq_adj_grad_op.tfq_adj_grad( util.convert_to_tensor(circuit_batch), symbol_names, tf.convert_to_tensor(symbol_values_array), [[1.0]] * batch_size, tf.convert_to_tensor(upstream_grads)) with self.assertRaisesRegex(TypeError, 'missing'): # we are missing an argument. # pylint: disable=no-value-for-parameter tfq_adj_grad_op.tfq_adj_grad( util.convert_to_tensor(circuit_batch), symbol_names, tf.convert_to_tensor(symbol_values_array), tf.convert_to_tensor(upstream_grads)) # pylint: enable=no-value-for-parameter with self.assertRaisesRegex(TypeError, 'positional arguments'): # pylint: disable=too-many-function-args tfq_adj_grad_op.tfq_adj_grad( util.convert_to_tensor(circuit_batch), symbol_names, tf.convert_to_tensor(symbol_values_array), util.convert_to_tensor([[x] for x in pauli_sums]), tf.convert_to_tensor(upstream_grads), []) with self.assertRaisesRegex(tf.errors.InvalidArgumentError, expected_regex='do not match'): # wrong op size. tfq_adj_grad_op.tfq_adj_grad( util.convert_to_tensor([cirq.Circuit()]), symbol_names, symbol_values_array.astype(np.float64), util.convert_to_tensor([[x] for x in pauli_sums]), tf.convert_to_tensor(upstream_grads)) with self.assertRaisesRegex(tf.errors.InvalidArgumentError, expected_regex='rank 2'): # wrong grad shape. tfq_adj_grad_op.tfq_adj_grad( util.convert_to_tensor(circuit_batch), symbol_names, tf.convert_to_tensor(symbol_values_array), util.convert_to_tensor([[x] for x in pauli_sums]), tf.convert_to_tensor([upstream_grads])) with self.assertRaisesRegex( tf.errors.InvalidArgumentError, expected_regex='gradients and circuits do not match'): # wrong grad batch size. tfq_adj_grad_op.tfq_adj_grad( util.convert_to_tensor(circuit_batch), symbol_names, tf.convert_to_tensor(symbol_values_array), util.convert_to_tensor([[x] for x in pauli_sums]), tf.convert_to_tensor([[0 for i in range(len(symbol_names))]])) with self.assertRaisesRegex( tf.errors.InvalidArgumentError, expected_regex='gradients and pauli sum dimension do not match' ): # wrong grad inner size. tfq_adj_grad_op.tfq_adj_grad( util.convert_to_tensor(circuit_batch), symbol_names, tf.convert_to_tensor(symbol_values_array), util.convert_to_tensor([[x] for x in pauli_sums]), tf.convert_to_tensor([[0, 0] for _ in range(len(circuit_batch))]))
def differentiate_analytic(self, programs, symbol_names, symbol_values, pauli_sums, forward_pass_vals, grad): return tfq_adj_grad_op.tfq_adj_grad(programs, symbol_names, symbol_values, pauli_sums, grad)