# -*- coding: utf-8 -*-

# Copyright 2018, IBM.
#
# This source code is licensed under the Apache License, Version 2.0 found in
# the LICENSE.txt file in the root directory of this source tree.

"""A module for monitoring various qiskit functionality"""

import sys
import time
import threading
from qiskit.exceptions import QiskitError

_NOTEBOOK_ENV = False
if ('ipykernel' in sys.modules) and ('spyder' not in sys.modules):
    _NOTEBOOK_ENV = True
    from IPython.display import display    # pylint: disable=import-error

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


# -*- coding: utf-8 -*-

# Copyright 2019, IBM.
#
# This source code is licensed under the Apache License, Version 2.0 found in
# the LICENSE.txt file in the root directory of this source tree.

# pylint: disable=invalid-name,invalid-sequence-index
# pylint: disable=unsupported-assignment-operation

"""
Expand 2-qubit Unitary operators into an equivalent
decomposition over SU(2)+CNOT, using the KAK method.

Computes a sequence of 10 single and two qubit gates, including 3 CNOTs,
which multiply to U, including global phase. Uses Vatan and Williams
optimal two-qubit circuit (quant-ph/0308006v3). The decomposition algorithm
which achieves this is explained well in Drury and Love, 0806.4015.

Based on MATLAB implementation by David Gosset.
"""
import math

import numpy as np
import scipy.linalg as la

from qiskit.circuit.quantumregister import QuantumRegister
from qiskit.circuit.quantumcircuit import QuantumCircuit
from qiskit.extensions.standard.iden import IdGate
from qiskit.extensions.standard.u1 import U1Gate
from qiskit.extensions.standard.u2 import U2Gate
from qiskit.extensions.standard.u3 import U3Gate
from qiskit.extensions.standard.cx import CnotGate
from qiskit.exceptions import QiskitError
from qiskit.quantum_info.operators.predicates import is_unitary_matrix

_CUTOFF_PRECISION = 1e-10

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 simplify_U(theta, phi, lam):
    """Return the gate u1, u2, or u3 implementing U with the fewest pulses.

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

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

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

def two_qubit_kak(unitary):
    """Decompose a two-qubit gate over SU(2)+CNOT using the KAK decomposition.

    Args:
        unitary (Operator): a 4x4 unitary operator to decompose.

    Returns:
        QuantumCircuit: a circuit implementing the unitary over SU(2)+CNOT

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    theta = 2*gamma - np.pi/2

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    return return_circuit


# -*- coding: utf-8 -*-

# Copyright 2019, IBM.
#
# This source code is licensed under the Apache License, Version 2.0 found in
# the LICENSE.txt file in the root directory of this source tree.

"""
Transformation pass that extends the circuit with new virtual qubits (i.e. ancilla).
Which qubits to add are previously allocated in the 'layout' property, by a previous pass.
"""

from qiskit.transpiler.basepasses import TransformationPass
from qiskit.transpiler.exceptions import TranspilerError

class EnlargeWithAncilla(TransformationPass):
    """Extends the DAG circuit with virtual qubits (ancilla) that are specified in
    the layout, but not present in the circuit."""

    def __init__(self, layout=None):
        """
        Args:
            layout (Layout): layout of qubits to consider
        """
        super().__init__()
        self.layout = layout

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

        Args:
            dag (DAGCircuit): DAG to extend.

        Returns:
            DAGCircuit: An extended DAG.

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

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

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

        for qreg in new_qregs:
            dag.add_qreg(qreg)

        return dag


# -*- coding: utf-8 -*-

# Copyright 2017, IBM.
#
# This source code is licensed under the Apache License, Version 2.0 found in
# the LICENSE.txt file in the root directory of this source tree.

# pylint: disable=invalid-name

"""
controlled-H gate.
"""
from qiskit.circuit import CompositeGate
from qiskit.circuit import Gate
from qiskit.circuit import QuantumCircuit
from qiskit.circuit import QuantumRegister
from qiskit.circuit.decorators import _op_expand, _to_bits
from qiskit.extensions.standard.x import XGate
from qiskit.extensions.standard.h import HGate
from qiskit.extensions.standard.cx import CnotGate
from qiskit.extensions.standard.t import TGate
from qiskit.extensions.standard.s import SGate
from qiskit.extensions.standard.s import SdgGate

class CHGate(Gate):
    """controlled-H gate."""

    def __init__(self):
        """Create new CH gate."""
        super().__init__("ch", 2, [])

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

    def inverse(self):
        """Invert this gate."""
        return CHGate()  # self-inverse

@_to_bits(2)
@_op_expand(2)
def ch(self, ctl, tgt):
    """Apply CH from ctl to tgt."""
    return self.append(CHGate(), [ctl, tgt], [])

QuantumCircuit.ch = ch
CompositeGate.ch = ch


# -*- coding: utf-8 -*-

# Copyright 2018, IBM.
#
# This source code is licensed under the Apache License, Version 2.0 found in
# the LICENSE.txt file in the root directory of this source tree.

"""A module for monitoring backends."""

import math
import datetime
from IPython.display import display                     # pylint: disable=import-error
from IPython.core.magic import (line_magic,             # pylint: disable=import-error
                                Magics, magics_class)
import matplotlib.pyplot as plt                         # pylint: disable=import-error
import matplotlib.colors                                # pylint: disable=import-error
import matplotlib as mpl                                # pylint: disable=import-error
from matplotlib import cm                               # pylint: disable=import-error
from matplotlib.patches import Circle                   # pylint: disable=import-error
import ipywidgets as widgets                            # pylint: disable=import-error
from qiskit.exceptions import QiskitError
from qiskit.visualization.gate_map import plot_gate_map

try:
    # pylint: disable=import-error,no-name-in-module
    from qiskit.providers.ibmq import IBMQ, IBMQBackend
except ImportError:
    pass

@magics_class
class BackendMonitor(Magics):
    """A class of status magic functions.
    """
    @line_magic
    def qiskit_backend_monitor(self, line='', cell=None):  # pylint: disable=W0613
        """A Jupyter magic function to monitor backends.
        """
        backend = self.shell.user_ns[line]
        if not isinstance(backend, IBMQBackend):
            raise QiskitError('Input variable is not of type IBMQBackend.')
        title_style = "style='color:#ffffff;background-color:#000000;padding-top: 1%;"
        title_style += "padding-bottom: 1%;padding-left: 1%; margin-top: 0px'"
        title_html = "
{name}
".format(
            style=title_style, name=backend.name())

        details = [config_tab(backend)]

        tab_contents = ['Configuration']

        if not backend.configuration().simulator:
            tab_contents.extend(['Qubit Properties', 'Multi-Qubit Gates',
                                 'Error Map', 'Job History'])
            details.extend([qubits_tab(backend), gates_tab(backend),
                            detailed_map(backend), job_history(backend)])

        tabs = widgets.Tab(layout=widgets.Layout(overflow_y='scroll'))
        tabs.children = details
        for i in range(len(details)):
            tabs.set_title(i, tab_contents[i])

        title_widget = widgets.HTML(value=title_html,
                                    layout=widgets.Layout(margin='0px 0px 0px 0px'))

        backend_monitor = widgets.VBox([title_widget, tabs],
                                       layout=widgets.Layout(border='4px solid #000000',
                                                             max_height='650px', min_height='650px',
                                                             overflow_y='hidden'))

        display(backend_monitor)

def config_tab(backend):
    """The backend configuration widget.

    Args:
        backend (IBMQbackend): The backend.

    Returns:
        grid: A GridBox widget.
    """
    status = backend.status().to_dict()
    config = backend.configuration().to_dict()

    config_dict = {**status, **config}

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

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

    footer = "
"

    # Upper HBox widget data

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

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

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

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

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

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

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

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

    return grid

def qubits_tab(backend):
    """The qubits properties widget

    Args:
        backend (IBMQbackend): The backend.

    Returns:
        VBox: A VBox widget.
    """
    props = backend.properties().to_dict()

    header_html = "
{key}: {value}
"
    header_html = header_html.format(key='last_update_date',
                                     value=props['last_update_date'])
    update_date_widget = widgets.HTML(value=header_html)

    qubit_html = "
"
    qubit_html += """"""

    qubit_html += "
	Frequency	T1	T2	"
    qubit_html += "U1 gate error	U2 gate error	U3 gate error	"
    qubit_html += "Readout error
"
    qubit_footer = "
"

    for qub in range(len(props['qubits'])):
        name = 'Q%s' % qub
        qubit_data = props['qubits'][qub]
        gate_data = props['gates'][3*qub:3*qub+3]
        t1_info = qubit_data[0]
        t2_info = qubit_data[1]
        freq_info = qubit_data[2]
        readout_info = qubit_data[3]

        freq = str(round(freq_info['value'], 5))+' '+freq_info['unit']
        T1 = str(round(t1_info['value'],  # pylint: disable=invalid-name
                       5))+' ' + t1_info['unit']
        T2 = str(round(t2_info['value'],  # pylint: disable=invalid-name
                       5))+' ' + t2_info['unit']
        # pylint: disable=invalid-name
        U1 = str(round(gate_data[0]['parameters'][0]['value'], 5))
        # pylint: disable=invalid-name
        U2 = str(round(gate_data[1]['parameters'][0]['value'], 5))
        # pylint: disable=invalid-name
        U3 = str(round(gate_data[2]['parameters'][0]['value'], 5))

        readout_error = round(readout_info['value'], 5)
        qubit_html += "
%s	%s	"
        qubit_html += "%s	%s	%s	%s	%s	%s
"
        qubit_html = qubit_html % (name, freq, T1, T2, U1, U2, U3, readout_error)
    qubit_html += qubit_footer

    qubit_widget = widgets.HTML(value=qubit_html)

    out = widgets.VBox([update_date_widget,
                        qubit_widget])

    return out

def gates_tab(backend):
    """The multiple qubit gate error widget.

    Args:
        backend (IBMQbackend): The backend.

    Returns:
        VBox: A VBox widget.
    """
    config = backend.configuration().to_dict()
    props = backend.properties().to_dict()

    multi_qubit_gates = props['gates'][3*config['n_qubits']:]

    header_html = "
{key}: {value}
"
    header_html = header_html.format(key='last_update_date',
                                     value=props['last_update_date'])

    update_date_widget = widgets.HTML(value=header_html,
                                      layout=widgets.Layout(grid_area='top'))

    gate_html = "
"
    gate_html += """"""

    gate_html += "
	Type	Gate error
"
    gate_footer = "
"

    # Split gates into two columns
    left_num = math.ceil(len(multi_qubit_gates)/3)
    mid_num = math.ceil((len(multi_qubit_gates)-left_num)/2)

    left_table = gate_html

    for qub in range(left_num):
        gate = multi_qubit_gates[qub]
        name = gate['name']
        ttype = gate['gate']
        error = round(gate['parameters'][0]['value'], 5)

        left_table += "
%s"
        left_table += "	%s	%s
"
        left_table = left_table % (name, ttype, error)
    left_table += gate_footer

    middle_table = gate_html

    for qub in range(left_num, left_num+mid_num):
        gate = multi_qubit_gates[qub]
        name = gate['name']
        ttype = gate['gate']
        error = round(gate['parameters'][0]['value'], 5)

        middle_table += "
%s"
        middle_table += "	%s	%s
"
        middle_table = middle_table % (name, ttype, error)
    middle_table += gate_footer

    right_table = gate_html

    for qub in range(left_num+mid_num, len(multi_qubit_gates)):
        gate = multi_qubit_gates[qub]
        name = gate['name']
        ttype = gate['gate']
        error = round(gate['parameters'][0]['value'], 5)

        right_table += "
%s"
        right_table += "	%s	%s
"
        right_table = right_table % (name, ttype, error)
    right_table += gate_footer

    left_table_widget = widgets.HTML(value=left_table,
                                     layout=widgets.Layout(grid_area='left'))
    middle_table_widget = widgets.HTML(value=middle_table,
                                       layout=widgets.Layout(grid_area='middle'))
    right_table_widget = widgets.HTML(value=right_table,
                                      layout=widgets.Layout(grid_area='right'))

    grid = widgets.GridBox(children=[update_date_widget,
                                     left_table_widget,
                                     middle_table_widget,
                                     right_table_widget],
                           layout=widgets.Layout(
                               grid_template_rows='auto auto',
                               grid_template_columns='33% 33% 33%',
                               grid_template_areas='''
                                                   "top top top"
                                                   "left middle right"
                                                   ''',
                               grid_gap='0px 0px'))

    return grid

def detailed_map(backend):
    """Widget for displaying detailed noise map.

    Args:
        backend (IBMQbackend): The backend.

    Returns:
        GridBox: Widget holding noise map images.
    """
    props = backend.properties().to_dict()
    config = backend.configuration().to_dict()
    single_gate_errors = [q['parameters'][0]['value']
                          for q in props['gates'][2:3*config['n_qubits']:3]]
    single_norm = matplotlib.colors.Normalize(
        vmin=min(single_gate_errors), vmax=max(single_gate_errors))
    q_colors = [cm.viridis(single_norm(err)) for err in single_gate_errors]

    cmap = config['coupling_map']

    cx_errors = []
    for line in cmap:
        for item in props['gates'][3*config['n_qubits']:]:
            if item['qubits'] == line:
                cx_errors.append(item['parameters'][0]['value'])
                break
        else:
            continue

    cx_norm = matplotlib.colors.Normalize(
        vmin=min(cx_errors), vmax=max(cx_errors))
    line_colors = [cm.viridis(cx_norm(err)) for err in cx_errors]

    single_widget = widgets.Output(layout=widgets.Layout(display='flex-inline', grid_area='left',
                                                         align_items='center'))

    cmap_widget = widgets.Output(layout=widgets.Layout(display='flex-inline', grid_area='top',
                                                       width='auto', height='auto',
                                                       align_items='center'))

    cx_widget = widgets.Output(layout=widgets.Layout(display='flex-inline', grid_area='right',
                                                     align_items='center'))

    tick_locator = mpl.ticker.MaxNLocator(nbins=5)
    with cmap_widget:
        noise_map = plot_gate_map(backend, qubit_color=q_colors,
                                  line_color=line_colors,
                                  qubit_size=28,
                                  plot_directed=True)
        width, height = noise_map.get_size_inches()

        noise_map.set_size_inches(1.25*width, 1.25*height)

        display(noise_map)
        plt.close(noise_map)

    with single_widget:
        cbl_fig = plt.figure(figsize=(3, 1))
        ax1 = cbl_fig.add_axes([0.05, 0.80, 0.9, 0.15])
        single_cb = mpl.colorbar.ColorbarBase(ax1, cmap=cm.viridis,
                                              norm=single_norm,
                                              orientation='horizontal')
        single_cb.locator = tick_locator
        single_cb.update_ticks()
        ax1.set_title('Single-qubit U3 error rate')
        display(cbl_fig)
        plt.close(cbl_fig)

    with cx_widget:
        cx_fig = plt.figure(figsize=(3, 1))
        ax2 = cx_fig.add_axes([0.05, 0.80, 0.9, 0.15])
        cx_cb = mpl.colorbar.ColorbarBase(ax2, cmap=cm.viridis,
                                          norm=cx_norm,
                                          orientation='horizontal')
        cx_cb.locator = tick_locator
        cx_cb.update_ticks()
        ax2.set_title('CNOT error rate')
        display(cx_fig)
        plt.close(cx_fig)

    out_box = widgets.GridBox([single_widget, cmap_widget, cx_widget],
                              layout=widgets.Layout(
                                  grid_template_rows='auto auto',
                                  grid_template_columns='33% 33% 33%',
                                  grid_template_areas='''
                                                "top top top"
                                                "left . right"
                                                ''',
                                  grid_gap='0px 0px'))
    return out_box

def job_history(backend):
    """Widget for displaying job history

    Args:
     backend (IBMQbackend): The backend.

    Returns:
        Tab: A tab widget for history images.
    """
    year = widgets.Output(layout=widgets.Layout(display='flex-inline',
                                                align_items='center',
                                                min_height='400px'))

    month = widgets.Output(layout=widgets.Layout(display='flex-inline',
                                                 align_items='center',
                                                 min_height='400px'))

    week = widgets.Output(layout=widgets.Layout(display='flex-inline',
                                                align_items='center',
                                                min_height='400px'))

    tabs = widgets.Tab(layout=widgets.Layout(max_height='620px'))
    tabs.children = [year, month, week]
    tabs.set_title(0, 'Year')
    tabs.set_title(1, 'Month')
    tabs.set_title(2, 'Week')
    tabs.selected_index = 1

    _build_job_history(tabs, backend)
    return tabs

def _build_job_history(tabs, backend):

    backends = IBMQ.backends(backend.name())
    past_year_date = datetime.datetime.now() - datetime.timedelta(days=365)
    date_filter = {'creationDate': {'gt': past_year_date.isoformat()}}
    jobs = []
    for back in backends:
        jobs.extend(back.jobs(limit=None, db_filter=date_filter))

    with tabs.children[1]:
        month_plot = plot_job_history(jobs, interval='month')
        display(month_plot)
        plt.close(month_plot)

    with tabs.children[0]:
        year_plot = plot_job_history(jobs, interval='year')
        display(year_plot)
        plt.close(year_plot)

    with tabs.children[2]:
        week_plot = plot_job_history(jobs, interval='week')
        display(week_plot)
        plt.close(week_plot)

def plot_job_history(jobs, interval='year'):
    """Plots the job history of the user from the given list of jobs.

    Args:
        jobs (list): A list of jobs with type IBMQjob.
        interval (str): Interval over which to examine.

    Returns:
        fig: A Matplotlib figure instance.
    """
    def get_date(job):
        """Returns a datetime object from a IBMQJob instance.

        Args:
            job (IBMQJob): A job.

        Returns:
            dt: A datetime object.
        """
        return datetime.datetime.strptime(job.creation_date(),
                                          '%Y-%m-%dT%H:%M:%S.%fZ')

    current_time = datetime.datetime.now()

    if interval == 'year':
        bins = [(current_time - datetime.timedelta(days=k*365/12))
                for k in range(12)]
    elif interval == 'month':
        bins = [(current_time - datetime.timedelta(days=k)) for k in range(30)]
    elif interval == 'week':
        bins = [(current_time - datetime.timedelta(days=k)) for k in range(7)]

    binned_jobs = [0]*len(bins)

    if interval == 'year':
        for job in jobs:
            for ind, dat in enumerate(bins):
                date = get_date(job)
                if date.month == dat.month:
                    binned_jobs[ind] += 1
                    break
            else:
                continue
    else:
        for job in jobs:
            for ind, dat in enumerate(bins):
                date = get_date(job)
                if date.day == dat.day and date.month == dat.month:
                    binned_jobs[ind] += 1
                    break
            else:
                continue

    nz_bins = []
    nz_idx = []
    for ind, val in enumerate(binned_jobs):
        if val != 0:
            nz_idx.append(ind)
            nz_bins.append(val)

    total_jobs = sum(binned_jobs)

    colors = ['#003f5c', '#ffa600', '#374c80', '#ff764a',
              '#7a5195', '#ef5675', '#bc5090']

    if interval == 'year':
        labels = ['{}-{}'.format(str(bins[b].year)[2:], bins[b].month) for b in nz_idx]
    else:
        labels = ['{}-{}'.format(bins[b].month, bins[b].day) for b in nz_idx]
    fig, ax = plt.subplots(1, 1, figsize=(5, 5))  # pylint: disable=invalid-name
    ax.pie(nz_bins[::-1], labels=labels, colors=colors, textprops={'fontsize': 14},
           rotatelabels=True, counterclock=False)
    ax.add_artist(Circle((0, 0), 0.7, color='white', zorder=1))
    ax.text(0, 0, total_jobs, horizontalalignment='center',
            verticalalignment='center', fontsize=26)
    fig.tight_layout()
    return fig


# -*- coding: utf-8 -*-

# Copyright 2019, IBM.
#
# This source code is licensed under the Apache License, Version 2.0 found in
# the LICENSE.txt file in the root directory of this source tree.

"""
Transpiler pass to remove reset gate when the qubit is in zero state
"""

from qiskit.circuit import Reset
from qiskit.transpiler.basepasses import TransformationPass

class RemoveResetInZeroState(TransformationPass):
    """Remove reset gate when the qubit is in zero state"""

    def run(self, dag):
        """Return a new circuit that has been optimized."""
        resets = dag.op_nodes(Reset)
        for reset in resets:
            predecessor = next(dag.predecessors(reset))
            if predecessor.type == 'in':
                dag.remove_op_node(reset)
        return dag


# -*- coding: utf-8 -*-

# Copyright 2019, IBM.
#
# This source code is licensed under the Apache License, Version 2.0 found in
# the LICENSE.txt file in the root directory of this source tree.

"""
Sample pulse.
"""
import numpy as np

from qiskit.pulse.channels import PulseChannel
from qiskit.pulse.exceptions import PulseError
from .instruction import Instruction
from .command import Command

class SamplePulse(Command):
    """Container for functional pulse."""

    def __init__(self, samples, name=None):
        """Create new sample pulse command.

        Args:
            samples (ndarray): Complex array of pulse envelope.
            name (str): Unique name to identify the pulse.
        Raises:
            PulseError: when pulse envelope amplitude exceeds 1.
        """
        super().__init__(duration=len(samples), name=name)

        if np.any(np.abs(samples) > 1):
            raise PulseError('Absolute value of pulse envelope amplitude exceeds 1.')

        self._samples = samples

    @property
    def samples(self):
        """Return sample values."""
        return self._samples

    def draw(self, **kwargs):
        """Plot the interpolated envelope of pulse.

        Keyword Args:
            dt (float): Time interval of samples.
            interp_method (str): Method of interpolation
                (set `None` for turn off the interpolation).
            filename (str): Name required to save pulse image.
            interactive (bool): When set true show the circuit in a new window
                (this depends on the matplotlib backend being used supporting this).
            dpi (int): Resolution of saved image.
            nop (int): Data points for interpolation.
            size (tuple): Size of figure.
        """
        from qiskit.tools.visualization import pulse_drawer

        return pulse_drawer(self._samples, self.duration, **kwargs)

    def __eq__(self, other):
        """Two SamplePulses are the same if they are of the same type
        and have the same name and samples.

        Args:
            other (SamplePulse): other SamplePulse

        Returns:
            bool: are self and other equal.
        """
        if super().__eq__(other) and \
                (self._samples == other._samples).all():
            return True
        return False

    def __hash__(self):
        return hash((super().__hash__(), self._samples.tostring()))

    def __repr__(self):
        return '%s(%s, duration=%d)' % (self.__class__.__name__, self.name, self.duration)

    # pylint: disable=arguments-differ
    def to_instruction(self, channel: PulseChannel, name=None) -> 'PulseInstruction':
        return PulseInstruction(self, channel, name=name)
    # pylint: enable=arguments-differ

class PulseInstruction(Instruction):
    """Instruction to drive a pulse to an `PulseChannel`. """

    def __init__(self, command: SamplePulse, channel: PulseChannel, name=None):
        super().__init__(command, channel, name=name)


# -*- coding: utf-8 -*-

# Copyright 2017, IBM.
#
# This source code is licensed under the Apache License, Version 2.0 found in
# the LICENSE.txt file in the root directory of this source tree.

"""
controlled-u3 gate.
"""
from qiskit.circuit import CompositeGate
from qiskit.circuit import Gate
from qiskit.circuit import QuantumCircuit
from qiskit.circuit import QuantumRegister
from qiskit.circuit.decorators import _op_expand, _to_bits
from qiskit.extensions.standard.u1 import U1Gate
from qiskit.extensions.standard.u3 import U3Gate
from qiskit.extensions.standard.cx import CnotGate

class Cu3Gate(Gate):
    """controlled-u3 gate."""

    def __init__(self, theta, phi, lam):
        """Create new cu3 gate."""
        super().__init__("cu3", 2, [theta, phi, lam])

    def _define(self):
        """
        gate cu3(theta,phi,lambda) c, t
        { u1((lambda-phi)/2) t; cx c,t;
          u3(-theta/2,0,-(phi+lambda)/2) t; cx c,t;
          u3(theta/2,phi,0) t;
        }
        """
        definition = []
        q = QuantumRegister(2, "q")
        rule = [
            (U1Gate((self.params[2] - self.params[1]) / 2), [q[1]], []),
            (CnotGate(), [q[0], q[1]], []),
            (U3Gate(-self.params[0] / 2, 0, -(self.params[1] + self.params[2]) / 2), [q[1]], []),
            (CnotGate(), [q[0], q[1]], []),
            (U3Gate(self.params[0] / 2, self.params[1], 0), [q[1]], [])
        ]
        for inst in rule:
            definition.append(inst)
        self.definition = definition

    def inverse(self):
        """Invert this gate."""
        return Cu3Gate(-self.params[0], -self.params[2], -self.params[1])

@_to_bits(2)
@_op_expand(2)
def cu3(self, theta, phi, lam, ctl, tgt):
    """Apply cu3 from ctl to tgt with angle theta, phi, lam."""
    return self.append(Cu3Gate(theta, phi, lam), [ctl, tgt], [])

QuantumCircuit.cu3 = cu3
CompositeGate.cu3 = cu3


# -*- coding: utf-8 -*-

# Copyright 2018, IBM.
#
# This source code is licensed under the Apache License, Version 2.0 found in
# the LICENSE.txt file in the root directory of this source tree.

"""
Example showing how to draw a quantum circuit using Qiskit Terra.

"""

from qiskit import QuantumCircuit, QuantumRegister, ClassicalRegister

def build_bell_circuit():
    """Returns a circuit putting 2 qubits in the Bell state."""
    q = QuantumRegister(2)
    c = ClassicalRegister(2)
    qc = QuantumCircuit(q, c)
    qc.h(q[0])
    qc.cx(q[0], q[1])
    qc.measure(q, c)
    return qc

# Create the circuit
bell_circuit = build_bell_circuit()

# Use the internal .draw() to print the circuit
print(bell_circuit)


# -*- coding: utf-8 -*-

# Copyright 2019, IBM.
#
# This source code is licensed under the Apache License, Version 2.0 found in
# the LICENSE.txt file in the root directory of this source tree.

"""Circuit transpile function"""
import warnings

from qiskit.transpiler import Layout, CouplingMap
from qiskit.tools.parallel import parallel_map
from qiskit.transpiler.preset_passmanagers import (default_pass_manager_simulator,
                                                   default_pass_manager)
from qiskit.compiler.transpile_config import TranspileConfig
from qiskit.pulse import Schedule

def transpile(circuits,
              backend=None,
              basis_gates=None, coupling_map=None, backend_properties=None,
              initial_layout=None, seed_transpiler=None,
              optimization_level=None,
              pass_manager=None,
              seed_mapper=None):  # deprecated
    """transpile one or more circuits, according to some desired
    transpilation targets.

    All arguments may be given as either singleton or list. In case of list,
    the length must be equal to the number of circuits being transpiled.

    Transpilation is done in parallel using multiprocessing.

    Args:
        circuits (QuantumCircuit or list[QuantumCircuit]):
            Circuit(s) to transpile

        backend (BaseBackend):
            If set, transpiler options are automatically grabbed from
            backend.configuration() and backend.properties().
            If any other option is explicitly set (e.g. coupling_map), it
            will override the backend's.
            Note: the backend arg is purely for convenience. The resulting
                circuit may be run on any backend as long as it is compatible.

        basis_gates (list[str]):
            List of basis gate names to unroll to.
            e.g:
                ['u1', 'u2', 'u3', 'cx']
            If None, do not unroll.

        coupling_map (CouplingMap or list):
            Coupling map (perhaps custom) to target in mapping.
            Multiple formats are supported:
            a. CouplingMap instance

            b. list
                Must be given as an adjacency matrix, where each entry
                specifies all two-qubit interactions supported by backend
                e.g:
                    [[0, 1], [0, 3], [1, 2], [1, 5], [2, 5], [4, 1], [5, 3]]

        backend_properties (BackendProperties):
            properties returned by a backend, including information on gate
            errors, readout errors, qubit coherence times, etc. For a backend
            that provides this information, it can be obtained with:
            ``backend.properties()``

        initial_layout (Layout or dict or list):
            Initial position of virtual qubits on physical qubits.
            If this layout makes the circuit compatible with the coupling_map
            constraints, it will be used.
            The final layout is not guaranteed to be the same, as the transpiler
            may permute qubits through swaps or other means.

            Multiple formats are supported:
            a. Layout instance

            b. dict
                virtual to physical:
                    {qr[0]: 0,
                     qr[1]: 3,
                     qr[2]: 5}

                physical to virtual:
                    {0: qr[0],
                     3: qr[1],
                     5: qr[2]}

            c. list
                virtual to physical:
                    [0, 3, 5]  # virtual qubits are ordered (in addition to named)

                physical to virtual:
                    [qr[0], None, None, qr[1], None, qr[2]]

        seed_transpiler (int):
            sets random seed for the stochastic parts of the transpiler

        optimization_level (int):
            How much optimization to perform on the circuits.
            Higher levels generate more optimized circuits,
            at the expense of longer transpilation time.
                0: no optimization
                1: light optimization
                2: heavy optimization

        pass_manager (PassManager):
            The pass manager to use for a custom pipeline of transpiler passes.
            If this arg is present, all other args will be ignored and the
            pass manager will be used directly (Qiskit will not attempt to
            auto-select a pass manager based on transpile options).

        seed_mapper (int):
            DEPRECATED in 0.8: use ``seed_transpiler`` kwarg instead

    Returns:
        QuantumCircuit or list[QuantumCircuit]: transpiled circuit(s).

    Raises:
        TranspilerError: in case of bad inputs to transpiler or errors in passes
    """
    # Deprecation matter
    if seed_mapper:
        warnings.warn("seed_mapper has been deprecated and will be removed in the "
                      "0.9 release. Instead use seed_transpiler to set the seed "
                      "for all stochastic parts of the.", DeprecationWarning)
        seed_transpiler = seed_mapper

    # transpiling schedules is not supported yet.
    if isinstance(circuits, Schedule) or \
       (isinstance(circuits, list) and all(isinstance(c, Schedule) for c in circuits)):
        return circuits

    # Get TranspileConfig(s) to configure the circuit transpilation job(s)
    circuits = circuits if isinstance(circuits, list) else [circuits]
    transpile_configs = _parse_transpile_args(circuits, backend, basis_gates, coupling_map,
                                              backend_properties, initial_layout,
                                              seed_transpiler, optimization_level,
                                              pass_manager)

    # Transpile circuits in parallel
    circuits = parallel_map(_transpile_circuit, list(zip(circuits, transpile_configs)))

    if len(circuits) == 1:
        return circuits[0]
    return circuits

# FIXME: (Ali) This function should really be public and have the
# signature (circuit, transpile_config). It is currently written like this
# because our parallel tool can only parallelize functions over one variable.
def _transpile_circuit(circuit_config_tuple):
    """Select a PassManager and run a single circuit through it.

    Args:
        circuit_config_tuple (tuple):
            circuit (QuantumCircuit): circuit to transpile
            transpile_config (TranspileConfig): configuration dictating how to transpile

    Returns:
        QuantumCircuit: transpiled circuit
    """
    circuit, transpile_config = circuit_config_tuple

    # if the pass manager is not already selected, choose an appropriate one.
    if transpile_config.pass_manager:
        pass_manager = transpile_config.pass_manager

    elif transpile_config.coupling_map:
        pass_manager = default_pass_manager(transpile_config.basis_gates,
                                            transpile_config.coupling_map,
                                            transpile_config.initial_layout,
                                            transpile_config.seed_transpiler)
    else:
        pass_manager = default_pass_manager_simulator(transpile_config.basis_gates)

    return pass_manager.run(circuit)

def _parse_transpile_args(circuits, backend,
                          basis_gates, coupling_map, backend_properties,
                          initial_layout, seed_transpiler, optimization_level,
                          pass_manager):
    """Resolve the various types of args allowed to the transpile() function through
    duck typing, overriding args, etc. Refer to the transpile() docstring for details on
    what types of inputs are allowed.

    Here the args are resolved by converting them to standard instances, and prioritizing
    them in case a transpile option is passed through multiple args (explicitly setting an
    arg has more priority than the arg set by backend)

    Returns:
        list[TranspileConfig]: a transpile config for each circuit, which is a standardized
            object that configures the transpiler and determines the pass manager to use.
    """
    # Each arg could be single or a list. If list, it must be the same size as
    # number of circuits. If single, duplicate to create a list of that size.
    num_circuits = len(circuits)

    basis_gates = _parse_basis_gates(basis_gates, backend, circuits)

    coupling_map = _parse_coupling_map(coupling_map, backend, num_circuits)

    backend_properties = _parse_backend_properties(backend_properties, backend, num_circuits)

    initial_layout = _parse_initial_layout(initial_layout, circuits)

    seed_transpiler = _parse_seed_transpiler(seed_transpiler, num_circuits)

    optimization_level = _parse_optimization_level(optimization_level, num_circuits)

    pass_manager = _parse_pass_manager(pass_manager, num_circuits)

    transpile_configs = []
    for args in zip(basis_gates, coupling_map, backend_properties, initial_layout,
                    seed_transpiler, optimization_level, pass_manager):
        transpile_config = TranspileConfig(basis_gates=args[0],
                                           coupling_map=args[1],
                                           backend_properties=args[2],
                                           initial_layout=args[3],
                                           seed_transpiler=args[4],
                                           optimization_level=args[5],
                                           pass_manager=args[6])
        transpile_configs.append(transpile_config)

    return transpile_configs

def _parse_basis_gates(basis_gates, backend, circuits):
    # try getting basis_gates from user, else backend
    if basis_gates is None:
        if getattr(backend, 'configuration', None):
            basis_gates = getattr(backend.configuration(), 'basis_gates', None)
    # basis_gates could be None, or a list of basis, e.g. ['u3', 'cx']
    if isinstance(basis_gates, str):
        warnings.warn("The parameter basis_gates is now a list of strings. "
                      "For example, this basis ['u1','u2','u3','cx'] should be used "
                      "instead of 'u1,u2,u3,cx'. The string format will be "
                      "removed after 0.9", DeprecationWarning, 2)
        basis_gates = basis_gates.split(',')
    if basis_gates is None or (isinstance(basis_gates, list) and
                               all(isinstance(i, str) for i in basis_gates)):
        basis_gates = [basis_gates] * len(circuits)
    # no basis means don't unroll (all circuit gates are valid basis)
    basis_gates = [[inst.name for inst, _, _ in circuit.data] if basis is None
                   else basis for basis, circuit in zip(basis_gates, circuits)]

    return basis_gates

def _parse_coupling_map(coupling_map, backend, num_circuits):
    # try getting coupling_map from user, else backend
    if coupling_map is None:
        if getattr(backend, 'configuration', None):
            coupling_map = getattr(backend.configuration(), 'coupling_map', None)
    # coupling_map could be None, or a list of lists, e.g. [[0, 1], [2, 1]]
    if coupling_map is None or isinstance(coupling_map, CouplingMap):
        coupling_map = [coupling_map] * num_circuits
    elif isinstance(coupling_map, list) and all(isinstance(i, list) and len(i) == 2
                                                for i in coupling_map):
        coupling_map = [coupling_map] * num_circuits
    coupling_map = [CouplingMap(cm) if isinstance(cm, list) else cm for cm in coupling_map]
    return coupling_map

def _parse_backend_properties(backend_properties, backend, num_circuits):
    # try getting backend_properties from user, else backend
    if backend_properties is None:
        if getattr(backend, 'properties', None):
            backend_properties = backend.properties()
    if not isinstance(backend_properties, list):
        backend_properties = [backend_properties] * num_circuits
    return backend_properties

def _parse_initial_layout(initial_layout, circuits):
    # initial_layout could be None, or a list of ints, e.g. [0, 5, 14]
    # or a list of tuples/None e.g. [qr[0], None, qr[1]] or a dict e.g. {qr[0]: 0}
    def _layout_from_raw(initial_layout, circuit):
        if isinstance(initial_layout, list):
            if all(isinstance(elem, int) for elem in initial_layout):
                initial_layout = Layout.from_intlist(initial_layout, *circuit.qregs)
            elif all(elem is None or isinstance(elem, tuple) for elem in initial_layout):
                initial_layout = Layout.from_tuplelist(initial_layout)
        elif isinstance(initial_layout, dict):
            initial_layout = Layout(initial_layout)
        return initial_layout
    # multiple layouts?
    if isinstance(initial_layout, list) and \
       any(isinstance(i, (list, dict)) for i in initial_layout):
        initial_layout = [_layout_from_raw(lo, circ) if isinstance(lo, (list, dict)) else lo
                          for lo, circ in zip(initial_layout, circuits)]
    else:
        # even if one layout, but multiple circuits, the layout needs to be adapted for each
        initial_layout = [_layout_from_raw(initial_layout, circ) for circ in circuits]
    if not isinstance(initial_layout, list):
        initial_layout = [initial_layout] * len(circuits)
    return initial_layout

def _parse_seed_transpiler(seed_transpiler, num_circuits):
    if not isinstance(seed_transpiler, list):
        seed_transpiler = [seed_transpiler] * num_circuits
    return seed_transpiler

def _parse_optimization_level(optimization_level, num_circuits):
    if not isinstance(optimization_level, list):
        optimization_level = [optimization_level] * num_circuits
    return optimization_level

def _parse_pass_manager(pass_manager, num_circuits):
    if not isinstance(pass_manager, list):
        pass_manager = [pass_manager] * num_circuits
    return pass_manager


# -*- coding: utf-8 -*-

# Copyright 2019, IBM.
#
# This source code is licensed under the Apache License, Version 2.0 found in
# the LICENSE.txt file in the root directory of this source tree.

"""
Helper module for simplified Qiskit usage.

In general we recommend using the SDK modules directly. However, to get something
running quickly we have provided this wrapper module.
"""
import warnings
import logging

from qiskit.compiler import transpile, assemble

logger = logging.getLogger(__name__)

def execute(experiments, backend,
            basis_gates=None, coupling_map=None,  # circuit transpile options
            backend_properties=None, initial_layout=None,
            seed_transpiler=None, optimization_level=None, pass_manager=None,
            qobj_id=None, qobj_header=None, shots=1024,  # common run options
            memory=False, max_credits=10, seed_simulator=None,
            default_qubit_los=None, default_meas_los=None,  # schedule run options
            schedule_los=None, meas_level=2, meas_return='avg',
            memory_slots=None, memory_slot_size=100, rep_time=None, parameter_binds=None,
            seed=None, seed_mapper=None,  # deprecated
            config=None, circuits=None,
            **run_config):
    """Execute a list of circuits or pulse schedules on a backend.

    The execution is asynchronous, and a handle to a job instance is returned.

    Args:
        experiments (QuantumCircuit or list[QuantumCircuit] or Schedule or list[Schedule]):
            Circuit(s) or pulse schedule(s) to execute

        backend (BaseBackend):
            Backend to execute circuits on.
            Transpiler options are automatically grabbed from
            backend.configuration() and backend.properties().
            If any other option is explicitly set (e.g. coupling_map), it
            will override the backend's.

        basis_gates (list[str]):
            List of basis gate names to unroll to.
            e.g:
                ['u1', 'u2', 'u3', 'cx']
            If None, do not unroll.

        coupling_map (CouplingMap or list):
            Coupling map (perhaps custom) to target in mapping.
            Multiple formats are supported:
            a. CouplingMap instance

            b. list
                Must be given as an adjacency matrix, where each entry
                specifies all two-qubit interactions supported by backend
                e.g:
                    [[0, 1], [0, 3], [1, 2], [1, 5], [2, 5], [4, 1], [5, 3]]

        backend_properties (BackendProperties):
            Properties returned by a backend, including information on gate
            errors, readout errors, qubit coherence times, etc. For a backend
            that provides this information, it can be obtained with:
            ``backend.properties()``

        initial_layout (Layout or dict or list):
            Initial position of virtual qubits on physical qubits.
            If this layout makes the circuit compatible with the coupling_map
            constraints, it will be used.
            The final layout is not guaranteed to be the same, as the transpiler
            may permute qubits through swaps or other means.

            Multiple formats are supported:
            a. Layout instance

            b. dict
                virtual to physical:
                    {qr[0]: 0,
                     qr[1]: 3,
                     qr[2]: 5}

                physical to virtual:
                    {0: qr[0],
                     3: qr[1],
                     5: qr[2]}

            c. list
                virtual to physical:
                    [0, 3, 5]  # virtual qubits are ordered (in addition to named)

                physical to virtual:
                    [qr[0], None, None, qr[1], None, qr[2]]

        seed_transpiler (int):
            Sets random seed for the stochastic parts of the transpiler

        optimization_level (int):
            How much optimization to perform on the circuits.
            Higher levels generate more optimized circuits,
            at the expense of longer transpilation time.
                0: no optimization
                1: light optimization
                2: heavy optimization

        pass_manager (PassManager):
            The pass manager to use during transpilation. If this arg is present,
            auto-selection of pass manager based on the transpile options will be
            turned off and this pass manager will be used directly.

        qobj_id (str):
            String identifier to annotate the Qobj

        qobj_header (QobjHeader or dict):
            User input that will be inserted in Qobj header, and will also be
            copied to the corresponding Result header. Headers do not affect the run.

        shots (int):
            Number of repetitions of each circuit, for sampling. Default: 2014

        memory (bool):
            If True, per-shot measurement bitstrings are returned as well
            (provided the backend supports it). For OpenPulse jobs, only
            measurement level 2 supports this option. Default: False

        max_credits (int):
            Maximum credits to spend on job. Default: 10

        seed_simulator (int):
            Random seed to control sampling, for when backend is a simulator

        default_qubit_los (list):
            List of default qubit lo frequencies

        default_meas_los (list):
            List of default meas lo frequencies

        schedule_los (None or list[Union[Dict[PulseChannel, float], LoConfig]] or
                      Union[Dict[PulseChannel, float], LoConfig]):
            Experiment LO configurations

        meas_level (int):
            Set the appropriate level of the measurement output for pulse experiments.

        meas_return (str):
            Level of measurement data for the backend to return
            For `meas_level` 0 and 1:
                "single" returns information from every shot.
                "avg" returns average measurement output (averaged over number of shots).

        memory_slots (int):
            Number of classical memory slots used in this job.

        memory_slot_size (int):
            Size of each memory slot if the output is Level 0.

        rep_time (int): repetition time of the experiment in μs.
            The delay between experiments will be rep_time.
            Must be from the list provided by the device.

        parameter_binds (list[dict{Parameter: Value}]):
            List of Parameter bindings over which the set of experiments will be
            executed. Each list element (bind) should be of the form
            {Parameter1: value1, Parameter2: value2, ...}. All binds will be
            executed across all experiments, e.g. if parameter_binds is a
            length-n list, and there are m experiments, a total of m x n
            experiments will be run (one for each experiment/bind pair).

        seed (int):
            DEPRECATED in 0.8: use ``seed_simulator`` kwarg instead

        seed_mapper (int):
            DEPRECATED in 0.8: use ``seed_transpiler`` kwarg instead

        config (dict):
            DEPRECATED in 0.8: use run_config instead

        circuits (QuantumCircuit or list[QuantumCircuit]):
            DEPRECATED in 0.8: use ``experiments`` kwarg instead.

        run_config (dict):
            Extra arguments used to configure the run (e.g. for Aer configurable backends)
            Refer to the backend documentation for details on these arguments
            Note: for now, these keyword arguments will both be copied to the
            Qobj config, and passed to backend.run()

    Returns:
        BaseJob: returns job instance derived from BaseJob

    Raises:
        QiskitError: if the execution cannot be interpreted as either circuits or schedules
    """
    if circuits is not None:
        experiments = circuits
        warnings.warn("the `circuits` arg in `execute()` has been deprecated. "
                      "please use `experiments`, which can handle both circuit "
                      "and pulse Schedules", DeprecationWarning)

    # transpiling the circuits using given transpile options
    experiments = transpile(experiments,
                            basis_gates=basis_gates,
                            coupling_map=coupling_map,
                            backend_properties=backend_properties,
                            initial_layout=initial_layout,
                            seed_transpiler=seed_transpiler,
                            optimization_level=optimization_level,
                            backend=backend,
                            pass_manager=pass_manager,
                            seed_mapper=seed_mapper,  # deprecated
                            )

    # assembling the circuits into a qobj to be run on the backend
    qobj = assemble(experiments,
                    qobj_id=qobj_id,
                    qobj_header=qobj_header,
                    shots=shots,
                    memory=memory,
                    max_credits=max_credits,
                    seed_simulator=seed_simulator,
                    default_qubit_los=default_qubit_los,
                    default_meas_los=default_meas_los,
                    schedule_los=schedule_los,
                    meas_level=meas_level,
                    meas_return=meas_return,
                    memory_slots=memory_slots,
                    memory_slot_size=memory_slot_size,
                    rep_time=rep_time,
                    parameter_binds=parameter_binds,
                    backend=backend,
                    config=config,  # deprecated
                    seed=seed,  # deprecated
                    run_config=run_config
                    )

    # executing the circuits on the backend and returning the job
    return backend.run(qobj, **run_config)


# -*- coding: utf-8 -*-

# Copyright 2019, IBM.
#
# This source code is licensed under the Apache License, Version 2.0 found in
# the LICENSE.txt file in the root directory of this source tree.

"""
Physical qubit.
"""
from typing import List

from qiskit.pulse.exceptions import PulseError
from .pulse_channels import DriveChannel, ControlChannel, MeasureChannel
from .channels import AcquireChannel

class Qubit:
    """Physical qubit."""

    def __init__(self, index: int,
                 drive_channels: List[DriveChannel] = None,
                 control_channels: List[ControlChannel] = None,
                 measure_channels: List[MeasureChannel] = None,
                 acquire_channels: List[AcquireChannel] = None):
        self._index = index
        self._drives = drive_channels
        self._controls = control_channels
        self._measures = measure_channels
        self._acquires = acquire_channels

    def __eq__(self, other):
        """Two physical qubits are the same if they have the same index and channels.

        Args:
            other (Qubit): other Qubit

        Returns:
            bool: are self and other equal.
        """
        # pylint: disable=too-many-boolean-expressions
        if (type(self) is type(other) and
                self._index == other._index and
                self._drives == other._drives and
                self._controls == other._controls and
                self._measures == other._measures and
                self._acquires == other._acquires):
            return True
        return False

    @property
    def index(self) -> int:
        """Return the index of this qubit."""
        return self._index

    @property
    def drive(self) -> DriveChannel:
        """Return the primary drive channel of this qubit."""
        if self._drives:
            return self._drives[0]
        else:
            raise PulseError("No drive channels in q[%d]" % self._index)

    @property
    def control(self) -> ControlChannel:
        """Return the primary control channel of this qubit."""
        if self._controls:
            return self._controls[0]
        else:
            raise PulseError("No control channels in q[%d]" % self._index)

    @property
    def measure(self) -> MeasureChannel:
        """Return the primary measure channel of this qubit."""
        if self._measures:
            return self._measures[0]
        else:
            raise PulseError("No measurement channels in q[%d]" % self._index)

    @property
    def acquire(self) -> AcquireChannel:
        """Return the primary acquire channel of this qubit."""
        if self._acquires:
            return self._acquires[0]
        else:
            raise PulseError("No acquire channels in q[%d]" % self._index)


# -*- coding: utf-8 -*-

# Copyright 2017, IBM.
#
# This source code is licensed under the Apache License, Version 2.0 found in
# the LICENSE.txt file in the root directory of this source tree.

"""
Quantum Fourier Transform examples.

Note: if you have only cloned the Qiskit repository but not
used `pip install`, the examples only work from the root directory.
"""

import math
from qiskit import QuantumRegister, ClassicalRegister, QuantumCircuit
from qiskit import execute, BasicAer
from qiskit.providers.ibmq import least_busy, IBMQ

###############################################################
# make the qft
###############################################################
def input_state(circ, q, n):
    """n-qubit input state for QFT that produces output 1."""
    for j in range(n):
        circ.h(q[j])
        circ.u1(math.pi/float(2**(j)), q[j]).inverse()

def qft(circ, q, n):
    """n-qubit QFT on q in circ."""
    for j in range(n):
        for k in range(j):
            circ.cu1(math.pi/float(2**(j-k)), q[j], q[k])
        circ.h(q[j])

q = QuantumRegister(5, "q")
c = ClassicalRegister(5, "c")
qft3 = QuantumCircuit(q, c, name="qft3")
qft4 = QuantumCircuit(q, c, name="qft4")
qft5 = QuantumCircuit(q, c, name="qft5")

input_state(qft3, q, 3)
qft3.barrier()
qft(qft3, q, 3)
qft3.barrier()
for j in range(3):
    qft3.measure(q[j], c[j])

input_state(qft4, q, 4)
qft4.barrier()
qft(qft4, q, 4)
qft4.barrier()
for j in range(4):
    qft4.measure(q[j], c[j])

input_state(qft5, q, 5)
qft5.barrier()
qft(qft5, q, 5)
qft5.barrier()
for j in range(5):
    qft5.measure(q[j], c[j])

print(qft3)
print(qft4)
print(qft5)

###############################################################
# Set up the API and execute the program.
###############################################################
try:
    IBMQ.load_accounts()
except:
    print("""WARNING: There's no connection with the API for remote backends.
             Have you initialized a file with your personal token?
             For now, there's only access to local simulator backends...""")

print('Qasm simulator')
sim_backend = BasicAer.get_backend('qasm_simulator')
job = execute([qft3, qft4, qft5], sim_backend, shots=1024)
result = job.result()
print(result.get_counts(qft3))
print(result.get_counts(qft4))
print(result.get_counts(qft5))

# Second version: real device
least_busy_device = least_busy(IBMQ.backends(simulator=False,
                                             filters=lambda x: x.configuration().n_qubits > 4))
print("Running on current least busy device: ", least_busy_device)
job = execute([qft3, qft4, qft5], least_busy_device, shots=1024)
result = job.result()
print(result.get_counts(qft3))
print(result.get_counts(qft4))
print(result.get_counts(qft5))


# -*- coding: utf-8 -*-

# Copyright 2019, IBM.
#
# This source code is licensed under the Apache License, Version 2.0 found in
# the LICENSE.txt file in the root directory of this source tree.

"""Assemble function for converting a list of circuits into a qobj"""
import warnings
import uuid
import logging
import copy

from qiskit.circuit import QuantumCircuit
from qiskit.exceptions import QiskitError
from qiskit.pulse import Schedule, LoConfig
from qiskit.pulse.commands import PulseInstruction
from qiskit.compiler.run_config import RunConfig
from qiskit.qobj import (QasmQobj, PulseQobj, QobjExperimentHeader, QobjHeader,
                         QasmQobjInstruction, QasmQobjExperimentConfig, QasmQobjExperiment,
                         QasmQobjConfig, PulseQobjInstruction, PulseQobjExperimentConfig,
                         PulseQobjExperiment, PulseQobjConfig, QobjPulseLibrary)
from qiskit.qobj.converters import PulseQobjConverter, LoConfigConverter
from qiskit.validation.exceptions import ModelValidationError

logger = logging.getLogger(__name__)

def assemble_circuits(circuits, qobj_id=None, qobj_header=None, run_config=None):
    """Assembles a list of circuits into a qobj which can be run on the backend.

    Args:
        circuits (list[QuantumCircuits]): circuit(s) to assemble
        qobj_id (int): identifier for the generated qobj
        qobj_header (QobjHeader): header to pass to the results
        run_config (RunConfig): configuration of the runtime environment

    Returns:
        QasmQobj: the Qobj to be run on the backends
    """
    qobj_config = QasmQobjConfig()
    if run_config:
        qobj_config = QasmQobjConfig(**run_config.to_dict())

    # Pack everything into the Qobj
    experiments = []
    max_n_qubits = 0
    max_memory_slots = 0
    for circuit in circuits:
        # header stuff
        n_qubits = 0
        memory_slots = 0
        qubit_labels = []
        clbit_labels = []

        qreg_sizes = []
        creg_sizes = []
        for qreg in circuit.qregs:
            qreg_sizes.append([qreg.name, qreg.size])
            for j in range(qreg.size):
                qubit_labels.append([qreg.name, j])
            n_qubits += qreg.size
        for creg in circuit.cregs:
            creg_sizes.append([creg.name, creg.size])
            for j in range(creg.size):
                clbit_labels.append([creg.name, j])
            memory_slots += creg.size

        # TODO: why do we need creq_sizes and qreg_sizes in header
        # TODO: we need to rethink memory_slots as they are tied to classical bit
        experimentheader = QobjExperimentHeader(qubit_labels=qubit_labels,
                                                n_qubits=n_qubits,
                                                qreg_sizes=qreg_sizes,
                                                clbit_labels=clbit_labels,
                                                memory_slots=memory_slots,
                                                creg_sizes=creg_sizes,
                                                name=circuit.name)
        # TODO: why do we need n_qubits and memory_slots in both the header and the config
        experimentconfig = QasmQobjExperimentConfig(n_qubits=n_qubits, memory_slots=memory_slots)

        # Convert conditionals from QASM-style (creg ?= int) to qobj-style
        # (register_bit ?= 1), by assuming device has unlimited register slots
        # (supported only for simulators). Map all measures to a register matching
        # their clbit_index, create a new register slot for every conditional gate
        # and add a bfunc to map the creg=val mask onto the gating register bit.

        is_conditional_experiment = any(op.control for (op, qargs, cargs) in circuit.data)
        max_conditional_idx = 0

        instructions = []
        for op_context in circuit.data:
            instruction = op_context[0].assemble()

            # Add register attributes to the instruction
            qargs = op_context[1]
            cargs = op_context[2]
            if qargs:
                qubit_indices = [qubit_labels.index([qubit[0].name, qubit[1]])
                                 for qubit in qargs]
                instruction.qubits = qubit_indices
            if cargs:
                clbit_indices = [clbit_labels.index([clbit[0].name, clbit[1]])
                                 for clbit in cargs]
                instruction.memory = clbit_indices
                # If the experiment has conditional instructions, assume every
                # measurement result may be needed for a conditional gate.
                if instruction.name == "measure" and is_conditional_experiment:
                    instruction.register = clbit_indices

            # To convert to a qobj-style conditional, insert a bfunc prior
            # to the conditional instruction to map the creg ?= val condition
            # onto a gating register bit.
            if hasattr(instruction, '_control'):
                ctrl_reg, ctrl_val = instruction._control
                mask = 0
                val = 0
                for clbit in clbit_labels:
                    if clbit[0] == ctrl_reg.name:
                        mask |= (1 << clbit_labels.index(clbit))
                        val |= (((ctrl_val >> clbit[1]) & 1) << clbit_labels.index(clbit))

                conditional_reg_idx = memory_slots + max_conditional_idx
                conversion_bfunc = QasmQobjInstruction(name='bfunc',
                                                       mask="0x%X" % mask,
                                                       relation='==',
                                                       val="0x%X" % val,
                                                       register=conditional_reg_idx)
                instructions.append(conversion_bfunc)
                instruction.conditional = conditional_reg_idx
                max_conditional_idx += 1
                # Delete control attribute now that we have replaced it with
                # the conditional and bfuc
                del instruction._control

            instructions.append(instruction)

        experiments.append(QasmQobjExperiment(instructions=instructions, header=experimentheader,
                                              config=experimentconfig))
        if n_qubits > max_n_qubits:
            max_n_qubits = n_qubits
        if memory_slots > max_memory_slots:
            max_memory_slots = memory_slots

    qobj_config.memory_slots = max_memory_slots
    qobj_config.n_qubits = max_n_qubits

    return QasmQobj(qobj_id=qobj_id,
                    config=qobj_config,
                    experiments=experiments,
                    header=qobj_header)

def assemble_schedules(schedules, qobj_id=None, qobj_header=None, run_config=None):
    """Assembles a list of schedules into a qobj which can be run on the backend.
    Args:
        schedules (list[Schedule]): schedules to assemble
        qobj_id (int): identifier for the generated qobj
        qobj_header (QobjHeader): header to pass to the results
        run_config (RunConfig): configuration of the runtime environment
    Returns:
        PulseQobj: the Qobj to be run on the backends
    Raises:
        QiskitError: when invalid schedules or configs are provided
    """
    qobj_config = QasmQobjConfig()
    if run_config:
        qobj_config = QasmQobjConfig(**run_config.to_dict())

    # Get appropriate convertors
    instruction_converter = PulseQobjConverter
    instruction_converter = instruction_converter(PulseQobjInstruction, **run_config.to_dict())
    lo_converter = LoConfigConverter(PulseQobjExperimentConfig, run_config.qubit_lo_freq,
                                     run_config.meas_lo_freq, **run_config.to_dict())

    # Pack everything into the Qobj
    qobj_schedules = []
    user_pulselib = set()
    for idx, schedule in enumerate(schedules):
        # instructions
        qobj_instructions = []
        # Instructions are returned as tuple of shifted time and instruction
        for shift, instruction in schedule.instructions:
            # TODO: support conditional gate
            qobj_instructions.append(instruction_converter(shift, instruction))
            if isinstance(instruction, PulseInstruction):
                # add samples to pulse library
                user_pulselib.add(instruction.command)
        # experiment header
        qobj_experiment_header = QobjExperimentHeader(
            name=schedule.name or 'Experiment-%d' % idx
        )

        qobj_schedules.append({
            'header': qobj_experiment_header,
            'instructions': qobj_instructions
        })

    # setup pulse_library
    run_config.pulse_library = [QobjPulseLibrary(name=pulse.name, samples=pulse.samples)
                                for pulse in user_pulselib]

    # create qob experiment field
    experiments = []
    if len(run_config.schedule_los) == 1:
        lo_dict = run_config.schedule_los.pop()
        # update global config
        q_los = lo_converter.get_qubit_los(lo_dict)
        if q_los:
            run_config.qubit_lo_freq = q_los
        m_los = lo_converter.get_meas_los(lo_dict)
        if m_los:
            run_config.meas_lo_freq = m_los

    if run_config.schedule_los:
        # multiple frequency setups
        if len(qobj_schedules) == 1:
            # frequency sweep
            for lo_dict in run_config.schedule_los:
                experiments.append(PulseQobjExperiment(
                    instructions=qobj_schedules[0]['instructions'],
                    experimentheader=qobj_schedules[0]['header'],
                    experimentconfig=lo_converter(lo_dict)
                ))
        elif len(qobj_schedules) == len(run_config.schedule_los):
            # n:n setup
            for lo_dict, schedule in zip(run_config.schedule_los, qobj_schedules):
                experiments.append(PulseQobjExperiment(
                    instructions=schedule['instructions'],
                    experimentheader=schedule['header'],
                    experimentconfig=lo_converter(lo_dict)
                ))
        else:
            raise QiskitError('Invalid LO setting is specified. '
                              'The LO should be configured for each schedule, or '
                              'single setup for all schedules (unique), or '
                              'multiple setups for a single schedule (frequency sweep),'
                              'or no LO configured at all.')
    else:
        # unique frequency setup
        for schedule in qobj_schedules:
            experiments.append(PulseQobjExperiment(
                instructions=schedule['instructions'],
                experimentheader=schedule['header'],
            ))

    qobj_config = PulseQobjConfig(**run_config.to_dict())

    return PulseQobj(qobj_id=qobj_id,
                     config=qobj_config,
                     experiments=experiments,
                     header=qobj_header)

# TODO: parallelize over the experiments (serialize each separately, then add global header/config)
def assemble(experiments,
             backend=None,
             qobj_id=None, qobj_header=None,  # common run options
             shots=1024, memory=False, max_credits=None, seed_simulator=None,
             default_qubit_los=None, default_meas_los=None,  # schedule run options
             schedule_los=None, meas_level=2, meas_return='avg',
             memory_slots=None, memory_slot_size=100, rep_time=None, parameter_binds=None,
             config=None, seed=None,  # deprecated
             **run_config):
    """Assemble a list of circuits or pulse schedules into a Qobj.

    This function serializes the payloads, which could be either circuits or schedules,
    to create Qobj "experiments". It further annotates the experiment payload with
    header and configurations.

    Args:
        experiments (QuantumCircuit or list[QuantumCircuit] or Schedule or list[Schedule]):
            Circuit(s) or pulse schedule(s) to execute

        backend (BaseBackend):
            If set, some runtime options are automatically grabbed from
            backend.configuration() and backend.defaults().
            If any other option is explicitly set (e.g. rep_rate), it
            will override the backend's.
            If any other options is set in the run_config, it will
            also override the backend's.

        qobj_id (str):
            String identifier to annotate the Qobj

        qobj_header (QobjHeader or dict):
            User input that will be inserted in Qobj header, and will also be
            copied to the corresponding Result header. Headers do not affect the run.

        shots (int):
            Number of repetitions of each circuit, for sampling. Default: 2014

        memory (bool):
            If True, per-shot measurement bitstrings are returned as well
            (provided the backend supports it). For OpenPulse jobs, only
            measurement level 2 supports this option. Default: False

        max_credits (int):
            Maximum credits to spend on job. Default: 10

        seed_simulator (int):
            Random seed to control sampling, for when backend is a simulator

        default_qubit_los (list):
            List of default qubit lo frequencies

        default_meas_los (list):
            List of default meas lo frequencies

        schedule_los (None or list[Union[Dict[PulseChannel, float], LoConfig]] or
                      Union[Dict[PulseChannel, float], LoConfig]):
            Experiment LO configurations

        meas_level (int):
            Set the appropriate level of the measurement output for pulse experiments.

        meas_return (str):
            Level of measurement data for the backend to return
            For `meas_level` 0 and 1:
                "single" returns information from every shot.
                "avg" returns average measurement output (averaged over number of shots).

        memory_slots (int):
            Number of classical memory slots used in this job.

        memory_slot_size (int):
            Size of each memory slot if the output is Level 0.

        rep_time (int): repetition time of the experiment in μs.
            The delay between experiments will be rep_time.
            Must be from the list provided by the device.

        parameter_binds (list[dict{Parameter: Value}]):
            List of Parameter bindings over which the set of experiments will be
            executed. Each list element (bind) should be of the form
            {Parameter1: value1, Parameter2: value2, ...}. All binds will be
            executed across all experiments, e.g. if parameter_binds is a
            length-n list, and there are m experiments, a total of m x n
            experiments will be run (one for each experiment/bind pair).

        seed (int):
            DEPRECATED in 0.8: use ``seed_simulator`` kwarg instead

        config (dict):
            DEPRECATED in 0.8: use run_config instead

        run_config (dict):
            extra arguments used to configure the run (e.g. for Aer configurable backends)
            Refer to the backend documentation for details on these arguments

    Returns:
        Qobj: a qobj which can be run on a backend. Depending on the type of input,
            this will be either a QasmQobj or a PulseQobj.

    Raises:
        QiskitError: if the input cannot be interpreted as either circuits or schedules
    """
    # deprecation matter
    if config:
        warnings.warn('config is not used anymore. Set all configs in '
                      'run_config.', DeprecationWarning)
        run_config = run_config or config
    if seed:
        warnings.warn('seed is deprecated in favor of seed_simulator.', DeprecationWarning)
        seed_simulator = seed_simulator or seed

    # Get RunConfig(s) that will be inserted in Qobj to configure the run
    experiments = experiments if isinstance(experiments, list) else [experiments]
    qobj_id, qobj_header, run_config = _parse_run_args(backend, qobj_id, qobj_header,
                                                       shots, memory, max_credits, seed_simulator,
                                                       default_qubit_los, default_meas_los,
                                                       schedule_los, meas_level, meas_return,
                                                       memory_slots, memory_slot_size, rep_time,
                                                       parameter_binds, **run_config)

    # assemble either circuits or schedules
    if all(isinstance(exp, QuantumCircuit) for exp in experiments):
        # If circuits are parameterized, bind parameters and remove from run_config
        bound_experiments, run_config = _expand_parameters(circuits=experiments,
                                                           run_config=run_config)
        return assemble_circuits(circuits=bound_experiments, qobj_id=qobj_id,
                                 qobj_header=qobj_header, run_config=run_config)

    elif all(isinstance(exp, Schedule) for exp in experiments):
        return assemble_schedules(schedules=experiments, qobj_id=qobj_id,
                                  qobj_header=qobj_header, run_config=run_config)

    else:
        raise QiskitError("bad input to assemble() function; "
                          "must be either circuits or schedules")

# TODO: rework to return a list of RunConfigs (one for each experiments), and a global one
def _parse_run_args(backend, qobj_id, qobj_header,
                    shots, memory, max_credits, seed_simulator,
                    default_qubit_los, default_meas_los,
                    schedule_los, meas_level, meas_return,
                    memory_slots, memory_slot_size, rep_time,
                    parameter_binds, **run_config):
    """Resolve the various types of args allowed to the assemble() function through
    duck typing, overriding args, etc. Refer to the assemble() docstring for details on
    what types of inputs are allowed.

    Here the args are resolved by converting them to standard instances, and prioritizing
    them in case a run option is passed through multiple args (explicitly setting an arg
    has more priority than the arg set by backend)

    Returns:
        RunConfig: a run config, which is a standardized object that configures the qobj
            and determines the runtime environment.
    """
    # grab relevant info from backend if it exists
    backend_config = None
    backend_default = None
    if backend:
        backend_config = backend.configuration()
        # TODO : Remove usage of config.defaults when backend.defaults() is updated.
        try:
            backend_default = backend.defaults()
        except (ModelValidationError, AttributeError):
            from collections import namedtuple
            backend_config_defaults = getattr(backend_config, 'defaults', {})
            BackendDefault = namedtuple('BackendDefault', ('qubit_freq_est', 'meas_freq_est'))
            backend_default = BackendDefault(
                qubit_freq_est=backend_config_defaults.get('qubit_freq_est'),
                meas_freq_est=backend_config_defaults.get('meas_freq_est')
            )

    memory_slots = memory_slots or getattr(backend_config, 'memory_slots', None)
    rep_time = rep_time or getattr(backend_config, 'rep_times', None)
    if isinstance(rep_time, list):
        rep_time = rep_time[-1]

    parameter_binds = parameter_binds or []

    # add default empty lo config
    schedule_los = schedule_los or []
    if isinstance(schedule_los, (LoConfig, dict)):
        schedule_los = [schedule_los]

    # Convert to LoConfig if lo configuration supplied as dictionary
    schedule_los = [lo_config if isinstance(lo_config, LoConfig) else LoConfig(lo_config)
                    for lo_config in schedule_los]

    qubit_lo_freq = default_qubit_los or getattr(backend_default, 'qubit_freq_est', [])
    meas_lo_freq = default_meas_los or getattr(backend_default, 'meas_freq_est', [])

    # an identifier for the Qobj
    qobj_id = qobj_id or str(uuid.uuid4())

    # The header that goes at the top of the Qobj (and later Result)
    # we process it as dict, then write entries that are not None to a QobjHeader object
    qobj_header = qobj_header or {}
    if isinstance(qobj_header, QobjHeader):
        qobj_header = qobj_header.to_dict()
    backend_name = getattr(backend_config, 'backend_name', None)
    backend_version = getattr(backend_config, 'backend_version', None)
    qobj_header = {**dict(backend_name=backend_name, backend_version=backend_version),
                   **qobj_header}
    qobj_header = QobjHeader(**{k: v for k, v in qobj_header.items() if v is not None})

    # create run configuration and populate
    run_config_dict = dict(shots=shots,
                           memory=memory,
                           max_credits=max_credits,
                           seed_simulator=seed_simulator,
                           seed=seed_simulator,  # deprecated
                           qubit_lo_freq=qubit_lo_freq,
                           meas_lo_freq=meas_lo_freq,
                           schedule_los=schedule_los,
                           meas_level=meas_level,
                           meas_return=meas_return,
                           memory_slots=memory_slots,
                           memory_slot_size=memory_slot_size,
                           rep_time=rep_time,
                           parameter_binds=parameter_binds,
                           **run_config)
    run_config = RunConfig(**{k: v for k, v in run_config_dict.items() if v is not None})

    return qobj_id, qobj_header, run_config

def _expand_parameters(circuits, run_config):
    """Verifies that there is a single common set of parameters shared between
    all circuits and all parameter binds in the run_config. Returns an expanded
    list of circuits (if parameterized) with all parameters bound, and a copy of
    the run_config with parameter_binds cleared.

    If neither the circuits nor the run_config specify parameters, the two are
    returned unmodified.

    Raises:
        QiskitError: if run_config parameters are not compatible with circuit parameters

    Returns:
        Tuple(List[QuantumCircuit], RunConfig):
          - List of input circuits expanded and with parameters bound
          - RunConfig with parameter_binds removed
    """

    parameter_binds = run_config.parameter_binds
    if parameter_binds or \
       any(circuit.parameters for circuit in circuits):

        all_bind_parameters = [bind.keys()
                               for bind in parameter_binds]
        all_circuit_parameters = [circuit.parameters for circuit in circuits]

        # Collect set of all unique parameters across all circuits and binds
        unique_parameters = set(param
                                for param_list in all_bind_parameters + all_circuit_parameters
                                for param in param_list)

        # Check that all parameters are common to all circuits and binds
        if not all_bind_parameters \
           or not all_circuit_parameters \
           or any(unique_parameters != bind_params for bind_params in all_bind_parameters) \
           or any(unique_parameters != parameters for parameters in all_circuit_parameters):
            raise QiskitError(
                ('Mismatch between run_config.parameter_binds and all circuit parameters. ' +
                 'Parameter binds: {} ' +
                 'Circuit parameters: {}').format(all_bind_parameters, all_circuit_parameters))

        circuits = [circuit.bind_parameters(binds)
                    for circuit in circuits
                    for binds in parameter_binds]

        # All parameters have been expanded and bound, so remove from run_config
        run_config = copy.deepcopy(run_config)
        run_config.parameter_binds = []

    return circuits, run_config