def test_composite_tags(self): """ Test the tags setter, add_tags_recursive, remove_tags_recursive """ exp1 = FakeExperiment([0, 2]) exp2 = FakeExperiment([1, 3]) par_exp = BatchExperiment([exp1, exp2]) expdata = par_exp.run(FakeBackend()).block_for_results() data1 = expdata.child_data(0) data2 = expdata.child_data(1) expdata.tags = ["a", "c", "a"] data1.tags = ["b"] self.assertEqual(sorted(expdata.tags), ["a", "c"]) self.assertEqual(sorted(data1.tags), ["b"]) self.assertEqual(sorted(data2.tags), []) expdata.add_tags_recursive(["d", "c"]) self.assertEqual(sorted(expdata.tags), ["a", "c", "d"]) self.assertEqual(sorted(data1.tags), ["b", "c", "d"]) self.assertEqual(sorted(data2.tags), ["c", "d"]) expdata.remove_tags_recursive(["a", "b"]) self.assertEqual(sorted(expdata.tags), ["c", "d"]) self.assertEqual(sorted(data1.tags), ["c", "d"]) self.assertEqual(sorted(data2.tags), ["c", "d"])
def setUp(self): super().setUp() exp1 = self.SimpleExperiment(range(4)) exp2 = self.SimpleExperiment(range(4)) exp3 = self.SimpleExperiment(range(4)) batch1 = BatchExperiment([exp2, exp3]) self.batch2 = BatchExperiment([exp1, batch1]) exp1.set_transpile_options(coupling_map=[[0, 1], [1, 3], [3, 2]]) exp2.set_transpile_options(coupling_map=[[0, 1], [1, 2], [2, 3]])
def test_experiment_config(self): """Test converting to and from config works""" exp1 = FakeExperiment([0]) exp1.set_run_options(shots=1000) exp2 = FakeExperiment([2]) exp2.set_run_options(shots=2000) exp = BatchExperiment([exp1, exp2]) loaded_exp = BatchExperiment.from_config(exp.config()) self.assertNotEqual(exp, loaded_exp) self.assertTrue(self.json_equiv(exp, loaded_exp))
def test_nested_composite(self): """ Test nested parallel experiments. """ exp1 = FakeExperiment([0, 2]) exp2 = FakeExperiment([1, 3]) exp3 = ParallelExperiment([exp1, exp2]) exp4 = BatchExperiment([exp3, exp1]) exp5 = ParallelExperiment([exp4, FakeExperiment([4])]) nested_exp = BatchExperiment([exp5, exp3]) expdata = nested_exp.run(FakeBackend()) self.assertExperimentDone(expdata)
def test_mixed_batch_exp(self): """Test batch state and process tomography experiment""" # Subsystem unitaries state_op = qi.random_unitary(2, seed=321) chan_op = qi.random_unitary(2, seed=123) state_target = qi.Statevector(state_op.to_instruction()) chan_target = qi.Choi(chan_op.to_instruction()) state_exp = StateTomography(state_op) chan_exp = ProcessTomography(chan_op) batch_exp = BatchExperiment([state_exp, chan_exp]) # Run batch experiments backend = AerSimulator(seed_simulator=9000) par_data = batch_exp.run(backend) self.assertExperimentDone(par_data) f_threshold = 0.95 # Check state tomo results state_results = par_data.child_data(0).analysis_results() state = filter_results(state_results, "state").value # Check fit state fidelity state_fid = filter_results(state_results, "state_fidelity").value self.assertGreater(state_fid, f_threshold, msg="fit fidelity is low") # Manually check fidelity target_fid = qi.state_fidelity(state, state_target, validate=False) self.assertAlmostEqual(state_fid, target_fid, places=6, msg="result fidelity is incorrect") # Check process tomo results chan_results = par_data.child_data(1).analysis_results() chan = filter_results(chan_results, "state").value # Check fit process fidelity chan_fid = filter_results(chan_results, "process_fidelity").value self.assertGreater(chan_fid, f_threshold, msg="fit fidelity is low") # Manually check fidelity target_fid = qi.process_fidelity(chan, chan_target, require_cp=False, require_tp=False) self.assertAlmostEqual(chan_fid, target_fid, places=6, msg="result fidelity is incorrect")
def test_nested_composite(self): """ Test nested parallel experiments. """ exp1 = FakeExperiment([0, 2]) exp2 = FakeExperiment([1, 3]) exp3 = ParallelExperiment([exp1, exp2]) exp4 = BatchExperiment([exp3, exp1]) exp5 = ParallelExperiment([exp4, FakeExperiment([4])]) nested_exp = BatchExperiment([exp5, exp3]) expdata = nested_exp.run(FakeBackend()).block_for_results() status = expdata.status() self.assertEqual(status.name, "DONE")
def test_batch_exp_with_measurement_qubits(self): """Test batch process tomography experiment with kwargs""" seed = 1111 nq = 3 ops = [qi.random_unitary(2, seed=seed + i) for i in range(nq)] # Preparation circuit circuit = QuantumCircuit(nq) for i, op in enumerate(ops): circuit.append(op, [i]) # Component experiments exps = [] targets = [] for i in range(nq): targets.append(ops[i]) exps.append( ProcessTomography(circuit, measurement_qubits=[i], preparation_qubits=[i])) # Run batch experiments backend = AerSimulator(seed_simulator=9000) batch_exp = BatchExperiment(exps) batch_data = batch_exp.run(backend) batch_data.block_for_results() # Check target fidelity of component experiments f_threshold = 0.95 for i in range(batch_exp.num_experiments): results = batch_data.component_experiment_data( i).analysis_results() # Check state is density matrix state = filter_results(results, "state").value self.assertTrue(isinstance(state, qi.Choi), msg="fitted state is not a Choi matrix") # Check fit state fidelity fid = filter_results(results, "process_fidelity").value self.assertGreater(fid, f_threshold, msg="fit fidelity is low") # Manually check fidelity target_fid = qi.process_fidelity(state, targets[i], require_tp=False, require_cp=False) self.assertAlmostEqual(fid, target_fid, places=6, msg="result fidelity is incorrect")
def setUp(self): super().setUp() self.backend = FakeBackend() self.share_level = "hey" exp1 = FakeExperiment([0, 2]) exp2 = FakeExperiment([1, 3]) par_exp = ParallelExperiment([exp1, exp2]) exp3 = FakeExperiment([0, 1, 2, 3]) batch_exp = BatchExperiment([par_exp, exp3]) self.rootdata = batch_exp.run(backend=self.backend).block_for_results() self.assertEqual(len(self.rootdata.child_data()), 2) self.rootdata.share_level = self.share_level
def test_batch_exp(self): """Test batch state tomography experiment with measurement_qubits kwarg""" # Subsystem unitaries seed = 1111 nq = 3 ops = [qi.random_unitary(2, seed=seed + i) for i in range(nq)] # Preparation circuit circuit = QuantumCircuit(nq) for i, op in enumerate(ops): circuit.append(op, [i]) # Component experiments exps = [] targets = [] for i in range(nq): targets.append(qi.Statevector(ops[i].to_instruction())) exps.append(StateTomography(circuit, measurement_qubits=[i])) # Run batch experiments backend = AerSimulator(seed_simulator=9000) batch_exp = BatchExperiment(exps) batch_data = batch_exp.run(backend) self.assertExperimentDone(batch_data) # Check target fidelity of component experiments f_threshold = 0.95 for i in range(batch_exp.num_experiments): results = batch_data.child_data(i).analysis_results() # Check state is density matrix state = filter_results(results, "state").value self.assertTrue(isinstance(state, qi.DensityMatrix), msg="fitted state is not density matrix") # Check fit state fidelity fid = filter_results(results, "state_fidelity").value self.assertGreater(fid, f_threshold, msg="fit fidelity is low") # Manually check fidelity target_fid = qi.state_fidelity(state, targets[i], validate=False) self.assertAlmostEqual(fid, target_fid, places=6, msg="result fidelity is incorrect")
def test_roundtrip_serializable(self): """Test round trip JSON serialization""" exp1 = FakeExperiment([0]) exp1.set_run_options(shots=1000) exp2 = FakeExperiment([2]) exp2.set_run_options(shots=2000) exp = BatchExperiment([exp1, exp2]) self.assertRoundTripSerializable(exp, self.json_equiv)
def test_flatten_results_nested(self): """Test combining results.""" exp0 = FakeExperiment([0]) exp1 = FakeExperiment([1]) exp2 = FakeExperiment([2]) exp3 = FakeExperiment([3]) comp_exp = ParallelExperiment( [ BatchExperiment(2 * [ParallelExperiment([exp0, exp1])]), BatchExperiment(3 * [ParallelExperiment([exp2, exp3])]), ], flatten_results=True, ) expdata = comp_exp.run(FakeBackend()) self.assertExperimentDone(expdata) # Check no child data was saved self.assertEqual(len(expdata.child_data()), 0) # Check right number of analysis results is returned self.assertEqual(len(expdata.analysis_results()), 30)
def test_analysis_replace_results_false(self): """ Test replace_results of composite experiment data """ exp1 = FakeExperiment([0, 2]) exp2 = FakeExperiment([1, 3]) par_exp = BatchExperiment([exp1, exp2]) data1 = par_exp.run(FakeBackend()).block_for_results() # Additional data not part of composite experiment exp3 = FakeExperiment([0, 1]) extra_data = exp3.run(FakeBackend()).block_for_results() data1.add_child_data(extra_data) # Replace results data2 = par_exp.analysis.run(data1).block_for_results() self.assertNotEqual(data1.experiment_id, data2.experiment_id) self.assertEqual(len(data1.child_data()), len(data2.child_data())) for sub1, sub2 in zip(data1.child_data(), data2.child_data()): self.assertNotEqual(sub1.experiment_id, sub2.experiment_id)
def test_flatten_results_partial(self): """Test flattening results.""" exp0 = FakeExperiment([0]) exp1 = FakeExperiment([1]) exp2 = FakeExperiment([2]) exp3 = FakeExperiment([3]) comp_exp = BatchExperiment([ ParallelExperiment([exp0, exp1, exp2], flatten_results=True), ParallelExperiment([exp2, exp3], flatten_results=True), ], ) expdata = comp_exp.run(FakeBackend()) self.assertExperimentDone(expdata) # Check out experiment wasnt flattened self.assertEqual(len(expdata.child_data()), 2) self.assertEqual(len(expdata.analysis_results()), 0) # check inner experiments were flattened child0 = expdata.child_data(0) child1 = expdata.child_data(1) self.assertEqual(len(child0.child_data()), 0) self.assertEqual(len(child1.child_data()), 0) # Check right number of analysis results is returned self.assertEqual(len(child0.analysis_results()), 9) self.assertEqual(len(child1.analysis_results()), 6)
def setUp(self): super().setUp() self.backend = FakeMelbourne() self.share_level = "hey" exp1 = FakeExperiment([0, 2]) exp2 = FakeExperiment([1, 3]) par_exp = ParallelExperiment([exp1, exp2]) exp3 = FakeExperiment(4) batch_exp = BatchExperiment([par_exp, exp3]) self.rootdata = CompositeExperimentData(batch_exp, backend=self.backend) self.rootdata.share_level = self.share_level
def test_composite_subexp_data(self): """ Verify that sub-experiment data of parallel and batch experiments are correctly marginalized """ counts = [ { "0000": 1, "0010": 6, "0011": 3, "0100": 4, "0101": 2, "0110": 1, "0111": 3, "1000": 5, "1001": 3, "1010": 4, "1100": 4, "1101": 3, "1110": 8, "1111": 5, }, { "0001": 3, "0010": 4, "0011": 5, "0100": 2, "0101": 1, "0111": 7, "1000": 3, "1001": 2, "1010": 1, "1011": 1, "1100": 7, "1101": 8, "1110": 2, }, { "0000": 1, "0001": 1, "0010": 8, "0011": 7, "0100": 2, "0101": 2, "0110": 2, "0111": 1, "1000": 6, "1010": 4, "1011": 4, "1100": 5, "1101": 2, "1110": 2, "1111": 5, }, { "0000": 4, "0001": 5, "0101": 4, "0110": 8, "0111": 2, "1001": 6, "1010": 8, "1011": 8, "1101": 1, "1110": 3, "1111": 3, }, { "0000": 3, "0001": 6, "0010": 7, "0011": 1, "0100": 1, "0101": 5, "0110": 4, "1000": 2, "1001": 4, "1011": 3, "1100": 6, "1111": 1, }, ] class Backend(FakeBackend): """ Bacekend to be used in test_composite_subexp_data """ def run(self, run_input, **options): results = [] for circ, cnt in zip(run_input, counts): results.append({ "shots": -1, "success": True, "header": { "metadata": circ.metadata }, "data": { "counts": cnt }, }) res = { "backend_name": "backend", "backend_version": "0", "qobj_id": uuid.uuid4().hex, "job_id": uuid.uuid4().hex, "success": True, "results": results, } return FakeJob(backend=self, result=Result.from_dict(res)) class Experiment(FakeExperiment): """ Experiment to be used in test_composite_subexp_data """ def __init__(self, qubits, num_circs): super().__init__(qubits) self._ncircs = num_circs def circuits(self): nqubits = len(self._physical_qubits) circs = [] for _ in range(self._ncircs): circ = QuantumCircuit(nqubits, nqubits) circ.metadata = {} circs.append(circ) return circs exp1 = Experiment([0, 2], 5) exp2 = Experiment([1], 2) exp3 = Experiment([3], 2) exp4 = Experiment([1, 3], 3) par_exp = ParallelExperiment( [exp1, BatchExperiment([ParallelExperiment([exp2, exp3]), exp4])]) expdata = par_exp.run(Backend()).block_for_results() self.assertEqual(len(expdata.data()), len(counts)) for circ_data, circ_counts in zip(expdata.data(), counts): self.assertDictEqual(circ_data["counts"], circ_counts) counts1 = [ [ { "00": 14, "10": 19, "11": 11, "01": 8 }, { "01": 14, "10": 7, "11": 13, "00": 12 }, { "00": 14, "01": 5, "10": 16, "11": 17 }, { "00": 4, "01": 16, "10": 19, "11": 13 }, { "00": 12, "01": 15, "10": 11, "11": 5 }, ], [ { "00": 10, "01": 10, "10": 12, "11": 20 }, { "00": 12, "01": 10, "10": 7, "11": 17 }, { "00": 17, "01": 7, "10": 14, "11": 14 }, { "00": 9, "01": 14, "10": 22, "11": 7 }, { "00": 17, "01": 10, "10": 9, "11": 7 }, ], ] self.assertEqual(len(expdata.child_data()), len(counts1)) for childdata, child_counts in zip(expdata.child_data(), counts1): self.assertEqual(len(childdata.data()), len(child_counts)) for circ_data, circ_counts in zip(childdata.data(), child_counts): self.assertDictEqual(circ_data["counts"], circ_counts) counts2 = [ [{ "00": 10, "01": 10, "10": 12, "11": 20 }, { "00": 12, "01": 10, "10": 7, "11": 17 }], [ { "00": 17, "01": 7, "10": 14, "11": 14 }, { "00": 9, "01": 14, "10": 22, "11": 7 }, { "00": 17, "01": 10, "10": 9, "11": 7 }, ], ] self.assertEqual(len(expdata.child_data(1).child_data()), len(counts2)) for childdata, child_counts in zip( expdata.child_data(1).child_data(), counts2): for circ_data, circ_counts in zip(childdata.data(), child_counts): self.assertDictEqual(circ_data["counts"], circ_counts) counts3 = [ [{ "0": 22, "1": 30 }, { "0": 19, "1": 27 }], [{ "0": 20, "1": 32 }, { "0": 22, "1": 24 }], ] self.assertEqual(len(expdata.child_data(1).child_data(0).child_data()), len(counts3)) for childdata, child_counts in zip( expdata.child_data(1).child_data(0).child_data(), counts3): self.assertEqual(len(childdata.data()), len(child_counts)) for circ_data, circ_counts in zip(childdata.data(), child_counts): self.assertDictEqual(circ_data["counts"], circ_counts)
class TestBatchTranspileOptions(QiskitExperimentsTestCase): """ For batch experiments, circuits are transpiled with the transpile options of the sub-experiments """ class SimpleExperiment(BaseExperiment): """ An experiment that creates a circuit of four qubits. Qubits 1 and 2 are inactive. Qubits 0 and 3 form a Bell state. The purpose: we will test with varying coupling maps, spanning from a coupling map that directly connects qubits 0 and 3 (hence qubits 1 and 2 remains inactive also in the transpiled circuit) to a coupling map with distance 3 between qubits 0 and 3. """ def __init__(self, qubits, backend=None): super().__init__( qubits, analysis=TestBatchTranspileOptions.SimpleAnalysis(), backend=backend) def circuits(self): circ = QuantumCircuit(4, 4) circ.h(0) circ.cx(0, 3) circ.barrier() circ.measure(range(4), range(4)) return [circ] class SimpleAnalysis(BaseAnalysis): """ The number of non-zero counts is equal to 2^(distance between qubits 0 and 3 in the transpiled circuit + 1) """ def _run_analysis(self, experiment_data): analysis_results = [ AnalysisResultData(name="non-zero counts", value=len( experiment_data.data(0)["counts"])), ] return analysis_results, [] def setUp(self): super().setUp() exp1 = self.SimpleExperiment(range(4)) exp2 = self.SimpleExperiment(range(4)) exp3 = self.SimpleExperiment(range(4)) batch1 = BatchExperiment([exp2, exp3]) self.batch2 = BatchExperiment([exp1, batch1]) exp1.set_transpile_options(coupling_map=[[0, 1], [1, 3], [3, 2]]) exp2.set_transpile_options(coupling_map=[[0, 1], [1, 2], [2, 3]]) # exp3 circuit: two active qubits and six instructions: hadamard, cnot, four measurements. # exp1 circuit: three active qubits (0, 1, 3) and seven instructions: hadamard, # two 2Q gates, four measurements. # exp2 circuit: four active qubits and eight instructions. def test_batch_transpiled_circuits(self): """ For batch experiments, circuits are transpiled with the transpile options of the sub-experiments """ circs = self.batch2._transpiled_circuits() numbers_of_gates = [len(circ.data) for circ in circs] self.assertEqual(set(numbers_of_gates), set([7, 8, 9])) def test_batch_transpile_options_integrated(self): """ The goal is to verify that not only `_trasnpiled_circuits` works well (`test_batch_transpiled_circuits` takes care of it) but that it's correctly called within the entire flow of `BaseExperiment.run`. """ backend = Aer.get_backend("aer_simulator") noise_model = noise.NoiseModel() noise_model.add_all_qubit_quantum_error( noise.depolarizing_error(0.5, 2), ["cx", "swap"]) expdata = self.batch2.run(backend, noise_model=noise_model, shots=1000) expdata.block_for_results() self.assertEqual(expdata.child_data(0).analysis_results(0).value, 8) self.assertEqual( expdata.child_data(1).child_data(0).analysis_results(0).value, 16) self.assertEqual( expdata.child_data(1).child_data(1).analysis_results(0).value, 4)