Loading python/qcor.in.py +25 −13 Original line number Diff line number Diff line Loading @@ -33,6 +33,15 @@ FermionOperator = xacc.quantum.FermionOperator FLOAT_REF = typing.NewType('value', float) INT_REF = typing.NewType('value', int) typing_to_simple_map = {'<class \'_pyqcor.qreg\'>': 'qreg', '<class \'float\'>': 'float', 'typing.List[float]': 'List[float]', '<class \'int\'>': 'int', 'typing.List[int]': 'List[int]', '<class \'_pyxacc.quantum.PauliOperator\'>': 'PauliOperator', '<class \'_pyxacc.quantum.FermionOperator\'>': 'FermionOperator', 'typing.List[typing.Tuple[int, int]]': 'List[Tuple[int,int]]', 'typing.List[_pyxacc.quantum.PauliOperator]': 'List[PauliOperator]', 'typing.List[_pyxacc.quantum.FermionOperator]': 'List[FermionOperator]'} # Need to add a few extra header paths # for the clang code-gen mechanism. Mac OS X will # need QCOR_EXTRA_HEADERS, all will need the Loading Loading @@ -723,9 +732,18 @@ class KernelBuilder(object): self.qjit_str += self.TAB+"{} = _internal_python_createObservable(\"{}\", \"{}\")\n".format(op_var_name, op_type, op_str) self.qjit_str += self.TAB+'exp_i_theta({}, {}, {})\n'.format(self.qreg_name, params_str, op_var_name) def invoke(self, kernel_function : qjit): arg_names, _, _, _, _, _, type_annotations = inspect.getfullargspec( kernel_function) args_dict = {k:v for k,v in kernel_function.type_annotations.items() if str(typing_to_simple_map[str(v)]) != 'qreg'} self.kernel_args = {**args_dict, **self.kernel_args} self.qjit_str+= self.TAB+'{}({}, {})\n'.format(kernel_function.kernel_name(), self.qreg_name, ','.join(list(self.kernel_args.keys()))) def from_qasm(self, qasm_str): xacc_ir = xacc.getCompiler('staq').compile(qasm_str).getComposites()[0] pyxasm = xacc.getCompiler('pyxasm').translate(xacc_ir, {'qreg_name':self.qreg_name, 'tab_prepend':self.TAB}) pyxasm = xacc.getCompiler('pyxasm').translate(xacc_ir) pyxasm = pyxasm.replace('__translate_qrg__', self.qreg_name) pyxasm = '\n'.join(self.TAB+line for line in pyxasm.split('\n')) processed_str = pyxasm self.qjit_str += processed_str Loading Loading @@ -776,21 +794,15 @@ class KernelBuilder(object): def create(self): # print(self.qjit_str) allowed_type_map = {'<class \'_pyqcor.qreg\'>': 'qreg', '<class \'float\'>': 'float', 'typing.List[float]': 'List[float]', '<class \'int\'>': 'int', 'typing.List[int]': 'List[int]', '<class \'_pyxacc.quantum.PauliOperator\'>': 'PauliOperator', '<class \'_pyxacc.quantum.FermionOperator\'>': 'FermionOperator', 'typing.List[typing.Tuple[int, int]]': 'List[Tuple[int,int]]', 'typing.List[_pyxacc.quantum.PauliOperator]': 'List[PauliOperator]', 'typing.List[_pyxacc.quantum.FermionOperator]': 'List[FermionOperator]'} kernel_name = '__internal_qjit_kernelbuilder_kernel_'+str(uuid.uuid4()).replace('-','_') if inspect.stack()[-1].code_context is not None: kernel_name = inspect.stack()[-1].code_context[0].split(' = ')[0] for element in inspect.stack(): if len(element.code_context) and element.code_context[0] != None: if '.create()' in element.code_context[0]: kernel_name = element.code_context[0].strip().split(' = ')[0] # FIXME optionally add , if we have kernel_args args_str = 'q : qreg'+ (', ' if len(self.kernel_args) else '') + ', '.join(k+' : '+allowed_type_map[str(v)] for k,v in self.kernel_args.items()) args_str = 'q : qreg'+ (', ' if len(self.kernel_args) else '') + ', '.join(k+' : '+typing_to_simple_map[str(v)] for k,v in self.kernel_args.items()) func = 'def {}({}):\n'.format(kernel_name, args_str)+self.qjit_str # print(func) result = globals() Loading python/tests/CMakeLists.txt +6 −0 Original line number Diff line number Diff line Loading @@ -19,6 +19,12 @@ set_tests_properties(qcor_python_jit_simple #set_tests_properties(qcor_python_jit_nested_kernels # PROPERTIES ENVIRONMENT "PYTHONPATH=${CMAKE_INSTALL_PREFIX}:$ENV{PYTHONPATH}") #add_test (NAME qcor_python_kernel_builder # COMMAND ${Python_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/test_kernel_builder.py # WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) #set_tests_properties(qcor_python_kernel_builder # PROPERTIES ENVIRONMENT "PYTHONPATH=${CMAKE_INSTALL_PREFIX}:$ENV{PYTHONPATH}") add_test (NAME qcor_python_jit_decompose COMMAND ${Python_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/test_jit_decompose.py WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} Loading python/tests/test_kernel_builder.py 0 → 100644 +155 −0 Original line number Diff line number Diff line import unittest from qcor import * class TestKernelBuilder(unittest.TestCase): def test_simple_bell(self): set_qpu('qpp', {'shots':100}) builder = KernelBuilder() builder.h(0) for i in range(5): builder.cnot(i, i+1) builder.measure_all() ghz_6 = builder.create() q = qalloc(6) ghz_6(q) counts = q.counts() print(counts) self.assertTrue('111111' in counts) self.assertTrue('000000' in counts) self.assertTrue(len(counts) == 2) def test_variational_spec(self): set_qpu('qpp') builder = KernelBuilder() builder.x(0) builder.ry(1, 't') builder.cnot(1, 0) ansatz = builder.create() H = -2.1433 * X(0) * X(1) - 2.1433 * \ Y(0) * Y(1) + .21829 * Z(0) - 6.125 * Z(1) + 5.907 n_params = 1 obj = createObjectiveFunction(ansatz, H, n_params) # evaluate at a concrete set of params vqe_energy = obj([.59]) self.assertAlmostEqual(vqe_energy, -1.74, places=1) # Run full optimization optimizer = createOptimizer('nlopt') results = optimizer.optimize(obj) self.assertAlmostEqual(results[0], -1.74, places=1) def test_from_qasm(self): set_qpu('qpp', {'shots':100}) src = '''OPENQASM 2.0; include "qelib1.inc"; qreg q[3]; creg c[3]; h q[0]; cx q[0],q[1]; cx q[1],q[2]; measure q[0] -> c[0]; measure q[1] -> c[1]; measure q[2] -> c[2]; ''' builder = KernelBuilder() builder.from_qasm(src) test_from_qasm = builder.create() q = qalloc(3) test_from_qasm(q) counts = q.counts() self.assertTrue('111' in counts) self.assertTrue('000' in counts) self.assertTrue(len(counts) == 2) # def test_synthesis(self): def test_exp(self): exponent_op = adag(0) * a(1) - adag(1) * a(0) builder = KernelBuilder() builder.x(0) builder.exp('theta', exponent_op) ansatz = builder.create() # Define the hamiltonian H = -2.1433 * X(0) * X(1) - 2.1433 * Y(0) * Y(1) + .21829 * Z(0) - 6.125 * Z(1) + 5.907 # Create the ObjectiveFunction, specify central finite diff gradient obj = createObjectiveFunction(ansatz, H, 1, {'gradient-strategy':'central', 'step':1e-1}) # create the lbfgs optimizer optimizer = createOptimizer('nlopt', {'algorithm':'l-bfgs', 'ftol':1e-3}) results = optimizer.optimize(obj) self.assertAlmostEqual(results[0], -1.74, places=1) def test_synthesis(self): set_qpu('qpp', {'shots':100}) try: import numpy as np except: print('No numpy, cant run test_synthesis') return ccnot = np.eye(8) ccnot[6,6] = 0.0 ccnot[7,7] = 0.0 ccnot[6,7] = 1.0 ccnot[7,6] = 1.0 # Synthesize the CCNOT kernel # using the KernelBuilder builder = KernelBuilder() [builder.x(i) for i in range(3)] builder.synthesize(unitary=ccnot) builder.measure(range(3)) ccnot_circuit = builder.create() q = qalloc(3) ccnot_circuit(q) counts = q.counts() self.assertTrue(len(counts) == 1) self.assertTrue('110' in counts) def test_call_previous_kernels(self): builder = KernelBuilder() builder.x(0) builder.ry(1, 't') builder.cnot(1, 0) ansatz = builder.create() @qjit def x0x1(q : qreg, t:float): ansatz(q, t) H(q[0]) H(q[1]) Measure(q[0]) Measure(q[1]) q = qalloc(2) x0x1(q, 2.2) self.assertAlmostEqual(q.exp_val_z(), .8085, places=1) b = KernelBuilder() b.invoke(ansatz) b.h(0) b.h(1) b.measure_all() test = b.create() q = qalloc(2) test(q, 2.2) self.assertAlmostEqual(q.exp_val_z(), .8085, places=1) if __name__ == '__main__': unittest.main() No newline at end of file Loading
python/qcor.in.py +25 −13 Original line number Diff line number Diff line Loading @@ -33,6 +33,15 @@ FermionOperator = xacc.quantum.FermionOperator FLOAT_REF = typing.NewType('value', float) INT_REF = typing.NewType('value', int) typing_to_simple_map = {'<class \'_pyqcor.qreg\'>': 'qreg', '<class \'float\'>': 'float', 'typing.List[float]': 'List[float]', '<class \'int\'>': 'int', 'typing.List[int]': 'List[int]', '<class \'_pyxacc.quantum.PauliOperator\'>': 'PauliOperator', '<class \'_pyxacc.quantum.FermionOperator\'>': 'FermionOperator', 'typing.List[typing.Tuple[int, int]]': 'List[Tuple[int,int]]', 'typing.List[_pyxacc.quantum.PauliOperator]': 'List[PauliOperator]', 'typing.List[_pyxacc.quantum.FermionOperator]': 'List[FermionOperator]'} # Need to add a few extra header paths # for the clang code-gen mechanism. Mac OS X will # need QCOR_EXTRA_HEADERS, all will need the Loading Loading @@ -723,9 +732,18 @@ class KernelBuilder(object): self.qjit_str += self.TAB+"{} = _internal_python_createObservable(\"{}\", \"{}\")\n".format(op_var_name, op_type, op_str) self.qjit_str += self.TAB+'exp_i_theta({}, {}, {})\n'.format(self.qreg_name, params_str, op_var_name) def invoke(self, kernel_function : qjit): arg_names, _, _, _, _, _, type_annotations = inspect.getfullargspec( kernel_function) args_dict = {k:v for k,v in kernel_function.type_annotations.items() if str(typing_to_simple_map[str(v)]) != 'qreg'} self.kernel_args = {**args_dict, **self.kernel_args} self.qjit_str+= self.TAB+'{}({}, {})\n'.format(kernel_function.kernel_name(), self.qreg_name, ','.join(list(self.kernel_args.keys()))) def from_qasm(self, qasm_str): xacc_ir = xacc.getCompiler('staq').compile(qasm_str).getComposites()[0] pyxasm = xacc.getCompiler('pyxasm').translate(xacc_ir, {'qreg_name':self.qreg_name, 'tab_prepend':self.TAB}) pyxasm = xacc.getCompiler('pyxasm').translate(xacc_ir) pyxasm = pyxasm.replace('__translate_qrg__', self.qreg_name) pyxasm = '\n'.join(self.TAB+line for line in pyxasm.split('\n')) processed_str = pyxasm self.qjit_str += processed_str Loading Loading @@ -776,21 +794,15 @@ class KernelBuilder(object): def create(self): # print(self.qjit_str) allowed_type_map = {'<class \'_pyqcor.qreg\'>': 'qreg', '<class \'float\'>': 'float', 'typing.List[float]': 'List[float]', '<class \'int\'>': 'int', 'typing.List[int]': 'List[int]', '<class \'_pyxacc.quantum.PauliOperator\'>': 'PauliOperator', '<class \'_pyxacc.quantum.FermionOperator\'>': 'FermionOperator', 'typing.List[typing.Tuple[int, int]]': 'List[Tuple[int,int]]', 'typing.List[_pyxacc.quantum.PauliOperator]': 'List[PauliOperator]', 'typing.List[_pyxacc.quantum.FermionOperator]': 'List[FermionOperator]'} kernel_name = '__internal_qjit_kernelbuilder_kernel_'+str(uuid.uuid4()).replace('-','_') if inspect.stack()[-1].code_context is not None: kernel_name = inspect.stack()[-1].code_context[0].split(' = ')[0] for element in inspect.stack(): if len(element.code_context) and element.code_context[0] != None: if '.create()' in element.code_context[0]: kernel_name = element.code_context[0].strip().split(' = ')[0] # FIXME optionally add , if we have kernel_args args_str = 'q : qreg'+ (', ' if len(self.kernel_args) else '') + ', '.join(k+' : '+allowed_type_map[str(v)] for k,v in self.kernel_args.items()) args_str = 'q : qreg'+ (', ' if len(self.kernel_args) else '') + ', '.join(k+' : '+typing_to_simple_map[str(v)] for k,v in self.kernel_args.items()) func = 'def {}({}):\n'.format(kernel_name, args_str)+self.qjit_str # print(func) result = globals() Loading
python/tests/CMakeLists.txt +6 −0 Original line number Diff line number Diff line Loading @@ -19,6 +19,12 @@ set_tests_properties(qcor_python_jit_simple #set_tests_properties(qcor_python_jit_nested_kernels # PROPERTIES ENVIRONMENT "PYTHONPATH=${CMAKE_INSTALL_PREFIX}:$ENV{PYTHONPATH}") #add_test (NAME qcor_python_kernel_builder # COMMAND ${Python_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/test_kernel_builder.py # WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) #set_tests_properties(qcor_python_kernel_builder # PROPERTIES ENVIRONMENT "PYTHONPATH=${CMAKE_INSTALL_PREFIX}:$ENV{PYTHONPATH}") add_test (NAME qcor_python_jit_decompose COMMAND ${Python_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/test_jit_decompose.py WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} Loading
python/tests/test_kernel_builder.py 0 → 100644 +155 −0 Original line number Diff line number Diff line import unittest from qcor import * class TestKernelBuilder(unittest.TestCase): def test_simple_bell(self): set_qpu('qpp', {'shots':100}) builder = KernelBuilder() builder.h(0) for i in range(5): builder.cnot(i, i+1) builder.measure_all() ghz_6 = builder.create() q = qalloc(6) ghz_6(q) counts = q.counts() print(counts) self.assertTrue('111111' in counts) self.assertTrue('000000' in counts) self.assertTrue(len(counts) == 2) def test_variational_spec(self): set_qpu('qpp') builder = KernelBuilder() builder.x(0) builder.ry(1, 't') builder.cnot(1, 0) ansatz = builder.create() H = -2.1433 * X(0) * X(1) - 2.1433 * \ Y(0) * Y(1) + .21829 * Z(0) - 6.125 * Z(1) + 5.907 n_params = 1 obj = createObjectiveFunction(ansatz, H, n_params) # evaluate at a concrete set of params vqe_energy = obj([.59]) self.assertAlmostEqual(vqe_energy, -1.74, places=1) # Run full optimization optimizer = createOptimizer('nlopt') results = optimizer.optimize(obj) self.assertAlmostEqual(results[0], -1.74, places=1) def test_from_qasm(self): set_qpu('qpp', {'shots':100}) src = '''OPENQASM 2.0; include "qelib1.inc"; qreg q[3]; creg c[3]; h q[0]; cx q[0],q[1]; cx q[1],q[2]; measure q[0] -> c[0]; measure q[1] -> c[1]; measure q[2] -> c[2]; ''' builder = KernelBuilder() builder.from_qasm(src) test_from_qasm = builder.create() q = qalloc(3) test_from_qasm(q) counts = q.counts() self.assertTrue('111' in counts) self.assertTrue('000' in counts) self.assertTrue(len(counts) == 2) # def test_synthesis(self): def test_exp(self): exponent_op = adag(0) * a(1) - adag(1) * a(0) builder = KernelBuilder() builder.x(0) builder.exp('theta', exponent_op) ansatz = builder.create() # Define the hamiltonian H = -2.1433 * X(0) * X(1) - 2.1433 * Y(0) * Y(1) + .21829 * Z(0) - 6.125 * Z(1) + 5.907 # Create the ObjectiveFunction, specify central finite diff gradient obj = createObjectiveFunction(ansatz, H, 1, {'gradient-strategy':'central', 'step':1e-1}) # create the lbfgs optimizer optimizer = createOptimizer('nlopt', {'algorithm':'l-bfgs', 'ftol':1e-3}) results = optimizer.optimize(obj) self.assertAlmostEqual(results[0], -1.74, places=1) def test_synthesis(self): set_qpu('qpp', {'shots':100}) try: import numpy as np except: print('No numpy, cant run test_synthesis') return ccnot = np.eye(8) ccnot[6,6] = 0.0 ccnot[7,7] = 0.0 ccnot[6,7] = 1.0 ccnot[7,6] = 1.0 # Synthesize the CCNOT kernel # using the KernelBuilder builder = KernelBuilder() [builder.x(i) for i in range(3)] builder.synthesize(unitary=ccnot) builder.measure(range(3)) ccnot_circuit = builder.create() q = qalloc(3) ccnot_circuit(q) counts = q.counts() self.assertTrue(len(counts) == 1) self.assertTrue('110' in counts) def test_call_previous_kernels(self): builder = KernelBuilder() builder.x(0) builder.ry(1, 't') builder.cnot(1, 0) ansatz = builder.create() @qjit def x0x1(q : qreg, t:float): ansatz(q, t) H(q[0]) H(q[1]) Measure(q[0]) Measure(q[1]) q = qalloc(2) x0x1(q, 2.2) self.assertAlmostEqual(q.exp_val_z(), .8085, places=1) b = KernelBuilder() b.invoke(ansatz) b.h(0) b.h(1) b.measure_all() test = b.create() q = qalloc(2) test(q, 2.2) self.assertAlmostEqual(q.exp_val_z(), .8085, places=1) if __name__ == '__main__': unittest.main() No newline at end of file