def von_neumann_entropy( state: 'cirq.QUANTUM_STATE_LIKE', qid_shape: Optional[Tuple[int, ...]] = None, validate: bool = True, atol: float = 1e-7, ) -> float: """Calculates the von Neumann entropy of a quantum state in bits. If `state` is a square matrix, it is assumed to be a density matrix rather than a (pure) state tensor. Args: state: The quantum state. qid_shape: The qid shape of the given state. validate: Whether to check if the given state is a valid quantum state. atol: Absolute numerical tolerance to use for validation. Returns: The calculated von Neumann entropy. Raises: ValueError: Invalid quantum state. """ if isinstance(state, QuantumState) and state._is_density_matrix(): state = state.data if isinstance(state, np.ndarray) and state.ndim == 2 and state.shape[0] == state.shape[1]: if validate: if qid_shape is None: qid_shape = (state.shape[0],) validate_density_matrix(state, qid_shape=qid_shape, dtype=state.dtype, atol=atol) eigenvalues = np.linalg.eigvalsh(state) return stats.entropy(np.abs(eigenvalues), base=2) if validate: _ = quantum_state(state, qid_shape=qid_shape, copy=False, validate=True, atol=atol) return 0.0
def fidelity( state1: 'cirq.QUANTUM_STATE_LIKE', state2: 'cirq.QUANTUM_STATE_LIKE', qid_shape: Optional[Tuple[int, ...]] = None, validate: bool = True, atol: float = 1e-7, ) -> float: """Fidelity of two quantum states. The fidelity of two density matrices ρ and σ is defined as trace(sqrt(sqrt(ρ) σ sqrt(ρ)))^2. The given states can be state vectors or density matrices. Args: state1: The first state. state2: The second state. qid_shape: The qid shape of the given states. validate: Whether to check if the given states are valid quantum states. atol: Absolute numerical tolerance to use for validation. Returns: The fidelity. Raises: ValueError: The qid shape of the given states was not specified and could not be inferred. ValueError: Invalid quantum state. """ # Two ints if isinstance(state1, int) and isinstance(state2, int): if validate: _validate_int_state(state1, qid_shape) _validate_int_state(state2, qid_shape) return float(state1 == state2) # Two ProductStates if isinstance(state1, value.ProductState) and isinstance(state2, value.ProductState): if len(state1) != len(state2): raise ValueError( 'Mismatched number of qubits in product states: ' f'{len(state1)} and {len(state2)}.' ) if validate: _validate_product_state(state1, qid_shape) _validate_product_state(state2, qid_shape) prod = 1.0 for q, s1 in state1: s2 = state2[q] prod *= np.abs(np.vdot(s1.state_vector(), s2.state_vector())) return prod**2 # Two numpy arrays that are either state vector, state tensor, or # density matrix if ( isinstance(state1, np.ndarray) and state1.dtype.kind == 'c' and isinstance(state2, np.ndarray) and state2.dtype.kind == 'c' ): state1, state2 = _numpy_arrays_to_state_vectors_or_density_matrices( state1, state2, qid_shape=qid_shape, validate=validate, atol=atol ) return _fidelity_state_vectors_or_density_matrices(state1, state2) # Use QuantumState machinery for the general case if qid_shape is None: try: qid_shape = infer_qid_shape(state1, state2) except: raise ValueError( 'Failed to infer the qid shape of the given states. ' 'Please specify the qid shape explicitly using the `qid_shape` argument.' ) state1 = quantum_state(state1, qid_shape=qid_shape, validate=validate, atol=atol) state2 = quantum_state(state2, qid_shape=qid_shape, validate=validate, atol=atol) state1_arr = state1.state_vector_or_density_matrix() state2_arr = state2.state_vector_or_density_matrix() return _fidelity_state_vectors_or_density_matrices(state1_arr, state2_arr)