Ejemplo n.º 1
0
    def test_mcu1(self, num_controls):
        c = QuantumRegister(num_controls, name='c')
        o = QuantumRegister(1, name='o')
        allsubsets = list(
            chain(*[
                combinations(range(num_controls), ni)
                for ni in range(num_controls + 1)
            ]))
        for subset in allsubsets:
            qc = QuantumCircuit(o, c)
            for idx in subset:
                qc.x(c[idx])
            qc.h(o[0])
            qc.mcu1(pi, [c[i] for i in range(num_controls)], o[0])
            qc.h(o[0])
            for idx in subset:
                qc.x(c[idx])

            vec = np.asarray(
                q_execute(qc, BasicAer.get_backend(
                    'statevector_simulator')).result().get_statevector(
                        qc, decimals=16))
            vec_o = [0, 1] if len(subset) == num_controls else [1, 0]
            # print(vec, np.array(vec_o + [0] * (2 ** (num_controls + num_ancillae + 1) - 2)))
            f = state_fidelity(
                vec, np.array(vec_o + [0] * (2**(num_controls + 1) - 2)))
            self.assertAlmostEqual(f, 1)
Ejemplo n.º 2
0
    def execute(self, circuits):
        """
        A wrapper for all algorithms to interface with quantum backend.

        Args:
            circuits (QuantumCircuit or list[QuantumCircuit]): circuits to execute

        Returns:
            Result or [Result]: Result objects it will be a list if number of circuits
            exceed the maximum number (300)
        """

        if not isinstance(circuits, list):
            circuits = [circuits]
        jobs = []
        chunks = int(np.ceil(len(circuits) / self.MAX_CIRCUITS_PER_JOB))
        for i in range(chunks):
            sub_circuits = circuits[i * self.MAX_CIRCUITS_PER_JOB:(i + 1) *
                                    self.MAX_CIRCUITS_PER_JOB]
            jobs.append(
                q_execute(sub_circuits, self._backend, **self._execute_config))

        if logger.isEnabledFor(logging.DEBUG):
            logger.debug(summarize_circuits(circuits))

        results = []
        for job in jobs:
            results.append(job.result(**self._qjob_config))

        result = functools.reduce(lambda x, y: x + y, results)
        return result
Ejemplo n.º 3
0
 def test_logic_expr_oracle(self, dimacs_str, sols, mct_mode, optimization):
     """ Logic Expr oracle test """
     num_shots = 1024
     leo = LogicalExpressionOracle(dimacs_str,
                                   optimization=optimization,
                                   mct_mode=mct_mode)
     leo_circuit = leo.circuit
     m = ClassicalRegister(1, name='m')
     for assignment in itertools.product([True, False],
                                         repeat=len(leo.variable_register)):
         qc = QuantumCircuit(m, leo.variable_register)
         for idx, t_f in enumerate(assignment):
             if t_f:
                 qc.x(leo.variable_register[idx])
         qc += leo_circuit
         qc.barrier(leo.output_register)
         qc.measure(leo.output_register, m)
         # print(qc.draw(line_length=10000))
         counts = q_execute(qc,
                            BasicAer.get_backend('qasm_simulator'),
                            shots=num_shots).result().get_counts(qc)
         if assignment in sols:
             self.assertEqual(counts['1'], num_shots)
         else:
             self.assertEqual(counts['0'], num_shots)
Ejemplo n.º 4
0
    def test_cnx(self, num_controls, num_ancillae):
        c = QuantumRegister(num_controls, name='c')
        o = QuantumRegister(1, name='o')
        a = QuantumRegister(num_ancillae, name='a')
        allsubsets = list(chain(
            *[combinations(range(num_controls), ni) for ni in range(num_controls + 1)]))
        for subset in allsubsets:
            qc = QuantumCircuit(o, c, a)
            for idx in subset:
                qc.x(c[idx])
            qc.cnx(
                [c[i] for i in range(num_controls)],
                [a[i] for i in range(num_ancillae)],
                o[0]
            )
            for idx in subset:
                qc.x(c[idx])

            vec = np.asarray(q_execute(qc, qiskit.Aer.get_backend(
                'statevector_simulator')).result().get_statevector(qc, decimals=16))
            vec_o = [0, 1] if len(subset) == num_controls else [1, 0]
            np.testing.assert_almost_equal(
                vec,
                np.array(vec_o + [0] *
                         (2 ** (num_controls + num_ancillae + 1) - 2))
            )
Ejemplo n.º 5
0
    def construct_circuit(self, mode, register=None):
        """
        Construct the statevector of desired initial state.

        Args:
            mode (string): `vector` or `circuit`. The `vector` mode produces the vector.
                            While the `circuit` constructs the quantum circuit corresponding that
                            vector.
            register (QuantumRegister): register for circuit construction.

        Returns:
            QuantumCircuit or numpy.ndarray: statevector.

        Raises:
            AquaError: when mode is not 'vector' or 'circuit'.
        """
        if mode == 'vector':
            if self._state_vector is None:
                if self._circuit is not None:
                    self._state_vector = np.asarray(
                        q_execute(
                            self._circuit,
                            BasicAer.get_backend('statevector_simulator')).
                        result().get_statevector(self._circuit))
            return self._state_vector
        elif mode == 'circuit':
            if self._circuit is None:
                if register is None:
                    register = QuantumRegister(self._num_qubits, name='q')

                # create emtpy quantum circuit
                circuit = QuantumCircuit()

                # if register is actually a list of qubits
                if type(register) is list:

                    # loop over all qubits and add the required registers
                    for q in register:
                        if not circuit.has_register(q[0]):
                            circuit.add_register(q[0])
                else:
                    # if an actual register is given, add it
                    circuit.add_register(register)

                if self._state is None or self._state == 'random':
                    svc = StateVectorCircuit(self._state_vector)
                    svc.construct_circuit(circuit, register)
                elif self._state == 'zero':
                    pass
                elif self._state == 'uniform':
                    for i in range(self._num_qubits):
                        circuit.u2(0.0, np.pi, register[i])
                else:
                    pass
                self._circuit = circuit
            return self._circuit.copy()
        else:
            raise AquaError('Mode should be either "vector" or "circuit"')
Ejemplo n.º 6
0
    def construct_circuit(self, mode='circuit', register=None):
        # pylint: disable=import-outside-toplevel
        from qiskit import BasicAer

        if mode == 'vector':
            if self._state_vector is None:
                if self._circuit is not None:
                    self._state_vector = np.asarray(
                        q_execute(
                            self._circuit,
                            BasicAer.get_backend('statevector_simulator')).
                        result().get_statevector(self._circuit))
            return self._state_vector
        elif mode == 'circuit':
            if self._circuit is None:
                # create empty quantum circuit
                circuit = QuantumCircuit()

                if register is None:
                    register = QuantumRegister(self._num_qubits, name='q')

                if isinstance(register, QuantumRegister):
                    circuit.add_register(register)
                elif isinstance(register, list):
                    for q in register:
                        if isinstance(q, Qubit):
                            if not circuit.has_register(q.register):
                                circuit.add_register(q.register)
                        else:
                            raise AquaError('Unexpected qubit type {}.'.format(
                                type(q)))
                else:
                    raise AquaError('Unexpected register type {}.'.format(
                        type(register)))

                if self._state is None or self._state == 'random':
                    svc = StateVectorCircuit(self._state_vector)
                    svc.construct_circuit(circuit=circuit, register=register)
                elif self._state == 'uniform':
                    for i in range(self._num_qubits):
                        circuit.u(np.pi / 2, 0.0, np.pi, register[i])
                elif self._state == 'zero':
                    pass
                else:
                    AquaError('Unexpected state mode {}.'.format(self._state))
                self._circuit = circuit
            return self._circuit.copy()
        else:
            raise AquaError('Mode should be either "vector" or "circuit"')
Ejemplo n.º 7
0
    def test_mct(self, num_controls):
        c = QuantumRegister(num_controls, name='c')
        o = QuantumRegister(1, name='o')
        allsubsets = list(
            chain(*[
                combinations(range(num_controls), ni)
                for ni in range(num_controls + 1)
            ]))
        for subset in allsubsets:
            for mode in ['basic', 'advanced', 'noancilla']:
                qc = QuantumCircuit(o, c)
                if mode == 'basic':
                    if num_controls <= 2:
                        num_ancillae = 0
                    else:
                        num_ancillae = num_controls - 2
                elif mode == 'noancilla':
                    num_ancillae = 0
                else:
                    if num_controls <= 4:
                        num_ancillae = 0
                    else:
                        num_ancillae = 1
                if num_ancillae > 0:
                    a = QuantumRegister(num_ancillae, name='a')
                    qc.add_register(a)
                for idx in subset:
                    qc.x(c[idx])
                qc.mct([c[i] for i in range(num_controls)],
                       o[0], [a[i] for i in range(num_ancillae)],
                       mode=mode)
                for idx in subset:
                    qc.x(c[idx])

                vec = np.asarray(
                    q_execute(qc, get_aer_backend(
                        'statevector_simulator')).result().get_statevector(
                            qc, decimals=16))
                vec_o = [0, 1] if len(subset) == num_controls else [1, 0]
                # print(vec, np.array(vec_o + [0] * (2 ** (num_controls + num_ancillae + 1) - 2)))
                f = state_fidelity(
                    vec,
                    np.array(vec_o + [0] *
                             (2**(num_controls + num_ancillae + 1) - 2)))
                self.assertAlmostEqual(f, 1)
            return
Ejemplo n.º 8
0
    def construct_circuit(self, mode, register=None):
        """
        Construct the statevector of desired initial state.

        Args:
            mode (string): `vector` or `circuit`. The `vector` mode produces the vector.
                            While the `circuit` constructs the quantum circuit corresponding that
                            vector.
            register (QuantumRegister): register for circuit construction.

        Returns:
            QuantumCircuit or numpy.ndarray: statevector.

        Raises:
            ValueError: when mode is not 'vector' or 'circuit'.
        """
        if mode == 'vector':
            if self._state_vector is None:
                if self._circuit is not None:
                    self._state_vector = np.asarray(
                        q_execute(self._circuit,
                                  get_aer_backend('statevector_simulator')).
                        result().get_statevector(self._circuit))
            return self._state_vector
        elif mode == 'circuit':
            if self._circuit is None:
                if register is None:
                    register = QuantumRegister(self._num_qubits, name='q')
                circuit = QuantumCircuit(register)
                if self._state is None or self._state == 'random':
                    circuit.initialize(
                        self._state_vector,
                        [register[i] for i in range(self._num_qubits)])
                    circuit = Custom._convert_to_basis_gates(circuit)
                elif self._state == 'zero':
                    pass
                elif self._state == 'uniform':
                    for i in range(self._num_qubits):
                        circuit.u2(0.0, np.pi, register[i])
                else:
                    pass
                self._circuit = circuit
            return self._circuit
        else:
            raise ValueError('Mode should be either "vector" or "circuit"')
Ejemplo n.º 9
0
 def test_sat_oracle(self, cnf_str, sols):
     num_shots = 1024
     for cnx_mode in ['basic', 'advanced']:
         sat = SAT(cnf_str, cnx_mode=cnx_mode)
         sat_circuit = sat.construct_circuit()
         m = ClassicalRegister(1, name='m')
         for assignment in itertools.product([True, False], repeat=len(sat.variable_register())):
             qc = QuantumCircuit(m, sat.variable_register())
             for idx, tf in enumerate(assignment):
                 if tf:
                     qc.x(sat.variable_register()[idx])
             qc += sat_circuit
             qc.barrier(sat._qr_outcome)
             qc.measure(sat._qr_outcome, m)
             counts = q_execute(qc, get_aer_backend(
                 'qasm_simulator'), shots=num_shots).result().get_counts(qc)
             if assignment in sols:
                 assert(counts['1'] == num_shots)
             else:
                 assert(counts['0'] == num_shots)
Ejemplo n.º 10
0
 def test_sat_oracle(self, cnf_str, sols):
     num_shots = 1024
     sat = get_oracle_instance('SAT')
     sat.init_args(cnf_str)
     sat_circuit = sat.construct_circuit()
     m = ClassicalRegister(1, name='m')
     for assignment in itertools.product([True, False],
                                         repeat=len(
                                             sat.variable_register())):
         qc = QuantumCircuit(m, sat.variable_register())
         for idx, tf in enumerate(assignment):
             if tf:
                 qc.x(sat.variable_register()[idx])
         qc += sat_circuit
         qc.measure(sat._qr_outcome, m)
         counts = q_execute(qc, 'local_qasm_simulator',
                            shots=num_shots).result().get_counts(qc)
         if assignment in sols:
             assert (counts['1'] == num_shots)
         else:
             assert (counts['0'] == num_shots)
Ejemplo n.º 11
0
    def test_mct(self, num_controls, mode):
        c = QuantumRegister(num_controls, name='c')
        o = QuantumRegister(1, name='o')
        subsets = [tuple(range(i)) for i in range(num_controls + 1)]
        for subset in subsets:
            qc = QuantumCircuit(o, c)
            if mode == 'basic':
                if num_controls <= 2:
                    num_ancillae = 0
                else:
                    num_ancillae = num_controls - 2
            elif mode == 'noancilla':
                num_ancillae = 0
            else:
                if num_controls <= 4:
                    num_ancillae = 0
                else:
                    num_ancillae = 1
            if num_ancillae > 0:
                a = QuantumRegister(num_ancillae, name='a')
                qc.add_register(a)
            for idx in subset:
                qc.x(c[idx])
            qc.mct(
                [c[i] for i in range(num_controls)],
                o[0],
                [a[i] for i in range(num_ancillae)],
                mode=mode
            )
            for idx in subset:
                qc.x(c[idx])

            vec = np.asarray(q_execute(qc, BasicAer.get_backend(
                'statevector_simulator')).result().get_statevector(qc, decimals=16))
            vec_o = [0, 1] if len(subset) == num_controls else [1, 0]
            f = state_fidelity(vec, np.array(vec_o + [0] * (2 ** (num_controls + num_ancillae + 1) - 2)))
            self.assertAlmostEqual(f, 1)
Ejemplo n.º 12
0
    def test_mcmt(self, num_controls, num_targets,
                  single_control_gate_function):

        c = QuantumRegister(num_controls, name='c')
        o = QuantumRegister(num_targets, name='o')

        subsets = [tuple(range(i)) for i in range(num_controls + 1)]
        for subset in subsets:
            # Expecting some other modes
            for mode in ['basic']:
                self.log.debug("Subset is {0}".format(subset))
                self.log.debug("Num controls = {0}".format(num_controls))
                self.log.debug("Num targets = {0}".format(num_targets))
                self.log.debug("Gate function is {0}".format(
                    single_control_gate_function.__name__))
                self.log.debug("Mode is {0}".format(mode))
                qc = QuantumCircuit(o, c)
                # Initialize all targets to 1, just to be sure that
                # the generic gate has some effect (f.e. Z gate has no effect
                # on a 0 state)
                qc.x(o)

                if mode == 'basic':
                    if num_controls <= 1:
                        num_ancillae = 0
                    else:
                        num_ancillae = num_controls - 1
                    self.log.debug("Num ancillae is {0} ".format(num_ancillae))

                if num_ancillae > 0:
                    a = QuantumRegister(num_ancillae, name='a')
                    qc.add_register(a)

                for idx in subset:
                    qc.x(c[idx])
                qc.mcmt([c[i] for i in range(num_controls)],
                        [a[i] for i in range(num_ancillae)],
                        single_control_gate_function,
                        o,
                        mode=mode)
                for idx in subset:
                    qc.x(c[idx])

                vec = np.asarray(
                    q_execute(qc, get_aer_backend('statevector_simulator')).
                    result().get_statevector(qc, decimals=16))
                # target register is initially |11...1>, with length equal to 2**(n_targets)
                vec_exp = np.array([0] * (2**(num_targets) - 1) + [1])
                if (single_control_gate_function.__name__ == "cz"):
                    # Z gate flips the last qubit only if it's applied an odd
                    # number of times
                    if (len(subset) == num_controls
                            and (num_controls % 2) == 1):
                        vec_exp[-1] = -1
                elif (single_control_gate_function.__name__ == "ch"):
                    # if all the control qubits have been activated,
                    # we repeatedly apply the kronecker product of the Hadamard
                    # with itself and then multiply the results for the original
                    # state of the target qubits
                    if (len(subset) == num_controls):
                        h = 1 / np.sqrt(2) * np.array([[1, 1], [1, -1]])
                        h_tot = np.array([1])
                        for i in range(num_targets):
                            h_tot = np.kron(h_tot, h)
                        vec_exp = np.dot(h_tot, vec_exp)
                else:
                    raise ValueError("Gate {0} not implementend yet".format(
                        single_control_gate_function.__name__))
                # append the remaining part of the state
                vec_exp = np.concatenate(
                    (vec_exp,
                     [0] * (2**(num_controls + num_ancillae + num_targets) -
                            vec_exp.size)))
                f = state_fidelity(vec, vec_exp)
                self.assertAlmostEqual(f, 1)
Ejemplo n.º 13
0
    def test_evolution(self):
        SIZE = 2
        # SPARSITY = 0
        # X = [[0, 1], [1, 0]]
        # Y = [[0, -1j], [1j, 0]]
        Z = [[1, 0], [0, -1]]
        _I = [[1, 0], [0, 1]]
        # + 0.5 * np.kron(Y, X)# + 0.3 * np.kron(Z, X) + 0.4 * np.kron(Z, Y)
        h1 = np.kron(_I, Z)

        # np.random.seed(2)
        temp = np.random.random((2**SIZE, 2**SIZE))
        h1 = temp + temp.T
        qubit_op = Operator(matrix=h1)
        # qubit_op_jw.chop_by_threshold(10 ** -10)

        if qubit_op.grouped_paulis is None:
            qubit_op._matrix_to_paulis()
            qubit_op._paulis_to_grouped_paulis()

        for ps in qubit_op.grouped_paulis:
            for p1 in ps:
                for p2 in ps:
                    if p1 != p2:
                        np.testing.assert_almost_equal(
                            p1[1].to_matrix() @ p2[1].to_matrix(),
                            p2[1].to_matrix() @ p1[1].to_matrix())

        state_in = Custom(SIZE, state='random')

        evo_time = 1
        num_time_slices = 3

        # announces params
        self.log.debug('evo time:        {}'.format(evo_time))
        self.log.debug('num time slices: {}'.format(num_time_slices))
        self.log.debug('state_in:        {}'.format(state_in._state_vector))

        # get the exact state_out from raw matrix multiplication
        state_out_exact = qubit_op.evolve(
            state_in=state_in.construct_circuit('vector'),
            evo_time=evo_time,
            evo_mode='matrix',
            num_time_slices=0)
        # self.log.debug('exact:\n{}'.format(state_out_exact))
        qubit_op_temp = copy.deepcopy(qubit_op)
        for expansion_mode in ['trotter', 'suzuki']:
            self.log.debug('Under {} expansion mode:'.format(expansion_mode))
            for expansion_order in [1, 2, 3, 4
                                    ] if expansion_mode == 'suzuki' else [1]:
                # assure every time the operator from the original one
                qubit_op = copy.deepcopy(qubit_op_temp)
                if expansion_mode == 'suzuki':
                    self.log.debug(
                        'With expansion order {}:'.format(expansion_order))
                state_out_matrix = qubit_op.evolve(
                    state_in=state_in.construct_circuit('vector'),
                    evo_time=evo_time,
                    evo_mode='matrix',
                    num_time_slices=num_time_slices,
                    expansion_mode=expansion_mode,
                    expansion_order=expansion_order)

                quantum_registers = QuantumRegister(qubit_op.num_qubits,
                                                    name='q')
                qc = QuantumCircuit(quantum_registers)
                qc += state_in.construct_circuit('circuit', quantum_registers)
                qc += qubit_op.evolve(
                    evo_time=evo_time,
                    evo_mode='circuit',
                    num_time_slices=num_time_slices,
                    quantum_registers=quantum_registers,
                    expansion_mode=expansion_mode,
                    expansion_order=expansion_order,
                )
                job = q_execute(qc,
                                BasicAer.get_backend('statevector_simulator'))
                state_out_circuit = np.asarray(job.result().get_statevector(
                    qc, decimals=16))

                self.log.debug(
                    'The fidelity between exact and matrix:   {}'.format(
                        state_fidelity(state_out_exact, state_out_matrix)))
                self.log.debug(
                    'The fidelity between exact and circuit:  {}'.format(
                        state_fidelity(state_out_exact, state_out_circuit)))
                f_mc = state_fidelity(state_out_matrix, state_out_circuit)
                self.log.debug(
                    'The fidelity between matrix and circuit: {}'.format(f_mc))
                self.assertAlmostEqual(f_mc, 1)
Ejemplo n.º 14
0
    def test_evolution(self):
        SIZE = 2
        #SPARSITY = 0
        #X = [[0, 1], [1, 0]]
        #Y = [[0, -1j], [1j, 0]]
        Z = [[1, 0], [0, -1]]
        I = [[1, 0], [0, 1]]
        # + 0.5 * np.kron(Y, X)# + 0.3 * np.kron(Z, X) + 0.4 * np.kron(Z, Y)
        h1 = np.kron(I, Z)

        # np.random.seed(2)
        temp = np.random.random((2 ** SIZE, 2 ** SIZE))
        h1 = temp + temp.T
        qubitOp = Operator(matrix=h1)
        # qubitOp_jw.chop_by_threshold(10 ** -10)

        # self.log.debug('matrix:\n{}\n'.format(qubitOp.matrix))
        # self.log.debug('paulis:')
        # self.log.debug(qubitOp.print_operators('paulis'))

        if qubitOp.grouped_paulis is None:
            qubitOp._matrix_to_paulis()
            qubitOp._paulis_to_grouped_paulis()

        for ps in qubitOp.grouped_paulis:
            for p1 in ps:
                for p2 in ps:
                    if p1 != p2:
                        np.testing.assert_almost_equal(
                            p1[1].to_matrix() @ p2[1].to_matrix(),
                            p2[1].to_matrix() @ p1[1].to_matrix()
                        )

        flattened_grouped_paulis = [
            pauli for group in qubitOp.grouped_paulis for pauli in group[1:]]

        state_in = get_initial_state_instance('CUSTOM')
        state_in.init_args(SIZE, state='random')

        evo_time = 1
        num_time_slices = 1

        # announces params
        self.log.debug('evo time:        {}'.format(evo_time))
        self.log.debug('num time slices: {}'.format(num_time_slices))
        self.log.debug('state_in:        {}'.format(state_in._state_vector))

        # get the exact state_out from raw matrix multiplication
        state_out_exact = qubitOp.evolve(
            state_in.construct_circuit('vector'), evo_time, 'matrix', 0)
        # self.log.debug('exact:\n{}'.format(state_out_exact))
        qubitOp_temp = copy.deepcopy(qubitOp)
        for grouping in ['default', 'random']:
            self.log.debug('Under {} paulis grouping:'.format(grouping))
            for expansion_mode in ['trotter', 'suzuki']:
                self.log.debug(
                    'Under {} expansion mode:'.format(expansion_mode))
                for expansion_order in [1, 2, 3, 4] if expansion_mode == 'suzuki' else [1]:
                    # assure every time the operator from the original one
                    qubitOp = copy.deepcopy(qubitOp_temp)
                    if expansion_mode == 'suzuki':
                        self.log.debug(
                            'With expansion order {}:'.format(expansion_order))
                    state_out_matrix = qubitOp.evolve(
                        state_in.construct_circuit(
                            'vector'), evo_time, 'matrix', num_time_slices,
                        paulis_grouping=grouping,
                        expansion_mode=expansion_mode,
                        expansion_order=expansion_order
                    )

                    quantum_registers = QuantumRegister(qubitOp.num_qubits)
                    qc = state_in.construct_circuit(
                        'circuit', quantum_registers)
                    qc += qubitOp.evolve(
                        None, evo_time, 'circuit', num_time_slices,
                        quantum_registers=quantum_registers,
                        paulis_grouping=grouping,
                        expansion_mode=expansion_mode,
                        expansion_order=expansion_order,
                    )
                    job = q_execute(qc, qiskit.Aer.get_backend(
                        'statevector_simulator'), skip_transpiler=True)
                    state_out_circuit = np.asarray(
                        job.result().get_statevector(qc))

                    self.log.debug('The fidelity between exact and matrix:   {}'.format(
                        state_fidelity(state_out_exact, state_out_matrix)
                    ))
                    self.log.debug('The fidelity between exact and circuit:  {}'.format(
                        state_fidelity(state_out_exact, state_out_circuit)
                    ))
                    f_mc = state_fidelity(state_out_matrix, state_out_circuit)
                    self.log.debug(
                        'The fidelity between matrix and circuit: {}'.format(f_mc))
                    self.assertAlmostEqual(f_mc, 1)
Ejemplo n.º 15
0
def run_exp(num_reps=1):

    # choice of Hi basis
    H_basis = [Pauli.from_label(p) for p in ['II', 'ZI', 'IZ', 'ZZ', 'YY', 'XX']]

    num_qubits = 2
    evo_time = 1
    epsilon = 0.1
    L = 32    ## number of local hamiltonian terms

    ############################################################
    # Generate a random Hamiltonian H as the sum of m basis Hi operators
    ############################################################

    hs = np.random.random(L)
    indexes = np.random.randint(low=0, high=6, size=L)

    ## H in matrix form
    H_matrix = np.zeros((2 ** num_qubits, 2 ** num_qubits))

    ## H as a list of pauli operators (unweighted)
    H_list = []
    for i in range(L):
        H_matrix = H_matrix + hs[i] * H_basis[indexes[i]].to_matrix()
        H_list.append(H_basis[indexes[i]])
    print('matrix H: \n', H_matrix)

    # H as a pauli operator
    H_qubitOp = op_converter.to_weighted_pauli_operator(MatrixOperator(matrix=H_matrix))

    # Generate an initial state
    state_in = Custom(num_qubits, state='random')

    ############################################################
    # Ground truth and benchmarks
    ############################################################

    # Ground truth
    state_in_vec = state_in.construct_circuit('vector')
    groundtruth = expm(-1.j * H_matrix * evo_time) @ state_in_vec
    print('The directly computed groundtruth evolution result state is')
    print('{}\n.'.format(groundtruth))

    # Build circuit using Qiskit's evolve algorithm, which based on Trotter-Suzuki.
    quantum_registers = QuantumRegister(num_qubits)
    circuit = state_in.construct_circuit('circuit', quantum_registers)
    circuit += H_qubitOp.evolve(
        None, evo_time, num_time_slices=10,
        quantum_registers=quantum_registers,
        expansion_mode='suzuki',
        expansion_order=1
    )

    # Simulate Trotter-Suzuki circuit and print it
    backend = BasicAer.get_backend('statevector_simulator')
    job = q_execute(circuit, backend)
    circuit_execution_result = np.asarray(job.result().get_statevector(circuit))
    print('The simulated (suzuki) evolution result state is')
    print('{}\n'.format(circuit_execution_result))

    # The difference between the ground truth and the simulated state
    # measured by "Fidelity"
    fidelity_suzuki = state_fidelity(groundtruth, circuit_execution_result)
    print('Fidelity between the groundtruth and the circuit result states is {}.'.format(fidelity_suzuki))
    print('\n')

    ############################################################
    # Our qdrift implementation
    ############################################################

    quantum_registers = QuantumRegister(num_qubits)
    circuit = state_in.construct_circuit('circuit', quantum_registers)

    # Contruct the circuit which implements qdrift
    circuit = time_evolve_qubits(quantum_registers, circuit, num_qubits, H_list, hs, evo_time, epsilon, num_reps)

    # Simulate circuit and print it
    backend = BasicAer.get_backend('statevector_simulator')
    job = q_execute(circuit, backend)
    circuit_execution_result = np.asarray(job.result().get_statevector(circuit))
    print('The simulated (qdrift) evolution result state is\n{}.'.format(circuit_execution_result))
    print('\n')

    # Measure the fidelity
    fidelity_qdrift = state_fidelity(groundtruth, circuit_execution_result)
    print('Fidelity between the groundtruth and the circuit result states is {}.'.format(fidelity_qdrift))
    print('\n')

    print('benchmark, suzuki:', fidelity_suzuki)
    print('qdrift:', fidelity_qdrift)
    return fidelity_qdrift, fidelity_suzuki