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 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 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 _convert_result(output: Dict[str, float], n_shots: int) -> BackendResult: counts = Counter({ OutcomeArray.from_readouts([json.loads(state)]): int(prob * n_shots) for state, prob in output.items() }) return BackendResult(counts=counts)
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 _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 _calculate_results(self, qscall: "QSharpCallable", n_shots: Optional[int] = None) -> BackendResult: if n_shots: shots_ar = np.array([qscall.simulate() for _ in range(n_shots)], dtype=np.uint8) shots = OutcomeArray.from_readouts(shots_ar) # type: ignore # ^ type ignore as array is ok for Sequence[Sequence[int]] # outputs should correspond to default register, # as mapped by FlattenRegisters() return BackendResult(shots=shots) raise ValueError("Parameter n_shots is required for this backend")
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 circuit_status(self, handle: ResultHandle) -> CircuitStatus: self._check_handle_type(handle) jobid = cast(str, handle[0]) message = "" n_shots = cast(int, handle[1]) if self._MACHINE_DEBUG: n_bits = literal_eval(jobid[len(_DEBUG_HANDLE_PREFIX) :]) empty_ar = OutcomeArray.from_ints([0] * n_shots, n_bits, big_endian=True) self._cache[handle].update({"result": BackendResult(shots=empty_ar)}) statenum = StatusEnum.COMPLETED else: job = qsharp.azure.status(jobid) status = job.status.lower() statenum = _STATUS_MAP.get(status, StatusEnum.ERROR) message = repr(job) if statenum is StatusEnum.COMPLETED: output = qsharp.azure.output(jobid) self._cache[handle].update({"result": _convert_result(output, n_shots)}) return CircuitStatus(statenum, message)
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 _hex_to_outar(hexes: Sequence[str], width: int) -> OutcomeArray: ints = [int(hexst, 16) for hexst in hexes] return OutcomeArray.from_ints(ints, width)