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 _check_qreg(self, register): """Raise exception if r is not in this circuit or not qreg.""" if not isinstance(register, QuantumRegister): raise QiskitError("expected quantum register") if not self.has_register(register): raise QiskitError("register '%s' not in this circuit" % register.name)
def _check_creg(self, register): """Raise exception if r is not in this circuit or not creg.""" if not isinstance(register, ClassicalRegister): raise QiskitError("Expected ClassicalRegister, but %s given" % type(register)) if not self.has_register(register): raise QiskitError("register '%s' not in this circuit" % register.name)
def add_register(self, *regs): """Add registers.""" for register in regs: if register in self.qregs or register in self.cregs: raise QiskitError("register name \"%s\" already exists" % register.name) if isinstance(register, QuantumRegister): self.qregs.append(register) elif isinstance(register, ClassicalRegister): self.cregs.append(register) else: raise QiskitError("expected a register")
def _best_subset(backend, n_qubits): """Computes the qubit mapping with the best connectivity. Parameters: backend (BaseBackend): A Qiskit backend instance. n_qubits (int): Number of subset qubits to consider. Returns: ndarray: Array of qubits to use for best connectivity mapping. Raises: QiskitError: Wrong number of qubits given. """ if n_qubits == 1: return np.array([0]) elif n_qubits <= 0: raise QiskitError('Number of qubits <= 0.') device_qubits = backend.configuration().n_qubits if n_qubits > device_qubits: raise QiskitError('Number of qubits greater than device.') cmap = np.asarray(getattr(backend.configuration(), 'coupling_map', None)) data = np.ones_like(cmap[:, 0]) sp_cmap = sp.coo_matrix((data, (cmap[:, 0], cmap[:, 1])), shape=(device_qubits, device_qubits)).tocsr() best = 0 best_map = None # do bfs with each node as starting point for k in range(sp_cmap.shape[0]): bfs = cs.breadth_first_order(sp_cmap, i_start=k, directed=False, return_predecessors=False) connection_count = 0 for i in range(n_qubits): node_idx = bfs[i] for j in range(sp_cmap.indptr[node_idx], sp_cmap.indptr[node_idx + 1]): node = sp_cmap.indices[j] for counter in range(n_qubits): if node == bfs[counter]: connection_count += 1 break if connection_count > best: best = connection_count best_map = bfs[0:n_qubits] return best_map
def _check_qubit(self, qubit): """Raise exception if qubit is not in this circuit or bad format.""" if not isinstance(qubit, tuple): raise QiskitError("%s is not a tuple." "A qubit should be formated as a tuple." % str(qubit)) if not len(qubit) == 2: raise QiskitError( "%s is not a tuple with two elements, but %i instead" % len(qubit)) if not isinstance(qubit[1], int): raise QiskitError( "The second element of a tuple defining a qubit should be an int:" "%s was found instead" % type(qubit[1]).__name__) self._check_qreg(qubit[0]) qubit[0].check_range(qubit[1])
def job_monitor(job, interval=2, monitor_async=False): """Monitor the status of a IBMQJob instance. Args: job (BaseJob): Job to monitor. interval (int): Time interval between status queries. monitor_async (bool): Monitor asyncronously (in Jupyter only). Raises: QiskitError: When trying to run async outside of Jupyter """ if _NOTEBOOK_ENV: style = "font-size:16px;" header = "<p style='{style}'>Job Status: %s </p>".format(style=style) status = widgets.HTML(value=header % job.status().value) display(status) if monitor_async: thread = threading.Thread(target=_html_checker, args=(job, interval, status, header)) thread.start() else: _html_checker(job, interval, status, header) else: if monitor_async: raise QiskitError( 'monitor_async only available in Jupyter notebooks.') _text_checker(job, interval)
def __init__(self, *regs, name=None): """Create a new circuit. A circuit is a list of instructions bound to some registers. Args: *regs (Registers): registers to include in the circuit. name (str or None): the name of the quantum circuit. If None, an automatically generated string will be assigned. Raises: QiskitError: if the circuit name, if given, is not valid. """ if name is None: name = self.cls_prefix() + str(self.cls_instances()) self._increment_instances() if not isinstance(name, str): raise QiskitError("The circuit name should be a string " "(or None to auto-generate a name).") self.name = name # Data contains a list of instructions in the order they were applied. self.data = [] # This is a map of registers bound to this circuit, by name. self.qregs = [] self.cregs = [] self.add_register(*regs)
def _modifiers(self, gate): """Apply any modifiers of this instruction to another one.""" if self.control is not None: self.check_circuit() if not gate.circuit.has_register(self.control[0]): raise QiskitError("control register %s not found" % self.control[0].name) gate.c_if(self.control[0], self.control[1])
def c_if(self, classical, val): """Add classical control on register classical and value val.""" self.check_circuit() self.circuit._check_creg(classical) if val < 0: raise QiskitError("control value should be non-negative") self.control = (classical, val) return self
def _check_dups(self, qubits): """Raise exception. if list of qubits contains duplicates. """ squbits = set(qubits) if len(squbits) != len(qubits): raise QiskitError("duplicate qubit arguments")
def _check_qubit(self, qubit): """Raise exception if q is not an argument or not qreg in circuit.""" self.check_circuit() self.circuit._check_qubit(qubit) if (qubit[0].name, qubit[1]) not in map(lambda x: (x[0].name, x[1]), self.qargs): raise QiskitError("qubit '%s[%d]' not argument of gate" % (qubit[0].name, qubit[1]))
def __init__(self, name, param, qargs, cargs, circuit=None): """Create a new instruction. Args: name (str): instruction name param (list[sympy.Basic|qasm.Node|int|float|complex|str]): list of parameters qargs (list[(QuantumRegister, index)]): list of quantum args cargs (list[(ClassicalRegister, index)]): list of classical args circuit (QuantumCircuit or Instruction): where the instruction is attached Raises: QiskitError: when the register is not in the correct format. """ if not all( (type(i[0]), type(i[1])) == (QuantumRegister, int) for i in qargs): raise QiskitError("qarg not (QuantumRegister, int) tuple") if not all((type(i[0]), type(i[1])) == (ClassicalRegister, int) for i in cargs): raise QiskitError("carg not (ClassicalRegister, int) tuple") self.name = name self.param = [] # a list of gate params stored as sympy objects for single_param in param: # example: u2(pi/2, sin(pi/4)) if isinstance(single_param, sympy.Basic): self.param.append(single_param) # example: OpenQASM parsed instruction elif isinstance(single_param, _node.Node): self.param.append(single_param.sym()) # example: u3(0.1, 0.2, 0.3) elif isinstance(single_param, (int, float)): self.param.append(sympy.Number(single_param)) # example: Initialize([complex(0,1), complex(0,0)]) elif isinstance(single_param, complex): self.param.append(single_param.real + single_param.imag * sympy.I) # example: snapshot('label') elif isinstance(single_param, str): self.param.append(sympy.Symbol(single_param)) else: raise QiskitError("invalid param type {0} in instruction " "{1}".format(type(single_param), name)) self.qargs = qargs self.cargs = cargs self._decompositions = [] self.control = None # tuple (ClassicalRegister, int) for "if" self.circuit = circuit
def __init__(self, size, name=None): """Create a new generic register. """ if name is None: name = '%s%i' % (self.prefix, next(self.instances_counter)) if not isinstance(name, str): raise QiskitError("The circuit name should be a string " "(or None for autogenerate a name).") test = re.compile('[a-z][a-zA-Z0-9_]*') if test.match(name) is None: raise QiskitError("%s is an invalid OPENQASM register name." % name) self.name = name self.size = size if size <= 0: raise QiskitError("register size must be positive")
def _check_compatible_regs(self, rhs): """Raise exception if the circuits are defined on incompatible registers""" list1 = self.qregs + self.cregs list2 = rhs.qregs + rhs.cregs for element1 in list1: for element2 in list2: if element2.name == element1.name: if element1 != element2: raise QiskitError("circuits are not compatible")
def __getitem__(self, key): """ Arg: key (int): index of the bit/qubit to be retrieved. Returns: tuple[Register, int]: a tuple in the form `(self, key)`. Raises: QiskitError: if the `key` is not an integer. QiskitIndexError: if the `key` is not in the range `(0, self.size)`. """ if not isinstance(key, int): raise QiskitError("expected integer index into register") self.check_range(key) return self, key
def _get_backend_instance(self, backend_cls): """ Return an instance of a backend from its class. Args: backend_cls (class): Backend class. Returns: BaseBackend: a backend instance. Raises: QiskitError: if the backend could not be instantiated. """ # Verify that the backend can be instantiated. try: backend_instance = backend_cls(provider=self) except Exception as err: raise QiskitError('Backend %s could not be instantiated: %s' % (backend_cls, err)) return backend_instance
def least_busy(backends): """ 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: backends (list[BaseBackend]): backends to choose from Returns: BaseBackend: the the least busy backend Raises: QiskitError: if passing a list of backend names that is either empty or none have attribute ``pending_jobs`` """ try: return min([b for b in backends if b.status().operational], key=lambda b: b.status().pending_jobs) except (ValueError, TypeError): raise QiskitError("Can only find least_busy backend from a non-empty list.")
def q_if(self, *qregs): """Add controls to this gate.""" # pylint: disable=unused-argument raise QiskitError("control not implemented")
def inverse(self): """Invert this gate.""" raise QiskitError("inverse not implemented")
def parallel_map(task, values, task_args=tuple(), task_kwargs={}, # pylint: disable=W0102 num_processes=CPU_COUNT): """ Parallel execution of a mapping of `values` to the function `task`. This is functionally equivalent to:: result = [task(value, *task_args, **task_kwargs) for value in values] On Windows this function defaults to a serial implementation to avoid the overhead from spawning processes in Windows. Args: task (func): Function that is to be called for each value in ``task_vec``. values (array_like): List or array of values for which the ``task`` function is to be evaluated. task_args (list): Optional additional arguments to the ``task`` function. task_kwargs (dict): Optional additional keyword argument to the ``task`` function. num_processes (int): Number of processes to spawn. Returns: result: The result list contains the value of ``task(value, *task_args, **task_kwargs)`` for each value in ``values``. Raises: QiskitError: If user interrupts via keyboard. Events: terra.transpiler.parallel.start: The collection of parallel tasks are about to start. terra.transpiler.parallel.update: One of the parallel task has finished. terra.transpiler.parallel.finish: All the parallel tasks have finished. """ if len(values) == 1: return [task(values[0], *task_args, **task_kwargs)] Publisher().publish("terra.transpiler.parallel.start", len(values)) nfinished = [0] def _callback(_): nfinished[0] += 1 Publisher().publish("terra.transpiler.parallel.done", nfinished[0]) # Run in parallel if not Win and not in parallel already if platform.system() != 'Windows' and num_processes > 1 \ and os.getenv('QISKIT_IN_PARALLEL') == 'FALSE': os.environ['QISKIT_IN_PARALLEL'] = 'TRUE' try: pool = Pool(processes=num_processes) async_res = [pool.apply_async(task, (value,) + task_args, task_kwargs, _callback) for value in values] while not all([item.ready() for item in async_res]): for item in async_res: item.wait(timeout=0.1) pool.terminate() pool.join() except KeyboardInterrupt: pool.terminate() pool.join() Publisher().publish("terra.parallel.parallel.finish") raise QiskitError('Keyboard interrupt in parallel_map.') Publisher().publish("terra.transpiler.parallel.finish") os.environ['QISKIT_IN_PARALLEL'] = 'FALSE' return [ar.get() for ar in async_res] # Cannot do parallel on Windows , if another parallel_map is running in parallel, # or len(values) == 1. results = [] for _, value in enumerate(values): result = task(value, *task_args, **task_kwargs) results.append(result) _callback(0) Publisher().publish("terra.transpiler.parallel.finish") return results
def add(self, gate): """Add instruction to set.""" if not isinstance(gate, Instruction): raise QiskitError("attempt to add non-Instruction" + " to InstructionSet") self.instructions.append(gate)
def check_circuit(self): """Raise exception if self.circuit is None.""" if self.circuit is None: raise QiskitError("Instruction's circuit not assigned")