Instruction:
Write a Python 3 function for
plotting the gate map of a device.

Response:
def plot_gate_map(backend, figsize=None,
                  plot_directed=False,
                  label_qubits=True,
                  qubit_size=24,
                  line_width=4,
                  font_size=12,
                  qubit_color=None,
                  line_color=None,
                  font_color='w'):
    """Plots the gate map of a device.

    Args:
        backend (BaseBackend): A backend instance,
        figsize (tuple): Output figure size (wxh) in inches.
        plot_directed (bool): Plot directed coupling map.
        label_qubits (bool): Label the qubits.
        qubit_size (float): Size of qubit marker.
        line_width (float): Width of lines.
        font_size (int): Font size of qubit labels.
        qubit_color (list): A list of colors for the qubits
        line_color (list): A list of colors for each line from coupling_map.
        font_color (str): The font color for the qubit labels.

    Returns:
        Figure: A Matplotlib figure instance.

    Raises:
        QiskitError: if tried to pass a simulator.
        ImportError: if matplotlib not installed.
    """
    if not HAS_MATPLOTLIB:
        raise ImportError('Must have Matplotlib installed.')

    if backend.configuration().simulator:
        raise QiskitError('Requires a device backend, not simulator.')

    mpl_data = {}

    mpl_data['ibmq_20_tokyo'] = [[0, 0], [0, 1], [0, 2], [0, 3], [0, 4],
                                 [1, 0], [1, 1], [1, 2], [1, 3], [1, 4],
                                 [2, 0], [2, 1], [2, 2], [2, 3], [2, 4],
                                 [3, 0], [3, 1], [3, 2], [3, 3], [3, 4]]

    mpl_data['ibmq_poughkeepsie'] = mpl_data['ibmq_20_tokyo']

    mpl_data['ibmq_16_melbourne'] = [[0, 0], [0, 1], [0, 2], [0, 3], [0, 4],
                                     [0, 5], [0, 6], [1, 7], [1, 6], [1, 5],
                                     [1, 4], [1, 3], [1, 2], [1, 1]]

    mpl_data['ibmq_16_rueschlikon'] = [[1, 0], [0, 0], [0, 1], [0, 2], [0, 3],
                                       [0, 4], [0, 5], [0, 6], [0, 7], [1, 7],
                                       [1, 6], [1, 5], [1, 4], [1, 3], [1, 2], [1, 1]]

    mpl_data['ibmq_5_tenerife'] = [[1, 0], [0, 1], [1, 1], [1, 2], [2, 1]]

    mpl_data['ibmq_5_yorktown'] = mpl_data['ibmq_5_tenerife']

    config = backend.configuration()
    name = config.backend_name
    cmap = config.coupling_map

    dep_names = {'ibmqx5': 'ibmq_16_rueschlikon',
                 'ibmqx4': 'ibmq_5_tenerife',
                 'ibmqx2': 'ibmq_5_yorktown'}

    if name in dep_names.keys():
        name = dep_names[name]

    if name in mpl_data.keys():
        grid_data = mpl_data[name]
    else:
        fig, ax = plt.subplots(figsize=(5, 5))  # pylint: disable=invalid-name
        ax.axis('off')
        return fig

    x_max = max([d[1] for d in grid_data])
    y_max = max([d[0] for d in grid_data])
    max_dim = max(x_max, y_max)

    if figsize is None:
        if x_max/max_dim > 0.33 and y_max/max_dim > 0.33:
            figsize = (5, 5)
        else:
            figsize = (9, 3)

    fig, ax = plt.subplots(figsize=figsize)  # pylint: disable=invalid-name
    ax.axis('off')
    fig.tight_layout()

    # set coloring
    if qubit_color is None:
        qubit_color = ['#648fff']*config.n_qubits
    if line_color is None:
        line_color = ['#648fff']*len(cmap)

    # Add lines for couplings
    for ind, edge in enumerate(cmap):
        is_symmetric = False
        if edge[::-1] in cmap:
            is_symmetric = True
        y_start = grid_data[edge[0]][0]
        x_start = grid_data[edge[0]][1]
        y_end = grid_data[edge[1]][0]
        x_end = grid_data[edge[1]][1]

        if is_symmetric:
            if y_start == y_end:
                x_end = (x_end - x_start)/2+x_start

            elif x_start == x_end:
                y_end = (y_end - y_start)/2+y_start

            else:
                x_end = (x_end - x_start)/2+x_start
                y_end = (y_end - y_start)/2+y_start
        ax.add_artist(plt.Line2D([x_start, x_end], [-y_start, -y_end],
                                 color=line_color[ind], linewidth=line_width,
                                 zorder=0))
        if plot_directed:
            dx = x_end-x_start  # pylint: disable=invalid-name
            dy = y_end-y_start  # pylint: disable=invalid-name
            if is_symmetric:
                x_arrow = x_start+dx*0.95
                y_arrow = -y_start-dy*0.95
                dx_arrow = dx*0.01
                dy_arrow = -dy*0.01
                head_width = 0.15
            else:
                x_arrow = x_start+dx*0.5
                y_arrow = -y_start-dy*0.5
                dx_arrow = dx*0.2
                dy_arrow = -dy*0.2
                head_width = 0.2
            ax.add_patch(mpatches.FancyArrow(x_arrow,
                                             y_arrow,
                                             dx_arrow,
                                             dy_arrow,
                                             head_width=head_width,
                                             length_includes_head=True,
                                             edgecolor=None,
                                             linewidth=0,
                                             facecolor=line_color[ind],
                                             zorder=1))

    # Add circles for qubits
    for var, idx in enumerate(grid_data):
        _idx = [idx[1], -idx[0]]
        width = _GraphDist(qubit_size, ax, True)
        height = _GraphDist(qubit_size, ax, False)
        ax.add_artist(mpatches.Ellipse(
            _idx, width, height, color=qubit_color[var], zorder=1))
        if label_qubits:
            ax.text(*_idx, s=str(var),
                    horizontalalignment='center',
                    verticalalignment='center',
                    color=font_color, size=font_size, weight='bold')
    ax.set_xlim([-1, x_max+1])
    ax.set_ylim([-(y_max+1), 1])
    plt.close(fig)
    return fig


Instruction:
Can you create a Python 3 function that
distances abs of the current time series

Response:
def dist_abs(self):
        """Distance abs
        """
        bounds = self.ax.get_xlim() if self.x else self.ax.get_ylim()
        return bounds[0] - bounds[1]


Instruction:
Can you write a function in Python 3 where it
prints the node data with indent.

Response:
def to_string(self, indent):
        """Print the node data, with indent."""
        ind = indent * ' '
        print(ind, 'qreg')
        self.children[0].to_string(indent + 3)


Instruction:
How would you explain what the following Python 3 function does
def _verify_backends(self):
        ret = OrderedDict()
        for backend_cls in SIMULATORS:
            try:
                backend_instance = self._get_backend_instance(backend_cls)
                backend_name = backend_instance.name()
                ret[backend_name] = backend_instance
            except QiskitError as err:
                # Ignore backends that could not be initialized.
                logger.info('Basic Aer backend %s is not available: %s',
                            backend_cls, str(err))
        return ret

Response: Verify that all Basic Aer backends are available.


Instruction:
Write a Python 3 script for
returning an instance of a backend from its class.

Response:
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


Instruction:
Write a Python 3 function for
returning a list of qubits as ( QuantumRegister index ) pairs.

Response:
def qubits(self):
        """Return a list of qubits as (QuantumRegister, index) pairs."""
        return [(v, i) for k, v in self.qregs.items() for i in range(v.size)]


Instruction:
Can you implement a function in Python 3 that
returns a list of bits as ( ClassicalRegister index ) pairs.

Response:
def clbits(self):
        """Return a list of bits as (ClassicalRegister, index) pairs."""
        return [(v, i) for k, v in self.cregs.items() for i in range(v.size)]


Instruction:
Implement a Python 3 function for
renaming a classical or quantum register throughout the circuit.

Response:
def rename_register(self, regname, newname):
        """Rename a classical or quantum register throughout the circuit.

        regname = existing register name string
        newname = replacement register name string
        """
        if regname == newname:
            return
        if newname in self.qregs or newname in self.cregs:
            raise DAGCircuitError("duplicate register name %s" % newname)
        if regname not in self.qregs and regname not in self.cregs:
            raise DAGCircuitError("no register named %s" % regname)
        if regname in self.qregs:
            reg = self.qregs[regname]
            reg.name = newname
            self.qregs[newname] = reg
            self.qregs.pop(regname, None)
        if regname in self.cregs:
            reg = self.cregs[regname]
            reg.name = newname
            self.qregs[newname] = reg
            self.qregs.pop(regname, None)

        for node in self._multi_graph.nodes():
            if node.type == "in" or node.type == "out":
                if node.name and regname in node.name:
                    node.name = newname
            elif node.type == "op":
                qa = []
                for a in node.qargs:
                    if a[0] == regname:
                        a = (newname, a[1])
                    qa.append(a)
                node.qargs = qa
                ca = []
                for a in node.cargs:
                    if a[0] == regname:
                        a = (newname, a[1])
                    ca.append(a)
                node.cargs = ca
                if node.condition is not None:
                    if node.condition[0] == regname:
                        node.condition = (newname, node.condition[1])
        # eX = edge, d= data
        for _, _, edge_data in self._multi_graph.edges(data=True):
            if regname in edge_data['name']:
                edge_data['name'] = re.sub(regname, newname, edge_data['name'])


Instruction:
Create a Python 3 function to
remove all operations with the given name.

Response:
def remove_all_ops_named(self, opname):
        """Remove all operation nodes with the given name."""
        for n in self.named_nodes(opname):
            self.remove_op_node(n)


Instruction:
Can you implement a function in Python 3 that
adds all wires in a quantum register.

Response:
def add_qreg(self, qreg):
        """Add all wires in a quantum register."""
        if not isinstance(qreg, QuantumRegister):
            raise DAGCircuitError("not a QuantumRegister instance.")
        if qreg.name in self.qregs:
            raise DAGCircuitError("duplicate register %s" % qreg.name)
        self.qregs[qreg.name] = qreg
        for j in range(qreg.size):
            self._add_wire((qreg, j))


Instruction:
Write a Python 3 function for
adding all wires in a classical register.

Response:
def add_creg(self, creg):
        """Add all wires in a classical register."""
        if not isinstance(creg, ClassicalRegister):
            raise DAGCircuitError("not a ClassicalRegister instance.")
        if creg.name in self.cregs:
            raise DAGCircuitError("duplicate register %s" % creg.name)
        self.cregs[creg.name] = creg
        for j in range(creg.size):
            self._add_wire((creg, j))


Instruction:
Implement a function in Python 3 to
add a wire to the circuit.

Response:
def _add_wire(self, wire):
        """Add a qubit or bit to the circuit.

        Args:
            wire (tuple): (Register,int) containing a register instance and index
            This adds a pair of in and out nodes connected by an edge.

        Raises:
            DAGCircuitError: if trying to add duplicate wire
        """
        if wire not in self.wires:
            self.wires.append(wire)
            self._max_node_id += 1
            input_map_wire = self.input_map[wire] = self._max_node_id

            self._max_node_id += 1
            output_map_wire = self._max_node_id

            wire_name = "%s[%s]" % (wire[0].name, wire[1])

            inp_node = DAGNode(data_dict={'type': 'in', 'name': wire_name, 'wire': wire},
                               nid=input_map_wire)
            outp_node = DAGNode(data_dict={'type': 'out', 'name': wire_name, 'wire': wire},
                                nid=output_map_wire)
            self._id_to_node[input_map_wire] = inp_node
            self._id_to_node[output_map_wire] = outp_node

            self.input_map[wire] = inp_node
            self.output_map[wire] = outp_node

            self._multi_graph.add_node(inp_node)
            self._multi_graph.add_node(outp_node)

            self._multi_graph.add_edge(inp_node,
                                       outp_node)

            self._multi_graph.adj[inp_node][outp_node][0]["name"] \
                = "%s[%s]" % (wire[0].name, wire[1])
            self._multi_graph.adj[inp_node][outp_node][0]["wire"] \
                = wire
        else:
            raise DAGCircuitError("duplicate wire %s" % (wire,))


Instruction:
Here you have a function in Python 3, explain what it does
def _check_condition(self, name, condition):
        # Verify creg exists
        if condition is not None and condition[0].name not in self.cregs:
            raise DAGCircuitError("invalid creg in condition for %s" % name)

Response: Verify that the condition is valid.


Instruction:
Make a summary of the following Python 3 code
def _check_bits(self, args, amap):
        # Check for each wire
        for wire in args:
            if wire not in amap:
                raise DAGCircuitError("(qu)bit %s[%d] not found" %
                                      (wire[0].name, wire[1]))

Response: Check the values of a list of ( qu ) bit arguments.


Instruction:
Write a Python 3 function for
returning a list of bits in the given condition.

Response:
def _bits_in_condition(self, cond):
        """Return a list of bits in the given condition.

        Args:
            cond (tuple or None): optional condition (ClassicalRegister, int)

        Returns:
            list[(ClassicalRegister, idx)]: list of bits
        """
        all_bits = []
        if cond is not None:
            all_bits.extend([(cond[0], j) for j in range(self.cregs[cond[0].name].size)])
        return all_bits


Instruction:
Implement a Python 3 function for
adding a new operation node to the multi - graph and assign properties.

Response:
def _add_op_node(self, op, qargs, cargs, condition=None):
        """Add a new operation node to the graph and assign properties.

        Args:
            op (Instruction): the operation associated with the DAG node
            qargs (list): list of quantum wires to attach to.
            cargs (list): list of classical wires to attach to.
            condition (tuple or None): optional condition (ClassicalRegister, int)
        """
        node_properties = {
            "type": "op",
            "op": op,
            "name": op.name,
            "qargs": qargs,
            "cargs": cargs,
            "condition": condition
        }

        # Add a new operation node to the graph
        self._max_node_id += 1
        new_node = DAGNode(data_dict=node_properties, nid=self._max_node_id)
        self._multi_graph.add_node(new_node)
        self._id_to_node[self._max_node_id] = new_node


Instruction:
Write a Python 3 function that can
apply an operation to the output of the circuit.

Response:
def apply_operation_back(self, op, qargs=None, cargs=None, condition=None):
        """Apply an operation to the output of the circuit.

        Args:
            op (Instruction): the operation associated with the DAG node
            qargs (list[tuple]): qubits that op will be applied to
            cargs (list[tuple]): cbits that op will be applied to
            condition (tuple or None): optional condition (ClassicalRegister, int)

        Returns:
            DAGNode: the current max node

        Raises:
            DAGCircuitError: if a leaf node is connected to multiple outputs

        """
        qargs = qargs or []
        cargs = cargs or []

        all_cbits = self._bits_in_condition(condition)
        all_cbits.extend(cargs)

        self._check_condition(op.name, condition)
        self._check_bits(qargs, self.output_map)
        self._check_bits(all_cbits, self.output_map)

        self._add_op_node(op, qargs, cargs, condition)

        # Add new in-edges from predecessors of the output nodes to the
        # operation node while deleting the old in-edges of the output nodes
        # and adding new edges from the operation node to each output node
        al = [qargs, all_cbits]
        for q in itertools.chain(*al):
            ie = list(self._multi_graph.predecessors(self.output_map[q]))

            if len(ie) != 1:
                raise DAGCircuitError("output node has multiple in-edges")

            self._multi_graph.add_edge(ie[0], self._id_to_node[self._max_node_id],
                                       name="%s[%s]" % (q[0].name, q[1]), wire=q)
            self._multi_graph.remove_edge(ie[0], self.output_map[q])
            self._multi_graph.add_edge(self._id_to_node[self._max_node_id], self.output_map[q],
                                       name="%s[%s]" % (q[0].name, q[1]), wire=q)

        return self._id_to_node[self._max_node_id]


Instruction:
Can you generate the documentation for the following Python 3 function
def _check_edgemap_registers(self, edge_map, keyregs, valregs, valreg=True):
        # FIXME: some mixing of objects and strings here are awkward (due to
        # self.qregs/self.cregs still keying on string.
        add_regs = set()
        reg_frag_chk = {}
        for v in keyregs.values():
            reg_frag_chk[v] = {j: False for j in range(len(v))}
        for k in edge_map.keys():
            if k[0].name in keyregs:
                reg_frag_chk[k[0]][k[1]] = True
        for k, v in reg_frag_chk.items():
            s = set(v.values())
            if len(s) == 2:
                raise DAGCircuitError("edge_map fragments reg %s" % k)
            elif s == set([False]):
                if k in self.qregs.values() or k in self.cregs.values():
                    raise DAGCircuitError("unmapped duplicate reg %s" % k)
                else:
                    # Add registers that appear only in keyregs
                    add_regs.add(k)
            else:
                if valreg:
                    # If mapping to a register not in valregs, add it.
                    # (k,0) exists in edge_map because edge_map doesn't
                    # fragment k
                    if not edge_map[(k, 0)][0].name in valregs:
                        size = max(map(lambda x: x[1],
                                       filter(lambda x: x[0] == edge_map[(k, 0)][0],
                                              edge_map.values())))
                        qreg = QuantumRegister(size + 1, edge_map[(k, 0)][0].name)
                        add_regs.add(qreg)
        return add_regs

Response: Check that the wiremap does not leave duplicate registers.


Instruction:
Can you write a function in Python 3 where it
checks that the wire_map is consistent.

Response:
def _check_wiremap_validity(self, wire_map, keymap, valmap):
        """Check that the wiremap is consistent.

        Check that the wiremap refers to valid wires and that
        those wires have consistent types.

        Args:
            wire_map (dict): map from (register,idx) in keymap to
                (register,idx) in valmap
            keymap (dict): a map whose keys are wire_map keys
            valmap (dict): a map whose keys are wire_map values

        Raises:
            DAGCircuitError: if wire_map not valid
        """
        for k, v in wire_map.items():
            kname = "%s[%d]" % (k[0].name, k[1])
            vname = "%s[%d]" % (v[0].name, v[1])
            if k not in keymap:
                raise DAGCircuitError("invalid wire mapping key %s" % kname)
            if v not in valmap:
                raise DAGCircuitError("invalid wire mapping value %s" % vname)
            if type(k) is not type(v):
                raise DAGCircuitError("inconsistent wire_map at (%s,%s)" %
                                      (kname, vname))


Instruction:
Can you write a function in Python 3 where it
maps the condition tuple to the new condition tuple.

Response:
def _map_condition(self, wire_map, condition):
        """Use the wire_map dict to change the condition tuple's creg name.

        Args:
            wire_map (dict): a map from wires to wires
            condition (tuple): (ClassicalRegister,int)
        Returns:
            tuple(ClassicalRegister,int): new condition
        """
        if condition is None:
            new_condition = None
        else:
            # Map the register name, using fact that registers must not be
            # fragmented by the wire_map (this must have been checked
            # elsewhere)
            bit0 = (condition[0], 0)
            new_condition = (wire_map.get(bit0, bit0)[0], condition[1])
        return new_condition


Instruction:
Make a summary of the following Python 3 code
def extend_back(self, dag, edge_map=None):
        edge_map = edge_map or {}
        for qreg in dag.qregs.values():
            if qreg.name not in self.qregs:
                self.add_qreg(QuantumRegister(qreg.size, qreg.name))
            edge_map.update([(qbit, qbit) for qbit in qreg if qbit not in edge_map])

        for creg in dag.cregs.values():
            if creg.name not in self.cregs:
                self.add_creg(ClassicalRegister(creg.size, creg.name))
            edge_map.update([(cbit, cbit) for cbit in creg if cbit not in edge_map])

        self.compose_back(dag, edge_map)

Response: Add dag at the end of self using edge_map.


Instruction:
Make a summary of the following Python 3 code
def compose_back(self, input_circuit, edge_map=None):
        edge_map = edge_map or {}

        # Check the wire map for duplicate values
        if len(set(edge_map.values())) != len(edge_map):
            raise DAGCircuitError("duplicates in wire_map")

        add_qregs = self._check_edgemap_registers(edge_map,
                                                  input_circuit.qregs,
                                                  self.qregs)
        for qreg in add_qregs:
            self.add_qreg(qreg)

        add_cregs = self._check_edgemap_registers(edge_map,
                                                  input_circuit.cregs,
                                                  self.cregs)
        for creg in add_cregs:
            self.add_creg(creg)

        self._check_wiremap_validity(edge_map, input_circuit.input_map,
                                     self.output_map)

        # Compose
        for nd in input_circuit.topological_nodes():
            if nd.type == "in":
                # if in wire_map, get new name, else use existing name
                m_wire = edge_map.get(nd.wire, nd.wire)
                # the mapped wire should already exist
                if m_wire not in self.output_map:
                    raise DAGCircuitError("wire %s[%d] not in self" % (m_wire[0].name, m_wire[1]))

                if nd.wire not in input_circuit.wires:
                    raise DAGCircuitError("inconsistent wire type for %s[%d] in input_circuit"
                                          % (nd.wire[0].name, nd.wire[1]))

            elif nd.type == "out":
                # ignore output nodes
                pass
            elif nd.type == "op":
                condition = self._map_condition(edge_map, nd.condition)
                self._check_condition(nd.name, condition)
                m_qargs = list(map(lambda x: edge_map.get(x, x), nd.qargs))
                m_cargs = list(map(lambda x: edge_map.get(x, x), nd.cargs))
                self.apply_operation_back(nd.op, m_qargs, m_cargs, condition)
            else:
                raise DAGCircuitError("bad node type %s" % nd.type)

Response: Apply the input circuit to the output of this circuit.


Instruction:
Can you tell what is the following Python 3 function doing
def depth(self):
        if not nx.is_directed_acyclic_graph(self._multi_graph):
            raise DAGCircuitError("not a DAG")

        depth = nx.dag_longest_path_length(self._multi_graph) - 1
        return depth if depth != -1 else 0

Response: Return the depth of the current node in the DAG.


Instruction:
Write a Python 3 function that can
check that a list of wires is compatible with a node.

Response:
def _check_wires_list(self, wires, node):
        """Check that a list of wires is compatible with a node to be replaced.

        - no duplicate names
        - correct length for operation
        Raise an exception otherwise.

        Args:
            wires (list[register, index]): gives an order for (qu)bits
                in the input circuit that is replacing the node.
            node (DAGNode): a node in the dag

        Raises:
            DAGCircuitError: if check doesn't pass.
        """
        if len(set(wires)) != len(wires):
            raise DAGCircuitError("duplicate wires")

        wire_tot = len(node.qargs) + len(node.cargs)
        if node.condition is not None:
            wire_tot += node.condition[0].size

        if len(wires) != wire_tot:
            raise DAGCircuitError("expected %d wires, got %d"
                                  % (wire_tot, len(wires)))


Instruction:
Implement a function in Python 3 to
return predecessor and successor dictionaries.

Response:
def _make_pred_succ_maps(self, node):
        """Return predecessor and successor dictionaries.

        Args:
            node (DAGNode): reference to multi_graph node

        Returns:
            tuple(dict): tuple(predecessor_map, successor_map)
                These map from wire (Register, int) to predecessor (successor)
                nodes of n.
        """

        pred_map = {e[2]['wire']: e[0] for e in
                    self._multi_graph.in_edges(nbunch=node, data=True)}
        succ_map = {e[2]['wire']: e[1] for e in
                    self._multi_graph.out_edges(nbunch=node, data=True)}
        return pred_map, succ_map


Instruction:
Make a summary of the following Python 3 code
def _full_pred_succ_maps(self, pred_map, succ_map, input_circuit,
                             wire_map):
        """Map all wires of the input circuit.

        Map all wires of the input circuit to predecessor and
        successor nodes in self, keyed on wires in self.

        Args:
            pred_map (dict): comes from _make_pred_succ_maps
            succ_map (dict): comes from _make_pred_succ_maps
            input_circuit (DAGCircuit): the input circuit
            wire_map (dict): the map from wires of input_circuit to wires of self

        Returns:
            tuple: full_pred_map, full_succ_map (dict, dict)

        Raises:
            DAGCircuitError: if more than one predecessor for output nodes
        """
        full_pred_map = {}
        full_succ_map = {}
        for w in input_circuit.input_map:
            # If w is wire mapped, find the corresponding predecessor
            # of the node
            if w in wire_map:
                full_pred_map[wire_map[w]] = pred_map[wire_map[w]]
                full_succ_map[wire_map[w]] = succ_map[wire_map[w]]
            else:
                # Otherwise, use the corresponding output nodes of self
                # and compute the predecessor.
                full_succ_map[w] = self.output_map[w]
                full_pred_map[w] = self._multi_graph.predecessors(
                    self.output_map[w])[0]
                if len(list(self._multi_graph.predecessors(self.output_map[w]))) != 1:
                    raise DAGCircuitError("too many predecessors for %s[%d] "
                                          "output node" % (w[0], w[1]))

        return full_pred_map, full_succ_map

Response: Map all wires of the input circuit to predecessor and successor nodes in self and compute the full predecessors of the output nodes.


Instruction:
Can you generate the documentation for the following Python 3 function
def topological_nodes(self):
        return nx.lexicographical_topological_sort(self._multi_graph,
                                                   key=lambda x: str(x.qargs))

Response: Yield nodes in topological order.


Instruction:
Can you implement a function in Python 3 that
substitutes one node with a dag.

Response:
def substitute_node_with_dag(self, node, input_dag, wires=None):
        """Replace one node with dag.

        Args:
            node (DAGNode): node to substitute
            input_dag (DAGCircuit): circuit that will substitute the node
            wires (list[(Register, index)]): gives an order for (qu)bits
                in the input circuit. This order gets matched to the node wires
                by qargs first, then cargs, then conditions.

        Raises:
            DAGCircuitError: if met with unexpected predecessor/successors
        """
        if isinstance(node, int):
            warnings.warn('Calling substitute_node_with_dag() with a node id is deprecated,'
                          ' use a DAGNode instead',
                          DeprecationWarning, 2)

            node = self._id_to_node[node]

        condition = node.condition
        # the dag must be ammended if used in a
        # conditional context. delete the op nodes and replay
        # them with the condition.
        if condition:
            input_dag.add_creg(condition[0])
            to_replay = []
            for sorted_node in input_dag.topological_nodes():
                if sorted_node.type == "op":
                    sorted_node.op.control = condition
                    to_replay.append(sorted_node)
            for input_node in input_dag.op_nodes():
                input_dag.remove_op_node(input_node)
            for replay_node in to_replay:
                input_dag.apply_operation_back(replay_node.op, replay_node.qargs,
                                               replay_node.cargs, condition=condition)

        if wires is None:
            qwires = [w for w in input_dag.wires if isinstance(w[0], QuantumRegister)]
            cwires = [w for w in input_dag.wires if isinstance(w[0], ClassicalRegister)]
            wires = qwires + cwires

        self._check_wires_list(wires, node)

        # Create a proxy wire_map to identify fragments and duplicates
        # and determine what registers need to be added to self
        proxy_map = {w: QuantumRegister(1, 'proxy') for w in wires}
        add_qregs = self._check_edgemap_registers(proxy_map,
                                                  input_dag.qregs,
                                                  {}, False)
        for qreg in add_qregs:
            self.add_qreg(qreg)

        add_cregs = self._check_edgemap_registers(proxy_map,
                                                  input_dag.cregs,
                                                  {}, False)
        for creg in add_cregs:
            self.add_creg(creg)

        # Replace the node by iterating through the input_circuit.
        # Constructing and checking the validity of the wire_map.
        # If a gate is conditioned, we expect the replacement subcircuit
        # to depend on those control bits as well.
        if node.type != "op":
            raise DAGCircuitError("expected node type \"op\", got %s"
                                  % node.type)

        condition_bit_list = self._bits_in_condition(node.condition)

        wire_map = {k: v for k, v in zip(wires,
                                         [i for s in [node.qargs,
                                                      node.cargs,
                                                      condition_bit_list]
                                          for i in s])}
        self._check_wiremap_validity(wire_map, wires, self.input_map)
        pred_map, succ_map = self._make_pred_succ_maps(node)
        full_pred_map, full_succ_map = self._full_pred_succ_maps(pred_map, succ_map,
                                                                 input_dag, wire_map)
        # Now that we know the connections, delete node
        self._multi_graph.remove_node(node)

        # Iterate over nodes of input_circuit
        for sorted_node in input_dag.topological_op_nodes():
            # Insert a new node
            condition = self._map_condition(wire_map, sorted_node.condition)
            m_qargs = list(map(lambda x: wire_map.get(x, x),
                               sorted_node.qargs))
            m_cargs = list(map(lambda x: wire_map.get(x, x),
                               sorted_node.cargs))
            self._add_op_node(sorted_node.op, m_qargs, m_cargs, condition)
            # Add edges from predecessor nodes to new node
            # and update predecessor nodes that change
            all_cbits = self._bits_in_condition(condition)
            all_cbits.extend(m_cargs)
            al = [m_qargs, all_cbits]
            for q in itertools.chain(*al):
                self._multi_graph.add_edge(full_pred_map[q],
                                           self._id_to_node[self._max_node_id],
                                           name="%s[%s]" % (q[0].name, q[1]),
                                           wire=q)
                full_pred_map[q] = self._id_to_node[self._max_node_id]

        # Connect all predecessors and successors, and remove
        # residual edges between input and output nodes
        for w in full_pred_map:
            self._multi_graph.add_edge(full_pred_map[w],
                                       full_succ_map[w],
                                       name="%s[%s]" % (w[0].name, w[1]),
                                       wire=w)
            o_pred = list(self._multi_graph.predecessors(self.output_map[w]))
            if len(o_pred) > 1:
                if len(o_pred) != 2:
                    raise DAGCircuitError("expected 2 predecessors here")

                p = [x for x in o_pred if x != full_pred_map[w]]
                if len(p) != 1:
                    raise DAGCircuitError("expected 1 predecessor to pass filter")

                self._multi_graph.remove_edge(p[0], self.output_map[w])


Instruction:
How would you explain what the following Python 3 function does
def edges(self, nodes=None):
        for source_node, dest_node, edge_data in self._multi_graph.edges(nodes, data=True):
            yield source_node, dest_node, edge_data

Response: Iterate over edges of the node values.


Instruction:
Make a summary of the following Python 3 code
def op_nodes(self, op=None):
        nodes = []
        for node in self._multi_graph.nodes():
            if node.type == "op":
                if op is None or isinstance(node.op, op):
                    nodes.append(node)
        return nodes

Response: Returns the list of op nodes in the dag.


Instruction:
How would you implement a function in Python 3 that
gets the list of gate nodes in the dag.

Response:
def gate_nodes(self):
        """Get the list of gate nodes in the dag.

        Returns:
            list: the list of node ids that represent gates.
        """
        nodes = []
        for node in self.op_nodes():
            if isinstance(node.op, Gate):
                nodes.append(node)
        return nodes


Instruction:
Can you generate the documentation for the following Python 3 function
def get_named_nodes(self, *names):
        warnings.warn('The method get_named_nodes() is being replaced by named_nodes()',
                      'Returning a list of node_ids is also deprecated, named_nodes() '
                      'returns a list of DAGNodes ',
                      DeprecationWarning, 2)

        named_nodes = []
        for node in self._multi_graph.nodes():
            if node.type == 'op' and node.op.name in names:
                named_nodes.append(node._node_id)
        return named_nodes

Response: Deprecated. Use named_nodes instead.


Instruction:
Can you write a function in Python 3 where it
gets the set of op nodes with the given name.

Response:
def named_nodes(self, *names):
        """Get the set of "op" nodes with the given name."""
        named_nodes = []
        for node in self._multi_graph.nodes():
            if node.type == 'op' and node.op.name in names:
                named_nodes.append(node)
        return named_nodes


Instruction:
Given the following Python 3 function, write the documentation
def get_2q_nodes(self):
        warnings.warn('The method get_2q_nodes() is being replaced by twoQ_gates()',
                      'Returning a list of data_dicts is also deprecated, twoQ_gates() '
                      'returns a list of DAGNodes.',
                      DeprecationWarning, 2)

        two_q_nodes = []
        for node in self._multi_graph.nodes():
            if node.type == 'op' and len(node.qargs) == 2:
                two_q_nodes.append(node.data_dict)

        return two_q_nodes

Response: Deprecated. Use twoQ_gates() to get a list of data_dicts.


Instruction:
Here you have a function in Python 3, explain what it does
def twoQ_gates(self):
        two_q_gates = []
        for node in self.gate_nodes():
            if len(node.qargs) == 2:
                two_q_gates.append(node)
        return two_q_gates

Response: Get list of 2 - qubit gates. Ignore snapshot barriers and the like.


Instruction:
Write a Python 3 script to
get list of 3 - or - more - qubit gates.

Response:
def threeQ_or_more_gates(self):
        """Get list of 3-or-more-qubit gates: (id, data)."""
        three_q_gates = []
        for node in self.gate_nodes():
            if len(node.qargs) >= 3:
                three_q_gates.append(node)
        return three_q_gates


Instruction:
Here you have a function in Python 3, explain what it does
def predecessors(self, node):
        if isinstance(node, int):
            warnings.warn('Calling predecessors() with a node id is deprecated,'
                          ' use a DAGNode instead',
                          DeprecationWarning, 2)
            node = self._id_to_node[node]

        return self._multi_graph.predecessors(node)

Response: Returns the list of predecessors of a node as DAGNodes.


Instruction:
Explain what the following Python 3 code does
def quantum_predecessors(self, node):

        predecessors = []
        for predecessor in self.predecessors(node):
            if isinstance(self._multi_graph.get_edge_data(predecessor, node, key=0)['wire'][0],
                          QuantumRegister):
                predecessors.append(predecessor)
        return predecessors

Response: Returns the list of predecessors of a node that are connected by a quantum edge as DAGNodes.


Instruction:
Given the following Python 3 function, write the documentation
def ancestors(self, node):
        if isinstance(node, int):
            warnings.warn('Calling ancestors() with a node id is deprecated,'
                          ' use a DAGNode instead',
                          DeprecationWarning, 2)
            node = self._id_to_node[node]

        return nx.ancestors(self._multi_graph, node)

Response: Returns the set of ancestors of a node as DAGNodes.


Instruction:
How would you implement a function in Python 3 that
returns the list of successors of a node that are connected by a quantum edge as DAGNodes.

Response:
def quantum_successors(self, node):
        """Returns list of the successors of a node that are
        connected by a quantum edge as DAGNodes."""
        if isinstance(node, int):
            warnings.warn('Calling quantum_successors() with a node id is deprecated,'
                          ' use a DAGNode instead',
                          DeprecationWarning, 2)
            node = self._id_to_node[node]

        successors = []
        for successor in self.successors(node):
            if isinstance(self._multi_graph.get_edge_data(
                    node, successor, key=0)['wire'][0],
                          QuantumRegister):
                successors.append(successor)
        return successors


Instruction:
Make a summary of the following Python 3 code
def remove_op_node(self, node):
        if isinstance(node, int):
            warnings.warn('Calling remove_op_node() with a node id is deprecated,'
                          ' use a DAGNode instead',
                          DeprecationWarning, 2)
            node = self._id_to_node[node]

        if node.type != 'op':
            raise DAGCircuitError('The method remove_op_node only works on op node types. An "%s" '
                                  'node type was wrongly provided.' % node.type)

        pred_map, succ_map = self._make_pred_succ_maps(node)

        # remove from graph and map
        self._multi_graph.remove_node(node)

        for w in pred_map.keys():
            self._multi_graph.add_edge(pred_map[w], succ_map[w],
                                       name="%s[%s]" % (w[0].name, w[1]), wire=w)

Response: Remove an operation node n.


Instruction:
Given the following Python 3 function, write the documentation
def remove_ancestors_of(self, node):
        if isinstance(node, int):
            warnings.warn('Calling remove_ancestors_of() with a node id is deprecated,'
                          ' use a DAGNode instead',
                          DeprecationWarning, 2)
            node = self._id_to_node[node]

        anc = nx.ancestors(self._multi_graph, node)
        # TODO: probably better to do all at once using
        # multi_graph.remove_nodes_from; same for related functions ...
        for anc_node in anc:
            if anc_node.type == "op":
                self.remove_op_node(anc_node)

Response: Remove all of the ancestor operation nodes of node.


Instruction:
Can you generate the documentation for the following Python 3 function
def remove_descendants_of(self, node):
        if isinstance(node, int):
            warnings.warn('Calling remove_descendants_of() with a node id is deprecated,'
                          ' use a DAGNode instead',
                          DeprecationWarning, 2)
            node = self._id_to_node[node]

        desc = nx.descendants(self._multi_graph, node)
        for desc_node in desc:
            if desc_node.type == "op":
                self.remove_op_node(desc_node)

Response: Remove all of the descendant operation nodes of node.


Instruction:
Make a summary of the following Python 3 code
def remove_nonancestors_of(self, node):
        if isinstance(node, int):
            warnings.warn('Calling remove_nonancestors_of() with a node id is deprecated,'
                          ' use a DAGNode instead',
                          DeprecationWarning, 2)
            node = self._id_to_node[node]

        anc = nx.ancestors(self._multi_graph, node)
        comp = list(set(self._multi_graph.nodes()) - set(anc))
        for n in comp:
            if n.type == "op":
                self.remove_op_node(n)

Response: Remove all of the non - ancestors operation nodes of node.


Instruction:
Write a Python 3 function for
removing all of the non - descendant operation nodes of node.

Response:
def remove_nondescendants_of(self, node):
        """Remove all of the non-descendants operation nodes of node."""
        if isinstance(node, int):
            warnings.warn('Calling remove_nondescendants_of() with a node id is deprecated,'
                          ' use a DAGNode instead',
                          DeprecationWarning, 2)
            node = self._id_to_node[node]

        dec = nx.descendants(self._multi_graph, node)
        comp = list(set(self._multi_graph.nodes()) - set(dec))
        for n in comp:
            if n.type == "op":
                self.remove_op_node(n)


Instruction:
Here you have a function in Python 3, explain what it does
def layers(self):
        graph_layers = self.multigraph_layers()
        try:
            next(graph_layers)  # Remove input nodes
        except StopIteration:
            return

        def add_nodes_from(layer, nodes):
            """ Convert DAGNodes into a format that can be added to a
             multigraph and then add to graph"""
            layer._multi_graph.add_nodes_from(nodes)

        for graph_layer in graph_layers:

            # Get the op nodes from the layer, removing any input and output nodes.
            op_nodes = [node for node in graph_layer if node.type == "op"]

            # Stop yielding once there are no more op_nodes in a layer.
            if not op_nodes:
                return

            # Construct a shallow copy of self
            new_layer = DAGCircuit()
            new_layer.name = self.name

            for creg in self.cregs.values():
                new_layer.add_creg(creg)
            for qreg in self.qregs.values():
                new_layer.add_qreg(qreg)

            add_nodes_from(new_layer, self.input_map.values())
            add_nodes_from(new_layer, self.output_map.values())
            add_nodes_from(new_layer, op_nodes)

            # The quantum registers that have an operation in this layer.
            support_list = [
                op_node.qargs
                for op_node in op_nodes
                if op_node.name not in {"barrier", "snapshot", "save", "load", "noise"}
            ]

            # Now add the edges to the multi_graph
            # By default we just wire inputs to the outputs.
            wires = {self.input_map[wire]: self.output_map[wire]
                     for wire in self.wires}
            # Wire inputs to op nodes, and op nodes to outputs.
            for op_node in op_nodes:
                args = self._bits_in_condition(op_node.condition) \
                       + op_node.cargs + op_node.qargs
                arg_ids = (self.input_map[(arg[0], arg[1])] for arg in args)
                for arg_id in arg_ids:
                    wires[arg_id], wires[op_node] = op_node, wires[arg_id]

            # Add wiring to/from the operations and between unused inputs & outputs.
            new_layer._multi_graph.add_edges_from(wires.items())
            yield {"graph": new_layer, "partition": support_list}

Response: Yields a shallow view on all d layers of this circuit.


Instruction:
Here you have a function in Python 3, explain what it does
def serial_layers(self):
        for next_node in self.topological_op_nodes():
            new_layer = DAGCircuit()
            for qreg in self.qregs.values():
                new_layer.add_qreg(qreg)
            for creg in self.cregs.values():
                new_layer.add_creg(creg)
            # Save the support of the operation we add to the layer
            support_list = []
            # Operation data
            op = copy.copy(next_node.op)
            qa = copy.copy(next_node.qargs)
            ca = copy.copy(next_node.cargs)
            co = copy.copy(next_node.condition)
            _ = self._bits_in_condition(co)

            # Add node to new_layer
            new_layer.apply_operation_back(op, qa, ca, co)
            # Add operation to partition
            if next_node.name not in ["barrier",
                                      "snapshot", "save", "load", "noise"]:
                support_list.append(list(qa))
            l_dict = {"graph": new_layer, "partition": support_list}
            yield l_dict

Response: Yields a list of all serial layers for all gates of this circuit.


Instruction:
Can you tell what is the following Python 3 function doing
def multigraph_layers(self):
        predecessor_count = dict()  # Dict[node, predecessors not visited]
        cur_layer = [node for node in self.input_map.values()]
        yield cur_layer
        next_layer = []
        while cur_layer:
            for node in cur_layer:
                # Count multiedges with multiplicity.
                for successor in self._multi_graph.successors(node):
                    multiplicity = self._multi_graph.number_of_edges(node, successor)
                    if successor in predecessor_count:
                        predecessor_count[successor] -= multiplicity
                    else:
                        predecessor_count[successor] = \
                            self._multi_graph.in_degree(successor) - multiplicity

                    if predecessor_count[successor] == 0:
                        next_layer.append(successor)
                        del predecessor_count[successor]

            yield next_layer
            cur_layer = next_layer
            next_layer = []

Response: Yields all layers of the multigraph.


Instruction:
Make a summary of the following Python 3 code
def collect_runs(self, namelist):
        group_list = []

        # Iterate through the nodes of self in topological order
        # and form tuples containing sequences of gates
        # on the same qubit(s).
        topo_ops = list(self.topological_op_nodes())
        nodes_seen = dict(zip(topo_ops, [False] * len(topo_ops)))
        for node in topo_ops:
            if node.name in namelist and node.condition is None \
                    and not nodes_seen[node]:
                group = [node]
                nodes_seen[node] = True
                s = list(self._multi_graph.successors(node))
                while len(s) == 1 and \
                        s[0].type == "op" and \
                        s[0].name in namelist:
                    group.append(s[0])
                    nodes_seen[s[0]] = True
                    s = list(self._multi_graph.successors(s[0]))
                if len(group) >= 1:
                    group_list.append(tuple(group))
        return set(group_list)

Response: Return a set of non - conditional runs of op nodes with the given names.


Instruction:
Can you tell what is the following Python 3 function doing
def nodes_on_wire(self, wire, only_ops=False):
        current_node = self.input_map.get(wire, None)

        if not current_node:
            raise DAGCircuitError('The given wire %s is not present in the circuit'
                                  % str(wire))

        more_nodes = True
        while more_nodes:
            more_nodes = False
            # allow user to just get ops on the wire - not the input/output nodes
            if current_node.type == 'op' or not only_ops:
                yield current_node

            # find the adjacent node that takes the wire being looked at as input
            for node, edges in self._multi_graph.adj[current_node].items():
                if any(wire == edge['wire'] for edge in edges.values()):
                    current_node = node
                    more_nodes = True
                    break

Response: Iterator for nodes that affect a given wire.


Instruction:
Can you generate a brief explanation for the following Python 3 code
def count_ops(self):
        op_dict = {}
        for node in self.topological_op_nodes():
            name = node.name
            if name not in op_dict:
                op_dict[name] = 1
            else:
                op_dict[name] += 1
        return op_dict

Response: Count the occurrences of operation names.


Instruction:
How would you explain what the following Python 3 function does
def properties(self):
        summary = {"size": self.size(),
                   "depth": self.depth(),
                   "width": self.width(),
                   "bits": self.num_cbits(),
                   "factors": self.num_tensor_factors(),
                   "operations": self.count_ops()}
        return summary

Response: Return a dictionary of circuit properties.


Instruction:
Here you have a function in Python 3, explain what it does
def tomography_basis(basis, prep_fun=None, meas_fun=None):
    ret = TomographyBasis(basis)
    ret.prep_fun = prep_fun
    ret.meas_fun = meas_fun
    return ret

Response: Generates a TomographyBasis object from a list of functions.


Instruction:
Can you tell what is the following Python 3 function doing
def __pauli_prep_gates(circuit, qreg, op):
    bas, proj = op
    if bas not in ['X', 'Y', 'Z']:
        raise QiskitError("There's no X, Y or Z basis for this Pauli "
                          "preparation")

    if bas == "X":
        if proj == 1:
            circuit.u2(np.pi, np.pi, qreg)  # H.X
        else:
            circuit.u2(0., np.pi, qreg)  # H
    elif bas == "Y":
        if proj == 1:
            circuit.u2(-0.5 * np.pi, np.pi, qreg)  # S.H.X
        else:
            circuit.u2(0.5 * np.pi, np.pi, qreg)  # S.H
    elif bas == "Z" and proj == 1:
        circuit.u3(np.pi, 0., np.pi, qreg)

Response: Add state preparation gates to a circuit.


Instruction:
Make a summary of the following Python 3 code
def __pauli_meas_gates(circuit, qreg, op):
    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)

Response: Add state measurement gates to a circuit.


Instruction:
How would you code a function in Python 3 to
add state preparation gates to a SIC.

Response:
def __sic_prep_gates(circuit, qreg, op):
    """
    Add state preparation gates to a circuit.
    """
    bas, proj = op

    if bas != 'S':
        raise QiskitError('Not in SIC basis!')

    theta = -2 * np.arctan(np.sqrt(2))
    if proj == 1:
        circuit.u3(theta, np.pi, 0.0, qreg)
    elif proj == 2:
        circuit.u3(theta, np.pi / 3, 0.0, qreg)
    elif proj == 3:
        circuit.u3(theta, -np.pi / 3, 0.0, qreg)


Instruction:
Can you implement a function in Python 3 that
generates a dictionary of process tomography experiment configurations. This returns a data structure that is used by other tomography functions to generate state and process tomography circuits, and extract tomography data from results after execution on a backend. A quantum process tomography set is created by specifying a preparation basis along with a measurement basis. The preparation basis may be a user defined `tomography_basis`, or one of the two built in basis 'SIC' or 'Pauli'. - SIC: Is a minimal symmetric informationally complete preparation basis for 4 states for each qubit (4 ^ number of qubits total preparation states). These correspond to the |0> state and the 3 other vertices of a tetrahedron on the Bloch-sphere. - Pauli: Is a tomographically overcomplete preparation basis of the six eigenstates of the 3 Pauli operators (6 ^ number of qubits total preparation states). Args: meas_qubits (list): The qubits being measured. meas_basis (tomography_basis or str): The qubit measurement basis. The default value is 'Pauli'. prep_qubits (list or None): The qubits being prepared. If None then meas_qubits will be used for process tomography experiments. prep_basis (tomography_basis or str): The qubit preparation basis. The default value is 'SIC'. Returns: dict: A dict of tomography configurations that can be parsed by `create_tomography_circuits` and `tomography_data` functions for implementing quantum tomography experiments. This output contains fields "qubits", "meas_basis", "prep_basus", circuits". ``` { 'qubits': qubits (list[ints]), 'meas_basis': meas_basis (tomography_basis), 'prep_basis': prep_basis (tomography_basis), 'circuit_labels': (list[string]), 'circuits': (list[dict]) # prep and meas configurations } ```

Response:
def process_tomography_set(meas_qubits, meas_basis='Pauli',
                           prep_qubits=None, prep_basis='SIC'):
    """
    Generate a dictionary of process tomography experiment configurations.

    This returns a data structure that is used by other tomography functions
    to generate state and process tomography circuits, and extract tomography
    data from results after execution on a backend.

   A quantum process tomography set is created by specifying a preparation
    basis along with a measurement basis. The preparation basis may be a
    user defined `tomography_basis`, or one of the two built in basis 'SIC'
    or 'Pauli'.
    - SIC: Is a minimal symmetric informationally complete preparation
           basis for 4 states for each qubit (4 ^ number of qubits total
           preparation states). These correspond to the |0> state and the 3
           other vertices of a tetrahedron on the Bloch-sphere.
    - Pauli: Is a tomographically overcomplete preparation basis of the six
             eigenstates of the 3 Pauli operators (6 ^ number of qubits
             total preparation states).

    Args:
        meas_qubits (list): The qubits being measured.
        meas_basis (tomography_basis or str): The qubit measurement basis.
            The default value is 'Pauli'.
        prep_qubits (list or None): The qubits being prepared. If None then
            meas_qubits will be used for process tomography experiments.
        prep_basis (tomography_basis or str): The qubit preparation basis.
            The default value is 'SIC'.

    Returns:
        dict: A dict of tomography configurations that can be parsed by
        `create_tomography_circuits` and `tomography_data` functions
        for implementing quantum tomography experiments. This output contains
        fields "qubits", "meas_basis", "prep_basus", circuits".
        ```
        {
            'qubits': qubits (list[ints]),
            'meas_basis': meas_basis (tomography_basis),
            'prep_basis': prep_basis (tomography_basis),
            'circuit_labels': (list[string]),
            'circuits': (list[dict])  # prep and meas configurations
        }
        ```
    """
    return tomography_set(meas_qubits, meas_basis=meas_basis,
                          prep_qubits=prep_qubits, prep_basis=prep_basis)


Instruction:
Write a Python 3 function that can
add tomography measurement circuits to a QuantumProgram. The quantum program must contain a circuit 'name', which is treated as a state preparation circuit for state tomography, or as teh circuit being measured for process tomography. This function then appends the circuit with a set of measurements specified by the input `tomography_set`, optionally it also prepends the circuit with state preparation circuits if they are specified in the `tomography_set`. For n-qubit tomography with a tomographically complete set of preparations and measurements this results in $4^n 3^n$ circuits being added to the quantum program. Args: circuit (QuantumCircuit): The circuit to be appended with tomography state preparation and/or measurements. qreg (QuantumRegister): the quantum register containing qubits to be measured. creg (ClassicalRegister): the classical register containing bits to store measurement outcomes. tomoset (tomography_set): the dict of tomography configurations. Returns: list: A list of quantum tomography circuits for the input circuit. Raises: QiskitError: if circuit is not a valid QuantumCircuit Example: For a tomography set specifying state tomography of qubit-0 prepared by a circuit 'circ' this would return: ``` ['circ_meas_X(0)', 'circ_meas_Y(0)', 'circ_meas_Z(0)'] ``` For process tomography of the same circuit with preparation in the SIC-POVM basis it would return: ``` [ 'circ_prep_S0(0)_meas_X(0)', 'circ_prep_S0(0)_meas_Y(0)', 'circ_prep_S0(0)_meas_Z(0)', 'circ_prep_S1(0)_meas_X(0)', 'circ_prep_S1(0)_meas_Y(0)', 'circ_prep_S1(0)_meas_Z(0)', 'circ_prep_S2(0)_meas_X(0)', 'circ_prep_S2(0)_meas_Y(0)', 'circ_prep_S2(0)_meas_Z(0)', 'circ_prep_S3(0)_meas_X(0)', 'circ_prep_S3(0)_meas_Y(0)', 'circ_prep_S3(0)_meas_Z(0)' ] ```

Response:
def create_tomography_circuits(circuit, qreg, creg, tomoset):
    """
    Add tomography measurement circuits to a QuantumProgram.

    The quantum program must contain a circuit 'name', which is treated as a
    state preparation circuit for state tomography, or as teh circuit being
    measured for process tomography. This function then appends the circuit
    with a set of measurements specified by the input `tomography_set`,
    optionally it also prepends the circuit with state preparation circuits if
    they are specified in the `tomography_set`.

    For n-qubit tomography with a tomographically complete set of preparations
    and measurements this results in $4^n 3^n$ circuits being added to the
    quantum program.

    Args:
        circuit (QuantumCircuit): The circuit to be appended with tomography
                                  state preparation and/or measurements.
        qreg (QuantumRegister): the quantum register containing qubits to be
                                measured.
        creg (ClassicalRegister): the classical register containing bits to
                                  store measurement outcomes.
        tomoset (tomography_set): the dict of tomography configurations.

    Returns:
        list: A list of quantum tomography circuits for the input circuit.

    Raises:
        QiskitError: if circuit is not a valid QuantumCircuit

    Example:
        For a tomography set specifying state tomography of qubit-0 prepared
        by a circuit 'circ' this would return:
        ```
        ['circ_meas_X(0)', 'circ_meas_Y(0)', 'circ_meas_Z(0)']
        ```
        For process tomography of the same circuit with preparation in the
        SIC-POVM basis it would return:
        ```
        [
            'circ_prep_S0(0)_meas_X(0)', 'circ_prep_S0(0)_meas_Y(0)',
            'circ_prep_S0(0)_meas_Z(0)', 'circ_prep_S1(0)_meas_X(0)',
            'circ_prep_S1(0)_meas_Y(0)', 'circ_prep_S1(0)_meas_Z(0)',
            'circ_prep_S2(0)_meas_X(0)', 'circ_prep_S2(0)_meas_Y(0)',
            'circ_prep_S2(0)_meas_Z(0)', 'circ_prep_S3(0)_meas_X(0)',
            'circ_prep_S3(0)_meas_Y(0)', 'circ_prep_S3(0)_meas_Z(0)'
        ]
        ```
    """

    if not isinstance(circuit, QuantumCircuit):
        raise QiskitError('Input circuit must be a QuantumCircuit object')

    dics = tomoset['circuits']
    labels = tomography_circuit_names(tomoset, circuit.name)
    tomography_circuits = []
    for label, conf in zip(labels, dics):
        tmp = circuit
        # Add prep circuits
        if 'prep' in conf:
            prep = QuantumCircuit(qreg, creg, name='tmp_prep')
            for qubit, op in conf['prep'].items():
                tomoset['prep_basis'].prep_gate(prep, qreg[qubit], op)
                prep.barrier(qreg[qubit])
            tmp = prep + tmp
        # Add measurement circuits
        meas = QuantumCircuit(qreg, creg, name='tmp_meas')
        for qubit, op in conf['meas'].items():
            meas.barrier(qreg[qubit])
            tomoset['meas_basis'].meas_gate(meas, qreg[qubit], op)
            meas.measure(qreg[qubit], creg[qubit])
        tmp = tmp + meas
        # Add label to the circuit
        tmp.name = label
        tomography_circuits.append(tmp)

    logger.info('>> created tomography circuits for "%s"', circuit.name)
    return tomography_circuits


Instruction:
Can you implement a function in Python 3 that
returns a dictionary for a state or process tomography experiment.

Response:
def tomography_data(results, name, tomoset):
    """
    Return a results dict for a state or process tomography experiment.

    Args:
        results (Result): Results from execution of a process tomography
            circuits on a backend.
        name (string): The name of the circuit being reconstructed.
        tomoset (tomography_set): the dict of tomography configurations.

    Returns:
        list: A list of dicts for the outcome of each process tomography
        measurement circuit.
    """

    labels = tomography_circuit_names(tomoset, name)
    circuits = tomoset['circuits']
    data = []
    prep = None
    for j, _ in enumerate(labels):
        counts = marginal_counts(results.get_counts(labels[j]),
                                 tomoset['qubits'])
        shots = sum(counts.values())
        meas = circuits[j]['meas']
        prep = circuits[j].get('prep', None)
        meas_qubits = sorted(meas.keys())
        if prep:
            prep_qubits = sorted(prep.keys())
        circuit = {}
        for c in counts.keys():
            circuit[c] = {}
            circuit[c]['meas'] = [(meas[meas_qubits[k]], int(c[-1 - k]))
                                  for k in range(len(meas_qubits))]
            if prep:
                circuit[c]['prep'] = [prep[prep_qubits[k]]
                                      for k in range(len(prep_qubits))]
        data.append({'counts': counts, 'shots': shots, 'circuit': circuit})

    ret = {'data': data, 'meas_basis': tomoset['meas_basis']}
    if prep:
        ret['prep_basis'] = tomoset['prep_basis']
    return ret


Instruction:
Write a Python 3 script for
computing the marginal counts for a subset of measured qubits.

Response:
def marginal_counts(counts, meas_qubits):
    """
    Compute the marginal counts for a subset of measured qubits.

    Args:
        counts (dict): the counts returned from a backend ({str: int}).
        meas_qubits (list[int]): the qubits to return the marginal
                                 counts distribution for.

    Returns:
        dict: A counts dict for the meas_qubits.abs
        Example: if `counts = {'00': 10, '01': 5}`
            `marginal_counts(counts, [0])` returns `{'0': 15, '1': 0}`.
            `marginal_counts(counts, [0])` returns `{'0': 10, '1': 5}`.
    """
    # pylint: disable=cell-var-from-loop
    # Extract total number of qubits from count keys
    num_of_qubits = len(list(counts.keys())[0])

    # keys for measured qubits only
    qs = sorted(meas_qubits, reverse=True)

    meas_keys = count_keys(len(qs))

    # get regex match strings for summing outcomes of other qubits
    rgx = [
        reduce(lambda x, y: (key[qs.index(y)] if y in qs else '\\d') + x,
               range(num_of_qubits), '') for key in meas_keys
    ]

    # build the return list
    meas_counts = []
    for m in rgx:
        c = 0
        for key, val in counts.items():
            if match(m, key):
                c += val
        meas_counts.append(c)

    # return as counts dict on measured qubits only
    return dict(zip(meas_keys, meas_counts))


Instruction:
Can you create a Python 3 function that
fits a Choi - matrix or process - matrix from tomography measurement data.

Response:
def fit_tomography_data(tomo_data, method='wizard', options=None):
    """
    Reconstruct a density matrix or process-matrix from tomography data.

    If the input data is state_tomography_data the returned operator will
    be a density matrix. If the input data is process_tomography_data the
    returned operator will be a Choi-matrix in the column-vectorization
    convention.

    Args:
        tomo_data (dict): process tomography measurement data.
        method (str): the fitting method to use.
            Available methods:
                - 'wizard' (default)
                - 'leastsq'
        options (dict or None): additional options for fitting method.

    Returns:
        numpy.array: The fitted operator.

    Available methods:
        - 'wizard' (Default): The returned operator will be constrained to be
                              positive-semidefinite.
            Options:
            - 'trace': the trace of the returned operator.
                       The default value is 1.
            - 'beta': hedging parameter for computing frequencies from
                      zero-count data. The default value is 0.50922.
            - 'epsilon: threshold for truncating small eigenvalues to zero.
                        The default value is 0
        - 'leastsq': Fitting without positive-semidefinite constraint.
            Options:
            - 'trace': Same as for 'wizard' method.
            - 'beta': Same as for 'wizard' method.
    Raises:
        Exception: if the `method` parameter is not valid.
    """

    if isinstance(method, str) and method.lower() in ['wizard', 'leastsq']:
        # get options
        trace = __get_option('trace', options)
        beta = __get_option('beta', options)
        # fit state
        rho = __leastsq_fit(tomo_data, trace=trace, beta=beta)
        if method == 'wizard':
            # Use wizard method to constrain positivity
            epsilon = __get_option('epsilon', options)
            rho = __wizard(rho, epsilon=epsilon)
        return rho
    else:
        raise Exception('Invalid reconstruction method "%s"' % method)


Instruction:
How would you explain what the following Python 3 function does
def __leastsq_fit(tomo_data, weights=None, trace=None, beta=None):
    if trace is None:
        trace = 1.  # default to unit trace

    data = tomo_data['data']
    keys = data[0]['circuit'].keys()

    # Get counts and shots
    counts = []
    shots = []
    ops = []
    for dat in data:
        for key in keys:
            counts.append(dat['counts'][key])
            shots.append(dat['shots'])
            projectors = dat['circuit'][key]
            op = __projector(projectors['meas'], tomo_data['meas_basis'])
            if 'prep' in projectors:
                op_prep = __projector(projectors['prep'],
                                      tomo_data['prep_basis'])
                op = np.kron(op_prep.conj(), op)
            ops.append(op)

    # Convert counts to frequencies
    counts = np.array(counts)
    shots = np.array(shots)
    freqs = counts / shots

    # Use hedged frequencies to calculate least squares fitting weights
    if weights is None:
        if beta is None:
            beta = 0.50922
        K = len(keys)
        freqs_hedged = (counts + beta) / (shots + K * beta)
        weights = np.sqrt(shots / (freqs_hedged * (1 - freqs_hedged)))

    return __tomo_linear_inv(freqs, ops, weights, trace=trace)

Response: Reconstruct a state from unconstrained least - squares fitting.


Instruction:
Make a summary of the following Python 3 code
def __tomo_linear_inv(freqs, ops, weights=None, trace=None):
    # get weights matrix
    if weights is not None:
        W = np.array(weights)
        if W.ndim == 1:
            W = np.diag(W)

    # Get basis S matrix
    S = np.array([vectorize(m).conj()
                  for m in ops]).reshape(len(ops), ops[0].size)
    if weights is not None:
        S = np.dot(W, S)  # W.S

    # get frequencies vec
    v = np.array(freqs)  # |f>
    if weights is not None:
        v = np.dot(W, freqs)  # W.|f>
    Sdg = S.T.conj()  # S^*.W^*
    inv = np.linalg.pinv(np.dot(Sdg, S))  # (S^*.W^*.W.S)^-1

    # linear inversion of freqs
    ret = devectorize(np.dot(inv, np.dot(Sdg, v)))
    # renormalize to input trace value
    if trace is not None:
        ret = trace * ret / np.trace(ret)
    return ret

Response: Reconstruct a matrix through linear inversion of the given freqs and ops.


Instruction:
Create a Python 3 function for
returning the nearest positive semidefinite operator to an operator. This method is based on reference [1]. It constrains positivity by setting negative eigenvalues to zero and rescaling the positive eigenvalues. Args: rho (array_like): the input operator. epsilon(float or None): threshold (>=0) for truncating small eigenvalues values to zero. Returns: numpy.array: A positive semidefinite numpy array.

Response:
def __wizard(rho, epsilon=None):
    """
    Returns the nearest positive semidefinite operator to an operator.

    This method is based on reference [1]. It constrains positivity
    by setting negative eigenvalues to zero and rescaling the positive
    eigenvalues.

    Args:
        rho (array_like): the input operator.
        epsilon(float or None): threshold (>=0) for truncating small
            eigenvalues values to zero.

    Returns:
        numpy.array: A positive semidefinite numpy array.
    """
    if epsilon is None:
        epsilon = 0.  # default value

    dim = len(rho)
    rho_wizard = np.zeros([dim, dim])
    v, w = np.linalg.eigh(rho)  # v eigenvecrors v[0] < v[1] <...
    for j in range(dim):
        if v[j] < epsilon:
            tmp = v[j]
            v[j] = 0.
            # redistribute loop
            x = 0.
            for k in range(j + 1, dim):
                x += tmp / (dim - (j + 1))
                v[k] = v[k] + tmp / (dim - (j + 1))
    for j in range(dim):
        rho_wizard = rho_wizard + v[j] * outer(w[:, j])
    return rho_wizard


Instruction:
Write a Python 3 script to
build the list of circuits to rotate to points in phase space.

Response:
def build_wigner_circuits(circuit, phis, thetas, qubits,
                          qreg, creg):
    """Create the circuits to rotate to points in phase space
    Args:
        circuit (QuantumCircuit): The circuit to be appended with tomography
                                  state preparation and/or measurements.
        phis (np.matrix[[complex]]): phis
        thetas (np.matrix[[complex]]): thetas
        qubits (list[int]): a list of the qubit indexes of qreg to be measured.
        qreg (QuantumRegister): the quantum register containing qubits to be
                                measured.
        creg (ClassicalRegister): the classical register containing bits to
                                    store measurement outcomes.

    Returns:
        list: A list of names of the added wigner function circuits.

    Raises:
        QiskitError: if circuit is not a valid QuantumCircuit.
    """

    if not isinstance(circuit, QuantumCircuit):
        raise QiskitError('Input circuit must be a QuantumCircuit object')

    tomography_circuits = []
    points = len(phis[0])
    for point in range(points):
        label = '_wigner_phase_point'
        label += str(point)
        tmp_circ = QuantumCircuit(qreg, creg, name=label)
        for qubit, _ in enumerate(qubits):
            tmp_circ.u3(thetas[qubit][point], 0,
                        phis[qubit][point], qreg[qubits[qubit]])
            tmp_circ.measure(qreg[qubits[qubit]], creg[qubits[qubit]])
        # Add to original circuit
        tmp_circ = circuit + tmp_circ
        tmp_circ.name = circuit.name + label
        tomography_circuits.append(tmp_circ)

    logger.info('>> Created Wigner function circuits for "%s"', circuit.name)
    return tomography_circuits


Instruction:
Create a Python 3 function to
get the value of the Wigner function at measured points in the state tomography.

Response:
def wigner_data(q_result, meas_qubits, labels, shots=None):
    """Get the value of the Wigner function from measurement results.

    Args:
        q_result (Result): Results from execution of a state tomography
                            circuits on a backend.
        meas_qubits (list[int]): a list of the qubit indexes measured.
        labels (list[str]): a list of names of the circuits
        shots (int): number of shots

    Returns:
        list: The values of the Wigner function at measured points in
            phase space
    """
    num = len(meas_qubits)

    dim = 2**num
    p = [0.5 + 0.5 * np.sqrt(3), 0.5 - 0.5 * np.sqrt(3)]
    parity = 1

    for i in range(num):
        parity = np.kron(parity, p)

    w = [0] * len(labels)
    wpt = 0
    counts = [marginal_counts(q_result.get_counts(circ), meas_qubits)
              for circ in labels]
    for entry in counts:
        x = [0] * dim

        for i in range(dim):
            if bin(i)[2:].zfill(num) in entry:
                x[i] = float(entry[bin(i)[2:].zfill(num)])

        if shots is None:
            shots = np.sum(x)

        for i in range(dim):
            w[wpt] = w[wpt] + (x[i] / shots) * parity[i]
        wpt += 1

    return w


Instruction:
Implement a function in Python 3 to
add state preparation gates to a circuit.

Response:
def prep_gate(self, circuit, qreg, op):
        """
        Add state preparation gates to a circuit.

        Args:
            circuit (QuantumCircuit): circuit to add a preparation to.
            qreg (tuple(QuantumRegister,int)): quantum register to apply
            preparation to.
            op (tuple(str, int)): the basis label and index for the
            preparation op.
        """
        if self.prep_fun is None:
            pass
        else:
            self.prep_fun(circuit, qreg, op)


Instruction:
Make a summary of the following Python 3 code
def meas_gate(self, circuit, qreg, op):
        if self.meas_fun is None:
            pass
        else:
            self.meas_fun(circuit, qreg, op)

Response: Add measurement gates to a circuit.


Instruction:
Can you generate the documentation for the following Python 3 function
def _text_checker(job, interval, _interval_set=False, quiet=False, output=sys.stdout):
    status = job.status()
    msg = status.value
    prev_msg = msg
    msg_len = len(msg)

    if not quiet:
        print('\r%s: %s' % ('Job Status', msg), end='', file=output)
    while status.name not in ['DONE', 'CANCELLED', 'ERROR']:
        time.sleep(interval)
        status = job.status()
        msg = status.value

        if status.name == 'QUEUED':
            msg += ' (%s)' % job.queue_position()
            if not _interval_set:
                interval = max(job.queue_position(), 2)
        else:
            if not _interval_set:
                interval = 2

        # Adjust length of message so there are no artifacts
        if len(msg) < msg_len:
            msg += ' ' * (msg_len - len(msg))
        elif len(msg) > msg_len:
            msg_len = len(msg)

        if msg != prev_msg and not quiet:
            print('\r%s: %s' % ('Job Status', msg), end='', file=output)
            prev_msg = msg
    if not quiet:
        print('', file=output)

Response: A text - based job status checker.


Instruction:
Implement a function in Python 3 to
monitor the status of a Jupyter notebook.

Response:
def job_monitor(job, interval=None, monitor_async=False, quiet=False, output=sys.stdout):
    """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).
        quiet (bool): If True, do not print status messages.
        output (file): The file like object to write status messages to.
        By default this is sys.stdout.

    Raises:
        QiskitError: When trying to run async outside of Jupyter
        ImportError: ipywidgets not available for notebook.
    """
    if interval is None:
        _interval_set = False
        interval = 2
    else:
        _interval_set = True
    if _NOTEBOOK_ENV:
        if monitor_async:
            try:
                import ipywidgets as widgets  # pylint: disable=import-error
            except ImportError:
                raise ImportError('These functions  need ipywidgets. '
                                  'Run "pip install ipywidgets" before.')
            from qiskit.tools.jupyter.jupyter_magics import _html_checker  # pylint: disable=C0412

            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)

            thread = threading.Thread(target=_html_checker, args=(job, interval,
                                                                  status, header))
            thread.start()
        else:
            _text_checker(job, interval, _interval_set,
                          quiet=quiet, output=output)

    else:
        if monitor_async:
            raise QiskitError(
                'monitor_async only available in Jupyter notebooks.')
        _text_checker(job, interval, _interval_set, quiet=quiet, output=output)


Instruction:
Write a Python 3 function that can
compute the Euler angles for a single - qubit gate.

Response:
def euler_angles_1q(unitary_matrix):
    """Compute Euler angles for a single-qubit gate.

    Find angles (theta, phi, lambda) such that
    unitary_matrix = phase * Rz(phi) * Ry(theta) * Rz(lambda)

    Args:
        unitary_matrix (ndarray): 2x2 unitary matrix

    Returns:
        tuple: (theta, phi, lambda) Euler angles of SU(2)

    Raises:
        QiskitError: if unitary_matrix not 2x2, or failure
    """
    if unitary_matrix.shape != (2, 2):
        raise QiskitError("euler_angles_1q: expected 2x2 matrix")
    phase = la.det(unitary_matrix)**(-1.0/2.0)
    U = phase * unitary_matrix  # U in SU(2)
    # OpenQASM SU(2) parameterization:
    # U[0, 0] = exp(-i(phi+lambda)/2) * cos(theta/2)
    # U[0, 1] = -exp(-i(phi-lambda)/2) * sin(theta/2)
    # U[1, 0] = exp(i(phi-lambda)/2) * sin(theta/2)
    # U[1, 1] = exp(i(phi+lambda)/2) * cos(theta/2)
    # Find theta
    if abs(U[0, 0]) > _CUTOFF_PRECISION:
        theta = 2 * math.acos(abs(U[0, 0]))
    else:
        theta = 2 * math.asin(abs(U[1, 0]))
    # Find phi and lambda
    phase11 = 0.0
    phase10 = 0.0
    if abs(math.cos(theta/2.0)) > _CUTOFF_PRECISION:
        phase11 = U[1, 1] / math.cos(theta/2.0)
    if abs(math.sin(theta/2.0)) > _CUTOFF_PRECISION:
        phase10 = U[1, 0] / math.sin(theta/2.0)
    phiplambda = 2 * math.atan2(np.imag(phase11), np.real(phase11))
    phimlambda = 2 * math.atan2(np.imag(phase10), np.real(phase10))
    phi = 0.0
    if abs(U[0, 0]) > _CUTOFF_PRECISION and abs(U[1, 0]) > _CUTOFF_PRECISION:
        phi = (phiplambda + phimlambda) / 2.0
        lamb = (phiplambda - phimlambda) / 2.0
    else:
        if abs(U[0, 0]) < _CUTOFF_PRECISION:
            lamb = -phimlambda
        else:
            lamb = phiplambda
    # Check the solution
    Rzphi = np.array([[np.exp(-1j*phi/2.0), 0],
                      [0, np.exp(1j*phi/2.0)]], dtype=complex)
    Rytheta = np.array([[np.cos(theta/2.0), -np.sin(theta/2.0)],
                        [np.sin(theta/2.0), np.cos(theta/2.0)]], dtype=complex)
    Rzlambda = np.array([[np.exp(-1j*lamb/2.0), 0],
                         [0, np.exp(1j*lamb/2.0)]], dtype=complex)
    V = np.dot(Rzphi, np.dot(Rytheta, Rzlambda))
    if la.norm(V - U) > _CUTOFF_PRECISION:
        raise QiskitError("euler_angles_1q: incorrect result")
    return theta, phi, lamb


Instruction:
Write a Python 3 script to
simplify a general U gate.

Response:
def simplify_U(theta, phi, lam):
    """Return the gate u1, u2, or u3 implementing U with the fewest pulses.

    The returned gate implements U exactly, not up to a global phase.

    Args:
        theta, phi, lam: input Euler rotation angles for a general U gate

    Returns:
        Gate: one of IdGate, U1Gate, U2Gate, U3Gate.
    """
    gate = U3Gate(theta, phi, lam)
    # Y rotation is 0 mod 2*pi, so the gate is a u1
    if abs(gate.params[0] % (2.0 * math.pi)) < _CUTOFF_PRECISION:
        gate = U1Gate(gate.params[0] + gate.params[1] + gate.params[2])
    # Y rotation is pi/2 or -pi/2 mod 2*pi, so the gate is a u2
    if isinstance(gate, U3Gate):
        # theta = pi/2 + 2*k*pi
        if abs((gate.params[0] - math.pi / 2) % (2.0 * math.pi)) < _CUTOFF_PRECISION:
            gate = U2Gate(gate.params[1],
                          gate.params[2] + (gate.params[0] - math.pi / 2))
        # theta = -pi/2 + 2*k*pi
        if abs((gate.params[0] + math.pi / 2) % (2.0 * math.pi)) < _CUTOFF_PRECISION:
            gate = U2Gate(gate.params[1] + math.pi,
                          gate.params[2] - math.pi + (gate.params[0] + math.pi / 2))
    # u1 and lambda is 0 mod 4*pi so gate is nop
    if isinstance(gate, U1Gate) and abs(gate.params[0] % (4.0 * math.pi)) < _CUTOFF_PRECISION:
        gate = IdGate()
    return gate


Instruction:
Can you tell what is the following Python 3 function doing
def two_qubit_kak(unitary):
    if hasattr(unitary, 'to_operator'):
        # If input is a BaseOperator subclass this attempts to convert
        # the object to an Operator so that we can extract the underlying
        # numpy matrix from `Operator.data`.
        unitary = unitary.to_operator().data
    if hasattr(unitary, 'to_matrix'):
        # If input is Gate subclass or some other class object that has
        # a to_matrix method this will call that method.
        unitary = unitary.to_matrix()
    # Convert to numpy array incase not already an array
    unitary_matrix = np.array(unitary, dtype=complex)
    # Check input is a 2-qubit unitary
    if unitary_matrix.shape != (4, 4):
        raise QiskitError("two_qubit_kak: Expected 4x4 matrix")
    if not is_unitary_matrix(unitary_matrix):
        raise QiskitError("Input matrix is not unitary.")
    phase = la.det(unitary_matrix)**(-1.0/4.0)
    # Make it in SU(4), correct phase at the end
    U = phase * unitary_matrix
    # B changes to the Bell basis
    B = (1.0/math.sqrt(2)) * np.array([[1, 1j, 0, 0],
                                       [0, 0, 1j, 1],
                                       [0, 0, 1j, -1],
                                       [1, -1j, 0, 0]], dtype=complex)

    # We also need B.conj().T below
    Bdag = B.conj().T
    # U' = Bdag . U . B
    Uprime = Bdag.dot(U.dot(B))
    # M^2 = trans(U') . U'
    M2 = Uprime.T.dot(Uprime)

    # Diagonalize M2
    # Must use diagonalization routine which finds a real orthogonal matrix P
    # when M2 is real.
    D, P = la.eig(M2)
    D = np.diag(D)
    # If det(P) == -1 then in O(4), apply a swap to make P in SO(4)
    if abs(la.det(P)+1) < 1e-5:
        swap = np.array([[1, 0, 0, 0],
                         [0, 0, 1, 0],
                         [0, 1, 0, 0],
                         [0, 0, 0, 1]], dtype=complex)
        P = P.dot(swap)
        D = swap.dot(D.dot(swap))

    Q = np.sqrt(D)  # array from elementwise sqrt
    # Want to take square root so that Q has determinant 1
    if abs(la.det(Q)+1) < 1e-5:
        Q[0, 0] = -Q[0, 0]

    # Q^-1*P.T = P' -> QP' = P.T (solve for P' using Ax=b)
    Pprime = la.solve(Q, P.T)
    # K' now just U' * P * P'
    Kprime = Uprime.dot(P.dot(Pprime))

    K1 = B.dot(Kprime.dot(P.dot(Bdag)))
    A = B.dot(Q.dot(Bdag))
    K2 = B.dot(P.T.dot(Bdag))
    # KAK = K1 * A * K2
    KAK = K1.dot(A.dot(K2))

    # Verify decomp matches input unitary.
    if la.norm(KAK - U) > 1e-6:
        raise QiskitError("two_qubit_kak: KAK decomposition " +
                          "does not return input unitary.")

    # Compute parameters alpha, beta, gamma so that
    # A = exp(i * (alpha * XX + beta * YY + gamma * ZZ))
    xx = np.array([[0, 0, 0, 1],
                   [0, 0, 1, 0],
                   [0, 1, 0, 0],
                   [1, 0, 0, 0]], dtype=complex)

    yy = np.array([[0, 0, 0, -1],
                   [0, 0, 1, 0],
                   [0, 1, 0, 0],
                   [-1, 0, 0, 0]], dtype=complex)

    zz = np.array([[1, 0, 0, 0],
                   [0, -1, 0, 0],
                   [0, 0, -1, 0],
                   [0, 0, 0, 1]], dtype=complex)

    A_real_tr = A.real.trace()
    alpha = math.atan2(A.dot(xx).imag.trace(), A_real_tr)
    beta = math.atan2(A.dot(yy).imag.trace(), A_real_tr)
    gamma = math.atan2(A.dot(zz).imag.trace(), A_real_tr)

    # K1 = kron(U1, U2) and K2 = kron(V1, V2)
    # Find the matrices U1, U2, V1, V2

    # Find a block in K1 where U1_ij * [U2] is not zero
    L = K1[0:2, 0:2]
    if la.norm(L) < 1e-9:
        L = K1[0:2, 2:4]
        if la.norm(L) < 1e-9:
            L = K1[2:4, 2:4]
    # Remove the U1_ij prefactor
    Q = L.dot(L.conj().T)
    U2 = L / math.sqrt(Q[0, 0].real)

    # Now grab U1 given we know U2
    R = K1.dot(np.kron(np.identity(2), U2.conj().T))
    U1 = np.zeros((2, 2), dtype=complex)
    U1[0, 0] = R[0, 0]
    U1[0, 1] = R[0, 2]
    U1[1, 0] = R[2, 0]
    U1[1, 1] = R[2, 2]

    # Repeat K1 routine for K2
    L = K2[0:2, 0:2]
    if la.norm(L) < 1e-9:
        L = K2[0:2, 2:4]
        if la.norm(L) < 1e-9:
            L = K2[2:4, 2:4]
    Q = np.dot(L, np.transpose(L.conjugate()))
    V2 = L / np.sqrt(Q[0, 0])
    R = np.dot(K2, np.kron(np.identity(2), np.transpose(V2.conjugate())))

    V1 = np.zeros_like(U1)
    V1[0, 0] = R[0, 0]
    V1[0, 1] = R[0, 2]
    V1[1, 0] = R[2, 0]
    V1[1, 1] = R[2, 2]

    if la.norm(np.kron(U1, U2) - K1) > 1e-4:
        raise QiskitError("two_qubit_kak: K1 != U1 x U2")
    if la.norm(np.kron(V1, V2) - K2) > 1e-4:
        raise QiskitError("two_qubit_kak: K2 != V1 x V2")

    test = la.expm(1j*(alpha * xx + beta * yy + gamma * zz))
    if la.norm(A - test) > 1e-4:
        raise QiskitError("two_qubit_kak: " +
                          "Matrix A does not match xx,yy,zz decomposition.")

    # Circuit that implements K1 * A * K2 (up to phase), using
    # Vatan and Williams Fig. 6 of quant-ph/0308006v3
    # Include prefix and suffix single-qubit gates into U2, V1 respectively.

    V2 = np.array([[np.exp(1j*np.pi/4), 0],
                   [0, np.exp(-1j*np.pi/4)]], dtype=complex).dot(V2)
    U1 = U1.dot(np.array([[np.exp(-1j*np.pi/4), 0],
                          [0, np.exp(1j*np.pi/4)]], dtype=complex))

    # Corrects global phase: exp(ipi/4)*phase'
    U1 = U1.dot(np.array([[np.exp(1j*np.pi/4), 0],
                          [0, np.exp(1j*np.pi/4)]], dtype=complex))
    U1 = phase.conjugate() * U1

    # Test
    g1 = np.kron(V1, V2)
    g2 = np.array([[1, 0, 0, 0],
                   [0, 0, 0, 1],
                   [0, 0, 1, 0],
                   [0, 1, 0, 0]], dtype=complex)

    theta = 2*gamma - np.pi/2

    Ztheta = np.array([[np.exp(1j*theta/2), 0],
                       [0, np.exp(-1j*theta/2)]], dtype=complex)

    kappa = np.pi/2 - 2*alpha
    Ykappa = np.array([[math.cos(kappa/2), math.sin(kappa/2)],
                       [-math.sin(kappa/2), math.cos(kappa/2)]], dtype=complex)
    g3 = np.kron(Ztheta, Ykappa)
    g4 = np.array([[1, 0, 0, 0],
                   [0, 1, 0, 0],
                   [0, 0, 0, 1],
                   [0, 0, 1, 0]], dtype=complex)

    zeta = 2*beta - np.pi/2
    Yzeta = np.array([[math.cos(zeta/2), math.sin(zeta/2)],
                      [-math.sin(zeta/2), math.cos(zeta/2)]], dtype=complex)
    g5 = np.kron(np.identity(2), Yzeta)
    g6 = g2
    g7 = np.kron(U1, U2)

    V = g2.dot(g1)
    V = g3.dot(V)
    V = g4.dot(V)
    V = g5.dot(V)
    V = g6.dot(V)
    V = g7.dot(V)

    if la.norm(V - U*phase.conjugate()) > 1e-6:
        raise QiskitError("two_qubit_kak: " +
                          "sequence incorrect, unknown error")

    v1_param = euler_angles_1q(V1)
    v2_param = euler_angles_1q(V2)
    u1_param = euler_angles_1q(U1)
    u2_param = euler_angles_1q(U2)

    v1_gate = U3Gate(v1_param[0], v1_param[1], v1_param[2])
    v2_gate = U3Gate(v2_param[0], v2_param[1], v2_param[2])
    u1_gate = U3Gate(u1_param[0], u1_param[1], u1_param[2])
    u2_gate = U3Gate(u2_param[0], u2_param[1], u2_param[2])

    q = QuantumRegister(2)
    return_circuit = QuantumCircuit(q)

    return_circuit.append(v1_gate, [q[1]])

    return_circuit.append(v2_gate, [q[0]])

    return_circuit.append(CnotGate(), [q[0], q[1]])

    gate = U3Gate(0.0, 0.0, -2.0*gamma + np.pi/2.0)
    return_circuit.append(gate, [q[1]])

    gate = U3Gate(-np.pi/2.0 + 2.0*alpha, 0.0, 0.0)
    return_circuit.append(gate, [q[0]])

    return_circuit.append(CnotGate(), [q[1], q[0]])

    gate = U3Gate(-2.0*beta + np.pi/2.0, 0.0, 0.0)
    return_circuit.append(gate, [q[0]])

    return_circuit.append(CnotGate(), [q[0], q[1]])

    return_circuit.append(u1_gate, [q[1]])

    return_circuit.append(u2_gate, [q[0]])

    return return_circuit

Response: Decomposes a two - qubit gate over SU ( 2 + CNOT using the KAK decomposition.


Instruction:
How would you code a function in Python 3 to
extend a DAG with virtual qubits that are not in the circuit yet.

Response:
def run(self, dag):
        """
        Extends dag with virtual qubits that are in layout but not in the circuit yet.

        Args:
            dag (DAGCircuit): DAG to extend.

        Returns:
            DAGCircuit: An extended DAG.

        Raises:
            TranspilerError: If there is not layout in the property set or not set at init time.
        """
        self.layout = self.layout or self.property_set['layout']

        if self.layout is None:
            raise TranspilerError("EnlargeWithAncilla requires property_set[\"layout\"] or"
                                  " \"layout\" parameter to run")

        layout_virtual_qubits = self.layout.get_virtual_bits().keys()
        new_qregs = set(virtual_qubit[0] for virtual_qubit in layout_virtual_qubits
                        if virtual_qubit not in dag.wires)

        for qreg in new_qregs:
            dag.add_qreg(qreg)

        return dag


Instruction:
Implement a Python 3 function for
defining the class entry.

Response:
def _define(self):
        """
        gate ch a,b {
        h b;
        sdg b;
        cx a,b;
        h b;
        t b;
        cx a,b;
        t b;
        h b;
        s b;
        x b;
        s a;}
        """
        definition = []
        q = QuantumRegister(2, "q")
        rule = [
            (HGate(), [q[1]], []),
            (SdgGate(), [q[1]], []),
            (CnotGate(), [q[0], q[1]], []),
            (HGate(), [q[1]], []),
            (TGate(), [q[1]], []),
            (CnotGate(), [q[0], q[1]], []),
            (TGate(), [q[1]], []),
            (HGate(), [q[1]], []),
            (SGate(), [q[1]], []),
            (XGate(), [q[1]], []),
            (SGate(), [q[0]], [])
        ]
        for inst in rule:
            definition.append(inst)
        self.definition = definition


Instruction:
Can you generate a brief explanation for the following Python 3 code
def config_tab(backend):
    status = backend.status().to_dict()
    config = backend.configuration().to_dict()

    config_dict = {**status, **config}

    upper_list = ['n_qubits', 'operational',
                  'status_msg', 'pending_jobs',
                  'basis_gates', 'local', 'simulator']

    lower_list = list(set(config_dict.keys()).difference(upper_list))
    # Remove gates because they are in a different tab
    lower_list.remove('gates')
    upper_str = "
"
    upper_str += """"""

    footer = "
"

    # Upper HBox widget data

    upper_str += "
Property	Value
"
    for key in upper_list:
        upper_str += "
%s	%s
" % (
            key, config_dict[key])
    upper_str += footer

    upper_table = widgets.HTML(
        value=upper_str, layout=widgets.Layout(width='100%', grid_area='left'))

    image_widget = widgets.Output(
        layout=widgets.Layout(display='flex-inline', grid_area='right',
                              padding='10px 10px 10px 10px',
                              width='auto', max_height='300px',
                              align_items='center'))

    if not config['simulator']:
        with image_widget:
            gate_map = plot_gate_map(backend)
            display(gate_map)
        plt.close(gate_map)

    lower_str = "
"
    lower_str += """"""
    lower_str += "

"
    for key in lower_list:
        if key != 'name':
            lower_str += "
%s	%s
" % (
                key, config_dict[key])
    lower_str += footer

    lower_table = widgets.HTML(value=lower_str,
                               layout=widgets.Layout(
                                   width='auto',
                                   grid_area='bottom'))

    grid = widgets.GridBox(children=[upper_table, image_widget, lower_table],
                           layout=widgets.Layout(
                               grid_template_rows='auto auto',
                               grid_template_columns='25% 25% 25% 25%',
                               grid_template_areas='''
                               "left right right right"
                               "bottom bottom bottom bottom"
                               ''',
                               grid_gap='0px 0px'))

    return grid

Response: A function that creates a new configuration tab.