Commit 2a8dc15e authored by Nguyen, Thien Minh's avatar Nguyen, Thien Minh
Browse files

Merge branch 'master' into tnguyen/pyxasm-ftqc

parents dd66b37b 9bfb12ae
Loading
Loading
Loading
Loading

examples/README.md

0 → 100644
+35 −0
Original line number Diff line number Diff line
Here we show a few examples of QCOR programs. These exampls highlight many aspects of the API and show how typical QCOR programs are formed. To run these, simply navigate to the desired directory and execute the `in_file.cpp` with `qcor -o out_file -qpu [qpu-name] in_file.cpp`.

`adapt/` examples using the [adaptive VQE algorithm](https://arxiv.org/abs/1911.10205).

`adder/` implementations for addition of classical numbers on QPUs.

`adjoint_test/` showcases QCOR's `adjoint` functionality, which maps a quantum kernel to its Hermitian conjugate. 

`bell/` contains examples generating the bell state on quantum computer. Highlights multi-kernel, multi-qreg use cases. 

`deuteron/` contains examples solving the ground state of the Deuteron Hamiltonian using hybrid, variational methods. Contains example for operator exponentiation.

`error_mitigation/` examples employing error mitigation strategies.

`ftqc_qrt/` contains various fault tolerant quantum computation routines employing error correction methods. Replies on QCOR quantum runtime (qrt) library. Compile with `qcor -qpu aer[noise-model:<noise.json>] -qrt ftqc [ftqc_qrt_file].cpp `. 

`grover/` contains an implementation of [Grover's algorithm](https://en.wikipedia.org/wiki/Grover%27s_algorithm) and a `.qasm` file for the Grover 5 qubit kernel. 

`hadamard_test/` shows examples of kernel composition with 'Hadamard' and 'X' gate kernels.

`hybrid/` highlights quantum-classical computation tasks in QCOR, such as VQE, QAOA, and ADAPT.

`placement/` contains examples highlighting user controls for mapping logical qubits to physical qubits on an accelerator.

`qaoa/` examples for the [Quantum Approximate Optimization Algorithm](https://arxiv.org/abs/1411.4028). Includes an example for the `arg_translation` functor for mapping results from an optimizer to the arguments for the kernel function.

`qjit/` highlights "just in time" compilation capabilities of QCOR. 

`qpe/` showcases examples for [quantum phase estimation](https://en.wikipedia.org/wiki/Quantum_phase_estimation_algorithm) algorithm. Files Requiring quantum runtime library (qrt), compile with: `qcor -o qpe -qpu qpp -shots 1024 -qrt qpe_example_qrt.cpp`

`qsim/` a suite of examples employing the "Quantum Simulation Model" with qcor.  

`simple/` highlights core features and functionality of QCOR programs running straightforward quantum computing schemes. Reccomended starting point for new users. 

`unitary/` examples mapping a unitary matrix to its quantum circuit representation. 
 No newline at end of file
+19 −0
Original line number Diff line number Diff line
Employing the QCOR just-in-time (qjit) compilation features, we can wrap QCOR in Python bindings. Here we give examples of how this is used.

`bell.py` gives a straightforward implementation of the bell state on a quantum computer. A good first example for new users.

`exp_i_theta.py` highlights operator exponentiation in qcor.

`multiple_kernel.py` shows how one might solve a problem using multiple quantum kernels. Shows kernel composition functionality.
 
`openfermion_integration.py` shows interop capabilities of [openFermion](https://github.com/quantumlib/OpenFermion) with QCOR. Shows how an `openFermion` `FermionOperator` can be used as a `qcor` `Operator` for variational problems.   

`qaoa_circuit.py` shows an implementation of the Quantum Approximate Eigensolver circuit and args translation functor in Python.

`qsim_example.py`shows workflow of quantum simulation (qsim) routines in qcor.

`qsim_vqe.py` qsim example of VQE routine for Deuteron Hamiltonian.

`vqe_qcor_spec.py` example of VQE using `taskInitiate` for asynchronous execution of quantum-classical hybrid computations. 

`pyscf_qubit_tapering.py` example of using the QCOR `OperatorTransform`, specifically running [Qubit Tapering](https://arxiv.org/abs/1701.08213) followed by VQE using the QSim library.
 No newline at end of file
+28 −0
Original line number Diff line number Diff line
from qcor import *

# Create the H2 hamiltonian with Pyscf
H = createOperator('pyscf', {'basis': 'sto-3g', 'geometry': 'H  0.000000   0.0      0.0\nH   0.0        0.0  .7474'})
print('\nOriginal:\n', H.toString())

# Run the Qubit Tapering Observable Transform
H_tapered = operatorTransform('qubit-tapering', H)
print('\nTapered:\n', H_tapered)

# Define a simple 1 qubit ansatz
@qjit
def ansatz(q : qreg, phi : float, theta : float):
    Rx(q[0], phi)
    Ry(q[0], theta)

# Create the problem model, provide the state 
# prep circuit, Hamiltonian and note variational parameters 
num_params = 2
problemModel = qsim.ModelBuilder.createModel(ansatz, H_tapered, 2)

# Create the VQE workflow
workflow = qsim.getWorkflow('vqe')

# Execute and print the result
result = workflow.execute(problemModel)
energy = result['energy']
print(energy)
 No newline at end of file
+46 −3
Original line number Diff line number Diff line
@@ -421,7 +421,13 @@ PYBIND11_MODULE(_pyqcor, m) {
  py::class_<qcor::QJIT, std::shared_ptr<qcor::QJIT>>(m, "QJIT", "")
      .def(py::init<>(), "")
      .def("write_cache", &qcor::QJIT::write_cache, "")
      .def("jit_compile", &qcor::QJIT::jit_compile, "")
      .def(
          "jit_compile",
          [](qcor::QJIT &qjit, const std::string src) {
            bool turn_on_hetmap_kernel_ctor = true;
            qjit.jit_compile(src, turn_on_hetmap_kernel_ctor, {});
          },
          "")
      .def(
          "internal_python_jit_compile",
          [](qcor::QJIT &qjit, const std::string src,
@@ -430,7 +436,12 @@ PYBIND11_MODULE(_pyqcor, m) {
            qjit.jit_compile(src, turn_on_hetmap_kernel_ctor, dependency);
          },
          "")
      .def("run_syntax_handler", &qcor::QJIT::run_syntax_handler, "")
      .def(
          "run_syntax_handler",
          [](qcor::QJIT &qjit, const std::string src) {
            return qjit.run_syntax_handler(src, true);
          },
          "")
      .def(
          "invoke",
          [](qcor::QJIT &qjit, const std::string name, KernelArgDict args) {
@@ -523,7 +534,7 @@ PYBIND11_MODULE(_pyqcor, m) {
  m.def(
      "createOperator",
      [](const std::string &type, const std::string &repr) {
        return qcor::createOperator(type, repr);
        auto op = qcor::createOperator(type, repr);
      },
      "");
  m.def(
@@ -550,6 +561,12 @@ PYBIND11_MODULE(_pyqcor, m) {
      },
      "");

  m.def(
      "operatorTransform",
      [](const std::string &type, std::shared_ptr<Observable> obs) {
        return qcor::operatorTransform(type, obs);
      },
      "");
  m.def(
      "internal_observe",
      [](std::shared_ptr<CompositeInstruction> kernel,
@@ -615,6 +632,32 @@ PYBIND11_MODULE(_pyqcor, m) {
              model.user_defined_ansatz = kernel_functor;
              return std::move(model);
            },
            "")
        .def(
            "createModel",
            [](py::object py_kernel, std::shared_ptr<Observable> &obs,
               const int n_params) {
              qcor::qsim::QuantumSimulationModel model;
              auto nq = obs->nBits();
              auto kernel_functor = std::make_shared<qcor::PyKernelFunctor>(
                  py_kernel, nq, n_params);
              model.observable = obs.get();
              model.user_defined_ansatz = kernel_functor;
              return std::move(model);
            },
            "")

        .def(
            "createModel",
            [](py::object py_kernel, std::shared_ptr<Observable> &obs,
               const int n_qubits, const int n_params) {
              qcor::qsim::QuantumSimulationModel model;
              auto kernel_functor = std::make_shared<qcor::PyKernelFunctor>(
                  py_kernel, n_qubits, n_params);
              model.observable = obs.get();
              model.user_defined_ansatz = kernel_functor;
              return std::move(model);
            },
            "");

    // CostFunctionEvaluator bindings
+12 −8
Original line number Diff line number Diff line
@@ -262,16 +262,20 @@ class qjit(object):
        argument variable should point to x[0], for example. 
        """

        if [str(x) for x in self.type_annotations.values()] == ['<class \'_pyqcor.qreg\'>', '<class \'float\'>']:
            ret_dict = {}
            for arg_name, _type in self.type_annotations.items():
                if str(_type) == '<class \'_pyqcor.qreg\'>':
                    ret_dict[arg_name] = q
                elif str(_type) == '<class \'float\'>':
                    ret_dict[arg_name] = x[0]
        # Local vars used to figure out if we have 
        # arg structures that look like (qreg, float...)
        type_annots_list = [str(self.type_annotations[x]) for x in self.arg_names]
        default_float_args = ['<class \'float\'>']
        intersection = list(set(type_annots_list[1:]) & set(default_float_args) ) 

        if intersection == default_float_args:
            # This handles all (qreg, float...)
            ret_dict = {self.arg_names[0]:q}
            for i, arg_name in enumerate(self.arg_names[1:]):
                ret_dict[arg_name] = x[i]
            if len(ret_dict) != len(self.type_annotations):
                print(
                    'Error, could not translate vector parameters x into arguments for quantum kernel.')
                    'Error, could not translate vector parameters x into arguments for quantum kernel. ', len(ret_dict), len(self.type_annotations))
                exit(1)
            return ret_dict
        elif [str(x) for x in self.type_annotations.values()] == ['<class \'_pyqcor.qreg\'>', 'typing.List[float]']: