def do_sample(self, samples, circuit, noise_model=None, initial_state=0, *args, **kwargs) -> QubitWaveFunction: assert (noise_model is None) state = qulacs.QuantumState(self.n_qubits) lsb = BitStringLSB.from_int(initial_state, nbits=self.n_qubits) state.set_computational_basis( BitString.from_binary(lsb.binary).integer) self.circuit.update_quantum_state(state) if hasattr(self, "measurements"): result = {} for sample in range(samples): sample_result = {} for t, m in self.measurements.items(): m.update_quantum_state(state) sample_result[t] = state.get_classical_value(t) sample_result = dict( sorted(sample_result.items(), key=lambda x: x[0])) binary = BitString.from_array(sample_result.values()) if binary in result: result[binary] += 1 else: result[binary] = 1 return QubitWaveFunction(state=result) else: # sample from the whole wavefunction (all-Z measurement) result = state.sampling(samples) return self.convert_measurements(backend_result=result)
def convert_bitstring(key: typing.Union[BitString, numbers.Integral], n_qubits): if isinstance(key, numbers.Integral): return BitString.from_int(integer=key, nbits=n_qubits) elif isinstance(key, str): return BitString.from_binary(binary=key, nbits=n_qubits) else: return key
def do_sample(self, samples, circuit, noise_model=None, initial_state=0, *args, **kwargs) -> QubitWaveFunction: """ Helper function for performing sampling. Parameters ---------- samples: int: the number of samples to be taken. circuit: the circuit to sample from. noise_model: optional: noise model to be applied to the circuit. initial_state: sampling supports initial states for qulacs. Indicates the initial state to which circuit is applied. args kwargs Returns ------- QubitWaveFunction: the results of sampling, as a Qubit Wave Function. """ state = self.initialize_state(self.n_qubits) lsb = BitStringLSB.from_int(initial_state, nbits=self.n_qubits) state.set_computational_basis( BitString.from_binary(lsb.binary).integer) circuit.update_quantum_state(state) sampled = state.sampling(samples) return self.convert_measurements(backend_result=sampled)
def convert_measurements(self, backend_result) -> QubitWaveFunction: """ Transform backend evaluation results into QubitWaveFunction Parameters ---------- backend_result: the return value of backend simulation. Returns ------- QubitWaveFunction results transformed to tequila native QubitWaveFunction """ result = QubitWaveFunction() # todo there are faster ways for k in backend_result: converted_key = BitString.from_binary( BitStringLSB.from_int(integer=k, nbits=self.n_qubits).binary) if converted_key in result._state: result._state[converted_key] += 1 else: result._state[converted_key] = 1 if hasattr(self, "measurements"): mqubits = self.measurements keymap = KeyMapRegisterToSubregister( subregister=mqubits, register=[i for i in range(self.n_qubits)]) result = result.apply_keymap(keymap=keymap) return result
def do_simulate(self, variables, initial_state, *args, **kwargs): """ Helper function to perform simulation. Parameters ---------- variables: dict: variables to supply to the circuit. initial_state: information indicating the initial state on which the circuit should act. args kwargs Returns ------- QubitWaveFunction: QubitWaveFunction representing result of the simulation. """ state = self.initialize_state(n_qubits=self.n_qubits) lsb = BitStringLSB.from_int(initial_state, nbits=self.n_qubits) state.set_computational_basis( BitString.from_binary(lsb.binary).integer) self.circuit.update_quantum_state(state) wfn = QubitWaveFunction.from_array(arr=state.get_vector(), numbering=self.numbering) return wfn
def from_int(cls, i: int, coeff=1, n_qubits: int = None): if isinstance(i, BitString): return QubitWaveFunction(state={i: coeff}, n_qubits=n_qubits) else: return QubitWaveFunction( state={BitString.from_int(integer=i, nbits=n_qubits): coeff}, n_qubits=n_qubits)
def do_simulate(self, variables, initial_state, *args, **kwargs): state = qulacs.QuantumState(self.n_qubits) lsb = BitStringLSB.from_int(initial_state, nbits=self.n_qubits) state.set_computational_basis(BitString.from_binary(lsb.binary).integer) self.circuit.update_quantum_state(state) wfn = QubitWaveFunction.from_array(arr=state.get_vector(), numbering=self.numbering) return wfn
def convert_measurements(self, backend_result) -> QubitWaveFunction: result = QubitWaveFunction() # todo there are faster ways for k in backend_result: converted_key = BitString.from_binary(BitStringLSB.from_int(integer=k, nbits=self.n_qubits).binary) if converted_key in result._state: result._state[converted_key] += 1 else: result._state[converted_key] = 1 return result
def apply_paulistring(self, paulistring: 'PauliString'): """ Inefficient function which computes action of a single paulistring :param paulistring: PauliString :return: Expectation Value """ result = QubitWaveFunction() for k, v in self.items(): arr = k.array c = v for idx, p in paulistring.items(): if p.lower() == "x": arr[idx] = (arr[idx] + 1) % 2 elif p.lower() == "y": c *= 1.0j * (-1) ** (arr[idx]) arr[idx] = (arr[idx] + 1) % 2 elif p.lower() == "z": c *= (-1) ** (arr[idx]) else: raise TequilaException("unknown pauli: " + str(p)) result[BitString.from_array(array=arr)] = c return paulistring.coeff * result
def from_string(cls, string: str, n_qubits: int = None): """ Complex values like (x+iy)|...> will currently not work, you need to type Real and imaginary separately Or improve this constructor :-) e.g instead of (0.5+1.0j)|0101> do 0.5|0101> + 1.0j|0101> :param paths: :param string: :return: """ try: state = dict() string = string.replace(" ", "") string = string.replace("*", "") string = string.replace("+-", "-") string = string.replace("-+", "-") terms = (string + "terminate").split('>') for term in terms: if term == 'terminate': break tmp = term.split("|") coeff = tmp[0] if coeff == '': coeff = 1.0 else: coeff = complex(coeff) basis_state = BitString.from_binary(binary=tmp[1]) state[basis_state] = coeff except ValueError: raise TequilaException( "Failed to initialize QubitWaveFunction from string:" + string + "\n" "did you try complex values?\n" "currently you need to type real and imaginary parts separately\n" "e.g. instead of (0.5+1.0j)|0101> do 0.5|0101> + 1.0j|0101>") except: raise TequilaException( "Failed to initialize QubitWaveFunction from string:" + string) return QubitWaveFunction(state=state, n_qubits=n_qubits)
def convert_measurements(self, backend_result, target_qubits=None) -> QubitWaveFunction: """ Transform backend evaluation results into QubitWaveFunction Parameters ---------- backend_result: the return value of backend simulation. Returns ------- QubitWaveFunction results transformed to tequila native QubitWaveFunction """ result = QubitWaveFunction() # todo there are faster ways for k in backend_result: converted_key = BitString.from_binary( BitStringLSB.from_int(integer=k, nbits=self.n_qubits).binary) if converted_key in result._state: result._state[converted_key] += 1 else: result._state[converted_key] = 1 if target_qubits is not None: mapped_target = [self.qubit_map[q].number for q in target_qubits] mapped_full = [ self.qubit_map[q].number for q in self.abstract_qubits ] keymap = KeyMapRegisterToSubregister(subregister=mapped_target, register=mapped_full) result = result.apply_keymap(keymap=keymap) return result