def preprocess_parameterized(self, q_device, q_layer_parameterized, q_layer_fixed, q_layer_measure, x, ): circ_parameterized, params = tq2qiskit_parameterized( q_device, q_layer_parameterized.func_list) circ_fixed = tq2qiskit(q_device, q_layer_fixed, remove_ops=self.remove_ops, remove_ops_thres=self.remove_ops_thres) circ = circ_parameterized + circ_fixed v_c_reg_mapping = q_layer_measure.v_c_reg_mapping if v_c_reg_mapping is not None: for q_reg, c_reg in v_c_reg_mapping['v2c'].items(): circ.measure(q_reg, c_reg) else: circ.measure(list(range(q_device.n_wires)), list(range( q_device.n_wires))) transpiled_circ = self.transpile(circ) self.transpiled_circs = [transpiled_circ] # construct the parameter_binds binds_all = [] for inputs_single in x: binds = {} for k, input_single in enumerate(inputs_single): binds[params[k]] = input_single.item() binds_all.append(binds) return transpiled_circ, binds_all
def state_tq_vs_qiskit_test(): bsz = 1 for n_wires in range(2, 10): q_dev = tq.QuantumDevice(n_wires=n_wires) q_dev.reset_states(bsz=bsz) x = torch.randn((1, 100000), dtype=F_DTYPE) q_layer = AllRandomLayer(n_wires=n_wires, wires=list(range(n_wires)), n_ops_rd=500, n_ops_cin=500, n_funcs=500, qiskit_compatible=True) q_layer(q_dev, x) state_tq = q_dev.states.reshape(bsz, -1) state_tq = switch_little_big_endian_state(state_tq.data.numpy()) # qiskit circ = tq2qiskit(q_layer, x) # Select the StatevectorSimulator from the Aer provider simulator = Aer.get_backend('statevector_simulator') # Execute and get counts result = execute(circ, simulator).result() state_qiskit = result.get_statevector(circ) stable_threshold = 1e-5 try: # WARNING: need to remove the global phase! The qiskit simulated # results sometimes has global phase shift. global_phase = find_global_phase(state_tq, np.expand_dims(state_qiskit, 0), stable_threshold) if global_phase is None: logger.exception(f"Cannot find a stable enough factor to " f"reduce the global phase, increase the " f"stable_threshold and try again") raise RuntimeError assert np.allclose(state_tq * global_phase, state_qiskit, atol=1e-6) logger.info(f"PASS tq vs qiskit [n_wires]={n_wires}") except AssertionError: logger.exception(f"FAIL tq vs qiskit [n_wires]={n_wires}") raise AssertionError except RuntimeError: raise RuntimeError logger.info(f"PASS tq vs qiskit statevector test")
def build_module_description_test(): import pdb from torchquantum.plugins import tq2qiskit pdb.set_trace() from examples.core.models.q_models import QFCModel12 q_model = QFCModel12({'n_blocks': 4}) desc = build_module_op_list(q_model.q_layer) print(desc) q_dev = tq.QuantumDevice(n_wires=4) m = build_module_from_op_list(desc) tq2qiskit(q_dev, m, draw=True) desc = build_module_op_list( tq.RandomLayerAllTypes(n_ops=200, wires=[0, 1, 2, 3], qiskit_compatible=True)) print(desc) m1 = build_module_from_op_list(desc) tq2qiskit(q_dev, m1, draw=True)
def measurement_tq_vs_qiskit_test(): bsz = 1 for n_wires in range(2, 10): q_dev = tq.QuantumDevice(n_wires=n_wires) q_dev.reset_states(bsz=bsz) x = torch.randn((1, 100000), dtype=F_DTYPE) q_layer = AllRandomLayer(n_wires=n_wires, wires=list(range(n_wires)), n_ops_rd=500, n_ops_cin=500, n_funcs=500, qiskit_compatible=True) q_layer(q_dev, x) measurer = tq.MeasureAll(obs=tq.PauliZ) # flip because qiskit is from N to 0, tq is from 0 to N measured_tq = np.flip(measurer(q_dev).data[0].numpy()) # qiskit circ = tq2qiskit(q_layer, x) circ.measure(list(range(n_wires)), list(range(n_wires))) # Select the QasmSimulator from the Aer provider simulator = Aer.get_backend('qasm_simulator') # Execute and get counts result = execute(circ, simulator, shots=1000000).result() counts = result.get_counts(circ) measured_qiskit = get_expectations_from_counts(counts, n_wires=n_wires) try: # WARNING: the measurement has randomness, so tolerate larger # differences (MAX 20%) between tq and qiskit # typical mean difference is less than 1% diff = np.abs(measured_tq - measured_qiskit).mean() diff_ratio = (np.abs( (measured_tq - measured_qiskit) / measured_qiskit)).mean() logger.info(f"Diff: tq vs qiskit {diff} \t Diff Ratio: " f"{diff_ratio}") assert np.allclose(measured_tq, measured_qiskit, atol=1e-4, rtol=2e-1) logger.info(f"PASS tq vs qiskit [n_wires]={n_wires}") except AssertionError: logger.exception(f"FAIL tq vs qiskit [n_wires]={n_wires}") raise AssertionError logger.info(f"PASS tq vs qiskit measurement test")
def unitary_tq_vs_qiskit_test(): for n_wires in range(2, 10): q_dev = tq.QuantumDevice(n_wires=n_wires) x = torch.randn((1, 100000), dtype=F_DTYPE) q_layer = AllRandomLayer(n_wires=n_wires, wires=list(range(n_wires)), n_ops_rd=500, n_ops_cin=500, n_funcs=500, qiskit_compatible=True) unitary_tq = q_layer.get_unitary(q_dev, x) unitary_tq = switch_little_big_endian_matrix(unitary_tq.data.numpy()) # qiskit circ = tq2qiskit(q_layer, x) simulator = Aer.get_backend('unitary_simulator') result = execute(circ, simulator).result() unitary_qiskit = result.get_unitary(circ) stable_threshold = 1e-5 try: # WARNING: need to remove the global phase! The qiskit simulated # results sometimes has global phase shift. global_phase = find_global_phase(unitary_tq, unitary_qiskit, stable_threshold) if global_phase is None: logger.exception(f"Cannot find a stable enough factor to " f"reduce the global phase, increase the " f"stable_threshold and try again") raise RuntimeError assert np.allclose(unitary_tq * global_phase, unitary_qiskit, atol=1e-6) logger.info(f"PASS tq vs qiskit [n_wires]={n_wires}") except AssertionError: logger.exception(f"FAIL tq vs qiskit [n_wires]={n_wires}") raise AssertionError except RuntimeError: raise RuntimeError logger.info(f"PASS tq vs qiskit unitary test")
def process(self, q_device: tq.QuantumDevice, q_layer: tq.QuantumModule, q_layer_measure: tq.QuantumModule, x): circs = [] for i, x_single in tqdm(enumerate(x)): circ = tq2qiskit(q_device, q_layer, x_single.unsqueeze(0)) if q_layer_measure.v_c_reg_mapping is not None: for q_reg, c_reg in q_layer_measure.v_c_reg_mapping[ 'v2c'].items(): circ.measure(q_reg, c_reg) else: circ.measure(list(range(q_device.n_wires)), list(range( q_device.n_wires))) circs.append(circ) transpiled_circs = self.transpile(circs) self.transpiled_circs = transpiled_circs job = execute(experiments=transpiled_circs, backend=self.backend, shots=self.n_shots, # initial_layout=self.initial_layout, seed_transpiler=self.seed_transpiler, seed_simulator=self.seed_simulator, coupling_map=self.coupling_map, basis_gates=self.basis_gates, noise_model=self.noise_model, optimization_level=self.optimization_level, ) job_monitor(job, interval=1) result = job.result() counts = result.get_counts() measured_qiskit = get_expectations_from_counts( counts, n_wires=q_device.n_wires) measured_qiskit = torch.tensor(measured_qiskit, device=x.device) return measured_qiskit
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)
def evaluate_all(self, model, dataflow, solutions, writer=None, iter_n=None, population_size=None): scores = [] best_solution = None best_solution_accuracy = 0 best_solution_loss = 0 best_solution_success_rate = 0 best_solution_score = 999999 for i, solution in tqdm.tqdm(enumerate(solutions)): fingerprint = solution.copy() arch = solution['arch'] fingerprint['arch'] = arch[:arch[-1] * configs.model.arch.n_layers_per_block] fingerprint['arch'].append(arch[-1]) fingerprint = str(fingerprint) if fingerprint in self.solution_lib.keys(): """circuit has been simulated before""" logger.info(f"loaded from lib") loss = self.solution_lib[fingerprint]['loss'] accuracy = self.solution_lib[fingerprint]['accuracy'] success_rate = self.solution_lib[fingerprint]['success_rate'] else: if model.qiskit_processor is not None: model.qiskit_processor.set_layout(solution['layout']) model.set_sample_arch(solution['arch']) with torch.no_grad(): target_all = None output_all = None for feed_dict in 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, 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.dataset.name == 'vqe': loss = output_all[0].item() accuracy = -1 else: k = 1 _, indices = output_all.topk(k, dim=1) masks = indices.eq( target_all.view(-1, 1).expand_as(indices)) size = target_all.shape[0] corrects = masks.sum().item() accuracy = corrects / size loss = F.nll_loss(output_all, target_all).item() if configs.es.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) else: success_rate = 1 self.solution_lib[fingerprint] = { 'loss': loss, 'accuracy': accuracy, 'success_rate': success_rate, } if configs.es.score_mode == 'loss_succ': score = loss / success_rate elif configs.es.score_mode == 'acc_succ': score = -accuracy * success_rate else: raise NotImplementedError scores.append(score) logger.info(f"Current solution: {solution}\n" f"Accuracy: {accuracy:.5f}, Loss: {loss:.5f}, " f"Success Rate: {success_rate: .5f}, " f"Score: {score:.5f}") if score < best_solution_score: best_solution = solution best_solution_accuracy = accuracy best_solution_success_rate = success_rate best_solution_loss = loss best_solution_score = score logger.info(f"Best of iteration: " f"Solution: {best_solution}\n" f"Accuracy: {best_solution_accuracy:.5f}, " f"Loss: {best_solution_loss:.5f}, " f"Success Rate: {best_solution_success_rate: .5f}, " f"Score: {best_solution_score:.5f}") if population_size is not None and writer is not None and \ population_size is not None: writer.add_scalar('es/accuracy', accuracy, iter_n * population_size + i) writer.add_scalar('es/loss', loss, iter_n * population_size + i) writer.add_scalar('es/success_rate', success_rate, iter_n * population_size + i) writer.add_scalar('es/score', score, iter_n * population_size + i) return scores, best_solution_accuracy, best_solution_loss, \ best_solution_success_rate, best_solution_score
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()}")
def process_multi_measure(self, q_device: tq.QuantumDevice, q_layer: tq.QuantumModule, q_layer_measure: tq.QuantumModule,): obs_list = q_layer_measure.obs_list v_c_reg_mapping = q_layer_measure.v_c_reg_mapping circ_fixed = tq2qiskit(q_device, q_layer, remove_ops=self.remove_ops, remove_ops_thres=self.remove_ops_thres) transpiled_circ_fixed = self.transpile(circ_fixed) circ_all = [] for hamil in obs_list: circ_diagonalize = QuantumCircuit(q_device.n_wires, q_device.n_wires) # diagonalize the measurements for wire, observable in zip(hamil['wires'], hamil['observables']): if observable == 'x': circ_diagonalize.h(qubit=wire) elif observable == 'y': circ_diagonalize.z(qubit=wire) circ_diagonalize.s(qubit=wire) circ_diagonalize.h(qubit=wire) if v_c_reg_mapping is not None: for q_reg, c_reg in v_c_reg_mapping['v2c'].items(): circ_diagonalize.measure(q_reg, c_reg) else: circ_diagonalize.measure(list(range(q_device.n_wires)), list(range(q_device.n_wires))) transpiled_circ_diagonalize = self.transpile(circ_diagonalize) circ_all.append(transpiled_circ_fixed + transpiled_circ_diagonalize) self.transpiled_circs = circ_all if hasattr(self.backend.configuration(), 'max_experiments'): chunk_size = self.backend.configuration().max_experiments else: # using simulator, apply multithreading chunk_size = len(circ_all) // self.max_jobs split_circs = [circ_all[i:i + chunk_size] for i in range( 0, len(circ_all), chunk_size)] qiskit_verbose = self.max_jobs <= 2 feed_dicts = [] for split_circ in split_circs: feed_dict = { 'experiments': split_circ, 'backend': self.backend, 'pass_manager': self.empty_pass_manager, 'shots': self.n_shots, 'seed_simulator': self.seed_simulator, 'noise_model': self.noise_model, } feed_dicts.append([feed_dict, qiskit_verbose]) p = multiprocessing.Pool(self.max_jobs) results = p.map(run_job_worker, feed_dicts) p.close() if all(isinstance(result, dict) for result in results): counts = results else: if isinstance(results[-1], dict): results[-1] = [results[-1]] counts = list(itertools.chain(*results)) measured_qiskit = get_expectations_from_counts( counts, n_wires=q_device.n_wires) measured_qiskit = torch.tensor(measured_qiskit, device=q_device.state.device) return measured_qiskit