Esempio n. 1
0
def correction_ghz4(measurements, N, operation_pos):
    # print("Measurements: ", measurements)
    # There are two protocols in this case:
    #  1 or 2 ancilla bell pairs
    N_ancillas = len(measurements)
    # If 1 bell pair is used: Then even measument sum requires no correction.
    # Odd measurement requires X correction
    if N_ancillas == 2:
        if sum(measurements) % 2 == 1:
            return [
                qt.rx(np.pi, N, operation_pos[0]),
                qt.rx(np.pi, N, operation_pos[1])
            ]
        else:
            return []
    # If two pairs are used then odd measurement means the state collapsed into
    # something mixed, as a result of entanglement disitillation.
    # Even result may o no require correction, do calculation by hand
    elif N_ancillas == 4:
        if sum(measurements) % 2 == 1:
            return None

        # Results that require no correction.
        no_correction_list = [0, 3, 12, 15]
        # Transform measurement result into int by binary transform
        m_bin = int(''.join(map(str, measurements)), 2)
        if m_bin in no_correction_list:
            return []
        else:
            return [
                qt.rx(np.pi, N, operation_pos[0]),
                qt.rx(np.pi, N, operation_pos[1])
            ]
Esempio n. 2
0
def correction_ghz3(measurements, N, operation_pos):
    """
    Correction opertions for the GHZ state of size 3.
    On the case when 3 bell pairs are collapsed into the GHZ.
    """
    N_ancillas = len(measurements)

    if N_ancillas == 1:
        # Only one qubit in the Bell states are used is measured
        # Result 0 requires no correction, result 1 requires to apply a Pauli X
        if measurements == [0]:
            return []
        elif measurements == [1]:
            return [qt.rx(np.pi, N, operation_pos)]

    elif N_ancillas == 3:
        if sum(measurements) % 2 == 1:
            return None

        no_correction_list = [0, 3]
        m_bin = int(''.join(map(str, measurements)), 2)
        if m_bin in no_correction_list:
            return []
        else:
            return [qt.rx(np.pi, N, operation_pos)]
Esempio n. 3
0
def get2(x):
    """ parametrized (6 parameters) circuitry which can create a c. GHZ 
    state i.e. |000> - |111>"""
    g1 = qt.tensor(qt.rx(x[0]), qt.rx(x[1]), qt.rx(x[2]))
    g2 = qt.cnot(3, 1, 2)
    g3 = qt.cnot(3, 0, 2)
    g4 = qt.tensor(qt.rx(x[3]), qt.rx(x[4]), qt.ry(x[5]))
    return g4 * g3 * g2 * g1 * qt.tensor(zero, zero, zero)
Esempio n. 4
0
def circuitZBraidingCorrectionSimulation(psi0, c_ops=[]):
    N = 8
    schedule = []
    for i in range(2):
        # Z braiding, stage 1
        schedule += [rx(np.pi / 2., N=N, target=i) for i in [4, 5]]
        # Z braiding, stage 2
        schedule += [rz(-np.pi / 2., N=N, target=i) for i in [4, 5]]
        # Z braiding, stage 3
        schedule += [controlled_gate(sigmaz(), N=N, control=4, target=5)]
        # Z braiding, stage 4
        schedule += [rx(-np.pi / 2., N=N, target=i) for i in [4, 5]]
    # perform time evolution and return the final state
    return scheduledUnitaryEvolution(psi0, schedule)
Esempio n. 5
0
 def as_qobj_operator(self, instance: "GateInstance") -> qutip.Qobj:
     p = self.decompose_params(instance.params)
     op = qutip.rx(0, self.num_qubits, 0)
     i = 0
     for gate_type, targets in self.gate_placements:
         fake_instance = GateInstance(gate_type, targets, p[i:i + gate_type.num_params])
         op = self._expand_gate(gate_type.as_qobj_operator(fake_instance), gate_type.num_qubits, self.num_qubits, targets) * op
         i += gate_type.num_params
     return op
Esempio n. 6
0
def CRt_echo(tend, psi0):
    # Echoed CR in qubit 1 frame
    if tend == 0:
        return qt.expect(e_op_list, psi0)

    tlist = np.arange(0, tend, dt)
    output1 = qt.mesolve(Htp, psi0, tlist[0:int(len(tlist) / 2)], [], [], {})
    psiEcho = qt.tensor(qt.rx(np.pi), qt.identity(2)) * output1.states[-1]
    output2 = qt.mesolve(Htm, psiEcho, tlist[int(len(tlist) / 2):], [],
                         e_op_list, {})
    return np.array(output2.expect)[:, -1]
def env_error_single(rho, a0, a1, t, N=1, pos=0):
    """Apply environmental error on a single qubit from the state rho."""
    a = (a0 + a1)*t
    X = qt.rx(np.pi, N, pos)
    Y = qt.ry(np.pi, N, pos)
    Z = qt.rz(np.pi, N, pos)
    # ss = sigma_z * rho * sigma_z.dag()
    lamb = np.exp(-a * t)
    c1 = (3*lamb + 1)/4
    c2 = (1 - lamb)/4
    # print("T: ", t, "lamb: ", lamb)
    rho = (c1 * rho + c2 * (Z * rho * Z.dag() + X * rho * X.dag()
           + Y * rho * Y.dag()))
    return rho
def measure_single_Zbasis_random(rho, p, N=1, pos=0):
    """
    Probabilisticly measure and collapse the state on the given position.

    Parameters
    -----------
    rho : (densmat) the state to apply the noisy gate on
    p : (scalar) measurement error rate
    N : (int) total system size
    pos : (int) position of the qubit to be measured
    """
    X = qt.rx(np.pi, N, pos)
    rho = (1 - p)*rho + p*(X * rho * X.dag())
    measurement, collapsed_rho = ops.random_measure_single_Zbasis(rho, N,
                                                                  pos, True)
    return measurement, collapsed_rho
def measure_single_Zbasis_forced(rho, p, project, N=1, pos=0):
    """
    Collapse the state on the given position and to the given projector.

    Parameters
    -----------
    rho : (densmat) the state to apply the noisy gate on
    p : (scalar) measurement error rate
    project : (scalar) 0 or 1, projector involved in the measurement collapse
    N : (int) total system size
    pos : (int) position of the qubit to be measured
    """
    X = qt.rx(np.pi, N, pos)
    rho = (1 - p)*rho + p*(X * rho * X.dag())
    p, collapsed_rho = ops.forced_measure_single_Zbasis(rho, N, pos,
                                                        project, True)
    return collapsed_rho
def teleport(state, mres):
    X_ = qt.rx(-np.pi, N=3, target=2)
    Z_ = qt.rz(-np.pi, N=3, target=2)
    state_array = state.full()
    if mres == 1:
        state = -1j * X_ * state
        amp = [state_array[3], state_array[2]]
        return qt.Qobj(amp).unit()
    if mres == 2:
        state = -1j * Z_ * state
        amp = [state_array[4], -state_array[5]]
        return qt.Qobj(amp).unit()
    if mres == 3:
        state = -1 * Z_ * X_ * state
        amp = [state_array[7], -state_array[6]]
        return qt.Qobj(amp).unit()
    amp = [state_array[0], state_array[1]]
    return qt.Qobj(amp).unit()
    def _generate_bell_pair_BK(self):
        # Generate a Bell pair using the Barret-Kok protocol.
        # For this case set the initial state to be |+>
        # Probaility of success
        s = .5
        r = (1 - self.eta) * s / (1 - self.eta * s)
        p_success = (1 - r) * self.eta**2

        # This circuit number of steps
        attempts = self._success_number_of_attempts(p_success) + 1
        time = self.time_lookup["bell_pair"] * attempts

        # Update check
        self.check["bell_pair"] += 1

        # Generate Bell pair with F=1
        bell = qt.bell_state('10') * qt.bell_state('10').dag()
        # Apply noisy 1q X to transform state
        bell = errs.single_qubit_gate(bell, qt.rx(np.pi, 2, 0), self.ps, 2, 0)

        return time, bell
Esempio n. 12
0
    def plot_trajectories(self, times, trajs, plot_title=''):
        '''
		Plot output of a simulation result on the Bloch sphere
		'''
        f = plt.figure(figsize=(5, 5), facecolor='white')
        f.suptitle(plot_title, x=0.2)
        # plt.title(plot_title)
        xp2 = qu.rx(np.pi * 0.5)
        yp2 = qu.ry(np.pi * 0.5)
        zp2 = qu.rz(np.pi * 0.5)
        xpi = qu.sigmax()
        ypi = qu.sigmay()
        zpi = qu.sigmaz()
        up = qu.basis(2, 0)
        dn = qu.basis(2, 1)
        # ax = f.add_subplot(1, 1, 1, axisbg='red')

        # p1 = f.add_subplot(2,2,1)
        # plt.plot(times,trajs[0])
        # legend(['OneX','OneY','OneZ'],loc='best')

        # p2 = f.add_subplot(2,2,3)
        # pure = norm(trajs[0],axis=1)
        # plt.plot(times,pure)
        # legend(['Purity'],loc='best')
        # ylim(-0.1,1.1)
        # p3 = f.add_subplot(1,2,2, projection='3d')
        b = qu.Bloch(fig=f)  #,axes=p3)
        b.zlabel = [r"$\left|1\right\rangle $", r"$\left|0\right\rangle$"]
        b.xlabel = [r"$ X $", r""]
        b.ylabel = [r"$ Y $", r""]
        b.vector_color = sb.color_palette()
        b.add_states([yp2 * up, xp2 * xpi * up, up])
        b.point_color = sb.color_palette('dark')[3:4]
        b.add_points(trajs, 'l')
        # b.add_points(trajs[0][0].transpose(),'s')
        b.font_size = 30
        b.sphere_color = '000000'
        b.render(f)
        b.show()
Esempio n. 13
0
def teleport(state, result):
    X_ = qt.rx(-np.pi, N=3, target=2)
    Z_ = qt.rz(-np.pi, N=3, target=2)
    state_array = state.full()

    if result == 1:
        state = -1j * Z_ * state
        amp = [-state_array[2], state_array[3]]
        return qt.Qobj(amp).unit()

    if result == 2:
        state = -1j * X_ * state
        amp = [state_array[5], state_array[4]]
        return qt.Qobj(amp).unit()

    if result == 0:
        state = -1 * Z_ * X_ * state
        amp = [state_array[1], -state_array[0]]
        return qt.Qobj(amp).unit()

    amp = [-state_array[6], -state_array[7]]
    return qt.Qobj(amp).unit()
    def start_epl(self, rho=None):
        """
        Circuit that generates a Bell pair using the EPL protocol.

        NOTE: rho is not taken from arguments, only exists due to
        how 'circuit.py' is constructed.
        """
        self._reset_check()
        # Generate Bell pairs
        # First pair with swap
        time1, bell1 = self._generate_bell_single_click()
        bell1 = self._swap_pair(bell1, [0, 1])
        # Second pair
        time2, bell2 = self._generate_bell_single_click()
        self.check["time"] += time1 + time2
        self.check["time0"] += time1 + time2
        # Apply cutoff here

        # Dephase pair 1
        rho = errs.env_error_all(bell1, self.a0, self.a1, time2)

        # Join state
        rho = qt.tensor(rho, bell2)

        # NOTE: Decide which state collapses.
        # Apply two qubit gates
        controls = [0, 1]
        targets = [2, 3]
        rho = self._apply_two_qubit_gates(rho, controls, targets, "X")

        # Measure ancillas in Z basis
        projections = [1] * 2
        p_success, rho = self._collapse_ancillas_EPL(rho, targets)

        # Apply X to rotate state
        rho = self._apply_single_qubit_gates(rho, [qt.rx(np.pi, 2, 0)], [0])

        return p_success, self.check, rho
Esempio n. 15
0
 def RX(self, target, theta):
     self.state = rx(theta, self.qubits, self.qubits - 1 - target) * self.state
 def rx(self, theta : float) -> None:
     self.parent._apply(qt.rx(theta), self.qubit_id)
def get_sigmas(N=1, pos=0):
    """Return set of single qubit X Y Z gates."""
    sigmas = [qt.qeye([2]*N), qt.rx(np.pi, N, pos), qt.ry(np.pi, N, pos),
              qt.rz(np.pi, N, pos)]
    return sigmas
Esempio n. 18
0
 def as_qobj_operator(self, instance: "GateInstance") -> qutip.Qobj:
     return qutip.rx(instance.params[0])
Esempio n. 19
0
def create_data(time_per_count, num_samples, num_counts, gate_list, time_unit, noise_type=None, walking_amp=None, telegraph_amp=None, \
                res=None, freq_list=None, amp_list=None, phase_list=None, start_f=None, stop_f=None, fluctuators=None, plot_noise=False, \
                add_noise=False, noise_object=None, dc_angle_offset=0, constant_linear_drift=0):
    #time_per_shot: time in seconds for a single (prep-gate-measure+delay)
    #num_samples: how many timestamps and strings of counts you want to have
    #num_counts: how many data points to create (how many ones and zeros) per sample (i.e. per timestamp) --> affects both time of a sample and precision
    #num_shots: how many times (shots) you apply (prep-gate_list-meas) to get one count (a single 0 or 1) --> determines the time of one count, but won't affect precision
    #gate_list: gates you want to do for your operation, entered as a list of strings
    #xerr,yerr,zerr: 2D tuples with overrotation amplitude in radians and frequency in Hz
    #constant linear drift: enter in rads/second
    rho0 = _qt.operator_to_vector(_qt.ket2dm(_qt.basis(2, 0)))
    rho1 = _qt.operator_to_vector(_qt.ket2dm(_qt.basis(2, 1)))
    zero_counts = []
    one_counts = []
    timestep = num_counts * time_per_count  #the time to get a full bitstring of zeros and ones for one sample, i.e. one timestamp
    timestamps = np.arange(
        timestep, num_samples * timestep,
        timestep)  #array of 1*timestep, 2*timestep,....(num_samples)*timestep
    probs = []
    total_time = (time_per_count * num_counts * num_samples) / time_unit

    sig = 0
    if noise_type == "Sine":
        #this function returns the noise object so you can enter it back in as a parameter
        # in the event that you call the function repeatedly for an identical set of parameters
        if noise_object != None:
            sig = noise_object
            #print("REUSING NOISE OBJECT")
            while total_time > sig.times[-1] + timestep:
                sig.next_interval()
                #print("Doing a NEXT INTERVAL")
        else:
            #print("INITIALIZING NEW NOISE")
            sig = _ns.NoiseSignalSine(time_unit=time_unit)
            sig.configure_noise(resolution_factor=res,
                                freq_list=freq_list,
                                amp_list=amp_list,
                                phase_list=phase_list,
                                total_time=total_time)
            sig.init()
            if add_noise != None:
                sig.add_random_noise(
                    add_noise
                )  #add normal noise with specified std deviation if requested
    elif noise_type == "Random Walk":
        sig = _ns.NoiseSignalRandomWalk(initial_seed=1234, time_unit=time_unit)
        sig.configure_noise(walking_amp, res, total_time)
        sig.init()
    elif noise_type == "Telegraph":
        sig = _ns.NoiseSignalTelegraph(initial_seed=1234, time_unit=time_unit)
        sig.configure_noise(exponent=1,
                            amplitude=telegraph_amp,
                            total_fluctuators=fluctuators,
                            start_freq=start_f,
                            stop_freq=stop_f,
                            total_time=total_time)
        sig.init()
        sig.interpolation_settings(do_interpolation=True,
                                   resolution_factor=res)

    if plot_noise == True:
        sig.plot_noise_signal()

    angle_list = []
    expected_angle_list = []

    compressed_gate_list = compress_gate_list(gate_list)
    for time in timestamps:
        noise_at_time = 0
        if noise_type != None:
            #print(time/time_unit)
            noise_at_time = sig[time / time_unit]
        rho = rho0
        total_angle = 0
        total_ideal_angle = 0

        for gate in compressed_gate_list:
            gate_name = gate[0]
            gate_repetitions = gate[1]
            '''
            Next step: calculate change in rotation error within each shot. Currently takes the time at the start of the experiment shot
            and applies that to all gates in one shot. Depending on the timescale of the error and time per shot, this simplification may need
            to be addressed so that each gate, say each Gx in (Gx)^11, has an error associated with its specific time, not the same error for
            all 11 Gx gates.
            '''

            if gate_name == 'Gx':
                angle = (
                    np.pi / 2 + noise_at_time
                ) * gate_repetitions + dc_angle_offset + constant_linear_drift * time
                ideal_angle = (
                    np.pi / 2
                ) * gate_repetitions + dc_angle_offset + constant_linear_drift * time
                rho = (_qt.to_super(_qt.rx(angle))) * rho
                #this section just keeps the angle between 0 and pi
                angle = angle % (2 * np.pi)
                ideal_angle = ideal_angle % (2 * np.pi)
                if angle > np.pi:
                    angle = 2 * np.pi - angle
                if angle < 0:
                    angle = 0 + abs(angle)
                if ideal_angle > np.pi:
                    ideal_angle = 2 * np.pi - ideal_angle
                if ideal_angle < 0:
                    ideal_angle = 0 + abs(ideal_angle)
            elif gate_name == 'Gy':
                angle = (
                    np.pi / 2 + noise_at_time
                ) * gate_repetitions + dc_angle_offset + constant_linear_drift * time
                ideal_angle = (
                    np.pi / 2
                ) * gate_repetitions + dc_angle_offset + constant_linear_drift * time
                rho = (_qt.to_super(_qt.ry(angle))) * rho
                #this section just keeps the angle between 0 and pi
                angle = angle % (2 * np.pi)
                ideal_angle = ideal_angle % (2 * np.pi)
                if angle > np.pi:
                    angle = 2 * np.pi - angle
                if angle < 0:
                    angle = 0 + abs(angle)
                if ideal_angle > np.pi:
                    ideal_angle = 2 * np.pi - ideal_angle
                if ideal_angle < 0:
                    ideal_angle = 0 + abs(ideal_angle)
            elif gate_name == 'Gz':
                angle = (
                    np.pi / 2 + noise_at_time
                ) * gate_repetitions + dc_angle_offset + constant_linear_drift * time
                ideal_angle = (
                    np.pi / 2
                ) * gate_repetitions + dc_angle_offset + constant_linear_drift * time
                rho = (_qt.to_super(_qt.rz(angle))) * rho
                #this section just keeps the angle between 0 and pi
                angle = angle % (2 * np.pi)
                ideal_angle = ideal_angle % (2 * np.pi)
                if angle > np.pi:
                    angle = 2 * np.pi - angle
                if angle < 0:
                    angle = 0 + abs(angle)
                if ideal_angle > np.pi:
                    ideal_angle = 2 * np.pi - ideal_angle
                if ideal_angle < 0:
                    ideal_angle = 0 + abs(ideal_angle)
            elif gate_name == "Gi":
                #apply only the oscillating drift angle, don't add it to pi/2
                angle = (
                    noise_at_time
                ) * gate_repetitions + dc_angle_offset + constant_linear_drift * time
                ideal_angle = 0 + dc_angle_offset + constant_linear_drift * time
                print("applying Gi with angle ", angle)
                rho = (_qt.to_super(_qt.rz(angle))) * rho
                angle = angle % (2 * np.pi)
                ideal_angle = 0
                if angle > np.pi:
                    angle = 2 * np.pi - angle
                if angle < 0:
                    angle = 0 + abs(angle)
                if ideal_angle > np.pi:
                    ideal_angle = 2 * np.pi - ideal_angle
                if ideal_angle < 0:
                    ideal_angle = 0 + abs(ideal_angle)
            total_angle += angle
            total_ideal_angle += ideal_angle

        #append the total rotation angle after timestamp 'time'
        angle_list.append(total_angle)
        expected_angle_list.append(total_ideal_angle)
        #calculate probabilities of being in 1 after the experiment has been applied
        p1 = (rho.dag() * rho1).norm()
        #fix the p1 if it exceeds 1 due to rounding error
        if p1 > 1:
            #print("p1 exceeds 1 for time {}".format(time))
            #print("prob is {}".format(p1))
            #print("Resetting to {}".format(2-p1))
            p1 = 2 - p1
        probs.append(p1)
        one_count = np.random.binomial(
            num_counts, p1
        )  #simulates a summation of the number of 1-counts you get in one bitstring sample
        zero_count = num_counts - one_count  #simulates summation of the number of 0-counts in one bitstring sample
        one_counts.append(one_count)
        zero_counts.append(zero_count)

    if plot_noise == True:
        plt.plot(timestamps,
                 np.asarray(expected_angle_list),
                 label="Ideal Angle",
                 ls='dashed',
                 color='orange')
        plt.plot(timestamps, np.asarray(angle_list), label="Drifting Angle")
        plt.legend()
        plt.xlabel("Time, seconds")
        plt.yticks(np.linspace(0, np.pi, 5),
                   ['0', '$\pi/4$', '$\pi/2$', '$3\pi/4$', '$\pi$'])
        plt.ylabel("Angle, radians\n(Displayed between 0 and $\pi$)")
        plt.title("Time-Dependent Rotation Angle after each {}".format(
            gate_list_to_string(gate_list)))
        plt.grid()
        plt.show()

        plt.figure(figsize=(15, 3))
        plt.plot(timestamps, probs)
        plt.ylim(0, 1)
        plt.xlim(timestamps[0], timestamps[-1])
        plt.xlabel("Time, seconds")
        plt.ylabel("Probability of Measuring State {1}")
        plt.title("Simulated {} with {} Noise".format(
            gate_list_to_string(gate_list), noise_type))
        plt.grid()
        plt.show()

    return (np.asarray(one_counts), np.asarray(zero_counts),
            np.asarray(timestamps), probs, np.asarray(expected_angle_list),
            np.asarray(angle_list), sig)
Esempio n. 20
0
def ramsey_experiment(left_gate_list, right_gate_list, L, field_f, transition_f, nCounts, time_per_gate, gate_switching_time, \
                      experiment_sample_time, time_units=1e-6, noise_type=None, freq_list=0,amp_list=0, phase_list=0,\
                      start_f=0, stop_f=0, fluctuators=0, plot_noise = False):
    #left and right gate_lists: lists of the gates sandwiching the Gi gates
    #L: the number of Gi gates. If you want to vary this, make it a list
    #field_f: frequency of external field in Hz. To vary this, make it a list. Either L or field_f must vary.
    #transition_f: frequency of the qubit transition in Hz.
    #time_per_gate: total time to complete one Gx, Gy, Gi, or Gz
    #switching_time: additional time before you start any new gate or change gates
    #experiment_sample_time: time at which you trigger a single expeimrent (single count), usually 60 Hz triggered
    #nCounts: number of times to repeat one experiment (a single set of parameters)
    #time_units: baseline units (in seconds) for any additional drift noise signal you may want to add. Defaults to ms.

    #check that the input has something to be varied
    if type(L) == type(field_f):
        print("Error: Either L or field_f must vary over a range!")
        return None
    #this list will contain the varied parameter, either detuning in Hz or delay time in s
    varied_param = []

    if type(L) == list:
        total_experiments = len(L)
        experiment_list = []
        for l in L:
            experiment_list.append(left_gate_list + ['Gi'] * l +
                                   right_gate_list)
        field_f_list = [field_f] * total_experiments
        varied_param = [(time_per_gate * l + gate_switching_time) for l in L]

    else:
        total_experiments = len(field_f)
        experiment_list = [left_gate_list + ['Gi'] * L + right_gate_list
                           ] * total_experiments
        field_f_list = field_f
        varied_param = delta_list

    #create a noise object:
    if noise_type != None and noise_type == "Sine":
        total_time = total_experiments * nCounts * experiment_sample_time + 1  #assumes that every count is taken every 0.016 seconds; no experiment takes longer
        sig = _ns.NoiseSignalSine(time_unit=time_units)
        sig.configure_noise(resolution_factor=1,
                            freq_list=freq_list,
                            amp_list=amp_list,
                            phase_list=phase_list,
                            total_time=total_time / time_units)
        sig.init()

        if plot_noise == True:
            sig.plot_noise_signal()

    probs = [
    ]  #a list of total_expeirment* elements. Has the probability for each experiment set (assumes constant p for all nCounts)
    time_per_experiment_set = [
    ]  #has the time at the start of each experiment set
    ones_counts = []  #number of 1s counted for each experiment set
    angles = []  #total theta rotation for each experiment set
    ideal_angles = []  #has the ideal theta rotation for each experiment set
    transition_f_list = [
    ]  #list of the transition frequency at the start of each experiment set
    detuning_list = [
    ]  #list of the detuning at the start of each experiment set
    absolute_time = 0  #seconds
    rho0 = _qt.operator_to_vector(_qt.ket2dm(_qt.basis(2, 0)))
    rho1 = _qt.operator_to_vector(_qt.ket2dm(_qt.basis(2, 1)))

    for experiment_index in range(total_experiments):
        experiment = experiment_list[experiment_index]
        compressed_experiment = compress_gate_list(experiment)
        #the following line assumes that each count for each experiment set is triggered at 0.0167 seconds (no single gate sequence can be longer than 1/60)
        absolute_time += experiment_sample_time * nCounts
        #print("Starting experiment set {} at {} s".format(experiment_index, absolute_time))
        rho = rho0
        total_angle = 0
        total_ideal_angle = 0
        modified_transition_f = transition_f
        detuning = field_f_list[experiment_index] - modified_transition_f
        for gate_name, repetitions in compressed_experiment:
            if noise_type != None:
                if absolute_time >= total_time:
                    print("Abs time: {}, total_time: {}".format(
                        absolute_time, total_time))
                detuning_noise = sig[absolute_time / time_units]
            else:
                detuning_noise = 0
            if gate_name == 'Gx':
                angle = (np.pi / 2) * repetitions
                ideal_angle = (np.pi / 2) * repetitions
                rho = (_qt.to_super(_qt.rx(angle))) * rho
                #this section just keeps the angle between 0 and pi
                angle = angle % (2 * np.pi)
                ideal_angle = ideal_angle % (2 * np.pi)
                if angle > np.pi:
                    angle = 2 * np.pi - angle
                if angle < 0:
                    angle = 0 + abs(angle)
                if ideal_angle > np.pi:
                    ideal_angle = 2 * np.pi - ideal_angle
                if ideal_angle < 0:
                    ideal_angle = 0 + abs(ideal_angle)
            elif gate_name == 'Gy':
                angle = (np.pi / 2) * repetitions
                ideal_angle = (np.pi / 2) * repetitions
                rho = (_qt.to_super(_qt.ry(angle))) * rho
                #this section just keeps the angle between 0 and pi
                angle = angle % (2 * np.pi)
                ideal_angle = ideal_angle % (2 * np.pi)
                if angle > np.pi:
                    angle = 2 * np.pi - angle
                if angle < 0:
                    angle = 0 + abs(angle)
                if ideal_angle > np.pi:
                    ideal_angle = 2 * np.pi - ideal_angle
                if ideal_angle < 0:
                    ideal_angle = 0 + abs(ideal_angle)
            elif gate_name == "Gi":
                #print("starting {} with z-rotation 2pi*{:.2f}".format(gate_list_to_string(experiment), detuning*(time_per_gate*repetitions + gate_switching_time)))
                #make the transition frequency oscillate between a fraction of its nominal value
                modified_transition_f = transition_f * (1 + detuning_noise)
                detuning = field_f_list[
                    experiment_index] - modified_transition_f
                angle = 2 * np.pi * detuning * (time_per_gate * repetitions +
                                                gate_switching_time)
                rho = (_qt.to_super(_qt.rz(angle))) * rho
            total_angle += angle
            total_ideal_angle += ideal_angle

        #calculate probabilities of being in 1 after the all the gates in the experiment have been applied
        p1 = (rho.dag() * rho1).norm()
        #fix the p1 if it exceeds 1 due to rounding error
        if p1 > 1:
            p1 = 2 - p1
        #get nCounts of data (bits) for the experiment
        one_counts = np.random.binomial(nCounts, p1)
        angles.append(total_angle)
        ideal_angles.append(total_ideal_angle)
        probs.append(p1)
        ones_counts.append(one_counts)
        time_per_experiment_set.append(absolute_time)
        transition_f_list.append(modified_transition_f)
        detuning_list.append(detuning)

    return np.asarray(ones_counts), np.asarray(
        time_per_experiment_set), np.asarray(probs), np.asarray(varied_param)
 def rx(self, theta: float) -> None:
     self.state = qt.rx(theta) * self.state
Esempio n. 22
0
def CO_rx(Chromosome, phase=np.pi / 8):
    return np.dot(Chromosome, np.array(qc.rx(phase).full()))
Esempio n. 23
0
def Rx(angle):
    return qt.rx(angle)