Example #1
0
def test_get_qvm_noise_supported_gates_from_aspen8_isa(
        qcs_aspen8_quantum_processor, noise_model_dict):
    gates = _get_qvm_noise_supported_gates(
        qcs_aspen8_quantum_processor.to_compiler_isa())

    for q in range(len(qcs_aspen8_quantum_processor._isa.architecture.nodes)):
        if q not in ASPEN_8_QUBITS_NO_RX:
            for g in [
                    RX(np.pi / 2, q),
                    RX(-np.pi / 2, q),
                    RX(np.pi, q),
                    RX(-np.pi, q),
            ]:
                assert g in gates
        if q not in ASPEN_8_QUBITS_NO_RZ:
            assert RZ(THETA, q) in gates

    for edge in qcs_aspen8_quantum_processor._isa.architecture.edges:
        if (
                edge.node_ids[0],
                edge.node_ids[1],
        ) in ASPEN_8_EDGES_NO_CZ:
            continue
        assert CZ(edge.node_ids[0], edge.node_ids[1]) in gates
        assert CZ(edge.node_ids[1], edge.node_ids[0]) in gates
def test_gates_in_isa(isa_dict):
    isa = ISA.from_dict(isa_dict)
    gates = gates_in_isa(isa)
    for q in [0, 1, 2]:
        for g in [I, RX(np.pi / 2), RX(-np.pi / 2), RZ(THETA)]:
            assert g(q) in gates

    assert CZ(0, 1) in gates
    assert CZ(1, 0) in gates
    assert ISWAP(1, 2) in gates
    assert ISWAP(2, 1) in gates
    assert CPHASE(THETA)(2, 0) in gates
    assert CPHASE(THETA)(0, 2) in gates
Example #3
0
def NN_encode(qubit: QubitPlaceholder,
              N: int) -> (Program, List[QubitPlaceholder]):

    ### qubit: qubit you want to encode (main qubit)
    ### N: number of qubits you want to encode the main qubit in.
    ### For N=1, there is no encoding

    code_register = QubitPlaceholder.register(
        N)  # the List[QubitPlaceholder] of the qubits you have encoded into
    code_register[0] = qubit

    pq = Program()

    ### creation of GHZ state:
    for ii in range(N - 1):
        pq += CNOT(code_register[ii], code_register[ii + 1])

    for jj in range(N - 1):
        pq += H(code_register[jj])
        pq += CZ(code_register[jj + 1], code_register[jj])

    for kk in range(N - 1):
        pq += CNOT(code_register[kk], code_register[-1])

    return pq, code_register
Example #4
0
def generate_parametric_cz_phase_ramsey_program(qcid: int,
                                                other_qcid: int) -> Program:
    """
    Generate a single CZ phase Ramsey experiment at a given phase.

    :param qcid: The qubit to move around the Bloch sphere and measure the incurred RZ on.
    :param other_qcid: The other qubit that constitutes a two-qubit pair along with `qcid`.
    :param phase: The phase kick to supply after playing the CZ pulse on the equator.
    :param num_shots: The number of shots to average over for the data point.
    :return: A parametric Program for performing a CZ Ramsey experiment.
    """
    program = Program()
    # NOTE: only need readout register for `qcid` not `other_qcid` since `other_qcid` is only
    #       needed to identify which CZ gate we're using
    ro = program.declare('ro', 'BIT', 1)
    theta = program.declare('theta', 'REAL')

    # go to the equator
    program += Program(RX(np.pi / 2, qcid))
    # apply the CZ gate - note that CZ is symmetric, so the order of qubits doesn't matter
    program += Program(CZ(qcid, other_qcid))
    # go to |1> after a phase kick
    program += Program(RZ(theta, qcid), RX(np.pi / 2, qcid))

    program += MEASURE(qcid, ro[0])

    return program
    def prep_circuit_program(self, prog):
        #Prepare parametric gates
        ro = prog.declare('ro', memory_type='BIT')
        self.params = self.get_params(prog)
        params_dict = {}
        for i in range(len(gates)):
            q1 = gates[i][0]
            q2 = gates[i][1]
            for k in range(0, 3):
                index = i * 18 + 6 * k
                angles = self.params[index], self.params[index +
                                                         1], self.params[index
                                                                         + 2]
                prog.inst([g for g in self.single_qubit_unitary(angles, q1)])
                index += 3
                angles = self.params[index], self.params[index +
                                                         1], self.params[index
                                                                         + 2]
                prog.inst([g for g in self.single_qubit_unitary(angles, q2)])
                prog.inst(CZ(q1, q2))

        index = 18 * len(gates)
        angles = self.params[index], self.params[index +
                                                 1], self.params[index + 2]
        prog.inst([g for g in self.single_qubit_unitary(angles, self.n - 1)])

        prog += MEASURE(15, ro)
        return prog
Example #6
0
def test_to_latex():
    """A test to give full coverage of latex_generation."""
    p = Program()
    p.inst(
        X(0),
        RX(1.0, 5),
        Y(0),
        CZ(0, 2),
        SWAP(0, 1),
        MEASURE(0, None),
        CNOT(2, 0),
        X(0).controlled(1),
        Y(0).dagger(),
    )
    _ = to_latex(p)

    # Modify settings to access non-standard control paths.
    settings = DiagramSettings(impute_missing_qubits=True)
    _ = to_latex(p, settings)

    settings = DiagramSettings(abbreviate_controlled_rotations=True)
    _ = to_latex(p, settings)

    settings = DiagramSettings(label_qubit_lines=False)
    _ = to_latex(p, settings)
Example #7
0
    def prep_circuit_program(self):
        prog = Program()
        #Prepare parametric gates
        self.params, self.params_mapping = self.get_params_and_mapping(prog)
        params_dict = {}
        l = math.floor(math.log(self.n, 2))
        for i in range(0, l):
            #number of gates in the ith layer is 2^(log(n)-i-1)
            for j in range(0, math.floor(math.pow(2, l-i-1))):
                q1 = 2**i - 1 + j*(2**(i + 1))
                q2 = q1  + 2**i
                for k in range(0, 3):
                    #TODO: call the function to create gates in here instead of creating them beforehand
                    #Declare the parameters here and just pass them to the single qqubit unitary function
                    #need to have the program handle a vector of params since our optimizers cannot handle a tensor or a dictionary
                    #make mapping between params tensor and vector
                    index = self.params_mapping[i][j][k][0]
                    angles = self.params[index], self.params[index+1], self.params[index+2]
                    prog.inst([g for g in self.single_qubit_unitary(angles, q1)])
                    index = self.params_mapping[i][j][k][1]
                    angles = self.params[index], self.params[index+1], self.params[index+2]
                    prog.inst([g for g in self.single_qubit_unitary(angles, q2)])
                    prog.inst(CZ(q1, q2))

        index = self.params_mapping[math.floor(math.log(self.n, 2))]
        angles = self.params[index], self.params[index+1], self.params[index+2]
        prog.inst([g for g in self.single_qubit_unitary(angles, math.floor(math.log(self.n, 2)))])
        ro = prog.declare('ro', memory_type='BIT', memory_size=1)
        prog.measure(self.n - 1, ro[0])
        return prog
Example #8
0
def generate_cz_phase_ramsey_experiments(
        cz_qubits: Sequence[int], measure_qubit: int,
        angles: Sequence[float]) -> List[ObservablesExperiment]:
    """
    Return ObservablesExperiments containing programs that constitute a CZ phase ramsey experiment.

    :param cz_qubits: the qubits participating in the cz gate
    :param measure_qubit: Which qubit to measure.
    :param angles: A list of angles at which to make a measurement
    :return: ObservablesExperiments which can be run to estimate the effective RZ rotation
        applied to a single qubit during the application of a CZ gate.
    """
    expts = []
    for angle in angles:
        settings = []
        program = Program()
        # apply CZ, possibly inducing an effective RZ on measure qubit by some angle
        program += CZ(*cz_qubits)
        # apply phase to measure_qubit akin to T2 experiment
        program += RZ(angle, measure_qubit)
        settings = [
            ExperimentSetting(minusY(measure_qubit),
                              PauliTerm('Y', measure_qubit))
        ]

        expts.append(ObservablesExperiment([settings], program))

    return expts
Example #9
0
def add_gate_program_grover4(p, gate):
    erase = [
        '(', ')', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '.', '-'
    ]
    gate_data = gate.split(' ')
    name_gate = gate_data[0]
    for char in erase:
        name_gate = name_gate.replace(char, '')

    if name_gate == 'H':
        p.inst(RZ(pi / 2, int(gate_data[1])), RX(pi / 2, int(gate_data[1])),
               RZ(pi / 2, int(gate_data[1])))
    if name_gate == 'X':
        p.inst(RZ(pi / 2, int(gate_data[1])), RX(pi / 2, int(gate_data[1])),
               RZ(pi, int(gate_data[1])), RX(-pi / 2, int(gate_data[1])),
               RZ(-pi / 2, int(gate_data[1])))
    if name_gate == 'CNOT':
        p.inst(RZ(pi / 2, int(gate_data[2])), RX(pi / 2, int(gate_data[2])),
               CZ(int(gate_data[1]), int(gate_data[2])),
               RX(-pi / 2, int(gate_data[2])), RZ(-pi / 2, int(gate_data[2])))
    if name_gate == 'RZ':
        angle = float(gate_data[0].replace('RZ(', '').replace(')', ''))
        p.inst(RZ(-pi / 8, int(gate_data[1])))
    if name_gate == 'PHASE':
        angle = float(gate_data[0].replace('PHASE(', '').replace(')', ''))
        p.inst(RZ(0.19634954084936207, int(gate_data[1])))
    return p
Example #10
0
def bell_ckt_gd():
    ckt = Program()
    theta_0 = ckt.declare('theta_0', memory_type='REAL')
    theta_1 = ckt.declare("theta_1", memory_type='REAL')
    x_theta = ckt.declare("x_theta", memory_type='REAL')
    ro = ckt.declare('ro', memory_type='BIT', memory_size=2)
    ckt += RX(x_theta, 1)
    ckt += RZ(x_theta, 1)
    ckt += RX(-1 * x_theta, 1)

    ckt += RX(theta_0, 0)
    ckt += RZ(theta_0, 0)

    ckt += RX(x_theta, 0)
    ckt += RZ(theta_1, 0)
    ckt += RX(-1 * x_theta, 0)

    ckt += CZ(1, 0)

    ckt += RX(x_theta, 0)
    ckt += RZ(-1 * theta_1, 0)
    ckt += RX(-1 * x_theta, 0)

    ckt += MEASURE(0, ro[0])
    ckt.wrap_in_numshots_loop(1000)
    return ckt
def test_variance_bootstrap():
    qubits = [0, 1]
    qc = get_test_qc(n_qubits=len(qubits))
    state_prep = Program([H(q) for q in qubits])
    state_prep.inst(CZ(qubits[0], qubits[1]))
    tomo_expt = generate_state_tomography_experiment(state_prep, qubits)
    results = list(
        measure_observables(qc=qc, tomo_experiment=tomo_expt, n_shots=10_000))
    estimate, status = iterative_mle_state_estimate(results=results,
                                                    qubits=qubits,
                                                    dilution=0.5)
    rho_est = estimate.estimate.state_point_est
    purity = np.trace(rho_est @ rho_est)
    purity = np.real_if_close(purity)
    assert purity.imag == 0.0

    def my_mle_estimator(_r, _q):
        return iterative_mle_state_estimate(results=_r,
                                            qubits=_q,
                                            dilution=0.5,
                                            entropy_penalty=0.0,
                                            beta=0.0)[0]

    boot_purity, boot_var = estimate_variance(results=results,
                                              qubits=qubits,
                                              tomo_estimator=my_mle_estimator,
                                              functional=dm.purity,
                                              n_resamples=5,
                                              project_to_physical=False)

    np.testing.assert_allclose(purity,
                               boot_purity,
                               atol=2 * np.sqrt(boot_var),
                               rtol=0.01)
def create_graph_state(graph: nx.Graph):
    """Write a program to create a graph state according to the specified graph

    A graph state involves Hadamarding all your qubits and then applying a CZ for each
    edge in the graph. A graph state and the ability to measure it however you want gives
    you universal quantum computation. The authoritative references are

     - https://journals.aps.org/prl/abstract/10.1103/PhysRevLett.86.5188
     - https://arxiv.org/abs/quant-ph/0301052

    Similar to a Bell state / GHZ state, we can try to prepare a graph state and measure
    how well we've done according to expected parities.

    :param graph: The graph. Nodes are used as arguments to gates, so they should be qubit-like.
    :return: A program that constructs a graph state.
    """
    program = Program()
    for q in graph.nodes:
        program += H(q)

    program += Pragma('COMMUTING_BLOCKS')
    for a, b in graph.edges:
        program += Pragma('BLOCK')
        program += CZ(a, b)
        program += Pragma('END_BLOCK')
    program += Pragma('END_COMMUTING_BLOCKS')

    return program
Example #13
0
def test_decoherence_noise():
    prog = Program(RX(np.pi / 2, 0), CZ(0, 1), RZ(np.pi, 0))
    gates = _get_program_gates(prog)
    m1 = _decoherence_noise_model(gates,
                                  T1=INFINITY,
                                  T2=INFINITY,
                                  ro_fidelity=1.)

    # with no readout error, assignment_probs = identity matrix
    assert np.allclose(m1.assignment_probs[0], np.eye(2))
    assert np.allclose(m1.assignment_probs[1], np.eye(2))
    for g in m1.gates:
        # with infinite coherence time all kraus maps should only have a single, unitary kraus op
        assert len(g.kraus_ops) == 1
        k0, = g.kraus_ops
        # check unitarity
        k0dk0 = k0.dot(k0.conjugate().transpose())
        assert np.allclose(k0dk0, np.eye(k0dk0.shape[0]))

    # verify that selective (by qubit) dephasing and readout infidelity is working
    m2 = _decoherence_noise_model(gates,
                                  T1=INFINITY,
                                  T2={0: 30e-6},
                                  ro_fidelity={
                                      0: .95,
                                      1: 1.0
                                  })
    assert np.allclose(m2.assignment_probs[0], [[.95, 0.05], [.05, .95]])
    assert np.allclose(m2.assignment_probs[1], np.eye(2))
    for g in m2.gates:
        if 0 in g.targets:
            # single dephasing (no damping) channel on qc 0, no noise on qc1 -> 2 Kraus ops
            assert len(g.kraus_ops) == 2
        else:
            assert len(g.kraus_ops) == 1

    # verify that combined T1 and T2 will lead to 4 outcome Kraus map.
    m3 = _decoherence_noise_model(gates, T1={0: 30e-6}, T2={0: 30e-6})
    for g in m3.gates:
        if 0 in g.targets:
            # damping (implies dephasing) channel on qc 0, no noise on qc1 -> 4 Kraus ops
            assert len(g.kraus_ops) == 4
        else:
            assert len(g.kraus_ops) == 1

    # verify that gate names are translated
    new_prog = apply_noise_model(prog, m3)
    new_gates = _get_program_gates(new_prog)

    # check that headers have been embedded
    headers = _noise_model_program_header(m3)
    assert all(
        (isinstance(i, Pragma) and i.command in ["ADD-KRAUS", "READOUT-POVM"])
        or isinstance(i, DefGate) for i in headers)
    assert headers.out() in new_prog.out()

    # verify that high-level add_decoherence_noise reproduces new_prog
    new_prog2 = add_decoherence_noise(prog, T1={0: 30e-6}, T2={0: 30e-6})
    assert new_prog == new_prog2
Example #14
0
def test_to_pyquil_from_pyquil_simple():
    p = Program()
    p += X(0)
    p += Y(1)
    p += Z(2)
    p += CNOT(0, 1)
    p += CZ(1, 2)
    assert p.out() == to_pyquil(from_pyquil(p)).out()
Example #15
0
def test_to_pyquil_from_pyquil_not_starting_at_zero():
    p = Program()
    p += X(10)
    p += Y(11)
    p += Z(12)
    p += CNOT(10, 11)
    p += CZ(11, 12)
    assert p.out() == to_pyquil(from_pyquil(p)).out()
Example #16
0
def get_dagger_of_native_gate(gate):
    if gate.name == "RZ":
        return RZ(-gate.params[0], gate.qubits[0])
    if gate.name == "RX":
        return RX(-gate.params[0], gate.qubits[0])
    if gate.name == "CZ":
        return CZ(*gate.qubits)

    raise ValueError("Unsupported gate: " + str(gate))
Example #17
0
 def construct_program(trimmed):
     pq = Program(H(0), CNOT(0, 1), CNOT(1, 2))
     ro = pq.declare("ro", "BIT", 1)
     pq.measure(0, ro)
     if trimmed:
         pq.if_then(ro, X(0), X(1))
     else:
         pq.if_then(ro, Program(X(0), H(3)), Program(X(1), CZ(3, 4)))
     return pq
def test_noise_helpers():
    rx90_0, rxm90_1, i_1, cz_01 = gates = RX(np.pi / 2)(0), RX(-np.pi / 2)(1), I(1), CZ(0, 1)
    prog = Program(*gates)
    inferred_gates = _get_program_gates(prog)
    assert set(inferred_gates) == set(gates)
    noisy_names = _get_noisy_names(gates)
    assert noisy_names[rx90_0] == "NOISY-RX-PLUS-90"
    assert noisy_names[rxm90_1] == "NOISY-RX-MINUS-90"
    assert noisy_names[i_1] == "NOISY-I"
    assert noisy_names[cz_01] == "NOISY-CZ"
Example #19
0
def test_get_qvm_noise_supported_gates_from_compiler_isa(compiler_isa):
    gates = _get_qvm_noise_supported_gates(compiler_isa)
    for q in [0, 1, 2]:
        for g in [
                I(q),
                RX(np.pi / 2, q),
                RX(-np.pi / 2, q),
                RX(np.pi, q),
                RX(-np.pi, q),
                RZ(THETA, q),
        ]:
            assert g in gates

    assert CZ(0, 1) in gates
    assert CZ(1, 0) in gates
    assert ISWAP(1, 2) in gates
    assert ISWAP(2, 1) in gates
    assert CPHASE(THETA, 2, 0) in gates
    assert CPHASE(THETA, 0, 2) in gates
Example #20
0
def test_lifted_gate_modified():
    test_unitary = lifted_gate(RZ(np.pi / 4, 0).dagger(), 1)
    true_unitary = mat.RZ(-np.pi / 4)
    assert np.allclose(test_unitary, true_unitary)

    test_unitary = lifted_gate(X(0).dagger().controlled(1), 2)
    true_unitary = lifted_gate(CNOT(1, 0), 2)
    other_true = mat.CNOT
    assert np.allclose(test_unitary, true_unitary)
    assert np.allclose(other_true, true_unitary)

    test_unitary = lifted_gate(
        X(1).dagger().controlled(0).dagger().dagger(), 2)
    true_unitary = lifted_gate(CNOT(0, 1), 2)
    assert np.allclose(test_unitary, true_unitary)

    test_unitary = lifted_gate(
        X(0).dagger().controlled(1).dagger().dagger().controlled(2), 3)
    true_unitary = lifted_gate(CCNOT(1, 2, 0), 3)
    other_true = mat.CCNOT
    assert np.allclose(test_unitary, true_unitary)
    assert np.allclose(other_true, true_unitary)

    test_unitary = lifted_gate(
        RY(np.pi / 4, 0).dagger().controlled(2).dagger().dagger(), 3)
    ry_part = lifted_gate(RY(-np.pi / 4, 0), 1)
    zero = np.eye(2)
    zero[1, 1] = 0
    one = np.eye(2)
    one[0, 0] = 0
    true_unitary = np.kron(zero, np.eye(4)) + np.kron(
        one, np.kron(np.eye(2), ry_part))
    assert np.allclose(test_unitary, true_unitary)

    test_unitary = lifted_gate(PHASE(0.0, 1).forked(0, [np.pi]), 2)
    true_unitary = lifted_gate(CZ(0, 1), 2)
    assert np.allclose(test_unitary, true_unitary)

    test_unitary = lifted_gate(
        PHASE(0.0, 2).forked(1, [0.0]).forked(0, [0.0, np.pi]), 3)
    true_unitary = lifted_gate(CZ(1, 2).controlled(0), 3)
    assert np.allclose(test_unitary, true_unitary)
Example #21
0
def test_apply_noise_model():
    p = Program(RX(np.pi / 2, 0), RX(np.pi / 2, 1), CZ(0, 1), RX(np.pi / 2, 1))
    noise_model = _decoherence_noise_model(_get_program_gates(p))
    pnoisy = apply_noise_model(p, noise_model)
    for i in pnoisy:
        if isinstance(i, DefGate):
            pass
        elif isinstance(i, Pragma):
            assert i.command in ['ADD-KRAUS', 'READOUT-POVM']
        elif isinstance(i, Gate):
            assert i.name in NO_NOISE or not i.params
def test_generate_2q_state_tomography_experiment():
    p = Program()
    p += H(0)
    p += CZ(0, 1)
    two_q_exp = generate_state_tomography_experiment(p, qubits=[0, 1])
    dimension = 2**2

    assert [str(two_q_exp[idx][0].out_operator) for idx in list(range(0, dimension ** 2))] == \
           ['(1+0j)*I', '(1+0j)*X1', '(1+0j)*Y1', '(1+0j)*Z1',
            '(1+0j)*X0', '(1+0j)*X0*X1', '(1+0j)*X0*Y1', '(1+0j)*X0*Z1',
            '(1+0j)*Y0', '(1+0j)*Y0*X1', '(1+0j)*Y0*Y1', '(1+0j)*Y0*Z1',
            '(1+0j)*Z0', '(1+0j)*Z0*X1', '(1+0j)*Z0*Y1', '(1+0j)*Z0*Z1']
def twoq_rb_gateset(q1: int, q2: int) -> Iterable[Gate]:
    """
    Yield the gateset for 2-qubit randomized benchmarking.

    This is two 1-q gatesets and ``CZ``.

    :param q1: The first qubit.
    :param q2: The second qubit.
    """
    yield from oneq_rb_gateset(q1)
    yield from oneq_rb_gateset(q2)
    yield CZ(q1, q2)
def twoq_rb_gateset(q1: QubitPlaceholder, q2: QubitPlaceholder) -> Iterable[Gate]:
    """
    Yield the gateset for 2-qubit randomized benchmarking.

    This is two 1-q gatesets and ``CZ``.

    :param q1: The first qubit. Might I suggest you provide a :py:class:`QubitPlaceholder`?
    :param q2: The second qubit. Might I suggest you provide a :py:class:`QubitPlaceholder`?
    """
    yield from oneq_rb_gateset(q1)
    yield from oneq_rb_gateset(q2)
    yield CZ(q1, q2)
Example #25
0
def two_qubit_gateset(q0: int, q1: int) -> List[Gate]:
    """
    Return the RX, RZ, CZ native gateset on two qubits.

    Args:
        q0: One of the two qubits to use for the gateset.
        q1: The other qubit to use for the gateset.

    Returns:
        A list of Gate objects representing an (RX, RZ, CZ) 2Q gateset.
    """
    return one_qubit_gateset(q0) + one_qubit_gateset(q1) + [CZ(q0, q1)]
Example #26
0
def _CNOT(q0: QubitLike, q1: QubitLike) -> Program:
    """
    A CNOT in terms of RX(+-pi/2), RZ(theta), and CZ

    .. note:
        This uses two of :py:func:`_H`, so it picks up twice the global phase.
        Don't control this gate.
    """
    p = Program()
    p.inst(_H(q1))
    p.inst(CZ(q0, q1))
    p.inst(_H(q1))
    return p
Example #27
0
def test_apply_noise_model_perturbed_angles():
    eps = 1e-15
    p = Program(RX(np.pi / 2 + eps, 0), RX(np.pi / 2 - eps, 1), CZ(0, 1),
                RX(np.pi / 2 + eps, 1))
    noise_model = _decoherence_noise_model(_get_program_gates(p))
    pnoisy = apply_noise_model(p, noise_model)
    for i in pnoisy:
        if isinstance(i, DefGate):
            pass
        elif isinstance(i, Pragma):
            assert i.command in ["ADD-KRAUS", "READOUT-POVM"]
        elif isinstance(i, Gate):
            assert i.name in NO_NOISE or not i.params
Example #28
0
    def CNOT(self, p, g_qubits):
        '''
        ----------
        CNOT Gate:
        ----------
        Circuit used for implementing CNOT.

        |q1>_________x_____________
                     |
        |q2>____[H]_[CZ]_[H]_______

        https://bit.ly/3i5CJZI
        '''
        self.H(p, [g_qubits[1]])
        p += CZ(g_qubits[0], g_qubits[1])
        self.H(p, [g_qubits[1]])
Example #29
0
def test_to_latex():
    """A test to give full coverage of latex_generation and latex_config."""
    qubits = range(3)
    p = Program()
    p.inst(X(qubits[0]), Y(qubits[0]), CZ(qubits[0], qubits[2]),
           SWAP(qubits[0], qubits[1]), MEASURE(qubits[0], None),
           CNOT(qubits[2], qubits[0]))
    _ = to_latex(p)

    # Modify settings to access non-standard control paths.
    settings = get_default_settings()
    settings['gates']['AllocateQubitGate']['draw_id'] = True
    settings['gate_shadow'] = None
    _ = to_latex(p, settings)

    settings['control']['shadow'] = True
    _ = to_latex(p, settings)
def CNOT_X_basis(control, target) -> Program:
    """
    The CNOT in the X basis, i.e.

    CNOTX = |+X+| * I + |-X-| * Z

    where |+> and |-> are the +/- eigenstate of the Pauli X operator and * denotes a tensor product.

    :param control: qubit label
    :param target: qubit label
    :return: program
    """
    prog = Program()
    prog += H(control)
    prog += CZ(control, target)
    prog += H(control)
    return prog