예제 #1
0
    def _state_dict(self) -> Dict[str, Any]:
        state_dict = dict()
        # need to store model arch because of randomness of random layers
        state_dict['model_arch'] = self.model
        state_dict['model'] = self.model.state_dict()
        state_dict['optimizer'] = self.optimizer.state_dict()
        state_dict['scheduler'] = self.scheduler.state_dict()
        if getattr(self.model, 'sample_arch', None) is not None:
            state_dict['sample_arch'] = self.model.sample_arch
        try:
            state_dict['q_layer_op_list'] = build_module_op_list(
                self.model.q_layer)
            state_dict['encoder_func_list'] = self.model.encoder.func_list
        except AttributeError:
            logger.warning(f"No q_layer_op_list or encoder_func_list found, "
                           f"will not save them")

        if self.solution is not None:
            state_dict['solution'] = self.solution
            state_dict['score'] = self.score

        try:
            state_dict['v_c_reg_mapping'] = self.model.measure.v_c_reg_mapping
        except AttributeError:
            logger.warning(f"No v_c_reg_mapping found, will not save it.")
        return state_dict
예제 #2
0
    def _trigger(self):
        if self.scalar not in self.trainer.summary:
            logger.warning(
                f'`{self.scalar}` has not been added to `trainer.summary`.')
            return
        step, value = self.trainer.summary[self.scalar][-1]

        if self.step is not None and step <= self.step:
            logger.warning(
                f'`{self.scalar}` has not been updated since last trigger.')
            return
        self.step = step

        if (self.best is None
                or (self.extreme == 'min' and value < self.best[1])
                or (self.extreme == 'max' and value > self.best[1])):
            self.best = (step, value)
            save_path = os.path.join(self.save_dir, self.name + '.pt')
            try:
                io.save(save_path, self.trainer.state_dict())
            except OSError:
                logger.exception(
                    f'Error occurred when saving checkpoint "{save_path}".')
            else:
                logger.info(f'Checkpoint saved: "{save_path}" ({value:.5g}).')

        if self.best is not None:
            self.trainer.summary.add_scalar(self.scalar + '/' + self.extreme,
                                            self.best[1])
예제 #3
0
def init(
    backend: str = 'nccl',
    timeout: timedelta = default_pg_timeout,
) -> None:
    from mpi4py import MPI
    world_comm = MPI.COMM_WORLD
    local_comm = MPI.COMM_WORLD.Split_type(MPI.COMM_TYPE_SHARED)

    global _world_size, _world_rank, _local_size, _local_rank
    _world_size, _world_rank = world_comm.Get_size(), world_comm.Get_rank()
    _local_size, _local_rank = local_comm.Get_size(), local_comm.Get_rank()

    if 'MASTER_HOST' in os.environ:
        master_host = 'tcp://' + os.environ['MASTER_HOST']
    else:
        master_host = f'tcp://localhost:{get_free_tcp_port()}'
        logger.warning(
            'Distributed environment not detected, fall back to default')

    torch.distributed.init_process_group(
        backend=backend,
        init_method=master_host,
        timeout=timeout,
        world_size=_world_size,
        rank=_world_rank,
    )
예제 #4
0
    def __init__(self,
                 has_params: bool = False,
                 trainable: bool = False,
                 init_params=None,
                 n_wires=None,
                 wires=None):
        super().__init__()
        self.params = None
        # number of wires of the operator
        # n_wires is used in gates that can be applied to arbitrary number
        # of qubits such as MultiRZ
        self.n_wires = n_wires
        # wires that the operator applies to
        self.wires = wires
        self._name = self.__class__.__name__
        # for static mode
        self.static_matrix = None
        self.inverse = False

        try:
            assert not (trainable and not has_params)
        except AssertionError:
            has_params = True
            logger.warning(f"Module must have parameters to be trainable; "
                           f"Switched 'has_params' to True.")

        self.has_params = has_params
        self.trainable = trainable
        if self.has_params:
            self.params = self.build_params(trainable=self.trainable)
            self.reset_params(init_params)
예제 #5
0
def build_module_from_op_list(op_list: List[Dict],
                              remove_ops=False,
                              thres=None) -> tq.QuantumModule:
    logger.info(f"Building module from op_list...")
    thres = 1e-5 if thres is None else thres
    n_removed_ops = 0
    ops = []
    for info in op_list:
        params = info['params']

        if remove_ops:
            if params is not None:
                params = np.array(params) if isinstance(params, Iterable) \
                    else np.array([params])
                params = params % (2 * np.pi)
                params[params > np.pi] -= 2 * np.pi
                if all(abs(params) < thres):
                    n_removed_ops += 1
                    continue

        op = tq.op_name_dict[info['name']](
            has_params=info['has_params'],
            trainable=info['trainable'],
            wires=info['wires'],
            n_wires=info['n_wires'],
            init_params=info['params'],
        )
        ops.append(op)

    if n_removed_ops > 0:
        logger.warning(f"Remove in total {n_removed_ops} pruned operations.")
    else:
        logger.info(f"Do not remove any operations.")

    return tq.QuantumModuleFromOps(ops)
예제 #6
0
 def get_n_ops_per_chunk(self):
     """separate the space to several subspace"""
     n_chunks = self.strategy['n_chunks']
     if self.strategy['chunk_mode'] == 'same_interval':
         logger.warning(f"same_interval chunking may cause extra long "
                        f"time to sample a sub network because of the "
                        f"Central Limit Theorem of n_ops in a subnet")
         self.n_ops_per_chunk = list(np.linspace(self.n_ops_smallest,
                                                 self.n_ops_largest,
                                                 n_chunks + 1).astype(int))
     elif self.strategy['chunk_mode'] == 'same_n_samples':
         logger.info("estimating the chunks...")
         n_ops_all = []
         n_chunk_est_samples = self.strategy['n_chunk_est_samples']
         for k in range(n_chunk_est_samples):
             sample_arch = self.get_random_sample_arch()
             n_ops_all.append(self.get_sample_stats(sample_arch))
         n_ops_all.sort()
         idx_all = np.linspace(0, n_chunk_est_samples - 1, n_chunks +
                               1).astype(int)
         self.n_ops_per_chunk = [n_ops_all[idx] for idx in idx_all]
         self.n_ops_per_chunk[0] = self.n_ops_smallest
         self.n_ops_per_chunk[-1] = self.n_ops_largest
     else:
         raise NotImplementedError(
             f"chunk mode {self.strategy['chunk_mode']} not supported.")
예제 #7
0
 def build_flat_module_list(self, module_list=None):
     if module_list is None:
         module_list = self.module_list
     for module in module_list:
         if len(module.graph.module_list) == 0 and not \
                 isinstance(module, tq.Operator):
             logger.warning(f"Module with no operations exists!")
         if len(module.graph.module_list) == 0 and isinstance(
                 module, tq.Operator):
             # leaf node
             self.flat_module_list.append(module)
         else:
             self.build_flat_module_list(module.graph.module_list)
예제 #8
0
    def __init__(self,
                 population_size,
                 parent_size,
                 mutation_size,
                 mutation_prob,
                 crossover_size,
                 n_wires,
                 n_available_wires,
                 arch_space,
                 gene_mask=None,
                 enumerate_layout=False,
                 random_search=False
                 ):
        self.population_size = population_size
        self.parent_size = parent_size
        self.mutation_size = mutation_size
        self.mutation_prob = mutation_prob
        self.crossover_size = crossover_size
        assert self.population_size == self.parent_size + self.mutation_size \
               + self.crossover_size

        self.n_wires = n_wires
        self.n_available_wires = n_available_wires
        self.arch_space = arch_space

        self.converter = Converter(
            self.n_wires,
            self.n_available_wires,
            self.arch_space
        )

        self.gene_choice = self.converter.get_gene_choice()
        self.gene_len = len(self.gene_choice)
        self.best_solution = None
        self.best_score = None

        self.random_search = random_search

        # to constraint the design space in a fine-grained manner
        self.gene_mask = gene_mask
        if gene_mask is not None and \
                all(np.array(gene_mask[:n_wires]) == -1) and \
                all(np.array(gene_mask[n_wires:]) > -1) and enumerate_layout:
            # enumerate all possible layouts and only need run 1 iteration
            logger.warning(f"Shift to exhaustive search for best layout, "
                           f"surpass all evolution configs!")
            self.population = self.enumerate_layout()
        else:
            # initialize with random samples
            self.population = self.random_sample(self.population_size)
예제 #9
0
 def _state_dict(self) -> Dict[str, Any]:
     state_dict = dict()
     # need to store model arch because of randomness of random layers
     state_dict['model_arch'] = self.model
     state_dict['model'] = self.model.state_dict()
     state_dict['optimizer'] = self.optimizer.state_dict()
     state_dict['scheduler'] = self.scheduler.state_dict()
     if getattr(self.model, 'sample_arch', None) is not None:
         state_dict['sample_arch'] = self.model.sample_arch
     try:
         state_dict['v_c_reg_mapping'] = self.model.measure.v_c_reg_mapping
     except AttributeError:
         logger.warning(f"No v_c_reg_mapping found, will not save it.")
     return state_dict
예제 #10
0
    def _before_train(self) -> None:
        checkpoints = glob.glob(os.path.join(self.load_dir, 'step-*.pt'))
        if not checkpoints:
            logger.warning(f'No checkpoints found: "{self.load_dir}".')
            return

        load_path = max(checkpoints, key=os.path.getmtime)
        try:
            state_dict = io.load(load_path, map_location='cpu')
            self.trainer.load_state_dict(state_dict)
        except OSError:
            logger.exception(
                f'Error occurred when loading checkpoint "{load_path}".')
        else:
            logger.info(f'Checkpoint loaded: "{load_path}".')
예제 #11
0
    def _state_dict(self) -> Dict[str, Any]:
        state_dict = dict()
        # need to store model arch because of randomness of random layers
        state_dict['model_arch'] = self.model
        state_dict['model'] = self.model.state_dict()
        state_dict['optimizer'] = self.optimizer.state_dict()
        state_dict['scheduler'] = self.scheduler.state_dict()
        if getattr(self.model, 'sample_arch', None) is not None:
            state_dict['sample_arch'] = self.model.sample_arch

        if self.solution is not None:
            state_dict['solution'] = self.solution
            state_dict['score'] = self.score

        if getattr(self.model, 'encoder', None) is not None:
            if getattr(self.model.encoder, 'func_list', None) is not None:
                state_dict['encoder_func_list'] = self.model.encoder.func_list

        if getattr(self.model, 'q_layer', None) is not None:
            state_dict['q_layer_op_list'] = build_module_op_list(
                self.model.q_layer)

        if getattr(self.model, 'measure', None) is not None:
            if getattr(self.model.measure, 'v_c_reg_mapping',
                       None) is not None:
                state_dict['v_c_reg_mapping'] = \
                    self.model.measure.v_c_reg_mapping

        if getattr(self.model, 'nodes', None) is not None:
            state_dict['encoder_func_list'] = [
                node.encoder.func_list for node in self.model.nodes
            ]
            if configs.model.transpile_before_run:
                # only save op_list if transpile before run
                state_dict['q_layer_op_list'] = [
                    build_module_op_list(node.q_layer)
                    for node in self.model.nodes
                ]
            state_dict['v_c_reg_mapping'] = [
                node.measure.v_c_reg_mapping for node in self.model.nodes
            ]
        for attr in [
                'v_c_reg_mapping', 'encoder_func_list', 'q_layer_op_list'
        ]:
            if state_dict.get(attr, None) is None:
                logger.warning(f"No {attr} found, will not save it.")

        return state_dict
예제 #12
0
 def __init__(self, *, devices: Optional[List[int]] = None) -> None:
     if devices is not None:
         self.devices = devices
     else:
         env = os.environ.get('CUDA_VISIBLE_DEVICES')
         if env:
             self.devices = list(map(int, env.split(',')))
         elif env is None:
             self.devices = list(range(torch.cuda.device_count()))
             if len(self.devices) > 1:
                 logger.warning(
                     'Neither `devices` nor `CUDA_VISIBLE_DEVICES` is set! '
                     'All {} visible GPUs will be monitored.'.format(
                         len(self.devices)))
         else:
             raise RuntimeError('No GPU device is specified!')
예제 #13
0
    def __init__(
        self,
        wires,
        n_ops=None,
        n_params=None,
        op_ratios=None,
        op_types=(tq.RX, tq.RY, tq.RZ, tq.CNOT),
        seed=None,
        qiskit_compatible=False,
    ):
        super().__init__()
        self.n_ops = n_ops
        self.n_params = n_params
        assert n_params is not None or n_ops is not None
        self.wires = wires if isinstance(wires, Iterable) else [wires]
        self.n_wires = len(wires)

        op_types = op_types if isinstance(op_types, Iterable) else [op_types]
        if op_ratios is None:
            op_ratios = [1] * len(op_types)
        else:
            op_ratios = op_ratios if isinstance(op_ratios,
                                                Iterable) else [op_ratios]
        op_types_valid = []
        op_ratios_valid = []

        if qiskit_compatible:
            for op_type, op_ratio in zip(op_types, op_ratios):
                if op_type().name.lower() in QISKIT_INCOMPATIBLE_FUNC_NAMES:
                    logger.warning(f"Remove {op_type} from op_types to make "
                                   f"the layer qiskit-compatible.")
                else:
                    op_types_valid.append(op_type)
                    op_ratios_valid.append(op_ratio)
        else:
            op_types_valid = op_types
            op_ratios_valid = op_ratios

        self.op_types = op_types_valid
        self.op_ratios = np.array(op_ratios_valid) / sum(op_ratios_valid)

        self.seed = seed
        self.op_list = tq.QuantumModuleList()
        if seed is not None:
            np.random.seed(seed)
        self.build_random_layer()
예제 #14
0
def run_job_worker(data):
    while True:
        try:
            job = execute(**(data[0]))
            qiskit_verbose = data[1]
            if qiskit_verbose:
                job_monitor(job, interval=1)
            result = job.result()
            counts = result.get_counts()
            break
        except Exception as e:
            if "Job was cancelled" in str(e):
                logger.warning(f"Job is cancelled manually.")
                return None
            else:
                logger.warning(f"Job failed because {e}, rerun now.")

    return counts
예제 #15
0
def cos_adjust_noise(current_epoch, n_epochs, prob_schedule,
                     prob_schedule_separator, orig_noise_total_prob):
    if prob_schedule is None:
        noise_total_prob = orig_noise_total_prob
    elif prob_schedule == 'increase':
        # scale the cos
        if current_epoch <= prob_schedule_separator:
            noise_total_prob = orig_noise_total_prob * (
                -np.cos(current_epoch / prob_schedule_separator * np.pi) / 2 +
                0.5)
        else:
            noise_total_prob = orig_noise_total_prob
    elif prob_schedule == 'decrease':
        if current_epoch >= prob_schedule_separator:
            noise_total_prob = orig_noise_total_prob * (np.cos(
                (current_epoch - prob_schedule_separator) /
                (n_epochs - prob_schedule_separator) * np.pi) / 2 + 0.5)
        else:
            noise_total_prob = orig_noise_total_prob
    elif prob_schedule == 'increase_decrease':
        # if current_epoch <= self.prob_schedule_separator:
        #     self.noise_total_prob = self.orig_noise_total_prob * \
        #         1 / (1 + np.exp(-(current_epoch - (
        #             self.prob_schedule_separator / 2)) / 10))
        # else:
        #     self.noise_total_prob = self.orig_noise_total_prob * \
        #         1 / (1 + np.exp((current_epoch - (
        #             self.n_epochs + self.prob_schedule_separator) / 2) /
        #                 10))
        if current_epoch <= prob_schedule_separator:
            noise_total_prob = orig_noise_total_prob * (
                -np.cos(current_epoch / prob_schedule_separator * np.pi) / 2 +
                0.5)
        else:
            noise_total_prob = orig_noise_total_prob * (np.cos(
                (current_epoch - prob_schedule_separator) /
                (n_epochs - prob_schedule_separator) * np.pi) / 2 + 0.5)
    else:
        logger.warning(f"Not implemented schedule{prob_schedule}, "
                       f"will not change prob!")
        noise_total_prob = orig_noise_total_prob

    return noise_total_prob
예제 #16
0
def get_provider(backend_name, hub=None):
    # mass-inst-tech-1 or MIT-1
    if backend_name in ['ibmq_casablanca', 'ibmq_rome', 'ibmq_bogota']:
        if hub == 'mass' or hub is None:
            provider = IBMQ.get_provider(hub='ibm-q-research',
                                         group='mass-inst-tech-1',
                                         project='main')
        elif hub == 'mit':
            provider = IBMQ.get_provider(hub='ibm-q-research',
                                         group='MIT-1',
                                         project='main')
        else:
            raise ValueError(f"not supported backend {backend_name} in hub "
                             f"{hub}")
    elif backend_name in [
            'ibmq_paris', 'ibmq_toronto', 'ibmq_manhattan', 'ibmq_guadalupe'
    ]:
        provider = IBMQ.get_provider(hub='ibm-q-ornl',
                                     group='anl',
                                     project='csc428')
    else:
        if hub == 'mass' or hub is None:
            try:
                provider = IBMQ.get_provider(hub='ibm-q-research',
                                             group='mass-inst-tech-1',
                                             project='main')
            except QiskitError:
                logger.warning(f"Cannot use MIT backend, roll back to open")
                provider = IBMQ.get_provider(hub='ibm-q')
        elif hub == 'mit':
            provider = IBMQ.get_provider(hub='ibm-q-research',
                                         group='MIT-1',
                                         project='main')
        else:
            provider = IBMQ.get_provider(hub='ibm-q')

    return provider
예제 #17
0
    def _state_dict(self) -> Dict[str, Any]:
        # remove hook otherwise the 'model' cannot be pickled
        self.remove_act_quant_hook()
        state_dict = dict()
        # need to store model arch because of randomness of random layers
        state_dict['model_arch'] = self.model
        state_dict['model'] = self.model.state_dict()
        state_dict['optimizer'] = self.optimizer.state_dict()
        state_dict['scheduler'] = self.scheduler.state_dict()
        if getattr(self.model, 'sample_arch', None) is not None:
            state_dict['sample_arch'] = self.model.sample_arch

        if self.solution is not None:
            state_dict['solution'] = self.solution
            state_dict['score'] = self.score

        if getattr(self.model, 'encoder', None) is not None:
            if getattr(self.model.encoder, 'func_list', None) is not None:
                state_dict['encoder_func_list'] = self.model.encoder.func_list

        if getattr(self.model, 'q_layer', None) is not None:
            state_dict['q_layer_op_list'] = build_module_op_list(
                self.model.q_layer)

        if getattr(self.model, 'measure', None) is not None:
            if getattr(self.model.measure, 'v_c_reg_mapping',
                       None) is not None:
                state_dict['v_c_reg_mapping'] = \
                    self.model.measure.v_c_reg_mapping

        if getattr(self.model, 'noise_model_tq', None) is not None:
            state_dict['noise_model_tq'] = self.model.noise_model_tq

        if configs.trainer.act_quant:
            state_dict['act_quant'] = {
                'act_quant_bit': self.quantizers[0].precision,
                'act_quant_level': self.quantizers[0].level,
                'act_quant_ratio': self.quantizers[0].quant_ratio,
                'act_quant_lower_bound': self.quantizers[0].lower_bound,
                'act_quant_upper_bound': self.quantizers[0].upper_bound,
            }

        if getattr(self.model, 'nodes', None) is not None:
            state_dict['encoder_func_list'] = [
                node.encoder.func_list for node in self.model.nodes
            ]
            if configs.model.transpile_before_run:
                # only save op_list if transpile before run
                state_dict['q_layer_op_list'] = [
                    build_module_op_list(node.q_layer)
                    for node in self.model.nodes
                ]
            state_dict['v_c_reg_mapping'] = [
                node.measure.v_c_reg_mapping for node in self.model.nodes
            ]

            # one node has one own noise model
            state_dict['noise_model_tq'] = [
                node.noise_model_tq for node in self.model.nodes
            ]

        for attr in [
                'v_c_reg_mapping', 'encoder_func_list', 'q_layer_op_list',
                'noise_model_tq'
        ]:
            if state_dict.get(attr, None) is None:
                logger.warning(f"No {attr} found, will not save it.")

        return state_dict
예제 #18
0
        filters=lambda x: x.configuration().n_qubits >= args.n and not x.
        configuration().simulator and x.status().operational)

    candidates = []
    now = datetime.now()
    for back in backends:
        backend_status = back.status()
        if not backend_status.operational or \
                backend_status.status_msg != 'active':
            continue
        if isinstance(back, IBMQBackend):
            end_time = now + timedelta(minutes=args.m)
            try:
                if back.reservations(now, end_time):
                    logger.warning(
                        f"{back} jobs: {back.status().pending_jobs}, "
                        f"has reservation in {args.m} minutes.")
                    continue
                else:
                    logger.info(f"{back} jobs: {back.status().pending_jobs}, "
                                f"has no reservation in {args.m} minutes.")
            except Exception as err:  # pylint: disable=broad-except
                logger.warning(
                    "Unable to find backend reservation "
                    "information. "
                    "It will not be taken into consideration. %s", str(err))
        candidates.append(back)
    if not candidates:
        raise ValueError('No backend matches the criteria.')

    least_busy_dev = min(candidates, key=lambda b: b.status().pending_jobs)
예제 #19
0
def tq2qiskit(q_device: tq.QuantumDevice,
              m: tq.QuantumModule,
              x=None,
              draw=False,
              remove_ops=False,
              remove_ops_thres=1e-4):
    # build the module list without changing the statevector of QuantumDevice
    original_wires_per_block = m.wires_per_block
    original_static_mode = m.static_mode
    m.static_off()
    m.static_on(wires_per_block=q_device.n_wires)
    m.is_graph_top = False

    # forward to register all modules and parameters
    if x is None:
        m.forward(q_device)
    else:
        m.forward(q_device, x)

    m.is_graph_top = True
    m.graph.build_flat_module_list()

    module_list = m.graph.flat_module_list
    m.static_off()

    if original_static_mode:
        m.static_on(wires_per_block=original_wires_per_block)

    circ = QuantumCircuit(q_device.n_wires, q_device.n_wires)

    for module in module_list:
        try:
            # no params in module or batch size == 1, because we will
            # generate only one qiskit QuantumCircuit
            assert (module.params is None or module.params.shape[0] == 1)
        except AssertionError:
            logger.exception(f"Cannot convert batch model tq module")

    n_removed_ops = 0

    for module in module_list:
        if remove_ops:
            if module.name in [
                    'RX', 'RY', 'RZ', 'RXX', 'RYY', 'RZZ', 'RZX', 'PhaseShift',
                    'CRX', 'CRY', 'CRZ', 'U1', 'CU1'
            ]:
                param = module.params[0][0].item()
                param = param % (2 * np.pi)
                param = param - 2 * np.pi if param > np.pi else param
                if abs(param) < remove_ops_thres:
                    n_removed_ops += 1
                    continue

            elif module.name in ['U2', 'U3', 'CU3']:
                param = module.params[0].data.cpu().numpy()
                param = param % (2 * np.pi)
                param[param > np.pi] -= 2 * np.pi
                if all(abs(param) < remove_ops_thres):
                    n_removed_ops += 1
                    continue

        if module.name == 'Hadamard':
            circ.h(*module.wires)
        elif module.name == 'SHadamard':
            circ.ry(np.pi / 4, *module.wires)
        elif module.name == 'PauliX':
            circ.x(*module.wires)
        elif module.name == 'PauliY':
            circ.y(*module.wires)
        elif module.name == 'PauliZ':
            circ.z(*module.wires)
        elif module.name == 'S':
            circ.s(*module.wires)
        elif module.name == 'T':
            circ.t(*module.wires)
        elif module.name == 'SX':
            circ.sx(*module.wires)
        elif module.name == 'CNOT':
            circ.cnot(*module.wires)
        elif module.name == 'CZ':
            circ.cz(*module.wires)
        elif module.name == 'CY':
            circ.cy(*module.wires)
        elif module.name == 'RX':
            circ.rx(module.params[0][0].item(), *module.wires)
        elif module.name == 'RY':
            circ.ry(module.params[0][0].item(), *module.wires)
        elif module.name == 'RZ':
            circ.rz(module.params[0][0].item(), *module.wires)
        elif module.name == 'RXX':
            circ.rxx(module.params[0][0].item(), *module.wires)
        elif module.name == 'RYY':
            circ.ryy(module.params[0][0].item(), *module.wires)
        elif module.name == 'RZZ':
            circ.rzz(module.params[0][0].item(), *module.wires)
        elif module.name == 'RZX':
            circ.rzx(module.params[0][0].item(), *module.wires)
        elif module.name == 'SWAP':
            circ.swap(*module.wires)
        elif module.name == 'SSWAP':
            # square root of swap
            from torchquantum.plugins.qiskit_unitary_gate import UnitaryGate
            mat = module.matrix.data.cpu().numpy()
            mat = switch_little_big_endian_matrix(mat)
            circ.append(UnitaryGate(mat), module.wires, [])
        elif module.name == 'CSWAP':
            circ.cswap(*module.wires)
        elif module.name == 'Toffoli':
            circ.ccx(*module.wires)
        elif module.name == 'PhaseShift':
            circ.p(module.params[0][0].item(), *module.wires)
        elif module.name == 'CRX':
            circ.crx(module.params[0][0].item(), *module.wires)
        elif module.name == 'CRY':
            circ.cry(module.params[0][0].item(), *module.wires)
        elif module.name == 'CRZ':
            circ.crz(module.params[0][0].item(), *module.wires)
        elif module.name == 'U1':
            circ.u1(module.params[0][0].item(), *module.wires)
        elif module.name == 'CU1':
            circ.cu1(module.params[0][0].item(), *module.wires)
        elif module.name == 'U2':
            circ.u2(*list(module.params[0].data.cpu().numpy()), *module.wires)
        elif module.name == 'U3':
            circ.u3(*list(module.params[0].data.cpu().numpy()), *module.wires)
        elif module.name == 'CU3':
            circ.cu3(*list(module.params[0].data.cpu().numpy()), *module.wires)
        elif module.name == 'QubitUnitary' or \
                module.name == 'QubitUnitaryFast' or \
                module.name == 'TrainableUnitary' or \
                module.name == 'TrainableUnitaryStrict':
            from torchquantum.plugins.qiskit_unitary_gate import UnitaryGate
            mat = module.params[0].data.cpu().numpy()
            mat = switch_little_big_endian_matrix(mat)
            circ.append(UnitaryGate(mat), module.wires, [])
        elif module.name == 'MultiCNOT':
            circ.mcx(module.wires[:-1], module.wires[-1])
        elif module.name == 'MultiXCNOT':
            controls = module.wires[:-1]
            target = module.wires[-1]
            num_ctrl_qubits = len(controls)

            gate = qiskit_gate.MCXGrayCode(num_ctrl_qubits,
                                           ctrl_state='0' * num_ctrl_qubits)
            circ.append(gate, controls + [target], [])
        else:
            logger.exception(f"{module.name} cannot be converted to Qiskit.")
            raise NotImplementedError(module.name)

        if module.inverse:
            data = list(circ.data[-1])
            del circ.data[-1]
            circ.data.append(tuple([data[0].inverse()] + data[1:]))
    if draw:
        import matplotlib.pyplot as plt
        circ.draw()
        plt.show()

    if n_removed_ops > 0:
        logger.warning(f"Remove {n_removed_ops} operations with small "
                       f"parameter magnitude.")

    return circ
예제 #20
0
def main() -> None:
    torch.backends.cudnn.benchmark = True

    parser = argparse.ArgumentParser()
    parser.add_argument('config', metavar='FILE', help='config file')
    parser.add_argument('--run-dir', metavar='DIR', help='run directory')
    parser.add_argument('--pdb', action='store_true', help='pdb')
    parser.add_argument('--verbose', action='store_true', help='verbose')
    parser.add_argument('--gpu', type=str, help='gpu ids', default=None)
    parser.add_argument('--print-configs',
                        action='store_true',
                        help='print ALL configs')
    parser.add_argument('--jobs',
                        type=int,
                        default=None,
                        help='max parallel job on qiskit')
    parser.add_argument('--hub', type=str, default=None, help='IBMQ provider')

    args, opts = parser.parse_known_args()

    configs.load(os.path.join(args.run_dir, 'metainfo', 'configs.yaml'))
    configs.load(args.config, recursive=True)
    configs.update(opts)

    # for eval, always need load weights
    configs.ckpt.weight_from_scratch = False

    if configs.debug.pdb or args.pdb:
        pdb.set_trace()

    configs.verbose = args.verbose
    configs.qiskit.hub = args.hub

    if args.gpu is not None:
        os.environ['CUDA_VISIBLE_DEVICES'] = args.gpu

    if args.jobs is not None:
        configs.qiskit.max_jobs = args.jobs

    if configs.run.device == 'gpu':
        device = torch.device('cuda')
    elif configs.run.device == 'cpu':
        device = torch.device('cpu')
    else:
        raise ValueError(configs.run.device)

    if args.print_configs:
        print_conf = configs
    else:
        print_conf = get_cared_configs(configs, 'eval')

    logger.info(f'Evaluation started: "{args.run_dir}".' + '\n' +
                f'{print_conf}')

    eval_config_dir = args.config.replace('/', '.').replace(
        'examples.', '').replace('.yml', '').replace('configs.', '')
    configs.eval_config_dir = eval_config_dir
    configs.run_dir = args.run_dir

    # if configs.qiskit.use_qiskit:
    #     IBMQ.load_account()
    #     if configs.run.bsz == 'qiskit_max':
    #         configs.run.bsz = IBMQ.get_provider(hub='ibm-q').get_backend(
    #             configs.qiskit.backend_name).configuration().max_experiments

    dataset = builder.make_dataset()
    sampler = torch.utils.data.SequentialSampler(
        dataset[configs.dataset.split])
    dataflow = torch.utils.data.DataLoader(
        dataset[configs.dataset.split],
        sampler=sampler,
        batch_size=configs.run.bsz,
        num_workers=configs.run.workers_per_gpu,
        pin_memory=True)

    state_dict = io.load(os.path.join(args.run_dir, configs.ckpt.name),
                         map_location='cpu')
    model_load = state_dict['model_arch']
    model = builder.make_model()
    for module_load, module in zip(model_load.modules(), model.modules()):
        if isinstance(module, tq.RandomLayer):
            # random layer, need to restore the architecture
            module.rebuild_random_layer_from_op_list(
                n_ops_in=module_load.n_ops,
                wires_in=module_load.wires,
                op_list_in=module_load.op_list,
            )

    model.load_state_dict(state_dict['model'], strict=False)

    solution = None
    if 'solution' in state_dict.keys():
        solution = state_dict['solution']
        logger.info(f"Evaluate the solution {solution}")
        logger.info(f"Original score: {state_dict['score']}")
        model.set_sample_arch(solution['arch'])

    if 'v_c_reg_mapping' in state_dict.keys():
        if getattr(model, 'q_layer', None) is not None:
            try:
                model.measure.set_v_c_reg_mapping(
                    state_dict['v_c_reg_mapping'])
            except AttributeError:
                logger.warning(f"Cannot set v_c_reg_mapping.")
        elif getattr(model, 'nodes', None) is not None:
            for k, node in enumerate(model.nodes):
                node.measure.set_v_c_reg_mapping(
                    state_dict['v_c_reg_mapping'][k])

    if state_dict.get('q_layer_op_list', None) is not None and not \
            configs.model.load_op_list:
        logger.warning(f"the model has op_list but is not loaded!!")

    if configs.model.load_op_list:
        assert state_dict['q_layer_op_list'] is not None
        logger.warning(f"Loading the op_list, will replace the q_layer in "
                       f"the original model!")
        if getattr(model, 'q_layer', None) is not None:
            q_layer = build_module_from_op_list(
                op_list=state_dict['q_layer_op_list'],
                remove_ops=configs.prune.eval.remove_ops,
                thres=configs.prune.eval.remove_ops_thres)
            model.q_layer = q_layer
        elif getattr(model, 'nodes', None) is not None:
            for k, node in enumerate(model.nodes):
                q_layer = build_module_from_op_list(
                    op_list=state_dict['q_layer_op_list'][k],
                    remove_ops=configs.prune.eval.remove_ops,
                    thres=configs.prune.eval.remove_ops_thres)
                node.q_layer = q_layer

    if state_dict.get('noise_model_tq', None) is not None:
        # the readout error is ALSO applied for eval and test so need load
        # noise_model_tq
        if getattr(model, 'q_layer', None) is not None:
            model.set_noise_model_tq(state_dict['noise_model_tq'])
            if getattr(configs, 'add_noise', False):
                model.noise_model_tq.mode = 'train'
                model.noise_model_tq.noise_total_prob = \
                    configs.noise_total_prob
            else:
                model.noise_model_tq.mode = 'test'
        elif getattr(model, 'nodes', None) is not None:
            for k, node in enumerate(model.nodes):
                node.set_noise_model_tq(state_dict['noise_model_tq'][k])
                if getattr(configs, 'add_noise', False):
                    node.noise_model_tq.mode = 'train'
                    node.noise_model_tq.noise_total_prob = \
                        configs.noise_total_prob
                else:
                    node.noise_model_tq.mode = 'test'

    if configs.model.transpile_before_run:
        # transpile the q_layer
        logger.warning(f"Transpile the q_layer to basis gate set before "
                       f"evaluation, will replace the q_layer!")
        processor = builder.make_qiskit_processor()

        circ = tq2qiskit(model.q_device, model.q_layer)
        """
        add measure because the transpile process may permute the wires, 
        so we need to get the final q reg to c reg mapping 
        """
        circ.measure(list(range(model.q_device.n_wires)),
                     list(range(model.q_device.n_wires)))

        if solution is not None:
            processor.set_layout(solution['layout'])
            logger.warning(f"Set layout {solution['layout']} for transpile!")

        logger.info("Transpiling circuit...")
        circ_transpiled = processor.transpile(circs=circ)
        q_layer = qiskit2tq(circ=circ_transpiled)

        model.measure.set_v_c_reg_mapping(get_v_c_reg_mapping(circ_transpiled))
        model.q_layer = q_layer

    if configs.legalization.legalize:
        legalize_unitary(model)

    if configs.act_quant.add_in_eval:
        quantizers = []
        assert getattr(model, 'nodes', None) is not None
        if getattr(configs.act_quant, 'act_quant_bit', None) is not None:
            # settings from config file has higher priority
            act_quant_bit = configs.act_quant.act_quant_bit
            act_quant_ratio = configs.act_quant.act_quant_ratio
            act_quant_level = configs.act_quant.act_quant_level
            act_quant_lower_bound = configs.act_quant.act_quant_lower_bound
            act_quant_upper_bound = configs.act_quant.act_quant_upper_bound
            logger.warning(f"Get act_quant setting from config file!")
        elif state_dict.get('act_quant', None) is not None:
            act_quant_bit = state_dict['act_quant']['act_quant_bit']
            act_quant_ratio = state_dict['act_quant']['act_quant_ratio']
            act_quant_level = state_dict['act_quant']['act_quant_level']
            act_quant_lower_bound = state_dict['act_quant'][
                'act_quant_lower_bound']
            act_quant_upper_bound = state_dict['act_quant'][
                'act_quant_upper_bound']
            logger.warning(f"Get act_quant setting from ckpt file!")
        elif getattr(configs.trainer, 'act_quant_bit', None) is not None:
            # if the act_quant info is not stored in ckpt, use the info from
            # training config file
            act_quant_bit = configs.trainer.act_quant_bit
            act_quant_ratio = configs.trainer.act_quant_ratio
            act_quant_level = configs.trainer.act_quant_level
            act_quant_lower_bound = configs.trainer.act_quant_lower_bound
            act_quant_upper_bound = configs.trainer.act_quant_upper_bound
            logger.warning(f"Get act_quant setting from previous training "
                           f"config file!")
        else:
            raise NotImplementedError('No act_quant info specified!')

        logger.warning(f"act_quant_bit={act_quant_bit}, "
                       f"act_quant_ratio={act_quant_ratio}, "
                       f"act_quant_level={act_quant_level}, "
                       f"act_quant_lower_bound={act_quant_lower_bound}, "
                       f"act_quant_upper_bound={act_quant_upper_bound}")

        for k, node in enumerate(model.nodes):
            if configs.trainer.act_quant_skip_last_node and k == len(
                    model.nodes) - 1:
                continue
            quantizer = PACTActivationQuantizer(
                module=node,
                precision=act_quant_bit,
                level=act_quant_level,
                alpha=1.0,
                backprop_alpha=False,
                quant_ratio=act_quant_ratio,
                device=device,
                lower_bound=act_quant_lower_bound,
                upper_bound=act_quant_upper_bound,
            )
            quantizers.append(quantizer)

        for quantizer in quantizers:
            quantizer.register_hook()

    if getattr(configs, 'pre_specified_mean', None) is not None and \
            configs.pre_specified_std \
            is not None:
        for k, node in enumerate(model.nodes):
            node.pre_specified_mean_std = {
                'mean': configs.pre_specified_mean[k],
                'std': configs.pre_specified_std[k],
            }

    model.to(device)
    model.eval()

    if configs.qiskit.use_qiskit:
        qiskit_processor = builder.make_qiskit_processor()
        if configs.qiskit.initial_layout is not None:
            layout = configs.qiskit.initial_layout
            logger.warning(f"Use layout {layout} from config file")
        elif 'solution' in state_dict.keys():
            layout = state_dict['solution']['layout']
            logger.warning(f"Use layout {layout} from checkpoint file")
        else:
            layout = None
            logger.warning(f"No specified layout")
        qiskit_processor.set_layout(layout)
        model.set_qiskit_processor(qiskit_processor)

    if getattr(configs.model.arch, 'sample_arch', None) is not None:
        sample_arch = configs.model.arch.sample_arch
        logger.warning(f"Setting sample arch {sample_arch} from config file!")
        if isinstance(sample_arch, str):
            # this is the name of arch
            sample_arch = get_named_sample_arch(model.arch_space, sample_arch)
            logger.warning(f"Decoded sample arch: {sample_arch}")
        model.set_sample_arch(sample_arch)

    if configs.get_n_params:
        n_params = model.count_sample_params()
        logger.info(f"Number of sampled params: {n_params}")
        exit(0)

    if configs.qiskit.est_success_rate:
        circ_parameterized, params = tq2qiskit_parameterized(
            model.q_device, model.encoder.func_list)
        circ_fixed = tq2qiskit(model.q_device, model.q_layer)
        circ = circ_parameterized + circ_fixed
        transpiled_circ = model.qiskit_processor.transpile(circ)

        success_rate = get_success_rate(model.qiskit_processor.properties,
                                        transpiled_circ)
        logger.info(f"Success rate: {success_rate}")
        logger.info(f"Size: {transpiled_circ.size()}")
        logger.info(f"Depth: {transpiled_circ.depth()}")
        logger.info(f"Width: {transpiled_circ.width()}")
        exit(0)

    total_params = sum(p.numel() for p in model.parameters())
    logger.info(f'Model Size: {total_params}')

    if hasattr(model, 'sample_arch') and not configs.model.load_op_list:
        n_params = model.count_sample_params()
        logger.info(f"Number of sampled params: {n_params}")

    with torch.no_grad():
        target_all = None
        output_all = None
        for feed_dict in tqdm.tqdm(dataflow):
            if configs.run.device == 'gpu':
                inputs = feed_dict[configs.dataset.input_name].cuda(
                    non_blocking=True)
                targets = feed_dict[configs.dataset.target_name].cuda(
                    non_blocking=True)
            else:
                inputs = feed_dict[configs.dataset.input_name]
                targets = feed_dict[configs.dataset.target_name]

            outputs = model(inputs,
                            verbose=configs.verbose,
                            use_qiskit=configs.qiskit.use_qiskit)

            if target_all is None:
                target_all = targets
                output_all = outputs
            else:
                target_all = torch.cat([target_all, targets], dim=0)
                output_all = torch.cat([output_all, outputs], dim=0)
            # if configs.verbose:
            #     logger.info(f"Measured log_softmax: {outputs}")
            if not configs.dataset.name == 'vqe':
                log_acc(output_all, target_all)

    logger.info("Final:")
    if not configs.dataset.name == 'vqe':
        log_acc(output_all, target_all)
    else:
        logger.info(f"Eigenvalue: {output_all.detach().cpu().numpy()}")
예제 #21
0
def main() -> None:
    # dist.init()
    torch.backends.cudnn.benchmark = True
    # torch.cuda.set_device(dist.local_rank())

    parser = argparse.ArgumentParser()
    parser.add_argument('config', metavar='FILE', help='config file')
    parser.add_argument('--ckpt-dir', metavar='DIR', help='run directory')
    parser.add_argument('--pdb', action='store_true', help='pdb')
    parser.add_argument('--gpu', type=str, help='gpu ids', default=None)
    parser.add_argument('--print-configs',
                        action='store_true',
                        help='print ALL configs')
    args, opts = parser.parse_known_args()

    configs.load(args.config, recursive=True)
    configs.update(opts)

    if configs.debug.pdb or args.pdb:
        pdb.set_trace()

    if args.gpu is not None:
        os.environ['CUDA_VISIBLE_DEVICES'] = args.gpu

    if configs.debug.set_seed:
        torch.manual_seed(configs.debug.seed)
        np.random.seed(configs.debug.seed)

    if configs.run.device == 'gpu':
        device = torch.device('cuda')
    elif configs.run.device == 'cpu':
        device = torch.device('cpu')
    else:
        raise ValueError(configs.run.device)

    if isinstance(configs.optimizer.lr, str):
        configs.optimizer.lr = eval(configs.optimizer.lr)

    # set the run dir according to config file's name
    args.run_dir = 'runs/' + args.config.replace('/', '.').replace(
        'examples.', '').replace('.yml', '').replace('configs.', '')
    set_run_dir(args.run_dir)

    logger.info(' '.join([sys.executable] + sys.argv))

    if args.print_configs:
        print_conf = configs
    else:
        print_conf = get_cared_configs(configs, 'train')

    logger.info(f'Training started: "{args.run_dir}".' + '\n' +
                f'{print_conf}')

    dataset = builder.make_dataset()
    dataflow = dict()

    # for split in dataset:
    #     sampler = torch.utils.data.distributed.DistributedSampler(
    #         dataset[split],
    #         num_replicas=dist.size(),
    #         rank=dist.rank(),
    #         shuffle=(split == 'train'))
    #     dataflow[split] = torch.utils.data.DataLoader(
    #         dataset[split],
    #         batch_size=configs.run.bsz // dist.size(),
    #         sampler=sampler,
    #         num_workers=configs.run.workers_per_gpu,
    #         pin_memory=True)

    for split in dataset:
        if split == 'train':
            sampler = torch.utils.data.RandomSampler(dataset[split])
            batch_size = configs.run.bsz
        else:
            # for valid and test, use SequentialSampler to make the train.py
            # and eval.py results consistent
            sampler = torch.utils.data.SequentialSampler(dataset[split])
            batch_size = getattr(configs.run, 'eval_bsz', configs.run.bsz)

        dataflow[split] = torch.utils.data.DataLoader(
            dataset[split],
            batch_size=batch_size,
            sampler=sampler,
            num_workers=configs.run.workers_per_gpu,
            pin_memory=True)

    model = builder.make_model()

    state_dict = {}
    solution = None
    score = None
    if configs.ckpt.load_ckpt:
        logger.warning('Loading checkpoint!')
        state_dict = io.load(os.path.join(args.ckpt_dir, configs.ckpt.name),
                             map_location='cpu')
        if getattr(state_dict, 'model_arch', None) is not None:
            model_load = state_dict['model_arch']
            for module_load, module in zip(model_load.modules(),
                                           model.modules()):
                if isinstance(module, tq.RandomLayer):
                    # random layer, need to restore the architecture
                    module.rebuild_random_layer_from_op_list(
                        n_ops_in=module_load.n_ops,
                        wires_in=module_load.wires,
                        op_list_in=module_load.op_list,
                    )

        if not configs.ckpt.weight_from_scratch:
            model.load_state_dict(state_dict['model'], strict=False)
        else:
            logger.warning(f"DO NOT load weight, train weights from scratch!")

        if 'solution' in state_dict.keys():
            solution = state_dict['solution']
            logger.info(f"Loading the solution {solution}")
            logger.info(f"Original score: {state_dict['score']}")
            model.set_sample_arch(solution['arch'])
            score = state_dict['score']

        if 'v_c_reg_mapping' in state_dict.keys():
            try:
                model.measure.set_v_c_reg_mapping(
                    state_dict['v_c_reg_mapping'])
            except AttributeError:
                logger.warning(f"Cannot set v_c_reg_mapping.")

        if configs.model.load_op_list:
            assert state_dict['q_layer_op_list'] is not None
            logger.warning(f"Loading the op_list, will replace the q_layer in "
                           f"the original model!")
            q_layer = build_module_from_op_list(state_dict['q_layer_op_list'])
            model.q_layer = q_layer

    if configs.model.transpile_before_run:
        # transpile the q_layer
        logger.warning(f"Transpile the q_layer to basis gate set before "
                       f"training, will replace the q_layer!")
        processor = builder.make_qiskit_processor()

        if getattr(model, 'q_layer', None) is not None:
            circ = tq2qiskit(model.q_device, model.q_layer)
            """
            add measure because the transpile process may permute the wires, 
            so we need to get the final q reg to c reg mapping 
            """
            circ.measure(list(range(model.q_device.n_wires)),
                         list(range(model.q_device.n_wires)))
            logger.info("Transpiling circuit...")

            if solution is not None:
                processor.set_layout(solution['layout'])
                logger.warning(
                    f"Set layout {solution['layout']} for transpile!")

            circ_transpiled = processor.transpile(circs=circ)
            q_layer = qiskit2tq(circ=circ_transpiled)

            model.measure.set_v_c_reg_mapping(
                get_v_c_reg_mapping(circ_transpiled))
            model.q_layer = q_layer

            if configs.trainer.add_noise:
                # noise-aware training
                noise_model_tq = builder.make_noise_model_tq()
                noise_model_tq.is_add_noise = True
                noise_model_tq.v_c_reg_mapping = get_v_c_reg_mapping(
                    circ_transpiled)
                noise_model_tq.p_c_reg_mapping = get_p_c_reg_mapping(
                    circ_transpiled)
                noise_model_tq.p_v_reg_mapping = get_p_v_reg_mapping(
                    circ_transpiled)
                model.set_noise_model_tq(noise_model_tq)

        elif getattr(model, 'nodes', None) is not None:
            # every node has a noise model because it is possible that
            # different nodes run on different QC
            for node in model.nodes:
                circ = tq2qiskit(node.q_device, node.q_layer)
                circ.measure(list(range(node.q_device.n_wires)),
                             list(range(node.q_device.n_wires)))
                circ_transpiled = processor.transpile(circs=circ)
                q_layer = qiskit2tq(circ=circ_transpiled)

                node.measure.set_v_c_reg_mapping(
                    get_v_c_reg_mapping(circ_transpiled))
                node.q_layer = q_layer

                if configs.trainer.add_noise:
                    # noise-aware training
                    noise_model_tq = builder.make_noise_model_tq()
                    noise_model_tq.is_add_noise = True
                    noise_model_tq.v_c_reg_mapping = get_v_c_reg_mapping(
                        circ_transpiled)
                    noise_model_tq.p_c_reg_mapping = get_p_c_reg_mapping(
                        circ_transpiled)
                    noise_model_tq.p_v_reg_mapping = get_p_v_reg_mapping(
                        circ_transpiled)
                    node.set_noise_model_tq(noise_model_tq)

    if getattr(configs.model.arch, 'sample_arch', None) is not None and \
            not configs.model.transpile_before_run:
        sample_arch = configs.model.arch.sample_arch
        logger.warning(f"Setting sample arch {sample_arch} from config file!")
        if isinstance(sample_arch, str):
            # this is the name of arch
            sample_arch = get_named_sample_arch(model.arch_space, sample_arch)
            logger.warning(f"Decoded sample arch: {sample_arch}")
        model.set_sample_arch(sample_arch)

    if configs.trainer.name == 'pruning_trainer':
        """
        in pruning, convert the super layers to module list, otherwise the 
        pruning ratio is difficulty to set
        """
        logger.warning(f"Convert sampled layer to module list layer!")
        model.q_layer = build_module_from_op_list(
            build_module_op_list(model.q_layer))

    model.to(device)
    # model = torch.nn.parallel.DistributedDataParallel(
    #     model.cuda(),
    #     device_ids=[dist.local_rank()],
    #     find_unused_parameters=True)
    if getattr(model, 'sample_arch', None) is not None and \
            not configs.model.transpile_before_run and \
            not configs.trainer.name == 'pruning_trainer':
        n_params = model.count_sample_params()
        logger.info(f"Number of sampled params: {n_params}")

    total_params = sum(p.numel() for p in model.parameters())
    logger.info(f'Model Size: {total_params}')

    # logger.info(f'Model MACs: {profile_macs(model, inputs)}')

    criterion = builder.make_criterion()
    optimizer = builder.make_optimizer(model)
    scheduler = builder.make_scheduler(optimizer)
    trainer = builder.make_trainer(model=model,
                                   criterion=criterion,
                                   optimizer=optimizer,
                                   scheduler=scheduler)
    trainer.solution = solution
    trainer.score = score

    # trainer state_dict will be loaded in a callback
    callbacks = builder.make_callbacks(dataflow, state_dict)

    trainer.train_with_defaults(dataflow['train'],
                                num_epochs=configs.run.n_epochs,
                                callbacks=callbacks)
예제 #22
0
    def load(self):
        if self.grayscale:
            tran = [
                transforms.ToTensor(),
                transforms.Grayscale(num_output_channels=1),
                transforms.Normalize(
                    (0.2989 * 0.4914 + 0.587 * 0.4822 + 0.114 * 0.4465, ),
                    (((0.2989 * 0.2023)**2 + (0.587 * 0.1994)**2 +
                      (0.114 * 0.2010)**2)**0.5, ))
            ]
        else:
            tran = [
                transforms.ToTensor(),
                transforms.Normalize((0.4914, 0.4822, 0.4465),
                                     (0.2023, 0.1994, 0.2010))
            ]

        if not self.center_crop == 32:
            tran.append(transforms.CenterCrop(self.center_crop))
        if not self.resize == 32:
            tran.append(
                transforms.Resize(self.resize, interpolation=self.resize_mode))
        transform = transforms.Compose(tran)

        if self.split == 'train' or self.split == 'valid':
            train_valid = datasets.CIFAR10(self.root,
                                           train=True,
                                           download=True,
                                           transform=transform)
            targets = torch.tensor(train_valid.targets)
            idx, _ = torch.stack([
                targets == number for number in self.digits_of_interest
            ]).max(dim=0)
            # targets = targets[idx]
            train_valid.targets = targets[idx].numpy().tolist()
            train_valid.data = train_valid.data[idx]

            train_len = int(self.train_valid_split_ratio[0] * len(train_valid))
            split = [train_len, len(train_valid) - train_len]
            train_subset, valid_subset = torch.utils.data.random_split(
                train_valid, split, generator=torch.Generator().manual_seed(1))
            if self.split == 'train':
                self.data = train_subset
            else:
                if self.n_valid_samples is None:
                    # use all samples in valid set
                    self.data = valid_subset
                else:
                    # use a subset of valid set, useful to speedup evo search
                    valid_subset.indices = valid_subset.indices[:self.
                                                                n_valid_samples]
                    self.data = valid_subset
                    logger.warning(f"Only use the front "
                                   f"{self.n_valid_samples} images as "
                                   f"VALID set.")

        else:
            test = datasets.CIFAR10(self.root,
                                    train=False,
                                    transform=transform)
            targets = torch.tensor(test.targets)
            idx, _ = torch.stack([
                targets == number for number in self.digits_of_interest
            ]).max(dim=0)
            test.targets = targets[idx].numpy().tolist()
            test.data = test.data[idx]
            if self.n_test_samples is None:
                # use all samples as test set
                self.data = test
            else:
                # use a subset as test set
                test.targets = test.targets[:self.n_test_samples]
                test.data = test.data[:self.n_test_samples]
                self.data = test
                logger.warning(f"Only use the front {self.n_test_samples} "
                               f"images as TEST set.")
예제 #23
0
    def sample_noise_op(self, op_in):
        if not (self.mode == 'train' and self.is_add_noise):
            return []

        op_name = op_in.name.lower()
        if op_name == 'paulix':
            op_name = 'x'
        elif op_name == 'cnot':
            op_name = 'cx'
        elif op_name in ['sx', 'id']:
            pass
        elif op_name == 'rz':
            # no noise
            return []
        else:
            logger.warning(f"No noise model for {op_name} operation!")

        wires = op_in.wires

        p_wires = [self.p_v_reg_mapping['v2p'][wire] for wire in wires]

        if tuple(p_wires) in self.parsed_dict[op_name].keys():
            inst_prob = self.parsed_dict[op_name][tuple(p_wires)]
        else:
            # not in the real coupling map, so only give a dummy one
            if len(p_wires) == 1:
                inst_prob = self.parsed_dict[op_name][(0, )]
            elif len(p_wires) == 2:
                inst_prob = self.parsed_dict[op_name][(0, 1)]

        inst = inst_prob['instructions']
        if len(inst) == 0:
            return []

        probs = inst_prob['probabilities']

        magnified_probs = self.magnify_probs(probs)

        idx = np.random.choice(list(range(len(inst) + 1)),
                               p=magnified_probs + [1 - sum(magnified_probs)])
        if idx == len(inst):
            return []

        instructions = inst[idx]

        ops = []
        for instruction in instructions:
            v_wires = [
                self.p_v_reg_mapping['p2v'][qubit]
                for qubit in instruction['qubits']
            ]
            if instruction['name'] == 'x':
                op = tq.PauliX(wires=v_wires)
            elif instruction['name'] == 'y':
                op = tq.PauliY(wires=v_wires)
            elif instruction['name'] == 'z':
                op = tq.PauliZ(wires=v_wires)
            elif instruction['name'] == 'reset':
                op = tq.Reset(wires=v_wires)
            else:
                # ignore operations specified by self.ignored_ops
                # logger.warning(f"skip noise operation {instruction['name']}")
                continue
            ops.append(op)

        return ops
예제 #24
0
    def load(self):
        tran = [transforms.ToTensor(),
                transforms.Normalize((0.1307,), (0.3081,))]
        if not self.center_crop == 28:
            tran.append(transforms.CenterCrop(self.center_crop))
        if not self.resize == 28:
            tran.append(transforms.Resize(self.resize,
                                          interpolation=self.resize_mode))
        transform = transforms.Compose(tran)

        if self.split == 'train' or self.split == 'valid':
            if self.fashion:
                train_valid = datasets.FashionMNIST(
                    self.root, train=True, download=True, transform=transform)
            else:
                train_valid = datasets.MNIST(
                    self.root, train=True, download=True, transform=transform)
            idx, _ = torch.stack([train_valid.targets == number for number in
                                  self.digits_of_interest]).max(dim=0)
            train_valid.targets = train_valid.targets[idx]
            train_valid.data = train_valid.data[idx]

            train_len = int(self.train_valid_split_ratio[0] * len(train_valid))
            split = [train_len, len(train_valid) - train_len]
            train_subset, valid_subset = torch.utils.data.random_split(
                train_valid, split, generator=torch.Generator().manual_seed(1))

            if self.split == 'train':
                self.data = train_subset
            else:
                if self.n_valid_samples is None:
                    # use all samples in valid set
                    self.data = valid_subset
                else:
                    # use a subset of valid set, useful to speedup evo search
                    valid_subset.indices = valid_subset.indices[
                                           :self.n_valid_samples]
                    self.data = valid_subset
                    logger.warning(f"Only use the front "
                                   f"{self.n_valid_samples} images as "
                                   f"VALID set.")

        else:
            if self.fashion:
                test = datasets.FashionMNIST(self.root,
                                             train=False, transform=transform)
            else:
                test = datasets.MNIST(self.root,
                                      train=False, transform=transform)
            idx, _ = torch.stack([test.targets == number for number in
                                  self.digits_of_interest]).max(dim=0)
            test.targets = test.targets[idx]
            test.data = test.data[idx]
            if self.n_test_samples is None:
                # use all samples as test set
                self.data = test
            else:
                # use a subset as test set
                test.targets = test.targets[:self.n_test_samples]
                test.data = test.data[:self.n_test_samples]
                self.data = test
                logger.warning(f"Only use the front {self.n_test_samples} "
                               f"images as TEST set.")