def circuit_status(self, handle: ResultHandle) -> CircuitStatus: self._check_handle_type(handle) jobid = handle[0] message = "" measure_permutations = json.loads(handle[1]) # type: ignore if self._MACHINE_DEBUG: n_qubits, n_shots = literal_eval( jobid[len(_DEBUG_HANDLE_PREFIX):]) # type: ignore empty_ar = OutcomeArray.from_ints([0] * n_shots, n_qubits, big_endian=True) self._cache[handle].update( {"result": BackendResult(shots=empty_ar)}) statenum = StatusEnum.COMPLETED else: data = put(self._url, data={ "id": jobid }, headers=self._header).json() status = data["status"] if "ERROR" in data: message = data["ERROR"] statenum = _STATUS_MAP.get(status, StatusEnum.ERROR) if statenum is StatusEnum.COMPLETED: shots = OutcomeArray.from_ints(data["samples"], data["no_qubits"], big_endian=True) shots = shots.choose_indices(measure_permutations) self._cache[handle].update( {"result": BackendResult(shots=shots)}) return CircuitStatus(statenum, message)
def backendresult_to_qiskit_resultdata( res: BackendResult, header: "QobjExperimentHeader", final_map: Optional[Dict[UnitID, UnitID]], ) -> ExperimentResultData: data: Dict[str, Any] = dict() if res.contains_state_results: qbits = ( _gen_uids(header.qreg_sizes, Qubit) if hasattr(header, "qreg_sizes") else [] ) if final_map: qbits = [final_map[q] for q in qbits] stored_res = res.get_result(qbits) if stored_res.state is not None: data["statevector"] = stored_res.state if stored_res.unitary is not None: data["unitary"] = stored_res.unitary if res.contains_measured_results: cbits = ( _gen_uids(header.creg_sizes, Bit) if hasattr(header, "creg_sizes") else [] ) if final_map: cbits = [final_map[c] for c in cbits] stored_res = res.get_result(cbits) if stored_res.shots is not None: data["memory"] = [hex(i) for i in stored_res.shots.to_intlist()] data["counts"] = dict(Counter(data["memory"])) elif stored_res.counts is not None: data["counts"] = { hex(i.to_intlist()[0]): f for i, f in stored_res.counts.items() } return ExperimentResultData(**data)
def circuit_status(self, handle: ResultHandle) -> CircuitStatus: self._check_handle_type(handle) jobid = str(handle[0]) n_shots = cast(int, handle[1]) if self._MACHINE_DEBUG: n_qubits: int = literal_eval(jobid[len(_DEBUG_HANDLE_PREFIX):]) zero_counts: Counter = Counter() zero_array = OutcomeArray.from_ints( ints=[0], width=n_qubits, big_endian=False, ) zero_counts[zero_array] = n_shots if handle in self._cache: self._cache[handle].update( {"result": BackendResult(counts=zero_counts)}) else: self._cache[handle] = { "result": BackendResult(counts=zero_counts) } statenum = StatusEnum.COMPLETED else: measure_permutations = json.loads(str(handle[2])) url = self._url + str(jobid) resp = get(url, headers=self._header).json() status = resp["status"] statenum = _STATUS_MAP.get(status) # type: ignore if statenum is StatusEnum.COMPLETED: ionq_counts = resp["data"]["histogram"] tket_counts: Counter = Counter() # reverse engineer counts. Imprecise, due to rounding. max_counts = 0 max_array = None for outcome_key, prob in ionq_counts.items(): array = OutcomeArray.from_ints( ints=[int(outcome_key)], width=int(resp["qubits"]), big_endian=False, ) array = array.choose_indices(measure_permutations) array_counts = round(n_shots * float(prob)) tket_counts[array] = array_counts if array_counts > max_counts: max_counts = array_counts max_array = array # account for rounding error sum_counts = sum(tket_counts.values()) diff = n_shots - sum_counts tket_counts[max_array] += diff if handle in self._cache: self._cache[handle].update( {"result": BackendResult(counts=tket_counts)}) else: self._cache[handle] = { "result": BackendResult(counts=tket_counts) } return CircuitStatus(statenum)
def process_circuits( self, circuits: Iterable[Circuit], n_shots: Optional[int] = None, valid_check: bool = True, **kwargs: KwargTypes, ) -> List[ResultHandle]: circuit_list = list(circuits) if valid_check: self._check_all_circuits(circuit_list, nomeasure_warn=(n_shots is not None)) handle_list = [] for circuit in circuit_list: qulacs_state = self._sim(circuit.n_qubits) qulacs_state.set_zero_state() qulacs_circ = tk_to_qulacs(circuit) qulacs_circ.update_quantum_state(qulacs_state) state = qulacs_state.get_vector() qubits = sorted(circuit.qubits, reverse=True) shots = None bits = None if n_shots: bits2index = list((com.bits[0], qubits.index(com.qubits[0])) for com in circuit if com.op.type == OpType.Measure) if len(bits2index) == 0: bits = circuit.bits shots = OutcomeArray.from_ints([0] * n_shots, len(bits)) else: bits, choose_indices = zip(*bits2index) samples = qulacs_state.sampling(n_shots) shots = OutcomeArray.from_ints(samples, circuit.n_qubits) shots = shots.choose_indices(choose_indices) try: phase = float(circuit.phase) coeff = np.exp(phase * np.pi * 1j) state *= coeff except TypeError: warning( "Global phase is dependent on a symbolic parameter, so cannot " "adjust for phase") implicit_perm = circuit.implicit_qubit_permutation() qubits = [implicit_perm[qb] for qb in qubits] handle = ResultHandle(str(uuid4())) self._cache[handle] = { "result": BackendResult(state=state, shots=shots, c_bits=bits, q_bits=qubits) } handle_list.append(handle) del qulacs_state del qulacs_circ return handle_list
def process_circuits( self, circuits: Iterable[Circuit], n_shots: Optional[int] = None, valid_check: bool = True, **kwargs: KwargTypes, ) -> List[ResultHandle]: """ Submit circuits to the backend for running. The results will be stored in the backend's result cache to be retrieved by the corresponding get_<data> method. Use keyword arguments to specify parameters to be used in submitting circuits See specific Backend derived class for available parameters, from the following list: * `seed`: RNG seed for simulators :param circuits: Circuits to process on the backend. :type circuits: Iterable[Circuit] :param n_shots: Number of shots to run per circuit. None is to be used for state/unitary simulators. Defaults to None. :type n_shots: Optional[int], optional :param valid_check: Explicitly check that all circuits satisfy all required predicates to run on the backend. Defaults to True :type valid_check: bool, optional :return: Handles to results for each input circuit, as an interable in the same order as the circuits. :rtype: List[ResultHandle] """ circuit_list = list(circuits) if valid_check: self._check_all_circuits(circuit_list) handle_list = [] for circuit in circuit_list: handle = ResultHandle(str(uuid4())) mycirc, measure_map = tk_to_mymeasures(circuit) qubit_list, bit_list = zip(*measure_map.items()) qubit_shots = sample_mycircuit(mycirc, set(qubit_list), n_shots, kwargs.get("seed")) # Pad shot table with 0 columns for unused bits all_shots = np.zeros((n_shots, len(circuit.bits)), dtype=int) all_shots[:, :len(qubit_list)] = qubit_shots res_bits = [ measure_map[q] for q in sorted(qubit_list, reverse=True) ] for b in circuit.bits: if b not in bit_list: res_bits.append(b) res = BackendResult(c_bits=res_bits, shots=OutcomeArray.from_readouts(all_shots)) self._cache[handle] = {"result": res} handle_list.append(handle) return handle_list
def package_results( self, circuit: CirqCircuit, q_bits: Sequence[Qubit] ) -> List[BackendResult]: moments = self._simulator.simulate_moment_steps(circuit) all_backres = [ BackendResult(density_matrix=run.density_matrix(copy=True), q_bits=q_bits) for run in moments ] return all_backres
def _get_result(completed_task: Union[AwsQuantumTask, LocalQuantumTask], want_state: bool) -> Dict[str, BackendResult]: result = completed_task.result() kwargs = {} if want_state: kwargs["state"] = result.get_value_by_result_type( ResultType.StateVector()) else: kwargs["shots"] = OutcomeArray.from_readouts(result.measurements) return {"result": BackendResult(**kwargs)}
def package_result(self, circuit: CirqCircuit, q_bits: Sequence[Qubit]) -> BackendResult: run = cast( StateVectorTrialResult, self._simulator.simulate( circuit, qubit_order=ops.QubitOrder.as_qubit_order( ops.QubitOrder.DEFAULT).order_for(circuit.all_qubits()), ), ) return BackendResult(state=run.final_state_vector, q_bits=q_bits)
def package_results( self, circuit: CirqCircuit, q_bits: Sequence[Qubit] ) -> List[BackendResult]: moments = self._simulator.simulate_moment_steps( circuit, qubit_order=ops.QubitOrder.as_qubit_order(ops.QubitOrder.DEFAULT).order_for( circuit.all_qubits() ), ) all_backres = [ BackendResult(state=run.state.state_vector(), q_bits=q_bits) for run in moments ] return all_backres
def process_circuits( self, circuits: Iterable[Circuit], n_shots: Optional[int] = None, valid_check: bool = True, **kwargs: KwargTypes, ) -> List[ResultHandle]: """ See :py:meth:`pytket.backends.Backend.process_circuits`. Supported kwargs: `seed`. """ circuit_list = list(circuits) if valid_check: self._check_all_circuits(circuit_list) handle_list = [] for circuit in circuit_list: sim = Simulator(rnd_seed=kwargs.get("seed")) fwd = ForwarderEngine(sim) eng = MainEngine(backend=sim, engine_list=[fwd]) qureg = eng.allocate_qureg(circuit.n_qubits) tk_to_projectq(eng, qureg, circuit, True) eng.flush() state = np.array( eng.backend.cheat()[1], dtype=complex ) # `cheat()` returns tuple:(a dictionary of qubit indices, statevector) handle = ResultHandle(str(uuid4())) 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() # reverse qubits as projectq state is dlo res_qubits = [ implicit_perm[qb] for qb in sorted(circuit.qubits, reverse=True) ] measures = circuit.n_gates_of_type(OpType.Measure) if measures == 0 and n_shots is not None: backres = self.empty_result(circuit, n_shots=n_shots) else: backres = BackendResult(q_bits=res_qubits, state=state) self._cache[handle] = {"result": backres} handle_list.append(handle) return handle_list
def process_circuits( self, circuits: Iterable[Circuit], n_shots: Optional[int] = None, valid_check: bool = True, **kwargs: KwargTypes, ) -> List[ResultHandle]: """ Submit circuits to the backend for running. The results will be stored in the backend's result cache to be retrieved by the corresponding get_<data> method. Use keyword arguments to specify parameters to be used in submitting circuits See specific Backend derived class for available parameters, from the following list: * `seed`: RNG seed for simulators :param circuits: Circuits to process on the backend. :type circuits: Iterable[Circuit] :param n_shots: Number of shots to run per circuit. None is to be used for state/unitary simulators. Defaults to None. :type n_shots: Optional[int], optional :param valid_check: Explicitly check that all circuits satisfy all required predicates to run on the backend. Defaults to True :type valid_check: bool, optional :return: Handles to results for each input circuit, as an interable in the same order as the circuits. :rtype: List[ResultHandle] """ circuit_list = list(circuits) if valid_check: self._check_all_circuits(circuit_list) handle_list = [] for circuit in circuit_list: handle = ResultHandle(str(uuid4())) mycirc = tk_to_mycircuit(circuit) state = run_mycircuit(mycirc) state *= np.exp(1j * np.pi * circuit.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 qiskit_result_to_backendresult(res: Result) -> Iterator[BackendResult]: for result in res.results: header = result.header width = header.memory_slots c_bits = ( _gen_uids(header.creg_sizes, Bit) if hasattr(header, "creg_sizes") else None ) q_bits = ( _gen_uids(header.qreg_sizes, Qubit) if hasattr(header, "qreg_sizes") else None ) shots, counts, state, unitary = (None,) * 4 datadict = result.data.to_dict() if len(datadict) == 0 and result.shots > 0: n_bits = len(c_bits) if c_bits else 0 shots = OutcomeArray.from_readouts( np.zeros((result.shots, n_bits), dtype=np.uint8) # type: ignore ) else: if "memory" in datadict: memory = datadict["memory"] shots = _hex_to_outar(memory, width) elif "counts" in datadict: qis_counts = datadict["counts"] counts = Counter( dict( (_hex_to_outar([hexst], width), count) for hexst, count in qis_counts.items() ) ) if "statevector" in datadict: state = datadict["statevector"] if "unitary" in datadict: unitary = datadict["unitary"] yield BackendResult( c_bits=c_bits, q_bits=q_bits, shots=shots, counts=counts, state=state, unitary=unitary, )
def _convert_result(resultdict: Dict[str, List[str]]) -> BackendResult: array_dict = { creg: np.array([list(a) for a in reslist]).astype(np.uint8) for creg, reslist in resultdict.items() } reversed_creg_names = sorted(array_dict.keys(), reverse=True) c_bits = [ Bit(name, ind) for name in reversed_creg_names for ind in range(array_dict[name].shape[-1] - 1, -1, -1) ] stacked_array = np.hstack( [array_dict[name] for name in reversed_creg_names]) return BackendResult( c_bits=c_bits, shots=OutcomeArray.from_readouts( cast(Sequence[Sequence[int]], stacked_array)), )
def get_result(self, handle: ResultHandle, **kwargs: KwargTypes) -> BackendResult: """ See :py:meth:`pytket.backends.Backend.get_result`. Supported kwargs: none. """ try: return super().get_result(handle) except CircuitNotRunError: if handle not in self._cache: raise CircuitNotRunError(handle) qam = self._cache[handle]["qam"] shots = qam.wait().read_memory(region_name="ro") shots = OutcomeArray.from_readouts(shots) res = BackendResult(shots=shots, c_bits=self._cache[handle]["c_bits"]) self._cache[handle].update({"result": res}) return res
def run_circuit(self, circuit: Circuit, **kwargs: KwargTypes) -> BackendResult: cirq_circ = tk_to_cirq(circuit) bit_to_qubit_map = {b: q for q, b in circuit.qubit_to_bit_map.items()} if not cirq_circ.has_measurements(): # type: ignore n_shots = cast(int, kwargs.get("n_shots")) return self.empty_result(circuit, n_shots=n_shots) else: run = self._simulator.run(cirq_circ, repetitions=cast(int, kwargs.get("n_shots"))) run_dict = run.data.to_dict() c_bits = [ bit for key in run_dict.keys() for bit in bit_to_qubit_map.keys() if str(bit) == key ] individual_readouts = [ list(readout.values()) for readout in run_dict.values() ] shots = OutcomeArray.from_readouts( [list(r) for r in zip(*individual_readouts)]) return BackendResult(shots=shots, c_bits=c_bits)
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 package_result( self, circuit: CirqCircuit, q_bits: Sequence[Qubit] ) -> BackendResult: run = cast(DensityMatrixTrialResult, self._simulator.simulate(circuit)) return BackendResult(density_matrix=run.final_density_matrix, q_bits=q_bits)