def test_expectation(client_configuration: QCSClientConfiguration): wfnsim = WavefunctionSimulator(client_configuration=client_configuration) bell = Program(H(0), CNOT(0, 1)) expects = wfnsim.expectation(bell, [sZ(0) * sZ(1), sZ(0), sZ(1), sX(0) * sX(1)]) assert expects.size == 4 np.testing.assert_allclose(expects, [1, 0, 0, 1]) pauli_sum = PauliSum([sZ(0) * sZ(1)]) expects = wfnsim.expectation(bell, pauli_sum) assert expects.size == 1 np.testing.assert_allclose(expects, [1])
def test_expectation(forest: ForestConnection): # The forest fixture (argument) to this test is to ensure this is # skipped when a forest web api key is unavailable. You could also # pass it to the constructor of WavefunctionSimulator() but it is not # necessary. wfnsim = WavefunctionSimulator() bell = Program(H(0), CNOT(0, 1)) expects = wfnsim.expectation(bell, [sZ(0) * sZ(1), sZ(0), sZ(1), sX(0) * sX(1)]) assert expects.size == 4 np.testing.assert_allclose(expects, [1, 0, 0, 1]) pauli_sum = PauliSum([sZ(0) * sZ(1)]) expects = wfnsim.expectation(bell, pauli_sum) assert expects.size == 1 np.testing.assert_allclose(expects, [1])
def test_measure_observables_many_progs(forest): expts = [ ExperimentSetting(sI(), o1 * o2) for o1, o2 in itertools.product([sI(0), sX(0), sY(0), sZ(0)], [sI(1), sX(1), sY(1), sZ(1)]) ] qc = get_qc('2q-qvm') qc.qam.random_seed = 51 for prog in _random_2q_programs(): suite = TomographyExperiment(expts, program=prog, qubits=[0, 1]) assert len(suite) == 4 * 4 gsuite = group_experiments(suite) assert len( gsuite ) == 3 * 3 # can get all the terms with I for free in this case wfn = WavefunctionSimulator() wfn_exps = {} for expt in expts: wfn_exps[expt] = wfn.expectation(gsuite.program, PauliSum([expt.out_operator])) for res in measure_observables(qc, gsuite, n_shots=1_000): np.testing.assert_allclose(wfn_exps[res.setting], res.expectation, atol=0.1)
def test_penalties(): sim = WavefunctionSimulator() pq = prepare_qubits(1) initial_wf = sim.wavefunction(pq) print("Initial WF is {}".format(initial_wf)) #000 Test expectation = sim.expectation(pq, prepare_cost()) print("Expectation value is {}".format(expectation))
def test_expectation_vs_lisp_qvm(qvm, n_qubits): for _ in range(20): prog = _generate_random_program(n_qubits=n_qubits, length=10) operator = _generate_random_pauli(n_qubits=n_qubits, n_terms=5) lisp_wf = WavefunctionSimulator() lisp_exp = lisp_wf.expectation(prep_prog=prog, pauli_terms=operator) ref_wf = ReferenceWavefunctionSimulator(n_qubits=n_qubits).do_program(prog) ref_exp = ref_wf.expectation(operator=operator) np.testing.assert_allclose(lisp_exp, ref_exp, atol=1e-15)
class ForestStateBackend(Backend): def __init__(self): """Backend for running simulations on the Rigetti QVM Wavefunction Simulator. """ self._sim = WavefunctionSimulator() def get_state(self, circuit, fit_to_constraints=True): """Calculate the statevector for a circuit. :param circuit: circuit to calculate :return: complex numpy array of statevector """ c = circuit.copy() if fit_to_constraints: Transform.RebaseToQuil().apply(c) p = tk_to_pyquil(c) wf = self._sim.wavefunction(p) return wf.amplitudes def run(self, circuit, shots, fit_to_constraints=True): pass def get_pauli_expectation_value(self, state_circuit, pauli, shots=1000): c = state_circuit.copy() Transform.RebaseToQuil().apply(c) prog = tk_to_pyquil(c) pauli_term = _gen_PauliTerm(pauli) return self._sim.expectation(prog, [pauli_term]) def get_operator_expectation_value(self, state_circuit, operator, shots=1000): c = state_circuit.copy() Transform.RebaseToQuil().apply(c) prog = tk_to_pyquil(c) pauli_sum = PauliSum([ _gen_PauliTerm(term, coeff) for term, coeff in operator.terms.items() ]) return self._sim.expectation(prog, pauli_sum)
def test_z_gates(errors): # pq = prepare_qubits(0) # Z = np.array([[1,0],[0,-1]]) # Z1Z2Z3 = np.kron(Z, np.kron(Z,Z)) # first_penalty = 0.5 * (np.eye(8) + Z1Z2Z3) # helper_op = 0.5 * (np.eye(2) - Z) # penalty_111 = np.kron(helper_op, np.kron(helper_op, helper_op)) # final_penalty = first_penalty # penalty_dfn = DefGate("PENALTY", final_penalty) # PENALTY = penalty_dfn.get_constructor() sim = WavefunctionSimulator() pq = prepare_qubits(errors) initial_wf = sim.wavefunction(pq) print("Initial is {}".format(initial_wf)) #ps = (sI(0) - sZ(0))*(sI(1) - sZ(1))*(sI(2) - sZ(2)) ps = sI(0) + (sZ(0) * sZ(1) * sZ(2)) expectation = sim.expectation(pq, ps) print("Expectation value for {} errors is {}".format(errors, expectation))
theta_8 = 2 * np.pi * np.random.random() theta_9 = 2 * np.pi * np.random.random() theta_10 = 2 * np.pi * np.random.random() theta_11 = 2 * np.pi * np.random.random() theta_12 = 2 * np.pi * np.random.random() theta_13 = 2 * np.pi * np.random.random() theta_14 = 2 * np.pi * np.random.random() params = np.array([ theta_0, theta_1, theta_2, theta_3, theta_4, theta_5, theta_6, theta_7, theta_8, theta_9, theta_10, theta_11, theta_12, theta_13, theta_14 ]) # compute exact expactation value true[i] = float( np.real(wv_sim.expectation(prep_prog=ansatz(params), pauli_terms=zz))) # calibration for 0 state cal0 = run_and_measure_wrapped(device=QPU, prog_in=calibration_ansatz(0), trials=calibration_trials).T # cal0 is dictionary of qubit measurements # cal0[q] is list of outputs of qubit q # number of ones in cal0[q] is sum(cal0[q]) # number of zeros is cal0[q] is len(cal0[q]) - sum(cal0[q]) # pq0 is number ones / len(cal0[q]) p00[i] = float(sum(cal0[0])) / len(cal0[0]) p10[i] = float(sum(cal0[1])) / len(cal0[1]) # calibration for 1 state cal1 = run_and_measure_wrapped(device=QPU,
prog_out += RZ(params[8], 1) prog_out += CNOT(0,1) prog_out += RZ(params[9], 0) prog_out += RX(params[10], 0) prog_out += RZ(params[11], 0) prog_out += RZ(params[12], 1) prog_out += RX(params[13], 1) prog_out += RZ(params[14], 1) return prog_out true=float(np.real(wv_sim.expectation(prep_prog=ansatz(params), pauli_terms=[operator]))) true=np.zeros((shots,1)) estimate=np.zeros((shots,1)) not_mitigated=np.zeros((shots,1)) for i in tqdm.tqdm(range(N)): params={0: 2*np.pi*np.random.random(), 1: 2*np.pi*np.random.random(), 2: 2*np.pi*np.random.random(), 3: 2*np.pi*np.random.random(), 4: 2*np.pi*np.random.random(), 5: 2*np.pi*np.random.random(), 6: 2*np.pi*np.random.random(), 7: 2*np.pi*np.random.random(),
class ForestStateBackend(Backend): _supports_state = True _supports_expectation = True _persistent_handles = False def __init__(self) -> None: """Backend for running simulations on the Rigetti QVM Wavefunction Simulator.""" super().__init__() self._sim = WavefunctionSimulator() @property def required_predicates(self) -> List[Predicate]: return [ NoClassicalControlPredicate(), NoFastFeedforwardPredicate(), NoMidMeasurePredicate(), NoSymbolsPredicate(), GateSetPredicate({ OpType.X, OpType.Y, OpType.Z, OpType.H, OpType.S, OpType.T, OpType.Rx, OpType.Ry, OpType.Rz, OpType.CZ, OpType.CX, OpType.CCX, OpType.CU1, OpType.U1, OpType.SWAP, }), DefaultRegisterPredicate(), ] def default_compilation_pass(self, optimisation_level: int = 1) -> BasePass: assert optimisation_level in range(3) passlist = [DecomposeBoxes(), FlattenRegisters()] if optimisation_level == 1: passlist.append(SynthesiseIBM()) elif optimisation_level == 2: passlist.append(FullPeepholeOptimise()) passlist.append(RebaseQuil()) if optimisation_level > 0: passlist.append(EulerAngleReduction(OpType.Rx, OpType.Rz)) return SequencePass(passlist) @property def _result_id_type(self) -> _ResultIdTuple: return (int, ) def process_circuits( self, circuits: Iterable[Circuit], n_shots: Optional[int] = None, valid_check: bool = True, **kwargs: KwargTypes, ) -> List[ResultHandle]: handle_list = [] if valid_check: self._check_all_circuits(circuits) for circuit in circuits: p = tk_to_pyquil(circuit) for qb in circuit.qubits: # Qubits with no gates will not be included in the Program # Add identities to ensure all qubits are present and dimension # is as expected p += I(Qubit_(qb.index[0])) handle = ResultHandle(uuid4().int) state = np.array(self._sim.wavefunction(p).amplitudes) try: phase = float(circuit.phase) coeff = np.exp(phase * np.pi * 1j) state *= coeff except ValueError: warning( "Global phase is dependent on a symbolic parameter, so cannot " "adjust for phase") implicit_perm = circuit.implicit_qubit_permutation() res_qubits = [ implicit_perm[qb] for qb in sorted(circuit.qubits, reverse=True) ] res = BackendResult(q_bits=res_qubits, state=state) self._cache[handle] = {"result": res} handle_list.append(handle) return handle_list def circuit_status(self, handle: ResultHandle) -> CircuitStatus: if handle in self._cache: return CircuitStatus(StatusEnum.COMPLETED) raise CircuitNotRunError(handle) @property def device(self) -> Optional[Device]: return None def _gen_PauliTerm(self, term: QubitPauliString, coeff: complex = 1.0) -> PauliTerm: pauli_term = ID() * coeff for q, p in term.to_dict().items(): pauli_term *= PauliTerm(p.name, _default_q_index(q)) return pauli_term # type: ignore def get_pauli_expectation_value(self, state_circuit: Circuit, pauli: QubitPauliString) -> complex: """Calculates the expectation value of the given circuit using the built-in QVM functionality :param state_circuit: Circuit that generates the desired state :math:`\\left|\\psi\\right>`. :type state_circuit: Circuit :param pauli: Pauli operator :type pauli: QubitPauliString :return: :math:`\\left<\\psi | P | \\psi \\right>` :rtype: complex """ prog = tk_to_pyquil(state_circuit) pauli_term = self._gen_PauliTerm(pauli) return complex(self._sim.expectation(prog, [pauli_term])) def get_operator_expectation_value( self, state_circuit: Circuit, operator: QubitPauliOperator) -> complex: """Calculates the expectation value of the given circuit with respect to the operator using the built-in QVM functionality :param state_circuit: Circuit that generates the desired state :math:`\\left|\\psi\\right>`. :type state_circuit: Circuit :param operator: Operator :math:`H`. :type operator: QubitPauliOperator :return: :math:`\\left<\\psi | H | \\psi \\right>` :rtype: complex """ prog = tk_to_pyquil(state_circuit) pauli_sum = PauliSum([ self._gen_PauliTerm(term, coeff) for term, coeff in operator._dict.items() ]) return complex(self._sim.expectation(prog, pauli_sum))