def test_get_qasms_noname(self): """Test the get_qasms from a qprogram without names. """ q_program = QuantumProgram() qr = q_program.create_quantum_register(size=3) cr = q_program.create_classical_register(size=3) qc1 = q_program.create_circuit(qregisters=[qr], cregisters=[cr]) qc2 = q_program.create_circuit(qregisters=[qr], cregisters=[cr]) qc1.h(qr[0]) qc1.cx(qr[0], qr[1]) qc1.cx(qr[1], qr[2]) qc1.measure(qr[0], cr[0]) qc1.measure(qr[1], cr[1]) qc1.measure(qr[2], cr[2]) qc2.h(qr) qc2.measure(qr[0], cr[0]) qc2.measure(qr[1], cr[1]) qc2.measure(qr[2], cr[2]) results = dict( zip(q_program.get_circuit_names(), q_program.get_qasms())) qr_name_len = len(qr.name) cr_name_len = len(cr.name) self.assertEqual(len(results[qc1.name]), qr_name_len * 9 + cr_name_len * 4 + 147) self.assertEqual(len(results[qc2.name]), qr_name_len * 7 + cr_name_len * 4 + 137)
def test_get_register_and_circuit_names_nonames(self): """Get the names of the circuits and registers after create them without a name """ q_program = QuantumProgram() qr1 = q_program.create_quantum_register(size=3) cr1 = q_program.create_classical_register(size=3) qr2 = q_program.create_quantum_register(size=3) cr2 = q_program.create_classical_register(size=3) q_program.create_circuit(qregisters=[qr1], cregisters=[cr1]) q_program.create_circuit(qregisters=[qr2], cregisters=[cr2]) q_program.create_circuit(qregisters=[qr1, qr2], cregisters=[cr1, cr2]) qrn = q_program.get_quantum_register_names() crn = q_program.get_classical_register_names() qcn = q_program.get_circuit_names() self.assertEqual(len(qrn), 2) self.assertEqual(len(crn), 2) self.assertEqual(len(qcn), 3)
def test_get_register_and_circuit_names_nonames(self): """Get the names of the circuits and registers after create them without a name """ q_program = QuantumProgram() qr1 = q_program.create_quantum_register(size=3) cr1 = q_program.create_classical_register(size=3) qr2 = q_program.create_quantum_register(size=3) cr2 = q_program.create_classical_register(size=3) q_program.create_circuit(qregisters=[qr1], cregisters=[cr1]) q_program.create_circuit(qregisters=[qr2], cregisters=[cr2]) q_program.create_circuit(qregisters=[qr1, qr2], cregisters=[cr1, cr2]) qrn = q_program.get_quantum_register_names() crn = q_program.get_classical_register_names() qcn = q_program.get_circuit_names() self.assertEqual(len(qrn), 2) self.assertEqual(len(crn), 2) self.assertEqual(len(qcn), 3)
def test_get_register_and_circuit_names(self): """Get the names of the circuits and registers. If all is correct we should get the arrays of the names Previusly: Libraries: from qiskit import QuantumProgram """ QP_program = QuantumProgram() qr1 = QP_program.create_quantum_register("qr1", 3, verbose=False) cr1 = QP_program.create_classical_register("cr1", 3, verbose=False) qr2 = QP_program.create_quantum_register("qr2", 3, verbose=False) cr2 = QP_program.create_classical_register("cr2", 3, verbose=False) QP_program.create_circuit("qc1", [qr1], [cr1]) QP_program.create_circuit("qc2", [qr2], [cr2]) QP_program.create_circuit("qc2", [qr1, qr2], [cr1, cr2]) qrn = QP_program.get_quantum_register_names() crn = QP_program.get_classical_register_names() qcn = QP_program.get_circuit_names() self.assertEqual(qrn, ['qr1', 'qr2']) self.assertEqual(crn, ['cr1', 'cr2']) self.assertEqual(qcn, ['qc1', 'qc2'])
def test_get_qasms_noname(self): """Test the get_qasms from a qprogram without names. """ q_program = QuantumProgram() qr = q_program.create_quantum_register(size=3) cr = q_program.create_classical_register(size=3) qc1 = q_program.create_circuit(qregisters=[qr], cregisters=[cr]) qc2 = q_program.create_circuit(qregisters=[qr], cregisters=[cr]) qc1.h(qr[0]) qc1.cx(qr[0], qr[1]) qc1.cx(qr[1], qr[2]) qc1.measure(qr[0], cr[0]) qc1.measure(qr[1], cr[1]) qc1.measure(qr[2], cr[2]) qc2.h(qr) qc2.measure(qr[0], cr[0]) qc2.measure(qr[1], cr[1]) qc2.measure(qr[2], cr[2]) results = dict(zip(q_program.get_circuit_names(), q_program.get_qasms())) qr_name_len = len(qr.name) cr_name_len = len(cr.name) self.assertEqual(len(results[qc1.name]), qr_name_len * 9 + cr_name_len * 4 + 147) self.assertEqual(len(results[qc2.name]), qr_name_len * 7 + cr_name_len * 4 + 137)
def test_get_register_and_circuit_names(self): """Get the names of the circuits and registers. If all is correct we should get the arrays of the names Previusly: Libraries: from qiskit import QuantumProgram """ QP_program = QuantumProgram() qr1 = QP_program.create_quantum_register("qr1", 3, verbose=False) cr1 = QP_program.create_classical_register("cr1", 3, verbose=False) qr2 = QP_program.create_quantum_register("qr2", 3, verbose=False) cr2 = QP_program.create_classical_register("cr2", 3, verbose=False) QP_program.create_circuit("qc1", [qr1], [cr1]) QP_program.create_circuit("qc2", [qr2], [cr2]) QP_program.create_circuit("qc2", [qr1, qr2], [cr1, cr2]) qrn = QP_program.get_quantum_register_names() crn = QP_program.get_classical_register_names() qcn = QP_program.get_circuit_names() self.assertEqual(qrn, {'qr1', 'qr2'}) self.assertEqual(crn, {'cr1', 'cr2'}) self.assertEqual(qcn, {'qc1', 'qc2'})
class LocalQasmSimulatorTest(unittest.TestCase): """Test local qasm simulator.""" @classmethod def setUpClass(cls): cls.moduleName = os.path.splitext(__file__)[0] cls.pdf = PdfPages(cls.moduleName + '.pdf') cls.log = logging.getLogger(__name__) cls.log.setLevel(logging.INFO) logFileName = cls.moduleName + '.log' handler = logging.FileHandler(logFileName) handler.setLevel(logging.INFO) log_fmt = ('{}.%(funcName)s:%(levelname)s:%(asctime)s:' ' %(message)s'.format(cls.__name__)) formatter = logging.Formatter(log_fmt) handler.setFormatter(formatter) cls.log.addHandler(handler) @classmethod def tearDownClass(cls): cls.pdf.close() def setUp(self): self.seed = 88 self.qasmFileName = os.path.join(qiskit.__path__[0], '../test/python/qasm/example.qasm') self.qp = QuantumProgram() def tearDown(self): pass def test_qasm_simulator_single_shot(self): """Test single shot run.""" shots = 1 self.qp.load_qasm_file(self.qasmFileName, name='example') basis_gates = [] # unroll to base gates unroller = unroll.Unroller( qasm.Qasm(data=self.qp.get_qasm("example")).parse(), unroll.JsonBackend(basis_gates)) circuit = unroller.execute() config = {'shots': shots, 'seed': self.seed} job = {'compiled_circuit': circuit, 'config': config} result = QasmSimulator(job).run() self.assertEqual(result['status'], 'DONE') def test_qasm_simulator(self): """Test data counts output for single circuit run against reference.""" shots = 1024 self.qp.load_qasm_file(self.qasmFileName, name='example') basis_gates = [] # unroll to base gates unroller = unroll.Unroller( qasm.Qasm(data=self.qp.get_qasm("example")).parse(), unroll.JsonBackend(basis_gates)) circuit = unroller.execute() config = {'shots': shots, 'seed': self.seed} job = {'compiled_circuit': circuit, 'config': config} result = QasmSimulator(job).run() expected = {'100 100': 137, '011 011': 131, '101 101': 117, '111 111': 127, '000 000': 131, '010 010': 141, '110 110': 116, '001 001': 124} self.assertEqual(result['data']['counts'], expected) def test_if_statement(self): self.log.info('test_if_statement_x') shots = 100 max_qubits = 3 qp = QuantumProgram() qr = qp.create_quantum_register('qr', max_qubits) cr = qp.create_classical_register('cr', max_qubits) circuit = qp.create_circuit('test_if', [qr], [cr]) circuit.x(qr[0]) circuit.x(qr[1]) circuit.measure(qr[0], cr[0]) circuit.measure(qr[1], cr[1]) circuit.x(qr[2]).c_if(cr, 0x3) circuit.measure(qr[0], cr[0]) circuit.measure(qr[1], cr[1]) circuit.measure(qr[2], cr[2]) circuit2 = qp.create_circuit('test_if_case_2', [qr], [cr]) circuit2.x(qr[0]) circuit2.measure(qr[0], cr[0]) circuit2.measure(qr[1], cr[1]) circuit2.x(qr[2]).c_if(cr, 0x3) circuit2.measure(qr[0], cr[0]) circuit2.measure(qr[1], cr[1]) circuit2.measure(qr[2], cr[2]) basis_gates = [] # unroll to base gates unroller = unroll.Unroller( qasm.Qasm(data=qp.get_qasm('test_if')).parse(), unroll.JsonBackend(basis_gates)) ucircuit = unroller.execute() unroller = unroll.Unroller( qasm.Qasm(data=qp.get_qasm('test_if_case_2')).parse(), unroll.JsonBackend(basis_gates)) ucircuit2 = unroller.execute() config = {'shots': shots, 'seed': self.seed} job = {'compiled_circuit': ucircuit, 'config': config} result_if_true = QasmSimulator(job).run() job = {'compiled_circuit': ucircuit2, 'config': config} result_if_false = QasmSimulator(job).run() self.log.info('result_if_true circuit:') self.log.info(circuit.qasm()) self.log.info('result_if_true={0}'.format(result_if_true)) del circuit.data[1] self.log.info('result_if_false circuit:') self.log.info(circuit.qasm()) self.log.info('result_if_false={0}'.format(result_if_false)) self.assertTrue(result_if_true['data']['counts']['111'] == 100) self.assertTrue(result_if_false['data']['counts']['001'] == 100) def test_teleport(self): """test teleportation as in tutorials""" self.log.info('test_teleport') pi = np.pi shots = 1000 qp = QuantumProgram() qr = qp.create_quantum_register('qr', 3) cr0 = qp.create_classical_register('cr0', 1) cr1 = qp.create_classical_register('cr1', 1) cr2 = qp.create_classical_register('cr2', 1) circuit = qp.create_circuit('teleport', [qr], [cr0, cr1, cr2]) circuit.h(qr[1]) circuit.cx(qr[1], qr[2]) circuit.ry(pi/4, qr[0]) circuit.cx(qr[0], qr[1]) circuit.h(qr[0]) circuit.barrier(qr) circuit.measure(qr[0], cr0[0]) circuit.measure(qr[1], cr1[0]) circuit.z(qr[2]).c_if(cr0, 1) circuit.x(qr[2]).c_if(cr1, 1) circuit.measure(qr[2], cr2[0]) backend = 'local_qasm_simulator' qobj = qp.compile('teleport', backend=backend, shots=shots, seed=self.seed) results = qp.run(qobj) data = results.get_counts('teleport') alice = {} bob = {} alice['00'] = data['0 0 0'] + data['1 0 0'] alice['01'] = data['0 1 0'] + data['1 1 0'] alice['10'] = data['0 0 1'] + data['1 0 1'] alice['11'] = data['0 1 1'] + data['1 1 1'] bob['0'] = data['0 0 0'] + data['0 1 0'] + data['0 0 1'] + data['0 1 1'] bob['1'] = data['1 0 0'] + data['1 1 0'] + data['1 0 1'] + data['1 1 1'] self.log.info('test_telport: circuit:') self.log.info( circuit.qasm() ) self.log.info('test_teleport: data {0}'.format(data)) self.log.info('test_teleport: alice {0}'.format(alice)) self.log.info('test_teleport: bob {0}'.format(bob)) alice_ratio = 1/np.tan(pi/8)**2 bob_ratio = bob['0']/float(bob['1']) error = abs(alice_ratio - bob_ratio) / alice_ratio self.log.info('test_teleport: relative error = {0:.4f}'.format(error)) self.assertLess(error, 0.05) def profile_qasm_simulator(self): """Profile randomly generated circuits. Writes profile results to <this_module>.prof as well as recording to the log file. number of circuits = 100. number of operations/circuit in [1, 40] number of qubits in [1, 5] """ seed = 88 shots = 1024 nCircuits = 100 minDepth = 1 maxDepth = 40 minQubits = 1 maxQubits = 5 pr = cProfile.Profile() randomCircuits = RandomQasmGenerator(seed, minQubits=minQubits, maxQubits=maxQubits, minDepth=minDepth, maxDepth=maxDepth) randomCircuits.add_circuits(nCircuits) self.qp = randomCircuits.getProgram() pr.enable() self.qp.execute(self.qp.get_circuit_names(), backend='local_qasm_simulator', shots=shots) pr.disable() sout = io.StringIO() ps = pstats.Stats(pr, stream=sout).sort_stats('cumulative') self.log.info('------- start profiling QasmSimulator -----------') ps.print_stats() self.log.info(sout.getvalue()) self.log.info('------- stop profiling QasmSimulator -----------') sout.close() pr.dump_stats(self.moduleName + '.prof') def profile_nqubit_speed_grow_depth(self): """simulation time vs the number of qubits where the circuit depth is 10x the number of simulated qubits. Also creates a pdf file with this module name showing a plot of the results. Compilation is not included in speed. """ import matplotlib.pyplot as plt from matplotlib.ticker import MaxNLocator qubitRangeMax = 15 nQubitList = range(1,qubitRangeMax + 1) nCircuits = 10 shots = 1024 seed = 88 maxTime = 30 # seconds; timing stops when simulation time exceeds this number fmtStr1 = 'profile_nqubit_speed::nqubits:{0}, backend:{1}, elapsed_time:{2:.2f}' fmtStr2 = 'backend:{0}, circuit:{1}, numOps:{2}, result:{3}' fmtStr3 = 'minDepth={minDepth}, maxDepth={maxDepth}, num circuits={nCircuits}, shots={shots}' backendList = ['local_qasm_simulator', 'local_unitary_simulator'] if shutil.which('qasm_simulator'): backendList.append('local_qasm_cpp_simulator') else: self.log.info('profile_nqubit_speed::\"qasm_simulator\" executable not in path...skipping') fig = plt.figure(0) plt.clf() ax = fig.add_axes((0.1, 0.25, 0.8, 0.6)) for i, backend in enumerate(backendList): elapsedTime = np.zeros(len(nQubitList)) if backend is 'local_unitary_simulator': doMeasure = False else: doMeasure = True j, timedOut = 0, False while j < qubitRangeMax and not timedOut: nQubits = nQubitList[j] randomCircuits = RandomQasmGenerator(seed, minQubits=nQubits, maxQubits=nQubits, minDepth=nQubits*10, maxDepth=nQubits*10) randomCircuits.add_circuits(nCircuits, doMeasure=doMeasure) qp = randomCircuits.getProgram() cnames = qp.get_circuit_names() qobj = qp.compile(cnames, backend=backend, shots=shots, seed=seed) start = time.perf_counter() results = qp.run(qobj) stop = time.perf_counter() elapsedTime[j] = stop - start if elapsedTime[j] > maxTime: timedOut = True self.log.info(fmtStr1.format(nQubits, backend, elapsedTime[j])) if backend is not 'local_unitary_simulator': for name in cnames: self.log.info(fmtStr2.format( backend, name, len(qp.get_circuit(name)), results.get_data(name))) j += 1 ax.xaxis.set_major_locator(MaxNLocator(integer=True)) if backend is 'local_unitary_simulator': ax.plot(nQubitList[:j], elapsedTime[:j], label=backend, marker='o') else: ax.plot(nQubitList[:j], elapsedTime[:j]/shots, label=backend, marker='o') ax.set_yscale('log', basey=10) ax.set_xlabel('number of qubits') ax.set_ylabel('process time/shot') ax.set_title('profile_nqubit_speed_grow_depth') fig.text(0.1, 0.05, fmtStr3.format(minDepth='10*nQubits', maxDepth='10*nQubits', nCircuits=nCircuits, shots=shots)) ax.legend() self.pdf.savefig(fig) def profile_nqubit_speed_constant_depth(self): """simulation time vs the number of qubits where the circuit depth is fixed at 40. Also creates a pdf file with this module name showing a plot of the results. Compilation is not included in speed. """ import matplotlib.pyplot as plt from matplotlib.ticker import MaxNLocator qubitRangeMax = 15 nQubitList = range(1,qubitRangeMax + 1) maxDepth = 40 minDepth = 40 nCircuits = 10 shots = 1024 seed = 88 maxTime = 30 # seconds; timing stops when simulation time exceeds this number fmtStr1 = 'profile_nqubit_speed::nqubits:{0}, backend:{1}, elapsed_time:{2:.2f}' fmtStr2 = 'backend:{0}, circuit:{1}, numOps:{2}, result:{3}' fmtStr3 = 'minDepth={minDepth}, maxDepth={maxDepth}, num circuits={nCircuits}, shots={shots}' backendList = ['local_qasm_simulator', 'local_unitary_simulator'] if shutil.which('qasm_simulator'): backendList.append('local_qasm_cpp_simulator') else: self.log.info('profile_nqubit_speed::\"qasm_simulator\" executable not in path...skipping') fig = plt.figure(0) plt.clf() ax = fig.add_axes((0.1, 0.2, 0.8, 0.6)) for i, backend in enumerate(backendList): elapsedTime = np.zeros(len(nQubitList)) if backend is 'local_unitary_simulator': doMeasure = False else: doMeasure = True j, timedOut = 0, False while j < qubitRangeMax and not timedOut: nQubits = nQubitList[j] randomCircuits = RandomQasmGenerator(seed, minQubits=nQubits, maxQubits=nQubits, minDepth=minDepth, maxDepth=maxDepth) randomCircuits.add_circuits(nCircuits, doMeasure=doMeasure) qp = randomCircuits.getProgram() cnames = qp.get_circuit_names() qobj = qp.compile(cnames, backend=backend, shots=shots, seed=seed) start = time.perf_counter() results = qp.run(qobj) stop = time.perf_counter() elapsedTime[j] = stop - start if elapsedTime[j] > maxTime: timedOut = True self.log.info(fmtStr1.format(nQubits, backend, elapsedTime[j])) if backend is not 'local_unitary_simulator': for name in cnames: self.log.info(fmtStr2.format( backend, name, len(qp.get_circuit(name)), results.get_data(name))) j += 1 ax.xaxis.set_major_locator(MaxNLocator(integer=True)) if backend is 'local_unitary_simulator': ax.plot(nQubitList[:j], elapsedTime[:j], label=backend, marker='o') else: ax.plot(nQubitList[:j], elapsedTime[:j]/shots, label=backend, marker='o') ax.set_yscale('log', basey=10) ax.set_xlabel('number of qubits') ax.set_ylabel('process time/shot') ax.set_title('profile_nqubit_speed_constant_depth') fig.text(0.1, 0.05, fmtStr3.format(minDepth=minDepth, maxDepth=maxDepth, nCircuits=nCircuits, shots=shots)) ax.legend() self.pdf.savefig(fig)
class TestLocalQasmSimulatorPy(QiskitTestCase): """Test local_qasm_simulator_py.""" @classmethod def setUpClass(cls): super().setUpClass() if do_profiling: cls.pdf = PdfPages(cls.moduleName + '.pdf') @classmethod def tearDownClass(cls): if do_profiling: cls.pdf.close() def setUp(self): self.seed = 88 self.qasm_filename = self._get_resource_path('qasm/example.qasm') self.qp = QuantumProgram() self.qp.load_qasm_file(self.qasm_filename, name='example') basis_gates = [] # unroll to base gates unroller = unroll.Unroller( qasm.Qasm(data=self.qp.get_qasm('example')).parse(), unroll.JsonBackend(basis_gates)) circuit = unroller.execute() circuit_config = { 'coupling_map': None, 'basis_gates': 'u1,u2,u3,cx,id', 'layout': None, 'seed': self.seed } resources = {'max_credits': 3} self.qobj = { 'id': 'test_sim_single_shot', 'config': { 'max_credits': resources['max_credits'], 'shots': 1024, 'backend_name': 'local_qasm_simulator_py', }, 'circuits': [{ 'name': 'test', 'compiled_circuit': circuit, 'compiled_circuit_qasm': None, 'config': circuit_config }] } self.q_job = QuantumJob(self.qobj, backend=QasmSimulatorPy(), circuit_config=circuit_config, seed=self.seed, resources=resources, preformatted=True) def tearDown(self): pass def test_qasm_simulator_single_shot(self): """Test single shot run.""" shots = 1 self.qobj['config']['shots'] = shots result = QasmSimulatorPy().run(self.q_job).result() self.assertEqual(result.get_status(), 'COMPLETED') def test_qasm_simulator(self): """Test data counts output for single circuit run against reference.""" result = QasmSimulatorPy().run(self.q_job).result() shots = 1024 threshold = 0.04 * shots counts = result.get_counts('test') target = { '100 100': shots / 8, '011 011': shots / 8, '101 101': shots / 8, '111 111': shots / 8, '000 000': shots / 8, '010 010': shots / 8, '110 110': shots / 8, '001 001': shots / 8 } self.assertDictAlmostEqual(counts, target, threshold) def test_if_statement(self): self.log.info('test_if_statement_x') shots = 100 max_qubits = 3 qp = QuantumProgram() qr = qp.create_quantum_register('qr', max_qubits) cr = qp.create_classical_register('cr', max_qubits) circuit_if_true = qp.create_circuit('test_if_true', [qr], [cr]) circuit_if_true.x(qr[0]) circuit_if_true.x(qr[1]) circuit_if_true.measure(qr[0], cr[0]) circuit_if_true.measure(qr[1], cr[1]) circuit_if_true.x(qr[2]).c_if(cr, 0x3) circuit_if_true.measure(qr[0], cr[0]) circuit_if_true.measure(qr[1], cr[1]) circuit_if_true.measure(qr[2], cr[2]) circuit_if_false = qp.create_circuit('test_if_false', [qr], [cr]) circuit_if_false.x(qr[0]) circuit_if_false.measure(qr[0], cr[0]) circuit_if_false.measure(qr[1], cr[1]) circuit_if_false.x(qr[2]).c_if(cr, 0x3) circuit_if_false.measure(qr[0], cr[0]) circuit_if_false.measure(qr[1], cr[1]) circuit_if_false.measure(qr[2], cr[2]) basis_gates = [] # unroll to base gates unroller = unroll.Unroller( qasm.Qasm(data=qp.get_qasm('test_if_true')).parse(), unroll.JsonBackend(basis_gates)) ucircuit_true = unroller.execute() unroller = unroll.Unroller( qasm.Qasm(data=qp.get_qasm('test_if_false')).parse(), unroll.JsonBackend(basis_gates)) ucircuit_false = unroller.execute() qobj = { 'id': 'test_if_qobj', 'config': { 'max_credits': 3, 'shots': shots, 'backend_name': 'local_qasm_simulator_py', }, 'circuits': [{ 'name': 'test_if_true', 'compiled_circuit': ucircuit_true, 'compiled_circuit_qasm': None, 'config': { 'coupling_map': None, 'basis_gates': 'u1,u2,u3,cx,id', 'layout': None, 'seed': None } }, { 'name': 'test_if_false', 'compiled_circuit': ucircuit_false, 'compiled_circuit_qasm': None, 'config': { 'coupling_map': None, 'basis_gates': 'u1,u2,u3,cx,id', 'layout': None, 'seed': None } }] } q_job = QuantumJob(qobj, backend=QasmSimulatorPy(), preformatted=True) result = QasmSimulatorPy().run(q_job).result() result_if_true = result.get_data('test_if_true') self.log.info('result_if_true circuit:') self.log.info(circuit_if_true.qasm()) self.log.info('result_if_true=%s', result_if_true) result_if_false = result.get_data('test_if_false') self.log.info('result_if_false circuit:') self.log.info(circuit_if_false.qasm()) self.log.info('result_if_false=%s', result_if_false) self.assertTrue(result_if_true['counts']['111'] == 100) self.assertTrue(result_if_false['counts']['001'] == 100) @unittest.skipIf(version_info.minor == 5, "Due to gate ordering issues with Python 3.5 \ we have to disable this test until fixed" ) def test_teleport(self): """test teleportation as in tutorials""" self.log.info('test_teleport') pi = np.pi shots = 1000 qp = QuantumProgram() qr = qp.create_quantum_register('qr', 3) cr0 = qp.create_classical_register('cr0', 1) cr1 = qp.create_classical_register('cr1', 1) cr2 = qp.create_classical_register('cr2', 1) circuit = qp.create_circuit('teleport', [qr], [cr0, cr1, cr2]) circuit.h(qr[1]) circuit.cx(qr[1], qr[2]) circuit.ry(pi / 4, qr[0]) circuit.cx(qr[0], qr[1]) circuit.h(qr[0]) circuit.barrier(qr) circuit.measure(qr[0], cr0[0]) circuit.measure(qr[1], cr1[0]) circuit.z(qr[2]).c_if(cr0, 1) circuit.x(qr[2]).c_if(cr1, 1) circuit.measure(qr[2], cr2[0]) backend = 'local_qasm_simulator_py' qobj = qp.compile('teleport', backend=backend, shots=shots, seed=self.seed) results = qp.run(qobj) data = results.get_counts('teleport') alice = {} bob = {} alice['00'] = data['0 0 0'] + data['1 0 0'] alice['01'] = data['0 1 0'] + data['1 1 0'] alice['10'] = data['0 0 1'] + data['1 0 1'] alice['11'] = data['0 1 1'] + data['1 1 1'] bob['0'] = data['0 0 0'] + data['0 1 0'] + data['0 0 1'] + data['0 1 1'] bob['1'] = data['1 0 0'] + data['1 1 0'] + data['1 0 1'] + data['1 1 1'] self.log.info('test_telport: circuit:') self.log.info(circuit.qasm()) self.log.info('test_teleport: data %s', data) self.log.info('test_teleport: alice %s', alice) self.log.info('test_teleport: bob %s', bob) alice_ratio = 1 / np.tan(pi / 8)**2 bob_ratio = bob['0'] / float(bob['1']) error = abs(alice_ratio - bob_ratio) / alice_ratio self.log.info('test_teleport: relative error = %s', error) self.assertLess(error, 0.05) @unittest.skipIf(not do_profiling, "skipping simulator profiling.") def profile_qasm_simulator(self): """Profile randomly generated circuits. Writes profile results to <this_module>.prof as well as recording to the log file. number of circuits = 100. number of operations/circuit in [1, 40] number of qubits in [1, 5] """ seed = 88 shots = 1024 n_circuits = 100 min_depth = 1 max_depth = 40 min_qubits = 1 max_qubits = 5 pr = cProfile.Profile() random_circuits = RandomQasmGenerator(seed, min_qubits=min_qubits, max_qubits=max_qubits, min_depth=min_depth, max_depth=max_depth) random_circuits.add_circuits(n_circuits) self.qp = random_circuits.get_program() pr.enable() self.qp.execute(self.qp.get_circuit_names(), backend='local_qasm_simulator_py', shots=shots) pr.disable() sout = io.StringIO() ps = pstats.Stats(pr, stream=sout).sort_stats('cumulative') self.log.info('------- start profiling QasmSimulatorPy -----------') ps.print_stats() self.log.info(sout.getvalue()) self.log.info('------- stop profiling QasmSimulatorPy -----------') sout.close() pr.dump_stats(self.moduleName + '.prof') @unittest.skipIf(not do_profiling, "skipping simulator profiling.") def profile_nqubit_speed_grow_depth(self): """simulation time vs the number of qubits where the circuit depth is 10x the number of simulated qubits. Also creates a pdf file with this module name showing a plot of the results. Compilation is not included in speed. """ import matplotlib.pyplot as plt from matplotlib.ticker import MaxNLocator qubit_range_max = 15 n_qubit_list = range(1, qubit_range_max + 1) n_circuits = 10 shots = 1024 seed = 88 max_time = 30 # seconds; timing stops when simulation time exceeds this number fmt_str1 = 'profile_nqubit_speed::nqubits:{0}, backend:{1}, elapsed_time:{2:.2f}' fmt_str2 = 'backend:{0}, circuit:{1}, numOps:{2}, result:{3}' fmt_str3 = 'minDepth={minDepth}, maxDepth={maxDepth}, num circuits={nCircuits},' \ 'shots={shots}' backend_list = [ 'local_qasm_simulator_py', 'local_unitary_simulator_py' ] if shutil.which('qasm_simulator'): backend_list.append('local_qasm_simulator_cpp') else: self.log.info('profile_nqubit_speed::\"qasm_simulator\" executable' 'not in path...skipping') fig = plt.figure(0) plt.clf() ax = fig.add_axes((0.1, 0.25, 0.8, 0.6)) for _, backend in enumerate(backend_list): elapsed_time = np.zeros(len(n_qubit_list)) if backend == 'local_unitary_simulator_py': do_measure = False else: do_measure = True j, timed_out = 0, False while j < qubit_range_max and not timed_out: n_qubits = n_qubit_list[j] random_circuits = RandomQasmGenerator(seed, min_qubits=n_qubits, max_qubits=n_qubits, min_depth=n_qubits * 10, max_depth=n_qubits * 10) random_circuits.add_circuits(n_circuits, do_measure=do_measure) qp = random_circuits.get_program() c_names = qp.get_circuit_names() qobj = qp.compile(c_names, backend=backend, shots=shots, seed=seed) start = time.perf_counter() results = qp.run(qobj) stop = time.perf_counter() elapsed_time[j] = stop - start if elapsed_time[j] > max_time: timed_out = True self.log.info( fmt_str1.format(n_qubits, backend, elapsed_time[j])) if backend != 'local_unitary_simulator_py': for name in c_names: log_str = fmt_str2.format(backend, name, len(qp.get_circuit(name)), results.get_data(name)) self.log.info(log_str) j += 1 ax.xaxis.set_major_locator(MaxNLocator(integer=True)) if backend == 'local_unitary_simulator_py': ax.plot(n_qubit_list[:j], elapsed_time[:j], label=backend, marker='o') else: ax.plot(n_qubit_list[:j], elapsed_time[:j] / shots, label=backend, marker='o') ax.set_yscale('log', basey=10) ax.set_xlabel('number of qubits') ax.set_ylabel('process time/shot') ax.set_title('profile_nqubit_speed_grow_depth') fig.text( 0.1, 0.05, fmt_str3.format(minDepth='10*nQubits', maxDepth='10*nQubits', nCircuits=n_circuits, shots=shots)) ax.legend() self.pdf.savefig(fig) @unittest.skipIf(not do_profiling, "skipping simulator profiling.") def profile_nqubit_speed_constant_depth(self): """simulation time vs the number of qubits where the circuit depth is fixed at 40. Also creates a pdf file with this module name showing a plot of the results. Compilation is not included in speed. """ import matplotlib.pyplot as plt from matplotlib.ticker import MaxNLocator qubit_range_max = 15 n_qubit_list = range(1, qubit_range_max + 1) max_depth = 40 min_depth = 40 n_circuits = 10 shots = 1024 seed = 88 max_time = 30 # seconds; timing stops when simulation time exceeds this number fmt_str1 = 'profile_nqubit_speed::nqubits:{0}, backend:{1},' \ 'elapsed_time:{2:.2f}' fmt_str2 = 'backend:{0}, circuit:{1}, numOps:{2}, result:{3}' fmt_str3 = 'minDepth={minDepth}, maxDepth={maxDepth},' \ 'num circuits={nCircuits}, shots={shots}' backend_list = [ 'local_qasm_simulator_py', 'local_unitary_simulator_py' ] if shutil.which('qasm_simulator'): backend_list.append('local_qasm_simulator_cpp') else: self.log.info('profile_nqubit_speed::\"qasm_simulator\" executable' 'not in path...skipping') fig = plt.figure(0) plt.clf() ax = fig.add_axes((0.1, 0.2, 0.8, 0.6)) for _, backend in enumerate(backend_list): elapsedTime = np.zeros(len(n_qubit_list)) if backend == 'local_unitary_simulator_py': doMeasure = False else: doMeasure = True j, timedOut = 0, False while j < qubit_range_max and not timedOut: nQubits = n_qubit_list[j] randomCircuits = RandomQasmGenerator(seed, min_qubits=nQubits, max_qubits=nQubits, min_depth=min_depth, max_depth=max_depth) randomCircuits.add_circuits(n_circuits, do_measure=doMeasure) qp = randomCircuits.get_program() cnames = qp.get_circuit_names() qobj = qp.compile(cnames, backend=backend, shots=shots, seed=seed) start = time.perf_counter() results = qp.run(qobj) stop = time.perf_counter() elapsedTime[j] = stop - start if elapsedTime[j] > max_time: timedOut = True self.log.info(fmt_str1.format(nQubits, backend, elapsedTime[j])) if backend != 'local_unitary_simulator_py': for name in cnames: log_str = fmt_str2.format(backend, name, len(qp.get_circuit(name)), results.get_data(name)) self.log.info(log_str) j += 1 ax.xaxis.set_major_locator(MaxNLocator(integer=True)) if backend == 'local_unitary_simulator_py': ax.plot(n_qubit_list[:j], elapsedTime[:j], label=backend, marker='o') else: ax.plot(n_qubit_list[:j], elapsedTime[:j] / shots, label=backend, marker='o') ax.set_yscale('log', basey=10) ax.set_xlabel('number of qubits') ax.set_ylabel('process time/shot') ax.set_title('profile_nqubit_speed_constant_depth') fig.text( 0.1, 0.05, fmt_str3.format(minDepth=min_depth, maxDepth=max_depth, nCircuits=n_circuits, shots=shots)) ax.legend() self.pdf.savefig(fig)
class LocalUnitarySimulatorTest(unittest.TestCase): """Test local unitary simulator.""" def setUp(self): self.seed = 88 self.qasmFileName = os.path.join(qiskit.__path__[0], '../test/python/qasm/example.qasm') self.qp = QuantumProgram() self.moduleName = os.path.splitext(__file__)[0] self.modulePath = os.path.dirname(__file__) logFileName = self.moduleName + '.log' logging.basicConfig(filename=logFileName, level=logging.INFO) def tearDown(self): pass def test_unitary_simulator(self): """test generation of circuit unitary""" shots = 1024 self.qp.load_qasm_file(self.qasmFileName, name='example') basis_gates = [] # unroll to base gates unroller = unroll.Unroller( qasm.Qasm(data=self.qp.get_qasm("example")).parse(), unroll.JsonBackend(basis_gates)) circuit = unroller.execute() # if we want to manipulate the circuit, we have to convert it to a dict circuit = json.loads(circuit.decode()) #strip measurements from circuit to avoid warnings circuit['operations'] = [op for op in circuit['operations'] if op['name'] != 'measure'] # the simulator is expecting a JSON format, so we need to convert it back to JSON job = {'compiled_circuit': json.dumps(circuit).encode()} # numpy savetxt is currently prints complex numbers in a way # loadtxt can't read. To save file do, # fmtstr=['% .4g%+.4gj' for i in range(numCols)] # np.savetxt('example_unitary_matrix.dat', numpyMatrix, fmt=fmtstr, delimiter=',') expected = np.loadtxt(os.path.join(self.modulePath, 'example_unitary_matrix.dat'), dtype='complex', delimiter=',') result = UnitarySimulator(job).run() self.assertTrue(np.allclose(result['data']['unitary'], expected, rtol=1e-3)) def profile_unitary_simulator(self): """Profile randomly generated circuits. Writes profile results to <this_module>.prof as well as recording to the log file. number of circuits = 100. number of operations/circuit in [1, 40] number of qubits in [1, 5] """ nCircuits = 100 maxDepth = 40 maxQubits = 5 pr = cProfile.Profile() randomCircuits = RandomQasmGenerator(seed=self.seed, maxDepth=maxDepth, maxQubits=maxQubits) randomCircuits.add_circuits(nCircuits, doMeasure=False) self.qp = randomCircuits.getProgram() pr.enable() self.qp.execute(self.qp.get_circuit_names(), backend='local_unitary_simulator') pr.disable() sout = io.StringIO() ps = pstats.Stats(pr, stream=sout).sort_stats('cumulative') logging.info('------- start profiling UnitarySimulator -----------') ps.print_stats() logging.info(sout.getvalue()) logging.info('------- stop profiling UnitarySimulator -----------') sout.close() pr.dump_stats(self.moduleName + '.prof')
# second eight (qu)bits have superposition of # '8' = 00111000 # ';' = 00111011 # these differ only on the rightmost two bits circuit.h(quantum_r[9]) circuit.cx(quantum_r[9], quantum_r[8]) circuit.x(quantum_r[11]) circuit.x(quantum_r[12]) circuit.x(quantum_r[13]) # measure for j in range(16): circuit.measure(quantum_r[j], classical_r[j]) qp.get_circuit_names() QASM_source = qp.get_qasm('Circuit') print(QASM_source) import os import shutil from qiskit.tools.visualization import latex_drawer import pdf2image def circuitImage(circuit, basis="u1,u2,u3,cx"): """Obtain the circuit in image format Note: Requires pdflatex installed (to compile Latex) Note: Required pdf2image Python package (to display pdf as image) """
class QC(): ''' class QC ''' # pylint: disable=too-many-instance-attributes def __init__(self, backend='local_qasm_simulator', remote=False, qubits=3): # private member # __qp self.__qp = None # calc phase self.phase = [ ['0', 'initialized.'] ] # config self.backend = backend self.remote = remote self.qubits = qubits # circuits variable self.shots = 2 # async self.wait = False self.last = ['init', 'None'] self.load() def load(self, api_info=True): ''' load ''' self.__qp = QuantumProgram() if self.remote: try: import Qconfig self.__qp.set_api(Qconfig.APItoken, Qconfig.config["url"], hub=Qconfig.config["hub"], group=Qconfig.config["group"], project=Qconfig.config["project"]) except ImportError as ex: msg = 'Error in loading Qconfig.py!. Error = {}\n'.format(ex) sys.stdout.write(msg) sys.stdout.flush() return False if api_info is True: api = self.__qp.get_api() sys.stdout.write('<IBM Quantum Experience API information>\n') sys.stdout.flush() sys.stdout.write('Version: {0}\n'.format(api.api_version())) sys.stdout.write('User jobs (last 5):\n') jobs = api.get_jobs(limit=500) def format_date(job_item): ''' format ''' return datetime.strptime(job_item['creationDate'], '%Y-%m-%dT%H:%M:%S.%fZ') sortedjobs = sorted(jobs, key=format_date) sys.stdout.write(' {0:<32} {1:<24} {2:<9} {3}\n' .format('id', 'creationDate', 'status', 'backend')) sys.stdout.write('{:-^94}\n'.format("")) for job in sortedjobs[-5:]: sys.stdout.write(' {0:<32} {1:<24} {2:<9} {3}\n' .format(job['id'], job['creationDate'], job['status'], job['backend']['name'])) sys.stdout.write('There are {0} jobs on the server\n' .format(len(jobs))) sys.stdout.write('Credits: {0}\n' .format(api.get_my_credits())) sys.stdout.flush() self.backends = self.__qp.available_backends() status = self.__qp.get_backend_status(self.backend) if 'available' in status: if status['available'] is False: return False return True def set_config(self, config=None): ''' set config ''' if config is None: config = {} if 'backend' in config: self.backend = str(config['backend']) if 'local_' in self.backend: self.remote = False else: self.remote = True if 'remote' in config: self.remote = config['remote'] if 'qubits' in config: self.qubits = int(config['qubits']) return True def _progress(self, phasename, text): self.phase.append([str(phasename), str(text)]) text = "Phase {0}: {1}".format(phasename, text) sys.stdout.write("{}\n".format(text)) sys.stdout.flush() def _init_circuit(self): self._progress('1', 'Initialize quantum registers and circuit') qubits = self.qubits quantum_registers = [ {"name": "cin", "size": 1}, {"name": "qa", "size": qubits}, {"name": "qb", "size": qubits}, {"name": "cout", "size": 1} ] classical_registers = [ {"name": "ans", "size": qubits + 1} ] if 'cin' in self.__qp.get_quantum_register_names(): self.__qp.destroy_quantum_registers(quantum_registers) self.__qp.destroy_classical_registers(classical_registers) q_r = self.__qp.create_quantum_registers(quantum_registers) c_r = self.__qp.create_classical_registers(classical_registers) self.__qp.create_circuit("qcirc", q_r, c_r) def _create_circuit_qadd(self): # quantum ripple-carry adder from Cuccaro et al, quant-ph/0410184 def majority(circuit, q_a, q_b, q_c): ''' majority ''' circuit.cx(q_c, q_b) circuit.cx(q_c, q_a) circuit.ccx(q_a, q_b, q_c) def unmaj(circuit, q_a, q_b, q_c): ''' unmajority ''' circuit.ccx(q_a, q_b, q_c) circuit.cx(q_c, q_a) circuit.cx(q_a, q_b) def adder(circuit, c_in, q_a, q_b, c_out, qubits): ''' adder ''' # pylint: disable=too-many-arguments majority(circuit, c_in[0], q_b[0], q_a[0]) for i in range(qubits - 1): majority(circuit, q_a[i], q_b[i + 1], q_a[i + 1]) circuit.cx(q_a[qubits - 1], c_out[0]) for i in range(qubits - 1)[::-1]: unmaj(circuit, q_a[i], q_b[i + 1], q_a[i + 1]) unmaj(circuit, c_in[0], q_b[0], q_a[0]) if 'add' not in self.__qp.get_circuit_names(): [c_in, q_a, q_b, c_out] = map(self.__qp.get_quantum_register, ["cin", "qa", "qb", "cout"]) ans = self.__qp.get_classical_register('ans') qadder = self.__qp.create_circuit("qadd", [c_in, q_a, q_b, c_out], [ans]) adder(qadder, c_in, q_a, q_b, c_out, self.qubits) return 'add' in self.__qp.get_circuit_names() def _create_circuit_qsub(self): circuit_names = self.__qp.get_circuit_names() if 'qsub' not in circuit_names: if 'qadd' not in circuit_names: self._create_circuit_qadd() # subtractor circuit self.__qp.add_circuit('qsub', self.__qp.get_circuit('qadd')) qsubtractor = self.__qp.get_circuit('qsub') qsubtractor.reverse() return 'qsub' in self.__qp.get_circuit_names() def _qadd(self, input_a, input_b=None, subtract=False, observe=False): # pylint: disable=too-many-locals def measure(circuit, q_b, c_out, ans): ''' measure ''' circuit.barrier() for i in range(self.qubits): circuit.measure(q_b[i], ans[i]) circuit.measure(c_out[0], ans[self.qubits]) def char2q(circuit, cbit, qbit): ''' char2q ''' if cbit == '1': circuit.x(qbit) elif cbit == 'H': circuit.h(qbit) self.shots = 5 * (2**self.qubits) def input_state(circuit, input_a, input_b=None): ''' input state ''' input_a = input_a[::-1] for i in range(self.qubits): char2q(circuit, input_a[i], q_a[i]) if input_b is not None: input_b = input_b[::-1] for i in range(self.qubits): char2q(circuit, input_b[i], q_b[i]) def reset_input(circuit, c_in, q_a, c_out): ''' reset input ''' circuit.reset(c_in) circuit.reset(c_out) for i in range(self.qubits): circuit.reset(q_a[i]) # get registers [c_in, q_a, q_b, c_out] = map(self.__qp.get_quantum_register, ["cin", "qa", "qb", "cout"]) ans = self.__qp.get_classical_register('ans') qcirc = self.__qp.get_circuit('qcirc') self._progress('2', 'Define input state ({})' .format('QADD' if subtract is False else 'QSUB')) if input_b is not None: if subtract is True: # subtract input_state(qcirc, input_b, input_a) else: # add input_state(qcirc, input_a, input_b) else: reset_input(qcirc, c_in, q_a, c_out) input_state(qcirc, input_a) self._progress('3', 'Define quantum circuit ({})' .format('QADD' if subtract is False else 'QSUB')) if subtract is True: self._create_circuit_qsub() qcirc.extend(self.__qp.get_circuit('qsub')) else: self._create_circuit_qadd() qcirc.extend(self.__qp.get_circuit('qadd')) if observe is True: measure(qcirc, q_b, c_out, ans) def _qsub(self, input_a, input_b=None, observe=False): self._qadd(input_a, input_b, subtract=True, observe=observe) def _qope(self, input_a, operator, input_b=None, observe=False): if operator == '+': return self._qadd(input_a, input_b, observe=observe) elif operator == '-': return self._qsub(input_a, input_b, observe=observe) return None def _compile(self, name, cross_backend=None, print_qasm=False): self._progress('4', 'Compile quantum circuit') coupling_map = None if cross_backend is not None: backend_conf = self.__qp.get_backend_configuration(cross_backend) coupling_map = backend_conf.get('coupling_map', None) if coupling_map is None: sys.stdout.write('backend: {} coupling_map not found' .format(cross_backend)) qobj = self.__qp.compile([name], backend=self.backend, shots=self.shots, seed=1, coupling_map=coupling_map) if print_qasm is True: sys.stdout.write(self.__qp.get_compiled_qasm(qobj, 'qcirc')) sys.stdout.flush() return qobj def _run(self, qobj): self._progress('5', 'Run quantum circuit (wait for answer)') result = self.__qp.run(qobj, wait=5, timeout=100000) return result def _run_async(self, qobj): ''' _run_async ''' self._progress('5', 'Run quantum circuit') self.wait = True def async_result(result): ''' async call back ''' self.wait = False self.last = self.result_parse(result) self.__qp.run_async(qobj, wait=5, timeout=100000, callback=async_result) def _is_regular_number(self, numstring, base): ''' returns input binary format string or None. ''' if base == 'bin': binstring = numstring elif base == 'dec': if numstring == 'H': binstring = 'H'*self.qubits else: binstring = format(int(numstring), "0{}b".format(self.qubits)) if len(binstring) != self.qubits: return None return binstring def get_seq(self, text, base='dec'): ''' convert seq and check it if text is invalid, return the list of length 0. ''' operators = u'(\\+|\\-)' seq = re.split(operators, text) # length check if len(seq) % 2 == 0 or len(seq) == 1: return [] # regex if base == 'bin': regex = re.compile(r'[01H]+') else: regex = re.compile(r'(^(?!.H)[0-9]+|H)') for i in range(0, len(seq), 2): match = regex.match(seq[i]) if match is None: return [] num = match.group(0) seq[i] = self._is_regular_number(num, base) if seq[i] is None: return [] return seq def result_parse(self, result): ''' result_parse ''' data = result.get_data("qcirc") sys.stdout.write("job id: {0}\n".format(result.get_job_id())) sys.stdout.write("raw result: {0}\n".format(data)) sys.stdout.write("{:=^40}\n".format("answer")) counts = data['counts'] sortedcounts = sorted(counts.items(), key=lambda x: -x[1]) sortedans = [] for count in sortedcounts: if count[0][0] == '1': ans = 'OR' else: ans = str(int(count[0][-self.qubits:], 2)) sortedans.append(ans) sys.stdout.write('Dec: {0:>2} Bin: {1} Count: {2} \n' .format(ans, str(count[0]), str(count[1]))) sys.stdout.write('{0:d} answer{1}\n' .format(len(sortedans), '' if len(sortedans) == 1 else 's')) sys.stdout.write("{:=^40}\n".format("")) if 'time' in data: sys.stdout.write("time: {0:<3} sec\n".format(data['time'])) sys.stdout.write("All process done.\n") sys.stdout.flush() uniqanswer = sorted(set(sortedans), key=sortedans.index) ans = ",".join(uniqanswer) return [str(result), ans] def exec_calc(self, text, base='dec', wait_result=False): ''' exec_calc ''' seq = self.get_seq(text, base) print('QC seq:', seq) if seq == []: return ["Syntax error", None] # fail message fail_msg = None try: self._init_circuit() numbers = seq[0::2] # slice even index i = 1 observe = False for oper in seq[1::2]: # slice odd index if i == len(numbers) - 1: observe = True if i == 1: self._qope(numbers[0], oper, numbers[1], observe=observe) else: self._qope(numbers[i], oper, observe=observe) i = i + 1 qobj = self._compile('qcirc') if wait_result is True: [status, ans] = self.result_parse(self._run(qobj)) else: self._run_async(qobj) [status, ans] = [ 'Wait. Calculating on {0}'.format(self.backend), '...' ] except QISKitError as ex: fail_msg = ('There was an error in the circuit!. Error = {}\n' .format(ex)) except RegisterSizeError as ex: fail_msg = ('Error in the number of registers!. Error = {}\n' .format(ex)) if fail_msg is not None: sys.stdout.write(fail_msg) sys.stdout.flush() return ["FAIL", None] return [status, ans]
class LocalUnitarySimulatorTest(unittest.TestCase): """Test local unitary simulator.""" @classmethod def setUpClass(cls): cls.moduleName = os.path.splitext(__file__)[0] cls.log = logging.getLogger(__name__) cls.log.setLevel(logging.INFO) logFileName = cls.moduleName + '.log' handler = logging.FileHandler(logFileName) handler.setLevel(logging.INFO) log_fmt = ('{}.%(funcName)s:%(levelname)s:%(asctime)s:' ' %(message)s'.format(cls.__name__)) formatter = logging.Formatter(log_fmt) handler.setFormatter(formatter) cls.log.addHandler(handler) def setUp(self): self.seed = 88 self.qasmFileName = os.path.join(qiskit.__path__[0], '../test/python/qasm/example.qasm') self.modulePath = os.path.dirname(__file__) self.qp = QuantumProgram() def tearDown(self): pass def test_unitary_simulator(self): """test generation of circuit unitary""" shots = 1024 self.qp.load_qasm_file(self.qasmFileName, name='example') basis_gates = [] # unroll to base gates unroller = unroll.Unroller( qasm.Qasm(data=self.qp.get_qasm("example")).parse(), unroll.JsonBackend(basis_gates)) circuit = unroller.execute() # if we want to manipulate the circuit, we have to convert it to a dict circuit = json.loads(circuit.decode()) #strip measurements from circuit to avoid warnings circuit['operations'] = [ op for op in circuit['operations'] if op['name'] != 'measure' ] # the simulator is expecting a JSON format, so we need to convert it back to JSON job = {'compiled_circuit': json.dumps(circuit).encode()} # numpy savetxt is currently prints complex numbers in a way # loadtxt can't read. To save file do, # fmtstr=['% .4g%+.4gj' for i in range(numCols)] # np.savetxt('example_unitary_matrix.dat', numpyMatrix, fmt=fmtstr, delimiter=',') expected = np.loadtxt(os.path.join(self.modulePath, 'example_unitary_matrix.dat'), dtype='complex', delimiter=',') result = UnitarySimulator(job).run() self.assertTrue( np.allclose(result['data']['unitary'], expected, rtol=1e-3)) def profile_unitary_simulator(self): """Profile randomly generated circuits. Writes profile results to <this_module>.prof as well as recording to the log file. number of circuits = 100. number of operations/circuit in [1, 40] number of qubits in [1, 5] """ nCircuits = 100 maxDepth = 40 maxQubits = 5 pr = cProfile.Profile() randomCircuits = RandomQasmGenerator(seed=self.seed, maxDepth=maxDepth, maxQubits=maxQubits) randomCircuits.add_circuits(nCircuits, doMeasure=False) self.qp = randomCircuits.getProgram() pr.enable() self.qp.execute(self.qp.get_circuit_names(), backend='local_unitary_simulator') pr.disable() sout = io.StringIO() ps = pstats.Stats(pr, stream=sout).sort_stats('cumulative') self.log.info('------- start profiling UnitarySimulator -----------') ps.print_stats() self.log.info(sout.getvalue()) self.log.info('------- stop profiling UnitarySimulator -----------') sout.close() pr.dump_stats(self.moduleName + '.prof')
class LocalUnitarySimulatorTest(QiskitTestCase): """Test local unitary simulator.""" def setUp(self): self.seed = 88 self.qasm_filename = self._get_resource_path('qasm/example.qasm') self.qp = QuantumProgram() def tearDown(self): pass def test_unitary_simulator(self): """test generation of circuit unitary""" self.qp.load_qasm_file(self.qasm_filename, name='example') basis_gates = [] # unroll to base gates unroller = unroll.Unroller( qasm.Qasm(data=self.qp.get_qasm('example')).parse(), unroll.JsonBackend(basis_gates)) circuit = unroller.execute() # strip measurements from circuit to avoid warnings circuit['operations'] = [op for op in circuit['operations'] if op['name'] != 'measure'] # the simulator is expecting a JSON format, so we need to convert it # back to JSON qobj = { 'id': 'unitary', 'config': { 'max_credits': None, 'shots': 1, 'backend_name': 'local_unitary_simulator_py' }, 'circuits': [ { 'name': 'test', 'compiled_circuit': circuit, 'compiled_circuit_qasm': self.qp.get_qasm('example'), 'config': { 'coupling_map': None, 'basis_gates': None, 'layout': None, 'seed': None } } ] } # numpy.savetxt currently prints complex numbers in a way # loadtxt can't read. To save file do, # fmtstr=['% .4g%+.4gj' for i in range(numCols)] # np.savetxt('example_unitary_matrix.dat', numpyMatrix, fmt=fmtstr, # delimiter=',') expected = np.loadtxt(self._get_resource_path('example_unitary_matrix.dat'), dtype='complex', delimiter=',') q_job = QuantumJob(qobj, backend=UnitarySimulatorPy(), preformatted=True) result = UnitarySimulatorPy().run(q_job).result() self.assertTrue(np.allclose(result.get_unitary('test'), expected, rtol=1e-3)) def test_two_unitary_simulator(self): """test running two circuits This test is similar to one in test_quantumprogram but doesn't use multiprocessing. """ qr = QuantumRegister(2) cr = ClassicalRegister(1) qc1 = QuantumCircuit(qr, cr) qc2 = QuantumCircuit(qr, cr) qc1.h(qr) qc2.cx(qr[0], qr[1]) backend = UnitarySimulatorPy() qobj = compile([qc1, qc2], backend=backend) job = backend.run(QuantumJob(qobj, backend=backend, preformatted=True)) unitary1 = job.result().get_unitary(qc1) unitary2 = job.result().get_unitary(qc2) unitaryreal1 = np.array([[0.5, 0.5, 0.5, 0.5], [0.5, -0.5, 0.5, -0.5], [0.5, 0.5, -0.5, -0.5], [0.5, -0.5, -0.5, 0.5]]) unitaryreal2 = np.array([[1, 0, 0, 0], [0, 0, 0, 1], [0., 0, 1, 0], [0, 1, 0, 0]]) norm1 = np.trace(np.dot(np.transpose(np.conj(unitaryreal1)), unitary1)) norm2 = np.trace(np.dot(np.transpose(np.conj(unitaryreal2)), unitary2)) self.assertAlmostEqual(norm1, 4) self.assertAlmostEqual(norm2, 4) def profile_unitary_simulator(self): """Profile randomly generated circuits. Writes profile results to <this_module>.prof as well as recording to the log file. number of circuits = 100. number of operations/circuit in [1, 40] number of qubits in [1, 5] """ n_circuits = 100 max_depth = 40 max_qubits = 5 pr = cProfile.Profile() random_circuits = RandomQasmGenerator(seed=self.seed, max_depth=max_depth, max_qubits=max_qubits) random_circuits.add_circuits(n_circuits, do_measure=False) self.qp = random_circuits.get_program() pr.enable() self.qp.execute(self.qp.get_circuit_names(), backend=UnitarySimulatorPy()) pr.disable() sout = io.StringIO() ps = pstats.Stats(pr, stream=sout).sort_stats('cumulative') self.log.info('------- start profiling UnitarySimulatorPy -----------') ps.print_stats() self.log.info(sout.getvalue()) self.log.info('------- stop profiling UnitarySimulatorPy -----------') sout.close() pr.dump_stats(self.moduleName + '.prof')
class LocalQasmSimulatorTest(unittest.TestCase): """Test local qasm simulator.""" @classmethod def setUpClass(cls): cls.moduleName = os.path.splitext(__file__)[0] cls.pdf = PdfPages(cls.moduleName + '.pdf') cls.log = logging.getLogger(__name__) cls.log.setLevel(logging.INFO) logFileName = cls.moduleName + '.log' handler = logging.FileHandler(logFileName) handler.setLevel(logging.INFO) log_fmt = ('{}.%(funcName)s:%(levelname)s:%(asctime)s:' ' %(message)s'.format(cls.__name__)) formatter = logging.Formatter(log_fmt) handler.setFormatter(formatter) cls.log.addHandler(handler) @classmethod def tearDownClass(cls): cls.pdf.close() def setUp(self): self.seed = 88 self.qasmFileName = os.path.join(qiskit.__path__[0], '../test/python/qasm/example.qasm') self.qp = QuantumProgram() def tearDown(self): pass def test_qasm_simulator_single_shot(self): """Test single shot run.""" shots = 1 self.qp.load_qasm_file(self.qasmFileName, name='example') basis_gates = [] # unroll to base gates unroller = unroll.Unroller( qasm.Qasm(data=self.qp.get_qasm("example")).parse(), unroll.JsonBackend(basis_gates)) circuit = unroller.execute() config = {'shots': shots, 'seed': self.seed} job = {'compiled_circuit': circuit, 'config': config} result = QasmSimulator(job).run() self.assertEqual(result['status'], 'DONE') def test_qasm_simulator(self): """Test data counts output for single circuit run against reference.""" shots = 1024 self.qp.load_qasm_file(self.qasmFileName, name='example') basis_gates = [] # unroll to base gates unroller = unroll.Unroller( qasm.Qasm(data=self.qp.get_qasm("example")).parse(), unroll.JsonBackend(basis_gates)) circuit = unroller.execute() config = {'shots': shots, 'seed': self.seed} job = {'compiled_circuit': circuit, 'config': config} result = QasmSimulator(job).run() expected = { '100 100': 137, '011 011': 131, '101 101': 117, '111 111': 127, '000 000': 131, '010 010': 141, '110 110': 116, '001 001': 124 } self.assertEqual(result['data']['counts'], expected) def test_if_statement(self): self.log.info('test_if_statement_x') shots = 100 max_qubits = 3 qp = QuantumProgram() qr = qp.create_quantum_register('qr', max_qubits) cr = qp.create_classical_register('cr', max_qubits) circuit = qp.create_circuit('test_if', [qr], [cr]) circuit.x(qr[0]) circuit.x(qr[1]) circuit.measure(qr[0], cr[0]) circuit.measure(qr[1], cr[1]) circuit.x(qr[2]).c_if(cr, 0x3) circuit.measure(qr[0], cr[0]) circuit.measure(qr[1], cr[1]) circuit.measure(qr[2], cr[2]) circuit2 = qp.create_circuit('test_if_case_2', [qr], [cr]) circuit2.x(qr[0]) circuit2.measure(qr[0], cr[0]) circuit2.measure(qr[1], cr[1]) circuit2.x(qr[2]).c_if(cr, 0x3) circuit2.measure(qr[0], cr[0]) circuit2.measure(qr[1], cr[1]) circuit2.measure(qr[2], cr[2]) basis_gates = [] # unroll to base gates unroller = unroll.Unroller( qasm.Qasm(data=qp.get_qasm('test_if')).parse(), unroll.JsonBackend(basis_gates)) ucircuit = unroller.execute() unroller = unroll.Unroller( qasm.Qasm(data=qp.get_qasm('test_if_case_2')).parse(), unroll.JsonBackend(basis_gates)) ucircuit2 = unroller.execute() config = {'shots': shots, 'seed': self.seed} job = {'compiled_circuit': ucircuit, 'config': config} result_if_true = QasmSimulator(job).run() job = {'compiled_circuit': ucircuit2, 'config': config} result_if_false = QasmSimulator(job).run() self.log.info('result_if_true circuit:') self.log.info(circuit.qasm()) self.log.info('result_if_true={0}'.format(result_if_true)) del circuit.data[1] self.log.info('result_if_false circuit:') self.log.info(circuit.qasm()) self.log.info('result_if_false={0}'.format(result_if_false)) self.assertTrue(result_if_true['data']['counts']['111'] == 100) self.assertTrue(result_if_false['data']['counts']['001'] == 100) def test_teleport(self): """test teleportation as in tutorials""" self.log.info('test_teleport') pi = np.pi shots = 1000 qp = QuantumProgram() qr = qp.create_quantum_register('qr', 3) cr0 = qp.create_classical_register('cr0', 1) cr1 = qp.create_classical_register('cr1', 1) cr2 = qp.create_classical_register('cr2', 1) circuit = qp.create_circuit('teleport', [qr], [cr0, cr1, cr2]) circuit.h(qr[1]) circuit.cx(qr[1], qr[2]) circuit.ry(pi / 4, qr[0]) circuit.cx(qr[0], qr[1]) circuit.h(qr[0]) circuit.barrier(qr) circuit.measure(qr[0], cr0[0]) circuit.measure(qr[1], cr1[0]) circuit.z(qr[2]).c_if(cr0, 1) circuit.x(qr[2]).c_if(cr1, 1) circuit.measure(qr[2], cr2[0]) backend = 'local_qasm_simulator' qobj = qp.compile('teleport', backend=backend, shots=shots, seed=self.seed) results = qp.run(qobj) data = results.get_counts('teleport') alice = {} bob = {} alice['00'] = data['0 0 0'] + data['1 0 0'] alice['01'] = data['0 1 0'] + data['1 1 0'] alice['10'] = data['0 0 1'] + data['1 0 1'] alice['11'] = data['0 1 1'] + data['1 1 1'] bob['0'] = data['0 0 0'] + data['0 1 0'] + data['0 0 1'] + data['0 1 1'] bob['1'] = data['1 0 0'] + data['1 1 0'] + data['1 0 1'] + data['1 1 1'] self.log.info('test_telport: circuit:') self.log.info(circuit.qasm()) self.log.info('test_teleport: data {0}'.format(data)) self.log.info('test_teleport: alice {0}'.format(alice)) self.log.info('test_teleport: bob {0}'.format(bob)) alice_ratio = 1 / np.tan(pi / 8)**2 bob_ratio = bob['0'] / float(bob['1']) error = abs(alice_ratio - bob_ratio) / alice_ratio self.log.info('test_teleport: relative error = {0:.4f}'.format(error)) self.assertLess(error, 0.05) def profile_qasm_simulator(self): """Profile randomly generated circuits. Writes profile results to <this_module>.prof as well as recording to the log file. number of circuits = 100. number of operations/circuit in [1, 40] number of qubits in [1, 5] """ seed = 88 shots = 1024 nCircuits = 100 minDepth = 1 maxDepth = 40 minQubits = 1 maxQubits = 5 pr = cProfile.Profile() randomCircuits = RandomQasmGenerator(seed, minQubits=minQubits, maxQubits=maxQubits, minDepth=minDepth, maxDepth=maxDepth) randomCircuits.add_circuits(nCircuits) self.qp = randomCircuits.getProgram() pr.enable() self.qp.execute(self.qp.get_circuit_names(), backend='local_qasm_simulator', shots=shots) pr.disable() sout = io.StringIO() ps = pstats.Stats(pr, stream=sout).sort_stats('cumulative') self.log.info('------- start profiling QasmSimulator -----------') ps.print_stats() self.log.info(sout.getvalue()) self.log.info('------- stop profiling QasmSimulator -----------') sout.close() pr.dump_stats(self.moduleName + '.prof') def profile_nqubit_speed_grow_depth(self): """simulation time vs the number of qubits where the circuit depth is 10x the number of simulated qubits. Also creates a pdf file with this module name showing a plot of the results. Compilation is not included in speed. """ import matplotlib.pyplot as plt from matplotlib.ticker import MaxNLocator qubitRangeMax = 15 nQubitList = range(1, qubitRangeMax + 1) nCircuits = 10 shots = 1024 seed = 88 maxTime = 30 # seconds; timing stops when simulation time exceeds this number fmtStr1 = 'profile_nqubit_speed::nqubits:{0}, backend:{1}, elapsed_time:{2:.2f}' fmtStr2 = 'backend:{0}, circuit:{1}, numOps:{2}, result:{3}' fmtStr3 = 'minDepth={minDepth}, maxDepth={maxDepth}, num circuits={nCircuits}, shots={shots}' backendList = ['local_qasm_simulator', 'local_unitary_simulator'] if shutil.which('qasm_simulator'): backendList.append('local_qasm_cpp_simulator') else: self.log.info( 'profile_nqubit_speed::\"qasm_simulator\" executable not in path...skipping' ) fig = plt.figure(0) plt.clf() ax = fig.add_axes((0.1, 0.25, 0.8, 0.6)) for i, backend in enumerate(backendList): elapsedTime = np.zeros(len(nQubitList)) if backend is 'local_unitary_simulator': doMeasure = False else: doMeasure = True j, timedOut = 0, False while j < qubitRangeMax and not timedOut: nQubits = nQubitList[j] randomCircuits = RandomQasmGenerator(seed, minQubits=nQubits, maxQubits=nQubits, minDepth=nQubits * 10, maxDepth=nQubits * 10) randomCircuits.add_circuits(nCircuits, doMeasure=doMeasure) qp = randomCircuits.getProgram() cnames = qp.get_circuit_names() qobj = qp.compile(cnames, backend=backend, shots=shots, seed=seed) start = time.perf_counter() results = qp.run(qobj) stop = time.perf_counter() elapsedTime[j] = stop - start if elapsedTime[j] > maxTime: timedOut = True self.log.info(fmtStr1.format(nQubits, backend, elapsedTime[j])) if backend is not 'local_unitary_simulator': for name in cnames: self.log.info( fmtStr2.format(backend, name, len(qp.get_circuit(name)), results.get_data(name))) j += 1 ax.xaxis.set_major_locator(MaxNLocator(integer=True)) if backend is 'local_unitary_simulator': ax.plot(nQubitList[:j], elapsedTime[:j], label=backend, marker='o') else: ax.plot(nQubitList[:j], elapsedTime[:j] / shots, label=backend, marker='o') ax.set_yscale('log', basey=10) ax.set_xlabel('number of qubits') ax.set_ylabel('process time/shot') ax.set_title('profile_nqubit_speed_grow_depth') fig.text( 0.1, 0.05, fmtStr3.format(minDepth='10*nQubits', maxDepth='10*nQubits', nCircuits=nCircuits, shots=shots)) ax.legend() self.pdf.savefig(fig) def profile_nqubit_speed_constant_depth(self): """simulation time vs the number of qubits where the circuit depth is fixed at 40. Also creates a pdf file with this module name showing a plot of the results. Compilation is not included in speed. """ import matplotlib.pyplot as plt from matplotlib.ticker import MaxNLocator qubitRangeMax = 15 nQubitList = range(1, qubitRangeMax + 1) maxDepth = 40 minDepth = 40 nCircuits = 10 shots = 1024 seed = 88 maxTime = 30 # seconds; timing stops when simulation time exceeds this number fmtStr1 = 'profile_nqubit_speed::nqubits:{0}, backend:{1}, elapsed_time:{2:.2f}' fmtStr2 = 'backend:{0}, circuit:{1}, numOps:{2}, result:{3}' fmtStr3 = 'minDepth={minDepth}, maxDepth={maxDepth}, num circuits={nCircuits}, shots={shots}' backendList = ['local_qasm_simulator', 'local_unitary_simulator'] if shutil.which('qasm_simulator'): backendList.append('local_qasm_cpp_simulator') else: self.log.info( 'profile_nqubit_speed::\"qasm_simulator\" executable not in path...skipping' ) fig = plt.figure(0) plt.clf() ax = fig.add_axes((0.1, 0.2, 0.8, 0.6)) for i, backend in enumerate(backendList): elapsedTime = np.zeros(len(nQubitList)) if backend is 'local_unitary_simulator': doMeasure = False else: doMeasure = True j, timedOut = 0, False while j < qubitRangeMax and not timedOut: nQubits = nQubitList[j] randomCircuits = RandomQasmGenerator(seed, minQubits=nQubits, maxQubits=nQubits, minDepth=minDepth, maxDepth=maxDepth) randomCircuits.add_circuits(nCircuits, doMeasure=doMeasure) qp = randomCircuits.getProgram() cnames = qp.get_circuit_names() qobj = qp.compile(cnames, backend=backend, shots=shots, seed=seed) start = time.perf_counter() results = qp.run(qobj) stop = time.perf_counter() elapsedTime[j] = stop - start if elapsedTime[j] > maxTime: timedOut = True self.log.info(fmtStr1.format(nQubits, backend, elapsedTime[j])) if backend is not 'local_unitary_simulator': for name in cnames: self.log.info( fmtStr2.format(backend, name, len(qp.get_circuit(name)), results.get_data(name))) j += 1 ax.xaxis.set_major_locator(MaxNLocator(integer=True)) if backend is 'local_unitary_simulator': ax.plot(nQubitList[:j], elapsedTime[:j], label=backend, marker='o') else: ax.plot(nQubitList[:j], elapsedTime[:j] / shots, label=backend, marker='o') ax.set_yscale('log', basey=10) ax.set_xlabel('number of qubits') ax.set_ylabel('process time/shot') ax.set_title('profile_nqubit_speed_constant_depth') fig.text( 0.1, 0.05, fmtStr3.format(minDepth=minDepth, maxDepth=maxDepth, nCircuits=nCircuits, shots=shots)) ax.legend() self.pdf.savefig(fig)
class TestLocalQasmSimulatorPy(QiskitTestCase): """Test local_qasm_simulator_py.""" @classmethod def setUpClass(cls): super().setUpClass() if do_profiling: cls.pdf = PdfPages(cls.moduleName + '.pdf') @classmethod def tearDownClass(cls): if do_profiling: cls.pdf.close() def setUp(self): self.seed = 88 self.qasm_filename = self._get_resource_path('qasm/example.qasm') self.qp = QuantumProgram() self.qp.load_qasm_file(self.qasm_filename, name='example') basis_gates = [] # unroll to base gates unroller = unroll.Unroller( qasm.Qasm(data=self.qp.get_qasm('example')).parse(), unroll.JsonBackend(basis_gates)) circuit = unroller.execute() circuit_config = {'coupling_map': None, 'basis_gates': 'u1,u2,u3,cx,id', 'layout': None, 'seed': self.seed} resources = {'max_credits': 3} self.qobj = {'id': 'test_sim_single_shot', 'config': { 'max_credits': resources['max_credits'], 'shots': 1024, 'backend_name': 'local_qasm_simulator_py', }, 'circuits': [ { 'name': 'test', 'compiled_circuit': circuit, 'compiled_circuit_qasm': None, 'config': circuit_config } ]} self.q_job = QuantumJob(self.qobj, backend=QasmSimulatorPy(), circuit_config=circuit_config, seed=self.seed, resources=resources, preformatted=True) def tearDown(self): pass def test_qasm_simulator_single_shot(self): """Test single shot run.""" shots = 1 self.qobj['config']['shots'] = shots result = QasmSimulatorPy().run(self.q_job).result() self.assertEqual(result.get_status(), 'COMPLETED') def test_qasm_simulator(self): """Test data counts output for single circuit run against reference.""" result = QasmSimulatorPy().run(self.q_job).result() shots = 1024 threshold = 0.04 * shots counts = result.get_counts('test') target = {'100 100': shots / 8, '011 011': shots / 8, '101 101': shots / 8, '111 111': shots / 8, '000 000': shots / 8, '010 010': shots / 8, '110 110': shots / 8, '001 001': shots / 8} self.assertDictAlmostEqual(counts, target, threshold) def test_if_statement(self): self.log.info('test_if_statement_x') shots = 100 max_qubits = 3 qp = QuantumProgram() qr = qp.create_quantum_register('qr', max_qubits) cr = qp.create_classical_register('cr', max_qubits) circuit_if_true = qp.create_circuit('test_if_true', [qr], [cr]) circuit_if_true.x(qr[0]) circuit_if_true.x(qr[1]) circuit_if_true.measure(qr[0], cr[0]) circuit_if_true.measure(qr[1], cr[1]) circuit_if_true.x(qr[2]).c_if(cr, 0x3) circuit_if_true.measure(qr[0], cr[0]) circuit_if_true.measure(qr[1], cr[1]) circuit_if_true.measure(qr[2], cr[2]) circuit_if_false = qp.create_circuit('test_if_false', [qr], [cr]) circuit_if_false.x(qr[0]) circuit_if_false.measure(qr[0], cr[0]) circuit_if_false.measure(qr[1], cr[1]) circuit_if_false.x(qr[2]).c_if(cr, 0x3) circuit_if_false.measure(qr[0], cr[0]) circuit_if_false.measure(qr[1], cr[1]) circuit_if_false.measure(qr[2], cr[2]) basis_gates = [] # unroll to base gates unroller = unroll.Unroller( qasm.Qasm(data=qp.get_qasm('test_if_true')).parse(), unroll.JsonBackend(basis_gates)) ucircuit_true = unroller.execute() unroller = unroll.Unroller( qasm.Qasm(data=qp.get_qasm('test_if_false')).parse(), unroll.JsonBackend(basis_gates)) ucircuit_false = unroller.execute() qobj = { 'id': 'test_if_qobj', 'config': { 'max_credits': 3, 'shots': shots, 'backend_name': 'local_qasm_simulator_py', }, 'circuits': [ { 'name': 'test_if_true', 'compiled_circuit': ucircuit_true, 'compiled_circuit_qasm': None, 'config': { 'coupling_map': None, 'basis_gates': 'u1,u2,u3,cx,id', 'layout': None, 'seed': None } }, { 'name': 'test_if_false', 'compiled_circuit': ucircuit_false, 'compiled_circuit_qasm': None, 'config': { 'coupling_map': None, 'basis_gates': 'u1,u2,u3,cx,id', 'layout': None, 'seed': None } } ] } q_job = QuantumJob(qobj, backend=QasmSimulatorPy(), preformatted=True) result = QasmSimulatorPy().run(q_job).result() result_if_true = result.get_data('test_if_true') self.log.info('result_if_true circuit:') self.log.info(circuit_if_true.qasm()) self.log.info('result_if_true=%s', result_if_true) result_if_false = result.get_data('test_if_false') self.log.info('result_if_false circuit:') self.log.info(circuit_if_false.qasm()) self.log.info('result_if_false=%s', result_if_false) self.assertTrue(result_if_true['counts']['111'] == 100) self.assertTrue(result_if_false['counts']['001'] == 100) @unittest.skipIf(version_info.minor == 5, "Due to gate ordering issues with Python 3.5 \ we have to disable this test until fixed") def test_teleport(self): """test teleportation as in tutorials""" self.log.info('test_teleport') pi = np.pi shots = 1000 qp = QuantumProgram() qr = qp.create_quantum_register('qr', 3) cr0 = qp.create_classical_register('cr0', 1) cr1 = qp.create_classical_register('cr1', 1) cr2 = qp.create_classical_register('cr2', 1) circuit = qp.create_circuit('teleport', [qr], [cr0, cr1, cr2]) circuit.h(qr[1]) circuit.cx(qr[1], qr[2]) circuit.ry(pi/4, qr[0]) circuit.cx(qr[0], qr[1]) circuit.h(qr[0]) circuit.barrier(qr) circuit.measure(qr[0], cr0[0]) circuit.measure(qr[1], cr1[0]) circuit.z(qr[2]).c_if(cr0, 1) circuit.x(qr[2]).c_if(cr1, 1) circuit.measure(qr[2], cr2[0]) backend = 'local_qasm_simulator_py' qobj = qp.compile('teleport', backend=backend, shots=shots, seed=self.seed) results = qp.run(qobj) data = results.get_counts('teleport') alice = {} bob = {} alice['00'] = data['0 0 0'] + data['1 0 0'] alice['01'] = data['0 1 0'] + data['1 1 0'] alice['10'] = data['0 0 1'] + data['1 0 1'] alice['11'] = data['0 1 1'] + data['1 1 1'] bob['0'] = data['0 0 0'] + data['0 1 0'] + data['0 0 1'] + data['0 1 1'] bob['1'] = data['1 0 0'] + data['1 1 0'] + data['1 0 1'] + data['1 1 1'] self.log.info('test_telport: circuit:') self.log.info(circuit.qasm()) self.log.info('test_teleport: data %s', data) self.log.info('test_teleport: alice %s', alice) self.log.info('test_teleport: bob %s', bob) alice_ratio = 1/np.tan(pi/8)**2 bob_ratio = bob['0']/float(bob['1']) error = abs(alice_ratio - bob_ratio) / alice_ratio self.log.info('test_teleport: relative error = %s', error) self.assertLess(error, 0.05) @unittest.skipIf(not do_profiling, "skipping simulator profiling.") def profile_qasm_simulator(self): """Profile randomly generated circuits. Writes profile results to <this_module>.prof as well as recording to the log file. number of circuits = 100. number of operations/circuit in [1, 40] number of qubits in [1, 5] """ seed = 88 shots = 1024 n_circuits = 100 min_depth = 1 max_depth = 40 min_qubits = 1 max_qubits = 5 pr = cProfile.Profile() random_circuits = RandomQasmGenerator(seed, min_qubits=min_qubits, max_qubits=max_qubits, min_depth=min_depth, max_depth=max_depth) random_circuits.add_circuits(n_circuits) self.qp = random_circuits.get_program() pr.enable() self.qp.execute(self.qp.get_circuit_names(), backend='local_qasm_simulator_py', shots=shots) pr.disable() sout = io.StringIO() ps = pstats.Stats(pr, stream=sout).sort_stats('cumulative') self.log.info('------- start profiling QasmSimulatorPy -----------') ps.print_stats() self.log.info(sout.getvalue()) self.log.info('------- stop profiling QasmSimulatorPy -----------') sout.close() pr.dump_stats(self.moduleName + '.prof') @unittest.skipIf(not do_profiling, "skipping simulator profiling.") def profile_nqubit_speed_grow_depth(self): """simulation time vs the number of qubits where the circuit depth is 10x the number of simulated qubits. Also creates a pdf file with this module name showing a plot of the results. Compilation is not included in speed. """ import matplotlib.pyplot as plt from matplotlib.ticker import MaxNLocator qubit_range_max = 15 n_qubit_list = range(1, qubit_range_max + 1) n_circuits = 10 shots = 1024 seed = 88 max_time = 30 # seconds; timing stops when simulation time exceeds this number fmt_str1 = 'profile_nqubit_speed::nqubits:{0}, backend:{1}, elapsed_time:{2:.2f}' fmt_str2 = 'backend:{0}, circuit:{1}, numOps:{2}, result:{3}' fmt_str3 = 'minDepth={minDepth}, maxDepth={maxDepth}, num circuits={nCircuits},' \ 'shots={shots}' backend_list = ['local_qasm_simulator_py', 'local_unitary_simulator_py'] if shutil.which('qasm_simulator'): backend_list.append('local_qasm_simulator_cpp') else: self.log.info('profile_nqubit_speed::\"qasm_simulator\" executable' 'not in path...skipping') fig = plt.figure(0) plt.clf() ax = fig.add_axes((0.1, 0.25, 0.8, 0.6)) for _, backend in enumerate(backend_list): elapsed_time = np.zeros(len(n_qubit_list)) if backend == 'local_unitary_simulator_py': do_measure = False else: do_measure = True j, timed_out = 0, False while j < qubit_range_max and not timed_out: n_qubits = n_qubit_list[j] random_circuits = RandomQasmGenerator(seed, min_qubits=n_qubits, max_qubits=n_qubits, min_depth=n_qubits * 10, max_depth=n_qubits * 10) random_circuits.add_circuits(n_circuits, do_measure=do_measure) qp = random_circuits.get_program() c_names = qp.get_circuit_names() qobj = qp.compile(c_names, backend=backend, shots=shots, seed=seed) start = time.perf_counter() results = qp.run(qobj) stop = time.perf_counter() elapsed_time[j] = stop - start if elapsed_time[j] > max_time: timed_out = True self.log.info(fmt_str1.format(n_qubits, backend, elapsed_time[j])) if backend != 'local_unitary_simulator_py': for name in c_names: log_str = fmt_str2.format( backend, name, len(qp.get_circuit(name)), results.get_data(name)) self.log.info(log_str) j += 1 ax.xaxis.set_major_locator(MaxNLocator(integer=True)) if backend == 'local_unitary_simulator_py': ax.plot(n_qubit_list[:j], elapsed_time[:j], label=backend, marker='o') else: ax.plot(n_qubit_list[:j], elapsed_time[:j]/shots, label=backend, marker='o') ax.set_yscale('log', basey=10) ax.set_xlabel('number of qubits') ax.set_ylabel('process time/shot') ax.set_title('profile_nqubit_speed_grow_depth') fig.text(0.1, 0.05, fmt_str3.format(minDepth='10*nQubits', maxDepth='10*nQubits', nCircuits=n_circuits, shots=shots)) ax.legend() self.pdf.savefig(fig) @unittest.skipIf(not do_profiling, "skipping simulator profiling.") def profile_nqubit_speed_constant_depth(self): """simulation time vs the number of qubits where the circuit depth is fixed at 40. Also creates a pdf file with this module name showing a plot of the results. Compilation is not included in speed. """ import matplotlib.pyplot as plt from matplotlib.ticker import MaxNLocator qubit_range_max = 15 n_qubit_list = range(1, qubit_range_max + 1) max_depth = 40 min_depth = 40 n_circuits = 10 shots = 1024 seed = 88 max_time = 30 # seconds; timing stops when simulation time exceeds this number fmt_str1 = 'profile_nqubit_speed::nqubits:{0}, backend:{1},' \ 'elapsed_time:{2:.2f}' fmt_str2 = 'backend:{0}, circuit:{1}, numOps:{2}, result:{3}' fmt_str3 = 'minDepth={minDepth}, maxDepth={maxDepth},' \ 'num circuits={nCircuits}, shots={shots}' backend_list = ['local_qasm_simulator_py', 'local_unitary_simulator_py'] if shutil.which('qasm_simulator'): backend_list.append('local_qasm_simulator_cpp') else: self.log.info('profile_nqubit_speed::\"qasm_simulator\" executable' 'not in path...skipping') fig = plt.figure(0) plt.clf() ax = fig.add_axes((0.1, 0.2, 0.8, 0.6)) for _, backend in enumerate(backend_list): elapsedTime = np.zeros(len(n_qubit_list)) if backend == 'local_unitary_simulator_py': doMeasure = False else: doMeasure = True j, timedOut = 0, False while j < qubit_range_max and not timedOut: nQubits = n_qubit_list[j] randomCircuits = RandomQasmGenerator(seed, min_qubits=nQubits, max_qubits=nQubits, min_depth=min_depth, max_depth=max_depth) randomCircuits.add_circuits(n_circuits, do_measure=doMeasure) qp = randomCircuits.get_program() cnames = qp.get_circuit_names() qobj = qp.compile(cnames, backend=backend, shots=shots, seed=seed) start = time.perf_counter() results = qp.run(qobj) stop = time.perf_counter() elapsedTime[j] = stop - start if elapsedTime[j] > max_time: timedOut = True self.log.info(fmt_str1.format(nQubits, backend, elapsedTime[j])) if backend != 'local_unitary_simulator_py': for name in cnames: log_str = fmt_str2.format( backend, name, len(qp.get_circuit(name)), results.get_data(name)) self.log.info(log_str) j += 1 ax.xaxis.set_major_locator(MaxNLocator(integer=True)) if backend == 'local_unitary_simulator_py': ax.plot(n_qubit_list[:j], elapsedTime[:j], label=backend, marker='o') else: ax.plot(n_qubit_list[:j], elapsedTime[:j]/shots, label=backend, marker='o') ax.set_yscale('log', basey=10) ax.set_xlabel('number of qubits') ax.set_ylabel('process time/shot') ax.set_title('profile_nqubit_speed_constant_depth') fig.text(0.1, 0.05, fmt_str3.format(minDepth=min_depth, maxDepth=max_depth, nCircuits=n_circuits, shots=shots)) ax.legend() self.pdf.savefig(fig)
class LocalUnitarySimulatorTest(QiskitTestCase): """Test local unitary simulator.""" def setUp(self): self.seed = 88 self.qasm_filename = self._get_resource_path('qasm/example.qasm') self.qp = QuantumProgram() def tearDown(self): pass def test_unitary_simulator(self): """test generation of circuit unitary""" self.qp.load_qasm_file(self.qasm_filename, name='example') basis_gates = [] # unroll to base gates unroller = unroll.Unroller( qasm.Qasm(data=self.qp.get_qasm('example')).parse(), unroll.JsonBackend(basis_gates)) circuit = unroller.execute() # strip measurements from circuit to avoid warnings circuit['operations'] = [ op for op in circuit['operations'] if op['name'] != 'measure' ] # the simulator is expecting a JSON format, so we need to convert it # back to JSON qobj = { 'id': 'unitary', 'config': { 'max_credits': None, 'shots': 1, 'backend_name': 'local_unitary_simulator_py' }, 'circuits': [{ 'name': 'test', 'compiled_circuit': circuit, 'compiled_circuit_qasm': self.qp.get_qasm('example'), 'config': { 'coupling_map': None, 'basis_gates': None, 'layout': None, 'seed': None } }] } # numpy.savetxt currently prints complex numbers in a way # loadtxt can't read. To save file do, # fmtstr=['% .4g%+.4gj' for i in range(numCols)] # np.savetxt('example_unitary_matrix.dat', numpyMatrix, fmt=fmtstr, # delimiter=',') expected = np.loadtxt( self._get_resource_path('example_unitary_matrix.dat'), dtype='complex', delimiter=',') q_job = QuantumJob(qobj, backend=UnitarySimulatorPy(), preformatted=True) result = UnitarySimulatorPy().run(q_job).result() self.assertTrue( np.allclose(result.get_unitary('test'), expected, rtol=1e-3)) def test_two_unitary_simulator(self): """test running two circuits This test is similar to one in test_quantumprogram but doesn't use multiprocessing. """ qr = QuantumRegister(2) cr = ClassicalRegister(1) qc1 = QuantumCircuit(qr, cr) qc2 = QuantumCircuit(qr, cr) qc1.h(qr) qc2.cx(qr[0], qr[1]) backend = UnitarySimulatorPy() qobj = compile([qc1, qc2], backend=backend) job = backend.run(QuantumJob(qobj, backend=backend, preformatted=True)) unitary1 = job.result().get_unitary(qc1) unitary2 = job.result().get_unitary(qc2) unitaryreal1 = np.array([[0.5, 0.5, 0.5, 0.5], [0.5, -0.5, 0.5, -0.5], [0.5, 0.5, -0.5, -0.5], [0.5, -0.5, -0.5, 0.5]]) unitaryreal2 = np.array([[1, 0, 0, 0], [0, 0, 0, 1], [0., 0, 1, 0], [0, 1, 0, 0]]) norm1 = np.trace(np.dot(np.transpose(np.conj(unitaryreal1)), unitary1)) norm2 = np.trace(np.dot(np.transpose(np.conj(unitaryreal2)), unitary2)) self.assertAlmostEqual(norm1, 4) self.assertAlmostEqual(norm2, 4) def profile_unitary_simulator(self): """Profile randomly generated circuits. Writes profile results to <this_module>.prof as well as recording to the log file. number of circuits = 100. number of operations/circuit in [1, 40] number of qubits in [1, 5] """ n_circuits = 100 max_depth = 40 max_qubits = 5 pr = cProfile.Profile() random_circuits = RandomQasmGenerator(seed=self.seed, max_depth=max_depth, max_qubits=max_qubits) random_circuits.add_circuits(n_circuits, do_measure=False) self.qp = random_circuits.get_program() pr.enable() self.qp.execute(self.qp.get_circuit_names(), backend=UnitarySimulatorPy()) pr.disable() sout = io.StringIO() ps = pstats.Stats(pr, stream=sout).sort_stats('cumulative') self.log.info('------- start profiling UnitarySimulatorPy -----------') ps.print_stats() self.log.info(sout.getvalue()) self.log.info('------- stop profiling UnitarySimulatorPy -----------') sout.close() pr.dump_stats(self.moduleName + '.prof')
class LocalUnitarySimulatorTest(QiskitTestCase): """Test local unitary simulator.""" def setUp(self): self.seed = 88 self.qasmFileName = self._get_resource_path('qasm/example.qasm') self.qp = QuantumProgram() def tearDown(self): pass def test_unitary_simulator(self): """test generation of circuit unitary""" shots = 1024 self.qp.load_qasm_file(self.qasmFileName, name='example') basis_gates = [] # unroll to base gates unroller = unroll.Unroller( qasm.Qasm(data=self.qp.get_qasm('example')).parse(), unroll.JsonBackend(basis_gates)) circuit = unroller.execute() #strip measurements from circuit to avoid warnings circuit['operations'] = [ op for op in circuit['operations'] if op['name'] != 'measure' ] # the simulator is expecting a JSON format, so we need to convert it back to JSON qobj = { 'id': 'unitary', 'config': { 'max_credits': None, 'shots': 1, 'backend': 'local_unitary_simulator' }, 'circuits': [{ 'name': 'test', 'compiled_circuit': circuit, 'compiled_circuit_qasm': self.qp.get_qasm('example'), 'config': { 'coupling_map': None, 'basis_gates': None, 'layout': None, 'seed': None } }] } # numpy.savetxt currently prints complex numbers in a way # loadtxt can't read. To save file do, # fmtstr=['% .4g%+.4gj' for i in range(numCols)] # np.savetxt('example_unitary_matrix.dat', numpyMatrix, fmt=fmtstr, delimiter=',') expected = np.loadtxt( self._get_resource_path('example_unitary_matrix.dat'), dtype='complex', delimiter=',') result = UnitarySimulator(qobj).run() self.assertTrue( np.allclose(result.get_data('test')['unitary'], expected, rtol=1e-3)) def profile_unitary_simulator(self): """Profile randomly generated circuits. Writes profile results to <this_module>.prof as well as recording to the log file. number of circuits = 100. number of operations/circuit in [1, 40] number of qubits in [1, 5] """ nCircuits = 100 maxDepth = 40 maxQubits = 5 pr = cProfile.Profile() randomCircuits = RandomQasmGenerator(seed=self.seed, maxDepth=maxDepth, maxQubits=maxQubits) randomCircuits.add_circuits(nCircuits, doMeasure=False) self.qp = randomCircuits.getProgram() pr.enable() self.qp.execute(self.qp.get_circuit_names(), backend='local_unitary_simulator') pr.disable() sout = io.StringIO() ps = pstats.Stats(pr, stream=sout).sort_stats('cumulative') self.log.info('------- start profiling UnitarySimulator -----------') ps.print_stats() self.log.info(sout.getvalue()) self.log.info('------- stop profiling UnitarySimulator -----------') sout.close() pr.dump_stats(self.moduleName + '.prof')