def _qid_shape_(self): return protocols.qid_shape(self.to_circuit())
def _assert_apply_unitary_works_when_axes_transposed(val: Any, *, atol: float = 1e-8 ) -> None: """Tests whether a value's _apply_unitary_ handles out-of-order axes. A common mistake to make when implementing `_apply_unitary_` is to assume that the incoming axes will be contiguous, or ascending, or that they can be flattened, or that other axes have a length of two, etc, etc ,etc. This method checks that `_apply_unitary_` does the same thing to out-of-order axes that it does to contiguous in-order axes. Args: val: The operation, gate, or other unitary object to test. atol: Absolute error tolerance. """ # Only test custom apply unitary methods. if not hasattr(val, '_apply_unitary_') or not protocols.has_unitary(val): return # Pick sizes and shapes. shape = protocols.qid_shape(val) n = len(shape) padded_shape = shape + (1, 2, 2, 3) padded_n = len(padded_shape) size = np.product(padded_shape).item() # Shuffle the axes. permutation = list(range(padded_n)) random.shuffle(permutation) transposed_shape = [0] * padded_n for i in range(padded_n): transposed_shape[permutation[i]] = padded_shape[i] # Prepare input states. in_order_input = lin_alg_utils.random_superposition(size).reshape( padded_shape) out_of_order_input = np.empty(shape=transposed_shape, dtype=np.complex128) out_of_order_input.transpose(permutation)[...] = in_order_input # Apply to in-order and out-of-order axes. in_order_output = protocols.apply_unitary( val, protocols.ApplyUnitaryArgs( target_tensor=in_order_input, available_buffer=np.empty_like(in_order_input), axes=range(n), ), ) out_of_order_output = protocols.apply_unitary( val, protocols.ApplyUnitaryArgs( target_tensor=out_of_order_input, available_buffer=np.empty_like(out_of_order_input), axes=permutation[:n], ), ) # Put the out of order output back into order, to enable comparison. reordered_output = out_of_order_output.transpose(permutation) # The results should be identical. if not np.allclose(in_order_output, reordered_output, atol=atol): raise AssertionError( f'The _apply_unitary_ method of {repr(val)} acted differently on ' f'out-of-order axes than on in-order axes.\n' f'\n' f'The failing axis order: {repr(permutation[:n])}')
def set_state_vector(self, state: 'cirq.STATE_VECTOR_LIKE'): update_state = qis.to_valid_state_vector( state, len(self.qubit_map), qid_shape=protocols.qid_shape(self, None), dtype=self._dtype ) np.copyto(self._state_vector, update_state)
def assert_all_implemented_act_on_effects_match_unitary( val: Any, assert_tableau_implemented: bool = False, assert_ch_form_implemented: bool = False) -> None: """Uses val's effect on final_state_vector to check act_on(val)'s behavior. Checks that act_on with CliffordTableau or StabilizerStateCHForm behaves consistently with act_on through final state vector. Does not work with Operations or Gates expecting non-qubit Qids. If either of the assert_*_implmented args is true, fails if the corresponding method is not implemented for the test circuit. Args: val: A gate or operation that may be an input to protocols.act_on. assert_tableau_implemented: asserts that protocols.act_on() works with val and ActOnCliffordTableauArgs inputs. assert_ch_form_implemented: asserts that protocols.act_on() works with val and ActOnStabilizerStateChFormArgs inputs. """ # pylint: disable=unused-variable __tracebackhide__ = True # pylint: enable=unused-variable num_qubits_val = protocols.num_qubits(val) if (protocols.is_parameterized(val) or not protocols.has_unitary(val) or protocols.qid_shape(val) != (2, ) * num_qubits_val): if assert_tableau_implemented or assert_ch_form_implemented: assert False, ("Could not assert if any act_on methods were " "implemented. Operating on qudits or with a " "non-unitary or parameterized operation is " "unsupported.\n\nval: {!r}".format(val)) return None qubits = LineQubit.range(protocols.num_qubits(val) * 2) qubit_map = {qubit: i for i, qubit in enumerate(qubits)} circuit = Circuit() for i in range(num_qubits_val): circuit.append([ common_gates.H(qubits[i]), common_gates.CNOT(qubits[i], qubits[-i - 1]) ]) if hasattr(val, "on"): circuit.append(val.on(*qubits[:num_qubits_val])) else: circuit.append(val.with_qubits(*qubits[:num_qubits_val])) state_vector = np.reshape(final_state_vector(circuit, qubit_order=qubits), protocols.qid_shape(qubits)) tableau = _final_clifford_tableau(circuit, qubit_map) if tableau is None: assert ( not assert_tableau_implemented ), "Failed to generate final tableau for the test circuit.\n\nval: {!r}".format( val) else: assert all( state_vector_has_stabilizer(state_vector, stab) for stab in tableau.stabilizers()), ( "act_on clifford tableau is not consistent with " "final_state_vector simulation.\n\nval: {!r}".format(val)) stabilizer_ch_form = _final_stabilizer_state_ch_form(circuit, qubit_map) if stabilizer_ch_form is None: assert not assert_ch_form_implemented, ("Failed to generate final " "stabilizer state CH form " "for the test circuit." "\n\nval: {!r}".format(val)) else: np.testing.assert_allclose( np.reshape(stabilizer_ch_form.state_vector(), protocols.qid_shape(qubits)), state_vector, atol=1e-07, )
def _qid_shape_(self): return protocols.qid_shape(self._original)
def _qid_shape_(self) -> Tuple[int, ...]: return protocols.qid_shape(self.qubits)
def _qid_shape_(self) -> Tuple[int, ...]: return protocols.qid_shape(self.sub_gate)
def _qid_shape_(self): return protocols.qid_shape(self.gate)