Source code for c3.libraries.tasks

from c3.c3objs import C3obj, Quantity
import tensorflow as tf
import numpy as np
import c3.libraries.constants as constants
import c3.utils.tf_utils as tf_utils
import c3.utils.qt_utils as qt_utils


task_lib = dict()


[docs]def task_deco(cl): """ Decorator for task classes list. """ task_lib[str(cl.__name__)] = cl return cl
[docs]class Task(C3obj): # TODO BETTER NAME FOR TASK! """Task that is part of the measurement setup.""" def __init__( self, name: str = " ", desc: str = " ", comment: str = " ", params: dict = None ): super().__init__(name=name, desc=desc, comment=comment, params=params)
[docs]@task_deco class InitialiseGround(Task): """Initialise the ground state with a given thermal distribution.""" def __init__( self, name: str = "init_ground", desc: str = " ", comment: str = " ", init_temp: Quantity = None, params=None, ): super().__init__(name=name, desc=desc, comment=comment, params=params) if init_temp: self.params["init_temp"] = init_temp
[docs] def initialise(self, drift_ham, lindbladian=False, init_temp=None): """ Prepare the initial state of the system. At the moment finite temperature requires open system dynamics. Parameters ---------- drift_ham : tf.Tensor Drift Hamiltonian. lindbladian : boolean Whether to include open system dynamics. Required for Temperature > 0. init_temp : Quantity Temperature of the device. Returns ------- tf.Tensor State or density vector """ if init_temp is None: init_temp = tf.cast( self.params["init_temp"].get_value(), dtype=tf.complex128 ) diag = tf.linalg.diag_part(drift_ham) dim = len(diag) if abs(init_temp) > np.finfo(float).eps: # this checks that it's not zero # TODO Deal with dressed basis for thermal state freq_diff = diag - diag[0] beta = 1 / (init_temp * constants.kb) det_bal = tf.exp(-constants.hbar * freq_diff * beta) norm_bal = det_bal / tf.reduce_sum(det_bal) dm = tf.linalg.diag(norm_bal) if lindbladian: return tf_utils.tf_dm_to_vec(dm) else: raise Warning("C3:WARNING: We still need to do Von Neumann right.") else: state = tf.constant( qt_utils.basis(dim, 0), shape=[dim, 1], dtype=tf.complex128 ) if lindbladian: return tf_utils.tf_dm_to_vec(tf_utils.tf_state_to_dm(state)) else: return state
[docs]@task_deco class ConfusionMatrix(Task): """Allows for misclassificaiton of readout measurement.""" def __init__( self, name: str = "conf_matrix", desc: str = " ", comment: str = " ", params=None, **confusion_rows, ): super().__init__(name=name, desc=desc, comment=comment, params=params) for qubit, conf_row in confusion_rows.items(): self.params["confusion_row_" + qubit] = conf_row
[docs] def confuse(self, pops): """ Apply the confusion (or misclassification) matrix to populations. Parameters ---------- pops : list Populations Returns ------- list Populations after misclassification. """ conf_matrix = tf.constant([[1]], dtype=tf.float64) for conf_row in self.params.values(): row1 = conf_row.get_value() row2 = tf.ones_like(row1) - row1 conf_mat = tf.concat([[row1], [row2]], 0) conf_matrix = tf_utils.tf_kron(conf_matrix, conf_mat) pops = tf.linalg.matmul(conf_matrix, pops) return pops
[docs]@task_deco class MeasurementRescale(Task): """ Rescale the result of the measurements. This is usually done to account for preparation errors. Parameters ---------- meas_offset : Quantity Offset added to the measured signal. meas_scale : Quantity Factor multiplied to the measured signal. """ def __init__( self, name: str = "meas_rescale", desc: str = " ", comment: str = " ", meas_offset: Quantity = None, meas_scale: Quantity = None, params=None, ): super().__init__(name=name, desc=desc, comment=comment, params=params) if meas_offset: self.params["meas_offset"] = meas_offset if meas_scale: self.params["meas_scale"] = meas_scale
[docs] def rescale(self, pop1): """ Apply linear rescaling and offset to the readout value. Parameters ---------- pop1 : tf.float64 Population in first excited state. Returns ------- tf.float64 Population after rescaling. """ return ( pop1 * self.params["meas_scale"].get_value() + self.params["meas_offset"].get_value() )