def test_transpile_grid_circuit(self): c = Circuit() qb = pytket._tket.circuit.Qubit("grid", 0, 0) c.add_qubit(qb) c.Rz(1, qb) qsc = jaqal_circuit_from_tket_circuit(c) jcirc = CircuitBuilder() reg = jcirc.register("baseregister", 1) reg2 = jcirc.map("grid0_0", reg, slice(0, 1, 1)) block = jcirc.block() block.gate("prepare_all") block.gate("Rz", reg2[0], pi) block.gate("measure_all") self.assertEqual(generate_jaqal_program(jcirc.build()), generate_jaqal_program(qsc))
backend = ProjectQBackend() ideal_energy = backend.get_operator_expectation_value( ansatz, QubitPauliOperator.from_OpenFermion(hamiltonian)) print(ideal_energy) # Ideally the state generated by this ansatz will only span the computational basis states with exactly two of the four qubits in state $\lvert 1 \rangle$. This is because these basis states correspond to two electrons being present in the molecule. # # This ansatz is a hardware-efficient model that is designed to explore a large portion of the Hilbert space with relatively few entangling gates. Unfortunately, with this much freedom, it will regularly generate states that have no physical interpretation such as states spanning multiple basis states corresponding to different numbers of electrons in the system (which we assume is fixed and conserved). # # We can mitigate this by using a syndrome qubit that calculates the parity of the other qubits. Post-selecting this syndrome with $\langle 0 \rvert$ will project the remaining state onto the subspace of basis states with even parity, increasing the likelihood the observed state will be a physically admissible state. # # Even if the ansatz parameters are tuned to give a physical state, real devices have noise and imperfect gates, so in practice we may also measure bad states with a small probability. If this syndrome qubit is measured as 1, it means an error has definitely occurred, so we should discard the shot. syn = Qubit("synq", 0) syn_res = Bit("synres", 0) ansatz.add_qubit(syn) ansatz.add_bit(syn_res) for qb in qubits: ansatz.CX(qb, syn) ansatz.Measure(syn, syn_res) # Using this, we can define a filter function which removes the shots which the syndrome qubit detected as erroneous. `BackendResult` objects allow retrieval of shots in any bit order, so we can retrieve the `synres` results separately and use them to filter the shots from the remaining bits. The Backends example notebook describes this in more detail. def filter_shots(backend_result, syn_res_bit): bits = sorted(backend_result.get_bitlist()) bits.remove(syn_res_bit) syn_shots = backend_result.get_shots([syn_res])[:, 0] main_shots = backend_result.get_shots(bits) return main_shots[syn_shots == 0] filtered_rows = shot_table[shot_table[:, syn_res_index] == 0]