def _create_program_graph(self, dag):
        """
        Program graph has virtual qubits as nodes.
        Two nodes have an edge if the corresponding virtual qubits
        participate in a 2-qubit gate. The edge is weighted by the
        number of CNOTs between the pair.
        """
        idx = 0
        for q in dag.qubits():
            self.qarg_to_id[q[0].name + str(q[1])] = idx
            idx += 1
        for gate in dag.twoQ_gates():
            qid1 = self._qarg_to_id(gate.qargs[0])
            qid2 = self._qarg_to_id(gate.qargs[1])
            min_q = min(qid1, qid2)
            max_q = max(qid1, qid2)
            edge_weight = 1
            if self.prog_graph.has_edge(min_q, max_q):
                edge_weight = self.prog_graph[min_q][max_q]['weight'] + 1
            self.prog_graph.add_edge(min_q, max_q, weight=edge_weight)
        return idx

def _create_program_graph ( self , dag ) : idx = 0 for q in dag . qubits ( ) : self . qarg_to_id [ q [ 0 ] . name + str ( q [ 1 ] ) ] = idx idx += 1 for gate in dag . twoQ_gates ( ) : qid1 = self . _qarg_to_id ( gate . qargs [ 0 ] ) qid2 = self . _qarg_to_id ( gate . qargs [ 1 ] ) min_q = min ( qid1 , qid2 ) max_q = max ( qid1 , qid2 ) edge_weight = 1 if self . prog_graph . has_edge ( min_q , max_q ) : edge_weight = self . prog_graph [ min_q ] [ max_q ] [ 'weight' ] + 1 self . prog_graph . add_edge ( min_q , max_q , weight = edge_weight ) return idx

Program graph has virtual qubits as nodes . Two nodes have an edge if the corresponding virtual qubits participate in a 2 - qubit gate . The edge is weighted by the number of CNOTs between the pair .


def _select_next_edge(self):
        """
        If there is an edge with one endpoint mapped, return it.
        Else return in the first edge
        """
        for edge in self.pending_program_edges:
            q1_mapped = edge[0] in self.prog2hw
            q2_mapped = edge[1] in self.prog2hw
            assert not (q1_mapped and q2_mapped)
            if q1_mapped or q2_mapped:
                return edge
        return self.pending_program_edges[0]

def _select_next_edge ( self ) : for edge in self . pending_program_edges : q1_mapped = edge [ 0 ] in self . prog2hw q2_mapped = edge [ 1 ] in self . prog2hw assert not ( q1_mapped and q2_mapped ) if q1_mapped or q2_mapped : return edge return self . pending_program_edges [ 0 ]

If there is an edge with one endpoint mapped return it . Else return in the first edge


def _select_best_remaining_cx(self):
        """
        Select best remaining CNOT in the hardware for the next program edge.
        """
        candidates = []
        for gate in self.gate_list:
            chk1 = gate[0] in self.available_hw_qubits
            chk2 = gate[1] in self.available_hw_qubits
            if chk1 and chk2:
                candidates.append(gate)
        best_reliab = 0
        best_item = None
        for item in candidates:
            if self.gate_cost[item] > best_reliab:
                best_reliab = self.gate_cost[item]
                best_item = item
        return best_item

def _select_best_remaining_cx ( self ) : candidates = [ ] for gate in self . gate_list : chk1 = gate [ 0 ] in self . available_hw_qubits chk2 = gate [ 1 ] in self . available_hw_qubits if chk1 and chk2 : candidates . append ( gate ) best_reliab = 0 best_item = None for item in candidates : if self . gate_cost [ item ] > best_reliab : best_reliab = self . gate_cost [ item ] best_item = item return best_item

Select best remaining CNOT in the hardware for the next program edge .


def _select_best_remaining_qubit(self, prog_qubit):
        """
        Select the best remaining hardware qubit for the next program qubit.
        """
        reliab_store = {}
        for hw_qubit in self.available_hw_qubits:
            reliab = 1
            for n in self.prog_graph.neighbors(prog_qubit):
                if n in self.prog2hw:
                    reliab *= self.swap_costs[self.prog2hw[n]][hw_qubit]
            reliab *= self.readout_errors[hw_qubit]
            reliab_store[hw_qubit] = reliab
        max_reliab = 0
        best_hw_qubit = None
        for hw_qubit in reliab_store:
            if reliab_store[hw_qubit] > max_reliab:
                max_reliab = reliab_store[hw_qubit]
                best_hw_qubit = hw_qubit
        return best_hw_qubit

def _select_best_remaining_qubit ( self , prog_qubit ) : reliab_store = { } for hw_qubit in self . available_hw_qubits : reliab = 1 for n in self . prog_graph . neighbors ( prog_qubit ) : if n in self . prog2hw : reliab *= self . swap_costs [ self . prog2hw [ n ] ] [ hw_qubit ] reliab *= self . readout_errors [ hw_qubit ] reliab_store [ hw_qubit ] = reliab max_reliab = 0 best_hw_qubit = None for hw_qubit in reliab_store : if reliab_store [ hw_qubit ] > max_reliab : max_reliab = reliab_store [ hw_qubit ] best_hw_qubit = hw_qubit return best_hw_qubit

Select the best remaining hardware qubit for the next program qubit .


def run(self, dag):
        """Main run method for the noise adaptive layout."""
        self._initialize_backend_prop()
        num_qubits = self._create_program_graph(dag)
        if num_qubits > len(self.swap_graph):
            raise TranspilerError('Number of qubits greater than device.')
        for end1, end2, _ in sorted(self.prog_graph.edges(data=True),
                                    key=lambda x: x[2]['weight'], reverse=True):
            self.pending_program_edges.append((end1, end2))
        while self.pending_program_edges:
            edge = self._select_next_edge()
            q1_mapped = edge[0] in self.prog2hw
            q2_mapped = edge[1] in self.prog2hw
            if (not q1_mapped) and (not q2_mapped):
                best_hw_edge = self._select_best_remaining_cx()
                self.prog2hw[edge[0]] = best_hw_edge[0]
                self.prog2hw[edge[1]] = best_hw_edge[1]
                self.available_hw_qubits.remove(best_hw_edge[0])
                self.available_hw_qubits.remove(best_hw_edge[1])
            elif not q1_mapped:
                best_hw_qubit = self._select_best_remaining_qubit(edge[0])
                self.prog2hw[edge[0]] = best_hw_qubit
                self.available_hw_qubits.remove(best_hw_qubit)
            else:
                best_hw_qubit = self._select_best_remaining_qubit(edge[1])
                self.prog2hw[edge[1]] = best_hw_qubit
                self.available_hw_qubits.remove(best_hw_qubit)
            new_edges = [x for x in self.pending_program_edges
                         if not (x[0] in self.prog2hw and x[1] in self.prog2hw)]
            self.pending_program_edges = new_edges
        for qid in self.qarg_to_id.values():
            if qid not in self.prog2hw:
                self.prog2hw[qid] = self.available_hw_qubits[0]
                self.available_hw_qubits.remove(self.prog2hw[qid])
        layout = Layout()
        for q in dag.qubits():
            pid = self._qarg_to_id(q)
            hwid = self.prog2hw[pid]
            layout[(q[0], q[1])] = hwid
        self.property_set['layout'] = layout

def
run
(
self
,
dag
)
:
self
.
_initialize_backend_prop
(
)
num_qubits
=
self
.
_create_program_graph
(
dag
)
if
num_qubits
>
len
(
self
.
swap_graph
)
:
raise
TranspilerError
(
'Number of qubits greater than device.'
)
for
end1
,
end2
,
_
in
sorted
(
self
.
prog_graph
.
edges
(
data
=
True
)
,
key
=
lambda
x
:
x
[
2
]
[
'weight'
]
,
reverse
=
True
)
:
self
.
pending_program_edges
.
append
(
(
end1
,
end2
)
)
while
self
.
pending_program_edges
:
edge
=
self
.
_select_next_edge
(
)
q1_mapped
=
edge
[
0
]
in
self
.
prog2hw
q2_mapped
=
edge
[
1
]
in
self
.
prog2hw
if
(
not
q1_mapped
)
and
(
not
q2_mapped
)
:
best_hw_edge
=
self
.
_select_best_remaining_cx
(
)
self
.
prog2hw
[
edge
[
0
]
]
=
best_hw_edge
[
0
]
self
.
prog2hw
[
edge
[
1
]
]
=
best_hw_edge
[
1
]
self
.
available_hw_qubits
.
remove
(
best_hw_edge
[
0
]
)
self
.
available_hw_qubits
.
remove
(
best_hw_edge
[
1
]
)
elif
not
q1_mapped
:
best_hw_qubit
=
self
.
_select_best_remaining_qubit
(
edge
[
0
]
)
self
.
prog2hw
[
edge
[
0
]
]
=
best_hw_qubit
self
.
available_hw_qubits
.
remove
(
best_hw_qubit
)
else
:
best_hw_qubit
=
self
.
_select_best_remaining_qubit
(
edge
[
1
]
)
self
.
prog2hw
[
edge
[
1
]
]
=
best_hw_qubit
self
.
available_hw_qubits
.
remove
(
best_hw_qubit
)
new_edges
=
[
x
for
x
in
self
.
pending_program_edges
if
not
(
x
[
0
]
in
self
.
prog2hw
and
x
[
1
]
in
self
.
prog2hw
)
]
self
.
pending_program_edges
=
new_edges
for
qid
in
self
.
qarg_to_id
.
values
(
)
:
if
qid
not
in
self
.
prog2hw
:
self
.
prog2hw
[
qid
]
=
self
.
available_hw_qubits
[
0
]
self
.
available_hw_qubits
.
remove
(
self
.
prog2hw
[
qid
]
)
layout
=
Layout
(
)
for
q
in
dag
.
qubits
(
)
:
pid
=
self
.
_qarg_to_id
(
q
)
hwid
=
self
.
prog2hw
[
pid
]
layout
[
(
q
[
0
]
,
q
[
1
]
)
]
=
hwid
self
.
property_set
[
'layout'
]
=
layout

Main run method for the noise adaptive layout .


def instruction_list(self):
        """Return a list of instructions for this CompositeGate.

        If the CompositeGate itself contains composites, call
        this method recursively.
        """
        instruction_list = []
        for instruction in self.data:
            if isinstance(instruction, CompositeGate):
                instruction_list.extend(instruction.instruction_list())
            else:
                instruction_list.append(instruction)
        return instruction_list

def instruction_list ( self ) : instruction_list = [ ] for instruction in self . data : if isinstance ( instruction , CompositeGate ) : instruction_list . extend ( instruction . instruction_list ( ) ) else : instruction_list . append ( instruction ) return instruction_list

Return a list of instructions for this CompositeGate .


def inverse(self):
        """Invert this gate."""
        self.data = [gate.inverse() for gate in reversed(self.data)]
        self.inverse_flag = not self.inverse_flag
        return self

def inverse ( self ) : self . data = [ gate . inverse ( ) for gate in reversed ( self . data ) ] self . inverse_flag = not self . inverse_flag return self


def q_if(self, *qregs):
        """Add controls to this gate."""
        self.data = [gate.q_if(qregs) for gate in self.data]
        return self

def q_if ( self , * qregs ) : self . data = [ gate . q_if ( qregs ) for gate in self . data ] return self


def c_if(self, classical, val):
        """Add classical control register."""
        self.data = [gate.c_if(classical, val) for gate in self.data]
        return self

def c_if ( self , classical , val ) : self . data = [ gate . c_if ( classical , val ) for gate in self . data ] return self


def is_unitary(self, atol=None, rtol=None):
        """Return True if operator is a unitary matrix."""
        if atol is None:
            atol = self._atol
        if rtol is None:
            rtol = self._rtol
        return is_unitary_matrix(self._data, rtol=rtol, atol=atol)

def is_unitary ( self , atol = None , rtol = None ) : if atol is None : atol = self . _atol if rtol is None : rtol = self . _rtol return is_unitary_matrix ( self . _data , rtol = rtol , atol = atol )

Return True if operator is a unitary matrix .


def conjugate(self):
        """Return the conjugate of the operator."""
        return Operator(
            np.conj(self.data), self.input_dims(), self.output_dims())

def conjugate ( self ) : return Operator ( np . conj ( self . data ) , self . input_dims ( ) , self . output_dims ( ) )


def transpose(self):
        """Return the transpose of the operator."""
        return Operator(
            np.transpose(self.data), self.input_dims(), self.output_dims())

def transpose ( self ) : return Operator ( np . transpose ( self . data ) , self . input_dims ( ) , self . output_dims ( ) )


def power(self, n):
        """Return the matrix power of the operator.

        Args:
            n (int): the power to raise the matrix to.

        Returns:
            BaseOperator: the n-times composed operator.

        Raises:
            QiskitError: if the input and output dimensions of the operator
            are not equal, or the power is not a positive integer.
        """
        if not isinstance(n, int):
            raise QiskitError("Can only take integer powers of Operator.")
        if self.input_dims() != self.output_dims():
            raise QiskitError("Can only power with input_dims = output_dims.")
        # Override base class power so we can implement more efficiently
        # using Numpy.matrix_power
        return Operator(
            np.linalg.matrix_power(self.data, n), self.input_dims(),
            self.output_dims())

Return the matrix power of the operator .


def _shape(self):
        """Return the tensor shape of the matrix operator"""
        return tuple(reversed(self.output_dims())) + tuple(
            reversed(self.input_dims()))

def _shape ( self ) : return tuple ( reversed ( self . output_dims ( ) ) ) + tuple ( reversed ( self . input_dims ( ) ) )


def _instruction_to_operator(cls, instruction):
        """Convert a QuantumCircuit or Instruction to an Operator."""
        # Convert circuit to an instruction
        if isinstance(instruction, QuantumCircuit):
            instruction = instruction.to_instruction()
        # Initialize an identity operator of the correct size of the circuit
        op = Operator(np.eye(2 ** instruction.num_qubits))
        op._append_instruction(instruction)
        return op

Convert a QuantumCircuit or Instruction to an Operator .


def swap_mapper_layer_update(self, i, first_layer, best_layout, best_d,
                                 best_circ, layer_list):
        """Update the QASM string for an iteration of swap_mapper.

        i = layer number
        first_layer = True if this is the first layer with multi-qubit gates
        best_layout = layout returned from swap algorithm
        best_d = depth returned from swap algorithm
        best_circ = swap circuit returned from swap algorithm
        layer_list = list of circuit objects for each layer

        Return DAGCircuit object to append to the output DAGCircuit.
        """
        layout = best_layout
        dagcircuit_output = DAGCircuit()
        QR = QuantumRegister(self.coupling_map.size(), 'q')
        dagcircuit_output.add_qreg(QR)
        # Identity wire-map for composing the circuits
        identity_wire_map = {(QR, j): (QR, j) for j in range(self.coupling_map.size())}

        # If this is the first layer with multi-qubit gates,
        # output all layers up to this point and ignore any
        # swap gates. Set the initial layout.
        if first_layer:
            # Output all layers up to this point
            for j in range(i + 1):
                dagcircuit_output.compose_back(layer_list[j]["graph"], layout)
        # Otherwise, we output the current layer and the associated swap gates.
        else:
            # Output any swaps
            if best_d > 0:
                dagcircuit_output.compose_back(best_circ, identity_wire_map)

            # Output this layer
            dagcircuit_output.compose_back(layer_list[i]["graph"], layout)
        return dagcircuit_output

Update the QASM string for an iteration of swap_mapper .


def _separate_bitstring(bitstring, creg_sizes):
    """Separate a bitstring according to the registers defined in the result header."""
    substrings = []
    running_index = 0
    for _, size in reversed(creg_sizes):
        substrings.append(bitstring[running_index: running_index + size])
        running_index += size
    return ' '.join(substrings)

def
_separate_bitstring
(
bitstring
,
creg_sizes
)
:
substrings
=
[
]
running_index
=
0
for
_
,
size
in
reversed
(
creg_sizes
)
:
substrings
.
append
(
bitstring
[
running_index
:
running_index
+
size
]
)
running_index
+=
size
return
' '
.
join
(
substrings
)

Separate a bitstring according to the registers defined in the result header .


def format_level_0_memory(memory):
    """ Format an experiment result memory object for measurement level 0.

    Args:
        memory (list): Memory from experiment with `meas_level==1`. `avg` or
            `single` will be inferred from shape of result memory.

    Returns:
        np.ndarray: Measurement level 0 complex numpy array

    Raises:
        QiskitError: If the returned numpy array does not have 2 (avg) or 3 (single)
            indicies.
    """
    formatted_memory = _list_to_complex_array(memory)
    # infer meas_return from shape of returned data.
    if not 2 <= len(formatted_memory.shape) <= 3:
        raise QiskitError('Level zero memory is not of correct shape.')
    return formatted_memory

Format an experiment result memory object for measurement level 0 .


def format_level_1_memory(memory):
    """ Format an experiment result memory object for measurement level 1.

    Args:
        memory (list): Memory from experiment with `meas_level==1`. `avg` or
            `single` will be inferred from shape of result memory.

    Returns:
        np.ndarray: Measurement level 1 complex numpy array

    Raises:
        QiskitError: If the returned numpy array does not have 1 (avg) or 2 (single)
            indicies.
    """
    formatted_memory = _list_to_complex_array(memory)
    # infer meas_return from shape of returned data.
    if not 1 <= len(formatted_memory.shape) <= 2:
        raise QiskitError('Level one memory is not of correct shape.')
    return formatted_memory

Format an experiment result memory object for measurement level 1 .


def format_level_2_memory(memory, header=None):
    """ Format an experiment result memory object for measurement level 2.

    Args:
        memory (list): Memory from experiment with `meas_level==2` and `memory==True`.
        header (dict): the experiment header dictionary containing
            useful information for postprocessing.

    Returns:
        list[str]: List of bitstrings
    """
    memory_list = []
    for shot_memory in memory:
        memory_list.append(format_counts_memory(shot_memory, header))
    return memory_list

def format_level_2_memory ( memory , header = None ) : memory_list = [ ] for shot_memory in memory : memory_list . append ( format_counts_memory ( shot_memory , header ) ) return memory_list

Format an experiment result memory object for measurement level 2 .


def format_counts(counts, header=None):
    """Format a single experiment result coming from backend to present
    to the Qiskit user.

    Args:
        counts (dict): counts histogram of multiple shots
        header (dict): the experiment header dictionary containing
            useful information for postprocessing.

    Returns:
        dict: a formatted counts
    """
    counts_dict = {}
    for key, val in counts.items():
        key = format_counts_memory(key, header)
        counts_dict[key] = val
    return counts_dict

def format_counts ( counts , header = None ) : counts_dict = { } for key , val in counts . items ( ) : key = format_counts_memory ( key , header ) counts_dict [ key ] = val return counts_dict

Format a single experiment result coming from backend to present to the Qiskit user .


def format_statevector(vec, decimals=None):
    """Format statevector coming from the backend to present to the Qiskit user.

    Args:
        vec (list): a list of [re, im] complex numbers.
        decimals (int): the number of decimals in the statevector.
            If None, no rounding is done.

    Returns:
        list[complex]: a list of python complex numbers.
    """
    num_basis = len(vec)
    vec_complex = np.zeros(num_basis, dtype=complex)
    for i in range(num_basis):
        vec_complex[i] = vec[i][0] + 1j * vec[i][1]
    if decimals:
        vec_complex = np.around(vec_complex, decimals=decimals)
    return vec_complex

def format_statevector ( vec , decimals = None ) : num_basis = len ( vec ) vec_complex = np . zeros ( num_basis , dtype = complex ) for i in range ( num_basis ) : vec_complex [ i ] = vec [ i ] [ 0 ] + 1j * vec [ i ] [ 1 ] if decimals : vec_complex = np . around ( vec_complex , decimals = decimals ) return vec_complex

Format statevector coming from the backend to present to the Qiskit user .


def format_unitary(mat, decimals=None):
    """Format unitary coming from the backend to present to the Qiskit user.

    Args:
        mat (list[list]): a list of list of [re, im] complex numbers
        decimals (int): the number of decimals in the statevector.
            If None, no rounding is done.

    Returns:
        list[list[complex]]: a matrix of complex numbers
    """
    num_basis = len(mat)
    mat_complex = np.zeros((num_basis, num_basis), dtype=complex)
    for i, vec in enumerate(mat):
        mat_complex[i] = format_statevector(vec, decimals)
    return mat_complex

def format_unitary ( mat , decimals = None ) : num_basis = len ( mat ) mat_complex = np . zeros ( ( num_basis , num_basis ) , dtype = complex ) for i , vec in enumerate ( mat ) : mat_complex [ i ] = format_statevector ( vec , decimals ) return mat_complex

Format unitary coming from the backend to present to the Qiskit user .


def requires_submit(func):
    """
    Decorator to ensure that a submit has been performed before
    calling the method.

    Args:
        func (callable): test function to be decorated.

    Returns:
        callable: the decorated function.
    """
    @functools.wraps(func)
    def _wrapper(self, *args, **kwargs):
        if self._future is None:
            raise JobError("Job not submitted yet!. You have to .submit() first!")
        return func(self, *args, **kwargs)
    return _wrapper

Decorator to ensure that a submit has been performed before calling the method .


def submit(self):
        """Submit the job to the backend for execution.

        Raises:
            QobjValidationError: if the JSON serialization of the Qobj passed
            during construction does not validate against the Qobj schema.

            JobError: if trying to re-submit the job.
        """
        if self._future is not None:
            raise JobError("We have already submitted the job!")

        validate_qobj_against_schema(self._qobj)
        self._future = self._executor.submit(self._fn, self._job_id, self._qobj)

def
submit
(
self
)
:
if
self
.
_future
is
not
:
raise
JobError
(
"We have already submitted the job!"
)
validate_qobj_against_schema
(
self
.
_qobj
)
self
.
_future
=
self
.
_executor
.
submit
(
self
.
_fn
,
self
.
_job_id
,
self
.
_qobj
)

Submit the job to the backend for execution .


def status(self):
        """Gets the status of the job by querying the Python's future

        Returns:
            qiskit.providers.JobStatus: The current JobStatus

        Raises:
            JobError: If the future is in unexpected state
            concurrent.futures.TimeoutError: if timeout occurred.
        """
        # The order is important here
        if self._future.running():
            _status = JobStatus.RUNNING
        elif self._future.cancelled():
            _status = JobStatus.CANCELLED
        elif self._future.done():
            _status = JobStatus.DONE if self._future.exception() is None else JobStatus.ERROR
        else:
            # Note: There is an undocumented Future state: PENDING, that seems to show up when
            # the job is enqueued, waiting for someone to pick it up. We need to deal with this
            # state but there's no public API for it, so we are assuming that if the job is not
            # in any of the previous states, is PENDING, ergo INITIALIZING for us.
            _status = JobStatus.INITIALIZING

        return _status

Gets the status of the job by querying the Python s future


def includes(self, lo_freq: float) -> bool:
        """Whether `lo_freq` is within the `LoRange`.

        Args:
            lo_freq: LO frequency to be checked

        Returns:
            bool: True if lo_freq is included in this range, otherwise False
        """
        if self._lb <= lo_freq <= self._ub:
            return True
        return False

def includes ( self , lo_freq : float ) -> bool : if self . _lb <= lo_freq <= self . _ub : return True return False


def iplot_bloch_multivector(rho, figsize=None):
    """ Create a bloch sphere representation.

        Graphical representation of the input array, using as much bloch
        spheres as qubit are required.

        Args:
            rho (array): State vector or density matrix
            figsize (tuple): Figure size in pixels.
    """

    # HTML
    html_template = Template("""

    """)

    # JavaScript
    javascript_template = Template("""

    """)
    rho = _validate_input_state(rho)
    if figsize is None:
        options = {}
    else:
        options = {'width': figsize[0], 'height': figsize[1]}

    # Process data and execute
    num = int(np.log2(len(rho)))

    bloch_data = []
    for i in range(num):
        pauli_singles = [Pauli.pauli_single(num, i, 'X'), Pauli.pauli_single(num, i, 'Y'),
                         Pauli.pauli_single(num, i, 'Z')]
        bloch_state = list(map(lambda x: np.real(np.trace(np.dot(x.to_matrix(), rho))),
                               pauli_singles))
        bloch_data.append(bloch_state)

    div_number = str(time.time())
    div_number = re.sub('[.]', '', div_number)

    html = html_template.substitute({
        'divNumber': div_number
    })

    javascript = javascript_template.substitute({
        'data': bloch_data,
        'divNumber': div_number,
        'options': options
    })

    display(HTML(html + javascript))

"""
    <script>
        requirejs.config({
            paths: {
                qVisualization: "https://qvisualization.mybluemix.net/q-visualizations"
            }
        });
        data = $data;
        dataValues = [];
        for (var i = 0; i < data.length; i++) {
            // Coordinates
            var x = data[i][0];
            var y = data[i][1];
            var z = data[i][2];
            var point = {'x': x,
                        'y': y,
                        'z': z};
            dataValues.push(point);
        }

        require(["qVisualization"], function(qVisualizations) {
            // Plot figure
            qVisualizations.plotState("bloch_$divNumber",
                                      "bloch",
                                      dataValues,
                                      $options);
        });
    </script>
    """


def get_qubit_los(self, user_lo_config):
        """Embed default qubit LO frequencies from backend and format them to list object.
        If configured lo frequency is the same as default, this method returns `None`.

        Args:
            user_lo_config (LoConfig): A dictionary of LOs to format.

        Returns:
            list: A list of qubit LOs.

        Raises:
            PulseError: when LO frequencies are missing.
        """
        try:
            _q_los = self.default_qubit_los.copy()
        except KeyError:
            raise PulseError('Qubit default frequencies not exist.')

        for channel, lo_freq in user_lo_config.qubit_lo_dict().items():
            _q_los[channel.index] = lo_freq

        if _q_los == self.default_qubit_los:
            return None
        return _q_los

def
get_qubit_los
(
self
,
user_lo_config
)
:
try
:
_q_los
=
self
.
default_qubit_los
.
copy
(
)
except
KeyError
:
raise
PulseError
(
'Qubit default frequencies not exist.'
)
for
channel
,
lo_freq
in
user_lo_config
.
qubit_lo_dict
(
)
.
items
(
)
:
_q_los
[
channel
.
index
]
=
lo_freq
if
_q_los
==
self
.
default_qubit_los
:
return
return
_q_los

Embed default qubit LO frequencies from backend and format them to list object . If configured lo frequency is the same as default this method returns None .


def get_meas_los(self, user_lo_config):
        """Embed default meas LO frequencies from backend and format them to list object.
        If configured lo frequency is the same as default, this method returns `None`.

        Args:
            user_lo_config (LoConfig): A dictionary of LOs to format.

        Returns:
            list: A list of meas LOs.

        Raises:
            PulseError: when LO frequencies are missing.
        """
        try:
            _m_los = self.default_meas_los.copy()
        except KeyError:
            raise PulseError('Default measurement frequencies not exist.')

        for channel, lo_freq in user_lo_config.meas_lo_dict().items():
            _m_los[channel.index] = lo_freq

        if _m_los == self.default_meas_los:
            return None
        return _m_los

Embed default meas LO frequencies from backend and format them to list object . If configured lo frequency is the same as default this method returns None .


def run(self, dag):
        """Expand all op nodes to the given basis.

        Args:
            dag(DAGCircuit): input dag

        Raises:
            QiskitError: if unable to unroll given the basis due to undefined
            decomposition rules (such as a bad basis) or excessive recursion.

        Returns:
            DAGCircuit: output unrolled dag
        """
        # Walk through the DAG and expand each non-basis node
        for node in dag.op_nodes():
            basic_insts = ['measure', 'reset', 'barrier', 'snapshot']
            if node.name in basic_insts:
                # TODO: this is legacy behavior.Basis_insts should be removed that these
                #  instructions should be part of the device-reported basis. Currently, no
                #  backend reports "measure", for example.
                continue
            if node.name in self.basis:  # If already a base, ignore.
                continue

            # TODO: allow choosing other possible decompositions
            rule = node.op.definition
            if not rule:
                raise QiskitError("Cannot unroll the circuit to the given basis, %s. "
                                  "No rule to expand instruction %s." %
                                  (str(self.basis), node.op.name))

            # hacky way to build a dag on the same register as the rule is defined
            # TODO: need anonymous rules to address wires by index
            decomposition = DAGCircuit()
            decomposition.add_qreg(rule[0][1][0][0])
            for inst in rule:
                decomposition.apply_operation_back(*inst)

            unrolled_dag = self.run(decomposition)  # recursively unroll ops
            dag.substitute_node_with_dag(node, unrolled_dag)
        return dag

Expand all op nodes to the given basis .


def iplot_state_qsphere(rho, figsize=None):
    """ Create a Q sphere representation.

        Graphical representation of the input array, using a Q sphere for each
        eigenvalue.

        Args:
            rho (array): State vector or density matrix.
            figsize (tuple): Figure size in pixels.
    """

    # HTML
    html_template = Template("""

    """)

    # JavaScript
    javascript_template = Template("""

    """)
    rho = _validate_input_state(rho)
    if figsize is None:
        options = {}
    else:
        options = {'width': figsize[0], 'height': figsize[1]}

    qspheres_data = []
    # Process data and execute
    num = int(np.log2(len(rho)))

    # get the eigenvectors and eigenvalues
    weig, stateall = linalg.eigh(rho)

    for _ in range(2**num):
        # start with the max
        probmix = weig.max()
        prob_location = weig.argmax()
        if probmix > 0.001:
            # print("The " + str(k) + "th eigenvalue = " + str(probmix))
            # get the max eigenvalue
            state = stateall[:, prob_location]
            loc = np.absolute(state).argmax()
            # get the element location closes to lowest bin representation.
            for j in range(2**num):
                test = np.absolute(np.absolute(state[j]) -
                                   np.absolute(state[loc]))
                if test < 0.001:
                    loc = j
                    break
            # remove the global phase
            angles = (np.angle(state[loc]) + 2 * np.pi) % (2 * np.pi)
            angleset = np.exp(-1j*angles)
            state = angleset*state
            state.flatten()

            spherepoints = []
            for i in range(2**num):
                # get x,y,z points

                element = bin(i)[2:].zfill(num)
                weight = element.count("1")

                number_of_divisions = n_choose_k(num, weight)
                weight_order = bit_string_index(element)

                angle = weight_order * 2 * np.pi / number_of_divisions

                zvalue = -2 * weight / num + 1
                xvalue = np.sqrt(1 - zvalue**2) * np.cos(angle)
                yvalue = np.sqrt(1 - zvalue**2) * np.sin(angle)

                # get prob and angle - prob will be shade and angle color
                prob = np.real(np.dot(state[i], state[i].conj()))
                angles = (np.angle(state[i]) + 2 * np.pi) % (2 * np.pi)
                qpoint = {
                    'x': xvalue,
                    'y': yvalue,
                    'z': zvalue,
                    'prob': prob,
                    'phase': angles
                }
                spherepoints.append(qpoint)

            # Associate all points to one sphere
            sphere = {
                'points': spherepoints,
                'eigenvalue': probmix
            }

            # Add sphere to the spheres array
            qspheres_data.append(sphere)
            weig[prob_location] = 0

    div_number = str(time.time())
    div_number = re.sub('[.]', '', div_number)

    html = html_template.substitute({
        'divNumber': div_number
    })

    javascript = javascript_template.substitute({
        'data': qspheres_data,
        'divNumber': div_number,
        'options': options
    })

    display(HTML(html + javascript))

"""
    <script>
        requirejs.config({
            paths: {
                qVisualization: "https://qvisualization.mybluemix.net/q-visualizations"
            }
        });
        require(["qVisualization"], function(qVisualizations) {
            data = $data;
            qVisualizations.plotState("qsphere_$divNumber",
                                      "qsphere",
                                      data,
                                      $options);
        });
    </script>

    """


def n_choose_k(n, k):
    """Return the number of combinations for n choose k.

    Args:
        n (int): the total number of options .
        k (int): The number of elements.

    Returns:
        int: returns the binomial coefficient
    """
    if n == 0:
        return 0
    return reduce(lambda x, y: x * y[0] / y[1],
                  zip(range(n - k + 1, n + 1),
                      range(1, k + 1)), 1)

def n_choose_k ( n , k ) : if n == 0 : return 0 return reduce ( lambda x , y : x * y [ 0 ] / y [ 1 ] , zip ( range ( n - k + 1 , n + 1 ) , range ( 1 , k + 1 ) ) , 1 )

Return the number of combinations for n choose k .


def lex_index(n, k, lst):
    """Return  the lex index of a combination..

    Args:
        n (int): the total number of options .
        k (int): The number of elements.
        lst (list): list

    Returns:
        int: returns int index for lex order

    Raises:
        VisualizationError: if length of list is not equal to k
    """
    if len(lst) != k:
        raise VisualizationError("list should have length k")
    comb = list(map(lambda x: n - 1 - x, lst))
    dualm = sum([n_choose_k(comb[k - 1 - i], i + 1) for i in range(k)])
    return int(dualm)

def
lex_index
(
n
,
k
,
lst
)
:
if
len
(
lst
)
!=
k
:
raise
VisualizationError
(
"list should have length k"
)
comb
=
list
(
map
(
lambda
x
:
n
1
x
,
lst
)
)
dualm
=
sum
(
[
n_choose_k
(
comb
[
k
1
i
]
,
i
+
1
)
for
i
in
range
(
k
)
]
)
return
int
(
dualm
)

Return the lex index of a combination ..


def plot_state_paulivec(rho, title="", figsize=None, color=None):
    """Plot the paulivec representation of a quantum state.

    Plot a bargraph of the mixed state rho over the pauli matrices

    Args:
        rho (ndarray): Numpy array for state vector or density matrix
        title (str): a string that represents the plot title
        figsize (tuple): Figure size in inches.
        color (list or str): Color of the expectation value bars.
    Returns:
         matplotlib.Figure: The matplotlib.Figure of the visualization
    Raises:
        ImportError: Requires matplotlib.
    """
    if not HAS_MATPLOTLIB:
        raise ImportError('Must have Matplotlib installed.')
    rho = _validate_input_state(rho)
    if figsize is None:
        figsize = (7, 5)
    num = int(np.log2(len(rho)))
    labels = list(map(lambda x: x.to_label(), pauli_group(num)))
    values = list(map(lambda x: np.real(np.trace(np.dot(x.to_matrix(), rho))),
                      pauli_group(num)))
    numelem = len(values)
    if color is None:
        color = "#648fff"

    ind = np.arange(numelem)  # the x locations for the groups
    width = 0.5  # the width of the bars
    fig, ax = plt.subplots(figsize=figsize)
    ax.grid(zorder=0, linewidth=1, linestyle='--')
    ax.bar(ind, values, width, color=color, zorder=2)
    ax.axhline(linewidth=1, color='k')
    # add some text for labels, title, and axes ticks
    ax.set_ylabel('Expectation value', fontsize=14)
    ax.set_xticks(ind)
    ax.set_yticks([-1, -0.5, 0, 0.5, 1])
    ax.set_xticklabels(labels, fontsize=14, rotation=70)
    ax.set_xlabel('Pauli', fontsize=14)
    ax.set_ylim([-1, 1])
    ax.set_facecolor('#eeeeee')
    for tick in ax.xaxis.get_major_ticks()+ax.yaxis.get_major_ticks():
        tick.label.set_fontsize(14)
    ax.set_title(title, fontsize=16)
    plt.close(fig)
    return fig

Plot the paulivec representation of a quantum state .


def get_unique_backends():
    """Gets the unique backends that are available.

    Returns:
        list: Unique available backends.

    Raises:
        QiskitError: No backends available.
    """
    backends = IBMQ.backends()
    unique_hardware_backends = []
    unique_names = []
    for back in backends:
        if back.name() not in unique_names and not back.configuration().simulator:
            unique_hardware_backends.append(back)
            unique_names.append(back.name())
    if not unique_hardware_backends:
        raise QiskitError('No backends available.')
    return unique_hardware_backends

def
get_unique_backends
(
)
:
backends
=
IBMQ
.
backends
(
)
unique_hardware_backends
=
[
]
unique_names
=
[
]
for
back
in
backends
:
if
back
.
name
(
)
not
in
unique_names
and
not
back
.
configuration
(
)
.
simulator
:
unique_hardware_backends
.
append
(
back
)
unique_names
.
append
(
back
.
name
(
)
)
if
not
unique_hardware_backends
:
raise
QiskitError
(
'No backends available.'
)
return
unique_hardware_backends

Gets the unique backends that are available .


def op(self):
        """Returns the Instruction object corresponding to the op for the node else None"""
        if 'type' not in self.data_dict or self.data_dict['type'] != 'op':
            raise QiskitError("The node %s is not an op node" % (str(self)))
        return self.data_dict.get('op')

def
op
(
self
)
:
if
'type'
not
in
self
.
data_dict
or
self
.
data_dict
[
'type'
]
!=
'op'
:
raise
QiskitError
(
"The node %s is not an op node"
%
(
str
(
self
)
)
)
return
self
.
data_dict
.
get
(
'op'
)


def constant(duration: int, amp: complex, name: str = None) -> SamplePulse:
    """Generates constant-sampled `SamplePulse`.

    Applies `left` sampling strategy to generate discrete pulse from continuous function.

    Args:
        duration: Duration of pulse. Must be greater than zero.
        amp: Complex pulse amplitude.
        name: Name of pulse.
    """
    return _sampled_constant_pulse(duration, amp, name=name)

def constant ( duration : int , amp : complex , name : str = None ) -> SamplePulse : return _sampled_constant_pulse ( duration , amp , name = name )

Generates constant - sampled SamplePulse .


def zero(duration: int, name: str = None) -> SamplePulse:
    """Generates zero-sampled `SamplePulse`.

    Args:
        duration: Duration of pulse. Must be greater than zero.
        name: Name of pulse.
    """
    return _sampled_zero_pulse(duration, name=name)

def zero ( duration : int , name : str = None ) -> SamplePulse : return _sampled_zero_pulse ( duration , name = name )


def square(duration: int, amp: complex, period: float = None,
           phase: float = 0, name: str = None) -> SamplePulse:
    """Generates square wave `SamplePulse`.

    Applies `left` sampling strategy to generate discrete pulse from continuous function.

    Args:
        duration: Duration of pulse. Must be greater than zero.
        amp: Pulse amplitude. Wave range is [-amp, amp].
        period: Pulse period, units of dt. If `None` defaults to single cycle.
        phase: Pulse phase.
        name: Name of pulse.
    """
    if period is None:
        period = duration

    return _sampled_square_pulse(duration, amp, period, phase=phase, name=name)

def square ( duration : int , amp : complex , period : float = None , phase : float = 0 , name : str = None ) -> SamplePulse : if period is None : period = duration return _sampled_square_pulse ( duration , amp , period , phase = phase , name = name )


def sawtooth(duration: int, amp: complex, period: float = None,
             phase: float = 0, name: str = None) -> SamplePulse:
    """Generates sawtooth wave `SamplePulse`.

    Args:
        duration: Duration of pulse. Must be greater than zero.
        amp: Pulse amplitude. Wave range is [-amp, amp].
        period: Pulse period, units of dt. If `None` defaults to single cycle.
        phase: Pulse phase.
        name: Name of pulse.
    """
    if period is None:
        period = duration

    return _sampled_sawtooth_pulse(duration, amp, period, phase=phase, name=name)

def sawtooth ( duration : int , amp : complex , period : float = None , phase : float = 0 , name : str = None ) -> SamplePulse : if period is None : period = duration return _sampled_sawtooth_pulse ( duration , amp , period , phase = phase , name = name )


def triangle(duration: int, amp: complex, period: float = None,
             phase: float = 0, name: str = None) -> SamplePulse:
    """Generates triangle wave `SamplePulse`.

    Applies `left` sampling strategy to generate discrete pulse from continuous function.

    Args:
        duration: Duration of pulse. Must be greater than zero.
        amp: Pulse amplitude. Wave range is [-amp, amp].
        period: Pulse period, units of dt. If `None` defaults to single cycle.
        phase: Pulse phase.
        name: Name of pulse.
    """
    if period is None:
        period = duration

    return _sampled_triangle_pulse(duration, amp, period, phase=phase, name=name)

def triangle ( duration : int , amp : complex , period : float = None , phase : float = 0 , name : str = None ) -> SamplePulse : if period is None : period = duration return _sampled_triangle_pulse ( duration , amp , period , phase = phase , name = name )


def cos(duration: int, amp: complex, freq: float = None,
        phase: float = 0, name: str = None) -> SamplePulse:
    """Generates cosine wave `SamplePulse`.

    Applies `left` sampling strategy to generate discrete pulse from continuous function.

    Args:
        duration: Duration of pulse. Must be greater than zero.
        amp: Pulse amplitude.
        freq: Pulse frequency, units of 1/dt. If `None` defaults to single cycle.
        phase: Pulse phase.
        name: Name of pulse.
    """
    if freq is None:
        freq = 1/duration

    return _sampled_cos_pulse(duration, amp, freq, phase=phase, name=name)

def cos ( duration : int , amp : complex , freq : float = None , phase : float = 0 , name : str = None ) -> SamplePulse : if freq is None : freq = 1 / duration return _sampled_cos_pulse ( duration , amp , freq , phase = phase , name = name )


def sin(duration: int, amp: complex, freq: float = None,
        phase: float = 0, name: str = None) -> SamplePulse:
    """Generates sine wave `SamplePulse`.

    Args:
        duration: Duration of pulse. Must be greater than zero.
        amp: Pulse amplitude.
        freq: Pulse frequency, units of 1/dt. If `None` defaults to single cycle.
        phase: Pulse phase.
        name: Name of pulse.
    """
    if freq is None:
        freq = 1/duration

    return _sampled_sin_pulse(duration, amp, freq, phase=phase, name=name)

def sin ( duration : int , amp : complex , freq : float = None , phase : float = 0 , name : str = None ) -> SamplePulse : if freq is None : freq = 1 / duration return _sampled_sin_pulse ( duration , amp , freq , phase = phase , name = name )


def gaussian(duration: int, amp: complex, sigma: float, name: str = None) -> SamplePulse:
    r"""Generates unnormalized gaussian `SamplePulse`.

    Centered at `duration/2` and zeroed at `t=-1` to prevent large initial discontinuity.

    Applies `left` sampling strategy to generate discrete pulse from continuous function.

    Integrated area under curve is $\Omega_g(amp, sigma) = amp \times np.sqrt(2\pi \sigma^2)$

    Args:
        duration: Duration of pulse. Must be greater than zero.
        amp: Pulse amplitude at `duration/2`.
        sigma: Width (standard deviation) of pulse.
        name: Name of pulse.
    """
    center = duration/2
    zeroed_width = duration + 2
    return _sampled_gaussian_pulse(duration, amp, center, sigma,
                                   zeroed_width=zeroed_width, rescale_amp=True, name=name)

def gaussian ( duration : int , amp : complex , sigma : float , name : str = None ) -> SamplePulse : center = duration / 2 zeroed_width = duration + 2 return _sampled_gaussian_pulse ( duration , amp , center , sigma , zeroed_width = zeroed_width , rescale_amp = True , name = name )

r Generates unnormalized gaussian SamplePulse .


def gaussian_deriv(duration: int, amp: complex, sigma: float, name: str = None) -> SamplePulse:
    r"""Generates unnormalized gaussian derivative `SamplePulse`.

    Applies `left` sampling strategy to generate discrete pulse from continuous function.

    Args:
        duration: Duration of pulse. Must be greater than zero.
        amp: Pulse amplitude at `center`.
        sigma: Width (standard deviation) of pulse.
        name: Name of pulse.
    """
    center = duration/2
    return _sampled_gaussian_deriv_pulse(duration, amp, center, sigma, name=name)

def gaussian_deriv ( duration : int , amp : complex , sigma : float , name : str = None ) -> SamplePulse : center = duration / 2 return _sampled_gaussian_deriv_pulse ( duration , amp , center , sigma , name = name )

r Generates unnormalized gaussian derivative SamplePulse .


def gaussian_square(duration: int, amp: complex, sigma: float,
                    risefall: int, name: str = None) -> SamplePulse:
    """Generates gaussian square `SamplePulse`.

    Centered at `duration/2` and zeroed at `t=-1` and `t=duration+1` to prevent
    large initial/final discontinuities.

    Applies `left` sampling strategy to generate discrete pulse from continuous function.

    Args:
        duration: Duration of pulse. Must be greater than zero.
        amp: Pulse amplitude.
        sigma: Width (standard deviation) of gaussian rise/fall portion of the pulse.
        risefall: Number of samples over which pulse rise and fall happen. Width of
            square portion of pulse will be `duration-2*risefall`.
        name: Name of pulse.
    """
    center = duration/2
    width = duration-2*risefall
    zeroed_width = duration + 2
    return _sampled_gaussian_square_pulse(duration, amp, center, width, sigma,
                                          zeroed_width=zeroed_width, name=name)

def gaussian_square ( duration : int , amp : complex , sigma : float , risefall : int , name : str = None ) -> SamplePulse : center = duration / 2 width = duration - 2 * risefall zeroed_width = duration + 2 return _sampled_gaussian_square_pulse ( duration , amp , center , width , sigma , zeroed_width = zeroed_width , name = name )


def dist_real(self):
        """Compute distance.
        """
        x0, y0 = self.ax.transAxes.transform(  # pylint: disable=invalid-name
            (0, 0))
        x1, y1 = self.ax.transAxes.transform(  # pylint: disable=invalid-name
            (1, 1))
        value = x1 - x0 if self.x else y1 - y0
        return value

def
dist_real
(
self
)
:
x0
,
y0
=
self
.
ax
.
transAxes
.
transform
(
# pylint: disable=invalid-name
(
0
,
0
)
)
x1
,
y1
=
self
.
ax
.
transAxes
.
transform
(
# pylint: disable=invalid-name
(
1
,
1
)
)
value
=
x1
x0
if
self
.
x
else
y1
y0
return
value


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

def
to_string
(
self
,
indent
)
:
ind
=
indent
*
' '
print
(
ind
,
'qreg'
)
self
.
children
[
0
]
.
to_string
(
indent
+
3
)


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

Return an instance of a backend from its class .


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'])

def
rename_register
(
self
,
regname
,
newname
)
:
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
,
)
if
regname
in
self
.
cregs
:
reg
=
self
.
cregs
[
regname
]
reg
.
name
=
newname
self
.
qregs
[
newname
]
=
reg
self
.
qregs
.
pop
(
regname
,
)
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
:
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'
]
)

Rename a classical or quantum register throughout the circuit .


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)

def remove_all_ops_named ( self , opname ) : for n in self . named_nodes ( opname ) : self . remove_op_node ( n )

Remove all operation nodes with the given name .


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))

def
add_qreg
(
self
,
qreg
)
:
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
)
)


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))

def
add_creg
(
self
,
creg
)
:
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
)
)


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,))

def
_add_wire
(
self
,
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
,
)
)


def _check_condition(self, name, condition):
        """Verify that the condition is valid.

        Args:
            name (string): used for error reporting
            condition (tuple or None): a condition tuple (ClassicalRegister,int)

        Raises:
            DAGCircuitError: if conditioning on an invalid register
        """
        # 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)

def
_check_condition
(
self
,
name
,
condition
)
:
# Verify creg exists
if
condition
is
not
and
condition
[
0
]
.
name
not
in
self
.
cregs
:
raise
DAGCircuitError
(
"invalid creg in condition for %s"
%
name
)


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

def _bits_in_condition ( self , cond ) : 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

Return a list of bits in the given condition .


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

def
_add_op_node
(
self
,
op
,
qargs
,
cargs
,
condition
=
)
:
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

Add a new operation node to the graph and assign properties .


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]

Apply an operation to the output of the circuit .


def _check_edgemap_registers(self, edge_map, keyregs, valregs, valreg=True):
        """Check that wiremap neither fragments nor leaves duplicate registers.

        1. There are no fragmented registers. A register in keyregs
        is fragmented if not all of its (qu)bits are renamed by edge_map.
        2. There are no duplicate registers. A register is duplicate if
        it appears in both self and keyregs but not in edge_map.

        Args:
            edge_map (dict): map from (reg,idx) in keyregs to (reg,idx) in valregs
            keyregs (dict): a map from register names to Register objects
            valregs (dict): a map from register names to Register objects
            valreg (bool): if False the method ignores valregs and does not
                add regs for bits in the edge_map image that don't appear in valregs

        Returns:
            set(Register): the set of regs to add to self

        Raises:
            DAGCircuitError: if the wiremap fragments, or duplicates exist
        """
        # 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

Check that wiremap neither fragments nor leaves duplicate registers .


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))

def
_check_wiremap_validity
(
self
,
wire_map
,
keymap
,
valmap
)
:
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
)
)


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

Use the wire_map dict to change the condition tuple s creg name .


def extend_back(self, dag, edge_map=None):
        """Add `dag` at the end of `self`, using `edge_map`.
        """
        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)

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 )

Add dag at the end of self using edge_map .


def compose_back(self, input_circuit, edge_map=None):
        """Apply the input circuit to the output of this circuit.

        The two bases must be "compatible" or an exception occurs.
        A subset of input qubits of the input circuit are mapped
        to a subset of output qubits of this circuit.

        Args:
            input_circuit (DAGCircuit): circuit to append
            edge_map (dict): map {(Register, int): (Register, int)}
                from the output wires of input_circuit to input wires
                of self.

        Raises:
            DAGCircuitError: if missing, duplicate or incosistent wire
        """
        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)

Apply the input circuit to the output of this circuit .


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)))

def
_check_wires_list
(
self
,
wires
,
node
)
:
if
len
(
set
(
wires
)
)
!=
len
(
wires
)
:
raise
DAGCircuitError
(
"duplicate wires"
)
wire_tot
=
len
(
node
.
qargs
)
+
len
(
node
.
cargs
)
if
node
.
condition
is
not
:
wire_tot
+=
node
.
condition
[
0
]
.
size
if
len
(
wires
)
!=
wire_tot
:
raise
DAGCircuitError
(
"expected %d wires, got %d"
%
(
wire_tot
,
len
(
wires
)
)
)

Check that a list of wires is compatible with a node to be replaced .


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

def _make_pred_succ_maps ( self , node ) : 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

Return predecessor and successor dictionaries .


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


def topological_nodes(self):
        """
        Yield nodes in topological order.

        Returns:
            generator(DAGNode): node in topological order
        """
        return nx.lexicographical_topological_sort(self._multi_graph,
                                                   key=lambda x: str(x.qargs))

def topological_nodes ( self ) : return nx . lexicographical_topological_sort ( self . _multi_graph , key = lambda x : str ( x . qargs ) )


def edges(self, nodes=None):
        """Iterator for node values.

        Yield:
            node: the node.
        """
        for source_node, dest_node, edge_data in self._multi_graph.edges(nodes, data=True):
            yield source_node, dest_node, edge_data

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


def op_nodes(self, op=None):
        """Get the list of "op" nodes in the dag.

        Args:
            op (Type): Instruction subclass op nodes to return. if op=None, return
                all op nodes.
        Returns:
            list[DAGNode]: the list of node ids containing the given op.
        """
        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

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


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

def gate_nodes ( self ) : nodes = [ ] for node in self . op_nodes ( ) : if isinstance ( node . op , Gate ) : nodes . append ( node ) return nodes


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

def named_nodes ( self , * names ) : 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

Get the set of op nodes with the given name .


def twoQ_gates(self):
        """Get list of 2-qubit gates. Ignore snapshot, barriers, and the like."""
        two_q_gates = []
        for node in self.gate_nodes():
            if len(node.qargs) == 2:
                two_q_gates.append(node)
        return two_q_gates

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

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


def predecessors(self, node):
        """Returns list of the predecessors of a node as DAGNodes."""
        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)

Returns list of the predecessors of a node as DAGNodes .


def quantum_predecessors(self, node):
        """Returns list of the predecessors of a node that are
        connected by a quantum edge as DAGNodes."""

        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

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

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


def ancestors(self, node):
        """Returns set of the ancestors of a node as DAGNodes."""
        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)

Returns set of the ancestors of a node as DAGNodes .


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

Returns list of the successors of a node that are connected by a quantum edge as DAGNodes .


def remove_op_node(self, node):
        """Remove an operation node n.

        Add edges from predecessors to successors.
        """
        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)


def remove_ancestors_of(self, node):
        """Remove all of the ancestor operation nodes of 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)

Remove all of the ancestor operation nodes of node .


def remove_descendants_of(self, node):
        """Remove all of the descendant operation nodes of 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)

Remove all of the descendant operation nodes of node .


def remove_nonancestors_of(self, node):
        """Remove all of the non-ancestors operation nodes of 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)

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


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)

Remove all of the non - descendants operation nodes of node .


def layers(self):
        """Yield a shallow view on a layer of this DAGCircuit for all d layers of this circuit.

        A layer is a circuit whose gates act on disjoint qubits, i.e.
        a layer has depth 1. The total number of layers equals the
        circuit depth d. The layers are indexed from 0 to d-1 with the
        earliest layer at index 0. The layers are constructed using a
        greedy algorithm. Each returned layer is a dict containing
        {"graph": circuit graph, "partition": list of qubit lists}.

        TODO: Gates that use the same cbits will end up in different
        layers as this is currently implemented. This may not be
        the desired behavior.
        """
        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}

Yield a shallow view on a layer of this DAGCircuit for all d layers of this circuit .


def serial_layers(self):
        """Yield a layer for all gates of this circuit.

        A serial layer is a circuit with one gate. The layers have the
        same structure as in layers().
        """
        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

Yield a layer for all gates of this circuit .


def multigraph_layers(self):
        """Yield layers of the multigraph."""
        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 = []

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
=
[
]


def collect_runs(self, namelist):
        """Return a set of non-conditional runs of "op" nodes with the given names.

        For example, "... h q[0]; cx q[0],q[1]; cx q[0],q[1]; h q[1]; .."
        would produce the tuple of cx nodes as an element of the set returned
        from a call to collect_runs(["cx"]). If instead the cx nodes were
        "cx q[0],q[1]; cx q[1],q[0];", the method would still return the
        pair in a tuple. The namelist can contain names that are not
        in the circuit's basis.

        Nodes must have only one successor to continue the run.
        """
        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)

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


def nodes_on_wire(self, wire, only_ops=False):
        """
        Iterator for nodes that affect a given wire

        Args:
            wire (tuple(Register, index)): the wire to be looked at.
            only_ops (bool): True if only the ops nodes are wanted
                        otherwise all nodes are returned.
        Yield:
             DAGNode: the successive ops on the given wire

        Raises:
            DAGCircuitError: if the given wire doesn't exist in the DAG
        """
        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


def count_ops(self):
        """Count the occurrences of operation names.

        Returns a dictionary of counts keyed on the operation name.
        """
        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

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

Count the occurrences of operation names .


def properties(self):
        """Return a dictionary of circuit properties."""
        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

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

Return a dictionary of circuit properties .


def tomography_basis(basis, prep_fun=None, meas_fun=None):
    """
    Generate a TomographyBasis object.

    See TomographyBasis for further details.abs

    Args:
        prep_fun (callable) optional: the function which adds preparation
            gates to a circuit.
        meas_fun (callable) optional: the function which adds measurement
            gates to a circuit.

    Returns:
        TomographyBasis: A tomography basis.
    """
    ret = TomographyBasis(basis)
    ret.prep_fun = prep_fun
    ret.meas_fun = meas_fun
    return ret

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


def __pauli_meas_gates(circuit, qreg, op):
    """
    Add state measurement gates to a circuit.
    """
    if op not in ['X', 'Y', 'Z']:
        raise QiskitError("There's no X, Y or Z basis for this Pauli "
                          "measurement")

    if op == "X":
        circuit.u2(0., np.pi, qreg)  # H
    elif op == "Y":
        circuit.u2(0., 0.5 * np.pi, qreg)

Add state measurement gates to a circuit .