예제 #1
0
def test_measurement_with_output_bit():
    c = circuit.Circuit()
    c.add_qubit("A")

    c.add_qubit("O")
    c.add_qubit("O2")

    c.add_rotate_y("A", time=0, angle=np.pi / 2)

    sampler = circuit.selection_sampler(1)
    c.add_measurement("A", time=1, sampler=sampler, output_bit="O")

    c.add_rotate_y("A", time=3.5, angle=np.pi / 2)

    sampler = circuit.selection_sampler(1)
    c.add_measurement("A", time=4, sampler=sampler, output_bit="O2")

    c.add_rotate_y("A", time=5, angle=np.pi / 2)
    c.order()

    sdm = sparsedm.SparseDM(c.get_qubit_names())

    assert sdm.classical['O'] == 0
    assert sdm.classical['O2'] == 0

    c.apply_to(sdm)

    assert np.allclose(sdm.trace(), 0.25)

    assert sdm.classical == {'O': 1, 'O2': 1}
예제 #2
0
def test_euler_rotation():
    c = circuit.Circuit("test")
    c.add_qubit("A")

    theta = 0.3
    lamda = 0.7
    phi = 4.2

    g = circuit.RotateEuler(bit="A", time=0, theta=theta, lamda=lamda, phi=phi)
    gconj = circuit.RotateEuler(
        bit="A",
        time=10,
        theta=-theta,
        lamda=-phi,
        phi=-lamda)

    c.add_gate(g)
    c.add_gate(gconj)

    c.order()

    sdm = sparsedm.SparseDM(c.get_qubit_names())

    c.apply_to(sdm)

    d = sdm.full_dm.get_diag()

    assert np.allclose(d, [1, 0])
예제 #3
0
def test_noisy_measurement_sampler():
    c = circuit.Circuit()
    c.add_qubit("A", 0, 0)

    c.add_hadamard("A", 1)

    sampler = circuit.uniform_noisy_sampler(seed=42, readout_error=0.1)
    m1 = c.add_measurement("A", time=2, sampler=sampler)

    sdm = sparsedm.SparseDM("A")

    true_state = []
    for _ in range(20):
        c.apply_to(sdm)
        true_state.append(sdm.classical['A'])

    # these samples assume a certain seed (=42)
    assert m1.measurements == [0, 1, 0, 0, 1, 0,
                               1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 1, 1]
    assert true_state != m1.measurements
    assert true_state == [0, 1, 0, 0, 1, 0, 1,
                          0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 1, 0, 1]

    # we have two measurement errors
    mprob = 0.9**18 * 0.1**2
    assert np.allclose(sdm.classical_probability, mprob)
    # and each measurement has outcome 1/2
    totprob = mprob * 0.5**20
    assert np.allclose(sdm.trace(), totprob)
예제 #4
0
    def handle_init(self, cmds):

        # Interpret commands.
        self.t1 = None
        self.t2 = None
        for cmd in cmds:
            if cmd.iface == 'quantumsim':
                if cmd.oper == 'error':
                    if 't1' in cmd:
                        self.t1 = cmd['t1']
                    if 't2' in cmd:
                        self.t2 = cmd['t2']
                else:
                    raise ValueError('Unknown ArbCmd %s.%s' %
                                     (cmd.iface, cmd.oper))

        # Loading QuantumSim can take some time, so defer to initialize
        # callback. We also have logging at that point in time, so it should
        # provide a nice UX.
        self.debug('Trying to load QuantumSim...')
        import quantumsim.ptm as ptm
        self.ptm = ptm
        import quantumsim.sparsedm as sdm
        self.sdm = sdm.SparseDM(self.MAX_QUBITS)
        import numpy as np
        self.np = np
        self.info('QuantumSim loaded {}using CUDA acceleration',
                  '' if sdm.using_gpu else '*without* ')
예제 #5
0
def test_cphase_rotation():

    c = circuit.Circuit("test")
    c.add_qubit("A")
    c.add_qubit("B")

    c.add_gate("rotate_y", "A", angle=1.2, time=0)
    c.add_gate("rotate_y", "B", angle=1.2, time=0)

    for t in [1, 2, 3, 4, 5]:
        g = circuit.CPhaseRotation("A", "B", 2 * np.pi / 5, t)
        c.add_gate(g)

    c.add_gate("rotate_y", "A", angle=-1.2, time=6)
    c.add_gate("rotate_y", "B", angle=-1.2, time=6)

    c.order()

    sdm = sparsedm.SparseDM(c.get_qubit_names())

    c.apply_to(sdm)

    d = sdm.full_dm.get_diag()

    assert np.allclose(d, [1, 0, 0, 0])
예제 #6
0
def test_three_qbit_clean():
    c = circuit.Circuit()

    qubit_names = ["D1", "A1", "D2", "A2", "D3"]

    # clean ancillas have infinite life-time
    for qb in qubit_names:
        # set lifetime to only almost inf so that waiting gates are added but
        # ineffective
        c.add_qubit(qb, np.inf, 1e10)

    c.add_hadamard("A1", time=0)
    c.add_hadamard("A2", time=0)

    c.add_cphase("A1", "D1", time=200)
    c.add_cphase("A2", "D2", time=200)

    c.add_cphase("A1", "D2", time=100)
    c.add_cphase("A2", "D3", time=100)

    c.add_hadamard("A1", time=300)
    c.add_hadamard("A2", time=300)

    with pytest.warns(UserWarning):
        m1 = circuit.Measurement("A1", time=350, sampler=None)
    c.add_gate(m1)
    with pytest.warns(UserWarning):
        m2 = circuit.Measurement("A2", time=350, sampler=None)
    c.add_gate(m2)

    c.add_waiting_gates(tmin=0, tmax=1500)

    c.order()

    assert len(c.gates) == 27

    sdm = sparsedm.SparseDM(qubit_names)

    for bit in sdm.classical:
        sdm.classical[bit] = 1

    sdm.classical["D3"] = 0

    assert sdm.classical == {'A1': 1, 'A2': 1, 'D3': 0, 'D1': 1, 'D2': 1}

    for i in range(100):
        c.apply_to(sdm)

    assert len(m1.measurements) == 100
    assert len(m2.measurements) == 100

    assert sdm.classical == {}

    # in a clean run, we expect just one possible path
    assert np.allclose(sdm.trace(), 1)

    assert m1.measurements == [1] * 100
    assert m2.measurements == [0, 1] * 50
예제 #7
0
def test_classical_not():
    sdm = sparsedm.SparseDM("A")
    c = circuit.Circuit()
    c.add_qubit(circuit.ClassicalBit("A"))
    c.add_gate(circuit.ClassicalNOT("A", time=0))
    c.order()

    assert sdm.classical['A'] == 0

    c.apply_to(sdm)

    assert sdm.classical['A'] == 1
예제 #8
0
def test_three_qbit_clean_qasm():
    config_qasm = os.path.join(os.path.dirname(__file__),
                               'config_qasm_5q.json')
    config_sim = os.path.join(os.path.dirname(__file__),
                              'config_simulator.json')
    parser = qasm.ConfigurableParser(config_qasm, config_sim)
    with pytest.warns(UserWarning):
        circuits = parser.parse(threequbit_qasm.split('\n'))
    assert len(circuits) == 1
    c = circuits[0]

    qubit_names = ["q0", "q1", "q2", "q3", "q4"]

    with pytest.warns(UserWarning):
        m1 = circuit.Measurement("q1", time=400, sampler=None)
    c.add_gate(m1)
    with pytest.warns(UserWarning):
        m2 = circuit.Measurement("q3", time=400, sampler=None)
    c.add_gate(m2)

    c.add_waiting_gates(tmin=0, tmax=1500)

    c.order()

    assert len(c.gates) == 29

    sdm = sparsedm.SparseDM(qubit_names)

    for bit in sdm.classical:
        sdm.classical[bit] = 1

    sdm.classical["q4"] = 0

    assert sdm.classical == {'q1': 1, 'q3': 1, 'q4': 0, 'q0': 1, 'q2': 1}

    for i in range(100):
        c.apply_to(sdm)

    assert len(m1.measurements) == 100
    assert len(m2.measurements) == 100

    assert sdm.classical == {}

    # in a clean run, we expect just one possible path
    assert np.allclose(sdm.trace(), 1)

    assert m1.measurements == [1] * 100
    assert m2.measurements == [0, 1] * 50
예제 #9
0
def test_ramsey():

    for t1, t2 in [(np.inf, np.inf), (1000, 2000),
                   (np.inf, 1000), (1000, 1000)]:
        c = circuit.Circuit("Ramsey")
        c.add_qubit("Q", t1=t1, t2=t2)
        c.add_rotate_y("Q", time=0, angle=np.pi / 2)
        c.add_rotate_y("Q", time=1000, angle=-np.pi / 2)
        c.add_waiting_gates()
        c.order()

        sdm = sparsedm.SparseDM(c.get_qubit_names())
        c.apply_to(sdm)
        sdm.project_measurement("Q", 0)

        assert np.allclose(sdm.trace(), 0.5 * (1 + np.exp(-1000 / t2)))
예제 #10
0
    def get_values(self):
        results = []

        for c in self.parser.circuits:
            qubits = list(sorted(c.get_qubit_names()))
            d = sdm.SparseDM(qubits)
            # this ensures that the qubits are in the density matrix
            # in the right order. (fix this, should use d.idx_in_full!)
            for q in qubits:
                d.ensure_dense(q)
            c.apply_to(d)
            diag = d.full_dm.get_diag()
            parity = diag[[0, 3]].sum()
            p0 = diag[[1, 3]].sum()
            p1 = diag[[2, 3]].sum()
            results.append((p0, p1, parity))

        return np.array(results).T
예제 #11
0
def test_two_qubit_tpcp():
    c = circuit.Circuit("test")
    c.add_qubit("A", t1=30000, t2=30000)
    c.add_qubit("B", t1=30000, t2=30000)

    c.add_gate("rotate_y", "A", angle=1.2, time=0)
    c.add_gate("rotate_y", "B", angle=0.2, time=0)
    c.add_gate("rotate_z", "A", angle=0.1, time=1)
    c.add_gate("rotate_x", "B", angle=0.3, time=1)
    c.add_gate("cphase", "A", "B", time=2)

    sdm = sparsedm.SparseDM(c.get_qubit_names())
    for i in range(100):
        c.apply_to(sdm)
        x = sdm.full_dm.get_diag()
        assert np.allclose(x.sum(), 1)  # trace preserved
        assert np.all(x > 0)  # probabilities greater than zero

    assert np.allclose(np.linalg.eigvalsh(sdm.full_dm.to_array()),
                       [0, 0, 0, 1])
예제 #12
0
def test_integration_surface17():
    def make_circuit(
            t1=np.inf,
            t2=np.inf,
            seed=42,
            readout_error=0.015,
            t_gate=40,
            t_rest=1000):
        surf17 = circuit.Circuit("Surface 17")

        t_rest += t_gate  # nominal rest time is between two gates

        x_bits = ["X%d" % i for i in range(4)]
        z_bits = ["Z%d" % i for i in range(4)]

        d_bits = ["D%d" % i for i in range(9)]

        for b in x_bits + z_bits + d_bits:
            surf17.add_qubit(b, t1, t2)

        def add_x(c, x_anc, d_bits, t=0, t_gate=t_gate):
            t += t_gate
            for d in d_bits:
                if d is not None:
                    c.add_cphase(d, x_anc, time=t)
                t += t_gate

        add_x(surf17, "X0", [None, None, "D2", "D1"], t=0)
        add_x(surf17, "X1", ["D1", "D0", "D4", "D3"], t=0)
        add_x(surf17, "X2", ["D5", "D4", "D8", "D7"], t=0)
        add_x(surf17, "X3", ["D7", "D6", None, None], t=0)

        t2 = 4 * t_gate + t_rest

        add_x(surf17, "Z0", ["D0", "D3", None, None], t=t2)
        add_x(surf17, "Z1", ["D2", "D5", "D1", "D4"], t=t2)
        add_x(surf17, "Z2", ["D4", "D7", "D3", "D6"], t=t2)
        add_x(surf17, "Z3", [None, None, "D5", "D8"], t=t2)

        sampler = circuit.BiasedSampler(
            readout_error=readout_error, alpha=1, seed=seed)

        for b in x_bits + d_bits:
            surf17.add_hadamard(b, time=0)
            surf17.add_hadamard(b, time=5 * t_gate)

        for b in z_bits:
            surf17.add_hadamard(b, time=4 * t_gate + t_rest)
            surf17.add_hadamard(b, time=4 * t_gate + t_rest + 5 * t_gate)

        for b in z_bits:
            surf17.add_measurement(
                b, time=10 * t_gate + t_rest, sampler=sampler)

        for b in x_bits:
            surf17.add_measurement(b, time=6 * t_gate, sampler=sampler)

        surf17.add_waiting_gates(
            only_qubits=x_bits, tmax=6 * t_gate, tmin=-t_rest - 5 * t_gate)
        surf17.add_waiting_gates(only_qubits=z_bits + d_bits, tmin=0)

        surf17.order()

        return surf17

    def syndrome_to_byte(syndrome):
        byte = 0

        for i in range(4):
            byte += syndrome["X%d" % i] << (i + 4)
        for i in range(4):
            byte += syndrome["Z%d" % i] << i

        return byte

    seed = 890793515

    t1 = 25000.0
    t2 = 35000.0
    ro_error = 0.015
    t_gate = 40.0
    t_rest = 1000.0

    rounds = 20

    c = make_circuit(t1=t1, t2=t2, seed=seed,
                     readout_error=ro_error, t_gate=t_gate, t_rest=t_rest)

    sdm = sparsedm.SparseDM(c.get_qubit_names())
    for b in ["D%d" % i for i in range(9)]:
        sdm.ensure_dense(b)

    syndromes = []
    for _ in range(rounds):
        c.apply_to(sdm)

        sdm.renormalize()

        syndromes.append(syndrome_to_byte(sdm.classical))

    syndrome = bytes(syndromes)

    assert syndrome == b'jHhJhL\x08L\tK)K\x08K\x08K\x08K\x08I'
예제 #13
0
def run(seed,
        cycles=10,
        padding_to=20,
        test_data_flag=False,
        error_rate=0.0015,
        **kwargs):

    circuit = make_circuit(seed=seed, **kwargs)

    sdm = sparsedm.SparseDM(circuit.get_qubit_names())
    for b in ["D%d" % i for i in range(9)]:
        sdm.ensure_dense(b)

    measurements = []
    diagonals = []

    for _ in range(cycles):
        circuit.apply_to(sdm, apply_all_pending=False)

        sdm.renormalize()

        measurement = [sdm.classical[b] for b in measurement_bits]
        measurements.append(measurement)

        diagonal = sdm.full_dm.get_diag()
        diagonals.append(diagonal)

    state = np.random.RandomState(seed=seed + 4 * 10**8)

    # # # PATCH PART I # # #
    measurements = np.array(measurements)
    new_order = [3, 2, 1, 0, 7, 6, 5, 4]
    measurements = measurements[:, new_order]
    # # # END # # #

    errors = (state.random_sample(len(measurements) * len(measurements[0])) <
              error_rate).tolist()
    measurements = [[measurements[i][j] ^ errors[i * 8 + j] for j in range(8)]
                    for i in range(len(measurements))]

    # # # PATCH PART II # # #
    measurements = np.array(measurements)
    new_order = [3, 2, 1, 0, 7, 6, 5, 4]
    measurements = measurements[:, new_order]
    measurements = [list(mes) for mes in measurements]
    # # # END # # #

    stabilizers = [[m0[j] ^ m1[j] for j in range(8)]
                   for m0, m1 in zip(measurements, [[0] * 8] + measurements)]

    events = [[s0[j] ^ s1[j] for j in range(8)]
              for s0, s1 in zip(stabilizers, [[0] * 8] + stabilizers)]

    final_stabilizers, parities = get_noisy_measurement(diagonals, seed)
    final_events = [[z1 ^ z2 for z1, z2 in zip(fs, ls[4:])]
                    for fs, ls in zip(final_stabilizers, stabilizers)]

    if test_data_flag is False:
        final_events = final_events[-1]
        final_stabilizers = final_stabilizers[-1]
        parities = parities[-1]

    else:
        events += [[0] * 8 for j in range(padding_to - cycles)]

    return measurements, events, final_stabilizers,\
        final_events, parities
예제 #14
0
    def quantumsim_simulation(self, error, init_state, expected_measurement=np.array([]), expected_q_state=0, t1=3500, t2=1500, meas_error=0.03):

        N_exp = self.N_exp
        N_qubits = self.N_qubits

        if expected_measurement.size == 0:

                                # CIRCUIT DECLARATION
            c = self.qsimc.circuit_function(np.inf, np.inf, 0, 0, init_state)

            # SIMULATING
            sdm = sparsedm.SparseDM(c.get_qubit_names())

            measurements = []

            c.apply_to(sdm)

            # for q in range(N_qubits):
            #     if sdm.classical["m"+str(q)]:
            #         measurements.append(sdm.classical["m"+str(q)])

            for q in sdm.classical:
                if "m" in str(q):
                    measurements.append(sdm.classical[str(q)])

            measurement = np.array(measurements, dtype=float)
            expected_q_state = sdm.full_dm.dm.ravel()

            return measurement, expected_q_state

        else:

            # CIRCUIT DECLARATION
            c = self.qsimc.circuit_function(
                t1, t2, error, meas_error, init_state)
            # c = self.qsimc.circuit_function(error, meas_error, init_state)

            for i in range(N_exp):

                # SIMULATING
                sdm = sparsedm.SparseDM(c.get_qubit_names())
                c.apply_to(sdm)

                measurements = []

                # for q in range(N_qubits):
                #     if sdm.classical["m"+str(q)]:
                #         measurements.append(sdm.classical["m"+str(q)])

                for q in sdm.classical:
                    if "m" in str(q):
                        measurements.append(sdm.classical[str(q)])

                measurement = np.array(measurements, dtype=float)
                print("Expected Measurement:")
                print(expected_measurement)
                print("Actual Measurement:")
                print(measurement)

                q_state = sdm.full_dm.dm.ravel()

                exp_m_int = int(''.join(str(int(e))
                                        for e in expected_measurement.tolist()), 2)
                m_int = int(''.join(str(int(e))
                                    for e in measurement.tolist()), 2)
                self.tomography_matrix[exp_m_int,
                                       m_int] = self.tomography_matrix[exp_m_int, m_int] + 1/N_exp

                self.fidelity_registry.append(
                    np.dot(expected_q_state, q_state))

                self.success_registry.append(1 if np.array_equal(
                    measurement, expected_measurement) else 0)

            # return self.probability_of_success(self.success_registry, N_exp), self.tomography_matrix
            return self.probability_of_success(), self.tomography_matrix