def _init_from_bool(self, z, x): """Construct pauli from boolean array. Args: z (numpy.ndarray): boolean, z vector x (numpy.ndarray): boolean, x vector Returns: Pauli: self Raises: QISKitError: if z or x are None or the length of z and x are different. """ if z is None: raise QISKitError("z vector must not be None.") if x is None: raise QISKitError("x vector must not be None.") if len(z) != len(x): raise QISKitError("length of z and x vectors must be " "the same. (z: {} vs x: {})".format( len(z), len(x))) z = _make_np_bool(z) x = _make_np_bool(x) self._z = z self._x = x return self
def __iadd__(self, other): """Append a Result object to current Result object. Arg: other (Result): a Result object to append. Returns: Result: The current object with appended results. Raises: QISKitError: if the Results cannot be combined. """ warnings.warn( 'Result addition is deprecated and will be removed in ' 'version 0.7+.', DeprecationWarning) this_backend = self.backend_name other_backend = other.backend_name if this_backend != other_backend: raise QISKitError( 'Result objects from different backends cannot be combined.') if not self.success or not other.success: raise QISKitError( 'Can not combine a failed result with another result.') self.results.extend(other.results) return self
def measure(self, qubit, cbit): """Measure quantum bit into classical bit (tuples). Args: qubit (QuantumRegister|tuple): quantum register cbit (ClassicalRegister|tuple): classical register Returns: qiskit.Instruction: the attached measure instruction. Raises: QISKitError: if qubit is not in this circuit or bad format; if cbit is not in this circuit or not creg. """ if isinstance(qubit, QuantumRegister) and isinstance(cbit, ClassicalRegister) \ and len(qubit) == len(cbit): instructions = InstructionSet() for i in range(qubit.size): instructions.add(self.measure((qubit, i), (cbit, i))) return instructions elif isinstance(qubit, QuantumRegister) and isinstance( cbit, ClassicalRegister) and len(qubit) != len(cbit): raise QISKitError( "qubit (%s) and cbit (%s) should have the same length" % (len(qubit), len(cbit))) elif not (isinstance(qubit, tuple) and isinstance(cbit, tuple)): raise QISKitError( "Both qubit <%s> and cbit <%s> should be Registers or formated as tuples. " "Hint: You can use subscript eg. cbit[0] to convert it into tuple." % (type(qubit).__name__, type(cbit).__name__)) self._check_qubit(qubit) self._check_creg(cbit[0]) cbit[0].check_range(cbit[1]) return self._attach(Measure(qubit, cbit, self))
def __init__(self, param, arg, circ=None): """Create new initialize composite gate.""" num_qubits = math.log2(len(param)) # Check if param is a power of 2 if num_qubits == 0 or not num_qubits.is_integer(): raise QISKitError("Desired vector not a positive power of 2.") self.num_qubits = int(num_qubits) # Check if number of desired qubits agrees with available qubits if len(arg) != self.num_qubits: raise QISKitError("Number of complex amplitudes do not correspond " "to the number of qubits.") # Check if probabilities (amplitudes squared) sum to 1 if not math.isclose(sum(numpy.absolute(param) ** 2), 1.0, abs_tol=_EPS): raise QISKitError("Sum of amplitudes-squared does not equal one.") super().__init__("init", param, arg, circ) # call to generate the circuit that takes the desired vector to zero self.gates_to_uncompute() # remove zero rotations and double cnots self.optimize_gates() # invert the circuit to create the desired vector from zero (assuming # the qubits are in the zero state) self.inverse()
def _get_experiment(self, key=None): """Return an experiment from a given key. Args: key (str or QuantumCircuit or None): reference to a quantum circuit If None and there is only one circuit available, returns that one. Returns: ExperimentResult: an Experiment. Raises: QISKitError: if there is no data for the circuit, or an unhandled error occurred while fetching the data. """ if self._is_error(): raise QISKitError(str(self.status)) if isinstance(key, QuantumCircuit): key = key.name elif key is None: if len(self.results) != 1: raise QISKitError( "You have to select a circuit when there is more than " "one available") else: key = list(self.results.keys())[0] key = str(key) return self.results[key]
def _wait_for_job(job_id, api, wait=5, timeout=60): """Wait until all online ran circuits of a qobj are 'COMPLETED'. Args: job_id (list(str)): is a list of id strings. api (IBMQuantumExperience.IBMQuantumExperience.IBMQuantumExperience): IBMQuantumExperience API connection wait (int): is the time to wait between requests, in seconds timeout (int): is how long we wait before failing, in seconds Returns: dict: A list of results that correspond to the jobids. Raises: QISKitError: job didn't return status or reported error in status """ timer = 0 job_result = api.get_job(job_id) if 'status' not in job_result: raise QISKitError("get_job didn't return status: %s" % (pprint.pformat(job_result))) while job_result['status'] == 'RUNNING': if timer >= timeout: return { 'job_id': job_id, 'status': 'ERROR', 'result': 'QISkit Time Out' } time.sleep(wait) timer += wait logger.info('status = %s (%d seconds)', job_result['status'], timer) job_result = api.get_job(job_id) if 'status' not in job_result: raise QISKitError("get_job didn't return status: %s" % (pprint.pformat(job_result))) if (job_result['status'] == 'ERROR_CREATING_JOB' or job_result['status'] == 'ERROR_RUNNING_JOB'): return { 'job_id': job_id, 'status': 'ERROR', 'result': job_result['status'] } # Get the results job_result_return = [] for index in range(len(job_result['qasms'])): job_result_return.append({ 'data': job_result['qasms'][index]['data'], 'status': job_result['qasms'][index]['status'] }) return { 'job_id': job_id, 'status': job_result['status'], 'result': job_result_return }
def register(*args, provider_class=IBMQProvider, **kwargs): """ Authenticate against an online backend provider. This is a factory method that returns the provider that gets registered. Note that if no parameters are passed, this method will try to automatically discover the credentials for IBMQ in the following places, in order:: 1. in the `Qconfig.py` file in the current working directory. 2. in the environment variables. 3. in the `qiskitrc` configuration file. Args: args (tuple): positional arguments passed to provider class initialization provider_class (BaseProvider): provider class kwargs (dict): keyword arguments passed to provider class initialization. For the IBMQProvider default this can include things such as: * token (str): The token used to register on the online backend such as the quantum experience. * url (str): The url used for online backend such as the quantum experience. * hub (str): The hub used for online backend. * group (str): The group used for online backend. * project (str): The project used for online backend. * proxies (dict): Proxy configuration for the API, as a dict with 'urls' and credential keys. * verify (bool): If False, ignores SSL certificates errors. Returns: BaseProvider: the provider instance that was just registered. Raises: QISKitError: if the provider could not be registered (e.g. due to conflict, or if no credentials were provided.) """ # Try to autodiscover credentials if not passed. if not args and not kwargs and provider_class == IBMQProvider: kwargs = credentials.discover_credentials().get( credentials.get_account_name(IBMQProvider)) or {} if not kwargs: raise QISKitError( 'No IBMQ credentials found. Please pass them explicitly or ' 'store them before calling register() with store_credentials()' ) try: provider = provider_class(*args, **kwargs) except Exception as ex: raise QISKitError( "Couldn't instantiate provider! Error: {0}".format(ex)) _DEFAULT_PROVIDER.add_provider(provider) return provider
def _wait_for_job(jobid, api, wait=5, timeout=60, silent=True): """Wait until all online ran jobs are 'COMPLETED'. Args: jobid: is a list of id strings. api (IBMQuantumExperience): IBMQuantumExperience API connection wait (int): is the time to wait between requests, in seconds timeout (int): is how long we wait before failing, in seconds silent (bool): is an option to print out the running information or not Returns: A list of results that correspond to the jobids. Raises: QISKitError: """ timer = 0 timeout_over = False job_result = api.get_job(jobid) if 'status' not in job_result: from pprint import pformat raise QISKitError("get_job didn't return status: %s" % (pformat(job_result))) while job_result['status'] == 'RUNNING': if timer >= timeout: return {'status': 'ERROR', 'result': 'Time Out'} time.sleep(wait) timer += wait if not silent: print('status = %s (%d seconds)' % (job_result['status'], timer)) job_result = api.get_job(jobid) if 'status' not in job_result: from pprint import pformat raise QISKitError("get_job didn't return status: %s" % (pformat(job_result))) if job_result['status'] == 'ERROR_CREATING_JOB' or job_result[ 'status'] == 'ERROR_RUNNING_JOB': return {'status': 'ERROR', 'result': job_result['status']} # Get the results job_result_return = [] for index in range(len(job_result['qasms'])): job_result_return.append({ 'data': job_result['qasms'][index]['data'], 'status': job_result['qasms'][index]['status'] }) return {'status': job_result['status'], 'result': job_result_return}
def from_label(cls, label): r"""Take pauli string to construct pauli. The qubit index of pauli label is q_{n-1} ... q_0. E.g., a pauli is $P_{n-1} \otimes ... \otimes P_0$ Args: label (str): pauli label Returns: Pauli: the constructed pauli Raises: QISKitError: invalid character in the label """ z = np.zeros(len(label), dtype=np.bool) x = np.zeros(len(label), dtype=np.bool) for i, char in enumerate(label): if char == 'X': x[-i - 1] = True elif char == 'Z': z[-i - 1] = True elif char == 'Y': z[-i - 1] = True x[-i - 1] = True elif char != 'I': raise QISKitError( "Pauli string must be only consisted of 'I', 'X', " "'Y' or 'Z' but you have {}.".format(char)) return cls(z=z, x=x)
def update_x(self, x, indices=None): """ Update partial or entire x. Args: x (numpy.ndarray or list): to-be-updated x indices (numpy.ndarray or list or optional): to-be-updated qubit indices Returns: Pauli: self Raises: QISKitError: when updating whole x, the number of qubits must be the same. """ x = _make_np_bool(x) if indices is None: if len(self._x) != len(x): raise QISKitError( "During updating whole x, you can not change " "the number of qubits.") self._x = x else: if not isinstance(indices, list) and not isinstance( indices, np.ndarray): indices = [indices] for p, idx in enumerate(indices): self._x[idx] = x[p] return self
def update_z(self, z, indices=None): """ Update partial or entire z. Args: z (numpy.ndarray or list): to-be-updated z indices (numpy.ndarray or list or optional): to-be-updated qubit indices Returns: Pauli: self Raises: QISKitError: when updating whole z, the number of qubits must be the same. """ z = _make_np_bool(z) if indices is None: if len(self._z) != len(z): raise QISKitError("During updating whole z, you can not " "change the number of qubits.") self._z = z else: if not isinstance(indices, list) and not isinstance( indices, np.ndarray): indices = [indices] for p, idx in enumerate(indices): self._z[idx] = z[p] return self
def register(*args, provider_class=IBMQProvider, **kwargs): """ Authenticate against an online backend provider. This is a factory method that returns the provider that gets registered. Args: args (tuple): positional arguments passed to provider class initialization provider_class (BaseProvider): provider class kwargs (dict): keyword arguments passed to provider class initialization. For the IBMQProvider default this can include things such as; token (str): The token used to register on the online backend such as the quantum experience. url (str): The url used for online backend such as the quantum experience. hub (str): The hub used for online backend. group (str): The group used for online backend. project (str): The project used for online backend. proxies (dict): Proxy configuration for the API, as a dict with 'urls' and credential keys. verify (bool): If False, ignores SSL certificates errors. Returns: BaseProvider: the provider instance that was just registered. Raises: QISKitError: if the provider could not be registered (e.g. due to conflict) """ try: provider = provider_class(*args, **kwargs) except Exception as ex: raise QISKitError("Couldn't instance provider!. Error: {0}".format(ex)) _DEFAULT_PROVIDER.add_provider(provider) return provider
def add_provider(self, provider): """ Add a new provider to the list of known providers. Args: provider (BaseProvider): Provider instance. Returns: BaseProvider: the provider instance. Raises: QISKitError: if trying to add a provider identical to one already registered """ # Check for backend name clashes, emitting a warning. current_backends = {str(backend) for backend in self.available_backends()} added_backends = {str(backend) for backend in provider.available_backends()} common_backends = added_backends.intersection(current_backends) # checks for equality of provider instances, based on the __eq__ method if provider not in self.providers: self.providers.append(provider) else: raise QISKitError("The same provider has already been registered!") if common_backends: logger.warning( 'The backend names "%s" of this provider are already in use. ' 'Refer to documentation for `available_backends()` and `unregister()`.', list(common_backends)) return provider
def remove_provider(self, provider_name): """ Remove a provider from the list of known providers. Args: provider_name (str): name of the provider to be removed. Raises: QISKitError: if the provider name is not valid. """ if provider_name == 'local': raise QISKitError("Cannot unregister 'local' provider.") try: self.providers.pop(provider_name) except KeyError: raise QISKitError("'%s' provider is not registered.")
def __init__(self, q_jobs, callback, max_workers=1): """ Args: q_jobs (list(QuantumJob)): List of QuantumJob objects. callback (fn(results)): The function that will be called when all jobs finish. The signature of the function must be: fn(results) results: A list of Result objects. max_workers (int): The maximum number of workers to use. Raises: QISKitError: if any of the job backends could not be found. """ self.q_jobs = q_jobs self.max_workers = max_workers # check whether any jobs are remote self.online = any(qj.backend not in local_backends() for qj in q_jobs) self.futures = {} self.lock = Lock() # Set a default dummy callback just in case the user doesn't want # to pass any callback. self.callback = (lambda rs: ()) if callback is None else callback self.num_jobs = len(self.q_jobs) self.jobs_results = [] if self.online: # verify backends across all jobs for q_job in q_jobs: if q_job.backend not in remote_backends() + local_backends(): raise QISKitError("Backend %s not found!" % q_job.backend) if self.online: # I/O intensive -> use ThreadedPoolExecutor self.executor_class = futures.ThreadPoolExecutor else: # CPU intensive -> use ProcessPoolExecutor self.executor_class = futures.ProcessPoolExecutor
def least_busy(names): """ Return the least busy available backend for those that have a `pending_jobs` in their `status`. Backends such as local backends that do not have this are not considered. Args: names (list[str]): backend names to choose from (e.g. output of ``available_backends()``) Returns: str: the name of the least busy backend Raises: QISKitError: if passing a list of backend names that is either empty or none have attribute ``pending_jobs`` """ backends = [get_backend(name) for name in names] try: return min([ b for b in backends if b.status()['operational'] and 'pending_jobs' in b.status() ], key=lambda b: b.status()['pending_jobs']).name() except (ValueError, TypeError): raise QISKitError( "Can only find least_busy backend from a non-empty list.")
def register(token, url='https://quantumexperience.ng.bluemix.net/api', hub=None, group=None, project=None, proxies=None, verify=True, provider_name='ibmq'): """ Authenticate against an online backend provider. Args: token (str): The token used to register on the online backend such as the quantum experience. url (str): The url used for online backend such as the quantum experience. hub (str): The hub used for online backend. group (str): The group used for online backend. project (str): The project used for online backend. proxies (dict): Proxy configuration for the API, as a dict with 'urls' and credential keys. verify (bool): If False, ignores SSL certificates errors. provider_name (str): the unique name for the online backend provider (for example, 'ibmq' for the IBM Quantum Experience). Raises: QISKitError: if the provider name is not recognized. """ if provider_name == 'ibmq': provider = IBMQProvider(token, url, hub, group, project, proxies, verify) _DEFAULT_PROVIDER.add_provider(provider) else: raise QISKitError('provider name %s is not recognized' % provider_name)
def get_output(self): """Returns the generated circuit.""" if not self._is_circuit_valid(): raise QISKitError( "Invalid circuit! Please check the syntax of your circuit." "Has the Qasm parsing been called?. e.g: unroller.execute().") return self.circuit
def store_credentials(provider_class=IBMQProvider, overwrite=False, filename=None, **kwargs): """ Store the credentials for a single provider in the configuration file. Args: provider_class (class): class of the Provider for the credentials. overwrite (bool): overwrite existing credentials. filename (str): full path to the qiskitrc file. If `None`, the default location is used (`HOME/.qiskit/qiskitrc`). kwargs (dict): keyword arguments passed to provider class initialization. Raises: QISKitError: If provider already exists and overwrite=False; or if the account_name could not be assigned. """ # Set the name of the Provider from the class. account_name = get_account_name(provider_class) # Read the current providers stored in the configuration file. filename = filename or DEFAULT_QISKITRC_FILE credentials = read_credentials_from_qiskitrc(filename) if account_name in credentials.keys() and not overwrite: raise QISKitError('%s is already present and overwrite=False' % account_name) # Append the provider, trim the empty options and store it in the file. kwargs = {key: value for key, value in kwargs.items() if value is not None} credentials[account_name] = {**kwargs} write_qiskit_rc(credentials, filename)
def add_ibmq_provider(self, credentials_dict, provider_name=None): """ Add a new IBMQProvider to the list of known providers. Args: credentials_dict (dict): dictionary of credentials for a provider. provider_name (str): User-provided name for the provider. A name will automatically be assigned if possible. Raises: QISKitError: if a provider with the same name is already in the list; or if a provider name could not be assigned. Returns: IBMQProvider: the new IBMQProvider instance. """ # Automatically assign a name if not specified. if not provider_name: if 'quantumexperience' in credentials_dict['url']: provider_name = 'ibmq' elif 'q-console' in credentials_dict['url']: provider_name = 'qnet' else: raise QISKitError( 'Cannot parse provider name from credentials.') ibmq_provider = IBMQProvider(**credentials_dict) return self.add_provider(ibmq_provider, provider_name)
def load_qasm_file(qasm_file, name=None, basis_gates="id,u0,u1,u2,u3,x,y,z,h,s,sdg,t,tdg,rx,ry,rz," "cx,cy,cz,ch,crz,cu1,cu3,swap,ccx,cswap"): """Construct a quantum circuit from a qasm representation (file). Args: qasm_file (str): a string for the filename including its location. name (str or None): the name of the quantum circuit after loading qasm text into it. If no name is give the name is of the text file. basis_gates (str): basis gates for the quantum circuit. Returns: QuantumCircuit: circuit constructed from qasm. Raises: QISKitError: if the file cannot be read. """ if not os.path.exists(qasm_file): raise QISKitError('qasm file "{0}" not found'.format(qasm_file)) if not name: name = os.path.splitext(os.path.basename(qasm_file))[0] with open(qasm_file) as file: qasm_data = file.read() return load_qasm_string(qasm_data, name=name, basis_gates=basis_gates)
def remove_provider(self, provider): """ Remove a provider from the list of known providers. Args: provider (BaseProvider): provider to be removed. Raises: QISKitError: if the provider is not registered. """ if isinstance(provider, LocalProvider): raise QISKitError("Cannot unregister 'local' provider.") try: self.providers.remove(provider) except ValueError: raise QISKitError("'%s' provider is not registered.")
def run_circuit(self, circuit): """Apply the single-qubit gate. Args: circuit (QobjExperiment): experiment from qobj experiments list Returns: dict: A dictionary of results. Raises: QISKitError: if the number of qubits in the circuit is greater than 24. Note that the practical qubit limit is much lower than 24. """ self._number_of_qubits = circuit.header.number_of_qubits if self._number_of_qubits > 24: raise QISKitError("np.einsum implementation limits local_unitary_simulator" + " to 24 qubit circuits.") result = { 'data': {}, 'name': circuit.header.name } # Initilize unitary as rank 2*N tensor self._unitary_state = np.reshape(np.eye(2 ** self._number_of_qubits, dtype=complex), self._number_of_qubits * [2, 2]) for operation in circuit.instructions: if operation.name in ('U', 'u1', 'u2', 'u3'): params = getattr(operation, 'params', None) qubit = operation.qubits[0] gate = single_gate_matrix(operation.name, params) self._add_unitary_single(gate, qubit) elif operation.name in ('id', 'u0'): pass elif operation.name in ('CX', 'cx'): qubit0 = operation.qubits[0] qubit1 = operation.qubits[1] gate = np.array([[1, 0, 0, 0], [0, 0, 0, 1], [0, 0, 1, 0], [0, 1, 0, 0]]) self._add_unitary_two(gate, qubit0, qubit1) elif operation.name == 'measure': logger.info('Warning have dropped measure from unitary ' 'simulator') elif operation.name == 'reset': logger.info('Warning have dropped reset from unitary ' 'simulator') elif operation.name == 'barrier': pass else: result['status'] = 'ERROR' return result # Reshape unitary rank-2n tensor back to a matrix result['data']['unitary'] = np.reshape(self._unitary_state, 2 * [2 ** self._number_of_qubits]) result['status'] = 'DONE' result['success'] = True result['shots'] = 1 return result
def vqe(molecule='H2', depth=6, max_trials=200, shots=1): if molecule == 'H2': n_qubits = 2 Z1 = 1 Z2 = 1 min_distance = 0.2 max_distance = 4 elif molecule == 'LiH': n_qubits = 4 Z1 = 1 Z2 = 3 min_distance = 0.5 max_distance = 5 else: raise QISKitError("Unknown molecule for VQE.") # Read Hamiltonian ham_name = os.path.join(os.path.dirname(__file__), molecule + '/' + molecule + 'Equilibrium.txt') pauli_list = Hamiltonian_from_file(ham_name) H = make_Hamiltonian(pauli_list) # Exact Energy exact = np.amin(la.eig(H)[0]).real print('The exact ground state energy is: {}'.format(exact)) # Optimization device = 'qasm_simulator' if shots == 1: device = 'statevector_simulator' if 'statevector' not in device: H = group_paulis(pauli_list) entangler_map = get_backend(device).configuration()['coupling_map'] if entangler_map == 'all-to-all': entangler_map = {i: [j for j in range(n_qubits) if j != i] for i in range(n_qubits)} else: entangler_map = mapper.coupling_list2dict(entangler_map) initial_theta = np.random.randn(2 * n_qubits * depth) # initial angles initial_c = 0.01 # first theta perturbations target_update = 2 * np.pi * 0.1 # aimed update on first trial save_step = 20 # print optimization trajectory cost = partial(cost_function, H, n_qubits, depth, entangler_map, shots, device) SPSA_params, circuits_cal = SPSA_calibration(cost, initial_theta, initial_c, target_update, stat=25) output, circuits_opt = SPSA_optimization(cost, initial_theta, SPSA_params, max_trials, save_step, last_avg=1) return circuits_cal + circuits_opt
def available_backends(self, filters=None): """Get a list of available backends from all providers (after filtering). Note: If two or more providers share similar backend names, only the backends belonging to the first registered provider will be returned. Args: filters (dict or callable): filtering conditions. each will either pass through, or be filtered out: 1) dict: {'criteria': value} the criteria can be over backend's `configuration` or `status` e.g. {'local': False, 'simulator': False, 'operational': True} 2) callable: BaseBackend -> bool e.g. lambda x: x.configuration()['n_qubits'] > 5 Returns: list[BaseBackend]: a list of backend instances available from all the providers. Raises: QISKitError: if passing filters that is neither dict nor callable """ # pylint: disable=arguments-differ backends = [] for provider in self.providers: backends.extend(provider.available_backends()) if filters is not None: if isinstance(filters, dict): # exact match filter: # e.g. {'n_qubits': 5, 'operational': True} for key, value in filters.items(): backends = [ instance for instance in backends if instance.configuration().get(key) == value or instance.status().get(key) == value ] elif callable(filters): # acceptor filter: accept or reject a specific backend # e.g. lambda x: x.configuration()['n_qubits'] > 5 accepted_backends = [] for backend in backends: try: if filters(backend) is True: accepted_backends.append(backend) except Exception: # pylint: disable=broad-except pass backends = accepted_backends else: raise QISKitError( 'backend filters must be either dict or callable.') return backends
def __init__(self, q_jobs, callback, max_workers=1, token=None, url=None, api=None): """ Args: q_jobs (list(QuantumJob)): List of QuantumJob objects. callback (fn(results)): The function that will be called when all jobs finish. The signature of the function must be: fn(results) results: A list of Result objects. max_workers (int): The maximum number of workers to use. token (str): Server API token url (str): Server URL. api (IBMQuantumExperience): API instance to use. If set, /token/ and /url/ are ignored. """ self.q_jobs = q_jobs self.max_workers = max_workers # check whether any jobs are remote self._local_backends = backends.local_backends() self.online = any(qj.backend not in self._local_backends for qj in q_jobs) self.futures = {} self.lock = Lock() # Set a default dummy callback just in case the user doesn't want # to pass any callback. self.callback = (lambda rs: ()) if callback is None else callback self.num_jobs = len(self.q_jobs) self.jobs_results = [] if self.online: self._api = api if api else IBMQuantumExperience( token, {"url": url}, verify=True) self._online_backends = remote_backends(self._api) # Check for the existance of the backend for q_job in q_jobs: if q_job.backend not in self._online_backends + self._local_backends: raise QISKitError("Backend %s not found!" % q_job.backend) self._api_config = {} self._api_config["token"] = token self._api_config["url"] = {"url": url} else: self._api = None self._online_backends = None self._api_config = None if self.online: # I/O intensive -> use ThreadedPoolExecutor self.executor_class = futures.ThreadPoolExecutor else: # CPU intensive -> use ProcessPoolExecutor self.executor_class = futures.ProcessPoolExecutor
def _get_experiment(self, key=None): """Return an experiment from a given key. Args: key (str or QuantumCircuit or int or None): the index of the experiment, as specified by ``get_data()``. Returns: ExperimentResult: the results for an experiment. Raises: QISKitError: if there is no data for the circuit, or an unhandled error occurred while fetching the data. """ if not self.success: raise QISKitError( getattr(self, 'status', 'Result was not successful')) # Automatically return the first result if no key was provided. if key is None: if len(self.results) != 1: raise QISKitError( 'You have to select a circuit when there is more than ' 'one available') else: key = 0 # Key is an integer: return result by index. if isinstance(key, int): return self.results[key] # Key is a QuantumCircuit or str: retrieve result by name. if isinstance(key, QuantumCircuit): key = key.name try: # Look into `result[x].header.name` for the names. return next( result for result in self.results if getattr(getattr(result, 'header', None), 'name', '') == key) except StopIteration: raise QISKitError('Data for experiment "%s" could not be found.' % key)
def einsum_matmul_index(gate_indices, number_of_qubits): """Return the index string for Numpy.eignsum matrix multiplication. The returned indices are to perform a matrix multiplication A.B where the matrix A is an M-qubit matrix, matrix B is an N-qubit matrix, and M <= N, and identity matrices are implied on the subsystems where A has no support on B. Args: gate_indices (list[int]): the indices of the right matrix subsystems to contract with the left matrix. number_of_qubits (int): the total number of qubits for the right matrix. Returns: str: An indices string for the Numpy.einsum function. Raises: QISKitError: if the total number of qubits plus the number of contracted indices is greater than 26. """ # Since we use ASCII alphabet for einsum index labels we are limited # to 26 total free left (lowercase) and 26 right (uppercase) indexes. # The rank of the contracted tensor reduces this as we need to use that # many characters for the contracted indices if len(gate_indices) + number_of_qubits > 26: raise QISKitError("Total number of free indexes limited to 26") # Right indices for the N-qubit input and output tensor idx_right = ascii_uppercase[:number_of_qubits] # Left ndicies for N-qubit input tensor idx_left_in = ascii_lowercase[:number_of_qubits] # Left indices for the N-qubit output tensor idx_left_out = list(idx_left_in) # Left and right indices for the M-qubit multiplying tensor mat_left = "" mat_right = "" # Update left indices for mat and output for pos, idx in enumerate(reversed(gate_indices)): mat_left += ascii_lowercase[-1 - pos] mat_right += idx_left_in[-1 - idx] idx_left_out[-1 - idx] = ascii_lowercase[-1 - pos] idx_left_out = "".join(idx_left_out) # Combine indices into matrix multiplication string format # for numpy.einsum function return "{mat_l}{mat_r}, ".format(mat_l=mat_left, mat_r=mat_right) + \ "{tens_lin}{tens_r}->{tens_lout}{tens_r}".format(tens_lin=idx_left_in, tens_lout=idx_left_out, tens_r=idx_right)
def __pauli_meas_gates(circuit, qreg, op): """ Add state measurement gates to a circuit. """ if op not in ['X', 'Y', 'Z']: raise QISKitError("There's no X, Y or Z basis for this Pauli measurement") if op == "X": circuit.u2(0., np.pi, qreg) # H elif op == "Y": circuit.u2(0., 0.5 * np.pi, qreg) # H.S^*
def get_snapshot(self, slot=None, circuit=None): """Get snapshot at a specific slot. Args: slot (str): snapshot slot to retrieve. If None and there is only one slot, return that one. circuit (str or QuantumCircuit or None): reference to a quantum circuit If None and there is only one circuit available, returns that one. Returns: dict[slot: dict[str: array]]: list of 2^n_qubits complex amplitudes. Raises: QISKitError: if there is no snapshot at all, or in this slot """ try: snapshots_dict = self.get_snapshots(circuit) if slot is None: slots = list(snapshots_dict.keys()) if len(slots) == 1: slot = slots[0] else: raise QISKitError("You have to select a slot when there " "is more than one available") snapshot_dict = snapshots_dict[slot] snapshot_types = list(snapshot_dict.keys()) if len(snapshot_types) == 1: snapshot_list = snapshot_dict[snapshot_types[0]] if len(snapshot_list) == 1: return snapshot_list[0] else: return snapshot_list else: return snapshot_dict except KeyError: raise QISKitError('No snapshot at slot {0} for ' 'circuit "{1}"'.format(slot, circuit))