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 : r 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 : r 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 ( ( 0 , 0 ) ) x1 , y1 = self . ax . transAxes . transform ( ( 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
]
)
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
)
:
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 = None ) : node_properties = { "type" : "op" , "op" : op , "name" : op . name , "qargs" : qargs , "cargs" : cargs , "condition" : condition } 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]

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

def
_check_edgemap_registers
(
self
,
edge_map
,
keyregs
,
valregs
,
valreg
=
True
)
:
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_regs
.
add
(
k
)
else
:
if
valreg
:
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

def _map_condition ( self , wire_map , condition ) : if condition is None : new_condition = None else : 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
_full_pred_succ_maps
(
self
,
pred_map
,
succ_map
,
input_circuit
,
wire_map
)
:
full_pred_map
=
{
}
full_succ_map
=
{
}
for
w
in
input_circuit
.
input_map
:
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
:
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}

def layers ( self ) : graph_layers = self . multigraph_layers ( ) try : next ( graph_layers ) except StopIteration : return def add_nodes_from ( layer , nodes ) : layer . _multi_graph . add_nodes_from ( nodes ) for graph_layer in graph_layers : op_nodes = [ node for node in graph_layer if node . type == "op" ] if not op_nodes : return 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 ) support_list = [ op_node . qargs for op_node in op_nodes if op_node . name not in { "barrier" , "snapshot" , "save" , "load" , "noise" } ] wires = { self . input_map [ wire ] : self . output_map [ wire ] for wire in self . wires } 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 ] 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

def serial_layers ( self ) : for next_node in self . topological_op_nodes ( ) : new_layer = DAGCircuit ( ) for qreg in self . qregs . values ( ) : new_layer . add_qreg ( qreg ) for creg in self . cregs . values ( ) : new_layer . add_creg ( creg ) support_list = [ ] 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 ) new_layer . apply_operation_back ( op , qa , ca , co ) 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 ( ) cur_layer = [ node for node in self . input_map . values ( ) ] yield cur_layer next_layer = [ ] while cur_layer : for node in cur_layer : 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)

def collect_runs ( self , namelist ) : group_list = [ ] 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 .


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

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

    Quantum State Tomography:
        Be default it will return a set for performing Quantum State
        Tomography where individual qubits are measured in the Pauli basis.
        A custom measurement basis may also be used by defining a user
        `tomography_basis` and passing this in for the `meas_basis` argument.

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

    Args:
        meas_qubits (list): The qubits being measured.
        meas_basis (tomography_basis or str): The qubit measurement basis.
            The default value is 'Pauli'.
        prep_qubits (list or None): The qubits being prepared. If None then
            meas_qubits will be used for process tomography experiments.
        prep_basis (tomography_basis or None): The optional qubit preparation
            basis. If no basis is specified state tomography will be performed
            instead of process tomography. A built in basis may be specified by
            'SIC' or 'Pauli'  (SIC basis recommended for > 2 qubits).

    Returns:
        dict: A dict of tomography configurations that can be parsed by
        `create_tomography_circuits` and `tomography_data` functions
        for implementing quantum tomography experiments. This output contains
        fields "qubits", "meas_basis", "circuits". It may also optionally
        contain a field "prep_basis" for process tomography experiments.
        ```
        {
            'qubits': qubits (list[ints]),
            'meas_basis': meas_basis (tomography_basis),
            'circuit_labels': (list[string]),
            'circuits': (list[dict])  # prep and meas configurations
            # optionally for process tomography experiments:
            'prep_basis': prep_basis (tomography_basis)
        }
        ```
    Raises:
        QiskitError: if the Qubits argument is not a list.
    """
    if not isinstance(meas_qubits, list):
        raise QiskitError('Qubits argument must be a list')
    num_of_qubits = len(meas_qubits)

    if prep_qubits is None:
        prep_qubits = meas_qubits
    if not isinstance(prep_qubits, list):
        raise QiskitError('prep_qubits argument must be a list')
    if len(prep_qubits) != len(meas_qubits):
        raise QiskitError('meas_qubits and prep_qubitsare different length')

    if isinstance(meas_basis, str):
        if meas_basis.lower() == 'pauli':
            meas_basis = PAULI_BASIS

    if isinstance(prep_basis, str):
        if prep_basis.lower() == 'pauli':
            prep_basis = PAULI_BASIS
        elif prep_basis.lower() == 'sic':
            prep_basis = SIC_BASIS

    circuits = []
    circuit_labels = []

    # add meas basis configs
    if prep_basis is None:
        # State Tomography
        for meas_product in product(meas_basis.keys(), repeat=num_of_qubits):
            meas = dict(zip(meas_qubits, meas_product))
            circuits.append({'meas': meas})
            # Make label
            label = '_meas_'
            for qubit, op in meas.items():
                label += '%s(%d)' % (op[0], qubit)
            circuit_labels.append(label)
        return {'qubits': meas_qubits,
                'circuits': circuits,
                'circuit_labels': circuit_labels,
                'meas_basis': meas_basis}

    # Process Tomography
    num_of_s = len(list(prep_basis.values())[0])
    plst_single = [(b, s)
                   for b in prep_basis.keys()
                   for s in range(num_of_s)]
    for plst_product in product(plst_single, repeat=num_of_qubits):
        for meas_product in product(meas_basis.keys(),
                                    repeat=num_of_qubits):
            prep = dict(zip(prep_qubits, plst_product))
            meas = dict(zip(meas_qubits, meas_product))
            circuits.append({'prep': prep, 'meas': meas})
            # Make label
            label = '_prep_'
            for qubit, op in prep.items():
                label += '%s%d(%d)' % (op[0], op[1], qubit)
            label += '_meas_'
            for qubit, op in meas.items():
                label += '%s(%d)' % (op[0], qubit)
            circuit_labels.append(label)
    return {'qubits': meas_qubits,
            'circuits': circuits,
            'circuit_labels': circuit_labels,
            'prep_basis': prep_basis,
            'meas_basis': meas_basis}

Generate a dictionary of tomography experiment configurations .


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

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

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

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

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

Generate a dictionary of process tomography experiment configurations .


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

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

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

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

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

    Raises:
        QiskitError: if circuit is not a valid QuantumCircuit

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

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

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

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

Add tomography measurement circuits to a QuantumProgram .


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

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

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

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

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

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

Return a results dict for a state or process tomography experiment .


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

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

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

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

    meas_keys = count_keys(len(qs))

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

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

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

def marginal_counts ( counts , meas_qubits ) : num_of_qubits = len ( list ( counts . keys ( ) ) [ 0 ] ) qs = sorted ( meas_qubits , reverse = True ) meas_keys = count_keys ( len ( qs ) ) rgx = [ reduce ( lambda x , y : ( key [ qs . index ( y ) ] if y in qs else '\\d' ) + x , range ( num_of_qubits ) , '' ) for key in meas_keys ] meas_counts = [ ] for m in rgx : c = 0 for key , val in counts . items ( ) : if match ( m , key ) : c += val meas_counts . append ( c ) return dict ( zip ( meas_keys , meas_counts ) )

Compute the marginal counts for a subset of measured qubits .


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

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

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

    Returns:
        numpy.array: The fitted operator.

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

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

def
fit_tomography_data
(
tomo_data
,
method
=
'wizard'
,
options
=
)
:
if
isinstance
(
method
,
str
)
and
method
.
lower
(
)
in
[
'wizard'
,
'leastsq'
]
:
trace
=
__get_option
(
'trace'
,
options
)
beta
=
__get_option
(
'beta'
,
options
)
rho
=
__leastsq_fit
(
tomo_data
,
trace
=
trace
,
beta
=
beta
)
if
method
==
'wizard'
:
epsilon
=
__get_option
(
'epsilon'
,
options
)
rho
=
__wizard
(
rho
,
epsilon
=
epsilon
)
return
rho
else
:
raise
Exception
(
'Invalid reconstruction method "%s"'
%
method
)

Reconstruct a density matrix or process - matrix from tomography data .


def __leastsq_fit(tomo_data, weights=None, trace=None, beta=None):
    """
    Reconstruct a state from unconstrained least-squares fitting.

    Args:
        tomo_data (list[dict]): state or process tomography data.
        weights (list or array or None): weights to use for least squares
            fitting. The default is standard deviation from a binomial
            distribution.
        trace (float or None): trace of returned operator. The default is 1.
        beta (float or None): hedge parameter (>=0) for computing frequencies
            from zero-count data. The default value is 0.50922.

    Returns:
        numpy.array: A numpy array of the reconstructed operator.
    """
    if trace is None:
        trace = 1.  # default to unit trace

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

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

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

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

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

def __leastsq_fit ( tomo_data , weights = None , trace = None , beta = None ) : if trace is None : trace = 1. data = tomo_data [ 'data' ] keys = data [ 0 ] [ 'circuit' ] . keys ( ) counts = [ ] shots = [ ] ops = [ ] for dat in data : for key in keys : counts . append ( dat [ 'counts' ] [ key ] ) shots . append ( dat [ 'shots' ] ) projectors = dat [ 'circuit' ] [ key ] op = __projector ( projectors [ 'meas' ] , tomo_data [ 'meas_basis' ] ) if 'prep' in projectors : op_prep = __projector ( projectors [ 'prep' ] , tomo_data [ 'prep_basis' ] ) op = np . kron ( op_prep . conj ( ) , op ) ops . append ( op ) counts = np . array ( counts ) shots = np . array ( shots ) freqs = counts / shots if weights is None : if beta is None : beta = 0.50922 K = len ( keys ) freqs_hedged = ( counts + beta ) / ( shots + K * beta ) weights = np . sqrt ( shots / ( freqs_hedged * ( 1 - freqs_hedged ) ) ) return __tomo_linear_inv ( freqs , ops , weights , trace = trace )

Reconstruct a state from unconstrained least - squares fitting .


def __projector(op_list, basis):
    """Returns a projectors.
    """
    ret = 1
    # list is from qubit 0 to 1
    for op in op_list:
        label, eigenstate = op
        ret = np.kron(basis[label][eigenstate], ret)
    return ret

def __projector ( op_list , basis ) : ret = 1 for op in op_list : label , eigenstate = op ret = np . kron ( basis [ label ] [ eigenstate ] , ret ) return ret


def __tomo_linear_inv(freqs, ops, weights=None, trace=None):
    """
    Reconstruct a matrix through linear inversion.

    Args:
        freqs (list[float]): list of observed frequences.
        ops (list[np.array]): list of corresponding projectors.
        weights (list[float] or array_like):
            weights to be used for weighted fitting.
        trace (float or None): trace of returned operator.

    Returns:
        numpy.array: A numpy array of the reconstructed operator.
    """
    # get weights matrix
    if weights is not None:
        W = np.array(weights)
        if W.ndim == 1:
            W = np.diag(W)

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

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

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

def __tomo_linear_inv ( freqs , ops , weights = None , trace = None ) : if weights is not None : W = np . array ( weights ) if W . ndim == 1 : W = np . diag ( W ) S = np . array ( [ vectorize ( m ) . conj ( ) for m in ops ] ) . reshape ( len ( ops ) , ops [ 0 ] . size ) if weights is not None : S = np . dot ( W , S ) v = np . array ( freqs ) if weights is not None : v = np . dot ( W , freqs ) Sdg = S . T . conj ( ) inv = np . linalg . pinv ( np . dot ( Sdg , S ) ) ret = devectorize ( np . dot ( inv , np . dot ( Sdg , v ) ) ) if trace is not None : ret = trace * ret / np . trace ( ret ) return ret

Reconstruct a matrix through linear inversion .


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

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

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

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

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

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

Returns the nearest positive semidefinite operator to an operator .


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

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

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

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

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

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

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

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

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

    return w

def wigner_data ( q_result , meas_qubits , labels , shots = None ) : num = len ( meas_qubits ) dim = 2 ** num p = [ 0.5 + 0.5 * np . sqrt ( 3 ) , 0.5 - 0.5 * np . sqrt ( 3 ) ] parity = 1 for i in range ( num ) : parity = np . kron ( parity , p ) w = [ 0 ] * len ( labels ) wpt = 0 counts = [ marginal_counts ( q_result . get_counts ( circ ) , meas_qubits ) for circ in labels ] for entry in counts : x = [ 0 ] * dim for i in range ( dim ) : if bin ( i ) [ 2 : ] . zfill ( num ) in entry : x [ i ] = float ( entry [ bin ( i ) [ 2 : ] . zfill ( num ) ] ) if shots is None : shots = np . sum ( x ) for i in range ( dim ) : w [ wpt ] = w [ wpt ] + ( x [ i ] / shots ) * parity [ i ] wpt += 1 return w

Get the value of the Wigner function from measurement results .


def meas_gate(self, circuit, qreg, op):
        """
        Add measurement gates to a circuit.

        Args:
            circuit (QuantumCircuit): circuit to add measurement to.
            qreg (tuple(QuantumRegister,int)): quantum register being measured.
            op (str): the basis label for the measurement.
        """
        if self.meas_fun is None:
            pass
        else:
            self.meas_fun(circuit, qreg, op)

def meas_gate ( self , circuit , qreg , op ) : if self . meas_fun is None : pass else : self . meas_fun ( circuit , qreg , op )


def _text_checker(job, interval, _interval_set=False, quiet=False, output=sys.stdout):
    """A text-based job status checker

    Args:
        job (BaseJob): The job to check.
        interval (int): The interval at which to check.
        _interval_set (bool): Was interval time set by user?
        quiet (bool): If True, do not print status messages.
        output (file): The file like object to write status messages to.
        By default this is sys.stdout.

    """
    status = job.status()
    msg = status.value
    prev_msg = msg
    msg_len = len(msg)

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

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

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

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

def
_text_checker
(
job
,
interval
,
_interval_set
=
False
,
quiet
=
False
,
output
=
sys
.
stdout
)
:
status
=
job
.
status
(
)
msg
=
status
.
value
prev_msg
=
msg
msg_len
=
len
(
msg
)
if
not
quiet
:
print
(
'\r%s: %s'
%
(
'Job Status'
,
msg
)
,
end
=
''
,
file
=
output
)
while
status
.
name
not
in
[
'DONE'
,
'CANCELLED'
,
'ERROR'
]
:
time
.
sleep
(
interval
)
status
=
job
.
status
(
)
msg
=
status
.
value
if
status
.
name
==
'QUEUED'
:
msg
+=
' (%s)'
%
job
.
queue_position
(
)
if
not
_interval_set
:
interval
=
max
(
job
.
queue_position
(
)
,
2
)
else
:
if
not
_interval_set
:
interval
=
2
if
len
(
msg
)
<
msg_len
:
msg
+=
' '
*
(
msg_len
len
(
msg
)
)
elif
len
(
msg
)
>
msg_len
:
msg_len
=
len
(
msg
)
if
msg
!=
prev_msg
and
not
quiet
:
print
(
'\r%s: %s'
%
(
'Job Status'
,
msg
)
,
end
=
''
,
file
=
output
)
prev_msg
=
msg
if
not
quiet
:
print
(
''
,
file
=
output
)


def job_monitor(job, interval=None, monitor_async=False, quiet=False, output=sys.stdout):
    """Monitor the status of a IBMQJob instance.

    Args:
        job (BaseJob): Job to monitor.
        interval (int): Time interval between status queries.
        monitor_async (bool): Monitor asyncronously (in Jupyter only).
        quiet (bool): If True, do not print status messages.
        output (file): The file like object to write status messages to.
        By default this is sys.stdout.

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

            style = "font-size:16px;"
            header = "<p style='{style}'>Job Status: %s </p>".format(
                style=style)
            status = widgets.HTML(value=header % job.status().value)
            display(status)

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

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

Monitor the status of a IBMQJob instance .


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

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

    Args:
        unitary_matrix (ndarray): 2x2 unitary matrix

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

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

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

Compute Euler angles for a single - qubit gate .