def get_parities_from_measurements(measurements: List[Tuple[int]], ising_operator: IsingOperator) -> Parities: """Get expectation values from bitstrings. Args: measurements (list): the measured bitstrings ising_operator (openfermion.ops.IsingOperator): the operator Returns: zquantum.core.measurement.Parities: the parities of each term in the operator """ # check input format if isinstance(ising_operator, IsingOperator) == False: raise Exception("Input operator not openfermion.IsingOperator") # Count number of occurrences of bitstrings bitstring_frequencies = Counter(measurements) # Count parity occurences values = [] for _, term in enumerate(ising_operator.terms): values.append([0, 0]) marked_qubits = [op[0] for op in term] for bitstring, count in bitstring_frequencies.items(): bitstring_int = convert_bitstring_to_int(bitstring) if parity_even_p(bitstring_int, marked_qubits): values[-1][0] += count else: values[-1][1] += count # Count parity occurences for pairwise products of operators correlations = [ np.zeros((len(ising_operator.terms), len(ising_operator.terms), 2)) ] for term1_index, term1 in enumerate(ising_operator.terms): for term2_index, term2 in enumerate(ising_operator.terms): marked_qubits_term1 = [op[0] for op in term1] marked_qubits_term2 = [op[0] for op in term2] for bitstring, count in bitstring_frequencies.items(): bitstring_int = convert_bitstring_to_int(bitstring) parity1 = parity_even_p(bitstring_int, marked_qubits_term1) parity2 = parity_even_p(bitstring_int, marked_qubits_term2) if parity1 == parity2: correlations[0][term1_index, term2_index][0] += count else: correlations[0][term1_index, term2_index][1] += count return Parities(np.array(values), correlations)
def get_expectation_values( self, ising_operator: IsingOperator) -> ExpectationValues: """Get the expectation values of an operator from the measurements. Args: ising_operator (openfermion.ops.IsingOperator): the operator Returns: zquantum.core.measurement.ExpectationValues: the expectation values of each term in the operator """ # We require operator to be IsingOperator because measurements are always performed in the Z basis, # so we need the operator to be Ising (containing only Z terms). # A general Qubit Operator could have X or Y terms which don’t get directly measured. if isinstance(ising_operator, IsingOperator) == False: raise Exception("Input operator is not openfermion.IsingOperator") # Count number of occurrences of bitstrings bitstring_frequencies = self.get_counts() num_measurements = len(self.bitstrings) # Perform weighted average expectation_values = [] for term, coefficient in ising_operator.terms.items(): expectation = 0 marked_qubits = [op[0] for op in term] for bitstring, count in bitstring_frequencies.items(): bitstring_int = convert_bitstring_to_int(bitstring) if parity_even_p(bitstring_int, marked_qubits): value = float(count) / num_measurements else: value = -float(count) / num_measurements expectation += np.real(coefficient) * value expectation_values.append(np.real(expectation)) return ExpectationValues(np.array(expectation_values))
def test_parity_even_p(): state_index = 11 marked_qubits = [0, 1] with pytest.raises(AssertionError): parity_even_p("", marked_qubits) assert parity_even_p(state_index, marked_qubits)