Example #1
0
def lindbladian_average_infid(ideal: np.ndarray,
                              actual: tf.constant,
                              index=[0],
                              dims=[2]) -> tf.constant:
    """
    Average fidelity uses the Pauli basis to compare. Thus, perfect gates are
    always 2x2 (per qubit) and the actual unitary needs to be projected down.

    Parameters
    ----------
    ideal: np.ndarray
        Contains ideal unitary representations of the gate
    actual: tf.Tensor
        Contains actual unitary representations of the gate
    index : int
        Index of the qubit(s) in the Hilbert space to be evaluated
    dims : list
        List of dimensions of qubits
    """
    U_ideal = tf_super(ideal)
    actual_comp = tf_project_to_comp(actual,
                                     dims=dims,
                                     index=index,
                                     to_super=True)
    infid = 1 - tf_superoper_average_fidelity(actual_comp, U_ideal, lvls=dims)
    return infid
Example #2
0
def lindbladian_average_infid(
    U_dict: dict, gate: str, index, dims, proj=True
):
    """
    Average fidelity uses the Pauli basis to compare. Thus, perfect gates are
    always 2x2 (per qubit) and the actual unitary needs to be projected down.

    Parameters
    ----------
    U_dict : dict
        Contains unitary representations of the gates, identified by a key.
    index : int
        Index of the qubit(s) in the Hilbert space to be evaluated
    dims : list
        List of dimensions of qubits
    proj : boolean
        Project to computational subspace
    """
    U = U_dict[gate]
    ideal = tf.constant(
        perfect_gate(gate, index, dims=[2]*len(dims)),
        dtype=tf.complex128
    )
    U_ideal = tf_super(ideal)
    infid = 1 - tf_superoper_average_fidelity(U, U_ideal, lvls=dims)
    return infid
Example #3
0
def lindbladian_unitary_infid(U_dict: dict, gate: str, index, dims, proj: bool):
    """
    Variant of the unitary fidelity for the Lindbladian propagator.

    Parameters
    ----------
    U_dict : dict
        Contains unitary representations of the gates, identified by a key.
    index : int
        Index of the qubit(s) in the Hilbert space to be evaluated
    gate : str
        One of the keys of U_dict, selects the gate to be evaluated
    dims : list
        List of dimensions of qubits
    proj : boolean
        Project to computational subspace

    Returns
    -------
    tf.float
        Overlap fidelity for the Lindblad propagator.
    """
    # Here we deal with the projected case differently because it's not easy
    # to select the right section of the superoper
    U = U_dict[gate]
    projection = "fulluni"
    fid_lvls = np.prod([dims[i] for i in index])
    if proj:
        projection = "wzeros"
        fid_lvls = 2 ** len(index)
    U_ideal = tf_super(
        tf.Variable(perfect_gate(gate, index, dims, projection), dtype=tf.complex128)
    )
    infid = 1 - tf_superoper_unitary_overlap(U, U_ideal, lvls=fid_lvls)
    return infid
Example #4
0
def lindbladian_unitary_infid(ideal: np.ndarray,
                              actual: tf.constant,
                              index=[0],
                              dims=[2]) -> tf.constant:
    """
    Variant of the unitary fidelity for the Lindbladian propagator.

    Parameters
    ----------
    ideal: np.ndarray
        Contains ideal unitary representations of the gate
    actual: tf.Tensor
        Contains actual unitary representations of the gate
    index : List[int]
        Index of the qubit(s) in the Hilbert space to be evaluated
    dims : list
        List of dimensions of qubits

    Returns
    -------
    tf.float
        Overlap fidelity for the Lindblad propagator.
    """
    U_ideal = tf_super(ideal)
    actual_comp = tf_project_to_comp(actual,
                                     dims=dims,
                                     index=index,
                                     to_super=True)
    fid_lvls = 2**len(index)
    infid = 1 - tf_superoper_unitary_overlap(
        actual_comp, U_ideal, lvls=fid_lvls)
    return infid
Example #5
0
def get_average_fidelitiy(get_error_process):
    lvls = [3, 3]
    Lambda = get_error_process
    d = 4
    err = tf_super(Lambda)
    choi = super_to_choi(err)
    chi = tf_choi_to_chi(choi, dims=lvls)
    fid = tf_abs((chi[0, 0] / d + 1) / (d + 1))
    return fid
Example #6
0
    def get_dephasing_channel(self, t_final, amps):
        """
        Compute the matrix of the dephasing channel to be applied on the operation.

        Parameters
        ----------
        t_final : tf.float64
            Duration of the operation.
        amps : dict of tf.float64
            Dictionary of average amplitude on each drive line.
        Returns
        -------
        tf.tensor
            Matrix representation of the dephasing channel.
        """

        tot_dim = self.tot_dim
        ones = tf.ones(tot_dim, dtype=tf.complex128)
        Id = tf_utils.tf_super(tf.linalg.diag(ones))
        deph_ch = Id
        for line in amps.keys():
            amp = amps[line]
            qubit = self.couplings[line].connected[0]
            # TODO extend this to multiple qubits
            ann_oper = self.ann_opers[self.names.index(qubit)]
            num_oper = tf.constant(
                np.matmul(ann_oper.T.conj(), ann_oper), dtype=tf.complex128
            )
            Z = tf_utils.tf_super(
                tf.linalg.expm(
                    1.0j * num_oper * tf.constant(np.pi, dtype=tf.complex128)
                )
            )
            p = t_final * amp * self.dephasing_strength
            print("dephasing stength: ", p)
            if p.numpy() > 1 or p.numpy() < 0:
                raise ValueError("strengh of dephasing channels outside [0,1]")
                print("dephasing stength: ", p)
            # TODO: check that this is right (or do you put the Zs together?)
            deph_ch = deph_ch * ((1 - p) * Id + p * Z)
        return deph_ch
Example #7
0
def lindbladian_epc_analytical(U_dict: dict, proj: bool):
    real_cliffords = evaluate_sequences(U_dict, cliffords_decomp)
    lvls = int(np.sqrt(real_cliffords[0].shape[0]))
    projection = "fulluni"
    fid_lvls = lvls
    if proj:
        projection = "wzeros"
        fid_lvls = 2
    ideal_cliffords = perfect_cliffords(str(lvls), projection)
    fids = []
    for C_indx in range(24):
        C_real = real_cliffords[C_indx]
        C_ideal = tf_super(tf.Variable(ideal_cliffords[C_indx], dtype=tf.complex128))
        ave_fid = tf_superoper_average_fidelity(C_real, C_ideal, lvls=fid_lvls)
        fids.append(ave_fid)
    infid = 1 - tf_ave(fids)
    return infid
Example #8
0
def lindbladian_epc_analytical(U_dict: dict,
                               index,
                               dims,
                               proj: bool,
                               cliffords=False):
    num_gates = len(dims)
    if cliffords:
        real_cliffords = evaluate_sequences(U_dict,
                                            [[C] for C in cliffords_string])
    elif num_gates == 1:
        real_cliffords = evaluate_sequences(U_dict, cliffords_decomp)
    elif num_gates == 2:
        real_cliffords = evaluate_sequences(U_dict, cliffords_decomp_xId)
    ideal_cliffords = perfect_cliffords(lvls=[2] * num_gates,
                                        num_gates=num_gates)
    fids = []
    for C_indx in range(24):
        C_real = real_cliffords[C_indx]
        C_ideal = tf_super(
            tf.constant(ideal_cliffords[C_indx], dtype=tf.complex128))
        ave_fid = tf_superoper_average_fidelity(C_real, C_ideal, lvls=dims)
        fids.append(ave_fid)
    infid = 1 - tf_ave(fids)
    return infid
Example #9
0
    def get_gates(self):
        """
        Compute the unitary representation of operations. If no operations are
        specified in self.opt_gates the complete gateset is computed.

        Returns
        -------
        dict
            A dictionary of gate names and their unitary representation.
        """
        model = self.pmap.model
        generator = self.pmap.generator
        instructions = self.pmap.instructions
        gates = {}
        gate_keys = self.opt_gates
        if gate_keys is None:
            gate_keys = instructions.keys()

        for gate in gate_keys:
            try:
                instr = instructions[gate]
            except KeyError:
                raise Exception(
                    f"C3:Error: Gate '{gate}' is not defined."
                    f" Available gates are:\n {list(instructions.keys())}.")
            signal = generator.generate_signals(instr)
            U = self.propagation(signal, gate)
            if model.use_FR:
                # TODO change LO freq to at the level of a line
                freqs = {}
                framechanges = {}
                for line, ctrls in instr.comps.items():
                    # TODO calculate properly the average frequency that each qubit sees
                    offset = 0.0
                    for ctrl in ctrls.values():
                        if "freq_offset" in ctrl.params.keys():
                            if ctrl.params["amp"] != 0.0:
                                offset = ctrl.params["freq_offset"].get_value()
                    freqs[line] = tf.cast(
                        ctrls["carrier"].params["freq"].get_value() + offset,
                        tf.complex128,
                    )
                    framechanges[line] = tf.cast(
                        ctrls["carrier"].params["framechange"].get_value(),
                        tf.complex128,
                    )
                t_final = tf.constant(instr.t_end - instr.t_start,
                                      dtype=tf.complex128)
                FR = model.get_Frame_Rotation(t_final, freqs, framechanges)
                if model.lindbladian:
                    SFR = tf_utils.tf_super(FR)
                    U = tf.matmul(SFR, U)
                    self.FR = SFR
                else:
                    U = tf.matmul(FR, U)
                    self.FR = FR
            if model.dephasing_strength != 0.0:
                if not model.lindbladian:
                    raise ValueError(
                        "Dephasing can only be added when lindblad is on.")
                else:
                    amps = {}
                    for line, ctrls in instr.comps.items():
                        amp, sum = generator.devices["awg"].get_average_amp()
                        amps[line] = tf.cast(amp, tf.complex128)
                    t_final = tf.constant(instr.t_end - instr.t_start,
                                          dtype=tf.complex128)
                    dephasing_channel = model.get_dephasing_channel(
                        t_final, amps)
                    U = tf.matmul(dephasing_channel, U)
            gates[gate] = U
            self.unitaries = gates
        return gates
Example #10
0
    def plot_dynamics(self, psi_init, seq, goal=-1, debug=False):
        # TODO double check if it works well
        """
        Plotting code for time-resolved populations.

        Parameters
        ----------
        psi_init: tf.Tensor
            Initial state or density matrix.
        seq: list
            List of operations to apply to the initial state.
        goal: tf.float64
            Value of the goal function, if used.
        debug: boolean
            If true, return a matplotlib figure instead of saving.
        """
        dUs = self.dUs
        psi_t = psi_init.numpy()
        pop_t = self.populations(psi_t, self.model.lindbladian)
        for gate in seq:
            for du in dUs[gate]:
                psi_t = np.matmul(du.numpy(), psi_t)
                pops = self.populations(psi_t, self.model.lindbladian)
                pop_t = np.append(pop_t, pops, axis=1)
            if self.model.use_FR:
                instr = self.gateset.instructions[gate]
                signal, ts = self.generator.generate_signals(instr)
                # TODO change LO freq to at the level of a line
                freqs = {}
                framechanges = {}
                for line, ctrls in instr.comps.items():
                    offset = 0.0
                    if "gauss" in ctrls:
                        if ctrls['gauss'].params["amp"] != 0.0:
                            offset = ctrls['gauss'].params[
                                'freq_offset'].get_value()

                    freqs[line] = tf.cast(
                        ctrls['carrier'].params['freq'].get_value() + offset,
                        tf.complex128)
                    framechanges[line] = tf.cast(
                        ctrls['carrier'].params['framechange'].get_value(),
                        tf.complex128)
                t_final = tf.constant(instr.t_end - instr.t_start,
                                      dtype=tf.complex128)
                FR = self.model.get_Frame_Rotation(t_final, freqs,
                                                   framechanges)
                if self.model.lindbladian:
                    FR = tf_utils.tf_super(FR)
                psi_t = tf.matmul(FR, psi_t)
                # TODO added framchanged psi to list

        fig, axs = plt.subplots(1, 1)
        ts = self.ts
        dt = ts[1] - ts[0]
        ts = np.linspace(0.0, dt * pop_t.shape[1], pop_t.shape[1])
        axs.plot(ts / 1e-9, pop_t.T)
        axs.grid(linestyle="--")
        axs.tick_params(direction="in",
                        left=True,
                        right=True,
                        top=True,
                        bottom=True)
        axs.set_xlabel('Time [ns]')
        axs.set_ylabel('Population')
        plt.legend(self.model.state_labels)
        if debug:
            plt.show()
        else:
            plt.savefig(
                self.logdir +
                f"dynamics/eval_{self.dynamics_plot_counter}_{seq[0]}_{goal}.png",
                dpi=300)
Example #11
0
    def get_gates(self):
        """
        Compute the unitary representation of operations. If no operations are
        specified in self.opt_gates the complete gateset is computed.

        Returns
        -------
        dict
            A dictionary of gate names and their unitary representation.
        """
        gates = {}
        if "opt_gates" in self.__dict__:
            gate_keys = self.opt_gates
        else:
            gate_keys = self.gateset.instructions.keys()
        for gate in gate_keys:
            try:
                instr = self.gateset.instructions[gate]
            except KeyError:
                raise Exception(
                    f"C3:Error: Gate \'{gate}\' is not defined."
                    f" Available gates are:\n {list(self.gateset.instructions.keys())}."
                )
            signal, ts = self.generator.generate_signals(instr)
            U = self.propagation(signal, ts, gate)
            if self.model.use_FR:
                # TODO change LO freq to at the level of a line
                freqs = {}
                framechanges = {}
                for line, ctrls in instr.comps.items():
                    # TODO calculate properly the average frequency that each qubit sees
                    offset = 0.0
                    if "gauss" in ctrls:
                        if ctrls['gauss'].params["amp"] != 0.0:
                            offset = ctrls['gauss'].params[
                                'freq_offset'].get_value()
                    if "flux" in ctrls:
                        if ctrls['flux'].params["amp"] != 0.0:
                            offset = ctrls['flux'].params[
                                'freq_offset'].get_value()
                    if "pwc" in ctrls:
                        offset = ctrls['pwc'].params['freq_offset'].get_value()
                    # print("gate: ", gate, "; line: ", line, "; offset: ", offset)
                    freqs[line] = tf.cast(
                        ctrls['carrier'].params['freq'].get_value() + offset,
                        tf.complex128)
                    framechanges[line] = tf.cast(
                        ctrls['carrier'].params['framechange'].get_value(),
                        tf.complex128)
                t_final = tf.constant(instr.t_end - instr.t_start,
                                      dtype=tf.complex128)
                FR = self.model.get_Frame_Rotation(t_final, freqs,
                                                   framechanges)
                if self.model.lindbladian:
                    SFR = tf_utils.tf_super(FR)
                    U = tf.matmul(SFR, U)
                    self.FR = SFR
                else:
                    U = tf.matmul(FR, U)
                    self.FR = FR
            if self.model.dephasing_strength != 0.0:
                if not self.model.lindbladian:
                    raise ValueError(
                        'Dephasing can only be added when lindblad is on.')
                else:
                    amps = {}
                    for line, ctrls in instr.comps.items():
                        amp, sum = self.generator.devices[
                            'awg'].get_average_amp()
                        amps[line] = tf.cast(amp, tf.complex128)
                    t_final = tf.constant(instr.t_end - instr.t_start,
                                          dtype=tf.complex128)
                    dephasing_channel = self.model.get_dephasing_channel(
                        t_final, amps)
                    U = tf.matmul(dephasing_channel, U)
            gates[gate] = U
            self.unitaries = gates
        return gates
Example #12
0
def test_tf_super():
    for el in data["tf_super"]:
        np.testing.assert_allclose(actual=tf_super(el["in"]),
                                   desired=el["desired"])
Example #13
0
    def compute_propagators(self):
        """
        Compute the unitary representation of operations. If no operations are
        specified in self.opt_gates the complete gateset is computed.

        Returns
        -------
        dict
            A dictionary of gate names and their unitary representation.
        """
        model = self.pmap.model
        generator = self.pmap.generator
        instructions = self.pmap.instructions
        propagators = {}
        partial_propagators = {}
        gate_ids = self.opt_gates
        if gate_ids is None:
            gate_ids = instructions.keys()

        for gate in gate_ids:
            try:
                instr = instructions[gate]
            except KeyError:
                raise Exception(
                    f"C3:Error: Gate '{gate}' is not defined."
                    f" Available gates are:\n {list(instructions.keys())}.")

            model.controllability = self.use_control_fields
            result = self.propagation(model, generator, instr)
            U = result["U"]
            dUs = result["dUs"]
            self.ts = result["ts"]
            if model.use_FR:
                # TODO change LO freq to at the level of a line
                freqs = {}
                framechanges = {}
                for line, ctrls in instr.comps.items():
                    # TODO calculate properly the average frequency that each qubit sees
                    offset = 0.0
                    for ctrl in ctrls.values():
                        if "freq_offset" in ctrl.params.keys():
                            if ctrl.params["amp"] != 0.0:
                                offset = ctrl.params["freq_offset"].get_value()
                    freqs[line] = tf.cast(
                        ctrls["carrier"].params["freq"].get_value() + offset,
                        tf.complex128,
                    )
                    framechanges[line] = tf.cast(
                        ctrls["carrier"].params["framechange"].get_value(),
                        tf.complex128,
                    )
                t_final = tf.constant(instr.t_end - instr.t_start,
                                      dtype=tf.complex128)
                FR = model.get_Frame_Rotation(t_final, freqs, framechanges)
                if model.lindbladian:
                    SFR = tf_super(FR)
                    U = tf.matmul(SFR, U)
                    self.FR = SFR
                else:
                    U = tf.matmul(FR, U)
                    self.FR = FR
            if model.dephasing_strength != 0.0:
                if not model.lindbladian:
                    raise ValueError(
                        "Dephasing can only be added when lindblad is on.")
                else:
                    amps = {}
                    for line, ctrls in instr.comps.items():
                        amp, sum = generator.devices["awg"].get_average_amp()
                        amps[line] = tf.cast(amp, tf.complex128)
                    t_final = tf.constant(instr.t_end - instr.t_start,
                                          dtype=tf.complex128)
                    dephasing_channel = model.get_dephasing_channel(
                        t_final, amps)
                    U = tf.matmul(dephasing_channel, U)
            propagators[gate] = U
            partial_propagators[gate] = dUs

        # TODO we might want to move storing of the propagators to the instruction object
        if self.overwrite_propagators:
            self.propagators = propagators
            self.partial_propagators = partial_propagators
        else:
            self.propagators.update(propagators)
            self.partial_propagators.update(partial_propagators)
        self.compute_propagators_timestamp = time.time()
        return propagators