Esempio n. 1
0
    def _build_internal_circuit(self) -> qiskit.QuantumCircuit:
        control_reg = create_register(self.num_control_qubits, name='control')
        state_reg = create_register(self._oracle.num_state_qubits,
                                    name='state')
        output_reg = self._oracle.get_register('output', [])
        ancilla_reg = create_ancillas_for(self._oracle, self._a_op,
                                          self._rs_op)
        circuit = create_circuit(control_reg,
                                 state_reg,
                                 output_reg,
                                 ancilla_reg,
                                 name=self.name)

        self._oracle(circuit,
                     control=control_reg,
                     state=state_reg,
                     output=output_reg,
                     ancilla=ancilla_reg)
        self._a_op.apply_inverse(circuit, state_reg, ancilla=ancilla_reg)
        self._rs_op(circuit,
                    control=control_reg,
                    state=state_reg,
                    ancilla=ancilla_reg)
        self._a_op(circuit, state_reg, ancilla=ancilla_reg)

        return circuit
    def _build_internal_circuit(self) -> qiskit.QuantumCircuit:
        state_reg = create_register(self._q_op.num_target_qubits, name='state')
        output_reg = create_register(self.num_output_qubits, name='output')
        ancilla_reg = create_register(
            max(self._a_op.num_ancillas, self._q_op.num_ancillas),
            name='ancilla', reg_type='ancilla'
        )
        circuit = create_circuit(state_reg, output_reg, ancilla_reg, name=self.name)

        # reverse qubits
        output_reg = output_reg[::-1]

        # apply A operator
        self._a_op(circuit, state_reg, ancilla_reg)

        # apply Hadamard on output register
        circuit.h(output_reg)

        # apply controlled-Q operator
        for k, q in enumerate(output_reg):
            for _ in range(2**k):
                self._q_op(circuit, q, state_reg, ancilla_reg)

        # reverse qubits
        output_reg = output_reg[::-1]

        # apply inverse QFT
        qft(circuit, output_reg, do_swaps=False, inverse=True)

        return circuit
Esempio n. 3
0
    def _build_internal_circuit(self) -> qiskit.QuantumCircuit:
        control_reg = create_register(self.num_control_qubits, name='control')
        state_reg = create_register(self.num_state_qubits, name='state')
        circuit = create_circuit(control_reg, state_reg, name=self.name)

        ref_state = [1] * self.num_state_qubits

        target_states = self.target_states
        if self.reverse:
            target_states = [
                state for state in get_basis_states(self.num_state_qubits,
                                                    out_type='list')
                if state not in target_states
            ]

        for state in target_states:
            for bit, rbit, q in zip(state, ref_state, state_reg):
                if bool(bit) is not bool(rbit):
                    circuit.x(q)
            circuit.mcp(self.phase, control_reg[:] + state_reg[:-1],
                        state_reg[-1])
            ref_state = state

        for bit, q in zip(ref_state, state_reg):
            if not bit:
                circuit.x(q)

        return circuit
Esempio n. 4
0
    def _build_internal_circuit(self) -> qiskit.QuantumCircuit:
        state_reg = create_register(self.oracle.get_register('state').size, name='state')
        output_reg = create_register(1, name='output')
        ancilla_reg = create_ancillas_for(self.state_loading_op, self.oracle)
        circuit = create_circuit(state_reg, ancilla_reg, name=self.name)
        self.state_loading_op(circuit, state=state_reg, ancilla=ancilla_reg)
        self.oracle(circuit, state=state_reg, output=output_reg, ancilla=ancilla_reg)

        return circuit
Esempio n. 5
0
    def _build_internal_circuit(self) -> qiskit.QuantumCircuit:
        state_reg = create_register(self._q_op.get_register('state').size, name='state')
        output_reg = create_register(1, name='output')
        ancilla_reg = create_ancillas_for(self._a_op, self._q_op, name='ancilla')
        circuit = create_circuit(state_reg, output_reg, ancilla_reg, name=self.name)

        # apply A operator
        self._a_op(circuit, state=state_reg, output=output_reg, ancilla=ancilla_reg)

        # apply Q operator
        for _ in range(self.num_q_applications):
            self._q_op(circuit, state=state_reg, output=output_reg, ancilla=ancilla_reg)

        return circuit
Esempio n. 6
0
    def _build_internal_circuit(self) -> qiskit.QuantumCircuit:
        state_reg = create_register(self.rs_op.get_register('state').size, name='state')
        output_reg = create_register(1, name='output')
        ancilla_reg = create_ancillas_for(self.a_op, self.rs_op)
        circuit = create_circuit(state_reg, output_reg, ancilla_reg, name=self.name)

        # Add pi phase to states with output qubit = |0>
        circuit.x(output_reg)
        circuit.p(np.pi, output_reg)
        circuit.x(output_reg)

        # A^dag
        self.a_op.apply_inverse(circuit)
        # Reflection on source state
        self.rs_op(circuit)
        # A
        self.a_op(circuit)

        return circuit
Esempio n. 7
0
 def to_phase_oracle(self, num_controls: int = 0) -> PhaseOracle:
     control_reg = create_register(num_controls, 'control')
     state_reg = create_register(self.num_state_qubits, 'state')
     output_reg = create_register(1, 'ancilla', reg_type='ancilla')
     circuit = create_circuit(control_reg,
                              state_reg,
                              output_reg,
                              name='Controlled' + self.name)
     if num_controls > 0:
         circuit.mcx(control_reg, output_reg)
     else:
         circuit.x(output_reg)
     circuit.h(output_reg)
     circuit = self.apply(circuit, state_reg, output_reg)
     circuit.h(output_reg)
     if num_controls > 0:
         circuit.mcx(control_reg, output_reg)
     else:
         circuit.x(output_reg)
     ret = PhaseOracle(self.target_states,
                       num_control_qubits=num_controls,
                       reverse=self.reverse)
     ret._set_internal_circuit(circuit)
     return ret
def create_ancillas_for(*operators: QuantumOperator,
                        name: typing.Optional[str] = 'ancilla'):
    num_ancillas = max(op.num_ancillas for op in operators)
    return create_register(num_ancillas, name=name, reg_type='ancilla')
Esempio n. 9
0
def grover_circuit(
    target: typing.Union[typing.Sequence[BinarySequenceType],
                         BinarySequenceType],
    source: BinarySequenceType = None,
    niter: typing.Union[int, None] = None,
    oracle_type: str = 'phase',
    measure: bool = True,
) -> qiskit.QuantumCircuit:

    assert len(target) > 0
    # Input is a single target
    if not isinstance(target[0], typing.Sequence):
        target = [target]

    # number of qubits
    num_qubits = len(target[0])
    # number of targets
    num_targets = len(target)

    # initial (source) state to start with
    if source is None:
        source = [0] * num_qubits

    # get optimal number of iterations
    if niter is None:
        niter = optimal_iterations(num_qubits, num_targets=num_targets)

    # quantum circuit
    qreg = qiskit.QuantumRegister(num_qubits, name='q')
    qc = qiskit.QuantumCircuit(qreg, name='grover')

    # initialize
    # construct source
    source_sv = state_to_sv(source)
    init_source_op = InitializeSourceOperator(state_vector=source_sv)
    init_source_op(qc, qreg)
    # construct equal superposition
    a_op = DiffusionOperator(num_qubits=num_qubits,
                             source_state_vector=source_sv)
    a_op(qc, qreg)

    # Grover iterations
    rs_op = PhaseOracle(target_state=source)
    if oracle_type == 'phase':
        oracle = PhaseOracle(target_state=target)
    elif oracle_type == 'bool':
        oracle = BooleanOracle(target_state=target).to_phase_oracle()
    else:
        raise ValueError("Unknown oracle type %s", oracle_type)
    grover_op = GroverIterate(a_op=a_op, rs_op=rs_op, oracle=oracle)
    ancilla = create_register(grover_op.num_ancillas, name='ancilla')
    add_registers_to_circuit(qc, ancilla)
    for _ in range(niter):
        grover_op(qc, qreg, ancilla=ancilla)

    # measurement
    if measure:
        creg = qiskit.ClassicalRegister(
            grover_op.get_register('state').size, 'output')
        qc.add_register(creg)
        qc.measure(grover_op.get_register('state'), creg)

    return qc